diff options
Diffstat (limited to 'src/engine/menus')
-rw-r--r-- | src/engine/menus/booster_pack.asm | 42 | ||||
-rw-r--r-- | src/engine/menus/common.asm | 8 | ||||
-rw-r--r-- | src/engine/menus/glossary.asm | 221 | ||||
-rw-r--r-- | src/engine/menus/play_area.asm | 570 | ||||
-rw-r--r-- | src/engine/menus/start.asm | 418 | ||||
-rw-r--r-- | src/engine/menus/unknown.asm | 103 |
6 files changed, 1358 insertions, 4 deletions
diff --git a/src/engine/menus/booster_pack.asm b/src/engine/menus/booster_pack.asm new file mode 100644 index 0000000..934b730 --- /dev/null +++ b/src/engine/menus/booster_pack.asm @@ -0,0 +1,42 @@ +_OpenBoosterPack: + ld a, PLAYER_TURN + ldh [hWhoseTurn], a +; clears DECK_SIZE bytes starting from wPlayerDuelVariables + ld h, a + ld l, $00 +.loop_clear + xor a + ld [hli], a + ld a, l + cp DECK_SIZE + jr c, .loop_clear + +; fills wDuelTempList with 0, 1, 2, 3, ... +; up to the number of cards received in Boster Pack + xor a + ld hl, wBoosterCardsDrawn + ld de, wDuelTempList + ld c, $00 +.loop_index_sequence + ld a, [hli] + or a + jr z, .done_index_sequence + ld a, c + ld [de], a + inc de + inc c + jr .loop_index_sequence +.done_index_sequence + ld a, $ff ; terminator byte + ld [de], a + + lb de, $38, $9f + call SetupText + bank1call InitAndDrawCardListScreenLayout + ldtx hl, ChooseTheCardYouWishToExamineText + ldtx de, BoosterPackText + bank1call SetCardListHeaderText + ld a, A_BUTTON | START + ld [wNoItemSelectionMenuKeys], a + bank1call DisplayCardList + ret diff --git a/src/engine/menus/common.asm b/src/engine/menus/common.asm index 069d168..60ad0a9 100644 --- a/src/engine/menus/common.asm +++ b/src/engine/menus/common.asm @@ -19,8 +19,8 @@ DoCardPop: farcall _DoCardPop ret -Func_7576: - farcall Func_1991f +AddStarterDeck: + farcall _AddStarterDeck ret PreparePrinterConnection: @@ -43,8 +43,8 @@ SetUpAndStartLinkDuel: farcall _SetUpAndStartLinkDuel ret -Func_7594: - farcall Func_1a61f +ShowPromotionalCardScreen: + farcall _ShowPromotionalCardScreen ret OpenBoosterPack: diff --git a/src/engine/menus/glossary.asm b/src/engine/menus/glossary.asm new file mode 100644 index 0000000..78f44dd --- /dev/null +++ b/src/engine/menus/glossary.asm @@ -0,0 +1,221 @@ +OpenGlossaryScreen: + xor a + ld [wGlossaryPageNo], a + call .display_menu + + xor a + ld [wInPlayAreaCurPosition], a + ld de, OpenGlossaryScreen_TransitionTable ; this data is stored in bank 2. + ld hl, wMenuInputTablePointer + ld [hl], e + inc hl + ld [hl], d + ld a, $ff + ld [wDuelInitialPrizesUpperBitsSet], a + xor a + ld [wCheckMenuCursorBlinkCounter], a +.next + ld a, $01 + ld [wVBlankOAMCopyToggle], a + call DoFrame + ldh a, [hKeysPressed] + and SELECT + jr nz, .on_select + + farcall YourOrOppPlayAreaScreen_HandleInput + jr nc, .next + + cp -1 ; b button + jr nz, .check_button + + farcall ZeroObjectPositionsWithCopyToggleOn + ret + +.check_button + push af + farcall ZeroObjectPositionsWithCopyToggleOn + pop af + + cp $09 ; $09: next page or prev page + jr z, .change_page + + call .print_description + call .display_menu + xor a + ld [wCheckMenuCursorBlinkCounter], a + jr .next + +.on_select + ld a, $01 + farcall PlaySFXConfirmOrCancel +.change_page + ld a, [wGlossaryPageNo] + xor $01 ; swap page + ld [wGlossaryPageNo], a + call .print_menu + jr .next + +; display glossary menu. +.display_menu ; 1852b (6:452b) + xor a + ld [wTileMapFill], a + call ZeroObjectPositions + ld a, $01 + ld [wVBlankOAMCopyToggle], a + call DoFrame + call EmptyScreen + call Set_OBJ_8x8 + farcall LoadCursorTile + + lb de, 5, 0 + call InitTextPrinting + ldtx hl, PokemonCardGlossaryText + call ProcessTextFromID + call .print_menu + ldtx hl, ChooseWordAndPressAButtonText + call DrawWideTextBox_PrintText + ret + +; print texts in glossary menu. +.print_menu ; 1855a (6:455a) + ld hl, wDefaultText + + ld a, TX_SYMBOL + ld [hli], a + + ld a, [wGlossaryPageNo] + add SYM_1 + ld [hli], a + + ld a, TX_SYMBOL + ld [hli], a + + ld a, SYM_SLASH + ld [hli], a + + ld a, TX_SYMBOL + ld [hli], a + + ld a, SYM_2 + ld [hli], a + + ld [hl], TX_END + + lb de, 16, 1 + call InitTextPrinting + ld hl, wDefaultText + call ProcessText + + lb de, 1, 3 + call InitTextPrinting + ld a, [wGlossaryPageNo] + or a + jr nz, .page_two + + ldtx hl, GlossaryMenuPage1Text + jr .page_one + +.page_two + ldtx hl, GlossaryMenuPage2Text +.page_one + call ProcessTextFromID + ret + +; display glossary description. +.print_description ; 18598 (6:4598) + push af + xor a + ld [wTileMapFill], a + call EmptyScreen + lb de, 5, 0 + call InitTextPrinting + ldtx hl, PokemonCardGlossaryText + call ProcessTextFromID + lb de, 0, 4 + lb bc, 20, 14 + call DrawRegularTextBox + + ld a, [wGlossaryPageNo] + or a + jr nz, .back_page + + ld hl, GlossaryData1 + jr .front_page + +.back_page + ld hl, GlossaryData2 +.front_page + pop af + ; hl += (a + (a << 2)). + ; that is, + ; hl += (5 * a). + ld c, a + ld b, 0 + add hl, bc + sla a + sla a + ld c, a + add hl, bc + ld a, [hli] + push hl + ld d, a + ld e, $02 + call InitTextPrinting + ld a, [hli] + ld h, [hl] + ld l, a + call ProcessTextFromID + pop hl + lb de, 1, 5 + call InitTextPrinting + inc hl + inc hl + ld a, [hli] + ld h, [hl] + ld l, a + ld a, $01 + ld [wLineSeparation], a + call ProcessTextFromID + xor a + ld [wLineSeparation], a + call EnableLCD +.loop + call DoFrame + ldh a, [hKeysPressed] + and B_BUTTON + jr z, .loop + + ld a, -1 + farcall PlaySFXConfirmOrCancel + ret + +; unit: 5 bytes. +; [structure] +; horizontal align (1) / title text id (2) / desc. text id (2) +glossary_entry: MACRO + db \1 + tx \2 + tx \3 +ENDM + +GlossaryData1: + glossary_entry 7, AboutTheDeckText, DeckDescriptionText + glossary_entry 5, AboutTheDiscardPileText, DiscardPileDescriptionText + glossary_entry 7, AboutTheHandText, HandDescriptionText + glossary_entry 6, AboutTheArenaText, ArenaDescriptionText + glossary_entry 6, AboutTheBenchText, BenchDescriptionText + glossary_entry 4, AboutTheActivePokemonText, ActivePokemonDescriptionText + glossary_entry 5, AboutBenchPokemonText, BenchPokemonDescriptionText + glossary_entry 7, AboutPrizesText, PrizesDescriptionText + glossary_entry 5, AboutDamageCountersText, DamageCountersDescriptionText + +GlossaryData2: + glossary_entry 5, AboutEnergyCardsText, EnergyCardsDescriptionText + glossary_entry 5, AboutTrainerCardsText, TrainerCardsDescriptionText + glossary_entry 5, AboutBasicPokemonText, BasicPokemonDescriptionText + glossary_entry 5, AboutEvolutionCardsText, EvolutionCardsDescriptionText + glossary_entry 6, AboutAttackingText, AttackingDescriptionText + glossary_entry 5, AboutPokemonPowerText, PokemonPowerDescriptionText + glossary_entry 6, AboutWeaknessText, WeaknessDescriptionText + glossary_entry 6, AboutResistanceText, ResistanceDescriptionText + glossary_entry 6, AboutRetreatingText, RetreatingDescriptionText diff --git a/src/engine/menus/play_area.asm b/src/engine/menus/play_area.asm new file mode 100644 index 0000000..047d24f --- /dev/null +++ b/src/engine/menus/play_area.asm @@ -0,0 +1,570 @@ +; this function is called when the player is shown the "In Play Area" screen. +; it can be called with either the select button (DuelMenuShortcut_BothActivePokemon), +; or via the "In Play Area" item of the Check menu (DuelCheckMenu_InPlayArea) +OpenInPlayAreaScreen: + ld a, INPLAYAREA_PLAYER_ACTIVE + ld [wInPlayAreaCurPosition], a +.start + xor a + ld [wCheckMenuCursorBlinkCounter], a + farcall DrawInPlayAreaScreen + call EnableLCD + call IsClairvoyanceActive + jr c, .clairvoyance_on + + ld de, OpenInPlayAreaScreen_TransitionTable1 + jr .clairvoyance_off + +.clairvoyance_on + ld de, OpenInPlayAreaScreen_TransitionTable2 +.clairvoyance_off + ld hl, wMenuInputTablePointer + ld [hl], e + inc hl + ld [hl], d + ld a, [wInPlayAreaCurPosition] + call .print_associated_text +.on_frame + ld a, $01 + ld [wVBlankOAMCopyToggle], a + call DoFrame + + ldh a, [hDPadHeld] + and START + jr nz, .selection + + ; if this function's been called from 'select' button, + ; wInPlayAreaFromSelectButton is on. + ld a, [wInPlayAreaFromSelectButton] + or a + jr z, .handle_input ; if it's from the Check menu, jump. + + ldh a, [hDPadHeld] + and SELECT + jr nz, .skip_input + +.handle_input + ld a, [wInPlayAreaCurPosition] + ld [wInPlayAreaTemporaryPosition], a + call OpenInPlayAreaScreen_HandleInput + jr c, .pressed + + ld a, [wInPlayAreaCurPosition] + cp INPLAYAREA_PLAYER_PLAY_AREA + jp z, .show_turn_holder_play_area + cp INPLAYAREA_OPP_PLAY_AREA + jp z, .show_non_turn_holder_play_area + + ; check if the cursor moved. + ld hl, wInPlayAreaTemporaryPosition + cp [hl] + call nz, .print_associated_text + + jr .on_frame + +.pressed + cp -1 + jr nz, .selection + + ; pressed b button. + call ZeroObjectPositionsAndToggleOAMCopy_Bank6 + lb de, $38, $9f + call SetupText + scf + ret + +.skip_input + call ZeroObjectPositionsAndToggleOAMCopy_Bank6 + lb de, $38, $9f + call SetupText + or a + ret + +.selection ; pressed a button or start button. + call ZeroObjectPositionsAndToggleOAMCopy_Bank6 + lb de, $38, $9f + call SetupText + ld a, [wInPlayAreaCurPosition] + ld [wInPlayAreaPreservedPosition], a + ld hl, .jump_table + call JumpToFunctionInTable + ld a, [wInPlayAreaPreservedPosition] + ld [wInPlayAreaCurPosition], a + + jp .start + +.print_associated_text ; 18171 (6:4171) +; each position has a text associated to it, +; which is printed at the bottom of the screen + push af + lb de, 1, 17 + call InitTextPrinting + ldtx hl, EmptyLineText + call ProcessTextFromID + + ld hl, hffb0 + ld [hl], $01 + ldtx hl, HandText_2 + call ProcessTextFromID + + ld hl, hffb0 + ld [hl], $00 + lb de, 1, 17 + call InitTextPrinting + pop af + ld hl, OpenInPlayAreaScreen_TextTable + ld b, 0 + sla a + ld c, a + add hl, bc + + ; hl = OpenInPlayAreaScreen_TextTable + 2 * (wInPlayAreaCurPosition) + ld a, [hli] + ld h, [hl] + ld l, a + ld a, h + + ; jump ahead if entry does not contain null text (it's not active pokemon) + or a + jr nz, .print_hand_or_discard_pile + + ld a, l + ; bench slots have dummy text IDs assigned to them, which are never used. + ; these are secretly not text id's, but rather, 2-byte PLAY_AREA_BENCH_* constants + ; check if the value at register l is one of those, and jump ahead if not + cp PLAY_AREA_BENCH_5 + $01 + jr nc, .print_hand_or_discard_pile + +; if we make it here, we need to print a Pokemon card name. +; wInPlayAreaCurPosition determines which duelist +; and l contains the PLAY_AREA_* location of the card. + ld a, [wInPlayAreaCurPosition] + cp INPLAYAREA_PLAYER_HAND + jr nc, .opponent_side + + ld a, l + add DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + cp -1 + ret z + + call GetCardIDFromDeckIndex + call LoadCardDataToBuffer1_FromCardID + jr .display_card_name + +.opponent_side + ld a, l + add DUELVARS_ARENA_CARD + call GetNonTurnDuelistVariable + cp -1 + ret z + + call SwapTurn + call GetCardIDFromDeckIndex + call LoadCardDataToBuffer1_FromCardID + call SwapTurn + +.display_card_name + ld a, 18 + call CopyCardNameAndLevel + ld hl, wDefaultText + call ProcessText + ret + +.print_hand_or_discard_pile +; if we make it here, cursor position is to Hand or Discard Pile +; so DuelistHandText_2 or DuelistDiscardPileText will be printed + + ld a, [wInPlayAreaCurPosition] + cp INPLAYAREA_OPP_ACTIVE + jr nc, .opp_side_print_hand_or_discard_pile + call PrintTextNoDelay + ret + +.opp_side_print_hand_or_discard_pile + call SwapTurn + call PrintTextNoDelay + call SwapTurn + ret + +.show_turn_holder_play_area + lb de, $38, $9f + call SetupText + ldh a, [hWhoseTurn] + push af + bank1call OpenTurnHolderPlayAreaScreen + pop af + ldh [hWhoseTurn], a + ld a, [wInPlayAreaPreservedPosition] + ld [wInPlayAreaCurPosition], a + jp .start + +.show_non_turn_holder_play_area + lb de, $38, $9f + call SetupText + ldh a, [hWhoseTurn] + push af + bank1call OpenNonTurnHolderPlayAreaScreen + pop af + ldh [hWhoseTurn], a + ld a, [wInPlayAreaPreservedPosition] + ld [wInPlayAreaCurPosition], a + jp .start + +.jump_table ; (6:4228) + dw OpenInPlayAreaScreen_TurnHolderPlayArea ; 0x00: INPLAYAREA_PLAYER_BENCH_1 + dw OpenInPlayAreaScreen_TurnHolderPlayArea ; 0x01: INPLAYAREA_PLAYER_BENCH_2 + dw OpenInPlayAreaScreen_TurnHolderPlayArea ; 0x02: INPLAYAREA_PLAYER_BENCH_3 + dw OpenInPlayAreaScreen_TurnHolderPlayArea ; 0x03: INPLAYAREA_PLAYER_BENCH_4 + dw OpenInPlayAreaScreen_TurnHolderPlayArea ; 0x04: INPLAYAREA_PLAYER_BENCH_5 + dw OpenInPlayAreaScreen_TurnHolderPlayArea ; 0x05: INPLAYAREA_PLAYER_ACTIVE + dw OpenInPlayAreaScreen_TurnHolderHand ; 0x06: INPLAYAREA_PLAYER_HAND + dw OpenInPlayAreaScreen_TurnHolderDiscardPile ; 0x07: INPLAYAREA_PLAYER_DISCARD_PILE + dw OpenInPlayAreaScreen_NonTurnHolderPlayArea ; 0x08: INPLAYAREA_OPP_ACTIVE + dw OpenInPlayAreaScreen_NonTurnHolderHand ; 0x09: INPLAYAREA_OPP_HAND + dw OpenInPlayAreaScreen_NonTurnHolderDiscardPile ; 0x0a: INPLAYAREA_OPP_DISCARD_PILE + dw OpenInPlayAreaScreen_NonTurnHolderPlayArea ; 0x0b: INPLAYAREA_OPP_BENCH_1 + dw OpenInPlayAreaScreen_NonTurnHolderPlayArea ; 0x0c: INPLAYAREA_OPP_BENCH_2 + dw OpenInPlayAreaScreen_NonTurnHolderPlayArea ; 0x0d: INPLAYAREA_OPP_BENCH_3 + dw OpenInPlayAreaScreen_NonTurnHolderPlayArea ; 0x0e: INPLAYAREA_OPP_BENCH_4 + dw OpenInPlayAreaScreen_NonTurnHolderPlayArea ; 0x0f: INPLAYAREA_OPP_BENCH_5 + +OpenInPlayAreaScreen_TurnHolderPlayArea: + ; wInPlayAreaCurPosition constants conveniently map to (PLAY_AREA_* constants - 1) + ; for bench locations. this mapping is taken for granted in the following code. + ld a, [wInPlayAreaCurPosition] + inc a + cp INPLAYAREA_PLAYER_ACTIVE + $01 + jr nz, .on_bench + xor a ; PLAY_AREA_ARENA +.on_bench + ld [wCurPlayAreaSlot], a + add DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + cp -1 + ret z + call GetCardIDFromDeckIndex + call LoadCardDataToBuffer1_FromCardID + xor a + ld [wCurPlayAreaY], a + bank1call OpenCardPage_FromCheckPlayArea + ret + +OpenInPlayAreaScreen_NonTurnHolderPlayArea: + ld a, [wInPlayAreaCurPosition] + sub INPLAYAREA_OPP_ACTIVE + or a + jr z, .active + ; convert INPLAYAREA_OPP_BENCH_* constant to PLAY_AREA_BENCH_* constant + sub INPLAYAREA_OPP_BENCH_1 - INPLAYAREA_OPP_ACTIVE - PLAY_AREA_BENCH_1 +.active + ld [wCurPlayAreaSlot], a + add DUELVARS_ARENA_CARD + call GetNonTurnDuelistVariable + cp -1 + ret z + call SwapTurn + call GetCardIDFromDeckIndex + call LoadCardDataToBuffer1_FromCardID + xor a + ld [wCurPlayAreaY], a + bank1call OpenCardPage_FromCheckPlayArea + call SwapTurn + ret + +OpenInPlayAreaScreen_TurnHolderHand: + ldh a, [hWhoseTurn] + push af + bank1call OpenTurnHolderHandScreen_Simple + pop af + ldh [hWhoseTurn], a + ret + +OpenInPlayAreaScreen_NonTurnHolderHand: + ldh a, [hWhoseTurn] + push af + bank1call OpenNonTurnHolderHandScreen_Simple + pop af + ldh [hWhoseTurn], a + ret + +OpenInPlayAreaScreen_TurnHolderDiscardPile: + ldh a, [hWhoseTurn] + push af + bank1call OpenTurnHolderDiscardPileScreen + pop af + ldh [hWhoseTurn], a + ret + +OpenInPlayAreaScreen_NonTurnHolderDiscardPile: + ldh a, [hWhoseTurn] + push af + bank1call OpenNonTurnHolderDiscardPileScreen + pop af + ldh [hWhoseTurn], a + ret + +OpenInPlayAreaScreen_TextTable: +; note that for bench slots, the entries are +; PLAY_AREA_BENCH_* constants in practice + tx HandText ; INPLAYAREA_PLAYER_BENCH_1 + tx CheckText ; INPLAYAREA_PLAYER_BENCH_2 + tx AttackText ; INPLAYAREA_PLAYER_BENCH_3 + tx PKMNPowerText ; INPLAYAREA_PLAYER_BENCH_4 + tx DoneText ; INPLAYAREA_PLAYER_BENCH_5 + dw NULL ; INPLAYAREA_PLAYER_ACTIVE + tx DuelistHandText_2 ; INPLAYAREA_PLAYER_HAND + tx DuelistDiscardPileText ; INPLAYAREA_PLAYER_DISCARD_PILE + dw NULL ; INPLAYAREA_OPP_ACTIVE + tx DuelistHandText_2 ; INPLAYAREA_OPP_HAND + tx DuelistDiscardPileText ; INPLAYAREA_OPP_DISCARD_PILE + tx HandText ; INPLAYAREA_OPP_BENCH_1 + tx CheckText ; INPLAYAREA_OPP_BENCH_2 + tx AttackText ; INPLAYAREA_OPP_BENCH_3 + tx PKMNPowerText ; INPLAYAREA_OPP_BENCH_4 + tx DoneText ; INPLAYAREA_OPP_BENCH_5 + +in_play_area_cursor_transition: MACRO + cursor_transition \1, \2, \3, INPLAYAREA_\4, INPLAYAREA_\5, INPLAYAREA_\6, INPLAYAREA_\7 +ENDM + +; it's related to wMenuInputTablePointer. +; with this table, the cursor moves into the proper location by the input. +; note that the unit of the position is not a 8x8 tile. +OpenInPlayAreaScreen_TransitionTable1: + in_play_area_cursor_transition $18, $8c, $00, PLAYER_ACTIVE, PLAYER_PLAY_AREA, PLAYER_BENCH_2, PLAYER_BENCH_5 + in_play_area_cursor_transition $30, $8c, $00, PLAYER_ACTIVE, PLAYER_PLAY_AREA, PLAYER_BENCH_3, PLAYER_BENCH_1 + in_play_area_cursor_transition $48, $8c, $00, PLAYER_ACTIVE, PLAYER_PLAY_AREA, PLAYER_BENCH_4, PLAYER_BENCH_2 + in_play_area_cursor_transition $60, $8c, $00, PLAYER_ACTIVE, PLAYER_PLAY_AREA, PLAYER_BENCH_5, PLAYER_BENCH_3 + in_play_area_cursor_transition $78, $8c, $00, PLAYER_ACTIVE, PLAYER_PLAY_AREA, PLAYER_BENCH_1, PLAYER_BENCH_4 + in_play_area_cursor_transition $30, $6c, $00, OPP_ACTIVE, PLAYER_BENCH_1, PLAYER_DISCARD_PILE, PLAYER_DISCARD_PILE + in_play_area_cursor_transition $78, $80, $00, PLAYER_DISCARD_PILE, PLAYER_BENCH_1, PLAYER_ACTIVE, PLAYER_ACTIVE + in_play_area_cursor_transition $78, $70, $00, OPP_ACTIVE, PLAYER_HAND, PLAYER_ACTIVE, PLAYER_ACTIVE + in_play_area_cursor_transition $78, $34, 1 << OAM_X_FLIP, OPP_BENCH_1, PLAYER_ACTIVE, OPP_DISCARD_PILE, OPP_DISCARD_PILE + in_play_area_cursor_transition $30, $20, 1 << OAM_X_FLIP, OPP_BENCH_1, OPP_DISCARD_PILE, OPP_ACTIVE, OPP_ACTIVE + in_play_area_cursor_transition $30, $38, 1 << OAM_X_FLIP, OPP_BENCH_1, PLAYER_ACTIVE, OPP_ACTIVE, OPP_ACTIVE + in_play_area_cursor_transition $90, $14, 1 << OAM_X_FLIP, OPP_PLAY_AREA, OPP_ACTIVE, OPP_BENCH_5, OPP_BENCH_2 + in_play_area_cursor_transition $78, $14, 1 << OAM_X_FLIP, OPP_PLAY_AREA, OPP_ACTIVE, OPP_BENCH_1, OPP_BENCH_3 + in_play_area_cursor_transition $60, $14, 1 << OAM_X_FLIP, OPP_PLAY_AREA, OPP_ACTIVE, OPP_BENCH_2, OPP_BENCH_4 + in_play_area_cursor_transition $48, $14, 1 << OAM_X_FLIP, OPP_PLAY_AREA, OPP_ACTIVE, OPP_BENCH_3, OPP_BENCH_5 + in_play_area_cursor_transition $30, $14, 1 << OAM_X_FLIP, OPP_PLAY_AREA, OPP_ACTIVE, OPP_BENCH_4, OPP_BENCH_1 + +OpenInPlayAreaScreen_TransitionTable2: + in_play_area_cursor_transition $18, $8c, $00, PLAYER_ACTIVE, PLAYER_PLAY_AREA, PLAYER_BENCH_2, PLAYER_BENCH_5 + in_play_area_cursor_transition $30, $8c, $00, PLAYER_ACTIVE, PLAYER_PLAY_AREA, PLAYER_BENCH_3, PLAYER_BENCH_1 + in_play_area_cursor_transition $48, $8c, $00, PLAYER_ACTIVE, PLAYER_PLAY_AREA, PLAYER_BENCH_4, PLAYER_BENCH_2 + in_play_area_cursor_transition $60, $8c, $00, PLAYER_ACTIVE, PLAYER_PLAY_AREA, PLAYER_BENCH_5, PLAYER_BENCH_3 + in_play_area_cursor_transition $78, $8c, $00, PLAYER_ACTIVE, PLAYER_PLAY_AREA, PLAYER_BENCH_1, PLAYER_BENCH_4 + in_play_area_cursor_transition $30, $6c, $00, OPP_ACTIVE, PLAYER_BENCH_1, PLAYER_DISCARD_PILE, PLAYER_DISCARD_PILE + in_play_area_cursor_transition $78, $80, $00, PLAYER_DISCARD_PILE, PLAYER_BENCH_1, PLAYER_ACTIVE, PLAYER_ACTIVE + in_play_area_cursor_transition $78, $70, $00, OPP_ACTIVE, PLAYER_HAND, PLAYER_ACTIVE, PLAYER_ACTIVE + in_play_area_cursor_transition $78, $34, 1 << OAM_X_FLIP, OPP_BENCH_1, PLAYER_ACTIVE, OPP_DISCARD_PILE, OPP_DISCARD_PILE + in_play_area_cursor_transition $30, $20, 1 << OAM_X_FLIP, OPP_BENCH_1, OPP_DISCARD_PILE, OPP_ACTIVE, OPP_ACTIVE + in_play_area_cursor_transition $30, $38, 1 << OAM_X_FLIP, OPP_HAND, PLAYER_ACTIVE, OPP_ACTIVE, OPP_ACTIVE + in_play_area_cursor_transition $90, $14, 1 << OAM_X_FLIP, OPP_PLAY_AREA, OPP_ACTIVE, OPP_BENCH_5, OPP_BENCH_2 + in_play_area_cursor_transition $78, $14, 1 << OAM_X_FLIP, OPP_PLAY_AREA, OPP_ACTIVE, OPP_BENCH_1, OPP_BENCH_3 + in_play_area_cursor_transition $60, $14, 1 << OAM_X_FLIP, OPP_PLAY_AREA, OPP_ACTIVE, OPP_BENCH_2, OPP_BENCH_4 + in_play_area_cursor_transition $48, $14, 1 << OAM_X_FLIP, OPP_PLAY_AREA, OPP_ACTIVE, OPP_BENCH_3, OPP_BENCH_5 + in_play_area_cursor_transition $30, $14, 1 << OAM_X_FLIP, OPP_PLAY_AREA, OPP_ACTIVE, OPP_BENCH_4, OPP_BENCH_1 + +OpenInPlayAreaScreen_HandleInput: + xor a + ld [wPlaysSfx], a + ld hl, wMenuInputTablePointer + ld e, [hl] + inc hl + ld d, [hl] + ld a, [wInPlayAreaCurPosition] + ld l, a + ld h, $07 + call HtimesL + add hl, de + + ldh a, [hDPadHeld] + or a + jp z, .check_button + + inc hl + inc hl + inc hl + + ; check d-pad + bit D_UP_F, a + jr z, .else_if_down + + ; up + ld a, [hl] + jr .process_dpad + +.else_if_down + inc hl + bit D_DOWN_F, a + jr z, .else_if_right + + ; down + ld a, [hl] + jr .process_dpad + +.else_if_right + inc hl + bit D_RIGHT_F, a + jr z, .else_if_left + + ; right + ld a, [hl] + jr .process_dpad + +.else_if_left + inc hl + bit D_LEFT_F, a + jr z, .check_button + + ; left + ld a, [hl] +.process_dpad + push af + ld a, [wInPlayAreaCurPosition] + ld [wInPlayAreaPreservedPosition], a + pop af + + ld [wInPlayAreaCurPosition], a + cp INPLAYAREA_PLAYER_ACTIVE + jr c, .player_area + cp INPLAYAREA_OPP_BENCH_1 + jr c, .next + cp INPLAYAREA_PLAYER_PLAY_AREA + jr c, .opponent_area + + jr .next + +.player_area + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + dec a + jr nz, .bench_pokemon_exists + + ; no pokemon in player's bench. + ; then move to player's play area. + ld a, INPLAYAREA_PLAYER_PLAY_AREA + ld [wInPlayAreaCurPosition], a + jr .next + +.bench_pokemon_exists + ld b, a + ld a, [wInPlayAreaCurPosition] + cp b + jr c, .next + + ; handle index overflow + ldh a, [hDPadHeld] + bit D_RIGHT_F, a + jr z, .on_left + + xor a + ld [wInPlayAreaCurPosition], a + jr .next + +.on_left + ld a, b + dec a + ld [wInPlayAreaCurPosition], a + jr .next + +.opponent_area + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetNonTurnDuelistVariable + dec a + jr nz, .bench_pokemon_exists_2 + + ld a, INPLAYAREA_OPP_PLAY_AREA + ld [wInPlayAreaCurPosition], a + jr .next + +.bench_pokemon_exists_2 + ld b, a + ld a, [wInPlayAreaCurPosition] + sub INPLAYAREA_OPP_BENCH_1 + cp b + jr c, .next + + ldh a, [hDPadHeld] + bit D_LEFT_F, a + jr z, .on_right + + ld a, INPLAYAREA_OPP_BENCH_1 + ld [wInPlayAreaCurPosition], a + jr .next + +.on_right + ld a, b + add INPLAYAREA_OPP_DISCARD_PILE + ld [wInPlayAreaCurPosition], a +.next + ld a, $01 + ld [wPlaysSfx], a + xor a + ld [wCheckMenuCursorBlinkCounter], a +.check_button + ldh a, [hKeysPressed] + and A_BUTTON | B_BUTTON + jr z, .return + + and A_BUTTON + jr nz, .a_button + + ; pressed b button + ld a, -1 + farcall PlaySFXConfirmOrCancel + scf + ret + +.a_button + call .draw_cursor + ld a, $01 + farcall PlaySFXConfirmOrCancel + ld a, [wInPlayAreaCurPosition] + scf + ret + +.return + ld a, [wPlaysSfx] + or a + jr z, .skip_sfx + call PlaySFX +.skip_sfx + ld hl, wCheckMenuCursorBlinkCounter + ld a, [hl] + inc [hl] + and $10 - 1 + ret nz + + bit 4, [hl] ; = and $10 + jr nz, ZeroObjectPositionsAndToggleOAMCopy_Bank6 + +.draw_cursor ; 184a0 (6:44a0) + call ZeroObjectPositions + ld hl, wMenuInputTablePointer + ld e, [hl] + inc hl + ld d, [hl] + ld a, [wInPlayAreaCurPosition] + ld l, a + ld h, $07 + call HtimesL + add hl, de + + ld d, [hl] ; x position. + inc hl + ld e, [hl] ; y position. + inc hl + ld b, [hl] ; attribute. + ld c, $00 + call SetOneObjectAttributes + or a + ret + +ZeroObjectPositionsAndToggleOAMCopy_Bank6: + call ZeroObjectPositions + ld a, $01 + ld [wVBlankOAMCopyToggle], a + ret diff --git a/src/engine/menus/start.asm b/src/engine/menus/start.asm new file mode 100644 index 0000000..4d46d4a --- /dev/null +++ b/src/engine/menus/start.asm @@ -0,0 +1,418 @@ +; plays the Opening sequence, and handles player selection +; in the Title Screen and Start Menu +HandleTitleScreen: +; if last selected item in Start Menu is 0 (Card Pop!) +; then skip straight to the Start Menu +; this makes it so that returning from Card Pop! +; doesn't play the Opening sequence + ld a, [wLastSelectedStartMenuItem] + or a + jr z, .start_menu + +.play_opening + ld a, MUSIC_STOP + call PlaySong + call Func_3ca0 + call PlayIntroSequence + call LoadTitleScreenSprites + + xor a + ld [wd635], a + ld a, $3c + ld [wTitleScreenIgnoreInputCounter], a +.loop + call DoFrameIfLCDEnabled + call UpdateRNGSources + call AnimateRandomTitleScreenOrb + ld hl, wd635 + inc [hl] + call AssertSongFinished + or a + jr nz, .song_playing + ; reset back to the opening sequence + farcall Func_10ab4 + jr .play_opening + +.song_playing + ; should we ignore user input? + ld hl, wTitleScreenIgnoreInputCounter + ld a, [hl] + or a + jr z, .check_keys + ; ignore input, decrement the counter + dec [hl] + jr .loop + +.check_keys + ldh a, [hKeysPressed] + and A_BUTTON | START + jr z, .loop + ld a, SFX_02 + call PlaySFX + farcall Func_10ab4 + +.start_menu + call CheckIfHasSaveData + call HandleStartMenu + +; new game + ld a, [wStartMenuChoice] + cp START_MENU_NEW_GAME + jr nz, .continue_from_diary + call DeleteSaveDataForNewGame + jr c, HandleTitleScreen + jr .card_pop +.continue_from_diary + ld a, [wStartMenuChoice] + cp START_MENU_CONTINUE_FROM_DIARY + jr nz, .card_pop + call AskToContinueFromDiaryWithDuelData + jr c, HandleTitleScreen +.card_pop + ld a, [wStartMenuChoice] + cp START_MENU_CARD_POP + jr nz, .continue_duel + call ShowCardPopCGBDisclaimer + jr c, HandleTitleScreen +.continue_duel + call ResetDoFrameFunction + call Func_3ca0 + ret + +; updates wHasSaveData and wHasDuelSaveData +; depending on whether the save data is valid or not +CheckIfHasSaveData: + farcall ValidateBackupGeneralSaveData + ld a, TRUE + jr c, .no_error + ld a, FALSE +.no_error + ld [wHasSaveData], a + cp $00 ; or a + jr z, .write_has_duel_data + bank1call ValidateSavedNonLinkDuelData + ld a, TRUE + jr nc, .write_has_duel_data + ld a, FALSE +.write_has_duel_data + ld [wHasDuelSaveData], a + farcall ValidateBackupGeneralSaveData + ret + +; handles printing the Start Menu +; and getting player input and choice +HandleStartMenu: + ld a, MUSIC_PC_MAIN_MENU + call PlaySong + call DisableLCD + farcall Func_10000 + lb de, $30, $8f + call SetupText + call Func_3ca0 + xor a + ld [wLineSeparation], a + call .DrawPlayerPortrait + call .SetStartMenuParams + + ld a, $ff + ld [wTitleScreenIgnoreInputCounter], a + ld a, [wLastSelectedStartMenuItem] + cp $4 + jr c, .init_menu + ld a, [wHasSaveData] + or a + jr z, .init_menu + ld a, 1 ; start at second menu option +.init_menu + ld hl, wStartMenuParams + farcall InitAndPrintPauseMenu + farcall FlashWhiteScreen + +.wait_input + call DoFrameIfLCDEnabled + call UpdateRNGSources + call HandleMenuInput + push af + call PrintStartMenuDescriptionText + pop af + jr nc, .wait_input + ldh a, [hCurMenuItem] + cp e + jr nz, .wait_input + + ld [wLastSelectedStartMenuItem], a + ld a, [wHasSaveData] + or a + jr nz, .no_adjustment + ; New Game is 3rd option + ; but when there's no save data, + ; it's the 1st in menu list, so adjust it + inc e + inc e +.no_adjustment + ld a, e + ld [wStartMenuChoice], a + ret + +.SetStartMenuParams + ld hl, .StartMenuParams + ld de, wStartMenuParams + ld bc, .StartMenuParamsEnd - .StartMenuParams + call CopyDataHLtoDE + + ld e, 0 + ld a, [wHasSaveData] + or a + jr z, .get_text_id ; New Game + inc e + ld a, 2 + call .AddItems + ld a, [wHasDuelSaveData] + or a + jr z, .get_text_id ; Continue From Diary + inc e + ld a, 1 + call .AddItems + ; Continue Duel + +.get_text_id + sla e + ld d, $00 + ld hl, .StartMenuTextIDs + add hl, de + ; set text ID as Start Menu param + ld a, [hli] + ld [wStartMenuParams + 6], a + ld a, [hl] + ld [wStartMenuParams + 7], a + ret + +; adds c items to start menu list +; this means adding 2 units per item to the text box height +; and adding to the number of items +.AddItems + push bc + ld c, a + ; number of items in menu + ld a, [wStartMenuParams + 12] + add c + ld [wStartMenuParams + 12], a + ; height of text box + sla c + ld a, [wStartMenuParams + 3] + add c + ld [wStartMenuParams + 3], a + pop bc + ret + +.StartMenuParams + db 0, 0 ; start menu coords + db 14, 4 ; start menu text box dimensions + + db 2, 2 ; text alignment for InitTextPrinting + tx NewGameText + db $ff + + db 1, 2 ; cursor x, cursor y + db 2 ; y displacement between items + db 1 ; number of items + db SYM_CURSOR_R ; cursor tile number + db SYM_SPACE ; tile behind cursor + dw NULL ; function pointer if non-0 +.StartMenuParamsEnd + +.StartMenuTextIDs + tx NewGameText + tx CardPopContinueDiaryNewGameText + tx CardPopContinueDiaryNewGameContinueDuelText + +.DrawPlayerPortrait + lb bc, 14, 1 + farcall $4, DrawPlayerPortrait + ret + +; prints the description for the current selected item +; in the Start Menu in the text box +PrintStartMenuDescriptionText: + push hl + push bc + push de + ; don't print if it's already showing + ld a, [wCurMenuItem] + ld e, a + ld a, [wCurHighlightedStartMenuItem] + cp e + jr z, .skip + ld a, [wHasSaveData] + or a + jr nz, .has_data + ; New Game option is 3rd element + ; in function table, so add 2 + inc e + inc e +.has_data + + ld a, e + push af + lb de, 0, 10 + lb bc, 20, 8 + call DrawRegularTextBox + pop af + ld hl, .StartMenuDescriptionFunctionTable + call JumpToFunctionInTable +.skip + ld a, [wCurMenuItem] + ld [wCurHighlightedStartMenuItem], a + pop de + pop bc + pop hl + ret + +.StartMenuDescriptionFunctionTable + dw .CardPop + dw .ContinueFromDiary + dw .NewGame + dw .ContinueDuel + +.CardPop + lb de, 1, 12 + call InitTextPrinting + ldtx hl, WhenYouCardPopWithFriendText + call PrintTextNoDelay + ret + +.ContinueDuel + lb de, 1, 12 + call InitTextPrinting + ldtx hl, TheGameWillContinueFromThePointInTheDuelText + call PrintTextNoDelay + ret + +.NewGame + lb de, 1, 12 + call InitTextPrinting + ldtx hl, StartANewGameText + call PrintTextNoDelay + ret + +.ContinueFromDiary + ; get OW map name + ld a, [wCurOverworldMap] + add a + ld c, a + ld b, $00 + ld hl, OverworldMapNames + add hl, bc + ld a, [hli] + ld [wTxRam2 + 0], a + ld a, [hl] + ld [wTxRam2 + 1], a + + ; get medal count + ld a, [wMedalCount] + ld [wTxRam3 + 0], a + xor a + ld [wTxRam3 + 1], a + + ; print text + lb de, 1, 10 + call InitTextPrinting + ldtx hl, ContinueFromDiarySummaryText + call PrintTextNoDelay + + ld a, [wTotalNumCardsCollected] + ld d, a + ld a, [wTotalNumCardsToCollect] + ld e, a + ld bc, $90e + farcall Func_1024f + ld bc, $a10 + farcall Func_101df + ret + +; asks the player whether it's okay to delete +; the save data in order to create a new one +; if player answers "yes", delete it +DeleteSaveDataForNewGame: +; exit if there no save data + ld a, [wHasSaveData] + or a + ret z + + call DisableLCD + farcall Func_10000 + call Func_3ca0 + farcall FlashWhiteScreen + call DoFrameIfLCDEnabled + ldtx hl, SavedDataAlreadyExistsText + call PrintScrollableText_NoTextBoxLabel + ldtx hl, OKToDeleteTheDataText + call YesOrNoMenuWithText + ret c ; quit if chose "no" + farcall InvalidateSaveData + ldtx hl, AllDataWasDeletedText + call PrintScrollableText_NoTextBoxLabel + or a + ret + +; asks the player if the game should resume +; from diary even though there is Duel save data +; returns carry if "no" was selected +AskToContinueFromDiaryWithDuelData: +; return if there's no duel save data + ld a, [wHasDuelSaveData] + or a + ret z + + call DisableLCD + farcall Func_10000 + call Func_3ca0 + farcall FlashWhiteScreen + call DoFrameIfLCDEnabled + ldtx hl, DataExistsWhenPowerWasTurnedOFFDuringDuelText + call PrintScrollableText_NoTextBoxLabel + ldtx hl, ContinueFromDiaryText + call YesOrNoMenuWithText + ret c + or a + ret + +; shows disclaimer for Card Pop! +; in case player is not playing in CGB +; return carry if disclaimer was shown +ShowCardPopCGBDisclaimer: +; return if playing in CGB + ld a, [wConsole] + cp CONSOLE_CGB + ret z + + lb de, 0, 10 + lb bc, 20, 8 + call DrawRegularTextBox + lb de, 1,12 + call InitTextPrinting + ldtx hl, YouCanAccessCardPopOnlyWithGameBoyColorsText + call PrintTextNoDelay + lb bc, SYM_CURSOR_D, SYM_BOX_BOTTOM + lb de, 18, 17 + call SetCursorParametersForTextBox + call WaitForButtonAorB + scf + ret + +DrawPlayerPortraitAndPrintNewGameText: + call DisableLCD + farcall Func_10a9b + farcall Func_10000 + call Func_3ca0 + ld hl, HandleAllSpriteAnimations + call SetDoFrameFunction + lb bc, 7, 3 + farcall $4, DrawPlayerPortrait + farcall Func_10af9 + call DoFrameIfLCDEnabled + ldtx hl, IsCrazyAboutPokemonAndPokemonCardCollectingText + call PrintScrollableText_NoTextBoxLabel + call ResetDoFrameFunction + call Func_3ca0 + ret diff --git a/src/engine/menus/unknown.asm b/src/engine/menus/unknown.asm new file mode 100644 index 0000000..c6f04fa --- /dev/null +++ b/src/engine/menus/unknown.asm @@ -0,0 +1,103 @@ +Func_18661: ; unreferenced + xor a + ld [wPlaysSfx], a + ld a, [wCheckMenuCursorXPosition] + ld d, a + ld a, [wCheckMenuCursorYPosition] + ld e, a + ldh a, [hDPadHeld] + or a + jr z, .check_button +; check input from dpad + bit D_LEFT_F, a + jr nz, .left_or_right + bit D_RIGHT_F, a + jr z, .check_up_and_down +.left_or_right +; swap the lsb of x position value. + ld a, d + xor $1 + ld d, a + jr .cursor_moved + +.check_up_and_down + bit D_UP_F, a + jr nz, .up_or_down + bit D_DOWN_F, a + jr z, .check_button +.up_or_down + ld a, e + xor $1 + ld e, a +.cursor_moved + ld a, $1 + ld [wPlaysSfx], a + push de + call .draw_blank_cursor + pop de + ld a, d + ld [wCheckMenuCursorXPosition], a + ld a, e + ld [wCheckMenuCursorYPosition], a + xor a + ld [wCheckMenuCursorBlinkCounter], a +.check_button + ldh a, [hKeysPressed] + and A_BUTTON | B_BUTTON + jr z, .check_cursor_moved + and A_BUTTON + jr nz, .a_button + +; b button + ld a, -1 + call Func_190fb + scf + ret + +; a button +.a_button + call .draw_cursor + ld a, 1 + call Func_190fb + scf + ret + +.check_cursor_moved + ld a, [wPlaysSfx] + or a + jr z, .check_cursor_blink + call PlaySFX +.check_cursor_blink + ld hl, wCheckMenuCursorBlinkCounter + ld a, [hl] + inc [hl] + and %00001111 + ret nz + ld a, SYM_CURSOR_R + bit D_RIGHT_F, [hl] + jr z, .draw_tile +.draw_blank_cursor ; 186d4 (6:46d4) + ld a, SYM_SPACE +.draw_tile + ld e, a + ld a, 10 + ld l, a + ld a, [wCheckMenuCursorXPosition] + ld h, a + call HtimesL + ld a, l + add 1 + ld b, a + ld a, [wCheckMenuCursorYPosition] + sla a + add 14 + ld c, a + ld a, e + ; b = 11, c = y_pos * 2 + 14 + ; h = x_pos * 10, l = 10 + call WriteByteToBGMap0 + or a + ret +.draw_cursor ; 186f3 (6:46f3) + ld a, SYM_CURSOR_R + jr .draw_tile |