dmgtris/src/state_title.asm

798 lines
14 KiB
NASM

; DMGTRIS
; Copyright (C) 2023 - Randy Thiemann <randy.thiemann@gmail.com>
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <https://www.gnu.org/licenses/>.
IF !DEF(STATE_TITLE_ASM)
DEF STATE_TITLE_ASM EQU 1
INCLUDE "globals.asm"
INCLUDE "res/title_data.inc"
SECTION "Title Variables", WRAM0
wSelected:: ds 1
SECTION "Title Function Trampolines", ROM0
; Trampolines to the banked function.
SwitchToTitle::
ld b, BANK_TITLE
rst RSTSwitchBank
call SwitchToTitleB
rst RSTRestoreBank
jp EventLoopPostHandler
; Banks and jumps to the actual handler.
TitleEventLoopHandler::
ld b, BANK_TITLE
rst RSTSwitchBank
call TitleEventLoopHandlerB
rst RSTRestoreBank
jp EventLoopPostHandler
; Banks and jumps to the actual handler.
TitleVBlankHandler::
ld b, BANK_TITLE
rst RSTSwitchBank
call TitleVBlankHandlerB
rst RSTRestoreBank
jp EventLoop
DrawOption6:
ld b, BANK_OTHER
rst RSTSwitchBank
ldh a, [hStartSpeed]
ld l, a
ldh a, [hStartSpeed+1]
ld h, a
ld a, [hl]
swap a
and a, $0F
ld b, a
ld a, TILE_0
add a, b
ld hl, TITLE_OPTION_6+TITLE_OPTION_OFFSET+2
ld [hl], a
ldh a, [hStartSpeed]
ld l, a
ldh a, [hStartSpeed+1]
ld h, a
ld a, [hl]
and a, $0F
ld b, a
ld a, TILE_0
add a, b
ld hl, TITLE_OPTION_6+TITLE_OPTION_OFFSET+3
ld [hl], a
ldh a, [hStartSpeed]
ld l, a
ldh a, [hStartSpeed+1]
ld h, a
inc hl
ld a, [hl]
swap a
and a, $0F
ld b, a
ld a, TILE_0
add a, b
ld hl, TITLE_OPTION_6+TITLE_OPTION_OFFSET+0
ld [hl], a
ldh a, [hStartSpeed]
ld l, a
ldh a, [hStartSpeed+1]
ld h, a
inc hl
ld a, [hl]
and a, $0F
ld b, a
ld a, TILE_0
add a, b
ld hl, TITLE_OPTION_6+TITLE_OPTION_OFFSET+1
ld [hl], a
jp RSTRestoreBank
SECTION "Title Functions Banked", ROMX, BANK[BANK_TITLE]
SwitchToTitleB:
; Turn the screen off if it's on.
ldh a, [rLCDC]
and LCDCF_ON
jr z, :+ ; Screen is already off.
wait_vram
xor a, a
ldh [rLCDC], a
; Load the gameplay tilemap.
: ld de, sTitleScreenTileMap
ld hl, $9800
ld bc, sTitleScreenTileMapEnd - sTitleScreenTileMap
call UnsafeMemCopy
; Title screen easter egg.
ld a, [wInitialC]
cp a, $14
jr nz, .notsgb
ld de, sEasterS0
ld hl, EASTER_0
ld bc, 5
call UnsafeMemCopy
ld de, sEasterS1
ld hl, EASTER_1
ld bc, 5
call UnsafeMemCopy
jr .oam
.notsgb
ld a, [wInitialA]
cp a, $FF
jr nz, .notmgb
ld de, sEasterM0
ld hl, EASTER_0
ld bc, 5
call UnsafeMemCopy
ld de, sEasterM1
ld hl, EASTER_1
ld bc, 5
call UnsafeMemCopy
jr .oam
.notmgb
ld a, [wInitialA]
cp a, $11
jr nz, .noegg
ld a, [wInitialB]
bit 0, a
jr nz, .agb
ld de, sEasterC0
ld hl, EASTER_0-1
ld bc, 12
call UnsafeMemCopy
ld de, sEasterC1
ld hl, EASTER_1-1
ld bc, 12
call UnsafeMemCopy
jr .oam
.agb
ld de, sEasterA0
ld hl, EASTER_0-1
ld bc, 12
call UnsafeMemCopy
ld de, sEasterA1
ld hl, EASTER_1-1
ld bc, 12
call UnsafeMemCopy
jr .oam
.noegg
; Clear OAM.
.oam
call ClearOAM
call SetNumberSpritePositions
; Set up the palettes.
ld a, PALETTE_INVERTED
set_bg_palette
set_obj0_palette
set_obj1_palette
; GBC init
call GBCTitleInit
; Install the event loop handlers.
ld a, STATE_TITLE
ldh [hGameState], a
xor a, a
ld [wSelected], a
; And turn the LCD back on before we start.
ld a, LCDCF_ON | LCDCF_BGON | LCDCF_BLK01
ldh [rLCDC], a
; Music start
call SFXKill
ld a, MUSIC_MENU
call SFXEnqueue
; Make sure the first game loop starts just like all the future ones.
wait_vblank
wait_vblank_end
ret
; Handles title screen input.
TitleEventLoopHandlerB:
call GBCTitleProcess
; Start game?
.abstart
ldh a, [hStartState]
ld b, a
ldh a, [hAState]
ld c, a
ldh a, [hBState]
or a, b
or a, c
cp a, 1
jr nz, .up
ldh a, [hSelectState]
cp a, 0
jp z, SwitchToGameplay
jp SwitchToGameplayBig
; Change menu selection?
.up
ldh a, [hUpState]
cp a, 1
jr nz, .down
ld a, [wSelected]
cp a, 0
jr z, :+
dec a
ld [wSelected], a
ret
: ld a, TITLE_OPTIONS-1
ld [wSelected], a
ret
.down
ldh a, [hDownState]
cp a, 1
jr nz, .left
ld a, [wSelected]
cp a, TITLE_OPTIONS-1
jr z, :+
inc a
ld [wSelected], a
ret
: xor a, a
ld [wSelected], a
ret
.left
ldh a, [hLeftState]
cp a, 1
jp z, DecrementOption
cp a, 16
jr c, .right
ldh a, [hFrameCtr]
and 3
cp a, 3
jr nz, .right
call DecrementOption
ret
.right
ldh a, [hRightState]
cp a, 1
jp z, IncrementOption
cp a, 16
jr c, .done
ldh a, [hFrameCtr]
and 3
cp a, 3
jr nz, .done
call IncrementOption
.done
ret
; Decrements the currently selected option.
DecrementOption:
.opt0
ld a, [wSelected]
cp a, 0
jr nz, .opt1
ld a, [wSwapABState]
cp a, 0
jr z, :+
dec a
ld [wSwapABState], a
ld [rSwapABState], a
ret
: ld a, BUTTON_MODE_COUNT-1
ld [wSwapABState], a
ld [rSwapABState], a
ret
.opt1
cp a, 1
jr nz, .opt2
ld a, [wRNGModeState]
cp a, 0
jr z, :+
dec a
ld [wRNGModeState], a
ld [rRNGModeState], a
ret
: ld a, RNG_MODE_COUNT-1
ld [wRNGModeState], a
ld [rRNGModeState], a
ret
.opt2
cp a, 2
jr nz, .opt3
ld a, [wRotModeState]
cp a, 0
jr z, :+
dec a
ld [wRotModeState], a
ld [rRotModeState], a
ret
: ld a, ROT_MODE_COUNT-1
ld [wRotModeState], a
ld [rRotModeState], a
ret
.opt3
cp a, 3
jr nz, .opt4
ld a, [wDropModeState]
cp a, 0
jr z, :+
dec a
ld [wDropModeState], a
ld [rDropModeState], a
ret
: ld a, DROP_MODE_COUNT-1
ld [wDropModeState], a
ld [rDropModeState], a
ret
.opt4
cp a, 4
jr nz, .opt5
ld a, [wSpeedCurveState]
cp a, 0
jr z, :+
dec a
ld [wSpeedCurveState], a
ld [rSpeedCurveState], a
call InitSpeedCurve
ret
: ld a, SCURVE_COUNT-1
ld [wSpeedCurveState], a
ld [rSpeedCurveState], a
call InitSpeedCurve
ret
.opt5
cp a, 5
jr nz, .opt6
ld a, [wAlways20GState]
cp a, 0
jr z, :+
dec a
ld [wAlways20GState], a
ld [rAlways20GState], a
ret
: ld a, HIG_MODE_COUNT-1
ld [wAlways20GState], a
ld [rAlways20GState], a
ret
.opt6
jr DecrementLevel
; Decrements start level.
DecrementLevel:
; Decrement
ldh a, [hStartSpeed]
ld l, a
ldh a, [hStartSpeed+1]
ld h, a
ld bc, -SCURVE_ENTRY_SIZE
add hl, bc
ld a, l
ldh [hStartSpeed], a
ld [rSelectedStartLevel], a
ld a, h
ldh [hStartSpeed+1], a
ld [rSelectedStartLevel+1], a
jp CheckLevelRange
; Increments the selected option.
IncrementOption:
.opt0
ld a, [wSelected]
cp a, 0
jr nz, .opt1
ld a, [wSwapABState]
cp a, BUTTON_MODE_COUNT-1
jr z, :+
inc a
ld [wSwapABState], a
ld [rSwapABState], a
ret
: xor a, a
ld [wSwapABState], a
ld [rSwapABState], a
ret
.opt1
cp a, 1
jr nz, .opt2
ld a, [wRNGModeState]
cp a, RNG_MODE_COUNT-1
jr z, :+
inc a
ld [wRNGModeState], a
ld [rRNGModeState], a
ret
: xor a, a
ld [wRNGModeState], a
ld [rRNGModeState], a
ret
.opt2
cp a, 2
jr nz, .opt3
ld a, [wRotModeState]
cp a, ROT_MODE_COUNT-1
jr z, :+
inc a
ld [wRotModeState], a
ld [rRotModeState], a
ret
: xor a, a
ld [wRotModeState], a
ld [rRotModeState], a
ret
.opt3
cp a, 3
jr nz, .opt4
ld a, [wDropModeState]
cp a, DROP_MODE_COUNT-1
jr z, :+
inc a
ld [wDropModeState], a
ld [rDropModeState], a
ret
: xor a, a
ld [wDropModeState], a
ld [rDropModeState], a
ret
.opt4
cp a, 4
jr nz, .opt5
ld a, [wSpeedCurveState]
cp a, SCURVE_COUNT-1
jr z, :+
inc a
ld [wSpeedCurveState], a
ld [rSpeedCurveState], a
call InitSpeedCurve
ret
: xor a, a
ld [wSpeedCurveState], a
ld [rSpeedCurveState], a
call InitSpeedCurve
ret
.opt5
cp a, 5
jr nz, .opt6
ld a, [wAlways20GState]
cp a, HIG_MODE_COUNT-1
jr z, :+
inc a
ld [wAlways20GState], a
ld [rAlways20GState], a
ret
: xor a, a
ld [wAlways20GState], a
ld [rAlways20GState], a
ret
.opt6
jr IncrementLevel
; Increments start level.
IncrementLevel:
; Increment
ldh a, [hStartSpeed]
ld l, a
ldh a, [hStartSpeed+1]
ld h, a
ld bc, SCURVE_ENTRY_SIZE
add hl, bc
ld a, l
ldh [hStartSpeed], a
ld [rSelectedStartLevel], a
ld a, h
ldh [hStartSpeed+1], a
ld [rSelectedStartLevel+1], a
jp CheckLevelRange
; Wipes the start level upon selecting a new speed curve.
InitSpeedCurve:
ld a, [wSpeedCurveState]
call GetStart
ld a, l
ldh [hStartSpeed], a
ld [rSelectedStartLevel], a
ld a, h
ldh [hStartSpeed+1], a
ld [rSelectedStartLevel+1], a
ret
; Gets the end of a speed curve.
GetEnd:
ld a, [wSpeedCurveState]
cp a, SCURVE_DMGT
jr nz, :+
ld bc, sDMGTSpeedCurveEnd
ret
: cp a, SCURVE_TGM1
jr nz, :+
ld bc, sTGM1SpeedCurveEnd
ret
: cp a, SCURVE_TGM3
jr nz, :+
ld bc, sTGM3SpeedCurveEnd
ret
: cp a, SCURVE_DEAT
jr nz, :+
ld bc, sDEATSpeedCurveEnd
ret
: cp a, SCURVE_SHIR
jr nz, :+
ld bc, sSHIRSpeedCurveEnd
ret
: ld bc, sCHILSpeedCurveEnd
ret
; Gets the beginning of a speed curve.
GetStart:
ld a, [wSpeedCurveState]
cp a, SCURVE_DMGT
jr nz, :+
ld hl, sDMGTSpeedCurve
ret
: cp a, SCURVE_TGM1
jr nz, :+
ld hl, sTGM1SpeedCurve
ret
: cp a, SCURVE_TGM3
jr nz, :+
ld hl, sTGM3SpeedCurve
ret
: cp a, SCURVE_DEAT
jr nz, :+
ld hl, sDEATSpeedCurve
ret
: cp a, SCURVE_SHIR
jr nz, :+
ld hl, sSHIRSpeedCurve
ret
: ld hl, sCHILSpeedCurve
ret
; Make sure we don't overflow the level range.
CheckLevelRange:
; At end?
call GetEnd
ldh a, [hStartSpeed]
cp a, c
jr nz, .notatend
ldh a, [hStartSpeed+1]
cp a, b
jr nz, .notatend
call GetStart
ld a, l
ld [rSelectedStartLevel], a
ldh [hStartSpeed], a
ld a, h
ld [rSelectedStartLevel+1], a
ldh [hStartSpeed+1], a
.notatend
ld de, -SCURVE_ENTRY_SIZE
call GetStart
add hl, de
ldh a, [hStartSpeed]
cp a, l
jr nz, .notatstart
ldh a, [hStartSpeed+1]
cp a, h
jr nz, .notatstart
call GetEnd
ld h, b
ld l, c
add hl, de
ld a, l
ld [rSelectedStartLevel], a
ldh [hStartSpeed], a
ld a, h
ld [rSelectedStartLevel+1], a
ldh [hStartSpeed+1], a
.notatstart
ret
; Handles the display of the menu.
TitleVBlankHandlerB:
call ToATTR
ld a, TILE_UNSELECTED
ld hl, TITLE_OPTION_0
ld [hl], a
ld hl, TITLE_OPTION_1
ld [hl], a
ld hl, TITLE_OPTION_2
ld [hl], a
ld hl, TITLE_OPTION_3
ld [hl], a
ld hl, TITLE_OPTION_4
ld [hl], a
ld hl, TITLE_OPTION_5
ld [hl], a
ld hl, TITLE_OPTION_6
ld [hl], a
ld a, [wSelected]
ld hl, TITLE_OPTION_0
cp a, 0
jr z, :+
ld hl, TITLE_OPTION_1
cp a, 1
jr z, :+
ld hl, TITLE_OPTION_2
cp a, 2
jr z, :+
ld hl, TITLE_OPTION_3
cp a, 3
jr z, :+
ld hl, TITLE_OPTION_4
cp a, 4
jr z, :+
ld hl, TITLE_OPTION_5
cp a, 5
jr z, :+
ld hl, TITLE_OPTION_6
: ld a, TILE_SELECTED
ld [hl], a
; Draw option 0.
xor a, a
ld b, a
ld a, [wSwapABState]
sla a
sla a
ld c, a
ld hl, sOption0
add hl, bc
ld d, h
ld e, l
ld hl, TITLE_OPTION_0+TITLE_OPTION_OFFSET
ld bc, 4
call UnsafeMemCopy
; Draw option 1.
xor a, a
ld b, a
ld a, [wRNGModeState]
sla a
sla a
ld c, a
ld hl, sOption1
add hl, bc
ld d, h
ld e, l
ld hl, TITLE_OPTION_1+TITLE_OPTION_OFFSET
ld bc, 4
call UnsafeMemCopy
; Draw option 2.
xor a, a
ld b, a
ld a, [rRotModeState]
sla a
sla a
ld c, a
ld hl, sOption2
add hl, bc
ld d, h
ld e, l
ld hl, TITLE_OPTION_2+TITLE_OPTION_OFFSET
ld bc, 4
call UnsafeMemCopy
; Draw option 3.
xor a, a
ld b, a
ld a, [rDropModeState]
sla a
sla a
ld c, a
ld hl, sOption3
add hl, bc
ld d, h
ld e, l
ld hl, TITLE_OPTION_3+TITLE_OPTION_OFFSET
ld bc, 4
call UnsafeMemCopy
; Draw option 5.
xor a, a
ld b, a
ld a, [wSpeedCurveState]
sla a
sla a
ld c, a
ld hl, sOption4
add hl, bc
ld d, h
ld e, l
ld hl, TITLE_OPTION_4+TITLE_OPTION_OFFSET
ld bc, 4
call UnsafeMemCopy
; Draw option 5.
ld a, [wSpeedCurveState]
cp a, SCURVE_DEAT
jr z, .disabled
cp a, SCURVE_SHIR
jr z, .disabled
xor a, a
ld b, a
ld a, [wAlways20GState]
sla a
sla a
ld c, a
ld hl, sOption5
add hl, bc
ld d, h
ld e, l
ld hl, TITLE_OPTION_5+TITLE_OPTION_OFFSET
ld bc, 4
call UnsafeMemCopy
jr .opt6
.disabled
ld de, sDisabled
ld hl, TITLE_OPTION_5+TITLE_OPTION_OFFSET
ld bc, 4
call UnsafeMemCopy
; Draw option 6.
.opt6
jp DrawOption6
ENDC