diff --git a/main.asm b/main.asm index 1405adac7..d769208d6 100644 --- a/main.asm +++ b/main.asm @@ -58,562 +58,34 @@ SECTION "start",HOME[$150] 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 - -.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 +INCLUDE "vblank.asm" DelayFrame: ; 0x45a -; delay for one frame - ld a, $1 - ld [$cfb3], a ; was H_VBLANKOCCURRED +; Wait for one frame + ld a, 1 + ld [VBlankOccurred], a -; 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] +; 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 - jr nz, .halt\@ ; 0x465 $f8 + jr nz, .halt 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 diff --git a/vblank.asm b/vblank.asm new file mode 100644 index 000000000..78d7151f0 --- /dev/null +++ b/vblank.asm @@ -0,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