summaryrefslogtreecommitdiff
path: root/engine/menu
diff options
context:
space:
mode:
Diffstat (limited to 'engine/menu')
-rwxr-xr-xengine/menu/buy_sell_toss.asm235
-rwxr-xr-xengine/menu/clock_reset.asm254
-rwxr-xr-xengine/menu/delete_save_change_clock.asm296
-rwxr-xr-xengine/menu/main_menu.asm361
-rwxr-xr-xengine/menu/mart.asm970
-rwxr-xr-xengine/menu/menu.asm841
-rw-r--r--engine/menu/menu_2.asm253
-rwxr-xr-xengine/menu/mon_menu.asm304
-rwxr-xr-xengine/menu/naming_screen.asm1467
-rwxr-xr-xengine/menu/options_menu.asm583
-rw-r--r--engine/menu/pack.asm1711
-rwxr-xr-xengine/menu/scrolling_menu.asm543
-rwxr-xr-xengine/menu/start_menu.asm1993
-rwxr-xr-xengine/menu/switch_items.asm274
-rwxr-xr-xengine/menu/timeset.asm773
-rwxr-xr-xengine/menu/tmhm.asm49
-rwxr-xr-xengine/menu/trainer_card.asm623
17 files changed, 11530 insertions, 0 deletions
diff --git a/engine/menu/buy_sell_toss.asm b/engine/menu/buy_sell_toss.asm
new file mode 100755
index 000000000..84481d030
--- /dev/null
+++ b/engine/menu/buy_sell_toss.asm
@@ -0,0 +1,235 @@
+SelectQuantityToToss: ; 24fbf
+ ld hl, TossItem_MenuHeader
+ call LoadMenuHeader
+ call Toss_Sell_Loop
+ ret
+; 24fc9
+
+SelectQuantityToBuy: ; 24fc9
+ farcall GetItemPrice
+RooftopSale_SelectQuantityToBuy: ; 24fcf
+ ld a, d
+ ld [wBuffer1], a
+ ld a, e
+ ld [wBuffer2], a
+ ld hl, BuyItem_MenuHeader
+ call LoadMenuHeader
+ call Toss_Sell_Loop
+ ret
+; 24fe1
+
+SelectQuantityToSell: ; 24fe1
+ farcall GetItemPrice
+ ld a, d
+ ld [wBuffer1], a
+ ld a, e
+ ld [wBuffer2], a
+ ld hl, SellItem_MenuHeader
+ call LoadMenuHeader
+ call Toss_Sell_Loop
+ ret
+; 24ff9
+
+Toss_Sell_Loop: ; 24ff9
+ ld a, 1
+ ld [wItemQuantityChangeBuffer], a
+.loop
+ call BuySellToss_UpdateQuantityDisplay ; update display
+ call BuySellToss_InterpretJoypad ; joy action
+ jr nc, .loop
+ cp -1
+ jr nz, .nope ; pressed B
+ scf
+ ret
+
+.nope
+ and a
+ ret
+; 2500e
+
+BuySellToss_InterpretJoypad: ; 2500e
+ call JoyTextDelay_ForcehJoyDown ; get joypad
+ bit B_BUTTON_F, c
+ jr nz, .b
+ bit A_BUTTON_F, c
+ jr nz, .a
+ bit D_DOWN_F, c
+ jr nz, .down
+ bit D_UP_F, c
+ jr nz, .up
+ bit D_LEFT_F, c
+ jr nz, .left
+ bit D_RIGHT_F, c
+ jr nz, .right
+ and a
+ ret
+
+.b
+ ld a, -1
+ scf
+ ret
+
+.a
+ ld a, 0
+ scf
+ ret
+
+.down
+ ld hl, wItemQuantityChangeBuffer
+ dec [hl]
+ jr nz, .finish_down
+ ld a, [wItemQuantityBuffer]
+ ld [hl], a
+
+.finish_down
+ and a
+ ret
+
+.up
+ ld hl, wItemQuantityChangeBuffer
+ inc [hl]
+ ld a, [wItemQuantityBuffer]
+ cp [hl]
+ jr nc, .finish_up
+ ld [hl], 1
+
+.finish_up
+ and a
+ ret
+
+.left
+ ld a, [wItemQuantityChangeBuffer]
+ sub 10
+ jr c, .load_1
+ jr z, .load_1
+ jr .finish_left
+
+.load_1
+ ld a, 1
+
+.finish_left
+ ld [wItemQuantityChangeBuffer], a
+ and a
+ ret
+
+.right
+ ld a, [wItemQuantityChangeBuffer]
+ add 10
+ ld b, a
+ ld a, [wItemQuantityBuffer]
+ cp b
+ jr nc, .finish_right
+ ld b, a
+
+.finish_right
+ ld a, b
+ ld [wItemQuantityChangeBuffer], a
+ and a
+ ret
+; 25072
+
+BuySellToss_UpdateQuantityDisplay: ; 25072
+ call MenuBox
+ call MenuBoxCoord2Tile
+ ld de, SCREEN_WIDTH + 1
+ add hl, de
+ ld [hl], "×"
+ inc hl
+ ld de, wItemQuantityChangeBuffer
+ lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+ call PrintNum
+ ld a, [wMenuDataPointer]
+ ld e, a
+ ld a, [wMenuDataPointer + 1]
+ ld d, a
+ ld a, [wMenuDataBank]
+ call FarCall_de
+ ret
+; 25097
+
+ret_25097: ; 25097
+ ret
+; 25098
+
+DisplayPurchasePrice: ; 25098
+ call BuySell_MultiplyPrice
+ call BuySell_DisplaySubtotal
+ ret
+; 2509f
+
+DisplaySellingPrice: ; 2509f
+ call BuySell_MultiplyPrice
+ call Sell_HalvePrice
+ call BuySell_DisplaySubtotal
+ ret
+; 250a9
+
+BuySell_MultiplyPrice: ; 250a9
+ xor a
+ ld [hMultiplicand + 0], a
+ ld a, [wBuffer1]
+ ld [hMultiplicand + 1], a
+ ld a, [wBuffer2]
+ ld [hMultiplicand + 2], a
+ ld a, [wItemQuantityChangeBuffer]
+ ld [hMultiplier], a
+ push hl
+ call Multiply
+ pop hl
+ ret
+; 250c1
+
+Sell_HalvePrice: ; 250c1
+ push hl
+ ld hl, hProduct + 1
+ ld a, [hl]
+ srl a
+ ld [hli], a
+ ld a, [hl]
+ rra
+ ld [hli], a
+ ld a, [hl]
+ rra
+ ld [hl], a
+ pop hl
+ ret
+; 250d1
+
+BuySell_DisplaySubtotal: ; 250d1
+ push hl
+ ld hl, hMoneyTemp
+ ld a, [hProduct + 1]
+ ld [hli], a
+ ld a, [hProduct + 2]
+ ld [hli], a
+ ld a, [hProduct + 3]
+ ld [hl], a
+ pop hl
+ inc hl
+ ld de, hMoneyTemp
+ lb bc, PRINTNUM_MONEY | 3, 6
+ call PrintNum
+ call WaitBGMap
+ ret
+; 250ed
+
+TossItem_MenuHeader: ; 0x250ed
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 15, 9, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw ret_25097
+ db 0 ; default option
+; 0x250f5
+
+BuyItem_MenuHeader: ; 0x250f5
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 15, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+ dw DisplayPurchasePrice
+ db -1 ; default option
+; 0x250fd
+
+SellItem_MenuHeader: ; 0x250fd
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 15, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+ dw DisplaySellingPrice
+ db 0 ; default option
+; 0x25105
diff --git a/engine/menu/clock_reset.asm b/engine/menu/clock_reset.asm
new file mode 100755
index 000000000..c05129349
--- /dev/null
+++ b/engine/menu/clock_reset.asm
@@ -0,0 +1,254 @@
+
+ResetClock_GetWraparoundTime: ; 20000 (8:4000)
+ push hl
+ dec a
+ ld e, a
+ ld d, 0
+ ld hl, .WrapAroundTimes
+rept 4
+ add hl, de
+endr
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ inc hl
+ ld b, [hl]
+ inc hl
+ ld c, [hl]
+ pop hl
+ ret
+; 20015 (8:4015)
+
+.WrapAroundTimes: ; 20015
+ dw wBuffer4
+ db 7, 4
+
+ dw wBuffer5
+ db 24, 12
+
+ dw wBuffer6
+ db 60, 15
+; 20021
+
+RestartClock: ; 20021 (8:4021)
+; If we're here, we had an RTC overflow.
+ ld hl, .Text_ClockTimeMayBeWrong
+ call PrintText
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ call LoadStandardMenuHeader
+ call ClearTileMap
+ ld hl, .Text_SetWithControlPad
+ call PrintText
+ call .SetClock
+ call ExitMenu
+ pop bc
+ ld hl, wOptions
+ ld [hl], b
+ ld c, a
+ ret
+; 20047 (8:4047)
+
+.Text_ClockTimeMayBeWrong: ; 0x20047
+ ; The clock's time may be wrong. Please reset the time.
+ text_jump UnknownText_0x1c40e6
+ db "@"
+; 0x2004c
+
+.Text_SetWithControlPad: ; 0x2004c
+ ; Set with the Control Pad. Confirm: A Button Cancel: B Button
+ text_jump UnknownText_0x1c411c
+ db "@"
+; 0x20051
+
+.SetClock: ; 20051 (8:4051)
+ ld a, 1
+ ld [wBuffer1], a ; which digit
+ ld [wBuffer2], a
+ ld a, 8
+ ld [wBuffer3], a
+ call UpdateTime
+ call GetWeekday
+ ld [wBuffer4], a
+ ld a, [hHours]
+ ld [wBuffer5], a
+ ld a, [hMinutes]
+ ld [wBuffer6], a
+
+.loop
+ call .joy_loop
+ jr nc, .loop
+ and a
+ ret nz
+ call .PrintTime
+ ld hl, .Text_IsThisOK
+ call PrintText
+ call YesNoBox
+ jr c, .cancel
+ ld a, [wBuffer4]
+ ld [wStringBuffer2], a
+ ld a, [wBuffer5]
+ ld [wStringBuffer2 + 1], a
+ ld a, [wBuffer6]
+ ld [wStringBuffer2 + 2], a
+ xor a
+ ld [wStringBuffer2 + 3], a
+ call InitTime
+ call .PrintTime
+ ld hl, .Text_ClockReset
+ call PrintText
+ call WaitPressAorB_BlinkCursor
+ xor a
+ ret
+
+.cancel
+ ld a, $1
+ ret
+; 200b0 (8:40b0)
+
+.Text_IsThisOK: ; 0x200b0
+ ; Is this OK?
+ text_jump UnknownText_0x1c415b
+ db "@"
+; 0x200b5
+
+.Text_ClockReset: ; 0x200b5
+ ; The clock has been reset.
+ text_jump UnknownText_0x1c4168
+ db "@"
+; 0x200ba
+
+.joy_loop
+ call JoyTextDelay_ForcehJoyDown
+ ld c, a
+ push af
+ call .PrintTime
+ pop af
+ bit 0, a
+ jr nz, .press_A
+ bit 1, a
+ jr nz, .press_B
+ bit 6, a
+ jr nz, .pressed_up
+ bit 7, a
+ jr nz, .pressed_down
+ bit 5, a
+ jr nz, .pressed_left
+ bit 4, a
+ jr nz, .pressed_right
+ jr .joy_loop
+
+.press_A
+ ld a, $0
+ scf
+ ret
+
+.press_B
+ ld a, $1
+ scf
+ ret
+
+.pressed_up
+ ld a, [wBuffer1]
+ call ResetClock_GetWraparoundTime
+ ld a, [de]
+ inc a
+ ld [de], a
+ cp b
+ jr c, .done_scroll
+ ld a, $0
+ ld [de], a
+ jr .done_scroll
+
+.pressed_down
+ ld a, [wBuffer1]
+ call ResetClock_GetWraparoundTime
+ ld a, [de]
+ dec a
+ ld [de], a
+ cp -1
+ jr nz, .done_scroll
+ ld a, b
+ dec a
+ ld [de], a
+ jr .done_scroll
+
+.pressed_left
+ ld hl, wBuffer1
+ dec [hl]
+ jr nz, .done_scroll
+ ld [hl], $3
+ jr .done_scroll
+
+.pressed_right
+ ld hl, wBuffer1
+ inc [hl]
+ ld a, [hl]
+ cp $4
+ jr c, .done_scroll
+ ld [hl], $1
+
+.done_scroll
+ xor a
+ ret
+
+.PrintTime: ; 2011f (8:411f)
+ hlcoord 0, 5
+ ld b, 5
+ ld c, 18
+ call TextBox
+ decoord 1, 8
+ ld a, [wBuffer4]
+ ld b, a
+ farcall PrintDayOfWeek
+ ld a, [wBuffer5]
+ ld b, a
+ ld a, [wBuffer6]
+ ld c, a
+ decoord 11, 8
+ farcall PrintHoursMins
+ ld a, [wBuffer2]
+ lb de, " ", " "
+ call .PlaceChars
+ ld a, [wBuffer1]
+ lb de, "▲", "▼"
+ call .PlaceChars
+ ld a, [wBuffer1]
+ ld [wBuffer2], a
+ ret
+; 20160 (8:4160)
+
+.unreferenced ; 20160
+; unused
+ ld a, [wBuffer3]
+ ld b, a
+ call Coord2Tile
+ ret
+; 20168
+
+.PlaceChars: ; 20168 (8:4168)
+ push de
+ call ResetClock_GetWraparoundTime
+ ld a, [wBuffer3]
+ dec a
+ ld b, a
+ call Coord2Tile
+ pop de
+ ld [hl], d
+ ld bc, 2 * SCREEN_WIDTH
+ add hl, bc
+ ld [hl], e
+ ret
+; 2017c (8:417c)
+
+UnreferencedString_HourJP: ; 2017c
+; unused
+ db "じ@" ; HR
+; 2017e
+
+UnreferencedString_MinuteJP: ; 2017e
+; unused
+ db "ふん@" ; MIN
+; 20181
diff --git a/engine/menu/delete_save_change_clock.asm b/engine/menu/delete_save_change_clock.asm
new file mode 100755
index 000000000..431dc6034
--- /dev/null
+++ b/engine/menu/delete_save_change_clock.asm
@@ -0,0 +1,296 @@
+_ResetClock: ; 4d3b1
+ farcall BlankScreen
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ call LoadStandardFont
+ call LoadFontsExtra
+ ld de, MUSIC_MAIN_MENU
+ call PlayMusic
+ ld hl, .text_askreset
+ call PrintText
+ ld hl, .NoYes_MenuHeader
+ call CopyMenuHeader
+ call VerticalMenu
+ ret c
+ ld a, [wMenuCursorY]
+ cp $1
+ ret z
+ call ClockResetPassword
+ jr c, .wrongpassword
+ ld a, BANK(sRTCStatusFlags)
+ call GetSRAMBank
+ ld a, $80
+ ld [sRTCStatusFlags], a
+ call CloseSRAM
+ ld hl, .text_okay
+ call PrintText
+ ret
+
+.wrongpassword
+ ld hl, .text_wrong
+ call PrintText
+ ret
+
+.text_okay ; 0x4d3fe
+ ; Password OK. Select CONTINUE & reset settings.
+ text_jump UnknownText_0x1c55db
+ db "@"
+
+.text_wrong ; 0x4d403
+ ; Wrong password!
+ text_jump UnknownText_0x1c560b
+ db "@"
+
+.text_askreset ; 0x4d408
+ ; Reset the clock?
+ text_jump UnknownText_0x1c561c
+ db "@"
+
+.NoYes_MenuHeader: ; 0x4d40d
+ db 0 ; flags
+ menu_coords 14, 7, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .NoYes_MenuData
+ db 1 ; default option
+
+.NoYes_MenuData: ; 0x4d415
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 2 ; items
+ db "NO@"
+ db "YES@"
+
+ClockResetPassword: ; 4d41e
+ call .CalculatePassword
+ push de
+ ld hl, wStringBuffer2
+ ld bc, 5
+ xor a
+ call ByteFill
+ ld a, $4
+ ld [wStringBuffer2 + 5], a
+ ld hl, .pleaseenterpasswordtext
+ call PrintText
+.loop
+ call .updateIDdisplay
+.loop2
+ call JoyTextDelay
+ ld a, [hJoyLast]
+ ld b, a
+ and A_BUTTON
+ jr nz, .confirm
+ ld a, b
+ and D_PAD
+ jr z, .loop2
+ call .dpadinput
+ ld c, 3
+ call DelayFrames
+ jr .loop
+
+.confirm
+ call .ConvertDecIDToBytes
+ pop de
+ ld a, e
+ cp l
+ jr nz, .nope
+ ld a, d
+ cp h
+ jr nz, .nope
+ and a
+ ret
+
+.nope
+ scf
+ ret
+
+.pleaseenterpasswordtext ; 0x4d463
+ ; Please enter the password.
+ text_jump UnknownText_0x1c562e
+ db "@"
+
+.updateIDdisplay ; 4d468
+ hlcoord 14, 15
+ ld de, wStringBuffer2
+ ld c, 5
+.loop3
+ ld a, [de]
+ add "0"
+ ld [hli], a
+ inc de
+ dec c
+ jr nz, .loop3
+ hlcoord 14, 16
+ ld bc, 5
+ ld a, " "
+ call ByteFill
+ hlcoord 14, 16
+ ld a, [wStringBuffer2 + 5]
+ ld e, a
+ ld d, $0
+ add hl, de
+ ld [hl], "▲"
+ ret
+
+.dpadinput ; 4d490
+ ld a, b
+ and D_LEFT
+ jr nz, .left
+ ld a, b
+ and D_RIGHT
+ jr nz, .right
+ ld a, b
+ and D_UP
+ jr nz, .up
+ ld a, b
+ and D_DOWN
+ jr nz, .down
+ ret
+
+.left
+ ld a, [wStringBuffer2 + 5]
+ and a
+ ret z
+ dec a
+ ld [wStringBuffer2 + 5], a
+ ret
+
+.right
+ ld a, [wStringBuffer2 + 5]
+ cp $4
+ ret z
+ inc a
+ ld [wStringBuffer2 + 5], a
+ ret
+
+.up
+ call .getcurrentdigit
+ ld a, [hl]
+ cp 9
+ jr z, .wraparound_up
+ inc a
+ ld [hl], a
+ ret
+
+.wraparound_up
+ ld [hl], $0
+ ret
+
+.down
+ call .getcurrentdigit
+ ld a, [hl]
+ and a
+ jr z, .wraparound_down
+ dec a
+ ld [hl], a
+ ret
+
+.wraparound_down
+ ld [hl], 9
+ ret
+
+.getcurrentdigit ; 4d4d5
+ ld a, [wStringBuffer2 + 5]
+ ld e, a
+ ld d, $0
+ ld hl, wStringBuffer2
+ add hl, de
+ ret
+
+.ConvertDecIDToBytes: ; 4d4e0
+ ld hl, 0
+ ld de, wStringBuffer2 + 4
+ ld bc, 1
+ call .ConvertToBytes
+ ld bc, 10
+ call .ConvertToBytes
+ ld bc, 100
+ call .ConvertToBytes
+ ld bc, 1000
+ call .ConvertToBytes
+ ld bc, 10000
+.ConvertToBytes: ; 4d501
+ ld a, [de]
+ dec de
+ push hl
+ ld hl, 0
+ call AddNTimes
+ ld c, l
+ ld b, h
+ pop hl
+ add hl, bc
+ ret
+
+.CalculatePassword: ; 4d50f
+ ld a, BANK(sPlayerData)
+ call GetSRAMBank
+ ld de, 0
+ ld hl, sPlayerData + (wPlayerID - wPlayerData)
+ ld c, $2
+ call .ComponentFromNumber
+ ld hl, sPlayerData + (wPlayerName - wPlayerData)
+ ld c, NAME_LENGTH_JAPANESE - 1
+ call .ComponentFromString
+ ld hl, sPlayerData + (wMoney - wPlayerData)
+ ld c, $3
+ call .ComponentFromNumber
+ call CloseSRAM
+ ret
+
+.ComponentFromNumber: ; 4d533
+ ld a, [hli]
+ add e
+ ld e, a
+ ld a, $0
+ adc d
+ ld d, a
+ dec c
+ jr nz, .ComponentFromNumber
+ ret
+
+.ComponentFromString: ; 4d53e
+ ld a, [hli]
+ cp "@"
+ ret z
+ add e
+ ld e, a
+ ld a, $0
+ adc d
+ ld d, a
+ dec c
+ jr nz, .ComponentFromString
+ ret
+
+_DeleteSaveData: ; 4d54c
+ farcall BlankScreen
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ call LoadStandardFont
+ call LoadFontsExtra
+ ld de, MUSIC_MAIN_MENU
+ call PlayMusic
+ ld hl, .Text_ClearAllSaveData
+ call PrintText
+ ld hl, .NoYesMenuHeader
+ call CopyMenuHeader
+ call VerticalMenu
+ ret c
+ ld a, [wMenuCursorY]
+ cp $1
+ ret z
+ farcall EmptyAllSRAMBanks
+ ret
+
+.Text_ClearAllSaveData: ; 0x4d580
+ ; Clear all save data?
+ text_jump UnknownText_0x1c564a
+ db "@"
+
+.NoYesMenuHeader: ; 0x4d585
+ db 0 ; flags
+ menu_coords 14, 7, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+
+.MenuData: ; 0x4d58d
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 2 ; items
+ db "NO@"
+ db "YES@"
diff --git a/engine/menu/main_menu.asm b/engine/menu/main_menu.asm
new file mode 100755
index 000000000..d83ce873b
--- /dev/null
+++ b/engine/menu/main_menu.asm
@@ -0,0 +1,361 @@
+GFX_49c0c: ; 49c0c
+INCBIN "gfx/unknown/049c0c.2bpp"
+; 49cdc
+
+MainMenu: ; 49cdc
+ xor a
+ ld [wDisableTextAcceleration], a
+ call Function49ed0
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ call SetPalettes
+ ld hl, wGameTimerPause
+ res GAMETIMERPAUSE_TIMER_PAUSED_F, [hl]
+ call MainMenu_GetWhichMenu
+ ld [wWhichIndexSet], a
+ call MainMenu_PrintCurrentTimeAndDay
+ ld hl, .MenuHeader
+ call LoadMenuHeader
+ call MainMenuJoypadLoop
+ call CloseWindow
+ jr c, .quit
+ call ClearTileMap
+ ld a, [wMenuSelection]
+ ld hl, .Jumptable
+ rst JumpTable
+ jr MainMenu
+
+.quit
+ ret
+; 49d14
+
+.MenuHeader: ; 49d14
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 0, 0, 16, 7
+ dw .MenuData
+ db 1 ; default option
+; 49d1c
+
+.MenuData: ; 49d1c
+ db STATICMENU_CURSOR ; flags
+ db 0 ; items
+ dw MainMenuItems
+ dw PlaceMenuStrings
+ dw .Strings
+; 49d20
+
+.Strings: ; 49d24
+ db "CONTINUE@"
+ db "NEW GAME@"
+ db "OPTION@"
+ db "MYSTERY GIFT@"
+ db "MOBILE@"
+ db "MOBILE STUDIUM@"
+
+.Jumptable: ; 0x49d60
+ dw MainMenu_Continue
+ dw MainMenu_NewGame
+ dw MainMenu_Options
+ dw MainMenu_MysteryGift
+ dw MainMenu_Mobile
+ dw MainMenu_MobileStudium
+; 0x49d6c
+
+CONTINUE EQU 0
+NEW_GAME EQU 1
+OPTION EQU 2
+MYSTERY_GIFT EQU 3
+MOBILE EQU 4
+MOBILE_STUDIUM EQU 5
+
+MainMenuItems:
+
+NewGameMenu: ; 0x49d6c
+ db 2
+ db NEW_GAME
+ db OPTION
+ db -1
+
+ContinueMenu: ; 0x49d70
+ db 3
+ db CONTINUE
+ db NEW_GAME
+ db OPTION
+ db -1
+
+MobileMysteryMenu: ; 0x49d75
+ db 5
+ db CONTINUE
+ db NEW_GAME
+ db OPTION
+ db MYSTERY_GIFT
+ db MOBILE
+ db -1
+
+MobileMenu: ; 0x49d7c
+ db 4
+ db CONTINUE
+ db NEW_GAME
+ db OPTION
+ db MOBILE
+ db -1
+
+MobileStudiumMenu: ; 0x49d82
+ db 5
+ db CONTINUE
+ db NEW_GAME
+ db OPTION
+ db MOBILE
+ db MOBILE_STUDIUM
+ db -1
+
+MysteryMobileStudiumMenu: ; 0x49d89
+ db 6
+ db CONTINUE
+ db NEW_GAME
+ db OPTION
+ db MYSTERY_GIFT
+ db MOBILE
+ db MOBILE_STUDIUM
+ db -1
+
+MysteryMenu: ; 0x49d91
+ db 4
+ db CONTINUE
+ db NEW_GAME
+ db OPTION
+ db MYSTERY_GIFT
+ db -1
+
+MysteryStudiumMenu: ; 0x49d97
+ db 5
+ db CONTINUE
+ db NEW_GAME
+ db OPTION
+ db MYSTERY_GIFT
+ db MOBILE_STUDIUM
+ db -1
+
+StudiumMenu: ; 0x49d9e
+ db 4
+ db CONTINUE
+ db NEW_GAME
+ db OPTION
+ db MOBILE_STUDIUM
+ db -1
+
+
+MainMenu_GetWhichMenu: ; 49da4
+ nop
+ nop
+ nop
+ ld a, [wSaveFileExists]
+ and a
+ jr nz, .next
+ ld a, $0 ; New Game
+ ret
+
+.next
+ ld a, [hCGB]
+ cp $1
+ ld a, $1
+ ret nz
+ ld a, BANK(sNumDailyMysteryGiftPartnerIDs)
+ call GetSRAMBank
+ ld a, [sNumDailyMysteryGiftPartnerIDs]
+ cp -1
+ call CloseSRAM
+ jr nz, .mystery_gift
+ ; This check makes no difference.
+ ld a, [wStatusFlags]
+ bit STATUSFLAGS_MAIN_MENU_MOBILE_CHOICES_F, a
+ ld a, $1 ; Continue
+ jr z, .ok
+ jr .ok
+
+.ok
+ jr .ok2
+
+.ok2
+ ld a, $1 ; Continue
+ ret
+
+.mystery_gift
+ ; This check makes no difference.
+ ld a, [wStatusFlags]
+ bit STATUSFLAGS_MAIN_MENU_MOBILE_CHOICES_F, a
+ jr z, .ok3
+ jr .ok3
+
+.ok3
+ jr .ok4
+
+.ok4
+ ld a, $6 ; Mystery Gift
+ ret
+; 49de4
+
+MainMenuJoypadLoop: ; 49de4
+ call SetUpMenu
+.loop
+ call MainMenu_PrintCurrentTimeAndDay
+ ld a, [w2DMenuFlags1]
+ set 5, a
+ ld [w2DMenuFlags1], a
+ call GetScrollingMenuJoypad
+ ld a, [wMenuJoypad]
+ cp B_BUTTON
+ jr z, .b_button
+ cp A_BUTTON
+ jr z, .a_button
+ jr .loop
+
+.a_button
+ call PlayClickSFX
+ and a
+ ret
+
+.b_button
+ scf
+ ret
+; 49e09
+
+MainMenu_PrintCurrentTimeAndDay: ; 49e09
+ ld a, [wSaveFileExists]
+ and a
+ ret z
+ xor a
+ ld [hBGMapMode], a
+ call .PlaceBox
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ call .PlaceTime
+ pop af
+ ld [wOptions], a
+ ld a, $1
+ ld [hBGMapMode], a
+ ret
+; 49e27
+
+
+.PlaceBox: ; 49e27
+ call CheckRTCStatus
+ and $80
+ jr nz, .TimeFail
+ hlcoord 0, 14
+ ld b, 2
+ ld c, 18
+ call TextBox
+ ret
+
+.TimeFail:
+ call SpeechTextBox
+ ret
+; 49e3d
+
+
+.PlaceTime: ; 49e3d
+ ld a, [wSaveFileExists]
+ and a
+ ret z
+ call CheckRTCStatus
+ and $80
+ jp nz, .PrintTimeNotSet
+ call UpdateTime
+ call GetWeekday
+ ld b, a
+ decoord 1, 15
+ call .PlaceCurrentDay
+ decoord 4, 16
+ ld a, [hHours]
+ ld c, a
+ farcall PrintHour
+ ld [hl], ":"
+ inc hl
+ ld de, hMinutes
+ lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+ call PrintNum
+ ret
+
+.min
+; unused
+ db "min.@"
+; 49e75
+
+.PrintTimeNotSet: ; 49e75
+ hlcoord 1, 14
+ ld de, .TimeNotSet
+ call PlaceString
+ ret
+; 49e7f
+
+.TimeNotSet: ; 49e7f
+ db "TIME NOT SET@"
+; 49e8c
+
+.UnusedText: ; 49e8c
+ ; Clock time unknown
+ text_jump UnknownText_0x1c5182
+ db "@"
+; 49e91
+
+.PlaceCurrentDay: ; 49e91
+ push de
+ ld hl, .Days
+ ld a, b
+ call GetNthString
+ ld d, h
+ ld e, l
+ pop hl
+ call PlaceString
+ ld h, b
+ ld l, c
+ ld de, .Day
+ call PlaceString
+ ret
+; 49ea8
+
+.Days:
+ db "SUN@"
+ db "MON@"
+ db "TUES@"
+ db "WEDNES@"
+ db "THURS@"
+ db "FRI@"
+ db "SATUR@"
+.Day:
+ db "DAY@"
+; 49ed0
+
+Function49ed0: ; 49ed0
+ xor a
+ ld [hMapAnims], a
+ call ClearTileMap
+ call LoadFontsExtra
+ call LoadStandardFont
+ call ClearWindowData
+ ret
+; 49ee0
+
+
+MainMenu_NewGame: ; 49ee0
+ farcall NewGame
+ ret
+; 49ee7
+
+MainMenu_Options: ; 49ee7
+ farcall OptionsMenu
+ ret
+; 49eee
+
+MainMenu_Continue: ; 49eee
+ farcall Continue
+ ret
+; 49ef5
+
+MainMenu_MysteryGift: ; 49ef5
+ farcall MysteryGift
+ ret
+; 49efc
diff --git a/engine/menu/mart.asm b/engine/menu/mart.asm
new file mode 100755
index 000000000..911251f65
--- /dev/null
+++ b/engine/menu/mart.asm
@@ -0,0 +1,970 @@
+ const_def
+ const MARTTEXT_HOW_MANY
+ const MARTTEXT_COSTS_THIS_MUCH
+ const MARTTEXT_NOT_ENOUGH_MONEY
+ const MARTTEXT_BAG_FULL
+ const MARTTEXT_HERE_YOU_GO
+ const MARTTEXT_SOLD_OUT
+
+OpenMartDialog:: ; 15a45
+ call GetMart
+ ld a, c
+ ld [wEngineBuffer1], a
+ call LoadMartPointer
+ ld a, [wEngineBuffer1]
+ ld hl, .dialogs
+ rst JumpTable
+ ret
+; 15a57
+
+.dialogs
+ dw MartDialog
+ dw HerbShop
+ dw BargainShop
+ dw Pharmacist
+ dw RooftopSale
+; 15a61
+
+MartDialog: ; 15a61
+ ld a, 0
+ ld [wEngineBuffer1], a
+ xor a
+ ld [wEngineBuffer5], a
+ call StandardMart
+ ret
+; 15a6e
+
+HerbShop: ; 15a6e
+ call FarReadMart
+ call LoadStandardMenuHeader
+ ld hl, Text_HerbShop_Intro
+ call MartTextBox
+ call BuyMenu
+ ld hl, Text_HerbShop_ComeAgain
+ call MartTextBox
+ ret
+; 15a84
+
+BargainShop: ; 15a84
+ ld b, BANK(BargainShopData)
+ ld de, BargainShopData
+ call LoadMartPointer
+ call ReadMart
+ call LoadStandardMenuHeader
+ ld hl, Text_BargainShop_Intro
+ call MartTextBox
+ call BuyMenu
+ ld hl, wBargainShopFlags
+ ld a, [hli]
+ or [hl]
+ jr z, .skip_set
+ ld hl, wDailyFlags
+ set DAILYFLAGS_GOLDENROD_UNDERGROUND_BARGAIN_F, [hl]
+
+.skip_set
+ ld hl, Text_BargainShop_ComeAgain
+ call MartTextBox
+ ret
+; 15aae
+
+Pharmacist: ; 15aae
+ call FarReadMart
+ call LoadStandardMenuHeader
+ ld hl, Text_Pharmacist_Intro
+ call MartTextBox
+ call BuyMenu
+ ld hl, Text_Pharmacist_ComeAgain
+ call MartTextBox
+ ret
+; 15ac4
+
+RooftopSale: ; 15ac4
+ ld b, BANK(RooftopSaleMart1)
+ ld de, RooftopSaleMart1
+ ld hl, wStatusFlags
+ bit STATUSFLAGS_HALL_OF_FAME_F, [hl]
+ jr z, .ok
+ ld b, BANK(RooftopSaleMart2)
+ ld de, RooftopSaleMart2
+
+.ok
+ call LoadMartPointer
+ call ReadMart
+ call LoadStandardMenuHeader
+ ld hl, Text_Mart_HowMayIHelpYou
+ call MartTextBox
+ call BuyMenu
+ ld hl, Text_Mart_ComeAgain
+ call MartTextBox
+ ret
+; 15aee
+
+INCLUDE "data/items/rooftop_sale.asm"
+
+LoadMartPointer: ; 15b10
+ ld a, b
+ ld [wMartPointerBank], a
+ ld a, e
+ ld [wMartPointer], a
+ ld a, d
+ ld [wMartPointer + 1], a
+ ld hl, wCurMart
+ xor a
+ ld bc, 16
+ call ByteFill
+ xor a
+ ld [wEngineBuffer5], a
+ ld [wBargainShopFlags], a
+ ld [wFacingDirection], a
+ ret
+; 15b31
+
+GetMart: ; 15b31
+ ld a, e
+ cp (Marts.End - Marts) / 2
+ jr c, .IsAMart
+ ld b, BANK(DefaultMart)
+ ld de, DefaultMart
+ ret
+
+.IsAMart:
+ ld hl, Marts
+ add hl, de
+ add hl, de
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ld b, BANK(Marts)
+ ret
+; 15b47
+
+StandardMart: ; 15b47
+.loop
+ ld a, [wEngineBuffer5]
+ ld hl, .MartFunctions
+ rst JumpTable
+ ld [wEngineBuffer5], a
+ cp $ff
+ jr nz, .loop
+ ret
+
+.MartFunctions:
+ dw .HowMayIHelpYou
+ dw .TopMenu
+ dw .Buy
+ dw .Sell
+ dw .Quit
+ dw .AnythingElse
+; 15b62
+
+.HowMayIHelpYou: ; 15b62
+ call LoadStandardMenuHeader
+ ld hl, Text_Mart_HowMayIHelpYou
+ call PrintText
+ ld a, $1 ; top menu
+ ret
+; 15b6e
+
+.TopMenu: ; 15b6e
+ ld hl, MenuHeader_BuySell
+ call CopyMenuHeader
+ call VerticalMenu
+ jr c, .quit
+ ld a, [wMenuCursorY]
+ cp $1
+ jr z, .buy
+ cp $2
+ jr z, .sell
+.quit
+ ld a, $4 ; Come again!
+ ret
+.buy
+ ld a, $2 ; buy
+ ret
+.sell
+ ld a, $3 ; sell
+ ret
+; 15b8d
+
+.Buy: ; 15b8d
+ call ExitMenu
+ call FarReadMart
+ call BuyMenu
+ and a
+ ld a, $5 ; Anything else?
+ ret
+; 15b9a
+
+.Sell: ; 15b9a
+ call ExitMenu
+ call SellMenu
+ ld a, $5 ; Anything else?
+ ret
+; 15ba3
+
+.Quit: ; 15ba3
+ call ExitMenu
+ ld hl, Text_Mart_ComeAgain
+ call MartTextBox
+ ld a, $ff ; exit
+ ret
+; 15baf
+
+.AnythingElse: ; 15baf
+ call LoadStandardMenuHeader
+ ld hl, Text_Mart_AnythingElse
+ call PrintText
+ ld a, $1 ; top menu
+ ret
+; 15bbb
+
+FarReadMart: ; 15bbb
+ ld hl, wMartPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, wCurMart
+.CopyMart:
+ ld a, [wMartPointerBank]
+ call GetFarByte
+ ld [de], a
+ inc hl
+ inc de
+ cp -1
+ jr nz, .CopyMart
+ ld hl, wMartItem1BCD
+ ld de, wCurMart + 1
+.ReadMartItem:
+ ld a, [de]
+ inc de
+ cp -1
+ jr z, .done
+ push de
+ call GetMartItemPrice
+ pop de
+ jr .ReadMartItem
+
+.done
+ ret
+; 15be5
+
+GetMartItemPrice: ; 15be5
+; Return the price of item a in BCD at hl and in tiles at wStringBuffer1.
+ push hl
+ ld [wCurItem], a
+ farcall GetItemPrice
+ pop hl
+
+GetMartPrice: ; 15bf0
+; Return price de in BCD at hl and in tiles at wStringBuffer1.
+ push hl
+ ld a, d
+ ld [wStringBuffer2], a
+ ld a, e
+ ld [wStringBuffer2 + 1], a
+ ld hl, wStringBuffer1
+ ld de, wStringBuffer2
+ lb bc, PRINTNUM_LEADINGZEROS | 2, 6 ; 6 digits
+ call PrintNum
+ pop hl
+
+ ld de, wStringBuffer1
+ ld c, 6 / 2 ; 6 digits
+.loop
+ call .CharToNybble
+ swap a
+ ld b, a
+ call .CharToNybble
+ or b
+ ld [hli], a
+ dec c
+ jr nz, .loop
+ ret
+; 15c1a
+
+.CharToNybble: ; 15c1a
+ ld a, [de]
+ inc de
+ cp " "
+ jr nz, .not_space
+ ld a, "0"
+
+.not_space
+ sub "0"
+ ret
+; 15c25
+
+ReadMart: ; 15c25
+; Load the mart pointer. Mart data is local (no need for bank).
+ ld hl, wMartPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ push hl
+; set hl to the first item
+ inc hl
+ ld bc, wMartItem1BCD
+ ld de, wCurMart + 1
+.loop
+; copy the item to wCurMart + (ItemIndex)
+ ld a, [hli]
+ ld [de], a
+ inc de
+; -1 is the terminator
+ cp -1
+ jr z, .done
+
+ push de
+; copy the price to de
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+ ld d, a
+; convert the price to 3-byte BCD at [bc]
+ push hl
+ ld h, b
+ ld l, c
+ call GetMartPrice
+ ld b, h
+ ld c, l
+ pop hl
+
+ pop de
+ jr .loop
+
+.done
+ pop hl
+ ld a, [hl]
+ ld [wCurMart], a
+ ret
+; 15c51
+
+INCLUDE "data/items/bargain_shop.asm"
+
+
+BuyMenu: ; 15c62
+ call FadeToMenu
+ farcall BlankScreen
+ xor a
+ ld [wMenuScrollPositionBackup], a
+ ld a, 1
+ ld [wMenuCursorBufferBackup], a
+.loop
+ call BuyMenuLoop ; menu loop
+ jr nc, .loop
+ call CloseSubmenu
+ ret
+; 15c7d
+
+LoadBuyMenuText: ; 15c7d
+; load text from a nested table
+; which table is in wEngineBuffer1
+; which entry is in register a
+ push af
+ call GetMartDialogGroup ; gets a pointer from GetMartDialogGroup.MartTextFunctionPointers
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ pop af
+ ld e, a
+ ld d, 0
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call PrintText
+ ret
+; 15c91
+
+MartAskPurchaseQuantity: ; 15c91
+ call GetMartDialogGroup ; gets a pointer from GetMartDialogGroup.MartTextFunctionPointers
+ inc hl
+ inc hl
+ ld a, [hl]
+ and a
+ jp z, StandardMartAskPurchaseQuantity
+ cp 1
+ jp z, BargainShopAskPurchaseQuantity
+ jp RooftopSaleAskPurchaseQuantity
+; 15ca3
+
+GetMartDialogGroup: ; 15ca3
+ ld a, [wEngineBuffer1]
+ ld e, a
+ ld d, 0
+ ld hl, .MartTextFunctionPointers
+ add hl, de
+ add hl, de
+ add hl, de
+ ret
+; 15cb0
+
+.MartTextFunctionPointers: ; 15cb0
+ dwb .StandardMartPointers, 0
+ dwb .HerbShopPointers, 0
+ dwb .BargainShopPointers, 1
+ dwb .PharmacyPointers, 0
+ dwb .StandardMartPointers, 2
+; 15cbf
+
+.StandardMartPointers: ; 15cbf
+ dw Text_Mart_HowMany
+ dw Text_Mart_CostsThisMuch
+ dw Text_Mart_InsufficientFunds
+ dw Text_Mart_BagFull
+ dw Text_Mart_HereYouGo
+ dw BuyMenuLoop
+
+.HerbShopPointers: ; 15ccb
+ dw Text_HerbShop_HowMany
+ dw Text_HerbShop_CostsThisMuch
+ dw Text_HerbShop_InsufficientFunds
+ dw Text_HerbShop_BagFull
+ dw Text_HerbShop_HereYouGo
+ dw BuyMenuLoop
+
+.BargainShopPointers: ; 15cd7
+ dw BuyMenuLoop
+ dw Text_BargainShop_CostsThisMuch
+ dw Text_BargainShop_InsufficientFunds
+ dw Text_BargainShop_BagFull
+ dw Text_BargainShop_HereYouGo
+ dw Text_BargainShop_SoldOut
+
+.PharmacyPointers: ; 15ce3
+ dw Text_Pharmacy_HowMany
+ dw Text_Pharmacy_CostsThisMuch
+ dw Text_Pharmacy_InsufficientFunds
+ dw Text_Pharmacy_BagFull
+ dw Text_Pharmacy_HereYouGo
+ dw BuyMenuLoop
+; 15cef
+
+
+BuyMenuLoop: ; 15cef
+ farcall PlaceMoneyTopRight
+ call UpdateSprites
+ ld hl, MenuHeader_Buy
+ call CopyMenuHeader
+ ld a, [wMenuCursorBufferBackup]
+ ld [wMenuCursorBuffer], a
+ ld a, [wMenuScrollPositionBackup]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wMenuScrollPositionBackup], a
+ ld a, [wMenuCursorY]
+ ld [wMenuCursorBufferBackup], a
+ call SpeechTextBox
+ ld a, [wMenuJoypad]
+ cp B_BUTTON
+ jr z, .set_carry
+ cp A_BUTTON
+ jr z, .useless_pointer
+
+.useless_pointer
+ call MartAskPurchaseQuantity
+ jr c, .cancel
+ call MartConfirmPurchase
+ jr c, .cancel
+ ld de, wMoney
+ ld bc, hMoneyTemp
+ ld a, $3 ; useless load
+ call CompareMoney
+ jr c, .insufficient_funds
+ ld hl, wNumItems
+ call ReceiveItem
+ jr nc, .insufficient_bag_space
+ ld a, [wMartItemID]
+ ld e, a
+ ld d, $0
+ ld b, SET_FLAG
+ ld hl, wBargainShopFlags
+ call FlagAction
+ call PlayTransactionSound
+ ld de, wMoney
+ ld bc, hMoneyTemp
+ call TakeMoney
+ ld a, MARTTEXT_HERE_YOU_GO
+ call LoadBuyMenuText
+ call JoyWaitAorB
+
+.cancel
+ call SpeechTextBox
+ and a
+ ret
+
+.set_carry
+ scf
+ ret
+
+.insufficient_bag_space
+ ld a, MARTTEXT_BAG_FULL
+ call LoadBuyMenuText
+ call JoyWaitAorB
+ and a
+ ret
+
+.insufficient_funds
+ ld a, MARTTEXT_NOT_ENOUGH_MONEY
+ call LoadBuyMenuText
+ call JoyWaitAorB
+ and a
+ ret
+; 15d83
+
+StandardMartAskPurchaseQuantity:
+ ld a, 99
+ ld [wItemQuantityBuffer], a
+ ld a, MARTTEXT_HOW_MANY
+ call LoadBuyMenuText
+ farcall SelectQuantityToBuy
+ call ExitMenu
+ ret
+; 15d97
+
+MartConfirmPurchase: ; 15d97
+ predef PartyMonItemName
+ ld a, MARTTEXT_COSTS_THIS_MUCH
+ call LoadBuyMenuText
+ call YesNoBox
+ ret
+; 15da5
+
+BargainShopAskPurchaseQuantity:
+ ld a, 1
+ ld [wItemQuantityChangeBuffer], a
+ ld a, [wMartItemID]
+ ld e, a
+ ld d, $0
+ ld b, CHECK_FLAG
+ ld hl, wBargainShopFlags
+ call FlagAction
+ ld a, c
+ and a
+ jr nz, .SoldOut
+ ld a, [wMartItemID]
+ ld e, a
+ ld d, $0
+ ld hl, wMartPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ inc hl
+ add hl, de
+ add hl, de
+ add hl, de
+ inc hl
+ ld a, [hli]
+ ld [hMoneyTemp + 2], a
+ ld a, [hl]
+ ld [hMoneyTemp + 1], a
+ xor a
+ ld [hMoneyTemp], a
+ and a
+ ret
+
+.SoldOut:
+ ld a, MARTTEXT_SOLD_OUT
+ call LoadBuyMenuText
+ call JoyWaitAorB
+ scf
+ ret
+; 15de2
+
+RooftopSaleAskPurchaseQuantity:
+ ld a, MARTTEXT_HOW_MANY
+ call LoadBuyMenuText
+ call .GetSalePrice
+ ld a, 99
+ ld [wItemQuantityBuffer], a
+ farcall RooftopSale_SelectQuantityToBuy
+ call ExitMenu
+ ret
+; 15df9
+
+.GetSalePrice: ; 15df9
+ ld a, [wMartItemID]
+ ld e, a
+ ld d, 0
+ ld hl, wMartPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ inc hl
+ add hl, de
+ add hl, de
+ add hl, de
+ inc hl
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ret
+; 15e0e
+
+
+Text_Mart_HowMany: ; 0x15e0e
+ ; How many?
+ text_jump UnknownText_0x1c4bfd
+ db "@"
+; 0x15e13
+
+Text_Mart_CostsThisMuch: ; 0x15e13
+ ; @ (S) will be ¥@ .
+ text_jump UnknownText_0x1c4c08
+ db "@"
+; 0x15e18
+
+MenuHeader_Buy: ; 0x15e18
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 1, 3, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x15e20
+
+.MenuData ; 0x15e20
+ db SCROLLINGMENU_DISPLAY_ARROWS | SCROLLINGMENU_ENABLE_FUNCTION3 ; flags
+ db 4, 8 ; rows, columns
+ db 1 ; horizontal spacing
+ dbw 0, wCurMart
+ dba PlaceMenuItemName
+ dba .PrintBCDPrices
+ dba UpdateItemDescription
+; 15e30
+
+.PrintBCDPrices: ; 15e30
+ ld a, [wScrollingMenuCursorPosition]
+ ld c, a
+ ld b, 0
+ ld hl, wMartItem1BCD
+ add hl, bc
+ add hl, bc
+ add hl, bc
+ push de
+ ld d, h
+ ld e, l
+ pop hl
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ ld c, PRINTNUM_LEADINGZEROS | PRINTNUM_MONEY | 3
+ call PrintBCDNumber
+ ret
+; 15e4a (5:5e4a)
+
+Text_HerbShop_Intro: ; 0x15e4a
+ ; Hello, dear. I sell inexpensive herbal medicine. They're good, but a trifle bitter. Your #MON may not like them. Hehehehe…
+ text_jump UnknownText_0x1c4c28
+ db "@"
+; 0x15e4f
+
+Text_HerbShop_HowMany: ; 0x15e4f
+ ; How many?
+ text_jump UnknownText_0x1c4ca3
+ db "@"
+; 0x15e54
+
+Text_HerbShop_CostsThisMuch: ; 0x15e54
+ ; @ (S) will be ¥@ .
+ text_jump UnknownText_0x1c4cae
+ db "@"
+; 0x15e59
+
+Text_HerbShop_HereYouGo: ; 0x15e59
+ ; Thank you, dear. Hehehehe…
+ text_jump UnknownText_0x1c4cce
+ db "@"
+; 0x15e5e
+
+Text_HerbShop_BagFull: ; 0x15e5e
+ ; Oh? Your PACK is full, dear.
+ text_jump UnknownText_0x1c4cea
+ db "@"
+; 0x15e63
+
+Text_HerbShop_InsufficientFunds: ; 0x15e63
+ ; Hehehe… You don't have the money.
+ text_jump UnknownText_0x1c4d08
+ db "@"
+; 0x15e68
+
+Text_HerbShop_ComeAgain: ; 0x15e68
+ ; Come again, dear. Hehehehe…
+ text_jump UnknownText_0x1c4d2a
+ db "@"
+; 0x15e6d
+
+Text_BargainShop_Intro: ; 0x15e6d
+ ; Hiya! Care to see some bargains? I sell rare items that nobody else carries--but only one of each item.
+ text_jump UnknownText_0x1c4d47
+ db "@"
+; 0x15e72
+
+Text_BargainShop_CostsThisMuch: ; 0x15e72
+ ; costs ¥@ . Want it?
+ text_jump UnknownText_0x1c4db0
+ db "@"
+; 0x15e77
+
+Text_BargainShop_HereYouGo: ; 0x15e77
+ ; Thanks.
+ text_jump UnknownText_0x1c4dcd
+ db "@"
+; 0x15e7c
+
+Text_BargainShop_BagFull: ; 0x15e7c
+ ; Uh-oh, your PACK is chock-full.
+ text_jump UnknownText_0x1c4dd6
+ db "@"
+; 0x15e81
+
+Text_BargainShop_SoldOut: ; 0x15e81
+ ; You bought that already. I'm all sold out of it.
+ text_jump UnknownText_0x1c4df7
+ db "@"
+; 0x15e86
+
+Text_BargainShop_InsufficientFunds: ; 0x15e86
+ ; Uh-oh, you're short on funds.
+ text_jump UnknownText_0x1c4e28
+ db "@"
+; 0x15e8b
+
+Text_BargainShop_ComeAgain: ; 0x15e8b
+ ; Come by again sometime.
+ text_jump UnknownText_0x1c4e46
+ db "@"
+; 0x15e90
+
+Text_Pharmacist_Intro: ; 0x15e90
+ ; What's up? Need some medicine?
+ text_jump UnknownText_0x1c4e5f
+ db "@"
+; 0x15e95
+
+Text_Pharmacy_HowMany: ; 0x15e95
+ ; How many?
+ text_jump UnknownText_0x1c4e7e
+ db "@"
+; 0x15e9a
+
+Text_Pharmacy_CostsThisMuch: ; 0x15e9a
+ ; @ (S) will cost ¥@ .
+ text_jump UnknownText_0x1c4e89
+ db "@"
+; 0x15e9f
+
+Text_Pharmacy_HereYouGo: ; 0x15e9f
+ ; Thanks much!
+ text_jump UnknownText_0x1c4eab
+ db "@"
+; 0x15ea4
+
+Text_Pharmacy_BagFull: ; 0x15ea4
+ ; You don't have any more space.
+ text_jump UnknownText_0x1c4eb9
+ db "@"
+; 0x15ea9
+
+Text_Pharmacy_InsufficientFunds: ; 0x15ea9
+ ; Huh? That's not enough money.
+ text_jump UnknownText_0x1c4ed8
+ db "@"
+; 0x15eae
+
+Text_Pharmacist_ComeAgain: ; 0x15eae
+ ; All right. See you around.
+ text_jump UnknownText_0x1c4ef6
+ db "@"
+; 0x15eb3
+
+
+SellMenu: ; 15eb3
+ call DisableSpriteUpdates
+ farcall DepositSellInitPackBuffers
+.loop
+ farcall DepositSellPack
+ ld a, [wPackUsedItem]
+ and a
+ jp z, .quit
+ call .TryToSellItem
+ jr .loop
+
+.quit
+ call ReturnToMapWithSpeechTextbox
+ and a
+ ret
+; 15ed3
+
+.Unreferenced_NothingToSell:
+ ld hl, .NothingToSellText
+ call MenuTextBoxBackup
+ and a
+ ret
+; 15edb
+
+.NothingToSellText: ; 0x15edb
+ ; You don't have anything to sell.
+ text_jump UnknownText_0x1c4f12
+ db "@"
+; 0x15ee0
+
+
+.TryToSellItem: ; 15ee0
+ farcall CheckItemMenu
+ ld a, [wItemAttributeParamBuffer]
+ ld hl, .dw
+ rst JumpTable
+ ret
+; 15eee
+
+.dw ; 15eee
+ dw .try_sell
+ dw .cant_buy
+ dw .cant_buy
+ dw .cant_buy
+ dw .try_sell
+ dw .try_sell
+ dw .try_sell
+; 15efc
+
+.cant_buy ; 15efc
+ ret
+; 15efd
+
+
+.try_sell ; 15efd
+ farcall _CheckTossableItem
+ ld a, [wItemAttributeParamBuffer]
+ and a
+ jr z, .okay_to_sell
+ ld hl, TextMart_CantBuyFromYou
+ call PrintText
+ and a
+ ret
+
+.okay_to_sell
+ ld hl, Text_Mart_SellHowMany
+ call PrintText
+ farcall PlaceMoneyAtTopLeftOfTextbox
+ farcall SelectQuantityToSell
+ call ExitMenu
+ jr c, .declined
+ hlcoord 1, 14
+ lb bc, 3, 18
+ call ClearBox
+ ld hl, Text_Mart_ICanPayThisMuch
+ call PrintTextBoxText
+ call YesNoBox
+ jr c, .declined
+ ld de, wMoney
+ ld bc, hMoneyTemp
+ call GiveMoney
+ ld a, [wMartItemID]
+ ld hl, wNumItems
+ call TossItem
+ predef PartyMonItemName
+ hlcoord 1, 14
+ lb bc, 3, 18
+ call ClearBox
+ ld hl, Text_Mart_SoldForAmount
+ call PrintTextBoxText
+ call PlayTransactionSound
+ farcall PlaceMoneyBottomLeft
+ call JoyWaitAorB
+
+.declined
+ call ExitMenu
+ and a
+ ret
+; 15f73
+
+Text_Mart_SellHowMany: ; 0x15f73
+ ; How many?
+ text_jump UnknownText_0x1c4f33
+ db "@"
+; 0x15f78
+
+Text_Mart_ICanPayThisMuch: ; 0x15f78
+ ; I can pay you ¥@ . Is that OK?
+ text_jump UnknownText_0x1c4f3e
+ db "@"
+; 0x15f7d
+
+.UnusedString15f7d: ; 15f7d
+ db "!ダミー!@"
+
+Text_Mart_HowMayIHelpYou: ; 0x15f83
+ ; Welcome! How may I help you?
+ text_jump UnknownText_0x1c4f62
+ db "@"
+; 0x15f88
+
+MenuHeader_BuySell: ; 0x15f88
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 0, 0, 7, 8
+ dw .MenuData
+ db 1 ; default option
+; 0x15f90
+
+.MenuData ; 0x15f90
+ db STATICMENU_CURSOR ; strings
+ db 3 ; items
+ db "BUY@"
+ db "SELL@"
+ db "QUIT@"
+; 0x15f96
+
+Text_Mart_HereYouGo: ; 0x15fa0
+ ; Here you are. Thank you!
+ text_jump UnknownText_0x1c4f80
+ db "@"
+; 0x15fa5
+
+Text_Mart_InsufficientFunds: ; 0x15fa5
+ ; You don't have enough money.
+ text_jump UnknownText_0x1c4f9a
+ db "@"
+; 0x15faa
+
+Text_Mart_BagFull: ; 0x15faa
+ ; You can't carry any more items.
+ text_jump UnknownText_0x1c4fb7
+ db "@"
+; 0x15faf
+
+TextMart_CantBuyFromYou: ; 0x15faf
+ ; Sorry, I can't buy that from you.
+ text_jump UnknownText_0x1c4fd7
+ db "@"
+; 0x15fb4
+
+Text_Mart_ComeAgain: ; 0x15fb4
+ ; Please come again!
+ text_jump UnknownText_0x1c4ff9
+ db "@"
+; 0x15fb9
+
+Text_Mart_AnythingElse: ; 0x15fb9
+ text_jump UnknownText_0x1c500d
+ db "@"
+; 0x15fbe
+
+Text_Mart_SoldForAmount: ; 0x15fbe
+ text_jump UnknownText_0x1c502e
+ db "@"
+; 0x15fc3
+
+PlayTransactionSound: ; 15fc3
+ call WaitSFX
+ ld de, SFX_TRANSACTION
+ call PlaySFX
+ ret
+; 15fcd
+
+MartTextBox: ; 15fcd
+ call MenuTextBox
+ call JoyWaitAorB
+ call ExitMenu
+ ret
+; 15fd7
diff --git a/engine/menu/menu.asm b/engine/menu/menu.asm
new file mode 100755
index 000000000..51de2e1a4
--- /dev/null
+++ b/engine/menu/menu.asm
@@ -0,0 +1,841 @@
+_2DMenu_:: ; 2400e
+ ld hl, CopyMenuData
+ ld a, [wMenuData_2DMenuItemStringsBank]
+ rst FarCall
+
+ call Draw2DMenu
+ call UpdateSprites
+ call ApplyTilemap
+ call Get2DMenuSelection
+ ret
+; 24022
+
+_InterpretBattleMenu:: ; 24022
+ ld hl, CopyMenuData
+ ld a, [wMenuData_2DMenuItemStringsBank]
+ rst FarCall
+
+ call Draw2DMenu
+ farcall MobileTextBorder
+ call UpdateSprites
+ call ApplyTilemap
+ call Get2DMenuSelection
+ ret
+; 2403c
+
+_InterpretMobileMenu:: ; 2403c
+ ld hl, CopyMenuData
+ ld a, [wMenuData_2DMenuItemStringsBank]
+ rst FarCall
+
+ call Draw2DMenu
+ farcall MobileTextBorder
+ call UpdateSprites
+ call ApplyTilemap
+ call Init2DMenuCursorPosition
+ ld hl, w2DMenuFlags1
+ set 7, [hl]
+.loop
+ call DelayFrame
+ farcall Function10032e
+ ld a, [wcd2b]
+ and a
+ jr nz, .quit
+ call MobileMenuJoypad
+ ld a, [wMenuJoypadFilter]
+ and c
+ jr z, .loop
+ call Mobile_GetMenuSelection
+ ret
+
+.quit
+ ld a, [w2DMenuNumCols]
+ ld c, a
+ ld a, [w2DMenuNumRows]
+ call SimpleMultiply
+ ld [wMenuCursorBuffer], a
+ and a
+ ret
+; 24085
+
+
+
+Draw2DMenu: ; 24085
+ xor a
+ ld [hBGMapMode], a
+ call MenuBox
+ call Place2DMenuItemStrings
+ ret
+; 2408f
+
+Get2DMenuSelection: ; 2408f
+ call Init2DMenuCursorPosition
+ call StaticMenuJoypad
+ call MenuClickSound
+Mobile_GetMenuSelection: ; 24098
+ ld a, [wMenuDataFlags]
+ bit 1, a
+ jr z, .skip
+ call GetMenuJoypad
+ bit SELECT_F, a
+ jr nz, .quit1
+
+.skip
+ ld a, [wMenuDataFlags]
+ bit 0, a
+ jr nz, .skip2
+ call GetMenuJoypad
+ bit B_BUTTON_F, a
+ jr nz, .quit2
+
+.skip2
+ ld a, [w2DMenuNumCols]
+ ld c, a
+ ld a, [wMenuCursorY]
+ dec a
+ call SimpleMultiply
+ ld c, a
+ ld a, [wMenuCursorX]
+ add c
+ ld [wMenuCursorBuffer], a
+ and a
+ ret
+
+.quit1
+ scf
+ ret
+
+.quit2
+ scf
+ ret
+; 240cd
+
+Get2DMenuNumberOfColumns: ; 240cd
+ ld a, [wMenuData_2DMenuDimensions]
+ and $f
+ ret
+; 240d3
+
+Get2DMenuNumberOfRows: ; 240d3
+ ld a, [wMenuData_2DMenuDimensions]
+ swap a
+ and $f
+ ret
+; 240db
+
+Place2DMenuItemStrings: ; 240db
+ ld hl, wMenuData_2DMenuItemStringsAddr
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ call GetMenuTextStartCoord
+ call Coord2Tile
+ call Get2DMenuNumberOfRows
+ ld b, a
+.row
+ push bc
+ push hl
+ call Get2DMenuNumberOfColumns
+ ld c, a
+.col
+ push bc
+ ld a, [wMenuData_2DMenuItemStringsBank]
+ call Place2DMenuItemName
+ inc de
+ ld a, [wMenuData_2DMenuSpacing]
+ ld c, a
+ ld b, 0
+ add hl, bc
+ pop bc
+ dec c
+ jr nz, .col
+ pop hl
+ ld bc, 2 * SCREEN_WIDTH
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .row
+ ld hl, wMenuData_2DMenuFunctionAddr
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ or h
+ ret z
+ ld a, [wMenuData_2DMenuFunctionBank]
+ rst FarCall
+ ret
+; 2411a
+
+
+Init2DMenuCursorPosition: ; 2411a (9:411a)
+ call GetMenuTextStartCoord
+ ld a, b
+ ld [w2DMenuCursorInitY], a
+ dec c
+ ld a, c
+ ld [w2DMenuCursorInitX], a
+ call Get2DMenuNumberOfRows
+ ld [w2DMenuNumRows], a
+ call Get2DMenuNumberOfColumns
+ ld [w2DMenuNumCols], a
+ call .InitFlags_a
+ call .InitFlags_b
+ call .InitFlags_c
+ ld a, [w2DMenuNumCols]
+ ld e, a
+ ld a, [wMenuCursorBuffer]
+ ld b, a
+ xor a
+ ld d, 0
+.loop
+ inc d
+ add e
+ cp b
+ jr c, .loop
+ sub e
+ ld c, a
+ ld a, b
+ sub c
+ and a
+ jr z, .reset1
+ cp e
+ jr z, .okay1
+ jr c, .okay1
+.reset1
+ ld a, 1
+.okay1
+ ld [wMenuCursorX], a
+ ld a, [w2DMenuNumRows]
+ ld e, a
+ ld a, d
+ and a
+ jr z, .reset2
+ cp e
+ jr z, .okay2
+ jr c, .okay2
+.reset2
+ ld a, 1
+.okay2
+ ld [wMenuCursorY], a
+ xor a
+ ld [wCursorOffCharacter], a
+ ld [wCursorCurrentTile], a
+ ld [wCursorCurrentTile + 1], a
+ ret
+; 24179
+
+.InitFlags_a: ; 24179
+ xor a
+ ld hl, w2DMenuFlags1
+ ld [hli], a
+ ld [hld], a
+ ld a, [wMenuDataFlags]
+ bit 5, a
+ ret z
+ set 5, [hl]
+ set 4, [hl]
+ ret
+; 2418a
+
+.InitFlags_b: ; 2418a
+ ld a, [wMenuData_2DMenuSpacing]
+ or $20
+ ld [w2DMenuCursorOffsets], a
+ ret
+; 24193
+
+.InitFlags_c: ; 24193
+ ld hl, wMenuDataFlags
+ ld a, A_BUTTON
+ bit 0, [hl]
+ jr nz, .skip
+ or B_BUTTON
+.skip
+ bit 1, [hl]
+ jr z, .skip2
+ or SELECT
+.skip2
+ ld [wMenuJoypadFilter], a
+ ret
+; 241a8
+
+
+_StaticMenuJoypad:: ; 241a8
+ call Place2DMenuCursor
+_ScrollingMenuJoypad:: ; 241ab
+ ld hl, w2DMenuFlags2
+ res 7, [hl]
+ ld a, [hBGMapMode]
+ push af
+ call MenuJoypadLoop
+ pop af
+ ld [hBGMapMode], a
+ ret
+; 241ba
+
+MobileMenuJoypad: ; 241ba
+ ld hl, w2DMenuFlags2
+ res 7, [hl]
+ ld a, [hBGMapMode]
+ push af
+ call Move2DMenuCursor
+ call Do2DMenuRTCJoypad
+ jr nc, .skip_joypad
+ call _2DMenuInterpretJoypad
+.skip_joypad
+ pop af
+ ld [hBGMapMode], a
+ call GetMenuJoypad
+ ld c, a
+ ret
+; 241d5
+
+
+Unreferenced_Function241d5: ; 241d5
+ call Place2DMenuCursor
+.loop
+ call Move2DMenuCursor
+ call HDMATransferTileMapToWRAMBank3 ; BUG: This function is in another bank.
+ ; Pointer in current bank (9) is bogus.
+ call .loop2
+ jr nc, .done
+ call _2DMenuInterpretJoypad
+ jr c, .done
+ ld a, [w2DMenuFlags1]
+ bit 7, a
+ jr nz, .done
+ call GetMenuJoypad
+ ld c, a
+ ld a, [wMenuJoypadFilter]
+ and c
+ jr z, .loop
+
+.done
+ ret
+
+.loop2
+ call Menu_WasButtonPressed
+ ret c
+ ld c, 1
+ ld b, 3
+ call AdvanceMobileInactivityTimerAndCheckExpired ; BUG: This function is in another bank.
+ ; Pointer in current bank (9) is bogus.
+ ret c
+ farcall Function100337
+ ret c
+ ld a, [w2DMenuFlags1]
+ bit 7, a
+ jr z, .loop2
+ and a
+ ret
+; 24216
+
+
+MenuJoypadLoop: ; 24216
+.loop
+ call Move2DMenuCursor
+ call .BGMap_OAM
+ call Do2DMenuRTCJoypad
+ jr nc, .done
+ call _2DMenuInterpretJoypad
+ jr c, .done
+ ld a, [w2DMenuFlags1]
+ bit 7, a
+ jr nz, .done
+ call GetMenuJoypad
+ ld b, a
+ ld a, [wMenuJoypadFilter]
+ and b
+ jr z, .loop
+
+.done
+ ret
+; 24238
+
+.BGMap_OAM: ; 24238
+ ld a, [hOAMUpdate]
+ push af
+ ld a, $1
+ ld [hOAMUpdate], a
+ call WaitBGMap
+ pop af
+ ld [hOAMUpdate], a
+ xor a
+ ld [hBGMapMode], a
+ ret
+; 24249
+
+Do2DMenuRTCJoypad: ; 24249
+.loopRTC
+ call RTC
+ call Menu_WasButtonPressed
+ ret c
+ ld a, [w2DMenuFlags1]
+ bit 7, a
+ jr z, .loopRTC
+ and a
+ ret
+; 24259
+
+Menu_WasButtonPressed: ; 24259
+ ld a, [w2DMenuFlags1]
+ bit 6, a
+ jr z, .skip_to_joypad
+ callfar PlaySpriteAnimationsAndDelayFrame
+
+.skip_to_joypad
+ call JoyTextDelay
+ call GetMenuJoypad
+ and a
+ ret z
+ scf
+ ret
+; 24270
+
+_2DMenuInterpretJoypad: ; 24270
+ call GetMenuJoypad
+ bit A_BUTTON_F, a
+ jp nz, .a_b_start_select
+ bit B_BUTTON_F, a
+ jp nz, .a_b_start_select
+ bit SELECT_F, a
+ jp nz, .a_b_start_select
+ bit START_F, a
+ jp nz, .a_b_start_select
+ bit D_RIGHT_F, a
+ jr nz, .d_right
+ bit D_LEFT_F, a
+ jr nz, .d_left
+ bit D_UP_F, a
+ jr nz, .d_up
+ bit D_DOWN_F, a
+ jr nz, .d_down
+ and a
+ ret
+
+.set_bit_7 ; 24299
+ ld hl, w2DMenuFlags2
+ set 7, [hl]
+ scf
+ ret
+
+.d_down
+ ld hl, wMenuCursorY
+ ld a, [w2DMenuNumRows]
+ cp [hl]
+ jr z, .check_wrap_around_down
+ inc [hl]
+ xor a
+ ret
+
+.check_wrap_around_down
+ ld a, [w2DMenuFlags1]
+ bit 5, a
+ jr nz, .wrap_around_down
+ bit 3, a
+ jp nz, .set_bit_7
+ xor a
+ ret
+
+.wrap_around_down
+ ld [hl], $1
+ xor a
+ ret
+
+.d_up
+ ld hl, wMenuCursorY
+ ld a, [hl]
+ dec a
+ jr z, .check_wrap_around_up
+ ld [hl], a
+ xor a
+ ret
+
+.check_wrap_around_up
+ ld a, [w2DMenuFlags1]
+ bit 5, a
+ jr nz, .wrap_around_up
+ bit 2, a
+ jp nz, .set_bit_7
+ xor a
+ ret
+
+.wrap_around_up
+ ld a, [w2DMenuNumRows]
+ ld [hl], a
+ xor a
+ ret
+
+.d_left
+ ld hl, wMenuCursorX
+ ld a, [hl]
+ dec a
+ jr z, .check_wrap_around_left
+ ld [hl], a
+ xor a
+ ret
+
+.check_wrap_around_left
+ ld a, [w2DMenuFlags1]
+ bit 4, a
+ jr nz, .wrap_around_left
+ bit 1, a
+ jp nz, .set_bit_7
+ xor a
+ ret
+
+.wrap_around_left
+ ld a, [w2DMenuNumCols]
+ ld [hl], a
+ xor a
+ ret
+
+.d_right
+ ld hl, wMenuCursorX
+ ld a, [w2DMenuNumCols]
+ cp [hl]
+ jr z, .check_wrap_around_right
+ inc [hl]
+ xor a
+ ret
+
+.check_wrap_around_right
+ ld a, [w2DMenuFlags1]
+ bit 4, a
+ jr nz, .wrap_around_right
+ bit 0, a
+ jp nz, .set_bit_7
+ xor a
+ ret
+
+.wrap_around_right
+ ld [hl], $1
+ xor a
+ ret
+; 24318
+
+.a_b_start_select ; 24318
+ xor a
+ ret
+; 2431a
+
+Move2DMenuCursor: ; 2431a
+ ld hl, wCursorCurrentTile
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [hl]
+ cp "▶"
+ jr nz, Place2DMenuCursor
+ ld a, [wCursorOffCharacter]
+ ld [hl], a
+Place2DMenuCursor: ; 24329
+ ld a, [w2DMenuCursorInitY]
+ ld b, a
+ ld a, [w2DMenuCursorInitX]
+ ld c, a
+ call Coord2Tile
+ ld a, [w2DMenuCursorOffsets]
+ swap a
+ and $f
+ ld c, a
+ ld a, [wMenuCursorY]
+ ld b, a
+ xor a
+ dec b
+ jr z, .got_row
+.row_loop
+ add c
+ dec b
+ jr nz, .row_loop
+
+.got_row
+ ld c, SCREEN_WIDTH
+ call AddNTimes
+ ld a, [w2DMenuCursorOffsets]
+ and $f
+ ld c, a
+ ld a, [wMenuCursorX]
+ ld b, a
+ xor a
+ dec b
+ jr z, .got_col
+.col_loop
+ add c
+ dec b
+ jr nz, .col_loop
+
+.got_col
+ ld c, a
+ add hl, bc
+ ld a, [hl]
+ cp "▶"
+ jr z, .cursor_on
+ ld [wCursorOffCharacter], a
+ ld [hl], "▶"
+
+.cursor_on
+ ld a, l
+ ld [wCursorCurrentTile], a
+ ld a, h
+ ld [wCursorCurrentTile + 1], a
+ ret
+; 24374
+
+_PushWindow:: ; 24374
+ ld a, [rSVBK]
+ push af
+ ld a, BANK(wWindowStack)
+ ld [rSVBK], a
+
+ ld hl, wWindowStackPointer
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ push de
+
+ ld b, $10
+ ld hl, wMenuFlags
+.loop
+ ld a, [hli]
+ ld [de], a
+ dec de
+ dec b
+ jr nz, .loop
+
+; If bit 6 or 7 of the menu flags is set, set bit 0 of the address
+; at 7:[wWindowStackPointer], and draw the menu using the coordinates from the header.
+; Otherwise, reset bit 0 of 7:[wWindowStackPointer].
+ ld a, [wMenuFlags]
+ bit 6, a
+ jr nz, .bit_6
+ bit 7, a
+ jr z, .not_bit_7
+
+.bit_6
+ ld hl, wWindowStackPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ set 0, [hl]
+ call MenuBoxCoord2Tile
+ call .copy
+ call MenuBoxCoord2Attr
+ call .copy
+ jr .done
+
+.not_bit_7
+ pop hl ; last-pushed register was de
+ push hl
+ ld a, [hld]
+ ld l, [hl]
+ ld h, a
+ res 0, [hl]
+
+.done
+ pop hl
+ call .ret ; empty function
+ ld a, h
+ ld [de], a
+ dec de
+ ld a, l
+ ld [de], a
+ dec de
+ ld hl, wWindowStackPointer
+ ld [hl], e
+ inc hl
+ ld [hl], d
+
+ pop af
+ ld [rSVBK], a
+ ld hl, wWindowStackSize
+ inc [hl]
+ ret
+; 243cd
+
+.copy ; 243cd
+ call GetMenuBoxDims
+ inc b
+ inc c
+ call .ret ; empty function
+
+.row
+ push bc
+ push hl
+
+.col
+ ld a, [hli]
+ ld [de], a
+ dec de
+ dec c
+ jr nz, .col
+
+ pop hl
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .row
+
+ ret
+; 243e7
+
+.ret ; 243e7
+ ret
+; 243e8
+
+_ExitMenu:: ; 243e8
+ xor a
+ ld [hBGMapMode], a
+
+ ld a, [rSVBK]
+ push af
+ ld a, BANK(wWindowStack)
+ ld [rSVBK], a
+
+ call GetWindowStackTop
+ ld a, l
+ or h
+ jp z, Error_Cant_ExitMenu
+ ld a, l
+ ld [wWindowStackPointer], a
+ ld a, h
+ ld [wWindowStackPointer + 1], a
+ call PopWindow
+ ld a, [wMenuFlags]
+ bit 0, a
+ jr z, .loop
+ ld d, h
+ ld e, l
+ call RestoreTileBackup
+
+.loop
+ call GetWindowStackTop
+ ld a, h
+ or l
+ jr z, .done
+ call PopWindow
+
+.done
+ pop af
+ ld [rSVBK], a
+ ld hl, wWindowStackSize
+ dec [hl]
+ ret
+; 24423
+
+Unreferenced_Function24423: ; 24423
+ ld a, [wVramState]
+ bit 0, a
+ ret z
+ xor a ; sScratch
+ call GetSRAMBank
+ hlcoord 0, 0
+ ld de, sScratch
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ call CopyBytes
+ call CloseSRAM
+ call OverworldTextModeSwitch
+ xor a ; sScratch
+ call GetSRAMBank
+ ld hl, sScratch
+ decoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+.loop
+ ld a, [hl]
+ cp $61
+ jr c, .next
+ ld [de], a
+.next
+ inc hl
+ inc de
+ dec bc
+ ld a, c
+ or b
+ jr nz, .loop
+ call CloseSRAM
+ ret
+; 2445d
+
+Error_Cant_ExitMenu: ; 2445d
+ ld hl, .Text_NoWindowsAvailableForPopping
+ call PrintText
+ call WaitBGMap
+.InfiniteLoop:
+ jr .InfiniteLoop
+; 24468
+
+.Text_NoWindowsAvailableForPopping: ; 24468
+ text_jump UnknownText_0x1c46b7
+ db "@"
+; 2446d
+
+_InitVerticalMenuCursor:: ; 2446d
+ ld a, [wMenuDataFlags]
+ ld b, a
+ ld hl, w2DMenuCursorInitY
+ ld a, [wMenuBorderTopCoord]
+ inc a
+ bit 6, b
+ jr nz, .skip_offset
+ inc a
+.skip_offset
+ ld [hli], a
+; w2DMenuCursorInitX
+ ld a, [wMenuBorderLeftCoord]
+ inc a
+ ld [hli], a
+; w2DMenuNumRows
+ ld a, [wMenuDataItems]
+ ld [hli], a
+; w2DMenuNumCols
+ ld a, 1
+ ld [hli], a
+; w2DMenuFlags1
+ ld [hl], $0
+ bit 5, b
+ jr z, .skip_bit_5
+ set 5, [hl]
+.skip_bit_5
+ ld a, [wMenuFlags]
+ bit 4, a
+ jr z, .skip_bit_6
+ set 6, [hl]
+.skip_bit_6
+ inc hl
+; w2DMenuFlags2
+ xor a
+ ld [hli], a
+; w2DMenuCursorOffsets
+ ln a, 2, 0
+ ld [hli], a
+; wMenuJoypadFilter
+ ld a, A_BUTTON
+ bit 0, b
+ jr nz, .skip_bit_1
+ add B_BUTTON
+.skip_bit_1
+ ld [hli], a
+; wMenuCursorY
+ ld a, [wMenuCursorBuffer]
+ and a
+ jr z, .load_at_the_top
+ ld c, a
+ ld a, [wMenuDataItems]
+ cp c
+ jr nc, .load_position
+.load_at_the_top
+ ld c, 1
+.load_position
+ ld [hl], c
+ inc hl
+; wMenuCursorX
+ ld a, 1
+ ld [hli], a
+; wCursorOffCharacter, wCursorCurrentTile
+ xor a
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ret
+; 244c3
diff --git a/engine/menu/menu_2.asm b/engine/menu/menu_2.asm
new file mode 100644
index 000000000..16cce5348
--- /dev/null
+++ b/engine/menu/menu_2.asm
@@ -0,0 +1,253 @@
+PlaceMenuItemName: ; 0x24ab4
+ push de
+ ld a, [wMenuSelection]
+ ld [wNamedObjectIndexBuffer], a
+ call GetItemName
+ pop hl
+ call PlaceString
+ ret
+
+PlaceMenuItemQuantity: ; 0x24ac3
+ push de
+ ld a, [wMenuSelection]
+ ld [wCurItem], a
+ farcall _CheckTossableItem
+ ld a, [wItemAttributeParamBuffer]
+ pop hl
+ and a
+ jr nz, .done
+ ld de, $15
+ add hl, de
+ ld [hl], "×"
+ inc hl
+ ld de, wMenuSelectionQuantity
+ lb bc, 1, 2
+ call PrintNum
+
+.done
+ ret
+
+PlaceMoneyTopRight: ; 24ae8
+ ld hl, MenuHeader_0x24b15
+ call CopyMenuHeader
+ jr PlaceMoneyTextBox
+
+PlaceMoneyBottomLeft: ; 24af0
+ ld hl, MenuHeader_0x24b1d
+ call CopyMenuHeader
+ jr PlaceMoneyTextBox
+
+PlaceMoneyAtTopLeftOfTextbox: ; 24af8
+ ld hl, MenuHeader_0x24b15
+ lb de, 0, 11
+ call OffsetMenuHeader
+
+PlaceMoneyTextBox: ; 24b01
+ call MenuBox
+ call MenuBoxCoord2Tile
+ ld de, SCREEN_WIDTH + 1
+ add hl, de
+ ld de, wMoney
+ lb bc, PRINTNUM_MONEY | 3, 6
+ call PrintNum
+ ret
+
+MenuHeader_0x24b15: ; 0x24b15
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 11, 0, SCREEN_WIDTH - 1, 2
+ dw NULL
+ db 1 ; default option
+
+MenuHeader_0x24b1d: ; 0x24b1d
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 0, 11, 8, 13
+ dw NULL
+ db 1 ; default option
+
+DisplayCoinCaseBalance: ; 24b25
+ ; Place a text box of size 1x7 at 11, 0.
+ hlcoord 11, 0
+ ld b, 1
+ ld c, 7
+ call TextBox
+ hlcoord 12, 0
+ ld de, CoinString
+ call PlaceString
+ hlcoord 17, 1
+ ld de, ShowMoney_TerminatorString
+ call PlaceString
+ ld de, wCoins
+ lb bc, 2, 4
+ hlcoord 13, 1
+ call PrintNum
+ ret
+
+DisplayMoneyAndCoinBalance: ; 24b4e
+ hlcoord 5, 0
+ ld b, 3
+ ld c, 13
+ call TextBox
+ hlcoord 6, 1
+ ld de, MoneyString
+ call PlaceString
+ hlcoord 12, 1
+ ld de, wMoney
+ lb bc, PRINTNUM_MONEY | 3, 6
+ call PrintNum
+ hlcoord 6, 3
+ ld de, CoinString
+ call PlaceString
+ hlcoord 15, 3
+ ld de, wCoins
+ lb bc, 2, 4
+ call PrintNum
+ ret
+
+MoneyString: ; 24b83
+ db "MONEY@"
+CoinString: ; 24b89
+ db "COIN@"
+ShowMoney_TerminatorString: ; 24b8e
+ db "@"
+
+Unreferenced_Function24b8f: ; 24b8f
+; related to safari?
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ hlcoord 0, 0
+ ld b, 3
+ ld c, 7
+ call TextBox
+ hlcoord 1, 1
+ ld de, wSafariTimeRemaining
+ lb bc, 2, 3
+ call PrintNum
+ hlcoord 4, 1
+ ld de, .slash_500
+ call PlaceString
+ hlcoord 1, 3
+ ld de, .booru_ko
+ call PlaceString
+ hlcoord 5, 3
+ ld de, wSafariBallsRemaining
+ lb bc, 1, 2
+ call PrintNum
+ pop af
+ ld [wOptions], a
+ ret
+
+.slash_500 ; 24bcf
+ db "/500@"
+.booru_ko ; 24bd4
+ db "ボール   こ@"
+
+StartMenu_DrawBugContestStatusBox: ; 24bdc
+ hlcoord 0, 0
+ ld b, 5
+ ld c, 17
+ call TextBox
+ ret
+
+StartMenu_PrintBugContestStatus: ; 24be7
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ call StartMenu_DrawBugContestStatusBox
+ hlcoord 1, 5
+ ld de, .Balls_EN
+ call PlaceString
+ hlcoord 8, 5
+ ld de, wParkBallsRemaining
+ lb bc, PRINTNUM_RIGHTALIGN | 1, 2
+ call PrintNum
+ hlcoord 1, 1
+ ld de, .CAUGHT
+ call PlaceString
+ ld a, [wContestMon]
+ and a
+ ld de, .None
+ jr z, .no_contest_mon
+ ld [wd265], a
+ call GetPokemonName
+
+.no_contest_mon
+ hlcoord 8, 1
+ call PlaceString
+ ld a, [wContestMon]
+ and a
+ jr z, .skip_level
+ hlcoord 1, 3
+ ld de, .LEVEL
+ call PlaceString
+ ld a, [wContestMonLevel]
+ ld h, b
+ ld l, c
+ inc hl
+ ld c, 3
+ call Print8BitNumRightAlign
+
+.skip_level
+ pop af
+ ld [wOptions], a
+ ret
+
+.Balls_JP: ; 24c43
+ db "ボール   こ@"
+.CAUGHT: ; 24c4b
+ db "CAUGHT@"
+.Balls_EN: ; 24c52
+ db "BALLS:@"
+.None: ; 24c59
+ db "None@"
+.LEVEL: ; 24c5e
+ db "LEVEL@"
+
+FindApricornsInBag: ; 24c64
+; Checks the bag for Apricorns.
+ ld hl, wBuffer1
+ xor a
+ ld [hli], a
+ dec a
+ ld bc, 10
+ call ByteFill
+
+ ld hl, ApricornBalls
+.loop
+ ld a, [hl]
+ cp -1
+ jr z, .done
+ push hl
+ ld [wCurItem], a
+ ld hl, wNumItems
+ call CheckItem
+ pop hl
+ jr nc, .nope
+ ld a, [hl]
+ call .addtobuffer
+.nope
+ inc hl
+ inc hl
+ jr .loop
+
+.done
+ ld a, [wBuffer1]
+ and a
+ ret nz
+ scf
+ ret
+
+.addtobuffer ; 24c94
+ push hl
+ ld hl, wBuffer1
+ inc [hl]
+ ld e, [hl]
+ ld d, 0
+ add hl, de
+ ld [hl], a
+ pop hl
+ ret
+
+INCLUDE "data/items/apricorn_balls.asm"
diff --git a/engine/menu/mon_menu.asm b/engine/menu/mon_menu.asm
new file mode 100755
index 000000000..088b1b1a3
--- /dev/null
+++ b/engine/menu/mon_menu.asm
@@ -0,0 +1,304 @@
+INCLUDE "data/mon_menu.asm"
+
+MonSubmenu: ; 24d19
+ xor a
+ ld [hBGMapMode], a
+ call GetMonSubmenuItems
+ farcall FreezeMonIcons
+ ld hl, .MenuHeader
+ call LoadMenuHeader
+ call .GetTopCoord
+ call PopulateMonMenu
+
+ ld a, 1
+ ld [hBGMapMode], a
+ call MonMenuLoop
+ ld [wMenuSelection], a
+
+ call ExitMenu
+ ret
+; 24d3f
+
+.MenuHeader: ; 24d3f
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 6, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+ dw 0
+ db 1 ; default option
+; 24d47
+
+.GetTopCoord: ; 24d47
+; TopCoord = 1 + BottomCoord - 2 * (NumSubmenuItems + 1)
+ ld a, [wBuffer1]
+ inc a
+ add a
+ ld b, a
+ ld a, [wMenuBorderBottomCoord]
+ sub b
+ inc a
+ ld [wMenuBorderTopCoord], a
+ call MenuBox
+ ret
+; 24d59
+
+MonMenuLoop: ; 24d59
+.loop
+ ld a, MENU_UNUSED_3 | MENU_BACKUP_TILES_2 ; flags
+ ld [wMenuDataFlags], a
+ ld a, [wBuffer1] ; items
+ ld [wMenuDataItems], a
+ call InitVerticalMenuCursor
+ ld hl, w2DMenuFlags1
+ set 6, [hl]
+ call StaticMenuJoypad
+ ld de, SFX_READ_TEXT_2
+ call PlaySFX
+ ld a, [hJoyPressed]
+ bit A_BUTTON_F, a
+ jr nz, .select
+ bit B_BUTTON_F, a
+ jr nz, .cancel
+ jr .loop
+
+.cancel
+ ld a, MONMENUITEM_CANCEL
+ ret
+
+.select
+ ld a, [wMenuCursorY]
+ dec a
+ ld c, a
+ ld b, 0
+ ld hl, wBuffer2
+ add hl, bc
+ ld a, [hl]
+ ret
+; 24d91
+
+PopulateMonMenu: ; 24d91
+ call MenuBoxCoord2Tile
+ ld bc, 2 * SCREEN_WIDTH + 2
+ add hl, bc
+ ld de, wBuffer2
+.loop
+ ld a, [de]
+ inc de
+ cp -1
+ ret z
+ push de
+ push hl
+ call GetMonMenuString
+ pop hl
+ call PlaceString
+ ld bc, 2 * SCREEN_WIDTH
+ add hl, bc
+ pop de
+ jr .loop
+; 24db0
+
+GetMonMenuString: ; 24db0
+ ld hl, MonMenuOptions + 1
+ ld de, 3
+ call IsInArray
+ dec hl
+ ld a, [hli]
+ cp MONMENU_MENUOPTION
+ jr z, .NotMove
+ inc hl
+ ld a, [hl]
+ ld [wd265], a
+ call GetMoveName
+ ret
+
+.NotMove:
+ inc hl
+ ld a, [hl]
+ dec a
+ ld hl, MonMenuOptionStrings
+ call GetNthString
+ ld d, h
+ ld e, l
+ ret
+; 24dd4
+
+GetMonSubmenuItems: ; 24dd4
+ call ResetMonSubmenu
+ ld a, [wCurPartySpecies]
+ cp EGG
+ jr z, .egg
+ ld a, [wLinkMode]
+ and a
+ jr nz, .skip_moves
+ ld a, MON_MOVES
+ call GetPartyParamLocation
+ ld d, h
+ ld e, l
+ ld c, NUM_MOVES
+.loop
+ push bc
+ push de
+ ld a, [de]
+ and a
+ jr z, .next
+ push hl
+ call IsFieldMove
+ pop hl
+ jr nc, .next
+ call AddMonMenuItem
+
+.next
+ pop de
+ inc de
+ pop bc
+ dec c
+ jr nz, .loop
+
+.skip_moves
+ ld a, MONMENUITEM_STATS
+ call AddMonMenuItem
+ ld a, MONMENUITEM_SWITCH
+ call AddMonMenuItem
+ ld a, MONMENUITEM_MOVE
+ call AddMonMenuItem
+ ld a, [wLinkMode]
+ and a
+ jr nz, .skip2
+ push hl
+ ld a, MON_ITEM
+ call GetPartyParamLocation
+ ld d, [hl]
+ farcall ItemIsMail
+ pop hl
+ ld a, MONMENUITEM_MAIL
+ jr c, .ok
+ ld a, MONMENUITEM_ITEM
+
+.ok
+ call AddMonMenuItem
+
+.skip2
+ ld a, [wBuffer1]
+ cp NUM_MONMENU_ITEMS
+ jr z, .ok2
+ ld a, MONMENUITEM_CANCEL
+ call AddMonMenuItem
+
+.ok2
+ call TerminateMonSubmenu
+ ret
+
+.egg
+ ld a, MONMENUITEM_STATS
+ call AddMonMenuItem
+ ld a, MONMENUITEM_SWITCH
+ call AddMonMenuItem
+ ld a, MONMENUITEM_CANCEL
+ call AddMonMenuItem
+ call TerminateMonSubmenu
+ ret
+; 24e52
+
+IsFieldMove: ; 24e52
+ ld b, a
+ ld hl, MonMenuOptions
+.next
+ ld a, [hli]
+ cp -1
+ jr z, .nope
+ cp MONMENU_MENUOPTION
+ jr z, .nope
+ ld d, [hl]
+ inc hl
+ ld a, [hli]
+ cp b
+ jr nz, .next
+ ld a, d
+ scf
+
+.nope
+ ret
+; 24e68
+
+ResetMonSubmenu: ; 24e68
+ xor a
+ ld [wBuffer1], a
+ ld hl, wBuffer2
+ ld bc, NUM_MONMENU_ITEMS + 1
+ call ByteFill
+ ret
+; 24e76
+
+TerminateMonSubmenu: ; 24e76
+ ld a, [wBuffer1]
+ ld e, a
+ ld d, 0
+ ld hl, wBuffer2
+ add hl, de
+ ld [hl], -1
+ ret
+; 24e83
+
+AddMonMenuItem: ; 24e83
+ push hl
+ push de
+ push af
+ ld a, [wBuffer1]
+ ld e, a
+ inc a
+ ld [wBuffer1], a
+ ld d, 0
+ ld hl, wBuffer2
+ add hl, de
+ pop af
+ ld [hl], a
+ pop de
+ pop hl
+ ret
+; 24e99
+
+BattleMonMenu: ; 24e99
+ ld hl, MenuHeader_0x24ed4
+ call CopyMenuHeader
+ xor a
+ ld [hBGMapMode], a
+ call MenuBox
+ call UpdateSprites
+ call PlaceVerticalMenuItems
+ call WaitBGMap
+ call CopyMenuData
+ ld a, [wMenuDataFlags]
+ bit 7, a
+ jr z, .set_carry
+ call InitVerticalMenuCursor
+ ld hl, w2DMenuFlags1
+ set 6, [hl]
+ call StaticMenuJoypad
+ ld de, SFX_READ_TEXT_2
+ call PlaySFX
+ ld a, [hJoyPressed]
+ bit B_BUTTON_F, a
+ jr z, .clear_carry
+ ret z
+
+.set_carry
+ scf
+ ret
+
+.clear_carry
+ and a
+ ret
+; 24ed4
+
+MenuHeader_0x24ed4: ; 24ed4
+ db 0 ; flags
+ menu_coords 11, 11, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+ dw MenuData_0x24edc
+ db 1 ; default option
+; 24edc
+
+MenuData_0x24edc: ; 24edc
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 3 ; items
+ db "SWITCH@"
+ db "STATS@"
+ db "CANCEL@"
+; 24ef2
diff --git a/engine/menu/naming_screen.asm b/engine/menu/naming_screen.asm
new file mode 100755
index 000000000..a958e10eb
--- /dev/null
+++ b/engine/menu/naming_screen.asm
@@ -0,0 +1,1467 @@
+NAMINGSCREEN_CURSOR EQU $7e
+
+NAMINGSCREEN_BORDER EQUS "\"■\"" ; $60
+NAMINGSCREEN_MIDDLELINE EQUS "\"→\"" ; $eb
+NAMINGSCREEN_UNDERLINE EQUS "\"<DOT>\"" ; $f2
+
+_NamingScreen: ; 0x116b7
+ call DisableSpriteUpdates
+ call NamingScreen
+ call ReturnToMapWithSpeechTextbox
+ ret
+
+; 0x116c1
+
+NamingScreen: ; 116c1
+ ld hl, wNamingScreenDestinationPointer
+ ld [hl], e
+ inc hl
+ ld [hl], d
+ ld hl, wNamingScreenType
+ ld [hl], b
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ ld a, [hMapAnims]
+ push af
+ xor a
+ ld [hMapAnims], a
+ ld a, [hInMenu]
+ push af
+ ld a, $1
+ ld [hInMenu], a
+ call .SetUpNamingScreen
+ call DelayFrame
+.loop
+ call NamingScreenJoypadLoop
+ jr nc, .loop
+ pop af
+ ld [hInMenu], a
+ pop af
+ ld [hMapAnims], a
+ pop af
+ ld [wOptions], a
+ call ClearJoypad
+ ret
+
+; 116f8
+
+.SetUpNamingScreen: ; 116f8
+ call ClearBGPalettes
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ call DisableLCD
+ call LoadNamingScreenGFX
+ call NamingScreen_InitText
+ ld a, LCDC_DEFAULT
+ ld [rLCDC], a
+ call .GetNamingScreenSetup
+ call WaitBGMap
+ call WaitTop
+ call SetPalettes
+ call NamingScreen_InitNameEntry
+ ret
+
+; 1171d
+
+.GetNamingScreenSetup: ; 1171d
+ ld a, [wNamingScreenType]
+ and 7
+ ld e, a
+ ld d, 0
+ ld hl, .Jumptable
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+; 1172e
+
+.Jumptable: ; 1172e (4:572e)
+ dw .Pokemon
+ dw .Player
+ dw .Rival
+ dw .Mom
+ dw .Box
+ dw .Tomodachi
+ dw .Pokemon
+ dw .Pokemon
+
+.Pokemon: ; 1173e (4:573e)
+ ld a, [wCurPartySpecies]
+ ld [wd265], a
+ ld hl, LoadMenuMonIcon
+ ld a, BANK(LoadMenuMonIcon)
+ ld e, $1
+ rst FarCall ; ; indirect jump to LoadMenuMonIcon (8e83f (23:683f))
+ ld a, [wCurPartySpecies]
+ ld [wd265], a
+ call GetPokemonName
+ hlcoord 5, 2
+ call PlaceString
+ ld l, c
+ ld h, b
+ ld de, .NicknameStrings
+ call PlaceString
+ inc de
+ hlcoord 5, 4
+ call PlaceString
+ farcall GetGender
+ jr c, .genderless
+ ld a, "♂"
+ jr nz, .place_gender
+ ld a, "♀"
+.place_gender
+ hlcoord 1, 2
+ ld [hl], a
+.genderless
+ call .StoreMonIconParams
+ ret
+
+; 11780 (4:5780)
+
+.NicknameStrings: ; 11780
+ db "'S@"
+ db "NICKNAME?@"
+
+; 1178d
+
+.Player: ; 1178d (4:578d)
+ farcall GetPlayerIcon
+ call .LoadSprite
+ hlcoord 5, 2
+ ld de, .PlayerNameString
+ call PlaceString
+ call .StoreSpriteIconParams
+ ret
+
+; 117a3 (4:57a3)
+
+.PlayerNameString: ; 117a3
+ db "YOUR NAME?@"
+
+; 117ae
+
+.Rival: ; 117ae (4:57ae)
+ ld de, SilverSpriteGFX
+ ld b, BANK(SilverSpriteGFX)
+ call .LoadSprite
+ hlcoord 5, 2
+ ld de, .RivalNameString
+ call PlaceString
+ call .StoreSpriteIconParams
+ ret
+
+; 117c3 (4:57c3)
+
+.RivalNameString: ; 117c3
+ db "RIVAL'S NAME?@"
+
+; 117d1
+
+.Mom: ; 117d1 (4:57d1)
+ ld de, MomSpriteGFX
+ ld b, BANK(MomSpriteGFX)
+ call .LoadSprite
+ hlcoord 5, 2
+ ld de, .MomNameString
+ call PlaceString
+ call .StoreSpriteIconParams
+ ret
+
+; 117e6 (4:57e6)
+
+.MomNameString: ; 117e6
+ db "MOTHER'S NAME?@"
+
+; 117f5
+
+.Box: ; 117f5 (4:57f5)
+ ld de, PokeBallSpriteGFX
+ ld hl, vTiles0 tile $00
+ lb bc, BANK(PokeBallSpriteGFX), 4
+ call Request2bpp
+ xor a
+ ld hl, wSpriteAnimDict
+ ld [hli], a
+ ld [hl], a
+ depixel 4, 4, 4, 0
+ ld a, SPRITE_ANIM_INDEX_RED_WALK
+ call _InitSpriteAnimStruct
+ ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+ add hl, bc
+ ld [hl], $0
+ hlcoord 5, 2
+ ld de, .BoxNameString
+ call PlaceString
+ call .StoreBoxIconParams
+ ret
+
+; 11822 (4:5822)
+
+.BoxNameString: ; 11822
+ db "BOX NAME?@"
+
+; 1182c
+
+.Tomodachi: ; 1182c (4:582c)
+ hlcoord 3, 2
+ ld de, .oTomodachi_no_namae_sutoringu
+ call PlaceString
+ call .StoreSpriteIconParams
+ ret
+
+; 11839 (4:5839)
+
+.oTomodachi_no_namae_sutoringu ; 11839
+ db "おともだち の なまえは?@"
+
+; 11847
+
+.LoadSprite: ; 11847 (4:5847)
+ push de
+ ld hl, vTiles0 tile $00
+ ld c, $4
+ push bc
+ call Request2bpp
+ pop bc
+ ld hl, 12 tiles
+ add hl, de
+ ld e, l
+ ld d, h
+ ld hl, vTiles0 tile $04
+ call Request2bpp
+ xor a
+ ld hl, wSpriteAnimDict
+ ld [hli], a
+ ld [hl], a
+ pop de
+ ld b, SPRITE_ANIM_INDEX_RED_WALK
+ ld a, d
+ cp HIGH(KrisSpriteGFX)
+ jr nz, .not_kris
+ ld a, e
+ cp LOW(KrisSpriteGFX)
+ jr nz, .not_kris
+ ld b, SPRITE_ANIM_INDEX_BLUE_WALK
+.not_kris
+ ld a, b
+ depixel 4, 4, 4, 0
+ call _InitSpriteAnimStruct
+ ret
+
+.StoreMonIconParams: ; 1187b (4:587b)
+ ld a, MON_NAME_LENGTH - 1
+ hlcoord 5, 6
+ jr .StoreParams
+
+.StoreSpriteIconParams: ; 11882 (4:5882)
+ ld a, PLAYER_NAME_LENGTH - 1
+ hlcoord 5, 6
+ jr .StoreParams
+
+.StoreBoxIconParams: ; 11889 (4:5889)
+ ld a, BOX_NAME_LENGTH - 1
+ hlcoord 5, 4
+ jr .StoreParams
+
+.StoreParams: ; 11890 (4:5890)
+ ld [wNamingScreenMaxNameLength], a
+ ld a, l
+ ld [wNamingScreenStringEntryCoord], a
+ ld a, h
+ ld [wNamingScreenStringEntryCoord + 1], a
+ ret
+
+NamingScreen_IsTargetBox: ; 1189c
+ push bc
+ push af
+ ld a, [wNamingScreenType]
+ sub $3
+ ld b, a
+ pop af
+ dec b
+ pop bc
+ ret
+
+; 118a8
+
+NamingScreen_InitText: ; 118a8
+ call WaitTop
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, NAMINGSCREEN_BORDER
+ call ByteFill
+ hlcoord 1, 1
+ lb bc, 6, 18
+ call NamingScreen_IsTargetBox
+ jr nz, .not_box
+ lb bc, 4, 18
+
+.not_box
+ call ClearBox
+ ld de, NameInputUpper
+NamingScreen_ApplyTextInputMode: ; 118ca
+ call NamingScreen_IsTargetBox
+ jr nz, .not_box
+ ld hl, BoxNameInputLower - NameInputLower
+ add hl, de
+ ld d, h
+ ld e, l
+
+.not_box
+ push de
+ hlcoord 1, 8
+ lb bc, 7, 18
+ call NamingScreen_IsTargetBox
+ jr nz, .not_box_2
+ hlcoord 1, 6
+ lb bc, 9, 18
+
+.not_box_2
+ call ClearBox
+ hlcoord 1, 16
+ lb bc, 1, 18
+ call ClearBox
+ pop de
+ hlcoord 2, 8
+ ld b, $5
+ call NamingScreen_IsTargetBox
+ jr nz, .row
+ hlcoord 2, 6
+ ld b, $6
+
+.row
+ ld c, $11
+.col
+ ld a, [de]
+ ld [hli], a
+ inc de
+ dec c
+ jr nz, .col
+ push de
+ ld de, 2 * SCREEN_WIDTH - $11
+ add hl, de
+ pop de
+ dec b
+ jr nz, .row
+ ret
+
+; 11915
+
+NamingScreenJoypadLoop: ; 11915
+ call JoyTextDelay
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .quit
+ call .RunJumptable
+ farcall PlaySpriteAnimationsAndDelayFrame
+ call .UpdateStringEntry
+ call DelayFrame
+ and a
+ ret
+
+.quit
+ callfar ClearSpriteAnims
+ call ClearSprites
+ xor a
+ ld [hSCX], a
+ ld [hSCY], a
+ scf
+ ret
+
+; 11940
+
+.UpdateStringEntry: ; 11940
+ xor a
+ ld [hBGMapMode], a
+ hlcoord 1, 5
+ call NamingScreen_IsTargetBox
+ jr nz, .got_coords
+ hlcoord 1, 3
+
+.got_coords
+ lb bc, 1, 18
+ call ClearBox
+ ld hl, wNamingScreenDestinationPointer
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ld hl, wNamingScreenStringEntryCoord
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call PlaceString
+ ld a, $1
+ ld [hBGMapMode], a
+ ret
+
+; 11968
+
+.RunJumptable: ; 11968
+ ld a, [wJumptableIndex]
+ ld e, a
+ ld d, $0
+ ld hl, .Jumptable
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+; 11977
+
+.Jumptable: ; 11977 (4:5977)
+ dw .InitCursor
+ dw .ReadButtons
+
+.InitCursor: ; 1197b (4:597b)
+ depixel 10, 3
+ call NamingScreen_IsTargetBox
+ jr nz, .got_cursor_position
+ ld d, 8 * 8
+.got_cursor_position
+ ld a, SPRITE_ANIM_INDEX_NAMING_SCREEN_CURSOR
+ call _InitSpriteAnimStruct
+ ld a, c
+ ld [wNamingScreenCursorObjectPointer], a
+ ld a, b
+ ld [wNamingScreenCursorObjectPointer + 1], a
+ ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+ add hl, bc
+ ld a, [hl]
+ ld hl, SPRITEANIMSTRUCT_0E
+ add hl, bc
+ ld [hl], a
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+.ReadButtons: ; 119a1 (4:59a1)
+ ld hl, hJoyPressed ; $ffa7
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .a
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .b
+ ld a, [hl]
+ and START
+ jr nz, .start
+ ld a, [hl]
+ and SELECT
+ jr nz, .select
+ ret
+
+.a
+ call .GetCursorPosition
+ cp $1
+ jr z, .select
+ cp $2
+ jr z, .b
+ cp $3
+ jr z, .end
+ call NamingScreen_GetLastCharacter
+ call NamingScreen_TryAddCharacter
+ ret nc
+
+.start
+ ld hl, wNamingScreenCursorObjectPointer
+ ld c, [hl]
+ inc hl
+ ld b, [hl]
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld [hl], $8
+ ld hl, SPRITEANIMSTRUCT_0D
+ add hl, bc
+ ld [hl], $4
+ call NamingScreen_IsTargetBox
+ ret nz
+ inc [hl]
+ ret
+
+.b
+ call NamingScreen_DeleteCharacter
+ ret
+
+.end
+ call NamingScreen_StoreEntry
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+.select
+ ld hl, wNamingScreenLetterCase
+ ld a, [hl]
+ xor 1
+ ld [hl], a
+ jr z, .upper
+ ld de, NameInputLower
+ call NamingScreen_ApplyTextInputMode
+ ret
+
+.upper
+ ld de, NameInputUpper
+ call NamingScreen_ApplyTextInputMode
+ ret
+
+.GetCursorPosition: ; 11a0b (4:5a0b)
+ ld hl, wNamingScreenCursorObjectPointer
+ ld c, [hl]
+ inc hl
+ ld b, [hl]
+
+NamingScreen_GetCursorPosition: ; 11a11 (4:5a11)
+ ld hl, SPRITEANIMSTRUCT_0D
+ add hl, bc
+ ld a, [hl]
+ push bc
+ ld b, $4
+ call NamingScreen_IsTargetBox
+ jr nz, .not_box
+ inc b
+.not_box
+ cp b
+ pop bc
+ jr nz, .not_bottom_row
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld a, [hl]
+ cp $3
+ jr c, .case_switch
+ cp $6
+ jr c, .delete
+ ld a, $3
+ ret
+
+.case_switch
+ ld a, $1
+ ret
+
+.delete
+ ld a, $2
+ ret
+
+.not_bottom_row
+ xor a
+ ret
+
+NamingScreen_AnimateCursor: ; 11a3b (4:5a3b)
+ call .GetDPad
+ ld hl, SPRITEANIMSTRUCT_0D
+ add hl, bc
+ ld a, [hl]
+ ld e, a
+ swap e
+ ld hl, SPRITEANIMSTRUCT_YOFFSET
+ add hl, bc
+ ld [hl], e
+ ld d, $4
+ call NamingScreen_IsTargetBox
+ jr nz, .ok
+ inc d
+.ok
+ cp d
+ ld de, .LetterEntries
+ ld a, SPRITE_ANIM_FRAMESET_TEXT_ENTRY_CURSOR - SPRITE_ANIM_FRAMESET_TEXT_ENTRY_CURSOR ; 0
+ jr nz, .ok2
+ ld de, .CaseDelEnd
+ ld a, SPRITE_ANIM_FRAMESET_TEXT_ENTRY_CURSOR_BIG - SPRITE_ANIM_FRAMESET_TEXT_ENTRY_CURSOR ; 1
+.ok2
+ ld hl, SPRITEANIMSTRUCT_0E
+ add hl, bc
+ add [hl] ; default SPRITE_ANIM_FRAMESET_TEXT_ENTRY_CURSOR
+ ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+ add hl, bc
+ ld [hl], a
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld l, [hl]
+ ld h, $0
+ add hl, de
+ ld a, [hl]
+ ld hl, SPRITEANIMSTRUCT_XOFFSET
+ add hl, bc
+ ld [hl], a
+ ret
+
+; 11a79 (4:5a79)
+
+.LetterEntries: ; 11a79
+ db $00, $10, $20, $30, $40, $50, $60, $70, $80
+
+.CaseDelEnd: ; 11a82
+ db $00, $00, $00, $30, $30, $30, $60, $60, $60
+
+; 11a8b
+
+.GetDPad: ; 11a8b (4:5a8b)
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_UP
+ jr nz, .up
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .down
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .left
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, .right
+ ret
+
+.right
+ call NamingScreen_GetCursorPosition
+ and a
+ jr nz, .asm_11ab7
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld a, [hl]
+ cp $8
+ jr nc, .asm_11ab4
+ inc [hl]
+ ret
+
+.asm_11ab4
+ ld [hl], $0
+ ret
+
+.asm_11ab7
+ cp $3
+ jr nz, .asm_11abc
+ xor a
+.asm_11abc
+ ld e, a
+ add a
+ add e
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld [hl], a
+ ret
+
+.left
+ call NamingScreen_GetCursorPosition
+ and a
+ jr nz, .asm_11ad8
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .asm_11ad5
+ dec [hl]
+ ret
+
+.asm_11ad5
+ ld [hl], $8
+ ret
+
+.asm_11ad8
+ cp $1
+ jr nz, .asm_11ade
+ ld a, $4
+.asm_11ade
+ dec a
+ dec a
+ ld e, a
+ add a
+ add e
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld [hl], a
+ ret
+
+.down
+ ld hl, SPRITEANIMSTRUCT_0D
+ add hl, bc
+ ld a, [hl]
+ call NamingScreen_IsTargetBox
+ jr nz, .asm_11af9
+ cp $5
+ jr nc, .asm_11aff
+ inc [hl]
+ ret
+
+.asm_11af9
+ cp $4
+ jr nc, .asm_11aff
+ inc [hl]
+ ret
+
+.asm_11aff
+ ld [hl], $0
+ ret
+
+.up
+ ld hl, SPRITEANIMSTRUCT_0D
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .asm_11b0c
+ dec [hl]
+ ret
+
+.asm_11b0c
+ ld [hl], $4
+ call NamingScreen_IsTargetBox
+ ret nz
+ inc [hl]
+ ret
+
+NamingScreen_TryAddCharacter: ; 11b14 (4:5b14)
+ ld a, [wNamingScreenLastCharacter] ; lost
+MailComposition_TryAddCharacter: ; 11b17 (4:5b17)
+ ld a, [wNamingScreenMaxNameLength]
+ ld c, a
+ ld a, [wNamingScreenCurrNameLength]
+ cp c
+ ret nc
+
+ ld a, [wNamingScreenLastCharacter]
+
+NamingScreen_LoadNextCharacter: ; 11b23
+ call NamingScreen_GetTextCursorPosition
+ ld [hl], a
+
+NamingScreen_AdvanceCursor_CheckEndOfString: ; 11b27
+ ld hl, wNamingScreenCurrNameLength
+ inc [hl]
+ call NamingScreen_GetTextCursorPosition
+ ld a, [hl]
+ cp "@"
+ jr z, .end_of_string
+ ld [hl], NAMINGSCREEN_UNDERLINE
+ and a
+ ret
+
+.end_of_string
+ scf
+ ret
+
+; 11b39 (4:5b39)
+
+; unused
+ ld a, [wNamingScreenCurrNameLength]
+ and a
+ ret z
+ push hl
+ ld hl, wNamingScreenCurrNameLength
+ dec [hl]
+ call NamingScreen_GetTextCursorPosition
+ ld c, [hl]
+ pop hl
+
+.loop
+ ld a, [hli]
+ cp $ff
+ jr z, NamingScreen_AdvanceCursor_CheckEndOfString
+ cp c
+ jr z, .done
+ inc hl
+ jr .loop
+
+.done
+ ld a, [hl]
+ jr NamingScreen_LoadNextCharacter
+
+; 11b56
+
+INCLUDE "data/text/unused_dakutens.asm"
+
+; 11bbc
+
+NamingScreen_DeleteCharacter: ; 11bbc (4:5bbc)
+ ld hl, wNamingScreenCurrNameLength
+ ld a, [hl]
+ and a
+ ret z
+ dec [hl]
+ call NamingScreen_GetTextCursorPosition
+ ld [hl], NAMINGSCREEN_UNDERLINE
+ inc hl
+ ld a, [hl]
+ cp NAMINGSCREEN_UNDERLINE
+ ret nz
+ ld [hl], NAMINGSCREEN_MIDDLELINE
+ ret
+
+NamingScreen_GetTextCursorPosition: ; 11bd0 (4:5bd0)
+ push af
+ ld hl, wNamingScreenDestinationPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wNamingScreenCurrNameLength]
+ ld e, a
+ ld d, 0
+ add hl, de
+ pop af
+ ret
+
+; 11be0
+
+NamingScreen_InitNameEntry: ; 11be0
+; load NAMINGSCREEN_UNDERLINE, (NAMINGSCREEN_MIDDLELINE * [wNamingScreenMaxNameLength]), "@" into the dw address at wNamingScreenDestinationPointer
+ ld hl, wNamingScreenDestinationPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld [hl], NAMINGSCREEN_UNDERLINE
+ inc hl
+ ld a, [wNamingScreenMaxNameLength]
+ dec a
+ ld c, a
+ ld a, NAMINGSCREEN_MIDDLELINE
+.loop
+ ld [hli], a
+ dec c
+ jr nz, .loop
+ ld [hl], "@"
+ ret
+
+; 11bf7
+
+NamingScreen_StoreEntry: ; 11bf7 (4:5bf7)
+ ld hl, wNamingScreenDestinationPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wNamingScreenMaxNameLength]
+ ld c, a
+.loop
+ ld a, [hl]
+ cp NAMINGSCREEN_MIDDLELINE
+ jr z, .terminator
+ cp NAMINGSCREEN_UNDERLINE
+ jr nz, .not_terminator
+.terminator
+ ld [hl], "@"
+.not_terminator
+ inc hl
+ dec c
+ jr nz, .loop
+ ret
+
+NamingScreen_GetLastCharacter: ; 11c11 (4:5c11)
+ ld hl, wNamingScreenCursorObjectPointer
+ ld c, [hl]
+ inc hl
+ ld b, [hl]
+ ld hl, SPRITEANIMSTRUCT_XOFFSET
+ add hl, bc
+ ld a, [hl]
+ ld hl, SPRITEANIMSTRUCT_XCOORD
+ add hl, bc
+ add [hl]
+ sub $8
+ srl a
+ srl a
+ srl a
+ ld e, a
+ ld hl, SPRITEANIMSTRUCT_YOFFSET
+ add hl, bc
+ ld a, [hl]
+ ld hl, SPRITEANIMSTRUCT_YCOORD
+ add hl, bc
+ add [hl]
+ sub $10
+ srl a
+ srl a
+ srl a
+ ld d, a
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH
+.loop
+ ld a, d
+ and a
+ jr z, .done
+ add hl, bc
+ dec d
+ jr .loop
+
+.done
+ add hl, de
+ ld a, [hl]
+ ld [wNamingScreenLastCharacter], a
+ ret
+
+LoadNamingScreenGFX: ; 11c51
+ call ClearSprites
+ callfar ClearSpriteAnims
+ call LoadStandardFont
+ call LoadFontsExtra
+
+ ld de, NamingScreenGFX_MiddleLine
+ ld hl, vTiles0 tile NAMINGSCREEN_MIDDLELINE
+ lb bc, BANK(NamingScreenGFX_MiddleLine), 1
+ call Get1bpp
+
+ ld de, NamingScreenGFX_UnderLine
+ ld hl, vTiles0 tile NAMINGSCREEN_UNDERLINE
+ lb bc, BANK(NamingScreenGFX_UnderLine), 1
+ call Get1bpp
+
+ ld de, vTiles2 tile NAMINGSCREEN_BORDER
+ ld hl, NamingScreenGFX_Border
+ ld bc, 1 tiles
+ ld a, BANK(NamingScreenGFX_Border)
+ call FarCopyBytes
+
+ ld de, vTiles0 tile NAMINGSCREEN_CURSOR
+ ld hl, NamingScreenGFX_Cursor
+ ld bc, 2 tiles
+ ld a, BANK(NamingScreenGFX_Cursor)
+ call FarCopyBytes
+
+ ld a, $5
+ ld hl, wSpriteAnimDict + 9 * 2
+ ld [hli], a
+ ld [hl], NAMINGSCREEN_CURSOR
+ xor a
+ ld [hSCY], a
+ ld [wGlobalAnimYOffset], a
+ ld [hSCX], a
+ ld [wGlobalAnimXOffset], a
+ ld [wJumptableIndex], a
+ ld [wNamingScreenLetterCase], a
+ ld [hBGMapMode], a
+ ld [wNamingScreenCurrNameLength], a
+ ld a, $7
+ ld [hWX], a
+ ret
+
+; 11cb7
+
+NamingScreenGFX_Border: ; 11cb7
+INCBIN "gfx/naming_screen/border.2bpp"
+; 11cc7
+
+NamingScreenGFX_Cursor: ; 11cc7
+INCBIN "gfx/naming_screen/cursor.2bpp"
+; 11ce7
+
+INCLUDE "data/text/name_input_chars.asm"
+; 11e5d
+
+NamingScreenGFX_End: ; unused
+INCBIN "gfx/naming_screen/end.1bpp"
+; 11e6d
+
+NamingScreenGFX_MiddleLine:
+INCBIN "gfx/naming_screen/middle_line.1bpp"
+; 11e6d
+
+NamingScreenGFX_UnderLine: ; 11e6d
+INCBIN "gfx/naming_screen/underline.1bpp"
+; 11e75
+
+_ComposeMailMessage: ; 11e75 (mail?)
+ ld hl, wNamingScreenDestinationPointer
+ ld [hl], e
+ inc hl
+ ld [hl], d
+ ld a, [hMapAnims]
+ push af
+ xor a
+ ld [hMapAnims], a
+ ld a, [hInMenu]
+ push af
+ ld a, $1
+ ld [hInMenu], a
+ call .InitBlankMail
+ call DelayFrame
+
+.loop
+ call .DoMailEntry
+ jr nc, .loop
+
+ pop af
+ ld [hInMenu], a
+ pop af
+ ld [hMapAnims], a
+ ret
+
+.InitBlankMail: ; 11e9a (4:5e9a)
+ call ClearBGPalettes
+ call DisableLCD
+ call LoadNamingScreenGFX
+ ld de, vTiles0 tile $00
+ ld hl, .MailIcon
+ ld bc, 8 tiles
+ ld a, BANK(.MailIcon)
+ call FarCopyBytes
+ xor a
+ ld hl, wSpriteAnimDict
+ ld [hli], a
+ ld [hl], a
+
+ ; init mail icon
+ depixel 3, 2
+ ld a, SPRITE_ANIM_INDEX_PARTY_MON
+ call _InitSpriteAnimStruct
+
+ ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+ add hl, bc
+ ld [hl], $0
+ call .InitCharset
+ ld a, LCDC_DEFAULT
+ ld [rLCDC], a
+ call .initwNamingScreenMaxNameLength
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ call WaitBGMap
+ call WaitTop
+ ld a, %11100100
+ call DmgToCgbBGPals
+ ld a, %11100100
+ call DmgToCgbObjPal0
+ call NamingScreen_InitNameEntry
+ ld hl, wNamingScreenDestinationPointer
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ld hl, MAIL_LINE_LENGTH
+ add hl, de
+ ld [hl], "<NEXT>"
+ ret
+
+; 11ef4 (4:5ef4)
+
+.MailIcon: ; 11ef4
+INCBIN "gfx/icons/mail_big.2bpp"
+; 11f74
+
+.initwNamingScreenMaxNameLength ; 11f74 (4:5f74)
+ ld a, MAIL_MSG_LENGTH + 1
+ ld [wNamingScreenMaxNameLength], a
+ ret
+
+; 11f7a (4:5f7a)
+
+.UnusedString11f7a:
+ db "メールを かいてね@"
+
+; 11f84
+
+.InitCharset: ; 11f84 (4:5f84)
+ call WaitTop
+ hlcoord 0, 0
+ ld bc, 6 * SCREEN_WIDTH
+ ld a, NAMINGSCREEN_BORDER
+ call ByteFill
+ hlcoord 0, 6
+ ld bc, 12 * SCREEN_WIDTH
+ ld a, " "
+ call ByteFill
+ hlcoord 1, 1
+ lb bc, 4, SCREEN_WIDTH - 2
+ call ClearBox
+ ld de, MailEntry_Uppercase
+
+.PlaceMailCharset: ; 11fa9 (4:5fa9)
+ hlcoord 1, 7
+ ld b, 6
+.next
+ ld c, SCREEN_WIDTH - 1
+.loop_
+ ld a, [de]
+ ld [hli], a
+ inc de
+ dec c
+ jr nz, .loop_
+ push de
+ ld de, SCREEN_WIDTH + 1
+ add hl, de
+ pop de
+ dec b
+ jr nz, .next
+ ret
+
+.DoMailEntry: ; 11fc0 (4:5fc0)
+ call JoyTextDelay
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .exit_mail
+ call .DoJumptable
+ farcall PlaySpriteAnimationsAndDelayFrame
+ call .Update
+ call DelayFrame
+ and a
+ ret
+
+.exit_mail
+ callfar ClearSpriteAnims
+ call ClearSprites
+ xor a
+ ld [hSCX], a
+ ld [hSCY], a
+ scf
+ ret
+
+.Update: ; 11feb (4:5feb)
+ xor a
+ ld [hBGMapMode], a
+ hlcoord 1, 1
+ lb bc, 4, 18
+ call ClearBox
+ ld hl, wNamingScreenDestinationPointer
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ hlcoord 2, 2
+ call PlaceString
+ ld a, $1
+ ld [hBGMapMode], a
+ ret
+
+.DoJumptable: ; 12008 (4:6008)
+ ld a, [wJumptableIndex]
+ ld e, a
+ ld d, 0
+ ld hl, .Jumptable
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.Jumptable: ; 12017 (4:6017)
+ dw .init_blinking_cursor
+ dw .process_joypad
+
+.init_blinking_cursor ; 1201b (4:601b)
+ depixel 9, 2
+ ld a, SPRITE_ANIM_INDEX_COMPOSE_MAIL_CURSOR
+ call _InitSpriteAnimStruct
+ ld a, c
+ ld [wNamingScreenCursorObjectPointer], a
+ ld a, b
+ ld [wNamingScreenCursorObjectPointer + 1], a
+ ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+ add hl, bc
+ ld a, [hl]
+ ld hl, SPRITEANIMSTRUCT_0E
+ add hl, bc
+ ld [hl], a
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+.process_joypad ; 1203a (4:603a)
+ ld hl, hJoyPressed ; $ffa7
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .a
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .b
+ ld a, [hl]
+ and START
+ jr nz, .start
+ ld a, [hl]
+ and SELECT
+ jr nz, .select
+ ret
+
+.a
+ call NamingScreen_PressedA_GetCursorCommand
+ cp $1
+ jr z, .select
+ cp $2
+ jr z, .b
+ cp $3
+ jr z, .finished
+ call NamingScreen_GetLastCharacter
+ call MailComposition_TryAddLastCharacter
+ jr c, .start
+ ld hl, wNamingScreenCurrNameLength
+ ld a, [hl]
+ cp MAIL_LINE_LENGTH
+ ret nz
+ inc [hl]
+ call NamingScreen_GetTextCursorPosition
+ ld [hl], NAMINGSCREEN_UNDERLINE
+ dec hl
+ ld [hl], "<NEXT>"
+ ret
+
+.start
+ ld hl, wNamingScreenCursorObjectPointer
+ ld c, [hl]
+ inc hl
+ ld b, [hl]
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld [hl], $9
+ ld hl, SPRITEANIMSTRUCT_0D
+ add hl, bc
+ ld [hl], $5
+ ret
+
+.b
+ call NamingScreen_DeleteCharacter
+ ld hl, wNamingScreenCurrNameLength
+ ld a, [hl]
+ cp MAIL_LINE_LENGTH
+ ret nz
+ dec [hl]
+ call NamingScreen_GetTextCursorPosition
+ ld [hl], NAMINGSCREEN_UNDERLINE
+ inc hl
+ ld [hl], "<NEXT>"
+ ret
+
+.finished
+ call NamingScreen_StoreEntry
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+.select
+ ld hl, wNamingScreenLetterCase
+ ld a, [hl]
+ xor 1
+ ld [hl], a
+ jr nz, .switch_to_lowercase
+ ld de, MailEntry_Uppercase
+ call .PlaceMailCharset
+ ret
+
+.switch_to_lowercase
+ ld de, MailEntry_Lowercase
+ call .PlaceMailCharset
+ ret
+
+; called from engine/sprite_anims.asm
+
+ComposeMail_AnimateCursor: ; 120c1 (4:60c1)
+ call .GetDPad
+ ld hl, SPRITEANIMSTRUCT_0D
+ add hl, bc
+ ld a, [hl]
+ ld e, a
+ swap e
+ ld hl, SPRITEANIMSTRUCT_YOFFSET
+ add hl, bc
+ ld [hl], e
+ cp $5
+ ld de, .LetterEntries
+ ld a, 0
+ jr nz, .got_pointer
+ ld de, .CaseDelEnd
+ ld a, 1
+.got_pointer
+ ld hl, SPRITEANIMSTRUCT_0E
+ add hl, bc
+ add [hl]
+ ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+ add hl, bc
+ ld [hl], a
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld l, [hl]
+ ld h, 0
+ add hl, de
+ ld a, [hl]
+ ld hl, SPRITEANIMSTRUCT_XOFFSET
+ add hl, bc
+ ld [hl], a
+ ret
+
+; 120f8 (4:60f8)
+
+.LetterEntries: ; 120f8
+ db $00, $10, $20, $30, $40, $50, $60, $70, $80, $90
+
+.CaseDelEnd: ; 12102
+ db $00, $00, $00, $30, $30, $30, $60, $60, $60, $60
+
+; 1210c
+
+.GetDPad: ; 1210c (4:610c)
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_UP
+ jr nz, .up
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .down
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .left
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, .right
+ ret
+
+.right
+ call ComposeMail_GetCursorPosition
+ and a
+ jr nz, .case_del_done_right
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld a, [hl]
+ cp $9
+ jr nc, .wrap_around_letter_right
+ inc [hl]
+ ret
+
+.wrap_around_letter_right
+ ld [hl], $0
+ ret
+
+.case_del_done_right
+ cp $3
+ jr nz, .wrap_around_command_right
+ xor a
+.wrap_around_command_right
+ ld e, a
+ add a
+ add e
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld [hl], a
+ ret
+
+.left
+ call ComposeMail_GetCursorPosition
+ and a
+ jr nz, .caps_del_done_left
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .wrap_around_letter_left
+ dec [hl]
+ ret
+
+.wrap_around_letter_left
+ ld [hl], $9
+ ret
+
+.caps_del_done_left
+ cp $1
+ jr nz, .wrap_around_command_left
+ ld a, $4
+.wrap_around_command_left
+ dec a
+ dec a
+ ld e, a
+ add a
+ add e
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld [hl], a
+ ret
+
+.down
+ ld hl, SPRITEANIMSTRUCT_0D
+ add hl, bc
+ ld a, [hl]
+ cp $5
+ jr nc, .wrap_around_down
+ inc [hl]
+ ret
+
+.wrap_around_down
+ ld [hl], $0
+ ret
+
+.up
+ ld hl, SPRITEANIMSTRUCT_0D
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .wrap_around_up
+ dec [hl]
+ ret
+
+.wrap_around_up
+ ld [hl], $5
+ ret
+
+NamingScreen_PressedA_GetCursorCommand: ; 12185 (4:6185)
+ ld hl, wNamingScreenCursorObjectPointer
+ ld c, [hl]
+ inc hl
+ ld b, [hl]
+
+ComposeMail_GetCursorPosition: ; 1218b (4:618b)
+ ld hl, SPRITEANIMSTRUCT_0D
+ add hl, bc
+ ld a, [hl]
+ cp $5
+ jr nz, .letter
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld a, [hl]
+ cp $3
+ jr c, .case
+ cp $6
+ jr c, .del
+ ld a, $3
+ ret
+
+.case
+ ld a, $1
+ ret
+
+.del
+ ld a, $2
+ ret
+
+.letter
+ xor a
+ ret
+
+MailComposition_TryAddLastCharacter: ; 121ac (4:61ac)
+ ld a, [wNamingScreenLastCharacter]
+ jp MailComposition_TryAddCharacter
+
+; 121b2 (4:61b2)
+
+; unused
+ ld a, [wNamingScreenCurrNameLength]
+ and a
+ ret z
+ cp $11
+ jr nz, .asm_121c3
+ push hl
+ ld hl, wNamingScreenCurrNameLength
+ dec [hl]
+ dec [hl]
+ jr .asm_121c8
+
+.asm_121c3
+ push hl
+ ld hl, wNamingScreenCurrNameLength
+ dec [hl]
+
+.asm_121c8
+ call NamingScreen_GetTextCursorPosition
+ ld c, [hl]
+ pop hl
+.asm_121cd
+ ld a, [hli]
+ cp $ff
+ jp z, NamingScreen_AdvanceCursor_CheckEndOfString
+ cp c
+ jr z, .asm_121d9
+ inc hl
+ jr .asm_121cd
+
+.asm_121d9
+ ld a, [hl]
+ jp NamingScreen_LoadNextCharacter
+
+; 121dd
+
+INCLUDE "data/text/mail_input_chars.asm"
+
+; 122c1
diff --git a/engine/menu/options_menu.asm b/engine/menu/options_menu.asm
new file mode 100755
index 000000000..c0a255cb0
--- /dev/null
+++ b/engine/menu/options_menu.asm
@@ -0,0 +1,583 @@
+_OptionsMenu: ; e41d0
+ ld hl, hInMenu
+ ld a, [hl]
+ push af
+ ld [hl], $1
+ call ClearBGPalettes
+ hlcoord 0, 0
+ ld b, 16
+ ld c, 18
+ call TextBox
+ hlcoord 2, 2
+ ld de, StringOptions
+ call PlaceString
+ xor a
+ ld [wJumptableIndex], a
+ ld c, $6 ; number of items on the menu minus 1 (for cancel)
+
+.print_text_loop ; this next will display the settings of each option when the menu is opened
+ push bc
+ xor a
+ ld [hJoyLast], a
+ call GetOptionPointer
+ pop bc
+ ld hl, wJumptableIndex
+ inc [hl]
+ dec c
+ jr nz, .print_text_loop
+
+ call UpdateFrame
+ xor a
+ ld [wJumptableIndex], a
+ inc a
+ ld [hBGMapMode], a
+ call WaitBGMap
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ call SetPalettes
+
+.joypad_loop
+ call JoyTextDelay
+ ld a, [hJoyPressed]
+ and START | B_BUTTON
+ jr nz, .ExitOptions
+ call OptionsControl
+ jr c, .dpad
+ call GetOptionPointer
+ jr c, .ExitOptions
+
+.dpad
+ call Options_UpdateCursorPosition
+ ld c, 3
+ call DelayFrames
+ jr .joypad_loop
+
+.ExitOptions:
+ ld de, SFX_TRANSACTION
+ call PlaySFX
+ call WaitSFX
+ pop af
+ ld [hInMenu], a
+ ret
+; e4241
+
+StringOptions: ; e4241
+ db "TEXT SPEED<LNBRK>"
+ db " :<LNBRK>"
+ db "BATTLE SCENE<LNBRK>"
+ db " :<LNBRK>"
+ db "BATTLE STYLE<LNBRK>"
+ db " :<LNBRK>"
+ db "SOUND<LNBRK>"
+ db " :<LNBRK>"
+ db "PRINT<LNBRK>"
+ db " :<LNBRK>"
+ db "MENU ACCOUNT<LNBRK>"
+ db " :<LNBRK>"
+ db "FRAME<LNBRK>"
+ db " :TYPE<LNBRK>"
+ db "CANCEL@"
+; e42d6
+
+
+GetOptionPointer: ; e42d6
+ ld a, [wJumptableIndex] ; load the cursor position to a
+ ld e, a ; copy it to de
+ ld d, 0
+ ld hl, .Pointers
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl ; jump to the code of the current highlighted item
+; e42e5
+
+.Pointers:
+ dw Options_TextSpeed
+ dw Options_BattleScene
+ dw Options_BattleStyle
+ dw Options_Sound
+ dw Options_Print
+ dw Options_MenuAccount
+ dw Options_Frame
+ dw Options_Cancel
+; e42f5
+
+
+ const_def
+ const OPT_TEXT_SPEED_FAST ; 0
+ const OPT_TEXT_SPEED_MED ; 1
+ const OPT_TEXT_SPEED_SLOW ; 2
+
+Options_TextSpeed: ; e42f5
+ call GetTextSpeed
+ ld a, [hJoyPressed]
+ bit D_LEFT_F, a
+ jr nz, .LeftPressed
+ bit D_RIGHT_F, a
+ jr z, .NonePressed
+ ld a, c ; right pressed
+ cp OPT_TEXT_SPEED_SLOW
+ jr c, .Increase
+ ld c, OPT_TEXT_SPEED_FAST + -1
+
+.Increase:
+ inc c
+ ld a, e
+ jr .Save
+
+.LeftPressed:
+ ld a, c
+ and a
+ jr nz, .Decrease
+ ld c, OPT_TEXT_SPEED_SLOW + 1
+
+.Decrease:
+ dec c
+ ld a, d
+
+.Save:
+ ld b, a
+ ld a, [wOptions]
+ and $f0
+ or b
+ ld [wOptions], a
+
+.NonePressed:
+ ld b, 0
+ ld hl, .Strings
+ add hl, bc
+ add hl, bc
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ hlcoord 11, 3
+ call PlaceString
+ and a
+ ret
+; e4331
+
+.Strings:
+; entries correspond to OPT_TEXT_SPEED_* constants
+ dw .Fast
+ dw .Mid
+ dw .Slow
+
+.Fast: db "FAST@"
+.Mid: db "MID @"
+.Slow: db "SLOW@"
+; e4346
+
+
+GetTextSpeed: ; e4346
+; converts TEXT_DELAY_* value in a to OPT_TEXT_SPEED_* value in c,
+; with previous/next TEXT_DELAY_* values in d/e
+ ld a, [wOptions]
+ and $7
+ cp TEXT_DELAY_SLOW
+ jr z, .slow
+ cp TEXT_DELAY_FAST
+ jr z, .fast
+ ; none of the above
+ ld c, OPT_TEXT_SPEED_MED
+ lb de, TEXT_DELAY_FAST, TEXT_DELAY_SLOW
+ ret
+
+.slow
+ ld c, OPT_TEXT_SPEED_SLOW
+ lb de, TEXT_DELAY_MED, TEXT_DELAY_FAST
+ ret
+
+.fast
+ ld c, OPT_TEXT_SPEED_FAST
+ lb de, TEXT_DELAY_SLOW, TEXT_DELAY_MED
+ ret
+; e4365
+
+
+Options_BattleScene: ; e4365
+ ld hl, wOptions
+ ld a, [hJoyPressed]
+ bit D_LEFT_F, a
+ jr nz, .LeftPressed
+ bit D_RIGHT_F, a
+ jr z, .NonePressed
+ bit BATTLE_SCENE, [hl]
+ jr nz, .ToggleOn
+ jr .ToggleOff
+
+.LeftPressed:
+ bit BATTLE_SCENE, [hl]
+ jr z, .ToggleOff
+ jr .ToggleOn
+
+.NonePressed:
+ bit BATTLE_SCENE, [hl]
+ jr z, .ToggleOn
+ jr .ToggleOff
+
+.ToggleOn:
+ res BATTLE_SCENE, [hl]
+ ld de, .On
+ jr .Display
+
+.ToggleOff:
+ set BATTLE_SCENE, [hl]
+ ld de, .Off
+
+.Display:
+ hlcoord 11, 5
+ call PlaceString
+ and a
+ ret
+; e4398
+
+.On: db "ON @"
+.Off: db "OFF@"
+; e43a0
+
+
+Options_BattleStyle: ; e43a0
+ ld hl, wOptions
+ ld a, [hJoyPressed]
+ bit D_LEFT_F, a
+ jr nz, .LeftPressed
+ bit D_RIGHT_F, a
+ jr z, .NonePressed
+ bit BATTLE_SHIFT, [hl]
+ jr nz, .ToggleShift
+ jr .ToggleSet
+
+.LeftPressed:
+ bit BATTLE_SHIFT, [hl]
+ jr z, .ToggleSet
+ jr .ToggleShift
+
+.NonePressed:
+ bit BATTLE_SHIFT, [hl]
+ jr nz, .ToggleSet
+
+.ToggleShift:
+ res BATTLE_SHIFT, [hl]
+ ld de, .Shift
+ jr .Display
+
+.ToggleSet:
+ set BATTLE_SHIFT, [hl]
+ ld de, .Set
+
+.Display:
+ hlcoord 11, 7
+ call PlaceString
+ and a
+ ret
+; e43d1
+
+.Shift: db "SHIFT@"
+.Set: db "SET @"
+; e43dd
+
+
+Options_Sound: ; e43dd
+ ld hl, wOptions
+ ld a, [hJoyPressed]
+ bit D_LEFT_F, a
+ jr nz, .LeftPressed
+ bit D_RIGHT_F, a
+ jr z, .NonePressed
+ bit STEREO, [hl]
+ jr nz, .SetMono
+ jr .SetStereo
+
+.LeftPressed:
+ bit STEREO, [hl]
+ jr z, .SetStereo
+ jr .SetMono
+
+.NonePressed:
+ bit STEREO, [hl]
+ jr nz, .ToggleStereo
+ jr .ToggleMono
+
+.SetMono:
+ res STEREO, [hl]
+ call RestartMapMusic
+
+.ToggleMono:
+ ld de, .Mono
+ jr .Display
+
+.SetStereo:
+ set STEREO, [hl]
+ call RestartMapMusic
+
+.ToggleStereo:
+ ld de, .Stereo
+
+.Display:
+ hlcoord 11, 9
+ call PlaceString
+ and a
+ ret
+; e4416
+
+.Mono: db "MONO @"
+.Stereo: db "STEREO@"
+; e4424
+
+
+ const_def
+ const OPT_PRINT_LIGHTEST ; 0
+ const OPT_PRINT_LIGHTER ; 1
+ const OPT_PRINT_NORMAL ; 2
+ const OPT_PRINT_DARKER ; 3
+ const OPT_PRINT_DARKEST ; 4
+
+Options_Print: ; e4424
+ call GetPrinterSetting
+ ld a, [hJoyPressed]
+ bit D_LEFT_F, a
+ jr nz, .LeftPressed
+ bit D_RIGHT_F, a
+ jr z, .NonePressed
+ ld a, c
+ cp OPT_PRINT_DARKEST
+ jr c, .Increase
+ ld c, OPT_PRINT_LIGHTEST - 1
+
+.Increase:
+ inc c
+ ld a, e
+ jr .Save
+
+.LeftPressed:
+ ld a, c
+ and a
+ jr nz, .Decrease
+ ld c, OPT_PRINT_DARKEST + 1
+
+.Decrease:
+ dec c
+ ld a, d
+
+.Save:
+ ld b, a
+ ld [wGBPrinter], a
+
+.NonePressed:
+ ld b, $0
+ ld hl, .Strings
+ add hl, bc
+ add hl, bc
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ hlcoord 11, 11
+ call PlaceString
+ and a
+ ret
+; e445a
+
+.Strings:
+; entries correspond to OPT_PRINT_* constants
+ dw .Lightest
+ dw .Lighter
+ dw .Normal
+ dw .Darker
+ dw .Darkest
+
+.Lightest: db "LIGHTEST@"
+.Lighter: db "LIGHTER @"
+.Normal: db "NORMAL @"
+.Darker: db "DARKER @"
+.Darkest: db "DARKEST @"
+; e4491
+
+
+GetPrinterSetting: ; e4491
+; converts GBPRINTER_* value in a to OPT_PRINT_* value in c,
+; with previous/next GBPRINTER_* values in d/e
+ ld a, [wGBPrinter]
+ and a
+ jr z, .IsLightest
+ cp GBPRINTER_LIGHTER
+ jr z, .IsLight
+ cp GBPRINTER_DARKER
+ jr z, .IsDark
+ cp GBPRINTER_DARKEST
+ jr z, .IsDarkest
+ ; none of the above
+ ld c, OPT_PRINT_NORMAL
+ lb de, GBPRINTER_LIGHTER, GBPRINTER_DARKER
+ ret
+
+.IsLightest:
+ ld c, OPT_PRINT_LIGHTEST
+ lb de, GBPRINTER_DARKEST, GBPRINTER_LIGHTER
+ ret
+
+.IsLight:
+ ld c, OPT_PRINT_LIGHTER
+ lb de, GBPRINTER_LIGHTEST, GBPRINTER_NORMAL
+ ret
+
+.IsDark:
+ ld c, OPT_PRINT_DARKER
+ lb de, GBPRINTER_NORMAL, GBPRINTER_DARKEST
+ ret
+
+.IsDarkest:
+ ld c, OPT_PRINT_DARKEST
+ lb de, GBPRINTER_DARKER, GBPRINTER_LIGHTEST
+ ret
+; e44c1
+
+Options_MenuAccount: ; e44c1
+ ld hl, wOptions2
+ ld a, [hJoyPressed]
+ bit D_LEFT_F, a
+ jr nz, .LeftPressed
+ bit D_RIGHT_F, a
+ jr z, .NonePressed
+ bit MENU_ACCOUNT, [hl]
+ jr nz, .ToggleOff
+ jr .ToggleOn
+
+.LeftPressed:
+ bit MENU_ACCOUNT, [hl]
+ jr z, .ToggleOn
+ jr .ToggleOff
+
+.NonePressed:
+ bit MENU_ACCOUNT, [hl]
+ jr nz, .ToggleOn
+
+.ToggleOff:
+ res MENU_ACCOUNT, [hl]
+ ld de, .Off
+ jr .Display
+
+.ToggleOn:
+ set MENU_ACCOUNT, [hl]
+ ld de, .On
+
+.Display:
+ hlcoord 11, 13
+ call PlaceString
+ and a
+ ret
+; e44f2
+
+.Off: db "OFF@"
+.On: db "ON @"
+; e44fa
+
+
+Options_Frame: ; e44fa
+ ld hl, wTextBoxFrame
+ ld a, [hJoyPressed]
+ bit D_LEFT_F, a
+ jr nz, .LeftPressed
+ bit D_RIGHT_F, a
+ jr nz, .RightPressed
+ and a
+ ret
+
+.RightPressed:
+ ld a, [hl]
+ inc a
+ jr .Save
+
+.LeftPressed:
+ ld a, [hl]
+ dec a
+
+.Save:
+ and $7
+ ld [hl], a
+UpdateFrame: ; e4512
+ ld a, [wTextBoxFrame]
+ hlcoord 16, 15 ; where on the screen the number is drawn
+ add "1"
+ ld [hl], a
+ call LoadFontsExtra
+ and a
+ ret
+; e4520
+
+Options_Cancel: ; e4520
+ ld a, [hJoyPressed]
+ and A_BUTTON
+ jr nz, .Exit
+ and a
+ ret
+
+.Exit:
+ scf
+ ret
+; e452a
+
+OptionsControl: ; e452a
+ ld hl, wJumptableIndex
+ ld a, [hJoyLast]
+ cp D_DOWN
+ jr z, .DownPressed
+ cp D_UP
+ jr z, .UpPressed
+ and a
+ ret
+
+.DownPressed:
+ ld a, [hl] ; load the cursor position to a
+ cp $7 ; maximum number of items in option menu
+ jr nz, .CheckFive
+ ld [hl], $0
+ scf
+ ret
+
+.CheckFive: ; I have no idea why this exists...
+ cp $5
+ jr nz, .Increase
+ ld [hl], $5
+
+.Increase:
+ inc [hl]
+ scf
+ ret
+
+.UpPressed:
+ ld a, [hl]
+ cp $6
+ jr nz, .NotSix
+ ld [hl], $5 ; Another thing where I'm not sure why it exists
+ scf
+ ret
+
+.NotSix:
+ and a
+ jr nz, .Decrease
+ ld [hl], $8 ; number of option items +1
+
+.Decrease:
+ dec [hl]
+ scf
+ ret
+; e455c
+
+Options_UpdateCursorPosition: ; e455c
+ hlcoord 1, 1
+ ld de, SCREEN_WIDTH
+ ld c, $10
+.loop
+ ld [hl], " "
+ add hl, de
+ dec c
+ jr nz, .loop
+ hlcoord 1, 2
+ ld bc, 2 * SCREEN_WIDTH
+ ld a, [wJumptableIndex]
+ call AddNTimes
+ ld [hl], "▶"
+ ret
+; e4579
diff --git a/engine/menu/pack.asm b/engine/menu/pack.asm
new file mode 100644
index 000000000..ea3a051ac
--- /dev/null
+++ b/engine/menu/pack.asm
@@ -0,0 +1,1711 @@
+; Pack.Jumptable and BattlePack.Jumptable indexes
+ const_def
+ const PACKSTATE_INITGFX ; 0
+ const PACKSTATE_INITITEMSPOCKET ; 1
+ const PACKSTATE_ITEMSPOCKETMENU ; 2
+ const PACKSTATE_INITBALLSPOCKET ; 3
+ const PACKSTATE_BALLSPOCKETMENU ; 4
+ const PACKSTATE_INITKEYITEMSPOCKET ; 5
+ const PACKSTATE_KEYITEMSPOCKETMENU ; 6
+ const PACKSTATE_INITTMHMPOCKET ; 7
+ const PACKSTATE_TMHMPOCKETMENU ; 8
+ const PACKSTATE_QUITNOSCRIPT ; 9
+ const PACKSTATE_QUITRUNSCRIPT ; 10
+
+Pack: ; 10000
+ ld hl, wOptions
+ set NO_TEXT_SCROLL, [hl]
+ call InitPackBuffers
+.loop
+ call JoyTextDelay
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .done
+ call .RunJumptable
+ call DelayFrame
+ jr .loop
+
+.done
+ ld a, [wCurrPocket]
+ ld [wLastPocket], a
+ ld hl, wOptions
+ res NO_TEXT_SCROLL, [hl]
+ ret
+; 10026
+
+.RunJumptable: ; 10026
+ ld a, [wJumptableIndex]
+ ld hl, .Jumptable
+ call Pack_GetJumptablePointer
+ jp hl
+
+; 10030
+
+.Jumptable: ; 10030 (4:4030)
+; entries correspond to PACKSTATE_* constants
+ dw .InitGFX ; 0
+ dw .InitItemsPocket ; 1
+ dw .ItemsPocketMenu ; 2
+ dw .InitBallsPocket ; 3
+ dw .BallsPocketMenu ; 4
+ dw .InitKeyItemsPocket ; 5
+ dw .KeyItemsPocketMenu ; 6
+ dw .InitTMHMPocket ; 7
+ dw .TMHMPocketMenu ; 8
+ dw Pack_QuitNoScript ; 9
+ dw Pack_QuitRunScript ; 10
+
+.InitGFX: ; 10046 (4:4046)
+ xor a
+ ld [hBGMapMode], a
+ call Pack_InitGFX
+ ld a, [wPackJumptableIndex]
+ ld [wJumptableIndex], a
+ call Pack_InitColors
+ ret
+
+.InitItemsPocket: ; 10056 (4:4056)
+ xor a ; ITEM_POCKET
+ ld [wCurrPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ call WaitBGMap_DrawPackGFX
+ call Pack_JumptableNext
+ ret
+
+.ItemsPocketMenu: ; 10067 (4:4067)
+ ld hl, ItemsPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wItemsPocketCursor]
+ ld [wMenuCursorBuffer], a
+ ld a, [wItemsPocketScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wItemsPocketScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wItemsPocketCursor], a
+ ld b, PACKSTATE_INITTMHMPOCKET ; left
+ ld c, PACKSTATE_INITBALLSPOCKET ; right
+ call Pack_InterpretJoypad
+ ret c
+ call .ItemBallsKey_LoadSubmenu
+ ret
+
+.InitKeyItemsPocket: ; 10094 (4:4094)
+ ld a, KEY_ITEM_POCKET
+ ld [wCurrPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ call WaitBGMap_DrawPackGFX
+ call Pack_JumptableNext
+ ret
+
+.KeyItemsPocketMenu: ; 100a6 (4:40a6)
+ ld hl, KeyItemsPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wKeyItemsPocketCursor]
+ ld [wMenuCursorBuffer], a
+ ld a, [wKeyItemsPocketScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wKeyItemsPocketScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wKeyItemsPocketCursor], a
+ ld b, PACKSTATE_INITBALLSPOCKET ; left
+ ld c, PACKSTATE_INITTMHMPOCKET ; right
+ call Pack_InterpretJoypad
+ ret c
+ call .ItemBallsKey_LoadSubmenu
+ ret
+
+.InitTMHMPocket: ; 100d3 (4:40d3)
+ ld a, TM_HM_POCKET
+ ld [wCurrPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ xor a
+ ld [hBGMapMode], a
+ call WaitBGMap_DrawPackGFX
+ call Pack_JumptableNext
+ ret
+
+.TMHMPocketMenu: ; 100e8 (4:40e8)
+ farcall TMHMPocket
+ ld b, PACKSTATE_INITKEYITEMSPOCKET ; left
+ ld c, PACKSTATE_INITITEMSPOCKET ; right
+ call Pack_InterpretJoypad
+ ret c
+ farcall _CheckTossableItem
+ ld a, [wItemAttributeParamBuffer]
+ and a
+ jr nz, .use_quit
+ ld hl, .MenuHeader2
+ ld de, .Jumptable2
+ jr .load_jump
+
+.use_quit
+ ld hl, .MenuHeader1
+ ld de, .Jumptable1
+.load_jump
+ push de
+ call LoadMenuHeader
+ call VerticalMenu
+ call ExitMenu
+ pop hl
+ ret c
+ ld a, [wMenuCursorY]
+ dec a
+ call Pack_GetJumptablePointer
+ jp hl
+
+; 10124 (4:4124)
+.MenuHeader1: ; 0x10124
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 13, 7, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData_1
+ db 1 ; default option
+; 0x1012c
+
+.MenuData_1: ; 0x1012c
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 2 ; items
+ db "USE@"
+ db "QUIT@"
+; 0x10137
+
+.Jumptable1: ; 10137
+ dw .UseItem
+ dw QuitItemSubmenu
+
+; 1013b
+
+.MenuHeader2: ; 0x1013b
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 13, 5, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData_2
+ db 1 ; default option
+; 0x10143
+
+.MenuData_2: ; 0x10143
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 3 ; items
+ db "USE@"
+ db "GIVE@"
+ db "QUIT@"
+; 0x10153
+
+.Jumptable2: ; 10153
+ dw .UseItem
+ dw GiveItem
+ dw QuitItemSubmenu
+; 10159
+
+.UseItem: ; 10159
+ farcall AskTeachTMHM
+ ret c
+ farcall ChooseMonToLearnTMHM
+ jr c, .declined
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ res NO_TEXT_SCROLL, [hl]
+ farcall TeachTMHM
+ pop af
+ ld [wOptions], a
+.declined
+ xor a
+ ld [hBGMapMode], a
+ call Pack_InitGFX
+ call WaitBGMap_DrawPackGFX
+ call Pack_InitColors
+ ret
+
+.InitBallsPocket: ; 10186 (4:4186)
+ ld a, BALL_POCKET
+ ld [wCurrPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ call WaitBGMap_DrawPackGFX
+ call Pack_JumptableNext
+ ret
+
+.BallsPocketMenu: ; 10198 (4:4198)
+ ld hl, BallsPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wBallsPocketCursor]
+ ld [wMenuCursorBuffer], a
+ ld a, [wBallsPocketScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wBallsPocketScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wBallsPocketCursor], a
+ ld b, PACKSTATE_INITITEMSPOCKET ; left
+ ld c, PACKSTATE_INITKEYITEMSPOCKET ; right
+ call Pack_InterpretJoypad
+ ret c
+ call .ItemBallsKey_LoadSubmenu
+ ret
+
+.ItemBallsKey_LoadSubmenu: ; 101c5 (4:41c5)
+ farcall _CheckTossableItem
+ ld a, [wItemAttributeParamBuffer]
+ and a
+ jr nz, .tossable
+ farcall CheckSelectableItem
+ ld a, [wItemAttributeParamBuffer]
+ and a
+ jr nz, .selectable
+ farcall CheckItemMenu
+ ld a, [wItemAttributeParamBuffer]
+ and a
+ jr nz, .usable
+ jr .unusable
+
+.selectable
+ farcall CheckItemMenu
+ ld a, [wItemAttributeParamBuffer]
+ and a
+ jr nz, .selectable_usable
+ jr .selectable_unusable
+
+.tossable
+ farcall CheckSelectableItem
+ ld a, [wItemAttributeParamBuffer]
+ and a
+ jr nz, .tossable_selectable
+ jr .tossable_unselectable
+
+.usable
+ ld hl, MenuHeader_UsableKeyItem
+ ld de, Jumptable_UseGiveTossRegisterQuit
+ jr .build_menu
+
+.selectable_usable
+ ld hl, MenuHeader_UsableItem
+ ld de, Jumptable_UseGiveTossQuit
+ jr .build_menu
+
+.tossable_selectable
+ ld hl, MenuHeader_UnusableItem
+ ld de, Jumptable_UseQuit
+ jr .build_menu
+
+.tossable_unselectable
+ ld hl, MenuHeader_UnusableKeyItem
+ ld de, Jumptable_UseRegisterQuit
+ jr .build_menu
+
+.unusable
+ ld hl, MenuHeader_HoldableKeyItem
+ ld de, Jumptable_GiveTossRegisterQuit
+ jr .build_menu
+
+.selectable_unusable
+ ld hl, MenuHeader_HoldableItem
+ ld de, Jumptable_GiveTossQuit
+.build_menu
+ push de
+ call LoadMenuHeader
+ call VerticalMenu
+ call ExitMenu
+ pop hl
+ ret c
+ ld a, [wMenuCursorY]
+ dec a
+ call Pack_GetJumptablePointer
+ jp hl
+
+; 10249 (4:4249)
+MenuHeader_UsableKeyItem: ; 0x10249
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 13, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x10251
+
+.MenuData: ; 0x10251
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 5 ; items
+ db "USE@"
+ db "GIVE@"
+ db "TOSS@"
+ db "SEL@"
+ db "QUIT@"
+; 0x1026a
+
+Jumptable_UseGiveTossRegisterQuit: ; 1026a
+ dw UseItem
+ dw GiveItem
+ dw TossMenu
+ dw RegisterItem
+ dw QuitItemSubmenu
+; 10274
+
+MenuHeader_UsableItem: ; 0x10274
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 13, 3, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x1027c
+
+.MenuData: ; 0x1027c
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 4 ; items
+ db "USE@"
+ db "GIVE@"
+ db "TOSS@"
+ db "QUIT@"
+; 0x10291
+
+Jumptable_UseGiveTossQuit: ; 10291
+ dw UseItem
+ dw GiveItem
+ dw TossMenu
+ dw QuitItemSubmenu
+; 10299
+
+MenuHeader_UnusableItem: ; 0x10299
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 13, 7, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x102a1
+
+.MenuData: ; 0x102a1
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 2 ; items
+ db "USE@"
+ db "QUIT@"
+; 0x102ac
+
+Jumptable_UseQuit: ; 102ac
+ dw UseItem
+ dw QuitItemSubmenu
+; 102b0
+
+MenuHeader_UnusableKeyItem: ; 0x102b0
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 13, 5, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x102b8
+
+.MenuData: ; 0x102b8
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 3 ; items
+ db "USE@"
+ db "SEL@"
+ db "QUIT@"
+; 0x102c7
+
+Jumptable_UseRegisterQuit: ; 102c7
+ dw UseItem
+ dw RegisterItem
+ dw QuitItemSubmenu
+; 102cd
+
+MenuHeader_HoldableKeyItem: ; 0x102cd
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 13, 3, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x102d5
+
+.MenuData: ; 0x102d5
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 4 ; items
+ db "GIVE@"
+ db "TOSS@"
+ db "SEL@"
+ db "QUIT@"
+; 0x102ea
+
+Jumptable_GiveTossRegisterQuit: ; 102ea
+ dw GiveItem
+ dw TossMenu
+ dw RegisterItem
+ dw QuitItemSubmenu
+; 102f2
+
+MenuHeader_HoldableItem: ; 0x102f2
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 13, 5, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x102fa
+
+.MenuData: ; 0x102fa
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 3 ; items
+ db "GIVE@"
+ db "TOSS@"
+ db "QUIT@"
+; 0x1030b
+
+Jumptable_GiveTossQuit: ; 1030b
+ dw GiveItem
+ dw TossMenu
+ dw QuitItemSubmenu
+
+; 10311
+
+UseItem: ; 10311
+ farcall CheckItemMenu
+ ld a, [wItemAttributeParamBuffer]
+ ld hl, .dw
+ rst JumpTable
+ ret
+; 1031f
+
+.dw ; 1031f (4:431f)
+; entries correspond to ITEMMENU_* constants
+ dw .Oak ; ITEMMENU_NOUSE
+ dw .Oak
+ dw .Oak
+ dw .Oak
+ dw .Current ; ITEMMENU_CURRENT
+ dw .Party ; ITEMMENU_PARTY
+ dw .Field ; ITEMMENU_CLOSE
+; 1035c
+
+.Oak: ; 1032d (4:432d)
+ ld hl, Text_ThisIsntTheTime
+ call Pack_PrintTextNoScroll
+ ret
+
+.Current: ; 10334 (4:4334)
+ call DoItemEffect
+ ret
+
+.Party: ; 10338 (4:4338)
+ ld a, [wPartyCount]
+ and a
+ jr z, .NoPokemon
+ call DoItemEffect
+ xor a
+ ld [hBGMapMode], a
+ call Pack_InitGFX
+ call WaitBGMap_DrawPackGFX
+ call Pack_InitColors
+ ret
+
+.NoPokemon:
+ ld hl, TextJump_YouDontHaveAMon
+ call Pack_PrintTextNoScroll
+ ret
+
+.Field: ; 10355 (4:4355)
+ call DoItemEffect
+ ld a, [wItemEffectSucceeded]
+ and a
+ jr z, .Oak
+ ld a, PACKSTATE_QUITRUNSCRIPT
+ ld [wJumptableIndex], a
+ ret
+; 10364 (4:4364)
+
+TossMenu: ; 10364
+ ld hl, Text_ThrowAwayHowMany
+ call Pack_PrintTextNoScroll
+ farcall SelectQuantityToToss
+ push af
+ call ExitMenu
+ pop af
+ jr c, .finish
+ call Pack_GetItemName
+ ld hl, Text_ConfirmThrowAway
+ call MenuTextBox
+ call YesNoBox
+ push af
+ call ExitMenu
+ pop af
+ jr c, .finish
+ ld hl, wNumItems
+ ld a, [wCurItemQuantity]
+ call TossItem
+ call Pack_GetItemName
+ ld hl, Text_ThrewAway
+ call Pack_PrintTextNoScroll
+.finish
+ ret
+; 1039d
+
+Unreferenced_ResetPocketCursorPositions: ; 1039d
+ ld a, [wCurrPocket]
+ and a ; ITEM_POCKET
+ jr z, .items
+ dec a ; BALL_POCKET
+ jr z, .balls
+ dec a ; KEY_ITEM_POCKET
+ jr z, .key
+ ret
+
+.balls
+ xor a
+ ld [wBallsPocketCursor], a
+ ld [wBallsPocketScrollPosition], a
+ ret
+
+.items
+ xor a
+ ld [wItemsPocketCursor], a
+ ld [wItemsPocketScrollPosition], a
+ ret
+
+.key
+ xor a
+ ld [wKeyItemsPocketCursor], a
+ ld [wKeyItemsPocketScrollPosition], a
+ ret
+; 103c2
+
+RegisterItem: ; 103c2
+ farcall CheckSelectableItem
+ ld a, [wItemAttributeParamBuffer]
+ and a
+ jr nz, .cant_register
+ ld a, [wCurrPocket]
+ rrca
+ rrca
+ and $c0
+ ld b, a
+ ld a, [wCurItemQuantity]
+ inc a
+ and $3f
+ or b
+ ld [wWhichRegisteredItem], a
+ ld a, [wCurItem]
+ ld [wRegisteredItem], a
+ call Pack_GetItemName
+ ld de, SFX_FULL_HEAL
+ call WaitPlaySFX
+ ld hl, Text_RegisteredItem
+ call Pack_PrintTextNoScroll
+ ret
+
+.cant_register
+ ld hl, Text_CantRegister
+ call Pack_PrintTextNoScroll
+ ret
+; 103fd
+
+GiveItem: ; 103fd
+ ld a, [wPartyCount]
+ and a
+ jp z, .NoPokemon
+ ld a, [wOptions]
+ push af
+ res NO_TEXT_SCROLL, a
+ ld [wOptions], a
+ ld a, PARTYMENUACTION_GIVE_ITEM
+ ld [wPartyMenuActionText], a
+ call ClearBGPalettes
+ farcall LoadPartyMenuGFX
+ farcall InitPartyMenuWithCancel
+ farcall InitPartyMenuGFX
+.loop
+ farcall WritePartyMenuTilemap
+ farcall PrintPartyMenuText
+ call WaitBGMap
+ call SetPalettes
+ call DelayFrame
+ farcall PartyMenuSelect
+ jr c, .finish
+ ld a, [wCurPartySpecies]
+ cp EGG
+ jr nz, .give
+ ld hl, .Egg
+ call PrintText
+ jr .loop
+
+.give
+ ld a, [wJumptableIndex]
+ push af
+ ld a, [wPackJumptableIndex]
+ push af
+ call GetCurNick
+ ld hl, wStringBuffer1
+ ld de, wMonOrItemNameBuffer
+ ld bc, MON_NAME_LENGTH
+ call CopyBytes
+ call TryGiveItemToPartymon
+ pop af
+ ld [wPackJumptableIndex], a
+ pop af
+ ld [wJumptableIndex], a
+.finish
+ pop af
+ ld [wOptions], a
+ xor a
+ ld [hBGMapMode], a
+ call Pack_InitGFX
+ call WaitBGMap_DrawPackGFX
+ call Pack_InitColors
+ ret
+
+.NoPokemon: ; 10486 (4:4486)
+ ld hl, TextJump_YouDontHaveAMon
+ call Pack_PrintTextNoScroll
+ ret
+; 1048d (4:448d)
+.Egg: ; 0x1048d
+ ; An EGG can't hold an item.
+ text_jump Text_AnEGGCantHoldAnItem
+ db "@"
+; 0x10492
+
+QuitItemSubmenu: ; 10492
+ ret
+; 10493
+
+BattlePack: ; 10493
+ ld hl, wOptions
+ set NO_TEXT_SCROLL, [hl]
+ call InitPackBuffers
+.loop
+ call JoyTextDelay
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .end
+ call .RunJumptable
+ call DelayFrame
+ jr .loop
+
+.end
+ ld a, [wCurrPocket]
+ ld [wLastPocket], a
+ ld hl, wOptions
+ res NO_TEXT_SCROLL, [hl]
+ ret
+; 104b9
+
+.RunJumptable: ; 104b9
+ ld a, [wJumptableIndex]
+ ld hl, .Jumptable
+ call Pack_GetJumptablePointer
+ jp hl
+
+; 104c3
+
+.Jumptable: ; 104c3 (4:44c3)
+; entries correspond to PACKSTATE_* constants
+ dw .InitGFX ; 0
+ dw .InitItemsPocket ; 1
+ dw .ItemsPocketMenu ; 2
+ dw .InitBallsPocket ; 3
+ dw .BallsPocketMenu ; 4
+ dw .InitKeyItemsPocket ; 5
+ dw .KeyItemsPocketMenu ; 6
+ dw .InitTMHMPocket ; 7
+ dw .TMHMPocketMenu ; 8
+ dw Pack_QuitNoScript ; 9
+ dw Pack_QuitRunScript ; 10
+
+.InitGFX: ; 104d9 (4:44d9)
+ xor a
+ ld [hBGMapMode], a
+ call Pack_InitGFX
+ ld a, [wPackJumptableIndex]
+ ld [wJumptableIndex], a
+ call Pack_InitColors
+ ret
+
+.InitItemsPocket: ; 104e9 (4:44e9)
+ xor a ; ITEM_POCKET
+ ld [wCurrPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ call WaitBGMap_DrawPackGFX
+ call Pack_JumptableNext
+ ret
+
+.ItemsPocketMenu: ; 104fa (4:44fa)
+ ld hl, ItemsPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wItemsPocketCursor]
+ ld [wMenuCursorBuffer], a
+ ld a, [wItemsPocketScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wItemsPocketScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wItemsPocketCursor], a
+ ld b, PACKSTATE_INITTMHMPOCKET ; left
+ ld c, PACKSTATE_INITBALLSPOCKET ; right
+ call Pack_InterpretJoypad
+ ret c
+ call ItemSubmenu
+ ret
+
+.InitKeyItemsPocket: ; 10527 (4:4527)
+ ld a, KEY_ITEM_POCKET
+ ld [wCurrPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ call WaitBGMap_DrawPackGFX
+ call Pack_JumptableNext
+ ret
+
+.KeyItemsPocketMenu: ; 10539 (4:4539)
+ ld hl, KeyItemsPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wKeyItemsPocketCursor]
+ ld [wMenuCursorBuffer], a
+ ld a, [wKeyItemsPocketScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wKeyItemsPocketScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wKeyItemsPocketCursor], a
+ ld b, PACKSTATE_INITBALLSPOCKET ; left
+ ld c, PACKSTATE_INITTMHMPOCKET ; right
+ call Pack_InterpretJoypad
+ ret c
+ call ItemSubmenu
+ ret
+
+.InitTMHMPocket: ; 10566 (4:4566)
+ ld a, TM_HM_POCKET
+ ld [wCurrPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ xor a
+ ld [hBGMapMode], a
+ call WaitBGMap_DrawPackGFX
+ ld hl, Text_PackEmptyString
+ call Pack_PrintTextNoScroll
+ call Pack_JumptableNext
+ ret
+
+.TMHMPocketMenu: ; 10581 (4:4581)
+ farcall TMHMPocket
+ ld b, PACKSTATE_INITKEYITEMSPOCKET ; left
+ ld c, PACKSTATE_INITITEMSPOCKET ; right
+ call Pack_InterpretJoypad
+ ret c
+ xor a
+ call TMHMSubmenu
+ ret
+
+.InitBallsPocket: ; 10594 (4:4594)
+ ld a, BALL_POCKET
+ ld [wCurrPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ call WaitBGMap_DrawPackGFX
+ call Pack_JumptableNext
+ ret
+
+.BallsPocketMenu: ; 105a6 (4:45a6)
+ ld hl, BallsPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wBallsPocketCursor]
+ ld [wMenuCursorBuffer], a
+ ld a, [wBallsPocketScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wBallsPocketScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wBallsPocketCursor], a
+ ld b, PACKSTATE_INITITEMSPOCKET ; left
+ ld c, PACKSTATE_INITKEYITEMSPOCKET ; right
+ call Pack_InterpretJoypad
+ ret c
+ call ItemSubmenu
+ ret
+
+ItemSubmenu: ; 105d3 (4:45d3)
+ farcall CheckItemContext
+ ld a, [wItemAttributeParamBuffer]
+TMHMSubmenu: ; 105dc (4:45dc)
+ and a
+ jr z, .NoUse
+ ld hl, .UsableMenuHeader
+ ld de, .UsableJumptable
+ jr .proceed
+
+.NoUse:
+ ld hl, .UnusableMenuHeader
+ ld de, .UnusableJumptable
+.proceed
+ push de
+ call LoadMenuHeader
+ call VerticalMenu
+ call ExitMenu
+ pop hl
+ ret c
+ ld a, [wMenuCursorY]
+ dec a
+ call Pack_GetJumptablePointer
+ jp hl
+
+; 10601 (4:4601)
+.UsableMenuHeader: ; 0x10601
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 13, 7, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .UsableMenuData
+ db 1 ; default option
+; 0x10609
+
+.UsableMenuData: ; 0x10609
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 2 ; items
+ db "USE@"
+ db "QUIT@"
+; 0x10614
+
+.UsableJumptable: ; 10614
+ dw .Use
+ dw .Quit
+; 10618
+
+.UnusableMenuHeader: ; 0x10618
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 13, 9, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .UnusableMenuData
+ db 1 ; default option
+; 0x10620
+
+.UnusableMenuData: ; 0x10620
+ db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+ db 1 ; items
+ db "QUIT@"
+; 0x10627
+
+.UnusableJumptable: ; 10627
+ dw .Quit
+; 10629
+
+.Use: ; 10629
+ farcall CheckItemContext
+ ld a, [wItemAttributeParamBuffer]
+ ld hl, .ItemFunctionJumptable
+ rst JumpTable
+ ret
+
+.ItemFunctionJumptable: ; 10637 (4:4637)
+; entries correspond to ITEMMENU_* constants
+ dw .Oak ; ITEMMENU_NOUSE
+ dw .Oak
+ dw .Oak
+ dw .Oak
+ dw .Unused ; ITEMMENU_CURRENT
+ dw .BattleField ; ITEMMENU_PARTY
+ dw .BattleOnly ; ITEMMENU_CLOSE
+
+.Oak: ; 10645 (4:4645)
+ ld hl, Text_ThisIsntTheTime
+ call Pack_PrintTextNoScroll
+ ret
+
+.Unused: ; 1064c (4:464c)
+ call DoItemEffect
+ ld a, [wItemEffectSucceeded]
+ and a
+ jr nz, .ReturnToBattle
+ ret
+
+.BattleField: ; 10656 (4:4656)
+ call DoItemEffect
+ ld a, [wItemEffectSucceeded]
+ and a
+ jr nz, .quit_run_script
+ xor a
+ ld [hBGMapMode], a
+ call Pack_InitGFX
+ call WaitBGMap_DrawPackGFX
+ call Pack_InitColors
+ ret
+
+.ReturnToBattle: ; 1066c (4:466c)
+ call ClearBGPalettes
+ jr .quit_run_script
+
+.BattleOnly: ; 10671 (4:4671)
+ call DoItemEffect
+ ld a, [wItemEffectSucceeded]
+ and a
+ jr z, .Oak
+ cp $2
+ jr z, .didnt_use_item
+.quit_run_script ; 1067e (4:467e)
+ ld a, PACKSTATE_QUITRUNSCRIPT
+ ld [wJumptableIndex], a
+ ret
+
+.didnt_use_item ; 10684 (4:4684)
+ xor a
+ ld [wItemEffectSucceeded], a
+ ret
+; 10689 (4:4689)
+.Quit: ; 10689
+ ret
+; 1068a
+
+InitPackBuffers: ; 1068a
+ xor a
+ ld [wJumptableIndex], a
+ ; pocket id -> jumptable index
+ ld a, [wLastPocket]
+ maskbits NUM_POCKETS
+ ld [wCurrPocket], a
+ inc a
+ add a
+ dec a
+ ld [wPackJumptableIndex], a
+ xor a ; FALSE
+ ld [wPackUsedItem], a
+ xor a
+ ld [wSwitchItem], a
+ ret
+; 106a5
+
+DepositSellInitPackBuffers: ; 106a5
+ xor a
+ ld [hBGMapMode], a
+ ld [wJumptableIndex], a ; PACKSTATE_INITGFX
+ ld [wPackJumptableIndex], a ; PACKSTATE_INITGFX
+ ld [wCurrPocket], a ; ITEM_POCKET
+ ld [wPackUsedItem], a
+ ld [wSwitchItem], a
+ call Pack_InitGFX
+ call Pack_InitColors
+ ret
+; 106be
+
+DepositSellPack: ; 106be
+.loop
+ call .RunJumptable
+ call DepositSellTutorial_InterpretJoypad
+ jr c, .loop
+ ret
+; 106c7
+
+.RunJumptable: ; 106c7
+ ld a, [wJumptableIndex]
+ ld hl, .Jumptable
+ call Pack_GetJumptablePointer
+ jp hl
+
+; 106d1
+
+.Jumptable: ; 106d1 (4:46d1)
+; entries correspond to *_POCKET constants
+ dw .ItemsPocket
+ dw .BallsPocket
+ dw .KeyItemsPocket
+ dw .TMHMPocket
+
+.ItemsPocket: ; 106d9 (4:46d9)
+ xor a ; ITEM_POCKET
+ call InitPocket
+ ld hl, PC_Mart_ItemsPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wItemsPocketCursor]
+ ld [wMenuCursorBuffer], a
+ ld a, [wItemsPocketScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wItemsPocketScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wItemsPocketCursor], a
+ ret
+
+.KeyItemsPocket: ; 106ff (4:46ff)
+ ld a, KEY_ITEM_POCKET
+ call InitPocket
+ ld hl, PC_Mart_KeyItemsPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wKeyItemsPocketCursor]
+ ld [wMenuCursorBuffer], a
+ ld a, [wKeyItemsPocketScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wKeyItemsPocketScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wKeyItemsPocketCursor], a
+ ret
+
+.TMHMPocket: ; 10726 (4:4726)
+ ld a, TM_HM_POCKET
+ call InitPocket
+ call WaitBGMap_DrawPackGFX
+ farcall TMHMPocket
+ ld a, [wCurItem]
+ ld [wCurItem], a
+ ret
+
+.BallsPocket: ; 1073b (4:473b)
+ ld a, BALL_POCKET
+ call InitPocket
+ ld hl, PC_Mart_BallsPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wBallsPocketCursor]
+ ld [wMenuCursorBuffer], a
+ ld a, [wBallsPocketScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wBallsPocketScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wBallsPocketCursor], a
+ ret
+
+InitPocket: ; 10762 (4:4762)
+ ld [wCurrPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ call WaitBGMap_DrawPackGFX
+ ret
+
+DepositSellTutorial_InterpretJoypad: ; 1076f
+ ld hl, wMenuJoypad
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .a_button
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .b_button
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .d_left
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, .d_right
+ scf
+ ret
+
+.a_button
+ ld a, TRUE
+ ld [wPackUsedItem], a
+ and a
+ ret
+
+.b_button
+ xor a ; FALSE
+ ld [wPackUsedItem], a
+ and a
+ ret
+
+.d_left
+ ld a, [wJumptableIndex]
+ dec a
+ maskbits NUM_POCKETS
+ ld [wJumptableIndex], a
+ push de
+ ld de, SFX_SWITCH_POCKETS
+ call PlaySFX
+ pop de
+ scf
+ ret
+
+.d_right
+ ld a, [wJumptableIndex]
+ inc a
+ maskbits NUM_POCKETS
+ ld [wJumptableIndex], a
+ push de
+ ld de, SFX_SWITCH_POCKETS
+ call PlaySFX
+ pop de
+ scf
+ ret
+; 107bb
+
+TutorialPack: ; 107bb
+ call DepositSellInitPackBuffers
+ ld a, [wInputType]
+ or a
+ jr z, .loop
+ farcall _DudeAutoInput_RightA
+.loop
+ call .RunJumptable
+ call DepositSellTutorial_InterpretJoypad
+ jr c, .loop
+ xor a ; FALSE
+ ld [wPackUsedItem], a
+ ret
+; 107d7
+
+.RunJumptable: ; 107d7
+ ld a, [wJumptableIndex]
+ ld hl, .dw
+ call Pack_GetJumptablePointer
+ jp hl
+
+; 107e1
+
+.dw ; 107e1 (4:47e1)
+; entries correspond to *_POCKET constants
+ dw .Items
+ dw .Balls
+ dw .KeyItems
+ dw .TMHM
+
+.Items: ; 107e9 (4:47e9)
+ xor a ; ITEM_POCKET
+ ld hl, .ItemsMenuHeader
+ jr .DisplayPocket
+
+; 107ef (4:47ef)
+.ItemsMenuHeader: ; 0x107ef
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .ItemsMenuData
+ db 1 ; default option
+; 0x107f7
+
+.ItemsMenuData: ; 0x107f7
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags
+ db 5, 8 ; rows, columns
+ db 2 ; horizontal spacing
+ dbw 0, wDudeNumItems
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+; 10807
+
+.KeyItems: ; 10807 (4:4807)
+ ld a, KEY_ITEM_POCKET
+ ld hl, .KeyItemsMenuHeader
+ jr .DisplayPocket
+
+; 1080e (4:480e)
+.KeyItemsMenuHeader: ; 0x1080e
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .KeyItemsMenuData
+ db 1 ; default option
+; 0x10816
+
+.KeyItemsMenuData: ; 0x10816
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags
+ db 5, 8 ; rows, columns
+ db 1 ; horizontal spacing
+ dbw 0, wDudeNumKeyItems
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+; 10826
+
+.TMHM: ; 10826 (4:4826)
+ ld a, TM_HM_POCKET
+ call InitPocket
+ call WaitBGMap_DrawPackGFX
+ farcall TMHMPocket
+ ld a, [wCurItem]
+ ld [wCurItem], a
+ ret
+
+.Balls: ; 1083b (4:483b)
+ ld a, BALL_POCKET
+ ld hl, .BallsMenuHeader
+ jr .DisplayPocket
+
+; 10842 (4:4842)
+.BallsMenuHeader: ; 0x10842
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .BallsMenuData
+ db 1 ; default option
+; 0x1084a
+
+.BallsMenuData: ; 0x1084a
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags
+ db 5, 8 ; rows, columns
+ db 2 ; horizontal spacing
+ dbw 0, wDudeNumBalls
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+; 1085a
+
+.DisplayPocket: ; 1085a (4:485a)
+ push hl
+ call InitPocket
+ pop hl
+ call CopyMenuHeader
+ call ScrollingMenu
+ ret
+
+Pack_JumptableNext: ; 10866 (4:4866)
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+Pack_GetJumptablePointer: ; 1086b
+ ld e, a
+ ld d, 0
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ret
+; 10874
+
+Pack_QuitNoScript: ; 10874 (4:4874)
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ xor a ; FALSE
+ ld [wPackUsedItem], a
+ ret
+
+Pack_QuitRunScript: ; 1087e (4:487e)
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ld a, TRUE
+ ld [wPackUsedItem], a
+ ret
+
+Pack_PrintTextNoScroll: ; 10889 (4:4889)
+ ld a, [wOptions]
+ push af
+ set NO_TEXT_SCROLL, a
+ ld [wOptions], a
+ call PrintText
+ pop af
+ ld [wOptions], a
+ ret
+
+WaitBGMap_DrawPackGFX: ; 1089a (4:489a)
+ call WaitBGMap
+DrawPackGFX: ; 1089d
+ ld a, [wCurrPocket]
+ maskbits NUM_POCKETS
+ ld e, a
+ ld d, $0
+ ld a, [wBattleType]
+ cp BATTLETYPE_TUTORIAL
+ jr z, .male_dude
+ ld a, [wPlayerGender]
+ bit PLAYERGENDER_FEMALE_F, a
+ jr nz, .female
+.male_dude
+ ld hl, PackGFXPointers
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld e, a
+ ld d, [hl]
+ ld hl, vTiles2 tile $50
+ lb bc, BANK(PackGFX), 15
+ call Request2bpp
+ ret
+
+.female
+ farcall DrawKrisPackGFX
+ ret
+; 108cc
+
+PackGFXPointers: ; 108cc
+ dw PackGFX + (15 tiles) * 1 ; ITEM_POCKET
+ dw PackGFX + (15 tiles) * 3 ; BALL_POCKET
+ dw PackGFX + (15 tiles) * 0 ; KEY_ITEM_POCKET
+ dw PackGFX + (15 tiles) * 2 ; TM_HM_POCKET
+; 108d4
+
+Pack_InterpretJoypad: ; 108d4 (4:48d4)
+ ld hl, wMenuJoypad
+ ld a, [wSwitchItem]
+ and a
+ jr nz, .switching_item
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .a_button
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .b_button
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .d_left
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, .d_right
+ ld a, [hl]
+ and SELECT
+ jr nz, .select
+ scf
+ ret
+
+.a_button
+ and a
+ ret
+
+.b_button
+ ld a, PACKSTATE_QUITNOSCRIPT
+ ld [wJumptableIndex], a
+ scf
+ ret
+
+.d_left
+ ld a, b
+ ld [wJumptableIndex], a
+ ld [wPackJumptableIndex], a
+ push de
+ ld de, SFX_SWITCH_POCKETS
+ call PlaySFX
+ pop de
+ scf
+ ret
+
+.d_right
+ ld a, c
+ ld [wJumptableIndex], a
+ ld [wPackJumptableIndex], a
+ push de
+ ld de, SFX_SWITCH_POCKETS
+ call PlaySFX
+ pop de
+ scf
+ ret
+
+.select
+ farcall SwitchItemsInBag
+ ld hl, Text_MoveItemWhere
+ call Pack_PrintTextNoScroll
+ scf
+ ret
+
+.switching_item
+ ld a, [hl]
+ and A_BUTTON | SELECT
+ jr nz, .place_insert
+ ld a, [hl]
+ and B_BUTTON
+ jr nz, .end_switch
+ scf
+ ret
+
+.place_insert
+ farcall SwitchItemsInBag
+ ld de, SFX_SWITCH_POKEMON
+ call WaitPlaySFX
+ ld de, SFX_SWITCH_POKEMON
+ call WaitPlaySFX
+.end_switch
+ xor a
+ ld [wSwitchItem], a
+ scf
+ ret
+
+Pack_InitGFX: ; 10955
+ call ClearBGPalettes
+ call ClearTileMap
+ call ClearSprites
+ call DisableLCD
+ ld hl, PackMenuGFX
+ ld de, vTiles2
+ ld bc, $60 tiles
+ ld a, BANK(PackMenuGFX)
+ call FarCopyBytes
+; Background (blue if male, pink if female)
+ hlcoord 0, 1
+ ld bc, 11 * SCREEN_WIDTH
+ ld a, $24
+ call ByteFill
+; This is where the items themselves will be listed.
+ hlcoord 5, 1
+ lb bc, 11, 15
+ call ClearBox
+; ◀▶ POCKET ▼▲ ITEMS
+ hlcoord 0, 0
+ ld a, $28
+ ld c, SCREEN_WIDTH
+.loop
+ ld [hli], a
+ inc a
+ dec c
+ jr nz, .loop
+ call DrawPocketName
+ call PlacePackGFX
+; Place the textbox for displaying the item description
+ hlcoord 0, SCREEN_HEIGHT - 4 - 2
+ lb bc, 4, SCREEN_WIDTH - 2
+ call TextBox
+ call EnableLCD
+ call DrawPackGFX
+ ret
+; 109a5
+
+PlacePackGFX: ; 109a5
+ hlcoord 0, 3
+ ld a, $50
+ ld de, SCREEN_WIDTH - 5
+ ld b, 3
+.row
+ ld c, 5
+.column
+ ld [hli], a
+ inc a
+ dec c
+ jr nz, .column
+ add hl, de
+ dec b
+ jr nz, .row
+ ret
+; 109bb
+
+DrawPocketName: ; 109bb
+ ld a, [wCurrPocket]
+ ; * 15
+ ld d, a
+ swap a
+ sub d
+ ld d, 0
+ ld e, a
+ ld hl, .tilemap
+ add hl, de
+ ld d, h
+ ld e, l
+ hlcoord 0, 7
+ ld c, 3
+.row
+ ld b, 5
+.col
+ ld a, [de]
+ inc de
+ ld [hli], a
+ dec b
+ jr nz, .col
+ ld a, c
+ ld c, SCREEN_WIDTH - 5
+ add hl, bc
+ ld c, a
+ dec c
+ jr nz, .row
+ ret
+; 109e1
+
+.tilemap ; 109e1
+; ITEM_POCKET
+ db $00, $04, $04, $04, $01 ; top border
+ db $06, $07, $08, $09, $0a ; Items
+ db $02, $05, $05, $05, $03 ; bottom border
+; BALL_POCKET
+ db $00, $04, $04, $04, $01 ; top border
+ db $15, $16, $17, $18, $19 ; Balls
+ db $02, $05, $05, $05, $03 ; bottom border
+; KEY_ITEM_POCKET
+ db $00, $04, $04, $04, $01 ; top border
+ db $0b, $0c, $0d, $0e, $0f ; Key Items
+ db $02, $05, $05, $05, $03 ; bottom border
+; TM_HM_POCKET
+ db $00, $04, $04, $04, $01 ; top border
+ db $10, $11, $12, $13, $14 ; TM/HM
+ db $02, $05, $05, $05, $03 ; bottom border
+; 10a1d
+
+Pack_GetItemName: ; 10a1d
+ ld a, [wCurItem]
+ ld [wNamedObjectIndexBuffer], a
+ call GetItemName
+ call CopyName1
+ ret
+; 10a2a
+
+Unreferenced_Pack_ClearTilemap: ; 10a2a
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ ld a, " "
+ call ByteFill
+ ret
+; 10a36
+
+ClearPocketList: ; 10a36 (4:4a36)
+ hlcoord 5, 2
+ lb bc, 10, SCREEN_WIDTH - 5
+ call ClearBox
+ ret
+
+Pack_InitColors: ; 10a40
+ call WaitBGMap
+ ld b, SCGB_PACKPALS
+ call GetSGBLayout
+ call SetPalettes
+ call DelayFrame
+ ret
+; 10a4f
+
+ItemsPocketMenuHeader: ; 0x10a4f
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x10a57
+
+.MenuData: ; 0x10a57
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags
+ db 5, 8 ; rows, columns
+ db 2 ; horizontal spacing
+ dbw 0, wNumItems
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+; 10a67
+
+PC_Mart_ItemsPocketMenuHeader: ; 0x10a67
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x10a6f
+
+.MenuData: ; 0x10a6f
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP ; flags
+ db 5, 8 ; rows, columns
+ db 2 ; horizontal spacing
+ dbw 0, wNumItems
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+; 10a7f
+
+KeyItemsPocketMenuHeader: ; 0x10a7f
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x10a87
+
+.MenuData: ; 0x10a87
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags
+ db 5, 8 ; rows, columns
+ db 1 ; horizontal spacing
+ dbw 0, wNumKeyItems
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+; 10a97
+
+PC_Mart_KeyItemsPocketMenuHeader: ; 0x10a97
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x10a9f
+
+.MenuData: ; 0x10a9f
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP ; flags
+ db 5, 8 ; rows, columns
+ db 1 ; horizontal spacing
+ dbw 0, wNumKeyItems
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+; 10aaf
+
+BallsPocketMenuHeader: ; 0x10aaf
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x10ab7
+
+.MenuData: ; 0x10ab7
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags
+ db 5, 8 ; rows, columns
+ db 2 ; horizontal spacing
+ dbw 0, wNumBalls
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+; 10ac7
+
+PC_Mart_BallsPocketMenuHeader: ; 0x10ac7
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x10acf
+
+.MenuData: ; 0x10acf
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP ; flags
+ db 5, 8 ; rows, columns
+ db 2 ; horizontal spacing
+ dbw 0, wNumBalls
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+; 10adf
+
+Text_PackNoItems: ; 0x10adf
+ ; No items.
+ text_jump UnknownText_0x1c0b9a
+ db "@"
+; 0x10ae4
+
+Text_ThrowAwayHowMany: ; 0x10ae4
+ ; Throw away how many?
+ text_jump UnknownText_0x1c0ba5
+ db "@"
+; 0x10ae9
+
+Text_ConfirmThrowAway: ; 0x10ae9
+ ; Throw away @ @ (S)?
+ text_jump UnknownText_0x1c0bbb
+ db "@"
+; 0x10aee
+
+Text_ThrewAway: ; 0x10aee
+ ; Threw away @ (S).
+ text_jump UnknownText_0x1c0bd8
+ db "@"
+; 0x10af3
+
+Text_ThisIsntTheTime: ; 0x10af3
+ ; OAK: ! This isn't the time to use that!
+ text_jump UnknownText_0x1c0bee
+ db "@"
+; 0x10af8
+
+TextJump_YouDontHaveAMon: ; 0x10af8
+ ; You don't have a #MON!
+ text_jump Text_YouDontHaveAMon
+ db "@"
+; 0x10afd
+
+Text_RegisteredItem: ; 0x10afd
+ ; Registered the @ .
+ text_jump UnknownText_0x1c0c2e
+ db "@"
+; 0x10b02
+
+Text_CantRegister: ; 0x10b02
+ ; You can't register that item.
+ text_jump UnknownText_0x1c0c45
+ db "@"
+; 0x10b07
+
+Text_MoveItemWhere: ; 0x10b07
+ ; Where should this be moved to?
+ text_jump UnknownText_0x1c0c63
+ db "@"
+; 0x10b0c
+
+Text_PackEmptyString: ; 0x10b0c
+ ;
+ text_jump UnknownText_0x1c0c83
+ db "@"
+; 0x10b11
+
+TextJump_YouCantUseItInABattle: ; 0x10b11
+ ; Doesn't seem to be used anywhere
+ ; "You can't use it in a battle."
+ text_jump Text_YouCantUseItInABattle
+ db "@"
+; 0x10b16
+
+PackMenuGFX:
+INCBIN "gfx/pack/pack_menu.2bpp"
+PackGFX:
+INCBIN "gfx/pack/pack.2bpp"
diff --git a/engine/menu/scrolling_menu.asm b/engine/menu/scrolling_menu.asm
new file mode 100755
index 000000000..3be3d839c
--- /dev/null
+++ b/engine/menu/scrolling_menu.asm
@@ -0,0 +1,543 @@
+_InitScrollingMenu:: ; 245af
+ xor a
+ ld [wMenuJoypad], a
+ ld [hBGMapMode], a
+ inc a
+ ld [hInMenu], a
+ call InitScrollingMenuCursor
+ call ScrollingMenu_InitFlags
+ call ScrollingMenu_ValidateSwitchItem
+ call ScrollingMenu_InitDisplay
+ call ApplyTilemap
+ xor a
+ ld [hBGMapMode], a
+ ret
+; 245cb
+
+_ScrollingMenu:: ; 245cb
+.loop
+ call ScrollingMenuJoyAction
+ jp c, .exit
+ call z, .zero
+ jr .loop
+; 245d6
+
+.exit ; 245d6
+ call MenuClickSound
+ ld [wMenuJoypad], a
+ ld a, 0
+ ld [hInMenu], a
+ ret
+; 245e1
+
+.zero ; 245e1
+ call ScrollingMenu_InitDisplay
+ ld a, 1
+ ld [hBGMapMode], a
+ ld c, 3
+ call DelayFrames
+ xor a
+ ld [hBGMapMode], a
+ ret
+; 245f1
+
+ScrollingMenu_InitDisplay: ; 245f1
+ xor a
+ ld [hBGMapMode], a
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ call ScrollingMenu_UpdateDisplay
+ call ScrollingMenu_PlaceCursor
+ call ScrollingMenu_CheckCallFunction3
+ pop af
+ ld [wOptions], a
+ ret
+; 24609
+
+ScrollingMenuJoyAction: ; 24609
+.loop
+ call ScrollingMenuJoypad
+ ld a, [hJoyLast]
+ and D_PAD
+ ld b, a
+ ld a, [hJoyPressed]
+ and BUTTONS
+ or b
+ bit A_BUTTON_F, a
+ jp nz, .a_button
+ bit B_BUTTON_F, a
+ jp nz, .b_button
+ bit SELECT_F, a
+ jp nz, .select
+ bit START_F, a
+ jp nz, .start
+ bit D_RIGHT_F, a
+ jp nz, .d_right
+ bit D_LEFT_F, a
+ jp nz, .d_left
+ bit D_UP_F, a
+ jp nz, .d_up
+ bit D_DOWN_F, a
+ jp nz, .d_down
+ jr .loop
+; 24640
+
+.unreferenced ; unused
+ ld a, -1
+ and a
+ ret
+; 24644
+
+.a_button ; 24644
+ call PlaceHollowCursor
+ ld a, [wMenuCursorY]
+ dec a
+ call ScrollingMenu_GetListItemCoordAndFunctionArgs
+ ld a, [wMenuSelection]
+ ld [wCurItem], a
+ ld a, [wMenuSelectionQuantity]
+ ld [wItemQuantityBuffer], a
+ call ScrollingMenu_GetCursorPosition
+ dec a
+ ld [wScrollingMenuCursorPosition], a
+ ld [wCurItemQuantity], a
+ ld a, [wMenuSelection]
+ cp -1
+ jr z, .b_button
+ ld a, A_BUTTON
+ scf
+ ret
+; 2466f
+
+.b_button ; 2466f
+ ld a, B_BUTTON
+ scf
+ ret
+; 24673
+
+.select ; 24673
+ ld a, [wMenuDataFlags]
+ bit 7, a
+ jp z, xor_a_dec_a
+ ld a, [wMenuCursorY]
+ dec a
+ call ScrollingMenu_GetListItemCoordAndFunctionArgs
+ ld a, [wMenuSelection]
+ cp -1
+ jp z, xor_a_dec_a
+ call ScrollingMenu_GetCursorPosition
+ dec a
+ ld [wScrollingMenuCursorPosition], a
+ ld a, SELECT
+ scf
+ ret
+; 24695
+
+.start ; 24695
+ ld a, [wMenuDataFlags]
+ bit 6, a
+ jp z, xor_a_dec_a
+ ld a, START
+ scf
+ ret
+; 246a1
+
+.d_left ; 246a1
+ ld hl, w2DMenuFlags2
+ bit 7, [hl]
+ jp z, xor_a_dec_a
+ ld a, [wMenuDataFlags]
+ bit 3, a
+ jp z, xor_a_dec_a
+ ld a, D_LEFT
+ scf
+ ret
+; 246b5
+
+.d_right ; 246b5
+ ld hl, w2DMenuFlags2
+ bit 7, [hl]
+ jp z, xor_a_dec_a
+ ld a, [wMenuDataFlags]
+ bit 2, a
+ jp z, xor_a_dec_a
+ ld a, D_RIGHT
+ scf
+ ret
+; 246c9
+
+.d_up ; 246c9
+ ld hl, w2DMenuFlags2
+ bit 7, [hl]
+ jp z, xor_a
+ ld hl, wMenuScrollPosition
+ ld a, [hl]
+ and a
+ jr z, .xor_dec_up
+ dec [hl]
+ jp xor_a
+
+.xor_dec_up
+ jp xor_a_dec_a
+; 246df
+
+.d_down ; 246df
+ ld hl, w2DMenuFlags2
+ bit 7, [hl]
+ jp z, xor_a
+ ld hl, wMenuScrollPosition
+ ld a, [wMenuData_ScrollingMenuHeight]
+ add [hl]
+ ld b, a
+ ld a, [wScrollingMenuListSize]
+ cp b
+ jr c, .xor_dec_down
+ inc [hl]
+ jp xor_a
+
+.xor_dec_down
+ jp xor_a_dec_a
+; 246fc
+
+ScrollingMenu_GetCursorPosition: ; 246fc
+ ld a, [wMenuScrollPosition]
+ ld c, a
+ ld a, [wMenuCursorY]
+ add c
+ ld c, a
+ ret
+; 24706
+
+ScrollingMenu_ClearLeftColumn: ; 24706 (9:4706)
+ call MenuBoxCoord2Tile
+ ld de, SCREEN_WIDTH
+ add hl, de
+ ld de, 2 * SCREEN_WIDTH
+ ld a, [wMenuData_ScrollingMenuHeight]
+.loop
+ ld [hl], " "
+ add hl, de
+ dec a
+ jr nz, .loop
+ ret
+
+InitScrollingMenuCursor: ; 2471a
+ ld hl, wMenuData_ItemsPointerAddr
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wMenuData_ItemsPointerBank]
+ call GetFarByte
+ ld [wScrollingMenuListSize], a
+ ld a, [wMenuData_ScrollingMenuHeight]
+ ld c, a
+ ld a, [wMenuScrollPosition]
+ add c
+ ld c, a
+ ld a, [wScrollingMenuListSize]
+ inc a
+ cp c
+ jr nc, .skip
+ ld a, [wMenuData_ScrollingMenuHeight]
+ ld c, a
+ ld a, [wScrollingMenuListSize]
+ inc a
+ sub c
+ jr nc, .store
+ xor a
+
+.store
+ ld [wMenuScrollPosition], a
+
+.skip
+ ld a, [wMenuScrollPosition]
+ ld c, a
+ ld a, [wMenuCursorBuffer]
+ add c
+ ld b, a
+ ld a, [wScrollingMenuListSize]
+ inc a
+ cp b
+ jr c, .asm_2475a
+ jr nc, .asm_24763
+
+.asm_2475a
+ xor a
+ ld [wMenuScrollPosition], a
+ ld a, $1
+ ld [wMenuCursorBuffer], a
+
+.asm_24763
+ ret
+; 24764
+
+ScrollingMenu_InitFlags: ; 24764
+ ld a, [wMenuDataFlags]
+ ld c, a
+ ld a, [wScrollingMenuListSize]
+ ld b, a
+ ld a, [wMenuBorderTopCoord]
+ add 1
+ ld [w2DMenuCursorInitY], a
+ ld a, [wMenuBorderLeftCoord]
+ add 0
+ ld [w2DMenuCursorInitX], a
+ ld a, [wMenuData_ScrollingMenuHeight]
+ cp b
+ jr c, .no_extra_row
+ jr z, .no_extra_row
+ ld a, b
+ inc a
+.no_extra_row
+ ld [w2DMenuNumRows], a
+ ld a, 1
+ ld [w2DMenuNumCols], a
+ ld a, $8c
+ bit 2, c
+ jr z, .skip_set_0
+ set 0, a
+
+.skip_set_0
+ bit 3, c
+ jr z, .skip_set_1
+ set 1, a
+
+.skip_set_1
+ ld [w2DMenuFlags1], a
+ xor a
+ ld [w2DMenuFlags2], a
+ ld a, $20
+ ld [w2DMenuCursorOffsets], a
+ ld a, A_BUTTON | B_BUTTON | D_UP | D_DOWN
+ bit 7, c
+ jr z, .disallow_select
+ add SELECT
+
+.disallow_select
+ bit 6, c
+ jr z, .disallow_start
+ add START
+
+.disallow_start
+ ld [wMenuJoypadFilter], a
+ ld a, [w2DMenuNumRows]
+ ld b, a
+ ld a, [wMenuCursorBuffer]
+ and a
+ jr z, .reset_cursor
+ cp b
+ jr z, .cursor_okay
+ jr c, .cursor_okay
+
+.reset_cursor
+ ld a, 1
+
+.cursor_okay
+ ld [wMenuCursorY], a
+ ld a, 1
+ ld [wMenuCursorX], a
+ xor a
+ ld [wCursorCurrentTile], a
+ ld [wCursorCurrentTile + 1], a
+ ld [wCursorOffCharacter], a
+ ret
+; 247dd
+
+ScrollingMenu_ValidateSwitchItem: ; 247dd
+ ld a, [wScrollingMenuListSize]
+ ld c, a
+ ld a, [wSwitchItem]
+ and a
+ jr z, .done
+ dec a
+ cp c
+ jr c, .done
+ xor a
+ ld [wSwitchItem], a
+
+.done
+ ret
+; 247f0
+
+ScrollingMenu_UpdateDisplay: ; 247f0
+ call ClearWholeMenuBox
+ ld a, [wMenuDataFlags]
+ bit 4, a ; place arrows
+ jr z, .okay
+ ld a, [wMenuScrollPosition]
+ and a
+ jr z, .okay
+ ld a, [wMenuBorderTopCoord]
+ ld b, a
+ ld a, [wMenuBorderRightCoord]
+ ld c, a
+ call Coord2Tile
+ ld [hl], "▲"
+
+.okay
+ call MenuBoxCoord2Tile
+ ld bc, SCREEN_WIDTH + 1
+ add hl, bc
+ ld a, [wMenuData_ScrollingMenuHeight]
+ ld b, a
+ ld c, $0
+.loop
+ ld a, [wMenuScrollPosition]
+ add c
+ ld [wScrollingMenuCursorPosition], a
+ ld a, c
+ call ScrollingMenu_GetListItemCoordAndFunctionArgs
+ ld a, [wMenuSelection]
+ cp -1
+ jr z, .cancel
+ push bc
+ push hl
+ call ScrollingMenu_CallFunctions1and2
+ pop hl
+ ld bc, 2 * SCREEN_WIDTH
+ add hl, bc
+ pop bc
+ inc c
+ ld a, c
+ cp b
+ jr nz, .loop
+ ld a, [wMenuDataFlags]
+ bit 4, a ; place arrows
+ jr z, .done
+ ld a, [wMenuBorderBottomCoord]
+ ld b, a
+ ld a, [wMenuBorderRightCoord]
+ ld c, a
+ call Coord2Tile
+ ld [hl], "▼"
+
+.done
+ ret
+
+.cancel
+ ld a, [wMenuDataFlags]
+ bit 0, a ; call function on cancel
+ jr nz, .call_function
+ ld de, .string_2485f
+ call PlaceString
+ ret
+
+.string_2485f
+ db "CANCEL@"
+
+.call_function
+ ld d, h
+ ld e, l
+ ld hl, wMenuData_ScrollingMenuFunction1
+ jp CallPointerAt
+; 2486e
+
+ScrollingMenu_CallFunctions1and2: ; 2486e
+ push hl
+ ld d, h
+ ld e, l
+ ld hl, wMenuData_ScrollingMenuFunction1
+ call CallPointerAt
+ pop hl
+ ld a, [wMenuData_ScrollingMenuWidth]
+ and a
+ jr z, .done
+ ld e, a
+ ld d, $0
+ add hl, de
+ ld d, h
+ ld e, l
+ ld hl, wMenuData_ScrollingMenuFunction2
+ call CallPointerAt
+
+.done
+ ret
+; 2488b
+
+ScrollingMenu_PlaceCursor: ; 2488b
+ ld a, [wSwitchItem]
+ and a
+ jr z, .done
+ ld b, a
+ ld a, [wMenuScrollPosition]
+ cp b
+ jr nc, .done
+ ld c, a
+ ld a, [wMenuData_ScrollingMenuHeight]
+ add c
+ cp b
+ jr c, .done
+ ld a, b
+ sub c
+ dec a
+ add a
+ add $1
+ ld c, a
+ ld a, [wMenuBorderTopCoord]
+ add c
+ ld b, a
+ ld a, [wMenuBorderLeftCoord]
+ add $0
+ ld c, a
+ call Coord2Tile
+ ld [hl], "▷"
+
+.done
+ ret
+; 248b8
+
+ScrollingMenu_CheckCallFunction3: ; 248b8
+ ld a, [wMenuDataFlags]
+ bit 5, a ; call function 3
+ ret z
+ bit 1, a ; call function 3 if not switching items
+ jr z, .call
+ ld a, [wSwitchItem]
+ and a
+ ret nz
+
+.call
+ ld a, [wMenuCursorY]
+ dec a
+ call ScrollingMenu_GetListItemCoordAndFunctionArgs
+ ld hl, wMenuData_ScrollingMenuFunction3
+ call CallPointerAt
+ ret
+; 248d5
+
+ScrollingMenu_GetListItemCoordAndFunctionArgs: ; 248d5
+ push de
+ push hl
+ ld e, a
+ ld a, [wMenuScrollPosition]
+ add e
+ ld e, a
+ ld d, $0
+ ld hl, wMenuData_ItemsPointerAddr
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ inc hl ; items
+ ld a, [wMenuData_ScrollingMenuSpacing]
+ cp 1
+ jr z, .got_spacing
+ cp 2
+ jr z, .pointless_jump
+.pointless_jump
+ add hl, de
+.got_spacing
+ add hl, de
+ ld a, [wMenuData_ItemsPointerBank]
+ call GetFarByte
+ ld [wMenuSelection], a
+ ld [wCurItem], a
+ inc hl
+ ld a, [wMenuData_ItemsPointerBank]
+ call GetFarByte
+ ld [wMenuSelectionQuantity], a
+ pop hl
+ pop de
+ ret
+; 2490c
diff --git a/engine/menu/start_menu.asm b/engine/menu/start_menu.asm
new file mode 100755
index 000000000..037efd947
--- /dev/null
+++ b/engine/menu/start_menu.asm
@@ -0,0 +1,1993 @@
+; StartMenu.Items indexes
+ const_def
+ const STARTMENUITEM_POKEDEX ; 0
+ const STARTMENUITEM_POKEMON ; 1
+ const STARTMENUITEM_PACK ; 2
+ const STARTMENUITEM_STATUS ; 3
+ const STARTMENUITEM_SAVE ; 4
+ const STARTMENUITEM_OPTION ; 5
+ const STARTMENUITEM_EXIT ; 6
+ const STARTMENUITEM_POKEGEAR ; 7
+ const STARTMENUITEM_QUIT ; 8
+
+
+StartMenu:: ; 125cd
+
+ call ClearWindowData
+
+ ld de, SFX_MENU
+ call PlaySFX
+
+ farcall ReanchorBGMap_NoOAMUpdate
+
+ ld hl, wStatusFlags2
+ bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
+ ld hl, .MenuHeader
+ jr z, .GotMenuData
+ ld hl, .ContestMenuHeader
+.GotMenuData:
+
+ call LoadMenuHeader
+ call .SetUpMenuItems
+ ld a, [wBattleMenuCursorBuffer]
+ ld [wMenuCursorBuffer], a
+ call .DrawMenuAccount_
+ call DrawVariableLengthMenuBox
+ call .DrawBugContestStatusBox
+ call SafeUpdateSprites
+ call _OpenAndCloseMenu_HDMATransferTileMapAndAttrMap
+ farcall LoadFonts_NoOAMUpdate
+ call .DrawBugContestStatus
+ call UpdateTimePals
+ jr .Select
+
+.Reopen:
+ call UpdateSprites
+ call UpdateTimePals
+ call .SetUpMenuItems
+ ld a, [wBattleMenuCursorBuffer]
+ ld [wMenuCursorBuffer], a
+
+.Select:
+ call .GetInput
+ jr c, .Exit
+ call .DrawMenuAccount
+ ld a, [wMenuCursorBuffer]
+ ld [wBattleMenuCursorBuffer], a
+ call PlayClickSFX
+ call PlaceHollowCursor
+ call .OpenMenu
+
+; Menu items have different return functions.
+; For example, saving exits the menu.
+ ld hl, .MenuReturns
+ ld e, a
+ ld d, 0
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.MenuReturns:
+ dw .Reopen
+ dw .Exit
+ dw .ExitMenuCallFuncCloseText
+ dw .ExitMenuRunScriptCloseText
+ dw .ExitMenuRunScript
+ dw .ReturnEnd
+ dw .ReturnRedraw
+
+.Exit:
+ ld a, [hOAMUpdate]
+ push af
+ ld a, 1
+ ld [hOAMUpdate], a
+ call LoadFontsExtra
+ pop af
+ ld [hOAMUpdate], a
+.ReturnEnd:
+ call ExitMenu
+.ReturnEnd2:
+ call CloseText
+ call UpdateTimePals
+ ret
+
+.GetInput:
+; Return carry on exit, and no-carry on selection.
+ xor a
+ ld [hBGMapMode], a
+ call .DrawMenuAccount
+ call SetUpMenu
+ ld a, $ff
+ ld [wMenuSelection], a
+.loop
+ call .PrintMenuAccount
+ call GetScrollingMenuJoypad
+ ld a, [wMenuJoypad]
+ cp B_BUTTON
+ jr z, .b
+ cp A_BUTTON
+ jr z, .a
+ jr .loop
+.a
+ call PlayClickSFX
+ and a
+ ret
+.b
+ scf
+ ret
+; 12691
+
+.ExitMenuRunScript: ; 12691
+ call ExitMenu
+ ld a, HMENURETURN_SCRIPT
+ ld [hMenuReturn], a
+ ret
+; 12699
+
+.ExitMenuRunScriptCloseText: ; 12699
+ call ExitMenu
+ ld a, HMENURETURN_SCRIPT
+ ld [hMenuReturn], a
+ jr .ReturnEnd2
+; 126a2
+
+.ExitMenuCallFuncCloseText: ; 126a2
+ call ExitMenu
+ ld hl, wQueuedScriptAddr
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wQueuedScriptBank]
+ rst FarCall
+ jr .ReturnEnd2
+; 126b1
+
+.ReturnRedraw: ; 126b1
+ call .Clear
+ jp .Reopen
+; 126b7
+
+.Clear: ; 126b7
+ call ClearBGPalettes
+ call Call_ExitMenu
+ call ReloadTilesetAndPalettes
+ call .DrawMenuAccount_
+ call DrawVariableLengthMenuBox
+ call .DrawBugContestStatus
+ call UpdateSprites
+ call ret_d90
+ call FinishExitMenu
+ ret
+; 126d3
+
+
+.MenuHeader:
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 10, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+ dw .MenuData
+ db 1 ; default selection
+
+.ContestMenuHeader:
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 10, 2, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+ dw .MenuData
+ db 1 ; default selection
+
+.MenuData:
+ db STATICMENU_CURSOR | STATICMENU_WRAP | STATICMENU_ENABLE_START ; flags
+ dn 0, 0 ; rows, columns
+ dw wMenuItemsList
+ dw .MenuString
+ dw .Items
+
+.Items:
+; entries correspond to STARTMENUITEM_* constants
+ dw StartMenu_Pokedex, .PokedexString, .PokedexDesc
+ dw StartMenu_Pokemon, .PartyString, .PartyDesc
+ dw StartMenu_Pack, .PackString, .PackDesc
+ dw StartMenu_Status, .StatusString, .StatusDesc
+ dw StartMenu_Save, .SaveString, .SaveDesc
+ dw StartMenu_Option, .OptionString, .OptionDesc
+ dw StartMenu_Exit, .ExitString, .ExitDesc
+ dw StartMenu_Pokegear, .PokegearString, .PokegearDesc
+ dw StartMenu_Quit, .QuitString, .QuitDesc
+
+.PokedexString: db "#DEX@"
+.PartyString: db "#MON@"
+.PackString: db "PACK@"
+.StatusString: db "<PLAYER>@"
+.SaveString: db "SAVE@"
+.OptionString: db "OPTION@"
+.ExitString: db "EXIT@"
+.PokegearString: db "<POKE>GEAR@"
+.QuitString: db "QUIT@"
+
+.PokedexDesc:
+ db "#MON"
+ next "database@"
+
+.PartyDesc:
+ db "Party <PKMN>"
+ next "status@"
+
+.PackDesc:
+ db "Contains"
+ next "items@"
+
+.PokegearDesc:
+ db "Trainer's"
+ next "key device@"
+
+.StatusDesc:
+ db "Your own"
+ next "status@"
+
+.SaveDesc:
+ db "Save your"
+ next "progress@"
+
+.OptionDesc:
+ db "Change"
+ next "settings@"
+
+.ExitDesc:
+ db "Close this"
+ next "menu@"
+
+.QuitDesc:
+ db "Quit and"
+ next "be judged.@"
+
+
+.OpenMenu: ; 127e5
+ ld a, [wMenuSelection]
+ call .GetMenuAccountTextPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+; 127ef
+
+.MenuString: ; 127ef
+ push de
+ ld a, [wMenuSelection]
+ call .GetMenuAccountTextPointer
+ inc hl
+ inc hl
+ ld a, [hli]
+ ld d, [hl]
+ ld e, a
+ pop hl
+ call PlaceString
+ ret
+; 12800
+
+.MenuDesc: ; 12800
+ push de
+ ld a, [wMenuSelection]
+ cp $ff
+ jr z, .none
+ call .GetMenuAccountTextPointer
+rept 4
+ inc hl
+endr
+ ld a, [hli]
+ ld d, [hl]
+ ld e, a
+ pop hl
+ call PlaceString
+ ret
+.none
+ pop de
+ ret
+; 12819
+
+
+.GetMenuAccountTextPointer: ; 12819
+ ld e, a
+ ld d, 0
+ ld hl, wMenuDataPointerTableAddr
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+rept 6
+ add hl, de
+endr
+ ret
+; 12829
+
+
+.SetUpMenuItems: ; 12829
+ xor a
+ ld [wWhichIndexSet], a
+ call .FillMenuList
+
+ ld hl, wStatusFlags
+ bit STATUSFLAGS_POKEDEX_F, [hl]
+ jr z, .no_pokedex
+ ld a, STARTMENUITEM_POKEDEX
+ call .AppendMenuList
+.no_pokedex
+
+ ld a, [wPartyCount]
+ and a
+ jr z, .no_pokemon
+ ld a, STARTMENUITEM_POKEMON
+ call .AppendMenuList
+.no_pokemon
+
+ ld a, [wLinkMode]
+ and a
+ jr nz, .no_pack
+ ld hl, wStatusFlags2
+ bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
+ jr nz, .no_pack
+ ld a, STARTMENUITEM_PACK
+ call .AppendMenuList
+.no_pack
+
+ ld hl, wPokegearFlags
+ bit POKEGEAR_OBTAINED_F, [hl]
+ jr z, .no_pokegear
+ ld a, STARTMENUITEM_POKEGEAR
+ call .AppendMenuList
+.no_pokegear
+
+ ld a, STARTMENUITEM_STATUS
+ call .AppendMenuList
+
+ ld a, [wLinkMode]
+ and a
+ jr nz, .no_save
+ ld hl, wStatusFlags2
+ bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
+ ld a, STARTMENUITEM_QUIT
+ jr nz, .write
+ ld a, STARTMENUITEM_SAVE
+.write
+ call .AppendMenuList
+.no_save
+
+ ld a, STARTMENUITEM_OPTION
+ call .AppendMenuList
+ ld a, STARTMENUITEM_EXIT
+ call .AppendMenuList
+ ld a, c
+ ld [wMenuItemsList], a
+ ret
+; 1288d
+
+
+.FillMenuList: ; 1288d
+ xor a
+ ld hl, wMenuItemsList
+ ld [hli], a
+ ld a, -1
+ ld bc, wMenuItemsListEnd - (wMenuItemsList + 1)
+ call ByteFill
+ ld de, wMenuItemsList + 1
+ ld c, 0
+ ret
+; 128a0
+
+.AppendMenuList: ; 128a0
+ ld [de], a
+ inc de
+ inc c
+ ret
+; 128a4
+
+.DrawMenuAccount_: ; 128a4
+ jp .DrawMenuAccount
+; 128a7
+
+.PrintMenuAccount: ; 128a7
+ call .IsMenuAccountOn
+ ret z
+ call .DrawMenuAccount
+ decoord 0, 14
+ jp .MenuDesc
+; 128b4
+
+.DrawMenuAccount: ; 128b4
+ call .IsMenuAccountOn
+ ret z
+ hlcoord 0, 13
+ lb bc, 5, 10
+ call ClearBox
+ hlcoord 0, 13
+ ld b, 3
+ ld c, 8
+ jp TextBoxPalette
+; 128cb
+
+.IsMenuAccountOn: ; 128cb
+ ld a, [wOptions2]
+ and 1 << MENU_ACCOUNT
+ ret
+; 128d1
+
+.DrawBugContestStatusBox: ; 128d1
+ ld hl, wStatusFlags2
+ bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
+ ret z
+ farcall StartMenu_DrawBugContestStatusBox
+ ret
+; 128de
+
+.DrawBugContestStatus: ; 128de
+ ld hl, wStatusFlags2
+ bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
+ jr nz, .contest
+ ret
+.contest
+ farcall StartMenu_PrintBugContestStatus
+ ret
+; 128ed
+
+
+StartMenu_Exit: ; 128ed
+; Exit the menu.
+
+ ld a, 1
+ ret
+; 128f0
+
+
+StartMenu_Quit: ; 128f0
+; Retire from the bug catching contest.
+
+ ld hl, .EndTheContestText
+ call StartMenuYesNo
+ jr c, .DontEndContest
+ ld a, BANK(BugCatchingContestReturnToGateScript)
+ ld hl, BugCatchingContestReturnToGateScript
+ call FarQueueScript
+ ld a, 4
+ ret
+
+.DontEndContest:
+ ld a, 0
+ ret
+
+.EndTheContestText:
+ text_jump UnknownText_0x1c1a6c
+ db "@"
+; 1290b
+
+
+StartMenu_Save: ; 1290b
+; Save the game.
+
+ call BufferScreen
+ farcall SaveMenu
+ jr nc, .asm_12919
+ ld a, 0
+ ret
+.asm_12919
+ ld a, 1
+ ret
+; 1291c
+
+
+StartMenu_Option: ; 1291c
+; Game options.
+
+ call FadeToMenu
+ farcall OptionsMenu
+ ld a, 6
+ ret
+; 12928
+
+
+StartMenu_Status: ; 12928
+; Player status.
+
+ call FadeToMenu
+ farcall TrainerCard
+ call CloseSubmenu
+ ld a, 0
+ ret
+; 12937
+
+
+StartMenu_Pokedex: ; 12937
+
+ ld a, [wPartyCount]
+ and a
+ jr z, .asm_12949
+
+ call FadeToMenu
+ farcall Pokedex
+ call CloseSubmenu
+
+.asm_12949
+ ld a, 0
+ ret
+; 1294c
+
+
+StartMenu_Pokegear: ; 1294c
+
+ call FadeToMenu
+ farcall PokeGear
+ call CloseSubmenu
+ ld a, 0
+ ret
+; 1295b
+
+
+StartMenu_Pack: ; 1295b
+
+ call FadeToMenu
+ farcall Pack
+ ld a, [wPackUsedItem]
+ and a
+ jr nz, .used_item
+ call CloseSubmenu
+ ld a, 0
+ ret
+
+.used_item
+ call ExitAllMenus
+ ld a, 4
+ ret
+; 12976
+
+
+StartMenu_Pokemon: ; 12976
+
+ ld a, [wPartyCount]
+ and a
+ jr z, .return
+
+ call FadeToMenu
+
+.choosemenu
+ xor a
+ ld [wPartyMenuActionText], a ; Choose a POKéMON.
+ call ClearBGPalettes
+
+.menu
+ farcall LoadPartyMenuGFX
+ farcall InitPartyMenuWithCancel
+ farcall InitPartyMenuGFX
+
+.menunoreload
+ farcall WritePartyMenuTilemap
+ farcall PrintPartyMenuText
+ call WaitBGMap
+ call SetPalettes ; load regular palettes?
+ call DelayFrame
+ farcall PartyMenuSelect
+ jr c, .return ; if cancelled or pressed B
+
+ call PokemonActionSubmenu
+ cp 3
+ jr z, .menu
+ cp 0
+ jr z, .choosemenu
+ cp 1
+ jr z, .menunoreload
+ cp 2
+ jr z, .quit
+
+.return
+ call CloseSubmenu
+ ld a, 0
+ ret
+
+.quit
+ ld a, b
+ push af
+ call ExitAllMenus
+ pop af
+ ret
+; 129d5
+
+HasNoItems: ; 129d5
+ ld a, [wNumItems]
+ and a
+ ret nz
+ ld a, [wNumKeyItems]
+ and a
+ ret nz
+ ld a, [wNumBalls]
+ and a
+ ret nz
+ ld hl, wTMsHMs
+ ld b, NUM_TMS + NUM_HMS
+.loop
+ ld a, [hli]
+ and a
+ jr nz, .done
+ dec b
+ jr nz, .loop
+ scf
+ ret
+.done
+ and a
+ ret
+
+TossItemFromPC: ; 129f4
+ push de
+ call PartyMonItemName
+ farcall _CheckTossableItem
+ ld a, [wItemAttributeParamBuffer]
+ and a
+ jr nz, .key_item
+ ld hl, .TossHowMany
+ call MenuTextBox
+ farcall SelectQuantityToToss
+ push af
+ call CloseWindow
+ call ExitMenu
+ pop af
+ jr c, .quit
+ ld hl, .ConfirmToss
+ call MenuTextBox
+ call YesNoBox
+ push af
+ call ExitMenu
+ pop af
+ jr c, .quit
+ pop hl
+ ld a, [wCurItemQuantity]
+ call TossItem
+ call PartyMonItemName
+ ld hl, .TossedThisMany
+ call MenuTextBox
+ call ExitMenu
+ and a
+ ret
+
+.key_item
+ call .CantToss
+.quit
+ pop hl
+ scf
+ ret
+
+.TossHowMany:
+ ; Toss out how many @ (S)?
+ text_jump UnknownText_0x1c1a90
+ db "@"
+
+.ConfirmToss:
+ ; Throw away @ @ (S)?
+ text_jump UnknownText_0x1c1aad
+ db "@"
+
+.TossedThisMany:
+ ; Discarded @ (S).
+ text_jump UnknownText_0x1c1aca
+ db "@"
+
+.CantToss:
+ ld hl, .TooImportantToToss
+ call MenuTextBoxBackup
+ ret
+
+.TooImportantToToss:
+ ; That's too impor- tant to toss out!
+ text_jump UnknownText_0x1c1adf
+ db "@"
+; 0x12a60
+
+CantUseItem: ; 12a60
+ ld hl, CantUseItemText
+ call MenuTextBoxWaitButton
+ ret
+; 12a67
+
+CantUseItemText: ; 12a67
+ text_jump UnknownText_0x1c1b03
+ db "@"
+; 12a6c
+
+
+PartyMonItemName: ; 12a6c
+ ld a, [wCurItem]
+ ld [wd265], a
+ call GetItemName
+ call CopyName1
+ ret
+; 12a79
+
+
+CancelPokemonAction: ; 12a79
+ farcall InitPartyMenuWithCancel
+ farcall UnfreezeMonIcons
+ ld a, 1
+ ret
+; 12a88
+
+
+PokemonActionSubmenu: ; 12a88
+ hlcoord 1, 15
+ lb bc, 2, 18
+ call ClearBox
+ farcall MonSubmenu
+ call GetCurNick
+ ld a, [wMenuSelection]
+ ld hl, .Actions
+ ld de, 3
+ call IsInArray
+ jr nc, .nothing
+
+ inc hl
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.nothing
+ ld a, 0
+ ret
+
+.Actions:
+ dbw MONMENUITEM_CUT, MonMenu_Cut
+ dbw MONMENUITEM_FLY, MonMenu_Fly
+ dbw MONMENUITEM_SURF, MonMenu_Surf
+ dbw MONMENUITEM_STRENGTH, MonMenu_Strength
+ dbw MONMENUITEM_FLASH, MonMenu_Flash
+ dbw MONMENUITEM_WHIRLPOOL, MonMenu_Whirlpool
+ dbw MONMENUITEM_DIG, MonMenu_Dig
+ dbw MONMENUITEM_TELEPORT, MonMenu_Teleport
+ dbw MONMENUITEM_SOFTBOILED, MonMenu_Softboiled_MilkDrink
+ dbw MONMENUITEM_MILKDRINK, MonMenu_Softboiled_MilkDrink
+ dbw MONMENUITEM_HEADBUTT, MonMenu_Headbutt
+ dbw MONMENUITEM_WATERFALL, MonMenu_Waterfall
+ dbw MONMENUITEM_ROCKSMASH, MonMenu_RockSmash
+ dbw MONMENUITEM_SWEETSCENT, MonMenu_SweetScent
+ dbw MONMENUITEM_STATS, OpenPartyStats
+ dbw MONMENUITEM_SWITCH, SwitchPartyMons
+ dbw MONMENUITEM_ITEM, GiveTakePartyMonItem
+ dbw MONMENUITEM_CANCEL, CancelPokemonAction
+ dbw MONMENUITEM_MOVE, ManagePokemonMoves
+ dbw MONMENUITEM_MAIL, MonMailAction
+; 12aec
+
+
+SwitchPartyMons: ; 12aec
+
+; Don't try if there's nothing to switch!
+ ld a, [wPartyCount]
+ cp 2
+ jr c, .DontSwitch
+
+ ld a, [wCurPartyMon]
+ inc a
+ ld [wSwitchMon], a
+
+ farcall HoldSwitchmonIcon
+ farcall InitPartyMenuNoCancel
+
+ ld a, PARTYMENUACTION_MOVE
+ ld [wPartyMenuActionText], a
+ farcall WritePartyMenuTilemap
+ farcall PrintPartyMenuText
+
+ hlcoord 0, 1
+ ld bc, SCREEN_WIDTH * 2
+ ld a, [wSwitchMon]
+ dec a
+ call AddNTimes
+ ld [hl], "▷"
+ call WaitBGMap
+ call SetPalettes
+ call DelayFrame
+
+ farcall PartyMenuSelect
+ bit 1, b
+ jr c, .DontSwitch
+
+ farcall _SwitchPartyMons
+
+ xor a
+ ld [wPartyMenuActionText], a
+
+ farcall LoadPartyMenuGFX
+ farcall InitPartyMenuWithCancel
+ farcall InitPartyMenuGFX
+
+ ld a, 1
+ ret
+
+.DontSwitch:
+ xor a
+ ld [wPartyMenuActionText], a
+ call CancelPokemonAction
+ ret
+; 12b60
+
+
+GiveTakePartyMonItem: ; 12b60
+
+; Eggs can't hold items!
+ ld a, [wCurPartySpecies]
+ cp EGG
+ jr z, .cancel
+
+ ld hl, GiveTakeItemMenuData
+ call LoadMenuHeader
+ call VerticalMenu
+ call ExitMenu
+ jr c, .cancel
+
+ call GetCurNick
+ ld hl, wStringBuffer1
+ ld de, wMonOrItemNameBuffer
+ ld bc, MON_NAME_LENGTH
+ call CopyBytes
+ ld a, [wMenuCursorY]
+ cp 1
+ jr nz, .take
+
+ call LoadStandardMenuHeader
+ call ClearPalettes
+ call .GiveItem
+ call ClearPalettes
+ call LoadFontsBattleExtra
+ call ExitMenu
+ ld a, 0
+ ret
+
+.take
+ call TakePartyItem
+ ld a, 3
+ ret
+
+.cancel
+ ld a, 3
+ ret
+; 12ba9
+
+
+.GiveItem:
+
+ farcall DepositSellInitPackBuffers
+
+.loop
+ farcall DepositSellPack
+
+ ld a, [wcf66]
+ and a
+ jr z, .quit
+
+ ld a, [wcf65]
+ cp 2
+ jr z, .next
+
+ call CheckTossableItem
+ ld a, [wItemAttributeParamBuffer]
+ and a
+ jr nz, .next
+
+ call TryGiveItemToPartymon
+ jr .quit
+
+.next
+ ld hl, CantBeHeldText
+ call MenuTextBoxBackup
+ jr .loop
+
+.quit
+ ret
+; 12bd9
+
+
+TryGiveItemToPartymon: ; 12bd9
+
+ call SpeechTextBox
+ call PartyMonItemName
+ call GetPartyItemLocation
+ ld a, [hl]
+ and a
+ jr z, .give_item_to_mon
+
+ push hl
+ ld d, a
+ farcall ItemIsMail
+ pop hl
+ jr c, .please_remove_mail
+ ld a, [hl]
+ jr .already_holding_item
+
+.give_item_to_mon
+ call GiveItemToPokemon
+ ld hl, MadeHoldText
+ call MenuTextBoxBackup
+ call GivePartyItem
+ ret
+
+.please_remove_mail
+ ld hl, PleaseRemoveMailText
+ call MenuTextBoxBackup
+ ret
+
+.already_holding_item
+ ld [wd265], a
+ call GetItemName
+ ld hl, SwitchAlreadyHoldingText
+ call StartMenuYesNo
+ jr c, .abort
+
+ call GiveItemToPokemon
+ ld a, [wd265]
+ push af
+ ld a, [wCurItem]
+ ld [wd265], a
+ pop af
+ ld [wCurItem], a
+ call ReceiveItemFromPokemon
+ jr nc, .bag_full
+
+ ld hl, TookAndMadeHoldText
+ call MenuTextBoxBackup
+ ld a, [wd265]
+ ld [wCurItem], a
+ call GivePartyItem
+ ret
+
+.bag_full
+ ld a, [wd265]
+ ld [wCurItem], a
+ call ReceiveItemFromPokemon
+ ld hl, ItemStorageIsFullText
+ call MenuTextBoxBackup
+
+.abort
+ ret
+; 12c4c
+
+
+GivePartyItem: ; 12c4c
+
+ call GetPartyItemLocation
+ ld a, [wCurItem]
+ ld [hl], a
+ ld d, a
+ farcall ItemIsMail
+ jr nc, .done
+ call ComposeMailMessage
+
+.done
+ ret
+; 12c60
+
+
+TakePartyItem: ; 12c60
+
+ call SpeechTextBox
+ call GetPartyItemLocation
+ ld a, [hl]
+ and a
+ jr z, .asm_12c8c
+
+ ld [wCurItem], a
+ call ReceiveItemFromPokemon
+ jr nc, .asm_12c94
+
+ farcall ItemIsMail
+ call GetPartyItemLocation
+ ld a, [hl]
+ ld [wd265], a
+ ld [hl], NO_ITEM
+ call GetItemName
+ ld hl, TookFromText
+ call MenuTextBoxBackup
+ jr .asm_12c9a
+
+.asm_12c8c
+ ld hl, IsntHoldingAnythingText
+ call MenuTextBoxBackup
+ jr .asm_12c9a
+
+.asm_12c94
+ ld hl, ItemStorageIsFullText
+ call MenuTextBoxBackup
+
+.asm_12c9a
+ ret
+; 12c9b
+
+
+GiveTakeItemMenuData: ; 12c9b
+ db MENU_SPRITE_ANIMS | MENU_BACKUP_TILES ; flags
+ menu_coords 12, 12, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+ dw .Items
+ db 1 ; default option
+
+.Items:
+ db STATICMENU_CURSOR ; flags
+ db 2 ; # items
+ db "GIVE@"
+ db "TAKE@"
+; 12caf
+
+
+TookAndMadeHoldText: ; 12caf
+ text_jump UnknownText_0x1c1b2c
+ db "@"
+; 12cb4
+
+MadeHoldText: ; 12cb4
+ text_jump UnknownText_0x1c1b57
+ db "@"
+; 12cb9
+
+PleaseRemoveMailText: ; 12cb9
+ text_jump UnknownText_0x1c1b6f
+ db "@"
+; 12cbe
+
+IsntHoldingAnythingText: ; 12cbe
+ text_jump UnknownText_0x1c1b8e
+ db "@"
+; 12cc3
+
+ItemStorageIsFullText: ; 12cc3
+ text_jump UnknownText_0x1c1baa
+ db "@"
+; 12cc8
+
+TookFromText: ; 12cc8
+ text_jump UnknownText_0x1c1bc4
+ db "@"
+; 12ccd
+
+SwitchAlreadyHoldingText: ; 12ccd
+ text_jump UnknownText_0x1c1bdc
+ db "@"
+; 12cd2
+
+CantBeHeldText: ; 12cd2
+ text_jump UnknownText_0x1c1c09
+ db "@"
+; 12cd7
+
+
+GetPartyItemLocation: ; 12cd7
+ push af
+ ld a, MON_ITEM
+ call GetPartyParamLocation
+ pop af
+ ret
+; 12cdf
+
+
+ReceiveItemFromPokemon: ; 12cdf
+ ld a, 1
+ ld [wItemQuantityChangeBuffer], a
+ ld hl, wNumItems
+ jp ReceiveItem
+; 12cea
+
+
+GiveItemToPokemon: ; 12cea (4:6cea)
+ ld a, 1
+ ld [wItemQuantityChangeBuffer], a
+ ld hl, wNumItems
+ jp TossItem
+
+StartMenuYesNo: ; 12cf5
+ call MenuTextBox
+ call YesNoBox
+ jp ExitMenu
+; 12cfe
+
+
+ComposeMailMessage: ; 12cfe (4:6cfe)
+ ld de, wTempMailMessage
+ farcall _ComposeMailMessage
+ ld hl, wPlayerName
+ ld de, wTempMailAuthor
+ ld bc, NAME_LENGTH - 1
+ call CopyBytes
+ ld hl, wPlayerID
+ ld bc, 2
+ call CopyBytes
+ ld a, [wCurPartySpecies]
+ ld [de], a
+ inc de
+ ld a, [wCurItem]
+ ld [de], a
+ ld a, [wCurPartyMon]
+ ld hl, sPartyMail
+ ld bc, MAIL_STRUCT_LENGTH
+ call AddNTimes
+ ld d, h
+ ld e, l
+ ld hl, wTempMail
+ ld bc, MAIL_STRUCT_LENGTH
+ ld a, BANK(sPartyMail)
+ call GetSRAMBank
+ call CopyBytes
+ call CloseSRAM
+ ret
+
+MonMailAction: ; 12d45
+; If in the time capsule or trade center,
+; selecting the mail only allows you to
+; read the mail.
+ ld a, [wLinkMode]
+ cp LINK_TIMECAPSULE
+ jr z, .read
+ cp LINK_TRADECENTER
+ jr z, .read
+
+; Show the READ/TAKE/QUIT menu.
+ ld hl, .MenuHeader
+ call LoadMenuHeader
+ call VerticalMenu
+ call ExitMenu
+
+; Interpret the menu.
+ jp c, .done
+ ld a, [wMenuCursorY]
+ cp $1
+ jr z, .read
+ cp $2
+ jr z, .take
+ jp .done
+
+.read
+ farcall ReadPartyMonMail
+ ld a, $0
+ ret
+
+.take
+ ld hl, .sendmailtopctext
+ call StartMenuYesNo
+ jr c, .RemoveMailToBag
+ ld a, [wCurPartyMon]
+ ld b, a
+ farcall SendMailToPC
+ jr c, .MailboxFull
+ ld hl, .sentmailtopctext
+ call MenuTextBoxBackup
+ jr .done
+
+.MailboxFull:
+ ld hl, .mailboxfulltext
+ call MenuTextBoxBackup
+ jr .done
+
+.RemoveMailToBag:
+ ld hl, .mailwilllosemessagetext
+ call StartMenuYesNo
+ jr c, .done
+ call GetPartyItemLocation
+ ld a, [hl]
+ ld [wCurItem], a
+ call ReceiveItemFromPokemon
+ jr nc, .BagIsFull
+ call GetPartyItemLocation
+ ld [hl], $0
+ call GetCurNick
+ ld hl, .tookmailfrommontext
+ call MenuTextBoxBackup
+ jr .done
+
+.BagIsFull:
+ ld hl, .bagfulltext
+ call MenuTextBoxBackup
+ jr .done
+
+.done
+ ld a, $3
+ ret
+; 12dc9
+
+
+.MenuHeader:
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 12, 10, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x12dd1
+
+.MenuData:
+ db STATICMENU_CURSOR ; flags
+ db 3 ; items
+ db "READ@"
+ db "TAKE@"
+ db "QUIT@"
+; 0x12de2
+
+
+.mailwilllosemessagetext
+; The MAIL will lose its message. OK?
+ text_jump UnknownText_0x1c1c22
+ db "@"
+; 0x12de7
+
+.tookmailfrommontext
+; MAIL detached from <POKEMON>.
+ text_jump UnknownText_0x1c1c47
+ db "@"
+; 0x12dec
+
+.bagfulltext
+; There's no space for removing MAIL.
+ text_jump UnknownText_0x1c1c62
+ db "@"
+; 0x12df1
+
+.sendmailtopctext
+; Send the removed MAIL to your PC?
+ text_jump UnknownText_0x1c1c86
+ db "@"
+; 0x12df6
+
+.mailboxfulltext
+; Your PC's MAILBOX is full.
+ text_jump UnknownText_0x1c1ca9
+ db "@"
+; 0x12dfb
+
+.sentmailtopctext
+; The MAIL was sent to your PC.
+ text_jump UnknownText_0x1c1cc4
+ db "@"
+; 0x12e00
+
+
+OpenPartyStats: ; 12e00
+ call LoadStandardMenuHeader
+ call ClearSprites
+; PartyMon
+ xor a
+ ld [wMonType], a
+ call LowVolume
+ predef StatsScreenInit
+ call MaxVolume
+ call Call_ExitMenu
+ ld a, 0
+ ret
+; 12e1b
+
+
+MonMenu_Cut: ; 12e1b
+ farcall CutFunction
+ ld a, [wFieldMoveSucceeded]
+ cp $1
+ jr nz, .Fail
+ ld b, $4
+ ld a, $2
+ ret
+
+.Fail:
+ ld a, $3
+ ret
+; 12e30
+
+
+MonMenu_Fly: ; 12e30
+ farcall FlyFunction
+ ld a, [wFieldMoveSucceeded]
+ cp $2
+ jr z, .Fail
+ cp $0
+ jr z, .Error
+ farcall StubbedTrainerRankings_Fly
+ ld b, $4
+ ld a, $2
+ ret
+
+.Fail:
+ ld a, $3
+ ret
+
+.Error:
+ ld a, $0
+ ret
+
+.Unreferenced:
+ ld a, $1
+ ret
+; 12e55
+
+MonMenu_Flash: ; 12e55
+ farcall OWFlash
+ ld a, [wFieldMoveSucceeded]
+ cp $1
+ jr nz, .Fail
+ ld b, $4
+ ld a, $2
+ ret
+
+.Fail:
+ ld a, $3
+ ret
+; 12e6a
+
+MonMenu_Strength: ; 12e6a
+ farcall StrengthFunction
+ ld a, [wFieldMoveSucceeded]
+ cp $1
+ jr nz, .Fail
+ ld b, $4
+ ld a, $2
+ ret
+
+.Fail:
+ ld a, $3
+ ret
+; 12e7f
+
+MonMenu_Whirlpool: ; 12e7f
+ farcall WhirlpoolFunction
+ ld a, [wFieldMoveSucceeded]
+ cp $1
+ jr nz, .Fail
+ ld b, $4
+ ld a, $2
+ ret
+
+.Fail:
+ ld a, $3
+ ret
+; 12e94
+
+MonMenu_Waterfall: ; 12e94
+ farcall WaterfallFunction
+ ld a, [wFieldMoveSucceeded]
+ cp $1
+ jr nz, .Fail
+ ld b, $4
+ ld a, $2
+ ret
+
+.Fail:
+ ld a, $3
+ ret
+; 12ea9
+
+MonMenu_Teleport: ; 12ea9
+ farcall TeleportFunction
+ ld a, [wFieldMoveSucceeded]
+ and a
+ jr z, .Fail
+ ld b, $4
+ ld a, $2
+ ret
+
+.Fail:
+ ld a, $3
+ ret
+; 12ebd
+
+MonMenu_Surf: ; 12ebd
+ farcall SurfFunction
+ ld a, [wFieldMoveSucceeded]
+ and a
+ jr z, .Fail
+ ld b, $4
+ ld a, $2
+ ret
+
+.Fail:
+ ld a, $3
+ ret
+; 12ed1
+
+MonMenu_Dig: ; 12ed1
+ farcall DigFunction
+ ld a, [wFieldMoveSucceeded]
+ cp $1
+ jr nz, .Fail
+ ld b, $4
+ ld a, $2
+ ret
+
+.Fail:
+ ld a, $3
+ ret
+; 12ee6
+
+MonMenu_Softboiled_MilkDrink: ; 12ee6
+ call .CheckMonHasEnoughHP
+ jr nc, .NotEnoughHP
+ farcall Softboiled_MilkDrinkFunction
+ jr .finish
+
+.NotEnoughHP:
+ ld hl, .Text_NotEnoughHP
+ call PrintText
+
+.finish
+ xor a
+ ld [wPartyMenuActionText], a
+ ld a, $3
+ ret
+; 12f00
+
+.Text_NotEnoughHP:
+ ; Not enough HP!
+ text_jump UnknownText_0x1c1ce3
+ db "@"
+; 0x12f05
+
+.CheckMonHasEnoughHP:
+; Need to have at least (MaxHP / 5) HP left.
+ ld a, MON_MAXHP
+ call GetPartyParamLocation
+ ld a, [hli]
+ ld [hDividend + 0], a
+ ld a, [hl]
+ ld [hDividend + 1], a
+ ld a, 5
+ ld [hDivisor], a
+ ld b, 2
+ call Divide
+ ld a, MON_HP + 1
+ call GetPartyParamLocation
+ ld a, [hQuotient + 2]
+ sub [hl]
+ dec hl
+ ld a, [hQuotient + 1]
+ sbc [hl]
+ ret
+; 12f26
+
+MonMenu_Headbutt: ; 12f26
+ farcall HeadbuttFunction
+ ld a, [wFieldMoveSucceeded]
+ cp $1
+ jr nz, .Fail
+ ld b, $4
+ ld a, $2
+ ret
+
+.Fail:
+ ld a, $3
+ ret
+; 12f3b
+
+MonMenu_RockSmash: ; 12f3b
+ farcall RockSmashFunction
+ ld a, [wFieldMoveSucceeded]
+ cp $1
+ jr nz, .Fail
+ ld b, $4
+ ld a, $2
+ ret
+
+.Fail:
+ ld a, $3
+ ret
+; 12f50
+
+MonMenu_SweetScent: ; 12f50
+ farcall SweetScentFromMenu
+ ld b, $4
+ ld a, $2
+ ret
+; 12f5b
+
+ChooseMoveToDelete: ; 12f5b
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ call LoadFontsBattleExtra
+ call .ChooseMoveToDelete
+ pop bc
+ ld a, b
+ ld [wOptions], a
+ push af
+ call ClearBGPalettes
+ pop af
+ ret
+; 12f73
+
+.ChooseMoveToDelete
+ call SetUpMoveScreenBG
+ ld de, DeleteMoveScreenAttrs
+ call SetMenuAttributes
+ call SetUpMoveList
+ ld hl, w2DMenuFlags1
+ set 6, [hl]
+ jr .enter_loop
+
+.loop
+ call ScrollingMenuJoypad
+ bit B_BUTTON_F, a
+ jp nz, .b_button
+ bit A_BUTTON_F, a
+ jp nz, .a_button
+
+.enter_loop
+ call PrepareToPlaceMoveData
+ call PlaceMoveData
+ jp .loop
+; 12f9c
+
+.a_button
+ and a
+ jr .finish
+
+.b_button
+ scf
+
+.finish
+ push af
+ xor a
+ ld [wSwitchMon], a
+ ld hl, w2DMenuFlags1
+ res 6, [hl]
+ call ClearSprites
+ call ClearTileMap
+ pop af
+ ret
+; 12fb2
+
+DeleteMoveScreenAttrs: ; 12fb2
+ db 3, 1
+ db 3, 1
+ db $40, $00
+ dn 2, 0
+ db D_UP | D_DOWN | A_BUTTON | B_BUTTON
+; 12fba
+
+ManagePokemonMoves: ; 12fba
+ ld a, [wCurPartySpecies]
+ cp EGG
+ jr z, .egg
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ call MoveScreenLoop
+ pop af
+ ld [wOptions], a
+ call ClearBGPalettes
+
+.egg
+ ld a, $0
+ ret
+; 12fd5
+
+MoveScreenLoop: ; 12fd5
+ ld a, [wCurPartyMon]
+ inc a
+ ld [wPartyMenuCursor], a
+ call SetUpMoveScreenBG
+ call Function132d3
+ ld de, MoveScreenAttributes
+ call SetMenuAttributes
+.loop
+ call SetUpMoveList
+ ld hl, w2DMenuFlags1
+ set 6, [hl]
+ jr .skip_joy
+
+.joy_loop
+ call ScrollingMenuJoypad
+ bit 1, a
+ jp nz, .b_button
+ bit 0, a
+ jp nz, .a_button
+ bit 4, a
+ jp nz, .d_right
+ bit 5, a
+ jp nz, .d_left
+
+.skip_joy
+ call PrepareToPlaceMoveData
+ ld a, [wMoveSwapBuffer]
+ and a
+ jr nz, .moving_move
+ call PlaceMoveData
+ jp .joy_loop
+
+.moving_move
+ ld a, " "
+ hlcoord 1, 11
+ ld bc, 5
+ call ByteFill
+ hlcoord 1, 12
+ lb bc, 5, SCREEN_WIDTH - 2
+ call ClearBox
+ hlcoord 1, 12
+ ld de, String_MoveWhere
+ call PlaceString
+ jp .joy_loop
+.b_button
+ call PlayClickSFX
+ call WaitSFX
+ ld a, [wMoveSwapBuffer]
+ and a
+ jp z, .exit
+
+ ld a, [wMoveSwapBuffer]
+ ld [wMenuCursorY], a
+ xor a
+ ld [wMoveSwapBuffer], a
+ hlcoord 1, 2
+ lb bc, 8, SCREEN_WIDTH - 2
+ call ClearBox
+ jp .loop
+; 1305b
+
+.d_right
+ ld a, [wMoveSwapBuffer]
+ and a
+ jp nz, .joy_loop
+
+ ld a, [wCurPartyMon]
+ ld b, a
+ push bc
+ call .cycle_right
+ pop bc
+ ld a, [wCurPartyMon]
+ cp b
+ jp z, .joy_loop
+ jp MoveScreenLoop
+
+.d_left
+ ld a, [wMoveSwapBuffer]
+ and a
+ jp nz, .joy_loop
+ ld a, [wCurPartyMon]
+ ld b, a
+ push bc
+ call .cycle_left
+ pop bc
+ ld a, [wCurPartyMon]
+ cp b
+ jp z, .joy_loop
+ jp MoveScreenLoop
+
+.cycle_right
+ ld a, [wCurPartyMon]
+ inc a
+ ld [wCurPartyMon], a
+ ld c, a
+ ld b, 0
+ ld hl, wPartySpecies
+ add hl, bc
+ ld a, [hl]
+ cp -1
+ jr z, .cycle_left
+ cp EGG
+ ret nz
+ jr .cycle_right
+
+.cycle_left
+ ld a, [wCurPartyMon]
+ and a
+ ret z
+.cycle_left_loop
+ ld a, [wCurPartyMon]
+ dec a
+ ld [wCurPartyMon], a
+ ld c, a
+ ld b, 0
+ ld hl, wPartySpecies
+ add hl, bc
+ ld a, [hl]
+ cp EGG
+ ret nz
+ ld a, [wCurPartyMon]
+ and a
+ jr z, .cycle_right
+ jr .cycle_left_loop
+; 130c6
+
+.a_button
+ call PlayClickSFX
+ call WaitSFX
+ ld a, [wMoveSwapBuffer]
+ and a
+ jr nz, .place_move
+ ld a, [wMenuCursorY]
+ ld [wMoveSwapBuffer], a
+ call PlaceHollowCursor
+ jp .moving_move
+
+.place_move
+ ld hl, wPartyMon1Moves
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld a, [wCurPartyMon]
+ call AddNTimes
+ push hl
+ call .copy_move
+ pop hl
+ ld bc, $15
+ add hl, bc
+ call .copy_move
+ ld a, [wBattleMode]
+ jr z, .swap_moves
+ ld hl, wBattleMonMoves
+ ld bc, $20
+ ld a, [wCurPartyMon]
+ call AddNTimes
+ push hl
+ call .copy_move
+ pop hl
+ ld bc, 6
+ add hl, bc
+ call .copy_move
+
+.swap_moves
+ ld de, SFX_SWITCH_POKEMON
+ call PlaySFX
+ call WaitSFX
+ ld de, SFX_SWITCH_POKEMON
+ call PlaySFX
+ call WaitSFX
+ hlcoord 1, 2
+ lb bc, 8, 18
+ call ClearBox
+ hlcoord 10, 10
+ lb bc, 1, 9
+ call ClearBox
+ jp .loop
+; 1313a
+
+.copy_move
+ push hl
+ ld a, [wMenuCursorY]
+ dec a
+ ld c, a
+ ld b, $0
+ add hl, bc
+ ld d, h
+ ld e, l
+ pop hl
+ ld a, [wMoveSwapBuffer]
+ dec a
+ ld c, a
+ ld b, $0
+ add hl, bc
+ ld a, [de]
+ ld b, [hl]
+ ld [hl], a
+ ld a, b
+ ld [de], a
+ ret
+; 13154
+
+.exit
+ xor a
+ ld [wMoveSwapBuffer], a
+ ld hl, w2DMenuFlags1
+ res 6, [hl]
+ call ClearSprites
+ jp ClearTileMap
+; 13163
+
+MoveScreenAttributes: ; 13163
+ db 3, 1
+ db 3, 1
+ db $40, $00
+ dn 2, 0
+ db D_UP | D_DOWN | D_LEFT | D_RIGHT | A_BUTTON | B_BUTTON
+; 1316b
+
+String_MoveWhere: ; 1316b
+ db "Where?@"
+; 13172
+
+SetUpMoveScreenBG: ; 13172
+ call ClearBGPalettes
+ call ClearTileMap
+ call ClearSprites
+ xor a
+ ld [hBGMapMode], a
+ farcall LoadStatsScreenPageTilesGFX
+ farcall ClearSpriteAnims2
+ ld a, [wCurPartyMon]
+ ld e, a
+ ld d, $0
+ ld hl, wPartySpecies
+ add hl, de
+ ld a, [hl]
+ ld [wd265], a
+ ld e, $2
+ farcall LoadMenuMonIcon
+ hlcoord 0, 1
+ ld b, 9
+ ld c, 18
+ call TextBox
+ hlcoord 0, 11
+ ld b, 5
+ ld c, 18
+ call TextBox
+ hlcoord 2, 0
+ lb bc, 2, 3
+ call ClearBox
+ xor a
+ ld [wMonType], a
+ ld hl, wPartyMonNicknames
+ ld a, [wCurPartyMon]
+ call GetNick
+ hlcoord 5, 1
+ call PlaceString
+ push bc
+ farcall CopyMonToTempMon
+ pop hl
+ call PrintLevel
+ ld hl, wPlayerHPPal
+ call SetHPPal
+ ld b, SCGB_MOVE_LIST
+ call GetSGBLayout
+ hlcoord 16, 0
+ lb bc, 1, 3
+ jp ClearBox
+; 131ef
+
+SetUpMoveList: ; 131ef
+ xor a
+ ld [hBGMapMode], a
+ ld [wMoveSwapBuffer], a
+ ld [wMonType], a
+ predef CopyMonToTempMon
+ ld hl, wTempMonMoves
+ ld de, wListMoves_MoveIndicesBuffer
+ ld bc, NUM_MOVES
+ call CopyBytes
+ ld a, SCREEN_WIDTH * 2
+ ld [wBuffer1], a
+ hlcoord 2, 3
+ predef ListMoves
+ hlcoord 10, 4
+ predef ListMovePP
+ call WaitBGMap
+ call SetPalettes
+ ld a, [wNumMoves]
+ inc a
+ ld [w2DMenuNumRows], a
+ hlcoord 0, 11
+ ld b, 5
+ ld c, 18
+ jp TextBox
+; 13235
+
+PrepareToPlaceMoveData: ; 13235
+ ld hl, wPartyMon1Moves
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld a, [wCurPartyMon]
+ call AddNTimes
+ ld a, [wMenuCursorY]
+ dec a
+ ld c, a
+ ld b, $0
+ add hl, bc
+ ld a, [hl]
+ ld [wCurMove], a
+ hlcoord 1, 12
+ lb bc, 5, 18
+ jp ClearBox
+; 13256
+
+PlaceMoveData: ; 13256
+ xor a
+ ld [hBGMapMode], a
+ hlcoord 0, 10
+ ld de, String_MoveType_Top
+ call PlaceString
+ hlcoord 0, 11
+ ld de, String_MoveType_Bottom
+ call PlaceString
+ hlcoord 12, 12
+ ld de, String_MoveAtk
+ call PlaceString
+ ld a, [wCurMove]
+ ld b, a
+ hlcoord 2, 12
+ predef PrintMoveType
+ ld a, [wCurMove]
+ dec a
+ ld hl, Moves + MOVE_POWER
+ ld bc, MOVE_LENGTH
+ call AddNTimes
+ ld a, BANK(Moves)
+ call GetFarByte
+ hlcoord 16, 12
+ cp 2
+ jr c, .no_power
+ ld [wd265], a
+ ld de, wd265
+ lb bc, 1, 3
+ call PrintNum
+ jr .description
+
+.no_power
+ ld de, String_MoveNoPower
+ call PlaceString
+
+.description
+ hlcoord 1, 14
+ predef PrintMoveDesc
+ ld a, $1
+ ld [hBGMapMode], a
+ ret
+; 132ba
+
+String_MoveType_Top: ; 132ba
+ db "┌─────┐@"
+; 132c2
+String_MoveType_Bottom: ; 132c2
+ db "│TYPE/└@"
+; 132ca
+String_MoveAtk: ; 132ca
+ db "ATK/@"
+; 132cf
+String_MoveNoPower: ; 132cf
+ db "---@"
+; 132d3
+
+Function132d3: ; 132d3
+ call Function132da
+ call Function132fe
+ ret
+; 132da
+
+Function132da: ; 132da
+ ld a, [wCurPartyMon]
+ and a
+ ret z
+ ld c, a
+ ld e, a
+ ld d, 0
+ ld hl, wPartyCount
+ add hl, de
+.loop
+ ld a, [hl]
+ and a
+ jr z, .prev
+ cp EGG
+ jr z, .prev
+ cp NUM_POKEMON + 1
+ jr c, .legal
+
+.prev
+ dec hl
+ dec c
+ jr nz, .loop
+ ret
+
+.legal
+ hlcoord 16, 0
+ ld [hl], "◀"
+ ret
+; 132fe
+
+Function132fe: ; 132fe
+ ld a, [wCurPartyMon]
+ inc a
+ ld c, a
+ ld a, [wPartyCount]
+ cp c
+ ret z
+ ld e, c
+ ld d, 0
+ ld hl, wPartySpecies
+ add hl, de
+.loop
+ ld a, [hl]
+ cp -1
+ ret z
+ and a
+ jr z, .next
+ cp EGG
+ jr z, .next
+ cp NUM_POKEMON + 1
+ jr c, .legal
+
+.next
+ inc hl
+ jr .loop
+
+.legal
+ hlcoord 18, 0
+ ld [hl], "▶"
+ ret
+; 13327
diff --git a/engine/menu/switch_items.asm b/engine/menu/switch_items.asm
new file mode 100755
index 000000000..77b635246
--- /dev/null
+++ b/engine/menu/switch_items.asm
@@ -0,0 +1,274 @@
+SwitchItemsInBag: ; 2490c (9:490c)
+ ld a, [wSwitchItem]
+ and a
+ jr z, .init
+ ld b, a
+ ld a, [wScrollingMenuCursorPosition]
+ inc a
+ cp b
+ jr z, .trivial
+ ld a, [wScrollingMenuCursorPosition]
+ call ItemSwitch_GetNthItem
+ ld a, [hl]
+ cp -1
+ ret z
+ ld a, [wSwitchItem]
+ dec a
+ ld [wSwitchItem], a
+ call Function249a7
+ jp c, Function249d1
+ ld a, [wScrollingMenuCursorPosition]
+ ld c, a
+ ld a, [wSwitchItem]
+ cp c
+ jr c, .asm_2497a
+ jr .asm_2494a
+
+.init
+ ld a, [wScrollingMenuCursorPosition]
+ inc a
+ ld [wSwitchItem], a
+ ret
+
+.trivial
+ xor a
+ ld [wSwitchItem], a
+ ret
+
+.asm_2494a
+ ld a, [wSwitchItem]
+ call Function24a40
+ ld a, [wScrollingMenuCursorPosition]
+ ld d, a
+ ld a, [wSwitchItem]
+ ld e, a
+ call Function24a6c
+ push bc
+ ld a, [wSwitchItem]
+ call ItemSwitch_GetNthItem
+ dec hl
+ push hl
+ call ItemSwitch_ConvertSpacingToDW
+ add hl, bc
+ ld d, h
+ ld e, l
+ pop hl
+ pop bc
+ call Function24aab
+ ld a, [wScrollingMenuCursorPosition]
+ call Function24a4d
+ xor a
+ ld [wSwitchItem], a
+ ret
+
+.asm_2497a
+ ld a, [wSwitchItem]
+ call Function24a40
+ ld a, [wScrollingMenuCursorPosition]
+ ld d, a
+ ld a, [wSwitchItem]
+ ld e, a
+ call Function24a6c
+ push bc
+ ld a, [wSwitchItem]
+ call ItemSwitch_GetNthItem
+ ld d, h
+ ld e, l
+ call ItemSwitch_ConvertSpacingToDW
+ add hl, bc
+ pop bc
+ call CopyBytes
+ ld a, [wScrollingMenuCursorPosition]
+ call Function24a4d
+ xor a
+ ld [wSwitchItem], a
+ ret
+
+Function249a7: ; 249a7 (9:49a7)
+ ld a, [wSwitchItem]
+ call ItemSwitch_GetNthItem
+ ld d, h
+ ld e, l
+ ld a, [wScrollingMenuCursorPosition]
+ call ItemSwitch_GetNthItem
+ ld a, [de]
+ cp [hl]
+ jr nz, .asm_249cd
+ ld a, [wScrollingMenuCursorPosition]
+ call Function24a97
+ cp 99
+ jr z, .asm_249cd
+ ld a, [wSwitchItem]
+ call Function24a97
+ cp 99
+ jr nz, .asm_249cf
+.asm_249cd
+ and a
+ ret
+
+.asm_249cf
+ scf
+ ret
+
+Function249d1: ; 249d1 (9:49d1)
+ ld a, [wSwitchItem]
+ call ItemSwitch_GetNthItem
+ inc hl
+ push hl
+ ld a, [wScrollingMenuCursorPosition]
+ call ItemSwitch_GetNthItem
+ inc hl
+ ld a, [hl]
+ pop hl
+ add [hl]
+ cp 100
+ jr c, .asm_24a01
+ sub 99
+ push af
+ ld a, [wScrollingMenuCursorPosition]
+ call ItemSwitch_GetNthItem
+ inc hl
+ ld [hl], 99
+ ld a, [wSwitchItem]
+ call ItemSwitch_GetNthItem
+ inc hl
+ pop af
+ ld [hl], a
+ xor a
+ ld [wSwitchItem], a
+ ret
+
+.asm_24a01
+ push af
+ ld a, [wScrollingMenuCursorPosition]
+ call ItemSwitch_GetNthItem
+ inc hl
+ pop af
+ ld [hl], a
+ ld hl, wMenuData_ItemsPointerAddr
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wSwitchItem]
+ cp [hl]
+ jr nz, .asm_24a25
+ dec [hl]
+ ld a, [wSwitchItem]
+ call ItemSwitch_GetNthItem
+ ld [hl], $ff
+ xor a
+ ld [wSwitchItem], a
+ ret
+
+.asm_24a25
+ dec [hl]
+ call ItemSwitch_ConvertSpacingToDW
+ push bc
+ ld a, [wSwitchItem]
+ call ItemSwitch_GetNthItem
+ pop bc
+ push hl
+ add hl, bc
+ pop de
+.asm_24a34
+ ld a, [hli]
+ ld [de], a
+ inc de
+ cp $ff
+ jr nz, .asm_24a34
+ xor a
+ ld [wSwitchItem], a
+ ret
+
+Function24a40: ; 24a40 (9:4a40)
+ call ItemSwitch_GetNthItem
+ ld de, wd002
+ call ItemSwitch_ConvertSpacingToDW
+ call CopyBytes
+ ret
+
+Function24a4d: ; 24a4d (9:4a4d)
+ call ItemSwitch_GetNthItem
+ ld d, h
+ ld e, l
+ ld hl, wd002
+ call ItemSwitch_ConvertSpacingToDW
+ call CopyBytes
+ ret
+
+ItemSwitch_GetNthItem: ; 24a5c (9:4a5c)
+ push af
+ call ItemSwitch_ConvertSpacingToDW
+ ld hl, wMenuData_ItemsPointerAddr
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ inc hl
+ pop af
+ call AddNTimes
+ ret
+
+Function24a6c: ; 24a6c (9:4a6c)
+ push hl
+ call ItemSwitch_ConvertSpacingToDW
+ ld a, d
+ sub e
+ jr nc, .dont_negate
+ dec a
+ cpl
+.dont_negate
+ ld hl, 0
+ call AddNTimes
+ ld b, h
+ ld c, l
+ pop hl
+ ret
+
+ItemSwitch_ConvertSpacingToDW: ; 24a80 (9:4a80)
+; This function is absolutely idiotic.
+ push hl
+ ld a, [wMenuData_ScrollingMenuSpacing]
+ ld c, a
+ ld b, 0
+ ld hl, .spacing_dws
+ add hl, bc
+ add hl, bc
+ ld c, [hl]
+ inc hl
+ ld b, [hl]
+ pop hl
+ ret
+
+; 24a91 (9:4a91)
+
+.spacing_dws ; 24a91
+ dw 0, 1, 2
+; 24a97
+
+Function24a97: ; 24a97 (9:4a97)
+ push af
+ call ItemSwitch_ConvertSpacingToDW
+ ld a, c
+ cp 2
+ jr nz, .not_2
+ pop af
+ call ItemSwitch_GetNthItem
+ inc hl
+ ld a, [hl]
+ ret
+
+.not_2
+ pop af
+ ld a, $1
+ ret
+
+Function24aab: ; 24aab (9:4aab)
+.loop
+ ld a, [hld]
+ ld [de], a
+ dec de
+ dec bc
+ ld a, b
+ or c
+ jr nz, .loop
+ ret
diff --git a/engine/menu/timeset.asm b/engine/menu/timeset.asm
new file mode 100755
index 000000000..eda3094e1
--- /dev/null
+++ b/engine/menu/timeset.asm
@@ -0,0 +1,773 @@
+TIMESET_UP_ARROW EQUS "\"♂\"" ; $ef
+TIMESET_DOWN_ARROW EQUS "\"♀\"" ; $f5
+
+InitClock: ; 90672 (24:4672)
+; Ask the player to set the time.
+ ld a, [hInMenu]
+ push af
+ ld a, $1
+ ld [hInMenu], a
+
+ ld a, $0
+ ld [wSpriteUpdatesEnabled], a
+ ld a, $10
+ ld [wMusicFade], a
+ ld a, LOW(MUSIC_NONE)
+ ld [wMusicFadeID], a
+ ld a, HIGH(MUSIC_NONE)
+ ld [wMusicFadeID + 1], a
+ ld c, 8
+ call DelayFrames
+ call RotateFourPalettesLeft
+ call ClearTileMap
+ call ClearSprites
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ xor a
+ ld [hBGMapMode], a
+ call LoadStandardFont
+ ld de, TimeSetBackgroundGFX
+ ld hl, vTiles2 tile $00
+ lb bc, BANK(TimeSetBackgroundGFX), 1
+ call Request1bpp
+ ld de, TimeSetUpArrowGFX
+ ld hl, vTiles2 tile $01
+ lb bc, BANK(TimeSetUpArrowGFX), 1
+ call Request1bpp
+ ld de, TimeSetDownArrowGFX
+ ld hl, vTiles2 tile $02
+ lb bc, BANK(TimeSetDownArrowGFX), 1
+ call Request1bpp
+ call .ClearScreen
+ call WaitBGMap
+ call RotateFourPalettesRight
+ ld hl, Text_WokeUpOak
+ call PrintText
+ ld hl, wTimeSetBuffer
+ ld bc, 50
+ xor a
+ call ByteFill
+ ld a, 10 ; default hour = 10 AM
+ ld [wInitHourBuffer], a
+
+.loop
+ ld hl, Text_WhatTimeIsIt
+ call PrintText
+ hlcoord 3, 7
+ ld b, 2
+ ld c, 15
+ call TextBox
+ hlcoord 11, 7
+ ld [hl], $1
+ hlcoord 11, 10
+ ld [hl], $2
+ hlcoord 4, 9
+ call DisplayHourOClock
+ ld c, 10
+ call DelayFrames
+
+.SetHourLoop:
+ call JoyTextDelay
+ call SetHour
+ jr nc, .SetHourLoop
+
+ ld a, [wInitHourBuffer]
+ ld [wStringBuffer2 + 1], a
+ call .ClearScreen
+ ld hl, Text_WhatHrs
+ call PrintText
+ call YesNoBox
+ jr nc, .HourIsSet
+ call .ClearScreen
+ jr .loop
+
+.HourIsSet:
+ ld hl, Text_HowManyMinutes
+ call PrintText
+ hlcoord 11, 7
+ lb bc, 2, 7
+ call TextBox
+ hlcoord 15, 7
+ ld [hl], $1
+ hlcoord 15, 10
+ ld [hl], $2
+ hlcoord 12, 9
+ call DisplayMinutesWithMinString
+ ld c, 10
+ call DelayFrames
+
+.SetMinutesLoop:
+ call JoyTextDelay
+ call SetMinutes
+ jr nc, .SetMinutesLoop
+
+ ld a, [wInitMinuteBuffer]
+ ld [wStringBuffer2 + 2], a
+ call .ClearScreen
+ ld hl, Text_WhoaMins
+ call PrintText
+ call YesNoBox
+ jr nc, .MinutesAreSet
+ call .ClearScreen
+ jr .HourIsSet
+
+.MinutesAreSet:
+ call InitTimeOfDay
+ ld hl, OakText_ResponseToSetTime
+ call PrintText
+ call WaitPressAorB_BlinkCursor
+ pop af
+ ld [hInMenu], a
+ ret
+
+.ClearScreen: ; 90783 (24:4783)
+ xor a
+ ld [hBGMapMode], a
+ hlcoord 0, 0
+ ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+ xor a
+ call ByteFill
+ ld a, $1
+ ld [hBGMapMode], a
+ ret
+
+SetHour: ; 90795 (24:4795)
+ ld a, [hJoyPressed]
+ and A_BUTTON
+ jr nz, .Confirm
+
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_UP
+ jr nz, .up
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .down
+ call DelayFrame
+ and a
+ ret
+
+.down
+ ld hl, wInitHourBuffer
+ ld a, [hl]
+ and a
+ jr nz, .DecreaseThroughMidnight
+ ld a, 23 + 1
+.DecreaseThroughMidnight:
+ dec a
+ ld [hl], a
+ jr .okay
+
+.up
+ ld hl, wInitHourBuffer
+ ld a, [hl]
+ cp 23
+ jr c, .AdvanceThroughMidnight
+ ld a, -1
+.AdvanceThroughMidnight:
+ inc a
+ ld [hl], a
+
+.okay
+ hlcoord 4, 9
+ ld a, " "
+ ld bc, 15
+ call ByteFill
+ hlcoord 4, 9
+ call DisplayHourOClock
+ call WaitBGMap
+ and a
+ ret
+
+.Confirm:
+ scf
+ ret
+
+DisplayHourOClock: ; 907de (24:47de)
+ push hl
+ ld a, [wInitHourBuffer]
+ ld c, a
+ ld e, l
+ ld d, h
+ call PrintHour
+ inc hl
+ ld de, String_oclock
+ call PlaceString
+ pop hl
+ ret
+; 907f1 (24:47f1)
+
+UnreferencedFunction907f1: ; 907f1
+ ld h, d
+ ld l, e
+ push hl
+ call DisplayHourOClock
+ pop de
+ inc de
+ inc de
+ ld a, ":"
+ ld [de], a
+ inc de
+ push de
+ ld hl, 3
+ add hl, de
+ ld a, [de]
+ inc de
+ ld [hli], a
+ ld a, [de]
+ ld [hl], a
+ pop hl
+ call DisplayMinutesWithMinString
+ inc hl
+ inc hl
+ inc hl
+ ret
+; 90810
+
+SetMinutes: ; 90810 (24:4810)
+ ld a, [hJoyPressed]
+ and A_BUTTON
+ jr nz, .a_button
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_UP
+ jr nz, .d_up
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .d_down
+ call DelayFrame
+ and a
+ ret
+
+.d_down
+ ld hl, wInitMinuteBuffer
+ ld a, [hl]
+ and a
+ jr nz, .decrease
+ ld a, 59 + 1
+.decrease
+ dec a
+ ld [hl], a
+ jr .finish_dpad
+
+.d_up
+ ld hl, wInitMinuteBuffer
+ ld a, [hl]
+ cp 59
+ jr c, .increase
+ ld a, -1
+.increase
+ inc a
+ ld [hl], a
+.finish_dpad
+ hlcoord 12, 9
+ ld a, " "
+ ld bc, 7
+ call ByteFill
+ hlcoord 12, 9
+ call DisplayMinutesWithMinString
+ call WaitBGMap
+ and a
+ ret
+.a_button
+ scf
+ ret
+
+DisplayMinutesWithMinString: ; 90859 (24:4859)
+ ld de, wInitMinuteBuffer
+ call PrintTwoDigitNumberRightAlign
+ inc hl
+ ld de, String_min
+ call PlaceString
+ ret
+
+PrintTwoDigitNumberRightAlign: ; 90867 (24:4867)
+ push hl
+ ld a, " "
+ ld [hli], a
+ ld [hl], a
+ pop hl
+ lb bc, PRINTNUM_RIGHTALIGN | 1, 2
+ call PrintNum
+ ret
+; 90874 (24:4874)
+
+Text_WokeUpOak: ; 0x90874
+ ; Zzz… Hm? Wha…? You woke me up! Will you check the clock for me?
+ text_jump UnknownText_0x1bc29c
+ db "@"
+; 0x90879
+
+Text_WhatTimeIsIt: ; 0x90879
+ ; What time is it?
+ text_jump UnknownText_0x1bc2eb
+ db "@"
+; 0x9087e
+
+String_oclock:
+ db "o'clock@"
+; 90886
+
+Text_WhatHrs: ; 0x90886
+ ; What?@ @
+ text_jump UnknownText_0x1bc2fd
+ start_asm
+ hlcoord 1, 16
+ call DisplayHourOClock
+ ld hl, .QuestionMark
+ ret
+; 90895 (24:4895)
+
+.QuestionMark: ; 0x90895
+ ; ?
+ text_jump UnknownText_0x1bc305
+ db "@"
+; 0x9089a
+
+Text_HowManyMinutes: ; 0x9089a
+ ; How many minutes?
+ text_jump UnknownText_0x1bc308
+ db "@"
+; 0x9089f
+
+String_min:
+ db "min.@"
+; 908a4
+
+Text_WhoaMins: ; 0x908a4
+ ; Whoa!@ @
+ text_jump UnknownText_0x1bc31b
+ start_asm
+ hlcoord 7, 14
+ call DisplayMinutesWithMinString
+ ld hl, .QuestionMark
+ ret
+; 908b3 (24:48b3)
+
+.QuestionMark: ; 0x908b3
+ ; ?
+ text_jump UnknownText_0x1bc323
+ db "@"
+; 0x908b8
+
+OakText_ResponseToSetTime: ; 0x908b8
+ start_asm
+ decoord 1, 14
+ ld a, [wInitHourBuffer]
+ ld c, a
+ call PrintHour
+ ld [hl], ":"
+ inc hl
+ ld de, wInitMinuteBuffer
+ lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+ call PrintNum
+ ld b, h
+ ld c, l
+ ld a, [wInitHourBuffer]
+ cp MORN_HOUR
+ jr c, .nite
+ cp DAY_HOUR + 1
+ jr c, .morn
+ cp NITE_HOUR
+ jr c, .day
+.nite:
+ ld hl, .sodark
+ ret
+.morn:
+ ld hl, .overslept
+ ret
+.day:
+ ld hl, .yikes
+ ret
+; 908ec (24:48ec)
+
+.overslept ; 0x908ec
+ ; ! I overslept!
+ text_jump UnknownText_0x1bc326
+ db "@"
+; 0x908f1
+
+.yikes ; 0x908f1
+ ; ! Yikes! I over- slept!
+ text_jump UnknownText_0x1bc336
+ db "@"
+; 0x908f6
+
+.sodark ; 0x908f6
+ ; ! No wonder it's so dark!
+ text_jump UnknownText_0x1bc34f
+ db "@"
+; 0x908fb
+
+TimeSetBackgroundGFX: ; 908fb
+INCBIN "gfx/new_game/timeset_bg.1bpp"
+TimeSetUpArrowGFX: ; 90903
+INCBIN "gfx/new_game/up_arrow.1bpp"
+TimeSetDownArrowGFX: ; 9090b
+INCBIN "gfx/new_game/down_arrow.1bpp"
+; 90913
+
+SetDayOfWeek: ; 90913
+ ld a, [hInMenu]
+ push af
+ ld a, $1
+ ld [hInMenu], a
+ ld de, TimeSetUpArrowGFX
+ ld hl, vTiles0 tile TIMESET_UP_ARROW
+ lb bc, BANK(TimeSetUpArrowGFX), 1
+ call Request1bpp
+ ld de, TimeSetDownArrowGFX
+ ld hl, vTiles0 tile TIMESET_DOWN_ARROW
+ lb bc, BANK(TimeSetDownArrowGFX), 1
+ call Request1bpp
+ xor a
+ ld [wTempDayOfWeek], a
+.loop
+ hlcoord 0, 12
+ lb bc, 4, 18
+ call TextBox
+ call LoadStandardMenuHeader
+ ld hl, .WhatDayIsItText
+ call PrintText
+ hlcoord 9, 3
+ ld b, 2
+ ld c, 9
+ call TextBox
+ hlcoord 14, 3
+ ld [hl], TIMESET_UP_ARROW
+ hlcoord 14, 6
+ ld [hl], TIMESET_DOWN_ARROW
+ hlcoord 10, 5
+ call .PlaceWeekdayString
+ call ApplyTilemap
+ ld c, 10
+ call DelayFrames
+.loop2
+ call JoyTextDelay
+ call .GetJoypadAction
+ jr nc, .loop2
+ call ExitMenu
+ call UpdateSprites
+ ld hl, .ConfirmWeekdayText
+ call PrintText
+ call YesNoBox
+ jr c, .loop
+ ld a, [wTempDayOfWeek]
+ ld [wStringBuffer2], a
+ call InitDayOfWeek
+ call LoadStandardFont
+ pop af
+ ld [hInMenu], a
+ ret
+; 90993
+
+.GetJoypadAction: ; 90993
+ ld a, [hJoyPressed]
+ and A_BUTTON
+ jr z, .not_A
+ scf
+ ret
+
+.not_A
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_UP
+ jr nz, .d_up
+ ld a, [hl]
+ and D_DOWN
+ jr nz, .d_down
+ call DelayFrame
+ and a
+ ret
+
+.d_down
+ ld hl, wTempDayOfWeek
+ ld a, [hl]
+ and a
+ jr nz, .decrease
+ ld a, SATURDAY + 1
+
+.decrease
+ dec a
+ ld [hl], a
+ jr .finish_dpad
+
+.d_up
+ ld hl, wTempDayOfWeek
+ ld a, [hl]
+ cp 6
+ jr c, .increase
+ ld a, SUNDAY - 1
+
+.increase
+ inc a
+ ld [hl], a
+
+.finish_dpad
+ xor a
+ ld [hBGMapMode], a
+ hlcoord 10, 4
+ ld b, 2
+ ld c, 9
+ call ClearBox
+ hlcoord 10, 5
+ call .PlaceWeekdayString
+ call WaitBGMap
+ and a
+ ret
+; 909de
+
+.PlaceWeekdayString: ; 909de
+ push hl
+ ld a, [wTempDayOfWeek]
+ ld e, a
+ ld d, 0
+ ld hl, .WeekdayStrings
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld d, [hl]
+ ld e, a
+ pop hl
+ call PlaceString
+ ret
+; 909f2
+
+.WeekdayStrings: ; 909f2
+; entries correspond to wCurDay constants (see constants/wram_constants.asm)
+ dw .Sunday
+ dw .Monday
+ dw .Tuesday
+ dw .Wednesday
+ dw .Thursday
+ dw .Friday
+ dw .Saturday
+ dw .Sunday
+
+.Sunday: db " SUNDAY@"
+.Monday: db " MONDAY@"
+.Tuesday: db " TUESDAY@"
+.Wednesday: db "WEDNESDAY@"
+.Thursday: db "THURSDAY@"
+.Friday: db " FRIDAY@"
+.Saturday: db "SATURDAY@"
+
+
+.WhatDayIsItText: ; 0x90a3f
+ ; What day is it?
+ text_jump UnknownText_0x1bc369
+ db "@"
+; 0x90a44
+
+.ConfirmWeekdayText: ; 0x90a44
+ start_asm
+ hlcoord 1, 14
+ call .PlaceWeekdayString
+ ld hl, .IsIt
+ ret
+; 90a4f (24:4a4f)
+
+.IsIt: ; 0x90a4f
+ ; , is it?
+ text_jump UnknownText_0x1bc37a
+ db "@"
+; 0x90a54
+
+InitialSetDSTFlag: ; 90a54
+ ld a, [wDST]
+ set 7, a
+ ld [wDST], a
+ hlcoord 1, 14
+ lb bc, 3, 18
+ call ClearBox
+ ld hl, .Text
+ call PlaceHLTextAtBC
+ ret
+; 90a6c
+
+.Text: ; 90a6c
+ start_asm
+ call UpdateTime
+ ld a, [hHours]
+ ld b, a
+ ld a, [hMinutes]
+ ld c, a
+ decoord 1, 14
+ farcall PrintHoursMins
+ ld hl, .DSTIsThatOK
+ ret
+; 90a83 (24:4a83)
+
+.DSTIsThatOK: ; 0x90a83
+ ; DST, is that OK?
+ text_jump Text_DSTIsThatOK
+ db "@"
+; 0x90a88
+
+InitialClearDSTFlag: ; 90a88
+ ld a, [wDST]
+ res 7, a
+ ld [wDST], a
+ hlcoord 1, 14
+ lb bc, 3, 18
+ call ClearBox
+ ld hl, .Text
+ call PlaceHLTextAtBC
+ ret
+; 90aa0
+
+.Text: ; 90aa0
+ start_asm
+ call UpdateTime
+ ld a, [hHours]
+ ld b, a
+ ld a, [hMinutes]
+ ld c, a
+ decoord 1, 14
+ farcall PrintHoursMins
+ ld hl, .IsThatOK
+ ret
+; 90ab7
+
+.IsThatOK: ; 0x90ab7
+ ; , is that OK?
+ text_jump UnknownText_0x1c5ff1
+ db "@"
+; 0x90abc
+
+DebugDisplayTime: ; 90abc
+ hlcoord 1, 14
+ lb bc, 3, SCREEN_WIDTH - 2
+ call ClearBox
+ ld hl, .Text
+ call PlaceHLTextAtBC
+ ret
+; 90acc
+
+.Text: ; 0x90acc
+ start_asm
+ call UpdateTime
+
+ hlcoord 1, 14
+ ld [hl], "R"
+ inc hl
+ ld [hl], "T"
+ inc hl
+ ld [hl], " "
+ inc hl
+
+ ld de, hRTCDayLo
+ call .PrintTime
+
+ hlcoord 1, 16
+ ld [hl], "D"
+ inc hl
+ ld [hl], "F"
+ inc hl
+ ld [hl], " "
+ inc hl
+
+ ld de, wStartDay
+ call .PrintTime
+
+ ld [hl], " "
+ inc hl
+
+ ld a, [wDST]
+ bit 7, a
+ jr z, .off
+
+ ld [hl], "O"
+ inc hl
+ ld [hl], "N"
+ inc hl
+ jr .done
+
+.off
+ ld [hl], "O"
+ inc hl
+ ld [hl], "F"
+ inc hl
+ ld [hl], "F"
+ inc hl
+
+.done
+ ld hl, .NowOnDebug
+ ret
+; 90b13
+
+.NowOnDebug: ; 0x90b13
+ text "<PARA>Now on DEBUG…"
+ prompt
+; 0x90b23
+
+.PrintTime: ; 90b23
+ lb bc, 1, 3
+ call PrintNum
+ ld [hl], "."
+ inc hl
+ inc de
+ lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+ call PrintNum
+ ld [hl], ":"
+ inc hl
+ inc de
+ lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+ call PrintNum
+ ret
+; 90b3e
+
+PrintHour: ; 90b3e (24:4b3e)
+ ld l, e
+ ld h, d
+ push bc
+ call GetTimeOfDayString
+ call PlaceString
+ ld l, c
+ ld h, b
+ inc hl
+ pop bc
+ call AdjustHourForAMorPM
+ ld [wd265], a
+ ld de, wd265
+ call PrintTwoDigitNumberRightAlign
+ ret
+
+GetTimeOfDayString: ; 90b58 (24:4b58)
+ ld a, c
+ cp MORN_HOUR
+ jr c, .nite
+ cp DAY_HOUR
+ jr c, .morn
+ cp NITE_HOUR
+ jr c, .day
+.nite
+ ld de, .nite_string
+ ret
+.morn
+ ld de, .morn_string
+ ret
+.day
+ ld de, .day_string
+ ret
+; 90b71 (24:4b71)
+
+.nite_string: db "NITE@"
+.morn_string: db "MORN@"
+.day_string: db "DAY@"
+; 90b7f
+
+AdjustHourForAMorPM:
+; Convert the hour stored in c (0-23) to a 1-12 value
+ ld a, c
+ or a
+ jr z, .midnight
+ cp NOON_HOUR
+ ret c
+ ret z
+ sub NOON_HOUR
+ ret
+
+.midnight
+ ld a, NOON_HOUR
+ ret
diff --git a/engine/menu/tmhm.asm b/engine/menu/tmhm.asm
new file mode 100755
index 000000000..9db3dc291
--- /dev/null
+++ b/engine/menu/tmhm.asm
@@ -0,0 +1,49 @@
+CanLearnTMHMMove: ; 11639
+ ld a, [wCurPartySpecies]
+ ld [wCurSpecies], a
+ call GetBaseData
+ ld hl, wBaseTMHM
+ push hl
+
+ ld a, [wPutativeTMHMMove]
+ ld b, a
+ ld c, 0
+ ld hl, TMHMMoves
+.loop
+ ld a, [hli]
+ and a
+ jr z, .end
+ cp b
+ jr z, .asm_11659
+ inc c
+ jr .loop
+
+.asm_11659
+ pop hl
+ ld b, CHECK_FLAG
+ push de
+ ld d, 0
+ predef SmallFarFlagAction
+ pop de
+ ret
+
+.end
+ pop hl
+ ld c, 0
+ ret
+; 1166a
+
+GetTMHMMove: ; 1166a
+ ld a, [wd265]
+ dec a
+ ld hl, TMHMMoves
+ ld b, 0
+ ld c, a
+ add hl, bc
+ ld a, [hl]
+ ld [wd265], a
+ ret
+; 1167a
+
+
+INCLUDE "data/moves/tmhm_moves.asm"
diff --git a/engine/menu/trainer_card.asm b/engine/menu/trainer_card.asm
new file mode 100755
index 000000000..e84c1c9f3
--- /dev/null
+++ b/engine/menu/trainer_card.asm
@@ -0,0 +1,623 @@
+; TrainerCard.Jumptable indexes
+ const_def
+ const TRAINERCARDSTATE_PAGE1_LOADGFX ; 0
+ const TRAINERCARDSTATE_PAGE1_JOYPAD ; 1
+ const TRAINERCARDSTATE_PAGE2_LOADGFX ; 2
+ const TRAINERCARDSTATE_PAGE2_JOYPAD ; 3
+ const TRAINERCARDSTATE_PAGE3_LOADGFX ; 4
+ const TRAINERCARDSTATE_PAGE3_JOYPAD ; 5
+ const TRAINERCARDSTATE_QUIT ; 6
+
+TrainerCard: ; 25105
+ ld a, [wVramState]
+ push af
+ xor a
+ ld [wVramState], a
+ ld hl, wOptions
+ ld a, [hl]
+ push af
+ set NO_TEXT_SCROLL, [hl]
+ call .InitRAM
+.loop
+ call UpdateTime
+ call JoyTextDelay
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .quit
+ ld a, [hJoyLast]
+ and B_BUTTON
+ jr nz, .quit
+ call .RunJumptable
+ call DelayFrame
+ jr .loop
+
+.quit
+ pop af
+ ld [wOptions], a
+ pop af
+ ld [wVramState], a
+ ret
+
+.InitRAM: ; 2513b (9:513b)
+ call ClearBGPalettes
+ call ClearSprites
+ call ClearTileMap
+ call DisableLCD
+
+ farcall GetCardPic
+
+ ld hl, CardRightCornerGFX
+ ld de, vTiles2 tile $1c
+ ld bc, 1 tiles
+ ld a, BANK(CardRightCornerGFX)
+ call FarCopyBytes
+
+ ld hl, CardStatusGFX
+ ld de, vTiles2 tile $29
+ ld bc, 86 tiles
+ ld a, BANK(CardStatusGFX)
+ call FarCopyBytes
+
+ call TrainerCard_PrintTopHalfOfCard
+
+ hlcoord 0, 8
+ ld d, 6
+ call TrainerCard_InitBorder
+
+ call EnableLCD
+ call WaitBGMap
+ ld b, SCGB_TRAINER_CARD
+ call GetSGBLayout
+ call SetPalettes
+ call WaitBGMap
+ ld hl, wJumptableIndex
+ xor a ; TRAINERCARDSTATE_PAGE1_LOADGFX
+ ld [hli], a ; wJumptableIndex
+ ld [hli], a ; wTrainerCardBadgeFrameCounter
+ ld [hli], a ; wTrainerCardBadgeTileID
+ ld [hl], a ; wTrainerCardBadgeAttributes
+ ret
+
+.RunJumptable: ; 2518e (9:518e)
+ jumptable .Jumptable, wJumptableIndex
+
+.Jumptable: ; 2519d (9:519d)
+; entries correspond to TRAINERCARDSTATE_* constants
+ dw TrainerCard_Page1_LoadGFX
+ dw TrainerCard_Page1_Joypad
+ dw TrainerCard_Page2_LoadGFX
+ dw TrainerCard_Page2_Joypad
+ dw TrainerCard_Page3_LoadGFX
+ dw TrainerCard_Page3_Joypad
+ dw TrainerCard_Quit
+
+TrainerCard_IncrementJumptable: ; 251ab (9:51ab)
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+TrainerCard_Quit: ; 251b0 (9:51b0)
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+TrainerCard_Page1_LoadGFX: ; 251b6 (9:51b6)
+ call ClearSprites
+ hlcoord 0, 8
+ ld d, 6
+ call TrainerCard_InitBorder
+ call WaitBGMap
+ ld de, CardStatusGFX
+ ld hl, vTiles2 tile $29
+ lb bc, BANK(CardStatusGFX), 86
+ call Request2bpp
+ call TrainerCard_Page1_PrintDexCaught_GameTime
+ call TrainerCard_IncrementJumptable
+ ret
+
+TrainerCard_Page1_Joypad: ; 251d7 (9:51d7)
+ call TrainerCard_Page1_PrintGameTime
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_RIGHT | A_BUTTON
+ jr nz, .pressed_right_a
+ ret
+
+.pressed_right_a
+ ld a, TRAINERCARDSTATE_PAGE2_LOADGFX
+ ld [wJumptableIndex], a
+ ret
+
+.Unreferenced_KantoCheck:
+ ld a, [wKantoBadges]
+ and a
+ ret z
+ ld a, TRAINERCARDSTATE_PAGE3_LOADGFX
+ ld [wJumptableIndex], a
+ ret
+
+; 251f4
+
+TrainerCard_Page2_LoadGFX: ; 251f4 (9:51f4)
+ call ClearSprites
+ hlcoord 0, 8
+ ld d, 6
+ call TrainerCard_InitBorder
+ call WaitBGMap
+ ld de, LeaderGFX
+ ld hl, vTiles2 tile $29
+ lb bc, BANK(LeaderGFX), 86
+ call Request2bpp
+ ld de, BadgeGFX
+ ld hl, vTiles0 tile $00
+ lb bc, BANK(BadgeGFX), 44
+ call Request2bpp
+ call TrainerCard_Page2_3_InitObjectsAndStrings
+ call TrainerCard_IncrementJumptable
+ ret
+
+TrainerCard_Page2_Joypad: ; 25221 (9:5221)
+ ld hl, TrainerCard_JohtoBadgesOAM
+ call TrainerCard_Page2_3_AnimateBadges
+ ld hl, hJoyLast
+ ld a, [hl]
+ and A_BUTTON
+ jr nz, .Quit
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .d_left
+ ret
+
+.d_left
+ ld a, TRAINERCARDSTATE_PAGE1_LOADGFX
+ ld [wJumptableIndex], a
+ ret
+
+.Unreferenced_KantoCheck:
+ ld a, [wKantoBadges]
+ and a
+ ret z
+ ld a, TRAINERCARDSTATE_PAGE3_LOADGFX
+ ld [wJumptableIndex], a
+ ret
+
+.Quit:
+ ld a, TRAINERCARDSTATE_QUIT
+ ld [wJumptableIndex], a
+ ret
+
+TrainerCard_Page3_LoadGFX: ; 2524c (9:524c)
+ call ClearSprites
+ hlcoord 0, 8
+ ld d, 6
+ call TrainerCard_InitBorder
+ call WaitBGMap
+ ld de, LeaderGFX2
+ ld hl, vTiles2 tile $29
+ lb bc, BANK(LeaderGFX2), 86
+ call Request2bpp
+ ld de, BadgeGFX2
+ ld hl, vTiles0 tile $00
+ lb bc, BANK(BadgeGFX2), 44
+ call Request2bpp
+ call TrainerCard_Page2_3_InitObjectsAndStrings
+ call TrainerCard_IncrementJumptable
+ ret
+
+TrainerCard_Page3_Joypad: ; 25279 (9:5279)
+ ld hl, TrainerCard_JohtoBadgesOAM
+ call TrainerCard_Page2_3_AnimateBadges
+ ld hl, hJoyLast
+ ld a, [hl]
+ and D_LEFT
+ jr nz, .left
+ ld a, [hl]
+ and D_RIGHT
+ jr nz, .right
+ ret
+
+.left
+ ld a, TRAINERCARDSTATE_PAGE2_LOADGFX
+ ld [wJumptableIndex], a
+ ret
+
+.right
+ ld a, TRAINERCARDSTATE_PAGE1_LOADGFX
+ ld [wJumptableIndex], a
+ ret
+
+TrainerCard_PrintTopHalfOfCard: ; 25299 (9:5299)
+ hlcoord 0, 0
+ ld d, 5
+ call TrainerCard_InitBorder
+ hlcoord 2, 2
+ ld de, .Name_Money
+ call PlaceString
+ hlcoord 2, 4
+ ld de, .ID_No
+ call TrainerCardSetup_PlaceTilemapString
+ hlcoord 7, 2
+ ld de, wPlayerName
+ call PlaceString
+ hlcoord 5, 4
+ ld de, wPlayerID
+ lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+ call PrintNum
+ hlcoord 7, 6
+ ld de, wMoney
+ lb bc, PRINTNUM_MONEY | 3, 6
+ call PrintNum
+ hlcoord 1, 3
+ ld de, .HorizontalDivider
+ call TrainerCardSetup_PlaceTilemapString
+ hlcoord 14, 1
+ lb bc, 5, 7
+ xor a
+ ld [hGraphicStartTile], a
+ predef PlaceGraphic
+ ret
+
+; 252ec (9:52ec)
+
+.Name_Money: ; 252ec
+ db "NAME/"
+ next ""
+ next "MONEY@"
+
+.ID_No: ; 252f9
+ db $27, $28, -1 ; ID NO
+
+.HorizontalDivider: ; 252fc
+ db $25, $25, $25, $25, $25, $25, $25, $25, $25, $25, $25, $25, $26, -1 ; ____________>
+; 2530a
+
+TrainerCard_Page1_PrintDexCaught_GameTime: ; 2530a (9:530a)
+ hlcoord 2, 10
+ ld de, .Dex_PlayTime
+ call PlaceString
+ hlcoord 10, 15
+ ld de, .Badges
+ call PlaceString
+ ld hl, wPokedexCaught
+ ld b, wEndPokedexCaught - wPokedexCaught
+ call CountSetBits
+ ld de, wd265
+ hlcoord 15, 10
+ lb bc, 1, 3
+ call PrintNum
+ call TrainerCard_Page1_PrintGameTime
+ hlcoord 2, 8
+ ld de, .StatusTilemap
+ call TrainerCardSetup_PlaceTilemapString
+ ld a, [wStatusFlags]
+ bit STATUSFLAGS_POKEDEX_F, a
+ ret nz
+ hlcoord 1, 9
+ lb bc, 2, 17
+ call ClearBox
+ ret
+
+.Dex_PlayTime:
+ db "#DEX"
+ next "PLAY TIME@@"
+
+.Badges:
+ db " BADGES▶@"
+
+.StatusTilemap: ; 25366
+ db $29, $2a, $2b, $2c, $2d, -1
+; 2536c
+
+TrainerCard_Page2_3_InitObjectsAndStrings: ; 2536c (9:536c)
+ hlcoord 2, 8
+ ld de, .BadgesTilemap
+ call TrainerCardSetup_PlaceTilemapString
+ hlcoord 2, 10
+ ld a, $29
+ ld c, 4
+.loop
+ call TrainerCard_Page2_3_PlaceLeadersFaces
+rept 4
+ inc hl
+endr
+ dec c
+ jr nz, .loop
+ hlcoord 2, 13
+ ld a, $51
+ ld c, 4
+.loop2
+ call TrainerCard_Page2_3_PlaceLeadersFaces
+rept 4
+ inc hl
+endr
+ dec c
+ jr nz, .loop2
+ xor a
+ ld [wTrainerCardBadgeFrameCounter], a
+ ld hl, TrainerCard_JohtoBadgesOAM
+ call TrainerCard_Page2_3_OAMUpdate
+ ret
+
+; 253a2 (9:53a2)
+
+.BadgesTilemap: ; 253a2
+ db $79, $7a, $7b, $7c, $7d, -1 ; "BADGES"
+; 253a8
+
+TrainerCardSetup_PlaceTilemapString: ; 253a8 (9:53a8)
+.loop
+ ld a, [de]
+ cp -1
+ ret z
+ ld [hli], a
+ inc de
+ jr .loop
+
+TrainerCard_InitBorder: ; 253b0 (9:53b0)
+ ld e, SCREEN_WIDTH
+.loop1
+ ld a, $23
+ ld [hli], a
+ dec e
+ jr nz, .loop1
+
+ ld a, $23
+ ld [hli], a
+ ld e, SCREEN_HEIGHT - 1
+ ld a, " "
+.loop2
+ ld [hli], a
+ dec e
+ jr nz, .loop2
+
+ ld a, $1c
+ ld [hli], a
+ ld a, $23
+ ld [hli], a
+.loop3
+ ld a, $23
+ ld [hli], a
+
+ ld e, SCREEN_HEIGHT
+ ld a, " "
+.loop4
+ ld [hli], a
+ dec e
+ jr nz, .loop4
+
+ ld a, $23
+ ld [hli], a
+ dec d
+ jr nz, .loop3
+
+ ld a, $23
+ ld [hli], a
+ ld a, $24
+ ld [hli], a
+
+ ld e, SCREEN_HEIGHT - 1
+ ld a, " "
+.loop5
+ ld [hli], a
+ dec e
+ jr nz, .loop5
+ ld a, $23
+ ld [hli], a
+ ld e, SCREEN_WIDTH
+.loop6
+ ld a, $23
+ ld [hli], a
+ dec e
+ jr nz, .loop6
+ ret
+
+TrainerCard_Page2_3_PlaceLeadersFaces: ; 253f4 (9:53f4)
+ push de
+ push hl
+ ld [hli], a
+ inc a
+ ld [hli], a
+ inc a
+ ld [hli], a
+ inc a
+ ld [hli], a
+ inc a
+ ld de, SCREEN_WIDTH - 3
+ add hl, de
+ ld [hli], a
+ inc a
+ ld [hli], a
+ inc a
+ ld [hli], a
+ inc a
+ ld de, SCREEN_WIDTH - 3
+ add hl, de
+ ld [hli], a
+ inc a
+ ld [hli], a
+ inc a
+ ld [hli], a
+ inc a
+ pop hl
+ pop de
+ ret
+
+TrainerCard_Page1_PrintGameTime: ; 25415 (9:5415)
+ hlcoord 11, 12
+ ld de, wGameTimeHours
+ lb bc, 2, 4
+ call PrintNum
+ inc hl
+ ld de, wGameTimeMinutes
+ lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+ call PrintNum
+ ld a, [hVBlankCounter]
+ and $1f
+ ret nz
+ hlcoord 15, 12
+ ld a, [hl]
+ xor " " ^ $2e ; alternate between space and small colon ($2e) tiles
+ ld [hl], a
+ ret
+
+TrainerCard_Page2_3_AnimateBadges: ; 25438 (9:5438)
+ ld a, [hVBlankCounter]
+ and %111
+ ret nz
+ ld a, [wTrainerCardBadgeFrameCounter]
+ inc a
+ and %111
+ ld [wTrainerCardBadgeFrameCounter], a
+ jr TrainerCard_Page2_3_OAMUpdate
+
+TrainerCard_Page2_3_OAMUpdate: ; 25448 (9:5448)
+; copy flag array pointer
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+; get flag array
+ ld d, a
+ ld a, [de]
+ ld c, a
+ ld de, wVirtualOAMSprite00
+ ld b, NUM_JOHTO_BADGES
+.loop
+ srl c
+ push bc
+ jr nc, .skip_badge
+ push hl
+ ld a, [hli] ; y
+ ld b, a
+ ld a, [hli] ; x
+ ld c, a
+ ld a, [hli] ; pal
+ ld [wTrainerCardBadgeAttributes], a
+ ld a, [wTrainerCardBadgeFrameCounter]
+ add l
+ ld l, a
+ ld a, 0
+ adc h
+ ld h, a
+ ld a, [hl]
+ ld [wTrainerCardBadgeTileID], a
+ call .PrepOAM
+ pop hl
+.skip_badge
+ ld bc, $b ; 3 + 2 * 4
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .loop
+ ret
+
+.PrepOAM: ; 2547b (9:547b)
+ ld a, [wTrainerCardBadgeTileID]
+ and 1 << 7
+ jr nz, .xflip
+ ld hl, .facing1
+ jr .loop2
+
+.xflip
+ ld hl, .facing2
+.loop2
+ ld a, [hli]
+ cp -1
+ ret z
+ add b
+ ld [de], a ; y
+ inc de
+
+ ld a, [hli]
+ add c
+ ld [de], a ; x
+ inc de
+
+ ld a, [wTrainerCardBadgeTileID]
+ and $ff ^ (1 << 7)
+ add [hl]
+ ld [de], a ; tile id
+ inc hl
+ inc de
+
+ ld a, [wTrainerCardBadgeAttributes]
+ add [hl]
+ ld [de], a ; attributes
+ inc hl
+ inc de
+ jr .loop2
+
+; 254a7 (9:54a7)
+
+.facing1 ; 254a7
+ dsprite 0, 0, 0, 0, $00, 0
+ dsprite 0, 0, 1, 0, $01, 0
+ dsprite 1, 0, 0, 0, $02, 0
+ dsprite 1, 0, 1, 0, $03, 0
+ db -1
+
+.facing2 ; 254b8
+ dsprite 0, 0, 0, 0, $01, 0 | X_FLIP
+ dsprite 0, 0, 1, 0, $00, 0 | X_FLIP
+ dsprite 1, 0, 0, 0, $03, 0 | X_FLIP
+ dsprite 1, 0, 1, 0, $02, 0 | X_FLIP
+ db -1
+
+TrainerCard_JohtoBadgesOAM: ; 254c9
+; Template OAM data for each badge on the trainer card.
+; Format:
+ ; y, x, palette
+ ; cycle 1: face tile, in1 tile, in2 tile, in3 tile
+ ; cycle 2: face tile, in1 tile, in2 tile, in3 tile
+
+ dw wJohtoBadges
+
+ ; Zephyrbadge
+ db $68, $18, 0
+ db $00, $20, $24, $20 | (1 << 7)
+ db $00, $20, $24, $20 | (1 << 7)
+
+ ; Hivebadge
+ db $68, $38, 0
+ db $04, $20, $24, $20 | (1 << 7)
+ db $04, $20, $24, $20 | (1 << 7)
+
+ ; Plainbadge
+ db $68, $58, 0
+ db $08, $20, $24, $20 | (1 << 7)
+ db $08, $20, $24, $20 | (1 << 7)
+
+ ; Fogbadge
+ db $68, $78, 0
+ db $0c, $20, $24, $20 | (1 << 7)
+ db $0c, $20, $24, $20 | (1 << 7)
+
+ ; Mineralbadge
+ db $80, $38, 0
+ db $10, $20, $24, $20 | (1 << 7)
+ db $10, $20, $24, $20 | (1 << 7)
+
+ ; Stormbadge
+ db $80, $18, 0
+ db $14, $20, $24, $20 | (1 << 7)
+ db $14, $20, $24, $20 | (1 << 7)
+
+ ; Glacierbadge
+ db $80, $58, 0
+ db $18, $20, $24, $20 | (1 << 7)
+ db $18, $20, $24, $20 | (1 << 7)
+
+ ; Risingbadge
+ ; X-flips on alternate cycles.
+ db $80, $78, 0
+ db $1c, $20, $24, $20 | (1 << 7)
+ db $1c | (1 << 7), $20, $24, $20 | (1 << 7)
+; 25523
+
+CardStatusGFX: INCBIN "gfx/trainer_card/card_status.2bpp"
+
+LeaderGFX: INCBIN "gfx/trainer_card/leaders.2bpp"
+LeaderGFX2: INCBIN "gfx/trainer_card/leaders.2bpp"
+BadgeGFX: INCBIN "gfx/trainer_card/badges.2bpp"
+BadgeGFX2: INCBIN "gfx/trainer_card/badges.2bpp"
+
+CardRightCornerGFX: INCBIN "gfx/trainer_card/card_right_corner.2bpp"