Baseball Clu Clu Land Excitebike Pac-Man (Namco) Tennis Balloon Fight Bomberman (U) Burger Time (U) Defender 2 (U)
14333 lines
301 KiB
ArmAsm
14333 lines
301 KiB
ArmAsm
;----------------------------------------------------
|
|
; NES Specific
|
|
;----------------------------------------------------
|
|
|
|
; PPU registers
|
|
PPUCTRL = $2000
|
|
PPUMASK = $2001
|
|
PPUSTATUS = $2002
|
|
OAMADDR = $2003
|
|
OAMDATA = $2004
|
|
PPUSCROLL = $2005
|
|
PPUADDR = $2006
|
|
PPUDATA = $2007
|
|
OAMDMA = $4014
|
|
JOY1 = $4016
|
|
|
|
APUPC1BASE = $4000
|
|
APUPC1SWEEP = $4001
|
|
APUPC1TLOW = $4002
|
|
APUPC1THIGH = $4003
|
|
|
|
APUPC2BASE = $4004
|
|
APUPC2SWEEP = $4005
|
|
APUPC2LOW = $4006
|
|
APUPC2HIGH = $4007
|
|
|
|
APUTRIBASE = $4008
|
|
APUTRILOW = $400A
|
|
APUTRIHIGH = $400B
|
|
|
|
APUNOISEBASE = $400C
|
|
APUNOISELOOP = $400E
|
|
APUNOISELENGTH = $400F
|
|
|
|
APUDMABASE = $4010
|
|
APUDMALOAD = $4011
|
|
APUDMAADDR = $4012
|
|
APUDMALEN = $4013
|
|
|
|
APUCTRL = $4015
|
|
APUSTATUS = $4015
|
|
APUFRAMECNT = $4017
|
|
|
|
|
|
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
|
|
PAD_MENU_INPUT=PAD_SELECT|PAD_START|PAD_VERTICAL
|
|
|
|
;----------------------------------------------------
|
|
; Pacman Specific
|
|
;----------------------------------------------------
|
|
|
|
NmiHandlerOffset = $C10E
|
|
ResetOffset = $C033
|
|
IrqHandlerOffset = $C17E
|
|
|
|
;==============================================================================
|
|
; Zero Page
|
|
;==============================================================================
|
|
|
|
;------------------------------------------------------------------------------
|
|
; General work pointers / scratch
|
|
;------------------------------------------------------------------------------
|
|
|
|
workPtr0 = $00
|
|
workPtr1 = $02
|
|
|
|
workValue0 = $04
|
|
workValue1 = $05
|
|
workValue2 = $06
|
|
workValue3 = $07
|
|
workValue4 = $08
|
|
workValue5 = $09
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Maze pathfinding / direction selection workspace
|
|
;------------------------------------------------------------------------------
|
|
|
|
pathCompareValue = $0A
|
|
pathFallbackValue = $0B
|
|
legalDirections = $0C
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Indirect dispatcher vector
|
|
;------------------------------------------------------------------------------
|
|
|
|
dispatchVector = $10
|
|
|
|
;------------------------------------------------------------------------------
|
|
; 16-bit arithmetic workspace
|
|
;------------------------------------------------------------------------------
|
|
|
|
arithmeticValue = $12
|
|
arithmeticOperand = $14
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Actor fixed-point/motion records
|
|
;
|
|
; Each actor record occupies four bytes.
|
|
;------------------------------------------------------------------------------
|
|
|
|
pacmanMotion = $1A
|
|
ghost1Motion = $1E
|
|
ghost2Motion = $22
|
|
ghost3Motion = $26
|
|
ghost4Motion = $2A
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Pac-Man maze targeting
|
|
;------------------------------------------------------------------------------
|
|
|
|
pacmanTargetRow = $2E
|
|
pacmanTargetColumn = $30
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Sprite/animation selection
|
|
;------------------------------------------------------------------------------
|
|
|
|
pacmanSpriteFrame = $32
|
|
ghostSpriteFrames = $33
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Ghost direction/control state
|
|
;------------------------------------------------------------------------------
|
|
|
|
ghostDirectionFlags = $39
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Main gameplay state
|
|
;------------------------------------------------------------------------------
|
|
|
|
gameState = $3F
|
|
|
|
;------------------------------------------------------------------------------
|
|
; PPU / player-screen state
|
|
;------------------------------------------------------------------------------
|
|
|
|
ppuCtrlShadow = $43
|
|
|
|
cocktailModeFlag = $46
|
|
activePlayerFlag = $47
|
|
gameplaySuspended = $48
|
|
|
|
frameCounter = $4B
|
|
stateTimer = $4C
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Input / Pac-Man movement
|
|
;------------------------------------------------------------------------------
|
|
|
|
currentInput = $4D
|
|
newlyPressedInput = $4E
|
|
previousInput = $4F
|
|
|
|
pacmanRequestedDirection = $50
|
|
pacmanDirection = $51
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Score / round / maze progression
|
|
;------------------------------------------------------------------------------
|
|
|
|
highScoreDigits = $61
|
|
|
|
roundNumber = $67
|
|
roundDisplayValue = $68
|
|
|
|
pelletsRemaining = $6A
|
|
extraLifeAwarded = $6B
|
|
|
|
actorStatusDisplay = $6C
|
|
|
|
playerScoreDigits = $70
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Audio Engine
|
|
;------------------------------------------------------------------------------
|
|
audioRequestPtr = $F0
|
|
audioChannelTablePtr = $F2
|
|
audioSequenceTablePtr = $F4
|
|
audioWorkPtr = $F6
|
|
audioWorkValue = $F7
|
|
audioChannelFlags = $F8
|
|
audioRequestIndex = $FC
|
|
audioChannelOffset = $FD
|
|
audioIndirectPtr = $FE
|
|
|
|
.segment "PRG"
|
|
|
|
.org $C000
|
|
|
|
CopyrightText:
|
|
.byte $43,$4F,$50,$59,$20,$52,$49,$47
|
|
.byte $48,$54,$20,$31,$39,$38,$34,$20
|
|
.byte $31,$39,$39,$33,$20,$4E,$41,$4D
|
|
.byte $43,$4F,$20,$4C,$54,$44,$2E,$20
|
|
.byte $41,$4C,$4C,$20,$52,$49,$47,$48
|
|
.byte $54,$53,$20,$52,$45,$53,$45,$52
|
|
.byte $56,$45,$44
|
|
|
|
Reset:
|
|
ldx #$00
|
|
stx PPUCTRL
|
|
sei
|
|
cld
|
|
dex
|
|
txs
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
ldx #$02
|
|
|
|
@WaitForPpu:
|
|
lda #$06
|
|
sta PPUMASK
|
|
|
|
lda PPUSTATUS
|
|
|
|
@WaitVBlank:
|
|
lda PPUSTATUS
|
|
bpl @WaitVBlank
|
|
|
|
lda #$00
|
|
sta PPUSCROLL
|
|
sta PPUSCROLL
|
|
dex
|
|
bne @WaitForPpu
|
|
|
|
lda #$00
|
|
tay
|
|
|
|
@ClearLowRam:
|
|
sta $0000,y
|
|
iny
|
|
cpy #$3E
|
|
bne @ClearLowRam
|
|
|
|
ldx #$08
|
|
ldy #$87
|
|
|
|
@ClearRamPages:
|
|
sta ($00),y
|
|
iny
|
|
bne @ClearRamPages
|
|
inc $01
|
|
cpx $01
|
|
bne @ClearRamPages
|
|
|
|
lda #$06
|
|
sta PPUMASK
|
|
|
|
lda #$00
|
|
sta PPUSCROLL
|
|
sta PPUSCROLL
|
|
sta $41
|
|
sta $42
|
|
sta PPUCTRL
|
|
sta PPUMASK
|
|
tay
|
|
|
|
@CheckRamSignature:
|
|
lda RamSignature,y
|
|
cmp $0052,y
|
|
bne @InitializeRamSignature
|
|
|
|
iny
|
|
cpy #$0F
|
|
bne @CheckRamSignature
|
|
|
|
beq @SignatureAlreadyPresent
|
|
|
|
@InitializeRamSignature:
|
|
lda #$00
|
|
tay
|
|
|
|
@ClearZeroPage:
|
|
sta $0000,y
|
|
iny
|
|
bne @ClearZeroPage
|
|
|
|
ldy #$00
|
|
|
|
@CopyRamSignature:
|
|
lda RamSignature,y
|
|
sta $0052,y
|
|
iny
|
|
cpy #$0F
|
|
bne @CopyRamSignature
|
|
|
|
lda #$01
|
|
sta $64
|
|
|
|
@SignatureAlreadyPresent:
|
|
ldy #$00
|
|
sty $3F
|
|
|
|
lda #$07
|
|
sta $45
|
|
lda #$01
|
|
cmp $47
|
|
bne @SkipSwap
|
|
|
|
cmp $46
|
|
bne @SkipSwap
|
|
|
|
@SwapLoop:
|
|
lda $77,y
|
|
sta workPtr0
|
|
|
|
lda $67,y
|
|
sta $77,y
|
|
|
|
lda workPtr0
|
|
sta $67,y
|
|
|
|
iny
|
|
cpy #$10
|
|
bne @SwapLoop
|
|
|
|
@SkipSwap:
|
|
lda #$1F
|
|
sta APUCTRL
|
|
|
|
lda #$C0
|
|
sta APUFRAMECNT
|
|
|
|
jsr InitializeAudioEngine
|
|
jsr $EEB4
|
|
|
|
lda #$88
|
|
sta $43
|
|
sta PPUCTRL
|
|
|
|
lda #$FF
|
|
sta $48
|
|
sta $023F
|
|
sta $024B
|
|
|
|
jmp MainEntry
|
|
|
|
RamSignature:
|
|
.byte "HIROKI AOYAGI"
|
|
.byte $AA, $55
|
|
|
|
;==============================================================================
|
|
; $C10E-$C17E: NMI Handler
|
|
;
|
|
; Local:
|
|
; Handles the per-frame NMI. Saves the CPU registers, configures the PPU,
|
|
; performs sprite OAM DMA, calls several frame-processing routines, restores
|
|
; the current scroll and PPU control state, polls both controllers, selects
|
|
; the active controller input, and conditionally performs additional
|
|
; per-frame processing.
|
|
;
|
|
; Global:
|
|
; Primary VBlank/frame interrupt entry point. This routine ties together
|
|
; rendering updates, sprite DMA, controller polling, and other work that
|
|
; needs to occur once per video frame.
|
|
;
|
|
; Notes:
|
|
; $41/$42 are used as the two PPUSCROLL writes.
|
|
; $45 supplies the source page for OAM DMA.
|
|
; $4D/$4E receive controller 1/2 input bits.
|
|
; $4F receives the controller state selected by $46/$47.
|
|
;
|
|
; The purposes of $40-$48 and the called routines at FlushGameplayPpuUpdates
|
|
; ReadNearbyNametableTiles, UpdatePalettes, and InitializeAudioChannels will
|
|
; be refined during later passes.
|
|
;==============================================================================
|
|
|
|
NmiHandler:
|
|
pha
|
|
txa
|
|
pha
|
|
tya
|
|
pha
|
|
|
|
lda #$1E
|
|
sta PPUMASK
|
|
|
|
lda #$00
|
|
sta OAMADDR
|
|
sta $40
|
|
|
|
lda $45
|
|
sta OAMDMA
|
|
|
|
jsr FlushGameplayPpuUpdates
|
|
jsr ReadNearbyNametableTiles
|
|
jsr UpdatePalettes
|
|
|
|
; Restore the two PPU scroll components.
|
|
lda $41
|
|
sta PPUSCROLL
|
|
|
|
lda $42
|
|
sta PPUSCROLL
|
|
|
|
; Construct the PPUCTRL value for this frame.
|
|
lda $47
|
|
and $46
|
|
and #$01
|
|
asl
|
|
ora $43
|
|
sta PPUCTRL
|
|
|
|
; Strobe the controller ports.
|
|
lda #$01
|
|
sta JOY1
|
|
|
|
lda #$00
|
|
sta JOY1
|
|
|
|
; Read eight serial bits from both controllers.
|
|
ldx #$08
|
|
|
|
@ReadControllers:
|
|
lda JOY1
|
|
and #$03
|
|
cmp #$01
|
|
ror $4D
|
|
|
|
lda APUFRAMECNT
|
|
and #$03
|
|
cmp #$01
|
|
ror $4E
|
|
|
|
dex
|
|
bne @ReadControllers
|
|
|
|
; Controller 1 is the default input source.
|
|
ldx currentInput
|
|
|
|
; Under the condition controlled by $46/$47,
|
|
; use controller 2 instead.
|
|
lda cocktailModeFlag
|
|
and activePlayerFlag
|
|
beq @ControllerSelected
|
|
|
|
ldx newlyPressedInput
|
|
|
|
@ControllerSelected:
|
|
stx previousInput
|
|
|
|
; Advance a per-frame counter.
|
|
inc frameCounter
|
|
|
|
; $48 gates an additional per-frame routine.
|
|
lda $48
|
|
bne @NmiDone
|
|
|
|
jsr InitializeAudioChannels
|
|
|
|
@NmiDone:
|
|
pla
|
|
tay
|
|
pla
|
|
tax
|
|
pla
|
|
IrqHandler:
|
|
rti
|
|
|
|
UpdatePalettes:
|
|
lda $0299
|
|
cmp #$0F
|
|
bne @CheckSecondPalette
|
|
|
|
lda PPUSTATUS
|
|
lda #$3F
|
|
sta PPUADDR
|
|
lda #$00
|
|
sta PPUADDR
|
|
|
|
ldy #$00
|
|
|
|
@CopyFirstPalette:
|
|
lda $0299,y
|
|
sta PPUDATA
|
|
iny
|
|
cpy #$10
|
|
bne @CopyFirstPalette
|
|
|
|
@CheckSecondPalette:
|
|
lda $02A9
|
|
cmp #$0F
|
|
bne @CheckPaletteState
|
|
|
|
lda PPUSTATUS
|
|
lda #$3F
|
|
sta PPUADDR
|
|
lda #$10
|
|
sta PPUADDR
|
|
|
|
ldy #$00
|
|
|
|
@CopySecondPalette:
|
|
lda $02A9,y
|
|
sta PPUDATA
|
|
iny
|
|
cpy #$10
|
|
bne @CopySecondPalette
|
|
|
|
@CheckPaletteState:
|
|
lda $0299
|
|
cmp #$0F
|
|
beq @ResetPpuAddress
|
|
|
|
lda $02A9
|
|
cmp #$0F
|
|
beq @ResetPpuAddress
|
|
|
|
rts
|
|
|
|
@ResetPpuAddress:
|
|
lda #$30
|
|
sta PPUADDR
|
|
|
|
lda #$00
|
|
sta PPUADDR
|
|
sta PPUADDR
|
|
sta PPUADDR
|
|
|
|
sta $0299
|
|
sta $02A9
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $C1E7-$C266: Main Initialization and State Dispatch
|
|
;
|
|
; Local:
|
|
; Synchronizes with the NMI through $40, initializes PPU/OAM and several
|
|
; game-state variables, calls four initialization routines, initializes the
|
|
; two 16-byte palette buffers, then enters the main state-dispatch loop.
|
|
;
|
|
; The loop synchronizes with NMI again, uses $3F as an index into a table of
|
|
; five handler addresses, stores the selected address in $10/$11, and jumps
|
|
; to that handler indirectly.
|
|
;
|
|
; Global:
|
|
; This is the main program entry reached from Reset after hardware and RAM
|
|
; initialization. It transitions the game into its normal frame-driven state
|
|
; machine. NMI clears $40 each frame, allowing the foreground/main code to
|
|
; proceed through its next state-machine update.
|
|
;
|
|
; Notes:
|
|
; $40 clearly provides synchronization between foreground code and NMI.
|
|
; Writing $01 to $40 and spinning until NMI clears it forms a frame wait.
|
|
;
|
|
; $3F is used here as a state/dispatch index. Its exact semantic states will
|
|
; be named as the individual handlers are decoded.
|
|
;
|
|
; $10/$11 form a temporary indirect JMP pointer.
|
|
;
|
|
; $C267 begins the state-handler address table and is intentionally left for
|
|
; the next decoding pass.
|
|
;==============================================================================
|
|
|
|
MainEntry:
|
|
lda #$01
|
|
sta $40
|
|
|
|
@WaitForInitialNmi:
|
|
lda $40
|
|
bne @WaitForInitialNmi
|
|
|
|
lda #$08
|
|
sta PPUCTRL
|
|
sta ppuCtrlShadow
|
|
|
|
lda PPUSTATUS
|
|
|
|
lda #$00
|
|
sta PPUMASK
|
|
|
|
tax
|
|
|
|
@ClearOamPage:
|
|
sta $0700,x
|
|
inx
|
|
bne @ClearOamPage
|
|
|
|
sta cocktailModeFlag
|
|
|
|
jsr ClearGameplayNametables
|
|
jsr InitializeNametableAttributes
|
|
jsr InitializeNametableData
|
|
jsr $E419
|
|
|
|
ldy #$00
|
|
|
|
@InitializePaletteBuffers:
|
|
lda TitleScreenPalette,y
|
|
sta $0299,y
|
|
iny
|
|
cpy #$20
|
|
bne @InitializePaletteBuffers
|
|
|
|
lda #$2D
|
|
sta actorStatusDisplay
|
|
sta actorStatusDisplay+1
|
|
sta actorStatusDisplay+2
|
|
sta actorStatusDisplay+3
|
|
|
|
lda #$FF
|
|
sta $023F
|
|
sta gameplaySuspended
|
|
|
|
lda #$00
|
|
sta activePlayerFlag
|
|
sta cocktailModeFlag
|
|
sta $42
|
|
sta $41
|
|
sta stateTimer
|
|
sta $87
|
|
sta $88
|
|
|
|
lda gameState
|
|
bne @UseAlternatePpuCtrl
|
|
|
|
lda #$8A
|
|
bne @SetPpuCtrl
|
|
|
|
@UseAlternatePpuCtrl:
|
|
lda #$88
|
|
|
|
@SetPpuCtrl:
|
|
sta PPUCTRL
|
|
sta ppuCtrlShadow
|
|
|
|
MainDispatchLoop:
|
|
lda #$01
|
|
sta $40
|
|
|
|
@WaitForNmi:
|
|
lda $40
|
|
bne @WaitForNmi
|
|
|
|
ldy gameState
|
|
|
|
lda $C267,y
|
|
sta dispatchVector
|
|
|
|
lda $C268,y
|
|
sta dispatchVector+1
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $C267-$C26E: Main State Dispatch Table
|
|
;
|
|
; Local:
|
|
; Four 16-bit addresses used by the indirect state dispatcher at the end of
|
|
; MainEntry. $3F is used directly as a byte offset into this table:
|
|
;
|
|
; lda MainStateHandlerTable,y
|
|
; sta $10
|
|
; lda MainStateHandlerTable+1,y
|
|
; sta $11
|
|
; jmp ($0010)
|
|
;
|
|
; This implies the normal state values in $3F are even byte offsets:
|
|
; $00, $02, $04, $06
|
|
;
|
|
; Global:
|
|
; Selects one of four major foreground/game-state handlers. This is the
|
|
; top-level state machine entered after Reset initialization and synchronized
|
|
; to the NMI-driven frame loop.
|
|
;
|
|
; Notes:
|
|
; The four targets are:
|
|
; InitialStateHandler
|
|
; PlayerSelectionState
|
|
; State04Handler
|
|
; TimedStateTransition
|
|
;
|
|
; Handler names remain provisional until each target is decoded.
|
|
;==============================================================================
|
|
|
|
MainStateHandlerTable:
|
|
.word InitialStateHandler
|
|
.word PlayerSelectionState
|
|
.word State04Handler
|
|
.word TimedStateTransition
|
|
|
|
;==============================================================================
|
|
; $C26F-$C279: Timed State Transition Handler
|
|
;
|
|
; Local:
|
|
; Decrements the counter at $0F once per frame. While the counter remains
|
|
; nonzero, control returns to the common NMI synchronization/dispatch loop
|
|
; at $C250.
|
|
;
|
|
; When the counter reaches zero, changes the main state offset at $3F to
|
|
; $02 and then returns to the same dispatch loop.
|
|
;
|
|
; Global:
|
|
; Implements the handler selected when the main state offset is $06.
|
|
; This appears to be a timed transitional state. Another state places a
|
|
; duration in $0F and selects state $06; this handler counts that duration
|
|
; down before advancing to state $02.
|
|
;
|
|
; Notes:
|
|
; $0F is clearly being used as a countdown timer here, but its broader use
|
|
; should be traced before assigning it a permanent global name.
|
|
;
|
|
; $3F is the byte offset into MainStateHandlerTable:
|
|
; $00 -> InitialStateHandler
|
|
; $02 -> PlayerSelectionState
|
|
; $04 -> State04Handler
|
|
; $06 -> this handler
|
|
;
|
|
; $C250 is inside MainEntry and is the common frame synchronization point.
|
|
;==============================================================================
|
|
|
|
TimedStateTransition:
|
|
dec $0F
|
|
bne MainDispatchLoop
|
|
|
|
lda #$02
|
|
sta gameState
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
|
|
;==============================================================================
|
|
; $C27A-$C2A5: Initial/Input State Handler
|
|
;
|
|
; Local:
|
|
; Checks controller-1 state bits $0C. If either bit is set, selects state
|
|
; $06, initializes the countdown at $0F to $5A, and jumps back to MainEntry.
|
|
;
|
|
; Otherwise increments $42. When $42 reaches $F0, resets it to zero,
|
|
; changes the saved PPUCTRL value at $43 to $88, and selects state $06
|
|
; with the same $5A countdown.
|
|
;
|
|
; If $42 has not yet reached $F0, the initialization of state $06 is
|
|
; skipped and execution reaches the common JMP back to MainDispatchLoop.
|
|
;
|
|
; Global:
|
|
; Handler selected by main state offset $00. It appears to manage an early
|
|
; or attract/input-wait state, transitioning into the timed state either
|
|
; because of controller input or because the scrolling/progression value
|
|
; at $42 reaches $F0.
|
|
;
|
|
; Notes:
|
|
; $4D is controller-1 input assembled by NmiHandler.
|
|
; $42 is also used as the second PPUSCROLL write during NMI.
|
|
; Exact game-state semantics will be refined in later passes.
|
|
;==============================================================================
|
|
|
|
InitialStateHandler:
|
|
lda currentInput
|
|
and #$0C
|
|
beq @AdvanceScroll
|
|
|
|
lda #$06
|
|
sta gameState
|
|
|
|
lda #$5A
|
|
sta $0F
|
|
|
|
jmp MainEntry
|
|
|
|
@AdvanceScroll:
|
|
inc $42
|
|
|
|
lda #$F0
|
|
cmp $42
|
|
bne @ReturnToMainLoop
|
|
|
|
lda #$00
|
|
sta $42
|
|
|
|
lda #$88
|
|
sta ppuCtrlShadow
|
|
|
|
lda #$06
|
|
sta gameState
|
|
|
|
lda #$5A
|
|
sta $0F
|
|
|
|
@ReturnToMainLoop:
|
|
jmp MainDispatchLoop
|
|
|
|
;==============================================================================
|
|
; $C2A6-$C30A: Initialize Nametable Data
|
|
;
|
|
; Local:
|
|
; Performs two groups of PPU writes used during initial screen setup.
|
|
;
|
|
; First phase:
|
|
; - Begins at PPU address $20E5.
|
|
; - Copies $17 bytes from the ROM data at TitleScreenTileBlock
|
|
; - Repeats this for six rows.
|
|
; - Advances the destination PPU address by $20 after each row.
|
|
;
|
|
; Second phase:
|
|
; - Processes nine variable-length PPU update records beginning at $C3B0.
|
|
; - Each record supplies a two-byte PPU address followed by data bytes.
|
|
; - $FF terminates the data portion of each record.
|
|
;
|
|
; Global:
|
|
; Called from MainEntry during initial game setup. This routine constructs
|
|
; part of the initial nametable/display before normal state dispatch begins.
|
|
;
|
|
; Notes:
|
|
; $00/$01 are used here as a 16-bit PPU destination address.
|
|
; $02 counts the six repeated rows.
|
|
; $03 counts $17 bytes within each row.
|
|
;
|
|
; TitleScreenTileBlock is a repeated row of tile data.
|
|
; $C3B0 contains nine encoded PPU update records.
|
|
;
|
|
; These ROM data blocks will be named more precisely when their contents
|
|
; and resulting screen regions are decoded in later passes.
|
|
;==============================================================================
|
|
|
|
InitializeNametableData:
|
|
; Initial PPU destination = $20E5.
|
|
lda #$20
|
|
sta workPtr0
|
|
|
|
lda #$E5
|
|
sta workPtr0+1
|
|
|
|
; Write six rows.
|
|
lda #$06
|
|
sta workPtr1
|
|
|
|
ldy #$00
|
|
|
|
@WriteRow:
|
|
lda PPUSTATUS
|
|
|
|
lda workPtr0
|
|
sta PPUADDR
|
|
|
|
lda workPtr0+1
|
|
sta PPUADDR
|
|
|
|
; Each row contains $17 bytes.
|
|
lda #$17
|
|
sta workPtr1+1
|
|
|
|
@WriteRowBytes:
|
|
lda TitleScreenTileBlock,y
|
|
sta PPUDATA
|
|
|
|
iny
|
|
|
|
dec workPtr1+1
|
|
bne @WriteRowBytes
|
|
|
|
; Advance the PPU destination by $20.
|
|
lda workPtr0+1
|
|
clc
|
|
adc #$20
|
|
sta workPtr0+1
|
|
|
|
lda #$00
|
|
adc workPtr0
|
|
sta workPtr0
|
|
|
|
dec workPtr1
|
|
bne @WriteRow
|
|
|
|
; Process nine additional encoded PPU update records.
|
|
lda #$09
|
|
sta workPtr0
|
|
|
|
ldy #$00
|
|
|
|
@NextPpuRecord:
|
|
lda PPUSTATUS
|
|
|
|
; First two bytes of each record are the PPU destination address.
|
|
lda TitleScreenPpuRecords,y
|
|
sta PPUADDR
|
|
iny
|
|
|
|
lda TitleScreenPpuRecords,y
|
|
sta PPUADDR
|
|
iny
|
|
|
|
@WritePpuRecord:
|
|
lda TitleScreenPpuRecords,y
|
|
cmp #$FF
|
|
beq @EndPpuRecord
|
|
|
|
sta PPUDATA
|
|
iny
|
|
bne @WritePpuRecord
|
|
|
|
@EndPpuRecord:
|
|
iny
|
|
|
|
dec workPtr0
|
|
bne @NextPpuRecord
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $C30B-$C325: Initialize Nametable Attributes
|
|
;
|
|
; Local:
|
|
; Writes $18 bytes from TitleScreenAttributeData to PPU address $23C8.
|
|
;
|
|
; Global:
|
|
; Initializes a portion of the nametable attribute table during startup.
|
|
;==============================================================================
|
|
|
|
InitializeNametableAttributes:
|
|
lda PPUSTATUS
|
|
|
|
lda #$23
|
|
sta PPUADDR
|
|
|
|
lda #$C8
|
|
sta PPUADDR
|
|
|
|
ldy #$00
|
|
|
|
@CopyAttributes:
|
|
lda TitleScreenAttributeData,y
|
|
sta PPUDATA
|
|
|
|
iny
|
|
cpy #$18
|
|
bne @CopyAttributes
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $C326-$C3AF: Initial Nametable Tile Block
|
|
;
|
|
; Local:
|
|
; Contains six rows of $17 (23) tile indices. InitializeNametableData copies
|
|
; these rows sequentially to the PPU beginning at $20E5, advancing the PPU
|
|
; destination by $20 after each row.
|
|
;
|
|
; Destination layout:
|
|
; Row 0 -> $20E5-$20FB
|
|
; Row 1 -> $2105-$211B
|
|
; Row 2 -> $2125-$213B
|
|
; Row 3 -> $2145-$215B
|
|
; Row 4 -> $2165-$217B
|
|
; Row 5 -> $2185-$219B
|
|
;
|
|
; Global:
|
|
; Forms a rectangular portion of the initial nametable display constructed
|
|
; during MainEntry. The first and last rows consist primarily of border
|
|
; tiles, while the middle four rows contain the interior graphic/tile data.
|
|
;
|
|
; Notes:
|
|
; Each row is exactly $17 bytes.
|
|
;
|
|
; Tile values are left numeric during this pass. Their visual meanings can
|
|
; be determined later from the CHR-ROM and assigned symbolic tile names if
|
|
; useful.
|
|
;==============================================================================
|
|
|
|
TitleScreenTileBlock:
|
|
; Row 0 -> PPU $20E5-$20FB
|
|
.byte $E4,$E8,$E8,$E8,$E8,$E8,$E8,$E8
|
|
.byte $E8,$E8,$E8,$E8,$E8,$E8,$E8,$E8
|
|
.byte $E8,$E8,$E8,$E8,$E8,$E8,$E5
|
|
|
|
; Row 1 -> PPU $2105-$211B
|
|
.byte $EB,$88,$80,$81,$82,$83,$84,$85
|
|
.byte $86,$87,$88,$88,$89,$8A,$8B,$8C
|
|
.byte $8D,$8E,$8F,$90,$91,$A3,$E9
|
|
|
|
; Row 2 -> PPU $2125-$213B
|
|
.byte $EB,$88,$92,$93,$94,$95,$96,$97
|
|
.byte $98,$99,$9A,$9B,$9C,$9D,$9E,$9F
|
|
.byte $A0,$A1,$A2,$A3,$A4,$A3,$E9
|
|
|
|
; Row 3 -> PPU $2145-$215B
|
|
.byte $EB,$88,$92,$A5,$A6,$A7,$A8,$A9
|
|
.byte $AA,$AB,$AC,$AD,$AE,$A3,$AF,$D0
|
|
.byte $D1,$D2,$A3,$D3,$A4,$A3,$E9
|
|
|
|
; Row 4 -> PPU $2165-$217B
|
|
.byte $EB,$88,$D4,$D5,$D6,$D7,$D8,$D9
|
|
.byte $DA,$DB,$88,$88,$DC,$D7,$DD,$DE
|
|
.byte $DF,$E0,$E1,$E2,$E3,$A3,$E9
|
|
|
|
; Row 5 -> PPU $2185-$219B
|
|
.byte $E7,$EA,$EA,$EA,$EA,$EA,$EA,$EA
|
|
.byte $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
|
|
.byte $EA,$EA,$EA,$EA,$EA,$EA,$E6
|
|
|
|
;==============================================================================
|
|
; $C3B0-$C43E: Initial Screen PPU Records
|
|
;
|
|
; Local:
|
|
; Nine variable-length PPU write records consumed by InitializeNametableData.
|
|
; Each record has the form:
|
|
;
|
|
; .byte PPU address high
|
|
; .byte PPU address low
|
|
; .byte tile data...
|
|
; .byte $FF
|
|
;
|
|
; InitializeNametableData processes exactly nine records. For each record it
|
|
; loads the two-byte destination into PPUADDR and copies tile values to
|
|
; PPUDATA until the $FF terminator is encountered.
|
|
;
|
|
; Global:
|
|
; Supplies additional initial-screen graphics and text after the main
|
|
; six-row tile block has been installed. These records include player-count
|
|
; selections and copyright/licensing text as represented by the ROM's
|
|
; nametable tile values.
|
|
;
|
|
; Notes:
|
|
; Many values correspond directly to ASCII character codes, but not all do.
|
|
; Preserve the original tile bytes rather than converting these records to
|
|
; assembler strings during this pass.
|
|
;
|
|
; $FF is structural and is not written to PPUDATA.
|
|
;==============================================================================
|
|
|
|
TitleScreenPpuRecords:
|
|
;------------------------------------------------------------------------------
|
|
; Record 0: $C3B0-$C3C7
|
|
; PPU destination: $2065
|
|
; Data length: $15 (21) tiles
|
|
;------------------------------------------------------------------------------
|
|
.byte $20,$65
|
|
.byte $B0,$B3,$B2,$20,$20,$20,$20
|
|
.byte $B4,$B5,$B6,$B7,$B8,$B9,$BA,$BB
|
|
.byte $20,$20,$20,$B1,$B3,$B2
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Record 1: $C3C8-$C3D2
|
|
; PPU destination: $220C
|
|
; Data length: $08
|
|
;
|
|
; Visible tile values correspond to:
|
|
; "1 PLAYER"
|
|
;------------------------------------------------------------------------------
|
|
.byte $22,$0C
|
|
.byte $31,$20,$50,$4C,$41,$59,$45,$52
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Record 2: $C3D3-$C3DE
|
|
; PPU destination: $224C
|
|
; Data length: $09
|
|
;
|
|
; Visible tile values correspond to:
|
|
; "2 PLAYERS"
|
|
;------------------------------------------------------------------------------
|
|
.byte $22,$4C
|
|
.byte $32,$20,$50,$4C,$41,$59,$45,$52,$53
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Record 3: $C3DF-$C3FC
|
|
; PPU destination: $22E3
|
|
; Data length: $1B (27)
|
|
;
|
|
; Mostly text-like tile data containing the original copyright/date/NAMCO
|
|
; display. Special tile values are retained numerically.
|
|
;------------------------------------------------------------------------------
|
|
.byte $22,$E3
|
|
.byte $54,$4D,$20,$CC,$20,$5D
|
|
.byte $20,$31,$39,$38,$30
|
|
.byte $20,$31,$39,$39,$33
|
|
.byte $20,$4E,$41,$4D,$43,$4F
|
|
.byte $20,$4C,$54,$44,$5B
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Record 4: $C3FD-$C411
|
|
; PPU destination: $2327
|
|
; Data length: $12 (18)
|
|
;
|
|
; Mostly text-like tile data containing:
|
|
; NAMCO HOMETEK ... INC
|
|
;
|
|
; Special tile values remain numeric.
|
|
;------------------------------------------------------------------------------
|
|
.byte $23,$27
|
|
.byte $4E,$41,$4D,$43,$4F,$20
|
|
.byte $48,$4F,$4D,$45,$54,$45,$4B
|
|
.byte $CD
|
|
.byte $49,$4E,$43
|
|
.byte $5B
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Record 5: $C412-$C428
|
|
; PPU destination: $2366
|
|
; Data length: $14 (20)
|
|
;
|
|
; Tile values correspond to:
|
|
; "LICENSED BY NINTENDO"
|
|
;------------------------------------------------------------------------------
|
|
.byte $23,$66
|
|
.byte $4C,$49,$43,$45,$4E,$53,$45,$44
|
|
.byte $20
|
|
.byte $42,$59
|
|
.byte $20
|
|
.byte $4E,$49,$4E,$54,$45,$4E,$44,$4F
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Record 6: $C429-$C42D
|
|
; PPU destination: $2293
|
|
; Data length: $02
|
|
;------------------------------------------------------------------------------
|
|
.byte $22,$93
|
|
.byte $CE,$CF
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Record 7: $C42E-$C439
|
|
; PPU destination: $22AC
|
|
; Data length: $09
|
|
;------------------------------------------------------------------------------
|
|
.byte $22,$AC
|
|
.byte $23,$24,$25,$26,$27,$28,$29,$2A,$2B
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Record 8: $C43A-$C43E
|
|
; PPU destination: $20FC
|
|
; Data length: $02
|
|
;------------------------------------------------------------------------------
|
|
.byte $20,$FC
|
|
.byte $0E,$0F
|
|
.byte $FF
|
|
|
|
|
|
;==============================================================================
|
|
; $C43F-$C45E: Initial Palette Data
|
|
;
|
|
; Local:
|
|
; Contains $20 bytes copied to RAM $0299-$02B8 during MainEntry. The first
|
|
; $10 bytes feed PPU palette $3F00-$3F0F and the second $10 bytes feed
|
|
; $3F10-$3F1F through UpdatePalettes.
|
|
;
|
|
; Global:
|
|
; Defines the initial background and sprite palette configuration.
|
|
;
|
|
; Notes:
|
|
; Palette values remain numeric during this pass.
|
|
;==============================================================================
|
|
|
|
TitleScreenPalette:
|
|
|
|
; Background palettes
|
|
.byte $0F,$20,$0F,$06
|
|
.byte $0F,$26,$20,$27
|
|
.byte $0F,$06,$0F,$26
|
|
.byte $0F,$06,$20,$26
|
|
|
|
; Sprite palettes
|
|
.byte $0F,$27,$20,$06
|
|
.byte $0F,$11,$20,$33
|
|
.byte $0F,$20,$20,$21
|
|
.byte $0F,$09,$20,$17
|
|
|
|
|
|
;==============================================================================
|
|
; $C45F-$C476: Initial Nametable Attribute Data
|
|
;
|
|
; Local:
|
|
; Contains $18 attribute bytes copied by InitializeNametableAttributes to
|
|
; PPU $23C8-$23DF.
|
|
;
|
|
; Global:
|
|
; Defines background-palette selections for part of the initial nametable
|
|
; display.
|
|
;
|
|
; Notes:
|
|
; Attribute bytes remain raw during this first pass.
|
|
;==============================================================================
|
|
|
|
TitleScreenAttributeData:
|
|
.byte $80,$A0,$A0,$A0,$A0,$A0,$A0,$00
|
|
.byte $00,$66,$55,$55,$55,$55,$DD,$00
|
|
.byte $08,$0A,$0A,$0A,$0A,$0A,$0A,$00
|
|
|
|
;==============================================================================
|
|
; $C477-$C506: Player Selection State Handler
|
|
;
|
|
; Local:
|
|
; Handles input and display updates for the player-count selection state.
|
|
;
|
|
; On first entry, identified by $87/$88 both being zero, copies a small
|
|
; display-data sequence from $C507 to RAM beginning at $024B and captures
|
|
; the current controller states for bits $04 and $08.
|
|
;
|
|
; $87/$88 form a 16-bit counter that advances once per frame. When its high
|
|
; byte reaches $02, the counter is reset and the main state changes to $04.
|
|
;
|
|
; During normal processing:
|
|
; - Detects changes to controller bit $04.
|
|
; - When that bit becomes active, toggles $47 between 0 and 1 and changes
|
|
; display data associated with the selected player count.
|
|
; - Detects changes to controller bit $08.
|
|
; - When bit $08 becomes active, clears $48, calls $EEB4, and jumps to
|
|
; GameModeEntry.
|
|
;
|
|
; Global:
|
|
; Handler selected by MainStateHandlerTable when $3F = $02. The surrounding PPU
|
|
; data and controller behavior strongly indicate that this state implements
|
|
; the "1 PLAYER" / "2 PLAYERS" selection screen.
|
|
;
|
|
; If no selection completes within the $87/$88 timeout, execution advances
|
|
; automatically to main state $04.
|
|
;
|
|
; Notes:
|
|
; $50 stores the previous masked state of controller bit $04.
|
|
; $51 stores the previous masked state of controller bit $08.
|
|
;
|
|
; $87/$88 act as a 16-bit frame counter in this state.
|
|
;
|
|
; $47 is toggled between 0 and 1 when the $04 input becomes active. This
|
|
; strongly suggests it represents the current 1-player/2-player selection,
|
|
; but the name should be confirmed through later consumers.
|
|
;
|
|
; $C507 begins an adjacent display-data table consumed during state entry.
|
|
;==============================================================================
|
|
|
|
PlayerSelectionState:
|
|
lda $87
|
|
ora $88
|
|
bne @AdvanceTimeout
|
|
|
|
ldy #$00
|
|
|
|
@InitializeDisplayData:
|
|
lda PlayerCountSelectionDisplayData,y
|
|
sta $024B,y
|
|
iny
|
|
cmp #$FF
|
|
bne @InitializeDisplayData
|
|
|
|
lda currentInput
|
|
and #$04
|
|
sta pacmanRequestedDirection
|
|
|
|
lda currentInput
|
|
and #$08
|
|
sta pacmanDirection
|
|
|
|
@AdvanceTimeout:
|
|
clc
|
|
lda #$01
|
|
adc $87
|
|
sta $87
|
|
|
|
lda $88
|
|
adc #$00
|
|
sta $88
|
|
|
|
cmp #$02
|
|
bne @CheckSelectionInput
|
|
|
|
lda #$00
|
|
sta $87
|
|
|
|
lda #$04
|
|
sta gameState
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
@CheckSelectionInput:
|
|
lda currentInput
|
|
and #$04
|
|
cmp pacmanRequestedDirection
|
|
beq @CheckConfirmInput
|
|
|
|
sta pacmanRequestedDirection
|
|
|
|
lda #$00
|
|
sta $88
|
|
|
|
lda #$01
|
|
sta $87
|
|
|
|
lda pacmanRequestedDirection
|
|
beq @CheckConfirmInput
|
|
|
|
ldx #$00
|
|
|
|
inc activePlayerFlag
|
|
lda activePlayerFlag
|
|
and #$01
|
|
sta activePlayerFlag
|
|
beq @UseFirstSelectionData
|
|
|
|
inx
|
|
|
|
@UseFirstSelectionData:
|
|
lda $C50F,x
|
|
sta $024D
|
|
|
|
lda $C510,x
|
|
sta $0251
|
|
|
|
lda #$22
|
|
sta $024B
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
@CheckConfirmInput:
|
|
lda currentInput
|
|
and #$08
|
|
cmp pacmanDirection
|
|
bne @ConfirmStateChanged
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
@ConfirmStateChanged:
|
|
sta pacmanDirection
|
|
|
|
lda pacmanDirection
|
|
bne @ConfirmPressed
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
@ConfirmPressed:
|
|
lda #$00
|
|
sta gameplaySuspended
|
|
|
|
jsr $EEB4
|
|
|
|
jmp GameModeEntry
|
|
|
|
;==============================================================================
|
|
; $C507-$C511: Player Selection Display Data
|
|
;
|
|
; Local:
|
|
; Contains display-update data used by PlayerSelectionState.
|
|
;
|
|
; The first eight bytes, $C507-$C50E, are copied to RAM beginning at $024B
|
|
; when the player-selection state is first entered. The copy terminates after
|
|
; the $FF byte has also been stored.
|
|
;
|
|
; The final three bytes, $C50F-$C511, form an overlapping pair table used
|
|
; when $47 toggles between its two selection values:
|
|
;
|
|
; X = 0 -> $5C, $20
|
|
; X = 1 -> $20, $5C
|
|
;
|
|
; These values are written to $024D and $0251, respectively.
|
|
;
|
|
; Global:
|
|
; Provides the display-update data for the "1 PLAYER" / "2 PLAYERS"
|
|
; selection state. The overlapping three-byte table moves a $5C tile
|
|
; between two display positions while placing $20 at the other position.
|
|
;
|
|
; Notes:
|
|
; $5C appears to be the selection-marker tile and $20 appears to clear the
|
|
; alternate position. Their exact visual appearance can be confirmed later
|
|
; against CHR-ROM.
|
|
;
|
|
; $FF terminates the initialization data copied to $024B.
|
|
;==============================================================================
|
|
|
|
PlayerCountSelectionDisplayData:
|
|
.byte $22,$0A,$5C,$00
|
|
.byte $22,$4A,$20,$FF
|
|
|
|
PlayerCountSelectionMarkerTiles:
|
|
.byte $5C,$20,$5C
|
|
|
|
|
|
;==============================================================================
|
|
; $C512-$C52D: State $04 Handler / Substate Dispatcher
|
|
;
|
|
; Local:
|
|
; Handles the top-level processing for main state $04.
|
|
;
|
|
; First checks controller-1 bits $0C. If either bit is active, changes the
|
|
; main state back to $02 and jumps to MainEntry, causing the main display
|
|
; initialization sequence to run again.
|
|
;
|
|
; Otherwise uses $87 as a byte offset into a table of 16-bit handler
|
|
; addresses beginning at $C52E. The selected address is placed in $10/$11
|
|
; and execution jumps to it indirectly.
|
|
;
|
|
; Global:
|
|
; This is the fourth major handler in MainStateHandlerTable. Unlike states $00,
|
|
; $02, and $06, state $04 contains its own secondary state machine driven
|
|
; by $87.
|
|
;
|
|
; $87 therefore has a different role depending on the current main state.
|
|
; In state $02 it participated in a 16-bit frame counter with $88. Here it
|
|
; acts as the byte offset into a secondary dispatch table.
|
|
;
|
|
; Notes:
|
|
; $87 appears to take even values because it indexes packed 16-bit addresses
|
|
; directly rather than multiplying a state number by two.
|
|
;
|
|
; The substate table begins immediately afterward at $C52E.
|
|
; We leave the individual substate handlers for following passes.
|
|
;==============================================================================
|
|
|
|
State04Handler:
|
|
lda currentInput
|
|
and #$0C
|
|
beq @DispatchSubstate
|
|
|
|
lda #$02
|
|
sta gameState
|
|
|
|
jmp MainEntry
|
|
|
|
@DispatchSubstate:
|
|
ldy $87
|
|
|
|
lda State04SubstateTable,y
|
|
sta dispatchVector
|
|
|
|
lda State04SubstateTable+1,y
|
|
sta dispatchVector+1
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $C52E-$C545: State $04 Substate Dispatch Table
|
|
;
|
|
; Local:
|
|
; Twelve 16-bit handler addresses selected by State04Handler using $87 as
|
|
; a direct byte offset.
|
|
;
|
|
; Valid offsets observed from the table structure are:
|
|
; $00,$02,$04,$06,$08,$0A,$0C,$0E,$10,$12,$14,$16
|
|
;
|
|
; Global:
|
|
; Defines the secondary state machine used while the top-level game state
|
|
; is $04. Several intermediate substates deliberately share the same handler
|
|
; at $C573.
|
|
;
|
|
; Notes:
|
|
; Later code advances $87 using two INC instructions, confirming that $87
|
|
; is a byte offset into this table rather than an ordinal state number.
|
|
;==============================================================================
|
|
|
|
State04SubstateTable:
|
|
.word State04Initialize ; $00
|
|
.word State04TimedSubstate ; $02
|
|
.word State04TimedSubstate ; $04
|
|
.word State04TimedSubstate ; $06
|
|
.word State04TimedSubstate ; $08
|
|
.word State04TimedSubstate ; $0A
|
|
.word State04TimedSubstate ; $0C
|
|
.word State04TimedSubstate ; $0E
|
|
.word State04TimedSubstate ; $10
|
|
.word State04TimedSubstate ; $12
|
|
.word State04LongDelay ; $14
|
|
.word State04FinalPhase ; $16
|
|
|
|
;==============================================================================
|
|
; $C546-$C572: State $04 Initialization Substate
|
|
;
|
|
; Local:
|
|
; Performs the one-time initialization for state $04 when substate offset
|
|
; $87 is $00.
|
|
;
|
|
; First synchronizes with NMI using $40. It then sets PPUCTRL/$43 to $08,
|
|
; disables rendering through PPUMASK, clears $88, and calls three setup
|
|
; routines:
|
|
;
|
|
; $C5D8
|
|
; $C608
|
|
; SetSelectionFlagAndContinue
|
|
;
|
|
; After setup completes, advances $87 by two, selecting substate $02 on the
|
|
; following frame. PPUCTRL/$43 are then changed to $88 before returning to
|
|
; MainDispatchLoop.
|
|
;
|
|
; Global:
|
|
; Entry/initialization substate for the secondary state machine used by
|
|
; main state $04. It prepares the display and state-specific data before
|
|
; handing execution to the shared $C573 substate handler.
|
|
;
|
|
; Notes:
|
|
; $40 continues to act as the foreground/NMI synchronization flag.
|
|
;
|
|
; $87 is a byte offset into State04SubstateTable. The two INC instructions
|
|
; deliberately advance it from $00 to $02.
|
|
;
|
|
; The three called routines remain structurally named by address until they
|
|
; are decoded. $C5D8 and $C608 appear to perform direct PPU initialization,
|
|
; while SetSelectionFlagAndContinue operates on state/display data.
|
|
;==============================================================================
|
|
|
|
State04Initialize:
|
|
lda #$01
|
|
sta $40
|
|
|
|
@WaitForNmi:
|
|
lda $40
|
|
bne @WaitForNmi
|
|
|
|
lda #$08
|
|
sta PPUCTRL
|
|
sta ppuCtrlShadow
|
|
|
|
lda #$00
|
|
sta PPUMASK
|
|
sta $88
|
|
|
|
jsr $C5D8
|
|
jsr InitializeState04PpuData
|
|
jsr LoadState04DisplayData
|
|
|
|
inc $87
|
|
inc $87
|
|
|
|
lda #$88
|
|
sta PPUCTRL
|
|
sta ppuCtrlShadow
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
;==============================================================================
|
|
; $C573-$C588: State $04 Shared Timed Substate Handler
|
|
;
|
|
; Local:
|
|
; Advances $88 once per frame. At $30 frames, clears $88, invokes the
|
|
; state-$04 display-data helper, and advances $87 by two to the next
|
|
; secondary state.
|
|
;
|
|
; Global:
|
|
; Shared timing handler used by state-$04 substates $02-$12.
|
|
;
|
|
; Notes:
|
|
; LoadState04DisplayData is kept as a raw address temporarily to guarantee
|
|
; byte identity while the overlapping $C5A6-$C5D8 region is being resolved.
|
|
;==============================================================================
|
|
|
|
State04TimedSubstate:
|
|
inc $88
|
|
|
|
lda $88
|
|
cmp #$30
|
|
bne @ReturnToMainLoop
|
|
|
|
lda #$00
|
|
sta $88
|
|
|
|
jsr $C5A6
|
|
|
|
inc $87
|
|
inc $87
|
|
|
|
@ReturnToMainLoop:
|
|
jmp MainDispatchLoop
|
|
|
|
;==============================================================================
|
|
; $C589-$C59F: State $04 Long Delay Substate
|
|
;
|
|
; Local:
|
|
; Increments $88 once per frame and waits until it reaches $80.
|
|
;
|
|
; While $88 is not $80, returns to MainDispatchLoop.
|
|
;
|
|
; When $88 reaches $80:
|
|
; - Advances $87 by two, selecting substate $16.
|
|
; - Clears $88.
|
|
; - Returns to MainDispatchLoop.
|
|
;
|
|
; Global:
|
|
; Implements substate $14 of the state $04 secondary state machine. It
|
|
; follows the series of $30-frame substates handled by
|
|
; State04TimedSubstate and introduces a longer delay before entering the
|
|
; final known substate at $16.
|
|
;
|
|
; Notes:
|
|
; $88 is the frame counter for this substate.
|
|
; $87 is the byte offset into State04SubstateTable.
|
|
;
|
|
; Unlike substates $02-$12, reaching the timeout here does not call
|
|
; SetSelectionFlagAndContinue. It simply advances from substate $14 to $16.
|
|
;==============================================================================
|
|
|
|
State04LongDelay:
|
|
inc $88
|
|
|
|
lda $88
|
|
cmp #$80
|
|
beq @AdvanceSubstate
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
@AdvanceSubstate:
|
|
inc $87
|
|
inc $87
|
|
|
|
lda #$00
|
|
sta $88
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
|
|
;==============================================================================
|
|
; $C59F-$C5A5: Select Alternate Player Mode and Continue
|
|
;
|
|
; Local:
|
|
; Sets $47 to $01 and tail-jumps to the routine at GameModeEntry.
|
|
;
|
|
; Global:
|
|
; Forces the same $47 flag that PlayerSelectionState toggles between $00
|
|
; and $01, then transfers control to GameModeEntry. This strongly links the routine
|
|
; to the player-count/player-mode selection logic.
|
|
;
|
|
; The exact global purpose of GameModeEntry has not yet been decoded, so the routine
|
|
; and $47 remain conservatively named during this pass.
|
|
;
|
|
; Notes:
|
|
; There is no RTS. Control is permanently transferred to GameModeEntry.
|
|
;
|
|
; $47 is known to be constrained to 0/1 by PlayerSelectionState and is also
|
|
; consulted by NmiHandler when selecting controller input and constructing
|
|
; PPUCTRL. We should trace GameModeEntry before assigning $47 a final semantic name.
|
|
;==============================================================================
|
|
|
|
SetSelectionFlagAndContinue:
|
|
lda #$01
|
|
sta activePlayerFlag
|
|
jmp GameModeEntry
|
|
|
|
|
|
;==============================================================================
|
|
; $C5A6-$C5D7: State $04 Display Data Loader
|
|
;
|
|
; Local:
|
|
; Uses $87 as a byte offset into a pointer table at $C687. The selected
|
|
; $FF-terminated stream is copied through $00/$01 into RAM beginning at
|
|
; $024B, including the $FF terminator.
|
|
;
|
|
; The byte following the terminator controls an optional secondary copy:
|
|
; nonzero -> return
|
|
; zero -> copy 16 bytes using a substate-derived offset
|
|
;
|
|
; Global:
|
|
; Supplies update/display data as the state-$04 secondary state machine
|
|
; progresses.
|
|
;
|
|
; Notes:
|
|
; $00/$01 form the temporary source pointer.
|
|
;==============================================================================
|
|
|
|
LoadState04DisplayData:
|
|
ldy $87
|
|
|
|
lda CharacterIntroDisplayDataTable,y
|
|
sta workPtr0
|
|
|
|
lda CharacterIntroDisplayDataTable+1,y
|
|
sta workPtr0+1
|
|
|
|
ldy #$00
|
|
|
|
@CopyDisplayData:
|
|
lda (workPtr0),y
|
|
sta $024B,y
|
|
|
|
iny
|
|
cmp #$FF
|
|
bne @CopyDisplayData
|
|
|
|
lda (workPtr0),y
|
|
beq @SecondaryCopy
|
|
|
|
rts
|
|
|
|
@SecondaryCopy:
|
|
lda $87
|
|
sec
|
|
sbc #$02
|
|
asl
|
|
asl
|
|
tay
|
|
|
|
ldx #$10
|
|
|
|
@CopySecondaryData:
|
|
lda CharacterIntroSpriteData,y
|
|
sta $0760,y
|
|
|
|
iny
|
|
dex
|
|
bne @CopySecondaryData
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $C5D8-$C607: Initialize Playfield Area
|
|
;
|
|
; Local:
|
|
; Sets the PPU destination to $20C0 and fills 24 complete 32-tile nametable
|
|
; rows.
|
|
;
|
|
; Each row consists of:
|
|
; 2 x $2D
|
|
; 28 x $20
|
|
; 2 x $2D
|
|
;
|
|
; The inner count at $01 is reinitialized to $1C at the beginning of every
|
|
; row. $00 begins at $17 and counts rows down through zero.
|
|
;
|
|
; Global:
|
|
; Called during State04Initialize with rendering disabled. Builds the large
|
|
; rectangular background area used by state $04.
|
|
;
|
|
; Notes:
|
|
; The BPL at $C605 intentionally returns to $C5E6, not directly to the first
|
|
; tile write. This reloads $01 with $1C for every row and must be preserved
|
|
; for byte identity.
|
|
;==============================================================================
|
|
|
|
InitializePlayfieldArea:
|
|
lda #$20
|
|
sta PPUADDR
|
|
|
|
lda #$C0
|
|
sta PPUADDR
|
|
|
|
lda #$17
|
|
sta workPtr0
|
|
|
|
@NextRow:
|
|
lda #$1C
|
|
sta workPtr0+1
|
|
|
|
lda #$2D
|
|
sta PPUDATA
|
|
sta PPUDATA
|
|
|
|
lda #$20
|
|
|
|
@ClearRowInterior:
|
|
sta PPUDATA
|
|
dec workPtr0+1
|
|
bne @ClearRowInterior
|
|
|
|
lda #$2D
|
|
sta PPUDATA
|
|
sta PPUDATA
|
|
|
|
dec workPtr0
|
|
bpl @NextRow
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $C608-$C666: Initialize State $04 PPU Data
|
|
;
|
|
; Local:
|
|
; Performs three groups of PPU initialization:
|
|
;
|
|
; 1. Writes $24 (36) bytes from $C76E to PPUDATA beginning at PPU $23C8.
|
|
;
|
|
; 2. Processes a sequence of variable-length PPU write records beginning
|
|
; at $C69B. Each record contains a two-byte PPU destination followed by
|
|
; data bytes terminated by $FF.
|
|
;
|
|
; 3. Writes a full $20-byte palette table from CharacterIntroPalette to PPU palette RAM
|
|
; beginning at $3F00.
|
|
;
|
|
; After the palette transfer, resets PPUADDR away from palette space and
|
|
; returns.
|
|
;
|
|
; Global:
|
|
; Called by State04Initialize while rendering is disabled. Together with
|
|
; InitializePlayfieldArea, this routine constructs the PPU state needed by
|
|
; the state-$04 display sequence.
|
|
;
|
|
; Notes:
|
|
; Unlike InitializeNametableData, the PPU-record loop at $C61D does not
|
|
; contain an explicit record count. The encoded data and Y wrap behavior
|
|
; determine when processing terminates. We should decode $C69B before
|
|
; assigning a more precise description to that stream.
|
|
;
|
|
; CharacterIntroPalette begins the 32-byte palette table.
|
|
; $C76E is the source of the 36-byte attribute-data transfer.
|
|
;==============================================================================
|
|
|
|
InitializeState04PpuData:
|
|
; Set PPU destination to $23C8.
|
|
lda #$23
|
|
sta PPUADDR
|
|
|
|
lda #$C8
|
|
sta PPUADDR
|
|
|
|
; Copy $24 bytes of attribute data.
|
|
ldy #$00
|
|
|
|
@CopyAttributeData:
|
|
lda $C76E,y
|
|
sta PPUDATA
|
|
|
|
iny
|
|
cpy #$24
|
|
bne @CopyAttributeData
|
|
|
|
; Process encoded PPU write data from $C69B.
|
|
ldy #$00
|
|
|
|
@NextPpuRecord:
|
|
lda CharacterNicknameHeaderData,y
|
|
sta PPUADDR
|
|
iny
|
|
|
|
lda CharacterNicknameHeaderData,y
|
|
sta PPUADDR
|
|
iny
|
|
|
|
@CopyPpuRecord:
|
|
lda CharacterNicknameHeaderData,y
|
|
cmp #$FF
|
|
beq @EndPpuRecord
|
|
|
|
sta PPUDATA
|
|
iny
|
|
bne @CopyPpuRecord
|
|
|
|
@EndPpuRecord:
|
|
lda PPUSTATUS
|
|
|
|
; Upload the complete 32-byte palette directly.
|
|
lda #$3F
|
|
sta PPUADDR
|
|
|
|
lda #$00
|
|
sta PPUADDR
|
|
|
|
ldy #$00
|
|
|
|
@CopyPalette:
|
|
lda CharacterIntroPalette,y
|
|
sta PPUDATA
|
|
|
|
iny
|
|
cpy #$20
|
|
bne @CopyPalette
|
|
|
|
; Reset the PPU address following palette access.
|
|
lda #$3F
|
|
sta PPUADDR
|
|
|
|
lda #$00
|
|
sta PPUADDR
|
|
sta PPUADDR
|
|
sta PPUADDR
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $C667-$C686: State $04 Palette Data
|
|
;
|
|
; Local:
|
|
; Complete 32-byte palette uploaded directly to PPU $3F00-$3F1F by
|
|
; InitializeState04PpuData.
|
|
;
|
|
; Global:
|
|
; Defines the background and sprite colors used by the state-$04 display.
|
|
;
|
|
; Notes:
|
|
; First 16 bytes are the four background palettes.
|
|
; Second 16 bytes are the four sprite palettes.
|
|
;==============================================================================
|
|
CharacterIntroPalette:
|
|
; Background palettes
|
|
.byte $0F,$20,$0F,$06
|
|
.byte $0F,$06,$0F,$33
|
|
.byte $0F,$33,$0F,$27
|
|
.byte $0F,$17,$0F,$21
|
|
|
|
; Sprite palettes
|
|
.byte $0F,$27,$20,$06
|
|
.byte $0F,$11,$20,$33
|
|
.byte $0F,$20,$20,$21
|
|
.byte $0F,$09,$20,$17
|
|
|
|
;==============================================================================
|
|
; $C687-$C69A: State $04 Display Data Pointer Table
|
|
;
|
|
; Local:
|
|
; Contains ten 16-bit pointers to display/update data streams. The helper at
|
|
; $C5A6 uses $87 directly as a byte offset into this table:
|
|
;
|
|
; ldy $87
|
|
; lda CharacterIntroDisplayDataTable,y
|
|
; sta $00
|
|
; lda CharacterIntroDisplayDataTable+1,y
|
|
; sta $01
|
|
;
|
|
; The valid table offsets are therefore:
|
|
; $00,$02,$04,$06,$08,$0A,$0C,$0E,$10,$12
|
|
;
|
|
; Global:
|
|
; Selects the display data used as the state-$04 secondary state machine
|
|
; progresses. State04Initialize uses offset $00, while the successive timed
|
|
; substates use offsets $02 through $12.
|
|
;
|
|
; Notes:
|
|
; Each target begins a $FF-terminated display/update stream copied into RAM
|
|
; at $024B by LoadState04DisplayData.
|
|
;
|
|
; Several streams contain an additional control byte following $FF. The
|
|
; helper uses that byte to decide whether to perform its secondary copy.
|
|
;==============================================================================
|
|
|
|
CharacterIntroDisplayDataTable:
|
|
.word CharacterNicknameHeaderData ; $87 = $00 Character; NICKNAME
|
|
.word ShadowNameData ; $87 = $02 : SHADOW
|
|
.word BlinkyNameData ; $87 = $04 _BLINKY_
|
|
.word SpeedyNameData ; $87 = $06 : SPEEDY
|
|
.word PinkyNameData ; $87 = $08 _PINKY_
|
|
.word CharacterIntroGraphicData0 ; $87 = $0A
|
|
.word CharacterIntroGraphicData1 ; $87 = $0C
|
|
.word PokeyNameData ; $87 = $0E
|
|
.word ClydeNameData ; $87 = $10
|
|
.word ScoringLegendData ; $87 = $12
|
|
|
|
;==============================================================================
|
|
; $C69B-$C72D: State $04 Display Update Streams
|
|
;
|
|
; Local:
|
|
; Contains ten display/update streams selected through
|
|
; CharacterIntroDisplayDataTable according to the state-$04 substate offset $87.
|
|
;
|
|
; LoadState04DisplayData copies the selected stream into RAM beginning at
|
|
; $024B until it encounters $FF. The $FF byte itself is also copied.
|
|
;
|
|
; For several streams, the byte immediately following $FF is $00. The
|
|
; loader examines this byte and uses it to trigger its optional secondary
|
|
; data copy.
|
|
;
|
|
; Global:
|
|
; Supplies the sequence of text and display changes shown during the timed
|
|
; state-$04 sequence. The data reveals that this portion of the attract/
|
|
; information display introduces game characters and later installs
|
|
; scoring/instruction-related display data.
|
|
;
|
|
; Notes:
|
|
; Many tile values correspond directly to ASCII-like character tiles, but
|
|
; special tile values are retained numerically.
|
|
;
|
|
; $00 bytes appearing after $FF belong to the control mechanism used by
|
|
; LoadState04DisplayData. They are not part of the $FF-terminated portion
|
|
; copied to $024B.
|
|
;
|
|
; The final stream at $C707 is structurally different: it contains multiple
|
|
; apparent PPU/update command groups before the final $FF.
|
|
;==============================================================================
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $C69B-$C6B2
|
|
; State04 substate offset: $00
|
|
;
|
|
; Destination prefix: $20E6
|
|
;
|
|
; Tile data corresponds approximately to:
|
|
; "CHARACTER ; NICKNAME"
|
|
;
|
|
; No explicit $00 control byte follows this stream before the next record.
|
|
;------------------------------------------------------------------------------
|
|
|
|
CharacterNicknameHeaderData:
|
|
.byte $20,$E6
|
|
.byte $43,$48,$41,$52,$41,$43,$54,$45,$52
|
|
.byte $20,$3B,$20,$20
|
|
.byte $4E,$49,$43,$4B,$4E,$41,$4D,$45
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $C6B3-$C6BD
|
|
; State04 substate offset: $02
|
|
;
|
|
; Destination prefix: $2148
|
|
;
|
|
; Text-like tile data:
|
|
; ":SHADOW"
|
|
;
|
|
; $00 after $FF selects the loader's secondary-copy path.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ShadowNameData:
|
|
.byte $21,$48
|
|
.byte $3A,$53,$48,$41,$44,$4F,$57
|
|
.byte $FF
|
|
.byte $00
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $C6BE-$C6C8
|
|
; State04 substate offset: $04
|
|
;
|
|
; Destination prefix: $2153
|
|
;
|
|
; Text-like tile data:
|
|
; "_BLINKY_"
|
|
;
|
|
; No trailing $00 before the next stream.
|
|
;------------------------------------------------------------------------------
|
|
|
|
BlinkyNameData:
|
|
.byte $21,$53
|
|
.byte $5F,$42,$4C,$49,$4E,$4B,$59,$5F
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $C6C9-$C6D3
|
|
; State04 substate offset: $06
|
|
;
|
|
; Destination prefix: $21A8
|
|
;
|
|
; Text-like tile data:
|
|
; ":SPEEDY"
|
|
;
|
|
; $00 after $FF selects the loader's secondary-copy path.
|
|
;------------------------------------------------------------------------------
|
|
SpeedyNameData:
|
|
.byte $21,$A8
|
|
.byte $3A,$53,$50,$45,$45,$44,$59
|
|
.byte $FF
|
|
.byte $00
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $C6D4-$C6DD
|
|
; State04 substate offset: $08
|
|
;
|
|
; Destination prefix: $21B3
|
|
;
|
|
; Text-like tile data:
|
|
; "_PINKY_"
|
|
;------------------------------------------------------------------------------
|
|
PinkyNameData:
|
|
.byte $21,$B3
|
|
.byte $5F,$50,$49,$4E,$4B,$59,$5F
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $C6DE-$C6E9
|
|
; State04 substate offset: $0A
|
|
;
|
|
; Destination prefix: $2208
|
|
;
|
|
; Contains graphical/special tile values rather than plain character codes.
|
|
; $00 after $FF selects the loader's secondary-copy path.
|
|
;------------------------------------------------------------------------------
|
|
CharacterIntroGraphicData0:
|
|
.byte $22,$08
|
|
.byte $B6,$C1,$C3,$B7,$B4,$C2,$B3,$C4
|
|
.byte $FF
|
|
.byte $00
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $C6EA-$C6F2
|
|
; State04 substate offset: $0C
|
|
;
|
|
; Destination prefix: $2213
|
|
;
|
|
; Contains another set of special graphical tile values.
|
|
;------------------------------------------------------------------------------
|
|
CharacterIntroGraphicData1:
|
|
.byte $22,$13
|
|
.byte $C8,$B5,$C5,$C0,$C6,$C8
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $C6F3-$C6FC
|
|
; State04 substate offset: $0E
|
|
;
|
|
; Destination prefix: $2268
|
|
;
|
|
; Text-like tile data:
|
|
; ":POKEY"
|
|
;
|
|
; $00 after $FF selects the loader's secondary-copy path.
|
|
;------------------------------------------------------------------------------
|
|
PokeyNameData:
|
|
.byte $22,$68
|
|
.byte $3A,$50,$4F,$4B,$45,$59
|
|
.byte $FF
|
|
.byte $00
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $C6FD-$C706
|
|
; State04 substate offset: $10
|
|
;
|
|
; Destination prefix: $2273
|
|
;
|
|
; Text-like tile data:
|
|
; "_CLYDE_"
|
|
;------------------------------------------------------------------------------
|
|
ClydeNameData:
|
|
.byte $22,$73
|
|
.byte $5F,$43,$4C,$59,$44,$45,$5F
|
|
.byte $FF
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $C707-$C72D
|
|
; State04 substate offset: $12
|
|
;
|
|
; Final composite display stream. Unlike the earlier simple records, this
|
|
; contains several apparent update groups separated by $00 bytes before the
|
|
; final $FF.
|
|
;
|
|
; Visible character-like portions include:
|
|
; "10 PTS"
|
|
; "50 PTS"
|
|
;
|
|
; The special tile values $CE,$CF and $23-$2B are preserved numerically.
|
|
;------------------------------------------------------------------------------
|
|
ScoringLegendData:
|
|
.byte $22,$AD
|
|
.byte $03,$20,$31,$30,$20,$50,$54,$53
|
|
.byte $00
|
|
|
|
.byte $22,$ED
|
|
.byte $01,$20,$35,$30,$20,$50,$54,$53
|
|
.byte $00
|
|
|
|
.byte $23,$34
|
|
.byte $CE,$CF
|
|
.byte $00
|
|
|
|
.byte $23,$4D
|
|
.byte $23,$24,$25,$26,$27,$28,$29,$2A,$2B
|
|
.byte $FF
|
|
|
|
|
|
;==============================================================================
|
|
; $C72E-$C76D: State $04 Secondary Object/Sprite Data
|
|
;
|
|
; Local:
|
|
; Contains 64 bytes of secondary display data used by
|
|
; LoadState04DisplayData.
|
|
;
|
|
; When a state-$04 display stream requests the secondary-copy path, the
|
|
; loader calculates:
|
|
;
|
|
; Y = ($87 - $02) * 4
|
|
;
|
|
; It then copies $10 (16) bytes from:
|
|
;
|
|
; CharacterIntroSpriteData,Y
|
|
;
|
|
; to:
|
|
;
|
|
; $0760,Y
|
|
;
|
|
; Because state-$04 substates advance by two, Y advances by eight bytes:
|
|
;
|
|
; $87 = $02 -> Y = $00
|
|
; $87 = $04 -> Y = $08
|
|
; $87 = $06 -> Y = $10
|
|
; $87 = $08 -> Y = $18
|
|
; ...
|
|
;
|
|
; The 16-byte transfers therefore intentionally overlap by eight bytes.
|
|
;
|
|
; Global:
|
|
; Supplies progressively updated object/sprite-related state during the
|
|
; state-$04 timed display sequence. The destination lies in RAM page $07,
|
|
; which is also used as an OAM DMA source elsewhere in the program.
|
|
;
|
|
; The repeated four-byte patterns strongly suggest sprite/OAM-style records,
|
|
; but exact field semantics should be confirmed against the code that
|
|
; consumes $0760 and the active OAM page before assigning field names.
|
|
;
|
|
; Notes:
|
|
; The table is safest to represent as 16 four-byte records during this pass.
|
|
; This preserves its natural repeated structure while allowing the loader's
|
|
; overlapping 16-byte windows to remain obvious.
|
|
;==============================================================================
|
|
|
|
CharacterIntroSpriteData:
|
|
; $C72E - record $00
|
|
.byte $48,$1C,$40,$26
|
|
|
|
; $C732 - record $01
|
|
.byte $48,$1B,$40,$2E
|
|
|
|
; $C736 - record $02
|
|
.byte $50,$1F,$40,$26
|
|
|
|
; $C73A - record $03
|
|
.byte $50,$1D,$40,$2E
|
|
|
|
; $C73E - record $04
|
|
.byte $60,$1C,$41,$26
|
|
|
|
; $C742 - record $05
|
|
.byte $60,$1B,$41,$2E
|
|
|
|
; $C746 - record $06
|
|
.byte $68,$1F,$41,$26
|
|
|
|
; $C74A - record $07
|
|
.byte $68,$1D,$41,$2E
|
|
|
|
; $C74E - record $08
|
|
.byte $78,$1C,$42,$26
|
|
|
|
; $C752 - record $09
|
|
.byte $78,$1B,$42,$2E
|
|
|
|
; $C756 - record $0A
|
|
.byte $80,$1F,$42,$26
|
|
|
|
; $C75A - record $0B
|
|
.byte $80,$1D,$42,$2E
|
|
|
|
; $C75E - record $0C
|
|
.byte $90,$1C,$43,$26
|
|
|
|
; $C762 - record $0D
|
|
.byte $90,$1B,$43,$2E
|
|
|
|
; $C766 - record $0E
|
|
.byte $98,$1F,$43,$26
|
|
|
|
; $C76A - record $0F
|
|
.byte $98,$1D,$43,$2E
|
|
|
|
|
|
;==============================================================================
|
|
; $C76E-$C791: State $04 Nametable Attribute Data
|
|
;
|
|
; Local:
|
|
; Contains $24 (36) bytes copied directly to PPUDATA by
|
|
; InitializeState04PpuData.
|
|
;
|
|
; The destination begins at PPU $23C8, so the complete transfer covers:
|
|
;
|
|
; $23C8-$23EB
|
|
;
|
|
; Global:
|
|
; Defines background palette selection attributes used by the state-$04
|
|
; display. The highly regular $00/$55/$AA/$FF pattern assigns repeating
|
|
; palette selections across large regions of the nametable.
|
|
;
|
|
; Notes:
|
|
; These are NES attribute-table bytes rather than tile indices.
|
|
;
|
|
; Each attribute byte contains four 2-bit palette selections. Values such
|
|
; as $00, $55, $AA and $FF therefore select the same palette throughout all
|
|
; four quadrants covered by that attribute byte:
|
|
;
|
|
; $00 -> palette 0 in all four quadrants
|
|
; $55 -> palette 1 in all four quadrants
|
|
; $AA -> palette 2 in all four quadrants
|
|
; $FF -> palette 3 in all four quadrants
|
|
;
|
|
; The final $22 mixes palette selections within its attribute regions.
|
|
;==============================================================================
|
|
|
|
CharacterIntroAttributeData:
|
|
.byte $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byte $55,$55,$55,$55,$55,$55,$55,$55
|
|
.byte $AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
|
|
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
|
.byte $AA,$AA,$AA,$22
|
|
|
|
;==============================================================================
|
|
; $C792-$C7A0: State $04 Final-Phase Dispatcher
|
|
;
|
|
; Local:
|
|
; Uses $88 as a direct byte offset into a four-entry table of 16-bit
|
|
; addresses beginning at $C7A1.
|
|
;
|
|
; The selected address is stored in the temporary pointer $10/$11 and
|
|
; execution is transferred to it using an indirect JMP.
|
|
;
|
|
; Global:
|
|
; Implements state-$04 substate offset $16. Rather than performing the work
|
|
; directly, this substate introduces another secondary state machine.
|
|
;
|
|
; At this stage:
|
|
;
|
|
; $3F = $04 main state
|
|
; $87 = $16 state-$04 substate
|
|
; $88 final-phase dispatch offset
|
|
;
|
|
; This provides another level of progression within the final state-$04
|
|
; phase.
|
|
;
|
|
; Notes:
|
|
; $88 is used directly as a byte offset, so normal values are expected to
|
|
; advance by two:
|
|
;
|
|
; $00, $02, $04, $06
|
|
;
|
|
; The individual target handlers will be named as they are decoded.
|
|
;==============================================================================
|
|
State04FinalPhase:
|
|
ldy $88
|
|
|
|
lda State04FinalPhaseTable,y
|
|
sta dispatchVector
|
|
|
|
lda State04FinalPhaseTable+1,y
|
|
sta dispatchVector+1
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $C7A1-$C7A6: State $04 Final-Phase Dispatch Table
|
|
;
|
|
; Local:
|
|
; Three 16-bit handler addresses indexed by $88.
|
|
;
|
|
; Global:
|
|
; Selects the processing stage used during State04FinalPhase.
|
|
;
|
|
; Notes:
|
|
; Valid byte offsets established by the table are $00, $02 and $04.
|
|
; $C7A7 is executable code and is not part of the pointer table.
|
|
;==============================================================================
|
|
|
|
State04FinalPhaseTable:
|
|
.word State04FinalPhaseInitialize ; $88 = $00
|
|
.word State04FinalPhaseActive ; $88 = $02
|
|
.word State04FinalPhaseComplete ; $88 = $04
|
|
|
|
;==============================================================================
|
|
; $C7A7-$C7F1: State $04 Final-Phase Initialization
|
|
;
|
|
; Local:
|
|
; Initializes the first stage of State04FinalPhase.
|
|
;
|
|
; Copies a $FF-terminated display/update stream from State04FinalDisplayData
|
|
; into RAM at $024B, including the terminator.
|
|
;
|
|
; Initializes several state variables and object/display values, clears
|
|
; $001E-$0031 and $0278-$028B, calls the helper at $DAF1, then advances
|
|
; $88 by two to select final-phase offset $02.
|
|
;
|
|
; Global:
|
|
; First handler selected by State04FinalPhase when $88 = $00. It prepares
|
|
; the RAM and display state required by the next final-phase handler at
|
|
; $C7F2.
|
|
;
|
|
; Notes:
|
|
; $1A is initialized to $FF.
|
|
; $1B, $89 and $8A are initialized to $00.
|
|
;
|
|
; $0274 = $F4
|
|
; $0276 = $A8
|
|
; $028C = $01
|
|
; $0292 = $20
|
|
;
|
|
; The exact semantics of these locations will be refined after tracing
|
|
; their consumers.
|
|
;
|
|
; State04FinalDisplayData is a display/update stream in the same general RAM
|
|
; command area used elsewhere through $024B.
|
|
;==============================================================================
|
|
|
|
State04FinalPhaseInitialize:
|
|
ldy #$00
|
|
|
|
@CopyDisplayData:
|
|
lda State04FinalDisplayData,y
|
|
sta $024B,y
|
|
iny
|
|
cmp #$FF
|
|
bne @CopyDisplayData
|
|
|
|
lda #$FF
|
|
sta pacmanMotion
|
|
|
|
lda #$00
|
|
sta $1B
|
|
sta $89
|
|
sta $8A
|
|
|
|
lda #$F4
|
|
sta $0274
|
|
|
|
lda #$A8
|
|
sta $0276
|
|
|
|
lda #$01
|
|
sta $028C
|
|
|
|
lda #$20
|
|
sta $0292
|
|
|
|
lda #$00
|
|
tay
|
|
|
|
@ClearLowRamBlock:
|
|
sta $001E,y
|
|
iny
|
|
cpy #$14
|
|
bne @ClearLowRamBlock
|
|
|
|
tay
|
|
|
|
@ClearObjectRamBlock:
|
|
sta $0278,y
|
|
iny
|
|
cpy #$14
|
|
bne @ClearObjectRamBlock
|
|
|
|
jsr $DAF1
|
|
|
|
inc $88
|
|
inc $88
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
;==============================================================================
|
|
; $C7F2-$C856: State $04 Final-Phase Active Handler
|
|
;
|
|
; Local:
|
|
; Calls two per-frame helpers at UpdateState04Objects and
|
|
; AnimateState04DisplayPattern, then examines $0274.
|
|
;
|
|
; When $0274 equals one of:
|
|
;
|
|
; $E0
|
|
; $D1
|
|
; $C2
|
|
; $B3
|
|
;
|
|
; the routine calls InitializeState04ObjectSlot.
|
|
;
|
|
; Processing otherwise continues until $0274 reaches $40. While it has not
|
|
; reached $40, control returns to MainDispatchLoop.
|
|
;
|
|
; When $0274 reaches $40, the routine:
|
|
;
|
|
; - Initializes four 4-byte structures beginning at $001E.
|
|
; - Sets $1A = $01 and $1B = $50.
|
|
; - Sets $0293-$0296 to $01.
|
|
; - Clears $89.
|
|
; - Writes a short display/update sequence at $024B/$024D.
|
|
; - Advances $88 by two, selecting final-phase offset $04.
|
|
;
|
|
; Global:
|
|
; Active middle stage of State04FinalPhase. The handler appears to drive
|
|
; an animated sequence by calling UpdateState04Objects/AnimateState04DisplayPattern
|
|
; each frame and reacting when $0274 reaches several specific values.
|
|
;
|
|
; The milestone values $E0,$D1,$C2,$B3 invoke InitializeState04ObjectSlot. The exact meaning of
|
|
; those milestones should be assigned after the movement/update helpers are
|
|
; decoded.
|
|
;
|
|
; Notes:
|
|
; $0274 was initialized to $F4 by State04FinalPhaseInitialize, so the
|
|
; descending milestone tests strongly suggest $0274 is modified by one of
|
|
; the per-frame helper routines.
|
|
;
|
|
; The four low-RAM structures are $001E/$0022/$0026/$002A. Each receives
|
|
; $00 in its first byte and $C0 in its second byte. The remaining two bytes
|
|
; are not changed by this loop.
|
|
;==============================================================================
|
|
|
|
State04FinalPhaseActive:
|
|
jsr UpdateState04Objects
|
|
jsr AnimateState04DisplayPattern
|
|
|
|
lda $0274
|
|
|
|
cmp #$E0
|
|
beq @RunMilestoneUpdate
|
|
|
|
cmp #$D1
|
|
beq @RunMilestoneUpdate
|
|
|
|
cmp #$C2
|
|
beq @RunMilestoneUpdate
|
|
|
|
cmp #$B3
|
|
bne @CheckForCompletion
|
|
|
|
@RunMilestoneUpdate:
|
|
jsr InitializeState04ObjectSlot
|
|
|
|
@CheckForCompletion:
|
|
lda $0274
|
|
cmp #$40
|
|
beq @CompletePhase
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
@CompletePhase:
|
|
ldy #$00
|
|
|
|
@InitializeStructures:
|
|
lda #$00
|
|
sta ghost1Motion,y
|
|
|
|
lda #$C0
|
|
sta ghost1Motion+1,y
|
|
|
|
iny
|
|
iny
|
|
iny
|
|
iny
|
|
|
|
cpy #$10
|
|
bne @InitializeStructures
|
|
|
|
lda #$01
|
|
sta pacmanMotion
|
|
|
|
lda #$50
|
|
sta pacmanMotion+1
|
|
|
|
lda #$01
|
|
sta $0293
|
|
sta $0294
|
|
sta $0295
|
|
sta $0296
|
|
|
|
lda #$00
|
|
sta $89
|
|
|
|
lda #$22
|
|
sta $024B
|
|
|
|
lda #$20
|
|
sta $024D
|
|
|
|
inc $88
|
|
inc $88
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
;==============================================================================
|
|
; $C857-$C8A7: State $04 Final-Phase Completion Handler
|
|
;
|
|
; Local:
|
|
; Final handler for final-phase offset $88 = $04.
|
|
;
|
|
; If $8A is nonzero, calls RotateState04ObjectSlots and decrements the countdown. When the
|
|
; countdown reaches zero, scans status entries beginning at $028D until an
|
|
; entry with one or more upper-three status bits set is found.
|
|
;
|
|
; The matching entry and associated state are cleared. If $89 has reached
|
|
; $04, the routine sets $47 to $01 and transfers control to GameModeEntry.
|
|
;
|
|
; When $8A is already zero on entry, calls $C8DC and returns to the common
|
|
; main dispatch loop.
|
|
;
|
|
; Global:
|
|
; Final processing stage of the nested state-$04 sequence:
|
|
;
|
|
; $3F = $04
|
|
; $87 = $16
|
|
; $88 = $04
|
|
;
|
|
; The eventual transfer to GameModeEntry appears to leave this attract/display
|
|
; sequence and enter another major portion of the program.
|
|
;
|
|
; Notes:
|
|
; $8A acts as a countdown here.
|
|
; $89 is tested against $04 for completion.
|
|
;
|
|
; The scan at $028D looks for the first entry satisfying:
|
|
;
|
|
; ($028D,Y & $E0) != 0
|
|
;
|
|
; Exact object/state semantics remain for a later pass.
|
|
;==============================================================================
|
|
|
|
State04FinalPhaseComplete:
|
|
lda $8A
|
|
beq @RunRegularUpdate
|
|
|
|
jsr RotateState04ObjectSlots
|
|
|
|
dec $8A
|
|
beq @CountdownComplete
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
@CountdownComplete:
|
|
ldy #$00
|
|
|
|
@FindEntry:
|
|
lda $028D,y
|
|
and #$E0
|
|
bne @EntryFound
|
|
|
|
iny
|
|
bne @FindEntry
|
|
|
|
@EntryFound:
|
|
lda #$00
|
|
sta $028D,y
|
|
|
|
lda #$00
|
|
sta $0293,y
|
|
|
|
tya
|
|
asl
|
|
asl
|
|
tay
|
|
|
|
lda #$00
|
|
sta $0278,y
|
|
sta $027A,y
|
|
sta ghost1Motion,y
|
|
sta ghost1Motion+1,y
|
|
|
|
lda #$A8
|
|
sta $0276
|
|
|
|
lda $89
|
|
cmp #$04
|
|
beq @FinishSequence
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
@FinishSequence:
|
|
lda #$01
|
|
sta activePlayerFlag
|
|
|
|
jmp GameModeEntry
|
|
|
|
@RunRegularUpdate:
|
|
jsr UpdateState04Objects
|
|
|
|
jmp MainDispatchLoop
|
|
|
|
;==============================================================================
|
|
; $C8A8-$C8DB: Allocate/Initialize State $04 Object Slot
|
|
;
|
|
; Local:
|
|
; Searches four 4-byte structures beginning at $0278 for the first slot
|
|
; whose first byte is zero.
|
|
;
|
|
; During the search, $00 tracks the logical slot number while Y advances
|
|
; by four bytes per structure.
|
|
;
|
|
; Once a free slot is found, initializes that structure:
|
|
;
|
|
; +0 = $F4
|
|
; +2 = $A8
|
|
;
|
|
; It also initializes corresponding four-byte-strided zero-page state:
|
|
;
|
|
; $001E+Y = $FF
|
|
; $001F+Y = $00
|
|
;
|
|
; The logical slot number saved in $00 is then used to index two separate
|
|
; per-slot arrays:
|
|
;
|
|
; $0293+slot = current $89 value
|
|
; $028D+slot = $0C
|
|
;
|
|
; Finally increments $89 and returns.
|
|
;
|
|
; Global:
|
|
; Called by State04FinalPhaseActive whenever $0274 reaches the milestone
|
|
; values $E0, $D1, $C2, or $B3.
|
|
;
|
|
; This strongly suggests that the routine activates one additional object
|
|
; at each milestone during the state-$04 final sequence. Four slots are
|
|
; available, matching the four milestone values.
|
|
;
|
|
; Notes:
|
|
; $0278 appears to be the first field of a four-byte structure array.
|
|
; $027A is the third field of the same structure.
|
|
;
|
|
; $001E/$001F are parallel four-byte-strided state fields.
|
|
;
|
|
; $028D and $0293 are indexed by logical slot number rather than the
|
|
; four-byte structure offset.
|
|
;
|
|
; Exact object semantics remain deliberately unnamed until UpdateState04Objects
|
|
; and RotateState04ObjectSlots reveal how these structures are updated.
|
|
;==============================================================================
|
|
|
|
InitializeState04ObjectSlot:
|
|
ldy #$00
|
|
sty workPtr0
|
|
|
|
@FindFreeSlot:
|
|
lda $0278,y
|
|
beq @InitializeSlot
|
|
|
|
inc workPtr0
|
|
|
|
iny
|
|
iny
|
|
iny
|
|
iny
|
|
|
|
bne @FindFreeSlot
|
|
|
|
@InitializeSlot:
|
|
lda #$F4
|
|
sta $0278,y
|
|
|
|
lda #$A8
|
|
sta $027A,y
|
|
|
|
lda #$FF
|
|
sta ghost1Motion,y
|
|
|
|
lda #$00
|
|
sta $001F,y
|
|
|
|
ldy workPtr0
|
|
|
|
lda $89
|
|
sta $0293,y
|
|
|
|
lda #$0C
|
|
sta $028D,y
|
|
|
|
inc $89
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $C8DC-$C8EA: State $04 Per-Frame Object Update Coordinator
|
|
;
|
|
; Local:
|
|
; Runs four update stages in sequence:
|
|
;
|
|
; UpdateTransitionObjectPositions
|
|
; RotateState04ObjectSlots
|
|
; UpdateState04ObjectStatus
|
|
; CheckState04ObjectTrigger
|
|
;
|
|
; After those return, tail-jumps to $DAF1 rather than returning directly.
|
|
;
|
|
; Global:
|
|
; Called once per frame during portions of the state-$04 final sequence.
|
|
; This routine coordinates the lower-level movement/object/display work
|
|
; associated with that sequence.
|
|
;
|
|
; It is called from both State04FinalPhaseActive and
|
|
; State04FinalPhaseComplete.
|
|
;
|
|
; Notes:
|
|
; The exact responsibilities of $EA19, $C92E, $C9FA, CheckState04ObjectTrigger
|
|
; and $DAF1 will be refined as those routines are decoded.
|
|
;
|
|
; The JMP to $DAF1 is a tail call: $DAF1 ultimately returns directly to
|
|
; the original caller of this routine.
|
|
;==============================================================================
|
|
UpdateState04Objects:
|
|
jsr UpdateTransitionObjectPositions
|
|
jsr RotateState04ObjectSlots
|
|
jsr UpdateState04ObjectStatus
|
|
jsr CheckState04ObjectTrigger
|
|
jmp BuildEntitySpriteBuffer
|
|
|
|
;==============================================================================
|
|
; $C8EB-$C92D: Check State $04 Object Trigger
|
|
;
|
|
; Local:
|
|
; Returns immediately when $1A is negative.
|
|
;
|
|
; Otherwise computes:
|
|
;
|
|
; threshold = $0274 + $08
|
|
;
|
|
; and scans four 4-byte structures beginning at $0278.
|
|
;
|
|
; For each active structure, compares its first byte against the threshold.
|
|
; When a qualifying structure is found, uses $89 as an index into a ROM
|
|
; table at $C9EE, installs the resulting value into a per-slot status array,
|
|
; clears a related slot value, initializes $8A to $40, and clears $028C and
|
|
; $0276.
|
|
;
|
|
; Global:
|
|
; Part of UpdateState04Objects. Appears to detect when one of the active
|
|
; state-$04 objects crosses a position threshold relative to the primary
|
|
; value at $0274, then initiates a $40-frame/countdown event through $8A.
|
|
;
|
|
; Notes:
|
|
; $00 holds the comparison threshold ($0274 + $08).
|
|
; $01 tracks the logical object slot while Y steps through four-byte
|
|
; structures.
|
|
;
|
|
; $89 is incremented as part of the event setup.
|
|
;
|
|
; $C9EE is a small ROM lookup table that remains to be decoded.
|
|
;==============================================================================
|
|
|
|
CheckState04ObjectTrigger:
|
|
lda pacmanMotion
|
|
bpl @Continue
|
|
|
|
rts
|
|
|
|
@Continue:
|
|
lda $0274
|
|
clc
|
|
adc #$08
|
|
sta workPtr0
|
|
|
|
ldy #$00
|
|
sty workPtr0+1
|
|
|
|
@ScanObjects:
|
|
lda $0278,y
|
|
beq @NextObject
|
|
|
|
cmp workPtr0
|
|
bcc @TriggerEvent
|
|
|
|
@NextObject:
|
|
inc workPtr0+1
|
|
|
|
iny
|
|
iny
|
|
iny
|
|
iny
|
|
|
|
cpy #$10
|
|
bne @ScanObjects
|
|
|
|
rts
|
|
|
|
@TriggerEvent:
|
|
ldy $89
|
|
inc $89
|
|
|
|
lda #$40
|
|
sta $8A
|
|
|
|
lda $C9EE,y
|
|
|
|
ldy workPtr0+1
|
|
sta $028D,y
|
|
|
|
lda #$00
|
|
sta $0293,y
|
|
|
|
lda #$00
|
|
sta $028C
|
|
sta $0276
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $C92E-$C9B7: Rotate State $04 Object Slots
|
|
;
|
|
; Local:
|
|
; Rotates four related object/state entries across several parallel arrays.
|
|
;
|
|
; The routine operates on:
|
|
;
|
|
; $001E/$001F four-byte-strided zero-page structures
|
|
; $0278-$0287 four 4-byte object structures
|
|
; $028D-$0290 four object/status bytes
|
|
; $0293-$0296 four object/index bytes
|
|
;
|
|
; For each array, the first entry is saved temporarily, entries 1-3 are
|
|
; shifted toward entry 0, and the saved entry 0 is moved to entry 3.
|
|
;
|
|
; Global:
|
|
; Called by UpdateState04Objects every frame, and also directly from
|
|
; State04FinalPhaseComplete while its $8A countdown is active.
|
|
;
|
|
; This appears to cycle the four state-$04 object slots through a fixed
|
|
; ordering while keeping their parallel state/status arrays synchronized.
|
|
;
|
|
; Notes:
|
|
; $00-$03 are temporary storage.
|
|
;
|
|
; The zero-page structures use a four-byte stride but only the first two
|
|
; bytes of each structure are moved here.
|
|
;
|
|
; The $0278 array moves all four bytes of each structure.
|
|
;
|
|
; $028D-$0290 and $0293-$0296 are simple four-entry byte arrays.
|
|
;==============================================================================
|
|
RotateState04ObjectSlots:
|
|
; -------------------------------------------------------------------------
|
|
; Rotate the first two bytes of the four-byte-strided zero-page structures.
|
|
;
|
|
; Entries:
|
|
; 0 -> $001E/$001F
|
|
; 1 -> $0022/$0023
|
|
; 2 -> $0026/$0027
|
|
; 3 -> $002A/$002B
|
|
; -------------------------------------------------------------------------
|
|
|
|
lda ghost1Motion
|
|
sta workPtr0
|
|
|
|
lda ghost1Motion+1
|
|
sta workPtr0+1
|
|
|
|
ldy #$00
|
|
|
|
@ShiftLowRamStructures:
|
|
lda ghost2Motion,y
|
|
sta ghost1Motion,y
|
|
|
|
lda ghost2Motion+1,y
|
|
sta ghost1Motion+1,y
|
|
|
|
iny
|
|
iny
|
|
iny
|
|
iny
|
|
|
|
cpy #$0C
|
|
bne @ShiftLowRamStructures
|
|
|
|
lda workPtr0
|
|
sta ghost4Motion
|
|
|
|
lda workPtr0+1
|
|
sta ghost4Motion+1
|
|
|
|
; -------------------------------------------------------------------------
|
|
; Rotate four complete 4-byte structures at $0278-$0287.
|
|
; -------------------------------------------------------------------------
|
|
|
|
lda $0278
|
|
sta workPtr0
|
|
|
|
lda $0279
|
|
sta workPtr0+1
|
|
|
|
lda $027A
|
|
sta workPtr1
|
|
|
|
lda $027B
|
|
sta workPtr1+1
|
|
|
|
ldy #$00
|
|
|
|
@ShiftObjectStructures:
|
|
lda $027C,y
|
|
sta $0278,y
|
|
|
|
iny
|
|
cpy #$0C
|
|
bne @ShiftObjectStructures
|
|
|
|
lda workPtr0
|
|
sta $0284
|
|
|
|
lda workPtr0+1
|
|
sta $0285
|
|
|
|
lda workPtr1
|
|
sta $0286
|
|
|
|
lda workPtr1+1
|
|
sta $0287
|
|
|
|
; -------------------------------------------------------------------------
|
|
; Rotate the four status bytes at $028D-$0290.
|
|
; -------------------------------------------------------------------------
|
|
|
|
lda $028D
|
|
sta workPtr0
|
|
|
|
ldy #$00
|
|
|
|
@ShiftStatusArray:
|
|
lda $028E,y
|
|
sta $028D,y
|
|
|
|
iny
|
|
cpy #$03
|
|
bne @ShiftStatusArray
|
|
|
|
lda workPtr0
|
|
sta $0290
|
|
|
|
; -------------------------------------------------------------------------
|
|
; Rotate the four associated index/state bytes at $0293-$0296.
|
|
; -------------------------------------------------------------------------
|
|
|
|
lda $0293
|
|
sta workPtr0
|
|
|
|
ldy #$00
|
|
|
|
@ShiftIndexArray:
|
|
lda $0294,y
|
|
sta $0293,y
|
|
|
|
iny
|
|
cpy #$03
|
|
bne @ShiftIndexArray
|
|
|
|
lda workPtr0
|
|
sta $0296
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $C9B8-$C9D7: Animate State $04 Display Pattern
|
|
;
|
|
; Local:
|
|
; Uses the frame counter at $4B to periodically copy one of two four-byte
|
|
; patterns into RAM $024B-$024E.
|
|
;
|
|
; The routine runs only when the low three bits of $4B are zero:
|
|
;
|
|
; ($4B & $07) == 0
|
|
;
|
|
; so the display data is updated once every eight frames.
|
|
;
|
|
; Bit 3 of $4B selects between two adjacent four-byte patterns beginning
|
|
; at $C9F2:
|
|
;
|
|
; bit 3 = 0 -> source $C9F2-$C9F5
|
|
; bit 3 = 1 -> source $C9F6-$C9F9
|
|
;
|
|
; Global:
|
|
; Called by State04FinalPhaseActive once per frame. Provides a simple
|
|
; two-frame animation/blink effect by updating the command/display buffer
|
|
; at $024B according to the NMI-driven frame counter $4B.
|
|
;
|
|
; Notes:
|
|
; $4B is incremented by NmiHandler once per frame.
|
|
;
|
|
; The source data at $C9F2 overlaps the tail of nearby ROM data. We should
|
|
; decode the surrounding $C9D8-$C9F9 region before assigning a more
|
|
; specific visual meaning to the two animation frames.
|
|
;==============================================================================
|
|
AnimateState04DisplayPattern:
|
|
lda frameCounter
|
|
and #$07
|
|
beq @UpdatePattern
|
|
|
|
rts
|
|
|
|
@UpdatePattern:
|
|
ldx #$00
|
|
ldy #$00
|
|
|
|
lda frameCounter
|
|
and #$08
|
|
beq @CopyPattern
|
|
|
|
ldy #$04
|
|
|
|
@CopyPattern:
|
|
lda State04AnimationFrames,y
|
|
sta $024B,x
|
|
|
|
inx
|
|
iny
|
|
|
|
cpx #$04
|
|
bne @CopyPattern
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $C9D8-$C9ED: State $04 Final Display Data
|
|
;==============================================================================
|
|
|
|
State04FinalDisplayData:
|
|
.byte $22,$AD
|
|
.byte $2D,$2D,$2D,$2D,$2D,$2D,$2D,$2D
|
|
.byte $00
|
|
|
|
.byte $22,$ED
|
|
.byte $2D,$2D,$2D,$2D,$2D,$2D,$2D,$2D
|
|
.byte $FF
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $C9EE-$C9F1: Adjacent data, purpose not yet resolved.
|
|
;------------------------------------------------------------------------------
|
|
|
|
State04UnknownData:
|
|
.byte $2D,$2F,$32,$34
|
|
|
|
|
|
;==============================================================================
|
|
; $C9F2-$C9F9: State $04 Animation Frames
|
|
;
|
|
; Two four-byte animation/update frames.
|
|
;
|
|
; $4B bit 3 = 0 -> frame 0
|
|
; $4B bit 3 = 1 -> frame 1
|
|
;==============================================================================
|
|
|
|
State04AnimationFrames:
|
|
.byte $22,$C7,$20,$FF
|
|
.byte $22,$C7,$01,$FF
|
|
|
|
;==============================================================================
|
|
; $C9FA-$CA3F: Update State $04 Object Status Animation
|
|
;
|
|
; Local:
|
|
; Selects an animation/status value from a ROM table at State04ObjectStatusTable and writes
|
|
; the value into active entries of $028D-$0290.
|
|
;
|
|
; The selected table range depends on $1A:
|
|
;
|
|
; $1A negative -> base offset $00
|
|
; $1A nonnegative -> base offset $0A
|
|
;
|
|
; $B7 is incremented each call and its low three bits select an entry from
|
|
; the first lookup range. The resulting value is written to $028C.
|
|
;
|
|
; The routine then updates the four status entries $028D-$0290 only once
|
|
; every eight frames. Bit 3 of $4B selects between two animation phases.
|
|
;
|
|
; Global:
|
|
; Called by UpdateState04Objects during the active state-$04 final sequence.
|
|
; Provides periodic animation/status changes for the four object slots
|
|
; maintained in $028D-$0290.
|
|
;
|
|
; Notes:
|
|
; $B7 behaves as an additional animation counter here.
|
|
;
|
|
; $4B is the NMI-driven frame counter.
|
|
;
|
|
; $028C is updated on every call, while $028D-$0290 are changed only when
|
|
; ($4B & $07) == 0.
|
|
;
|
|
; The table beginning at State04ObjectStatusTable follows this routine immediately and can be
|
|
; decoded separately.
|
|
;==============================================================================
|
|
|
|
UpdateState04ObjectStatus:
|
|
ldx #$00
|
|
|
|
lda $1A
|
|
bmi @UseTableBase
|
|
|
|
ldx #$0A
|
|
|
|
@UseTableBase:
|
|
stx workPtr0
|
|
|
|
inc $B7
|
|
|
|
lda $B7
|
|
and #$07
|
|
clc
|
|
adc workPtr0
|
|
tay
|
|
|
|
lda State04ObjectStatusTable,y
|
|
sta $028C
|
|
|
|
; Only update the four object entries once every eight frames.
|
|
lda $4B
|
|
and #$07
|
|
beq @UpdateObjectEntries
|
|
|
|
rts
|
|
|
|
@UpdateObjectEntries:
|
|
lda frameCounter
|
|
and #$08
|
|
beq @SelectTableValue
|
|
|
|
lda #$01
|
|
|
|
@SelectTableValue:
|
|
clc
|
|
adc workPtr0
|
|
adc #$08
|
|
tay
|
|
|
|
lda State04ObjectStatusTable,y
|
|
sta workPtr0
|
|
|
|
ldy #$00
|
|
|
|
@UpdateStatusEntries:
|
|
lda $028D,y
|
|
beq @NextStatusEntry
|
|
|
|
lda workPtr0
|
|
sta $028D,y
|
|
|
|
@NextStatusEntry:
|
|
iny
|
|
cpy #$04
|
|
bne @UpdateStatusEntries
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $CA40-$CA53: State $04 Object Status/Animation Lookup
|
|
;
|
|
; Local:
|
|
; Twenty-byte lookup table used by UpdateState04ObjectStatus.
|
|
;
|
|
; The routine selects one of two 10-byte groups:
|
|
;
|
|
; $1A negative -> group at offset $00
|
|
; $1A nonnegative -> group at offset $0A
|
|
;
|
|
; Within each group:
|
|
;
|
|
; bytes 0-7 are selected by ($B7 & $07)
|
|
; bytes 8-9 are selected by the slower frame-animation state
|
|
;
|
|
; Global:
|
|
; Supplies animation/status values for the four objects used during the
|
|
; final state-$04 sequence.
|
|
;
|
|
; Notes:
|
|
; Exact meanings of the individual values remain intentionally unnamed
|
|
; until the consumers of $028C and $028D-$0290 are better understood.
|
|
;==============================================================================
|
|
State04ObjectStatusTable:
|
|
; Group 0, selected while $1A is negative.
|
|
.byte $04,$04,$04,$05,$05,$04,$01,$01
|
|
.byte $0C,$0D
|
|
|
|
; Group 1, selected while $1A is nonnegative.
|
|
.byte $08,$08,$08,$09,$09,$08,$01,$01
|
|
.byte $1E,$1F
|
|
|
|
;==============================================================================
|
|
; $CA54-$CAD6: Main Game/Mode Initialization and Dispatch Loop
|
|
;
|
|
; Local:
|
|
; Reconfigures the PPU, waits for VBlank, disables rendering, clears several
|
|
; state variables, and invokes three initialization helpers.
|
|
;
|
|
; Depending on $48, initializes or preserves parts of two parallel RAM
|
|
; regions beginning at $67 and $77. It then initializes additional state,
|
|
; re-enables NMI through PPUCTRL=$88, and synchronizes with NMI via $40.
|
|
;
|
|
; After initialization, enters a persistent foreground loop that:
|
|
;
|
|
; - optionally watches controller bits $0C and returns to MainEntry,
|
|
; - services the countdown at $4C,
|
|
; - uses $3F as a byte offset into an eight-entry dispatch table at $CAD7,
|
|
; - indirect-jumps through $10/$11 to the selected handler.
|
|
;
|
|
; Global:
|
|
; Multiple earlier state-machine paths converge here, making this a major
|
|
; transition point out of the initial/state-$04 sequence and into another
|
|
; top-level game-mode state machine.
|
|
;
|
|
; The routine contains both one-time initialization and the common dispatch
|
|
; loop used by the handlers selected from $CAD7.
|
|
;
|
|
; Notes:
|
|
; $3F is reused as a byte offset into this new dispatch table.
|
|
;
|
|
; $40 continues to provide foreground/NMI synchronization.
|
|
;
|
|
; $4C acts as a countdown/delay gate in the dispatch loop.
|
|
;
|
|
; The exact semantics of $48, $46, $67-$86 and the new dispatch states will
|
|
; be refined as their handlers are decoded.
|
|
;==============================================================================
|
|
GameModeEntry:
|
|
lda #$08
|
|
sta PPUCTRL
|
|
sta ppuCtrlShadow
|
|
|
|
@WaitForVBlank:
|
|
lda PPUSTATUS
|
|
bpl @WaitForVBlank
|
|
|
|
lda #$00
|
|
sta PPUMASK
|
|
sta gameState
|
|
sta cocktailModeFlag
|
|
sta $69
|
|
sta $4A
|
|
|
|
jsr ClearGameplayNametables
|
|
jsr DrawGameplayHudLabels
|
|
jsr DrawGameplayScoreFields
|
|
|
|
lda gameplaySuspended
|
|
beq @ClearPlayerState
|
|
|
|
lda #$01
|
|
sta roundNumber
|
|
|
|
bne @InitializeCommonState
|
|
|
|
@ClearPlayerState:
|
|
lda #$00
|
|
tay
|
|
|
|
@ClearPlayerStateLoop:
|
|
sta roundNumber,y
|
|
iny
|
|
cpy #$20
|
|
bne @ClearPlayerStateLoop
|
|
|
|
lda #$03
|
|
sta roundNumber
|
|
sta $77
|
|
|
|
sta $0600
|
|
sta $0601
|
|
|
|
@InitializeCommonState:
|
|
lda #$FF
|
|
sta roundDisplayValue
|
|
sta $78
|
|
sta $0245
|
|
|
|
lda #$88
|
|
sta ppuCtrlShadow
|
|
sta PPUCTRL
|
|
|
|
GameModeFrameSync:
|
|
@WaitForNextFrame:
|
|
lda #$01
|
|
sta $40
|
|
|
|
@WaitForNmi:
|
|
lda $40
|
|
bne @WaitForNmi
|
|
|
|
@DispatchLoop:
|
|
lda gameplaySuspended
|
|
beq @ProcessDelay
|
|
|
|
lda currentInput
|
|
and #$0C
|
|
beq @ProcessDelay
|
|
|
|
lda #$02 ; TODO: what is state $02?
|
|
sta gameState
|
|
|
|
jmp MainEntry
|
|
|
|
@ProcessDelay:
|
|
lda stateTimer
|
|
beq @DispatchState
|
|
|
|
dec stateTimer
|
|
bne @WaitForNextFrame
|
|
|
|
@DispatchState:
|
|
ldy gameState
|
|
|
|
lda GameModeStateTable,y
|
|
sta dispatchVector
|
|
|
|
lda GameModeStateTable+1,y
|
|
sta dispatchVector+1
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $CAD7-$CAE6: Game Mode State Dispatch Table
|
|
;
|
|
; Local:
|
|
; Eight 16-bit handler addresses selected by GameModeEntry using $3F as a
|
|
; direct byte offset.
|
|
;
|
|
; Global:
|
|
; Defines the next major foreground state machine entered through GameModeEntry.
|
|
;
|
|
; Notes:
|
|
; Since $3F indexes raw bytes rather than words, expected state offsets are:
|
|
;
|
|
; $00,$02,$04,$06,$08,$0A,$0C,$0E
|
|
;
|
|
; Handler names remain unresolved until each target is decoded.
|
|
;==============================================================================
|
|
|
|
GameModeStateTable:
|
|
.word GameModeState00 ; $3F = $00
|
|
.word GameModeState02 ; $3F = $02
|
|
.word GameModeState04 ; $3F = $04
|
|
.word GameModeState06 ; $3F = $06
|
|
.word GameModeState08 ; $3F = $08
|
|
.word GameModeState0A ; $3F = $0A
|
|
.word GameModeState0C ; $3F = $0C
|
|
.word InitializeGameplayTransitionState
|
|
; $3F = $0E
|
|
|
|
;==============================================================================
|
|
; $CAE7-$CAE8: Game-Mode Auxiliary Pointer
|
|
;
|
|
; Local:
|
|
; Two-byte little-endian ROM value containing $E7BF.
|
|
;
|
|
; Global:
|
|
; Sits immediately between GameModeStateTable and the $3F=$04 handler.
|
|
; Its consumer has not yet been established during this pass.
|
|
;
|
|
; Notes:
|
|
; Keep this as data rather than attempting to decode it as 6502 code.
|
|
;==============================================================================
|
|
|
|
GameModeAuxPointer:
|
|
.word $E7BF
|
|
|
|
;==============================================================================
|
|
; $CAE9-$CB5A: Game-Mode State $04 / Pause and Per-Frame Processing
|
|
;
|
|
; Local:
|
|
; First checks $060F. If nonzero, immediately returns to the common
|
|
; NMI/frame synchronization point at $CAA7.
|
|
;
|
|
; Otherwise performs edge detection on controller bit $08 using $49 as
|
|
; the stored previous state.
|
|
;
|
|
; On a new active $08 input:
|
|
; - increments $4A,
|
|
; - installs a short update command at $024B onward,
|
|
; - selects between two command variants according to $47 & $46,
|
|
; - uses bit 0 of $4A to alternate the displayed data,
|
|
; - optionally clears $060F.
|
|
;
|
|
; When no new pause/input edge is being handled, and bit 0 of $4A is clear,
|
|
; calls a sequence of gameplay/update helpers before returning to the common
|
|
; frame synchronization point.
|
|
;
|
|
; Global:
|
|
; Handler selected when GameModeStateTable offset $3F = $04.
|
|
;
|
|
; The adjacent data beginning at $CB5B contains the tile values for the word
|
|
; "PAUSE", strongly indicating that this handler manages pause-state input
|
|
; and display updates while also running the normal per-frame gameplay
|
|
; helper chain when not paused.
|
|
;
|
|
; Notes:
|
|
; $49 stores the previous masked state of controller bit $08.
|
|
; $4A is incremented on each newly detected active edge and bit 0 is used
|
|
; here as a pause/run toggle.
|
|
;
|
|
; $060F is consulted as another gate associated with this handler.
|
|
;
|
|
; Helper routines remain address-named during this pass.
|
|
;==============================================================================
|
|
|
|
GameModeState04:
|
|
lda $060F
|
|
beq @CheckPauseInput
|
|
|
|
jmp GameModeFrameSync
|
|
|
|
@CheckPauseInput:
|
|
lda currentInput
|
|
and #$08
|
|
cmp $49
|
|
beq @ProcessCurrentMode
|
|
|
|
sta $49
|
|
|
|
lda $49
|
|
beq @ProcessCurrentMode
|
|
|
|
inc $4A
|
|
|
|
ldx #$22
|
|
|
|
lda activePlayerFlag
|
|
and cocktailModeFlag
|
|
beq @SetCommandAddress
|
|
|
|
ldx #$2A
|
|
|
|
@SetCommandAddress:
|
|
stx $024B
|
|
|
|
lda #$37
|
|
sta $024C
|
|
|
|
ldx #$06
|
|
ldy #$00
|
|
|
|
lda $4A
|
|
and #$01
|
|
beq @CopyPauseData
|
|
|
|
ldx #$00
|
|
sta $060F
|
|
|
|
@CopyPauseData:
|
|
lda PauseDisplayData,x
|
|
sta $024D,y
|
|
|
|
inx
|
|
iny
|
|
|
|
cpy #$06
|
|
bne @CopyPauseData
|
|
|
|
jmp GameModeFrameSync
|
|
|
|
@ProcessCurrentMode:
|
|
lda $4A
|
|
and #$01
|
|
beq @RunFrameUpdates
|
|
|
|
jmp GameModeFrameSync
|
|
|
|
@RunFrameUpdates:
|
|
jsr UpdateGameplayTimers
|
|
jsr UpdateGameplayTileState
|
|
jsr UpdatePlayerMovement
|
|
jsr UpdatePlayerDirectionAnimation
|
|
jsr UpdateGameplayEntities
|
|
jsr UpdateEntitySpriteStates
|
|
jsr UpdateEntityStatusFlags
|
|
jsr UpdatePeriodicFourEntryState
|
|
jsr CheckGameplayProximity
|
|
jsr CheckEntityCollisions
|
|
|
|
jmp GameModeFrameSync
|
|
|
|
;==============================================================================
|
|
; $CB5B-$CB66: Pause Display Data
|
|
;
|
|
; Local:
|
|
; Two six-byte display strings selected by GameModeState04.
|
|
;
|
|
; Offset $00:
|
|
; "PAUSE",$FF
|
|
;
|
|
; Offset $06:
|
|
; five $2D tiles followed by $FF, used to replace/clear the pause text.
|
|
;
|
|
; Global:
|
|
; Provides the visible pause-state update controlled by $4A bit 0.
|
|
;==============================================================================
|
|
|
|
PauseDisplayData:
|
|
.byte $50,$41,$55,$53,$45,$FF
|
|
.byte $2D,$2D,$2D,$2D,$2D,$FF
|
|
|
|
|
|
;==============================================================================
|
|
; $CB67-$CC9B: Game-Mode State $02 Handler
|
|
;
|
|
; Local:
|
|
; Implements a multi-phase initialization/progression state.
|
|
;
|
|
; When $87 is zero, constructs structured data in RAM page $07 using several
|
|
; ROM lookup tables. The construction is influenced by $48, $47, $46,
|
|
; $68 and $69.
|
|
;
|
|
; Once $87 is nonzero, it advances once per frame. At $87=$78, initializes
|
|
; a new group of RAM state and prepares display/update data in $024B-$0254.
|
|
;
|
|
; At $87=$C0, checks $0600/$0601. If both are zero, clears a large area of
|
|
; page $07 and advances the main game-mode state to $04.
|
|
;
|
|
; Global:
|
|
; Handler selected by GameModeStateTable when $3F=$02. This appears to be
|
|
; a substantial setup/transition state between game-mode phases, preparing
|
|
; object/OAM-related RAM, display command data, and other game state before
|
|
; handing control to GameModeState04.
|
|
;
|
|
; Notes:
|
|
; $87 serves as the phase timer/progression value.
|
|
;
|
|
; $00/$01 initially form a pointer to $0760 during the page-$07 build.
|
|
; The same locations are reused later as temporary display-address values.
|
|
;
|
|
; ROM tables $CC9C-$CCD8 immediately follow this routine and should be
|
|
; decoded next.
|
|
;==============================================================================
|
|
|
|
GameModeState02:
|
|
lda $87
|
|
beq @BuildInitialData
|
|
|
|
jmp @AdvancePhase
|
|
|
|
@BuildInitialData:
|
|
lda #$60
|
|
sta workPtr0
|
|
|
|
lda #$07
|
|
sta workPtr0+1
|
|
|
|
lda $48
|
|
bne @AdvancePhase
|
|
|
|
lda #$02
|
|
sta workValue0
|
|
|
|
ldy #$00
|
|
sty workValue1
|
|
sty workValue2
|
|
sty workValue3
|
|
|
|
@BuildOuterLoop:
|
|
ldx workValue2
|
|
|
|
lda State02PositionTable,x
|
|
sta workPtr1
|
|
|
|
lda State02PositionTable + 1,x
|
|
sta workPtr1+1
|
|
|
|
ldx workValue3
|
|
|
|
lda State02EntryCounts,x
|
|
sta workValue4
|
|
|
|
@BuildInnerLoop:
|
|
lda workPtr1+1
|
|
sta ($00),y
|
|
|
|
ldx workValue1
|
|
|
|
lda State02ValueTableA,x
|
|
iny
|
|
sta (workPtr0),y
|
|
|
|
lda State02ValueTableB,x
|
|
iny
|
|
sta (workPtr0),y
|
|
|
|
lda workPtr1
|
|
iny
|
|
sta ($00),y
|
|
|
|
lda workPtr1
|
|
clc
|
|
adc #$08
|
|
sta workPtr1
|
|
|
|
iny
|
|
inc workValue1
|
|
|
|
dec workValue4
|
|
bne @BuildInnerLoop
|
|
|
|
inc workValue2
|
|
inc workValue2
|
|
inc workValue3
|
|
|
|
lda $69
|
|
bne @ContinueBuild
|
|
|
|
lda roundDisplayValue
|
|
bne @AdvancePhase
|
|
|
|
@ContinueBuild:
|
|
dec workValue0
|
|
beq @CheckPlayerMode
|
|
|
|
bpl @BuildOuterLoop
|
|
bmi @AdvancePhase
|
|
|
|
@CheckPlayerMode:
|
|
lda activePlayerFlag
|
|
beq @AdvancePhase
|
|
|
|
lda cocktailModeFlag
|
|
beq @BuildOuterLoop
|
|
|
|
inc workValue1
|
|
inc workValue1
|
|
inc workValue1
|
|
|
|
bne @BuildOuterLoop
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $CBE4
|
|
; Frame-based progression portion of the same state.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@AdvancePhase:
|
|
lda $87
|
|
cmp #$C0
|
|
bne @IncrementPhase
|
|
|
|
jmp $CC7C
|
|
|
|
@IncrementPhase:
|
|
inc $87
|
|
|
|
lda $87
|
|
cmp #$78
|
|
beq @InitializeMidPhase
|
|
|
|
jmp $CC99
|
|
|
|
@InitializeMidPhase:
|
|
lda #$A8
|
|
sta $1C
|
|
|
|
lda #$60
|
|
sta pacmanMotion
|
|
sta ghost1Motion
|
|
sta ghost2Motion
|
|
|
|
lda #$58
|
|
sta ghost3Motion
|
|
sta $20
|
|
|
|
lda #$68
|
|
sta ghost4Motion
|
|
|
|
lda #$70
|
|
sta $24
|
|
sta $28
|
|
sta $2C
|
|
|
|
lda #$00
|
|
tay
|
|
|
|
@ClearOamRegion:
|
|
sta $0778,y
|
|
iny
|
|
cpy #$24
|
|
bne @ClearOamRegion
|
|
|
|
lda activePlayerFlag
|
|
and cocktailModeFlag
|
|
beq @NoPlayerOffset
|
|
|
|
lda #$08
|
|
|
|
@NoPlayerOffset:
|
|
sta $00
|
|
|
|
lda $67
|
|
sec
|
|
sbc #$01
|
|
asl
|
|
tay
|
|
|
|
lda State02DisplayAddressTable,y
|
|
clc
|
|
adc workPtr0
|
|
sta workPtr0
|
|
|
|
lda State02DisplayAddressTable+1,y
|
|
sta workPtr0+1
|
|
|
|
lda workPtr0
|
|
sta $024B
|
|
|
|
lda workPtr0+1
|
|
sta $024C
|
|
|
|
lda #$2D
|
|
sta $024D
|
|
sta $024E
|
|
|
|
lda #$00
|
|
sta $024F
|
|
|
|
lda $00
|
|
sta $0250
|
|
|
|
lda $01
|
|
clc
|
|
adc #$20
|
|
sta $0251
|
|
|
|
lda #$2D
|
|
sta $0252
|
|
sta $0253
|
|
|
|
lda #$FF
|
|
sta $0254
|
|
|
|
jsr UpdatePlayerDirectionAnimation
|
|
jsr UpdateEntitySpriteStates
|
|
jsr $DA40
|
|
|
|
jmp $CC99
|
|
|
|
@CheckCompletion:
|
|
lda $0600
|
|
ora $0601
|
|
bne $CC99
|
|
|
|
lda $48
|
|
bne @AdvanceMainState
|
|
|
|
lda #$00
|
|
sta $69
|
|
tay
|
|
|
|
@ClearPage07Region:
|
|
sta $0760,y
|
|
iny
|
|
cpy #$A0
|
|
bne @ClearPage07Region
|
|
|
|
@AdvanceMainState:
|
|
lda #$04
|
|
sta $3F
|
|
|
|
@ReturnToFrameLoop:
|
|
jmp GameModeFrameSync
|
|
|
|
;==============================================================================
|
|
; $CC9C-$CCD8: Game-Mode State $02 Lookup Tables
|
|
;
|
|
; Local:
|
|
; Collection of lookup tables consumed by GameModeState02 while constructing
|
|
; page-$07 object/display data and preparing the update command at $024B.
|
|
;
|
|
; Global:
|
|
; Supplies the tile/status/position/count/address parameters used by the
|
|
; state-$02 setup sequence.
|
|
;
|
|
; Notes:
|
|
; The tables are separated according to the exact addresses referenced by
|
|
; GameModeState02. Names remain structural during this first pass.
|
|
;==============================================================================
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $CC9C-$CCAD: State $02 tile/value table
|
|
;
|
|
; Indexed through $05:
|
|
;
|
|
; lda State02ValueTableA,x
|
|
;
|
|
; Written as the second byte of each 4-byte structure generated at $0760+.
|
|
; Length: $12 (18) bytes.
|
|
;------------------------------------------------------------------------------
|
|
|
|
State02ValueTableA:
|
|
.byte $C6,$C3,$C1,$BA,$C7,$BB
|
|
.byte $B0,$B1,$B2,$B3,$B4,$B5
|
|
.byte $B6,$B7,$B4,$B8,$B9,$B6
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $CCAE-$CCBF: State $02 secondary value table
|
|
;
|
|
; Indexed through the same $05 value as State02ValueTableA.
|
|
;
|
|
; Written as the third byte of each generated 4-byte structure.
|
|
; Length: $12 (18) bytes.
|
|
;------------------------------------------------------------------------------
|
|
|
|
State02ValueTableB:
|
|
.byte $00,$00,$00,$00,$00,$00
|
|
.byte $02,$02,$02,$02,$02,$02
|
|
.byte $02,$02,$02,$02,$02,$02
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $CCC0-$CCC5: State $02 position/parameter pairs
|
|
;
|
|
; GameModeState02 accesses this table as overlapping little groups:
|
|
;
|
|
; lda State02PositionTable,x
|
|
; lda State02PositionTable+1,x
|
|
;
|
|
; $06 advances by 2 each outer pass.
|
|
;
|
|
; Therefore the natural structure is three 2-byte pairs.
|
|
;------------------------------------------------------------------------------
|
|
|
|
State02PositionTable:
|
|
.byte $44,$88
|
|
.byte $44,$60
|
|
.byte $50,$70
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $CCC6-$CCC8: State $02 entry-count table
|
|
;
|
|
; Indexed by $07. Determines how many four-byte structures are emitted by
|
|
; each inner construction loop.
|
|
;------------------------------------------------------------------------------
|
|
|
|
State02EntryCounts:
|
|
.byte $06,$06,$03
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $CCC9-$CCD0: Additional state-$02 values
|
|
;
|
|
; No direct reference has yet been established in the portion decoded so far.
|
|
; Keep this data structurally separated until its consumer is found.
|
|
;------------------------------------------------------------------------------
|
|
|
|
State02UnknownData:
|
|
.byte $C0,$C1,$C2,$C3,$C4,$C5,$C3,$C6
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $CCD1-$CCD8: Display-address table
|
|
;
|
|
; Indexed by:
|
|
;
|
|
; ($67 - 1) * 2
|
|
;
|
|
; and read as two-byte values:
|
|
;
|
|
; lda State02DisplayAddressTable,y
|
|
; lda State02DisplayAddressTable+1,y
|
|
;
|
|
; The bytes form four PPU-style address pairs:
|
|
;
|
|
; $2317
|
|
; $2319
|
|
; $231B
|
|
; $2357
|
|
;
|
|
; When $47 & $46 is nonzero, $08 is added to the low byte before the command
|
|
; is placed into $024B/$024C.
|
|
;------------------------------------------------------------------------------
|
|
|
|
State02DisplayAddressTable:
|
|
.byte $23,$17
|
|
.byte $23,$19
|
|
.byte $23,$1B
|
|
.byte $23,$57
|
|
|
|
;==============================================================================
|
|
; $CCD9-$CD05: Game-Mode State $06 Handler
|
|
;
|
|
; Local:
|
|
; Increments $DA each frame. Normally falls through to a group of four
|
|
; per-frame update routines.
|
|
;
|
|
; When $DA reaches $28, resets $DA to $02, changes the main game-mode state
|
|
; to $04, finds an even-indexed entry in $B8+X containing $08, and changes
|
|
; that entry to $06 before continuing through the same update routines.
|
|
;
|
|
; Global:
|
|
; Handler selected by GameModeStateTable when $3F = $06. Implements a timed
|
|
; transition back to game-mode state $04 while continuing normal frame
|
|
; processing throughout the delay.
|
|
;
|
|
; Notes:
|
|
; $DA is used as a frame/progression counter.
|
|
; The $B8 array is searched only at even offsets.
|
|
;==============================================================================
|
|
|
|
GameModeState06:
|
|
inc $DA
|
|
|
|
lda #$28
|
|
cmp $DA
|
|
bne @RunFrameUpdates
|
|
|
|
lda #$02
|
|
sta $DA
|
|
|
|
lda #$04
|
|
sta $3F
|
|
|
|
lda #$08
|
|
|
|
ldx #$FE
|
|
|
|
@FindStateEntry:
|
|
inx
|
|
inx
|
|
cmp $B8,x
|
|
bne @FindStateEntry
|
|
|
|
lda #$06
|
|
sta $B8,x
|
|
|
|
@RunFrameUpdates:
|
|
jsr UpdatePeriodicFourEntryState
|
|
jsr UpdateEntityMovementStates
|
|
jsr UpdateEntitySpriteStates
|
|
jsr $DA40
|
|
|
|
jmp GameModeFrameSync
|
|
|
|
|
|
;==============================================================================
|
|
; $CD06-$CDAF: Game-Mode State $08 Handler
|
|
;
|
|
; Local:
|
|
; Multi-phase timed state using $87, $DB, and $32.
|
|
;
|
|
; During the initial phase, $DB counts down. When it expires, $87 advances,
|
|
; $DB and $0603 are initialized to $0A, and $001E-$0031 are cleared.
|
|
;
|
|
; During the active phase, $DB periodically advances $32 until $32 reaches
|
|
; $1E. The completion logic then updates the two parallel 16-byte state
|
|
; blocks at $67-$76 and $77-$86 and selects the next game-mode state.
|
|
;
|
|
; Global:
|
|
; Handler selected by GameModeStateTable when $3F = $08.
|
|
;
|
|
; Notes:
|
|
; $DB acts as a short-period timer.
|
|
; $87 distinguishes the initial and active phases.
|
|
; $67-$76 and $77-$86 are interchangeable 16-byte state structures.
|
|
;
|
|
; A few cross-flow destinations are kept as raw addresses during this pass
|
|
; to preserve the original control flow exactly.
|
|
;==============================================================================
|
|
|
|
GameModeState08:
|
|
lda $87
|
|
bne @ActivePhase
|
|
|
|
dec $DB
|
|
bne @InitialFrameUpdates
|
|
|
|
inc $87
|
|
|
|
lda #$0A
|
|
sta $DB
|
|
sta $0603
|
|
|
|
lda #$00
|
|
tax
|
|
|
|
@ClearLowRamState:
|
|
sta $1E,x
|
|
inx
|
|
cpx #$14
|
|
bne @ClearLowRamState
|
|
|
|
@InitialFrameUpdates:
|
|
jsr UpdatePeriodicFourEntryState
|
|
jsr UpdateEntitySpriteStates
|
|
jsr $DA40
|
|
|
|
jmp GameModeFrameSync
|
|
|
|
@ActivePhase:
|
|
dec $DB
|
|
bpl @ActiveFrameUpdates
|
|
|
|
lda #$0A
|
|
sta $DB
|
|
|
|
lda $32
|
|
clc
|
|
adc #$01
|
|
sta $32
|
|
|
|
cmp #$1E
|
|
beq @PhaseComplete
|
|
|
|
@ActiveFrameUpdates:
|
|
jsr UpdatePeriodicFourEntryState
|
|
jsr $DA40
|
|
|
|
jmp GameModeFrameSync
|
|
|
|
@PhaseComplete:
|
|
lda $48
|
|
bne @SinglePlayerRestart
|
|
|
|
dec $67
|
|
bne @ContinuePlayerHandling
|
|
|
|
lda #$00
|
|
sta $87
|
|
sta $69
|
|
|
|
lda #$0A
|
|
sta $3F
|
|
|
|
jmp GameModeFrameSync
|
|
|
|
@ContinuePlayerHandling:
|
|
lda #$00
|
|
sta $3F
|
|
|
|
lda #$01
|
|
sta $69
|
|
|
|
lda $47
|
|
beq @CheckPrimaryBlock
|
|
|
|
lda $77
|
|
bne @SwapBlocksAndToggle
|
|
|
|
@CheckPrimaryBlock:
|
|
lda $67
|
|
bne $CDAD
|
|
|
|
sta $69
|
|
|
|
lda $46
|
|
beq @SinglePlayerRestart
|
|
|
|
ldx #$0F
|
|
|
|
@SwapBlocksForMainEntry:
|
|
lda $67,x
|
|
sta $00
|
|
|
|
lda $77,x
|
|
sta $67,x
|
|
|
|
lda $00
|
|
sta $77,x
|
|
|
|
dex
|
|
bpl @SwapBlocksForMainEntry
|
|
|
|
@SinglePlayerRestart:
|
|
lda #$00
|
|
sta $46
|
|
|
|
lda #$00
|
|
sta $3F
|
|
|
|
jmp MainEntry
|
|
|
|
|
|
@SwapBlocksAndToggle:
|
|
ldx #$0F
|
|
|
|
@SwapBlocks:
|
|
lda $67,x
|
|
sta $00
|
|
|
|
lda $77,x
|
|
sta $67,x
|
|
|
|
lda $00
|
|
sta $77,x
|
|
|
|
dex
|
|
bpl @SwapBlocks
|
|
|
|
inc $46
|
|
|
|
lda $46
|
|
and #$01
|
|
sta $46
|
|
|
|
jmp GameModeFrameSync
|
|
|
|
|
|
;==============================================================================
|
|
; $CDB0-$CE1E: Game-Mode State $0C Handler
|
|
;
|
|
; Local:
|
|
; Uses $87 as a frame/progression counter.
|
|
;
|
|
; On first entry ($87 == 0):
|
|
; - Clears $001E-$0031.
|
|
; - Increments $87.
|
|
; - Initializes $32 to $01.
|
|
;
|
|
; On subsequent frames, processing is throttled by the low three bits of
|
|
; the NMI-driven frame counter $4B. Only once every eight frames does the
|
|
; handler:
|
|
;
|
|
; - Alternate a value written to $029E according to bit 0 of $87.
|
|
; - Set $0299 to $0F.
|
|
; - Increment $87.
|
|
;
|
|
; When $87 reaches $10, the routine clears $1A/$1C/$87 and selects a new
|
|
; main game-mode state according to the value at $68.
|
|
;
|
|
; Global:
|
|
; Handler selected by GameModeStateTable when $3F = $0C.
|
|
;
|
|
; This appears to implement a short visual/timed transition. The write of
|
|
; $0F to $0299 interacts directly with the palette-update mechanism decoded
|
|
; earlier, while $029E lies inside that first 16-byte palette/update buffer.
|
|
;
|
|
; Notes:
|
|
; $4B is the NMI-driven frame counter.
|
|
;
|
|
; $87 advances only once every eight frames after initialization.
|
|
;
|
|
; $68 controls which state is selected when the sequence completes.
|
|
;==============================================================================
|
|
|
|
GameModeState0C:
|
|
lda $87
|
|
bne @TimedPhase
|
|
|
|
ldx #$00
|
|
|
|
@ClearLowRam:
|
|
sta $1E,x
|
|
inx
|
|
cpx #$14
|
|
bne @ClearLowRam
|
|
|
|
inc $87
|
|
|
|
lda #$01
|
|
sta $32
|
|
|
|
bne @RunFrameUpdates
|
|
|
|
|
|
@TimedPhase:
|
|
lda $4B
|
|
and #$07
|
|
bne @RunFrameUpdates
|
|
|
|
ldx #$11
|
|
|
|
lda $87
|
|
and #$01
|
|
bne @SetPaletteValue
|
|
|
|
ldx #$20
|
|
|
|
@SetPaletteValue:
|
|
stx $029E
|
|
|
|
lda #$0F
|
|
sta $0299
|
|
|
|
inc $87
|
|
|
|
lda #$10
|
|
cmp $87
|
|
bne @RunFrameUpdates
|
|
|
|
lda #$00
|
|
sta $1A
|
|
sta $1C
|
|
sta $87
|
|
|
|
lda $68
|
|
cmp #$01
|
|
beq @SelectState0E
|
|
|
|
inc $87
|
|
inc $87
|
|
|
|
cmp #$04
|
|
beq @SelectState0E
|
|
|
|
inc $87
|
|
inc $87
|
|
|
|
cmp #$08
|
|
beq @SelectState0E
|
|
|
|
cmp #$0C
|
|
beq @SelectState0E
|
|
|
|
cmp #$10
|
|
bne @SelectState00
|
|
|
|
|
|
@SelectState0E:
|
|
lda #$0E
|
|
sta $3F
|
|
|
|
jmp @RunFrameUpdates
|
|
|
|
|
|
@SelectState00:
|
|
lda #$00
|
|
sta $3F
|
|
|
|
|
|
@RunFrameUpdates:
|
|
jsr UpdatePeriodicFourEntryState
|
|
jsr $DA40
|
|
|
|
jmp GameModeFrameSync
|
|
|
|
|
|
;==============================================================================
|
|
; $CE1F-$CEBE: Game-Mode State $0A Handler
|
|
;
|
|
; Local:
|
|
; Uses $87 to distinguish between initialization and subsequent processing.
|
|
;
|
|
; On initial entry:
|
|
; - Fills $0700-$075F with $FF.
|
|
; - Initializes $00/$01 as a pointer to $0760.
|
|
; - Builds structured four-byte records in page $07 from several ROM
|
|
; lookup tables beginning at $CEBF.
|
|
;
|
|
; The builder uses:
|
|
;
|
|
; $00/$01 destination pointer ($0760)
|
|
; $02/$03 per-group values
|
|
; $04 outer pass counter, initially $03
|
|
; $05 shared table index
|
|
; $06 index into the value-pair table
|
|
; $07 index into the entry-count table
|
|
; $08 inner record counter
|
|
;
|
|
; Player/mode variables $47, $77, and $46 influence whether passes repeat
|
|
; and whether the lookup index is advanced.
|
|
;
|
|
; After the construction phase, $87 is incremented. A later entry either
|
|
; clears $0760-$07FF and transitions to the code at $CD5E, or simply
|
|
; returns to the common frame loop.
|
|
;
|
|
; Global:
|
|
; Handler selected by GameModeStateTable when $3F = $0A.
|
|
;
|
|
; Structurally this is closely related to GameModeState02, but uses a
|
|
; different set of ROM tables and first clears $0700-$075F to $FF. Both
|
|
; handlers construct arrays of four-byte records in page $07.
|
|
;
|
|
; Notes:
|
|
; The tables at $CEBF-$CEF2 are decoded immediately after this routine.
|
|
; Semantic object names are deferred until the page-$07 consumers are
|
|
; understood more completely.
|
|
;==============================================================================
|
|
|
|
GameModeState0A:
|
|
lda $87
|
|
beq @Initialize
|
|
|
|
jmp $CEAA
|
|
|
|
@Initialize:
|
|
ldy #$00
|
|
|
|
lda #$FF
|
|
|
|
@FillPage07Prefix:
|
|
sta $0700,y
|
|
iny
|
|
cpy #$60
|
|
bne @FillPage07Prefix
|
|
|
|
lda #$60
|
|
sta $00
|
|
|
|
lda #$07
|
|
sta $01
|
|
|
|
lda #$03
|
|
sta $04
|
|
|
|
ldy #$00
|
|
sty $05
|
|
sty $06
|
|
sty $07
|
|
|
|
@BuildOuterLoop:
|
|
ldx $06
|
|
|
|
lda State0AParameterPairs,x
|
|
sta $02
|
|
|
|
lda State0AParameterPairs+1,x
|
|
sta $03
|
|
|
|
ldx $07
|
|
|
|
lda State0AEntryCounts,x
|
|
sta $08
|
|
|
|
|
|
@BuildInnerLoop:
|
|
lda $03
|
|
sta ($00),y
|
|
|
|
ldx $05
|
|
|
|
lda State0AValueTableA,x
|
|
iny
|
|
sta ($00),y
|
|
|
|
lda State0AValueTableB,x
|
|
iny
|
|
sta ($00),y
|
|
|
|
lda $02
|
|
iny
|
|
sta ($00),y
|
|
|
|
lda $02
|
|
clc
|
|
adc #$08
|
|
sta $02
|
|
|
|
iny
|
|
inc $05
|
|
|
|
dec $08
|
|
bne @BuildInnerLoop
|
|
|
|
inc $06
|
|
inc $06
|
|
|
|
inc $07
|
|
|
|
lda $47
|
|
beq @ContinueOuterPass
|
|
|
|
lda $77
|
|
bne @ContinueOuterPass
|
|
|
|
lda $04
|
|
cmp #$02
|
|
beq $CEAA
|
|
|
|
|
|
@ContinueOuterPass:
|
|
dec $04
|
|
beq @CheckPlayerMode
|
|
|
|
bpl @BuildOuterLoop
|
|
bmi @FinishInitialization
|
|
|
|
|
|
@CheckPlayerMode:
|
|
lda $47
|
|
beq @FinishInitialization
|
|
|
|
lda $46
|
|
beq @BuildOuterLoop
|
|
|
|
|
|
@AdjustTableIndex:
|
|
inc $05
|
|
inc $05
|
|
inc $05
|
|
|
|
bne @BuildOuterLoop
|
|
|
|
|
|
@FinishInitialization:
|
|
inc $87
|
|
bne @ReturnToFrameLoop
|
|
|
|
|
|
@PostInitialization:
|
|
lda #$00
|
|
tay
|
|
|
|
@ClearPage07Region:
|
|
sta $0760,y
|
|
iny
|
|
cpy #$A0
|
|
bne @ClearPage07Region
|
|
|
|
jmp $CD5E
|
|
|
|
|
|
@ReturnToFrameLoop:
|
|
jmp GameModeFrameSync
|
|
|
|
|
|
;==============================================================================
|
|
; $CEBF-$CEF2: Game-Mode State $0A Lookup Tables
|
|
;
|
|
; Local:
|
|
; Lookup data used by GameModeState0A to construct four-byte records in
|
|
; page $07.
|
|
;
|
|
; Global:
|
|
; Provides the object/tile/value and layout parameters for state $0A.
|
|
;==============================================================================
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $CEBF-$CED2: Primary value table
|
|
; Length: $14 (20) bytes
|
|
;------------------------------------------------------------------------------
|
|
|
|
State0AValueTableA:
|
|
.byte $BC,$B2,$BD,$B4,$B6,$BE,$B4,$B5
|
|
.byte $B0,$B1,$B2,$B3,$B4,$B5,$B6,$B7
|
|
.byte $B4,$B8,$B9,$B6
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $CED3-$CEE6: Secondary value table
|
|
; Length: $14 (20) bytes
|
|
;------------------------------------------------------------------------------
|
|
|
|
State0AValueTableB:
|
|
.byte $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byte $02,$02,$02,$02,$02,$02,$02,$02
|
|
.byte $02,$02,$02,$02
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $CEE7-$CEEE: Parameter-pair table
|
|
;
|
|
; $06 advances by two, so represent this as four 2-byte pairs.
|
|
;------------------------------------------------------------------------------
|
|
|
|
State0AParameterPairs:
|
|
.byte $38,$88
|
|
.byte $60,$88
|
|
.byte $44,$60
|
|
.byte $50,$70
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $CEEF-$CEF2: Inner-loop entry counts
|
|
;------------------------------------------------------------------------------
|
|
|
|
State0AEntryCounts:
|
|
.byte $04,$04,$06,$03
|
|
|
|
;==============================================================================
|
|
; $CEF3-$D0AA: Game-Mode State $00 Initialization
|
|
;
|
|
; Local:
|
|
; Performs the main initialization for the game-mode state machine:
|
|
;
|
|
; - Synchronizes with NMI and disables rendering.
|
|
; - Clears working RAM $87-$EF.
|
|
; - Clears page $0700-$07FF.
|
|
; - Copies a 32-byte palette table from GameplayPaletteData to $0299-$02B8.
|
|
; - Selects game-mode state $02.
|
|
; - Initializes gameplay/state variables and invokes several setup helpers.
|
|
; - Loads numerous parameters from ROM lookup tables.
|
|
; - Initializes arrays and display/update data.
|
|
; - Re-enables NMI with PPUCTRL=$88.
|
|
; - Returns to GameModeFrameSync.
|
|
;
|
|
; Global:
|
|
; Primary initialization handler for GameModeStateTable offset $00.
|
|
; Establishes the working state used by the later $02/$04/etc. handlers.
|
|
;
|
|
; Notes:
|
|
; Many ROM tables referenced from $EBxx/$ECxx are intentionally left raw
|
|
; during this pass and will be named when those regions are reached.
|
|
;==============================================================================
|
|
|
|
GameModeState00:
|
|
lda #$01
|
|
sta $40
|
|
|
|
@WaitForNmi:
|
|
lda $40
|
|
bne @WaitForNmi
|
|
|
|
lda #$08
|
|
sta PPUCTRL
|
|
sta $43
|
|
|
|
lda #$00
|
|
sta PPUMASK
|
|
|
|
ldx #$00
|
|
|
|
@ClearWorkingRam:
|
|
sta $87,x
|
|
inx
|
|
cpx #$69
|
|
bne @ClearWorkingRam
|
|
|
|
tax
|
|
|
|
@ClearPage07:
|
|
sta $0700,x
|
|
inx
|
|
bne @ClearPage07
|
|
|
|
ldy #$00
|
|
|
|
@LoadPalette:
|
|
lda GameplayPaletteData,y
|
|
sta $0299,y
|
|
iny
|
|
cpy #$20
|
|
bne @LoadPalette
|
|
|
|
lda #$02
|
|
sta $3F
|
|
|
|
lda $69
|
|
bne $CF4A
|
|
|
|
sta $8B
|
|
|
|
lda #$01
|
|
sta $6C
|
|
sta $6D
|
|
sta $6E
|
|
sta $6F
|
|
|
|
lda #$C0
|
|
sta $6A
|
|
|
|
lda $68
|
|
cmp #$16
|
|
beq @SkipIncrement68
|
|
|
|
inc $68
|
|
|
|
@SkipIncrement68:
|
|
jsr InitializeGameplayAttributes
|
|
jsr DrawMazeNametable
|
|
jsr DrawGameplayScoreFields
|
|
jsr InitializeGameNametableRegion
|
|
jsr DrawLevelProgressMarkers
|
|
jsr $E5C1
|
|
jsr DrawGameplayHudLabels
|
|
|
|
@ContinueSetup:
|
|
ldx $68
|
|
|
|
lda #$00
|
|
clc
|
|
|
|
@MultiplyBy6:
|
|
dex
|
|
bmi @MultiplyBy6Done
|
|
|
|
adc #$06
|
|
bne @MultiplyBy6
|
|
|
|
@MultiplyBy6Done:
|
|
sta $00
|
|
tax
|
|
|
|
lda $EBB6,x
|
|
tax
|
|
|
|
lda #$00
|
|
clc
|
|
|
|
@MultiplyBy22:
|
|
dex
|
|
bmi @MultiplyBy22Done
|
|
|
|
adc #$16
|
|
bne @MultiplyBy22
|
|
|
|
@MultiplyBy22Done:
|
|
tay
|
|
|
|
ldx #$00
|
|
|
|
@CopyGameParameters:
|
|
lda $EC40,y
|
|
sta $9F,x
|
|
inx
|
|
iny
|
|
cpx #$16
|
|
bne @CopyGameParameters
|
|
|
|
ldx $00
|
|
|
|
lda $EBB6,x
|
|
asl
|
|
asl
|
|
asl
|
|
tax
|
|
|
|
ldy #$00
|
|
sty $D0
|
|
|
|
; Save the first selected table value separately.
|
|
lda $ECAE,x
|
|
sta $CF
|
|
|
|
@CopyTableECae:
|
|
lda $ECAE,x
|
|
sta $0097,y
|
|
|
|
inx
|
|
iny
|
|
cpy #$08
|
|
bne @CopyTableECae
|
|
|
|
inc $00
|
|
|
|
ldx $00
|
|
lda $EBB6,x
|
|
sta $8C
|
|
|
|
inc $00
|
|
|
|
ldx $00
|
|
lda $EBB6,x
|
|
asl
|
|
tax
|
|
|
|
lda $ECCE,x
|
|
sta $8D
|
|
inx
|
|
lda $ECCE,x
|
|
sta $8E
|
|
|
|
inc $00
|
|
|
|
lda $69
|
|
beq @UseAlternateData
|
|
|
|
ldx #$0C
|
|
ldy #$00
|
|
|
|
lda $ECDC,x
|
|
sta $008F,y
|
|
|
|
iny
|
|
inx
|
|
|
|
lda #$C0
|
|
sec
|
|
sbc $6A
|
|
sta $01
|
|
|
|
@CopyOffsetData:
|
|
lda $01
|
|
clc
|
|
adc $ECDC,x
|
|
sta $008F,y
|
|
|
|
iny
|
|
inx
|
|
|
|
cpy #$04
|
|
bne @CopyOffsetData
|
|
|
|
beq @InitializeArray
|
|
|
|
@UseAlternateData:
|
|
ldx $00
|
|
|
|
lda $EBB6,x
|
|
asl
|
|
asl
|
|
tax
|
|
|
|
ldy #$00
|
|
|
|
@CopyAlternateData:
|
|
lda $ECDC,x
|
|
sta $008F,y
|
|
|
|
inx
|
|
iny
|
|
cpy #$04
|
|
bne @CopyAlternateData
|
|
|
|
|
|
@InitializeArray:
|
|
lda #$04
|
|
sta $B8
|
|
|
|
lda #$01
|
|
sta $B9
|
|
|
|
lda $8F
|
|
sta $01
|
|
|
|
ldx #$00
|
|
|
|
@InitializeArrayLoop:
|
|
dec $01
|
|
beq @InitializeArrayTail
|
|
|
|
lda #$02
|
|
sta $BA,x
|
|
|
|
lda #$00
|
|
sta $BB,x
|
|
|
|
inx
|
|
inx
|
|
bne @InitializeArrayLoop
|
|
|
|
|
|
@InitializeArrayTail:
|
|
lda #$00
|
|
|
|
@ClearRemainingArray:
|
|
cpx #$06
|
|
beq @ContinueFinalSetup
|
|
|
|
sta $BA,x
|
|
sta $BB,x
|
|
|
|
inx
|
|
inx
|
|
bne @ClearRemainingArray
|
|
|
|
|
|
@ContinueFinalSetup:
|
|
lda $90
|
|
sta $D3
|
|
|
|
inc $00
|
|
|
|
ldx $00
|
|
lda $EBB6,x
|
|
sta $93
|
|
|
|
inc $00
|
|
|
|
ldx $00
|
|
lda $EBB6,x
|
|
sta $96
|
|
|
|
lda $A5
|
|
sta $B5
|
|
|
|
lda $A6
|
|
sta $B6
|
|
|
|
lda $AF
|
|
sta $C4
|
|
sta $C6
|
|
sta $C8
|
|
sta $CA
|
|
|
|
lda $B0
|
|
sta $C5
|
|
sta $C7
|
|
sta $C9
|
|
sta $CB
|
|
|
|
lda #$01
|
|
sta $50
|
|
sta $51
|
|
|
|
ldy #$00
|
|
ldx #$00
|
|
|
|
lda $46
|
|
and $47
|
|
beq @CopyDisplayInit
|
|
|
|
ldy #$09
|
|
|
|
@CopyDisplayInit:
|
|
lda GameDisplayInitialData,y
|
|
sta $026B,x
|
|
|
|
iny
|
|
inx
|
|
cpx #$09
|
|
bne @CopyDisplayInit
|
|
|
|
ldy #$00
|
|
|
|
@CopyStateData:
|
|
lda GameStateInitialValues,y
|
|
sta $0032,y
|
|
iny
|
|
cpy #$0C
|
|
bne @CopyStateData
|
|
|
|
ldy #$00
|
|
|
|
@NormalizeValues:
|
|
lda $006C,y
|
|
cmp #$02
|
|
bne @NextNormalizeValue
|
|
|
|
lda #$01
|
|
sta $006C,y
|
|
|
|
@NextNormalizeValue:
|
|
iny
|
|
cpy #$04
|
|
bne @NormalizeValues
|
|
|
|
sty $C0
|
|
|
|
lda #$FF
|
|
sta $89
|
|
|
|
lda #$88
|
|
sta PPUCTRL
|
|
sta $43
|
|
|
|
jmp GameModeFrameSync
|
|
|
|
;==============================================================================
|
|
; $D0AB-$D0F2: Initialize/Clear Repeated Nametable Region
|
|
;
|
|
; Local:
|
|
; Selects an initial PPU destination based on ($46 & $47):
|
|
;
|
|
; zero -> $2256
|
|
; nonzero -> $2A56
|
|
;
|
|
; It then performs 10 iterations. For each iteration:
|
|
;
|
|
; - Sets PPUADDR to the current destination.
|
|
; - Writes six $20 tiles.
|
|
; - Writes two $2D tiles.
|
|
; - Advances the destination address by $20.
|
|
;
|
|
; Global:
|
|
; Called from GameModeState00 during game/round initialization while
|
|
; rendering is disabled. This prepares the same rectangular display region
|
|
; in one of two nametable locations depending on the current player/mode
|
|
; state represented by $46/$47.
|
|
;
|
|
; Notes:
|
|
; $00/$01 form the current 16-bit PPU destination address.
|
|
; $02 counts 10 rows.
|
|
; $03 counts the six $20 tile writes in each row.
|
|
;
|
|
; $20 and $2D are retained as raw tile IDs during this pass.
|
|
;==============================================================================
|
|
|
|
InitializeGameNametableRegion:
|
|
ldy #$22
|
|
|
|
lda $46
|
|
and $47
|
|
beq @SetDestination
|
|
|
|
ldy #$2A
|
|
|
|
@SetDestination:
|
|
sty $00
|
|
|
|
lda #$56
|
|
sta $01
|
|
|
|
lda #$0A
|
|
sta $02
|
|
|
|
@NextRow:
|
|
lda PPUSTATUS
|
|
|
|
lda $00
|
|
sta PPUADDR
|
|
|
|
lda $01
|
|
sta PPUADDR
|
|
|
|
lda #$06
|
|
sta $03
|
|
|
|
lda #$20
|
|
|
|
@WriteInterior:
|
|
sta PPUDATA
|
|
|
|
dec $03
|
|
bne @WriteInterior
|
|
|
|
lda #$2D
|
|
sta PPUDATA
|
|
sta PPUDATA
|
|
|
|
; Advance the destination by one full nametable row ($20 bytes).
|
|
lda $01
|
|
clc
|
|
adc #$20
|
|
sta $01
|
|
|
|
lda $00
|
|
adc #$00
|
|
sta $00
|
|
|
|
dec $02
|
|
bne @NextRow
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D0F3-$D130: Game-Mode State $00 Initialization Data
|
|
;
|
|
; Local:
|
|
; Contains three adjacent data blocks consumed during GameModeState00:
|
|
;
|
|
; $D0F3-$D0FE 12-byte state initialization table
|
|
; $D0FF-$D110 18-byte display/update table
|
|
; $D111-$D130 32-byte palette table
|
|
;
|
|
; Global:
|
|
; Supplies initial state, display-command, and palette data used when
|
|
; GameModeState00 prepares a new game/round state.
|
|
;
|
|
; Notes:
|
|
; The display table is intentionally kept as raw tile/command bytes during
|
|
; this pass. GameModeState00 selects either offset $00 or $09 from this
|
|
; table and copies nine bytes to $026B-$0273.
|
|
;
|
|
; The palette table is copied in full to $0299-$02B8.
|
|
;==============================================================================
|
|
|
|
|
|
;==============================================================================
|
|
; $D0F3-$D0FE: Game State Initialization Values
|
|
;
|
|
; Local:
|
|
; 12 bytes copied directly to zero-page RAM $32-$3D:
|
|
;
|
|
; ROM $D0F3-$D0FE -> RAM $0032-$003D
|
|
;
|
|
; Global:
|
|
; Establishes a compact block of initial game-state values during
|
|
; GameModeState00.
|
|
;
|
|
; Notes:
|
|
; Individual fields remain unnamed until their consumers are traced.
|
|
;==============================================================================
|
|
|
|
GameStateInitialValues:
|
|
.byte $04,$0C,$0A,$0A
|
|
.byte $0A,$00,$00,$00
|
|
.byte $01,$02,$03,$00
|
|
|
|
|
|
;==============================================================================
|
|
; $D0FF-$D110: Game Display Initialization Data
|
|
;
|
|
; Local:
|
|
; Contains two 9-byte records. GameModeState00 selects the first record when
|
|
; ($46 & $47) is zero and the second record when it is nonzero.
|
|
;
|
|
; The selected nine bytes are copied to RAM $026B-$0273.
|
|
;
|
|
; Global:
|
|
; Provides alternate display/update initialization according to the active
|
|
; player/mode state.
|
|
;
|
|
; Notes:
|
|
; These bytes appear to mix PPU/update-command values and tile IDs.
|
|
; Preserve them numerically until the consumer of $026B is decoded.
|
|
;==============================================================================
|
|
GameDisplayInitialData:
|
|
|
|
; Record 0, selected when ($46 & $47) == 0.
|
|
; $D0FF-$D107
|
|
.byte $21,$36,$20,$F7,$B0,$B3,$B2,$20,$B6
|
|
|
|
; Record 1, selected when ($46 & $47) != 0.
|
|
; $D108-$D110
|
|
.byte $29,$B6,$29,$77,$B1,$B3,$B2,$28,$B6
|
|
|
|
|
|
;==============================================================================
|
|
; $D111-$D130: Initial Gameplay Palette
|
|
;
|
|
; Local:
|
|
; Complete 32-byte palette copied to RAM $0299-$02B8 by GameModeState00.
|
|
; The NMI palette-update mechanism later transfers these buffers into PPU
|
|
; palette RAM.
|
|
;
|
|
; Global:
|
|
; Defines the initial background and sprite color palettes used for normal
|
|
; gameplay/game-mode initialization.
|
|
;
|
|
; Notes:
|
|
; $D111-$D120 contains four background palettes.
|
|
; $D121-$D130 contains four sprite palettes.
|
|
;
|
|
; Palette values are retained as NES color indices.
|
|
;==============================================================================
|
|
GameplayPaletteData:
|
|
; Background palette 0
|
|
.byte $0F,$20,$0F,$06
|
|
|
|
; Background palette 1
|
|
.byte $0F,$11,$0F,$27
|
|
|
|
; Background palette 2
|
|
.byte $0F,$16,$26,$06
|
|
|
|
; Background palette 3
|
|
.byte $0F,$19,$17,$12
|
|
|
|
; Sprite palette 0
|
|
.byte $0F,$27,$20,$06
|
|
|
|
; Sprite palette 1
|
|
.byte $0F,$11,$20,$33
|
|
|
|
; Sprite palette 2
|
|
.byte $0F,$21,$20,$21
|
|
|
|
; Sprite palette 3
|
|
.byte $0F,$09,$20,$17
|
|
|
|
;==============================================================================
|
|
; $D131-$D15F: Initialize Gameplay Nametable Attributes
|
|
;
|
|
; Local:
|
|
; Copies the 64-byte attribute table at $D160 to two PPU destinations:
|
|
;
|
|
; pass 1 -> PPU $23C0-$23FF
|
|
; pass 2 -> PPU $2BC0-$2BFF
|
|
;
|
|
; The first pass uses X=$01. After copying all $40 bytes, X is decremented.
|
|
; Since X becomes zero, execution falls through into the setup for the
|
|
; second destination at $2BC0.
|
|
;
|
|
; After the second copy, X decrements from $00 to $FF and the routine
|
|
; returns.
|
|
;
|
|
; Global:
|
|
; Called by GameModeState00 during game/round initialization. Initializes
|
|
; complete attribute tables for two nametables using identical palette-
|
|
; selection data.
|
|
;
|
|
; Notes:
|
|
; The branch at $D15E intentionally jumps back into the shared copy loop
|
|
; after selecting PPU address $2BC0.
|
|
;
|
|
; $D160 begins the 64-byte attribute source table and is not executable.
|
|
;==============================================================================
|
|
|
|
InitializeGameplayAttributes:
|
|
lda PPUSTATUS
|
|
|
|
lda #$23
|
|
sta PPUADDR
|
|
|
|
lda #$C0
|
|
sta PPUADDR
|
|
|
|
ldx #$01
|
|
|
|
@CopyAttributeTable:
|
|
ldy #$00
|
|
|
|
@CopyAttributeBytes:
|
|
lda GameplayAttributeData,y
|
|
sta PPUDATA
|
|
|
|
iny
|
|
cpy #$40
|
|
bne @CopyAttributeBytes
|
|
|
|
dex
|
|
beq @SetupSecondNametable
|
|
|
|
rts
|
|
|
|
@SetupSecondNametable:
|
|
lda PPUSTATUS
|
|
|
|
lda #$2B
|
|
sta PPUADDR
|
|
|
|
lda #$C0
|
|
sta PPUADDR
|
|
|
|
bne @CopyAttributeTable
|
|
|
|
;==============================================================================
|
|
; $D160-$D19F: Gameplay Nametable Attribute Data
|
|
;
|
|
; Local:
|
|
; Complete 64-byte NES attribute table copied to both PPU $23C0-$23FF and
|
|
; $2BC0-$2BFF by InitializeGameplayAttributes.
|
|
;
|
|
; Global:
|
|
; Defines background-palette selections for the gameplay nametables.
|
|
;
|
|
; Notes:
|
|
; Common values:
|
|
;
|
|
; $00 -> palette 0 in all four attribute quadrants
|
|
; $55 -> palette 1 in all four quadrants
|
|
;
|
|
; Values such as $11, $51, $50 and $05 combine different palette selections
|
|
; within the four quadrants of an attribute byte.
|
|
;==============================================================================
|
|
|
|
GameplayAttributeData:
|
|
.byte $55,$55,$55,$55,$55,$11,$00,$00
|
|
.byte $55,$55,$55,$55,$55,$11,$00,$00
|
|
.byte $55,$55,$55,$55,$55,$11,$00,$00
|
|
.byte $55,$55,$55,$55,$55,$51,$50,$50
|
|
.byte $55,$55,$55,$55,$55,$11,$05,$05
|
|
.byte $55,$55,$55,$55,$55,$11,$00,$00
|
|
.byte $55,$55,$55,$55,$55,$55,$55,$55
|
|
.byte $55,$55,$55,$55,$55,$55,$55,$55
|
|
|
|
;==============================================================================
|
|
; $D1A0-$D289: Gameplay Timers and State Progression
|
|
;
|
|
; Local:
|
|
; Updates several gameplay timers, palette-animation values, progression
|
|
; counters, and state variables.
|
|
;
|
|
; Global:
|
|
; Called once per active gameplay frame from GameModeState04. Coordinates
|
|
; several independent timing and progression systems.
|
|
;
|
|
; Notes:
|
|
; Address-based local labels are used during this pass to make the original
|
|
; branch destinations explicit and simplify byte-identical verification.
|
|
;==============================================================================
|
|
|
|
UpdateGameplayTimers:
|
|
lda $89
|
|
bmi @D1E1
|
|
|
|
inc $8A
|
|
|
|
lda #$3C
|
|
cmp $8A
|
|
bne @D1C9
|
|
|
|
lda #$00
|
|
sta $8A
|
|
|
|
dec $89
|
|
bpl @D1C9
|
|
|
|
sta $88
|
|
|
|
ldx #$00
|
|
|
|
@D1B7:
|
|
lda $39,x
|
|
and #$FC
|
|
sta $00
|
|
|
|
txa
|
|
ora $00
|
|
sta $39,x
|
|
|
|
inx
|
|
cpx #$04
|
|
bne @D1B7
|
|
|
|
@D1C9:
|
|
lda $89
|
|
cmp #$02
|
|
bcs @D1E1
|
|
|
|
ldx #$11
|
|
|
|
lda $8A
|
|
and #$08
|
|
bne @D1D9
|
|
|
|
ldx #$20
|
|
|
|
@D1D9:
|
|
stx $02AE
|
|
|
|
lda #$0F
|
|
sta $02A9
|
|
|
|
|
|
@D1E1:
|
|
lda $88
|
|
bne @D213
|
|
|
|
lda $CF
|
|
cmp #$FF
|
|
beq @D213
|
|
|
|
inc $D1
|
|
|
|
lda $D1
|
|
cmp #$3C
|
|
bne @D213
|
|
|
|
lda #$00
|
|
sta $D1
|
|
|
|
dec $CF
|
|
bpl @D213
|
|
|
|
inc $D0
|
|
|
|
lda $D0
|
|
and #$01
|
|
beq @D209
|
|
|
|
jsr $E08E
|
|
|
|
lda #$0F
|
|
bne @D20B
|
|
|
|
@D209:
|
|
lda $D2
|
|
|
|
@D20B:
|
|
sta $87
|
|
|
|
ldx $D0
|
|
lda $97,x
|
|
sta $CF
|
|
|
|
|
|
@D213:
|
|
lda $D3
|
|
beq @D236
|
|
|
|
clc
|
|
adc $6A
|
|
cmp #$C0
|
|
bne @D236
|
|
|
|
jsr ActivateNextStateEntry
|
|
|
|
lda $D3
|
|
ldx #$00
|
|
|
|
@D225:
|
|
cmp $8F,x
|
|
bne @D231
|
|
|
|
inx
|
|
lda $8F,x
|
|
sta $D3
|
|
|
|
jmp @D236
|
|
|
|
@D231:
|
|
inx
|
|
cpx #$04
|
|
bne @D225
|
|
|
|
|
|
@D236:
|
|
inc $D6
|
|
|
|
lda #$60
|
|
cmp $D6
|
|
bne @D251
|
|
|
|
lda #$00
|
|
sta $D6
|
|
|
|
inc $D5
|
|
|
|
lda $D5
|
|
cmp $96
|
|
bne @D251
|
|
|
|
lda #$00
|
|
sta $D5
|
|
|
|
jsr ActivateNextStateEntry
|
|
|
|
|
|
@D251:
|
|
ldx $D4
|
|
|
|
cpx #$02
|
|
beq @D26E
|
|
|
|
lda $8D,x
|
|
cmp $6A
|
|
bne @D26E
|
|
|
|
inc $D4
|
|
|
|
lda #$01
|
|
sta $D2
|
|
|
|
txa
|
|
asl
|
|
tax
|
|
|
|
lda $AB,x
|
|
sta $CA
|
|
|
|
lda $AC,x
|
|
sta $CB
|
|
|
|
|
|
@D26E:
|
|
ora $D7
|
|
ora $D8
|
|
beq @D289
|
|
|
|
dec $D8
|
|
bne @D289
|
|
|
|
lda $D7
|
|
beq @D283
|
|
|
|
dec $D7
|
|
|
|
lda #$3C
|
|
sta $D8
|
|
|
|
rts
|
|
|
|
|
|
@D283:
|
|
sta $2E
|
|
sta $30
|
|
sta $8B
|
|
|
|
|
|
@D289:
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D28A-$D29B: Activate First Available State Entry
|
|
;
|
|
; Local:
|
|
; Searches the even-indexed entries at $BA, $BC, and $BE for the first
|
|
; zero value.
|
|
;
|
|
; When a zero entry is found, replaces it with $02 and returns.
|
|
;
|
|
; If all three entries are already nonzero, returns without modifying them.
|
|
;
|
|
; Global:
|
|
; Called by UpdateGameplayTimers when certain progression timers expire.
|
|
; This appears to activate the next available entry in a three-element
|
|
; state array.
|
|
;
|
|
; Notes:
|
|
; Only the even addresses $BA/$BC/$BE are examined. The interleaved bytes
|
|
; $BB/$BD/$BF form a parallel field initialized elsewhere.
|
|
;
|
|
; The meaning of state value $02 will be refined when the consumers of
|
|
; $BA-$BF are decoded.
|
|
;==============================================================================
|
|
ActivateNextStateEntry:
|
|
ldx #$00
|
|
|
|
@FindAvailableEntry:
|
|
lda $BA,x
|
|
bne @NextEntry
|
|
|
|
lda #$02
|
|
sta $BA,x
|
|
|
|
rts
|
|
|
|
@NextEntry:
|
|
inx
|
|
inx
|
|
|
|
cpx #$06
|
|
bne @FindAvailableEntry
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D29C-$D2A3: Sequential Tile/Value Table
|
|
;
|
|
; Local:
|
|
; Eight sequential values from $24 through $2B.
|
|
;
|
|
; Global:
|
|
; Consumer has not yet been decoded during this pass. Given the sequential
|
|
; values and the surrounding graphics-oriented code, this may represent
|
|
; tile IDs or animation values.
|
|
;
|
|
; Notes:
|
|
; Keep the table generically named until a direct reference establishes its
|
|
; exact purpose.
|
|
;==============================================================================
|
|
|
|
SequentialValueTableD29C:
|
|
.byte $24,$25,$26,$27,$28,$29,$2A,$2B
|
|
|
|
|
|
|
|
;==============================================================================
|
|
; $D2A4-$D36B: Gameplay Proximity / State Transition Handler
|
|
;
|
|
; Local:
|
|
; Returns immediately when $6A is zero.
|
|
;
|
|
; Otherwise scans even-indexed state entries beginning at $B8. Entries whose
|
|
; state value is $04 undergo two proximity tests using the four-byte
|
|
; structures beginning at $001E.
|
|
;
|
|
; $02 is shifted once for each scanned entry and acts as a candidate bitmask.
|
|
; When a qualifying entry is found, the routine selects one of several state
|
|
; transition paths based on X and ($02 & $88).
|
|
;
|
|
; Global:
|
|
; Called during normal gameplay processing from GameModeState04. This
|
|
; routine appears to detect proximity/collision conditions and initiate
|
|
; corresponding gameplay-state transitions.
|
|
;
|
|
; Notes:
|
|
; $00/$01 form a temporary pointer, initially $001E.
|
|
; $02 is a shifting bitmask.
|
|
; $03 is temporary storage for distance/index calculations.
|
|
;
|
|
; Lookup tables begin at ProximityCandidateValues and will be decoded separately.
|
|
;==============================================================================
|
|
CheckGameplayProximity:
|
|
lda $6A
|
|
bne @Start
|
|
|
|
rts
|
|
|
|
@Start:
|
|
lda #$1E
|
|
sta $00
|
|
|
|
lda #$00
|
|
sta $01
|
|
|
|
lda #$01
|
|
sta $02
|
|
|
|
ldx #$00
|
|
|
|
@ScanEntries:
|
|
lda $B8,x
|
|
cmp #$04
|
|
bne @NextEntry
|
|
|
|
ldy #$00
|
|
|
|
lda $1A
|
|
cmp ($00),y
|
|
bcs @FirstAxisReverse
|
|
|
|
lda ($00),y
|
|
sec
|
|
sbc $1A
|
|
bcs @CheckFirstAxisDistance
|
|
|
|
@FirstAxisReverse:
|
|
sbc ($00),y
|
|
|
|
@CheckFirstAxisDistance:
|
|
cmp #$0A
|
|
bcs @NextEntry
|
|
|
|
sta $03
|
|
|
|
ldy #$02
|
|
|
|
lda $1C
|
|
cmp ($00),y
|
|
bcs @SecondAxisReverse
|
|
|
|
lda ($00),y
|
|
sec
|
|
sbc $1C
|
|
bcs @CheckSecondAxisDistance
|
|
|
|
@SecondAxisReverse:
|
|
sbc ($00),y
|
|
|
|
@CheckSecondAxisDistance:
|
|
cmp #$0A
|
|
bcs @NextEntry
|
|
|
|
adc $03
|
|
cmp #$05
|
|
bcc @CandidateFound
|
|
|
|
|
|
@NextEntry:
|
|
inx
|
|
inx
|
|
|
|
lda $00
|
|
clc
|
|
adc #$04
|
|
sta $00
|
|
|
|
asl $02
|
|
|
|
cpx #$0A
|
|
bne @ScanEntries
|
|
|
|
rts
|
|
|
|
|
|
@CandidateFound:
|
|
cpx #$08
|
|
beq @ProcessSecondaryState
|
|
|
|
lda $02
|
|
and $88
|
|
beq @SpecialCandidate
|
|
|
|
txa
|
|
lsr
|
|
sta $03
|
|
|
|
ldy $D9
|
|
|
|
lda ProximityCandidateValues,y
|
|
|
|
ldy $03
|
|
sta $0033,y
|
|
|
|
lda #$00
|
|
sta $32
|
|
|
|
ldy $D9
|
|
|
|
lda ProximityDDValues,y
|
|
sta $DD
|
|
|
|
lda ProximityDEValues,y
|
|
sta $DE
|
|
|
|
inc $D9
|
|
|
|
lda #$08
|
|
sta $B8,x
|
|
sta $0607
|
|
|
|
lda #$06
|
|
sta $3F
|
|
|
|
jmp $E0E6
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D337
|
|
; Candidate path selected when ($02 & $88) == 0.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@SpecialCandidate:
|
|
lda #$08
|
|
sta $3F
|
|
|
|
lda #$12
|
|
sta $32
|
|
|
|
lda #$80
|
|
sta $DB
|
|
|
|
lda #$00
|
|
sta $87
|
|
|
|
rts
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D348
|
|
; Special path selected when X == $08.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@ProcessSecondaryState:
|
|
lda $8B
|
|
beq @InitializeSecondaryState
|
|
|
|
rts
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D34D
|
|
; Initialize secondary state.
|
|
;------------------------------------------------------------------------------
|
|
@InitializeSecondaryState:
|
|
sta $D7
|
|
|
|
lda #$80
|
|
sta $D8
|
|
sta $8B
|
|
sta $0606
|
|
|
|
ldy $93
|
|
|
|
lda SecondaryStateDDValues,y
|
|
sta $DD
|
|
|
|
lda SecondaryStateDEValues,y
|
|
sta $DE
|
|
|
|
lda SecondaryState37Values,y
|
|
sta $37
|
|
|
|
jmp $E0E6
|
|
|
|
;==============================================================================
|
|
; $D36C-$D38F: Gameplay Proximity / Transition Lookup Data
|
|
;
|
|
; Local:
|
|
; Lookup data used by CheckGameplayProximity when a qualifying proximity
|
|
; condition triggers a gameplay-state transition.
|
|
;
|
|
; Global:
|
|
; Supplies values written to $33+, $37, $DD and $DE during the different
|
|
; transition paths handled by CheckGameplayProximity.
|
|
;
|
|
; Notes:
|
|
; $D370 is intentionally a label inside the table beginning at $D36C.
|
|
; No bytes are duplicated.
|
|
;==============================================================================
|
|
ProximityCandidateValues:
|
|
; $D36C-$D36F
|
|
.byte $2D,$2F,$32,$34
|
|
|
|
SecondaryState37Values:
|
|
; $D370-$D373
|
|
; Also forms bytes 4-7 of ProximityCandidateValues.
|
|
.byte $2C,$2E,$30,$31
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D374-$D377
|
|
; Consumer not yet established.
|
|
;------------------------------------------------------------------------------
|
|
ProximityUnknownTableD374:
|
|
.byte $33,$35,$36,$37
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D378-$D37B
|
|
; Indexed by $D9 and loaded into $DE.
|
|
;------------------------------------------------------------------------------
|
|
ProximityDEValues:
|
|
.byte $00,$00,$00,$01
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D37C-$D37F
|
|
; Indexed by $D9 and loaded into $DD.
|
|
;------------------------------------------------------------------------------
|
|
ProximityDDValues:
|
|
.byte $02,$04,$08,$06
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D380-$D387
|
|
; Indexed by $93 and loaded into $DD.
|
|
;------------------------------------------------------------------------------
|
|
SecondaryStateDDValues:
|
|
.byte $01,$03,$05,$07
|
|
.byte $00,$00,$00,$00
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D388-$D38F
|
|
; Indexed by $93 and loaded into $DE.
|
|
;------------------------------------------------------------------------------
|
|
SecondaryStateDEValues:
|
|
.byte $00,$00,$00,$00
|
|
.byte $01,$02,$03,$05
|
|
|
|
;==============================================================================
|
|
; $D390-...: Gameplay Direction / Movement Processing
|
|
;
|
|
; Local:
|
|
; Processes directional controller input, validates a requested direction
|
|
; against the current map/tile state, and selects movement parameters.
|
|
;
|
|
; Global:
|
|
; Called during normal gameplay processing from GameModeState04.
|
|
;
|
|
; Notes:
|
|
; Address-derived labels are retained during this pass to make branch
|
|
; targets explicit while maintaining byte identity.
|
|
;==============================================================================
|
|
|
|
UpdatePlayerMovement:
|
|
lda $48
|
|
beq @D397
|
|
|
|
jmp $D506
|
|
|
|
@D397:
|
|
lda $4F
|
|
and #$F0
|
|
beq @D3D2
|
|
|
|
ldx #$FF
|
|
|
|
@D39F:
|
|
inx
|
|
asl
|
|
bcc @D39F
|
|
|
|
lda InputDirectionTable,x
|
|
sta $50
|
|
|
|
clc
|
|
adc #$02
|
|
and #$03
|
|
cmp $51
|
|
bne @D3C9
|
|
|
|
lda $1A
|
|
ora $1C
|
|
and #$07
|
|
bne @D3C2
|
|
|
|
ldy $50
|
|
|
|
lda $022B,y
|
|
and #$F0
|
|
bne @D3C9
|
|
|
|
|
|
@D3C2:
|
|
lda $50
|
|
sta $51
|
|
|
|
jmp @D3D6
|
|
|
|
|
|
@D3C9:
|
|
ldx $50
|
|
|
|
lda $022B,x
|
|
and #$F0
|
|
beq @D3D6
|
|
|
|
|
|
@D3D2:
|
|
lda $51
|
|
sta $50
|
|
|
|
|
|
@D3D6:
|
|
ldx #$04
|
|
|
|
lda $88
|
|
bne @D3DE
|
|
|
|
ldx #$0A
|
|
|
|
@D3DE:
|
|
lda $022A
|
|
cmp #$01
|
|
beq @D3F4
|
|
|
|
cmp #$02
|
|
beq @D3F4
|
|
|
|
dex
|
|
dex
|
|
|
|
cmp #$03
|
|
beq @D3F4
|
|
|
|
cmp #$09
|
|
beq @D3F4
|
|
|
|
dex
|
|
dex
|
|
|
|
|
|
@D3F4:
|
|
lda $9F,x
|
|
sta $B5
|
|
|
|
lda $A0,x
|
|
sta $B6
|
|
|
|
lda $51
|
|
asl
|
|
tay
|
|
|
|
lda MovementArithmeticTable,y
|
|
sta $10
|
|
|
|
lda MovementArithmeticTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $D40E-$D415: Movement Arithmetic Dispatch Table
|
|
;
|
|
; Local:
|
|
; Four 16-bit handlers selected using the internal direction value in $51.
|
|
;
|
|
; Global:
|
|
; Dispatches into direction-specific coordinate arithmetic used by
|
|
; UpdatePlayerMovement.
|
|
;
|
|
; Notes:
|
|
; Direction semantics remain unnamed during this pass.
|
|
;==============================================================================
|
|
MovementArithmeticTable:
|
|
.word $D416
|
|
.word $D41A
|
|
.word $D435
|
|
.word $D431
|
|
;==============================================================================
|
|
; $D416-$D443: Direction-Specific Movement Arithmetic
|
|
;
|
|
; Local:
|
|
; Four entry points selected by MovementArithmeticTable converge into two
|
|
; shared arithmetic paths.
|
|
;
|
|
; $D416/$D41A select the coordinate component and enter subtraction.
|
|
; $D431/$D435 select the coordinate component and enter addition.
|
|
;
|
|
; Global:
|
|
; Computes the fixed-point movement result used by the second direction
|
|
; dispatch beginning at MovementApplyResult.
|
|
;
|
|
; Notes:
|
|
; Shared labels are deliberately non-local because multiple entry-point
|
|
; labels must branch into the same code.
|
|
;==============================================================================
|
|
|
|
MovementArithmeticD416:
|
|
ldx #$02
|
|
bne MovementSubtract
|
|
|
|
MovementArithmeticD41A:
|
|
ldx #$00
|
|
|
|
MovementSubtract:
|
|
lda $1B,x
|
|
sec
|
|
sbc $B5
|
|
sta $1B,x
|
|
|
|
lda #$00
|
|
bcs MovementSubtractNoBorrow
|
|
|
|
lda #$01
|
|
|
|
MovementSubtractNoBorrow:
|
|
clc
|
|
adc $B6
|
|
sta $CC
|
|
|
|
jmp MovementApplyResult
|
|
|
|
|
|
MovementArithmeticD431:
|
|
ldx #$00
|
|
beq MovementAdd
|
|
|
|
|
|
MovementArithmeticD435:
|
|
ldx #$02
|
|
|
|
|
|
MovementAdd:
|
|
lda $1B,x
|
|
clc
|
|
adc $B5
|
|
sta $1B,x
|
|
|
|
lda #$00
|
|
adc $B6
|
|
sta $CC
|
|
|
|
;==============================================================================
|
|
; $D444-$D459: Apply Movement Result and Dispatch Direction Handler
|
|
;
|
|
; Local:
|
|
; Decrements the movement accumulator $CC. If it becomes negative, returns
|
|
; immediately.
|
|
;
|
|
; Otherwise uses the current direction value at $51 as a byte offset into a
|
|
; four-entry handler table beginning at $D45A.
|
|
;
|
|
; Global:
|
|
; Second stage of UpdatePlayerMovement. After the fixed-point arithmetic
|
|
; performed by the $D416-$D443 handlers, this dispatches to the actual
|
|
; direction-specific coordinate/tile movement code.
|
|
;
|
|
; Notes:
|
|
; $51 is multiplied by two before indexing the pointer table.
|
|
;==============================================================================
|
|
|
|
MovementApplyResult:
|
|
dec $CC
|
|
bpl @D449
|
|
|
|
rts
|
|
|
|
|
|
@D449:
|
|
lda $51
|
|
asl
|
|
tay
|
|
|
|
lda MovementDirectionTable,y
|
|
sta $10
|
|
|
|
lda MovementDirectionTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $D45A-$D461: Direction-Specific Movement Dispatch Table
|
|
;
|
|
; Local:
|
|
; Four handlers selected according to the internal direction value in $51.
|
|
;
|
|
; Notes:
|
|
; Handler names remain address-based until coordinate effects are fully
|
|
; mapped to semantic direction names.
|
|
;==============================================================================
|
|
|
|
MovementDirectionTable:
|
|
.word MovementDirectionD49A
|
|
.word MovementDirectionD490
|
|
.word MovementDirectionD46C
|
|
.word MovementDirectionD462
|
|
|
|
;==============================================================================
|
|
; $D462-$D501: Direction-Specific Movement Handlers
|
|
;
|
|
; Local:
|
|
; Four entry points selected by MovementDirectionTable.
|
|
;
|
|
; $D462 and $D46C enter the increment path.
|
|
; $D490 and $D49A enter the decrement path.
|
|
;
|
|
; X selects which coordinate component at $1A/$1C is modified. $00 and $01
|
|
; preserve working indexes used for collision/tile checks against $022B.
|
|
;
|
|
; After movement, the shared tail handles coordinate wrapping/state flags
|
|
; and, when aligned to an 8-unit boundary, commits a requested direction
|
|
; change from $50 to $51.
|
|
;
|
|
; Global:
|
|
; Final stage of UpdatePlayerMovement. Applies movement to the player's
|
|
; coordinate state and reconciles requested direction changes.
|
|
;
|
|
; Notes:
|
|
; Entry points intentionally share code. Use non-local labels for shared
|
|
; targets so ca65 scope rules do not change the branch structure.
|
|
;==============================================================================
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D462
|
|
; Increment coordinate component X=0.
|
|
;------------------------------------------------------------------------------
|
|
|
|
MovementDirectionD462:
|
|
ldx #$00
|
|
stx $00
|
|
|
|
lda #$03
|
|
sta $01
|
|
|
|
bne MovementIncrement
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D46C
|
|
; Increment coordinate component X=2.
|
|
;------------------------------------------------------------------------------
|
|
|
|
MovementDirectionD46C:
|
|
ldx #$02
|
|
stx $00
|
|
stx $01
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D472: Shared increment path.
|
|
;------------------------------------------------------------------------------
|
|
|
|
MovementIncrement:
|
|
lda $1A,x
|
|
clc
|
|
adc #$01
|
|
sta $1A,x
|
|
|
|
and #$04
|
|
bne MovementSharedTail
|
|
|
|
ldx $01
|
|
|
|
lda $022B,x
|
|
and #$F0
|
|
beq MovementSharedTail
|
|
|
|
ldx $00
|
|
|
|
lda $1A,x
|
|
and #$FC
|
|
sta $1A,x
|
|
|
|
bne MovementSharedTail
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D490
|
|
; Decrement coordinate component X=0.
|
|
;------------------------------------------------------------------------------
|
|
|
|
MovementDirectionD490:
|
|
ldx #$00
|
|
stx $00
|
|
|
|
lda #$01
|
|
sta $01
|
|
|
|
bne MovementDecrement
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D49A
|
|
; Decrement coordinate component X=2.
|
|
;------------------------------------------------------------------------------
|
|
|
|
MovementDirectionD49A:
|
|
ldx #$02
|
|
stx $00
|
|
|
|
lda #$00
|
|
sta $01
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D4A2: Shared decrement path.
|
|
;------------------------------------------------------------------------------
|
|
|
|
MovementDecrement:
|
|
lda $1A,x
|
|
sec
|
|
sbc #$01
|
|
sta $1A,x
|
|
|
|
and #$04
|
|
beq MovementSharedTail
|
|
|
|
ldx $01
|
|
|
|
lda $022B,x
|
|
and #$F0
|
|
beq MovementSharedTail
|
|
|
|
ldx $00
|
|
|
|
lda $1A,x
|
|
clc
|
|
adc #$04
|
|
and #$FC
|
|
sta $1A,x
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D4C1: Shared movement/wrap tail.
|
|
;------------------------------------------------------------------------------
|
|
|
|
MovementSharedTail:
|
|
lda $1A
|
|
|
|
cmp #$18
|
|
bcc MovementCheckLeftWrap
|
|
|
|
cmp #$A9
|
|
bcs MovementCheckLeftWrap
|
|
|
|
lda $38
|
|
and #$DF
|
|
bcc MovementStoreWrapState
|
|
|
|
MovementCheckLeftWrap:
|
|
lda #$20
|
|
ora $38
|
|
|
|
MovementStoreWrapState:
|
|
sta $38
|
|
|
|
lda $1A
|
|
cmp #$0B
|
|
bcs MovementCheckRightWrap
|
|
|
|
lda #$BF
|
|
sta $1A
|
|
bne MovementCheckAlignment
|
|
|
|
MovementCheckRightWrap:
|
|
cmp #$C0
|
|
bcc MovementCheckAlignment
|
|
|
|
lda #$0B
|
|
sta $1A
|
|
|
|
|
|
MovementCheckAlignment:
|
|
lda $1A
|
|
ora $1C
|
|
and #$07
|
|
bne MovementReturnToArithmetic
|
|
|
|
lda $50
|
|
cmp $51
|
|
beq MovementReturnToArithmetic
|
|
|
|
sta $51
|
|
|
|
inc $CC
|
|
inc $CC
|
|
|
|
|
|
MovementReturnToArithmetic:
|
|
jmp MovementApplyResult
|
|
|
|
;==============================================================================
|
|
; $D502-$D505: Controller Direction Mapping
|
|
;==============================================================================
|
|
|
|
InputDirectionTable:
|
|
.byte $03,$01,$02,$00
|
|
|
|
;==============================================================================
|
|
; $D506-$D51E: Scripted Direction/Input Update
|
|
;
|
|
; Local:
|
|
; Uses $E3 as a countdown and $E4 as an offset into the table beginning at
|
|
; $D51F.
|
|
;
|
|
; Each time $E3 reaches zero:
|
|
; - Advances $E4 by two.
|
|
; - Loads a new duration from $D51F+$E4 into $E3.
|
|
;
|
|
; It then takes the following table byte, masks it to two bits, and
|
|
; tail-jumps into UpdatePlayerMovement at $D3A6 with that value in A.
|
|
;
|
|
; Global:
|
|
; Entered from UpdatePlayerMovement when $48 is nonzero. This provides a
|
|
; scripted/autonomous direction source in place of normal controller input.
|
|
;
|
|
; Notes:
|
|
; $E4 indexes two-byte table records:
|
|
;
|
|
; byte 0 = duration/count
|
|
; byte 1 = direction/control value
|
|
;
|
|
; The second byte is masked with #$03 before entering movement processing.
|
|
;==============================================================================
|
|
|
|
UpdateScriptedDirection:
|
|
ldy $E4
|
|
|
|
dec $E3
|
|
bne @UseCurrentEntry
|
|
|
|
inc $E4
|
|
inc $E4
|
|
|
|
ldy $E4
|
|
|
|
lda ScriptedDirectionTable,y
|
|
sta $E3
|
|
|
|
@UseCurrentEntry:
|
|
lda ScriptedDirectionTable+1,y
|
|
and #$03
|
|
|
|
jmp $D3A6
|
|
|
|
;==============================================================================
|
|
; $D51F-...: Scripted Direction Table
|
|
;
|
|
; Local:
|
|
; Two-byte records used by UpdateScriptedDirection:
|
|
;
|
|
; byte 0 = duration
|
|
; byte 1 = direction/control number
|
|
;
|
|
; Global:
|
|
; Drives autonomous/scripted movement when $48 selects this path instead of
|
|
; normal player controller processing.
|
|
;==============================================================================
|
|
ScriptedDirectionTable:
|
|
.byte $00,$01
|
|
.byte $D0,$00
|
|
.byte $28,$01
|
|
.byte $28,$02
|
|
.byte $90,$03
|
|
.byte $38,$00
|
|
.byte $20,$03
|
|
.byte $18,$01
|
|
.byte $60,$02
|
|
.byte $30,$01
|
|
.byte $10,$02
|
|
.byte $48,$01
|
|
.byte $18,$02
|
|
.byte $40,$01
|
|
.byte $20,$02
|
|
.byte $18,$00
|
|
.byte $20,$03
|
|
.byte $40,$02
|
|
.byte $38,$01
|
|
.byte $18,$02
|
|
.byte $E0,$03
|
|
.byte $30,$00
|
|
.byte $28,$01
|
|
.byte $28,$02
|
|
.byte $20,$02
|
|
.byte $80,$03
|
|
.byte $40,$00
|
|
.byte $40,$01
|
|
|
|
;==============================================================================
|
|
; $D557-$D586: Update Four Gameplay Entities
|
|
;
|
|
; Local:
|
|
; Iterates four gameplay entries using X offsets:
|
|
;
|
|
; $00, $02, $04, $06
|
|
;
|
|
; Initializes several temporary values before the loop:
|
|
;
|
|
; $00 = $2F
|
|
; $01 = $02
|
|
; $02 = $1E
|
|
; $03 = $00
|
|
; $04 = $01
|
|
;
|
|
; For each entry, calls the dispatcher at $D587. After each call:
|
|
;
|
|
; $00 += 4
|
|
; $02 += 4
|
|
; $04 <<= 1
|
|
; X += 2
|
|
;
|
|
; Processing ends after X reaches $08.
|
|
;
|
|
; Global:
|
|
; Called every active gameplay frame from GameModeState04. Coordinates
|
|
; per-entry updates for four gameplay entities/state slots.
|
|
;
|
|
; Notes:
|
|
; $00 and $02 appear to advance through parallel four-byte-strided RAM
|
|
; structures.
|
|
;
|
|
; $04 becomes a per-entry bitmask:
|
|
;
|
|
; $01,$02,$04,$08
|
|
;
|
|
; The exact roles of the temporary values will become clearer as the
|
|
; dispatcher at $D587 and its handlers are decoded.
|
|
;==============================================================================
|
|
|
|
UpdateGameplayEntities:
|
|
ldx #$00
|
|
|
|
lda #$2F
|
|
sta $00
|
|
|
|
lda #$02
|
|
sta $01
|
|
|
|
lda #$1E
|
|
sta $02
|
|
|
|
lda #$00
|
|
sta $03
|
|
|
|
lda #$01
|
|
sta $04
|
|
|
|
@UpdateNextEntity:
|
|
jsr $D587
|
|
|
|
lda $00
|
|
clc
|
|
adc #$04
|
|
sta $00
|
|
|
|
lda $02
|
|
clc
|
|
adc #$04
|
|
sta $02
|
|
|
|
asl $04
|
|
|
|
inx
|
|
inx
|
|
|
|
cpx #$08
|
|
bne @UpdateNextEntity
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D587-$D595: Gameplay Entity State Dispatcher
|
|
;
|
|
; Local:
|
|
; Reads the state value for the current entity from $B8,X and uses that
|
|
; value directly as a byte offset into EntityStateTable.
|
|
;
|
|
; The selected 16-bit handler address is copied to $10/$11 and execution
|
|
; transfers to it with an indirect JMP.
|
|
;
|
|
; Global:
|
|
; Called by UpdateGameplayEntities once for each of four gameplay entity
|
|
; slots. This provides the per-entity state machine used by those entries.
|
|
;
|
|
; Notes:
|
|
; X identifies the current entry using even offsets:
|
|
;
|
|
; $00,$02,$04,$06
|
|
;
|
|
; $B8,X is a byte offset into the pointer table, so valid state values are
|
|
; even:
|
|
;
|
|
; $00,$02,$04,$06,$08
|
|
;==============================================================================
|
|
|
|
DispatchGameplayEntityState:
|
|
ldy $B8,x
|
|
|
|
lda EntityStateTable,y
|
|
sta $10
|
|
|
|
lda EntityStateTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $D596-$D59F: Gameplay Entity State Table
|
|
;
|
|
; Local:
|
|
; Five 16-bit handlers indexed directly by the even state value stored in
|
|
; $B8,X.
|
|
;
|
|
; Global:
|
|
; Defines the per-entity state machine used by
|
|
; DispatchGameplayEntityState.
|
|
;
|
|
; Notes:
|
|
; States $04 and $06 deliberately share the same handler at $D5A1.
|
|
; State $08 targets $D5A0, one byte before that shared handler, suggesting
|
|
; another intentional overlapping entry point.
|
|
;==============================================================================
|
|
|
|
EntityStateTable:
|
|
.word $D8D5 ; state $00
|
|
.word $D885 ; state $02
|
|
.word $D5A1 ; state $04
|
|
.word $D5A1 ; state $06
|
|
.word EntityState08 ; state $08
|
|
|
|
;==============================================================================
|
|
; $D5A0: Entity State $08 Handler
|
|
;
|
|
; Local:
|
|
; Returns immediately.
|
|
;
|
|
; Global:
|
|
; The entity-state table uses this as the handler for state $08, effectively
|
|
; disabling further processing for that entity state.
|
|
;==============================================================================
|
|
|
|
EntityState08:
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $D5A1-$D5B4: Entity State $04/$06 Secondary Dispatcher
|
|
;
|
|
; Local:
|
|
; Called for entity states $04 and $06 from EntityStateTable.
|
|
;
|
|
; First invokes the common entity helper at $D821. It then reads the
|
|
; secondary state value at $B9,X, doubles it, and uses the result as a byte
|
|
; offset into a four-entry pointer table at $D5B5.
|
|
;
|
|
; The selected address is stored in $10/$11 and execution transfers through
|
|
; an indirect JMP.
|
|
;
|
|
; Global:
|
|
; Provides a second-level state machine for gameplay entities whose primary
|
|
; state at $B8,X is $04 or $06.
|
|
;
|
|
; Notes:
|
|
; $B9,X behaves as an ordinal secondary state here. Unlike several earlier
|
|
; state tables, the value is explicitly multiplied by two before indexing
|
|
; the pointer table.
|
|
;==============================================================================
|
|
|
|
DispatchEntitySecondaryState:
|
|
jsr $D821
|
|
|
|
lda $B9,x
|
|
asl
|
|
tay
|
|
|
|
lda EntitySecondaryStateTable,y
|
|
sta $10
|
|
|
|
lda EntitySecondaryStateTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $D5B5-$D5BC: Entity Secondary-State Dispatch Table
|
|
;
|
|
; Local:
|
|
; Four handler addresses selected using ($B9,X * 2).
|
|
;
|
|
; Global:
|
|
; Defines the second-level state machine used by primary entity states
|
|
; $04 and $06.
|
|
;==============================================================================
|
|
|
|
EntitySecondaryStateTable:
|
|
.word EntitySecondaryState0 ; secondary state 0
|
|
.word EntitySecondaryState1 ; secondary state 1
|
|
.word EntitySecondaryState2 ; secondary state 2
|
|
.word EntitySecondaryState3 ; secondary state 3
|
|
|
|
;==============================================================================
|
|
; $D5BD-$D5D2: Secondary-State Coordinate Adjustment
|
|
;
|
|
; Local:
|
|
; Secondary state 2 enters at $D5BD and selects Y=$03.
|
|
; Secondary state 3 enters at $D5C1 and selects Y=$01.
|
|
;
|
|
; Both then read through the indirect pointer at $02/$03, add the
|
|
; entity-specific values at $C2,X/$C3,X, write the low-byte result back
|
|
; through the pointer, and store the high-byte result in $CC.
|
|
;
|
|
; Control then tail-jumps to $D5EB.
|
|
;
|
|
; Global:
|
|
; Shared movement/update arithmetic for two secondary entity states.
|
|
;
|
|
; Notes:
|
|
; $02/$03 were initialized by UpdateGameplayEntities and advance by four
|
|
; bytes per entity, so they identify the current entity's four-byte state
|
|
; structure.
|
|
;==============================================================================
|
|
|
|
EntitySecondaryState2:
|
|
ldy #$03
|
|
bne EntitySecondaryAdjust
|
|
|
|
EntitySecondaryState3:
|
|
ldy #$01
|
|
|
|
EntitySecondaryAdjust:
|
|
lda ($02),y
|
|
clc
|
|
adc $C2,x
|
|
sta ($02),y
|
|
|
|
lda #$00
|
|
adc $C3,x
|
|
sta $CC
|
|
|
|
jmp $D5EB
|
|
|
|
;==============================================================================
|
|
; $D5D3-$D5EE: Entity Secondary States $00/$01 Movement Arithmetic
|
|
;
|
|
; Local:
|
|
; Secondary state 0 enters at $D5D3 and selects Y=$03.
|
|
; Secondary state 1 enters at $D5D7 and selects Y=$01.
|
|
;
|
|
; Both subtract the entity-specific movement value at $C2,X from the
|
|
; structure addressed by $02/$03. Borrow is converted into a high-byte
|
|
; adjustment using $C3,X and stored in $CC.
|
|
;
|
|
; Afterward, $CC is decremented. A negative result returns immediately;
|
|
; otherwise execution continues into another secondary dispatcher at $D5EF.
|
|
;
|
|
; Global:
|
|
; Complements the addition paths at $D5BD/$D5C1. Together, the four
|
|
; secondary states provide signed movement along two coordinate components.
|
|
;
|
|
; Notes:
|
|
; The shared labels are non-local because multiple handler entry points
|
|
; converge into them.
|
|
;==============================================================================
|
|
|
|
EntitySecondaryState0:
|
|
ldy #$03
|
|
bne EntitySecondarySubtract
|
|
|
|
|
|
EntitySecondaryState1:
|
|
ldy #$01
|
|
|
|
|
|
EntitySecondarySubtract:
|
|
lda ($02),y
|
|
sec
|
|
sbc $C2,x
|
|
sta ($02),y
|
|
|
|
lda #$00
|
|
bcs EntitySecondarySubtractNoBorrow
|
|
|
|
lda #$01
|
|
|
|
|
|
EntitySecondarySubtractNoBorrow:
|
|
clc
|
|
adc $C3,x
|
|
sta $CC
|
|
|
|
|
|
;==============================================================================
|
|
; $D5EB-$D600: Apply Entity Movement and Dispatch Direction Substate
|
|
;
|
|
; Local:
|
|
; Shared continuation reached by both the addition and subtraction
|
|
; secondary-state handlers.
|
|
;
|
|
; Decrements $CC. If it becomes negative, returns. Otherwise reads the
|
|
; current entity secondary state from $B9,X, doubles it, and selects a
|
|
; handler from the table at $D601.
|
|
;
|
|
; Global:
|
|
; Final arithmetic stage for entity movement before dispatching into the
|
|
; direction/substate-specific update handlers.
|
|
;==============================================================================
|
|
|
|
EntitySecondaryApplyResult:
|
|
dec $CC
|
|
bpl EntityDirectionDispatch
|
|
|
|
rts
|
|
|
|
|
|
EntityDirectionDispatch:
|
|
lda $B9,x
|
|
asl
|
|
tay
|
|
|
|
lda EntityDirectionStateTable,y
|
|
sta $10
|
|
|
|
lda EntityDirectionStateTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $D601-$D608: Entity Direction-State Dispatch Table
|
|
;
|
|
; Local:
|
|
; Four handlers selected from the entity's secondary state at $B9,X.
|
|
;
|
|
; Notes:
|
|
; The pointer order deliberately differs from the physical order of the
|
|
; handlers in ROM.
|
|
;==============================================================================
|
|
|
|
EntityDirectionStateTable:
|
|
.word $D609
|
|
.word $D61D
|
|
.word $D60F
|
|
.word $D617
|
|
|
|
;==============================================================================
|
|
; $D609-$D622: Entity Direction-State Handlers
|
|
;
|
|
; Local:
|
|
; Four handlers selected by EntityDirectionStateTable.
|
|
;
|
|
; Each handler configures:
|
|
;
|
|
; $05 = +1 or -1
|
|
; Y = $00 or $02
|
|
;
|
|
; before entering the shared coordinate-update code at $D623.
|
|
;
|
|
; Global:
|
|
; Provides the four direction-specific movement modes for the per-entity
|
|
; state machine.
|
|
;
|
|
; Notes:
|
|
; The four states form two coordinate axes and two signed directions:
|
|
;
|
|
; $D609 -> $05=$FF, Y=$02
|
|
; $D60F -> $05=$01, Y=$02
|
|
; $D617 -> $05=$01, Y=$00
|
|
; $D61D -> $05=$FF, Y=$00
|
|
;
|
|
; Concrete direction names remain deferred until the coordinate axes are
|
|
; mapped to screen X/Y.
|
|
;==============================================================================
|
|
|
|
EntityDirectionD609:
|
|
lda #$FF
|
|
sta $05
|
|
bne EntityDirectionAxis2
|
|
|
|
|
|
EntityDirectionD60F:
|
|
lda #$01
|
|
sta $05
|
|
|
|
|
|
EntityDirectionAxis2:
|
|
ldy #$02
|
|
bne EntityDirectionMove
|
|
|
|
|
|
EntityDirectionD617:
|
|
lda #$01
|
|
sta $05
|
|
bne EntityDirectionAxis0
|
|
|
|
|
|
EntityDirectionD61D:
|
|
lda #$FF
|
|
sta $05
|
|
|
|
|
|
EntityDirectionAxis0:
|
|
ldy #$00
|
|
|
|
;==============================================================================
|
|
; $D623-$D69A: Shared Entity Direction Movement
|
|
;
|
|
; Local:
|
|
; Applies the signed step in $05 to either byte $00 or $02 of the entity
|
|
; structure referenced by $02/$03.
|
|
;
|
|
; Performs coordinate wrapping/bounds handling, updates a per-entity flag
|
|
; stored in $39+, checks tile/grid alignment, and when the entity reaches a
|
|
; specific location ($60,$70) changes the entity primary state to $02.
|
|
;
|
|
; Global:
|
|
; Shared movement implementation for the four handlers above.
|
|
;
|
|
; Notes:
|
|
; This section eventually rejoins the earlier movement arithmetic at $D5EB
|
|
; when the entity is not aligned to the grid.
|
|
;==============================================================================
|
|
|
|
EntityDirectionMove:
|
|
lda ($02),y
|
|
clc
|
|
adc $05
|
|
sta ($02),y
|
|
|
|
ldy #$00
|
|
|
|
lda ($02),y
|
|
cmp #$0A
|
|
bne @D637
|
|
|
|
lda #$BF
|
|
sta ($02),y
|
|
bne @D64B
|
|
|
|
|
|
@D637:
|
|
cmp #$C0
|
|
bne @D641
|
|
|
|
lda #$0B
|
|
sta ($02),y
|
|
bne @D64B
|
|
|
|
|
|
@D641:
|
|
cmp #$18
|
|
bcc @D64B
|
|
|
|
cmp #$A9
|
|
bcc @D64F
|
|
|
|
|
|
@D64B:
|
|
lda #$20
|
|
bne @D651
|
|
|
|
|
|
@D64F:
|
|
lda #$00
|
|
|
|
|
|
@D651:
|
|
sta $05
|
|
|
|
txa
|
|
lsr
|
|
tay
|
|
|
|
lda $39,y
|
|
and #$DF
|
|
ora $05
|
|
sta $39,y
|
|
|
|
ldy #$00
|
|
lda ($02),y
|
|
|
|
ldy #$02
|
|
ora ($02),y
|
|
and #$07
|
|
beq @D66E
|
|
|
|
jmp EntitySecondaryApplyResult
|
|
|
|
@D66E:
|
|
ldy #$00
|
|
|
|
lda ($02),y
|
|
cmp #$60
|
|
bne $D69B
|
|
|
|
ldy #$02
|
|
|
|
lda ($02),y
|
|
cmp #$70
|
|
bne $D69B
|
|
|
|
lda #$02
|
|
sta $B8,x
|
|
|
|
lda #$00
|
|
clc
|
|
sbc $04
|
|
and $88
|
|
sta $88
|
|
|
|
txa
|
|
lsr
|
|
tay
|
|
sta $05
|
|
|
|
lda $39,y
|
|
and #$FC
|
|
ora $05
|
|
sta $39,y
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D69B-$D6C6: Entity Movement Continuation / Target Selection
|
|
;
|
|
; Local:
|
|
; Continues entity processing after direction movement.
|
|
;
|
|
; Primary entity state $06 selects the fixed value $6F60 in $CD/$CE.
|
|
; Otherwise entity bitmasks in $04 are tested against $88 and $87.
|
|
;
|
|
; ($04 & $88) != 0 transfers to $D70A.
|
|
; ($04 & $87) != 0 transfers to $D6CF.
|
|
;
|
|
; If neither mask matches, the current entity index X selects a 16-bit value
|
|
; from EntityTargetTable and processing continues at $D778.
|
|
;
|
|
; Global:
|
|
; Chooses the next entity target/path-processing mode based on entity state
|
|
; and per-entity bitmasks.
|
|
;
|
|
; Notes:
|
|
; Cross-region branch targets remain raw until the destination blocks are
|
|
; decoded.
|
|
;==============================================================================
|
|
|
|
EntityMovementContinuation:
|
|
lda $B8,x
|
|
cmp #$06
|
|
bne @CheckEntityMasks
|
|
|
|
lda #$60
|
|
sta $CD
|
|
|
|
lda #$6F
|
|
sta $CE
|
|
|
|
jmp $D778
|
|
|
|
|
|
@CheckEntityMasks:
|
|
lda $04
|
|
and $88
|
|
bne $D70A
|
|
|
|
lda $04
|
|
and $87
|
|
bne $D6CF
|
|
|
|
txa
|
|
tay
|
|
|
|
lda EntityTargetTable,y
|
|
sta $CD
|
|
|
|
lda EntityTargetTable+1,y
|
|
sta $CE
|
|
|
|
jmp $D778
|
|
|
|
;==============================================================================
|
|
; $D6C7-$D6CE: Entity Target Table
|
|
;
|
|
; Local:
|
|
; Four 16-bit values indexed directly by the even entity offset X.
|
|
;
|
|
; Global:
|
|
; Supplies the $CD/$CE working target used by EntityMovementContinuation.
|
|
;
|
|
; Notes:
|
|
; Values are retained numerically until the consumer at $D778 is decoded.
|
|
;==============================================================================
|
|
|
|
EntityTargetTable:
|
|
.word $08A8
|
|
.word $0818
|
|
.word $D0A8
|
|
.word $D018
|
|
|
|
;==============================================================================
|
|
; $D6CF-$D6DD: Entity Target-Selection Dispatcher
|
|
;
|
|
; Local:
|
|
; Uses the current even entity index X directly as a byte offset into the
|
|
; four-entry pointer table at $D6DE.
|
|
;
|
|
; The selected handler address is stored in $10/$11 and execution transfers
|
|
; through an indirect JMP.
|
|
;
|
|
; Global:
|
|
; Entered from EntityMovementContinuation when the current entity's bit in
|
|
; $87 is set. Selects entity-specific target/path behavior.
|
|
;
|
|
; Notes:
|
|
; X is already constrained by the calling code to the even entity offsets:
|
|
;
|
|
; $00,$02,$04,$06
|
|
;
|
|
; Therefore no multiply-by-two is required here.
|
|
;==============================================================================
|
|
|
|
DispatchEntityTargetBehavior:
|
|
txa
|
|
tay
|
|
|
|
lda EntityTargetBehaviorTable,y
|
|
sta $10
|
|
|
|
lda EntityTargetBehaviorTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $D6DE-$D6E5: Entity Target-Behavior Dispatch Table
|
|
;
|
|
; Local:
|
|
; Four 16-bit handlers indexed directly by the even entity index X.
|
|
;
|
|
; Global:
|
|
; Selects different target/path calculations for each of the four gameplay
|
|
; entities.
|
|
;
|
|
; Notes:
|
|
; The fourth entry deliberately points backward to $D6E6, immediately after
|
|
; this table.
|
|
;==============================================================================
|
|
|
|
EntityTargetBehaviorTable:
|
|
.word EntityTargetBehaviorD73B ; X = $00
|
|
.word EntityTargetBehaviorD745 ; X = $02
|
|
.word EntityTargetBehaviorD764 ; X = $04
|
|
.word EntityTargetBehaviorD6E6 ; X = $06
|
|
|
|
;==============================================================================
|
|
; $D6E6-$D73A: Entity Target Behavior - Proximity/Direction Selection
|
|
;
|
|
; Local:
|
|
; Computes absolute differences between $1A/$2A and $1C/$2C.
|
|
; If either difference is at least $20, transfers to EntityTargetBehaviorD73B.
|
|
;
|
|
; Otherwise attempts up to five candidate directions. Each candidate is
|
|
; checked against the data addressed by $00/$01 and against the current
|
|
; entity direction/state at $B9,X.
|
|
;
|
|
; The selected value is stored into $B9,X before returning to the common
|
|
; entity movement result handler at $D5EB.
|
|
;
|
|
; Global:
|
|
; Fourth entry in EntityTargetBehaviorTable, selected for entity X=$06.
|
|
;
|
|
; Notes:
|
|
; Cross-block target $D73B remains raw until that handler is decoded.
|
|
;==============================================================================
|
|
|
|
EntityTargetBehaviorD6E6:
|
|
lda $1A
|
|
sec
|
|
sbc $2A
|
|
bcs @D6F4
|
|
|
|
sta $05
|
|
|
|
lda #$00
|
|
sec
|
|
sbc $05
|
|
|
|
@D6F4:
|
|
cmp #$20
|
|
bcs $D73B
|
|
|
|
lda $1C
|
|
sec
|
|
sbc $2C
|
|
bcs @D703
|
|
|
|
sta $05
|
|
|
|
lda #$00
|
|
sec
|
|
sbc $05
|
|
|
|
@D703:
|
|
cmp #$20
|
|
bcs $D73B
|
|
|
|
lda $4B
|
|
sta $05
|
|
|
|
lda #$05
|
|
sta $06
|
|
|
|
|
|
@D712:
|
|
dec $06
|
|
bne @D71A
|
|
|
|
lda #$02
|
|
bne @D736
|
|
|
|
|
|
@D71A:
|
|
inc $05
|
|
|
|
lda $05
|
|
and #$03
|
|
tay
|
|
|
|
lda ($00),y
|
|
and #$F8
|
|
bne @D712
|
|
|
|
lda $05
|
|
clc
|
|
adc #$02
|
|
and #$03
|
|
cmp $B9,x
|
|
beq @D712
|
|
|
|
lda $05
|
|
and #$03
|
|
|
|
|
|
@D736:
|
|
sta $B9,x
|
|
|
|
jmp EntitySecondaryApplyResult
|
|
|
|
;==============================================================================
|
|
; $D73B-$D777: Entity Target Calculation Handlers
|
|
;
|
|
; Local:
|
|
; Three handlers selected by EntityTargetBehaviorTable.
|
|
;
|
|
; $D73B:
|
|
; Uses the current $1A/$1C coordinate pair directly as the target.
|
|
;
|
|
; $D745:
|
|
; Uses $51 to select a signed coordinate offset from the table at $D75C,
|
|
; then adds that offset to $1A/$1C.
|
|
;
|
|
; $D764:
|
|
; Reflects/extrapolates the current coordinate pair relative to
|
|
; $1E/$20.
|
|
;
|
|
; All three produce the target coordinate in $CD/$CE and converge on the
|
|
; still-undecoded common processing at $D778.
|
|
;
|
|
; Global:
|
|
; Three of the four target strategies selected by
|
|
; EntityTargetBehaviorTable.
|
|
;
|
|
; Notes:
|
|
; Cross-block destination $D778 remains raw until the common handler is
|
|
; decoded separately.
|
|
;==============================================================================
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D73B: direct target
|
|
;------------------------------------------------------------------------------
|
|
|
|
EntityTargetBehaviorD73B:
|
|
lda $1A
|
|
sta $CD
|
|
|
|
lda $1C
|
|
sta $CE
|
|
|
|
bne $D778
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D745: direction-offset target
|
|
;------------------------------------------------------------------------------
|
|
|
|
EntityTargetBehaviorD745:
|
|
lda $51
|
|
asl
|
|
tay
|
|
|
|
lda EntityDirectionTargetOffsets,y
|
|
clc
|
|
adc $1A
|
|
sta $CD
|
|
|
|
lda EntityDirectionTargetOffsets+1,y
|
|
clc
|
|
adc $1C
|
|
sta $CE
|
|
|
|
jmp $D778
|
|
|
|
;==============================================================================
|
|
; $D75C-$D763: Direction Target Offset Table
|
|
;
|
|
; Local:
|
|
; Four signed coordinate offset pairs selected by ($51 * 2).
|
|
;
|
|
; As signed 8-bit values:
|
|
;
|
|
; 0 -> ( 0, -24 )
|
|
; 1 -> (-24, 0 )
|
|
; 2 -> ( 0, +24 )
|
|
; 3 -> (+24, 0 )
|
|
;
|
|
; Global:
|
|
; Used by EntityTargetBehaviorD745 to project a target position in the
|
|
; entity's current direction.
|
|
;==============================================================================
|
|
|
|
EntityDirectionTargetOffsets:
|
|
.byte $00,$E8
|
|
.byte $E8,$00
|
|
.byte $00,$18
|
|
.byte $18,$00
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D764: relative/reflected target
|
|
;
|
|
; Computes:
|
|
;
|
|
; $CD = $1A + ($1A - $1E)
|
|
; $CE = $1C + ($1C - $20)
|
|
;
|
|
; which algebraically corresponds to:
|
|
;
|
|
; $CD = 2*$1A - $1E
|
|
; $CE = 2*$1C - $20
|
|
;
|
|
; using 8-bit arithmetic.
|
|
;------------------------------------------------------------------------------
|
|
|
|
EntityTargetBehaviorD764:
|
|
lda $1A
|
|
sec
|
|
sbc $1E
|
|
|
|
clc
|
|
adc $1A
|
|
sta $CD
|
|
|
|
lda $1C
|
|
sec
|
|
sbc $20
|
|
|
|
clc
|
|
adc $1C
|
|
sta $CE
|
|
|
|
;==============================================================================
|
|
; $D778-$D79F: Common Entity Target Processing
|
|
;
|
|
; Local:
|
|
; Shared continuation used after an entity target coordinate has been
|
|
; calculated in $CD/$CE.
|
|
;
|
|
; Uses the entity primary state at $B8,X, minus $04, as a byte offset into
|
|
; a packed pointer table beginning at $D881. The selected pointer is stored
|
|
; in $0A/$0B and passed to BuildLegalDirectionList.
|
|
;
|
|
; The results returned in $0C/$0D determine the entity's next secondary
|
|
; state at $B9,X:
|
|
;
|
|
; $0C == $FF
|
|
; -> force state $02
|
|
;
|
|
; $0C != $FF and $0D == $FF
|
|
; -> store $0C into $B9,X and return
|
|
;
|
|
; $0C != $FF and $0D != $FF
|
|
; -> continue at $D7A0 for additional selection logic
|
|
;
|
|
; Global:
|
|
; Common target-evaluation stage reached by the entity target strategies
|
|
; at $D73B, $D745 and $D764, as well as fixed-target paths from earlier
|
|
; entity processing.
|
|
;
|
|
; Notes:
|
|
; $D881 remains undecoded and is therefore referenced by address.
|
|
;
|
|
; The branch to $D7A0 is intentionally kept raw because $D7A0 belongs to
|
|
; the next block and is an explicit continuation rather than an RTS.
|
|
;==============================================================================
|
|
|
|
EntityTargetCommon:
|
|
lda $B8,x
|
|
sec
|
|
sbc #$04
|
|
tay
|
|
|
|
lda $D881,y
|
|
sta $0A
|
|
|
|
lda $D882,y
|
|
sta $0B
|
|
|
|
jsr BuildLegalDirectionList
|
|
|
|
lda $0C
|
|
cmp #$FF
|
|
bne @D795
|
|
|
|
lda #$02
|
|
bne @D79D
|
|
|
|
|
|
@D795:
|
|
lda $0D
|
|
cmp #$FF
|
|
bne $D7A0
|
|
|
|
lda $0C
|
|
|
|
|
|
@D79D:
|
|
sta $B9,x
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D7A0-$D820: Select Entity Direction Toward Target
|
|
;
|
|
; Local:
|
|
; Entered from EntityTargetCommon when both $0C and $0D returned by
|
|
; BuildLegalDirectionList are valid.
|
|
;
|
|
; Computes absolute coordinate distances between target $CD/$CE and the
|
|
; current entity coordinates addressed through $02/$03.
|
|
;
|
|
; $05 accumulates direction-order information according to:
|
|
; - sign of the horizontal/vertical difference
|
|
; - which axis has the larger absolute distance
|
|
;
|
|
; The result is used to index a direction-priority table at $D871.
|
|
; Candidate directions are compared against the four values at $0C-$0F.
|
|
; When a candidate matches, execution branches back to the common direction
|
|
; store at $D79D.
|
|
;
|
|
; If the preferred candidates fail, the routine tests directions adjacent
|
|
; to the current secondary state $B9,X before eventually returning.
|
|
;
|
|
; Global:
|
|
; Alternate continuation of EntityTargetCommon. Selects the next movement
|
|
; direction for an entity based on its current position and target.
|
|
;
|
|
; Notes:
|
|
; $05 is a temporary direction-priority index.
|
|
; $06/$07 hold absolute coordinate differences.
|
|
; $08 is temporary storage during absolute-value calculations.
|
|
;
|
|
; $D871 is not decoded yet and remains a raw table reference.
|
|
;==============================================================================
|
|
|
|
SelectEntityDirectionTowardTarget:
|
|
ldy #$00
|
|
sty $05
|
|
|
|
lda $CD
|
|
sec
|
|
sbc ($02),y
|
|
bcs @D7B9
|
|
|
|
sta $08
|
|
|
|
lda #$00
|
|
sec
|
|
sbc $08
|
|
|
|
inc $05
|
|
inc $05
|
|
inc $05
|
|
inc $05
|
|
|
|
@D7B9:
|
|
sta $06
|
|
|
|
lda $CE
|
|
|
|
ldy #$02
|
|
|
|
sec
|
|
sbc ($02),y
|
|
bcs @D7D2
|
|
|
|
sta $08
|
|
|
|
lda #$00
|
|
sec
|
|
sbc $08
|
|
|
|
inc $05
|
|
inc $05
|
|
|
|
@D7D2:
|
|
sta $07
|
|
|
|
lda $06
|
|
cmp $07
|
|
bcs @D7DB
|
|
|
|
inc $05
|
|
|
|
@D7DB:
|
|
lda $05
|
|
asl
|
|
sta $05
|
|
|
|
lda #$02
|
|
sta $06
|
|
|
|
|
|
@D7E3:
|
|
ldy $05
|
|
|
|
lda $D871,y
|
|
|
|
ldy #$00
|
|
|
|
@D7EA:
|
|
cmp $000C,y
|
|
beq $D79D
|
|
|
|
iny
|
|
cpy #$04
|
|
bne @D7EA
|
|
|
|
inc $05
|
|
|
|
dec $06
|
|
bne @D7E3
|
|
|
|
lda $B9,x
|
|
sec
|
|
sbc #$01
|
|
and #$03
|
|
|
|
ldy #$00
|
|
|
|
@D802:
|
|
cmp $000C,y
|
|
beq $D79D
|
|
|
|
iny
|
|
cpy #$04
|
|
bne @D802
|
|
|
|
lda $B9,x
|
|
clc
|
|
adc #$01
|
|
and #$03
|
|
|
|
ldy #$00
|
|
|
|
@D814:
|
|
cmp $000C,y
|
|
beq $D79D
|
|
|
|
iny
|
|
cpy #$04
|
|
bne @D814
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D821-$D870: Select Entity Movement Parameters
|
|
;
|
|
; Local:
|
|
; Chooses the two-byte movement/step value stored at:
|
|
;
|
|
; $C2,X
|
|
; $C3,X
|
|
;
|
|
; for the current gameplay entity.
|
|
;
|
|
; Selection depends on:
|
|
;
|
|
; - primary entity state $B8,X
|
|
; - current entity coordinates through ($02)
|
|
; - entity bitmask $04 against $88
|
|
; - whether X is zero or identifies another entity
|
|
;
|
|
; Parameter pairs are copied from several global values:
|
|
;
|
|
; $B3/$B4
|
|
; $CA/$CB
|
|
; $AF/$B0
|
|
; $B1/$B2
|
|
;
|
|
; Primary state $06 instead installs the fixed pair:
|
|
;
|
|
; $00,$02
|
|
;
|
|
; Global:
|
|
; Called before the $B9,X secondary-state dispatcher at $D5A1. This chooses
|
|
; the movement increment used by the entity movement arithmetic.
|
|
;
|
|
; Notes:
|
|
; The coordinate pointer $02/$03 identifies the current entity's structure.
|
|
; X is the even entity slot index.
|
|
;==============================================================================
|
|
|
|
SelectEntityMovementSpeed:
|
|
lda $B8,x
|
|
cmp #$06
|
|
beq @D864
|
|
|
|
ldy #$02
|
|
|
|
lda ($02),y
|
|
cmp #$70
|
|
bne @D843
|
|
|
|
ldy #$00
|
|
|
|
lda ($02),y
|
|
cmp #$90
|
|
bcs @D83D
|
|
|
|
cmp #$30
|
|
bcs @D843
|
|
|
|
@D83D:
|
|
lda $B3
|
|
sta $C2,x
|
|
|
|
lda $B4
|
|
sta $C3,x
|
|
|
|
rts
|
|
|
|
|
|
@D843:
|
|
lda $04
|
|
and $88
|
|
bne @D85A
|
|
|
|
txa
|
|
bne @D854
|
|
|
|
lda $CA
|
|
sta $C2
|
|
|
|
lda $CB
|
|
sta $C3
|
|
|
|
rts
|
|
|
|
|
|
@D854:
|
|
lda $AF
|
|
sta $C2,x
|
|
|
|
lda $B0
|
|
sta $C3,x
|
|
|
|
rts
|
|
|
|
|
|
@D85A:
|
|
lda $B1
|
|
sta $C2,x
|
|
|
|
lda $B2
|
|
sta $C3,x
|
|
|
|
rts
|
|
|
|
|
|
@D864:
|
|
lda #$00
|
|
sta $C2,x
|
|
|
|
lda #$02
|
|
sta $C3,x
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D871-$D880: Entity Direction Priority Table
|
|
;
|
|
; Local:
|
|
; Sixteen direction values used by SelectEntityDirectionTowardTarget.
|
|
;
|
|
; $05 is derived from:
|
|
; - the sign of each target-coordinate difference,
|
|
; - which axis has the greater absolute distance.
|
|
;
|
|
; $05 is doubled before indexing this table, and the routine may examine
|
|
; the following entry as its second preferred candidate.
|
|
;
|
|
; Global:
|
|
; Defines the preferred entity movement directions for the different
|
|
; relative target-position quadrants/axis priorities.
|
|
;
|
|
; Notes:
|
|
; Values are internal direction numbers 0-3. Concrete direction names remain
|
|
; deferred until the internal direction numbering is fully mapped.
|
|
;
|
|
; The natural layout is eight pairs of preferred directions.
|
|
;==============================================================================
|
|
|
|
EntityDirectionPriorityTable:
|
|
.byte $03,$02
|
|
.byte $02,$03
|
|
.byte $03,$00
|
|
.byte $00,$03
|
|
.byte $01,$02
|
|
.byte $02,$01
|
|
.byte $01,$00
|
|
.byte $00,$01
|
|
|
|
;==============================================================================
|
|
; $D881-$D884: Entity Path/Map Pointer Table
|
|
;
|
|
; Local:
|
|
; Two 16-bit values selected according to entity primary state:
|
|
;
|
|
; state $04 -> $0000
|
|
; state $06 -> $082C
|
|
;
|
|
; The selected value is placed in $0A/$0B and passed to the helper at
|
|
; BuildLegalDirectionList.
|
|
;
|
|
; Global:
|
|
; Supplies state-dependent path/map parameters used by EntityTargetCommon.
|
|
;
|
|
; Notes:
|
|
; Keep the entries as literal 16-bit values until BuildLegalDirectionList
|
|
; is decoded and the semantic meaning of $0A/$0B is established.
|
|
;==============================================================================
|
|
|
|
EntityPathParameterTable:
|
|
.word $0000
|
|
.word $082C
|
|
|
|
;==============================================================================
|
|
; $D885-$D8D4: Entity Primary State $02 Handler
|
|
;==============================================================================
|
|
|
|
UpdateEntityState02:
|
|
lda #$00
|
|
tay
|
|
sta $05
|
|
|
|
lda #$80
|
|
sta $06
|
|
|
|
lda ($02),y
|
|
cmp #$60
|
|
beq UpdateEntityState02SecondaryPhase
|
|
|
|
bcc @D89C
|
|
|
|
dec $05
|
|
|
|
lda #$01
|
|
bne @D89E
|
|
|
|
@D89C:
|
|
lda #$03
|
|
|
|
@D89E:
|
|
sta $B9,x
|
|
|
|
ldy #$01
|
|
|
|
lda ($02),y
|
|
clc
|
|
adc $06
|
|
sta ($02),y
|
|
|
|
ldy #$00
|
|
|
|
lda ($02),y
|
|
adc $05
|
|
sta ($02),y
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $D8B2-$D8D4: Entity State $02 Secondary Movement Phase
|
|
;==============================================================================
|
|
|
|
UpdateEntityState02SecondaryPhase:
|
|
lda #$00
|
|
sta $B9,x
|
|
|
|
ldy #$03
|
|
|
|
lda ($02),y
|
|
sec
|
|
sbc #$80
|
|
sta ($02),y
|
|
|
|
ldy #$02
|
|
|
|
lda ($02),y
|
|
sbc #$00
|
|
sta ($02),y
|
|
|
|
cmp #$58
|
|
beq @D8CC
|
|
|
|
rts
|
|
|
|
@D8CC:
|
|
lda #$01
|
|
sta $B9,x
|
|
|
|
lda #$04
|
|
sta $B8,x
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $D8D5-$D913: Entity Primary State $00 Handler
|
|
;
|
|
; Local:
|
|
; Initializes working movement values:
|
|
;
|
|
; $05 = $00
|
|
; $06 = $80
|
|
;
|
|
; Then uses the entity secondary state at $B9,X as a byte offset into a
|
|
; two-entry table at $D8EC.
|
|
;
|
|
; The selected subhandler adjusts bytes 3/2 of the current entity structure
|
|
; through $02/$03. When the resulting high byte crosses defined thresholds,
|
|
; $B9,X advances to secondary state $02 or resets to $00.
|
|
;
|
|
; Global:
|
|
; Handler selected by EntityStateTable for primary entity state $00.
|
|
;
|
|
; Notes:
|
|
; Unlike the $D5A1 secondary dispatcher, $B9,X is already treated as a byte
|
|
; offset here. Valid values are $00 and $02.
|
|
;==============================================================================
|
|
|
|
EntityState00:
|
|
lda #$00
|
|
sta $05
|
|
|
|
lda #$80
|
|
sta $06
|
|
|
|
ldy $B9,x
|
|
|
|
lda EntityState00SubstateTable,y
|
|
sta $10
|
|
|
|
lda EntityState00SubstateTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
|
|
;==============================================================================
|
|
; $D8EC-$D8EF: Entity State $00 Secondary Table
|
|
;==============================================================================
|
|
|
|
EntityState00SubstateTable:
|
|
.word UpdateEntityState00MovingNegative
|
|
.word UpdateEntityState00MovingPositive
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D8F0: secondary state $00
|
|
;------------------------------------------------------------------------------
|
|
|
|
UpdateEntityState00MovingNegative:
|
|
dec $05
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $D8F2: secondary state $02
|
|
;------------------------------------------------------------------------------
|
|
|
|
UpdateEntityState00MovingPositive:
|
|
ldy #$03
|
|
|
|
lda ($02),y
|
|
clc
|
|
adc $06
|
|
sta ($02),y
|
|
|
|
ldy #$02
|
|
|
|
lda ($02),y
|
|
adc $05
|
|
sta ($02),y
|
|
|
|
cmp #$69
|
|
bcs @D90B
|
|
|
|
lda #$02
|
|
bne @D911
|
|
|
|
|
|
@D90B:
|
|
cmp #$70
|
|
bcc @D913
|
|
|
|
lda #$00
|
|
|
|
@D911:
|
|
sta $B9,x
|
|
|
|
@D913:
|
|
rts
|
|
;==============================================================================
|
|
; $D914-$D943: Update Four Gameplay Entity States
|
|
;
|
|
; Local:
|
|
; Iterates the four gameplay entity slots using even X offsets:
|
|
;
|
|
; $00,$02,$04,$06
|
|
;
|
|
; Initializes the same per-entity working values used by the other entity
|
|
; update coordinator:
|
|
;
|
|
; $00 = $2F
|
|
; $01 = $02
|
|
; $02 = $1E
|
|
; $03 = $00
|
|
; $04 = $01
|
|
;
|
|
; Calls the entity dispatcher at $D944 for each slot.
|
|
;
|
|
; After each call:
|
|
;
|
|
; $00 += 4
|
|
; $02 += 4
|
|
; $04 <<= 1
|
|
; X += 2
|
|
;
|
|
; Global:
|
|
; Called from GameModeState06 during its per-frame update sequence.
|
|
; Processes a second entity-state machine for all four gameplay entities.
|
|
;
|
|
; Notes:
|
|
; The layout closely parallels UpdateGameplayEntities at $D557, but uses
|
|
; a different dispatcher and therefore a different behavior set.
|
|
;==============================================================================
|
|
|
|
UpdateEntityMovementStates:
|
|
ldx #$00
|
|
|
|
lda #$2F
|
|
sta $00
|
|
|
|
lda #$02
|
|
sta $01
|
|
|
|
lda #$1E
|
|
sta $02
|
|
|
|
lda #$00
|
|
sta $03
|
|
|
|
lda #$01
|
|
sta $04
|
|
|
|
@D92A:
|
|
jsr $D944
|
|
|
|
lda $00
|
|
clc
|
|
adc #$04
|
|
sta $00
|
|
|
|
lda $02
|
|
clc
|
|
adc #$04
|
|
sta $02
|
|
|
|
asl $04
|
|
|
|
inx
|
|
inx
|
|
|
|
cpx #$08
|
|
bne @D92A
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D944-$D952: Gameplay Entity Transition-State Dispatcher
|
|
;
|
|
; Local:
|
|
; Reads the current entity primary state from $B8,X and uses it directly as
|
|
; a byte offset into the packed pointer table at $D953.
|
|
;
|
|
; The selected 16-bit address is stored in $10/$11 and execution transfers
|
|
; to it through an indirect JMP.
|
|
;
|
|
; Global:
|
|
; Called by UpdateEntityMovementStates once for each of the four
|
|
; gameplay entity slots.
|
|
;
|
|
; Notes:
|
|
; X identifies the entity using even offsets:
|
|
;
|
|
; $00,$02,$04,$06
|
|
;
|
|
; $B8,X is itself an even byte offset into the pointer table:
|
|
;
|
|
; $00,$02,$04,$06,$08
|
|
;==============================================================================
|
|
|
|
DispatchEntityMovementState:
|
|
ldy $B8,x
|
|
|
|
lda EntityMovementStateHandlerTable,y
|
|
sta $10
|
|
|
|
lda EntityMovementStateHandlerTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
|
|
;==============================================================================
|
|
; $D953-$D95C: Gameplay Entity Transition-State Table
|
|
;
|
|
; Local:
|
|
; Five 16-bit handlers indexed directly by the entity primary state stored
|
|
; in $B8,X.
|
|
;
|
|
; Global:
|
|
; Defines the per-entity behavior used by
|
|
; DispatchEntityMovementState.
|
|
;
|
|
; Notes:
|
|
; States $00, $02, $04 and $08 all use the same handler at $D95D.
|
|
;
|
|
; State $06 reuses DispatchEntitySecondaryState at $D5A1.
|
|
;==============================================================================
|
|
|
|
EntityMovementStateHandlerTable:
|
|
.word EntityMovementStateNoOp ; state $00
|
|
.word EntityMovementStateNoOp ; state $02
|
|
.word EntityMovementStateNoOp ; state $04
|
|
.word DispatchEntitySecondaryState ; state $06
|
|
.word EntityMovementStateNoOp ; state $08
|
|
|
|
;==============================================================================
|
|
; $D95D: No-Op Entity Transition Handler
|
|
;
|
|
; Local:
|
|
; Returns immediately.
|
|
;
|
|
; Global:
|
|
; Used by EntityMovementStateHandlerTable for primary entity states
|
|
; $00, $02, $04 and $08.
|
|
;==============================================================================
|
|
EntityMovementStateNoOp:
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D95E-$D979: Check Entity Transition State
|
|
;
|
|
; Local:
|
|
; Scans the four primary entity-state entries at:
|
|
;
|
|
; $B8,$BA,$BC,$BE
|
|
;
|
|
; If any entity is in primary state $06, stores the current A value
|
|
; ($06 from the CMP) into $0608 and returns.
|
|
;
|
|
; If no entity is in state $06, tests $88. When $88 is nonzero, stores that
|
|
; value into $0609 before returning.
|
|
;
|
|
; Global:
|
|
; Called during normal gameplay processing. Exports entity/state conditions
|
|
; to RAM $0608/$0609 for use by other gameplay systems.
|
|
;
|
|
; Notes:
|
|
; $00 is initialized but not subsequently used inside this routine in the
|
|
; decoded path. Preserve the write because another overlapping entry or
|
|
; external expectation may depend on it.
|
|
;==============================================================================
|
|
|
|
UpdateEntityStatusFlags:
|
|
ldx #$00
|
|
stx $00
|
|
|
|
@D962:
|
|
lda $B8,x
|
|
cmp #$06
|
|
bne @D96C
|
|
|
|
sta $0608
|
|
rts
|
|
|
|
@D96C:
|
|
inx
|
|
inx
|
|
|
|
cpx #$08
|
|
bne @D962
|
|
|
|
lda $88
|
|
beq UpdatePlayerVerticalRegionFlag
|
|
|
|
sta $0609
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D97A-$D98D: Update Gameplay Range Flag
|
|
;==============================================================================
|
|
UpdatePlayerVerticalRegionFlag:
|
|
ldy #$00
|
|
|
|
lda $6A
|
|
cmp #$88
|
|
bcs @D988
|
|
|
|
iny
|
|
|
|
cmp #$42
|
|
bcs @D988
|
|
|
|
iny
|
|
|
|
@D988:
|
|
lda #$01
|
|
sta $060A,y
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D98E-$D9C5: Update Direction-Dependent Gameplay Value
|
|
;
|
|
; Local:
|
|
; Builds a base value from the current direction $51, then selects an
|
|
; additional offset based on coordinate alignment, tile state, and $B7.
|
|
;
|
|
; The resulting value is stored in $32.
|
|
;
|
|
; Notes:
|
|
; Address-derived labels preserve the original compact control flow.
|
|
;==============================================================================
|
|
|
|
UpdatePlayerDirectionAnimation:
|
|
lda $51
|
|
asl
|
|
clc
|
|
adc #$02
|
|
sta $00
|
|
|
|
lda $1A
|
|
ora $1C
|
|
and #$07
|
|
bne @D9AE
|
|
|
|
ldy $51
|
|
|
|
lda $022B,y
|
|
and #$F0
|
|
beq @D9AE
|
|
|
|
lda $B7
|
|
and #$03
|
|
jmp @D9B2
|
|
|
|
|
|
@D9AE:
|
|
inc $B7
|
|
|
|
lda $B7
|
|
|
|
@D9B2:
|
|
and #$07
|
|
cmp #$06
|
|
bcc @D9BC
|
|
|
|
lda #$01
|
|
bne @D9C3
|
|
|
|
|
|
@D9BC:
|
|
tay
|
|
|
|
lda PlayerDirectionAnimationOffsets,y
|
|
clc
|
|
adc $00
|
|
|
|
|
|
@D9C3:
|
|
sta $32
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $D9C6-$D9CB: Direction-Value Offset Table
|
|
;
|
|
; Local:
|
|
; Six values indexed by $B7 & $07 when that result is less than six.
|
|
;
|
|
; Global:
|
|
; Provides the small offset added to the direction-derived base before the
|
|
; result is stored in $32.
|
|
;==============================================================================
|
|
|
|
PlayerDirectionAnimationOffsets:
|
|
.byte $00,$00,$00,$01,$01,$00
|
|
|
|
;==============================================================================
|
|
; $D9CC-$D9EA: Update Four Entity Display/State Values
|
|
;
|
|
; Local:
|
|
; Initializes:
|
|
;
|
|
; X = $00
|
|
; $00 = $00 or $01 depending on frame-counter bit 3
|
|
; $01 = $01
|
|
;
|
|
; Then iterates the four entity slots:
|
|
;
|
|
; X = $00,$02,$04,$06
|
|
;
|
|
; For each entity:
|
|
; - Calls the dispatcher at $D9EB.
|
|
; - Shifts $01 left once, producing per-entity masks:
|
|
;
|
|
; $01,$02,$04,$08
|
|
;
|
|
; - Advances X by two.
|
|
;
|
|
; Global:
|
|
; Called from several game-mode states and during normal gameplay. Provides
|
|
; per-frame updates for all four gameplay entities, with an alternating
|
|
; phase selected from frame-counter bit 3.
|
|
;
|
|
; Notes:
|
|
; $4B is the NMI-driven frame counter.
|
|
; $00 is a two-phase animation/control value.
|
|
; $01 is the current entity bitmask.
|
|
;==============================================================================
|
|
|
|
UpdateEntitySpriteStates:
|
|
lda #$00
|
|
tax
|
|
sta $00
|
|
|
|
lda $4B
|
|
and #$08
|
|
beq @D9DC
|
|
|
|
lda #$01
|
|
sta $00
|
|
|
|
|
|
@D9DC:
|
|
lda #$01
|
|
sta $01
|
|
|
|
|
|
@D9E0:
|
|
jsr $D9EB
|
|
|
|
asl $01
|
|
|
|
inx
|
|
inx
|
|
|
|
cpx #$08
|
|
bne @D9E0
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $D9EB-$D9F9: Per-Entity Display/State Dispatcher
|
|
;==============================================================================
|
|
|
|
DispatchEntitySpriteState:
|
|
ldy $B8,x
|
|
|
|
lda EntitySpriteStateHandlerTable,y
|
|
sta $10
|
|
|
|
lda EntitySpriteStateHandlerTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
|
|
;==============================================================================
|
|
; $D9FA-$DA03: Entity Display/State Table
|
|
;==============================================================================
|
|
EntitySpriteStateHandlerTable:
|
|
.word UpdateNormalEntitySprite ; state $00
|
|
.word UpdateNormalEntitySprite ; state $02
|
|
.word UpdateNormalEntitySprite ; state $04
|
|
.word UpdateSpecialEntitySprite ; state $06
|
|
.word $D9EA ; state $08 -> shared RTS
|
|
|
|
;==============================================================================
|
|
; $DA04-$DA3F: Entity Display/State Value Handlers
|
|
;
|
|
; Local:
|
|
; Three entry points used by EntitySpriteStateHandlerTable:
|
|
;
|
|
; $DA21 primary states $00/$02/$04
|
|
; $DA2D primary state $06
|
|
;
|
|
; $DA04 is shared calculation code entered by those handlers.
|
|
;
|
|
; Each path computes a value from the entity secondary state $B9,X, combines
|
|
; it with a base value, and stores the final result into one of $33-$36
|
|
; according to the current entity index X.
|
|
;
|
|
; Global:
|
|
; Produces per-entity display/state values during UpdateEntitySpriteStates.
|
|
;
|
|
; Notes:
|
|
; X is an even entity index ($00,$02,$04,$06). TXA/LSR converts this into
|
|
; the ordinal entity index 0-3 for the final store at $33,Y.
|
|
;==============================================================================
|
|
|
|
;==============================================================================
|
|
; $DA04-$DA3F: Entity Display/State Value Handlers
|
|
;
|
|
; Local:
|
|
; Shared calculations used by the per-entity display/state dispatcher.
|
|
;
|
|
; Global:
|
|
; UpdateNormalEntitySprite handles primary states $00/$02/$04.
|
|
; UpdateSpecialEntitySprite handles primary state $06.
|
|
;
|
|
; Notes:
|
|
; Non-local labels are intentional because multiple handler entry points
|
|
; branch backward into shared code.
|
|
;==============================================================================
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DA04
|
|
;------------------------------------------------------------------------------
|
|
|
|
CalculateEntitySpriteValue:
|
|
lda $B9,x
|
|
sta $03
|
|
|
|
lda #$0A
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DA0A
|
|
;------------------------------------------------------------------------------
|
|
|
|
CalculateEntitySpriteValueLoop:
|
|
dec $03
|
|
bmi AddEntitySpriteBase
|
|
|
|
clc
|
|
adc #$02
|
|
bne CalculateEntitySpriteValueLoop
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DA13
|
|
;------------------------------------------------------------------------------
|
|
|
|
AddEntitySpriteBase:
|
|
clc
|
|
adc $00
|
|
sta $02
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DA18
|
|
;------------------------------------------------------------------------------
|
|
|
|
StoreEntitySpriteValue:
|
|
txa
|
|
lsr
|
|
tay
|
|
|
|
lda $02
|
|
sta $0033,y
|
|
|
|
rts
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DA21
|
|
; Primary entity states $00/$02/$04.
|
|
;------------------------------------------------------------------------------
|
|
|
|
UpdateNormalEntitySprite:
|
|
lda $01
|
|
and $88
|
|
beq CalculateEntitySpriteValue
|
|
|
|
lda #$1E
|
|
sta $02
|
|
|
|
bne AddEntitySpriteBase
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DA2D
|
|
; Primary entity state $06.
|
|
;------------------------------------------------------------------------------
|
|
|
|
UpdateSpecialEntitySprite:
|
|
lda $B9,x
|
|
sta $03
|
|
|
|
lda #$20
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DA33
|
|
;------------------------------------------------------------------------------
|
|
|
|
UpdateSpecialEntitySpriteLoop:
|
|
dec $03
|
|
bmi UpdateSpecialEntitySpriteDone
|
|
|
|
clc
|
|
adc #$01
|
|
bne UpdateSpecialEntitySpriteLoop
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DA3C
|
|
;------------------------------------------------------------------------------
|
|
|
|
UpdateSpecialEntitySpriteDone:
|
|
sta $02
|
|
|
|
bmi StoreEntitySpriteValue
|
|
|
|
;==============================================================================
|
|
; $DA40-$DAF0: Gameplay Entity Collision / Slot Exchange
|
|
;
|
|
; Local:
|
|
; Copies $24 bytes from zero-page $1A-$3D to RAM $0274-$0297.
|
|
;
|
|
; Then initializes an indirect pointer to $0284 and scans entity structures
|
|
; while testing them against the primary coordinate pair at $0274/$0276.
|
|
;
|
|
; For each enabled entity, computes absolute coordinate differences. If both
|
|
; axes are within $19 and their combined distance is below $10, exchanges
|
|
; coordinate and associated state fields between the primary slot and the
|
|
; selected entity slot.
|
|
;
|
|
; If no qualifying overlap is found, advances the structure pointer backward
|
|
; by four bytes, shifts the per-entity mask, and continues.
|
|
;
|
|
; Global:
|
|
; Called in several game-mode states and during normal gameplay. Maintains
|
|
; the mirrored gameplay/object state in $0274+ and handles close-overlap
|
|
; exchanges between entity slots.
|
|
;
|
|
; Notes:
|
|
; $00/$01 form a temporary pointer, initially $0284.
|
|
; $02 counts entity slots.
|
|
; $03 is a bitmask, initially $08.
|
|
; $04-$06 are temporary coordinate/state values during a swap.
|
|
;
|
|
; $DAF1 is a separate routine and is not included in this block.
|
|
;==============================================================================
|
|
|
|
CheckEntityCollisions:
|
|
ldx #$23
|
|
|
|
@CopyWorkingState:
|
|
lda $1A,x
|
|
sta $0274,x
|
|
|
|
dex
|
|
bpl @CopyWorkingState
|
|
|
|
lda #$84
|
|
sta $00
|
|
|
|
lda #$02
|
|
sta $01
|
|
|
|
lda #$08
|
|
sta $03
|
|
|
|
lda #$03
|
|
sta $02
|
|
|
|
|
|
@CheckNextEntity:
|
|
lda $03
|
|
and $88
|
|
bne @AdvanceEntity
|
|
|
|
ldy #$00
|
|
|
|
lda $0274
|
|
cmp ($00),y
|
|
bcs @FirstAxisReverse
|
|
|
|
lda ($00),y
|
|
sec
|
|
sbc $0274
|
|
bcs @CheckFirstAxis
|
|
|
|
@FirstAxisReverse:
|
|
sbc ($00),y
|
|
|
|
@CheckFirstAxis:
|
|
cmp #$19
|
|
bcs @AdvanceEntity
|
|
|
|
sta $04
|
|
|
|
ldy #$02
|
|
|
|
lda $0276
|
|
cmp ($00),y
|
|
bcs @SecondAxisReverse
|
|
|
|
lda ($00),y
|
|
sec
|
|
sbc $0276
|
|
bcs @CheckSecondAxis
|
|
|
|
@SecondAxisReverse:
|
|
sbc ($00),y
|
|
|
|
@CheckSecondAxis:
|
|
cmp #$19
|
|
bcs @AdvanceEntity
|
|
|
|
adc $04
|
|
cmp #$10
|
|
bcs @AdvanceEntity
|
|
|
|
; Save the primary slot coordinates/state.
|
|
lda $0274
|
|
sta $03
|
|
|
|
lda $0276
|
|
sta $04
|
|
|
|
lda $028C
|
|
sta $05
|
|
|
|
lda $0292
|
|
sta $06
|
|
|
|
; Copy selected entity coordinates into the primary slot.
|
|
ldy #$00
|
|
lda ($00),y
|
|
sta $0274
|
|
|
|
lda $03
|
|
sta ($00),y
|
|
|
|
ldy #$02
|
|
lda ($00),y
|
|
sta $0276
|
|
|
|
lda $04
|
|
sta ($00),y
|
|
|
|
; Exchange the parallel status values.
|
|
ldx $02
|
|
|
|
lda $028D,x
|
|
sta $028C
|
|
|
|
lda $05
|
|
sta $028D,x
|
|
|
|
lda $0293,x
|
|
sta $0292
|
|
|
|
lda $06
|
|
sta $0293,x
|
|
|
|
jmp $DAEB
|
|
|
|
|
|
@AdvanceEntity:
|
|
lda $00
|
|
sec
|
|
sbc #$04
|
|
sta $00
|
|
|
|
lsr $03
|
|
|
|
dec $02
|
|
bmi @NoCollision
|
|
|
|
jmp @CheckNextEntity
|
|
|
|
|
|
@NoCollision:
|
|
jsr $E1DA
|
|
|
|
jmp $DAF1
|
|
|
|
;==============================================================================
|
|
; $DAF1-$DBEE: Rebuild Gameplay Entity Render Data
|
|
;
|
|
; Local:
|
|
; Builds four-byte render/object records in page $07 from mirrored gameplay
|
|
; state beginning at $0274.
|
|
;
|
|
; Working variables:
|
|
;
|
|
; $00/$01 = source pointer, initially $0274
|
|
; $02/$03 = destination pointer, initially $0700
|
|
; $04 = source-group index
|
|
; $05 = record/lookup index
|
|
; $06 = temporary lookup index
|
|
;
|
|
; X advances through even entity offsets $00,$02,$04,$06.
|
|
;
|
|
; Encoded state values at $028C+ determine which lookup-table path is used
|
|
; to construct bytes 1 and 2 of each four-byte output record.
|
|
;
|
|
; Global:
|
|
; Called by several gameplay paths to rebuild the page-$07 representation
|
|
; used by the rendering/object pipeline.
|
|
;
|
|
; Notes:
|
|
; Several ROM tables referenced here remain undecoded:
|
|
;
|
|
; $DBEE
|
|
; $DCEE
|
|
; $DD22
|
|
; EntitySpriteAttributeTable0
|
|
; EntitySpriteCoordinateOffsets
|
|
; $DE57
|
|
;
|
|
; $DBEE is particularly interesting because it is also the RTS terminating
|
|
; this routine. The ROM intentionally uses that address as both executable
|
|
; code and the base of a later indexed lookup.
|
|
;==============================================================================
|
|
BuildEntitySpriteBuffer:
|
|
lda #$74
|
|
sta $00
|
|
|
|
lda #$02
|
|
sta $01
|
|
|
|
lda #$00
|
|
sta $02
|
|
|
|
lda #$07
|
|
sta $03
|
|
|
|
lda #$00
|
|
sta $04
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DB05
|
|
; Start/restart one source group.
|
|
;------------------------------------------------------------------------------
|
|
|
|
BuildSpriteBufferNextGroup:
|
|
lda #$00
|
|
sta $05
|
|
|
|
tax
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DB0A
|
|
; Build one four-byte render record.
|
|
;------------------------------------------------------------------------------
|
|
|
|
BuildSpriteBufferNextSprite:
|
|
ldy #$02
|
|
|
|
lda ($00),y
|
|
bne AdjustSpriteY
|
|
|
|
lda #$FF
|
|
bne StoreSpriteY
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DB14
|
|
;------------------------------------------------------------------------------
|
|
|
|
AdjustSpriteY:
|
|
clc
|
|
adc EntitySpriteCoordinateOffsets,x
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DB18
|
|
;------------------------------------------------------------------------------
|
|
|
|
StoreSpriteY:
|
|
ldy #$00
|
|
sta ($02),y
|
|
|
|
ldy $04
|
|
|
|
lda $028C,y
|
|
asl
|
|
rol
|
|
rol
|
|
and #$03
|
|
|
|
beq BuildSpriteClass0
|
|
|
|
cmp #$02
|
|
beq BuildSpriteClass2
|
|
|
|
bcc BuildSpriteClass1
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DB2E
|
|
; Status-class path.
|
|
;------------------------------------------------------------------------------
|
|
|
|
lda $028C,y
|
|
asl
|
|
asl
|
|
clc
|
|
adc $05
|
|
tay
|
|
|
|
sta $06
|
|
|
|
lda $DD22,y
|
|
|
|
ldy #$01
|
|
sta ($02),y
|
|
|
|
ldy $04
|
|
lda $0292,y
|
|
|
|
ldy $06
|
|
ora EntitySpriteCoordinateOffsets,y
|
|
|
|
ldy #$02
|
|
sta ($02),y
|
|
|
|
jmp BuildSpriteX
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DB51
|
|
;------------------------------------------------------------------------------
|
|
|
|
BuildSpriteClass0:
|
|
lda $028C,y
|
|
asl
|
|
asl
|
|
clc
|
|
adc $05
|
|
tay
|
|
|
|
sta $06
|
|
|
|
lda $DBEE,y
|
|
|
|
ldy #$01
|
|
sta ($02),y
|
|
|
|
ldy $04
|
|
lda $0292,y
|
|
|
|
ldy $06
|
|
ora $DD22,y
|
|
|
|
ldy #$02
|
|
sta ($02),y
|
|
|
|
jmp BuildSpriteX
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DB74
|
|
;------------------------------------------------------------------------------
|
|
|
|
BuildSpriteClass1:
|
|
lda $028C,y
|
|
asl
|
|
asl
|
|
clc
|
|
adc $05
|
|
tay
|
|
|
|
sta $06
|
|
|
|
lda $DCEE,y
|
|
|
|
ldy #$01
|
|
sta ($02),y
|
|
|
|
ldy $04
|
|
lda $0292,y
|
|
|
|
ldy $06
|
|
ora $DE22,y
|
|
|
|
ldy #$02
|
|
sta ($02),y
|
|
|
|
jmp BuildSpriteX
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DB97
|
|
;------------------------------------------------------------------------------
|
|
|
|
BuildSpriteClass2:
|
|
lda $028C,y
|
|
asl
|
|
asl
|
|
clc
|
|
adc $05
|
|
tay
|
|
|
|
sta $06
|
|
|
|
lda $DD22,y
|
|
|
|
ldy #$01
|
|
sta ($02),y
|
|
|
|
ldy $04
|
|
lda $0292,y
|
|
|
|
ldy $06
|
|
ora EntitySpriteCoordinateOffsets,y
|
|
|
|
ldy #$02
|
|
sta ($02),y
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DBB7
|
|
; Construct byte 3 of the render record.
|
|
;------------------------------------------------------------------------------
|
|
|
|
BuildSpriteX:
|
|
ldy #$00
|
|
|
|
lda ($00),y
|
|
bne AdjustSpriteX
|
|
|
|
lda #$FF
|
|
bne StoreSpriteX
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DBC0
|
|
;------------------------------------------------------------------------------
|
|
|
|
AdjustSpriteX:
|
|
clc
|
|
adc EntitySpriteCoordinateOffsets+1,x
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DBC4
|
|
;------------------------------------------------------------------------------
|
|
|
|
StoreSpriteX:
|
|
ldy #$03
|
|
sta ($02),y
|
|
|
|
; Advance destination by one 4-byte record.
|
|
lda $02
|
|
clc
|
|
adc #$04
|
|
sta $02
|
|
|
|
inc $05
|
|
|
|
inx
|
|
inx
|
|
|
|
cpx #$08
|
|
beq BuildSpriteBufferNextSource
|
|
|
|
jmp BuildSpriteBufferNextSprite
|
|
|
|
|
|
BuildSpriteBufferNextSource:
|
|
lda $00
|
|
clc
|
|
adc #$04
|
|
sta $00
|
|
|
|
inc $04
|
|
|
|
lda $04
|
|
cmp #$06
|
|
beq BuildSpriteBufferDone
|
|
|
|
jmp BuildSpriteBufferNextGroup
|
|
|
|
BuildSpriteBufferDone:
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $DBEE-$DC3F: Gameplay Entity Render Lookup Data
|
|
;
|
|
; Local:
|
|
; Lookup data used by BuildEntitySpriteBuffer.
|
|
;
|
|
; The routine constructs an index from:
|
|
;
|
|
; ($028C,Y * 4) + $05
|
|
;
|
|
; and uses that value to index this region for render-facing object data.
|
|
;
|
|
; Global:
|
|
; Supplies tile/state values used when rebuilding the four-byte page-$07
|
|
; entity records.
|
|
;
|
|
; Notes:
|
|
; The region contains strongly patterned groups of repeated values, but the
|
|
; complete set of consumers has not yet been decoded. Keep this as one
|
|
; contiguous table during the first pass rather than assigning speculative
|
|
; semantic subdivisions.
|
|
;==============================================================================
|
|
|
|
EntitySpriteTileTable0:
|
|
|
|
; $DBEE-$DBFD
|
|
.byte $4C,$4C,$4C,$4C
|
|
.byte $00,$00,$00,$00
|
|
.byte $04,$04,$03,$03
|
|
.byte $08,$08,$07,$07
|
|
|
|
; $DBFE-$DC0D
|
|
.byte $02,$01,$02,$01
|
|
.byte $06,$05,$06,$05
|
|
.byte $03,$03,$04,$04
|
|
.byte $07,$07,$08,$08
|
|
|
|
; $DC0E-$DC1D
|
|
.byte $01,$02,$01,$02
|
|
.byte $05,$06,$05,$06
|
|
.byte $18,$18,$19,$19
|
|
.byte $18,$18,$1A,$1A
|
|
|
|
; $DC1E-$DC2D
|
|
.byte $1B,$1C,$1D,$1F
|
|
.byte $1B,$1C,$1E,$20
|
|
.byte $21,$21,$22,$22
|
|
.byte $21,$21,$23,$23
|
|
|
|
; $DC2E-$DC3D
|
|
.byte $1C,$1B,$1F,$1D
|
|
.byte $1C,$1B,$20,$1E
|
|
.byte $00,$00,$00,$00
|
|
.byte $09,$09,$0A,$0A
|
|
|
|
; $DC3E-$DC3F
|
|
.byte $0B,$0B
|
|
|
|
;==============================================================================
|
|
; $DC40-$DCED: Gameplay Entity Render Lookup Data, Continued
|
|
;
|
|
; Local:
|
|
; Additional render/tile lookup values associated with the table beginning
|
|
; at $DBEE.
|
|
;
|
|
; The data is strongly grouped into repeated pairs and four-byte patterns,
|
|
; consistent with direction/animation variants used by the four-byte entity
|
|
; render records.
|
|
;
|
|
; Global:
|
|
; Part of the graphics-facing lookup data used when gameplay state is
|
|
; converted into page-$07 render records.
|
|
;
|
|
; Notes:
|
|
; Keep these bytes as a contiguous data block for now. $DCEE is separately
|
|
; referenced by BuildEntitySpriteBuffer and therefore marks the next
|
|
; known lookup-table boundary.
|
|
;==============================================================================
|
|
EntityRenderLookupDC40:
|
|
; $DC40-$DC4F
|
|
.byte $0C,$0C,$4C,$4C
|
|
.byte $0D,$0D,$4C,$4C
|
|
.byte $0E,$0E,$4C,$4C
|
|
.byte $0F,$0F,$4C,$4C
|
|
|
|
; $DC50-$DC5F
|
|
.byte $10,$10,$4C,$4C
|
|
.byte $11,$11,$4C,$4C
|
|
.byte $12,$12,$4C,$4C
|
|
.byte $13,$13,$14,$15
|
|
|
|
; $DC60-$DC6F
|
|
.byte $16,$17,$4C,$4C
|
|
.byte $4C,$4C,$24,$24
|
|
.byte $25,$25,$24,$24
|
|
.byte $26,$26,$27,$27
|
|
|
|
; $DC70-$DC7F
|
|
.byte $4C,$4C,$28,$29
|
|
.byte $2A,$2B,$2C,$2C
|
|
.byte $2D,$2D,$29,$28
|
|
.byte $2B,$2A,$90,$91
|
|
|
|
; $DC80-$DC8F
|
|
.byte $92,$93,$94,$95
|
|
.byte $96,$97,$98,$99
|
|
.byte $9A,$9B,$9C,$9D
|
|
.byte $9E,$9F,$A0,$A1
|
|
|
|
; $DC90-$DC9F
|
|
.byte $A2,$A3,$A4,$A5
|
|
.byte $A6,$A7,$A8,$A9
|
|
.byte $AA,$AB,$AC,$AD
|
|
.byte $AE,$AF,$2E,$2F
|
|
|
|
; $DCA0-$DCAF
|
|
.byte $30,$31,$32,$2F
|
|
.byte $33,$31,$34,$2F
|
|
.byte $35,$31,$36,$2F
|
|
.byte $37,$31,$38,$2F
|
|
|
|
; $DCB0-$DCBF
|
|
.byte $39,$31,$3A,$2F
|
|
.byte $3B,$31,$3C,$2F
|
|
.byte $3D,$31,$3E,$3F
|
|
.byte $40,$41,$42,$3F
|
|
|
|
; $DCC0-$DCCF
|
|
.byte $43,$41,$44,$45
|
|
.byte $46,$47,$48,$45
|
|
.byte $49,$47,$4A,$45
|
|
.byte $4B,$47,$4D,$4E
|
|
|
|
; $DCD0-$DCDF
|
|
.byte $4F,$50,$4E,$4D
|
|
.byte $50,$4F,$4F,$50
|
|
.byte $4D,$4E,$50,$4F
|
|
.byte $4E,$4D,$4D,$4E
|
|
|
|
; $DCE0-$DCED
|
|
.byte $4F,$51,$4E,$52
|
|
.byte $53,$54,$4F,$51
|
|
.byte $4D,$4E,$53,$54
|
|
.byte $4E,$52
|
|
|
|
;==============================================================================
|
|
; $DCEE-$DD21: Gameplay Entity Render Lookup Table
|
|
;
|
|
; Local:
|
|
; Lookup values used by BuildEntitySpriteBuffer in the status-class
|
|
; path beginning at $DB74.
|
|
;
|
|
; The index is constructed from:
|
|
;
|
|
; ($028C,Y * 4) + $05
|
|
;
|
|
; and the selected byte is written as byte 1 of the generated page-$07
|
|
; render record.
|
|
;
|
|
; Global:
|
|
; Supplies graphics/tile values for one class of gameplay entity render
|
|
; states.
|
|
;
|
|
; Notes:
|
|
; The repeated $4C values and four-byte groupings strongly suggest
|
|
; animation/direction variants. Keep the table as raw values during this
|
|
; first pass.
|
|
;
|
|
; $DD22 is separately referenced by the render-data builder and therefore
|
|
; marks the next lookup-table boundary.
|
|
;==============================================================================
|
|
|
|
EntitySpriteTileTable2:
|
|
|
|
; $DCEE-$DCFD
|
|
.byte $55,$4C,$56,$4C
|
|
.byte $56,$4C,$55,$4C
|
|
.byte $4C,$57,$4C,$58
|
|
.byte $4C,$59,$4C,$5A
|
|
|
|
; $DCFE-$DD0D
|
|
.byte $4C,$5B,$4C,$5C
|
|
.byte $4C,$4C,$4C,$5D
|
|
.byte $18,$18,$19,$5E
|
|
.byte $60,$61,$19,$5E
|
|
|
|
; $DD0E-$DD1D
|
|
.byte $1B,$1C,$1D,$62
|
|
.byte $1B,$1C,$1E,$63
|
|
.byte $64,$65,$66,$67
|
|
.byte $64,$65,$68,$69
|
|
|
|
; $DD1E-$DD21
|
|
.byte $6A,$6B,$4C,$4C
|
|
|
|
|
|
|
|
;==============================================================================
|
|
; $DD22-$DE21: Gameplay Entity Render Attribute Lookup
|
|
;
|
|
; Local:
|
|
; 256-byte lookup table used by BuildEntitySpriteBuffer.
|
|
;
|
|
; Entries are predominantly:
|
|
;
|
|
; $00
|
|
; $40
|
|
; $80
|
|
; $C0
|
|
;
|
|
; These values occupy bits 6-7 and are ORed with the corresponding value
|
|
; from $0292+ before being written as byte 2 of a page-$07 four-byte render
|
|
; record.
|
|
;
|
|
; Global:
|
|
; Supplies upper-bit render attributes for gameplay entities across their
|
|
; various states, animation phases and directional variants.
|
|
;
|
|
; Notes:
|
|
; The table is exactly $100 bytes long:
|
|
;
|
|
; $DD22-$DE21
|
|
;
|
|
; $DE22 is independently referenced by another render-data path and therefore
|
|
; marks the next table boundary.
|
|
;==============================================================================
|
|
|
|
EntitySpriteAttributeTable0:
|
|
|
|
; $DD22-$DD31
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$40,$80,$C0
|
|
.byte $80,$C0,$80,$C0
|
|
.byte $80,$C0,$80,$C0
|
|
|
|
; $DD32-$DD41
|
|
.byte $00,$00,$80,$80
|
|
.byte $00,$00,$80,$80
|
|
.byte $00,$40,$00,$40
|
|
.byte $00,$40,$00,$40
|
|
|
|
; $DD42-$DD51
|
|
.byte $40,$40,$C0,$C0
|
|
.byte $40,$40,$C0,$C0
|
|
.byte $00,$40,$00,$40
|
|
.byte $00,$40,$00,$40
|
|
|
|
; $DD52-$DD61
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$40,$00,$40
|
|
.byte $00,$40,$00,$40
|
|
|
|
; $DD62-$DD71
|
|
.byte $40,$40,$40,$40
|
|
.byte $40,$40,$40,$40
|
|
.byte $00,$40,$80,$C0
|
|
.byte $00,$40,$00,$40
|
|
|
|
; $DD72-$DD81
|
|
.byte $00,$40,$00,$40
|
|
.byte $00,$00,$00,$40
|
|
.byte $00,$00,$00,$40
|
|
.byte $00,$00,$00,$40
|
|
|
|
; $DD82-$DD91
|
|
.byte $00,$00,$00,$40
|
|
.byte $00,$00,$00,$40
|
|
.byte $00,$00,$00,$40
|
|
.byte $00,$00,$00,$40
|
|
|
|
; $DD92-$DDA1
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$40,$00,$40
|
|
.byte $00,$40,$00,$40
|
|
|
|
; $DDA2-$DDB1
|
|
.byte $00,$40,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$40,$00,$40
|
|
.byte $40,$40,$40,$40
|
|
|
|
; $DDB2-$DDC1
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
|
|
; $DDC2-$DDD1
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
|
|
; $DDD2-$DDE1
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
|
|
; $DDE2-$DDF1
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
|
|
; $DDF2-$DE01
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
|
|
; $DE02-$DE11
|
|
.byte $00,$00,$00,$00
|
|
.byte $40,$40,$00,$40
|
|
.byte $80,$00,$80,$80
|
|
.byte $00,$C0,$C0,$C0
|
|
|
|
; $DE12-$DE21
|
|
.byte $00,$00,$00,$00
|
|
.byte $40,$00,$00,$00
|
|
.byte $80,$80,$80,$80
|
|
.byte $80,$80,$C0,$80
|
|
|
|
;==============================================================================
|
|
; $DE22-$DE55: Secondary Gameplay Entity Render Attribute Lookup
|
|
;
|
|
; Local:
|
|
; Lookup data used by BuildEntitySpriteBuffer in the path beginning
|
|
; at $DB74.
|
|
;
|
|
; Values from this table are ORed with the corresponding state value from
|
|
; $0292+ and written as byte 2 of a four-byte page-$07 render record.
|
|
;
|
|
; Global:
|
|
; Supplies upper-bit render attributes for one class of gameplay entity
|
|
; render states.
|
|
;
|
|
; Notes:
|
|
; As with the larger table at $DD22, the significant nonzero values occupy
|
|
; the upper bits, primarily $40 and $80.
|
|
;
|
|
; EntitySpriteCoordinateOffsets is separately referenced as another
|
|
; lookup-table base and therefore marks the next known boundary.
|
|
;==============================================================================
|
|
|
|
EntitySpriteAttributeTable1:
|
|
|
|
; $DE22-$DE31
|
|
.byte $00,$00,$00,$00
|
|
.byte $80,$00,$80,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
|
|
; $DE32-$DE41
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$40,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
|
|
; $DE42-$DE51
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
.byte $00,$00,$00,$00
|
|
|
|
; $DE52-$DE55
|
|
.byte $00,$00,$00,$00
|
|
|
|
;==============================================================================
|
|
; $DE56-$DE5D: Entity Render Coordinate Adjustment Table
|
|
;
|
|
; Local:
|
|
; Eight coordinate-adjustment bytes used by
|
|
; BuildEntitySpriteBuffer.
|
|
;
|
|
; X takes even values $00,$02,$04,$06, and the routine reads:
|
|
;
|
|
; EntitySpriteCoordinateOffsets,X
|
|
; EntitySpriteCoordinateOffsets+1,X
|
|
;
|
|
; giving four byte pairs.
|
|
;
|
|
; Global:
|
|
; Adjusts source coordinates when building page-$07 four-byte render
|
|
; records.
|
|
;==============================================================================
|
|
|
|
EntitySpriteCoordinateOffsets:
|
|
.byte $03,$F4
|
|
.byte $03,$FC
|
|
.byte $0B,$F4
|
|
.byte $0B,$FC
|
|
|
|
;==============================================================================
|
|
; $DE5E-$DE7D: Periodic Four-Entry State Update
|
|
;
|
|
; Local:
|
|
; Once every 16 frames, updates the four entries at $6C-$6F:
|
|
;
|
|
; $07 -> remains $07
|
|
; $01 -> becomes $02
|
|
; anything else -> becomes $01
|
|
;==============================================================================
|
|
|
|
UpdatePeriodicFourEntryState:
|
|
lda $4B
|
|
and #$0F
|
|
beq @DE65
|
|
|
|
rts
|
|
|
|
|
|
@DE65:
|
|
tax
|
|
|
|
|
|
@DE66:
|
|
lda $6C,x
|
|
cmp #$07
|
|
beq @DE76
|
|
|
|
cmp #$01
|
|
bne @DE74
|
|
|
|
lda #$02
|
|
bne @DE76
|
|
|
|
|
|
@DE74:
|
|
lda #$01
|
|
|
|
|
|
@DE76:
|
|
sta $6C,x
|
|
|
|
inx
|
|
cpx #$04
|
|
bne @DE66
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $DE7E-$DF6B: Gameplay PPU / Display Update Processor
|
|
;
|
|
; Local:
|
|
; Processes several gameplay display-update buffers and writes their data
|
|
; directly to the PPU.
|
|
;
|
|
; Handles:
|
|
; - Six-byte update block at $023F using destination $026B/$026C.
|
|
; - Six-byte update block at $0245 using destination $0272/$0273.
|
|
; - Three-byte periodic update at $026F-$0271.
|
|
; - Four state values at $6C-$6F written to PPU addresses in the table
|
|
; beginning at GameplayStatusPpuAddressTable.
|
|
; - Generic PPU command stream beginning at $024B.
|
|
;
|
|
; Global:
|
|
; Central gameplay display-update routine.
|
|
;
|
|
; Notes:
|
|
; UpdateAnimatedGameplayPpuFields at $DF15 is a shared entry point reached from
|
|
; several earlier control-flow paths and is therefore a global label rather
|
|
; than a ca65 cheap-local label.
|
|
;==============================================================================
|
|
|
|
FlushGameplayPpuUpdates:
|
|
lda $48
|
|
beq @DE85
|
|
|
|
jmp UpdateAnimatedGameplayPpuFields
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DE85
|
|
; Process the update block beginning at $023F.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@DE85:
|
|
lda $023F
|
|
cmp #$FF
|
|
beq @DEB5
|
|
|
|
lda PPUSTATUS
|
|
|
|
lda $026B
|
|
sta PPUADDR
|
|
|
|
lda $026C
|
|
sta PPUADDR
|
|
|
|
ldy #$00
|
|
|
|
|
|
@DE9B:
|
|
lda $023F,y
|
|
sta PPUDATA
|
|
|
|
iny
|
|
cpy #$06
|
|
bne @DE9B
|
|
|
|
lda #$30
|
|
sta PPUDATA
|
|
|
|
lda #$FF
|
|
sta $023F
|
|
|
|
bne @DEE2
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DEB5
|
|
; Process the update block beginning at $0245.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@DEB5:
|
|
lda $0245
|
|
cmp #$FF
|
|
beq @DEE2
|
|
|
|
lda PPUSTATUS
|
|
|
|
lda $0272
|
|
sta PPUADDR
|
|
|
|
lda $0273
|
|
sta PPUADDR
|
|
|
|
ldy #$00
|
|
|
|
|
|
@DECB:
|
|
lda $0245,y
|
|
sta PPUDATA
|
|
|
|
iny
|
|
cpy #$06
|
|
bne @DECB
|
|
|
|
lda #$30
|
|
sta PPUDATA
|
|
|
|
lda #$FF
|
|
sta $0245
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DEE2
|
|
; Periodic three-byte display update.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@DEE2:
|
|
lda $4B
|
|
and #$07
|
|
bne UpdateAnimatedGameplayPpuFields
|
|
|
|
lda PPUSTATUS
|
|
|
|
lda $026D
|
|
sta PPUADDR
|
|
|
|
lda $026E
|
|
sta PPUADDR
|
|
|
|
ldx #$00
|
|
|
|
lda $4B
|
|
and #$18
|
|
beq @DF05
|
|
|
|
|
|
@DEFB:
|
|
lda $026F,x
|
|
sta PPUDATA
|
|
|
|
inx
|
|
cpx #$03
|
|
bne @DEFB
|
|
|
|
beq UpdateAnimatedGameplayPpuFields
|
|
|
|
|
|
@DF05:
|
|
lda #$20
|
|
|
|
|
|
@DF07:
|
|
sta PPUDATA
|
|
|
|
inx
|
|
cpx #$03
|
|
bne @DF07
|
|
|
|
|
|
;==============================================================================
|
|
; $DF15: Shared frame-dependent display update entry
|
|
;==============================================================================
|
|
UpdateAnimatedGameplayPpuFields:
|
|
lda $4B
|
|
and #$01
|
|
beq @DF42
|
|
|
|
ldy #$00
|
|
ldx #$00
|
|
|
|
lda $46
|
|
and $47
|
|
beq @DF27
|
|
|
|
ldy #$08
|
|
|
|
|
|
@DF27:
|
|
lda PPUSTATUS
|
|
|
|
lda GameplayStatusPpuAddressTable,y
|
|
sta PPUADDR
|
|
|
|
lda GameplayStatusPpuAddressTable+1,y
|
|
sta PPUADDR
|
|
|
|
lda $6C,x
|
|
sta PPUDATA
|
|
|
|
iny
|
|
iny
|
|
|
|
inx
|
|
cpx #$04
|
|
bne @DF27
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $DF42
|
|
; Process the $024B command stream.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@DF42:
|
|
lda PPUSTATUS
|
|
|
|
ldy #$FF
|
|
|
|
|
|
@DF46:
|
|
iny
|
|
|
|
lda $024B,y
|
|
cmp #$FF
|
|
beq @DF66
|
|
|
|
sta PPUADDR
|
|
|
|
iny
|
|
|
|
lda $024B,y
|
|
sta PPUADDR
|
|
|
|
|
|
@DF55:
|
|
iny
|
|
|
|
lda $024B,y
|
|
beq @DF46
|
|
|
|
cmp #$FF
|
|
beq @DF66
|
|
|
|
sta PPUDATA
|
|
|
|
bne @DF55
|
|
|
|
|
|
@DF66:
|
|
sta $024B
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $DF6C-$DF7B: Gameplay PPU Address Table
|
|
;
|
|
; Local:
|
|
; Eight PPU addresses stored in high-byte/low-byte order.
|
|
;
|
|
; When ($46 & $47) == 0, the first four addresses are used.
|
|
; Otherwise the second four addresses are used.
|
|
;
|
|
; Values from $6C-$6F are written to the selected addresses.
|
|
;
|
|
; Notes:
|
|
; These must remain .byte pairs. Using .word would reverse each address
|
|
; because ca65 emits words little-endian.
|
|
;==============================================================================
|
|
|
|
GameplayStatusPpuAddressTable:
|
|
.byte $20,$B4
|
|
.byte $20,$A2
|
|
.byte $22,$D4
|
|
.byte $22,$C2
|
|
|
|
.byte $28,$B4
|
|
.byte $28,$A2
|
|
.byte $2A,$D4
|
|
.byte $2A,$C2
|
|
|
|
;==============================================================================
|
|
; $DF7C-$E042: Gameplay Tile / State Update
|
|
;
|
|
; Local:
|
|
; Processes selected values of $022A, updates $6C-$6F, emits a command into
|
|
; the $024B display-command buffer, updates $6A and related gameplay state,
|
|
; and may transfer control to $E0E6.
|
|
;
|
|
; Global:
|
|
; Called during the normal gameplay frame-update chain.
|
|
;
|
|
; Notes:
|
|
; $E043 and $E044 are lookup-table bases used near the end of this routine.
|
|
; Those bytes are data and begin immediately after the final JMP at $E040.
|
|
;==============================================================================
|
|
|
|
UpdateGameplayTileState:
|
|
ldx #$00
|
|
|
|
lda $022A
|
|
cmp #$09
|
|
beq $DFBB
|
|
|
|
inx
|
|
inx
|
|
|
|
cmp #$03
|
|
beq $DFBB
|
|
|
|
cmp #$01
|
|
beq @DF94
|
|
|
|
cmp #$02
|
|
beq @DF94
|
|
|
|
rts
|
|
|
|
|
|
@DF94:
|
|
jsr $E063
|
|
|
|
lda $1A
|
|
sta $02
|
|
|
|
lda $1C
|
|
sta $03
|
|
|
|
jsr $E263
|
|
|
|
ldx #$00
|
|
|
|
lda $03
|
|
and #$07
|
|
beq @DFAD
|
|
|
|
inx
|
|
inx
|
|
|
|
|
|
@DFAD:
|
|
lda $02
|
|
and #$0F
|
|
cmp #$04
|
|
beq @DFB6
|
|
|
|
inx
|
|
|
|
@DFB6:
|
|
lda #$07
|
|
sta $6C,x
|
|
|
|
@DFBB:
|
|
ldx #$04
|
|
lda #$00
|
|
sta $D5
|
|
sta $D6
|
|
|
|
lda $1A
|
|
sta $02
|
|
|
|
lda $1C
|
|
sta $03
|
|
|
|
jsr $E263
|
|
|
|
ldy #$FF
|
|
|
|
@DFCE:
|
|
iny
|
|
|
|
lda $024B,y
|
|
cmp #$FF
|
|
bne @DFCE
|
|
|
|
tya
|
|
beq @DFDC
|
|
|
|
lda #$00
|
|
sta $024B,y
|
|
|
|
iny
|
|
|
|
|
|
@DFDC:
|
|
lda $03
|
|
sta $024B,y
|
|
|
|
iny
|
|
|
|
lda $02
|
|
sta $024B,y
|
|
|
|
iny
|
|
|
|
lda $E043,x
|
|
sta $024B,y
|
|
|
|
iny
|
|
|
|
lda #$FF
|
|
sta $024B,y
|
|
|
|
lda #$07
|
|
sta $022A
|
|
|
|
lda $E044,x
|
|
sta $DC
|
|
|
|
dec $6A
|
|
bne @E012
|
|
|
|
lda #$0C
|
|
sta $3F
|
|
|
|
lda #$00
|
|
sta $87
|
|
|
|
lda #$48
|
|
sta $4C
|
|
|
|
|
|
@E012:
|
|
lda $6A
|
|
|
|
cmp #$37
|
|
beq @E01C
|
|
|
|
cmp #$86
|
|
bne $E036
|
|
|
|
@E01C:
|
|
lda #$0A
|
|
sta $D7
|
|
|
|
lda #$3C
|
|
sta $D8
|
|
|
|
ldy $93
|
|
|
|
lda GameplayStateValueLookup,y
|
|
sta $37
|
|
|
|
lda #$03
|
|
sta $3D
|
|
|
|
lda #$60
|
|
sta $2E
|
|
|
|
lda #$80
|
|
sta $30
|
|
|
|
lda $6A
|
|
and #$01
|
|
tay
|
|
|
|
lda #$01
|
|
sta $0604,y
|
|
|
|
jmp $E0E6
|
|
|
|
;==============================================================================
|
|
; $E043-$E048: Gameplay Tile-State Lookup
|
|
;
|
|
; Local:
|
|
; Used by UpdateGameplayTileState through overlapping indexed reads at
|
|
; $E043,X and $E044,X.
|
|
;==============================================================================
|
|
|
|
TileEventDisplayLookup:
|
|
.byte $08,$01,$07,$01,$07,$05
|
|
|
|
;==============================================================================
|
|
; $E049-$E05A: Activate First Available State Slot
|
|
;
|
|
; Local:
|
|
; Scans the three even-indexed entries:
|
|
;
|
|
; $BA,$BC,$BE
|
|
;
|
|
; for the first zero value. If one is found, changes it to $02 and returns.
|
|
; If all three are already active/nonzero, returns without modification.
|
|
;==============================================================================
|
|
|
|
ActivateNextStateSlotE049:
|
|
ldx #$00
|
|
|
|
@E04B:
|
|
lda $BA,x
|
|
bne @E054
|
|
|
|
lda #$02
|
|
sta $BA,x
|
|
|
|
rts
|
|
|
|
|
|
@E054:
|
|
inx
|
|
inx
|
|
|
|
cpx #$06
|
|
bne @E04B
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E05B-$E062: Gameplay State Value Lookup
|
|
;
|
|
; Local:
|
|
; Eight sequential values indexed by $93 and copied into $37 during
|
|
; gameplay-state transitions.
|
|
;==============================================================================
|
|
|
|
GameplayStateValueLookup:
|
|
.byte $24,$25,$26,$27,$28,$29,$2A,$2B
|
|
|
|
;==============================================================================
|
|
; $E063-$E0E5: Initialize / Adjust Entity Direction State
|
|
;
|
|
; Local:
|
|
; Initializes several gameplay variables and scans all four entity slots.
|
|
;
|
|
; Initialization:
|
|
;
|
|
; if $8C == 0:
|
|
; $8A = $1E
|
|
;
|
|
; $89 = $00
|
|
; $88 = $0F
|
|
; $D9 = $00
|
|
;
|
|
; The low two bits of $39-$3C are normalized to $01, preserving the upper
|
|
; six bits.
|
|
;
|
|
; Palette/update values are installed at:
|
|
;
|
|
; $02AE = $11
|
|
; $02A9 = $0F
|
|
;
|
|
; Then the four entity structures are examined. For eligible entities in
|
|
; primary state $04, a candidate secondary direction is calculated from
|
|
; $B9,X and accepted when coordinate alignment and path-map checks permit it.
|
|
;
|
|
; Global:
|
|
; Called from UpdateGameplayTileState before that routine derives its
|
|
; direction/tile update.
|
|
;
|
|
; Notes:
|
|
; $00/$01 and $02/$03 are parallel indirect pointers.
|
|
; X advances through entity offsets $00,$02,$04,$06.
|
|
; $04 temporarily holds a candidate direction value.
|
|
;==============================================================================
|
|
InitializeEntityDirectionState:
|
|
lda $8C
|
|
bne @E06D
|
|
|
|
lda #$1E
|
|
sta $8A
|
|
|
|
lda #$00
|
|
|
|
|
|
@E06D:
|
|
sta $89
|
|
|
|
lda #$0F
|
|
sta $88
|
|
|
|
ldx #$03
|
|
|
|
@E075:
|
|
lda $39,x
|
|
and #$FC
|
|
ora #$01
|
|
sta $39,x
|
|
|
|
dex
|
|
bpl @E075
|
|
|
|
lda #$11
|
|
sta $02AE
|
|
|
|
lda #$0F
|
|
sta $02A9
|
|
|
|
lda #$00
|
|
sta $D9
|
|
|
|
ldx #$00
|
|
|
|
lda #$2F
|
|
sta $00
|
|
|
|
lda #$02
|
|
sta $01
|
|
|
|
lda #$1E
|
|
sta $02
|
|
|
|
lda #$00
|
|
sta $03
|
|
|
|
@E09E:
|
|
lda #$0F
|
|
cmp $88
|
|
beq @E0AA
|
|
|
|
lda $D2
|
|
bne @E0D1
|
|
|
|
@E0AA:
|
|
lda $B8,x
|
|
cmp #$04
|
|
bne @E0D1
|
|
|
|
lda $B9,x
|
|
clc
|
|
adc #$02
|
|
and #$03
|
|
sta $04
|
|
|
|
ldy #$00
|
|
|
|
lda ($02),y
|
|
|
|
ldy #$02
|
|
|
|
ora ($02),y
|
|
and #$07
|
|
bne @E0CD
|
|
|
|
ldy $04
|
|
|
|
lda ($00),y
|
|
and #$F8
|
|
bne @E0D1
|
|
|
|
|
|
@E0CD:
|
|
lda $04
|
|
sta $B9,x
|
|
|
|
|
|
@E0D1:
|
|
lda $00
|
|
clc
|
|
adc #$04
|
|
sta $00
|
|
|
|
lda $02
|
|
clc
|
|
adc #$04
|
|
sta $02
|
|
|
|
inx
|
|
inx
|
|
|
|
cpx #$08
|
|
bne @E0AA
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E0E6-$E1BF: Score / State Display Update
|
|
;
|
|
; Updates the six decimal-like values at $70-$75 using increments at $DC-$E1,
|
|
; converts the result into display characters at $023F, handles progression
|
|
; state associated with $6B/$73/$67, appends display commands to $024B, then
|
|
; compares and updates the saved values at $61-$66.
|
|
;==============================================================================
|
|
|
|
UpdateScoreDisplay:
|
|
lda $48
|
|
beq @E0EB
|
|
|
|
rts
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E0EB
|
|
; Add $DC-$E1 into the six values at $70-$75 using decimal carry handling.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E0EB:
|
|
ldy #$00
|
|
|
|
lda #$06
|
|
sta $00
|
|
|
|
clc
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E0F2
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E0F2:
|
|
lda $70,y
|
|
adc $DC,y
|
|
sta $70,y
|
|
|
|
cmp #$0A
|
|
bcc @E105
|
|
|
|
sbc #$0A
|
|
sta $70,y
|
|
|
|
sec
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E105
|
|
; Clear the consumed increment and continue through all six entries.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E105:
|
|
lda #$00
|
|
sta $DC,y
|
|
|
|
iny
|
|
|
|
dec $00
|
|
bne @E0F2
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E10F
|
|
; Convert the six numeric values into display/tile values.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ldx #$00
|
|
|
|
dey
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E112
|
|
; Suppress leading zero-style values by replacing $30 with $20.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E112:
|
|
lda $70,y
|
|
jsr $E1CE
|
|
|
|
cmp #$30
|
|
bne @E12B
|
|
|
|
lda #$20
|
|
sta $023F,x
|
|
|
|
inx
|
|
|
|
dey
|
|
bne @E112
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E125
|
|
; Convert remaining digits without leading-space suppression.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E125:
|
|
lda $70,y
|
|
jsr $E1CE
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E12B
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E12B:
|
|
sta $023F,x
|
|
|
|
inx
|
|
|
|
dey
|
|
bpl @E125
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E132
|
|
; Progression check.
|
|
;------------------------------------------------------------------------------
|
|
|
|
lda $6B
|
|
bne @E196
|
|
|
|
lda #$01
|
|
cmp $73
|
|
bne @E196
|
|
|
|
lda #$01
|
|
sta $6B
|
|
sta $0602
|
|
|
|
inc $67
|
|
|
|
lda $67
|
|
sec
|
|
sbc #$02
|
|
asl
|
|
sta $00
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Locate the $FF terminator of the $024B display-command stream.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ldy #$FF
|
|
|
|
|
|
@E14D:
|
|
iny
|
|
|
|
lda $024B,y
|
|
cmp #$FF
|
|
bne @E14D
|
|
|
|
tya
|
|
beq @E15D
|
|
|
|
lda #$00
|
|
sta $024B,y
|
|
|
|
iny
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E15D
|
|
; Select a display offset according to $46 & $47.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E15D:
|
|
lda $46
|
|
and $47
|
|
beq @E165
|
|
|
|
lda #$08
|
|
|
|
|
|
@E165:
|
|
sta $01
|
|
|
|
ldx #$00
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E169
|
|
; Append two five-byte command templates from $E1C0.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E169:
|
|
lda ScorePpuCommandTemplates,x
|
|
clc
|
|
adc $01
|
|
sta $024B,y
|
|
|
|
iny
|
|
inx
|
|
|
|
lda ScorePpuCommandTemplates,x
|
|
clc
|
|
adc $00
|
|
sta $024B,y
|
|
|
|
lda #$03
|
|
sta $02
|
|
|
|
|
|
@E182:
|
|
iny
|
|
inx
|
|
|
|
lda ScorePpuCommandTemplates,x
|
|
sta $024B,y
|
|
|
|
dec $02
|
|
bne @E182
|
|
|
|
iny
|
|
inx
|
|
|
|
cpx #$0A
|
|
bne @E169
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E196
|
|
; Compare saved values $61-$66 with current values $70-$75.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E196:
|
|
ldy #$05
|
|
|
|
|
|
@E198:
|
|
lda $61,y
|
|
cmp $70,y
|
|
beq @E1A3
|
|
|
|
bcc @E1A7
|
|
|
|
rts
|
|
|
|
|
|
@E1A3:
|
|
dey
|
|
bpl @E198
|
|
|
|
rts
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E1A7
|
|
; Copy display buffer $023F-$0244 to $0245-$024A.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E1A7:
|
|
ldx #$00
|
|
|
|
|
|
@E1A9:
|
|
lda $023F,x
|
|
sta $0245,x
|
|
|
|
inx
|
|
cpx #$06
|
|
bne @E1A9
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Copy current values $70-$75 into saved values $61-$66.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ldx #$00
|
|
|
|
|
|
@E1B4:
|
|
lda $70,x
|
|
sta $61,x
|
|
|
|
inx
|
|
cpx #$06
|
|
bne @E1B4
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E1C0-$E1C9: Score Display Command Table
|
|
;==============================================================================
|
|
|
|
ScorePpuCommandTemplates:
|
|
.byte $23,$17,$3C,$3D,$00
|
|
.byte $23,$37,$3E,$3F,$FF
|
|
|
|
;==============================================================================
|
|
; $E1CA-$E1D9: Convert High Nibble to Display Character
|
|
;
|
|
; Input:
|
|
; A = packed numeric value
|
|
;
|
|
; Output:
|
|
; A = display character code
|
|
;
|
|
; Behavior:
|
|
; Uses the original high nibble:
|
|
;
|
|
; $0-$9 -> $30-$39
|
|
; $A-$F -> $40-$45
|
|
;
|
|
; Global:
|
|
; Called by UpdateScoreDisplay while building the display buffer at
|
|
; $023F.
|
|
;==============================================================================
|
|
|
|
ConvertNibbleToDigitTile:
|
|
lsr
|
|
lsr
|
|
lsr
|
|
lsr
|
|
|
|
and #$0F
|
|
|
|
cmp #$0A
|
|
bcs @HexDigit
|
|
|
|
adc #$30
|
|
rts
|
|
|
|
@HexDigit:
|
|
adc #$36
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E1DA-$E262: Rebuild Gameplay Coordinate/Map Buffer
|
|
;
|
|
; Local:
|
|
; Converts the primary coordinate pair $1A/$1C through the helper at $E263
|
|
; and stores the result at $0200/$0201.
|
|
;
|
|
; Then iterates through gameplay coordinate structures beginning at $1A,
|
|
; advancing X by four each iteration.
|
|
;
|
|
; For each iteration:
|
|
; - Converts the current $1A+X/$1C+X pair through $E263.
|
|
; - Initializes working 16-bit values in $12-$15.
|
|
; - Calls helpers at $E2D4 and $E2C6.
|
|
; - Emits two groups of four bytes into the buffer at $0202+.
|
|
;
|
|
; The output loop terminates when Y reaches $28.
|
|
;
|
|
; Global:
|
|
; Called after gameplay collision/entity-state changes to rebuild a
|
|
; 40-byte coordinate/map-facing buffer in page $02.
|
|
;
|
|
; Notes:
|
|
; $E263 is the next known helper and is already called elsewhere.
|
|
;==============================================================================
|
|
|
|
BuildNearbyTileAddressBuffer:
|
|
lda $1A
|
|
sta $02
|
|
|
|
lda $1C
|
|
sta $03
|
|
|
|
jsr $E263
|
|
|
|
lda $03
|
|
sta $0200
|
|
|
|
lda $02
|
|
sta $0201
|
|
|
|
ldx #$00
|
|
ldy #$00
|
|
|
|
|
|
@E1F2:
|
|
lda $1A,x
|
|
sta $02
|
|
|
|
lda $1C,x
|
|
sta $03
|
|
|
|
jsr $E263
|
|
|
|
lda #$20
|
|
sta $14
|
|
|
|
lda #$00
|
|
sta $15
|
|
|
|
lda $02
|
|
sta $12
|
|
|
|
lda $03
|
|
sta $13
|
|
|
|
jsr $E2D4
|
|
|
|
lda $13
|
|
sta $0202,y
|
|
|
|
lda $12
|
|
iny
|
|
sta $0202,y
|
|
|
|
lda $03
|
|
iny
|
|
sta $0202,y
|
|
|
|
lda $02
|
|
sec
|
|
sbc #$01
|
|
iny
|
|
sta $0202,y
|
|
|
|
lda #$20
|
|
sta $14
|
|
|
|
lda #$00
|
|
sta $15
|
|
|
|
lda $02
|
|
sta $12
|
|
|
|
lda $03
|
|
sta $13
|
|
|
|
jsr $E2C6
|
|
|
|
lda $13
|
|
iny
|
|
sta $0202,y
|
|
|
|
lda $12
|
|
iny
|
|
sta $0202,y
|
|
|
|
lda $03
|
|
iny
|
|
sta $0202,y
|
|
|
|
lda $02
|
|
clc
|
|
adc #$01
|
|
iny
|
|
sta $0202,y
|
|
|
|
inx
|
|
inx
|
|
inx
|
|
inx
|
|
|
|
iny
|
|
|
|
cpy #$28
|
|
bne @E1F2
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E263-$E2A1: Convert Gameplay Coordinates to Map/PPU Address
|
|
;
|
|
; Input:
|
|
; $02 = first gameplay coordinate
|
|
; $03 = second gameplay coordinate
|
|
;
|
|
; Output:
|
|
; $02/$03 = converted 16-bit map/PPU-style address
|
|
;
|
|
; Local:
|
|
; Derives a nametable-style address from the coordinate pair.
|
|
;
|
|
; The second coordinate is adjusted by -4, aligned to an 8-unit boundary,
|
|
; then multiplied/shifted while carries are accumulated in $05.
|
|
;
|
|
; The first coordinate is adjusted by -4 and divided by eight before being
|
|
; added to the low address byte.
|
|
;
|
|
; The resulting address receives a base of $20xx.
|
|
;
|
|
; When ($46 & $47) is nonzero, $08 is added to the high/result byte at $03,
|
|
; selecting the corresponding alternate nametable region.
|
|
;
|
|
; Global:
|
|
; Called from several gameplay routines whenever object coordinates need to
|
|
; be converted into map/PPU addresses.
|
|
;
|
|
; Notes:
|
|
; $04/$05 are temporary low/high address components.
|
|
;==============================================================================
|
|
|
|
ConvertPixelToNametableAddress:
|
|
lda #$00
|
|
sta $05
|
|
|
|
lda $03
|
|
sec
|
|
sbc #$04
|
|
and #$F8
|
|
|
|
asl
|
|
rol $05
|
|
|
|
asl
|
|
rol $05
|
|
|
|
clc
|
|
adc #$40
|
|
sta $04
|
|
|
|
lda #$00
|
|
adc $05
|
|
sta $05
|
|
|
|
lda $02
|
|
sec
|
|
sbc #$04
|
|
|
|
lsr
|
|
lsr
|
|
lsr
|
|
|
|
clc
|
|
adc $04
|
|
sta $02
|
|
|
|
lda $05
|
|
clc
|
|
adc #$20
|
|
sta $03
|
|
|
|
lda $46
|
|
and $47
|
|
bne @E299
|
|
|
|
rts
|
|
|
|
@E299:
|
|
lda $03
|
|
clc
|
|
adc #$08
|
|
sta $03
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E2A2-$E2C5: Read PPU Values for Coordinate Address Buffer
|
|
;
|
|
; Reads 21 PPU addresses stored at $0200-$0229 and stores the corresponding
|
|
; PPU data bytes at $022A-$023E.
|
|
;
|
|
; PPUSTATUS is read once before processing the address list.
|
|
;==============================================================================
|
|
|
|
ReadNearbyNametableTiles:
|
|
ldx #$00
|
|
ldy #$00
|
|
|
|
lda PPUSTATUS
|
|
|
|
|
|
@E2A9:
|
|
lda $0200,x
|
|
sta PPUADDR
|
|
|
|
inx
|
|
|
|
lda $0200,x
|
|
sta PPUADDR
|
|
|
|
; Buffered PPU read.
|
|
lda PPUDATA
|
|
|
|
; Actual requested value.
|
|
lda PPUDATA
|
|
sta $022A,y
|
|
|
|
inx
|
|
iny
|
|
|
|
cpx #$2A
|
|
bne @E2A9
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $E2C6-$E2D3: Add 16-Bit Working Values
|
|
;
|
|
; Input:
|
|
; $12/$13 = low/high first operand
|
|
; $14/$15 = low/high second operand
|
|
;
|
|
; Output:
|
|
; $12/$13 = 16-bit sum
|
|
;==============================================================================
|
|
|
|
Add16BitWorkingValue:
|
|
clc
|
|
|
|
lda $12
|
|
adc $14
|
|
sta $12
|
|
|
|
lda $13
|
|
adc $15
|
|
sta $13
|
|
|
|
rts
|
|
;==============================================================================
|
|
; $E2D4-$E2E1: Subtract 16-Bit Working Values
|
|
;
|
|
; Input:
|
|
; $12/$13 = low/high first operand
|
|
; $14/$15 = low/high second operand
|
|
;
|
|
; Output:
|
|
; $12/$13 = first operand - second operand
|
|
;==============================================================================
|
|
Subtract16BitWorkingValue:
|
|
sec
|
|
|
|
lda $12
|
|
sbc $14
|
|
sta $12
|
|
|
|
lda $13
|
|
sbc $15
|
|
sta $13
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E2E2-$E381: Draw Gameplay Nametable
|
|
;
|
|
; Local:
|
|
; Expands compressed gameplay map data directly into VRAM.
|
|
;
|
|
; The primary destination begins at:
|
|
;
|
|
; $2040 when ($47 & $46) == 0
|
|
; $2840 when ($47 & $46) != 0
|
|
;
|
|
; The compressed source pointer is loaded from $FFF6/$FFF7.
|
|
;
|
|
; After the primary map is written, a small decoration pattern from
|
|
; MazeNametableDecorationTiles is written to additional PPU locations.
|
|
;
|
|
; Global:
|
|
; Called from GameModeState00 while initializing gameplay.
|
|
;
|
|
; Notes:
|
|
; $00/$01 = compressed source pointer during the first phase
|
|
; $02/$03 = PPU destination during the first phase
|
|
; $04 = number of PPU bytes remaining in current row
|
|
; $05 = repeat count extracted from the source byte
|
|
; X = row counter
|
|
; Y = compressed source index
|
|
;==============================================================================
|
|
|
|
DrawMazeNametable:
|
|
lda #$20
|
|
sta $02
|
|
|
|
lda #$40
|
|
sta $03
|
|
|
|
lda $47
|
|
and $46
|
|
beq @E2F4
|
|
|
|
lda #$28
|
|
sta $02
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E2F4
|
|
; Load compressed-map source pointer.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E2F4:
|
|
lda MazeDataPointerBytes+1
|
|
sta $01
|
|
|
|
lda MazeDataPointerBytes
|
|
sta $00
|
|
|
|
ldx #$1B
|
|
ldy #$00
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E302
|
|
; Set PPU destination for the next row.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E302:
|
|
lda PPUSTATUS
|
|
|
|
lda $02
|
|
sta PPUADDR
|
|
|
|
lda $03
|
|
sta PPUADDR
|
|
|
|
lda #$16
|
|
sta $04
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E313
|
|
; Start decoding the next compressed source byte.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E313:
|
|
lda #$00
|
|
sta $05
|
|
|
|
lda ($00),y
|
|
|
|
asl
|
|
rol $05
|
|
|
|
asl
|
|
rol $05
|
|
|
|
lda ($00),y
|
|
and #$3F
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E321
|
|
; Repeat the decoded value according to the repeat count in $05.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E321:
|
|
sta PPUDATA
|
|
|
|
dec $04
|
|
dec $05
|
|
bpl @E321
|
|
|
|
iny
|
|
bne @E32F
|
|
|
|
inc $01
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E32F
|
|
; Continue until the current row contains $16 output bytes.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E32F:
|
|
lda $04
|
|
bne @E313
|
|
|
|
lda $03
|
|
clc
|
|
adc #$20
|
|
sta $03
|
|
|
|
lda $02
|
|
adc #$00
|
|
sta $02
|
|
|
|
dex
|
|
bne @E302
|
|
|
|
|
|
;==============================================================================
|
|
; $E345-$E381: Draw additional nametable decoration strips.
|
|
;==============================================================================
|
|
|
|
ldy #$02
|
|
|
|
lda #$21
|
|
sta $00
|
|
|
|
lda #$D6
|
|
sta $01
|
|
|
|
lda $47
|
|
and $46
|
|
beq @E359
|
|
|
|
lda #$29
|
|
sta $00
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E359
|
|
; Start one decoration strip.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E359:
|
|
ldx #$07
|
|
|
|
lda PPUSTATUS
|
|
|
|
lda $00
|
|
sta PPUADDR
|
|
|
|
lda $01
|
|
sta PPUADDR
|
|
|
|
lda MazeNametableDecorationTiles,y
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E36B
|
|
; Write the selected table value eight times.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E36B:
|
|
sta PPUDATA
|
|
|
|
dex
|
|
bpl @E36B
|
|
|
|
lda $01
|
|
clc
|
|
adc #$20
|
|
sta $01
|
|
|
|
lda #$00
|
|
adc $00
|
|
sta $00
|
|
|
|
dey
|
|
bpl @E359
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E382-$E385: Gameplay Nametable Decoration Table
|
|
;==============================================================================
|
|
|
|
MazeNametableDecorationTiles:
|
|
.byte $2D,$04,$2D
|
|
;==============================================================================
|
|
; $E385-$E3FE: Initialize Gameplay Nametable Regions
|
|
;
|
|
; Fills gameplay nametable regions with tile $2D, then clears the corresponding
|
|
; attribute-table regions.
|
|
;
|
|
; Address-based global labels are used for shared entry points to avoid ca65
|
|
; cheap-local scope issues and collisions with previously defined symbols.
|
|
;==============================================================================
|
|
|
|
ClearGameplayNametables:
|
|
lda PPUSTATUS
|
|
|
|
lda #$20
|
|
sta PPUADDR
|
|
|
|
lda #$00
|
|
sta PPUADDR
|
|
|
|
lda #$01
|
|
sta $02
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E396
|
|
; Shared entry used for another nametable pass.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ClearGameplayNametablesSecondPass:
|
|
lda #$01
|
|
sta $03
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E39A
|
|
; Initialize fill counters.
|
|
;------------------------------------------------------------------------------
|
|
|
|
InitializeNametableFillCounters:
|
|
lda #$03
|
|
sta $00
|
|
|
|
lda #$C0
|
|
sta $01
|
|
|
|
lda #$2D
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E3A4
|
|
; Shared fill loop.
|
|
;------------------------------------------------------------------------------
|
|
|
|
FillNametableByte:
|
|
sta PPUDATA
|
|
|
|
dec $01
|
|
bne FillNametableByte
|
|
|
|
dec $00
|
|
bpl FillNametableByte
|
|
|
|
dec $03
|
|
bne AdvanceNametableFillPass
|
|
|
|
lda #$40
|
|
sta $01
|
|
|
|
lda #$00
|
|
beq FillNametableByte
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E3BB
|
|
; Advance to alternate nametable / next phase.
|
|
;------------------------------------------------------------------------------
|
|
|
|
AdvanceNametableFillPass:
|
|
dec $02
|
|
bne ClearGameplayAttributeTables
|
|
|
|
lda PPUSTATUS
|
|
|
|
lda #$28
|
|
sta PPUADDR
|
|
|
|
lda #$00
|
|
sta PPUADDR
|
|
|
|
jmp ClearGameplayNametablesSecondPass
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E3CF
|
|
; Begin clearing attribute-table regions.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ClearGameplayAttributeTables:
|
|
lda #$01
|
|
sta $00
|
|
|
|
lda PPUSTATUS
|
|
|
|
lda #$23
|
|
sta PPUADDR
|
|
|
|
lda #$C0
|
|
sta PPUADDR
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E3E0
|
|
; Shared attribute-clear setup.
|
|
;------------------------------------------------------------------------------
|
|
|
|
BeginAttributeTableClear:
|
|
lda #$00
|
|
tay
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E3E3
|
|
; Write $20 zero bytes to PPUDATA.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ClearAttributeTableLoop:
|
|
sta PPUDATA
|
|
|
|
iny
|
|
cpy #$20
|
|
bne ClearAttributeTableLoop
|
|
|
|
dec $00
|
|
bne ClearSecondAttributeTable
|
|
|
|
rts
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E3F0
|
|
; Set destination to the second attribute table, $2BC0.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ClearSecondAttributeTable:
|
|
lda PPUSTATUS
|
|
|
|
lda #$2B
|
|
sta PPUADDR
|
|
|
|
lda #$C0
|
|
sta PPUADDR
|
|
|
|
bne BeginAttributeTableClear
|
|
|
|
;==============================================================================
|
|
; $E3FF-$E473: Draw Gameplay Numeric / Status Fields
|
|
;
|
|
; Local:
|
|
; Configures a PPU destination and repeatedly draws numeric fields through
|
|
; the helper at DrawSixDigitScore.
|
|
;
|
|
; Initial destination/configuration:
|
|
;
|
|
; $00/$01 = PPU destination
|
|
; $04 = destination stride
|
|
; X = index into a pointer table at ScoreFieldSourcePointerTable
|
|
;
|
|
; The destination and table index vary depending on $47 & $46.
|
|
;
|
|
; Three fields are drawn per pass. The routine may perform another pass
|
|
; according to $47 and the current field counter.
|
|
;
|
|
; Global:
|
|
; Called by GameModeState00 as part of gameplay initialization.
|
|
;
|
|
; Notes:
|
|
; DrawSixDigitScore renders one numeric field using the source pointer
|
|
; loaded from the table at ScoreFieldSourcePointerTable.
|
|
;==============================================================================
|
|
|
|
DrawGameplayScoreFields:
|
|
lda #$20
|
|
sta $00
|
|
|
|
lda #$B6
|
|
sta $01
|
|
|
|
lda #$80
|
|
sta $04
|
|
|
|
ldx #$00
|
|
|
|
lda $47
|
|
and $46
|
|
beq @E429
|
|
|
|
lda #$28
|
|
sta $00
|
|
|
|
bne @E429
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Alternate setup path.
|
|
;------------------------------------------------------------------------------
|
|
|
|
lda #$20
|
|
sta $00
|
|
|
|
lda #$83
|
|
sta $01
|
|
|
|
lda #$09
|
|
sta $04
|
|
|
|
lda #$01
|
|
sta $47
|
|
|
|
ldx #$0C
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E429
|
|
; Adjust lookup-table index for alternate player/mode state.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E429:
|
|
lda $47
|
|
and $46
|
|
beq @E436
|
|
|
|
txa
|
|
clc
|
|
adc #$06
|
|
tax
|
|
|
|
|
|
@E436:
|
|
lda #$03
|
|
sta $05
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E43A: render one status field.
|
|
;------------------------------------------------------------------------------
|
|
|
|
@E43A:
|
|
lda PPUSTATUS
|
|
|
|
lda $00
|
|
sta PPUADDR
|
|
|
|
lda $01
|
|
sta PPUADDR
|
|
|
|
lda ScoreFieldSourcePointerTable,x
|
|
sta $02
|
|
|
|
lda ScoreFieldSourcePointerTable+1,x
|
|
sta $03
|
|
|
|
jsr DrawSixDigitScore
|
|
|
|
inx
|
|
inx
|
|
|
|
lda $01
|
|
clc
|
|
adc $04
|
|
sta $01
|
|
|
|
lda #$00
|
|
adc $00
|
|
sta $00
|
|
|
|
dec $05
|
|
|
|
lda $05
|
|
cmp #$01
|
|
bne @E46D
|
|
|
|
lda $47
|
|
beq @E473
|
|
|
|
|
|
@E46D:
|
|
lda $05
|
|
bne @E43A
|
|
|
|
|
|
@E473:
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E474-$E49E: Draw Six-Digit Numeric Field
|
|
;
|
|
; Input:
|
|
; $02/$03 = pointer to packed numeric values
|
|
;
|
|
; Local:
|
|
; Processes six source values from index 5 down to 0.
|
|
;
|
|
; Leading values whose low nibble is zero are rendered as spaces ($20).
|
|
; Once a nonzero low nibble is encountered, remaining values are converted
|
|
; through the shared conversion entry at $E1CE and written to PPUDATA.
|
|
;
|
|
; The final value at Y=0 is always converted, after which a trailing $30
|
|
; character is written.
|
|
;
|
|
; Notes:
|
|
; The conversion calls MUST target $E1CE, not $E1CA. $E1CE is the shared
|
|
; entry that begins with AND #$0F, while $E1CA additionally shifts A right
|
|
; four times.
|
|
;==============================================================================
|
|
DrawSixDigitScore:
|
|
ldy #$05
|
|
|
|
|
|
SkipLeadingZeroDigits:
|
|
lda ($02),y
|
|
and #$0F
|
|
bne ConvertCurrentScoreDigit
|
|
|
|
lda #$20
|
|
sta PPUDATA
|
|
|
|
dey
|
|
bne SkipLeadingZeroDigits
|
|
|
|
beq DrawFinalScoreDigit
|
|
|
|
|
|
LoadNextScoreDigit:
|
|
lda ($02),y
|
|
|
|
|
|
ConvertCurrentScoreDigit:
|
|
jsr $E1CE
|
|
|
|
sta PPUDATA
|
|
|
|
dey
|
|
bne LoadNextScoreDigit
|
|
|
|
|
|
DrawFinalScoreDigit:
|
|
lda ($02),y
|
|
|
|
jsr $E1CE
|
|
|
|
sta PPUDATA
|
|
|
|
lda #$30
|
|
sta PPUDATA
|
|
|
|
rts
|
|
;==============================================================================
|
|
; $E49F-$E4B0: Gameplay Status Field Source Pointer Table
|
|
;
|
|
; Local:
|
|
; Nine little-endian zero-page/RAM pointers used by the gameplay status-field
|
|
; drawing routine beginning at $E3FF.
|
|
;
|
|
; X indexes this table in steps of two. Each selected address is loaded into
|
|
; $02/$03 and passed to DrawSixDigitScore.
|
|
;
|
|
; Global:
|
|
; Selects the numeric/state arrays rendered into the different gameplay
|
|
; status display fields.
|
|
;==============================================================================
|
|
|
|
ScoreFieldSourcePointerTable:
|
|
.word $0061
|
|
.word $0070
|
|
.word $0080
|
|
|
|
.word $0061
|
|
.word $0080
|
|
.word $0070
|
|
|
|
.word $0070
|
|
.word $0061
|
|
.word $0080
|
|
|
|
;==============================================================================
|
|
; $E4B1-$E501: Build Entity Direction Candidate List
|
|
;
|
|
; Input:
|
|
; $00/$01 = pointer to direction/path data
|
|
; $0A/$0B = comparison values prepared by the caller
|
|
; X = current entity slot index
|
|
;
|
|
; Output:
|
|
; $0C-$0F = candidate direction values, with invalid entries marked $FF
|
|
;
|
|
; Local:
|
|
; First clears all four candidate entries to $FF.
|
|
;
|
|
; Then examines four values through ($00),Y. A candidate is accepted when
|
|
; either:
|
|
;
|
|
; value == $0A
|
|
;
|
|
; or:
|
|
;
|
|
; (value & $F8) != 0
|
|
; and value == $0B
|
|
;
|
|
; Accepted entries store their Y index into $0C-$0F.
|
|
;
|
|
; The entity's reverse/current-excluded direction is then calculated from
|
|
; $B9,X and explicitly removed from the candidate list.
|
|
;
|
|
; Finally performs up to three passes compacting $FF holes by shifting the
|
|
; following entry left.
|
|
;
|
|
; Global:
|
|
; Called by EntityTargetCommon at $D778 before entity direction selection.
|
|
;
|
|
; Notes:
|
|
; $0C-$0F therefore form a filtered list of legal direction indices.
|
|
;==============================================================================
|
|
|
|
BuildLegalDirectionList:
|
|
ldy #$FF
|
|
|
|
sty $0C
|
|
sty $0D
|
|
sty $0E
|
|
sty $0F
|
|
|
|
iny
|
|
|
|
|
|
ScanDirectionCandidate:
|
|
lda ($00),y
|
|
cmp $0A
|
|
beq AcceptDirectionCandidate
|
|
|
|
and #$F8
|
|
beq AcceptDirectionCandidate
|
|
|
|
cmp $0B
|
|
bne NextDirectionCandidate
|
|
|
|
|
|
AcceptDirectionCandidate:
|
|
tya
|
|
sta $000C,y
|
|
|
|
|
|
NextDirectionCandidate:
|
|
iny
|
|
cpy #$04
|
|
bne ScanDirectionCandidate
|
|
|
|
lda $B9,x
|
|
clc
|
|
adc #$02
|
|
and #$03
|
|
tay
|
|
|
|
lda #$FF
|
|
sta $000C,y
|
|
|
|
lda #$03
|
|
sta $0B
|
|
|
|
|
|
CompactDirectionListPass:
|
|
ldy #$00
|
|
|
|
|
|
CompactDirectionListEntry:
|
|
lda $000C,y
|
|
cmp #$FF
|
|
bne NextDirectionListEntry
|
|
|
|
lda $000D,y
|
|
sta $000C,y
|
|
|
|
lda #$FF
|
|
sta $000D,y
|
|
|
|
|
|
NextDirectionListEntry:
|
|
iny
|
|
cpy #$03
|
|
bne CompactDirectionListEntry
|
|
|
|
dec $0B
|
|
bne CompactDirectionListPass
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E502-$E53B: Draw Gameplay Initialization Data
|
|
;
|
|
; Local:
|
|
; Reads compact PPU command data beginning at $E53C and writes the payloads
|
|
; directly to PPUDATA.
|
|
;
|
|
; X selects between two passes/variants.
|
|
; Y indexes the command stream.
|
|
; $00 holds the number of bytes remaining in the current payload.
|
|
;
|
|
; Global:
|
|
; Called from GameModeState00 during gameplay initialization.
|
|
;==============================================================================
|
|
|
|
DrawGameplayHudLabels:
|
|
ldx #$01
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E504
|
|
; Reset command-stream index for a pass.
|
|
;------------------------------------------------------------------------------
|
|
|
|
InitData_E504:
|
|
ldy #$00
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E506
|
|
; Start one command record.
|
|
;------------------------------------------------------------------------------
|
|
|
|
InitData_E506:
|
|
lda $E53C,y
|
|
|
|
cpx #$00
|
|
bne InitData_E50F
|
|
|
|
adc #$07
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E50F
|
|
; Write PPU destination address.
|
|
;------------------------------------------------------------------------------
|
|
|
|
InitData_E50F:
|
|
sta PPUADDR
|
|
|
|
iny
|
|
|
|
lda $E53C,y
|
|
sta PPUADDR
|
|
|
|
iny
|
|
|
|
lda $E53C,y
|
|
sta $00
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E51F
|
|
; Write record payload.
|
|
;------------------------------------------------------------------------------
|
|
|
|
InitData_E51F:
|
|
iny
|
|
|
|
lda $E53C,y
|
|
sta PPUDATA
|
|
|
|
dec $00
|
|
bne InitData_E51F
|
|
|
|
iny
|
|
|
|
cpy #$11
|
|
bne InitData_E534
|
|
|
|
lda $47
|
|
bne InitData_E534
|
|
|
|
rts
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E534
|
|
; Continue through the first/second stream section.
|
|
;------------------------------------------------------------------------------
|
|
|
|
InitData_E534:
|
|
cpy #$17
|
|
bne InitData_E506
|
|
|
|
dex
|
|
beq InitData_E504
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E53C-$E552: Gameplay Initialization PPU Command Data
|
|
;
|
|
; Record format:
|
|
; byte 0 = PPU address high
|
|
; byte 1 = PPU address low
|
|
; byte 2 = payload length
|
|
; remaining bytes = payload written to PPUDATA
|
|
;==============================================================================
|
|
|
|
GameplayHudInitializationData:
|
|
|
|
; $E53C: PPU $2076, 8-byte payload
|
|
.byte $20,$76,$08
|
|
.byte $B4,$B5,$B6,$B7,$B8,$B9,$BA,$BB
|
|
|
|
; $E547: PPU $20F7, 3-byte payload
|
|
.byte $20,$F7,$03
|
|
.byte $B0,$B3,$B2
|
|
|
|
; $E54D: PPU $2177, 3-byte payload
|
|
.byte $21,$77,$03
|
|
.byte $B1,$B3,$B2
|
|
|
|
;==============================================================================
|
|
; $E553-$E5C0: Draw Progression / Status Markers
|
|
;
|
|
; Local:
|
|
; Returns immediately when $67 is zero.
|
|
;
|
|
; Otherwise computes:
|
|
;
|
|
; count = min($67 + 1, $07)
|
|
;
|
|
; and stores that in $02.
|
|
;
|
|
; Initializes:
|
|
;
|
|
; $03 = $04
|
|
; $00/$01 = $2317
|
|
;
|
|
; If ($46 & $47) != 0, the high destination byte is adjusted by $08.
|
|
;
|
|
; The routine then performs nested loops, calling the helper at $E59A with
|
|
; Y=$3C. The helper writes a 2x2-style pattern at the current PPU position.
|
|
;
|
|
; Global:
|
|
; Called during gameplay initialization to draw a progression/status display.
|
|
;
|
|
; Notes:
|
|
; $E59A is a valid internal helper entry point within this routine.
|
|
;==============================================================================
|
|
|
|
DrawLevelProgressMarkers:
|
|
lda $67
|
|
bne Progression_E558
|
|
|
|
rts
|
|
|
|
|
|
Progression_E558:
|
|
clc
|
|
adc #$01
|
|
|
|
cmp #$07
|
|
bcc Progression_E55F
|
|
|
|
lda #$07
|
|
|
|
|
|
Progression_E55F:
|
|
sta $02
|
|
|
|
lda #$04
|
|
sta $03
|
|
|
|
lda #$23
|
|
sta $00
|
|
|
|
lda #$17
|
|
sta $01
|
|
|
|
lda $46
|
|
and $47
|
|
beq Progression_E57C
|
|
|
|
lda $00
|
|
clc
|
|
adc #$08
|
|
sta $00
|
|
|
|
|
|
Progression_E57C:
|
|
dec $02
|
|
bne Progression_E581
|
|
|
|
rts
|
|
|
|
|
|
Progression_E581:
|
|
dec $03
|
|
bne Progression_E58A
|
|
|
|
lda $01
|
|
clc
|
|
adc #$3A
|
|
sta $01
|
|
|
|
|
|
Progression_E58A:
|
|
ldy #$3C
|
|
|
|
jsr Draw2x2Marker
|
|
|
|
lda $01
|
|
clc
|
|
adc #$02
|
|
sta $01
|
|
|
|
bne Progression_E57C
|
|
|
|
;==============================================================================
|
|
; $E59A-$E5C0: Draw 2x2 Progression Marker
|
|
;
|
|
; Input:
|
|
; $00/$01 = first PPU destination
|
|
; Y = first tile value
|
|
;
|
|
; Effect:
|
|
; Writes Y and Y+1 horizontally, then Y+2 and Y+3 one row ($20 bytes)
|
|
; below the initial destination.
|
|
;==============================================================================
|
|
|
|
Draw2x2Marker:
|
|
lda $00
|
|
sta PPUADDR
|
|
|
|
lda $01
|
|
sta PPUADDR
|
|
|
|
sty PPUDATA
|
|
|
|
iny
|
|
sty PPUDATA
|
|
|
|
lda $00
|
|
sta PPUADDR
|
|
|
|
lda $01
|
|
clc
|
|
adc #$20
|
|
sta PPUADDR
|
|
|
|
iny
|
|
sty PPUDATA
|
|
|
|
iny
|
|
sty PPUDATA
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $-$E699: Initialize Gameplay State / Markers
|
|
;
|
|
; Local:
|
|
; Builds several gameplay marker/display values using the current value at
|
|
; $68 and a collection of lookup tables beginning at LevelProgressMarkerIndexTable
|
|
;
|
|
; The routine:
|
|
; - Initializes working values at $0A-$0F.
|
|
; - Derives an index/count from $68.
|
|
; - Selects PPU coordinates according to $46/$47.
|
|
; - Draws repeated 2x2 marker blocks using Draw2x2Marker.
|
|
; - Combines several lookup-table values into $0A+ working state.
|
|
; - Writes the resulting values directly into PPU attribute/display areas.
|
|
; - Selects final values for $02B6 and $02A9.
|
|
;
|
|
; Global:
|
|
; Called from GameModeState00 during initial gameplay setup.
|
|
;
|
|
; Notes:
|
|
; Address-oriented labels are used for the larger loops to preserve the
|
|
; original compact branch structure.
|
|
;==============================================================================
|
|
|
|
InitializeLevelProgressDisplay:
|
|
lda #$00
|
|
sta $03
|
|
sta $0E
|
|
sta $0F
|
|
|
|
lda #$15
|
|
sta $0A
|
|
|
|
lda #$11
|
|
sta $0D
|
|
|
|
lda #$05
|
|
sta $0B
|
|
sta $0C
|
|
|
|
lda $68
|
|
sta $02
|
|
|
|
sec
|
|
sbc #$07
|
|
bcc UseFirstLevelProgressIndex
|
|
|
|
cmp #$0C
|
|
bcc ClampLevelProgressIndex
|
|
|
|
lda #$0C
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E5E9
|
|
;------------------------------------------------------------------------------
|
|
|
|
ClampLevelProgressIndex:
|
|
tax
|
|
|
|
lda #$07
|
|
sta $02
|
|
|
|
bne InitializeLevelProgressPosition
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E5F0
|
|
;------------------------------------------------------------------------------
|
|
|
|
UseFirstLevelProgressIndex:
|
|
ldx #$00
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E5F2
|
|
; Initial PPU destination.
|
|
;------------------------------------------------------------------------------
|
|
|
|
InitializeLevelProgressPosition:
|
|
lda #$22
|
|
sta $00
|
|
|
|
lda #$56
|
|
sta $01
|
|
|
|
lda $46
|
|
and $47
|
|
beq InitializeLevelProgressRowCounter
|
|
|
|
lda $00
|
|
clc
|
|
adc #$08
|
|
sta $00
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E605
|
|
;------------------------------------------------------------------------------
|
|
|
|
InitializeLevelProgressRowCounter:
|
|
lda #$05
|
|
sta $04
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E609
|
|
; Main marker loop.
|
|
;------------------------------------------------------------------------------
|
|
|
|
DrawNextLevelProgressMarker:
|
|
dec $04
|
|
bne SelectLevelProgressMarker
|
|
|
|
lda $01
|
|
clc
|
|
adc #$38
|
|
sta $01
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E612
|
|
; Select marker information.
|
|
;------------------------------------------------------------------------------
|
|
|
|
SelectLevelProgressMarker:
|
|
lda LevelProgressMarkerIndexTable,x
|
|
sta $05
|
|
|
|
asl
|
|
asl
|
|
adc #$60
|
|
tay
|
|
|
|
jsr Draw2x2Marker
|
|
|
|
ldy $03
|
|
|
|
lda LevelProgressAttributeIndexTable,y
|
|
sta $06
|
|
|
|
lda LevelProgressAttributeIndexTable+1,y
|
|
sta $07
|
|
|
|
ldy $05
|
|
|
|
lda LevelProgressAttributeBits,y
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E633
|
|
; Shift selected marker bits.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ShiftLevelProgressAttributeBits:
|
|
dec $07
|
|
bmi StoreLevelProgressAttributeBits
|
|
|
|
asl
|
|
asl
|
|
bcc ShiftLevelProgressAttributeBits
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E63B
|
|
; Combine marker bits into working values.
|
|
;------------------------------------------------------------------------------
|
|
|
|
StoreLevelProgressAttributeBits:
|
|
ldy $06
|
|
|
|
ora $0A,y
|
|
sta $0A,y
|
|
|
|
lda $01
|
|
clc
|
|
adc #$02
|
|
sta $01
|
|
|
|
inc $03
|
|
inc $03
|
|
|
|
inx
|
|
|
|
dec $02
|
|
bpl DrawNextLevelProgressMarker
|
|
|
|
|
|
;==============================================================================
|
|
; Write generated marker-state values into PPU memory.
|
|
;==============================================================================
|
|
|
|
ldx #$23
|
|
|
|
lda $47
|
|
and $46
|
|
beq SetLevelProgressAttributeAddress
|
|
|
|
ldx #$2B
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E65D
|
|
; Set first PPU destination.
|
|
;------------------------------------------------------------------------------
|
|
|
|
SetLevelProgressAttributeAddress:
|
|
stx PPUADDR
|
|
stx $00
|
|
|
|
lda #$E5
|
|
sta PPUADDR
|
|
|
|
ldx #$00
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E667
|
|
; Reset count for one three-byte PPU group.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ResetAttributeWriteCount:
|
|
lda #$03
|
|
sta $01
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E66B
|
|
; Write three values from $0A+.
|
|
;------------------------------------------------------------------------------
|
|
|
|
WriteLevelProgressAttribute:
|
|
lda $0A,x
|
|
sta PPUDATA
|
|
|
|
inx
|
|
|
|
dec $01
|
|
bne WriteLevelProgressAttribute
|
|
|
|
inc $02
|
|
bne SelectLevelProgressPalette
|
|
|
|
lda $00
|
|
sta PPUADDR
|
|
|
|
lda #$ED
|
|
sta PPUADDR
|
|
|
|
bne ResetAttributeWriteCount
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E685
|
|
; Select final marker/display value.
|
|
;------------------------------------------------------------------------------
|
|
|
|
SelectLevelProgressPalette:
|
|
lda $68
|
|
|
|
cmp #$10
|
|
bcc StoreLevelProgressPalette
|
|
|
|
lda #$0F
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E68D
|
|
;------------------------------------------------------------------------------
|
|
|
|
StoreLevelProgressPalette:
|
|
tay
|
|
|
|
lda LevelProgressPaletteTable,y
|
|
sta $02B6
|
|
|
|
lda #$0F
|
|
sta $02A9
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $E69A-$E6AD: Gameplay Marker Level Index Table
|
|
;==============================================================================
|
|
|
|
LevelProgressMarkerIndexTable:
|
|
.byte $00,$01,$02,$02
|
|
.byte $03,$03,$04,$04
|
|
.byte $05,$05,$06,$06
|
|
.byte $07,$07,$07,$07
|
|
.byte $07,$07,$07,$07
|
|
|
|
;==============================================================================
|
|
; $E6AE-$E6BD: Gameplay Marker Working-Value Table
|
|
;
|
|
; Used as byte pairs through $03.
|
|
;==============================================================================
|
|
|
|
LevelProgressAttributeIndexTable:
|
|
.byte $00,$03
|
|
.byte $01,$02
|
|
.byte $01,$03
|
|
.byte $02,$02
|
|
.byte $03,$01
|
|
.byte $04,$00
|
|
.byte $04,$01
|
|
.byte $05,$00
|
|
|
|
;==============================================================================
|
|
; $E6BE-$E6C5: Gameplay Marker Bit/Pattern Table
|
|
;==============================================================================
|
|
|
|
LevelProgressAttributeBits:
|
|
.byte $02,$02,$02,$02
|
|
.byte $03,$03,$03,$03
|
|
|
|
;==============================================================================
|
|
; $E6C6-$E6D5: Gameplay Marker Final Value Table
|
|
;
|
|
; Indexed by min($68,$0F). Selected value is stored at $02B6.
|
|
;==============================================================================
|
|
|
|
LevelProgressPaletteTable:
|
|
.byte $16,$16,$26,$26
|
|
.byte $06,$06,$19,$19
|
|
.byte $17,$17,$17,$17
|
|
.byte $12,$12,$12,$12
|
|
|
|
|
|
;==============================================================================
|
|
; $E6D6-$E737: Initialize Gameplay Transition State
|
|
;==============================================================================
|
|
|
|
InitializeGameplayTransitionState:
|
|
lda #$08
|
|
sta $43
|
|
sta PPUCTRL
|
|
|
|
|
|
TransitionInit_E6DD:
|
|
lda PPUSTATUS
|
|
bpl TransitionInit_E6DD
|
|
|
|
lda #$01
|
|
sta $060D
|
|
sta $060E
|
|
|
|
lda #$00
|
|
sta PPUMASK
|
|
|
|
jsr ClearPlayfieldNametable
|
|
|
|
lda #$01
|
|
sta $028D
|
|
|
|
lda #$01
|
|
sta $0293
|
|
|
|
lda #$F7
|
|
sta $0278
|
|
|
|
lda #$7C
|
|
sta $027A
|
|
|
|
lda #$FF
|
|
sta $1E
|
|
|
|
lda #$00
|
|
sta $1F
|
|
|
|
lda #$00
|
|
sta $88
|
|
|
|
ldy #$00
|
|
|
|
|
|
TransitionInit_CopyPalette:
|
|
lda GameplayTransitionPalette,y
|
|
sta $02A9,y
|
|
|
|
iny
|
|
cpy #$10
|
|
bne TransitionInit_CopyPalette
|
|
|
|
lda #$20
|
|
sta $026F
|
|
sta $0270
|
|
sta $0271
|
|
|
|
lda #$10
|
|
sta $3F
|
|
|
|
lda #$88
|
|
sta PPUCTRL
|
|
sta $43
|
|
|
|
jmp $CAA7
|
|
|
|
|
|
;==============================================================================
|
|
; $E738-$E7AE: Initialize Gameplay PPU Region
|
|
;
|
|
; Selects $2000/$2800 according to $47 & $46, performs a patterned fill,
|
|
; clears $40 PPU bytes, and conditionally writes tile $5E at $2230/$2A30.
|
|
;
|
|
; Several branches deliberately re-enter the counter setup at $E751.
|
|
;==============================================================================
|
|
|
|
ClearPlayfieldNametable:
|
|
ldx #$20
|
|
|
|
lda $47
|
|
and $46
|
|
beq SetPlayfieldPpuAddress
|
|
|
|
ldx #$28
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E742
|
|
; Initialize selected nametable address.
|
|
;------------------------------------------------------------------------------
|
|
|
|
SetPlayfieldPpuAddress:
|
|
lda PPUSTATUS
|
|
|
|
stx PPUADDR
|
|
|
|
lda #$00
|
|
sta PPUADDR
|
|
|
|
lda #$1C
|
|
sta $00
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E751
|
|
; Shared counter-setup entry.
|
|
;
|
|
; The outer $00 loop deliberately jumps back here rather than rebuilding $00.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ResetPlayfieldFillCounters:
|
|
lda #$02
|
|
sta $01
|
|
|
|
lda #$1C
|
|
sta $02
|
|
|
|
lda #$02
|
|
sta $03
|
|
|
|
lda #$2D
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E75F
|
|
; Shared PPUDATA write point.
|
|
;------------------------------------------------------------------------------
|
|
|
|
WritePlayfieldFillByte:
|
|
sta PPUDATA
|
|
|
|
ldx $01
|
|
beq AdvancePlayfieldInnerRun
|
|
|
|
dec $01
|
|
bne WritePlayfieldFillByte
|
|
|
|
lda #$20
|
|
bne WritePlayfieldFillByte
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E76E
|
|
; Process the second run counter.
|
|
;------------------------------------------------------------------------------
|
|
|
|
AdvancePlayfieldInnerRun:
|
|
ldx $02
|
|
beq AdvancePlayfieldOuterRun
|
|
|
|
dec $02
|
|
bne WritePlayfieldFillByte
|
|
|
|
lda #$2D
|
|
bne WritePlayfieldFillByte
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E77A
|
|
; Process outer fill counters.
|
|
;------------------------------------------------------------------------------
|
|
|
|
AdvancePlayfieldOuterRun:
|
|
dec $03
|
|
bne WritePlayfieldFillByte
|
|
|
|
dec $00
|
|
bne ResetPlayfieldFillCounters
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E782
|
|
; Clear $40 PPU bytes.
|
|
;------------------------------------------------------------------------------
|
|
|
|
lda #$00
|
|
tax
|
|
|
|
|
|
ClearPlayfieldTail:
|
|
sta PPUDATA
|
|
|
|
inx
|
|
cpx #$40
|
|
bne ClearPlayfieldTail
|
|
|
|
lda $87
|
|
cmp #$02
|
|
beq DrawPlayfieldSpecialTile
|
|
|
|
rts
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $E794
|
|
; Optional special tile at PPU $2230 or $2A30.
|
|
;------------------------------------------------------------------------------
|
|
|
|
DrawPlayfieldSpecialTile:
|
|
ldx #$22
|
|
|
|
lda $47
|
|
and $46
|
|
beq SetSpecialTilePpuAddress
|
|
|
|
ldx #$2A
|
|
|
|
|
|
SetSpecialTilePpuAddress:
|
|
lda PPUSTATUS
|
|
|
|
stx PPUADDR
|
|
|
|
lda #$30
|
|
sta PPUADDR
|
|
|
|
lda #$5E
|
|
sta PPUDATA
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $E7AF-$E7BE: Gameplay Transition Palette
|
|
;==============================================================================
|
|
|
|
GameplayTransitionPalette:
|
|
.byte $0F,$36,$20,$06
|
|
.byte $0F,$27,$20,$06
|
|
.byte $0F,$11,$20,$33
|
|
.byte $0F,$36,$20,$11
|
|
|
|
;==============================================================================
|
|
; $E7BF-$E7CD: Gameplay Transition Update Coordinator
|
|
;
|
|
; Runs several already-known gameplay/render helpers, then dispatches through
|
|
; the state machine at $E7CE before returning to the main game-mode dispatcher.
|
|
;==============================================================================
|
|
|
|
UpdateIntermissionTransition:
|
|
jsr $EA19
|
|
jsr $EA94
|
|
jsr BuildEntitySpriteBuffer
|
|
jsr DispatchIntermissionState
|
|
|
|
jmp $CAA7
|
|
|
|
|
|
;==============================================================================
|
|
; $E7CE-$E7DC: Transition state dispatcher
|
|
;
|
|
; $87 is an even state value used directly as a byte offset into the table.
|
|
;==============================================================================
|
|
|
|
DispatchIntermissionState:
|
|
ldy $87
|
|
|
|
lda IntermissionStateHandlerTable,y
|
|
sta $10
|
|
|
|
lda IntermissionStateHandlerTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
|
|
;==============================================================================
|
|
; $E7DD-$E7E2: Transition state pointer table
|
|
;==============================================================================
|
|
|
|
IntermissionStateHandlerTable:
|
|
.word DispatchIntermissionPhase
|
|
.word DispatchIntermissionState2Phase
|
|
.word DispatchIntermissionState4Phase
|
|
|
|
|
|
;==============================================================================
|
|
; $E7E3-$E7F1: Secondary transition-state dispatcher
|
|
;
|
|
; $88 is used directly as a byte offset into another pointer table.
|
|
;==============================================================================
|
|
|
|
DispatchIntermissionPhase:
|
|
ldy $88
|
|
|
|
lda IntermissionPhaseHandlerTable,y
|
|
sta $10
|
|
|
|
lda IntermissionPhaseHandlerTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
|
|
;==============================================================================
|
|
; $E7F2-$E7F9: Transition substate pointer table
|
|
;==============================================================================
|
|
|
|
IntermissionPhaseHandlerTable:
|
|
.word UpdateIntermissionPhase0
|
|
.word UpdateIntermissionPhase1
|
|
.word UpdateIntermissionPhase2
|
|
.word UpdateIntermissionPhase3
|
|
|
|
|
|
;==============================================================================
|
|
; $E7FA-$E822: Transition substate 0
|
|
;
|
|
; Waits until $0278 reaches at least $D0, then advances $88 by two and
|
|
; initializes several mirrored object/state values.
|
|
;==============================================================================
|
|
|
|
UpdateIntermissionPhase0:
|
|
lda $0278
|
|
cmp #$D0
|
|
bcc TransitionSubstate_E802
|
|
|
|
rts
|
|
|
|
|
|
TransitionSubstate_E802:
|
|
inc $88
|
|
inc $88
|
|
|
|
lda #$0C
|
|
sta $028C
|
|
|
|
lda #$20
|
|
sta $0292
|
|
|
|
lda #$F7
|
|
sta $0274
|
|
|
|
lda #$7C
|
|
sta $0276
|
|
|
|
lda #$FE
|
|
sta $1A
|
|
|
|
lda #$E0
|
|
sta $1B
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $E823-$E84D: Transition substate 1
|
|
;
|
|
; Waits for $0274 to become zero, then advances $88 and initializes a
|
|
; different object/state configuration.
|
|
;==============================================================================
|
|
|
|
UpdateIntermissionPhase1:
|
|
lda $0274
|
|
beq TransitionSubstate_E829
|
|
|
|
rts
|
|
|
|
|
|
TransitionSubstate_E829:
|
|
inc $88
|
|
inc $88
|
|
|
|
lda #$40
|
|
sta $4C
|
|
|
|
lda #$1E
|
|
sta $028C
|
|
|
|
lda #$22
|
|
sta $0292
|
|
|
|
lda #$09
|
|
sta $0274
|
|
|
|
lda #$7C
|
|
sta $0276
|
|
|
|
lda #$01
|
|
sta $1A
|
|
|
|
lda #$00
|
|
sta $1B
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $E84E-$E8B9: Transition substate 2
|
|
;
|
|
; Waits until $0274 reaches at least $80, then advances $88 and initializes
|
|
; four related coordinate/state structures and their mirrored render values.
|
|
;==============================================================================
|
|
|
|
UpdateIntermissionPhase2:
|
|
lda #$01
|
|
sta $060D
|
|
sta $060E
|
|
|
|
lda $0274
|
|
cmp #$80
|
|
bcs TransitionSubstate_E85D
|
|
|
|
rts
|
|
|
|
|
|
TransitionSubstate_E85D:
|
|
inc $88
|
|
inc $88
|
|
|
|
lda #$01
|
|
sta $1E
|
|
sta $22
|
|
sta $26
|
|
sta $2A
|
|
|
|
lda #$C0
|
|
sta $1F
|
|
sta $23
|
|
sta $27
|
|
sta $2B
|
|
|
|
clc
|
|
|
|
lda #$38
|
|
sta $028D
|
|
|
|
adc #$01
|
|
sta $028E
|
|
|
|
adc #$01
|
|
sta $028F
|
|
|
|
adc #$01
|
|
sta $0290
|
|
|
|
lda #$21
|
|
sta $0293
|
|
sta $0294
|
|
sta $0295
|
|
sta $0296
|
|
|
|
lda #$09
|
|
sta $0278
|
|
sta $0280
|
|
|
|
lda #$19
|
|
sta $027C
|
|
sta $0284
|
|
|
|
lda #$6C
|
|
sta $027A
|
|
sta $027E
|
|
|
|
lda #$7C
|
|
sta $0282
|
|
sta $0286
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $E8BA-$E8C6: Transition substate 3
|
|
;
|
|
; Waits for $0278 to become zero, then primes delay $4C and transfers to the
|
|
; routine at $EA14.
|
|
;==============================================================================
|
|
|
|
UpdateIntermissionPhase3:
|
|
lda $0278
|
|
beq TransitionSubstate_E8C0
|
|
|
|
rts
|
|
|
|
|
|
TransitionSubstate_E8C0:
|
|
lda #$40
|
|
sta $4C
|
|
|
|
jmp $EA14
|
|
|
|
|
|
;==============================================================================
|
|
; $E8C7-$E8D5: Transition State $02 Substate Dispatcher
|
|
;
|
|
; Local:
|
|
; Uses $88 as an even byte offset into IntermissionState2PhaseTable.
|
|
;==============================================================================
|
|
|
|
DispatchIntermissionState2Phase:
|
|
ldy $88
|
|
|
|
lda IntermissionState2PhaseTable,y
|
|
sta $10
|
|
|
|
lda IntermissionState2PhaseTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
|
|
;==============================================================================
|
|
; $E8D6-$E8DB: Transition phase table
|
|
;==============================================================================
|
|
|
|
IntermissionState2PhaseTable:
|
|
.word UpdateIntermissionState2Phase0
|
|
.word UpdateIntermissionState2Phase1
|
|
.word UpdateIntermissionState2Phase2
|
|
|
|
|
|
;==============================================================================
|
|
; $E8DC-$E904: Transition phase 0
|
|
;
|
|
; Waits until $0278 reaches $A0, then advances the $88 state and initializes
|
|
; the primary mirrored object/state values.
|
|
;==============================================================================
|
|
|
|
UpdateIntermissionState2Phase0:
|
|
lda $0278
|
|
cmp #$A0
|
|
bcc TransitionPhase_E8E4
|
|
|
|
rts
|
|
|
|
|
|
TransitionPhase_E8E4:
|
|
inc $88
|
|
inc $88
|
|
|
|
lda #$0C
|
|
sta $028C
|
|
|
|
lda #$20
|
|
sta $0292
|
|
|
|
lda #$F7
|
|
sta $0274
|
|
|
|
lda #$7C
|
|
sta $0276
|
|
|
|
lda #$FF
|
|
sta $1A
|
|
|
|
lda #$00
|
|
sta $1B
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $E905-$E93E: Transition phase 1
|
|
;
|
|
; Watches $0274. At $80 it installs one object configuration. At $78 it
|
|
; clears the position pair and advances to the next phase.
|
|
;==============================================================================
|
|
|
|
UpdateIntermissionState2Phase1:
|
|
lda $0274
|
|
|
|
cmp #$80
|
|
bne TransitionPhase_E92D
|
|
|
|
lda #$FF
|
|
sta $1A
|
|
|
|
lda #$C0
|
|
sta $1B
|
|
|
|
lda #$42
|
|
sta $028E
|
|
|
|
lda #$00
|
|
sta $0294
|
|
|
|
lda #$80
|
|
sta $027C
|
|
|
|
lda #$7C
|
|
sta $027E
|
|
|
|
lda #$00
|
|
sta $22
|
|
sta $23
|
|
|
|
rts
|
|
|
|
|
|
TransitionPhase_E92D:
|
|
cmp #$78
|
|
beq TransitionPhase_E933
|
|
|
|
rts
|
|
|
|
|
|
TransitionPhase_E933:
|
|
lda #$00
|
|
sta $1A
|
|
sta $1B
|
|
|
|
inc $88
|
|
inc $88
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $E93F-$E96D: Transition phase 2
|
|
;
|
|
; Uses bit $40 of $028C and timer/state value $89 to alternate the object
|
|
; state between values $46 and $47. Eventually transfers to $EA14.
|
|
;==============================================================================
|
|
|
|
UpdateIntermissionState2Phase2:
|
|
lda $028C
|
|
and #$40
|
|
bne TransitionPhase_E953
|
|
|
|
lda #$46
|
|
sta $028C
|
|
|
|
lda #$45
|
|
sta $028E
|
|
|
|
lda #$40
|
|
sta $89
|
|
|
|
rts
|
|
|
|
|
|
TransitionPhase_E953:
|
|
dec $89
|
|
beq TransitionPhase_E958
|
|
|
|
rts
|
|
|
|
|
|
TransitionPhase_E958:
|
|
lda $028C
|
|
cmp #$47
|
|
bne TransitionPhase_E963
|
|
|
|
jmp $EA14
|
|
|
|
|
|
TransitionPhase_E963:
|
|
lda #$47
|
|
sta $028C
|
|
|
|
lda #$40
|
|
sta $89
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $E96E-$E97C: Transition State $04 Dispatcher
|
|
;
|
|
; $88 is an even byte offset into the four-entry phase table.
|
|
;==============================================================================
|
|
DispatchIntermissionState4Phase:
|
|
ldy $88
|
|
|
|
lda IntermissionState4PhaseTable,y
|
|
sta $10
|
|
|
|
lda IntermissionState4PhaseTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $E97D-$E984: Transition State $04 Phase Table
|
|
;==============================================================================
|
|
IntermissionState4PhaseTable:
|
|
.word UpdateIntermissionState4Phase0
|
|
.word UpdateIntermissionState4Phase1
|
|
.word UpdateIntermissionState4Phase2
|
|
.word UpdateIntermissionState4Phase3
|
|
|
|
;==============================================================================
|
|
; $E985-$E9AD: Phase 0
|
|
;
|
|
; Waits until $0278 reaches $D8, advances $88, then installs the initial
|
|
; mirrored object/state configuration.
|
|
;==============================================================================
|
|
|
|
UpdateIntermissionState4Phase0:
|
|
lda $0278
|
|
cmp #$D8
|
|
bcc TransitionPhase_E98D
|
|
|
|
rts
|
|
|
|
TransitionPhase_E98D:
|
|
inc $88
|
|
inc $88
|
|
|
|
lda #$4C
|
|
sta $028C
|
|
|
|
lda #$20
|
|
sta $0292
|
|
|
|
lda #$F7
|
|
sta $0274
|
|
|
|
lda #$7C
|
|
sta $0276
|
|
|
|
lda #$FF
|
|
sta $1A
|
|
|
|
lda #$00
|
|
sta $1B
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E9AE-$E9D8: Phase 1
|
|
;
|
|
; Waits for $0274 to reach zero, advances $88 and installs the next object
|
|
; configuration.
|
|
;==============================================================================
|
|
|
|
UpdateIntermissionState4Phase1:
|
|
lda $0274
|
|
beq TransitionPhase_E9B4
|
|
|
|
rts
|
|
|
|
TransitionPhase_E9B4:
|
|
inc $88
|
|
inc $88
|
|
|
|
lda #$28
|
|
sta $4C
|
|
|
|
lda #$4A
|
|
sta $028C
|
|
|
|
lda #$23
|
|
sta $0292
|
|
|
|
lda #$09
|
|
sta $0274
|
|
|
|
lda #$7C
|
|
sta $0276
|
|
|
|
lda #$01
|
|
sta $1A
|
|
|
|
lda #$00
|
|
sta $1B
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $E9D9-$EA09: Phase 2
|
|
;
|
|
; Enables transition flags, waits until $0274 reaches $19, then advances $88
|
|
; and sets the next mirrored-state values.
|
|
;==============================================================================
|
|
UpdateIntermissionState4Phase2:
|
|
lda #$01
|
|
sta $060D
|
|
sta $060E
|
|
|
|
lda $0274
|
|
cmp #$19
|
|
bcs TransitionPhase_E9E8
|
|
|
|
rts
|
|
|
|
TransitionPhase_E9E8:
|
|
inc $88
|
|
inc $88
|
|
|
|
lda #$4C
|
|
sta $028D
|
|
|
|
lda #$21
|
|
sta $0293
|
|
|
|
lda #$11
|
|
sta $0278
|
|
|
|
lda #$84
|
|
sta $027A
|
|
|
|
lda #$01
|
|
sta $1E
|
|
|
|
lda #$00
|
|
sta $1F
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $EA0A-$EA18: Phase 3
|
|
;
|
|
; Waits for $0278 to reach zero, then primes the next game-mode/state
|
|
; transition.
|
|
;==============================================================================
|
|
UpdateIntermissionState4Phase3:
|
|
lda $0278
|
|
beq TransitionPhase_EA10
|
|
|
|
rts
|
|
|
|
TransitionPhase_EA10:
|
|
lda #$40
|
|
sta $4C
|
|
|
|
lda #$00
|
|
sta $3F
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $EA19-$EA93: Update Mirrored Gameplay Object Positions
|
|
;
|
|
; Local:
|
|
; Walks five four-byte structures in parallel:
|
|
;
|
|
; $00/$01 -> source gameplay structures beginning at $001A
|
|
; $02/$03 -> mirrored structures beginning at $0274
|
|
;
|
|
; Movement increments from the source structures are added into mirrored
|
|
; coordinates. Attribute bit $20 in $0292+ is adjusted according to the
|
|
; resulting coordinate, and coordinate reset/wrap handling is performed.
|
|
;
|
|
; Global:
|
|
; Called from gameplay transition processing before render data is rebuilt.
|
|
;
|
|
; Notes:
|
|
; Several branches deliberately re-enter shared code, so global address-style
|
|
; labels are used throughout.
|
|
;==============================================================================
|
|
UpdateTransitionObjectPositions:
|
|
lda #$1A
|
|
sta $00
|
|
|
|
lda #$00
|
|
sta $01
|
|
|
|
lda #$74
|
|
sta $02
|
|
|
|
lda #$02
|
|
sta $03
|
|
|
|
ldx #$00
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EA2B
|
|
; Process one structure.
|
|
;------------------------------------------------------------------------------
|
|
UpdateNextTransitionObject:
|
|
ldy #$00
|
|
|
|
lda ($02),y
|
|
beq AdvanceTransitionObjectPointers
|
|
|
|
iny
|
|
|
|
lda ($00),y
|
|
clc
|
|
adc ($02),y
|
|
sta ($02),y
|
|
|
|
dey
|
|
|
|
lda ($00),y
|
|
adc ($02),y
|
|
sta ($02),y
|
|
|
|
cmp #$C0
|
|
bcc UpdateTransitionObjectAttribute
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EA44
|
|
; Set attribute bit $20.
|
|
;------------------------------------------------------------------------------
|
|
SetTransitionObjectAttributeBit:
|
|
lda #$20
|
|
ora $0292,x
|
|
sta $0292,x
|
|
|
|
bne CheckTransitionObjectWrap
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EA4E
|
|
; Clear/set attribute according to coordinate range.
|
|
;
|
|
; If value < $40, branch backward to $EA44 and set bit $20.
|
|
; Otherwise clear bit $20 with mask $DF.
|
|
;------------------------------------------------------------------------------
|
|
|
|
UpdateTransitionObjectAttribute:
|
|
cmp #$40
|
|
bcc SetTransitionObjectAttributeBit
|
|
|
|
lda #$DF
|
|
and $0292,x
|
|
sta $0292,x
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EA5A
|
|
; Coordinate wrap/reset test.
|
|
;------------------------------------------------------------------------------
|
|
|
|
CheckTransitionObjectWrap:
|
|
ldy #$00
|
|
|
|
lda ($02),y
|
|
cmp #$FC
|
|
bcc CheckTransitionObjectLowBoundary
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EA62
|
|
; Reset coordinate/movement state.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ResetTransitionObjectPosition:
|
|
lda #$00
|
|
sta ($02),y
|
|
sta ($00),y
|
|
|
|
iny
|
|
sta ($00),y
|
|
|
|
iny
|
|
sta ($02),y
|
|
|
|
bne AdvanceTransitionObjectPointers
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EA70
|
|
; Values below $04 also take the reset path.
|
|
;------------------------------------------------------------------------------
|
|
|
|
CheckTransitionObjectLowBoundary:
|
|
cmp #$04
|
|
bcc ResetTransitionObjectPosition
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EA74
|
|
; Advance both source and mirrored pointers.
|
|
;------------------------------------------------------------------------------
|
|
|
|
AdvanceTransitionObjectPointers:
|
|
lda $00
|
|
clc
|
|
adc #$04
|
|
sta $00
|
|
|
|
lda $01
|
|
adc #$00
|
|
sta $01
|
|
|
|
lda $02
|
|
clc
|
|
adc #$04
|
|
sta $02
|
|
|
|
lda $03
|
|
adc #$00
|
|
sta $03
|
|
|
|
inx
|
|
|
|
cpx #$05
|
|
bne UpdateNextTransitionObject
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $EA94-$EAA2: Gameplay Animation State Dispatcher
|
|
;
|
|
; $87 is an even state value used directly as an offset into the pointer table
|
|
; at $EAA3.
|
|
;==============================================================================
|
|
|
|
DispatchTransitionAnimation:
|
|
ldy $87
|
|
|
|
lda TransitionAnimationHandlerTable,y
|
|
sta $10
|
|
|
|
lda TransitionAnimationHandlerTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $EAA3-$EAA8: Gameplay Animation State Table
|
|
;==============================================================================
|
|
|
|
TransitionAnimationHandlerTable:
|
|
.word DispatchTransitionAnimationPhase
|
|
.word DispatchTransitionAnimationState2
|
|
.word DispatchTransitionAnimationState4
|
|
|
|
;==============================================================================
|
|
; $EAA9-$EAB7: Animation Substate Dispatcher
|
|
;
|
|
; $88 is an even state value used directly as an offset into this table.
|
|
;==============================================================================
|
|
|
|
DispatchTransitionAnimationPhase:
|
|
ldy $88
|
|
|
|
lda TransitionAnimationPhaseTable,y
|
|
sta $10
|
|
|
|
lda TransitionAnimationPhaseTable+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
|
|
;==============================================================================
|
|
; $EAB8-$EABF: Animation Substate Table
|
|
;==============================================================================
|
|
|
|
TransitionAnimationPhaseTable:
|
|
.word UpdateTransitionAnimationFrame
|
|
.word UpdateTransitionAnimationType1
|
|
.word UpdateTransitionAnimationType2
|
|
.word UpdateTransitionAnimationPattern
|
|
|
|
|
|
;==============================================================================
|
|
; $EAC0-$EACD: Animation Substate 0
|
|
;
|
|
; Advances $B7 modulo eight and uses it to select a value for $028D.
|
|
;==============================================================================
|
|
|
|
UpdateTransitionAnimationFrame:
|
|
inc $B7
|
|
|
|
lda $B7
|
|
and #$07
|
|
tay
|
|
|
|
lda TransitionAnimationFrameTable,y
|
|
sta $028D
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $EACE-$EAD5: Animation frame table
|
|
;==============================================================================
|
|
|
|
TransitionAnimationFrameTable:
|
|
.byte $04,$04,$04,$05
|
|
.byte $05,$04,$01,$01
|
|
|
|
|
|
;==============================================================================
|
|
; $EAD6-$EAEC: Animation Substate 1
|
|
;
|
|
; Runs only when ($4B & 7) == 0. Alternates $028C between $0C and $0D
|
|
; according to frame-counter bit 3, then falls back into the common animation
|
|
; update path beginning at $EAC0.
|
|
;==============================================================================
|
|
|
|
UpdateTransitionAnimationType1:
|
|
lda $4B
|
|
and #$07
|
|
bne UpdateTransitionAnimationFrame
|
|
|
|
lda $4B
|
|
and #$08
|
|
bne AnimationSubstate_EAE7
|
|
|
|
lda #$0C
|
|
bne AnimationSubstate_EAE9
|
|
|
|
|
|
AnimationSubstate_EAE7:
|
|
lda #$0D
|
|
|
|
|
|
AnimationSubstate_EAE9:
|
|
sta $028C
|
|
|
|
bne UpdateTransitionAnimationFrame
|
|
|
|
|
|
;==============================================================================
|
|
; $EAED-$EB03: Animation Substate 2
|
|
;
|
|
; Updates only once every eight frames and alternates $028C between $1E/$1F
|
|
; according to frame-counter bit 3.
|
|
;==============================================================================
|
|
|
|
UpdateTransitionAnimationType2:
|
|
lda $4B
|
|
and #$07
|
|
beq AnimationSubstate_EAF5
|
|
|
|
rts
|
|
|
|
|
|
AnimationSubstate_EAF5:
|
|
lda $4B
|
|
and #$08
|
|
bne AnimationSubstate_EB00
|
|
|
|
lda #$1E
|
|
bne AnimationSubstate_EB02
|
|
|
|
|
|
AnimationSubstate_EB00:
|
|
lda #$1F
|
|
|
|
|
|
AnimationSubstate_EB02:
|
|
sta $028C
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $EB04-$EB28: Animation Substate 3
|
|
;
|
|
; Advances $B7 modulo eight, maps the result through a small index table, and
|
|
; uses the selected entry to load four consecutive animation values into
|
|
; $028D-$0290.
|
|
;
|
|
; The final BNE intentionally branches backward into the common update path.
|
|
;==============================================================================
|
|
|
|
UpdateTransitionAnimationPattern:
|
|
inc $B7
|
|
|
|
lda $B7
|
|
and #$07
|
|
tay
|
|
|
|
lda TransitionAnimationPatternIndex,y
|
|
tay
|
|
|
|
lda TransitionAnimationPatternTiles,y
|
|
sta $028D
|
|
|
|
lda TransitionAnimationPatternTiles+1,y
|
|
sta $028E
|
|
|
|
lda TransitionAnimationPatternTiles+2,y
|
|
sta $028F
|
|
|
|
lda TransitionAnimationPatternTiles+3,y
|
|
sta $0290
|
|
|
|
bne UpdateTransitionAnimationType2
|
|
|
|
|
|
;==============================================================================
|
|
; $EB29-$EB30: Animation pattern index table
|
|
;==============================================================================
|
|
|
|
TransitionAnimationPatternIndex:
|
|
.byte $00,$00,$00,$04
|
|
.byte $04,$00,$08,$08
|
|
|
|
|
|
;==============================================================================
|
|
; $EB31-$EB3C: Animation pattern data
|
|
;
|
|
; Indexed using offsets 0, 4 and 8. The final logical group continues beyond
|
|
; this initial range, so preserve the next code/data boundary carefully.
|
|
;==============================================================================
|
|
TransitionAnimationPatternTiles:
|
|
.byte $3C,$3D,$3E,$3F
|
|
.byte $3C,$40,$3E,$41
|
|
.byte $38,$39,$3A,$3B
|
|
|
|
;==============================================================================
|
|
; $EB3D-$EB4B: Gameplay Animation State $02 Dispatcher
|
|
;==============================================================================
|
|
|
|
DispatchTransitionAnimationState2:
|
|
ldy $88
|
|
|
|
lda TransitionAnimationState2Table,y
|
|
sta $10
|
|
|
|
lda TransitionAnimationState2Table+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
|
|
;==============================================================================
|
|
; $EB4C-$EB51: Gameplay Animation State $02 Pointer Table
|
|
;==============================================================================
|
|
|
|
TransitionAnimationState2Table:
|
|
.word UpdateTransitionAnimationFrame
|
|
.word UpdateTransitionAnimationState2
|
|
.word UpdateTransitionAnimationFrame
|
|
|
|
|
|
;==============================================================================
|
|
; $EB52-$EB6C: Animation State $02 Handler
|
|
;==============================================================================
|
|
|
|
UpdateTransitionAnimationState2:
|
|
jsr UpdateTransitionAnimationType1
|
|
|
|
lda $0274
|
|
cmp #$7D
|
|
bne AnimationState2_EB62
|
|
|
|
lda #$43
|
|
sta $028E
|
|
|
|
rts
|
|
|
|
|
|
AnimationState2_EB62:
|
|
cmp #$7B
|
|
beq AnimationState2_EB68
|
|
|
|
rts
|
|
|
|
|
|
AnimationState2_EB68:
|
|
lda #$44
|
|
sta $028E
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $EB6D-$EB7B: Gameplay Animation State $04 Dispatcher
|
|
;==============================================================================
|
|
DispatchTransitionAnimationState4:
|
|
ldy $88
|
|
|
|
lda TransitionAnimationState4Table,y
|
|
sta $10
|
|
|
|
lda TransitionAnimationState4Table+1,y
|
|
sta $11
|
|
|
|
jmp ($0010)
|
|
|
|
;==============================================================================
|
|
; $EB7C-$EB83: Gameplay Animation State $04 Pointer Table
|
|
;==============================================================================
|
|
|
|
TransitionAnimationState4Table:
|
|
.word UpdateTransitionAnimationFrame
|
|
.word UpdateTransitionAnimationState4Type1
|
|
.word UpdateTransitionAnimationState4Type2
|
|
.word UpdateTransitionAnimationState4Type2
|
|
|
|
;==============================================================================
|
|
; $EB84-$EB9E: Animation State $04 Handler 1
|
|
;
|
|
; Alternates $028C between $48/$49 every eight frames, while non-update
|
|
; frames tail-jump into the common $EAC0 animation updater.
|
|
;==============================================================================
|
|
UpdateTransitionAnimationState4Type1:
|
|
lda $4B
|
|
and #$07
|
|
beq AnimationState4_EB8E
|
|
|
|
jmp UpdateTransitionAnimationFrame
|
|
|
|
AnimationState4_EB8E:
|
|
lda $4B
|
|
and #$08
|
|
bne AnimationState4_EB97
|
|
|
|
lda #$48
|
|
bne AnimationState4_EB99
|
|
|
|
AnimationState4_EB97:
|
|
lda #$49
|
|
|
|
AnimationState4_EB99:
|
|
sta $028C
|
|
|
|
jmp UpdateTransitionAnimationFrame
|
|
|
|
;==============================================================================
|
|
; $EB9F-$EBB5: Animation State $04 Handler 2/3
|
|
;
|
|
; Alternates $028C between $4A and $4B every eight frames.
|
|
;==============================================================================
|
|
|
|
UpdateTransitionAnimationState4Type2:
|
|
lda $4B
|
|
and #$07
|
|
beq AnimationState4_EBA6
|
|
|
|
rts
|
|
|
|
AnimationState4_EBA6:
|
|
lda $4B
|
|
and #$08
|
|
bne AnimationState4_EBB0
|
|
|
|
lda #$4A
|
|
bne AnimationState4_EBB2
|
|
|
|
AnimationState4_EBB0:
|
|
lda #$4B
|
|
|
|
AnimationState4_EBB2:
|
|
sta $028C
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $EBB6-$EC3F: Gameplay Lookup Data
|
|
;
|
|
; Raw lookup data preserved byte-for-byte.
|
|
; Semantic subdivision is deferred until the consuming routines are decoded.
|
|
;==============================================================================
|
|
|
|
MazeGameplayData_EBB6:
|
|
|
|
; $EBB6-$EBC5
|
|
.byte $00,$07,$00,$00,$00,$04,$01,$06
|
|
.byte $01,$01,$01,$04,$01,$04,$02,$02
|
|
|
|
; $EBC6-$EBD5
|
|
.byte $02,$03,$02,$03,$02,$02,$02,$03
|
|
.byte $02,$02,$02,$02,$03,$03,$03,$05
|
|
|
|
; $EBD6-$EBE5
|
|
.byte $03,$02,$03,$03,$03,$02,$03,$02
|
|
.byte $04,$03,$03,$02,$03,$02,$04,$03
|
|
|
|
; $EBE6-$EBF5
|
|
.byte $03,$01,$04,$02,$05,$03,$03,$05
|
|
.byte $04,$02,$05,$03,$03,$02,$04,$02
|
|
|
|
; $EBF6-$EC05
|
|
.byte $06,$03,$03,$01,$05,$02,$06,$03
|
|
.byte $03,$01,$05,$02,$07,$03,$03,$03
|
|
|
|
; $EC06-$EC15
|
|
.byte $05,$02,$07,$03,$03,$01,$06,$02
|
|
.byte $07,$03,$03,$01,$06,$02,$07,$03
|
|
|
|
; $EC16-$EC25
|
|
.byte $03,$00,$06,$02,$07,$03,$03,$01
|
|
.byte $06,$02,$07,$03,$03,$00,$06,$02
|
|
|
|
; $EC26-$EC35
|
|
.byte $07,$03,$03,$00,$06,$02,$07,$03
|
|
.byte $03,$00,$06,$02,$07,$03,$04,$00
|
|
|
|
; $EC36-$EC3F
|
|
.byte $06,$02,$07,$03,$04,$00,$06,$02
|
|
.byte $07,$03
|
|
|
|
|
|
;==============================================================================
|
|
; $EC40-$ECAB: Gameplay Parameter Lookup Data
|
|
;
|
|
; Raw lookup data preserved byte-for-byte.
|
|
;
|
|
; The byte pattern strongly resembles little-endian 16-bit quantities, but
|
|
; semantic grouping is intentionally deferred until the consuming routines
|
|
; have been identified.
|
|
;==============================================================================
|
|
MazeGameplayData_EC40:
|
|
; $EC40-$EC4F
|
|
.byte $D0,$00,$C0,$00,$A0,$00,$B0,$00
|
|
.byte $A0,$00,$80,$00,$A0,$00,$B0,$00
|
|
|
|
; $EC50-$EC5F
|
|
.byte $90,$00,$50,$00,$50,$00,$D0,$00
|
|
.byte $C0,$00,$A0,$00,$B0,$00,$A0,$00
|
|
|
|
; $EC60-$EC6F
|
|
.byte $80,$00,$B0,$00,$C0,$00,$A0,$00
|
|
.byte $50,$00,$50,$00,$F0,$00,$E0,$00
|
|
|
|
; $EC70-$EC7F
|
|
.byte $C0,$00,$E0,$00,$D0,$00,$B0,$00
|
|
.byte $E0,$00,$F0,$00,$D0,$00,$70,$00
|
|
|
|
; $EC80-$EC8F
|
|
.byte $70,$00,$00,$01,$F0,$00,$D0,$00
|
|
.byte $00,$01,$F0,$00,$D0,$00,$00,$01
|
|
|
|
; $EC90-$EC9F
|
|
.byte $10,$01,$F0,$00,$80,$00,$80,$00
|
|
.byte $00,$01,$F0,$00,$D0,$00,$00,$01
|
|
|
|
; $ECA0-$ECAB
|
|
.byte $F0,$00,$D0,$00,$20,$01,$30,$01
|
|
.byte $10,$01,$80,$00
|
|
|
|
|
|
|
|
;==============================================================================
|
|
; $ECAC-$ECFF: Gameplay Lookup / Parameter Data
|
|
;
|
|
; Raw data preserved byte-for-byte. Semantic subdivision is intentionally
|
|
; deferred until the consuming routines are decoded.
|
|
;==============================================================================
|
|
|
|
MazeGameplayData_ECAC:
|
|
|
|
; $ECAC-$ECBB
|
|
.byte $80,$00,$07,$14,$07,$14,$05,$14
|
|
.byte $05,$FF,$07,$14,$07,$14,$05,$FF
|
|
|
|
; $ECBC-$ECCB
|
|
.byte $00,$00,$05,$14,$05,$14,$05,$FF
|
|
.byte $00,$00,$05,$14,$05,$14,$05,$FF
|
|
|
|
; $ECCC-$ECDB
|
|
.byte $00,$00,$14,$0A,$1E,$0F,$28,$14
|
|
.byte $32,$19,$3C,$1E,$50,$28,$64,$32
|
|
|
|
; $ECDC-$ECEB
|
|
.byte $02,$1E,$5A,$00,$03,$32,$00,$00
|
|
.byte $04,$00,$00,$00,$01,$07,$11,$20
|
|
|
|
; $ECEC-$ECFB
|
|
.byte $2D,$1F,$D0,$D0,$10,$13,$D0,$D0
|
|
.byte $10,$1D,$2D,$11,$C3,$C3,$03,$11
|
|
|
|
; $ECFC-$ECFF
|
|
.byte $C3,$C3,$03,$11
|
|
|
|
;==============================================================================
|
|
; $ED00-$EDFF: Gameplay Lookup / Pattern Data
|
|
;
|
|
; Raw data preserved byte-for-byte. This region contains highly structured
|
|
; repeated values and bit-pattern-like fields, but semantic subdivisions are
|
|
; deferred until the routines that consume this region are identified.
|
|
;==============================================================================
|
|
|
|
MazeLayoutData_ED00:
|
|
|
|
; $ED00-$ED0F
|
|
.byte $2D,$11,$03,$1F,$10,$1D,$03,$1F
|
|
.byte $10,$1D,$03,$11,$03,$1F,$10,$1D
|
|
|
|
; $ED10-$ED1F
|
|
.byte $03,$1F,$10,$1D,$03,$11,$2D,$11
|
|
.byte $01,$11,$20,$11,$03,$11,$20,$11
|
|
|
|
; $ED20-$ED2F
|
|
.byte $03,$11,$03,$11,$20,$11,$03,$11
|
|
.byte $20,$11,$01,$11,$2D,$11,$03,$1E
|
|
|
|
; $ED30-$ED3F
|
|
.byte $10,$1C,$03,$1E,$10,$1C,$03,$1A
|
|
.byte $03,$1E,$10,$1C,$03,$1E,$10,$1C
|
|
|
|
; $ED40-$ED4F
|
|
.byte $03,$11,$2D,$11,$C3,$C3,$C3,$C3
|
|
.byte $83,$11,$2D,$11,$03,$1F,$10,$1D
|
|
|
|
; $ED50-$ED5F
|
|
.byte $03,$1B,$03,$1F,$10,$10,$10,$1D
|
|
.byte $03,$1B,$03,$1F,$10,$1D,$03,$11
|
|
|
|
; $ED60-$ED6F
|
|
.byte $2D,$11,$03,$1E,$10,$1C,$03,$11
|
|
.byte $03,$1E,$10,$13,$10,$1C,$03,$11
|
|
|
|
; $ED70-$ED7F
|
|
.byte $03,$1E,$10,$1C,$03,$11,$2D,$11
|
|
.byte $C3,$03,$11,$83,$11,$83,$11,$C3
|
|
|
|
; $ED80-$ED8F
|
|
.byte $03,$11,$2D,$1E,$90,$1D,$03,$15
|
|
.byte $10,$18,$08,$1A,$08,$19,$10,$14
|
|
|
|
; $ED90-$ED9F
|
|
.byte $03,$1F,$90,$1C,$2D,$E0,$11,$03
|
|
.byte $11,$C0,$80,$11,$03,$11,$E0,$2D
|
|
|
|
; $EDA0-$EDAF
|
|
.byte $E0,$11,$03,$11,$00,$1F,$17,$2C
|
|
.byte $16,$1D,$00,$11,$03,$11,$E0,$2D
|
|
|
|
; $EDB0-$EDBF
|
|
.byte $22,$90,$1C,$03,$1A,$00,$11,$80
|
|
.byte $11,$00,$1A,$03,$1E,$90,$21,$04
|
|
|
|
; $EDC0-$EDCF
|
|
.byte $06,$C0,$03,$40,$11,$80,$11,$40
|
|
.byte $03,$C0,$05,$2D,$22,$90,$1D,$03
|
|
|
|
; $EDD0-$EDDF
|
|
.byte $1B,$00,$1E,$90,$1C,$00,$1B,$03
|
|
.byte $1F,$90,$21,$2D,$E0,$11,$03,$11
|
|
|
|
; $EDE0-$EDEF
|
|
.byte $C0,$80,$11,$03,$11,$E0,$2D,$E0
|
|
.byte $11,$03,$11,$00,$1F,$90,$1D,$00
|
|
|
|
; $EDF0-$EDFF
|
|
.byte $11,$03,$11,$E0,$2D,$1F,$90,$1C
|
|
.byte $03,$1A,$00,$1E,$10,$13,$10,$1C
|
|
|
|
;==============================================================================
|
|
; $EE00-$EE8B: Gameplay Lookup / Pattern Data
|
|
;
|
|
; Raw data preserved byte-for-byte.
|
|
;==============================================================================
|
|
|
|
MazeLayoutData_EE00:
|
|
|
|
; $EE00-$EE0F
|
|
.byte $00,$1A,$03,$1E,$90,$1D,$2D,$11
|
|
.byte $C3,$C3,$03,$11,$C3,$C3,$03,$11
|
|
|
|
; $EE10-$EE1F
|
|
.byte $2D,$11,$03,$19,$10,$1D,$03,$19
|
|
.byte $10,$18,$09,$1A,$09,$19,$10,$18
|
|
|
|
; $EE20-$EE2F
|
|
.byte $03,$1F,$10,$18,$03,$11,$2D,$11
|
|
.byte $01,$43,$11,$C3,$03,$00,$C3,$03
|
|
|
|
; $EE30-$EE3F
|
|
.byte $11,$43,$01,$11,$2D,$15,$10,$1D
|
|
.byte $03,$11,$03,$1B,$03,$1F,$90,$1D
|
|
|
|
; $EE40-$EE4F
|
|
.byte $03,$1B,$03,$11,$03,$1F,$10,$14
|
|
.byte $2D,$15,$10,$1C,$03,$1A,$03,$11
|
|
|
|
; $EE50-$EE5F
|
|
.byte $03,$1E,$10,$13,$10,$1C,$03,$11
|
|
.byte $03,$1A,$03,$1E,$10,$14,$2D,$11
|
|
|
|
; $EE60-$EE6F
|
|
.byte $C3,$03,$11,$83,$11,$83,$11,$C3
|
|
.byte $03,$11,$2D,$11,$03,$19,$90,$12
|
|
|
|
; $EE70-$EE7F
|
|
.byte $10,$18,$03,$1A,$03,$19,$10,$12
|
|
.byte $90,$18,$03,$11,$2D,$11,$C3,$C3
|
|
|
|
; $EE80-$EE8B
|
|
.byte $C3,$C3,$83,$11,$2D,$1E,$D0,$D0
|
|
.byte $D0,$D0,$90,$1C
|
|
|
|
|
|
;==============================================================================
|
|
; $EE8C-$EECF: Initialize Runtime Work Buffers
|
|
;
|
|
; Initializes zero-page runtime pointers and hardware state, clears $0600-$060F,
|
|
; then clears sixteen locations at eight-byte intervals beginning at $0620.
|
|
;==============================================================================
|
|
|
|
InitializeAudioEngine:
|
|
lda #$00
|
|
sta audioRequestPtr
|
|
|
|
lda #$06
|
|
sta audioRequestPtr+1
|
|
|
|
lda #$20
|
|
sta audioChannelTablePtr
|
|
|
|
lda #$06
|
|
sta audioChannelTablePtr+1
|
|
|
|
lda $F100
|
|
sta audioSequenceTablePtr
|
|
|
|
lda $F101
|
|
sta audioSequenceTablePtr+1
|
|
|
|
lda #$40
|
|
sta audioWorkValue
|
|
|
|
lda #$1F
|
|
sta APUSTATUS
|
|
|
|
lda #$C0
|
|
sta APUFRAMECNT
|
|
|
|
ldy #$00
|
|
|
|
lda #$00
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EEB8
|
|
; Clear sixteen contiguous bytes through ($F0).
|
|
;------------------------------------------------------------------------------
|
|
|
|
RuntimeInit_Clear0600:
|
|
sta (audioRequestPtr),y
|
|
|
|
iny
|
|
cpy #$10
|
|
bne RuntimeInit_Clear0600
|
|
|
|
ldy #$00
|
|
ldx #$10
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EEC3
|
|
; Clear sixteen entries at an eight-byte stride.
|
|
;
|
|
; LDA #$00 is intentionally executed on every iteration.
|
|
;------------------------------------------------------------------------------
|
|
RuntimeInit_Clear0620Stride:
|
|
lda #$00
|
|
sta (audioChannelTablePtr),y
|
|
|
|
tya
|
|
clc
|
|
adc #$08
|
|
tay
|
|
|
|
dex
|
|
bne RuntimeInit_Clear0620Stride
|
|
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $EED0-$EF2C: Initialize and Scan Runtime Command Slots
|
|
;
|
|
; Clears runtime work values, then scans sixteen 8-byte entries addressed
|
|
; through $F2/$F3. Occupied entries update flags through $FE/$FF, while newly
|
|
; activated entries copy four bytes through the pointer selected in $F6.
|
|
;
|
|
; Execution falls through at $EF2D into the next processing phase.
|
|
;==============================================================================
|
|
|
|
InitializeAudioChannels:
|
|
lda #$00
|
|
sta audioChannelFlags
|
|
sta $F9
|
|
sta $FA
|
|
sta $FB
|
|
sta audioChannelOffset
|
|
sta $FF
|
|
|
|
lda #$F8
|
|
sta audioIndirectPtr
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EEE2
|
|
; Examine one eight-byte slot.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ScanAudioChannelSlot:
|
|
ldy $FD
|
|
|
|
lda (audioChannelTablePtr),y
|
|
beq AdvanceAudioChannelSlot
|
|
|
|
cmp #$05
|
|
bcc ActivateAudioChannelSlot
|
|
|
|
sec
|
|
sbc #$05
|
|
tay
|
|
|
|
lda #$01
|
|
sta ($FE),y
|
|
|
|
jmp AdvanceAudioChannelSlot
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EEF5
|
|
; Process slot values $01-$04.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ActivateAudioChannelSlot:
|
|
sec
|
|
sbc #$01
|
|
tay
|
|
|
|
lda ($FE),y
|
|
bne AdvanceAudioChannelSlot
|
|
|
|
lda #$01
|
|
sta ($FE),y
|
|
|
|
tya
|
|
tax
|
|
|
|
adc #$04
|
|
|
|
ldy $FD
|
|
sta ($F2),y
|
|
|
|
txa
|
|
asl
|
|
asl
|
|
sta $F6
|
|
|
|
ldx #$00
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EF12
|
|
; Set initial four-byte copy count.
|
|
;------------------------------------------------------------------------------
|
|
|
|
BeginAudioChannelParameterCopy:
|
|
lda #$04
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EF14
|
|
; Push the current copy count.
|
|
;
|
|
; The loop at $EF20 deliberately returns here, so PHA is repeated on every
|
|
; iteration.
|
|
;------------------------------------------------------------------------------
|
|
|
|
CopyAudioChannelParameter:
|
|
pha
|
|
|
|
iny
|
|
|
|
lda ($F2),y
|
|
sta ($F6,x)
|
|
|
|
inc $F6
|
|
|
|
pla
|
|
|
|
sec
|
|
sbc #$01
|
|
bne CopyAudioChannelParameter
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EF22
|
|
; Advance to the next eight-byte slot.
|
|
;------------------------------------------------------------------------------
|
|
|
|
AdvanceAudioChannelSlot:
|
|
lda $FD
|
|
clc
|
|
adc #$08
|
|
sta $FD
|
|
|
|
cmp #$80
|
|
bcc ScanAudioChannelSlot
|
|
|
|
; Fall through to $EF2D.
|
|
|
|
|
|
;==============================================================================
|
|
; $EF2D-$F006: Process Runtime Command Entries
|
|
;
|
|
; Continuation of the runtime command-slot scan.
|
|
;
|
|
; $FC indexes source commands through ($F0).
|
|
; $FD indexes eight-byte runtime records through ($F2).
|
|
;
|
|
; Empty runtime records are initialized from tables through $F4/$F5 and
|
|
; command bytes fetched through the helper at $F0C3. Active records update
|
|
; countdowns and command parameters before both indices advance.
|
|
;==============================================================================
|
|
|
|
UpdateAudioChannels:
|
|
ldy #$00
|
|
sty $FC
|
|
sty $FD
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EF33
|
|
; Process one source entry.
|
|
;------------------------------------------------------------------------------
|
|
|
|
UpdateNextAudioSequence:
|
|
ldy $FC
|
|
|
|
lda ($F0),y
|
|
bne CheckAudioChannelActive
|
|
|
|
jmp AdvanceAudioSequence
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EF3B
|
|
; Check the corresponding runtime record.
|
|
;------------------------------------------------------------------------------
|
|
|
|
CheckAudioChannelActive:
|
|
ldy $FD
|
|
|
|
lda ($F2),y
|
|
bne TickAudioChannelDelay
|
|
|
|
lda $FC
|
|
asl
|
|
tay
|
|
|
|
lda ($F4),y
|
|
pha
|
|
|
|
lda $FD
|
|
adc #$05
|
|
tay
|
|
|
|
pla
|
|
sta ($F2),y
|
|
|
|
lda $FC
|
|
asl
|
|
adc #$01
|
|
tay
|
|
|
|
lda ($F4),y
|
|
pha
|
|
|
|
lda $FD
|
|
adc #$06
|
|
tay
|
|
|
|
pla
|
|
sta ($F2),y
|
|
|
|
jsr $F0C3
|
|
|
|
ldy $FD
|
|
sta ($F2),y
|
|
|
|
jsr $F0C3
|
|
tax
|
|
|
|
lda $FD
|
|
clc
|
|
adc #$01
|
|
tay
|
|
|
|
txa
|
|
sta ($F2),y
|
|
|
|
jsr $F0C3
|
|
tax
|
|
|
|
lda $FD
|
|
clc
|
|
adc #$02
|
|
tay
|
|
|
|
txa
|
|
sta ($F2),y
|
|
|
|
jsr $F0C3
|
|
tax
|
|
|
|
lda $FD
|
|
clc
|
|
adc #$04
|
|
tay
|
|
|
|
txa
|
|
sta ($F2),y
|
|
|
|
jmp DecodeAudioCommand
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EF94
|
|
; Decrement the active record countdown at offset 7.
|
|
;------------------------------------------------------------------------------
|
|
|
|
TickAudioChannelDelay:
|
|
lda $FD
|
|
clc
|
|
adc #$07
|
|
tay
|
|
|
|
lda ($F2),y
|
|
sec
|
|
sbc #$01
|
|
sta ($F2),y
|
|
|
|
bne AdvanceAudioSequence
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EFA2
|
|
; Fetch and decode the next runtime command byte.
|
|
;------------------------------------------------------------------------------
|
|
|
|
DecodeAudioCommand:
|
|
jsr $F0C3
|
|
|
|
cmp #$F0
|
|
bcs $F00D
|
|
|
|
cmp #$C0
|
|
bcs LoadAudioCommandDelay
|
|
|
|
pha
|
|
|
|
and #$F0
|
|
lsr
|
|
lsr
|
|
lsr
|
|
tax
|
|
|
|
lda AudioFrequencyLookupTable,x
|
|
sta $FE
|
|
|
|
lda AudioFrequencyLookupTable+1,x
|
|
sta $FF
|
|
|
|
pla
|
|
|
|
and #$0F
|
|
beq ApplyAudioFrequencyMask
|
|
|
|
tax
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EFC4
|
|
; Shift the selected mask by the command low nibble.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ShiftAudioFrequencyMask:
|
|
lsr $FE
|
|
ror $FF
|
|
|
|
dex
|
|
bne ShiftAudioFrequencyMask
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EFCB
|
|
; Merge the generated mask into the runtime record.
|
|
;------------------------------------------------------------------------------
|
|
|
|
ApplyAudioFrequencyMask:
|
|
lda $FD
|
|
clc
|
|
adc #$04
|
|
tay
|
|
|
|
lda ($F2),y
|
|
and #$F8
|
|
ora $FE
|
|
sta ($F2),y
|
|
|
|
lda $FF
|
|
dey
|
|
sta ($F2),y
|
|
|
|
ldy $FD
|
|
|
|
lda ($F2),y
|
|
cmp #$05
|
|
bcc LoadAudioCommandDelay
|
|
|
|
sec
|
|
sbc #$04
|
|
sta ($F2),y
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EFEB
|
|
; Load the new runtime countdown.
|
|
;------------------------------------------------------------------------------
|
|
|
|
LoadAudioCommandDelay:
|
|
jsr $F0C3
|
|
pha
|
|
|
|
lda $FD
|
|
clc
|
|
adc #$07
|
|
tay
|
|
|
|
pla
|
|
sta ($F2),y
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; $EFF8
|
|
; Advance to the next runtime/source entry.
|
|
;------------------------------------------------------------------------------
|
|
|
|
AdvanceAudioSequence:
|
|
lda $FD
|
|
clc
|
|
adc #$08
|
|
sta $FD
|
|
|
|
lda $FC
|
|
adc #$01
|
|
sta $FC
|
|
|
|
cmp #$10
|
|
|
|
; Fall through at $F007 to the next control-flow block.
|
|
|
|
;==============================================================================
|
|
; $F007-$F00C: Runtime command-loop termination / continuation
|
|
;
|
|
; Entry is the fall-through from the CMP #$10 at $F005.
|
|
;==============================================================================
|
|
|
|
FinishAudioSequenceScan:
|
|
bcs AudioSequenceUpdateDone
|
|
|
|
jmp UpdateNextAudioSequence
|
|
|
|
|
|
AudioSequenceUpdateDone:
|
|
rts
|
|
|
|
|
|
;==============================================================================
|
|
; $F00D-$F01D: Runtime Command Dispatcher
|
|
;
|
|
; Input:
|
|
; A = command byte >= $F0
|
|
;
|
|
; Uses the low nibble to select a handler through the pointer table at $F01E.
|
|
;==============================================================================
|
|
|
|
DispatchAudioCommand:
|
|
and #$0F
|
|
asl
|
|
tax
|
|
|
|
lda AudioCommandHandlerTable,x
|
|
sta $FE
|
|
|
|
lda AudioCommandHandlerTable+1,x
|
|
sta $FF
|
|
|
|
jmp ($00FE)
|
|
|
|
|
|
;==============================================================================
|
|
; $F01E-$F03D: Runtime Command Handler Table
|
|
;
|
|
; Sixteen 16-bit handlers. Unsupported command values use the no-op handler
|
|
; at $F03E.
|
|
;==============================================================================
|
|
|
|
AudioCommandHandlerTable:
|
|
.word StopAudioSequence ; $F0
|
|
.word AudioCommandF1 ; $F1
|
|
.word AudioCommandF2 ; $F2
|
|
.word AudioCommandF3 ; $F3
|
|
.word AudioCommandF4 ; $F4
|
|
.word AudioCommandF5 ; $F5
|
|
.word AudioCommandF6 ; $F6
|
|
.word StopAudioSequence ; $F7
|
|
.word StopAudioSequence ; $F8
|
|
.word StopAudioSequence ; $F9
|
|
.word StopAudioSequence ; $FA
|
|
.word StopAudioSequence ; $FB
|
|
.word StopAudioSequence ; $FC
|
|
.word StopAudioSequence ; $FD
|
|
.word StopAudioSequence ; $FE
|
|
.word StopAudioSequence ; $FF
|
|
|
|
|
|
;==============================================================================
|
|
; $F03E-$F04A: Runtime command no-op/terminate handler
|
|
;
|
|
; Clears the current source entry and current runtime record, then advances
|
|
; through the common continuation at $EFF8.
|
|
;==============================================================================
|
|
|
|
StopAudioSequence:
|
|
ldy $FC
|
|
|
|
lda #$00
|
|
sta ($F0),y
|
|
|
|
ldy $FD
|
|
sta ($F2),y
|
|
|
|
jmp AdvanceAudioSequence
|
|
|
|
|
|
;==============================================================================
|
|
; $F04B-$F062: Runtime command $F1
|
|
;
|
|
; Fetches one command byte and merges its bits into runtime-record byte 0/1.
|
|
;==============================================================================
|
|
|
|
AudioCommandF1:
|
|
jsr FetchAudioSequenceByte
|
|
pha
|
|
|
|
lda $FD
|
|
clc
|
|
adc #$01
|
|
tay
|
|
|
|
lda ($F2),y
|
|
and #$3F
|
|
sta ($F2),y
|
|
|
|
pla
|
|
ora ($F2),y
|
|
sta ($F2),y
|
|
|
|
jmp DecodeAudioCommand
|
|
|
|
;==============================================================================
|
|
; $F063-$F07A: Runtime command $F2
|
|
;==============================================================================
|
|
|
|
AudioCommandF2:
|
|
jsr FetchAudioSequenceByte
|
|
pha
|
|
|
|
lda $FD
|
|
clc
|
|
adc #$01
|
|
tay
|
|
|
|
lda ($F2),y
|
|
and #$CF
|
|
sta ($F2),y
|
|
|
|
pla
|
|
ora ($F2),y
|
|
sta ($F2),y
|
|
|
|
jmp DecodeAudioCommand
|
|
|
|
;==============================================================================
|
|
; $F07B-$F092: Runtime command $F3
|
|
;==============================================================================
|
|
|
|
AudioCommandF3:
|
|
jsr FetchAudioSequenceByte
|
|
pha
|
|
|
|
lda $FD
|
|
clc
|
|
adc #$01
|
|
tay
|
|
|
|
lda ($F2),y
|
|
and #$F0
|
|
sta ($F2),y
|
|
|
|
pla
|
|
ora ($F2),y
|
|
sta ($F2),y
|
|
|
|
jmp DecodeAudioCommand
|
|
|
|
;==============================================================================
|
|
; $F093-$F0A2: Runtime command $F4
|
|
;==============================================================================
|
|
|
|
AudioCommandF4:
|
|
jsr FetchAudioSequenceByte
|
|
pha
|
|
|
|
lda $FD
|
|
clc
|
|
adc #$02
|
|
tay
|
|
|
|
pla
|
|
sta ($F2),y
|
|
|
|
jmp DecodeAudioCommand
|
|
|
|
;==============================================================================
|
|
; $F0A3-$F0B2: Runtime command $F5
|
|
;==============================================================================
|
|
|
|
AudioCommandF5:
|
|
jsr FetchAudioSequenceByte
|
|
pha
|
|
|
|
lda $FD
|
|
clc
|
|
adc #$04
|
|
tay
|
|
|
|
pla
|
|
sta ($F2),y
|
|
|
|
jmp DecodeAudioCommand
|
|
|
|
;==============================================================================
|
|
; $F0B3-$F0C2: Runtime command $F6
|
|
;==============================================================================
|
|
|
|
AudioCommandF6:
|
|
jsr FetchAudioSequenceByte
|
|
pha
|
|
|
|
lda $FD
|
|
clc
|
|
adc #$01
|
|
tay
|
|
|
|
pla
|
|
sta ($F2),y
|
|
|
|
jmp DecodeAudioCommand
|
|
|
|
;==============================================================================
|
|
; $F0C3-$F0E7: Fetch Runtime Command Byte
|
|
;
|
|
; Uses the 16-bit source pointer stored in runtime-record bytes +5/+6.
|
|
;
|
|
; Output:
|
|
; A = byte read from the command stream
|
|
;
|
|
; Side effect:
|
|
; Advances the source pointer by one and writes it back into bytes +5/+6.
|
|
;==============================================================================
|
|
|
|
FetchAudioSequenceByte:
|
|
lda $FD
|
|
clc
|
|
adc #$05
|
|
tay
|
|
|
|
lda ($F2),y
|
|
sta $FE
|
|
|
|
iny
|
|
|
|
lda ($F2),y
|
|
sta $FF
|
|
|
|
ldx #$00
|
|
|
|
lda ($FE,x)
|
|
pha
|
|
|
|
lda $FE
|
|
|
|
dey
|
|
clc
|
|
adc #$01
|
|
sta ($F2),y
|
|
|
|
lda $FF
|
|
adc #$00
|
|
|
|
iny
|
|
sta ($F2),y
|
|
|
|
pla
|
|
|
|
rts
|
|
|
|
;==============================================================================
|
|
; $F0E8-$F14F: Runtime / Audio Lookup Data
|
|
;
|
|
; Raw data preserved byte-for-byte.
|
|
;
|
|
; The first portion is referenced by UpdateAudioChannels through
|
|
; $F0E8,X / $F0E9,X as paired mask values. Later portions appear to contain
|
|
; additional pointers and command/parameter data.
|
|
;
|
|
; Semantic subdivision is deferred until all consumers are decoded.
|
|
;==============================================================================
|
|
AudioFrequencyLookupTable:
|
|
; $F0E8-$F0F7
|
|
.byte $03,$F9,$03,$C0,$03,$8A,$03,$57
|
|
.byte $03,$27,$02,$FA,$02,$CF,$02,$A7
|
|
|
|
; $F0F8-$F107
|
|
.byte $02,$81,$02,$5D,$02,$3B,$02,$1B
|
|
.byte $02,$F1,$CB,$F3,$14,$F4,$22,$F1
|
|
|
|
; $F108-$F117
|
|
.byte $3C,$F3,$3F,$F4,$50,$F4,$37,$F1
|
|
.byte $E4,$F1,$1D,$F3,$CF,$F1,$62,$F1
|
|
|
|
; $F118-$F127
|
|
.byte $8D,$F1,$B0,$F1,$07,$F2,$7A,$F2
|
|
.byte $61,$F4,$01,$03,$7F,$08,$A2,$0C
|
|
|
|
; $F128-$F137
|
|
.byte $A2,$0C,$A2,$0C,$A2,$0C,$A2,$0C
|
|
.byte $A2,$0C,$A2,$0C,$A2,$0C,$F0,$03
|
|
|
|
; $F138-$F147
|
|
.byte $04,$7F,$08,$33,$01,$23,$01,$03
|
|
.byte $01,$A2,$01,$92,$01,$72,$01,$52
|
|
|
|
; $F148-$F14F
|
|
.byte $01,$32,$01,$22,$01,$02,$01,$A1
|
|
|
|
|
|
|
|
;==============================================================================
|
|
; $F150-$F24F: Runtime / Audio Command Data
|
|
;
|
|
; Raw data preserved byte-for-byte.
|
|
;
|
|
; The region contains strongly patterned pairs and command-like values used
|
|
; by the late-PRG runtime/audio interpreter. Semantic subdivision is deferred
|
|
; until its individual consumers are mapped.
|
|
;==============================================================================
|
|
AudioSequenceData_F150:
|
|
; $F150-$F15F
|
|
.byte $01,$91,$01,$C0,$08,$91,$01,$A1
|
|
.byte $01,$02,$01,$22,$01,$32,$01,$52
|
|
|
|
; $F160-$F16F
|
|
.byte $01,$F0,$01,$96,$7F,$28,$82,$01
|
|
.byte $92,$01,$A2,$01,$B2,$01,$03,$01
|
|
|
|
; $F170-$F17F
|
|
.byte $13,$01,$23,$01,$33,$01,$43,$01
|
|
.byte $53,$01,$33,$01,$23,$01,$13,$01
|
|
|
|
; $F180-$F18F
|
|
.byte $03,$01,$B2,$01,$A2,$01,$92,$01
|
|
.byte $82,$01,$72,$01,$F0,$01,$96,$7F
|
|
|
|
; $F190-$F19F
|
|
.byte $28,$A2,$01,$B2,$01,$03,$01,$13
|
|
.byte $01,$23,$01,$33,$01,$43,$01,$53
|
|
|
|
; $F1A0-$F1AF
|
|
.byte $01,$33,$01,$23,$01,$13,$01,$03
|
|
.byte $01,$B2,$01,$A2,$01,$92,$01,$F0
|
|
|
|
; $F1B0-$F1BF
|
|
.byte $01,$96,$7F,$28,$B2,$01,$03,$01
|
|
.byte $13,$01,$23,$01,$33,$01,$43,$01
|
|
|
|
; $F1C0-$F1CF
|
|
.byte $53,$01,$33,$01,$23,$01,$13,$01
|
|
.byte $03,$01,$B2,$01,$A2,$01,$F0,$02
|
|
|
|
; $F1D0-$F1DF
|
|
.byte $9C,$7F,$28,$31,$01,$71,$01,$A1
|
|
.byte $01,$12,$01,$32,$01,$72,$01,$A2
|
|
|
|
; $F1E0-$F1EF
|
|
.byte $01,$13,$01,$F0,$02,$00,$7F,$10
|
|
.byte $20,$03,$50,$03,$80,$02,$A0,$02
|
|
|
|
; $F1F0-$F1FF
|
|
.byte $21,$02,$51,$02,$81,$01,$A1,$01
|
|
.byte $02,$01,$22,$01,$32,$01,$52,$01
|
|
|
|
; $F200-$F20F
|
|
.byte $F5,$18,$73,$01,$C0,$08,$F0,$01
|
|
.byte $03,$7F,$08,$72,$02,$82,$08,$72
|
|
|
|
; $F210-$F21F
|
|
.byte $02,$82,$08,$72,$02,$82,$08,$42
|
|
.byte $02,$52,$04,$32,$04,$82,$06,$82
|
|
|
|
; $F220-$F22F
|
|
.byte $08,$B2,$02,$03,$10,$C0,$08,$72
|
|
.byte $02,$82,$08,$72,$02,$82,$08,$72
|
|
|
|
; $F230-$F23F
|
|
.byte $02,$82,$08,$42,$02,$52,$04,$32
|
|
.byte $04,$82,$06,$82,$08,$42,$02,$52
|
|
|
|
; $F240-$F24F
|
|
.byte $10,$C0,$08,$72,$02,$82,$08,$72
|
|
.byte $02,$82,$08,$72,$02,$82,$08,$42
|
|
|
|
;==============================================================================
|
|
; $F250-$F34F: Runtime / Audio Command Data
|
|
;
|
|
; Raw data preserved byte-for-byte.
|
|
; Semantic subdivision is deferred until the individual stream consumers are
|
|
; fully mapped.
|
|
;==============================================================================
|
|
|
|
AudioSequenceData_F250:
|
|
|
|
; $F250-$F25F
|
|
.byte $02,$52,$04,$32,$04,$82,$06,$82
|
|
.byte $08,$A2,$02,$B2,$08,$03,$02,$13
|
|
|
|
; $F260-$F26F
|
|
.byte $0A,$13,$02,$23,$0C,$03,$02,$13
|
|
.byte $08,$A2,$02,$B2,$08,$82,$0A,$A2
|
|
|
|
; $F270-$F27F
|
|
.byte $02,$B2,$0A,$72,$02,$82,$10,$C0
|
|
.byte $08,$F0,$02,$81,$7F,$40,$80,$08
|
|
|
|
; $F280-$F28F
|
|
.byte $C0,$06,$80,$04,$C0,$02,$80,$08
|
|
.byte $C0,$06,$80,$04,$C0,$02,$80,$08
|
|
|
|
; $F290-$F29F
|
|
.byte $C0,$06,$80,$04,$C0,$02,$01,$04
|
|
.byte $C0,$01,$11,$04,$C0,$01,$21,$04
|
|
|
|
; $F2A0-$F2AF
|
|
.byte $C0,$01,$31,$04,$C0,$01,$80,$08
|
|
.byte $C0,$06,$80,$04,$C0,$02,$80,$08
|
|
|
|
; $F2B0-$F2BF
|
|
.byte $C0,$06,$80,$04,$C0,$02,$80,$08
|
|
.byte $C0,$06,$80,$04,$C0,$02,$01,$04
|
|
|
|
; $F2C0-$F2CF
|
|
.byte $C0,$01,$11,$04,$C0,$01,$21,$04
|
|
.byte $C0,$01,$31,$04,$C0,$01,$80,$08
|
|
|
|
; $F2D0-$F2DF
|
|
.byte $C0,$06,$80,$04,$C0,$02,$80,$08
|
|
.byte $C0,$06,$80,$04,$C0,$02,$80,$08
|
|
|
|
; $F2E0-$F2EF
|
|
.byte $C0,$06,$80,$04,$C0,$02,$01,$04
|
|
.byte $C0,$01,$11,$04,$C0,$01,$21,$04
|
|
|
|
; $F2F0-$F2FF
|
|
.byte $C0,$01,$31,$04,$C0,$01,$81,$0A
|
|
.byte $31,$04,$C0,$01,$21,$04,$C0,$01
|
|
|
|
; $F300-$F30F
|
|
.byte $11,$04,$C0,$01,$B0,$04,$C0,$01
|
|
.byte $80,$04,$C0,$01,$70,$04,$C0,$01
|
|
|
|
; $F310-$F31F
|
|
.byte $60,$08,$C0,$02,$70,$08,$C0,$02
|
|
.byte $80,$0C,$C0,$06,$F0,$02,$98,$7F
|
|
|
|
; $F320-$F32F
|
|
.byte $28,$33,$01,$23,$01,$13,$01,$03
|
|
.byte $01,$A2,$01,$82,$01,$72,$01,$52
|
|
|
|
; $F330-$F33F
|
|
.byte $01,$32,$01,$12,$01,$A1,$01,$71
|
|
.byte $01,$31,$01,$F0,$01,$42,$7F,$38
|
|
|
|
; $F340-$F34F
|
|
.byte $23,$02,$33,$02,$43,$02,$53,$02
|
|
.byte $43,$02,$33,$02,$23,$02,$13,$02
|
|
|
|
;==============================================================================
|
|
; $F350-$F44F: Runtime / Audio Command Data
|
|
;
|
|
; Raw command/parameter stream preserved byte-for-byte.
|
|
; Semantic subdivision is deferred until all stream consumers are mapped.
|
|
;==============================================================================
|
|
|
|
AudioSequenceData_F350:
|
|
|
|
; $F350-$F35F
|
|
.byte $23,$02,$33,$02,$43,$02,$33,$02
|
|
.byte $23,$02,$13,$02,$03,$02,$13,$02
|
|
|
|
; $F360-$F36F
|
|
.byte $23,$02,$33,$02,$23,$02,$13,$02
|
|
.byte $03,$02,$B2,$02,$03,$02,$13,$02
|
|
|
|
; $F370-$F37F
|
|
.byte $23,$02,$13,$02,$03,$02,$B2,$02
|
|
.byte $A2,$02,$B2,$02,$03,$02,$23,$02
|
|
|
|
; $F380-$F38F
|
|
.byte $03,$02,$B2,$02,$A2,$02,$92,$02
|
|
.byte $A2,$02,$B2,$02,$03,$02,$B2,$02
|
|
|
|
; $F390-$F39F
|
|
.byte $A2,$02,$92,$02,$82,$02,$92,$02
|
|
.byte $A2,$02,$03,$02,$A2,$02,$92,$02
|
|
|
|
; $F3A0-$F3AF
|
|
.byte $82,$02,$F2,$00,$F3,$00,$F5,$18
|
|
.byte $31,$01,$71,$01,$B1,$01,$32,$01
|
|
|
|
; $F3B0-$F3BF
|
|
.byte $72,$01,$B2,$01,$33,$01,$73,$01
|
|
.byte $C0,$02,$31,$01,$71,$01,$B1,$01
|
|
|
|
; $F3C0-$F3CF
|
|
.byte $32,$01,$72,$01,$B2,$01,$33,$01
|
|
.byte $73,$01,$F0,$01,$81,$7F,$40,$31
|
|
|
|
; $F3D0-$F3DF
|
|
.byte $08,$32,$08,$A1,$08,$71,$08,$32
|
|
.byte $07,$A1,$07,$71,$0C,$C0,$06,$41
|
|
|
|
; $F3E0-$F3EF
|
|
.byte $08,$42,$08,$B1,$08,$81,$08,$42
|
|
.byte $07,$B1,$07,$81,$0C,$C0,$06,$31
|
|
|
|
; $F3F0-$F3FF
|
|
.byte $08,$32,$08,$A1,$08,$71,$08,$32
|
|
.byte $07,$A1,$07,$71,$0C,$C0,$06,$61
|
|
|
|
; $F400-$F40F
|
|
.byte $05,$71,$05,$81,$05,$81,$05,$91
|
|
.byte $05,$A1,$05,$A1,$05,$B1,$05,$02
|
|
|
|
; $F410-$F41F
|
|
.byte $05,$32,$0C,$F0,$02,$82,$7F,$40
|
|
.byte $30,$18,$A0,$08,$30,$0E,$A0,$0C
|
|
|
|
; $F420-$F42F
|
|
.byte $C0,$06,$40,$18,$B0,$08,$40,$0E
|
|
.byte $B0,$0C,$C0,$06,$30,$18,$A0,$08
|
|
|
|
; $F430-$F43F
|
|
.byte $30,$0E,$A0,$0C,$C0,$06,$A0,$0F
|
|
.byte $01,$0F,$21,$0F,$31,$0C,$F0,$01
|
|
|
|
; $F440-$F44F
|
|
.byte $9F,$7F,$28,$01,$01,$41,$01,$71
|
|
.byte $01,$A1,$01,$02,$01,$F5,$18,$F0
|
|
|
|
|
|
;==============================================================================
|
|
; $F450-$F49A: Runtime / Audio Command Data
|
|
;
|
|
; Raw command data preserved byte-for-byte.
|
|
;==============================================================================
|
|
|
|
AudioSequenceData_F450:
|
|
|
|
; $F450-$F45F
|
|
.byte $01,$9F,$7F,$28,$02,$01,$A1,$01
|
|
.byte $71,$01,$41,$01,$F5,$18,$01,$01
|
|
|
|
; $F460-$F46F
|
|
.byte $F0,$01,$9F,$7F,$28,$52,$01,$92
|
|
.byte $01,$03,$01,$33,$01,$F5,$18,$53
|
|
|
|
; $F470-$F47F
|
|
.byte $03,$F5,$28,$53,$01,$33,$01,$03
|
|
.byte $01,$92,$01,$F5,$18,$52,$03,$92
|
|
|
|
; $F480-$F48F
|
|
.byte $01,$13,$01,$43,$01,$73,$01,$F5
|
|
.byte $18,$93,$0A,$F5,$28,$93,$01,$73
|
|
|
|
; $F490-$F49A
|
|
.byte $01,$43,$01,$13,$01,$F5,$18,$92
|
|
.byte $03,$F0,$FF
|
|
|
|
;==============================================================================
|
|
; $F49B-$F64F: PRG Padding
|
|
;==============================================================================
|
|
.res $0B5B, $FF
|
|
|
|
|
|
;==============================================================================
|
|
; $FFF6-$FFF9: Final ROM Data
|
|
;
|
|
; Notes:
|
|
; $FFF6/$FFF7 are read directly by DrawMazeNametable:
|
|
;
|
|
; lda $FFF7
|
|
; sta $01
|
|
; lda $FFF6
|
|
; sta $00
|
|
;
|
|
; Therefore the first two bytes form the little-endian value $ECEC.
|
|
;
|
|
; $FFF8/$FFF9 form the little-endian value $C10E.
|
|
;==============================================================================
|
|
|
|
MazeDataPointerBytes:
|
|
.byte $EC,$EC
|
|
.byte $0E,$C1
|
|
|
|
;==============================================================================
|
|
; $FFFA-$FFFF: Interrupt Vectors
|
|
;==============================================================================
|
|
.org $FFFA
|
|
CpuInterruptVectors:
|
|
.word NmiHandler ; NMI
|
|
.word Reset ; Reset
|
|
.word IrqHandler ; IRQ/BRK
|