shithub: pokecrystal

Download patch

ref: 86c1b05fbc74711d03e4a2122342c55e58d99995
parent: 98e670f3637b5f845a91423ee2d624d2f1e331a6
author: mid-kid <esteve.varela@gmail.com>
date: Mon Aug 6 13:20:05 EDT 2018

Split print_move_description and mon_menu

--- a/engine/items/tmhm.asm
+++ b/engine/items/tmhm.asm
@@ -557,18 +557,3 @@
 	ld a, b
 	ld [wTempTMHM], a
 	ret
-
-PrintMoveDesc:
-	push hl
-	ld hl, MoveDescriptions
-	ld a, [wCurSpecies]
-	dec a
-	ld c, a
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld e, a
-	ld d, [hl]
-	pop hl
-	jp PlaceString
--- a/engine/menus/start_menu.asm
+++ b/engine/menus/start_menu.asm
@@ -539,1309 +539,3 @@
 	call ExitAllMenus
 	pop af
 	ret
-
-HasNoItems:
-	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:
-	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 "@"
-
-CantUseItem:
-	ld hl, CantUseItemText
-	call MenuTextBoxWaitButton
-	ret
-
-CantUseItemText:
-	text_jump UnknownText_0x1c1b03
-	db "@"
-
-PartyMonItemName:
-	ld a, [wCurItem]
-	ld [wNamedObjectIndexBuffer], a
-	call GetItemName
-	call CopyName1
-	ret
-
-CancelPokemonAction:
-	farcall InitPartyMenuWithCancel
-	farcall UnfreezeMonIcons
-	ld a, 1
-	ret
-
-PokemonActionSubmenu:
-	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
-
-SwitchPartyMons:
-; 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
-
-GiveTakePartyMonItem:
-; 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
-
-.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
-
-TryGiveItemToPartymon:
-	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 [wNamedObjectIndexBuffer], a
-	call GetItemName
-	ld hl, SwitchAlreadyHoldingText
-	call StartMenuYesNo
-	jr c, .abort
-
-	call GiveItemToPokemon
-	ld a, [wNamedObjectIndexBuffer]
-	push af
-	ld a, [wCurItem]
-	ld [wNamedObjectIndexBuffer], a
-	pop af
-	ld [wCurItem], a
-	call ReceiveItemFromPokemon
-	jr nc, .bag_full
-
-	ld hl, TookAndMadeHoldText
-	call MenuTextBoxBackup
-	ld a, [wNamedObjectIndexBuffer]
-	ld [wCurItem], a
-	call GivePartyItem
-	ret
-
-.bag_full
-	ld a, [wNamedObjectIndexBuffer]
-	ld [wCurItem], a
-	call ReceiveItemFromPokemon
-	ld hl, ItemStorageIsFullText
-	call MenuTextBoxBackup
-
-.abort
-	ret
-
-GivePartyItem:
-	call GetPartyItemLocation
-	ld a, [wCurItem]
-	ld [hl], a
-	ld d, a
-	farcall ItemIsMail
-	jr nc, .done
-	call ComposeMailMessage
-
-.done
-	ret
-
-TakePartyItem:
-	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 [wNamedObjectIndexBuffer], 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
-
-GiveTakeItemMenuData:
-	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@"
-
-TookAndMadeHoldText:
-	text_jump UnknownText_0x1c1b2c
-	db "@"
-
-MadeHoldText:
-	text_jump UnknownText_0x1c1b57
-	db "@"
-
-PleaseRemoveMailText:
-	text_jump UnknownText_0x1c1b6f
-	db "@"
-
-IsntHoldingAnythingText:
-	text_jump UnknownText_0x1c1b8e
-	db "@"
-
-ItemStorageIsFullText:
-	text_jump UnknownText_0x1c1baa
-	db "@"
-
-TookFromText:
-	text_jump UnknownText_0x1c1bc4
-	db "@"
-
-SwitchAlreadyHoldingText:
-	text_jump UnknownText_0x1c1bdc
-	db "@"
-
-CantBeHeldText:
-	text_jump UnknownText_0x1c1c09
-	db "@"
-
-GetPartyItemLocation:
-	push af
-	ld a, MON_ITEM
-	call GetPartyParamLocation
-	pop af
-	ret
-
-ReceiveItemFromPokemon:
-	ld a, 1
-	ld [wItemQuantityChangeBuffer], a
-	ld hl, wNumItems
-	jp ReceiveItem
-
-GiveItemToPokemon:
-	ld a, 1
-	ld [wItemQuantityChangeBuffer], a
-	ld hl, wNumItems
-	jp TossItem
-
-StartMenuYesNo:
-	call MenuTextBox
-	call YesNoBox
-	jp ExitMenu
-
-ComposeMailMessage:
-	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:
-; 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
-
-.MenuHeader:
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 12, 10, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
-	dw .MenuData
-	db 1 ; default option
-
-.MenuData:
-	db STATICMENU_CURSOR ; flags
-	db 3 ; items
-	db "READ@"
-	db "TAKE@"
-	db "QUIT@"
-
-.mailwilllosemessagetext
-; The MAIL will lose its message. OK?
-	text_jump UnknownText_0x1c1c22
-	db "@"
-
-.tookmailfrommontext
-; MAIL detached from <POKEMON>.
-	text_jump UnknownText_0x1c1c47
-	db "@"
-
-.bagfulltext
-; There's no space for removing MAIL.
-	text_jump UnknownText_0x1c1c62
-	db "@"
-
-.sendmailtopctext
-; Send the removed MAIL to your PC?
-	text_jump UnknownText_0x1c1c86
-	db "@"
-
-.mailboxfulltext
-; Your PC's MAILBOX is full.
-	text_jump UnknownText_0x1c1ca9
-	db "@"
-
-.sentmailtopctext
-; The MAIL was sent to your PC.
-	text_jump UnknownText_0x1c1cc4
-	db "@"
-
-OpenPartyStats:
-	call LoadStandardMenuHeader
-	call ClearSprites
-; PartyMon
-	xor a
-	ld [wMonType], a
-	call LowVolume
-	predef StatsScreenInit
-	call MaxVolume
-	call Call_ExitMenu
-	ld a, 0
-	ret
-
-MonMenu_Cut:
-	farcall CutFunction
-	ld a, [wFieldMoveSucceeded]
-	cp $1
-	jr nz, .Fail
-	ld b, $4
-	ld a, $2
-	ret
-
-.Fail:
-	ld a, $3
-	ret
-
-MonMenu_Fly:
-	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
-
-MonMenu_Flash:
-	farcall OWFlash
-	ld a, [wFieldMoveSucceeded]
-	cp $1
-	jr nz, .Fail
-	ld b, $4
-	ld a, $2
-	ret
-
-.Fail:
-	ld a, $3
-	ret
-
-MonMenu_Strength:
-	farcall StrengthFunction
-	ld a, [wFieldMoveSucceeded]
-	cp $1
-	jr nz, .Fail
-	ld b, $4
-	ld a, $2
-	ret
-
-.Fail:
-	ld a, $3
-	ret
-
-MonMenu_Whirlpool:
-	farcall WhirlpoolFunction
-	ld a, [wFieldMoveSucceeded]
-	cp $1
-	jr nz, .Fail
-	ld b, $4
-	ld a, $2
-	ret
-
-.Fail:
-	ld a, $3
-	ret
-
-MonMenu_Waterfall:
-	farcall WaterfallFunction
-	ld a, [wFieldMoveSucceeded]
-	cp $1
-	jr nz, .Fail
-	ld b, $4
-	ld a, $2
-	ret
-
-.Fail:
-	ld a, $3
-	ret
-
-MonMenu_Teleport:
-	farcall TeleportFunction
-	ld a, [wFieldMoveSucceeded]
-	and a
-	jr z, .Fail
-	ld b, $4
-	ld a, $2
-	ret
-
-.Fail:
-	ld a, $3
-	ret
-
-MonMenu_Surf:
-	farcall SurfFunction
-	ld a, [wFieldMoveSucceeded]
-	and a
-	jr z, .Fail
-	ld b, $4
-	ld a, $2
-	ret
-
-.Fail:
-	ld a, $3
-	ret
-
-MonMenu_Dig:
-	farcall DigFunction
-	ld a, [wFieldMoveSucceeded]
-	cp $1
-	jr nz, .Fail
-	ld b, $4
-	ld a, $2
-	ret
-
-.Fail:
-	ld a, $3
-	ret
-
-MonMenu_Softboiled_MilkDrink:
-	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
-
-.Text_NotEnoughHP:
-	; Not enough HP!
-	text_jump UnknownText_0x1c1ce3
-	db "@"
-
-.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
-
-MonMenu_Headbutt:
-	farcall HeadbuttFunction
-	ld a, [wFieldMoveSucceeded]
-	cp $1
-	jr nz, .Fail
-	ld b, $4
-	ld a, $2
-	ret
-
-.Fail:
-	ld a, $3
-	ret
-
-MonMenu_RockSmash:
-	farcall RockSmashFunction
-	ld a, [wFieldMoveSucceeded]
-	cp $1
-	jr nz, .Fail
-	ld b, $4
-	ld a, $2
-	ret
-
-.Fail:
-	ld a, $3
-	ret
-
-MonMenu_SweetScent:
-	farcall SweetScentFromMenu
-	ld b, $4
-	ld a, $2
-	ret
-
-ChooseMoveToDelete:
-	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
-
-.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
-
-.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
-
-DeleteMoveScreenAttrs:
-	db 3, 1
-	db 3, 1
-	db $40, $00
-	dn 2, 0
-	db D_UP | D_DOWN | A_BUTTON | B_BUTTON
-
-ManagePokemonMoves:
-	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
-
-MoveScreenLoop:
-	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
-
-.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
-
-.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
-
-.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
-
-.exit
-	xor a
-	ld [wMoveSwapBuffer], a
-	ld hl, w2DMenuFlags1
-	res 6, [hl]
-	call ClearSprites
-	jp ClearTileMap
-
-MoveScreenAttributes:
-	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
-
-String_MoveWhere:
-	db "Where?@"
-
-SetUpMoveScreenBG:
-	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 [wTempIconSpecies], a
-	ld e, MONICON_MOVES
-	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
-
-SetUpMoveList:
-	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
-
-PrepareToPlaceMoveData:
-	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 [wCurSpecies], a
-	hlcoord 1, 12
-	lb bc, 5, 18
-	jp ClearBox
-
-PlaceMoveData:
-	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, [wCurSpecies]
-	ld b, a
-	hlcoord 2, 12
-	predef PrintMoveType
-	ld a, [wCurSpecies]
-	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 [wDeciramBuffer], a
-	ld de, wDeciramBuffer
-	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
-
-String_MoveType_Top:
-	db "┌─────┐@"
-String_MoveType_Bottom:
-	db "│TYPE/└@"
-String_MoveAtk:
-	db "ATK/@"
-String_MoveNoPower:
-	db "---@"
-
-Function132d3:
-	call Function132da
-	call Function132fe
-	ret
-
-Function132da:
-	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
-
-Function132fe:
-	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
--- a/engine/pokemon/mon_menu.asm
+++ b/engine/pokemon/mon_menu.asm
@@ -1,290 +1,1305 @@
-INCLUDE "data/mon_menu.asm"
+HasNoItems:
+	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
 
