Symptom

v0.04 loaded job-specific sprites, and with one particular party it looked almost right — 3 of 4 heroes correct. Reordering the party scrambled which hero got which sprite. Sprites tracked party position, not hero identity.

Evidence

The numeral test showed each slot receiving a block number matching its seat, not its character. A "works for one formation, breaks on shuffle" bug is a classic signature of confusing two index spaces — here, slot (seat 0–3 in the party lineup) versus charID (Bartz=0, Lenna=1, Galuf=2, Faris=3, Krile=4).

Root cause

The v0.04 hook lives at C1:2517, inside the battle sprite loader. v0.04 assumed the X register there encoded the party slot (slot = ((X−8)>>3)&3) and then read hero identity from RAM. Reading the surrounding code in the Bank C1 disassembly showed both assumptions were wrong:

C1/24EB  Y = 0                     ; loop over party slots
C1/24EE  LDA $CFC6,Y               ; A = CHARACTER ID for slot Y ($FF = empty)
C1/2505  ASL ×3 / TAX              ; X = charID × 8  ← row into pointer matrix
C1/250B  LDA $C124A3,X → $70       ; walk-sprite base for this HERO
C1/2517  LDA $C124A7,X → $76       ; ★ KO-sprite pointer  ← our hook site
C1/2526  LDA $CFCA,Y               ; job (0-21); × $600 selects the job's art
C1/259A  PLY / INY / CPY #4 / loop

WW_v0.05_checkpoint.ips