diff options
Diffstat (limited to 'src/home/menus.asm')
-rw-r--r-- | src/home/menus.asm | 974 |
1 files changed, 974 insertions, 0 deletions
diff --git a/src/home/menus.asm b/src/home/menus.asm new file mode 100644 index 0000000..9c1f274 --- /dev/null +++ b/src/home/menus.asm @@ -0,0 +1,974 @@ +; initializes parameters for a card list (e.g. list of hand cards in a duel, or booster pack cards) +; input: + ; a = list length + ; de = initial page scroll offset, initial item (in the visible page) + ; hl: 9 bytes with the rest of the parameters +InitializeCardListParameters: + ld [wNumListItems], a + ld a, d + ld [wListScrollOffset], a + ld a, e + ld [wCurMenuItem], a + add d + ldh [hCurMenuItem], a + ld a, [hli] + ld [wCursorXPosition], a + ld a, [hli] + ld [wCursorYPosition], a + ld a, [hli] + ld [wListItemXPosition], a + ld a, [hli] + ld [wListItemNameMaxLength], a + ld a, [hli] + ld [wNumMenuItems], a + ld a, [hli] + ld [wCursorTile], a + ld a, [hli] + ld [wTileBehindCursor], a + ld a, [hli] + ld [wListFunctionPointer], a + ld a, [hli] + ld [wListFunctionPointer + 1], a + xor a + ld [wCursorBlinkCounter], a + ld a, 1 + ld [wYDisplacementBetweenMenuItems], a + ret + +; similar to HandleMenuInput, but conveniently returns parameters related to the +; state of the list in a, d, and e if A or B were pressed. also returns carry +; if A or B were pressed, nc otherwise. returns -1 in a if B was pressed. +; used for example in the Hand card list and Discard Pile card list screens. +HandleCardListInput: + call HandleMenuInput + ret nc + ld a, [wListScrollOffset] + ld d, a + ld a, [wCurMenuItem] + ld e, a + ldh a, [hCurMenuItem] + scf + ret + +; initializes parameters for a menu, given the 8 bytes starting at hl, +; which are loaded to the following addresses: +; wCursorXPosition, wCursorYPosition, wYDisplacementBetweenMenuItems, wNumMenuItems, +; wCursorTile, wTileBehindCursor, wMenuFunctionPointer. +; also sets the current menu item (wCurMenuItem) to the one specified in register a. +InitializeMenuParameters: + ld [wCurMenuItem], a + ldh [hCurMenuItem], a + ld de, wCursorXPosition + ld b, wMenuFunctionPointer + $2 - wCursorXPosition +.loop + ld a, [hli] + ld [de], a + inc de + dec b + jr nz, .loop + xor a + ld [wCursorBlinkCounter], a + ret + +; returns with the carry flag set if A or B were pressed +; returns a = 0 if A was pressed, a = -1 if B was pressed +; note: return values still subject to those of the function at [wMenuFunctionPointer] if any +HandleMenuInput: + xor a + ld [wRefreshMenuCursorSFX], a + ldh a, [hDPadHeld] + or a + jr z, .up_down_done + ld b, a + ld a, [wNumMenuItems] + ld c, a + ld a, [wCurMenuItem] + bit D_UP_F, b + jr z, .not_up + dec a + bit 7, a + jr z, .handle_up_or_down + ld a, [wNumMenuItems] + dec a ; wrapping around, so load the bottommost item + jr .handle_up_or_down +.not_up + bit D_DOWN_F, b + jr z, .up_down_done + inc a + cp c + jr c, .handle_up_or_down + xor a ; wrapping around, so load the topmost item +.handle_up_or_down + push af + ld a, $1 + ld [wRefreshMenuCursorSFX], a ; buffer sound for up/down + call EraseCursor + pop af + ld [wCurMenuItem], a + xor a + ld [wCursorBlinkCounter], a +.up_down_done + ld a, [wCurMenuItem] + ldh [hCurMenuItem], a + ld hl, wMenuFunctionPointer ; call the function if non-0 (periodically) + ld a, [hli] + or [hl] + jr z, .check_A_or_B + ld a, [hld] + ld l, [hl] + ld h, a + ldh a, [hCurMenuItem] + call CallHL + jr nc, RefreshMenuCursor_CheckPlaySFX +.A_pressed_draw_cursor + call DrawCursor2 +.A_pressed + call PlayOpenOrExitScreenSFX + ld a, [wCurMenuItem] + ld e, a + ldh a, [hCurMenuItem] + scf + ret +.check_A_or_B + ldh a, [hKeysPressed] + and A_BUTTON | B_BUTTON + jr z, RefreshMenuCursor_CheckPlaySFX + and A_BUTTON + jr nz, .A_pressed_draw_cursor + ; B button pressed + ld a, [wCurMenuItem] + ld e, a + ld a, $ff + ldh [hCurMenuItem], a + call PlayOpenOrExitScreenSFX + scf + ret + +; plays an "open screen" sound (SFX_02) if [hCurMenuItem] != 0xff +; plays an "exit screen" sound (SFX_03) if [hCurMenuItem] == 0xff +PlayOpenOrExitScreenSFX: + push af + ldh a, [hCurMenuItem] + inc a + jr z, .play_exit_sfx + ld a, SFX_02 + jr .play_sfx +.play_exit_sfx + ld a, SFX_03 +.play_sfx + call PlaySFX + pop af + ret + +; called once per frame when a menu is open +; play the sound effect at wRefreshMenuCursorSFX if non-0 and blink the +; cursor when wCursorBlinkCounter hits 16 (i.e. every 16 frames) +RefreshMenuCursor_CheckPlaySFX: + ld a, [wRefreshMenuCursorSFX] + or a + jr z, RefreshMenuCursor + call PlaySFX +; fallthrough + +RefreshMenuCursor: + ld hl, wCursorBlinkCounter + ld a, [hl] + inc [hl] +; blink the cursor every 16 frames + and $f + ret nz + ld a, [wCursorTile] + bit 4, [hl] + jr z, DrawCursor +; fallthrough + +; set the tile at [wCursorXPosition],[wCursorYPosition] to [wTileBehindCursor] +EraseCursor: + ld a, [wTileBehindCursor] +; fallthrough + +; set the tile at [wCursorXPosition],[wCursorYPosition] to a +DrawCursor: + ld c, a + ld a, [wYDisplacementBetweenMenuItems] + ld l, a + ld a, [wCurMenuItem] + ld h, a + call HtimesL + ld a, l + ld hl, wCursorXPosition + ld d, [hl] + inc hl + add [hl] + ld e, a + call AdjustCoordinatesForBGScroll + ld a, c + ld c, e + ld b, d + call WriteByteToBGMap0 + or a + ret + +; set the tile at [wCursorXPosition],[wCursorYPosition] to [wCursorTile] +DrawCursor2: + ld a, [wCursorTile] + jr DrawCursor + +; set wCurMenuItem, and hCurMenuItem to a, and zero wCursorBlinkCounter +SetMenuItem: + ld [wCurMenuItem], a + ldh [hCurMenuItem], a + xor a + ld [wCursorBlinkCounter], a + ret + +; handle input for the 2-row 3-column duel menu. +; only handles input not involving the B, START, or SELECT buttons, that is, +; navigating through the menu or selecting an item with the A button. +; other input in handled by PrintDuelMenuAndHandleInput.handle_input +HandleDuelMenuInput: + ldh a, [hDPadHeld] + or a + jr z, .blink_cursor + ld b, a + ld hl, wCurMenuItem + and D_UP | D_DOWN + jr z, .check_left + ld a, [hl] + xor 1 ; move to the other menu item in the same column + jr .dpad_pressed +.check_left + bit D_LEFT_F, b + jr z, .check_right + ld a, [hl] + sub 2 + jr nc, .dpad_pressed + ; wrap to the rightmost item in the same row + and 1 + add 4 + jr .dpad_pressed +.check_right + bit D_RIGHT_F, b + jr z, .dpad_not_pressed + ld a, [hl] + add 2 + cp 6 + jr c, .dpad_pressed + ; wrap to the leftmost item in the same row + and 1 +.dpad_pressed + push af + ld a, SFX_01 + call PlaySFX + call .erase_cursor + pop af + ld [wCurMenuItem], a + ldh [hCurMenuItem], a + xor a + ld [wCursorBlinkCounter], a + jr .blink_cursor +.dpad_not_pressed + ldh a, [hDPadHeld] + and A_BUTTON + jp nz, HandleMenuInput.A_pressed +.blink_cursor + ; blink cursor every 16 frames + ld hl, wCursorBlinkCounter + ld a, [hl] + inc [hl] + and $f + ret nz + ld a, SYM_CURSOR_R + bit 4, [hl] + jr z, .draw_cursor +.erase_cursor + ld a, SYM_SPACE +.draw_cursor + ld e, a + ld a, [wCurMenuItem] + add a + ld c, a + ld b, $0 + ld hl, DuelMenuCursorCoords + add hl, bc + ld b, [hl] + inc hl + ld c, [hl] + ld a, e + call WriteByteToBGMap0 + ld a, [wCurMenuItem] + ld e, a + or a + ret + +DuelMenuCursorCoords: + db 2, 14 ; Hand + db 2, 16 ; Attack + db 8, 14 ; Check + db 8, 16 ; Pkmn Power + db 14, 14 ; Retreat + db 14, 16 ; Done + +; print the items of a list of cards (hand cards in a duel, cards from a booster pack...) +; and initialize the parameters of the list given: + ; wDuelTempList = card list source + ; a = list length + ; de = initial page scroll offset, initial item (in the visible page) + ; hl: 9 bytes with the rest of the parameters +PrintCardListItems: + call InitializeCardListParameters + ld hl, wMenuFunctionPointer + ld a, LOW(CardListMenuFunction) + ld [hli], a + ld a, HIGH(CardListMenuFunction) + ld [hli], a + ld a, 2 + ld [wYDisplacementBetweenMenuItems], a + ld a, 1 + ld [wCardListIndicatorYPosition], a +; fallthrough + +; like PrintCardListItems, except more parameters are already initialized +; called instead of PrintCardListItems to reload the list after moving up or down +ReloadCardListItems: + ld e, SYM_SPACE + ld a, [wListScrollOffset] + or a + jr z, .cant_go_up + ld e, SYM_CURSOR_U +.cant_go_up + ld a, [wCursorYPosition] + dec a + ld c, a + ld b, 18 + ld a, e + call WriteByteToBGMap0 + ld e, SYM_SPACE + ld a, [wListScrollOffset] + ld hl, wNumMenuItems + add [hl] + ld hl, wNumListItems + cp [hl] + jr nc, .cant_go_down + ld e, SYM_CURSOR_D +.cant_go_down + ld a, [wNumMenuItems] + add a + add c + dec a + ld c, a + ld a, e + call WriteByteToBGMap0 + ld a, [wListScrollOffset] + ld e, a + ld d, $00 + ld hl, wDuelTempList + add hl, de + ld a, [wNumMenuItems] + ld b, a + ld a, [wListItemXPosition] + ld d, a + ld a, [wCursorYPosition] + ld e, a + ld c, $00 +.next_card + ld a, [hl] + cp $ff + jr z, .done + push hl + push bc + push de + call LoadCardDataToBuffer1_FromDeckIndex + call DrawCardSymbol + call InitTextPrinting + ld a, [wListItemNameMaxLength] + call CopyCardNameAndLevel + ld hl, wDefaultText + call ProcessText + pop de + pop bc + pop hl + inc hl + ld a, [wNumListItems] + dec a + inc c + cp c + jr c, .done + inc e + inc e + dec b + jr nz, .next_card +.done + ret + +; reload a list of cards, except don't print their names +Func_2827: + ld a, $01 + ldh [hffb0], a + call ReloadCardListItems + xor a + ldh [hffb0], a + ret + +; convert the number at a to TX_SYMBOL text format and write it to wDefaultText +; if the first digit is a 0, delete it and shift the number one tile to the left +OneByteNumberToTxSymbol_TrimLeadingZerosAndAlign: + call OneByteNumberToTxSymbol + ld a, [hli] + cp SYM_0 + jr nz, .not_zero + ; shift number one tile to the left + ld a, [hld] + ld [hli], a + ld [hl], SYM_SPACE +.not_zero + ret + +; this function is always loaded to wMenuFunctionPointer by PrintCardListItems +; takes care of things like handling page scrolling and calling the function at wListFunctionPointer +CardListMenuFunction: + ldh a, [hDPadHeld] + ld b, a + ld a, [wNumMenuItems] + dec a + ld c, a + ld a, [wCurMenuItem] + bit D_UP_F, b + jr z, .not_up + cp c + jp nz, .continue + ; we're at the top of the page + xor a + ld [wCurMenuItem], a ; set to first item + ld hl, wListScrollOffset + ld a, [hl] + or a ; can we scroll up? + jr z, .no_more_items + dec [hl] ; scroll page up + call ReloadCardListItems + jp .continue +.not_up + bit D_DOWN_F, b + jr z, .not_down + or a + jr nz, .not_last_visible_item + ; we're at the bottom of the page + ld a, c + ld [wCurMenuItem], a ; set to last item + ld a, [wListScrollOffset] + add c + inc a + ld hl, wNumListItems + cp [hl] ; can we scroll down? + jr z, .no_more_items + ld hl, wListScrollOffset + inc [hl] ; scroll page down + call ReloadCardListItems + jp .continue +.not_last_visible_item + ; this appears to be a redundant check + ld hl, wListScrollOffset + add [hl] + ld hl, wNumListItems + cp [hl] + jp c, .continue ; should always jump + ld hl, wCurMenuItem + dec [hl] +.no_more_items + xor a + ld [wRefreshMenuCursorSFX], a + jp .continue +.not_down + bit D_LEFT_F, b + jr z, .not_left + ld a, [wListScrollOffset] + or a + jr z, .continue + ld hl, wNumMenuItems + sub [hl] + jr c, .top_of_page_reached + ld [wListScrollOffset], a + call ReloadCardListItems + jr .continue +.top_of_page_reached + call EraseCursor + ld a, [wListScrollOffset] + ld hl, wCurMenuItem + add [hl] + ld c, a + ld hl, wNumMenuItems + sub [hl] + jr nc, .asm_28c4 + add [hl] +.asm_28c4 + ld [wCurMenuItem], a + xor a + ld [wListScrollOffset], a + ld [wRefreshMenuCursorSFX], a + call ReloadCardListItems + jr .continue +.not_left + bit D_RIGHT_F, b + jr z, .continue + ld a, [wNumMenuItems] + ld hl, wNumListItems + cp [hl] + jr nc, .continue + ld a, [wListScrollOffset] + ld hl, wNumMenuItems + add [hl] + ld c, a + add [hl] + dec a + ld hl, wNumListItems + cp [hl] + jr nc, .asm_28f9 + ld a, c + ld [wListScrollOffset], a + call ReloadCardListItems + jr .continue +.asm_28f9 + call EraseCursor + ld a, [wListScrollOffset] + ld hl, wCurMenuItem + add [hl] + ld c, a + ld a, [wNumListItems] + ld hl, wNumMenuItems + sub [hl] + ld [wListScrollOffset], a + ld b, a + ld a, c + sub b + jr nc, .asm_2914 + add [hl] +.asm_2914 + ld [wCurMenuItem], a + call ReloadCardListItems +.continue + ld a, [wListScrollOffset] + ld hl, wCurMenuItem + add [hl] + ldh [hCurMenuItem], a + ld a, [wCardListIndicatorYPosition] + cp $ff + jr z, .skip_printing_indicator + ; print <sel_item>/<num_items> + ld c, a + ldh a, [hCurMenuItem] + inc a + call OneByteNumberToTxSymbol_TrimLeadingZeros + ld b, 13 + ld a, 2 + call CopyDataToBGMap0 + ld b, 15 + ld a, SYM_SLASH + call WriteByteToBGMap0 + ld a, [wNumListItems] + call OneByteNumberToTxSymbol_TrimLeadingZeros + ld b, 16 + ld a, 2 + call CopyDataToBGMap0 +.skip_printing_indicator + ld hl, wListFunctionPointer + ld a, [hli] + or [hl] + jr z, .no_list_function + ld a, [hld] + ld l, [hl] + ld h, a + ldh a, [hCurMenuItem] + jp hl ; execute the function at wListFunctionPointer +.no_list_function + ldh a, [hKeysPressed] + and A_BUTTON | B_BUTTON + ret z + and B_BUTTON + jr nz, .pressed_b + scf + ret +.pressed_b + ld a, $ff + ldh [hCurMenuItem], a + scf + ret + +; convert the number at a to TX_SYMBOL text format and write it to wDefaultText +; replace leading zeros with SYM_SPACE +OneByteNumberToTxSymbol_TrimLeadingZeros: + call OneByteNumberToTxSymbol + ld a, [hl] + cp SYM_0 + ret nz + ld [hl], SYM_SPACE + ret + +; convert the number at a to TX_SYMBOL text format and write it to wDefaultText +OneByteNumberToTxSymbol: + ld hl, wDefaultText + push hl + ld e, SYM_0 - 1 +.first_digit_loop + inc e + sub 10 + jr nc, .first_digit_loop + ld [hl], e ; first digit + inc hl + add SYM_0 + 10 + ld [hli], a ; second digit + ld [hl], SYM_SPACE + pop hl + ret + +; translate the TYPE_* constant in wLoadedCard1Type to an index for CardSymbolTable +CardTypeToSymbolID: + ld a, [wLoadedCard1Type] + cp TYPE_TRAINER + jr nc, .trainer_card + cp TYPE_ENERGY + jr c, .pokemon_card + ; energy card + and 7 ; convert energy constant to type constant + ret +.trainer_card + ld a, 11 + ret +.pokemon_card + ld a, [wLoadedCard1Stage] ; different symbol for each evolution stage + add 8 + ret + +; return the entry in CardSymbolTable of the TYPE_* constant in wLoadedCard1Type +; also return the first byte of said entry (starting tile number) in a +GetCardSymbolData: + call CardTypeToSymbolID + add a + ld c, a + ld b, 0 + ld hl, CardSymbolTable + add hl, bc + ld a, [hl] + ret + +; draw, at de, the 2x2 tile card symbol associated to the TYPE_* constant in wLoadedCard1Type +DrawCardSymbol: + push hl + push de + push bc + call GetCardSymbolData + dec d + dec d + dec e + ld a, [wConsole] + cp CONSOLE_CGB + jr nz, .tiles + ; CGB-only attrs (palette) + push hl + inc hl + ld a, [hl] + lb bc, 2, 2 + lb hl, 0, 0 + call BankswitchVRAM1 + call FillRectangle + call BankswitchVRAM0 + pop hl +.tiles + ld a, [hl] + lb hl, 1, 2 + lb bc, 2, 2 + call FillRectangle + pop bc + pop de + pop hl + ret + +CardSymbolTable: +; starting tile number, cgb palette (grey, yellow/red, green/blue, pink/orange) + db $e0, $01 ; TYPE_ENERGY_FIRE + db $e4, $02 ; TYPE_ENERGY_GRASS + db $e8, $01 ; TYPE_ENERGY_LIGHTNING + db $ec, $02 ; TYPE_ENERGY_WATER + db $f0, $03 ; TYPE_ENERGY_PSYCHIC + db $f4, $03 ; TYPE_ENERGY_FIGHTING + db $f8, $00 ; TYPE_ENERGY_DOUBLE_COLORLESS + db $fc, $02 ; TYPE_ENERGY_UNUSED + db $d0, $02 ; TYPE_PKMN_*, Basic + db $d4, $02 ; TYPE_PKMN_*, Stage 1 + db $d8, $01 ; TYPE_PKMN_*, Stage 2 + db $dc, $02 ; TYPE_TRAINER + +; copy the name and level of the card at wLoadedCard1 to wDefaultText +; a = length in number of tiles (the resulting string will be padded with spaces to match it) +CopyCardNameAndLevel: + farcall _CopyCardNameAndLevel + ret + +; sets cursor parameters for navigating in a text box, but using +; default values for the cursor tile (SYM_CURSOR_R) and the tile behind it (SYM_SPACE). +; d,e: coordinates of the cursor +SetCursorParametersForTextBox_Default: + lb bc, SYM_CURSOR_R, SYM_SPACE ; cursor tile, tile behind cursor + call SetCursorParametersForTextBox +; fallthrough + +; wait until A or B is pressed. +; return carry if A is pressed, nc if B is pressed. erase the cursor either way +WaitForButtonAorB: + call DoFrame + call RefreshMenuCursor + ldh a, [hKeysPressed] + bit A_BUTTON_F, a + jr nz, .a_pressed + bit B_BUTTON_F, a + jr z, WaitForButtonAorB + call EraseCursor + scf + ret +.a_pressed + call EraseCursor + or a + ret + +; sets cursor parameters for navigating in a text box +; d,e: coordinates of the cursor +; b,c: tile numbers of the cursor and of the tile behind it +SetCursorParametersForTextBox: + xor a + ld hl, wCurMenuItem + ld [hli], a + ld [hl], d ; wCursorXPosition + inc hl + ld [hl], e ; wCursorYPosition + inc hl + ld [hl], 0 ; wYDisplacementBetweenMenuItems + inc hl + ld [hl], 1 ; wNumMenuItems + inc hl + ld [hl], b ; wCursorTile + inc hl + ld [hl], c ; wTileBehindCursor + ld [wCursorBlinkCounter], a + ret + +; draw a 20x6 text box aligned to the bottom of the screen, +; print the text at hl without letter delay, and wait for A or B pressed +DrawWideTextBox_PrintTextNoDelay_Wait: + call DrawWideTextBox_PrintTextNoDelay + jp WaitForWideTextBoxInput + +; draw a 20x6 text box aligned to the bottom of the screen +; and print the text at hl without letter delay +DrawWideTextBox_PrintTextNoDelay: + push hl + call DrawWideTextBox + ld a, 19 + jr DrawTextBox_PrintTextNoDelay + +; draw a 12x6 text box aligned to the bottom left of the screen +; and print the text at hl without letter delay +DrawNarrowTextBox_PrintTextNoDelay: + push hl + call DrawNarrowTextBox + ld a, 11 +; fallthrough + +DrawTextBox_PrintTextNoDelay: + lb de, 1, 14 + call AdjustCoordinatesForBGScroll + call InitTextPrintingInTextbox + pop hl + ld a, l + or h + jp nz, PrintTextNoDelay + ld hl, wDefaultText + jp ProcessText + +; draw a 20x6 text box aligned to the bottom of the screen +; and print the text at hl with letter delay +DrawWideTextBox_PrintText: + push hl + call DrawWideTextBox + ld a, 19 + lb de, 1, 14 + call AdjustCoordinatesForBGScroll + call InitTextPrintingInTextbox + call EnableLCD + pop hl + jp PrintText + +; draw a 12x6 text box aligned to the bottom left of the screen +DrawNarrowTextBox: + lb de, 0, 12 + lb bc, 12, 6 + call AdjustCoordinatesForBGScroll + call DrawRegularTextBox + ret + +; draw a 12x6 text box aligned to the bottom left of the screen, +; print the text at hl without letter delay, and wait for A or B pressed +DrawNarrowTextBox_WaitForInput: + call DrawNarrowTextBox_PrintTextNoDelay + xor a + ld hl, NarrowTextBoxMenuParameters + call InitializeMenuParameters + call EnableLCD +.wait_A_or_B_loop + call DoFrame + call RefreshMenuCursor + ldh a, [hKeysPressed] + and A_BUTTON | B_BUTTON + jr z, .wait_A_or_B_loop + ret + +NarrowTextBoxMenuParameters: + db 10, 17 ; cursor x, cursor y + db 1 ; y displacement between items + db 1 ; number of items + db SYM_CURSOR_D ; cursor tile number + db SYM_BOX_BOTTOM ; tile behind cursor + dw NULL ; function pointer if non-0 + +; draw a 20x6 text box aligned to the bottom of the screen +DrawWideTextBox: + lb de, 0, 12 + lb bc, 20, 6 + call AdjustCoordinatesForBGScroll + call DrawRegularTextBox + ret + +; draw a 20x6 text box aligned to the bottom of the screen, +; print the text at hl with letter delay, and wait for A or B pressed +DrawWideTextBox_WaitForInput: + call DrawWideTextBox_PrintText +; fallthrough + +; wait for A or B to be pressed on a wide (20x6) text box +WaitForWideTextBoxInput: + xor a + ld hl, WideTextBoxMenuParameters + call InitializeMenuParameters + call EnableLCD +.wait_A_or_B_loop + call DoFrame + call RefreshMenuCursor + ldh a, [hKeysPressed] + and A_BUTTON | B_BUTTON + jr z, .wait_A_or_B_loop + call EraseCursor + ret + +WideTextBoxMenuParameters: + db 18, 17 ; cursor x, cursor y + db 1 ; y displacement between items + db 1 ; number of items + db SYM_CURSOR_D ; cursor tile number + db SYM_BOX_BOTTOM ; tile behind cursor + dw NULL ; function pointer if non-0 + +; display a two-item horizontal menu with custom text provided in hl and handle input +TwoItemHorizontalMenu: + call DrawWideTextBox_PrintText + lb de, 6, 16 ; x, y + ld a, d + ld [wLeftmostItemCursorX], a + lb bc, SYM_CURSOR_R, SYM_SPACE ; cursor tile, tile behind cursor + call SetCursorParametersForTextBox + ld a, 1 + ld [wCurMenuItem], a + call EnableLCD + jp HandleYesOrNoMenu.refresh_menu + +YesOrNoMenuWithText_SetCursorToYes: + ld a, $01 + ld [wDefaultYesOrNo], a +; fallthrough + +; display a yes / no menu in a 20x8 textbox with custom text provided in hl and handle input +; wDefaultYesOrNo determines whether the cursor initially points to YES or to NO +; returns carry if "no" selected +YesOrNoMenuWithText: + call DrawWideTextBox_PrintText +; fallthrough + +; prints the YES / NO menu items at coordinates x,y = 7,16 and handles input +; input: wDefaultYesOrNo. returns carry if "no" selected +YesOrNoMenu: + lb de, 7, 16 ; x, y + call PrintYesOrNoItems + lb de, 6, 16 ; x, y + jr HandleYesOrNoMenu + +; prints the YES / NO menu items at coordinates x,y = 3,16 and handles input +; input: wDefaultYesOrNo. returns carry if "no" selected +YesOrNoMenuWithText_LeftAligned: + call DrawNarrowTextBox_PrintTextNoDelay + lb de, 3, 16 ; x, y + call PrintYesOrNoItems + lb de, 2, 16 ; x, y +; fallthrough + +HandleYesOrNoMenu: + ld a, d + ld [wLeftmostItemCursorX], a + lb bc, SYM_CURSOR_R, SYM_SPACE ; cursor tile, tile behind cursor + call SetCursorParametersForTextBox + ld a, [wDefaultYesOrNo] + ld [wCurMenuItem], a + call EnableLCD + jr .refresh_menu +.wait_button_loop + call DoFrame + call RefreshMenuCursor + ldh a, [hKeysPressed] + bit A_BUTTON_F, a + jr nz, .a_pressed + ldh a, [hDPadHeld] + and D_RIGHT | D_LEFT + jr z, .wait_button_loop + ; left or right pressed, so switch to the other menu item + ld a, SFX_01 + call PlaySFX + call EraseCursor +.refresh_menu + ld a, [wLeftmostItemCursorX] + ld c, a + ; default to the second option (NO) + ld hl, wCurMenuItem + ld a, [hl] + xor $1 + ld [hl], a + ; x separation between left and right items is 4 tiles + add a + add a + add c + ld [wCursorXPosition], a + xor a + ld [wCursorBlinkCounter], a + jr .wait_button_loop +.a_pressed + ld a, [wCurMenuItem] + ldh [hCurMenuItem], a + or a + jr nz, .no +;.yes + ld [wDefaultYesOrNo], a ; 0 + ret +.no + xor a + ld [wDefaultYesOrNo], a ; 0 + ld a, 1 + ldh [hCurMenuItem], a + scf + ret + +; prints "YES NO" at de +PrintYesOrNoItems: + call AdjustCoordinatesForBGScroll + ldtx hl, YesOrNoText + call InitTextPrinting_ProcessTextFromID + ret + +ContinueDuel: + ld a, BANK(_ContinueDuel) + call BankswitchROM + jp _ContinueDuel |