-MonSubmenu:
-	xor a
-	ld [hBGMapMode], a
-	call GetMonSubmenuItems
-	farcall FreezeMonIcons
-	ld hl, .MenuHeader
-	call LoadMenuHeader
-	call .GetTopCoord
-	call PopulateMonMenu
+TossItemFromPC:
+	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
 
-	ld a, 1
-	ld [hBGMapMode], a
-	call MonMenuLoop
-	ld [wMenuSelection], a
+.key_item
+	call .CantToss
+.quit
+	pop hl
+	scf
+	ret
 
-	call ExitMenu
+.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
 
-.MenuHeader:
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 6, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
-	dw 0
-	db 1 ; default option
+.TooImportantToToss:
+	; That's too impor- tant to toss out!
+	text_jump UnknownText_0x1c1adf
+	db "@"
 
-.GetTopCoord:
-; 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
+CantUseItem:
+	ld hl, CantUseItemText
+	call MenuTextBoxWaitButton
 	ret
 
-MonMenuLoop:
-.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
+CantUseItemText:
+	text_jump UnknownText_0x1c1b03
+	db "@"
 
-.cancel
-	ld a, MONMENUITEM_CANCEL
+PartyMonItemName:
+	ld a, [wCurItem]
+	ld [wNamedObjectIndexBuffer], a
+	call GetItemName
+	call CopyName1
 	ret
 
