REDIVIVUS

Proposals / #1701

D2ClientSoundChannelStrc: the last-applied position and obstruction (+0x0c..+0x14, +0x1c) are floats, +0x18 an int

checked · by Nishimura-Katsuo · submitted 2026-11-08

SOUND_UpdateChannelParams (0x004dfc20) caches what it last applied and returns early when nothing changed. The cache holds the sound's own floats: MOV bit copies of D2SoundChannelStrc fPosX..fPosZ into +0x0c..+0x14 (004dffd9..004dffe8), FLD/FSTP of fUnitDistance into +0x1c (004dfff1), FUCOMPP of +0x1c against fUnitDistance (004dfe15); SOUND_PlaySoundWithPanning clears +0x1c with FLDZ/FSTP (004e0303). +0x18 is the integer volume (CMP EDI,[EBX+0x18] at 004dfe06; -1 at 004e0306). The Mac twin agrees (UCOMISS/MOVSS on +0x1c). Typed undefined4, the source prints uint32_t: the rebuild truncates positions to integers on store (UB for negatives) and converts back on compare, so the early return never fires and every channel re-sends pan/3D/EAX/volume each update. +0x18 is cosmetic. The dw prefixes now mislead (fLastPosX.. fits the rules); only default names may be proposed, so renames are left to review.

Changes 5, applied together

  1. Struct field win /D2Client/D2ClientSoundChannelStrc + 0xc

    typeundefined4→float
  2. Struct field win /D2Client/D2ClientSoundChannelStrc + 0x10

    typeundefined4→float
  3. Struct field win /D2Client/D2ClientSoundChannelStrc + 0x14

    typeundefined4→float
  4. Struct field win /D2Client/D2ClientSoundChannelStrc + 0x18

    typeundefined4→int32_t
  5. Struct field win /D2Client/D2ClientSoundChannelStrc + 0x1c

    typeundefined4→float