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:
1 parent
ef4a1044f7
commit
c79a52e354
23 files changed
+5434
-86
No files matched your search
+13
-3
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
@@ -0,0 +1,2 @@
|
||||
.segment "CHR"
|
||||
.incbin "chr.bin"
|
||||
File renamed without changes.
@@ -0,0 +1,2 @@
|
||||
.segment "HEADER"
|
||||
.incbin "header.bin"
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
+6
@@ -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
|
||||
|
||||
|
||||
File renamed without changes.
Symlink
+1
@@ -0,0 +1 @@
|
||||
../rom.nes
|
||||
File renamed without changes.
Binary file not shown.
@@ -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.
|
||||
@@ -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
|
||||
@@ -1,6 +0,0 @@
|
||||
MEMORY {
|
||||
PRG: start = $C000, size = $4000, file = %O, fill = yes;
|
||||
}
|
||||
SEGMENTS {
|
||||
PRG: load = PRG, type = ro;
|
||||
}
|
||||
@@ -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.
|
||||
@@ -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.
Reference in new issue
Block a user