-.select
-	ld a, [wMenuCursorY]
-	dec a
-	ld c, a
-	ld b, 0
-	ld hl, wBuffer2
-	add hl, bc
-	ld a, [hl]
+CancelPokemonAction:
+	farcall InitPartyMenuWithCancel
+	farcall UnfreezeMonIcons
+	ld a, 1
 	ret
 
-PopulateMonMenu:
-	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
-
-GetMonMenuString:
-	ld hl, MonMenuOptions + 1
+PokemonActionSubmenu:
+	hlcoord 1, 15
+	lb bc, 2, 18
+	call ClearBox
+	farcall MonSubmenu
+	call GetCurNick
+	ld a, [wMenuSelection]
+	ld hl, .Actions
 	ld de, 3
 	call IsInArray
-	dec hl
-	ld a, [hli]
-	cp MONMENU_MENUOPTION
-	jr z, .NotMove
+	jr nc, .nothing
+
 	inc hl
-	ld a, [hl]
-	ld [wNamedObjectIndexBuffer], a
-	call GetMoveName
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+.nothing
+	ld a, 0
 	ret
 
-.NotMove:
-	inc hl
-	ld a, [hl]
+.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
+
+SwitchPartyMons:
+; 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
-	ld hl, MonMenuOptionStrings
-	call GetNthString
-	ld d, h
-	ld e, l
+	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
 
