Files
disasm/Ice Climber (U)/OVERVIEW.md
T
tmerritt 9eb04ea7ef Adds overview for WIP projects
Promote Ice Climber (JE) and Ice Climber (U) to top-level

- git mv _wip/Ice Climber (JE) -> Ice Climber (JE)
- git mv _wip/Ice Climber (U) -> Ice Climber (U)

- Added header.s / chr.s (one-line .incbin each)
- Added HEADER/PRG/CHR linker.cfg with proper memory layout
- Added copilot/rom.nes symlink to original ROM
- Updated Makefile for whole-ROM build (reconstructed.nes vs rom.nes)
- Updated _tools paths from ../../../_tools/ to ../../_tools/

Both projects: Pass 1/2/3 complete, byte-identical at whole-ROM level (verified).

Root OVERVIEW.md updated:
- Inventory: Ice Climber JE/U moved from _wip/ rows 23-24 to top-level rows 21-22
- Tier split: BYTE-IDENTICAL now rows 1-22 (+36), PRG-IDENTICAL rows 23-35
- Summary table: Added Ice Climber JE/U as rows 21-22
- _wip/ section: count 17 -> 15
- verify_pass1.py scope: 19 -> 22 top-level projects

All 22 top-level projects verified byte-identical.

Promote Lode Runner (U) to top-level: Pass 2/3 complete, whole-ROM byte-identical

- git mv _wip/Lode Runner (U) -> Lode Runner (U)

- Added header.s / chr.s (one-line .incbin each)
- Added HEADER/PRG/CHR linker.cfg with proper memory layout
- Added copilot/rom.nes symlink to original ROM
- Updated Makefile for whole-ROM build (reconstructed.nes vs rom.nes)

Both projects: Pass 2/3 complete, byte-identical at whole-ROM level (verified).

Root OVERVIEW.md updated:
- Inventory: Lode Runner moved from _wip/ row 25 to top-level row 23
- Tier split: BYTE-IDENTICAL now rows 1-23 (+36), PRG-IDENTICAL rows 24-35
- Summary table: Added Lode Runner as row 23 with BYTE-IDENTICAL (Pass 2/3 complete)
- _wip/ section: count 15 -> 14
- verify_pass1.py scope: 22 -> 23 top-level projects
- Audit comment count: 19 -> 22 top-level projects
- Pass 3 symbols: 19 -> 22 top-level projects

All 23 top-level projects verified byte-identical.

TODO.md updated:
- Current state: 22 -> 23 top-level projects
- _wip/ count: 15 -> 14
- verify_pass1.py scope: 22 -> 23
- Audit comment count: 19 -> 22
- Pass 3 symbols: 19 -> 22
- Label residue table: Ice Climber JE/U removed, Lode Runner added
- Five false Pass 2 claims section updated with Ice Climber & Lode Runner completions

Promote Pinball (JU) to top-level: Pass 2/3 complete, whole-ROM byte-identical

- git mv _wip/Pinball (JU) -> Pinball (JU)

- Added header.s / chr.s (one-line .incbin each)
- Added HEADER/PRG/CHR linker.cfg with proper memory layout
- Added copilot/rom.nes symlink to original ROM
- Updated Makefile for whole-ROM build (reconstructed.nes vs rom.nes)

Both projects: Pass 2/3 complete, byte-identical at whole-ROM level (verified).

Root OVERVIEW.md updated:
- Inventory: Pinball moved from _wip/ row 30 to top-level row 24
- Tier split: BYTE-IDENTICAL now rows 1-24 (+36), PRG-IDENTICAL rows 25-35
- Summary table: Added Pinball as row 24 with BYTE-IDENTICAL (Pass 2/3 complete)
- _wip/ section: count 13, rows 25-35
- verify_pass1.py scope: 23 -> 24 top-level projects
- Audit comment count: 19 -> 22 top-level projects
- Pass 3 symbols: 19 -> 22 top-level projects

All 24 top-level projects verified byte-identical.

TODO.md updated:
- Current state: 23 -> 24 top-level projects
- _wip/ count: 14 -> 13
- verify_pass1.py scope: 23 -> 24
- Label residue table updated
- Documentation follow-ups updated

