diff options
Diffstat (limited to 'engine/menus')
-rw-r--r-- | engine/menus/empty_sram.asm | 19 | ||||
-rw-r--r-- | engine/menus/intro_menu.asm | 1133 | ||||
-rw-r--r-- | engine/menus/main_menu.asm | 253 | ||||
-rw-r--r-- | engine/menus/menu.asm | 675 | ||||
-rw-r--r-- | engine/menus/menu_2.asm | 298 | ||||
-rw-r--r-- | engine/menus/naming_screen.asm | 1377 | ||||
-rw-r--r-- | engine/menus/save.asm | 1092 | ||||
-rw-r--r-- | engine/menus/scrolling_menu.asm | 519 | ||||
-rw-r--r-- | engine/menus/start_menu.asm | 541 | ||||
-rw-r--r-- | engine/menus/trainer_card.asm | 624 |
10 files changed, 6531 insertions, 0 deletions
diff --git a/engine/menus/empty_sram.asm b/engine/menus/empty_sram.asm new file mode 100644 index 00000000..264f0813 --- /dev/null +++ b/engine/menus/empty_sram.asm @@ -0,0 +1,19 @@ +EmptyAllSRAMBanks: + ld a, 0 + call .EmptyBank + ld a, 1 + call .EmptyBank + ld a, 2 + call .EmptyBank + ld a, 3 + call .EmptyBank + ret + +.EmptyBank: + call OpenSRAM + ld hl, SRAM_Begin + ld bc, SRAM_End - SRAM_Begin + xor a + call ByteFill + call CloseSRAM + ret diff --git a/engine/menus/intro_menu.asm b/engine/menus/intro_menu.asm new file mode 100644 index 00000000..c85b56f6 --- /dev/null +++ b/engine/menus/intro_menu.asm @@ -0,0 +1,1133 @@ +MainMenu_NewGame: +NewGame: + xor a + ld [wDebugFlags], a + call ResetWRAM + call ClearTilemapEtc + call OakSpeech + call InitializeWorld + + ld a, SPAWN_HOME + ld [wDefaultSpawnpoint], a + + ld a, MAPSETUP_WARP + ldh [hMapEntryMethod], a + jp FinishContinueFunction + +ResetWRAM: + xor a + ldh [hBGMapMode], a + call _ResetWRAM + ret + +_ResetWRAM: + ld hl, wVirtualOAM + ld bc, wOptions - wVirtualOAM + xor a + call ByteFill + + ld hl, wGameData + ld bc, wGameDataEnd - wGameData + xor a + call ByteFill + + ldh a, [rLY] + ldh [hUnusedBackup], a + call DelayFrame + ldh a, [hRandomSub] + ld [wPlayerID], a + + ldh a, [rLY] + ldh [hUnusedBackup], a + call DelayFrame + ldh a, [hRandomAdd] + ld [wPlayerID + 1], a + + ld hl, wPartyCount + call .InitList + + xor a + ld [wCurBox], a + ld [wSavedAtLeastOnce], a + + call SetDefaultBoxNames + + ld a, BANK(sBoxCount) + call OpenSRAM + ld hl, sBoxCount + call .InitList + call CloseSRAM + + ld hl, wNumItems + call .InitList + + ld hl, wNumKeyItems + call .InitList + + ld hl, wNumBalls + call .InitList + + ld hl, wNumPCItems + call .InitList + + xor a + ld [wRoamMon1Species], a + ld [wRoamMon2Species], a + ld [wRoamMon3Species], a + ld a, -1 + ld [wRoamMon1MapGroup], a + ld [wRoamMon2MapGroup], a + ld [wRoamMon3MapGroup], a + ld [wRoamMon1MapNumber], a + ld [wRoamMon2MapNumber], a + ld [wRoamMon3MapNumber], a + + ld a, BANK(sMysteryGiftItem) + call OpenSRAM + ld hl, sMysteryGiftItem + xor a + ld [hli], a + dec a + ld [hl], a + call CloseSRAM + + call LoadOrRegenerateLuckyIDNumber + call InitializeMagikarpHouse + + xor a + ld [wMonType], a + + ld [wJohtoBadges], a + ld [wKantoBadges], a + + ld [wCoins], a + ld [wCoins + 1], a + +if START_MONEY >= $10000 + ld a, HIGH(START_MONEY >> 8) +endc + ld [wMoney], a + ld a, HIGH(START_MONEY) ; mid + ld [wMoney + 1], a + ld a, LOW(START_MONEY) + ld [wMoney + 2], a + + xor a + ld [wWhichMomItem], a + + ld hl, wMomItemTriggerBalance + ld [hl], HIGH(MOM_MONEY >> 8) + inc hl + ld [hl], HIGH(MOM_MONEY) ; mid + inc hl + ld [hl], LOW(MOM_MONEY) + + call InitializeNPCNames + + farcall InitDecorations + + farcall DeletePartyMonMail + + call ResetGameTime + ret + +.InitList: +; Loads 0 in the count and -1 in the first item or mon slot. + xor a + ld [hli], a + dec a + ld [hl], a + ret + +SetDefaultBoxNames: + ld hl, wBoxNames + ld c, 0 +.loop + push hl + ld de, .Box + call CopyName2 + dec hl + ld a, c + inc a + cp 10 + jr c, .less + sub 10 + ld [hl], "1" + inc hl + +.less + add "0" + ld [hli], a + ld [hl], "@" + pop hl + ld de, 9 + add hl, de + inc c + ld a, c + cp NUM_BOXES + jr c, .loop + ret + +.Box: + db "BOX@" + +InitializeMagikarpHouse: + ld hl, wBestMagikarpLengthFeet + ld a, $3 + ld [hli], a + ld a, $6 + ld [hli], a + ld de, .Ralph + call CopyName2 + ret + +.Ralph: + db "RALPH@" + +InitializeNPCNames: + ld hl, .Rival + ld de, wRivalName + call .Copy + + ld hl, .Mom + ld de, wMomsName + call .Copy + + ld hl, .Red + ld de, wRedsName + call .Copy + + ld hl, .Green + ld de, wGreensName + +.Copy: + ld bc, NAME_LENGTH + call CopyBytes + ret + +.Rival: db "???@" +.Red: db "RED@" +.Green: db "GREEN@" +.Mom: db "MOM@" + +InitializeWorld: + call ShrinkPlayer + farcall SpawnPlayer + farcall _InitializeStartDay + ret + +LoadOrRegenerateLuckyIDNumber: + ld a, BANK(sLuckyIDNumber) + call OpenSRAM + ld a, [wCurDay] + inc a + ld b, a + ld a, [sLuckyNumberDay] + cp b + ld a, [sLuckyIDNumber + 1] + ld c, a + ld a, [sLuckyIDNumber] + jr z, .skip + ld a, b + ld [sLuckyNumberDay], a + call Random + ld c, a + call Random + +.skip + ld [wLuckyIDNumber], a + ld [sLuckyIDNumber], a + ld a, c + ld [wLuckyIDNumber + 1], a + ld [sLuckyIDNumber + 1], a + jp CloseSRAM + +MainMenu_Continue: +Continue: + farcall TryLoadSaveFile + jr c, .FailToLoad + call LoadStandardMenuHeader + call DisplaySaveInfoOnContinue + ld a, $1 + ldh [hBGMapMode], a + ld c, 20 + call DelayFrames + call ConfirmContinue + jr nc, .Check1Pass + call CloseWindow + jr .FailToLoad + +.Check1Pass: + call Continue_CheckRTC_RestartClock + jr nc, .Check2Pass + call CloseWindow + jr .FailToLoad + +.Check2Pass: + ld a, $8 + ld [wMusicFade], a + ld a, LOW(MUSIC_NONE) + ld [wMusicFadeID], a + ld a, HIGH(MUSIC_NONE) + ld [wMusicFadeID + 1], a + call ClearBGPalettes + call CloseWindow + call ClearTilemap + ld c, 20 + call DelayFrames + farcall JumpRoamMons + farcall MysteryGift_CopyReceivedDecosToPC ; Mystery Gift + farcall ClockContinue + ld a, [wSpawnAfterChampion] + cp SPAWN_LANCE + jr z, .SpawnAfterE4 + ld a, MAPSETUP_CONTINUE + ldh [hMapEntryMethod], a + jp FinishContinueFunction + +.FailToLoad: + ret + +.SpawnAfterE4: + ld a, SPAWN_NEW_BARK + ld [wDefaultSpawnpoint], a + call PostCreditsSpawn + jp FinishContinueFunction + +SpawnAfterRed: + ld a, SPAWN_MT_SILVER + ld [wDefaultSpawnpoint], a + +PostCreditsSpawn: + xor a + ld [wSpawnAfterChampion], a + ld a, MAPSETUP_WARP + ldh [hMapEntryMethod], a + ret + +ConfirmContinue: +.loop + call DelayFrame + call GetJoypad + ld hl, hJoyPressed + bit A_BUTTON_F, [hl] + jr nz, .PressA + bit B_BUTTON_F, [hl] + jr z, .loop + scf + ret + +.PressA: + ret + +Continue_CheckRTC_RestartClock: + call CheckRTCStatus + and %10000000 ; Day count exceeded 16383 + jr z, .pass + farcall RestartClock + ld a, c + and a + jr z, .pass + scf + ret + +.pass + xor a + ret + +FinishContinueFunction: +.loop + xor a + ld [wDontPlayMapMusicOnReload], a + ld hl, wGameTimerPause + set GAMETIMERPAUSE_TIMER_PAUSED_F, [hl] + farcall OverworldLoop + ld a, [wSpawnAfterChampion] + cp SPAWN_RED + jr z, .AfterRed + jp Reset + +.AfterRed: + call SpawnAfterRed + jr .loop + +DisplaySaveInfoOnContinue: + call CheckRTCStatus + and %10000000 + jr z, .clock_ok + lb de, 4, 8 + call DisplayContinueDataWithRTCError + ret + +.clock_ok + lb de, 4, 8 + call DisplayNormalContinueData + ret + +DisplayNormalContinueData: + call Continue_LoadMenuHeader + call Continue_DisplayBadgesDex + call Continue_PrintGameTime + call LoadFontsExtra + call UpdateSprites + ret + +DisplayContinueDataWithRTCError: + call Continue_LoadMenuHeader + call Continue_DisplayBadgesDex + call Continue_UnknownGameTime + call LoadFontsExtra + call UpdateSprites + ret + +Continue_LoadMenuHeader: + xor a + ldh [hBGMapMode], a + ld hl, .MenuHeader_Dex + ld a, [wStatusFlags] + bit STATUSFLAGS_POKEDEX_F, a + jr nz, .show_menu + ld hl, .MenuHeader_NoDex + +.show_menu + call _OffsetMenuHeader + call MenuBox + call PlaceVerticalMenuItems + ret + +.MenuHeader_Dex: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 0, 15, 9 + dw .MenuData_Dex + db 1 ; default option + +.MenuData_Dex: + db 0 ; flags + db 4 ; items + db "PLAYER <PLAYER>@" + db "BADGES@" + db "#DEX@" + db "TIME@" + +.MenuHeader_NoDex: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 0, 15, 9 + dw .MenuData_NoDex + db 1 ; default option + +.MenuData_NoDex: + db 0 ; flags + db 4 ; items + db "PLAYER <PLAYER>@" + db "BADGES@" + db " @" + db "TIME@" + +Continue_DisplayBadgesDex: + call MenuBoxCoord2Tile + push hl + decoord 13, 4, 0 + add hl, de + call Continue_DisplayBadgeCount + pop hl + push hl + decoord 12, 6, 0 + add hl, de + call Continue_DisplayPokedexNumCaught + pop hl + ret + +Continue_PrintGameTime: + decoord 9, 8, 0 + add hl, de + call Continue_DisplayGameTime + ret + +Continue_UnknownGameTime: + decoord 9, 8, 0 + add hl, de + ld de, .three_question_marks + call PlaceString + ret + +.three_question_marks + db " ???@" + +Continue_DisplayBadgeCount: + push hl + ld hl, wJohtoBadges + ld b, 2 + call CountSetBits + pop hl + ld de, wNumSetBits + lb bc, 1, 2 + jp PrintNum + +Continue_DisplayPokedexNumCaught: + ld a, [wStatusFlags] + bit STATUSFLAGS_POKEDEX_F, a + ret z + push hl + ld hl, wPokedexCaught +if NUM_POKEMON % 8 + ld b, NUM_POKEMON / 8 + 1 +else + ld b, NUM_POKEMON / 8 +endc + call CountSetBits + pop hl + ld de, wNumSetBits + lb bc, 1, 3 + jp PrintNum + +Continue_DisplayGameTime: + ld de, wGameTimeHours + lb bc, 2, 3 + call PrintNum + ld [hl], "<COLON>" + inc hl + ld de, wGameTimeMinutes + lb bc, PRINTNUM_LEADINGZEROS | 1, 2 + jp PrintNum + +OakSpeech: + farcall InitClock + call RotateFourPalettesLeft + call ClearTilemap + + ld de, MUSIC_ROUTE_30 + call PlayMusic + + call RotateFourPalettesRight + call RotateThreePalettesRight + xor a + ld [wCurPartySpecies], a + ld a, POKEMON_PROF + ld [wTrainerClass], a + call Intro_PrepTrainerPic + + ld b, SCGB_TRAINER_OR_MON_FRONTPIC_PALS + call GetSGBLayout + call Intro_RotatePalettesLeftFrontpic + + ld hl, OakText1 + call PrintText + call RotateThreePalettesRight + call ClearTilemap + + ld a, MARILL + ld [wCurSpecies], a + ld [wCurPartySpecies], a + call GetBaseData + + hlcoord 6, 4 + hlcoord 6, 4 ; TriHard + call PrepMonFrontpic + + xor a + ld [wTempMonDVs], a + ld [wTempMonDVs + 1], a + + ld b, SCGB_TRAINER_OR_MON_FRONTPIC_PALS + call GetSGBLayout + call Intro_WipeInFrontpic + + ld hl, OakText2 + call PrintText + ld hl, OakText4 + call PrintText + call RotateThreePalettesRight + call ClearTilemap + + xor a + ld [wCurPartySpecies], a + ld a, POKEMON_PROF + ld [wTrainerClass], a + call Intro_PrepTrainerPic + + ld b, SCGB_TRAINER_OR_MON_FRONTPIC_PALS + call GetSGBLayout + call Intro_RotatePalettesLeftFrontpic + + ld hl, OakText5 + call PrintText + call RotateThreePalettesRight + call ClearTilemap + + xor a + ld [wCurPartySpecies], a + ld a, CAL + ld [wTrainerClass], a + call Intro_PrepTrainerPic + + ld b, SCGB_TRAINER_OR_MON_FRONTPIC_PALS + call GetSGBLayout + call Intro_RotatePalettesLeftFrontpic + + ld hl, OakText6 + call PrintText + call NamePlayer + ld hl, OakText7 + call PrintText + ret + +OakText1: + text_far _OakText1 + text_end + +OakText2: + text_far _OakText2 + text_asm + ld a, MARILL + call PlayMonCry + call WaitSFX + ld hl, OakText3 + ret + +OakText3: + text_far _OakText3 + text_end + +OakText4: + text_far _OakText4 + text_end + +OakText5: + text_far _OakText5 + text_end + +OakText6: + text_far _OakText6 + text_end + +OakText7: + text_far _OakText7 + text_end + +NamePlayer: + call MovePlayerPicRight + ld hl, NameMenuHeader + call ShowPlayerNamingChoices + ld a, [wMenuCursorY] + dec a + jr z, .NewName + ld de, wPlayerName + call StorePlayerName + farcall ApplyMonOrTrainerPals + call MovePlayerPicLeft + ret + +.NewName: + ld b, NAME_PLAYER + ld de, wPlayerName + farcall NamingScreen + + call RotateThreePalettesRight + call ClearTilemap + + call LoadFontsExtra + call WaitBGMap + + xor a + ld [wCurPartySpecies], a + ld a, CAL + ld [wTrainerClass], a + call Intro_PrepTrainerPic + + ld b, SCGB_TRAINER_OR_MON_FRONTPIC_PALS + call GetSGBLayout + call RotateThreePalettesLeft + + ld hl, wPlayerName + ld de, PlayerNameArray + call InitName + ret + +INCLUDE "data/player_names.asm" + +ShowPlayerNamingChoices: + call LoadMenuHeader + call VerticalMenu + ld a, [wMenuCursorY] + dec a + call CopyNameFromMenu + call CloseWindow + ret + +StorePlayerName: + ld hl, wStringBuffer2 + ld bc, NAME_LENGTH + call CopyBytes + ret + +ShrinkPlayer: + ldh a, [hROMBank] + push af + + ld a, 32 ; fade time + ld [wMusicFade], a + ld de, MUSIC_NONE + ld a, e + ld [wMusicFadeID], a + ld a, d + ld [wMusicFadeID + 1], a + + ld de, SFX_ESCAPE_ROPE + call PlaySFX + pop af + rst Bankswitch + + ld c, 8 + call DelayFrames + + ld hl, Shrink1Pic + ld b, BANK(Shrink1Pic) + call ShrinkFrame + + ld c, 8 + call DelayFrames + + ld hl, Shrink2Pic + ld b, BANK(Shrink2Pic) + call ShrinkFrame + + ld c, 8 + call DelayFrames + + hlcoord 6, 5 + ld b, 7 + ld c, 7 + call ClearBox + + ld c, 3 + call DelayFrames + + call Intro_PlaceChrisSprite + call LoadFontsExtra + + ld c, 50 + call DelayFrames + + call RotateThreePalettesRight + call ClearTilemap + ret + +MovePlayerPicRight: + hlcoord 6, 4 + ld de, $1 + jr MovePlayerPic + +MovePlayerPicLeft: + hlcoord 13, 4 + ld de, -1 +MovePlayerPic: + ld c, $8 +.loop + push bc + push hl + push de + xor a + ldh [hBGMapMode], a + lb bc, 7, 7 + predef PlaceGraphic + xor a + ldh [hBGMapThird], a + call WaitBGMap + call DelayFrame + pop de + pop hl + add hl, de + pop bc + dec c + jr nz, .loop + ret + +Intro_RotatePalettesLeftFrontpic: + ld hl, IntroFadePalettes + ld b, IntroFadePalettes.End - IntroFadePalettes +.loop + ld a, [hli] + call DmgToCgbBGPals + ld c, 10 + call DelayFrames + dec b + jr nz, .loop + ret + +IntroFadePalettes: + dc 1, 1, 1, 0 + dc 2, 2, 2, 0 + dc 3, 3, 3, 0 + dc 3, 3, 2, 0 + dc 3, 3, 1, 0 + dc 3, 2, 1, 0 +.End + +Intro_WipeInFrontpic: + ld a, $77 + ldh [hWX], a + call DelayFrame + ld a, %11100100 + call DmgToCgbBGPals +.loop + call DelayFrame + ldh a, [hWX] + sub $8 + cp -1 + ret z + ldh [hWX], a + jr .loop + +Intro_PrepTrainerPic: + ld de, vTiles2 + farcall GetTrainerPic + xor a + ldh [hGraphicStartTile], a + hlcoord 6, 4 + lb bc, 7, 7 + predef PlaceGraphic + ret + +ShrinkFrame: + ld de, vTiles2 + ld c, 7 * 7 + predef DecompressGet2bpp + xor a + ldh [hGraphicStartTile], a + hlcoord 6, 4 + lb bc, 7, 7 + predef PlaceGraphic + ret + +Intro_PlaceChrisSprite: + ld de, ChrisSpriteGFX + lb bc, BANK(ChrisSpriteGFX), 12 + ld hl, vTiles0 + call Request2bpp + + ld hl, wVirtualOAMSprite00 + ld de, .sprites + ld a, [de] + inc de + + ld c, a +.loop + ld a, [de] + inc de + ld [hli], a ; y + ld a, [de] + inc de + ld [hli], a ; x + ld a, [de] + inc de + ld [hli], a ; tile id + xor a ; PAL_OW_RED + ld [hli], a + dec c + jr nz, .loop + ret + +.sprites + db 4 + ; y pxl, x pxl, tile offset + db 9 * 8 + 4, 9 * 8, 0 + db 9 * 8 + 4, 10 * 8, 1 + db 10 * 8 + 4, 9 * 8, 2 + db 10 * 8 + 4, 10 * 8, 3 + +IntroSequence: + callfar Copyright_GFPresents + jr c, StartTitleScreen + callfar GoldSilverIntro + + ; fallthrough + +StartTitleScreen: + call TitleScreen + call DelayFrame +.loop + call RunTitleScreen + jr nc, .loop + + call ClearSprites + call ClearBGPalettes + + ld hl, rLCDC + res rLCDC_SPRITE_SIZE, [hl] ; 8x8 + call ClearTilemap + xor a + ldh [hLCDCPointer], a + ld b, SCGB_DIPLOMA + call GetSGBLayout + call UpdateTimePals + ld a, [wIntroSceneFrameCounter] + cp $5 + jr c, .ok + xor a +.ok + ld e, a + ld d, 0 + ld hl, .dw + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.dw + dw MainMenu + dw DeleteSaveData + dw IntroSequence + dw IntroSequence + dw ResetClock + +INCLUDE "engine/movie/title.asm" + +RunTitleScreen: + call Function63fe + ld a, [wJumptableIndex] + bit 7, a + jr nz, .done_title + call TitleScreenScene + ld a, $1 + ldh [hOAMUpdate], a + farcall PlaySpriteAnimations + xor a + ldh [hOAMUpdate], a + call Function64b1 + call DelayFrame + and a + ret + +.done_title + scf + ret + +Function63fe: +IF DEF(_GOLD) + ldh a, [hVBlankCounter] + and $7 + ret nz +ENDC + ld hl, wLYOverrides + $5f + ld a, [hl] + dec a + ld bc, 2 * SCREEN_WIDTH + call ByteFill + ret + +TitleScreenScene: + ld e, a + ld d, 0 + ld hl, .scenes + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.scenes + dw TitleScreenTimer + dw TitleScreenMain + dw TitleScreenEnd + +.Unreferenced_NextScene: + ld hl, wJumptableIndex + inc [hl] + ret + +TitleScreenTimer: +; Next scene + ld hl, wJumptableIndex + inc [hl] + +; Start a timer + ld hl, wTitleScreenTimer +IF DEF(_GOLD) + ld de, 84 * 60 + 16 +ELIF DEF(_SILVER) + ld de, 73 * 60 + 36 +ENDC + ld [hl], e + inc hl + ld [hl], d + ret + +TitleScreenMain: +; Run the timer down. + ld hl, wTitleScreenTimer + ld e, [hl] + inc hl + ld d, [hl] + ld a, e + or d + jr z, .end + + dec de + ld [hl], d + dec hl + ld [hl], e + +; Save data can be deleted by pressing Up + B + Select. + call GetJoypad + ld hl, hJoyDown + ld a, [hl] + and D_UP + B_BUTTON + SELECT + cp D_UP + B_BUTTON + SELECT + jr z, .delete_save_data + +; Clock can be reset by pressing Down + B + Select. + ld a, [hl] + and D_DOWN + B_BUTTON + SELECT + cp D_DOWN + B_BUTTON + SELECT + jr z, .clock_reset + ld a, [hl] + and START | A_BUTTON + jr nz, .incave + ret + +.incave + ld a, 0 + jr .done + +.delete_save_data + ld a, 1 + +.done + ld [wIntroSceneFrameCounter], a + +; Return to the intro sequence. + ld hl, wJumptableIndex + set 7, [hl] + ret + +.end +; Next scene + ld hl, wJumptableIndex + inc [hl] + +; Fade out the title screen music + xor a ; MUSIC_NONE + ld [wMusicFadeID], a + ld [wMusicFadeID + 1], a + ld hl, wMusicFade + ld [hl], 8 ; 1 second + + ld hl, wTitleScreenTimer + inc [hl] + ret + +.clock_reset + ld a, 4 + ld [wIntroSceneFrameCounter], a + +; Return to the intro sequence. + ld hl, wJumptableIndex + set 7, [hl] + ret + +TitleScreenEnd: +; Wait until the music is done fading. + + ld hl, wTitleScreenTimer + inc [hl] + + ld a, [wMusicFade] + and a + ret nz + + ld a, 2 + ld [wIntroSceneFrameCounter], a + +; Back to the intro. + ld hl, wJumptableIndex + set 7, [hl] + ret + +DeleteSaveData: + farcall _DeleteSaveData + jp Init + +ResetClock: + farcall _ResetClock + jp Init + +Function64b1: + ; If bit 0 or 1 of [wTitleScreenTimer] is set, we don't need to be here. + ld a, [wTitleScreenTimer] + and %00000011 + ret nz +IF DEF(_GOLD) + ld bc, wSpriteAnim10 + ld hl, SPRITEANIMSTRUCT_FRAME + add hl, bc + ld l, [hl] + ld h, 0 + add hl, hl + add hl, hl + ld de, .Data_64e0 + add hl, de + ; If bit 2 of [wTitleScreenTimer] is set, get the second dw; else, get the first dw + ld a, [wTitleScreenTimer] + and %00000100 + srl a + srl a + ld e, a + ld d, 0 + add hl, de + add hl, de + ld a, [hli] + and a + ret z + ld e, a + ld d, [hl] +ELIF DEF(_SILVER) + depixel 15, 11, 4, 0 +ENDC + ld a, SPRITE_ANIM_INDEX_GS_TITLE_TRAIL + call InitSpriteAnimStruct + ret + +IF DEF(_GOLD) +.Data_64e0: +; frame 0 y, x; frame 1 y, x + db 11 * 8 + 4, 10 * 8, 0 * 8, 0 * 8 + db 11 * 8 + 4, 13 * 8, 11 * 8 + 4, 11 * 8 + db 11 * 8 + 4, 13 * 8, 11 * 8 + 4, 15 * 8 + db 11 * 8 + 4, 17 * 8, 11 * 8 + 4, 15 * 8 + db 0 * 8, 0 * 8, 11 * 8 + 4, 15 * 8 + db 0 * 8, 0 * 8, 11 * 8 + 4, 11 * 8 +ENDC + +Copyright: + call ClearTilemap + call LoadFontsExtra + ld de, CopyrightGFX + ld hl, vTiles2 tile $60 + lb bc, BANK(CopyrightGFX), 30 + call Request2bpp + hlcoord 2, 7 + ld de, CopyrightString + jp PlaceString + +CopyrightString: + ; ©1995-2000 Nintendo + db $60, $61, $62, $63, $7a, $7b, $7c, $7d + db $65, $66, $67, $68, $69, $6a + + ; ©1995-2000 Creatures inc. + next $60, $61, $62, $63, $7a, $7b, $7c, $7d + db $6b, $6c, $6d, $6e, $6f, $70, $71, $72 + + ; ©1995-2000 GAME FREAK inc. + next $60, $61, $62, $63, $7a, $7b, $7c, $7d + db $73, $74, $75, $76, $77, $78, $79, $71, $72 + + db "@" + +GameInit:: + call ClearWindowData + farcall TryLoadSaveData + jp IntroSequence diff --git a/engine/menus/main_menu.asm b/engine/menus/main_menu.asm new file mode 100644 index 00000000..4e9113a8 --- /dev/null +++ b/engine/menus/main_menu.asm @@ -0,0 +1,253 @@ +MainMenu: + ld de, MUSIC_NONE + call PlayMusic + call DelayFrame + ld de, MUSIC_MAIN_MENU + ld a, e + ld [wMapMusic], a + call PlayMusic +.loop + xor a + ld [wDisableTextAcceleration], a + call ClearTilemapEtc + ld b, SCGB_DIPLOMA + call GetSGBLayout + ld hl, wGameTimerPause + res GAMETIMERPAUSE_TIMER_PAUSED_F, [hl] + call MainMenu_GetWhichMenu + ld [wWhichIndexSet], a + call MainMenu_PrintCurrentTimeAndDay + ld hl, .MenuHeader + call LoadMenuHeader + call MainMenuJoypadLoop + call CloseWindow + jr c, .quit + call ClearTilemap + ld a, [wMenuSelection] + ld hl, .Jumptable + rst JumpTable + jr .loop + +.quit + jp StartTitleScreen + +.MenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 0, 14, 7 + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_CURSOR ; flags + db 0 ; items + dw MainMenuItems + dw PlaceMenuStrings + dw .Strings + +.Strings: + db "CONTINUE@" + db "NEW GAME@" + db "OPTION@" + db "MYSTERY GIFT@" + +.Jumptable: + dw MainMenu_Continue + dw MainMenu_NewGame + dw MainMenu_Options + dw MainMenu_MysteryGift + +CONTINUE EQU 0 +NEW_GAME EQU 1 +OPTION EQU 2 +MYSTERY_GIFT EQU 3 + +MainMenuItems: + +NewGameMenu: + db 2 + db NEW_GAME + db OPTION + db -1 + +ContinueMenu: + db 3 + db CONTINUE + db NEW_GAME + db OPTION + db -1 + +MysteryMenu: + db 4 + db CONTINUE + db NEW_GAME + db OPTION + db MYSTERY_GIFT + db -1 + +MainMenu_GetWhichMenu: + nop + nop + nop + ld a, [wSaveFileExists] + and a + jr nz, .next + ld a, $0 ; New Game + ret + +.next + ldh a, [hCGB] + cp $1 + ld a, $1 + ret nz + ld a, BANK(sNumDailyMysteryGiftPartnerIDs) + call OpenSRAM + ld a, [sNumDailyMysteryGiftPartnerIDs] + cp -1 + call CloseSRAM + ld a, $1 ; Continue + ret z + ld a, $2 ; New Game + ret + +MainMenuJoypadLoop: + call SetUpMenu +.loop + call MainMenu_PrintCurrentTimeAndDay + call GetScrollingMenuJoypad + ld a, [wMenuJoypad] + cp B_BUTTON + jr z, .b_button + cp A_BUTTON + jr z, .a_button + jr .loop + +.a_button + call PlayClickSFX + and a + ret + +.b_button + scf + ret + +MainMenu_PrintCurrentTimeAndDay: + ld a, [wSaveFileExists] + and a + ret z + xor a + ldh [hBGMapMode], a + call .PlaceBox + ld hl, wOptions + ld a, [hl] + push af + set NO_TEXT_SCROLL, [hl] + call .PlaceTime + pop af + ld [wOptions], a + ld a, $1 + ldh [hBGMapMode], a + ret + +.PlaceBox: + call CheckRTCStatus + and $80 + jr nz, .TimeFail + hlcoord 0, 12 + ld b, 4 + ld c, 13 + call Textbox + ret + +.TimeFail: + call SpeechTextbox + ret + +.PlaceTime: + ld a, [wSaveFileExists] + and a + ret z + call CheckRTCStatus + and %10000000 ; Day count exceeded 16383 + jp nz, .PrintTimeNotSet + call UpdateTime + hlcoord 1, 13 + lb bc, 4, 13 + call ClearBox + call GetWeekday + ld b, a + decoord 1, 14 + call .PlaceCurrentDay + decoord 4, 16 + ldh a, [hHours] + ld c, a + farcall PrintHour + ld [hl], ":" + inc hl + ld de, hMinutes + lb bc, PRINTNUM_LEADINGZEROS | 1, 2 + call PrintNum + ret + +.min +; unused + db "min.@" + +.PrintTimeNotSet: + hlcoord 1, 14 + ld de, .TimeNotSet + call PlaceString + ret + +.TimeNotSet: + db "TIME NOT SET@" + +.MainMenuTimeUnknownText: + text_far _MainMenuTimeUnknownText + text_end + +.PlaceCurrentDay: + push de + ld hl, .Days + ld a, b + call GetNthString + ld d, h + ld e, l + pop hl + call PlaceString + ld h, b + ld l, c + ld de, .Day + call PlaceString + ret + +.Days: + db "SUN@" + db "MON@" + db "TUES@" + db "WEDNES@" + db "THURS@" + db "FRI@" + db "SATUR@" +.Day: + db "DAY@" + +ClearTilemapEtc: + xor a + ldh [hMapAnims], a + call ClearTilemap + call LoadFontsExtra + call LoadStandardFont + call ClearWindowData + ret + +MainMenu_MysteryGift: +MysteryGift: + call UpdateTime + farcall DoMysteryGiftIfDayHasPassed + farcall DoMysteryGift + ret + +MainMenu_Options: +OptionsMenu: + farcall _OptionsMenu + ret diff --git a/engine/menus/menu.asm b/engine/menus/menu.asm new file mode 100644 index 00000000..b678d714 --- /dev/null +++ b/engine/menus/menu.asm @@ -0,0 +1,675 @@ +_2DMenu_:: + xor a + ldh [hBGMapMode], a + call MenuBox + call Place2DMenuItemStrings + call UpdateSprites + call ApplyTilemap + call Init2DMenuCursorPosition + call StaticMenuJoypad + call MenuClickSound + ld a, [wMenuDataFlags] + bit 1, a + jr z, .skip + call GetMenuJoypad + bit SELECT_F, a + jr nz, .quit1 + +.skip + ld a, [wMenuDataFlags] + bit 0, a + jr nz, .skip2 + call GetMenuJoypad + bit B_BUTTON_F, a + jr nz, .quit2 + +.skip2 + ld a, [w2DMenuNumCols] + ld c, a + ld a, [wMenuCursorY] + dec a + call SimpleMultiply + ld c, a + ld a, [wMenuCursorX] + add c + ld [wMenuCursorBuffer], a + and a + ret + +.quit1 + scf + ret + +.quit2 + scf + ret + +Get2DMenuNumberOfColumns: + ld a, [wMenuData_2DMenuDimensions] + and $f + ret + +Get2DMenuNumberOfRows: + ld a, [wMenuData_2DMenuDimensions] + swap a + and $f + ret + +Place2DMenuItemStrings: + ld hl, wMenuData_2DMenuItemStringsAddr + ld e, [hl] + inc hl + ld d, [hl] + call GetMenuTextStartCoord + call Coord2Tile + call Get2DMenuNumberOfRows + ld b, a +.row + push bc + push hl + call Get2DMenuNumberOfColumns + ld c, a +.col + push bc + ld a, [wMenuData_2DMenuItemStringsBank] + call Place2DMenuItemName + inc de + ld a, [wMenuData_2DMenuSpacing] + ld c, a + ld b, 0 + add hl, bc + pop bc + dec c + jr nz, .col + pop hl + ld bc, 2 * SCREEN_WIDTH + add hl, bc + pop bc + dec b + jr nz, .row + ld hl, wMenuData_2DMenuFunctionAddr + ld a, [hli] + ld h, [hl] + ld l, a + or h + ret z + ld a, [wMenuData_2DMenuFunctionBank] + rst FarCall + ret + +Init2DMenuCursorPosition: + call GetMenuTextStartCoord + ld a, b + ld [w2DMenuCursorInitY], a + dec c + ld a, c + ld [w2DMenuCursorInitX], a + call Get2DMenuNumberOfRows + ld [w2DMenuNumRows], a + call Get2DMenuNumberOfColumns + ld [w2DMenuNumCols], a + call .InitFlags_a + call .InitFlags_b + call .InitFlags_c + ld a, [w2DMenuNumCols] + ld e, a + ld a, [wMenuCursorBuffer] + ld b, a + xor a + ld d, 0 +.loop + inc d + add e + cp b + jr c, .loop + sub e + ld c, a + ld a, b + sub c + and a + jr z, .reset1 + cp e + jr z, .okay1 + jr c, .okay1 +.reset1 + ld a, 1 +.okay1 + ld [wMenuCursorX], a + ld a, [w2DMenuNumRows] + ld e, a + ld a, d + and a + jr z, .reset2 + cp e + jr z, .okay2 + jr c, .okay2 +.reset2 + ld a, 1 +.okay2 + ld [wMenuCursorY], a + xor a + ld [wCursorOffCharacter], a + ld [wCursorCurrentTile], a + ld [wCursorCurrentTile + 1], a + ret + +.InitFlags_a: + xor a + ld hl, w2DMenuFlags1 + ld [hli], a + ld [hld], a + ld a, [wMenuDataFlags] + bit 5, a + ret z + set 5, [hl] + set 4, [hl] + ret + +.InitFlags_b: + ld a, [wMenuData_2DMenuSpacing] + or $20 + ld [w2DMenuCursorOffsets], a + ret + +.InitFlags_c: + ld hl, wMenuDataFlags + ld a, A_BUTTON + bit 0, [hl] + jr nz, .skip + or B_BUTTON +.skip + bit 1, [hl] + jr z, .skip2 + or SELECT +.skip2 + ld [wMenuJoypadFilter], a + ret + +_StaticMenuJoypad:: + call Place2DMenuCursor +_ScrollingMenuJoypad:: + ld hl, w2DMenuFlags2 + res 7, [hl] + ldh a, [hBGMapMode] + push af + +.menu_joypad_loop + call Move2DMenuCursor + ldh a, [hOAMUpdate] + push af + ld a, $1 + ldh [hOAMUpdate], a + call WaitBGMap + pop af + ldh [hOAMUpdate], a + xor a + ldh [hBGMapMode], a + +.loopRTC + call UpdateTimeAndPals + call Menu_WasButtonPressed + jr c, .pressed + ld a, [w2DMenuFlags1] + bit 7, a + jp nz, .done + jr .loopRTC + +.pressed + call _2DMenuInterpretJoypad + jp c, .done + ld a, [w2DMenuFlags1] + bit 7, a + jr nz, .done + call GetMenuJoypad + ld b, a + ld a, [wMenuJoypadFilter] + and b + jp z, .menu_joypad_loop + +.done + pop af + ldh [hBGMapMode], a + call GetMenuJoypad + ret + +Menu_WasButtonPressed: + ld a, [w2DMenuFlags1] + bit 6, a + jr z, .skip_to_joypad + callfar PlaySpriteAnimationsAndDelayFrame + +.skip_to_joypad + call JoyTextDelay + call GetMenuJoypad + and a + ret z + scf + ret + +_2DMenuInterpretJoypad: + call GetMenuJoypad + bit A_BUTTON_F, a + jp nz, .a_b_start_select + bit B_BUTTON_F, a + jp nz, .a_b_start_select + bit SELECT_F, a + jp nz, .a_b_start_select + bit START_F, a + jp nz, .a_b_start_select + bit D_RIGHT_F, a + jr nz, .d_right + bit D_LEFT_F, a + jr nz, .d_left + bit D_UP_F, a + jr nz, .d_up + bit D_DOWN_F, a + jr nz, .d_down + and a + ret + +.set_bit_7 + ld hl, w2DMenuFlags2 + set 7, [hl] + scf + ret + +.d_down + ld hl, wMenuCursorY + ld a, [w2DMenuNumRows] + cp [hl] + jr z, .check_wrap_around_down + inc [hl] + xor a + ret + +.check_wrap_around_down + ld a, [w2DMenuFlags1] + bit 5, a + jr nz, .wrap_around_down + bit 3, a + jp nz, .set_bit_7 + xor a + ret + +.wrap_around_down + ld [hl], $1 + xor a + ret + +.d_up + ld hl, wMenuCursorY + ld a, [hl] + dec a + jr z, .check_wrap_around_up + ld [hl], a + xor a + ret + +.check_wrap_around_up + ld a, [w2DMenuFlags1] + bit 5, a + jr nz, .wrap_around_up + bit 2, a + jp nz, .set_bit_7 + xor a + ret + +.wrap_around_up + ld a, [w2DMenuNumRows] + ld [hl], a + xor a + ret + +.d_left + ld hl, wMenuCursorX + ld a, [hl] + dec a + jr z, .check_wrap_around_left + ld [hl], a + xor a + ret + +.check_wrap_around_left + ld a, [w2DMenuFlags1] + bit 4, a + jr nz, .wrap_around_left + bit 1, a + jp nz, .set_bit_7 + xor a + ret + +.wrap_around_left + ld a, [w2DMenuNumCols] + ld [hl], a + xor a + ret + +.d_right + ld hl, wMenuCursorX + ld a, [w2DMenuNumCols] + cp [hl] + jr z, .check_wrap_around_right + inc [hl] + xor a + ret + +.check_wrap_around_right + ld a, [w2DMenuFlags1] + bit 4, a + jr nz, .wrap_around_right + bit 0, a + jp nz, .set_bit_7 + xor a + ret + +.wrap_around_right + ld [hl], $1 + xor a + ret + +.a_b_start_select + xor a + ret + +Move2DMenuCursor: + ld hl, wCursorCurrentTile + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [hl] + cp "▶" + jr nz, Place2DMenuCursor + ld a, [wCursorOffCharacter] + ld [hl], a +Place2DMenuCursor: + ld a, [w2DMenuCursorInitY] + ld b, a + ld a, [w2DMenuCursorInitX] + ld c, a + call Coord2Tile + ld a, [w2DMenuCursorOffsets] + swap a + and $f + ld c, a + ld a, [wMenuCursorY] + ld b, a + xor a + dec b + jr z, .got_row +.row_loop + add c + dec b + jr nz, .row_loop + +.got_row + ld c, SCREEN_WIDTH + call AddNTimes + ld a, [w2DMenuCursorOffsets] + and $f + ld c, a + ld a, [wMenuCursorX] + ld b, a + xor a + dec b + jr z, .got_col +.col_loop + add c + dec b + jr nz, .col_loop + +.got_col + ld c, a + add hl, bc + ld a, [hl] + cp "▶" + jr z, .cursor_on + ld [wCursorOffCharacter], a + ld [hl], "▶" + +.cursor_on + ld a, l + ld [wCursorCurrentTile], a + ld a, h + ld [wCursorCurrentTile + 1], a + ret + +_PushWindow:: + xor a ; BANK(sWindowStack) + call OpenSRAM + + ld hl, wWindowStackPointer + ld e, [hl] + inc hl + ld d, [hl] + push de + ld b, $10 + ld hl, wMenuFlags +.loop + ld a, [hli] + ld [de], a + dec de + dec b + jr nz, .loop + +; If bit 6 or 7 of the menu flags is set, set bit 0 of the address +; at 7:[wWindowStackPointer], and draw the menu using the coordinates from the header. +; Otherwise, reset bit 0 of 7:[wWindowStackPointer]. + ld a, [wMenuFlags] + bit 6, a + jr nz, .bit_6 + bit 7, a + jr z, .not_bit_7 + +.bit_6 + ld hl, wWindowStackPointer + ld a, [hli] + ld h, [hl] + ld l, a + set 0, [hl] + call MenuBoxCoord2Tile + call GetMenuBoxDims + inc b + inc c + call .ret ; empty function + +.row + push bc + push hl + +.col + ld a, [hli] + ld [de], a + dec de + dec c + jr nz, .col + + pop hl + ld bc, SCREEN_WIDTH + add hl, bc + pop bc + dec b + jr nz, .row + jr .done + +.not_bit_7 + pop hl ; last-pushed register was de + push hl + ld a, [hld] + ld l, [hl] + ld h, a + res 0, [hl] + +.done + pop hl + call .ret ; empty function + ld a, h + ld [de], a + dec de + ld a, l + ld [de], a + dec de + ld hl, wWindowStackPointer + ld [hl], e + inc hl + ld [hl], d + + call CloseSRAM + ld hl, wWindowStackSize + inc [hl] + ret + +.ret + ret + +_ExitMenu:: + xor a + ldh [hBGMapMode], a + + xor a ; BANK(sWindowStack) + call OpenSRAM + + call GetWindowStackTop + ld a, l + or h + jp z, Error_Cant_ExitMenu + ld a, l + ld [wWindowStackPointer], a + ld a, h + ld [wWindowStackPointer + 1], a + call PopWindow + ld a, [wMenuFlags] + bit 0, a + jr z, .loop + ld d, h + ld e, l + call RestoreTileBackup + +.loop + call GetWindowStackTop + ld a, h + or l + jr z, .done + call PopWindow + +.done + call CloseSRAM + ld hl, wWindowStackSize + dec [hl] + call Function2434b + ld a, [wSpriteUpdatesEnabled] + cp 0 + ret z + call ReloadPalettes + ret + +Function2434b: + ld a, [wVramState] + bit 0, a + ret z + xor a ; sScratch + call OpenSRAM + hlcoord 0, 0 + ld de, sScratch + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + call CopyBytes + call CloseSRAM + call OverworldTextModeSwitch + xor a ; sScratch + call OpenSRAM + ld hl, sScratch + decoord 0, 0 + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT +.loop + ld a, [hl] + cp $61 + jr c, .next + ld [de], a +.next + inc hl + inc de + dec bc + ld a, c + or b + jr nz, .loop + call CloseSRAM + ret + +Error_Cant_ExitMenu: + ld hl, .WindowPoppingErrorText + call PrintText + call WaitBGMap +.infinite_loop + jr .infinite_loop + +.WindowPoppingErrorText: + text_far _WindowPoppingErrorText + text_end + +_InitVerticalMenuCursor:: + ld a, [wMenuDataFlags] + ld b, a + ld hl, w2DMenuCursorInitY + ld a, [wMenuBorderTopCoord] + inc a + bit 6, b + jr nz, .skip_offset + inc a +.skip_offset + ld [hli], a +; w2DMenuCursorInitX + ld a, [wMenuBorderLeftCoord] + inc a + ld [hli], a +; w2DMenuNumRows + ld a, [wMenuDataItems] + ld [hli], a +; w2DMenuNumCols + ld a, 1 + ld [hli], a +; w2DMenuFlags1 + ld [hl], $0 + bit 5, b + jr z, .skip_bit_5 + set 5, [hl] +.skip_bit_5 + ld a, [wMenuFlags] + bit 4, a + jr z, .skip_bit_6 + set 6, [hl] +.skip_bit_6 + inc hl +; w2DMenuFlags2 + xor a + ld [hli], a +; w2DMenuCursorOffsets + ln a, 2, 0 + ld [hli], a +; wMenuJoypadFilter + ld a, A_BUTTON + bit 0, b + jr nz, .skip_bit_1 + add B_BUTTON +.skip_bit_1 + ld [hli], a +; wMenuCursorY + ld a, [wMenuCursorBuffer] + and a + jr z, .load_at_the_top + ld c, a + ld a, [wMenuDataItems] + cp c + jr nc, .load_position +.load_at_the_top + ld c, 1 +.load_position + ld [hl], c + inc hl +; wMenuCursorX + ld a, 1 + ld [hli], a +; wCursorOffCharacter, wCursorCurrentTile + xor a + ld [hli], a + ld [hli], a + ld [hli], a + ret diff --git a/engine/menus/menu_2.asm b/engine/menus/menu_2.asm new file mode 100644 index 00000000..2fd65e2b --- /dev/null +++ b/engine/menus/menu_2.asm @@ -0,0 +1,298 @@ +PlaceMenuItemName: + push de + ld a, [wMenuSelection] + ld [wNamedObjectIndexBuffer], a + call GetItemName + pop hl + call PlaceString + ret + +PlaceMenuItemQuantity: + push de + ld a, [wMenuSelection] + ld [wCurItem], a + farcall _CheckTossableItem + ld a, [wItemAttributeParamBuffer] + pop hl + and a + jr nz, .done + ld de, $15 + add hl, de + ld [hl], "×" + inc hl + ld de, wMenuSelectionQuantity + lb bc, 1, 2 + call PrintNum + +.done + ret + +PlaceMoneyTopRight: + ld hl, MenuHeader_0x24a3d + call CopyMenuHeader + jr PlaceMoneyTextbox + +PlaceMoneyBottomLeft: + ld hl, MenuHeader_0x24a45 + call CopyMenuHeader + jr PlaceMoneyTextbox + +PlaceMoneyAtTopLeftOfTextbox: + ld hl, MenuHeader_0x24a3d + lb de, 0, 11 + call OffsetMenuHeader + +PlaceMoneyTextbox: + call MenuBox + call MenuBoxCoord2Tile + ld de, SCREEN_WIDTH + 1 + add hl, de + ld de, wMoney + lb bc, PRINTNUM_MONEY | 3, 6 + call PrintNum + ret + +MenuHeader_0x24a3d: + db MENU_BACKUP_TILES ; flags + menu_coords 11, 0, SCREEN_WIDTH - 1, 2 + dw NULL + db 1 ; default option + +MenuHeader_0x24a45: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 11, 8, 13 + dw NULL + db 1 ; default option + +DisplayCoinCaseBalance: + ; Place a text box of size 1x7 at 11, 0. + hlcoord 11, 0 + ld b, 1 + ld c, 7 + call Textbox + hlcoord 12, 0 + ld de, CoinString + call PlaceString + hlcoord 17, 1 + ld de, ShowMoney_TerminatorString + call PlaceString + ld de, wCoins + lb bc, 2, 4 + hlcoord 13, 1 + call PrintNum + ret + +DisplayMoneyAndCoinBalance: + hlcoord 5, 0 + ld b, 3 + ld c, 13 + call Textbox + hlcoord 6, 1 + ld de, MoneyString + call PlaceString + hlcoord 12, 1 + ld de, wMoney + lb bc, PRINTNUM_MONEY | 3, 6 + call PrintNum + hlcoord 6, 3 + ld de, CoinString + call PlaceString + hlcoord 15, 3 + ld de, wCoins + lb bc, 2, 4 + call PrintNum + ret + +MoneyString: + db "MONEY@" +CoinString: + db "COIN@" +ShowMoney_TerminatorString: + db "@@" + +Unreferenced_Function24ab8: +; related to safari? + ld hl, wOptions + ld a, [hl] + push af + set NO_TEXT_SCROLL, [hl] + hlcoord 0, 0 + ld b, 3 + ld c, 7 + call Textbox + hlcoord 1, 1 + ld de, wSafariTimeRemaining + lb bc, 2, 3 + call PrintNum + hlcoord 4, 1 + ld de, .slash_500 + call PlaceString + hlcoord 1, 3 + ld de, .booru_ko + call PlaceString + hlcoord 5, 3 + ld de, wSafariBallsRemaining + lb bc, 1, 2 + call PrintNum + pop af + ld [wOptions], a + ret + +.slash_500 + db "/500@" +.booru_ko + db "ボール こ@" + +StartMenu_DrawBugContestStatusBox: + hlcoord 0, 0 + ld b, 5 + ld c, 17 + call Textbox + ret + +StartMenu_PrintBugContestStatus: + ld hl, wOptions + ld a, [hl] + push af + set NO_TEXT_SCROLL, [hl] + call StartMenu_DrawBugContestStatusBox + hlcoord 1, 5 + ld de, .Balls_EN + call PlaceString + hlcoord 8, 5 + ld de, wParkBallsRemaining + lb bc, PRINTNUM_LEFTALIGN | 1, 2 + call PrintNum + hlcoord 1, 1 + ld de, .CAUGHT + call PlaceString + ld a, [wContestMon] + and a + ld de, .None + jr z, .no_contest_mon + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + +.no_contest_mon + hlcoord 8, 1 + call PlaceString + ld a, [wContestMon] + and a + jr z, .skip_level + hlcoord 1, 3 + ld de, .LEVEL + call PlaceString + ld a, [wContestMonLevel] + ld h, b + ld l, c + inc hl + ld c, 3 + call Print8BitNumLeftAlign + +.skip_level + pop af + ld [wOptions], a + ret + +.Balls_JP: + db "ボール こ@" +.CAUGHT: + db "CAUGHT@" +.Balls_EN: + db "BALLS:@" +.None: + db "None@" +.LEVEL: + db "LEVEL@" + +Kurt_SelectApricorn: + call FindApricornsInBag + jr c, .nope + ld hl, .MenuHeader + call LoadMenuHeader + call DoNthMenu + call CloseWindow + jr c, .nope + ld a, [wMenuSelection] + jr .done + +.nope + xor a ; FALSE + +.done + ld c, a + ret + +.MenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 0, 14, 17 + dw .MenuData + db 1 ; default option + +.MenuData: + db SCROLLINGMENU_ENABLE_SELECT | SCROLLINGMENU_ENABLE_FUNCTION3 + dbw 0, wBuffer1 + dw .Name + dw NULL + +.Name: + ld a, [wMenuSelection] + and a + jp nz, PlaceMenuItemName + ld h, d + ld l, e + ld de, .Cancel + call PlaceString + ret + +.Cancel + db "CANCEL@" + +FindApricornsInBag: +; Checks the bag for Apricorns. + ld hl, wBuffer1 + xor a + ld [hli], a + dec a + ld bc, 10 + call ByteFill + + ld hl, ApricornBalls +.loop + ld a, [hl] + cp -1 + jr z, .done + push hl + ld [wCurItem], a + ld hl, wNumItems + call CheckItem + pop hl + jr nc, .nope + ld a, [hl] + call .addtobuffer +.nope + inc hl + inc hl + jr .loop + +.done + xor a + call .addtobuffer + ld a, [wBuffer1] + cp 1 + ret nz + scf + ret + +.addtobuffer + push hl + ld hl, wBuffer1 + inc [hl] + ld e, [hl] + ld d, 0 + add hl, de + ld [hl], a + pop hl + ret + +INCLUDE "data/items/apricorn_balls.asm" diff --git a/engine/menus/naming_screen.asm b/engine/menus/naming_screen.asm new file mode 100644 index 00000000..34e2c6f2 --- /dev/null +++ b/engine/menus/naming_screen.asm @@ -0,0 +1,1377 @@ +NAMINGSCREEN_CURSOR EQU $7e + +NAMINGSCREEN_BORDER EQU "■" ; $60 +NAMINGSCREEN_MIDDLELINE EQU "→" ; $eb +NAMINGSCREEN_UNDERLINE EQU "<DOT>" ; $f2 + +_NamingScreen: + call DisableSpriteUpdates + call NamingScreen + call ReturnToMapWithSpeechTextbox + ret + +NamingScreen: + ld hl, wNamingScreenDestinationPointer + ld [hl], e + inc hl + ld [hl], d + ld hl, wNamingScreenType + ld [hl], b + ld hl, wOptions + ld a, [hl] + push af + set NO_TEXT_SCROLL, [hl] + ldh a, [hMapAnims] + push af + xor a + ldh [hMapAnims], a + ldh a, [hInMenu] + push af + ld a, $1 + ldh [hInMenu], a + call .SetUpNamingScreen + call DelayFrame +.loop + call NamingScreenJoypadLoop + jr nc, .loop + pop af + ldh [hInMenu], a + pop af + ldh [hMapAnims], a + pop af + ld [wOptions], a + call ClearJoypad + ret + +.SetUpNamingScreen: + call ClearBGPalettes + ld b, SCGB_DIPLOMA + call GetSGBLayout + call DisableLCD + call LoadNamingScreenGFX + call NamingScreen_InitText + ld a, LCDC_DEFAULT + ldh [rLCDC], a + call .GetNamingScreenSetup + call WaitBGMap + call WaitTop + call SetPalettes + call NamingScreen_InitNameEntry + ret + +.GetNamingScreenSetup: + ld a, [wNamingScreenType] + maskbits NUM_NAME_TYPES + ld e, a + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.Jumptable: +; entries correspond to NAME_* constants + dw .Pokemon + dw .Player + dw .Rival + dw .Mom + dw .Box + dw .Pokemon + dw .Pokemon + dw .Pokemon + +.Pokemon: + ld a, [wCurPartySpecies] + ld [wTempIconSpecies], a + ld hl, LoadMenuMonIcon + ld a, BANK(LoadMenuMonIcon) + ld e, MONICON_NAMINGSCREEN + rst FarCall + ld a, [wCurPartySpecies] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + hlcoord 5, 2 + call PlaceString + ld l, c + ld h, b + ld de, .NicknameStrings + call PlaceString + inc de + hlcoord 5, 4 + call PlaceString + farcall GetGender + jr c, .genderless + ld a, "♂" + jr nz, .place_gender + ld a, "♀" +.place_gender + hlcoord 1, 2 + ld [hl], a +.genderless + call .StoreMonIconParams + ret + +.NicknameStrings: + db "'S@" + db "NICKNAME?@" + +.Player: + ld de, ChrisSpriteGFX + call .LoadSprite + hlcoord 5, 2 + ld de, .PlayerNameString + call PlaceString + call .StoreSpriteIconParams + ret + +.PlayerNameString: + db "YOUR NAME?@" + +.Rival: + ld de, SilverSpriteGFX + call .LoadSprite + hlcoord 5, 2 + ld de, .RivalNameString + call PlaceString + call .StoreSpriteIconParams + ret + +.RivalNameString: + db "RIVAL'S NAME?@" + +.Mom: + ld de, MomSpriteGFX + call .LoadSprite + hlcoord 5, 2 + ld de, .MomNameString + call PlaceString + call .StoreSpriteIconParams + ret + +.MomNameString: + db "MOTHER'S NAME?@" + +.Box: + ld de, PokeBallSpriteGFX + ld hl, vTiles0 tile $00 + lb bc, BANK(PokeBallSpriteGFX), 4 + call Request2bpp + xor a + ld hl, wSpriteAnimDict + ld [hli], a + ld [hl], a + depixel 4, 4, 4, 0 + ld a, SPRITE_ANIM_INDEX_RED_WALK + call InitSpriteAnimStruct + ld hl, SPRITEANIMSTRUCT_FRAMESET_ID + add hl, bc + ld [hl], $0 + hlcoord 5, 2 + ld de, .BoxNameString + call PlaceString + call .StoreBoxIconParams + ret + +.BoxNameString: + db "BOX NAME?@" + +.LoadSprite: + push de + ld hl, vTiles0 tile $00 + lb bc, BANK(ChrisSpriteGFX), 4 + call Request2bpp + pop de + ld hl, 12 tiles + add hl, de + ld e, l + ld d, h + ld hl, vTiles0 tile $04 + lb bc, BANK(ChrisSpriteGFX), 4 + call Request2bpp + xor a + ld hl, wSpriteAnimDict + ld [hli], a + ld [hl], a + lb de, $24, $20 + ld a, SPRITE_ANIM_INDEX_RED_WALK + call InitSpriteAnimStruct + ret + +.StoreMonIconParams: + ld a, MON_NAME_LENGTH - 1 + hlcoord 5, 6 + jr .StoreParams + +.StoreSpriteIconParams: + ld a, PLAYER_NAME_LENGTH - 1 + hlcoord 5, 6 + jr .StoreParams + +.StoreBoxIconParams: + ld a, BOX_NAME_LENGTH - 1 + hlcoord 5, 4 + jr .StoreParams + +.StoreParams: + ld [wNamingScreenMaxNameLength], a + ld a, l + ld [wNamingScreenStringEntryCoord], a + ld a, h + ld [wNamingScreenStringEntryCoord + 1], a + ret + +NamingScreen_IsTargetBox: + push bc + push af + ld a, [wNamingScreenType] + sub $3 + ld b, a + pop af + dec b + pop bc + ret + +NamingScreen_InitText: + call WaitTop + hlcoord 0, 0 + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + ld a, NAMINGSCREEN_BORDER + call ByteFill + hlcoord 1, 1 + lb bc, 6, 18 + call NamingScreen_IsTargetBox + jr nz, .not_box + lb bc, 4, 18 + +.not_box + call ClearBox + ld de, NameInputUpper +NamingScreen_ApplyTextInputMode: + call NamingScreen_IsTargetBox + jr nz, .not_box + ld hl, BoxNameInputLower - NameInputLower + add hl, de + ld d, h + ld e, l + +.not_box + push de + hlcoord 1, 8 + lb bc, 7, 18 + call NamingScreen_IsTargetBox + jr nz, .not_box_2 + hlcoord 1, 6 + lb bc, 9, 18 + +.not_box_2 + call ClearBox + hlcoord 1, 16 + lb bc, 1, 18 + call ClearBox + pop de + hlcoord 2, 8 + ld b, $5 + call NamingScreen_IsTargetBox + jr nz, .row + hlcoord 2, 6 + ld b, $6 + +.row + ld c, $11 +.col + ld a, [de] + ld [hli], a + inc de + dec c + jr nz, .col + push de + ld de, 2 * SCREEN_WIDTH - $11 + add hl, de + pop de + dec b + jr nz, .row + ret + +NamingScreenJoypadLoop: + call JoyTextDelay + ld a, [wJumptableIndex] + bit 7, a + jr nz, .quit + call .RunJumptable + farcall PlaySpriteAnimationsAndDelayFrame + call .UpdateStringEntry + call DelayFrame + and a + ret + +.quit + callfar ClearSpriteAnims + call ClearSprites + xor a + ldh [hSCX], a + ldh [hSCY], a + scf + ret + +.UpdateStringEntry: + xor a + ldh [hBGMapMode], a + hlcoord 1, 5 + call NamingScreen_IsTargetBox + jr nz, .got_coords + hlcoord 1, 3 + +.got_coords + lb bc, 1, 18 + call ClearBox + ld hl, wNamingScreenDestinationPointer + ld e, [hl] + inc hl + ld d, [hl] + ld hl, wNamingScreenStringEntryCoord + ld a, [hli] + ld h, [hl] + ld l, a + call PlaceString + ld a, $1 + ldh [hBGMapMode], a + ret + +.RunJumptable: + ld a, [wJumptableIndex] + ld e, a + ld d, $0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.Jumptable: + dw .InitCursor + dw .ReadButtons + +.InitCursor: + depixel 10, 3 + call NamingScreen_IsTargetBox + jr nz, .got_cursor_position + ld d, 8 * 8 +.got_cursor_position + ld a, SPRITE_ANIM_INDEX_NAMING_SCREEN_CURSOR + call InitSpriteAnimStruct + ld a, c + ld [wNamingScreenCursorObjectPointer], a + ld a, b + ld [wNamingScreenCursorObjectPointer + 1], a + ld hl, SPRITEANIMSTRUCT_FRAMESET_ID + add hl, bc + ld a, [hl] + ld hl, SPRITEANIMSTRUCT_0E + add hl, bc + ld [hl], a + ld hl, wJumptableIndex + inc [hl] + ret + +.ReadButtons: + ld hl, hJoyPressed + ld a, [hl] + and A_BUTTON + jr nz, .a + ld a, [hl] + and B_BUTTON + jr nz, .b + ld a, [hl] + and START + jr nz, .start + ld a, [hl] + and SELECT + jr nz, .select + ret + +.a + call .GetCursorPosition + cp $1 + jr z, .select + cp $2 + jr z, .b + cp $3 + jr z, .end + call NamingScreen_GetLastCharacter + call NamingScreen_TryAddCharacter + ret nc + +.start + ld hl, wNamingScreenCursorObjectPointer + ld c, [hl] + inc hl + ld b, [hl] + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld [hl], $8 + ld hl, SPRITEANIMSTRUCT_0D + add hl, bc + ld [hl], $4 + call NamingScreen_IsTargetBox + ret nz + inc [hl] + ret + +.b + call NamingScreen_DeleteCharacter + ret + +.end + call NamingScreen_StoreEntry + ld hl, wJumptableIndex + set 7, [hl] + ret + +.select + ld hl, wNamingScreenLetterCase + ld a, [hl] + xor 1 + ld [hl], a + jr z, .upper + ld de, NameInputLower + call NamingScreen_ApplyTextInputMode + ret + +.upper + ld de, NameInputUpper + call NamingScreen_ApplyTextInputMode + ret + +.GetCursorPosition: + ld hl, wNamingScreenCursorObjectPointer + ld c, [hl] + inc hl + ld b, [hl] + +NamingScreen_GetCursorPosition: + ld hl, SPRITEANIMSTRUCT_0D + add hl, bc + ld a, [hl] + push bc + ld b, $4 + call NamingScreen_IsTargetBox + jr nz, .not_box + inc b +.not_box + cp b + pop bc + jr nz, .not_bottom_row + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld a, [hl] + cp $3 + jr c, .case_switch + cp $6 + jr c, .delete + ld a, $3 + ret + +.case_switch + ld a, $1 + ret + +.delete + ld a, $2 + ret + +.not_bottom_row + xor a + ret + +NamingScreen_AnimateCursor: + call .GetDPad + ld hl, SPRITEANIMSTRUCT_0D + add hl, bc + ld a, [hl] + ld e, a + swap e + ld hl, SPRITEANIMSTRUCT_YOFFSET + add hl, bc + ld [hl], e + ld d, $4 + call NamingScreen_IsTargetBox + jr nz, .ok + inc d +.ok + cp d + ld de, .LetterEntries + ld a, SPRITE_ANIM_FRAMESET_TEXT_ENTRY_CURSOR - SPRITE_ANIM_FRAMESET_TEXT_ENTRY_CURSOR ; 0 + jr nz, .ok2 + ld de, .CaseDelEnd + ld a, SPRITE_ANIM_FRAMESET_TEXT_ENTRY_CURSOR_BIG - SPRITE_ANIM_FRAMESET_TEXT_ENTRY_CURSOR ; 1 +.ok2 + ld hl, SPRITEANIMSTRUCT_0E + add hl, bc + add [hl] ; default SPRITE_ANIM_FRAMESET_TEXT_ENTRY_CURSOR + ld hl, SPRITEANIMSTRUCT_FRAMESET_ID + add hl, bc + ld [hl], a + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld l, [hl] + ld h, $0 + add hl, de + ld a, [hl] + ld hl, SPRITEANIMSTRUCT_XOFFSET + add hl, bc + ld [hl], a + ret + +.LetterEntries: + db $00, $10, $20, $30, $40, $50, $60, $70, $80 + +.CaseDelEnd: + db $00, $00, $00, $30, $30, $30, $60, $60, $60 + +.GetDPad: + ld hl, hJoyLast + ld a, [hl] + and D_UP + jr nz, .up + ld a, [hl] + and D_DOWN + jr nz, .down + ld a, [hl] + and D_LEFT + jr nz, .left + ld a, [hl] + and D_RIGHT + jr nz, .right + ret + +.right + call NamingScreen_GetCursorPosition + and a + jr nz, .asm_11e76 + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld a, [hl] + cp $8 + jr nc, .asm_11e73 + inc [hl] + ret + +.asm_11e73 + ld [hl], $0 + ret + +.asm_11e76 + cp $3 + jr nz, .asm_11e7b + xor a +.asm_11e7b + ld e, a + add a + add e + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld [hl], a + ret + +.left + call NamingScreen_GetCursorPosition + and a + jr nz, .asm_11e97 + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld a, [hl] + and a + jr z, .asm_11e94 + dec [hl] + ret + +.asm_11e94 + ld [hl], $8 + ret + +.asm_11e97 + cp $1 + jr nz, .asm_11e9d + ld a, $4 +.asm_11e9d + dec a + dec a + ld e, a + add a + add e + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld [hl], a + ret + +.down + ld hl, SPRITEANIMSTRUCT_0D + add hl, bc + ld a, [hl] + call NamingScreen_IsTargetBox + jr nz, .asm_11eb8 + cp $5 + jr nc, .asm_11ebe + inc [hl] + ret + +.asm_11eb8 + cp $4 + jr nc, .asm_11ebe + inc [hl] + ret + +.asm_11ebe + ld [hl], $0 + ret + +.up + ld hl, SPRITEANIMSTRUCT_0D + add hl, bc + ld a, [hl] + and a + jr z, .asm_11ecb + dec [hl] + ret + +.asm_11ecb + ld [hl], $4 + call NamingScreen_IsTargetBox + ret nz + inc [hl] + ret + +NamingScreen_TryAddCharacter: + ld a, [wNamingScreenLastCharacter] + ld hl, Dakutens + cp "゙" ; $e5 + jr z, asm_11f06 + ld hl, Handakutens + cp "゚" ; $e4 + jr z, asm_11f06 + +MailComposition_TryAddCharacter: + ld a, [wNamingScreenMaxNameLength] + ld c, a + ld a, [wNamingScreenCurNameLength] + cp c + ret nc + + ld a, [wNamingScreenLastCharacter] + +NamingScreen_LoadNextCharacter: + call NamingScreen_GetTextCursorPosition + ld [hl], a + +NamingScreen_AdvanceCursor_CheckEndOfString: + ld hl, wNamingScreenCurNameLength + inc [hl] + call NamingScreen_GetTextCursorPosition + ld a, [hl] + cp "@" + jr z, .end_of_string + ld [hl], NAMINGSCREEN_UNDERLINE + and a + ret + +.end_of_string + scf + ret + +asm_11f06: + ld a, [wNamingScreenCurNameLength] + and a + ret z + push hl + ld hl, wNamingScreenCurNameLength + dec [hl] + call NamingScreen_GetTextCursorPosition + ld c, [hl] + pop hl + +.loop + ld a, [hli] + cp $ff + jr z, NamingScreen_AdvanceCursor_CheckEndOfString + cp c + jr z, .done + inc hl + jr .loop + +.done + ld a, [hl] + jr NamingScreen_LoadNextCharacter + +INCLUDE "data/text/dakutens.asm" + +NamingScreen_DeleteCharacter: + ld hl, wNamingScreenCurNameLength + ld a, [hl] + and a + ret z + dec [hl] + call NamingScreen_GetTextCursorPosition + ld [hl], NAMINGSCREEN_UNDERLINE + inc hl + ld a, [hl] + cp NAMINGSCREEN_UNDERLINE + ret nz + ld [hl], NAMINGSCREEN_MIDDLELINE + ret + +NamingScreen_GetTextCursorPosition: + push af + ld hl, wNamingScreenDestinationPointer + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wNamingScreenCurNameLength] + ld e, a + ld d, 0 + add hl, de + pop af + ret + +NamingScreen_InitNameEntry: +; load NAMINGSCREEN_UNDERLINE, (NAMINGSCREEN_MIDDLELINE * [wNamingScreenMaxNameLength]), "@" into the dw address at wNamingScreenDestinationPointer + ld hl, wNamingScreenDestinationPointer + ld a, [hli] + ld h, [hl] + ld l, a + ld [hl], NAMINGSCREEN_UNDERLINE + inc hl + ld a, [wNamingScreenMaxNameLength] + dec a + ld c, a + ld a, NAMINGSCREEN_MIDDLELINE +.loop + ld [hli], a + dec c + jr nz, .loop + ld [hl], "@" + ret + +NamingScreen_StoreEntry: + ld hl, wNamingScreenDestinationPointer + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wNamingScreenMaxNameLength] + ld c, a +.loop + ld a, [hl] + cp NAMINGSCREEN_MIDDLELINE + jr z, .terminator + cp NAMINGSCREEN_UNDERLINE + jr nz, .not_terminator +.terminator + ld [hl], "@" +.not_terminator + inc hl + dec c + jr nz, .loop + ret + +NamingScreen_GetLastCharacter: + ld hl, wNamingScreenCursorObjectPointer + ld c, [hl] + inc hl + ld b, [hl] + ld hl, SPRITEANIMSTRUCT_XOFFSET + add hl, bc + ld a, [hl] + ld hl, SPRITEANIMSTRUCT_XCOORD + add hl, bc + add [hl] + sub $8 + srl a + srl a + srl a + ld e, a + ld hl, SPRITEANIMSTRUCT_YOFFSET + add hl, bc + ld a, [hl] + ld hl, SPRITEANIMSTRUCT_YCOORD + add hl, bc + add [hl] + sub $10 + srl a + srl a + srl a + ld d, a + hlcoord 0, 0 + ld bc, SCREEN_WIDTH +.loop + ld a, d + and a + jr z, .done + add hl, bc + dec d + jr .loop + +.done + add hl, de + ld a, [hl] + ld [wNamingScreenLastCharacter], a + ret + +LoadNamingScreenGFX: + call ClearSprites + callfar ClearSpriteAnims + call LoadStandardFont + call LoadFontsExtra + + ld de, NamingScreenGFX_MiddleLine + ld hl, vTiles0 tile NAMINGSCREEN_MIDDLELINE + lb bc, BANK(NamingScreenGFX_MiddleLine), 1 + call Get1bpp + + ld de, NamingScreenGFX_UnderLine + ld hl, vTiles0 tile NAMINGSCREEN_UNDERLINE + lb bc, BANK(NamingScreenGFX_UnderLine), 1 + call Get1bpp + + ld de, vTiles2 tile NAMINGSCREEN_BORDER + ld hl, NamingScreenGFX_Border + ld bc, 1 tiles + ld a, BANK(NamingScreenGFX_Border) + call FarCopyBytes + + ld de, vTiles0 tile NAMINGSCREEN_CURSOR + ld hl, NamingScreenGFX_Cursor + ld bc, 2 tiles + ld a, BANK(NamingScreenGFX_Cursor) + call FarCopyBytes + + ld a, $5 + ld hl, wSpriteAnimDict + 9 * 2 + ld [hli], a + ld [hl], NAMINGSCREEN_CURSOR + xor a + ldh [hSCY], a + ld [wGlobalAnimYOffset], a + ldh [hSCX], a + ld [wGlobalAnimXOffset], a + ld [wJumptableIndex], a + ld [wNamingScreenLetterCase], a + ldh [hBGMapMode], a + ld [wNamingScreenCurNameLength], a + ld a, $7 + ldh [hWX], a + ret + +NamingScreenGFX_Border: +INCBIN "gfx/naming_screen/border.2bpp" + +NamingScreenGFX_Cursor: +INCBIN "gfx/naming_screen/cursor.2bpp" + +INCLUDE "data/text/name_input_chars.asm" + +NamingScreenGFX_End: ; unused +INCBIN "gfx/naming_screen/end.1bpp" + +NamingScreenGFX_MiddleLine: +INCBIN "gfx/naming_screen/middle_line.1bpp" + +NamingScreenGFX_UnderLine: +INCBIN "gfx/naming_screen/underline.1bpp" + +_ComposeMailMessage: + ld hl, wNamingScreenDestinationPointer + ld [hl], e + inc hl + ld [hl], d + ldh a, [hMapAnims] + push af + xor a + ldh [hMapAnims], a + ldh a, [hInMenu] + push af + ld a, $1 + ldh [hInMenu], a + call .InitBlankMail + call DelayFrame + +.loop + call .DoMailEntry + jr nc, .loop + + pop af + ldh [hInMenu], a + pop af + ldh [hMapAnims], a + ret + +.InitBlankMail: + call ClearBGPalettes + call DisableLCD + call LoadNamingScreenGFX + ld de, vTiles0 tile $00 + ld hl, .MailIcon + ld bc, 8 tiles + ld a, BANK(.MailIcon) + call FarCopyBytes + xor a + ld hl, wSpriteAnimDict + ld [hli], a + ld [hl], a + + ; init mail icon + depixel 3, 2 + ld a, SPRITE_ANIM_INDEX_PARTY_MON + call InitSpriteAnimStruct + + ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID + add hl, bc + ld [hl], $0 + call .InitCharset + ld a, LCDC_DEFAULT + ldh [rLCDC], a + call .initwNamingScreenMaxNameLength + ld b, SCGB_DIPLOMA + call GetSGBLayout + call WaitBGMap + call WaitTop + ld a, %11100100 + call DmgToCgbBGPals + ld a, %11100100 + call DmgToCgbObjPal0 + call NamingScreen_InitNameEntry + ld hl, wNamingScreenDestinationPointer + ld e, [hl] + inc hl + ld d, [hl] + ld hl, MAIL_LINE_LENGTH + add hl, de + ld [hl], "<NEXT>" + ret + +.MailIcon: +INCBIN "gfx/icons/mail_big.2bpp" + +.initwNamingScreenMaxNameLength + ld a, MAIL_MSG_LENGTH + 1 + ld [wNamingScreenMaxNameLength], a + ret + +.UnusedString11f7a: + db "メールを かいてね@" + +.InitCharset: + call WaitTop + hlcoord 0, 0 + ld bc, 6 * SCREEN_WIDTH + ld a, NAMINGSCREEN_BORDER + call ByteFill + hlcoord 0, 6 + ld bc, 12 * SCREEN_WIDTH + ld a, " " + call ByteFill + hlcoord 1, 1 + lb bc, 4, SCREEN_WIDTH - 2 + call ClearBox + ld de, MailEntry_Uppercase + +.PlaceMailCharset: + hlcoord 1, 7 + ld b, 6 +.next + ld c, SCREEN_WIDTH - 1 +.loop_ + ld a, [de] + ld [hli], a + inc de + dec c + jr nz, .loop_ + push de + ld de, SCREEN_WIDTH + 1 + add hl, de + pop de + dec b + jr nz, .next + ret + +.DoMailEntry: + call JoyTextDelay + ld a, [wJumptableIndex] + bit 7, a + jr nz, .exit_mail + call .DoJumptable + farcall PlaySpriteAnimationsAndDelayFrame + call .Update + call DelayFrame + and a + ret + +.exit_mail + callfar ClearSpriteAnims + call ClearSprites + xor a + ldh [hSCX], a + ldh [hSCY], a + scf + ret + +.Update: + xor a + ldh [hBGMapMode], a + hlcoord 1, 1 + lb bc, 4, 18 + call ClearBox + ld hl, wNamingScreenDestinationPointer + ld e, [hl] + inc hl + ld d, [hl] + hlcoord 2, 2 + call PlaceString + ld a, $1 + ldh [hBGMapMode], a + ret + +.DoJumptable: + ld a, [wJumptableIndex] + ld e, a + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.Jumptable: + dw .init_blinking_cursor + dw .process_joypad + +.init_blinking_cursor + depixel 9, 2 + ld a, SPRITE_ANIM_INDEX_COMPOSE_MAIL_CURSOR + call InitSpriteAnimStruct + ld a, c + ld [wNamingScreenCursorObjectPointer], a + ld a, b + ld [wNamingScreenCursorObjectPointer + 1], a + ld hl, SPRITEANIMSTRUCT_FRAMESET_ID + add hl, bc + ld a, [hl] + ld hl, SPRITEANIMSTRUCT_0E + add hl, bc + ld [hl], a + ld hl, wJumptableIndex + inc [hl] + ret + +.process_joypad + ld hl, hJoyPressed + ld a, [hl] + and A_BUTTON + jr nz, .a + ld a, [hl] + and B_BUTTON + jr nz, .b + ld a, [hl] + and START + jr nz, .start + ld a, [hl] + and SELECT + jr nz, .select + ret + +.a + call NamingScreen_PressedA_GetCursorCommand + cp $1 + jr z, .select + cp $2 + jr z, .b + cp $3 + jr z, .finished + call NamingScreen_GetLastCharacter + call MailComposition_TryAddLastCharacter + jr c, .start + ld hl, wNamingScreenCurNameLength + ld a, [hl] + cp MAIL_LINE_LENGTH + ret nz + inc [hl] + call NamingScreen_GetTextCursorPosition + ld [hl], NAMINGSCREEN_UNDERLINE + dec hl + ld [hl], "<NEXT>" + ret + +.start + ld hl, wNamingScreenCursorObjectPointer + ld c, [hl] + inc hl + ld b, [hl] + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld [hl], $9 + ld hl, SPRITEANIMSTRUCT_0D + add hl, bc + ld [hl], $5 + ret + +.b + call NamingScreen_DeleteCharacter + ld hl, wNamingScreenCurNameLength + ld a, [hl] + cp MAIL_LINE_LENGTH + ret nz + dec [hl] + call NamingScreen_GetTextCursorPosition + ld [hl], NAMINGSCREEN_UNDERLINE + inc hl + ld [hl], "<NEXT>" + ret + +.finished + call NamingScreen_StoreEntry + ld hl, wJumptableIndex + set 7, [hl] + ret + +.select + ld hl, wNamingScreenLetterCase + ld a, [hl] + xor 1 + ld [hl], a + jr nz, .switch_to_lowercase + ld de, MailEntry_Uppercase + call .PlaceMailCharset + ret + +.switch_to_lowercase + ld de, MailEntry_Lowercase + call .PlaceMailCharset + ret + +; called from engine/sprite_anims.asm + +ComposeMail_AnimateCursor: + call .GetDPad + ld hl, SPRITEANIMSTRUCT_0D + add hl, bc + ld a, [hl] + ld e, a + swap e + ld hl, SPRITEANIMSTRUCT_YOFFSET + add hl, bc + ld [hl], e + cp $5 + ld de, .LetterEntries + ld a, 0 + jr nz, .got_pointer + ld de, .CaseDelEnd + ld a, 1 +.got_pointer + ld hl, SPRITEANIMSTRUCT_0E + add hl, bc + add [hl] + ld hl, SPRITEANIMSTRUCT_FRAMESET_ID + add hl, bc + ld [hl], a + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld l, [hl] + ld h, 0 + add hl, de + ld a, [hl] + ld hl, SPRITEANIMSTRUCT_XOFFSET + add hl, bc + ld [hl], a + ret + +.LetterEntries: + db $00, $10, $20, $30, $40, $50, $60, $70, $80, $90 + +.CaseDelEnd: + db $00, $00, $00, $30, $30, $30, $60, $60, $60, $60 + +.GetDPad: + ld hl, hJoyLast + ld a, [hl] + and D_UP + jr nz, .up + ld a, [hl] + and D_DOWN + jr nz, .down + ld a, [hl] + and D_LEFT + jr nz, .left + ld a, [hl] + and D_RIGHT + jr nz, .right + ret + +.right + call ComposeMail_GetCursorPosition + and a + jr nz, .case_del_done_right + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld a, [hl] + cp $9 + jr nc, .wrap_around_letter_right + inc [hl] + ret + +.wrap_around_letter_right + ld [hl], $0 + ret + +.case_del_done_right + cp $3 + jr nz, .wrap_around_command_right + xor a +.wrap_around_command_right + ld e, a + add a + add e + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld [hl], a + ret + +.left + call ComposeMail_GetCursorPosition + and a + jr nz, .caps_del_done_left + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld a, [hl] + and a + jr z, .wrap_around_letter_left + dec [hl] + ret + +.wrap_around_letter_left + ld [hl], $9 + ret + +.caps_del_done_left + cp $1 + jr nz, .wrap_around_command_left + ld a, $4 +.wrap_around_command_left + dec a + dec a + ld e, a + add a + add e + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld [hl], a + ret + +.down + ld hl, SPRITEANIMSTRUCT_0D + add hl, bc + ld a, [hl] + cp $5 + jr nc, .wrap_around_down + inc [hl] + ret + +.wrap_around_down + ld [hl], $0 + ret + +.up + ld hl, SPRITEANIMSTRUCT_0D + add hl, bc + ld a, [hl] + and a + jr z, .wrap_around_up + dec [hl] + ret + +.wrap_around_up + ld [hl], $5 + ret + +NamingScreen_PressedA_GetCursorCommand: + ld hl, wNamingScreenCursorObjectPointer + ld c, [hl] + inc hl + ld b, [hl] + +ComposeMail_GetCursorPosition: + ld hl, SPRITEANIMSTRUCT_0D + add hl, bc + ld a, [hl] + cp $5 + jr nz, .letter + ld hl, SPRITEANIMSTRUCT_0C + add hl, bc + ld a, [hl] + cp $3 + jr c, .case + cp $6 + jr c, .del + ld a, $3 + ret + +.case + ld a, $1 + ret + +.del + ld a, $2 + ret + +.letter + xor a + ret + +MailComposition_TryAddLastCharacter: + ld a, [wNamingScreenLastCharacter] + ld hl, Dakutens + cp "゙" ; $e5 + jr z, .asm_1258b + ld hl, Handakutens + cp "゚" ; $e4 + jp nz, MailComposition_TryAddCharacter + +.asm_1258b + ld a, [wNamingScreenCurNameLength] + and a + ret z + cp $11 + jr nz, .asm_1259c + push hl + ld hl, wNamingScreenCurNameLength + dec [hl] + dec [hl] + jr .asm_125a1 + +.asm_1259c + push hl + ld hl, wNamingScreenCurNameLength + dec [hl] + +.asm_125a1 + call NamingScreen_GetTextCursorPosition + ld c, [hl] + pop hl +.asm_125a6 + ld a, [hli] + cp $ff + jp z, NamingScreen_AdvanceCursor_CheckEndOfString + cp c + jr z, .asm_125b2 + inc hl + jr .asm_125a6 + +.asm_125b2 + ld a, [hl] + jp NamingScreen_LoadNextCharacter + +INCLUDE "data/text/mail_input_chars.asm" diff --git a/engine/menus/save.asm b/engine/menus/save.asm new file mode 100644 index 00000000..f8207204 --- /dev/null +++ b/engine/menus/save.asm @@ -0,0 +1,1092 @@ +SaveMenu: + call LoadStandardMenuHeader + lb de, 4, 0 + farcall DisplayNormalContinueData + call SpeechTextbox + call UpdateSprites + farcall SaveMenu_CopyTilemapAtOnce + ld hl, WouldYouLikeToSaveTheGameText + call SaveTheGame_yesorno + jr nz, .refused + call AskOverwriteSaveFile + jr c, .refused + call PauseGameLogic + call SavingDontTurnOffThePower + call ResumeGameLogic + call ExitMenu + and a + ret + +.refused + call ExitMenu + call ReloadPalettes + farcall SaveMenu_CopyTilemapAtOnce + scf + ret + +SaveAfterLinkTrade: + call PauseGameLogic + farcall StageRTCTimeForSave + farcall BackupMysteryGift + call SavePokemonData + call SaveChecksum + call SaveBackupPokemonData + call SaveBackupChecksum + farcall BackupPartyMonMail + farcall SaveRTC + call ResumeGameLogic + ret + +ChangeBoxSaveGame: + push de + ld hl, ChangeBoxSaveText + call MenuTextbox + call YesNoBox + call ExitMenu + jr c, .refused + call AskOverwriteSaveFile + jr c, .refused + call PauseGameLogic + call SaveBox + pop de + ld a, e + ld [wCurBox], a + call LoadBox + call SavingDontTurnOffThePower + call ResumeGameLogic + and a + ret +.refused + pop de + ret + +Link_SaveGame: + call AskOverwriteSaveFile + jr c, .refused + call PauseGameLogic + call SavingDontTurnOffThePower + call ResumeGameLogic + and a + +.refused + ret + +MoveMonWOMail_SaveGame: + call PauseGameLogic + push de + call SaveBox + pop de + ld a, e + ld [wCurBox], a + call LoadBox + call ResumeGameLogic + ret + +MoveMonWOMail_InsertMon_SaveGame: + call PauseGameLogic + push de + call SaveBox + pop de + ld a, e + ld [wCurBox], a + ld a, TRUE + ld [wSaveFileExists], a + farcall StageRTCTimeForSave + farcall BackupMysteryGift + call ValidateSave + call SaveOptions + call SavePlayerData + call SavePokemonData + call SaveChecksum + call ValidateBackupSave + call SaveBackupOptions + call SaveBackupPlayerData + call SaveBackupPokemonData + call SaveBackupChecksum + farcall BackupPartyMonMail + farcall SaveRTC + call LoadBox + call ResumeGameLogic + ld de, SFX_SAVE + call PlaySFX + ld c, 24 + call DelayFrames + ret + +StartMoveMonWOMail_SaveGame: + ld hl, MoveMonWOMailSaveText + call MenuTextbox + call YesNoBox + call ExitMenu + jr c, .refused + call AskOverwriteSaveFile + jr c, .refused + call PauseGameLogic + call SavingDontTurnOffThePower + call ResumeGameLogic + and a + ret + +.refused + scf + ret + +PauseGameLogic: + ld a, TRUE + ld [wGameLogicPaused], a + ret + +ResumeGameLogic: + xor a ; FALSE + ld [wGameLogicPaused], a + ret + +AddHallOfFameEntry: + ld a, BANK(sHallOfFame) + call OpenSRAM + ld hl, sHallOfFame + HOF_LENGTH * (NUM_HOF_TEAMS - 1) - 1 + ld de, sHallOfFame + HOF_LENGTH * NUM_HOF_TEAMS - 1 + ld bc, HOF_LENGTH * (NUM_HOF_TEAMS - 1) +.loop + ld a, [hld] + ld [de], a + dec de + dec bc + ld a, c + or b + jr nz, .loop + ld hl, wHallOfFamePokemonList + ld de, sHallOfFame + ld bc, wHallOfFamePokemonListEnd - wHallOfFamePokemonList + 1 + call CopyBytes + call CloseSRAM + ret + +SaveGameData: + call _SaveGameData + ret + +AskOverwriteSaveFile: + ld a, [wSaveFileExists] + and a + jr z, .erase + call CompareLoadedAndSavedPlayerID + jr z, .yoursavefile + ld hl, AnotherSaveFileText + call SaveTheGame_yesorno + jr nz, .refused + jr .erase + +.yoursavefile + ld hl, AlreadyASaveFileText + call SaveTheGame_yesorno + jr nz, .refused + jr .ok + +.erase + call ErasePreviousSave + +.ok + and a + ret + +.refused + scf + ret + +SaveTheGame_yesorno: + ld b, BANK(WouldYouLikeToSaveTheGameText) + call MapTextbox + call LoadMenuTextbox + lb bc, 0, 7 + call PlaceYesNoBox + ld a, [wMenuCursorY] + dec a + call CloseWindow + push af + call ReloadPalettes + pop af + and a + ret + +CompareLoadedAndSavedPlayerID: + ld a, BANK(sPlayerData) + call OpenSRAM + ld hl, sPlayerData + (wPlayerID - wPlayerData) + ld a, [hli] + ld c, [hl] + ld b, a + call CloseSRAM + ld a, [wPlayerID] + cp b + ret nz + ld a, [wPlayerID + 1] + cp c + ret + +SavingDontTurnOffThePower: + ; Prevent joypad interrupts + xor a + ldh [hJoypadReleased], a + ldh [hJoypadPressed], a + ldh [hJoypadSum], a + ldh [hJoypadDown], a + ; Save the text speed setting to the stack + ld a, [wOptions] + push af + ; Set the text speed to medium + ld a, TEXT_DELAY_MED + ld [wOptions], a + ; SAVING... DON'T TURN OFF THE POWER. + ld hl, SavingDontTurnOffThePowerText + call PrintText + ; Restore the text speed setting + pop af + ld [wOptions], a + ; Wait for 16 frames + ld c, 16 + call DelayFrames + call _SaveGameData + ; wait 32 frames + ld c, 32 + call DelayFrames + ; copy the original text speed setting to the stack + ld a, [wOptions] + push af + ; set text speed to medium + ld a, TEXT_DELAY_MED + ld [wOptions], a + ; <PLAYER> saved the game! + ld hl, SavedTheGameText + call PrintText + ; restore the original text speed setting + pop af + ld [wOptions], a + ld de, SFX_SAVE + call WaitPlaySFX + call WaitSFX + ; wait 30 frames + ld c, 30 + call DelayFrames + ret + +_SaveGameData: + ld a, TRUE + ld [wSaveFileExists], a + farcall StageRTCTimeForSave + farcall BackupMysteryGift + call ValidateSave + call SaveOptions + call SavePlayerData + call SavePokemonData + call SaveBox + call SaveChecksum + call ValidateBackupSave + call SaveBackupOptions + call SaveBackupPlayerData + call SaveBackupPokemonData + call SaveBackupChecksum + call UpdateStackTop + farcall BackupPartyMonMail + farcall SaveRTC + ret + +UpdateStackTop: +; sStackTop appears to be unused. +; It could have been used to debug stack overflow during saving. + call FindStackTop + ld a, BANK(sStackTop) + call OpenSRAM + ld a, [sStackTop + 0] + ld e, a + ld a, [sStackTop + 1] + ld d, a + or e + jr z, .update + ld a, e + sub l + ld a, d + sbc h + jr c, .done + +.update + ld a, l + ld [sStackTop + 0], a + ld a, h + ld [sStackTop + 1], a + +.done + call CloseSRAM + ret + +FindStackTop: +; Find the furthest point that sp has traversed to. +; This is distinct from the current value of sp. + ld hl, wStackTop - $fc +.loop + ld a, [hl] + or a + ret nz + inc hl + jr .loop + +ErasePreviousSave: + call EraseBoxes + call EraseHallOfFame + call EraseLinkBattleStats + call EraseMysteryGift + ld a, BANK(sStackTop) + call OpenSRAM + xor a + ld [sStackTop + 0], a + ld [sStackTop + 1], a + call CloseSRAM + ld a, $1 + ld [wSavedAtLeastOnce], a + ret + +EraseLinkBattleStats: + ld a, BANK(sLinkBattleStats) + call OpenSRAM + ld hl, sLinkBattleStats + ld bc, sLinkBattleStatsEnd - sLinkBattleStats + xor a + call ByteFill + jp CloseSRAM + +EraseMysteryGift: + ld a, BANK(sBackupMysteryGiftItem) + call OpenSRAM + ld hl, sBackupMysteryGiftItem + ld bc, sBackupMysteryGiftItemEnd - sBackupMysteryGiftItem + xor a + call ByteFill + jp CloseSRAM + +EraseHallOfFame: + ld a, BANK(sHallOfFame) + call OpenSRAM + ld hl, sHallOfFame + ld bc, sHallOfFameEnd - sHallOfFame + xor a + call ByteFill + jp CloseSRAM + +ValidateSave: + ld a, BANK(sCheckValue1) ; aka BANK(sCheckValue2) + call OpenSRAM + ld a, SAVE_CHECK_VALUE_1 + ld [sCheckValue1], a + ld a, SAVE_CHECK_VALUE_2 + ld [sCheckValue2], a + jp CloseSRAM + +SaveOptions: + ld a, BANK(sOptions) + call OpenSRAM + ld hl, wOptions + ld de, sOptions + ld bc, wOptionsEnd - wOptions + call CopyBytes + ld a, [wOptions] + and $ff ^ (1 << NO_TEXT_SCROLL) + ld [sOptions], a + jp CloseSRAM + +SavePlayerData: + ld a, BANK(sPlayerData) + call OpenSRAM + ld hl, wPlayerData + ld de, sPlayerData + ld bc, wPlayerDataEnd - wPlayerData + call CopyBytes + ld hl, wCurMapData + ld de, sCurMapData + ld bc, wCurMapDataEnd - wCurMapData + call CopyBytes + jp CloseSRAM + +SavePokemonData: + ld a, BANK(sPokemonData) + call OpenSRAM + ld hl, wPokemonData + ld de, sPokemonData + ld bc, wPokemonDataEnd - wPokemonData + call CopyBytes + call CloseSRAM + ret + +SaveBox: + call GetBoxAddress + call SaveBoxAddress + ret + +SaveChecksum: + ld hl, sGameData + ld bc, sGameDataEnd - sGameData + ld a, BANK(sGameData) + call OpenSRAM + call Checksum + ld a, e + ld [sChecksum + 0], a + ld a, d + ld [sChecksum + 1], a + call CloseSRAM + ret + +ValidateBackupSave: + ld a, BANK(sBackupCheckValue1) ; aka BANK(sBackupCheckValue2) + call OpenSRAM + ld a, SAVE_CHECK_VALUE_1 + ld [sBackupCheckValue1], a + ld a, SAVE_CHECK_VALUE_2 + ld [sBackupCheckValue2], a + call CloseSRAM + ret + +SaveBackupOptions: + ld a, BANK(sBackupOptions) + call OpenSRAM + ld hl, wOptions + ld de, sBackupOptions + ld bc, wOptionsEnd - wOptions + call CopyBytes + call CloseSRAM + ret + +SaveBackupPlayerData: + ld a, BANK(sBackupPlayerData3) + call OpenSRAM + ld hl, wPlayerData3 + ld de, sBackupPlayerData3 + ld bc, wPlayerData3End - wPlayerData3 + call CopyBytes + ld a, BANK(sBackupPlayerData1) + call OpenSRAM + ld hl, wPlayerData1 + ld de, sBackupPlayerData1 + ld bc, wPlayerData1End - wPlayerData1 + call CopyBytes + ld a, BANK(sBackupPlayerData2) + call OpenSRAM + ld hl, wPlayerData2 + ld de, sBackupPlayerData2 + ld bc, wPlayerData2End - wPlayerData2 + call CopyBytes + ld a, BANK(sBackupCurMapData) + call OpenSRAM + ld hl, wCurMapData + ld de, sBackupCurMapData + ld bc, wCurMapDataEnd - wCurMapData + call CopyBytes + call CloseSRAM + ret + +SaveBackupPokemonData: + ld a, BANK(sBackupPokemonData) + call OpenSRAM + ld hl, wPokemonData + ld de, sBackupPokemonData + ld bc, wPokemonDataEnd - wPokemonData + call CopyBytes + call CloseSRAM + ret + +SaveBackupChecksum: + ld a, BANK(sBackupPlayerData3) + call OpenSRAM + ld hl, sBackupPlayerData3 + ld bc, wPlayerData3End - wPlayerData3 + call Checksum + push de + ld hl, sBackupPokemonData + ld bc, wPokemonDataEnd - wPokemonData + call Checksum + pop hl + add hl, de + ld a, BANK(sBackupPlayerData1) + call OpenSRAM + push hl + ld hl, sBackupPlayerData1 + ld bc, wPlayerData1End - wPlayerData1 + call Checksum + pop hl + add hl, de + ld a, BANK(sBackupPlayerData2) + call OpenSRAM + push hl + ld hl, sBackupPlayerData2 + ld bc, wPlayerData2End - wPlayerData2 + call Checksum + pop hl + add hl, de + ld a, BANK(sBackupCurMapData) + call OpenSRAM + push hl + ld hl, sBackupCurMapData + ld bc, wCurMapDataEnd - wCurMapData + call Checksum + pop hl + add hl, de + ld a, l + ld [sBackupChecksum + 0], a + ld a, h + ld [sBackupChecksum + 1], a + call CloseSRAM + ret + +TryLoadSaveFile: + call VerifyChecksum + jr nz, .backup + call LoadPlayerData + call LoadPokemonData + call LoadBox + farcall RestorePartyMonMail + farcall RestoreMysteryGift + call ValidateBackupSave + call SaveBackupOptions + call SaveBackupPlayerData + call SaveBackupPokemonData + call SaveBackupChecksum + and a + ret + +.backup + call VerifyBackupChecksum + jr nz, .corrupt + call LoadBackupPlayerData + call LoadBackupPokemonData + call LoadBox + farcall RestorePartyMonMail + farcall RestoreMysteryGift + call ValidateSave + call SaveOptions + call SavePlayerData + call SavePokemonData + call SaveChecksum + and a + ret + +.corrupt + ld a, [wOptions] + push af + set NO_TEXT_SCROLL, a + ld [wOptions], a + ld hl, SaveFileCorruptedText + call PrintText + pop af + ld [wOptions], a + scf + ret + +TryLoadSaveData: + xor a ; FALSE + ld [wSaveFileExists], a + call CheckPrimarySaveFile + ld a, [wSaveFileExists] + and a + jr z, .backup + + ld a, BANK(sPlayerData) + call OpenSRAM + ld hl, sPlayerData + wStartDay - wPlayerData + ld de, wStartDay + ld bc, $e + call CopyBytes + call CloseSRAM + ret + +.backup + call CheckBackupSaveFile + ld a, [wSaveFileExists] + and a + jr z, .corrupt + + ld a, BANK(sBackupPlayerData1) + call OpenSRAM + ld hl, sBackupPlayerData1 + wStartDay - wPlayerData + ld de, wStartDay + ld bc, $e + call CopyBytes + call CloseSRAM + ret + +.corrupt + ld hl, DefaultOptions + ld de, wOptions + ld bc, wOptionsEnd - wOptions + call CopyBytes + call ClearClock + ret + +INCLUDE "data/default_options.asm" + +CheckPrimarySaveFile: + ld a, BANK(sCheckValue1) ; aka BANK(sCheckValue2) + call OpenSRAM + ld a, [sCheckValue1] + cp SAVE_CHECK_VALUE_1 + jr nz, .nope + ld a, [sCheckValue2] + cp SAVE_CHECK_VALUE_2 + jr nz, .nope + ld hl, sOptions + ld de, wOptions + ld bc, wOptionsEnd - wOptions + call CopyBytes + call CloseSRAM + call CheckTextDelay + ld a, TRUE + ld [wSaveFileExists], a + +.nope + call CloseSRAM + ret + +CheckBackupSaveFile: + ld a, BANK(sBackupCheckValue1) ; aka BANK(sBackupCheckValue2) + call OpenSRAM + ld a, [sBackupCheckValue1] + cp SAVE_CHECK_VALUE_1 + jr nz, .nope + ld a, [sBackupCheckValue2] + cp SAVE_CHECK_VALUE_2 + jr nz, .nope + ld hl, sBackupOptions + ld de, wOptions + ld bc, wOptionsEnd - wOptions + call CopyBytes + call CheckTextDelay + ld a, $2 + ld [wSaveFileExists], a + +.nope + call CloseSRAM + ret + +CheckTextDelay: +; Fix options if text delay is invalid + ld hl, wTextboxFlags + res NO_TEXT_DELAY_F, [hl] + ld a, [wOptions] + and TEXT_DELAY_MASK + cp TEXT_DELAY_FAST + ret z + cp TEXT_DELAY_MED + ret z + cp TEXT_DELAY_SLOW + ret z + ld a, [wOptions] + and $ff ^ TEXT_DELAY_MASK + or (1 << FAST_TEXT_DELAY_F) | (1 << NO_TEXT_DELAY_F) + ld [wOptions], a + ret + +LoadPlayerData: + ld a, BANK(sPlayerData) + call OpenSRAM + ld hl, sPlayerData + ld de, wPlayerData + ld bc, wPlayerDataEnd - wPlayerData + call CopyBytes + ld hl, sCurMapData + ld de, wCurMapData + ld bc, wCurMapDataEnd - wCurMapData + call CopyBytes + call CloseSRAM + ret + +LoadPokemonData: + ld a, BANK(sPokemonData) + call OpenSRAM + ld hl, sPokemonData + ld de, wPokemonData + ld bc, wPokemonDataEnd - wPokemonData + call CopyBytes + call CloseSRAM + ret + +LoadBox: + call GetBoxAddress + call LoadBoxAddress + ret + +VerifyChecksum: + ld hl, sGameData + ld bc, sGameDataEnd - sGameData + ld a, BANK(sGameData) + call OpenSRAM + call Checksum + ld a, [sChecksum + 0] + cp e + jr nz, .fail + ld a, [sChecksum + 1] + cp d +.fail + push af + call CloseSRAM + pop af + ret + +LoadBackupPlayerData: + ld a, BANK(sBackupPlayerData3) + call OpenSRAM + ld hl, sBackupPlayerData3 + ld de, wPlayerData3 + ld bc, wPlayerData3End - wPlayerData3 + call CopyBytes + + ld a, BANK(sBackupPlayerData1) + call OpenSRAM + ld hl, sBackupPlayerData1 + ld de, wPlayerData1 + ld bc, wPlayerData1End - wPlayerData1 + call CopyBytes + + ld a, BANK(sBackupPlayerData2) + call OpenSRAM + ld hl, sBackupPlayerData2 + ld de, wPlayerData2 + ld bc, wPlayerData2End - wPlayerData2 + call CopyBytes + + ld a, BANK(sBackupCurMapData) + call OpenSRAM + ld hl, sBackupCurMapData + ld de, wCurMapData + ld bc, wCurMapDataEnd - wCurMapData + call CopyBytes + call CloseSRAM + ret + +LoadBackupPokemonData: + ld a, BANK(sBackupPokemonData) + call OpenSRAM + ld hl, sBackupPokemonData + ld de, wPokemonData + ld bc, wPokemonDataEnd - wPokemonData + call CopyBytes + call CloseSRAM + ret + +VerifyBackupChecksum: + ld a, BANK(sBackupPokemonData) + call OpenSRAM + ld hl, sBackupPokemonData + ld bc, wPokemonDataEnd - wPokemonData + call Checksum + push de + + ld hl, sBackupPlayerData3 + ld bc, wPlayerData3End - wPlayerData3 + call Checksum + pop hl + add hl, de + + ld a, BANK(sBackupPlayerData1) + call OpenSRAM + push hl + ld hl, sBackupPlayerData1 + ld bc, wPlayerData1End - wPlayerData1 + call Checksum + pop hl + add hl, de + + ld a, BANK(sBackupPlayerData2) + call OpenSRAM + push hl + ld hl, sBackupPlayerData2 + ld bc, wPlayerData2End - wPlayerData2 + call Checksum + pop hl + add hl, de + + ld a, BANK(sBackupCurMapData) + call OpenSRAM + push hl + ld hl, sBackupCurMapData + ld bc, wCurMapDataEnd - wCurMapData + call Checksum + pop hl + add hl, de + ld d, h + ld e, l + ld a, [sBackupChecksum + 0] + cp e + jr nz, .fail + ld a, [sBackupChecksum + 1] + cp d +.fail + push af + call CloseSRAM + pop af + ret + +GetBoxAddress: + ld a, [wCurBox] + cp NUM_BOXES + jr c, .ok + xor a + ld [wCurBox], a + +.ok + ld e, a + ld d, 0 + ld hl, BoxAddresses +rept 5 + add hl, de +endr + ld a, [hli] + push af + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + ld a, [hli] + ld h, [hl] + ld l, a + pop af + ret + +SaveBoxAddress: +; Save box via wBoxPartialData. +; We do this in three steps because the size of wBoxPartialData is less than +; the size of sBox. + push hl +; Load the first part of the active box. + push af + push de + ld a, BANK(sBox) + call OpenSRAM + ld hl, sBox + ld de, wBoxPartialData + ld bc, (wBoxPartialDataEnd - wBoxPartialData) + call CopyBytes + call CloseSRAM + pop de + pop af +; Save it to the target box. + push af + push de + call OpenSRAM + ld hl, wBoxPartialData + ld bc, (wBoxPartialDataEnd - wBoxPartialData) + call CopyBytes + call CloseSRAM + +; Load the second part of the active box. + ld a, BANK(sBox) + call OpenSRAM + ld hl, sBox + (wBoxPartialDataEnd - wBoxPartialData) + ld de, wBoxPartialData + ld bc, (wBoxPartialDataEnd - wBoxPartialData) + call CopyBytes + call CloseSRAM + pop de + pop af + + ld hl, (wBoxPartialDataEnd - wBoxPartialData) + add hl, de + ld e, l + ld d, h +; Save it to the next part of the target box. + push af + push de + call OpenSRAM + ld hl, wBoxPartialData + ld bc, (wBoxPartialDataEnd - wBoxPartialData) + call CopyBytes + call CloseSRAM + +; Load the third and final part of the active box. + ld a, BANK(sBox) + call OpenSRAM + ld hl, sBox + (wBoxPartialDataEnd - wBoxPartialData) * 2 + ld de, wBoxPartialData + ld bc, sBoxEnd - (sBox + (wBoxPartialDataEnd - wBoxPartialData) * 2) ; $8e + call CopyBytes + call CloseSRAM + pop de + pop af + + ld hl, (wBoxPartialDataEnd - wBoxPartialData) + add hl, de + ld e, l + ld d, h +; Save it to the final part of the target box. + call OpenSRAM + ld hl, wBoxPartialData + ld bc, sBoxEnd - (sBox + (wBoxPartialDataEnd - wBoxPartialData) * 2) ; $8e + call CopyBytes + call CloseSRAM + + pop hl + ret + +LoadBoxAddress: +; Load box via wBoxPartialData. +; We do this in three steps because the size of wBoxPartialData is less than +; the size of sBox. + push hl + ld l, e + ld h, d +; Load part 1 + push af + push hl + call OpenSRAM + ld de, wBoxPartialData + ld bc, (wBoxPartialDataEnd - wBoxPartialData) + call CopyBytes + call CloseSRAM + ld a, BANK(sBox) + call OpenSRAM + ld hl, wBoxPartialData + ld de, sBox + ld bc, (wBoxPartialDataEnd - wBoxPartialData) + call CopyBytes + call CloseSRAM + pop hl + pop af + + ld de, (wBoxPartialDataEnd - wBoxPartialData) + add hl, de +; Load part 2 + push af + push hl + call OpenSRAM + ld de, wBoxPartialData + ld bc, (wBoxPartialDataEnd - wBoxPartialData) + call CopyBytes + call CloseSRAM + ld a, BANK(sBox) + call OpenSRAM + ld hl, wBoxPartialData + ld de, sBox + (wBoxPartialDataEnd - wBoxPartialData) + ld bc, (wBoxPartialDataEnd - wBoxPartialData) + call CopyBytes + call CloseSRAM + pop hl + pop af +; Load part 3 + ld de, (wBoxPartialDataEnd - wBoxPartialData) + add hl, de + call OpenSRAM + ld de, wBoxPartialData + ld bc, sBoxEnd - (sBox + (wBoxPartialDataEnd - wBoxPartialData) * 2) ; $8e + call CopyBytes + call CloseSRAM + ld a, BANK(sBox) + call OpenSRAM + ld hl, wBoxPartialData + ld de, sBox + (wBoxPartialDataEnd - wBoxPartialData) * 2 + ld bc, sBoxEnd - (sBox + (wBoxPartialDataEnd - wBoxPartialData) * 2) ; $8e + call CopyBytes + call CloseSRAM + + pop hl + ret + +EraseBoxes: + ld hl, BoxAddresses + ld c, NUM_BOXES +.next + push bc + ld a, [hli] + call OpenSRAM + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + xor a + ld [de], a + inc de + ld a, -1 + ld [de], a + inc de + ld bc, sBoxEnd - (sBox + 2) +.clear + xor a + ld [de], a + inc de + dec bc + ld a, b + or c + jr nz, .clear + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + ld a, -1 + ld [de], a + inc de + xor a + ld [de], a + call CloseSRAM + pop bc + dec c + jr nz, .next + ret + +BoxAddresses: +; dbww bank, address, address + dbww BANK(sBox1), sBox1, sBox1End + dbww BANK(sBox2), sBox2, sBox2End + dbww BANK(sBox3), sBox3, sBox3End + dbww BANK(sBox4), sBox4, sBox4End + dbww BANK(sBox5), sBox5, sBox5End + dbww BANK(sBox6), sBox6, sBox6End + dbww BANK(sBox7), sBox7, sBox7End + dbww BANK(sBox8), sBox8, sBox8End + dbww BANK(sBox9), sBox9, sBox9End + dbww BANK(sBox10), sBox10, sBox10End + dbww BANK(sBox11), sBox11, sBox11End + dbww BANK(sBox12), sBox12, sBox12End + dbww BANK(sBox13), sBox13, sBox13End + dbww BANK(sBox14), sBox14, sBox14End + +Checksum: + ld de, 0 +.loop + ld a, [hli] + add e + ld e, a + ld a, 0 + adc d + ld d, a + dec bc + ld a, b + or c + jr nz, .loop + ret + +WouldYouLikeToSaveTheGameText: + text_far _WouldYouLikeToSaveTheGameText + text_end + +SavingDontTurnOffThePowerText: + text_far _SavingDontTurnOffThePowerText + text_end + +SavedTheGameText: + text_far _SavedTheGameText + text_end + +AlreadyASaveFileText: + text_far _AlreadyASaveFileText + text_end + +AnotherSaveFileText: + text_far _AnotherSaveFileText + text_end + +SaveFileCorruptedText: + text_far _SaveFileCorruptedText + text_end + +ChangeBoxSaveText: + text_far _ChangeBoxSaveText + text_end + +MoveMonWOMailSaveText: + text_far _MoveMonWOMailSaveText + text_end diff --git a/engine/menus/scrolling_menu.asm b/engine/menus/scrolling_menu.asm new file mode 100644 index 00000000..f051e71c --- /dev/null +++ b/engine/menus/scrolling_menu.asm @@ -0,0 +1,519 @@ +_InitScrollingMenu:: + xor a + ld [wMenuJoypad], a + ldh [hBGMapMode], a + inc a + ldh [hInMenu], a + call InitScrollingMenuCursor + call ScrollingMenu_InitFlags + call ScrollingMenu_ValidateSwitchItem + call ScrollingMenu_InitDisplay + call ApplyTilemap + xor a + ldh [hBGMapMode], a + ret + +_ScrollingMenu:: +.loop + call ScrollingMenuJoyAction + jp c, .exit + call z, .zero + jr .loop + +.exit + call MenuClickSound + ld [wMenuJoypad], a + ld a, 0 + ldh [hInMenu], a + ret + +.zero + call ScrollingMenu_InitDisplay + ld a, 1 + ldh [hBGMapMode], a + ld c, 3 + call DelayFrames + xor a + ldh [hBGMapMode], a + ret + +ScrollingMenu_InitDisplay: + xor a + ldh [hBGMapMode], a + ld hl, wOptions + ld a, [hl] + push af + set NO_TEXT_SCROLL, [hl] + call ScrollingMenu_UpdateDisplay + call ScrollingMenu_PlaceCursor + call ScrollingMenu_CheckCallFunction3 + pop af + ld [wOptions], a + ret + +ScrollingMenuJoyAction: +.loop + call ScrollingMenuJoypad + ldh a, [hJoyLast] + and D_PAD + ld b, a + ldh a, [hJoyPressed] + and BUTTONS + or b + bit A_BUTTON_F, a + jp nz, .a_button + bit B_BUTTON_F, a + jp nz, .b_button + bit SELECT_F, a + jp nz, .select + bit START_F, a + jp nz, .start + bit D_RIGHT_F, a + jp nz, .d_right + bit D_LEFT_F, a + jp nz, .d_left + bit D_UP_F, a + jp nz, .d_up + bit D_DOWN_F, a + jp nz, .d_down + jr .loop + +.unreferenced ; unused + ld a, -1 + and a + ret + +.a_button + call PlaceHollowCursor + ld a, [wMenuCursorY] + dec a + call ScrollingMenu_GetListItemCoordAndFunctionArgs + ld a, [wMenuSelection] + ld [wCurItem], a + ld a, [wMenuSelectionQuantity] + ld [wItemQuantityBuffer], a + call ScrollingMenu_GetCursorPosition + dec a + ld [wScrollingMenuCursorPosition], a + ld [wCurItemQuantity], a + ld a, [wMenuSelection] + cp -1 + jr z, .b_button + ld a, A_BUTTON + scf + ret + +.b_button + ld a, B_BUTTON + scf + ret + +.select + ld a, [wMenuDataFlags] + bit 7, a + jp z, xor_a_dec_a + ld a, [wMenuCursorY] + dec a + call ScrollingMenu_GetListItemCoordAndFunctionArgs + ld a, [wMenuSelection] + cp -1 + jp z, xor_a_dec_a + call ScrollingMenu_GetCursorPosition + dec a + ld [wScrollingMenuCursorPosition], a + ld a, SELECT + scf + ret + +.start + ld a, [wMenuDataFlags] + bit 6, a + jp z, xor_a_dec_a + ld a, START + scf + ret + +.d_left + ld hl, w2DMenuFlags2 + bit 7, [hl] + jp z, xor_a_dec_a + ld a, [wMenuDataFlags] + bit 3, a + jp z, xor_a_dec_a + ld a, D_LEFT + scf + ret + +.d_right + ld hl, w2DMenuFlags2 + bit 7, [hl] + jp z, xor_a_dec_a + ld a, [wMenuDataFlags] + bit 2, a + jp z, xor_a_dec_a + ld a, D_RIGHT + scf + ret + +.d_up + ld hl, w2DMenuFlags2 + bit 7, [hl] + jp z, xor_a + ld hl, wMenuScrollPosition + ld a, [hl] + and a + jr z, .xor_dec_up + dec [hl] + jp xor_a + +.xor_dec_up + jp xor_a_dec_a + +.d_down + ld hl, w2DMenuFlags2 + bit 7, [hl] + jp z, xor_a + ld hl, wMenuScrollPosition + ld a, [wMenuData_ScrollingMenuHeight] + add [hl] + ld b, a + ld a, [wScrollingMenuListSize] + cp b + jr c, .xor_dec_down + inc [hl] + jp xor_a + +.xor_dec_down + jp xor_a_dec_a + +ScrollingMenu_GetCursorPosition: + ld a, [wMenuScrollPosition] + ld c, a + ld a, [wMenuCursorY] + add c + ld c, a + ret + +ScrollingMenu_ClearLeftColumn: + call MenuBoxCoord2Tile + ld de, SCREEN_WIDTH + add hl, de + ld de, 2 * SCREEN_WIDTH + ld a, [wMenuData_ScrollingMenuHeight] +.loop + ld [hl], " " + add hl, de + dec a + jr nz, .loop + ret + +InitScrollingMenuCursor: + ld hl, wMenuData_ItemsPointerAddr + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wMenuData_ItemsPointerBank] + call GetFarByte + ld [wScrollingMenuListSize], a + ld a, [wMenuData_ScrollingMenuHeight] + ld c, a + ld a, [wMenuScrollPosition] + add c + ld c, a + ld a, [wScrollingMenuListSize] + inc a + cp c + jr nc, .skip + ld a, [wMenuData_ScrollingMenuHeight] + ld c, a + ld a, [wScrollingMenuListSize] + inc a + sub c + jr nc, .store + xor a + +.store + ld [wMenuScrollPosition], a + +.skip + ld a, [wMenuScrollPosition] + ld c, a + ld a, [wMenuCursorBuffer] + add c + ld b, a + ld a, [wScrollingMenuListSize] + inc a + cp b + jr c, .wrap + jr nc, .done + +.wrap + xor a + ld [wMenuScrollPosition], a + ld a, $1 + ld [wMenuCursorBuffer], a + +.done + ret + +ScrollingMenu_InitFlags: + ld a, [wMenuDataFlags] + ld c, a + ld a, [wScrollingMenuListSize] + ld b, a + ld a, [wMenuBorderTopCoord] + add 1 + ld [w2DMenuCursorInitY], a + ld a, [wMenuBorderLeftCoord] + add 0 + ld [w2DMenuCursorInitX], a + ld a, [wMenuData_ScrollingMenuHeight] + cp b + jr c, .no_extra_row + jr z, .no_extra_row + ld a, b + inc a +.no_extra_row + ld [w2DMenuNumRows], a + ld a, 1 + ld [w2DMenuNumCols], a + ld a, $8c + bit 2, c + jr z, .skip_set_0 + set 0, a + +.skip_set_0 + bit 3, c + jr z, .skip_set_1 + set 1, a + +.skip_set_1 + ld [w2DMenuFlags1], a + xor a + ld [w2DMenuFlags2], a + ld a, $20 + ld [w2DMenuCursorOffsets], a + ld a, A_BUTTON | B_BUTTON | D_UP | D_DOWN + bit 7, c + jr z, .disallow_select + add SELECT + +.disallow_select + bit 6, c + jr z, .disallow_start + add START + +.disallow_start + ld [wMenuJoypadFilter], a + ld a, [w2DMenuNumRows] + ld b, a + ld a, [wMenuCursorBuffer] + and a + jr z, .reset_cursor + cp b + jr z, .cursor_okay + jr c, .cursor_okay + +.reset_cursor + ld a, 1 + +.cursor_okay + ld [wMenuCursorY], a + ld a, 1 + ld [wMenuCursorX], a + xor a + ld [wCursorCurrentTile], a + ld [wCursorCurrentTile + 1], a + ld [wCursorOffCharacter], a + ret + +ScrollingMenu_ValidateSwitchItem: + ld a, [wScrollingMenuListSize] + ld c, a + ld a, [wSwitchItem] + and a + jr z, .done + dec a + cp c + jr c, .done + xor a + ld [wSwitchItem], a + +.done + ret + +ScrollingMenu_UpdateDisplay: + call ClearWholeMenuBox + ld a, [wMenuDataFlags] + bit 4, a ; place arrows + jr z, .okay + ld a, [wMenuScrollPosition] + and a + jr z, .okay + ld a, [wMenuBorderTopCoord] + ld b, a + ld a, [wMenuBorderRightCoord] + ld c, a + call Coord2Tile + ld [hl], "▲" + +.okay + call MenuBoxCoord2Tile + ld bc, SCREEN_WIDTH + 1 + add hl, bc + ld a, [wMenuData_ScrollingMenuHeight] + ld b, a + ld c, $0 +.loop + ld a, [wMenuScrollPosition] + add c + ld [wScrollingMenuCursorPosition], a + ld a, c + call ScrollingMenu_GetListItemCoordAndFunctionArgs + ld a, [wMenuSelection] + cp -1 + jr z, .cancel + push bc + push hl + call ScrollingMenu_CallFunctions1and2 + pop hl + ld bc, 2 * SCREEN_WIDTH + add hl, bc + pop bc + inc c + ld a, c + cp b + jr nz, .loop + ld a, [wMenuDataFlags] + bit 4, a ; place arrows + jr z, .done + ld a, [wMenuBorderBottomCoord] + ld b, a + ld a, [wMenuBorderRightCoord] + ld c, a + call Coord2Tile + ld [hl], "▼" + +.done + ret + +.cancel + ld a, [wMenuDataFlags] + bit 0, a ; call function on cancel + jr nz, .call_function + ld de, .string_24787 + call PlaceString + ret + +.string_24787 + db "CANCEL@" + +.call_function + ld d, h + ld e, l + ld hl, wMenuData_ScrollingMenuFunction1 + jp CallPointerAt + +ScrollingMenu_CallFunctions1and2: + push hl + ld d, h + ld e, l + ld hl, wMenuData_ScrollingMenuFunction1 + call CallPointerAt + pop hl + ld a, [wMenuData_ScrollingMenuWidth] + and a + jr z, .done + ld e, a + ld d, $0 + add hl, de + ld d, h + ld e, l + ld hl, wMenuData_ScrollingMenuFunction2 + call CallPointerAt + +.done + ret + +ScrollingMenu_PlaceCursor: + ld a, [wSwitchItem] + and a + jr z, .done + ld b, a + ld a, [wMenuScrollPosition] + cp b + jr nc, .done + ld c, a + ld a, [wMenuData_ScrollingMenuHeight] + add c + cp b + jr c, .done + ld a, b + sub c + dec a + add a + add $1 + ld c, a + ld a, [wMenuBorderTopCoord] + add c + ld b, a + ld a, [wMenuBorderLeftCoord] + add $0 + ld c, a + call Coord2Tile + ld [hl], "▷" + +.done + ret + +ScrollingMenu_CheckCallFunction3: + ld a, [wMenuDataFlags] + bit 5, a ; call function 3 + ret z + bit 1, a ; call function 3 if not switching items + jr z, .call + ld a, [wSwitchItem] + and a + ret nz + +.call + ld a, [wMenuCursorY] + dec a + call ScrollingMenu_GetListItemCoordAndFunctionArgs + ld hl, wMenuData_ScrollingMenuFunction3 + call CallPointerAt + ret + +ScrollingMenu_GetListItemCoordAndFunctionArgs: + push de + push hl + ld e, a + ld a, [wMenuScrollPosition] + add e + ld e, a + ld d, $0 + ld hl, wMenuData_ItemsPointerAddr + ld a, [hli] + ld h, [hl] + ld l, a + inc hl ; items + ld a, [wMenuData_ScrollingMenuItemFormat] + cp SCROLLINGMENU_ITEMS_NORMAL + jr z, .got_spacing + cp SCROLLINGMENU_ITEMS_QUANTITY + jr z, .pointless_jump +.pointless_jump + add hl, de +.got_spacing + add hl, de + ld a, [wMenuData_ItemsPointerBank] + call GetFarByte + ld [wMenuSelection], a + ld [wCurItem], a + inc hl + ld a, [wMenuData_ItemsPointerBank] + call GetFarByte + ld [wMenuSelectionQuantity], a + pop hl + pop de + ret diff --git a/engine/menus/start_menu.asm b/engine/menus/start_menu.asm new file mode 100644 index 00000000..dbadf637 --- /dev/null +++ b/engine/menus/start_menu.asm @@ -0,0 +1,541 @@ +; StartMenu.Items indexes + const_def + const STARTMENUITEM_POKEDEX ; 0 + const STARTMENUITEM_POKEMON ; 1 + const STARTMENUITEM_PACK ; 2 + const STARTMENUITEM_STATUS ; 3 + const STARTMENUITEM_SAVE ; 4 + const STARTMENUITEM_OPTION ; 5 + const STARTMENUITEM_EXIT ; 6 + const STARTMENUITEM_POKEGEAR ; 7 + const STARTMENUITEM_QUIT ; 8 + +StartMenu:: + call ClearWindowData + + ld de, SFX_MENU + call PlaySFX + + farcall ReanchorBGMap_NoOAMUpdate + + ld hl, wStatusFlags2 + bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl] + ld hl, .MenuHeader + jr z, .GotMenuData + ld hl, .ContestMenuHeader + +.GotMenuData: + call LoadMenuHeader + call .SetUpMenuItems + ld a, [wBattleMenuCursorBuffer] + ld [wMenuCursorBuffer], a + call .DrawMenuAccount + call DrawVariableLengthMenuBox + call .DrawBugContestStatusBox + call SafeUpdateSprites + call _OpenAndCloseMenu_HDMATransferTilemapAndAttrmap + farcall LoadFonts_NoOAMUpdate + call .DrawBugContestStatus + call UpdateTimePals + jr .Select + +.Reopen: + call UpdateSprites + call UpdateTimePals + call .SetUpMenuItems + ld a, [wBattleMenuCursorBuffer] + ld [wMenuCursorBuffer], a + +.Select: + call .GetInput + jr c, .Exit + call ._DrawMenuAccount + ld a, [wMenuCursorBuffer] + ld [wBattleMenuCursorBuffer], a + call PlayClickSFX + call PlaceHollowCursor + call .OpenMenu + +; Menu items have different return functions. +; For example, saving exits the menu. + ld hl, .MenuReturns + ld e, a + ld d, 0 + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.MenuReturns: + dw .Reopen + dw .Exit + dw .ExitMenuCallFuncCloseText + dw .ExitMenuRunScriptCloseText + dw .ExitMenuRunScript + dw .ReturnEnd + dw .ReturnRedraw + +.Exit: + ldh a, [hOAMUpdate] + push af + ld a, 1 + ldh [hOAMUpdate], a + call LoadFontsExtra + pop af + ldh [hOAMUpdate], a +.ReturnEnd: + call ExitMenu +.ReturnEnd2: + call CloseText + call UpdateTimePals + ret + +.GetInput: +; Return carry on exit, and no-carry on selection. + xor a + ldh [hBGMapMode], a + call ._DrawMenuAccount + call SetUpMenu + ld a, $ff + ld [wMenuSelection], a +.loop + call .PrintMenuAccount + call GetScrollingMenuJoypad + ld a, [wMenuJoypad] + cp B_BUTTON + jr z, .b + cp A_BUTTON + jr z, .a + jr .loop +.a + call PlayClickSFX + and a + ret +.b + scf + ret + +.ExitMenuRunScript: + call ExitMenu + ld a, HMENURETURN_SCRIPT + ldh [hMenuReturn], a + ret + +.ExitMenuRunScriptCloseText: + call ExitMenu + ld a, HMENURETURN_SCRIPT + ldh [hMenuReturn], a + jr .ReturnEnd2 + +.ExitMenuCallFuncCloseText: + call ExitMenu + ld hl, wQueuedScriptAddr + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wQueuedScriptBank] + rst FarCall + jr .ReturnEnd2 + +.ReturnRedraw: + call .Clear + jp .Reopen + +.Clear: + call ClearBGPalettes + call Call_ExitMenu + call ReloadTilesetAndPalettes + call .DrawMenuAccount + call DrawVariableLengthMenuBox + call .DrawBugContestStatus + call UpdateSprites + call ReloadPalettes + call FinishExitMenu + ret + +.MenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 10, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1 + dw .MenuData + db 1 ; default selection + +.ContestMenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 10, 2, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1 + dw .MenuData + db 1 ; default selection + +.MenuData: + db STATICMENU_CURSOR | STATICMENU_WRAP | STATICMENU_ENABLE_START ; flags + dn 0, 0 ; rows, columns + dw wMenuItemsList + dw .MenuString + dw .Items + +.Items: +; entries correspond to STARTMENUITEM_* constants + dw StartMenu_Pokedex, .PokedexString, .PokedexDesc + dw StartMenu_Pokemon, .PartyString, .PartyDesc + dw StartMenu_Pack, .PackString, .PackDesc + dw StartMenu_Status, .StatusString, .StatusDesc + dw StartMenu_Save, .SaveString, .SaveDesc + dw StartMenu_Option, .OptionString, .OptionDesc + dw StartMenu_Exit, .ExitString, .ExitDesc + dw StartMenu_Pokegear, .PokegearString, .PokegearDesc + dw StartMenu_Quit, .QuitString, .QuitDesc + +.PokedexString: db "#DEX@" +.PartyString: db "#MON@" +.PackString: db "PACK@" +.StatusString: db "<PLAYER>@" +.SaveString: db "SAVE@" +.OptionString: db "OPTION@" +.ExitString: db "EXIT@" +.PokegearString: db "<POKE>GEAR@" +.QuitString: db "QUIT@" + +.PokedexDesc: + db "#MON" + next "database@" + +.PartyDesc: + db "Party <PKMN>" + next "status@" + +.PackDesc: + db "Contains" + next "items@" + +.PokegearDesc: + db "Trainer's" + next "key device@" + +.StatusDesc: + db "Your own" + next "status@" + +.SaveDesc: + db "Save your" + next "progress@" + +.OptionDesc: + db "Change" + next "settings@" + +.ExitDesc: + db "Close this" + next "menu@" + +.QuitDesc: + db "Quit and" + next "be judged.@" + +.OpenMenu: + ld a, [wMenuSelection] + call .GetMenuAccountTextPointer + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.MenuString: + push de + ld a, [wMenuSelection] + call .GetMenuAccountTextPointer + inc hl + inc hl + ld a, [hli] + ld d, [hl] + ld e, a + pop hl + call PlaceString + ret + +.MenuDesc: + push de + ld a, [wMenuSelection] + cp $ff + jr z, .none + call .GetMenuAccountTextPointer +rept 4 + inc hl +endr + ld a, [hli] + ld d, [hl] + ld e, a + pop hl + call PlaceString + ret +.none + pop de + ret + +.GetMenuAccountTextPointer: + ld e, a + ld d, 0 + ld hl, wMenuDataPointerTableAddr + ld a, [hli] + ld h, [hl] + ld l, a +rept 6 + add hl, de +endr + ret + +.SetUpMenuItems: + xor a + ld [wWhichIndexSet], a + call .FillMenuList + + ld hl, wStatusFlags + bit STATUSFLAGS_POKEDEX_F, [hl] + jr z, .no_pokedex + ld a, STARTMENUITEM_POKEDEX + call .AppendMenuList +.no_pokedex + + ld a, [wPartyCount] + and a + jr z, .no_pokemon + ld a, STARTMENUITEM_POKEMON + call .AppendMenuList +.no_pokemon + + ld a, [wLinkMode] + and a + jr nz, .no_pack + ld hl, wStatusFlags2 + bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl] + jr nz, .no_pack + ld a, STARTMENUITEM_PACK + call .AppendMenuList +.no_pack + + ld hl, wPokegearFlags + bit POKEGEAR_OBTAINED_F, [hl] + jr z, .no_pokegear + ld a, STARTMENUITEM_POKEGEAR + call .AppendMenuList +.no_pokegear + + ld a, STARTMENUITEM_STATUS + call .AppendMenuList + + ld a, [wLinkMode] + and a + jr nz, .no_save + ld hl, wStatusFlags2 + bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl] + ld a, STARTMENUITEM_QUIT + jr nz, .write + ld a, STARTMENUITEM_SAVE +.write + call .AppendMenuList +.no_save + + ld a, STARTMENUITEM_OPTION + call .AppendMenuList + ld a, STARTMENUITEM_EXIT + call .AppendMenuList + ld a, c + ld [wMenuItemsList], a + ret + +.FillMenuList: + xor a + ld hl, wMenuItemsList + ld [hli], a + ld a, -1 + ld bc, wMenuItemsListEnd - (wMenuItemsList + 1) + call ByteFill + ld de, wMenuItemsList + 1 + ld c, 0 + ret + +.AppendMenuList: + ld [de], a + inc de + inc c + ret + +.DrawMenuAccount: + jp ._DrawMenuAccount + +.PrintMenuAccount: + call .IsMenuAccountOn + ret z + call ._DrawMenuAccount + decoord 0, 14 + jp .MenuDesc + +._DrawMenuAccount: + call .IsMenuAccountOn + ret z + hlcoord 0, 13 + lb bc, 5, 10 + call ClearBox + hlcoord 0, 13 + ld b, 3 + ld c, 8 + jp TextboxPalette + +.IsMenuAccountOn: + ld a, [wOptions2] + and 1 << MENU_ACCOUNT + ret + +.DrawBugContestStatusBox: + ld hl, wStatusFlags2 + bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl] + ret z + farcall StartMenu_DrawBugContestStatusBox + ret + +.DrawBugContestStatus: + ld hl, wStatusFlags2 + bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl] + jr nz, .contest + ret +.contest + farcall StartMenu_PrintBugContestStatus + ret + +StartMenu_Exit: +; Exit the menu. + + ld a, 1 + ret + +StartMenu_Quit: +; Retire from the bug catching contest. + + ld hl, .StartMenuContestEndText + call StartMenuYesNo + jr c, .DontEndContest + ld a, BANK(BugCatchingContestReturnToGateScript) + ld hl, BugCatchingContestReturnToGateScript + call FarQueueScript + ld a, 4 + ret + +.DontEndContest: + ld a, 0 + ret + +.StartMenuContestEndText: + text_far _StartMenuContestEndText + text_end + +StartMenu_Save: +; Save the game. + + call BufferScreen + farcall SaveMenu + jr nc, .asm_12ce0 + ld a, 0 + ret +.asm_12ce0 + ld a, 1 + ret + +StartMenu_Option: +; Game options. + + call FadeToMenu + farcall OptionsMenu + ld a, 6 + ret + +StartMenu_Status: +; Player status. + + call FadeToMenu + farcall TrainerCard + call CloseSubmenu + ld a, 0 + ret + +StartMenu_Pokedex: + ld a, [wPartyCount] + and a + jr z, .asm_12de0 + + call FadeToMenu + farcall Pokedex + call CloseSubmenu + +.asm_12de0 + ld a, 0 + ret + +StartMenu_Pokegear: + call FadeToMenu + farcall PokeGear + call CloseSubmenu + ld a, 0 + ret + +StartMenu_Pack: + call FadeToMenu + farcall Pack + ld a, [wPackUsedItem] + and a + jr nz, .used_item + call CloseSubmenu + ld a, 0 + ret + +.used_item + call ExitAllMenus + ld a, 4 + ret + +StartMenu_Pokemon: + ld a, [wPartyCount] + and a + jr z, .return + + call FadeToMenu + +.choosemenu + xor a + ld [wPartyMenuActionText], a ; Choose a POKéMON. + call ClearBGPalettes + +.menu + farcall LoadPartyMenuGFX + farcall InitPartyMenuWithCancel + farcall InitPartyMenuGFX + +.menunoreload + farcall WritePartyMenuTilemap + farcall PrintPartyMenuText + call WaitBGMap + call SetPalettes ; load regular palettes? + call DelayFrame + farcall PartyMenuSelect + jr c, .return ; if cancelled or pressed B + + call PokemonActionSubmenu + cp 3 + jr z, .menu + cp 0 + jr z, .choosemenu + cp 1 + jr z, .menunoreload + cp 2 + jr z, .quit + +.return + call CloseSubmenu + ld a, 0 + ret + +.quit + ld a, b + push af + call ExitAllMenus + pop af + ret diff --git a/engine/menus/trainer_card.asm b/engine/menus/trainer_card.asm new file mode 100644 index 00000000..7061d4bd --- /dev/null +++ b/engine/menus/trainer_card.asm @@ -0,0 +1,624 @@ +; TrainerCard.Jumptable indexes + const_def + const TRAINERCARDSTATE_PAGE1_LOADGFX ; 0 + const TRAINERCARDSTATE_PAGE1_JOYPAD ; 1 + const TRAINERCARDSTATE_PAGE2_LOADGFX ; 2 + const TRAINERCARDSTATE_PAGE2_JOYPAD ; 3 + const TRAINERCARDSTATE_PAGE3_LOADGFX ; 4 + const TRAINERCARDSTATE_PAGE3_JOYPAD ; 5 + const TRAINERCARDSTATE_QUIT ; 6 + +TrainerCard: + ld a, [wVramState] + push af + xor a + ld [wVramState], a + ld hl, wOptions + ld a, [hl] + push af + set NO_TEXT_SCROLL, [hl] + call .InitRAM +.loop + call UpdateTime + call JoyTextDelay + ld a, [wJumptableIndex] + bit 7, a + jr nz, .quit + ldh a, [hJoyLast] + and B_BUTTON + jr nz, .quit + call .RunJumptable + call DelayFrame + jr .loop + +.quit + pop af + ld [wOptions], a + pop af + ld [wVramState], a + ret + +.InitRAM: + call ClearBGPalettes + call ClearSprites + call ClearTilemap + call DisableLCD + + ld hl, ChrisCardPic + ld de, vTiles2 + ld bc, 41 tiles + ld a, BANK(ChrisCardPic) + call FarCopyBytes + + ld hl, CardStatusGFX + ld de, vTiles2 tile $29 + ld bc, 86 tiles + ld a, BANK(CardStatusGFX) + call FarCopyBytes + + call TrainerCard_PrintTopHalfOfCard + + hlcoord 0, 8 + ld d, 6 + call TrainerCard_InitBorder + + call EnableLCD + call WaitBGMap + ld b, SCGB_TRAINER_CARD + call GetSGBLayout + call SetPalettes + call WaitBGMap + ld hl, wJumptableIndex + xor a ; TRAINERCARDSTATE_PAGE1_LOADGFX + ld [hli], a ; wJumptableIndex + ld [hli], a ; wTrainerCardBadgeFrameCounter + ld [hli], a ; wTrainerCardBadgeTileID + ld [hl], a ; wTrainerCardBadgeAttributes + ret + +.RunJumptable: + jumptable .Jumptable, wJumptableIndex + +.Jumptable: +; entries correspond to TRAINERCARDSTATE_* constants + dw TrainerCard_Page1_LoadGFX + dw TrainerCard_Page1_Joypad + dw TrainerCard_Page2_LoadGFX + dw TrainerCard_Page2_Joypad + dw TrainerCard_Page3_LoadGFX + dw TrainerCard_Page3_Joypad + dw TrainerCard_Quit + +TrainerCard_IncrementJumptable: + ld hl, wJumptableIndex + inc [hl] + ret + +TrainerCard_Quit: + ld hl, wJumptableIndex + set 7, [hl] + ret + +TrainerCard_Page1_LoadGFX: + call ClearSprites + hlcoord 0, 8 + ld d, 6 + call TrainerCard_InitBorder + call WaitBGMap + ld de, CardStatusGFX + ld hl, vTiles2 tile $29 + lb bc, BANK(CardStatusGFX), 86 + call Request2bpp + call TrainerCard_Page1_PrintDexCaught_GameTime + call TrainerCard_IncrementJumptable + ret + +TrainerCard_Page1_Joypad: + call TrainerCard_Page1_PrintGameTime + ld hl, hJoyLast + ld a, [hl] + and D_RIGHT | A_BUTTON + jr nz, .pressed_right_a + ret + +.pressed_right_a + ld a, TRAINERCARDSTATE_PAGE2_LOADGFX + ld [wJumptableIndex], a + ret + +.Unreferenced_KantoCheck: + ld a, [wKantoBadges] + and a + ret z + ld a, TRAINERCARDSTATE_PAGE3_LOADGFX + ld [wJumptableIndex], a + ret + +TrainerCard_Page2_LoadGFX: + call ClearSprites + hlcoord 0, 8 + ld d, 6 + call TrainerCard_InitBorder + call WaitBGMap + ld de, LeaderGFX + ld hl, vTiles2 tile $29 + lb bc, BANK(LeaderGFX), 86 + call Request2bpp + ld de, BadgeGFX + ld hl, vTiles0 tile $00 + lb bc, BANK(BadgeGFX), 44 + call Request2bpp + call TrainerCard_Page2_3_InitObjectsAndStrings + call TrainerCard_IncrementJumptable + ret + +TrainerCard_Page2_Joypad: + ld hl, TrainerCard_JohtoBadgesOAM + call TrainerCard_Page2_3_AnimateBadges + ld hl, hJoyLast + ld a, [hl] + and A_BUTTON + jr nz, .Quit + ld a, [hl] + and D_LEFT + jr nz, .d_left + ret + +.d_left + ld a, TRAINERCARDSTATE_PAGE1_LOADGFX + ld [wJumptableIndex], a + ret + +.Unreferenced_KantoCheck: + ld a, [wKantoBadges] + and a + ret z + ld a, TRAINERCARDSTATE_PAGE3_LOADGFX + ld [wJumptableIndex], a + ret + +.Quit: + ld a, TRAINERCARDSTATE_QUIT + ld [wJumptableIndex], a + ret + +TrainerCard_Page3_LoadGFX: + call ClearSprites + hlcoord 0, 8 + ld d, 6 + call TrainerCard_InitBorder + call WaitBGMap + ld de, LeaderGFX2 + ld hl, vTiles2 tile $29 + lb bc, BANK(LeaderGFX2), 86 + call Request2bpp + ld de, BadgeGFX2 + ld hl, vTiles0 tile $00 + lb bc, BANK(BadgeGFX2), 44 + call Request2bpp + call TrainerCard_Page2_3_InitObjectsAndStrings + call TrainerCard_IncrementJumptable + ret + +TrainerCard_Page3_Joypad: + ld hl, TrainerCard_JohtoBadgesOAM + call TrainerCard_Page2_3_AnimateBadges + ld hl, hJoyLast + ld a, [hl] + and D_LEFT + jr nz, .left + ld a, [hl] + and D_RIGHT + jr nz, .right + ret + +.left + ld a, TRAINERCARDSTATE_PAGE2_LOADGFX + ld [wJumptableIndex], a + ret + +.right + ld a, TRAINERCARDSTATE_PAGE1_LOADGFX + ld [wJumptableIndex], a + ret + +TrainerCard_PrintTopHalfOfCard: + hlcoord 0, 0 + ld d, 5 + call TrainerCard_InitBorder + hlcoord 2, 2 + ld de, .Name_Money + call PlaceString + hlcoord 2, 4 + ld de, .ID_No + call TrainerCardSetup_PlaceTilemapString + hlcoord 7, 2 + ld de, wPlayerName + call PlaceString + hlcoord 5, 4 + ld de, wPlayerID + lb bc, PRINTNUM_LEADINGZEROS | 2, 5 + call PrintNum + hlcoord 7, 6 + ld de, wMoney + lb bc, PRINTNUM_MONEY | 3, 6 + call PrintNum + hlcoord 1, 3 + ld de, .HorizontalDivider + call TrainerCardSetup_PlaceTilemapString + hlcoord 14, 1 + ld de, SCREEN_WIDTH + xor a + ld b, 7 + +.row + ld c, 5 + push hl + +.col + ld [hli], a + inc a + dec c + jr nz, .col + pop hl + add hl, de + dec b + jr nz, .row + ret + +.Name_Money: + db "NAME/" + next "" + next "MONEY@" + +.ID_No: + db $27, $28, -1 ; ID NO + +.HorizontalDivider: + db $25, $25, $25, $25, $25, $25, $25, $25, $25, $25, $25, $25, $26, -1 ; ____________> + +TrainerCard_Page1_PrintDexCaught_GameTime: + hlcoord 2, 10 + ld de, .Dex_PlayTime + call PlaceString + hlcoord 12, 15 + ld de, .Badges + call PlaceString + ld hl, wPokedexCaught + ld b, wEndPokedexCaught - wPokedexCaught + call CountSetBits + ld de, wNumSetBits + hlcoord 15, 10 + lb bc, 1, 3 + call PrintNum + call TrainerCard_Page1_PrintGameTime + hlcoord 2, 8 + ld de, .StatusTilemap + call TrainerCardSetup_PlaceTilemapString + ld a, [wStatusFlags] + bit STATUSFLAGS_POKEDEX_F, a + ret nz + hlcoord 1, 9 + lb bc, 2, 17 + call ClearBox + ret + +.Dex_PlayTime: + db "#DEX" + next "PLAY TIME@" + + db "@" ; unused + +.Badges: + db "BADGES▶@" + +.StatusTilemap: + db $29, $2a, $2b, $2c, $2d, -1 + +TrainerCard_Page2_3_InitObjectsAndStrings: + hlcoord 2, 8 + ld de, .BadgesTilemap + call TrainerCardSetup_PlaceTilemapString + hlcoord 2, 10 + ld a, $29 + ld c, 4 +.loop + call TrainerCard_Page2_3_PlaceLeadersFaces +rept 4 + inc hl +endr + dec c + jr nz, .loop + hlcoord 2, 13 + ld a, $51 + ld c, 4 +.loop2 + call TrainerCard_Page2_3_PlaceLeadersFaces +rept 4 + inc hl +endr + dec c + jr nz, .loop2 + xor a + ld [wTrainerCardBadgeFrameCounter], a + ld hl, TrainerCard_JohtoBadgesOAM + call TrainerCard_Page2_3_OAMUpdate + ret + +.BadgesTilemap: + db $79, $7a, $7b, $7c, $7d, -1 ; "BADGES" + +TrainerCardSetup_PlaceTilemapString: +.loop + ld a, [de] + cp -1 + ret z + ld [hli], a + inc de + jr .loop + +TrainerCard_InitBorder: + ld e, SCREEN_WIDTH +.loop1 + ld a, $23 + ld [hli], a + dec e + jr nz, .loop1 + + ld a, $23 + ld [hli], a + ld e, SCREEN_HEIGHT - 1 + ld a, " " +.loop2 + ld [hli], a + dec e + jr nz, .loop2 + + ld a, $4 + ld [hli], a + ld a, $23 + ld [hli], a +.loop3 + ld a, $23 + ld [hli], a + + ld e, SCREEN_HEIGHT + ld a, " " +.loop4 + ld [hli], a + dec e + jr nz, .loop4 + + ld a, $23 + ld [hli], a + dec d + jr nz, .loop3 + + ld a, $23 + ld [hli], a + ld a, $24 + ld [hli], a + + ld e, SCREEN_HEIGHT - 1 + ld a, " " +.loop5 + ld [hli], a + dec e + jr nz, .loop5 + ld a, $23 + ld [hli], a + ld e, SCREEN_WIDTH +.loop6 + ld a, $23 + ld [hli], a + dec e + jr nz, .loop6 + ret + +TrainerCard_Page2_3_PlaceLeadersFaces: + push de + push hl + ld [hli], a + inc a + ld [hli], a + inc a + ld [hli], a + inc a + ld [hli], a + inc a + ld de, SCREEN_WIDTH - 3 + add hl, de + ld [hli], a + inc a + ld [hli], a + inc a + ld [hli], a + inc a + ld de, SCREEN_WIDTH - 3 + add hl, de + ld [hli], a + inc a + ld [hli], a + inc a + ld [hli], a + inc a + pop hl + pop de + ret + +TrainerCard_Page1_PrintGameTime: + hlcoord 11, 12 + ld de, wGameTimeHours + lb bc, 2, 4 + call PrintNum + inc hl + ld de, wGameTimeMinutes + lb bc, PRINTNUM_LEADINGZEROS | 1, 2 + call PrintNum + ldh a, [hVBlankCounter] + and $1f + ret nz + hlcoord 15, 12 + ld a, [hl] + xor " " ^ $2e ; alternate between space and small colon ($2e) tiles + ld [hl], a + ret + +TrainerCard_Page2_3_AnimateBadges: + ldh a, [hVBlankCounter] + and %111 + ret nz + ld a, [wTrainerCardBadgeFrameCounter] + inc a + and %111 + ld [wTrainerCardBadgeFrameCounter], a + jr TrainerCard_Page2_3_OAMUpdate + +TrainerCard_Page2_3_OAMUpdate: +; copy flag array pointer + ld a, [hli] + ld e, a + ld a, [hli] +; get flag array + ld d, a + ld a, [de] + ld c, a + ld de, wVirtualOAMSprite00 + ld b, NUM_JOHTO_BADGES +.loop + srl c + push bc + jr nc, .skip_badge + push hl + ld a, [hli] ; y + ld b, a + ld a, [hli] ; x + ld c, a + ld a, [hli] ; pal + ld [wTrainerCardBadgeAttributes], a + ld a, [wTrainerCardBadgeFrameCounter] + add l + ld l, a + ld a, 0 + adc h + ld h, a + ld a, [hl] + ld [wTrainerCardBadgeTileID], a + call .PrepOAM + pop hl +.skip_badge + ld bc, $b ; 3 + 2 * 4 + add hl, bc + pop bc + dec b + jr nz, .loop + ret + +.PrepOAM: + ld a, [wTrainerCardBadgeTileID] + and 1 << 7 + jr nz, .xflip + ld hl, .facing1 + jr .loop2 + +.xflip + ld hl, .facing2 +.loop2 + ld a, [hli] + cp -1 + ret z + add b + ld [de], a ; y + inc de + + ld a, [hli] + add c + ld [de], a ; x + inc de + + ld a, [wTrainerCardBadgeTileID] + and $ff ^ (1 << 7) + add [hl] + ld [de], a ; tile id + inc hl + inc de + + ld a, [wTrainerCardBadgeAttributes] + add [hl] + ld [de], a ; attributes + inc hl + inc de + jr .loop2 + +.facing1 + dbsprite 0, 0, 0, 0, $00, 0 + dbsprite 1, 0, 0, 0, $01, 0 + dbsprite 0, 1, 0, 0, $02, 0 + dbsprite 1, 1, 0, 0, $03, 0 + db -1 + +.facing2 + dbsprite 0, 0, 0, 0, $01, 0 | X_FLIP + dbsprite 1, 0, 0, 0, $00, 0 | X_FLIP + dbsprite 0, 1, 0, 0, $03, 0 | X_FLIP + dbsprite 1, 1, 0, 0, $02, 0 | X_FLIP + db -1 + +TrainerCard_JohtoBadgesOAM: +; Template OAM data for each badge on the trainer card. +; Format: + ; y, x, palette + ; cycle 1: face tile, in1 tile, in2 tile, in3 tile + ; cycle 2: face tile, in1 tile, in2 tile, in3 tile + + dw wJohtoBadges + + ; Zephyrbadge + db $68, $18, 0 + db $00, $20, $24, $20 | (1 << 7) + db $00, $20, $24, $20 | (1 << 7) + + ; Hivebadge + db $68, $38, 0 + db $04, $20, $24, $20 | (1 << 7) + db $04, $20, $24, $20 | (1 << 7) + + ; Plainbadge + db $68, $58, 0 + db $08, $20, $24, $20 | (1 << 7) + db $08, $20, $24, $20 | (1 << 7) + + ; Fogbadge + db $68, $78, 0 + db $0c, $20, $24, $20 | (1 << 7) + db $0c, $20, $24, $20 | (1 << 7) + + ; Mineralbadge + db $80, $38, 0 + db $10, $20, $24, $20 | (1 << 7) + db $10, $20, $24, $20 | (1 << 7) + + ; Stormbadge + db $80, $18, 0 + db $14, $20, $24, $20 | (1 << 7) + db $14, $20, $24, $20 | (1 << 7) + + ; Glacierbadge + db $80, $58, 0 + db $18, $20, $24, $20 | (1 << 7) + db $18, $20, $24, $20 | (1 << 7) + + ; Risingbadge + ; X-flips on alternate cycles. + db $80, $78, 0 + db $1c, $20, $24, $20 | (1 << 7) + db $1c | (1 << 7), $20, $24, $20 | (1 << 7) + +ChrisCardPic: INCBIN "gfx/trainer_card/chris_card.2bpp" +CardGFX: INCBIN "gfx/trainer_card/trainer_card.2bpp" +CardStatusGFX: INCBIN "gfx/trainer_card/card_status.2bpp" + +LeaderGFX: INCBIN "gfx/trainer_card/leaders.2bpp" +LeaderGFX2: INCBIN "gfx/trainer_card/leaders.2bpp" +BadgeGFX: INCBIN "gfx/trainer_card/badges.2bpp" +BadgeGFX2: INCBIN "gfx/trainer_card/badges.2bpp" |