-GetMonSubmenuItems:
-	call ResetMonSubmenu
+.DontSwitch:
+	xor a
+	ld [wPartyMenuActionText], a
+	call CancelPokemonAction
+	ret
+
+GiveTakePartyMonItem:
+; Eggs can't hold items!
 	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
+	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
+
+.GiveItem:
+	farcall DepositSellInitPackBuffers
+
 .loop
-	push bc
-	push de
-	ld a, [de]
+	farcall DepositSellPack
+
+	ld a, [wcf66]
 	and a
+	jr z, .quit
+
+	ld a, [wcf65]
+	cp 2
 	jr z, .next
-	push hl
-	call IsFieldMove
-	pop hl
-	jr nc, .next
-	call AddMonMenuItem
 
+	call CheckTossableItem
+	ld a, [wItemAttributeParamBuffer]
+	and a
+	jr nz, .next
+
+	call TryGiveItemToPartymon
+	jr .quit
+
 .next
-	pop de
-	inc de
-	pop bc
-	dec c
-	jr nz, .loop
+	ld hl, CantBeHeldText
+	call MenuTextBoxBackup
+	jr .loop
 
-.skip_moves
-	ld a, MONMENUITEM_STATS
-	call AddMonMenuItem
-	ld a, MONMENUITEM_SWITCH
-	call AddMonMenuItem
-	ld a, MONMENUITEM_MOVE
-	call AddMonMenuItem
-	ld a, [wLinkMode]
+.quit
+	ret
+
+TryGiveItemToPartymon:
+	call SpeechTextBox
+	call PartyMonItemName
+	call GetPartyItemLocation
+	ld a, [hl]
 	and a
-	jr nz, .skip2
+	jr z, .give_item_to_mon
+
 	push hl
-	ld a, MON_ITEM
-	call GetPartyParamLocation
-	ld d, [hl]
+	ld d, a
 	farcall ItemIsMail
 	pop hl
-	ld a, MONMENUITEM_MAIL
-	jr c, .ok
-	ld a, MONMENUITEM_ITEM
+	jr c, .please_remove_mail
+	ld a, [hl]
+	jr .already_holding_item
 
-.ok
-	call AddMonMenuItem
+.give_item_to_mon
+	call GiveItemToPokemon
+	ld hl, MadeHoldText
+	call MenuTextBoxBackup
+	call GivePartyItem
+	ret
 
