Implement the basics of the window HUD functionality (#15)

This commit is contained in:
xCrystal 2023-08-27 19:18:52 +02:00
parent 4ee4655e72
commit 6e49bb9893
6 changed files with 118 additions and 15 deletions

View File

@ -126,6 +126,8 @@ EnterMap:
ld [wPoisonStepCount], a
.dontresetpoison
call EnableOverworldWindowHUD
xor a ; end map entry
ldh [hMapEntryMethod], a
ld a, MAPSTATUS_HANDLE

View File

@ -1165,6 +1165,7 @@ Script_loadtrainer:
ret
Script_startbattle:
call DisableWindowHUD
call BufferScreen
predef StartBattle
ld a, [wBattleResult]

View File

@ -2,9 +2,12 @@
LCD::
push af
; hLCDCPointer is used in battle transition, battle anims, and movies (crystal intro, credits, etc.)
; uses rSTAT_INT_HBLANK and doesn't overlap with hWindowHUD.
ldh a, [hLCDCPointer]
and a
jr z, .done
jr z, .next
; At this point it's assumed we're in BANK(wLYOverrides)!
push bc
@ -19,6 +22,21 @@ LCD::
ldh [c], a
pop bc
.next
; hWindowHUD uses rSTAT_INT_LYC
ldh a, [hWindowHUD]
and a
jr z, .done
; disable window for the remainder of the frame
.wait_hblank
ldh a, [rSTAT]
and rSTAT_STATUS_FLAGS
jr nz, .wait_hblank
ldh a, [rLCDC]
res rLCDC_WINDOW_ENABLE, a
ldh [rLCDC], a
.done
pop af
reti

View File

@ -62,22 +62,22 @@ VBlank0::
ld hl, hVBlankCounter
inc [hl]
; 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, [hROMBank]
ldh [hROMBankBackup], a
; enable window back in case LCD interrupt disabled it mid-frame due to hWindowHUD
ldh a, [rLCDC]
set rLCDC_WINDOW_ENABLE, a
ldh [rLCDC], a
ld a, [hWindowHUD]
and a
jr z, .next
xor a
ldh [hWY], a
.next
ldh a, [hSCX]
ldh [rSCX], a
ldh a, [hSCY]
@ -117,6 +117,30 @@ VBlank0::
xor a
ld [wVBlankOccurred], a
; if hWindowHUD is active, enable interrupts so the LCD interrupt can trigger
ldh a, [hWindowHUD]
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
ld a, [wOverworldDelay]
and a
jr z, .ok
@ -139,6 +163,26 @@ VBlank0::
ldh a, [hROMBankBackup]
rst Bankswitch
; if hWindowHUD is not active, we're done
ldh a, [hWindowHUD]
and a
ret z
; interrupts must be enabled in the cycle that rLY becomes [hWindowHUD] to prevent flickering
; wait until [hWindowHUD] - [rLY] is NOT between 0 and 2 before disabling interrupts
.wait_loop
ldh a, [rLY]
ld b, a
ldh a, [hWindowHUD]
sub b
cp 2 + 1
jr c, .wait_loop
; restore normal interrupts: enable ints besides joypad and let vblank finish
di
ld a, IE_DEFAULT
ldh [rIE], a
ret
VBlank2::

View File

@ -108,3 +108,36 @@ SafeUpdateSprites::
pop af
ldh [hOAMUpdate], a
ret
OVERWORLD_HUD_HEIGHT EQU 8
EnableOverworldWindowHUD::
ld a, OVERWORLD_HUD_HEIGHT - 1
; fallthrough
EnableWindowHUD:
ldh [hWindowHUD], a
; configure LCD interrupt
ldh [rLYC], a
ld a, 1 << rSTAT_INT_LYC ; LYC=LC
ldh [rSTAT], a
; make window hidden this frame to prevent graphical glitches
ld a, $90
ldh [hWY], a
ret
DisableWindowHUD::
xor a
ldh [hWindowHUD], a
; configure LCD interrupt
xor a
ldh [rLYC], a
ld a, 1 << rSTAT_INT_HBLANK ; hblank (default)
ldh [rSTAT], a
; leave window in default state (enabled and hidden)
ld a, $90
ldh [hWY], a
ldh a, [rLCDC]
set rLCDC_WINDOW_ENABLE, a
ldh [rLCDC], a
ret

View File

@ -145,5 +145,10 @@ hDMATransfer:: db
hSystemBooted:: db
if DEF(_DEBUG)
hDebugRoomMenuPage::
hDebugRoomMenuPage:: db
endc
hWindowHUD::
; Window HUD is enabled when non-0.
; Its value indicates the last scanline that the window spans from the top.
db