3.3 KiB
Pass 1 NMI callback audit
Dispatcher
The hardware NMI vector enters $C0A6. The fixed prologue saves A/X/Y, performs
OAM DMA from page $02, then executes JMP ($0002). Every installed callback
must therefore finish through the common epilogue at $C0B8 or deliberately
reset/restart the program.
$C888 is the generic installer:
- Y ->
$0002(callback low byte) - X ->
$0003(callback high byte) - PPU NMI remains enabled through the shadow value at
$00
Confirmed callback installations
$C6C8 installed at $C0EC
Caller loads Y=$C8, X=$C6, then calls $C888.
Role: early/main gameplay display callback. It updates OAM entries at
$0214-$0217 and $0284-$0287, advances animation counters $8E/$8F, and
terminates with JMP $C0B8.
$CFAA installed at $CF5C
Caller loads Y=$AA, X=$CF, then calls $C888.
Role: gameplay sequencing callback. It decrements/increments $32, updates OAM
coordinates, and changes the callback vector to one of the following mid-routine
continuations as state thresholds are crossed:
$CFC3$D03E$D08A
The routine ultimately reaches the gameplay display tail at $C6C8, which exits
through $C0B8.
$DAA2 installed at $DA27
Caller loads Y=$A2, X=$DA, then calls $C888.
Role: title/menu/attract controller callback. It polls controller port $4016,
updates $09/$0A/$0D, writes one OAM cursor entry at $0200-$0203, and either:
- jumps to
$C0B8for the normal NMI epilogue, - restarts title/game initialization through
$DA2F/$DA4C, or - restarts the initial state through
$C0C7.
Important correction: $DB0D (78 88 98) is used as OAM Y-position data for
$0200, not as an NMI callback-low-byte table. Consequently $BA78/$BA88/$BA98
are not callbacks.
$C5A0 installed at $FC8E
Caller loads Y=$A0, X=$C5, then calls $C888.
Role: active gameplay controller/animation callback. It serially reads $4016,
updates input-derived state $2E/$30, angle/selection fields $17/$44/$45, OAM
entries, and then enters $C6C8 before returning through $C0B8.
Direct callback-vector transitions
The following direct writes to $02/$03 are confirmed executable and are part
of the $CFAA-$D121 callback state machine:
$CFB6/$CFBA: install$CFC3$CFDA/$CFDE: install$D03E$D006/$D00A: install$D03E$D02B/$D02F: install$D08A$D05E/$D062: install$D08A$D07A/$D07E: install$D08A
These are mid-routine continuation entries, not independent top-level systems.
They share state in $17/$1D/$1E/$1F/$32/$34/$35 and converge on $C6C8.
Confirmed callback set
Top-level callback installations:
$C5A0$C6C8$CFAA$DAA2
Dynamic continuation callbacks:
$CFC3$D03E$D08A
Common normal exit:
$C0B8
No other verified executable write to $0002/$0003 has been found. Apparent
writes inside compressed hole packages are data and are excluded.
Source conversion
The previously retained callback spans are now emitted as annotated instructions:
$C5A0-$C71D: gameplay input/display callback chain$CFAA-$D123: gameplay sequence callback and dynamic continuation entries
The three bytes at $C71E-$C720 remain data because execution at $C71B jumps
directly to the NMI epilogue and cannot fall through into them.