-.skip2
-	ld a, [wBuffer1]
-	cp NUM_MONMENU_ITEMS
-	jr z, .ok2
-	ld a, MONMENUITEM_CANCEL
-	call AddMonMenuItem
+.please_remove_mail
+	ld hl, PleaseRemoveMailText
+	call MenuTextBoxBackup
+	ret
 
-.ok2
-	call TerminateMonSubmenu
+.already_holding_item
+	ld [wNamedObjectIndexBuffer], a
+	call GetItemName
+	ld hl, SwitchAlreadyHoldingText
+	call StartMenuYesNo
+	jr c, .abort
+
+	call GiveItemToPokemon
+	ld a, [wNamedObjectIndexBuffer]
+	push af
+	ld a, [wCurItem]
+	ld [wNamedObjectIndexBuffer], a
+	pop af
+	ld [wCurItem], a
+	call ReceiveItemFromPokemon
+	jr nc, .bag_full
+
+	ld hl, TookAndMadeHoldText
+	call MenuTextBoxBackup
+	ld a, [wNamedObjectIndexBuffer]
+	ld [wCurItem], a
+	call GivePartyItem
 	ret
 
-.egg
-	ld a, MONMENUITEM_STATS
-	call AddMonMenuItem
-	ld a, MONMENUITEM_SWITCH
-	call AddMonMenuItem
-	ld a, MONMENUITEM_CANCEL
-	call AddMonMenuItem
-	call TerminateMonSubmenu
+.bag_full
+	ld a, [wNamedObjectIndexBuffer]
+	ld [wCurItem], a
+	call ReceiveItemFromPokemon
+	ld hl, ItemStorageIsFullText
+	call MenuTextBoxBackup
+
+.abort
 	ret
 
