The original tracer followed only vectors and direct jsr/jmp/branch targets and
knew just the 151 documented 6502 opcodes. Wild Gunman dispatches at runtime, so
~4.9 KB of real code was filed as .byte data.
Root cause: Label_C341 ($C341) is a computed goto that pulls the CALLER's return
address with two 'pla' instructions, so its jump table physically follows each
'jsr $C341' (opcode 20 41 C3) and is indexed by A*2. Seven call sites exist; the
table at $C114 (after 'lda $33 / jsr $C341') decodes to 14 valid targets.
Changes:
- Tracer rebuilt with all 54 undocumented opcodes + 26 unofficial NOPs (these
ROMs use them as 2/3-byte padding; a tracer that halts on them strands code)
- Iterative expansion seeded from inline $C341 tables, in-trace control-flow
references, and explicit pointer tables (e.g. the 5-entry table at $DEDD)
- prg.s updated SURGICALLY: all 249 existing routine headers, semantic labels
and locals.inc aliases preserved; only data->code promotion applied
- Fixed a byte-dropping parser bug: some .byte lines use symbolic values
(Zp01, NmiPhase, Ctrl1), which a $XX-only regex silently skipped
- Branch targets landing mid-instruction now force a split so labels land on
real instruction boundaries
- Bytes that cannot be assembled stay .byte: ca65's 6502 has no
SLO/RLA/SRE/RRA/ISC/DCP/LAS/TAS/ANE/AXS/LXA mnemonics
Verified: 1,597 -> 3,956 instructions, 3,352 -> 8,085 code bytes (49.3%).
Every one of the 16,384 PRG bytes emitted exactly once, every value equal to the
ROM, zero audit-comment mismatches. Byte-identical ROM verified.