; 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. VBlank:: push af push bc push de push hl ldh a, [hVBlank] and 7 ld e, a ld d, 0 ld hl, .VBlanks add hl, de add hl, de ld a, [hli] ld h, [hl] ld l, a call _hl_ call GameTimer pop hl pop de pop bc pop af reti .VBlanks: dw VBlank0 ; normal operation dw VBlank1 ; battle transition, battle anims (double speed mode) dw VBlank2 ; link dw VBlank3 ; battle anims (regular speed mode) dw VBlank4 ; printer dw VBlank5 ; credits dw VBlank6 dw VBlank0 ; just in case VBlank0:: ; normal operation ; rng ; scx, scy, wy, wx ; bg map buffer ; palettes ; dma transfer ; bg map ; tiles ; oam ; joypad ; sound ; inc frame counter ld hl, hVBlankCounter inc [hl] ldh a, [hROMBank] ldh [hROMBankBackup], a ; enable window back in case LCD interrupt disabled it mid-frame due to hWindowHUDLY ldh a, [rLCDC] set rLCDC_WINDOW_ENABLE, a ldh [rLCDC], a ld a, [hWindowHUDLY] and a jr z, .next xor a ldh [hWY], a .next ldh a, [hSCX] ldh [rSCX], a ldh a, [hSCY] ldh [rSCY], a ldh a, [hWY] ldh [rWY], a ldh a, [hWX] ldh [rWX], a ; There's only time to call one of these in one vblank. ; Calls are in order of priority. call UpdateBGMapBuffer jr c, .done call UpdatePalsIfCGB jr c, .done call DMATransfer jr c, .done call UpdateBGMap ; These have their own timing checks. call Serve2bppRequest call Serve1bppRequest call AnimateTileset .done ldh a, [hOAMUpdate] and a jr nz, .done_oam call hTransferShadowOAM .done_oam ; vblank-sensitive operations are done xor a ldh [hVBlankOccurred], a ; if hWindowHUDLY is active, enable interrupts so the LCD interrupt can trigger ; while non-vblank-sensitive operations are executed. ldh a, [hWindowHUDLY] and a jr z, .next2 ; enable lcd stat ld a, 1 << LCD_STAT ldh [rIE], a ei .next2 ; advance random variables ldh a, [rDIV] ld b, a ldh a, [hRandomAdd] adc b ldh [hRandomAdd], a ldh a, [rDIV] ld b, a ldh a, [hRandomSub] sbc b ldh [hRandomSub], a ldh a, [hOverworldDelay] and a jr z, .ok dec a ldh [hOverworldDelay], a .ok ldh a, [hTextDelayFrames] and a jr z, .ok2 dec a ldh [hTextDelayFrames], a .ok2 call UpdateJoypad ld a, BANK(_UpdateSound) rst Bankswitch call _UpdateSound ldh a, [hROMBankBackup] rst Bankswitch ldh a, [hWindowHUDLY] and a jr z, .no_window_hud ; interrupts must be enabled in the cycle that rLY becomes [hWindowHUDLY] to prevent flickering ; wait until [hWindowHUDLY] - [rLY] is NOT between 0 and 2 before disabling interrupts .wait_loop ldh a, [rLY] ld b, a ldh a, [hWindowHUDLY] sub b cp 2 + 1 jr c, .wait_loop .no_window_hud ; if hWindowHUDLY is active, only LCD_STAT is enabled. ; if hLCDStatIntRequired changeed during last frame, interrupts to request have changed. ; so, restore normal interrupts: enable ints besides joypad (and maybe lcd stat) and let vblank finish. di ld a, [hLCDStatIntRequired] and a ld a, IE_DEFAULT jr nz, .enable_ints ld a, IE_DEFAULT_WO_LCD_STAT .enable_ints ldh [rIE], a ret VBlank2:: ; sound only ldh a, [hROMBank] ldh [hROMBankBackup], a ld a, BANK(_UpdateSound) rst Bankswitch call _UpdateSound ldh a, [hROMBankBackup] rst Bankswitch xor a ldh [hVBlankOccurred], a ret VBlank1:: ; scx, scy ; palettes ; bg map ; tiles ; oam ; sound / lcd stat ldh a, [hROMBank] ldh [hROMBankBackup], a ldh a, [hSCX] ldh [rSCX], a ldh a, [hSCY] ldh [rSCY], a call UpdateCGBPals jr c, .done call UpdateBGMap call Serve2bppRequest_VBlank call hTransferShadowOAM .done xor a ldh [hVBlankOccurred], a ; get requested ints ldh a, [rIF] ld b, a ; discard requested ints xor a ldh [rIF], a ; enable lcd stat ld a, 1 << LCD_STAT ldh [rIE], a ; rerequest serial int if applicable (still disabled) ; request lcd stat ld a, b and 1 << SERIAL or 1 << LCD_STAT ldh [rIF], a ei ld a, BANK(_UpdateSound) rst Bankswitch call _UpdateSound ldh a, [hROMBankBackup] rst Bankswitch di ; get requested ints ldh a, [rIF] ld b, a ; discard requested ints xor a ldh [rIF], a ; enable ints besides joypad ld a, IE_DEFAULT ldh [rIE], a ; rerequest ints ld a, b ldh [rIF], a ret VBlank3:: ; scx, scy ; palettes ; bg map ; tiles ; oam ; sound / lcd stat ldh a, [hROMBank] ldh [hROMBankBackup], a ldh a, [hSCX] ldh [rSCX], a ldh a, [hSCY] ldh [rSCY], a ldh a, [hCGBPalUpdate] and a call nz, ForceUpdateCGBPals jr c, .done call UpdateBGMap call Serve2bppRequest_VBlank call hTransferShadowOAM .done xor a ldh [hVBlankOccurred], a ldh a, [rIF] push af xor a ldh [rIF], a ld a, 1 << LCD_STAT ldh [rIE], a ldh [rIF], a ei ld a, BANK(_UpdateSound) rst Bankswitch call _UpdateSound ldh a, [hROMBankBackup] rst Bankswitch di ; request lcdstat ldh a, [rIF] ld b, a ; and any other ints pop af or b ld b, a ; reset ints xor a ldh [rIF], a ; enable ints besides joypad ld a, IE_DEFAULT ldh [rIE], a ; request ints ld a, b ldh [rIF], a ret VBlank4:: ; bg map ; tiles ; oam ; joypad ; serial ; sound ldh a, [hROMBank] ldh [hROMBankBackup], a call UpdateBGMap call Serve2bppRequest call hTransferShadowOAM call UpdateJoypad xor a ldh [hVBlankOccurred], a call AskSerial ld a, BANK(_UpdateSound) rst Bankswitch call _UpdateSound ldh a, [hROMBankBackup] rst Bankswitch ret VBlank5:: ; scx ; palettes ; bg map ; tiles ; joypad ; ldh a, [hROMBank] ldh [hROMBankBackup], a ldh a, [hSCX] ldh [rSCX], a call UpdatePalsIfCGB jr c, .done call UpdateBGMap call Serve2bppRequest .done xor a ldh [hVBlankOccurred], a call UpdateJoypad xor a ldh [rIF], a ld a, 1 << LCD_STAT ldh [rIE], a ; request lcd stat ldh [rIF], a ei ld a, BANK(_UpdateSound) rst Bankswitch call _UpdateSound ldh a, [hROMBankBackup] rst Bankswitch di xor a ldh [rIF], a ; enable ints besides joypad ld a, IE_DEFAULT ldh [rIE], a ret VBlank6:: ; palettes ; tiles ; dma transfer ; sound ldh a, [hROMBank] ldh [hROMBankBackup], a ; inc frame counter ld hl, hVBlankCounter inc [hl] call UpdateCGBPals jr c, .done call Serve2bppRequest call Serve1bppRequest call DMATransfer .done xor a ldh [hVBlankOccurred], a ld a, BANK(_UpdateSound) rst Bankswitch call _UpdateSound ldh a, [hROMBankBackup] rst Bankswitch ret