Promote Wild Gunman (U) from _wip to top-level project

Moves Wild Gunman (U) from _wip/ to Wild Gunman (U)/ with full ROM build:
- Adds header.s, chr.s, linker.cfg (HEADER+PRG+CHR segments)
- Updates Makefile to build and verify reconstructed.nes vs rom.nes
- Adds rom.nes copy + copilot/rom.nes symlink per repo convention
- Verified byte-identical build

Pass 1 complete: full code/data classification (~20% code / ~80% data)
Pass 2 partial: routine headers for all labels, semantic naming for key
routines (Reset, NmiHandler, MainStateDispatch, MainLoopBody, etc.),
zero-page aliases in locals.inc

Updates root OVERVIEW.md:
- Removes Wild Gunman from _wip skeleton table (23 -> 22 skeletons)
- Adds Wild Gunman as #13 in numbered inventory (BYTE-IDENTICAL, Pass 2)
- Updates summary count from 12 to 13 projects
This commit is contained in:
tmerritt committed 2026-10-16 18:51:15 -04:00
1 parent ef4a1044f7
commit c79a52e354
23 files changed
+5434 -86

No files matched your search

+13 -3
View File
@@ -144,11 +144,21 @@ This document provides a consolidated overview of all NES disassembly projects i
- **Build fix:** None needed; byte-identical out of the box (`make` in `copilot/`). Pass 1/2/3 complete — full code/data classification, semantic routine naming, and data table naming all done
- **Details:** `CIRCUS/OVERVIEW.md`
### 13. Wild Gunman (U)
- **Folder:** `Wild Gunman (U)/`
- **ROM:** `rom.nes` (24,592 bytes)
- **Source:** `copilot/prg.s` (~3,000 lines with routine headers)
- **Linker:** HEADER at $0000 (16 bytes), PRG at $C000 (16 KB), CHR at $0000 (8 KB)
- **Vectors:** NMI → $C086 (`NmiHandler`), RESET → $C000 (`Reset`), IRQ → $C000 (reuses `Reset`)
- **Key subsystems:** NMI-driven frame loop — main loop is a spin loop waiting on NMI phase flag ($20); NMI handler does OAM DMA ($4014), PPU updates, and calls game logic subroutines ($C29F, $C233, $C3AC, $C265); main state dispatcher at $C0B3 based on `GameMode` ($30); reset copies sprite/OAM data from $C844 to $05F0; APU enabled via $4015 = $0F
- **Build fix:** None needed; byte-identical out of the box (`make` in `copilot/`). Pass 1 complete — full code/data classification (~20% code / ~80% data); Pass 2 partial — routine headers and semantic naming for key routines (`Reset`, `NmiHandler`, `MainStateDispatch`, `MainLoopBody`, etc.); zero-page aliases in `locals.inc` (`GameMode`=$30, `NmiPhase`=$20, `NmiFlag`=$22, `Timer2F`=$2F, etc.)
- **Details:** `Wild Gunman (U)/OVERVIEW.md`
---
## Skeleton Projects (under `_wip/`)
23 additional ROMs awaiting full disassembly. Each is set up as a Pass-0 skeleton (`default_project.tar.gz`): `copilot/` contains the split `prg.bin`/`header.bin`/`chr.bin`, a symbolic skeleton `prg.s`, and builds **BYTE-IDENTICAL** at the PRG level. Mapper 0 / 16 KB PRG / 8 KB CHR for all.
22 additional ROMs awaiting full disassembly. Each is set up as a Pass-0 skeleton (`default_project.tar.gz`): `copilot/` contains the split `prg.bin`/`header.bin`/`chr.bin`, a symbolic skeleton `prg.s`, and builds **BYTE-IDENTICAL** at the PRG level. Mapper 0 / 16 KB PRG / 8 KB CHR for all.
| Project | Vectors (NMI/RESET/IRQ) | Mir. | Status |
|---------|--------------------------|------|--------|
@@ -175,7 +185,6 @@ This document provides a consolidated overview of all NES disassembly projects i
| `Raid on Bungeling Bay (U)` | $C04C / $C000 / $C2C0 | H | BYTE-IDENTICAL |
| `Raid on Bungeling Bay (U) [a2]` | $C04C / $C000 / $C2C0 | V | BYTE-IDENTICAL |
| `Urban Champion (JU)` | $CA91 / $CA00 / $CA00 | H | BYTE-IDENTICAL |
| `Wild Gunman (U)` | $C086 / $C000 / $C000 | H | BYTE-IDENTICAL |
Notable vector/header observations for Pass 1 work:
- **Pac-Man (U)** RESET at `$FF00` (vector-page tail), while the Tengen variant RESETs at `$C033` — different builds confirmed (PRG bytes differ).
@@ -240,7 +249,7 @@ make verify # (where supported by the Makefile)
## Summary
All 12 projects in this repository rebuild **byte-identical** to their original ROMs:
All 13 projects in this repository rebuild **byte-identical** to their original ROMs:
| # | Project | Build Status |
|---|---------|--------------|
@@ -256,6 +265,7 @@ All 12 projects in this repository rebuild **byte-identical** to their original
| 10 | Donkey Kong 3 (JUE) | BYTE-IDENTICAL |
| 11 | Donkey Kong Jr. (JU) | BYTE-IDENTICAL (Pass 1) |
| 12 | CIRCUS | BYTE-IDENTICAL (Pass 2/3) |
| 13 | Wild Gunman (U) | BYTE-IDENTICAL (Pass 2) |
Every project builds successfully with `make` in the `copilot/` folder, and every reconstructed ROM matches the original byte-for-byte. Donkey Kong Jr. shares the same byte-identical build guarantee; its remaining Pass 2/3 work is semantic renaming and table decoding, not build-correctness.
+158
View File
@@ -0,0 +1,158 @@
# Wild Gunman (U) — Game Flow from Power-On
This document describes the execution flow of the disassembled Wild Gunman (U) PRG bank (16 KB, mapped at CPU **$C000–$FFFF**), starting from power-on. It is based entirely on `copilot/prg.s` in the repository. The rebuild is verified **byte-identical** to the original `prg.bin`.
---
## 1. ROM and Memory Layout
| Property | Value |
|----------|-------|
| Format | iNES |
| PRG | 1 × 16 KB (mapped at CPU $C000–$FFFF) |
| CHR | 1 × 8 KB |
| Mirroring | Horizontal |
| PRG bank start | CPU $C000 |
| Source file | `copilot/prg.s` (~3,000 lines with headers) |
| Output | `reconstructed_prg.bin` (16,384 bytes) |
### Interrupt vectors (CPU $FFFA–$FFFF)
| Vector | Address | Handler |
|--------|---------|---------|
| NMI | $C086 | `NmiHandler` |
| RESET | $C000 | `Reset` |
| IRQ / BRK | $C000 | Reuses `Reset` |
---
## 2. Build Status
`make` in `copilot/` assembles `prg.s` with `ca65`, links with `ld65`, and verifies against `prg.bin`.
**Verification result: BYTE-IDENTICAL** — `reconstructed_prg.bin` matches `prg.bin` exactly (all 16,384 bytes), and `prg.bin` matches the PRG bank of `Wild Gunman (U) [!].nes`.
---
## 3. Pass Status
| Pass | Status | Description |
|------|--------|-------------|
| Pass 1 | Complete | Code/data split — entire PRG bank classified as traced code (~20%) or explicit `.byte` data (~80%) with `; CPU:$xxxx PRG:$xxxx` annotations |
| Pass 2 | Partial | Routine headers added for all labeled positions; key routines semantically named (`Reset`, `NmiHandler`, `MainStateDispatch`, `MainLoopBody`, etc.); zero-page aliases in `locals.inc` |
| Pass 3 | Partial | Some data tables referenced by name in code; deeper table naming is future work |
---
## 4. Reset — CPU $FFFC → $C000
**`Reset`** ($C000)
On power-on or reset:
1. `CLD` — clear decimal mode; `SEI` — disable maskable interrupts.
2. **Wait for PPU warm-up vblank** — poll `$2002` bit 7 until clear (`bpl` loop at $C002–$C005).
3. `STX $2000 / STX $2001` — disable PPU rendering and NMI with X=0.
4. `DEX / TXS` — initialize stack pointer to $FF.
5. `LDX $05EC` — read OAM base value; `LDY #$06 / STY $01` — set up a 6-page counter.
6. **Clear RAM** — zero pages $0000–$05FF via indirect store loop (`STA (Zp00),Y` with page increment).
7. `LDX #$5F / STX $05EC` — set OAM base to $5F.
8. `JSR ResetInitSub1` ($C20B) and `JSR ResetInitSub2` ($C21B) — initialization subroutines.
9. Set scroll to 0 (`STA $2005` twice with Y=0).
10. `LDY #$01 / STY $30` — set `GameMode` = 1.
11. `LDA #$0F / STA $4015` — enable all APU channels.
12. `JSR $FFF7` — jump via vector to sound init at $F40F.
13. `LDA #$90 / STA $2000` — set PPUCTRL = $90 (NMI enabled, $2000 base).
14. `STA Zp08` ($08 = $90); `LDA #$02 / STA Zp09` ($09 = $02).
15. Copy 12 bytes from $C844 to $05F0 (sprite/OAM data table).
16. **Main loop** (`Label_C07C` at $C07C): check `NmiPhase` ($20); if nonzero, jump to $C061; otherwise call `MainLoopBody` ($C573) and loop forever.
**Key point:** Like several other games in this repo, the main loop is essentially driven by NMI. The `Reset` code sets up hardware and enters a loop that waits for NMI phase changes.
---
## 5. NMI / Frame Heartbeat — `NmiHandler` ($C086)
The NMI fires once per frame:
1. **Save registers** (`PHP / PHA / TXA / PHA / TYA / PHA`).
2. Set OAMADDR to 0 (`STA $2003`), trigger OAM DMA (`STA $4014` with value 2 → $0200–$02FF).
3. Check `NmiFlag` ($22) — if nonzero, skip to $C0A6 (restore registers, RTI).
4. **Game logic** — call `NmiGameLogic3` ($C29F), `NmiGameLogic1` ($C233), `NmiGameLogic5` ($C3AC), `NmiGameLogic2` ($C265).
5. `LDY #$01 / STY NmiFlag` and `STY NmiPhase` — set both flags to 1.
6. **Restore registers** (`PLA / TAY / PLA / TAX / PLA / PLP / RTI`).
---
## 6. Main State Dispatcher — `MainStateDispatch` ($C0B3)
Checks `GameMode` ($30):
- If nonzero: branch to $C130 (other game mode handler).
- If zero: check `Ctrl1` ($16) bit 4 (`AND #$10`); if zero, go to $C10A.
- Otherwise, read `OAMBase` ($05FC) into Y; if nonzero, go to $C10F.
- Continue with startup sequence.
---
## 7. Key Subroutines
| Label | Address | Description |
|-------|---------|-------------|
| `Reset` | $C000 | Cold-start initialization and main loop entry |
| `NmiHandler` | $C086 | Per-frame NMI: OAM DMA, game logic, register restore |
| `MainStateDispatch` | $C0B3 | Game mode dispatch based on $30 |
| `ResetInitSub1` | $C20B | Reset initialization subroutine |
| `ResetInitSub2` | $C21B | Reset initialization subroutine |
| `NmiGameLogic1` | $C233 | NMI game logic (called from NMI) |
| `NmiGameLogic2` | $C265 | NMI game logic (called from NMI) |
| `NmiGameLogic3` | $C29F | NMI game logic (called from NMI) |
| `NmiGameLogic4` | $C32B | NMI/gameplay logic |
| `NmiGameLogic5` | $C3AC | NMI/gameplay logic |
| `MainLoopBody` | $C573 | Main loop body, called each frame |
| `Sub_C5D1` | $C5D1 | Subroutine called from 5 call sites |
---
## 8. Zero-Page Aliases (`locals.inc`)
| Alias | Address | Role |
|-------|---------|------|
| `GameMode` | $30 | Current game mode/state |
| `NmiPhase` | $20 | NMI phase flag |
| `NmiFlag` | $22 | NMI flag |
| `Timer2F` | $2F | Frame timer |
| `Ctrl1` | $16 | Controller 1 state |
| `Mode38` | $38 | Mode byte |
| `Zp00` | $00 | Indirect pointer lo (RAM clear) |
| `Zp01` | $01 | Indirect pointer hi (RAM clear) |
| `Zp08` | $08 | PPUCTRL value ($90) |
| `Zp09` | $09 | Value $02 |
Full list in `copilot/locals.inc`.
---
## 9. Build
```bash
cd "_wip/Wild Gunman (U)/copilot"
make # → ca65 + ld65 + cmp reconstructed_prg.bin prg.bin → "BYTE-IDENTICAL"
```
---
## 10. Notes
- The PRG is approximately 20% code / 80% data. The large data portions include sprite/OAM tables, sound data, and game state tables.
- The NMI handler drives the per-frame game loop; the main loop (`Reset` at $C07C) spins waiting for NMI phase changes.
- `GameMode` ($30) selects between different game states/modes.
- The vectors at $FFF4 and $FFF7 are indirect jump targets to sound routines at $F372 and $F40F respectively.
- IRQ vector points to $C000 (Reset) and is effectively unused.
---
## 11. Next Steps
- **Promotion** — move to a top-level `Wild Gunman (U)/` folder, add `header.s` / `chr.s` + full-ROM `make` target (as e.g. `Burger Time (U)`), then join the root `OVERVIEW.md` numbered inventory.
- **Pass 2/3 continuation** — semantically rename remaining `Label_Cxxxx` routines, name data tables (sprite data at $C844, sound tables in $E000–$FFFF range), and refine zero-page aliases.
+25
View File
@@ -0,0 +1,25 @@
CA65 ?= ca65
LD65 ?= ld65
all: reconstructed.nes verify
prg.o: prg.s symbols.inc locals.inc
$(CA65) -g -o $@ $<
header.o: header.s
$(CA65) -g -o $@ $<
chr.o: chr.s
$(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
cmp reconstructed.nes rom.nes
@echo "Byte-identical ROM verified."
clean:
rm -f *.o reconstructed.nes reconstructed.map reconstructed.lbl
.PHONY: all verify clean
File renamed without changes.
+2
View File
@@ -0,0 +1,2 @@
.segment "CHR"
.incbin "chr.bin"
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 = $C000, size = $4000, file = %O, fill = yes;
CHR: start = $0000, size = $2000, file = %O, fill = yes;
}
SEGMENTS {
HEADER: load = HEADER, type = ro;
PRG: load = PRG, type = ro;
CHR: load = CHR, type = ro;
}
+18
View File
@@ -0,0 +1,18 @@
; Wild Gunman (U) zero-page aliases - Pass 2
; Semantic names for addresses with observed usage patterns; ZpXX names for
; addresses whose role is not yet uniquely determined.
GameMode = $30 ; Current game mode/state, set to 1 during reset.
NmiPhase = $20 ; NMI phase flag, set to 1 by NMI handler.
NmiFlag = $22 ; NMI flag, set to 1 by NMI handler.
Timer2F = $2F ; Timer incremented each frame in main loop.
Ctrl1 = $16 ; Controller 1 state, checked in MainStateDispatch.
Mode38 = $38 ; Mode byte checked in MainStateDispatch.
OAMBase = $05EC ; OAM/sprite base address used in reset init.
SpriteData = $05F0 ; Sprite data destination in reset init.
; Generic zero-page aliases (role not yet uniquely determined)
Zp00 = $00 ; Used as indirect pointer lo in RAM clear loop
Zp01 = $01 ; Used as indirect pointer hi in RAM clear loop
Zp08 = $08 ; Set to $90 during reset (PPUCTRL value)
Zp09 = $09 ; Set to $02 during reset
File renamed without changes.
File diff suppressed because it is too large. Load diff
+249
View File
@@ -0,0 +1,249 @@
al 00FFF7 .Label_FFF7
al 00FFF4 .Label_FFF4
al 00F76F .Label_F76F
al 00F724 .Label_F724
al 00F723 .Label_F723
al 00F70A .Label_F70A
al 00F702 .Label_F702
al 00F709 .Label_F709
al 00F6D2 .Label_F6D2
al 00F6D0 .Label_F6D0
al 00F6BC .Label_F6BC
al 00F6B1 .Label_F6B1
al 00F6C7 .Label_F6C7
al 00F6D9 .Label_F6D9
al 00F67F .Label_F67F
al 00F67D .Label_F67D
al 00F674 .Label_F674
al 00F686 .Label_F686
al 00F652 .Label_F652
al 00F650 .Label_F650
al 00F642 .Label_F642
al 00F64B .Label_F64B
al 00F659 .Label_F659
al 00F613 .Label_F613
al 00F60F .Label_F60F
al 00F60E .Label_F60E
al 00F5FD .Label_F5FD
al 00F5FB .Label_F5FB
al 00F5EF .Label_F5EF
al 00F5EC .Label_F5EC
al 00F5E1 .Label_F5E1
al 00F5D5 .Label_F5D5
al 00F5C7 .Label_F5C7
al 00F5B4 .Label_F5B4
al 00F617 .Label_F617
al 00F5AC .Label_F5AC
al 00F592 .Label_F592
al 00F5B0 .Label_F5B0
al 00F583 .Label_F583
al 00F570 .Label_F570
al 00F573 .Label_F573
al 00F5BD .Label_F5BD
al 00F59E .Label_F59E
al 00F588 .Label_F588
al 00F58E .Label_F58E
al 00F57F .Label_F57F
al 00F579 .Label_F579
al 00F53F .Label_F53F
al 00F5A9 .Label_F5A9
al 00F532 .Label_F532
al 00F53D .Label_F53D
al 00F51A .Label_F51A
al 00F50D .Label_F50D
al 00F50A .Label_F50A
al 00F4EF .Label_F4EF
al 00F48A .Label_F48A
al 00F48E .Label_F48E
al 00F468 .Label_F468
al 00F453 .Label_F453
al 00F440 .Label_F440
al 00F42A .Label_F42A
al 00F426 .Label_F426
al 00F418 .Label_F418
al 00F40F .Label_F40F
al 00F3EB .Label_F3EB
al 00F3EE .Label_F3EE
al 00F3E3 .Label_F3E3
al 00F3C0 .Label_F3C0
al 00F3A8 .Label_F3A8
al 00F39D .Label_F39D
al 00F38F .Label_F38F
al 00F38B .Label_F38B
al 00F391 .Label_F391
al 00F387 .Label_F387
al 00F372 .Label_F372
al 00DEED .Label_DEED
al 00DED4 .Label_DED4
al 00DAE0 .Label_DAE0
al 00DAD2 .Label_DAD2
al 00D97C .Label_D97C
al 00D996 .Label_D996
al 00D978 .Label_D978
al 00D969 .Label_D969
al 00D965 .Label_D965
al 00D959 .Label_D959
al 00D973 .Label_D973
al 00D955 .Label_D955
al 00D8FF .Label_D8FF
al 00D8EF .Label_D8EF
al 00D8E5 .Label_D8E5
al 00D8E3 .Label_D8E3
al 00D8D9 .Label_D8D9
al 00D8D7 .Label_D8D7
al 00D5B3 .Label_D5B3
al 00D5AF .Label_D5AF
al 00D4F4 .Label_D4F4
al 00D416 .Label_D416
al 00D3EE .Label_D3EE
al 00D3FD .Label_D3FD
al 00D3CF .Label_D3CF
al 00D3C4 .Label_D3C4
al 00D3C2 .Label_D3C2
al 00D3B9 .Label_D3B9
al 00D3BF .Label_D3BF
al 00D396 .Label_D396
al 00D382 .Label_D382
al 00D36C .Label_D36C
al 00D33C .Label_D33C
al 00D363 .Label_D363
al 00D365 .Label_D365
al 00D317 .Label_D317
al 00D313 .Label_D313
al 00D2F2 .Label_D2F2
al 00D2E2 .Label_D2E2
al 00D2D5 .Label_D2D5
al 00D2D3 .Label_D2D3
al 00D2CF .Label_D2CF
al 00D2D2 .Label_D2D2
al 00D273 .Label_D273
al 00D25E .Label_D25E
al 00D23B .Label_D23B
al 00D213 .Label_D213
al 00D208 .Label_D208
al 00D1FF .Label_D1FF
al 00D205 .Label_D205
al 00D1C9 .Label_D1C9
al 00D1D3 .Label_D1D3
al 00D1C5 .Label_D1C5
al 00D1D9 .Label_D1D9
al 00D1AE .Label_D1AE
al 00D19D .Label_D19D
al 00D187 .Label_D187
al 00D175 .Label_D175
al 00D172 .Label_D172
al 00D165 .Label_D165
al 00D154 .Label_D154
al 00D15B .Label_D15B
al 00D149 .Label_D149
al 00D14E .Label_D14E
al 00D118 .Label_D118
al 00D110 .Label_D110
al 00D134 .Label_D134
al 00D11D .Label_D11D
al 00D0FF .Label_D0FF
al 00D0F1 .Label_D0F1
al 00D0E3 .Label_D0E3
al 00D0DA .Label_D0DA
al 00D0CE .Label_D0CE
al 00D0D1 .Label_D0D1
al 00D0C3 .Label_D0C3
al 00D0B6 .Label_D0B6
al 00D0A6 .Label_D0A6
al 00D097 .Label_D097
al 00D089 .Label_D089
al 00D068 .Label_D068
al 00D053 .Label_D053
al 00D04F .Label_D04F
al 00D054 .Label_D054
al 00D03E .Label_D03E
al 00D02B .Label_D02B
al 00D027 .Label_D027
al 00D02C .Label_D02C
al 00D01C .Label_D01C
al 00CF0C .Label_CF0C
al 00CF01 .Label_CF01
al 00C5EC .Label_C5EC
al 00C5E6 .Label_C5E6
al 00C5DF .Label_C5DF
al 00C5D7 .Label_C5D7
al 00C5D1 .Sub_C5D1
al 00C585 .Label_C585
al 00C573 .MainLoopBody
al 00C4ED .Label_C4ED
al 00C4C2 .Label_C4C2
al 00C4C6 .Label_C4C6
al 00C4B5 .Label_C4B5
al 00C4AA .Label_C4AA
al 00C421 .Label_C421
al 00C411 .Label_C411
al 00C3E7 .Label_C3E7
al 00C3D0 .Label_C3D0
al 00C3B9 .Label_C3B9
al 00C3AC .NmiGameLogic5
al 00C3A3 .Label_C3A3
al 00C38F .Label_C38F
al 00C38C .Label_C38C
al 00C389 .Label_C389
al 00C37D .Label_C37D
al 00C367 .Label_C367
al 00C341 .Label_C341
al 00C33D .Label_C33D
al 00C337 .Label_C337
al 00C32B .NmiGameLogic4
al 00C324 .Label_C324
al 00C30B .Label_C30B
al 00C2F5 .Label_C2F5
al 00C2E3 .Label_C2E3
al 00C2CA .Label_C2CA
al 00C2BB .Label_C2BB
al 00C2D4 .Label_C2D4
al 00C2E2 .Label_C2E2
al 00C29F .NmiGameLogic3
al 00C29E .Label_C29E
al 00C275 .Label_C275
al 00C273 .Label_C273
al 00C265 .NmiGameLogic2
al 00C25A .Label_C25A
al 00C24D .Label_C24D
al 00C259 .Label_C259
al 00C233 .NmiGameLogic1
al 00C232 .Label_C232
al 00C22B .Label_C22B
al 00C225 .Label_C225
al 00C21B .ResetInitSub2
al 00C212 .Label_C212
al 00C202 .Label_C202
al 00C1EB .Label_C1EB
al 00C1CA .Label_C1CA
al 00C1A8 .Label_C1A8
al 00C1F7 .Label_C1F7
al 00C19B .Label_C19B
al 00C192 .Label_C192
al 00C183 .Label_C183
al 00C197 .Label_C197
al 00C189 .Label_C189
al 00C170 .Label_C170
al 00C169 .Label_C169
al 00C179 .Label_C179
al 00C156 .Label_C156
al 00C16D .Label_C16D
al 00C101 .Label_C101
al 00C0DE .Label_C0DE
al 00C0D4 .Label_C0D4
al 00C0F0 .Label_C0F0
al 00C10F .Label_C10F
al 00C10A .Label_C10A
al 00C130 .Label_C130
al 00C0B3 .MainStateDispatch
al 00C0A6 .Label_C0A6
al 00C086 .NmiHandler
al 00C06E .Label_C06E
al 00C06B .Label_C06B
al 00C061 .Label_C061
al 00C07C .Label_C07C
al 00C056 .Label_C056
al 00C02C .Label_C02C
al 00C01E .Label_C01E
al 00C002 .Label_C002
al 00C000 .Reset
@@ -1,13 +1,19 @@
Modules list:
-------------
header.o:
HEADER Offs=000000 Size=000010 Align=00001 Fill=0000
prg.o:
PRG Offs=000000 Size=004000 Align=00001 Fill=0000
chr.o:
CHR Offs=000000 Size=002000 Align=00001 Fill=0000
Segment list:
-------------
Name Start End Size Align
----------------------------------------------------
CHR 000000 001FFF 002000 00001
HEADER 000000 00000F 000010 00001
PRG 00C000 00FFFF 004000 00001
+1
View File
@@ -0,0 +1 @@
../rom.nes
File renamed without changes.
-53
View File
@@ -1,53 +0,0 @@
# Wild Gunman (U) — Skeleton Project
ROM: `_wip/Wild Gunman (U)/Wild Gunman (U) [!].nes` (24,592 bytes, iNES). Status: **SKELETON — not yet disassembled.** The entire 16 KB PRG bank is a single unclassified block; `copilot/prg.s` is the default-project skeleton (`default_project.tar.gz`) that reproduces it as one `.incbin`. The skeleton build is **byte-identical** at the PRG level.
## ROM Facts
| Property | Value |
|----------|-------|
| Mapper | 0 (NROM) — from the iNES header |
| PRG | 16 KB (header claims map at CPU $C000–$FFFF) |
| CHR | 8 KB |
| Mirroring | Horizontal |
| Battery-backed flag | clear |
| ROM SHA-256 | `bee7de2cad3133ee6414423e904597154e70e85340fcce5c0829e78c996d84fc` |
| PRG SHA-256 | `1d22036e41b62ec7645bcbab7604034449988193ef7ddcd59c168bc39b417690` |
## Interrupt Vectors (taken from PRG $3FFA–$3FFF)
| Vector | Target | Note |
|--------|--------|------|
| NMI | `$C086` | per-frame heartbeat |
| RESET | `$C000` | cold start at $C000 — the usual pattern in this repo |
| IRQ | `$C000` | redirects to RESET — unused placeholder |
## `copilot/` Contents
| File | Purpose |
|------|---------|
| `Wild Gunman (U) [!].nes` | original ROM image (reference) |
| `prg.bin` / `header.bin` / `chr.bin` | split image, produced by `_tools/splitnes.py` |
| `prg.s` | Pass-1 skeleton: `.incbin "prg.bin", $0000, $4000` (whole PRG) |
| `symbols.inc` | shared NES hardware constants (PPU/APU/controller, from the skeleton) |
| `locals.inc` | project-local zero-page aliases — empty for now (filled in Pass 2) |
| `linker.cfg` | PRG at $C000, 16 KB, `fill = yes` |
| `Makefile` | links `reconstructed_prg.bin` and `cmp`s it against `prg.bin` |
| `reconstructed_prg.bin` | build output from the last verified build |
Header/CHR are reproduced verbatim from `header.bin`/`chr.bin` (not linked): `make` verifies **PRG bytes only** at this stage, which is exactly what a skeleton proves. When this project is promoted to a full disassembly, `header.s` / `chr.s` (as e.g. `Burger Time (U)`) and a full-ROM `make` target get added.
## Build
```bash
cd "_wip/Wild Gunman (U)/copilot"
make # → cmp reconstructed_prg.bin prg.bin → "BYTE-IDENTICAL"
```
## Next Steps (per `PROMPTS.md`)
1. **Pass 1** — replace the blanket `.incbin` with classified code/data: trace reachability from RESET ($C000) and NMI ($C086), emit per-instruction `; PRG:$xxxx AA BB` annotations, keep unreached bytes as explicit `.byte` blocks.
2. **Pass 2** — replace `Label_`/`Sub_` names with semantic routine names; fill `locals.inc`.
3. **Pass 3** — name data tables/structures; release provisional flags.
4. **Promotion** — move to a top-level `<name>/copilot/` folder, add full-ROM build (header.s + chr.s + vectors), and write the power-on flow `OVERVIEW.md` in the established style; then it joins the root index's numbered inventory.
-10
View File
@@ -1,10 +0,0 @@
all: reconstructed_prg.bin verify
prg.o: prg.s symbols.inc prg.bin
ca65 -g -o $@ prg.s
reconstructed_prg.bin: prg.o linker.cfg
ld65 -C linker.cfg -m reconstructed.map -Ln reconstructed.lbl -o $@ prg.o
verify: reconstructed_prg.bin prg.bin
cmp reconstructed_prg.bin prg.bin
@echo BYTE-IDENTICAL
clean:
rm -f prg.o reconstructed_prg.bin reconstructed.map reconstructed.lbl
-6
View File
@@ -1,6 +0,0 @@
MEMORY {
PRG: start = $C000, size = $4000, file = %O, fill = yes;
}
SEGMENTS {
PRG: load = PRG, type = ro;
}
-2
View File
@@ -1,2 +0,0 @@
; Wild Gunman (U) zero-page aliases (declared during Pass 2).
; These intentionally conservative names will be refined in Passes 2 and 3.
-12
View File
@@ -1,12 +0,0 @@
; Wild Gunman (U) NES disassembly - Pass 1 (skeleton)
; Generated from the supplied 16 KiB PRG image.
; Pass 1 classifies recursively reachable code, inline address tables, vectors,
; and untraced/data regions. All PRG data bytes are emitted explicitly with .byte directives.
.setcpu "6502"
.include "symbols.inc"
.include "locals.inc"
.segment "PRG"
.incbin "prg.bin", $0000, $4000
Whitespace-only changes.