ref: 8902050000c9975a5b71e776ce810bf945cab2ea
parent: a058572fd568a75664783181a80af3ebea235e36
author: yenatch <[email protected]>
date: Tue Feb 5 10:33:57 EST 2013
Move VBlank function to a file
--- a/main.asm
+++ b/main.asm
@@ -58,561 +58,33 @@
INCBIN "baserom.gbc",$150,$283 - $150
+
VBlank: ; 283
- 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
+INCLUDE "vblank.asm"
-.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
+DelayFrame: ; 0x45a
+; Wait for one frame
+ ld a, 1
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]
+; Wait for the next VBlank, halting to conserve battery
+.halt
+ halt ; rgbasm adds a nop after this instruction by default
+ ld a, [VBlankOccurred]
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
+ jr nz, .halt
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
-
-
-DelayFrame: ; 0x45a
-; delay for one frame
- ld a, $1
- ld [$cfb3], a ; was H_VBLANKOCCURRED
-
-; wait for the next Vblank, halting to conserve battery
-.halt\@
- db $76, $00 ; XXX this is a hack--rgbasm adds a nop after this instr even when ints are enabled
- ld a, [$cfb3]
- and a
- jr nz, .halt\@ ; 0x465 $f8
- ret
; 0x468
DelayFrames: ; 0x468
-; wait n frames, where n is the value in c
+; Wait c frames
call DelayFrame
dec c
jr nz, DelayFrames
ret
; 0x46f
+
RTC: ; 46f
; update time and time-sensitive palettes
--- /dev/null
+++ b/vblank.asm
@@ -1,0 +1,539 @@
+; 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