-IsFieldMove:
+GivePartyItem:
+	call GetPartyItemLocation
+	ld a, [wCurItem]
+	ld [hl], a
+	ld d, a
+	farcall ItemIsMail
+	jr nc, .done
+	call ComposeMailMessage
+
+.done
+	ret
+
+TakePartyItem:
+	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 [wNamedObjectIndexBuffer], 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
+
+GiveTakeItemMenuData:
+	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@"
+
+TookAndMadeHoldText:
+	text_jump UnknownText_0x1c1b2c
+	db "@"
+
+MadeHoldText:
+	text_jump UnknownText_0x1c1b57
+	db "@"
+
+PleaseRemoveMailText:
+	text_jump UnknownText_0x1c1b6f
+	db "@"
+
+IsntHoldingAnythingText:
+	text_jump UnknownText_0x1c1b8e
+	db "@"
+
+ItemStorageIsFullText:
+	text_jump UnknownText_0x1c1baa
+	db "@"
+
+TookFromText:
+	text_jump UnknownText_0x1c1bc4
+	db "@"
+
+SwitchAlreadyHoldingText:
+	text_jump UnknownText_0x1c1bdc
+	db "@"
+
+CantBeHeldText:
+	text_jump UnknownText_0x1c1c09
+	db "@"
+
+GetPartyItemLocation:
+	push af
+	ld a, MON_ITEM
+	call GetPartyParamLocation
+	pop af
+	ret
+
+ReceiveItemFromPokemon:
+	ld a, 1
+	ld [wItemQuantityChangeBuffer], a
+	ld hl, wNumItems
+	jp ReceiveItem
+
+GiveItemToPokemon:
+	ld a, 1
+	ld [wItemQuantityChangeBuffer], a
+	ld hl, wNumItems
+	jp TossItem
+
+StartMenuYesNo:
+	call MenuTextBox
+	call YesNoBox
+	jp ExitMenu
+
+ComposeMailMessage:
+	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:
+; 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
-	ld hl, MonMenuOptions
-.next
+	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
+
+.MenuHeader:
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 12, 10, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+	dw .MenuData
+	db 1 ; default option
+
+.MenuData:
+	db STATICMENU_CURSOR ; flags
+	db 3 ; items
+	db "READ@"
+	db "TAKE@"
+	db "QUIT@"
+
+.mailwilllosemessagetext
+; The MAIL will lose its message. OK?
+	text_jump UnknownText_0x1c1c22
+	db "@"
+
+.tookmailfrommontext
+; MAIL detached from <POKEMON>.
+	text_jump UnknownText_0x1c1c47
+	db "@"
+
+.bagfulltext
+; There's no space for removing MAIL.
+	text_jump UnknownText_0x1c1c62
+	db "@"
+
+.sendmailtopctext
+; Send the removed MAIL to your PC?
+	text_jump UnknownText_0x1c1c86
+	db "@"
+
+.mailboxfulltext
+; Your PC's MAILBOX is full.
+	text_jump UnknownText_0x1c1ca9
+	db "@"
+
+.sentmailtopctext
+; The MAIL was sent to your PC.
+	text_jump UnknownText_0x1c1cc4
+	db "@"
+
+OpenPartyStats:
+	call LoadStandardMenuHeader
+	call ClearSprites
+; PartyMon
+	xor a
+	ld [wMonType], a
+	call LowVolume
+	predef StatsScreenInit
+	call MaxVolume
+	call Call_ExitMenu
+	ld a, 0
+	ret
+
+MonMenu_Cut:
+	farcall CutFunction
+	ld a, [wFieldMoveSucceeded]
+	cp $1
+	jr nz, .Fail
+	ld b, $4
+	ld a, $2
+	ret
+
+.Fail:
+	ld a, $3
+	ret
+
+MonMenu_Fly:
+	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
+
+MonMenu_Flash:
+	farcall OWFlash
+	ld a, [wFieldMoveSucceeded]
+	cp $1
+	jr nz, .Fail
+	ld b, $4
+	ld a, $2
+	ret
+
+.Fail:
+	ld a, $3
+	ret
+
+MonMenu_Strength:
+	farcall StrengthFunction
+	ld a, [wFieldMoveSucceeded]
+	cp $1
+	jr nz, .Fail
+	ld b, $4
+	ld a, $2
+	ret
+
+.Fail:
+	ld a, $3
+	ret
+
+MonMenu_Whirlpool:
+	farcall WhirlpoolFunction
+	ld a, [wFieldMoveSucceeded]
+	cp $1
+	jr nz, .Fail
+	ld b, $4
+	ld a, $2
+	ret
+
+.Fail:
+	ld a, $3
+	ret
+
+MonMenu_Waterfall:
+	farcall WaterfallFunction
+	ld a, [wFieldMoveSucceeded]
+	cp $1
+	jr nz, .Fail
+	ld b, $4
+	ld a, $2
+	ret
+
+.Fail:
+	ld a, $3
+	ret
+
+MonMenu_Teleport:
+	farcall TeleportFunction
+	ld a, [wFieldMoveSucceeded]
+	and a
+	jr z, .Fail
+	ld b, $4
+	ld a, $2
+	ret
+
+.Fail:
+	ld a, $3
+	ret
+
+MonMenu_Surf:
+	farcall SurfFunction
+	ld a, [wFieldMoveSucceeded]
+	and a
+	jr z, .Fail
+	ld b, $4
+	ld a, $2
+	ret
+
+.Fail:
+	ld a, $3
+	ret
+
+MonMenu_Dig:
+	farcall DigFunction
+	ld a, [wFieldMoveSucceeded]
+	cp $1
+	jr nz, .Fail
+	ld b, $4
+	ld a, $2
+	ret
+
+.Fail:
+	ld a, $3
+	ret
+
+MonMenu_Softboiled_MilkDrink:
+	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
+
+.Text_NotEnoughHP:
+	; Not enough HP!
+	text_jump UnknownText_0x1c1ce3
+	db "@"
+
+.CheckMonHasEnoughHP:
+; Need to have at least (MaxHP / 5) HP left.
+	ld a, MON_MAXHP
+	call GetPartyParamLocation
 	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
+	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
 
-.nope
+MonMenu_Headbutt:
+	farcall HeadbuttFunction
+	ld a, [wFieldMoveSucceeded]
+	cp $1
+	jr nz, .Fail
+	ld b, $4
+	ld a, $2
 	ret
 
