; goes through whole deck in hl ; for each card ID, goes to its corresponding ; entry in sCardCollection and decrements its count DecrementDeckCardsInCollection: push hl ld b, $0 ld d, DECK_SIZE .loop_deck ld a, [hli] or a jr z, .done ld c, a push hl ld hl, sCardCollection add hl, bc dec [hl] pop hl dec d jr nz, .loop_deck .done pop hl ret ; like AddDeckToCollection, but takes care to ; check if increasing the collection count would ; go over MAX_AMOUNT_OF_CARD and caps it ; this is because it's used within Gift Center, ; so we cannot assume that the deck configuration ; won't make it go over MAX_AMOUNT_OF_CARD ; hl = deck configuration, with cards to add AddGiftCenterDeckCardsToCollection: push hl ld b, $0 ld d, DECK_SIZE .loop_deck ld a, [hli] or a jr z, .done ld c, a push hl push de push bc ld a, ALL_DECKS call CreateCardCollectionListWithDeckCards pop bc pop de ld hl, wTempCardCollection add hl, bc ld a, [hl] cp MAX_AMOUNT_OF_CARD jr z, .next_card ; capped call EnableSRAM ; no DisableSRAM ld hl, sCardCollection add hl, bc ld a, [hl] cp CARD_NOT_OWNED jr nz, .incr ; not owned xor a ld [hl], a .incr inc [hl] .next_card pop hl dec d jr nz, .loop_deck .done pop hl ret ; adds all cards in deck in hl to player's collection ; assumes SRAM is enabled ; hl = pointer to deck cards AddDeckToCollection: push hl ld b, $0 ld d, DECK_SIZE .loop_deck ld a, [hli] or a jr z, .done ld c, a push hl ld hl, sCardCollection add hl, bc inc [hl] pop hl dec d jr nz, .loop_deck .done pop hl ret ; draws the screen which shows the player's current ; deck configurations ; a = DECK_* flags to pick which deck names to show DrawDecksScreen: ld [hffb5], a call EmptyScreenAndLoadFontDuelAndHandCardsIcons lb de, 0, 0 lb bc, 20, 4 call DrawRegularTextBox lb de, 0, 3 lb bc, 20, 4 call DrawRegularTextBox lb de, 0, 6 lb bc, 20, 4 call DrawRegularTextBox lb de, 0, 9 lb bc, 20, 4 call DrawRegularTextBox ld hl, DeckNameMenuData call PlaceTextItems ; mark all decks as invalid ld a, NUM_DECKS ld hl, wDecksValid call ClearNBytesFromHL ; for each deck, check if it has cards and if so ; mark is as valid in wDecksValid ; deck 1 ld a, [hffb5] ; should be ldh bit 0, a jr z, .skip_name_1 ld hl, sDeck1Name lb de, 6, 2 call PrintDeckName .skip_name_1 ld hl, sDeck1Cards call CheckIfDeckHasCards jr c, .deck_2 ld a, TRUE ld [wDeck1Valid], a .deck_2 ld a, [hffb5] ; should be ldh bit 1, a jr z, .skip_name_2 ld hl, sDeck2Name lb de, 6, 5 call PrintDeckName .skip_name_2 ld hl, sDeck2Cards call CheckIfDeckHasCards jr c, .deck_3 ld a, TRUE ld [wDeck2Valid], a .deck_3 ld a, [hffb5] ; should be ldh bit 2, a jr z, .skip_name_3 ld hl, sDeck3Name lb de, 6, 8 call PrintDeckName .skip_name_3 ld hl, sDeck3Cards call CheckIfDeckHasCards jr c, .deck_4 ld a, TRUE ld [wDeck3Valid], a .deck_4 ld a, [hffb5] ; should be ldh bit 3, a jr z, .skip_name_4 ld hl, sDeck4Name lb de, 6, 11 call PrintDeckName .skip_name_4 ld hl, sDeck4Cards call CheckIfDeckHasCards jr c, .place_cursor ld a, TRUE ld [wDeck4Valid], a .place_cursor ; places cursor on sCurrentlySelectedDeck ; if it's an empty deck, then advance the cursor ; until it's selecting a valid deck call EnableSRAM ld a, [sCurrentlySelectedDeck] ld c, a ld b, $0 ld d, 2 .check_valid_deck ld hl, wDecksValid add hl, bc ld a, [hl] or a jr nz, .valid_selected_deck inc c ld a, NUM_DECKS cp c jr nz, .check_valid_deck ld c, 0 ; roll back to deck 1 dec d jr z, .valid_selected_deck jr .check_valid_deck .valid_selected_deck ld a, c ld [sCurrentlySelectedDeck], a call DisableSRAM call DrawHandCardsTileOnCurDeck call EnableLCD ret DeckNameMenuData: textitem 4, 2, Deck1Text textitem 4, 5, Deck2Text textitem 4, 8, Deck3Text textitem 4, 11, Deck4Text db $ff ; copies text from hl to wDefaultText ; with " deck" appended to the end ; hl = ptr to deck name CopyDeckName: ld de, wDefaultText call CopyListFromHLToDE ld hl, wDefaultText call GetTextLengthInTiles ld b, $0 ld hl, wDefaultText add hl, bc ld d, h ld e, l ld hl, DeckNameSuffix call CopyListFromHLToDE ret ; prints deck name given in hl in position de ; if it's an empty deck, print "NEW DECK" instead ; returns carry if it's an empty deck ; hl = deck name (sDeck1Name ~ sDeck4Name) ; de = coordinates to print text PrintDeckName: push hl call CheckIfDeckHasCards pop hl jr c, .new_deck ; print " deck" push de ld de, wDefaultText call CopyListFromHLToDEInSRAM ld hl, wDefaultText call GetTextLengthInTiles ld b, $0 ld hl, wDefaultText add hl, bc ld d, h ld e, l ld hl, DeckNameSuffix call CopyListFromHLToDE pop de ld hl, wDefaultText call InitTextPrinting call ProcessText or a ret .new_deck ; print "NEW DECK" call InitTextPrinting ldtx hl, NewDeckText call ProcessTextFromID scf ret DeckNameSuffix: db " deck" done ; copies a $00-terminated list from hl to de CopyListFromHLToDE: ld a, [hli] ld [de], a or a ret z inc de jr CopyListFromHLToDE ; same as CopyListFromHLToDE, but for SRAM copying CopyListFromHLToDEInSRAM: call EnableSRAM call CopyListFromHLToDE call DisableSRAM ret ; appends text in hl to wDefaultText ; then adds "deck" to the end ; returns carry if deck has no cards ; hl = text to append ; de = input to InitTextPrinting AppendDeckName: push hl call CheckIfDeckHasCards pop hl ret c ; no cards push de ; append the text from hl ld de, wDefaultText call CopyListFromHLToDEInSRAM ; get string length (up to DECK_NAME_SIZE_WO_SUFFIX) ld hl, wDefaultText call GetTextLengthInTiles ld a, c cp DECK_NAME_SIZE_WO_SUFFIX jr c, .got_len ld c, DECK_NAME_SIZE_WO_SUFFIX .got_len ld b, $0 ld hl, wDefaultText add hl, bc ld d, h ld e, l ; append "deck" starting from the given length ld hl, .text_start ld b, .text_end - .text_start call CopyNBytesFromHLToDE xor a ; TX_END ld [wDefaultText + DECK_NAME_SIZE + 2], a pop de ld hl, wDefaultText call InitTextPrinting call ProcessText or a ret .text_start db " deck " .text_end ; returns carry if the deck in hl ; is not valid, that is, has no cards ; alternatively, the direct address of the cards ; can be used, since DECK_SIZE > DECK_NAME_SIZE ; hl = deck name (sDeck1Name ~ sDeck4Name) ; or deck cards (sDeck1Cards ~ sDeck4Cards) CheckIfDeckHasCards: ld bc, DECK_NAME_SIZE add hl, bc call EnableSRAM ld a, [hl] call DisableSRAM ; being max size means last char ; is not TX_END, i.e. $0 or a jr nz, .max_size scf ret .max_size or a ret ; calculates the y coordinate of the currently selected deck ; and draws the hands card tile at that position DrawHandCardsTileOnCurDeck: call EnableSRAM ld a, [sCurrentlySelectedDeck] call DisableSRAM ld h, 3 ld l, a call HtimesL ld e, l inc e ; (sCurrentlySelectedDeck * 3) + 1 ld d, 2 ; fallthrough ; de = coordinates to draw rectangle DrawHandCardsTileAtDE: ld a, $38 ; hand cards tile lb hl, 1, 2 lb bc, 2, 2 call FillRectangle ret ; handles user input when selecting a card filter ; when building a deck configuration ; the handling of selecting cards themselves from the list ; to add/remove to the deck is done in HandleDeckCardSelectionList HandleDeckBuildScreen: call WriteCardListsTerminatorBytes call CountNumberOfCardsForEachCardType .skip_count call DrawCardTypeIconsAndPrintCardCounts xor a ld [wCardListVisibleOffset], a ld [wCurCardTypeFilter], a ; FILTER_GRASS call PrintFilteredCardList .skip_draw ld hl, FiltersCardSelectionParams call InitCardSelectionParams .wait_input call DoFrame ldh a, [hDPadHeld] and START jr z, .no_start_btn_1 ld a, $01 call PlaySFXConfirmOrCancel call ConfirmDeckConfiguration ld a, [wCurCardTypeFilter] ld [wTempCardTypeFilter], a jr .wait_input .no_start_btn_1 ld a, [wCurCardTypeFilter] ld b, a ld a, [wTempCardTypeFilter] cp b jr z, .check_down_btn ; need to refresh the filtered card list ld [wCurCardTypeFilter], a ld hl, wCardListVisibleOffset ld [hl], 0 call PrintFilteredCardList ld a, NUM_FILTERS ld [wCardListNumCursorPositions], a .check_down_btn ldh a, [hDPadHeld] and D_DOWN jr z, .no_down_btn call ConfirmSelectionAndReturnCarry jr .jump_to_list .no_down_btn call HandleCardSelectionInput jr nc, .wait_input ld a, [hffb3] cp $ff ; operation cancelled? jp z, OpenDeckConfigurationMenu ; input was made to jump to the card list .jump_to_list ld a, [wNumEntriesInCurFilter] or a jr z, .wait_input xor a .wait_list_input ld hl, FilteredCardListSelectionParams call InitCardSelectionParams ld a, [wNumEntriesInCurFilter] ld [wNumCardListEntries], a ld hl, wNumVisibleCardListEntries cp [hl] jr nc, .ok ; if total number of entries is greater than or equal to ; the number of visible entries, then set number of cursor positions ; as number of visible entries ld [wCardListNumCursorPositions], a .ok ld hl, PrintDeckBuildingCardList ld d, h ld a, l ld hl, wCardListUpdateFunction ld [hli], a ld [hl], d ld a, $01 ld [wced2], a .loop_input call DoFrame ldh a, [hDPadHeld] and START jr z, .no_start_btn_2 ld a, $01 call PlaySFXConfirmOrCancel ; temporarily store current cursor position ; to retrieve it later ld a, [wCardListCursorPos] ld [wTempFilteredCardListNumCursorPositions], a call ConfirmDeckConfiguration ld a, [wTempFilteredCardListNumCursorPositions] jr .wait_list_input .no_start_btn_2 call HandleSelectUpAndDownInList jr c, .loop_input call HandleDeckCardSelectionList jr c, .selection_made jr .loop_input .open_card_page ld a, $01 call PlaySFXConfirmOrCancel ld a, [wCardListNumCursorPositions] ld [wTempCardListNumCursorPositions], a ld a, [wCardListCursorPos] ld [wTempCardListCursorPos], a ; set wFilteredCardList as current card list ; and show card page screen ld de, wFilteredCardList ld hl, wCurCardListPtr ld [hl], e inc hl ld [hl], d call OpenCardPageFromCardList call DrawCardTypeIconsAndPrintCardCounts ld hl, FiltersCardSelectionParams call InitCardSelectionParams ld a, [wCurCardTypeFilter] ld [wTempCardTypeFilter], a call DrawHorizontalListCursor_Visible call PrintDeckBuildingCardList ld hl, FilteredCardListSelectionParams call InitCardSelectionParams ld a, [wTempCardListNumCursorPositions] ld [wCardListNumCursorPositions], a ld a, [wTempCardListCursorPos] ld [wCardListCursorPos], a jr .loop_input .selection_made call DrawListCursor_Invisible ld a, [wCardListCursorPos] ld [wTempCardListCursorPos], a ld a, [hffb3] cp $ff jr nz, .open_card_page ; cancelled ld hl, FiltersCardSelectionParams call InitCardSelectionParams ld a, [wCurCardTypeFilter] ld [wTempCardTypeFilter], a jp .wait_input OpenDeckConfigurationMenu: xor a ld [wYourOrOppPlayAreaCurPosition], a ld de, wDeckConfigurationMenuTransitionTable ld hl, wMenuInputTablePointer ld a, [de] ld [hli], a inc de ld a, [de] ld [hl], a ld a, $ff ld [wDuelInitialPrizesUpperBitsSet], a .skip_init xor a ld [wCheckMenuCursorBlinkCounter], a ld hl, wDeckConfigurationMenuHandlerFunction ld a, [hli] ld h, [hl] ld l, a jp hl HandleDeckConfigurationMenu: lb de, 0, 0 lb bc, 20, 6 call DrawRegularTextBox ld hl, DeckBuildMenuData call PlaceTextItems .do_frame ld a, $1 ld [wVBlankOAMCopyToggle], a call DoFrame call YourOrOppPlayAreaScreen_HandleInput jr nc, .do_frame ld [wced6], a cp $ff jr nz, .asm_94b5 .draw_icons call DrawCardTypeIconsAndPrintCardCounts ld a, [wTempCardListCursorPos] ld [wCardListCursorPos], a ld a, [wCurCardTypeFilter] call PrintFilteredCardList jp HandleDeckBuildScreen.skip_draw .asm_94b5 push af call YourOrOppPlayAreaScreen_HandleInput.draw_cursor ld a, $01 ld [wVBlankOAMCopyToggle], a pop af ld hl, .func_table call JumpToFunctionInTable jr OpenDeckConfigurationMenu.skip_init .func_table dw ConfirmDeckConfiguration ; Confirm dw ModifyDeckConfiguration ; Modify dw ChangeDeckName ; Name dw SaveDeckConfiguration ; Save dw DismantleDeck ; Dismantle dw CancelDeckModifications ; Cancel ConfirmDeckConfiguration: ld hl, wCardListVisibleOffset ld a, [hl] ld hl, wCardListVisibleOffsetBackup ld [hl], a call HandleDeckConfirmationMenu ld hl, wCardListVisibleOffsetBackup ld a, [hl] ld hl, wCardListVisibleOffset ld [hl], a call DrawCardTypeIconsAndPrintCardCounts ld hl, FiltersCardSelectionParams call InitCardSelectionParams ld a, [wCurCardTypeFilter] ld [wTempCardTypeFilter], a call DrawHorizontalListCursor_Visible ld a, [wCurCardTypeFilter] call PrintFilteredCardList ld a, [wced6] ld [wCardListCursorPos], a ret ModifyDeckConfiguration: add sp, $2 jr HandleDeckConfigurationMenu.draw_icons ; returns carry set if player chose to go back CancelDeckModifications: ; if deck was not changed, cancel modification immediately call CheckIfCurrentDeckWasChanged jr nc, .cancel_modification ; else prompt the player to confirm ldtx hl, QuitModifyingTheDeckText call YesOrNoMenuWithText jr c, SaveDeckConfiguration.go_back .cancel_modification add sp, $2 or a ret SaveDeckConfiguration: ; handle deck configuration size ld a, [wTotalCardCount] cp DECK_SIZE jp z, .ask_to_save_deck ; can be jr ldtx hl, ThisIsntA60CardDeckText call DrawWideTextBox_WaitForInput ldtx hl, ReturnToOriginalConfigurationText call YesOrNoMenuWithText jr c, .print_deck_size_warning ; return no carry add sp, $2 or a ret .print_deck_size_warning ldtx hl, TheDeckMustInclude60CardsText call DrawWideTextBox_WaitForInput jr .go_back .ask_to_save_deck ldtx hl, SaveThisDeckText call YesOrNoMenuWithText jr c, .go_back call CheckIfThereAreAnyBasicCardsInDeck jr c, .set_carry ldtx hl, ThereAreNoBasicPokemonInThisDeckText call DrawWideTextBox_WaitForInput ldtx hl, YouMustIncludeABasicPokemonInTheDeckText call DrawWideTextBox_WaitForInput .go_back call DrawCardTypeIconsAndPrintCardCounts call PrintDeckBuildingCardList ld a, [wced6] ld [wCardListCursorPos], a ret .set_carry add sp, $2 scf ret DismantleDeck: ldtx hl, DismantleThisDeckText call YesOrNoMenuWithText jr c, SaveDeckConfiguration.go_back call CheckIfHasOtherValidDecks jp nc, .Dismantle ; can be jr ldtx hl, ThereIsOnly1DeckSoCannotBeDismantledText call DrawWideTextBox_WaitForInput call EmptyScreen ld hl, FiltersCardSelectionParams call InitCardSelectionParams ld a, [wCurCardTypeFilter] ld [wTempCardTypeFilter], a call DrawHorizontalListCursor_Visible call PrintDeckBuildingCardList call EnableLCD ld a, [wced6] ld [wCardListCursorPos], a ret .Dismantle call EnableSRAM call GetPointerToDeckName ld a, [hl] or a jr z, .done_dismantle ld a, NAME_BUFFER_LENGTH call ClearNBytesFromHL call GetPointerToDeckCards call AddDeckToCollection ld a, DECK_SIZE call ClearNBytesFromHL .done_dismantle call DisableSRAM add sp, $2 ret ChangeDeckName: call InputCurDeckName add sp, $2 jp HandleDeckBuildScreen.skip_count ; returns carry if current deck was changed ; either through its card configuration or its name CheckIfCurrentDeckWasChanged: ld a, [wTotalCardCount] or a jr z, .skip_size_check cp DECK_SIZE jr nz, .set_carry .skip_size_check ; copy the selected deck to wCurDeckCardChanges call GetPointerToDeckCards ld de, wCurDeckCardChanges ld b, DECK_SIZE call EnableSRAM call CopyNBytesFromHLToDE call DisableSRAM ; loops through cards in wCurDeckCards ; then if that card is found in wCurDeckCardChanges ; overwrite it by $0 ld a, $ff ; terminator byte ld [wCurDeckCardChanges + DECK_SIZE], a ld de, wCurDeckCards .loop_outer ld a, [de] or a jr z, .check_empty ld b, a inc de ld hl, wCurDeckCardChanges .loop_inner ld a, [hli] cp $ff jr z, .loop_outer cp b jr nz, .loop_inner ; found dec hl xor a ld [hli], a ; remove jr .loop_outer .check_empty ld hl, wCurDeckCardChanges .loop_check_empty ld a, [hli] cp $ff jr z, .is_empty or a jr nz, .set_carry jr .loop_check_empty .is_empty ; wCurDeckCardChanges is empty (all $0) ; check if name was changed call GetPointerToDeckName ld de, wCurDeckName call EnableSRAM .loop_name ld a, [de] cp [hl] jr nz, .set_carry inc de inc hl or a jr nz, .loop_name call DisableSRAM ret .set_carry call DisableSRAM scf ret ; returns carry if doesn't have a valid deck ; aside from the current deck CheckIfHasOtherValidDecks: ld hl, wDecksValid lb bc, 0, 0 .loop inc b ld a, NUM_DECKS cp b jr c, .check_has_cards ld a, [hli] or a jr z, .loop ; is valid inc c ld a, 1 cp c jr nc, .loop ; just 1 valid ; at least 2 decks are valid .no_carry or a ret .check_has_cards ; doesn't have at least 2 valid decks ; check if current deck is the only one ; that is valid (i.e. has cards) call GetPointerToDeckCards call EnableSRAM ld a, [hl] call DisableSRAM or a jr z, .no_carry ; no cards ; has cards, is the only valid deck! scf ret ; checks if wCurDeckCards has any basics ; returns carry set if there is at least ; 1 Basic Pokemon card CheckIfThereAreAnyBasicCardsInDeck: ld hl, wCurDeckCards .loop_cards ld a, [hli] ld e, a or a jr z, .no_carry call LoadCardDataToBuffer1_FromCardID jr c, .no_carry ld a, [wLoadedCard1Type] and TYPE_ENERGY jr nz, .loop_cards ld a, [wLoadedCard1Stage] or a jr nz, .loop_cards ; is basic card scf ret .no_carry or a ret FiltersCardSelectionParams: db 1 ; x pos db 1 ; y pos db 0 ; y spacing db 2 ; x spacing db NUM_FILTERS ; num entries db SYM_CURSOR_D ; visible cursor tile db SYM_SPACE ; invisible cursor tile dw NULL ; wCardListHandlerFunction FilteredCardListSelectionParams: db 0 ; x pos db 7 ; y pos db 2 ; y spacing db 0 ; x spacing db NUM_FILTERED_LIST_VISIBLE_CARDS ; num entries db SYM_CURSOR_R ; visible cursor tile db SYM_SPACE ; invisible cursor tile dw NULL ; wCardListHandlerFunction DeckConfigurationMenu_TransitionTable: cursor_transition $10, $20, $00, $03, $03, $01, $02 cursor_transition $48, $20, $00, $04, $04, $02, $00 cursor_transition $80, $20, $00, $05, $05, $00, $01 cursor_transition $10, $30, $00, $00, $00, $04, $05 cursor_transition $48, $30, $00, $01, $01, $05, $03 cursor_transition $80, $30, $00, $02, $02, $03, $04 ; draws each card type icon in a line ; the respective card counts underneath each icon ; and prints"X/60" in the upper-right corner, ; where X is the total card count DrawCardTypeIconsAndPrintCardCounts: call Set_OBJ_8x8 call Func_8d78 lb bc, 0, 5 ld a, SYM_BOX_TOP call FillBGMapLineWithA call DrawCardTypeIcons call PrintCardTypeCounts lb de, 15, 0 call PrintTotalCardCount lb de, 17, 0 call PrintSlashSixty call EnableLCD ret ; fills one line at coordinate bc in BG Map ; with the byte in register a ; fills the same line with $04 in VRAM1 if in CGB ; bc = coordinates FillBGMapLineWithA: call BCCoordToBGMap0Address ld b, SCREEN_WIDTH call FillDEWithA ld a, [wConsole] cp CONSOLE_CGB ret nz ; return if not CGB ld a, $04 ld b, SCREEN_WIDTH call BankswitchVRAM1 call FillDEWithA call BankswitchVRAM0 ret ; saves the count of each type of card that is in wCurDeckCards ; stores these values in wCardFilterCounts CountNumberOfCardsForEachCardType: ld hl, wCardFilterCounts ld de, CardTypeFilters .loop ld a, [de] cp -1 ret z inc de call CountNumberOfCardsOfType ld [hli], a jr .loop ; fills de with b bytes of the value in register a FillDEWithA: push hl ld l, e ld h, d .loop ld [hli], a dec b jr nz, .loop pop hl ret ; draws all the card type icons ; in a line specified by .CardTypeIcons DrawCardTypeIcons: ld hl, .CardTypeIcons .loop ld a, [hli] or a ret z ; done ld d, [hl] ; x coord inc hl ld e, [hl] ; y coord inc hl call .DrawIcon jr .loop ; input: ; de = coordinates .DrawIcon push hl push af lb hl, 1, 2 lb bc, 2, 2 call FillRectangle pop af call GetCardTypeIconPalette ld b, a ld a, [wConsole] cp CONSOLE_CGB jr nz, .not_cgb ld a, b lb bc, 2, 2 lb hl, 0, 0 call BankswitchVRAM1 call FillRectangle call BankswitchVRAM0 .not_cgb pop hl ret .CardTypeIcons ; icon tile, x coord, y coord db ICON_TILE_GRASS, 1, 2 db ICON_TILE_FIRE, 3, 2 db ICON_TILE_WATER, 5, 2 db ICON_TILE_LIGHTNING, 7, 2 db ICON_TILE_FIGHTING, 9, 2 db ICON_TILE_PSYCHIC, 11, 2 db ICON_TILE_COLORLESS, 13, 2 db ICON_TILE_TRAINER, 15, 2 db ICON_TILE_ENERGY, 17, 2 db $00 DeckBuildMenuData: ; x, y, text id textitem 2, 2, ConfirmText textitem 9, 2, ModifyText textitem 16, 2, NameText textitem 2, 4, SaveText textitem 9, 4, DismantleText textitem 16, 4, CancelText db $ff ; prints "/60" to the coordinates given in de PrintSlashSixty: ld hl, wDefaultText ld a, TX_SYMBOL ld [hli], a ld a, SYM_SLASH ld [hli], a ld a, TX_SYMBOL ld [hli], a ld a, SYM_6 ld [hli], a ld a, TX_SYMBOL ld [hli], a ld a, SYM_0 ld [hli], a ld [hl], TX_END call InitTextPrinting ld hl, wDefaultText call ProcessText ret ; creates two separate lists given the card type in register a ; if a card matches the card type given, then it's added to wFilteredCardList ; if a card has been owned by the player, and its card count is at least 1, ; (or in case it's 0 if it's in any deck configurations saved) ; then its collection count is also added to wOwnedCardsCountList ; if input a is $ff, then all card types are included CreateFilteredCardList: push af push bc push de push hl ; clear wOwnedCardsCountList and wFilteredCardList push af ld a, DECK_SIZE ld hl, wOwnedCardsCountList call ClearNBytesFromHL ld a, DECK_SIZE ld hl, wFilteredCardList call ClearNBytesFromHL pop af ; loops all cards in collection ld hl, $0 ld de, $0 ld b, a ; input card type .loop_card_ids inc e call GetCardType jr c, .store_count ld c, a ld a, b cp $ff jr z, .add_card and FILTER_ENERGY cp FILTER_ENERGY jr z, .check_energy ld a, c cp b jr nz, .loop_card_ids jr .add_card .check_energy ld a, c and TYPE_ENERGY cp TYPE_ENERGY jr nz, .loop_card_ids .add_card push bc push hl ld bc, wFilteredCardList add hl, bc ld [hl], e ld hl, wTempCardCollection add hl, de ld a, [hl] pop hl cp CARD_NOT_OWNED jr z, .next_card ; jump if never seen card or a jr nz, .ok ; has at least 1 call IsCardInAnyDeck jr c, .next_card ; jump if not in any deck .ok push hl ld bc, wOwnedCardsCountList add hl, bc ld [hl], a pop hl inc l .next_card pop bc jr .loop_card_ids .store_count ld a, l ld [wNumEntriesInCurFilter], a ; add terminator bytes in both lists xor a ld c, l ld b, h ld hl, wFilteredCardList add hl, bc ld [hl], a ; $00 ld a, $ff ld hl, wOwnedCardsCountList add hl, bc ld [hl], a ; $ff pop hl pop de pop bc pop af ret ; returns carry if card ID in register e is not ; found in any of the decks saved in SRAM IsCardInAnyDeck: push af push hl ld hl, sDeck1Cards call .FindCardInDeck jr nc, .found_card ld hl, sDeck2Cards call .FindCardInDeck jr nc, .found_card ld hl, sDeck3Cards call .FindCardInDeck jr nc, .found_card ld hl, sDeck4Cards call .FindCardInDeck jr nc, .found_card pop hl pop af scf ret .found_card pop hl pop af or a ret ; returns carry if input card ID in register e ; is not found in deck given by hl .FindCardInDeck call EnableSRAM ld b, DECK_SIZE .loop ld a, [hli] cp e jr z, .not_found dec b jr nz, .loop ; not found call DisableSRAM scf ret .not_found call DisableSRAM or a ret ; preserves all registers ; hl = start of bytes to set to $0 ; a = number of bytes to set to $0 ClearNBytesFromHL: push af push bc push hl ld b, a xor a .loop ld [hli], a dec b jr nz, .loop pop hl pop bc pop af ret ; returns the number of times that card e ; appears in wCurDeckCards GetCountOfCardInCurDeck: push hl ld hl, wCurDeckCards ld d, 0 .loop ld a, [hli] or a jr z, .done cp e jr nz, .loop inc d jr .loop .done ld a, d pop hl ret ; returns total count of card ID e ; looks it up in wFilteredCardList ; then uses the index to retrieve the count ; value from wOwnedCardsCountList GetOwnedCardCount: push hl ld hl, wFilteredCardList ld d, -1 .loop inc d ld a, [hli] or a jr z, .not_found cp e jr nz, .loop ld hl, wOwnedCardsCountList push de ld e, d ld d, $00 add hl, de pop de ld a, [hl] pop hl ret .not_found xor a pop hl ret ; appends text "X/Y", where X is the number of included cards ; and Y is the total number of cards in storage of a given card ID ; input: ; e = card ID AppendOwnedCardCountAndStorageCountNumbers: push af push bc push de push hl ; count how many bytes until $00 .loop ld a, [hl] or a jr z, .print inc hl jr .loop .print push de call GetCountOfCardInCurDeck call ConvertToNumericalDigits ld [hl], TX_SYMBOL inc hl ld [hl], SYM_SLASH inc hl pop de call GetOwnedCardCount call ConvertToNumericalDigits ld [hl], TX_END pop hl pop de pop bc pop af ret ; determines the ones and tens digits in a for printing ; the ones place is added $20 (SYM_0) so that it maps to a numerical character ; if the tens is 0, it maps to an empty character ; a = value to calculate digits CalculateOnesAndTensDigits: push af push bc push de push hl ld c, -1 .loop inc c sub 10 jr nc, .loop jr z, .zero1 add 10 ; a = a mod 10 ; c = floor(a / 10) .zero1 ; ones digit add SYM_0 ld hl, wOnesAndTensPlace ld [hli], a ; tens digit ld a, c or a jr z, .zero2 add SYM_0 .zero2 ld [hl], a pop hl pop de pop bc pop af ret ; converts value in register a to ; numerical symbols for ProcessText ; places the symbols in hl ConvertToNumericalDigits: call CalculateOnesAndTensDigits push hl ld hl, wOnesAndTensPlace ld a, [hli] ld b, a ld a, [hl] pop hl ld [hl], TX_SYMBOL inc hl ld [hli], a ld [hl], TX_SYMBOL inc hl ld a, b ld [hli], a ret ; counts the number of cards in wCurDeckCards ; that are the same type as input in register a ; if input is $20, counts all energy cards instead ; input: ; - a = card type ; output: ; - a = number of cards of same type CountNumberOfCardsOfType: push de push hl ld hl, $0 ld b, a ld c, 0 .loop_cards push hl push bc ld bc, wCurDeckCards add hl, bc ld a, [hl] pop bc pop hl inc l or a jr z, .done ; end of card list ; get card type and compare it with input type ; if input is FILTER_ENERGY, run a separate comparison ; if it's the same type, increase the count ld e, a call GetCardType jr c, .done push hl ld l, a ld a, b and FILTER_ENERGY cp FILTER_ENERGY jr z, .check_energy ld a, l pop hl cp b jr nz, .loop_cards jr .incr_count ; counts all energy cards as the same .check_energy ld a, l pop hl and TYPE_ENERGY cp TYPE_ENERGY jr nz, .loop_cards .incr_count inc c jr .loop_cards .done ld a, c pop hl pop de ret ; prints the card count of each individual card type ; assumes CountNumberOfCardsForEachCardType was already called ; this is done by processing text in a single line ; and concatenating all digits PrintCardTypeCounts: ld bc, $0 ld hl, wDefaultText .loop push hl ld hl, wCardFilterCounts add hl, bc ld a, [hl] pop hl push bc call ConvertToNumericalDigits pop bc inc c ld a, NUM_FILTERS cp c jr nz, .loop ld [hl], TX_END lb de, 1, 4 call InitTextPrinting ld hl, wDefaultText call ProcessText ret ; prints the list of cards, applying the filter from register a ; the counts of each card displayed is taken from wCurDeck ; a = card type filter PrintFilteredCardList: push af ld hl, CardTypeFilters ld b, $00 ld c, a add hl, bc ld a, [hl] push af ; copy sCardCollection to wTempCardCollection call EnableSRAM ld hl, sCardCollection ld de, wTempCardCollection ld b, CARD_COLLECTION_SIZE - 1 call CopyNBytesFromHLToDE call DisableSRAM ld a, [wIncludeCardsInDeck] or a jr z, .ok call GetPointerToDeckCards ld d, h ld e, l call IncrementDeckCardsInTempCollection .ok pop af call CreateFilteredCardList ld a, NUM_FILTERED_LIST_VISIBLE_CARDS ld [wNumVisibleCardListEntries], a lb de, 1, 7 ld hl, wCardListCoords ld [hl], e inc hl ld [hl], d call PrintDeckBuildingCardList pop af ret ; used to filter the cards in the deck building/card selection screen CardTypeFilters: db FILTER_GRASS db FILTER_FIRE db FILTER_WATER db FILTER_LIGHTNING db FILTER_FIGHTING db FILTER_PSYCHIC db FILTER_COLORLESS db FILTER_TRAINER db FILTER_ENERGY db -1 ; end of list ; counts all the cards from each card type ; (stored in wCardFilterCounts) and store it in wTotalCardCount ; also prints it in coordinates de PrintTotalCardCount: push de ld bc, $0 ld hl, wCardFilterCounts .loop ld a, [hli] add b ld b, a inc c ld a, NUM_FILTERS cp c jr nz, .loop ld hl, wDefaultText ld a, b ld [wTotalCardCount], a push bc call ConvertToNumericalDigits pop bc ld [hl], TX_END pop de call InitTextPrinting ld hl, wDefaultText call ProcessText ret ; prints the name, level and storage count of the cards ; that are visible in the list window ; in the form: ; CARD NAME/LEVEL X/Y ; where X is the current count of that card ; and Y is the storage count of that card PrintDeckBuildingCardList: push bc ld hl, wCardListCoords ld e, [hl] inc hl ld d, [hl] ld b, 19 ; x coord ld c, e dec c ld a, [wCardListVisibleOffset] or a jr z, .no_cursor ld a, SYM_CURSOR_U jr .got_cursor_tile .no_cursor ld a, SYM_SPACE .got_cursor_tile call WriteByteToBGMap0 ; iterates by decreasing value in wNumVisibleCardListEntries ; by 1 until it reaches 0 ld a, [wCardListVisibleOffset] ld c, a ld b, $0 ld hl, wFilteredCardList add hl, bc ld a, [wNumVisibleCardListEntries] .loop_filtered_cards push de or a jr z, .exit_loop ld b, a ld a, [hli] or a jr z, .invalid_card ; card ID of 0 ld e, a call AddCardIDToVisibleList call LoadCardDataToBuffer1_FromCardID ld a, 13 push bc push hl push de call CopyCardNameAndLevel pop de call AppendOwnedCardCountAndStorageCountNumbers pop hl pop bc pop de push hl call InitTextPrinting ld hl, wDefaultText jr .process_text .invalid_card pop de push hl call InitTextPrinting ld hl, Text_9a30 .process_text call ProcessText pop hl ld a, b dec a inc e inc e jr .loop_filtered_cards .exit_loop ld a, [hli] or a jr z, .cannot_scroll pop de ; draw down cursor because ; there are still more cards ; to be scrolled down xor a ; FALSE ld [wUnableToScrollDown], a ld a, SYM_CURSOR_D jr .draw_cursor .cannot_scroll pop de ld a, TRUE ld [wUnableToScrollDown], a ld a, SYM_SPACE .draw_cursor ld b, 19 ; x coord ld c, e dec c dec c call WriteByteToBGMap0 pop bc ret Text_9a30: db "" db "" db "" Text_9a36: db "" db "" db "" db "" db "" db "" db "" db "" db "" db "" db "" db "" db "" db "" db "" db "" db "" done ; writes the card ID in register e to wVisibleListCardIDs ; given its position in the list in register b ; input: ; b = list position (starts from bottom) ; e = card ID AddCardIDToVisibleList: push af push bc push hl ld hl, wVisibleListCardIDs ld c, b ld a, [wNumVisibleCardListEntries] sub c ld c, a ; wNumVisibleCardListEntries - b ld b, $0 add hl, bc ld [hl], e pop hl pop bc pop af ret ; copies data from hl to: ; wCardListCursorXPos ; wCardListCursorYPos ; wCardListYSpacing ; wCardListXSpacing ; wCardListNumCursorPositions ; wVisibleCursorTile ; wInvisibleCursorTile ; wCardListHandlerFunction InitCardSelectionParams: ld [wCardListCursorPos], a ld [hffb3], a ld de, wCardListCursorXPos ld b, $9 .loop ld a, [hli] ld [de], a inc de dec b jr nz, .loop xor a ld [wCheckMenuCursorBlinkCounter], a ret HandleCardSelectionInput: xor a ; FALSE ld [wPlaysSfx], a ldh a, [hDPadHeld] or a jr z, .handle_ab_btns ; handle d-pad ld b, a ld a, [wCardListNumCursorPositions] ld c, a ld a, [wCardListCursorPos] bit D_LEFT_F, b jr z, .check_d_right dec a bit 7, a jr z, .got_cursor_pos ; if underflow, set to max cursor pos ld a, [wCardListNumCursorPositions] dec a jr .got_cursor_pos .check_d_right bit D_RIGHT_F, b jr z, .handle_ab_btns inc a cp c jr c, .got_cursor_pos ; if over max pos, set to pos 0 xor a .got_cursor_pos push af ld a, TRUE ld [wPlaysSfx], a call DrawHorizontalListCursor_Invisible pop af ld [wCardListCursorPos], a xor a ld [wCheckMenuCursorBlinkCounter], a .handle_ab_btns ld a, [wCardListCursorPos] ld [hffb3], a ldh a, [hKeysPressed] and A_BUTTON | B_BUTTON jr z, HandleCardSelectionCursorBlink and A_BUTTON jr nz, ConfirmSelectionAndReturnCarry ; b button ld a, $ff ld [hffb3], a call PlaySFXConfirmOrCancel scf ret ; outputs cursor position in e and selection in a ConfirmSelectionAndReturnCarry: call DrawHorizontalListCursor_Visible ld a, $01 call PlaySFXConfirmOrCancel ld a, [wCardListCursorPos] ld e, a ld a, [hffb3] scf ret HandleCardSelectionCursorBlink: ld a, [wPlaysSfx] or a jr z, .skip_sfx call PlaySFX .skip_sfx ld hl, wCheckMenuCursorBlinkCounter ld a, [hl] inc [hl] and $0f ret nz ld a, [wVisibleCursorTile] bit 4, [hl] jr z, DrawHorizontalListCursor DrawHorizontalListCursor_Invisible: ld a, [wInvisibleCursorTile] ; fallthrough ; like DrawListCursor but only ; for lists with one line, and each entry ; being laid horizontally ; a = tile to write DrawHorizontalListCursor: ld e, a ld a, [wCardListXSpacing] ld l, a ld a, [wCardListCursorPos] ld h, a call HtimesL ld a, l ld hl, wCardListCursorXPos add [hl] ld b, a ; x coord ld hl, wCardListCursorYPos ld a, [hl] ld c, a ; y coord ld a, e call WriteByteToBGMap0 or a ret DrawHorizontalListCursor_Visible: ld a, [wVisibleCursorTile] jr DrawHorizontalListCursor ; handles user input when selecting cards to add ; to deck configuration ; returns carry if a selection was made ; (either selected card or cancelled) ; outputs in a the list index if selection was made ; or $ff if operation was cancelled HandleDeckCardSelectionList: xor a ; FALSE ld [wPlaysSfx], a ldh a, [hDPadHeld] or a jp z, .asm_9bb9 ld b, a ld a, [wCardListNumCursorPositions] ld c, a ld a, [wCardListCursorPos] bit D_UP_F, b jr z, .check_d_down push af ld a, TRUE ld [wPlaysSfx], a pop af dec a bit 7, a jr z, .asm_9b8f ld a, [wCardListVisibleOffset] or a jr z, .asm_9b5a dec a ld [wCardListVisibleOffset], a ld hl, wCardListUpdateFunction call CallIndirect xor a jr .asm_9b8f .asm_9b5a xor a ld [wPlaysSfx], a jr .asm_9b8f .check_d_down bit D_DOWN_F, b jr z, .asm_9b9d push af ld a, TRUE ld [wPlaysSfx], a pop af inc a cp c jr c, .asm_9b8f push af ld a, [wUnableToScrollDown] or a jr nz, .cannot_scroll_down ld a, [wCardListVisibleOffset] inc a ld [wCardListVisibleOffset], a ld hl, wCardListUpdateFunction call CallIndirect pop af dec a jr .asm_9b8f .cannot_scroll_down pop af dec a push af xor a ; FALSE ld [wPlaysSfx], a pop af .asm_9b8f push af call DrawListCursor_Invisible pop af ld [wCardListCursorPos], a xor a ld [wCheckMenuCursorBlinkCounter], a jr .asm_9bb9 .asm_9b9d ld a, [wced2] or a jr z, .asm_9bb9 bit D_LEFT_F, b jr z, .check_d_right call GetSelectedVisibleCardID call RemoveCardFromDeckAndUpdateCount jr .asm_9bb9 .check_d_right bit D_RIGHT_F, b jr z, .asm_9bb9 call GetSelectedVisibleCardID call AddCardToDeckAndUpdateCount .asm_9bb9 ld a, [wCardListCursorPos] ld [hffb3], a ld hl, wCardListHandlerFunction ld a, [hli] or [hl] jr z, .handle_ab_btns ; this code seemingly never runs ; because wCardListHandlerFunction is always NULL ld a, [hld] ld l, [hl] ld h, a ld a, [hffb3] call CallHL jr nc, .handle_blink .select_card call DrawListCursor_Visible ld a, $01 call PlaySFXConfirmOrCancel ld a, [wCardListCursorPos] ld e, a ld a, [hffb3] scf ret .handle_ab_btns ldh a, [hKeysPressed] and A_BUTTON | B_BUTTON jr z, .check_sfx and A_BUTTON jr nz, .select_card ld a, $ff ld [hffb3], a call PlaySFXConfirmOrCancel scf ret .check_sfx ld a, [wPlaysSfx] or a jr z, .handle_blink call PlaySFX .handle_blink ld hl, wCheckMenuCursorBlinkCounter ld a, [hl] inc [hl] and $0f ret nz ld a, [wVisibleCursorTile] bit 4, [hl] jr z, DrawListCursor ; fallthrough DrawListCursor_Invisible: ld a, [wInvisibleCursorTile] ; fallthrough ; draws cursor considering wCardListCursorPos ; spaces each entry horizontally by wCardListXSpacing ; and vertically by wCardListYSpacing ; a = tile to write DrawListCursor: ld e, a ld a, [wCardListXSpacing] ld l, a ld a, [wCardListCursorPos] ld h, a call HtimesL ld a, l ld hl, wCardListCursorXPos add [hl] ld b, a ; x coord ld a, [wCardListYSpacing] ld l, a ld a, [wCardListCursorPos] ld h, a call HtimesL ld a, l ld hl, wCardListCursorYPos add [hl] ld c, a ; y coord ld a, e call WriteByteToBGMap0 or a ret DrawListCursor_Visible: ld a, [wVisibleCursorTile] jr DrawListCursor OpenCardPageFromCardList: ; get the card index that is selected ; and open its card page ld hl, wCurCardListPtr ld a, [hli] ld h, [hl] ld l, a ld a, [wCardListCursorPos] ld c, a ld b, $0 add hl, bc ld a, [wCardListVisibleOffset] ld c, a ld b, $0 add hl, bc ld e, [hl] ld d, $0 push de call LoadCardDataToBuffer1_FromCardID lb de, $38, $9f call SetupText bank1call OpenCardPage_FromCheckHandOrDiscardPile pop de .handle_input ldh a, [hDPadHeld] ld b, a and A_BUTTON | B_BUTTON | SELECT | START jp nz, .exit ; check d-pad ; if UP or DOWN is pressed, change the ; card that is being shown, given the ; order in the current card list xor a ; FALSE ld [wPlaysSfx], a ld a, [wCardListNumCursorPositions] ld c, a ld a, [wCardListCursorPos] bit D_UP_F, b jr z, .check_d_down push af ld a, TRUE ld [wPlaysSfx], a pop af dec a bit 7, a jr z, .reopen_card_page ld a, [wCardListVisibleOffset] or a jr z, .handle_regular_card_page_input dec a ld [wCardListVisibleOffset], a xor a jr .reopen_card_page .check_d_down bit D_DOWN_F, b jr z, .handle_regular_card_page_input push af ld a, TRUE ld [wPlaysSfx], a pop af inc a cp c jr c, .reopen_card_page push af ld hl, wCurCardListPtr ld a, [hli] ld h, [hl] ld l, a ld a, [wCardListCursorPos] ld c, a ld b, $0 add hl, bc ld a, [wCardListVisibleOffset] inc a ld c, a ld b, $0 add hl, bc ld a, [hl] or a jr z, .skip_change_card ld a, [wCardListVisibleOffset] inc a ld [wCardListVisibleOffset], a pop af dec a .reopen_card_page ld [wCardListCursorPos], a ld a, [wPlaysSfx] or a jp z, OpenCardPageFromCardList call PlaySFX jp OpenCardPageFromCardList .skip_change_card pop af jr .handle_regular_card_page_input ; unnecessary jr .handle_regular_card_page_input push de bank1call OpenCardPage.input_loop pop de jp .handle_input .exit ld a, $1 ld [wVBlankOAMCopyToggle], a ld a, [wCardListCursorPos] ld [wTempCardListCursorPos], a ret ; opens card page from the card list Func_9ced: ; unreferenced ld hl, wVisibleListCardIDs ld a, [wCardListCursorPos] ld c, a ld b, $00 add hl, bc ld e, [hl] inc hl ld d, [hl] call LoadCardDataToBuffer1_FromCardID ld de, $389f call SetupText bank1call OpenCardPage_FromHand ld a, $01 ld [wVBlankOAMCopyToggle], a ret ; adds card in register e to deck configuration ; and updates the values shown for its count ; in the card selection list ; input: ; e = card ID AddCardToDeckAndUpdateCount: call TryAddCardToDeck ret c ; failed to add card push de call PrintCardTypeCounts lb de, 15, 0 call PrintTotalCardCount pop de call GetCountOfCardInCurDeck call PrintNumberValueInCursorYPos ret ; tries to add card ID in register e to wCurDeckCards ; fails to add card if one of the following conditions are met: ; - total cards are equal to wMaxNumCardsAllowed ; - cards with the same name as it reached the allowed limit ; - player doesn't own more copies in the collection ; returns carry if fails ; otherwise, writes card ID to first empty slot in wCurDeckCards ; input: ; e = card ID TryAddCardToDeck: ld a, [wMaxNumCardsAllowed] ld d, a ld a, [wTotalCardCount] cp d jr nz, .not_equal ; wMaxNumCardsAllowed == wTotalCardCount scf ret .not_equal push de call .CheckIfCanAddCardWithSameName pop de ret c ; cannot add more cards with this name push de call GetCountOfCardInCurDeck ld b, a ld hl, wOwnedCardsCountList ld d, $0 ld a, [wCardListVisibleOffset] ld e, a add hl, de ld a, [wCardListCursorPos] ld e, a add hl, de ld d, [hl] ld a, b cp d pop de scf ret z ; cannot add because player doesn't own more copies ld a, SFX_01 call PlaySFX push de call .AddCardToCurDeck ld a, [wCurCardTypeFilter] ld c, a ld b, $0 ld hl, wCardFilterCounts add hl, bc inc [hl] pop de or a ret ; finds first empty slot in wCurDeckCards ; then writes the value in e to it .AddCardToCurDeck ld hl, wCurDeckCards .loop ld a, [hl] or a jr z, .empty inc hl jr .loop .empty ld [hl], e inc hl xor a ld [hl], a ret ; returns carry if card ID in e cannot be ; added to the current deck configuration ; due to having reached the maximum number ; of cards allowed with that same name ; e = card id .CheckIfCanAddCardWithSameName call LoadCardDataToBuffer1_FromCardID ld a, [wLoadedCard1Type] cp TYPE_ENERGY_DOUBLE_COLORLESS jr z, .double_colorless ; basic energy cards have no limit and TYPE_ENERGY cp TYPE_ENERGY jr z, .exit ; return if basic energy card .double_colorless ; compare this card's name to ; the names of cards in list wCurDeckCards ld a, [wLoadedCard1Name + 0] ld c, a ld a, [wLoadedCard1Name + 1] ld b, a ld hl, wCurDeckCards ld d, 0 push de .loop_cards ld a, [hli] or a jr z, .exit_pop_de ld e, a ld d, $0 call GetCardName ld a, e cp c jr nz, .loop_cards ld a, d cp b jr nz, .loop_cards ; has same name pop de inc d ; increment counter of cards with this name ld a, [wSameNameCardsLimit] cp d push de jr nz, .loop_cards ; reached the maximum number ; of cards with same name allowed pop de scf ret .exit_pop_de pop de .exit or a ret ; gets the element in wVisibleListCardIDs ; corresponding to index wCardListCursorPos GetSelectedVisibleCardID: ld hl, wVisibleListCardIDs ld a, [wCardListCursorPos] ld e, a ld d, $00 add hl, de ld e, [hl] ret ; appends the digits of value in register a to wDefaultText ; then prints it in cursor Y position ; a = value to convert to numerical digits PrintNumberValueInCursorYPos: ld hl, wDefaultText call ConvertToNumericalDigits ld [hl], TX_END ld a, [wCardListYSpacing] ld l, a ld a, [wCardListCursorPos] ld h, a call HtimesL ld a, l ld hl, wCardListCursorYPos add [hl] ld e, a ld d, 14 call InitTextPrinting ld hl, wDefaultText call ProcessText ret ; removes card in register e from deck configuration ; and updates the values shown for its count ; in the card selection list ; input: ; e = card ID RemoveCardFromDeckAndUpdateCount: call RemoveCardFromDeck ret nc push de call PrintCardTypeCounts lb de, 15, 0 call PrintTotalCardCount pop de call GetCountOfCardInCurDeck call PrintNumberValueInCursorYPos ret ; removes card ID in e from wCurDeckCards RemoveCardFromDeck: push de call GetCountOfCardInCurDeck pop de or a ret z ; card is not in deck ld a, SFX_01 call PlaySFX push de call .RemoveCard ld a, [wCurCardTypeFilter] ld c, a ld b, $0 ld hl, wCardFilterCounts add hl, bc dec [hl] pop de scf ret ; remove first card instance of card ID in e ; and shift all elements up by one .RemoveCard ld hl, wCurDeckCards ld d, 0 ; unnecessary .loop_1 inc d ; unnecessary ld a, [hli] cp e jr nz, .loop_1 ld c, l ld b, h dec bc .loop_2 inc d ; unnecessary ld a, [hli] or a jr z, .done ld [bc], a inc bc jr .loop_2 .done xor a ld [bc], a ret UpdateConfirmationCardScreen: ld hl, hffb0 ld [hl], $01 call PrintCurDeckNumberAndName ld hl, hffb0 ld [hl], $00 jp PrintConfirmationCardList HandleDeckConfirmationMenu: ; if deck is empty, just show deck info header with empty card list ld a, [wTotalCardCount] or a jp z, ShowDeckInfoHeaderAndWaitForBButton ; create list of all unique cards call SortCurDeckCardsByID call CreateCurDeckUniqueCardList xor a ld [wCardListVisibleOffset], a .init_params ld hl, .CardSelectionParams call InitCardSelectionParams ld a, [wNumUniqueCards] ld [wNumCardListEntries], a cp NUM_DECK_CONFIRMATION_VISIBLE_CARDS jr c, .no_cap ld a, NUM_DECK_CONFIRMATION_VISIBLE_CARDS .no_cap ld [wCardListNumCursorPositions], a ld [wNumVisibleCardListEntries], a call ShowConfirmationCardScreen ld hl, UpdateConfirmationCardScreen ld d, h ld a, l ld hl, wCardListUpdateFunction ld [hli], a ld [hl], d xor a ld [wced2], a .loop_input call DoFrame call HandleDeckCardSelectionList jr c, .selection_made call HandleLeftRightInCardList jr c, .loop_input ldh a, [hDPadHeld] and START jr z, .loop_input .selected_card ld a, $01 call PlaySFXConfirmOrCancel ld a, [wCardListCursorPos] ld [wced7], a ; set wOwnedCardsCountList as current card list ; and show card page screen ld de, wOwnedCardsCountList ld hl, wCurCardListPtr ld [hl], e inc hl ld [hl], d call OpenCardPageFromCardList jr .init_params .selection_made ld a, [hffb3] cp $ff ret z ; operation cancelled jr .selected_card .CardSelectionParams db 0 ; x pos db 5 ; y pos db 2 ; y spacing db 0 ; x spacing db 7 ; num entries db SYM_CURSOR_R ; visible cursor tile db SYM_SPACE ; invisible cursor tile dw NULL ; wCardListHandlerFunction ; handles pressing left/right in card lists ; scrolls up/down a number of wCardListNumCursorPositions ; entries respectively ; returns carry if scrolling happened HandleLeftRightInCardList: ld a, [wCardListNumCursorPositions] ld d, a ld a, [wCardListVisibleOffset] ld c, a ldh a, [hDPadHeld] cp D_RIGHT jr z, .right cp D_LEFT jr z, .left or a ret .right ld a, [wCardListVisibleOffset] add d ld b, a add d ld hl, wNumCardListEntries cp [hl] jr c, .got_new_pos ld a, [wNumCardListEntries] sub d ld b, a jr .got_new_pos .left ld a, [wCardListVisibleOffset] sub d ld b, a jr nc, .got_new_pos ld b, 0 ; first index .got_new_pos ld a, b ld [wCardListVisibleOffset], a cp c jr z, .asm_9efa ld a, SFX_01 call PlaySFX ld hl, wCardListUpdateFunction call CallIndirect .asm_9efa scf ret ; handles scrolling up and down with Select button ; in this case, the cursor position goes up/down ; by wCardListNumCursorPositions entries respectively ; return carry if scrolling happened, otherwise no carry HandleSelectUpAndDownInList: ld a, [wCardListNumCursorPositions] ld d, a ld a, [wCardListVisibleOffset] ld c, a ldh a, [hDPadHeld] cp SELECT | D_DOWN jr z, .sel_down cp SELECT | D_UP jr z, .sel_up or a ret .sel_down ld a, [wCardListVisibleOffset] add d ld b, a ; wCardListVisibleOffset + wCardListNumCursorPositions add d ld hl, wNumCardListEntries cp [hl] jr c, .got_new_pos ld a, [wNumCardListEntries] sub d ld b, a ; wNumCardListEntries - wCardListNumCursorPositions jr .got_new_pos .sel_up ld a, [wCardListVisibleOffset] sub d ld b, a ; wCardListVisibleOffset - wCardListNumCursorPositions jr nc, .got_new_pos ld b, 0 ; go to first position .got_new_pos ld a, b ld [wCardListVisibleOffset], a cp c jr z, .set_carry ld a, SFX_01 call PlaySFX ld hl, wCardListUpdateFunction call CallIndirect .set_carry scf ret ; simply draws the deck info header ; then awaits a b button press to exit ShowDeckInfoHeaderAndWaitForBButton: call ShowDeckInfoHeader .wait_input call DoFrame ldh a, [hKeysPressed] and B_BUTTON jr z, .wait_input ld a, $ff call PlaySFXConfirmOrCancel ret ShowConfirmationCardScreen: call ShowDeckInfoHeader lb de, 3, 5 ld hl, wCardListCoords ld [hl], e inc hl ld [hl], d call PrintConfirmationCardList ret ; counts all values stored in wCardFilterCounts ; if the total count is 0, then ; prints "No cards chosen." TallyCardsInCardFilterLists: lb bc, 0, 0 ld hl, wCardFilterCounts .loop ld a, [hli] add b ld b, a inc c ld a, NUM_FILTERS cp c jr nz, .loop ld a, b or a ret nz lb de, 11, 1 call InitTextPrinting ldtx hl, NoCardsChosenText call ProcessTextFromID ret ; draws a box on the top of the screen ; with wCurDeck's number, name and card count ; and draws the Hand Cards icon if it's ; the current dueling deck ShowDeckInfoHeader: call EmptyScreenAndLoadFontDuelAndHandCardsIcons lb de, 0, 0 lb bc, 20, 4 call DrawRegularTextBox ld a, [wCurDeckName] or a jp z, .print_card_count ; can be jr ; draw hand cards icon if it's the current dueling deck call PrintCurDeckNumberAndName ld a, [wCurDeck] ld b, a call EnableSRAM ld a, [sCurrentlySelectedDeck] call DisableSRAM cp b jr nz, .print_card_count lb de, 2, 1 call DrawHandCardsTileAtDE .print_card_count lb de, 14, 1 call PrintTotalCardCount lb de, 16, 1 call PrintSlashSixty call TallyCardsInCardFilterLists call EnableLCD ret ; prints the name of wCurDeck in the form ; "X・ deck", where X is the number ; of the deck in the given menu ; if no current deck, print blank line PrintCurDeckNumberAndName: ld a, [wCurDeck] cp $ff jr z, .skip_deck_numeral ; print the deck number in the menu ; in the form "X・" lb de, 3, 2 call InitTextPrinting ld a, [wCurDeck] bit 7, a jr z, .incr_by_one and $7f jr .got_deck_numeral .incr_by_one inc a .got_deck_numeral ld hl, wDefaultText call ConvertToNumericalDigits ld [hl], "FW0_・" inc hl ld [hl], TX_END ld hl, wDefaultText call ProcessText .skip_deck_numeral ld hl, wCurDeckName ld de, wDefaultText call CopyListFromHLToDE ld a, [wCurDeck] cp $ff jr z, .blank_deck_name ; print " deck" ld hl, wDefaultText call GetTextLengthInTiles ld b, $0 ld hl, wDefaultText add hl, bc ld d, h ld e, l ld hl, DeckNameSuffix call CopyListFromHLToDE lb de, 6, 2 ld hl, wDefaultText call InitTextPrinting call ProcessText ret .blank_deck_name lb de, 2, 2 ld hl, wDefaultText call InitTextPrinting call ProcessText ret ; sorts wCurDeckCards by ID SortCurDeckCardsByID: ; wOpponentDeck is used to temporarily store deck's cards ; so that it can be later sorted by ID ld hl, wCurDeckCards ld de, wOpponentDeck ld bc, wDuelTempList ld a, -1 ld [bc], a .loop_copy inc a ; incr deck index push af ld a, [hli] ld [de], a inc de or a jr z, .sort_cards pop af ld [bc], a ; store deck index inc bc jr .loop_copy .sort_cards pop af ld a, $ff ; terminator byte for wDuelTempList ld [bc], a ; force Opp Turn so that SortCardsInDuelTempListByID can be used ldh a, [hWhoseTurn] push af ld a, OPPONENT_TURN ldh [hWhoseTurn], a call SortCardsInDuelTempListByID pop af ldh [hWhoseTurn], a ; given the ordered cards in wOpponentDeck, ; each entry in it corresponds to its deck index ; (first ordered card is deck index 0, second is deck index 1, etc) ; place these in this order in wCurDeckCards ld hl, wCurDeckCards ld de, wDuelTempList .loop_order_by_deck_index ld a, [de] cp $ff jr z, .done ld c, a ld b, $0 push hl ld hl, wOpponentDeck add hl, bc ld a, [hl] pop hl ld [hli], a inc de jr .loop_order_by_deck_index .done xor a ld [hl], a ret ; goes through list in wCurDeckCards, and for each card in it ; creates list in wUniqueDeckCardList of all unique cards ; it finds (assuming wCurDeckCards is sorted by ID) ; also counts the total number of the different cards CreateCurDeckUniqueCardList: ld b, 0 ld c, $0 ld hl, wCurDeckCards ld de, wUniqueDeckCardList .loop ld a, [hli] cp c jr z, .loop ld c, a ld [de], a inc de or a jr z, .done inc b jr .loop .done ld a, b ld [wNumUniqueCards], a ret ; prints the list of cards visible in the window ; of the confirmation screen ; card info is presented with name, level and ; its count preceded by "x" PrintConfirmationCardList: push bc ld hl, wCardListCoords ld e, [hl] inc hl ld d, [hl] ld b, 19 ; x coord ld c, e dec c ld a, [wCardListVisibleOffset] or a jr z, .no_cursor ld a, SYM_CURSOR_U jr .got_cursor_tile_1 .no_cursor ld a, SYM_SPACE .got_cursor_tile_1 call WriteByteToBGMap0 ; iterates by decreasing value in wNumVisibleCardListEntries ; by 1 until it reaches 0 ld a, [wCardListVisibleOffset] ld c, a ld b, $0 ld hl, wOwnedCardsCountList add hl, bc ld a, [wNumVisibleCardListEntries] .loop_cards push de or a jr z, .exit_loop ld b, a ld a, [hli] or a jr z, .no_more_cards ld e, a call AddCardIDToVisibleList call LoadCardDataToBuffer1_FromCardID ; places in wDefaultText the card's name and level ; then appends at the end "x" with the count of that card ; draws the card's type icon as well ld a, 13 push bc push hl push de call CopyCardNameAndLevel pop de call .PrintCardCount pop hl pop bc pop de call .DrawCardTypeIcon push hl call InitTextPrinting ld hl, wDefaultText call ProcessText pop hl ld a, b dec a inc e inc e jr .loop_cards .exit_loop ld a, [hli] or a jr z, .no_more_cards pop de xor a ; FALSE ld [wUnableToScrollDown], a ld a, SYM_CURSOR_D jr .got_cursor_tile_2 .no_more_cards pop de ld a, TRUE ld [wUnableToScrollDown], a ld a, SYM_SPACE .got_cursor_tile_2 ld b, 19 ; x coord ld c, e dec c dec c call WriteByteToBGMap0 pop bc ret ; prints the card count preceded by a cross ; for example "x42" .PrintCardCount push af push bc push de push hl .loop_search ld a, [hl] or a jr z, .found_card_id inc hl jr .loop_search .found_card_id call GetCountOfCardInCurDeck ld [hl], TX_SYMBOL inc hl ld [hl], SYM_CROSS inc hl call ConvertToNumericalDigits ld [hl], TX_END pop hl pop de pop bc pop af ret ; draws the icon corresponding to the loaded card's type ; can be any of Pokemon stages (basic, 1st and 2nd stage) ; Energy or Trainer ; draws it 2 tiles to the left and 1 up to ; the current coordinate in de .DrawCardTypeIcon push hl push de push bc ld a, [wLoadedCard1Type] cp TYPE_ENERGY jr nc, .not_pkmn_card ; pokemon card ld a, [wLoadedCard1Stage] ld b, a add b add b add b ; *4 add ICON_TILE_BASIC_POKEMON jr .got_tile .not_pkmn_card cp TYPE_TRAINER jr nc, .trainer_card ; energy card sub TYPE_ENERGY ld b, a add b add b add b ; *4 add ICON_TILE_FIRE jr .got_tile .trainer_card ld a, ICON_TILE_TRAINER .got_tile dec d dec d dec e push af lb hl, 1, 2 lb bc, 2, 2 call FillRectangle pop af call GetCardTypeIconPalette ld b, a ld a, [wConsole] cp CONSOLE_CGB jr nz, .skip_pal ld a, b lb bc, 2, 2 lb hl, 0, 0 call BankswitchVRAM1 call FillRectangle call BankswitchVRAM0 .skip_pal pop bc pop de pop hl ret ; returns in a the BG Pal corresponding to the ; card type icon in input register a ; if not found, returns $00 GetCardTypeIconPalette: push bc push hl ld b, a ld hl, .CardTypeIconPalettes .loop ld a, [hli] or a jr z, .done cp b jr z, .done inc hl jp .loop ; can be jr .done ld a, [hl] pop hl pop bc ret .CardTypeIconPalettes ; icon tile, BG pal db ICON_TILE_FIRE, 1 db ICON_TILE_GRASS, 2 db ICON_TILE_LIGHTNING, 1 db ICON_TILE_WATER, 2 db ICON_TILE_FIGHTING, 3 db ICON_TILE_PSYCHIC, 3 db ICON_TILE_COLORLESS, 0 db ICON_TILE_ENERGY, 2 db ICON_TILE_BASIC_POKEMON, 2 db ICON_TILE_STAGE_1_POKEMON, 2 db ICON_TILE_STAGE_2_POKEMON, 1 db ICON_TILE_TRAINER, 2 db $00, $ff ; inits WRAM vars to start creating deck configuration to send PrepareToBuildDeckConfigurationToSend: ld hl, wCurDeckCards ld a, wCurDeckCardsEnd - wCurDeckCards call ClearNBytesFromHL ld a, $ff ld [wCurDeck], a ld hl, .text ld de, wCurDeckName call CopyListFromHLToDE ld hl, .DeckConfigurationParams call InitDeckBuildingParams call HandleDeckBuildScreen ret .text text "Cards chosen to send" done .DeckConfigurationParams db DECK_SIZE ; max number of cards db 60 ; max number of same name cards db FALSE ; whether to include deck cards dw HandleSendDeckConfigurationMenu dw SendDeckConfigurationMenu_TransitionTable SendDeckConfigurationMenu_TransitionTable: cursor_transition $10, $20, $00, $00, $00, $01, $02 cursor_transition $48, $20, $00, $01, $01, $02, $00 cursor_transition $80, $20, $00, $02, $02, $00, $01 SendDeckConfigurationMenuData: textitem 2, 2, ConfirmText textitem 9, 2, SendText textitem 16, 2, CancelText db $ff HandleSendDeckConfigurationMenu: ld de, $0 lb bc, 20, 6 call DrawRegularTextBox ld hl, SendDeckConfigurationMenuData call PlaceTextItems ld a, $ff ld [wDuelInitialPrizesUpperBitsSet], a .loop_input ld a, $01 ld [wVBlankOAMCopyToggle], a call DoFrame call YourOrOppPlayAreaScreen_HandleInput jr nc, .loop_input ld [wced6], a cp $ff jr nz, .asm_a23b call DrawCardTypeIconsAndPrintCardCounts ld a, [wTempCardListCursorPos] ld [wCardListCursorPos], a ld a, [wCurCardTypeFilter] call PrintFilteredCardList jp HandleDeckBuildScreen.skip_draw .asm_a23b ld hl, .func_table call JumpToFunctionInTable jp OpenDeckConfigurationMenu.skip_init .func_table dw ConfirmDeckConfiguration ; Confirm dw .SendDeckConfiguration ; Send dw .CancelSendDeckConfiguration ; Cancel .SendDeckConfiguration ld a, [wCurDeckCards] or a jr z, .CancelSendDeckConfiguration xor a ld [wCardListVisibleOffset], a ld hl, Data_b04a call InitCardSelectionParams ld hl, wCurDeckCards ld de, wDuelTempList call CopyListFromHLToDE call PrintCardToSendText call Func_b088 call EnableLCD ldtx hl, SendTheseCardsText call YesOrNoMenuWithText jr nc, .asm_a279 add sp, $2 jp HandleDeckBuildScreen.skip_count .asm_a279 add sp, $2 scf ret .CancelSendDeckConfiguration add sp, $2 or a ret ; copies b bytes from hl to de CopyNBytesFromHLToDE: ld a, [hli] ld [de], a inc de dec b jr nz, CopyNBytesFromHLToDE ret ; handles the screen showing all the player's cards HandlePlayersCardsScreen: call WriteCardListsTerminatorBytes call PrintPlayersCardsHeaderInfo xor a ld [wCardListVisibleOffset], a ld [wCurCardTypeFilter], a call PrintFilteredCardSelectionList call EnableLCD xor a ld hl, FiltersCardSelectionParams call InitCardSelectionParams .wait_input call DoFrame ld a, [wCurCardTypeFilter] ld b, a ld a, [wTempCardTypeFilter] cp b jr z, .check_d_down ld [wCurCardTypeFilter], a ld hl, wCardListVisibleOffset ld [hl], $00 call PrintFilteredCardSelectionList ld hl, hffb0 ld [hl], $01 call PrintPlayersCardsText ld hl, hffb0 ld [hl], $00 ld a, NUM_FILTERS ld [wCardListNumCursorPositions], a .check_d_down ldh a, [hDPadHeld] and D_DOWN jr z, .no_d_down call ConfirmSelectionAndReturnCarry jr .jump_to_list .no_d_down call HandleCardSelectionInput jr nc, .wait_input ld a, [hffb3] cp $ff ; operation cancelled jr nz, .jump_to_list ret .jump_to_list ld a, [wNumEntriesInCurFilter] or a jr z, .wait_input xor a ld hl, Data_a396 call InitCardSelectionParams ld a, [wNumEntriesInCurFilter] ld [wNumCardListEntries], a ld hl, wNumVisibleCardListEntries cp [hl] jr nc, .asm_a300 ld [wCardListNumCursorPositions], a .asm_a300 ld hl, PrintCardSelectionList ld d, h ld a, l ld hl, wCardListUpdateFunction ld [hli], a ld [hl], d xor a ld [wced2], a .loop_input call DoFrame call HandleSelectUpAndDownInList jr c, .loop_input call HandleDeckCardSelectionList jr c, .asm_a36a ldh a, [hDPadHeld] and START jr z, .loop_input ; start btn pressed .open_card_page ld a, $01 call PlaySFXConfirmOrCancel ld a, [wCardListNumCursorPositions] ld [wTempCardListNumCursorPositions], a ld a, [wCardListCursorPos] ld [wTempCardListCursorPos], a ; set wFilteredCardList as current card list ; and show card page screen ld de, wFilteredCardList ld hl, wCurCardListPtr ld [hl], e inc hl ld [hl], d call OpenCardPageFromCardList call PrintPlayersCardsHeaderInfo ld hl, FiltersCardSelectionParams call InitCardSelectionParams ld a, [wCurCardTypeFilter] ld [wTempCardTypeFilter], a call DrawHorizontalListCursor_Visible call PrintCardSelectionList call EnableLCD ld hl, Data_a396 call InitCardSelectionParams ld a, [wTempCardListNumCursorPositions] ld [wCardListNumCursorPositions], a ld a, [wTempCardListCursorPos] ld [wCardListCursorPos], a jr .loop_input .asm_a36a call DrawListCursor_Invisible ld a, [wCardListCursorPos] ld [wTempCardListCursorPos], a ld a, [hffb3] cp $ff jr nz, .open_card_page ld hl, FiltersCardSelectionParams call InitCardSelectionParams ld a, [wCurCardTypeFilter] ld [wTempCardTypeFilter], a ld hl, hffb0 ld [hl], $01 call PrintPlayersCardsText ld hl, hffb0 ld [hl], $00 jp .wait_input Data_a396: db 1 ; x pos db 5 ; y pos db 2 ; y spacing db 0 ; x spacing db 7 ; num entries db SYM_CURSOR_R ; visible cursor tile db SYM_SPACE ; invisible cursor tile dw NULL ; wCardListHandlerFunction ; a = which card type filter PrintFilteredCardSelectionList: push af ld hl, CardTypeFilters ld b, $00 ld c, a add hl, bc ld a, [hl] push af ld a, ALL_DECKS call CreateCardCollectionListWithDeckCards pop af call CreateFilteredCardList ld a, NUM_DECK_CONFIRMATION_VISIBLE_CARDS ld [wNumVisibleCardListEntries], a lb de, 2, 5 ld hl, wCardListCoords ld [hl], e inc hl ld [hl], d ld a, SYM_SPACE ld [wCursorAlternateTile], a call PrintCardSelectionList pop af ret ; outputs in wTempCardCollection all the cards in sCardCollection ; plus the cards that are being used in built decks ; a = DECK_* flags for which decks to include in the collection CreateCardCollectionListWithDeckCards: ld [hffb5], a ; copies sCardCollection to wTempCardCollection ld hl, sCardCollection ld de, wTempCardCollection ld b, CARD_COLLECTION_SIZE - 1 call EnableSRAM call CopyNBytesFromHLToDE call DisableSRAM ; deck_1 ld a, [hffb5] ; should be ldh bit DECK_1_F, a jr z, .deck_2 ld de, sDeck1Cards call IncrementDeckCardsInTempCollection .deck_2 ld a, [hffb5] ; should be ldh bit DECK_2_F, a jr z, .deck_3 ld de, sDeck2Cards call IncrementDeckCardsInTempCollection .deck_3 ld a, [hffb5] ; should be ldh bit DECK_3_F, a jr z, .deck_4 ld de, sDeck3Cards call IncrementDeckCardsInTempCollection .deck_4 ld a, [hffb5] ; should be ldh bit DECK_4_F, a ret z ld de, sDeck4Cards call IncrementDeckCardsInTempCollection ret ; goes through cards in deck in de ; and for each card ID, increments its corresponding ; entry in wTempCardCollection IncrementDeckCardsInTempCollection: call EnableSRAM ld bc, wTempCardCollection ld h, DECK_SIZE .loop ld a, [de] inc de or a jr z, .done push hl ld h, $0 ld l, a add hl, bc inc [hl] pop hl dec h jr nz, .loop .done call DisableSRAM ret ; prints the name, level and storage count of the cards ; that are visible in the list window ; in the form: ; CARD NAME/LEVEL X ; where X is the current count of that card PrintCardSelectionList: push bc ld hl, wCardListCoords ld e, [hl] inc hl ld d, [hl] ld b, 19 ; x coord ld c, e ld a, [wCardListVisibleOffset] or a jr z, .alternate_cursor_tile ld a, SYM_CURSOR_U jr .got_cursor_tile_1 .alternate_cursor_tile ld a, [wCursorAlternateTile] .got_cursor_tile_1 call WriteByteToBGMap0 ; iterates by decreasing value in wNumVisibleCardListEntries ; by 1 until it reaches 0 ld a, [wCardListVisibleOffset] ld c, a ld b, $0 ld hl, wFilteredCardList add hl, bc ld a, [wNumVisibleCardListEntries] .loop_filtered_cards push de or a jr z, .exit_loop ld b, a ld a, [hli] or a jr z, .invalid_card ; card ID of 0 ld e, a call AddCardIDToVisibleList call LoadCardDataToBuffer1_FromCardID ; places in wDefaultText the card's name and level ; then appends at the end the count of that card ; in the card storage ld a, 14 push bc push hl push de call CopyCardNameAndLevel pop de call AppendOwnedCardCountNumber pop hl pop bc pop de push hl call InitTextPrinting ld hl, wDefaultText jr .process_text .invalid_card pop de push hl call InitTextPrinting ld hl, Text_9a36 .process_text call ProcessText pop hl ld a, b dec a inc e inc e jr .loop_filtered_cards .exit_loop ld a, [hli] or a jr z, .cannot_scroll pop de ; draw down cursor because ; there are still more cards ; to be scrolled down xor a ; FALSE ld [wUnableToScrollDown], a ld a, SYM_CURSOR_D jr .got_cursor_tile_2 .cannot_scroll pop de ld a, TRUE ld [wUnableToScrollDown], a ld a, [wCursorAlternateTile] .got_cursor_tile_2 ld b, 19 ; x coord ld c, e dec c dec c call WriteByteToBGMap0 pop bc ret ; appends the card count given in register e ; to the list in hl, in numerical form ; (i.e. its numeric symbol representation) AppendOwnedCardCountNumber: push af push bc push de push hl ; increment hl until end is reached ($00 byte) .loop ld a, [hl] or a jr z, .end inc hl jr .loop .end call GetOwnedCardCount call ConvertToNumericalDigits ld [hl], $00 ; insert byte terminator pop hl pop de pop bc pop af ret ; print header info (card count and player name) PrintPlayersCardsHeaderInfo: call Set_OBJ_8x8 call Func_8d78 .skip_empty_screen lb bc, 0, 4 ld a, SYM_BOX_TOP call FillBGMapLineWithA call PrintTotalNumberOfCardsInCollection call PrintPlayersCardsText call DrawCardTypeIcons ret ; prints "'s cards" PrintPlayersCardsText: lb de, 1, 0 call InitTextPrinting ld de, wDefaultText call CopyPlayerName ld hl, wDefaultText call ProcessText ld hl, wDefaultText call GetTextLengthInTiles inc b ld d, b ld e, 0 call InitTextPrinting ldtx hl, SCardsText call ProcessTextFromID ret PrintTotalNumberOfCardsInCollection: ld a, ALL_DECKS call CreateCardCollectionListWithDeckCards ; count all the cards in collection ld de, wTempCardCollection + 1 ld b, 0 ld hl, 0 .loop_all_cards ld a, [de] inc de and $7f push bc ld b, $00 ld c, a add hl, bc pop bc inc b ld a, NUM_CARDS cp b jr nz, .loop_all_cards ; hl = total number of cards in collection call .GetTotalCountDigits ld hl, wTempCardCollection ld de, wOnesAndTensPlace ld b, $00 call .PlaceNumericalChar call .PlaceNumericalChar call .PlaceNumericalChar call .PlaceNumericalChar call .PlaceNumericalChar ld a, $07 ld [hli], a ld [hl], TX_END lb de, 13, 0 call InitTextPrinting ld hl, wTempCardCollection call ProcessText ret ; places a numerical character in hl from de ; doesn't place a 0 if no non-0 ; numerical character has been placed before ; this makes it so that there are no ; 0s in more significant digits .PlaceNumericalChar ld [hl], TX_SYMBOL inc hl ld a, b or a jr z, .leading_num ld a, [de] inc de ld [hli], a ret .leading_num ; don't place a 0 as a leading number ld a, [de] inc de cp SYM_0 jr z, .space_char ld [hli], a ld b, $01 ; at least one non-0 char was placed ret .space_char xor a ; SYM_SPACE ld [hli], a ret ; gets the digits in decimal form ; of value stored in hl ; stores the result in wOnesAndTensPlace .GetTotalCountDigits ld de, wOnesAndTensPlace ld bc, -10000 call .GetDigit ld bc, -1000 call .GetDigit ld bc, -100 call .GetDigit ld bc, -10 call .GetDigit ld bc, -1 call .GetDigit ret .GetDigit ld a, SYM_0 - 1 .loop inc a add hl, bc jr c, .loop ld [de], a inc de ld a, l sub c ld l, a ld a, h sbc b ld h, a ret