shithub: pokecrystal

Download patch

ref: 97c511cd2f271252cbc9e9746668081422231ca5
parent: baa0dc5a963a79843b37888bcfe1d2dfe833ade9
author: mid-kid <esteve.varela@gmail.com>
date: Wed Mar 14 09:28:36 EDT 2018

Organize the engine/ directory, take 2

Renamed `game` to `games` and `menu` to `menus`.
Moved some functions from `engine/routines/` to their fitting subdirectories.

Made two new subdirectories:
* engine/rtc: Contains all RTC-related things. Menus, hardware, misc
functions.
* engine/items: Contains all item-related things. Pack, item effects,
other item handlers.

diff: cannot open a/engine/game//null: file does not exist: 'a/engine/game//null' diff: cannot open b/engine/games//null: file does not exist: 'b/engine/games//null' diff: cannot open b/engine/items//null: file does not exist: 'b/engine/items//null' diff: cannot open a/engine/menu//null: file does not exist: 'a/engine/menu//null' diff: cannot open b/engine/menus//null: file does not exist: 'b/engine/menus//null' diff: cannot open b/engine/rtc//null: file does not exist: 'b/engine/rtc//null'
--- a/engine/game/card_flip.asm
+++ /dev/null
@@ -1,1692 +1,0 @@
-CARDFLIP_LIGHT_OFF EQU $ef
-CARDFLIP_LIGHT_ON  EQU $f5
-
-CARDFLIP_DECK_SIZE EQU 4 * 6
-
-; two labels below called from inside ./dummy_game.asm
-Unknown_e00ed: ; e00ed (38:40ed)
-; Graphics for an unused Game Corner
-; game were meant to be here.
-ret_e00ed: ; e00ed (38:40ed)
-	ret
-
-_CardFlip: ; e00ee (38:40ee)
-	ld hl, wOptions
-	set 4, [hl]
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	ld de, MUSIC_NONE
-	call PlayMusic
-	call DelayFrame
-	call DisableLCD
-	call LoadStandardFont
-	call LoadFontsExtra
-
-	ld hl, CardFlipLZ01
-	ld de, vTiles2 tile $00
-	call Decompress
-	ld hl, CardFlipLZ02
-	ld de, vTiles2 tile $3e
-	call Decompress
-	ld hl, CardFlipLZ03
-	ld de, vTiles0 tile $00
-	call Decompress
-	ld hl, CardFlipOffButtonGFX
-	ld de, vTiles0 tile CARDFLIP_LIGHT_OFF
-	ld bc, 1 tiles
-	call CopyBytes
-	ld hl, CardFlipOnButtonGFX
-	ld de, vTiles0 tile CARDFLIP_LIGHT_ON
-	ld bc, 1 tiles
-	call CopyBytes
-
-	call CardFlip_ShiftDigitsLeftTwoPixels
-	call CardFlip_InitTilemap
-	call CardFlip_InitAttrPals
-	call EnableLCD
-	call WaitBGMap2
-	ld a, $e4
-	call DmgToCgbBGPals
-	ld de, $e4e4
-	call DmgToCgbObjPals
-	call DelayFrame
-	xor a
-	ld [wJumptableIndex], a
-	ld a, $2
-	ld [wCardFlipCursorY], a
-	ld [wCardFlipCursorX], a
-	ld de, MUSIC_GAME_CORNER
-	call PlayMusic
-.MasterLoop:
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .leavethegame
-	call .CardFlip
-	jr .MasterLoop
-.leavethegame
-	call WaitSFX
-	ld de, SFX_QUIT_SLOTS
-	call PlaySFX
-	call WaitSFX
-	call ClearBGPalettes
-	ld hl, wOptions
-	res 4, [hl]
-	ret
-
-.CardFlip: ; e0191 (38:4191)
-	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
-; e01a0 (38:41a0)
-
-.Jumptable: ; e01a0
-	dw .AskPlayWithThree
-	dw .DeductCoins
-	dw .ChooseACard
-	dw .PlaceYourBet
-	dw .CheckTheCard
-	dw .TabulateTheResult
-	dw .PlayAgain
-	dw .Quit
-; e01b0
-
-.Increment: ; e01b0
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-; e01b5
-
-.AskPlayWithThree: ; e01b5
-	ld hl, .PlayWithThreeCoinsText
-	call CardFlip_UpdateCoinBalanceDisplay
-	call YesNoBox
-	jr c, .SaidNo
-	call CardFlip_ShuffleDeck
-	call .Increment
-	ret
-
-.SaidNo:
-	ld a, 7
-	ld [wJumptableIndex], a
-	ret
-; e01cd
-
-.PlayWithThreeCoinsText: ; 0xe01cd
-	; Play with three coins?
-	text_jump UnknownText_0x1c5793
-	db "@"
-; 0xe01d2
-
-.DeductCoins: ; e01d2
-	ld a, [wCoins]
-	ld h, a
-	ld a, [wCoins + 1]
-	ld l, a
-	ld a, h
-	and a
-	jr nz, .deduct ; You have at least 256 coins.
-	ld a, l
-	cp 3
-	jr nc, .deduct ; You have at least 3 coins.
-	ld hl, .NotEnoughCoinsText
-	call CardFlip_UpdateCoinBalanceDisplay
-	ld a, 7
-	ld [wJumptableIndex], a
-	ret
-
-.deduct
-	ld de, -3
-	add hl, de
-	ld a, h
-	ld [wCoins], a
-	ld a, l
-	ld [wCoins + 1], a
-	ld de, SFX_TRANSACTION
-	call PlaySFX
-	xor a
-	ld [hBGMapMode], a
-	call CardFlip_PrintCoinBalance
-	ld a, $1
-	ld [hBGMapMode], a
-	call WaitSFX
-	call .Increment
-	ret
-; e0212
-
-.NotEnoughCoinsText: ; 0xe0212
-	; Not enough coins…
-	text_jump UnknownText_0x1c57ab
-	db "@"
-; 0xe0217
-
-.ChooseACard: ; e0217
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 0, 0
-	lb bc, 12, 9
-	call CardFlip_FillGreenBox
-	hlcoord 9, 0
-	ld bc, SCREEN_WIDTH
-	ld a, [wCardFlipNumCardsPlayed]
-	call AddNTimes
-	ld [hl], CARDFLIP_LIGHT_ON
-	ld a, $1
-	ld [hBGMapMode], a
-	ld c, 20
-	call DelayFrames
-	hlcoord 2, 0
-	call PlaceCardFaceDown
-	ld a, $1
-	ld [hBGMapMode], a
-	ld c, 20
-	call DelayFrames
-	hlcoord 2, 6
-	call PlaceCardFaceDown
-	call WaitBGMap
-	ld hl, .ChooseACardText
-	call CardFlip_UpdateCoinBalanceDisplay
-	xor a
-	ld [wCardFlipWhichCard], a
-.loop
-	call JoyTextDelay
-	ld a, [hJoyLast]
-	and A_BUTTON
-	jr nz, .next
-	ld de, SFX_KINESIS
-	call PlaySFX
-	call PlaceOAMCardBorder
-	ld c, 4
-	call DelayFrames
-	ld hl, wCardFlipWhichCard
-	ld a, [hl]
-	xor $1
-	ld [hl], a
-	jr .loop
-
-.next
-	ld de, SFX_SLOT_MACHINE_START
-	call PlaySFX
-	ld a, $3
-.loop2
-	push af
-	call PlaceOAMCardBorder
-	ld c, 4
-	call DelayFrames
-	call ClearSprites
-	ld c, 4
-	call DelayFrames
-	pop af
-	dec a
-	jr nz, .loop2
-	ld hl, wCardFlipWhichCard
-	ld a, [hl]
-	push af
-	xor $1
-	ld [hl], a
-	call GetCoordsOfChosenCard
-	lb bc, 6, 5
-	call CardFlip_FillGreenBox
-	pop af
-	ld [wCardFlipWhichCard], a
-	call .Increment
-	ret
-; e02b2
-
-.ChooseACardText: ; 0xe02b2
-	; Choose a card.
-	text_jump UnknownText_0x1c57be
-	db "@"
-; 0xe02b7
-
-.PlaceYourBet: ; e02b7
-	ld hl, .PlaceYourBetText
-	call CardFlip_UpdateCoinBalanceDisplay
-.betloop
-	call JoyTextDelay
-	ld a, [hJoyLast]
-	and A_BUTTON
-	jr nz, .betdone
-	call ChooseCard_HandleJoypad
-	call CardFlip_UpdateCursorOAM
-	call DelayFrame
-	jr .betloop
-
-.betdone
-	call .Increment
-	ret
-; e02d5
-
-.PlaceYourBetText: ; 0xe02d5
-	; Place your bet.
-	text_jump UnknownText_0x1c57ce
-	db "@"
-; 0xe02da
-
-.CheckTheCard: ; e02da
-	xor a
-	ld [hVBlankCounter], a
-	call CardFlip_UpdateCursorOAM
-	call WaitSFX
-	ld de, SFX_CHOOSE_A_CARD
-	call PlaySFX
-	call WaitSFX
-	ld a, [wCardFlipNumCardsPlayed]
-	ld e, a
-	ld d, 0
-	ld hl, wDeck
-	add hl, de
-	add hl, de
-	ld a, [wCardFlipWhichCard]
-	ld e, a
-	add hl, de
-	ld a, [hl]
-	ld [wCardFlipFaceUpCard], a
-	ld e, a
-	ld hl, wDiscardPile
-	add hl, de
-	ld [hl], TRUE
-	call GetCoordsOfChosenCard
-	call CardFlip_DisplayCardFaceUp
-	call WaitBGMap2
-	call .Increment
-	ret
-; e0314
-
-.TabulateTheResult: ; e0314
-	call CardFlip_CheckWinCondition
-	call WaitPressAorB_BlinkCursor
-	call .Increment
-	ret
-; e031e
-
-.PlayAgain: ; e031e
-	call ClearSprites
-	ld hl, .PlayAgainText
-	call CardFlip_UpdateCoinBalanceDisplay
-	call YesNoBox
-	jr nc, .Continue
-	call .Increment
-	ret
-
-.Continue:
-	ld a, [wCardFlipNumCardsPlayed]
-	inc a
-	ld [wCardFlipNumCardsPlayed], a
-	cp 12
-	jr c, .KeepTheCurrentDeck
-	call CardFlip_InitTilemap
-	ld a, $1
-	ld [hBGMapMode], a
-	call CardFlip_ShuffleDeck
-	ld hl, .CardsShuffledText
-	call PrintText
-	jr .LoopAround
-
-.KeepTheCurrentDeck:
-	call CardFlip_BlankDiscardedCardSlot
-
-.LoopAround:
-	ld a, 1
-	ld [wJumptableIndex], a
-	ret
-; e0356
-
-.PlayAgainText: ; 0xe0356
-	; Want to play again?
-	text_jump UnknownText_0x1c57df
-	db "@"
-; 0xe035b
-
-.CardsShuffledText: ; 0xe035b
-	; The cards have been shuffled.
-	text_jump UnknownText_0x1c57f4
-	db "@"
-; 0xe0360
-
-.Quit: ; e0360
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-; e0366
-
-CardFlip_ShuffleDeck: ; e0366
-	ld hl, wDeck
-	ld bc, CARDFLIP_DECK_SIZE
-	xor a
-	call ByteFill
-	ld de, wDeck
-	ld c, CARDFLIP_DECK_SIZE - 1
-.loop
-	call Random
-	and $1f
-	cp CARDFLIP_DECK_SIZE
-	jr nc, .loop
-	ld l, a
-	ld h, $0
-	add hl, de
-	ld a, [hl]
-	and a
-	jr nz, .loop
-	ld [hl], c
-	dec c
-	jr nz, .loop
-	xor a
-	ld [wCardFlipNumCardsPlayed], a
-	ld hl, wDiscardPile
-	ld bc, CARDFLIP_DECK_SIZE
-	call ByteFill
-	ret
-; e0398
-
-CollapseCursorPosition: ; e0398
-	ld hl, 0
-	ld bc, 6
-	ld a, [wCardFlipCursorY]
-	call AddNTimes
-	ld b, $0
-	ld a, [wCardFlipCursorX]
-	ld c, a
-	add hl, bc
-	ret
-; e03ac
-
-GetCoordsOfChosenCard: ; e03ac
-	ld a, [wCardFlipWhichCard]
-	and a
-	jr nz, .BottomCard
-	hlcoord 2, 0
-	bcpixel 2, 3
-	jr .done
-
-.BottomCard:
-	hlcoord 2, 6
-	bcpixel 8, 3
-
-.done
-	ret
-; e03c1
-
-PlaceCardFaceDown: ; e03c1
-	xor a
-	ld [hBGMapMode], a
-	ld de, .FaceDownCardTilemap
-	lb bc, 6, 5
-	call CardFlip_CopyToBox
-	ret
-; e03ce
-
-.FaceDownCardTilemap: ; e03ce
-	db $08, $09, $09, $09, $0a
-	db $0b, $28, $2b, $28, $0c
-	db $0b, $2c, $2d, $2e, $0c
-	db $0b, $2f, $30, $31, $0c
-	db $0b, $32, $33, $34, $0c
-	db $0d, $0e, $0e, $0e, $0f
-; e03ec
-
-CardFlip_DisplayCardFaceUp: ; e03ec
-	xor a
-	ld [hBGMapMode], a
-	push hl
-	push hl
-	; Flip the card face up.
-	ld de, .FaceUpCardTilemap
-	lb bc, 6, 5
-	call CardFlip_CopyToBox
-
-	; Get the level and species of the upturned card.
-	ld a, [wCardFlipFaceUpCard]
-	ld e, a
-	ld d, 0
-	ld hl, .Deck
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld e, a
-	ld d, [hl]
-
-	; Place the level.
-	pop hl
-	ld bc, 3 + SCREEN_WIDTH
-	add hl, bc
-	ld [hl], e
-
-	; Place the Pokepic.
-	ld bc, SCREEN_HEIGHT
-	add hl, bc
-	ld a, d
-	ld de, SCREEN_WIDTH
-	ld b, 3
-.row
-	push hl
-	ld c, 3
-.col
-	ld [hli], a
-	inc a
-	dec c
-	jr nz, .col
-	pop hl
-	add hl, de
-	dec b
-	jr nz, .row
-	pop hl
-
-	; Pointless CGB check
-	ld a, [hCGB]
-	and a
-	ret z
-
-	; Set the attributes
-	ld de, wAttrMap - wTileMap
-	add hl, de
-	ld a, [wCardFlipFaceUpCard]
-	and 3
-	inc a
-	lb bc, 6, 5
-	call CardFlip_FillBox
-	ret
-; e043b
-
-.FaceUpCardTilemap: ; e043b
-	db $18, $19, $19, $19, $1a
-	db $1b, $35, $7f, $7f, $1c
-	db $0b, $28, $28, $28, $0c
-	db $0b, $28, $28, $28, $0c
-	db $0b, $28, $28, $28, $0c
-	db $1d, $1e, $1e, $1e, $1f
-; e0459
-
-.Deck: ; e0459
-	; level, pic anchor (3x3)
-	db "1", $4e, "1", $57, "1", $69, "1", $60
-	db "2", $4e, "2", $57, "2", $69, "2", $60
-	db "3", $4e, "3", $57, "3", $69, "3", $60
-	db "4", $4e, "4", $57, "4", $69, "4", $60
-	db "5", $4e, "5", $57, "5", $69, "5", $60
-	db "6", $4e, "6", $57, "6", $69, "6", $60
-; e0489
-
-CardFlip_UpdateCoinBalanceDisplay: ; e0489
-	push hl
-	hlcoord 0, 12
-	ld b, 4
-	ld c, SCREEN_WIDTH - 2
-	call TextBox
-	pop hl
-	call PrintTextBoxText
-	call CardFlip_PrintCoinBalance
-	ret
-; e049c
-
-CardFlip_PrintCoinBalance: ; e049c
-	hlcoord 9, 15
-	ld b, 1
-	ld c, 9
-	call TextBox
-	hlcoord 10, 16
-	ld de, .CoinStr
-	call PlaceString
-	hlcoord 15, 16
-	ld de, wCoins
-	lb bc, PRINTNUM_LEADINGZEROS | 2, 4
-	call PrintNum
-	ret
-; e04bc
-
-.CoinStr:
-	db "COIN@"
-; e04c1
-
-CardFlip_InitTilemap: ; e04c1 (38:44c1)
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 0, 0
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	ld a, $29
-	call ByteFill
-	hlcoord 9, 0
-	ld de, CardFlipTilemap
-	lb bc, 12, 11
-	call CardFlip_CopyToBox
-	hlcoord 0, 12
-	lb bc, 4, 18
-	call TextBox
-	ret
-; e04e5 (38:44e5)
-
-CardFlip_FillGreenBox: ; e04e5
-	ld a, $29
-
-CardFlip_FillBox: ; e04e7 (38:44e7)
-.row
-	push bc
-	push hl
-.col
-	ld [hli], a
-	dec c
-	jr nz, .col
-	pop hl
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	pop bc
-	dec b
-	jr nz, .row
-	ret
-
-CardFlip_CopyToBox: ; e04f7 (38:44f7)
-.row
-	push bc
-	push hl
-.col
-	ld a, [de]
-	inc de
-	ld [hli], a
-	dec c
-	jr nz, .col
-	pop hl
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	pop bc
-	dec b
-	jr nz, .row
-	ret
-; e0509 (38:4509)
-
-CardFlip_CopyOAM: ; e0509
-	ld de, wVirtualOAMSprite00
-	ld a, [hli]
-.loop
-	push af
-	ld a, [hli]
-	add b
-	ld [de], a ; y
-	inc de
-	ld a, [hli]
-	add c
-	ld [de], a ; x
-	inc de
-	ld a, [hli]
-	ld [de], a ; tile id
-	inc de
-	ld a, [hli]
-	ld [de], a ; attributes
-	inc de
-	pop af
-	dec a
-	jr nz, .loop
-	ret
-; e0521
-
-CardFlip_ShiftDigitsLeftTwoPixels: ; e0521 (38:4521)
-	ld de, vTiles0 tile "0"
-	ld hl, vTiles0 tile "0" + 2
-	ld bc, 10 tiles - 2
-	call CopyBytes
-	ld hl, vTiles0 tile "9" + 1 tiles - 2
-	xor a
-	ld [hli], a
-	ld [hl], a
-	ret
-; e0534 (38:4534)
-
-CardFlip_BlankDiscardedCardSlot: ; e0534
-	xor a
-	ld [hBGMapMode], a
-	ld a, [wCardFlipFaceUpCard]
-	ld e, a
-	ld d, 0
-
-	and 3 ; get mon
-	ld c, a
-	ld b, 0
-
-	ld a, e
-	and $1c ; get level
-	srl a
-	add LOW(.Jumptable)
-	ld l, a
-	ld a, 0
-	adc HIGH(.Jumptable)
-	ld h, a
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-; e0553
-
-.Jumptable: ; e0553
-	dw .Level1
-	dw .Level2
-	dw .Level3
-	dw .Level4
-	dw .Level5
-	dw .Level6
-; e055f
-
-.Level1: ; e055f
-	ld hl, wDiscardPile + 4
-	add hl, de
-	ld a, [hl]
-	and a
-	jr nz, .discarded2
-	hlcoord 13, 3
-	add hl, bc
-	add hl, bc
-	ld [hl], $36
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hl], $37
-	ret
-
-.discarded2
-	hlcoord 13, 3
-	add hl, bc
-	add hl, bc
-	ld [hl], $36
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hl], $3d
-	ret
-; e0583
-
-.Level2: ; e0583
-	ld hl, wDiscardPile - 4
-	add hl, de
-	ld a, [hl]
-	and a
-	jr nz, .discarded1
-	hlcoord 13, 4
-	add hl, bc
-	add hl, bc
-	ld [hl], $3b
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hl], $3a
-	ret
-
-.discarded1
-	hlcoord 13, 4
-	add hl, bc
-	add hl, bc
-	ld [hl], $3d
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hl], $3a
-	ret
-; e05a7
-
-.Level3: ; e05a7
-	ld hl, wDiscardPile + 4
-	add hl, de
-	ld a, [hl]
-	and a
-	jr nz, .discarded4
-	hlcoord 13, 6
-	add hl, bc
-	add hl, bc
-	ld [hl], $36
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hl], $38
-	ret
-
-.discarded4
-	hlcoord 13, 6
-	add hl, bc
-	add hl, bc
-	ld [hl], $36
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hl], $3d
-	ret
-; e05cb
-
-.Level4: ; e05cb
-	ld hl, wDiscardPile - 4
-	add hl, de
-	ld a, [hl]
-	and a
-	jr nz, .discarded3
-	hlcoord 13, 7
-	add hl, bc
-	add hl, bc
-	ld [hl], $3c
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hl], $3a
-	ret
-
-.discarded3
-	hlcoord 13, 7
-	add hl, bc
-	add hl, bc
-	ld [hl], $3d
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hl], $3a
-	ret
-; e05ef
-
-.Level5: ; e05ef
-	ld hl, wDiscardPile + 4
-	add hl, de
-	ld a, [hl]
-	and a
-	jr nz, .discarded6
-	hlcoord 13, 9
-	add hl, bc
-	add hl, bc
-	ld [hl], $36
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hl], $39
-	ret
-
-.discarded6
-	hlcoord 13, 9
-	add hl, bc
-	add hl, bc
-	ld [hl], $36
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hl], $3d
-	ret
-; e0613
-
-.Level6: ; e0613
-	ld hl, wDiscardPile - 4
-	add hl, de
-	ld a, [hl]
-	and a
-	jr nz, .discarded5
-	hlcoord 13, 10
-	add hl, bc
-	add hl, bc
-	ld [hl], $3c
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hl], $3a
-	ret
-
-.discarded5
-	hlcoord 13, 10
-	add hl, bc
-	add hl, bc
-	ld [hl], $3d
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hl], $3a
-	ret
-; e0637
-
-CardFlip_CheckWinCondition: ; e0637
-	call CollapseCursorPosition
-	add hl, hl
-	ld de, .Jumptable
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-; e0643
-
-.Jumptable: ; e0643
-	dw .Impossible
-	dw .Impossible
-	dw .PikaJiggly
-	dw .PikaJiggly
-	dw .PoliOddish
-	dw .PoliOddish
-
-	dw .Impossible
-	dw .Impossible
-	dw .Pikachu
-	dw .Jigglypuff
-	dw .Poliwag
-	dw .Oddish
-
-	dw .OneTwo
-	dw .One
-	dw .PikaOne
-	dw .JigglyOne
-	dw .PoliOne
-	dw .OddOne
-
-	dw .OneTwo
-	dw .Two
-	dw .PikaTwo
-	dw .JigglyTwo
-	dw .PoliTwo
-	dw .OddTwo
-
-	dw .ThreeFour
-	dw .Three
-	dw .PikaThree
-	dw .JigglyThree
-	dw .PoliThree
-	dw .OddThree
-
-	dw .ThreeFour
-	dw .Four
-	dw .PikaFour
-	dw .JigglyFour
-	dw .PoliFour
-	dw .OddFour
-
-	dw .FiveSix
-	dw .Five
-	dw .PikaFive
-	dw .JigglyFive
-	dw .PoliFive
-	dw .OddFive
-
-	dw .FiveSix
-	dw .Six
-	dw .PikaSix
-	dw .JigglySix
-	dw .PoliSix
-	dw .OddSix
-; e06a3
-
-.Impossible: ; e06a3
-	jp .Lose
-; e06a6
-
-.PikaJiggly: ; e06a6
-	ld a, [wCardFlipFaceUpCard]
-	and $2
-	jp nz, .Lose
-	jr .WinSix
-
-.PoliOddish: ; e06b0
-	ld a, [wCardFlipFaceUpCard]
-	and $2
-	jr nz, .WinSix
-	jp .Lose
-
-.WinSix: ; e06ba
-	ld c, $6
-	ld de, SFX_2ND_PLACE
-	jp .Payout
-; e06c2
-
-.OneTwo: ; e06c2
-	ld a, [wCardFlipFaceUpCard]
-	and $18
-	jr z, .WinNine
-	jp .Lose
-
-.ThreeFour: ; e06cc
-	ld a, [wCardFlipFaceUpCard]
-	and $18
-	cp $8
-	jr z, .WinNine
-	jp .Lose
-
-.FiveSix: ; e06d8
-	ld a, [wCardFlipFaceUpCard]
-	and $18
-	cp $10
-	jr z, .WinNine
-	jp .Lose
-
-.WinNine: ; e06e4
-	ld c, $9
-	ld de, SFX_2ND_PLACE
-	jp .Payout
-; e06ec
-
-.Pikachu: ; e06ec
-	ld a, [wCardFlipFaceUpCard]
-	and $3
-	jr z, .WinTwelve
-	jp .Lose
-
-.Jigglypuff: ; e06f6
-	ld a, [wCardFlipFaceUpCard]
-	and $3
-	cp $1
-	jr z, .WinTwelve
-	jp .Lose
-
-.Poliwag: ; e0702
-	ld a, [wCardFlipFaceUpCard]
-	and $3
-	cp $2
-	jr z, .WinTwelve
-	jp .Lose
-
-.Oddish: ; e070e
-	ld a, [wCardFlipFaceUpCard]
-	and $3
-	cp $3
-	jr z, .WinTwelve
-	jp .Lose
-
-.WinTwelve: ; e071a
-	ld c, $c
-	ld de, SFX_2ND_PLACE
-	jp .Payout
-; e0722
-
-.One: ; e0722
-	ld a, [wCardFlipFaceUpCard]
-	and $1c
-	jr z, .WinEighteen
-	jp .Lose
-
-.Two: ; e072c
-	ld a, [wCardFlipFaceUpCard]
-	and $1c
-	cp $4
-	jr z, .WinEighteen
-	jp .Lose
-
-.Three: ; e0738
-	ld a, [wCardFlipFaceUpCard]
-	and $1c
-	cp $8
-	jr z, .WinEighteen
-	jp .Lose
-
-.Four: ; e0744
-	ld a, [wCardFlipFaceUpCard]
-	and $1c
-	cp $c
-	jr z, .WinEighteen
-	jp .Lose
-
-.Five: ; e0750
-	ld a, [wCardFlipFaceUpCard]
-	and $1c
-	cp $10
-	jr z, .WinEighteen
-	jp .Lose
-
-.Six: ; e075c
-	ld a, [wCardFlipFaceUpCard]
-	and $1c
-	cp $14
-	jr z, .WinEighteen
-	jp .Lose
-
-.WinEighteen: ; e0768
-	ld c, $12
-	ld de, SFX_2ND_PLACE
-	jp .Payout
-; e0770
-
-
-.PikaOne: ; e0770
-	ld e, $0
-	jr .CheckWin72
-
-.JigglyOne: ; e0774
-	ld e, $1
-	jr .CheckWin72
-
-.PoliOne: ; e0778
-	ld e, $2
-	jr .CheckWin72
-
-.OddOne: ; e077c
-	ld e, $3
-	jr .CheckWin72
-
-.PikaTwo: ; e0780
-	ld e, $4
-	jr .CheckWin72
-
-.JigglyTwo: ; e0784
-	ld e, $5
-	jr .CheckWin72
-
-.PoliTwo: ; e0788
-	ld e, $6
-	jr .CheckWin72
-
-.OddTwo: ; e078c
-	ld e, $7
-	jr .CheckWin72
-
-.PikaThree: ; e0790
-	ld e, $8
-	jr .CheckWin72
-
-.JigglyThree: ; e0794
-	ld e, $9
-	jr .CheckWin72
-
-.PoliThree: ; e0798
-	ld e, $a
-	jr .CheckWin72
-
-.OddThree: ; e079c
-	ld e, $b
-	jr .CheckWin72
-
-.PikaFour: ; e07a0
-	ld e, $c
-	jr .CheckWin72
-
-.JigglyFour: ; e07a4
-	ld e, $d
-	jr .CheckWin72
-
-.PoliFour: ; e07a8
-	ld e, $e
-	jr .CheckWin72
-
-.OddFour: ; e07ac
-	ld e, $f
-	jr .CheckWin72
-
-.PikaFive: ; e07b0
-	ld e, $10
-	jr .CheckWin72
-
-.JigglyFive: ; e07b4
-	ld e, $11
-	jr .CheckWin72
-
-.PoliFive: ; e07b8
-	ld e, $12
-	jr .CheckWin72
-
-.OddFive: ; e07bc
-	ld e, $13
-	jr .CheckWin72
-
-.PikaSix: ; e07c0
-	ld e, $14
-	jr .CheckWin72
-
-.JigglySix: ; e07c4
-	ld e, $15
-	jr .CheckWin72
-
-.PoliSix: ; e07c8
-	ld e, $16
-	jr .CheckWin72
-
-.OddSix: ; e07cc
-	ld e, $17
-
-.CheckWin72: ; e07ce
-	ld a, [wCardFlipFaceUpCard]
-	cp e
-	jr nz, .Lose
-	ld c, 72
-	ld de, SFX_2ND_PLACE
-	jr .Payout
-
-.Lose: ; e07db
-	ld de, SFX_WRONG
-	call PlaySFX
-	ld hl, .Text_Darn
-	call CardFlip_UpdateCoinBalanceDisplay
-	call WaitSFX
-	ret
-
-.Payout: ; e07eb
-	push bc
-	push de
-	ld hl, .Text_Yeah
-	call CardFlip_UpdateCoinBalanceDisplay
-	pop de
-	call PlaySFX
-	call WaitSFX
-	pop bc
-.loop
-	push bc
-	call .IsCoinCaseFull
-	jr c, .full
-	call .AddCoinPlaySFX
-
-.full
-	call CardFlip_PrintCoinBalance
-	ld c, 2
-	call DelayFrames
-	pop bc
-	dec c
-	jr nz, .loop
-	ret
-; e0811
-
-.Text_Yeah: ; 0xe0811
-	; Yeah!
-	text_jump UnknownText_0x1c5813
-	db "@"
-; 0xe0816
-
-.Text_Darn: ; 0xe0816
-	; Darn…
-	text_jump UnknownText_0x1c581a
-	db "@"
-; 0xe081b
-
-.AddCoinPlaySFX: ; e081b
-	ld a, [wCoins]
-	ld h, a
-	ld a, [wCoins + 1]
-	ld l, a
-	inc hl
-	ld a, h
-	ld [wCoins], a
-	ld a, l
-	ld [wCoins + 1], a
-	ld de, SFX_PAY_DAY
-	call PlaySFX
-	ret
-; e0833
-
-.IsCoinCaseFull: ; e0833
-	ld a, [wCoins]
-	cp HIGH(MAX_COINS)
-	jr c, .less
-	jr z, .check_low
-	jr .more
-
-.check_low
-	ld a, [wCoins + 1]
-	cp LOW(MAX_COINS)
-	jr c, .less
-
-.more
-	scf
-	ret
-
-.less
-	and a
-	ret
-; e0849
-
-PlaceOAMCardBorder: ; e0849
-	call GetCoordsOfChosenCard
-	ld hl, .SpriteData
-	call CardFlip_CopyOAM
-	ret
-; e0853
-
-.SpriteData: ; e0853
-	db 18
-	dsprite 0, 0, 0, 0, $04, 0
-	dsprite 0, 0, 1, 0, $06, 0
-	dsprite 0, 0, 2, 0, $06, 0
-	dsprite 0, 0, 3, 0, $06, 0
-	dsprite 0, 0, 4, 0, $04, 0 | X_FLIP
-
-	dsprite 1, 0, 0, 0, $05, 0
-	dsprite 1, 0, 4, 0, $05, 0 | X_FLIP
-
-	dsprite 2, 0, 0, 0, $05, 0
-	dsprite 2, 0, 4, 0, $05, 0 | X_FLIP
-
-	dsprite 3, 0, 0, 0, $05, 0
-	dsprite 3, 0, 4, 0, $05, 0 | X_FLIP
-
-	dsprite 4, 0, 0, 0, $05, $00
-	dsprite 4, 0, 4, 0, $05, 0 | X_FLIP
-
-	dsprite 5, 0, 0, 0, $04, 0 | Y_FLIP
-	dsprite 5, 0, 1, 0, $06, 0 | Y_FLIP
-	dsprite 5, 0, 2, 0, $06, 0 | Y_FLIP
-	dsprite 5, 0, 3, 0, $06, 0 | Y_FLIP
-	dsprite 5, 0, 4, 0, $04, 0 | X_FLIP | Y_FLIP
-; e089c
-
-ChooseCard_HandleJoypad: ; e089c
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_LEFT
-	jp nz, .d_left
-	ld a, [hl]
-	and D_RIGHT
-	jp nz, .d_right
-	ld a, [hl]
-	and D_UP
-	jp nz, .d_up
-	ld a, [hl]
-	and D_DOWN
-	jp nz, .d_down
-	ret
-; e08b8
-
-.d_left ; e08b8
-	ld hl, wCardFlipCursorX
-	ld a, [wCardFlipCursorY]
-	and a
-	jr z, .mon_pair_left
-	cp $1
-	jr z, .mon_group_left
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-	jp .play_sound
-
-.mon_group_left
-	ld a, [hl]
-	cp $3
-	jr c, .left_to_number_gp
-	dec [hl]
-	jp .play_sound
-
-.mon_pair_left
-	ld a, [hl]
-	and $e
-	ld [hl], a
-	cp $3
-	jr c, .left_to_number_gp
-	dec [hl]
-	dec [hl]
-	jp .play_sound
-
-.left_to_number_gp
-	ld a, $2
-	ld [wCardFlipCursorY], a
-	ld a, $1
-	ld [wCardFlipCursorX], a
-	jp .play_sound
-; e08ef
-
-.d_right ; e08ef
-	ld hl, wCardFlipCursorX
-	ld a, [wCardFlipCursorY]
-	and a
-	jr z, .mon_pair_right
-	ld a, [hl]
-	cp $5
-	ret nc
-	inc [hl]
-	jr .play_sound
-
-.mon_pair_right
-	ld a, [hl]
-	and $e
-	ld [hl], a
-	cp $4
-	ret nc
-	inc [hl]
-	inc [hl]
-	jr .play_sound
-
-.d_up ; e090a
-	ld hl, wCardFlipCursorY
-	ld a, [wCardFlipCursorX]
-	and a
-	jr z, .num_pair_up
-	cp $1
-	jr z, .num_gp_up
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-	jr .play_sound
-
-.num_gp_up
-	ld a, [hl]
-	cp $3
-	jr c, .up_to_mon_group
-	dec [hl]
-	jr .play_sound
-
-.num_pair_up
-	ld a, [hl]
-	and $e
-	ld [hl], a
-	cp $3
-	jr c, .up_to_mon_group
-	dec [hl]
-	dec [hl]
-	jr .play_sound
-
-.up_to_mon_group
-	ld a, $1
-	ld [wCardFlipCursorY], a
-	ld a, $2
-	ld [wCardFlipCursorX], a
-	jr .play_sound
-
-.d_down ; e093d
-	ld hl, wCardFlipCursorY
-	ld a, [wCardFlipCursorX]
-	and a
-	jr z, .num_pair_down
-	ld hl, wCardFlipCursorY
-	ld a, [hl]
-	cp $7
-	ret nc
-	inc [hl]
-	jr .play_sound
-
-.num_pair_down
-	ld a, [hl]
-	and $e
-	ld [hl], a
-	cp $6
-	ret nc
-	inc [hl]
-	inc [hl]
-
-.play_sound ; e0959
-	ld de, SFX_POKEBALLS_PLACED_ON_TABLE
-	call PlaySFX
-	ret
-; e0960
-
-CardFlip_UpdateCursorOAM: ; e0960
-	call ClearSprites
-	ld a, [hCGB]
-	and a
-	jr nz, .skip
-	ld a, [hVBlankCounter]
-	and $4
-	ret nz
-
-.skip
-	call CollapseCursorPosition
-	add hl, hl
-	add hl, hl
-	ld de, .OAMData
-	add hl, de
-	ld a, [hli]
-	ld c, a
-	ld a, [hli]
-	ld b, a
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	call CardFlip_CopyOAM
-	ret
-; e0981
-
-.OAMData: ; e0981
-cardflip_cursor: MACRO
-if _NARG >= 5
-	dbpixel \1, \2, \3, \4
-	dw \5
-else
-	dbpixel \1, \2
-	dw \3
-endc
-ENDM
-
-	cardflip_cursor 11,  2,       .Impossible
-	cardflip_cursor 12,  2,       .Impossible
-	cardflip_cursor 13,  2,       .PokeGroupPair
-	cardflip_cursor 13,  2,       .PokeGroupPair
-	cardflip_cursor 17,  2,       .PokeGroupPair
-	cardflip_cursor 17,  2,       .PokeGroupPair
-
-	cardflip_cursor 11,  3,       .Impossible
-	cardflip_cursor 12,  3,       .Impossible
-	cardflip_cursor 13,  3,       .PokeGroup
-	cardflip_cursor 15,  3,       .PokeGroup
-	cardflip_cursor 17,  3,       .PokeGroup
-	cardflip_cursor 19,  3,       .PokeGroup
-
-	cardflip_cursor 11,  5,       .NumGroupPair
-	cardflip_cursor 12,  5,       .NumGroup
-	cardflip_cursor 13,  5,       .SingleTile
-	cardflip_cursor 15,  5,       .SingleTile
-	cardflip_cursor 17,  5,       .SingleTile
-	cardflip_cursor 19,  5,       .SingleTile
-
-	cardflip_cursor 11,  5,       .NumGroupPair
-	cardflip_cursor 12,  6, 0, 4, .NumGroup
-	cardflip_cursor 13,  6, 0, 4, .SingleTile
-	cardflip_cursor 15,  6, 0, 4, .SingleTile
-	cardflip_cursor 17,  6, 0, 4, .SingleTile
-	cardflip_cursor 19,  6, 0, 4, .SingleTile
-
-	cardflip_cursor 11,  8,       .NumGroupPair
-	cardflip_cursor 12,  8,       .NumGroup
-	cardflip_cursor 13,  8,       .SingleTile
-	cardflip_cursor 15,  8,       .SingleTile
-	cardflip_cursor 17,  8,       .SingleTile
-	cardflip_cursor 19,  8,       .SingleTile
-
-	cardflip_cursor 11,  8,       .NumGroupPair
-	cardflip_cursor 12,  9, 0, 4, .NumGroup
-	cardflip_cursor 13,  9, 0, 4, .SingleTile
-	cardflip_cursor 15,  9, 0, 4, .SingleTile
-	cardflip_cursor 17,  9, 0, 4, .SingleTile
-	cardflip_cursor 19,  9, 0, 4, .SingleTile
-
-	cardflip_cursor 11, 11,       .NumGroupPair
-	cardflip_cursor 12, 11,       .NumGroup
-	cardflip_cursor 13, 11,       .SingleTile
-	cardflip_cursor 15, 11,       .SingleTile
-	cardflip_cursor 17, 11,       .SingleTile
-	cardflip_cursor 19, 11,       .SingleTile
-
-	cardflip_cursor 11, 11,       .NumGroupPair
-	cardflip_cursor 12, 12, 0, 4, .NumGroup
-	cardflip_cursor 13, 12, 0, 4, .SingleTile
-	cardflip_cursor 15, 12, 0, 4, .SingleTile
-	cardflip_cursor 17, 12, 0, 4, .SingleTile
-	cardflip_cursor 19, 12, 0, 4, .SingleTile
-; e0a41
-
-.SingleTile: ; e0a41
-	db 6
-	dsprite  0, 0,  -1, 7, $00, 0 | PRIORITY
-	dsprite  0, 0,   0, 0, $02, 0 | PRIORITY
-	dsprite  0, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  0, 5,  -1, 7, $00, 0 | Y_FLIP | PRIORITY
-	dsprite  0, 5,   0, 0, $02, 0 | Y_FLIP | PRIORITY
-	dsprite  0, 5,   1, 0, $03, 0 | PRIORITY
-
-.PokeGroup: ; e0a5a
-	db 26
-	dsprite  0, 0,  -1, 7, $00, 0 | PRIORITY
-	dsprite  0, 0,   0, 0, $02, 0 | PRIORITY
-	dsprite  0, 0,   1, 0, $00, 0 | X_FLIP | PRIORITY
-	dsprite  1, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  1, 0,   1, 0, $01, 0 | X_FLIP | PRIORITY
-	dsprite  2, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  2, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  3, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  3, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  4, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  4, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  5, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  5, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  6, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  6, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  7, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  7, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  8, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  8, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  9, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  9, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite 10, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite 10, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite 10, 1,  -1, 7, $00, 0 | Y_FLIP | PRIORITY
-	dsprite 10, 1,   0, 0, $02, 0 | Y_FLIP | PRIORITY
-	dsprite 10, 1,   1, 0, $03, 0 | PRIORITY
-
-.NumGroup: ; e0ac3
-	db 20
-	dsprite  0, 0,  -1, 7, $00, 0 | PRIORITY
-	dsprite  0, 0,   0, 0, $02, 0 | PRIORITY
-	dsprite  0, 0,   1, 0, $02, 0 | PRIORITY
-	dsprite  0, 0,   2, 0, $03, 0 | PRIORITY
-	dsprite  0, 0,   3, 0, $02, 0 | PRIORITY
-	dsprite  0, 0,   4, 0, $03, 0 | PRIORITY
-	dsprite  0, 0,   5, 0, $02, 0 | PRIORITY
-	dsprite  0, 0,   6, 0, $03, 0 | PRIORITY
-	dsprite  0, 0,   7, 0, $02, 0 | PRIORITY
-	dsprite  0, 0,   8, 0, $03, 0 | PRIORITY
-	dsprite  0, 5,  -1, 7, $00, 0 | Y_FLIP | PRIORITY
-	dsprite  0, 5,   0, 0, $02, 0 | Y_FLIP | PRIORITY
-	dsprite  0, 5,   1, 0, $02, 0 | Y_FLIP | PRIORITY
-	dsprite  0, 5,   2, 0, $03, 0 | PRIORITY
-	dsprite  0, 5,   3, 0, $02, 0 | Y_FLIP | PRIORITY
-	dsprite  0, 5,   4, 0, $03, 0 | PRIORITY
-	dsprite  0, 5,   5, 0, $02, 0 | Y_FLIP | PRIORITY
-	dsprite  0, 5,   6, 0, $03, 0 | PRIORITY
-	dsprite  0, 5,   7, 0, $02, 0 | Y_FLIP | PRIORITY
-	dsprite  0, 5,   8, 0, $03, 0 | PRIORITY
-
-.NumGroupPair: ; e0b14
-	db 30
-	dsprite  0, 0,   0, 0, $00, 0 | PRIORITY
-	dsprite  0, 0,   1, 0, $02, 0 | PRIORITY
-	dsprite  0, 0,   2, 0, $02, 0 | PRIORITY
-	dsprite  0, 0,   3, 0, $03, 0 | PRIORITY
-	dsprite  0, 0,   4, 0, $02, 0 | PRIORITY
-	dsprite  0, 0,   5, 0, $03, 0 | PRIORITY
-	dsprite  0, 0,   6, 0, $02, 0 | PRIORITY
-	dsprite  0, 0,   7, 0, $03, 0 | PRIORITY
-	dsprite  0, 0,   8, 0, $02, 0 | PRIORITY
-	dsprite  0, 0,   9, 0, $03, 0 | PRIORITY
-	dsprite  1, 0,   0, 0, $01, 0 | PRIORITY
-	dsprite  1, 0,   3, 0, $03, 0 | PRIORITY
-	dsprite  1, 0,   5, 0, $03, 0 | PRIORITY
-	dsprite  1, 0,   7, 0, $03, 0 | PRIORITY
-	dsprite  1, 0,   9, 0, $03, 0 | PRIORITY
-	dsprite  2, 0,   0, 0, $01, 0 | PRIORITY
-	dsprite  2, 0,   3, 0, $03, 0 | PRIORITY
-	dsprite  2, 0,   5, 0, $03, 0 | PRIORITY
-	dsprite  2, 0,   7, 0, $03, 0 | PRIORITY
-	dsprite  2, 0,   9, 0, $03, 0 | PRIORITY
-	dsprite  2, 1,   0, 0, $00, 0 | Y_FLIP | PRIORITY
-	dsprite  2, 1,   1, 0, $02, 0 | Y_FLIP | PRIORITY
-	dsprite  2, 1,   2, 0, $02, 0 | Y_FLIP | PRIORITY
-	dsprite  2, 1,   3, 0, $03, 0 | PRIORITY
-	dsprite  2, 1,   4, 0, $03, 0 | PRIORITY
-	dsprite  2, 1,   5, 0, $03, 0 | PRIORITY
-	dsprite  2, 1,   6, 0, $03, 0 | PRIORITY
-	dsprite  2, 1,   7, 0, $03, 0 | PRIORITY
-	dsprite  2, 1,   8, 0, $03, 0 | PRIORITY
-	dsprite  2, 1,   9, 0, $03, 0 | PRIORITY
-
-.PokeGroupPair: ; e0b8d
-	db 38
-	dsprite  0, 0,  -1, 7, $00, 0 | PRIORITY
-	dsprite  0, 0,   3, 0, $00, 0 | X_FLIP | PRIORITY
-	dsprite  1, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  1, 0,   3, 0, $01, 0 | X_FLIP | PRIORITY
-	dsprite  2, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  2, 0,   3, 0, $01, 0 | X_FLIP | PRIORITY
-	dsprite  3, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  3, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  3, 0,   3, 0, $03, 0 | PRIORITY
-	dsprite  4, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  4, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  4, 0,   3, 0, $03, 0 | PRIORITY
-	dsprite  5, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  5, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  5, 0,   3, 0, $03, 0 | PRIORITY
-	dsprite  6, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  6, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  6, 0,   3, 0, $03, 0 | PRIORITY
-	dsprite  7, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  7, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  7, 0,   3, 0, $03, 0 | PRIORITY
-	dsprite  8, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  8, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  8, 0,   3, 0, $03, 0 | PRIORITY
-	dsprite  9, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite  9, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite  9, 0,   3, 0, $03, 0 | PRIORITY
-	dsprite 10, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite 10, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite 10, 0,   3, 0, $03, 0 | PRIORITY
-	dsprite 11, 0,  -1, 7, $01, 0 | PRIORITY
-	dsprite 11, 0,   1, 0, $03, 0 | PRIORITY
-	dsprite 11, 0,   3, 0, $03, 0 | PRIORITY
-	dsprite 11, 1,  -1, 7, $00, 0 | Y_FLIP | PRIORITY
-	dsprite 11, 1,   0, 0, $02, 0 | Y_FLIP | PRIORITY
-	dsprite 11, 1,   1, 0, $03, 0 | Y_FLIP | PRIORITY
-	dsprite 11, 1,   2, 0, $02, 0 | Y_FLIP | PRIORITY
-	dsprite 11, 1,   3, 0, $03, 0 | X_FLIP | Y_FLIP | PRIORITY
-
-.Impossible: ; e0c26
-	db 4
-	dsprite  0, 0,   0, 0, $00, 0 | PRIORITY
-	dsprite  0, 0,   1, 0, $00, 0 | X_FLIP | PRIORITY
-	dsprite  1, 0,   0, 0, $00, 0 | Y_FLIP | PRIORITY
-	dsprite  1, 0,   1, 0, $00, 0 | X_FLIP | Y_FLIP | PRIORITY
-; e0c37
-
-CardFlip_InitAttrPals: ; e0c37 (38:4c37)
-	ld a, [hCGB]
-	and a
-	ret z
-
-	hlcoord 0, 0, wAttrMap
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	xor a
-	call ByteFill
-
-	hlcoord 12, 1, wAttrMap
-	lb bc, 2, 2
-	ld a, $1
-	call CardFlip_FillBox
-
-	hlcoord 14, 1, wAttrMap
-	lb bc, 2, 2
-	ld a, $2
-	call CardFlip_FillBox
-
-	hlcoord 16, 1, wAttrMap
-	lb bc, 2, 2
-	ld a, $3
-	call CardFlip_FillBox
-
-	hlcoord 18, 1, wAttrMap
-	lb bc, 2, 2
-	ld a, $4
-	call CardFlip_FillBox
-
-	hlcoord 9, 0, wAttrMap
-	lb bc, 12, 1
-	ld a, $1
-	call CardFlip_FillBox
-
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld hl, .palettes
-	ld de, wBGPals1
-	ld bc, 9 palettes
-	call CopyBytes
-	pop af
-	ld [rSVBK], a
-	ret
-; e0c93 (38:4c93)
-
-.palettes ; e0c93
-INCLUDE "gfx/card_flip/card_flip.pal"
-; e0cdb
-
-CardFlipLZ03: ; e0cdb
-INCBIN "gfx/card_flip/card_flip_3.2bpp.lz"
-
-CardFlipOffButtonGFX: ; e0cf6
-INCBIN "gfx/card_flip/off.2bpp"
-
-CardFlipOnButtonGFX: ; e0d06
-INCBIN "gfx/card_flip/on.2bpp"
-
-CardFlipLZ01: ; e0d16
-INCBIN "gfx/card_flip/card_flip_1.2bpp.lz"
-
-CardFlipLZ02: ; e0ea8
-INCBIN "gfx/card_flip/card_flip_2.2bpp.lz"
-
-CardFlipTilemap: ; e110c
-INCBIN "gfx/card_flip/card_flip.tilemap"
-; e1190
--- a/engine/game/dummy_game.asm
+++ /dev/null
@@ -1,612 +1,0 @@
-_DummyGame: ; e1e5b (38:5e5b)
-	call .LoadGFXAndPals
-	call DelayFrame
-.loop
-	call .JumptableLoop
-	jr nc, .loop
-	ret
-
-.LoadGFXAndPals:
-	call DisableLCD
-	ld b, SCGB_DIPLOMA
-	call GetSGBLayout
-	callfar ClearSpriteAnims
-	ld hl, LZ_e2221
-	ld de, vTiles2 tile $00
-	call Decompress
-	ld hl, Unknown_e00ed
-	ld de, vTiles0 tile $00
-	ld bc, 4 tiles
-	ld a, BANK(Unknown_e00ed)
-	call FarCopyBytes
-	ld a, $8
-	ld hl, wc300
-	ld [hli], a
-	ld [hl], $0
-	hlcoord 0, 0
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	xor a
-	call ByteFill
-	xor a
-	ld [hSCY], a
-	ld [hSCX], a
-	ld [rWY], a
-	ld [wJumptableIndex], a
-	ld a, $1
-	ld [hBGMapMode], a
-	ld a, LCDC_DEFAULT
-	ld [rLCDC], a
-	ld a, $e4
-	call DmgToCgbBGPals
-	ld a, $e0
-	call DmgToCgbObjPal0
-	ret
-
-.JumptableLoop:
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .quit
-	call .ExecuteJumptable
-	callfar PlaySpriteAnimations
-	call DelayFrame
-	and a
-	ret
-
-.quit
-	scf
-	ret
-
-.ExecuteJumptable:
-	jumptable .Jumptable, wJumptableIndex
-
-.Jumptable:
-	dw .RestartGame
-	dw .ResetBoard
-	dw .InitBoardTilemapAndCursorObject
-	dw .CheckTriesRemaining
-	dw .PickCard1
-	dw .PickCard2
-	dw .DelayPickAgain
-	dw .RevealAll
-	dw .AskPlayAgain
-
-.RestartGame:
-	call DummyGame_InitStrings
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-.ResetBoard:
-	call ret_e00ed
-	jr nc, .proceed
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-.proceed
-	call DummyGame_InitBoard
-	ld hl, wJumptableIndex
-	inc [hl]
-	xor a
-	ld [wDummyGameCounter], a
-	ld hl, wDummyGameLastMatches
-rept 4
-	ld [hli], a
-endr
-	ld [hl], a
-	ld [wDummyGameNumCardsMatched], a
-.InitBoardTilemapAndCursorObject:
-	ld hl, wDummyGameCounter
-	ld a, [hl]
-	cp 45
-	jr nc, .spawn_object
-	inc [hl]
-	call DummyGame_Card2Coord
-	xor a
-	ld [wDummyGameLastCardPicked], a
-	call DummyGame_PlaceCard
-	ret
-
-.spawn_object
-	depixel 6, 3, 4, 4
-	ld a, SPRITE_ANIM_INDEX_DUMMY_GAME
-	call _InitSpriteAnimStruct
-	ld a, 5
-	ld [wDummyGameNumberTriesRemaining], a
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-.CheckTriesRemaining:
-	ld a, [wDummyGameNumberTriesRemaining]
-	hlcoord 17, 0
-	add "0"
-	ld [hl], a
-	ld hl, wDummyGameNumberTriesRemaining
-	ld a, [hl]
-	and a
-	jr nz, .next_try
-	ld a, $7
-	ld [wJumptableIndex], a
-	ret
-
-.next_try
-	dec [hl]
-	xor a
-	ld [wcf64], a
-	ld hl, wJumptableIndex
-	inc [hl]
-.PickCard1:
-	ld a, [wcf64]
-	and a
-	ret z
-	dec a
-	ld e, a
-	ld d, 0
-	ld hl, wDummyGameCards
-	add hl, de
-	ld a, [hl]
-	cp -1
-	ret z
-	ld [wDummyGameLastCardPicked], a
-	ld [wDummyGameCard1], a
-	ld a, e
-	ld [wDummyGameCard1Location], a
-	call DummyGame_Card2Coord
-	call DummyGame_PlaceCard
-	xor a
-	ld [wcf64], a
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-.PickCard2:
-	ld a, [wcf64]
-	and a
-	ret z
-	dec a
-	ld hl, wDummyGameCard1Location
-	cp [hl]
-	ret z
-	ld e, a
-	ld d, 0
-	ld hl, wDummyGameCards
-	add hl, de
-	ld a, [hl]
-	cp -1
-	ret z
-	ld [wDummyGameLastCardPicked], a
-	ld [wDummyGameCard2], a
-	ld a, e
-	ld [wDummyGameCard2Location], a
-	call DummyGame_Card2Coord
-	call DummyGame_PlaceCard
-	ld a, 64
-	ld [wDummyGameCounter], a
-	ld hl, wJumptableIndex
-	inc [hl]
-.DelayPickAgain:
-	ld hl, wDummyGameCounter
-	ld a, [hl]
-	and a
-	jr z, .PickAgain
-	dec [hl]
-	ret
-
-.PickAgain:
-	call DummyGame_CheckMatch
-	ld a, $3
-	ld [wJumptableIndex], a
-	ret
-
-.RevealAll:
-	ld a, [hJoypadPressed]
-	and A_BUTTON
-	ret z
-	xor a
-	ld [wDummyGameCounter], a
-.RevelationLoop:
-	ld hl, wDummyGameCounter
-	ld a, [hl]
-	cp 45
-	jr nc, .finish_round
-	inc [hl]
-	push af
-	call DummyGame_Card2Coord
-	pop af
-	push hl
-	ld e, a
-	ld d, $0
-	ld hl, wDummyGameCards
-	add hl, de
-	ld a, [hl]
-	pop hl
-	cp -1
-	jr z, .RevelationLoop
-	ld [wDummyGameLastCardPicked], a
-	call DummyGame_PlaceCard
-	jr .RevelationLoop
-
-.finish_round
-	call WaitPressAorB_BlinkCursor
-	ld hl, wJumptableIndex
-	inc [hl]
-.AskPlayAgain:
-	call ret_e00ed
-	jr nc, .restart
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-.restart
-	xor a
-	ld [wJumptableIndex], a
-	ret
-
-; e2010
-
-DummyGame_CheckMatch: ; e2010
-	ld hl, wDummyGameCard1
-	ld a, [hli]
-	cp [hl]
-	jr nz, .no_match
-
-	ld a, [wDummyGameCard1Location]
-	call DummyGame_Card2Coord
-	call DummyGame_DeleteCard
-
-	ld a, [wDummyGameCard2Location]
-	call DummyGame_Card2Coord
-	call DummyGame_DeleteCard
-
-	ld a, [wDummyGameCard1Location]
-	ld e, a
-	ld d, $0
-	ld hl, wDummyGameCards
-	add hl, de
-	ld [hl], -1
-
-	ld a, [wDummyGameCard2Location]
-	ld e, a
-	ld d, 0
-	ld hl, wDummyGameCards
-	add hl, de
-	ld [hl], -1
-
-	ld hl, wDummyGameLastMatches
-.find_empty_slot
-	ld a, [hli]
-	and a
-	jr nz, .find_empty_slot
-	dec hl
-	ld a, [wDummyGameCard1]
-	ld [hl], a
-	ld [wDummyGameLastCardPicked], a
-	ld hl, wDummyGameNumCardsMatched
-	ld e, [hl]
-	inc [hl]
-	inc [hl]
-	ld d, 0
-	hlcoord 5, 0
-	add hl, de
-	call DummyGame_PlaceCard
-	ld hl, .VictoryText
-	call PrintText
-	ret
-
-.no_match
-	xor a
-	ld [wDummyGameLastCardPicked], a
-
-	ld a, [wDummyGameCard1Location]
-	call DummyGame_Card2Coord
-	call DummyGame_PlaceCard
-
-	ld a, [wDummyGameCard2Location]
-	call DummyGame_Card2Coord
-	call DummyGame_PlaceCard
-
-	ld hl, DummyGameText_Darn
-	call PrintText
-	ret
-
-.VictoryText:
-	start_asm
-	push bc
-	hlcoord 2, 13
-	call DummyGame_PlaceCard
-	ld hl, DummyGameText_Yeah
-	pop bc
-	inc bc
-	inc bc
-	inc bc
-	ret
-
-; e2093
-
-DummyGameText_Yeah: ; 0xe2093
-	; , yeah!
-	text_jump UnknownText_0x1c1a5b
-	db "@"
-; 0xe2098
-
-DummyGameText_Darn: ; 0xe2098
-	; Darn…
-	text_jump UnknownText_0x1c1a65
-	db "@"
-; 0xe209d
-
-DummyGame_InitBoard: ; e209d
-	ld hl, wDummyGameCards
-	ld bc, wDummyGameCardsEnd - wDummyGameCards
-	xor a
-	call ByteFill
-	call DummyGame_GetDistributionOfTiles
-
-	ld c, 2
-	ld b, [hl]
-	call DummyGame_SampleTilePlacement
-
-	ld c, 8
-	ld b, [hl]
-	call DummyGame_SampleTilePlacement
-
-	ld c, 4
-	ld b, [hl]
-	call DummyGame_SampleTilePlacement
-
-	ld c, 7
-	ld b, [hl]
-	call DummyGame_SampleTilePlacement
-
-	ld c, 3
-	ld b, [hl]
-	call DummyGame_SampleTilePlacement
-
-	ld c, 6
-	ld b, [hl]
-	call DummyGame_SampleTilePlacement
-
-	ld c, 1
-	ld b, [hl]
-	call DummyGame_SampleTilePlacement
-
-	ld c, 5
-	ld hl, wDummyGameCards
-	ld b, wDummyGameCardsEnd - wDummyGameCards
-.loop
-	ld a, [hl]
-	and a
-	jr nz, .no_load
-	ld [hl], c
-.no_load
-	inc hl
-	dec b
-	jr nz, .loop
-	ret
-
-; e20e5
-
-DummyGame_SampleTilePlacement: ; e20e5
-	push hl
-	ld de, wDummyGameCards
-.loop
-	call Random
-	and %00111111
-	cp 45
-	jr nc, .loop
-	ld l, a
-	ld h, 0
-	add hl, de
-	ld a, [hl]
-	and a
-	jr nz, .loop
-	ld [hl], c
-	dec b
-	jr nz, .loop
-	pop hl
-	inc hl
-	ret
-
-; e2101
-
-DummyGame_GetDistributionOfTiles: ; e2101
-	ld a, [wMenuCursorY]
-	dec a
-	ld l, a
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	add hl, hl
-	ld de, .distributions
-	add hl, de
-	ret
-
-.distributions
-	db $02, $03, $06, $06, $06, $08, $08, $06
-	db $02, $02, $04, $06, $06, $08, $08, $09
-	db $02, $02, $02, $04, $07, $08, $08, $0c
-; e2128
-
-DummyGame_PlaceCard: ; e2128
-	ld a, [wDummyGameLastCardPicked]
-	sla a
-	sla a
-	add 4
-	ld [hli], a
-	inc a
-	ld [hld], a
-	inc a
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hli], a
-	inc a
-	ld [hl], a
-	ld c, 3
-	call DelayFrames
-	ret
-
-; e2142
-
-DummyGame_DeleteCard: ; e2142
-	ld a, $1
-	ld [hli], a
-	ld [hld], a
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld [hli], a
-	ld [hl], a
-	ld c, 3
-	call DelayFrames
-	ret
-
-; e2152
-
-DummyGame_InitStrings: ; e2152
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, $1
-	call ByteFill
-	hlcoord 0, 0
-	ld de, .japstr1
-	call PlaceString
-	hlcoord 15, 0
-	ld de, .japstr2
-	call PlaceString
-	ld hl, .dummy_text
-	call PrintText
-	ret
-
-.dummy_text
-	db "@"
-.japstr1
-	db "とったもの@"
-.japstr2
-	db "あと かい@"
-; e2183
-
-DummyGame_Card2Coord: ; e2183
-	ld d, 0
-.find_row
-	sub 9
-	jr c, .found_row
-	inc d
-	jr .find_row
-
-.found_row
-	add 9
-	ld e, a
-	hlcoord 1, 2
-	ld bc, 2 * SCREEN_WIDTH
-.loop2
-	ld a, d
-	and a
-	jr z, .done
-	add hl, bc
-	dec d
-	jr .loop2
-
-.done
-	sla e
-	add hl, de
-	ret
-
-; e21a1
-
-DummyGame_InterpretJoypad_AnimateCursor: ; e21a1 (38:61a1)
-	ld a, [wJumptableIndex]
-	cp $7
-	jr nc, .quit
-	call JoyTextDelay
-	ld hl, hJoypadPressed ; $ffa3
-	ld a, [hl]
-	and A_BUTTON
-	jr nz, .pressed_a
-	ld a, [hl]
-	and D_LEFT
-	jr nz, .pressed_left
-	ld a, [hl]
-	and D_RIGHT
-	jr nz, .pressed_right
-	ld a, [hl]
-	and D_UP
-	jr nz, .pressed_up
-	ld a, [hl]
-	and D_DOWN
-	jr nz, .pressed_down
-	ret
-
-.quit
-	ld hl, SPRITEANIMSTRUCT_INDEX
-	add hl, bc
-	ld [hl], $0
-	ret
-
-.pressed_a
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	inc a
-	ld [wcf64], a
-	ret
-
-.pressed_left
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld a, [hl]
-	and a
-	ret z
-	sub 1 tiles
-	ld [hl], a
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	dec [hl]
-	ret
-
-.pressed_right
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld a, [hl]
-	cp (9 - 1) tiles
-	ret z
-	add 1 tiles
-	ld [hl], a
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	inc [hl]
-	ret
-
-.pressed_up
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld a, [hl]
-	and a
-	ret z
-	sub 1 tiles
-	ld [hl], a
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	sub 9
-	ld [hl], a
-	ret
-
-.pressed_down
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld a, [hl]
-	cp (5 - 1) tiles
-	ret z
-	add 1 tiles
-	ld [hl], a
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	add 9
-	ld [hl], a
-	ret
-
-; e2221 (38:6221)
-
-LZ_e2221: ; e2221
-INCBIN "gfx/dummy_game/dummy_game.2bpp.lz"
--- a/engine/game/slot_machine.asm
+++ /dev/null
@@ -1,2352 +1,0 @@
-SLOTS_NO_BIAS  EQU -1
-SLOTS_NO_MATCH EQU -1
-
-SLOTS_SEVEN    EQU $00
-SLOTS_POKEBALL EQU $04
-SLOTS_CHERRY   EQU $08
-SLOTS_PIKACHU  EQU $0c
-SLOTS_SQUIRTLE EQU $10
-SLOTS_STARYU   EQU $14
-
-REEL_SIZE EQU 15
-
-; Constants for slot_reel offsets (see macros/wram.asm)
-REEL_ACTION        EQUS "(wReel1ReelAction - wReel1)"
-REEL_TILEMAP_ADDR  EQUS "(wReel1TilemapAddr - wReel1)"
-REEL_POSITION      EQUS "(wReel1Position - wReel1)"
-REEL_SPIN_DISTANCE EQUS "(wReel1SpinDistance - wReel1)"
-REEL_SPIN_RATE     EQUS "(wReel1SpinRate - wReel1)"
-REEL_OAM_ADDR      EQUS "(wReel1OAMAddr - wReel1)"
-REEL_X_COORD       EQUS "(wReel1XCoord - wReel1)"
-REEL_MANIP_COUNTER EQUS "(wReel1ManipCounter - wReel1)"
-REEL_MANIP_DELAY   EQUS "(wReel1ManipDelay - wReel1)"
-REEL_FIELD_0B      EQUS "(wReel1Field0b - wReel1)"
-REEL_STOP_DELAY    EQUS "(wReel1StopDelay - wReel1)"
-
-; SlotsJumptable constants
-	const_def
-	const SLOTS_INIT
-	const SLOTS_BET_AND_START
-	const SLOTS_WAIT_START
-	const SLOTS_WAIT_REEL1
-	const SLOTS_WAIT_STOP_REEL1
-	const SLOTS_WAIT_REEL2
-	const SLOTS_WAIT_STOP_REEL2
-	const SLOTS_WAIT_REEL3
-	const SLOTS_WAIT_STOP_REEL3
-	const SLOTS_NEXT_09
-	const SLOTS_NEXT_0A
-	const SLOTS_NEXT_0B
-	const SLOTS_FLASH_IF_WIN
-	const SLOTS_FLASH_SCREEN
-	const SLOTS_GIVE_EARNED_COINS
-	const SLOTS_PAYOUT_TEXT_AND_ANIM
-	const SLOTS_PAYOUT_ANIM
-	const SLOTS_RESTART_OF_QUIT
-	const SLOTS_QUIT
-SLOTS_END_LOOP_F EQU 7
-
-; ReelActionJumptable constants
-	const_def
-	const REEL_ACTION_DO_NOTHING
-	const REEL_ACTION_STOP_REEL_IGNORE_JOYPAD
-	const REEL_ACTION_QUADRUPLE_RATE
-	const REEL_ACTION_DOUBLE_RATE
-	const REEL_ACTION_NORMAL_RATE
-	const REEL_ACTION_HALF_RATE
-	const REEL_ACTION_QUARTER_RATE
-	const REEL_ACTION_STOP_REEL1
-	const REEL_ACTION_STOP_REEL2
-	const REEL_ACTION_STOP_REEL3
-	const REEL_ACTION_SET_UP_REEL2_SKIP_TO_7
-	const REEL_ACTION_WAIT_REEL2_SKIP_TO_7
-	const REEL_ACTION_FAST_SPIN_REEL2_UNTIL_LINED_UP_7S
-	const REEL_ACTION_UNUSED
-	const REEL_ACTION_CHECK_DROP_REEL
-	const REEL_ACTION_WAIT_DROP_REEL
-	const REEL_ACTION_START_SLOW_ADVANCE_REEL3
-	const REEL_ACTION_WAIT_SLOW_ADVANCE_REEL3
-	const REEL_ACTION_INIT_GOLEM
-	const REEL_ACTION_WAIT_GOLEM
-	const REEL_ACTION_END_GOLEM
-	const REEL_ACTION_INIT_CHANSEY
-	const REEL_ACTION_WAIT_CHANSEY
-	const REEL_ACTION_WAIT_EGG
-	const REEL_ACTION_DROP_REEL
-
-_SlotMachine:
-	ld hl, wOptions
-	set NO_TEXT_SCROLL, [hl]
-	call .InitGFX
-	call DelayFrame
-.loop
-	call SlotsLoop
-	jr nc, .loop
-	call WaitSFX
-	ld de, SFX_QUIT_SLOTS
-	call PlaySFX
-	call WaitSFX
-	call ClearBGPalettes
-	farcall StubbedTrainerRankings_EndSlotsWinStreak
-	ld hl, wOptions
-	res NO_TEXT_SCROLL, [hl]
-	ld hl, rLCDC
-	res rLCDC_SPRITE_SIZE, [hl] ; 8x8
-	ret
-
-.InitGFX: ; 926f7 (24:66f7)
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	ld de, MUSIC_NONE
-	call PlayMusic
-	call DelayFrame
-	call DisableLCD
-	hlbgcoord 0, 0
-	ld bc, vBGMap1 - vBGMap0
-	ld a, " "
-	call ByteFill
-	ld b, SCGB_SLOT_MACHINE
-	call GetSGBLayout
-	callfar ClearSpriteAnims
-	ld hl, wSlots
-	ld bc, wSlotsDataEnd - wSlots
-	xor a
-	call ByteFill
-
-	ld hl, Slots2LZ
-	ld de, vTiles0 tile $00
-	call Decompress
-
-	ld hl, Slots3LZ
-	ld de, vTiles0 tile $40
-	call Decompress
-
-	ld hl, Slots1LZ
-	ld de, vTiles2 tile $00
-	call Decompress
-
-	ld hl, Slots2LZ
-	ld de, vTiles2 tile $25
-	call Decompress
-
-	ld hl, SlotsTilemap
-	decoord 0, 0
-	ld bc, SCREEN_WIDTH * 12
-	call CopyBytes
-
-	ld hl, rLCDC
-	set rLCDC_SPRITE_SIZE, [hl] ; 8x16
-	call EnableLCD
-	ld hl, wSlots
-	ld bc, wSlotsEnd - wSlots
-	xor a
-	call ByteFill
-	call Slots_InitReelTiles
-	call Slots_GetPals
-	ld a, $7
-	ld hl, wSpriteAnimDict
-	ld [hli], a
-	ld [hl], $40
-	xor a ; SLOTS_INIT
-	ld [wJumptableIndex], a
-	ld a, SLOTS_NO_BIAS
-	ld [wSlotBias], a
-	ld de, MUSIC_GAME_CORNER
-	call PlayMusic
-	xor a
-	ld [wKeepSevenBiasChance], a ; 87.5% chance
-	call Random
-	and %00101010
-	ret nz
-	ld a, 1
-	ld [wKeepSevenBiasChance], a ; 12.5% chance
-	ret
-
-Slots_GetPals: ; 9279b (24:679b)
-	ld a, %11100100
-	call DmgToCgbBGPals
-	lb de, %11100100, %11100100
-	ld a, [hCGB]
-	and a
-	jr nz, .cgb
-	lb de, %11000000, %11100100
-.cgb
-	call DmgToCgbObjPals
-	ret
-
-SlotsLoop: ; 927af (24:67af)
-	ld a, [wJumptableIndex]
-	bit SLOTS_END_LOOP_F, a
-	jr nz, .stop
-	call SlotsJumptable
-	call Slots_SpinReels
-	xor a
-	ld [wCurrSpriteOAMAddr], a
-	callfar DoNextFrameForFirst16Sprites
-	call .PrintCoinsAndPayout
-	call .Stubbed_Function927d3
-	call DelayFrame
-	and a
-	ret
-
-.stop
-	scf
-	ret
-
-.Stubbed_Function927d3: ; 927d3 (24:67d3)
-; dummied out
-	ret
-	ld a, [wReel1ReelAction]
-	and a
-	ret nz
-	ld a, [wReel2ReelAction]
-	and a
-	ret nz
-	ld a, [wFirstTwoReelsMatchingSevens]
-	and a
-	jr nz, .matching_sevens
-	ld a, %11100100
-	call DmgToCgbBGPals
-	ret
-
-.matching_sevens
-	ld a, [wTextDelayFrames]
-	and $7
-	ret nz
-	ld a, [rBGP]
-	xor %00001100
-	call DmgToCgbBGPals
-	ret
-
-; 927f8
-
-.PrintCoinsAndPayout: ; 927f8 (24:67f8)
-	hlcoord 5, 1
-	ld de, wCoins
-	lb bc, PRINTNUM_LEADINGZEROS | 2, 4
-	call PrintNum
-	hlcoord 11, 1
-	ld de, wPayout
-	lb bc, PRINTNUM_LEADINGZEROS | 2, 4
-	call PrintNum
-	ret
-
-; 92811 (24:6811)
-
-Unreferenced_Function92811: ; 92811
-; debug function?
-	ld a, [wSlotBias]
-	add 0
-	daa
-	ld e, a
-	and $f
-	add "0"
-	hlcoord 1, 0
-	ld [hl], a
-	ld a, e
-	swap a
-	and $f
-	add "0"
-	hlcoord 0, 0
-	ld [hl], a
-	ret
-
-; 9282c
-
-Unreferenced_Function9282c: ; 9282c
-; animate OAM tiles?
-	ld hl, wcf66
-	ld a, [hl]
-	inc [hl]
-	and $7
-	ret nz
-	ld hl, wVirtualOAMSprite16TileID
-	ld c, NUM_SPRITE_OAM_STRUCTS - 16
-.loop
-	ld a, [hl]
-	xor %00100000
-	ld [hli], a ; tile id
-rept SPRITEOAMSTRUCT_LENGTH + -1
-	inc hl
-endr
-	dec c
-	jr nz, .loop
-	ret
-
-; 92844
-
-SlotsJumptable: ; 92844 (24:6844)
-	jumptable .Jumptable, wJumptableIndex
-
-.Jumptable:
-	dw SlotsAction_Init              ; 00
-	dw SlotsAction_BetAndStart       ; 01
-	dw SlotsAction_WaitStart         ; 02
-	dw SlotsAction_WaitReel1         ; 03
-	dw SlotsAction_WaitStopReel1     ; 04
-	dw SlotsAction_WaitReel2         ; 05
-	dw SlotsAction_WaitStopReel2     ; 06
-	dw SlotsAction_WaitReel3         ; 07
-	dw SlotsAction_WaitStopReel3     ; 08
-	dw SlotsAction_Next              ; 09
-	dw SlotsAction_Next              ; 0a
-	dw SlotsAction_Next              ; 0b
-	dw SlotsAction_FlashIfWin        ; 0c
-	dw SlotsAction_FlashScreen       ; 0d
-	dw SlotsAction_GiveEarnedCoins   ; 0e
-	dw SlotsAction_PayoutTextAndAnim ; 0f
-	dw SlotsAction_PayoutAnim        ; 10
-	dw SlotsAction_RestartOrQuit     ; 11
-	dw SlotsAction_Quit              ; 12
-
-SlotsAction_Next: ; 92879 (24:6879)
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-SlotsAction_Init: ; 9287e (24:687e)
-	call SlotsAction_Next
-	xor a
-	ld [wFirstTwoReelsMatching], a
-	ld [wFirstTwoReelsMatchingSevens], a
-	ld a, SLOTS_NO_MATCH
-	ld [wSlotMatched], a
-	ret
-
-SlotsAction_BetAndStart: ; 9288e (24:688e)
-	call Slots_AskBet
-	jr nc, .proceed
-	ld a, SLOTS_QUIT
-	ld [wJumptableIndex], a
-	ret
-
-.proceed
-	call SlotsAction_Next
-	call Slots_IlluminateBetLights
-	call Slots_InitBias
-	ld a, 32
-	ld [wSlotsDelay], a
-	ld a, REEL_ACTION_NORMAL_RATE
-	ld [wReel1ReelAction], a
-	ld [wReel2ReelAction], a
-	ld [wReel3ReelAction], a
-	ld a, 4
-	ld [wReel1ManipCounter], a
-	ld [wReel2ManipCounter], a
-	ld [wReel3ManipCounter], a
-	call WaitSFX
-	ld a, SFX_SLOT_MACHINE_START
-	call Slots_PlaySFX
-	ret
-
-SlotsAction_WaitStart: ; 928c6 (24:68c6)
-	ld hl, wSlotsDelay
-	ld a, [hl]
-	and a
-	jr z, .proceed
-	dec [hl]
-	ret
-
-.proceed
-	call SlotsAction_Next
-	xor a
-	ld [hJoypadSum], a
-	ret
-
-SlotsAction_WaitReel1: ; 928d6 (24:68d6)
-	ld hl, hJoypadSum
-	ld a, [hl]
-	and A_BUTTON
-	ret z
-	call SlotsAction_Next
-	call Slots_StopReel1
-	ld [wReel1ReelAction], a
-SlotsAction_WaitStopReel1: ; 928e6 (24:68e6)
-	ld a, [wReel1ReelAction]
-	cp REEL_ACTION_DO_NOTHING
-	ret nz
-	ld a, SFX_STOP_SLOT
-	call Slots_PlaySFX
-	ld bc, wReel1
-	ld de, wReel1Stopped
-	call Slots_LoadReelState
-	call SlotsAction_Next
-	xor a
-	ld [hJoypadSum], a
-SlotsAction_WaitReel2: ; 92900 (24:6900)
-	ld hl, hJoypadSum
-	ld a, [hl]
-	and A_BUTTON
-	ret z
-	call SlotsAction_Next
-	call Slots_StopReel2
-	ld [wReel2ReelAction], a
-SlotsAction_WaitStopReel2: ; 92910 (24:6910)
-	ld a, [wReel2ReelAction]
-	cp REEL_ACTION_DO_NOTHING
-	ret nz
-	ld a, SFX_STOP_SLOT
-	call Slots_PlaySFX
-	ld bc, wReel2
-	ld de, wReel2Stopped
-	call Slots_LoadReelState
-	call SlotsAction_Next
-	xor a
-	ld [hJoypadSum], a
-SlotsAction_WaitReel3: ; 9292a (24:692a)
-	ld hl, hJoypadSum
-	ld a, [hl]
-	and A_BUTTON
-	ret z
-	call SlotsAction_Next
-	call Slots_StopReel3
-	ld [wReel3ReelAction], a
-SlotsAction_WaitStopReel3: ; 9293a (24:693a)
-	ld a, [wReel3ReelAction]
-	cp REEL_ACTION_DO_NOTHING
-	ret nz
-	ld a, SFX_STOP_SLOT
-	call Slots_PlaySFX
-	ld bc, wReel3
-	ld de, wReel3Stopped
-	call Slots_LoadReelState
-	call SlotsAction_Next
-	xor a
-	ld [hJoypadSum], a
-	ret
-
-SlotsAction_FlashIfWin: ; 92955 (24:6955)
-	ld a, [wSlotMatched]
-	cp SLOTS_NO_MATCH
-	jr nz, .GotIt
-	call SlotsAction_Next
-	call SlotsAction_Next
-	ret
-
-.GotIt:
-	call SlotsAction_Next
-	ld a, 16
-	ld [wSlotsDelay], a
-SlotsAction_FlashScreen: ; 9296b (24:696b)
-	ld hl, wSlotsDelay
-	ld a, [hl]
-	and a
-	jr z, .done
-	dec [hl]
-	srl a
-	ret z
-
-	ld a, [rOBP0]
-	xor $ff
-	ld e, a
-	ld d, a
-	call DmgToCgbObjPals
-	ret
-
-.done
-	call Slots_GetPals
-	call SlotsAction_Next
-	ret
-
-SlotsAction_GiveEarnedCoins: ; 92987 (24:6987)
-	xor a
-	ld [wFirstTwoReelsMatching], a
-	ld [wFirstTwoReelsMatchingSevens], a
-	ld a, %11100100
-	call DmgToCgbBGPals
-	call Slots_GetPayout
-	xor a
-	ld [wSlotsDelay], a
-	call SlotsAction_Next
-	ret
-
-SlotsAction_PayoutTextAndAnim: ; 9299e (24:699e)
-	call Slots_PayoutText
-	call SlotsAction_Next
-SlotsAction_PayoutAnim: ; 929a4 (24:69a4)
-	ld hl, wSlotsDelay
-	ld a, [hl]
-	inc [hl]
-	and $1
-	ret z
-	ld hl, wPayout
-	ld a, [hli]
-	ld d, a
-	or [hl]
-	jr z, .done
-	ld e, [hl]
-	dec de
-	ld [hl], e
-	dec hl
-	ld [hl], d
-	ld hl, wCoins
-	ld d, [hl]
-	inc hl
-	ld e, [hl]
-	call Slots_CheckCoinCaseFull
-	jr c, .okay
-	inc de
-.okay
-	ld [hl], e
-	dec hl
-	ld [hl], d
-	ld a, [wSlotsDelay]
-	and $7
-	ret z ; ret nz would be more appropriate
-	ld de, SFX_GET_COIN_FROM_SLOTS
-	call PlaySFX
-	ret
-
-.done
-	call SlotsAction_Next
-	ret
-
-SlotsAction_RestartOrQuit: ; 929d9 (24:69d9)
-	call Slots_DeilluminateBetLights
-	call WaitPressAorB_BlinkCursor
-	call Slots_AskPlayAgain
-	jr c, .exit_slots
-	ld a, SLOTS_INIT
-	ld [wJumptableIndex], a
-	ret
-
-.exit_slots
-	ld a, SLOTS_QUIT
-	ld [wJumptableIndex], a
-	ret
-
-SlotsAction_Quit: ; 929f0 (24:69f0)
-	ld hl, wJumptableIndex
-	set SLOTS_END_LOOP_F, [hl]
-	ret
-
-Slots_LoadReelState: ; 929f6 (24:69f6)
-	push de
-	call Slots_GetCurrentReelState
-	pop de
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hli]
-	ld [de], a
-	ret
-
-Slots_CheckCoinCaseFull: ; 92a04 (24:6a04)
-	ld a, d
-	cp HIGH(MAX_COINS)
-	jr c, .not_full
-	ld a, e
-	cp LOW(MAX_COINS)
-	jr c, .not_full
-	scf
-	ret
-
-.not_full
-	and a
-	ret
-
-Slots_GetCurrentReelState: ; 92a12 (24:6a12)
-	ld hl, REEL_POSITION
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr nz, .okay
-	ld a, $f
-.okay
-	dec a
-	and $f
-	ld e, a
-	ld d, $0
-	ld hl, REEL_TILEMAP_ADDR
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	add hl, de
-	ret
-
-Slots_StopReel1: ; 92a2b (24:6a2b)
-; Always set the REEL_ACTION_STOP_REEL1 action.
-	ld a, REEL_ACTION_STOP_REEL1
-	ret
-
-Slots_StopReel2: ; 92a2e (24:6a2e)
-; As long as, the following three meet, there's a 31.25% chance
-; to set action REEL_ACTION_SET_UP_REEL2_SKIP_TO_7:
-; - Bet is >= 2 coins
-; - There's a 7 symbol visible in reel #1
-; - Current spin isn't biased or is biased towards SEVEN
-; In any other case, REEL_ACTION_STOP_REEL2 is set.
-
-	ld a, [wSlotBet]
-	cp $2
-	jr c, .dont_jump
-	ld a, [wSlotBias]
-	and a
-	jr z, .skip
-	cp SLOTS_NO_BIAS
-	jr nz, .dont_jump
-.skip
-	call .CheckReel1ForASeven
-	jr nz, .dont_jump
-	call Random
-	cp $50 ; 32%
-	jr nc, .dont_jump
-	ld a, REEL_ACTION_SET_UP_REEL2_SKIP_TO_7
-	ret
-
-.dont_jump
-	ld a, REEL_ACTION_STOP_REEL2
-	ret
-
-.CheckReel1ForASeven: ; 92a51 (24:6a51)
-	ld a, [wReel1Stopped]
-	and a
-	ret z
-	ld a, [wReel1Stopped + 1]
-	and a
-	ret z
-	ld a, [wReel1Stopped + 2]
-	and a
-	ret
-
-Slots_StopReel3: ; 92a60 (24:6a60)
-; If no matching SEVEN symbols in reels #1 and #2:
-; - REEL_ACTION_STOP_REEL3, 100%
-
-; If matching SEVEN symbols and NO bias to SEVEN:
-; - REEL_ACTION_STOP_REEL3, 37.5%
-; - REEL_ACTION_START_SLOW_ADVANCE_REEL3, 31.3%
-; - REEL_ACTION_INIT_GOLEM, 31.3%
-; - REEL_ACTION_INIT_CHANSEY, 0%
-
-; If matching SEVEN symbols and bias to SEVEN:
-; - REEL_ACTION_STOP_REEL3, 29.7%
-; - REEL_ACTION_START_SLOW_ADVANCE_REEL3, 23.4%
-; - REEL_ACTION_INIT_GOLEM, 23.4%
-; - REEL_ACTION_INIT_CHANSEY, 23.4%
-
-	ld a, [wFirstTwoReelsMatching]
-	and a
-	jr z, .stop
-	ld a, [wFirstTwoReelsMatchingSevens]
-	and a
-	jr z, .stop
-	ld a, [wSlotBias]
-	and a
-	jr nz, .biased
-	call Random
-	cp 180
-	jr nc, .stop
-	cp 120
-	jr nc, .slow_advance
-	cp 60
-	jr nc, .golem
-	ld a, REEL_ACTION_INIT_CHANSEY
-	ret
-
-.biased
-	call Random
-	cp 160
-	jr nc, .stop
-	cp 80
-	jr nc, .slow_advance
-.golem
-	ld a, REEL_ACTION_INIT_GOLEM
-	ret
-
-.slow_advance
-	ld a, REEL_ACTION_START_SLOW_ADVANCE_REEL3
-	ret
-
-.stop
-	ld a, REEL_ACTION_STOP_REEL3
-	ret
-
-Slots_InitReelTiles: ; 92a98 (24:6a98)
-	ld bc, wReel1
-	ld hl, REEL_OAM_ADDR
-	add hl, bc
-	ld de, wVirtualOAMSprite16
-	ld [hl], e
-	inc hl
-	ld [hl], d
-	ld hl, REEL_TILEMAP_ADDR
-	add hl, bc
-	ld de, Reel1Tilemap
-	ld [hl], e
-	inc hl
-	ld [hl], d
-	ld hl, REEL_X_COORD
-	add hl, bc
-	ld [hl], 6 * 8
-	call .OAM
-
-	ld bc, wReel2
-	ld hl, REEL_OAM_ADDR
-	add hl, bc
-	ld de, wVirtualOAMSprite24
-	ld [hl], e
-	inc hl
-	ld [hl], d
-	ld hl, REEL_TILEMAP_ADDR
-	add hl, bc
-	ld de, Reel2Tilemap
-	ld [hl], e
-	inc hl
-	ld [hl], d
-	ld hl, REEL_X_COORD
-	add hl, bc
-	ld [hl], 10 * 8
-	call .OAM
-
-	ld bc, wReel3
-	ld hl, REEL_OAM_ADDR
-	add hl, bc
-	ld de, wVirtualOAMSprite32
-	ld [hl], e
-	inc hl
-	ld [hl], d
-	ld hl, REEL_TILEMAP_ADDR
-	add hl, bc
-	ld de, Reel3Tilemap
-	ld [hl], e
-	inc hl
-	ld [hl], d
-	ld hl, REEL_X_COORD
-	add hl, bc
-	ld [hl], 14 * 8
-	call .OAM
-	ret
-
-.OAM: ; 92af9 (24:6af9)
-	ld hl, REEL_ACTION
-	add hl, bc
-	ld [hl], REEL_ACTION_DO_NOTHING
-	ld hl, REEL_POSITION
-	add hl, bc
-	ld [hl], REEL_SIZE - 1
-	ld hl, REEL_SPIN_DISTANCE
-	add hl, bc
-	ld [hl], REEL_ACTION_DO_NOTHING
-	call Slots_UpdateReelPositionAndOAM
-	ret
-
-Slots_SpinReels: ; 92b0f (24:6b0f)
-	ld bc, wReel1
-	call .SpinReel
-	ld bc, wReel2
-	call .SpinReel
-	ld bc, wReel3
-	call .SpinReel
-	ret
-
-.SpinReel: ; 92b22 (24:6b22)
-	ld hl, REEL_SPIN_DISTANCE
-	add hl, bc
-	ld a, [hl]
-	and $f
-	jr nz, .skip
-	call ReelActionJumptable
-.skip
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld a, [hl]
-	and a
-	ret z
-	ld d, a
-	ld hl, REEL_SPIN_DISTANCE
-	add hl, bc
-	add [hl]
-	ld [hl], a
-	and $f
-	jr z, Slots_UpdateReelPositionAndOAM
-	ld hl, REEL_OAM_ADDR
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld e, $8
-.loop
-	ld a, [hl]
-	add d
-	ld [hli], a
-	inc hl
-	inc hl
-	inc hl
-	dec e
-	jr nz, .loop
-	ret
-
-Slots_UpdateReelPositionAndOAM: ; 92b53 (24:6b53)
-	ld hl, REEL_X_COORD
-	add hl, bc
-	ld a, [hl]
-	ld [wCurrReelXCoord], a
-	ld a, 10 * 8
-	ld [wCurrReelYCoord], a
-	ld hl, REEL_POSITION
-	add hl, bc
-	ld e, [hl]
-	ld d, 0
-	ld hl, REEL_TILEMAP_ADDR
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	add hl, de
-	ld e, l
-	ld d, h
-	call .LoadOAM
-	ld hl, REEL_POSITION
-	add hl, bc
-	ld a, [hl]
-	inc a
-	and $f
-	cp REEL_SIZE
-	jr nz, .load
-	xor a
-.load
-	ld [hl], a
-	ret
-
-.LoadOAM: ; 92b83 (24:6b83)
-	ld hl, REEL_OAM_ADDR
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-.loop
-	ld a, [wCurrReelYCoord]
-	ld [hli], a ; y
-	ld a, [wCurrReelXCoord]
-	ld [hli], a ; x
-	ld a, [de]
-	ld [hli], a ; tile id
-	srl a
-	srl a
-	set OAM_PRIORITY, a
-	ld [hli], a ; attributes
-
-	ld a, [wCurrReelYCoord]
-	ld [hli], a ; y
-	ld a, [wCurrReelXCoord]
-	add 1 * TILE_WIDTH
-	ld [hli], a ; x
-	ld a, [de]
-	inc a
-	inc a
-	ld [hli], a ; tile id
-	srl a
-	srl a
-	set OAM_PRIORITY, a
-	ld [hli], a ; attributes
-	inc de
-	ld a, [wCurrReelYCoord]
-	sub 2 * TILE_WIDTH
-	ld [wCurrReelYCoord], a
-	cp 2 * TILE_WIDTH
-	jr nz, .loop
-	ret
-
-; 92bbe (24:6bbe)
-
-Unreferenced_Function92bbe: ; 92bbe
-	push hl
-	srl a
-	srl a
-	add LOW(.Unknown_92bce)
-	ld l, a
-	ld a, 0
-	adc HIGH(.Unknown_92bce)
-	ld h, a
-	ld a, [hl]
-	pop hl
-	ret
-
-; 92bce
-
-.Unknown_92bce: ; 92bce
-	db 0, 1, 2, 3, 4, 5
-; 92bd4
-
-ReelActionJumptable: ; 92bd4 (24:6bd4)
-	ld hl, REEL_ACTION
-	add hl, bc
-	ld e, [hl]
-	ld d, 0
-	ld hl, .Jumptable
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-; 92be4 (24:6be4)
-
-.Jumptable: ; 92be4
-	dw ReelAction_DoNothing                   ; 00
-	dw ReelAction_StopReelIgnoreJoypad        ; 01
-	dw ReelAction_QuadrupleRate               ; 02
-	dw ReelAction_DoubleRate                  ; 03
-	dw ReelAction_NormalRate                  ; 04
-	dw ReelAction_HalfRate                    ; 05
-	dw ReelAction_QuarterRate                 ; 06
-	dw ReelAction_StopReel1                   ; 07
-	dw ReelAction_StopReel2                   ; 08
-	dw ReelAction_StopReel3                   ; 09
-	dw ReelAction_SetUpReel2SkipTo7           ; 0a
-	dw ReelAction_WaitReel2SkipTo7            ; 0b
-	dw ReelAction_FastSpinReel2UntilLinedUp7s ; 0c
-	dw ReelAction_Unused                      ; 0d
-	dw ReelAction_CheckDropReel               ; 0e
-	dw ReelAction_WaitDropReel                ; 0f
-	dw ReelAction_StartSlowAdvanceReel3       ; 10
-	dw ReelAction_WaitSlowAdvanceReel3        ; 11
-	dw ReelAction_InitGolem                   ; 12
-	dw ReelAction_WaitGolem                   ; 13
-	dw ReelAction_EndGolem                    ; 14
-	dw ReelAction_InitChansey                 ; 15
-	dw ReelAction_WaitChansey                 ; 16
-	dw ReelAction_WaitEgg                     ; 17
-	dw ReelAction_DropReel                    ; 18
-; 92c16
-
-ReelAction_DoNothing: ; 92c16
-	ret
-
-; 92c17
-
-ReelAction_QuadrupleRate: ; 92c17
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 16
-	ret
-
-; 92c1e
-
-ReelAction_DoubleRate: ; 92c1e
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 8
-	ret
-
-; 92c25
-
-ReelAction_NormalRate: ; 92c25
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 4
-	ret
-
-; 92c2c
-
-ReelAction_HalfRate: ; 92c2c
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 2
-	ret
-
-; 92c33
-
-ReelAction_QuarterRate: ; 92c33
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 1
-	ret
-
-; 92c3a
-
-Slots_StopReel: ; 92c3a
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 0
-	ld hl, REEL_ACTION
-	add hl, bc
-	ld [hl], REEL_ACTION_STOP_REEL_IGNORE_JOYPAD
-	ld hl, REEL_STOP_DELAY
-	add hl, bc
-	ld [hl], 3
-ReelAction_StopReelIgnoreJoypad: ; 92c4c
-	ld hl, REEL_STOP_DELAY
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .EndReel
-	dec [hl]
-	ret
-
-.EndReel:
-	ld hl, REEL_ACTION
-	add hl, bc
-	ld a, REEL_ACTION_DO_NOTHING
-	ld [hl], a
-	ret
-
-; 92c5e
-
-ReelAction_StopReel1: ; 92c5e
-; If no bias: don't manipulate reel.
-; If bias: manipulate reel up to wReel1ManipCounter (i.e. 4) slots,
-; stoping early if the biased symbol shows up anywhere in reel #1,
-; even if the current bet won't allow lining it up.
-
-	ld a, [wSlotBias]
-	cp SLOTS_NO_BIAS
-	jr z, .NoBias
-	ld hl, REEL_MANIP_COUNTER
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .NoBias
-	dec [hl]
-	call .CheckForBias
-	ret nz
-.NoBias:
-	call Slots_StopReel
-	ret
-
-; 92c76
-
-.CheckForBias: ; 92c76
-	call Slots_GetCurrentReelState
-	ld a, [wSlotBias]
-	ld e, a
-	ld a, [hli]
-	cp e
-	ret z
-	ld a, [hli]
-	cp e
-	ret z
-	ld a, [hl]
-	cp e
-	ret
-
-; 92c86
-
-ReelAction_StopReel2: ; 92c86
-; If no bias: don't manipulate reel.
-; If bias: manipulate reel up to wReel2ManipCounter (i.e. 4) slots,
-; stoping early if the biased symbol is lined up in the first two
-; reels, according to the lines that the current bet allows.
-
-	call Slots_CheckMatchedFirstTwoReels
-	jr nc, .nope
-	ld a, [wSlotBuildingMatch]
-	ld hl, wSlotBias
-	cp [hl]
-	jr z, .NoBias
-.nope
-	ld a, [wSlotBias]
-	cp SLOTS_NO_BIAS
-	jr z, .NoBias
-	ld hl, REEL_MANIP_COUNTER
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .NoBias
-	dec [hl]
-	ret
-
-.NoBias:
-	call Slots_StopReel
-	ret
-
-; 92ca9
-
-ReelAction_StopReel3: ; 92ca9
-; Manipulate the reel up to wReel3ManipCounter (i.e. 4) slots,
-; stopping early if the bias symbol is lined up for a win.
-; If not biased to any symbols, stop as soon as nothing is lined up.
-
-	call Slots_CheckMatchedAllThreeReels
-	jr nc, .NoMatch
-	ld hl, wSlotBias
-	cp [hl]
-	jr z, .NoBias
-	ld hl, REEL_MANIP_COUNTER
-	add hl, bc
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-	ret
-
-.NoMatch:
-	ld a, [wSlotBias]
-	cp SLOTS_NO_BIAS
-	jr z, .NoBias
-	ld hl, REEL_MANIP_COUNTER
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .NoBias
-	dec [hl]
-	ret
-
-.NoBias:
-	call Slots_StopReel
-	ret
-
-; 92cd2
-
-ReelAction_SetUpReel2SkipTo7: ; 92cd2
-; Unique reel 2 action (see Slots_StopReel2)
-; Ensures that 7 symbols become lined up in the first two reels,
-; but more often than not, this is only a way to get our hopes up, as
-; it makes exciting reel #3 modes with no success hope more common.
-
-	call Slots_CheckMatchedFirstTwoReels
-	jr nc, .no_match
-	ld a, [wFirstTwoReelsMatchingSevens]
-	and a
-	jr z, .no_match
-	call Slots_StopReel
-	ret
-
-.no_match
-	ld a, SFX_STOP_SLOT
-	call Slots_PlaySFX
-	ld hl, REEL_ACTION
-	add hl, bc
-	inc [hl] ; REEL_ACTION_WAIT_REEL2_SKIP_TO_7
-	ld hl, REEL_MANIP_DELAY
-	add hl, bc
-	ld [hl], 32
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 0
-	ret
-
-; 92cf8
-
-ReelAction_WaitReel2SkipTo7: ; 92cf8
-	ld hl, REEL_MANIP_DELAY
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .asm_92d02
-	dec [hl]
-	ret
-
-.asm_92d02
-	ld a, SFX_THROW_BALL
-	call Slots_PlaySFX
-	ld hl, REEL_ACTION
-	add hl, bc
-	inc [hl] ; REEL_ACTION_FAST_SPIN_REEL2_UNTIL_LINED_UP_7S
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 8
-	ret
-
-; 92d13
-
-ReelAction_FastSpinReel2UntilLinedUp7s: ; 92d13
-	call Slots_CheckMatchedFirstTwoReels
-	ret nc
-	ld a, [wFirstTwoReelsMatchingSevens]
-	and a
-	ret z
-	call Slots_StopReel
-	ret
-
-; 92d20
-
-ReelAction_InitGolem: ; 92d20
-; Ensures SEVENs are lined up if there's bias to SEVEN.
-; Ensures nothing is lined up if there's no bias symbols.
-; No other bias symbols are compatible with this mode.
-
-; This is achieved by throwing Golem until the desired result
-; is produced. The amount of Golem thrown can be anywhere from
-;  1 to 14 for SEVEN bias, and 4-8 for no bias.
-
-	call Slots_CheckMatchedAllThreeReels
-	ret c
-	ld a, SFX_STOP_SLOT
-	call Slots_PlaySFX
-	call Slots_WaitSFX
-	ld hl, REEL_ACTION
-	add hl, bc
-	inc [hl] ; REEL_ACTION_WAIT_GOLEM
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 0
-	call Slots_GetNumberOfGolems
-	push bc
-	push af
-	depixel 12, 13
-	ld a, SPRITE_ANIM_INDEX_SLOTS_GOLEM
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_0E
-	add hl, bc
-	pop af
-	ld [hl], a
-	pop bc
-	xor a
-	ld [wSlotsDelay], a
-ReelAction_WaitGolem: ; 92d4f
-	ld a, [wSlotsDelay]
-	cp 2
-	jr z, .two
-	cp 1
-	jr z, .one
-	ret
-
-.two
-	call Slots_CheckMatchedAllThreeReels
-	call Slots_StopReel
-	ret
-
-.one
-	ld hl, REEL_ACTION
-	add hl, bc
-	inc [hl] ; REEL_ACTION_END_GOLEM
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 8
-	ret
-
-; 92d6e
-
-ReelAction_EndGolem: ; 92d6e
-	xor a
-	ld [wSlotsDelay], a
-	ld hl, REEL_ACTION
-	add hl, bc
-	dec [hl] ; REEL_ACTION_WAIT_GOLEM
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 0
-	ret
-
-; 92d7e
-
-ReelAction_InitChansey: ; 92d7e
-; Ensures the lining up of SEVEN symbols, but this mode is only possible
-; when there is bias to SEVEN symbols (and even then, it's still rare).
-; Chansey releases and egg and reel #3 is made to advance 17 slots very
-; quickly as many times as necessary for the match to SEVENs to show up.
-
-	call Slots_CheckMatchedAllThreeReels
-	ret c
-	ld a, SFX_STOP_SLOT
-	call Slots_PlaySFX
-	call Slots_WaitSFX
-	ld hl, REEL_ACTION
-	add hl, bc
-	inc [hl] ; REEL_ACTION_WAIT_CHANSEY
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 0
-	push bc
-	depixel 12, 0
-	ld a, SPRITE_ANIM_INDEX_SLOTS_CHANSEY
-	call _InitSpriteAnimStruct
-	pop bc
-	xor a
-	ld [wSlotsDelay], a
-	ret
-
-; 92da4
-
-ReelAction_WaitChansey: ; 92da4
-	ld a, [wSlotsDelay]
-	and a
-	ret z
-	ld hl, REEL_ACTION
-	add hl, bc
-	inc [hl] ; REEL_ACTION_WAIT_EGG
-	ld a, 2
-	ld [wSlotsDelay], a
-ReelAction_WaitEgg: ; 92db3
-	ld a, [wSlotsDelay]
-	cp $4
-	ret c
-	ld hl, REEL_ACTION
-	add hl, bc
-	inc [hl] ; REEL_ACTION_DROP_REEL
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 16
-	ld hl, REEL_MANIP_DELAY
-	add hl, bc
-	ld [hl], 17
-ReelAction_DropReel: ; 92dca
-	ld hl, REEL_MANIP_DELAY
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .check_match
-	dec [hl]
-	ret
-
-.check_match
-	call Slots_CheckMatchedAllThreeReels
-	jr nc, .EggAgain
-	and a
-	jr nz, .EggAgain
-	ld a, 5
-	ld [wSlotsDelay], a
-	call Slots_StopReel
-	ret
-
-.EggAgain:
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 0
-	ld hl, REEL_ACTION
-	add hl, bc
-	dec [hl]
-	dec [hl] ; REEL_ACTION_WAIT_CHANSEY
-	ld a, 1
-	ld [wSlotsDelay], a
-	ret
-
-; 92df7
-
-ReelAction_Unused: ; 92df7
-	call Slots_CheckMatchedAllThreeReels
-	ret c
-	ld a, SFX_STOP_SLOT
-	call Slots_PlaySFX
-	call Slots_WaitSFX
-	ld hl, REEL_ACTION
-	add hl, bc
-	inc [hl] ; REEL_ACTION_CHECK_DROP_REEL
-	call Slots_GetNumberOfGolems
-	ld hl, REEL_MANIP_DELAY
-	add hl, bc
-	ld [hl], a
-ReelAction_CheckDropReel: ; 92e10
-	ld hl, REEL_MANIP_DELAY
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr nz, .spin
-	call Slots_CheckMatchedAllThreeReels
-	call Slots_StopReel
-	ret
-
-.spin
-	dec [hl]
-	ld hl, REEL_ACTION
-	add hl, bc
-	inc [hl] ; REEL_ACTION_WAIT_DROP_REEL
-	ld hl, REEL_FIELD_0B
-	add hl, bc
-	ld [hl], 32
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 0
-ReelAction_WaitDropReel: ; 92e31
-	ld hl, REEL_FIELD_0B
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .DropReel
-	dec [hl]
-	ret
-
-.DropReel:
-	ld hl, REEL_ACTION
-	add hl, bc
-	dec [hl]
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 8
-	ret
-
-; 92e47
-
-ReelAction_StartSlowAdvanceReel3: ; 92e47
-; Ensures SEVENs are lined up if there's bias to SEVEN.
-; Ensures nothing is lined up if there's no bias symbols.
-; No other bias symbols are compatible with this mode.
-
-; This is achieved by slowly advancing the reel a full round,
-; plus any necessary slot until the desired result is produced.
-
-	call Slots_CheckMatchedAllThreeReels
-	ret c
-	ld a, SFX_STOP_SLOT
-	call Slots_PlaySFX
-	call Slots_WaitSFX
-	ld hl, REEL_SPIN_RATE
-	add hl, bc
-	ld [hl], 1
-	ld hl, REEL_ACTION
-	add hl, bc
-	inc [hl] ; REEL_ACTION_WAIT_SLOW_ADVANCE_REEL3
-	ld hl, REEL_MANIP_DELAY
-	add hl, bc
-	ld [hl], 16
-ReelAction_WaitSlowAdvanceReel3: ; 92e64
-	ld hl, REEL_MANIP_DELAY
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .check1
-	dec [hl]
-.play_sfx
-	ld a, SFX_GOT_SAFARI_BALLS
-	call Slots_PlaySFX
-	ret
-
-.check1
-	ld a, [wSlotBias]
-	and a
-	jr nz, .check2
-	call Slots_CheckMatchedAllThreeReels
-	jr nc, .play_sfx
-	and a
-	jr nz, .play_sfx
-	call Slots_StopReel
-	call WaitSFX
-	ret
-
-.check2
-	call Slots_CheckMatchedAllThreeReels
-	jr c, .play_sfx
-	call Slots_StopReel
-	call WaitSFX
-	ret
-
-; 92e94
-
-Slots_CheckMatchedFirstTwoReels: ; 92e94
-	xor a
-	ld [wFirstTwoReelsMatching], a
-	ld [wFirstTwoReelsMatchingSevens], a
-	call Slots_GetCurrentReelState
-	call Slots_CopyReelState
-	ld a, [wSlotBet]
-	and 3
-	ld e, a
-	ld d, 0
-	ld hl, .Jumptable
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, .return
-	push de
-	jp hl
-
-.return
-	ld a, [wFirstTwoReelsMatching]
-	and a
-	ret z
-	scf
-	ret
-
-; 92ebd
-
-.Jumptable: ; 92ebd
-	dw .zero
-	dw .one
-	dw .two
-	dw .three
-; 92ec5
-
-.three ; 92ec5
-	call .CheckUpwardsDiag
-	call .CheckDownwardsDiag
-
-.two ; 92ecb
-	call .CheckBottomRow
-	call .CheckTopRow
-
-.one ; 92ed1
-	call .CheckMiddleRow
-
-.zero ; 92ed4
-	ret
-
-; 92ed5
-
-.CheckBottomRow: ; 92ed5
-	ld hl, wCurrReelStopped
-	ld a, [wReel1Stopped]
-	cp [hl]
-	call z, .StoreResult
-	ret
-
-; 92ee0
-
-.CheckUpwardsDiag: ; 92ee0
-	ld hl, wCurrReelStopped + 1
-	ld a, [wReel1Stopped]
-	cp [hl]
-	call z, .StoreResult
-	ret
-
-; 92eeb
-
-.CheckMiddleRow: ; 92eeb
-	ld hl, wCurrReelStopped + 1
-	ld a, [wReel1Stopped + 1]
-	cp [hl]
-	call z, .StoreResult
-	ret
-
-; 92ef6
-
-.CheckDownwardsDiag: ; 92ef6
-	ld hl, wCurrReelStopped + 1
-	ld a, [wReel1Stopped + 2]
-	cp [hl]
-	call z, .StoreResult
-	ret
-
-; 92f01
-
-.CheckTopRow: ; 92f01
-	ld hl, wCurrReelStopped + 2
-	ld a, [wReel1Stopped + 2]
-	cp [hl]
-	call z, .StoreResult
-	ret
-
-; 92f0c
-
-.StoreResult: ; 92f0c
-	ld [wSlotBuildingMatch], a
-	and a
-	jr nz, .matching_sevens
-	ld a, 1
-	ld [wFirstTwoReelsMatchingSevens], a
-
-.matching_sevens
-	ld a, 1
-	ld [wFirstTwoReelsMatching], a
-	ret
-
-; 92f1d
-
-Slots_CheckMatchedAllThreeReels: ; 92f1d
-	ld a, SLOTS_NO_MATCH
-	ld [wSlotMatched], a
-	call Slots_GetCurrentReelState
-	call Slots_CopyReelState
-	ld a, [wSlotBet]
-	and 3
-	ld e, a
-	ld d, 0
-	ld hl, .Jumptable
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, .return
-	push de
-	jp hl
-
-.return
-	ld a, [wSlotMatched]
-	cp SLOTS_NO_MATCH
-	jr nz, .matched_nontrivial
-	and a
-	ret
-
-.matched_nontrivial
-	scf
-	ret
-
-; 92f48
-
-.Jumptable: ; 92f48
-	dw .zero
-	dw .one
-	dw .two
-	dw .three
-; 92f50
-
-.three ; 92f50
-	call .CheckUpwardsDiag
-	call .CheckDownwardsDiag
-
-.two ; 92f56
-	call .CheckBottomRow
-	call .CheckTopRow
-
-.one ; 92f5c
-	call .CheckMiddleRow
-
-.zero ; 92f5f
-	ret
-
-; 92f60
-
-.CheckBottomRow: ; 92f60
-	ld hl, wCurrReelStopped
-	ld a, [wReel1Stopped]
-	cp [hl]
-	ret nz
-	ld hl, wReel2Stopped
-	cp [hl]
-	call z, .StoreResult
-	ret
-
-; 92f70
-
-.CheckUpwardsDiag: ; 92f70
-	ld hl, wCurrReelStopped + 2
-	ld a, [wReel1Stopped]
-	cp [hl]
-	ret nz
-	ld hl, wReel2Stopped + 1
-	cp [hl]
-	call z, .StoreResult
-	ret
-
-; 92f80
-
-.CheckMiddleRow: ; 92f80
-	ld hl, wCurrReelStopped + 1
-	ld a, [wReel1Stopped + 1]
-	cp [hl]
-	ret nz
-	ld hl, wReel2Stopped + 1
-	cp [hl]
-	call z, .StoreResult
-	ret
-
-; 92f90
-
-.CheckDownwardsDiag: ; 92f90
-	ld hl, wCurrReelStopped
-	ld a, [wReel1Stopped + 2]
-	cp [hl]
-	ret nz
-	ld hl, wReel2Stopped + 1
-	cp [hl]
-	call z, .StoreResult
-	ret
-
-; 92fa0
-
-.CheckTopRow: ; 92fa0
-	ld hl, wCurrReelStopped + 2
-	ld a, [wReel1Stopped + 2]
-	cp [hl]
-	ret nz
-	ld hl, wReel2Stopped + 2
-	cp [hl]
-	call z, .StoreResult
-	ret
-
-; 92fb0
-
-.StoreResult: ; 92fb0
-	ld [wSlotMatched], a
-	ret
-
-; 92fb4
-
-Slots_CopyReelState: ; 92fb4
-	ld de, wCurrReelStopped
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-	ret
-
-; 92fc0
-
-Slots_GetNumberOfGolems: ; 92fc0
-	ld hl, REEL_POSITION
-	add hl, bc
-	ld a, [hl]
-	push af
-	push hl
-	call .Check7Bias
-	pop hl
-	pop af
-	ld [hl], a
-	ld a, e
-	ret
-
-; 92fcf
-
-.Check7Bias: ; 92fcf
-	ld a, [wSlotBias]
-	and a
-	jr nz, .not_biased_to_seven
-	ld e, $0
-.loop1
-	ld hl, REEL_POSITION
-	add hl, bc
-	inc [hl]
-	inc e
-	push de
-	call Slots_CheckMatchedAllThreeReels
-	pop de
-	jr nc, .loop1
-	and a
-	jr nz, .loop1
-	ret
-
-.not_biased_to_seven
-	call Random
-	and $7
-	cp $4 ; ((50 percent) & 7) + 1
-	jr c, .not_biased_to_seven
-	ld e, a
-.loop2
-	ld a, e
-	inc e
-	ld hl, REEL_POSITION
-	add hl, bc
-	add [hl]
-	ld [hl], a
-	push de
-	call Slots_CheckMatchedAllThreeReels
-	pop de
-	jr c, .loop2
-	ret
-
-; 93002
-
-Slots_InitBias: ; 93002 (24:7002)
-	ld a, [wSlotBias]
-	and a
-	ret z
-	ld hl, .Normal
-	ld a, [wScriptVar]
-	and a
-	jr z, .okay
-	ld hl, .Lucky
-.okay
-	call Random
-	ld c, a
-.loop
-	ld a, [hli]
-	cp c
-	jr nc, .done
-	inc hl
-	jr .loop
-
-.done
-	ld a, [hl]
-	ld [wSlotBias], a
-	ret
-
-; 93023 (24:7023)
-
-.Normal: ; 93023
-	db $01, SLOTS_SEVEN    ; 1/256
-	db $03, SLOTS_POKEBALL ; 1/128
-	db $0a, SLOTS_STARYU   ; 7/256
-	db $14, SLOTS_SQUIRTLE ; 5/128
-	db $28, SLOTS_PIKACHU  ; 5/64
-	db $30, SLOTS_CHERRY   ; 1/32
-	db $ff, SLOTS_NO_BIAS   ; everything else
-; 93031
-
-.Lucky: ; 93031
-	db $02, SLOTS_SEVEN    ;  1/128
-	db $03, SLOTS_POKEBALL ;  1/256
-	db $08, SLOTS_STARYU   ;  5/256
-	db $10, SLOTS_SQUIRTLE ;  1/32
-	db $1e, SLOTS_PIKACHU  ;  7/128
-	db $50, SLOTS_CHERRY   ; 25/128
-	db $ff, SLOTS_NO_BIAS   ; everything else
-; 9303f
-
-Slots_IlluminateBetLights: ; 9303f (24:703f)
-	ld b, $14 ; turned on
-	ld a, [wSlotBet]
-	dec a
-	jr z, Slots_Lights1OnOff
-	dec a
-	jr z, Slots_Lights2OnOff
-	jr Slots_Lights3OnOff
-
-Slots_DeilluminateBetLights: ; 9304c (24:704c)
-	ld b, $23 ; turned off
-Slots_Lights3OnOff: ; 9304e (24:704e)
-	hlcoord 3, 2
-	call Slots_TurnLightsOnOrOff
-	hlcoord 3, 10
-	call Slots_TurnLightsOnOrOff
-Slots_Lights2OnOff: ; 9305a (24:705a)
-	hlcoord 3, 4
-	call Slots_TurnLightsOnOrOff
-	hlcoord 3, 8
-	call Slots_TurnLightsOnOrOff
-Slots_Lights1OnOff: ; 93066 (24:7066)
-	hlcoord 3, 6
-
-Slots_TurnLightsOnOrOff: ; 93069 (24:7069)
-	ld a, b
-	ld [hl], a
-	ld de, SCREEN_WIDTH / 2 + 3
-	add hl, de
-	ld [hl], a
-	ld de, SCREEN_WIDTH / 2 - 3
-	add hl, de
-	inc a
-	ld [hl], a
-	ld de, SCREEN_WIDTH / 2 + 3
-	add hl, de
-	ld [hl], a
-	ret
-
-Slots_AskBet: ; 9307c (24:707c)
-.loop
-	ld hl, .Text_BetHowManyCoins
-	call PrintText
-	ld hl, .MenuHeader
-	call LoadMenuHeader
-	call VerticalMenu
-	call CloseWindow
-	ret c
-	ld a, [wMenuCursorY]
-	ld b, a
-	ld a, 4
-	sub b
-	ld [wSlotBet], a
-	ld hl, wCoins
-	ld c, a
-	ld a, [hli]
-	and a
-	jr nz, .Start
-	ld a, [hl]
-	cp c
-	jr nc, .Start
-	ld hl, .Text_NotEnoughCoins
-	call PrintText
-	jr .loop
-
-.Start:
-	ld hl, wCoins + 1
-	ld a, [hl]
-	sub c
-	ld [hld], a
-	jr nc, .ok
-	dec [hl]
-.ok
-	call WaitSFX
-	ld de, SFX_PAY_DAY
-	call PlaySFX
-	ld hl, .Text_Start
-	call PrintText
-	and a
-	ret
-
-; 930c7 (24:70c7)
-
-.Text_BetHowManyCoins: ; 0x930c7
-	; Bet how many coins?
-	text_jump UnknownText_0x1c5049
-	db "@"
-; 0x930cc
-
-.Text_Start: ; 0x930cc
-	; Start!
-	text_jump UnknownText_0x1c505e
-	db "@"
-; 0x930d1
-
-.Text_NotEnoughCoins: ; 0x930d1
-	; Not enough coins.
-	text_jump UnknownText_0x1c5066
-	db "@"
-; 0x930d6
-
-.MenuHeader: ; 0x930d6
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 14, 10, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
-	dw .MenuData
-	db 1 ; default option
-; 0x930de
-
-.MenuData: ; 0x930de
-	db STATICMENU_CURSOR ; flags
-	db 3 ; items
-	db " 3@"
-	db " 2@"
-	db " 1@"
-; 0x930e9
-
-Slots_AskPlayAgain: ; 930e9 (24:70e9)
-	ld hl, wCoins
-	ld a, [hli]
-	or [hl]
-	jr nz, .you_have_coins
-	ld hl, .Text_OutOfCoins
-	call PrintText
-	ld c, 60
-	call DelayFrames
-	jr .exit_slots
-
-.you_have_coins
-	ld hl, .Text_PlayAgain
-	call PrintText
-	call LoadMenuTextBox
-	lb bc, 14, 12
-	call PlaceYesNoBox
-	ld a, [wMenuCursorY]
-	dec a
-	call CloseWindow
-	and a
-	jr nz, .exit_slots
-	and a
-	ret
-
-.exit_slots
-	scf
-	ret
-
-; 9311a (24:711a)
-
-.Text_OutOfCoins: ; 9311a
-	text_jump UnknownText_0x1c5079
-	db "@"
-
-.Text_PlayAgain: ; 9311f
-	text_jump UnknownText_0x1c5092
-	db "@"
-
-Slots_GetPayout: ; 93124 (24:7124)
-	ld a, [wSlotMatched]
-	cp SLOTS_NO_MATCH
-	jr z, .no_win
-	srl a
-	ld e, a
-	ld d, 0
-	ld hl, .PayoutTable
-	add hl, de
-	ld a, [hli]
-	ld [wPayout + 1], a
-	ld e, a
-	ld a, [hl]
-	ld [wPayout], a
-	ld d, a
-	farcall StubbedTrainerRankings_AddToSlotsPayouts
-	ret
-
-.PayoutTable:
-	dw 300
-	dw  50
-	dw   6
-	dw   8
-	dw  10
-	dw  15
-
-.no_win
-	ld hl, wPayout
-	xor a
-	ld [hli], a
-	ld [hl], a
-	ret
-
-Slots_PayoutText: ; 93158 (24:7158)
-	ld a, [wSlotMatched]
-	cp SLOTS_NO_MATCH
-	jr nz, .MatchedSomething
-	ld hl, .Text_Darn
-	call PrintText
-	farcall StubbedTrainerRankings_EndSlotsWinStreak
-	ret
-
-.MatchedSomething:
-	srl a
-	ld e, a
-	ld d, 0
-	ld hl, .PayoutStrings
-	add hl, de
-	add hl, de
-	add hl, de
-	ld de, wStringBuffer2
-	ld bc, 4
-	call CopyBytes
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, .return
-	push de
-	jp hl
-
-.return
-	ld hl, .Text_PrintPayout
-	call PrintText
-	farcall StubbedTrainerRankings_AddToSlotsWinStreak
-	ret
-
-; 93195 (24:7195)
-
-.PayoutStrings: ; 93195
-	dbw "300@", .LinedUpSevens
-	dbw "50@@", .LinedUpPokeballs
-	dbw "6@@@", .LinedUpMonOrCherry
-	dbw "8@@@", .LinedUpMonOrCherry
-	dbw "10@@", .LinedUpMonOrCherry
-	dbw "15@@", .LinedUpMonOrCherry
-; 931b9
-
-.Text_PrintPayout: ; 0x931b9
-	start_asm
-	ld a, [wSlotMatched]
-	add $25
-	ldcoord_a 2, 13
-	inc a
-	ldcoord_a 2, 14
-	inc a
-	ldcoord_a 3, 13
-	inc a
-	ldcoord_a 3, 14
-	hlcoord 18, 17
-	ld [hl], "▼"
-	ld hl, .Text_LinedUpWonCoins
-rept 4
-	inc bc
-endr
-	ret
-
-; 931db
-
-.Text_LinedUpWonCoins: ; 0x931db
-	; lined up! Won @  coins!
-	text_jump UnknownText_0x1c509f
-	db "@"
-; 0x931e0
-
-.Text_Darn: ; 0x931e0
-	; Darn!
-	text_jump UnknownText_0x1c50bb
-	db "@"
-; 0x931e5
-
-.LinedUpSevens: ; 931e5
-	ld a, SFX_2ND_PLACE
-	call Slots_PlaySFX
-	call WaitSFX
-
-; Oddly, the rarest mode (wKeepSevenBiasChance = 1) is the one with
-; the worse odds to favor seven symbol streaks (12.5% vs 25%).
-; it's possible that either the wKeepSevenBiasChance initialization
-; or this code was intended to lead to flipped percentages.
-	ld a, [wKeepSevenBiasChance]
-	and a
-	jr nz, .lower_seven_streak_odds
-	call Random
-	and %0010100
-	ret z ; 25% chance to stick with seven symbol bias
-	ld a, SLOTS_NO_BIAS
-	ld [wSlotBias], a
-	ret
-
-.lower_seven_streak_odds
-	call Random
-	and %0011100
-	ret z ; 12.5% chance to stick with seven symbol bias
-	ld a, SLOTS_NO_BIAS
-	ld [wSlotBias], a
-	ret
-
-; 9320b
-
-.LinedUpPokeballs: ; 9320b
-	ld a, SFX_3RD_PLACE
-	call Slots_PlaySFX
-	call WaitSFX
-	ret
-
-; 93214
-
-.LinedUpMonOrCherry: ; 93214
-	ld a, SFX_PRESENT
-	call Slots_PlaySFX
-	call WaitSFX
-	ret
-
-; 9321d
-
-Slots_AnimateGolem: ; 9321d (24:721d)
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld e, [hl]
-	ld d, 0
-	ld hl, .Jumptable
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-.Jumptable: ; 9322d (24:722d)
-	dw .init
-	dw .fall
-	dw .roll
-
-.init ; 93233 (24:7233)
-	ld hl, SPRITEANIMSTRUCT_0E
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr nz, .retain
-	ld a, 2
-	ld [wSlotsDelay], a
-	ld hl, SPRITEANIMSTRUCT_INDEX
-	add hl, bc
-	ld [hl], $0
-	ret
-
-.retain
-	dec [hl]
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	inc [hl]
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $30
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld [hl], $0
-
-.fall ; 93259 (24:7259)
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	cp $20
-	jr c, .play_sound
-	dec [hl]
-	ld e, a
-	ld d, 14 * 8
-	farcall BattleAnim_Sine_e
-	ld a, e
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.play_sound
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	inc [hl]
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld [hl], $2
-	ld a, 1
-	ld [wSlotsDelay], a
-	ld a, SFX_PLACE_PUZZLE_PIECE_DOWN
-	call Slots_PlaySFX
-	ret
-
-.roll ; 93289 (24:7289)
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld a, [hl]
-	inc [hl]
-	inc [hl]
-	cp 9 * 8
-	jr nc, .restart
-	and $3
-	ret nz
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld a, [hl]
-	xor $ff
-	inc a
-	ld [hl], a
-	ld [hSCY], a
-	ret
-
-.restart
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	xor a
-	ld [hl], a
-	ld [hSCY], a
-	ret
-
-Slots_AnimateChansey: ; 932ac (24:72ac)
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld e, [hl]
-	ld d, 0
-	ld hl, .Jumptable
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-.Jumptable: ; 932bc (24:72bc)
-	dw .walk
-	dw .one
-	dw .two
-
-.walk ; 932c2 (24:72c2)
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld a, [hl]
-	inc [hl]
-	cp 13 * 8
-	jr z, .limit
-	and $f
-	ret nz
-	ld de, SFX_JUMP_OVER_LEDGE
-	call PlaySFX
-	ret
-
-.limit
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	inc [hl]
-	ld a, 1
-	ld [wSlotsDelay], a
-
-.one ; 932e0 (24:72e0)
-	ld a, [wSlotsDelay]
-	cp $2
-	jr z, .retain
-	cp $5
-	ret nz
-	ld hl, SPRITEANIMSTRUCT_INDEX
-	add hl, bc
-	ld [hl], $0
-	ret
-
-.retain
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	inc [hl]
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $8
-.two ; 932fc (24:72fc)
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .spawn_egg
-	dec [hl]
-	ret
-
-.spawn_egg
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	dec [hl]
-	push bc
-	depixel 12, 13, 0, 4
-	ld a, SPRITE_ANIM_INDEX_SLOTS_EGG
-	call _InitSpriteAnimStruct
-	pop bc
-	ret
-
-; 93316 (24:7316)
-
-Slots_WaitSFX: ; 93316
-	push bc
-	ld c, 16
-	call DelayFrames
-	pop bc
-	ret
-
-; 9331e
-
-Slots_PlaySFX: ; 9331e (24:731e)
-	push de
-	ld e, a
-	ld d, 0
-	call PlaySFX
-	pop de
-	ret
-
-; 93327 (24:7327)
-
-; The first three positions are repeated to
-; avoid needing to check indices when copying.
-Reel1Tilemap: ; 93327
-	db SLOTS_SEVEN    ;  0
-	db SLOTS_CHERRY   ;  1
-	db SLOTS_STARYU   ;  2
-	db SLOTS_PIKACHU  ;  3
-	db SLOTS_SQUIRTLE ;  4
-	db SLOTS_SEVEN    ;  5
-	db SLOTS_CHERRY   ;  6
-	db SLOTS_STARYU   ;  7
-	db SLOTS_PIKACHU  ;  8
-	db SLOTS_SQUIRTLE ;  9
-	db SLOTS_POKEBALL ; 10
-	db SLOTS_CHERRY   ; 11
-	db SLOTS_STARYU   ; 12
-	db SLOTS_PIKACHU  ; 13
-	db SLOTS_SQUIRTLE ; 14
-	db SLOTS_SEVEN    ;  0
-	db SLOTS_CHERRY   ;  1
-	db SLOTS_STARYU   ;  2
-
-Reel2Tilemap: ; 93339
-	db SLOTS_SEVEN    ;  0
-	db SLOTS_PIKACHU  ;  1
-	db SLOTS_CHERRY   ;  2
-	db SLOTS_SQUIRTLE ;  3
-	db SLOTS_STARYU   ;  4
-	db SLOTS_POKEBALL ;  5
-	db SLOTS_PIKACHU  ;  6
-	db SLOTS_CHERRY   ;  7
-	db SLOTS_SQUIRTLE ;  8
-	db SLOTS_STARYU   ;  9
-	db SLOTS_POKEBALL ; 10
-	db SLOTS_PIKACHU  ; 11
-	db SLOTS_CHERRY   ; 12
-	db SLOTS_SQUIRTLE ; 13
-	db SLOTS_STARYU   ; 14
-	db SLOTS_SEVEN    ;  0
-	db SLOTS_PIKACHU  ;  1
-	db SLOTS_CHERRY   ;  2
-
-Reel3Tilemap: ; 9334b
-	db SLOTS_SEVEN    ;  0
-	db SLOTS_PIKACHU  ;  1
-	db SLOTS_CHERRY   ;  2
-	db SLOTS_SQUIRTLE ;  3
-	db SLOTS_STARYU   ;  4
-	db SLOTS_PIKACHU  ;  5
-	db SLOTS_CHERRY   ;  6
-	db SLOTS_SQUIRTLE ;  7
-	db SLOTS_STARYU   ;  8
-	db SLOTS_PIKACHU  ;  9
-	db SLOTS_POKEBALL ; 10
-	db SLOTS_CHERRY   ; 11
-	db SLOTS_SQUIRTLE ; 12
-	db SLOTS_STARYU   ; 13
-	db SLOTS_PIKACHU  ; 14
-	db SLOTS_SEVEN    ;  0
-	db SLOTS_PIKACHU  ;  1
-	db SLOTS_CHERRY   ;  2
-; 9335d
-
-SlotsTilemap: ; 9335d
-INCBIN "gfx/slots/slots.tilemap"
-; 9344d
-
-Slots1LZ: ; 9344d
-INCBIN "gfx/slots/slots_1.2bpp.lz"
-; 935cd
-
-Slots2LZ: ; 935cd
-INCBIN "gfx/slots/slots_2.2bpp.lz"
-; 9382d
-
-Slots3LZ: ; 9382d
-INCBIN "gfx/slots/slots_3.2bpp.lz"
-; 93a3d
--- a/engine/game/unown_puzzle.asm
+++ /dev/null
@@ -1,877 +1,0 @@
-PUZZLE_BORDER EQU $ee
-PUZZLE_VOID   EQU $ef
-
-puzcoord EQUS "* 6 +"
-
-_UnownPuzzle: ; e1190
-	ld a, [hInMenu]
-	push af
-	ld a, $1
-	ld [hInMenu], a
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	xor a
-	ld [hBGMapMode], a
-	call DisableLCD
-	ld hl, wMisc ; includes wPuzzlePieces
-	ld bc, wMiscEnd - wMisc
-	xor a
-	call ByteFill
-	ld hl, UnownPuzzleCursorGFX
-	ld de, vTiles1 tile $60
-	ld bc, 4 tiles
-	call CopyBytes
-	ld hl, UnownPuzzleStartCancelLZ
-	ld de, vTiles1 tile $6d
-	call Decompress
-	call LoadUnownPuzzlePiecesGFX
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, PUZZLE_BORDER
-	call ByteFill
-	hlcoord 4, 3
-	lb bc, 12, 12
-	ld a, PUZZLE_VOID
-	call UnownPuzzle_FillBox
-	call InitUnownPuzzlePiecePositions
-	call UnownPuzzle_UpdateTilemap
-	call PlaceStartCancelBox
-	xor a
-	ld [hSCY], a
-	ld [hSCX], a
-	ld [rWY], a
-	ld [wJumptableIndex], a
-	ld [wHoldingUnownPuzzlePiece], a
-	ld [wUnownPuzzleCursorPosition], a
-	ld [wUnownPuzzleHeldPiece], a
-	ld a, %10010011
-	ld [rLCDC], a
-	call WaitBGMap
-	ld b, SCGB_UNOWN_PUZZLE
-	call GetSGBLayout
-	ld a, $e4
-	call DmgToCgbBGPals
-	ld a, $24
-	call DmgToCgbObjPal0
-	xor a
-	ld [wSolvedUnownPuzzle], a
-	call DelayFrame
-.loop
-	call JoyTextDelay
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .quit
-	call UnownPuzzleJumptable
-	ld a, [wHoldingUnownPuzzlePiece]
-	and a
-	jr nz, .holding_piece
-	ld a, [hVBlankCounter]
-	and $10
-	jr z, .clear
-.holding_piece
-	call RedrawUnownPuzzlePieces
-	jr .next
-
-.clear
-	call ClearSprites
-.next
-	call DelayFrame
-	jr .loop
-
-.quit
-	pop af
-	ld [hInMenu], a
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	ld a, LCDC_DEFAULT
-	ld [rLCDC], a
-	ret
-; e124e
-
-InitUnownPuzzlePiecePositions: ; e124e
-	ld c,  1
-	ld b, 16
-.load_loop
-	call Random
-	and $f
-	ld hl, .PuzzlePieceInitialPositions
-	ld e, a
-	ld d, $0
-	add hl, de
-	ld e, [hl]
-	ld hl, wPuzzlePieces
-	add hl, de
-	ld a, [hl]
-	and a
-	jr nz, .load_loop
-	ld [hl], c
-	inc c
-	dec b
-	jr nz, .load_loop
-	ret
-; e126d
-
-.PuzzlePieceInitialPositions: ; e126d
-initpuzcoord: MACRO
-rept _NARG / 2
-	db \1 puzcoord \2
-	shift
-	shift
-endr
-ENDM
-	initpuzcoord 0,0, 0,1, 0,2, 0,3, 0,4, 0,5
-	initpuzcoord 1,0,                     1,5
-	initpuzcoord 2,0,                     2,5
-	initpuzcoord 3,0,                     3,5
-	initpuzcoord 4,0,                     4,5
-	initpuzcoord 5,0,                     5,5
-	                   ; START > CANCEL
-; e127d
-
-PlaceStartCancelBox: ; e127d
-	call PlaceStartCancelBoxBorder
-	hlcoord 5, 16
-	ld a, $f6
-	ld c, 10
-.loop
-	ld [hli], a
-	inc a
-	dec c
-	jr nz, .loop
-	ret
-; e128d
-
-PlaceStartCancelBoxBorder: ; e128d
-	hlcoord 4, 15
-	ld a, $f0
-	ld [hli], a
-	ld bc, 10
-	ld a, $f1
-	call ByteFill
-	hlcoord 15, 15
-	ld a, $f2
-	ld [hli], a
-	hlcoord 4, 16
-	ld a, $f3
-	ld [hli], a
-	ld bc, 10
-	ld a, PUZZLE_VOID
-	call ByteFill
-	hlcoord 15, 16
-	ld a, $f3
-	ld [hli], a
-	hlcoord 4, 17
-	ld a, $f4
-	ld [hli], a
-	ld bc, 10
-	ld a, $f1
-	call ByteFill
-	hlcoord 15, 17
-	ld a, $f5
-	ld [hl], a
-	ret
-; e12ca
-
-UnownPuzzleJumptable: ; e12ca
-	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
-; e12d9
-
-.Jumptable: ; e12d9
-	dw .Function
-; e12db
-
-.Function: ; e12db
-	ld a, [hJoyPressed]
-	and START
-	jp nz, UnownPuzzle_Quit
-	ld a, [hJoyPressed]
-	and A_BUTTON
-	jp nz, UnownPuzzle_A
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_UP
-	jr nz, .d_up
-	ld a, [hl]
-	and D_DOWN
-	jr nz, .d_down
-	ld a, [hl]
-	and D_LEFT
-	jr nz, .d_left
-	ld a, [hl]
-	and D_RIGHT
-	jr nz, .d_right
-	ret
-
-.d_up
-	ld hl, wUnownPuzzleCursorPosition
-	ld a, [hl]
-	cp 1 puzcoord 0
-	ret c
-	sub 6
-	ld [hl], a
-	jr .done_joypad
-
-.d_down
-	ld hl, wUnownPuzzleCursorPosition
-	ld a, [hl]
-	cp 4 puzcoord 1
-	ret z
-	cp 4 puzcoord 2
-	ret z
-	cp 4 puzcoord 3
-	ret z
-	cp 4 puzcoord 4
-	ret z
-	cp 5 puzcoord 0
-	ret nc
-	add 6
-	ld [hl], a
-	jr .done_joypad
-
-.d_left
-	ld hl, wUnownPuzzleCursorPosition
-	ld a, [hl]
-	and a
-	ret z
-	cp 1 puzcoord 0
-	ret z
-	cp 2 puzcoord 0
-	ret z
-	cp 3 puzcoord 0
-	ret z
-	cp 4 puzcoord 0
-	ret z
-	cp 5 puzcoord 0
-	ret z
-	cp 5 puzcoord 5
-	jr z, .left_overflow
-	dec [hl]
-	jr .done_joypad
-
-.left_overflow
-	ld [hl], 5 puzcoord 0
-	jr .done_joypad
-
-.d_right
-	ld hl, wUnownPuzzleCursorPosition
-	ld a, [hl]
-	cp 0 puzcoord 5
-	ret z
-	cp 1 puzcoord 5
-	ret z
-	cp 2 puzcoord 5
-	ret z
-	cp 3 puzcoord 5
-	ret z
-	cp 4 puzcoord 5
-	ret z
-	cp 5 puzcoord 5
-	ret z
-	cp 5 puzcoord 0
-	jr z, .right_overflow
-	inc [hl]
-	jr .done_joypad
-
-.right_overflow
-	ld [hl], 5 puzcoord 5
-
-.done_joypad
-	ld a, [wHoldingUnownPuzzlePiece]
-	and a
-	jr nz, .holding_piece
-	ld de, SFX_POUND
-	jr .play_sfx
-
-.holding_piece
-	ld de, SFX_MOVE_PUZZLE_PIECE
-
-.play_sfx
-	call PlaySFX
-	ret
-; e1376
-
-UnownPuzzle_A: ; e1376
-	ld a, [wHoldingUnownPuzzlePiece]
-	and a
-	jr nz, .TryPlacePiece
-	call UnownPuzzle_CheckCurrentTileOccupancy
-	and a
-	jr z, UnownPuzzle_InvalidAction
-	ld de, SFX_MEGA_KICK
-	call PlaySFX
-	ld [hl], 0
-	ld [wUnownPuzzleHeldPiece], a
-	call RedrawUnownPuzzlePieces
-	call FillUnoccupiedPuzzleSpace
-	call WaitBGMap
-	call WaitSFX
-	ld a, TRUE
-	ld [wHoldingUnownPuzzlePiece], a
-	ret
-
-.TryPlacePiece:
-	call UnownPuzzle_CheckCurrentTileOccupancy
-	and a
-	jr nz, UnownPuzzle_InvalidAction
-	ld de, SFX_PLACE_PUZZLE_PIECE_DOWN
-	call PlaySFX
-	ld a, [wUnownPuzzleHeldPiece]
-	ld [hl], a
-	call PlaceUnownPuzzlePieceGFX
-	call WaitBGMap
-	xor a
-	ld [wUnownPuzzleHeldPiece], a
-	call RedrawUnownPuzzlePieces
-	xor a
-	ld [wHoldingUnownPuzzlePiece], a
-	call WaitSFX
-	call CheckSolvedUnownPuzzle
-	ret nc
-
-; You solved the puzzle!
-	call PlaceStartCancelBoxBorder
-	call ClearSprites
-	ld de, SFX_1ST_PLACE
-	call PlaySFX
-	call WaitSFX
-	call SimpleWaitPressAorB
-	ld a, TRUE
-	ld [wSolvedUnownPuzzle], a
-UnownPuzzle_Quit: ; e13de
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-UnownPuzzle_InvalidAction: ; e13e4
-	ld de, SFX_WRONG
-	call PlaySFX
-	call WaitSFX
-	ret
-; e13ee
-
-UnownPuzzle_FillBox: ; e13ee
-	ld de, SCREEN_WIDTH
-.row
-	push bc
-	push hl
-.col
-	ld [hli], a
-	dec c
-	jr nz, .col
-	pop hl
-	add hl, de
-	pop bc
-	dec b
-	jr nz, .row
-	ret
-; e13fe
-
-UnownPuzzle_UpdateTilemap: ; e13fe
-	xor a
-	ld [wUnownPuzzleCursorPosition], a
-	ld c, 6 * 6
-.loop
-	push bc
-	call UnownPuzzle_CheckCurrentTileOccupancy
-	ld [wUnownPuzzleHeldPiece], a
-	and a
-	jr z, .not_holding_piece
-	call PlaceUnownPuzzlePieceGFX
-	jr .next
-
-.not_holding_piece
-	call FillUnoccupiedPuzzleSpace
-
-.next
-	ld hl, wUnownPuzzleCursorPosition
-	inc [hl]
-	pop bc
-	dec c
-	jr nz, .loop
-	ret
-; e141f
-
-PlaceUnownPuzzlePieceGFX: ; e141f
-	ld a, $2 ; tilemap coords
-	call GetUnownPuzzleCoordData
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	push hl
-	call GetCurrentPuzzlePieceVTileCorner
-	pop hl
-	ld de, SCREEN_WIDTH
-	ld b, 3
-.row
-	ld c, 3
-	push hl
-.col
-	ld [hli], a
-	inc a
-	dec c
-	jr nz, .col
-	add 9
-	pop hl
-	add hl, de
-	dec b
-	jr nz, .row
-	ret
-; e1441
-
-FillUnoccupiedPuzzleSpace: ; e1441
-	ld a, 2 ; tilemap coords
-	call GetUnownPuzzleCoordData
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	push hl
-	ld a, 4 ; tile
-	call GetUnownPuzzleCoordData
-	ld a, [hl]
-	pop hl
-	ld de, SCREEN_WIDTH
-	ld b, 3
-.row
-	ld c, 3
-	push hl
-.col
-	ld [hli], a
-	dec c
-	jr nz, .col
-	pop hl
-	add hl, de
-	dec b
-	jr nz, .row
-	ret
-; e1463
-
-GetUnownPuzzleCoordData: ; e1463
-	ld e, a
-	ld d, 0
-	ld hl, UnownPuzzleCoordData
-	add hl, de
-	ld a, [wUnownPuzzleCursorPosition]
-	ld e, a
-rept 6
-	add hl, de
-endr
-	ret
-; e1475
-
-UnownPuzzle_CheckCurrentTileOccupancy: ; e1475
-	ld hl, wPuzzlePieces
-	ld a, [wUnownPuzzleCursorPosition]
-	ld e, a
-	ld d, $0
-	add hl, de
-	ld a, [hl]
-	ret
-; e1481
-
-GetCurrentPuzzlePieceVTileCorner: ; e1481
-	ld a, [wUnownPuzzleHeldPiece]
-	ld hl, .Corners
-	add l
-	ld l, a
-	ld a, $0
-	adc h
-	ld h, a
-	ld a, [hl]
-	ret
-; e148f
-
-.Corners: ; e148f
-; 00, 01, 02
-; 0c, 0d, 0e
-; 18, 19, 1a
-	db $e0 ; no piece selected
-	db $00, $03, $06, $09
-	db $24, $27, $2a, $2d
-	db $48, $4b, $4e, $51
-	db $6c, $6f, $72, $75
-; e14a0
-
-CheckSolvedUnownPuzzle: ; e14a0
-	ld hl, .SolvedPuzzleConfiguration
-	ld de, wPuzzlePieces
-	ld c, 6 * 6
-.loop
-	ld a, [de]
-	cp [hl]
-	jr nz, .not_solved
-	inc de
-	inc hl
-	dec c
-	jr nz, .loop
-	scf
-	ret
-
-.not_solved
-	and a
-	ret
-; e14b5
-
-.SolvedPuzzleConfiguration: ; e14b5
-	db $00, $00, $00, $00, $00, $00
-	db $00, $01, $02, $03, $04, $00
-	db $00, $05, $06, $07, $08, $00
-	db $00, $09, $0a, $0b, $0c, $00
-	db $00, $0d, $0e, $0f, $10, $00
-	db $00, $00, $00, $00, $00, $00
-; e14d9
-
-RedrawUnownPuzzlePieces: ; e14d9
-	call GetCurrentPuzzlePieceVTileCorner
-	ld [wd002], a
-	xor a
-	call GetUnownPuzzleCoordData ; get pixel positions
-	ld a, [hli]
-	ld b, [hl]
-	ld c, a
-	ld a, [wd002]
-	cp $e0
-	jr z, .NoPiece
-	ld hl, .OAM_HoldingPiece
-	jr .load
-
-.NoPiece:
-	ld hl, .OAM_NotHoldingPiece
-
-.load
-	ld de, wVirtualOAMSprite00
-.loop
-	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, [wd002]
-	add [hl]
-	ld [de], a ; tile id
-	inc hl
-	inc de
-	ld a, [hli]
-	ld [de], a ; attributes
-	inc de
-	jr .loop
-; e150f
-
-.OAM_HoldingPiece: ; e150f
-	dsprite -1, -4, -1, -4, $00, 0
-	dsprite -1, -4,  0, -4, $01, 0
-	dsprite -1, -4,  0,  4, $02, 0
-	dsprite  0, -4, -1, -4, $0c, 0
-	dsprite  0, -4,  0, -4, $0d, 0
-	dsprite  0, -4,  0,  4, $0e, 0
-	dsprite  0,  4, -1, -4, $18, 0
-	dsprite  0,  4,  0, -4, $19, 0
-	dsprite  0,  4,  0,  4, $1a, 0
-	db -1
-
-.OAM_NotHoldingPiece: ; e1534
-	dsprite -1, -4, -1, -4, $00, 0
-	dsprite -1, -4,  0, -4, $01, 0
-	dsprite -1, -4,  0,  4, $00, 0 | X_FLIP
-	dsprite  0, -4, -1, -4, $02, 0
-	dsprite  0, -4,  0, -4, $03, 0
-	dsprite  0, -4,  0,  4, $02, 0 | X_FLIP
-	dsprite  0,  4, -1, -4, $00, 0 | Y_FLIP
-	dsprite  0,  4,  0, -4, $01, 0 | Y_FLIP
-	dsprite  0,  4,  0,  4, $00, 0 | X_FLIP | Y_FLIP
-	db -1
-
-UnownPuzzleCoordData: ; e1559
-
-puzzle_coords: MACRO
-	dbpixel \1, \2, \3, \4
-	dwcoord \5, \6
-	db \7, \8
-ENDM
-; OAM coords, tilemap coords, vacant tile, filler
-	puzzle_coords  3,  3, 4, 4,  1,  0, PUZZLE_BORDER, 0
-	puzzle_coords  6,  3, 4, 4,  4,  0, PUZZLE_BORDER, 0
-	puzzle_coords  9,  3, 4, 4,  7,  0, PUZZLE_BORDER, 0
-	puzzle_coords 12,  3, 4, 4, 10,  0, PUZZLE_BORDER, 0
-	puzzle_coords 15,  3, 4, 4, 13,  0, PUZZLE_BORDER, 0
-	puzzle_coords 18,  3, 4, 4, 16,  0, PUZZLE_BORDER, 0
-
-	puzzle_coords  3,  6, 4, 4,  1,  3, PUZZLE_BORDER, 0
-	puzzle_coords  6,  6, 4, 4,  4,  3, PUZZLE_VOID,   0
-	puzzle_coords  9,  6, 4, 4,  7,  3, PUZZLE_VOID,   0
-	puzzle_coords 12,  6, 4, 4, 10,  3, PUZZLE_VOID,   0
-	puzzle_coords 15,  6, 4, 4, 13,  3, PUZZLE_VOID,   0
-	puzzle_coords 18,  6, 4, 4, 16,  3, PUZZLE_BORDER, 0
-
-	puzzle_coords  3,  9, 4, 4,  1,  6, PUZZLE_BORDER, 0
-	puzzle_coords  6,  9, 4, 4,  4,  6, PUZZLE_VOID,   0
-	puzzle_coords  9,  9, 4, 4,  7,  6, PUZZLE_VOID,   0
-	puzzle_coords 12,  9, 4, 4, 10,  6, PUZZLE_VOID,   0
-	puzzle_coords 15,  9, 4, 4, 13,  6, PUZZLE_VOID,   0
-	puzzle_coords 18,  9, 4, 4, 16,  6, PUZZLE_BORDER, 0
-
-	puzzle_coords  3, 12, 4, 4,  1,  9, PUZZLE_BORDER, 0
-	puzzle_coords  6, 12, 4, 4,  4,  9, PUZZLE_VOID,   0
-	puzzle_coords  9, 12, 4, 4,  7,  9, PUZZLE_VOID,   0
-	puzzle_coords 12, 12, 4, 4, 10,  9, PUZZLE_VOID,   0
-	puzzle_coords 15, 12, 4, 4, 13,  9, PUZZLE_VOID,   0
-	puzzle_coords 18, 12, 4, 4, 16,  9, PUZZLE_BORDER, 0
-
-	puzzle_coords  3, 15, 4, 4,  1, 12, PUZZLE_BORDER, 0
-	puzzle_coords  6, 15, 4, 4,  4, 12, PUZZLE_VOID,   0
-	puzzle_coords  9, 15, 4, 4,  7, 12, PUZZLE_VOID,   0
-	puzzle_coords 12, 15, 4, 4, 10, 12, PUZZLE_VOID,   0
-	puzzle_coords 15, 15, 4, 4, 13, 12, PUZZLE_VOID,   0
-	puzzle_coords 18, 15, 4, 4, 16, 12, PUZZLE_BORDER, 0
-
-	puzzle_coords  3, 18, 4, 4,  1, 15, PUZZLE_BORDER, 0
-	puzzle_coords  6, 18, 4, 4,  4, 15, PUZZLE_BORDER, 0
-	puzzle_coords  9, 18, 4, 4,  7, 15, PUZZLE_BORDER, 0
-	puzzle_coords 12, 18, 4, 4, 10, 15, PUZZLE_BORDER, 0
-	puzzle_coords 15, 18, 4, 4, 13, 15, PUZZLE_BORDER, 0
-	puzzle_coords 18, 18, 4, 4, 16, 15, PUZZLE_BORDER, 0
-
-ConvertLoadedPuzzlePieces: ; e1631
-	ld hl, vTiles2
-	ld de, vTiles0
-	ld b, 6
-.loop
-	push bc
-	push hl
-	push hl
-	call .EnlargePuzzlePieceTiles
-	pop hl
-	ld bc, 1 tiles / 2
-	add hl, bc
-	call .EnlargePuzzlePieceTiles
-	pop hl
-	ld bc, 6 tiles
-	add hl, bc
-	pop bc
-	dec b
-	jr nz, .loop
-	call UnownPuzzle_AddPuzzlePieceBorders
-	ret
-; e1654
-
-.EnlargePuzzlePieceTiles: ; e1654
-; double size
-	ld c, 6
-.loop1
-	push bc
-	push hl
-	push hl
-	ld c, 4
-.loop2
-	push bc
-	ld a, [hli]
-	and $f0
-	swap a
-	call .GetEnlargedTile
-	ld c, a
-	ld a, [hli]
-	and $f0
-	swap a
-	call .GetEnlargedTile
-	ld b, a
-	ld a, c
-	ld [de], a
-	inc de
-	ld a, b
-	ld [de], a
-	inc de
-	ld a, c
-	ld [de], a
-	inc de
-	ld a, b
-	ld [de], a
-	inc de
-	pop bc
-	dec c
-	jr nz, .loop2
-	pop hl
-	ld c, 4
-.loop3
-	push bc
-	ld a, [hli]
-	and $f
-	call .GetEnlargedTile
-	ld c, a
-	ld a, [hli]
-	and $f
-	call .GetEnlargedTile
-	ld b, a
-	ld a, c
-	ld [de], a
-	inc de
-	ld a, b
-	ld [de], a
-	inc de
-	ld a, c
-	ld [de], a
-	inc de
-	ld a, b
-	ld [de], a
-	inc de
-	pop bc
-	dec c
-	jr nz, .loop3
-	pop hl
-	ld bc, 1 tiles
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .loop1
-	ret
-; e16aa
-
-.GetEnlargedTile: ; e16aa
-	push hl
-	ld hl, .EnlargedTiles
-	add l
-	ld l, a
-	ld a, 0
-	adc h
-	ld h, a
-	ld a, [hl]
-	pop hl
-	ret
-; e16b7
-
-.EnlargedTiles: ; e16b7
-
-x = 0
-rept 16
-	db ((x & %1000) * %11000) + ((x & %0100) * %1100) + ((x & %0010) * %110) + ((x & %0001) * %11)
-x = x + 1
-endr
-; e16c7
-
-UnownPuzzle_AddPuzzlePieceBorders: ; e16c7
-	ld hl, PuzzlePieceBorderData
-	ld a, 8
-.loop
-	push af
-	push hl
-	ld a, [hli]
-	ld e, a
-	ld a, [hli]
-	ld d, a
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	call .LoadGFX
-	pop hl
-rept 4
-	inc hl
-endr
-	pop af
-	dec a
-	jr nz, .loop
-	ret
-; e16e2
-
-.LoadGFX: ; e16e2
-	lb bc, 4, 4
-.loop1
-	push bc
-
-.loop2
-	push de
-	push hl
-
-	ld b, 1 tiles
-.loop3
-	ld a, [de]
-	or [hl]
-	ld [hli], a
-	inc de
-	dec b
-	jr nz, .loop3
-
-	pop hl
-	ld de, 3 tiles
-	add hl, de
-	pop de
-	dec c
-	jr nz, .loop2
-
-	ld bc, 24 tiles
-	add hl, bc
-	pop bc
-	dec b
-	jr nz, .loop1
-	ret
-; e1703
-
-PuzzlePieceBorderData: ; e1703
-	dw .TileBordersGFX + 0 tiles, vTiles0 tile $00
-	dw .TileBordersGFX + 1 tiles, vTiles0 tile $01
-	dw .TileBordersGFX + 2 tiles, vTiles0 tile $02
-	dw .TileBordersGFX + 3 tiles, vTiles0 tile $0c
-	dw .TileBordersGFX + 4 tiles, vTiles0 tile $0e
-	dw .TileBordersGFX + 5 tiles, vTiles0 tile $18
-	dw .TileBordersGFX + 6 tiles, vTiles0 tile $19
-	dw .TileBordersGFX + 7 tiles, vTiles0 tile $1a
-; e1723
-
-.TileBordersGFX: ; e1723
-INCBIN "gfx/unown_puzzle/tile_borders.2bpp"
-
-LoadUnownPuzzlePiecesGFX: ; e17a3
-	ld a, [wScriptVar]
-	maskbits NUM_UNOWN_PUZZLES
-	ld e, a
-	ld d, 0
-	ld hl, .LZPointers
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, vTiles2
-	call Decompress
-	call ConvertLoadedPuzzlePieces
-	ret
-; e17bd
-
-.LZPointers: ; e17bd
-; entries correspond to UNOWNPUZZLE_* constants
-	dw KabutoPuzzleLZ
-	dw OmanytePuzzleLZ
-	dw AerodactylPuzzleLZ
-	dw HoOhPuzzleLZ
-; e17c5
-
-UnownPuzzleCursorGFX: ; e17c5
-INCBIN "gfx/unown_puzzle/cursor.2bpp"
-
-UnownPuzzleStartCancelLZ: ; e1805
-INCBIN "gfx/unown_puzzle/start_cancel.2bpp.lz"
-
-HoOhPuzzleLZ: ; e18ab
-INCBIN "gfx/unown_puzzle/hooh.2bpp.lz"
-
-AerodactylPuzzleLZ: ; e19fb
-INCBIN "gfx/unown_puzzle/aerodactyl.2bpp.lz"
-
-KabutoPuzzleLZ: ; e1bab
-INCBIN "gfx/unown_puzzle/kabuto.2bpp.lz"
-
-OmanytePuzzleLZ: ; e1c9b
-INCBIN "gfx/unown_puzzle/omanyte.2bpp.lz"
--- /dev/null
+++ b/engine/games/card_flip.asm
@@ -1,0 +1,1692 @@
+CARDFLIP_LIGHT_OFF EQU $ef
+CARDFLIP_LIGHT_ON  EQU $f5
+
+CARDFLIP_DECK_SIZE EQU 4 * 6
+
+; two labels below called from inside ./dummy_game.asm
+Unknown_e00ed: ; e00ed (38:40ed)
+; Graphics for an unused Game Corner
+; game were meant to be here.
+ret_e00ed: ; e00ed (38:40ed)
+	ret
+
+_CardFlip: ; e00ee (38:40ee)
+	ld hl, wOptions
+	set 4, [hl]
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	ld de, MUSIC_NONE
+	call PlayMusic
+	call DelayFrame
+	call DisableLCD
+	call LoadStandardFont
+	call LoadFontsExtra
+
+	ld hl, CardFlipLZ01
+	ld de, vTiles2 tile $00
+	call Decompress
+	ld hl, CardFlipLZ02
+	ld de, vTiles2 tile $3e
+	call Decompress
+	ld hl, CardFlipLZ03
+	ld de, vTiles0 tile $00
+	call Decompress
+	ld hl, CardFlipOffButtonGFX
+	ld de, vTiles0 tile CARDFLIP_LIGHT_OFF
+	ld bc, 1 tiles
+	call CopyBytes
+	ld hl, CardFlipOnButtonGFX
+	ld de, vTiles0 tile CARDFLIP_LIGHT_ON
+	ld bc, 1 tiles
+	call CopyBytes
+
+	call CardFlip_ShiftDigitsLeftTwoPixels
+	call CardFlip_InitTilemap
+	call CardFlip_InitAttrPals
+	call EnableLCD
+	call WaitBGMap2
+	ld a, $e4
+	call DmgToCgbBGPals
+	ld de, $e4e4
+	call DmgToCgbObjPals
+	call DelayFrame
+	xor a
+	ld [wJumptableIndex], a
+	ld a, $2
+	ld [wCardFlipCursorY], a
+	ld [wCardFlipCursorX], a
+	ld de, MUSIC_GAME_CORNER
+	call PlayMusic
+.MasterLoop:
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .leavethegame
+	call .CardFlip
+	jr .MasterLoop
+.leavethegame
+	call WaitSFX
+	ld de, SFX_QUIT_SLOTS
+	call PlaySFX
+	call WaitSFX
+	call ClearBGPalettes
+	ld hl, wOptions
+	res 4, [hl]
+	ret
+
+.CardFlip: ; e0191 (38:4191)
+	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
+; e01a0 (38:41a0)
+
+.Jumptable: ; e01a0
+	dw .AskPlayWithThree
+	dw .DeductCoins
+	dw .ChooseACard
+	dw .PlaceYourBet
+	dw .CheckTheCard
+	dw .TabulateTheResult
+	dw .PlayAgain
+	dw .Quit
+; e01b0
+
+.Increment: ; e01b0
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+; e01b5
+
+.AskPlayWithThree: ; e01b5
+	ld hl, .PlayWithThreeCoinsText
+	call CardFlip_UpdateCoinBalanceDisplay
+	call YesNoBox
+	jr c, .SaidNo
+	call CardFlip_ShuffleDeck
+	call .Increment
+	ret
+
+.SaidNo:
+	ld a, 7
+	ld [wJumptableIndex], a
+	ret
+; e01cd
+
+.PlayWithThreeCoinsText: ; 0xe01cd
+	; Play with three coins?
+	text_jump UnknownText_0x1c5793
+	db "@"
+; 0xe01d2
+
+.DeductCoins: ; e01d2
+	ld a, [wCoins]
+	ld h, a
+	ld a, [wCoins + 1]
+	ld l, a
+	ld a, h
+	and a
+	jr nz, .deduct ; You have at least 256 coins.
+	ld a, l
+	cp 3
+	jr nc, .deduct ; You have at least 3 coins.
+	ld hl, .NotEnoughCoinsText
+	call CardFlip_UpdateCoinBalanceDisplay
+	ld a, 7
+	ld [wJumptableIndex], a
+	ret
+
+.deduct
+	ld de, -3
+	add hl, de
+	ld a, h
+	ld [wCoins], a
+	ld a, l
+	ld [wCoins + 1], a
+	ld de, SFX_TRANSACTION
+	call PlaySFX
+	xor a
+	ld [hBGMapMode], a
+	call CardFlip_PrintCoinBalance
+	ld a, $1
+	ld [hBGMapMode], a
+	call WaitSFX
+	call .Increment
+	ret
+; e0212
+
+.NotEnoughCoinsText: ; 0xe0212
+	; Not enough coins…
+	text_jump UnknownText_0x1c57ab
+	db "@"
+; 0xe0217
+
+.ChooseACard: ; e0217
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 0, 0
+	lb bc, 12, 9
+	call CardFlip_FillGreenBox
+	hlcoord 9, 0
+	ld bc, SCREEN_WIDTH
+	ld a, [wCardFlipNumCardsPlayed]
+	call AddNTimes
+	ld [hl], CARDFLIP_LIGHT_ON
+	ld a, $1
+	ld [hBGMapMode], a
+	ld c, 20
+	call DelayFrames
+	hlcoord 2, 0
+	call PlaceCardFaceDown
+	ld a, $1
+	ld [hBGMapMode], a
+	ld c, 20
+	call DelayFrames
+	hlcoord 2, 6
+	call PlaceCardFaceDown
+	call WaitBGMap
+	ld hl, .ChooseACardText
+	call CardFlip_UpdateCoinBalanceDisplay
+	xor a
+	ld [wCardFlipWhichCard], a
+.loop
+	call JoyTextDelay
+	ld a, [hJoyLast]
+	and A_BUTTON
+	jr nz, .next
+	ld de, SFX_KINESIS
+	call PlaySFX
+	call PlaceOAMCardBorder
+	ld c, 4
+	call DelayFrames
+	ld hl, wCardFlipWhichCard
+	ld a, [hl]
+	xor $1
+	ld [hl], a
+	jr .loop
+
+.next
+	ld de, SFX_SLOT_MACHINE_START
+	call PlaySFX
+	ld a, $3
+.loop2
+	push af
+	call PlaceOAMCardBorder
+	ld c, 4
+	call DelayFrames
+	call ClearSprites
+	ld c, 4
+	call DelayFrames
+	pop af
+	dec a
+	jr nz, .loop2
+	ld hl, wCardFlipWhichCard
+	ld a, [hl]
+	push af
+	xor $1
+	ld [hl], a
+	call GetCoordsOfChosenCard
+	lb bc, 6, 5
+	call CardFlip_FillGreenBox
+	pop af
+	ld [wCardFlipWhichCard], a
+	call .Increment
+	ret
+; e02b2
+
+.ChooseACardText: ; 0xe02b2
+	; Choose a card.
+	text_jump UnknownText_0x1c57be
+	db "@"
+; 0xe02b7
+
+.PlaceYourBet: ; e02b7
+	ld hl, .PlaceYourBetText
+	call CardFlip_UpdateCoinBalanceDisplay
+.betloop
+	call JoyTextDelay
+	ld a, [hJoyLast]
+	and A_BUTTON
+	jr nz, .betdone
+	call ChooseCard_HandleJoypad
+	call CardFlip_UpdateCursorOAM
+	call DelayFrame
+	jr .betloop
+
+.betdone
+	call .Increment
+	ret
+; e02d5
+
+.PlaceYourBetText: ; 0xe02d5
+	; Place your bet.
+	text_jump UnknownText_0x1c57ce
+	db "@"
+; 0xe02da
+
+.CheckTheCard: ; e02da
+	xor a
+	ld [hVBlankCounter], a
+	call CardFlip_UpdateCursorOAM
+	call WaitSFX
+	ld de, SFX_CHOOSE_A_CARD
+	call PlaySFX
+	call WaitSFX
+	ld a, [wCardFlipNumCardsPlayed]
+	ld e, a
+	ld d, 0
+	ld hl, wDeck
+	add hl, de
+	add hl, de
+	ld a, [wCardFlipWhichCard]
+	ld e, a
+	add hl, de
+	ld a, [hl]
+	ld [wCardFlipFaceUpCard], a
+	ld e, a
+	ld hl, wDiscardPile
+	add hl, de
+	ld [hl], TRUE
+	call GetCoordsOfChosenCard
+	call CardFlip_DisplayCardFaceUp
+	call WaitBGMap2
+	call .Increment
+	ret
+; e0314
+
+.TabulateTheResult: ; e0314
+	call CardFlip_CheckWinCondition
+	call WaitPressAorB_BlinkCursor
+	call .Increment
+	ret
+; e031e
+
+.PlayAgain: ; e031e
+	call ClearSprites
+	ld hl, .PlayAgainText
+	call CardFlip_UpdateCoinBalanceDisplay
+	call YesNoBox
+	jr nc, .Continue
+	call .Increment
+	ret
+
+.Continue:
+	ld a, [wCardFlipNumCardsPlayed]
+	inc a
+	ld [wCardFlipNumCardsPlayed], a
+	cp 12
+	jr c, .KeepTheCurrentDeck
+	call CardFlip_InitTilemap
+	ld a, $1
+	ld [hBGMapMode], a
+	call CardFlip_ShuffleDeck
+	ld hl, .CardsShuffledText
+	call PrintText
+	jr .LoopAround
+
+.KeepTheCurrentDeck:
+	call CardFlip_BlankDiscardedCardSlot
+
+.LoopAround:
+	ld a, 1
+	ld [wJumptableIndex], a
+	ret
+; e0356
+
+.PlayAgainText: ; 0xe0356
+	; Want to play again?
+	text_jump UnknownText_0x1c57df
+	db "@"
+; 0xe035b
+
+.CardsShuffledText: ; 0xe035b
+	; The cards have been shuffled.
+	text_jump UnknownText_0x1c57f4
+	db "@"
+; 0xe0360
+
+.Quit: ; e0360
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+; e0366
+
+CardFlip_ShuffleDeck: ; e0366
+	ld hl, wDeck
+	ld bc, CARDFLIP_DECK_SIZE
+	xor a
+	call ByteFill
+	ld de, wDeck
+	ld c, CARDFLIP_DECK_SIZE - 1
+.loop
+	call Random
+	and $1f
+	cp CARDFLIP_DECK_SIZE
+	jr nc, .loop
+	ld l, a
+	ld h, $0
+	add hl, de
+	ld a, [hl]
+	and a
+	jr nz, .loop
+	ld [hl], c
+	dec c
+	jr nz, .loop
+	xor a
+	ld [wCardFlipNumCardsPlayed], a
+	ld hl, wDiscardPile
+	ld bc, CARDFLIP_DECK_SIZE
+	call ByteFill
+	ret
+; e0398
+
+CollapseCursorPosition: ; e0398
+	ld hl, 0
+	ld bc, 6
+	ld a, [wCardFlipCursorY]
+	call AddNTimes
+	ld b, $0
+	ld a, [wCardFlipCursorX]
+	ld c, a
+	add hl, bc
+	ret
+; e03ac
+
+GetCoordsOfChosenCard: ; e03ac
+	ld a, [wCardFlipWhichCard]
+	and a
+	jr nz, .BottomCard
+	hlcoord 2, 0
+	bcpixel 2, 3
+	jr .done
+
+.BottomCard:
+	hlcoord 2, 6
+	bcpixel 8, 3
+
+.done
+	ret
+; e03c1
+
+PlaceCardFaceDown: ; e03c1
+	xor a
+	ld [hBGMapMode], a
+	ld de, .FaceDownCardTilemap
+	lb bc, 6, 5
+	call CardFlip_CopyToBox
+	ret
+; e03ce
+
+.FaceDownCardTilemap: ; e03ce
+	db $08, $09, $09, $09, $0a
+	db $0b, $28, $2b, $28, $0c
+	db $0b, $2c, $2d, $2e, $0c
+	db $0b, $2f, $30, $31, $0c
+	db $0b, $32, $33, $34, $0c
+	db $0d, $0e, $0e, $0e, $0f
+; e03ec
+
+CardFlip_DisplayCardFaceUp: ; e03ec
+	xor a
+	ld [hBGMapMode], a
+	push hl
+	push hl
+	; Flip the card face up.
+	ld de, .FaceUpCardTilemap
+	lb bc, 6, 5
+	call CardFlip_CopyToBox
+
+	; Get the level and species of the upturned card.
+	ld a, [wCardFlipFaceUpCard]
+	ld e, a
+	ld d, 0
+	ld hl, .Deck
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld e, a
+	ld d, [hl]
+
+	; Place the level.
+	pop hl
+	ld bc, 3 + SCREEN_WIDTH
+	add hl, bc
+	ld [hl], e
+
+	; Place the Pokepic.
+	ld bc, SCREEN_HEIGHT
+	add hl, bc
+	ld a, d
+	ld de, SCREEN_WIDTH
+	ld b, 3
+.row
+	push hl
+	ld c, 3
+.col
+	ld [hli], a
+	inc a
+	dec c
+	jr nz, .col
+	pop hl
+	add hl, de
+	dec b
+	jr nz, .row
+	pop hl
+
+	; Pointless CGB check
+	ld a, [hCGB]
+	and a
+	ret z
+
+	; Set the attributes
+	ld de, wAttrMap - wTileMap
+	add hl, de
+	ld a, [wCardFlipFaceUpCard]
+	and 3
+	inc a
+	lb bc, 6, 5
+	call CardFlip_FillBox
+	ret
+; e043b
+
+.FaceUpCardTilemap: ; e043b
+	db $18, $19, $19, $19, $1a
+	db $1b, $35, $7f, $7f, $1c
+	db $0b, $28, $28, $28, $0c
+	db $0b, $28, $28, $28, $0c
+	db $0b, $28, $28, $28, $0c
+	db $1d, $1e, $1e, $1e, $1f
+; e0459
+
+.Deck: ; e0459
+	; level, pic anchor (3x3)
+	db "1", $4e, "1", $57, "1", $69, "1", $60
+	db "2", $4e, "2", $57, "2", $69, "2", $60
+	db "3", $4e, "3", $57, "3", $69, "3", $60
+	db "4", $4e, "4", $57, "4", $69, "4", $60
+	db "5", $4e, "5", $57, "5", $69, "5", $60
+	db "6", $4e, "6", $57, "6", $69, "6", $60
+; e0489
+
+CardFlip_UpdateCoinBalanceDisplay: ; e0489
+	push hl
+	hlcoord 0, 12
+	ld b, 4
+	ld c, SCREEN_WIDTH - 2
+	call TextBox
+	pop hl
+	call PrintTextBoxText
+	call CardFlip_PrintCoinBalance
+	ret
+; e049c
+
+CardFlip_PrintCoinBalance: ; e049c
+	hlcoord 9, 15
+	ld b, 1
+	ld c, 9
+	call TextBox
+	hlcoord 10, 16
+	ld de, .CoinStr
+	call PlaceString
+	hlcoord 15, 16
+	ld de, wCoins
+	lb bc, PRINTNUM_LEADINGZEROS | 2, 4
+	call PrintNum
+	ret
+; e04bc
+
+.CoinStr:
+	db "COIN@"
+; e04c1
+
+CardFlip_InitTilemap: ; e04c1 (38:44c1)
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 0, 0
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	ld a, $29
+	call ByteFill
+	hlcoord 9, 0
+	ld de, CardFlipTilemap
+	lb bc, 12, 11
+	call CardFlip_CopyToBox
+	hlcoord 0, 12
+	lb bc, 4, 18
+	call TextBox
+	ret
+; e04e5 (38:44e5)
+
+CardFlip_FillGreenBox: ; e04e5
+	ld a, $29
+
+CardFlip_FillBox: ; e04e7 (38:44e7)
+.row
+	push bc
+	push hl
+.col
+	ld [hli], a
+	dec c
+	jr nz, .col
+	pop hl
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	pop bc
+	dec b
+	jr nz, .row
+	ret
+
+CardFlip_CopyToBox: ; e04f7 (38:44f7)
+.row
+	push bc
+	push hl
+.col
+	ld a, [de]
+	inc de
+	ld [hli], a
+	dec c
+	jr nz, .col
+	pop hl
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	pop bc
+	dec b
+	jr nz, .row
+	ret
+; e0509 (38:4509)
+
+CardFlip_CopyOAM: ; e0509
+	ld de, wVirtualOAMSprite00
+	ld a, [hli]
+.loop
+	push af
+	ld a, [hli]
+	add b
+	ld [de], a ; y
+	inc de
+	ld a, [hli]
+	add c
+	ld [de], a ; x
+	inc de
+	ld a, [hli]
+	ld [de], a ; tile id
+	inc de
+	ld a, [hli]
+	ld [de], a ; attributes
+	inc de
+	pop af
+	dec a
+	jr nz, .loop
+	ret
+; e0521
+
+CardFlip_ShiftDigitsLeftTwoPixels: ; e0521 (38:4521)
+	ld de, vTiles0 tile "0"
+	ld hl, vTiles0 tile "0" + 2
+	ld bc, 10 tiles - 2
+	call CopyBytes
+	ld hl, vTiles0 tile "9" + 1 tiles - 2
+	xor a
+	ld [hli], a
+	ld [hl], a
+	ret
+; e0534 (38:4534)
+
+CardFlip_BlankDiscardedCardSlot: ; e0534
+	xor a
+	ld [hBGMapMode], a
+	ld a, [wCardFlipFaceUpCard]
+	ld e, a
+	ld d, 0
+
+	and 3 ; get mon
+	ld c, a
+	ld b, 0
+
+	ld a, e
+	and $1c ; get level
+	srl a
+	add LOW(.Jumptable)
+	ld l, a
+	ld a, 0
+	adc HIGH(.Jumptable)
+	ld h, a
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+; e0553
+
+.Jumptable: ; e0553
+	dw .Level1
+	dw .Level2
+	dw .Level3
+	dw .Level4
+	dw .Level5
+	dw .Level6
+; e055f
+
+.Level1: ; e055f
+	ld hl, wDiscardPile + 4
+	add hl, de
+	ld a, [hl]
+	and a
+	jr nz, .discarded2
+	hlcoord 13, 3
+	add hl, bc
+	add hl, bc
+	ld [hl], $36
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hl], $37
+	ret
+
+.discarded2
+	hlcoord 13, 3
+	add hl, bc
+	add hl, bc
+	ld [hl], $36
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hl], $3d
+	ret
+; e0583
+
+.Level2: ; e0583
+	ld hl, wDiscardPile - 4
+	add hl, de
+	ld a, [hl]
+	and a
+	jr nz, .discarded1
+	hlcoord 13, 4
+	add hl, bc
+	add hl, bc
+	ld [hl], $3b
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hl], $3a
+	ret
+
+.discarded1
+	hlcoord 13, 4
+	add hl, bc
+	add hl, bc
+	ld [hl], $3d
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hl], $3a
+	ret
+; e05a7
+
+.Level3: ; e05a7
+	ld hl, wDiscardPile + 4
+	add hl, de
+	ld a, [hl]
+	and a
+	jr nz, .discarded4
+	hlcoord 13, 6
+	add hl, bc
+	add hl, bc
+	ld [hl], $36
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hl], $38
+	ret
+
+.discarded4
+	hlcoord 13, 6
+	add hl, bc
+	add hl, bc
+	ld [hl], $36
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hl], $3d
+	ret
+; e05cb
+
+.Level4: ; e05cb
+	ld hl, wDiscardPile - 4
+	add hl, de
+	ld a, [hl]
+	and a
+	jr nz, .discarded3
+	hlcoord 13, 7
+	add hl, bc
+	add hl, bc
+	ld [hl], $3c
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hl], $3a
+	ret
+
+.discarded3
+	hlcoord 13, 7
+	add hl, bc
+	add hl, bc
+	ld [hl], $3d
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hl], $3a
+	ret
+; e05ef
+
+.Level5: ; e05ef
+	ld hl, wDiscardPile + 4
+	add hl, de
+	ld a, [hl]
+	and a
+	jr nz, .discarded6
+	hlcoord 13, 9
+	add hl, bc
+	add hl, bc
+	ld [hl], $36
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hl], $39
+	ret
+
+.discarded6
+	hlcoord 13, 9
+	add hl, bc
+	add hl, bc
+	ld [hl], $36
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hl], $3d
+	ret
+; e0613
+
+.Level6: ; e0613
+	ld hl, wDiscardPile - 4
+	add hl, de
+	ld a, [hl]
+	and a
+	jr nz, .discarded5
+	hlcoord 13, 10
+	add hl, bc
+	add hl, bc
+	ld [hl], $3c
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hl], $3a
+	ret
+
+.discarded5
+	hlcoord 13, 10
+	add hl, bc
+	add hl, bc
+	ld [hl], $3d
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hl], $3a
+	ret
+; e0637
+
+CardFlip_CheckWinCondition: ; e0637
+	call CollapseCursorPosition
+	add hl, hl
+	ld de, .Jumptable
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+; e0643
+
+.Jumptable: ; e0643
+	dw .Impossible
+	dw .Impossible
+	dw .PikaJiggly
+	dw .PikaJiggly
+	dw .PoliOddish
+	dw .PoliOddish
+
+	dw .Impossible
+	dw .Impossible
+	dw .Pikachu
+	dw .Jigglypuff
+	dw .Poliwag
+	dw .Oddish
+
+	dw .OneTwo
+	dw .One
+	dw .PikaOne
+	dw .JigglyOne
+	dw .PoliOne
+	dw .OddOne
+
+	dw .OneTwo
+	dw .Two
+	dw .PikaTwo
+	dw .JigglyTwo
+	dw .PoliTwo
+	dw .OddTwo
+
+	dw .ThreeFour
+	dw .Three
+	dw .PikaThree
+	dw .JigglyThree
+	dw .PoliThree
+	dw .OddThree
+
+	dw .ThreeFour
+	dw .Four
+	dw .PikaFour
+	dw .JigglyFour
+	dw .PoliFour
+	dw .OddFour
+
+	dw .FiveSix
+	dw .Five
+	dw .PikaFive
+	dw .JigglyFive
+	dw .PoliFive
+	dw .OddFive
+
+	dw .FiveSix
+	dw .Six
+	dw .PikaSix
+	dw .JigglySix
+	dw .PoliSix
+	dw .OddSix
+; e06a3
+
+.Impossible: ; e06a3
+	jp .Lose
+; e06a6
+
+.PikaJiggly: ; e06a6
+	ld a, [wCardFlipFaceUpCard]
+	and $2
+	jp nz, .Lose
+	jr .WinSix
+
+.PoliOddish: ; e06b0
+	ld a, [wCardFlipFaceUpCard]
+	and $2
+	jr nz, .WinSix
+	jp .Lose
+
+.WinSix: ; e06ba
+	ld c, $6
+	ld de, SFX_2ND_PLACE
+	jp .Payout
+; e06c2
+
+.OneTwo: ; e06c2
+	ld a, [wCardFlipFaceUpCard]
+	and $18
+	jr z, .WinNine
+	jp .Lose
+
+.ThreeFour: ; e06cc
+	ld a, [wCardFlipFaceUpCard]
+	and $18
+	cp $8
+	jr z, .WinNine
+	jp .Lose
+
+.FiveSix: ; e06d8
+	ld a, [wCardFlipFaceUpCard]
+	and $18
+	cp $10
+	jr z, .WinNine
+	jp .Lose
+
+.WinNine: ; e06e4
+	ld c, $9
+	ld de, SFX_2ND_PLACE
+	jp .Payout
+; e06ec
+
+.Pikachu: ; e06ec
+	ld a, [wCardFlipFaceUpCard]
+	and $3
+	jr z, .WinTwelve
+	jp .Lose
+
+.Jigglypuff: ; e06f6
+	ld a, [wCardFlipFaceUpCard]
+	and $3
+	cp $1
+	jr z, .WinTwelve
+	jp .Lose
+
+.Poliwag: ; e0702
+	ld a, [wCardFlipFaceUpCard]
+	and $3
+	cp $2
+	jr z, .WinTwelve
+	jp .Lose
+
+.Oddish: ; e070e
+	ld a, [wCardFlipFaceUpCard]
+	and $3
+	cp $3
+	jr z, .WinTwelve
+	jp .Lose
+
+.WinTwelve: ; e071a
+	ld c, $c
+	ld de, SFX_2ND_PLACE
+	jp .Payout
+; e0722
+
+.One: ; e0722
+	ld a, [wCardFlipFaceUpCard]
+	and $1c
+	jr z, .WinEighteen
+	jp .Lose
+
+.Two: ; e072c
+	ld a, [wCardFlipFaceUpCard]
+	and $1c
+	cp $4
+	jr z, .WinEighteen
+	jp .Lose
+
+.Three: ; e0738
+	ld a, [wCardFlipFaceUpCard]
+	and $1c
+	cp $8
+	jr z, .WinEighteen
+	jp .Lose
+
+.Four: ; e0744
+	ld a, [wCardFlipFaceUpCard]
+	and $1c
+	cp $c
+	jr z, .WinEighteen
+	jp .Lose
+
+.Five: ; e0750
+	ld a, [wCardFlipFaceUpCard]
+	and $1c
+	cp $10
+	jr z, .WinEighteen
+	jp .Lose
+
+.Six: ; e075c
+	ld a, [wCardFlipFaceUpCard]
+	and $1c
+	cp $14
+	jr z, .WinEighteen
+	jp .Lose
+
+.WinEighteen: ; e0768
+	ld c, $12
+	ld de, SFX_2ND_PLACE
+	jp .Payout
+; e0770
+
+
+.PikaOne: ; e0770
+	ld e, $0
+	jr .CheckWin72
+
+.JigglyOne: ; e0774
+	ld e, $1
+	jr .CheckWin72
+
+.PoliOne: ; e0778
+	ld e, $2
+	jr .CheckWin72
+
+.OddOne: ; e077c
+	ld e, $3
+	jr .CheckWin72
+
+.PikaTwo: ; e0780
+	ld e, $4
+	jr .CheckWin72
+
+.JigglyTwo: ; e0784
+	ld e, $5
+	jr .CheckWin72
+
+.PoliTwo: ; e0788
+	ld e, $6
+	jr .CheckWin72
+
+.OddTwo: ; e078c
+	ld e, $7
+	jr .CheckWin72
+
+.PikaThree: ; e0790
+	ld e, $8
+	jr .CheckWin72
+
+.JigglyThree: ; e0794
+	ld e, $9
+	jr .CheckWin72
+
+.PoliThree: ; e0798
+	ld e, $a
+	jr .CheckWin72
+
+.OddThree: ; e079c
+	ld e, $b
+	jr .CheckWin72
+
+.PikaFour: ; e07a0
+	ld e, $c
+	jr .CheckWin72
+
+.JigglyFour: ; e07a4
+	ld e, $d
+	jr .CheckWin72
+
+.PoliFour: ; e07a8
+	ld e, $e
+	jr .CheckWin72
+
+.OddFour: ; e07ac
+	ld e, $f
+	jr .CheckWin72
+
+.PikaFive: ; e07b0
+	ld e, $10
+	jr .CheckWin72
+
+.JigglyFive: ; e07b4
+	ld e, $11
+	jr .CheckWin72
+
+.PoliFive: ; e07b8
+	ld e, $12
+	jr .CheckWin72
+
+.OddFive: ; e07bc
+	ld e, $13
+	jr .CheckWin72
+
+.PikaSix: ; e07c0
+	ld e, $14
+	jr .CheckWin72
+
+.JigglySix: ; e07c4
+	ld e, $15
+	jr .CheckWin72
+
+.PoliSix: ; e07c8
+	ld e, $16
+	jr .CheckWin72
+
+.OddSix: ; e07cc
+	ld e, $17
+
+.CheckWin72: ; e07ce
+	ld a, [wCardFlipFaceUpCard]
+	cp e
+	jr nz, .Lose
+	ld c, 72
+	ld de, SFX_2ND_PLACE
+	jr .Payout
+
+.Lose: ; e07db
+	ld de, SFX_WRONG
+	call PlaySFX
+	ld hl, .Text_Darn
+	call CardFlip_UpdateCoinBalanceDisplay
+	call WaitSFX
+	ret
+
+.Payout: ; e07eb
+	push bc
+	push de
+	ld hl, .Text_Yeah
+	call CardFlip_UpdateCoinBalanceDisplay
+	pop de
+	call PlaySFX
+	call WaitSFX
+	pop bc
+.loop
+	push bc
+	call .IsCoinCaseFull
+	jr c, .full
+	call .AddCoinPlaySFX
+
+.full
+	call CardFlip_PrintCoinBalance
+	ld c, 2
+	call DelayFrames
+	pop bc
+	dec c
+	jr nz, .loop
+	ret
+; e0811
+
+.Text_Yeah: ; 0xe0811
+	; Yeah!
+	text_jump UnknownText_0x1c5813
+	db "@"
+; 0xe0816
+
+.Text_Darn: ; 0xe0816
+	; Darn…
+	text_jump UnknownText_0x1c581a
+	db "@"
+; 0xe081b
+
+.AddCoinPlaySFX: ; e081b
+	ld a, [wCoins]
+	ld h, a
+	ld a, [wCoins + 1]
+	ld l, a
+	inc hl
+	ld a, h
+	ld [wCoins], a
+	ld a, l
+	ld [wCoins + 1], a
+	ld de, SFX_PAY_DAY
+	call PlaySFX
+	ret
+; e0833
+
+.IsCoinCaseFull: ; e0833
+	ld a, [wCoins]
+	cp HIGH(MAX_COINS)
+	jr c, .less
+	jr z, .check_low
+	jr .more
+
+.check_low
+	ld a, [wCoins + 1]
+	cp LOW(MAX_COINS)
+	jr c, .less
+
+.more
+	scf
+	ret
+
+.less
+	and a
+	ret
+; e0849
+
+PlaceOAMCardBorder: ; e0849
+	call GetCoordsOfChosenCard
+	ld hl, .SpriteData
+	call CardFlip_CopyOAM
+	ret
+; e0853
+
+.SpriteData: ; e0853
+	db 18
+	dsprite 0, 0, 0, 0, $04, 0
+	dsprite 0, 0, 1, 0, $06, 0
+	dsprite 0, 0, 2, 0, $06, 0
+	dsprite 0, 0, 3, 0, $06, 0
+	dsprite 0, 0, 4, 0, $04, 0 | X_FLIP
+
+	dsprite 1, 0, 0, 0, $05, 0
+	dsprite 1, 0, 4, 0, $05, 0 | X_FLIP
+
+	dsprite 2, 0, 0, 0, $05, 0
+	dsprite 2, 0, 4, 0, $05, 0 | X_FLIP
+
+	dsprite 3, 0, 0, 0, $05, 0
+	dsprite 3, 0, 4, 0, $05, 0 | X_FLIP
+
+	dsprite 4, 0, 0, 0, $05, $00
+	dsprite 4, 0, 4, 0, $05, 0 | X_FLIP
+
+	dsprite 5, 0, 0, 0, $04, 0 | Y_FLIP
+	dsprite 5, 0, 1, 0, $06, 0 | Y_FLIP
+	dsprite 5, 0, 2, 0, $06, 0 | Y_FLIP
+	dsprite 5, 0, 3, 0, $06, 0 | Y_FLIP
+	dsprite 5, 0, 4, 0, $04, 0 | X_FLIP | Y_FLIP
+; e089c
+
+ChooseCard_HandleJoypad: ; e089c
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_LEFT
+	jp nz, .d_left
+	ld a, [hl]
+	and D_RIGHT
+	jp nz, .d_right
+	ld a, [hl]
+	and D_UP
+	jp nz, .d_up
+	ld a, [hl]
+	and D_DOWN
+	jp nz, .d_down
+	ret
+; e08b8
+
+.d_left ; e08b8
+	ld hl, wCardFlipCursorX
+	ld a, [wCardFlipCursorY]
+	and a
+	jr z, .mon_pair_left
+	cp $1
+	jr z, .mon_group_left
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+	jp .play_sound
+
+.mon_group_left
+	ld a, [hl]
+	cp $3
+	jr c, .left_to_number_gp
+	dec [hl]
+	jp .play_sound
+
+.mon_pair_left
+	ld a, [hl]
+	and $e
+	ld [hl], a
+	cp $3
+	jr c, .left_to_number_gp
+	dec [hl]
+	dec [hl]
+	jp .play_sound
+
+.left_to_number_gp
+	ld a, $2
+	ld [wCardFlipCursorY], a
+	ld a, $1
+	ld [wCardFlipCursorX], a
+	jp .play_sound
+; e08ef
+
+.d_right ; e08ef
+	ld hl, wCardFlipCursorX
+	ld a, [wCardFlipCursorY]
+	and a
+	jr z, .mon_pair_right
+	ld a, [hl]
+	cp $5
+	ret nc
+	inc [hl]
+	jr .play_sound
+
+.mon_pair_right
+	ld a, [hl]
+	and $e
+	ld [hl], a
+	cp $4
+	ret nc
+	inc [hl]
+	inc [hl]
+	jr .play_sound
+
+.d_up ; e090a
+	ld hl, wCardFlipCursorY
+	ld a, [wCardFlipCursorX]
+	and a
+	jr z, .num_pair_up
+	cp $1
+	jr z, .num_gp_up
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+	jr .play_sound
+
+.num_gp_up
+	ld a, [hl]
+	cp $3
+	jr c, .up_to_mon_group
+	dec [hl]
+	jr .play_sound
+
+.num_pair_up
+	ld a, [hl]
+	and $e
+	ld [hl], a
+	cp $3
+	jr c, .up_to_mon_group
+	dec [hl]
+	dec [hl]
+	jr .play_sound
+
+.up_to_mon_group
+	ld a, $1
+	ld [wCardFlipCursorY], a
+	ld a, $2
+	ld [wCardFlipCursorX], a
+	jr .play_sound
+
+.d_down ; e093d
+	ld hl, wCardFlipCursorY
+	ld a, [wCardFlipCursorX]
+	and a
+	jr z, .num_pair_down
+	ld hl, wCardFlipCursorY
+	ld a, [hl]
+	cp $7
+	ret nc
+	inc [hl]
+	jr .play_sound
+
+.num_pair_down
+	ld a, [hl]
+	and $e
+	ld [hl], a
+	cp $6
+	ret nc
+	inc [hl]
+	inc [hl]
+
+.play_sound ; e0959
+	ld de, SFX_POKEBALLS_PLACED_ON_TABLE
+	call PlaySFX
+	ret
+; e0960
+
+CardFlip_UpdateCursorOAM: ; e0960
+	call ClearSprites
+	ld a, [hCGB]
+	and a
+	jr nz, .skip
+	ld a, [hVBlankCounter]
+	and $4
+	ret nz
+
+.skip
+	call CollapseCursorPosition
+	add hl, hl
+	add hl, hl
+	ld de, .OAMData
+	add hl, de
+	ld a, [hli]
+	ld c, a
+	ld a, [hli]
+	ld b, a
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	call CardFlip_CopyOAM
+	ret
+; e0981
+
+.OAMData: ; e0981
+cardflip_cursor: MACRO
+if _NARG >= 5
+	dbpixel \1, \2, \3, \4
+	dw \5
+else
+	dbpixel \1, \2
+	dw \3
+endc
+ENDM
+
+	cardflip_cursor 11,  2,       .Impossible
+	cardflip_cursor 12,  2,       .Impossible
+	cardflip_cursor 13,  2,       .PokeGroupPair
+	cardflip_cursor 13,  2,       .PokeGroupPair
+	cardflip_cursor 17,  2,       .PokeGroupPair
+	cardflip_cursor 17,  2,       .PokeGroupPair
+
+	cardflip_cursor 11,  3,       .Impossible
+	cardflip_cursor 12,  3,       .Impossible
+	cardflip_cursor 13,  3,       .PokeGroup
+	cardflip_cursor 15,  3,       .PokeGroup
+	cardflip_cursor 17,  3,       .PokeGroup
+	cardflip_cursor 19,  3,       .PokeGroup
+
+	cardflip_cursor 11,  5,       .NumGroupPair
+	cardflip_cursor 12,  5,       .NumGroup
+	cardflip_cursor 13,  5,       .SingleTile
+	cardflip_cursor 15,  5,       .SingleTile
+	cardflip_cursor 17,  5,       .SingleTile
+	cardflip_cursor 19,  5,       .SingleTile
+
+	cardflip_cursor 11,  5,       .NumGroupPair
+	cardflip_cursor 12,  6, 0, 4, .NumGroup
+	cardflip_cursor 13,  6, 0, 4, .SingleTile
+	cardflip_cursor 15,  6, 0, 4, .SingleTile
+	cardflip_cursor 17,  6, 0, 4, .SingleTile
+	cardflip_cursor 19,  6, 0, 4, .SingleTile
+
+	cardflip_cursor 11,  8,       .NumGroupPair
+	cardflip_cursor 12,  8,       .NumGroup
+	cardflip_cursor 13,  8,       .SingleTile
+	cardflip_cursor 15,  8,       .SingleTile
+	cardflip_cursor 17,  8,       .SingleTile
+	cardflip_cursor 19,  8,       .SingleTile
+
+	cardflip_cursor 11,  8,       .NumGroupPair
+	cardflip_cursor 12,  9, 0, 4, .NumGroup
+	cardflip_cursor 13,  9, 0, 4, .SingleTile
+	cardflip_cursor 15,  9, 0, 4, .SingleTile
+	cardflip_cursor 17,  9, 0, 4, .SingleTile
+	cardflip_cursor 19,  9, 0, 4, .SingleTile
+
+	cardflip_cursor 11, 11,       .NumGroupPair
+	cardflip_cursor 12, 11,       .NumGroup
+	cardflip_cursor 13, 11,       .SingleTile
+	cardflip_cursor 15, 11,       .SingleTile
+	cardflip_cursor 17, 11,       .SingleTile
+	cardflip_cursor 19, 11,       .SingleTile
+
+	cardflip_cursor 11, 11,       .NumGroupPair
+	cardflip_cursor 12, 12, 0, 4, .NumGroup
+	cardflip_cursor 13, 12, 0, 4, .SingleTile
+	cardflip_cursor 15, 12, 0, 4, .SingleTile
+	cardflip_cursor 17, 12, 0, 4, .SingleTile
+	cardflip_cursor 19, 12, 0, 4, .SingleTile
+; e0a41
+
+.SingleTile: ; e0a41
+	db 6
+	dsprite  0, 0,  -1, 7, $00, 0 | PRIORITY
+	dsprite  0, 0,   0, 0, $02, 0 | PRIORITY
+	dsprite  0, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  0, 5,  -1, 7, $00, 0 | Y_FLIP | PRIORITY
+	dsprite  0, 5,   0, 0, $02, 0 | Y_FLIP | PRIORITY
+	dsprite  0, 5,   1, 0, $03, 0 | PRIORITY
+
+.PokeGroup: ; e0a5a
+	db 26
+	dsprite  0, 0,  -1, 7, $00, 0 | PRIORITY
+	dsprite  0, 0,   0, 0, $02, 0 | PRIORITY
+	dsprite  0, 0,   1, 0, $00, 0 | X_FLIP | PRIORITY
+	dsprite  1, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  1, 0,   1, 0, $01, 0 | X_FLIP | PRIORITY
+	dsprite  2, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  2, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  3, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  3, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  4, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  4, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  5, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  5, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  6, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  6, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  7, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  7, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  8, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  8, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  9, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  9, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite 10, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite 10, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite 10, 1,  -1, 7, $00, 0 | Y_FLIP | PRIORITY
+	dsprite 10, 1,   0, 0, $02, 0 | Y_FLIP | PRIORITY
+	dsprite 10, 1,   1, 0, $03, 0 | PRIORITY
+
+.NumGroup: ; e0ac3
+	db 20
+	dsprite  0, 0,  -1, 7, $00, 0 | PRIORITY
+	dsprite  0, 0,   0, 0, $02, 0 | PRIORITY
+	dsprite  0, 0,   1, 0, $02, 0 | PRIORITY
+	dsprite  0, 0,   2, 0, $03, 0 | PRIORITY
+	dsprite  0, 0,   3, 0, $02, 0 | PRIORITY
+	dsprite  0, 0,   4, 0, $03, 0 | PRIORITY
+	dsprite  0, 0,   5, 0, $02, 0 | PRIORITY
+	dsprite  0, 0,   6, 0, $03, 0 | PRIORITY
+	dsprite  0, 0,   7, 0, $02, 0 | PRIORITY
+	dsprite  0, 0,   8, 0, $03, 0 | PRIORITY
+	dsprite  0, 5,  -1, 7, $00, 0 | Y_FLIP | PRIORITY
+	dsprite  0, 5,   0, 0, $02, 0 | Y_FLIP | PRIORITY
+	dsprite  0, 5,   1, 0, $02, 0 | Y_FLIP | PRIORITY
+	dsprite  0, 5,   2, 0, $03, 0 | PRIORITY
+	dsprite  0, 5,   3, 0, $02, 0 | Y_FLIP | PRIORITY
+	dsprite  0, 5,   4, 0, $03, 0 | PRIORITY
+	dsprite  0, 5,   5, 0, $02, 0 | Y_FLIP | PRIORITY
+	dsprite  0, 5,   6, 0, $03, 0 | PRIORITY
+	dsprite  0, 5,   7, 0, $02, 0 | Y_FLIP | PRIORITY
+	dsprite  0, 5,   8, 0, $03, 0 | PRIORITY
+
+.NumGroupPair: ; e0b14
+	db 30
+	dsprite  0, 0,   0, 0, $00, 0 | PRIORITY
+	dsprite  0, 0,   1, 0, $02, 0 | PRIORITY
+	dsprite  0, 0,   2, 0, $02, 0 | PRIORITY
+	dsprite  0, 0,   3, 0, $03, 0 | PRIORITY
+	dsprite  0, 0,   4, 0, $02, 0 | PRIORITY
+	dsprite  0, 0,   5, 0, $03, 0 | PRIORITY
+	dsprite  0, 0,   6, 0, $02, 0 | PRIORITY
+	dsprite  0, 0,   7, 0, $03, 0 | PRIORITY
+	dsprite  0, 0,   8, 0, $02, 0 | PRIORITY
+	dsprite  0, 0,   9, 0, $03, 0 | PRIORITY
+	dsprite  1, 0,   0, 0, $01, 0 | PRIORITY
+	dsprite  1, 0,   3, 0, $03, 0 | PRIORITY
+	dsprite  1, 0,   5, 0, $03, 0 | PRIORITY
+	dsprite  1, 0,   7, 0, $03, 0 | PRIORITY
+	dsprite  1, 0,   9, 0, $03, 0 | PRIORITY
+	dsprite  2, 0,   0, 0, $01, 0 | PRIORITY
+	dsprite  2, 0,   3, 0, $03, 0 | PRIORITY
+	dsprite  2, 0,   5, 0, $03, 0 | PRIORITY
+	dsprite  2, 0,   7, 0, $03, 0 | PRIORITY
+	dsprite  2, 0,   9, 0, $03, 0 | PRIORITY
+	dsprite  2, 1,   0, 0, $00, 0 | Y_FLIP | PRIORITY
+	dsprite  2, 1,   1, 0, $02, 0 | Y_FLIP | PRIORITY
+	dsprite  2, 1,   2, 0, $02, 0 | Y_FLIP | PRIORITY
+	dsprite  2, 1,   3, 0, $03, 0 | PRIORITY
+	dsprite  2, 1,   4, 0, $03, 0 | PRIORITY
+	dsprite  2, 1,   5, 0, $03, 0 | PRIORITY
+	dsprite  2, 1,   6, 0, $03, 0 | PRIORITY
+	dsprite  2, 1,   7, 0, $03, 0 | PRIORITY
+	dsprite  2, 1,   8, 0, $03, 0 | PRIORITY
+	dsprite  2, 1,   9, 0, $03, 0 | PRIORITY
+
+.PokeGroupPair: ; e0b8d
+	db 38
+	dsprite  0, 0,  -1, 7, $00, 0 | PRIORITY
+	dsprite  0, 0,   3, 0, $00, 0 | X_FLIP | PRIORITY
+	dsprite  1, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  1, 0,   3, 0, $01, 0 | X_FLIP | PRIORITY
+	dsprite  2, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  2, 0,   3, 0, $01, 0 | X_FLIP | PRIORITY
+	dsprite  3, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  3, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  3, 0,   3, 0, $03, 0 | PRIORITY
+	dsprite  4, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  4, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  4, 0,   3, 0, $03, 0 | PRIORITY
+	dsprite  5, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  5, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  5, 0,   3, 0, $03, 0 | PRIORITY
+	dsprite  6, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  6, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  6, 0,   3, 0, $03, 0 | PRIORITY
+	dsprite  7, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  7, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  7, 0,   3, 0, $03, 0 | PRIORITY
+	dsprite  8, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  8, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  8, 0,   3, 0, $03, 0 | PRIORITY
+	dsprite  9, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite  9, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite  9, 0,   3, 0, $03, 0 | PRIORITY
+	dsprite 10, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite 10, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite 10, 0,   3, 0, $03, 0 | PRIORITY
+	dsprite 11, 0,  -1, 7, $01, 0 | PRIORITY
+	dsprite 11, 0,   1, 0, $03, 0 | PRIORITY
+	dsprite 11, 0,   3, 0, $03, 0 | PRIORITY
+	dsprite 11, 1,  -1, 7, $00, 0 | Y_FLIP | PRIORITY
+	dsprite 11, 1,   0, 0, $02, 0 | Y_FLIP | PRIORITY
+	dsprite 11, 1,   1, 0, $03, 0 | Y_FLIP | PRIORITY
+	dsprite 11, 1,   2, 0, $02, 0 | Y_FLIP | PRIORITY
+	dsprite 11, 1,   3, 0, $03, 0 | X_FLIP | Y_FLIP | PRIORITY
+
+.Impossible: ; e0c26
+	db 4
+	dsprite  0, 0,   0, 0, $00, 0 | PRIORITY
+	dsprite  0, 0,   1, 0, $00, 0 | X_FLIP | PRIORITY
+	dsprite  1, 0,   0, 0, $00, 0 | Y_FLIP | PRIORITY
+	dsprite  1, 0,   1, 0, $00, 0 | X_FLIP | Y_FLIP | PRIORITY
+; e0c37
+
+CardFlip_InitAttrPals: ; e0c37 (38:4c37)
+	ld a, [hCGB]
+	and a
+	ret z
+
+	hlcoord 0, 0, wAttrMap
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	xor a
+	call ByteFill
+
+	hlcoord 12, 1, wAttrMap
+	lb bc, 2, 2
+	ld a, $1
+	call CardFlip_FillBox
+
+	hlcoord 14, 1, wAttrMap
+	lb bc, 2, 2
+	ld a, $2
+	call CardFlip_FillBox
+
+	hlcoord 16, 1, wAttrMap
+	lb bc, 2, 2
+	ld a, $3
+	call CardFlip_FillBox
+
+	hlcoord 18, 1, wAttrMap
+	lb bc, 2, 2
+	ld a, $4
+	call CardFlip_FillBox
+
+	hlcoord 9, 0, wAttrMap
+	lb bc, 12, 1
+	ld a, $1
+	call CardFlip_FillBox
+
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld hl, .palettes
+	ld de, wBGPals1
+	ld bc, 9 palettes
+	call CopyBytes
+	pop af
+	ld [rSVBK], a
+	ret
+; e0c93 (38:4c93)
+
+.palettes ; e0c93
+INCLUDE "gfx/card_flip/card_flip.pal"
+; e0cdb
+
+CardFlipLZ03: ; e0cdb
+INCBIN "gfx/card_flip/card_flip_3.2bpp.lz"
+
+CardFlipOffButtonGFX: ; e0cf6
+INCBIN "gfx/card_flip/off.2bpp"
+
+CardFlipOnButtonGFX: ; e0d06
+INCBIN "gfx/card_flip/on.2bpp"
+
+CardFlipLZ01: ; e0d16
+INCBIN "gfx/card_flip/card_flip_1.2bpp.lz"
+
+CardFlipLZ02: ; e0ea8
+INCBIN "gfx/card_flip/card_flip_2.2bpp.lz"
+
+CardFlipTilemap: ; e110c
+INCBIN "gfx/card_flip/card_flip.tilemap"
+; e1190
--- /dev/null
+++ b/engine/games/dummy_game.asm
@@ -1,0 +1,612 @@
+_DummyGame: ; e1e5b (38:5e5b)
+	call .LoadGFXAndPals
+	call DelayFrame
+.loop
+	call .JumptableLoop
+	jr nc, .loop
+	ret
+
+.LoadGFXAndPals:
+	call DisableLCD
+	ld b, SCGB_DIPLOMA
+	call GetSGBLayout
+	callfar ClearSpriteAnims
+	ld hl, LZ_e2221
+	ld de, vTiles2 tile $00
+	call Decompress
+	ld hl, Unknown_e00ed
+	ld de, vTiles0 tile $00
+	ld bc, 4 tiles
+	ld a, BANK(Unknown_e00ed)
+	call FarCopyBytes
+	ld a, $8
+	ld hl, wc300
+	ld [hli], a
+	ld [hl], $0
+	hlcoord 0, 0
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	xor a
+	call ByteFill
+	xor a
+	ld [hSCY], a
+	ld [hSCX], a
+	ld [rWY], a
+	ld [wJumptableIndex], a
+	ld a, $1
+	ld [hBGMapMode], a
+	ld a, LCDC_DEFAULT
+	ld [rLCDC], a
+	ld a, $e4
+	call DmgToCgbBGPals
+	ld a, $e0
+	call DmgToCgbObjPal0
+	ret
+
+.JumptableLoop:
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .quit
+	call .ExecuteJumptable
+	callfar PlaySpriteAnimations
+	call DelayFrame
+	and a
+	ret
+
+.quit
+	scf
+	ret
+
+.ExecuteJumptable:
+	jumptable .Jumptable, wJumptableIndex
+
+.Jumptable:
+	dw .RestartGame
+	dw .ResetBoard
+	dw .InitBoardTilemapAndCursorObject
+	dw .CheckTriesRemaining
+	dw .PickCard1
+	dw .PickCard2
+	dw .DelayPickAgain
+	dw .RevealAll
+	dw .AskPlayAgain
+
+.RestartGame:
+	call DummyGame_InitStrings
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+.ResetBoard:
+	call ret_e00ed
+	jr nc, .proceed
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+.proceed
+	call DummyGame_InitBoard
+	ld hl, wJumptableIndex
+	inc [hl]
+	xor a
+	ld [wDummyGameCounter], a
+	ld hl, wDummyGameLastMatches
+rept 4
+	ld [hli], a
+endr
+	ld [hl], a
+	ld [wDummyGameNumCardsMatched], a
+.InitBoardTilemapAndCursorObject:
+	ld hl, wDummyGameCounter
+	ld a, [hl]
+	cp 45
+	jr nc, .spawn_object
+	inc [hl]
+	call DummyGame_Card2Coord
+	xor a
+	ld [wDummyGameLastCardPicked], a
+	call DummyGame_PlaceCard
+	ret
+
+.spawn_object
+	depixel 6, 3, 4, 4
+	ld a, SPRITE_ANIM_INDEX_DUMMY_GAME
+	call _InitSpriteAnimStruct
+	ld a, 5
+	ld [wDummyGameNumberTriesRemaining], a
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+.CheckTriesRemaining:
+	ld a, [wDummyGameNumberTriesRemaining]
+	hlcoord 17, 0
+	add "0"
+	ld [hl], a
+	ld hl, wDummyGameNumberTriesRemaining
+	ld a, [hl]
+	and a
+	jr nz, .next_try
+	ld a, $7
+	ld [wJumptableIndex], a
+	ret
+
+.next_try
+	dec [hl]
+	xor a
+	ld [wcf64], a
+	ld hl, wJumptableIndex
+	inc [hl]
+.PickCard1:
+	ld a, [wcf64]
+	and a
+	ret z
+	dec a
+	ld e, a
+	ld d, 0
+	ld hl, wDummyGameCards
+	add hl, de
+	ld a, [hl]
+	cp -1
+	ret z
+	ld [wDummyGameLastCardPicked], a
+	ld [wDummyGameCard1], a
+	ld a, e
+	ld [wDummyGameCard1Location], a
+	call DummyGame_Card2Coord
+	call DummyGame_PlaceCard
+	xor a
+	ld [wcf64], a
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+.PickCard2:
+	ld a, [wcf64]
+	and a
+	ret z
+	dec a
+	ld hl, wDummyGameCard1Location
+	cp [hl]
+	ret z
+	ld e, a
+	ld d, 0
+	ld hl, wDummyGameCards
+	add hl, de
+	ld a, [hl]
+	cp -1
+	ret z
+	ld [wDummyGameLastCardPicked], a
+	ld [wDummyGameCard2], a
+	ld a, e
+	ld [wDummyGameCard2Location], a
+	call DummyGame_Card2Coord
+	call DummyGame_PlaceCard
+	ld a, 64
+	ld [wDummyGameCounter], a
+	ld hl, wJumptableIndex
+	inc [hl]
+.DelayPickAgain:
+	ld hl, wDummyGameCounter
+	ld a, [hl]
+	and a
+	jr z, .PickAgain
+	dec [hl]
+	ret
+
+.PickAgain:
+	call DummyGame_CheckMatch
+	ld a, $3
+	ld [wJumptableIndex], a
+	ret
+
+.RevealAll:
+	ld a, [hJoypadPressed]
+	and A_BUTTON
+	ret z
+	xor a
+	ld [wDummyGameCounter], a
+.RevelationLoop:
+	ld hl, wDummyGameCounter
+	ld a, [hl]
+	cp 45
+	jr nc, .finish_round
+	inc [hl]
+	push af
+	call DummyGame_Card2Coord
+	pop af
+	push hl
+	ld e, a
+	ld d, $0
+	ld hl, wDummyGameCards
+	add hl, de
+	ld a, [hl]
+	pop hl
+	cp -1
+	jr z, .RevelationLoop
+	ld [wDummyGameLastCardPicked], a
+	call DummyGame_PlaceCard
+	jr .RevelationLoop
+
+.finish_round
+	call WaitPressAorB_BlinkCursor
+	ld hl, wJumptableIndex
+	inc [hl]
+.AskPlayAgain:
+	call ret_e00ed
+	jr nc, .restart
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+.restart
+	xor a
+	ld [wJumptableIndex], a
+	ret
+
+; e2010
+
+DummyGame_CheckMatch: ; e2010
+	ld hl, wDummyGameCard1
+	ld a, [hli]
+	cp [hl]
+	jr nz, .no_match
+
+	ld a, [wDummyGameCard1Location]
+	call DummyGame_Card2Coord
+	call DummyGame_DeleteCard
+
+	ld a, [wDummyGameCard2Location]
+	call DummyGame_Card2Coord
+	call DummyGame_DeleteCard
+
+	ld a, [wDummyGameCard1Location]
+	ld e, a
+	ld d, $0
+	ld hl, wDummyGameCards
+	add hl, de
+	ld [hl], -1
+
+	ld a, [wDummyGameCard2Location]
+	ld e, a
+	ld d, 0
+	ld hl, wDummyGameCards
+	add hl, de
+	ld [hl], -1
+
+	ld hl, wDummyGameLastMatches
+.find_empty_slot
+	ld a, [hli]
+	and a
+	jr nz, .find_empty_slot
+	dec hl
+	ld a, [wDummyGameCard1]
+	ld [hl], a
+	ld [wDummyGameLastCardPicked], a
+	ld hl, wDummyGameNumCardsMatched
+	ld e, [hl]
+	inc [hl]
+	inc [hl]
+	ld d, 0
+	hlcoord 5, 0
+	add hl, de
+	call DummyGame_PlaceCard
+	ld hl, .VictoryText
+	call PrintText
+	ret
+
+.no_match
+	xor a
+	ld [wDummyGameLastCardPicked], a
+
+	ld a, [wDummyGameCard1Location]
+	call DummyGame_Card2Coord
+	call DummyGame_PlaceCard
+
+	ld a, [wDummyGameCard2Location]
+	call DummyGame_Card2Coord
+	call DummyGame_PlaceCard
+
+	ld hl, DummyGameText_Darn
+	call PrintText
+	ret
+
+.VictoryText:
+	start_asm
+	push bc
+	hlcoord 2, 13
+	call DummyGame_PlaceCard
+	ld hl, DummyGameText_Yeah
+	pop bc
+	inc bc
+	inc bc
+	inc bc
+	ret
+
+; e2093
+
+DummyGameText_Yeah: ; 0xe2093
+	; , yeah!
+	text_jump UnknownText_0x1c1a5b
+	db "@"
+; 0xe2098
+
+DummyGameText_Darn: ; 0xe2098
+	; Darn…
+	text_jump UnknownText_0x1c1a65
+	db "@"
+; 0xe209d
+
+DummyGame_InitBoard: ; e209d
+	ld hl, wDummyGameCards
+	ld bc, wDummyGameCardsEnd - wDummyGameCards
+	xor a
+	call ByteFill
+	call DummyGame_GetDistributionOfTiles
+
+	ld c, 2
+	ld b, [hl]
+	call DummyGame_SampleTilePlacement
+
+	ld c, 8
+	ld b, [hl]
+	call DummyGame_SampleTilePlacement
+
+	ld c, 4
+	ld b, [hl]
+	call DummyGame_SampleTilePlacement
+
+	ld c, 7
+	ld b, [hl]
+	call DummyGame_SampleTilePlacement
+
+	ld c, 3
+	ld b, [hl]
+	call DummyGame_SampleTilePlacement
+
+	ld c, 6
+	ld b, [hl]
+	call DummyGame_SampleTilePlacement
+
+	ld c, 1
+	ld b, [hl]
+	call DummyGame_SampleTilePlacement
+
+	ld c, 5
+	ld hl, wDummyGameCards
+	ld b, wDummyGameCardsEnd - wDummyGameCards
+.loop
+	ld a, [hl]
+	and a
+	jr nz, .no_load
+	ld [hl], c
+.no_load
+	inc hl
+	dec b
+	jr nz, .loop
+	ret
+
+; e20e5
+
+DummyGame_SampleTilePlacement: ; e20e5
+	push hl
+	ld de, wDummyGameCards
+.loop
+	call Random
+	and %00111111
+	cp 45
+	jr nc, .loop
+	ld l, a
+	ld h, 0
+	add hl, de
+	ld a, [hl]
+	and a
+	jr nz, .loop
+	ld [hl], c
+	dec b
+	jr nz, .loop
+	pop hl
+	inc hl
+	ret
+
+; e2101
+
+DummyGame_GetDistributionOfTiles: ; e2101
+	ld a, [wMenuCursorY]
+	dec a
+	ld l, a
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	add hl, hl
+	ld de, .distributions
+	add hl, de
+	ret
+
+.distributions
+	db $02, $03, $06, $06, $06, $08, $08, $06
+	db $02, $02, $04, $06, $06, $08, $08, $09
+	db $02, $02, $02, $04, $07, $08, $08, $0c
+; e2128
+
+DummyGame_PlaceCard: ; e2128
+	ld a, [wDummyGameLastCardPicked]
+	sla a
+	sla a
+	add 4
+	ld [hli], a
+	inc a
+	ld [hld], a
+	inc a
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hli], a
+	inc a
+	ld [hl], a
+	ld c, 3
+	call DelayFrames
+	ret
+
+; e2142
+
+DummyGame_DeleteCard: ; e2142
+	ld a, $1
+	ld [hli], a
+	ld [hld], a
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld [hli], a
+	ld [hl], a
+	ld c, 3
+	call DelayFrames
+	ret
+
+; e2152
+
+DummyGame_InitStrings: ; e2152
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, $1
+	call ByteFill
+	hlcoord 0, 0
+	ld de, .japstr1
+	call PlaceString
+	hlcoord 15, 0
+	ld de, .japstr2
+	call PlaceString
+	ld hl, .dummy_text
+	call PrintText
+	ret
+
+.dummy_text
+	db "@"
+.japstr1
+	db "とったもの@"
+.japstr2
+	db "あと かい@"
+; e2183
+
+DummyGame_Card2Coord: ; e2183
+	ld d, 0
+.find_row
+	sub 9
+	jr c, .found_row
+	inc d
+	jr .find_row
+
+.found_row
+	add 9
+	ld e, a
+	hlcoord 1, 2
+	ld bc, 2 * SCREEN_WIDTH
+.loop2
+	ld a, d
+	and a
+	jr z, .done
+	add hl, bc
+	dec d
+	jr .loop2
+
+.done
+	sla e
+	add hl, de
+	ret
+
+; e21a1
+
+DummyGame_InterpretJoypad_AnimateCursor: ; e21a1 (38:61a1)
+	ld a, [wJumptableIndex]
+	cp $7
+	jr nc, .quit
+	call JoyTextDelay
+	ld hl, hJoypadPressed ; $ffa3
+	ld a, [hl]
+	and A_BUTTON
+	jr nz, .pressed_a
+	ld a, [hl]
+	and D_LEFT
+	jr nz, .pressed_left
+	ld a, [hl]
+	and D_RIGHT
+	jr nz, .pressed_right
+	ld a, [hl]
+	and D_UP
+	jr nz, .pressed_up
+	ld a, [hl]
+	and D_DOWN
+	jr nz, .pressed_down
+	ret
+
+.quit
+	ld hl, SPRITEANIMSTRUCT_INDEX
+	add hl, bc
+	ld [hl], $0
+	ret
+
+.pressed_a
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	inc a
+	ld [wcf64], a
+	ret
+
+.pressed_left
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld a, [hl]
+	and a
+	ret z
+	sub 1 tiles
+	ld [hl], a
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	dec [hl]
+	ret
+
+.pressed_right
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld a, [hl]
+	cp (9 - 1) tiles
+	ret z
+	add 1 tiles
+	ld [hl], a
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	inc [hl]
+	ret
+
+.pressed_up
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld a, [hl]
+	and a
+	ret z
+	sub 1 tiles
+	ld [hl], a
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	sub 9
+	ld [hl], a
+	ret
+
+.pressed_down
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld a, [hl]
+	cp (5 - 1) tiles
+	ret z
+	add 1 tiles
+	ld [hl], a
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	add 9
+	ld [hl], a
+	ret
+
+; e2221 (38:6221)
+
+LZ_e2221: ; e2221
+INCBIN "gfx/dummy_game/dummy_game.2bpp.lz"
--- /dev/null
+++ b/engine/games/slot_machine.asm
@@ -1,0 +1,2352 @@
+SLOTS_NO_BIAS  EQU -1
+SLOTS_NO_MATCH EQU -1
+
+SLOTS_SEVEN    EQU $00
+SLOTS_POKEBALL EQU $04
+SLOTS_CHERRY   EQU $08
+SLOTS_PIKACHU  EQU $0c
+SLOTS_SQUIRTLE EQU $10
+SLOTS_STARYU   EQU $14
+
+REEL_SIZE EQU 15
+
+; Constants for slot_reel offsets (see macros/wram.asm)
+REEL_ACTION        EQUS "(wReel1ReelAction - wReel1)"
+REEL_TILEMAP_ADDR  EQUS "(wReel1TilemapAddr - wReel1)"
+REEL_POSITION      EQUS "(wReel1Position - wReel1)"
+REEL_SPIN_DISTANCE EQUS "(wReel1SpinDistance - wReel1)"
+REEL_SPIN_RATE     EQUS "(wReel1SpinRate - wReel1)"
+REEL_OAM_ADDR      EQUS "(wReel1OAMAddr - wReel1)"
+REEL_X_COORD       EQUS "(wReel1XCoord - wReel1)"
+REEL_MANIP_COUNTER EQUS "(wReel1ManipCounter - wReel1)"
+REEL_MANIP_DELAY   EQUS "(wReel1ManipDelay - wReel1)"
+REEL_FIELD_0B      EQUS "(wReel1Field0b - wReel1)"
+REEL_STOP_DELAY    EQUS "(wReel1StopDelay - wReel1)"
+
+; SlotsJumptable constants
+	const_def
+	const SLOTS_INIT
+	const SLOTS_BET_AND_START
+	const SLOTS_WAIT_START
+	const SLOTS_WAIT_REEL1
+	const SLOTS_WAIT_STOP_REEL1
+	const SLOTS_WAIT_REEL2
+	const SLOTS_WAIT_STOP_REEL2
+	const SLOTS_WAIT_REEL3
+	const SLOTS_WAIT_STOP_REEL3
+	const SLOTS_NEXT_09
+	const SLOTS_NEXT_0A
+	const SLOTS_NEXT_0B
+	const SLOTS_FLASH_IF_WIN
+	const SLOTS_FLASH_SCREEN
+	const SLOTS_GIVE_EARNED_COINS
+	const SLOTS_PAYOUT_TEXT_AND_ANIM
+	const SLOTS_PAYOUT_ANIM
+	const SLOTS_RESTART_OF_QUIT
+	const SLOTS_QUIT
+SLOTS_END_LOOP_F EQU 7
+
+; ReelActionJumptable constants
+	const_def
+	const REEL_ACTION_DO_NOTHING
+	const REEL_ACTION_STOP_REEL_IGNORE_JOYPAD
+	const REEL_ACTION_QUADRUPLE_RATE
+	const REEL_ACTION_DOUBLE_RATE
+	const REEL_ACTION_NORMAL_RATE
+	const REEL_ACTION_HALF_RATE
+	const REEL_ACTION_QUARTER_RATE
+	const REEL_ACTION_STOP_REEL1
+	const REEL_ACTION_STOP_REEL2
+	const REEL_ACTION_STOP_REEL3
+	const REEL_ACTION_SET_UP_REEL2_SKIP_TO_7
+	const REEL_ACTION_WAIT_REEL2_SKIP_TO_7
+	const REEL_ACTION_FAST_SPIN_REEL2_UNTIL_LINED_UP_7S
+	const REEL_ACTION_UNUSED
+	const REEL_ACTION_CHECK_DROP_REEL
+	const REEL_ACTION_WAIT_DROP_REEL
+	const REEL_ACTION_START_SLOW_ADVANCE_REEL3
+	const REEL_ACTION_WAIT_SLOW_ADVANCE_REEL3
+	const REEL_ACTION_INIT_GOLEM
+	const REEL_ACTION_WAIT_GOLEM
+	const REEL_ACTION_END_GOLEM
+	const REEL_ACTION_INIT_CHANSEY
+	const REEL_ACTION_WAIT_CHANSEY
+	const REEL_ACTION_WAIT_EGG
+	const REEL_ACTION_DROP_REEL
+
+_SlotMachine:
+	ld hl, wOptions
+	set NO_TEXT_SCROLL, [hl]
+	call .InitGFX
+	call DelayFrame
+.loop
+	call SlotsLoop
+	jr nc, .loop
+	call WaitSFX
+	ld de, SFX_QUIT_SLOTS
+	call PlaySFX
+	call WaitSFX
+	call ClearBGPalettes
+	farcall StubbedTrainerRankings_EndSlotsWinStreak
+	ld hl, wOptions
+	res NO_TEXT_SCROLL, [hl]
+	ld hl, rLCDC
+	res rLCDC_SPRITE_SIZE, [hl] ; 8x8
+	ret
+
+.InitGFX: ; 926f7 (24:66f7)
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	ld de, MUSIC_NONE
+	call PlayMusic
+	call DelayFrame
+	call DisableLCD
+	hlbgcoord 0, 0
+	ld bc, vBGMap1 - vBGMap0
+	ld a, " "
+	call ByteFill
+	ld b, SCGB_SLOT_MACHINE
+	call GetSGBLayout
+	callfar ClearSpriteAnims
+	ld hl, wSlots
+	ld bc, wSlotsDataEnd - wSlots
+	xor a
+	call ByteFill
+
+	ld hl, Slots2LZ
+	ld de, vTiles0 tile $00
+	call Decompress
+
+	ld hl, Slots3LZ
+	ld de, vTiles0 tile $40
+	call Decompress
+
+	ld hl, Slots1LZ
+	ld de, vTiles2 tile $00
+	call Decompress
+
+	ld hl, Slots2LZ
+	ld de, vTiles2 tile $25
+	call Decompress
+
+	ld hl, SlotsTilemap
+	decoord 0, 0
+	ld bc, SCREEN_WIDTH * 12
+	call CopyBytes
+
+	ld hl, rLCDC
+	set rLCDC_SPRITE_SIZE, [hl] ; 8x16
+	call EnableLCD
+	ld hl, wSlots
+	ld bc, wSlotsEnd - wSlots
+	xor a
+	call ByteFill
+	call Slots_InitReelTiles
+	call Slots_GetPals
+	ld a, $7
+	ld hl, wSpriteAnimDict
+	ld [hli], a
+	ld [hl], $40
+	xor a ; SLOTS_INIT
+	ld [wJumptableIndex], a
+	ld a, SLOTS_NO_BIAS
+	ld [wSlotBias], a
+	ld de, MUSIC_GAME_CORNER
+	call PlayMusic
+	xor a
+	ld [wKeepSevenBiasChance], a ; 87.5% chance
+	call Random
+	and %00101010
+	ret nz
+	ld a, 1
+	ld [wKeepSevenBiasChance], a ; 12.5% chance
+	ret
+
+Slots_GetPals: ; 9279b (24:679b)
+	ld a, %11100100
+	call DmgToCgbBGPals
+	lb de, %11100100, %11100100
+	ld a, [hCGB]
+	and a
+	jr nz, .cgb
+	lb de, %11000000, %11100100
+.cgb
+	call DmgToCgbObjPals
+	ret
+
+SlotsLoop: ; 927af (24:67af)
+	ld a, [wJumptableIndex]
+	bit SLOTS_END_LOOP_F, a
+	jr nz, .stop
+	call SlotsJumptable
+	call Slots_SpinReels
+	xor a
+	ld [wCurrSpriteOAMAddr], a
+	callfar DoNextFrameForFirst16Sprites
+	call .PrintCoinsAndPayout
+	call .Stubbed_Function927d3
+	call DelayFrame
+	and a
+	ret
+
+.stop
+	scf
+	ret
+
+.Stubbed_Function927d3: ; 927d3 (24:67d3)
+; dummied out
+	ret
+	ld a, [wReel1ReelAction]
+	and a
+	ret nz
+	ld a, [wReel2ReelAction]
+	and a
+	ret nz
+	ld a, [wFirstTwoReelsMatchingSevens]
+	and a
+	jr nz, .matching_sevens
+	ld a, %11100100
+	call DmgToCgbBGPals
+	ret
+
+.matching_sevens
+	ld a, [wTextDelayFrames]
+	and $7
+	ret nz
+	ld a, [rBGP]
+	xor %00001100
+	call DmgToCgbBGPals
+	ret
+
+; 927f8
+
+.PrintCoinsAndPayout: ; 927f8 (24:67f8)
+	hlcoord 5, 1
+	ld de, wCoins
+	lb bc, PRINTNUM_LEADINGZEROS | 2, 4
+	call PrintNum
+	hlcoord 11, 1
+	ld de, wPayout
+	lb bc, PRINTNUM_LEADINGZEROS | 2, 4
+	call PrintNum
+	ret
+
+; 92811 (24:6811)
+
+Unreferenced_Function92811: ; 92811
+; debug function?
+	ld a, [wSlotBias]
+	add 0
+	daa
+	ld e, a
+	and $f
+	add "0"
+	hlcoord 1, 0
+	ld [hl], a
+	ld a, e
+	swap a
+	and $f
+	add "0"
+	hlcoord 0, 0
+	ld [hl], a
+	ret
+
+; 9282c
+
+Unreferenced_Function9282c: ; 9282c
+; animate OAM tiles?
+	ld hl, wcf66
+	ld a, [hl]
+	inc [hl]
+	and $7
+	ret nz
+	ld hl, wVirtualOAMSprite16TileID
+	ld c, NUM_SPRITE_OAM_STRUCTS - 16
+.loop
+	ld a, [hl]
+	xor %00100000
+	ld [hli], a ; tile id
+rept SPRITEOAMSTRUCT_LENGTH + -1
+	inc hl
+endr
+	dec c
+	jr nz, .loop
+	ret
+
+; 92844
+
+SlotsJumptable: ; 92844 (24:6844)
+	jumptable .Jumptable, wJumptableIndex
+
+.Jumptable:
+	dw SlotsAction_Init              ; 00
+	dw SlotsAction_BetAndStart       ; 01
+	dw SlotsAction_WaitStart         ; 02
+	dw SlotsAction_WaitReel1         ; 03
+	dw SlotsAction_WaitStopReel1     ; 04
+	dw SlotsAction_WaitReel2         ; 05
+	dw SlotsAction_WaitStopReel2     ; 06
+	dw SlotsAction_WaitReel3         ; 07
+	dw SlotsAction_WaitStopReel3     ; 08
+	dw SlotsAction_Next              ; 09
+	dw SlotsAction_Next              ; 0a
+	dw SlotsAction_Next              ; 0b
+	dw SlotsAction_FlashIfWin        ; 0c
+	dw SlotsAction_FlashScreen       ; 0d
+	dw SlotsAction_GiveEarnedCoins   ; 0e
+	dw SlotsAction_PayoutTextAndAnim ; 0f
+	dw SlotsAction_PayoutAnim        ; 10
+	dw SlotsAction_RestartOrQuit     ; 11
+	dw SlotsAction_Quit              ; 12
+
+SlotsAction_Next: ; 92879 (24:6879)
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+SlotsAction_Init: ; 9287e (24:687e)
+	call SlotsAction_Next
+	xor a
+	ld [wFirstTwoReelsMatching], a
+	ld [wFirstTwoReelsMatchingSevens], a
+	ld a, SLOTS_NO_MATCH
+	ld [wSlotMatched], a
+	ret
+
+SlotsAction_BetAndStart: ; 9288e (24:688e)
+	call Slots_AskBet
+	jr nc, .proceed
+	ld a, SLOTS_QUIT
+	ld [wJumptableIndex], a
+	ret
+
+.proceed
+	call SlotsAction_Next
+	call Slots_IlluminateBetLights
+	call Slots_InitBias
+	ld a, 32
+	ld [wSlotsDelay], a
+	ld a, REEL_ACTION_NORMAL_RATE
+	ld [wReel1ReelAction], a
+	ld [wReel2ReelAction], a
+	ld [wReel3ReelAction], a
+	ld a, 4
+	ld [wReel1ManipCounter], a
+	ld [wReel2ManipCounter], a
+	ld [wReel3ManipCounter], a
+	call WaitSFX
+	ld a, SFX_SLOT_MACHINE_START
+	call Slots_PlaySFX
+	ret
+
+SlotsAction_WaitStart: ; 928c6 (24:68c6)
+	ld hl, wSlotsDelay
+	ld a, [hl]
+	and a
+	jr z, .proceed
+	dec [hl]
+	ret
+
+.proceed
+	call SlotsAction_Next
+	xor a
+	ld [hJoypadSum], a
+	ret
+
+SlotsAction_WaitReel1: ; 928d6 (24:68d6)
+	ld hl, hJoypadSum
+	ld a, [hl]
+	and A_BUTTON
+	ret z
+	call SlotsAction_Next
+	call Slots_StopReel1
+	ld [wReel1ReelAction], a
+SlotsAction_WaitStopReel1: ; 928e6 (24:68e6)
+	ld a, [wReel1ReelAction]
+	cp REEL_ACTION_DO_NOTHING
+	ret nz
+	ld a, SFX_STOP_SLOT
+	call Slots_PlaySFX
+	ld bc, wReel1
+	ld de, wReel1Stopped
+	call Slots_LoadReelState
+	call SlotsAction_Next
+	xor a
+	ld [hJoypadSum], a
+SlotsAction_WaitReel2: ; 92900 (24:6900)
+	ld hl, hJoypadSum
+	ld a, [hl]
+	and A_BUTTON
+	ret z
+	call SlotsAction_Next
+	call Slots_StopReel2
+	ld [wReel2ReelAction], a
+SlotsAction_WaitStopReel2: ; 92910 (24:6910)
+	ld a, [wReel2ReelAction]
+	cp REEL_ACTION_DO_NOTHING
+	ret nz
+	ld a, SFX_STOP_SLOT
+	call Slots_PlaySFX
+	ld bc, wReel2
+	ld de, wReel2Stopped
+	call Slots_LoadReelState
+	call SlotsAction_Next
+	xor a
+	ld [hJoypadSum], a
+SlotsAction_WaitReel3: ; 9292a (24:692a)
+	ld hl, hJoypadSum
+	ld a, [hl]
+	and A_BUTTON
+	ret z
+	call SlotsAction_Next
+	call Slots_StopReel3
+	ld [wReel3ReelAction], a
+SlotsAction_WaitStopReel3: ; 9293a (24:693a)
+	ld a, [wReel3ReelAction]
+	cp REEL_ACTION_DO_NOTHING
+	ret nz
+	ld a, SFX_STOP_SLOT
+	call Slots_PlaySFX
+	ld bc, wReel3
+	ld de, wReel3Stopped
+	call Slots_LoadReelState
+	call SlotsAction_Next
+	xor a
+	ld [hJoypadSum], a
+	ret
+
+SlotsAction_FlashIfWin: ; 92955 (24:6955)
+	ld a, [wSlotMatched]
+	cp SLOTS_NO_MATCH
+	jr nz, .GotIt
+	call SlotsAction_Next
+	call SlotsAction_Next
+	ret
+
+.GotIt:
+	call SlotsAction_Next
+	ld a, 16
+	ld [wSlotsDelay], a
+SlotsAction_FlashScreen: ; 9296b (24:696b)
+	ld hl, wSlotsDelay
+	ld a, [hl]
+	and a
+	jr z, .done
+	dec [hl]
+	srl a
+	ret z
+
+	ld a, [rOBP0]
+	xor $ff
+	ld e, a
+	ld d, a
+	call DmgToCgbObjPals
+	ret
+
+.done
+	call Slots_GetPals
+	call SlotsAction_Next
+	ret
+
+SlotsAction_GiveEarnedCoins: ; 92987 (24:6987)
+	xor a
+	ld [wFirstTwoReelsMatching], a
+	ld [wFirstTwoReelsMatchingSevens], a
+	ld a, %11100100
+	call DmgToCgbBGPals
+	call Slots_GetPayout
+	xor a
+	ld [wSlotsDelay], a
+	call SlotsAction_Next
+	ret
+
+SlotsAction_PayoutTextAndAnim: ; 9299e (24:699e)
+	call Slots_PayoutText
+	call SlotsAction_Next
+SlotsAction_PayoutAnim: ; 929a4 (24:69a4)
+	ld hl, wSlotsDelay
+	ld a, [hl]
+	inc [hl]
+	and $1
+	ret z
+	ld hl, wPayout
+	ld a, [hli]
+	ld d, a
+	or [hl]
+	jr z, .done
+	ld e, [hl]
+	dec de
+	ld [hl], e
+	dec hl
+	ld [hl], d
+	ld hl, wCoins
+	ld d, [hl]
+	inc hl
+	ld e, [hl]
+	call Slots_CheckCoinCaseFull
+	jr c, .okay
+	inc de
+.okay
+	ld [hl], e
+	dec hl
+	ld [hl], d
+	ld a, [wSlotsDelay]
+	and $7
+	ret z ; ret nz would be more appropriate
+	ld de, SFX_GET_COIN_FROM_SLOTS
+	call PlaySFX
+	ret
+
+.done
+	call SlotsAction_Next
+	ret
+
+SlotsAction_RestartOrQuit: ; 929d9 (24:69d9)
+	call Slots_DeilluminateBetLights
+	call WaitPressAorB_BlinkCursor
+	call Slots_AskPlayAgain
+	jr c, .exit_slots
+	ld a, SLOTS_INIT
+	ld [wJumptableIndex], a
+	ret
+
+.exit_slots
+	ld a, SLOTS_QUIT
+	ld [wJumptableIndex], a
+	ret
+
+SlotsAction_Quit: ; 929f0 (24:69f0)
+	ld hl, wJumptableIndex
+	set SLOTS_END_LOOP_F, [hl]
+	ret
+
+Slots_LoadReelState: ; 929f6 (24:69f6)
+	push de
+	call Slots_GetCurrentReelState
+	pop de
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hli]
+	ld [de], a
+	ret
+
+Slots_CheckCoinCaseFull: ; 92a04 (24:6a04)
+	ld a, d
+	cp HIGH(MAX_COINS)
+	jr c, .not_full
+	ld a, e
+	cp LOW(MAX_COINS)
+	jr c, .not_full
+	scf
+	ret
+
+.not_full
+	and a
+	ret
+
+Slots_GetCurrentReelState: ; 92a12 (24:6a12)
+	ld hl, REEL_POSITION
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr nz, .okay
+	ld a, $f
+.okay
+	dec a
+	and $f
+	ld e, a
+	ld d, $0
+	ld hl, REEL_TILEMAP_ADDR
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	add hl, de
+	ret
+
+Slots_StopReel1: ; 92a2b (24:6a2b)
+; Always set the REEL_ACTION_STOP_REEL1 action.
+	ld a, REEL_ACTION_STOP_REEL1
+	ret
+
+Slots_StopReel2: ; 92a2e (24:6a2e)
+; As long as, the following three meet, there's a 31.25% chance
+; to set action REEL_ACTION_SET_UP_REEL2_SKIP_TO_7:
+; - Bet is >= 2 coins
+; - There's a 7 symbol visible in reel #1
+; - Current spin isn't biased or is biased towards SEVEN
+; In any other case, REEL_ACTION_STOP_REEL2 is set.
+
+	ld a, [wSlotBet]
+	cp $2
+	jr c, .dont_jump
+	ld a, [wSlotBias]
+	and a
+	jr z, .skip
+	cp SLOTS_NO_BIAS
+	jr nz, .dont_jump
+.skip
+	call .CheckReel1ForASeven
+	jr nz, .dont_jump
+	call Random
+	cp $50 ; 32%
+	jr nc, .dont_jump
+	ld a, REEL_ACTION_SET_UP_REEL2_SKIP_TO_7
+	ret
+
+.dont_jump
+	ld a, REEL_ACTION_STOP_REEL2
+	ret
+
+.CheckReel1ForASeven: ; 92a51 (24:6a51)
+	ld a, [wReel1Stopped]
+	and a
+	ret z
+	ld a, [wReel1Stopped + 1]
+	and a
+	ret z
+	ld a, [wReel1Stopped + 2]
+	and a
+	ret
+
+Slots_StopReel3: ; 92a60 (24:6a60)
+; If no matching SEVEN symbols in reels #1 and #2:
+; - REEL_ACTION_STOP_REEL3, 100%
+
+; If matching SEVEN symbols and NO bias to SEVEN:
+; - REEL_ACTION_STOP_REEL3, 37.5%
+; - REEL_ACTION_START_SLOW_ADVANCE_REEL3, 31.3%
+; - REEL_ACTION_INIT_GOLEM, 31.3%
+; - REEL_ACTION_INIT_CHANSEY, 0%
+
+; If matching SEVEN symbols and bias to SEVEN:
+; - REEL_ACTION_STOP_REEL3, 29.7%
+; - REEL_ACTION_START_SLOW_ADVANCE_REEL3, 23.4%
+; - REEL_ACTION_INIT_GOLEM, 23.4%
+; - REEL_ACTION_INIT_CHANSEY, 23.4%
+
+	ld a, [wFirstTwoReelsMatching]
+	and a
+	jr z, .stop
+	ld a, [wFirstTwoReelsMatchingSevens]
+	and a
+	jr z, .stop
+	ld a, [wSlotBias]
+	and a
+	jr nz, .biased
+	call Random
+	cp 180
+	jr nc, .stop
+	cp 120
+	jr nc, .slow_advance
+	cp 60
+	jr nc, .golem
+	ld a, REEL_ACTION_INIT_CHANSEY
+	ret
+
+.biased
+	call Random
+	cp 160
+	jr nc, .stop
+	cp 80
+	jr nc, .slow_advance
+.golem
+	ld a, REEL_ACTION_INIT_GOLEM
+	ret
+
+.slow_advance
+	ld a, REEL_ACTION_START_SLOW_ADVANCE_REEL3
+	ret
+
+.stop
+	ld a, REEL_ACTION_STOP_REEL3
+	ret
+
+Slots_InitReelTiles: ; 92a98 (24:6a98)
+	ld bc, wReel1
+	ld hl, REEL_OAM_ADDR
+	add hl, bc
+	ld de, wVirtualOAMSprite16
+	ld [hl], e
+	inc hl
+	ld [hl], d
+	ld hl, REEL_TILEMAP_ADDR
+	add hl, bc
+	ld de, Reel1Tilemap
+	ld [hl], e
+	inc hl
+	ld [hl], d
+	ld hl, REEL_X_COORD
+	add hl, bc
+	ld [hl], 6 * 8
+	call .OAM
+
+	ld bc, wReel2
+	ld hl, REEL_OAM_ADDR
+	add hl, bc
+	ld de, wVirtualOAMSprite24
+	ld [hl], e
+	inc hl
+	ld [hl], d
+	ld hl, REEL_TILEMAP_ADDR
+	add hl, bc
+	ld de, Reel2Tilemap
+	ld [hl], e
+	inc hl
+	ld [hl], d
+	ld hl, REEL_X_COORD
+	add hl, bc
+	ld [hl], 10 * 8
+	call .OAM
+
+	ld bc, wReel3
+	ld hl, REEL_OAM_ADDR
+	add hl, bc
+	ld de, wVirtualOAMSprite32
+	ld [hl], e
+	inc hl
+	ld [hl], d
+	ld hl, REEL_TILEMAP_ADDR
+	add hl, bc
+	ld de, Reel3Tilemap
+	ld [hl], e
+	inc hl
+	ld [hl], d
+	ld hl, REEL_X_COORD
+	add hl, bc
+	ld [hl], 14 * 8
+	call .OAM
+	ret
+
+.OAM: ; 92af9 (24:6af9)
+	ld hl, REEL_ACTION
+	add hl, bc
+	ld [hl], REEL_ACTION_DO_NOTHING
+	ld hl, REEL_POSITION
+	add hl, bc
+	ld [hl], REEL_SIZE - 1
+	ld hl, REEL_SPIN_DISTANCE
+	add hl, bc
+	ld [hl], REEL_ACTION_DO_NOTHING
+	call Slots_UpdateReelPositionAndOAM
+	ret
+
+Slots_SpinReels: ; 92b0f (24:6b0f)
+	ld bc, wReel1
+	call .SpinReel
+	ld bc, wReel2
+	call .SpinReel
+	ld bc, wReel3
+	call .SpinReel
+	ret
+
+.SpinReel: ; 92b22 (24:6b22)
+	ld hl, REEL_SPIN_DISTANCE
+	add hl, bc
+	ld a, [hl]
+	and $f
+	jr nz, .skip
+	call ReelActionJumptable
+.skip
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld a, [hl]
+	and a
+	ret z
+	ld d, a
+	ld hl, REEL_SPIN_DISTANCE
+	add hl, bc
+	add [hl]
+	ld [hl], a
+	and $f
+	jr z, Slots_UpdateReelPositionAndOAM
+	ld hl, REEL_OAM_ADDR
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld e, $8
+.loop
+	ld a, [hl]
+	add d
+	ld [hli], a
+	inc hl
+	inc hl
+	inc hl
+	dec e
+	jr nz, .loop
+	ret
+
+Slots_UpdateReelPositionAndOAM: ; 92b53 (24:6b53)
+	ld hl, REEL_X_COORD
+	add hl, bc
+	ld a, [hl]
+	ld [wCurrReelXCoord], a
+	ld a, 10 * 8
+	ld [wCurrReelYCoord], a
+	ld hl, REEL_POSITION
+	add hl, bc
+	ld e, [hl]
+	ld d, 0
+	ld hl, REEL_TILEMAP_ADDR
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	add hl, de
+	ld e, l
+	ld d, h
+	call .LoadOAM
+	ld hl, REEL_POSITION
+	add hl, bc
+	ld a, [hl]
+	inc a
+	and $f
+	cp REEL_SIZE
+	jr nz, .load
+	xor a
+.load
+	ld [hl], a
+	ret
+
+.LoadOAM: ; 92b83 (24:6b83)
+	ld hl, REEL_OAM_ADDR
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+.loop
+	ld a, [wCurrReelYCoord]
+	ld [hli], a ; y
+	ld a, [wCurrReelXCoord]
+	ld [hli], a ; x
+	ld a, [de]
+	ld [hli], a ; tile id
+	srl a
+	srl a
+	set OAM_PRIORITY, a
+	ld [hli], a ; attributes
+
+	ld a, [wCurrReelYCoord]
+	ld [hli], a ; y
+	ld a, [wCurrReelXCoord]
+	add 1 * TILE_WIDTH
+	ld [hli], a ; x
+	ld a, [de]
+	inc a
+	inc a
+	ld [hli], a ; tile id
+	srl a
+	srl a
+	set OAM_PRIORITY, a
+	ld [hli], a ; attributes
+	inc de
+	ld a, [wCurrReelYCoord]
+	sub 2 * TILE_WIDTH
+	ld [wCurrReelYCoord], a
+	cp 2 * TILE_WIDTH
+	jr nz, .loop
+	ret
+
+; 92bbe (24:6bbe)
+
+Unreferenced_Function92bbe: ; 92bbe
+	push hl
+	srl a
+	srl a
+	add LOW(.Unknown_92bce)
+	ld l, a
+	ld a, 0
+	adc HIGH(.Unknown_92bce)
+	ld h, a
+	ld a, [hl]
+	pop hl
+	ret
+
+; 92bce
+
+.Unknown_92bce: ; 92bce
+	db 0, 1, 2, 3, 4, 5
+; 92bd4
+
+ReelActionJumptable: ; 92bd4 (24:6bd4)
+	ld hl, REEL_ACTION
+	add hl, bc
+	ld e, [hl]
+	ld d, 0
+	ld hl, .Jumptable
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+; 92be4 (24:6be4)
+
+.Jumptable: ; 92be4
+	dw ReelAction_DoNothing                   ; 00
+	dw ReelAction_StopReelIgnoreJoypad        ; 01
+	dw ReelAction_QuadrupleRate               ; 02
+	dw ReelAction_DoubleRate                  ; 03
+	dw ReelAction_NormalRate                  ; 04
+	dw ReelAction_HalfRate                    ; 05
+	dw ReelAction_QuarterRate                 ; 06
+	dw ReelAction_StopReel1                   ; 07
+	dw ReelAction_StopReel2                   ; 08
+	dw ReelAction_StopReel3                   ; 09
+	dw ReelAction_SetUpReel2SkipTo7           ; 0a
+	dw ReelAction_WaitReel2SkipTo7            ; 0b
+	dw ReelAction_FastSpinReel2UntilLinedUp7s ; 0c
+	dw ReelAction_Unused                      ; 0d
+	dw ReelAction_CheckDropReel               ; 0e
+	dw ReelAction_WaitDropReel                ; 0f
+	dw ReelAction_StartSlowAdvanceReel3       ; 10
+	dw ReelAction_WaitSlowAdvanceReel3        ; 11
+	dw ReelAction_InitGolem                   ; 12
+	dw ReelAction_WaitGolem                   ; 13
+	dw ReelAction_EndGolem                    ; 14
+	dw ReelAction_InitChansey                 ; 15
+	dw ReelAction_WaitChansey                 ; 16
+	dw ReelAction_WaitEgg                     ; 17
+	dw ReelAction_DropReel                    ; 18
+; 92c16
+
+ReelAction_DoNothing: ; 92c16
+	ret
+
+; 92c17
+
+ReelAction_QuadrupleRate: ; 92c17
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 16
+	ret
+
+; 92c1e
+
+ReelAction_DoubleRate: ; 92c1e
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 8
+	ret
+
+; 92c25
+
+ReelAction_NormalRate: ; 92c25
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 4
+	ret
+
+; 92c2c
+
+ReelAction_HalfRate: ; 92c2c
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 2
+	ret
+
+; 92c33
+
+ReelAction_QuarterRate: ; 92c33
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 1
+	ret
+
+; 92c3a
+
+Slots_StopReel: ; 92c3a
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 0
+	ld hl, REEL_ACTION
+	add hl, bc
+	ld [hl], REEL_ACTION_STOP_REEL_IGNORE_JOYPAD
+	ld hl, REEL_STOP_DELAY
+	add hl, bc
+	ld [hl], 3
+ReelAction_StopReelIgnoreJoypad: ; 92c4c
+	ld hl, REEL_STOP_DELAY
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .EndReel
+	dec [hl]
+	ret
+
+.EndReel:
+	ld hl, REEL_ACTION
+	add hl, bc
+	ld a, REEL_ACTION_DO_NOTHING
+	ld [hl], a
+	ret
+
+; 92c5e
+
+ReelAction_StopReel1: ; 92c5e
+; If no bias: don't manipulate reel.
+; If bias: manipulate reel up to wReel1ManipCounter (i.e. 4) slots,
+; stoping early if the biased symbol shows up anywhere in reel #1,
+; even if the current bet won't allow lining it up.
+
+	ld a, [wSlotBias]
+	cp SLOTS_NO_BIAS
+	jr z, .NoBias
+	ld hl, REEL_MANIP_COUNTER
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .NoBias
+	dec [hl]
+	call .CheckForBias
+	ret nz
+.NoBias:
+	call Slots_StopReel
+	ret
+
+; 92c76
+
+.CheckForBias: ; 92c76
+	call Slots_GetCurrentReelState
+	ld a, [wSlotBias]
+	ld e, a
+	ld a, [hli]
+	cp e
+	ret z
+	ld a, [hli]
+	cp e
+	ret z
+	ld a, [hl]
+	cp e
+	ret
+
+; 92c86
+
+ReelAction_StopReel2: ; 92c86
+; If no bias: don't manipulate reel.
+; If bias: manipulate reel up to wReel2ManipCounter (i.e. 4) slots,
+; stoping early if the biased symbol is lined up in the first two
+; reels, according to the lines that the current bet allows.
+
+	call Slots_CheckMatchedFirstTwoReels
+	jr nc, .nope
+	ld a, [wSlotBuildingMatch]
+	ld hl, wSlotBias
+	cp [hl]
+	jr z, .NoBias
+.nope
+	ld a, [wSlotBias]
+	cp SLOTS_NO_BIAS
+	jr z, .NoBias
+	ld hl, REEL_MANIP_COUNTER
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .NoBias
+	dec [hl]
+	ret
+
+.NoBias:
+	call Slots_StopReel
+	ret
+
+; 92ca9
+
+ReelAction_StopReel3: ; 92ca9
+; Manipulate the reel up to wReel3ManipCounter (i.e. 4) slots,
+; stopping early if the bias symbol is lined up for a win.
+; If not biased to any symbols, stop as soon as nothing is lined up.
+
+	call Slots_CheckMatchedAllThreeReels
+	jr nc, .NoMatch
+	ld hl, wSlotBias
+	cp [hl]
+	jr z, .NoBias
+	ld hl, REEL_MANIP_COUNTER
+	add hl, bc
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+	ret
+
+.NoMatch:
+	ld a, [wSlotBias]
+	cp SLOTS_NO_BIAS
+	jr z, .NoBias
+	ld hl, REEL_MANIP_COUNTER
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .NoBias
+	dec [hl]
+	ret
+
+.NoBias:
+	call Slots_StopReel
+	ret
+
+; 92cd2
+
+ReelAction_SetUpReel2SkipTo7: ; 92cd2
+; Unique reel 2 action (see Slots_StopReel2)
+; Ensures that 7 symbols become lined up in the first two reels,
+; but more often than not, this is only a way to get our hopes up, as
+; it makes exciting reel #3 modes with no success hope more common.
+
+	call Slots_CheckMatchedFirstTwoReels
+	jr nc, .no_match
+	ld a, [wFirstTwoReelsMatchingSevens]
+	and a
+	jr z, .no_match
+	call Slots_StopReel
+	ret
+
+.no_match
+	ld a, SFX_STOP_SLOT
+	call Slots_PlaySFX
+	ld hl, REEL_ACTION
+	add hl, bc
+	inc [hl] ; REEL_ACTION_WAIT_REEL2_SKIP_TO_7
+	ld hl, REEL_MANIP_DELAY
+	add hl, bc
+	ld [hl], 32
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 0
+	ret
+
+; 92cf8
+
+ReelAction_WaitReel2SkipTo7: ; 92cf8
+	ld hl, REEL_MANIP_DELAY
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .asm_92d02
+	dec [hl]
+	ret
+
+.asm_92d02
+	ld a, SFX_THROW_BALL
+	call Slots_PlaySFX
+	ld hl, REEL_ACTION
+	add hl, bc
+	inc [hl] ; REEL_ACTION_FAST_SPIN_REEL2_UNTIL_LINED_UP_7S
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 8
+	ret
+
+; 92d13
+
+ReelAction_FastSpinReel2UntilLinedUp7s: ; 92d13
+	call Slots_CheckMatchedFirstTwoReels
+	ret nc
+	ld a, [wFirstTwoReelsMatchingSevens]
+	and a
+	ret z
+	call Slots_StopReel
+	ret
+
+; 92d20
+
+ReelAction_InitGolem: ; 92d20
+; Ensures SEVENs are lined up if there's bias to SEVEN.
+; Ensures nothing is lined up if there's no bias symbols.
+; No other bias symbols are compatible with this mode.
+
+; This is achieved by throwing Golem until the desired result
+; is produced. The amount of Golem thrown can be anywhere from
+;  1 to 14 for SEVEN bias, and 4-8 for no bias.
+
+	call Slots_CheckMatchedAllThreeReels
+	ret c
+	ld a, SFX_STOP_SLOT
+	call Slots_PlaySFX
+	call Slots_WaitSFX
+	ld hl, REEL_ACTION
+	add hl, bc
+	inc [hl] ; REEL_ACTION_WAIT_GOLEM
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 0
+	call Slots_GetNumberOfGolems
+	push bc
+	push af
+	depixel 12, 13
+	ld a, SPRITE_ANIM_INDEX_SLOTS_GOLEM
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_0E
+	add hl, bc
+	pop af
+	ld [hl], a
+	pop bc
+	xor a
+	ld [wSlotsDelay], a
+ReelAction_WaitGolem: ; 92d4f
+	ld a, [wSlotsDelay]
+	cp 2
+	jr z, .two
+	cp 1
+	jr z, .one
+	ret
+
+.two
+	call Slots_CheckMatchedAllThreeReels
+	call Slots_StopReel
+	ret
+
+.one
+	ld hl, REEL_ACTION
+	add hl, bc
+	inc [hl] ; REEL_ACTION_END_GOLEM
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 8
+	ret
+
+; 92d6e
+
+ReelAction_EndGolem: ; 92d6e
+	xor a
+	ld [wSlotsDelay], a
+	ld hl, REEL_ACTION
+	add hl, bc
+	dec [hl] ; REEL_ACTION_WAIT_GOLEM
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 0
+	ret
+
+; 92d7e
+
+ReelAction_InitChansey: ; 92d7e
+; Ensures the lining up of SEVEN symbols, but this mode is only possible
+; when there is bias to SEVEN symbols (and even then, it's still rare).
+; Chansey releases and egg and reel #3 is made to advance 17 slots very
+; quickly as many times as necessary for the match to SEVENs to show up.
+
+	call Slots_CheckMatchedAllThreeReels
+	ret c
+	ld a, SFX_STOP_SLOT
+	call Slots_PlaySFX
+	call Slots_WaitSFX
+	ld hl, REEL_ACTION
+	add hl, bc
+	inc [hl] ; REEL_ACTION_WAIT_CHANSEY
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 0
+	push bc
+	depixel 12, 0
+	ld a, SPRITE_ANIM_INDEX_SLOTS_CHANSEY
+	call _InitSpriteAnimStruct
+	pop bc
+	xor a
+	ld [wSlotsDelay], a
+	ret
+
+; 92da4
+
+ReelAction_WaitChansey: ; 92da4
+	ld a, [wSlotsDelay]
+	and a
+	ret z
+	ld hl, REEL_ACTION
+	add hl, bc
+	inc [hl] ; REEL_ACTION_WAIT_EGG
+	ld a, 2
+	ld [wSlotsDelay], a
+ReelAction_WaitEgg: ; 92db3
+	ld a, [wSlotsDelay]
+	cp $4
+	ret c
+	ld hl, REEL_ACTION
+	add hl, bc
+	inc [hl] ; REEL_ACTION_DROP_REEL
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 16
+	ld hl, REEL_MANIP_DELAY
+	add hl, bc
+	ld [hl], 17
+ReelAction_DropReel: ; 92dca
+	ld hl, REEL_MANIP_DELAY
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .check_match
+	dec [hl]
+	ret
+
+.check_match
+	call Slots_CheckMatchedAllThreeReels
+	jr nc, .EggAgain
+	and a
+	jr nz, .EggAgain
+	ld a, 5
+	ld [wSlotsDelay], a
+	call Slots_StopReel
+	ret
+
+.EggAgain:
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 0
+	ld hl, REEL_ACTION
+	add hl, bc
+	dec [hl]
+	dec [hl] ; REEL_ACTION_WAIT_CHANSEY
+	ld a, 1
+	ld [wSlotsDelay], a
+	ret
+
+; 92df7
+
+ReelAction_Unused: ; 92df7
+	call Slots_CheckMatchedAllThreeReels
+	ret c
+	ld a, SFX_STOP_SLOT
+	call Slots_PlaySFX
+	call Slots_WaitSFX
+	ld hl, REEL_ACTION
+	add hl, bc
+	inc [hl] ; REEL_ACTION_CHECK_DROP_REEL
+	call Slots_GetNumberOfGolems
+	ld hl, REEL_MANIP_DELAY
+	add hl, bc
+	ld [hl], a
+ReelAction_CheckDropReel: ; 92e10
+	ld hl, REEL_MANIP_DELAY
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr nz, .spin
+	call Slots_CheckMatchedAllThreeReels
+	call Slots_StopReel
+	ret
+
+.spin
+	dec [hl]
+	ld hl, REEL_ACTION
+	add hl, bc
+	inc [hl] ; REEL_ACTION_WAIT_DROP_REEL
+	ld hl, REEL_FIELD_0B
+	add hl, bc
+	ld [hl], 32
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 0
+ReelAction_WaitDropReel: ; 92e31
+	ld hl, REEL_FIELD_0B
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .DropReel
+	dec [hl]
+	ret
+
+.DropReel:
+	ld hl, REEL_ACTION
+	add hl, bc
+	dec [hl]
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 8
+	ret
+
+; 92e47
+
+ReelAction_StartSlowAdvanceReel3: ; 92e47
+; Ensures SEVENs are lined up if there's bias to SEVEN.
+; Ensures nothing is lined up if there's no bias symbols.
+; No other bias symbols are compatible with this mode.
+
+; This is achieved by slowly advancing the reel a full round,
+; plus any necessary slot until the desired result is produced.
+
+	call Slots_CheckMatchedAllThreeReels
+	ret c
+	ld a, SFX_STOP_SLOT
+	call Slots_PlaySFX
+	call Slots_WaitSFX
+	ld hl, REEL_SPIN_RATE
+	add hl, bc
+	ld [hl], 1
+	ld hl, REEL_ACTION
+	add hl, bc
+	inc [hl] ; REEL_ACTION_WAIT_SLOW_ADVANCE_REEL3
+	ld hl, REEL_MANIP_DELAY
+	add hl, bc
+	ld [hl], 16
+ReelAction_WaitSlowAdvanceReel3: ; 92e64
+	ld hl, REEL_MANIP_DELAY
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .check1
+	dec [hl]
+.play_sfx
+	ld a, SFX_GOT_SAFARI_BALLS
+	call Slots_PlaySFX
+	ret
+
+.check1
+	ld a, [wSlotBias]
+	and a
+	jr nz, .check2
+	call Slots_CheckMatchedAllThreeReels
+	jr nc, .play_sfx
+	and a
+	jr nz, .play_sfx
+	call Slots_StopReel
+	call WaitSFX
+	ret
+
+.check2
+	call Slots_CheckMatchedAllThreeReels
+	jr c, .play_sfx
+	call Slots_StopReel
+	call WaitSFX
+	ret
+
+; 92e94
+
+Slots_CheckMatchedFirstTwoReels: ; 92e94
+	xor a
+	ld [wFirstTwoReelsMatching], a
+	ld [wFirstTwoReelsMatchingSevens], a
+	call Slots_GetCurrentReelState
+	call Slots_CopyReelState
+	ld a, [wSlotBet]
+	and 3
+	ld e, a
+	ld d, 0
+	ld hl, .Jumptable
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, .return
+	push de
+	jp hl
+
+.return
+	ld a, [wFirstTwoReelsMatching]
+	and a
+	ret z
+	scf
+	ret
+
+; 92ebd
+
+.Jumptable: ; 92ebd
+	dw .zero
+	dw .one
+	dw .two
+	dw .three
+; 92ec5
+
+.three ; 92ec5
+	call .CheckUpwardsDiag
+	call .CheckDownwardsDiag
+
+.two ; 92ecb
+	call .CheckBottomRow
+	call .CheckTopRow
+
+.one ; 92ed1
+	call .CheckMiddleRow
+
+.zero ; 92ed4
+	ret
+
+; 92ed5
+
+.CheckBottomRow: ; 92ed5
+	ld hl, wCurrReelStopped
+	ld a, [wReel1Stopped]
+	cp [hl]
+	call z, .StoreResult
+	ret
+
+; 92ee0
+
+.CheckUpwardsDiag: ; 92ee0
+	ld hl, wCurrReelStopped + 1
+	ld a, [wReel1Stopped]
+	cp [hl]
+	call z, .StoreResult
+	ret
+
+; 92eeb
+
+.CheckMiddleRow: ; 92eeb
+	ld hl, wCurrReelStopped + 1
+	ld a, [wReel1Stopped + 1]
+	cp [hl]
+	call z, .StoreResult
+	ret
+
+; 92ef6
+
+.CheckDownwardsDiag: ; 92ef6
+	ld hl, wCurrReelStopped + 1
+	ld a, [wReel1Stopped + 2]
+	cp [hl]
+	call z, .StoreResult
+	ret
+
+; 92f01
+
+.CheckTopRow: ; 92f01
+	ld hl, wCurrReelStopped + 2
+	ld a, [wReel1Stopped + 2]
+	cp [hl]
+	call z, .StoreResult
+	ret
+
+; 92f0c
+
+.StoreResult: ; 92f0c
+	ld [wSlotBuildingMatch], a
+	and a
+	jr nz, .matching_sevens
+	ld a, 1
+	ld [wFirstTwoReelsMatchingSevens], a
+
+.matching_sevens
+	ld a, 1
+	ld [wFirstTwoReelsMatching], a
+	ret
+
+; 92f1d
+
+Slots_CheckMatchedAllThreeReels: ; 92f1d
+	ld a, SLOTS_NO_MATCH
+	ld [wSlotMatched], a
+	call Slots_GetCurrentReelState
+	call Slots_CopyReelState
+	ld a, [wSlotBet]
+	and 3
+	ld e, a
+	ld d, 0
+	ld hl, .Jumptable
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, .return
+	push de
+	jp hl
+
+.return
+	ld a, [wSlotMatched]
+	cp SLOTS_NO_MATCH
+	jr nz, .matched_nontrivial
+	and a
+	ret
+
+.matched_nontrivial
+	scf
+	ret
+
+; 92f48
+
+.Jumptable: ; 92f48
+	dw .zero
+	dw .one
+	dw .two
+	dw .three
+; 92f50
+
+.three ; 92f50
+	call .CheckUpwardsDiag
+	call .CheckDownwardsDiag
+
+.two ; 92f56
+	call .CheckBottomRow
+	call .CheckTopRow
+
+.one ; 92f5c
+	call .CheckMiddleRow
+
+.zero ; 92f5f
+	ret
+
+; 92f60
+
+.CheckBottomRow: ; 92f60
+	ld hl, wCurrReelStopped
+	ld a, [wReel1Stopped]
+	cp [hl]
+	ret nz
+	ld hl, wReel2Stopped
+	cp [hl]
+	call z, .StoreResult
+	ret
+
+; 92f70
+
+.CheckUpwardsDiag: ; 92f70
+	ld hl, wCurrReelStopped + 2
+	ld a, [wReel1Stopped]
+	cp [hl]
+	ret nz
+	ld hl, wReel2Stopped + 1
+	cp [hl]
+	call z, .StoreResult
+	ret
+
+; 92f80
+
+.CheckMiddleRow: ; 92f80
+	ld hl, wCurrReelStopped + 1
+	ld a, [wReel1Stopped + 1]
+	cp [hl]
+	ret nz
+	ld hl, wReel2Stopped + 1
+	cp [hl]
+	call z, .StoreResult
+	ret
+
+; 92f90
+
+.CheckDownwardsDiag: ; 92f90
+	ld hl, wCurrReelStopped
+	ld a, [wReel1Stopped + 2]
+	cp [hl]
+	ret nz
+	ld hl, wReel2Stopped + 1
+	cp [hl]
+	call z, .StoreResult
+	ret
+
+; 92fa0
+
+.CheckTopRow: ; 92fa0
+	ld hl, wCurrReelStopped + 2
+	ld a, [wReel1Stopped + 2]
+	cp [hl]
+	ret nz
+	ld hl, wReel2Stopped + 2
+	cp [hl]
+	call z, .StoreResult
+	ret
+
+; 92fb0
+
+.StoreResult: ; 92fb0
+	ld [wSlotMatched], a
+	ret
+
+; 92fb4
+
+Slots_CopyReelState: ; 92fb4
+	ld de, wCurrReelStopped
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+	ret
+
+; 92fc0
+
+Slots_GetNumberOfGolems: ; 92fc0
+	ld hl, REEL_POSITION
+	add hl, bc
+	ld a, [hl]
+	push af
+	push hl
+	call .Check7Bias
+	pop hl
+	pop af
+	ld [hl], a
+	ld a, e
+	ret
+
+; 92fcf
+
+.Check7Bias: ; 92fcf
+	ld a, [wSlotBias]
+	and a
+	jr nz, .not_biased_to_seven
+	ld e, $0
+.loop1
+	ld hl, REEL_POSITION
+	add hl, bc
+	inc [hl]
+	inc e
+	push de
+	call Slots_CheckMatchedAllThreeReels
+	pop de
+	jr nc, .loop1
+	and a
+	jr nz, .loop1
+	ret
+
+.not_biased_to_seven
+	call Random
+	and $7
+	cp $4 ; ((50 percent) & 7) + 1
+	jr c, .not_biased_to_seven
+	ld e, a
+.loop2
+	ld a, e
+	inc e
+	ld hl, REEL_POSITION
+	add hl, bc
+	add [hl]
+	ld [hl], a
+	push de
+	call Slots_CheckMatchedAllThreeReels
+	pop de
+	jr c, .loop2
+	ret
+
+; 93002
+
+Slots_InitBias: ; 93002 (24:7002)
+	ld a, [wSlotBias]
+	and a
+	ret z
+	ld hl, .Normal
+	ld a, [wScriptVar]
+	and a
+	jr z, .okay
+	ld hl, .Lucky
+.okay
+	call Random
+	ld c, a
+.loop
+	ld a, [hli]
+	cp c
+	jr nc, .done
+	inc hl
+	jr .loop
+
+.done
+	ld a, [hl]
+	ld [wSlotBias], a
+	ret
+
+; 93023 (24:7023)
+
+.Normal: ; 93023
+	db $01, SLOTS_SEVEN    ; 1/256
+	db $03, SLOTS_POKEBALL ; 1/128
+	db $0a, SLOTS_STARYU   ; 7/256
+	db $14, SLOTS_SQUIRTLE ; 5/128
+	db $28, SLOTS_PIKACHU  ; 5/64
+	db $30, SLOTS_CHERRY   ; 1/32
+	db $ff, SLOTS_NO_BIAS   ; everything else
+; 93031
+
+.Lucky: ; 93031
+	db $02, SLOTS_SEVEN    ;  1/128
+	db $03, SLOTS_POKEBALL ;  1/256
+	db $08, SLOTS_STARYU   ;  5/256
+	db $10, SLOTS_SQUIRTLE ;  1/32
+	db $1e, SLOTS_PIKACHU  ;  7/128
+	db $50, SLOTS_CHERRY   ; 25/128
+	db $ff, SLOTS_NO_BIAS   ; everything else
+; 9303f
+
+Slots_IlluminateBetLights: ; 9303f (24:703f)
+	ld b, $14 ; turned on
+	ld a, [wSlotBet]
+	dec a
+	jr z, Slots_Lights1OnOff
+	dec a
+	jr z, Slots_Lights2OnOff
+	jr Slots_Lights3OnOff
+
+Slots_DeilluminateBetLights: ; 9304c (24:704c)
+	ld b, $23 ; turned off
+Slots_Lights3OnOff: ; 9304e (24:704e)
+	hlcoord 3, 2
+	call Slots_TurnLightsOnOrOff
+	hlcoord 3, 10
+	call Slots_TurnLightsOnOrOff
+Slots_Lights2OnOff: ; 9305a (24:705a)
+	hlcoord 3, 4
+	call Slots_TurnLightsOnOrOff
+	hlcoord 3, 8
+	call Slots_TurnLightsOnOrOff
+Slots_Lights1OnOff: ; 93066 (24:7066)
+	hlcoord 3, 6
+
+Slots_TurnLightsOnOrOff: ; 93069 (24:7069)
+	ld a, b
+	ld [hl], a
+	ld de, SCREEN_WIDTH / 2 + 3
+	add hl, de
+	ld [hl], a
+	ld de, SCREEN_WIDTH / 2 - 3
+	add hl, de
+	inc a
+	ld [hl], a
+	ld de, SCREEN_WIDTH / 2 + 3
+	add hl, de
+	ld [hl], a
+	ret
+
+Slots_AskBet: ; 9307c (24:707c)
+.loop
+	ld hl, .Text_BetHowManyCoins
+	call PrintText
+	ld hl, .MenuHeader
+	call LoadMenuHeader
+	call VerticalMenu
+	call CloseWindow
+	ret c
+	ld a, [wMenuCursorY]
+	ld b, a
+	ld a, 4
+	sub b
+	ld [wSlotBet], a
+	ld hl, wCoins
+	ld c, a
+	ld a, [hli]
+	and a
+	jr nz, .Start
+	ld a, [hl]
+	cp c
+	jr nc, .Start
+	ld hl, .Text_NotEnoughCoins
+	call PrintText
+	jr .loop
+
+.Start:
+	ld hl, wCoins + 1
+	ld a, [hl]
+	sub c
+	ld [hld], a
+	jr nc, .ok
+	dec [hl]
+.ok
+	call WaitSFX
+	ld de, SFX_PAY_DAY
+	call PlaySFX
+	ld hl, .Text_Start
+	call PrintText
+	and a
+	ret
+
+; 930c7 (24:70c7)
+
+.Text_BetHowManyCoins: ; 0x930c7
+	; Bet how many coins?
+	text_jump UnknownText_0x1c5049
+	db "@"
+; 0x930cc
+
+.Text_Start: ; 0x930cc
+	; Start!
+	text_jump UnknownText_0x1c505e
+	db "@"
+; 0x930d1
+
+.Text_NotEnoughCoins: ; 0x930d1
+	; Not enough coins.
+	text_jump UnknownText_0x1c5066
+	db "@"
+; 0x930d6
+
+.MenuHeader: ; 0x930d6
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 14, 10, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+	dw .MenuData
+	db 1 ; default option
+; 0x930de
+
+.MenuData: ; 0x930de
+	db STATICMENU_CURSOR ; flags
+	db 3 ; items
+	db " 3@"
+	db " 2@"
+	db " 1@"
+; 0x930e9
+
+Slots_AskPlayAgain: ; 930e9 (24:70e9)
+	ld hl, wCoins
+	ld a, [hli]
+	or [hl]
+	jr nz, .you_have_coins
+	ld hl, .Text_OutOfCoins
+	call PrintText
+	ld c, 60
+	call DelayFrames
+	jr .exit_slots
+
+.you_have_coins
+	ld hl, .Text_PlayAgain
+	call PrintText
+	call LoadMenuTextBox
+	lb bc, 14, 12
+	call PlaceYesNoBox
+	ld a, [wMenuCursorY]
+	dec a
+	call CloseWindow
+	and a
+	jr nz, .exit_slots
+	and a
+	ret
+
+.exit_slots
+	scf
+	ret
+
+; 9311a (24:711a)
+
+.Text_OutOfCoins: ; 9311a
+	text_jump UnknownText_0x1c5079
+	db "@"
+
+.Text_PlayAgain: ; 9311f
+	text_jump UnknownText_0x1c5092
+	db "@"
+
+Slots_GetPayout: ; 93124 (24:7124)
+	ld a, [wSlotMatched]
+	cp SLOTS_NO_MATCH
+	jr z, .no_win
+	srl a
+	ld e, a
+	ld d, 0
+	ld hl, .PayoutTable
+	add hl, de
+	ld a, [hli]
+	ld [wPayout + 1], a
+	ld e, a
+	ld a, [hl]
+	ld [wPayout], a
+	ld d, a
+	farcall StubbedTrainerRankings_AddToSlotsPayouts
+	ret
+
+.PayoutTable:
+	dw 300
+	dw  50
+	dw   6
+	dw   8
+	dw  10
+	dw  15
+
+.no_win
+	ld hl, wPayout
+	xor a
+	ld [hli], a
+	ld [hl], a
+	ret
+
+Slots_PayoutText: ; 93158 (24:7158)
+	ld a, [wSlotMatched]
+	cp SLOTS_NO_MATCH
+	jr nz, .MatchedSomething
+	ld hl, .Text_Darn
+	call PrintText
+	farcall StubbedTrainerRankings_EndSlotsWinStreak
+	ret
+
+.MatchedSomething:
+	srl a
+	ld e, a
+	ld d, 0
+	ld hl, .PayoutStrings
+	add hl, de
+	add hl, de
+	add hl, de
+	ld de, wStringBuffer2
+	ld bc, 4
+	call CopyBytes
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, .return
+	push de
+	jp hl
+
+.return
+	ld hl, .Text_PrintPayout
+	call PrintText
+	farcall StubbedTrainerRankings_AddToSlotsWinStreak
+	ret
+
+; 93195 (24:7195)
+
+.PayoutStrings: ; 93195
+	dbw "300@", .LinedUpSevens
+	dbw "50@@", .LinedUpPokeballs
+	dbw "6@@@", .LinedUpMonOrCherry
+	dbw "8@@@", .LinedUpMonOrCherry
+	dbw "10@@", .LinedUpMonOrCherry
+	dbw "15@@", .LinedUpMonOrCherry
+; 931b9
+
+.Text_PrintPayout: ; 0x931b9
+	start_asm
+	ld a, [wSlotMatched]
+	add $25
+	ldcoord_a 2, 13
+	inc a
+	ldcoord_a 2, 14
+	inc a
+	ldcoord_a 3, 13
+	inc a
+	ldcoord_a 3, 14
+	hlcoord 18, 17
+	ld [hl], "▼"
+	ld hl, .Text_LinedUpWonCoins
+rept 4
+	inc bc
+endr
+	ret
+
+; 931db
+
+.Text_LinedUpWonCoins: ; 0x931db
+	; lined up! Won @  coins!
+	text_jump UnknownText_0x1c509f
+	db "@"
+; 0x931e0
+
+.Text_Darn: ; 0x931e0
+	; Darn!
+	text_jump UnknownText_0x1c50bb
+	db "@"
+; 0x931e5
+
+.LinedUpSevens: ; 931e5
+	ld a, SFX_2ND_PLACE
+	call Slots_PlaySFX
+	call WaitSFX
+
+; Oddly, the rarest mode (wKeepSevenBiasChance = 1) is the one with
+; the worse odds to favor seven symbol streaks (12.5% vs 25%).
+; it's possible that either the wKeepSevenBiasChance initialization
+; or this code was intended to lead to flipped percentages.
+	ld a, [wKeepSevenBiasChance]
+	and a
+	jr nz, .lower_seven_streak_odds
+	call Random
+	and %0010100
+	ret z ; 25% chance to stick with seven symbol bias
+	ld a, SLOTS_NO_BIAS
+	ld [wSlotBias], a
+	ret
+
+.lower_seven_streak_odds
+	call Random
+	and %0011100
+	ret z ; 12.5% chance to stick with seven symbol bias
+	ld a, SLOTS_NO_BIAS
+	ld [wSlotBias], a
+	ret
+
+; 9320b
+
+.LinedUpPokeballs: ; 9320b
+	ld a, SFX_3RD_PLACE
+	call Slots_PlaySFX
+	call WaitSFX
+	ret
+
+; 93214
+
+.LinedUpMonOrCherry: ; 93214
+	ld a, SFX_PRESENT
+	call Slots_PlaySFX
+	call WaitSFX
+	ret
+
+; 9321d
+
+Slots_AnimateGolem: ; 9321d (24:721d)
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld e, [hl]
+	ld d, 0
+	ld hl, .Jumptable
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+.Jumptable: ; 9322d (24:722d)
+	dw .init
+	dw .fall
+	dw .roll
+
+.init ; 93233 (24:7233)
+	ld hl, SPRITEANIMSTRUCT_0E
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr nz, .retain
+	ld a, 2
+	ld [wSlotsDelay], a
+	ld hl, SPRITEANIMSTRUCT_INDEX
+	add hl, bc
+	ld [hl], $0
+	ret
+
+.retain
+	dec [hl]
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	inc [hl]
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $30
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld [hl], $0
+
+.fall ; 93259 (24:7259)
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	cp $20
+	jr c, .play_sound
+	dec [hl]
+	ld e, a
+	ld d, 14 * 8
+	farcall BattleAnim_Sine_e
+	ld a, e
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.play_sound
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	inc [hl]
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld [hl], $2
+	ld a, 1
+	ld [wSlotsDelay], a
+	ld a, SFX_PLACE_PUZZLE_PIECE_DOWN
+	call Slots_PlaySFX
+	ret
+
+.roll ; 93289 (24:7289)
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld a, [hl]
+	inc [hl]
+	inc [hl]
+	cp 9 * 8
+	jr nc, .restart
+	and $3
+	ret nz
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld a, [hl]
+	xor $ff
+	inc a
+	ld [hl], a
+	ld [hSCY], a
+	ret
+
+.restart
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	xor a
+	ld [hl], a
+	ld [hSCY], a
+	ret
+
+Slots_AnimateChansey: ; 932ac (24:72ac)
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld e, [hl]
+	ld d, 0
+	ld hl, .Jumptable
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+.Jumptable: ; 932bc (24:72bc)
+	dw .walk
+	dw .one
+	dw .two
+
+.walk ; 932c2 (24:72c2)
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld a, [hl]
+	inc [hl]
+	cp 13 * 8
+	jr z, .limit
+	and $f
+	ret nz
+	ld de, SFX_JUMP_OVER_LEDGE
+	call PlaySFX
+	ret
+
+.limit
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	inc [hl]
+	ld a, 1
+	ld [wSlotsDelay], a
+
+.one ; 932e0 (24:72e0)
+	ld a, [wSlotsDelay]
+	cp $2
+	jr z, .retain
+	cp $5
+	ret nz
+	ld hl, SPRITEANIMSTRUCT_INDEX
+	add hl, bc
+	ld [hl], $0
+	ret
+
+.retain
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	inc [hl]
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $8
+.two ; 932fc (24:72fc)
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .spawn_egg
+	dec [hl]
+	ret
+
+.spawn_egg
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	dec [hl]
+	push bc
+	depixel 12, 13, 0, 4
+	ld a, SPRITE_ANIM_INDEX_SLOTS_EGG
+	call _InitSpriteAnimStruct
+	pop bc
+	ret
+
+; 93316 (24:7316)
+
+Slots_WaitSFX: ; 93316
+	push bc
+	ld c, 16
+	call DelayFrames
+	pop bc
+	ret
+
+; 9331e
+
+Slots_PlaySFX: ; 9331e (24:731e)
+	push de
+	ld e, a
+	ld d, 0
+	call PlaySFX
+	pop de
+	ret
+
+; 93327 (24:7327)
+
+; The first three positions are repeated to
+; avoid needing to check indices when copying.
+Reel1Tilemap: ; 93327
+	db SLOTS_SEVEN    ;  0
+	db SLOTS_CHERRY   ;  1
+	db SLOTS_STARYU   ;  2
+	db SLOTS_PIKACHU  ;  3
+	db SLOTS_SQUIRTLE ;  4
+	db SLOTS_SEVEN    ;  5
+	db SLOTS_CHERRY   ;  6
+	db SLOTS_STARYU   ;  7
+	db SLOTS_PIKACHU  ;  8
+	db SLOTS_SQUIRTLE ;  9
+	db SLOTS_POKEBALL ; 10
+	db SLOTS_CHERRY   ; 11
+	db SLOTS_STARYU   ; 12
+	db SLOTS_PIKACHU  ; 13
+	db SLOTS_SQUIRTLE ; 14
+	db SLOTS_SEVEN    ;  0
+	db SLOTS_CHERRY   ;  1
+	db SLOTS_STARYU   ;  2
+
+Reel2Tilemap: ; 93339
+	db SLOTS_SEVEN    ;  0
+	db SLOTS_PIKACHU  ;  1
+	db SLOTS_CHERRY   ;  2
+	db SLOTS_SQUIRTLE ;  3
+	db SLOTS_STARYU   ;  4
+	db SLOTS_POKEBALL ;  5
+	db SLOTS_PIKACHU  ;  6
+	db SLOTS_CHERRY   ;  7
+	db SLOTS_SQUIRTLE ;  8
+	db SLOTS_STARYU   ;  9
+	db SLOTS_POKEBALL ; 10
+	db SLOTS_PIKACHU  ; 11
+	db SLOTS_CHERRY   ; 12
+	db SLOTS_SQUIRTLE ; 13
+	db SLOTS_STARYU   ; 14
+	db SLOTS_SEVEN    ;  0
+	db SLOTS_PIKACHU  ;  1
+	db SLOTS_CHERRY   ;  2
+
+Reel3Tilemap: ; 9334b
+	db SLOTS_SEVEN    ;  0
+	db SLOTS_PIKACHU  ;  1
+	db SLOTS_CHERRY   ;  2
+	db SLOTS_SQUIRTLE ;  3
+	db SLOTS_STARYU   ;  4
+	db SLOTS_PIKACHU  ;  5
+	db SLOTS_CHERRY   ;  6
+	db SLOTS_SQUIRTLE ;  7
+	db SLOTS_STARYU   ;  8
+	db SLOTS_PIKACHU  ;  9
+	db SLOTS_POKEBALL ; 10
+	db SLOTS_CHERRY   ; 11
+	db SLOTS_SQUIRTLE ; 12
+	db SLOTS_STARYU   ; 13
+	db SLOTS_PIKACHU  ; 14
+	db SLOTS_SEVEN    ;  0
+	db SLOTS_PIKACHU  ;  1
+	db SLOTS_CHERRY   ;  2
+; 9335d
+
+SlotsTilemap: ; 9335d
+INCBIN "gfx/slots/slots.tilemap"
+; 9344d
+
+Slots1LZ: ; 9344d
+INCBIN "gfx/slots/slots_1.2bpp.lz"
+; 935cd
+
+Slots2LZ: ; 935cd
+INCBIN "gfx/slots/slots_2.2bpp.lz"
+; 9382d
+
+Slots3LZ: ; 9382d
+INCBIN "gfx/slots/slots_3.2bpp.lz"
+; 93a3d
--- /dev/null
+++ b/engine/games/unown_puzzle.asm
@@ -1,0 +1,877 @@
+PUZZLE_BORDER EQU $ee
+PUZZLE_VOID   EQU $ef
+
+puzcoord EQUS "* 6 +"
+
+_UnownPuzzle: ; e1190
+	ld a, [hInMenu]
+	push af
+	ld a, $1
+	ld [hInMenu], a
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	xor a
+	ld [hBGMapMode], a
+	call DisableLCD
+	ld hl, wMisc ; includes wPuzzlePieces
+	ld bc, wMiscEnd - wMisc
+	xor a
+	call ByteFill
+	ld hl, UnownPuzzleCursorGFX
+	ld de, vTiles1 tile $60
+	ld bc, 4 tiles
+	call CopyBytes
+	ld hl, UnownPuzzleStartCancelLZ
+	ld de, vTiles1 tile $6d
+	call Decompress
+	call LoadUnownPuzzlePiecesGFX
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, PUZZLE_BORDER
+	call ByteFill
+	hlcoord 4, 3
+	lb bc, 12, 12
+	ld a, PUZZLE_VOID
+	call UnownPuzzle_FillBox
+	call InitUnownPuzzlePiecePositions
+	call UnownPuzzle_UpdateTilemap
+	call PlaceStartCancelBox
+	xor a
+	ld [hSCY], a
+	ld [hSCX], a
+	ld [rWY], a
+	ld [wJumptableIndex], a
+	ld [wHoldingUnownPuzzlePiece], a
+	ld [wUnownPuzzleCursorPosition], a
+	ld [wUnownPuzzleHeldPiece], a
+	ld a, %10010011
+	ld [rLCDC], a
+	call WaitBGMap
+	ld b, SCGB_UNOWN_PUZZLE
+	call GetSGBLayout
+	ld a, $e4
+	call DmgToCgbBGPals
+	ld a, $24
+	call DmgToCgbObjPal0
+	xor a
+	ld [wSolvedUnownPuzzle], a
+	call DelayFrame
+.loop
+	call JoyTextDelay
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .quit
+	call UnownPuzzleJumptable
+	ld a, [wHoldingUnownPuzzlePiece]
+	and a
+	jr nz, .holding_piece
+	ld a, [hVBlankCounter]
+	and $10
+	jr z, .clear
+.holding_piece
+	call RedrawUnownPuzzlePieces
+	jr .next
+
+.clear
+	call ClearSprites
+.next
+	call DelayFrame
+	jr .loop
+
+.quit
+	pop af
+	ld [hInMenu], a
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	ld a, LCDC_DEFAULT
+	ld [rLCDC], a
+	ret
+; e124e
+
+InitUnownPuzzlePiecePositions: ; e124e
+	ld c,  1
+	ld b, 16
+.load_loop
+	call Random
+	and $f
+	ld hl, .PuzzlePieceInitialPositions
+	ld e, a
+	ld d, $0
+	add hl, de
+	ld e, [hl]
+	ld hl, wPuzzlePieces
+	add hl, de
+	ld a, [hl]
+	and a
+	jr nz, .load_loop
+	ld [hl], c
+	inc c
+	dec b
+	jr nz, .load_loop
+	ret
+; e126d
+
+.PuzzlePieceInitialPositions: ; e126d
+initpuzcoord: MACRO
+rept _NARG / 2
+	db \1 puzcoord \2
+	shift
+	shift
+endr
+ENDM
+	initpuzcoord 0,0, 0,1, 0,2, 0,3, 0,4, 0,5
+	initpuzcoord 1,0,                     1,5
+	initpuzcoord 2,0,                     2,5
+	initpuzcoord 3,0,                     3,5
+	initpuzcoord 4,0,                     4,5
+	initpuzcoord 5,0,                     5,5
+	                   ; START > CANCEL
+; e127d
+
+PlaceStartCancelBox: ; e127d
+	call PlaceStartCancelBoxBorder
+	hlcoord 5, 16
+	ld a, $f6
+	ld c, 10
+.loop
+	ld [hli], a
+	inc a
+	dec c
+	jr nz, .loop
+	ret
+; e128d
+
+PlaceStartCancelBoxBorder: ; e128d
+	hlcoord 4, 15
+	ld a, $f0
+	ld [hli], a
+	ld bc, 10
+	ld a, $f1
+	call ByteFill
+	hlcoord 15, 15
+	ld a, $f2
+	ld [hli], a
+	hlcoord 4, 16
+	ld a, $f3
+	ld [hli], a
+	ld bc, 10
+	ld a, PUZZLE_VOID
+	call ByteFill
+	hlcoord 15, 16
+	ld a, $f3
+	ld [hli], a
+	hlcoord 4, 17
+	ld a, $f4
+	ld [hli], a
+	ld bc, 10
+	ld a, $f1
+	call ByteFill
+	hlcoord 15, 17
+	ld a, $f5
+	ld [hl], a
+	ret
+; e12ca
+
+UnownPuzzleJumptable: ; e12ca
+	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
+; e12d9
+
+.Jumptable: ; e12d9
+	dw .Function
+; e12db
+
+.Function: ; e12db
+	ld a, [hJoyPressed]
+	and START
+	jp nz, UnownPuzzle_Quit
+	ld a, [hJoyPressed]
+	and A_BUTTON
+	jp nz, UnownPuzzle_A
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_UP
+	jr nz, .d_up
+	ld a, [hl]
+	and D_DOWN
+	jr nz, .d_down
+	ld a, [hl]
+	and D_LEFT
+	jr nz, .d_left
+	ld a, [hl]
+	and D_RIGHT
+	jr nz, .d_right
+	ret
+
+.d_up
+	ld hl, wUnownPuzzleCursorPosition
+	ld a, [hl]
+	cp 1 puzcoord 0
+	ret c
+	sub 6
+	ld [hl], a
+	jr .done_joypad
+
+.d_down
+	ld hl, wUnownPuzzleCursorPosition
+	ld a, [hl]
+	cp 4 puzcoord 1
+	ret z
+	cp 4 puzcoord 2
+	ret z
+	cp 4 puzcoord 3
+	ret z
+	cp 4 puzcoord 4
+	ret z
+	cp 5 puzcoord 0
+	ret nc
+	add 6
+	ld [hl], a
+	jr .done_joypad
+
+.d_left
+	ld hl, wUnownPuzzleCursorPosition
+	ld a, [hl]
+	and a
+	ret z
+	cp 1 puzcoord 0
+	ret z
+	cp 2 puzcoord 0
+	ret z
+	cp 3 puzcoord 0
+	ret z
+	cp 4 puzcoord 0
+	ret z
+	cp 5 puzcoord 0
+	ret z
+	cp 5 puzcoord 5
+	jr z, .left_overflow
+	dec [hl]
+	jr .done_joypad
+
+.left_overflow
+	ld [hl], 5 puzcoord 0
+	jr .done_joypad
+
+.d_right
+	ld hl, wUnownPuzzleCursorPosition
+	ld a, [hl]
+	cp 0 puzcoord 5
+	ret z
+	cp 1 puzcoord 5
+	ret z
+	cp 2 puzcoord 5
+	ret z
+	cp 3 puzcoord 5
+	ret z
+	cp 4 puzcoord 5
+	ret z
+	cp 5 puzcoord 5
+	ret z
+	cp 5 puzcoord 0
+	jr z, .right_overflow
+	inc [hl]
+	jr .done_joypad
+
+.right_overflow
+	ld [hl], 5 puzcoord 5
+
+.done_joypad
+	ld a, [wHoldingUnownPuzzlePiece]
+	and a
+	jr nz, .holding_piece
+	ld de, SFX_POUND
+	jr .play_sfx
+
+.holding_piece
+	ld de, SFX_MOVE_PUZZLE_PIECE
+
+.play_sfx
+	call PlaySFX
+	ret
+; e1376
+
+UnownPuzzle_A: ; e1376
+	ld a, [wHoldingUnownPuzzlePiece]
+	and a
+	jr nz, .TryPlacePiece
+	call UnownPuzzle_CheckCurrentTileOccupancy
+	and a
+	jr z, UnownPuzzle_InvalidAction
+	ld de, SFX_MEGA_KICK
+	call PlaySFX
+	ld [hl], 0
+	ld [wUnownPuzzleHeldPiece], a
+	call RedrawUnownPuzzlePieces
+	call FillUnoccupiedPuzzleSpace
+	call WaitBGMap
+	call WaitSFX
+	ld a, TRUE
+	ld [wHoldingUnownPuzzlePiece], a
+	ret
+
+.TryPlacePiece:
+	call UnownPuzzle_CheckCurrentTileOccupancy
+	and a
+	jr nz, UnownPuzzle_InvalidAction
+	ld de, SFX_PLACE_PUZZLE_PIECE_DOWN
+	call PlaySFX
+	ld a, [wUnownPuzzleHeldPiece]
+	ld [hl], a
+	call PlaceUnownPuzzlePieceGFX
+	call WaitBGMap
+	xor a
+	ld [wUnownPuzzleHeldPiece], a
+	call RedrawUnownPuzzlePieces
+	xor a
+	ld [wHoldingUnownPuzzlePiece], a
+	call WaitSFX
+	call CheckSolvedUnownPuzzle
+	ret nc
+
+; You solved the puzzle!
+	call PlaceStartCancelBoxBorder
+	call ClearSprites
+	ld de, SFX_1ST_PLACE
+	call PlaySFX
+	call WaitSFX
+	call SimpleWaitPressAorB
+	ld a, TRUE
+	ld [wSolvedUnownPuzzle], a
+UnownPuzzle_Quit: ; e13de
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+UnownPuzzle_InvalidAction: ; e13e4
+	ld de, SFX_WRONG
+	call PlaySFX
+	call WaitSFX
+	ret
+; e13ee
+
+UnownPuzzle_FillBox: ; e13ee
+	ld de, SCREEN_WIDTH
+.row
+	push bc
+	push hl
+.col
+	ld [hli], a
+	dec c
+	jr nz, .col
+	pop hl
+	add hl, de
+	pop bc
+	dec b
+	jr nz, .row
+	ret
+; e13fe
+
+UnownPuzzle_UpdateTilemap: ; e13fe
+	xor a
+	ld [wUnownPuzzleCursorPosition], a
+	ld c, 6 * 6
+.loop
+	push bc
+	call UnownPuzzle_CheckCurrentTileOccupancy
+	ld [wUnownPuzzleHeldPiece], a
+	and a
+	jr z, .not_holding_piece
+	call PlaceUnownPuzzlePieceGFX
+	jr .next
+
+.not_holding_piece
+	call FillUnoccupiedPuzzleSpace
+
+.next
+	ld hl, wUnownPuzzleCursorPosition
+	inc [hl]
+	pop bc
+	dec c
+	jr nz, .loop
+	ret
+; e141f
+
+PlaceUnownPuzzlePieceGFX: ; e141f
+	ld a, $2 ; tilemap coords
+	call GetUnownPuzzleCoordData
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	push hl
+	call GetCurrentPuzzlePieceVTileCorner
+	pop hl
+	ld de, SCREEN_WIDTH
+	ld b, 3
+.row
+	ld c, 3
+	push hl
+.col
+	ld [hli], a
+	inc a
+	dec c
+	jr nz, .col
+	add 9
+	pop hl
+	add hl, de
+	dec b
+	jr nz, .row
+	ret
+; e1441
+
+FillUnoccupiedPuzzleSpace: ; e1441
+	ld a, 2 ; tilemap coords
+	call GetUnownPuzzleCoordData
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	push hl
+	ld a, 4 ; tile
+	call GetUnownPuzzleCoordData
+	ld a, [hl]
+	pop hl
+	ld de, SCREEN_WIDTH
+	ld b, 3
+.row
+	ld c, 3
+	push hl
+.col
+	ld [hli], a
+	dec c
+	jr nz, .col
+	pop hl
+	add hl, de
+	dec b
+	jr nz, .row
+	ret
+; e1463
+
+GetUnownPuzzleCoordData: ; e1463
+	ld e, a
+	ld d, 0
+	ld hl, UnownPuzzleCoordData
+	add hl, de
+	ld a, [wUnownPuzzleCursorPosition]
+	ld e, a
+rept 6
+	add hl, de
+endr
+	ret
+; e1475
+
+UnownPuzzle_CheckCurrentTileOccupancy: ; e1475
+	ld hl, wPuzzlePieces
+	ld a, [wUnownPuzzleCursorPosition]
+	ld e, a
+	ld d, $0
+	add hl, de
+	ld a, [hl]
+	ret
+; e1481
+
+GetCurrentPuzzlePieceVTileCorner: ; e1481
+	ld a, [wUnownPuzzleHeldPiece]
+	ld hl, .Corners
+	add l
+	ld l, a
+	ld a, $0
+	adc h
+	ld h, a
+	ld a, [hl]
+	ret
+; e148f
+
+.Corners: ; e148f
+; 00, 01, 02
+; 0c, 0d, 0e
+; 18, 19, 1a
+	db $e0 ; no piece selected
+	db $00, $03, $06, $09
+	db $24, $27, $2a, $2d
+	db $48, $4b, $4e, $51
+	db $6c, $6f, $72, $75
+; e14a0
+
+CheckSolvedUnownPuzzle: ; e14a0
+	ld hl, .SolvedPuzzleConfiguration
+	ld de, wPuzzlePieces
+	ld c, 6 * 6
+.loop
+	ld a, [de]
+	cp [hl]
+	jr nz, .not_solved
+	inc de
+	inc hl
+	dec c
+	jr nz, .loop
+	scf
+	ret
+
+.not_solved
+	and a
+	ret
+; e14b5
+
+.SolvedPuzzleConfiguration: ; e14b5
+	db $00, $00, $00, $00, $00, $00
+	db $00, $01, $02, $03, $04, $00
+	db $00, $05, $06, $07, $08, $00
+	db $00, $09, $0a, $0b, $0c, $00
+	db $00, $0d, $0e, $0f, $10, $00
+	db $00, $00, $00, $00, $00, $00
+; e14d9
+
+RedrawUnownPuzzlePieces: ; e14d9
+	call GetCurrentPuzzlePieceVTileCorner
+	ld [wd002], a
+	xor a
+	call GetUnownPuzzleCoordData ; get pixel positions
+	ld a, [hli]
+	ld b, [hl]
+	ld c, a
+	ld a, [wd002]
+	cp $e0
+	jr z, .NoPiece
+	ld hl, .OAM_HoldingPiece
+	jr .load
+
+.NoPiece:
+	ld hl, .OAM_NotHoldingPiece
+
+.load
+	ld de, wVirtualOAMSprite00
+.loop
+	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, [wd002]
+	add [hl]
+	ld [de], a ; tile id
+	inc hl
+	inc de
+	ld a, [hli]
+	ld [de], a ; attributes
+	inc de
+	jr .loop
+; e150f
+
+.OAM_HoldingPiece: ; e150f
+	dsprite -1, -4, -1, -4, $00, 0
+	dsprite -1, -4,  0, -4, $01, 0
+	dsprite -1, -4,  0,  4, $02, 0
+	dsprite  0, -4, -1, -4, $0c, 0
+	dsprite  0, -4,  0, -4, $0d, 0
+	dsprite  0, -4,  0,  4, $0e, 0
+	dsprite  0,  4, -1, -4, $18, 0
+	dsprite  0,  4,  0, -4, $19, 0
+	dsprite  0,  4,  0,  4, $1a, 0
+	db -1
+
+.OAM_NotHoldingPiece: ; e1534
+	dsprite -1, -4, -1, -4, $00, 0
+	dsprite -1, -4,  0, -4, $01, 0
+	dsprite -1, -4,  0,  4, $00, 0 | X_FLIP
+	dsprite  0, -4, -1, -4, $02, 0
+	dsprite  0, -4,  0, -4, $03, 0
+	dsprite  0, -4,  0,  4, $02, 0 | X_FLIP
+	dsprite  0,  4, -1, -4, $00, 0 | Y_FLIP
+	dsprite  0,  4,  0, -4, $01, 0 | Y_FLIP
+	dsprite  0,  4,  0,  4, $00, 0 | X_FLIP | Y_FLIP
+	db -1
+
+UnownPuzzleCoordData: ; e1559
+
+puzzle_coords: MACRO
+	dbpixel \1, \2, \3, \4
+	dwcoord \5, \6
+	db \7, \8
+ENDM
+; OAM coords, tilemap coords, vacant tile, filler
+	puzzle_coords  3,  3, 4, 4,  1,  0, PUZZLE_BORDER, 0
+	puzzle_coords  6,  3, 4, 4,  4,  0, PUZZLE_BORDER, 0
+	puzzle_coords  9,  3, 4, 4,  7,  0, PUZZLE_BORDER, 0
+	puzzle_coords 12,  3, 4, 4, 10,  0, PUZZLE_BORDER, 0
+	puzzle_coords 15,  3, 4, 4, 13,  0, PUZZLE_BORDER, 0
+	puzzle_coords 18,  3, 4, 4, 16,  0, PUZZLE_BORDER, 0
+
+	puzzle_coords  3,  6, 4, 4,  1,  3, PUZZLE_BORDER, 0
+	puzzle_coords  6,  6, 4, 4,  4,  3, PUZZLE_VOID,   0
+	puzzle_coords  9,  6, 4, 4,  7,  3, PUZZLE_VOID,   0
+	puzzle_coords 12,  6, 4, 4, 10,  3, PUZZLE_VOID,   0
+	puzzle_coords 15,  6, 4, 4, 13,  3, PUZZLE_VOID,   0
+	puzzle_coords 18,  6, 4, 4, 16,  3, PUZZLE_BORDER, 0
+
+	puzzle_coords  3,  9, 4, 4,  1,  6, PUZZLE_BORDER, 0
+	puzzle_coords  6,  9, 4, 4,  4,  6, PUZZLE_VOID,   0
+	puzzle_coords  9,  9, 4, 4,  7,  6, PUZZLE_VOID,   0
+	puzzle_coords 12,  9, 4, 4, 10,  6, PUZZLE_VOID,   0
+	puzzle_coords 15,  9, 4, 4, 13,  6, PUZZLE_VOID,   0
+	puzzle_coords 18,  9, 4, 4, 16,  6, PUZZLE_BORDER, 0
+
+	puzzle_coords  3, 12, 4, 4,  1,  9, PUZZLE_BORDER, 0
+	puzzle_coords  6, 12, 4, 4,  4,  9, PUZZLE_VOID,   0
+	puzzle_coords  9, 12, 4, 4,  7,  9, PUZZLE_VOID,   0
+	puzzle_coords 12, 12, 4, 4, 10,  9, PUZZLE_VOID,   0
+	puzzle_coords 15, 12, 4, 4, 13,  9, PUZZLE_VOID,   0
+	puzzle_coords 18, 12, 4, 4, 16,  9, PUZZLE_BORDER, 0
+
+	puzzle_coords  3, 15, 4, 4,  1, 12, PUZZLE_BORDER, 0
+	puzzle_coords  6, 15, 4, 4,  4, 12, PUZZLE_VOID,   0
+	puzzle_coords  9, 15, 4, 4,  7, 12, PUZZLE_VOID,   0
+	puzzle_coords 12, 15, 4, 4, 10, 12, PUZZLE_VOID,   0
+	puzzle_coords 15, 15, 4, 4, 13, 12, PUZZLE_VOID,   0
+	puzzle_coords 18, 15, 4, 4, 16, 12, PUZZLE_BORDER, 0
+
+	puzzle_coords  3, 18, 4, 4,  1, 15, PUZZLE_BORDER, 0
+	puzzle_coords  6, 18, 4, 4,  4, 15, PUZZLE_BORDER, 0
+	puzzle_coords  9, 18, 4, 4,  7, 15, PUZZLE_BORDER, 0
+	puzzle_coords 12, 18, 4, 4, 10, 15, PUZZLE_BORDER, 0
+	puzzle_coords 15, 18, 4, 4, 13, 15, PUZZLE_BORDER, 0
+	puzzle_coords 18, 18, 4, 4, 16, 15, PUZZLE_BORDER, 0
+
+ConvertLoadedPuzzlePieces: ; e1631
+	ld hl, vTiles2
+	ld de, vTiles0
+	ld b, 6
+.loop
+	push bc
+	push hl
+	push hl
+	call .EnlargePuzzlePieceTiles
+	pop hl
+	ld bc, 1 tiles / 2
+	add hl, bc
+	call .EnlargePuzzlePieceTiles
+	pop hl
+	ld bc, 6 tiles
+	add hl, bc
+	pop bc
+	dec b
+	jr nz, .loop
+	call UnownPuzzle_AddPuzzlePieceBorders
+	ret
+; e1654
+
+.EnlargePuzzlePieceTiles: ; e1654
+; double size
+	ld c, 6
+.loop1
+	push bc
+	push hl
+	push hl
+	ld c, 4
+.loop2
+	push bc
+	ld a, [hli]
+	and $f0
+	swap a
+	call .GetEnlargedTile
+	ld c, a
+	ld a, [hli]
+	and $f0
+	swap a
+	call .GetEnlargedTile
+	ld b, a
+	ld a, c
+	ld [de], a
+	inc de
+	ld a, b
+	ld [de], a
+	inc de
+	ld a, c
+	ld [de], a
+	inc de
+	ld a, b
+	ld [de], a
+	inc de
+	pop bc
+	dec c
+	jr nz, .loop2
+	pop hl
+	ld c, 4
+.loop3
+	push bc
+	ld a, [hli]
+	and $f
+	call .GetEnlargedTile
+	ld c, a
+	ld a, [hli]
+	and $f
+	call .GetEnlargedTile
+	ld b, a
+	ld a, c
+	ld [de], a
+	inc de
+	ld a, b
+	ld [de], a
+	inc de
+	ld a, c
+	ld [de], a
+	inc de
+	ld a, b
+	ld [de], a
+	inc de
+	pop bc
+	dec c
+	jr nz, .loop3
+	pop hl
+	ld bc, 1 tiles
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .loop1
+	ret
+; e16aa
+
+.GetEnlargedTile: ; e16aa
+	push hl
+	ld hl, .EnlargedTiles
+	add l
+	ld l, a
+	ld a, 0
+	adc h
+	ld h, a
+	ld a, [hl]
+	pop hl
+	ret
+; e16b7
+
+.EnlargedTiles: ; e16b7
+
+x = 0
+rept 16
+	db ((x & %1000) * %11000) + ((x & %0100) * %1100) + ((x & %0010) * %110) + ((x & %0001) * %11)
+x = x + 1
+endr
+; e16c7
+
+UnownPuzzle_AddPuzzlePieceBorders: ; e16c7
+	ld hl, PuzzlePieceBorderData
+	ld a, 8
+.loop
+	push af
+	push hl
+	ld a, [hli]
+	ld e, a
+	ld a, [hli]
+	ld d, a
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	call .LoadGFX
+	pop hl
+rept 4
+	inc hl
+endr
+	pop af
+	dec a
+	jr nz, .loop
+	ret
+; e16e2
+
+.LoadGFX: ; e16e2
+	lb bc, 4, 4
+.loop1
+	push bc
+
+.loop2
+	push de
+	push hl
+
+	ld b, 1 tiles
+.loop3
+	ld a, [de]
+	or [hl]
+	ld [hli], a
+	inc de
+	dec b
+	jr nz, .loop3
+
+	pop hl
+	ld de, 3 tiles
+	add hl, de
+	pop de
+	dec c
+	jr nz, .loop2
+
+	ld bc, 24 tiles
+	add hl, bc
+	pop bc
+	dec b
+	jr nz, .loop1
+	ret
+; e1703
+
+PuzzlePieceBorderData: ; e1703
+	dw .TileBordersGFX + 0 tiles, vTiles0 tile $00
+	dw .TileBordersGFX + 1 tiles, vTiles0 tile $01
+	dw .TileBordersGFX + 2 tiles, vTiles0 tile $02
+	dw .TileBordersGFX + 3 tiles, vTiles0 tile $0c
+	dw .TileBordersGFX + 4 tiles, vTiles0 tile $0e
+	dw .TileBordersGFX + 5 tiles, vTiles0 tile $18
+	dw .TileBordersGFX + 6 tiles, vTiles0 tile $19
+	dw .TileBordersGFX + 7 tiles, vTiles0 tile $1a
+; e1723
+
+.TileBordersGFX: ; e1723
+INCBIN "gfx/unown_puzzle/tile_borders.2bpp"
+
+LoadUnownPuzzlePiecesGFX: ; e17a3
+	ld a, [wScriptVar]
+	maskbits NUM_UNOWN_PUZZLES
+	ld e, a
+	ld d, 0
+	ld hl, .LZPointers
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, vTiles2
+	call Decompress
+	call ConvertLoadedPuzzlePieces
+	ret
+; e17bd
+
+.LZPointers: ; e17bd
+; entries correspond to UNOWNPUZZLE_* constants
+	dw KabutoPuzzleLZ
+	dw OmanytePuzzleLZ
+	dw AerodactylPuzzleLZ
+	dw HoOhPuzzleLZ
+; e17c5
+
+UnownPuzzleCursorGFX: ; e17c5
+INCBIN "gfx/unown_puzzle/cursor.2bpp"
+
+UnownPuzzleStartCancelLZ: ; e1805
+INCBIN "gfx/unown_puzzle/start_cancel.2bpp.lz"
+
+HoOhPuzzleLZ: ; e18ab
+INCBIN "gfx/unown_puzzle/hooh.2bpp.lz"
+
+AerodactylPuzzleLZ: ; e19fb
+INCBIN "gfx/unown_puzzle/aerodactyl.2bpp.lz"
+
+KabutoPuzzleLZ: ; e1bab
+INCBIN "gfx/unown_puzzle/kabuto.2bpp.lz"
+
+OmanytePuzzleLZ: ; e1c9b
+INCBIN "gfx/unown_puzzle/omanyte.2bpp.lz"
--- /dev/null
+++ b/engine/gfx/drawkrispackgfx.asm
@@ -1,0 +1,20 @@
+DrawKrisPackGFX: ; 48e81
+	ld hl, PackFGFXPointers
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld e, a
+	ld d, [hl]
+	ld hl, vTiles2 tile $50
+	lb bc, BANK(PackFGFX), 15
+	call Request2bpp
+	ret
+
+PackFGFXPointers: ; 48e93
+	dw PackFGFX + (15 tiles) * 1 ; ITEM_POCKET
+	dw PackFGFX + (15 tiles) * 3 ; BALL_POCKET
+	dw PackFGFX + (15 tiles) * 0 ; KEY_ITEM_POCKET
+	dw PackFGFX + (15 tiles) * 2 ; TM_HM_POCKET
+
+PackFGFX: ; 48e9b
+INCBIN "gfx/pack/pack_f.2bpp"
--- /dev/null
+++ b/engine/gfx/loadoverworldfont.asm
@@ -1,0 +1,17 @@
+LoadOverworldFont:: ; 106594
+	ld de, .OverworldFontGFX
+	ld hl, vTiles1
+	lb bc, BANK(.OverworldFontGFX), $80
+	call Get2bpp
+	ld de, .OverworldFontSpaceGFX
+	ld hl, vTiles2 tile " "
+	lb bc, BANK(.OverworldFontSpaceGFX), 1
+	call Get2bpp
+	ret
+; 1065ad
+
+.OverworldFontGFX:
+INCBIN "gfx/font/overworld.2bpp"
+
+.OverworldFontSpaceGFX:
+INCBIN "gfx/font/overworld_space.2bpp"
--- /dev/null
+++ b/engine/gfx/placegraphic.asm
@@ -1,0 +1,55 @@
+PlaceGraphic: ; 2ef6e
+; Fill wBoxAlignment-aligned box width b height c
+; with iterating tile starting from hGraphicStartTile at hl.
+
+	ld de, SCREEN_WIDTH
+
+	ld a, [wBoxAlignment]
+	and a
+	jr nz, .right
+
+	ld a, [hGraphicStartTile]
+.x1
+	push bc
+	push hl
+
+.y1
+	ld [hl], a
+	add hl, de
+	inc a
+	dec c
+	jr nz, .y1
+
+	pop hl
+	inc hl
+	pop bc
+	dec b
+	jr nz, .x1
+	ret
+
+.right
+; Right-aligned.
+	push bc
+	ld b, 0
+	dec c
+	add hl, bc
+	pop bc
+
+	ld a, [hGraphicStartTile]
+.x2
+	push bc
+	push hl
+
+.y2
+	ld [hl], a
+	add hl, de
+	inc a
+	dec c
+	jr nz, .y2
+
+	pop hl
+	dec hl
+	pop bc
+	dec b
+	jr nz, .x2
+	ret
--- /dev/null
+++ b/engine/gfx/trademonfrontpic.asm
@@ -1,0 +1,38 @@
+GetTrademonFrontpic: ; 4d7fd
+	ld a, [wOTTrademonSpecies]
+	ld hl, wOTTrademonDVs
+	ld de, vTiles2
+	push de
+	push af
+	predef GetUnownLetter
+	pop af
+	ld [wCurPartySpecies], a
+	ld [wCurSpecies], a
+	call GetBaseData
+	pop de
+	predef GetAnimatedFrontpic
+	ret
+
+AnimateTrademonFrontpic: ; 4d81e
+	ld a, [wOTTrademonSpecies]
+	call IsAPokemon
+	ret c
+	farcall ShowOTTrademonStats
+	ld a, [wOTTrademonSpecies]
+	ld [wCurPartySpecies], a
+	ld a, [wOTTrademonDVs]
+	ld [wTempMonDVs], a
+	ld a, [wOTTrademonDVs + 1]
+	ld [wTempMonDVs + 1], a
+	ld b, SCGB_PLAYER_OR_MON_FRONTPIC_PALS
+	call GetSGBLayout
+	ld a, %11100100 ; 3,2,1,0
+	call DmgToCgbBGPals
+	farcall TradeAnim_ShowGetmonFrontpic
+	ld a, [wOTTrademonSpecies]
+	ld [wCurPartySpecies], a
+	hlcoord 7, 2
+	ld d, $0
+	ld e, ANIM_MON_TRADE
+	predef AnimateFrontpic
+	ret
--- a/engine/item_effects.asm
+++ /dev/null
@@ -1,3118 +1,0 @@
-_DoItemEffect:: ; e722
-	ld a, [wCurItem]
-	ld [wd265], a
-	call GetItemName
-	call CopyName1
-	ld a, 1
-	ld [wItemEffectSucceeded], a
-	ld a, [wCurItem]
-	dec a
-	ld hl, ItemEffects
-	rst JumpTable
-	ret
-; e73c
-
-
-ItemEffects: ; e73c
-; entries correspond to item ids
-	dw PokeBallEffect      ; MASTER_BALL
-	dw PokeBallEffect      ; ULTRA_BALL
-	dw NoEffect            ; BRIGHTPOWDER
-	dw PokeBallEffect      ; GREAT_BALL
-	dw PokeBallEffect      ; POKE_BALL
-	dw TownMapEffect       ; TOWN_MAP
-	dw BicycleEffect       ; BICYCLE
-	dw EvoStoneEffect      ; MOON_STONE
-	dw StatusHealingEffect ; ANTIDOTE
-	dw StatusHealingEffect ; BURN_HEAL
-	dw StatusHealingEffect ; ICE_HEAL
-	dw StatusHealingEffect ; AWAKENING
-	dw StatusHealingEffect ; PARLYZ_HEAL
-	dw FullRestoreEffect   ; FULL_RESTORE
-	dw RestoreHPEffect     ; MAX_POTION
-	dw RestoreHPEffect     ; HYPER_POTION
-	dw RestoreHPEffect     ; SUPER_POTION
-	dw RestoreHPEffect     ; POTION
-	dw EscapeRopeEffect    ; ESCAPE_ROPE
-	dw RepelEffect         ; REPEL
-	dw RestorePPEffect     ; MAX_ELIXER
-	dw EvoStoneEffect      ; FIRE_STONE
-	dw EvoStoneEffect      ; THUNDERSTONE
-	dw EvoStoneEffect      ; WATER_STONE
-	dw NoEffect            ; ITEM_19
-	dw VitaminEffect       ; HP_UP
-	dw VitaminEffect       ; PROTEIN
-	dw VitaminEffect       ; IRON
-	dw VitaminEffect       ; CARBOS
-	dw NoEffect            ; LUCKY_PUNCH
-	dw VitaminEffect       ; CALCIUM
-	dw RareCandyEffect     ; RARE_CANDY
-	dw XAccuracyEffect     ; X_ACCURACY
-	dw EvoStoneEffect      ; LEAF_STONE
-	dw NoEffect            ; METAL_POWDER
-	dw NoEffect            ; NUGGET
-	dw PokeDollEffect      ; POKE_DOLL
-	dw StatusHealingEffect ; FULL_HEAL
-	dw ReviveEffect        ; REVIVE
-	dw ReviveEffect        ; MAX_REVIVE
-	dw GuardSpecEffect     ; GUARD_SPEC
-	dw SuperRepelEffect    ; SUPER_REPEL
-	dw MaxRepelEffect      ; MAX_REPEL
-	dw DireHitEffect       ; DIRE_HIT
-	dw NoEffect            ; ITEM_2D
-	dw RestoreHPEffect     ; FRESH_WATER
-	dw RestoreHPEffect     ; SODA_POP
-	dw RestoreHPEffect     ; LEMONADE
-	dw XItemEffect         ; X_ATTACK
-	dw NoEffect            ; ITEM_32
-	dw XItemEffect         ; X_DEFEND
-	dw XItemEffect         ; X_SPEED
-	dw XItemEffect         ; X_SPECIAL
-	dw CoinCaseEffect      ; COIN_CASE
-	dw ItemfinderEffect    ; ITEMFINDER
-	dw PokeFluteEffect     ; POKE_FLUTE
-	dw NoEffect            ; EXP_SHARE
-	dw OldRodEffect        ; OLD_ROD
-	dw GoodRodEffect       ; GOOD_ROD
-	dw NoEffect            ; SILVER_LEAF
-	dw SuperRodEffect      ; SUPER_ROD
-	dw RestorePPEffect     ; PP_UP
-	dw RestorePPEffect     ; ETHER
-	dw RestorePPEffect     ; MAX_ETHER
-	dw RestorePPEffect     ; ELIXER
-	dw NoEffect            ; RED_SCALE
-	dw NoEffect            ; SECRETPOTION
-	dw NoEffect            ; S_S_TICKET
-	dw NoEffect            ; MYSTERY_EGG
-	dw NoEffect            ; CLEAR_BELL
-	dw NoEffect            ; SILVER_WING
-	dw RestoreHPEffect     ; MOOMOO_MILK
-	dw NoEffect            ; QUICK_CLAW
-	dw StatusHealingEffect ; PSNCUREBERRY
-	dw NoEffect            ; GOLD_LEAF
-	dw NoEffect            ; SOFT_SAND
-	dw NoEffect            ; SHARP_BEAK
-	dw StatusHealingEffect ; PRZCUREBERRY
-	dw StatusHealingEffect ; BURNT_BERRY
-	dw StatusHealingEffect ; ICE_BERRY
-	dw NoEffect            ; POISON_BARB
-	dw NoEffect            ; KINGS_ROCK
-	dw BitterBerryEffect   ; BITTER_BERRY
-	dw StatusHealingEffect ; MINT_BERRY
-	dw NoEffect            ; RED_APRICORN
-	dw NoEffect            ; TINYMUSHROOM
-	dw NoEffect            ; BIG_MUSHROOM
-	dw NoEffect            ; SILVERPOWDER
-	dw NoEffect            ; BLU_APRICORN
-	dw NoEffect            ; ITEM_5A
-	dw NoEffect            ; AMULET_COIN
-	dw NoEffect            ; YLW_APRICORN
-	dw NoEffect            ; GRN_APRICORN
-	dw NoEffect            ; CLEANSE_TAG
-	dw NoEffect            ; MYSTIC_WATER
-	dw NoEffect            ; TWISTEDSPOON
-	dw NoEffect            ; WHT_APRICORN
-	dw NoEffect            ; BLACKBELT
-	dw NoEffect            ; BLK_APRICORN
-	dw NoEffect            ; ITEM_64
-	dw NoEffect            ; PNK_APRICORN
-	dw NoEffect            ; BLACKGLASSES
-	dw NoEffect            ; SLOWPOKETAIL
-	dw NoEffect            ; PINK_BOW
-	dw NoEffect            ; STICK
-	dw NoEffect            ; SMOKE_BALL
-	dw NoEffect            ; NEVERMELTICE
-	dw NoEffect            ; MAGNET
-	dw StatusHealingEffect ; MIRACLEBERRY
-	dw NoEffect            ; PEARL
-	dw NoEffect            ; BIG_PEARL
-	dw NoEffect            ; EVERSTONE
-	dw NoEffect            ; SPELL_TAG
-	dw RestoreHPEffect     ; RAGECANDYBAR
-	dw NoEffect            ; GS_BALL
-	dw BlueCardEffect      ; BLUE_CARD
-	dw NoEffect            ; MIRACLE_SEED
-	dw NoEffect            ; THICK_CLUB
-	dw NoEffect            ; FOCUS_BAND
-	dw NoEffect            ; ITEM_78
-	dw EnergypowderEffect  ; ENERGYPOWDER
-	dw EnergyRootEffect    ; ENERGY_ROOT
-	dw HealPowderEffect    ; HEAL_POWDER
-	dw RevivalHerbEffect   ; REVIVAL_HERB
-	dw NoEffect            ; HARD_STONE
-	dw NoEffect            ; LUCKY_EGG
-	dw CardKeyEffect       ; CARD_KEY
-	dw NoEffect            ; MACHINE_PART
-	dw NoEffect            ; EGG_TICKET
-	dw NoEffect            ; LOST_ITEM
-	dw NoEffect            ; STARDUST
-	dw NoEffect            ; STAR_PIECE
-	dw BasementKeyEffect   ; BASEMENT_KEY
-	dw NoEffect            ; PASS
-	dw NoEffect            ; ITEM_87
-	dw NoEffect            ; ITEM_88
-	dw NoEffect            ; ITEM_89
-	dw NoEffect            ; CHARCOAL
-	dw RestoreHPEffect     ; BERRY_JUICE
-	dw NoEffect            ; SCOPE_LENS
-	dw NoEffect            ; ITEM_8D
-	dw NoEffect            ; ITEM_8E
-	dw NoEffect            ; METAL_COAT
-	dw NoEffect            ; DRAGON_FANG
-	dw NoEffect            ; ITEM_91
-	dw NoEffect            ; LEFTOVERS
-	dw NoEffect            ; ITEM_93
-	dw NoEffect            ; ITEM_94
-	dw NoEffect            ; ITEM_95
-	dw RestorePPEffect     ; MYSTERYBERRY
-	dw NoEffect            ; DRAGON_SCALE
-	dw NoEffect            ; BERSERK_GENE
-	dw NoEffect            ; ITEM_99
-	dw NoEffect            ; ITEM_9A
-	dw NoEffect            ; ITEM_9B
-	dw SacredAshEffect     ; SACRED_ASH
-	dw PokeBallEffect      ; HEAVY_BALL
-	dw NoEffect            ; FLOWER_MAIL
-	dw PokeBallEffect      ; LEVEL_BALL
-	dw PokeBallEffect      ; LURE_BALL
-	dw PokeBallEffect      ; FAST_BALL
-	dw NoEffect            ; ITEM_A2
-	dw NoEffect            ; LIGHT_BALL
-	dw PokeBallEffect      ; FRIEND_BALL
-	dw PokeBallEffect      ; MOON_BALL
-	dw PokeBallEffect      ; LOVE_BALL
-	dw NormalBoxEffect     ; NORMAL_BOX
-	dw GorgeousBoxEffect   ; GORGEOUS_BOX
-	dw EvoStoneEffect      ; SUN_STONE
-	dw NoEffect            ; POLKADOT_BOW
-	dw NoEffect            ; ITEM_AB
-	dw NoEffect            ; UP_GRADE
-	dw RestoreHPEffect     ; BERRY
-	dw RestoreHPEffect     ; GOLD_BERRY
-	dw SquirtbottleEffect  ; SQUIRTBOTTLE
-	dw NoEffect            ; ITEM_B0
-	dw PokeBallEffect      ; PARK_BALL
-	dw NoEffect            ; RAINBOW_WING
-	dw NoEffect            ; ITEM_B3
-; e8a2
-
-
-PokeBallEffect: ; e8a2
-	ld a, [wBattleMode]
-	dec a
-	jp nz, UseBallInTrainerBattle
-
-	ld a, [wPartyCount]
-	cp PARTY_LENGTH
-	jr nz, .room_in_party
-
-	ld a, BANK(sBoxCount)
-	call GetSRAMBank
-	ld a, [sBoxCount]
-	cp MONS_PER_BOX
-	call CloseSRAM
-	jp z, Ball_BoxIsFullMessage
-
-.room_in_party
-	xor a
-	ld [wWildMon], a
-	ld a, [wCurItem]
-	cp PARK_BALL
-	call nz, ReturnToBattle_UseBall
-
-	ld hl, wOptions
-	res NO_TEXT_SCROLL, [hl]
-	ld hl, UsedItemText
-	call PrintText
-
-	ld a, [wEnemyMonCatchRate]
-	ld b, a
-	ld a, [wBattleType]
-	cp BATTLETYPE_TUTORIAL
-	jp z, .catch_without_fail
-	ld a, [wCurItem]
-	cp MASTER_BALL
-	jp z, .catch_without_fail
-	ld a, [wCurItem]
-	ld c, a
-	ld hl, BallMultiplierFunctionTable
-
-.get_multiplier_loop
-	ld a, [hli]
-	cp $ff
-	jr z, .skip_or_return_from_ball_fn
-	cp c
-	jr z, .call_ball_function
-	inc hl
-	inc hl
-	jr .get_multiplier_loop
-
-.call_ball_function
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, .skip_or_return_from_ball_fn
-	push de
-	jp hl
-
-.skip_or_return_from_ball_fn
-	ld a, [wCurItem]
-	cp LEVEL_BALL
-	ld a, b
-	jp z, .skip_hp_calc
-
-	ld a, b
-	ld [hMultiplicand + 2], a
-
-	ld hl, wEnemyMonHP
-	ld b, [hl]
-	inc hl
-	ld c, [hl]
-	inc hl
-	ld d, [hl]
-	inc hl
-	ld e, [hl]
-	sla c
-	rl b
-
-	ld h, d
-	ld l, e
-	add hl, de
-	add hl, de
-	ld d, h
-	ld e, l
-	ld a, d
-	and a
-	jr z, .okay_1
-
-	srl d
-	rr e
-	srl d
-	rr e
-	srl b
-	rr c
-	srl b
-	rr c
-
-	ld a, c
-	and a
-	jr nz, .okay_1
-	ld c, $1
-.okay_1
-	ld b, e
-
-	push bc
-	ld a, b
-	sub c
-	ld [hMultiplier], a
-	xor a
-	ld [hDividend + 0], a
-	ld [hMultiplicand + 0], a
-	ld [hMultiplicand + 1], a
-	call Multiply
-	pop bc
-
-	ld a, b
-	ld [hDivisor], a
-	ld b, $4
-	call Divide
-
-	ld a, [hQuotient + 2]
-	and a
-	jr nz, .statuscheck
-	ld a, 1
-.statuscheck
-; This routine is buggy. It was intended that SLP and FRZ provide a higher
-; catch rate than BRN/PSN/PAR, which in turn provide a higher catch rate than
-; no status effect at all. But instead, it makes BRN/PSN/PAR provide no
-; benefit.
-; Uncomment the line below to fix this.
-	ld b, a
-	ld a, [wEnemyMonStatus]
-	and 1 << FRZ | SLP
-	ld c, 10
-	jr nz, .addstatus
-	; ld a, [wEnemyMonStatus]
-	and a
-	ld c, 5
-	jr nz, .addstatus
-	ld c, 0
-.addstatus
-	ld a, b
-	add c
-	jr nc, .max_1
-	ld a, $ff
-.max_1
-
-	; BUG: farcall overwrites a, and GetItemHeldEffect takes b anyway.
-	; This is probably the reason the HELD_CATCH_CHANCE effect is never used.
-	; Uncomment the line below to fix.
-	ld d, a
-	push de
-	ld a, [wBattleMonItem]
-	; ld b, a
-	farcall GetItemHeldEffect
-	ld a, b
-	cp HELD_CATCH_CHANCE
-	pop de
-	ld a, d
-	jr nz, .max_2
-	add c
-	jr nc, .max_2
-	ld a, $ff
-.max_2
-
-.skip_hp_calc
-	ld b, a
-	ld [wBuffer1], a
-	call Random
-
-	cp b
-	ld a, 0
-	jr z, .catch_without_fail
-	jr nc, .fail_to_catch
-
-.catch_without_fail
-	ld a, [wEnemyMonSpecies]
-
-.fail_to_catch
-	ld [wWildMon], a
-	ld c, 20
-	call DelayFrames
-
-	ld a, [wCurItem]
-	cp POKE_BALL + 1 ; Assumes Master/Ultra/Great come before
-	jr c, .not_kurt_ball
-	ld a, POKE_BALL
-.not_kurt_ball
-	ld [wBattleAnimParam], a
-
-	ld de, ANIM_THROW_POKE_BALL
-	ld a, e
-	ld [wFXAnimID], a
-	ld a, d
-	ld [wFXAnimID + 1], a
-	xor a
-	ld [hBattleTurn], a
-	ld [wBuffer2], a
-	ld [wNumHits], a
-	predef PlayBattleAnim
-
-	ld a, [wWildMon]
-	and a
-	jr nz, .caught
-	ld a, [wBuffer2]
-	cp $1
-	ld hl, Text_NoShake
-	jp z, .shake_and_break_free
-	cp $2
-	ld hl, Text_OneShake
-	jp z, .shake_and_break_free
-	cp $3
-	ld hl, Text_TwoShakes
-	jp z, .shake_and_break_free
-	cp $4
-	ld hl, Text_ThreeShakes
-	jp z, .shake_and_break_free
-.caught
-
-	ld hl, wEnemyMonStatus
-	ld a, [hli]
-	push af
-	inc hl
-	ld a, [hli]
-	push af
-	ld a, [hl]
-	push af
-	push hl
-	ld hl, wEnemyMonItem
-	ld a, [hl]
-	push af
-	push hl
-	ld hl, wEnemySubStatus5
-	ld a, [hl]
-	push af
-	set SUBSTATUS_TRANSFORMED, [hl]
-
-; This code is buggy. Any wild Pokémon that has Transformed will be
-; caught as a Ditto, even if it was something else like Mew.
-; To fix, do not set [wTempEnemyMonSpecies] to DITTO.
-	bit SUBSTATUS_TRANSFORMED, a
-	jr nz, .ditto
-	jr .not_ditto
-
-.ditto
-	ld a, DITTO
-	ld [wTempEnemyMonSpecies], a
-	jr .load_data
-
-.not_ditto
-	set SUBSTATUS_TRANSFORMED, [hl]
-	ld hl, wEnemyBackupDVs
-	ld a, [wEnemyMonDVs]
-	ld [hli], a
-	ld a, [wEnemyMonDVs + 1]
-	ld [hl], a
-
-.load_data
-	ld a, [wTempEnemyMonSpecies]
-	ld [wCurPartySpecies], a
-	ld a, [wEnemyMonLevel]
-	ld [wCurPartyLevel], a
-	farcall LoadEnemyMon
-
-	pop af
-	ld [wEnemySubStatus5], a
-
-	pop hl
-	pop af
-	ld [hl], a
-	pop hl
-	pop af
-	ld [hld], a
-	pop af
-	ld [hld], a
-	dec hl
-	pop af
-	ld [hl], a
-
-	ld hl, wEnemySubStatus5
-	bit SUBSTATUS_TRANSFORMED, [hl]
-	jr nz, .Transformed
-	ld hl, wWildMonMoves
-	ld de, wEnemyMonMoves
-	ld bc, NUM_MOVES
-	call CopyBytes
-
-	ld hl, wWildMonPP
-	ld de, wEnemyMonPP
-	ld bc, NUM_MOVES
-	call CopyBytes
-.Transformed:
-
-	ld a, [wEnemyMonSpecies]
-	ld [wWildMon], a
-	ld [wCurPartySpecies], a
-	ld [wd265], a
-	ld a, [wBattleType]
-	cp BATTLETYPE_TUTORIAL
-	jp z, .FinishTutorial
-
-	farcall StubbedTrainerRankings_WildMonsCaught
-
-	ld hl, Text_GotchaMonWasCaught
-	call PrintText
-
-	call ClearSprites
-
-	ld a, [wd265]
-	dec a
-	call CheckCaughtMon
-
-	ld a, c
-	push af
-	ld a, [wd265]
-	dec a
-	call SetSeenAndCaughtMon
-	pop af
-	and a
-	jr nz, .skip_pokedex
-
-	call CheckReceivedDex
-	jr z, .skip_pokedex
-
-	ld hl, Text_AddedToPokedex
-	call PrintText
-
-	call ClearSprites
-
-	ld a, [wEnemyMonSpecies]
-	ld [wd265], a
-	predef NewPokedexEntry
-
-.skip_pokedex
-	ld a, [wBattleType]
-	cp BATTLETYPE_CONTEST
-	jp z, .catch_bug_contest_mon
-	cp BATTLETYPE_CELEBI
-	jr nz, .not_celebi
-	ld hl, wBattleResult
-	set 6, [hl]
-.not_celebi
-
-	ld a, [wPartyCount]
-	cp PARTY_LENGTH
-	jr z, .SendToPC
-
-	xor a ; PARTYMON
-	ld [wMonType], a
-	call ClearSprites
-
-	predef TryAddMonToParty
-
-	farcall SetCaughtData
-
-	ld a, [wCurItem]
-	cp FRIEND_BALL
-	jr nz, .SkipPartyMonFriendBall
-
-	ld a, [wPartyCount]
-	dec a
-	ld hl, wPartyMon1Happiness
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-
-	ld a, FRIEND_BALL_HAPPINESS
-	ld [hl], a
-.SkipPartyMonFriendBall:
-
-	ld hl, Text_AskNicknameNewlyCaughtMon
-	call PrintText
-
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	call GetPokemonName
-
-	call YesNoBox
-	jp c, .return_from_capture
-
-	ld a, [wPartyCount]
-	dec a
-	ld [wCurPartyMon], a
-	ld hl, wPartyMonNicknames
-	ld bc, MON_NAME_LENGTH
-	call AddNTimes
-
-	ld d, h
-	ld e, l
-	push de
-	xor a ; PARTYMON
-	ld [wMonType], a
-	ld b, 0
-	farcall NamingScreen
-
-	call RotateThreePalettesRight
-
-	call LoadStandardFont
-
-	pop hl
-	ld de, wStringBuffer1
-	call InitName
-
-	jp .return_from_capture
-
-.SendToPC:
-	call ClearSprites
-
-	predef SendMonIntoBox
-
-	farcall SetBoxMonCaughtData
-
-	ld a, BANK(sBoxCount)
-	call GetSRAMBank
-
-	ld a, [sBoxCount]
-	cp MONS_PER_BOX
-	jr nz, .BoxNotFullYet
-	ld hl, wBattleResult
-	set 7, [hl]
-.BoxNotFullYet:
-	ld a, [wCurItem]
-	cp FRIEND_BALL
-	jr nz, .SkipBoxMonFriendBall
-	; The captured mon is now first in the box
-	ld a, FRIEND_BALL_HAPPINESS
-	ld [sBoxMon1Happiness], a
-.SkipBoxMonFriendBall:
-	call CloseSRAM
-
-	ld hl, Text_AskNicknameNewlyCaughtMon
-	call PrintText
-
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	call GetPokemonName
-
-	call YesNoBox
-	jr c, .SkipBoxMonNickname
-
-	xor a
-	ld [wCurPartyMon], a
-	ld a, BOXMON
-	ld [wMonType], a
-	ld de, wMonOrItemNameBuffer
-	ld b, $0
-	farcall NamingScreen
-
-	ld a, BANK(sBoxMonNicknames)
-	call GetSRAMBank
-
-	ld hl, wMonOrItemNameBuffer
-	ld de, sBoxMonNicknames
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-
-	ld hl, sBoxMonNicknames
-	ld de, wStringBuffer1
-	call InitName
-
-	call CloseSRAM
-
-.SkipBoxMonNickname:
-	ld a, BANK(sBoxMonNicknames)
-	call GetSRAMBank
-
-	ld hl, sBoxMonNicknames
-	ld de, wMonOrItemNameBuffer
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-
-	call CloseSRAM
-
-	ld hl, Text_SentToBillsPC
-	call PrintText
-
-	call RotateThreePalettesRight
-	call LoadStandardFont
-	jr .return_from_capture
-
-.catch_bug_contest_mon
-	farcall BugContest_SetCaughtContestMon
-	jr .return_from_capture
-
-.FinishTutorial:
-	ld hl, Text_GotchaMonWasCaught
-
-.shake_and_break_free
-	call PrintText
-	call ClearSprites
-
-.return_from_capture
-	ld a, [wBattleType]
-	cp BATTLETYPE_TUTORIAL
-	ret z
-	cp BATTLETYPE_DEBUG
-	ret z
-	cp BATTLETYPE_CONTEST
-	jr z, .used_park_ball
-
-	ld a, [wWildMon]
-	and a
-	jr z, .toss
-
-	call ClearBGPalettes
-	call ClearTileMap
-
-.toss
-	ld hl, wNumItems
-	inc a
-	ld [wItemQuantityChangeBuffer], a
-	jp TossItem
-
-.used_park_ball
-	ld hl, wParkBallsRemaining
-	dec [hl]
-	ret
-; ec0a
-
-
-BallMultiplierFunctionTable:
-; table of routines that increase or decrease the catch rate based on
-; which ball is used in a certain situation.
-	dbw ULTRA_BALL,  UltraBallMultiplier
-	dbw GREAT_BALL,  GreatBallMultiplier
-	dbw SAFARI_BALL, SafariBallMultiplier ; Safari Ball, leftover from RBY
-	dbw HEAVY_BALL,  HeavyBallMultiplier
-	dbw LEVEL_BALL,  LevelBallMultiplier
-	dbw LURE_BALL,   LureBallMultiplier
-	dbw FAST_BALL,   FastBallMultiplier
-	dbw MOON_BALL,   MoonBallMultiplier
-	dbw LOVE_BALL,   LoveBallMultiplier
-	dbw PARK_BALL,   ParkBallMultiplier
-	db -1 ; end
-
-UltraBallMultiplier:
-; multiply catch rate by 2
-	sla b
-	ret nc
-	ld b, $ff
-	ret
-
-SafariBallMultiplier:
-GreatBallMultiplier:
-ParkBallMultiplier:
-; multiply catch rate by 1.5
-	ld a, b
-	srl a
-	add b
-	ld b, a
-	ret nc
-	ld b, $ff
-	ret
-
-GetPokedexEntryBank:
-	push hl
-	push de
-	ld a, [wEnemyMonSpecies]
-	rlca
-	rlca
-	maskbits NUM_DEX_ENTRY_BANKS
-	ld hl, .PokedexEntryBanks
-	ld d, 0
-	ld e, a
-	add hl, de
-	ld a, [hl]
-	pop de
-	pop hl
-	ret
-
-.PokedexEntryBanks:
-	db BANK(PokedexEntries1)
-	db BANK(PokedexEntries2)
-	db BANK(PokedexEntries3)
-	db BANK(PokedexEntries4)
-
-HeavyBallMultiplier:
-; subtract 20 from catch rate if weight < 102.4 kg
-; else add 0 to catch rate if weight < 204.8 kg
-; else add 20 to catch rate if weight < 307.2 kg
-; else add 30 to catch rate if weight < 409.6 kg
-; else add 40 to catch rate (never happens)
-	ld a, [wEnemyMonSpecies]
-	ld hl, PokedexDataPointerTable
-	dec a
-	ld e, a
-	ld d, 0
-	add hl, de
-	add hl, de
-	ld a, BANK(PokedexDataPointerTable)
-	call GetFarHalfword
-
-.SkipText:
-	call GetPokedexEntryBank
-	call GetFarByte
-	inc hl
-	cp "@"
-	jr nz, .SkipText
-
-	call GetPokedexEntryBank
-	push bc
-	inc hl
-	inc hl
-	call GetFarHalfword
-
-	srl h
-	rr l
-	ld b, h
-	ld c, l
-
-	rept 4
-	srl b
-	rr c
-	endr
-	call .subbc
-
-	srl b
-	rr c
-	call .subbc
-
-	ld a, h
-	pop bc
-	jr .compare
-
-.subbc
-	; subtract bc from hl
-	push bc
-	ld a, b
-	cpl
-	ld b, a
-	ld a, c
-	cpl
-	ld c, a
-	inc bc
-	add hl, bc
-	pop bc
-	ret
-
-.compare
-	ld c, a
-	cp HIGH(1024) ; 102.4 kg
-	jr c, .lightmon
-
-	ld hl, .WeightsTable
-.lookup
-	ld a, c
-	cp [hl]
-	jr c, .heavymon
-	inc hl
-	inc hl
-	jr .lookup
-
-.heavymon
-	inc hl
-	ld a, b
-	add [hl]
-	ld b, a
-	ret nc
-	ld b, $ff
-	ret
-
-.lightmon
-	ld a, b
-	sub 20
-	ld b, a
-	ret nc
-	ld b, $1
-	ret
-
-.WeightsTable:
-; weight factor, boost
-	db HIGH(2048),   0
-	db HIGH(3072),  20
-	db HIGH(4096),  30
-	db HIGH(65280), 40
-
-LureBallMultiplier:
-; multiply catch rate by 3 if this is a fishing rod battle
-	ld a, [wBattleType]
-	cp BATTLETYPE_FISH
-	ret nz
-
-	ld a, b
-	add a
-	jr c, .max
-
-	add b
-	jr nc, .done
-.max
-	ld a, $ff
-.done
-	ld b, a
-	ret
-
-MoonBallMultiplier:
-; This function is buggy.
-; Intent:  multiply catch rate by 4 if mon evolves with moon stone
-; Reality: no boost
-	push bc
-	ld a, [wTempEnemyMonSpecies]
-	dec a
-	ld c, a
-	ld b, 0
-	ld hl, EvosAttacksPointers
-	add hl, bc
-	add hl, bc
-	ld a, BANK(EvosAttacksPointers)
-	call GetFarHalfword
-	pop bc
-
-	push bc
-	ld a, BANK(EvosAttacks)
-	call GetFarByte
-	cp EVOLVE_ITEM
-	pop bc
-	ret nz
-
-	inc hl
-	inc hl
-	inc hl
-
-; Moon Stone's constant from Pokémon Red is used.
-; No Pokémon evolve with Burn Heal,
-; so Moon Balls always have a catch rate of 1×.
-	push bc
-	ld a, BANK(EvosAttacks)
-	call GetFarByte
-	cp MOON_STONE_RED ; BURN_HEAL
-	pop bc
-	ret nz
-
-	sla b
-	jr c, .max
-	sla b
-	jr nc, .done
-.max
-	ld b, $ff
-.done
-	ret
-
-LoveBallMultiplier:
-; This function is buggy.
-; Intent:  multiply catch rate by 8 if mons are of same species, different sex
-; Reality: multiply catch rate by 8 if mons are of same species, same sex
-
-	; does species match?
-	ld a, [wTempEnemyMonSpecies]
-	ld c, a
-	ld a, [wTempBattleMonSpecies]
-	cp c
-	ret nz
-
-	; check player mon species
-	push bc
-	ld a, [wTempBattleMonSpecies]
-	ld [wCurPartySpecies], a
-	xor a ; PARTYMON
-	ld [wMonType], a
-	ld a, [wCurBattleMon]
-	ld [wCurPartyMon], a
-	farcall GetGender
-	jr c, .done1 ; no effect on genderless
-
-	ld d, 0 ; male
-	jr nz, .playermale
-	inc d   ; female
-.playermale
-
-	; check wild mon species
-	push de
-	ld a, [wTempEnemyMonSpecies]
-	ld [wCurPartySpecies], a
-	ld a, WILDMON
-	ld [wMonType], a
-	farcall GetGender
-	jr c, .done2 ; no effect on genderless
-
-	ld d, 0 ; male
-	jr nz, .wildmale
-	inc d   ; female
-.wildmale
-
-	ld a, d
-	pop de
-	cp d
-	pop bc
-	ret nz ; for the intended effect, this should be "ret z"
-
-	sla b
-	jr c, .max
-	sla b
-	jr c, .max
-	sla b
-	ret nc
-.max
-	ld b, $ff
-	ret
-
-.done2
-	pop de
-
-.done1
-	pop bc
-	ret
-
-FastBallMultiplier:
-; This function is buggy.
-; Intent:  multiply catch rate by 4 if enemy mon is in one of the three
-;          FleeMons tables.
-; Reality: multiply catch rate by 4 if enemy mon is one of the first three in
-;          the first FleeMons table.
-	ld a, [wTempEnemyMonSpecies]
-	ld c, a
-	ld hl, FleeMons
-	ld d, 3
-
-.loop
-	ld a, BANK(FleeMons)
-	call GetFarByte
-
-	inc hl
-	cp -1
-	jr z, .next
-	cp c
-	jr nz, .next ; for the intended effect, this should be "jr nz, .loop"
-	sla b
-	jr c, .max
-
-	sla b
-	ret nc
-
-.max
-	ld b, $ff
-	ret
-
-.next
-	dec d
-	jr nz, .loop
-	ret
-
-LevelBallMultiplier:
-; multiply catch rate by 8 if player mon level / 4 > enemy mon level
-; multiply catch rate by 4 if player mon level / 2 > enemy mon level
-; multiply catch rate by 2 if player mon level > enemy mon level
-	ld a, [wBattleMonLevel]
-	ld c, a
-	ld a, [wEnemyMonLevel]
-	cp c
-	ret nc ; if player is lower level, we're done here
-	sla b
-	jr c, .max
-
-	srl c
-	cp c
-	ret nc ; if player/2 is lower level, we're done here
-	sla b
-	jr c, .max
-
-	srl c
-	cp c
-	ret nc ; if player/4 is lower level, we're done here
-	sla b
-	ret nc
-
-.max
-	ld b, $ff
-	ret
-
-; These two texts were carried over from gen 1.
-; They are not used in gen 2, and are dummied out.
-
-Text_RBY_CatchMarowak: ; 0xedab
-	; It dodged the thrown BALL! This #MON can't be caught!
-	text_jump UnknownText_0x1c5a5a
-	db "@"
-; 0xedb0
-
-Text_RBY_NoShake: ; 0xedb0
-	; You missed the #MON!
-	text_jump UnknownText_0x1c5a90
-	db "@"
-; 0xedb5
-
-Text_NoShake: ; 0xedb5
-	; Oh no! The #MON broke free!
-	text_jump UnknownText_0x1c5aa6
-	db "@"
-; 0xedba
-
-Text_OneShake: ; 0xedba
-	; Aww! It appeared to be caught!
-	text_jump UnknownText_0x1c5ac3
-	db "@"
-; 0xedbf
-
-Text_TwoShakes: ; 0xedbf
-	; Aargh! Almost had it!
-	text_jump UnknownText_0x1c5ae3
-	db "@"
-; 0xedc4
-
-Text_ThreeShakes: ; 0xedc4
-	; Shoot! It was so close too!
-	text_jump UnknownText_0x1c5afa
-	db "@"
-; 0xedc9
-
-Text_GotchaMonWasCaught: ; 0xedc9
-	; Gotcha! @ was caught!@ @
-	text_jump UnknownText_0x1c5b17
-	start_asm
-	call WaitSFX
-	push bc
-	ld de, MUSIC_NONE
-	call PlayMusic
-	call DelayFrame
-	ld de, MUSIC_CAPTURE
-	call PlayMusic
-	pop bc
-	ld hl, TextJump_Waitbutton
-	ret
-; ede6
-
-TextJump_Waitbutton: ; 0xede6
-	; @
-	text_jump Text_Waitbutton_2
-	db "@"
-; 0xedeb
-
-Text_SentToBillsPC: ; 0xedeb
-	; was sent to BILL's PC.
-	text_jump UnknownText_0x1c5b38
-	db "@"
-; 0xedf0
-
-Text_AddedToPokedex: ; 0xedf0
-	; 's data was newly added to the #DEX.@ @
-	text_jump UnknownText_0x1c5b53
-	db "@"
-; 0xedf5
-
-Text_AskNicknameNewlyCaughtMon: ; 0xedf5
-	; Give a nickname to @ ?
-	text_jump UnknownText_0x1c5b7f
-	db "@"
-; 0xedfa
-
-ReturnToBattle_UseBall: ; edfa (3:6dfa)
-	farcall _ReturnToBattle_UseBall
-	ret
-
-TownMapEffect: ; ee01
-	farcall PokegearMap
-	ret
-; ee08
-
-
-BicycleEffect: ; ee08
-	farcall BikeFunction
-	ret
-; ee0f
-
-
-EvoStoneEffect: ; ee0f
-	ld b, PARTYMENUACTION_EVO_STONE
-	call UseItem_SelectMon
-
-	jp c, .DecidedNotToUse
-
-	ld a, MON_ITEM
-	call GetPartyParamLocation
-
-	ld a, [hl]
-	cp EVERSTONE
-	jr z, .NoEffect
-
-	ld a, $1
-	ld [wForceEvolution], a
-	farcall EvolvePokemon
-
-	ld a, [wMonTriedToEvolve]
-	and a
-	jr z, .NoEffect
-
-	jp UseDisposableItem
-
-.NoEffect:
-	call WontHaveAnyEffectMessage
-
-.DecidedNotToUse:
-	xor a
-	ld [wItemEffectSucceeded], a
-	ret
-; ee3d
-
-
-VitaminEffect: ; ee3d
-	ld b, PARTYMENUACTION_HEALING_ITEM
-	call UseItem_SelectMon
-
-	jp c, RareCandy_StatBooster_ExitMenu
-
-	call RareCandy_StatBooster_GetParameters
-
-	call GetStatExpRelativePointer
-
-	ld a, MON_STAT_EXP
-	call GetPartyParamLocation
-
-	add hl, bc
-	ld a, [hl]
-	cp 100
-	jr nc, NoEffectMessage
-
-	add 10
-	ld [hl], a
-	call UpdateStatsAfterItem
-
-	call GetStatExpRelativePointer
-
-	ld hl, StatStrings
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, wStringBuffer2
-	ld bc, ITEM_NAME_LENGTH
-	call CopyBytes
-
-	call Play_SFX_FULL_HEAL
-
-	ld hl, Text_StatRose
-	call PrintText
-
-	ld c, HAPPINESS_USEDITEM
-	farcall ChangeHappiness
-
-	jp UseDisposableItem
-
-
-NoEffectMessage: ; ee83
-	ld hl, WontHaveAnyEffectText
-	call PrintText
-	jp ClearPalettes
-; ee8c
-
-
-UpdateStatsAfterItem: ; ee8c
-	ld a, MON_MAXHP
-	call GetPartyParamLocation
-	ld d, h
-	ld e, l
-	ld a, MON_STAT_EXP - 1
-	call GetPartyParamLocation
-	ld b, TRUE
-	predef_jump CalcMonStats
-; ee9f
-
-RareCandy_StatBooster_ExitMenu: ; ee9f
-	xor a
-	ld [wItemEffectSucceeded], a
-	jp ClearPalettes
-; eea6
-
-
-Text_StatRose: ; 0xeea6
-	; 's @  rose.
-	text_jump UnknownText_0x1c5b9a
-	db "@"
-; 0xeeab
-
-
-StatStrings: ; eeab
-	dw .health
-	dw .attack
-	dw .defense
-	dw .speed
-	dw .special
-
-.health  db "HEALTH@"
-.attack  db "ATTACK@"
-.defense db "DEFENSE@"
-.speed   db "SPEED@"
-.special db "SPECIAL@"
-; eed9
-
-
-GetStatExpRelativePointer: ; eed9
-	ld a, [wCurItem]
-	ld hl, Table_eeeb
-.next
-	cp [hl]
-	inc hl
-	jr z, .got_it
-	inc hl
-	jr .next
-
-.got_it
-	ld a, [hl]
-	ld c, a
-	ld b, 0
-	ret
-; eeeb
-
-Table_eeeb: ; eeeb
-	db HP_UP,    MON_HP_EXP - MON_STAT_EXP
-	db PROTEIN, MON_ATK_EXP - MON_STAT_EXP
-	db IRON,    MON_DEF_EXP - MON_STAT_EXP
-	db CARBOS,  MON_SPD_EXP - MON_STAT_EXP
-	db CALCIUM, MON_SPC_EXP - MON_STAT_EXP
-; eef5
-
-
-RareCandy_StatBooster_GetParameters: ; eef5
-	ld a, [wCurPartySpecies]
-	ld [wCurSpecies], a
-	ld [wd265], a
-	ld a, MON_LEVEL
-	call GetPartyParamLocation
-	ld a, [hl]
-	ld [wCurPartyLevel], a
-	call GetBaseData
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMonNicknames
-	call GetNick
-	ret
-; 0xef14
-
-
-RareCandyEffect: ; ef14
-	ld b, PARTYMENUACTION_HEALING_ITEM
-	call UseItem_SelectMon
-
-	jp c, RareCandy_StatBooster_ExitMenu
-
-	call RareCandy_StatBooster_GetParameters
-
-	ld a, MON_LEVEL
-	call GetPartyParamLocation
-
-	ld a, [hl]
-	cp MAX_LEVEL
-	jp nc, NoEffectMessage
-
-	inc a
-	ld [hl], a
-	ld [wCurPartyLevel], a
-	push de
-	ld d, a
-	farcall CalcExpAtLevel
-
-	pop de
-	ld a, MON_EXP
-	call GetPartyParamLocation
-
-	ld a, [hMultiplicand]
-	ld [hli], a
-	ld a, [hMultiplicand + 1]
-	ld [hli], a
-	ld a, [hMultiplicand + 2]
-	ld [hl], a
-
-	ld a, MON_MAXHP
-	call GetPartyParamLocation
-	ld a, [hli]
-	ld b, a
-	ld c, [hl]
-	push bc
-	call UpdateStatsAfterItem
-
-	ld a, MON_MAXHP + 1
-	call GetPartyParamLocation
-
-	pop bc
-	ld a, [hld]
-	sub c
-	ld c, a
-	ld a, [hl]
-	sbc b
-	ld b, a
-	dec hl
-	ld a, [hl]
-	add c
-	ld [hld], a
-	ld a, [hl]
-	adc b
-	ld [hl], a
-	farcall LevelUpHappinessMod
-
-	ld a, PARTYMENUTEXT_LEVEL_UP
-	call ItemActionText
-
-	xor a ; PARTYMON
-	ld [wMonType], a
-	predef CopyMonToTempMon
-
-	hlcoord 9, 0
-	ld b, 10
-	ld c, 9
-	call TextBox
-
-	hlcoord 11, 1
-	ld bc, 4
-	predef PrintTempMonStats
-
-	call WaitPressAorB_BlinkCursor
-
-	xor a ; PARTYMON
-	ld [wMonType], a
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	predef LearnLevelMoves
-
-	xor a
-	ld [wForceEvolution], a
-	farcall EvolvePokemon
-
-	jp UseDisposableItem
-; efad
-
-
-HealPowderEffect: ; efad
-	ld b, PARTYMENUACTION_HEALING_ITEM
-	call UseItem_SelectMon
-
-	jp c, StatusHealer_ExitMenu
-
-	call UseStatusHealer
-
-	cp $0
-	jr nz, .asm_efc9
-	ld c, HAPPINESS_BITTERPOWDER
-	farcall ChangeHappiness
-
-	call LooksBitterMessage
-
-	ld a, $0
-
-.asm_efc9
-	jp StatusHealer_Jumptable
-; efcc
-
-
-StatusHealingEffect: ; efcc
-	ld b, PARTYMENUACTION_HEALING_ITEM
-	call UseItem_SelectMon
-	jp c, StatusHealer_ExitMenu
-
-FullyHealStatus: ; efd4
-	call UseStatusHealer
-	jp StatusHealer_Jumptable
-; efda
-
-
-UseStatusHealer: ; efda (3:6fda)
-	call IsMonFainted
-	ld a, $1
-	ret z
-	call GetItemHealingAction
-	ld a, MON_STATUS
-	call GetPartyParamLocation
-	ld a, [hl]
-	and c
-	jr nz, .good
-	call IsItemUsedOnConfusedMon
-	ld a, $1
-	ret nc
-	ld b, PARTYMENUTEXT_HEAL_CONFUSION
-.good
-	xor a
-	ld [hl], a
-	ld a, b
-	ld [wPartyMenuActionText], a
-	call HealStatus
-	call Play_SFX_FULL_HEAL
-	call ItemActionTextWaitButton
-	call UseDisposableItem
-	ld a, $0
-	ret
-
-IsItemUsedOnConfusedMon: ; f009 (3:7009)
-	call IsItemUsedOnBattleMon
-	jr nc, .nope
-	ld a, [wPlayerSubStatus3]
-	bit SUBSTATUS_CONFUSED, a
-	jr z, .nope
-	ld a, c
-	cp $ff
-	jr nz, .nope
-	scf
-	ret
-
-.nope
-	and a
-	ret
-
-BattlemonRestoreHealth: ; f01e (3:701e)
-	call IsItemUsedOnBattleMon
-	ret nc
-	ld a, MON_HP
-	call GetPartyParamLocation
-	ld a, [hli]
-	ld [wBattleMonHP], a
-	ld a, [hld]
-	ld [wBattleMonHP + 1], a
-	ret
-
-HealStatus: ; f030 (3:7030)
-	call IsItemUsedOnBattleMon
-	ret nc
-	xor a
-	ld [wBattleMonStatus], a
-	ld hl, wPlayerSubStatus5
-	res SUBSTATUS_TOXIC, [hl]
-	ld hl, wPlayerSubStatus1
-	res SUBSTATUS_NIGHTMARE, [hl]
-	call GetItemHealingAction
-	ld a, c
-	cp %11111111
-	jr nz, .not_full_heal
-	ld hl, wPlayerSubStatus3
-	res SUBSTATUS_CONFUSED, [hl]
-.not_full_heal
-	push bc
-	farcall CalcPlayerStats
-	pop bc
-	ret
-
-GetItemHealingAction: ; f058 (3:7058)
-	push hl
-	ld a, [wCurItem]
-	ld hl, StatusHealingActions
-	ld bc, 3
-.next
-	cp [hl]
-	jr z, .found_it
-	add hl, bc
-	jr .next
-
-.found_it
-	inc hl
-	ld b, [hl]
-	inc hl
-	ld a, [hl]
-	ld c, a
-	cp %11111111
-	pop hl
-	ret
-; f071 (3:7071)
-
-INCLUDE "data/items/heal_status.asm"
-
-StatusHealer_Jumptable: ; f09e (3:709e)
-	ld hl, .dw
-	rst JumpTable
-	ret
-
-.dw ; f0a3 (3:70a3)
-	dw StatusHealer_ClearPalettes
-	dw StatusHealer_NoEffect
-	dw StatusHealer_ExitMenu
-
-
-RevivalHerbEffect: ; f0a9
-	ld b, PARTYMENUACTION_HEALING_ITEM
-	call UseItem_SelectMon
-	jp c, StatusHealer_ExitMenu
-
-	call RevivePokemon
-	cp 0
-	jr nz, .asm_f0c5
-
-	ld c, HAPPINESS_REVIVALHERB
-	farcall ChangeHappiness
-	call LooksBitterMessage
-	ld a, 0
-
-.asm_f0c5
-	jp StatusHealer_Jumptable
-; f0c8
-
-
-ReviveEffect: ; f0c8
-	ld b, PARTYMENUACTION_HEALING_ITEM
-	call UseItem_SelectMon
-	jp c, StatusHealer_ExitMenu
-
-	call RevivePokemon
-	jp StatusHealer_Jumptable
-; f0d6
-
-
-RevivePokemon: ; f0d6
-	call IsMonFainted
-	ld a, 1
-	ret nz
-	ld a, [wBattleMode]
-	and a
-	jr z, .skip_to_revive
-
-	ld a, [wCurPartyMon]
-	ld c, a
-	ld d, 0
-	ld hl, wBattleParticipantsIncludingFainted
-	ld b, CHECK_FLAG
-	predef SmallFarFlagAction
-	ld a, c
-	and a
-	jr z, .skip_to_revive
-
-	ld a, [wCurPartyMon]
-	ld c, a
-	ld hl, wBattleParticipantsNotFainted
-	ld b, SET_FLAG
-	predef SmallFarFlagAction
-
-.skip_to_revive
-	xor a
-	ld [wLowHealthAlarm], a
-	ld a, [wCurItem]
-	cp REVIVE
-	jr z, .revive_half_hp
-
-	call ReviveFullHP
-	jr .finish_revive
-
-.revive_half_hp
-	call ReviveHalfHP
-
-.finish_revive
-	call HealHP_SFX_GFX
-	ld a, PARTYMENUTEXT_REVIVE
-	ld [wPartyMenuActionText], a
-	call ItemActionTextWaitButton
-	call UseDisposableItem
-	ld a, 0
-	ret
-; f128
-
-
-FullRestoreEffect: ; f128
-	ld b, PARTYMENUACTION_HEALING_ITEM
-	call UseItem_SelectMon
-	jp c, StatusHealer_ExitMenu
-
-	call IsMonFainted
-	jp z, StatusHealer_NoEffect
-
-	call IsMonAtFullHealth
-	jr c, .NotAtFullHealth
-
-	jp FullyHealStatus
-
-.NotAtFullHealth:
-	call .FullRestore
-	jp StatusHealer_Jumptable
-; f144
-
-
-.FullRestore: ; f144
-	xor a
-	ld [wLowHealthAlarm], a
-	call ReviveFullHP
-	ld a, MON_STATUS
-	call GetPartyParamLocation
-	xor a
-	ld [hli], a
-	ld [hl], a
-	call HealStatus
-	call BattlemonRestoreHealth
-	call HealHP_SFX_GFX
-	ld a, PARTYMENUTEXT_HEAL_HP
-	ld [wPartyMenuActionText], a
-	call ItemActionTextWaitButton
-	call UseDisposableItem
-	ld a, 0
-	ret
-; f16a
-
-
-BitterBerryEffect: ; f16a
-	ld hl, wPlayerSubStatus3
-	bit SUBSTATUS_CONFUSED, [hl]
-	ld a, 1
-	jr z, .done
-
-	res SUBSTATUS_CONFUSED, [hl]
-	xor a
-	ld [hBattleTurn], a
-	call UseItemText
-
-	ld hl, ConfusedNoMoreText
-	call StdBattleTextBox
-
-	ld a, 0
-
-.done
-	jp StatusHealer_Jumptable
-; f186
-
-
-RestoreHPEffect: ; f186
-	call ItemRestoreHP
-	jp StatusHealer_Jumptable
-; f18c
-
-
-EnergypowderEffect: ; f18c
-	ld c, HAPPINESS_BITTERPOWDER
-	jr EnergypowderEnergyRootCommon
-; f190
-
-EnergyRootEffect: ; f190
-	ld c, HAPPINESS_ENERGYROOT
-; f192
-
-EnergypowderEnergyRootCommon: ; f192
-	push bc
-	call ItemRestoreHP
-	pop bc
-	cp 0
-	jr nz, .skip_happiness
-
-	farcall ChangeHappiness
-	call LooksBitterMessage
-	ld a, 0
-
-.skip_happiness
-	jp StatusHealer_Jumptable
-; f1a9
-
-
-ItemRestoreHP: ; f1a9 (3:71a9)
-	ld b, PARTYMENUACTION_HEALING_ITEM
-	call UseItem_SelectMon
-	ld a, 2
-	ret c
-
-	call IsMonFainted
-	ld a, 1
-	ret z
-
-	call IsMonAtFullHealth
-	ld a, 1
-	ret nc
-
-	xor a
-	ld [wLowHealthAlarm], a
-	call GetHealingItemAmount
-	call RestoreHealth
-	call BattlemonRestoreHealth
-	call HealHP_SFX_GFX
-	ld a, PARTYMENUTEXT_HEAL_HP
-	ld [wPartyMenuActionText], a
-	call ItemActionTextWaitButton
-	call UseDisposableItem
-	ld a, 0
-	ret
-
-HealHP_SFX_GFX: ; f1db (3:71db)
-	push de
-	ld de, SFX_POTION
-	call WaitPlaySFX
-	pop de
-	ld a, [wCurPartyMon]
-	hlcoord 11, 0
-	ld bc, SCREEN_WIDTH * 2
-	call AddNTimes
-	ld a, $2
-	ld [wWhichHPBar], a
-	predef_jump AnimateHPBar
-
-UseItem_SelectMon: ; f1f9 (3:71f9)
-	call .SelectMon
-	ret c
-
-	ld a, [wCurPartySpecies]
-	cp EGG
-	jr nz, .not_egg
-
-	call CantUseOnEggMessage
-	scf
-	ret
-
-.not_egg
-	and a
-	ret
-
-.SelectMon: ; f20b (3:720b)
-	ld a, b
-	ld [wPartyMenuActionText], a
-	push hl
-	push de
-	push bc
-	call ClearBGPalettes
-	call ChooseMonToUseItemOn
-	pop bc
-	pop de
-	pop hl
-	ret
-
-ChooseMonToUseItemOn: ; f21c (3:721c)
-	farcall LoadPartyMenuGFX
-	farcall InitPartyMenuWithCancel
-	farcall InitPartyMenuGFX
-	farcall WritePartyMenuTilemap
-	farcall PrintPartyMenuText
-	call WaitBGMap
-	call SetPalettes
-	call DelayFrame
-	farcall PartyMenuSelect
-	ret
-
-ItemActionText: ; f24a (3:724a)
-	ld [wPartyMenuActionText], a
-	ld a, [wCurPartySpecies]
-	push af
-	ld a, [wCurPartyMon]
-	push af
-	push hl
-	push de
-	push bc
-	farcall WritePartyMenuTilemap
-	farcall PrintPartyMenuActionText
-	call WaitBGMap
-	call SetPalettes
-	call DelayFrame
-	pop bc
-	pop de
-	pop hl
-	pop af
-	ld [wCurPartyMon], a
-	pop af
-	ld [wCurPartySpecies], a
-	ret
-
-ItemActionTextWaitButton: ; f279 (3:7279)
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 0, 0
-	ld bc, wTileMapEnd - wTileMap
-	ld a, " "
-	call ByteFill
-	ld a, [wPartyMenuActionText]
-	call ItemActionText
-	ld a, $1
-	ld [hBGMapMode], a
-	ld c, 50
-	call DelayFrames
-	jp WaitPressAorB_BlinkCursor
-
-StatusHealer_NoEffect: ; f299 (3:7299)
-	call WontHaveAnyEffectMessage
-	jr StatusHealer_ClearPalettes
-
-StatusHealer_ExitMenu: ; f29e (3:729e)
-	xor a
-	ld [wItemEffectSucceeded], a
-StatusHealer_ClearPalettes: ; f2a2 (3:72a2)
-	call ClearPalettes
-	ret
-
-IsItemUsedOnBattleMon: ; f2a6 (3:72a6)
-	ld a, [wBattleMode]
-	and a
-	ret z
-	ld a, [wCurPartyMon]
-	push hl
-	ld hl, wCurBattleMon
-	cp [hl]
-	pop hl
-	jr nz, .nope
-	scf
-	ret
-
-.nope
-	xor a
-	ret
-
-ReviveHalfHP: ; f2ba (3:72ba)
-	call LoadHPFromBuffer1
-	srl d
-	rr e
-	jr ContinueRevive
-
-ReviveFullHP: ; f2c3 (3:72c3)
-	call LoadHPFromBuffer1
-ContinueRevive: ; f2c6 (3:72c6)
-	ld a, MON_HP
-	call GetPartyParamLocation
-	ld [hl], d
-	inc hl
-	ld [hl], e
-	jp LoadCurHPIntoBuffer5
-
-RestoreHealth: ; f2d1 (3:72d1)
-	ld a, MON_HP + 1
-	call GetPartyParamLocation
-	ld a, [hl]
-	add e
-	ld [hld], a
-	ld a, [hl]
-	adc d
-	ld [hl], a
-	jr c, .full_hp
-	call LoadCurHPIntoBuffer5
-	ld a, MON_HP + 1
-	call GetPartyParamLocation
-	ld d, h
-	ld e, l
-	ld a, MON_MAXHP + 1
-	call GetPartyParamLocation
-	ld a, [de]
-	sub [hl]
-	dec de
-	dec hl
-	ld a, [de]
-	sbc [hl]
-	jr c, .finish
-.full_hp
-	call ReviveFullHP
-.finish
-	ret
-
-RemoveHP: ; f2f9 (3:72f9)
-	ld a, MON_HP + 1
-	call GetPartyParamLocation
-	ld a, [hl]
-	sub e
-	ld [hld], a
-	ld a, [hl]
-	sbc d
-	ld [hl], a
-	jr nc, .okay
-	xor a
-	ld [hld], a
-	ld [hl], a
-.okay
-	call LoadCurHPIntoBuffer5
-	ret
-
-IsMonFainted: ; f30d (3:730d)
-	push de
-	call LoadMaxHPToBuffer1
-	call LoadCurHPToBuffer3
-	call LoadHPFromBuffer3
-	ld a, d
-	or e
-	pop de
-	ret
-
-IsMonAtFullHealth: ; f31b (3:731b)
-	call LoadHPFromBuffer3
-	ld h, d
-	ld l, e
-	call LoadHPFromBuffer1
-	ld a, l
-	sub e
-	ld a, h
-	sbc d
-	ret
-
-LoadCurHPIntoBuffer5: ; f328 (3:7328)
-	ld a, MON_HP
-	call GetPartyParamLocation
-	ld a, [hli]
-	ld [wBuffer6], a
-	ld a, [hl]
-	ld [wBuffer5], a
-	ret
-; f336 (3:7336)
-
-LoadHPIntoBuffer5: ; f336
-	ld a, d
-	ld [wBuffer6], a
-	ld a, e
-	ld [wBuffer5], a
-	ret
-; f33f
-
-LoadHPFromBuffer5: ; f33f
-	ld a, [wBuffer6]
-	ld d, a
-	ld a, [wBuffer5]
-	ld e, a
-	ret
-; f348
-
-LoadCurHPToBuffer3: ; f348 (3:7348)
-	ld a, MON_HP
-	call GetPartyParamLocation
-	ld a, [hli]
-	ld [wBuffer4], a
-	ld a, [hl]
-	ld [wBuffer3], a
-	ret
-
-LoadHPFromBuffer3: ; f356 (3:7356)
-	ld a, [wBuffer4]
-	ld d, a
-	ld a, [wBuffer3]
-	ld e, a
-	ret
-
-LoadMaxHPToBuffer1: ; f35f (3:735f)
-	push hl
-	ld a, MON_MAXHP
-	call GetPartyParamLocation
-	ld a, [hli]
-	ld [wBuffer2], a
-	ld a, [hl]
-	ld [wBuffer1], a
-	pop hl
-	ret
-
-LoadHPFromBuffer1: ; f36f (3:736f)
-	ld a, [wBuffer2]
-	ld d, a
-	ld a, [wBuffer1]
-	ld e, a
-	ret
-
-GetOneFifthMaxHP: ; f378 (3:7378)
-	push bc
-	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, [hQuotient + 1]
-	ld d, a
-	ld a, [hQuotient + 2]
-	ld e, a
-	pop bc
-	ret
-
-GetHealingItemAmount: ; f395 (3:7395)
-	push hl
-	ld a, [wCurItem]
-	ld hl, HealingHPAmounts
-	ld d, a
-.next
-	ld a, [hli]
-	cp -1
-	jr z, .NotFound
-	cp d
-	jr z, .done
-	inc hl
-	inc hl
-	jr .next
-
-.NotFound:
-	scf
-.done
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	pop hl
-	ret
-; f3af (3:73af)
-
-INCLUDE "data/items/heal_hp.asm"
-
-Softboiled_MilkDrinkFunction: ; f3df (3:73df)
-; Softboiled/Milk Drink in the field
-	ld a, [wPartyMenuCursor]
-	dec a
-	ld b, a
-	call .SelectMilkDrinkRecipient ; select pokemon
-	jr c, .skip
-	ld a, b
-	ld [wCurPartyMon], a
-	call IsMonFainted
-	call GetOneFifthMaxHP
-	call RemoveHP
-	push bc
-	call HealHP_SFX_GFX
-	pop bc
-	call GetOneFifthMaxHP
-	ld a, c
-	ld [wCurPartyMon], a
-	call IsMonFainted
-	call RestoreHealth
-	call HealHP_SFX_GFX
-	ld a, PARTYMENUTEXT_HEAL_HP
-	call ItemActionText
-	call JoyWaitAorB
-.skip
-	ld a, b
-	inc a
-	ld [wPartyMenuCursor], a
-	ret
-
-.SelectMilkDrinkRecipient: ; f419 (3:7419)
-.loop
-	push bc
-	ld a, PARTYMENUACTION_HEALING_ITEM
-	ld [wPartyMenuActionText], a
-	call ChooseMonToUseItemOn
-	pop bc
-	jr c, .set_carry
-	ld a, [wPartyMenuCursor]
-	dec a
-	ld c, a
-	ld a, b
-	cp c
-	jr z, .cant_use ; chose the same mon as user
-	ld a, c
-	ld [wCurPartyMon], a
-	call IsMonFainted
-	jr z, .cant_use
-	call IsMonAtFullHealth
-	jr nc, .cant_use
-	xor a
-	ret
-
-.set_carry
-	scf
-	ret
-
-.cant_use
-	push bc
-	ld hl, .Text_CantBeUsed
-	call MenuTextBoxBackup
-	pop bc
-	jr .loop
-; f44a (3:744a)
-
-.Text_CantBeUsed: ; 0xf44a
-	; That can't be used on this #MON.
-	text_jump UnknownText_0x1c5bac
-	db "@"
-; 0xf44f
-
-
-EscapeRopeEffect: ; f44f
-	xor a
-	ld [wItemEffectSucceeded], a
-	farcall EscapeRopeFunction
-
-	ld a, [wItemEffectSucceeded]
-	cp 1
-	call z, UseDisposableItem
-	ret
-; f462
-
-
-SuperRepelEffect: ; f462
-	ld b, 200
-	jr UseRepel
-; f466
-
-MaxRepelEffect: ; f466
-	ld b, 250
-	jr UseRepel
-; f466
-
-RepelEffect: ; f46a
-	ld b, 100
-; f46c
-
-UseRepel: ; f46c
-	ld a, [wRepelEffect]
-	and a
-	ld hl, TextJump_RepelUsedEarlierIsStillInEffect
-	jp nz, PrintText
-
-	ld a, b
-	ld [wRepelEffect], a
-	jp UseItemText
-
-
-TextJump_RepelUsedEarlierIsStillInEffect: ; 0xf47d
-	; The REPEL used earlier is still in effect.
-	text_jump Text_RepelUsedEarlierIsStillInEffect
-	db "@"
-; 0xf482
-
-
-XAccuracyEffect: ; f482
-	ld hl, wPlayerSubStatus4
-	bit SUBSTATUS_X_ACCURACY, [hl]
-	jp nz, WontHaveAnyEffect_NotUsedMessage
-	set SUBSTATUS_X_ACCURACY, [hl]
-	jp UseItemText
-; f48f
-
-
-PokeDollEffect: ; f48f
-	ld a, [wBattleMode]
-	dec a
-	jr nz, .asm_f4a6
-	inc a
-	ld [wForcedSwitch], a
-	ld a, [wBattleResult]
-	and $c0
-	or $2
-	ld [wBattleResult], a
-	jp UseItemText
-
-.asm_f4a6
-	xor a
-	ld [wItemEffectSucceeded], a
-	ret
-; f4ab
-
-
-GuardSpecEffect: ; f4ab
-	ld hl, wPlayerSubStatus4
-	bit SUBSTATUS_MIST, [hl]
-	jp nz, WontHaveAnyEffect_NotUsedMessage
-	set SUBSTATUS_MIST, [hl]
-	jp UseItemText
-; f4b8
-
-
-DireHitEffect: ; f4b8
-	ld hl, wPlayerSubStatus4
-	bit SUBSTATUS_FOCUS_ENERGY, [hl]
-	jp nz, WontHaveAnyEffect_NotUsedMessage
-	set SUBSTATUS_FOCUS_ENERGY, [hl]
-	jp UseItemText
-; f4c5
-
-
-XItemEffect: ; f4c5
-	call UseItemText
-
-	ld a, [wCurItem]
-	ld hl, XItemStats
-
-.loop
-	cp [hl]
-	jr z, .got_it
-	inc hl
-	inc hl
-	jr .loop
-
-.got_it
-	inc hl
-	ld b, [hl]
-	xor a
-	ld [hBattleTurn], a
-	ld [wAttackMissed], a
-	ld [wEffectFailed], a
-	farcall CheckIfStatCanBeRaised
-	call WaitSFX
-
-	farcall BattleCommand_StatUpMessage
-	farcall BattleCommand_StatUpFailText
-
-	ld a, [wCurBattleMon]
-	ld [wCurPartyMon], a
-	ld c, HAPPINESS_USEDXITEM
-	farcall ChangeHappiness
-	ret
-; f504
-
-INCLUDE "data/items/x_stats.asm"
-
-
-PokeFluteEffect: ; f50c
-	ld a, [wBattleMode]
-	and a
-	jr nz, .dummy
-.dummy
-
-	xor a
-	ld [wd002], a
-
-	ld b, $ff ^ SLP
-
-	ld hl, wPartyMon1Status
-	call .CureSleep
-
-	ld a, [wBattleMode]
-	cp WILD_BATTLE
-	jr z, .skip_otrainer
-	ld hl, wOTPartyMon1Status
-	call .CureSleep
-.skip_otrainer
-
-	ld hl, wBattleMonStatus
-	ld a, [hl]
-	and b
-	ld [hl], a
-	ld hl, wEnemyMonStatus
-	ld a, [hl]
-	and b
-	ld [hl], a
-
-	ld a, [wd002]
-	and a
-	ld hl, .CatchyTune
-	jp z, PrintText
-	ld hl, .PlayedTheFlute
-	call PrintText
-
-	ld a, [wLowHealthAlarm]
-	and 1 << DANGER_ON_F
-	jr nz, .dummy2
-.dummy2
-	ld hl, .AllSleepingMonWokeUp
-	jp PrintText
-
-
-.CureSleep:
-	ld de, PARTYMON_STRUCT_LENGTH
-	ld c, PARTY_LENGTH
-
-.loop
-	ld a, [hl]
-	push af
-	and SLP
-	jr z, .not_asleep
-	ld a, 1
-	ld [wd002], a
-.not_asleep
-	pop af
-	and b
-	ld [hl], a
-	add hl, de
-	dec c
-	jr nz, .loop
-	ret
-; f56c
-
-
-.CatchyTune: ; 0xf56c
-	; Played the # FLUTE. Now, that's a catchy tune!
-	text_jump UnknownText_0x1c5bf9
-	db "@"
-; 0xf571
-
-.AllSleepingMonWokeUp: ; 0xf571
-	; All sleeping #MON woke up.
-	text_jump UnknownText_0x1c5c28
-	db "@"
-; 0xf576
-
-.PlayedTheFlute: ; 0xf576
-	; played the # FLUTE.@ @
-	text_jump UnknownText_0x1c5c44
-	start_asm
-	ld a, [wBattleMode]
-	and a
-	jr nz, .battle
-
-	push de
-	ld de, SFX_POKEFLUTE
-	call WaitPlaySFX
-	call WaitSFX
-	pop de
-
-.battle
-	jp PokeFluteTerminatorCharacter
-; f58f
-
-
-BlueCardEffect: ; f58f
-	ld hl, .bluecardtext
-	jp MenuTextBoxWaitButton
-
-.bluecardtext
-	text_jump UnknownText_0x1c5c5e
-	db "@"
-; f59a
-
-
-CoinCaseEffect: ; f59a
-	ld hl, .coincasetext
-	jp MenuTextBoxWaitButton
-
-.coincasetext
-	text_jump UnknownText_0x1c5c7b
-	db "@"
-; f5a5
-
-
-OldRodEffect: ; f5a5
-	ld e, $0
-	jr UseRod
-; f5a9
-
-GoodRodEffect: ; f5a9
-	ld e, $1
-	jr UseRod
-; f5ad
-
-SuperRodEffect: ; f5ad
-	ld e, $2
-	jr UseRod
-; f5b1
-
-UseRod: ; f5b1
-	farcall FishFunction
-	ret
-; f5b8
-
-
-ItemfinderEffect: ; f5b8
-	farcall ItemFinder
-	ret
-; f5bf
-
-
-RestorePPEffect: ; f5bf
-	ld a, [wCurItem]
-	ld [wd002], a
-
-.loop
-	; Party Screen opens to choose on which mon to use the Item
-	ld b, PARTYMENUACTION_HEALING_ITEM
-	call UseItem_SelectMon
-	jp c, PPRestoreItem_Cancel
-
-.loop2
-	ld a, [wd002]
-	cp MAX_ELIXER
-	jp z, Elixer_RestorePPofAllMoves
-	cp ELIXER
-	jp z, Elixer_RestorePPofAllMoves
-
-	ld hl, TextJump_RaiseThePPOfWhichMove
-	ld a, [wd002]
-	cp PP_UP
-	jr z, .ppup
-	ld hl, TextJump_RestoreThePPOfWhichMove
-
-.ppup
-	call PrintText
-
-	ld a, [wCurMoveNum]
-	push af
-	xor a
-	ld [wCurMoveNum], a
-	ld a, $2
-	ld [wMoveSelectionMenuType], a
-	farcall MoveSelectionScreen
-	pop bc
-
-	ld a, b
-	ld [wCurMoveNum], a
-	jr nz, .loop
-	ld hl, wPartyMon1Moves
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call GetMthMoveOfNthPartymon
-
-	push hl
-	ld a, [hl]
-	ld [wd265], a
-	call GetMoveName
-	call CopyName1
-	pop hl
-
-	ld a, [wd002]
-	cp PP_UP
-	jp nz, Not_PP_Up
-
-	ld a, [hl]
-	cp SKETCH
-	jr z, .CantUsePPUpOnSketch
-
-	ld bc, MON_PP - MON_MOVES
-	add hl, bc
-	ld a, [hl]
-	cp PP_UP_MASK
-	jr c, .do_ppup
-
-.CantUsePPUpOnSketch:
-.pp_is_maxed_out
-	ld hl, TextJump_PPIsMaxedOut
-	call PrintText
-	jr .loop2
-
-.do_ppup
-	ld a, [hl]
-	add PP_UP_ONE
-	ld [hl], a
-	ld a, $1
-	ld [wd265], a
-	call ApplyPPUp
-	call Play_SFX_FULL_HEAL
-
-	ld hl, TextJump_PPsIncreased
-	call PrintText
-
-FinishPPRestore: ; f64c
-	call ClearPalettes
-	jp UseDisposableItem
-; f652
-
-BattleRestorePP: ; f652
-	ld a, [wBattleMode]
-	and a
-	jr z, .not_in_battle
-	ld a, [wCurPartyMon]
-	ld b, a
-	ld a, [wCurBattleMon]
-	cp b
-	jr nz, .not_in_battle
-	ld a, [wPlayerSubStatus5]
-	bit SUBSTATUS_TRANSFORMED, a
-	jr nz, .not_in_battle
-	call .UpdateBattleMonPP
-
-.not_in_battle
-	call Play_SFX_FULL_HEAL
-	ld hl, UnknownText_0xf739
-	call PrintText
-	jr FinishPPRestore
-
-.UpdateBattleMonPP:
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1Moves
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld de, wBattleMonMoves
-	ld b, NUM_MOVES
-.loop
-	ld a, [de]
-	and a
-	jr z, .done
-	cp [hl]
-	jr nz, .next
-	push hl
-	push de
-	push bc
-	rept NUM_MOVES + 2 ; wBattleMonPP - wBattleMonMoves
-	inc de
-	endr
-	ld bc, MON_PP - MON_MOVES
-	add hl, bc
-	ld a, [hl]
-	ld [de], a
-	pop bc
-	pop de
-	pop hl
-
-.next
-	inc hl
-	inc de
-	dec b
-	jr nz, .loop
-
-.done
-	ret
-; f6a7
-
-Not_PP_Up: ; f6a7
-	call RestorePP
-	jr nz, BattleRestorePP
-	jp PPRestoreItem_NoEffect
-; f6af
-
-Elixer_RestorePPofAllMoves: ; f6af
-	xor a
-	ld hl, wMenuCursorY
-	ld [hli], a
-	ld [hl], a
-	ld b, NUM_MOVES
-.moveLoop
-	push bc
-	ld hl, wPartyMon1Moves
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call GetMthMoveOfNthPartymon
-	ld a, [hl]
-	and a
-	jr z, .next
-
-	call RestorePP
-	jr z, .next
-	ld hl, wMenuCursorX
-	inc [hl]
-
-.next
-	ld hl, wMenuCursorY
-	inc [hl]
-	pop bc
-	dec b
-	jr nz, .moveLoop
-	ld a, [wMenuCursorX]
-	and a
-	jp nz, BattleRestorePP
-
-PPRestoreItem_NoEffect: ; f6dd
-	call WontHaveAnyEffectMessage
-
-PPRestoreItem_Cancel: ; f6e0
-	call ClearPalettes
-	xor a
-	ld [wItemEffectSucceeded], a
-	ret
-; f6e8
-
-RestorePP: ; f6e8
-	xor a ; PARTYMON
-	ld [wMonType], a
-	call GetMaxPPOfMove
-	ld hl, wPartyMon1PP
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call GetMthMoveOfNthPartymon
-	ld a, [wd265]
-	ld b, a
-	ld a, [hl]
-	and PP_MASK
-	cp b
-	jr nc, .dont_restore
-
-	ld a, [wd002]
-	cp MAX_ELIXER
-	jr z, .restore_all
-	cp MAX_ETHER
-	jr z, .restore_all
-
-	ld c, 5
-	cp MYSTERYBERRY
-	jr z, .restore_some
-
-	ld c, 10
-
-.restore_some
-	ld a, [hl]
-	and PP_MASK
-	add c
-	cp b
-	jr nc, .restore_all
-	ld b, a
-
-.restore_all
-	ld a, [hl]
-	and PP_UP_MASK
-	or b
-	ld [hl], a
-	ret
-
-.dont_restore
-	xor a
-	ret
-; f725
-
-TextJump_RaiseThePPOfWhichMove: ; 0xf725
-	; Raise the PP of which move?
-	text_jump Text_RaiseThePPOfWhichMove
-	db "@"
-; 0xf72a
-
-TextJump_RestoreThePPOfWhichMove: ; 0xf72a
-	; Restore the PP of which move?
-	text_jump Text_RestoreThePPOfWhichMove
-	db "@"
-; 0xf72f
-
-TextJump_PPIsMaxedOut: ; 0xf72f
-	; 's PP is maxed out.
-	text_jump Text_PPIsMaxedOut
-	db "@"
-; 0xf734
-
-TextJump_PPsIncreased: ; 0xf734
-	; 's PP increased.
-	text_jump Text_PPsIncreased
-	db "@"
-; 0xf739
-
-UnknownText_0xf739: ; 0xf739
-	; PP was restored.
-	text_jump UnknownText_0x1c5cf1
-	db "@"
-; 0xf73e
-
-
-SquirtbottleEffect: ; f73e
-	farcall _Squirtbottle
-	ret
-; f745
-
-
-CardKeyEffect: ; f745
-	farcall _CardKey
-	ret
-; f74c
-
-
-BasementKeyEffect: ; f74c
-	farcall _BasementKey
-	ret
-; f753
-
-
-SacredAshEffect: ; f753
-	farcall _SacredAsh
-	ld a, [wItemEffectSucceeded]
-	cp $1
-	ret nz
-	call UseDisposableItem
-	ret
-; f763
-
-
-NormalBoxEffect: ; f763
-	ld c, DECOFLAG_SILVER_TROPHY_DOLL
-	jr OpenBox
-; f767
-
-GorgeousBoxEffect: ; f767
-	ld c, DECOFLAG_GOLD_TROPHY_DOLL
-OpenBox: ; f769
-	farcall SetSpecificDecorationFlag
-
-	ld hl, .text
-	call PrintText
-
-	jp UseDisposableItem
-; f778
-
-.text ; 0xf778
-	; There was a trophy inside!
-	text_jump UnknownText_0x1c5d03
-	db "@"
-; 0xf77d
-
-NoEffect: ; f77d
-	jp IsntTheTimeMessage
-; f780
-
-
-Play_SFX_FULL_HEAL: ; f780
-	push de
-	ld de, SFX_FULL_HEAL
-	call WaitPlaySFX
-	pop de
-	ret
-; f789
-
-UseItemText: ; f789
-	ld hl, UsedItemText
-	call PrintText
-	call Play_SFX_FULL_HEAL
-	call WaitPressAorB_BlinkCursor
-UseDisposableItem: ; f795
-	ld hl, wNumItems
-	ld a, 1
-	ld [wItemQuantityChangeBuffer], a
-	jp TossItem
-; f7a0
-
-UseBallInTrainerBattle: ; f7a0
-	call ReturnToBattle_UseBall
-	ld de, ANIM_THROW_POKE_BALL
-	ld a, e
-	ld [wFXAnimID], a
-	ld a, d
-	ld [wFXAnimID + 1], a
-	xor a
-	ld [wBattleAnimParam], a
-	ld [hBattleTurn], a
-	ld [wNumHits], a
-	predef PlayBattleAnim
-	ld hl, BlockedTheBallText
-	call PrintText
-	ld hl, DontBeAThiefText
-	call PrintText
-	jr UseDisposableItem
-; f7ca
-
-WontHaveAnyEffect_NotUsedMessage: ; f7ca
-	ld hl, WontHaveAnyEffectText
-	call PrintText
-
-	; Item wasn't used.
-	ld a, $2
-	ld [wItemEffectSucceeded], a
-	ret
-; f7d6
-
-LooksBitterMessage: ; f7d6
-	ld hl, LooksBitterText
-	jp PrintText
-; f7dc
-
-Ball_BoxIsFullMessage: ; f7dc
-	ld hl, Ball_BoxIsFullText
-	call PrintText
-
-	; Item wasn't used.
-	ld a, $2
-	ld [wItemEffectSucceeded], a
-	ret
-; f7e8
-
-CantUseOnEggMessage: ; f7e8
-	ld hl, CantUseOnEggText
-	jr CantUseItemMessage
-
-IsntTheTimeMessage: ; f7ed
-	ld hl, IsntTheTimeText
-	jr CantUseItemMessage
-
-WontHaveAnyEffectMessage: ; f7f2
-	ld hl, WontHaveAnyEffectText
-	jr CantUseItemMessage
-
-BelongsToSomeoneElseMessage: ; f7f7
-	ld hl, BelongsToSomeoneElseText
-	jr CantUseItemMessage
-
-CyclingIsntAllowedMessage: ; f7fc
-	ld hl, CyclingIsntAllowedText
-	jr CantUseItemMessage
-
-CantGetOnYourBikeMessage: ; f801
-	ld hl, CantGetOnYourBikeText
-
-CantUseItemMessage: ; f804
-; Item couldn't be used.
-	xor a
-	ld [wItemEffectSucceeded], a
-	jp PrintText
-; f80b
-
-LooksBitterText: ; 0xf80b
-	; It looks bitter…
-	text_jump UnknownText_0x1c5d3e
-	db "@"
-; 0xf810
-
-CantUseOnEggText: ; 0xf810
-	; That can't be used on an EGG.
-	text_jump UnknownText_0x1c5d50
-	db "@"
-; 0xf815
-
-IsntTheTimeText: ; 0xf815
-	; OAK:  ! This isn't the time to use that!
-	text_jump UnknownText_0x1c5d6e
-	db "@"
-; 0xf81a
-
-BelongsToSomeoneElseText: ; 0xf81a
-	; That belongs to someone else!
-	text_jump UnknownText_0x1c5d97
-	db "@"
-; 0xf81f
-
-WontHaveAnyEffectText: ; 0xf81f
-	; It won't have any effect.
-	text_jump UnknownText_0x1c5db6
-	db "@"
-; 0xf824
-
-BlockedTheBallText: ; 0xf824
-	; The trainer blocked the BALL!
-	text_jump UnknownText_0x1c5dd0
-	db "@"
-; 0xf829
-
-DontBeAThiefText: ; 0xf829
-	; Don't be a thief!
-	text_jump UnknownText_0x1c5def
-	db "@"
-; 0xf82e
-
-CyclingIsntAllowedText: ; 0xf82e
-	; Cycling isn't allowed here.
-	text_jump UnknownText_0x1c5e01
-	db "@"
-; 0xf833
-
-CantGetOnYourBikeText: ; 0xf833
-	; Can't get on your @  now.
-	text_jump UnknownText_0x1c5e1d
-	db "@"
-; 0xf838
-
-Ball_BoxIsFullText: ; 0xf838
-	; The #MON BOX is full. That can't be used now.
-	text_jump UnknownText_0x1c5e3a
-	db "@"
-; 0xf83d
-
-UsedItemText: ; 0xf83d
-	; used the@ .
-	text_jump UnknownText_0x1c5e68
-	db "@"
-; 0xf842
-
-GotOnTheItemText: ; 0xf842
-	; got on the@ .
-	text_jump UnknownText_0x1c5e7b
-	db "@"
-; 0xf847
-
-GotOffTheItemText: ; 0xf847
-	; got off@ the @ .
-	text_jump UnknownText_0x1c5e90
-	db "@"
-; 0xf84c
-
-
-ApplyPPUp: ; f84c
-	ld a, MON_MOVES
-	call GetPartyParamLocation
-	push hl
-	ld de, wBuffer1
-	predef FillPP
-	pop hl
-	ld bc, MON_PP - MON_MOVES
-	add hl, bc
-	ld de, wBuffer1
-	ld b, 0
-.loop
-	inc b
-	ld a, b
-	cp NUM_MOVES + 1
-	ret z
-	ld a, [wd265]
-	dec a
-	jr nz, .use
-	ld a, [wMenuCursorY]
-	inc a
-	cp b
-	jr nz, .skip
-
-.use
-	ld a, [hl]
-	and PP_UP_MASK
-	ld a, [de] ; wasted cycle
-	call nz, ComputeMaxPP
-
-.skip
-	inc hl
-	inc de
-	jr .loop
-; f881
-
-
-
-ComputeMaxPP: ; f881
-	push bc
-	; Divide the base PP by 5.
-	ld a, [de]
-	ld [hDividend + 3], a
-	xor a
-	ld [hDividend], a
-	ld [hDividend + 1], a
-	ld [hDividend + 2], a
-	ld a, 5
-	ld [hDivisor], a
-	ld b, 4
-	call Divide
-	; Get the number of PP, which are bits 6 and 7 of the PP value stored in RAM.
-	ld a, [hl]
-	ld b, a
-	swap a
-	and $f
-	srl a
-	srl a
-	ld c, a
-	; If this value is 0, we are done
-	and a
-	jr z, .NoPPUp
-
-.loop
-	; Normally, a move with 40 PP would have 64 PP with three PP Ups.
-	; Since this would overflow into bit 6, we prevent that from happening
-	; by decreasing the extra amount of PP each PP Up provides, resulting
-	; in a maximum of 61.
-	ld a, [hQuotient + 2]
-	cp $8
-	jr c, .okay
-	ld a, $7
-
-.okay
-	add b
-	ld b, a
-	ld a, [wd265]
-	dec a
-	jr z, .NoPPUp
-	dec c
-	jr nz, .loop
-
-.NoPPUp:
-	ld [hl], b
-	pop bc
-	ret
-; f8b9
-
-RestoreAllPP: ; f8b9
-	ld a, MON_PP
-	call GetPartyParamLocation
-	push hl
-	ld a, MON_MOVES
-	call GetPartyParamLocation
-	pop de
-	xor a ; PARTYMON
-	ld [wMenuCursorY], a
-	ld [wMonType], a
-	ld c, NUM_MOVES
-.loop
-	ld a, [hli]
-	and a
-	ret z
-	push hl
-	push de
-	push bc
-	call GetMaxPPOfMove
-	pop bc
-	pop de
-	ld a, [de]
-	and PP_UP_MASK
-	ld b, a
-	ld a, [wd265]
-	add b
-	ld [de], a
-	inc de
-	ld hl, wMenuCursorY
-	inc [hl]
-	pop hl
-	dec c
-	jr nz, .loop
-	ret
-; f8ec
-
-
-GetMaxPPOfMove: ; f8ec
-	ld a, [wStringBuffer1 + 0]
-	push af
-	ld a, [wStringBuffer1 + 1]
-	push af
-
-	ld a, [wMonType]
-	and a
-
-	ld hl, wPartyMon1Moves
-	ld bc, PARTYMON_STRUCT_LENGTH
-	jr z, .got_partymon ; PARTYMON
-
-	ld hl, wOTPartyMon1Moves
-	dec a
-	jr z, .got_partymon ; OTPARTYMON
-
-	ld hl, wTempMonMoves
-	dec a
-	jr z, .got_nonpartymon ; BOXMON
-
-	ld hl, wTempMonMoves ; Wasted cycles
-	dec a
-	jr z, .got_nonpartymon ; TEMPMON
-
-	ld hl, wBattleMonMoves ; WILDMON
-
-.got_nonpartymon ; BOXMON, TEMPMON, WILDMON
-	call GetMthMoveOfCurrentMon
-	jr .gotdatmove
-
-.got_partymon ; PARTYMON, OTPARTYMON
-	call GetMthMoveOfNthPartymon
-
-.gotdatmove
-	ld a, [hl]
-	dec a
-
-	push hl
-	ld hl, Moves + MOVE_PP
-	ld bc, MOVE_LENGTH
-	call AddNTimes
-	ld a, BANK(Moves)
-	call GetFarByte
-	ld b, a
-	ld de, wStringBuffer1
-	ld [de], a
-	pop hl
-
-	push bc
-	ld bc, MON_PP - MON_MOVES
-	ld a, [wMonType]
-	cp WILDMON
-	jr nz, .notwild
-	ld bc, wEnemyMonPP - wEnemyMonMoves
-.notwild
-	add hl, bc
-	ld a, [hl]
-	and PP_UP_MASK
-	pop bc
-
-	or b
-	ld hl, wStringBuffer1 + 1
-	ld [hl], a
-	xor a
-	ld [wd265], a
-	ld a, b ; this gets lost anyway
-	call ComputeMaxPP
-	ld a, [hl]
-	and PP_MASK
-	ld [wd265], a
-
-	pop af
-	ld [wStringBuffer1 + 1], a
-	pop af
-	ld [wStringBuffer1 + 0], a
-	ret
-; f963
-
-GetMthMoveOfNthPartymon: ; f963
-	ld a, [wCurPartyMon]
-	call AddNTimes
-
-GetMthMoveOfCurrentMon: ; f969
-	ld a, [wMenuCursorY]
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ret
-; f971
--- a/engine/items.asm
+++ /dev/null
@@ -1,581 +1,0 @@
-_ReceiveItem:: ; d1d5
-	call DoesHLEqualNumItems
-	jp nz, PutItemInPocket
-	push hl
-	call CheckItemPocket
-	pop de
-	ld a, [wItemAttributeParamBuffer]
-	dec a
-	ld hl, .Pockets
-	rst JumpTable
-	ret
-
-.Pockets: ; d1e9
-; entries correspond to item types
-	dw .Item
-	dw .KeyItem
-	dw .Ball
-	dw .TMHM
-
-.Item: ; d1f1
-	ld h, d
-	ld l, e
-	jp PutItemInPocket
-
-.KeyItem: ; d1f6
-	ld h, d
-	ld l, e
-	jp ReceiveKeyItem
-
-.Ball: ; d1fb
-	ld hl, wNumBalls
-	jp PutItemInPocket
-
-.TMHM: ; d201
-	ld h, d
-	ld l, e
-	ld a, [wCurItem]
-	ld c, a
-	call GetTMHMNumber
-	jp ReceiveTMHM
-
-_TossItem:: ; d20d
-	call DoesHLEqualNumItems
-	jr nz, .remove
-	push hl
-	call CheckItemPocket
-	pop de
-	ld a, [wItemAttributeParamBuffer]
-	dec a
-	ld hl, .Pockets
-	rst JumpTable
-	ret
-
-.Pockets:
-; entries correspond to item types
-	dw .Item
-	dw .KeyItem
-	dw .Ball
-	dw .TMHM
-
-.Ball: ; d228
-	ld hl, wNumBalls
-	jp RemoveItemFromPocket
-
-.TMHM: ; d22e
-	ld h, d
-	ld l, e
-	ld a, [wCurItem]
-	ld c, a
-	call GetTMHMNumber
-	jp TossTMHM
-
-.KeyItem: ; d23a
-	ld h, d
-	ld l, e
-	jp TossKeyItem
-
-.Item: ; d23f
-	ld h, d
-	ld l, e
-
-.remove
-	jp RemoveItemFromPocket
-
-_CheckItem:: ; d244
-	call DoesHLEqualNumItems
-	jr nz, .nope
-	push hl
-	call CheckItemPocket
-	pop de
-	ld a, [wItemAttributeParamBuffer]
-	dec a
-	ld hl, .Pockets
-	rst JumpTable
-	ret
-
-.Pockets:
-; entries correspond to item types
-	dw .Item
-	dw .KeyItem
-	dw .Ball
-	dw .TMHM
-
-.Ball: ; d25f
-	ld hl, wNumBalls
-	jp CheckTheItem
-
-.TMHM: ; d265
-	ld h, d
-	ld l, e
-	ld a, [wCurItem]
-	ld c, a
-	call GetTMHMNumber
-	jp CheckTMHM
-
-.KeyItem: ; d271
-	ld h, d
-	ld l, e
-	jp CheckKeyItems
-
-.Item: ; d276
-	ld h, d
-	ld l, e
-
-.nope
-	jp CheckTheItem
-
-DoesHLEqualNumItems: ; d27b
-	ld a, l
-	cp LOW(wNumItems)
-	ret nz
-	ld a, h
-	cp HIGH(wNumItems)
-	ret
-
-GetPocketCapacity: ; d283
-	ld c, MAX_ITEMS
-	ld a, e
-	cp LOW(wNumItems)
-	jr nz, .not_bag
-	ld a, d
-	cp HIGH(wNumItems)
-	ret z
-
-.not_bag
-	ld c, MAX_PC_ITEMS
-	ld a, e
-	cp LOW(wPCItems)
-	jr nz, .not_pc
-	ld a, d
-	cp HIGH(wPCItems)
-	ret z
-
-.not_pc
-	ld c, MAX_BALLS
-	ret
-
-PutItemInPocket: ; d29c
-	ld d, h
-	ld e, l
-	inc hl
-	ld a, [wCurItem]
-	ld c, a
-	ld b, 0
-.loop
-	ld a, [hli]
-	cp -1
-	jr z, .terminator
-	cp c
-	jr nz, .next
-	ld a, 99
-	sub [hl]
-	add b
-	ld b, a
-	ld a, [wItemQuantityChangeBuffer]
-	cp b
-	jr z, .ok
-	jr c, .ok
-
-.next
-	inc hl
-	jr .loop
-
-.terminator
-	call GetPocketCapacity
-	ld a, [de]
-	cp c
-	jr c, .ok
-	and a
-	ret
-
-.ok
-	ld h, d
-	ld l, e
-	ld a, [wCurItem]
-	ld c, a
-	ld a, [wItemQuantityChangeBuffer]
-	ld [wItemQuantityBuffer], a
-.loop2
-	inc hl
-	ld a, [hli]
-	cp -1
-	jr z, .terminator2
-	cp c
-	jr nz, .loop2
-	ld a, [wItemQuantityBuffer]
-	add [hl]
-	cp 100
-	jr nc, .newstack
-	ld [hl], a
-	jr .done
-
-.newstack
-	ld [hl], 99
-	sub 99
-	ld [wItemQuantityBuffer], a
-	jr .loop2
-
-.terminator2
-	dec hl
-	ld a, [wCurItem]
-	ld [hli], a
-	ld a, [wItemQuantityBuffer]
-	ld [hli], a
-	ld [hl], -1
-	ld h, d
-	ld l, e
-	inc [hl]
-
-.done
-	scf
-	ret
-
-RemoveItemFromPocket: ; d2ff
-	ld d, h
-	ld e, l
-	ld a, [hli]
-	ld c, a
-	ld a, [wCurItemQuantity]
-	cp c
-	jr nc, .ok ; memory
-	ld c, a
-	ld b, $0
-	add hl, bc
-	add hl, bc
-	ld a, [wCurItem]
-	cp [hl]
-	inc hl
-	jr z, .skip
-	ld h, d
-	ld l, e
-	inc hl
-
-.ok
-	ld a, [wCurItem]
-	ld b, a
-.loop
-	ld a, [hli]
-	cp b
-	jr z, .skip
-	cp -1
-	jr z, .nope
-	inc hl
-	jr .loop
-
-.skip
-	ld a, [wItemQuantityChangeBuffer]
-	ld b, a
-	ld a, [hl]
-	sub b
-	jr c, .nope
-	ld [hl], a
-	ld [wItemQuantityBuffer], a
-	and a
-	jr nz, .yup
-	dec hl
-	ld b, h
-	ld c, l
-	inc hl
-	inc hl
-.loop2
-	ld a, [hli]
-	ld [bc], a
-	inc bc
-	cp -1
-	jr nz, .loop2
-	ld h, d
-	ld l, e
-	dec [hl]
-
-.yup
-	scf
-	ret
-
-.nope
-	and a
-	ret
-
-CheckTheItem: ; d349
-	ld a, [wCurItem]
-	ld c, a
-.loop
-	inc hl
-	ld a, [hli]
-	cp -1
-	jr z, .done
-	cp c
-	jr nz, .loop
-	scf
-	ret
-
-.done
-	and a
-	ret
-
-ReceiveKeyItem: ; d35a
-	ld hl, wNumKeyItems
-	ld a, [hli]
-	cp MAX_KEY_ITEMS
-	jr nc, .nope
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [wCurItem]
-	ld [hli], a
-	ld [hl], -1
-	ld hl, wNumKeyItems
-	inc [hl]
-	scf
-	ret
-
-.nope
-	and a
-	ret
-
-TossKeyItem: ; d374
-	ld a, [wCurItemQuantity]
-	ld e, a
-	ld d, 0
-	ld hl, wNumKeyItems
-	ld a, [hl]
-	cp e
-	jr nc, .ok
-	call .Toss
-	ret nc
-	jr .ok2
-
-.ok
-	dec [hl]
-	inc hl
-	add hl, de
-
-.ok2
-	ld d, h
-	ld e, l
-	inc hl
-.loop
-	ld a, [hli]
-	ld [de], a
-	inc de
-	cp -1
-	jr nz, .loop
-	scf
-	ret
-
-.Toss: ; d396
-	ld hl, wNumKeyItems
-	ld a, [wCurItem]
-	ld c, a
-.loop3
-	inc hl
-	ld a, [hl]
-	cp c
-	jr z, .ok3
-	cp -1
-	jr nz, .loop3
-	xor a
-	ret
-
-.ok3
-	ld a, [wNumKeyItems]
-	dec a
-	ld [wNumKeyItems], a
-	scf
-	ret
-
-CheckKeyItems: ; d3b1
-	ld a, [wCurItem]
-	ld c, a
-	ld hl, wKeyItems
-.loop
-	ld a, [hli]
-	cp c
-	jr z, .done
-	cp -1
-	jr nz, .loop
-	and a
-	ret
-
-.done
-	scf
-	ret
-
-ReceiveTMHM: ; d3c4
-	dec c
-	ld b, 0
-	ld hl, wTMsHMs
-	add hl, bc
-	ld a, [wItemQuantityChangeBuffer]
-	add [hl]
-	cp 100
-	jr nc, .toomany
-	ld [hl], a
-	scf
-	ret
-
-.toomany
-	and a
-	ret
-
-TossTMHM: ; d3d8
-	dec c
-	ld b, 0
-	ld hl, wTMsHMs
-	add hl, bc
-	ld a, [wItemQuantityChangeBuffer]
-	ld b, a
-	ld a, [hl]
-	sub b
-	jr c, .nope
-	ld [hl], a
-	ld [wItemQuantityBuffer], a
-	jr nz, .yup
-	ld a, [wTMHMPocketScrollPosition]
-	and a
-	jr z, .yup
-	dec a
-	ld [wTMHMPocketScrollPosition], a
-
-.yup
-	scf
-	ret
-
-.nope
-	and a
-	ret
-
-CheckTMHM: ; d3fb
-	dec c
-	ld b, $0
-	ld hl, wTMsHMs
-	add hl, bc
-	ld a, [hl]
-	and a
-	ret z
-	scf
-	ret
-
-GetTMHMNumber:: ; d407
-; Return the number of a TM/HM by item id c.
-	ld a, c
-; Skip any dummy items.
-	cp ITEM_C3 ; TM04-05
-	jr c, .done
-	cp ITEM_DC ; TM28-29
-	jr c, .skip
-	dec a
-.skip
-	dec a
-.done
-	sub TM01
-	inc a
-	ld c, a
-	ret
-
-GetNumberedTMHM: ; d417
-; Return the item id of a TM/HM by number c.
-	ld a, c
-; Skip any gaps.
-	cp ITEM_C3 - (TM01 - 1)
-	jr c, .done
-	cp ITEM_DC - (TM01 - 1) - 1
-	jr c, .skip_one
-.skip_two
-	inc a
-.skip_one
-	inc a
-.done
-	add TM01
-	dec a
-	ld c, a
-	ret
-
-_CheckTossableItem:: ; d427
-; Return 1 in wItemAttributeParamBuffer and carry if wCurItem can't be removed from the bag.
-	ld a, ITEMATTR_PERMISSIONS
-	call GetItemAttr
-	bit CANT_TOSS_F, a
-	jr nz, ItemAttr_ReturnCarry
-	and a
-	ret
-
-CheckSelectableItem: ; d432
-; Return 1 in wItemAttributeParamBuffer and carry if wCurItem can't be selected.
-	ld a, ITEMATTR_PERMISSIONS
-	call GetItemAttr
-	bit CANT_SELECT_F, a
-	jr nz, ItemAttr_ReturnCarry
-	and a
-	ret
-
-CheckItemPocket:: ; d43d
-; Return the pocket for wCurItem in wItemAttributeParamBuffer.
-	ld a, ITEMATTR_POCKET
-	call GetItemAttr
-	and $f
-	ld [wItemAttributeParamBuffer], a
-	ret
-
-CheckItemContext: ; d448
-; Return the context for wCurItem in wItemAttributeParamBuffer.
-	ld a, ITEMATTR_HELP
-	call GetItemAttr
-	and $f
-	ld [wItemAttributeParamBuffer], a
-	ret
-
-CheckItemMenu: ; d453
-; Return the menu for wCurItem in wItemAttributeParamBuffer.
-	ld a, ITEMATTR_HELP
-	call GetItemAttr
-	swap a
-	and $f
-	ld [wItemAttributeParamBuffer], a
-	ret
-
-GetItemAttr: ; d460
-; Get attribute a of wCurItem.
-
-	push hl
-	push bc
-
-	ld hl, ItemAttributes
-	ld c, a
-	ld b, 0
-	add hl, bc
-
-	xor a
-	ld [wItemAttributeParamBuffer], a
-
-	ld a, [wCurItem]
-	dec a
-	ld c, a
-	ld a, ITEMATTR_STRUCT_LENGTH
-	call AddNTimes
-	ld a, BANK(ItemAttributes)
-	call GetFarByte
-
-	pop bc
-	pop hl
-	ret
-
-ItemAttr_ReturnCarry: ; d47f
-	ld a, 1
-	ld [wItemAttributeParamBuffer], a
-	scf
-	ret
-
-GetItemPrice: ; d486
-; Return the price of wCurItem in de.
-	push hl
-	push bc
-	ld a, ITEMATTR_PRICE
-	call GetItemAttr
-	ld e, a
-	ld a, ITEMATTR_PRICE_HI
-	call GetItemAttr
-	ld d, a
-	pop bc
-	pop hl
-	ret
--- /dev/null
+++ b/engine/items/buy_sell_toss.asm
@@ -1,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
--- /dev/null
+++ b/engine/items/item_effects.asm
@@ -1,0 +1,3118 @@
+_DoItemEffect:: ; e722
+	ld a, [wCurItem]
+	ld [wd265], a
+	call GetItemName
+	call CopyName1
+	ld a, 1
+	ld [wItemEffectSucceeded], a
+	ld a, [wCurItem]
+	dec a
+	ld hl, ItemEffects
+	rst JumpTable
+	ret
+; e73c
+
+
+ItemEffects: ; e73c
+; entries correspond to item ids
+	dw PokeBallEffect      ; MASTER_BALL
+	dw PokeBallEffect      ; ULTRA_BALL
+	dw NoEffect            ; BRIGHTPOWDER
+	dw PokeBallEffect      ; GREAT_BALL
+	dw PokeBallEffect      ; POKE_BALL
+	dw TownMapEffect       ; TOWN_MAP
+	dw BicycleEffect       ; BICYCLE
+	dw EvoStoneEffect      ; MOON_STONE
+	dw StatusHealingEffect ; ANTIDOTE
+	dw StatusHealingEffect ; BURN_HEAL
+	dw StatusHealingEffect ; ICE_HEAL
+	dw StatusHealingEffect ; AWAKENING
+	dw StatusHealingEffect ; PARLYZ_HEAL
+	dw FullRestoreEffect   ; FULL_RESTORE
+	dw RestoreHPEffect     ; MAX_POTION
+	dw RestoreHPEffect     ; HYPER_POTION
+	dw RestoreHPEffect     ; SUPER_POTION
+	dw RestoreHPEffect     ; POTION
+	dw EscapeRopeEffect    ; ESCAPE_ROPE
+	dw RepelEffect         ; REPEL
+	dw RestorePPEffect     ; MAX_ELIXER
+	dw EvoStoneEffect      ; FIRE_STONE
+	dw EvoStoneEffect      ; THUNDERSTONE
+	dw EvoStoneEffect      ; WATER_STONE
+	dw NoEffect            ; ITEM_19
+	dw VitaminEffect       ; HP_UP
+	dw VitaminEffect       ; PROTEIN
+	dw VitaminEffect       ; IRON
+	dw VitaminEffect       ; CARBOS
+	dw NoEffect            ; LUCKY_PUNCH
+	dw VitaminEffect       ; CALCIUM
+	dw RareCandyEffect     ; RARE_CANDY
+	dw XAccuracyEffect     ; X_ACCURACY
+	dw EvoStoneEffect      ; LEAF_STONE
+	dw NoEffect            ; METAL_POWDER
+	dw NoEffect            ; NUGGET
+	dw PokeDollEffect      ; POKE_DOLL
+	dw StatusHealingEffect ; FULL_HEAL
+	dw ReviveEffect        ; REVIVE
+	dw ReviveEffect        ; MAX_REVIVE
+	dw GuardSpecEffect     ; GUARD_SPEC
+	dw SuperRepelEffect    ; SUPER_REPEL
+	dw MaxRepelEffect      ; MAX_REPEL
+	dw DireHitEffect       ; DIRE_HIT
+	dw NoEffect            ; ITEM_2D
+	dw RestoreHPEffect     ; FRESH_WATER
+	dw RestoreHPEffect     ; SODA_POP
+	dw RestoreHPEffect     ; LEMONADE
+	dw XItemEffect         ; X_ATTACK
+	dw NoEffect            ; ITEM_32
+	dw XItemEffect         ; X_DEFEND
+	dw XItemEffect         ; X_SPEED
+	dw XItemEffect         ; X_SPECIAL
+	dw CoinCaseEffect      ; COIN_CASE
+	dw ItemfinderEffect    ; ITEMFINDER
+	dw PokeFluteEffect     ; POKE_FLUTE
+	dw NoEffect            ; EXP_SHARE
+	dw OldRodEffect        ; OLD_ROD
+	dw GoodRodEffect       ; GOOD_ROD
+	dw NoEffect            ; SILVER_LEAF
+	dw SuperRodEffect      ; SUPER_ROD
+	dw RestorePPEffect     ; PP_UP
+	dw RestorePPEffect     ; ETHER
+	dw RestorePPEffect     ; MAX_ETHER
+	dw RestorePPEffect     ; ELIXER
+	dw NoEffect            ; RED_SCALE
+	dw NoEffect            ; SECRETPOTION
+	dw NoEffect            ; S_S_TICKET
+	dw NoEffect            ; MYSTERY_EGG
+	dw NoEffect            ; CLEAR_BELL
+	dw NoEffect            ; SILVER_WING
+	dw RestoreHPEffect     ; MOOMOO_MILK
+	dw NoEffect            ; QUICK_CLAW
+	dw StatusHealingEffect ; PSNCUREBERRY
+	dw NoEffect            ; GOLD_LEAF
+	dw NoEffect            ; SOFT_SAND
+	dw NoEffect            ; SHARP_BEAK
+	dw StatusHealingEffect ; PRZCUREBERRY
+	dw StatusHealingEffect ; BURNT_BERRY
+	dw StatusHealingEffect ; ICE_BERRY
+	dw NoEffect            ; POISON_BARB
+	dw NoEffect            ; KINGS_ROCK
+	dw BitterBerryEffect   ; BITTER_BERRY
+	dw StatusHealingEffect ; MINT_BERRY
+	dw NoEffect            ; RED_APRICORN
+	dw NoEffect            ; TINYMUSHROOM
+	dw NoEffect            ; BIG_MUSHROOM
+	dw NoEffect            ; SILVERPOWDER
+	dw NoEffect            ; BLU_APRICORN
+	dw NoEffect            ; ITEM_5A
+	dw NoEffect            ; AMULET_COIN
+	dw NoEffect            ; YLW_APRICORN
+	dw NoEffect            ; GRN_APRICORN
+	dw NoEffect            ; CLEANSE_TAG
+	dw NoEffect            ; MYSTIC_WATER
+	dw NoEffect            ; TWISTEDSPOON
+	dw NoEffect            ; WHT_APRICORN
+	dw NoEffect            ; BLACKBELT
+	dw NoEffect            ; BLK_APRICORN
+	dw NoEffect            ; ITEM_64
+	dw NoEffect            ; PNK_APRICORN
+	dw NoEffect            ; BLACKGLASSES
+	dw NoEffect            ; SLOWPOKETAIL
+	dw NoEffect            ; PINK_BOW
+	dw NoEffect            ; STICK
+	dw NoEffect            ; SMOKE_BALL
+	dw NoEffect            ; NEVERMELTICE
+	dw NoEffect            ; MAGNET
+	dw StatusHealingEffect ; MIRACLEBERRY
+	dw NoEffect            ; PEARL
+	dw NoEffect            ; BIG_PEARL
+	dw NoEffect            ; EVERSTONE
+	dw NoEffect            ; SPELL_TAG
+	dw RestoreHPEffect     ; RAGECANDYBAR
+	dw NoEffect            ; GS_BALL
+	dw BlueCardEffect      ; BLUE_CARD
+	dw NoEffect            ; MIRACLE_SEED
+	dw NoEffect            ; THICK_CLUB
+	dw NoEffect            ; FOCUS_BAND
+	dw NoEffect            ; ITEM_78
+	dw EnergypowderEffect  ; ENERGYPOWDER
+	dw EnergyRootEffect    ; ENERGY_ROOT
+	dw HealPowderEffect    ; HEAL_POWDER
+	dw RevivalHerbEffect   ; REVIVAL_HERB
+	dw NoEffect            ; HARD_STONE
+	dw NoEffect            ; LUCKY_EGG
+	dw CardKeyEffect       ; CARD_KEY
+	dw NoEffect            ; MACHINE_PART
+	dw NoEffect            ; EGG_TICKET
+	dw NoEffect            ; LOST_ITEM
+	dw NoEffect            ; STARDUST
+	dw NoEffect            ; STAR_PIECE
+	dw BasementKeyEffect   ; BASEMENT_KEY
+	dw NoEffect            ; PASS
+	dw NoEffect            ; ITEM_87
+	dw NoEffect            ; ITEM_88
+	dw NoEffect            ; ITEM_89
+	dw NoEffect            ; CHARCOAL
+	dw RestoreHPEffect     ; BERRY_JUICE
+	dw NoEffect            ; SCOPE_LENS
+	dw NoEffect            ; ITEM_8D
+	dw NoEffect            ; ITEM_8E
+	dw NoEffect            ; METAL_COAT
+	dw NoEffect            ; DRAGON_FANG
+	dw NoEffect            ; ITEM_91
+	dw NoEffect            ; LEFTOVERS
+	dw NoEffect            ; ITEM_93
+	dw NoEffect            ; ITEM_94
+	dw NoEffect            ; ITEM_95
+	dw RestorePPEffect     ; MYSTERYBERRY
+	dw NoEffect            ; DRAGON_SCALE
+	dw NoEffect            ; BERSERK_GENE
+	dw NoEffect            ; ITEM_99
+	dw NoEffect            ; ITEM_9A
+	dw NoEffect            ; ITEM_9B
+	dw SacredAshEffect     ; SACRED_ASH
+	dw PokeBallEffect      ; HEAVY_BALL
+	dw NoEffect            ; FLOWER_MAIL
+	dw PokeBallEffect      ; LEVEL_BALL
+	dw PokeBallEffect      ; LURE_BALL
+	dw PokeBallEffect      ; FAST_BALL
+	dw NoEffect            ; ITEM_A2
+	dw NoEffect            ; LIGHT_BALL
+	dw PokeBallEffect      ; FRIEND_BALL
+	dw PokeBallEffect      ; MOON_BALL
+	dw PokeBallEffect      ; LOVE_BALL
+	dw NormalBoxEffect     ; NORMAL_BOX
+	dw GorgeousBoxEffect   ; GORGEOUS_BOX
+	dw EvoStoneEffect      ; SUN_STONE
+	dw NoEffect            ; POLKADOT_BOW
+	dw NoEffect            ; ITEM_AB
+	dw NoEffect            ; UP_GRADE
+	dw RestoreHPEffect     ; BERRY
+	dw RestoreHPEffect     ; GOLD_BERRY
+	dw SquirtbottleEffect  ; SQUIRTBOTTLE
+	dw NoEffect            ; ITEM_B0
+	dw PokeBallEffect      ; PARK_BALL
+	dw NoEffect            ; RAINBOW_WING
+	dw NoEffect            ; ITEM_B3
+; e8a2
+
+
+PokeBallEffect: ; e8a2
+	ld a, [wBattleMode]
+	dec a
+	jp nz, UseBallInTrainerBattle
+
+	ld a, [wPartyCount]
+	cp PARTY_LENGTH
+	jr nz, .room_in_party
+
+	ld a, BANK(sBoxCount)
+	call GetSRAMBank
+	ld a, [sBoxCount]
+	cp MONS_PER_BOX
+	call CloseSRAM
+	jp z, Ball_BoxIsFullMessage
+
+.room_in_party
+	xor a
+	ld [wWildMon], a
+	ld a, [wCurItem]
+	cp PARK_BALL
+	call nz, ReturnToBattle_UseBall
+
+	ld hl, wOptions
+	res NO_TEXT_SCROLL, [hl]
+	ld hl, UsedItemText
+	call PrintText
+
+	ld a, [wEnemyMonCatchRate]
+	ld b, a
+	ld a, [wBattleType]
+	cp BATTLETYPE_TUTORIAL
+	jp z, .catch_without_fail
+	ld a, [wCurItem]
+	cp MASTER_BALL
+	jp z, .catch_without_fail
+	ld a, [wCurItem]
+	ld c, a
+	ld hl, BallMultiplierFunctionTable
+
+.get_multiplier_loop
+	ld a, [hli]
+	cp $ff
+	jr z, .skip_or_return_from_ball_fn
+	cp c
+	jr z, .call_ball_function
+	inc hl
+	inc hl
+	jr .get_multiplier_loop
+
+.call_ball_function
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, .skip_or_return_from_ball_fn
+	push de
+	jp hl
+
+.skip_or_return_from_ball_fn
+	ld a, [wCurItem]
+	cp LEVEL_BALL
+	ld a, b
+	jp z, .skip_hp_calc
+
+	ld a, b
+	ld [hMultiplicand + 2], a
+
+	ld hl, wEnemyMonHP
+	ld b, [hl]
+	inc hl
+	ld c, [hl]
+	inc hl
+	ld d, [hl]
+	inc hl
+	ld e, [hl]
+	sla c
+	rl b
+
+	ld h, d
+	ld l, e
+	add hl, de
+	add hl, de
+	ld d, h
+	ld e, l
+	ld a, d
+	and a
+	jr z, .okay_1
+
+	srl d
+	rr e
+	srl d
+	rr e
+	srl b
+	rr c
+	srl b
+	rr c
+
+	ld a, c
+	and a
+	jr nz, .okay_1
+	ld c, $1
+.okay_1
+	ld b, e
+
+	push bc
+	ld a, b
+	sub c
+	ld [hMultiplier], a
+	xor a
+	ld [hDividend + 0], a
+	ld [hMultiplicand + 0], a
+	ld [hMultiplicand + 1], a
+	call Multiply
+	pop bc
+
+	ld a, b
+	ld [hDivisor], a
+	ld b, $4
+	call Divide
+
+	ld a, [hQuotient + 2]
+	and a
+	jr nz, .statuscheck
+	ld a, 1
+.statuscheck
+; This routine is buggy. It was intended that SLP and FRZ provide a higher
+; catch rate than BRN/PSN/PAR, which in turn provide a higher catch rate than
+; no status effect at all. But instead, it makes BRN/PSN/PAR provide no
+; benefit.
+; Uncomment the line below to fix this.
+	ld b, a
+	ld a, [wEnemyMonStatus]
+	and 1 << FRZ | SLP
+	ld c, 10
+	jr nz, .addstatus
+	; ld a, [wEnemyMonStatus]
+	and a
+	ld c, 5
+	jr nz, .addstatus
+	ld c, 0
+.addstatus
+	ld a, b
+	add c
+	jr nc, .max_1
+	ld a, $ff
+.max_1
+
+	; BUG: farcall overwrites a, and GetItemHeldEffect takes b anyway.
+	; This is probably the reason the HELD_CATCH_CHANCE effect is never used.
+	; Uncomment the line below to fix.
+	ld d, a
+	push de
+	ld a, [wBattleMonItem]
+	; ld b, a
+	farcall GetItemHeldEffect
+	ld a, b
+	cp HELD_CATCH_CHANCE
+	pop de
+	ld a, d
+	jr nz, .max_2
+	add c
+	jr nc, .max_2
+	ld a, $ff
+.max_2
+
+.skip_hp_calc
+	ld b, a
+	ld [wBuffer1], a
+	call Random
+
+	cp b
+	ld a, 0
+	jr z, .catch_without_fail
+	jr nc, .fail_to_catch
+
+.catch_without_fail
+	ld a, [wEnemyMonSpecies]
+
+.fail_to_catch
+	ld [wWildMon], a
+	ld c, 20
+	call DelayFrames
+
+	ld a, [wCurItem]
+	cp POKE_BALL + 1 ; Assumes Master/Ultra/Great come before
+	jr c, .not_kurt_ball
+	ld a, POKE_BALL
+.not_kurt_ball
+	ld [wBattleAnimParam], a
+
+	ld de, ANIM_THROW_POKE_BALL
+	ld a, e
+	ld [wFXAnimID], a
+	ld a, d
+	ld [wFXAnimID + 1], a
+	xor a
+	ld [hBattleTurn], a
+	ld [wBuffer2], a
+	ld [wNumHits], a
+	predef PlayBattleAnim
+
+	ld a, [wWildMon]
+	and a
+	jr nz, .caught
+	ld a, [wBuffer2]
+	cp $1
+	ld hl, Text_NoShake
+	jp z, .shake_and_break_free
+	cp $2
+	ld hl, Text_OneShake
+	jp z, .shake_and_break_free
+	cp $3
+	ld hl, Text_TwoShakes
+	jp z, .shake_and_break_free
+	cp $4
+	ld hl, Text_ThreeShakes
+	jp z, .shake_and_break_free
+.caught
+
+	ld hl, wEnemyMonStatus
+	ld a, [hli]
+	push af
+	inc hl
+	ld a, [hli]
+	push af
+	ld a, [hl]
+	push af
+	push hl
+	ld hl, wEnemyMonItem
+	ld a, [hl]
+	push af
+	push hl
+	ld hl, wEnemySubStatus5
+	ld a, [hl]
+	push af
+	set SUBSTATUS_TRANSFORMED, [hl]
+
+; This code is buggy. Any wild Pokémon that has Transformed will be
+; caught as a Ditto, even if it was something else like Mew.
+; To fix, do not set [wTempEnemyMonSpecies] to DITTO.
+	bit SUBSTATUS_TRANSFORMED, a
+	jr nz, .ditto
+	jr .not_ditto
+
+.ditto
+	ld a, DITTO
+	ld [wTempEnemyMonSpecies], a
+	jr .load_data
+
+.not_ditto
+	set SUBSTATUS_TRANSFORMED, [hl]
+	ld hl, wEnemyBackupDVs
+	ld a, [wEnemyMonDVs]
+	ld [hli], a
+	ld a, [wEnemyMonDVs + 1]
+	ld [hl], a
+
+.load_data
+	ld a, [wTempEnemyMonSpecies]
+	ld [wCurPartySpecies], a
+	ld a, [wEnemyMonLevel]
+	ld [wCurPartyLevel], a
+	farcall LoadEnemyMon
+
+	pop af
+	ld [wEnemySubStatus5], a
+
+	pop hl
+	pop af
+	ld [hl], a
+	pop hl
+	pop af
+	ld [hld], a
+	pop af
+	ld [hld], a
+	dec hl
+	pop af
+	ld [hl], a
+
+	ld hl, wEnemySubStatus5
+	bit SUBSTATUS_TRANSFORMED, [hl]
+	jr nz, .Transformed
+	ld hl, wWildMonMoves
+	ld de, wEnemyMonMoves
+	ld bc, NUM_MOVES
+	call CopyBytes
+
+	ld hl, wWildMonPP
+	ld de, wEnemyMonPP
+	ld bc, NUM_MOVES
+	call CopyBytes
+.Transformed:
+
+	ld a, [wEnemyMonSpecies]
+	ld [wWildMon], a
+	ld [wCurPartySpecies], a
+	ld [wd265], a
+	ld a, [wBattleType]
+	cp BATTLETYPE_TUTORIAL
+	jp z, .FinishTutorial
+
+	farcall StubbedTrainerRankings_WildMonsCaught
+
+	ld hl, Text_GotchaMonWasCaught
+	call PrintText
+
+	call ClearSprites
+
+	ld a, [wd265]
+	dec a
+	call CheckCaughtMon
+
+	ld a, c
+	push af
+	ld a, [wd265]
+	dec a
+	call SetSeenAndCaughtMon
+	pop af
+	and a
+	jr nz, .skip_pokedex
+
+	call CheckReceivedDex
+	jr z, .skip_pokedex
+
+	ld hl, Text_AddedToPokedex
+	call PrintText
+
+	call ClearSprites
+
+	ld a, [wEnemyMonSpecies]
+	ld [wd265], a
+	predef NewPokedexEntry
+
+.skip_pokedex
+	ld a, [wBattleType]
+	cp BATTLETYPE_CONTEST
+	jp z, .catch_bug_contest_mon
+	cp BATTLETYPE_CELEBI
+	jr nz, .not_celebi
+	ld hl, wBattleResult
+	set 6, [hl]
+.not_celebi
+
+	ld a, [wPartyCount]
+	cp PARTY_LENGTH
+	jr z, .SendToPC
+
+	xor a ; PARTYMON
+	ld [wMonType], a
+	call ClearSprites
+
+	predef TryAddMonToParty
+
+	farcall SetCaughtData
+
+	ld a, [wCurItem]
+	cp FRIEND_BALL
+	jr nz, .SkipPartyMonFriendBall
+
+	ld a, [wPartyCount]
+	dec a
+	ld hl, wPartyMon1Happiness
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+
+	ld a, FRIEND_BALL_HAPPINESS
+	ld [hl], a
+.SkipPartyMonFriendBall:
+
+	ld hl, Text_AskNicknameNewlyCaughtMon
+	call PrintText
+
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	call GetPokemonName
+
+	call YesNoBox
+	jp c, .return_from_capture
+
+	ld a, [wPartyCount]
+	dec a
+	ld [wCurPartyMon], a
+	ld hl, wPartyMonNicknames
+	ld bc, MON_NAME_LENGTH
+	call AddNTimes
+
+	ld d, h
+	ld e, l
+	push de
+	xor a ; PARTYMON
+	ld [wMonType], a
+	ld b, 0
+	farcall NamingScreen
+
+	call RotateThreePalettesRight
+
+	call LoadStandardFont
+
+	pop hl
+	ld de, wStringBuffer1
+	call InitName
+
+	jp .return_from_capture
+
+.SendToPC:
+	call ClearSprites
+
+	predef SendMonIntoBox
+
+	farcall SetBoxMonCaughtData
+
+	ld a, BANK(sBoxCount)
+	call GetSRAMBank
+
+	ld a, [sBoxCount]
+	cp MONS_PER_BOX
+	jr nz, .BoxNotFullYet
+	ld hl, wBattleResult
+	set 7, [hl]
+.BoxNotFullYet:
+	ld a, [wCurItem]
+	cp FRIEND_BALL
+	jr nz, .SkipBoxMonFriendBall
+	; The captured mon is now first in the box
+	ld a, FRIEND_BALL_HAPPINESS
+	ld [sBoxMon1Happiness], a
+.SkipBoxMonFriendBall:
+	call CloseSRAM
+
+	ld hl, Text_AskNicknameNewlyCaughtMon
+	call PrintText
+
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	call GetPokemonName
+
+	call YesNoBox
+	jr c, .SkipBoxMonNickname
+
+	xor a
+	ld [wCurPartyMon], a
+	ld a, BOXMON
+	ld [wMonType], a
+	ld de, wMonOrItemNameBuffer
+	ld b, $0
+	farcall NamingScreen
+
+	ld a, BANK(sBoxMonNicknames)
+	call GetSRAMBank
+
+	ld hl, wMonOrItemNameBuffer
+	ld de, sBoxMonNicknames
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+
+	ld hl, sBoxMonNicknames
+	ld de, wStringBuffer1
+	call InitName
+
+	call CloseSRAM
+
+.SkipBoxMonNickname:
+	ld a, BANK(sBoxMonNicknames)
+	call GetSRAMBank
+
+	ld hl, sBoxMonNicknames
+	ld de, wMonOrItemNameBuffer
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+
+	call CloseSRAM
+
+	ld hl, Text_SentToBillsPC
+	call PrintText
+
+	call RotateThreePalettesRight
+	call LoadStandardFont
+	jr .return_from_capture
+
+.catch_bug_contest_mon
+	farcall BugContest_SetCaughtContestMon
+	jr .return_from_capture
+
+.FinishTutorial:
+	ld hl, Text_GotchaMonWasCaught
+
+.shake_and_break_free
+	call PrintText
+	call ClearSprites
+
+.return_from_capture
+	ld a, [wBattleType]
+	cp BATTLETYPE_TUTORIAL
+	ret z
+	cp BATTLETYPE_DEBUG
+	ret z
+	cp BATTLETYPE_CONTEST
+	jr z, .used_park_ball
+
+	ld a, [wWildMon]
+	and a
+	jr z, .toss
+
+	call ClearBGPalettes
+	call ClearTileMap
+
+.toss
+	ld hl, wNumItems
+	inc a
+	ld [wItemQuantityChangeBuffer], a
+	jp TossItem
+
+.used_park_ball
+	ld hl, wParkBallsRemaining
+	dec [hl]
+	ret
+; ec0a
+
+
+BallMultiplierFunctionTable:
+; table of routines that increase or decrease the catch rate based on
+; which ball is used in a certain situation.
+	dbw ULTRA_BALL,  UltraBallMultiplier
+	dbw GREAT_BALL,  GreatBallMultiplier
+	dbw SAFARI_BALL, SafariBallMultiplier ; Safari Ball, leftover from RBY
+	dbw HEAVY_BALL,  HeavyBallMultiplier
+	dbw LEVEL_BALL,  LevelBallMultiplier
+	dbw LURE_BALL,   LureBallMultiplier
+	dbw FAST_BALL,   FastBallMultiplier
+	dbw MOON_BALL,   MoonBallMultiplier
+	dbw LOVE_BALL,   LoveBallMultiplier
+	dbw PARK_BALL,   ParkBallMultiplier
+	db -1 ; end
+
+UltraBallMultiplier:
+; multiply catch rate by 2
+	sla b
+	ret nc
+	ld b, $ff
+	ret
+
+SafariBallMultiplier:
+GreatBallMultiplier:
+ParkBallMultiplier:
+; multiply catch rate by 1.5
+	ld a, b
+	srl a
+	add b
+	ld b, a
+	ret nc
+	ld b, $ff
+	ret
+
+GetPokedexEntryBank:
+	push hl
+	push de
+	ld a, [wEnemyMonSpecies]
+	rlca
+	rlca
+	maskbits NUM_DEX_ENTRY_BANKS
+	ld hl, .PokedexEntryBanks
+	ld d, 0
+	ld e, a
+	add hl, de
+	ld a, [hl]
+	pop de
+	pop hl
+	ret
+
+.PokedexEntryBanks:
+	db BANK(PokedexEntries1)
+	db BANK(PokedexEntries2)
+	db BANK(PokedexEntries3)
+	db BANK(PokedexEntries4)
+
+HeavyBallMultiplier:
+; subtract 20 from catch rate if weight < 102.4 kg
+; else add 0 to catch rate if weight < 204.8 kg
+; else add 20 to catch rate if weight < 307.2 kg
+; else add 30 to catch rate if weight < 409.6 kg
+; else add 40 to catch rate (never happens)
+	ld a, [wEnemyMonSpecies]
+	ld hl, PokedexDataPointerTable
+	dec a
+	ld e, a
+	ld d, 0
+	add hl, de
+	add hl, de
+	ld a, BANK(PokedexDataPointerTable)
+	call GetFarHalfword
+
+.SkipText:
+	call GetPokedexEntryBank
+	call GetFarByte
+	inc hl
+	cp "@"
+	jr nz, .SkipText
+
+	call GetPokedexEntryBank
+	push bc
+	inc hl
+	inc hl
+	call GetFarHalfword
+
+	srl h
+	rr l
+	ld b, h
+	ld c, l
+
+	rept 4
+	srl b
+	rr c
+	endr
+	call .subbc
+
+	srl b
+	rr c
+	call .subbc
+
+	ld a, h
+	pop bc
+	jr .compare
+
+.subbc
+	; subtract bc from hl
+	push bc
+	ld a, b
+	cpl
+	ld b, a
+	ld a, c
+	cpl
+	ld c, a
+	inc bc
+	add hl, bc
+	pop bc
+	ret
+
+.compare
+	ld c, a
+	cp HIGH(1024) ; 102.4 kg
+	jr c, .lightmon
+
+	ld hl, .WeightsTable
+.lookup
+	ld a, c
+	cp [hl]
+	jr c, .heavymon
+	inc hl
+	inc hl
+	jr .lookup
+
+.heavymon
+	inc hl
+	ld a, b
+	add [hl]
+	ld b, a
+	ret nc
+	ld b, $ff
+	ret
+
+.lightmon
+	ld a, b
+	sub 20
+	ld b, a
+	ret nc
+	ld b, $1
+	ret
+
+.WeightsTable:
+; weight factor, boost
+	db HIGH(2048),   0
+	db HIGH(3072),  20
+	db HIGH(4096),  30
+	db HIGH(65280), 40
+
+LureBallMultiplier:
+; multiply catch rate by 3 if this is a fishing rod battle
+	ld a, [wBattleType]
+	cp BATTLETYPE_FISH
+	ret nz
+
+	ld a, b
+	add a
+	jr c, .max
+
+	add b
+	jr nc, .done
+.max
+	ld a, $ff
+.done
+	ld b, a
+	ret
+
+MoonBallMultiplier:
+; This function is buggy.
+; Intent:  multiply catch rate by 4 if mon evolves with moon stone
+; Reality: no boost
+	push bc
+	ld a, [wTempEnemyMonSpecies]
+	dec a
+	ld c, a
+	ld b, 0
+	ld hl, EvosAttacksPointers
+	add hl, bc
+	add hl, bc
+	ld a, BANK(EvosAttacksPointers)
+	call GetFarHalfword
+	pop bc
+
+	push bc
+	ld a, BANK(EvosAttacks)
+	call GetFarByte
+	cp EVOLVE_ITEM
+	pop bc
+	ret nz
+
+	inc hl
+	inc hl
+	inc hl
+
+; Moon Stone's constant from Pokémon Red is used.
+; No Pokémon evolve with Burn Heal,
+; so Moon Balls always have a catch rate of 1×.
+	push bc
+	ld a, BANK(EvosAttacks)
+	call GetFarByte
+	cp MOON_STONE_RED ; BURN_HEAL
+	pop bc
+	ret nz
+
+	sla b
+	jr c, .max
+	sla b
+	jr nc, .done
+.max
+	ld b, $ff
+.done
+	ret
+
+LoveBallMultiplier:
+; This function is buggy.
+; Intent:  multiply catch rate by 8 if mons are of same species, different sex
+; Reality: multiply catch rate by 8 if mons are of same species, same sex
+
+	; does species match?
+	ld a, [wTempEnemyMonSpecies]
+	ld c, a
+	ld a, [wTempBattleMonSpecies]
+	cp c
+	ret nz
+
+	; check player mon species
+	push bc
+	ld a, [wTempBattleMonSpecies]
+	ld [wCurPartySpecies], a
+	xor a ; PARTYMON
+	ld [wMonType], a
+	ld a, [wCurBattleMon]
+	ld [wCurPartyMon], a
+	farcall GetGender
+	jr c, .done1 ; no effect on genderless
+
+	ld d, 0 ; male
+	jr nz, .playermale
+	inc d   ; female
+.playermale
+
+	; check wild mon species
+	push de
+	ld a, [wTempEnemyMonSpecies]
+	ld [wCurPartySpecies], a
+	ld a, WILDMON
+	ld [wMonType], a
+	farcall GetGender
+	jr c, .done2 ; no effect on genderless
+
+	ld d, 0 ; male
+	jr nz, .wildmale
+	inc d   ; female
+.wildmale
+
+	ld a, d
+	pop de
+	cp d
+	pop bc
+	ret nz ; for the intended effect, this should be "ret z"
+
+	sla b
+	jr c, .max
+	sla b
+	jr c, .max
+	sla b
+	ret nc
+.max
+	ld b, $ff
+	ret
+
+.done2
+	pop de
+
+.done1
+	pop bc
+	ret
+
+FastBallMultiplier:
+; This function is buggy.
+; Intent:  multiply catch rate by 4 if enemy mon is in one of the three
+;          FleeMons tables.
+; Reality: multiply catch rate by 4 if enemy mon is one of the first three in
+;          the first FleeMons table.
+	ld a, [wTempEnemyMonSpecies]
+	ld c, a
+	ld hl, FleeMons
+	ld d, 3
+
+.loop
+	ld a, BANK(FleeMons)
+	call GetFarByte
+
+	inc hl
+	cp -1
+	jr z, .next
+	cp c
+	jr nz, .next ; for the intended effect, this should be "jr nz, .loop"
+	sla b
+	jr c, .max
+
+	sla b
+	ret nc
+
+.max
+	ld b, $ff
+	ret
+
+.next
+	dec d
+	jr nz, .loop
+	ret
+
+LevelBallMultiplier:
+; multiply catch rate by 8 if player mon level / 4 > enemy mon level
+; multiply catch rate by 4 if player mon level / 2 > enemy mon level
+; multiply catch rate by 2 if player mon level > enemy mon level
+	ld a, [wBattleMonLevel]
+	ld c, a
+	ld a, [wEnemyMonLevel]
+	cp c
+	ret nc ; if player is lower level, we're done here
+	sla b
+	jr c, .max
+
+	srl c
+	cp c
+	ret nc ; if player/2 is lower level, we're done here
+	sla b
+	jr c, .max
+
+	srl c
+	cp c
+	ret nc ; if player/4 is lower level, we're done here
+	sla b
+	ret nc
+
+.max
+	ld b, $ff
+	ret
+
+; These two texts were carried over from gen 1.
+; They are not used in gen 2, and are dummied out.
+
+Text_RBY_CatchMarowak: ; 0xedab
+	; It dodged the thrown BALL! This #MON can't be caught!
+	text_jump UnknownText_0x1c5a5a
+	db "@"
+; 0xedb0
+
+Text_RBY_NoShake: ; 0xedb0
+	; You missed the #MON!
+	text_jump UnknownText_0x1c5a90
+	db "@"
+; 0xedb5
+
+Text_NoShake: ; 0xedb5
+	; Oh no! The #MON broke free!
+	text_jump UnknownText_0x1c5aa6
+	db "@"
+; 0xedba
+
+Text_OneShake: ; 0xedba
+	; Aww! It appeared to be caught!
+	text_jump UnknownText_0x1c5ac3
+	db "@"
+; 0xedbf
+
+Text_TwoShakes: ; 0xedbf
+	; Aargh! Almost had it!
+	text_jump UnknownText_0x1c5ae3
+	db "@"
+; 0xedc4
+
+Text_ThreeShakes: ; 0xedc4
+	; Shoot! It was so close too!
+	text_jump UnknownText_0x1c5afa
+	db "@"
+; 0xedc9
+
+Text_GotchaMonWasCaught: ; 0xedc9
+	; Gotcha! @ was caught!@ @
+	text_jump UnknownText_0x1c5b17
+	start_asm
+	call WaitSFX
+	push bc
+	ld de, MUSIC_NONE
+	call PlayMusic
+	call DelayFrame
+	ld de, MUSIC_CAPTURE
+	call PlayMusic
+	pop bc
+	ld hl, TextJump_Waitbutton
+	ret
+; ede6
+
+TextJump_Waitbutton: ; 0xede6
+	; @
+	text_jump Text_Waitbutton_2
+	db "@"
+; 0xedeb
+
+Text_SentToBillsPC: ; 0xedeb
+	; was sent to BILL's PC.
+	text_jump UnknownText_0x1c5b38
+	db "@"
+; 0xedf0
+
+Text_AddedToPokedex: ; 0xedf0
+	; 's data was newly added to the #DEX.@ @
+	text_jump UnknownText_0x1c5b53
+	db "@"
+; 0xedf5
+
+Text_AskNicknameNewlyCaughtMon: ; 0xedf5
+	; Give a nickname to @ ?
+	text_jump UnknownText_0x1c5b7f
+	db "@"
+; 0xedfa
+
+ReturnToBattle_UseBall: ; edfa (3:6dfa)
+	farcall _ReturnToBattle_UseBall
+	ret
+
+TownMapEffect: ; ee01
+	farcall PokegearMap
+	ret
+; ee08
+
+
+BicycleEffect: ; ee08
+	farcall BikeFunction
+	ret
+; ee0f
+
+
+EvoStoneEffect: ; ee0f
+	ld b, PARTYMENUACTION_EVO_STONE
+	call UseItem_SelectMon
+
+	jp c, .DecidedNotToUse
+
+	ld a, MON_ITEM
+	call GetPartyParamLocation
+
+	ld a, [hl]
+	cp EVERSTONE
+	jr z, .NoEffect
+
+	ld a, $1
+	ld [wForceEvolution], a
+	farcall EvolvePokemon
+
+	ld a, [wMonTriedToEvolve]
+	and a
+	jr z, .NoEffect
+
+	jp UseDisposableItem
+
+.NoEffect:
+	call WontHaveAnyEffectMessage
+
+.DecidedNotToUse:
+	xor a
+	ld [wItemEffectSucceeded], a
+	ret
+; ee3d
+
+
+VitaminEffect: ; ee3d
+	ld b, PARTYMENUACTION_HEALING_ITEM
+	call UseItem_SelectMon
+
+	jp c, RareCandy_StatBooster_ExitMenu
+
+	call RareCandy_StatBooster_GetParameters
+
+	call GetStatExpRelativePointer
+
+	ld a, MON_STAT_EXP
+	call GetPartyParamLocation
+
+	add hl, bc
+	ld a, [hl]
+	cp 100
+	jr nc, NoEffectMessage
+
+	add 10
+	ld [hl], a
+	call UpdateStatsAfterItem
+
+	call GetStatExpRelativePointer
+
+	ld hl, StatStrings
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, wStringBuffer2
+	ld bc, ITEM_NAME_LENGTH
+	call CopyBytes
+
+	call Play_SFX_FULL_HEAL
+
+	ld hl, Text_StatRose
+	call PrintText
+
+	ld c, HAPPINESS_USEDITEM
+	farcall ChangeHappiness
+
+	jp UseDisposableItem
+
+
+NoEffectMessage: ; ee83
+	ld hl, WontHaveAnyEffectText
+	call PrintText
+	jp ClearPalettes
+; ee8c
+
+
+UpdateStatsAfterItem: ; ee8c
+	ld a, MON_MAXHP
+	call GetPartyParamLocation
+	ld d, h
+	ld e, l
+	ld a, MON_STAT_EXP - 1
+	call GetPartyParamLocation
+	ld b, TRUE
+	predef_jump CalcMonStats
+; ee9f
+
+RareCandy_StatBooster_ExitMenu: ; ee9f
+	xor a
+	ld [wItemEffectSucceeded], a
+	jp ClearPalettes
+; eea6
+
+
+Text_StatRose: ; 0xeea6
+	; 's @  rose.
+	text_jump UnknownText_0x1c5b9a
+	db "@"
+; 0xeeab
+
+
+StatStrings: ; eeab
+	dw .health
+	dw .attack
+	dw .defense
+	dw .speed
+	dw .special
+
+.health  db "HEALTH@"
+.attack  db "ATTACK@"
+.defense db "DEFENSE@"
+.speed   db "SPEED@"
+.special db "SPECIAL@"
+; eed9
+
+
+GetStatExpRelativePointer: ; eed9
+	ld a, [wCurItem]
+	ld hl, Table_eeeb
+.next
+	cp [hl]
+	inc hl
+	jr z, .got_it
+	inc hl
+	jr .next
+
+.got_it
+	ld a, [hl]
+	ld c, a
+	ld b, 0
+	ret
+; eeeb
+
+Table_eeeb: ; eeeb
+	db HP_UP,    MON_HP_EXP - MON_STAT_EXP
+	db PROTEIN, MON_ATK_EXP - MON_STAT_EXP
+	db IRON,    MON_DEF_EXP - MON_STAT_EXP
+	db CARBOS,  MON_SPD_EXP - MON_STAT_EXP
+	db CALCIUM, MON_SPC_EXP - MON_STAT_EXP
+; eef5
+
+
+RareCandy_StatBooster_GetParameters: ; eef5
+	ld a, [wCurPartySpecies]
+	ld [wCurSpecies], a
+	ld [wd265], a
+	ld a, MON_LEVEL
+	call GetPartyParamLocation
+	ld a, [hl]
+	ld [wCurPartyLevel], a
+	call GetBaseData
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMonNicknames
+	call GetNick
+	ret
+; 0xef14
+
+
+RareCandyEffect: ; ef14
+	ld b, PARTYMENUACTION_HEALING_ITEM
+	call UseItem_SelectMon
+
+	jp c, RareCandy_StatBooster_ExitMenu
+
+	call RareCandy_StatBooster_GetParameters
+
+	ld a, MON_LEVEL
+	call GetPartyParamLocation
+
+	ld a, [hl]
+	cp MAX_LEVEL
+	jp nc, NoEffectMessage
+
+	inc a
+	ld [hl], a
+	ld [wCurPartyLevel], a
+	push de
+	ld d, a
+	farcall CalcExpAtLevel
+
+	pop de
+	ld a, MON_EXP
+	call GetPartyParamLocation
+
+	ld a, [hMultiplicand]
+	ld [hli], a
+	ld a, [hMultiplicand + 1]
+	ld [hli], a
+	ld a, [hMultiplicand + 2]
+	ld [hl], a
+
+	ld a, MON_MAXHP
+	call GetPartyParamLocation
+	ld a, [hli]
+	ld b, a
+	ld c, [hl]
+	push bc
+	call UpdateStatsAfterItem
+
+	ld a, MON_MAXHP + 1
+	call GetPartyParamLocation
+
+	pop bc
+	ld a, [hld]
+	sub c
+	ld c, a
+	ld a, [hl]
+	sbc b
+	ld b, a
+	dec hl
+	ld a, [hl]
+	add c
+	ld [hld], a
+	ld a, [hl]
+	adc b
+	ld [hl], a
+	farcall LevelUpHappinessMod
+
+	ld a, PARTYMENUTEXT_LEVEL_UP
+	call ItemActionText
+
+	xor a ; PARTYMON
+	ld [wMonType], a
+	predef CopyMonToTempMon
+
+	hlcoord 9, 0
+	ld b, 10
+	ld c, 9
+	call TextBox
+
+	hlcoord 11, 1
+	ld bc, 4
+	predef PrintTempMonStats
+
+	call WaitPressAorB_BlinkCursor
+
+	xor a ; PARTYMON
+	ld [wMonType], a
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	predef LearnLevelMoves
+
+	xor a
+	ld [wForceEvolution], a
+	farcall EvolvePokemon
+
+	jp UseDisposableItem
+; efad
+
+
+HealPowderEffect: ; efad
+	ld b, PARTYMENUACTION_HEALING_ITEM
+	call UseItem_SelectMon
+
+	jp c, StatusHealer_ExitMenu
+
+	call UseStatusHealer
+
+	cp $0
+	jr nz, .asm_efc9
+	ld c, HAPPINESS_BITTERPOWDER
+	farcall ChangeHappiness
+
+	call LooksBitterMessage
+
+	ld a, $0
+
+.asm_efc9
+	jp StatusHealer_Jumptable
+; efcc
+
+
+StatusHealingEffect: ; efcc
+	ld b, PARTYMENUACTION_HEALING_ITEM
+	call UseItem_SelectMon
+	jp c, StatusHealer_ExitMenu
+
+FullyHealStatus: ; efd4
+	call UseStatusHealer
+	jp StatusHealer_Jumptable
+; efda
+
+
+UseStatusHealer: ; efda (3:6fda)
+	call IsMonFainted
+	ld a, $1
+	ret z
+	call GetItemHealingAction
+	ld a, MON_STATUS
+	call GetPartyParamLocation
+	ld a, [hl]
+	and c
+	jr nz, .good
+	call IsItemUsedOnConfusedMon
+	ld a, $1
+	ret nc
+	ld b, PARTYMENUTEXT_HEAL_CONFUSION
+.good
+	xor a
+	ld [hl], a
+	ld a, b
+	ld [wPartyMenuActionText], a
+	call HealStatus
+	call Play_SFX_FULL_HEAL
+	call ItemActionTextWaitButton
+	call UseDisposableItem
+	ld a, $0
+	ret
+
+IsItemUsedOnConfusedMon: ; f009 (3:7009)
+	call IsItemUsedOnBattleMon
+	jr nc, .nope
+	ld a, [wPlayerSubStatus3]
+	bit SUBSTATUS_CONFUSED, a
+	jr z, .nope
+	ld a, c
+	cp $ff
+	jr nz, .nope
+	scf
+	ret
+
+.nope
+	and a
+	ret
+
+BattlemonRestoreHealth: ; f01e (3:701e)
+	call IsItemUsedOnBattleMon
+	ret nc
+	ld a, MON_HP
+	call GetPartyParamLocation
+	ld a, [hli]
+	ld [wBattleMonHP], a
+	ld a, [hld]
+	ld [wBattleMonHP + 1], a
+	ret
+
+HealStatus: ; f030 (3:7030)
+	call IsItemUsedOnBattleMon
+	ret nc
+	xor a
+	ld [wBattleMonStatus], a
+	ld hl, wPlayerSubStatus5
+	res SUBSTATUS_TOXIC, [hl]
+	ld hl, wPlayerSubStatus1
+	res SUBSTATUS_NIGHTMARE, [hl]
+	call GetItemHealingAction
+	ld a, c
+	cp %11111111
+	jr nz, .not_full_heal
+	ld hl, wPlayerSubStatus3
+	res SUBSTATUS_CONFUSED, [hl]
+.not_full_heal
+	push bc
+	farcall CalcPlayerStats
+	pop bc
+	ret
+
+GetItemHealingAction: ; f058 (3:7058)
+	push hl
+	ld a, [wCurItem]
+	ld hl, StatusHealingActions
+	ld bc, 3
+.next
+	cp [hl]
+	jr z, .found_it
+	add hl, bc
+	jr .next
+
+.found_it
+	inc hl
+	ld b, [hl]
+	inc hl
+	ld a, [hl]
+	ld c, a
+	cp %11111111
+	pop hl
+	ret
+; f071 (3:7071)
+
+INCLUDE "data/items/heal_status.asm"
+
+StatusHealer_Jumptable: ; f09e (3:709e)
+	ld hl, .dw
+	rst JumpTable
+	ret
+
+.dw ; f0a3 (3:70a3)
+	dw StatusHealer_ClearPalettes
+	dw StatusHealer_NoEffect
+	dw StatusHealer_ExitMenu
+
+
+RevivalHerbEffect: ; f0a9
+	ld b, PARTYMENUACTION_HEALING_ITEM
+	call UseItem_SelectMon
+	jp c, StatusHealer_ExitMenu
+
+	call RevivePokemon
+	cp 0
+	jr nz, .asm_f0c5
+
+	ld c, HAPPINESS_REVIVALHERB
+	farcall ChangeHappiness
+	call LooksBitterMessage
+	ld a, 0
+
+.asm_f0c5
+	jp StatusHealer_Jumptable
+; f0c8
+
+
+ReviveEffect: ; f0c8
+	ld b, PARTYMENUACTION_HEALING_ITEM
+	call UseItem_SelectMon
+	jp c, StatusHealer_ExitMenu
+
+	call RevivePokemon
+	jp StatusHealer_Jumptable
+; f0d6
+
+
+RevivePokemon: ; f0d6
+	call IsMonFainted
+	ld a, 1
+	ret nz
+	ld a, [wBattleMode]
+	and a
+	jr z, .skip_to_revive
+
+	ld a, [wCurPartyMon]
+	ld c, a
+	ld d, 0
+	ld hl, wBattleParticipantsIncludingFainted
+	ld b, CHECK_FLAG
+	predef SmallFarFlagAction
+	ld a, c
+	and a
+	jr z, .skip_to_revive
+
+	ld a, [wCurPartyMon]
+	ld c, a
+	ld hl, wBattleParticipantsNotFainted
+	ld b, SET_FLAG
+	predef SmallFarFlagAction
+
+.skip_to_revive
+	xor a
+	ld [wLowHealthAlarm], a
+	ld a, [wCurItem]
+	cp REVIVE
+	jr z, .revive_half_hp
+
+	call ReviveFullHP
+	jr .finish_revive
+
+.revive_half_hp
+	call ReviveHalfHP
+
+.finish_revive
+	call HealHP_SFX_GFX
+	ld a, PARTYMENUTEXT_REVIVE
+	ld [wPartyMenuActionText], a
+	call ItemActionTextWaitButton
+	call UseDisposableItem
+	ld a, 0
+	ret
+; f128
+
+
+FullRestoreEffect: ; f128
+	ld b, PARTYMENUACTION_HEALING_ITEM
+	call UseItem_SelectMon
+	jp c, StatusHealer_ExitMenu
+
+	call IsMonFainted
+	jp z, StatusHealer_NoEffect
+
+	call IsMonAtFullHealth
+	jr c, .NotAtFullHealth
+
+	jp FullyHealStatus
+
+.NotAtFullHealth:
+	call .FullRestore
+	jp StatusHealer_Jumptable
+; f144
+
+
+.FullRestore: ; f144
+	xor a
+	ld [wLowHealthAlarm], a
+	call ReviveFullHP
+	ld a, MON_STATUS
+	call GetPartyParamLocation
+	xor a
+	ld [hli], a
+	ld [hl], a
+	call HealStatus
+	call BattlemonRestoreHealth
+	call HealHP_SFX_GFX
+	ld a, PARTYMENUTEXT_HEAL_HP
+	ld [wPartyMenuActionText], a
+	call ItemActionTextWaitButton
+	call UseDisposableItem
+	ld a, 0
+	ret
+; f16a
+
+
+BitterBerryEffect: ; f16a
+	ld hl, wPlayerSubStatus3
+	bit SUBSTATUS_CONFUSED, [hl]
+	ld a, 1
+	jr z, .done
+
+	res SUBSTATUS_CONFUSED, [hl]
+	xor a
+	ld [hBattleTurn], a
+	call UseItemText
+
+	ld hl, ConfusedNoMoreText
+	call StdBattleTextBox
+
+	ld a, 0
+
+.done
+	jp StatusHealer_Jumptable
+; f186
+
+
+RestoreHPEffect: ; f186
+	call ItemRestoreHP
+	jp StatusHealer_Jumptable
+; f18c
+
+
+EnergypowderEffect: ; f18c
+	ld c, HAPPINESS_BITTERPOWDER
+	jr EnergypowderEnergyRootCommon
+; f190
+
+EnergyRootEffect: ; f190
+	ld c, HAPPINESS_ENERGYROOT
+; f192
+
+EnergypowderEnergyRootCommon: ; f192
+	push bc
+	call ItemRestoreHP
+	pop bc
+	cp 0
+	jr nz, .skip_happiness
+
+	farcall ChangeHappiness
+	call LooksBitterMessage
+	ld a, 0
+
+.skip_happiness
+	jp StatusHealer_Jumptable
+; f1a9
+
+
+ItemRestoreHP: ; f1a9 (3:71a9)
+	ld b, PARTYMENUACTION_HEALING_ITEM
+	call UseItem_SelectMon
+	ld a, 2
+	ret c
+
+	call IsMonFainted
+	ld a, 1
+	ret z
+
+	call IsMonAtFullHealth
+	ld a, 1
+	ret nc
+
+	xor a
+	ld [wLowHealthAlarm], a
+	call GetHealingItemAmount
+	call RestoreHealth
+	call BattlemonRestoreHealth
+	call HealHP_SFX_GFX
+	ld a, PARTYMENUTEXT_HEAL_HP
+	ld [wPartyMenuActionText], a
+	call ItemActionTextWaitButton
+	call UseDisposableItem
+	ld a, 0
+	ret
+
+HealHP_SFX_GFX: ; f1db (3:71db)
+	push de
+	ld de, SFX_POTION
+	call WaitPlaySFX
+	pop de
+	ld a, [wCurPartyMon]
+	hlcoord 11, 0
+	ld bc, SCREEN_WIDTH * 2
+	call AddNTimes
+	ld a, $2
+	ld [wWhichHPBar], a
+	predef_jump AnimateHPBar
+
+UseItem_SelectMon: ; f1f9 (3:71f9)
+	call .SelectMon
+	ret c
+
+	ld a, [wCurPartySpecies]
+	cp EGG
+	jr nz, .not_egg
+
+	call CantUseOnEggMessage
+	scf
+	ret
+
+.not_egg
+	and a
+	ret
+
+.SelectMon: ; f20b (3:720b)
+	ld a, b
+	ld [wPartyMenuActionText], a
+	push hl
+	push de
+	push bc
+	call ClearBGPalettes
+	call ChooseMonToUseItemOn
+	pop bc
+	pop de
+	pop hl
+	ret
+
+ChooseMonToUseItemOn: ; f21c (3:721c)
+	farcall LoadPartyMenuGFX
+	farcall InitPartyMenuWithCancel
+	farcall InitPartyMenuGFX
+	farcall WritePartyMenuTilemap
+	farcall PrintPartyMenuText
+	call WaitBGMap
+	call SetPalettes
+	call DelayFrame
+	farcall PartyMenuSelect
+	ret
+
+ItemActionText: ; f24a (3:724a)
+	ld [wPartyMenuActionText], a
+	ld a, [wCurPartySpecies]
+	push af
+	ld a, [wCurPartyMon]
+	push af
+	push hl
+	push de
+	push bc
+	farcall WritePartyMenuTilemap
+	farcall PrintPartyMenuActionText
+	call WaitBGMap
+	call SetPalettes
+	call DelayFrame
+	pop bc
+	pop de
+	pop hl
+	pop af
+	ld [wCurPartyMon], a
+	pop af
+	ld [wCurPartySpecies], a
+	ret
+
+ItemActionTextWaitButton: ; f279 (3:7279)
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 0, 0
+	ld bc, wTileMapEnd - wTileMap
+	ld a, " "
+	call ByteFill
+	ld a, [wPartyMenuActionText]
+	call ItemActionText
+	ld a, $1
+	ld [hBGMapMode], a
+	ld c, 50
+	call DelayFrames
+	jp WaitPressAorB_BlinkCursor
+
+StatusHealer_NoEffect: ; f299 (3:7299)
+	call WontHaveAnyEffectMessage
+	jr StatusHealer_ClearPalettes
+
+StatusHealer_ExitMenu: ; f29e (3:729e)
+	xor a
+	ld [wItemEffectSucceeded], a
+StatusHealer_ClearPalettes: ; f2a2 (3:72a2)
+	call ClearPalettes
+	ret
+
+IsItemUsedOnBattleMon: ; f2a6 (3:72a6)
+	ld a, [wBattleMode]
+	and a
+	ret z
+	ld a, [wCurPartyMon]
+	push hl
+	ld hl, wCurBattleMon
+	cp [hl]
+	pop hl
+	jr nz, .nope
+	scf
+	ret
+
+.nope
+	xor a
+	ret
+
+ReviveHalfHP: ; f2ba (3:72ba)
+	call LoadHPFromBuffer1
+	srl d
+	rr e
+	jr ContinueRevive
+
+ReviveFullHP: ; f2c3 (3:72c3)
+	call LoadHPFromBuffer1
+ContinueRevive: ; f2c6 (3:72c6)
+	ld a, MON_HP
+	call GetPartyParamLocation
+	ld [hl], d
+	inc hl
+	ld [hl], e
+	jp LoadCurHPIntoBuffer5
+
+RestoreHealth: ; f2d1 (3:72d1)
+	ld a, MON_HP + 1
+	call GetPartyParamLocation
+	ld a, [hl]
+	add e
+	ld [hld], a
+	ld a, [hl]
+	adc d
+	ld [hl], a
+	jr c, .full_hp
+	call LoadCurHPIntoBuffer5
+	ld a, MON_HP + 1
+	call GetPartyParamLocation
+	ld d, h
+	ld e, l
+	ld a, MON_MAXHP + 1
+	call GetPartyParamLocation
+	ld a, [de]
+	sub [hl]
+	dec de
+	dec hl
+	ld a, [de]
+	sbc [hl]
+	jr c, .finish
+.full_hp
+	call ReviveFullHP
+.finish
+	ret
+
+RemoveHP: ; f2f9 (3:72f9)
+	ld a, MON_HP + 1
+	call GetPartyParamLocation
+	ld a, [hl]
+	sub e
+	ld [hld], a
+	ld a, [hl]
+	sbc d
+	ld [hl], a
+	jr nc, .okay
+	xor a
+	ld [hld], a
+	ld [hl], a
+.okay
+	call LoadCurHPIntoBuffer5
+	ret
+
+IsMonFainted: ; f30d (3:730d)
+	push de
+	call LoadMaxHPToBuffer1
+	call LoadCurHPToBuffer3
+	call LoadHPFromBuffer3
+	ld a, d
+	or e
+	pop de
+	ret
+
+IsMonAtFullHealth: ; f31b (3:731b)
+	call LoadHPFromBuffer3
+	ld h, d
+	ld l, e
+	call LoadHPFromBuffer1
+	ld a, l
+	sub e
+	ld a, h
+	sbc d
+	ret
+
+LoadCurHPIntoBuffer5: ; f328 (3:7328)
+	ld a, MON_HP
+	call GetPartyParamLocation
+	ld a, [hli]
+	ld [wBuffer6], a
+	ld a, [hl]
+	ld [wBuffer5], a
+	ret
+; f336 (3:7336)
+
+LoadHPIntoBuffer5: ; f336
+	ld a, d
+	ld [wBuffer6], a
+	ld a, e
+	ld [wBuffer5], a
+	ret
+; f33f
+
+LoadHPFromBuffer5: ; f33f
+	ld a, [wBuffer6]
+	ld d, a
+	ld a, [wBuffer5]
+	ld e, a
+	ret
+; f348
+
+LoadCurHPToBuffer3: ; f348 (3:7348)
+	ld a, MON_HP
+	call GetPartyParamLocation
+	ld a, [hli]
+	ld [wBuffer4], a
+	ld a, [hl]
+	ld [wBuffer3], a
+	ret
+
+LoadHPFromBuffer3: ; f356 (3:7356)
+	ld a, [wBuffer4]
+	ld d, a
+	ld a, [wBuffer3]
+	ld e, a
+	ret
+
+LoadMaxHPToBuffer1: ; f35f (3:735f)
+	push hl
+	ld a, MON_MAXHP
+	call GetPartyParamLocation
+	ld a, [hli]
+	ld [wBuffer2], a
+	ld a, [hl]
+	ld [wBuffer1], a
+	pop hl
+	ret
+
+LoadHPFromBuffer1: ; f36f (3:736f)
+	ld a, [wBuffer2]
+	ld d, a
+	ld a, [wBuffer1]
+	ld e, a
+	ret
+
+GetOneFifthMaxHP: ; f378 (3:7378)
+	push bc
+	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, [hQuotient + 1]
+	ld d, a
+	ld a, [hQuotient + 2]
+	ld e, a
+	pop bc
+	ret
+
+GetHealingItemAmount: ; f395 (3:7395)
+	push hl
+	ld a, [wCurItem]
+	ld hl, HealingHPAmounts
+	ld d, a
+.next
+	ld a, [hli]
+	cp -1
+	jr z, .NotFound
+	cp d
+	jr z, .done
+	inc hl
+	inc hl
+	jr .next
+
+.NotFound:
+	scf
+.done
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	pop hl
+	ret
+; f3af (3:73af)
+
+INCLUDE "data/items/heal_hp.asm"
+
+Softboiled_MilkDrinkFunction: ; f3df (3:73df)
+; Softboiled/Milk Drink in the field
+	ld a, [wPartyMenuCursor]
+	dec a
+	ld b, a
+	call .SelectMilkDrinkRecipient ; select pokemon
+	jr c, .skip
+	ld a, b
+	ld [wCurPartyMon], a
+	call IsMonFainted
+	call GetOneFifthMaxHP
+	call RemoveHP
+	push bc
+	call HealHP_SFX_GFX
+	pop bc
+	call GetOneFifthMaxHP
+	ld a, c
+	ld [wCurPartyMon], a
+	call IsMonFainted
+	call RestoreHealth
+	call HealHP_SFX_GFX
+	ld a, PARTYMENUTEXT_HEAL_HP
+	call ItemActionText
+	call JoyWaitAorB
+.skip
+	ld a, b
+	inc a
+	ld [wPartyMenuCursor], a
+	ret
+
+.SelectMilkDrinkRecipient: ; f419 (3:7419)
+.loop
+	push bc
+	ld a, PARTYMENUACTION_HEALING_ITEM
+	ld [wPartyMenuActionText], a
+	call ChooseMonToUseItemOn
+	pop bc
+	jr c, .set_carry
+	ld a, [wPartyMenuCursor]
+	dec a
+	ld c, a
+	ld a, b
+	cp c
+	jr z, .cant_use ; chose the same mon as user
+	ld a, c
+	ld [wCurPartyMon], a
+	call IsMonFainted
+	jr z, .cant_use
+	call IsMonAtFullHealth
+	jr nc, .cant_use
+	xor a
+	ret
+
+.set_carry
+	scf
+	ret
+
+.cant_use
+	push bc
+	ld hl, .Text_CantBeUsed
+	call MenuTextBoxBackup
+	pop bc
+	jr .loop
+; f44a (3:744a)
+
+.Text_CantBeUsed: ; 0xf44a
+	; That can't be used on this #MON.
+	text_jump UnknownText_0x1c5bac
+	db "@"
+; 0xf44f
+
+
+EscapeRopeEffect: ; f44f
+	xor a
+	ld [wItemEffectSucceeded], a
+	farcall EscapeRopeFunction
+
+	ld a, [wItemEffectSucceeded]
+	cp 1
+	call z, UseDisposableItem
+	ret
+; f462
+
+
+SuperRepelEffect: ; f462
+	ld b, 200
+	jr UseRepel
+; f466
+
+MaxRepelEffect: ; f466
+	ld b, 250
+	jr UseRepel
+; f466
+
+RepelEffect: ; f46a
+	ld b, 100
+; f46c
+
+UseRepel: ; f46c
+	ld a, [wRepelEffect]
+	and a
+	ld hl, TextJump_RepelUsedEarlierIsStillInEffect
+	jp nz, PrintText
+
+	ld a, b
+	ld [wRepelEffect], a
+	jp UseItemText
+
+
+TextJump_RepelUsedEarlierIsStillInEffect: ; 0xf47d
+	; The REPEL used earlier is still in effect.
+	text_jump Text_RepelUsedEarlierIsStillInEffect
+	db "@"
+; 0xf482
+
+
+XAccuracyEffect: ; f482
+	ld hl, wPlayerSubStatus4
+	bit SUBSTATUS_X_ACCURACY, [hl]
+	jp nz, WontHaveAnyEffect_NotUsedMessage
+	set SUBSTATUS_X_ACCURACY, [hl]
+	jp UseItemText
+; f48f
+
+
+PokeDollEffect: ; f48f
+	ld a, [wBattleMode]
+	dec a
+	jr nz, .asm_f4a6
+	inc a
+	ld [wForcedSwitch], a
+	ld a, [wBattleResult]
+	and $c0
+	or $2
+	ld [wBattleResult], a
+	jp UseItemText
+
+.asm_f4a6
+	xor a
+	ld [wItemEffectSucceeded], a
+	ret
+; f4ab
+
+
+GuardSpecEffect: ; f4ab
+	ld hl, wPlayerSubStatus4
+	bit SUBSTATUS_MIST, [hl]
+	jp nz, WontHaveAnyEffect_NotUsedMessage
+	set SUBSTATUS_MIST, [hl]
+	jp UseItemText
+; f4b8
+
+
+DireHitEffect: ; f4b8
+	ld hl, wPlayerSubStatus4
+	bit SUBSTATUS_FOCUS_ENERGY, [hl]
+	jp nz, WontHaveAnyEffect_NotUsedMessage
+	set SUBSTATUS_FOCUS_ENERGY, [hl]
+	jp UseItemText
+; f4c5
+
+
+XItemEffect: ; f4c5
+	call UseItemText
+
+	ld a, [wCurItem]
+	ld hl, XItemStats
+
+.loop
+	cp [hl]
+	jr z, .got_it
+	inc hl
+	inc hl
+	jr .loop
+
+.got_it
+	inc hl
+	ld b, [hl]
+	xor a
+	ld [hBattleTurn], a
+	ld [wAttackMissed], a
+	ld [wEffectFailed], a
+	farcall CheckIfStatCanBeRaised
+	call WaitSFX
+
+	farcall BattleCommand_StatUpMessage
+	farcall BattleCommand_StatUpFailText
+
+	ld a, [wCurBattleMon]
+	ld [wCurPartyMon], a
+	ld c, HAPPINESS_USEDXITEM
+	farcall ChangeHappiness
+	ret
+; f504
+
+INCLUDE "data/items/x_stats.asm"
+
+
+PokeFluteEffect: ; f50c
+	ld a, [wBattleMode]
+	and a
+	jr nz, .dummy
+.dummy
+
+	xor a
+	ld [wd002], a
+
+	ld b, $ff ^ SLP
+
+	ld hl, wPartyMon1Status
+	call .CureSleep
+
+	ld a, [wBattleMode]
+	cp WILD_BATTLE
+	jr z, .skip_otrainer
+	ld hl, wOTPartyMon1Status
+	call .CureSleep
+.skip_otrainer
+
+	ld hl, wBattleMonStatus
+	ld a, [hl]
+	and b
+	ld [hl], a
+	ld hl, wEnemyMonStatus
+	ld a, [hl]
+	and b
+	ld [hl], a
+
+	ld a, [wd002]
+	and a
+	ld hl, .CatchyTune
+	jp z, PrintText
+	ld hl, .PlayedTheFlute
+	call PrintText
+
+	ld a, [wLowHealthAlarm]
+	and 1 << DANGER_ON_F
+	jr nz, .dummy2
+.dummy2
+	ld hl, .AllSleepingMonWokeUp
+	jp PrintText
+
+
+.CureSleep:
+	ld de, PARTYMON_STRUCT_LENGTH
+	ld c, PARTY_LENGTH
+
+.loop
+	ld a, [hl]
+	push af
+	and SLP
+	jr z, .not_asleep
+	ld a, 1
+	ld [wd002], a
+.not_asleep
+	pop af
+	and b
+	ld [hl], a
+	add hl, de
+	dec c
+	jr nz, .loop
+	ret
+; f56c
+
+
+.CatchyTune: ; 0xf56c
+	; Played the # FLUTE. Now, that's a catchy tune!
+	text_jump UnknownText_0x1c5bf9
+	db "@"
+; 0xf571
+
+.AllSleepingMonWokeUp: ; 0xf571
+	; All sleeping #MON woke up.
+	text_jump UnknownText_0x1c5c28
+	db "@"
+; 0xf576
+
+.PlayedTheFlute: ; 0xf576
+	; played the # FLUTE.@ @
+	text_jump UnknownText_0x1c5c44
+	start_asm
+	ld a, [wBattleMode]
+	and a
+	jr nz, .battle
+
+	push de
+	ld de, SFX_POKEFLUTE
+	call WaitPlaySFX
+	call WaitSFX
+	pop de
+
+.battle
+	jp PokeFluteTerminatorCharacter
+; f58f
+
+
+BlueCardEffect: ; f58f
+	ld hl, .bluecardtext
+	jp MenuTextBoxWaitButton
+
+.bluecardtext
+	text_jump UnknownText_0x1c5c5e
+	db "@"
+; f59a
+
+
+CoinCaseEffect: ; f59a
+	ld hl, .coincasetext
+	jp MenuTextBoxWaitButton
+
+.coincasetext
+	text_jump UnknownText_0x1c5c7b
+	db "@"
+; f5a5
+
+
+OldRodEffect: ; f5a5
+	ld e, $0
+	jr UseRod
+; f5a9
+
+GoodRodEffect: ; f5a9
+	ld e, $1
+	jr UseRod
+; f5ad
+
+SuperRodEffect: ; f5ad
+	ld e, $2
+	jr UseRod
+; f5b1
+
+UseRod: ; f5b1
+	farcall FishFunction
+	ret
+; f5b8
+
+
+ItemfinderEffect: ; f5b8
+	farcall ItemFinder
+	ret
+; f5bf
+
+
+RestorePPEffect: ; f5bf
+	ld a, [wCurItem]
+	ld [wd002], a
+
+.loop
+	; Party Screen opens to choose on which mon to use the Item
+	ld b, PARTYMENUACTION_HEALING_ITEM
+	call UseItem_SelectMon
+	jp c, PPRestoreItem_Cancel
+
+.loop2
+	ld a, [wd002]
+	cp MAX_ELIXER
+	jp z, Elixer_RestorePPofAllMoves
+	cp ELIXER
+	jp z, Elixer_RestorePPofAllMoves
+
+	ld hl, TextJump_RaiseThePPOfWhichMove
+	ld a, [wd002]
+	cp PP_UP
+	jr z, .ppup
+	ld hl, TextJump_RestoreThePPOfWhichMove
+
+.ppup
+	call PrintText
+
+	ld a, [wCurMoveNum]
+	push af
+	xor a
+	ld [wCurMoveNum], a
+	ld a, $2
+	ld [wMoveSelectionMenuType], a
+	farcall MoveSelectionScreen
+	pop bc
+
+	ld a, b
+	ld [wCurMoveNum], a
+	jr nz, .loop
+	ld hl, wPartyMon1Moves
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call GetMthMoveOfNthPartymon
+
+	push hl
+	ld a, [hl]
+	ld [wd265], a
+	call GetMoveName
+	call CopyName1
+	pop hl
+
+	ld a, [wd002]
+	cp PP_UP
+	jp nz, Not_PP_Up
+
+	ld a, [hl]
+	cp SKETCH
+	jr z, .CantUsePPUpOnSketch
+
+	ld bc, MON_PP - MON_MOVES
+	add hl, bc
+	ld a, [hl]
+	cp PP_UP_MASK
+	jr c, .do_ppup
+
+.CantUsePPUpOnSketch:
+.pp_is_maxed_out
+	ld hl, TextJump_PPIsMaxedOut
+	call PrintText
+	jr .loop2
+
+.do_ppup
+	ld a, [hl]
+	add PP_UP_ONE
+	ld [hl], a
+	ld a, $1
+	ld [wd265], a
+	call ApplyPPUp
+	call Play_SFX_FULL_HEAL
+
+	ld hl, TextJump_PPsIncreased
+	call PrintText
+
+FinishPPRestore: ; f64c
+	call ClearPalettes
+	jp UseDisposableItem
+; f652
+
+BattleRestorePP: ; f652
+	ld a, [wBattleMode]
+	and a
+	jr z, .not_in_battle
+	ld a, [wCurPartyMon]
+	ld b, a
+	ld a, [wCurBattleMon]
+	cp b
+	jr nz, .not_in_battle
+	ld a, [wPlayerSubStatus5]
+	bit SUBSTATUS_TRANSFORMED, a
+	jr nz, .not_in_battle
+	call .UpdateBattleMonPP
+
+.not_in_battle
+	call Play_SFX_FULL_HEAL
+	ld hl, UnknownText_0xf739
+	call PrintText
+	jr FinishPPRestore
+
+.UpdateBattleMonPP:
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1Moves
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld de, wBattleMonMoves
+	ld b, NUM_MOVES
+.loop
+	ld a, [de]
+	and a
+	jr z, .done
+	cp [hl]
+	jr nz, .next
+	push hl
+	push de
+	push bc
+	rept NUM_MOVES + 2 ; wBattleMonPP - wBattleMonMoves
+	inc de
+	endr
+	ld bc, MON_PP - MON_MOVES
+	add hl, bc
+	ld a, [hl]
+	ld [de], a
+	pop bc
+	pop de
+	pop hl
+
+.next
+	inc hl
+	inc de
+	dec b
+	jr nz, .loop
+
+.done
+	ret
+; f6a7
+
+Not_PP_Up: ; f6a7
+	call RestorePP
+	jr nz, BattleRestorePP
+	jp PPRestoreItem_NoEffect
+; f6af
+
+Elixer_RestorePPofAllMoves: ; f6af
+	xor a
+	ld hl, wMenuCursorY
+	ld [hli], a
+	ld [hl], a
+	ld b, NUM_MOVES
+.moveLoop
+	push bc
+	ld hl, wPartyMon1Moves
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call GetMthMoveOfNthPartymon
+	ld a, [hl]
+	and a
+	jr z, .next
+
+	call RestorePP
+	jr z, .next
+	ld hl, wMenuCursorX
+	inc [hl]
+
+.next
+	ld hl, wMenuCursorY
+	inc [hl]
+	pop bc
+	dec b
+	jr nz, .moveLoop
+	ld a, [wMenuCursorX]
+	and a
+	jp nz, BattleRestorePP
+
+PPRestoreItem_NoEffect: ; f6dd
+	call WontHaveAnyEffectMessage
+
+PPRestoreItem_Cancel: ; f6e0
+	call ClearPalettes
+	xor a
+	ld [wItemEffectSucceeded], a
+	ret
+; f6e8
+
+RestorePP: ; f6e8
+	xor a ; PARTYMON
+	ld [wMonType], a
+	call GetMaxPPOfMove
+	ld hl, wPartyMon1PP
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call GetMthMoveOfNthPartymon
+	ld a, [wd265]
+	ld b, a
+	ld a, [hl]
+	and PP_MASK
+	cp b
+	jr nc, .dont_restore
+
+	ld a, [wd002]
+	cp MAX_ELIXER
+	jr z, .restore_all
+	cp MAX_ETHER
+	jr z, .restore_all
+
+	ld c, 5
+	cp MYSTERYBERRY
+	jr z, .restore_some
+
+	ld c, 10
+
+.restore_some
+	ld a, [hl]
+	and PP_MASK
+	add c
+	cp b
+	jr nc, .restore_all
+	ld b, a
+
+.restore_all
+	ld a, [hl]
+	and PP_UP_MASK
+	or b
+	ld [hl], a
+	ret
+
+.dont_restore
+	xor a
+	ret
+; f725
+
+TextJump_RaiseThePPOfWhichMove: ; 0xf725
+	; Raise the PP of which move?
+	text_jump Text_RaiseThePPOfWhichMove
+	db "@"
+; 0xf72a
+
+TextJump_RestoreThePPOfWhichMove: ; 0xf72a
+	; Restore the PP of which move?
+	text_jump Text_RestoreThePPOfWhichMove
+	db "@"
+; 0xf72f
+
+TextJump_PPIsMaxedOut: ; 0xf72f
+	; 's PP is maxed out.
+	text_jump Text_PPIsMaxedOut
+	db "@"
+; 0xf734
+
+TextJump_PPsIncreased: ; 0xf734
+	; 's PP increased.
+	text_jump Text_PPsIncreased
+	db "@"
+; 0xf739
+
+UnknownText_0xf739: ; 0xf739
+	; PP was restored.
+	text_jump UnknownText_0x1c5cf1
+	db "@"
+; 0xf73e
+
+
+SquirtbottleEffect: ; f73e
+	farcall _Squirtbottle
+	ret
+; f745
+
+
+CardKeyEffect: ; f745
+	farcall _CardKey
+	ret
+; f74c
+
+
+BasementKeyEffect: ; f74c
+	farcall _BasementKey
+	ret
+; f753
+
+
+SacredAshEffect: ; f753
+	farcall _SacredAsh
+	ld a, [wItemEffectSucceeded]
+	cp $1
+	ret nz
+	call UseDisposableItem
+	ret
+; f763
+
+
+NormalBoxEffect: ; f763
+	ld c, DECOFLAG_SILVER_TROPHY_DOLL
+	jr OpenBox
+; f767
+
+GorgeousBoxEffect: ; f767
+	ld c, DECOFLAG_GOLD_TROPHY_DOLL
+OpenBox: ; f769
+	farcall SetSpecificDecorationFlag
+
+	ld hl, .text
+	call PrintText
+
+	jp UseDisposableItem
+; f778
+
+.text ; 0xf778
+	; There was a trophy inside!
+	text_jump UnknownText_0x1c5d03
+	db "@"
+; 0xf77d
+
+NoEffect: ; f77d
+	jp IsntTheTimeMessage
+; f780
+
+
+Play_SFX_FULL_HEAL: ; f780
+	push de
+	ld de, SFX_FULL_HEAL
+	call WaitPlaySFX
+	pop de
+	ret
+; f789
+
+UseItemText: ; f789
+	ld hl, UsedItemText
+	call PrintText
+	call Play_SFX_FULL_HEAL
+	call WaitPressAorB_BlinkCursor
+UseDisposableItem: ; f795
+	ld hl, wNumItems
+	ld a, 1
+	ld [wItemQuantityChangeBuffer], a
+	jp TossItem
+; f7a0
+
+UseBallInTrainerBattle: ; f7a0
+	call ReturnToBattle_UseBall
+	ld de, ANIM_THROW_POKE_BALL
+	ld a, e
+	ld [wFXAnimID], a
+	ld a, d
+	ld [wFXAnimID + 1], a
+	xor a
+	ld [wBattleAnimParam], a
+	ld [hBattleTurn], a
+	ld [wNumHits], a
+	predef PlayBattleAnim
+	ld hl, BlockedTheBallText
+	call PrintText
+	ld hl, DontBeAThiefText
+	call PrintText
+	jr UseDisposableItem
+; f7ca
+
+WontHaveAnyEffect_NotUsedMessage: ; f7ca
+	ld hl, WontHaveAnyEffectText
+	call PrintText
+
+	; Item wasn't used.
+	ld a, $2
+	ld [wItemEffectSucceeded], a
+	ret
+; f7d6
+
+LooksBitterMessage: ; f7d6
+	ld hl, LooksBitterText
+	jp PrintText
+; f7dc
+
+Ball_BoxIsFullMessage: ; f7dc
+	ld hl, Ball_BoxIsFullText
+	call PrintText
+
+	; Item wasn't used.
+	ld a, $2
+	ld [wItemEffectSucceeded], a
+	ret
+; f7e8
+
+CantUseOnEggMessage: ; f7e8
+	ld hl, CantUseOnEggText
+	jr CantUseItemMessage
+
+IsntTheTimeMessage: ; f7ed
+	ld hl, IsntTheTimeText
+	jr CantUseItemMessage
+
+WontHaveAnyEffectMessage: ; f7f2
+	ld hl, WontHaveAnyEffectText
+	jr CantUseItemMessage
+
+BelongsToSomeoneElseMessage: ; f7f7
+	ld hl, BelongsToSomeoneElseText
+	jr CantUseItemMessage
+
+CyclingIsntAllowedMessage: ; f7fc
+	ld hl, CyclingIsntAllowedText
+	jr CantUseItemMessage
+
+CantGetOnYourBikeMessage: ; f801
+	ld hl, CantGetOnYourBikeText
+
+CantUseItemMessage: ; f804
+; Item couldn't be used.
+	xor a
+	ld [wItemEffectSucceeded], a
+	jp PrintText
+; f80b
+
+LooksBitterText: ; 0xf80b
+	; It looks bitter…
+	text_jump UnknownText_0x1c5d3e
+	db "@"
+; 0xf810
+
+CantUseOnEggText: ; 0xf810
+	; That can't be used on an EGG.
+	text_jump UnknownText_0x1c5d50
+	db "@"
+; 0xf815
+
+IsntTheTimeText: ; 0xf815
+	; OAK:  ! This isn't the time to use that!
+	text_jump UnknownText_0x1c5d6e
+	db "@"
+; 0xf81a
+
+BelongsToSomeoneElseText: ; 0xf81a
+	; That belongs to someone else!
+	text_jump UnknownText_0x1c5d97
+	db "@"
+; 0xf81f
+
+WontHaveAnyEffectText: ; 0xf81f
+	; It won't have any effect.
+	text_jump UnknownText_0x1c5db6
+	db "@"
+; 0xf824
+
+BlockedTheBallText: ; 0xf824
+	; The trainer blocked the BALL!
+	text_jump UnknownText_0x1c5dd0
+	db "@"
+; 0xf829
+
+DontBeAThiefText: ; 0xf829
+	; Don't be a thief!
+	text_jump UnknownText_0x1c5def
+	db "@"
+; 0xf82e
+
+CyclingIsntAllowedText: ; 0xf82e
+	; Cycling isn't allowed here.
+	text_jump UnknownText_0x1c5e01
+	db "@"
+; 0xf833
+
+CantGetOnYourBikeText: ; 0xf833
+	; Can't get on your @  now.
+	text_jump UnknownText_0x1c5e1d
+	db "@"
+; 0xf838
+
+Ball_BoxIsFullText: ; 0xf838
+	; The #MON BOX is full. That can't be used now.
+	text_jump UnknownText_0x1c5e3a
+	db "@"
+; 0xf83d
+
+UsedItemText: ; 0xf83d
+	; used the@ .
+	text_jump UnknownText_0x1c5e68
+	db "@"
+; 0xf842
+
+GotOnTheItemText: ; 0xf842
+	; got on the@ .
+	text_jump UnknownText_0x1c5e7b
+	db "@"
+; 0xf847
+
+GotOffTheItemText: ; 0xf847
+	; got off@ the @ .
+	text_jump UnknownText_0x1c5e90
+	db "@"
+; 0xf84c
+
+
+ApplyPPUp: ; f84c
+	ld a, MON_MOVES
+	call GetPartyParamLocation
+	push hl
+	ld de, wBuffer1
+	predef FillPP
+	pop hl
+	ld bc, MON_PP - MON_MOVES
+	add hl, bc
+	ld de, wBuffer1
+	ld b, 0
+.loop
+	inc b
+	ld a, b
+	cp NUM_MOVES + 1
+	ret z
+	ld a, [wd265]
+	dec a
+	jr nz, .use
+	ld a, [wMenuCursorY]
+	inc a
+	cp b
+	jr nz, .skip
+
+.use
+	ld a, [hl]
+	and PP_UP_MASK
+	ld a, [de] ; wasted cycle
+	call nz, ComputeMaxPP
+
+.skip
+	inc hl
+	inc de
+	jr .loop
+; f881
+
+
+
+ComputeMaxPP: ; f881
+	push bc
+	; Divide the base PP by 5.
+	ld a, [de]
+	ld [hDividend + 3], a
+	xor a
+	ld [hDividend], a
+	ld [hDividend + 1], a
+	ld [hDividend + 2], a
+	ld a, 5
+	ld [hDivisor], a
+	ld b, 4
+	call Divide
+	; Get the number of PP, which are bits 6 and 7 of the PP value stored in RAM.
+	ld a, [hl]
+	ld b, a
+	swap a
+	and $f
+	srl a
+	srl a
+	ld c, a
+	; If this value is 0, we are done
+	and a
+	jr z, .NoPPUp
+
+.loop
+	; Normally, a move with 40 PP would have 64 PP with three PP Ups.
+	; Since this would overflow into bit 6, we prevent that from happening
+	; by decreasing the extra amount of PP each PP Up provides, resulting
+	; in a maximum of 61.
+	ld a, [hQuotient + 2]
+	cp $8
+	jr c, .okay
+	ld a, $7
+
+.okay
+	add b
+	ld b, a
+	ld a, [wd265]
+	dec a
+	jr z, .NoPPUp
+	dec c
+	jr nz, .loop
+
+.NoPPUp:
+	ld [hl], b
+	pop bc
+	ret
+; f8b9
+
+RestoreAllPP: ; f8b9
+	ld a, MON_PP
+	call GetPartyParamLocation
+	push hl
+	ld a, MON_MOVES
+	call GetPartyParamLocation
+	pop de
+	xor a ; PARTYMON
+	ld [wMenuCursorY], a
+	ld [wMonType], a
+	ld c, NUM_MOVES
+.loop
+	ld a, [hli]
+	and a
+	ret z
+	push hl
+	push de
+	push bc
+	call GetMaxPPOfMove
+	pop bc
+	pop de
+	ld a, [de]
+	and PP_UP_MASK
+	ld b, a
+	ld a, [wd265]
+	add b
+	ld [de], a
+	inc de
+	ld hl, wMenuCursorY
+	inc [hl]
+	pop hl
+	dec c
+	jr nz, .loop
+	ret
+; f8ec
+
+
+GetMaxPPOfMove: ; f8ec
+	ld a, [wStringBuffer1 + 0]
+	push af
+	ld a, [wStringBuffer1 + 1]
+	push af
+
+	ld a, [wMonType]
+	and a
+
+	ld hl, wPartyMon1Moves
+	ld bc, PARTYMON_STRUCT_LENGTH
+	jr z, .got_partymon ; PARTYMON
+
+	ld hl, wOTPartyMon1Moves
+	dec a
+	jr z, .got_partymon ; OTPARTYMON
+
+	ld hl, wTempMonMoves
+	dec a
+	jr z, .got_nonpartymon ; BOXMON
+
+	ld hl, wTempMonMoves ; Wasted cycles
+	dec a
+	jr z, .got_nonpartymon ; TEMPMON
+
+	ld hl, wBattleMonMoves ; WILDMON
+
+.got_nonpartymon ; BOXMON, TEMPMON, WILDMON
+	call GetMthMoveOfCurrentMon
+	jr .gotdatmove
+
+.got_partymon ; PARTYMON, OTPARTYMON
+	call GetMthMoveOfNthPartymon
+
+.gotdatmove
+	ld a, [hl]
+	dec a
+
+	push hl
+	ld hl, Moves + MOVE_PP
+	ld bc, MOVE_LENGTH
+	call AddNTimes
+	ld a, BANK(Moves)
+	call GetFarByte
+	ld b, a
+	ld de, wStringBuffer1
+	ld [de], a
+	pop hl
+
+	push bc
+	ld bc, MON_PP - MON_MOVES
+	ld a, [wMonType]
+	cp WILDMON
+	jr nz, .notwild
+	ld bc, wEnemyMonPP - wEnemyMonMoves
+.notwild
+	add hl, bc
+	ld a, [hl]
+	and PP_UP_MASK
+	pop bc
+
+	or b
+	ld hl, wStringBuffer1 + 1
+	ld [hl], a
+	xor a
+	ld [wd265], a
+	ld a, b ; this gets lost anyway
+	call ComputeMaxPP
+	ld a, [hl]
+	and PP_MASK
+	ld [wd265], a
+
+	pop af
+	ld [wStringBuffer1 + 1], a
+	pop af
+	ld [wStringBuffer1 + 0], a
+	ret
+; f963
+
+GetMthMoveOfNthPartymon: ; f963
+	ld a, [wCurPartyMon]
+	call AddNTimes
+
+GetMthMoveOfCurrentMon: ; f969
+	ld a, [wMenuCursorY]
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ret
+; f971
--- /dev/null
+++ b/engine/items/items.asm
@@ -1,0 +1,581 @@
+_ReceiveItem:: ; d1d5
+	call DoesHLEqualNumItems
+	jp nz, PutItemInPocket
+	push hl
+	call CheckItemPocket
+	pop de
+	ld a, [wItemAttributeParamBuffer]
+	dec a
+	ld hl, .Pockets
+	rst JumpTable
+	ret
+
+.Pockets: ; d1e9
+; entries correspond to item types
+	dw .Item
+	dw .KeyItem
+	dw .Ball
+	dw .TMHM
+
+.Item: ; d1f1
+	ld h, d
+	ld l, e
+	jp PutItemInPocket
+
+.KeyItem: ; d1f6
+	ld h, d
+	ld l, e
+	jp ReceiveKeyItem
+
+.Ball: ; d1fb
+	ld hl, wNumBalls
+	jp PutItemInPocket
+
+.TMHM: ; d201
+	ld h, d
+	ld l, e
+	ld a, [wCurItem]
+	ld c, a
+	call GetTMHMNumber
+	jp ReceiveTMHM
+
+_TossItem:: ; d20d
+	call DoesHLEqualNumItems
+	jr nz, .remove
+	push hl
+	call CheckItemPocket
+	pop de
+	ld a, [wItemAttributeParamBuffer]
+	dec a
+	ld hl, .Pockets
+	rst JumpTable
+	ret
+
+.Pockets:
+; entries correspond to item types
+	dw .Item
+	dw .KeyItem
+	dw .Ball
+	dw .TMHM
+
+.Ball: ; d228
+	ld hl, wNumBalls
+	jp RemoveItemFromPocket
+
+.TMHM: ; d22e
+	ld h, d
+	ld l, e
+	ld a, [wCurItem]
+	ld c, a
+	call GetTMHMNumber
+	jp TossTMHM
+
+.KeyItem: ; d23a
+	ld h, d
+	ld l, e
+	jp TossKeyItem
+
+.Item: ; d23f
+	ld h, d
+	ld l, e
+
+.remove
+	jp RemoveItemFromPocket
+
+_CheckItem:: ; d244
+	call DoesHLEqualNumItems
+	jr nz, .nope
+	push hl
+	call CheckItemPocket
+	pop de
+	ld a, [wItemAttributeParamBuffer]
+	dec a
+	ld hl, .Pockets
+	rst JumpTable
+	ret
+
+.Pockets:
+; entries correspond to item types
+	dw .Item
+	dw .KeyItem
+	dw .Ball
+	dw .TMHM
+
+.Ball: ; d25f
+	ld hl, wNumBalls
+	jp CheckTheItem
+
+.TMHM: ; d265
+	ld h, d
+	ld l, e
+	ld a, [wCurItem]
+	ld c, a
+	call GetTMHMNumber
+	jp CheckTMHM
+
+.KeyItem: ; d271
+	ld h, d
+	ld l, e
+	jp CheckKeyItems
+
+.Item: ; d276
+	ld h, d
+	ld l, e
+
+.nope
+	jp CheckTheItem
+
+DoesHLEqualNumItems: ; d27b
+	ld a, l
+	cp LOW(wNumItems)
+	ret nz
+	ld a, h
+	cp HIGH(wNumItems)
+	ret
+
+GetPocketCapacity: ; d283
+	ld c, MAX_ITEMS
+	ld a, e
+	cp LOW(wNumItems)
+	jr nz, .not_bag
+	ld a, d
+	cp HIGH(wNumItems)
+	ret z
+
+.not_bag
+	ld c, MAX_PC_ITEMS
+	ld a, e
+	cp LOW(wPCItems)
+	jr nz, .not_pc
+	ld a, d
+	cp HIGH(wPCItems)
+	ret z
+
+.not_pc
+	ld c, MAX_BALLS
+	ret
+
+PutItemInPocket: ; d29c
+	ld d, h
+	ld e, l
+	inc hl
+	ld a, [wCurItem]
+	ld c, a
+	ld b, 0
+.loop
+	ld a, [hli]
+	cp -1
+	jr z, .terminator
+	cp c
+	jr nz, .next
+	ld a, 99
+	sub [hl]
+	add b
+	ld b, a
+	ld a, [wItemQuantityChangeBuffer]
+	cp b
+	jr z, .ok
+	jr c, .ok
+
+.next
+	inc hl
+	jr .loop
+
+.terminator
+	call GetPocketCapacity
+	ld a, [de]
+	cp c
+	jr c, .ok
+	and a
+	ret
+
+.ok
+	ld h, d
+	ld l, e
+	ld a, [wCurItem]
+	ld c, a
+	ld a, [wItemQuantityChangeBuffer]
+	ld [wItemQuantityBuffer], a
+.loop2
+	inc hl
+	ld a, [hli]
+	cp -1
+	jr z, .terminator2
+	cp c
+	jr nz, .loop2
+	ld a, [wItemQuantityBuffer]
+	add [hl]
+	cp 100
+	jr nc, .newstack
+	ld [hl], a
+	jr .done
+
+.newstack
+	ld [hl], 99
+	sub 99
+	ld [wItemQuantityBuffer], a
+	jr .loop2
+
+.terminator2
+	dec hl
+	ld a, [wCurItem]
+	ld [hli], a
+	ld a, [wItemQuantityBuffer]
+	ld [hli], a
+	ld [hl], -1
+	ld h, d
+	ld l, e
+	inc [hl]
+
+.done
+	scf
+	ret
+
+RemoveItemFromPocket: ; d2ff
+	ld d, h
+	ld e, l
+	ld a, [hli]
+	ld c, a
+	ld a, [wCurItemQuantity]
+	cp c
+	jr nc, .ok ; memory
+	ld c, a
+	ld b, $0
+	add hl, bc
+	add hl, bc
+	ld a, [wCurItem]
+	cp [hl]
+	inc hl
+	jr z, .skip
+	ld h, d
+	ld l, e
+	inc hl
+
+.ok
+	ld a, [wCurItem]
+	ld b, a
+.loop
+	ld a, [hli]
+	cp b
+	jr z, .skip
+	cp -1
+	jr z, .nope
+	inc hl
+	jr .loop
+
+.skip
+	ld a, [wItemQuantityChangeBuffer]
+	ld b, a
+	ld a, [hl]
+	sub b
+	jr c, .nope
+	ld [hl], a
+	ld [wItemQuantityBuffer], a
+	and a
+	jr nz, .yup
+	dec hl
+	ld b, h
+	ld c, l
+	inc hl
+	inc hl
+.loop2
+	ld a, [hli]
+	ld [bc], a
+	inc bc
+	cp -1
+	jr nz, .loop2
+	ld h, d
+	ld l, e
+	dec [hl]
+
+.yup
+	scf
+	ret
+
+.nope
+	and a
+	ret
+
+CheckTheItem: ; d349
+	ld a, [wCurItem]
+	ld c, a
+.loop
+	inc hl
+	ld a, [hli]
+	cp -1
+	jr z, .done
+	cp c
+	jr nz, .loop
+	scf
+	ret
+
+.done
+	and a
+	ret
+
+ReceiveKeyItem: ; d35a
+	ld hl, wNumKeyItems
+	ld a, [hli]
+	cp MAX_KEY_ITEMS
+	jr nc, .nope
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [wCurItem]
+	ld [hli], a
+	ld [hl], -1
+	ld hl, wNumKeyItems
+	inc [hl]
+	scf
+	ret
+
+.nope
+	and a
+	ret
+
+TossKeyItem: ; d374
+	ld a, [wCurItemQuantity]
+	ld e, a
+	ld d, 0
+	ld hl, wNumKeyItems
+	ld a, [hl]
+	cp e
+	jr nc, .ok
+	call .Toss
+	ret nc
+	jr .ok2
+
+.ok
+	dec [hl]
+	inc hl
+	add hl, de
+
+.ok2
+	ld d, h
+	ld e, l
+	inc hl
+.loop
+	ld a, [hli]
+	ld [de], a
+	inc de
+	cp -1
+	jr nz, .loop
+	scf
+	ret
+
+.Toss: ; d396
+	ld hl, wNumKeyItems
+	ld a, [wCurItem]
+	ld c, a
+.loop3
+	inc hl
+	ld a, [hl]
+	cp c
+	jr z, .ok3
+	cp -1
+	jr nz, .loop3
+	xor a
+	ret
+
+.ok3
+	ld a, [wNumKeyItems]
+	dec a
+	ld [wNumKeyItems], a
+	scf
+	ret
+
+CheckKeyItems: ; d3b1
+	ld a, [wCurItem]
+	ld c, a
+	ld hl, wKeyItems
+.loop
+	ld a, [hli]
+	cp c
+	jr z, .done
+	cp -1
+	jr nz, .loop
+	and a
+	ret
+
+.done
+	scf
+	ret
+
+ReceiveTMHM: ; d3c4
+	dec c
+	ld b, 0
+	ld hl, wTMsHMs
+	add hl, bc
+	ld a, [wItemQuantityChangeBuffer]
+	add [hl]
+	cp 100
+	jr nc, .toomany
+	ld [hl], a
+	scf
+	ret
+
+.toomany
+	and a
+	ret
+
+TossTMHM: ; d3d8
+	dec c
+	ld b, 0
+	ld hl, wTMsHMs
+	add hl, bc
+	ld a, [wItemQuantityChangeBuffer]
+	ld b, a
+	ld a, [hl]
+	sub b
+	jr c, .nope
+	ld [hl], a
+	ld [wItemQuantityBuffer], a
+	jr nz, .yup
+	ld a, [wTMHMPocketScrollPosition]
+	and a
+	jr z, .yup
+	dec a
+	ld [wTMHMPocketScrollPosition], a
+
+.yup
+	scf
+	ret
+
+.nope
+	and a
+	ret
+
+CheckTMHM: ; d3fb
+	dec c
+	ld b, $0
+	ld hl, wTMsHMs
+	add hl, bc
+	ld a, [hl]
+	and a
+	ret z
+	scf
+	ret
+
+GetTMHMNumber:: ; d407
+; Return the number of a TM/HM by item id c.
+	ld a, c
+; Skip any dummy items.
+	cp ITEM_C3 ; TM04-05
+	jr c, .done
+	cp ITEM_DC ; TM28-29
+	jr c, .skip
+	dec a
+.skip
+	dec a
+.done
+	sub TM01
+	inc a
+	ld c, a
+	ret
+
+GetNumberedTMHM: ; d417
+; Return the item id of a TM/HM by number c.
+	ld a, c
+; Skip any gaps.
+	cp ITEM_C3 - (TM01 - 1)
+	jr c, .done
+	cp ITEM_DC - (TM01 - 1) - 1
+	jr c, .skip_one
+.skip_two
+	inc a
+.skip_one
+	inc a
+.done
+	add TM01
+	dec a
+	ld c, a
+	ret
+
+_CheckTossableItem:: ; d427
+; Return 1 in wItemAttributeParamBuffer and carry if wCurItem can't be removed from the bag.
+	ld a, ITEMATTR_PERMISSIONS
+	call GetItemAttr
+	bit CANT_TOSS_F, a
+	jr nz, ItemAttr_ReturnCarry
+	and a
+	ret
+
+CheckSelectableItem: ; d432
+; Return 1 in wItemAttributeParamBuffer and carry if wCurItem can't be selected.
+	ld a, ITEMATTR_PERMISSIONS
+	call GetItemAttr
+	bit CANT_SELECT_F, a
+	jr nz, ItemAttr_ReturnCarry
+	and a
+	ret
+
+CheckItemPocket:: ; d43d
+; Return the pocket for wCurItem in wItemAttributeParamBuffer.
+	ld a, ITEMATTR_POCKET
+	call GetItemAttr
+	and $f
+	ld [wItemAttributeParamBuffer], a
+	ret
+
+CheckItemContext: ; d448
+; Return the context for wCurItem in wItemAttributeParamBuffer.
+	ld a, ITEMATTR_HELP
+	call GetItemAttr
+	and $f
+	ld [wItemAttributeParamBuffer], a
+	ret
+
+CheckItemMenu: ; d453
+; Return the menu for wCurItem in wItemAttributeParamBuffer.
+	ld a, ITEMATTR_HELP
+	call GetItemAttr
+	swap a
+	and $f
+	ld [wItemAttributeParamBuffer], a
+	ret
+
+GetItemAttr: ; d460
+; Get attribute a of wCurItem.
+
+	push hl
+	push bc
+
+	ld hl, ItemAttributes
+	ld c, a
+	ld b, 0
+	add hl, bc
+
+	xor a
+	ld [wItemAttributeParamBuffer], a
+
+	ld a, [wCurItem]
+	dec a
+	ld c, a
+	ld a, ITEMATTR_STRUCT_LENGTH
+	call AddNTimes
+	ld a, BANK(ItemAttributes)
+	call GetFarByte
+
+	pop bc
+	pop hl
+	ret
+
+ItemAttr_ReturnCarry: ; d47f
+	ld a, 1
+	ld [wItemAttributeParamBuffer], a
+	scf
+	ret
+
+GetItemPrice: ; d486
+; Return the price of wCurItem in de.
+	push hl
+	push bc
+	ld a, ITEMATTR_PRICE
+	call GetItemAttr
+	ld e, a
+	ld a, ITEMATTR_PRICE_HI
+	call GetItemAttr
+	ld d, a
+	pop bc
+	pop hl
+	ret
--- /dev/null
+++ b/engine/items/mart.asm
@@ -1,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
--- /dev/null
+++ b/engine/items/pack.asm
@@ -1,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"
--- /dev/null
+++ b/engine/items/printitemdescription.asm
@@ -1,0 +1,31 @@
+PrintItemDescription: ; 0x1c8955
+; Print the description for item [wCurSpecies] at de.
+
+	ld a, [wCurSpecies]
+	cp TM01
+	jr c, .not_a_tm
+
+	ld [wCurItem], a
+	push de
+	farcall GetTMHMItemMove
+	pop hl
+	ld a, [wd265]
+	ld [wCurSpecies], a
+	predef PrintMoveDesc
+	ret
+
+.not_a_tm
+	push de
+	ld hl, ItemDescriptions
+	ld a, [wCurSpecies]
+	dec a
+	ld c, a
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	pop hl
+	jp PlaceString
+; 0x1c8987
--- /dev/null
+++ b/engine/items/switch_items.asm
@@ -1,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
--- /dev/null
+++ b/engine/items/tmhm.asm
@@ -1,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"
--- /dev/null
+++ b/engine/items/updateitemdescription.asm
@@ -1,0 +1,13 @@
+UpdateItemDescription: ; 0x244c3
+	ld a, [wMenuSelection]
+	ld [wCurSpecies], a
+	hlcoord 0, 12
+	ld b, 4
+	ld c, SCREEN_WIDTH - 2
+	call TextBox
+	ld a, [wMenuSelection]
+	cp -1
+	ret z
+	decoord 1, 14
+	farcall PrintItemDescription
+	ret
--- a/engine/menu/buy_sell_toss.asm
+++ /dev/null
@@ -1,235 +1,0 @@
-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
--- a/engine/menu/clock_reset.asm
+++ /dev/null
@@ -1,254 +1,0 @@
-
-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
--- a/engine/menu/delete_save_change_clock.asm
+++ /dev/null
@@ -1,296 +1,0 @@
-_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@"
--- a/engine/menu/main_menu.asm
+++ /dev/null
@@ -1,361 +1,0 @@
-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
--- a/engine/menu/mart.asm
+++ /dev/null
@@ -1,970 +1,0 @@
-	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
--- a/engine/menu/menu.asm
+++ /dev/null
@@ -1,841 +1,0 @@
-_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
--- a/engine/menu/menu_2.asm
+++ /dev/null
@@ -1,253 +1,0 @@
-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"
--- a/engine/menu/mon_menu.asm
+++ /dev/null
@@ -1,304 +1,0 @@
-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
--- a/engine/menu/naming_screen.asm
+++ /dev/null
@@ -1,1467 +1,0 @@
-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
--- a/engine/menu/options_menu.asm
+++ /dev/null
@@ -1,583 +1,0 @@
-_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
--- a/engine/menu/pack.asm
+++ /dev/null
@@ -1,1711 +1,0 @@
-; 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"
--- a/engine/menu/scrolling_menu.asm
+++ /dev/null
@@ -1,543 +1,0 @@
-_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
--- a/engine/menu/start_menu.asm
+++ /dev/null
@@ -1,1993 +1,0 @@
-; 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
--- a/engine/menu/switch_items.asm
+++ /dev/null
@@ -1,274 +1,0 @@
-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
--- a/engine/menu/timeset.asm
+++ /dev/null
@@ -1,773 +1,0 @@
-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
--- a/engine/menu/tmhm.asm
+++ /dev/null
@@ -1,49 +1,0 @@
-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"
--- a/engine/menu/trainer_card.asm
+++ /dev/null
@@ -1,623 +1,0 @@
-; 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"
--- /dev/null
+++ b/engine/menus/main_menu.asm
@@ -1,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
--- /dev/null
+++ b/engine/menus/menu.asm
@@ -1,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
--- /dev/null
+++ b/engine/menus/menu_2.asm
@@ -1,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"
--- /dev/null
+++ b/engine/menus/naming_screen.asm
@@ -1,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
--- /dev/null
+++ b/engine/menus/options_menu.asm
@@ -1,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
--- /dev/null
+++ b/engine/menus/scrolling_menu.asm
@@ -1,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
--- /dev/null
+++ b/engine/menus/start_menu.asm
@@ -1,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
--- /dev/null
+++ b/engine/menus/trainer_card.asm
@@ -1,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"
--- /dev/null
+++ b/engine/overworld/loadmappart.asm
@@ -1,0 +1,36 @@
+_LoadMapPart:: ; 4d15b
+	ld hl, wMisc
+	ld a, [wMetatileStandingY]
+	and a
+	jr z, .top_row
+	ld bc, WMISC_WIDTH * 2
+	add hl, bc
+
+.top_row
+	ld a, [wMetatileStandingX]
+	and a
+	jr z, .left_column
+	inc hl
+	inc hl
+
+.left_column
+	decoord 0, 0
+	ld b, SCREEN_HEIGHT
+.loop
+	ld c, SCREEN_WIDTH
+.loop2
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec c
+	jr nz, .loop2
+	ld a, l
+	add 4
+	ld l, a
+	jr nc, .carry
+	inc h
+
+.carry
+	dec b
+	jr nz, .loop
+	ret
--- /dev/null
+++ b/engine/pokemon/getbreedmonlevelgrowth.asm
@@ -1,0 +1,27 @@
+GetBreedMon1LevelGrowth: ; e698
+	ld hl, wBreedMon1Stats
+	ld de, wTempMon
+	ld bc, BOXMON_STRUCT_LENGTH
+	call CopyBytes
+	callfar CalcLevel
+	ld a, [wBreedMon1Level]
+	ld b, a
+	ld a, d
+	ld e, a
+	sub b
+	ld d, a
+	ret
+
+GetBreedMon2LevelGrowth: ; e6b3
+	ld hl, wBreedMon2Stats
+	ld de, wTempMon
+	ld bc, BOXMON_STRUCT_LENGTH
+	call CopyBytes
+	callfar CalcLevel
+	ld a, [wBreedMon2Level]
+	ld b, a
+	ld a, d
+	ld e, a
+	sub b
+	ld d, a
+	ret
--- /dev/null
+++ b/engine/pokemon/knowsmove.asm
@@ -1,0 +1,25 @@
+KnowsMove: ; f9ea
+	ld a, MON_MOVES
+	call GetPartyParamLocation
+	ld a, [wPutativeTMHMMove]
+	ld b, a
+	ld c, NUM_MOVES
+.loop
+	ld a, [hli]
+	cp b
+	jr z, .knows_move
+	dec c
+	jr nz, .loop
+	and a
+	ret
+
+.knows_move
+	ld hl, .Text_knows
+	call PrintText
+	scf
+	ret
+
+.Text_knows: ; 0xfa06
+	; knows @ .
+	text_jump UnknownText_0x1c5ea8
+	db "@"
--- /dev/null
+++ b/engine/pokemon/leveluphappinessmod.asm
@@ -1,0 +1,20 @@
+LevelUpHappinessMod: ; 2709e
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1CaughtLocation
+	call GetPartyLocation
+	ld a, [hl]
+	and $7f
+	ld d, a
+	ld a, [wMapGroup]
+	ld b, a
+	ld a, [wMapNumber]
+	ld c, a
+	call GetWorldMapLocation
+	cp d
+	ld c, HAPPINESS_GAINLEVEL
+	jr nz, .ok
+	ld c, HAPPINESS_GAINLEVELATHOME
+
+.ok
+	callfar ChangeHappiness
+	ret
--- /dev/null
+++ b/engine/pokemon/mon_menu.asm
@@ -1,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
--- /dev/null
+++ b/engine/pokemon/switchpartymons.asm
@@ -1,0 +1,145 @@
+_SwitchPartyMons:
+	ld a, [wd0e3]
+	dec a
+	ld [wBuffer3], a
+	ld b, a
+	ld a, [wMenuCursorY]
+	dec a
+	ld [wBuffer2], a
+	cp b
+	jr z, .skip
+	call .SwapMonAndMail
+	ld a, [wBuffer3]
+	call .ClearSprite
+	ld a, [wBuffer2]
+	call .ClearSprite
+.skip
+	ret
+
+.ClearSprite: ; 50f34 (14:4f34)
+	push af
+	hlcoord 0, 1
+	ld bc, 2 * SCREEN_WIDTH
+	call AddNTimes
+	ld bc, 2 * SCREEN_WIDTH
+	ld a, " "
+	call ByteFill
+	pop af
+	ld hl, wVirtualOAMSprite00
+	ld bc, 4 * SPRITEOAMSTRUCT_LENGTH
+	call AddNTimes
+	ld de, SPRITEOAMSTRUCT_LENGTH
+	ld c, 4
+.gfx_loop
+	ld [hl], SCREEN_WIDTH_PX ; y (off-screen)
+	add hl, de
+	dec c
+	jr nz, .gfx_loop
+	ld de, SFX_SWITCH_POKEMON
+	call WaitPlaySFX
+	ret
+
+.SwapMonAndMail: ; 50f62 (14:4f62)
+	push hl
+	push de
+	push bc
+	ld bc, wPartySpecies
+	ld a, [wBuffer2]
+	ld l, a
+	ld h, $0
+	add hl, bc
+	ld d, h
+	ld e, l
+	ld a, [wBuffer3]
+	ld l, a
+	ld h, $0
+	add hl, bc
+	ld a, [hl]
+	push af
+	ld a, [de]
+	ld [hl], a
+	pop af
+	ld [de], a
+	ld a, [wBuffer2]
+	ld hl, wPartyMon1Species
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	push hl
+	ld de, wd002
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call CopyBytes
+	ld a, [wBuffer3]
+	ld hl, wPartyMon1
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	pop de
+	push hl
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call CopyBytes
+	pop de
+	ld hl, wd002
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call CopyBytes
+	ld a, [wBuffer2]
+	ld hl, wPartyMonOT
+	call SkipNames
+	push hl
+	call .CopyNameTowd002
+	ld a, [wBuffer3]
+	ld hl, wPartyMonOT
+	call SkipNames
+	pop de
+	push hl
+	call .CopyName
+	pop de
+	ld hl, wd002
+	call .CopyName
+	ld hl, wPartyMonNicknames
+	ld a, [wBuffer2]
+	call SkipNames
+	push hl
+	call .CopyNameTowd002
+	ld hl, wPartyMonNicknames
+	ld a, [wBuffer3]
+	call SkipNames
+	pop de
+	push hl
+	call .CopyName
+	pop de
+	ld hl, wd002
+	call .CopyName
+	ld hl, sPartyMail
+	ld a, [wBuffer2]
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	push hl
+	ld de, wd002
+	ld bc, MAIL_STRUCT_LENGTH
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	call CopyBytes
+	ld hl, sPartyMail
+	ld a, [wBuffer3]
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	pop de
+	push hl
+	ld bc, MAIL_STRUCT_LENGTH
+	call CopyBytes
+	pop de
+	ld hl, wd002
+	ld bc, MAIL_STRUCT_LENGTH
+	call CopyBytes
+	call CloseSRAM
+	pop bc
+	pop de
+	pop hl
+	ret
+
+.CopyNameTowd002: ; 51036 (14:5036)
+	ld de, wd002
+
+.CopyName: ; 51039 (14:5039)
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ret
--- a/engine/routines/drawkrispackgfx.asm
+++ /dev/null
@@ -1,20 +1,0 @@
-DrawKrisPackGFX: ; 48e81
-	ld hl, PackFGFXPointers
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld e, a
-	ld d, [hl]
-	ld hl, vTiles2 tile $50
-	lb bc, BANK(PackFGFX), 15
-	call Request2bpp
-	ret
-
-PackFGFXPointers: ; 48e93
-	dw PackFGFX + (15 tiles) * 1 ; ITEM_POCKET
-	dw PackFGFX + (15 tiles) * 3 ; BALL_POCKET
-	dw PackFGFX + (15 tiles) * 0 ; KEY_ITEM_POCKET
-	dw PackFGFX + (15 tiles) * 2 ; TM_HM_POCKET
-
-PackFGFX: ; 48e9b
-INCBIN "gfx/pack/pack_f.2bpp"
--- a/engine/routines/getbreedmonlevelgrowth.asm
+++ /dev/null
@@ -1,27 +1,0 @@
-GetBreedMon1LevelGrowth: ; e698
-	ld hl, wBreedMon1Stats
-	ld de, wTempMon
-	ld bc, BOXMON_STRUCT_LENGTH
-	call CopyBytes
-	callfar CalcLevel
-	ld a, [wBreedMon1Level]
-	ld b, a
-	ld a, d
-	ld e, a
-	sub b
-	ld d, a
-	ret
-
-GetBreedMon2LevelGrowth: ; e6b3
-	ld hl, wBreedMon2Stats
-	ld de, wTempMon
-	ld bc, BOXMON_STRUCT_LENGTH
-	call CopyBytes
-	callfar CalcLevel
-	ld a, [wBreedMon2Level]
-	ld b, a
-	ld a, d
-	ld e, a
-	sub b
-	ld d, a
-	ret
--- a/engine/routines/knowsmove.asm
+++ /dev/null
@@ -1,25 +1,0 @@
-KnowsMove: ; f9ea
-	ld a, MON_MOVES
-	call GetPartyParamLocation
-	ld a, [wPutativeTMHMMove]
-	ld b, a
-	ld c, NUM_MOVES
-.loop
-	ld a, [hli]
-	cp b
-	jr z, .knows_move
-	dec c
-	jr nz, .loop
-	and a
-	ret
-
-.knows_move
-	ld hl, .Text_knows
-	call PrintText
-	scf
-	ret
-
-.Text_knows: ; 0xfa06
-	; knows @ .
-	text_jump UnknownText_0x1c5ea8
-	db "@"
--- a/engine/routines/leveluphappinessmod.asm
+++ /dev/null
@@ -1,20 +1,0 @@
-LevelUpHappinessMod: ; 2709e
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1CaughtLocation
-	call GetPartyLocation
-	ld a, [hl]
-	and $7f
-	ld d, a
-	ld a, [wMapGroup]
-	ld b, a
-	ld a, [wMapNumber]
-	ld c, a
-	call GetWorldMapLocation
-	cp d
-	ld c, HAPPINESS_GAINLEVEL
-	jr nz, .ok
-	ld c, HAPPINESS_GAINLEVELATHOME
-
-.ok
-	callfar ChangeHappiness
-	ret
--- a/engine/routines/loadmappart.asm
+++ /dev/null
@@ -1,36 +1,0 @@
-_LoadMapPart:: ; 4d15b
-	ld hl, wMisc
-	ld a, [wMetatileStandingY]
-	and a
-	jr z, .top_row
-	ld bc, WMISC_WIDTH * 2
-	add hl, bc
-
-.top_row
-	ld a, [wMetatileStandingX]
-	and a
-	jr z, .left_column
-	inc hl
-	inc hl
-
-.left_column
-	decoord 0, 0
-	ld b, SCREEN_HEIGHT
-.loop
-	ld c, SCREEN_WIDTH
-.loop2
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec c
-	jr nz, .loop2
-	ld a, l
-	add 4
-	ld l, a
-	jr nc, .carry
-	inc h
-
-.carry
-	dec b
-	jr nz, .loop
-	ret
--- a/engine/routines/loadoverworldfont.asm
+++ /dev/null
@@ -1,17 +1,0 @@
-LoadOverworldFont:: ; 106594
-	ld de, .OverworldFontGFX
-	ld hl, vTiles1
-	lb bc, BANK(.OverworldFontGFX), $80
-	call Get2bpp
-	ld de, .OverworldFontSpaceGFX
-	ld hl, vTiles2 tile " "
-	lb bc, BANK(.OverworldFontSpaceGFX), 1
-	call Get2bpp
-	ret
-; 1065ad
-
-.OverworldFontGFX:
-INCBIN "gfx/font/overworld.2bpp"
-
-.OverworldFontSpaceGFX:
-INCBIN "gfx/font/overworld_space.2bpp"
--- a/engine/routines/placegraphic.asm
+++ /dev/null
@@ -1,55 +1,0 @@
-PlaceGraphic: ; 2ef6e
-; Fill wBoxAlignment-aligned box width b height c
-; with iterating tile starting from hGraphicStartTile at hl.
-
-	ld de, SCREEN_WIDTH
-
-	ld a, [wBoxAlignment]
-	and a
-	jr nz, .right
-
-	ld a, [hGraphicStartTile]
-.x1
-	push bc
-	push hl
-
-.y1
-	ld [hl], a
-	add hl, de
-	inc a
-	dec c
-	jr nz, .y1
-
-	pop hl
-	inc hl
-	pop bc
-	dec b
-	jr nz, .x1
-	ret
-
-.right
-; Right-aligned.
-	push bc
-	ld b, 0
-	dec c
-	add hl, bc
-	pop bc
-
-	ld a, [hGraphicStartTile]
-.x2
-	push bc
-	push hl
-
-.y2
-	ld [hl], a
-	add hl, de
-	inc a
-	dec c
-	jr nz, .y2
-
-	pop hl
-	dec hl
-	pop bc
-	dec b
-	jr nz, .x2
-	ret
--- a/engine/routines/printhoursmins.asm
+++ /dev/null
@@ -1,63 +1,0 @@
-Unreferenced_Function1dd6a9: ; 1dd6a9
-	ld a, b
-	ld b, c
-	ld c, a
-	push bc
-	push de
-	ld hl, sp+$2
-	ld d, h
-	ld e, l
-	pop hl
-	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
-	call PrintNum
-	pop bc
-	ret
-
-PrintHoursMins: ; 1dd6bb (77:56bb)
-; Hours in b, minutes in c
-	ld a, b
-	cp 12
-	push af
-	jr c, .AM
-	jr z, .PM
-	sub 12
-	jr .PM
-.AM:
-	or a
-	jr nz, .PM
-	ld a, 12
-.PM:
-	ld b, a
-; Crazy stuff happening with the stack
-	push bc
-	ld hl, sp+$1
-	push de
-	push hl
-	pop de
-	pop hl
-	ld [hl], " "
-	lb bc, 1, 2
-	call PrintNum
-	ld [hl], ":"
-	inc hl
-	ld d, h
-	ld e, l
-	ld hl, sp+$0
-	push de
-	push hl
-	pop de
-	pop hl
-	lb bc, PRINTNUM_LEADINGZEROS | 1, 2
-	call PrintNum
-	pop bc
-	ld de, String_AM
-	pop af
-	jr c, .place_am_pm
-	ld de, String_PM
-.place_am_pm
-	inc hl
-	call PlaceString
-	ret
-
-String_AM: db "AM@" ; 1dd6fc
-String_PM: db "PM@" ; 1dd6ff
--- a/engine/routines/printitemdescription.asm
+++ /dev/null
@@ -1,31 +1,0 @@
-PrintItemDescription: ; 0x1c8955
-; Print the description for item [wCurSpecies] at de.
-
-	ld a, [wCurSpecies]
-	cp TM01
-	jr c, .not_a_tm
-
-	ld [wCurItem], a
-	push de
-	farcall GetTMHMItemMove
-	pop hl
-	ld a, [wd265]
-	ld [wCurSpecies], a
-	predef PrintMoveDesc
-	ret
-
-.not_a_tm
-	push de
-	ld hl, ItemDescriptions
-	ld a, [wCurSpecies]
-	dec a
-	ld c, a
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	pop hl
-	jp PlaceString
-; 0x1c8987
--- a/engine/routines/switchpartymons.asm
+++ /dev/null
@@ -1,145 +1,0 @@
-_SwitchPartyMons:
-	ld a, [wd0e3]
-	dec a
-	ld [wBuffer3], a
-	ld b, a
-	ld a, [wMenuCursorY]
-	dec a
-	ld [wBuffer2], a
-	cp b
-	jr z, .skip
-	call .SwapMonAndMail
-	ld a, [wBuffer3]
-	call .ClearSprite
-	ld a, [wBuffer2]
-	call .ClearSprite
-.skip
-	ret
-
-.ClearSprite: ; 50f34 (14:4f34)
-	push af
-	hlcoord 0, 1
-	ld bc, 2 * SCREEN_WIDTH
-	call AddNTimes
-	ld bc, 2 * SCREEN_WIDTH
-	ld a, " "
-	call ByteFill
-	pop af
-	ld hl, wVirtualOAMSprite00
-	ld bc, 4 * SPRITEOAMSTRUCT_LENGTH
-	call AddNTimes
-	ld de, SPRITEOAMSTRUCT_LENGTH
-	ld c, 4
-.gfx_loop
-	ld [hl], SCREEN_WIDTH_PX ; y (off-screen)
-	add hl, de
-	dec c
-	jr nz, .gfx_loop
-	ld de, SFX_SWITCH_POKEMON
-	call WaitPlaySFX
-	ret
-
-.SwapMonAndMail: ; 50f62 (14:4f62)
-	push hl
-	push de
-	push bc
-	ld bc, wPartySpecies
-	ld a, [wBuffer2]
-	ld l, a
-	ld h, $0
-	add hl, bc
-	ld d, h
-	ld e, l
-	ld a, [wBuffer3]
-	ld l, a
-	ld h, $0
-	add hl, bc
-	ld a, [hl]
-	push af
-	ld a, [de]
-	ld [hl], a
-	pop af
-	ld [de], a
-	ld a, [wBuffer2]
-	ld hl, wPartyMon1Species
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	push hl
-	ld de, wd002
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call CopyBytes
-	ld a, [wBuffer3]
-	ld hl, wPartyMon1
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	pop de
-	push hl
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call CopyBytes
-	pop de
-	ld hl, wd002
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call CopyBytes
-	ld a, [wBuffer2]
-	ld hl, wPartyMonOT
-	call SkipNames
-	push hl
-	call .CopyNameTowd002
-	ld a, [wBuffer3]
-	ld hl, wPartyMonOT
-	call SkipNames
-	pop de
-	push hl
-	call .CopyName
-	pop de
-	ld hl, wd002
-	call .CopyName
-	ld hl, wPartyMonNicknames
-	ld a, [wBuffer2]
-	call SkipNames
-	push hl
-	call .CopyNameTowd002
-	ld hl, wPartyMonNicknames
-	ld a, [wBuffer3]
-	call SkipNames
-	pop de
-	push hl
-	call .CopyName
-	pop de
-	ld hl, wd002
-	call .CopyName
-	ld hl, sPartyMail
-	ld a, [wBuffer2]
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	push hl
-	ld de, wd002
-	ld bc, MAIL_STRUCT_LENGTH
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	call CopyBytes
-	ld hl, sPartyMail
-	ld a, [wBuffer3]
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	pop de
-	push hl
-	ld bc, MAIL_STRUCT_LENGTH
-	call CopyBytes
-	pop de
-	ld hl, wd002
-	ld bc, MAIL_STRUCT_LENGTH
-	call CopyBytes
-	call CloseSRAM
-	pop bc
-	pop de
-	pop hl
-	ret
-
-.CopyNameTowd002: ; 51036 (14:5036)
-	ld de, wd002
-
-.CopyName: ; 51039 (14:5039)
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ret
--- a/engine/routines/trademonfrontpic.asm
+++ /dev/null
@@ -1,38 +1,0 @@
-GetTrademonFrontpic: ; 4d7fd
-	ld a, [wOTTrademonSpecies]
-	ld hl, wOTTrademonDVs
-	ld de, vTiles2
-	push de
-	push af
-	predef GetUnownLetter
-	pop af
-	ld [wCurPartySpecies], a
-	ld [wCurSpecies], a
-	call GetBaseData
-	pop de
-	predef GetAnimatedFrontpic
-	ret
-
-AnimateTrademonFrontpic: ; 4d81e
-	ld a, [wOTTrademonSpecies]
-	call IsAPokemon
-	ret c
-	farcall ShowOTTrademonStats
-	ld a, [wOTTrademonSpecies]
-	ld [wCurPartySpecies], a
-	ld a, [wOTTrademonDVs]
-	ld [wTempMonDVs], a
-	ld a, [wOTTrademonDVs + 1]
-	ld [wTempMonDVs + 1], a
-	ld b, SCGB_PLAYER_OR_MON_FRONTPIC_PALS
-	call GetSGBLayout
-	ld a, %11100100 ; 3,2,1,0
-	call DmgToCgbBGPals
-	farcall TradeAnim_ShowGetmonFrontpic
-	ld a, [wOTTrademonSpecies]
-	ld [wCurPartySpecies], a
-	hlcoord 7, 2
-	ld d, $0
-	ld e, ANIM_MON_TRADE
-	predef AnimateFrontpic
-	ret
--- a/engine/routines/updateitemdescription.asm
+++ /dev/null
@@ -1,13 +1,0 @@
-UpdateItemDescription: ; 0x244c3
-	ld a, [wMenuSelection]
-	ld [wCurSpecies], a
-	hlcoord 0, 12
-	ld b, 4
-	ld c, SCREEN_WIDTH - 2
-	call TextBox
-	ld a, [wMenuSelection]
-	cp -1
-	ret z
-	decoord 1, 14
-	farcall PrintItemDescription
-	ret
--- a/engine/rtc.asm
+++ /dev/null
@@ -1,209 +1,0 @@
-Unreferenced_StopRTC:
-	ld a, SRAM_ENABLE
-	ld [MBC3SRamEnable], a
-	call LatchClock
-	ld a, RTC_DH
-	ld [MBC3SRamBank], a
-	ld a, [MBC3RTC]
-	set 6, a ; halt
-	ld [MBC3RTC], a
-	call CloseSRAM
-	ret
-; 14019
-
-StartRTC: ; 14019
-	ld a, SRAM_ENABLE
-	ld [MBC3SRamEnable], a
-	call LatchClock
-	ld a, RTC_DH
-	ld [MBC3SRamBank], a
-	ld a, [MBC3RTC]
-	res 6, a ; halt
-	ld [MBC3RTC], a
-	call CloseSRAM
-	ret
-; 14032
-
-GetTimeOfDay:: ; 14032
-; get time of day based on the current hour
-	ld a, [hHours] ; hour
-	ld hl, TimesOfDay
-
-.check
-; if we're within the given time period,
-; get the corresponding time of day
-	cp [hl]
-	jr c, .match
-; else, get the next entry
-	inc hl
-	inc hl
-; try again
-	jr .check
-
-.match
-; get time of day
-	inc hl
-	ld a, [hl]
-	ld [wTimeOfDay], a
-	ret
-; 14044
-
-TimesOfDay: ; 14044
-; hours for the time of day
-; 0400-0959 morn | 1000-1759 day | 1800-0359 nite
-	db MORN_HOUR, NITE_F
-	db DAY_HOUR,  MORN_F
-	db NITE_HOUR, DAY_F
-	db MAX_HOUR,  NITE_F
-	db -1, MORN_F
-; 1404e
-
-Unreferenced_1404e:
-	db 20, NITE_F
-	db 40, MORN_F
-	db 60, DAY_F
-	db -1, MORN_F
-; 14056
-
-StageRTCTimeForSave: ; 14056
-	call UpdateTime
-	ld hl, wRTC
-	ld a, [wCurDay]
-	ld [hli], a
-	ld a, [hHours]
-	ld [hli], a
-	ld a, [hMinutes]
-	ld [hli], a
-	ld a, [hSeconds]
-	ld [hli], a
-	ret
-; 1406a
-
-SaveRTC: ; 1406a
-	ld a, $a
-	ld [MBC3SRamEnable], a
-	call LatchClock
-	ld hl, MBC3RTC
-	ld a, $c
-	ld [MBC3SRamBank], a
-	res 7, [hl]
-	ld a, BANK(sRTCStatusFlags)
-	ld [MBC3SRamBank], a
-	xor a
-	ld [sRTCStatusFlags], a
-	call CloseSRAM
-	ret
-; 14089
-
-StartClock:: ; 14089
-	call GetClock
-	call Function1409b
-	call FixDays
-	jr nc, .skip_set
-	; bit 5: Day count exceeds 139
-	; bit 6: Day count exceeds 255
-	call RecordRTCStatus ; set flag on sRTCStatusFlags
-
-.skip_set
-	call StartRTC
-	ret
-; 1409b
-
-Function1409b: ; 1409b
-	ld hl, hRTCDayHi
-	bit 7, [hl]
-	jr nz, .set_bit_7
-	bit 6, [hl]
-	jr nz, .set_bit_7
-	xor a
-	ret
-
-.set_bit_7
-	; Day count exceeds 16383
-	ld a, %10000000
-	call RecordRTCStatus ; set bit 7 on sRTCStatusFlags
-	ret
-; 140ae
-
-Function140ae: ; 140ae
-	call CheckRTCStatus
-	ld c, a
-	and %11000000 ; Day count exceeded 255 or 16383
-	jr nz, .time_overflow
-
-	ld a, c
-	and %00100000 ; Day count exceeded 139
-	jr z, .dont_update
-
-	call UpdateTime
-	ld a, [wRTC + 0]
-	ld b, a
-	ld a, [wCurDay]
-	cp b
-	jr c, .dont_update
-
-.time_overflow
-	farcall ClearDailyTimers
-	farcall Function170923
-; mobile
-	ld a, 5 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
-	call GetSRAMBank
-	ld a, [$aa8c] ; address of MBC30 bank
-	inc a
-	ld [$aa8c], a ; address of MBC30 bank
-	ld a, [$b2fa] ; address of MBC30 bank
-	inc a
-	ld [$b2fa], a ; address of MBC30 bank
-	call CloseSRAM
-	ret
-
-.dont_update
-	xor a
-	ret
-; 140ed
-
-_InitTime:: ; 140ed
-	call GetClock
-	call FixDays
-	ld hl, hRTCSeconds
-	ld de, wStartSecond
-
-	ld a, [wStringBuffer2 + 3]
-	sub [hl]
-	dec hl
-	jr nc, .okay_secs
-	add 60
-.okay_secs
-	ld [de], a
-	dec de
-
-	ld a, [wStringBuffer2 + 2]
-	sbc [hl]
-	dec hl
-	jr nc, .okay_mins
-	add 60
-.okay_mins
-	ld [de], a
-	dec de
-
-	ld a, [wStringBuffer2 + 1]
-	sbc [hl]
-	dec hl
-	jr nc, .okay_hrs
-	add 24
-.okay_hrs
-	ld [de], a
-	dec de
-
-	ld a, [wStringBuffer2]
-	sbc [hl]
-	dec hl
-	jr nc, .okay_days
-	add 140
-	ld c, 7
-	call SimpleDivide
-
-.okay_days
-	ld [de], a
-	ret
-; 1412a
--- /dev/null
+++ b/engine/rtc/clock_reset.asm
@@ -1,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
--- /dev/null
+++ b/engine/rtc/delete_save_change_clock.asm
@@ -1,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@"
--- /dev/null
+++ b/engine/rtc/printhoursmins.asm
@@ -1,0 +1,63 @@
+Unreferenced_Function1dd6a9: ; 1dd6a9
+	ld a, b
+	ld b, c
+	ld c, a
+	push bc
+	push de
+	ld hl, sp+$2
+	ld d, h
+	ld e, l
+	pop hl
+	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+	call PrintNum
+	pop bc
+	ret
+
+PrintHoursMins: ; 1dd6bb (77:56bb)
+; Hours in b, minutes in c
+	ld a, b
+	cp 12
+	push af
+	jr c, .AM
+	jr z, .PM
+	sub 12
+	jr .PM
+.AM:
+	or a
+	jr nz, .PM
+	ld a, 12
+.PM:
+	ld b, a
+; Crazy stuff happening with the stack
+	push bc
+	ld hl, sp+$1
+	push de
+	push hl
+	pop de
+	pop hl
+	ld [hl], " "
+	lb bc, 1, 2
+	call PrintNum
+	ld [hl], ":"
+	inc hl
+	ld d, h
+	ld e, l
+	ld hl, sp+$0
+	push de
+	push hl
+	pop de
+	pop hl
+	lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+	call PrintNum
+	pop bc
+	ld de, String_AM
+	pop af
+	jr c, .place_am_pm
+	ld de, String_PM
+.place_am_pm
+	inc hl
+	call PlaceString
+	ret
+
+String_AM: db "AM@" ; 1dd6fc
+String_PM: db "PM@" ; 1dd6ff
--- /dev/null
+++ b/engine/rtc/rtc.asm
@@ -1,0 +1,209 @@
+Unreferenced_StopRTC:
+	ld a, SRAM_ENABLE
+	ld [MBC3SRamEnable], a
+	call LatchClock
+	ld a, RTC_DH
+	ld [MBC3SRamBank], a
+	ld a, [MBC3RTC]
+	set 6, a ; halt
+	ld [MBC3RTC], a
+	call CloseSRAM
+	ret
+; 14019
+
+StartRTC: ; 14019
+	ld a, SRAM_ENABLE
+	ld [MBC3SRamEnable], a
+	call LatchClock
+	ld a, RTC_DH
+	ld [MBC3SRamBank], a
+	ld a, [MBC3RTC]
+	res 6, a ; halt
+	ld [MBC3RTC], a
+	call CloseSRAM
+	ret
+; 14032
+
+GetTimeOfDay:: ; 14032
+; get time of day based on the current hour
+	ld a, [hHours] ; hour
+	ld hl, TimesOfDay
+
+.check
+; if we're within the given time period,
+; get the corresponding time of day
+	cp [hl]
+	jr c, .match
+; else, get the next entry
+	inc hl
+	inc hl
+; try again
+	jr .check
+
+.match
+; get time of day
+	inc hl
+	ld a, [hl]
+	ld [wTimeOfDay], a
+	ret
+; 14044
+
+TimesOfDay: ; 14044
+; hours for the time of day
+; 0400-0959 morn | 1000-1759 day | 1800-0359 nite
+	db MORN_HOUR, NITE_F
+	db DAY_HOUR,  MORN_F
+	db NITE_HOUR, DAY_F
+	db MAX_HOUR,  NITE_F
+	db -1, MORN_F
+; 1404e
+
+Unreferenced_1404e:
+	db 20, NITE_F
+	db 40, MORN_F
+	db 60, DAY_F
+	db -1, MORN_F
+; 14056
+
+StageRTCTimeForSave: ; 14056
+	call UpdateTime
+	ld hl, wRTC
+	ld a, [wCurDay]
+	ld [hli], a
+	ld a, [hHours]
+	ld [hli], a
+	ld a, [hMinutes]
+	ld [hli], a
+	ld a, [hSeconds]
+	ld [hli], a
+	ret
+; 1406a
+
+SaveRTC: ; 1406a
+	ld a, $a
+	ld [MBC3SRamEnable], a
+	call LatchClock
+	ld hl, MBC3RTC
+	ld a, $c
+	ld [MBC3SRamBank], a
+	res 7, [hl]
+	ld a, BANK(sRTCStatusFlags)
+	ld [MBC3SRamBank], a
+	xor a
+	ld [sRTCStatusFlags], a
+	call CloseSRAM
+	ret
+; 14089
+
+StartClock:: ; 14089
+	call GetClock
+	call Function1409b
+	call FixDays
+	jr nc, .skip_set
+	; bit 5: Day count exceeds 139
+	; bit 6: Day count exceeds 255
+	call RecordRTCStatus ; set flag on sRTCStatusFlags
+
+.skip_set
+	call StartRTC
+	ret
+; 1409b
+
+Function1409b: ; 1409b
+	ld hl, hRTCDayHi
+	bit 7, [hl]
+	jr nz, .set_bit_7
+	bit 6, [hl]
+	jr nz, .set_bit_7
+	xor a
+	ret
+
+.set_bit_7
+	; Day count exceeds 16383
+	ld a, %10000000
+	call RecordRTCStatus ; set bit 7 on sRTCStatusFlags
+	ret
+; 140ae
+
+Function140ae: ; 140ae
+	call CheckRTCStatus
+	ld c, a
+	and %11000000 ; Day count exceeded 255 or 16383
+	jr nz, .time_overflow
+
+	ld a, c
+	and %00100000 ; Day count exceeded 139
+	jr z, .dont_update
+
+	call UpdateTime
+	ld a, [wRTC + 0]
+	ld b, a
+	ld a, [wCurDay]
+	cp b
+	jr c, .dont_update
+
+.time_overflow
+	farcall ClearDailyTimers
+	farcall Function170923
+; mobile
+	ld a, 5 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
+	call GetSRAMBank
+	ld a, [$aa8c] ; address of MBC30 bank
+	inc a
+	ld [$aa8c], a ; address of MBC30 bank
+	ld a, [$b2fa] ; address of MBC30 bank
+	inc a
+	ld [$b2fa], a ; address of MBC30 bank
+	call CloseSRAM
+	ret
+
+.dont_update
+	xor a
+	ret
+; 140ed
+
+_InitTime:: ; 140ed
+	call GetClock
+	call FixDays
+	ld hl, hRTCSeconds
+	ld de, wStartSecond
+
+	ld a, [wStringBuffer2 + 3]
+	sub [hl]
+	dec hl
+	jr nc, .okay_secs
+	add 60
+.okay_secs
+	ld [de], a
+	dec de
+
+	ld a, [wStringBuffer2 + 2]
+	sbc [hl]
+	dec hl
+	jr nc, .okay_mins
+	add 60
+.okay_mins
+	ld [de], a
+	dec de
+
+	ld a, [wStringBuffer2 + 1]
+	sbc [hl]
+	dec hl
+	jr nc, .okay_hrs
+	add 24
+.okay_hrs
+	ld [de], a
+	dec de
+
+	ld a, [wStringBuffer2]
+	sbc [hl]
+	dec hl
+	jr nc, .okay_days
+	add 140
+	ld c, 7
+	call SimpleDivide
+
+.okay_days
+	ld [de], a
+	ret
+; 1412a
--- /dev/null
+++ b/engine/rtc/timeset.asm
@@ -1,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
--- a/main.asm
+++ b/main.asm
@@ -32,30 +32,30 @@
 INCLUDE "engine/routines/printnum.asm"
 INCLUDE "engine/pokemon/health.asm"
 INCLUDE "engine/events/overworld.asm"
-INCLUDE "engine/items.asm"
+INCLUDE "engine/items/items.asm"
 INCLUDE "engine/overworld/player_step.asm"
 INCLUDE "engine/battle/anim_hp_bar.asm"
 INCLUDE "engine/pokemon/move_mon.asm"
 INCLUDE "engine/pokemon/billspctop.asm"
-INCLUDE "engine/routines/getbreedmonlevelgrowth.asm"
+INCLUDE "engine/pokemon/getbreedmonlevelgrowth.asm"
 INCLUDE "engine/events/bug_contest/caught_mon.asm"
-INCLUDE "engine/item_effects.asm"
+INCLUDE "engine/items/item_effects.asm"
 INCLUDE "engine/battle_anims/getpokeballwobble.asm"
-INCLUDE "engine/routines/knowsmove.asm"
+INCLUDE "engine/pokemon/knowsmove.asm"
 
 
 SECTION "bank4", ROMX
 
-INCLUDE "engine/menu/pack.asm"
+INCLUDE "engine/items/pack.asm"
 INCLUDE "engine/overworld/time.asm"
-INCLUDE "engine/menu/tmhm.asm"
-INCLUDE "engine/menu/naming_screen.asm"
+INCLUDE "engine/items/tmhm.asm"
+INCLUDE "engine/menus/naming_screen.asm"
 INCLUDE "engine/events/misc_scripts.asm"
 INCLUDE "engine/events/heal_machine_anim.asm"
 INCLUDE "engine/events/whiteout.asm"
 INCLUDE "engine/events/forced_movement.asm"
 INCLUDE "engine/events/itemfinder.asm"
-INCLUDE "engine/menu/start_menu.asm"
+INCLUDE "engine/menus/start_menu.asm"
 INCLUDE "engine/overworld/select_menu.asm"
 INCLUDE "engine/events/elevator.asm"
 INCLUDE "engine/events/bug_contest/contest.asm"
@@ -70,7 +70,7 @@
 
 SECTION "bank5", ROMX
 
-INCLUDE "engine/rtc.asm"
+INCLUDE "engine/rtc/rtc.asm"
 INCLUDE "engine/overworld/overworld.asm"
 INCLUDE "engine/overworld/tile_events.asm"
 INCLUDE "engine/save.asm"
@@ -77,7 +77,7 @@
 INCLUDE "engine/overworld/spawn_points.asm"
 INCLUDE "engine/overworld/map_setup.asm"
 INCLUDE "engine/events/pokecenter_pc.asm"
-INCLUDE "engine/menu/mart.asm"
+INCLUDE "engine/items/mart.asm"
 INCLUDE "engine/money.asm"
 INCLUDE "data/items/marts.asm"
 INCLUDE "engine/events/mom.asm"
@@ -95,26 +95,26 @@
 
 SECTION "Clock Reset", ROMX
 
-INCLUDE "engine/menu/clock_reset.asm"
+INCLUDE "engine/rtc/clock_reset.asm"
 
 
 SECTION "bank9", ROMX
 
 INCLUDE "data/text_buffers.asm"
-INCLUDE "engine/menu/menu.asm"
-INCLUDE "engine/routines/updateitemdescription.asm"
+INCLUDE "engine/menus/menu.asm"
+INCLUDE "engine/items/updateitemdescription.asm"
 INCLUDE "engine/events/pokepic.asm"
 INCLUDE "engine/overworld/map_objects_2.asm"
-INCLUDE "engine/menu/scrolling_menu.asm"
-INCLUDE "engine/menu/switch_items.asm"
-INCLUDE "engine/menu/menu_2.asm"
-INCLUDE "engine/menu/mon_menu.asm"
+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/battle/menu.asm"
-INCLUDE "engine/menu/buy_sell_toss.asm"
-INCLUDE "engine/menu/trainer_card.asm"
+INCLUDE "engine/items/buy_sell_toss.asm"
+INCLUDE "engine/menus/trainer_card.asm"
 INCLUDE "engine/events/prof_oaks_pc.asm"
 INCLUDE "engine/overworld/decorations.asm"
-INCLUDE "engine/routines/leveluphappinessmod.asm"
+INCLUDE "engine/pokemon/leveluphappinessmod.asm"
 INCLUDE "engine/battle/read_trainer_dvs.asm"
 INCLUDE "data/trainers/dvs.asm"
 INCLUDE "engine/battle/returntobattle_useball.asm"
@@ -148,7 +148,7 @@
 INCLUDE "data/moves/descriptions.asm"
 INCLUDE "engine/events/pokerus/pokerus.asm"
 INCLUDE "engine/battle/start_battle.asm"
-INCLUDE "engine/routines/placegraphic.asm"
+INCLUDE "engine/gfx/placegraphic.asm"
 
 
 SECTION "Effect Commands", ROMX
@@ -192,11 +192,11 @@
 SECTION "Crystal Features 1", ROMX
 
 INCLUDE "engine/init_gender.asm"
-INCLUDE "engine/routines/drawkrispackgfx.asm"
+INCLUDE "engine/gfx/drawkrispackgfx.asm"
 INCLUDE "engine/events/move_tutor.asm"
 INCLUDE "engine/gfx/crystal_layouts.asm"
 INCLUDE "engine/events/celebi.asm"
-INCLUDE "engine/menu/main_menu.asm"
+INCLUDE "engine/menus/main_menu.asm"
 INCLUDE "mobile/mobile_menu.asm"
 INCLUDE "engine/pokemon/search.asm"
 INCLUDE "mobile/mobile_12_2.asm"
@@ -212,7 +212,7 @@
 INCLUDE "engine/routines/savemenu_copytilemapatonce.asm"
 INCLUDE "engine/routines/checksave.asm"
 INCLUDE "data/maps/scenes.asm"
-INCLUDE "engine/routines/loadmappart.asm"
+INCLUDE "engine/overworld/loadmappart.asm"
 INCLUDE "engine/routines/phonering_copytilemapatonce.asm"
 
 Shrink1Pic: ; 4d249
@@ -222,10 +222,10 @@
 INCBIN "gfx/new_game/shrink2.2bpp.lz"
 
 INCLUDE "engine/link/link_2.asm"
-INCLUDE "engine/menu/delete_save_change_clock.asm"
+INCLUDE "engine/rtc/delete_save_change_clock.asm"
 INCLUDE "data/tilesets.asm"
 INCLUDE "engine/routines/flagpredef.asm"
-INCLUDE "engine/routines/trademonfrontpic.asm"
+INCLUDE "engine/gfx/trademonfrontpic.asm"
 INCLUDE "engine/events/pokerus/check_pokerus.asm"
 INCLUDE "engine/events/lucky_number.asm"
 INCLUDE "engine/pokemon/caught_data.asm"
@@ -257,7 +257,7 @@
 INCLUDE "engine/pokemon/mon_stats.asm"
 INCLUDE "engine/routines/initlist.asm"
 INCLUDE "engine/pokemon/experience.asm"
-INCLUDE "engine/routines/switchpartymons.asm"
+INCLUDE "engine/pokemon/switchpartymons.asm"
 INCLUDE "engine/gfx/load_pics.asm"
 INCLUDE "engine/pokemon/move_mon_wo_mail.asm"
 INCLUDE "data/pokemon/base_stats.asm"
@@ -316,10 +316,10 @@
 SECTION "bank24", ROMX
 
 INCLUDE "engine/phone/phone.asm"
-INCLUDE "engine/menu/timeset.asm"
+INCLUDE "engine/rtc/timeset.asm"
 INCLUDE "engine/pokegear/pokegear.asm"
 INCLUDE "engine/events/fish.asm"
-INCLUDE "engine/game/slot_machine.asm"
+INCLUDE "engine/games/slot_machine.asm"
 
 
 SECTION "Phone Engine", ROMX
@@ -430,9 +430,9 @@
 SECTION "bank38", ROMX
 
 INCLUDE "engine/events/print_unown_2.asm"
-INCLUDE "engine/game/card_flip.asm"
-INCLUDE "engine/game/unown_puzzle.asm"
-INCLUDE "engine/game/dummy_game.asm"
+INCLUDE "engine/games/card_flip.asm"
+INCLUDE "engine/games/unown_puzzle.asm"
+INCLUDE "engine/games/dummy_game.asm"
 INCLUDE "engine/pokemon/billspc.asm"
 
 
@@ -441,7 +441,7 @@
 CopyrightGFX:: ; e4000
 INCBIN "gfx/splash/copyright.2bpp"
 
-INCLUDE "engine/menu/options_menu.asm"
+INCLUDE "engine/menus/options_menu.asm"
 INCLUDE "engine/title/crystal_intro.asm"
 
 
@@ -477,7 +477,7 @@
 INCLUDE "engine/link/mystery_gift.asm"
 INCLUDE "engine/battle/used_move_text.asm"
 INCLUDE "mobile/mobile_41.asm"
-INCLUDE "engine/routines/loadoverworldfont.asm"
+INCLUDE "engine/gfx/loadoverworldfont.asm"
 
 
 SECTION "Mobile 42", ROMX
@@ -566,7 +566,7 @@
 SECTION "Miscellaneous Text", ROMX
 
 INCLUDE "data/items/names.asm"
-INCLUDE "engine/routines/printitemdescription.asm"
+INCLUDE "engine/items/printitemdescription.asm"
 INCLUDE "data/items/descriptions.asm"
 INCLUDE "data/moves/names.asm"
 INCLUDE "engine/overworld/landmarks.asm"
@@ -582,7 +582,7 @@
 
 SECTION "bank77_2", ROMX
 
-INCLUDE "engine/routines/printhoursmins.asm"
+INCLUDE "engine/rtc/printhoursmins.asm"
 INCLUDE "engine/events/diploma.asm"
 INCLUDE "engine/pokedex/pokedex_3.asm"
 INCLUDE "engine/events/catch_tutorial_input.asm"