diff options
author | ElectroDeoxys <ElectroDeoxys@gmail.com> | 2021-09-27 11:56:10 +0100 |
---|---|---|
committer | ElectroDeoxys <ElectroDeoxys@gmail.com> | 2021-09-27 11:56:10 +0100 |
commit | 7825b5ef0f09a877142ea1eb221e895bb60a0253 (patch) | |
tree | 9d46dfebd219919f5144786caf3ebfdf7cdab3a7 | |
parent | 48f83527c769441b6c123f3382d90e2e962ef9a0 (diff) |
Split bank 6
28 files changed, 6050 insertions, 5990 deletions
diff --git a/src/engine/auto_deck_machines.asm b/src/engine/auto_deck_machines.asm new file mode 100644 index 0000000..0f84cef --- /dev/null +++ b/src/engine/auto_deck_machines.asm @@ -0,0 +1,191 @@ +INCLUDE "data/auto_deck_card_lists.asm" +INCLUDE "data/auto_deck_machines.asm" + +; writes to sAutoDecks all the deck configurations +; from the Auto Deck Machine in wCurAutoDeckMachine +ReadAutoDeckConfiguration: + call EnableSRAM + ld a, [wCurAutoDeckMachine] + ld l, a + ld h, 6 * NUM_DECK_MACHINE_SLOTS + call HtimesL + ld bc, AutoDeckMachineEntries + add hl, bc + ld b, 0 +.loop_decks + call .GetPointerToSRAMAutoDeck + call .ReadDeckConfiguration + call .ReadDeckName + + ; store deck description text ID + push hl + ld de, wAutoDeckMachineTextDescriptions + ld h, b + ld l, 2 + call HtimesL + add hl, de + ld d, h + ld e, l + pop hl + ld a, [hli] + ld [de], a + inc de + ld a, [hli] + ld [de], a + inc b + ld a, b + cp NUM_DECK_MACHINE_SLOTS + jr nz, .loop_decks + call DisableSRAM + ret + +; outputs in de the saved deck with index b +.GetPointerToSRAMAutoDeck + push hl + ld l, b + ld h, DECK_STRUCT_SIZE + call HtimesL + ld de, sAutoDecks + add hl, de + ld d, h + ld e, l + pop hl + ret + +; writes the deck configuration in SRAM +; by reading the given deck card list +.ReadDeckConfiguration + push hl + push bc + push de + push de + ld e, [hl] + inc hl + ld d, [hl] + pop hl + ld bc, DECK_NAME_SIZE + add hl, bc +.loop_create_deck + ld a, [de] + inc de + ld b, a ; card count + or a + jr z, .done_create_deck + ld a, [de] + inc de + ld c, a ; card ID +.loop_card_count + ld [hl], c + inc hl + dec b + jr nz, .loop_card_count + jr .loop_create_deck +.done_create_deck + pop de + pop bc + pop hl + inc hl + inc hl + ret + +.ReadDeckName + push hl + push bc + push de + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wDismantledDeckName + call CopyText + pop hl + ld de, wDismantledDeckName +.loop_copy_name + ld a, [de] + ld [hli], a + or a + jr z, .done_copy_name + inc de + jr .loop_copy_name +.done_copy_name + pop bc + pop hl + inc hl + inc hl + ret + +; tries out all combinations of dismantling the player's decks +; in order to build the deck in wSelectedDeckMachineEntry +; if none of the combinations work, return carry set +; otherwise, return in a which deck flags should be dismantled +CheckWhichDecksToDismantleToBuildSavedDeck: + xor a + ld [wDecksToBeDismantled], a + +; first check if it can be built by +; only dismantling a single deck + ld a, DECK_1 +.loop_single_built_decks + call .CheckIfCanBuild + ret nc + sla a ; next deck + cp (1 << NUM_DECKS) + jr z, .two_deck_combinations + jr .loop_single_built_decks + +.two_deck_combinations +; next check all two deck combinations + ld a, DECK_1 | DECK_2 + call .CheckIfCanBuild + ret nc + ld a, DECK_1 | DECK_3 + call .CheckIfCanBuild + ret nc + ld a, DECK_1 | DECK_4 + call .CheckIfCanBuild + ret nc + ld a, DECK_2 | DECK_3 + call .CheckIfCanBuild + ret nc + ld a, DECK_2 | DECK_4 + call .CheckIfCanBuild + ret nc + ld a, DECK_3 | DECK_4 + call .CheckIfCanBuild + ret nc + +; all but one deck combinations + ld a, $ff ^ DECK_4 +.loop_three_deck_combinations + call .CheckIfCanBuild + ret nc + sra a + cp $ff + jr z, .all_decks + jr .loop_three_deck_combinations + +.all_decks +; finally check if can be built by dismantling all decks + call .CheckIfCanBuild + ret nc + +; none of the combinations work + scf + ret + +; returns carry if wSelectedDeckMachineEntry cannot be built +; by dismantling the decks given by register a +; a = DECK_* flags +.CheckIfCanBuild + push af + ld hl, wSelectedDeckMachineEntry + ld b, [hl] + farcall CheckIfCanBuildSavedDeck + jr c, .cannot_build + pop af + ld [wDecksToBeDismantled], a + or a + ret +.cannot_build + pop af + scf + ret diff --git a/src/engine/bank03.asm b/src/engine/bank03.asm index 3c83056..7bd4b75 100644 --- a/src/engine/bank03.asm +++ b/src/engine/bank03.asm @@ -2379,7 +2379,7 @@ ScriptCommand_ShowCardReceivedScreen: ; cee2 (3:4ee2) farcall Func_10000 farcall FlashWhiteScreen pop af - bank1call Func_7594 + bank1call ShowPromotionalCardScreen call WhiteOutDMGPals call DoFrameIfLCDEnabled call ReturnToOverworldNoCallback @@ -3199,7 +3199,7 @@ ScriptCommand_nop: ; d3d1 (3:53d1) ScriptCommand_GiveStarterDeck: ; d3d4 (3:53d4) ld a, [wStarterDeckChoice] - bank1call Func_7576 + bank1call AddStarterDeck jp IncreaseScriptPointerBy1 Unknown_d3dd: ; d3dd (3:53dd) diff --git a/src/engine/bank06.asm b/src/engine/bank06.asm deleted file mode 100644 index fa181f3..0000000 --- a/src/engine/bank06.asm +++ /dev/null @@ -1,5974 +0,0 @@ -; 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: ; 18000 (6:4000) - push bc - push de - ld [wCardNameLength], a - ld hl, wLoadedCard1Name - ld a, [hli] - ld h, [hl] - ld l, a - ld de, wDefaultText - push de - call CopyText ; copy card name to wDefaultText - pop hl - ld a, [hli] - cp TX_HALFWIDTH - jp z, _CopyCardNameAndLevel_HalfwidthText - -; the name doesn't start with TX_HALFWIDTH -; this doesn't appear to be ever the case (unless caller manipulates wLoadedCard1Name) - ld a, [wCardNameLength] - ld c, a - ld a, [wLoadedCard1Type] - cp TYPE_ENERGY - jr nc, .level_done ; jump if energy or trainer - ld a, [wLoadedCard1Level] - or a - jr z, .level_done - inc c - inc c - ld a, [wLoadedCard1Level] - cp 10 - jr c, .level_done - inc c ; second digit -.level_done - ld hl, wLoadedCard1Name - ld a, [hli] - ld h, [hl] - ld l, a - ld de, wDefaultText - push de - call CopyText - pop hl - push de - ld e, c - call GetTextLengthInTiles - add e - ld c, a - pop hl - push hl -.fill_loop - ld a, $70 - ld [hli], a - dec c - jr nz, .fill_loop - ld [hl], TX_END - pop hl - ld a, [wLoadedCard1Type] - cp TYPE_ENERGY - jr nc, .done - ld a, [wLoadedCard1Level] - or a - jr z, .done - ld a, TX_SYMBOL - ld [hli], a - ld [hl], SYM_Lv - inc hl - ld a, [wLoadedCard1Level] - cp 10 - jr c, .one_digit - ld [hl], TX_SYMBOL - inc hl - ld b, SYM_0 - 1 -.first_digit_loop - inc b - sub 10 - jr nc, .first_digit_loop - add 10 - ld [hl], b ; first digit - inc hl -.one_digit - ld [hl], TX_SYMBOL - inc hl - add SYM_0 - ld [hl], a ; last (or only) digit - inc hl -.done - pop de - pop bc - ret - -; the name starts with TX_HALFWIDTH -_CopyCardNameAndLevel_HalfwidthText: ; 18086 (6:4086) - ld a, [wCardNameLength] - inc a - add a - ld b, a - ld hl, wDefaultText -.find_end_text_loop - dec b - ld a, [hli] - or a ; TX_END - jr nz, .find_end_text_loop - dec hl - ld a, [wLoadedCard1Type] - cp TYPE_ENERGY - jr nc, .level_done - ld a, [wLoadedCard1Level] - or a - jr z, .level_done - ld c, a - ld a, " " - ld [hli], a - dec b - ld a, "L" - ld [hli], a - dec b - ld a, "v" - ld [hli], a - dec b - ld a, c - cp 10 - jr c, .got_level - push bc - ld b, "0" - 1 -.first_digit_loop - inc b - sub 10 - jr nc, .first_digit_loop - add 10 - ld [hl], b ; first digit - inc hl - pop bc - ld c, a - dec b -.got_level - ld a, c - add "0" - ld [hli], a ; last (or only) digit - dec b -.level_done - push hl - ld a, " " -.fill_spaces_loop - ld [hli], a - dec b - jr nz, .fill_spaces_loop - ld [hl], TX_END - pop hl - pop de - pop bc - ret - -; 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: ; 180d5 (6:40d5) - 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: ; 18248 (6:4248) - ; 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: ; 1826a (6:426a) - 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: ; 18293 (6:4293) - ldh a, [hWhoseTurn] - push af - bank1call OpenTurnHolderHandScreen_Simple - pop af - ldh [hWhoseTurn], a - ret - -OpenInPlayAreaScreen_NonTurnHolderHand: ; 1829d (6:429d) - ldh a, [hWhoseTurn] - push af - bank1call OpenNonTurnHolderHandScreen_Simple - pop af - ldh [hWhoseTurn], a - ret - -OpenInPlayAreaScreen_TurnHolderDiscardPile: ; 182a7 (6:42a7) - ldh a, [hWhoseTurn] - push af - bank1call OpenTurnHolderDiscardPileScreen - pop af - ldh [hWhoseTurn], a - ret - -OpenInPlayAreaScreen_NonTurnHolderDiscardPile: ; 182b1 (6:42b1) - 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: ; 183bb (6:43bb) - 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: ; 184bf (6:44bf) - call ZeroObjectPositions - ld a, $01 - ld [wVBlankOAMCopyToggle], a - ret - -OpenGlossaryScreen: ; 184c8 (6:44c8) - 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 - -Func_18661: ; 18661 (6:4661) - 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 - -INCLUDE "data/duel/effect_commands.asm" - -; reads the animation commands from PointerTable_AttackAnimation -; of attack in wLoadedAttackAnimation and plays them -PlayAttackAnimationCommands: ; 18f9c (6:4f9c) - ld a, [wLoadedAttackAnimation] - or a - ret z - - ld l, a - ld h, 0 - add hl, hl - ld de, PointerTable_AttackAnimation - add hl, de - ld e, [hl] - inc hl - ld d, [hl] - - push de - ld hl, wce7e - ld a, [hl] - or a - jr nz, .read_command - ld [hl], $01 - call Func_3b21 - pop de - - push de - ld a, DUEL_ANIM_SCREEN_MAIN_SCENE - ld [wDuelAnimationScreen], a - ld a, $01 - ld [wd4b3], a - xor a - ld [wDuelAnimLocationParam], a - ld a, [de] - cp $04 - jr z, .read_command - ld a, DUEL_ANIM_150 - call PlayDuelAnimation -.read_command - pop de - ; fallthrough - -PlayAttackAnimationCommands_NextCommand: ; 18fd4 (6:4fd4) - ld a, [de] - inc de - ld hl, AnimationCommandPointerTable - jp JumpToFunctionInTable - -AnimationCommand_AnimEnd: ; 18fdc (6:4fdc) - ret - -AnimationCommand_AnimPlayer: ; 18fdd (6:4fdd) - ldh a, [hWhoseTurn] - ld [wDuelAnimDuelistSide], a - ld a, [wDuelType] - cp $00 - jr nz, AnimationCommand_AnimNormal - ld a, PLAYER_TURN - ld [wDuelAnimDuelistSide], a - jr AnimationCommand_AnimNormal - -AnimationCommand_AnimOpponent: ; 18ff0 (6:4ff0) - call SwapTurn - ldh a, [hWhoseTurn] - ld [wDuelAnimDuelistSide], a - call SwapTurn - ld a, [wDuelType] - cp $00 - jr nz, AnimationCommand_AnimNormal - ld a, OPPONENT_TURN - ld [wDuelAnimDuelistSide], a - jr AnimationCommand_AnimNormal - -AnimationCommand_AnimUnknown2: ; 19009 (6:5009) - ld a, [wce82] - and $7f - ld [wDuelAnimLocationParam], a - jr AnimationCommand_AnimNormal - -AnimationCommand_AnimEnd2: ; 19013 (6:5013) - ret - -AnimationCommand_AnimNormal: ; 19014 (6:5014) - ld a, [de] - inc de - cp DUEL_ANIM_SHOW_DAMAGE - jr z, .show_damage - cp DUEL_ANIM_SHAKE1 - jr z, .shake_1 - cp DUEL_ANIM_SHAKE2 - jr z, .shake_2 - cp DUEL_ANIM_SHAKE3 - jr z, .shake_3 - -.play_anim - call PlayDuelAnimation - jr PlayAttackAnimationCommands_NextCommand - -.show_damage - ld a, DUEL_ANIM_PRINT_DAMAGE - call PlayDuelAnimation - ld a, [wce81] - ld [wd4b3], a - - push de - ld hl, wce7f - ld de, wDuelAnimDamage - ld a, [hli] - ld [de], a - inc de - ld a, [hli] - ld [de], a - pop de - - ld a, $8c - call PlayDuelAnimation - ld a, [wDuelDisplayedScreen] - cp DUEL_MAIN_SCENE - jr nz, .skip_update_hud - ld a, DUEL_ANIM_UPDATE_HUD - call PlayDuelAnimation -.skip_update_hud - jp PlayAttackAnimationCommands_NextCommand - -; screen shake happens differently -; depending on whose turn it is -.shake_1 - ld c, DUEL_ANIM_SMALL_SHAKE_X - ld b, DUEL_ANIM_SMALL_SHAKE_Y - jr .check_duelist - -.shake_2 - ld c, DUEL_ANIM_BIG_SHAKE_X - ld b, DUEL_ANIM_BIG_SHAKE_Y - jr .check_duelist - -.shake_3 - ld c, DUEL_ANIM_SMALL_SHAKE_Y - ld b, DUEL_ANIM_SMALL_SHAKE_X - -.check_duelist - ldh a, [hWhoseTurn] - cp PLAYER_TURN - ld a, c - jr z, .play_anim - ld a, [wDuelType] - cp $00 - ld a, c - jr z, .play_anim - ld a, b - jr .play_anim - -AnimationCommand_AnimUnknown: ; 19079 (6:5079) - ld a, [de] - inc de - ld [wd4b3], a - ld a, [wce82] - ld [wDuelAnimLocationParam], a - call SetDuelAnimationScreen - ld a, DUEL_ANIM_150 - call PlayDuelAnimation - jp PlayAttackAnimationCommands_NextCommand - -AnimationCommandPointerTable: ; 1908f (6:508f) - dw AnimationCommand_AnimEnd ; anim_end - dw AnimationCommand_AnimNormal ; anim_normal - dw AnimationCommand_AnimPlayer ; anim_player - dw AnimationCommand_AnimOpponent ; anim_opponent - dw AnimationCommand_AnimUnknown ; anim_unknown - dw AnimationCommand_AnimUnknown2 ; anim_unknown2 - dw AnimationCommand_AnimEnd2 ; anim_end2 (unused) - -; sets wDuelAnimationScreen according to wd4b3 -; if wd4b3 == $01, set it to Main Scene -; if wd4b3 == $04, st it to Play Area scene -SetDuelAnimationScreen: ; 1909d (6:509d) - ld a, [wd4b3] - cp $04 - jr z, .set_play_area_screen - cp $01 - ret nz - ld a, DUEL_ANIM_SCREEN_MAIN_SCENE - ld [wDuelAnimationScreen], a - ret - -.set_play_area_screen - ld a, [wDuelAnimLocationParam] - ld l, a - ld a, [wWhoseTurn] - ld h, a - cp PLAYER_TURN - jr z, .player - -; opponent - ld a, [wDuelType] - cp $00 - jr z, .asm_50c6 - -; link duel or vs. AI - bit 7, l - jr z, .asm_50e2 - jr .asm_50d2 - -.asm_50c6 - bit 7, l - jr z, .asm_50da - jr .asm_50ea - -.player - bit 7, l - jr z, .asm_50d2 - jr .asm_50e2 - -.asm_50d2 - ld l, UNKNOWN_SCREEN_4 - ld h, PLAYER_TURN - ld a, DUEL_ANIM_SCREEN_PLAYER_PLAY_AREA - jr .ok -.asm_50da - ld l, UNKNOWN_SCREEN_4 - ld h, OPPONENT_TURN - ld a, DUEL_ANIM_SCREEN_PLAYER_PLAY_AREA - jr .ok -.asm_50e2 - ld l, UNKNOWN_SCREEN_5 - ld h, OPPONENT_TURN - ld a, DUEL_ANIM_SCREEN_OPP_PLAY_AREA - jr .ok -.asm_50ea - ld l, UNKNOWN_SCREEN_5 - ld h, PLAYER_TURN - ld a, DUEL_ANIM_SCREEN_OPP_PLAY_AREA - -.ok - ld [wDuelAnimationScreen], a - ret - -Func_190f4: ; 190f4 (6:50f4) - ld a, [wd4b3] - cp $04 - jr z, Func_1910f - ; fallthrough - -Func_190fb: ; 190fb (6:50fb) - cp $01 - jr nz, .asm_510e - ld a, DUEL_ANIM_SCREEN_MAIN_SCENE - ld [wDuelAnimationScreen], a - ld a, [wDuelDisplayedScreen] - cp $01 - jr z, .asm_510e - bank1call DrawDuelMainScene -.asm_510e - ret - -Func_1910f: ; 1910f (6:510f) - call SetDuelAnimationScreen - ld a, [wDuelDisplayedScreen] - cp l - jr z, .skip_change_screen - ld a, l - push af - ld l, PLAYER_TURN - ld a, [wDuelType] - cp $00 - jr nz, .asm_5127 - ld a, [wWhoseTurn] - ld l, a -.asm_5127 - call DrawYourOrOppPlayAreaScreen_Bank0 - pop af - ld [wDuelDisplayedScreen], a -.skip_change_screen - call DrawWideTextBox - ret - -; prints text related to the damage received -; by card stored in wTempNonTurnDuelistCardID -; takes into account type effectiveness -PrintDamageText: ; 19132 (6:5132) - push hl - push bc - push de - ld a, [wLoadedAttackAnimation] - cp ATK_ANIM_HEAL - jr z, .skip - cp ATK_ANIM_HEALING_WIND_PLAY_AREA - jr z, .skip - - ld a, [wTempNonTurnDuelistCardID] - ld e, a - ld d, $00 - call LoadCardDataToBuffer1_FromCardID - ld a, 18 - call CopyCardNameAndLevel - ld [hl], TX_END - ld hl, wTxRam2 - xor a - ld [hli], a - ld [hl], a - ld hl, wce7f - ld a, [hli] - ld h, [hl] - ld l, a - call GetDamageText - ld a, l - or h - call nz, DrawWideTextBox_PrintText -.skip - pop de - pop bc - pop hl - ret - -; returns in hl the text id associated with -; the damage in hl and its effectiveness -GetDamageText: ; 19168 (6:5168) - ld a, l - or h - jr z, .no_damage - call LoadTxRam3 - ld a, [wce81] - ldtx hl, AttackDamageText - and (1 << RESISTANCE) | (1 << WEAKNESS) - ret z ; not weak or resistant - ldtx hl, WeaknessMoreDamage2Text - cp (1 << RESISTANCE) | (1 << WEAKNESS) - ret z ; weak and resistant - and (1 << WEAKNESS) - ldtx hl, WeaknessMoreDamageText - ret nz ; weak - ldtx hl, ResistanceLessDamageText - ret ; resistant - -.no_damage - call CheckNoDamageOrEffect - ret c - ldtx hl, NoDamageText - ld a, [wce81] - and (1 << RESISTANCE) - ret z ; not resistant - ldtx hl, ResistanceNoDamageText - ret ; resistant - -UpdateMainSceneHUD: ; 19199 (6:5199) - ld a, [wDuelDisplayedScreen] - cp DUEL_MAIN_SCENE - ret nz - bank1call DrawDuelHUDs - ret - -Func_191a3: ; 191a3 (6:51a3) - ret - -INCLUDE "data/duel/animations/attack_animations.asm" - -; if carry flag is set, only delays -; if carry not set: -; - set rRP to $c1, wait; -; - set rRP to $c0, wait; -; - return -Func_19674: ; 19674 (6:5674) - jr c, .delay_once - ld [hl], $c1 - ld a, 5 - jr .loop_delay_1 ; jump to possibly to add more cycles? -.loop_delay_1 - dec a - jr nz, .loop_delay_1 - ld [hl], $c0 - ld a, 14 - jr .loop_delay_2 ; jump to possibly to add more cycles? -.loop_delay_2 - dec a - jr nz, .loop_delay_2 - ret - -.delay_once - ld a, 21 - jr .loop_delay_3 ; jump to possibly to add more cycles? -.loop_delay_3 - dec a - jr nz, .loop_delay_3 - nop - ret - -; input a = byte to transmit through IR -TransmitByteThroughIR: ; 19692 (6:5692) - push hl - ld hl, rRP - push de - push bc - ld b, a - scf ; carry set - call Func_19674 - or a ; carry not set - call Func_19674 - ld c, 8 - ld c, 8 ; number of input bits -.loop - ld a, $00 - rr b - call Func_19674 - dec c - jr nz, .loop - pop bc - pop de - pop hl - ldh a, [rJOYP] - bit 1, a ; P11 - jr z, ReturnZFlagUnsetAndCarryFlagSet - xor a ; return z set - ret - -; same as ReceiveByteThroughIR but -; returns $0 in a if there's an error in IR -ReceiveByteThroughIR_ZeroIfUnsuccessful: ; 196ba (6:56ba) - call ReceiveByteThroughIR - ret nc - xor a - ret - -; returns carry if there's some time out -; and output in register a of $ff -; otherwise returns in a some sequence of bits -; related to how rRP sets/unsets bit 1 -ReceiveByteThroughIR: ; 196c0 (6:56c0) - push de - push bc - push hl - -; waits for bit 1 in rRP to be unset -; up to $100 loops - ld b, 0 - ld hl, rRP -.wait_ir - bit 1, [hl] - jr z, .ok - dec b - jr nz, .wait_ir - ; looped around $100 times - ; return $ff and carry set - pop hl - pop bc - pop de - scf - ld a, $ff - ret - -.ok -; delay for some cycles - ld a, 15 -.loop_delay - dec a - jr nz, .loop_delay - -; loop for each bit - ld e, 8 -.loop - ld a, $01 - ; possibly delay cycles? - ld b, 9 - ld b, 9 - ld b, 9 - ld b, 9 - -; checks for bit 1 in rRP -; if in any of the checks it is unset, -; then a is set to 0 -; this is done a total of 9 times - bit 1, [hl] - jr nz, .asm_196ec - xor a -.asm_196ec - bit 1, [hl] - jr nz, .asm_196f1 - xor a -.asm_196f1 - dec b - jr nz, .asm_196ec - ; one bit received - rrca - rr d - dec e - jr nz, .loop - ld a, d ; has bits set for each "cycle" that bit 1 was not unset - pop hl - pop bc - pop de - or a - ret - -ReturnZFlagUnsetAndCarryFlagSet: ; 19700 (6:5700) - ld a, $ff - or a ; z not set - scf ; carry set - ret - -; called when expecting to transmit data -Func_19705: ; 19705 (6:5705) - ld hl, rRP -.asm_19708 - ldh a, [rJOYP] - bit 1, a - jr z, ReturnZFlagUnsetAndCarryFlagSet - ld a, $aa ; request - call TransmitByteThroughIR - push hl - pop hl - call ReceiveByteThroughIR_ZeroIfUnsuccessful - cp $33 ; acknowledge - jr nz, .asm_19708 - xor a - ret - -; called when expecting to receive data -Func_1971e: ; 1971e (6:571e) - ld hl, rRP -.asm_19721 - ldh a, [rJOYP] - bit 1, a - jr z, ReturnZFlagUnsetAndCarryFlagSet - call ReceiveByteThroughIR_ZeroIfUnsuccessful - cp $aa ; request - jr nz, .asm_19721 - ld a, $33 ; acknowledge - call TransmitByteThroughIR - xor a - ret - -ReturnZFlagUnsetAndCarryFlagSet2: ; 19735 (6:5735) - jp ReturnZFlagUnsetAndCarryFlagSet - -TransmitIRDataBuffer: ; 19738 (6:5738) - call Func_19705 - jr c, ReturnZFlagUnsetAndCarryFlagSet2 - ld a, $49 - call TransmitByteThroughIR - ld a, $52 - call TransmitByteThroughIR - ld hl, wIRDataBuffer - ld c, 8 - jr TransmitNBytesFromHLThroughIR - -ReceiveIRDataBuffer: ; 1974e (6:5738) - call Func_1971e - jr c, ReturnZFlagUnsetAndCarryFlagSet2 - call ReceiveByteThroughIR - cp $49 - jr nz, ReceiveIRDataBuffer - call ReceiveByteThroughIR - cp $52 - jr nz, ReceiveIRDataBuffer - ld hl, wIRDataBuffer - ld c, 8 - jr ReceiveNBytesToHLThroughIR - -; hl = start of data to transmit -; c = number of bytes to transmit -TransmitNBytesFromHLThroughIR: ; 19768 (6:5768) - ld b, $0 -.loop_data_bytes - ld a, b - add [hl] - ld b, a - ld a, [hli] - call TransmitByteThroughIR - jr c, .asm_1977c - dec c - jr nz, .loop_data_bytes - ld a, b - cpl - inc a - call TransmitByteThroughIR -.asm_1977c - ret - -; hl = address to write received data -; c = number of bytes to be received -ReceiveNBytesToHLThroughIR: ; 1977d (6:577d) - ld b, 0 -.loop_data_bytes - call ReceiveByteThroughIR - jr c, ReturnZFlagUnsetAndCarryFlagSet2 - ld [hli], a - add b - ld b, a - dec c - jr nz, .loop_data_bytes - call ReceiveByteThroughIR - add b - or a - jr nz, ReturnZFlagUnsetAndCarryFlagSet2 - ret - -; disables interrupts, and sets joypad and IR communication port -; switches to CGB normal speed -StartIRCommunications: ; 19792 (6:5792) - di - call SwitchToCGBNormalSpeed - ld a, P14 - ldh [rJOYP], a - ld a, $c0 - ldh [rRP], a - ret - -; reenables interrupts, and switches CGB back to double speed -CloseIRCommunications: ; 1979f (6:579f) - ld a, P14 | P15 - ldh [rJOYP], a -.wait_vblank_on - ldh a, [rSTAT] - and STAT_LCDC_STATUS - cp STAT_ON_VBLANK - jr z, .wait_vblank_on -.wait_vblank_off - ldh a, [rSTAT] - and STAT_LCDC_STATUS - cp STAT_ON_VBLANK - jr nz, .wait_vblank_off - call SwitchToCGBDoubleSpeed - ei - ret - -; set rRP to 0 -ClearRP: ; 197b8 (6:57b8) - ld a, $00 - ldh [rRP], a - ret - -; expects to receive a command (IRCMD_* constant) -; in wIRDataBuffer + 1, then calls the subroutine -; corresponding to that command -ExecuteReceivedIRCommands: ; 197bd (6:57bd) - call StartIRCommunications -.loop_commands - call ReceiveIRDataBuffer - jr c, .error - jr nz, .loop_commands - ld hl, wIRDataBuffer + 1 - ld a, [hl] - ld hl, .CmdPointerTable - cp NUM_IR_COMMANDS - jr nc, .loop_commands ; invalid command - call .JumpToCmdPointer ; execute command - jr .loop_commands -.error - call CloseIRCommunications - xor a - scf - ret - -.JumpToCmdPointer - add a ; *2 - add l - ld l, a - ld a, 0 - adc h - ld h, a - ld a, [hli] - ld h, [hl] - ld l, a -.jp_hl - jp hl - -.CmdPointerTable - dw .Close ; IRCMD_CLOSE - dw .ReturnWithoutClosing ; IRCMD_RETURN_WO_CLOSING - dw .TransmitData ; IRCMD_TRANSMIT_DATA - dw .ReceiveData ; IRCMD_RECEIVE_DATA - dw .CallFunction ; IRCMD_CALL_FUNCTION - -; closes the IR communications -; pops hl so that the sp points -; to the return address of ExecuteReceivedIRCommands -.Close - pop hl - call CloseIRCommunications - or a - ret - -; returns without closing the IR communications -; will continue the command loop -.ReturnWithoutClosing - or a - ret - -; receives an address and number of bytes -; and transmits starting at that address -.TransmitData - call Func_19705 - ret c - call LoadRegistersFromIRDataBuffer - jp TransmitNBytesFromHLThroughIR - -; receives an address and number of bytes -; and writes the data received to that address -.ReceiveData - call LoadRegistersFromIRDataBuffer - ld l, e - ld h, d - call ReceiveNBytesToHLThroughIR - jr c, .asm_19812 - sub b - call TransmitByteThroughIR -.asm_19812 - ret - -; receives an address to call, then stores -; the registers in the IR data buffer -.CallFunction - call LoadRegistersFromIRDataBuffer - call .jp_hl - call StoreRegistersInIRDataBuffer - ret - -; returns carry set if request sent was not acknowledged -TrySendIRRequest: ; 1981d (6:581d) - call StartIRCommunications - ld hl, rRP - ld c, 4 -.send_request - ld a, $aa ; request - push bc - call TransmitByteThroughIR - push bc - pop bc - call ReceiveByteThroughIR_ZeroIfUnsuccessful - pop bc - cp $33 ; acknowledgement - jr z, .received_ack - dec c - jr nz, .send_request - scf - jr .close - -.received_ack - xor a -.close - push af - call CloseIRCommunications - pop af - ret - -; returns carry set if request was not received -TryReceiveIRRequest: ; 19842 (6:5842) - call StartIRCommunications - ld hl, rRP -.wait_request - call ReceiveByteThroughIR_ZeroIfUnsuccessful - cp $aa ; request - jr z, .send_ack - ldh a, [rJOYP] - cpl - and P10 | P11 - jr z, .wait_request - scf - jr .close - -.send_ack - ld a, $33 ; acknowledgement - call TransmitByteThroughIR - xor a -.close - push af - call CloseIRCommunications - pop af - ret - -; sends request for other device to close current communication -RequestCloseIRCommunication: ; 19865 (6:5865) - call StartIRCommunications - ld a, IRCMD_CLOSE - ld [wIRDataBuffer + 1], a - call TransmitIRDataBuffer -; fallthrough - -; calls CloseIRCommunications while preserving af -SafelyCloseIRCommunications: ; 19870 (6:5870) - push af - call CloseIRCommunications - pop af - ret - -; sends a request for data to be transmitted -; from the other device -; hl = start of data to request to transmit -; de = address to write data received -; c = length of data -RequestDataTransmissionThroughIR: ; 19876 (6:5876) - ld a, IRCMD_TRANSMIT_DATA - call TransmitRegistersThroughIR - push de - push bc - call Func_1971e - pop bc - pop hl - jr c, SafelyCloseIRCommunications - call ReceiveNBytesToHLThroughIR - jr SafelyCloseIRCommunications - -; transmits data to be written in the other device -; hl = start of data to transmit -; de = address for other device to write data -; c = length of data -RequestDataReceivalThroughIR: ; 19889 (6:5889) - ld a, IRCMD_RECEIVE_DATA - call TransmitRegistersThroughIR - call TransmitNBytesFromHLThroughIR - jr c, SafelyCloseIRCommunications - call ReceiveByteThroughIR - jr c, SafelyCloseIRCommunications - add b - jr nz, .asm_1989e - xor a - jr SafelyCloseIRCommunications -.asm_1989e - call ReturnZFlagUnsetAndCarryFlagSet - jr SafelyCloseIRCommunications - -; first stores all the current registers in wIRDataBuffer -; then transmits it through IR -TransmitRegistersThroughIR: ; 198a3 (6:58a3) - push hl - push de - push bc - call StoreRegistersInIRDataBuffer - call StartIRCommunications - call TransmitIRDataBuffer - pop bc - pop de - pop hl - ret nc - inc sp - inc sp - jr SafelyCloseIRCommunications - -; stores af, hl, de and bc in wIRDataBuffer -StoreRegistersInIRDataBuffer: ; 198b7 (6:58b7) - push de - push hl - push af - ld hl, wIRDataBuffer - pop de - ld [hl], e ; <- f - inc hl - ld [hl], d ; <- a - inc hl - pop de - ld [hl], e ; <- l - inc hl - ld [hl], d ; <- h - inc hl - pop de - ld [hl], e ; <- e - inc hl - ld [hl], d ; <- d - inc hl - ld [hl], c ; <- c - inc hl - ld [hl], b ; <- b - ret - -; loads all the registers that were stored -; from StoreRegistersInIRDataBuffer -LoadRegistersFromIRDataBuffer: ; 198d0 (6:58d0) - ld hl, wIRDataBuffer - ld e, [hl] - inc hl - ld d, [hl] - inc hl - push de - ld e, [hl] - inc hl - ld d, [hl] - inc hl - push de - ld e, [hl] - inc hl - ld d, [hl] - inc hl - ld c, [hl] - inc hl - ld b, [hl] - pop hl - pop af - ret - -; empties screen and replaces -; wVBlankFunctionTrampoline with HandleAllSpriteAnimations -Func_198e7: ; 198e7 (6:58e7) - call EmptyScreen - call Set_OBJ_8x8 - call Func_3ca4 - lb de, $38, $7f - call SetupText - ld hl, wVBlankFunctionTrampoline + 1 - ld de, wVBlankFunctionTrampolineBackup - call BackupVBlankFunctionTrampoline - di - ld [hl], LOW(HandleAllSpriteAnimations) - inc hl - ld [hl], HIGH(HandleAllSpriteAnimations) - ei - ret - -; sets backup VBlank function as wVBlankFunctionTrampoline -RestoreVBlankFunction: ; 19907 (6:5907) - ld hl, wVBlankFunctionTrampolineBackup - ld de, wVBlankFunctionTrampoline + 1 - call BackupVBlankFunctionTrampoline - call Func_3ca4 - bank1call ZeroObjectPositionsAndToggleOAMCopy - ret - -; copies 2 bytes from hl to de while interrupts are disabled -; used to load or store wVBlankFunctionTrampoline -; to wVBlankFunctionTrampolineBackup -BackupVBlankFunctionTrampoline: ; 19917 (6:5917) - di - ld a, [hli] - ld [de], a - inc de - ld a, [hld] - ld [de], a - ei - ret - -Func_1991f: ; 1991f (6:591f) - add a - ld e, a - ld d, 0 - ld hl, .data - add hl, de - ld a, PLAYER_TURN - ldh [hWhoseTurn], a - ld a, [hli] - add $02 - push hl - ld hl, sDeck1Name - call CopyDeckNameAndCards - pop hl - call SwapTurn - ld a, [hli] - add $02 - call LoadDeck - call SwapTurn - call EnableSRAM - ld h, $a1 - ld de, wPlayerDeck - ld c, $3c -.asm_594c - ld a, [de] - inc de - ld l, a - res 7, [hl] - dec c - jr nz, .asm_594c - - ld h, $a1 - ld de, wOpponentDeck - ld c, $1e -.asm_595b - ld a, [de] - inc de - ld l, a - res 7, [hl] - inc [hl] - dec c - jr nz, .asm_595b - - call DisableSRAM - ret -.data - db $03, $04, $05, $06, $07, $08 - -; clears saved data (card Collection/saved decks/Card Pop! data/etc) -; then adds the starter decks as saved decks -; marks all cards in Collection as not owned -InitSaveData: ; 1996e (6:596e) -; clear card and deck save data - call EnableSRAM - ld a, PLAYER_TURN - ldh [hWhoseTurn], a - ld hl, sCardAndDeckSaveData - ld bc, sCardAndDeckSaveDataEnd - sCardAndDeckSaveData -.loop_clear - xor a - ld [hli], a - dec bc - ld a, c - or b - jr nz, .loop_clear - -; add the starter decks - ld a, CHARMANDER_AND_FRIENDS_DECK - ld hl, sSavedDeck1 - call CopyDeckNameAndCards - ld a, SQUIRTLE_AND_FRIENDS_DECK - ld hl, sSavedDeck2 - call CopyDeckNameAndCards - ld a, BULBASAUR_AND_FRIENDS_DECK - ld hl, sSavedDeck3 - call CopyDeckNameAndCards - -; marks all cards in Collection to not owned - call EnableSRAM - ld hl, sCardCollection - ld a, CARD_NOT_OWNED -.loop_collection - ld [hl], a - inc l - jr nz, .loop_collection - - ld hl, sCurrentDuel - xor a - ld [hli], a - ld [hli], a ; sCurrentDuelChecksum - ld [hl], a - -; clears Card Pop! names - ld hl, sCardPopNameList - ld c, CARDPOP_NAME_LIST_MAX_ELEMS -.loop_card_pop_names - ld [hl], $0 - ld de, NAME_BUFFER_LENGTH - add hl, de - dec c - jr nz, .loop_card_pop_names - -; saved configuration options - ld a, 2 - ld [sPrinterContrastLevel], a - ld a, $2 - ld [sTextSpeed], a - ld [wTextSpeed], a - -; miscellaneous data - xor a - ld [sAnimationsDisabled], a - ld [sSkipDelayAllowed], a - ld [s0a004], a - ld [sTotalCardPopsDone], a - ld [sReceivedLegendaryCards], a - farcall InitPromotionalCardAndDeckCounterSaveData - call DisableSRAM - ret - -; input: -; a = Deck ID -; hl = destination to copy -CopyDeckNameAndCards: ; 199e0 (6:59e0) - push de - push bc - push hl - call LoadDeck - jr c, .done - call .CopyDeckName - pop hl - call EnableSRAM - push hl - ld de, wDefaultText -.loop_write_name - ld a, [de] - inc de - ld [hli], a - or a - jr nz, .loop_write_name - pop hl - - push hl - ld de, DECK_NAME_SIZE - add hl, de - ld de, wPlayerDeck - ld c, DECK_SIZE -.loop_write_cards - ld a, [de] - inc de - ld [hli], a - dec c - jr nz, .loop_write_cards - call DisableSRAM - or a -.done - pop hl - pop bc - pop de - ret - -.CopyDeckName - ld hl, wDeckName - ld a, [hli] - ld h, [hl] - ld l, a - ld de, wDefaultText - call CopyText - ret - -; hl = text ID -LoadLinkConnectingScene: ; 19a1f (6:5a1f) - push hl - call Func_198e7 - ld a, SCENE_GAMEBOY_LINK_CONNECTING - lb bc, 0, 0 - call LoadScene - pop hl - call DrawWideTextBox_PrintText - call EnableLCD - ret - -; shows Link Not Connected scene -; then asks the player whether they want to try again -; if the player selects "no", return carry -; input: -; - hl = text ID -LoadLinkNotConnectedSceneAndAskWhetherToTryAgain: ; 19a33 (6:5a33) - push hl - call RestoreVBlankFunction - call Func_198e7 - ld a, SCENE_GAMEBOY_LINK_NOT_CONNECTED - lb bc, 0, 0 - call LoadScene - pop hl - call DrawWideTextBox_WaitForInput - ldtx hl, WouldYouLikeToTryAgainText - call YesOrNoMenuWithText_SetCursorToYes -; fallthrough - -ClearRPAndRestoreVBlankFunction: ; 19a4c (6:5a4c) - push af - call ClearRP - call RestoreVBlankFunction - pop af - ret - -; prepares IR communication parameter data -; a = a IRPARAM_* constant for the function of this connection -InitIRCommunications: ; 19a55 (6:5a55) - ld hl, wOwnIRCommunicationParams - ld [hl], a - inc hl - ld [hl], $50 - inc hl - ld [hl], $4b - inc hl - ld [hl], $31 - ld a, $ff - ld [wIRCommunicationErrorCode], a - ld a, PLAYER_TURN - ldh [hWhoseTurn], a -; clear wNameBuffer and wOpponentName - xor a - ld [wNameBuffer], a - ld hl, wOpponentName - ld [hli], a - ld [hl], a -; loads player's name from SRAM -; to wDefaultText - call EnableSRAM - ld hl, sPlayerName - ld de, wDefaultText - ld c, NAME_BUFFER_LENGTH -.loop - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .loop - call DisableSRAM - ret - -; returns carry if communication was unsuccessful -; if a = 0, then it was a communication error -; if a = 1, then operation was cancelled by the player -PrepareSendCardOrDeckConfigurationThroughIR: ; 19a89 (6:5a89) - call InitIRCommunications - -; pressing A button triggers request for IR communication -.loop_frame - call DoFrame - ldh a, [hKeysPressed] - bit B_BUTTON_F, a - jr nz, .b_btn - ldh a, [hKeysHeld] - bit A_BUTTON_F, a - jr z, .loop_frame -; a btn - call TrySendIRRequest - jr nc, .request_success - or a - jr z, .loop_frame - xor a - scf - ret - -.b_btn - ; cancelled by the player - ld a, $01 - scf - ret - -.request_success - call ExchangeIRCommunicationParameters - ret c - ld a, [wOtherIRCommunicationParams + 3] - cp $31 - jr nz, SetIRCommunicationErrorCode_Error - or a - ret - -; exchanges player names and IR communication parameters -; checks whether parameters for communication match -; and if they don't, an error is issued -ExchangeIRCommunicationParameters: ; 19ab7 (6:5ab7) - ld hl, wOwnIRCommunicationParams - ld de, wOtherIRCommunicationParams - ld c, 4 - call RequestDataTransmissionThroughIR - jr c, .error - ld hl, wOtherIRCommunicationParams + 1 - ld a, [hli] - cp $50 - jr nz, .error - ld a, [hli] - cp $4b - jr nz, .error - ld a, [wOwnIRCommunicationParams] - ld hl, wOtherIRCommunicationParams - cp [hl] ; do parameters match? - jr nz, SetIRCommunicationErrorCode_Error - -; receives wDefaultText from other device -; and writes it to wNameBuffer - ld hl, wDefaultText - ld de, wNameBuffer - ld c, NAME_BUFFER_LENGTH - call RequestDataTransmissionThroughIR - jr c, .error -; transmits wDefaultText to be -; written in wNameBuffer in the other device - ld hl, wDefaultText - ld de, wNameBuffer - ld c, NAME_BUFFER_LENGTH - call RequestDataReceivalThroughIR - jr c, .error - or a - ret - -.error - xor a - scf - ret - -SetIRCommunicationErrorCode_Error: ; 19af9 (6:5af9) - ld hl, wIRCommunicationErrorCode - ld [hl], $01 - ld de, wIRCommunicationErrorCode - ld c, 1 - call RequestDataReceivalThroughIR - call RequestCloseIRCommunication - ld a, $01 - scf - ret - -SetIRCommunicationErrorCode_NoError: ; 19b0d (6:5b0d) - ld hl, wOwnIRCommunicationParams - ld [hl], $00 - ld de, wIRCommunicationErrorCode - ld c, 1 - call RequestDataReceivalThroughIR - ret c - call RequestCloseIRCommunication - or a - ret - -; makes device receptive to receive data from other device -; to write in wDuelTempList (either list of cards or a deck configuration) -; returns carry if some error occurred -TryReceiveCardOrDeckConfigurationThroughIR: ; 19b20 (6:5b20) - call InitIRCommunications -.loop_receive_request - xor a - ld [wDuelTempList], a - call TryReceiveIRRequest - jr nc, .receive_data - bit 1, a - jr nz, .cancelled - jr .loop_receive_request -.receive_data - call ExecuteReceivedIRCommands - ld a, [wIRCommunicationErrorCode] - or a - ret z ; no error - xor a - scf - ret - -.cancelled - ld a, $01 - scf - ret - -; returns carry if card(s) wasn't successfully sent -_SendCard: ; 19b41 (6:5b41) - call StopMusic - ldtx hl, SendingACardText - call LoadLinkConnectingScene - ld a, IRPARAM_SEND_CARDS - call PrepareSendCardOrDeckConfigurationThroughIR - jr c, .fail - - ; send cards - xor a - ld [wDuelTempList + DECK_SIZE], a - ld hl, wDuelTempList - ld e, l - ld d, h - ld c, DECK_SIZE + 1 - call RequestDataReceivalThroughIR - jr c, .fail - call SetIRCommunicationErrorCode_NoError - jr c, .fail - call ExecuteReceivedIRCommands - jr c, .fail - ld a, [wOwnIRCommunicationParams + 1] - cp $4f - jr nz, .fail - call PlayCardPopSong - xor a - call ClearRPAndRestoreVBlankFunction - ret - -.fail - call PlayCardPopSong - ldtx hl, CardTransferWasntSuccessful1Text - call LoadLinkNotConnectedSceneAndAskWhetherToTryAgain - jr nc, _SendCard ; loop back and try again - ; failed - scf - ret - -PlayCardPopSong: ; 19b87 (6:5b87) - ld a, MUSIC_CARD_POP - jp PlaySong - -_ReceiveCard: ; 19b8c (6:5b8c) - call StopMusic - ldtx hl, ReceivingACardText - call LoadLinkConnectingScene - ld a, IRPARAM_SEND_CARDS - call TryReceiveCardOrDeckConfigurationThroughIR - ld a, $4f - ld [wOwnIRCommunicationParams + 1], a - ld hl, wOwnIRCommunicationParams - ld e, l - ld d, h - ld c, 4 - call RequestDataReceivalThroughIR - jr c, .fail - call RequestCloseIRCommunication - jr c, .fail - call PlayCardPopSong - or a - call ClearRPAndRestoreVBlankFunction - ret - -.fail - call PlayCardPopSong - ldtx hl, CardTransferWasntSuccessful2Text - call LoadLinkNotConnectedSceneAndAskWhetherToTryAgain - jr nc, _ReceiveCard - scf - ret - -_SendDeckConfiguration: ; 19bc5 (6:5bc5) - call StopMusic - ldtx hl, SendingADeckConfigurationText - call LoadLinkConnectingScene - ld a, IRPARAM_SEND_DECK - call PrepareSendCardOrDeckConfigurationThroughIR - jr c, .fail - ld hl, wDuelTempList - ld e, l - ld d, h - ld c, DECK_STRUCT_SIZE - call RequestDataReceivalThroughIR - jr c, .fail - call SetIRCommunicationErrorCode_NoError - jr c, .fail - call PlayCardPopSong - call ClearRPAndRestoreVBlankFunction - or a - ret - -.fail - call PlayCardPopSong - ldtx hl, DeckConfigurationTransferWasntSuccessful1Text - call LoadLinkNotConnectedSceneAndAskWhetherToTryAgain - jr nc, _SendDeckConfiguration - scf - ret - -_ReceiveDeckConfiguration: ; 19bfb (6:5bfb) - call StopMusic - ldtx hl, ReceivingDeckConfigurationText - call LoadLinkConnectingScene - ld a, IRPARAM_SEND_DECK - call TryReceiveCardOrDeckConfigurationThroughIR - jr c, .fail - call PlayCardPopSong - call ClearRPAndRestoreVBlankFunction - or a - ret - -.fail - call PlayCardPopSong - ldtx hl, DeckConfigurationTransferWasntSuccessful2Text - call LoadLinkNotConnectedSceneAndAskWhetherToTryAgain - jr nc, _ReceiveDeckConfiguration ; loop back and try again - scf - ret - -_DoCardPop: ; 19c20 (6:5c20) -; loads scene for Card Pop! screen -; then checks if console is SGB -; and issues an error message in case it is - call Func_198e7 - ld a,SCENE_CARD_POP - lb bc, 0, 0 - call LoadScene - ldtx hl, AreYouBothReadyToCardPopText - call PrintScrollableText_NoTextBoxLabel - call RestoreVBlankFunction - ldtx hl, CardPopCannotBePlayedWithTheGameBoyText - ld a, [wConsole] - cp CONSOLE_SGB - jr z, .error - -; initiate the communications - call PauseSong - call Func_198e7 - ld a, SCENE_GAMEBOY_LINK_CONNECTING - lb bc, 0, 0 - call LoadScene - ldtx hl, PositionGameBoyColorsAndPressAButtonText - call DrawWideTextBox_PrintText - call EnableLCD - call HandleCardPopCommunications - push af - push hl - call ClearRP - call RestoreVBlankFunction - pop hl - pop af - jr c, .error - -; show the received card detail page -; and play the corresponding song - ld a, [wLoadedCard1ID] - call AddCardToCollectionAndUpdateAlbumProgress - ld hl, wLoadedCard1Name - ld a, [hli] - ld h, [hl] - ld l, a - call LoadTxRam2 - ld a, PLAYER_TURN - ldh [hWhoseTurn], a - ld a, SFX_5D - call PlaySFX -.wait_sfx - call AssertSFXFinished - or a - jr nz, .wait_sfx - ld a, [wCardPopCardObtainSong] - call PlaySong - ldtx hl, ReceivedThroughCardPopText - bank1call _DisplayCardDetailScreen - call ResumeSong - lb de, $38, $9f - call SetupText - bank1call OpenCardPage_FromHand - ret - -.error -; show Card Pop! error scene -; and print text in hl - push hl - call ResumeSong - call Func_198e7 - ld a, SCENE_CARD_POP_ERROR - lb bc, 0, 0 - call LoadScene - pop hl - call PrintScrollableText_NoTextBoxLabel - call RestoreVBlankFunction - ret - -; handles all communications to the other device to do Card Pop! -; returns carry if Card Pop! is unsuccessful -; and returns in hl the corresponding error text ID -HandleCardPopCommunications: ; 19cb2 (6:5cb2) -; copy CardPopNameList from SRAM to WRAM - call EnableSRAM - ld hl, sCardPopNameList - ld de, wCardPopNameList - ld bc, CARDPOP_NAME_LIST_SIZE - call CopyDataHLtoDE - call DisableSRAM - - ld a, IRPARAM_CARD_POP - call InitIRCommunications -.asm_19cc9 - call TryReceiveIRRequest ; receive request - jr nc, .asm_19d05 - bit 1, a - jr nz, .fail - call TrySendIRRequest ; send request - jr c, .asm_19cc9 - -; do the player name search, then transmit the result - call ExchangeIRCommunicationParameters - jr c, .fail - ld hl, wCardPopNameList - ld de, wOtherPlayerCardPopNameList - ld c, 0 ; $100 bytes = CARDPOP_NAME_LIST_SIZE - call RequestDataTransmissionThroughIR - jr c, .fail - call LookUpNameInCardPopNameList - ld hl, wCardPopNameSearchResult - ld de, wCardPopNameSearchResult - ld c, 1 - call RequestDataReceivalThroughIR - jr c, .fail - call SetIRCommunicationErrorCode_NoError - jr c, .fail - call ExecuteReceivedIRCommands - jr c, .fail - jr .check_search_result - -.asm_19d05 - call ExecuteReceivedIRCommands - ld a, [wIRCommunicationErrorCode] - or a - jr nz, .fail - call RequestCloseIRCommunication - jr c, .fail - -.check_search_result - ld a, [wCardPopNameSearchResult] - or a - jr z, .success - ; not $00, means the name was found in the list - ldtx hl, CannotCardPopWithFriendPreviouslyPoppedWithText - scf - ret - -.success - call DecideCardToReceiveFromCardPop - -; increment number of times Card Pop! was done -; and write the other player's name to sCardPopNameList -; the spot where this is written in the list is derived -; from the lower nybble of sTotalCardPopsDone -; that means that after 16 Card Pop!, the older -; names start to get overwritten - call EnableSRAM - ld hl, sTotalCardPopsDone - ld a, [hl] - inc [hl] - and $0f - swap a ; *NAME_BUFFER_LENGTH - ld l, a - ld h, $0 - ld de, sCardPopNameList - add hl, de - ld de, wNameBuffer - ld c, NAME_BUFFER_LENGTH -.loop_write_name - ld a, [de] - inc de - ld [hli], a - dec c - jr nz, .loop_write_name - call DisableSRAM - or a - ret - -.fail - ldtx hl, ThePopWasntSuccessfulText - scf - ret - -; looks up the name in wNameBuffer in wCardPopNameList -; used to know whether this save file has done Card Pop! -; with the other player already -; returns carry and wCardPopNameSearchResult = $ff if the name was found; -; returns no carry and wCardPopNameSearchResult = $00 otherwise -LookUpNameInCardPopNameList: ; 19d49 (6:5d49) -; searches for other player's name in this game's name list - ld hl, wCardPopNameList - ld c, CARDPOP_NAME_LIST_MAX_ELEMS -.loop_own_card_pop_name_list - push hl - ld de, wNameBuffer - call .CompareNames - pop hl - jr nc, .found_name - ld de, NAME_BUFFER_LENGTH - add hl, de - dec c - jr nz, .loop_own_card_pop_name_list - -; name was not found in wCardPopNameList - -; searches for this player's name in the other game's name list -; this is useless since it discards the result from the name comparisons -; as a result this loop will always return no carry - call EnableSRAM - ld hl, wOtherPlayerCardPopNameList - ld c, CARDPOP_NAME_LIST_MAX_ELEMS -.loop_other_card_pop_name_list - push hl - ld de, sPlayerName - call .CompareNames ; discards result from comparison - pop hl - ld de, NAME_BUFFER_LENGTH - add hl, de - dec c - jr nz, .loop_other_card_pop_name_list - xor a - jr .no_carry - -.found_name - ld a, $ff - scf -.no_carry - call DisableSRAM - ld [wCardPopNameSearchResult], a ; $00 if name was not found, $ff otherwise - ret - -; compares names in hl and de -; if they are different, return carry -.CompareNames - ld b, NAME_BUFFER_LENGTH -.loop_chars - ld a, [de] - inc de - cp [hl] - jr nz, .not_same - inc hl - dec b - jr nz, .loop_chars - or a - ret -.not_same - scf - ret - -; loads in wLoadedCard1 a random card to be received -; this selection is done based on the rarity that is -; decided from the names of both participants -; the card will always be a Pokemon card that is not -; from a Promotional set, with the exception -; of Venusaur1 and Mew2 -; output: -; - e = card ID chosen -DecideCardToReceiveFromCardPop: ; 19d92 (6:5d92) - ld a, PLAYER_TURN - ldh [hWhoseTurn], a - call EnableSRAM - ld hl, sPlayerName - call CalculateNameHash - call DisableSRAM - push de - ld hl, wNameBuffer - call CalculateNameHash - pop bc - -; de = other player's name hash -; bc = this player's name hash - -; updates RNG values to subtraction of these two hashes - ld hl, wRNG1 - ld a, b - sub d - ld d, a ; b - d - ld [hli], a ; wRNG1 - ld a, c - sub e - ld e, a ; c - e - ld [hli], a ; wRNG2 - ld [hl], $0 ; wRNGCounter - -; depending on the values obtained from the hashes, -; determine which rarity card to give to the player -; along with the song to play with each rarity -; the probabilities of each possibility can be calculated -; as follows (given 2 random player names): -; 101/256 ~ 39% for Circle -; 90/256 ~ 35% for Diamond -; 63/256 ~ 25% for Star -; 1/256 ~ .4% for Venusaur1 or Mew2 - ld a, e - cp 5 - jr z, .venusaur1_or_mew2 - cp 64 - jr c, .star_rarity ; < 64 - cp 154 - jr c, .diamond_rarity ; < 154 - ; >= 154 - - ld a, MUSIC_BOOSTER_PACK - ld b, CIRCLE - jr .got_rarity -.diamond_rarity - ld a, MUSIC_BOOSTER_PACK - ld b, DIAMOND - jr .got_rarity -.star_rarity - ld a, MUSIC_MATCH_VICTORY - ld b, STAR -.got_rarity - ld [wCardPopCardObtainSong], a - ld a, b - call CreateCardPopCandidateList - ; shuffle candidates and pick first from list - call ShuffleCards - ld a, [hl] - ld e, a -.got_card_id - ld d, $0 - call LoadCardDataToBuffer1_FromCardID - ld a, e - ret - -.venusaur1_or_mew2 -; choose either Venusaur1 or Mew2 -; depending on whether the lower -; bit of d is unset or set, respectively - ld a, MUSIC_MEDAL - ld [wCardPopCardObtainSong], a - ld e, VENUSAUR1 - ld a, d - and $1 ; get lower bit - jr z, .got_card_id - ld e, MEW2 - jr .got_card_id - -; lists in wCardPopCardCandidates all cards that: -; - are Pokemon cards; -; - have the same rarity as input register a; -; - are not from Promotional set. -; input: -; - a = card rarity -; output: -; - a = number of candidates -CreateCardPopCandidateList: ; 19df7 (6:5df7) - ld hl, wPlayerDeck - push hl - push de - push bc - ld b, a - - lb de, 0, GRASS_ENERGY -.loop_card_ids - call LoadCardDataToBuffer1_FromCardID - jr c, .count ; no more card IDs - ld a, [wLoadedCard1Type] - and TYPE_ENERGY - jr nz, .next_card_id ; not Pokemon card - ld a, [wLoadedCard1Rarity] - cp b - jr nz, .next_card_id ; not equal rarity - ld a, [wLoadedCard1Set] - and $f0 - cp PROMOTIONAL - jr z, .next_card_id ; no promos - ld [hl], e - inc hl -.next_card_id - inc de - jr .loop_card_ids - -; count all the cards that were listed -; and return it in a -.count - ld [hl], $00 ; invalid card ID as end of list - ld hl, wPlayerDeck - ld c, -1 -.loop_count - inc c - ld a, [hli] - or a - jr nz, .loop_count - ld a, c - pop bc - pop de - pop hl - ret - -; creates a unique two-byte hash from the name given in hl -; the low byte is calculated by simply adding up all characters -; the high byte is calculated by xoring all characters together -; input: -; - hl = points to the start of the name buffer -; output: -; - de = hash -CalculateNameHash: ; 19e32 (6:5e32) - ld c, NAME_BUFFER_LENGTH - ld de, $0 -.loop - ld a, e - add [hl] - ld e, a - ld a, d - xor [hl] - ld d, a - inc hl - dec c - jr nz, .loop - ret - -; sends serial data to printer -; if there's an error in connection, -; show Printer Not Connected scene with error message -_PreparePrinterConnection: ; 19e42 (6:5e42) - ld bc, $0 - lb de, PRINTERPKT_DATA, $0 - call SendPrinterPacket - ret nc ; return if no error - - ld hl, wPrinterStatus - ld a, [hl] - or a - jr nz, .asm_19e55 - ld [hl], $ff -.asm_19e55 - ld a, [hl] - cp $ff - jr z, ShowPrinterIsNotConnected -; fallthrough - -; shows message on screen depending on wPrinterStatus -; also shows SCENE_GAMEBOY_PRINTER_NOT_CONNECTED. -HandlePrinterError: ; 19e5a (6:5e5a) - ld a, [wPrinterStatus] - cp $ff - jr z, .cable_or_printer_switch - or a - jr z, .interrupted - bit PRINTER_ERROR_BATTERIES_LOST_CHARGE, a - jr nz, .batteries_lost_charge - bit PRINTER_ERROR_CABLE_PRINTER_SWITCH, a - jr nz, .cable_or_printer_switch - bit PRINTER_ERROR_PAPER_JAMMED, a - jr nz, .jammed_printer - - ldtx hl, PrinterPacketErrorText - ld a, $04 - jr ShowPrinterConnectionErrorScene -.cable_or_printer_switch - ldtx hl, CheckCableOrPrinterSwitchText - ld a, $02 - jr ShowPrinterConnectionErrorScene -.jammed_printer - ldtx hl, PrinterPaperIsJammedText - ld a, $03 - jr ShowPrinterConnectionErrorScene -.batteries_lost_charge - ldtx hl, BatteriesHaveLostTheirChargeText - ld a, $01 - jr ShowPrinterConnectionErrorScene -.interrupted - ldtx hl, PrintingWasInterruptedText - call DrawWideTextBox_WaitForInput - scf - ret - -ShowPrinterIsNotConnected: ; 19e94 (6:5e94) - ldtx hl, PrinterIsNotConnectedText - ld a, $02 -; fallthrough - -; a = error code -; hl = text ID to print in text box -ShowPrinterConnectionErrorScene: ; 19e99 (6:5e99) - push hl - ; unnecessary loading TxRam, since the text data - ; already incorporate the error number - ld l, a - ld h, $00 - call LoadTxRam3 - - call Func_198e7 - ld a, SCENE_GAMEBOY_PRINTER_NOT_CONNECTED - lb bc, 0, 0 - call LoadScene - pop hl - call DrawWideTextBox_WaitForInput - call RestoreVBlankFunction - scf - ret - -; main card printer function -Func_19eb4: ; 19eb4 (6:5eb4) - ld e, a - ld d, $0 - call LoadCardDataToBuffer1_FromCardID - call Func_198e7 - ld a, SCENE_GAMEBOY_PRINTER_TRANSMITTING - lb bc, 0, 0 - call LoadScene - ld a, 20 - call CopyCardNameAndLevel - ld [hl], TX_END - ld hl, $0 - call LoadTxRam2 - ldtx hl, NowPrintingText - call DrawWideTextBox_PrintText - call EnableLCD - call PrepareForPrinterCommunications - call DrawTopCardInfoInSRAMGfxBuffer0 - call Func_19f87 - call DrawCardPicInSRAMGfxBuffer2 - call Func_19f99 - jr c, .error - call DrawBottomCardInfoInSRAMGfxBuffer0 - call Func_1a011 - jr c, .error - call RestoreVBlankFunction - call ResetPrinterCommunicationSettings - or a - ret -.error - call RestoreVBlankFunction - call ResetPrinterCommunicationSettings - jp HandlePrinterError - -DrawCardPicInSRAMGfxBuffer2: ; 19f05 (6:5f05) - ld hl, wLoadedCard1Gfx - ld a, [hli] - ld h, [hl] - ld l, a - ld de, sGfxBuffer2 - call Func_37a5 - ; draw card's picture in sGfxBuffer2 - ld a, $40 - lb hl, 12, 1 - lb de, 2, 68 - lb bc, 16, 12 - call FillRectangle - ret - -; writes the tiles necessary to draw -; the card's information in sGfxBuffer0 -; this includes card's type, lv, HP and attacks if Pokemon card -; or otherwise just the card's name and type symbol -DrawTopCardInfoInSRAMGfxBuffer0: ; 19f20 (6:5f20) - call Func_1a025 - call Func_212f - - ; draw empty text box frame - ld hl, sGfxBuffer0 - ld a, $34 - lb de, $30, $31 - ld b, 20 - call CopyLine - ld c, 15 -.loop_lines - xor a ; SYM_SPACE - lb de, $36, $37 - ld b, 20 - call CopyLine - dec c - jr nz, .loop_lines - - ; draw card type symbol - ld a, $38 - lb hl, 1, 2 - lb de, 1, 65 - lb bc, 2, 2 - call FillRectangle - ; print card's name - lb de, 4, 65 - ld hl, wLoadedCard1Name - call InitTextPrinting_ProcessTextFromPointerToID - -; prints card's type, lv, HP and attacks if it's a Pokemon card - ld a, [wLoadedCard1Type] - cp TYPE_ENERGY - jr nc, .skip_pokemon_data - inc a ; symbol corresponding to card's type (color) - lb bc, 18, 65 - call WriteByteToBGMap0 - ld a, SYM_Lv - lb bc, 11, 66 - call WriteByteToBGMap0 - ld a, [wLoadedCard1Level] - lb bc, 12, 66 - bank1call WriteTwoDigitNumberInTxSymbolFormat - ld a, SYM_HP - lb bc, 15, 66 - call WriteByteToBGMap0 - ld a, [wLoadedCard1EffectCommands] - inc b - bank1call WriteTwoByteNumberInTxSymbolFormat -.skip_pokemon_data - ret - -Func_19f87: ; 19f87 (6:5f87) - call TryInitPrinterCommunications - ret c - ld hl, sGfxBuffer0 - call Func_1a0cc - ret c - call Func_1a0cc - call Func_1a111 - ret - -Func_19f99: ; 19f99 (6:5f99) - call TryInitPrinterCommunications - ret c - ld hl, sGfxBuffer0 + $8 tiles - ld c, $06 -.asm_19fa2 - call Func_1a0cc - ret c - dec c - jr nz, .asm_19fa2 - call Func_1a111 - ret - -; writes the tiles necessary to draw -; the card's information in sGfxBuffer0 -; this includes card's Retreat cost, Weakness, Resistance, -; and attack if it's Pokemon card -; or otherwise just the card's description. -DrawBottomCardInfoInSRAMGfxBuffer0: ; 19fad (6:5fad) - call Func_1a025 - xor a - ld [wCardPageType], a - ld hl, sGfxBuffer0 - ld b, 20 - ld c, 9 -.loop_lines - xor a ; SYM_SPACE - lb de, $36, $37 - call CopyLine - dec c - jr nz, .loop_lines - ld a, $35 - lb de, $32, $33 - call CopyLine - - ld a, [wLoadedCard1Type] - cp TYPE_ENERGY - jr nc, .not_pkmn_card - ld hl, RetreatWeakResistData - call PlaceTextItems - ld c, 66 - bank1call DisplayCardPage_PokemonOverview.attacks - ld a, SYM_No - lb bc, 15, 72 - call WriteByteToBGMap0 - inc b - ld a, [wLoadedCard1PokedexNumber] - bank1call WriteTwoByteNumberInTxSymbolFormat - ret - -.not_pkmn_card - bank1call SetNoLineSeparation - lb de, 1, 66 - ld a, SYM_No - call InitTextPrintingInTextbox - ld hl, wLoadedCard1NonPokemonDescription - call ProcessTextFromPointerToID - bank1call SetOneLineSeparation - ret - -RetreatWeakResistData: ; 1a004 (6:6004) - textitem 1, 70, RetreatText - textitem 1, 71, WeaknessText - textitem 1, 72, ResistanceText - db $ff - -Func_1a011: ; 1a011 (6:6011) - call TryInitPrinterCommunications - ret c - ld hl, sGfxBuffer0 - ld c, $05 -.asm_1a01a - call Func_1a0cc - ret c - dec c - jr nz, .asm_1a01a - call Func_1a108 - ret - -; calls setup text and sets wTilePatternSelector -Func_1a025: ; 1a025 (6:6025) - lb de, $40, $bf - call SetupText - ld a, $a4 - ld [wTilePatternSelector], a - xor a - ld [wTilePatternSelectorCorrection], a - ret - -; switches to CGB normal speed, resets serial -; enables SRAM and switches to SRAM1 -; and clears sGfxBuffer0 -PrepareForPrinterCommunications: ; 1a035 (6:6035) - call SwitchToCGBNormalSpeed - call ResetSerial - ld a, $10 - ld [wce9b], a - call EnableSRAM - ld a, [sPrinterContrastLevel] - ld [wPrinterContrastLevel], a - call DisableSRAM - ldh a, [hBankSRAM] - ld [wce8f], a - ld a, BANK("SRAM1") - call BankswitchSRAM - call EnableSRAM -; fallthrough - -ClearPrinterGfxBuffer: ; 1a035 (6:6035) - ld hl, sGfxBuffer0 - ld bc, $400 -.loop - xor a - ld [hli], a - dec bc - ld a, c - or b - jr nz, .loop - xor a - ld [wce9f], a - ret - -; reverts settings changed by PrepareForPrinterCommunications -ResetPrinterCommunicationSettings: ; 1a06b (6:606b) - push af - call SwitchToCGBDoubleSpeed - ld a, [wce8f] - call BankswitchSRAM - call DisableSRAM - lb de, $30, $bf - call SetupText - pop af - ret - -; unreferenced -; send some bytes through serial -Func_1a080: ; 1a080 (6:6080) - ld bc, $0 - lb de, PRINTERPKT_NUL, $0 - jp SendPrinterPacket - -; tries initiating the communications for -; sending data to printer -; returns carry if operation was cancelled -; by pressing B button or serial transfer took long -TryInitPrinterCommunications: ; 1a089 (6:6089) - xor a - ld [wPrinterInitAttempts], a -.wait_input - call DoFrame - ldh a, [hKeysHeld] - and B_BUTTON - jr nz, .b_button - ld bc, $0 - lb de, PRINTERPKT_NUL, $0 - call SendPrinterPacket - jr c, .delay - and (1 << PRINTER_STATUS_BUSY) | (1 << PRINTER_STATUS_PRINTING) - jr nz, .wait_input - -.init - ld bc, $0 - lb de, PRINTERPKT_INIT, $0 - call SendPrinterPacket - jr nc, .no_carry - ld hl, wPrinterInitAttempts - inc [hl] - ld a, [hl] - cp 3 - jr c, .wait_input - ; time out - scf - ret -.no_carry - ret - -.b_button - xor a - ld [wPrinterStatus], a - scf - ret - -.delay - ld c, 10 -.delay_loop - call DoFrame - dec c - jr nz, .delay_loop - jr .init - -; loads tiles given by map in hl to sGfxBuffer5 -; copies first 20 tiles, then offsets by 2 tiles -; and copies another 20 -Func_1a0cc: ; 1a0cc (6:60cc) - push bc - ld de, sGfxBuffer5 - call .Copy20Tiles - call .Copy20Tiles - push hl - call CompressDataForPrinterSerialTransfer - call SendPrinterPacket - pop hl - pop bc - ret - -; copies 20 tiles given by hl to de -; then adds 2 tiles to hl -.Copy20Tiles ; 1a0e0 (6:60e0) - push hl - ld c, 20 -.loop_tiles - ld a, [hli] - call .CopyTile - dec c - jr nz, .loop_tiles - pop hl - ld bc, 2 tiles - add hl, bc - ret - -; copies a tile to de -; a = tile to get from sGfxBuffer1 -.CopyTile ; 1a0f0 (6:60f0) - push hl - push bc - ld l, a - ld h, $00 - add hl, hl - add hl, hl - add hl, hl - add hl, hl ; *TILE_SIZE - ld bc, sGfxBuffer1 - add hl, bc - ld c, TILE_SIZE -.loop_copy - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .loop_copy - pop bc - pop hl - ret - -Func_1a108: ; 1a108 (6:6108) - call GetPrinterContrastSerialData - push hl - lb hl, $3, $1 - jr SendPrinterInstructionPacket - -Func_1a111: ; 1a111 (6:6111) - call GetPrinterContrastSerialData - push hl - ld hl, wce9b - ld a, [hl] - ld [hl], $00 - ld h, a - ld l, $01 -; fallthrough - -SendPrinterInstructionPacket: ; 1a11e (6:611e) - push hl - ld bc, $0 - lb de, PRINTERPKT_DATA, $0 - call SendPrinterPacket - jr c, .asm_1a135 - ld hl, sp+$00 ; contrast level bytes - ld bc, $4 ; instruction packets are 4 bytes in size - lb de, PRINTERPKT_PRINT_INSTRUCTION, $0 - call SendPrinterPacket -.asm_1a135 - pop hl - pop hl - ret - -; returns in h and l the bytes -; to be sent through serial to the printer -; for the set contrast level -GetPrinterContrastSerialData: ; 1a138 (6:6138) - ld a, [wPrinterContrastLevel] - ld e, a - ld d, $00 - ld hl, .contrast_level_data - add hl, de - ld h, [hl] - ld l, $e4 - ret - -.contrast_level_data - db $00, $20, $40, $60, $7f - -; unreferenced -Func_1a14b: ; 1a14b (6:614b) - ld a, $01 - jr .asm_1a15d - ld a, $02 - jr .asm_1a15d - ld a, $03 - jr .asm_1a15d - ld a, $04 - jr .asm_1a15d - ld a, $05 -.asm_1a15d - ld [wce9d], a - scf - ret - -; a = saved deck index to print -_PrintDeckConfiguration: ; 1a162 (6:6162) -; copies selected deck from SRAM to wDuelTempList - call EnableSRAM - ld l, a - ld h, DECK_STRUCT_SIZE - call HtimesL - ld de, sSavedDeck1 - add hl, de - ld de, wDuelTempList - ld bc, DECK_STRUCT_SIZE - call CopyDataHLtoDE - call DisableSRAM - - call ShowPrinterTransmitting - call PrepareForPrinterCommunications - call Func_1a025 - call Func_212f - lb de, 0, 64 - lb bc, 20, 4 - call DrawRegularTextBoxDMG - lb de, 4, 66 - call InitTextPrinting - ld hl, wDuelTempList ; print deck name - call ProcessText - ldtx hl, DeckPrinterText - call ProcessTextFromID - - ld a, 5 - ld [wPrinterHorizontalOffset], a - ld hl, wPrinterTotalCardCount - xor a - ld [hli], a - ld [hl], a - ld [wPrintOnlyStarRarity], a - - ld hl, wCurDeckCards -.loop_cards - ld a, [hl] - or a - jr z, .asm_1a1d6 - ld e, a - ld d, $00 - call LoadCardDataToBuffer1_FromCardID - - ; find out this card's count - ld a, [hli] - ld b, a - ld c, 1 -.loop_card_count - cp [hl] - jr nz, .got_card_count - inc hl - inc c - jr .loop_card_count - -.got_card_count - ld a, c - ld [wPrinterCardCount], a - call LoadCardInfoForPrinter - call AddToPrinterGfxBuffer - jr c, .printer_error - jr .loop_cards - -.asm_1a1d6 - call SendCardListToPrinter - jr c, .printer_error - call ResetPrinterCommunicationSettings - call RestoreVBlankFunction - or a - ret - -.printer_error - call ResetPrinterCommunicationSettings - call RestoreVBlankFunction - jp HandlePrinterError - -SendCardListToPrinter: ; 1a1ec (6:61ec) - ld a, [wPrinterHorizontalOffset] - cp 1 - jr z, .skip_load_gfx - call LoadGfxBufferForPrinter - ret c -.skip_load_gfx - call TryInitPrinterCommunications - ret c - call Func_1a108 - ret -; 0z1a1ff - -; increases printer horizontal offset by 2 -AddToPrinterGfxBuffer: ; 1a1ff (6:61ff) - push hl - ld hl, wPrinterHorizontalOffset - inc [hl] - inc [hl] - ld a, [hl] - pop hl - ; return no carry if below 18 - cp 18 - ccf - ret nc - ; >= 18 -; fallthrough - -; copies Gfx to Gfx buffer and sends some serial data -; returns carry set if unsuccessful -LoadGfxBufferForPrinter: ; 1a20b (6:620b) - push hl - call TryInitPrinterCommunications - jr c, .set_carry - ld a, [wPrinterHorizontalOffset] - srl a - ld c, a - ld hl, sGfxBuffer0 -.loop_gfx_buffer - call Func_1a0cc - jr c, .set_carry - dec c - jr nz, .loop_gfx_buffer - call Func_1a111 - jr c, .set_carry - - call ClearPrinterGfxBuffer - ld a, 1 - ld [wPrinterHorizontalOffset], a - pop hl - or a - ret - -.set_carry - pop hl - scf - ret - -; load symbol, name, level and card count to buffer -LoadCardInfoForPrinter: ; 1a235 (6:6235) - push hl - ld a, [wPrinterHorizontalOffset] - or %1000000 - ld e, a - ld d, 3 - ld a, [wPrintOnlyStarRarity] - or a - jr nz, .skip_card_symbol - ld hl, wPrinterTotalCardCount - ld a, [hli] - or [hl] - call z, DrawCardSymbol -.skip_card_symbol - ld a, 14 - call CopyCardNameAndLevel - call InitTextPrinting - ld hl, wDefaultText - call ProcessText - ld a, [wPrinterHorizontalOffset] - or %1000000 - ld c, a - ld b, 16 - ld a, SYM_CROSS - call WriteByteToBGMap0 - inc b - ld a, [wPrinterCardCount] - bank1call WriteTwoDigitNumberInTxSymbolFormat - pop hl - ret - -_PrintCardList: ; 1a270 (6:6270) -; if Select button is held when printing card list -; only print cards with Star rarity (excluding Promotional cards) -; even if it's not marked as seen in the collection - ld e, FALSE - ldh a, [hKeysHeld] - and SELECT - jr z, .no_select - inc e ; TRUE -.no_select - ld a, e - ld [wPrintOnlyStarRarity], a - - call ShowPrinterTransmitting - call CreateTempCardCollection - ld de, wDefaultText - call CopyPlayerName - call PrepareForPrinterCommunications - call Func_1a025 - call Func_212f - - lb de, 0, 64 - lb bc, 20, 4 - call DrawRegularTextBoxDMG - ld a, PLAYER_TURN - ldh [hWhoseTurn], a - lb de, 2, 66 - call InitTextPrinting - ld hl, wDefaultText - call ProcessText - ldtx hl, AllCardsOwnedText - call ProcessTextFromID - ld a, [wPrintOnlyStarRarity] - or a - jr z, .asm_1a2c2 - ld a, TX_HALF2FULL - call ProcessSpecialTextCharacter - lb de, 3, 84 - call Func_22ca -.asm_1a2c2 - ld a, $ff - ld [wCurPrinterCardType], a - xor a - ld hl, wPrinterTotalCardCount - ld [hli], a - ld [hl], a - ld [wPrinterNumCardTypes], a - ld a, 5 - ld [wPrinterHorizontalOffset], a - - ld e, GRASS_ENERGY -.loop_cards - push de - ld d, $00 - call LoadCardDataToBuffer1_FromCardID - jr c, .done_card_loop - ld d, HIGH(wTempCardCollection) - ld a, [de] ; card ID count in collection - ld [wPrinterCardCount], a - call .LoadCardTypeEntry - jr c, .printer_error_pop_de - - ld a, [wPrintOnlyStarRarity] - or a - jr z, .all_owned_cards_mode - ld a, [wLoadedCard1Set] - and %11110000 - cp PROMOTIONAL - jr z, .next_card - ld a, [wLoadedCard1Rarity] - cp STAR - jr nz, .next_card - ; not Promotional, and Star rarity - ld hl, wPrinterCardCount - res CARD_NOT_OWNED_F, [hl] - jr .got_card_count - -.all_owned_cards_mode - ld a, [wPrinterCardCount] - or a - jr z, .next_card - cp CARD_NOT_OWNED - jr z, .next_card ; ignore not owned cards - -.got_card_count - ld a, [wPrinterCardCount] - and CARD_COUNT_MASK - ld c, a - - ; add to total card count - ld hl, wPrinterTotalCardCount - add [hl] - ld [hli], a - ld a, 0 - adc [hl] - ld [hl], a - - ; add to current card type count - ld hl, wPrinterCurCardTypeCount - ld a, c - add [hl] - ld [hli], a - ld a, 0 - adc [hl] - ld [hl], a - - ld hl, wPrinterNumCardTypes - inc [hl] - ld hl, wce98 - inc [hl] - call LoadCardInfoForPrinter - call AddToPrinterGfxBuffer - jr c, .printer_error_pop_de -.next_card - pop de - inc e - jr .loop_cards - -.printer_error_pop_de - pop de -.printer_error - call ResetPrinterCommunicationSettings - call RestoreVBlankFunction - jp HandlePrinterError - -.done_card_loop - pop de - ; add separator line - ld a, [wPrinterHorizontalOffset] - dec a - or $40 - ld c, a - ld b, 0 - call BCCoordToBGMap0Address - ld a, $35 - lb de, $35, $35 - ld b, 20 - call CopyLine - call AddToPrinterGfxBuffer - jr c, .printer_error - - ld hl, wPrinterTotalCardCount - ld c, [hl] - inc hl - ld b, [hl] - ldtx hl, TotalNumberOfCardsText - call .PrintTextWithNumber - jr c, .printer_error - ld a, [wPrintOnlyStarRarity] - or a - jr nz, .done - ld a, [wPrinterNumCardTypes] - ld c, a - ld b, 0 - ldtx hl, TypesOfCardsText - call .PrintTextWithNumber - jr c, .printer_error - -.done - call SendCardListToPrinter - jr c, .printer_error - call ResetPrinterCommunicationSettings - call RestoreVBlankFunction - or a - ret - -; prints text ID given in hl -; with decimal representation of -; the number given in bc -; hl = text ID -; bc = number -.PrintTextWithNumber - push bc - ld a, [wPrinterHorizontalOffset] - dec a - or $40 - ld e, a - ld d, 2 - call InitTextPrinting - call ProcessTextFromID - ld d, 14 - call InitTextPrinting - pop hl - call TwoByteNumberToTxSymbol_TrimLeadingZeros - ld hl, wStringBuffer - call ProcessText - call AddToPrinterGfxBuffer - ret - -; loads this card's type icon and text -; if it's a new card type that hasn't been printed yet -.LoadCardTypeEntry - ld a, [wLoadedCard1Type] - ld c, a - cp TYPE_ENERGY - jr c, .got_type ; jump if Pokemon card - ld c, $08 - cp TYPE_TRAINER - jr nc, .got_type ; jump if Trainer card - ld c, $07 -.got_type - ld hl, wCurPrinterCardType - ld a, [hl] - cp c - ret z ; already handled this card type - - ; show corresponding icon and text - ; for this new card type - ld a, c - ld [hl], a ; set it as current card type - add a - add c ; *3 - ld c, a - ld b, $00 - ld hl, .IconTextList - add hl, bc - ld a, [wPrinterHorizontalOffset] - dec a - or %1000000 - ld e, a - ld d, 1 - ld a, [hli] - push hl - lb bc, 2, 2 - lb hl, 1, 2 - call FillRectangle - pop hl - ld d, 3 - inc e - call InitTextPrinting - ld a, [hli] - ld h, [hl] - ld l, a - call ProcessTextFromID - - call AddToPrinterGfxBuffer - ld hl, wPrinterCurCardTypeCount - xor a - ld [hli], a - ld [hl], a - ld [wce98], a - ret - -.IconTextList - ; Fire - db $e0 ; icon tile - tx FirePokemonText - - ; Grass - db $e4 ; icon tile - tx GrassPokemonText - - ; Lightning - db $e8 ; icon tile - tx LightningPokemonText - - ; Water - db $ec ; icon tile - tx WaterPokemonText - - ; Fighting - db $f0 ; icon tile - tx FightingPokemonText - - ; Psychic - db $f4 ; icon tile - tx PsychicPokemonText - - ; Colorless - db $f8 ; icon tile - tx ColorlessPokemonText - - ; Energy - db $fc ; icon tile - tx EnergyCardText - - ; Trainer - db $dc ; icon tile - tx TrainerCardText - -ShowPrinterTransmitting: ; 1a420 (6:6420) - call Func_198e7 - ld a, SCENE_GAMEBOY_PRINTER_TRANSMITTING - lb bc, 0, 0 - call LoadScene - ldtx hl, NowPrintingPleaseWaitText - call DrawWideTextBox_PrintText - call EnableLCD - ret - -; compresses $28 tiles in sGfxBuffer5 -; and writes it in sGfxBuffer5 + $28 tiles. -; compressed data has 2 commands to instruct on how to decompress it. -; - a command byte with bit 7 not set, means to copy that many + 1 -; bytes that are following it literally. -; - a command byte with bit 7 set, means to copy the following byte -; that many times + 2 (after masking the top bit of command byte). -; returns in bc the size of the compressed data and -; in de the packet type data. -CompressDataForPrinterSerialTransfer: ; 1a435 (6:6435) - ld hl, sGfxBuffer5 - ld de, sGfxBuffer5 + $28 tiles - ld bc, $28 tiles -.loop_remaining_data - ld a, $ff - inc b - dec b - jr nz, .check_compression - ld a, c -.check_compression - push bc - push de - ld c, a - call CheckDataCompression - ld a, e - ld c, e - pop de - jr c, .copy_byte - ld a, c - ld b, c - dec a - ld [de], a ; number of bytes to copy literally - 1 - inc de -.copy_literal_sequence - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .copy_literal_sequence - ld c, b - jr .sub_added_bytes - -.copy_byte - ld a, c - dec a - dec a - or %10000000 ; set high bit - ld [de], a ; = (n times to copy - 2) | %10000000 - inc de - ld a, [hl] ; byte to copy n times - ld [de], a - inc de - ld b, $0 - add hl, bc - -.sub_added_bytes - ld a, c - cpl - inc a - pop bc - add c - ld c, a - ld a, $ff - adc b - ld b, a - or c - jr nz, .loop_remaining_data - - ld hl, $10000 - (sGfxBuffer5 + $28 tiles) - add hl, de ; gets the size of the compressed data - ld c, l - ld b, h - ld hl, sGfxBuffer5 + $28 tiles - lb de, PRINTERPKT_DATA, $1 - ret - -; checks whether the next byte sequence in hl, up to c bytes, can be compressed -; returns carry if the next sequence of bytes can be compressed, -; i.e. has at least 3 consecutive bytes with the same value. -; in that case, returns in e the number of consecutive -; same value bytes that were found. -; if there are no bytes with same value, then count as many bytes left -; as possible until either there are no more remaining data bytes, -; or until a sequence of 3 bytes with the same value are found. -; in that case, the number of bytes in this sequence is returned in e. -CheckDataCompression: ; 1a485 (6:6485) - push hl - ld e, c - ld a, c -; if number of remaining bytes is less than 4 -; then no point in compressing - cp 4 - jr c, .no_carry - -; check first if there are at least -; 3 consecutive bytes with the same value - ld b, c - ld a, [hli] - cp [hl] - inc hl - jr nz, .literal_copy ; not same - cp [hl] - inc hl - jr nz, .literal_copy ; not same - -; 3 consecutive bytes were found with same value -; keep track of how many consecutive bytes -; with the same value there are in e - dec c - dec c - dec c - ld e, 3 -.loop_same_value - cp [hl] - jr nz, .set_carry ; exit when a different byte is found - inc hl - inc e - dec c - jr z, .set_carry ; exit when there is no more remaining data - bit 5, e - ; exit if number of consecutive bytes >= $20 - jr z, .loop_same_value -.set_carry - pop hl - scf - ret - -.literal_copy -; consecutive bytes are not the same value -; count the number of bytes there are left -; until a sequence of 3 bytes with the same value is found - pop hl - push hl - ld c, b ; number of remaining bytes - ld e, 1 - ld a, [hli] - dec c - jr z, .no_carry ; exit if no more data -.reset_same_value_count - ld d, 2 ; number of consecutive same value bytes to exit -.next_byte - inc e - dec c - jr z, .no_carry - bit 7, e - jr nz, .no_carry ; exit if >= $80 - cp [hl] - jr z, .same_consecutive_value - ld a, [hli] - jr .reset_same_value_count -.no_carry - pop hl - or a - ret - -.same_consecutive_value - inc hl - dec d - jr nz, .next_byte - ; 3 consecutive bytes with same value found - ; discard the last 3 bytes in the sequence - dec e - dec e - dec e - jr .no_carry - -; sets up to start a link duel -; decides which device will pick the number of prizes -; then exchanges names and duels between the players -; and starts the main duel routine -_SetUpAndStartLinkDuel: ; 1a4cf (6:64cf) - ld hl, sp+$00 - ld a, l - ld [wDuelReturnAddress + 0], a - ld a, h - ld [wDuelReturnAddress + 1], a - call Func_198e7 - - ld a, SCENE_GAMEBOY_LINK_TRANSMITTING - lb bc, 0, 0 - call LoadScene - - bank1call LoadPlayerDeck - call SwitchToCGBNormalSpeed - bank1call DecideLinkDuelVariables - push af - call RestoreVBlankFunction - pop af - jp c, .error - - ld a, DUELIST_TYPE_PLAYER - ld [wPlayerDuelistType], a - ld a, DUELIST_TYPE_LINK_OPP - ld [wOpponentDuelistType], a - ld a, DUELTYPE_LINK - ld [wDuelType], a - - call EmptyScreen - ld a, [wSerialOp] - cp $29 - jr nz, .asm_1a540 - - ld a, PLAYER_TURN - ldh [hWhoseTurn], a - call .ExchangeNamesAndDecks - jr c, .error - lb de, 6, 2 - lb bc, 8, 6 - call DrawRegularTextBox - lb de, 7, 4 - call InitTextPrinting - ldtx hl, PrizesCardsText - call ProcessTextFromID - ldtx hl, ChooseTheNumberOfPrizesText - call DrawWideTextBox_PrintText - call EnableLCD - call .PickNumberOfPrizeCards - ld a, [wNPCDuelPrizes] - call SerialSend8Bytes - jr .prizes_decided - -.asm_1a540 - ld a, OPPONENT_TURN - ldh [hWhoseTurn], a - call .ExchangeNamesAndDecks - jr c, .error - ldtx hl, PleaseWaitDecidingNumberOfPrizesText - call DrawWideTextBox_PrintText - call EnableLCD - call SerialRecv8Bytes - ld [wNPCDuelPrizes], a - -.prizes_decided - call ExchangeRNG - ld a, LINK_OPP_PIC - ld [wOpponentPortrait], a - ldh a, [hWhoseTurn] - push af - call EmptyScreen - bank1call SetDefaultPalettes - ld a, SHUFFLE_DECK - ld [wDuelDisplayedScreen], a - bank1call DrawDuelistPortraitsAndNames - ld a, OPPONENT_TURN - ldh [hWhoseTurn], a - ld a, [wNPCDuelPrizes] - ld l, a - ld h, $00 - call LoadTxRam3 - ldtx hl, BeginAPrizeDuelWithText - call DrawWideTextBox_WaitForInput - pop af - ldh [hWhoseTurn], a - call ExchangeRNG - bank1call StartDuel_VSLinkOpp - call SwitchToCGBDoubleSpeed - ret - -.error - ld a, -1 - ld [wDuelResult], a - call Func_198e7 - - ld a, SCENE_GAMEBOY_LINK_NOT_CONNECTED - lb bc, 0, 0 - call LoadScene - - ldtx hl, TransmissionErrorText - call DrawWideTextBox_WaitForInput - call RestoreVBlankFunction - call ResetSerial - ret - -.ExchangeNamesAndDecks - ld de, wDefaultText - push de - call CopyPlayerName - pop hl - ld de, wNameBuffer - ld c, NAME_BUFFER_LENGTH - call SerialExchangeBytes - ret c - xor a - ld hl, wOpponentName - ld [hli], a - ld [hl], a - ld hl, wPlayerDeck - ld de, wOpponentDeck - ld c, DECK_SIZE - call SerialExchangeBytes - ret - -; handles player choice of number of prize cards -; pressing left/right makes it decrease/increase respectively -; selection is confirmed by pressing A button -.PickNumberOfPrizeCards - ld a, PRIZES_4 - ld [wNPCDuelPrizes], a - xor a - ld [wPrizeCardSelectionFrameCounter], a -.loop_input - call DoFrame - ld a, [wNPCDuelPrizes] - add SYM_0 - ld e, a - ; check frame counter so that it - ; either blinks or shows number - ld hl, wPrizeCardSelectionFrameCounter - ld a, [hl] - inc [hl] - and $10 - jr z, .no_blink - ld e, SYM_SPACE -.no_blink - ld a, e - lb bc, 9, 6 - call WriteByteToBGMap0 - - ldh a, [hDPadHeld] - ld b, a - ld a, [wNPCDuelPrizes] - bit D_LEFT_F, b - jr z, .check_d_right - dec a - cp PRIZES_2 - jr nc, .got_prize_count - ld a, PRIZES_6 ; wrap around to 6 - jr .got_prize_count - -.check_d_right - bit D_RIGHT_F, b - jr z, .check_a_btn - inc a - cp PRIZES_6 + 1 - jr c, .got_prize_count - ld a, PRIZES_2 -.got_prize_count - ld [wNPCDuelPrizes], a - xor a - ld [wPrizeCardSelectionFrameCounter], a - -.check_a_btn - bit A_BUTTON_F, b - jr z, .loop_input - ret - -Func_1a61f: ; 1a61f (6:661f) - push af - lb de, $38, $9f - call SetupText - pop af - or a - jr nz, .else - ld a, MOLTRES2 - call .legendary_card_text - ld a, ARTICUNO2 - call .legendary_card_text - ld a, ZAPDOS3 - call .legendary_card_text - ld a, DRAGONITE1 -.legendary_card_text - ldtx hl, ReceivedLegendaryCardText - jr .print_text -.else - ldtx hl, ReceivedCardText - cp VILEPLUME - jr z, .print_text - cp BLASTOISE - jr z, .print_text - ldtx hl, ReceivedPromotionalFlyingPikachuText - cp FLYING_PIKACHU - jr z, .print_text - ldtx hl, ReceivedPromotionalSurfingPikachuText - cp SURFING_PIKACHU1 - jr z, .print_text - cp SURFING_PIKACHU2 - jr z, .print_text - ldtx hl, ReceivedPromotionalCardText -.print_text - push hl - ld e, a - ld d, $0 - call LoadCardDataToBuffer1_FromCardID - call PauseSong - ld a, MUSIC_MEDAL - call PlaySong - ld hl, wLoadedCard1Name - ld a, [hli] - ld h, [hl] - ld l, a - bank1call LoadTxRam2 ; switch to bank 1, but call a home func - ld a, PLAYER_TURN - ldh [hWhoseTurn], a - pop hl - bank1call _DisplayCardDetailScreen -.loop - call AssertSongFinished - or a - jr nz, .loop - - call ResumeSong - bank1call OpenCardPage_FromHand - ret - -_OpenBoosterPack: ; 1a68d (6:668d) - ld a, PLAYER_TURN - ldh [hWhoseTurn], a - ld h, a - ld l, $00 -.asm_6694 - xor a - ld [hli], a - ld a, l - cp $3c - jr c, .asm_6694 - xor a - ld hl, wBoosterCardsDrawn - ld de, wDuelTempList - ld c, $00 -.asm_66a4 - ld a, [hli] - or a - jr z, .asm_66ae - ld a, c - ld [de], a - inc de - inc c - jr .asm_66a4 -.asm_66ae - ld a, $ff - 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 - -CommentedOut_1a6cc: ; 1a6cc (6:66cc) - ret - -Func_1a6cd: ; 1a6cd (6:66cd) - ldh a, [hBankSRAM] - or a - ret nz - push hl - push de - push bc - ld hl, sCardCollection - ld bc, $0250 - ld a, [s0a000 + $b] - ld e, a -.asm_66de - ld a, [hli] - xor e - ld e, a - dec bc - ld a, c - or b - jr nz, .asm_66de - ld a, e - pop bc - pop de - pop hl - or a - ret z - xor a - ld [wTileMapFill], a - ld hl, wDoFrameFunction - ld [hli], a - ld [hl], a - ldh [hSCX], a - ldh [hSCY], a - bank1call ZeroObjectPositionsAndToggleOAMCopy - call EmptyScreen - call LoadSymbolsFont - bank1call SetDefaultPalettes - ld a, [wConsole] - cp $01 - jr nz, .asm_6719 - ld a, $e4 - ld [wOBP0], a - ld [wBGP], a - ld a, $01 - ld [wFlushPaletteFlags], a -.asm_6719 - lb de, $38, $9f - call SetupText - ld hl, $00a3 - bank1call DrawWholeScreenTextBox - ld a, $0a - ld [MBC3SRamEnable], a - xor a - ldh [hBankSRAM], a - ld [MBC3SRamBank], a - ld [MBC3RTC], a - ld [MBC3SRamEnable], a - jp Reset - ret - -Func_1a73a: ; 1a73a (6:673a) - ldh a, [hBankSRAM] - or a - ret nz - push hl - push de - push bc - ld hl, sCardCollection - ld bc, $0250 - ld e, $00 -.asm_6749 - ld a, [hli] - xor e - ld e, a - dec bc - ld a, c - or b - jr nz, .asm_6749 - ld a, $0a - ld [MBC3SRamEnable], a - ld a, e - ld [s0a00b], a - pop bc - pop de - pop hl - ret - -WhatIsYourNameData: ; 1a75e (6:675e) - textitem 1, 1, WhatIsYourNameText - db $ff -; [Deck1Data ~ Deck4Data] -; These are directed from around (2:4f05), -; without any bank description. -; That is, the developers hard-coded it. -_-;; -Deck1Data: ; 1a763 (6:6763) - textitem 2, 1, Deck1Text - textitem 14, 1, DeckText - db $ff -Deck2Data: ; 1a76c (6:676c) - textitem 2, 1, Deck2Text - textitem 14, 1, DeckText - db $ff -Deck3Data: ; 1a775 (6:6775) - textitem 2, 1, Deck3Text - textitem 14, 1, DeckText - db $ff -Deck4Data: ; 1a77e (6:677e) - textitem 2, 1, Deck4Text - textitem 14, 1, DeckText - db $ff - -; set each byte zero from hl for b bytes. -ClearMemory: ; 1a787 (6:6787) - 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 - -; play different sfx by a. -; if a is 0xff play SFX_03 (usually following a B press), -; else play SFX_02 (usually following an A press). -PlayAcceptOrDeclineSFX: ; 1a794 (6:6794) - push af - inc a - jr z, .sfx_decline - ld a, SFX_02 - jr .sfx_accept -.sfx_decline - ld a, SFX_03 -.sfx_accept - call PlaySFX - pop af - ret - -; get player name from the user -; into hl -InputPlayerName: ; 1a7a3 (6:67a3) - ld e, l - ld d, h - ld a, MAX_PLAYER_NAME_LENGTH - ld hl, WhatIsYourNameData - lb bc, 12, 1 - call InitializeInputName - call Set_OBJ_8x8 - xor a - ld [wTileMapFill], a - call EmptyScreen - call ZeroObjectPositions - ld a, $01 - ld [wVBlankOAMCopyToggle], a - call LoadSymbolsFont - lb de, $38, $bf - call SetupText - call LoadTextCursorTile - ld a, $02 - ld [wd009], a - call DrawNamingScreenBG - xor a - ld [wNamingScreenCursorX], a - ld [wNamingScreenCursorY], a - ld a, $09 - ld [wNamingScreenNumColumns], a - ld a, $06 - ld [wNamingScreenKeyboardHeight], a - ld a, $0f - ld [wVisibleCursorTile], a - ld a, $00 - ld [wInvisibleCursorTile], a -.loop - ld a, $01 - ld [wVBlankOAMCopyToggle], a - call DoFrame - call UpdateRNGSources - ldh a, [hDPadHeld] - and START - jr z, .else - ; if pressed start button. - ld a, $01 - call PlayAcceptOrDeclineSFX - call Func_1aa07 - ld a, 6 - ld [wNamingScreenCursorX], a - ld a, 5 - ld [wNamingScreenCursorY], a - call Func_1aa23 - jr .loop -.else - call NamingScreen_CheckButtonState - jr nc, .loop ; if not pressed, go back to the loop. - cp $ff - jr z, .on_b_button - ; on A button. - call NamingScreen_ProcessInput - jr nc, .loop - ; if the player selected the end button, - ; end its naming. - call FinalizeInputName - ret -.on_b_button - ld a, [wNamingScreenBufferLength] - or a - jr z, .loop ; empty string? - ; erase one character. - ld e, a - ld d, 0 - ld hl, wNamingScreenBuffer - add hl, de - dec hl - dec hl - ld [hl], TX_END - ld hl, wNamingScreenBufferLength ; note that its unit is byte, not word. - dec [hl] - dec [hl] - call PrintPlayerNameFromInput - jr .loop - -; it's called when naming(either player's or deck's) starts. -; a: maximum length of name(depending on whether player's or deck's). -; bc: position of name. -; de: dest. pointer. -; hl: pointer to text item of the question. -InitializeInputName: ; 1a846 (6:6846) - ld [wNamingScreenBufferMaxLength], a - push hl - ld hl, wNamingScreenNamePosition - ld [hl], b - inc hl - ld [hl], c - pop hl - ld b, h - ld c, l - ; set the question string. - ld hl, wNamingScreenQuestionPointer - ld [hl], c - inc hl - ld [hl], b - ; set the destination buffer. - ld hl, wNamingScreenDestPointer - ld [hl], e - inc hl - ld [hl], d - ; clear the name buffer. - ld a, NAMING_SCREEN_BUFFER_LENGTH - ld hl, wNamingScreenBuffer - call ClearMemory - ld hl, wNamingScreenBuffer - ld a, [wNamingScreenBufferMaxLength] - ld b, a - inc b -.loop - ; copy data from de to hl - ; for b bytes. - ld a, [de] - inc de - ld [hli], a - dec b - jr nz, .loop - ld hl, wNamingScreenBuffer - call GetTextLengthInTiles - ld a, c - ld [wNamingScreenBufferLength], a - ret - -FinalizeInputName: ; 1a880 (6:6880) - ld hl, wNamingScreenDestPointer - ld e, [hl] - inc hl - ld d, [hl] - ld l, e - ld h, d - ld de, wNamingScreenBuffer - ld a, [wNamingScreenBufferMaxLength] - ld b, a - inc b - jr InitializeInputName.loop - -; draws the keyboard frame -; and the question if it exists. -DrawNamingScreenBG: ; 1a892 (6:6892) - call DrawTextboxForKeyboard - call PrintPlayerNameFromInput - ld hl, wNamingScreenQuestionPointer - ld c, [hl] - inc hl - ld a, [hl] - ld h, a - or c - jr z, .put_text_end - ; print the question string. - ; ex) "What is your name?" - ld l, c - call PlaceTextItems -.put_text_end - ; print "End". - ld hl, .data - call PlaceTextItems - ldtx hl, PlayerNameKeyboardText - lb de, 2, 4 - call InitTextPrinting - call ProcessTextFromID - call EnableLCD - ret -.data - textitem $0f, $10, EndText ; "End" - db $ff - -DrawTextboxForKeyboard: ; 1a8c1 (6:68c1) - lb de, 0, 3 ; x, y - lb bc, 20, 15 ; w, h - call DrawRegularTextBox - ret - -PrintPlayerNameFromInput: ; 1a8cb (6:68cb) - ld hl, wNamingScreenNamePosition - ld d, [hl] - inc hl - ld e, [hl] - push de - call InitTextPrinting - ld a, [wNamingScreenBufferMaxLength] - ld e, a - ld a, $14 - sub e - inc a - ld e, a - ld d, 0 - ; print the underbars - ; before print the input. - ld hl, .char_underbar - add hl, de - call ProcessText - pop de - call InitTextPrinting - ; print the input from the user. - ld hl, wNamingScreenBuffer - call ProcessText - ret -.char_underbar - db $56 -rept 10 - textfw3 "_" -endr - done - -; check if button pressed. -; if pressed, set the carry bit on. -NamingScreen_CheckButtonState: ; 1a908 (6:6908) - xor a - ld [wPlaysSfx], a - ldh a, [hDPadHeld] - or a - jp z, .no_press - ; detected any button press. - ld b, a - ld a, [wNamingScreenKeyboardHeight] - ld c, a - ld a, [wNamingScreenCursorX] - ld h, a - ld a, [wNamingScreenCursorY] - ld l, a - bit D_UP_F, b - jr z, .asm_692c - ; up - dec a - bit D_DOWN_F, a - jr z, .asm_69a7 - ld a, c - dec a - jr .asm_69a7 -.asm_692c - bit D_DOWN_F, b - jr z, .asm_6937 - ; down - inc a - cp c - jr c, .asm_69a7 - xor a - jr .asm_69a7 -.asm_6937 - ld a, [wNamingScreenNumColumns] - ld c, a - ld a, h - bit D_LEFT_F, b - jr z, .asm_6974 - ; left - ld d, a - ld a, $06 - cp l - ld a, d - jr nz, .asm_696b - push hl - push bc - push af - call GetCharInfoFromPos_Player - inc hl - inc hl - inc hl - inc hl - inc hl - ld a, [hl] - dec a - ld d, a - pop af - pop bc - pop hl - sub d - cp $ff - jr nz, .asm_6962 - ld a, c - sub $02 - jr .asm_69aa -.asm_6962 - cp $fe - jr nz, .asm_696b - ld a, c - sub $03 - jr .asm_69aa -.asm_696b - dec a - bit D_DOWN_F, a - jr z, .asm_69aa - ld a, c - dec a - jr .asm_69aa -.asm_6974 - bit D_RIGHT_F, b - jr z, .no_press - ld d, a - ld a, $06 - cp l - ld a, d - jr nz, .asm_6990 - push hl - push bc - push af - call GetCharInfoFromPos_Player - inc hl - inc hl - inc hl - inc hl - ld a, [hl] - dec a - ld d, a - pop af - pop bc - pop hl - add d -.asm_6990 - inc a - cp c - jr c, .asm_69aa - inc c - cp c - jr c, .asm_69a4 - inc c - cp c - jr c, .asm_69a0 - ld a, $02 - jr .asm_69aa -.asm_69a0 - ld a, $01 - jr .asm_69aa -.asm_69a4 - xor a - jr .asm_69aa -.asm_69a7 - ld l, a - jr .asm_69ab -.asm_69aa - ld h, a -.asm_69ab - push hl - call GetCharInfoFromPos_Player - inc hl - inc hl - inc hl - ld a, [wd009] - cp $02 - jr nz, .asm_69bb - inc hl - inc hl -.asm_69bb - ld d, [hl] - push de - call Func_1aa07 - pop de - pop hl - ld a, l - ld [wNamingScreenCursorY], a - ld a, h - ld [wNamingScreenCursorX], a - xor a - ld [wCheckMenuCursorBlinkCounter], a - ld a, $06 - cp d - jp z, NamingScreen_CheckButtonState - ld a, $01 - ld [wPlaysSfx], a -.no_press - ldh a, [hKeysPressed] - and A_BUTTON | B_BUTTON - jr z, .asm_69ef - and A_BUTTON - jr nz, .asm_69e5 - ld a, $ff -.asm_69e5 - call PlayAcceptOrDeclineSFX - push af - call Func_1aa23 - pop af - scf - ret -.asm_69ef - ld a, [wPlaysSfx] - or a - jr z, .asm_69f8 - call PlaySFX -.asm_69f8 - ld hl, wCheckMenuCursorBlinkCounter - ld a, [hl] - inc [hl] - and $0f - ret nz - ld a, [wVisibleCursorTile] - bit 4, [hl] - jr z, Func_1aa07.asm_6a0a - -Func_1aa07: ; 1aa07 (6:6a07) - ld a, [wInvisibleCursorTile] -.asm_6a0a - ld e, a - ld a, [wNamingScreenCursorX] - ld h, a - ld a, [wNamingScreenCursorY] - ld l, a - call GetCharInfoFromPos_Player - ld a, [hli] - ld c, a - ld b, [hl] - dec b - ld a, e - call Func_1aa28 - call WriteByteToBGMap0 - or a - ret - -Func_1aa23: ; 1aa23 (6:6a23) - ld a, [wVisibleCursorTile] - jr Func_1aa07.asm_6a0a - -Func_1aa28: ; 1aa28 (6:6a28) - push af - push bc - push de - push hl - push af - call ZeroObjectPositions - pop af - ld b, a - ld a, [wInvisibleCursorTile] - cp b - jr z, .asm_6a60 - ld a, [wNamingScreenBufferLength] - srl a - ld d, a - ld a, [wNamingScreenBufferMaxLength] - srl a - ld e, a - ld a, d - cp e - jr nz, .asm_6a49 - dec a -.asm_6a49 - ld hl, wNamingScreenNamePosition - add [hl] - ld d, a - ld h, $08 - ld l, d - call HtimesL - ld a, l - add $08 - ld d, a - ld e, $18 - ld bc, $0000 - call SetOneObjectAttributes -.asm_6a60 - pop hl - pop de - pop bc - pop af - ret - -; load, to the first tile of v0Tiles0, the graphics for the -; blinking black square used in name input screens. -; for inputting full width text. -LoadTextCursorTile: ; 1aa65 (6:6a65) - ld hl, v0Tiles0 + $00 tiles - ld de, .data - ld b, 0 -.loop - ld a, TILE_SIZE - cp b - ret z - inc b - ld a, [de] - inc de - ld [hli], a - jr .loop - -.data -rept TILE_SIZE - db $ff -endr - -; set the carry bit on, -; if "End" was selected. -NamingScreen_ProcessInput: ; 1aa87 (6:6a87) - ld a, [wNamingScreenCursorX] - ld h, a - ld a, [wNamingScreenCursorY] - ld l, a - call GetCharInfoFromPos_Player - inc hl - inc hl - ; load types into de. - ld e, [hl] - inc hl - ld a, [hli] - ld d, a - cp $09 - jp z, .on_end - cp $07 - jr nz, .asm_6ab8 - ld a, [wd009] - or a - jr nz, .asm_6aac - ld a, $01 - jp .asm_6ace -.asm_6aac - dec a - jr nz, .asm_6ab4 - ld a, $02 - jp .asm_6ace -.asm_6ab4 - xor a - jp .asm_6ace -.asm_6ab8 - cp $08 - jr nz, .asm_6ad6 - ld a, [wd009] - or a - jr nz, .asm_6ac6 - ld a, $02 - jr .asm_6ace -.asm_6ac6 - dec a - jr nz, .asm_6acc - xor a - jr .asm_6ace -.asm_6acc - ld a, $01 -.asm_6ace - ld [wd009], a - call DrawNamingScreenBG - or a - ret -.asm_6ad6 - ld a, [wd009] - cp $02 - jr z, .read_char - ldfw3 bc, "“" - ld a, d - cp b - jr nz, .asm_6af4 - ld a, e - cp c - jr nz, .asm_6af4 - push hl - ld hl, TransitionTable1 ; from 55th. - call TransformCharacter - pop hl - jr c, .nothing - jr .asm_6b09 -.asm_6af4 - ldfw3 bc, "º(2)" - ld a, d - cp b - jr nz, .asm_6b1d - ld a, e - cp c - jr nz, .asm_6b1d - push hl - ld hl, TransitionTable2 ; from 72th. - call TransformCharacter - pop hl - jr c, .nothing -.asm_6b09 - ld a, [wNamingScreenBufferLength] - dec a - dec a - ld [wNamingScreenBufferLength], a - ld hl, wNamingScreenBuffer - push de - ld d, 0 - ld e, a - add hl, de - pop de - ld a, [hl] - jr .asm_6b37 -.asm_6b1d - ld a, d - or a - jr nz, .asm_6b37 - ld a, [wd009] - or a - jr nz, .asm_6b2b - ld a, TX_HIRAGANA - jr .asm_6b37 -.asm_6b2b - ld a, TX_KATAKANA - jr .asm_6b37 -; read character code from info. to register. -; hl: pointer. -.read_char - ld e, [hl] - inc hl - ld a, [hl] ; a: first byte of the code. - or a - ; if 2 bytes code, jump. - jr nz, .asm_6b37 - ; if 1 byte code(ascii), - ; set first byte to $0e. - ld a, $0e -; on 2 bytes code. -.asm_6b37 - ld d, a ; de: character code. - ld hl, wNamingScreenBufferLength - ld a, [hl] - ld c, a - push hl - ld hl, wNamingScreenBufferMaxLength - cp [hl] - pop hl - jr nz, .asm_6b4c - ; if the buffer is full - ; just change the last character of it. - ld hl, wNamingScreenBuffer - dec hl - dec hl - jr .asm_6b51 -; increase name length before add the character. -.asm_6b4c - inc [hl] - inc [hl] - ld hl, wNamingScreenBuffer -; write 2 bytes character codes to the name buffer. -; de: 2 bytes character codes. -; hl: dest. -.asm_6b51 - ld b, 0 - add hl, bc - ld [hl], d - inc hl - ld [hl], e - inc hl - ld [hl], TX_END ; null terminator. - call PrintPlayerNameFromInput -.nothing - or a - ret -.on_end - scf - ret - -; this transforms the last japanese character -; in the name buffer into its dakuon shape or something. -; it seems to have been deprecated as the game was translated into english. -; but it can still be applied to english, such as upper-lower case transition. -; hl: info. pointer. -TransformCharacter: ; 1ab61 (6:6b61) - ld a, [wNamingScreenBufferLength] - or a - jr z, .return ; if the length is zero, just return. - dec a - dec a - push hl - ld hl, wNamingScreenBuffer - ld d, 0 - ld e, a - add hl, de - ld e, [hl] - inc hl - ld d, [hl] - ; de: last character in the buffer, - ; but byte-wise swapped. - ld a, TX_KATAKANA - cp e - jr nz, .hiragana - ; if it's katakana, - ; make it hiragana by decreasing its high byte. - dec e -.hiragana - pop hl -.loop - ld a, [hli] - or a - jr z, .return - cp d - jr nz, .next - ld a, [hl] - cp e - jr nz, .next - inc hl - ld e, [hl] - inc hl - ld d, [hl] - or a - ret -.next - inc hl - inc hl - inc hl - jr .loop -.return - scf - ret - -; given the position of the current cursor, -; it returns the pointer to the proper information. -; h: position x. -; l: position y. -GetCharInfoFromPos_Player: ; 1ab93 (6:6b93) - push de - ; (information index) = (x) * (height) + (y) - ; (height) = 0x05(Deck) or 0x06(Player) - ld e, l - ld d, h - ld a, [wNamingScreenKeyboardHeight] - ld l, a - call HtimesL - ld a, l - add e - ld hl, KeyboardData_Player - pop de - or a - ret z -.loop - inc hl - inc hl - inc hl - inc hl - inc hl - inc hl - dec a - jr nz, .loop - ret - -; a set of keyboard datum. -; unit: 6 bytes. -; structure: -; abs. y pos. (1) / abs. x pos. (1) / type 1 (1) / type 2 (1) / char. code (2) -; unused data contains its character code as zero. -kbitem: MACRO - db \1, \2, \3, \4 -if (_NARG == 5) - dw \5 -elif (\5 == TX_FULLWIDTH3) - dw (\5 << 8) | STRCAT("FW3_", \6) -else - dw (\5 << 8) | \6 -endc -ENDM - -KeyboardData_Player: ; 1abaf (6:6baf) - kbitem $04, $02, $11, $00, TX_FULLWIDTH3, "A" - kbitem $06, $02, $12, $00, TX_FULLWIDTH3, "J" - kbitem $08, $02, $13, $00, TX_FULLWIDTH3, "S" - kbitem $0a, $02, $14, $00, "o" - kbitem $0c, $02, $15, $00, "d" - kbitem $10, $0f, $01, $09, $0000 - - kbitem $04, $04, $16, $00, TX_FULLWIDTH3, "B" - kbitem $06, $04, $17, $00, TX_FULLWIDTH3, "K" - kbitem $08, $04, $18, $00, TX_FULLWIDTH3, "T" - kbitem $0a, $04, $19, $00, TX_FULLWIDTH3, "&" - kbitem $0c, $04, $1a, $00, "e" - kbitem $10, $0f, $01, $09, $0000 - - kbitem $04, $06, $1b, $00, TX_FULLWIDTH3, "C" - kbitem $06, $06, $1c, $00, TX_FULLWIDTH3, "L" - kbitem $08, $06, $1d, $00, TX_FULLWIDTH3, "U" - kbitem $0a, $06, $1e, $00, "j" - kbitem $0c, $06, $1f, $00, "f" - kbitem $10, $0f, $01, $09, $0000 - - kbitem $04, $08, $20, $00, TX_FULLWIDTH3, "D" - kbitem $06, $08, $21, $00, TX_FULLWIDTH3, "M" - kbitem $08, $08, $22, $00, TX_FULLWIDTH3, "V" - kbitem $0a, $08, $23, $00, "k" - kbitem $0c, $08, $24, $00, "g" - kbitem $10, $0f, $01, $09, $0000 - - kbitem $04, $0a, $25, $00, TX_FULLWIDTH3, "E" - kbitem $06, $0a, $26, $00, TX_FULLWIDTH3, "N" - kbitem $08, $0a, $27, $00, TX_FULLWIDTH3, "W" - kbitem $0a, $0a, $28, $00, "w" - kbitem $0c, $0a, $29, $00, "h" - kbitem $10, $0f, $01, $09, $0000 - - kbitem $04, $0c, $2a, $00, TX_FULLWIDTH3, "F" - kbitem $06, $0c, $2b, $00, TX_FULLWIDTH3, "O" - kbitem $08, $0c, $2c, $00, TX_FULLWIDTH3, "X" - kbitem $0a, $0c, $2d, $00, "`" - kbitem $0c, $0c, $2e, $00, "i" - kbitem $10, $0f, $01, $09, $0000 - - kbitem $04, $0e, $2f, $00, TX_FULLWIDTH3, "G" - kbitem $06, $0e, $30, $00, TX_FULLWIDTH3, "P" - kbitem $08, $0e, $31, $00, TX_FULLWIDTH3, "Y" - kbitem $0a, $0e, $32, $00, "a" - kbitem $0c, $0e, $33, $00, TX_SYMBOL, SYM_No - kbitem $10, $0f, $01, $09, $0000 - - kbitem $04, $10, $34, $00, TX_FULLWIDTH3, "H" - kbitem $06, $10, $35, $00, TX_FULLWIDTH3, "Q" - kbitem $08, $10, $36, $00, TX_FULLWIDTH3, "Z" - kbitem $0a, $10, $3c, $00, "b" - kbitem $0c, $10, $3d, $00, TX_SYMBOL, SYM_Lv - kbitem $10, $0f, $01, $09, $0000 - - kbitem $04, $12, $37, $00, TX_FULLWIDTH3, "I" - kbitem $06, $12, $38, $00, TX_FULLWIDTH3, "R" - kbitem $08, $12, $39, $00, "n" - kbitem $0a, $12, $3a, $00, "c" - kbitem $0c, $12, $3b, $00, "p" - kbitem $10, $0f, $01, $09, $0000 - kbitem $00, $00, $00, $00, $0000 - -; a set of transition datum. -; unit: 4 bytes. -; structure: -; previous char. code (2) / translated char. code (2) -; - the former char. code contains 0x0e in high byte. -; - the latter char. code contains only low byte. -TransitionTable1: - dw $0e16, $003e - dw $0e17, $003f - dw $0e18, $0040 - dw $0e19, $0041 - dw $0e1a, $0042 - dw $0e1b, $0043 - dw $0e1c, $0044 - dw $0e1d, $0045 - dw $0e1e, $0046 - dw $0e1f, $0047 - dw $0e20, $0048 - dw $0e21, $0049 - dw $0e22, $004a - dw $0e23, $004b - dw $0e24, $004c - dw $0e2a, $004d - dw $0e2b, $004e - dw $0e2c, $004f - dw $0e2d, $0050 - dw $0e2e, $0051 - dw $0e52, $004d - dw $0e53, $004e - dw $0e54, $004f - dw $0e55, $0050 - dw $0e56, $0051 - dw $0000 - -TransitionTable2: - dw $0e2a, $0052 - dw $0e2b, $0053 - dw $0e2c, $0054 - dw $0e2d, $0055 - dw $0e2e, $0056 - dw $0e4d, $0052 - dw $0e4e, $0053 - dw $0e4f, $0054 - dw $0e50, $0055 - dw $0e51, $0056 - dw $0000 - -; get deck name from the user into de. -; function description is similar to the player's. -; refer to 'InputPlayerName'. -InputDeckName: ; 1ad89 (6:6d89) - push af - ; check if the buffer is empty. - ld a, [de] - or a - jr nz, .not_empty - ; this buffer will contain half-width chars. - ld a, TX_HALFWIDTH - ld [de], a -.not_empty - pop af - inc a - call InitializeInputName - call Set_OBJ_8x8 - - xor a - ld [wTileMapFill], a - call EmptyScreen - call ZeroObjectPositions - - ld a, $01 - ld [wVBlankOAMCopyToggle], a - call LoadSymbolsFont - - lb de, $38, $bf - call SetupText - call LoadHalfWidthTextCursorTile - - xor a - ld [wd009], a - call Func_1ae99 - - xor a - ld [wNamingScreenCursorX], a - ld [wNamingScreenCursorY], a - - ld a, $09 - ld [wNamingScreenNumColumns], a - ld a, $07 - ld [wNamingScreenKeyboardHeight], a - ld a, $0f - ld [wVisibleCursorTile], a - ld a, $00 - ld [wInvisibleCursorTile], a -.loop - ld a, $01 - ld [wVBlankOAMCopyToggle], a - call DoFrame - - call UpdateRNGSources - - ldh a, [hDPadHeld] - and START - jr z, .on_start - - ld a, $01 - call PlayAcceptOrDeclineSFX - call Func_1afa1 - - ld a, 6 - ld [wNamingScreenCursorX], a - ld [wNamingScreenCursorY], a - call Func_1afbd - - jr .loop -.on_start - call Func_1aefb - jr nc, .loop - - cp $ff - jr z, .asm_6e1c - - call Func_1aec3 - jr nc, .loop - - call FinalizeInputName - - ld hl, wNamingScreenDestPointer - ld a, [hli] - ld h, [hl] - ld l, a - inc hl - - ld a, [hl] - or a - jr nz, .return - - dec hl - ld [hl], TX_END -.return - ret -.asm_6e1c - ld a, [wNamingScreenBufferLength] - cp $02 - jr c, .loop - - ld e, a - ld d, 0 - ld hl, wNamingScreenBuffer - add hl, de - dec hl - ld [hl], TX_END - - ld hl, wNamingScreenBufferLength - dec [hl] - call ProcessTextWithUnderbar - - jp .loop - -; load, to the first tile of v0Tiles0, the graphics for the -; blinking black square used in name input screens. -; for inputting half width text. -LoadHalfWidthTextCursorTile: ; 1ae37 (6:6e37) - ld hl, v0Tiles0 + $00 tiles - ld de, .data - ld b, 0 -.loop - ld a, TILE_SIZE - cp b - ret z - inc b - ld a, [de] - inc de - ld [hli], a - jr .loop - -.data -rept TILE_SIZE - db $f0 -endr - -; it's only for naming the deck. -ProcessTextWithUnderbar: ; 1ae59 (6:6e59) - ld hl, wNamingScreenNamePosition - ld d, [hl] - inc hl - ld e, [hl] - call InitTextPrinting - ld hl, .underbar_data - ld de, wDefaultText -.loop ; copy the underbar string. - ld a, [hli] - ld [de], a - inc de - or a - jr nz, .loop - - ld hl, wNamingScreenBuffer - ld de, wDefaultText -.loop2 ; copy the input from the user. - ld a, [hli] - or a - jr z, .print_name - ld [de], a - inc de - jr .loop2 -.print_name - ld hl, wDefaultText - call ProcessText - ret -.underbar_data - db TX_HALFWIDTH -rept MAX_DECK_NAME_LENGTH - db "_" -endr - db TX_END - -Func_1ae99: ; 1ae99 (6:6e99) - call DrawTextboxForKeyboard - call ProcessTextWithUnderbar - ld hl, wNamingScreenQuestionPointer - ld c, [hl] - inc hl - ld a, [hl] - ld h, a - or c - jr z, .print - ; print the question string. - ld l, c - call PlaceTextItems -.print - ; print "End" - ld hl, DrawNamingScreenBG.data - call PlaceTextItems - ; print the keyboard characters. - ldtx hl, DeckNameKeyboardText ; "A B C D..." - lb de, 2, 4 - call InitTextPrinting - call ProcessTextFromID - call EnableLCD - ret - -Func_1aec3: ; 1aec3 (6:6ec3) - ld a, [wNamingScreenCursorX] - ld h, a - ld a, [wNamingScreenCursorY] - ld l, a - call GetCharInfoFromPos_Deck - inc hl - inc hl - ld a, [hl] - cp $01 - jr nz, .asm_6ed7 - scf - ret -.asm_6ed7 - ld d, a - ld hl, wNamingScreenBufferLength - ld a, [hl] - ld c, a - push hl - ld hl, wNamingScreenBufferMaxLength - cp [hl] - pop hl - jr nz, .asm_6eeb - ld hl, wNamingScreenBuffer - dec hl - jr .asm_6eef -.asm_6eeb - inc [hl] - ld hl, wNamingScreenBuffer -.asm_6eef - ld b, 0 - add hl, bc - ld [hl], d - inc hl - ld [hl], TX_END - call ProcessTextWithUnderbar - or a - ret - -Func_1aefb: ; 1aefb (6:6efb) - xor a - ld [wPlaysSfx], a - ldh a, [hDPadHeld] - or a - jp z, .asm_6f73 - ld b, a - ld a, [wNamingScreenKeyboardHeight] - ld c, a - ld a, [wNamingScreenCursorX] - ld h, a - ld a, [wNamingScreenCursorY] - ld l, a - bit 6, b - jr z, .asm_6f1f - dec a - bit 7, a - jr z, .asm_6f4b - ld a, c - dec a - jr .asm_6f4b -.asm_6f1f - bit 7, b - jr z, .asm_6f2a - inc a - cp c - jr c, .asm_6f4b - xor a - jr .asm_6f4b -.asm_6f2a - cp $06 - jr z, .asm_6f73 - ld a, [wNamingScreenNumColumns] - ld c, a - ld a, h - bit 5, b - jr z, .asm_6f40 - dec a - bit 7, a - jr z, .asm_6f4e - ld a, c - dec a - jr .asm_6f4e -.asm_6f40 - bit 4, b - jr z, .asm_6f73 - inc a - cp c - jr c, .asm_6f4e - xor a - jr .asm_6f4e -.asm_6f4b - ld l, a - jr .asm_6f4f -.asm_6f4e - ld h, a -.asm_6f4f - push hl - call GetCharInfoFromPos_Deck - inc hl - inc hl - ld d, [hl] - push de - call Func_1afa1 - pop de - pop hl - ld a, l - ld [wNamingScreenCursorY], a - ld a, h - ld [wNamingScreenCursorX], a - xor a - ld [wCheckMenuCursorBlinkCounter], a - ld a, $02 - cp d - jp z, Func_1aefb - ld a, $01 - ld [wPlaysSfx], a -.asm_6f73 - ldh a, [hKeysPressed] - and $03 - jr z, .asm_6f89 - and $01 - jr nz, .asm_6f7f - ld a, $ff -.asm_6f7f - call PlayAcceptOrDeclineSFX - push af - call Func_1afbd - pop af - scf - ret -.asm_6f89 - ld a, [wPlaysSfx] - or a - jr z, .asm_6f92 - call PlaySFX -.asm_6f92 - ld hl, wCheckMenuCursorBlinkCounter - ld a, [hl] - inc [hl] - and $0f - ret nz - ld a, [wVisibleCursorTile] - bit 4, [hl] - jr z, Func_1afa1.asm_6fa4 - -Func_1afa1: ; 1afa1 (6:6fa1) - ld a, [wInvisibleCursorTile] -.asm_6fa4 - ld e, a - ld a, [wNamingScreenCursorX] - ld h, a - ld a, [wNamingScreenCursorY] - ld l, a - call GetCharInfoFromPos_Deck - ld a, [hli] - ld c, a - ld b, [hl] - dec b - ld a, e - call Func_1afc2 - call WriteByteToBGMap0 - or a - ret - -Func_1afbd: ; 1afbd (6:6fbd) - ld a, [wVisibleCursorTile] - jr Func_1afa1.asm_6fa4 - -Func_1afc2: ; 1afc2 (6:6fc2) - push af - push bc - push de - push hl - push af - call ZeroObjectPositions - pop af - ld b, a - ld a, [wInvisibleCursorTile] - cp b - jr z, .asm_6ffb - ld a, [wNamingScreenBufferLength] - ld d, a - ld a, [wNamingScreenBufferMaxLength] - ld e, a - ld a, d - cp e - jr nz, .asm_6fdf - dec a -.asm_6fdf - dec a - ld d, a - ld hl, wNamingScreenNamePosition - ld a, [hl] - sla a - add d - ld d, a - ld h, $04 - ld l, d - call HtimesL - ld a, l - add $08 - ld d, a - ld e, $18 - ld bc, $0000 - call SetOneObjectAttributes -.asm_6ffb - pop hl - pop de - pop bc - pop af - ret - -; given the cursor position, -; returns the character information which the cursor directs. -; it's similar to "GetCharInfoFromPos_Player", -; but the data structure is different in its unit size. -; its unit size is 3, and player's is 6. -; h: x -; l: y -GetCharInfoFromPos_Deck: ; 1b000 (6:7000) - push de - ld e, l - ld d, h - ld a, [wNamingScreenKeyboardHeight] - ld l, a - call HtimesL - ld a, l - add e - ; x * h + y - ld hl, KeyboardData_Deck - pop de - or a - ret z -.loop - inc hl - inc hl - inc hl - dec a - jr nz, .loop - ret - -KeyboardData_Deck: ; 1b019 (6:7019) - db $04, $02, "A" - db $06, $02, "J" - db $08, $02, "S" - db $0a, $02, "?" - db $0c, $02, "4" - db $0e, $02, $02 - db $10, $0f, $01 - - db $04, $04, "B" - db $06, $04, "K" - db $08, $04, "T" - db $0a, $04, "&" - db $0c, $04, "5" - db $0e, $04, $02 - db $10, $0f, $01 - - db $04, $06, "C" - db $06, $06, "L" - db $08, $06, "U" - db $0a, $06, "+" - db $0c, $06, "6" - db $0e, $06, $02 - db $10, $0f, $01 - - db $04, $08, "D" - db $06, $08, "M" - db $08, $08, "V" - db $0a, $08, "-" - db $0c, $08, "7" - db $0e, $08, $02 - db $10, $0f, $01 - - db $04, $0a, "E" - db $06, $0a, "N" - db $08, $0a, "W" - db $0a, $0a, "'" - db $0c, $0a, "8" - db $0e, $0a, $02 - db $10, $0f, $01 - - db $04, $0c, "F" - db $06, $0c, "O" - db $08, $0c, "X" - db $0a, $0c, "0" - db $0c, $0c, "9" - db $0e, $0c, $02 - db $10, $0f, $01 - - db $04, $0e, "G" - db $06, $0e, "P" - db $08, $0e, "Y" - db $0a, $0e, "1" - db $0c, $0e, " " - db $0e, $0e, $02 - db $10, $0f, $01 - - db $04, $10, "H" - db $06, $10, "Q" - db $08, $10, "Z" - db $0a, $10, "2" - db $0c, $10, " " - db $0e, $10, $02 - db $10, $0f, $01 - - db $04, $12, "I" - db $06, $12, "R" - db $08, $12, "!" - db $0a, $12, "3" - db $0c, $12, " " - db $0e, $12, $02 - db $10, $0f, $01 - - ds 4 ; empty - -INCLUDE "data/auto_deck_card_lists.asm" -INCLUDE "data/auto_deck_machines.asm" - -; writes to sAutoDecks all the deck configurations -; from the Auto Deck Machine in wCurAutoDeckMachine -ReadAutoDeckConfiguration: ; 1ba14 (6:7a14) - call EnableSRAM - ld a, [wCurAutoDeckMachine] - ld l, a - ld h, 6 * NUM_DECK_MACHINE_SLOTS - call HtimesL - ld bc, AutoDeckMachineEntries - add hl, bc - ld b, 0 -.loop_decks - call .GetPointerToSRAMAutoDeck - call .ReadDeckConfiguration - call .ReadDeckName - - ; store deck description text ID - push hl - ld de, wAutoDeckMachineTextDescriptions - ld h, b - ld l, 2 - call HtimesL - add hl, de - ld d, h - ld e, l - pop hl - ld a, [hli] - ld [de], a - inc de - ld a, [hli] - ld [de], a - inc b - ld a, b - cp NUM_DECK_MACHINE_SLOTS - jr nz, .loop_decks - call DisableSRAM - ret - -; outputs in de the saved deck with index b -.GetPointerToSRAMAutoDeck - push hl - ld l, b - ld h, DECK_STRUCT_SIZE - call HtimesL - ld de, sAutoDecks - add hl, de - ld d, h - ld e, l - pop hl - ret - -; writes the deck configuration in SRAM -; by reading the given deck card list -.ReadDeckConfiguration - push hl - push bc - push de - push de - ld e, [hl] - inc hl - ld d, [hl] - pop hl - ld bc, DECK_NAME_SIZE - add hl, bc -.loop_create_deck - ld a, [de] - inc de - ld b, a ; card count - or a - jr z, .done_create_deck - ld a, [de] - inc de - ld c, a ; card ID -.loop_card_count - ld [hl], c - inc hl - dec b - jr nz, .loop_card_count - jr .loop_create_deck -.done_create_deck - pop de - pop bc - pop hl - inc hl - inc hl - ret - -.ReadDeckName - push hl - push bc - push de - ld a, [hli] - ld h, [hl] - ld l, a - ld de, wDismantledDeckName - call CopyText - pop hl - ld de, wDismantledDeckName -.loop_copy_name - ld a, [de] - ld [hli], a - or a - jr z, .done_copy_name - inc de - jr .loop_copy_name -.done_copy_name - pop bc - pop hl - inc hl - inc hl - ret - -; tries out all combinations of dismantling the player's decks -; in order to build the deck in wSelectedDeckMachineEntry -; if none of the combinations work, return carry set -; otherwise, return in a which deck flags should be dismantled -CheckWhichDecksToDismantleToBuildSavedDeck: ; 1ba9a (6:7a9a) - xor a - ld [wDecksToBeDismantled], a - -; first check if it can be built by -; only dismantling a single deck - ld a, DECK_1 -.loop_single_built_decks - call .CheckIfCanBuild - ret nc - sla a ; next deck - cp (1 << NUM_DECKS) - jr z, .two_deck_combinations - jr .loop_single_built_decks - -.two_deck_combinations -; next check all two deck combinations - ld a, DECK_1 | DECK_2 - call .CheckIfCanBuild - ret nc - ld a, DECK_1 | DECK_3 - call .CheckIfCanBuild - ret nc - ld a, DECK_1 | DECK_4 - call .CheckIfCanBuild - ret nc - ld a, DECK_2 | DECK_3 - call .CheckIfCanBuild - ret nc - ld a, DECK_2 | DECK_4 - call .CheckIfCanBuild - ret nc - ld a, DECK_3 | DECK_4 - call .CheckIfCanBuild - ret nc - -; all but one deck combinations - ld a, $ff ^ DECK_4 -.loop_three_deck_combinations - call .CheckIfCanBuild - ret nc - sra a - cp $ff - jr z, .all_decks - jr .loop_three_deck_combinations - -.all_decks -; finally check if can be built by dismantling all decks - call .CheckIfCanBuild - ret nc - -; none of the combinations work - scf - ret - -; returns carry if wSelectedDeckMachineEntry cannot be built -; by dismantling the decks given by register a -; a = DECK_* flags -.CheckIfCanBuild - push af - ld hl, wSelectedDeckMachineEntry - ld b, [hl] - farcall CheckIfCanBuildSavedDeck - jr c, .cannot_build - pop af - ld [wDecksToBeDismantled], a - or a - ret -.cannot_build - pop af - scf - ret diff --git a/src/engine/copy_card_name.asm b/src/engine/copy_card_name.asm new file mode 100644 index 0000000..feb33ca --- /dev/null +++ b/src/engine/copy_card_name.asm @@ -0,0 +1,152 @@ +; 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: + push bc + push de + ld [wCardNameLength], a + ld hl, wLoadedCard1Name + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wDefaultText + push de + call CopyText ; copy card name to wDefaultText + pop hl + ld a, [hli] + cp TX_HALFWIDTH + jp z, _CopyCardNameAndLevel_HalfwidthText + +; the name doesn't start with TX_HALFWIDTH +; this doesn't appear to be ever the case (unless caller manipulates wLoadedCard1Name) + ld a, [wCardNameLength] + ld c, a + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr nc, .level_done ; jump if energy or trainer + ld a, [wLoadedCard1Level] + or a + jr z, .level_done + inc c + inc c + ld a, [wLoadedCard1Level] + cp 10 + jr c, .level_done + inc c ; second digit +.level_done + ld hl, wLoadedCard1Name + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wDefaultText + push de + call CopyText + pop hl + push de + ld e, c + call GetTextLengthInTiles + add e + ld c, a + pop hl + push hl +.fill_loop + ld a, $70 + ld [hli], a + dec c + jr nz, .fill_loop + ld [hl], TX_END + pop hl + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr nc, .done + ld a, [wLoadedCard1Level] + or a + jr z, .done + ld a, TX_SYMBOL + ld [hli], a + ld [hl], SYM_Lv + inc hl + ld a, [wLoadedCard1Level] + cp 10 + jr c, .one_digit + ld [hl], TX_SYMBOL + inc hl + ld b, SYM_0 - 1 +.first_digit_loop + inc b + sub 10 + jr nc, .first_digit_loop + add 10 + ld [hl], b ; first digit + inc hl +.one_digit + ld [hl], TX_SYMBOL + inc hl + add SYM_0 + ld [hl], a ; last (or only) digit + inc hl +.done + pop de + pop bc + ret + +; the name starts with TX_HALFWIDTH +_CopyCardNameAndLevel_HalfwidthText: + ld a, [wCardNameLength] + inc a + add a + ld b, a + ld hl, wDefaultText +.find_end_text_loop + dec b + ld a, [hli] + or a ; TX_END + jr nz, .find_end_text_loop + dec hl + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr nc, .level_done + ld a, [wLoadedCard1Level] + or a + jr z, .level_done + ld c, a + ld a, " " + ld [hli], a + dec b + ld a, "L" + ld [hli], a + dec b + ld a, "v" + ld [hli], a + dec b + ld a, c + cp 10 + jr c, .got_level + push bc + ld b, "0" - 1 +.first_digit_loop + inc b + sub 10 + jr nc, .first_digit_loop + add 10 + ld [hl], b ; first digit + inc hl + pop bc + ld c, a + dec b +.got_level + ld a, c + add "0" + ld [hli], a ; last (or only) digit + dec b +.level_done + push hl + ld a, " " +.fill_spaces_loop + ld [hli], a + dec b + jr nz, .fill_spaces_loop + ld [hl], TX_END + pop hl + pop de + pop bc + ret diff --git a/src/engine/duel/animations.asm b/src/engine/duel/animations.asm new file mode 100644 index 0000000..46b1ea1 --- /dev/null +++ b/src/engine/duel/animations.asm @@ -0,0 +1,354 @@ +; reads the animation commands from PointerTable_AttackAnimation +; of attack in wLoadedAttackAnimation and plays them +PlayAttackAnimationCommands: + ld a, [wLoadedAttackAnimation] + or a + ret z + + ld l, a + ld h, 0 + add hl, hl + ld de, PointerTable_AttackAnimation + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + + push de + ld hl, wce7e + ld a, [hl] + or a + jr nz, .read_command + ld [hl], $01 + call Func_3b21 + pop de + + push de + ld a, DUEL_ANIM_SCREEN_MAIN_SCENE + ld [wDuelAnimationScreen], a + ld a, $01 + ld [wd4b3], a + xor a + ld [wDuelAnimLocationParam], a + ld a, [de] + cp $04 + jr z, .read_command + ld a, DUEL_ANIM_150 + call PlayDuelAnimation +.read_command + pop de + ; fallthrough + +PlayAttackAnimationCommands_NextCommand: + ld a, [de] + inc de + ld hl, AnimationCommandPointerTable + jp JumpToFunctionInTable + +AnimationCommand_AnimEnd: + ret + +AnimationCommand_AnimPlayer: + ldh a, [hWhoseTurn] + ld [wDuelAnimDuelistSide], a + ld a, [wDuelType] + cp $00 + jr nz, AnimationCommand_AnimNormal + ld a, PLAYER_TURN + ld [wDuelAnimDuelistSide], a + jr AnimationCommand_AnimNormal + +AnimationCommand_AnimOpponent: + call SwapTurn + ldh a, [hWhoseTurn] + ld [wDuelAnimDuelistSide], a + call SwapTurn + ld a, [wDuelType] + cp $00 + jr nz, AnimationCommand_AnimNormal + ld a, OPPONENT_TURN + ld [wDuelAnimDuelistSide], a + jr AnimationCommand_AnimNormal + +AnimationCommand_AnimUnknown2: + ld a, [wce82] + and $7f + ld [wDuelAnimLocationParam], a + jr AnimationCommand_AnimNormal + +AnimationCommand_AnimEnd2: + ret + +AnimationCommand_AnimNormal: + ld a, [de] + inc de + cp DUEL_ANIM_SHOW_DAMAGE + jr z, .show_damage + cp DUEL_ANIM_SHAKE1 + jr z, .shake_1 + cp DUEL_ANIM_SHAKE2 + jr z, .shake_2 + cp DUEL_ANIM_SHAKE3 + jr z, .shake_3 + +.play_anim + call PlayDuelAnimation + jr PlayAttackAnimationCommands_NextCommand + +.show_damage + ld a, DUEL_ANIM_PRINT_DAMAGE + call PlayDuelAnimation + ld a, [wce81] + ld [wd4b3], a + + push de + ld hl, wce7f + ld de, wDuelAnimDamage + ld a, [hli] + ld [de], a + inc de + ld a, [hli] + ld [de], a + pop de + + ld a, $8c + call PlayDuelAnimation + ld a, [wDuelDisplayedScreen] + cp DUEL_MAIN_SCENE + jr nz, .skip_update_hud + ld a, DUEL_ANIM_UPDATE_HUD + call PlayDuelAnimation +.skip_update_hud + jp PlayAttackAnimationCommands_NextCommand + +; screen shake happens differently +; depending on whose turn it is +.shake_1 + ld c, DUEL_ANIM_SMALL_SHAKE_X + ld b, DUEL_ANIM_SMALL_SHAKE_Y + jr .check_duelist + +.shake_2 + ld c, DUEL_ANIM_BIG_SHAKE_X + ld b, DUEL_ANIM_BIG_SHAKE_Y + jr .check_duelist + +.shake_3 + ld c, DUEL_ANIM_SMALL_SHAKE_Y + ld b, DUEL_ANIM_SMALL_SHAKE_X + +.check_duelist + ldh a, [hWhoseTurn] + cp PLAYER_TURN + ld a, c + jr z, .play_anim + ld a, [wDuelType] + cp $00 + ld a, c + jr z, .play_anim + ld a, b + jr .play_anim + +AnimationCommand_AnimUnknown: + ld a, [de] + inc de + ld [wd4b3], a + ld a, [wce82] + ld [wDuelAnimLocationParam], a + call SetDuelAnimationScreen + ld a, DUEL_ANIM_150 + call PlayDuelAnimation + jp PlayAttackAnimationCommands_NextCommand + +AnimationCommandPointerTable: + dw AnimationCommand_AnimEnd ; anim_end + dw AnimationCommand_AnimNormal ; anim_normal + dw AnimationCommand_AnimPlayer ; anim_player + dw AnimationCommand_AnimOpponent ; anim_opponent + dw AnimationCommand_AnimUnknown ; anim_unknown + dw AnimationCommand_AnimUnknown2 ; anim_unknown2 + dw AnimationCommand_AnimEnd2 ; anim_end2 (unused) + +; sets wDuelAnimationScreen according to wd4b3 +; if wd4b3 == $01, set it to Main Scene +; if wd4b3 == $04, st it to Play Area scene +SetDuelAnimationScreen: + ld a, [wd4b3] + cp $04 + jr z, .set_play_area_screen + cp $01 + ret nz + ld a, DUEL_ANIM_SCREEN_MAIN_SCENE + ld [wDuelAnimationScreen], a + ret + +.set_play_area_screen + ld a, [wDuelAnimLocationParam] + ld l, a + ld a, [wWhoseTurn] + ld h, a + cp PLAYER_TURN + jr z, .player + +; opponent + ld a, [wDuelType] + cp $00 + jr z, .asm_50c6 + +; link duel or vs. AI + bit 7, l + jr z, .asm_50e2 + jr .asm_50d2 + +.asm_50c6 + bit 7, l + jr z, .asm_50da + jr .asm_50ea + +.player + bit 7, l + jr z, .asm_50d2 + jr .asm_50e2 + +.asm_50d2 + ld l, UNKNOWN_SCREEN_4 + ld h, PLAYER_TURN + ld a, DUEL_ANIM_SCREEN_PLAYER_PLAY_AREA + jr .ok +.asm_50da + ld l, UNKNOWN_SCREEN_4 + ld h, OPPONENT_TURN + ld a, DUEL_ANIM_SCREEN_PLAYER_PLAY_AREA + jr .ok +.asm_50e2 + ld l, UNKNOWN_SCREEN_5 + ld h, OPPONENT_TURN + ld a, DUEL_ANIM_SCREEN_OPP_PLAY_AREA + jr .ok +.asm_50ea + ld l, UNKNOWN_SCREEN_5 + ld h, PLAYER_TURN + ld a, DUEL_ANIM_SCREEN_OPP_PLAY_AREA + +.ok + ld [wDuelAnimationScreen], a + ret + +Func_190f4: + ld a, [wd4b3] + cp $04 + jr z, Func_1910f + ; fallthrough + +Func_190fb: + cp $01 + jr nz, .done + ld a, DUEL_ANIM_SCREEN_MAIN_SCENE + ld [wDuelAnimationScreen], a + ld a, [wDuelDisplayedScreen] + cp $01 + jr z, .done + bank1call DrawDuelMainScene +.done + ret + +Func_1910f: + call SetDuelAnimationScreen + ld a, [wDuelDisplayedScreen] + cp l + jr z, .skip_change_screen + ld a, l + push af + ld l, PLAYER_TURN + ld a, [wDuelType] + cp $00 + jr nz, .asm_5127 + ld a, [wWhoseTurn] + ld l, a +.asm_5127 + call DrawYourOrOppPlayAreaScreen_Bank0 + pop af + ld [wDuelDisplayedScreen], a +.skip_change_screen + call DrawWideTextBox + ret + +; prints text related to the damage received +; by card stored in wTempNonTurnDuelistCardID +; takes into account type effectiveness +PrintDamageText: + push hl + push bc + push de + ld a, [wLoadedAttackAnimation] + cp ATK_ANIM_HEAL + jr z, .skip + cp ATK_ANIM_HEALING_WIND_PLAY_AREA + jr z, .skip + + ld a, [wTempNonTurnDuelistCardID] + ld e, a + ld d, $00 + call LoadCardDataToBuffer1_FromCardID + ld a, 18 + call CopyCardNameAndLevel + ld [hl], TX_END + ld hl, wTxRam2 + xor a + ld [hli], a + ld [hl], a + ld hl, wce7f + ld a, [hli] + ld h, [hl] + ld l, a + call GetDamageText + ld a, l + or h + call nz, DrawWideTextBox_PrintText +.skip + pop de + pop bc + pop hl + ret + +; returns in hl the text id associated with +; the damage in hl and its effectiveness +GetDamageText: + ld a, l + or h + jr z, .no_damage + call LoadTxRam3 + ld a, [wce81] + ldtx hl, AttackDamageText + and (1 << RESISTANCE) | (1 << WEAKNESS) + ret z ; not weak or resistant + ldtx hl, WeaknessMoreDamage2Text + cp (1 << RESISTANCE) | (1 << WEAKNESS) + ret z ; weak and resistant + and (1 << WEAKNESS) + ldtx hl, WeaknessMoreDamageText + ret nz ; weak + ldtx hl, ResistanceLessDamageText + ret ; resistant + +.no_damage + call CheckNoDamageOrEffect + ret c + ldtx hl, NoDamageText + ld a, [wce81] + and (1 << RESISTANCE) + ret z ; not resistant + ldtx hl, ResistanceNoDamageText + ret ; resistant + +UpdateMainSceneHUD: + ld a, [wDuelDisplayedScreen] + cp DUEL_MAIN_SCENE + ret nz + bank1call DrawDuelHUDs + ret + +Func_191a3: + ret + +INCLUDE "data/duel/animations/attack_animations.asm" diff --git a/src/engine/duel/core.asm b/src/engine/duel/core.asm index 3b4b95c..f2f08c7 100644 --- a/src/engine/duel/core.asm +++ b/src/engine/duel/core.asm @@ -5983,7 +5983,7 @@ PrintUsedTrainerCardDescription: ; byte 0 is $01, bytes 1 and 2 are the checksum, byte 3 is [wDuelType] ; next $33a bytes come from DuelDataToSave SaveDuelData: - farcall CommentedOut_1a6cc + farcall StubbedUnusedSaveDataValidation ld de, sCurrentDuel ; fallthrough diff --git a/src/data/duel/effect_commands.asm b/src/engine/duel/effect_commands.asm index e96ef7e..e96ef7e 100644 --- a/src/data/duel/effect_commands.asm +++ b/src/engine/duel/effect_commands.asm diff --git a/src/engine/game_loop.asm b/src/engine/game_loop.asm index c3745b6..d6e4fab 100644 --- a/src/engine/game_loop.asm +++ b/src/engine/game_loop.asm @@ -15,7 +15,7 @@ GameLoop: ld a, 1 ld [wUppercaseHalfWidthLetters], a ei - farcall CommentedOut_1a6cc + farcall StubbedUnusedSaveDataValidation ldh a, [hKeysHeld] cp A_BUTTON | B_BUTTON jr z, .ask_erase_backup_ram diff --git a/src/engine/input_name.asm b/src/engine/input_name.asm new file mode 100644 index 0000000..c9d222e --- /dev/null +++ b/src/engine/input_name.asm @@ -0,0 +1,1417 @@ +WhatIsYourNameData: + textitem 1, 1, WhatIsYourNameText + db $ff +; [Deck1Data ~ Deck4Data] +; These are directed from around (2:4f05), +; without any bank description. +; That is, the developers hard-coded it. -_-;; +Deck1Data: + textitem 2, 1, Deck1Text + textitem 14, 1, DeckText + db $ff +Deck2Data: + textitem 2, 1, Deck2Text + textitem 14, 1, DeckText + db $ff +Deck3Data: + textitem 2, 1, Deck3Text + textitem 14, 1, DeckText + db $ff +Deck4Data: + textitem 2, 1, Deck4Text + textitem 14, 1, DeckText + db $ff + +; set each byte zero from hl for b bytes. +ClearMemory: + 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 + +; play different sfx by a. +; if a is 0xff play SFX_03 (usually following a B press), +; else play SFX_02 (usually following an A press). +PlayAcceptOrDeclineSFX: + push af + inc a + jr z, .sfx_decline + ld a, SFX_02 + jr .sfx_accept +.sfx_decline + ld a, SFX_03 +.sfx_accept + call PlaySFX + pop af + ret + +; get player name from the user +; into hl +InputPlayerName: + ld e, l + ld d, h + ld a, MAX_PLAYER_NAME_LENGTH + ld hl, WhatIsYourNameData + lb bc, 12, 1 + call InitializeInputName + call Set_OBJ_8x8 + xor a + ld [wTileMapFill], a + call EmptyScreen + call ZeroObjectPositions + ld a, $01 + ld [wVBlankOAMCopyToggle], a + call LoadSymbolsFont + lb de, $38, $bf + call SetupText + call LoadTextCursorTile + ld a, $02 + ld [wd009], a + call DrawNamingScreenBG + xor a + ld [wNamingScreenCursorX], a + ld [wNamingScreenCursorY], a + ld a, $09 + ld [wNamingScreenNumColumns], a + ld a, $06 + ld [wNamingScreenKeyboardHeight], a + ld a, $0f + ld [wVisibleCursorTile], a + ld a, $00 + ld [wInvisibleCursorTile], a +.loop + ld a, $01 + ld [wVBlankOAMCopyToggle], a + call DoFrame + call UpdateRNGSources + ldh a, [hDPadHeld] + and START + jr z, .else + ; if pressed start button. + ld a, $01 + call PlayAcceptOrDeclineSFX + call Func_1aa07 + ld a, 6 + ld [wNamingScreenCursorX], a + ld a, 5 + ld [wNamingScreenCursorY], a + call Func_1aa23 + jr .loop +.else + call NamingScreen_CheckButtonState + jr nc, .loop ; if not pressed, go back to the loop. + cp $ff + jr z, .on_b_button + ; on A button. + call NamingScreen_ProcessInput + jr nc, .loop + ; if the player selected the end button, + ; end its naming. + call FinalizeInputName + ret +.on_b_button + ld a, [wNamingScreenBufferLength] + or a + jr z, .loop ; empty string? + ; erase one character. + ld e, a + ld d, 0 + ld hl, wNamingScreenBuffer + add hl, de + dec hl + dec hl + ld [hl], TX_END + ld hl, wNamingScreenBufferLength ; note that its unit is byte, not word. + dec [hl] + dec [hl] + call PrintPlayerNameFromInput + jr .loop + +; it's called when naming(either player's or deck's) starts. +; a: maximum length of name(depending on whether player's or deck's). +; bc: position of name. +; de: dest. pointer. +; hl: pointer to text item of the question. +InitializeInputName: + ld [wNamingScreenBufferMaxLength], a + push hl + ld hl, wNamingScreenNamePosition + ld [hl], b + inc hl + ld [hl], c + pop hl + ld b, h + ld c, l + ; set the question string. + ld hl, wNamingScreenQuestionPointer + ld [hl], c + inc hl + ld [hl], b + ; set the destination buffer. + ld hl, wNamingScreenDestPointer + ld [hl], e + inc hl + ld [hl], d + ; clear the name buffer. + ld a, NAMING_SCREEN_BUFFER_LENGTH + ld hl, wNamingScreenBuffer + call ClearMemory + ld hl, wNamingScreenBuffer + ld a, [wNamingScreenBufferMaxLength] + ld b, a + inc b +.loop + ; copy data from de to hl + ; for b bytes. + ld a, [de] + inc de + ld [hli], a + dec b + jr nz, .loop + ld hl, wNamingScreenBuffer + call GetTextLengthInTiles + ld a, c + ld [wNamingScreenBufferLength], a + ret + +FinalizeInputName: + ld hl, wNamingScreenDestPointer + ld e, [hl] + inc hl + ld d, [hl] + ld l, e + ld h, d + ld de, wNamingScreenBuffer + ld a, [wNamingScreenBufferMaxLength] + ld b, a + inc b + jr InitializeInputName.loop + +; draws the keyboard frame +; and the question if it exists. +DrawNamingScreenBG: + call DrawTextboxForKeyboard + call PrintPlayerNameFromInput + ld hl, wNamingScreenQuestionPointer + ld c, [hl] + inc hl + ld a, [hl] + ld h, a + or c + jr z, .put_text_end + ; print the question string. + ; ex) "What is your name?" + ld l, c + call PlaceTextItems +.put_text_end + ; print "End". + ld hl, .data + call PlaceTextItems + ldtx hl, PlayerNameKeyboardText + lb de, 2, 4 + call InitTextPrinting + call ProcessTextFromID + call EnableLCD + ret +.data + textitem $0f, $10, EndText ; "End" + db $ff + +DrawTextboxForKeyboard: + lb de, 0, 3 ; x, y + lb bc, 20, 15 ; w, h + call DrawRegularTextBox + ret + +PrintPlayerNameFromInput: + ld hl, wNamingScreenNamePosition + ld d, [hl] + inc hl + ld e, [hl] + push de + call InitTextPrinting + ld a, [wNamingScreenBufferMaxLength] + ld e, a + ld a, $14 + sub e + inc a + ld e, a + ld d, 0 + ; print the underbars + ; before print the input. + ld hl, .char_underbar + add hl, de + call ProcessText + pop de + call InitTextPrinting + ; print the input from the user. + ld hl, wNamingScreenBuffer + call ProcessText + ret +.char_underbar + db $56 +rept 10 + textfw3 "_" +endr + done + +; check if button pressed. +; if pressed, set the carry bit on. +NamingScreen_CheckButtonState: + xor a + ld [wPlaysSfx], a + ldh a, [hDPadHeld] + or a + jp z, .no_press + ; detected any button press. + ld b, a + ld a, [wNamingScreenKeyboardHeight] + ld c, a + ld a, [wNamingScreenCursorX] + ld h, a + ld a, [wNamingScreenCursorY] + ld l, a + bit D_UP_F, b + jr z, .asm_692c + ; up + dec a + bit D_DOWN_F, a + jr z, .asm_69a7 + ld a, c + dec a + jr .asm_69a7 +.asm_692c + bit D_DOWN_F, b + jr z, .asm_6937 + ; down + inc a + cp c + jr c, .asm_69a7 + xor a + jr .asm_69a7 +.asm_6937 + ld a, [wNamingScreenNumColumns] + ld c, a + ld a, h + bit D_LEFT_F, b + jr z, .asm_6974 + ; left + ld d, a + ld a, $06 + cp l + ld a, d + jr nz, .asm_696b + push hl + push bc + push af + call GetCharInfoFromPos_Player + inc hl + inc hl + inc hl + inc hl + inc hl + ld a, [hl] + dec a + ld d, a + pop af + pop bc + pop hl + sub d + cp $ff + jr nz, .asm_6962 + ld a, c + sub $02 + jr .asm_69aa +.asm_6962 + cp $fe + jr nz, .asm_696b + ld a, c + sub $03 + jr .asm_69aa +.asm_696b + dec a + bit D_DOWN_F, a + jr z, .asm_69aa + ld a, c + dec a + jr .asm_69aa +.asm_6974 + bit D_RIGHT_F, b + jr z, .no_press + ld d, a + ld a, $06 + cp l + ld a, d + jr nz, .asm_6990 + push hl + push bc + push af + call GetCharInfoFromPos_Player + inc hl + inc hl + inc hl + inc hl + ld a, [hl] + dec a + ld d, a + pop af + pop bc + pop hl + add d +.asm_6990 + inc a + cp c + jr c, .asm_69aa + inc c + cp c + jr c, .asm_69a4 + inc c + cp c + jr c, .asm_69a0 + ld a, $02 + jr .asm_69aa +.asm_69a0 + ld a, $01 + jr .asm_69aa +.asm_69a4 + xor a + jr .asm_69aa +.asm_69a7 + ld l, a + jr .asm_69ab +.asm_69aa + ld h, a +.asm_69ab + push hl + call GetCharInfoFromPos_Player + inc hl + inc hl + inc hl + ld a, [wd009] + cp $02 + jr nz, .asm_69bb + inc hl + inc hl +.asm_69bb + ld d, [hl] + push de + call Func_1aa07 + pop de + pop hl + ld a, l + ld [wNamingScreenCursorY], a + ld a, h + ld [wNamingScreenCursorX], a + xor a + ld [wCheckMenuCursorBlinkCounter], a + ld a, $06 + cp d + jp z, NamingScreen_CheckButtonState + ld a, $01 + ld [wPlaysSfx], a +.no_press + ldh a, [hKeysPressed] + and A_BUTTON | B_BUTTON + jr z, .asm_69ef + and A_BUTTON + jr nz, .asm_69e5 + ld a, $ff +.asm_69e5 + call PlayAcceptOrDeclineSFX + push af + call Func_1aa23 + pop af + scf + ret +.asm_69ef + ld a, [wPlaysSfx] + or a + jr z, .asm_69f8 + call PlaySFX +.asm_69f8 + ld hl, wCheckMenuCursorBlinkCounter + ld a, [hl] + inc [hl] + and $0f + ret nz + ld a, [wVisibleCursorTile] + bit 4, [hl] + jr z, Func_1aa07.asm_6a0a + +Func_1aa07: + ld a, [wInvisibleCursorTile] +.asm_6a0a + ld e, a + ld a, [wNamingScreenCursorX] + ld h, a + ld a, [wNamingScreenCursorY] + ld l, a + call GetCharInfoFromPos_Player + ld a, [hli] + ld c, a + ld b, [hl] + dec b + ld a, e + call Func_1aa28 + call WriteByteToBGMap0 + or a + ret + +Func_1aa23: + ld a, [wVisibleCursorTile] + jr Func_1aa07.asm_6a0a + +Func_1aa28: + push af + push bc + push de + push hl + push af + call ZeroObjectPositions + pop af + ld b, a + ld a, [wInvisibleCursorTile] + cp b + jr z, .asm_6a60 + ld a, [wNamingScreenBufferLength] + srl a + ld d, a + ld a, [wNamingScreenBufferMaxLength] + srl a + ld e, a + ld a, d + cp e + jr nz, .asm_6a49 + dec a +.asm_6a49 + ld hl, wNamingScreenNamePosition + add [hl] + ld d, a + ld h, $08 + ld l, d + call HtimesL + ld a, l + add $08 + ld d, a + ld e, $18 + ld bc, $0000 + call SetOneObjectAttributes +.asm_6a60 + pop hl + pop de + pop bc + pop af + ret + +; load, to the first tile of v0Tiles0, the graphics for the +; blinking black square used in name input screens. +; for inputting full width text. +LoadTextCursorTile: + ld hl, v0Tiles0 + $00 tiles + ld de, .data + ld b, 0 +.loop + ld a, TILE_SIZE + cp b + ret z + inc b + ld a, [de] + inc de + ld [hli], a + jr .loop + +.data +rept TILE_SIZE + db $ff +endr + +; set the carry bit on, +; if "End" was selected. +NamingScreen_ProcessInput: + ld a, [wNamingScreenCursorX] + ld h, a + ld a, [wNamingScreenCursorY] + ld l, a + call GetCharInfoFromPos_Player + inc hl + inc hl + ; load types into de. + ld e, [hl] + inc hl + ld a, [hli] + ld d, a + cp $09 + jp z, .on_end + cp $07 + jr nz, .asm_6ab8 + ld a, [wd009] + or a + jr nz, .asm_6aac + ld a, $01 + jp .asm_6ace +.asm_6aac + dec a + jr nz, .asm_6ab4 + ld a, $02 + jp .asm_6ace +.asm_6ab4 + xor a + jp .asm_6ace +.asm_6ab8 + cp $08 + jr nz, .asm_6ad6 + ld a, [wd009] + or a + jr nz, .asm_6ac6 + ld a, $02 + jr .asm_6ace +.asm_6ac6 + dec a + jr nz, .asm_6acc + xor a + jr .asm_6ace +.asm_6acc + ld a, $01 +.asm_6ace + ld [wd009], a + call DrawNamingScreenBG + or a + ret +.asm_6ad6 + ld a, [wd009] + cp $02 + jr z, .read_char + ldfw3 bc, "“" + ld a, d + cp b + jr nz, .asm_6af4 + ld a, e + cp c + jr nz, .asm_6af4 + push hl + ld hl, TransitionTable1 ; from 55th. + call TransformCharacter + pop hl + jr c, .nothing + jr .asm_6b09 +.asm_6af4 + ldfw3 bc, "º(2)" + ld a, d + cp b + jr nz, .asm_6b1d + ld a, e + cp c + jr nz, .asm_6b1d + push hl + ld hl, TransitionTable2 ; from 72th. + call TransformCharacter + pop hl + jr c, .nothing +.asm_6b09 + ld a, [wNamingScreenBufferLength] + dec a + dec a + ld [wNamingScreenBufferLength], a + ld hl, wNamingScreenBuffer + push de + ld d, 0 + ld e, a + add hl, de + pop de + ld a, [hl] + jr .asm_6b37 +.asm_6b1d + ld a, d + or a + jr nz, .asm_6b37 + ld a, [wd009] + or a + jr nz, .asm_6b2b + ld a, TX_HIRAGANA + jr .asm_6b37 +.asm_6b2b + ld a, TX_KATAKANA + jr .asm_6b37 +; read character code from info. to register. +; hl: pointer. +.read_char + ld e, [hl] + inc hl + ld a, [hl] ; a: first byte of the code. + or a + ; if 2 bytes code, jump. + jr nz, .asm_6b37 + ; if 1 byte code(ascii), + ; set first byte to $0e. + ld a, $0e +; on 2 bytes code. +.asm_6b37 + ld d, a ; de: character code. + ld hl, wNamingScreenBufferLength + ld a, [hl] + ld c, a + push hl + ld hl, wNamingScreenBufferMaxLength + cp [hl] + pop hl + jr nz, .asm_6b4c + ; if the buffer is full + ; just change the last character of it. + ld hl, wNamingScreenBuffer + dec hl + dec hl + jr .asm_6b51 +; increase name length before add the character. +.asm_6b4c + inc [hl] + inc [hl] + ld hl, wNamingScreenBuffer +; write 2 bytes character codes to the name buffer. +; de: 2 bytes character codes. +; hl: dest. +.asm_6b51 + ld b, 0 + add hl, bc + ld [hl], d + inc hl + ld [hl], e + inc hl + ld [hl], TX_END ; null terminator. + call PrintPlayerNameFromInput +.nothing + or a + ret +.on_end + scf + ret + +; this transforms the last japanese character +; in the name buffer into its dakuon shape or something. +; it seems to have been deprecated as the game was translated into english. +; but it can still be applied to english, such as upper-lower case transition. +; hl: info. pointer. +TransformCharacter: + ld a, [wNamingScreenBufferLength] + or a + jr z, .return ; if the length is zero, just return. + dec a + dec a + push hl + ld hl, wNamingScreenBuffer + ld d, 0 + ld e, a + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ; de: last character in the buffer, + ; but byte-wise swapped. + ld a, TX_KATAKANA + cp e + jr nz, .hiragana + ; if it's katakana, + ; make it hiragana by decreasing its high byte. + dec e +.hiragana + pop hl +.loop + ld a, [hli] + or a + jr z, .return + cp d + jr nz, .next + ld a, [hl] + cp e + jr nz, .next + inc hl + ld e, [hl] + inc hl + ld d, [hl] + or a + ret +.next + inc hl + inc hl + inc hl + jr .loop +.return + scf + ret + +; given the position of the current cursor, +; it returns the pointer to the proper information. +; h: position x. +; l: position y. +GetCharInfoFromPos_Player: + push de + ; (information index) = (x) * (height) + (y) + ; (height) = 0x05(Deck) or 0x06(Player) + ld e, l + ld d, h + ld a, [wNamingScreenKeyboardHeight] + ld l, a + call HtimesL + ld a, l + add e + ld hl, KeyboardData_Player + pop de + or a + ret z +.loop + inc hl + inc hl + inc hl + inc hl + inc hl + inc hl + dec a + jr nz, .loop + ret + +; a set of keyboard datum. +; unit: 6 bytes. +; structure: +; abs. y pos. (1) / abs. x pos. (1) / type 1 (1) / type 2 (1) / char. code (2) +; unused data contains its character code as zero. +kbitem: MACRO + db \1, \2, \3, \4 +if (_NARG == 5) + dw \5 +elif (\5 == TX_FULLWIDTH3) + dw (\5 << 8) | STRCAT("FW3_", \6) +else + dw (\5 << 8) | \6 +endc +ENDM + +KeyboardData_Player: + kbitem $04, $02, $11, $00, TX_FULLWIDTH3, "A" + kbitem $06, $02, $12, $00, TX_FULLWIDTH3, "J" + kbitem $08, $02, $13, $00, TX_FULLWIDTH3, "S" + kbitem $0a, $02, $14, $00, "o" + kbitem $0c, $02, $15, $00, "d" + kbitem $10, $0f, $01, $09, $0000 + + kbitem $04, $04, $16, $00, TX_FULLWIDTH3, "B" + kbitem $06, $04, $17, $00, TX_FULLWIDTH3, "K" + kbitem $08, $04, $18, $00, TX_FULLWIDTH3, "T" + kbitem $0a, $04, $19, $00, TX_FULLWIDTH3, "&" + kbitem $0c, $04, $1a, $00, "e" + kbitem $10, $0f, $01, $09, $0000 + + kbitem $04, $06, $1b, $00, TX_FULLWIDTH3, "C" + kbitem $06, $06, $1c, $00, TX_FULLWIDTH3, "L" + kbitem $08, $06, $1d, $00, TX_FULLWIDTH3, "U" + kbitem $0a, $06, $1e, $00, "j" + kbitem $0c, $06, $1f, $00, "f" + kbitem $10, $0f, $01, $09, $0000 + + kbitem $04, $08, $20, $00, TX_FULLWIDTH3, "D" + kbitem $06, $08, $21, $00, TX_FULLWIDTH3, "M" + kbitem $08, $08, $22, $00, TX_FULLWIDTH3, "V" + kbitem $0a, $08, $23, $00, "k" + kbitem $0c, $08, $24, $00, "g" + kbitem $10, $0f, $01, $09, $0000 + + kbitem $04, $0a, $25, $00, TX_FULLWIDTH3, "E" + kbitem $06, $0a, $26, $00, TX_FULLWIDTH3, "N" + kbitem $08, $0a, $27, $00, TX_FULLWIDTH3, "W" + kbitem $0a, $0a, $28, $00, "w" + kbitem $0c, $0a, $29, $00, "h" + kbitem $10, $0f, $01, $09, $0000 + + kbitem $04, $0c, $2a, $00, TX_FULLWIDTH3, "F" + kbitem $06, $0c, $2b, $00, TX_FULLWIDTH3, "O" + kbitem $08, $0c, $2c, $00, TX_FULLWIDTH3, "X" + kbitem $0a, $0c, $2d, $00, "`" + kbitem $0c, $0c, $2e, $00, "i" + kbitem $10, $0f, $01, $09, $0000 + + kbitem $04, $0e, $2f, $00, TX_FULLWIDTH3, "G" + kbitem $06, $0e, $30, $00, TX_FULLWIDTH3, "P" + kbitem $08, $0e, $31, $00, TX_FULLWIDTH3, "Y" + kbitem $0a, $0e, $32, $00, "a" + kbitem $0c, $0e, $33, $00, TX_SYMBOL, SYM_No + kbitem $10, $0f, $01, $09, $0000 + + kbitem $04, $10, $34, $00, TX_FULLWIDTH3, "H" + kbitem $06, $10, $35, $00, TX_FULLWIDTH3, "Q" + kbitem $08, $10, $36, $00, TX_FULLWIDTH3, "Z" + kbitem $0a, $10, $3c, $00, "b" + kbitem $0c, $10, $3d, $00, TX_SYMBOL, SYM_Lv + kbitem $10, $0f, $01, $09, $0000 + + kbitem $04, $12, $37, $00, TX_FULLWIDTH3, "I" + kbitem $06, $12, $38, $00, TX_FULLWIDTH3, "R" + kbitem $08, $12, $39, $00, "n" + kbitem $0a, $12, $3a, $00, "c" + kbitem $0c, $12, $3b, $00, "p" + kbitem $10, $0f, $01, $09, $0000 + kbitem $00, $00, $00, $00, $0000 + +; a set of transition datum. +; unit: 4 bytes. +; structure: +; previous char. code (2) / translated char. code (2) +; - the former char. code contains 0x0e in high byte. +; - the latter char. code contains only low byte. +TransitionTable1: + dw $0e16, $003e + dw $0e17, $003f + dw $0e18, $0040 + dw $0e19, $0041 + dw $0e1a, $0042 + dw $0e1b, $0043 + dw $0e1c, $0044 + dw $0e1d, $0045 + dw $0e1e, $0046 + dw $0e1f, $0047 + dw $0e20, $0048 + dw $0e21, $0049 + dw $0e22, $004a + dw $0e23, $004b + dw $0e24, $004c + dw $0e2a, $004d + dw $0e2b, $004e + dw $0e2c, $004f + dw $0e2d, $0050 + dw $0e2e, $0051 + dw $0e52, $004d + dw $0e53, $004e + dw $0e54, $004f + dw $0e55, $0050 + dw $0e56, $0051 + dw $0000 + +TransitionTable2: + dw $0e2a, $0052 + dw $0e2b, $0053 + dw $0e2c, $0054 + dw $0e2d, $0055 + dw $0e2e, $0056 + dw $0e4d, $0052 + dw $0e4e, $0053 + dw $0e4f, $0054 + dw $0e50, $0055 + dw $0e51, $0056 + dw $0000 + +; get deck name from the user into de. +; function description is similar to the player's. +; refer to 'InputPlayerName'. +InputDeckName: + push af + ; check if the buffer is empty. + ld a, [de] + or a + jr nz, .not_empty + ; this buffer will contain half-width chars. + ld a, TX_HALFWIDTH + ld [de], a +.not_empty + pop af + inc a + call InitializeInputName + call Set_OBJ_8x8 + + xor a + ld [wTileMapFill], a + call EmptyScreen + call ZeroObjectPositions + + ld a, $01 + ld [wVBlankOAMCopyToggle], a + call LoadSymbolsFont + + lb de, $38, $bf + call SetupText + call LoadHalfWidthTextCursorTile + + xor a + ld [wd009], a + call Func_1ae99 + + xor a + ld [wNamingScreenCursorX], a + ld [wNamingScreenCursorY], a + + ld a, $09 + ld [wNamingScreenNumColumns], a + ld a, $07 + ld [wNamingScreenKeyboardHeight], a + ld a, $0f + ld [wVisibleCursorTile], a + ld a, $00 + ld [wInvisibleCursorTile], a +.loop + ld a, $01 + ld [wVBlankOAMCopyToggle], a + call DoFrame + + call UpdateRNGSources + + ldh a, [hDPadHeld] + and START + jr z, .on_start + + ld a, $01 + call PlayAcceptOrDeclineSFX + call Func_1afa1 + + ld a, 6 + ld [wNamingScreenCursorX], a + ld [wNamingScreenCursorY], a + call Func_1afbd + + jr .loop +.on_start + call Func_1aefb + jr nc, .loop + + cp $ff + jr z, .asm_6e1c + + call Func_1aec3 + jr nc, .loop + + call FinalizeInputName + + ld hl, wNamingScreenDestPointer + ld a, [hli] + ld h, [hl] + ld l, a + inc hl + + ld a, [hl] + or a + jr nz, .return + + dec hl + ld [hl], TX_END +.return + ret +.asm_6e1c + ld a, [wNamingScreenBufferLength] + cp $02 + jr c, .loop + + ld e, a + ld d, 0 + ld hl, wNamingScreenBuffer + add hl, de + dec hl + ld [hl], TX_END + + ld hl, wNamingScreenBufferLength + dec [hl] + call ProcessTextWithUnderbar + + jp .loop + +; load, to the first tile of v0Tiles0, the graphics for the +; blinking black square used in name input screens. +; for inputting half width text. +LoadHalfWidthTextCursorTile: + ld hl, v0Tiles0 + $00 tiles + ld de, .data + ld b, 0 +.loop + ld a, TILE_SIZE + cp b + ret z + inc b + ld a, [de] + inc de + ld [hli], a + jr .loop + +.data +rept TILE_SIZE + db $f0 +endr + +; it's only for naming the deck. +ProcessTextWithUnderbar: + ld hl, wNamingScreenNamePosition + ld d, [hl] + inc hl + ld e, [hl] + call InitTextPrinting + ld hl, .underbar_data + ld de, wDefaultText +.loop ; copy the underbar string. + ld a, [hli] + ld [de], a + inc de + or a + jr nz, .loop + + ld hl, wNamingScreenBuffer + ld de, wDefaultText +.loop2 ; copy the input from the user. + ld a, [hli] + or a + jr z, .print_name + ld [de], a + inc de + jr .loop2 +.print_name + ld hl, wDefaultText + call ProcessText + ret +.underbar_data + db TX_HALFWIDTH +rept MAX_DECK_NAME_LENGTH + db "_" +endr + db TX_END + +Func_1ae99: + call DrawTextboxForKeyboard + call ProcessTextWithUnderbar + ld hl, wNamingScreenQuestionPointer + ld c, [hl] + inc hl + ld a, [hl] + ld h, a + or c + jr z, .print + ; print the question string. + ld l, c + call PlaceTextItems +.print + ; print "End" + ld hl, DrawNamingScreenBG.data + call PlaceTextItems + ; print the keyboard characters. + ldtx hl, DeckNameKeyboardText ; "A B C D..." + lb de, 2, 4 + call InitTextPrinting + call ProcessTextFromID + call EnableLCD + ret + +Func_1aec3: + ld a, [wNamingScreenCursorX] + ld h, a + ld a, [wNamingScreenCursorY] + ld l, a + call GetCharInfoFromPos_Deck + inc hl + inc hl + ld a, [hl] + cp $01 + jr nz, .asm_6ed7 + scf + ret +.asm_6ed7 + ld d, a + ld hl, wNamingScreenBufferLength + ld a, [hl] + ld c, a + push hl + ld hl, wNamingScreenBufferMaxLength + cp [hl] + pop hl + jr nz, .asm_6eeb + ld hl, wNamingScreenBuffer + dec hl + jr .asm_6eef +.asm_6eeb + inc [hl] + ld hl, wNamingScreenBuffer +.asm_6eef + ld b, 0 + add hl, bc + ld [hl], d + inc hl + ld [hl], TX_END + call ProcessTextWithUnderbar + or a + ret + +Func_1aefb: + xor a + ld [wPlaysSfx], a + ldh a, [hDPadHeld] + or a + jp z, .asm_6f73 + ld b, a + ld a, [wNamingScreenKeyboardHeight] + ld c, a + ld a, [wNamingScreenCursorX] + ld h, a + ld a, [wNamingScreenCursorY] + ld l, a + bit 6, b + jr z, .asm_6f1f + dec a + bit 7, a + jr z, .asm_6f4b + ld a, c + dec a + jr .asm_6f4b +.asm_6f1f + bit 7, b + jr z, .asm_6f2a + inc a + cp c + jr c, .asm_6f4b + xor a + jr .asm_6f4b +.asm_6f2a + cp $06 + jr z, .asm_6f73 + ld a, [wNamingScreenNumColumns] + ld c, a + ld a, h + bit 5, b + jr z, .asm_6f40 + dec a + bit 7, a + jr z, .asm_6f4e + ld a, c + dec a + jr .asm_6f4e +.asm_6f40 + bit 4, b + jr z, .asm_6f73 + inc a + cp c + jr c, .asm_6f4e + xor a + jr .asm_6f4e +.asm_6f4b + ld l, a + jr .asm_6f4f +.asm_6f4e + ld h, a +.asm_6f4f + push hl + call GetCharInfoFromPos_Deck + inc hl + inc hl + ld d, [hl] + push de + call Func_1afa1 + pop de + pop hl + ld a, l + ld [wNamingScreenCursorY], a + ld a, h + ld [wNamingScreenCursorX], a + xor a + ld [wCheckMenuCursorBlinkCounter], a + ld a, $02 + cp d + jp z, Func_1aefb + ld a, $01 + ld [wPlaysSfx], a +.asm_6f73 + ldh a, [hKeysPressed] + and $03 + jr z, .asm_6f89 + and $01 + jr nz, .asm_6f7f + ld a, $ff +.asm_6f7f + call PlayAcceptOrDeclineSFX + push af + call Func_1afbd + pop af + scf + ret +.asm_6f89 + ld a, [wPlaysSfx] + or a + jr z, .asm_6f92 + call PlaySFX +.asm_6f92 + ld hl, wCheckMenuCursorBlinkCounter + ld a, [hl] + inc [hl] + and $0f + ret nz + ld a, [wVisibleCursorTile] + bit 4, [hl] + jr z, Func_1afa1.asm_6fa4 + +Func_1afa1: + ld a, [wInvisibleCursorTile] +.asm_6fa4 + ld e, a + ld a, [wNamingScreenCursorX] + ld h, a + ld a, [wNamingScreenCursorY] + ld l, a + call GetCharInfoFromPos_Deck + ld a, [hli] + ld c, a + ld b, [hl] + dec b + ld a, e + call Func_1afc2 + call WriteByteToBGMap0 + or a + ret + +Func_1afbd: + ld a, [wVisibleCursorTile] + jr Func_1afa1.asm_6fa4 + +Func_1afc2: + push af + push bc + push de + push hl + push af + call ZeroObjectPositions + pop af + ld b, a + ld a, [wInvisibleCursorTile] + cp b + jr z, .asm_6ffb + ld a, [wNamingScreenBufferLength] + ld d, a + ld a, [wNamingScreenBufferMaxLength] + ld e, a + ld a, d + cp e + jr nz, .asm_6fdf + dec a +.asm_6fdf + dec a + ld d, a + ld hl, wNamingScreenNamePosition + ld a, [hl] + sla a + add d + ld d, a + ld h, $04 + ld l, d + call HtimesL + ld a, l + add $08 + ld d, a + ld e, $18 + ld bc, $0000 + call SetOneObjectAttributes +.asm_6ffb + pop hl + pop de + pop bc + pop af + ret + +; given the cursor position, +; returns the character information which the cursor directs. +; it's similar to "GetCharInfoFromPos_Player", +; but the data structure is different in its unit size. +; its unit size is 3, and player's is 6. +; h: x +; l: y +GetCharInfoFromPos_Deck: + push de + ld e, l + ld d, h + ld a, [wNamingScreenKeyboardHeight] + ld l, a + call HtimesL + ld a, l + add e + ; x * h + y + ld hl, KeyboardData_Deck + pop de + or a + ret z +.loop + inc hl + inc hl + inc hl + dec a + jr nz, .loop + ret + +KeyboardData_Deck: + db $04, $02, "A" + db $06, $02, "J" + db $08, $02, "S" + db $0a, $02, "?" + db $0c, $02, "4" + db $0e, $02, $02 + db $10, $0f, $01 + + db $04, $04, "B" + db $06, $04, "K" + db $08, $04, "T" + db $0a, $04, "&" + db $0c, $04, "5" + db $0e, $04, $02 + db $10, $0f, $01 + + db $04, $06, "C" + db $06, $06, "L" + db $08, $06, "U" + db $0a, $06, "+" + db $0c, $06, "6" + db $0e, $06, $02 + db $10, $0f, $01 + + db $04, $08, "D" + db $06, $08, "M" + db $08, $08, "V" + db $0a, $08, "-" + db $0c, $08, "7" + db $0e, $08, $02 + db $10, $0f, $01 + + db $04, $0a, "E" + db $06, $0a, "N" + db $08, $0a, "W" + db $0a, $0a, "'" + db $0c, $0a, "8" + db $0e, $0a, $02 + db $10, $0f, $01 + + db $04, $0c, "F" + db $06, $0c, "O" + db $08, $0c, "X" + db $0a, $0c, "0" + db $0c, $0c, "9" + db $0e, $0c, $02 + db $10, $0f, $01 + + db $04, $0e, "G" + db $06, $0e, "P" + db $08, $0e, "Y" + db $0a, $0e, "1" + db $0c, $0e, " " + db $0e, $0e, $02 + db $10, $0f, $01 + + db $04, $10, "H" + db $06, $10, "Q" + db $08, $10, "Z" + db $0a, $10, "2" + db $0c, $10, " " + db $0e, $10, $02 + db $10, $0f, $01 + + db $04, $12, "I" + db $06, $12, "R" + db $08, $12, "!" + db $0a, $12, "3" + db $0c, $12, " " + db $0e, $12, $02 + db $10, $0f, $01 + + ds 4 ; empty diff --git a/src/engine/link/card_pop.asm b/src/engine/link/card_pop.asm new file mode 100644 index 0000000..5f809ef --- /dev/null +++ b/src/engine/link/card_pop.asm @@ -0,0 +1,399 @@ +_DoCardPop: +; loads scene for Card Pop! screen +; then checks if console is SGB +; and issues an error message in case it is + call SetSpriteAnimationsAsVBlankFunction + ld a,SCENE_CARD_POP + lb bc, 0, 0 + call LoadScene + ldtx hl, AreYouBothReadyToCardPopText + call PrintScrollableText_NoTextBoxLabel + call RestoreVBlankFunction + ldtx hl, CardPopCannotBePlayedWithTheGameBoyText + ld a, [wConsole] + cp CONSOLE_SGB + jr z, .error + +; initiate the communications + call PauseSong + call SetSpriteAnimationsAsVBlankFunction + ld a, SCENE_GAMEBOY_LINK_CONNECTING + lb bc, 0, 0 + call LoadScene + ldtx hl, PositionGameBoyColorsAndPressAButtonText + call DrawWideTextBox_PrintText + call EnableLCD + call HandleCardPopCommunications + push af + push hl + call ClearRP + call RestoreVBlankFunction + pop hl + pop af + jr c, .error + +; show the received card detail page +; and play the corresponding song + ld a, [wLoadedCard1ID] + call AddCardToCollectionAndUpdateAlbumProgress + ld hl, wLoadedCard1Name + ld a, [hli] + ld h, [hl] + ld l, a + call LoadTxRam2 + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + ld a, SFX_5D + call PlaySFX +.wait_sfx + call AssertSFXFinished + or a + jr nz, .wait_sfx + ld a, [wCardPopCardObtainSong] + call PlaySong + ldtx hl, ReceivedThroughCardPopText + bank1call _DisplayCardDetailScreen + call ResumeSong + lb de, $38, $9f + call SetupText + bank1call OpenCardPage_FromHand + ret + +.error +; show Card Pop! error scene +; and print text in hl + push hl + call ResumeSong + call SetSpriteAnimationsAsVBlankFunction + ld a, SCENE_CARD_POP_ERROR + lb bc, 0, 0 + call LoadScene + pop hl + call PrintScrollableText_NoTextBoxLabel + call RestoreVBlankFunction + ret + +; handles all communications to the other device to do Card Pop! +; returns carry if Card Pop! is unsuccessful +; and returns in hl the corresponding error text ID +HandleCardPopCommunications: +; copy CardPopNameList from SRAM to WRAM + call EnableSRAM + ld hl, sCardPopNameList + ld de, wCardPopNameList + ld bc, CARDPOP_NAME_LIST_SIZE + call CopyDataHLtoDE + call DisableSRAM + + ld a, IRPARAM_CARD_POP + call InitIRCommunications +.asm_19cc9 + call TryReceiveIRRequest ; receive request + jr nc, .asm_19d05 + bit 1, a + jr nz, .fail + call TrySendIRRequest ; send request + jr c, .asm_19cc9 + +; do the player name search, then transmit the result + call ExchangeIRCommunicationParameters + jr c, .fail + ld hl, wCardPopNameList + ld de, wOtherPlayerCardPopNameList + ld c, 0 ; $100 bytes = CARDPOP_NAME_LIST_SIZE + call RequestDataTransmissionThroughIR + jr c, .fail + call LookUpNameInCardPopNameList + ld hl, wCardPopNameSearchResult + ld de, wCardPopNameSearchResult + ld c, 1 + call RequestDataReceivalThroughIR + jr c, .fail + call SetIRCommunicationErrorCode_NoError + jr c, .fail + call ExecuteReceivedIRCommands + jr c, .fail + jr .check_search_result + +.asm_19d05 + call ExecuteReceivedIRCommands + ld a, [wIRCommunicationErrorCode] + or a + jr nz, .fail + call RequestCloseIRCommunication + jr c, .fail + +.check_search_result + ld a, [wCardPopNameSearchResult] + or a + jr z, .success + ; not $00, means the name was found in the list + ldtx hl, CannotCardPopWithFriendPreviouslyPoppedWithText + scf + ret + +.success + call DecideCardToReceiveFromCardPop + +; increment number of times Card Pop! was done +; and write the other player's name to sCardPopNameList +; the spot where this is written in the list is derived +; from the lower nybble of sTotalCardPopsDone +; that means that after 16 Card Pop!, the older +; names start to get overwritten + call EnableSRAM + ld hl, sTotalCardPopsDone + ld a, [hl] + inc [hl] + and $0f + swap a ; *NAME_BUFFER_LENGTH + ld l, a + ld h, $0 + ld de, sCardPopNameList + add hl, de + ld de, wNameBuffer + ld c, NAME_BUFFER_LENGTH +.loop_write_name + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .loop_write_name + call DisableSRAM + or a + ret + +.fail + ldtx hl, ThePopWasntSuccessfulText + scf + ret + +; looks up the name in wNameBuffer in wCardPopNameList +; used to know whether this save file has done Card Pop! +; with the other player already +; returns carry and wCardPopNameSearchResult = $ff if the name was found; +; returns no carry and wCardPopNameSearchResult = $00 otherwise +LookUpNameInCardPopNameList: +; searches for other player's name in this game's name list + ld hl, wCardPopNameList + ld c, CARDPOP_NAME_LIST_MAX_ELEMS +.loop_own_card_pop_name_list + push hl + ld de, wNameBuffer + call .CompareNames + pop hl + jr nc, .found_name + ld de, NAME_BUFFER_LENGTH + add hl, de + dec c + jr nz, .loop_own_card_pop_name_list + +; name was not found in wCardPopNameList + +; searches for this player's name in the other game's name list +; this is useless since it discards the result from the name comparisons +; as a result this loop will always return no carry + call EnableSRAM + ld hl, wOtherPlayerCardPopNameList + ld c, CARDPOP_NAME_LIST_MAX_ELEMS +.loop_other_card_pop_name_list + push hl + ld de, sPlayerName + call .CompareNames ; discards result from comparison + pop hl + ld de, NAME_BUFFER_LENGTH + add hl, de + dec c + jr nz, .loop_other_card_pop_name_list + xor a + jr .no_carry + +.found_name + ld a, $ff + scf +.no_carry + call DisableSRAM + ld [wCardPopNameSearchResult], a ; $00 if name was not found, $ff otherwise + ret + +; compares names in hl and de +; if they are different, return carry +.CompareNames + ld b, NAME_BUFFER_LENGTH +.loop_chars + ld a, [de] + inc de + cp [hl] + jr nz, .not_same + inc hl + dec b + jr nz, .loop_chars + or a + ret +.not_same + scf + ret + +; loads in wLoadedCard1 a random card to be received +; this selection is done based on the rarity that is +; decided from the names of both participants +; the card will always be a Pokemon card that is not +; from a Promotional set, with the exception +; of Venusaur1 and Mew2 +; output: +; - e = card ID chosen +DecideCardToReceiveFromCardPop: + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + call EnableSRAM + ld hl, sPlayerName + call CalculateNameHash + call DisableSRAM + push de + ld hl, wNameBuffer + call CalculateNameHash + pop bc + +; de = other player's name hash +; bc = this player's name hash + +; updates RNG values to subtraction of these two hashes + ld hl, wRNG1 + ld a, b + sub d + ld d, a ; b - d + ld [hli], a ; wRNG1 + ld a, c + sub e + ld e, a ; c - e + ld [hli], a ; wRNG2 + ld [hl], $0 ; wRNGCounter + +; depending on the values obtained from the hashes, +; determine which rarity card to give to the player +; along with the song to play with each rarity +; the probabilities of each possibility can be calculated +; as follows (given 2 random player names): +; 101/256 ~ 39% for Circle +; 90/256 ~ 35% for Diamond +; 63/256 ~ 25% for Star +; 1/256 ~ .4% for Venusaur1 or Mew2 + ld a, e + cp 5 + jr z, .venusaur1_or_mew2 + cp 64 + jr c, .star_rarity ; < 64 + cp 154 + jr c, .diamond_rarity ; < 154 + ; >= 154 + + ld a, MUSIC_BOOSTER_PACK + ld b, CIRCLE + jr .got_rarity +.diamond_rarity + ld a, MUSIC_BOOSTER_PACK + ld b, DIAMOND + jr .got_rarity +.star_rarity + ld a, MUSIC_MATCH_VICTORY + ld b, STAR +.got_rarity + ld [wCardPopCardObtainSong], a + ld a, b + call CreateCardPopCandidateList + ; shuffle candidates and pick first from list + call ShuffleCards + ld a, [hl] + ld e, a +.got_card_id + ld d, $0 + call LoadCardDataToBuffer1_FromCardID + ld a, e + ret + +.venusaur1_or_mew2 +; choose either Venusaur1 or Mew2 +; depending on whether the lower +; bit of d is unset or set, respectively + ld a, MUSIC_MEDAL + ld [wCardPopCardObtainSong], a + ld e, VENUSAUR1 + ld a, d + and $1 ; get lower bit + jr z, .got_card_id + ld e, MEW2 + jr .got_card_id + +; lists in wCardPopCardCandidates all cards that: +; - are Pokemon cards; +; - have the same rarity as input register a; +; - are not from Promotional set. +; input: +; - a = card rarity +; output: +; - a = number of candidates +CreateCardPopCandidateList: + ld hl, wPlayerDeck + push hl + push de + push bc + ld b, a + + lb de, 0, GRASS_ENERGY +.loop_card_ids + call LoadCardDataToBuffer1_FromCardID + jr c, .count ; no more card IDs + ld a, [wLoadedCard1Type] + and TYPE_ENERGY + jr nz, .next_card_id ; not Pokemon card + ld a, [wLoadedCard1Rarity] + cp b + jr nz, .next_card_id ; not equal rarity + ld a, [wLoadedCard1Set] + and $f0 + cp PROMOTIONAL + jr z, .next_card_id ; no promos + ld [hl], e + inc hl +.next_card_id + inc de + jr .loop_card_ids + +; count all the cards that were listed +; and return it in a +.count + ld [hl], $00 ; invalid card ID as end of list + ld hl, wPlayerDeck + ld c, -1 +.loop_count + inc c + ld a, [hli] + or a + jr nz, .loop_count + ld a, c + pop bc + pop de + pop hl + ret + +; creates a unique two-byte hash from the name given in hl +; the low byte is calculated by simply adding up all characters +; the high byte is calculated by xoring all characters together +; input: +; - hl = points to the start of the name buffer +; output: +; - de = hash +CalculateNameHash: + ld c, NAME_BUFFER_LENGTH + ld de, $0 +.loop + ld a, e + add [hl] + ld e, a + ld a, d + xor [hl] + ld d, a + inc hl + dec c + jr nz, .loop + ret diff --git a/src/engine/link/ir_core.asm b/src/engine/link/ir_core.asm new file mode 100644 index 0000000..ab9eaae --- /dev/null +++ b/src/engine/link/ir_core.asm @@ -0,0 +1,531 @@ +; if carry flag is set, only delays +; if carry not set: +; - set rRP to $c1, wait; +; - set rRP to $c0, wait; +; - return +Func_19674: + jr c, .delay_once + ld [hl], $c1 + ld a, 5 + jr .loop_delay_1 ; jump to possibly to add more cycles? +.loop_delay_1 + dec a + jr nz, .loop_delay_1 + ld [hl], $c0 + ld a, 14 + jr .loop_delay_2 ; jump to possibly to add more cycles? +.loop_delay_2 + dec a + jr nz, .loop_delay_2 + ret + +.delay_once + ld a, 21 + jr .loop_delay_3 ; jump to possibly to add more cycles? +.loop_delay_3 + dec a + jr nz, .loop_delay_3 + nop + ret + +; input a = byte to transmit through IR +TransmitByteThroughIR: + push hl + ld hl, rRP + push de + push bc + ld b, a + scf ; carry set + call Func_19674 + or a ; carry not set + call Func_19674 + ld c, 8 + ld c, 8 ; number of input bits +.loop + ld a, $00 + rr b + call Func_19674 + dec c + jr nz, .loop + pop bc + pop de + pop hl + ldh a, [rJOYP] + bit 1, a ; P11 + jr z, ReturnZFlagUnsetAndCarryFlagSet + xor a ; return z set + ret + +; same as ReceiveByteThroughIR but +; returns $0 in a if there's an error in IR +ReceiveByteThroughIR_ZeroIfUnsuccessful: + call ReceiveByteThroughIR + ret nc + xor a + ret + +; returns carry if there's some time out +; and output in register a of $ff +; otherwise returns in a some sequence of bits +; related to how rRP sets/unsets bit 1 +ReceiveByteThroughIR: + push de + push bc + push hl + +; waits for bit 1 in rRP to be unset +; up to $100 loops + ld b, 0 + ld hl, rRP +.wait_ir + bit 1, [hl] + jr z, .ok + dec b + jr nz, .wait_ir + ; looped around $100 times + ; return $ff and carry set + pop hl + pop bc + pop de + scf + ld a, $ff + ret + +.ok +; delay for some cycles + ld a, 15 +.loop_delay + dec a + jr nz, .loop_delay + +; loop for each bit + ld e, 8 +.loop + ld a, $01 + ; possibly delay cycles? + ld b, 9 + ld b, 9 + ld b, 9 + ld b, 9 + +; checks for bit 1 in rRP +; if in any of the checks it is unset, +; then a is set to 0 +; this is done a total of 9 times + bit 1, [hl] + jr nz, .asm_196ec + xor a +.asm_196ec + bit 1, [hl] + jr nz, .asm_196f1 + xor a +.asm_196f1 + dec b + jr nz, .asm_196ec + ; one bit received + rrca + rr d + dec e + jr nz, .loop + ld a, d ; has bits set for each "cycle" that bit 1 was not unset + pop hl + pop bc + pop de + or a + ret + +ReturnZFlagUnsetAndCarryFlagSet: + ld a, $ff + or a ; z not set + scf ; carry set + ret + +; called when expecting to transmit data +Func_19705: + ld hl, rRP +.asm_19708 + ldh a, [rJOYP] + bit 1, a + jr z, ReturnZFlagUnsetAndCarryFlagSet + ld a, $aa ; request + call TransmitByteThroughIR + push hl + pop hl + call ReceiveByteThroughIR_ZeroIfUnsuccessful + cp $33 ; acknowledge + jr nz, .asm_19708 + xor a + ret + +; called when expecting to receive data +Func_1971e: + ld hl, rRP +.asm_19721 + ldh a, [rJOYP] + bit 1, a + jr z, ReturnZFlagUnsetAndCarryFlagSet + call ReceiveByteThroughIR_ZeroIfUnsuccessful + cp $aa ; request + jr nz, .asm_19721 + ld a, $33 ; acknowledge + call TransmitByteThroughIR + xor a + ret + +ReturnZFlagUnsetAndCarryFlagSet2: + jp ReturnZFlagUnsetAndCarryFlagSet + +TransmitIRDataBuffer: + call Func_19705 + jr c, ReturnZFlagUnsetAndCarryFlagSet2 + ld a, $49 + call TransmitByteThroughIR + ld a, $52 + call TransmitByteThroughIR + ld hl, wIRDataBuffer + ld c, 8 + jr TransmitNBytesFromHLThroughIR + +ReceiveIRDataBuffer: + call Func_1971e + jr c, ReturnZFlagUnsetAndCarryFlagSet2 + call ReceiveByteThroughIR + cp $49 + jr nz, ReceiveIRDataBuffer + call ReceiveByteThroughIR + cp $52 + jr nz, ReceiveIRDataBuffer + ld hl, wIRDataBuffer + ld c, 8 + jr ReceiveNBytesToHLThroughIR + +; hl = start of data to transmit +; c = number of bytes to transmit +TransmitNBytesFromHLThroughIR: + ld b, $0 +.loop_data_bytes + ld a, b + add [hl] + ld b, a + ld a, [hli] + call TransmitByteThroughIR + jr c, .asm_1977c + dec c + jr nz, .loop_data_bytes + ld a, b + cpl + inc a + call TransmitByteThroughIR +.asm_1977c + ret + +; hl = address to write received data +; c = number of bytes to be received +ReceiveNBytesToHLThroughIR: + ld b, 0 +.loop_data_bytes + call ReceiveByteThroughIR + jr c, ReturnZFlagUnsetAndCarryFlagSet2 + ld [hli], a + add b + ld b, a + dec c + jr nz, .loop_data_bytes + call ReceiveByteThroughIR + add b + or a + jr nz, ReturnZFlagUnsetAndCarryFlagSet2 + ret + +; disables interrupts, and sets joypad and IR communication port +; switches to CGB normal speed +StartIRCommunications: + di + call SwitchToCGBNormalSpeed + ld a, P14 + ldh [rJOYP], a + ld a, $c0 + ldh [rRP], a + ret + +; reenables interrupts, and switches CGB back to double speed +CloseIRCommunications: + ld a, P14 | P15 + ldh [rJOYP], a +.wait_vblank_on + ldh a, [rSTAT] + and STAT_LCDC_STATUS + cp STAT_ON_VBLANK + jr z, .wait_vblank_on +.wait_vblank_off + ldh a, [rSTAT] + and STAT_LCDC_STATUS + cp STAT_ON_VBLANK + jr nz, .wait_vblank_off + call SwitchToCGBDoubleSpeed + ei + ret + +; set rRP to 0 +ClearRP: + ld a, $00 + ldh [rRP], a + ret + +; expects to receive a command (IRCMD_* constant) +; in wIRDataBuffer + 1, then calls the subroutine +; corresponding to that command +ExecuteReceivedIRCommands: + call StartIRCommunications +.loop_commands + call ReceiveIRDataBuffer + jr c, .error + jr nz, .loop_commands + ld hl, wIRDataBuffer + 1 + ld a, [hl] + ld hl, .CmdPointerTable + cp NUM_IR_COMMANDS + jr nc, .loop_commands ; invalid command + call .JumpToCmdPointer ; execute command + jr .loop_commands +.error + call CloseIRCommunications + xor a + scf + ret + +.JumpToCmdPointer + add a ; *2 + add l + ld l, a + ld a, 0 + adc h + ld h, a + ld a, [hli] + ld h, [hl] + ld l, a +.jp_hl + jp hl + +.CmdPointerTable + dw .Close ; IRCMD_CLOSE + dw .ReturnWithoutClosing ; IRCMD_RETURN_WO_CLOSING + dw .TransmitData ; IRCMD_TRANSMIT_DATA + dw .ReceiveData ; IRCMD_RECEIVE_DATA + dw .CallFunction ; IRCMD_CALL_FUNCTION + +; closes the IR communications +; pops hl so that the sp points +; to the return address of ExecuteReceivedIRCommands +.Close + pop hl + call CloseIRCommunications + or a + ret + +; returns without closing the IR communications +; will continue the command loop +.ReturnWithoutClosing + or a + ret + +; receives an address and number of bytes +; and transmits starting at that address +.TransmitData + call Func_19705 + ret c + call LoadRegistersFromIRDataBuffer + jp TransmitNBytesFromHLThroughIR + +; receives an address and number of bytes +; and writes the data received to that address +.ReceiveData + call LoadRegistersFromIRDataBuffer + ld l, e + ld h, d + call ReceiveNBytesToHLThroughIR + jr c, .asm_19812 + sub b + call TransmitByteThroughIR +.asm_19812 + ret + +; receives an address to call, then stores +; the registers in the IR data buffer +.CallFunction + call LoadRegistersFromIRDataBuffer + call .jp_hl + call StoreRegistersInIRDataBuffer + ret + +; returns carry set if request sent was not acknowledged +TrySendIRRequest: + call StartIRCommunications + ld hl, rRP + ld c, 4 +.send_request + ld a, $aa ; request + push bc + call TransmitByteThroughIR + push bc + pop bc + call ReceiveByteThroughIR_ZeroIfUnsuccessful + pop bc + cp $33 ; acknowledgement + jr z, .received_ack + dec c + jr nz, .send_request + scf + jr .close + +.received_ack + xor a +.close + push af + call CloseIRCommunications + pop af + ret + +; returns carry set if request was not received +TryReceiveIRRequest: + call StartIRCommunications + ld hl, rRP +.wait_request + call ReceiveByteThroughIR_ZeroIfUnsuccessful + cp $aa ; request + jr z, .send_ack + ldh a, [rJOYP] + cpl + and P10 | P11 + jr z, .wait_request + scf + jr .close + +.send_ack + ld a, $33 ; acknowledgement + call TransmitByteThroughIR + xor a +.close + push af + call CloseIRCommunications + pop af + ret + +; sends request for other device to close current communication +RequestCloseIRCommunication: + call StartIRCommunications + ld a, IRCMD_CLOSE + ld [wIRDataBuffer + 1], a + call TransmitIRDataBuffer +; fallthrough + +; calls CloseIRCommunications while preserving af +SafelyCloseIRCommunications: + push af + call CloseIRCommunications + pop af + ret + +; sends a request for data to be transmitted +; from the other device +; hl = start of data to request to transmit +; de = address to write data received +; c = length of data +RequestDataTransmissionThroughIR: + ld a, IRCMD_TRANSMIT_DATA + call TransmitRegistersThroughIR + push de + push bc + call Func_1971e + pop bc + pop hl + jr c, SafelyCloseIRCommunications + call ReceiveNBytesToHLThroughIR + jr SafelyCloseIRCommunications + +; transmits data to be written in the other device +; hl = start of data to transmit +; de = address for other device to write data +; c = length of data +RequestDataReceivalThroughIR: + ld a, IRCMD_RECEIVE_DATA + call TransmitRegistersThroughIR + call TransmitNBytesFromHLThroughIR + jr c, SafelyCloseIRCommunications + call ReceiveByteThroughIR + jr c, SafelyCloseIRCommunications + add b + jr nz, .asm_1989e + xor a + jr SafelyCloseIRCommunications +.asm_1989e + call ReturnZFlagUnsetAndCarryFlagSet + jr SafelyCloseIRCommunications + +; first stores all the current registers in wIRDataBuffer +; then transmits it through IR +TransmitRegistersThroughIR: + push hl + push de + push bc + call StoreRegistersInIRDataBuffer + call StartIRCommunications + call TransmitIRDataBuffer + pop bc + pop de + pop hl + ret nc + inc sp + inc sp + jr SafelyCloseIRCommunications + +; stores af, hl, de and bc in wIRDataBuffer +StoreRegistersInIRDataBuffer: + push de + push hl + push af + ld hl, wIRDataBuffer + pop de + ld [hl], e ; <- f + inc hl + ld [hl], d ; <- a + inc hl + pop de + ld [hl], e ; <- l + inc hl + ld [hl], d ; <- h + inc hl + pop de + ld [hl], e ; <- e + inc hl + ld [hl], d ; <- d + inc hl + ld [hl], c ; <- c + inc hl + ld [hl], b ; <- b + ret + +; loads all the registers that were stored +; from StoreRegistersInIRDataBuffer +LoadRegistersFromIRDataBuffer: + ld hl, wIRDataBuffer + ld e, [hl] + inc hl + ld d, [hl] + inc hl + push de + ld e, [hl] + inc hl + ld d, [hl] + inc hl + push de + ld e, [hl] + inc hl + ld d, [hl] + inc hl + ld c, [hl] + inc hl + ld b, [hl] + pop hl + pop af + ret diff --git a/src/engine/link/ir_functions.asm b/src/engine/link/ir_functions.asm new file mode 100644 index 0000000..140dccb --- /dev/null +++ b/src/engine/link/ir_functions.asm @@ -0,0 +1,323 @@ +; hl = text ID +LoadLinkConnectingScene: + push hl + call SetSpriteAnimationsAsVBlankFunction + ld a, SCENE_GAMEBOY_LINK_CONNECTING + lb bc, 0, 0 + call LoadScene + pop hl + call DrawWideTextBox_PrintText + call EnableLCD + ret + +; shows Link Not Connected scene +; then asks the player whether they want to try again +; if the player selects "no", return carry +; input: +; - hl = text ID +LoadLinkNotConnectedSceneAndAskWhetherToTryAgain: + push hl + call RestoreVBlankFunction + call SetSpriteAnimationsAsVBlankFunction + ld a, SCENE_GAMEBOY_LINK_NOT_CONNECTED + lb bc, 0, 0 + call LoadScene + pop hl + call DrawWideTextBox_WaitForInput + ldtx hl, WouldYouLikeToTryAgainText + call YesOrNoMenuWithText_SetCursorToYes +; fallthrough + +ClearRPAndRestoreVBlankFunction: + push af + call ClearRP + call RestoreVBlankFunction + pop af + ret + +; prepares IR communication parameter data +; a = a IRPARAM_* constant for the function of this connection +InitIRCommunications: + ld hl, wOwnIRCommunicationParams + ld [hl], a + inc hl + ld [hl], $50 + inc hl + ld [hl], $4b + inc hl + ld [hl], $31 + ld a, $ff + ld [wIRCommunicationErrorCode], a + ld a, PLAYER_TURN + ldh [hWhoseTurn], a +; clear wNameBuffer and wOpponentName + xor a + ld [wNameBuffer], a + ld hl, wOpponentName + ld [hli], a + ld [hl], a +; loads player's name from SRAM +; to wDefaultText + call EnableSRAM + ld hl, sPlayerName + ld de, wDefaultText + ld c, NAME_BUFFER_LENGTH +.loop + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .loop + call DisableSRAM + ret + +; returns carry if communication was unsuccessful +; if a = 0, then it was a communication error +; if a = 1, then operation was cancelled by the player +PrepareSendCardOrDeckConfigurationThroughIR: + call InitIRCommunications + +; pressing A button triggers request for IR communication +.loop_frame + call DoFrame + ldh a, [hKeysPressed] + bit B_BUTTON_F, a + jr nz, .b_btn + ldh a, [hKeysHeld] + bit A_BUTTON_F, a + jr z, .loop_frame +; a btn + call TrySendIRRequest + jr nc, .request_success + or a + jr z, .loop_frame + xor a + scf + ret + +.b_btn + ; cancelled by the player + ld a, $01 + scf + ret + +.request_success + call ExchangeIRCommunicationParameters + ret c + ld a, [wOtherIRCommunicationParams + 3] + cp $31 + jr nz, SetIRCommunicationErrorCode_Error + or a + ret + +; exchanges player names and IR communication parameters +; checks whether parameters for communication match +; and if they don't, an error is issued +ExchangeIRCommunicationParameters: + ld hl, wOwnIRCommunicationParams + ld de, wOtherIRCommunicationParams + ld c, 4 + call RequestDataTransmissionThroughIR + jr c, .error + ld hl, wOtherIRCommunicationParams + 1 + ld a, [hli] + cp $50 + jr nz, .error + ld a, [hli] + cp $4b + jr nz, .error + ld a, [wOwnIRCommunicationParams] + ld hl, wOtherIRCommunicationParams + cp [hl] ; do parameters match? + jr nz, SetIRCommunicationErrorCode_Error + +; receives wDefaultText from other device +; and writes it to wNameBuffer + ld hl, wDefaultText + ld de, wNameBuffer + ld c, NAME_BUFFER_LENGTH + call RequestDataTransmissionThroughIR + jr c, .error +; transmits wDefaultText to be +; written in wNameBuffer in the other device + ld hl, wDefaultText + ld de, wNameBuffer + ld c, NAME_BUFFER_LENGTH + call RequestDataReceivalThroughIR + jr c, .error + or a + ret + +.error + xor a + scf + ret + +SetIRCommunicationErrorCode_Error: + ld hl, wIRCommunicationErrorCode + ld [hl], $01 + ld de, wIRCommunicationErrorCode + ld c, 1 + call RequestDataReceivalThroughIR + call RequestCloseIRCommunication + ld a, $01 + scf + ret + +SetIRCommunicationErrorCode_NoError: + ld hl, wOwnIRCommunicationParams + ld [hl], $00 + ld de, wIRCommunicationErrorCode + ld c, 1 + call RequestDataReceivalThroughIR + ret c + call RequestCloseIRCommunication + or a + ret + +; makes device receptive to receive data from other device +; to write in wDuelTempList (either list of cards or a deck configuration) +; returns carry if some error occurred +TryReceiveCardOrDeckConfigurationThroughIR: + call InitIRCommunications +.loop_receive_request + xor a + ld [wDuelTempList], a + call TryReceiveIRRequest + jr nc, .receive_data + bit 1, a + jr nz, .cancelled + jr .loop_receive_request +.receive_data + call ExecuteReceivedIRCommands + ld a, [wIRCommunicationErrorCode] + or a + ret z ; no error + xor a + scf + ret + +.cancelled + ld a, $01 + scf + ret + +; returns carry if card(s) wasn't successfully sent +_SendCard: + call StopMusic + ldtx hl, SendingACardText + call LoadLinkConnectingScene + ld a, IRPARAM_SEND_CARDS + call PrepareSendCardOrDeckConfigurationThroughIR + jr c, .fail + + ; send cards + xor a + ld [wDuelTempList + DECK_SIZE], a + ld hl, wDuelTempList + ld e, l + ld d, h + ld c, DECK_SIZE + 1 + call RequestDataReceivalThroughIR + jr c, .fail + call SetIRCommunicationErrorCode_NoError + jr c, .fail + call ExecuteReceivedIRCommands + jr c, .fail + ld a, [wOwnIRCommunicationParams + 1] + cp $4f + jr nz, .fail + call PlayCardPopSong + xor a + call ClearRPAndRestoreVBlankFunction + ret + +.fail + call PlayCardPopSong + ldtx hl, CardTransferWasntSuccessful1Text + call LoadLinkNotConnectedSceneAndAskWhetherToTryAgain + jr nc, _SendCard ; loop back and try again + ; failed + scf + ret + +PlayCardPopSong: + ld a, MUSIC_CARD_POP + jp PlaySong + +_ReceiveCard: + call StopMusic + ldtx hl, ReceivingACardText + call LoadLinkConnectingScene + ld a, IRPARAM_SEND_CARDS + call TryReceiveCardOrDeckConfigurationThroughIR + ld a, $4f + ld [wOwnIRCommunicationParams + 1], a + ld hl, wOwnIRCommunicationParams + ld e, l + ld d, h + ld c, 4 + call RequestDataReceivalThroughIR + jr c, .fail + call RequestCloseIRCommunication + jr c, .fail + call PlayCardPopSong + or a + call ClearRPAndRestoreVBlankFunction + ret + +.fail + call PlayCardPopSong + ldtx hl, CardTransferWasntSuccessful2Text + call LoadLinkNotConnectedSceneAndAskWhetherToTryAgain + jr nc, _ReceiveCard + scf + ret + +_SendDeckConfiguration: + call StopMusic + ldtx hl, SendingADeckConfigurationText + call LoadLinkConnectingScene + ld a, IRPARAM_SEND_DECK + call PrepareSendCardOrDeckConfigurationThroughIR + jr c, .fail + ld hl, wDuelTempList + ld e, l + ld d, h + ld c, DECK_STRUCT_SIZE + call RequestDataReceivalThroughIR + jr c, .fail + call SetIRCommunicationErrorCode_NoError + jr c, .fail + call PlayCardPopSong + call ClearRPAndRestoreVBlankFunction + or a + ret + +.fail + call PlayCardPopSong + ldtx hl, DeckConfigurationTransferWasntSuccessful1Text + call LoadLinkNotConnectedSceneAndAskWhetherToTryAgain + jr nc, _SendDeckConfiguration + scf + ret + +_ReceiveDeckConfiguration: + call StopMusic + ldtx hl, ReceivingDeckConfigurationText + call LoadLinkConnectingScene + ld a, IRPARAM_SEND_DECK + call TryReceiveCardOrDeckConfigurationThroughIR + jr c, .fail + call PlayCardPopSong + call ClearRPAndRestoreVBlankFunction + or a + ret + +.fail + call PlayCardPopSong + ldtx hl, DeckConfigurationTransferWasntSuccessful2Text + call LoadLinkNotConnectedSceneAndAskWhetherToTryAgain + jr nc, _ReceiveDeckConfiguration ; loop back and try again + scf + ret diff --git a/src/engine/link/link_duel.asm b/src/engine/link/link_duel.asm new file mode 100644 index 0000000..fc484d0 --- /dev/null +++ b/src/engine/link/link_duel.asm @@ -0,0 +1,179 @@ +; sets up to start a link duel +; decides which device will pick the number of prizes +; then exchanges names and duels between the players +; and starts the main duel routine +_SetUpAndStartLinkDuel: + ld hl, sp+$00 + ld a, l + ld [wDuelReturnAddress + 0], a + ld a, h + ld [wDuelReturnAddress + 1], a + call SetSpriteAnimationsAsVBlankFunction + + ld a, SCENE_GAMEBOY_LINK_TRANSMITTING + lb bc, 0, 0 + call LoadScene + + bank1call LoadPlayerDeck + call SwitchToCGBNormalSpeed + bank1call DecideLinkDuelVariables + push af + call RestoreVBlankFunction + pop af + jp c, .error + + ld a, DUELIST_TYPE_PLAYER + ld [wPlayerDuelistType], a + ld a, DUELIST_TYPE_LINK_OPP + ld [wOpponentDuelistType], a + ld a, DUELTYPE_LINK + ld [wDuelType], a + + call EmptyScreen + ld a, [wSerialOp] + cp $29 + jr nz, .asm_1a540 + + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + call .ExchangeNamesAndDecks + jr c, .error + lb de, 6, 2 + lb bc, 8, 6 + call DrawRegularTextBox + lb de, 7, 4 + call InitTextPrinting + ldtx hl, PrizesCardsText + call ProcessTextFromID + ldtx hl, ChooseTheNumberOfPrizesText + call DrawWideTextBox_PrintText + call EnableLCD + call .PickNumberOfPrizeCards + ld a, [wNPCDuelPrizes] + call SerialSend8Bytes + jr .prizes_decided + +.asm_1a540 + ld a, OPPONENT_TURN + ldh [hWhoseTurn], a + call .ExchangeNamesAndDecks + jr c, .error + ldtx hl, PleaseWaitDecidingNumberOfPrizesText + call DrawWideTextBox_PrintText + call EnableLCD + call SerialRecv8Bytes + ld [wNPCDuelPrizes], a + +.prizes_decided + call ExchangeRNG + ld a, LINK_OPP_PIC + ld [wOpponentPortrait], a + ldh a, [hWhoseTurn] + push af + call EmptyScreen + bank1call SetDefaultPalettes + ld a, SHUFFLE_DECK + ld [wDuelDisplayedScreen], a + bank1call DrawDuelistPortraitsAndNames + ld a, OPPONENT_TURN + ldh [hWhoseTurn], a + ld a, [wNPCDuelPrizes] + ld l, a + ld h, $00 + call LoadTxRam3 + ldtx hl, BeginAPrizeDuelWithText + call DrawWideTextBox_WaitForInput + pop af + ldh [hWhoseTurn], a + call ExchangeRNG + bank1call StartDuel_VSLinkOpp + call SwitchToCGBDoubleSpeed + ret + +.error + ld a, -1 + ld [wDuelResult], a + call SetSpriteAnimationsAsVBlankFunction + + ld a, SCENE_GAMEBOY_LINK_NOT_CONNECTED + lb bc, 0, 0 + call LoadScene + + ldtx hl, TransmissionErrorText + call DrawWideTextBox_WaitForInput + call RestoreVBlankFunction + call ResetSerial + ret + +.ExchangeNamesAndDecks + ld de, wDefaultText + push de + call CopyPlayerName + pop hl + ld de, wNameBuffer + ld c, NAME_BUFFER_LENGTH + call SerialExchangeBytes + ret c + xor a + ld hl, wOpponentName + ld [hli], a + ld [hl], a + ld hl, wPlayerDeck + ld de, wOpponentDeck + ld c, DECK_SIZE + call SerialExchangeBytes + ret + +; handles player choice of number of prize cards +; pressing left/right makes it decrease/increase respectively +; selection is confirmed by pressing A button +.PickNumberOfPrizeCards + ld a, PRIZES_4 + ld [wNPCDuelPrizes], a + xor a + ld [wPrizeCardSelectionFrameCounter], a +.loop_input + call DoFrame + ld a, [wNPCDuelPrizes] + add SYM_0 + ld e, a + ; check frame counter so that it + ; either blinks or shows number + ld hl, wPrizeCardSelectionFrameCounter + ld a, [hl] + inc [hl] + and $10 + jr z, .no_blink + ld e, SYM_SPACE +.no_blink + ld a, e + lb bc, 9, 6 + call WriteByteToBGMap0 + + ldh a, [hDPadHeld] + ld b, a + ld a, [wNPCDuelPrizes] + bit D_LEFT_F, b + jr z, .check_d_right + dec a + cp PRIZES_2 + jr nc, .got_prize_count + ld a, PRIZES_6 ; wrap around to 6 + jr .got_prize_count + +.check_d_right + bit D_RIGHT_F, b + jr z, .check_a_btn + inc a + cp PRIZES_6 + 1 + jr c, .got_prize_count + ld a, PRIZES_2 +.got_prize_count + ld [wNPCDuelPrizes], a + xor a + ld [wPrizeCardSelectionFrameCounter], a + +.check_a_btn + bit A_BUTTON_F, b + jr z, .loop_input + ret diff --git a/src/engine/link/printer.asm b/src/engine/link/printer.asm new file mode 100644 index 0000000..110fde4 --- /dev/null +++ b/src/engine/link/printer.asm @@ -0,0 +1,1124 @@ +; sends serial data to printer +; if there's an error in connection, +; show Printer Not Connected scene with error message +_PreparePrinterConnection: + ld bc, $0 + lb de, PRINTERPKT_DATA, $0 + call SendPrinterPacket + ret nc ; return if no error + + ld hl, wPrinterStatus + ld a, [hl] + or a + jr nz, .asm_19e55 + ld [hl], $ff +.asm_19e55 + ld a, [hl] + cp $ff + jr z, ShowPrinterIsNotConnected +; fallthrough + +; shows message on screen depending on wPrinterStatus +; also shows SCENE_GAMEBOY_PRINTER_NOT_CONNECTED. +HandlePrinterError: + ld a, [wPrinterStatus] + cp $ff + jr z, .cable_or_printer_switch + or a + jr z, .interrupted + bit PRINTER_ERROR_BATTERIES_LOST_CHARGE, a + jr nz, .batteries_lost_charge + bit PRINTER_ERROR_CABLE_PRINTER_SWITCH, a + jr nz, .cable_or_printer_switch + bit PRINTER_ERROR_PAPER_JAMMED, a + jr nz, .jammed_printer + + ldtx hl, PrinterPacketErrorText + ld a, $04 + jr ShowPrinterConnectionErrorScene +.cable_or_printer_switch + ldtx hl, CheckCableOrPrinterSwitchText + ld a, $02 + jr ShowPrinterConnectionErrorScene +.jammed_printer + ldtx hl, PrinterPaperIsJammedText + ld a, $03 + jr ShowPrinterConnectionErrorScene +.batteries_lost_charge + ldtx hl, BatteriesHaveLostTheirChargeText + ld a, $01 + jr ShowPrinterConnectionErrorScene +.interrupted + ldtx hl, PrintingWasInterruptedText + call DrawWideTextBox_WaitForInput + scf + ret + +ShowPrinterIsNotConnected: + ldtx hl, PrinterIsNotConnectedText + ld a, $02 +; fallthrough + +; a = error code +; hl = text ID to print in text box +ShowPrinterConnectionErrorScene: + push hl + ; unnecessary loading TxRam, since the text data + ; already incorporate the error number + ld l, a + ld h, $00 + call LoadTxRam3 + + call SetSpriteAnimationsAsVBlankFunction + ld a, SCENE_GAMEBOY_PRINTER_NOT_CONNECTED + lb bc, 0, 0 + call LoadScene + pop hl + call DrawWideTextBox_WaitForInput + call RestoreVBlankFunction + scf + ret + +; main card printer function +Func_19eb4: + ld e, a + ld d, $0 + call LoadCardDataToBuffer1_FromCardID + call SetSpriteAnimationsAsVBlankFunction + ld a, SCENE_GAMEBOY_PRINTER_TRANSMITTING + lb bc, 0, 0 + call LoadScene + ld a, 20 + call CopyCardNameAndLevel + ld [hl], TX_END + ld hl, $0 + call LoadTxRam2 + ldtx hl, NowPrintingText + call DrawWideTextBox_PrintText + call EnableLCD + call PrepareForPrinterCommunications + call DrawTopCardInfoInSRAMGfxBuffer0 + call Func_19f87 + call DrawCardPicInSRAMGfxBuffer2 + call Func_19f99 + jr c, .error + call DrawBottomCardInfoInSRAMGfxBuffer0 + call Func_1a011 + jr c, .error + call RestoreVBlankFunction + call ResetPrinterCommunicationSettings + or a + ret +.error + call RestoreVBlankFunction + call ResetPrinterCommunicationSettings + jp HandlePrinterError + +DrawCardPicInSRAMGfxBuffer2: + ld hl, wLoadedCard1Gfx + ld a, [hli] + ld h, [hl] + ld l, a + ld de, sGfxBuffer2 + call Func_37a5 + ; draw card's picture in sGfxBuffer2 + ld a, $40 + lb hl, 12, 1 + lb de, 2, 68 + lb bc, 16, 12 + call FillRectangle + ret + +; writes the tiles necessary to draw +; the card's information in sGfxBuffer0 +; this includes card's type, lv, HP and attacks if Pokemon card +; or otherwise just the card's name and type symbol +DrawTopCardInfoInSRAMGfxBuffer0: + call Func_1a025 + call Func_212f + + ; draw empty text box frame + ld hl, sGfxBuffer0 + ld a, $34 + lb de, $30, $31 + ld b, 20 + call CopyLine + ld c, 15 +.loop_lines + xor a ; SYM_SPACE + lb de, $36, $37 + ld b, 20 + call CopyLine + dec c + jr nz, .loop_lines + + ; draw card type symbol + ld a, $38 + lb hl, 1, 2 + lb de, 1, 65 + lb bc, 2, 2 + call FillRectangle + ; print card's name + lb de, 4, 65 + ld hl, wLoadedCard1Name + call InitTextPrinting_ProcessTextFromPointerToID + +; prints card's type, lv, HP and attacks if it's a Pokemon card + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr nc, .skip_pokemon_data + inc a ; symbol corresponding to card's type (color) + lb bc, 18, 65 + call WriteByteToBGMap0 + ld a, SYM_Lv + lb bc, 11, 66 + call WriteByteToBGMap0 + ld a, [wLoadedCard1Level] + lb bc, 12, 66 + bank1call WriteTwoDigitNumberInTxSymbolFormat + ld a, SYM_HP + lb bc, 15, 66 + call WriteByteToBGMap0 + ld a, [wLoadedCard1EffectCommands] + inc b + bank1call WriteTwoByteNumberInTxSymbolFormat +.skip_pokemon_data + ret + +Func_19f87: + call TryInitPrinterCommunications + ret c + ld hl, sGfxBuffer0 + call Func_1a0cc + ret c + call Func_1a0cc + call Func_1a111 + ret + +Func_19f99: + call TryInitPrinterCommunications + ret c + ld hl, sGfxBuffer0 + $8 tiles + ld c, $06 +.asm_19fa2 + call Func_1a0cc + ret c + dec c + jr nz, .asm_19fa2 + call Func_1a111 + ret + +; writes the tiles necessary to draw +; the card's information in sGfxBuffer0 +; this includes card's Retreat cost, Weakness, Resistance, +; and attack if it's Pokemon card +; or otherwise just the card's description. +DrawBottomCardInfoInSRAMGfxBuffer0: + call Func_1a025 + xor a + ld [wCardPageType], a + ld hl, sGfxBuffer0 + ld b, 20 + ld c, 9 +.loop_lines + xor a ; SYM_SPACE + lb de, $36, $37 + call CopyLine + dec c + jr nz, .loop_lines + ld a, $35 + lb de, $32, $33 + call CopyLine + + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr nc, .not_pkmn_card + ld hl, RetreatWeakResistData + call PlaceTextItems + ld c, 66 + bank1call DisplayCardPage_PokemonOverview.attacks + ld a, SYM_No + lb bc, 15, 72 + call WriteByteToBGMap0 + inc b + ld a, [wLoadedCard1PokedexNumber] + bank1call WriteTwoByteNumberInTxSymbolFormat + ret + +.not_pkmn_card + bank1call SetNoLineSeparation + lb de, 1, 66 + ld a, SYM_No + call InitTextPrintingInTextbox + ld hl, wLoadedCard1NonPokemonDescription + call ProcessTextFromPointerToID + bank1call SetOneLineSeparation + ret + +RetreatWeakResistData: + textitem 1, 70, RetreatText + textitem 1, 71, WeaknessText + textitem 1, 72, ResistanceText + db $ff + +Func_1a011: + call TryInitPrinterCommunications + ret c + ld hl, sGfxBuffer0 + ld c, $05 +.asm_1a01a + call Func_1a0cc + ret c + dec c + jr nz, .asm_1a01a + call Func_1a108 + ret + +; calls setup text and sets wTilePatternSelector +Func_1a025: + lb de, $40, $bf + call SetupText + ld a, $a4 + ld [wTilePatternSelector], a + xor a + ld [wTilePatternSelectorCorrection], a + ret + +; switches to CGB normal speed, resets serial +; enables SRAM and switches to SRAM1 +; and clears sGfxBuffer0 +PrepareForPrinterCommunications: + call SwitchToCGBNormalSpeed + call ResetSerial + ld a, $10 + ld [wce9b], a + call EnableSRAM + ld a, [sPrinterContrastLevel] + ld [wPrinterContrastLevel], a + call DisableSRAM + ldh a, [hBankSRAM] + ld [wce8f], a + ld a, BANK("SRAM1") + call BankswitchSRAM + call EnableSRAM +; fallthrough + +ClearPrinterGfxBuffer: + ld hl, sGfxBuffer0 + ld bc, $400 +.loop + xor a + ld [hli], a + dec bc + ld a, c + or b + jr nz, .loop + xor a + ld [wce9f], a + ret + +; reverts settings changed by PrepareForPrinterCommunications +ResetPrinterCommunicationSettings: + push af + call SwitchToCGBDoubleSpeed + ld a, [wce8f] + call BankswitchSRAM + call DisableSRAM + lb de, $30, $bf + call SetupText + pop af + ret + +; send some bytes through serial +Func_1a080: ; unreferenced + ld bc, $0 + lb de, PRINTERPKT_NUL, $0 + jp SendPrinterPacket + +; tries initiating the communications for +; sending data to printer +; returns carry if operation was cancelled +; by pressing B button or serial transfer took long +TryInitPrinterCommunications: + xor a + ld [wPrinterInitAttempts], a +.wait_input + call DoFrame + ldh a, [hKeysHeld] + and B_BUTTON + jr nz, .b_button + ld bc, $0 + lb de, PRINTERPKT_NUL, $0 + call SendPrinterPacket + jr c, .delay + and (1 << PRINTER_STATUS_BUSY) | (1 << PRINTER_STATUS_PRINTING) + jr nz, .wait_input + +.init + ld bc, $0 + lb de, PRINTERPKT_INIT, $0 + call SendPrinterPacket + jr nc, .no_carry + ld hl, wPrinterInitAttempts + inc [hl] + ld a, [hl] + cp 3 + jr c, .wait_input + ; time out + scf + ret +.no_carry + ret + +.b_button + xor a + ld [wPrinterStatus], a + scf + ret + +.delay + ld c, 10 +.delay_loop + call DoFrame + dec c + jr nz, .delay_loop + jr .init + +; loads tiles given by map in hl to sGfxBuffer5 +; copies first 20 tiles, then offsets by 2 tiles +; and copies another 20 +Func_1a0cc: + push bc + ld de, sGfxBuffer5 + call .Copy20Tiles + call .Copy20Tiles + push hl + call CompressDataForPrinterSerialTransfer + call SendPrinterPacket + pop hl + pop bc + ret + +; copies 20 tiles given by hl to de +; then adds 2 tiles to hl +.Copy20Tiles ; 1a0e0 (6:60e0) + push hl + ld c, 20 +.loop_tiles + ld a, [hli] + call .CopyTile + dec c + jr nz, .loop_tiles + pop hl + ld bc, 2 tiles + add hl, bc + ret + +; copies a tile to de +; a = tile to get from sGfxBuffer1 +.CopyTile ; 1a0f0 (6:60f0) + push hl + push bc + ld l, a + ld h, $00 + add hl, hl + add hl, hl + add hl, hl + add hl, hl ; *TILE_SIZE + ld bc, sGfxBuffer1 + add hl, bc + ld c, TILE_SIZE +.loop_copy + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .loop_copy + pop bc + pop hl + ret + +Func_1a108: + call GetPrinterContrastSerialData + push hl + lb hl, $3, $1 + jr SendPrinterInstructionPacket + +Func_1a111: + call GetPrinterContrastSerialData + push hl + ld hl, wce9b + ld a, [hl] + ld [hl], $00 + ld h, a + ld l, $01 +; fallthrough + +SendPrinterInstructionPacket: + push hl + ld bc, $0 + lb de, PRINTERPKT_DATA, $0 + call SendPrinterPacket + jr c, .asm_1a135 + ld hl, sp+$00 ; contrast level bytes + ld bc, $4 ; instruction packets are 4 bytes in size + lb de, PRINTERPKT_PRINT_INSTRUCTION, $0 + call SendPrinterPacket +.asm_1a135 + pop hl + pop hl + ret + +; returns in h and l the bytes +; to be sent through serial to the printer +; for the set contrast level +GetPrinterContrastSerialData: + ld a, [wPrinterContrastLevel] + ld e, a + ld d, $00 + ld hl, .contrast_level_data + add hl, de + ld h, [hl] + ld l, $e4 + ret + +.contrast_level_data + db $00, $20, $40, $60, $7f + +Func_1a14b: ; unreferenced + ld a, $01 + jr .asm_1a15d + ld a, $02 + jr .asm_1a15d + ld a, $03 + jr .asm_1a15d + ld a, $04 + jr .asm_1a15d + ld a, $05 +.asm_1a15d + ld [wce9d], a + scf + ret + +; a = saved deck index to print +_PrintDeckConfiguration: +; copies selected deck from SRAM to wDuelTempList + call EnableSRAM + ld l, a + ld h, DECK_STRUCT_SIZE + call HtimesL + ld de, sSavedDeck1 + add hl, de + ld de, wDuelTempList + ld bc, DECK_STRUCT_SIZE + call CopyDataHLtoDE + call DisableSRAM + + call ShowPrinterTransmitting + call PrepareForPrinterCommunications + call Func_1a025 + call Func_212f + lb de, 0, 64 + lb bc, 20, 4 + call DrawRegularTextBoxDMG + lb de, 4, 66 + call InitTextPrinting + ld hl, wDuelTempList ; print deck name + call ProcessText + ldtx hl, DeckPrinterText + call ProcessTextFromID + + ld a, 5 + ld [wPrinterHorizontalOffset], a + ld hl, wPrinterTotalCardCount + xor a + ld [hli], a + ld [hl], a + ld [wPrintOnlyStarRarity], a + + ld hl, wCurDeckCards +.loop_cards + ld a, [hl] + or a + jr z, .asm_1a1d6 + ld e, a + ld d, $00 + call LoadCardDataToBuffer1_FromCardID + + ; find out this card's count + ld a, [hli] + ld b, a + ld c, 1 +.loop_card_count + cp [hl] + jr nz, .got_card_count + inc hl + inc c + jr .loop_card_count + +.got_card_count + ld a, c + ld [wPrinterCardCount], a + call LoadCardInfoForPrinter + call AddToPrinterGfxBuffer + jr c, .printer_error + jr .loop_cards + +.asm_1a1d6 + call SendCardListToPrinter + jr c, .printer_error + call ResetPrinterCommunicationSettings + call RestoreVBlankFunction + or a + ret + +.printer_error + call ResetPrinterCommunicationSettings + call RestoreVBlankFunction + jp HandlePrinterError + +SendCardListToPrinter: + ld a, [wPrinterHorizontalOffset] + cp 1 + jr z, .skip_load_gfx + call LoadGfxBufferForPrinter + ret c +.skip_load_gfx + call TryInitPrinterCommunications + ret c + call Func_1a108 + ret +; 0z1a1ff + +; increases printer horizontal offset by 2 +AddToPrinterGfxBuffer: + push hl + ld hl, wPrinterHorizontalOffset + inc [hl] + inc [hl] + ld a, [hl] + pop hl + ; return no carry if below 18 + cp 18 + ccf + ret nc + ; >= 18 +; fallthrough + +; copies Gfx to Gfx buffer and sends some serial data +; returns carry set if unsuccessful +LoadGfxBufferForPrinter: + push hl + call TryInitPrinterCommunications + jr c, .set_carry + ld a, [wPrinterHorizontalOffset] + srl a + ld c, a + ld hl, sGfxBuffer0 +.loop_gfx_buffer + call Func_1a0cc + jr c, .set_carry + dec c + jr nz, .loop_gfx_buffer + call Func_1a111 + jr c, .set_carry + + call ClearPrinterGfxBuffer + ld a, 1 + ld [wPrinterHorizontalOffset], a + pop hl + or a + ret + +.set_carry + pop hl + scf + ret + +; load symbol, name, level and card count to buffer +LoadCardInfoForPrinter: + push hl + ld a, [wPrinterHorizontalOffset] + or %1000000 + ld e, a + ld d, 3 + ld a, [wPrintOnlyStarRarity] + or a + jr nz, .skip_card_symbol + ld hl, wPrinterTotalCardCount + ld a, [hli] + or [hl] + call z, DrawCardSymbol +.skip_card_symbol + ld a, 14 + call CopyCardNameAndLevel + call InitTextPrinting + ld hl, wDefaultText + call ProcessText + ld a, [wPrinterHorizontalOffset] + or %1000000 + ld c, a + ld b, 16 + ld a, SYM_CROSS + call WriteByteToBGMap0 + inc b + ld a, [wPrinterCardCount] + bank1call WriteTwoDigitNumberInTxSymbolFormat + pop hl + ret + +_PrintCardList: +; if Select button is held when printing card list +; only print cards with Star rarity (excluding Promotional cards) +; even if it's not marked as seen in the collection + ld e, FALSE + ldh a, [hKeysHeld] + and SELECT + jr z, .no_select + inc e ; TRUE +.no_select + ld a, e + ld [wPrintOnlyStarRarity], a + + call ShowPrinterTransmitting + call CreateTempCardCollection + ld de, wDefaultText + call CopyPlayerName + call PrepareForPrinterCommunications + call Func_1a025 + call Func_212f + + lb de, 0, 64 + lb bc, 20, 4 + call DrawRegularTextBoxDMG + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + lb de, 2, 66 + call InitTextPrinting + ld hl, wDefaultText + call ProcessText + ldtx hl, AllCardsOwnedText + call ProcessTextFromID + ld a, [wPrintOnlyStarRarity] + or a + jr z, .asm_1a2c2 + ld a, TX_HALF2FULL + call ProcessSpecialTextCharacter + lb de, 3, 84 + call Func_22ca +.asm_1a2c2 + ld a, $ff + ld [wCurPrinterCardType], a + xor a + ld hl, wPrinterTotalCardCount + ld [hli], a + ld [hl], a + ld [wPrinterNumCardTypes], a + ld a, 5 + ld [wPrinterHorizontalOffset], a + + ld e, GRASS_ENERGY +.loop_cards + push de + ld d, $00 + call LoadCardDataToBuffer1_FromCardID + jr c, .done_card_loop + ld d, HIGH(wTempCardCollection) + ld a, [de] ; card ID count in collection + ld [wPrinterCardCount], a + call .LoadCardTypeEntry + jr c, .printer_error_pop_de + + ld a, [wPrintOnlyStarRarity] + or a + jr z, .all_owned_cards_mode + ld a, [wLoadedCard1Set] + and %11110000 + cp PROMOTIONAL + jr z, .next_card + ld a, [wLoadedCard1Rarity] + cp STAR + jr nz, .next_card + ; not Promotional, and Star rarity + ld hl, wPrinterCardCount + res CARD_NOT_OWNED_F, [hl] + jr .got_card_count + +.all_owned_cards_mode + ld a, [wPrinterCardCount] + or a + jr z, .next_card + cp CARD_NOT_OWNED + jr z, .next_card ; ignore not owned cards + +.got_card_count + ld a, [wPrinterCardCount] + and CARD_COUNT_MASK + ld c, a + + ; add to total card count + ld hl, wPrinterTotalCardCount + add [hl] + ld [hli], a + ld a, 0 + adc [hl] + ld [hl], a + + ; add to current card type count + ld hl, wPrinterCurCardTypeCount + ld a, c + add [hl] + ld [hli], a + ld a, 0 + adc [hl] + ld [hl], a + + ld hl, wPrinterNumCardTypes + inc [hl] + ld hl, wce98 + inc [hl] + call LoadCardInfoForPrinter + call AddToPrinterGfxBuffer + jr c, .printer_error_pop_de +.next_card + pop de + inc e + jr .loop_cards + +.printer_error_pop_de + pop de +.printer_error + call ResetPrinterCommunicationSettings + call RestoreVBlankFunction + jp HandlePrinterError + +.done_card_loop + pop de + ; add separator line + ld a, [wPrinterHorizontalOffset] + dec a + or $40 + ld c, a + ld b, 0 + call BCCoordToBGMap0Address + ld a, $35 + lb de, $35, $35 + ld b, 20 + call CopyLine + call AddToPrinterGfxBuffer + jr c, .printer_error + + ld hl, wPrinterTotalCardCount + ld c, [hl] + inc hl + ld b, [hl] + ldtx hl, TotalNumberOfCardsText + call .PrintTextWithNumber + jr c, .printer_error + ld a, [wPrintOnlyStarRarity] + or a + jr nz, .done + ld a, [wPrinterNumCardTypes] + ld c, a + ld b, 0 + ldtx hl, TypesOfCardsText + call .PrintTextWithNumber + jr c, .printer_error + +.done + call SendCardListToPrinter + jr c, .printer_error + call ResetPrinterCommunicationSettings + call RestoreVBlankFunction + or a + ret + +; prints text ID given in hl +; with decimal representation of +; the number given in bc +; hl = text ID +; bc = number +.PrintTextWithNumber + push bc + ld a, [wPrinterHorizontalOffset] + dec a + or $40 + ld e, a + ld d, 2 + call InitTextPrinting + call ProcessTextFromID + ld d, 14 + call InitTextPrinting + pop hl + call TwoByteNumberToTxSymbol_TrimLeadingZeros + ld hl, wStringBuffer + call ProcessText + call AddToPrinterGfxBuffer + ret + +; loads this card's type icon and text +; if it's a new card type that hasn't been printed yet +.LoadCardTypeEntry + ld a, [wLoadedCard1Type] + ld c, a + cp TYPE_ENERGY + jr c, .got_type ; jump if Pokemon card + ld c, $08 + cp TYPE_TRAINER + jr nc, .got_type ; jump if Trainer card + ld c, $07 +.got_type + ld hl, wCurPrinterCardType + ld a, [hl] + cp c + ret z ; already handled this card type + + ; show corresponding icon and text + ; for this new card type + ld a, c + ld [hl], a ; set it as current card type + add a + add c ; *3 + ld c, a + ld b, $00 + ld hl, .IconTextList + add hl, bc + ld a, [wPrinterHorizontalOffset] + dec a + or %1000000 + ld e, a + ld d, 1 + ld a, [hli] + push hl + lb bc, 2, 2 + lb hl, 1, 2 + call FillRectangle + pop hl + ld d, 3 + inc e + call InitTextPrinting + ld a, [hli] + ld h, [hl] + ld l, a + call ProcessTextFromID + + call AddToPrinterGfxBuffer + ld hl, wPrinterCurCardTypeCount + xor a + ld [hli], a + ld [hl], a + ld [wce98], a + ret + +.IconTextList + ; Fire + db $e0 ; icon tile + tx FirePokemonText + + ; Grass + db $e4 ; icon tile + tx GrassPokemonText + + ; Lightning + db $e8 ; icon tile + tx LightningPokemonText + + ; Water + db $ec ; icon tile + tx WaterPokemonText + + ; Fighting + db $f0 ; icon tile + tx FightingPokemonText + + ; Psychic + db $f4 ; icon tile + tx PsychicPokemonText + + ; Colorless + db $f8 ; icon tile + tx ColorlessPokemonText + + ; Energy + db $fc ; icon tile + tx EnergyCardText + + ; Trainer + db $dc ; icon tile + tx TrainerCardText + +ShowPrinterTransmitting: + call SetSpriteAnimationsAsVBlankFunction + ld a, SCENE_GAMEBOY_PRINTER_TRANSMITTING + lb bc, 0, 0 + call LoadScene + ldtx hl, NowPrintingPleaseWaitText + call DrawWideTextBox_PrintText + call EnableLCD + ret + +; compresses $28 tiles in sGfxBuffer5 +; and writes it in sGfxBuffer5 + $28 tiles. +; compressed data has 2 commands to instruct on how to decompress it. +; - a command byte with bit 7 not set, means to copy that many + 1 +; bytes that are following it literally. +; - a command byte with bit 7 set, means to copy the following byte +; that many times + 2 (after masking the top bit of command byte). +; returns in bc the size of the compressed data and +; in de the packet type data. +CompressDataForPrinterSerialTransfer: + ld hl, sGfxBuffer5 + ld de, sGfxBuffer5 + $28 tiles + ld bc, $28 tiles +.loop_remaining_data + ld a, $ff + inc b + dec b + jr nz, .check_compression + ld a, c +.check_compression + push bc + push de + ld c, a + call CheckDataCompression + ld a, e + ld c, e + pop de + jr c, .copy_byte + ld a, c + ld b, c + dec a + ld [de], a ; number of bytes to copy literally - 1 + inc de +.copy_literal_sequence + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .copy_literal_sequence + ld c, b + jr .sub_added_bytes + +.copy_byte + ld a, c + dec a + dec a + or %10000000 ; set high bit + ld [de], a ; = (n times to copy - 2) | %10000000 + inc de + ld a, [hl] ; byte to copy n times + ld [de], a + inc de + ld b, $0 + add hl, bc + +.sub_added_bytes + ld a, c + cpl + inc a + pop bc + add c + ld c, a + ld a, $ff + adc b + ld b, a + or c + jr nz, .loop_remaining_data + + ld hl, $10000 - (sGfxBuffer5 + $28 tiles) + add hl, de ; gets the size of the compressed data + ld c, l + ld b, h + ld hl, sGfxBuffer5 + $28 tiles + lb de, PRINTERPKT_DATA, $1 + ret + +; checks whether the next byte sequence in hl, up to c bytes, can be compressed +; returns carry if the next sequence of bytes can be compressed, +; i.e. has at least 3 consecutive bytes with the same value. +; in that case, returns in e the number of consecutive +; same value bytes that were found. +; if there are no bytes with same value, then count as many bytes left +; as possible until either there are no more remaining data bytes, +; or until a sequence of 3 bytes with the same value are found. +; in that case, the number of bytes in this sequence is returned in e. +CheckDataCompression: + push hl + ld e, c + ld a, c +; if number of remaining bytes is less than 4 +; then no point in compressing + cp 4 + jr c, .no_carry + +; check first if there are at least +; 3 consecutive bytes with the same value + ld b, c + ld a, [hli] + cp [hl] + inc hl + jr nz, .literal_copy ; not same + cp [hl] + inc hl + jr nz, .literal_copy ; not same + +; 3 consecutive bytes were found with same value +; keep track of how many consecutive bytes +; with the same value there are in e + dec c + dec c + dec c + ld e, 3 +.loop_same_value + cp [hl] + jr nz, .set_carry ; exit when a different byte is found + inc hl + inc e + dec c + jr z, .set_carry ; exit when there is no more remaining data + bit 5, e + ; exit if number of consecutive bytes >= $20 + jr z, .loop_same_value +.set_carry + pop hl + scf + ret + +.literal_copy +; consecutive bytes are not the same value +; count the number of bytes there are left +; until a sequence of 3 bytes with the same value is found + pop hl + push hl + ld c, b ; number of remaining bytes + ld e, 1 + ld a, [hli] + dec c + jr z, .no_carry ; exit if no more data +.reset_same_value_count + ld d, 2 ; number of consecutive same value bytes to exit +.next_byte + inc e + dec c + jr z, .no_carry + bit 7, e + jr nz, .no_carry ; exit if >= $80 + cp [hl] + jr z, .same_consecutive_value + ld a, [hli] + jr .reset_same_value_count +.no_carry + pop hl + or a + ret + +.same_consecutive_value + inc hl + dec d + jr nz, .next_byte + ; 3 consecutive bytes with same value found + ; discard the last 3 bytes in the sequence + dec e + dec e + dec e + jr .no_carry 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/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 diff --git a/src/engine/promotional_card.asm b/src/engine/promotional_card.asm new file mode 100644 index 0000000..bb3250a --- /dev/null +++ b/src/engine/promotional_card.asm @@ -0,0 +1,61 @@ +; shows screen with the promotional card and received text +; depending on input a +; if $0 = Legendary Molters, Articuno, Zapdos and Dragonite cards +; otherwise, a card ID +_ShowPromotionalCardScreen: + push af + lb de, $38, $9f + call SetupText + pop af + or a + jr nz, .else + ld a, MOLTRES2 + call .legendary_card_text + ld a, ARTICUNO2 + call .legendary_card_text + ld a, ZAPDOS3 + call .legendary_card_text + ld a, DRAGONITE1 +.legendary_card_text + ldtx hl, ReceivedLegendaryCardText + jr .print_text +.else + ldtx hl, ReceivedCardText + cp VILEPLUME + jr z, .print_text + cp BLASTOISE + jr z, .print_text + ldtx hl, ReceivedPromotionalFlyingPikachuText + cp FLYING_PIKACHU + jr z, .print_text + ldtx hl, ReceivedPromotionalSurfingPikachuText + cp SURFING_PIKACHU1 + jr z, .print_text + cp SURFING_PIKACHU2 + jr z, .print_text + ldtx hl, ReceivedPromotionalCardText +.print_text + push hl + ld e, a + ld d, $0 + call LoadCardDataToBuffer1_FromCardID + call PauseSong + ld a, MUSIC_MEDAL + call PlaySong + ld hl, wLoadedCard1Name + ld a, [hli] + ld h, [hl] + ld l, a + bank1call LoadTxRam2 ; switch to bank 1, but call a home func + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + pop hl + bank1call _DisplayCardDetailScreen +.loop + call AssertSongFinished + or a + jr nz, .loop + + call ResumeSong + bank1call OpenCardPage_FromHand + ret diff --git a/src/engine/sprite_vblank.asm b/src/engine/sprite_vblank.asm new file mode 100644 index 0000000..5f099a1 --- /dev/null +++ b/src/engine/sprite_vblank.asm @@ -0,0 +1,39 @@ +; empties screen and replaces +; wVBlankFunctionTrampoline with HandleAllSpriteAnimations +SetSpriteAnimationsAsVBlankFunction: + call EmptyScreen + call Set_OBJ_8x8 + call Func_3ca4 + lb de, $38, $7f + call SetupText + ld hl, wVBlankFunctionTrampoline + 1 + ld de, wVBlankFunctionTrampolineBackup + call BackupVBlankFunctionTrampoline + di + ld [hl], LOW(HandleAllSpriteAnimations) + inc hl + ld [hl], HIGH(HandleAllSpriteAnimations) + ei + ret + +; sets backup VBlank function as wVBlankFunctionTrampoline +RestoreVBlankFunction: + ld hl, wVBlankFunctionTrampolineBackup + ld de, wVBlankFunctionTrampoline + 1 + call BackupVBlankFunctionTrampoline + call Func_3ca4 + bank1call ZeroObjectPositionsAndToggleOAMCopy + ret + +; copies 2 bytes from hl to de while interrupts are disabled +; used to load or store wVBlankFunctionTrampoline +; to wVBlankFunctionTrampolineBackup +BackupVBlankFunctionTrampoline: + di + ld a, [hli] + ld [de], a + inc de + ld a, [hld] + ld [de], a + ei + ret diff --git a/src/engine/starter_deck.asm b/src/engine/starter_deck.asm new file mode 100644 index 0000000..0500b4a --- /dev/null +++ b/src/engine/starter_deck.asm @@ -0,0 +1,182 @@ +; adds the chosen starter deck to the player's first deck configuration +; and also adds to the collection its corresponding extra cards +; input: +; - a = starter deck chosen +; $0 = Charmander +; $1 = Squirtle +; $2 = Bulbasaur +_AddStarterDeck: + add a + ld e, a + ld d, 0 + ld hl, .StarterCardIDs + add hl, de + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + ld a, [hli] ; main deck + add 2 + push hl + ld hl, sDeck1 + call CopyDeckNameAndCards + pop hl + call SwapTurn + ld a, [hli] ; extra deck + add 2 + call LoadDeck + call SwapTurn + +; wPlayerDeck = main starter deck +; wOpponentDeck = extra cards + call EnableSRAM + ld h, HIGH(sCardCollection) + ld de, wPlayerDeck + ld c, DECK_SIZE +.loop_main_cards + ld a, [de] + inc de + ld l, a + res CARD_NOT_OWNED_F, [hl] + dec c + jr nz, .loop_main_cards + + ld h, HIGH(sCardCollection) + ld de, wOpponentDeck + ld c, 30 ; number of extra cards +.loop_extra_cards + ld a, [de] + inc de + ld l, a + res CARD_NOT_OWNED_F, [hl] + inc [hl] + dec c + jr nz, .loop_extra_cards + call DisableSRAM + ret + +.StarterCardIDs + ; main deck, extra cards + db CHARMANDER_AND_FRIENDS_DECK_ID, CHARMANDER_EXTRA_DECK_ID + db SQUIRTLE_AND_FRIENDS_DECK_ID, SQUIRTLE_EXTRA_DECK_ID + db BULBASAUR_AND_FRIENDS_DECK_ID, BULBASAUR_EXTRA_DECK_ID + +; clears saved data (card Collection/saved decks/Card Pop! data/etc) +; then adds the starter decks as saved decks +; marks all cards in Collection as not owned +InitSaveData: +; clear card and deck save data + call EnableSRAM + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + ld hl, sCardAndDeckSaveData + ld bc, sCardAndDeckSaveDataEnd - sCardAndDeckSaveData +.loop_clear + xor a + ld [hli], a + dec bc + ld a, c + or b + jr nz, .loop_clear + +; add the starter decks + ld a, CHARMANDER_AND_FRIENDS_DECK + ld hl, sSavedDeck1 + call CopyDeckNameAndCards + ld a, SQUIRTLE_AND_FRIENDS_DECK + ld hl, sSavedDeck2 + call CopyDeckNameAndCards + ld a, BULBASAUR_AND_FRIENDS_DECK + ld hl, sSavedDeck3 + call CopyDeckNameAndCards + +; marks all cards in Collection to not owned + call EnableSRAM + ld hl, sCardCollection + ld a, CARD_NOT_OWNED +.loop_collection + ld [hl], a + inc l + jr nz, .loop_collection + + ld hl, sCurrentDuel + xor a + ld [hli], a + ld [hli], a ; sCurrentDuelChecksum + ld [hl], a + +; clears Card Pop! names + ld hl, sCardPopNameList + ld c, CARDPOP_NAME_LIST_MAX_ELEMS +.loop_card_pop_names + ld [hl], $0 + ld de, NAME_BUFFER_LENGTH + add hl, de + dec c + jr nz, .loop_card_pop_names + +; saved configuration options + ld a, 2 + ld [sPrinterContrastLevel], a + ld a, $2 + ld [sTextSpeed], a + ld [wTextSpeed], a + +; miscellaneous data + xor a + ld [sAnimationsDisabled], a + ld [sSkipDelayAllowed], a + ld [s0a004], a + ld [sTotalCardPopsDone], a + ld [sReceivedLegendaryCards], a + farcall InitPromotionalCardAndDeckCounterSaveData + call DisableSRAM + ret + +; input: +; a = Deck ID +; hl = destination to copy +CopyDeckNameAndCards: + push de + push bc + push hl + call LoadDeck + jr c, .done + call .CopyDeckName + pop hl + call EnableSRAM + push hl + ld de, wDefaultText +.loop_write_name + ld a, [de] + inc de + ld [hli], a + or a + jr nz, .loop_write_name + pop hl + + push hl + ld de, DECK_NAME_SIZE + add hl, de + ld de, wPlayerDeck + ld c, DECK_SIZE +.loop_write_cards + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .loop_write_cards + call DisableSRAM + or a +.done + pop hl + pop bc + pop de + ret + +.CopyDeckName + ld hl, wDeckName + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wDefaultText + call CopyText + ret diff --git a/src/engine/unused_save_validation.asm b/src/engine/unused_save_validation.asm new file mode 100644 index 0000000..9a30d38 --- /dev/null +++ b/src/engine/unused_save_validation.asm @@ -0,0 +1,96 @@ +; this is a commented out routine for save data validation +; sUnusedSaveDataValidationByte would be used to store some validation byte +; and xor'd with $250 bytes in SRAM starting from sCardCollection +; if the result wasn't 0, then it would mean there was +; some save corrpution and an error message would pop up +StubbedUnusedSaveDataValidation: + ret + +UnusedSaveDataValidation: ; unreferenced + ldh a, [hBankSRAM] + or a + ret nz + + push hl + push de + push bc + ld hl, sCardCollection + ld bc, $250 + ld a, [sUnusedSaveDataValidationByte] + ld e, a +.loop_xor + ld a, [hli] + xor e + ld e, a + dec bc + ld a, c + or b + jr nz, .loop_xor + ld a, e + pop bc + pop de + pop hl + or a + ret z + + xor a + ld [wTileMapFill], a + ld hl, wDoFrameFunction + ld [hli], a + ld [hl], a + ldh [hSCX], a + ldh [hSCY], a + bank1call ZeroObjectPositionsAndToggleOAMCopy + call EmptyScreen + call LoadSymbolsFont + bank1call SetDefaultPalettes + ld a, [wConsole] + cp CONSOLE_SGB + jr nz, .not_sgb + ld a, $e4 + ld [wOBP0], a + ld [wBGP], a + ld a, $01 + ld [wFlushPaletteFlags], a +.not_sgb + lb de, $38, $9f + call SetupText + ldtx hl, YourDataWasDestroyedSomehowText + bank1call DrawWholeScreenTextBox + ld a, SRAM_ENABLE + ld [MBC3SRamEnable], a + xor a + ldh [hBankSRAM], a + ld [MBC3SRamBank], a + ld [MBC3RTC], a + ld [MBC3SRamEnable], a + jp Reset + + ret + +UnusedCalculateSaveDataValidationByte: ; unreferenced + ldh a, [hBankSRAM] + or a + ret nz + push hl + push de + push bc + ld hl, sCardCollection + ld bc, $250 + ld e, $00 +.loop_xor + ld a, [hli] + xor e + ld e, a + dec bc + ld a, c + or b + jr nz, .loop_xor + ld a, SRAM_ENABLE + ld [MBC3SRamEnable], a + ld a, e + ld [sUnusedSaveDataValidationByte], a + pop bc + pop de + pop hl + ret diff --git a/src/layout.link b/src/layout.link index f2d8f2b..e731983 100644 --- a/src/layout.link +++ b/src/layout.link @@ -36,7 +36,7 @@ ROMX $01 "Duel Core" "Menus Common" ROMX $02 - "Menus" + "Menus 1" ROMX $03 "Bank 3" ROMX $04 @@ -44,7 +44,18 @@ ROMX $04 ROMX $05 "AI Logic 1" ROMX $06 - "Bank 6" + "Menus 2" + "Effect Commands" + "Animations Engine" + "IR Communications Core" + "Sprite Animations VBlank" + "Starter Deck" + "Link Functions" + "Promotional Card" + "Booster Pack Menu" + "Unused Save Validation" + "Input Name" + "Auto Deck Machines" ROMX $07 "Bank 7" "Credits Sequence" diff --git a/src/main.asm b/src/main.asm index 66be305..55df597 100644 --- a/src/main.asm +++ b/src/main.asm @@ -12,7 +12,7 @@ INCLUDE "engine/duel/core.asm" SECTION "Menus Common", ROMX INCLUDE "engine/menus/common.asm" -SECTION "Menus", ROMX +SECTION "Menus 1", ROMX INCLUDE "engine/menus/duel.asm" INCLUDE "engine/menus/deck_selection.asm" INCLUDE "engine/menus/deck_check.asm" @@ -31,8 +31,47 @@ SECTION "AI Logic 1", ROMX INCLUDE "data/deck_ai_pointers.asm" INCLUDE "engine/ai/core.asm" -SECTION "Bank 6", ROMX -INCLUDE "engine/bank06.asm" +SECTION "Menus 2", ROMX +INCLUDE "engine/copy_card_name.asm" +INCLUDE "engine/menus/play_area.asm" +INCLUDE "engine/menus/glossary.asm" +INCLUDE "engine/menus/unknown.asm" + +SECTION "Effect Commands", ROMX +INCLUDE "engine/duel/effect_commands.asm" + +SECTION "Animations Engine", ROMX +INCLUDE "engine/duel/animations.asm" + +SECTION "IR Communications Core", ROMX +INCLUDE "engine/link/ir_core.asm" + +SECTION "Sprite Animations VBlank", ROMX +INCLUDE "engine/sprite_vblank.asm" + +SECTION "Starter Deck", ROMX +INCLUDE "engine/starter_deck.asm" + +SECTION "Link Functions", ROMX +INCLUDE "engine/link/ir_functions.asm" +INCLUDE "engine/link/card_pop.asm" +INCLUDE "engine/link/printer.asm" +INCLUDE "engine/link/link_duel.asm" + +SECTION "Promotional Card", ROMX +INCLUDE "engine/promotional_card.asm" + +SECTION "Booster Pack Menu", ROMX +INCLUDE "engine/menus/booster_pack.asm" + +SECTION "Unused Save Validation", ROMX +INCLUDE "engine/unused_save_validation.asm" + +SECTION "Input Name", ROMX +INCLUDE "engine/input_name.asm" + +SECTION "Auto Deck Machines", ROMX +INCLUDE "engine/auto_deck_machines.asm" SECTION "Bank 7", ROMX INCLUDE "engine/bank07.asm" diff --git a/src/sram.asm b/src/sram.asm index 6aa8234..8cffb3f 100644 --- a/src/sram.asm +++ b/src/sram.asm @@ -29,7 +29,7 @@ sSkipDelayAllowed:: ; a009 ds $1 sReceivedLegendaryCards:: ; a00a ds $1 -s0a00b:: ; a00b +sUnusedSaveDataValidationByte:: ; a00b ds $1 s0a00c:: ; a00c ds $4 diff --git a/src/text/text1.asm b/src/text/text1.asm index e6192ee..39bd82d 100644 --- a/src/text/text1.asm +++ b/src/text/text1.asm @@ -763,7 +763,7 @@ ResetBackUpRamText: ; 372a9 (d:72a9) text "Reset Back Up RAM?" done -Text00a3: ; 372bd (d:72bd) +YourDataWasDestroyedSomehowText: ; 372bd (d:72bd) text "Your Data was destroyed" line "somehow." line "" diff --git a/src/text/text_offsets.asm b/src/text/text_offsets.asm index 0d212c2..ff38daa 100644 --- a/src/text/text_offsets.asm +++ b/src/text/text_offsets.asm @@ -164,7 +164,7 @@ TextOffsets:: ; 34000 (d:4000) textpointer Text00a0 ; 0x00a0 textpointer Text00a1 ; 0x00a1 textpointer ResetBackUpRamText ; 0x00a2 - textpointer Text00a3 ; 0x00a3 + textpointer YourDataWasDestroyedSomehowText ; 0x00a3 textpointer NoCardsInHandText ; 0x00a4 textpointer TheDiscardPileHasNoCardsText ; 0x00a5 textpointer PlayerDiscardPileText ; 0x00a6 |