split bank 1 into files

This commit is contained in:
YamaArashi 2016-09-17 18:17:57 -07:00
parent 6f1ac06e03
commit c2381bb3e6
12 changed files with 1482 additions and 1475 deletions

46
engine/black_out.asm Normal file
View file

@ -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

33
engine/debug1.asm Normal file
View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

149
engine/menu/swap_items.asm Normal file
View file

@ -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

767
engine/menu/text_box.asm Normal file
View file

@ -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

View file

@ -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

95
engine/remove_pokemon.asm Normal file
View file

@ -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

149
engine/special_warps.asm Normal file
View file

@ -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"

View file

@ -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

1486
main.asm

File diff suppressed because it is too large Load diff