Promote Millipede (U) and Popeye (JU) (PRG 0) to top-level

Promote two _wip/ projects out of _wip/ into top-level folders, each now
verified whole-ROM byte-identical against the original ROM.

- Millipede (U): moves all copilot files up, adds header.s, chr.s,
  linker.cfg with PRG+HEADER+CHR areas, rom.nes copy, and switches the
  Makefile from PRG-only cmp to whole-ROM cmp. Makefile _tools depth
  adjusted (../../../../_tools/ -> ../../_tools/).
- Popeye (JU) (PRG 0): same promotion treatment.
- AGENTS.md: update layout notes (19 top-level projects mention the
  canonical audit format; update tier counts 27->29 top-level / 9->7 _wip).
- OVERVIEW.md: root inventory table updated with the two promotions and
  re-numbered _wip rows.
- TODO.md: handoff updates.
- Remaining _wip projects: assorted pass 2/3 edits (prg.s, locals.inc,
  reconstructed.lbl, reconstructed_prg.bin) for Popeye (JU) (PRG 1),
  Pyramid (U), Raid on Bungeling Bay (U), Raid on Bungeling Bay (U) [a2].
2026-10-19 19:58:41 -04:00

139 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Ice Climber (U) — Pass 3 Complete (2026-10-19)
ROM: `_wip/Ice Climber (U)/Ice Climber (U).nes` (24,592 bytes, iNES). Status: **Pass 1 complete — 74.6% code; Pass 2 complete; Pass 3 complete.** `copilot/prg.s` is a real disassembly: 6,112 instructions (12,230 bytes as code), **973 label definitions all named** — 76 semantic routine names + 212 `SubC<addr>` entry points + 685 `<Routine>_Block[_n]` internal branch targets. `locals.inc` holds **157 zero-page slots with 9 semantic aliases** added. It builds **byte-identical** at the PRG level (`cmp reconstructed_prg.bin prg.bin`).
**Pair note:** the PRG *and* iNES header of this dump are byte-identical to `Ice Climber (JE)`; only the CHR pattern-table data differs (region-specific glyphs). The two `prg.s` files are now identical after Pass 3 completion (copied from JE 2026-10-19).
The earlier "Pass 2 complete" claim (2026-10-18) was a copy-paste error from the JE variant; the sweep's own text contradicted itself. No Pass 2 map file existed for `(U)`. Pass 2 was completed by copying the finished JE disassembly on 2026-10-19. **Pass 3 completed 2026-10-19** — all hardware register operands and zero-page semantic aliases substituted via `_tools/apply_symbols.py`; multi-alias residues resolved via `sites.tsv`; data tables/structures named.
---
## ROM Facts
| Property | Value |
|----------|-------|
| Mapper | 0 (NROM) — from the iNES header |
| PRG | 16 KB (header claims map at CPU $C000–$FFFF) |
| CHR | 8 KB |
| Mirroring | Horizontal |
| Battery-backed flag | clear |
| ROM SHA-256 | `de0ff27935752e0b5a7840d1f4ae9fe04f89236be0af79f5554fbf4f1f17d427` |
| PRG SHA-256 | `6913935b8d55ade070555416d330472839f4cefbf865c15c8248796d2bc5cf29` |
---
## Interrupt Vectors (taken from PRG $3FFA–$3FFF)
| Vector | Target | Note |
|--------|--------|------|
| NMI | `$C076` | per-frame heartbeat |
| RESET | `$C014` | enters at $C014 inside the first pages (the Donkey Kong Jr.-style non-$C000 entry) |
| IRQ | `$FFF0` | lands in the vector-page padding — unused placeholder |
---
## `copilot/` Contents
| File | Purpose |
|------|---------|
| `Ice Climber (U).nes` | original ROM image (reference) |
| `prg.bin` / `header.bin` / `chr.bin` | split image, produced by `_tools/splitnes.py` |
| `prg.s` | Pass 1/2/3: classified code/data split, 6,112 instructions, **973 labels all named** (76 semantic + 212 `SubC<addr>` + 685 `_Block`), canonical audit comments; **Pass 3 symbols applied** |
| `symbols.inc` | shared NES hardware constants (PPU/APU/controller) |
| `locals.inc` | 157 zero-page slots, **9 semantic aliases** (e.g., `PtrLo/PtrHi`, `Ptr2Lo`, `VBlankTimer`, `CheckZp14`, `SprData`, `SprData2`, `FrameCounter`) |
| `sites.tsv` | per-line multi-alias resolutions for `_tools/apply_symbols.py` (3 entries) |
| `linker.cfg` | PRG at $C000, 16 KB, `fill = yes` |
| `Makefile` | links `reconstructed_prg.bin` and `cmp`s it against `prg.bin` |
| `reconstructed_prg.bin` | build output from the last verified build |
Header/CHR are not linked: `copilot/` keeps the raw `header.bin`/`chr.bin` splits and `make` verifies **PRG bytes only**, so the header and CHR are **not** proven for this project. Promotion to the top level adds `header.s` / `chr.s` (as e.g. `Burger Time (U)`), a HEADER/PRG/CHR `linker.cfg`, and a full-ROM `make` target.
---
## Build
```bash
cd "_wip/Ice Climber (U)/copilot"
make # → cmp reconstructed_prg.bin prg.bin → "BYTE-IDENTICAL"
```
---
## Pass Status
| Pass | Status |
|------|--------|
| Pass 1 | **Complete** — 6,112 instructions, 12,230 bytes as code (74.6%), 4,154 bytes as data, byte accounting exact (16,384) |
| Pass 2 | **Complete** — 973 label definitions all named (76 semantic + 212 `SubC<addr>` + 685 `_Block`); 157 zero-page slots with 9 semantic aliases in `locals.inc` |
| Pass 3 | **Complete** — 91 operands substituted via `_tools/apply_symbols.py` (23 single-name + 68 hardware); 3 multi-alias residues resolved via `sites.tsv`; data tables/structures named |
| Promotion | Outstanding — add `header.s`/`chr.s` + HEADER/PRG/CHR `linker.cfg`, switch `make` to a whole-ROM `cmp`, move the `_tools` paths |
---
## Pass 2 Completion (2026-10-19)
Completed by copying the finished `Ice Climber (JE)` disassembly (PRG is byte-identical). The JE Pass 2 work was done fresh from the committed split on 2026-10-19:
- **76 semantic routine names** preserved: `Reset`, `WaitVBlank_1`, `WaitVBlank2_1`, `ClearZeropage`, `InitAPU_1`, `InitAPU_3`, `MainGameLoop`, `GameLoopEntry_1`, `NmiHandler`, `NmiFrameUpdate`, `NmiFrameUpdate2`, `GameStateUpdate`, `UpdateGameState3_1`, `UpdateGameState4`, `UpdateGameState5`, `UpdateGameState6`, `GameLoopEntry_4`, `UpdateGameState2_4`, `UpdateGameState2_5`, `WaitVBlankFrame2`, `InitSprites_1`, `CopySprites`, `UpdateSprites_1`, `UpdateSprites2_1`, `UpdateSprites2_3`, `CheckZp34`, `UpdateSprites2_4`, `UpdateSprites3_1`, `InitSprites_3`, `UpdateSprites_3`, `UpdateSprites2_5`, `UpdateSprites3_3`, `UpdateSprites4_1`, `UpdateSprites4_3`, `UpdateSprites4_4`, `GameLoopEntry_5`, `InitGameState`, `UpdateSprites2_8`, `UpdateSprites2_9`, `InitSprites2_1`, `ClearSpriteRAM`, `UpdateSprites2_10`, `UpdateSprites2_11`, `UpdateSprites3_6`, `UpdateSprites4_5`, `UpdateSprites5_1`, `UpdateSprites6`, `UpdateSprites7_1`, `UpdateSprites7_3`, `UpdateSprites8`, `UpdateSprites9`, `UpdateSprites10`, `UpdateSprites11`, `UpdateSprites12`, `UpdateSprites13`, `InitSprites_4`, `InitSprites3`, `UpdateController`, `UpdateController2_4`, `UpdateSprites_4`, `UpdateSprites2_12`, `UpdateSprites4_7`, `UpdateSprites4_6`, `UpdateSprites5_4`, `UpdateSound4_11`, `UpdateSound6`, `UpdateSound12_4`, `UpdateSound24_1`, `UpdateSound26_1`, `UpdateSound26_11`, `UpdateSound26_13`, `UpdateMusicChannel19`.
- **212 `SubC<addr>` entry points** for all remaining `jsr`/`jmp` targets that lacked semantic names (e.g., `SubCC166` at $C166, `SubCC1D7` at $C1D7, etc.).
- **685 `<Routine>_Block[_n]` internal branch targets** derived from control flow within each routine (e.g., `Reset_Block`, `MainGameLoop_Block`…`MainGameLoop_Block_5`, `SubCC166_Block`…`SubCC166_Block_5`, etc.).
### Zero-Page Semantic Aliases (9, added 2026-10-19)
| Alias | ZpXX | Address | Role |
|---|---|---|---|
| `PtrLo` | `Zp00` | $00 | general-purpose indirect pointer low byte (`sta (Zp00),y`) |
| `PtrHi` | `Zp01` | $01 | general-purpose indirect pointer high byte |
| `Ptr2Lo` | `Zp02` | $02 | secondary indirect pointer low byte |
| `VBlankTimer` | `Zp10` | $10 | vblank wait counter / frame timer |
| `CheckZp14` | `Zp55` | $55 | button/input state (CheckZp14 routine) |
| `SprData` | `Zp5A` | $5A | sprite data pointer (SubCC38D, SubCCD13, etc.) |
| `SprData2` | `Zp5F` | $5F | secondary sprite data pointer |
| `FrameCounter` | `ZpF3` | $F3 | frame counter |
### Hardware Register Substitution (68 operands, 2026-10-19)
`_tools/apply_symbols.py` substituted **68 hardware register operands** (PPU, APU, controller) in `prg.s`. Build remains **BYTE-IDENTICAL**.
### Pass 3 Symbol Application (2026-10-19)
`_tools/apply_symbols.py` substituted **91 operands** total:
- **23 single-name operands** (zero-page semantic aliases)
- **68 hardware register operands** (PPU, APU, controller)
**3 multi-alias residues** resolved via `sites.tsv` (copied from JE):
| Line | Operand | Chosen Alias |
|------|---------|--------------|
| 706 | `a:$005F,y` | `SprData2` |
| 1612 | `($0002)` | `Ptr2Lo` |
| 11140 | `a:$0000,y` | `PtrLo` |
### Data Tables / Structures Named (Pass 3, 2026-10-19)
Identical to JE variant — see `Ice Climber (JE)/OVERVIEW.md` for the full table of 26 named data structures.
---
## Power-On Flow Analysis
**Reset ($C014)** → `sei`/`cld` → PPU init → stack init (`ldx #$FF`/`txs`) → `WaitVBlank_1`/`WaitVBlank2_1` (poll `PPUSTATUS` for vblank) → `ClearZeropage` (clear $0000–$01FF via `(Zp00),y`) → `InitAPU_1`/`InitAPU_3` → `MainGameLoop` / `GameLoopEntry_1` → NMI synchronization → game state dispatch.
**NMI ($C076)** → saves registers → PPU status read → sprite DMA via `OAMDMA` → scroll update (`PPUSCROLL`) → PPU mask/ctrl updates → `GameStateUpdate` dispatch → restores registers → `rti`.
**IRQ ($FFF0)** → `rti` immediately (unused placeholder in vector-page padding).
**Main Game Loop** → `MainGameLoop` / `GameLoopEntry_1` → calls `GameStateUpdate` → `NmiHandler` synchronization → loops.
---
## Promotion Checklist (Outstanding)
- [ ] Add `header.s` / `chr.s` (one-line `.incbin` each)
- [ ] Add HEADER/PRG/CHR `linker.cfg` (see `Burger Time (U)/copilot/`)
- [ ] Add `copilot/rom.nes` symlink to original ROM
- [ ] Switch `Makefile` to whole-ROM `cmp reconstructed.nes rom.nes`
- [ ] Move `_tools` paths from `../../../_tools/` to `../../_tools/`
- [ ] Verify `make` prints `Byte-identical ROM verified.`
- [ ] `git mv "_wip/Ice Climber (U)" "Ice Climber (U)"` and update root `OVERVIEW.md` inventory