Replaced all 497 Label_XXXX labels with semantic names:
- 37 jmp-target labels renamed with routine-specific names
- 6 branch-target labels renamed with _Loop/_Next/_Block roles
- 454 internal branch targets renamed as <Routine>_Block/_Block_N
based on parent routine and block position
All 84 jsr targets already had semantic names.
Build verified byte-identical. verify_pass1.py passes with 'canoni'
comment format.
Updated TODO.md: removed Balloon Fight from Label_ residue table.
Balloon Fight's Pass 1 was already complete and hand-done to a higher standard
than a static tracer: 5,303 instructions / 11,260 code bytes, versus 5,277 /
11,202 from the complete-opcode tracer. The 166 bytes the tracer finds 'missing'
are genuinely data (command scripts at $D437/$D45A referenced by
'lda $D45A,y', the $C3B5 pointer table, the arithmetic table at $FBCA), so no
code was added.
The real remaining Pass 1 gap was the repo rule that no ROM byte stays hidden
in an .incbin. Two spans converted:
- $F4C5-$F4FF (59 bytes) -> TrailingFillBeforeApuTables: $FF padding after
the sound-init RTS at $F4C4, unreached
- $F5FC-$F5FF (4 bytes) -> SoundEngineTailBytes: unreachable filler between
the sound engine's final JMP ($F5F9) and ApuPeriodTable ($F600)
Verified: symbol layout restored (ApuPeriodTable $F600, UpdateAudioFrame $FFF7),
both new blocks byte-exact against the ROM, no .incbin remains.
Byte-identical ROM verified.