mirror of https://github.com/pret/pokecrystal.git
540 lines
7.3 KiB
NASM
540 lines
7.3 KiB
NASM
|
; VBlank is the interrupt responsible for updating VRAM.
|
||
|
|
||
|
; In Pokemon Crystal, VBlank has been hijacked to act as the
|
||
|
; main loop. After time-sensitive graphics operations have been
|
||
|
; performed, joypad input and sound functions are executed.
|
||
|
|
||
|
; This prevents the display and audio output from lagging.
|
||
|
|
||
|
push af
|
||
|
push bc
|
||
|
push de
|
||
|
push hl
|
||
|
|
||
|
; get vblank type
|
||
|
ld a, [$ff9e]
|
||
|
and $7
|
||
|
|
||
|
; get fn pointer
|
||
|
ld e, a
|
||
|
ld d, $0
|
||
|
ld hl, .VBlanks
|
||
|
add hl, de
|
||
|
add hl, de
|
||
|
ld a, [hli]
|
||
|
ld h, [hl]
|
||
|
ld l, a
|
||
|
|
||
|
; down to business
|
||
|
call JpHl
|
||
|
|
||
|
; since this is called once per frame
|
||
|
call GameTimer
|
||
|
|
||
|
pop hl
|
||
|
pop de
|
||
|
pop bc
|
||
|
pop af
|
||
|
reti
|
||
|
; 2a1
|
||
|
|
||
|
.VBlanks ; 2a1
|
||
|
dw VBlank0 ; 0
|
||
|
dw VBlank1 ; 1
|
||
|
dw VBlank2 ; 2
|
||
|
dw VBlank3 ; 3
|
||
|
dw VBlank4 ; 4
|
||
|
dw VBlank5 ; 5
|
||
|
dw VBlank6 ; 6
|
||
|
dw VBlank0 ; 7
|
||
|
; 2b1
|
||
|
|
||
|
|
||
|
VBlank0: ; 2b1
|
||
|
; normal operation
|
||
|
|
||
|
; rng
|
||
|
; scx, scy, wy, wx
|
||
|
; bg map buffer
|
||
|
; palettes
|
||
|
; dma transfer
|
||
|
; bg map
|
||
|
; tiles
|
||
|
; oam
|
||
|
; joypad
|
||
|
; sound
|
||
|
|
||
|
; inc frame counter
|
||
|
ld hl, $ff9b
|
||
|
inc [hl]
|
||
|
|
||
|
; advance rng
|
||
|
ld a, [$ff04] ; divider
|
||
|
ld b, a
|
||
|
ld a, [$ffe1]
|
||
|
adc b
|
||
|
ld [$ffe1], a
|
||
|
|
||
|
ld a, [$ff04] ; divider
|
||
|
ld b, a
|
||
|
ld a, [$ffe2]
|
||
|
sbc b
|
||
|
ld [$ffe2], a
|
||
|
|
||
|
; save bank
|
||
|
ld a, [$ff9d] ; current bank
|
||
|
ld [$ff8a], a
|
||
|
|
||
|
; scroll x
|
||
|
ld a, [$ffcf]
|
||
|
ld [$ff43], a ; scx
|
||
|
; scroll y
|
||
|
ld a, [$ffd0]
|
||
|
ld [$ff42], a ; scy
|
||
|
; window y
|
||
|
ld a, [$ffd2]
|
||
|
ld [$ff4a], a ; wy
|
||
|
; window x + 7
|
||
|
ld a, [$ffd1]
|
||
|
ld [$ff4b], a ; wx
|
||
|
|
||
|
; some time management is in order
|
||
|
; only have time for one of these during vblank
|
||
|
|
||
|
; bg map buffer has priority
|
||
|
call UpdateBGMapBuffer
|
||
|
jr c, .doneframeaction
|
||
|
|
||
|
; then pals
|
||
|
call UpdatePalsIfCGB
|
||
|
jr c, .doneframeaction
|
||
|
|
||
|
; dma transfer
|
||
|
call DMATransfer
|
||
|
jr c, .doneframeaction
|
||
|
|
||
|
; bg map
|
||
|
call UpdateBGMap
|
||
|
|
||
|
; these have their own timing checks
|
||
|
call SafeLoadTiles
|
||
|
call SafeLoadTiles2
|
||
|
call SafeTileAnimation
|
||
|
|
||
|
.doneframeaction
|
||
|
; oam update off?
|
||
|
ld a, [$ffd8]
|
||
|
and a
|
||
|
jr nz, .vblankoccurred
|
||
|
|
||
|
; update oam by dma transfer
|
||
|
call $ff80
|
||
|
; 403f:
|
||
|
; ld a, $c4
|
||
|
; ld [$ff46], a ; oam dma
|
||
|
; ld a, $28
|
||
|
; .loop
|
||
|
; dec a
|
||
|
; jr nz, .loop
|
||
|
; ret
|
||
|
|
||
|
|
||
|
; vblank-sensitive operations are done
|
||
|
|
||
|
.vblankoccurred
|
||
|
; tell other fns vblank happened
|
||
|
xor a
|
||
|
ld [VBlankOccurred], a
|
||
|
|
||
|
; dec $cfb1 until 0
|
||
|
ld a, [$cfb1]
|
||
|
and a
|
||
|
jr z, .textdelay
|
||
|
dec a
|
||
|
ld [$cfb1], a
|
||
|
|
||
|
.textdelay
|
||
|
; dec text delay counter until 0
|
||
|
ld a, [TextDelayFrames]
|
||
|
and a
|
||
|
jr z, .joypad
|
||
|
dec a
|
||
|
ld [TextDelayFrames], a
|
||
|
|
||
|
.joypad
|
||
|
call Joypad
|
||
|
|
||
|
; update sound
|
||
|
ld a, BANK(UpdateSound)
|
||
|
rst Bankswitch ; bankswitch
|
||
|
call UpdateSound
|
||
|
ld a, [$ff8a]
|
||
|
rst Bankswitch ; restore bank
|
||
|
|
||
|
;
|
||
|
ld a, [$ff98]
|
||
|
ld [$ffe3], a
|
||
|
|
||
|
ret
|
||
|
; 325
|
||
|
|
||
|
|
||
|
VBlank2: ; 325
|
||
|
; sound only
|
||
|
|
||
|
; save bank
|
||
|
ld a, [$ff9d]
|
||
|
ld [$ff8a], a
|
||
|
|
||
|
; update sound
|
||
|
ld a, BANK(UpdateSound)
|
||
|
rst Bankswitch ; bankswitch
|
||
|
call UpdateSound
|
||
|
|
||
|
; restore bank
|
||
|
ld a, [$ff8a]
|
||
|
rst Bankswitch
|
||
|
|
||
|
; tell other fns vblank happened
|
||
|
xor a
|
||
|
ld [VBlankOccurred], a
|
||
|
ret
|
||
|
; 337
|
||
|
|
||
|
|
||
|
VBlank1: ; 337
|
||
|
; scx, scy
|
||
|
; palettes
|
||
|
; bg map
|
||
|
; tiles
|
||
|
; oam
|
||
|
; sound / lcd stat
|
||
|
|
||
|
; save bank
|
||
|
ld a, [$ff9d]
|
||
|
ld [$ff8a], a
|
||
|
|
||
|
; scroll x
|
||
|
ld a, [$ffcf]
|
||
|
ld [$ff43], a ; scx
|
||
|
|
||
|
; scroll y
|
||
|
ld a, [$ffd0]
|
||
|
ld [$ff42], a ; scy
|
||
|
|
||
|
; time-sensitive fns
|
||
|
call UpdatePals
|
||
|
jr c, .vblankoccurred
|
||
|
|
||
|
; these have their own timing checks
|
||
|
call UpdateBGMap
|
||
|
call LoadTiles
|
||
|
; update oam by dma transfer
|
||
|
call $ff80
|
||
|
; 403f:
|
||
|
; ld a, $c4
|
||
|
; ld [$ff46], a ; oam dma
|
||
|
; ld a, $28
|
||
|
; .loop
|
||
|
; dec a
|
||
|
; jr nz, .loop
|
||
|
; ret
|
||
|
|
||
|
.vblankoccurred
|
||
|
; tell other fns vblank happened
|
||
|
xor a
|
||
|
ld [VBlankOccurred], a
|
||
|
|
||
|
; get requested ints
|
||
|
ld a, [$ff0f] ; IF
|
||
|
ld b, a
|
||
|
; discard requested ints
|
||
|
xor a
|
||
|
ld [$ff0f], a ; IF
|
||
|
; enable lcd stat
|
||
|
ld a, %10 ; lcd stat
|
||
|
ld [$ffff], a ; IE
|
||
|
; rerequest serial int if applicable (still disabled)
|
||
|
; request lcd stat
|
||
|
ld a, b
|
||
|
and %1000 ; serial
|
||
|
or %10 ; lcd stat
|
||
|
ld [$ff0f], a ; IF
|
||
|
|
||
|
ei
|
||
|
; update sound
|
||
|
ld a, BANK(UpdateSound)
|
||
|
rst Bankswitch ; bankswitch
|
||
|
call UpdateSound
|
||
|
; restore bank
|
||
|
ld a, [$ff8a]
|
||
|
rst Bankswitch
|
||
|
di
|
||
|
|
||
|
; get requested ints
|
||
|
ld a, [$ff0f] ; IF
|
||
|
ld b, a
|
||
|
; discard requested ints
|
||
|
xor a
|
||
|
ld [$ff0f], a ; IF
|
||
|
; enable ints besides joypad
|
||
|
ld a, %1111 ; serial timer lcdstat vblank
|
||
|
ld [$ffff], a ; IE
|
||
|
; rerequest ints
|
||
|
ld a, b
|
||
|
ld [$ff0f], a ; IF
|
||
|
ret
|
||
|
; 37f
|
||
|
|
||
|
|
||
|
UpdatePals: ; 37f
|
||
|
; update pals for either dmg or cgb
|
||
|
|
||
|
; check cgb
|
||
|
ld a, [$ffe6]
|
||
|
and a
|
||
|
jp nz, UpdateCGBPals
|
||
|
|
||
|
; update gb pals
|
||
|
ld a, [$cfc7]
|
||
|
ld [$ff47], a ; BGP
|
||
|
|
||
|
ld a, [$cfc8]
|
||
|
ld [$ff48], a ; OBP0
|
||
|
|
||
|
ld a, [$cfc9]
|
||
|
ld [$ff49], a ; 0BP1
|
||
|
|
||
|
and a
|
||
|
ret
|
||
|
; 396
|
||
|
|
||
|
|
||
|
VBlank3: ; 396
|
||
|
; scx, scy
|
||
|
; palettes
|
||
|
; bg map
|
||
|
; tiles
|
||
|
; oam
|
||
|
; sound / lcd stat
|
||
|
|
||
|
; save bank
|
||
|
ld a, [$ff9d]
|
||
|
ld [$ff8a], a
|
||
|
|
||
|
; scroll x
|
||
|
ld a, [$ffcf]
|
||
|
ld [$ff43], a ; scx
|
||
|
; scroll y
|
||
|
ld a, [$ffd0]
|
||
|
ld [$ff42], a ; scy
|
||
|
|
||
|
; any pals to update?
|
||
|
ld a, [$ffe5]
|
||
|
and a
|
||
|
call nz, ForceUpdateCGBPals
|
||
|
jr c, .vblankoccurred
|
||
|
; else
|
||
|
call UpdateBGMap
|
||
|
call LoadTiles
|
||
|
|
||
|
; update oam by dma transfer
|
||
|
call $ff80
|
||
|
; 403f:
|
||
|
; ld a, $c4 ; Sprites / $100
|
||
|
; ld [$ff46], a ; oam dma
|
||
|
; ld a, $28
|
||
|
; .loop
|
||
|
; dec a
|
||
|
; jr nz, .loop
|
||
|
; ret
|
||
|
|
||
|
.vblankoccurred
|
||
|
; tell other fns vblank happened
|
||
|
xor a
|
||
|
ld [VBlankOccurred], a
|
||
|
|
||
|
; save int flag
|
||
|
ld a, [$ff0f] ; IF
|
||
|
push af
|
||
|
; reset ints
|
||
|
xor a
|
||
|
ld [$ff0f], a ; IF
|
||
|
; force lcdstat int during sound update
|
||
|
ld a, %10 ; lcd stat
|
||
|
ld [$ffff], a ; IE
|
||
|
ld [$ff0f], a ; IF
|
||
|
|
||
|
ei
|
||
|
; update sound
|
||
|
ld a, BANK(UpdateSound)
|
||
|
rst Bankswitch ; bankswitch
|
||
|
call UpdateSound
|
||
|
; restore bank
|
||
|
ld a, [$ff8a]
|
||
|
rst Bankswitch
|
||
|
di
|
||
|
|
||
|
; request lcdstat
|
||
|
ld a, [$ff0f] ; IF
|
||
|
ld b, a
|
||
|
; and any other ints
|
||
|
pop af
|
||
|
or b
|
||
|
ld b, a
|
||
|
; reset ints
|
||
|
xor a
|
||
|
ld [$ff0f], a ; IF
|
||
|
; enable ints besides joypad
|
||
|
ld a, %1111 ; serial timer lcdstat vblank
|
||
|
ld [$ffff], a ; IE
|
||
|
; request ints
|
||
|
ld a, b
|
||
|
ld [$ff0f], a ; IF
|
||
|
ret
|
||
|
; 3df
|
||
|
|
||
|
|
||
|
VBlank4: ; 3df
|
||
|
; bg map
|
||
|
; tiles
|
||
|
; oam
|
||
|
; joypad
|
||
|
; serial
|
||
|
; sound
|
||
|
|
||
|
; save bank
|
||
|
ld a, [$ff9d]
|
||
|
ld [$ff8a], a
|
||
|
|
||
|
call UpdateBGMap
|
||
|
call SafeLoadTiles
|
||
|
|
||
|
; update oam by dma transfer
|
||
|
call $ff80
|
||
|
; 403f:
|
||
|
; ld a, $c4
|
||
|
; ld [$ff46], a ; oam dma
|
||
|
; ld a, $28
|
||
|
; .loop
|
||
|
; dec a
|
||
|
; jr nz, .loop
|
||
|
; ret
|
||
|
|
||
|
; update joypad
|
||
|
call Joypad
|
||
|
|
||
|
; tell other fns vblank happened
|
||
|
xor a
|
||
|
ld [VBlankOccurred], a
|
||
|
|
||
|
; handshake
|
||
|
call AskSerial
|
||
|
|
||
|
; update sound
|
||
|
ld a, BANK(UpdateSound)
|
||
|
rst Bankswitch ; bankswitch
|
||
|
call UpdateSound
|
||
|
; restore bank
|
||
|
ld a, [$ff8a]
|
||
|
rst Bankswitch
|
||
|
ret
|
||
|
; 400
|
||
|
|
||
|
|
||
|
VBlank5: ; 400
|
||
|
; scx
|
||
|
; palettes
|
||
|
; bg map
|
||
|
; tiles
|
||
|
; joypad
|
||
|
;
|
||
|
|
||
|
; save bank
|
||
|
ld a, [$ff9d]
|
||
|
ld [$ff8a], a
|
||
|
|
||
|
; scroll x
|
||
|
ld a, [$ffcf]
|
||
|
ld [$ff43], a ; scx
|
||
|
|
||
|
; if we can update pals, skip this part
|
||
|
call UpdatePalsIfCGB
|
||
|
jr c, .vblankoccurred
|
||
|
|
||
|
call UpdateBGMap
|
||
|
call SafeLoadTiles
|
||
|
|
||
|
.vblankoccurred
|
||
|
; tell other fns vblank happened
|
||
|
xor a
|
||
|
ld [VBlankOccurred], a
|
||
|
|
||
|
; joypad
|
||
|
call Joypad
|
||
|
|
||
|
; discard requested ints
|
||
|
xor a
|
||
|
ld [$ff0f], a ; IF
|
||
|
; enable lcd stat
|
||
|
ld a, %10 ; lcd stat
|
||
|
ld [$ffff], a ; IE
|
||
|
; request lcd stat
|
||
|
ld [$ff0f], a ; IF
|
||
|
|
||
|
ei
|
||
|
; update sound
|
||
|
ld a, BANK(UpdateSound)
|
||
|
rst Bankswitch ; bankswitch
|
||
|
call UpdateSound
|
||
|
; restore bank
|
||
|
ld a, [$ff8a]
|
||
|
rst Bankswitch
|
||
|
di
|
||
|
|
||
|
; discard requested ints
|
||
|
xor a
|
||
|
ld [$ff0f], a ; IF
|
||
|
; enable ints besides joypad
|
||
|
ld a, %1111 ; serial timer lcdstat vblank
|
||
|
ld [$ffff], a ; IE
|
||
|
ret
|
||
|
; 436
|
||
|
|
||
|
|
||
|
VBlank6: ; 436
|
||
|
; palettes
|
||
|
; tiles
|
||
|
; dma transfer
|
||
|
; sound
|
||
|
|
||
|
; save bank
|
||
|
ld a, [$ff9d]
|
||
|
ld [$ff8a], a
|
||
|
|
||
|
; inc frame counter
|
||
|
ld hl, $ff9b
|
||
|
inc [hl]
|
||
|
|
||
|
call UpdateCGBPals
|
||
|
jr c, .vblankoccurred
|
||
|
|
||
|
call SafeLoadTiles
|
||
|
call SafeLoadTiles2
|
||
|
call DMATransfer
|
||
|
|
||
|
.vblankoccurred
|
||
|
; tell other fns vblank happened
|
||
|
xor a
|
||
|
ld [VBlankOccurred], a
|
||
|
|
||
|
; update sound
|
||
|
ld a, BANK(UpdateSound)
|
||
|
rst Bankswitch ; bankswitch
|
||
|
call UpdateSound
|
||
|
; restore bank
|
||
|
ld a, [$ff8a]
|
||
|
rst Bankswitch
|
||
|
ret
|
||
|
; 45a
|