Not a bug — a missing feature. Battle KO sprites were perfect, but the main menu still drew KO'd heroes with the vanilla generic wounded sprite.
Rather than trace menu code (largely undisassembled), we searched the ROM for the data. The vanilla KO art lives at D4:9400, so any loader must hold a pointer containing the bytes 00 94 D4. The whole-ROM search found exactly two copies:
C1:24A3 — the battle matrix (already hooked in v0.05)C0:EC97 — a second table, 4-byte stride, five entries D4:9400 + charID × $C0A second search for code referencing EC97 found exactly one consumer:
C2:D2C3
Two tables, two consumers, both now known — the search proves there is no third path that could sneak vanilla sprites in. That completeness guarantee is the real payoff of data-driven search.
The menu loader, decoded
C2:D298 runs once per slot (loop at C2:D240):
C2/D2A9 LDA $000500,X → $EA ; 16-bit read of FieldChar bytes 0-1:
; $EA = charID (bits 0-2) + row (bit 7)
; $EB = job byte
C2/D2AF JSR $D2DB ; walk ptr = base[charID] + (job&$1F)×$600
C2/D2B2 ... JSR $D304 ; copy 24 tiles (walk poses)
C2/D2BB LDA $EA / AND #$0007 ; charID again...
C2/D2C3 LDA $C0EC97,X → $E0/$E2 ; ★ KO pointer from the table
C2/D2CF ... JSR $D304 ; copy 6 tiles (KO pose)
Note what this proves in passing: the game itself masks FieldChar byte 0 with #$07 to get the charID — so $0500 bit-packs charID (bits 0–2) and row (bit 7). Disassembly labels (this byte is named CharRow in one disassembly) describe one use of a byte, not necessarily all of it.
A neat trick used here: instruction widths prove processor state. The vanilla AND #$0007 assembles as 3 bytes — that only happens when the accumulator is 16-bit (M=0). We never had to run the code to know the register width at our hook; the opcode stream itself is the evidence.
Replace the 20 bytes at C2:D2BB (mask + table lookup) with
JSL $E852D0 + 16 NOPs.
The freespace routine (46 bytes) recomputes:
$E0 = ((job & $1F)×5 + (charID & $07)) × $C0
$E2 = $00E8
using the same masks the vanilla code uses, from the same scratch bytes ($EA/$EB) the game just refreshed — which means changing jobs inside the menu updates the KO sprite for free, through the vanilla refresh path.