Pass 1 verification for Balloon Fight / DK Jr, and fix DK 3 branch-target bug

Balloon Fight (JU) - verified complete (in 7d7d78d).
Donkey Kong Jr. (JU) - no source changes needed. Full byte-accounting audit of
prg.s: all 16,384 PRG bytes emitted exactly once (6,199 instructions + 3,889
.byte + 16 .word), every emitted value equals the ROM byte, zero audit-comment
mismatches, zero duplicate addresses, no .incbin remains. The complete-opcode
tracer reaches 6,135 instructions / 12,358 code bytes, all of which are already
in the file; the file carries 121 further code bytes the tracer does not find,
reached through the DeferredTaskHandlerTable dispatch at $BFFE.

Donkey Kong 3 (JUE) - real bug fix. The project was recorded as BYTE-IDENTICAL
but had never built byte-identical: its committed reconstructed.nes also
differed from rom.nes. The bne at CPU $C14C (PRG $014C) is annotated 'D0 12'
(target $C160) but assembled as 'D0 0D', because it referenced
StoreSelectedPlayerAndScreenFlags ($C15B) instead of the routine actually at
$C160. Retargeted to ClearAudioSetGameMode, which is also the semantically
correct destination for a 'mode != $01' test. cmp now passes.

Root OVERVIEW.md: added a Pass 1 methodology section recording both Pass 1
limitations (documented-opcodes-only, and no runtime dispatch) with the measured
per-project impact, and flagged Joypad Test Cartridge as the one project still
carrying the truncated Pass 1.

All 15 top-level projects verified byte-identical.
This commit is contained in:
tmerritt committed 2026-10-16 20:42:21 -04:00
1 parent 7d7d78dcda
commit e9caa8cb36
4 files changed
+39 -10

No files matched your search

