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:
1 parent
49e117bfcc
commit
df11857075
58 files changed
+39615
-263
No files matched your search
@@ -101,6 +101,10 @@ ZpFF = $FF ; 8 refs; reads=3 writes=5; used at $EE9B, EF7B, E
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Semantic zero-page aliases (Pass 3)
|
||||
;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
CA65 ?= ca65
|
||||
LD65 ?= ld65
|
||||
|
||||
all: reconstructed.nes verify
|
||||
|
||||
prg.o: prg.s symbols.inc locals.inc prg.bin
|
||||
$(CA65) -g -o $@ $<
|
||||
|
||||
header.o: header.s header.bin
|
||||
$(CA65) -g -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
|
||||
@echo "Byte-identical ROM verified."
|
||||
|
||||
clean:
|
||||
rm -f *.o reconstructed.nes reconstructed_prg.bin reconstructed.map reconstructed.lbl
|
||||
|
||||
.PHONY: all verify clean
|
||||
@@ -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 |
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
.segment "CHR"
|
||||
.incbin "chr.bin"
|
||||
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
.segment "HEADER"
|
||||
.incbin "header.bin"
|
||||
@@ -0,0 +1,10 @@
|
||||
MEMORY {
|
||||
HEADER: start = $0000, size = $0010, fill = yes;
|
||||
PRG: start = $8000, size = $8000, fill = yes;
|
||||
CHR: start = $0000, size = $2000, fill = yes;
|
||||
}
|
||||
SEGMENTS {
|
||||
HEADER: load = HEADER, type = ro;
|
||||
PRG: load = PRG, type = ro;
|
||||
CHR: load = CHR, type = ro;
|
||||
}
|
||||
@@ -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)
|
||||
Binary file not shown.
+14981
File diff suppressed because it is too large.
Load diff
Binary file not shown.
@@ -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
|
||||
Reference in new issue
Block a user