-ResetMonSubmenu:
+.Fail:
+	ld a, $3
+	ret
+
+MonMenu_RockSmash:
+	farcall RockSmashFunction
+	ld a, [wFieldMoveSucceeded]
+	cp $1
+	jr nz, .Fail
+	ld b, $4
+	ld a, $2
+	ret
+
+.Fail:
+	ld a, $3
+	ret
+
+MonMenu_SweetScent:
+	farcall SweetScentFromMenu
+	ld b, $4
+	ld a, $2
+	ret
+
+ChooseMoveToDelete:
+	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
+
+.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
+
+.a_button
+	and a
+	jr .finish
+
+.b_button
+	scf
+
+.finish
+	push af
 	xor a
-	ld [wBuffer1], a
-	ld hl, wBuffer2
-	ld bc, NUM_MONMENU_ITEMS + 1
-	call ByteFill
+	ld [wSwitchMon], a
+	ld hl, w2DMenuFlags1
+	res 6, [hl]
+	call ClearSprites
+	call ClearTileMap
+	pop af
 	ret
 
-TerminateMonSubmenu:
-	ld a, [wBuffer1]
-	ld e, a
-	ld d, 0
-	ld hl, wBuffer2
-	add hl, de
-	ld [hl], -1
+DeleteMoveScreenAttrs:
+	db 3, 1
+	db 3, 1
+	db $40, $00
+	dn 2, 0
+	db D_UP | D_DOWN | A_BUTTON | B_BUTTON
+
+ManagePokemonMoves:
+	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
 
-AddMonMenuItem:
+MoveScreenLoop:
+	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
+
+.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
+
+.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
-	push de
-	push af
-	ld a, [wBuffer1]
+	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
+
+.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
+
+.exit
+	xor a
+	ld [wMoveSwapBuffer], a
+	ld hl, w2DMenuFlags1
+	res 6, [hl]
+	call ClearSprites
+	jp ClearTileMap
+
+MoveScreenAttributes:
+	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
+
+String_MoveWhere:
+	db "Where?@"
+
+SetUpMoveScreenBG:
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	xor a
+	ld [hBGMapMode], a
+	farcall LoadStatsScreenPageTilesGFX
+	farcall ClearSpriteAnims2
+	ld a, [wCurPartyMon]
 	ld e, a
-	inc a
-	ld [wBuffer1], a
-	ld d, 0
-	ld hl, wBuffer2
+	ld d, $0
+	ld hl, wPartySpecies
 	add hl, de
-	pop af
-	ld [hl], a
-	pop de
+	ld a, [hl]
+	ld [wTempIconSpecies], a
+	ld e, MONICON_MOVES
+	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
-	ret
+	call PrintLevel
+	ld hl, wPlayerHPPal
+	call SetHPPal
+	ld b, SCGB_MOVE_LIST
+	call GetSGBLayout
+	hlcoord 16, 0
+	lb bc, 1, 3
+	jp ClearBox
 
-BattleMonMenu:
-	ld hl, MenuHeader_0x24ed4
-	call CopyMenuHeader
+SetUpMoveList:
 	xor a
 	ld [hBGMapMode], a
-	call MenuBox
-	call UpdateSprites
-	call PlaceVerticalMenuItems
+	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 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
+	call SetPalettes
+	ld a, [wNumMoves]
+	inc a
+	ld [w2DMenuNumRows], a
+	hlcoord 0, 11
+	ld b, 5
+	ld c, 18
+	jp TextBox
 
-.set_carry
-	scf
+PrepareToPlaceMoveData:
+	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 [wCurSpecies], a
+	hlcoord 1, 12
+	lb bc, 5, 18
+	jp ClearBox
+
+PlaceMoveData:
+	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, [wCurSpecies]
+	ld b, a
+	hlcoord 2, 12
+	predef PrintMoveType
+	ld a, [wCurSpecies]
+	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 [wDeciramBuffer], a
+	ld de, wDeciramBuffer
+	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
 
-.clear_carry
+String_MoveType_Top:
+	db "┌─────┐@"
+String_MoveType_Bottom:
+	db "│TYPE/└@"
+String_MoveAtk:
+	db "ATK/@"
+String_MoveNoPower:
+	db "---@"
+
+Function132d3:
+	call Function132da
+	call Function132fe
+	ret
+
+Function132da:
+	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
 
