summaryrefslogtreecommitdiff
path: root/home
diff options
context:
space:
mode:
Diffstat (limited to 'home')
-rw-r--r--home/audio.asm6
-rw-r--r--home/bankswitch.asm35
-rw-r--r--home/clear_sprites.asm21
-rw-r--r--home/copy.asm6
-rw-r--r--home/copy2.asm76
-rw-r--r--home/header.asm57
-rw-r--r--home/init.asm20
-rw-r--r--home/lcd.asm25
-rw-r--r--home/list_menu.asm526
-rw-r--r--home/move_mon.asm242
-rw-r--r--home/names.asm141
-rw-r--r--home/names2.asm93
-rw-r--r--home/overworld.asm50
-rw-r--r--home/overworld_text.asm31
-rw-r--r--home/pics.asm196
-rw-r--r--home/pokemon.asm464
-rw-r--r--home/predef.asm8
-rw-r--r--home/predef_text.asm237
-rw-r--r--home/print_bcd.asm77
-rw-r--r--home/print_num.asm217
-rw-r--r--home/start.asm10
-rwxr-xr-xhome/start_menu.asm2
-rw-r--r--home/text.asm14
-rw-r--r--home/trainers.asm436
-rw-r--r--home/uncompress.asm (renamed from home/pic.asm)6
-rw-r--r--home/vblank.asm22
-rw-r--r--home/vcopy.asm116
-rw-r--r--home/yes_no.asm40
28 files changed, 3011 insertions, 163 deletions
diff --git a/home/audio.asm b/home/audio.asm
index 242f038b..04f0276d 100644
--- a/home/audio.asm
+++ b/home/audio.asm
@@ -170,10 +170,10 @@ PlaySound::
.noFadeOut
xor a
ld [wNewSoundID], a
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
ld [hSavedROMBank], a
ld a, [wAudioROMBank]
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
cp BANK(Audio1_PlaySound)
jr nz, .checkForAudio2
@@ -198,7 +198,7 @@ PlaySound::
.next2
ld a, [hSavedROMBank]
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
jr .done
diff --git a/home/bankswitch.asm b/home/bankswitch.asm
new file mode 100644
index 00000000..086ca2f3
--- /dev/null
+++ b/home/bankswitch.asm
@@ -0,0 +1,35 @@
+BankswitchHome::
+; switches to bank # in a
+; Only use this when in the home bank!
+ ld [wBankswitchHomeTemp], a
+ ld a, [hLoadedROMBank]
+ ld [wBankswitchHomeSavedROMBank], a
+ ld a, [wBankswitchHomeTemp]
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ ret
+
+BankswitchBack::
+; returns from BankswitchHome
+ ld a, [wBankswitchHomeSavedROMBank]
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ ret
+
+Bankswitch::
+; self-contained bankswitch, use this when not in the home bank
+; switches to the bank in b
+ ld a, [hLoadedROMBank]
+ push af
+ ld a, b
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ ld bc, .Return
+ push bc
+ jp hl
+.Return
+ pop bc
+ ld a, b
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ ret
diff --git a/home/clear_sprites.asm b/home/clear_sprites.asm
new file mode 100644
index 00000000..34f4b4ec
--- /dev/null
+++ b/home/clear_sprites.asm
@@ -0,0 +1,21 @@
+ClearSprites::
+ xor a
+ ld hl, wOAMBuffer
+ ld b, 40 * 4
+.loop
+ ld [hli], a
+ dec b
+ jr nz, .loop
+ ret
+
+HideSprites::
+ ld a, 160
+ ld hl, wOAMBuffer
+ ld de, 4
+ ld b, 40
+.loop
+ ld [hl], a
+ add hl, de
+ dec b
+ jr nz, .loop
+ ret
diff --git a/home/copy.asm b/home/copy.asm
index be9c8c0c..910f508b 100644
--- a/home/copy.asm
+++ b/home/copy.asm
@@ -1,14 +1,14 @@
FarCopyData::
; Copy bc bytes from a:hl to de.
ld [wBuffer], a
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
push af
ld a, [wBuffer]
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
call CopyData
pop af
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ret
diff --git a/home/copy2.asm b/home/copy2.asm
index d4f35668..521223b6 100644
--- a/home/copy2.asm
+++ b/home/copy2.asm
@@ -2,24 +2,24 @@ FarCopyData2::
; Identical to FarCopyData, but uses hROMBankTemp
; as temp space instead of wBuffer.
ld [hROMBankTemp], a
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
push af
ld a, [hROMBankTemp]
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
call CopyData
pop af
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ret
FarCopyData3::
; Copy bc bytes from a:de to hl.
ld [hROMBankTemp], a
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
push af
ld a, [hROMBankTemp]
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
push hl
push de
@@ -31,7 +31,7 @@ FarCopyData3::
pop de
pop hl
pop af
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ret
@@ -39,10 +39,10 @@ FarCopyDataDouble::
; Expand bc bytes of 1bpp image data
; from a:hl to 2bpp data at de.
ld [hROMBankTemp], a
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
push af
ld a, [hROMBankTemp]
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
.loop
ld a, [hli]
@@ -55,7 +55,7 @@ FarCopyDataDouble::
or b
jr nz, .loop
pop af
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ret
@@ -64,27 +64,27 @@ CopyVideoData::
; tiles from b:de to hl, 8 tiles at a time.
; This takes c/8 frames.
- ld a, [H_AUTOBGTRANSFERENABLED]
+ ld a, [hAutoBGTransferEnabled]
push af
xor a ; disable auto-transfer while copying
- ld [H_AUTOBGTRANSFERENABLED], a
+ ld [hAutoBGTransferEnabled], a
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
ld [hROMBankTemp], a
ld a, b
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ld a, e
- ld [H_VBCOPYSRC], a
+ ld [hVBlankCopySource], a
ld a, d
- ld [H_VBCOPYSRC + 1], a
+ ld [hVBlankCopySource + 1], a
ld a, l
- ld [H_VBCOPYDEST], a
+ ld [hVBlankCopyDest], a
ld a, h
- ld [H_VBCOPYDEST + 1], a
+ ld [hVBlankCopyDest + 1], a
.loop
ld a, c
@@ -92,18 +92,18 @@ CopyVideoData::
jr nc, .keepgoing
.done
- ld [H_VBCOPYSIZE], a
+ ld [hVBlankCopySize], a
call DelayFrame
ld a, [hROMBankTemp]
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
pop af
- ld [H_AUTOBGTRANSFERENABLED], a
+ ld [hAutoBGTransferEnabled], a
ret
.keepgoing
ld a, 8
- ld [H_VBCOPYSIZE], a
+ ld [hVBlankCopySize], a
call DelayFrame
ld a, c
sub 8
@@ -114,26 +114,26 @@ CopyVideoDataDouble::
; Wait for the next VBlank, then copy c 1bpp
; tiles from b:de to hl, 8 tiles at a time.
; This takes c/8 frames.
- ld a, [H_AUTOBGTRANSFERENABLED]
+ ld a, [hAutoBGTransferEnabled]
push af
xor a ; disable auto-transfer while copying
- ld [H_AUTOBGTRANSFERENABLED], a
- ld a, [H_LOADEDROMBANK]
+ ld [hAutoBGTransferEnabled], a
+ ld a, [hLoadedROMBank]
ld [hROMBankTemp], a
ld a, b
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ld a, e
- ld [H_VBCOPYDOUBLESRC], a
+ ld [hVBlankCopyDoubleSource], a
ld a, d
- ld [H_VBCOPYDOUBLESRC + 1], a
+ ld [hVBlankCopyDoubleSource + 1], a
ld a, l
- ld [H_VBCOPYDOUBLEDEST], a
+ ld [hVBlankCopyDoubleDest], a
ld a, h
- ld [H_VBCOPYDOUBLEDEST + 1], a
+ ld [hVBlankCopyDoubleDest + 1], a
.loop
ld a, c
@@ -141,18 +141,18 @@ CopyVideoDataDouble::
jr nc, .keepgoing
.done
- ld [H_VBCOPYDOUBLESIZE], a
+ ld [hVBlankCopyDoubleSize], a
call DelayFrame
ld a, [hROMBankTemp]
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
pop af
- ld [H_AUTOBGTRANSFERENABLED], a
+ ld [hAutoBGTransferEnabled], a
ret
.keepgoing
ld a, 8
- ld [H_VBCOPYDOUBLESIZE], a
+ ld [hVBlankCopyDoubleSize], a
call DelayFrame
ld a, c
sub 8
@@ -200,16 +200,16 @@ CopyScreenTileBufferToVRAM::
.setup
ld a, d
- ld [H_VBCOPYBGSRC+1], a
+ ld [hVBlankCopyBGSource+1], a
call GetRowColAddressBgMap
ld a, l
- ld [H_VBCOPYBGDEST], a
+ ld [hVBlankCopyBGDest], a
ld a, h
- ld [H_VBCOPYBGDEST+1], a
+ ld [hVBlankCopyBGDest+1], a
ld a, c
- ld [H_VBCOPYBGNUMROWS], a
+ ld [hVBlankCopyBGNumRows], a
ld a, e
- ld [H_VBCOPYBGSRC], a
+ ld [hVBlankCopyBGSource], a
ret
ClearScreen::
diff --git a/home/header.asm b/home/header.asm
new file mode 100644
index 00000000..047f97f4
--- /dev/null
+++ b/home/header.asm
@@ -0,0 +1,57 @@
+; rst vectors (unused)
+
+SECTION "rst0", ROM0[$0000]
+ rst $38
+
+SECTION "rst8", ROM0[$0008]
+ rst $38
+
+SECTION "rst10", ROM0[$0010]
+ rst $38
+
+SECTION "rst18", ROM0[$0018]
+ rst $38
+
+SECTION "rst20", ROM0[$0020]
+ rst $38
+
+SECTION "rst28", ROM0[$0028]
+ rst $38
+
+SECTION "rst30", ROM0[$0030]
+ rst $38
+
+SECTION "rst38", ROM0[$0038]
+ rst $38
+
+
+; Game Boy hardware interrupts
+
+SECTION "vblank", ROM0[$0040]
+ jp VBlank
+
+SECTION "lcd", ROM0[$0048]
+ rst $38
+
+SECTION "timer", ROM0[$0050]
+ jp Timer
+
+SECTION "serial", ROM0[$0058]
+ jp Serial
+
+SECTION "joypad", ROM0[$0060]
+ reti
+
+
+SECTION "Header", ROM0[$0100]
+
+Start::
+; Nintendo requires all Game Boy ROMs to begin with a nop ($00) and a jp ($C3)
+; to the starting address.
+ nop
+ jp _Start
+
+; The Game Boy cartridge header data is patched over by rgbfix.
+; This makes sure it doesn't get used for anything else.
+
+ ds $0150 - @, $00
diff --git a/home/init.asm b/home/init.asm
index 9e3e2c82..83238bad 100644
--- a/home/init.asm
+++ b/home/init.asm
@@ -41,8 +41,8 @@ rLCDC_DEFAULT EQU %11100011
ld sp, wStack
- ld hl, $c000 ; start of WRAM
- ld bc, $2000 ; size of WRAM
+ ld hl, WRAM0_Begin
+ ld bc, WRAM1_End - WRAM0_Begin
.loop
ld [hl], 0
inc hl
@@ -53,14 +53,14 @@ rLCDC_DEFAULT EQU %11100011
call ClearVram
- ld hl, $ff80
- ld bc, $ffff - $ff80
+ ld hl, HRAM_Begin
+ ld bc, HRAM_End - HRAM_Begin
call FillMemory
call ClearSprites
- ld a, Bank(WriteDMACodeToHRAM)
- ld [H_LOADEDROMBANK], a
+ ld a, BANK(WriteDMACodeToHRAM)
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
call WriteDMACodeToHRAM
@@ -101,9 +101,9 @@ rLCDC_DEFAULT EQU %11100011
ld [wAudioROMBank], a
ld [wAudioSavedROMBank], a
ld a, $9c
- ld [H_AUTOBGTRANSFERDEST + 1], a
+ ld [hAutoBGTransferDest + 1], a
xor a
- ld [H_AUTOBGTRANSFERDEST], a
+ ld [hAutoBGTransferDest], a
dec a
ld [wUpdateSpritesEnabled], a
@@ -119,8 +119,8 @@ rLCDC_DEFAULT EQU %11100011
jp SetDefaultNamesBeforeTitlescreen
ClearVram::
- ld hl, $8000
- ld bc, $2000
+ ld hl, VRAM_Begin
+ ld bc, VRAM_End - VRAM_Begin
xor a
jp FillMemory
diff --git a/home/lcd.asm b/home/lcd.asm
new file mode 100644
index 00000000..e88a42b3
--- /dev/null
+++ b/home/lcd.asm
@@ -0,0 +1,25 @@
+DisableLCD::
+ xor a
+ ld [rIF], a
+ ld a, [rIE]
+ ld b, a
+ res 0, a
+ ld [rIE], a
+
+.wait
+ ld a, [rLY]
+ cp LY_VBLANK
+ jr nz, .wait
+
+ ld a, [rLCDC]
+ and $ff ^ rLCDC_ENABLE_MASK
+ ld [rLCDC], a
+ ld a, b
+ ld [rIE], a
+ ret
+
+EnableLCD::
+ ld a, [rLCDC]
+ set rLCDC_ENABLE, a
+ ld [rLCDC], a
+ ret
diff --git a/home/list_menu.asm b/home/list_menu.asm
new file mode 100644
index 00000000..4ce973b2
--- /dev/null
+++ b/home/list_menu.asm
@@ -0,0 +1,526 @@
+; INPUT:
+; [wListMenuID] = list menu ID
+; [wListPointer] = address of the list (2 bytes)
+DisplayListMenuID::
+ xor a
+ ld [hAutoBGTransferEnabled], a ; disable auto-transfer
+ ld a, 1
+ ld [hJoy7], a ; joypad state update flag
+ ld a, [wBattleType]
+ and a ; is it the Old Man battle?
+ jr nz, .specialBattleType
+ ld a, $01 ; hardcoded bank
+ jr .bankswitch
+.specialBattleType ; Old Man battle
+ ld a, BANK(DisplayBattleMenu)
+.bankswitch
+ call BankswitchHome
+ ld hl, wd730
+ set 6, [hl] ; turn off letter printing delay
+ xor a
+ ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped
+ ld [wListCount], a
+ ld a, [wListPointer]
+ ld l, a
+ ld a, [wListPointer + 1]
+ ld h, a ; hl = address of the list
+ ld a, [hl] ; the first byte is the number of entries in the list
+ ld [wListCount], a
+ ld a, LIST_MENU_BOX
+ ld [wTextBoxID], a
+ call DisplayTextBoxID ; draw the menu text box
+ call UpdateSprites ; disable sprites behind the text box
+; the code up to .skipMovingSprites appears to be useless
+ coord hl, 4, 2 ; coordinates of upper left corner of menu text box
+ lb de, 9, 14 ; height and width of menu text box
+ ld a, [wListMenuID]
+ and a ; is it a PC pokemon list?
+ jr nz, .skipMovingSprites
+ call UpdateSprites
+.skipMovingSprites
+ ld a, 1 ; max menu item ID is 1 if the list has less than 2 entries
+ ld [wMenuWatchMovingOutOfBounds], a
+ ld a, [wListCount]
+ cp 2 ; does the list have less than 2 entries?
+ jr c, .setMenuVariables
+ ld a, 2 ; max menu item ID is 2 if the list has at least 2 entries
+.setMenuVariables
+ ld [wMaxMenuItem], a
+ ld a, 4
+ ld [wTopMenuItemY], a
+ ld a, 5
+ ld [wTopMenuItemX], a
+ ld a, A_BUTTON | B_BUTTON | SELECT
+ ld [wMenuWatchedKeys], a
+ ld c, 10
+ call DelayFrames
+
+DisplayListMenuIDLoop::
+ xor a
+ ld [hAutoBGTransferEnabled], a ; disable transfer
+ call PrintListMenuEntries
+ ld a, 1
+ ld [hAutoBGTransferEnabled], a ; enable transfer
+ call Delay3
+ ld a, [wBattleType]
+ and a ; is it the Old Man battle?
+ jr z, .notOldManBattle
+.oldManBattle
+ ld a, "▶"
+ Coorda 5, 4 ; place menu cursor in front of first menu entry
+ ld c, 80
+ call DelayFrames
+ xor a
+ ld [wCurrentMenuItem], a
+ coord hl, 5, 4
+ ld a, l
+ ld [wMenuCursorLocation], a
+ ld a, h
+ ld [wMenuCursorLocation + 1], a
+ jr .buttonAPressed
+.notOldManBattle
+ call LoadGBPal
+ call HandleMenuInput
+ push af
+ call PlaceMenuCursor
+ pop af
+ bit 0, a ; was the A button pressed?
+ jp z, .checkOtherKeys
+.buttonAPressed
+ ld a, [wCurrentMenuItem]
+ call PlaceUnfilledArrowMenuCursor
+
+; pointless because both values are overwritten before they are read
+ ld a, $01
+ ld [wMenuExitMethod], a
+ ld [wChosenMenuItem], a
+
+ xor a
+ ld [wMenuWatchMovingOutOfBounds], a
+ ld a, [wCurrentMenuItem]
+ ld c, a
+ ld a, [wListScrollOffset]
+ add c
+ ld c, a
+ ld a, [wListCount]
+ and a ; is the list empty?
+ jp z, ExitListMenu ; if so, exit the menu
+ dec a
+ cp c ; did the player select Cancel?
+ jp c, ExitListMenu ; if so, exit the menu
+ ld a, c
+ ld [wWhichPokemon], a
+ ld a, [wListMenuID]
+ cp ITEMLISTMENU
+ jr nz, .skipMultiplying
+; if it's an item menu
+ sla c ; item entries are 2 bytes long, so multiply by 2
+.skipMultiplying
+ ld a, [wListPointer]
+ ld l, a
+ ld a, [wListPointer + 1]
+ ld h, a
+ inc hl ; hl = beginning of list entries
+ ld b, 0
+ add hl, bc
+ ld a, [hl]
+ ld [wcf91], a
+ ld a, [wListMenuID]
+ and a ; is it a PC pokemon list?
+ jr z, .pokemonList
+ push hl
+ call GetItemPrice
+ pop hl
+ ld a, [wListMenuID]
+ cp ITEMLISTMENU
+ jr nz, .skipGettingQuantity
+; if it's an item menu
+ inc hl
+ ld a, [hl] ; a = item quantity
+ ld [wMaxItemQuantity], a
+.skipGettingQuantity
+ ld a, [wcf91]
+ ld [wd0b5], a
+ ld a, BANK(ItemNames)
+ ld [wPredefBank], a
+ call GetName
+ jr .storeChosenEntry
+.pokemonList
+ ld hl, wPartyCount
+ ld a, [wListPointer]
+ cp l ; is it a list of party pokemon or box pokemon?
+ ld hl, wPartyMonNicks
+ jr z, .getPokemonName
+ ld hl, wBoxMonNicks ; box pokemon names
+.getPokemonName
+ ld a, [wWhichPokemon]
+ call GetPartyMonName
+.storeChosenEntry ; store the menu entry that the player chose and return
+ ld de, wcd6d
+ call CopyStringToCF4B ; copy name to wcf4b
+ ld a, CHOSE_MENU_ITEM
+ ld [wMenuExitMethod], a
+ ld a, [wCurrentMenuItem]
+ ld [wChosenMenuItem], a
+ xor a
+ ld [hJoy7], a ; joypad state update flag
+ ld hl, wd730
+ res 6, [hl] ; turn on letter printing delay
+ jp BankswitchBack
+.checkOtherKeys ; check B, SELECT, Up, and Down keys
+ bit 1, a ; was the B button pressed?
+ jp nz, ExitListMenu ; if so, exit the menu
+ bit 2, a ; was the select button pressed?
+ jp nz, HandleItemListSwapping ; if so, allow the player to swap menu entries
+ ld b, a
+ bit 7, b ; was Down pressed?
+ ld hl, wListScrollOffset
+ jr z, .upPressed
+.downPressed
+ ld a, [hl]
+ add 3
+ ld b, a
+ ld a, [wListCount]
+ cp b ; will going down scroll past the Cancel button?
+ jp c, DisplayListMenuIDLoop
+ inc [hl] ; if not, go down
+ jp DisplayListMenuIDLoop
+.upPressed
+ ld a, [hl]
+ and a
+ jp z, DisplayListMenuIDLoop
+ dec [hl]
+ jp DisplayListMenuIDLoop
+
+DisplayChooseQuantityMenu::
+; text box dimensions/coordinates for just quantity
+ coord hl, 15, 9
+ ld b, 1 ; height
+ ld c, 3 ; width
+ ld a, [wListMenuID]
+ cp PRICEDITEMLISTMENU
+ jr nz, .drawTextBox
+; text box dimensions/coordinates for quantity and price
+ coord hl, 7, 9
+ ld b, 1 ; height
+ ld c, 11 ; width
+.drawTextBox
+ call TextBoxBorder
+ coord hl, 16, 10
+ ld a, [wListMenuID]
+ cp PRICEDITEMLISTMENU
+ jr nz, .printInitialQuantity
+ coord hl, 8, 10
+.printInitialQuantity
+ ld de, InitialQuantityText
+ call PlaceString
+ xor a
+ ld [wItemQuantity], a ; initialize current quantity to 0
+ jp .incrementQuantity
+.waitForKeyPressLoop
+ call JoypadLowSensitivity
+ ld a, [hJoyPressed] ; newly pressed buttons
+ bit 0, a ; was the A button pressed?
+ jp nz, .buttonAPressed
+ bit 1, a ; was the B button pressed?
+ jp nz, .buttonBPressed
+ bit 6, a ; was Up pressed?
+ jr nz, .incrementQuantity
+ bit 7, a ; was Down pressed?
+ jr nz, .decrementQuantity
+ jr .waitForKeyPressLoop
+.incrementQuantity
+ ld a, [wMaxItemQuantity]
+ inc a
+ ld b, a
+ ld hl, wItemQuantity ; current quantity
+ inc [hl]
+ ld a, [hl]
+ cp b
+ jr nz, .handleNewQuantity
+; wrap to 1 if the player goes above the max quantity
+ ld a, 1
+ ld [hl], a
+ jr .handleNewQuantity
+.decrementQuantity
+ ld hl, wItemQuantity ; current quantity
+ dec [hl]
+ jr nz, .handleNewQuantity
+; wrap to the max quantity if the player goes below 1
+ ld a, [wMaxItemQuantity]
+ ld [hl], a
+.handleNewQuantity
+ coord hl, 17, 10
+ ld a, [wListMenuID]
+ cp PRICEDITEMLISTMENU
+ jr nz, .printQuantity
+.printPrice
+ ld c, $03
+ ld a, [wItemQuantity]
+ ld b, a
+ ld hl, hMoney ; total price
+; initialize total price to 0
+ xor a
+ ld [hli], a
+ ld [hli], a
+ ld [hl], a
+.addLoop ; loop to multiply the individual price by the quantity to get the total price
+ ld de, hMoney + 2
+ ld hl, hItemPrice + 2
+ push bc
+ predef AddBCDPredef ; add the individual price to the current sum
+ pop bc
+ dec b
+ jr nz, .addLoop
+ ld a, [hHalveItemPrices]
+ and a ; should the price be halved (for selling items)?
+ jr z, .skipHalvingPrice
+ xor a
+ ld [hDivideBCDDivisor], a
+ ld [hDivideBCDDivisor + 1], a
+ ld a, $02
+ ld [hDivideBCDDivisor + 2], a
+ predef DivideBCDPredef3 ; halves the price
+; store the halved price
+ ld a, [hDivideBCDQuotient]
+ ld [hMoney], a
+ ld a, [hDivideBCDQuotient + 1]
+ ld [hMoney + 1], a
+ ld a, [hDivideBCDQuotient + 2]
+ ld [hMoney + 2], a
+.skipHalvingPrice
+ coord hl, 12, 10
+ ld de, SpacesBetweenQuantityAndPriceText
+ call PlaceString
+ ld de, hMoney ; total price
+ ld c, $a3
+ call PrintBCDNumber
+ coord hl, 9, 10
+.printQuantity
+ ld de, wItemQuantity ; current quantity
+ lb bc, LEADING_ZEROES | 1, 2 ; 1 byte, 2 digits
+ call PrintNumber
+ jp .waitForKeyPressLoop
+.buttonAPressed ; the player chose to make the transaction
+ xor a
+ ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped
+ ret
+.buttonBPressed ; the player chose to cancel the transaction
+ xor a
+ ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped
+ ld a, $ff
+ ret
+
+InitialQuantityText::
+ db "×01@"
+
+SpacesBetweenQuantityAndPriceText::
+ db " @"
+
+ExitListMenu::
+ ld a, [wCurrentMenuItem]
+ ld [wChosenMenuItem], a
+ ld a, CANCELLED_MENU
+ ld [wMenuExitMethod], a
+ ld [wMenuWatchMovingOutOfBounds], a
+ xor a
+ ld [hJoy7], a
+ ld hl, wd730
+ res 6, [hl]
+ call BankswitchBack
+ xor a
+ ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped
+ scf
+ ret
+
+PrintListMenuEntries::
+ coord hl, 5, 3
+ ld b, 9
+ ld c, 14
+ call ClearScreenArea
+ ld a, [wListPointer]
+ ld e, a
+ ld a, [wListPointer + 1]
+ ld d, a
+ inc de ; de = beginning of list entries
+ ld a, [wListScrollOffset]
+ ld c, a
+ ld a, [wListMenuID]
+ cp ITEMLISTMENU
+ ld a, c
+ jr nz, .skipMultiplying
+; if it's an item menu
+; item entries are 2 bytes long, so multiply by 2
+ sla a
+ sla c
+.skipMultiplying
+ add e
+ ld e, a
+ jr nc, .noCarry
+ inc d
+.noCarry
+ coord hl, 6, 4 ; coordinates of first list entry name
+ ld b, 4 ; print 4 names
+.loop
+ ld a, b
+ ld [wWhichPokemon], a
+ ld a, [de]
+ ld [wd11e], a
+ cp $ff
+ jp z, .printCancelMenuItem
+ push bc
+ push de
+ push hl
+ push hl
+ push de
+ ld a, [wListMenuID]
+ and a
+ jr z, .pokemonPCMenu
+ cp MOVESLISTMENU
+ jr z, .movesMenu
+.itemMenu
+ call GetItemName
+ jr .placeNameString
+.pokemonPCMenu
+ push hl
+ ld hl, wPartyCount
+ ld a, [wListPointer]
+ cp l ; is it a list of party pokemon or box pokemon?
+ ld hl, wPartyMonNicks
+ jr z, .getPokemonName
+ ld hl, wBoxMonNicks ; box pokemon names
+.getPokemonName
+ ld a, [wWhichPokemon]
+ ld b, a
+ ld a, 4
+ sub b
+ ld b, a
+ ld a, [wListScrollOffset]
+ add b
+ call GetPartyMonName
+ pop hl
+ jr .placeNameString
+.movesMenu
+ call GetMoveName
+.placeNameString
+ call PlaceString
+ pop de
+ pop hl
+ ld a, [wPrintItemPrices]
+ and a ; should prices be printed?
+ jr z, .skipPrintingItemPrice
+.printItemPrice
+ push hl
+ ld a, [de]
+ ld de, ItemPrices
+ ld [wcf91], a
+ call GetItemPrice ; get price
+ pop hl
+ ld bc, SCREEN_WIDTH + 5 ; 1 row down and 5 columns right
+ add hl, bc
+ ld c, $a3 ; no leading zeroes, right-aligned, print currency symbol, 3 bytes
+ call PrintBCDNumber
+.skipPrintingItemPrice
+ ld a, [wListMenuID]
+ and a
+ jr nz, .skipPrintingPokemonLevel
+.printPokemonLevel
+ ld a, [wd11e]
+ push af
+ push hl
+ ld hl, wPartyCount
+ ld a, [wListPointer]
+ cp l ; is it a list of party pokemon or box pokemon?
+ ld a, PLAYER_PARTY_DATA
+ jr z, .next
+ ld a, BOX_DATA
+.next
+ ld [wMonDataLocation], a
+ ld hl, wWhichPokemon
+ ld a, [hl]
+ ld b, a
+ ld a, $04
+ sub b
+ ld b, a
+ ld a, [wListScrollOffset]
+ add b
+ ld [hl], a
+ call LoadMonData
+ ld a, [wMonDataLocation]
+ and a ; is it a list of party pokemon or box pokemon?
+ jr z, .skipCopyingLevel
+.copyLevel
+ ld a, [wLoadedMonBoxLevel]
+ ld [wLoadedMonLevel], a
+.skipCopyingLevel
+ pop hl
+ ld bc, $1c
+ add hl, bc
+ call PrintLevel
+ pop af
+ ld [wd11e], a
+.skipPrintingPokemonLevel
+ pop hl
+ pop de
+ inc de
+ ld a, [wListMenuID]
+ cp ITEMLISTMENU
+ jr nz, .nextListEntry
+.printItemQuantity
+ ld a, [wd11e]
+ ld [wcf91], a
+ call IsKeyItem ; check if item is unsellable
+ ld a, [wIsKeyItem]
+ and a ; is the item unsellable?
+ jr nz, .skipPrintingItemQuantity ; if so, don't print the quantity
+ push hl
+ ld bc, SCREEN_WIDTH + 8 ; 1 row down and 8 columns right
+ add hl, bc
+ ld a, "×"
+ ld [hli], a
+ ld a, [wd11e]
+ push af
+ ld a, [de]
+ ld [wMaxItemQuantity], a
+ push de
+ ld de, wd11e
+ ld [de], a
+ lb bc, 1, 2
+ call PrintNumber
+ pop de
+ pop af
+ ld [wd11e], a
+ pop hl
+.skipPrintingItemQuantity
+ inc de
+ pop bc
+ inc c
+ push bc
+ inc c
+ ld a, [wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1)
+ and a ; is an item being swapped?
+ jr z, .nextListEntry
+ sla a
+ cp c ; is it this item?
+ jr nz, .nextListEntry
+ dec hl
+ ld a, $ec ; unfilled right arrow menu cursor to indicate an item being swapped
+ ld [hli], a
+.nextListEntry
+ ld bc, 2 * SCREEN_WIDTH ; 2 rows
+ add hl, bc
+ pop bc
+ inc c
+ dec b
+ jp nz, .loop
+ ld bc, -8
+ add hl, bc
+ ld a, "▼"
+ ld [hl], a
+ ret
+.printCancelMenuItem
+ ld de, ListMenuCancelText
+ jp PlaceString
+
+ListMenuCancelText::
+ db "CANCEL@"
diff --git a/home/move_mon.asm b/home/move_mon.asm
new file mode 100644
index 00000000..e13ebf4e
--- /dev/null
+++ b/home/move_mon.asm
@@ -0,0 +1,242 @@
+; Function to remove a pokemon from the party or the current box.
+; wWhichPokemon determines the pokemon.
+; [wRemoveMonFromBox] == 0 specifies the party.
+; [wRemoveMonFromBox] != 0 specifies the current box.
+RemovePokemon::
+ jpab _RemovePokemon
+
+AddPartyMon::
+ push hl
+ push de
+ push bc
+ callba _AddPartyMon
+ pop bc
+ pop de
+ pop hl
+ ret
+
+; calculates all 5 stats of current mon and writes them to [de]
+CalcStats::
+ ld c, $0
+.statsLoop
+ inc c
+ call CalcStat
+ ld a, [hMultiplicand+1]
+ ld [de], a
+ inc de
+ ld a, [hMultiplicand+2]
+ ld [de], a
+ inc de
+ ld a, c
+ cp NUM_STATS
+ jr nz, .statsLoop
+ ret
+
+; calculates stat c of current mon
+; c: stat to calc (HP=1,Atk=2,Def=3,Spd=4,Spc=5)
+; b: consider stat exp?
+; hl: base ptr to stat exp values ([hl + 2*c - 1] and [hl + 2*c])
+CalcStat::
+ push hl
+ push de
+ push bc
+ ld a, b
+ ld d, a
+ push hl
+ ld hl, wMonHeader
+ ld b, $0
+ add hl, bc
+ ld a, [hl] ; read base value of stat
+ ld e, a
+ pop hl
+ push hl
+ sla c
+ ld a, d
+ and a
+ jr z, .statExpDone ; consider stat exp?
+ add hl, bc ; skip to corresponding stat exp value
+.statExpLoop ; calculates ceil(Sqrt(stat exp)) in b
+ xor a
+ ld [hMultiplicand], a
+ ld [hMultiplicand+1], a
+ inc b ; increment current stat exp bonus
+ ld a, b
+ cp $ff
+ jr z, .statExpDone
+ ld [hMultiplicand+2], a
+ ld [hMultiplier], a
+ call Multiply
+ ld a, [hld]
+ ld d, a
+ ld a, [hProduct + 3]
+ sub d
+ ld a, [hli]
+ ld d, a
+ ld a, [hProduct + 2]
+ sbc d ; test if (current stat exp bonus)^2 < stat exp
+ jr c, .statExpLoop
+.statExpDone
+ srl c
+ pop hl
+ push bc
+ ld bc, wPartyMon1DVs - (wPartyMon1HPExp - 1) ; also wEnemyMonDVs - wEnemyMonHP
+ add hl, bc
+ pop bc
+ ld a, c
+ cp $2
+ jr z, .getAttackIV
+ cp $3
+ jr z, .getDefenseIV
+ cp $4
+ jr z, .getSpeedIV
+ cp $5
+ jr z, .getSpecialIV
+.getHpIV
+ push bc
+ ld a, [hl] ; Atk IV
+ swap a
+ and $1
+ sla a
+ sla a
+ sla a
+ ld b, a
+ ld a, [hli] ; Def IV
+ and $1
+ sla a
+ sla a
+ add b
+ ld b, a
+ ld a, [hl] ; Spd IV
+ swap a
+ and $1
+ sla a
+ add b
+ ld b, a
+ ld a, [hl] ; Spc IV
+ and $1
+ add b ; HP IV: LSB of the other 4 IVs
+ pop bc
+ jr .calcStatFromIV
+.getAttackIV
+ ld a, [hl]
+ swap a
+ and $f
+ jr .calcStatFromIV
+.getDefenseIV
+ ld a, [hl]
+ and $f
+ jr .calcStatFromIV
+.getSpeedIV
+ inc hl
+ ld a, [hl]
+ swap a
+ and $f
+ jr .calcStatFromIV
+.getSpecialIV
+ inc hl
+ ld a, [hl]
+ and $f
+.calcStatFromIV
+ ld d, $0
+ add e
+ ld e, a
+ jr nc, .noCarry
+ inc d ; de = Base + IV
+.noCarry
+ sla e
+ rl d ; de = (Base + IV) * 2
+ srl b
+ srl b ; b = ceil(Sqrt(stat exp)) / 4
+ ld a, b
+ add e
+ jr nc, .noCarry2
+ inc d ; de = (Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4
+.noCarry2
+ ld [hMultiplicand+2], a
+ ld a, d
+ ld [hMultiplicand+1], a
+ xor a
+ ld [hMultiplicand], a
+ ld a, [wCurEnemyLVL]
+ ld [hMultiplier], a
+ call Multiply ; ((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level
+ ld a, [hMultiplicand]
+ ld [hDividend], a
+ ld a, [hMultiplicand+1]
+ ld [hDividend+1], a
+ ld a, [hMultiplicand+2]
+ ld [hDividend+2], a
+ ld a, $64
+ ld [hDivisor], a
+ ld a, $3
+ ld b, a
+ call Divide ; (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100
+ ld a, c
+ cp $1
+ ld a, 5 ; + 5 for non-HP stat
+ jr nz, .notHPStat
+ ld a, [wCurEnemyLVL]
+ ld b, a
+ ld a, [hMultiplicand+2]
+ add b
+ ld [hMultiplicand+2], a
+ jr nc, .noCarry3
+ ld a, [hMultiplicand+1]
+ inc a
+ ld [hMultiplicand+1], a ; HP: (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 + Level
+.noCarry3
+ ld a, 10 ; +10 for HP stat
+.notHPStat
+ ld b, a
+ ld a, [hMultiplicand+2]
+ add b
+ ld [hMultiplicand+2], a
+ jr nc, .noCarry4
+ ld a, [hMultiplicand+1]
+ inc a ; non-HP: (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 + 5
+ ld [hMultiplicand+1], a ; HP: (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 + Level + 10
+.noCarry4
+ ld a, [hMultiplicand+1] ; check for overflow (>999)
+ cp 999 / $100 + 1
+ jr nc, .overflow
+ cp 999 / $100
+ jr c, .noOverflow
+ ld a, [hMultiplicand+2]
+ cp 999 % $100 + 1
+ jr c, .noOverflow
+.overflow
+ ld a, 999 / $100 ; overflow: cap at 999
+ ld [hMultiplicand+1], a
+ ld a, 999 % $100
+ ld [hMultiplicand+2], a
+.noOverflow
+ pop bc
+ pop de
+ pop hl
+ ret
+
+AddEnemyMonToPlayerParty::
+ ld a, [hLoadedROMBank]
+ push af
+ ld a, BANK(_AddEnemyMonToPlayerParty)
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ call _AddEnemyMonToPlayerParty
+ pop bc
+ ld a, b
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ ret
+
+MoveMon::
+ ld a, [hLoadedROMBank]
+ push af
+ ld a, BANK(_MoveMon)
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ call _MoveMon
+ pop bc
+ ld a, b
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ ret
diff --git a/home/names.asm b/home/names.asm
new file mode 100644
index 00000000..cbc8910b
--- /dev/null
+++ b/home/names.asm
@@ -0,0 +1,141 @@
+GetMonName::
+ push hl
+ ld a, [hLoadedROMBank]
+ push af
+ ld a, BANK(MonsterNames)
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ ld a, [wd11e]
+ dec a
+ ld hl, MonsterNames
+ ld c, 10
+ ld b, 0
+ call AddNTimes
+ ld de, wcd6d
+ push de
+ ld bc, 10
+ call CopyData
+ ld hl, wcd6d + 10
+ ld [hl], "@"
+ pop de
+ pop af
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ pop hl
+ ret
+
+GetItemName::
+; given an item ID at [wd11e], store the name of the item into a string
+; starting at wcd6d
+ push hl
+ push bc
+ ld a, [wd11e]
+ cp HM_01 ; is this a TM/HM?
+ jr nc, .Machine
+
+ ld [wd0b5], a
+ ld a, ITEM_NAME
+ ld [wNameListType], a
+ ld a, BANK(ItemNames)
+ ld [wPredefBank], a
+ call GetName
+ jr .Finish
+
+.Machine
+ call GetMachineName
+.Finish
+ ld de, wcd6d ; pointer to where item name is stored in RAM
+ pop bc
+ pop hl
+ ret
+
+GetMachineName::
+; copies the name of the TM/HM in [wd11e] to wcd6d
+ push hl
+ push de
+ push bc
+ ld a, [wd11e]
+ push af
+ cp TM_01 ; is this a TM? [not HM]
+ jr nc, .WriteTM
+; if HM, then write "HM" and add 5 to the item ID, so we can reuse the
+; TM printing code
+ add 5
+ ld [wd11e], a
+ ld hl, HiddenPrefix ; points to "HM"
+ ld bc, 2
+ jr .WriteMachinePrefix
+.WriteTM
+ ld hl, TechnicalPrefix ; points to "TM"
+ ld bc, 2
+.WriteMachinePrefix
+ ld de, wcd6d
+ call CopyData
+
+; now get the machine number and convert it to text
+ ld a, [wd11e]
+ sub TM_01 - 1
+ ld b, "0"
+.FirstDigit
+ sub 10
+ jr c, .SecondDigit
+ inc b
+ jr .FirstDigit
+.SecondDigit
+ add 10
+ push af
+ ld a, b
+ ld [de], a
+ inc de
+ pop af
+ ld b, "0"
+ add b
+ ld [de], a
+ inc de
+ ld a, "@"
+ ld [de], a
+ pop af
+ ld [wd11e], a
+ pop bc
+ pop de
+ pop hl
+ ret
+
+TechnicalPrefix::
+ db "TM"
+HiddenPrefix::
+ db "HM"
+
+; sets carry if item is HM, clears carry if item is not HM
+; Input: a = item ID
+IsItemHM::
+ cp HM_01
+ jr c, .notHM
+ cp TM_01
+ ret
+.notHM
+ and a
+ ret
+
+; sets carry if move is an HM, clears carry if move is not an HM
+; Input: a = move ID
+IsMoveHM::
+ ld hl, HMMoves
+ ld de, 1
+ jp IsInArray
+
+HMMoves::
+INCLUDE "data/moves/hm_moves.asm"
+
+GetMoveName::
+ push hl
+ ld a, MOVE_NAME
+ ld [wNameListType], a
+ ld a, [wd11e]
+ ld [wd0b5], a
+ ld a, BANK(MoveNames)
+ ld [wPredefBank], a
+ call GetName
+ ld de, wcd6d ; pointer to where move name is stored in RAM
+ pop hl
+ ret
diff --git a/home/names2.asm b/home/names2.asm
new file mode 100644
index 00000000..319febd3
--- /dev/null
+++ b/home/names2.asm
@@ -0,0 +1,93 @@
+NamePointers::
+ dw MonsterNames
+ dw MoveNames
+ dw UnusedNames
+ dw ItemNames
+ dw wPartyMonOT ; player's OT names list
+ dw wEnemyMonOT ; enemy's OT names list
+ dw TrainerNames
+
+GetName::
+; arguments:
+; [wd0b5] = which name
+; [wNameListType] = which list
+; [wPredefBank] = bank of list
+;
+; returns pointer to name in de
+ ld a, [wd0b5]
+ ld [wd11e], a
+
+ ; TM names are separate from item names.
+ ; BUG: This applies to all names instead of just items.
+ cp HM_01
+ jp nc, GetMachineName
+
+ ld a, [hLoadedROMBank]
+ push af
+ push hl
+ push bc
+ push de
+ ld a, [wNameListType] ;List3759_entrySelector
+ dec a
+ jr nz, .otherEntries
+ ;1 = MON_NAMES
+ call GetMonName
+ ld hl, NAME_LENGTH
+ add hl, de
+ ld e, l
+ ld d, h
+ jr .gotPtr
+.otherEntries
+ ;2-7 = OTHER ENTRIES
+ ld a, [wPredefBank]
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ ld a, [wNameListType] ;VariousNames' entryID
+ dec a
+ add a
+ ld d, 0
+ ld e, a
+ jr nc, .skip
+ inc d
+.skip
+ ld hl, NamePointers
+ add hl, de
+ ld a, [hli]
+ ld [hSwapTemp + 1], a
+ ld a, [hl]
+ ld [hSwapTemp], a
+ ld a, [hSwapTemp]
+ ld h, a
+ ld a, [hSwapTemp + 1]
+ ld l, a
+ ld a, [wd0b5]
+ ld b, a
+ ld c, 0
+.nextName
+ ld d, h
+ ld e, l
+.nextChar
+ ld a, [hli]
+ cp "@"
+ jr nz, .nextChar
+ inc c ;entry counter
+ ld a, b ;wanted entry
+ cp c
+ jr nz, .nextName
+ ld h, d
+ ld l, e
+ ld de, wcd6d
+ ld bc, $14
+ call CopyData
+.gotPtr
+ ld a, e
+ ld [wUnusedCF8D], a
+ ld a, d
+ ld [wUnusedCF8D + 1], a
+ pop de
+ pop bc
+ pop hl
+ pop af
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ ret
diff --git a/home/overworld.asm b/home/overworld.asm
index b96efcb4..79e4ea97 100644
--- a/home/overworld.asm
+++ b/home/overworld.asm
@@ -88,7 +88,7 @@ OverworldLoopLessDelay::
call IsPlayerCharacterBeingControlledByGame
jr nz, .checkForOpponent
call CheckForHiddenObjectOrBookshelfOrCardKeyDoor
- ld a, [$ffeb]
+ ld a, [hFoundHiddenObjectOrBookshelf]
and a
jp z, OverworldLoop ; jump if a hidden object or bookshelf was found, but not if a card key door was found
call IsSpriteOrSignInFrontOfPlayer
@@ -762,8 +762,8 @@ HandleBlackOut::
call StopMusic
ld hl, wd72e
res 5, [hl]
- ld a, Bank(ResetStatusAndHalveMoneyOnBlackout) ; also Bank(SpecialWarpIn) and Bank(SpecialEnterMap)
- ld [H_LOADEDROMBANK], a
+ ld a, BANK(ResetStatusAndHalveMoneyOnBlackout) ; also BANK(SpecialWarpIn) and BANK(SpecialEnterMap)
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
call ResetStatusAndHalveMoneyOnBlackout
call SpecialWarpIn
@@ -772,7 +772,7 @@ HandleBlackOut::
StopMusic::
ld [wAudioFadeOutControl], a
- ld a, $ff
+ ld a, SFX_STOP_ALL_MUSIC
ld [wNewSoundID], a
call PlaySound
.wait
@@ -793,8 +793,8 @@ HandleFlyWarpOrDungeonWarp::
set 2, [hl] ; fly warp or dungeon warp
res 5, [hl] ; forced to ride bike
call LeaveMapAnim
- ld a, Bank(SpecialWarpIn)
- ld [H_LOADEDROMBANK], a
+ ld a, BANK(SpecialWarpIn)
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
call SpecialWarpIn
jp SpecialEnterMap
@@ -867,7 +867,7 @@ IsBikeRidingAllowed::
scf
ret
-INCLUDE "data/bike_riding_tilesets.asm"
+INCLUDE "data/tilesets/bike_riding_tilesets.asm"
; load the tile pattern data of the current tileset into VRAM
LoadTilesetTilePatternData::
@@ -1372,10 +1372,10 @@ TilePairCollisionsWater::
; this builds a tile map from the tile block map based on the current X/Y coordinates of the player's character
LoadCurrentMapView::
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
push af
ld a, [wTilesetBank] ; tile data ROM bank
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a ; switch to ROM bank that contains tile data
ld a, [wCurrentTileBlockMapViewPointer] ; address of upper left corner of current map view
ld e, a
@@ -1424,18 +1424,18 @@ LoadCurrentMapView::
dec b
jr nz, .rowLoop
ld hl, wTileMapBackup
- ld bc, $0000
+ ld bc, $0
.adjustForYCoordWithinTileBlock
ld a, [wYBlockCoord]
and a
jr z, .adjustForXCoordWithinTileBlock
- ld bc, $0030
+ ld bc, $30
add hl, bc
.adjustForXCoordWithinTileBlock
ld a, [wXBlockCoord]
and a
jr z, .copyToVisibleAreaBuffer
- ld bc, $0002
+ ld bc, $2
add hl, bc
.copyToVisibleAreaBuffer
coord de, 0, 0 ; base address for the tiles that are directly transferred to VRAM during V-blank
@@ -1457,7 +1457,7 @@ LoadCurrentMapView::
dec b
jr nz, .rowLoop2
pop af
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a ; restore previous ROM bank
ret
@@ -1739,7 +1739,7 @@ ScheduleSouthRowRedraw::
ld l, a
ld a, [wMapViewVRAMPointer + 1]
ld h, a
- ld bc, $0200
+ ld bc, $200
add hl, bc
ld a, h
and $03
@@ -1835,7 +1835,7 @@ DrawTileBlock::
ld a, [de]
ld [hl], a
inc de
- ld bc, $0015
+ ld bc, $15
add hl, bc
pop bc
dec c
@@ -2180,7 +2180,7 @@ LoadMapHeader::
jr nz, .zeroSpriteDataLoop
; initialize all C100-C1FF sprite entries to disabled (other than player's)
ld hl, wSpriteStateData1 + $12
- ld de, $0010
+ ld de, $10
ld c, $0f
.disableSpriteEntriesLoop
ld [hl], $ff
@@ -2291,10 +2291,10 @@ LoadMapHeader::
ld a, [wCurMap]
ld c, a
ld b, $00
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
push af
ld a, BANK(MapSongBanks)
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ld hl, MapSongBanks
add hl, bc
@@ -2304,7 +2304,7 @@ LoadMapHeader::
ld a, [hl]
ld [wMapMusicROMBank], a ; music 2
pop af
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ret
@@ -2322,7 +2322,7 @@ CopyMapConnectionHeader::
; function to load map data
LoadMapData::
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
push af
call DisableLCD
ld a, $98
@@ -2377,7 +2377,7 @@ LoadMapData::
call PlayDefaultMusicFadeOutCurrent
.restoreRomBank
pop af
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ret
@@ -2388,15 +2388,15 @@ SwitchToMapRomBank::
push bc
ld c, a
ld b, $00
- ld a, Bank(MapHeaderBanks)
+ ld a, BANK(MapHeaderBanks)
call BankswitchHome ; switch to ROM bank 3
ld hl, MapHeaderBanks
add hl, bc
ld a, [hl]
- ld [$ffe8], a ; save map ROM bank
+ ld [hMapROMBank], a ; save map ROM bank
call BankswitchBack
- ld a, [$ffe8]
- ld [H_LOADEDROMBANK], a
+ ld a, [hMapROMBank]
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a ; switch to map ROM bank
pop bc
pop hl
diff --git a/home/overworld_text.asm b/home/overworld_text.asm
new file mode 100644
index 00000000..b32335f7
--- /dev/null
+++ b/home/overworld_text.asm
@@ -0,0 +1,31 @@
+TextScriptEndingChar::
+ db "@"
+
+TextScriptEnd::
+ ld hl, TextScriptEndingChar
+ ret
+
+ExclamationText::
+ TX_FAR _ExclamationText
+ db "@"
+
+GroundRoseText::
+ TX_FAR _GroundRoseText
+ db "@"
+
+BoulderText::
+ TX_FAR _BoulderText
+ db "@"
+
+MartSignText::
+ TX_FAR _MartSignText
+ db "@"
+
+PokeCenterSignText::
+ TX_FAR _PokeCenterSignText
+ db "@"
+
+PickUpItemText::
+ TX_ASM
+ predef PickUpItem
+ jp TextScriptEnd
diff --git a/home/pics.asm b/home/pics.asm
new file mode 100644
index 00000000..c6d99cbb
--- /dev/null
+++ b/home/pics.asm
@@ -0,0 +1,196 @@
+; uncompresses the front or back sprite of the specified mon
+; assumes the corresponding mon header is already loaded
+; hl contains offset to sprite pointer ($b for front or $d for back)
+UncompressMonSprite::
+ ld bc, wMonHeader
+ add hl, bc
+ ld a, [hli]
+ ld [wSpriteInputPtr], a ; fetch sprite input pointer
+ ld a, [hl]
+ ld [wSpriteInputPtr+1], a
+; define (by index number) the bank that a pokemon's image is in
+; index = Mew, bank 1
+; index = Kabutops fossil, bank $B
+; index < $1F, bank 9
+; $1F ≤ index < $4A, bank $A
+; $4A ≤ index < $74, bank $B
+; $74 ≤ index < $99, bank $C
+; $99 ≤ index, bank $D
+ ld a, [wcf91] ; XXX name for this ram location
+ ld b, a
+ cp MEW
+ ld a, BANK(MewPicFront)
+ jr z, .GotBank
+ ld a, b
+ cp FOSSIL_KABUTOPS
+ ld a, BANK(FossilKabutopsPic)
+ jr z, .GotBank
+ ld a, b
+ cp TANGELA + 1
+ ld a, BANK(TangelaPicFront)
+ jr c, .GotBank
+ ld a, b
+ cp MOLTRES + 1
+ ld a, BANK(MoltresPicFront)
+ jr c, .GotBank
+ ld a, b
+ cp BEEDRILL + 2
+ ld a, BANK(BeedrillPicFront)
+ jr c, .GotBank
+ ld a, b
+ cp STARMIE + 1
+ ld a, BANK(StarmiePicFront)
+ jr c, .GotBank
+ ld a, BANK(VictreebelPicFront)
+.GotBank
+ jp UncompressSpriteData
+
+; de: destination location
+LoadMonFrontSprite::
+ push de
+ ld hl, wMonHFrontSprite - wMonHeader
+ call UncompressMonSprite
+ ld hl, wMonHSpriteDim
+ ld a, [hli]
+ ld c, a
+ pop de
+ ; fall through
+
+; postprocesses uncompressed sprite chunks to a 2bpp sprite and loads it into video ram
+; calculates alignment parameters to place both sprite chunks in the center of the 7*7 tile sprite buffers
+; de: destination location
+; a,c: sprite dimensions (in tiles of 8x8 each)
+LoadUncompressedSpriteData::
+ push de
+ and $f
+ ld [hSpriteWidth], a ; each byte contains 8 pixels (in 1bpp), so tiles=bytes for width
+ ld b, a
+ ld a, $7
+ sub b ; 7-w
+ inc a ; 8-w
+ srl a ; (8-w)/2 ; horizontal center (in tiles, rounded up)
+ ld b, a
+ add a
+ add a
+ add a
+ sub b ; 7*((8-w)/2) ; skip for horizontal center (in tiles)
+ ld [hSpriteOffset], a
+ ld a, c
+ swap a
+ and $f
+ ld b, a
+ add a
+ add a
+ add a ; 8*tiles is height in bytes
+ ld [hSpriteHeight], a
+ ld a, $7
+ sub b ; 7-h ; skip for vertical center (in tiles, relative to current column)
+ ld b, a
+ ld a, [hSpriteOffset]
+ add b ; 7*((8-w)/2) + 7-h ; combined overall offset (in tiles)
+ add a
+ add a
+ add a ; 8*(7*((8-w)/2) + 7-h) ; combined overall offset (in bytes)
+ ld [hSpriteOffset], a
+ xor a
+ ld [MBC1SRamBank], a
+ ld hl, sSpriteBuffer0
+ call ZeroSpriteBuffer ; zero buffer 0
+ ld de, sSpriteBuffer1
+ ld hl, sSpriteBuffer0
+ call AlignSpriteDataCentered ; copy and align buffer 1 to 0 (containing the MSB of the 2bpp sprite)
+ ld hl, sSpriteBuffer1
+ call ZeroSpriteBuffer ; zero buffer 1
+ ld de, sSpriteBuffer2
+ ld hl, sSpriteBuffer1
+ call AlignSpriteDataCentered ; copy and align buffer 2 to 1 (containing the LSB of the 2bpp sprite)
+ pop de
+ jp InterlaceMergeSpriteBuffers
+
+; copies and aligns the sprite data properly inside the sprite buffer
+; sprite buffers are 7*7 tiles in size, the loaded sprite is centered within this area
+AlignSpriteDataCentered::
+ ld a, [hSpriteOffset]
+ ld b, $0
+ ld c, a
+ add hl, bc
+ ld a, [hSpriteWidth]
+.columnLoop
+ push af
+ push hl
+ ld a, [hSpriteHeight]
+ ld c, a
+.columnInnerLoop
+ ld a, [de]
+ inc de
+ ld [hli], a
+ dec c
+ jr nz, .columnInnerLoop
+ pop hl
+ ld bc, 7*8 ; 7 tiles
+ add hl, bc ; advance one full column
+ pop af
+ dec a
+ jr nz, .columnLoop
+ ret
+
+; fills the sprite buffer (pointed to in hl) with zeros
+ZeroSpriteBuffer::
+ ld bc, SPRITEBUFFERSIZE
+.nextByteLoop
+ xor a
+ ld [hli], a
+ dec bc
+ ld a, b
+ or c
+ jr nz, .nextByteLoop
+ ret
+
+; combines the (7*7 tiles, 1bpp) sprite chunks in buffer 0 and 1 into a 2bpp sprite located in buffer 1 through 2
+; in the resulting sprite, the rows of the two source sprites are interlaced
+; de: output address
+InterlaceMergeSpriteBuffers::
+ xor a
+ ld [MBC1SRamBank], a
+ push de
+ ld hl, sSpriteBuffer2 + (SPRITEBUFFERSIZE - 1) ; destination: end of buffer 2
+ ld de, sSpriteBuffer1 + (SPRITEBUFFERSIZE - 1) ; source 2: end of buffer 1
+ ld bc, sSpriteBuffer0 + (SPRITEBUFFERSIZE - 1) ; source 1: end of buffer 0
+ ld a, SPRITEBUFFERSIZE/2 ; $c4
+ ld [hSpriteInterlaceCounter], a
+.interlaceLoop
+ ld a, [de]
+ dec de
+ ld [hld], a ; write byte of source 2
+ ld a, [bc]
+ dec bc
+ ld [hld], a ; write byte of source 1
+ ld a, [de]
+ dec de
+ ld [hld], a ; write byte of source 2
+ ld a, [bc]
+ dec bc
+ ld [hld], a ; write byte of source 1
+ ld a, [hSpriteInterlaceCounter]
+ dec a
+ ld [hSpriteInterlaceCounter], a
+ jr nz, .interlaceLoop
+ ld a, [wSpriteFlipped]
+ and a
+ jr z, .notFlipped
+ ld bc, 2*SPRITEBUFFERSIZE
+ ld hl, sSpriteBuffer1
+.swapLoop
+ swap [hl] ; if flipped swap nybbles in all bytes
+ inc hl
+ dec bc
+ ld a, b
+ or c
+ jr nz, .swapLoop
+.notFlipped
+ pop hl
+ ld de, sSpriteBuffer1
+ ld c, (2*SPRITEBUFFERSIZE)/16 ; $31, number of 16 byte chunks to be copied
+ ld a, [hLoadedROMBank]
+ ld b, a
+ jp CopyVideoData
diff --git a/home/pokemon.asm b/home/pokemon.asm
new file mode 100644
index 00000000..141baa65
--- /dev/null
+++ b/home/pokemon.asm
@@ -0,0 +1,464 @@
+DrawHPBar::
+; Draw an HP bar d tiles long, and fill it to e pixels.
+; If c is nonzero, show at least a sliver regardless.
+; The right end of the bar changes with [wHPBarType].
+
+ push hl
+ push de
+ push bc
+
+ ; Left
+ ld a, $71 ; "HP:"
+ ld [hli], a
+ ld a, $62
+ ld [hli], a
+
+ push hl
+
+ ; Middle
+ ld a, $63 ; empty
+.draw
+ ld [hli], a
+ dec d
+ jr nz, .draw
+
+ ; Right
+ ld a, [wHPBarType]
+ dec a
+ ld a, $6d ; status screen and battle
+ jr z, .ok
+ dec a ; pokemon menu
+.ok
+ ld [hl], a
+
+ pop hl
+
+ ld a, e
+ and a
+ jr nz, .fill
+
+ ; If c is nonzero, draw a pixel anyway.
+ ld a, c
+ and a
+ jr z, .done
+ ld e, 1
+
+.fill
+ ld a, e
+ sub 8
+ jr c, .partial
+ ld e, a
+ ld a, $6b ; full
+ ld [hli], a
+ ld a, e
+ and a
+ jr z, .done
+ jr .fill
+
+.partial
+ ; Fill remaining pixels at the end if necessary.
+ ld a, $63 ; empty
+ add e
+ ld [hl], a
+.done
+ pop bc
+ pop de
+ pop hl
+ ret
+
+
+; loads pokemon data from one of multiple sources to wLoadedMon
+; loads base stats to wMonHeader
+; INPUT:
+; [wWhichPokemon] = index of pokemon within party/box
+; [wMonDataLocation] = source
+; 00: player's party
+; 01: enemy's party
+; 02: current box
+; 03: daycare
+; OUTPUT:
+; [wcf91] = pokemon ID
+; wLoadedMon = base address of pokemon data
+; wMonHeader = base address of base stats
+LoadMonData::
+ jpab LoadMonData_
+
+OverwritewMoves::
+; Write c to [wMoves + b]. Unused.
+ ld hl, wMoves
+ ld e, b
+ ld d, 0
+ add hl, de
+ ld a, c
+ ld [hl], a
+ ret
+
+LoadFlippedFrontSpriteByMonIndex::
+ ld a, 1
+ ld [wSpriteFlipped], a
+
+LoadFrontSpriteByMonIndex::
+ push hl
+ ld a, [wd11e]
+ push af
+ ld a, [wcf91]
+ ld [wd11e], a
+ predef IndexToPokedex
+ ld hl, wd11e
+ ld a, [hl]
+ pop bc
+ ld [hl], b
+ and a
+ pop hl
+ jr z, .invalidDexNumber ; dex #0 invalid
+ cp NUM_POKEMON + 1
+ jr c, .validDexNumber ; dex >#151 invalid
+.invalidDexNumber
+ ld a, RHYDON ; $1
+ ld [wcf91], a
+ ret
+.validDexNumber
+ push hl
+ ld de, vFrontPic
+ call LoadMonFrontSprite
+ pop hl
+ ld a, [hLoadedROMBank]
+ push af
+ ld a, BANK(CopyUncompressedPicToHL)
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ xor a
+ ld [hStartTileID], a
+ call CopyUncompressedPicToHL
+ xor a
+ ld [wSpriteFlipped], a
+ pop af
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ ret
+
+
+PlayCry::
+; Play monster a's cry.
+ call GetCryData
+ call PlaySound
+ jp WaitForSoundToFinish
+
+GetCryData::
+; Load cry data for monster a.
+ dec a
+ ld c, a
+ ld b, 0
+ ld hl, CryData
+ add hl, bc
+ add hl, bc
+ add hl, bc
+
+ ld a, BANK(CryData)
+ call BankswitchHome
+ ld a, [hli]
+ ld b, a ; cry id
+ ld a, [hli]
+ ld [wFrequencyModifier], a
+ ld a, [hl]
+ ld [wTempoModifier], a
+ call BankswitchBack
+
+ ; Cry headers have 3 channels,
+ ; and start from index CRY_SFX_START,
+ ; so add 3 times the cry id.
+ ld a, b
+ ld c, CRY_SFX_START
+ rlca ; * 2
+ add b
+ add c
+ ret
+
+DisplayPartyMenu::
+ ld a, [hTilesetType]
+ push af
+ xor a
+ ld [hTilesetType], a
+ call GBPalWhiteOutWithDelay3
+ call ClearSprites
+ call PartyMenuInit
+ call DrawPartyMenu
+ jp HandlePartyMenuInput
+
+GoBackToPartyMenu::
+ ld a, [hTilesetType]
+ push af
+ xor a
+ ld [hTilesetType], a
+ call PartyMenuInit
+ call RedrawPartyMenu
+ jp HandlePartyMenuInput
+
+PartyMenuInit::
+ ld a, 1 ; hardcoded bank
+ call BankswitchHome
+ call LoadHpBarAndStatusTilePatterns
+ ld hl, wd730
+ set 6, [hl] ; turn off letter printing delay
+ xor a ; PLAYER_PARTY_DATA
+ ld [wMonDataLocation], a
+ ld [wMenuWatchMovingOutOfBounds], a
+ ld hl, wTopMenuItemY
+ inc a
+ ld [hli], a ; top menu item Y
+ xor a
+ ld [hli], a ; top menu item X
+ ld a, [wPartyAndBillsPCSavedMenuItem]
+ push af
+ ld [hli], a ; current menu item ID
+ inc hl
+ ld a, [wPartyCount]
+ and a ; are there more than 0 pokemon in the party?
+ jr z, .storeMaxMenuItemID
+ dec a
+; if party is not empty, the max menu item ID is ([wPartyCount] - 1)
+; otherwise, it is 0
+.storeMaxMenuItemID
+ ld [hli], a ; max menu item ID
+ ld a, [wForcePlayerToChooseMon]
+ and a
+ ld a, A_BUTTON | B_BUTTON
+ jr z, .next
+ xor a
+ ld [wForcePlayerToChooseMon], a
+ inc a ; a = A_BUTTON
+.next
+ ld [hli], a ; menu watched keys
+ pop af
+ ld [hl], a ; old menu item ID
+ ret
+
+HandlePartyMenuInput::
+ ld a, 1
+ ld [wMenuWrappingEnabled], a
+ ld a, $40
+ ld [wPartyMenuAnimMonEnabled], a
+ call HandleMenuInput_
+ call PlaceUnfilledArrowMenuCursor
+ ld b, a
+ xor a
+ ld [wPartyMenuAnimMonEnabled], a
+ ld a, [wCurrentMenuItem]
+ ld [wPartyAndBillsPCSavedMenuItem], a
+ ld hl, wd730
+ res 6, [hl] ; turn on letter printing delay
+ ld a, [wMenuItemToSwap]
+ and a
+ jp nz, .swappingPokemon
+ pop af
+ ld [hTilesetType], a
+ bit 1, b
+ jr nz, .noPokemonChosen
+ ld a, [wPartyCount]
+ and a
+ jr z, .noPokemonChosen
+ ld a, [wCurrentMenuItem]
+ ld [wWhichPokemon], a
+ ld hl, wPartySpecies
+ ld b, 0
+ ld c, a
+ add hl, bc
+ ld a, [hl]
+ ld [wcf91], a
+ ld [wBattleMonSpecies2], a
+ call BankswitchBack
+ and a
+ ret
+.noPokemonChosen
+ call BankswitchBack
+ scf
+ ret
+.swappingPokemon
+ bit 1, b ; was the B button pressed?
+ jr z, .handleSwap ; if not, handle swapping the pokemon
+.cancelSwap ; if the B button was pressed
+ callba ErasePartyMenuCursors
+ xor a
+ ld [wMenuItemToSwap], a
+ ld [wPartyMenuTypeOrMessageID], a
+ call RedrawPartyMenu
+ jr HandlePartyMenuInput
+.handleSwap
+ ld a, [wCurrentMenuItem]
+ ld [wWhichPokemon], a
+ callba SwitchPartyMon
+ jr HandlePartyMenuInput
+
+DrawPartyMenu::
+ ld hl, DrawPartyMenu_
+ jr DrawPartyMenuCommon
+
+RedrawPartyMenu::
+ ld hl, RedrawPartyMenu_
+
+DrawPartyMenuCommon::
+ ld b, BANK(RedrawPartyMenu_)
+ jp Bankswitch
+
+; prints a pokemon's status condition
+; INPUT:
+; de = address of status condition
+; hl = destination address
+PrintStatusCondition::
+ push de
+ dec de
+ dec de ; de = address of current HP
+ ld a, [de]
+ ld b, a
+ dec de
+ ld a, [de]
+ or b ; is the pokemon's HP zero?
+ pop de
+ jr nz, PrintStatusConditionNotFainted
+; if the pokemon's HP is 0, print "FNT"
+ ld a, "F"
+ ld [hli], a
+ ld a, "N"
+ ld [hli], a
+ ld [hl], "T"
+ and a
+ ret
+
+PrintStatusConditionNotFainted::
+ ld a, [hLoadedROMBank]
+ push af
+ ld a, BANK(PrintStatusAilment)
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ call PrintStatusAilment ; print status condition
+ pop bc
+ ld a, b
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ ret
+
+; function to print pokemon level, leaving off the ":L" if the level is at least 100
+; INPUT:
+; hl = destination address
+; [wLoadedMonLevel] = level
+PrintLevel::
+ ld a, $6e ; ":L" tile ID
+ ld [hli], a
+ ld c, 2 ; number of digits
+ ld a, [wLoadedMonLevel] ; level
+ cp 100
+ jr c, PrintLevelCommon
+; if level at least 100, write over the ":L" tile
+ dec hl
+ inc c ; increment number of digits to 3
+ jr PrintLevelCommon
+
+; prints the level without leaving off ":L" regardless of level
+; INPUT:
+; hl = destination address
+; [wLoadedMonLevel] = level
+PrintLevelFull::
+ ld a, $6e ; ":L" tile ID
+ ld [hli], a
+ ld c, 3 ; number of digits
+ ld a, [wLoadedMonLevel] ; level
+
+PrintLevelCommon::
+ ld [wd11e], a
+ ld de, wd11e
+ ld b, LEFT_ALIGN | 1 ; 1 byte
+ jp PrintNumber
+
+GetwMoves::
+; Unused. Returns the move at index a from wMoves in a
+ ld hl, wMoves
+ ld c, a
+ ld b, 0
+ add hl, bc
+ ld a, [hl]
+ ret
+
+; copies the base stat data of a pokemon to wMonHeader
+; INPUT:
+; [wd0b5] = pokemon ID
+GetMonHeader::
+ ld a, [hLoadedROMBank]
+ push af
+ ld a, BANK(BaseStats)
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ push bc
+ push de
+ push hl
+ ld a, [wd11e]
+ push af
+ ld a, [wd0b5]
+ ld [wd11e], a
+ ld de, FossilKabutopsPic
+ ld b, $66 ; size of Kabutops fossil and Ghost sprites
+ cp FOSSIL_KABUTOPS ; Kabutops fossil
+ jr z, .specialID
+ ld de, GhostPic
+ cp MON_GHOST ; Ghost
+ jr z, .specialID
+ ld de, FossilAerodactylPic
+ ld b, $77 ; size of Aerodactyl fossil sprite
+ cp FOSSIL_AERODACTYL ; Aerodactyl fossil
+ jr z, .specialID
+ cp MEW
+ jr z, .mew
+ predef IndexToPokedex ; convert pokemon ID in [wd11e] to pokedex number
+ ld a, [wd11e]
+ dec a
+ ld bc, MonBaseStatsEnd - MonBaseStats
+ ld hl, BaseStats
+ call AddNTimes
+ ld de, wMonHeader
+ ld bc, MonBaseStatsEnd - MonBaseStats
+ call CopyData
+ jr .done
+.specialID
+ ld hl, wMonHSpriteDim
+ ld [hl], b ; write sprite dimensions
+ inc hl
+ ld [hl], e ; write front sprite pointer
+ inc hl
+ ld [hl], d
+ jr .done
+.mew
+ ld hl, MewBaseStats
+ ld de, wMonHeader
+ ld bc, MonBaseStatsEnd - MonBaseStats
+ ld a, BANK(MewBaseStats)
+ call FarCopyData
+.done
+ ld a, [wd0b5]
+ ld [wMonHIndex], a
+ pop af
+ ld [wd11e], a
+ pop hl
+ pop de
+ pop bc
+ pop af
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ ret
+
+; copy party pokemon's name to wcd6d
+GetPartyMonName2::
+ ld a, [wWhichPokemon] ; index within party
+ ld hl, wPartyMonNicks
+
+; this is called more often
+GetPartyMonName::
+ push hl
+ push bc
+ call SkipFixedLengthTextEntries ; add NAME_LENGTH to hl, a times
+ ld de, wcd6d
+ push de
+ ld bc, NAME_LENGTH
+ call CopyData
+ pop de
+ pop bc
+ pop hl
+ ret
diff --git a/home/predef.asm b/home/predef.asm
index 9bb9be74..4f0c37d9 100644
--- a/home/predef.asm
+++ b/home/predef.asm
@@ -8,18 +8,18 @@ Predef::
; A hack for LoadDestinationWarpPosition.
; See LoadTilesetHeader (predef $19).
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
ld [wPredefParentBank], a
push af
ld a, BANK(GetPredefPointer)
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
call GetPredefPointer
ld a, [wPredefBank]
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ld de, .done
@@ -28,7 +28,7 @@ Predef::
.done
pop af
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ret
diff --git a/home/predef_text.asm b/home/predef_text.asm
new file mode 100644
index 00000000..059e23ab
--- /dev/null
+++ b/home/predef_text.asm
@@ -0,0 +1,237 @@
+; this function is used to display sign messages, sprite dialog, etc.
+; INPUT: [hSpriteIndexOrTextID] = sprite ID or text ID
+DisplayTextID::
+ ld a, [hLoadedROMBank]
+ push af
+ callba DisplayTextIDInit ; initialization
+ ld hl, wTextPredefFlag
+ bit 0, [hl]
+ res 0, [hl]
+ jr nz, .skipSwitchToMapBank
+ ld a, [wCurMap]
+ call SwitchToMapRomBank
+.skipSwitchToMapBank
+ ld a, 30 ; half a second
+ ld [hFrameCounter], a ; used as joypad poll timer
+ ld hl, wMapTextPtr
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a ; hl = map text pointer
+ ld d, $00
+ ld a, [hSpriteIndexOrTextID] ; text ID
+ ld [wSpriteIndex], a
+ and a
+ jp z, DisplayStartMenu
+ cp TEXT_SAFARI_GAME_OVER
+ jp z, DisplaySafariGameOverText
+ cp TEXT_MON_FAINTED
+ jp z, DisplayPokemonFaintedText
+ cp TEXT_BLACKED_OUT
+ jp z, DisplayPlayerBlackedOutText
+ cp TEXT_REPEL_WORE_OFF
+ jp z, DisplayRepelWoreOffText
+ ld a, [wNumSprites]
+ ld e, a
+ ld a, [hSpriteIndexOrTextID] ; sprite ID
+ cp e
+ jr z, .spriteHandling
+ jr nc, .skipSpriteHandling
+.spriteHandling
+; get the text ID of the sprite
+ push hl
+ push de
+ push bc
+ callba UpdateSpriteFacingOffsetAndDelayMovement ; update the graphics of the sprite the player is talking to (to face the right direction)
+ pop bc
+ pop de
+ ld hl, wMapSpriteData ; NPC text entries
+ ld a, [hSpriteIndexOrTextID]
+ dec a
+ add a
+ add l
+ ld l, a
+ jr nc, .noCarry
+ inc h
+.noCarry
+ inc hl
+ ld a, [hl] ; a = text ID of the sprite
+ pop hl
+.skipSpriteHandling
+; look up the address of the text in the map's text entries
+ dec a
+ ld e, a
+ sla e
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a ; hl = address of the text
+ ld a, [hl] ; a = first byte of text
+; check first byte of text for special cases
+ cp $fe ; Pokemart NPC
+ jp z, DisplayPokemartDialogue
+ cp $ff ; Pokemon Center NPC
+ jp z, DisplayPokemonCenterDialogue
+ cp $fc ; Item Storage PC
+ jp z, FuncTX_ItemStoragePC
+ cp $fd ; Bill's PC
+ jp z, FuncTX_BillsPC
+ cp $f9 ; Pokemon Center PC
+ jp z, FuncTX_PokemonCenterPC
+ cp $f5 ; Vending Machine
+ jr nz, .notVendingMachine
+ callba VendingMachineMenu ; jump banks to vending machine routine
+ jr AfterDisplayingTextID
+.notVendingMachine
+ cp $f7 ; prize menu
+ jp z, FuncTX_GameCornerPrizeMenu
+ cp $f6 ; cable connection NPC in Pokemon Center
+ jr nz, .notSpecialCase
+ callab CableClubNPC
+ jr AfterDisplayingTextID
+.notSpecialCase
+ call PrintText_NoCreatingTextBox ; display the text
+ ld a, [wDoNotWaitForButtonPressAfterDisplayingText]
+ and a
+ jr nz, HoldTextDisplayOpen
+
+AfterDisplayingTextID::
+ ld a, [wEnteringCableClub]
+ and a
+ jr nz, HoldTextDisplayOpen
+ call WaitForTextScrollButtonPress ; wait for a button press after displaying all the text
+
+; loop to hold the dialogue box open as long as the player keeps holding down the A button
+HoldTextDisplayOpen::
+ call Joypad
+ ld a, [hJoyHeld]
+ bit 0, a ; is the A button being pressed?
+ jr nz, HoldTextDisplayOpen
+
+CloseTextDisplay::
+ ld a, [wCurMap]
+ call SwitchToMapRomBank
+ ld a, $90
+ ld [hWY], a ; move the window off the screen
+ call DelayFrame
+ call LoadGBPal
+ xor a
+ ld [hAutoBGTransferEnabled], a ; disable continuous WRAM to VRAM transfer each V-blank
+; loop to make sprites face the directions they originally faced before the dialogue
+ ld hl, wSpriteStateData2 + $19
+ ld c, $0f
+ ld de, $10
+.restoreSpriteFacingDirectionLoop
+ ld a, [hl]
+ dec h
+ ld [hl], a
+ inc h
+ add hl, de
+ dec c
+ jr nz, .restoreSpriteFacingDirectionLoop
+ ld a, BANK(InitMapSprites)
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ call InitMapSprites ; reload sprite tile pattern data (since it was partially overwritten by text tile patterns)
+ ld hl, wFontLoaded
+ res 0, [hl]
+ ld a, [wd732]
+ bit 3, a ; used fly warp
+ call z, LoadPlayerSpriteGraphics
+ call LoadCurrentMapView
+ pop af
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ jp UpdateSprites
+
+DisplayPokemartDialogue::
+ push hl
+ ld hl, PokemartGreetingText
+ call PrintText
+ pop hl
+ inc hl
+ call LoadItemList
+ ld a, PRICEDITEMLISTMENU
+ ld [wListMenuID], a
+ ld a, [hLoadedROMBank]
+ push af
+ ld a, BANK(DisplayPokemartDialogue_)
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ call DisplayPokemartDialogue_
+ pop af
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ jp AfterDisplayingTextID
+
+PokemartGreetingText::
+ TX_FAR _PokemartGreetingText
+ db "@"
+
+LoadItemList::
+ ld a, 1
+ ld [wUpdateSpritesEnabled], a
+ ld a, h
+ ld [wItemListPointer], a
+ ld a, l
+ ld [wItemListPointer + 1], a
+ ld de, wItemList
+.loop
+ ld a, [hli]
+ ld [de], a
+ inc de
+ cp $ff
+ jr nz, .loop
+ ret
+
+DisplayPokemonCenterDialogue::
+; zeroing these doesn't appear to serve any purpose
+ xor a
+ ld [hItemPrice], a
+ ld [hItemPrice + 1], a
+ ld [hItemPrice + 2], a
+
+ inc hl
+ ld a, [hLoadedROMBank]
+ push af
+ ld a, BANK(DisplayPokemonCenterDialogue_)
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ call DisplayPokemonCenterDialogue_
+ pop af
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ jp AfterDisplayingTextID
+
+DisplaySafariGameOverText::
+ callab PrintSafariGameOverText
+ jp AfterDisplayingTextID
+
+DisplayPokemonFaintedText::
+ ld hl, PokemonFaintedText
+ call PrintText
+ jp AfterDisplayingTextID
+
+PokemonFaintedText::
+ TX_FAR _PokemonFaintedText
+ db "@"
+
+DisplayPlayerBlackedOutText::
+ ld hl, PlayerBlackedOutText
+ call PrintText
+ ld a, [wd732]
+ res 5, a ; reset forced to use bike bit
+ ld [wd732], a
+ jp HoldTextDisplayOpen
+
+PlayerBlackedOutText::
+ TX_FAR _PlayerBlackedOutText
+ db "@"
+
+DisplayRepelWoreOffText::
+ ld hl, RepelWoreOffText
+ call PrintText
+ jp AfterDisplayingTextID
+
+RepelWoreOffText::
+ TX_FAR _RepelWoreOffText
+ db "@"
diff --git a/home/print_bcd.asm b/home/print_bcd.asm
new file mode 100644
index 00000000..38aedd3c
--- /dev/null
+++ b/home/print_bcd.asm
@@ -0,0 +1,77 @@
+; function to print a BCD (Binary-coded decimal) number
+; de = address of BCD number
+; hl = destination address
+; c = flags and length
+; bit 7: if set, do not print leading zeroes
+; if unset, print leading zeroes
+; bit 6: if set, left-align the string (do not pad empty digits with spaces)
+; if unset, right-align the string
+; bit 5: if set, print currency symbol at the beginning of the string
+; if unset, do not print the currency symbol
+; bits 0-4: length of BCD number in bytes
+; Note that bits 5 and 7 are modified during execution. The above reflects
+; their meaning at the beginning of the functions's execution.
+PrintBCDNumber::
+ ld b, c ; save flags in b
+ res 7, c
+ res 6, c
+ res 5, c ; c now holds the length
+ bit 5, b
+ jr z, .loop
+ bit 7, b
+ jr nz, .loop
+ ld [hl], "¥"
+ inc hl
+.loop
+ ld a, [de]
+ swap a
+ call PrintBCDDigit ; print upper digit
+ ld a, [de]
+ call PrintBCDDigit ; print lower digit
+ inc de
+ dec c
+ jr nz, .loop
+ bit 7, b ; were any non-zero digits printed?
+ jr z, .done ; if so, we are done
+.numberEqualsZero ; if every digit of the BCD number is zero
+ bit 6, b ; left or right alignment?
+ jr nz, .skipRightAlignmentAdjustment
+ dec hl ; if the string is right-aligned, it needs to be moved back one space
+.skipRightAlignmentAdjustment
+ bit 5, b
+ jr z, .skipCurrencySymbol
+ ld [hl], "¥"
+ inc hl
+.skipCurrencySymbol
+ ld [hl], "0"
+ call PrintLetterDelay
+ inc hl
+.done
+ ret
+
+PrintBCDDigit::
+ and $f
+ and a
+ jr z, .zeroDigit
+.nonzeroDigit
+ bit 7, b ; have any non-space characters been printed?
+ jr z, .outputDigit
+; if bit 7 is set, then no numbers have been printed yet
+ bit 5, b ; print the currency symbol?
+ jr z, .skipCurrencySymbol
+ ld [hl], "¥"
+ inc hl
+ res 5, b
+.skipCurrencySymbol
+ res 7, b ; unset 7 to indicate that a nonzero digit has been reached
+.outputDigit
+ add "0"
+ ld [hli], a
+ jp PrintLetterDelay
+.zeroDigit
+ bit 7, b ; either printing leading zeroes or already reached a nonzero digit?
+ jr z, .outputDigit ; if so, print a zero digit
+ bit 6, b ; left or right alignment?
+ ret nz
+ inc hl ; if right-aligned, "print" a space by advancing the pointer
+ ret
diff --git a/home/print_num.asm b/home/print_num.asm
new file mode 100644
index 00000000..5155977b
--- /dev/null
+++ b/home/print_num.asm
@@ -0,0 +1,217 @@
+PrintNumber::
+; Print the c-digit, b-byte value at de.
+; Allows 2 to 7 digits. For 1-digit numbers, add
+; the value to char "0" instead of calling PrintNumber.
+; Flags LEADING_ZEROES and LEFT_ALIGN can be given
+; in bits 7 and 6 of b respectively.
+ push bc
+ xor a
+ ld [hPastLeadingZeros], a
+ ld [hNumToPrint], a
+ ld [hNumToPrint + 1], a
+ ld a, b
+ and $f
+ cp 1
+ jr z, .byte
+ cp 2
+ jr z, .word
+.long
+ ld a, [de]
+ ld [hNumToPrint], a
+ inc de
+ ld a, [de]
+ ld [hNumToPrint + 1], a
+ inc de
+ ld a, [de]
+ ld [hNumToPrint + 2], a
+ jr .start
+
+.word
+ ld a, [de]
+ ld [hNumToPrint + 1], a
+ inc de
+ ld a, [de]
+ ld [hNumToPrint + 2], a
+ jr .start
+
+.byte
+ ld a, [de]
+ ld [hNumToPrint + 2], a
+
+.start
+ push de
+
+ ld d, b
+ ld a, c
+ ld b, a
+ xor a
+ ld c, a
+ ld a, b
+
+ cp 2
+ jr z, .tens
+ cp 3
+ jr z, .hundreds
+ cp 4
+ jr z, .thousands
+ cp 5
+ jr z, .ten_thousands
+ cp 6
+ jr z, .hundred_thousands
+
+print_digit: macro
+
+if (\1) / $10000
+ ld a, \1 / $10000 % $100
+else xor a
+endc
+ ld [hPowerOf10 + 0], a
+
+if (\1) / $100
+ ld a, \1 / $100 % $100
+else xor a
+endc
+ ld [hPowerOf10 + 1], a
+
+ ld a, \1 / $1 % $100
+ ld [hPowerOf10 + 2], a
+
+ call .PrintDigit
+ call .NextDigit
+endm
+
+.millions print_digit 1000000
+.hundred_thousands print_digit 100000
+.ten_thousands print_digit 10000
+.thousands print_digit 1000
+.hundreds print_digit 100
+
+.tens
+ ld c, 0
+ ld a, [hNumToPrint + 2]
+.mod
+ cp 10
+ jr c, .ok
+ sub 10
+ inc c
+ jr .mod
+.ok
+
+ ld b, a
+ ld a, [hPastLeadingZeros]
+ or c
+ ld [hPastLeadingZeros], a
+ jr nz, .past
+ call .PrintLeadingZero
+ jr .next
+.past
+ ld a, "0"
+ add c
+ ld [hl], a
+.next
+
+ call .NextDigit
+.ones
+ ld a, "0"
+ add b
+ ld [hli], a
+ pop de
+ dec de
+ pop bc
+ ret
+
+.PrintDigit:
+; Divide by the current decimal place.
+; Print the quotient, and keep the modulus.
+ ld c, 0
+.loop
+ ld a, [hPowerOf10]
+ ld b, a
+ ld a, [hNumToPrint]
+ ld [hSavedNumToPrint], a
+ cp b
+ jr c, .underflow0
+ sub b
+ ld [hNumToPrint], a
+ ld a, [hPowerOf10 + 1]
+ ld b, a
+ ld a, [hNumToPrint + 1]
+ ld [hSavedNumToPrint + 1], a
+ cp b
+ jr nc, .noborrow1
+
+ ld a, [hNumToPrint]
+ or 0
+ jr z, .underflow1
+ dec a
+ ld [hNumToPrint], a
+ ld a, [hNumToPrint + 1]
+.noborrow1
+
+ sub b
+ ld [hNumToPrint + 1], a
+ ld a, [hPowerOf10 + 2]
+ ld b, a
+ ld a, [hNumToPrint + 2]
+ ld [hSavedNumToPrint + 2], a
+ cp b
+ jr nc, .noborrow2
+
+ ld a, [hNumToPrint + 1]
+ and a
+ jr nz, .borrowed
+
+ ld a, [hNumToPrint]
+ and a
+ jr z, .underflow2
+ dec a
+ ld [hNumToPrint], a
+ xor a
+.borrowed
+
+ dec a
+ ld [hNumToPrint + 1], a
+ ld a, [hNumToPrint + 2]
+.noborrow2
+ sub b
+ ld [hNumToPrint + 2], a
+ inc c
+ jr .loop
+
+.underflow2
+ ld a, [hSavedNumToPrint + 1]
+ ld [hNumToPrint + 1], a
+.underflow1
+ ld a, [hSavedNumToPrint]
+ ld [hNumToPrint], a
+.underflow0
+ ld a, [hPastLeadingZeros]
+ or c
+ jr z, .PrintLeadingZero
+
+ ld a, "0"
+ add c
+ ld [hl], a
+ ld [hPastLeadingZeros], a
+ ret
+
+.PrintLeadingZero:
+ bit BIT_LEADING_ZEROES, d
+ ret z
+ ld [hl], "0"
+ ret
+
+.NextDigit:
+; Increment unless the number is left-aligned,
+; leading zeroes are not printed, and no digits
+; have been printed yet.
+ bit BIT_LEADING_ZEROES, d
+ jr nz, .inc
+ bit BIT_LEFT_ALIGN, d
+ jr z, .inc
+ ld a, [hPastLeadingZeros]
+ and a
+ ret z
+.inc
+ inc hl
+ ret
diff --git a/home/start.asm b/home/start.asm
new file mode 100644
index 00000000..448b6362
--- /dev/null
+++ b/home/start.asm
@@ -0,0 +1,10 @@
+_Start::
+ cp GBC
+ jr z, .gbc
+ xor a
+ jr .ok
+.gbc
+ ld a, 0
+.ok
+ ld [wGBC], a
+ jp Init
diff --git a/home/start_menu.asm b/home/start_menu.asm
index eb4b4f2d..38333644 100755
--- a/home/start_menu.asm
+++ b/home/start_menu.asm
@@ -1,6 +1,6 @@
DisplayStartMenu::
ld a, BANK(StartMenu_Pokedex)
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ld a, [wWalkBikeSurfState] ; walking/biking/surfing
ld [wWalkBikeSurfStateCopy], a
diff --git a/home/text.asm b/home/text.asm
index 9db81530..0d2ed0a2 100644
--- a/home/text.asm
+++ b/home/text.asm
@@ -62,7 +62,7 @@ Char4ETest::
cp $4E ; next
jr nz, .char4FTest
ld bc, 2 * SCREEN_WIDTH
- ld a, [hFlags_0xFFF6]
+ ld a, [hFlagsFFF6]
bit 2, a
jr z, .ok
ld bc, SCREEN_WIDTH
@@ -180,7 +180,7 @@ Char59::
; or
; player active monster’s name
; (like Char5A but flipped)
- ld a, [H_WHOSETURN]
+ ld a, [hWhoseTurn]
xor 1
jr MonsterNameCharsCommon
@@ -189,7 +189,7 @@ Char5A::
; player active monster’s name
; or
; enemy active monster’s name, prefixed with “Enemy ”
- ld a, [H_WHOSETURN]
+ ld a, [hWhoseTurn]
MonsterNameCharsCommon::
push de
and a
@@ -365,7 +365,7 @@ TextCommandProcessor::
push af
set 1, a
ld e, a
- ld a, [$fff4]
+ ld a, [hClearLetterPrintingDelayFlags]
xor e
ld [wLetterPrintingDelayFlags], a
ld a, c
@@ -675,14 +675,14 @@ TextCommand0D::
; BB = bank
TextCommand17::
pop hl
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
push af
ld a, [hli]
ld e, a
ld a, [hli]
ld d, a
ld a, [hli]
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
push hl
ld l, e
@@ -690,7 +690,7 @@ TextCommand17::
call TextCommandProcessor
pop hl
pop af
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
jp NextTextCommand
diff --git a/home/trainers.asm b/home/trainers.asm
new file mode 100644
index 00000000..9c3519a2
--- /dev/null
+++ b/home/trainers.asm
@@ -0,0 +1,436 @@
+; stores hl in [wTrainerHeaderPtr]
+StoreTrainerHeaderPointer::
+ ld a, h
+ ld [wTrainerHeaderPtr], a
+ ld a, l
+ ld [wTrainerHeaderPtr+1], a
+ ret
+
+; executes the current map script from the function pointer array provided in hl.
+; a: map script index to execute (unless overridden by [wd733] bit 4)
+ExecuteCurMapScriptInTable::
+ push af
+ push de
+ call StoreTrainerHeaderPointer
+ pop hl
+ pop af
+ push hl
+ ld hl, wFlags_D733
+ bit 4, [hl]
+ res 4, [hl]
+ jr z, .useProvidedIndex ; test if map script index was overridden manually
+ ld a, [wCurMapScript]
+.useProvidedIndex
+ pop hl
+ ld [wCurMapScript], a
+ call CallFunctionInTable
+ ld a, [wCurMapScript]
+ ret
+
+LoadGymLeaderAndCityName::
+ push de
+ ld de, wGymCityName
+ ld bc, $11
+ call CopyData ; load city name
+ pop hl
+ ld de, wGymLeaderName
+ ld bc, NAME_LENGTH
+ jp CopyData ; load gym leader name
+
+; reads specific information from trainer header (pointed to at wTrainerHeaderPtr)
+; a: offset in header data
+; 0 -> flag's bit (into wTrainerHeaderFlagBit)
+; 2 -> flag's byte ptr (into hl)
+; 4 -> before battle text (into hl)
+; 6 -> after battle text (into hl)
+; 8 -> end battle text (into hl)
+ReadTrainerHeaderInfo::
+ push de
+ push af
+ ld d, $0
+ ld e, a
+ ld hl, wTrainerHeaderPtr
+ ld a, [hli]
+ ld l, [hl]
+ ld h, a
+ add hl, de
+ pop af
+ and a
+ jr nz, .nonZeroOffset
+ ld a, [hl]
+ ld [wTrainerHeaderFlagBit], a ; store flag's bit
+ jr .done
+.nonZeroOffset
+ cp $2
+ jr z, .readPointer ; read flag's byte ptr
+ cp $4
+ jr z, .readPointer ; read before battle text
+ cp $6
+ jr z, .readPointer ; read after battle text
+ cp $8
+ jr z, .readPointer ; read end battle text
+ cp $a
+ jr nz, .done
+ ld a, [hli] ; read end battle text (2) but override the result afterwards (XXX why, bug?)
+ ld d, [hl]
+ ld e, a
+ jr .done
+.readPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+.done
+ pop de
+ ret
+
+TrainerFlagAction::
+ predef_jump FlagActionPredef
+
+TalkToTrainer::
+ call StoreTrainerHeaderPointer
+ xor a
+ call ReadTrainerHeaderInfo ; read flag's bit
+ ld a, $2
+ call ReadTrainerHeaderInfo ; read flag's byte ptr
+ ld a, [wTrainerHeaderFlagBit]
+ ld c, a
+ ld b, FLAG_TEST
+ call TrainerFlagAction ; read trainer's flag
+ ld a, c
+ and a
+ jr z, .trainerNotYetFought ; test trainer's flag
+ ld a, $6
+ call ReadTrainerHeaderInfo ; print after battle text
+ jp PrintText
+.trainerNotYetFought
+ ld a, $4
+ call ReadTrainerHeaderInfo ; print before battle text
+ call PrintText
+ ld a, $a
+ call ReadTrainerHeaderInfo ; (?) does nothing apparently (maybe bug in ReadTrainerHeaderInfo)
+ push de
+ ld a, $8
+ call ReadTrainerHeaderInfo ; read end battle text
+ pop de
+ call SaveEndBattleTextPointers
+ ld hl, wFlags_D733
+ set 4, [hl] ; activate map script index override (index is set below)
+ ld hl, wFlags_0xcd60
+ bit 0, [hl] ; test if player is already engaging the trainer (because the trainer saw the player)
+ ret nz
+; if the player talked to the trainer of his own volition
+ call EngageMapTrainer
+ ld hl, wCurMapScript
+ inc [hl] ; increment map script index before StartTrainerBattle increments it again (next script function is usually EndTrainerBattle)
+ jp StartTrainerBattle
+
+; checks if any trainers are seeing the player and wanting to fight
+CheckFightingMapTrainers::
+ call CheckForEngagingTrainers
+ ld a, [wSpriteIndex]
+ cp $ff
+ jr nz, .trainerEngaging
+ xor a
+ ld [wSpriteIndex], a
+ ld [wTrainerHeaderFlagBit], a
+ ret
+.trainerEngaging
+ ld hl, wFlags_D733
+ set 3, [hl]
+ ld [wEmotionBubbleSpriteIndex], a
+ xor a ; EXCLAMATION_BUBBLE
+ ld [wWhichEmotionBubble], a
+ predef EmotionBubble
+ ld a, D_RIGHT | D_LEFT | D_UP | D_DOWN
+ ld [wJoyIgnore], a
+ xor a
+ ld [hJoyHeld], a
+ call TrainerWalkUpToPlayer_Bank0
+ ld hl, wCurMapScript
+ inc [hl] ; increment map script index (next script function is usually DisplayEnemyTrainerTextAndStartBattle)
+ ret
+
+; display the before battle text after the enemy trainer has walked up to the player's sprite
+DisplayEnemyTrainerTextAndStartBattle::
+ ld a, [wd730]
+ and $1
+ ret nz ; return if the enemy trainer hasn't finished walking to the player's sprite
+ ld [wJoyIgnore], a
+ ld a, [wSpriteIndex]
+ ld [hSpriteIndexOrTextID], a
+ call DisplayTextID
+ ; fall through
+
+StartTrainerBattle::
+ xor a
+ ld [wJoyIgnore], a
+ call InitBattleEnemyParameters
+ ld hl, wd72d
+ set 6, [hl]
+ set 7, [hl]
+ ld hl, wd72e
+ set 1, [hl]
+ ld hl, wCurMapScript
+ inc [hl] ; increment map script index (next script function is usually EndTrainerBattle)
+ ret
+
+EndTrainerBattle::
+ ld hl, wCurrentMapScriptFlags
+ set 5, [hl]
+ set 6, [hl]
+ ld hl, wd72d
+ res 7, [hl]
+ ld hl, wFlags_0xcd60
+ res 0, [hl] ; player is no longer engaged by any trainer
+ ld a, [wIsInBattle]
+ cp $ff
+ jp z, ResetButtonPressedAndMapScript
+ ld a, $2
+ call ReadTrainerHeaderInfo
+ ld a, [wTrainerHeaderFlagBit]
+ ld c, a
+ ld b, FLAG_SET
+ call TrainerFlagAction ; flag trainer as fought
+ ld a, [wEnemyMonOrTrainerClass]
+ cp OPP_ID_OFFSET
+ jr nc, .skipRemoveSprite ; test if trainer was fought (in that case skip removing the corresponding sprite)
+ ld hl, wMissableObjectList
+ ld de, $2
+ ld a, [wSpriteIndex]
+ call IsInArray ; search for sprite ID
+ inc hl
+ ld a, [hl]
+ ld [wMissableObjectIndex], a ; load corresponding missable object index and remove it
+ predef HideObject
+.skipRemoveSprite
+ ld hl, wd730
+ bit 4, [hl]
+ res 4, [hl]
+ ret nz
+
+ResetButtonPressedAndMapScript::
+ xor a
+ ld [wJoyIgnore], a
+ ld [hJoyHeld], a
+ ld [hJoyPressed], a
+ ld [hJoyReleased], a
+ ld [wCurMapScript], a ; reset battle status
+ ret
+
+; calls TrainerWalkUpToPlayer
+TrainerWalkUpToPlayer_Bank0::
+ jpba TrainerWalkUpToPlayer
+
+; sets opponent type and mon set/lvl based on the engaging trainer data
+InitBattleEnemyParameters::
+ ld a, [wEngagedTrainerClass]
+ ld [wCurOpponent], a
+ ld [wEnemyMonOrTrainerClass], a
+ cp OPP_ID_OFFSET
+ ld a, [wEngagedTrainerSet]
+ jr c, .noTrainer
+ ld [wTrainerNo], a
+ ret
+.noTrainer
+ ld [wCurEnemyLVL], a
+ ret
+
+GetSpritePosition1::
+ ld hl, _GetSpritePosition1
+ jr SpritePositionBankswitch
+
+GetSpritePosition2::
+ ld hl, _GetSpritePosition2
+ jr SpritePositionBankswitch
+
+SetSpritePosition1::
+ ld hl, _SetSpritePosition1
+ jr SpritePositionBankswitch
+
+SetSpritePosition2::
+ ld hl, _SetSpritePosition2
+SpritePositionBankswitch::
+ ld b, BANK(_GetSpritePosition1) ; BANK(_GetSpritePosition2), BANK(_SetSpritePosition1), BANK(_SetSpritePosition2)
+ jp Bankswitch ; indirect jump to one of the four functions
+
+CheckForEngagingTrainers::
+ xor a
+ call ReadTrainerHeaderInfo ; read trainer flag's bit (unused)
+ ld d, h ; store trainer header address in de
+ ld e, l
+.trainerLoop
+ call StoreTrainerHeaderPointer ; set trainer header pointer to current trainer
+ ld a, [de]
+ ld [wSpriteIndex], a ; store trainer flag's bit
+ ld [wTrainerHeaderFlagBit], a
+ cp $ff
+ ret z
+ ld a, $2
+ call ReadTrainerHeaderInfo ; read trainer flag's byte ptr
+ ld b, FLAG_TEST
+ ld a, [wTrainerHeaderFlagBit]
+ ld c, a
+ call TrainerFlagAction ; read trainer flag
+ ld a, c
+ and a ; has the trainer already been defeated?
+ jr nz, .continue
+ push hl
+ push de
+ push hl
+ xor a
+ call ReadTrainerHeaderInfo ; get trainer header pointer
+ inc hl
+ ld a, [hl] ; read trainer engage distance
+ pop hl
+ ld [wTrainerEngageDistance], a
+ ld a, [wSpriteIndex]
+ swap a
+ ld [wTrainerSpriteOffset], a
+ predef TrainerEngage
+ pop de
+ pop hl
+ ld a, [wTrainerSpriteOffset]
+ and a
+ ret nz ; break if the trainer is engaging
+.continue
+ ld hl, $c
+ add hl, de
+ ld d, h
+ ld e, l
+ jr .trainerLoop
+
+; hl = text if the player wins
+; de = text if the player loses
+SaveEndBattleTextPointers::
+ ld a, [hLoadedROMBank]
+ ld [wEndBattleTextRomBank], a
+ ld a, h
+ ld [wEndBattleWinTextPointer], a
+ ld a, l
+ ld [wEndBattleWinTextPointer + 1], a
+ ld a, d
+ ld [wEndBattleLoseTextPointer], a
+ ld a, e
+ ld [wEndBattleLoseTextPointer + 1], a
+ ret
+
+; loads data of some trainer on the current map and plays pre-battle music
+; [wSpriteIndex]: sprite ID of trainer who is engaged
+EngageMapTrainer::
+ ld hl, wMapSpriteExtraData
+ ld d, $0
+ ld a, [wSpriteIndex]
+ dec a
+ add a
+ ld e, a
+ add hl, de ; seek to engaged trainer data
+ ld a, [hli] ; load trainer class
+ ld [wEngagedTrainerClass], a
+ ld a, [hl] ; load trainer mon set
+ ld [wEngagedTrainerSet], a
+ jp PlayTrainerMusic
+
+PrintEndBattleText::
+ push hl
+ ld hl, wd72d
+ bit 7, [hl]
+ res 7, [hl]
+ pop hl
+ ret z
+ ld a, [hLoadedROMBank]
+ push af
+ ld a, [wEndBattleTextRomBank]
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ push hl
+ callba SaveTrainerName
+ ld hl, TrainerEndBattleText
+ call PrintText
+ pop hl
+ pop af
+ ld [hLoadedROMBank], a
+ ld [MBC1RomBank], a
+ callba FreezeEnemyTrainerSprite
+ jp WaitForSoundToFinish
+
+GetSavedEndBattleTextPointer::
+ ld a, [wBattleResult]
+ and a
+; won battle
+ jr nz, .lostBattle
+ ld a, [wEndBattleWinTextPointer]
+ ld h, a
+ ld a, [wEndBattleWinTextPointer + 1]
+ ld l, a
+ ret
+.lostBattle
+ ld a, [wEndBattleLoseTextPointer]
+ ld h, a
+ ld a, [wEndBattleLoseTextPointer + 1]
+ ld l, a
+ ret
+
+TrainerEndBattleText::
+ TX_FAR _TrainerNameText
+ TX_ASM
+ call GetSavedEndBattleTextPointer
+ call TextCommandProcessor
+ jp TextScriptEnd
+
+; only engage with the trainer if the player is not already
+; engaged with another trainer
+; XXX unused?
+CheckIfAlreadyEngaged::
+ ld a, [wFlags_0xcd60]
+ bit 0, a
+ ret nz
+ call EngageMapTrainer
+ xor a
+ ret
+
+PlayTrainerMusic::
+ ld a, [wEngagedTrainerClass]
+ cp OPP_SONY1
+ ret z
+ cp OPP_SONY2
+ ret z
+ cp OPP_SONY3
+ ret z
+ ld a, [wGymLeaderNo]
+ and a
+ ret nz
+ xor a
+ ld [wAudioFadeOutControl], a
+ ld a, SFX_STOP_ALL_MUSIC
+ call PlaySound
+ ld a, BANK(Music_MeetEvilTrainer)
+ ld [wAudioROMBank], a
+ ld [wAudioSavedROMBank], a
+ ld a, [wEngagedTrainerClass]
+ ld b, a
+ ld hl, EvilTrainerList
+.evilTrainerListLoop
+ ld a, [hli]
+ cp $ff
+ jr z, .noEvilTrainer
+ cp b
+ jr nz, .evilTrainerListLoop
+ ld a, MUSIC_MEET_EVIL_TRAINER
+ jr .PlaySound
+.noEvilTrainer
+ ld hl, FemaleTrainerList
+.femaleTrainerListLoop
+ ld a, [hli]
+ cp $ff
+ jr z, .maleTrainer
+ cp b
+ jr nz, .femaleTrainerListLoop
+ ld a, MUSIC_MEET_FEMALE_TRAINER
+ jr .PlaySound
+.maleTrainer
+ ld a, MUSIC_MEET_MALE_TRAINER
+.PlaySound
+ ld [wNewSoundID], a
+ jp PlaySound
+
+INCLUDE "data/trainers/encounter_types.asm"
diff --git a/home/pic.asm b/home/uncompress.asm
index a1c18e8a..cfc39f0f 100644
--- a/home/pic.asm
+++ b/home/uncompress.asm
@@ -2,10 +2,10 @@
; bank is given in a, sprite input stream is pointed to in wSpriteInputPtr
UncompressSpriteData::
ld b, a
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
push af
ld a, b
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ld a, SRAM_ENABLE
ld [MBC1SRamEnable], a
@@ -13,7 +13,7 @@ UncompressSpriteData::
ld [MBC1SRamBank], a
call _UncompressSpriteData
pop af
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
ret
diff --git a/home/vblank.asm b/home/vblank.asm
index e80fba75..78f5f69d 100644
--- a/home/vblank.asm
+++ b/home/vblank.asm
@@ -5,7 +5,7 @@ VBlank::
push de
push hl
- ld a, [H_LOADEDROMBANK]
+ ld a, [hLoadedROMBank]
ld [wVBlankSavedROMBank], a
ld a, [hSCX]
@@ -26,9 +26,9 @@ VBlank::
call VBlankCopy
call VBlankCopyDouble
call UpdateMovingBgTiles
- call $ff80 ; hOAMDMA
+ call hDMARoutine
ld a, BANK(PrepareOAMData)
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
call PrepareOAMData
@@ -36,24 +36,24 @@ VBlank::
call Random
- ld a, [H_VBLANKOCCURRED]
+ ld a, [hVBlankOccurred]
and a
jr z, .skipZeroing
xor a
- ld [H_VBLANKOCCURRED], a
+ ld [hVBlankOccurred], a
.skipZeroing
- ld a, [H_FRAMECOUNTER]
+ ld a, [hFrameCounter]
and a
jr z, .skipDec
dec a
- ld [H_FRAMECOUNTER], a
+ ld [hFrameCounter], a
.skipDec
call FadeOutAudio
ld a, [wAudioROMBank] ; music ROM bank
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
cp BANK(Audio1_UpdateMusic)
@@ -79,7 +79,7 @@ VBlank::
call z, ReadJoypad
ld a, [wVBlankSavedROMBank]
- ld [H_LOADEDROMBANK], a
+ ld [hLoadedROMBank], a
ld [MBC1RomBank], a
pop hl
@@ -96,10 +96,10 @@ DelayFrame::
NOT_VBLANKED EQU 1
ld a, NOT_VBLANKED
- ld [H_VBLANKOCCURRED], a
+ ld [hVBlankOccurred], a
.halt
halt
- ld a, [H_VBLANKOCCURRED]
+ ld a, [hVBlankOccurred]
and a
jr nz, .halt
ret
diff --git a/home/vcopy.asm b/home/vcopy.asm
index 3f49ad3e..a6213b32 100644
--- a/home/vcopy.asm
+++ b/home/vcopy.asm
@@ -120,15 +120,15 @@ RedrawRowOrColumn::
; the above function, RedrawRowOrColumn, is used when walking to
; improve efficiency.
AutoBgMapTransfer::
- ld a, [H_AUTOBGTRANSFERENABLED]
+ ld a, [hAutoBGTransferEnabled]
and a
ret z
ld hl, sp + 0
ld a, h
- ld [H_SPTEMP], a
+ ld [hSPTemp], a
ld a, l
- ld [H_SPTEMP + 1], a ; save stack pinter
- ld a, [H_AUTOBGTRANSFERPORTION]
+ ld [hSPTemp + 1], a ; save stack pinter
+ ld a, [hAutoBGTransferPortion]
and a
jr z, .transferTopThird
dec a
@@ -136,9 +136,9 @@ AutoBgMapTransfer::
.transferBottomThird
coord hl, 0, 12
ld sp, hl
- ld a, [H_AUTOBGTRANSFERDEST + 1]
+ ld a, [hAutoBGTransferDest + 1]
ld h, a
- ld a, [H_AUTOBGTRANSFERDEST]
+ ld a, [hAutoBGTransferDest]
ld l, a
ld de, (12 * 32)
add hl, de
@@ -147,24 +147,24 @@ AutoBgMapTransfer::
.transferTopThird
coord hl, 0, 0
ld sp, hl
- ld a, [H_AUTOBGTRANSFERDEST + 1]
+ ld a, [hAutoBGTransferDest + 1]
ld h, a
- ld a, [H_AUTOBGTRANSFERDEST]
+ ld a, [hAutoBGTransferDest]
ld l, a
ld a, TRANSFERMIDDLE
jr .doTransfer
.transferMiddleThird
coord hl, 0, 6
ld sp, hl
- ld a, [H_AUTOBGTRANSFERDEST + 1]
+ ld a, [hAutoBGTransferDest + 1]
ld h, a
- ld a, [H_AUTOBGTRANSFERDEST]
+ ld a, [hAutoBGTransferDest]
ld l, a
ld de, (6 * 32)
add hl, de
ld a, TRANSFERBOTTOM
.doTransfer
- ld [H_AUTOBGTRANSFERPORTION], a ; store next portion
+ ld [hAutoBGTransferPortion], a ; store next portion
ld b, 6
TransferBgRows::
@@ -192,73 +192,73 @@ TransferBgRows::
dec b
jr nz, TransferBgRows
- ld a, [H_SPTEMP]
+ ld a, [hSPTemp]
ld h, a
- ld a, [H_SPTEMP + 1]
+ ld a, [hSPTemp + 1]
ld l, a
ld sp, hl
ret
-; Copies [H_VBCOPYBGNUMROWS] rows from H_VBCOPYBGSRC to H_VBCOPYBGDEST.
-; If H_VBCOPYBGSRC is XX00, the transfer is disabled.
+; Copies [hVBlankCopyBGNumRows] rows from hVBlankCopyBGSource to hVBlankCopyBGDest.
+; If hVBlankCopyBGSource is XX00, the transfer is disabled.
VBlankCopyBgMap::
- ld a, [H_VBCOPYBGSRC] ; doubles as enabling byte
+ ld a, [hVBlankCopyBGSource] ; doubles as enabling byte
and a
ret z
ld hl, sp + 0
ld a, h
- ld [H_SPTEMP], a
+ ld [hSPTemp], a
ld a, l
- ld [H_SPTEMP + 1], a ; save stack pointer
- ld a, [H_VBCOPYBGSRC]
+ ld [hSPTemp + 1], a ; save stack pointer
+ ld a, [hVBlankCopyBGSource]
ld l, a
- ld a, [H_VBCOPYBGSRC + 1]
+ ld a, [hVBlankCopyBGSource + 1]
ld h, a
ld sp, hl
- ld a, [H_VBCOPYBGDEST]
+ ld a, [hVBlankCopyBGDest]
ld l, a
- ld a, [H_VBCOPYBGDEST + 1]
+ ld a, [hVBlankCopyBGDest + 1]
ld h, a
- ld a, [H_VBCOPYBGNUMROWS]
+ ld a, [hVBlankCopyBGNumRows]
ld b, a
xor a
- ld [H_VBCOPYBGSRC], a ; disable transfer so it doesn't continue next V-blank
+ ld [hVBlankCopyBGSource], a ; disable transfer so it doesn't continue next V-blank
jr TransferBgRows
VBlankCopyDouble::
-; Copy [H_VBCOPYDOUBLESIZE] 1bpp tiles
-; from H_VBCOPYDOUBLESRC to H_VBCOPYDOUBLEDEST.
+; Copy [hVBlankCopyDoubleSize] 1bpp tiles
+; from hVBlankCopyDoubleSource to hVBlankCopyDoubleDest.
; While we're here, convert to 2bpp.
; The process is straightforward:
; copy each byte twice.
- ld a, [H_VBCOPYDOUBLESIZE]
+ ld a, [hVBlankCopyDoubleSize]
and a
ret z
ld hl, sp + 0
ld a, h
- ld [H_SPTEMP], a
+ ld [hSPTemp], a
ld a, l
- ld [H_SPTEMP + 1], a
+ ld [hSPTemp + 1], a
- ld a, [H_VBCOPYDOUBLESRC]
+ ld a, [hVBlankCopyDoubleSource]
ld l, a
- ld a, [H_VBCOPYDOUBLESRC + 1]
+ ld a, [hVBlankCopyDoubleSource + 1]
ld h, a
ld sp, hl
- ld a, [H_VBCOPYDOUBLEDEST]
+ ld a, [hVBlankCopyDoubleDest]
ld l, a
- ld a, [H_VBCOPYDOUBLEDEST + 1]
+ ld a, [hVBlankCopyDoubleDest + 1]
ld h, a
- ld a, [H_VBCOPYDOUBLESIZE]
+ ld a, [hVBlankCopyDoubleSize]
ld b, a
xor a ; transferred
- ld [H_VBCOPYDOUBLESIZE], a
+ ld [hVBlankCopyDoubleSize], a
.loop
rept 3
@@ -286,19 +286,19 @@ VBlankCopyDouble::
jr nz, .loop
ld a, l
- ld [H_VBCOPYDOUBLEDEST], a
+ ld [hVBlankCopyDoubleDest], a
ld a, h
- ld [H_VBCOPYDOUBLEDEST + 1], a
+ ld [hVBlankCopyDoubleDest + 1], a
ld hl, sp + 0
ld a, l
- ld [H_VBCOPYDOUBLESRC], a
+ ld [hVBlankCopyDoubleSource], a
ld a, h
- ld [H_VBCOPYDOUBLESRC + 1], a
+ ld [hVBlankCopyDoubleSource + 1], a
- ld a, [H_SPTEMP]
+ ld a, [hSPTemp]
ld h, a
- ld a, [H_SPTEMP + 1]
+ ld a, [hSPTemp + 1]
ld l, a
ld sp, hl
@@ -306,37 +306,37 @@ VBlankCopyDouble::
VBlankCopy::
-; Copy [H_VBCOPYSIZE] 2bpp tiles (or 16 * [H_VBCOPYSIZE] tile map entries)
-; from H_VBCOPYSRC to H_VBCOPYDEST.
+; Copy [hVBlankCopySize] 2bpp tiles (or 16 * [hVBlankCopySize] tile map entries)
+; from hVBlankCopySource to hVBlankCopyDest.
; Source and destination addresses are updated,
; so transfer can continue in subsequent calls.
- ld a, [H_VBCOPYSIZE]
+ ld a, [hVBlankCopySize]
and a
ret z
ld hl, sp + 0
ld a, h
- ld [H_SPTEMP], a
+ ld [hSPTemp], a
ld a, l
- ld [H_SPTEMP + 1], a
+ ld [hSPTemp + 1], a
- ld a, [H_VBCOPYSRC]
+ ld a, [hVBlankCopySource]
ld l, a
- ld a, [H_VBCOPYSRC + 1]
+ ld a, [hVBlankCopySource + 1]
ld h, a
ld sp, hl
- ld a, [H_VBCOPYDEST]
+ ld a, [hVBlankCopyDest]
ld l, a
- ld a, [H_VBCOPYDEST + 1]
+ ld a, [hVBlankCopyDest + 1]
ld h, a
- ld a, [H_VBCOPYSIZE]
+ ld a, [hVBlankCopySize]
ld b, a
xor a ; transferred
- ld [H_VBCOPYSIZE], a
+ ld [hVBlankCopySize], a
.loop
rept 7
@@ -356,19 +356,19 @@ VBlankCopy::
jr nz, .loop
ld a, l
- ld [H_VBCOPYDEST], a
+ ld [hVBlankCopyDest], a
ld a, h
- ld [H_VBCOPYDEST + 1], a
+ ld [hVBlankCopyDest + 1], a
ld hl, sp + 0
ld a, l
- ld [H_VBCOPYSRC], a
+ ld [hVBlankCopySource], a
ld a, h
- ld [H_VBCOPYSRC + 1], a
+ ld [hVBlankCopySource + 1], a
- ld a, [H_SPTEMP]
+ ld a, [hSPTemp]
ld h, a
- ld a, [H_SPTEMP + 1]
+ ld a, [hSPTemp + 1]
ld l, a
ld sp, hl
diff --git a/home/yes_no.asm b/home/yes_no.asm
new file mode 100644
index 00000000..61aa1390
--- /dev/null
+++ b/home/yes_no.asm
@@ -0,0 +1,40 @@
+; displays yes/no choice
+; yes -> set carry
+YesNoChoice::
+ call SaveScreenTilesToBuffer1
+ call InitYesNoTextBoxParameters
+ jr DisplayYesNoChoice
+
+Func_35f4::
+ ld a, TWO_OPTION_MENU
+ ld [wTextBoxID], a
+ call InitYesNoTextBoxParameters
+ jp DisplayTextBoxID
+
+InitYesNoTextBoxParameters::
+ xor a ; YES_NO_MENU
+ ld [wTwoOptionMenuID], a
+ coord hl, 14, 7
+ ld bc, $80f
+ ret
+
+YesNoChoicePokeCenter::
+ call SaveScreenTilesToBuffer1
+ ld a, HEAL_CANCEL_MENU
+ ld [wTwoOptionMenuID], a
+ coord hl, 11, 6
+ lb bc, 8, 12
+ jr DisplayYesNoChoice
+
+WideYesNoChoice:: ; unused
+ call SaveScreenTilesToBuffer1
+ ld a, WIDE_YES_NO_MENU
+ ld [wTwoOptionMenuID], a
+ coord hl, 12, 7
+ lb bc, 8, 13
+
+DisplayYesNoChoice::
+ ld a, TWO_OPTION_MENU
+ ld [wTextBoxID], a
+ call DisplayTextBoxID
+ jp LoadScreenTilesFromBuffer1