Pass 2 _wip: Slalom (U), Kung Fu (U), Othello (U) label replacement complete

Pass 3 _wip: Slalom (U), Kung Fu (U), Othello (U) semantic naming complete
Pass 3 _wip: apply symbols (0 residue) for Slalom (U), Kung Fu (U), Othello (U)
Pass 2/3 _wip: 10 NROM projects (Elevator Action, 1942, Tag Team Wrestling, Galaga, Kung Fu a1, Stack-Up, Magmax, Ms Pac-Man Namco, Soccer, Sqoon)
Promote 13 _wip/NROM projects to NROM/ (Slalom, Kung Fu, Othello, Elevator Action, 1942, Tag Team Wrestling, Galaga, Kung Fu a1, Stack-Up, Magmax, Ms Pac-Man Namco, Soccer, Sqoon)
Pass 2/3 _wip: 5 CNROM games (Tiger-Heli, Paperboy, Last Starfighter, Mighty Bomb Jack, Kung-Fu Heroes)
Docs: document CDL capture + re-trace workflow in TODO.md
Adds more code for
 - Elevator Action (U)
 - Kung Fu (U)
 - Othello (U)
 - Slalom (U)
 - Sqoon (U)
This commit is contained in:
tmerritt committed 2026-10-21 14:42:00 -04:00
1 parent f8d62601e5
commit 0a49ee6da7
228 files changed
+101961 -37231

No files matched your search

