pokered/engine/menus/main_menu.asm
2022-07-10 21:11:03 -04:00

716 lines
14 KiB
NASM

MainMenu:
; Check save file
call InitOptions
xor a
ld [wOptionsInitialized], a
inc a
ld [wSaveFileStatus], a
call CheckForPlayerNameInSRAM
jr nc, .mainMenuLoop
predef LoadSAV
.mainMenuLoop
ld c, 20
call DelayFrames
xor a ; LINK_STATE_NONE
ld [wLinkState], a
ld hl, wPartyAndBillsPCSavedMenuItem
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
ld [wDefaultMap], a
ld hl, wd72e
res 6, [hl]
call ClearScreen
call RunDefaultPaletteCommand
call LoadTextBoxTilePatterns
call LoadFontTilePatterns
ld hl, wd730
set 6, [hl]
ld a, [wSaveFileStatus]
cp 1
jr z, .noSaveFile
; there's a save file
hlcoord 0, 0
ld b, 6
ld c, 13
call TextBoxBorder
hlcoord 2, 2
ld de, ContinueText
call PlaceString
jr .next2
.noSaveFile
hlcoord 0, 0
ld b, 4
ld c, 13
call TextBoxBorder
hlcoord 2, 2
ld de, NewGameText
call PlaceString
.next2
ld hl, wd730
res 6, [hl]
call UpdateSprites
xor a
ld [wCurrentMenuItem], a
ld [wLastMenuItem], a
ld [wMenuJoypadPollCount], a
inc a
ld [wTopMenuItemX], a
inc a
ld [wTopMenuItemY], a
ld a, A_BUTTON | B_BUTTON | START
ld [wMenuWatchedKeys], a
ld a, [wSaveFileStatus]
ld [wMaxMenuItem], a
call HandleMenuInput
bit BIT_B_BUTTON, a
jp nz, DisplayTitleScreen ; if so, go back to the title screen
ld c, 20
call DelayFrames
ld a, [wCurrentMenuItem]
ld b, a
ld a, [wSaveFileStatus]
cp 2
jp z, .skipInc
; If there's no save file, increment the current menu item so that the numbers
; are the same whether or not there's a save file.
inc b
.skipInc
ld a, b
and a
jr z, .choseContinue
cp 1
jp z, StartNewGame
call DisplayOptionMenu
ld a, 1
ld [wOptionsInitialized], a
jp .mainMenuLoop
.choseContinue
call DisplayContinueGameInfo
ld hl, wCurrentMapScriptFlags
set 5, [hl]
.inputLoop
xor a
ldh [hJoyPressed], a
ldh [hJoyReleased], a
ldh [hJoyHeld], a
call Joypad
ldh a, [hJoyHeld]
bit 0, a
jr nz, .pressedA
bit 1, a
jp nz, .mainMenuLoop ; pressed B
jr .inputLoop
.pressedA
call GBPalWhiteOutWithDelay3
call ClearScreen
ld a, PLAYER_DIR_DOWN
ld [wPlayerDirection], a
ld c, 10
call DelayFrames
ld a, [wNumHoFTeams]
and a
jp z, SpecialEnterMap
ld a, [wCurMap] ; map ID
cp HALL_OF_FAME
jp nz, SpecialEnterMap
xor a
ld [wDestinationMap], a
ld hl, wd732
set 2, [hl] ; fly warp or dungeon warp
call SpecialWarpIn
jp SpecialEnterMap
InitOptions:
ld a, TEXT_DELAY_FAST
ld [wLetterPrintingDelayFlags], a
ld a, TEXT_DELAY_MEDIUM
ld [wOptions], a
ret
LinkMenu:
xor a
ld [wLetterPrintingDelayFlags], a
ld hl, wd72e
set 6, [hl]
ld hl, LinkMenuEmptyText
call PrintText
call SaveScreenTilesToBuffer1
ld hl, WhereWouldYouLikeText
call PrintText
hlcoord 5, 5
ld b, $6
ld c, $d
call TextBoxBorder
call UpdateSprites
hlcoord 7, 7
ld de, CableClubOptionsText
call PlaceString
xor a
ld [wUnusedCD37], a
ld [wd72d], a
ld hl, wTopMenuItemY
ld a, $7
ld [hli], a
ld a, $6
ld [hli], a
xor a
ld [hli], a
inc hl
ld a, $2
ld [hli], a
inc a
; ld a, A_BUTTON | B_BUTTON
ld [hli], a ; wMenuWatchedKeys
xor a
ld [hl], a
.waitForInputLoop
call HandleMenuInput
and A_BUTTON | B_BUTTON
add a
add a
ld b, a
ld a, [wCurrentMenuItem]
add b
add $d0
ld [wLinkMenuSelectionSendBuffer], a
ld [wLinkMenuSelectionSendBuffer + 1], a
.exchangeMenuSelectionLoop
call Serial_ExchangeLinkMenuSelection
ld a, [wLinkMenuSelectionReceiveBuffer]
ld b, a
and $f0
cp $d0
jr z, .checkEnemyMenuSelection
ld a, [wLinkMenuSelectionReceiveBuffer + 1]
ld b, a
and $f0
cp $d0
jr nz, .exchangeMenuSelectionLoop
.checkEnemyMenuSelection
ld a, b
and $c ; did the enemy press A or B?
jr nz, .enemyPressedAOrB
; the enemy didn't press A or B
ld a, [wLinkMenuSelectionSendBuffer]
and $c ; did the player press A or B?
jr z, .waitForInputLoop ; if neither the player nor the enemy pressed A or B, try again
jr .doneChoosingMenuSelection ; if the player pressed A or B but the enemy didn't, use the player's selection
.enemyPressedAOrB
ld a, [wLinkMenuSelectionSendBuffer]
and $c ; did the player press A or B?
jr z, .useEnemyMenuSelection ; if the enemy pressed A or B but the player didn't, use the enemy's selection
; the enemy and the player both pressed A or B
; The gameboy that is clocking the connection wins.
ldh a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
jr z, .doneChoosingMenuSelection
.useEnemyMenuSelection
ld a, b
ld [wLinkMenuSelectionSendBuffer], a
and $3
ld [wCurrentMenuItem], a
.doneChoosingMenuSelection
ldh a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
jr nz, .skipStartingTransfer
call DelayFrame
call DelayFrame
ld a, START_TRANSFER_INTERNAL_CLOCK
ldh [rSC], a
.skipStartingTransfer
ld b, " "
ld c, " "
ld d, "▷"
ld a, [wLinkMenuSelectionSendBuffer]
and (B_BUTTON << 2) ; was B button pressed?
jr nz, .updateCursorPosition
; A button was pressed
ld a, [wCurrentMenuItem]
cp $2
jr z, .updateCursorPosition
ld c, d
ld d, b
dec a
jr z, .updateCursorPosition
ld b, c
ld c, d
.updateCursorPosition
ld a, b
ldcoord_a 6, 7
ld a, c
ldcoord_a 6, 9
ld a, d
ldcoord_a 6, 11
ld c, 40
call DelayFrames
call LoadScreenTilesFromBuffer1
ld a, [wLinkMenuSelectionSendBuffer]
and (B_BUTTON << 2) ; was B button pressed?
jr nz, .choseCancel ; cancel if B pressed
ld a, [wCurrentMenuItem]
cp $2
jr z, .choseCancel
xor a
ld [wWalkBikeSurfState], a ; start walking
ld a, [wCurrentMenuItem]
and a
ld a, COLOSSEUM
jr nz, .next
ld a, TRADE_CENTER
.next
ld [wd72d], a
ld hl, PleaseWaitText
call PrintText
ld c, 50
call DelayFrames
ld hl, wd732
res 1, [hl]
ld a, [wDefaultMap]
ld [wDestinationMap], a
call SpecialWarpIn
ld c, 20
call DelayFrames
xor a
ld [wMenuJoypadPollCount], a
ld [wSerialExchangeNybbleSendData], a
inc a ; LINK_STATE_IN_CABLE_CLUB
ld [wLinkState], a
ld [wEnteringCableClub], a
jr SpecialEnterMap
.choseCancel
xor a
ld [wMenuJoypadPollCount], a
vc_hook Wireless_net_stop
call Delay3
call CloseLinkConnection
ld hl, LinkCanceledText
vc_hook Wireless_net_end
call PrintText
ld hl, wd72e
res 6, [hl]
ret
WhereWouldYouLikeText:
text_far _WhereWouldYouLikeText
text_end
PleaseWaitText:
text_far _PleaseWaitText
text_end
LinkCanceledText:
text_far _LinkCanceledText
text_end
StartNewGame:
ld hl, wd732
res 1, [hl]
StartNewGameDebug:
call OakSpeech
ld c, 20
call DelayFrames
; enter map after using a special warp or loading the game from the main menu
SpecialEnterMap::
xor a
ldh [hJoyPressed], a
ldh [hJoyHeld], a
ldh [hJoy5], a
ld [wd72d], a
ld hl, wd732
set 0, [hl] ; count play time
call ResetPlayerSpriteData
ld c, 20
call DelayFrames
ld a, [wEnteringCableClub]
and a
ret nz
jp EnterMap
ContinueText:
db "CONTINUE"
next ""
; fallthrough
NewGameText:
db "NEW GAME"
next "OPTION@"
CableClubOptionsText:
db "TRADE CENTER"
next "COLOSSEUM"
next "CANCEL@"
DisplayContinueGameInfo:
xor a
ldh [hAutoBGTransferEnabled], a
hlcoord 4, 7
ld b, 8
ld c, 14
call TextBoxBorder
hlcoord 5, 9
ld de, SaveScreenInfoText
call PlaceString
hlcoord 12, 9
ld de, wPlayerName
call PlaceString
hlcoord 17, 11
call PrintNumBadges
hlcoord 16, 13
call PrintNumOwnedMons
hlcoord 13, 15
call PrintPlayTime
ld a, 1
ldh [hAutoBGTransferEnabled], a
ld c, 30
jp DelayFrames
PrintSaveScreenText:
xor a
ldh [hAutoBGTransferEnabled], a
hlcoord 4, 0
ld b, $8
ld c, $e
call TextBoxBorder
call LoadTextBoxTilePatterns
call UpdateSprites
hlcoord 5, 2
ld de, SaveScreenInfoText
call PlaceString
hlcoord 12, 2
ld de, wPlayerName
call PlaceString
hlcoord 17, 4
call PrintNumBadges
hlcoord 16, 6
call PrintNumOwnedMons
hlcoord 13, 8
call PrintPlayTime
ld a, $1
ldh [hAutoBGTransferEnabled], a
ld c, 30
jp DelayFrames
PrintNumBadges:
push hl
ld hl, wObtainedBadges
ld b, $1
call CountSetBits
pop hl
ld de, wNumSetBits
lb bc, 1, 2
jp PrintNumber
PrintNumOwnedMons:
push hl
ld hl, wPokedexOwned
ld b, wPokedexOwnedEnd - wPokedexOwned
call CountSetBits
pop hl
ld de, wNumSetBits
lb bc, 1, 3
jp PrintNumber
PrintPlayTime:
ld de, wPlayTimeHours
lb bc, 1, 3
call PrintNumber
ld [hl], $6d
inc hl
ld de, wPlayTimeMinutes
lb bc, LEADING_ZEROES | 1, 2
jp PrintNumber
SaveScreenInfoText:
db "PLAYER"
next "BADGES "
next "#DEX "
next "TIME@"
DisplayOptionMenu:
hlcoord 0, 0
ld b, 3
ld c, 18
call TextBoxBorder
hlcoord 0, 5
ld b, 3
ld c, 18
call TextBoxBorder
hlcoord 0, 10
ld b, 3
ld c, 18
call TextBoxBorder
hlcoord 1, 1
ld de, TextSpeedOptionText
call PlaceString
hlcoord 1, 6
ld de, BattleAnimationOptionText
call PlaceString
hlcoord 1, 11
ld de, BattleStyleOptionText
call PlaceString
hlcoord 2, 16
ld de, OptionMenuCancelText
call PlaceString
xor a
ld [wCurrentMenuItem], a
ld [wLastMenuItem], a
inc a
ld [wLetterPrintingDelayFlags], a
ld [wOptionsCancelCursorX], a
ld a, 3 ; text speed cursor Y coordinate
ld [wTopMenuItemY], a
call SetCursorPositionsFromOptions
ld a, [wOptionsTextSpeedCursorX] ; text speed cursor X coordinate
ld [wTopMenuItemX], a
ld a, $01
ldh [hAutoBGTransferEnabled], a ; enable auto background transfer
call Delay3
.loop
call PlaceMenuCursor
call SetOptionsFromCursorPositions
.getJoypadStateLoop
call JoypadLowSensitivity
ldh a, [hJoy5]
ld b, a
and A_BUTTON | B_BUTTON | START | D_RIGHT | D_LEFT | D_UP | D_DOWN ; any key besides select pressed?
jr z, .getJoypadStateLoop
bit BIT_B_BUTTON, b
jr nz, .exitMenu
bit BIT_START, b
jr nz, .exitMenu
bit BIT_A_BUTTON, b
jr z, .checkDirectionKeys
ld a, [wTopMenuItemY]
cp 16 ; is the cursor on Cancel?
jr nz, .loop
.exitMenu
ld a, SFX_PRESS_AB
call PlaySound
ret
.eraseOldMenuCursor
ld [wTopMenuItemX], a
call EraseMenuCursor
jp .loop
.checkDirectionKeys
ld a, [wTopMenuItemY]
bit BIT_D_DOWN, b
jr nz, .downPressed
bit BIT_D_UP, b
jr nz, .upPressed
cp 8 ; cursor in Battle Animation section?
jr z, .cursorInBattleAnimation
cp 13 ; cursor in Battle Style section?
jr z, .cursorInBattleStyle
cp 16 ; cursor on Cancel?
jr z, .loop
.cursorInTextSpeed
bit BIT_D_LEFT, b
jp nz, .pressedLeftInTextSpeed
jp .pressedRightInTextSpeed
.downPressed
cp 16
ld b, -13
ld hl, wOptionsTextSpeedCursorX
jr z, .updateMenuVariables
ld b, 5
cp 3
inc hl
jr z, .updateMenuVariables
cp 8
inc hl
jr z, .updateMenuVariables
ld b, 3
inc hl
jr .updateMenuVariables
.upPressed
cp 8
ld b, -5
ld hl, wOptionsTextSpeedCursorX
jr z, .updateMenuVariables
cp 13
inc hl
jr z, .updateMenuVariables
cp 16
ld b, -3
inc hl
jr z, .updateMenuVariables
ld b, 13
inc hl
.updateMenuVariables
add b
ld [wTopMenuItemY], a
ld a, [hl]
ld [wTopMenuItemX], a
call PlaceUnfilledArrowMenuCursor
jp .loop
.cursorInBattleAnimation
ld a, [wOptionsBattleAnimCursorX] ; battle animation cursor X coordinate
xor $0b ; toggle between 1 and 10
ld [wOptionsBattleAnimCursorX], a
jp .eraseOldMenuCursor
.cursorInBattleStyle
ld a, [wOptionsBattleStyleCursorX] ; battle style cursor X coordinate
xor $0b ; toggle between 1 and 10
ld [wOptionsBattleStyleCursorX], a
jp .eraseOldMenuCursor
.pressedLeftInTextSpeed
ld a, [wOptionsTextSpeedCursorX] ; text speed cursor X coordinate
cp 1
jr z, .updateTextSpeedXCoord
cp 7
jr nz, .fromSlowToMedium
sub 6
jr .updateTextSpeedXCoord
.fromSlowToMedium
sub 7
jr .updateTextSpeedXCoord
.pressedRightInTextSpeed
ld a, [wOptionsTextSpeedCursorX] ; text speed cursor X coordinate
cp 14
jr z, .updateTextSpeedXCoord
cp 7
jr nz, .fromFastToMedium
add 7
jr .updateTextSpeedXCoord
.fromFastToMedium
add 6
.updateTextSpeedXCoord
ld [wOptionsTextSpeedCursorX], a ; text speed cursor X coordinate
jp .eraseOldMenuCursor
TextSpeedOptionText:
db "TEXT SPEED"
next " FAST MEDIUM SLOW@"
BattleAnimationOptionText:
db "BATTLE ANIMATION"
next " ON OFF@"
BattleStyleOptionText:
db "BATTLE STYLE"
next " SHIFT SET@"
OptionMenuCancelText:
db "CANCEL@"
; sets the options variable according to the current placement of the menu cursors in the options menu
SetOptionsFromCursorPositions:
ld hl, TextSpeedOptionData
ld a, [wOptionsTextSpeedCursorX] ; text speed cursor X coordinate
ld c, a
.loop
ld a, [hli]
cp c
jr z, .textSpeedMatchFound
inc hl
jr .loop
.textSpeedMatchFound
ld a, [hl]
ld d, a
ld a, [wOptionsBattleAnimCursorX] ; battle animation cursor X coordinate
dec a
jr z, .battleAnimationOn
.battleAnimationOff
set 7, d
jr .checkBattleStyle
.battleAnimationOn
res 7, d
.checkBattleStyle
ld a, [wOptionsBattleStyleCursorX] ; battle style cursor X coordinate
dec a
jr z, .battleStyleShift
.battleStyleSet
set 6, d
jr .storeOptions
.battleStyleShift
res 6, d
.storeOptions
ld a, d
ld [wOptions], a
ret
; reads the options variable and places menu cursors in the correct positions within the options menu
SetCursorPositionsFromOptions:
ld hl, TextSpeedOptionData + 1
ld a, [wOptions]
ld c, a
and $3f
push bc
ld de, 2
call IsInArray
pop bc
dec hl
ld a, [hl]
ld [wOptionsTextSpeedCursorX], a ; text speed cursor X coordinate
hlcoord 0, 3
call .placeUnfilledRightArrow
sla c
ld a, 1 ; On
jr nc, .storeBattleAnimationCursorX
ld a, 10 ; Off
.storeBattleAnimationCursorX
ld [wOptionsBattleAnimCursorX], a ; battle animation cursor X coordinate
hlcoord 0, 8
call .placeUnfilledRightArrow
sla c
ld a, 1
jr nc, .storeBattleStyleCursorX
ld a, 10
.storeBattleStyleCursorX
ld [wOptionsBattleStyleCursorX], a ; battle style cursor X coordinate
hlcoord 0, 13
call .placeUnfilledRightArrow
; cursor in front of Cancel
hlcoord 0, 16
ld a, 1
.placeUnfilledRightArrow
ld e, a
ld d, 0
add hl, de
ld [hl], "▷"
ret
; table that indicates how the 3 text speed options affect frame delays
; Format:
; 00: X coordinate of menu cursor
; 01: delay after printing a letter (in frames)
TextSpeedOptionData:
db 14, TEXT_DELAY_SLOW
db 7, TEXT_DELAY_MEDIUM
db 1, TEXT_DELAY_FAST
db 7, -1 ; end (default X coordinate)
CheckForPlayerNameInSRAM:
; Check if the player name data in SRAM has a string terminator character
; (indicating that a name may have been saved there) and return whether it does
; in carry.
ld a, SRAM_ENABLE
ld [MBC1SRamEnable], a
ld a, $1
ld [MBC1SRamBankingMode], a
ld [MBC1SRamBank], a
ld b, NAME_LENGTH
ld hl, sPlayerName
.loop
ld a, [hli]
cp "@"
jr z, .found
dec b
jr nz, .loop
; not found
xor a
ld [MBC1SRamEnable], a
ld [MBC1SRamBankingMode], a
and a
ret
.found
xor a
ld [MBC1SRamEnable], a
ld [MBC1SRamBankingMode], a
scf
ret