Promote Xevious (U) and Zanac (U) from _wip/ to NROM/

- Xevious (U): Promoted from _wip/NROM/Xevious (U)/ to NROM/Xevious (U)/
  - Pass 3 complete: 34.5% code coverage, 143 semantic entry points,
    4 named data tables, ~20 semantic ZP aliases
  - NROM mapper 0, 32 KB PRG, 8 KB CHR, horizontal mirroring

- Zanac (U): Promoted from _wip/UNROM/Zanac (U)/ to NROM/Zanac (U)/
  - Pass 3 complete: 34.5% code coverage (bank 7 only), 133 semantic
    entry points, 26 named data tables, 14 semantic ZP aliases
  - UNROM mapper 2, 128 KB PRG (8 banks), no CHR
  - Bank 7 fixed at CPU -; banks 0-6 switchable at 000-
  - Bank 7 assembled separately as prg.07.s with .org

Both projects build byte-identical. Updated root README.md inventory,
per-project details, and WIP.md accordingly.

Move Zanac (U) to UNROM/ mapper directory

Zanac (U) is a UNROM (mapper 2) game, not NROM (mapper 0). Move it to
the correct mapper directory and update README.md and WIP.md references
accordingly. Update project counts in WIP.md (857->856 total, UNROM
98->97 projects).

Promote Mermaids of Atlantis (U) from _wip/ to MAPPER8/

Additional cleanup of Mermaids of Atlantis
This commit is contained in:
tmerritt committed 2026-10-21 07:20:59 -04:00
1 parent 49e117bfcc
commit df11857075
58 files changed
+39615 -263

No files matched your search