Binary file not shown.
+25
View File
@@ -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
+67
View File
@@ -0,0 +1,67 @@
# Kung Fu (U) (a1)
## Status
**Pass 3.** All address-derived `Label_XXXX` definitions replaced;
every `jsr`/`jmp` operand symbolic; hardware-register operands resolved
via `apply_symbols.py` (0 residue); audit comments aligned; `make`
stays byte-identical.
`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 | Vertical |
| 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 | $82D6 |
| RESET vector | $8258 |
| IRQ vector | $FFF0 |
| ROM file | `Kung Fu (U) [a1].nes` |
| SHA-256 | `9e8383b3bd99ccf9bc972c57d37599604e969aebab7a8f0c9428112fafb6b82d` |
### 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 |
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
.segment "CHR"
.incbin "chr.bin"
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
.segment "HEADER"
.incbin "header.bin"
+157
View File
@@ -0,0 +1,157 @@
8258 Reset
82D6 NmiHandler
# ---- derived internal branch-target names ----
8258 Reset
8262 Reset_OnCarryClear
8268 Reset_OnCarryClear2
8277 Reset_OnNonzero
8287 Reset_OnNonzero2
82A8 Reset_Loop
82AA Reset_OnNonzero3
82D3 Sub_82D3
82D6 NmiHandler
832E NmiHandler_Loop
8342 NmiHandler_OnNonnegative
8348 NmiHandler_Loop2
834D NmiHandler_Loop3
8360 NmiHandler_Loop4
837C NmiHandler_OnNonzero
8396 NmiHandler_Loop5
8399 NmiHandler_Loop6
83A7 Sub_83A7
83AB NmiHandler_OnNonzero2
83BD NmiHandler_Loop7
83CD NmiHandler_Loop8
83F0 Sub_83F0
83F5 NmiHandler_Loop9
83FF Sub_83FF
8436 NmiHandler_Loop10
88D4 Sub_88D4
88E9 Sub_88E9
88FA NmiHandler_Loop11
891D NmiHandler_Loop12
8920 NmiHandler_Loop13
8921 NmiHandler_Loop14
8925 NmiHandler_Loop15
8927 NmiHandler_Loop16
896A Sub_896A
8E25 Sub_8E25
8E34 Sub_8E34
8F6C Sub_8F6C
8F7B Sub_8F7B
8F97 NmiHandler_OnNonzero3
8FB1 NmiHandler_OnNonzero4
8FB8 Sub_8FB8
8FBE Sub_8FBE
8FC2 NmiHandler_OnNonzero5
8FC9 Sub_8FC9
8FDD Sub_8FDD
8FF1 NmiHandler_OnNonzero6
8FFF NmiHandler_OnNonzero7
9049 NmiHandler_Loop17
DAEA NmiHandler_OnNonzero8
DB01 NmiHandler_Loop18
DB0E NmiHandler_Loop19
DB13 NmiHandler_Loop20
DB16 NmiHandler_OnNonzero9
DB19 NmiHandler_Loop21
DB32 NmiHandler_Loop22
DB3E Sub_DB3E
F831 Sub_F831
F852 Sub_F852
F858 Sub_F858
F85A NmiHandler_OnNonzero10
F86B NmiHandler_Loop23
F86C Sub_F86C
F873 Sub_F873
F879 Sub_F879
F87D Sub_F87D
F887 NmiHandler_OnCarrySet
F895 NmiHandler_OnCarrySet2
F8A6 NmiHandler_OnCarrySet3
F8B3 NmiHandler_OnCarrySet4
F8D2 NmiHandler_Loop24
F8D7 NmiHandler_Loop25
F8DC NmiHandler_Loop26
F8E7 Sub_F8E7
F8EF NmiHandler_Loop27
F8F0 Sub_F8F0
F902 NmiHandler_Loop28
F90F NmiHandler_Loop29
F910 NmiHandler_Loop30
F91D NmiHandler_Loop31
F928 NmiHandler_Loop32
F92A NmiHandler_OnCarrySet5
F93A NmiHandler_OnCarrySet6
F946 NmiHandler_Loop33
F948 NmiHandler_OnCarrySet7
F958 NmiHandler_OnCarrySet8
F966 NmiHandler_Loop34
F967 Sub_F967
F97E NmiHandler_Loop35
F9B9 NmiHandler_OnCarrySet9
F9BE NmiHandler_OnCarrySet10
F9C9 NmiHandler_OnCarrySet11
F9CE NmiHandler_OnCarrySet12
F9D7 NmiHandler_Loop36
F9D9 Sub_F9D9
F9F0 NmiHandler_Loop37
FA01 NmiHandler_Loop38
FA02 NmiHandler_Loop39
FA07 NmiHandler_Loop40
FA10 NmiHandler_Loop41
FA12 NmiHandler_Loop42
FA1B NmiHandler_Loop43
FA26 NmiHandler_Loop44
FA35 NmiHandler_Loop45
FA8A Sub_FA8A
FA98 NmiHandler_OnNonzero11
FABE NmiHandler_Loop46
FACD NmiHandler_Loop47
FADC NmiHandler_Loop48
FAEB NmiHandler_Loop49
FAF0 NmiHandler_Loop50
FAF5 NmiHandler_Loop51
FAF6 NmiHandler_Loop52
FB02 NmiHandler_Loop53
FB12 NmiHandler_Loop54
FB1A NmiHandler_Loop55
FB1C NmiHandler_OnCarryClear
FB20 NmiHandler_Loop56
FB22 NmiHandler_Loop57
FB3B NmiHandler_Loop58
FB3C Sub_FB3C
FB45 NmiHandler_Loop59
FB4D NmiHandler_Loop60
FB51 NmiHandler_OnZero
FB56 NmiHandler_OnNonzero12
FB68 NmiHandler_Loop61
FB6C NmiHandler_OnCarryClear2
FB70 NmiHandler_Loop62
FBA5 NmiHandler_Loop63
FBB6 NmiHandler_Loop64
FBBE NmiHandler_Loop65
FBC2 Sub_FBC2
FBD0 NmiHandler_Loop66
FBDC NmiHandler_Loop67
FBE8 NmiHandler_Loop68
FBF6 NmiHandler_Loop69
FBFE NmiHandler_Loop70
FC03 NmiHandler_Loop71
FC09 NmiHandler_Loop72
FC1B NmiHandler_Loop73
FC21 NmiHandler_Loop74
FC36 NmiHandler_Loop75
FC47 NmiHandler_Loop76
FC4C NmiHandler_Loop77
FC54 NmiHandler_Loop78
FC62 NmiHandler_Loop79
FC68 NmiHandler_Loop80
FC8C NmiHandler_Loop81
FC97 NmiHandler_Loop82
FCA8 NmiHandler_Loop83
FCAB NmiHandler_Loop84
FCD8 NmiHandler_Loop85
FCD9 Sub_FCD9
FCDF Sub_FCDF
1 8258 Reset
2 82D6 NmiHandler
3 # ---- derived internal branch-target names ----
4 8258 Reset
5 8262 Reset_OnCarryClear
6 8268 Reset_OnCarryClear2
7 8277 Reset_OnNonzero
8 8287 Reset_OnNonzero2
9 82A8 Reset_Loop
10 82AA Reset_OnNonzero3
11 82D3 Sub_82D3
12 82D6 NmiHandler
13 832E NmiHandler_Loop
14 8342 NmiHandler_OnNonnegative
15 8348 NmiHandler_Loop2
16 834D NmiHandler_Loop3
17 8360 NmiHandler_Loop4
18 837C NmiHandler_OnNonzero
19 8396 NmiHandler_Loop5
20 8399 NmiHandler_Loop6
21 83A7 Sub_83A7
22 83AB NmiHandler_OnNonzero2
23 83BD NmiHandler_Loop7
24 83CD NmiHandler_Loop8
25 83F0 Sub_83F0
26 83F5 NmiHandler_Loop9
27 83FF Sub_83FF
28 8436 NmiHandler_Loop10
29 88D4 Sub_88D4
30 88E9 Sub_88E9
31 88FA NmiHandler_Loop11
32 891D NmiHandler_Loop12
33 8920 NmiHandler_Loop13
34 8921 NmiHandler_Loop14
35 8925 NmiHandler_Loop15
36 8927 NmiHandler_Loop16
37 896A Sub_896A
38 8E25 Sub_8E25
39 8E34 Sub_8E34
40 8F6C Sub_8F6C
41 8F7B Sub_8F7B
42 8F97 NmiHandler_OnNonzero3
43 8FB1 NmiHandler_OnNonzero4
44 8FB8 Sub_8FB8
45 8FBE Sub_8FBE
46 8FC2 NmiHandler_OnNonzero5
47 8FC9 Sub_8FC9
48 8FDD Sub_8FDD
49 8FF1 NmiHandler_OnNonzero6
50 8FFF NmiHandler_OnNonzero7
51 9049 NmiHandler_Loop17
52 DAEA NmiHandler_OnNonzero8
53 DB01 NmiHandler_Loop18
54 DB0E NmiHandler_Loop19
55 DB13 NmiHandler_Loop20
56 DB16 NmiHandler_OnNonzero9
57 DB19 NmiHandler_Loop21
58 DB32 NmiHandler_Loop22
59 DB3E Sub_DB3E
60 F831 Sub_F831
61 F852 Sub_F852
62 F858 Sub_F858
63 F85A NmiHandler_OnNonzero10
64 F86B NmiHandler_Loop23
65 F86C Sub_F86C
66 F873 Sub_F873
67 F879 Sub_F879
68 F87D Sub_F87D
69 F887 NmiHandler_OnCarrySet
70 F895 NmiHandler_OnCarrySet2
71 F8A6 NmiHandler_OnCarrySet3
72 F8B3 NmiHandler_OnCarrySet4
73 F8D2 NmiHandler_Loop24
74 F8D7 NmiHandler_Loop25
75 F8DC NmiHandler_Loop26
76 F8E7 Sub_F8E7
77 F8EF NmiHandler_Loop27
78 F8F0 Sub_F8F0
79 F902 NmiHandler_Loop28
80 F90F NmiHandler_Loop29
81 F910 NmiHandler_Loop30
82 F91D NmiHandler_Loop31
83 F928 NmiHandler_Loop32
84 F92A NmiHandler_OnCarrySet5
85 F93A NmiHandler_OnCarrySet6
86 F946 NmiHandler_Loop33
87 F948 NmiHandler_OnCarrySet7
88 F958 NmiHandler_OnCarrySet8
89 F966 NmiHandler_Loop34
90 F967 Sub_F967
91 F97E NmiHandler_Loop35
92 F9B9 NmiHandler_OnCarrySet9
93 F9BE NmiHandler_OnCarrySet10
94 F9C9 NmiHandler_OnCarrySet11
95 F9CE NmiHandler_OnCarrySet12
96 F9D7 NmiHandler_Loop36
97 F9D9 Sub_F9D9
98 F9F0 NmiHandler_Loop37
99 FA01 NmiHandler_Loop38
100 FA02 NmiHandler_Loop39
101 FA07 NmiHandler_Loop40
102 FA10 NmiHandler_Loop41
103 FA12 NmiHandler_Loop42
104 FA1B NmiHandler_Loop43
105 FA26 NmiHandler_Loop44
106 FA35 NmiHandler_Loop45
107 FA8A Sub_FA8A
108 FA98 NmiHandler_OnNonzero11
109 FABE NmiHandler_Loop46
110 FACD NmiHandler_Loop47
111 FADC NmiHandler_Loop48
112 FAEB NmiHandler_Loop49
113 FAF0 NmiHandler_Loop50
114 FAF5 NmiHandler_Loop51
115 FAF6 NmiHandler_Loop52
116 FB02 NmiHandler_Loop53
117 FB12 NmiHandler_Loop54
118 FB1A NmiHandler_Loop55
119 FB1C NmiHandler_OnCarryClear
120 FB20 NmiHandler_Loop56
121 FB22 NmiHandler_Loop57
122 FB3B NmiHandler_Loop58
123 FB3C Sub_FB3C
124 FB45 NmiHandler_Loop59
125 FB4D NmiHandler_Loop60
126 FB51 NmiHandler_OnZero
127 FB56 NmiHandler_OnNonzero12
128 FB68 NmiHandler_Loop61
129 FB6C NmiHandler_OnCarryClear2
130 FB70 NmiHandler_Loop62
131 FBA5 NmiHandler_Loop63
132 FBB6 NmiHandler_Loop64
133 FBBE NmiHandler_Loop65
134 FBC2 Sub_FBC2
135 FBD0 NmiHandler_Loop66
136 FBDC NmiHandler_Loop67
137 FBE8 NmiHandler_Loop68
138 FBF6 NmiHandler_Loop69
139 FBFE NmiHandler_Loop70
140 FC03 NmiHandler_Loop71
141 FC09 NmiHandler_Loop72
142 FC1B NmiHandler_Loop73
143 FC21 NmiHandler_Loop74
144 FC36 NmiHandler_Loop75
145 FC47 NmiHandler_Loop76
146 FC4C NmiHandler_Loop77
147 FC54 NmiHandler_Loop78
148 FC62 NmiHandler_Loop79
149 FC68 NmiHandler_Loop80
150 FC8C NmiHandler_Loop81
151 FC97 NmiHandler_Loop82
152 FCA8 NmiHandler_Loop83
153 FCAB NmiHandler_Loop84
154 FCD8 NmiHandler_Loop85
155 FCD9 Sub_FCD9
156 FCDF Sub_FCDF
+10
View File
@@ -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;
}
+54
View File
@@ -0,0 +1,54 @@
; Kung Fu (U) (a1) 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.
Zp00 = $00 ; 28 refs; reads=13 writes=15; used at $8274, 8277, 8287, 82AA, +22 more
Zp01 = $01 ; 14 refs; reads=5 writes=9; used at $8270, 827C, 8282, 828C, +8 more
Zp02 = $02 ; 5 refs; reads=3 writes=2; used at $83DB, 83E9, 83EE, 8FF3, +1 more
Zp03 = $03 ; 5 refs; reads=2 writes=3; used at $83E1, 8FE9, 9012, 9014
Zp04 = $04 ; 1 refs; reads=0 writes=1; used at $8FEB
Zp10 = $10 ; 9 refs; reads=5 writes=4; used at $82D6, 82DD, 839F, 8E30, +5 more
Zp11 = $11 ; 2 refs; reads=1 writes=1; used at $8325, 832C
Zp12 = $12 ; 1 refs; reads=0 writes=1; used at $8FD2
Zp13 = $13 ; 1 refs; reads=0 writes=1; used at $8FD7
Zp14 = $14 ; 4 refs; reads=3 writes=1; used at $8381, 9020, 9028, 903B
Zp15 = $15 ; 4 refs; reads=2 writes=2; used at $88FF, 902A, 9031, 9047
Zp18 = $18 ; 3 refs; reads=2 writes=1; used at $8350, 8360
Zp19 = $19 ; 3 refs; reads=2 writes=1; used at $8356, 8362
Zp1A = $1A ; 2 refs; reads=1 writes=1; used at $8364
Zp1B = $1B ; 2 refs; reads=1 writes=1; used at $8366
Zp1C = $1C ; 2 refs; reads=1 writes=1; used at $8368
Zp1D = $1D ; 2 refs; reads=1 writes=1; used at $836A
Zp1E = $1E ; 2 refs; reads=1 writes=1; used at $836C
Zp1F = $1F ; 2 refs; reads=1 writes=1; used at $836E
Zp20 = $20 ; 4 refs; reads=1 writes=3; used at $8338, 833E, 8394
Zp21 = $21 ; 3 refs; reads=2 writes=1; used at $8342, 8346
Zp35 = $35 ; 3 refs; reads=1 writes=2; used at $8391, 83D0, 88D8
Zp49 = $49 ; 2 refs; reads=1 writes=1; used at $834B
Zp4F = $4F ; 4 refs; reads=2 writes=2; used at $83E3, 83E5, 88DE
Zp50 = $50 ; 3 refs; reads=2 writes=1; used at $8321, 83A7, 88DC
Zp51 = $51 ; 5 refs; reads=4 writes=1; used at $83B2, 83BD, 83D4, 88D4, +1 more
Zp52 = $52 ; 2 refs; reads=1 writes=1; used at $82F5, 831A
Zp5C = $5C ; 1 refs; reads=1 writes=0; used at $88F4
Zp5D = $5D ; 1 refs; reads=1 writes=0; used at $88F6
Zp63 = $63 ; 1 refs; reads=0 writes=1; used at $83F9
Zp66 = $66 ; 1 refs; reads=0 writes=1; used at $831C
Zp6F = $6F ; 3 refs; reads=1 writes=2; used at $83F5, 83FD, 88E6
ZpF0 = $F0 ; 8 refs; reads=4 writes=4; used at $FB6A, FBA3, FBAA, FBAC, +2 more
ZpF1 = $F1 ; 3 refs; reads=1 writes=2; used at $F8E2, F8F4, F902
ZpF2 = $F2 ; 6 refs; reads=3 writes=3; used at $F92A, F948, F95F, F96D, +2 more
ZpF3 = $F3 ; 2 refs; reads=1 writes=1; used at $FB4B, FBBC
ZpF4 = $F4 ; 5 refs; reads=3 writes=2; used at $FB8B, FC21, FC2A, FC2C
ZpF5 = $F5 ; 10 refs; reads=8 writes=2; used at $FB40, FB49, FB56, FBB6, +6 more
ZpF6 = $F6 ; 8 refs; reads=4 writes=4; used at $F889, F89C, F8A8, F8B3, +3 more
ZpF7 = $F7 ; 2 refs; reads=1 writes=1; used at $FB77, FCE2
ZpF8 = $F8 ; 8 refs; reads=5 writes=3; used at $FB86, FC68, FC71, FC73, +2 more
ZpF9 = $F9 ; 7 refs; reads=6 writes=1; used at $FB7C, FBAE, FBDA, FC2E, +3 more
ZpFA = $FA ; 1 refs; reads=0 writes=1; used at $FB81
ZpFB = $FB ; 3 refs; reads=1 writes=2; used at $8927, F84F, FB3C
ZpFC = $FC ; 10 refs; reads=5 writes=5; used at $F84D, F9D9, F9E0, F9E4, +2 more
ZpFD = $FD ; 2 refs; reads=1 writes=1; used at $F84B, FAF6
ZpFE = $FE ; 6 refs; reads=3 writes=3; used at $F849, F967, F972, F976
ZpFF = $FF ; 8 refs; reads=4 writes=4; used at $F847, F8F0, F8F6, F8FA, +1 more
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
# routinemap (seed)
8258 Reset
82D6 NmiHandler
1 # routinemap (seed)
2 8258 Reset
3 82D6 NmiHandler
+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