-MenuHeader_0x24ed4:
-	db 0 ; flags
-	menu_coords 11, 11, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
-	dw MenuData_0x24edc
-	db 1 ; default option
+.legal
+	hlcoord 16, 0
+	ld [hl], "◀"
+	ret
 
-MenuData_0x24edc:
-	db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
-	db 3 ; items
-	db "SWITCH@"
-	db "STATS@"
-	db "CANCEL@"
+Function132fe:
+	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
--- /dev/null
+++ b/engine/pokemon/mon_submenu.asm
@@ -1,0 +1,290 @@
+INCLUDE "data/mon_menu.asm"
+
+MonSubmenu:
+	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
+
+.MenuHeader:
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 6, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+	dw 0
+	db 1 ; default option
+
+.GetTopCoord:
+; 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
+
+MonMenuLoop:
+.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
+
+PopulateMonMenu:
+	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
+
+GetMonMenuString:
+	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 [wNamedObjectIndexBuffer], a
+	call GetMoveName
+	ret
+
+.NotMove:
+	inc hl
+	ld a, [hl]
+	dec a
+	ld hl, MonMenuOptionStrings
+	call GetNthString
+	ld d, h
+	ld e, l
+	ret
+
+GetMonSubmenuItems:
+	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
+
+IsFieldMove:
+	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
+
+ResetMonSubmenu:
+	xor a
+	ld [wBuffer1], a
+	ld hl, wBuffer2
+	ld bc, NUM_MONMENU_ITEMS + 1
+	call ByteFill
+	ret
+
+TerminateMonSubmenu:
+	ld a, [wBuffer1]
+	ld e, a
+	ld d, 0
+	ld hl, wBuffer2
+	add hl, de
+	ld [hl], -1
+	ret
+
+AddMonMenuItem:
+	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
+
+BattleMonMenu:
+	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
+
+MenuHeader_0x24ed4:
+	db 0 ; flags
+	menu_coords 11, 11, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+	dw MenuData_0x24edc
+	db 1 ; default option
+
+MenuData_0x24edc:
+	db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags
+	db 3 ; items
+	db "SWITCH@"
+	db "STATS@"
+	db "CANCEL@"
--- /dev/null
+++ b/engine/pokemon/print_move_description.asm
@@ -1,0 +1,14 @@
+PrintMoveDesc:
+	push hl
+	ld hl, MoveDescriptions
+	ld a, [wCurSpecies]
+	dec a
+	ld c, a
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld e, a
+	ld d, [hl]
+	pop hl
+	jp PlaceString
--- a/main.asm
+++ b/main.asm
@@ -57,6 +57,7 @@
 INCLUDE "engine/events/forced_movement.asm"
 INCLUDE "engine/events/itemfinder.asm"
 INCLUDE "engine/menus/start_menu.asm"
+INCLUDE "engine/pokemon/mon_menu.asm"
 INCLUDE "engine/overworld/select_menu.asm"
 INCLUDE "engine/events/elevator.asm"
 INCLUDE "engine/events/bug_contest/contest.asm"
@@ -109,7 +110,7 @@
 INCLUDE "engine/menus/scrolling_menu.asm"
 INCLUDE "engine/items/switch_items.asm"
 INCLUDE "engine/menus/menu_2.asm"
-INCLUDE "engine/pokemon/mon_menu.asm"
+INCLUDE "engine/pokemon/mon_submenu.asm"
 INCLUDE "engine/battle/menu.asm"
 INCLUDE "engine/items/buy_sell_toss.asm"
 INCLUDE "engine/menus/trainer_card.asm"
@@ -144,6 +145,7 @@
 INCLUDE "engine/events/move_deleter.asm"
 INCLUDE "engine/link/mystery_gift_2.asm"
 INCLUDE "engine/items/tmhm.asm"
+INCLUDE "engine/pokemon/print_move_description.asm"
 INCLUDE "data/moves/descriptions.asm"
 INCLUDE "engine/events/pokerus/pokerus.asm"
 INCLUDE "engine/battle/start_battle.asm"