diff options
author | YamaArashi <shadow962@live.com> | 2016-09-17 18:17:57 -0700 |
---|---|---|
committer | YamaArashi <shadow962@live.com> | 2016-09-17 18:17:57 -0700 |
commit | c2381bb3e624e966c323610df762a299468a1728 (patch) | |
tree | b884b81317d0aa1e3c7d71df39838ec00ab6a2ce | |
parent | 6f1ac06e03cd046f61fb2370ff7379a29932bbb1 (diff) |
split bank 1 into files
-rw-r--r-- | engine/black_out.asm | 46 | ||||
-rw-r--r-- | engine/debug1.asm | 33 | ||||
-rw-r--r-- | engine/display_pokedex.asm | 19 | ||||
-rw-r--r-- | engine/display_text_id_init.asm | 78 | ||||
-rw-r--r-- | engine/menu/draw_start_menu.asm | 89 | ||||
-rw-r--r-- | engine/menu/swap_items.asm | 149 | ||||
-rw-r--r-- | engine/menu/text_box.asm | 767 | ||||
-rw-r--r-- | engine/overworld/set_blackout_map.asm | 29 | ||||
-rw-r--r-- | engine/remove_pokemon.asm | 95 | ||||
-rw-r--r-- | engine/special_warps.asm | 149 | ||||
-rw-r--r-- | engine/subtract_paid_money.asm | 17 | ||||
-rwxr-xr-x | main.asm | 1486 |
12 files changed, 1482 insertions, 1475 deletions
diff --git a/engine/black_out.asm b/engine/black_out.asm new file mode 100644 index 00000000..6c358ce3 --- /dev/null +++ b/engine/black_out.asm @@ -0,0 +1,46 @@ +ResetStatusAndHalveMoneyOnBlackout:: +; Reset player status on blackout. + xor a + ld [wBattleResult], a + ld [wWalkBikeSurfState], a + ld [wIsInBattle], a + ld [wMapPalOffset], a + ld [wNPCMovementScriptFunctionNum], a + ld [hJoyHeld], a + ld [wNPCMovementScriptPointerTableNum], a + ld [wFlags_0xcd60], a + + ld [hMoney], a + ld [hMoney + 1], a + ld [hMoney + 2], a + call HasEnoughMoney + jr c, .lostmoney ; never happens + + ; Halve the player's money. + ld a, [wPlayerMoney] + ld [hMoney], a + ld a, [wPlayerMoney + 1] + ld [hMoney + 1], a + ld a, [wPlayerMoney + 2] + ld [hMoney + 2], a + xor a + ld [hDivideBCDDivisor], a + ld [hDivideBCDDivisor + 1], a + ld a, 2 + ld [hDivideBCDDivisor + 2], a + predef DivideBCDPredef3 + ld a, [hDivideBCDQuotient] + ld [wPlayerMoney], a + ld a, [hDivideBCDQuotient + 1] + ld [wPlayerMoney + 1], a + ld a, [hDivideBCDQuotient + 2] + ld [wPlayerMoney + 2], a + +.lostmoney + ld hl, wd732 + set 2, [hl] + res 3, [hl] + set 6, [hl] + ld a, %11111111 + ld [wJoyIgnore], a + predef_jump HealParty diff --git a/engine/debug1.asm b/engine/debug1.asm new file mode 100644 index 00000000..a5eb7dde --- /dev/null +++ b/engine/debug1.asm @@ -0,0 +1,33 @@ +; This function appears to never be used. +; It is likely a debugging feature to give the player Tsunekazu Ishihara's +; favorite Pokemon. This is indicated by the overpowered Exeggutor, which +; Ishihara (president of Creatures Inc.) said was his favorite Pokemon in an ABC +; interview on February 8, 2000. +; "Exeggutor is my favorite. That's because I was always using this character +; while I was debugging the program." +; http://www.ign.com/articles/2000/02/09/abc-news-pokamon-chat-transcript + +SetIshiharaTeam: + ld de, IshiharaTeam +.loop + ld a, [de] + cp $ff + ret z + ld [wcf91], a + inc de + ld a, [de] + ld [wCurEnemyLVL], a + inc de + call AddPartyMon + jr .loop + +IshiharaTeam: + db EXEGGUTOR,90 + db MEW,20 + db JOLTEON,56 + db DUGTRIO,56 + db ARTICUNO,57 + db $FF + +EmptyFunc: + ret diff --git a/engine/display_pokedex.asm b/engine/display_pokedex.asm new file mode 100644 index 00000000..96a2dd6c --- /dev/null +++ b/engine/display_pokedex.asm @@ -0,0 +1,19 @@ +_DisplayPokedex: + ld hl, wd730 + set 6, [hl] + predef ShowPokedexData + ld hl, wd730 + res 6, [hl] + call ReloadMapData + ld c, 10 + call DelayFrames + predef IndexToPokedex + ld a, [wd11e] + dec a + ld c, a + ld b, FLAG_SET + ld hl, wPokedexSeen + predef FlagActionPredef + ld a, $1 + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + ret diff --git a/engine/display_text_id_init.asm b/engine/display_text_id_init.asm new file mode 100644 index 00000000..312d6329 --- /dev/null +++ b/engine/display_text_id_init.asm @@ -0,0 +1,78 @@ +; function that performs initialization for DisplayTextID +DisplayTextIDInit: + xor a + ld [wListMenuID],a + ld a,[wAutoTextBoxDrawingControl] + bit 0,a + jr nz,.skipDrawingTextBoxBorder + ld a,[hSpriteIndexOrTextID] ; text ID (or sprite ID) + and a + jr nz,.notStartMenu +; if text ID is 0 (i.e. the start menu) +; Note that the start menu text border is also drawn in the function directly +; below this, so this seems unnecessary. + CheckEvent EVENT_GOT_POKEDEX +; start menu with pokedex + coord hl, 10, 0 + ld b,$0e + ld c,$08 + jr nz,.drawTextBoxBorder +; start menu without pokedex + coord hl, 10, 0 + ld b,$0c + ld c,$08 + jr .drawTextBoxBorder +; if text ID is not 0 (i.e. not the start menu) then do a standard dialogue text box +.notStartMenu + coord hl, 0, 12 + ld b,$04 + ld c,$12 +.drawTextBoxBorder + call TextBoxBorder +.skipDrawingTextBoxBorder + ld hl,wFontLoaded + set 0,[hl] + ld hl,wFlags_0xcd60 + bit 4,[hl] + res 4,[hl] + jr nz,.skipMovingSprites + call UpdateSprites +.skipMovingSprites +; loop to copy C1X9 (direction the sprite is facing) to C2X9 for each sprite +; this is done because when you talk to an NPC, they turn to look your way +; the original direction they were facing must be restored after the dialogue is over + ld hl,wSpriteStateData1 + $19 + ld c,$0f + ld de,$0010 +.spriteFacingDirectionCopyLoop + ld a,[hl] + inc h + ld [hl],a + dec h + add hl,de + dec c + jr nz,.spriteFacingDirectionCopyLoop +; loop to force all the sprites in the middle of animation to stand still +; (so that they don't like they're frozen mid-step during the dialogue) + ld hl,wSpriteStateData1 + 2 + ld de,$0010 + ld c,e +.spriteStandStillLoop + ld a,[hl] + cp a,$ff ; is the sprite visible? + jr z,.nextSprite +; if it is visible + and a,$fc + ld [hl],a +.nextSprite + add hl,de + dec c + jr nz,.spriteStandStillLoop + ld b,$9c ; window background address + call CopyScreenTileBufferToVRAM ; transfer background in WRAM to VRAM + xor a + ld [hWY],a ; put the window on the screen + call LoadFontTilePatterns + ld a,$01 + ld [H_AUTOBGTRANSFERENABLED],a ; enable continuous WRAM to VRAM transfer each V-blank + ret diff --git a/engine/menu/draw_start_menu.asm b/engine/menu/draw_start_menu.asm new file mode 100644 index 00000000..4df9de27 --- /dev/null +++ b/engine/menu/draw_start_menu.asm @@ -0,0 +1,89 @@ +; function that displays the start menu +DrawStartMenu: + CheckEvent EVENT_GOT_POKEDEX +; menu with pokedex + coord hl, 10, 0 + ld b,$0e + ld c,$08 + jr nz,.drawTextBoxBorder +; shorter menu if the player doesn't have the pokedex + coord hl, 10, 0 + ld b,$0c + ld c,$08 +.drawTextBoxBorder + call TextBoxBorder + ld a,D_DOWN | D_UP | START | B_BUTTON | A_BUTTON + ld [wMenuWatchedKeys],a + ld a,$02 + ld [wTopMenuItemY],a ; Y position of first menu choice + ld a,$0b + ld [wTopMenuItemX],a ; X position of first menu choice + ld a,[wBattleAndStartSavedMenuItem] ; remembered menu selection from last time + ld [wCurrentMenuItem],a + ld [wLastMenuItem],a + xor a + ld [wMenuWatchMovingOutOfBounds],a + ld hl,wd730 + set 6,[hl] ; no pauses between printing each letter + coord hl, 12, 2 + CheckEvent EVENT_GOT_POKEDEX +; case for not having pokdex + ld a,$06 + jr z,.storeMenuItemCount +; case for having pokedex + ld de,StartMenuPokedexText + call PrintStartMenuItem + ld a,$07 +.storeMenuItemCount + ld [wMaxMenuItem],a ; number of menu items + ld de,StartMenuPokemonText + call PrintStartMenuItem + ld de,StartMenuItemText + call PrintStartMenuItem + ld de,wPlayerName ; player's name + call PrintStartMenuItem + ld a,[wd72e] + bit 6,a ; is the player using the link feature? +; case for not using link feature + ld de,StartMenuSaveText + jr z,.printSaveOrResetText +; case for using link feature + ld de,StartMenuResetText +.printSaveOrResetText + call PrintStartMenuItem + ld de,StartMenuOptionText + call PrintStartMenuItem + ld de,StartMenuExitText + call PlaceString + ld hl,wd730 + res 6,[hl] ; turn pauses between printing letters back on + ret + +StartMenuPokedexText: + db "POKéDEX@" + +StartMenuPokemonText: + db "POKéMON@" + +StartMenuItemText: + db "ITEM@" + +StartMenuSaveText: + db "SAVE@" + +StartMenuResetText: + db "RESET@" + +StartMenuExitText: + db "EXIT@" + +StartMenuOptionText: + db "OPTION@" + +PrintStartMenuItem: + push hl + call PlaceString + pop hl + ld de,SCREEN_WIDTH * 2 + add hl,de + ret diff --git a/engine/menu/swap_items.asm b/engine/menu/swap_items.asm new file mode 100644 index 00000000..b1fa78be --- /dev/null +++ b/engine/menu/swap_items.asm @@ -0,0 +1,149 @@ +HandleItemListSwapping: + ld a,[wListMenuID] + cp a,ITEMLISTMENU + jp nz,DisplayListMenuIDLoop ; only rearrange item list menus + push hl + ld hl,wListPointer + ld a,[hli] + ld h,[hl] + ld l,a + inc hl ; hl = beginning of list entries + ld a,[wCurrentMenuItem] + ld b,a + ld a,[wListScrollOffset] + add b + add a + ld c,a + ld b,0 + add hl,bc ; hl = address of currently selected item entry + ld a,[hl] + pop hl + inc a + jp z,DisplayListMenuIDLoop ; ignore attempts to swap the Cancel menu item + ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) + and a ; has the first item to swap already been chosen? + jr nz,.swapItems +; if not, set the currently selected item as the first item + ld a,[wCurrentMenuItem] + inc a + ld b,a + ld a,[wListScrollOffset] ; index of top (visible) menu item within the list + add b + ld [wMenuItemToSwap],a ; ID of item chosen for swapping (counts from 1) + ld c,20 + call DelayFrames + jp DisplayListMenuIDLoop +.swapItems + ld a,[wCurrentMenuItem] + inc a + ld b,a + ld a,[wListScrollOffset] + add b + ld b,a + ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) + cp b ; is the currently selected item the same as the first item to swap? + jp z,DisplayListMenuIDLoop ; ignore attempts to swap an item with itself + dec a + ld [wMenuItemToSwap],a ; ID of item chosen for swapping (counts from 1) + ld c,20 + call DelayFrames + push hl + push de + ld hl,wListPointer + ld a,[hli] + ld h,[hl] + ld l,a + inc hl ; hl = beginning of list entries + ld d,h + ld e,l ; de = beginning of list entries + ld a,[wCurrentMenuItem] + ld b,a + ld a,[wListScrollOffset] + add b + add a + ld c,a + ld b,0 + add hl,bc ; hl = address of currently selected item entry + ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) + add a + add e + ld e,a + jr nc,.noCarry + inc d +.noCarry ; de = address of first item to swap + ld a,[de] + ld b,a + ld a,[hli] + cp b + jr z,.swapSameItemType +.swapDifferentItems + ld [$ff95],a ; [$ff95] = second item ID + ld a,[hld] + ld [$ff96],a ; [$ff96] = second item quantity + ld a,[de] + ld [hli],a ; put first item ID in second item slot + inc de + ld a,[de] + ld [hl],a ; put first item quantity in second item slot + ld a,[$ff96] + ld [de],a ; put second item quantity in first item slot + dec de + ld a,[$ff95] + ld [de],a ; put second item ID in first item slot + xor a + ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped + pop de + pop hl + jp DisplayListMenuIDLoop +.swapSameItemType + inc de + ld a,[hl] + ld b,a + ld a,[de] + add b ; a = sum of both item quantities + cp a,100 ; is the sum too big for one item slot? + jr c,.combineItemSlots +; swap enough items from the first slot to max out the second slot if they can't be combined + sub a,99 + ld [de],a + ld a,99 + ld [hl],a + jr .done +.combineItemSlots + ld [hl],a ; put the sum in the second item slot + ld hl,wListPointer + ld a,[hli] + ld h,[hl] + ld l,a + dec [hl] ; decrease the number of items + ld a,[hl] + ld [wListCount],a ; update number of items variable + cp a,1 + jr nz,.skipSettingMaxMenuItemID + ld [wMaxMenuItem],a ; if the number of items is only one now, update the max menu item ID +.skipSettingMaxMenuItemID + dec de + ld h,d + ld l,e + inc hl + inc hl ; hl = address of item after first item to swap +.moveItemsUpLoop ; erase the first item slot and move up all the following item slots to fill the gap + ld a,[hli] + ld [de],a + inc de + inc a ; reached the $ff terminator? + jr z,.afterMovingItemsUp + ld a,[hli] + ld [de],a + inc de + jr .moveItemsUpLoop +.afterMovingItemsUp + xor a + ld [wListScrollOffset],a + ld [wCurrentMenuItem],a +.done + xor a + ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped + pop de + pop hl + jp DisplayListMenuIDLoop diff --git a/engine/menu/text_box.asm b/engine/menu/text_box.asm new file mode 100644 index 00000000..12067dd4 --- /dev/null +++ b/engine/menu/text_box.asm @@ -0,0 +1,767 @@ +; function to draw various text boxes +DisplayTextBoxID_: + ld a,[wTextBoxID] + cp a,TWO_OPTION_MENU + jp z,DisplayTwoOptionMenu + ld c,a + ld hl,TextBoxFunctionTable + ld de,3 + call SearchTextBoxTable + jr c,.functionTableMatch + ld hl,TextBoxCoordTable + ld de,5 + call SearchTextBoxTable + jr c,.coordTableMatch + ld hl,TextBoxTextAndCoordTable + ld de,9 + call SearchTextBoxTable + jr c,.textAndCoordTableMatch +.done + ret +.functionTableMatch + ld a,[hli] + ld h,[hl] + ld l,a ; hl = address of function + ld de,.done + push de + jp [hl] ; jump to the function +.coordTableMatch + call GetTextBoxIDCoords + call GetAddressOfScreenCoords + call TextBoxBorder + ret +.textAndCoordTableMatch + call GetTextBoxIDCoords + push hl + call GetAddressOfScreenCoords + call TextBoxBorder + pop hl + call GetTextBoxIDText + ld a,[wd730] + push af + ld a,[wd730] + set 6,a ; no pauses between printing each letter + ld [wd730],a + call PlaceString + pop af + ld [wd730],a + call UpdateSprites + ret + +; function to search a table terminated with $ff for a byte matching c in increments of de +; sets carry flag if a match is found and clears carry flag if not +SearchTextBoxTable: + dec de +.loop + ld a,[hli] + cp a,$ff + jr z,.notFound + cp c + jr z,.found + add hl,de + jr .loop +.found + scf +.notFound + ret + +; function to load coordinates from the TextBoxCoordTable or the TextBoxTextAndCoordTable +; INPUT: +; hl = address of coordinates +; OUTPUT: +; b = height +; c = width +; d = row of upper left corner +; e = column of upper left corner +GetTextBoxIDCoords: + ld a,[hli] ; column of upper left corner + ld e,a + ld a,[hli] ; row of upper left corner + ld d,a + ld a,[hli] ; column of lower right corner + sub e + dec a + ld c,a ; c = width + ld a,[hli] ; row of lower right corner + sub d + dec a + ld b,a ; b = height + ret + +; function to load a text address and text coordinates from the TextBoxTextAndCoordTable +GetTextBoxIDText: + ld a,[hli] + ld e,a + ld a,[hli] + ld d,a ; de = address of text + push de ; save text address + ld a,[hli] + ld e,a ; column of upper left corner of text + ld a,[hl] + ld d,a ; row of upper left corner of text + call GetAddressOfScreenCoords + pop de ; restore text address + ret + +; function to point hl to the screen coordinates +; INPUT: +; d = row +; e = column +; OUTPUT: +; hl = address of upper left corner of text box +GetAddressOfScreenCoords: + push bc + coord hl, 0, 0 + ld bc,20 +.loop ; loop to add d rows to the base address + ld a,d + and a + jr z,.addedRows + add hl,bc + dec d + jr .loop +.addedRows + pop bc + add hl,de + ret + +; Format: +; 00: text box ID +; 01-02: function address +TextBoxFunctionTable: + dbw MONEY_BOX, DisplayMoneyBox + dbw BUY_SELL_QUIT_MENU, DoBuySellQuitMenu + dbw FIELD_MOVE_MON_MENU, DisplayFieldMoveMonMenu + db $ff ; terminator + +; Format: +; 00: text box ID +; 01: column of upper left corner +; 02: row of upper left corner +; 03: column of lower right corner +; 04: row of lower right corner +TextBoxCoordTable: + db MESSAGE_BOX, 0, 12, 19, 17 + db $03, 0, 0, 19, 14 + db $07, 0, 0, 11, 6 + db LIST_MENU_BOX, 4, 2, 19, 12 + db $10, 7, 0, 19, 17 + db MON_SPRITE_POPUP, 6, 4, 14, 13 + db $ff ; terminator + +; Format: +; 00: text box ID +; 01: column of upper left corner +; 02: row of upper left corner +; 03: column of lower right corner +; 04: row of lower right corner +; 05-06: address of text +; 07: column of beginning of text +; 08: row of beginning of text +; table of window positions and corresponding text [key, start column, start row, end column, end row, text pointer [2 bytes], text column, text row] +TextBoxTextAndCoordTable: + db JP_MOCHIMONO_MENU_TEMPLATE + db 0,0,14,17 ; text box coordinates + dw JapaneseMochimonoText + db 3,0 ; text coordinates + + db USE_TOSS_MENU_TEMPLATE + db 13,10,19,14 ; text box coordinates + dw UseTossText + db 15,11 ; text coordinates + + db JP_SAVE_MESSAGE_MENU_TEMPLATE + db 0,0,7,5 ; text box coordinates + dw JapaneseSaveMessageText + db 2,2 ; text coordinates + + db JP_SPEED_OPTIONS_MENU_TEMPLATE + db 0,6,5,10 ; text box coordinates + dw JapaneseSpeedOptionsText + db 2,7 ; text coordinates + + db BATTLE_MENU_TEMPLATE + db 8,12,19,17 ; text box coordinates + dw BattleMenuText + db 10,14 ; text coordinates + + db SAFARI_BATTLE_MENU_TEMPLATE + db 0,12,19,17 ; text box coordinates + dw SafariZoneBattleMenuText + db 2,14 ; text coordinates + + db SWITCH_STATS_CANCEL_MENU_TEMPLATE + db 11,11,19,17 ; text box coordinates + dw SwitchStatsCancelText + db 13,12 ; text coordinates + + db BUY_SELL_QUIT_MENU_TEMPLATE + db 0,0,10,6 ; text box coordinates + dw BuySellQuitText + db 2,1 ; text coordinates + + db MONEY_BOX_TEMPLATE + db 11,0,19,2 ; text box coordinates + dw MoneyText + db 13,0 ; text coordinates + + db JP_AH_MENU_TEMPLATE + db 7,6,11,10 ; text box coordinates + dw JapaneseAhText + db 8,8 ; text coordinates + + db JP_POKEDEX_MENU_TEMPLATE + db 11,8,19,17 ; text box coordinates + dw JapanesePokedexMenu + db 12,10 ; text coordinates + +; note that there is no terminator + +BuySellQuitText: + db "BUY" + next "SELL" + next "QUIT@@" + +UseTossText: + db "USE" + next "TOSS@" + +JapaneseSaveMessageText: + db "きろく" + next "メッセージ@" + +JapaneseSpeedOptionsText: + db "はやい" + next "おそい@" + +MoneyText: + db "MONEY@" + +JapaneseMochimonoText: + db "もちもの@" + +JapaneseMainMenuText: + db "つづきから" + next "さいしょから@" + +BattleMenuText: + db "FIGHT ",$E1,$E2 + next "ITEM RUN@" + +SafariZoneBattleMenuText: + db "BALL× BAIT" + next "THROW ROCK RUN@" + +SwitchStatsCancelText: + db "SWITCH" + next "STATS" + next "CANCEL@" + +JapaneseAhText: + db "アッ!@" + +JapanesePokedexMenu: + db "データをみる" + next "なきごえ" + next "ぶんぷをみる" + next "キャンセル@" + +DisplayMoneyBox: + ld hl, wd730 + set 6, [hl] + ld a, MONEY_BOX_TEMPLATE + ld [wTextBoxID], a + call DisplayTextBoxID + coord hl, 13, 1 + ld b, 1 + ld c, 6 + call ClearScreenArea + coord hl, 12, 1 + ld de, wPlayerMoney + ld c, $a3 + call PrintBCDNumber + ld hl, wd730 + res 6, [hl] + ret + +CurrencyString: + db " ¥@" + +DoBuySellQuitMenu: + ld a, [wd730] + set 6, a ; no printing delay + ld [wd730], a + xor a + ld [wChosenMenuItem], a + ld a, BUY_SELL_QUIT_MENU_TEMPLATE + ld [wTextBoxID], a + call DisplayTextBoxID + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, $2 + ld [wMaxMenuItem], a + ld a, $1 + ld [wTopMenuItemY], a + ld a, $1 + ld [wTopMenuItemX], a + xor a + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ld [wMenuWatchMovingOutOfBounds], a + ld a, [wd730] + res 6, a ; turn on the printing delay + ld [wd730], a + call HandleMenuInput + call PlaceUnfilledArrowMenuCursor + bit 0, a ; was A pressed? + jr nz, .pressedA + bit 1, a ; was B pressed? (always true since only A/B are watched) + jr z, .pressedA + ld a, CANCELLED_MENU + ld [wMenuExitMethod], a + jr .quit +.pressedA + ld a, CHOSE_MENU_ITEM + ld [wMenuExitMethod], a + ld a, [wCurrentMenuItem] + ld [wChosenMenuItem], a + ld b, a + ld a, [wMaxMenuItem] + cp b + jr z, .quit + ret +.quit + ld a, CANCELLED_MENU + ld [wMenuExitMethod], a + ld a, [wCurrentMenuItem] + ld [wChosenMenuItem], a + scf + ret + +; displays a menu with two options to choose from +; b = Y of upper left corner of text region +; c = X of upper left corner of text region +; hl = address where the text box border should be drawn +DisplayTwoOptionMenu: + push hl + ld a, [wd730] + set 6, a ; no printing delay + ld [wd730], a + +; pointless because both values are overwritten before they are read + xor a + ld [wChosenMenuItem], a + ld [wMenuExitMethod], a + + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, $1 + ld [wMaxMenuItem], a + ld a, b + ld [wTopMenuItemY], a + ld a, c + ld [wTopMenuItemX], a + xor a + ld [wLastMenuItem], a + ld [wMenuWatchMovingOutOfBounds], a + push hl + ld hl, wTwoOptionMenuID + bit 7, [hl] ; select second menu item by default? + res 7, [hl] + jr z, .storeCurrentMenuItem + inc a +.storeCurrentMenuItem + ld [wCurrentMenuItem], a + pop hl + push hl + push hl + call TwoOptionMenu_SaveScreenTiles + ld a, [wTwoOptionMenuID] + ld hl, TwoOptionMenuStrings + ld e, a + ld d, $0 + ld a, $5 +.menuStringLoop + add hl, de + dec a + jr nz, .menuStringLoop + ld a, [hli] + ld c, a + ld a, [hli] + ld b, a + ld e, l + ld d, h + pop hl + push de + ld a, [wTwoOptionMenuID] + cp TRADE_CANCEL_MENU + jr nz, .notTradeCancelMenu + call CableClub_TextBoxBorder + jr .afterTextBoxBorder +.notTradeCancelMenu + call TextBoxBorder +.afterTextBoxBorder + call UpdateSprites + pop hl + ld a, [hli] + and a ; put blank line before first menu item? + ld bc, 20 + 2 + jr z, .noBlankLine + ld bc, 2 * 20 + 2 +.noBlankLine + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + pop hl + add hl, bc + call PlaceString + ld hl, wd730 + res 6, [hl] ; turn on the printing delay + ld a, [wTwoOptionMenuID] + cp NO_YES_MENU + jr nz, .notNoYesMenu +; No/Yes menu +; this menu type ignores the B button +; it only seems to be used when confirming the deletion of a save file + xor a + ld [wTwoOptionMenuID], a + ld a, [wFlags_0xcd60] + push af + push hl + ld hl, wFlags_0xcd60 + bit 5, [hl] + set 5, [hl] ; don't play sound when A or B is pressed in menu + pop hl +.noYesMenuInputLoop + call HandleMenuInput + bit 1, a ; A button pressed? + jr nz, .noYesMenuInputLoop ; try again if A was not pressed + pop af + pop hl + ld [wFlags_0xcd60], a + ld a, SFX_PRESS_AB + call PlaySound + jr .pressedAButton +.notNoYesMenu + xor a + ld [wTwoOptionMenuID], a + call HandleMenuInput + pop hl + bit 1, a ; A button pressed? + jr nz, .choseSecondMenuItem ; automatically choose the second option if B is pressed +.pressedAButton + ld a, [wCurrentMenuItem] + ld [wChosenMenuItem], a + and a + jr nz, .choseSecondMenuItem +; chose first menu item + ld a, CHOSE_FIRST_ITEM + ld [wMenuExitMethod], a + ld c, 15 + call DelayFrames + call TwoOptionMenu_RestoreScreenTiles + and a + ret +.choseSecondMenuItem + ld a, 1 + ld [wCurrentMenuItem], a + ld [wChosenMenuItem], a + ld a, CHOSE_SECOND_ITEM + ld [wMenuExitMethod], a + ld c, 15 + call DelayFrames + call TwoOptionMenu_RestoreScreenTiles + scf + ret + +; Some of the wider/taller two option menus will not have the screen areas +; they cover be fully saved/restored by the two functions below. +; The bottom and right edges of the menu may remain after the function returns. + +TwoOptionMenu_SaveScreenTiles: + ld de, wBuffer + lb bc, 5, 6 +.loop + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .loop + push bc + ld bc, SCREEN_WIDTH - 6 + add hl, bc + pop bc + ld c, $6 + dec b + jr nz, .loop + ret + +TwoOptionMenu_RestoreScreenTiles: + ld de, wBuffer + lb bc, 5, 6 +.loop + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .loop + push bc + ld bc, SCREEN_WIDTH - 6 + add hl, bc + pop bc + ld c, 6 + dec b + jr nz, .loop + call UpdateSprites + ret + +; Format: +; 00: byte width +; 01: byte height +; 02: byte put blank line before first menu item +; 03: word text pointer +TwoOptionMenuStrings: + db 4,3,0 + dw .YesNoMenu + db 6,3,0 + dw .NorthWestMenu + db 6,3,0 + dw .SouthEastMenu + db 6,3,0 + dw .YesNoMenu + db 6,3,0 + dw .NorthEastMenu + db 7,3,0 + dw .TradeCancelMenu + db 7,4,1 + dw .HealCancelMenu + db 4,3,0 + dw .NoYesMenu + +.NoYesMenu + db "NO" + next "YES@" +.YesNoMenu + db "YES" + next "NO@" +.NorthWestMenu + db "NORTH" + next "WEST@" +.SouthEastMenu + db "SOUTH" + next "EAST@" +.NorthEastMenu + db "NORTH" + next "EAST@" +.TradeCancelMenu + db "TRADE" + next "CANCEL@" +.HealCancelMenu + db "HEAL" + next "CANCEL@" + +DisplayFieldMoveMonMenu: + xor a + ld hl, wFieldMoves + ld [hli], a ; wFieldMoves + ld [hli], a ; wFieldMoves + 1 + ld [hli], a ; wFieldMoves + 2 + ld [hli], a ; wFieldMoves + 3 + ld [hli], a ; wNumFieldMoves + ld [hl], 12 ; wFieldMovesLeftmostXCoord + call GetMonFieldMoves + ld a, [wNumFieldMoves] + and a + jr nz, .fieldMovesExist + +; no field moves + coord hl, 11, 11 + ld b, 5 + ld c, 7 + call TextBoxBorder + call UpdateSprites + ld a, 12 + ld [hFieldMoveMonMenuTopMenuItemX], a + coord hl, 13, 12 + ld de, PokemonMenuEntries + jp PlaceString + +.fieldMovesExist + push af + +; Calculate the text box position and dimensions based on the leftmost X coord +; of the field move names before adjusting for the number of field moves. + coord hl, 0, 11 + ld a, [wFieldMovesLeftmostXCoord] + dec a + ld e, a + ld d, 0 + add hl, de + ld b, 5 + ld a, 18 + sub e + ld c, a + pop af + +; For each field move, move the top of the text box up 2 rows while the leaving +; the bottom of the text box at the bottom of the screen. + ld de, -SCREEN_WIDTH * 2 +.textBoxHeightLoop + add hl, de + inc b + inc b + dec a + jr nz, .textBoxHeightLoop + +; Make space for an extra blank row above the top field move. + ld de, -SCREEN_WIDTH + add hl, de + inc b + + call TextBoxBorder + call UpdateSprites + +; Calculate the position of the first field move name to print. + coord hl, 0, 12 + ld a, [wFieldMovesLeftmostXCoord] + inc a + ld e, a + ld d, 0 + add hl, de + ld de, -SCREEN_WIDTH * 2 + ld a, [wNumFieldMoves] +.calcFirstFieldMoveYLoop + add hl, de + dec a + jr nz, .calcFirstFieldMoveYLoop + + xor a + ld [wNumFieldMoves], a + ld de, wFieldMoves +.printNamesLoop + push hl + ld hl, FieldMoveNames + ld a, [de] + and a + jr z, .donePrintingNames + inc de + ld b, a ; index of name +.skipNamesLoop ; skip past names before the name we want + dec b + jr z, .reachedName +.skipNameLoop ; skip past current name + ld a, [hli] + cp "@" + jr nz, .skipNameLoop + jr .skipNamesLoop +.reachedName + ld b, h + ld c, l + pop hl + push de + ld d, b + ld e, c + call PlaceString + ld bc, SCREEN_WIDTH * 2 + add hl, bc + pop de + jr .printNamesLoop + +.donePrintingNames + pop hl + ld a, [wFieldMovesLeftmostXCoord] + ld [hFieldMoveMonMenuTopMenuItemX], a + coord hl, 0, 12 + ld a, [wFieldMovesLeftmostXCoord] + inc a + ld e, a + ld d, 0 + add hl, de + ld de, PokemonMenuEntries + jp PlaceString + +FieldMoveNames: + db "CUT@" + db "FLY@" + db "@" + db "SURF@" + db "STRENGTH@" + db "FLASH@" + db "DIG@" + db "TELEPORT@" + db "SOFTBOILED@" + +PokemonMenuEntries: + db "STATS" + next "SWITCH" + next "CANCEL@" + +GetMonFieldMoves: + ld a, [wWhichPokemon] + ld hl, wPartyMon1Moves + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld d, h + ld e, l + ld c, NUM_MOVES + 1 + ld hl, wFieldMoves +.loop + push hl +.nextMove + dec c + jr z, .done + ld a, [de] ; move ID + and a + jr z, .done + ld b, a + inc de + ld hl, FieldMoveDisplayData +.fieldMoveLoop + ld a, [hli] + cp $ff + jr z, .nextMove ; if the move is not a field move + cp b + jr z, .foundFieldMove + inc hl + inc hl + jr .fieldMoveLoop +.foundFieldMove + ld a, b + ld [wLastFieldMoveID], a + ld a, [hli] ; field move name index + ld b, [hl] ; field move leftmost X coordinate + pop hl + ld [hli], a ; store name index in wFieldMoves + ld a, [wNumFieldMoves] + inc a + ld [wNumFieldMoves], a + ld a, [wFieldMovesLeftmostXCoord] + cp b + jr c, .skipUpdatingLeftmostXCoord + ld a, b + ld [wFieldMovesLeftmostXCoord], a +.skipUpdatingLeftmostXCoord + ld a, [wLastFieldMoveID] + ld b, a + jr .loop +.done + pop hl + ret + +; Format: [Move id], [name index], [leftmost tile] +; Move id = id of move +; Name index = index of name in FieldMoveNames +; Leftmost tile = -1 + tile column in which the first letter of the move's name should be displayed +; "SOFTBOILED" is $08 because it has 4 more letters than "SURF", for example, whose value is $0C +FieldMoveDisplayData: + db CUT, $01, $0C + db FLY, $02, $0C + db $B4, $03, $0C ; unused field move + db SURF, $04, $0C + db STRENGTH, $05, $0A + db FLASH, $06, $0C + db DIG, $07, $0C + db TELEPORT, $08, $0A + db SOFTBOILED, $09, $08 + db $ff ; list terminator diff --git a/engine/overworld/set_blackout_map.asm b/engine/overworld/set_blackout_map.asm new file mode 100644 index 00000000..9bfe82bd --- /dev/null +++ b/engine/overworld/set_blackout_map.asm @@ -0,0 +1,29 @@ +SetLastBlackoutMap: +; Set the map to return to when +; blacking out or using Teleport or Dig. +; Safari rest houses don't count. + + push hl + ld hl, SafariZoneRestHouses + ld a, [wCurMap] + ld b, a +.loop + ld a, [hli] + cp -1 + jr z, .notresthouse + cp b + jr nz, .loop + jr .done + +.notresthouse + ld a, [wLastMap] + ld [wLastBlackoutMap], a +.done + pop hl + ret + +SafariZoneRestHouses: + db SAFARI_ZONE_REST_HOUSE_2 + db SAFARI_ZONE_REST_HOUSE_3 + db SAFARI_ZONE_REST_HOUSE_4 + db -1 diff --git a/engine/remove_pokemon.asm b/engine/remove_pokemon.asm new file mode 100644 index 00000000..1fcb5d09 --- /dev/null +++ b/engine/remove_pokemon.asm @@ -0,0 +1,95 @@ +_RemovePokemon: + ld hl, wPartyCount + ld a, [wRemoveMonFromBox] + and a + jr z, .asm_7b74 + ld hl, wNumInBox +.asm_7b74 + ld a, [hl] + dec a + ld [hli], a + ld a, [wWhichPokemon] + ld c, a + ld b, $0 + add hl, bc + ld e, l + ld d, h + inc de +.asm_7b81 + ld a, [de] + inc de + ld [hli], a + inc a + jr nz, .asm_7b81 + ld hl, wPartyMonOT + ld d, $5 + ld a, [wRemoveMonFromBox] + and a + jr z, .asm_7b97 + ld hl, wBoxMonOT + ld d, $13 +.asm_7b97 + ld a, [wWhichPokemon] + call SkipFixedLengthTextEntries + ld a, [wWhichPokemon] + cp d + jr nz, .asm_7ba6 + ld [hl], $ff + ret +.asm_7ba6 + ld d, h + ld e, l + ld bc, NAME_LENGTH + add hl, bc + ld bc, wPartyMonNicks + ld a, [wRemoveMonFromBox] + and a + jr z, .asm_7bb8 + ld bc, wBoxMonNicks +.asm_7bb8 + call CopyDataUntil + ld hl, wPartyMons + ld bc, wPartyMon2 - wPartyMon1 + ld a, [wRemoveMonFromBox] + and a + jr z, .asm_7bcd + ld hl, wBoxMons + ld bc, wBoxMon2 - wBoxMon1 +.asm_7bcd + ld a, [wWhichPokemon] + call AddNTimes + ld d, h + ld e, l + ld a, [wRemoveMonFromBox] + and a + jr z, .asm_7be4 + ld bc, wBoxMon2 - wBoxMon1 + add hl, bc + ld bc, wBoxMonOT + jr .asm_7beb +.asm_7be4 + ld bc, wPartyMon2 - wPartyMon1 + add hl, bc + ld bc, wPartyMonOT +.asm_7beb + call CopyDataUntil + ld hl, wPartyMonNicks + ld a, [wRemoveMonFromBox] + and a + jr z, .asm_7bfa + ld hl, wBoxMonNicks +.asm_7bfa + ld bc, NAME_LENGTH + ld a, [wWhichPokemon] + call AddNTimes + ld d, h + ld e, l + ld bc, NAME_LENGTH + add hl, bc + ld bc, wPokedexOwned + ld a, [wRemoveMonFromBox] + and a + jr z, .asm_7c15 + ld bc, wBoxMonNicksEnd +.asm_7c15 + jp CopyDataUntil diff --git a/engine/special_warps.asm b/engine/special_warps.asm new file mode 100644 index 00000000..de00a817 --- /dev/null +++ b/engine/special_warps.asm @@ -0,0 +1,149 @@ +SpecialWarpIn: + call LoadSpecialWarpData + predef LoadTilesetHeader + ld hl,wd732 + bit 2,[hl] ; dungeon warp or fly warp? + res 2,[hl] + jr z,.next +; if dungeon warp or fly warp + ld a,[wDestinationMap] + jr .next2 +.next + bit 1,[hl] + jr z,.next3 + call EmptyFunc +.next3 + ld a,0 +.next2 + ld b,a + ld a,[wd72d] + and a + jr nz,.next4 + ld a,b +.next4 + ld hl,wd732 + bit 4,[hl] ; dungeon warp? + ret nz +; if not dungeon warp + ld [wLastMap],a + ret + +; gets the map ID, tile block map view pointer, tileset, and coordinates +LoadSpecialWarpData: + ld a, [wd72d] + cp TRADE_CENTER + jr nz, .notTradeCenter + ld hl, TradeCenterSpec1 + ld a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK ; which gameboy is clocking determines who is on the left and who is on the right + jr z, .copyWarpData + ld hl, TradeCenterSpec2 + jr .copyWarpData +.notTradeCenter + cp COLOSSEUM + jr nz, .notColosseum + ld hl, ColosseumSpec1 + ld a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr z, .copyWarpData + ld hl, ColosseumSpec2 + jr .copyWarpData +.notColosseum + ld a, [wd732] + bit 1, a + jr nz, .notFirstMap + bit 2, a + jr nz, .notFirstMap + ld hl, FirstMapSpec +.copyWarpData + ld de, wCurMap + ld c, $7 +.copyWarpDataLoop + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .copyWarpDataLoop + ld a, [hli] + ld [wCurMapTileset], a + xor a + jr .done +.notFirstMap + ld a, [wLastMap] ; this value is overwritten before it's ever read + ld hl, wd732 + bit 4, [hl] ; used dungeon warp (jumped down hole/waterfall)? + jr nz, .usedDunegonWarp + bit 6, [hl] ; return to last pokemon center (or player's house)? + res 6, [hl] + jr z, .otherDestination +; return to last pokemon center or player's house + ld a, [wLastBlackoutMap] + jr .usedFlyWarp +.usedDunegonWarp + ld hl, wd72d + res 4, [hl] + ld a, [wDungeonWarpDestinationMap] + ld b, a + ld [wCurMap], a + ld a, [wWhichDungeonWarp] + ld c, a + ld hl, DungeonWarpList + ld de, 0 + ld a, 6 + ld [wDungeonWarpDataEntrySize], a +.dungeonWarpListLoop + ld a, [hli] + cp b + jr z, .matchedDungeonWarpDestinationMap + inc hl + jr .nextDungeonWarp +.matchedDungeonWarpDestinationMap + ld a, [hli] + cp c + jr z, .matchedDungeonWarpID +.nextDungeonWarp + ld a, [wDungeonWarpDataEntrySize] + add e + ld e, a + jr .dungeonWarpListLoop +.matchedDungeonWarpID + ld hl, DungeonWarpData + add hl, de + jr .copyWarpData2 +.otherDestination + ld a, [wDestinationMap] +.usedFlyWarp + ld b, a + ld [wCurMap], a + ld hl, FlyWarpDataPtr +.flyWarpDataPtrLoop + ld a, [hli] + inc hl + cp b + jr z, .foundFlyWarpMatch + inc hl + inc hl + jr .flyWarpDataPtrLoop +.foundFlyWarpMatch + ld a, [hli] + ld h, [hl] + ld l, a +.copyWarpData2 + ld de, wCurrentTileBlockMapViewPointer + ld c, $6 +.copyWarpDataLoop2 + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .copyWarpDataLoop2 + xor a ; OVERWORLD + ld [wCurMapTileset], a +.done + ld [wYOffsetSinceLastSpecialWarp], a + ld [wXOffsetSinceLastSpecialWarp], a + ld a, $ff ; the player's coordinates have already been updated using a special warp, so don't use any of the normal warps + ld [wDestinationWarpID], a + ret + +INCLUDE "data/special_warps.asm" diff --git a/engine/subtract_paid_money.asm b/engine/subtract_paid_money.asm new file mode 100644 index 00000000..2888c3fb --- /dev/null +++ b/engine/subtract_paid_money.asm @@ -0,0 +1,17 @@ +; subtracts the amount the player paid from their money +; sets carry flag if there is enough money and unsets carry flag if not +SubtractAmountPaidFromMoney_: + ld de,wPlayerMoney + ld hl,hMoney ; total price of items + ld c,3 ; length of money in bytes + call StringCmp + ret c + ld de,wPlayerMoney + 2 + ld hl,hMoney + 2 ; total price of items + ld c,3 ; length of money in bytes + predef SubBCDPredef ; subtract total price from money + ld a,MONEY_BOX + ld [wTextBoxID],a + call DisplayTextBoxID ; redraw money text box + and a + ret @@ -18,53 +18,7 @@ SECTION "bank1",ROMX,BANK[$1] INCLUDE "data/facing.asm" -ResetStatusAndHalveMoneyOnBlackout:: -; Reset player status on blackout. - xor a - ld [wBattleResult], a - ld [wWalkBikeSurfState], a - ld [wIsInBattle], a - ld [wMapPalOffset], a - ld [wNPCMovementScriptFunctionNum], a - ld [hJoyHeld], a - ld [wNPCMovementScriptPointerTableNum], a - ld [wFlags_0xcd60], a - - ld [hMoney], a - ld [hMoney + 1], a - ld [hMoney + 2], a - call HasEnoughMoney - jr c, .lostmoney ; never happens - - ; Halve the player's money. - ld a, [wPlayerMoney] - ld [hMoney], a - ld a, [wPlayerMoney + 1] - ld [hMoney + 1], a - ld a, [wPlayerMoney + 2] - ld [hMoney + 2], a - xor a - ld [hDivideBCDDivisor], a - ld [hDivideBCDDivisor + 1], a - ld a, 2 - ld [hDivideBCDDivisor + 2], a - predef DivideBCDPredef3 - ld a, [hDivideBCDQuotient] - ld [wPlayerMoney], a - ld a, [hDivideBCDQuotient + 1] - ld [wPlayerMoney + 1], a - ld a, [hDivideBCDQuotient + 2] - ld [wPlayerMoney + 2], a - -.lostmoney - ld hl, wd732 - set 2, [hl] - res 3, [hl] - set 6, [hl] - ld a, %11111111 - ld [wJoyIgnore], a - predef_jump HealParty - +INCLUDE "engine/black_out.asm" MewPicFront:: INCBIN "pic/bmon/mew.pic" MewPicBack:: INCBIN "pic/monback/mewb.pic" @@ -97,361 +51,17 @@ INCLUDE "engine/menu/main_menu.asm" INCLUDE "engine/oak_speech.asm" -SpecialWarpIn: - call LoadSpecialWarpData - predef LoadTilesetHeader - ld hl,wd732 - bit 2,[hl] ; dungeon warp or fly warp? - res 2,[hl] - jr z,.next -; if dungeon warp or fly warp - ld a,[wDestinationMap] - jr .next2 -.next - bit 1,[hl] - jr z,.next3 - call EmptyFunc -.next3 - ld a,0 -.next2 - ld b,a - ld a,[wd72d] - and a - jr nz,.next4 - ld a,b -.next4 - ld hl,wd732 - bit 4,[hl] ; dungeon warp? - ret nz -; if not dungeon warp - ld [wLastMap],a - ret - -; gets the map ID, tile block map view pointer, tileset, and coordinates -LoadSpecialWarpData: - ld a, [wd72d] - cp TRADE_CENTER - jr nz, .notTradeCenter - ld hl, TradeCenterSpec1 - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK ; which gameboy is clocking determines who is on the left and who is on the right - jr z, .copyWarpData - ld hl, TradeCenterSpec2 - jr .copyWarpData -.notTradeCenter - cp COLOSSEUM - jr nz, .notColosseum - ld hl, ColosseumSpec1 - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - jr z, .copyWarpData - ld hl, ColosseumSpec2 - jr .copyWarpData -.notColosseum - ld a, [wd732] - bit 1, a - jr nz, .notFirstMap - bit 2, a - jr nz, .notFirstMap - ld hl, FirstMapSpec -.copyWarpData - ld de, wCurMap - ld c, $7 -.copyWarpDataLoop - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .copyWarpDataLoop - ld a, [hli] - ld [wCurMapTileset], a - xor a - jr .done -.notFirstMap - ld a, [wLastMap] ; this value is overwritten before it's ever read - ld hl, wd732 - bit 4, [hl] ; used dungeon warp (jumped down hole/waterfall)? - jr nz, .usedDunegonWarp - bit 6, [hl] ; return to last pokemon center (or player's house)? - res 6, [hl] - jr z, .otherDestination -; return to last pokemon center or player's house - ld a, [wLastBlackoutMap] - jr .usedFlyWarp -.usedDunegonWarp - ld hl, wd72d - res 4, [hl] - ld a, [wDungeonWarpDestinationMap] - ld b, a - ld [wCurMap], a - ld a, [wWhichDungeonWarp] - ld c, a - ld hl, DungeonWarpList - ld de, 0 - ld a, 6 - ld [wDungeonWarpDataEntrySize], a -.dungeonWarpListLoop - ld a, [hli] - cp b - jr z, .matchedDungeonWarpDestinationMap - inc hl - jr .nextDungeonWarp -.matchedDungeonWarpDestinationMap - ld a, [hli] - cp c - jr z, .matchedDungeonWarpID -.nextDungeonWarp - ld a, [wDungeonWarpDataEntrySize] - add e - ld e, a - jr .dungeonWarpListLoop -.matchedDungeonWarpID - ld hl, DungeonWarpData - add hl, de - jr .copyWarpData2 -.otherDestination - ld a, [wDestinationMap] -.usedFlyWarp - ld b, a - ld [wCurMap], a - ld hl, FlyWarpDataPtr -.flyWarpDataPtrLoop - ld a, [hli] - inc hl - cp b - jr z, .foundFlyWarpMatch - inc hl - inc hl - jr .flyWarpDataPtrLoop -.foundFlyWarpMatch - ld a, [hli] - ld h, [hl] - ld l, a -.copyWarpData2 - ld de, wCurrentTileBlockMapViewPointer - ld c, $6 -.copyWarpDataLoop2 - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .copyWarpDataLoop2 - xor a ; OVERWORLD - ld [wCurMapTileset], a -.done - ld [wYOffsetSinceLastSpecialWarp], a - ld [wXOffsetSinceLastSpecialWarp], a - ld a, $ff ; the player's coordinates have already been updated using a special warp, so don't use any of the normal warps - ld [wDestinationWarpID], a - ret - -INCLUDE "data/special_warps.asm" - -; This function appears to never be used. -; It is likely a debugging feature to give the player Tsunekazu Ishihara's -; favorite Pokemon. This is indicated by the overpowered Exeggutor, which -; Ishihara (president of Creatures Inc.) said was his favorite Pokemon in an ABC -; interview on February 8, 2000. -; "Exeggutor is my favorite. That's because I was always using this character -; while I was debugging the program." -; http://www.ign.com/articles/2000/02/09/abc-news-pokamon-chat-transcript - -SetIshiharaTeam: - ld de, IshiharaTeam -.loop - ld a, [de] - cp $ff - ret z - ld [wcf91], a - inc de - ld a, [de] - ld [wCurEnemyLVL], a - inc de - call AddPartyMon - jr .loop - -IshiharaTeam: - db EXEGGUTOR,90 - db MEW,20 - db JOLTEON,56 - db DUGTRIO,56 - db ARTICUNO,57 - db $FF +INCLUDE "engine/special_warps.asm" -EmptyFunc: - ret +INCLUDE "engine/debug1.asm" INCLUDE "engine/menu/naming_screen.asm" INCLUDE "engine/oak_speech2.asm" -; subtracts the amount the player paid from their money -; sets carry flag if there is enough money and unsets carry flag if not -SubtractAmountPaidFromMoney_: - ld de,wPlayerMoney - ld hl,hMoney ; total price of items - ld c,3 ; length of money in bytes - call StringCmp - ret c - ld de,wPlayerMoney + 2 - ld hl,hMoney + 2 ; total price of items - ld c,3 ; length of money in bytes - predef SubBCDPredef ; subtract total price from money - ld a,MONEY_BOX - ld [wTextBoxID],a - call DisplayTextBoxID ; redraw money text box - and a - ret +INCLUDE "engine/subtract_paid_money.asm" -HandleItemListSwapping: - ld a,[wListMenuID] - cp a,ITEMLISTMENU - jp nz,DisplayListMenuIDLoop ; only rearrange item list menus - push hl - ld hl,wListPointer - ld a,[hli] - ld h,[hl] - ld l,a - inc hl ; hl = beginning of list entries - ld a,[wCurrentMenuItem] - ld b,a - ld a,[wListScrollOffset] - add b - add a - ld c,a - ld b,0 - add hl,bc ; hl = address of currently selected item entry - ld a,[hl] - pop hl - inc a - jp z,DisplayListMenuIDLoop ; ignore attempts to swap the Cancel menu item - ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) - and a ; has the first item to swap already been chosen? - jr nz,.swapItems -; if not, set the currently selected item as the first item - ld a,[wCurrentMenuItem] - inc a - ld b,a - ld a,[wListScrollOffset] ; index of top (visible) menu item within the list - add b - ld [wMenuItemToSwap],a ; ID of item chosen for swapping (counts from 1) - ld c,20 - call DelayFrames - jp DisplayListMenuIDLoop -.swapItems - ld a,[wCurrentMenuItem] - inc a - ld b,a - ld a,[wListScrollOffset] - add b - ld b,a - ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) - cp b ; is the currently selected item the same as the first item to swap? - jp z,DisplayListMenuIDLoop ; ignore attempts to swap an item with itself - dec a - ld [wMenuItemToSwap],a ; ID of item chosen for swapping (counts from 1) - ld c,20 - call DelayFrames - push hl - push de - ld hl,wListPointer - ld a,[hli] - ld h,[hl] - ld l,a - inc hl ; hl = beginning of list entries - ld d,h - ld e,l ; de = beginning of list entries - ld a,[wCurrentMenuItem] - ld b,a - ld a,[wListScrollOffset] - add b - add a - ld c,a - ld b,0 - add hl,bc ; hl = address of currently selected item entry - ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) - add a - add e - ld e,a - jr nc,.noCarry - inc d -.noCarry ; de = address of first item to swap - ld a,[de] - ld b,a - ld a,[hli] - cp b - jr z,.swapSameItemType -.swapDifferentItems - ld [$ff95],a ; [$ff95] = second item ID - ld a,[hld] - ld [$ff96],a ; [$ff96] = second item quantity - ld a,[de] - ld [hli],a ; put first item ID in second item slot - inc de - ld a,[de] - ld [hl],a ; put first item quantity in second item slot - ld a,[$ff96] - ld [de],a ; put second item quantity in first item slot - dec de - ld a,[$ff95] - ld [de],a ; put second item ID in first item slot - xor a - ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped - pop de - pop hl - jp DisplayListMenuIDLoop -.swapSameItemType - inc de - ld a,[hl] - ld b,a - ld a,[de] - add b ; a = sum of both item quantities - cp a,100 ; is the sum too big for one item slot? - jr c,.combineItemSlots -; swap enough items from the first slot to max out the second slot if they can't be combined - sub a,99 - ld [de],a - ld a,99 - ld [hl],a - jr .done -.combineItemSlots - ld [hl],a ; put the sum in the second item slot - ld hl,wListPointer - ld a,[hli] - ld h,[hl] - ld l,a - dec [hl] ; decrease the number of items - ld a,[hl] - ld [wListCount],a ; update number of items variable - cp a,1 - jr nz,.skipSettingMaxMenuItemID - ld [wMaxMenuItem],a ; if the number of items is only one now, update the max menu item ID -.skipSettingMaxMenuItemID - dec de - ld h,d - ld l,e - inc hl - inc hl ; hl = address of item after first item to swap -.moveItemsUpLoop ; erase the first item slot and move up all the following item slots to fill the gap - ld a,[hli] - ld [de],a - inc de - inc a ; reached the $ff terminator? - jr z,.afterMovingItemsUp - ld a,[hli] - ld [de],a - inc de - jr .moveItemsUpLoop -.afterMovingItemsUp - xor a - ld [wListScrollOffset],a - ld [wCurrentMenuItem],a -.done - xor a - ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped - pop de - pop hl - jp DisplayListMenuIDLoop +INCLUDE "engine/menu/swap_items.asm" INCLUDE "engine/overworld/pokemart.asm" @@ -459,1096 +69,22 @@ INCLUDE "engine/learn_move.asm" INCLUDE "engine/overworld/pokecenter.asm" -SetLastBlackoutMap: -; Set the map to return to when -; blacking out or using Teleport or Dig. -; Safari rest houses don't count. - - push hl - ld hl, SafariZoneRestHouses - ld a, [wCurMap] - ld b, a -.loop - ld a, [hli] - cp -1 - jr z, .notresthouse - cp b - jr nz, .loop - jr .done - -.notresthouse - ld a, [wLastMap] - ld [wLastBlackoutMap], a -.done - pop hl - ret +INCLUDE "engine/overworld/set_blackout_map.asm" -SafariZoneRestHouses: - db SAFARI_ZONE_REST_HOUSE_2 - db SAFARI_ZONE_REST_HOUSE_3 - db SAFARI_ZONE_REST_HOUSE_4 - db -1 - -; function that performs initialization for DisplayTextID -DisplayTextIDInit: - xor a - ld [wListMenuID],a - ld a,[wAutoTextBoxDrawingControl] - bit 0,a - jr nz,.skipDrawingTextBoxBorder - ld a,[hSpriteIndexOrTextID] ; text ID (or sprite ID) - and a - jr nz,.notStartMenu -; if text ID is 0 (i.e. the start menu) -; Note that the start menu text border is also drawn in the function directly -; below this, so this seems unnecessary. - CheckEvent EVENT_GOT_POKEDEX -; start menu with pokedex - coord hl, 10, 0 - ld b,$0e - ld c,$08 - jr nz,.drawTextBoxBorder -; start menu without pokedex - coord hl, 10, 0 - ld b,$0c - ld c,$08 - jr .drawTextBoxBorder -; if text ID is not 0 (i.e. not the start menu) then do a standard dialogue text box -.notStartMenu - coord hl, 0, 12 - ld b,$04 - ld c,$12 -.drawTextBoxBorder - call TextBoxBorder -.skipDrawingTextBoxBorder - ld hl,wFontLoaded - set 0,[hl] - ld hl,wFlags_0xcd60 - bit 4,[hl] - res 4,[hl] - jr nz,.skipMovingSprites - call UpdateSprites -.skipMovingSprites -; loop to copy C1X9 (direction the sprite is facing) to C2X9 for each sprite -; this is done because when you talk to an NPC, they turn to look your way -; the original direction they were facing must be restored after the dialogue is over - ld hl,wSpriteStateData1 + $19 - ld c,$0f - ld de,$0010 -.spriteFacingDirectionCopyLoop - ld a,[hl] - inc h - ld [hl],a - dec h - add hl,de - dec c - jr nz,.spriteFacingDirectionCopyLoop -; loop to force all the sprites in the middle of animation to stand still -; (so that they don't like they're frozen mid-step during the dialogue) - ld hl,wSpriteStateData1 + 2 - ld de,$0010 - ld c,e -.spriteStandStillLoop - ld a,[hl] - cp a,$ff ; is the sprite visible? - jr z,.nextSprite -; if it is visible - and a,$fc - ld [hl],a -.nextSprite - add hl,de - dec c - jr nz,.spriteStandStillLoop - ld b,$9c ; window background address - call CopyScreenTileBufferToVRAM ; transfer background in WRAM to VRAM - xor a - ld [hWY],a ; put the window on the screen - call LoadFontTilePatterns - ld a,$01 - ld [H_AUTOBGTRANSFERENABLED],a ; enable continuous WRAM to VRAM transfer each V-blank - ret - -; function that displays the start menu -DrawStartMenu: - CheckEvent EVENT_GOT_POKEDEX -; menu with pokedex - coord hl, 10, 0 - ld b,$0e - ld c,$08 - jr nz,.drawTextBoxBorder -; shorter menu if the player doesn't have the pokedex - coord hl, 10, 0 - ld b,$0c - ld c,$08 -.drawTextBoxBorder - call TextBoxBorder - ld a,D_DOWN | D_UP | START | B_BUTTON | A_BUTTON - ld [wMenuWatchedKeys],a - ld a,$02 - ld [wTopMenuItemY],a ; Y position of first menu choice - ld a,$0b - ld [wTopMenuItemX],a ; X position of first menu choice - ld a,[wBattleAndStartSavedMenuItem] ; remembered menu selection from last time - ld [wCurrentMenuItem],a - ld [wLastMenuItem],a - xor a - ld [wMenuWatchMovingOutOfBounds],a - ld hl,wd730 - set 6,[hl] ; no pauses between printing each letter - coord hl, 12, 2 - CheckEvent EVENT_GOT_POKEDEX -; case for not having pokdex - ld a,$06 - jr z,.storeMenuItemCount -; case for having pokedex - ld de,StartMenuPokedexText - call PrintStartMenuItem - ld a,$07 -.storeMenuItemCount - ld [wMaxMenuItem],a ; number of menu items - ld de,StartMenuPokemonText - call PrintStartMenuItem - ld de,StartMenuItemText - call PrintStartMenuItem - ld de,wPlayerName ; player's name - call PrintStartMenuItem - ld a,[wd72e] - bit 6,a ; is the player using the link feature? -; case for not using link feature - ld de,StartMenuSaveText - jr z,.printSaveOrResetText -; case for using link feature - ld de,StartMenuResetText -.printSaveOrResetText - call PrintStartMenuItem - ld de,StartMenuOptionText - call PrintStartMenuItem - ld de,StartMenuExitText - call PlaceString - ld hl,wd730 - res 6,[hl] ; turn pauses between printing letters back on - ret - -StartMenuPokedexText: - db "POKéDEX@" - -StartMenuPokemonText: - db "POKéMON@" - -StartMenuItemText: - db "ITEM@" - -StartMenuSaveText: - db "SAVE@" - -StartMenuResetText: - db "RESET@" - -StartMenuExitText: - db "EXIT@" - -StartMenuOptionText: - db "OPTION@" - -PrintStartMenuItem: - push hl - call PlaceString - pop hl - ld de,SCREEN_WIDTH * 2 - add hl,de - ret +INCLUDE "engine/display_text_id_init.asm" +INCLUDE "engine/menu/draw_start_menu.asm" INCLUDE "engine/overworld/cable_club_npc.asm" -; function to draw various text boxes -DisplayTextBoxID_: - ld a,[wTextBoxID] - cp a,TWO_OPTION_MENU - jp z,DisplayTwoOptionMenu - ld c,a - ld hl,TextBoxFunctionTable - ld de,3 - call SearchTextBoxTable - jr c,.functionTableMatch - ld hl,TextBoxCoordTable - ld de,5 - call SearchTextBoxTable - jr c,.coordTableMatch - ld hl,TextBoxTextAndCoordTable - ld de,9 - call SearchTextBoxTable - jr c,.textAndCoordTableMatch -.done - ret -.functionTableMatch - ld a,[hli] - ld h,[hl] - ld l,a ; hl = address of function - ld de,.done - push de - jp [hl] ; jump to the function -.coordTableMatch - call GetTextBoxIDCoords - call GetAddressOfScreenCoords - call TextBoxBorder - ret -.textAndCoordTableMatch - call GetTextBoxIDCoords - push hl - call GetAddressOfScreenCoords - call TextBoxBorder - pop hl - call GetTextBoxIDText - ld a,[wd730] - push af - ld a,[wd730] - set 6,a ; no pauses between printing each letter - ld [wd730],a - call PlaceString - pop af - ld [wd730],a - call UpdateSprites - ret - -; function to search a table terminated with $ff for a byte matching c in increments of de -; sets carry flag if a match is found and clears carry flag if not -SearchTextBoxTable: - dec de -.loop - ld a,[hli] - cp a,$ff - jr z,.notFound - cp c - jr z,.found - add hl,de - jr .loop -.found - scf -.notFound - ret - -; function to load coordinates from the TextBoxCoordTable or the TextBoxTextAndCoordTable -; INPUT: -; hl = address of coordinates -; OUTPUT: -; b = height -; c = width -; d = row of upper left corner -; e = column of upper left corner -GetTextBoxIDCoords: - ld a,[hli] ; column of upper left corner - ld e,a - ld a,[hli] ; row of upper left corner - ld d,a - ld a,[hli] ; column of lower right corner - sub e - dec a - ld c,a ; c = width - ld a,[hli] ; row of lower right corner - sub d - dec a - ld b,a ; b = height - ret - -; function to load a text address and text coordinates from the TextBoxTextAndCoordTable -GetTextBoxIDText: - ld a,[hli] - ld e,a - ld a,[hli] - ld d,a ; de = address of text - push de ; save text address - ld a,[hli] - ld e,a ; column of upper left corner of text - ld a,[hl] - ld d,a ; row of upper left corner of text - call GetAddressOfScreenCoords - pop de ; restore text address - ret - -; function to point hl to the screen coordinates -; INPUT: -; d = row -; e = column -; OUTPUT: -; hl = address of upper left corner of text box -GetAddressOfScreenCoords: - push bc - coord hl, 0, 0 - ld bc,20 -.loop ; loop to add d rows to the base address - ld a,d - and a - jr z,.addedRows - add hl,bc - dec d - jr .loop -.addedRows - pop bc - add hl,de - ret - -; Format: -; 00: text box ID -; 01-02: function address -TextBoxFunctionTable: - dbw MONEY_BOX, DisplayMoneyBox - dbw BUY_SELL_QUIT_MENU, DoBuySellQuitMenu - dbw FIELD_MOVE_MON_MENU, DisplayFieldMoveMonMenu - db $ff ; terminator - -; Format: -; 00: text box ID -; 01: column of upper left corner -; 02: row of upper left corner -; 03: column of lower right corner -; 04: row of lower right corner -TextBoxCoordTable: - db MESSAGE_BOX, 0, 12, 19, 17 - db $03, 0, 0, 19, 14 - db $07, 0, 0, 11, 6 - db LIST_MENU_BOX, 4, 2, 19, 12 - db $10, 7, 0, 19, 17 - db MON_SPRITE_POPUP, 6, 4, 14, 13 - db $ff ; terminator - -; Format: -; 00: text box ID -; 01: column of upper left corner -; 02: row of upper left corner -; 03: column of lower right corner -; 04: row of lower right corner -; 05-06: address of text -; 07: column of beginning of text -; 08: row of beginning of text -; table of window positions and corresponding text [key, start column, start row, end column, end row, text pointer [2 bytes], text column, text row] -TextBoxTextAndCoordTable: - db JP_MOCHIMONO_MENU_TEMPLATE - db 0,0,14,17 ; text box coordinates - dw JapaneseMochimonoText - db 3,0 ; text coordinates - - db USE_TOSS_MENU_TEMPLATE - db 13,10,19,14 ; text box coordinates - dw UseTossText - db 15,11 ; text coordinates - - db JP_SAVE_MESSAGE_MENU_TEMPLATE - db 0,0,7,5 ; text box coordinates - dw JapaneseSaveMessageText - db 2,2 ; text coordinates - - db JP_SPEED_OPTIONS_MENU_TEMPLATE - db 0,6,5,10 ; text box coordinates - dw JapaneseSpeedOptionsText - db 2,7 ; text coordinates - - db BATTLE_MENU_TEMPLATE - db 8,12,19,17 ; text box coordinates - dw BattleMenuText - db 10,14 ; text coordinates - - db SAFARI_BATTLE_MENU_TEMPLATE - db 0,12,19,17 ; text box coordinates - dw SafariZoneBattleMenuText - db 2,14 ; text coordinates - - db SWITCH_STATS_CANCEL_MENU_TEMPLATE - db 11,11,19,17 ; text box coordinates - dw SwitchStatsCancelText - db 13,12 ; text coordinates - - db BUY_SELL_QUIT_MENU_TEMPLATE - db 0,0,10,6 ; text box coordinates - dw BuySellQuitText - db 2,1 ; text coordinates - - db MONEY_BOX_TEMPLATE - db 11,0,19,2 ; text box coordinates - dw MoneyText - db 13,0 ; text coordinates - - db JP_AH_MENU_TEMPLATE - db 7,6,11,10 ; text box coordinates - dw JapaneseAhText - db 8,8 ; text coordinates - - db JP_POKEDEX_MENU_TEMPLATE - db 11,8,19,17 ; text box coordinates - dw JapanesePokedexMenu - db 12,10 ; text coordinates - -; note that there is no terminator - -BuySellQuitText: - db "BUY" - next "SELL" - next "QUIT@@" - -UseTossText: - db "USE" - next "TOSS@" - -JapaneseSaveMessageText: - db "きろく" - next "メッセージ@" - -JapaneseSpeedOptionsText: - db "はやい" - next "おそい@" - -MoneyText: - db "MONEY@" - -JapaneseMochimonoText: - db "もちもの@" - -JapaneseMainMenuText: - db "つづきから" - next "さいしょから@" - -BattleMenuText: - db "FIGHT ",$E1,$E2 - next "ITEM RUN@" - -SafariZoneBattleMenuText: - db "BALL× BAIT" - next "THROW ROCK RUN@" - -SwitchStatsCancelText: - db "SWITCH" - next "STATS" - next "CANCEL@" - -JapaneseAhText: - db "アッ!@" - -JapanesePokedexMenu: - db "データをみる" - next "なきごえ" - next "ぶんぷをみる" - next "キャンセル@" - -DisplayMoneyBox: - ld hl, wd730 - set 6, [hl] - ld a, MONEY_BOX_TEMPLATE - ld [wTextBoxID], a - call DisplayTextBoxID - coord hl, 13, 1 - ld b, 1 - ld c, 6 - call ClearScreenArea - coord hl, 12, 1 - ld de, wPlayerMoney - ld c, $a3 - call PrintBCDNumber - ld hl, wd730 - res 6, [hl] - ret - -CurrencyString: - db " ¥@" - -DoBuySellQuitMenu: - ld a, [wd730] - set 6, a ; no printing delay - ld [wd730], a - xor a - ld [wChosenMenuItem], a - ld a, BUY_SELL_QUIT_MENU_TEMPLATE - ld [wTextBoxID], a - call DisplayTextBoxID - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, $2 - ld [wMaxMenuItem], a - ld a, $1 - ld [wTopMenuItemY], a - ld a, $1 - ld [wTopMenuItemX], a - xor a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld [wMenuWatchMovingOutOfBounds], a - ld a, [wd730] - res 6, a ; turn on the printing delay - ld [wd730], a - call HandleMenuInput - call PlaceUnfilledArrowMenuCursor - bit 0, a ; was A pressed? - jr nz, .pressedA - bit 1, a ; was B pressed? (always true since only A/B are watched) - jr z, .pressedA - ld a, CANCELLED_MENU - ld [wMenuExitMethod], a - jr .quit -.pressedA - ld a, CHOSE_MENU_ITEM - ld [wMenuExitMethod], a - ld a, [wCurrentMenuItem] - ld [wChosenMenuItem], a - ld b, a - ld a, [wMaxMenuItem] - cp b - jr z, .quit - ret -.quit - ld a, CANCELLED_MENU - ld [wMenuExitMethod], a - ld a, [wCurrentMenuItem] - ld [wChosenMenuItem], a - scf - ret - -; displays a menu with two options to choose from -; b = Y of upper left corner of text region -; c = X of upper left corner of text region -; hl = address where the text box border should be drawn -DisplayTwoOptionMenu: - push hl - ld a, [wd730] - set 6, a ; no printing delay - ld [wd730], a - -; pointless because both values are overwritten before they are read - xor a - ld [wChosenMenuItem], a - ld [wMenuExitMethod], a - - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, $1 - ld [wMaxMenuItem], a - ld a, b - ld [wTopMenuItemY], a - ld a, c - ld [wTopMenuItemX], a - xor a - ld [wLastMenuItem], a - ld [wMenuWatchMovingOutOfBounds], a - push hl - ld hl, wTwoOptionMenuID - bit 7, [hl] ; select second menu item by default? - res 7, [hl] - jr z, .storeCurrentMenuItem - inc a -.storeCurrentMenuItem - ld [wCurrentMenuItem], a - pop hl - push hl - push hl - call TwoOptionMenu_SaveScreenTiles - ld a, [wTwoOptionMenuID] - ld hl, TwoOptionMenuStrings - ld e, a - ld d, $0 - ld a, $5 -.menuStringLoop - add hl, de - dec a - jr nz, .menuStringLoop - ld a, [hli] - ld c, a - ld a, [hli] - ld b, a - ld e, l - ld d, h - pop hl - push de - ld a, [wTwoOptionMenuID] - cp TRADE_CANCEL_MENU - jr nz, .notTradeCancelMenu - call CableClub_TextBoxBorder - jr .afterTextBoxBorder -.notTradeCancelMenu - call TextBoxBorder -.afterTextBoxBorder - call UpdateSprites - pop hl - ld a, [hli] - and a ; put blank line before first menu item? - ld bc, 20 + 2 - jr z, .noBlankLine - ld bc, 2 * 20 + 2 -.noBlankLine - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - pop hl - add hl, bc - call PlaceString - ld hl, wd730 - res 6, [hl] ; turn on the printing delay - ld a, [wTwoOptionMenuID] - cp NO_YES_MENU - jr nz, .notNoYesMenu -; No/Yes menu -; this menu type ignores the B button -; it only seems to be used when confirming the deletion of a save file - xor a - ld [wTwoOptionMenuID], a - ld a, [wFlags_0xcd60] - push af - push hl - ld hl, wFlags_0xcd60 - bit 5, [hl] - set 5, [hl] ; don't play sound when A or B is pressed in menu - pop hl -.noYesMenuInputLoop - call HandleMenuInput - bit 1, a ; A button pressed? - jr nz, .noYesMenuInputLoop ; try again if A was not pressed - pop af - pop hl - ld [wFlags_0xcd60], a - ld a, SFX_PRESS_AB - call PlaySound - jr .pressedAButton -.notNoYesMenu - xor a - ld [wTwoOptionMenuID], a - call HandleMenuInput - pop hl - bit 1, a ; A button pressed? - jr nz, .choseSecondMenuItem ; automatically choose the second option if B is pressed -.pressedAButton - ld a, [wCurrentMenuItem] - ld [wChosenMenuItem], a - and a - jr nz, .choseSecondMenuItem -; chose first menu item - ld a, CHOSE_FIRST_ITEM - ld [wMenuExitMethod], a - ld c, 15 - call DelayFrames - call TwoOptionMenu_RestoreScreenTiles - and a - ret -.choseSecondMenuItem - ld a, 1 - ld [wCurrentMenuItem], a - ld [wChosenMenuItem], a - ld a, CHOSE_SECOND_ITEM - ld [wMenuExitMethod], a - ld c, 15 - call DelayFrames - call TwoOptionMenu_RestoreScreenTiles - scf - ret - -; Some of the wider/taller two option menus will not have the screen areas -; they cover be fully saved/restored by the two functions below. -; The bottom and right edges of the menu may remain after the function returns. - -TwoOptionMenu_SaveScreenTiles: - ld de, wBuffer - lb bc, 5, 6 -.loop - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .loop - push bc - ld bc, SCREEN_WIDTH - 6 - add hl, bc - pop bc - ld c, $6 - dec b - jr nz, .loop - ret - -TwoOptionMenu_RestoreScreenTiles: - ld de, wBuffer - lb bc, 5, 6 -.loop - ld a, [de] - inc de - ld [hli], a - dec c - jr nz, .loop - push bc - ld bc, SCREEN_WIDTH - 6 - add hl, bc - pop bc - ld c, 6 - dec b - jr nz, .loop - call UpdateSprites - ret - -; Format: -; 00: byte width -; 01: byte height -; 02: byte put blank line before first menu item -; 03: word text pointer -TwoOptionMenuStrings: - db 4,3,0 - dw .YesNoMenu - db 6,3,0 - dw .NorthWestMenu - db 6,3,0 - dw .SouthEastMenu - db 6,3,0 - dw .YesNoMenu - db 6,3,0 - dw .NorthEastMenu - db 7,3,0 - dw .TradeCancelMenu - db 7,4,1 - dw .HealCancelMenu - db 4,3,0 - dw .NoYesMenu - -.NoYesMenu - db "NO" - next "YES@" -.YesNoMenu - db "YES" - next "NO@" -.NorthWestMenu - db "NORTH" - next "WEST@" -.SouthEastMenu - db "SOUTH" - next "EAST@" -.NorthEastMenu - db "NORTH" - next "EAST@" -.TradeCancelMenu - db "TRADE" - next "CANCEL@" -.HealCancelMenu - db "HEAL" - next "CANCEL@" - -DisplayFieldMoveMonMenu: - xor a - ld hl, wFieldMoves - ld [hli], a ; wFieldMoves - ld [hli], a ; wFieldMoves + 1 - ld [hli], a ; wFieldMoves + 2 - ld [hli], a ; wFieldMoves + 3 - ld [hli], a ; wNumFieldMoves - ld [hl], 12 ; wFieldMovesLeftmostXCoord - call GetMonFieldMoves - ld a, [wNumFieldMoves] - and a - jr nz, .fieldMovesExist - -; no field moves - coord hl, 11, 11 - ld b, 5 - ld c, 7 - call TextBoxBorder - call UpdateSprites - ld a, 12 - ld [hFieldMoveMonMenuTopMenuItemX], a - coord hl, 13, 12 - ld de, PokemonMenuEntries - jp PlaceString - -.fieldMovesExist - push af - -; Calculate the text box position and dimensions based on the leftmost X coord -; of the field move names before adjusting for the number of field moves. - coord hl, 0, 11 - ld a, [wFieldMovesLeftmostXCoord] - dec a - ld e, a - ld d, 0 - add hl, de - ld b, 5 - ld a, 18 - sub e - ld c, a - pop af - -; For each field move, move the top of the text box up 2 rows while the leaving -; the bottom of the text box at the bottom of the screen. - ld de, -SCREEN_WIDTH * 2 -.textBoxHeightLoop - add hl, de - inc b - inc b - dec a - jr nz, .textBoxHeightLoop - -; Make space for an extra blank row above the top field move. - ld de, -SCREEN_WIDTH - add hl, de - inc b - - call TextBoxBorder - call UpdateSprites - -; Calculate the position of the first field move name to print. - coord hl, 0, 12 - ld a, [wFieldMovesLeftmostXCoord] - inc a - ld e, a - ld d, 0 - add hl, de - ld de, -SCREEN_WIDTH * 2 - ld a, [wNumFieldMoves] -.calcFirstFieldMoveYLoop - add hl, de - dec a - jr nz, .calcFirstFieldMoveYLoop - - xor a - ld [wNumFieldMoves], a - ld de, wFieldMoves -.printNamesLoop - push hl - ld hl, FieldMoveNames - ld a, [de] - and a - jr z, .donePrintingNames - inc de - ld b, a ; index of name -.skipNamesLoop ; skip past names before the name we want - dec b - jr z, .reachedName -.skipNameLoop ; skip past current name - ld a, [hli] - cp "@" - jr nz, .skipNameLoop - jr .skipNamesLoop -.reachedName - ld b, h - ld c, l - pop hl - push de - ld d, b - ld e, c - call PlaceString - ld bc, SCREEN_WIDTH * 2 - add hl, bc - pop de - jr .printNamesLoop - -.donePrintingNames - pop hl - ld a, [wFieldMovesLeftmostXCoord] - ld [hFieldMoveMonMenuTopMenuItemX], a - coord hl, 0, 12 - ld a, [wFieldMovesLeftmostXCoord] - inc a - ld e, a - ld d, 0 - add hl, de - ld de, PokemonMenuEntries - jp PlaceString - -FieldMoveNames: - db "CUT@" - db "FLY@" - db "@" - db "SURF@" - db "STRENGTH@" - db "FLASH@" - db "DIG@" - db "TELEPORT@" - db "SOFTBOILED@" - -PokemonMenuEntries: - db "STATS" - next "SWITCH" - next "CANCEL@" - -GetMonFieldMoves: - ld a, [wWhichPokemon] - ld hl, wPartyMon1Moves - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld d, h - ld e, l - ld c, NUM_MOVES + 1 - ld hl, wFieldMoves -.loop - push hl -.nextMove - dec c - jr z, .done - ld a, [de] ; move ID - and a - jr z, .done - ld b, a - inc de - ld hl, FieldMoveDisplayData -.fieldMoveLoop - ld a, [hli] - cp $ff - jr z, .nextMove ; if the move is not a field move - cp b - jr z, .foundFieldMove - inc hl - inc hl - jr .fieldMoveLoop -.foundFieldMove - ld a, b - ld [wLastFieldMoveID], a - ld a, [hli] ; field move name index - ld b, [hl] ; field move leftmost X coordinate - pop hl - ld [hli], a ; store name index in wFieldMoves - ld a, [wNumFieldMoves] - inc a - ld [wNumFieldMoves], a - ld a, [wFieldMovesLeftmostXCoord] - cp b - jr c, .skipUpdatingLeftmostXCoord - ld a, b - ld [wFieldMovesLeftmostXCoord], a -.skipUpdatingLeftmostXCoord - ld a, [wLastFieldMoveID] - ld b, a - jr .loop -.done - pop hl - ret - -; Format: [Move id], [name index], [leftmost tile] -; Move id = id of move -; Name index = index of name in FieldMoveNames -; Leftmost tile = -1 + tile column in which the first letter of the move's name should be displayed -; "SOFTBOILED" is $08 because it has 4 more letters than "SURF", for example, whose value is $0C -FieldMoveDisplayData: - db CUT, $01, $0C - db FLY, $02, $0C - db $B4, $03, $0C ; unused field move - db SURF, $04, $0C - db STRENGTH, $05, $0A - db FLASH, $06, $0C - db DIG, $07, $0C - db TELEPORT, $08, $0A - db SOFTBOILED, $09, $08 - db $ff ; list terminator - +INCLUDE "engine/menu/text_box.asm" INCLUDE "engine/battle/moveEffects/drain_hp_effect.asm" INCLUDE "engine/menu/players_pc.asm" -_RemovePokemon: - ld hl, wPartyCount - ld a, [wRemoveMonFromBox] - and a - jr z, .asm_7b74 - ld hl, wNumInBox -.asm_7b74 - ld a, [hl] - dec a - ld [hli], a - ld a, [wWhichPokemon] - ld c, a - ld b, $0 - add hl, bc - ld e, l - ld d, h - inc de -.asm_7b81 - ld a, [de] - inc de - ld [hli], a - inc a - jr nz, .asm_7b81 - ld hl, wPartyMonOT - ld d, $5 - ld a, [wRemoveMonFromBox] - and a - jr z, .asm_7b97 - ld hl, wBoxMonOT - ld d, $13 -.asm_7b97 - ld a, [wWhichPokemon] - call SkipFixedLengthTextEntries - ld a, [wWhichPokemon] - cp d - jr nz, .asm_7ba6 - ld [hl], $ff - ret -.asm_7ba6 - ld d, h - ld e, l - ld bc, NAME_LENGTH - add hl, bc - ld bc, wPartyMonNicks - ld a, [wRemoveMonFromBox] - and a - jr z, .asm_7bb8 - ld bc, wBoxMonNicks -.asm_7bb8 - call CopyDataUntil - ld hl, wPartyMons - ld bc, wPartyMon2 - wPartyMon1 - ld a, [wRemoveMonFromBox] - and a - jr z, .asm_7bcd - ld hl, wBoxMons - ld bc, wBoxMon2 - wBoxMon1 -.asm_7bcd - ld a, [wWhichPokemon] - call AddNTimes - ld d, h - ld e, l - ld a, [wRemoveMonFromBox] - and a - jr z, .asm_7be4 - ld bc, wBoxMon2 - wBoxMon1 - add hl, bc - ld bc, wBoxMonOT - jr .asm_7beb -.asm_7be4 - ld bc, wPartyMon2 - wPartyMon1 - add hl, bc - ld bc, wPartyMonOT -.asm_7beb - call CopyDataUntil - ld hl, wPartyMonNicks - ld a, [wRemoveMonFromBox] - and a - jr z, .asm_7bfa - ld hl, wBoxMonNicks -.asm_7bfa - ld bc, NAME_LENGTH - ld a, [wWhichPokemon] - call AddNTimes - ld d, h - ld e, l - ld bc, NAME_LENGTH - add hl, bc - ld bc, wPokedexOwned - ld a, [wRemoveMonFromBox] - and a - jr z, .asm_7c15 - ld bc, wBoxMonNicksEnd -.asm_7c15 - jp CopyDataUntil - -_DisplayPokedex: - ld hl, wd730 - set 6, [hl] - predef ShowPokedexData - ld hl, wd730 - res 6, [hl] - call ReloadMapData - ld c, 10 - call DelayFrames - predef IndexToPokedex - ld a, [wd11e] - dec a - ld c, a - ld b, FLAG_SET - ld hl, wPokedexSeen - predef FlagActionPredef - ld a, $1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ret +INCLUDE "engine/remove_pokemon.asm" +INCLUDE "engine/display_pokedex.asm" SECTION "bank3",ROMX,BANK[$3] |