+1 -1
View File
@@ -364,7 +364,7 @@ DispatchGameModePhase:
cmp #$20 ; PRG $0146 | CPU $C146 | C9 20
bne CheckGameModeZero ; PRG $0148 | CPU $C148 | D0 1D
cpx #$01 ; PRG $014A | CPU $C14A | E0 01
bne StoreSelectedPlayerAndScreenFlags ; PRG $014C | CPU $C14C | D0 12
bne ClearAudioSetGameMode ; PRG $014C | CPU $C14C | D0 12
lda StartInputLatch ; PRG $014E | CPU $C14E | A5 37
bne ClampScreenSelectionPositionMin ; PRG $0150 | CPU $C150 | D0 21
ldy SelectedPlayerAndScreenFlags ; PRG $0152 | CPU $C152 | A4 38
@@ -650,10 +650,10 @@ al 00C1C9 .FillNametableTileBytes
al 00C1A9 .ClearNametable2000WithTile24
al 00C1AD .FillNametableAndClearAttributes
al 00C17D .ConvertPlayerSlotToOamOffset
al 00C160 .ClearAudioSetGameMode
al 00C16F .UpdateZp_37_C16F
al 00C173 .ClampScreenSelectionPositionMin
al 00C15B .StoreSelectedPlayerAndScreenFlags
al 00C173 .ClampScreenSelectionPositionMin
al 00C160 .ClearAudioSetGameMode
al 00C167 .CheckGameModeZero
al 00C18D .DispatchScreenState
al 00C13A .ClearActorFlagsLoop
Binary file not shown.
+36 -7
View File
@@ -18,7 +18,7 @@ This document provides a consolidated overview of all NES disassembly projects i
| 8 | Tennis (JU) | Japan | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL | $C07D / $C000 / $C000 |
| 9 | Pac-Man (USA) (Namco) | USA | 16 KB | 8 KB | Horizontal | BYTE-IDENTICAL | $C10E / $C000 / $C17E |
| 10 | Donkey Kong 3 (JUE) | Japan | 16 KB | 8 KB | Horizontal | BYTE-IDENTICAL | $C07D / $C000 / $C000 |
| 11 | Donkey Kong Jr. (JU) | Japan | 16 KB | 8 KB | Horizontal | BYTE-IDENTICAL (Pass 1) | $C6E6 / $C66E / $FFF0 |
| 11 | Donkey Kong Jr. (JU) | Japan | 16 KB | 8 KB | Horizontal | BYTE-IDENTICAL (Pass 2/3) | $C6E6 / $C66E / $FFF0 |
---
@@ -31,7 +31,7 @@ This document provides a consolidated overview of all NES disassembly projects i
- **Linker:** PRG at $C000, 16 KB; single segment
- **Vectors:** NMI → $C094 (`NmiHandler`), RESET → $C000 (`Reset`), IRQ → $C0F7 (`IrqHandler`, self-loop)
- **Key subsystems:** NMI-driven frame loop with PPU command buffer, round spawner ($C790), bonus objects ($CB74), carrier/rescue sequence ($C6F9), particle system ($CDAA), sound driver ($FFF7 banked)
- **Build fix:** None needed; byte-identical out of the box
- **Build fix:** None needed; byte-identical out of the box. **Pass 1 verified complete 2026-10-16** — 5,303 instructions / 11,260 code bytes (68.7%), which is *more* than the complete-opcode static tracer finds (5,277 / 11,202); the 166 tracer-only bytes are genuine data (command scripts at $D437/$D45A, the $C3B5 pointer table, the arithmetic table at $FBCA), not missed code. The last two `.incbin` spans were converted to explicit classified bytes (`TrailingFillBeforeApuTables` at $F4C5, `SoundEngineTailBytes` at $F5FC), so no ROM byte is hidden
- **Details:** `Balloon Fight (JU)/OVERVIEW.md`
### 2. Baseball (UE)
@@ -121,7 +121,7 @@ This document provides a consolidated overview of all NES disassembly projects i
- **Linker:** HEADER at $0000 (16 bytes), PRG at $C000 (16 KB), CHR at $0000 (8 KB)
- **Vectors:** NMI → $C07D (`NmiHandler`), RESET → $C000 (`Reset`), IRQ → $C000 (`Reset` reused)
- **Key subsystems:** Main loop with object/game state management at $C02E–$C18D, object movement and geometry calculations ($C28E–$C683), audio engine ($F8DE+) with sound channels ($F0–$FF), PPU command buffer streaming ($C3F4+)
- **Build fix:** Build split `main.s` into `header.s`, `prg.s`, `chr.s`; added `RandomStateAlt = $E4` for `dec $E4` at CPU $E71B (zero-page reuse with `RandomState0 = $54`)
- **Build fix:** Build split `main.s` into `header.s`, `prg.s`, `chr.s`; added `RandomStateAlt = $E4` for `dec $E4` at CPU $E71B (zero-page reuse with `RandomState0 = $54`). **2026-10-16 — one-byte branch-target bug fixed:** the project was recorded as BYTE-IDENTICAL but had never built byte-identical. The `bne` at CPU $C14C (PRG $014C) was annotated `D0 12` (target $C160) but assembled as `D0 0D`, because it was labelled `StoreSelectedPlayerAndScreenFlags` ($C15B) instead of the routine actually at $C160. Retargeted to `ClearAudioSetGameMode` — which is also the semantically correct target for a "mode != $01" test. `cmp` now passes.
- **Details:** `Donkey Kong 3 (JUE)/copilot/OVERVIEW.md`
### 11. Donkey Kong Jr. (JU)
@@ -131,7 +131,7 @@ This document provides a consolidated overview of all NES disassembly projects i
- **Linker:** HEADER at $0000 (16 bytes), PRG at $C000 (16 KB), CHR at $0000 (8 KB)
- **Vectors:** NMI → $C6E6 (`NmiHandler`), RESET → $C66E (`ResetHandler`), IRQ → $FFF0 (stray byte, effectively unused)
- **Key subsystems:** Reset idles in a PRNG-advance loop — the entire frame state machine (title/attract/gameplay/sound) runs inside the NMI handler; VRAM/event queue at $0300 with dispatch table at $BFFE; 8-byte PRNG at $18–$1F; sound timers at $F1AF
- **Build fix:** None needed; byte-identical out of the box (`make` in `copilot/`). Pass-1 status — unresolved bytes preserved as `.incbin` blocks pending Pass 2/3 renaming and table decoding
- **Build fix:** None needed; byte-identical out of the box (`make` in `copilot/`). **Pass 1 verified complete 2026-10-16** — a full byte-accounting audit of `prg.s` confirms all 16,384 PRG bytes are emitted exactly once (6,199 instructions + 3,889 `.byte` + 16 `.word`), every emitted value equals the ROM byte, and there are zero audit-comment mismatches or duplicate addresses. No `.incbin` remains. A complete-opcode static tracer independently reaches 6,135 instructions / 12,358 code bytes (75.4%) — every one of which is already present in the file, and the file carries 121 further code bytes the tracer does not find (reached via the `DeferredTaskHandlerTable` dispatch at $BFFE). Pass 2/3 naming is complete; Pass 3 tables are named (`DeferredTaskHandlerTable`, `HudDigitDescriptorTable`, …)
- **Details:** `Donkey Kong Jr. (JU)/OVERVIEW.md`
### 12. CIRCUS
@@ -258,13 +258,42 @@ make verify # (where supported by the Makefile)
---
## Pass 1 methodology note (2026-10-16)
The original Pass 1 disassembler had two limitations that silently understated
code coverage. Both are worth knowing before trusting a coverage percentage:
1. **Documented opcodes only.** Its table held the 151 documented 6502 opcodes.
These ROMs also use the 54 undocumented opcodes and the 26 unofficial NOPs
as 2/3-byte padding; a tracer that halts on them strands the real code behind.
2. **No runtime dispatch.** It followed only vectors and direct `jsr`/`jmp`/branch
targets. Games here dispatch through computed jumps — `jmp ($0014)`, the
`pla`-based inline-table gotos in Wild Gunman (`Label_C341`), and task tables
like Donkey Kong Jr.'s `DeferredTaskHandlerTable` at $BFFE.
Effect measured per project (old tracer → complete-opcode dispatch-aware tracer):
| Project | Old | Complete | Action taken |
|---------|-----|----------|--------------|
| NES PowerPad Test Card (U) | 546 instr | 559 | Pass 1 already sound |
| Joypad Test Cartridge (U) | 282 instr | **1,379** | **Pass 1 redo still outstanding** |
| Wild Gunman (U) | 1,600 instr | **4,083** | Pass 1 redone (49.3% code) |
| Balloon Fight (JU) | 5,216 instr | 5,277 | hand-done file was already better |
| Donkey Kong Jr. (JU) | 6,135 instr | 6,135 | file already complete |
**Joypad Test Cartridge (U) is the one project still carrying the old, truncated
Pass 1** — its recorded "3.5% code" is really ~18%, and roughly 2.4 KB of code is
still filed as `.byte` data. It must be redone before its Pass 2/3 can be trusted.
---
## Summary
All 15 projects in this repository rebuild **byte-identical** to their original ROMs:
| # | Project | Build Status | Pass 3 |
|---|---------|--------------|--------|
| 1 | Balloon Fight (JU) | BYTE-IDENTICAL | in progress |
| 1 | Balloon Fight (JU) | BYTE-IDENTICAL | complete (Pass 1 verified) |
| 2 | Baseball (UE) | BYTE-IDENTICAL | complete |
| 3 | Bomberman (U) | BYTE-IDENTICAL | complete |
| 4 | Burger Time (U) | BYTE-IDENTICAL | complete |
@@ -274,10 +303,10 @@ All 15 projects in this repository rebuild **byte-identical** to their original
| 8 | Tennis (JU) | BYTE-IDENTICAL | complete |
| 9 | Pac-Man (USA) (Namco) | BYTE-IDENTICAL | complete |
| 10 | Donkey Kong 3 (JUE) | BYTE-IDENTICAL | complete |
| 11 | Donkey Kong Jr. (JU) | BYTE-IDENTICAL | pending |
| 11 | Donkey Kong Jr. (JU) | BYTE-IDENTICAL | complete (Pass 1 verified) |
| 12 | CIRCUS | BYTE-IDENTICAL | complete |
| 13 | Wild Gunman (U) | BYTE-IDENTICAL | pending (Pass 1 redone) |
| 14 | Joypad Test Cartridge (U) | BYTE-IDENTICAL | pending |
| 15 | NES PowerPad Test Card (U) | BYTE-IDENTICAL | pending |
| 15 | NES PowerPad Test Card (U) | BYTE-IDENTICAL | complete |
The 20 `_wip/` skeleton projects above also all rebuild byte-identical (PRG level); all Pass 1 work and promotion to this index's numbered inventory is future work.