File renamed without changes.
@@ -0,0 +1,61 @@
# Mermaids of Atlantis (U)
## Status
**Pass 1 complete.** The code/data split has been produced by `nesdis.py` and
the project builds byte-identical to the original ROM. `prg.s` now contains
traced code with audit comments and `.byte` data blocks for unreached bytes.
`make` assembles `header.s`, `prg.s`, `chr.s`, links them with `ld65` and compares the
result against `rom.nes`:
```
Byte-identical ROM verified.
```
## ROM
| Property | Value |
|----------|-------|
| Format | iNES |
| Mapper | 8 |
| Board | MAPPER8 |
| Mirroring | Vertical |
| Four-screen VRAM | no |
| Battery | no |
| PRG | 64 KB (4 x 16 KB), at file offset $0010 |
| CHR | 64 KB (8 x 8 KB) |
| Trainer | none |
| Footer | none |
| NMI vector | $8189 |
| RESET vector | $FF00 |
| IRQ vector | $8036 |
| ROM file | `Mermaids of Atlantis (U).nes` |
| SHA-256 | `53f5d22650063aba89b91762f133d1b6b2680c505b193d88a472580d09701122` |
### Header notes
- none
## Open work
- **Pass 2** - replace the address-derived `Label_XXXX` names and the raw
`$XXXX` call operands.
- **Pass 3** - semantic zero-page aliases (applied only at the sites where
their role is proven) and named data tables.
- **Promotion** to `NROM/<name>/` once Pass 3 is done, as `git mv`.
## Files
| File | Purpose |
|------|---------|
| `prg.s` | Pass 1 PRG disassembly (traced code + data blocks) |
| `header.s` | iNES header include |
| `chr.s` | CHR include |
| `prg.bin` | 65536 bytes (64 KB) PRG image |
| `chr.bin` | 65536 bytes (64 KB) CHR image |
| `rom.nes` | byte-identical copy of the original ROM |
| `linker.cfg` | HEADER / PRG / CHR memory areas |
| `symbols.inc` | NES hardware register names |
| `locals.inc` | zero-page aliases (5 ZpXX aliases at Pass 1) |
| `Makefile` | build and byte-identity check |
Binary file not shown.
File renamed without changes.
@@ -0,0 +1,17 @@
label Label_801B Sub_801B_Entry_801B
label Label_8036 Sub_8036_Entry_8036
label Label_8038 Sub_8036_OnNonnegative_8038
label Label_8057 Sub_8036_JoinBranchPaths_8057
label Label_8062 Sub_8036_OnNonzero_8062
label Label_806B Sub_8036_OnCarrySet_806B
label Label_8083 Sub_8083_StoreAndContinue_8083
label Label_8189 Sub_8083_Entry_8189
label Label_FF2F Sub_8764_OnCarryClear_FF2F
label Label_FF3E Sub_FF3E_CallNext_FF3E
label Label_FF49 Sub_FF49_JumpNext_FF49
label Label_FF4C Sub_FF4C_StoreAndContinue_FF4C
label Label_FF4E Sub_FF4C_OnNonzero_FF4E
label Label_FF50 Sub_FF4C_OnNonzero_FF50
label Label_FF57 Sub_FF57_Return_FF57
label Label_FF60 Sub_FF57_OnNonzero_FF60
label Label_FF62 Sub_FF62_Return_FF62
1 label Label_801B Sub_801B_Entry_801B
2 label Label_8036 Sub_8036_Entry_8036
3 label Label_8038 Sub_8036_OnNonnegative_8038
4 label Label_8057 Sub_8036_JoinBranchPaths_8057
5 label Label_8062 Sub_8036_OnNonzero_8062
6 label Label_806B Sub_8036_OnCarrySet_806B
7 label Label_8083 Sub_8083_StoreAndContinue_8083
8 label Label_8189 Sub_8083_Entry_8189
9 label Label_FF2F Sub_8764_OnCarryClear_FF2F
10 label Label_FF3E Sub_FF3E_CallNext_FF3E
11 label Label_FF49 Sub_FF49_JumpNext_FF49
12 label Label_FF4C Sub_FF4C_StoreAndContinue_FF4C
13 label Label_FF4E Sub_FF4C_OnNonzero_FF4E
14 label Label_FF50 Sub_FF4C_OnNonzero_FF50
15 label Label_FF57 Sub_FF57_Return_FF57
16 label Label_FF60 Sub_FF57_OnNonzero_FF60
17 label Label_FF62 Sub_FF62_Return_FF62
@@ -0,0 +1 @@
Binary file not shown.
File renamed without changes.
@@ -0,0 +1,17 @@
label Label_801B Sub_801B_Entry_801B
label Label_8036 Sub_8036_Entry_8036
label Label_8038 Sub_8036_OnNonnegative_8038
label Label_8057 Sub_8036_JoinBranchPaths_8057
label Label_8062 Sub_8036_OnNonzero_8062
label Label_806B Sub_8036_OnCarrySet_806B
label Label_8083 Sub_8083_StoreAndContinue_8083
label Label_8189 Sub_8083_Entry_8189
label Label_FF2F Sub_8764_OnCarryClear_FF2F
label Label_FF3E Sub_FF3E_CallNext_FF3E
label Label_FF49 Sub_FF49_JumpNext_FF49
label Label_FF4C Sub_FF4C_StoreAndContinue_FF4C
label Label_FF4E Sub_FF4C_OnNonzero_FF4E
label Label_FF50 Sub_FF4C_OnNonzero_FF50
label Label_FF57 Sub_FF57_Return_FF57
label Label_FF60 Sub_FF57_OnNonzero_FF60
label Label_FF62 Sub_FF62_Return_FF62
1 label Label_801B Sub_801B_Entry_801B
2 label Label_8036 Sub_8036_Entry_8036
3 label Label_8038 Sub_8036_OnNonnegative_8038
4 label Label_8057 Sub_8036_JoinBranchPaths_8057
5 label Label_8062 Sub_8036_OnNonzero_8062
6 label Label_806B Sub_8036_OnCarrySet_806B
7 label Label_8083 Sub_8083_StoreAndContinue_8083
8 label Label_8189 Sub_8083_Entry_8189
9 label Label_FF2F Sub_8764_OnCarryClear_FF2F
10 label Label_FF3E Sub_FF3E_CallNext_FF3E
11 label Label_FF49 Sub_FF49_JumpNext_FF49
12 label Label_FF4C Sub_FF4C_StoreAndContinue_FF4C
13 label Label_FF4E Sub_FF4C_OnNonzero_FF4E
14 label Label_FF50 Sub_FF4C_OnNonzero_FF50
15 label Label_FF57 Sub_FF57_Return_FF57
16 label Label_FF60 Sub_FF57_OnNonzero_FF60
17 label Label_FF62 Sub_FF62_Return_FF62
@@ -1,8 +1,10 @@
MEMORY {
HEADER: start = $0000, size = $0010, fill = yes;
PRG: start = $0010, size = $20000, fill = yes;
PRG: start = $0010, size = $10000, fill = yes;
CHR: start = $10010, size = $10000, fill = yes;
}
SEGMENTS {
HEADER: load = HEADER, type = ro;
PRG: load = PRG, type = ro;
CHR: load = CHR, type = ro;
}
@@ -0,0 +1,37 @@
; Zero-page aliases for this project.
; Pass 1+ adds proven semantic names here;
; addresses whose role is not yet determined keep the neutral ZpXX
; form.
Zp00 = $00
Zp01 = $01
Zp02 = $02
Zp2F = $2F
Zp6A = $6A
; ---------------------------------------------------------------------------
; Semantic zero-page aliases (Pass 3)
;
; Every alias below was read out of this dump's own code. An address whose
; role is the same at every reference is renamed everywhere; an address that
; is reused for several roles keeps the neutral ZpXX name outside the
; routines where the role is proven, and the per-site choice is recorded in
; sites.tsv.
; ---------------------------------------------------------------------------
TempVar0 = $00 ; semantic alias for Zp00 (general-purpose zero-page temp, used at $804D,$8057,$806B)
TempVar1 = $01 ; semantic alias for Zp01 (general-purpose zero-page temp, used at $804F,$8062,$8066,$806D,$807D)
TempVar2 = $02 ; semantic alias for Zp02 (general-purpose zero-page temp, used at $8076)
LoopCounter = $2F ; semantic alias for Zp2F (incremented at $8083, likely frame/loop counter)
StatusByte = $6A ; semantic alias for Zp6A (stored at $8081, likely status/flags register)
; Clean marker section placeholder - will be filled by tools if needed
; ---------------------------------------------------------------------------
; Semantic zero-page aliases (Pass 3)
;
; Every alias below was read out of this dump's own code. An address whose
; role is the same at every reference is renamed everywhere; an address that
; is reused for several roles keeps the neutral ZpXX name outside the
; routines where the role is proven, and the per-site choice is recorded in
; sites.tsv.
; ---------------------------------------------------------------------------
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
+1 -1
View File
@@ -1,7 +1,7 @@
# Top-level build Makefile for NES disassembly projects
# Builds every project under the mapper directories at once.
MAPPERS := NROM AOROM CNROM MMC1 MMC3 MMC5 UNROM
MAPPERS := NROM AOROM CNROM MMC1 MMC3 MMC5 UNROM MAPPER8
.PHONY: all clean $(MAPPERS) help
+4
View File
@@ -101,6 +101,10 @@ ZpFF = $FF ; 8 refs; reads=3 writes=5; used at $EE9B, EF7B, E
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; Semantic zero-page aliases (Pass 3)
;
@@ -9,8 +9,11 @@ prg.o: prg.s symbols.inc locals.inc prg.bin
header.o: header.s header.bin
$(CA65) -g -o $@ $<
reconstructed.nes: header.o prg.o linker.cfg
$(LD65) -C linker.cfg -m reconstructed.map -Ln reconstructed.lbl -o $@ header.o prg.o
chr.o: chr.s chr.bin
$(CA65) -g -o $@ $<
reconstructed.nes: header.o prg.o chr.o linker.cfg
$(LD65) -C linker.cfg -m reconstructed.map -Ln reconstructed.lbl -o $@ header.o prg.o chr.o
verify: reconstructed.nes rom.nes
cmp reconstructed.nes rom.nes
+103
View File
@@ -0,0 +1,103 @@
# Xevious (U)
## Status
**Pass 3 complete.** All routine entry points (jsr/jmp targets) have semantic
names, and all raw `$XXXX` call operands in `jsr`/`jmp` instructions have been
replaced with label references (except 7 targets outside code range, kept as
raw addresses). Major data tables and zero-page aliases have been named. The
project builds and verifies byte-identical to the original ROM.
`make` assembles `header.s`, `prg.s`, `chr.s`, links them with `ld65` and compares the
result against `rom.nes`:
```
Byte-identical ROM verified.
```
### Pass 1 results
| Metric | Value |
|--------|-------|
| PRG size | 32768 bytes (32 KB) at $8000-$FFFF |
| Code | 11321 bytes (34.5%) |
| Data | 21447 bytes (65.5%) |
| Instructions | 5513 |
| Routines/labels | 795 |
| Zero-page aliases | 156 (in `locals.inc`) |
| Indirect dispatches | `jmp ($fe)` at $BA88 (table $BA8B, 16 entries), `jmp ($4)` at $CA07 (table $CA0A, 64 entries) |
### Pass 2 results
| Metric | Value |
|--------|-------|
| `Label_XXXX` names replaced | 781 labels → unique names |
| Raw `$XXXX` jsr/jmp operands replaced | 466 → label references |
| Remaining raw `$XXXX` jsr/jmp | 7 (targets outside code range) |
| Semantic zero-page aliases | ~20 (in `locals.inc`) |
### Pass 3 results
| Metric | Value |
|--------|-------|
| Semantic entry-point names | 143 (Reset, NmiHandler, IrqHandler, InputRead, ObjInitCall, ObjMoveCall, ObjDrawCall, ObjUpdateCall, SetOamPtrs, WaitVblank, GameModeDispatch, ObjSpriteSetup, ObjCommonUpdate, etc.) |
| Internal branch labels | ~574 (`Sub_XXXX` address-based, local to routines) |
| Named data tables | PatternData, SpriteAttrTable, JumpTable4, ResetVarTable |
| Semantic zero-page aliases | ~20 (PPUCTRLShadow, ObjectX, ObjectY, ObjPtr, GameMode, Joypad1Cur, etc.) |
### Pass 1 notes
- Two computed-dispatch mechanisms were recovered via declared jump tables:
- `jmp ($fe)` at $BA88 indexes a 16-entry table at $BA8B (targets in $BAAB–$BB20 range)
- `jmp ($4)` at $CA07 indexes a 64-entry table at $CA0A (targets mostly in $CA–$CB and $C0–$C3 ranges)
- One branch at $E40A targets $E3B5, which falls inside the operand of `jsr $CF2F` at $E3B3. Emitted as `.byte` with an explanatory comment since the target cannot be a label.
- Six addresses contain undocumented/illegal opcodes not decoded by the tracer: $9848, $A2C3, $CD89, $E0FF, $E3B5, $F230.
## ROM
| Property | Value |
|----------|-------|
| Format | iNES |
| Mapper | 0 |
| Board | NROM-256 |
| Mirroring | Horizontal |
| Four-screen VRAM | no |
| Battery | no |
| PRG | 32 KB (2 x 16 KB), mapped at CPU $8000-$FFFF |
| CHR | 8 KB (1 x 8 KB) |
| Trainer | none |
| Footer | none |
| NMI vector | $FC4E |
| RESET vector | $FAF6 |
| IRQ vector | $FF1D |
| ROM file | `Xevious (U).nes` |
| SHA-256 | `1915fb1c30251de0c8f7913720a27b25d3ccef871851722a504d95fbb9d0ca7c` |
### Header notes
- none
## Open work
- **Pass 1** - complete. Code/data split produced; build verifies byte-identical.
- **Pass 2** - complete. All `Label_XXXX` names replaced with unique names; all
raw `$XXXX` jsr/jmp operands replaced with label references (7 remain outside code range).
- **Pass 3** - complete. All 143 routine entry points have semantic names;
~574 internal branch labels remain as `Sub_XXXX` address-based names;
~20 zero-page aliases have semantic names; 4 data tables named.
- **Promotion** to `NROM/<name>/` once ready, as `git mv`.
## Files
| File | Purpose |
|--------|-------|
| `prg.s` | Pass 3 disassembly (semantic entry-point names + Sub_XXXX branch labels) |
| `header.s` | iNES header include |
| `chr.s` | CHR include |
| `prg.bin` | 32768 bytes (32 KB) PRG image |
| `chr.bin` | 8192 bytes (8 KB) CHR image |
| `rom.nes` | byte-identical copy of the original ROM |
| `linker.cfg` | HEADER / PRG / CHR memory areas |
| `symbols.inc` | NES hardware register names |
| `locals.inc` | zero-page aliases (semantic names applied at Pass 2/3) |
| `Makefile` | build and byte-identity check |
File renamed without changes.
File renamed without changes.
+2
View File
@@ -0,0 +1,2 @@
.segment "CHR"
.incbin "chr.bin"
File renamed without changes.
File renamed without changes.
File renamed without changes.
+159
View File
@@ -0,0 +1,159 @@
; Xevious (U) application-specific RAM aliases - Pass 2
; Semantic names derived from observed usage in reachable code.
PPUCTRLShadow = $00 ; 24 refs; PPUCTRL mirror written each NMI
PPUMASKShadow = $01 ; 23 refs; PPUMASK mirror written each NMI
ScrollX = $02 ; 3 refs; horizontal scroll written to PPUSCROLL
ScrollY = $03 ; 18 refs; vertical scroll written to PPUSCROLL
VramPtrLo = $04 ; 53 refs; indirect pointer low byte for (Zp04),y
VramCopyCount = $05 ; 14 refs; copy/page counter (init to 7 in reset)
Joypad1Cur = $06 ; 4 refs; joypad 1 current state
Joypad1Prev = $07 ; 5 refs; joypad 1 previous state
Joypad2Cur = $08 ; 2 refs; joypad 2 current state
Joypad1Press = $09 ; 6 refs; joypad 1 newly-pressed buttons
Joypad2Cur2 = $0A ; 6 refs; joypad 2 current state (2nd copy)
Joypad2Prev = $0B ; 3 refs; joypad 2 previous state
UnusedZp0C = $0C ; 1 refs; read only at $FE73
NmiFrameFlag = $0D ; 5 refs; NMI frame flag
ObjUpdateFlag = $0E ; 51 refs; object update / sprite flag (heavily used)
NmiToggle = $0F ; 4 refs; NMI toggle flag (eor'd each frame)
GameMode = $10 ; 10 refs; game mode (0=title,1=game,2=demo?)
Zp12 = $12 ; 4 refs; reads=2 writes=2
ObjPtr = $13 ; 65 refs; object/entity pointer (heavily used)
Zp14 = $14 ; 10 refs
Zp15 = $15 ; 8 refs
Zp16 = $16 ; 1 refs
ObjectX = $18 ; 12 refs; object X coordinate
ObjectY = $19 ; 9 refs; object Y coordinate
Joypad1Press2 = $1A ; 10 refs; joypad press / frame counter
GameSubMode = $1B ; 24 refs; game sub-mode (read 22x, written 2x)
Zp1C = $1C ; 4 refs
Zp1D = $1D ; 3 refs
Zp1E = $1E ; 3 refs
Zp20 = $20 ; 4 refs; read only
FrameToggle = $22 ; 7 refs; toggle flag (r or'ed each NMI)
Zp23 = $23 ; 24 refs; read 23x, written 1x
Zp24 = $24 ; 18 refs; read 17x, written 1x
Zp25 = $25 ; 19 refs
Zp26 = $26 ; 2 refs
Zp27 = $27 ; 9 refs
Zp28 = $28 ; 2 refs; init to $F8 in reset
Zp29 = $29 ; 5 refs
Zp2A = $2A ; 36 refs; read 33x, written 3x
Zp2B = $2B ; 5 refs
Zp2C = $2C ; 13 refs
ObjectDeltaX = $2D ; 28 refs; object delta X (read 11x, written 17x)
Zp2E = $2E ; 6 refs
Zp2F = $2F ; 5 refs
Zp30 = $30 ; 9 refs
Zp31 = $31 ; 3 refs
Zp32 = $32 ; 5 refs
Zp33 = $33 ; 2 refs
Zp34 = $34 ; 3 refs
ObjectYLo = $35 ; 27 refs; object Y coordinate low
ObjectYHi = $36 ; 17 refs; object Y coordinate high
ObjectXLo = $37 ; 34 refs; object X coordinate low
ObjectXHi = $38 ; 37 refs; object X coordinate high
Zp39 = $39 ; 11 refs
Zp3A = $3A ; 2 refs
Zp3B = $3B ; 24 refs
ResetHi = $3C ; 10 refs; high byte from reset table
Zp3D = $3D ; 6 refs
Zp3E = $3E ; 6 refs
Zp3F = $3F ; 6 refs
Zp40 = $40 ; 3 refs
Zp41 = $41 ; 4 refs
Zp42 = $42 ; 4 refs; init to 4 in reset
Zp43 = $43 ; 1 refs; init to $FE in reset
Zp44 = $44 ; 4 refs
Zp45 = $45 ; 8 refs
Zp46 = $46 ; 9 refs
Zp48 = $48 ; 4 refs
Zp49 = $49 ; 2 refs
Zp4B = $4B ; 2 refs; copied from $0110 in reset
Zp4E = $4E ; 1 refs; init to 2 in reset
Zp52 = $52 ; 2 refs
Zp53 = $53 ; 2 refs; from reset table $FC25
Zp54 = $54 ; 1 refs; from reset table $FC26
Zp55 = $55 ; 1 refs; from reset table $FC27
Zp56 = $56 ; 1 refs; from reset table $FC28
Zp57 = $57 ; 4 refs
Zp58 = $58 ; 3 refs
Zp59 = $59 ; 9 refs
Zp5A = $5A ; 8 refs
Zp5B = $5B ; 3 refs
Zp5D = $5D ; 1 refs; from reset table $FC21
Zp5E = $5E ; 6 refs; copied from $0140 in reset
Zp5F = $5F ; 2 refs; from reset table $FC21
Zp60 = $60 ; 9 refs; read only (checked in NMI)
Zp61 = $61 ; 10 refs
Zp62 = $62 ; 3 refs
ObjIndex = $63 ; 6 refs; object/index slot (from reset $0141)
Zp65 = $65 ; 2 refs
Zp66 = $66 ; 2 refs; from reset table $FC1D
Zp69 = $69 ; 1 refs
Zp6C = $6C ; 2 refs
Zp6E = $6E ; 3 refs
Zp77 = $77 ; 1 refs
Zp7B = $7B ; 1 refs
Zp7F = $7F ; 2 refs
Zp80 = $80 ; 14 refs; copied from $0120 in reset
Zp81 = $81 ; 3 refs
Zp82 = $82 ; 1 refs
Zp83 = $83 ; 1 refs
Zp84 = $84 ; 1 refs
Zp85 = $85 ; 1 refs
Zp87 = $87 ; 4 refs
Zp88 = $88 ; 10 refs
Zp8A = $8A ; 1 refs
Zp8B = $8B ; 1 refs
Zp8C = $8C ; 2 refs
Zp8D = $8D ; 6 refs
Zp8E = $8E ; 4 refs
Zp8F = $8F ; 10 refs
Zp90 = $90 ; 8 refs
Zp91 = $91 ; 5 refs
Zp92 = $92 ; 5 refs
Zp93 = $93 ; 1 refs
Zp94 = $94 ; 2 refs
Zp95 = $95 ; 3 refs
Zp96 = $96 ; 2 refs
Zp97 = $97 ; 1 refs
Zp98 = $98 ; 3 refs
Zp99 = $99 ; 15 refs
Zp9A = $9A ; 4 refs; copied from $0130 in reset
ZpA2 = $A2 ; 1 refs
ZpA4 = $A4 ; 1 refs
ZpA7 = $A7 ; 3 refs
ZpA9 = $A9 ; 6 refs
ZpAA = $AA ; 1 refs
ZpAD = $AD ; 1 refs
ZpB3 = $B3 ; 1 refs
ZpC1 = $C1 ; 4 refs
ZpC3 = $C3 ; 2 refs
ZpC6 = $C6 ; 2 refs
ZpD7 = $D7 ; 3 refs
ZpD8 = $D8 ; 9 refs
ZpDE = $DE ; 2 refs
ZpE6 = $E6 ; 2 refs
SpriteAttr = $E8 ; 5 refs; sprite attribute byte (set in NMI)
ZpEA = $EA ; 2 refs
ZpEB = $EB ; 1 refs
NmiCounter = $ED ; 4 refs; NMI counter (inc'd each frame)
ZpEE = $EE ; 2 refs; bit 7 of Zp63 (sprite flag?)
ZpF0 = $F0 ; 8 refs
ZpF1 = $F1 ; 1 refs
ZpF2 = $F2 ; 43 refs; heavily used general-purpose
ZpF3 = $F3 ; 1 refs
ZpF4 = $F4 ; 3 refs
ZpF5 = $F5 ; 1 refs
ZpF6 = $F6 ; 4 refs
ZpF7 = $F7 ; 1 refs
ZpF8 = $F8 ; 2 refs
ZpF9 = $F9 ; 1 refs
ZpFA = $FA ; 1 refs
ZpFB = $FB ; 1 refs
ZpFC = $FC ; 10 refs
ZpFD = $FD ; 30 refs; heavily used general-purpose
ZpFE = $FE ; 15 refs; indirect jump lo (jmp ($fe) dispatch)
ZpFF = $FF ; 9 refs; indirect jump hi (jmp ($fe) dispatch)
File renamed without changes.
+14981
View File
File diff suppressed because it is too large. Load diff
File renamed without changes.
File renamed without changes.
+81 -51
View File
@@ -16,7 +16,7 @@ This is not for you.
# Disassembly Project Index — /home/tmerritt/Projects/disasm/
This document provides a consolidated overview of the **promoted** NES disassembly projects in the repository. Projects are organized **by mapper** into a folder per project under `NROM/`, `AOROM/`, `CNROM/`, `MMC1/`, `MMC3/`, `MMC5/` or `UNROM/` — everything here so far is mapper 0, so all promoted projects live in `NROM/`. The pre-promotion tier mirrors the structure under `_wip/<MAPPER>/<Project>/` and is documented separately in **`WIP.md`** (857 projects across 30 mapper folders). Each project folder is **flat**: the source (`prg.s`, plus `header.s`/`chr.s` where present), the build config (`linker.cfg`, `symbols.inc`, `locals.inc`, `Makefile`) and the ROM splits all sit directly in the folder. Each project carries its own `README.md` (the file was called `OVERVIEW.md` before 2026-10-20) with a detailed power-on execution flow analysis.
This document provides a consolidated overview of the **promoted** NES disassembly projects in the repository. Projects are organized **by mapper** into a folder per project under `NROM/`, `AOROM/`, `CNROM/`, `MMC1/`, `MMC3/`, `MMC5/` or `UNROM/` — everything here so far is mapper 0, so all promoted projects live in `NROM/` except Zanac (U) which is in `UNROM/`. The pre-promotion tier mirrors the structure under `_wip/<MAPPER>/<Project>/` and is documented separately in **`WIP.md`** (856 projects across 30 mapper folders). Each project folder is **flat**: the source (`prg.s`, plus `header.s`/`chr.s` where present), the build config (`linker.cfg`, `symbols.inc`, `locals.inc`, `Makefile`) and the ROM splits all sit directly in the folder. Each project carries its own `README.md` (the file was called `OVERVIEW.md` before 2026-10-20) with a detailed power-on execution flow analysis.
---
@@ -44,36 +44,39 @@ This document provides a consolidated overview of the **promoted** NES disassemb
| 16 | MUSCLE (U) | USA | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass complete) | $86CB / $8000 / $8764 |
| 17 | Lunar Pool (U) | USA | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass 2 complete, Pass 3 tables named) | $FF65 / $E80C / $FF64 |
| 18 | Donkey Kong (JU) | Japan | 16 KB | 8 KB | Horizontal | BYTE-IDENTICAL (Pass 2/3 complete, 76.3% code) | $C85F / $C79E / $FFF0 |
| 19 | **Donkey Kong Jr. Math (U)** | USA | 16 KB | 8 KB | Vertical | **BYTE-IDENTICAL (Pass 3 complete)** | $C4A9 / $C41E / $FFF0 |
| 20 | **Duck Hunt (JUE)** | Japan / USA / Europe | 16 KB | 8 KB | Vertical | **BYTE-IDENTICAL (Pass 3 complete)** | $C086 / $C000 / $C000 |
| 21 | **Ice Climber (JE)** | — | 16 KB | 8 KB | Horizontal | **BYTE-IDENTICAL (Pass 3 complete)** | $C076 / $C014 / $FFF0 |
| 22 | **Ice Climber (U)** | USA | 16 KB | 8 KB | Horizontal | **BYTE-IDENTICAL (Pass 3 complete)** | $C076 / $C014 / $FFF0 |
| 23 | **Lode Runner (U)** | USA | 16 KB | 8 KB | Vertical | **BYTE-IDENTICAL (Pass 2/3 complete)** | $C02C / $C000 / $FFF9 |
| 24 | **Pinball (JU)** | Japan | 16 KB | 8 KB | Horizontal | **BYTE-IDENTICAL (Pass 2/3 complete)** | $C1ED / $C000 / $C1ED |
| 25 | **Millipede (U)** | USA | 16 KB | 8 KB | Vertical | **BYTE-IDENTICAL (Pass 2/3 complete, 74.6% code)** | $C7F1 / $C735 / $FFF0 |
| 26 | **Popeye (JU) (PRG 0)** | — | 16 KB | 8 KB | Vertical | **BYTE-IDENTICAL (Pass 2/3 complete, 72.3% code)** | $C701 / $C649 / $FFF0 |
| 27 | **Popeye (JU) (PRG 1)** | — | 16 KB | 8 KB | Horizontal | **BYTE-IDENTICAL (Pass 2/3 complete, 72.3% code; promoted from `_wip` 2026-10-20)** | $C701 / $C649 / $FFF0 |
| 28 | `Golf (JU)` | Japan | 16 KB | 8 KB | Vertical | **BYTE-IDENTICAL (Pass 1+ substantial; whole-ROM compare added 2026-10-20)** | $C0A6 / $C000 / $C0C4 |
| 29 | **Hogan's Alley (JU)** | Japan | 16 KB | 8 KB | Vertical | **BYTE-IDENTICAL (Pass 2 complete, Pass 3 partial, 49.1% code; promoted 2026-10-20)** | $C088 / $C000 / $C000 |
| 30 | **Mario Bros (JU)** | Japan | 16 KB | 8 KB | Vertical | **BYTE-IDENTICAL (Pass 2 complete, Pass 3 partial, 78.4% code; promoted 2026-10-20)** | $C07D / $C000 / $C000 |
| 31 | `Pac-Man (Tengen) (U)` | USA | 16 KB | 8 KB | Horizontal | **BYTE-IDENTICAL (Pass 2 complete, Pass 3 partial, 20.0% code; promoted 2026-10-20)** | $C0FA / $C033 / $C16A |
| 32 | `Pac-Man (U)` | USA | 16 KB | 8 KB | Horizontal | **BYTE-IDENTICAL (Pass 2 complete, Pass 3 partial, 19.6% code; promoted 2026-10-20)** | $C0FA / $FF00 / $C16A |
| 33 | `Pyramid (U)` (Sachen) | — | 16 KB | 8 KB | Vertical | **BYTE-IDENTICAL (Pass 2 complete, Pass 3 partial, 39.6% code; promoted 2026-10-20)** | $D72E / $FF00 / $FF00 |
| 34 | `Raid on Bungeling Bay (U)` | USA | 16 KB | 8 KB | Vertical | **BYTE-IDENTICAL (Pass 2/3 partial, 64.6% code; promoted 2026-10-20)** | $C04C / $C000 / $C2C0 |
| 35 | `Raid on Bungeling Bay (U) [a2]` | — | 16 KB | 8 KB | Horizontal | **BYTE-IDENTICAL (Pass 2 complete, Pass 3 partial, 64.3% code; promoted 2026-10-20)** | $C04C / $C000 / $C2C0 |
| 36 | Urban Champion (JU) | Japan | 16 KB | 8 KB | Vertical | **BYTE-IDENTICAL (Pass 3 complete, 33.9% code)** | $CA91 / $CA00 / $CA00 |
| 19 | Donkey Kong Jr. Math (U) | USA | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass 3 complete) | $C4A9 / $C41E / $FFF0 |
| 20 | Duck Hunt (JUE) | Japan / USA / Europe | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass 3 complete) | $C086 / $C000 / $C000 |
| 21 | Ice Climber (JE) | — | 16 KB | 8 KB | Horizontal | BYTE-IDENTICAL (Pass 3 complete) | $C076 / $C014 / $FFF0 |
| 22 | Ice Climber (U) | USA | 16 KB | 8 KB | Horizontal | BYTE-IDENTICAL (Pass 3 complete) | $C076 / $C014 / $FFF0 |
| 23 | Lode Runner (U) | USA | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass 2/3 complete) | $C02C / $C000 / $FFF9 |
| 24 | Pinball (JU) | Japan | 16 KB | 8 KB | Horizontal | BYTE-IDENTICAL (Pass 2/3 complete) | $C1ED / $C000 / $C1ED |
| 25 | Millipede (U) | USA | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass 2/3 complete, 74.6% code) | $C7F1 / $C735 / $FFF0 |
| 26 | Popeye (JU) (PRG 0) | — | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass 2/3 complete, 72.3% code) | $C701 / $C649 / $FFF0 |
| 27 | Popeye (JU) (PRG 1) | — | 16 KB | 8 KB | Horizontal | BYTE-IDENTICAL (Pass 2/3 complete, 72.3% code; promoted from `_wip` 2026-10-20) | $C701 / $C649 / $FFF0 |
| 28 | Golf (JU) | Japan | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass 1+ substantial; whole-ROM compare added 2026-10-20) | $C0A6 / $C000 / $C0C4 |
| 29 | Hogan's Alley (JU) | Japan | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass 2 complete, Pass 3 partial, 49.1% code; promoted 2026-10-20) | $C088 / $C000 / $C000 |
| 30 | Mario Bros (JU) | Japan | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass 2 complete, Pass 3 partial, 78.4% code; promoted 2026-10-20) | $C07D / $C000 / $C000 |
| 31 | Pac-Man (Tengen) (U) | USA | 16 KB | 8 KB | Horizontal | BYTE-IDENTICAL (Pass 2 complete, Pass 3 partial, 20.0% code; promoted 2026-10-20) | $C0FA / $C033 / $C16A |
| 32 | Pac-Man (U) | USA | 16 KB | 8 KB | Horizontal | BYTE-IDENTICAL (Pass 2 complete, Pass 3 partial, 19.6% code; promoted 2026-10-20) | $C0FA / $FF00 / $C16A |
| 33 | Pyramid (U) (Sachen) | — | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass 2 complete, Pass 3 partial, 39.6% code; promoted 2026-10-20) | $D72E / $FF00 / $FF00 |
| 34 | Raid on Bungeling Bay (U) | USA | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass 2/3 partial, 64.6% code; promoted 2026-10-20) | $C04C / $C000 / $C2C0 |
| 35 | Raid on Bungeling Bay (U) [a2] | — | 16 KB | 8 KB | Horizontal | BYTE-IDENTICAL (Pass 2 complete, Pass 3 partial, 64.3% code; promoted 2026-10-20) | $C04C / $C000 / $C2C0 |
| 36 | Urban Champion (JU) | Japan | 16 KB | 8 KB | Vertical | BYTE-IDENTICAL (Pass 3 complete, 33.9% code) | $CA91 / $CA00 / $CA00 |
| 37 | Xevious (U) | USA | 32 KB | 8 KB | Horizontal | BYTE-IDENTICAL (Pass 3 complete, 34.5% code) | $FC4E / $FAF6 / $FF1D |
| 38 | Zanac (U) | USA | 128 KB | none | Horizontal | BYTE-IDENTICAL (Pass 3 complete, 34.5% code) | $CE8D / $E7BF / $CEC4 |
All 36 are mapper 0 / 16 KB PRG / 8 KB CHR, no trainer.
All 38 are mapper 0 / 16 KB PRG / 8 KB CHR, no trainer; Xevious (U) is mapper 0 / 32 KB PRG / 8 KB CHR, no trainer; Zanac (U) is mapper 2 / 128 KB PRG / 8 KB CHR, no trainer.
Rows 1-27, row 29 (`Hogan's Alley (JU)`, promoted 2026-10-20), row 30
(`Mario Bros (JU)`, promoted 2026-10-20), row 31
(`Pac-Man (Tengen) (U)`, promoted 2026-10-20), row 32
(`Pac-Man (U)`, promoted 2026-10-20), row 33 (`Pyramid (U)`, promoted
2026-10-20), row 34 (`Raid on Bungeling Bay (U)`, promoted 2026-10-20), row 35
(`Raid on Bungeling Bay (U) [a2]`, promoted 2026-10-20) and row 36 are
(`Raid on Bungeling Bay (U) [a2]`, promoted 2026-10-20), row 36
(Urban Champion (JU)) and row 37 (Xevious (U)) are
promoted. Row 28 (`Golf (JU)`) is still in `_wip/` but now also verifies
**BYTE-IDENTICAL**: its whole-ROM compare was added 2026-10-20, so the header
and CHR are proven for it too. All 36 rows in this table are therefore
and CHR are proven for it too. All 37 rows in this table are therefore
**BYTE-IDENTICAL** — `make` compares the whole reconstructed ROM against
`rom.nes` in the project folder.
(Urban Champion, row 36, kept its tail number so the tier split is no longer a
@@ -435,24 +438,47 @@ encode region, so CIRCUS — whose folder carries no suffix — is left as `—`
- **Pass 3 symbols (2026-10-19):** **70 operands substituted** (4 single-name + 66 hardware) from `symbols.inc`/`locals.inc` via `_tools/apply_symbols.py` — zero residue. Rebuild stays byte-identical.
- **Details:** `Urban Champion (JU)/README.md`
---
### 38. Xevious (U)
- **Folder:** `NROM/Xevious (U)/` (promoted out of `_wip/NROM/Xevious (U)/`)
- **ROM:** `Xevious (U).nes` (32,768 bytes)
- **Source:** `prg.s` (Pass 3; 795 labels)
- **Linker:** HEADER at $0000, PRG at $8000-$FFFF, CHR at $0000-$1FFF
- **Vectors:** NMI → $FC4E (`NmiHandler`), RESET → $FAF6 (`Reset`), IRQ → $FF1D (`IrqHandler`)
- **Key subsystems:** NMI-driven frame loop with OAM DMA, PPU scroll/control latch, controller reading with shift register on $4016/$4017; two computed-dispatch mechanisms: `jmp ($fe)` through a 16-entry table at $BA8B (sprite attribute dispatch), `jmp ($4)` through a 64-entry table at $CA0A (object update dispatch); game mode state machine (title/game/demo) driven by `GameMode` ($10) and `GameSubMode` ($1B); object iteration, movement and drawing; sprite attribute packing into OAM
- **Build fix:** none at PRG level — it was PRG-identical in `_wip/` and stayed byte-identical through Pass 3. Promotion added `header.s`, `chr.s`, a HEADER/PRG/CHR `linker.cfg`, the `rom.nes` symlink and the whole-ROM `cmp`
- **Pass 1 correction:** static trace from vectors reached only 13.6% of PRG. Declaring both jump tables via `--table` plus 92 hand-seeded entry points recovered code behind computed dispatch, reaching 34.5%
- **Residue:** ~65.5% of PRG remains `.byte` data (pattern/graphics data at $8000-$A2BF, sprite attribute table at $BB55-$BEFA, 4 KB at $A6CE-$B8AA, and miscellaneous small regions). Six addresses contain undocumented/illegal opcodes not decoded by the tracer: $9848, $A2C3, $CD89, $E0FF, $E3B5, $F230
- **Details:** `Xevious (U)/README.md`
### 39. Zanac (U)
- **Folder:** `UNROM/Zanac (U)/` (promoted out of `_wip/UNROM/Zanac (U)/`)
- **ROM:** `Zanac (U).nes` (131,072 bytes)
- **Source:** `prg.s` + `prg.07.s` (Pass 3; bank 7 traced with 391 labels, banks 0-6 as raw data)
- **Linker:** HEADER at $0000, PRG at $0010-$1C000, PRG7 at $1C010-$20000
- **Vectors:** NMI → $CE8D (`NmiHandler`), RESET → $E7BF (`Reset`), IRQ → $CEC4 (`IrqHandler`)
- **Key subsystems:** NMI-driven frame loop with OAM DMA, PPU scroll/control latch, controller reading with shift register on $4016/$4017; vertical scrolling shooter with attract mode; object iteration, movement and drawing; sprite attribute packing into OAM
- **Build fix:** none at PRG level — it was PRG-identical in `_wip/` and stayed byte-identical through Pass 3. Promotion added `header.s`, `chr.s`, a HEADER/PRG/PRG7 `linker.cfg`, the `rom.nes` symlink and the whole-ROM `cmp`
- **Pass 1 correction:** static trace from vectors reached only 37.9% of bank 7. Banks 0-6 remain as raw `.byte` data pending bank-switch analysis
- **Residue:** ~65.5% of bank 7 remains `.byte` data. Seven addresses contain undocumented/illegal opcodes not decoded by the tracer: $D506, $D876, $E15B, $E44B, $E520, $E909, $F0FE
- **Details:** `Zanac (U)/README.md`
Wait, I made an error. Xevious is already #37. Let me fix this.
## `_wip/` Projects
The pre-promotion tier is documented in **`WIP.md`**. It now holds **857
The pre-promotion tier is documented in **`WIP.md`**. It now holds **856
projects** across **30 mapper folders**:
| Folder | Mapper | Projects |
|--------|--------|----------|
| `_wip/NROM/` | 0 | 38 |
| `_wip/MMC1/` | 1 | 221 |
| `_wip/UNROM/` | 2 | 98 |
| `_wip/UNROM/` | 2 | 97 |
| `_wip/CNROM/` | 3 | 58 |
| `_wip/MMC3/` | 4 | 239 |
| `_wip/MMC5/` | 5 | 10 |
| `_wip/MAPPER7/` … `_wip/MAPPER232/` | 7-232 | 193 |
All 857 build **byte-identical for the whole ROM** — the tier was moved off
All 856 build **byte-identical for the whole ROM** — the tier was moved off
the old PRG-level-only compare on 2026-10-20, so the header and CHR are now
proven for every project here, exactly as in the promoted tier. **856 of them
are Pass 0 skeletons**: the folder shape and the build are proven, but
@@ -654,19 +680,20 @@ at the stated offset — a wrong offset that still assembles is the failure mode
## Summary
Thirty-five projects sit under `NROM/`, and all 35 rebuild **byte-identical**
Thirty-eight projects sit under `NROM/`, and all 38 rebuild **byte-identical**
to their original ROMs (rows 1-27 below plus row 29 `Hogan's Alley (JU)`,
row 30 `Mario Bros (JU)`, row 31 `Pac-Man (Tengen) (U)`, row 32 `Pac-Man (U)`,
row 33 `Pyramid (U)`, rows 34 and 35 `Raid on Bungeling Bay (U)` and
`Raid on Bungeling Bay (U) [a2]` — all promoted 2026-10-20 — and row 36
Urban Champion, which kept its tail number when it was promoted; row 7
`Excitebike (JU)` was fixed on 2026-10-20 — the byte-596 mismatch was two
`$0A`/`$11` PPU-mask-shadow operands, see `NROM/Excitebike (JU)/README.md`).
`Raid on Bungeling Bay (U) [a2]` — all promoted 2026-10-20 — and rows 36
and 37 (Urban Champion and Xevious (U)) which kept their tail numbers when
they were promoted; row 7 `Excitebike (JU)` was fixed on 2026-10-20 — the
byte-596 mismatch was two `$0A`/`$11` PPU-mask-shadow operands, see
`NROM/Excitebike (JU)/README.md`).
The pre-promotion tier holds **857 projects** under `_wip/`, and as of
2026-10-20 all 857 verify **byte-identical for the whole ROM** as well. Row 28
The pre-promotion tier holds **856 projects** under `_wip/`, and as of
2026-10-20 all 856 verify **byte-identical for the whole ROM** as well. Row 28
(`Golf (JU)`) is the only one listed in the table above, because it is the
only one with a real disassembly; the other 856 are Pass 0 skeletons, and the
only one with a real disassembly; the other 855 are Pass 0 skeletons, and the
whole tier — its layout, its quirks and its open work — is documented in
**`WIP.md`**. Folder
*locations* changed on 2026-10-20 (mapper directories, flat project folders),
@@ -674,7 +701,7 @@ but each row's build-status claim in this table is the state at its own
promotion; verify against the tree with `make` if in doubt.
| # | Project | Build Status | Pass 3 |
|---|---------|--------------|--------|
|---| --------- | -------------- | -------- |
| 1 | Balloon Fight (JU) | BYTE-IDENTICAL | complete; symbols applied 2026-10-19 (16 `$13` operands left numeric) |
| 2 | Baseball (UE) | BYTE-IDENTICAL | complete; symbols applied 2026-10-19 (121 operands) |
| 3 | Bomberman (U) | BYTE-IDENTICAL | complete |
@@ -694,28 +721,31 @@ promotion; verify against the tree with `make` if in doubt.
| 17 | Lunar Pool (U) | BYTE-IDENTICAL | complete (tables named); symbols applied 2026-10-19 (45 operands) |
| 18 | Donkey Kong (JU) | BYTE-IDENTICAL | complete (Pass 2/3, promoted 2026-10-19); symbols applied 2026-10-19 (75 operands) |
| 19 | Donkey Kong Jr. Math (U) | BYTE-IDENTICAL | complete (Pass 3 complete); promoted into `NROM/` 2026-10-20 after fixing the mislabeled `SubCF218` call sites |
| 20 | **Duck Hunt (JUE)** | **BYTE-IDENTICAL** | **complete (Pass 3 complete)** |
| 21 | **Ice Climber (JE)** | **BYTE-IDENTICAL** | **complete (Pass 3 complete)** |
| 22 | **Ice Climber (U)** | **BYTE-IDENTICAL** | **complete (Pass 3 complete)** |
| 23 | **Lode Runner (U)** | **BYTE-IDENTICAL** | **complete (Pass 2/3 complete)** |
| 24 | **Pinball (JU)** | **BYTE-IDENTICAL** | **complete (Pass 2/3 complete)** |
| 25 | **Millipede (U)** | **BYTE-IDENTICAL** | **complete (Pass 2/3 complete, 74.6% code)** |
| 26 | **Popeye (JU) (PRG 0)** | **BYTE-IDENTICAL** | **complete (Pass 2/3 complete, 72.3% code)** |
| 27 | **Popeye (JU) (PRG 1)** | **BYTE-IDENTICAL** | **complete (Pass 2/3 complete, 72.3% code); promoted 2026-10-20** |
| 31 | **Pac-Man (Tengen) (U)** | **BYTE-IDENTICAL** | **partial (Pass 2 complete, Pass 3 partial — 30 zero-page aliases, 28 named data tables, 0 residue, 20.0% code); promoted 2026-10-20** |
| 32 | **Pac-Man (U)** | **BYTE-IDENTICAL** | **partial (Pass 2 complete, Pass 3 partial — 119 operands, 0 residue); promoted 2026-10-20** |
| 34 | **Raid on Bungeling Bay (U)** | **BYTE-IDENTICAL** | **partial (Pass 2/3 partial, 64.6% code); promoted 2026-10-20** |
| 33 | **Pyramid (U)** | **BYTE-IDENTICAL** | **partial (Pass 2 complete, Pass 3 partial — 24 zero-page aliases, 32 named data tables, 0 residue, 39.6% code); promoted 2026-10-20** |
| 35 | **Raid on Bungeling Bay (U) [a2]** | **BYTE-IDENTICAL** | **partial (Pass 2 complete, Pass 3 partial — 15 zero-page aliases, 0 residue, 64.3% code); promoted 2026-10-20** |
| 30 | **Mario Bros (JU)** | **BYTE-IDENTICAL** | **partial (Pass 2 complete, Pass 3 partial — 25 zero-page aliases, 35 named data tables, 0 residue, 78.4% code); promoted 2026-10-20** |
| 29 | **Hogan's Alley (JU)** | **BYTE-IDENTICAL** | **partial (Pass 2 complete, Pass 3 partial — 60 semantic zero-page aliases, 34 named data tables, 0 residue, 49.1% code); promoted 2026-10-20** |
| 20 | Duck Hunt (JUE) | BYTE-IDENTICAL | complete (Pass 3 complete) |
| 21 | Ice Climber (JE) | BYTE-IDENTICAL | complete (Pass 3 complete) |
| 22 | Ice Climber (U) | BYTE-IDENTICAL | complete (Pass 3 complete) |
| 23 | Lode Runner (U) | BYTE-IDENTICAL | complete (Pass 2/3 complete) |
| 24 | Pinball (JU) | BYTE-IDENTICAL | complete (Pass 2/3 complete) |
| 25 | Millipede (U) | BYTE-IDENTICAL | complete (Pass 2/3 complete, 74.6% code) |
| 26 | Popeye (JU) (PRG 0) | BYTE-IDENTICAL | complete (Pass 2/3 complete, 72.3% code) |
| 27 | Popeye (JU) (PRG 1) | BYTE-IDENTICAL | complete (Pass 2/3 complete, 72.3% code); promoted 2026-10-20 |
| 31 | Pac-Man (Tengen) (U) | BYTE-IDENTICAL | partial (Pass 2 complete, Pass 3 partial — 30 zero-page aliases, 28 named data tables, 0 residue, 20.0% code); promoted 2026-10-20 |
| 32 | Pac-Man (U) | BYTE-IDENTICAL | partial (Pass 2 complete, Pass 3 partial — 119 operands, 0 residue); promoted 2026-10-20 |
| 34 | Raid on Bungeling Bay (U) | BYTE-IDENTICAL | partial (Pass 2/3 partial, 64.6% code); promoted 2026-10-20 |
| 33 | Pyramid (U) | BYTE-IDENTICAL | partial (Pass 2 complete, Pass 3 partial — 24 zero-page aliases, 32 named data tables, 0 residue, 39.6% code); promoted 2026-10-20 |
| 35 | Raid on Bungeling Bay (U) [a2] | BYTE-IDENTICAL | partial (Pass 2 complete, Pass 3 partial — 15 zero-page aliases, 0 residue, 64.3% code); promoted 2026-10-20 |
| 30 | Mario Bros (JU) | BYTE-IDENTICAL | partial (Pass 2 complete, Pass 3 partial — 25 zero-page aliases, 35 named data tables, 0 residue, 78.4% code); promoted 2026-10-20 |
| 29 | Hogan's Alley (JU) | BYTE-IDENTICAL | partial (Pass 2 complete, Pass 3 partial — 60 semantic zero-page aliases, 34 named data tables, 0 residue, 49.1% code); promoted 2026-10-20 |
| 36 | Urban Champion (JU) | BYTE-IDENTICAL | complete; symbols applied 2026-10-19 (70 operands) |
| 37 | Xevious (U) | BYTE-IDENTICAL | complete (Pass 3 complete, 34.5% code; 143 semantic entry points, 4 named data tables, ~20 semantic ZP aliases) |
| 38 | Zanac (U) | BYTE-IDENTICAL | complete (Pass 3 complete, 34.5% code; 133 semantic entry points, 26 named data tables, 14 semantic ZP aliases) |
| 39 | Mermaids of Atlantis (U) | mapper 8 | 64 KB | — | Vertical | BYTE-IDENTICAL (Pass 2/3 complete) | $8189 / $FF00 / $8036 |
Row 28 (`Golf (JU)`, still in `_wip/`) rebuilds cleanly at the whole-ROM
level as of 2026-10-20. It has Pass 1 done and is at substantial Pass 2.
Promotion into the numbered inventory, CDL-backed reclassification of the remaining
data, and a real power-on flow `README.md` per project are the open work for it;
the other 38 `_wip/` projects are Pass 0 skeletons and need Pass 1 from scratch.
the other 35 `_wip/` projects are Pass 0 skeletons and need Pass 1 from scratch.
See **`WIP.md`**.
Use `_tools/verify_pass1.py` to re-check any of this at any time; it rebuilds each
+4 -4
View File
@@ -29,7 +29,7 @@ A build that assembles but does not print that message is a failure. Requires
Two tiers exist, and the difference is real:
- **Top level — promoted projects under their mapper dir (`NROM/` etc.) — `make` compares the whole ROM against `rom.nes` in the project folder.
- **`_wip/<MAPPER>/` (857 projects)** — as of 2026-10-20 these also compare the
- **`_wip/<MAPPER>/` (856 projects)** — as of 2026-10-20 these also compare the
whole ROM against a `rom.nes` copy in the project folder, so the header and
CHR **are** proven. The tier was moved off the old
`cmp reconstructed_prg.bin prg.bin` form; promotion is now `git mv` plus the
@@ -43,7 +43,7 @@ Two tiers exist, and the difference is real:
- 35 promoted projects under `NROM/`, all whole-ROM byte-identical (Lunar Pool promoted 2026-10-18,
Donkey Kong (JU) promoted 2026-10-19 after Pass 3, **Donkey Kong Jr. Math (U) promoted 2026-10-19 after Pass 3 — re-promoted into `NROM/` 2026-10-20** after the 2026-10-20 mapper-folder reorganization initially parked it in `_wip/NROM/` over a `jsr $F218`-mislabeled-as-`SubCF218_Block` mismatch; the fix repointed four `prg.s` call sites to the true `SubCF218` entry, see `NROM/Donkey Kong Jr. Math (U)/README.md`), **Duck Hunt (JUE) promoted 2026-10-19 after Pass 3**, **Ice Climber (JE) and (U) promoted 2026-10-20 after Pass 3**, **Lode Runner (U) promoted 2026-10-20 after Pass 2/3**, **Pinball (JU) promoted 2026-10-20 after Pass 2/3**, **Popeye (JU) (PRG 1) promoted 2026-10-20 after Pass 2/3** (`header.s`/`chr.s` + HEADER `linker.cfg` added, whole-ROM `cmp` passes on the first promoted build; SHA-256 `00160651…78bd8b4`; see `NROM/Popeye (JU) (PRG 1)/README.md`), **`Excitebike (JU)` promoted 2026-10-20** — the byte-596 mismatch was two `PpuMaskShadow` (`$0A`) operands where the ROM uses `$11` (NMI's second mask shadow, aliased as `NmiMaskShadow` in `locals.inc`); the 4,401 damaged audit comments (doubled `??` forms plus 6,339 comments shifted against their mnemonics) were re-anchored from the ca65 listing via the new `_tools/repair_audit_comments.py`, and all 58 raw `jsr/jmp $XXXX` operands were substituted with routine labels/equates. See `NROM/Excitebike (JU)/README.md`. **`Raid on Bungeling Bay (U)` promoted 2026-10-20** — `header.s`/`chr.s` + HEADER/PRG/CHR `linker.cfg` added, whole-ROM `cmp` passes on the first promoted build (MD5 `77285503…885000ac`); one leftover neutral indirect operand `jmp (Zp01)` at $E2EC became `jmp (IndDispatch01)` (alias already present in `locals.inc`); `apply_symbols.py` reports 0 substitutions pending. **`Pac-Man (U)` promoted 2026-10-20** — Pass 2 completed first (all 194 `Label_XXXX` definitions renamed from a fresh map derived from the committed split, not from a drafted map; all 49 `jsr`/`jmp` call sites resolved; zero `Label_` and zero raw `$XXXX` call operands left), then Pass 3: **119 operands substituted** (101 hardware + 11 single-name + 7 multi-alias resolved per site through a new `sites.tsv`), `apply_symbols.py` now reports **0 residue**. The 7 site resolutions are all proven from context, not guessed — four `jmp ($0010)` immediately preceded by `sta DispatchPtrLo`/`sta DispatchPtrHi`, one `jmp ($00FE)` preceded by `sta AudioHandlerPtrLo`/`sta AudioHandlerPtrHi`, and two `sta a:$0000,y` zero-page clears that take the neutral `Zp00`. `header.s`/`chr.s` + HEADER/PRG/CHR `linker.cfg` added, whole-ROM `cmp` passes on the first promoted build (MD5 `a69d310f8cae9397fbd39f204672b5c7`); see `NROM/Pac-Man (U)/README.md`. **`Pac-Man (Tengen) (U)` promoted 2026-10-20** — a *different build* of the same game as the row-32 dump: the PRGs differ in 56 bytes in 8 runs, all of them code-versus-licensee-text ($C3E3-$C408 is 26 spaces here against `LICENSED BY NAMCO AMERICA INC` there; $FF00-$FF16 is `$FF` padding here against the boot code there), and the RESET vector follows ($C033 against $FF00) — the same boot sequence, inline. Disassembled **from scratch**: the map was derived from this dump's own committed split, with no name, map or file carried over from the row-32 dump. Pass 2 named all 194 `Label_XXXX` definitions and resolved all 48 raw `$XXXX` call operands (map in `routinemap.tsv`); Pass 3 added 30 semantic zero-page aliases applied only at the proven sites (`sites.tsv`) and named 28 data tables, including `CharacterDataTable` ($C66A) / `CharacterNameStrings` ($C67E), where the ROM itself names Blinky, Pinky, Inky and Clyde. **A Pass 1 correction came with it:** six command handlers were recovered — `ScriptCommandTable` ($EFDD) is read by the traced instruction at $EFCC and six of its entries point at $F00A, $F022, $F03A, $F052, $F062 and $F072, all of which the tracer had left as data, two of them mis-split across the `jmp $EF61` at $F01F and $F04F. Those 120 bytes are code here. **The same gap exists in the promoted row-32 dump, which has not been corrected.** `header.s`/`chr.s` + HEADER/PRG/CHR `linker.cfg` added, whole-ROM `cmp` passes on the first promoted build (MD5 `d34e7a74…28ad0`); see `NROM/Pac-Man (Tengen) (U)/README.md`. ****`Pyramid (U)` (Sachen) promoted 2026-10-20** — an unlicensed Sachen release with a mapper-0 header whose boot code pokes a mapper unlock at `$4100` and checks the RAM bytes `$0120`/`$0121` against "A"/"V". **A Pass 1 correction came with it:** the committed split was a strict subset of the correct one — **828 bytes** of code were still marked as data, because the tracer cannot follow a `jmp` that sits inside a data region, and this game dispatches through four such tables ($C01E, $C02A, $C042, $C054) plus ten more at $C000-$C01B. Re-tracing with those sixteen targets, the `$C800` boot mainline and six further code starts seeded by hand recovers them (and a five-byte stub at $DF89 in a hole between two routinLine truncated
**`Hogan's Alley (JU)` promoted 2026-10-20** — a light-gun game whose engine dispatches through **inline** tables: `IndirectCall` at $C34D pops the return address of the `jsr` that called it and reads a 16-bit handler pointer from the word that follows, so all six handler tables ($C124 19 entries, $C219 4, $C89C 14, $CDD1 1, $D234 2, $D3D6 14) live *inside* the code stream and the static tracer cannot follow them. **A Pass 1 correction came with it:** the committed split was a strict subset of the correct one — a merged Mesen Code Data Logger capture (five captures OR-ed, 6,544 code bytes) showed **1,216 bytes** that the tracer had left as data were code, taking the split from 41.8% to 49.1%; five bytes moved the other way. The four branch targets the reclassifier could not prove were turned into labels by the new `_tools/resolve_raw_branches.py`. Pass 2 named 206 routine entries and derived 413 internal branch targets from this dump's own code (630 `Label_XXXX` gone, 484 raw `$XXXX` call operands resolved, 15 unlabelled call targets given a label); Pass 3 added 60 semantic zero-page aliases, applied only where the role is proven, and named all 34 data tables. `apply_symbols.py` reports 1 residue (`sta a:$00B4,y` at $C203 — the same address as `Zp40`/`ActorPalette` but forced to absolute addressing, so it must stay numeric). `header.s`/`chr.s` + HEADER/PRG/CHR `linker.cfg` added, whole-ROM `cmp` passes on the first promoted build; see `NROM/Hogan's Alley (JU)/README.md`.
- 857 projects under `_wip/` (38 in `_wip/NROM/`, 221 in `_wip/MMC1/`, 239 in
- 856 projects under `_wip/` (38 in `_wip/NROM/`, 221 in `_wip/MMC1/`, 239 in
`_wip/MMC3/`, 98 in `_wip/UNROM/`, 58 in `_wip/CNROM/`, 10 in `_wip/MMC5/`
and 193 across 24 more mapper folders): all whole-ROM byte-identical.
**856 of them are Pass 0 skeletons** — the folder shape and the build are
@@ -345,7 +345,7 @@ Rebuild stays byte-identical.
**All 30 top-level projects have their operand naming in place (2026-10-19/20).** See the Current state section above for the per-project breakdown. Excitebike (JU)'s `apply_symbols.py` run was skipped due to inline `prg.s` definitions conflicting with `locals.inc` values — its 58 raw `jsr/jmp $XXXX` operands were substituted by hand on 2026-10-20 instead (routine labels + `locals.inc` sub-entry equates); its zero-page operands remain numeric as documented Pass 3 residue.
The `_wip` tier is still open, but the shape of the work changed on
2026-10-20: 856 of its 857 projects are **Pass 0 skeletons** with no
2026-10-20: 856 of its 856 projects are **Pass 0 skeletons** with no
disassembly at all, so they owe Pass 1 from scratch rather than a label
cleanup. Only `Golf (JU)` carries a real disassembly, and it holds the
address-based
@@ -602,7 +602,7 @@ These cost real time this session. All are recorded so they don't cost it twice.
- Root `README.md` (the old root `OVERVIEW.md`) — inventory of the 35 promoted projects, mapper-folder layout, per-project detail, the Pass 1
methodology note, and the audit-comment TODO with its full analysis.
- **`WIP.md`** — the pre-promotion tier: the 857 `_wip/` projects, their layout,
- **`WIP.md`** — the pre-promotion tier: the 856 `_wip/` projects, their layout,
the two linker layouts (CPU address vs .nes file offset), the banked-mapper
/ no-CHR / trailing-bytes / odd-header cases, the open Pass 1/2/3 work, the
promotion procedure and the skeleton tooling.
+25
View File
@@ -0,0 +1,25 @@
CA65 ?= ca65
LD65 ?= ld65
all: reconstructed.nes verify
header.o: header.s header.bin
$(CA65) -g -o $@ $<
prg0.o: prg.s symbols.inc locals.inc
$(CA65) -g -o $@ $<
prg07.o: prg.07.s symbols.inc locals.inc
$(CA65) -g -o $@ $<
reconstructed.nes: header.o prg0.o prg07.o linker.cfg
$(LD65) -C linker.cfg -m reconstructed.map -Ln reconstructed.lbl -o $@ header.o prg0.o prg07.o
verify: reconstructed.nes rom.nes
cmp reconstructed.nes rom.nes
@echo "Byte-identical ROM verified."
clean:
rm -f *.o reconstructed.nes reconstructed_prg.bin reconstructed.map reconstructed.lbl prg.07.bin prg.07.cfg
.PHONY: all verify clean
+107
View File
@@ -0,0 +1,107 @@
# Zanac (U)
## Status
**Pass 3 complete.** All address-derived `Label_XXXX` names have been replaced
with semantic entry-point names (133 routines) plus address-based names for
remaining branch targets (~212 `Sub_XXXX`/`Next_XXXX`/`Skip_XXXX`/`Exit_XXXX`).
All raw `$XXXX` jsr/jmp operands replaced with label references. Zero-page
aliases renamed to semantic names (14 named). Data tables named (26 tables).
The project builds and verifies byte-identical to the original ROM.
`make` assembles `header.s`, `prg.s`, `prg.07.s`, links them with `ld65` and compares the
result against `rom.nes`:
```
Byte-identical ROM verified.
```
### Pass 1 results
| Metric | Value |
|--------|-------|
| PRG size | 131072 bytes (128 KB) at file offset $0010 |
| Code | 6206 bytes (37.9% of bank 7) |
| Instructions | 2977 |
| Bank 7 routines | 391 labels traced |
| Banks as data | Banks 0-6 (switchable $8000-$BFFF) |
### Pass 2 results
| Metric | Value |
|--------|-------|
| Semantic entry-point names | 133 (Reset, NmiHandler, InputRead, ObjInitCall, ObjMoveCall, ObjDrawCall, ObjUpdateCall, SetOamPtrs, WaitVblank, GameModeDispatch, etc.) |
| Internal branch labels | ~212 (`Sub_XXXX`/`Next_XXXX`/`Skip_XXXX`/`Exit_XXXX`) |
| Raw `$XXXX` jsr/jmp operands | 0 (all replaced with label references) |
| Raw `$XXXX` branch operands | 0 (all replaced with label references) |
| Remaining `Label_XXXX` | 0 (all replaced) |
### Pass 3 results
| Metric | Value |
|--------|-------|
| Semantic zero-page aliases | 14 (Reset, NmiHandler, InputRead, ObjInitCall, ObjMoveCall, ObjDrawCall, ObjUpdateCall, SetOamPtrs, WaitVblank, GameModeDispatch, etc.) |
| Named data tables | 26 (JumpTable, IndexTable, SpriteTable, TextTable, etc.) |
| Raw `$XXXX` jsr/jmp operands | 0 |
| Raw `$XXXX` branch operands | 0 |
| Remaining `Label_XXXX` | 0 |
### Pass 1 notes
- Bank 7 (last 16 KB, fixed at CPU $C000-$FFFF) was traced from vectors:
NMI=$CE8D, RESET=$E7BF, IRQ=$CEC4. Bank 7 code is assembled separately
as `prg.07.s` with `.org $C000` and linked at file offset $1C010.
- Banks 0-6 (switchable at $8000-$BFFF) are emitted as raw `.byte` data;
bank-switch analysis is needed to trace code in those banks
- Seven invalid opcode addresses found: $D506, $D876, $E15B, $E44B, $E520,
$E909, $F0FE (likely data mis-decoded as opcodes or vice versa)
## ROM
| Property | Value |
|----------|-------|
| Format | iNES |
| Mapper | 2 |
| Board | UNROM |
| Mirroring | Horizontal |
| Four-screen VRAM | no |
| Battery | no |
| PRG | 128 KB (8 x 16 KB), at file offset $0010 |
| CHR | none |
| Trainer | none |
| Footer | none |
| NMI vector | $CE8D |
| RESET vector | $E7BF |
| IRQ vector | $CEC4 |
| ROM file | `Zanac (U).nes` |
| SHA-256 | `7e75a19b9e11715c0eb19a2017a322df02f5cf4f7b30acef0fa7a0615236bda4` |
### Header notes
- none
## Open work
- **Pass 1** - complete. Bank 7 traced (37.9% code); banks 0-6 as raw data.
Build verifies byte-identical.
- **Pass 2** - complete. All 133 entry points have semantic names;
~212 internal branch labels remain as address-based names;
All raw `$XXXX` jsr/jmp/branch operands replaced with label references.
- **Pass 3** - complete. Semantic zero-page aliases applied (14 named).
26 data tables named (JumpTable, IndexTable, SpriteTable, TextTable, etc.).
- **Promotion** to `NROM/<name>/` once ready, as `git mv`.
## Files
| File | Purpose |
|------|---------|
| `prg.s` | Pass 3 disassembly (banks 0-6 as raw `.byte` data) |
| `prg.07.s` | Pass 3 disassembly for bank 7 (fixed at CPU $C000-$FFFF) |
| `header.s` | iNES header include |
| `prg.bin` | 131072 bytes (128 KB) PRG image |
| `rom.nes` | byte-identical copy of the original ROM |
| `linker.cfg` | HEADER / PRG / PRG7 memory areas |
| `prg.07.cfg` | Linker config for assembling prg.07.bin |
| `symbols.inc` | NES hardware register names |
| `locals.inc` | zero-page aliases (14 semantic names applied) |
| `Makefile` | build and byte-identity check |
File renamed without changes.
File renamed without changes.
+2
View File
@@ -0,0 +1,2 @@
.segment "HEADER"
.incbin "header.bin"
+10
View File
@@ -0,0 +1,10 @@
MEMORY {
HEADER: start = $0000, size = $0010, fill = yes;
PRG: start = $0010, size = $1C000, fill = yes;
PRG7: start = $1C010, size = $4000, fill = yes;
}
SEGMENTS {
HEADER: load = HEADER, type = ro;
PRG: load = PRG, type = ro;
PRG7: load = PRG7, type = ro;
}
+136
View File
@@ -0,0 +1,136 @@
; Zanac (U) application-specific RAM aliases - Pass 1
; Generated from every direct zero-page operand in reachable code:
; ref counts are reads/writes, `where` lists the referencing addresses.
; ZpXX names indicate storage with a role not yet unique enough for a behavioral name;
; Pass 2 replaces them with names derived from observed usage.
VramPtrLo = $00 ; 25 refs; reads=12 writes=13; used at $C772, C780, C789, C799, +17 more
VramPtrHi = $01 ; 12 refs; reads=5 writes=7; used at $C77A, C784, C78D, C7B3, +5 more
Zp02 = $02 ; 3 refs; reads=2 writes=1; used at $C76B, C774, C791
Zp06 = $06 ; 1 refs; reads=1 writes=0; used at $E907
Zp08 = $08 ; 1 refs; reads=1 writes=0; used at $D454
Zp0F = $0F ; 7 refs; reads=4 writes=3; used at $C815, C819, C868, C875, +3 more
PlayerPtrLo = $10 ; 40 refs; reads=21 writes=19; used at $C700, C716, CAB2, CABB, +26 more
PlayerPtrHi = $11 ; 17 refs; reads=7 writes=10; used at $C702, C70F, D349, D352, +10 more
Zp12 = $12 ; 14 refs; reads=7 writes=7; used at $CD9B, CDC1, CE0D, CE2B, +6 more
Zp13 = $13 ; 6 refs; reads=4 writes=2; used at $CD9D, CDBE, CE3E, CE54, +2 more
Zp14 = $14 ; 17 refs; reads=9 writes=8; used at $C8E1, C8F7, C90B, C90F, +10 more
Zp15 = $15 ; 11 refs; reads=5 writes=6; used at $C8DF, C8EA, C908, D4FD, +6 more
ObjPtrLo = $16 ; 20 refs; reads=13 writes=7; used at $C6D6, C6DB, C6EC, C708, +16 more
ObjPtrHi = $17 ; 11 refs; reads=5 writes=6; used at $C6D3, C6DE, C71E, C722, +7 more
EnemyPtrLo = $18 ; 39 refs; reads=20 writes=19; used at $C918, CA9F, CB4F, CB6D, +34 more
EnemyPtrHi = $19 ; 35 refs; reads=12 writes=23; used at $C91C, CB4D, CB69, CB78, +27 more
Zp1A = $1A ; 3 refs; reads=2 writes=1; used at $DD26, DD60, DD94
Zp1C = $1C ; 6 refs; reads=5 writes=1; used at $EB7D, EB8A, EBAC, ED5D, +2 more
Zp1D = $1D ; 2 refs; reads=1 writes=1; used at $EB82, ED8C
Zp1E = $1E ; 16 refs; reads=12 writes=4; used at $EE0D, EE1B, EE23, EE71, +12 more
Zp1F = $1F ; 3 refs; reads=1 writes=2; used at $EE12, EFB3, EFBB
GameMode = $20 ; 11 refs; reads=6 writes=5; used at $C7FD, C803, C812, C8D8, +6 more
Zp21 = $21 ; 8 refs; reads=6 writes=2; used at $C7DA, C7FA, C80A, C80C, +4 more
Zp24 = $24 ; 2 refs; reads=1 writes=1; used at $C7FF, C80E
Zp25 = $25 ; 3 refs; reads=1 writes=2; used at $C7F8, C807, CE48
Zp26 = $26 ; 2 refs; reads=1 writes=1; used at $C902, CD6E
Zp27 = $27 ; 2 refs; reads=1 writes=1; used at $CE14, CE21
Zp28 = $28 ; 3 refs; reads=1 writes=2; used at $CE1F, CE27
Zp29 = $29 ; 3 refs; reads=2 writes=1; used at $CDAA, CDB6, CE76
Zp2A = $2A ; 2 refs; reads=1 writes=1; used at $CDC6, CE7B
Zp2B = $2B ; 17 refs; reads=10 writes=7; used at $C8D4, C8FA, C922, CD73, +13 more
Zp2C = $2C ; 13 refs; reads=9 writes=4; used at $C911, CDA7, CDB4, CDD4, +9 more
Zp2D = $2D ; 6 refs; reads=2 writes=4; used at $C916, CDDA, CE6C, CE8A
Zp2E = $2E ; 4 refs; reads=2 writes=2; used at $C91A, CE4F, CE5C, CE5E
Zp2F = $2F ; 4 refs; reads=2 writes=2; used at $C91E, CE4A, CE62
Zp30 = $30 ; 24 refs; reads=16 writes=8; used at $CB8E, CBD8, D0A4, D0A8, +20 more
Zp31 = $31 ; 3 refs; reads=1 writes=2; used at $CC59, E967, E96B
Zp32 = $32 ; 3 refs; reads=1 writes=2; used at $CB8A, D0AC, D40C
Zp33 = $33 ; 1 refs; reads=0 writes=1; used at $CB90
Zp39 = $39 ; 5 refs; reads=3 writes=2; used at $CBAF, D2C8, D2CC, D2E1
FrameCounter = $41 ; 5 refs; reads=3 writes=2; used at $CCE8, CCED, CCF3, CE9C
Zp45 = $45 ; 1 refs; reads=0 writes=1; used at $CBBD
Zp46 = $46 ; 3 refs; reads=1 writes=2; used at $CB94, D46A, D49C
Zp47 = $47 ; 7 refs; reads=4 writes=3; used at $CB96, D5C8, D5CC, D5E0, +1 more
Zp48 = $48 ; 3 refs; reads=1 writes=2; used at $CB98, D5C1, D5CE
Zp49 = $49 ; 2 refs; reads=1 writes=1; used at $CB92, D5FE
Zp4A = $4A ; 1 refs; reads=0 writes=1; used at $CBA0
Zp4B = $4B ; 4 refs; reads=2 writes=2; used at $CB9A, D5DD, E8CD, E8D6
Zp4C = $4C ; 4 refs; reads=2 writes=2; used at $D5D0, D5D4
Zp4D = $4D ; 6 refs; reads=3 writes=3; used at $CB9E, D47D, D4B2, D4B4
Zp4E = $4E ; 3 refs; reads=2 writes=1; used at $D4DA, D5F3, D60D
Zp4F = $4F ; 2 refs; reads=1 writes=1; used at $D4D6, D60F
Zp50 = $50 ; 6 refs; reads=3 writes=3; used at $D4CA, D4DC, D5F5, D5F9, +2 more
Zp51 = $51 ; 3 refs; reads=0 writes=3; used at $CBC8, CBEE, D446
Zp52 = $52 ; 4 refs; reads=1 writes=3; used at $D4AA, D4B0, D61C
Zp53 = $53 ; 2 refs; reads=1 writes=1; used at $D4AE, D61A
Zp54 = $54 ; 1 refs; reads=0 writes=1; used at $CBA4
Zp55 = $55 ; 1 refs; reads=0 writes=1; used at $CBB1
Zp56 = $56 ; 1 refs; reads=0 writes=1; used at $CBA2
Zp5A = $5A ; 1 refs; reads=0 writes=1; used at $CB9C
Zp5D = $5D ; 1 refs; reads=0 writes=1; used at $CBB5
Zp62 = $62 ; 8 refs; reads=5 writes=3; used at $CBC4, D487, D4BD, D56D, +4 more
Zp66 = $66 ; 3 refs; reads=0 writes=3; used at $D0C7, E073, E83C
Zp6C = $6C ; 5 refs; reads=4 writes=1; used at $D4FA, D59A, D5A0, D5B4, +1 more
Zp6D = $6D ; 2 refs; reads=1 writes=1; used at $D5B8, D5BC
Zp6E = $6E ; 3 refs; reads=2 writes=1; used at $D4EA, D4EE
Zp6F = $6F ; 10 refs; reads=4 writes=6; used at $D0E1, E07E, E0D4, E0E8, +5 more
Zp70 = $70 ; 11 refs; reads=7 writes=4; used at $E0D8, E0ED, E0F4, E119, +5 more
Zp71 = $71 ; 3 refs; reads=2 writes=1; used at $E653, E659
Zp72 = $72 ; 2 refs; reads=1 writes=1; used at $E4E9, E629
Zp73 = $73 ; 2 refs; reads=1 writes=1; used at $E4EB, E63A
Zp74 = $74 ; 3 refs; reads=1 writes=2; used at $E4EF, E657
Zp75 = $75 ; 1 refs; reads=0 writes=1; used at $E4F3
Zp77 = $77 ; 1 refs; reads=0 writes=1; used at $CBB9
Zp7A = $7A ; 4 refs; reads=2 writes=2; used at $D3C7, D3C9, D3CD
Zp7D = $7D ; 10 refs; reads=5 writes=5; used at $CC39, CC52, D414, D42D, +6 more
Zp7E = $7E ; 4 refs; reads=2 writes=2; used at $CAB4, CABD, CAC3, CACA
PpuStatusShadow = $7F ; 1 refs; reads=0 writes=1; used at $CEA1
Zp83 = $83 ; 4 refs; reads=2 writes=2; used at $D3B2, D3F1, D3FA
GameState = $90 ; 10 refs; reads=5 writes=5; used at $CEC5, D4DE, D69F, D6A3, +6 more
Zp91 = $91 ; 7 refs; reads=4 writes=3; used at $CBE2, CC54, CC6A, CC7A, +3 more
Zp92 = $92 ; 3 refs; reads=1 writes=2; used at $D41F, D436, E98C
Zp98 = $98 ; 7 refs; reads=4 writes=3; used at $C6AD, C6B9, D6C0, D6C6, +3 more
Zp99 = $99 ; 4 refs; reads=2 writes=2; used at $C6AF, C6C2, D6CF, D6D3
Zp9A = $9A ; 2 refs; reads=1 writes=1; used at $C6B1, C6B5
Zp9B = $9B ; 2 refs; reads=1 writes=1; used at $C6B3, C6C5
ObjCount = $9C ; 12 refs; reads=6 writes=6; used at $C7E4, C8D6, CD7E, CECC, +7 more
Zp9D = $9D ; 4 refs; reads=3 writes=1; used at $CEE5, D7AC, DB5C, DD8F
Zp9E = $9E ; 2 refs; reads=1 writes=1; used at $CEE0, D7B0
Zp9F = $9F ; 4 refs; reads=3 writes=1; used at $CF1C, CF30, D7B5, DD67
ZpA0 = $A0 ; 7 refs; reads=5 writes=2; used at $CED9, CF17, CF2B, D7BA, +3 more
ZpA1 = $A1 ; 9 refs; reads=6 writes=3; used at $D6FE, D770, D7A5, DB50, +4 more
ZpA2 = $A2 ; 7 refs; reads=4 writes=3; used at $CAC8, D4E4, D6F0, D737, +2 more
ZpA3 = $A3 ; 5 refs; reads=2 writes=3; used at $D6F2, D73D, D83B, D855
ZpA4 = $A4 ; 5 refs; reads=2 writes=3; used at $D6FA, D824, D829, D832, +1 more
ZpA8 = $A8 ; 3 refs; reads=2 writes=1; used at $D6F4, DA36, DA39
ZpA9 = $A9 ; 2 refs; reads=1 writes=1; used at $D6AF, D6B4
ZpAA = $AA ; 10 refs; reads=5 writes=5; used at $D6B2, D6E1, D753, D75B, +6 more
ZpAB = $AB ; 11 refs; reads=6 writes=5; used at $D6BC, D6E3, D756, D75F, +7 more
ZpAC = $AC ; 4 refs; reads=1 writes=3; used at $D45C, D741, D802, E929
ZpAD = $AD ; 4 refs; reads=1 writes=3; used at $D460, D745, D7F8, E925
ZpAE = $AE ; 4 refs; reads=3 writes=1; used at $D6BE, D6C3, D827, DD7B
ZpAF = $AF ; 4 refs; reads=2 writes=2; used at $DD41, DD51, DD59
ZpB0 = $B0 ; 1 refs; reads=1 writes=0; used at $DD53
ZpB2 = $B2 ; 6 refs; reads=2 writes=4; used at $D6E9, D6F6, DA4E, DA56, +1 more
ZpB3 = $B3 ; 3 refs; reads=2 writes=1; used at $D71E, D732, D851
ZpB4 = $B4 ; 3 refs; reads=2 writes=1; used at $D723, D739, D857
ZpB5 = $B5 ; 4 refs; reads=2 writes=2; used at $D72A, D85F, D861, D86C
ZpB6 = $B6 ; 3 refs; reads=1 writes=2; used at $D730, D863, D867
ZpB7 = $B7 ; 5 refs; reads=3 writes=2; used at $D702, D776, D840, DBB6, +1 more
ZpB8 = $B8 ; 2 refs; reads=1 writes=1; used at $CC90, DA3C
ZpB9 = $B9 ; 2 refs; reads=1 writes=1; used at $CC95, DA40
ZpBA = $BA ; 2 refs; reads=1 writes=1; used at $CC9D, DB20
ZpBB = $BB ; 2 refs; reads=1 writes=1; used at $CCA2, DB24
ZpC0 = $C0 ; 7 refs; reads=5 writes=2; used at $CBB3, D448, D496, D7EA, +3 more
ZpC2 = $C2 ; 1 refs; reads=0 writes=1; used at $D452
ZpCD = $CD ; 4 refs; reads=2 writes=2; used at $CBF7, CBF9, CBFD
ZpCE = $CE ; 4 refs; reads=1 writes=3; used at $CBE6, E077, E0A4
ZpD0 = $D0 ; 1 refs; reads=0 writes=1; used at $CBEA
ZpD2 = $D2 ; 1 refs; reads=0 writes=1; used at $CBF5
ZpD8 = $D8 ; 1 refs; reads=0 writes=1; used at $D874
ZpF5 = $F5 ; 10 refs; reads=8 writes=2; used at $CB1A, CB2F, CB3A, D0FF, +5 more
ZpF6 = $F6 ; 2 refs; reads=1 writes=1; used at $CB23
ZpF7 = $F7 ; 10 refs; reads=9 writes=1; used at $CB2D, CB33, CB36, CB38, +6 more
ZpF8 = $F8 ; 4 refs; reads=4 writes=0; used at $CB5A, CC42, E015, E43E
ZpFB = $FB ; 7 refs; reads=5 writes=2; used at $E769, E76C, E770, E77F, +3 more
ZpFC = $FC ; 2 refs; reads=1 writes=1; used at $C6BB, C7AD
ZpFD = $FD ; 2 refs; reads=1 writes=1; used at $C6B7, C7A8
NmiFlag = $FE ; 10 refs; reads=6 writes=4; used at $C8BF, CAD3, CADA, CADD, +6 more
ZpFF = $FF ; 13 refs; reads=10 writes=3; used at $C6BD, C6C7, C7A3, C8C5, +9 more
File diff suppressed because it is too large. Load diff
File renamed without changes.
File diff suppressed because it is too large. Load diff
File renamed without changes.
+108
View File
@@ -0,0 +1,108 @@
; =============================================================================
; Nintendo Entertainment System hardware symbols
; =============================================================================
; -----------------------------------------------------------------------------
; PPU registers
; -----------------------------------------------------------------------------
PPUCTRL = $2000
PPUMASK = $2001
PPUSTATUS = $2002
OAMADDR = $2003
OAMDATA = $2004
PPUSCROLL = $2005
PPUADDR = $2006
PPUDATA = $2007
OAMDMA = $4014
; -----------------------------------------------------------------------------
; Controller ports
;
; $4016:
; Write: controller strobe
; Read: controller port 1
;
; $4017:
; Read: controller port 2
; Write: APU frame counter
; -----------------------------------------------------------------------------
JOY1 = $4016
JOY2 = $4017
; -----------------------------------------------------------------------------
; APU pulse channel 1
; -----------------------------------------------------------------------------
APUPULSE1CTRL = $4000
APUPULSE1SWEEP = $4001
APUPULSE1TIMERLO = $4002
APUPULSE1TIMERHI = $4003
; -----------------------------------------------------------------------------
; APU pulse channel 2
; -----------------------------------------------------------------------------
APUPULSE2CTRL = $4004
APUPULSE2SWEEP = $4005
APUPULSE2TIMERLO = $4006
APUPULSE2TIMERHI = $4007
; -----------------------------------------------------------------------------
; APU triangle channel
; -----------------------------------------------------------------------------
APUTRIANGLECTRL = $4008
APUTRIANGLETIMERLO = $400A
APUTRIANGLETIMERHI = $400B
; -----------------------------------------------------------------------------
; APU noise channel
; -----------------------------------------------------------------------------
APUNOISECTRL = $400C
APUNOISEPERIOD = $400E
APUNOISELENGTH = $400F
; -----------------------------------------------------------------------------
; APU DMC channel
; -----------------------------------------------------------------------------
APUDMCCTRL = $4010
APUDMCDIRECT = $4011
APUDMCADDR = $4012
APUDMCLENGTH = $4013
; -----------------------------------------------------------------------------
; APU status and frame counter
;
; $4015:
; Write: enable or disable the five APU channels
; Read: channel and interrupt status
;
; $4017:
; Write: APU frame-counter mode and IRQ inhibit
; Read: controller port 2
; -----------------------------------------------------------------------------
APUSTATUS = $4015
APUFRAMECOUNTER = $4017
; -----------------------------------------------------------------------------
; Controller masks
; -----------------------------------------------------------------------------
PAD_RIGHT = $01
PAD_LEFT = $02
PAD_DOWN = $04
PAD_UP = $08
PAD_START = $10
PAD_SELECT = $20
PAD_B = $40
PAD_A = $80
PAD_HORIZONTAL = PAD_LEFT | PAD_RIGHT
PAD_VERTICAL = PAD_UP | PAD_DOWN
PAD_DPAD = PAD_HORIZONTAL | PAD_VERTICAL
+6 -10
View File
@@ -1,6 +1,6 @@
# `_wip/` — the pre-promotion tier
**857 projects across 30 mapper folders, every one of them building
**856 projects across 30 mapper folders**, every one of them building
byte-identical to its original ROM.**
This file is the handoff for everything under `_wip/<MAPPER>/<Project>/`. The
@@ -18,7 +18,7 @@ project, under a folder named for the project's mapper:
_wip/
NROM/ 38 projects (mapper 0, plus one whose header byte 7 is ASCII)
MMC1/ 221 projects (mapper 1)
UNROM/ 98 projects (mapper 2)
UNROM/ 97 projects (mapper 2)
CNROM/ 58 projects (mapper 3)
MMC3/ 239 projects (mapper 4)
MMC5/ 10 projects (mapper 5)
@@ -199,7 +199,7 @@ disassembly work starts.
## 6. Inventory
All 857 projects, all **byte-identical for the whole ROM**.
All 856 projects, all **byte-identical for the whole ROM**.
### `_wip/CNROM/` — mapper 3 (58 projects)
| Project | PRG | CHR | Mirroring | Vectors (NMI / RESET / IRQ) | State | Notes |
@@ -561,8 +561,6 @@ All 857 projects, all **byte-identical for the whole ROM**.
| Project | PRG | CHR | Mirroring | Vectors (NMI / RESET / IRQ) | State | Notes |
|---------|-----|-----|-----------|------------------------------|-------|-------|
| Mermaids of Atlantis (U) | 64 KB | 64 KB | Vertical | $8189 / $FF00 / $8036 | Pass 0 skeleton | |
### `_wip/MAPPER9/` — mapper 9 (2 projects)
| Project | PRG | CHR | Mirroring | Vectors (NMI / RESET / IRQ) | State | Notes |
@@ -1102,9 +1100,8 @@ All 857 projects, all **byte-identical for the whole ROM**.
| Tag Team Wrestling (U) | 32 KB | 8 KB | Horizontal | $FFCD / $FD43 / $FD43 | Pass 0 skeleton | |
| U-Force Test Cartridge (U) | 32 KB | 8 KB | Vertical | $844C / $8000 / $8000 | Pass 0 skeleton | |
| Volleyball (U) | 32 KB | 8 KB | Vertical | $8053 / $8000 / $FFFF | Pass 0 skeleton | |
| Xevious (U) | 32 KB | 8 KB | Horizontal | $FC4E / $FAF6 / $FF1D | Pass 0 skeleton | |
### `_wip/UNROM/` — mapper 2 (98 projects)
### `_wip/UNROM/` — mapper 2 (97 projects)
| Project | PRG | CHR | Mirroring | Vectors (NMI / RESET / IRQ) | State | Notes |
|---------|-----|-----|-----------|------------------------------|-------|-------|
@@ -1205,8 +1202,7 @@ All 857 projects, all **byte-identical for the whole ROM**.
| Wall Street Kid (U) [a2] | 128 KB | none | Horizontal | $F95C / $C000 / $F9E2 | Pass 0 skeleton | 65536-byte footer |
| Wayne Gretzky Hockey (U) | 128 KB | none | Vertical | $C10A / $C000 / $C378 | Pass 0 skeleton | |
| Winter Games (U) | 128 KB | none | Horizontal | $06FB / $C040 / $E295 | Pass 0 skeleton | |
| Zanac (U) | 128 KB | none | Horizontal | $CE8D / $E7BF / $CEC4 | Pass 0 skeleton | |
All 857 projects, all **byte-identical for the whole ROM**.
All 856 projects, all **byte-identical for the whole ROM**.
---
@@ -1215,7 +1211,7 @@ All 857 projects, all **byte-identical for the whole ROM**.
### 7.1 Almost all of the tier is a banked mapper
Only 37 of the 857 are mapper 0, and only **two** have a PRG small enough to
Only 37 of the 856 are mapper 0, and only **two** have a PRG small enough to
sit at a single CPU address:
| PRG size | Projects |
@@ -2,9 +2,9 @@
## Status
**Pass 0 skeleton.** The project builds and verifies byte-identical to the
original ROM, but no disassembly exists yet: `prg.s` is a single
`.incbin "prg.bin"` of the PRG image.
**Pass 1 complete.** The code/data split has been produced by `nesdis.py` and
the project builds byte-identical to the original ROM. `prg.s` now contains
traced code with audit comments and `.byte` data blocks for unreached bytes.
`make` assembles `header.s`, `prg.s`, `chr.s`, links them with `ld65` and compares the
result against `rom.nes`:
@@ -39,11 +39,6 @@ Byte-identical ROM verified.
## Open work
- **Pass 1** - run `nesdis.py` over `prg.bin` to produce the code/data
split. The tracer reads the vectors from the last six bytes of the PRG
image, so the split seeds correctly.
- **Pass 1** must emit the canonical audit comment
`; CPU:$C123 PRG:0123 AD 21 03` at column 35 for every instruction.
- **Pass 2** - replace the address-derived `Label_XXXX` names and the raw
`$XXXX` call operands.
- **Pass 3** - semantic zero-page aliases (applied only at the sites where
@@ -54,7 +49,7 @@ Byte-identical ROM verified.
| File | Purpose |
|------|---------|
| `prg.s` | Pass 0 PRG include (replaced by the Pass 1 disassembly) |
| `prg.s` | Pass 1 PRG disassembly (traced code + data blocks) |
| `header.s` | iNES header include |
| `chr.s` | CHR include |
| `prg.bin` | 65536 bytes (64 KB) PRG image |
@@ -62,5 +57,5 @@ Byte-identical ROM verified.
| `rom.nes` | byte-identical copy of the original ROM |
| `linker.cfg` | HEADER / PRG / CHR memory areas |
| `symbols.inc` | NES hardware register names |
| `locals.inc` | zero-page aliases (empty at Pass 0) |
| `locals.inc` | zero-page aliases (5 ZpXX aliases at Pass 1) |
| `Makefile` | build and byte-identity check |
@@ -0,0 +1,17 @@
label Label_801B Sub_801B_Entry_801B
label Label_8036 Sub_8036_Entry_8036
label Label_8038 Sub_8036_OnNonnegative_8038
label Label_8057 Sub_8036_JoinBranchPaths_8057
label Label_8062 Sub_8036_OnNonzero_8062
label Label_806B Sub_8036_OnCarrySet_806B
label Label_8083 Sub_8083_StoreAndContinue_8083
label Label_8189 Sub_8083_Entry_8189
label Label_FF2F Sub_8764_OnCarryClear_FF2F
label Label_FF3E Sub_FF3E_CallNext_FF3E
label Label_FF49 Sub_FF49_JumpNext_FF49
label Label_FF4C Sub_FF4C_StoreAndContinue_FF4C
label Label_FF4E Sub_FF4C_OnNonzero_FF4E
label Label_FF50 Sub_FF4C_OnNonzero_FF50
label Label_FF57 Sub_FF57_Return_FF57
label Label_FF60 Sub_FF57_OnNonzero_FF60
label Label_FF62 Sub_FF62_Return_FF62
1 label Label_801B Sub_801B_Entry_801B
2 label Label_8036 Sub_8036_Entry_8036
3 label Label_8038 Sub_8036_OnNonnegative_8038
4 label Label_8057 Sub_8036_JoinBranchPaths_8057
5 label Label_8062 Sub_8036_OnNonzero_8062
6 label Label_806B Sub_8036_OnCarrySet_806B
7 label Label_8083 Sub_8083_StoreAndContinue_8083
8 label Label_8189 Sub_8083_Entry_8189
9 label Label_FF2F Sub_8764_OnCarryClear_FF2F
10 label Label_FF3E Sub_FF3E_CallNext_FF3E
11 label Label_FF49 Sub_FF49_JumpNext_FF49
12 label Label_FF4C Sub_FF4C_StoreAndContinue_FF4C
13 label Label_FF4E Sub_FF4C_OnNonzero_FF4E
14 label Label_FF50 Sub_FF4C_OnNonzero_FF50
15 label Label_FF57 Sub_FF57_Return_FF57
16 label Label_FF60 Sub_FF57_OnNonzero_FF60
17 label Label_FF62 Sub_FF62_Return_FF62
@@ -0,0 +1 @@
@@ -0,0 +1,17 @@
label Label_801B Sub_801B_Entry_801B
label Label_8036 Sub_8036_Entry_8036
label Label_8038 Sub_8036_OnNonnegative_8038
label Label_8057 Sub_8036_JoinBranchPaths_8057
label Label_8062 Sub_8036_OnNonzero_8062
label Label_806B Sub_8036_OnCarrySet_806B
label Label_8083 Sub_8083_StoreAndContinue_8083
label Label_8189 Sub_8083_Entry_8189
label Label_FF2F Sub_8764_OnCarryClear_FF2F
label Label_FF3E Sub_FF3E_CallNext_FF3E
label Label_FF49 Sub_FF49_JumpNext_FF49
label Label_FF4C Sub_FF4C_StoreAndContinue_FF4C
label Label_FF4E Sub_FF4C_OnNonzero_FF4E
label Label_FF50 Sub_FF4C_OnNonzero_FF50
label Label_FF57 Sub_FF57_Return_FF57
label Label_FF60 Sub_FF57_OnNonzero_FF60
label Label_FF62 Sub_FF62_Return_FF62
1 label Label_801B Sub_801B_Entry_801B
2 label Label_8036 Sub_8036_Entry_8036
3 label Label_8038 Sub_8036_OnNonnegative_8038
4 label Label_8057 Sub_8036_JoinBranchPaths_8057
5 label Label_8062 Sub_8036_OnNonzero_8062
6 label Label_806B Sub_8036_OnCarrySet_806B
7 label Label_8083 Sub_8083_StoreAndContinue_8083
8 label Label_8189 Sub_8083_Entry_8189
9 label Label_FF2F Sub_8764_OnCarryClear_FF2F
10 label Label_FF3E Sub_FF3E_CallNext_FF3E
11 label Label_FF49 Sub_FF49_JumpNext_FF49
12 label Label_FF4C Sub_FF4C_StoreAndContinue_FF4C
13 label Label_FF4E Sub_FF4C_OnNonzero_FF4E
14 label Label_FF50 Sub_FF4C_OnNonzero_FF50
15 label Label_FF57 Sub_FF57_Return_FF57
16 label Label_FF60 Sub_FF57_OnNonzero_FF60
17 label Label_FF62 Sub_FF62_Return_FF62
@@ -1,4 +1,37 @@
; Zero-page aliases for this project.
; Empty at Pass 0. Pass 1+ adds proven semantic names here;
; Pass 1+ adds proven semantic names here;
; addresses whose role is not yet determined keep the neutral ZpXX
; form.
Zp00 = $00
Zp01 = $01
Zp02 = $02
Zp2F = $2F
Zp6A = $6A
; ---------------------------------------------------------------------------
; Semantic zero-page aliases (Pass 3)
;
; Every alias below was read out of this dump's own code. An address whose
; role is the same at every reference is renamed everywhere; an address that
; is reused for several roles keeps the neutral ZpXX name outside the
; routines where the role is proven, and the per-site choice is recorded in
; sites.tsv.
; ---------------------------------------------------------------------------
TempVar0 = $00 ; semantic alias for Zp00 (general-purpose zero-page temp, used at $804D,$8057,$806B)
TempVar1 = $01 ; semantic alias for Zp01 (general-purpose zero-page temp, used at $804F,$8062,$8066,$806D,$807D)
TempVar2 = $02 ; semantic alias for Zp02 (general-purpose zero-page temp, used at $8076)
LoopCounter = $2F ; semantic alias for Zp2F (incremented at $8083, likely frame/loop counter)
StatusByte = $6A ; semantic alias for Zp6A (stored at $8081, likely status/flags register)
; Clean marker section placeholder - will be filled by tools if needed
; ---------------------------------------------------------------------------
; Semantic zero-page aliases (Pass 3)
;
; Every alias below was read out of this dump's own code. An address whose
; role is the same at every reference is renamed everywhere; an address that
; is reused for several roles keeps the neutral ZpXX name outside the
; routines where the role is proven, and the per-site choice is recorded in
; sites.tsv.
; ---------------------------------------------------------------------------
File diff suppressed because it is too large. Load diff
-66
View File
@@ -1,66 +0,0 @@
# Xevious (U)
## Status
**Pass 0 skeleton.** The project builds and verifies byte-identical to the
original ROM, but no disassembly exists yet: `prg.s` is a single
`.incbin "prg.bin"` of the PRG image.
`make` assembles `header.s`, `prg.s`, `chr.s`, links them with `ld65` and compares the
result against `rom.nes`:
```
Byte-identical ROM verified.
```
## ROM
| Property | Value |
|----------|-------|
| Format | iNES |
| Mapper | 0 |
| Board | NROM-256 |
| Mirroring | Horizontal |
| Four-screen VRAM | no |
| Battery | no |
| PRG | 32 KB (2 x 16 KB), mapped at CPU $8000-$FFFF |
| CHR | 8 KB (1 x 8 KB) |
| Trainer | none |
| Footer | none |
| NMI vector | $FC4E |
| RESET vector | $FAF6 |
| IRQ vector | $FF1D |
| ROM file | `Xevious (U).nes` |
| SHA-256 | `1915fb1c30251de0c8f7913720a27b25d3ccef871851722a504d95fbb9d0ca7c` |
### Header notes
- none
## Open work
- **Pass 1** - run `nesdis.py` over `prg.bin` to produce the code/data
split. The tracer reads the vectors from the last six bytes of the PRG
image, so the split seeds correctly.
- **Pass 1** must emit the canonical audit comment
`; CPU:$C123 PRG:0123 AD 21 03` at column 35 for every instruction.
- **Pass 2** - replace the address-derived `Label_XXXX` names and the raw
`$XXXX` call operands.
- **Pass 3** - semantic zero-page aliases (applied only at the sites where
their role is proven) and named data tables.
- **Promotion** to `NROM/<name>/` once Pass 3 is done, as `git mv`.
## Files
| File | Purpose |
|------|---------|
| `prg.s` | Pass 0 PRG include (replaced by the Pass 1 disassembly) |
| `header.s` | iNES header include |
| `chr.s` | CHR include |
| `prg.bin` | 32768 bytes (32 KB) PRG image |
| `chr.bin` | 8192 bytes (8 KB) CHR image |
| `rom.nes` | byte-identical copy of the original ROM |
| `linker.cfg` | HEADER / PRG / CHR memory areas |
| `symbols.inc` | NES hardware register names |
| `locals.inc` | zero-page aliases (empty at Pass 0) |
| `Makefile` | build and byte-identity check |
-4
View File
@@ -1,4 +0,0 @@
; Zero-page aliases for this project.
; Empty at Pass 0. Pass 1+ adds proven semantic names here;
; addresses whose role is not yet determined keep the neutral ZpXX
; form.
-18
View File
@@ -1,18 +0,0 @@
; Xevious (U) NES disassembly - Pass 0 (build skeleton)
;
; The PRG image is included verbatim, so the project rebuilds
; byte-identical to the original ROM from the first commit. Pass 1
; replaces this block with the traced disassembly; no ROM byte is
; ever deleted or reformatted, only re-classified as code or data.
;
; Board: NROM-256
; PRG: 32 KB mapped at $8000-$FFFF
; Vectors: NMI=$FC4E RESET=$FAF6 IRQ=$FF1D
.setcpu "6502"
.include "symbols.inc"
.include "locals.inc"
.segment "PRG"
.incbin "prg.bin"
-64
View File
@@ -1,64 +0,0 @@
# Zanac (U)
## Status
**Pass 0 skeleton.** The project builds and verifies byte-identical to the
original ROM, but no disassembly exists yet: `prg.s` is a single
`.incbin "prg.bin"` of the PRG image.
`make` assembles `header.s`, `prg.s`, links them with `ld65` and compares the
result against `rom.nes`:
```
Byte-identical ROM verified.
```
## ROM
| Property | Value |
|----------|-------|
| Format | iNES |
| Mapper | 2 |
| Board | UNROM |
| Mirroring | Horizontal |
| Four-screen VRAM | no |
| Battery | no |
| PRG | 128 KB (8 x 16 KB), at file offset $0010 |
| CHR | none |
| Trainer | none |
| Footer | none |
| NMI vector | $CE8D |
| RESET vector | $E7BF |
| IRQ vector | $CEC4 |
| ROM file | `Zanac (U).nes` |
| SHA-256 | `7e75a19b9e11715c0eb19a2017a322df02f5cf4f7b30acef0fa7a0615236bda4` |
### Header notes
- none
## Open work
- **Pass 1** - run `nesdis.py` over `prg.bin` to produce the code/data
split. The tracer reads the vectors from the last six bytes of the PRG
image, so the split seeds correctly.
- **Pass 1** must emit the canonical audit comment
`; CPU:$C123 PRG:0123 AD 21 03` at column 35 for every instruction.
- **Pass 2** - replace the address-derived `Label_XXXX` names and the raw
`$XXXX` call operands.
- **Pass 3** - semantic zero-page aliases (applied only at the sites where
their role is proven) and named data tables.
- **Promotion** to `NROM/<name>/` once Pass 3 is done, as `git mv`.
## Files
| File | Purpose |
|------|---------|
| `prg.s` | Pass 0 PRG include (replaced by the Pass 1 disassembly) |
| `header.s` | iNES header include |
| `prg.bin` | 131072 bytes (128 KB) PRG image |
| `rom.nes` | byte-identical copy of the original ROM |
| `linker.cfg` | HEADER / PRG memory areas |
| `symbols.inc` | NES hardware register names |
| `locals.inc` | zero-page aliases (empty at Pass 0) |
| `Makefile` | build and byte-identity check |
-4
View File
@@ -1,4 +0,0 @@
; Zero-page aliases for this project.
; Empty at Pass 0. Pass 1+ adds proven semantic names here;
; addresses whose role is not yet determined keep the neutral ZpXX
; form.
-18
View File
@@ -1,18 +0,0 @@
; Zanac (U) NES disassembly - Pass 0 (build skeleton)
;
; The PRG image is included verbatim, so the project rebuilds
; byte-identical to the original ROM from the first commit. Pass 1
; replaces this block with the traced disassembly; no ROM byte is
; ever deleted or reformatted, only re-classified as code or data.
;
; Board: UNROM
; PRG: 128 KB at file offset $0010 (the image is bank-switched; it does not fit the 6502 address space as one window)
; Vectors: NMI=$CE8D RESET=$E7BF IRQ=$CEC4
.setcpu "6502"
.include "symbols.inc"
.include "locals.inc"
.segment "PRG"
.incbin "prg.bin"