shithub: pokecrystal

Download patch

ref: baa0dc5a963a79843b37888bcfe1d2dfe833ade9
parent: 12070ca50067d3abe36a730190f88ee43f2cace9
author: mid-kid <esteve.varela@gmail.com>
date: Tue Mar 13 09:07:16 EDT 2018

Organize the engine/ directory

This is an informed attempt at reorganizing the engine/ directory by
creating categorized subdirectories, in order to make it easier to
navigate and find things.

The directories created are as follows:
* engine/game: Contains all "minigames", things like the unown puzzle
and slot machine.
* engine/gfx: Contains all handling of graphics. From loading palettes
to playing animations.
* engine/link: Contains all multiplayer functionality.
* engine/menu: Contains all generic/misc. menus and menu code.
Other, more specialized menus are in their own subdirectories (pokedex,
pokegear, party menu, etc).
* engine/overworld: Contains all handling of the overworld. From loading
and connecting maps to wild encounters and the scripting engine.
* engine/pokegear: In the same vein as engine/pokedex, except it could
use some more splitting up.
* engine/pokemon: Contains everything related to manipulating pokemon
data. From the pokemon storage system to evolution and mail.
* engine/printer: Contains everything related to printing things as well
as the printer communication.
* engine/title: Contains intro sequences, title screens and credits.

diff: cannot open b/engine/game//null: file does not exist: 'b/engine/game//null' diff: cannot open b/engine/gfx//null: file does not exist: 'b/engine/gfx//null' diff: cannot open b/engine/link//null: file does not exist: 'b/engine/link//null' diff: cannot open b/engine/menu//null: file does not exist: 'b/engine/menu//null' diff: cannot open b/engine/overworld//null: file does not exist: 'b/engine/overworld//null' diff: cannot open b/engine/pokegear//null: file does not exist: 'b/engine/pokegear//null' diff: cannot open b/engine/pokemon//null: file does not exist: 'b/engine/pokemon//null' diff: cannot open b/engine/printer//null: file does not exist: 'b/engine/printer//null' diff: cannot open b/engine/title//null: file does not exist: 'b/engine/title//null'
--- a/Makefile
+++ b/Makefile
@@ -21,8 +21,8 @@
 data/pokemon/dex_entries.o \
 data/pokemon/egg_moves.o \
 data/pokemon/evos_attacks.o \
-engine/credits.o \
-engine/events.o \
+engine/title/credits.o \
+engine/overworld/events.o \
 gfx/pics.o \
 gfx/sprites.o \
 lib/mobile/main.o
--- a/engine/billspc.asm
+++ /dev/null
@@ -1,2618 +1,0 @@
-_DepositPKMN: ; e2391 (38:6391)
-	ld hl, wOptions
-	ld a, [hl]
-	push af
-	set 4, [hl]
-	ld a, [wVramState]
-	push af
-	xor a
-	ld [wVramState], a
-	ld a, [hInMenu]
-	push af
-	ld a, $1
-	ld [hInMenu], a
-	xor a
-	ld [hMapAnims], a
-	call BillsPC_InitRAM
-	xor a
-	ld [wBillsPC_LoadedBox], a
-	call DelayFrame
-.loop
-	call JoyTextDelay
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .done
-	call .RunJumptable
-	call DelayFrame
-	jr .loop
-.done
-	call ClearSprites
-	pop af
-	ld [hInMenu], a
-	pop af
-	ld [wVramState], a
-	pop af
-	ld [wOptions], a
-	ret
-
-.RunJumptable: ; e23d5 (38:63d5)
-	ld a, [wJumptableIndex]
-	ld hl, .Jumptable
-	call BillsPC_Jumptable
-	jp hl
-
-.Jumptable: ; e23df (38:63df)
-	dw .Init
-	dw .HandleJoypad
-	dw .WhatsUp
-	dw .Submenu
-	dw BillsPC_EndJumptableLoop
-
-.Init: ; e23e9 (38:63e9)
-	xor a
-	ld [hBGMapMode], a
-	call ClearSprites
-	call CopyBoxmonSpecies
-	call BillsPC_BoxName
-	ld de, PCString_ChooseaPKMN
-	call BillsPC_PlaceString
-	ld a, $5
-	ld [wBillsPC_NumMonsOnScreen], a
-	call BillsPC_RefreshTextboxes
-	call PCMonInfo
-	ld a, $ff
-	ld [wCurPartySpecies], a
-	ld a, SCGB_BILLS_PC
-	call BillsPC_ApplyPalettes
-	call WaitBGMap
-	call BillsPC_UpdateSelectionCursor
-	call BillsPC_IncrementJumptableIndex
-	ret
-
-.HandleJoypad: ; e241a (38:641a)
-	ld hl, hJoyPressed ; $ffa7
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .b_button
-	ld a, [hl]
-	and A_BUTTON
-	jr nz, .a_button
-	call Withdraw_UpDown
-	and a
-	ret z
-	call BillsPC_UpdateSelectionCursor
-	xor a
-	ld [hBGMapMode], a
-	call BillsPC_RefreshTextboxes
-	call PCMonInfo
-	ld a, $1
-	ld [hBGMapMode], a
-	call DelayFrame
-	call DelayFrame
-	ret
-
-.a_button
-	call BillsPC_GetSelectedPokemonSpecies
-	and a
-	ret z
-	cp -1
-	jr z, .b_button
-	ld a, $2
-	ld [wJumptableIndex], a
-	ret
-; e2452 (38:6452)
-
-.go_back
-	ld hl, wJumptableIndex
-	dec [hl]
-	ret
-
-.b_button
-	ld a, $4
-	ld [wJumptableIndex], a
-	ret
-
-.WhatsUp: ; e245d (38:645d)
-	xor a
-	ld [hBGMapMode], a
-	call ClearSprites
-	call BillsPC_GetSelectedPokemonSpecies
-	ld [wCurPartySpecies], a
-	ld a, SCGB_BILLS_PC
-	call BillsPC_ApplyPalettes
-	ld de, PCString_WhatsUp
-	call BillsPC_PlaceString
-	ld a, $1
-	ld [wMenuCursorY], a
-	call BillsPC_IncrementJumptableIndex
-	ret
-
-.Submenu: ; e247d (38:647d)
-	ld hl, BillsPCDepositMenuHeader
-	call CopyMenuHeader
-	ld a, [wMenuCursorY]
-	call StoreTo_wMenuCursorBuffer
-	call VerticalMenu
-	jp c, BillsPCDepositFuncCancel
-	ld a, [wMenuCursorY]
-	dec a
-	and %11
-	ld e, a
-	ld d, 0
-	ld hl, BillsPCDepositJumptable
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-BillsPCDepositJumptable: ; e24a1 (38:64a1)
-	dw BillsPCDepositFuncDeposit ; Deposit Pokemon
-	dw BillsPCDepositFuncStats ; Pokemon Stats
-	dw BillsPCDepositFuncRelease ; Release Pokemon
-	dw BillsPCDepositFuncCancel ; Cancel
-
-
-BillsPCDepositFuncDeposit: ; e24a9 (38:64a9)
-	call BillsPC_CheckMail_PreventBlackout
-	jp c, BillsPCDepositFuncCancel
-	call DepositPokemon
-	jr c, .box_full
-	ld a, $0
-	ld [wJumptableIndex], a
-	xor a
-	ld [wBillsPC_CursorPosition], a
-	ld [wBillsPC_ScrollPosition], a
-	ret
-
-.box_full
-	ld de, PCString_WhatsUp
-	call BillsPC_PlaceString
-	ret
-
-BillsPCDepositFuncStats: ; e24c8 (38:64c8)
-	call LoadStandardMenuHeader
-	call BillsPC_StatsScreen
-	call ExitMenu
-	call PCMonInfo
-	call BillsPC_GetSelectedPokemonSpecies
-	ld [wCurPartySpecies], a
-	ld a, SCGB_BILLS_PC
-	call BillsPC_ApplyPalettes
-	ret
-
-BillsPCDepositFuncRelease: ; e24e0 (38:64e0)
-	call BillsPC_CheckMail_PreventBlackout
-	jr c, BillsPCDepositFuncCancel
-	call BillsPC_IsMonAnEgg
-	jr c, BillsPCDepositFuncCancel
-	ld a, [wMenuCursorY]
-	push af
-	ld de, PCString_ReleasePKMN
-	call BillsPC_PlaceString
-	call LoadStandardMenuHeader
-	lb bc, 14, 11
-	call PlaceYesNoBox
-	ld a, [wMenuCursorY]
-	dec a
-	call ExitMenu
-	and a
-	jr nz, .failed_release
-	ld a, [wBillsPC_CursorPosition]
-	ld hl, wBillsPC_ScrollPosition
-	add [hl]
-	ld [wCurPartyMon], a
-	xor a ; REMOVE_PARTY
-	ld [wPokemonWithdrawDepositParameter], a
-	farcall RemoveMonFromPartyOrBox
-	call ReleasePKMN_ByePKMN
-	ld a, $0
-	ld [wJumptableIndex], a
-	xor a
-	ld [wBillsPC_CursorPosition], a
-	ld [wBillsPC_ScrollPosition], a
-	pop af
-	ret
-
-.failed_release
-	ld de, PCString_WhatsUp
-	call BillsPC_PlaceString
-	pop af
-	ld [wMenuCursorY], a
-	ret
-
-BillsPCDepositFuncCancel: ; e2537 (38:6537)
-	ld a, $0
-	ld [wJumptableIndex], a
-	ret
-; e253d (38:653d)
-
-BillsPCDepositMenuHeader: ; 0xe253d (38:653d)
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 9, 4, SCREEN_WIDTH - 1, 13
-	dw .MenuData
-	db 1 ; default option
-; 0xe2545
-
-.MenuData: ; 0xe2545 (38:6545)
-	db STATICMENU_CURSOR ; flags
-	db 4 ; items
-	db "DEPOSIT@"
-	db "STATS@"
-	db "RELEASE@"
-	db "CANCEL@"
-; 0xe2564 (38:6564)
-
-Unreferenced_BillsPCClearThreeBoxes: ; e2564
-	hlcoord 0, 0
-	ld b,  4
-	ld c,  8
-	call ClearBox
-	hlcoord 0, 4
-	ld b, 10
-	ld c,  9
-	call ClearBox
-	hlcoord 0, 14
-	ld b,  2
-	ld c,  8
-	call ClearBox
-	ret
-; e2583
-
-_WithdrawPKMN: ; e2583 (38:6583)
-	ld hl, wOptions
-	ld a, [hl]
-	push af
-	set 4, [hl]
-	ld a, [wVramState]
-	push af
-	xor a
-	ld [wVramState], a
-	ld a, [hInMenu]
-	push af
-	ld a, $1
-	ld [hInMenu], a
-	xor a
-	ld [hMapAnims], a
-	call BillsPC_InitRAM
-	ld a, NUM_BOXES + 1
-	ld [wBillsPC_LoadedBox], a
-	call DelayFrame
-.loop
-	call JoyTextDelay
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .done
-	call .RunJumptable
-	call DelayFrame
-	jr .loop
-.done
-	call ClearSprites
-	pop af
-	ld [hInMenu], a
-	pop af
-	ld [wVramState], a
-	pop af
-	ld [wOptions], a
-	ret
-
-.RunJumptable: ; e25c8 (38:65c8)
-	ld a, [wJumptableIndex]
-	ld hl, .Jumptable
-	call BillsPC_Jumptable
-	jp hl
-
-.Jumptable: ; e25d2 (38:65d2)
-	dw .Init
-	dw .Joypad
-	dw .PrepSubmenu
-	dw BillsPC_Withdraw
-	dw BillsPC_EndJumptableLoop
-
-.Init: ; e25dc (38:65dc)
-	ld a, NUM_BOXES + 1
-	ld [wBillsPC_LoadedBox], a
-	xor a
-	ld [hBGMapMode], a
-	call ClearSprites
-	call CopyBoxmonSpecies
-	call BillsPC_BoxName
-	ld de, PCString_ChooseaPKMN
-	call BillsPC_PlaceString
-	ld a, $5
-	ld [wBillsPC_NumMonsOnScreen], a
-	call BillsPC_RefreshTextboxes
-	call PCMonInfo
-	ld a, $ff
-	ld [wCurPartySpecies], a
-	ld a, SCGB_BILLS_PC
-	call BillsPC_ApplyPalettes
-	call WaitBGMap
-	call BillsPC_UpdateSelectionCursor
-	call BillsPC_IncrementJumptableIndex
-	ret
-
-.Joypad: ; e2612 (38:6612)
-	ld hl, hJoyPressed ; $ffa7
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .b_button
-	ld a, [hl]
-	and A_BUTTON
-	jr nz, .a_button
-	call Withdraw_UpDown
-	and a
-	ret z
-	call BillsPC_UpdateSelectionCursor
-	xor a
-	ld [hBGMapMode], a
-	call BillsPC_RefreshTextboxes
-	call PCMonInfo
-	ld a, $1
-	ld [hBGMapMode], a
-	call DelayFrame
-	call DelayFrame
-	ret
-.a_button
-	call BillsPC_GetSelectedPokemonSpecies
-	and a
-	ret z
-	cp -1
-	jr z, .b_button
-	ld a, $2
-	ld [wJumptableIndex], a
-	ret ; e264a (38:664a)
-
-.unused
-	ld hl, wJumptableIndex
-	dec [hl]
-	ret
-
-.b_button
-	ld a, $4
-	ld [wJumptableIndex], a
-	ret
-; e2655
-
-.PrepSubmenu: ; e2655 (38:6655)
-	xor a
-	ld [hBGMapMode], a
-	call ClearSprites
-	call BillsPC_GetSelectedPokemonSpecies
-	ld [wCurPartySpecies], a
-	ld a, SCGB_BILLS_PC
-	call BillsPC_ApplyPalettes
-	ld de, PCString_WhatsUp
-	call BillsPC_PlaceString
-	ld a, $1
-	ld [wMenuCursorY], a
-	call BillsPC_IncrementJumptableIndex
-	ret
-
-BillsPC_Withdraw: ; e2675 (38:6675)
-	ld hl, .MenuHeader
-	call CopyMenuHeader
-	ld a, [wMenuCursorY]
-	call StoreTo_wMenuCursorBuffer
-	call VerticalMenu
-	jp c, .cancel
-	ld a, [wMenuCursorY]
-	dec a
-	and %11
-	ld e, a
-	ld d, 0
-	ld hl, .dw
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-.dw ; e2699 (38:6699) #mark
-	dw .withdraw ; Withdraw
-	dw .stats ; Stats
-	dw .release ; Release
-	dw .cancel ; Cancel
-
-
-.withdraw ; e26a1 (38:66a1)
-	call BillsPC_CheckMail_PreventBlackout
-	jp c, .cancel
-	call TryWithdrawPokemon
-	jr c, .FailedWithdraw
-	ld a, $0
-	ld [wJumptableIndex], a
-	xor a
-	ld [wBillsPC_CursorPosition], a
-	ld [wBillsPC_ScrollPosition], a
-	ret
-.FailedWithdraw:
-	ld de, PCString_WhatsUp
-	call BillsPC_PlaceString
-	ret
-
-.stats ; e26c0 (38:66c0)
-	call LoadStandardMenuHeader
-	call BillsPC_StatsScreen
-	call ExitMenu
-	call PCMonInfo
-	call BillsPC_GetSelectedPokemonSpecies
-	ld [wCurPartySpecies], a
-	ld a, SCGB_BILLS_PC
-	call BillsPC_ApplyPalettes
-	ret
-
-.release ; e26d8 (38:66d8)
-	ld a, [wMenuCursorY]
-	push af
-	call BillsPC_IsMonAnEgg
-	jr c, .FailedRelease
-	ld de, PCString_ReleasePKMN
-	call BillsPC_PlaceString
-	call LoadStandardMenuHeader
-	lb bc, 14, 11
-	call PlaceYesNoBox
-	ld a, [wMenuCursorY]
-	dec a
-	call ExitMenu
-	and a
-	jr nz, .FailedRelease
-	ld a, [wBillsPC_CursorPosition]
-	ld hl, wBillsPC_ScrollPosition
-	add [hl]
-	ld [wCurPartyMon], a
-	ld a, REMOVE_BOX
-	ld [wPokemonWithdrawDepositParameter], a
-	farcall RemoveMonFromPartyOrBox
-	call ReleasePKMN_ByePKMN
-	ld a, $0
-	ld [wJumptableIndex], a
-	xor a
-	ld [wBillsPC_CursorPosition], a
-	ld [wBillsPC_ScrollPosition], a
-	pop af
-	ret
-.FailedRelease:
-	ld de, PCString_WhatsUp
-	call BillsPC_PlaceString
-	pop af
-	ld [wMenuCursorY], a
-	ret
-
-.cancel ; e272b (38:672b)
-	ld a, $0
-	ld [wJumptableIndex], a
-	ret
-; e2731 (38:6731)
-
-.MenuHeader: ; 0xe2731
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 9, 4, SCREEN_WIDTH - 1, 13
-	dw .MenuData
-	db 1 ; default option
-; 0xe2739
-
-.MenuData: ; 0xe2739
-	db STATICMENU_CURSOR ; flags
-	db 4 ; items
-	db "WITHDRAW@"
-	db "STATS@"
-	db "RELEASE@"
-	db "CANCEL@"
-; 0xe2759
-
-_MovePKMNWithoutMail: ; e2759
-	ld hl, wOptions
-	ld a, [hl]
-	push af
-	set 4, [hl]
-	ld a, [wVramState]
-	push af
-	xor a
-	ld [wVramState], a
-	ld a, [hInMenu]
-	push af
-	ld a, $1
-	ld [hInMenu], a
-	xor a
-	ld [hMapAnims], a
-	call BillsPC_InitRAM
-	ld a, [wCurBox]
-	and $f
-	inc a
-	ld [wBillsPC_LoadedBox], a
-	call DelayFrame
-.asm_e2781
-	call JoyTextDelay
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .asm_e2793
-	call .RunJumptable
-	call DelayFrame
-	jr .asm_e2781
-
-.asm_e2793
-	call ClearSprites
-	pop af
-	ld [hInMenu], a
-	pop af
-	ld [wVramState], a
-	pop af
-	ld [wOptions], a
-	ret
-; e27a2
-
-.RunJumptable: ; e27a2
-	ld a, [wJumptableIndex]
-	ld hl, .Jumptable
-	call BillsPC_Jumptable
-	jp hl
-; e27ac
-
-.Jumptable: ; e27ac
-	dw .Init
-	dw .Joypad
-	dw .PrepSubmenu
-	dw .MoveMonWOMailSubmenu
-	dw .PrepInsertCursor
-	dw .Joypad2
-	dw BillsPC_EndJumptableLoop
-; e27ba
-
-.Init: ; e27ba
-	xor a
-	ld [hBGMapMode], a
-	call ClearSprites
-	call CopyBoxmonSpecies
-	ld de, PCString_ChooseaPKMN
-	call BillsPC_PlaceString
-	ld a, 5
-	ld [wBillsPC_NumMonsOnScreen], a
-	call BillsPC_RefreshTextboxes
-	call BillsPC_MoveMonWOMail_BoxNameAndArrows
-	call PCMonInfo
-	ld a, $ff
-	ld [wCurPartySpecies], a
-	ld a, SCGB_BILLS_PC
-	call BillsPC_ApplyPalettes
-	call WaitBGMap
-	call BillsPC_UpdateSelectionCursor
-	call BillsPC_IncrementJumptableIndex
-	ret
-; e27eb
-
-.Joypad: ; e27eb
-	ld hl, hJoyPressed
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .b_button
-	ld a, [hl]
-	and A_BUTTON
-	jr nz, .a_button
-	call MoveMonWithoutMail_DPad
-	jr c, .d_pad
-	and a
-	ret z
-	call BillsPC_UpdateSelectionCursor
-	xor a
-	ld [hBGMapMode], a
-	call BillsPC_RefreshTextboxes
-	call PCMonInfo
-	ld a, $1
-	ld [hBGMapMode], a
-	call DelayFrame
-	call DelayFrame
-	ret
-
-.d_pad
-	xor a
-	ld [wBillsPC_CursorPosition], a
-	ld [wBillsPC_ScrollPosition], a
-	ld a, $0
-	ld [wJumptableIndex], a
-	ret
-
-.a_button
-	call BillsPC_GetSelectedPokemonSpecies
-	and a
-	ret z
-	cp -1
-	jr z, .b_button
-	ld a, $2
-	ld [wJumptableIndex], a
-	ret
-
-.unused
-	ld hl, wJumptableIndex
-	dec [hl]
-	ret
-
-.b_button
-	ld a, $6
-	ld [wJumptableIndex], a
-	ret
-; e283d
-
-.PrepSubmenu: ; e283d
-	xor a
-	ld [hBGMapMode], a
-	call ClearSprites
-	call BillsPC_GetSelectedPokemonSpecies
-	ld [wCurPartySpecies], a
-	ld a, SCGB_BILLS_PC
-	call BillsPC_ApplyPalettes
-	ld de, PCString_WhatsUp
-	call BillsPC_PlaceString
-	ld a, $1
-	ld [wMenuCursorY], a
-	call BillsPC_IncrementJumptableIndex
-	ret
-; e285d
-
-.MoveMonWOMailSubmenu: ; e285d
-	ld hl, .MenuHeader
-	call CopyMenuHeader
-	ld a, [wMenuCursorY]
-	call StoreTo_wMenuCursorBuffer
-	call VerticalMenu
-	jp c, .Cancel
-	ld a, [wMenuCursorY]
-	dec a
-	and %11
-	ld e, a
-	ld d, 0
-	ld hl, .Jumptable2
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-; e2881
-
-.Jumptable2: ; e2881
-	dw .Move
-	dw .Stats
-	dw .Cancel
-; e2887
-
-.Move: ; e2887
-	call BillsPC_CheckMail_PreventBlackout
-	jp c, .Cancel
-	ld a, [wBillsPC_ScrollPosition]
-	ld [wBillsPC_BackupScrollPosition], a
-	ld a, [wBillsPC_CursorPosition]
-	ld [wBillsPC_BackupCursorPosition], a
-	ld a, [wBillsPC_LoadedBox]
-	ld [wBillsPC_BackupLoadedBox], a
-	ld a, $4
-	ld [wJumptableIndex], a
-	ret
-; e28a5
-
-.Stats: ; e28a5
-	call LoadStandardMenuHeader
-	call BillsPC_StatsScreen
-	call ExitMenu
-	call PCMonInfo
-	call BillsPC_GetSelectedPokemonSpecies
-	ld [wCurPartySpecies], a
-	ld a, SCGB_BILLS_PC
-	call BillsPC_ApplyPalettes
-	ret
-; e28bd
-
-.Cancel: ; e28bd
-	ld a, $0
-	ld [wJumptableIndex], a
-	ret
-; e28c3
-
-.MenuHeader: ; 0xe28c3
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 9, 4, SCREEN_WIDTH - 1, 13
-	dw .MenuData
-	db 1 ; default option
-; 0xe28cb
-
-.MenuData: ; 0xe28cb
-	db STATICMENU_CURSOR ; flags
-	db 3 ; items
-	db "MOVE@"
-	db "STATS@"
-	db "CANCEL@"
-; 0xe28df
-
-.PrepInsertCursor: ; e28df
-	xor a
-	ld [hBGMapMode], a
-	call CopyBoxmonSpecies
-	ld de, PCString_MoveToWhere
-	call BillsPC_PlaceString
-	ld a, $5
-	ld [wBillsPC_NumMonsOnScreen], a
-	call BillsPC_RefreshTextboxes
-	call BillsPC_MoveMonWOMail_BoxNameAndArrows
-	call ClearSprites
-	call BillsPC_UpdateInsertCursor
-	call WaitBGMap
-	call BillsPC_IncrementJumptableIndex
-	ret
-; e2903
-
-.Joypad2: ; e2903
-	ld hl, hJoyPressed
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .b_button_2
-	ld a, [hl]
-	and A_BUTTON
-	jr nz, .a_button_2
-	call MoveMonWithoutMail_DPad_2
-	jr c, .dpad_2
-	and a
-	ret z
-	call BillsPC_UpdateInsertCursor
-	xor a
-	ld [hBGMapMode], a
-	call BillsPC_RefreshTextboxes
-	ld a, $1
-	ld [hBGMapMode], a
-	call DelayFrame
-	call DelayFrame
-	ret
-
-.dpad_2
-	xor a
-	ld [wBillsPC_CursorPosition], a
-	ld [wBillsPC_ScrollPosition], a
-	ld a, $4
-	ld [wJumptableIndex], a
-	ret
-
-.a_button_2
-	call BillsPC_CheckSpaceInDestination
-	jr c, .no_space
-	call MovePKMNWitoutMail_InsertMon
-	ld a, $0
-	ld [wJumptableIndex], a
-	ret
-
-.no_space
-	ld hl, wJumptableIndex
-	dec [hl]
-	ret
-
-.b_button_2
-	ld a, [wBillsPC_BackupScrollPosition]
-	ld [wBillsPC_ScrollPosition], a
-	ld a, [wBillsPC_BackupCursorPosition]
-	ld [wBillsPC_CursorPosition], a
-	ld a, [wBillsPC_BackupLoadedBox]
-	ld [wBillsPC_LoadedBox], a
-	ld a, $0
-	ld [wJumptableIndex], a
-	ret
-; e2963
-
-BillsPC_InitRAM: ; e2963 (38:6963)
-	call ClearBGPalettes
-	call ClearSprites
-	call ClearTileMap
-	call BillsPC_InitGFX
-	ld hl, wBillsPCPokemonList
-	ld bc, $338
-	xor a
-	call ByteFill
-	xor a
-	ld [wJumptableIndex], a
-	ld [wcf64], a
-	ld [wcf65], a
-	ld [wcf66], a
-	ld [wBillsPC_CursorPosition], a
-	ld [wBillsPC_ScrollPosition], a
-	ret
-
-BillsPC_IncrementJumptableIndex: ; e298d (38:698d)
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-BillsPC_EndJumptableLoop: ; e2992 (38:6992)
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-_StatsScreenDPad: ; e2998 (38:6998)
-	ld a, [wBillsPC_NumMonsOnScreen]
-	ld d, a
-	ld a, [wBillsPC_NumMonsInBox]
-	and a
-	jr z, .empty
-	dec a
-	cp $1
-	jr z, .empty
-	ld e, a
-	ld a, [hl]
-	and D_UP
-	jr nz, BillsPC_PressUp
-	ld a, [hl]
-	and D_DOWN
-	jr nz, BillsPC_PressDown
-.empty
-	jp BillsPC_JoypadDidNothing
-
-Withdraw_UpDown: ; e29b5 (38:69b5)
-	ld hl, hJoyLast
-	ld a, [wBillsPC_NumMonsOnScreen]
-	ld d, a
-	ld a, [wBillsPC_NumMonsInBox]
-	ld e, a
-	and a
-	jr z, .empty
-	ld a, [hl]
-	and D_UP
-	jr nz, BillsPC_PressUp
-	ld a, [hl]
-	and D_DOWN
-	jr nz, BillsPC_PressDown
-.empty
-	jp BillsPC_JoypadDidNothing
-; e29d0 (38:69d0)
-
-MoveMonWithoutMail_DPad: ; e29d0
-	ld hl, hJoyLast
-	ld a, [wBillsPC_NumMonsOnScreen]
-	ld d, a
-	ld a, [wBillsPC_NumMonsInBox]
-	ld e, a
-	and a
-	jr z, .check_left_right
-	ld a, [hl]
-	and D_UP
-	jr nz, BillsPC_PressUp
-	ld a, [hl]
-	and D_DOWN
-	jr nz, BillsPC_PressDown
-
-.check_left_right
-	ld a, [hl]
-	and D_LEFT
-	jr nz, BillsPC_PressLeft
-	ld a, [hl]
-	and D_RIGHT
-	jr nz, BillsPC_PressRight
-	jr BillsPC_JoypadDidNothing
-
-MoveMonWithoutMail_DPad_2: ; e29f4
-	ld hl, hJoyLast
-	ld a, [wBillsPC_NumMonsOnScreen]
-	ld d, a
-	ld a, [wBillsPC_NumMonsInBox]
-	ld e, a
-	and a
-	jr z, .check_left_right
-
-	ld a, [hl]
-	and D_UP
-	jr nz, BillsPC_PressUp
-	ld a, [hl]
-	and D_DOWN
-	jr nz, BillsPC_PressDown
-
-.check_left_right
-	ld a, [hl]
-	and D_LEFT
-	jr nz, BillsPC_PressLeft
-	ld a, [hl]
-	and D_RIGHT
-	jr nz, BillsPC_PressRight
-	jr BillsPC_JoypadDidNothing
-
-BillsPC_PressUp: ; e2a18 (38:6a18)
-	ld hl, wBillsPC_CursorPosition
-	ld a, [hl]
-	and a
-	jr z, .top
-	dec [hl]
-	jr BillsPC_UpDownDidSomething
-
-.top
-	ld hl, wBillsPC_ScrollPosition
-	ld a, [hl]
-	and a
-	jr z, BillsPC_JoypadDidNothing
-	dec [hl]
-	jr BillsPC_UpDownDidSomething
-
-BillsPC_PressDown: ; e2a2c (38:6a2c)
-	ld a, [wBillsPC_CursorPosition]
-	ld hl, wBillsPC_ScrollPosition
-	add [hl]
-	inc a
-	cp e
-	jr nc, BillsPC_JoypadDidNothing
-
-	ld hl, wBillsPC_CursorPosition
-	ld a, [hl]
-	inc a
-	cp d
-	jr nc, .not_bottom
-	inc [hl]
-	jr BillsPC_UpDownDidSomething
-
-.not_bottom
-	ld hl, wBillsPC_ScrollPosition
-	inc [hl]
-	jr BillsPC_UpDownDidSomething
-; e2a48 (38:6a48)
-
-BillsPC_PressLeft: ; e2a48
-	ld hl, wBillsPC_LoadedBox
-	ld a, [hl]
-	and a
-	jr z, .wrap_around
-	dec [hl]
-	jr BillsPC_LeftRightDidSomething
-
-.wrap_around
-	ld [hl], NUM_BOXES
-	jr BillsPC_LeftRightDidSomething
-
-BillsPC_PressRight: ; e2a56
-	ld hl, wBillsPC_LoadedBox
-	ld a, [hl]
-	cp NUM_BOXES
-	jr z, .wrap_around
-	inc [hl]
-	jr BillsPC_LeftRightDidSomething
-
-.wrap_around
-	ld [hl], 0
-	jr BillsPC_LeftRightDidSomething
-
-BillsPC_JoypadDidNothing: ; e2a65 (38:6a65)
-	xor a
-	and a
-	ret
-
-BillsPC_UpDownDidSomething: ; e2a68 (38:6a68)
-	ld a, TRUE
-	and a
-	ret
-; e2a6c (38:6a6c)
-
-BillsPC_LeftRightDidSomething: ; e2a6c
-	scf
-	ret
-; e2a6e
-
-BillsPC_PlaceString: ; e2a6e (38:6a6e)
-	push de
-	hlcoord 0, 15
-	lb bc, 1, 18
-	call TextBox
-	pop de
-	hlcoord 1, 16
-	call PlaceString
-	ret
-; e2a80 (38:6a80)
-
-BillsPC_MoveMonWOMail_BoxNameAndArrows: ; e2a80
-	call BillsPC_BoxName
-	hlcoord 8, 1
-	ld [hl], $5f
-	hlcoord 19, 1
-	ld [hl], $5e
-	ret
-; e2a8e
-
-BillsPC_BoxName: ; e2a8e (38:6a8e)
-	hlcoord 8, 0
-	lb bc, 1, 10
-	call TextBox
-
-	ld a, [wBillsPC_LoadedBox]
-	and a
-	jr z, .party
-
-	cp NUM_BOXES + 1
-	jr nz, .gotbox
-
-	ld a, [wCurBox]
-	inc a
-.gotbox
-	dec a
-	ld hl, wBoxNames
-	ld bc, BOX_NAME_LENGTH
-	call AddNTimes
-	ld e, l
-	ld d, h
-	jr .print
-
-.party
-	ld de, .PartyPKMN
-.print
-	hlcoord 10, 1
-	call PlaceString
-	ret
-; e2abd (38:6abd)
-
-.PartyPKMN:
-	db "PARTY <PK><MN>@"
-; e2ac6
-
-PCMonInfo: ; e2ac6 (38:6ac6)
-; Display a monster's pic and
-; attributes when highlighting
-; it in a PC menu.
-
-; Includes the neat cascading
-; effect when showing the pic.
-
-; Example: Species, level, gender,
-; whether it's holding an item.
-
-	hlcoord 0, 0
-	lb bc, 15, 8
-	call ClearBox
-
-	hlcoord 8, 14
-	lb bc, 1, 3
-	call ClearBox
-
-	call BillsPC_GetSelectedPokemonSpecies
-	and a
-	ret z
-	cp -1
-	ret z
-
-	ld [wd265], a
-	hlcoord 1, 4
-	xor a
-	ld b, 7
-.row
-	ld c, 7
-	push af
-	push hl
-.col
-	ld [hli], a
-	add 7
-	dec c
-	jr nz, .col
-	pop hl
-	ld de, SCREEN_WIDTH
-	add hl, de
-	pop af
-	inc a
-	dec b
-	jr nz, .row
-
-	call BillsPC_LoadMonStats
-	ld a, [wd265]
-	ld [wCurPartySpecies], a
-	ld [wCurSpecies], a
-	ld hl, wTempMonDVs
-	predef GetUnownLetter
-	call GetBaseData
-	ld de, vTiles2 tile $00
-	predef GetMonFrontpic
-	xor a
-	ld [wBillsPC_MonHasMail], a
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	cp EGG
-	ret z
-
-	call GetBasePokemonName
-	hlcoord 1, 14
-	call PlaceString
-
-	hlcoord 1, 12
-	call PrintLevel
-
-	ld a, $3
-	ld [wMonType], a
-	farcall GetGender
-	jr c, .skip_gender
-	ld a, "♂"
-	jr nz, .printgender
-	ld a, "♀"
-.printgender
-	hlcoord 5, 12
-	ld [hl], a
-.skip_gender
-
-	ld a, [wTempMonItem]
-	and a
-	ret z
-
-	ld d, a
-	callfar ItemIsMail
-	jr c, .mail
-	ld a, $5d ; item icon
-	jr .printitem
-.mail
-	ld a, $1
-	ld [wBillsPC_MonHasMail], a
-	ld a, $5c ; mail icon
-.printitem
-	hlcoord 7, 12
-	ld [hl], a
-	ret
-
-BillsPC_LoadMonStats: ; e2b6d (38:6b6d)
-	ld a, [wBillsPC_CursorPosition]
-	ld hl, wBillsPC_ScrollPosition
-	add [hl]
-	ld e, a
-	ld d, $0
-	ld hl, wBillsPCPokemonList + 1 ; box number
-	add hl, de
-	add hl, de
-	add hl, de
-	ld a, [hl]
-	and a
-	jr z, .party
-	cp NUM_BOXES + 1
-	jr z, .sBox
-	ld b, a
-	call GetBoxPointer
-	ld a, b
-	call GetSRAMBank
-	push hl
-	ld bc, sBoxMon1Level - sBox
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, e
-	call AddNTimes
-	ld a, [hl]
-	ld [wTempMonLevel], a
-	pop hl
-	push hl
-	ld bc, sBoxMon1Item - sBox
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, e
-	call AddNTimes
-	ld a, [hl]
-	ld [wTempMonItem], a
-	pop hl
-	ld bc, sBoxMon1DVs - sBox
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, e
-	call AddNTimes
-	ld de, wTempMonDVs
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-	call CloseSRAM
-	ret
-
-.party
-	ld hl, wPartyMon1Level
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, e
-	call AddNTimes
-	ld a, [hl]
-	ld [wTempMonLevel], a
-	ld hl, wPartyMon1Item
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, e
-	call AddNTimes
-	ld a, [hl]
-	ld [wTempMonItem], a
-	ld hl, wPartyMon1DVs
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, e
-	call AddNTimes
-	ld de, wTempMonDVs
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-	ret
-
-.sBox
-	ld a, BANK(sBox)
-	call GetSRAMBank
-	ld hl, sBoxMon1Level
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, e
-	call AddNTimes
-	ld a, [hl]
-	ld [wTempMonLevel], a
-
-	ld hl, sBoxMon1Item
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, e
-	call AddNTimes
-	ld a, [hl]
-	ld [wTempMonItem], a
-
-	ld hl, sBoxMon1DVs
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, e
-	call AddNTimes
-	ld de, wTempMonDVs
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-
-	call CloseSRAM
-	ret
-
-BillsPC_RefreshTextboxes: ; e2c2c (38:6c2c)
-	hlcoord 8, 2
-	lb bc, 10, 10
-	call TextBox
-
-	hlcoord 8, 2
-	ld [hl], "└"
-	hlcoord 19, 2
-	ld [hl], "┘"
-
-	ld a, [wBillsPC_ScrollPosition]
-	ld e, a
-	ld d, 0
-	ld hl, wBillsPCPokemonList
-	add hl, de
-	add hl, de
-	add hl, de
-	ld e, l
-	ld d, h
-	hlcoord 9, 4
-	ld a, [wBillsPC_NumMonsOnScreen]
-.loop
-	push af
-	push de
-	push hl
-	call .PlaceNickname
-	pop hl
-	ld de, 2 * SCREEN_WIDTH
-	add hl, de
-	pop de
-	inc de
-	inc de
-	inc de
-	pop af
-	dec a
-	jr nz, .loop
-	ret
-; e2c67 (38:6c67)
-
-.CancelString:
-	db "CANCEL@"
-; e2c6e
-
-.PlaceNickname: ; e2c6e (38:6c6e)
-	ld a, [de]
-	and a
-	ret z
-	cp -1
-	jr nz, .get_nickname
-	ld de, .CancelString
-	call PlaceString
-	ret
-
-.get_nickname
-	inc de
-	ld a, [de]
-	ld b, a
-	inc de
-	ld a, [de]
-	ld e, a
-	ld a, b
-	and a
-	jr z, .party
-	cp NUM_BOXES + 1
-	jr z, .sBox
-	push hl
-	call GetBoxPointer
-	ld a, b
-	call GetSRAMBank
-	push hl
-	ld bc, sBoxMons - sBox
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, e
-	call AddNTimes
-	ld a, [hl]
-	pop hl
-	and a
-	jr z, .boxfail
-	ld bc, sBoxMonNicknames - sBox
-	add hl, bc
-	ld bc, MON_NAME_LENGTH
-	ld a, e
-	call AddNTimes
-	ld de, wStringBuffer1
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-	call CloseSRAM
-	pop hl
-	ld de, wStringBuffer1
-	call PlaceString
-	ret
-
-.boxfail
-	call CloseSRAM
-	pop hl
-	jr .placeholder_string
-
-.party
-	push hl
-	ld hl, wPartySpecies
-	ld d, $0
-	add hl, de
-	ld a, [hl]
-	and a
-	jr z, .partyfail
-	ld hl, wPartyMonNicknames
-	ld bc, MON_NAME_LENGTH
-	ld a, e
-	call AddNTimes
-	ld de, wStringBuffer1
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-	pop hl
-	ld de, wStringBuffer1
-	call PlaceString
-	ret
-
-.partyfail
-	pop hl
-	jr .placeholder_string
-
-.sBox
-	push hl
-	ld a, BANK(sBox)
-	call GetSRAMBank
-	ld hl, sBoxSpecies
-	ld d, $0
-	add hl, de
-	ld a, [hl]
-	and a
-	jr z, .sBoxFail
-	ld hl, sBoxMonNicknames
-	ld bc, MON_NAME_LENGTH
-	ld a, e
-	call AddNTimes
-	ld de, wStringBuffer1
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-	call CloseSRAM
-	pop hl
-	ld de, wStringBuffer1
-	call PlaceString
-	ret
-
-.sBoxFail
-	call CloseSRAM
-	pop hl
-.placeholder_string
-	ld de, .Placeholder
-	call PlaceString
-	ret
-; e2d2a (38:6d2a)
-
-.Placeholder:
-	db "-----@"
-; e2d30
-
-copy_box_data: MACRO
-.loop\@
-	ld a, [hl]
-	cp -1
-	jr z, .done\@
-	and a
-	jr z, .done\@
-	ld [de], a
-	inc de
-	ld a, [wBillsPC_LoadedBox]
-	ld [de], a
-	inc de
-	ld a, [wd003]
-	ld [de], a
-	inc a
-	ld [wd003], a
-	inc de
-	inc hl
-	ld a, [wd004]
-	inc a
-	ld [wd004], a
-	jr .loop\@
-
-.done\@
-if \1
-	call CloseSRAM
-endc
-	ld a, -1
-	ld [de], a
-	ld a, [wd004]
-	inc a
-	ld [wBillsPC_NumMonsInBox], a
-ENDM
-
-CopyBoxmonSpecies: ; e2d30 (38:6d30)
-	xor a
-	ld hl, wBillsPCPokemonList
-	ld bc, 3 * 30
-	call ByteFill
-	ld de, wBillsPCPokemonList
-	xor a
-	ld [wd003], a
-	ld [wd004], a
-	ld a, [wBillsPC_LoadedBox]
-	and a
-	jr z, .party
-	cp NUM_BOXES + 1
-	jr z, .sBox
-	ld b, a
-	call GetBoxPointer
-	ld a, b
-	call GetSRAMBank
-	inc hl
-	copy_box_data 1
-	ret
-
-.party
-	ld hl, wPartySpecies
-	copy_box_data 0
-	ret
-
-.sBox
-	ld a, BANK(sBox)
-	call GetSRAMBank
-	ld hl, sBoxSpecies
-	copy_box_data 1
-	ret
-
-BillsPC_GetSelectedPokemonSpecies: ; e2def (38:6def)
-	ld a, [wBillsPC_CursorPosition]
-	ld hl, wBillsPC_ScrollPosition
-	add [hl]
-	ld e, a
-	ld d, $0
-	ld hl, wBillsPCPokemonList
-	add hl, de
-	add hl, de
-	add hl, de
-	ld a, [hl]
-	ret
-
-BillsPC_UpdateSelectionCursor: ; e2e01 (38:6e01)
-	ld a, [wBillsPC_NumMonsInBox]
-	and a
-	jr nz, .place_cursor
-	call ClearSprites
-	ret
-
-.place_cursor
-	ld hl, .OAM
-	ld de, wVirtualOAMSprite00
-.loop
-	ld a, [hl]
-	cp -1
-	ret z
-	ld a, [wBillsPC_CursorPosition]
-	and $7
-	swap a
-	add [hl]
-	inc hl
-	ld [de], a ; y
-	inc de
-rept SPRITEOAMSTRUCT_LENGTH + -1
-	ld a, [hli]
-	ld [de], a
-	inc de
-endr
-	jr .loop
-; e2e2b (38:6e2b)
-
-.OAM: ; e2e2b
-	dsprite 4, 6, 10, 0, $00, 0
-	dsprite 4, 6, 11, 0, $00, 0
-	dsprite 4, 6, 12, 0, $00, 0
-	dsprite 4, 6, 13, 0, $00, 0
-	dsprite 4, 6, 14, 0, $00, 0
-	dsprite 4, 6, 15, 0, $00, 0
-	dsprite 4, 6, 16, 0, $00, 0
-	dsprite 4, 6, 17, 0, $00, 0
-	dsprite 4, 6, 18, 0, $00, 0
-	dsprite 4, 6, 18, 7, $00, 0
-	dsprite 7, 1, 10, 0, $00, 0 | Y_FLIP
-	dsprite 7, 1, 11, 0, $00, 0 | Y_FLIP
-	dsprite 7, 1, 12, 0, $00, 0 | Y_FLIP
-	dsprite 7, 1, 13, 0, $00, 0 | Y_FLIP
-	dsprite 7, 1, 14, 0, $00, 0 | Y_FLIP
-	dsprite 7, 1, 15, 0, $00, 0 | Y_FLIP
-	dsprite 7, 1, 16, 0, $00, 0 | Y_FLIP
-	dsprite 7, 1, 17, 0, $00, 0 | Y_FLIP
-	dsprite 7, 1, 18, 0, $00, 0 | Y_FLIP
-	dsprite 7, 1, 18, 7, $00, 0 | Y_FLIP
-	dsprite 5, 6,  9, 6, $01, 0
-	dsprite 6, 1,  9, 6, $01, 0 | Y_FLIP
-	dsprite 5, 6, 19, 1, $01, 0 | X_FLIP
-	dsprite 6, 1, 19, 1, $01, 0 | X_FLIP | Y_FLIP
-	db -1
-; e2e8c
-
-BillsPC_UpdateInsertCursor: ; e2e8c
-	ld hl, .OAM
-	ld de, wVirtualOAMSprite00
-.loop
-	ld a, [hl]
-	cp -1
-	ret z
-	ld a, [wBillsPC_CursorPosition]
-	and $7
-	swap a
-	add [hl]
-	inc hl
-	ld [de], a ; y
-	inc de
-rept SPRITEOAMSTRUCT_LENGTH + -1
-	ld a, [hli]
-	ld [de], a
-	inc de
-endr
-	jr .loop
-; e2eac
-
-.OAM: ; e2eac
-	dsprite 4, 7, 10, 0, $06, 0
-	dsprite 5, 3, 11, 0, $00, 0 | Y_FLIP
-	dsprite 5, 3, 12, 0, $00, 0 | Y_FLIP
-	dsprite 5, 3, 13, 0, $00, 0 | Y_FLIP
-	dsprite 5, 3, 14, 0, $00, 0 | Y_FLIP
-	dsprite 5, 3, 15, 0, $00, 0 | Y_FLIP
-	dsprite 5, 3, 16, 0, $00, 0 | Y_FLIP
-	dsprite 5, 3, 17, 0, $00, 0 | Y_FLIP
-	dsprite 5, 3, 18, 0, $00, 0 | Y_FLIP
-	dsprite 4, 7, 19, 0, $07, 0
-	db -1
-; e2ed5
-
-Unreferenced_BillsPC_FillBox: ; e2ed5
-.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
-; e2ee5
-
-BillsPC_CheckSpaceInDestination: ; e2ee5
-; If moving within a box, no need to be here.
-	ld hl, wBillsPC_LoadedBox
-	ld a, [wBillsPC_BackupLoadedBox]
-	cp [hl]
-	jr z, .same_box
-
-; Exceeding box or party capacity is a big no-no.
-	ld a, [wBillsPC_LoadedBox]
-	and a
-	jr z, .party
-	ld e, MONS_PER_BOX + 1
-	jr .compare
-
-.party
-	ld e, PARTY_LENGTH + 1
-.compare
-	ld a, [wBillsPC_NumMonsInBox]
-	cp e
-	jr nc, .no_room
-.same_box
-	and a
-	ret
-
-.no_room
-	ld de, PCString_TheresNoRoom
-	call BillsPC_PlaceString
-	ld de, SFX_WRONG
-	call WaitPlaySFX
-	call WaitSFX
-	ld c, 50
-	call DelayFrames
-	scf
-	ret
-; e2f18
-
-BillsPC_CheckMail_PreventBlackout: ; e2f18 (38:6f18)
-	ld a, [wBillsPC_LoadedBox]
-	and a
-	jr nz, .Okay
-	ld a, [wBillsPC_NumMonsInBox]
-	cp $3
-	jr c, .ItsYourLastPokemon
-	ld a, [wBillsPC_CursorPosition]
-	ld hl, wBillsPC_ScrollPosition
-	add [hl]
-	ld [wCurPartyMon], a
-	farcall CheckCurPartyMonFainted
-	jr c, .AllOthersFainted
-	ld a, [wBillsPC_MonHasMail]
-	and a
-	jr nz, .HasMail
-.Okay:
-	and a
-	ret
-
-.HasMail:
-	ld de, PCString_RemoveMail
-	jr .NotOkay
-
-.AllOthersFainted:
-	ld de, PCString_NoMoreUsablePKMN
-	jr .NotOkay
-
-.ItsYourLastPokemon:
-	ld de, PCString_ItsYourLastPKMN
-.NotOkay:
-	call BillsPC_PlaceString
-	ld de, SFX_WRONG
-	call WaitPlaySFX
-	call WaitSFX
-	ld c, 50
-	call DelayFrames
-	scf
-	ret
-
-BillsPC_IsMonAnEgg: ; e2f5f (38:6f5f)
-	ld a, [wCurPartySpecies]
-	cp EGG
-	jr z, .egg
-	and a
-	ret
-
-.egg
-	ld de, PCString_NoReleasingEGGS
-	call BillsPC_PlaceString
-	ld de, SFX_WRONG
-	call WaitPlaySFX
-	call WaitSFX
-	ld c, 50
-	call DelayFrames
-	scf
-	ret
-
-BillsPC_StatsScreen: ; e2f7e (38:6f7e)
-	call LowVolume
-	call BillsPC_CopyMon
-	ld a, $3
-	ld [wMonType], a
-	predef StatsScreenInit
-	call BillsPC_InitGFX
-	call MaxVolume
-	ret
-
-StatsScreenDPad: ; e2f95 (38:6f95)
-	ld hl, hJoyPressed ; $ffa7
-	ld a, [hl]
-	and A_BUTTON | B_BUTTON | D_RIGHT | D_LEFT
-	ld [wMenuJoypad], a
-	jr nz, .pressed_a_b_right_left
-	ld a, [hl]
-	and D_DOWN | D_UP
-	ld [wMenuJoypad], a
-	jr nz, .pressed_down_up
-	jr .pressed_a_b_right_left
-
-.pressed_down_up
-	call _StatsScreenDPad
-	and a
-	jr z, .did_nothing
-	call BillsPC_GetSelectedPokemonSpecies
-	ld [wd265], a
-	call BillsPC_LoadMonStats
-	ld a, [wd265]
-	ld [wCurPartySpecies], a
-	ld [wCurSpecies], a
-	ld hl, wTempMonDVs
-	predef GetUnownLetter
-	call GetBaseData
-	call BillsPC_CopyMon
-.pressed_a_b_right_left
-	ret
-
-.did_nothing
-	xor a
-	ld [wMenuJoypad], a
-	ret
-
-BillsPC_CopyMon: ; e2fd6 (38:6fd6)
-	ld a, [wBillsPC_CursorPosition]
-	ld hl, wBillsPC_ScrollPosition
-	add [hl]
-	ld [wCurPartyMon], a
-	ld a, [wBillsPC_LoadedBox]
-	and a
-	jr z, .party
-	cp NUM_BOXES + 1
-	jr nz, .box
-	ld a, BANK(sBox)
-	call GetSRAMBank
-	ld hl, sBoxSpecies
-	call CopySpeciesToTemp
-	ld hl, sBoxMonNicknames
-	call CopyNicknameToTemp
-	ld hl, sBoxMonOT
-	call CopyOTNameToTemp
-	ld hl, sBoxMons
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld de, wBufferMon
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call CopyBytes
-	call CloseSRAM
-	farcall CalcBufferMonStats
-	ret
-
-.party
-	ld hl, wPartySpecies
-	call CopySpeciesToTemp
-	ld hl, wPartyMonNicknames
-	call CopyNicknameToTemp
-	ld hl, wPartyMonOT
-	call CopyOTNameToTemp
-	ld hl, wPartyMon1
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld de, wBufferMon
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call CopyBytes
-	ret
-
-.box
-	ld b, a
-	call GetBoxPointer
-	ld a, b
-	call GetSRAMBank
-	push hl
-	inc hl
-	call CopySpeciesToTemp
-	pop hl
-	push hl
-	ld bc, sBoxMonNicknames - sBox
-	add hl, bc
-	call CopyNicknameToTemp
-	pop hl
-	push hl
-	ld bc, sBoxMonOT - sBox
-	add hl, bc
-	call CopyOTNameToTemp
-	pop hl
-	ld bc, sBoxMons - sBox
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	call CopyMonToTemp
-	call CloseSRAM
-	farcall CalcBufferMonStats
-	ret
-
-DepositPokemon: ; e307c (38:707c)
-	ld a, [wBillsPC_CursorPosition]
-	ld hl, wBillsPC_ScrollPosition
-	add [hl]
-	ld [wCurPartyMon], a
-	ld hl, wPartyMonNicknames
-	ld a, [wCurPartyMon]
-	call GetNick
-	ld a, PC_DEPOSIT
-	ld [wPokemonWithdrawDepositParameter], a
-	predef SendGetMonIntoFromBox
-	jr c, .asm_boxisfull
-	xor a ; REMOVE_PARTY
-	ld [wPokemonWithdrawDepositParameter], a
-	farcall RemoveMonFromPartyOrBox
-	ld a, [wCurPartySpecies]
-	call PlayMonCry
-	hlcoord 0, 0
-	lb bc, 15, 8
-	call ClearBox
-	hlcoord 8, 14
-	lb bc, 1, 3
-	call ClearBox
-	hlcoord 0, 15
-	lb bc, 1, 18
-	call TextBox
-	call WaitBGMap
-	hlcoord 1, 16
-	ld de, PCString_Stored
-	call PlaceString
-	ld l, c
-	ld h, b
-	ld de, wStringBuffer1
-	call PlaceString
-	ld a, "!"
-	ld [bc], a
-	ld c, 50
-	call DelayFrames
-	and a
-	ret
-
-.asm_boxisfull
-	ld de, PCString_BoxFull
-	call BillsPC_PlaceString
-	ld de, SFX_WRONG
-	call WaitPlaySFX
-	call WaitSFX
-	ld c, 50
-	call DelayFrames
-	scf
-	ret
-
-TryWithdrawPokemon: ; e30fa (38:70fa)
-	ld a, [wBillsPC_CursorPosition]
-	ld hl, wBillsPC_ScrollPosition
-	add [hl]
-	ld [wCurPartyMon], a
-	ld a, BANK(sBoxMonNicknames)
-	call GetSRAMBank
-	ld a, [wCurPartyMon]
-	ld hl, sBoxMonNicknames
-	call GetNick
-	call CloseSRAM
-	xor a
-	ld [wPokemonWithdrawDepositParameter], a
-	predef SendGetMonIntoFromBox
-	jr c, .PartyFull
-	ld a, REMOVE_BOX
-	ld [wPokemonWithdrawDepositParameter], a
-	farcall RemoveMonFromPartyOrBox
-	ld a, [wCurPartySpecies]
-	call PlayMonCry
-	hlcoord 0, 0
-	lb bc, 15, 8
-	call ClearBox
-	hlcoord 8, 14
-	lb bc, 1, 3
-	call ClearBox
-	hlcoord 0, 15
-	lb bc, 1, 18
-	call TextBox
-	call WaitBGMap
-	hlcoord 1, 16
-	ld de, PCString_Got
-	call PlaceString
-	ld l, c
-	ld h, b
-	ld de, wStringBuffer1
-	call PlaceString
-	ld a, $e7
-	ld [bc], a
-	ld c, 50
-	call DelayFrames
-	and a
-	ret
-
-.PartyFull:
-	ld de, PCString_PartyFull
-	call BillsPC_PlaceString
-	ld de, SFX_WRONG
-	call WaitPlaySFX
-	call WaitSFX
-	ld c, 50
-	call DelayFrames
-	scf
-	ret
-
-
-ReleasePKMN_ByePKMN: ; e3180 (38:7180)
-	hlcoord 0, 0
-	lb bc, 15, 8
-	call ClearBox
-	hlcoord 8, 14
-	lb bc, 1, 3
-	call ClearBox
-	hlcoord 0, 15
-	lb bc, 1, 18
-	call TextBox
-
-	call WaitBGMap
-	ld a, [wCurPartySpecies]
-	call GetCryIndex
-	jr c, .skip_cry
-	ld e, c
-	ld d, b
-	call PlayCry
-.skip_cry
-
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	call GetPokemonName
-	hlcoord 1, 16
-	ld de, PCString_ReleasedPKMN
-	call PlaceString
-	ld c, 80
-	call DelayFrames
-	hlcoord 0, 15
-	lb bc, 1, 18
-	call TextBox
-	hlcoord 1, 16
-	ld de, PCString_Bye
-	call PlaceString
-	ld l, c
-	ld h, b
-	inc hl
-	ld de, wStringBuffer1
-	call PlaceString
-	ld l, c
-	ld h, b
-	ld [hl], $e7
-	ld c, 50
-	call DelayFrames
-	ret
-; e31e7 (38:71e7)
-
-MovePKMNWitoutMail_InsertMon: ; e31e7
-	push hl
-	push de
-	push bc
-	push af
-	hlcoord 0, 15
-	lb bc, 1, 18
-	call TextBox
-	hlcoord 1, 16
-	ld de, .Saving_LeaveOn
-	call PlaceString
-	ld c, 20
-	call DelayFrames
-	pop af
-	pop bc
-	pop de
-	pop hl
-	ld a, [wCurBox]
-	push af
-	ld bc, 0
-	ld a, [wBillsPC_BackupLoadedBox]
-	and a
-	jr nz, .moving_from_box
-	set 0, c
-
-.moving_from_box
-	ld a, [wBillsPC_LoadedBox]
-	and a
-	jr nz, .moving_to_box
-	set 1, c
-
-.moving_to_box
-	ld hl, .Jumptable
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, .dw_return
-	push de
-	jp hl
-; e322a
-
-.dw_return ; e322a
-	pop af
-	ld e, a
-	farcall MoveMonWOMail_InsertMon_SaveGame
-	ret
-; e3233
-
-.Saving_LeaveOn:
-	db "Saving… Leave ON!@"
-; e3245
-
-.Jumptable: ; e3245
-	dw .BoxToBox
-	dw .PartyToBox
-	dw .BoxToParty
-	dw .PartyToParty
-; e324d
-
-.BoxToBox: ; e324d
-	ld hl, wBillsPC_BackupLoadedBox
-	ld a, [wBillsPC_LoadedBox]
-	cp [hl]
-	jr z, .same_box
-	call .CopyFromBox
-	call .CopyToBox
-	ret
-
-.same_box
-	call .CopyFromBox
-	call .CheckTrivialMove
-	call .CopyToBox
-	ret
-; e3267
-
-.PartyToBox: ; e3267
-	call .CopyFromParty
-	ld a, $1
-	ld [wGameLogicPaused], a
-	farcall SaveGameData
-	xor a
-	ld [wGameLogicPaused], a
-	call .CopyToBox
-	ret
-; e327d
-
-.BoxToParty: ; e327d
-	call .CopyFromBox
-	call .CopyToParty
-	ret
-; e3284
-
-.PartyToParty: ; e3284
-	call .CopyFromParty
-	call .CheckTrivialMove
-	call .CopyToParty
-	ret
-; e328e
-
-.CheckTrivialMove: ; e328e
-	ld a, [wBillsPC_CursorPosition]
-	ld hl, wBillsPC_ScrollPosition
-	add [hl]
-	ld e, a
-	ld a, [wBillsPC_BackupCursorPosition]
-	ld hl, wBillsPC_BackupScrollPosition
-	add [hl]
-	cp e
-	ret nc
-	ld hl, wBillsPC_CursorPosition
-	ld a, [hl]
-	and a
-	jr z, .top_of_screen
-	dec [hl]
-	ret
-
-.top_of_screen
-	ld hl, wBillsPC_ScrollPosition
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-	ret
-; e32b0
-
-.CopyFromBox: ; e32b0
-	ld a, [wBillsPC_BackupLoadedBox]
-	dec a
-	ld e, a
-	farcall MoveMonWOMail_SaveGame
-	ld a, [wBillsPC_BackupCursorPosition]
-	ld hl, wBillsPC_BackupScrollPosition
-	add [hl]
-	ld [wCurPartyMon], a
-	ld a, BANK(sBox)
-	call GetSRAMBank
-	ld hl, sBoxSpecies
-	call CopySpeciesToTemp
-	ld hl, sBoxMonNicknames
-	call CopyNicknameToTemp
-	ld hl, sBoxMonOT
-	call CopyOTNameToTemp
-	ld hl, sBoxMons
-	ld bc, BOXMON_STRUCT_LENGTH
-	call CopyMonToTemp
-	call CloseSRAM
-	farcall CalcBufferMonStats
-	ld a, REMOVE_BOX
-	ld [wPokemonWithdrawDepositParameter], a
-	farcall RemoveMonFromPartyOrBox
-	ret
-; e32fa
-
-.CopyToBox: ; e32fa
-	ld a, [wBillsPC_LoadedBox]
-	dec a
-	ld e, a
-	farcall MoveMonWOMail_SaveGame
-	ld a, [wBillsPC_CursorPosition]
-	ld hl, wBillsPC_ScrollPosition
-	add [hl]
-	ld [wCurPartyMon], a
-	farcall InsertPokemonIntoBox
-	ret
-; e3316
-
-.CopyFromParty: ; e3316
-	ld a, [wBillsPC_BackupCursorPosition]
-	ld hl, wBillsPC_BackupScrollPosition
-	add [hl]
-	ld [wCurPartyMon], a
-	ld hl, wPartySpecies
-	call CopySpeciesToTemp
-	ld hl, wPartyMonNicknames
-	call CopyNicknameToTemp
-	ld hl, wPartyMonOT
-	call CopyOTNameToTemp
-	ld hl, wPartyMon1Species
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call CopyMonToTemp
-	xor a ; REMOVE_PARTY
-	ld [wPokemonWithdrawDepositParameter], a
-	farcall RemoveMonFromPartyOrBox
-	ret
-; e3346
-
-.CopyToParty: ; e3346
-	ld a, [wBillsPC_CursorPosition]
-	ld hl, wBillsPC_ScrollPosition
-	add [hl]
-	ld [wCurPartyMon], a
-	farcall InsertPokemonIntoParty
-	ret
-; e3357
-
-CopySpeciesToTemp: ; e3357 (38:7357)
-	ld a, [wCurPartyMon]
-	ld c, a
-	ld b, $0
-	add hl, bc
-	ld a, [hl]
-	ld [wCurPartySpecies], a
-	ret
-
-CopyNicknameToTemp: ; e3363 (38:7363)
-	ld bc, MON_NAME_LENGTH
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld de, wBufferMonNick
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-	ret
-
-CopyOTNameToTemp: ; e3376 (38:7376)
-	ld bc, NAME_LENGTH
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld de, wBufferMonOT
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ret
-
-CopyMonToTemp: ; e3389 (38:7389)
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld de, wBufferMon
-	call CopyBytes
-	ret
-
-GetBoxPointer: ; e3396 (38:7396)
-	dec b
-	ld c, b
-	ld b, 0
-	ld hl, .boxes
-	add hl, bc
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld b, a
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ret
-; e33a6 (38:73a6)
-
-.boxes ; e33a6
-	;  bank, address
-	dba sBox1
-	dba sBox2
-	dba sBox3
-	dba sBox4
-	dba sBox5
-	dba sBox6
-	dba sBox7
-	dba sBox8
-	dba sBox9
-	dba sBox10
-	dba sBox11
-	dba sBox12
-	dba sBox13
-	dba sBox14
-; e33d0
-
-BillsPC_ApplyPalettes: ; e33d0 (38:73d0)
-	ld b, a
-	call GetSGBLayout
-	ld a, %11100100
-	call DmgToCgbBGPals
-	ld a, %11111100
-	call DmgToCgbObjPal0
-	ret
-
-BillsPC_Jumptable: ; e33df (38:73df)
-	ld e, a
-	ld d, $0
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ret
-
-BillsPC_InitGFX: ; e33e8 (38:73e8)
-	call DisableLCD
-	ld hl, vTiles2 tile $00
-	ld bc, $31 tiles
-	xor a
-	call ByteFill
-	call LoadStandardFont
-	call LoadFontsBattleExtra
-	ld hl, PCMailGFX
-	ld de, vTiles2 tile $5c
-	ld bc, 4 tiles
-	call CopyBytes
-	ld hl, PCSelectLZ
-	ld de, vTiles0 tile $00
-	call Decompress
-	ld a, 6
-	call SkipMusic
-	call EnableLCD
-	ret
-; e3419 (38:7419)
-
-PCSelectLZ: INCBIN "gfx/pc/pc.2bpp.lz"
-PCMailGFX:  INCBIN "gfx/pc/pc_mail.2bpp"
-; e34dd
-
-PCString_ChooseaPKMN: db "Choose a <PK><MN>.@"
-PCString_WhatsUp: db "What's up?@"
-PCString_ReleasePKMN: db "Release <PK><MN>?@"
-PCString_MoveToWhere: db "Move to where?@"
-PCString_ItsYourLastPKMN: db "It's your last <PK><MN>!@"
-PCString_TheresNoRoom: db "There's no room!@"
-PCString_NoMoreUsablePKMN: db "No more usable <PK><MN>!@"
-PCString_RemoveMail: db "Remove MAIL.@"
-PCString_ReleasedPKMN: db "Released <PK><MN>.@"
-PCString_Bye: db "Bye,@"
-PCString_Stored: db "Stored @"
-PCString_Got: db "Got @"
-PCString_Non: db "Non.@"
-PCString_BoxFull: db "The BOX is full.@"
-PCString_PartyFull: db "The party's full!@"
-PCString_NoReleasingEGGS: db "No releasing EGGS!@"
-; e35aa
-
-
-_ChangeBox: ; e35aa (38:75aa)
-	call LoadStandardMenuHeader
-	call BillsPC_ClearTilemap
-.loop
-	xor a
-	ld [hBGMapMode], a
-	call BillsPC_PrintBoxName
-	call BillsPC_PlaceChooseABoxString
-	ld hl, _ChangeBox_MenuHeader
-	call CopyMenuHeader
-	xor a
-	ld [wMenuScrollPosition], a
-	hlcoord 0, 4
-	lb bc, 8, 9
-	call TextBox
-	call ScrollingMenu
-	ld a, [wMenuJoypad]
-	cp B_BUTTON
-	jr z, .done
-	call BillsPC_PlaceWhatsUpString
-	call BillsPC_ChangeBoxSubmenu
-	jr .loop
-.done
-	call CloseWindow
-	ret
-
-BillsPC_ClearTilemap: ; e35e2 (38:75e2)
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, " "
-	call ByteFill
-	ret
-; e35f1 (38:75f1)
-
-_ChangeBox_MenuHeader: ; 0xe35f1
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 1, 5, 9, 12
-	dw .MenuData
-	db 1 ; default option
-; 0xe35f9
-
-.MenuData ; 0xe35f9
-	db MENU_UNUSED_1 | MENU_UNUSED_3 ; flags
-	db 4, 0
-	db 1
-	dba .boxes
-	dba .boxnames
-	dba NULL
-	dba BillsPC_PrintBoxCountAndCapacity
-; e3609
-
-.boxes ; e3609
-	db NUM_BOXES
-x = 1
-rept NUM_BOXES
-	db x
-x = x + 1
-endr
-	db -1
-; e3619
-
-.boxnames ; e3619
-	push de
-	ld a, [wMenuSelection]
-	dec a
-	call GetBoxName
-	pop hl
-	call PlaceString
-	ret
-; e3626
-
-GetBoxName: ; e3626 (38:7626)
-	ld bc, BOX_NAME_LENGTH
-	ld hl, wBoxNames
-	call AddNTimes
-	ld d, h
-	ld e, l
-	ret
-; e3632 (38:7632)
-
-BillsPC_PrintBoxCountAndCapacity: ; e3632
-	hlcoord 11, 7
-	lb bc, 5, 7
-	call TextBox
-	ld a, [wMenuSelection]
-	cp -1
-	ret z
-	hlcoord 12, 9
-	ld de, .Pokemon
-	call PlaceString
-	call GetBoxCount
-	ld [wd265], a
-	hlcoord 13, 11
-	ld de, wd265
-	lb bc, 1, 2
-	call PrintNum
-	ld de, .out_of_20
-	call PlaceString
-	ret
-; e3663
-
-.Pokemon: ; e3663
-	db "#MON@"
-; e3668
-
-.out_of_20 ; e3668
-	; db "/20@"
-	db "/"
-	db "0" + MONS_PER_BOX / 10 ; "2"
-	db "0" + MONS_PER_BOX % 10 ; "0"
-	db "@"
-; e366c
-
-GetBoxCount: ; e366c (38:766c)
-	ld a, [wCurBox]
-	ld c, a
-	ld a, [wMenuSelection]
-	dec a
-	cp c
-	jr z, .activebox
-	ld c, a
-	ld b, 0
-	ld hl, .boxbanks
-	add hl, bc
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld b, a
-	call GetSRAMBank
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [hl]
-	call CloseSRAM
-	ld c, a
-	ld a, [wSavedAtLeastOnce]
-	and a
-	jr z, .newfile
-	ld a, c
-	ret
-
-.newfile
-	xor a
-	ret
-
-.activebox
-	ld a, BANK(sBoxCount)
-	ld b, a
-	call GetSRAMBank
-	ld hl, sBoxCount
-	ld a, [hl]
-	call CloseSRAM
-	ret
-; e36a5 (38:76a5)
-
-.boxbanks ; e36a5
-	dba sBox1
-	dba sBox2
-	dba sBox3
-	dba sBox4
-	dba sBox5
-	dba sBox6
-	dba sBox7
-	dba sBox8
-	dba sBox9
-	dba sBox10
-	dba sBox11
-	dba sBox12
-	dba sBox13
-	dba sBox14
-; e36cf
-
-BillsPC_PrintBoxName: ; e36cf (38:76cf)
-	hlcoord 0, 0
-	ld b, 2
-	ld c, 18
-	call TextBox
-	hlcoord 1, 2
-	ld de, .Current
-	call PlaceString
-	ld a, [wCurBox]
-	and $f
-	call GetBoxName
-	hlcoord 11, 2
-	call PlaceString
-	ret
-; e36f1 (38:76f1)
-
-.Current: ; e36f1
-	db "CURRENT@"
-; e36f9
-
-BillsPC_ChangeBoxSubmenu: ; e36f9 (38:76f9)
-	ld hl, .MenuHeader
-	call LoadMenuHeader
-	call VerticalMenu
-	call ExitMenu
-	ret c
-	ld a, [wMenuCursorY]
-	cp $1
-	jr z, .Switch
-	cp $2
-	jr z, .Name
-	cp $3
-	jr z, .Print
-	and a
-	ret
-
-.Print:
-	call GetBoxCount
-	and a
-	jr z, .EmptyBox
-	ld e, l
-	ld d, h
-	ld a, [wMenuSelection]
-	dec a
-	ld c, a
-	farcall PrintPCBox
-	call BillsPC_ClearTilemap
-	and a
-	ret
-
-.EmptyBox:
-	call BillsPC_PlaceEmptyBoxString_SFX
-	and a
-	ret
-
-.Switch:
-	ld a, [wMenuSelection]
-	dec a
-	ld e, a
-	ld a, [wCurBox]
-	cp e
-	ret z
-	farcall ChangeBoxSaveGame
-	ret
-
-.Name:
-	ld b, $4 ; box
-	ld de, wd002
-	farcall NamingScreen
-	call ClearTileMap
-	call LoadStandardFont
-	call LoadFontsBattleExtra
-	ld a, [wMenuSelection]
-	dec a
-	call GetBoxName
-	ld e, l
-	ld d, h
-	ld hl, wd002
-	ld c, BOX_NAME_LENGTH - 1
-	call InitString
-	ld a, [wMenuSelection]
-	dec a
-	call GetBoxName
-	ld de, wd002
-	call CopyName2
-	ret
-; e3778 (38:7778)
-
-	hlcoord 11, 7 ; unused
-
-.MenuHeader: ; 0xe377b
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 11, 4, SCREEN_WIDTH - 1, 13
-	dw .MenuData
-	db 1 ; default option
-; 0xe3783
-
-.MenuData: ; 0xe3783
-	db STATICMENU_CURSOR ; flags
-	db 4 ; items
-	db "SWITCH@"
-	db "NAME@"
-	db "PRINT@"
-	db "QUIT@"
-; 0xe379c
-
-BillsPC_PlaceChooseABoxString: ; e379c (38:779c)
-	ld de, .ChooseABox
-	jr BillsPC_PlaceChangeBoxString
-; e37a1 (38:77a1)
-
-.ChooseABox: ; e37a1
-	db "Choose a BOX.@"
-; e37af
-
-BillsPC_PlaceWhatsUpString: ; e37af (38:77af)
-	ld de, .WhatsUp
-	jr BillsPC_PlaceChangeBoxString
-; e37b4 (38:77b4)
-
-.WhatsUp: ; e37b4
-	db "What's up?@"
-; e37be
-
-BillsPC_PlaceEmptyBoxString_SFX: ; e37be (38:77be)
-	ld de, .NoMonString
-	call BillsPC_PlaceChangeBoxString
-	ld de, SFX_WRONG
-	call WaitPlaySFX
-	call WaitSFX
-	ld c, 50
-	call DelayFrames
-	ret
-; e37d3 (38:77d3)
-
-.NoMonString: ; e37d3
-	db "There's no #MON.@"
-; e37e3
-
-BillsPC_PlaceChangeBoxString: ; e37e3 (38:77e3)
-	push de
-	hlcoord 0, 14
-	lb bc, 2, 18
-	call TextBox
-	pop de
-	hlcoord 1, 16
-	call PlaceString
-	ld a, $1
-	ld [hBGMapMode], a
-	ret
--- a/engine/billspctop.asm
+++ /dev/null
@@ -1,387 +1,0 @@
-_BillsPC: ; e3fd
-	call .CheckCanUsePC
-	ret c
-	call .LogIn
-	call .UseBillsPC
-	jp .LogOut
-
-.CheckCanUsePC: ; e40a (3:640a)
-	ld a, [wPartyCount]
-	and a
-	ret nz
-	ld hl, .Text_GottaHavePokemon
-	call MenuTextBoxBackup
-	scf
-	ret
-
-.Text_GottaHavePokemon: ; 0xe417
-	; You gotta have #MON to call!
-	text_jump UnknownText_0x1c1006
-	db "@"
-
-.LogIn: ; e41c (3:641c)
-	xor a
-	ld [hBGMapMode], a
-	call LoadStandardMenuHeader
-	call ClearPCItemScreen
-	ld hl, wOptions
-	ld a, [hl]
-	push af
-	set NO_TEXT_SCROLL, [hl]
-	ld hl, .Text_What
-	call PrintText
-	pop af
-	ld [wOptions], a
-	call LoadFontsBattleExtra
-	ret
-
-.Text_What: ; 0xe43a
-	; What?
-	text_jump UnknownText_0x1c1024
-	db "@"
-
-.LogOut: ; e43f (3:643f)
-	call CloseSubmenu
-	ret
-
-.UseBillsPC: ; e443 (3:6443)
-	ld hl, .MenuHeader
-	call LoadMenuHeader
-	ld a, $1
-.loop
-	ld [wMenuCursorBuffer], a
-	call SetPalettes
-	xor a
-	ld [wWhichIndexSet], a
-	ld [hBGMapMode], a
-	call DoNthMenu
-	jr c, .cancel
-	ld a, [wMenuCursorBuffer]
-	push af
-	ld a, [wMenuSelection]
-	ld hl, .Jumptable
-	rst JumpTable
-	pop bc
-	ld a, b
-	jr nc, .loop
-.cancel
-	call CloseWindow
-	ret
-
-.MenuHeader: ; 0xe46f
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
-	dw .MenuData
-	db 1 ; default option
-
-.MenuData: ; 0xe477
-	db STATICMENU_CURSOR ; flags
-	db 0 ; items
-	dw .items
-	dw PlaceMenuStrings
-	dw .strings
-
-.strings ; e47f
-	db "WITHDRAW <PK><MN>@"
-	db "DEPOSIT <PK><MN>@"
-	db "CHANGE BOX@"
-	db "MOVE <PK><MN> W/O MAIL@"
-	db "SEE YA!@"
-
-.Jumptable: ; e4ba (3:64ba)
-	dw BillsPC_WithdrawMenu
-	dw BillsPC_DepositMenu
-	dw BillsPC_ChangeBoxMenu
-	dw BillsPC_MovePKMNMenu
-	dw BillsPC_SeeYa
-
-.items ; e4c4
-	db 5
-	db 0 ; WITHDRAW
-	db 1;  DEPOSIT
-	db 2 ; CHANGE BOX
-	db 3 ; MOVE PKMN
-	db 4 ; SEE YA!
-	db -1
-
-BillsPC_SeeYa: ; e4cb
-	scf
-	ret
-
-BillsPC_MovePKMNMenu: ; e4cd
-	call LoadStandardMenuHeader
-	farcall IsAnyMonHoldingMail
-	jr nc, .no_mail
-	ld hl, .Text_MonHoldingMail
-	call PrintText
-	jr .quit
-
-.no_mail
-	farcall StartMoveMonWOMail_SaveGame
-	jr c, .quit
-	farcall _MovePKMNWithoutMail
-	call ReturnToMapFromSubmenu
-	call ClearPCItemScreen
-
-.quit
-	call CloseWindow
-	and a
-	ret
-
-.Text_MonHoldingMail: ; 0xe4f9
-	; There is a #MON holding MAIL. Please remove the MAIL.
-	text_jump UnknownText_0x1c102b
-	db "@"
-
-BillsPC_DepositMenu: ; e4fe (3:64fe)
-	call LoadStandardMenuHeader
-	farcall _DepositPKMN
-	call ReturnToMapFromSubmenu
-	call ClearPCItemScreen
-	call CloseWindow
-	and a
-	ret
-
-Unreferenced_Functione512:
-	ld a, [wPartyCount]
-	and a
-	jr z, .no_mon
-	cp 2
-	jr c, .only_one_mon
-	and a
-	ret
-
-.no_mon
-	ld hl, .Text_NoMon
-	call MenuTextBoxBackup
-	scf
-	ret
-
-.only_one_mon
-	ld hl, .Text_ItsYourLastMon
-	call MenuTextBoxBackup
-	scf
-	ret
-
-.Text_NoMon: ; 0xe52e
-	; You don't have a single #MON!
-	text_jump UnknownText_0x1c1062
-	db "@"
-
-.Text_ItsYourLastMon: ; 0xe533
-	; You can't deposit your last #MON!
-	text_jump UnknownText_0x1c1080
-	db "@"
-
-CheckCurPartyMonFainted: ; e538
-	ld hl, wPartyMon1HP
-	ld de, PARTYMON_STRUCT_LENGTH
-	ld b, $0
-.loop
-	ld a, [wCurPartyMon]
-	cp b
-	jr z, .skip
-	ld a, [hli]
-	or [hl]
-	jr nz, .notfainted
-	dec hl
-
-.skip
-	inc b
-	ld a, [wPartyCount]
-	cp b
-	jr z, .done
-	add hl, de
-	jr .loop
-
-.done
-	scf
-	ret
-
-.notfainted
-	and a
-	ret
-
-BillsPC_WithdrawMenu: ; e559 (3:6559)
-	call LoadStandardMenuHeader
-	farcall _WithdrawPKMN
-	call ReturnToMapFromSubmenu
-	call ClearPCItemScreen
-	call CloseWindow
-	and a
-	ret
-
-Unreferenced_Functione56d:
-	ld a, [wPartyCount]
-	cp PARTY_LENGTH
-	jr nc, .asm_e576
-	and a
-	ret
-
-.asm_e576
-	ld hl, UnknownText_0xe57e
-	call MenuTextBoxBackup
-	scf
-	ret
-
-UnknownText_0xe57e: ; 0xe57e
-	; You can't take any more #MON.
-	text_jump UnknownText_0x1c10a2
-	db "@"
-
-BillsPC_ChangeBoxMenu: ; e583 (3:6583)
-	farcall _ChangeBox
-	and a
-	ret
-
-ClearPCItemScreen: ; e58b
-	call DisableSpriteUpdates
-	xor a
-	ld [hBGMapMode], a
-	call ClearBGPalettes
-	call ClearSprites
-	hlcoord 0, 0
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	ld a, " "
-	call ByteFill
-	hlcoord 0, 0
-	lb bc, 10, 18
-	call TextBox
-	hlcoord 0, 12
-	lb bc, 4, 18
-	call TextBox
-	call WaitBGMap2
-	call SetPalettes ; load regular palettes?
-	ret
-
-CopyBoxmonToTempMon: ; e5bb
-	ld a, [wCurPartyMon]
-	ld hl, sBoxMon1Species
-	ld bc, BOXMON_STRUCT_LENGTH
-	call AddNTimes
-	ld de, wTempMonSpecies
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, BANK(sBoxMon1Species)
-	call GetSRAMBank
-	call CopyBytes
-	call CloseSRAM
-	ret
-
-Unreferenced_Functione5d9:
-	ld a, [wCurBox]
-	cp b
-	jr z, .same_box
-	ld a, b
-	ld hl, .BoxAddrs
-	ld bc, 3
-	call AddNTimes
-	ld a, [hli]
-	push af
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	pop af
-	jr .okay
-
-.same_box
-	ld a, BANK(sBoxCount)
-	ld hl, sBoxCount
-
-.okay
-	call GetSRAMBank
-	ld a, [hl]
-	ld bc, 1 + MONS_PER_BOX + 1
-	add hl, bc
-	ld b, a
-	ld c, $0
-	ld de, wc608
-	ld a, b
-	and a
-	jr z, .empty_box
-.loop
-	push hl
-	push bc
-	ld a, c
-	ld bc, 0
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [hl]
-	ld [de], a
-	inc de
-	ld [wCurSpecies], a
-	call GetBaseData
-	pop bc
-	pop hl
-
-	push hl
-	push bc
-	ld a, c
-	ld bc, MONS_PER_BOX * (BOXMON_STRUCT_LENGTH + NAME_LENGTH)
-	add hl, bc
-	call SkipNames
-	call CopyBytes
-	pop bc
-	pop hl
-
-	push hl
-	push bc
-	ld a, c
-	ld bc, MON_LEVEL
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [hl]
-	ld [de], a
-	inc de
-	pop bc
-	pop hl
-
-	push hl
-	push bc
-	ld a, c
-	ld bc, MON_DVS
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [hli]
-	and $f0
-	ld b, a
-	ld a, [hl]
-	and $f0
-	swap a
-	or b
-	ld b, a
-	ld a, [wBaseGender]
-	cp b
-	ld a, $1
-	jr c, .okay2
-	xor a
-.okay2
-	ld [de], a
-	inc de
-	pop bc
-	pop hl
-
-	inc c
-	dec b
-	jr nz, .loop
-.empty_box
-	call CloseSRAM
-	ret
-
-.BoxAddrs: ; e66e
-	dba sBox1
-	dba sBox2
-	dba sBox3
-	dba sBox4
-	dba sBox5
-	dba sBox6
-	dba sBox7
-	dba sBox8
-	dba sBox9
-	dba sBox10
-	dba sBox11
-	dba sBox12
-	dba sBox13
-	dba sBox14
--- a/engine/breeding.asm
+++ /dev/null
@@ -1,994 +1,0 @@
-CheckBreedmonCompatibility: ; 16e1d
-	call .CheckBreedingGroupCompatibility
-	ld c, $0
-	jp nc, .done
-	ld a, [wBreedMon1Species]
-	ld [wCurPartySpecies], a
-	ld a, [wBreedMon1DVs]
-	ld [wTempMonDVs], a
-	ld a, [wBreedMon1DVs + 1]
-	ld [wTempMonDVs + 1], a
-	ld a, TEMPMON
-	ld [wMonType], a
-	predef GetGender
-	jr c, .genderless
-	ld b, $1
-	jr nz, .breedmon2
-	inc b
-
-.breedmon2
-	push bc
-	ld a, [wBreedMon2Species]
-	ld [wCurPartySpecies], a
-	ld a, [wBreedMon2DVs]
-	ld [wTempMonDVs], a
-	ld a, [wBreedMon2DVs + 1]
-	ld [wTempMonDVs + 1], a
-	ld a, $3
-	ld [wMonType], a
-	predef GetGender
-	pop bc
-	jr c, .genderless
-	ld a, $1
-	jr nz, .compare_gender
-	inc a
-
-.compare_gender
-	cp b
-	jr nz, .compute
-
-.genderless
-	ld c, $0
-	ld a, [wBreedMon1Species]
-	cp DITTO
-	jr z, .ditto1
-	ld a, [wBreedMon2Species]
-	cp DITTO
-	jr nz, .done
-	jr .compute
-
-.ditto1
-	ld a, [wBreedMon2Species]
-	cp DITTO
-	jr z, .done
-
-.compute
-	call .CheckDVs
-	ld c, 255
-	jp z, .done
-	ld a, [wBreedMon2Species]
-	ld b, a
-	ld a, [wBreedMon1Species]
-	cp b
-	ld c, 254
-	jr z, .compare_ids
-	ld c, 128
-.compare_ids
-	; Speed up
-	ld a, [wBreedMon1ID]
-	ld b, a
-	ld a, [wBreedMon2ID]
-	cp b
-	jr nz, .done
-	ld a, [wBreedMon1ID + 1]
-	ld b, a
-	ld a, [wBreedMon2ID + 1]
-	cp b
-	jr nz, .done
-	ld a, c
-	sub 77
-	ld c, a
-
-.done
-	ld a, c
-	ld [wd265], a
-	ret
-; 16ebc
-
-
-.CheckDVs: ; 16ebc (5:6ebc)
-; If Defense DVs match and the lower 3 bits of the Special DVs match,
-; avoid breeding
-	ld a, [wBreedMon1DVs]
-	and %1111
-	ld b, a
-	ld a, [wBreedMon2DVs]
-	and %1111
-	cp b
-	ret nz
-	ld a, [wBreedMon1DVs + 1]
-	and %111
-	ld b, a
-	ld a, [wBreedMon2DVs + 1]
-	and %111
-	cp b
-	ret
-; 16ed6
-
-.CheckBreedingGroupCompatibility: ; 16ed6
-; If either mon is in the No Eggs group,
-; they are not compatible.
-	ld a, [wBreedMon2Species]
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld a, [wBaseEggGroups]
-	cp EGG_NONE * $11
-	jr z, .Incompatible
-
-	ld a, [wBreedMon1Species]
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld a, [wBaseEggGroups]
-	cp EGG_NONE * $11
-	jr z, .Incompatible
-
-; Ditto is automatically compatible with everything.
-; If not Ditto, load the breeding groups into b/c and d/e.
-	ld a, [wBreedMon2Species]
-	cp DITTO
-	jr z, .Compatible
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld a, [wBaseEggGroups]
-	push af
-	and $f
-	ld b, a
-	pop af
-	and $f0
-	swap a
-	ld c, a
-
-	ld a, [wBreedMon1Species]
-	cp DITTO
-	jr z, .Compatible
-	ld [wCurSpecies], a
-	push bc
-	call GetBaseData
-	pop bc
-	ld a, [wBaseEggGroups]
-	push af
-	and $f
-	ld d, a
-	pop af
-	and $f0
-	swap a
-	ld e, a
-
-	ld a, d
-	cp b
-	jr z, .Compatible
-	cp c
-	jr z, .Compatible
-
-	ld a, e
-	cp b
-	jr z, .Compatible
-	cp c
-	jr z, .Compatible
-
-.Incompatible:
-	and a
-	ret
-
-.Compatible:
-	scf
-	ret
-; 16f3e
-
-DoEggStep:: ; 16f3e
-	ld de, wPartySpecies
-	ld hl, wPartyMon1Happiness
-	ld c, 0
-.loop
-	ld a, [de]
-	inc de
-	cp -1
-	ret z
-	cp EGG
-	jr nz, .next
-	dec [hl]
-	jr nz, .next
-	ld a, 1
-	and a
-	ret
-
-.next
-	push de
-	ld de, PARTYMON_STRUCT_LENGTH
-	add hl, de
-	pop de
-	jr .loop
-; 16f5e
-
-OverworldHatchEgg:: ; 16f5e
-	call RefreshScreen
-	call LoadStandardMenuHeader
-	call HatchEggs
-	call ExitAllMenus
-	call RestartMapMusic
-	jp CloseText
-; 16f70
-
-HatchEggs: ; 16f70 (5:6f70)
-	ld de, wPartySpecies
-	ld hl, wPartyMon1Happiness
-	xor a
-	ld [wCurPartyMon], a
-
-.loop ; 16f7a (5:6f7a)
-	ld a, [de]
-	inc de
-	cp -1
-	jp z, .done
-	push de
-	push hl
-	cp EGG
-	jp nz, .next
-	ld a, [hl]
-	and a
-	jp nz, .next
-	ld [hl], $78
-
-	push de
-
-	farcall SetEggMonCaughtData
-	farcall StubbedTrainerRankings_EggsHatched
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1Species
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [hl]
-	ld [wCurPartySpecies], a
-	dec a
-	call SetSeenAndCaughtMon
-
-	ld a, [wCurPartySpecies]
-	cp TOGEPI
-	jr nz, .nottogepi
-	; set the event flag for hatching togepi
-	ld de, EVENT_TOGEPI_HATCHED
-	ld b, SET_FLAG
-	call EventFlagAction
-.nottogepi
-
-	pop de
-
-	ld a, [wCurPartySpecies]
-	dec de
-	ld [de], a
-	ld [wd265], a
-	ld [wCurSpecies], a
-	call GetPokemonName
-	xor a
-	ld [wd26b], a
-	call GetBaseData
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	push hl
-	ld bc, MON_MAXHP
-	add hl, bc
-	ld d, h
-	ld e, l
-	pop hl
-	push hl
-	ld bc, MON_LEVEL
-	add hl, bc
-	ld a, [hl]
-	ld [wCurPartyLevel], a
-	pop hl
-	push hl
-	ld bc, MON_STATUS
-	add hl, bc
-	xor a
-	ld [hli], a
-	ld [hl], a
-	pop hl
-	push hl
-	ld bc, MON_STAT_EXP - 1
-	add hl, bc
-	ld b, FALSE
-	predef CalcMonStats
-	pop bc
-	ld hl, MON_MAXHP
-	add hl, bc
-	ld d, h
-	ld e, l
-	ld hl, MON_HP
-	add hl, bc
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	ld [hl], a
-	ld hl, MON_ID
-	add hl, bc
-	ld a, [wPlayerID]
-	ld [hli], a
-	ld a, [wPlayerID + 1]
-	ld [hl], a
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMonOT
-	ld bc, NAME_LENGTH
-	call AddNTimes
-	ld d, h
-	ld e, l
-	ld hl, wPlayerName
-	call CopyBytes
-	ld hl, .Text_HatchEgg
-	call PrintText
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMonNicknames
-	ld bc, MON_NAME_LENGTH
-	call AddNTimes
-	ld d, h
-	ld e, l
-	push de
-	ld hl, .Text_NicknameHatchling
-	call PrintText
-	call YesNoBox
-	pop de
-	jr c, .nonickname
-
-	ld a, $1
-	ld [wd26b], a
-	xor a
-	ld [wMonType], a
-	push de
-	ld b, $0
-	farcall NamingScreen
-	pop hl
-	ld de, wStringBuffer1
-	call InitName
-	jr .next
-
-.nonickname
-	ld hl, wStringBuffer1
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-
-.next ; 1707d (5:707d)
-	ld hl, wCurPartyMon
-	inc [hl]
-	pop hl
-	ld de, PARTYMON_STRUCT_LENGTH
-	add hl, de
-	pop de
-	jp .loop
-
-.done ; 1708a (5:708a)
-	ret
-; 1708b (5:708b)
-
-.Text_HatchEgg: ; 0x1708b
-	; Huh? @ @
-	text_jump UnknownText_0x1c0db0
-	start_asm
-	ld hl, wVramState
-	res 0, [hl]
-	push hl
-	push de
-	push bc
-	ld a, [wCurPartySpecies]
-	push af
-	call EggHatch_AnimationSequence
-	ld hl, .ClearTextbox
-	call PrintText
-	pop af
-	ld [wCurPartySpecies], a
-	pop bc
-	pop de
-	pop hl
-	ld hl, .CameOutOfItsEgg
-	ret
-; 170b0 (5:70b0)
-
-.ClearTextbox: ; 0x170b0
-	;
-	text_jump UnknownText_0x1c0db8
-	db "@"
-; 0x170b5
-
-.CameOutOfItsEgg: ; 0x170b5
-	; came out of its EGG!@ @
-	text_jump UnknownText_0x1c0dba
-	db "@"
-; 0x170ba
-
-.Text_NicknameHatchling: ; 0x170ba
-	; Give a nickname to @ ?
-	text_jump UnknownText_0x1c0dd8
-	db "@"
-; 0x170bf
-
-InitEggMoves: ; 170bf
-	call GetHeritableMoves
-	ld d, h
-	ld e, l
-	ld b, NUM_MOVES
-.loop
-	ld a, [de]
-	and a
-	jr z, .done
-	ld hl, wEggMonMoves
-	ld c, NUM_MOVES
-.next
-	ld a, [de]
-	cp [hl]
-	jr z, .skip
-	inc hl
-	dec c
-	jr nz, .next
-	call GetEggMove
-	jr nc, .skip
-	call LoadEggMove
-
-.skip
-	inc de
-	dec b
-	jr nz, .loop
-
-.done
-	ret
-; 170e4
-
-GetEggMove: ; 170e4
-	push bc
-	ld a, [wEggMonSpecies]
-	dec a
-	ld c, a
-	ld b, 0
-	ld hl, EggMovePointers
-	add hl, bc
-	add hl, bc
-	ld a, BANK(EggMovePointers)
-	call GetFarHalfword
-.loop
-	ld a, BANK(EggMoves)
-	call GetFarByte
-	cp -1
-	jr z, .reached_end
-	ld b, a
-	ld a, [de]
-	cp b
-	jr z, .done_carry
-	inc hl
-	jr .loop
-
-.reached_end
-	call GetBreedmonMovePointer
-	ld b, NUM_MOVES
-.loop2
-	ld a, [de]
-	cp [hl]
-	jr z, .found_eggmove
-	inc hl
-	dec b
-	jr z, .inherit_tmhm
-	jr .loop2
-
-.found_eggmove
-	ld a, [wEggMonSpecies]
-	dec a
-	ld c, a
-	ld b, 0
-	ld hl, EvosAttacksPointers
-	add hl, bc
-	add hl, bc
-	ld a, BANK(EvosAttacksPointers)
-	call GetFarHalfword
-.loop3
-	ld a, BANK(EvosAttacks)
-	call GetFarByte
-	inc hl
-	and a
-	jr nz, .loop3
-.loop4
-	ld a, BANK(EvosAttacks)
-	call GetFarByte
-	and a
-	jr z, .inherit_tmhm
-	inc hl
-	ld a, BANK(EvosAttacks)
-	call GetFarByte
-	ld b, a
-	ld a, [de]
-	cp b
-	jr z, .done_carry
-	inc hl
-	jr .loop4
-
-.inherit_tmhm
-	ld hl, TMHMMoves
-.loop5
-	ld a, BANK(TMHMMoves)
-	call GetFarByte
-	inc hl
-	and a
-	jr z, .done
-	ld b, a
-	ld a, [de]
-	cp b
-	jr nz, .loop5
-	ld [wPutativeTMHMMove], a
-	predef CanLearnTMHMMove
-	ld a, c
-	and a
-	jr z, .done
-
-.done_carry
-	pop bc
-	scf
-	ret
-
-.done
-	pop bc
-	and a
-	ret
-; 17169
-
-LoadEggMove: ; 17169
-	push de
-	push bc
-	ld a, [de]
-	ld b, a
-	ld hl, wEggMonMoves
-	ld c, NUM_MOVES
-.loop
-	ld a, [hli]
-	and a
-	jr z, .done
-	dec c
-	jr nz, .loop
-	ld de, wEggMonMoves
-	ld hl, wEggMonMoves + 1
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hli]
-	ld [de], a
-
-.done
-	dec hl
-	ld [hl], b
-	ld hl, wEggMonMoves
-	ld de, wEggMonPP
-	predef FillPP
-	pop bc
-	pop de
-	ret
-; 17197
-
-GetHeritableMoves: ; 17197
-	ld hl, wBreedMon2Moves
-	ld a, [wBreedMon1Species]
-	cp DITTO
-	jr z, .ditto1
-	ld a, [wBreedMon2Species]
-	cp DITTO
-	jr z, .ditto2
-	ld a, [wBreedMotherOrNonDitto]
-	and a
-	ret z
-	ld hl, wBreedMon1Moves
-	ret
-
-.ditto1
-	ld a, [wCurPartySpecies]
-	push af
-	ld a, [wBreedMon2Species]
-	ld [wCurPartySpecies], a
-	ld a, [wBreedMon2DVs]
-	ld [wTempMonDVs], a
-	ld a, [wBreedMon2DVs + 1]
-	ld [wTempMonDVs + 1], a
-	ld a, TEMPMON
-	ld [wMonType], a
-	predef GetGender
-	jr c, .inherit_mon2_moves
-	jr nz, .inherit_mon2_moves
-	jr .inherit_mon1_moves
-
-.ditto2
-	ld a, [wCurPartySpecies]
-	push af
-	ld a, [wBreedMon1Species]
-	ld [wCurPartySpecies], a
-	ld a, [wBreedMon1DVs]
-	ld [wTempMonDVs], a
-	ld a, [wBreedMon1DVs + 1]
-	ld [wTempMonDVs + 1], a
-	ld a, TEMPMON
-	ld [wMonType], a
-	predef GetGender
-	jr c, .inherit_mon1_moves
-	jr nz, .inherit_mon1_moves
-
-.inherit_mon2_moves
-	ld hl, wBreedMon2Moves
-	pop af
-	ld [wCurPartySpecies], a
-	ret
-
-.inherit_mon1_moves
-	ld hl, wBreedMon1Moves
-	pop af
-	ld [wCurPartySpecies], a
-	ret
-; 1720b
-
-GetBreedmonMovePointer: ; 1720b
-	ld hl, wBreedMon1Moves
-	ld a, [wBreedMon1Species]
-	cp DITTO
-	ret z
-	ld a, [wBreedMon2Species]
-	cp DITTO
-	jr z, .ditto
-	ld a, [wBreedMotherOrNonDitto]
-	and a
-	ret z
-
-.ditto
-	ld hl, wBreedMon2Moves
-	ret
-; 17224
-
-
-GetEggFrontpic: ; 17224 (5:7224)
-	push de
-	ld [wCurPartySpecies], a
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld hl, wBattleMonDVs
-	predef GetUnownLetter
-	pop de
-	predef_jump GetMonFrontpic
-
-GetHatchlingFrontpic: ; 1723c (5:723c)
-	push de
-	ld [wCurPartySpecies], a
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld hl, wBattleMonDVs
-	predef GetUnownLetter
-	pop de
-	predef_jump GetAnimatedFrontpic
-
-Hatch_UpdateFrontpicBGMapCenter: ; 17254 (5:7254)
-	push af
-	call WaitTop
-	push hl
-	push bc
-	hlcoord 0, 0
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	ld a, " "
-	call ByteFill
-	pop bc
-	pop hl
-	ld a, b
-	ld [hBGMapAddress + 1], a
-	ld a, c
-	ld [hGraphicStartTile], a
-	lb bc, 7, 7
-	predef PlaceGraphic
-	pop af
-	call Hatch_LoadFrontpicPal
-	call SetPalettes
-	jp WaitBGMap
-
-EggHatch_DoAnimFrame: ; 1727f (5:727f)
-	push hl
-	push de
-	push bc
-	callfar PlaySpriteAnimations
-	call DelayFrame
-	pop bc
-	pop de
-	pop hl
-	ret
-
-EggHatch_AnimationSequence: ; 1728f (5:728f)
-	ld a, [wd265]
-	ld [wJumptableIndex], a
-	ld a, [wCurSpecies]
-	push af
-	ld de, MUSIC_NONE
-	call PlayMusic
-	farcall BlankScreen
-	call DisableLCD
-	ld hl, EggHatchGFX
-	ld de, vTiles0 tile $00
-	ld bc, 2 tiles
-	ld a, BANK(EggHatchGFX)
-	call FarCopyBytes
-	farcall ClearSpriteAnims
-	ld de, vTiles2 tile $00
-	ld a, [wJumptableIndex]
-	call GetHatchlingFrontpic
-	ld de, vTiles2 tile $31
-	ld a, EGG
-	call GetEggFrontpic
-	ld de, MUSIC_EVOLUTION
-	call PlayMusic
-	call EnableLCD
-	hlcoord 7, 4
-	ld b, HIGH(vBGMap0)
-	ld c, $31 ; Egg tiles start here
-	ld a, EGG
-	call Hatch_UpdateFrontpicBGMapCenter
-	ld c, 80
-	call DelayFrames
-	xor a
-	ld [wFrameCounter], a
-	ld a, [hSCX]
-	ld b, a
-.outerloop
-	ld hl, wFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp 8
-	jr nc, .done
-	ld e, [hl]
-.loop
-; wobble e times
-	ld a, 2
-	ld [hSCX], a
-	ld a, -2
-	ld [wGlobalAnimXOffset], a
-	call EggHatch_DoAnimFrame
-	ld c, 2
-	call DelayFrames
-	ld a, -2
-	ld [hSCX], a
-	ld a, 2
-	ld [wGlobalAnimXOffset], a
-	call EggHatch_DoAnimFrame
-	ld c, 2
-	call DelayFrames
-	dec e
-	jr nz, .loop
-	ld c, 16
-	call DelayFrames
-	call EggHatch_CrackShell
-	jr .outerloop
-
-.done
-	ld de, SFX_EGG_HATCH
-	call PlaySFX
-	xor a
-	ld [hSCX], a
-	ld [wGlobalAnimXOffset], a
-	call ClearSprites
-	call Hatch_InitShellFragments
-	hlcoord 6, 3
-	ld b, HIGH(vBGMap0)
-	ld c, $00 ; Hatchling tiles start here
-	ld a, [wJumptableIndex]
-	call Hatch_UpdateFrontpicBGMapCenter
-	call Hatch_ShellFragmentLoop
-	call WaitSFX
-	ld a, [wJumptableIndex]
-	ld [wCurPartySpecies], a
-	hlcoord 6, 3
-	ld d, $0
-	ld e, ANIM_MON_HATCH
-	predef AnimateFrontpic
-	pop af
-	ld [wCurSpecies], a
-	ret
-
-Hatch_LoadFrontpicPal: ; 17363 (5:7363)
-	ld [wPlayerHPPal], a
-	ld b, SCGB_EVOLUTION
-	ld c, $0
-	jp GetSGBLayout
-
-EggHatch_CrackShell: ; 1736d (5:736d)
-	ld a, [wFrameCounter]
-	dec a
-	and $7
-	cp $7
-	ret z
-	srl a
-	ret nc
-	swap a
-	srl a
-	add 9 * 8 + 4
-	ld d, a
-	ld e, 11 * 8
-	ld a, SPRITE_ANIM_INDEX_EGG_CRACK
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_TILE_ID
-	add hl, bc
-	ld [hl], $0
-	ld de, SFX_EGG_CRACK
-	jp PlaySFX
-; 17393 (5:7393)
-
-EggHatchGFX: ; 17393
-INCBIN "gfx/evo/egg_hatch.2bpp"
-; 173b3
-
-Hatch_InitShellFragments: ; 173b3 (5:73b3)
-	farcall ClearSpriteAnims
-	ld hl, .SpriteData
-.loop
-	ld a, [hli]
-	cp -1
-	jr z, .done
-	ld e, a
-	ld a, [hli]
-	ld d, a
-	ld a, [hli]
-	ld c, a
-	ld a, [hli]
-	ld b, a
-	push hl
-	push bc
-
-	ld a, SPRITE_ANIM_INDEX_EGG_HATCH
-	call _InitSpriteAnimStruct
-
-	ld hl, SPRITEANIMSTRUCT_TILE_ID
-	add hl, bc
-	ld [hl], $0
-
-	pop de
-	ld a, e
-	ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
-	add hl, bc
-	add [hl]
-	ld [hl], a
-
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld [hl], d
-
-	pop hl
-	jr .loop
-.done
-	ld de, SFX_EGG_HATCH
-	call PlaySFX
-	call EggHatch_DoAnimFrame
-	ret
-; 173ef (5:73ef)
-
-shell_fragment: MACRO
-; y tile, y pxl, x tile, x pxl, frameset offset, ???
-	db (\1 * 8) % $100 + \2, (\3 * 8) % $100 + \4, \5 - SPRITE_ANIM_FRAMESET_EGG_HATCH_1, \6
-ENDM
-
-.SpriteData: ; 173ef
-	shell_fragment 10, 4,  9, 0, SPRITE_ANIM_FRAMESET_EGG_HATCH_1, $3c
-	shell_fragment 11, 4,  9, 0, SPRITE_ANIM_FRAMESET_EGG_HATCH_2, $04
-	shell_fragment 10, 4, 10, 0, SPRITE_ANIM_FRAMESET_EGG_HATCH_1, $30
-	shell_fragment 11, 4, 10, 0, SPRITE_ANIM_FRAMESET_EGG_HATCH_2, $10
-	shell_fragment 10, 4, 11, 0, SPRITE_ANIM_FRAMESET_EGG_HATCH_3, $24
-	shell_fragment 11, 4, 11, 0, SPRITE_ANIM_FRAMESET_EGG_HATCH_4, $1c
-	shell_fragment 10, 0,  9, 4, SPRITE_ANIM_FRAMESET_EGG_HATCH_1, $36
-	shell_fragment 12, 0,  9, 4, SPRITE_ANIM_FRAMESET_EGG_HATCH_2, $0a
-	shell_fragment 10, 0, 10, 4, SPRITE_ANIM_FRAMESET_EGG_HATCH_3, $2a
-	shell_fragment 12, 0, 10, 4, SPRITE_ANIM_FRAMESET_EGG_HATCH_4, $16
-	db -1
-; 17418
-
-Hatch_ShellFragmentLoop: ; 17418 (5:7418)
-	ld c, 129
-.loop
-	call EggHatch_DoAnimFrame
-	dec c
-	jr nz, .loop
-	ret
-
-DayCareMon1: ; 17421
-	ld hl, DayCareMon1Text
-	call PrintText
-	ld a, [wBreedMon1Species]
-	call PlayMonCry
-	ld a, [wDayCareLady]
-	bit DAYCARELADY_HAS_MON_F, a
-	jr z, DayCareMonCursor
-	call ButtonSound
-	ld hl, wBreedMon2Nick
-	call DayCareMonCompatibilityText
-	jp PrintText
-
-DayCareMon2: ; 17440
-	ld hl, DayCareMon2Text
-	call PrintText
-	ld a, [wBreedMon2Species]
-	call PlayMonCry
-	ld a, [wDayCareMan]
-	bit DAYCAREMAN_HAS_MON_F, a
-	jr z, DayCareMonCursor
-	call ButtonSound
-	ld hl, wBreedMon1Nick
-	call DayCareMonCompatibilityText
-	jp PrintText
-
-DayCareMonCursor: ; 1745f
-	jp WaitPressAorB_BlinkCursor
-; 17462
-
-DayCareMon2Text: ; 0x17462
-	; It's @ that was left with the DAY-CARE LADY.
-	text_jump UnknownText_0x1c0df3
-	db "@"
-; 0x17467
-
-DayCareMon1Text: ; 0x17467
-	; It's @ that was left with the DAY-CARE MAN.
-	text_jump UnknownText_0x1c0e24
-	db "@"
-; 0x1746c
-
-DayCareMonCompatibilityText: ; 1746c
-	push bc
-	ld de, wStringBuffer1
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	call CheckBreedmonCompatibility
-	pop bc
-	ld a, [wd265]
-	ld hl, .AllAlone
-	cp -1
-	jr z, .done
-	ld hl, .Incompatible
-	and a
-	jr z, .done
-	ld hl, .HighCompatibility
-	cp 230
-	jr nc, .done
-	cp 70
-	ld hl, .ModerateCompatibility
-	jr nc, .done
-	ld hl, .SlightCompatibility
-
-.done
-	ret
-; 1749c
-
-.AllAlone: ; 0x1749c
-	; It's brimming with energy.
-	text_jump UnknownText_0x1c0e54
-	db "@"
-; 0x174a1
-
-.Incompatible: ; 0x174a1
-	; It has no interest in @ .
-	text_jump UnknownText_0x1c0e6f
-	db "@"
-; 0x174a6
-
-.HighCompatibility: ; 0x174a6
-	; It appears to care for @ .
-	text_jump UnknownText_0x1c0e8d
-	db "@"
-; 0x174ab
-
-.ModerateCompatibility: ; 0x174ab
-	; It's friendly with @ .
-	text_jump UnknownText_0x1c0eac
-	db "@"
-; 0x174b0
-
-.SlightCompatibility: ; 0x174b0
-	; It shows interest in @ .
-	text_jump UnknownText_0x1c0ec6
-	db "@"
-; 0x174b5
-
-Unreferenced_DayCareMonPrintEmptyString: ; 174b5
-	ld hl, .string
-	ret
-; 174b9
-
-.string ; 174b9
-	db "@"
-; 174ba
-
--- a/engine/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/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/caught_data.asm
+++ /dev/null
@@ -1,247 +1,0 @@
-CheckPartyFullAfterContest: ; 4d9e5
-	ld a, [wContestMon]
-	and a
-	jp z, .DidntCatchAnything
-	ld [wCurPartySpecies], a
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld hl, wPartyCount
-	ld a, [hl]
-	cp PARTY_LENGTH
-	jp nc, .TryAddToBox
-	inc a
-	ld [hl], a
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [wContestMon]
-	ld [hli], a
-	ld [wCurSpecies], a
-	ld a, -1
-	ld [hl], a
-	ld hl, wPartyMon1Species
-	ld a, [wPartyCount]
-	dec a
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld d, h
-	ld e, l
-	ld hl, wContestMon
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call CopyBytes
-	ld a, [wPartyCount]
-	dec a
-	ld hl, wPartyMonOT
-	call SkipNames
-	ld d, h
-	ld e, l
-	ld hl, wPlayerName
-	call CopyBytes
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	call GetPokemonName
-	ld hl, wStringBuffer1
-	ld de, wMonOrItemNameBuffer
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-	call GiveANickname_YesNo
-	jr c, .Party_SkipNickname
-	ld a, [wPartyCount]
-	dec a
-	ld [wCurPartyMon], a
-	xor a
-	ld [wMonType], a
-	ld de, wMonOrItemNameBuffer
-	callfar InitNickname
-
-.Party_SkipNickname:
-	ld a, [wPartyCount]
-	dec a
-	ld hl, wPartyMonNicknames
-	call SkipNames
-	ld d, h
-	ld e, l
-	ld hl, wMonOrItemNameBuffer
-	call CopyBytes
-	ld a, [wPartyCount]
-	dec a
-	ld hl, wPartyMon1Level
-	call GetPartyLocation
-	ld a, [hl]
-	ld [wCurPartyLevel], a
-	call SetCaughtData
-	ld a, [wPartyCount]
-	dec a
-	ld hl, wPartyMon1CaughtLocation
-	call GetPartyLocation
-	ld a, [hl]
-	and CAUGHT_GENDER_MASK
-	ld b, NATIONAL_PARK
-	or b
-	ld [hl], a
-	xor a
-	ld [wContestMon], a
-	and a ; BUGCONTEST_CAUGHT_MON
-	ld [wScriptVar], a
-	ret
-
-.TryAddToBox: ; 4daa3
-	ld a, BANK(sBoxCount)
-	call GetSRAMBank
-	ld hl, sBoxCount
-	ld a, [hl]
-	cp MONS_PER_BOX
-	call CloseSRAM
-	jr nc, .BoxFull
-	xor a
-	ld [wCurPartyMon], a
-	ld hl, wContestMon
-	ld de, wBufferMon
-	ld bc, BOXMON_STRUCT_LENGTH
-	call CopyBytes
-	ld hl, wPlayerName
-	ld de, wBufferMonOT
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	callfar InsertPokemonIntoBox
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	call GetPokemonName
-	call GiveANickname_YesNo
-	ld hl, wStringBuffer1
-	jr c, .Box_SkipNickname
-	ld a, BOXMON
-	ld [wMonType], a
-	ld de, wMonOrItemNameBuffer
-	callfar InitNickname
-	ld hl, wMonOrItemNameBuffer
-
-.Box_SkipNickname:
-	ld a, BANK(sBoxMonNicknames)
-	call GetSRAMBank
-	ld de, sBoxMonNicknames
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-	call CloseSRAM
-
-.BoxFull:
-	ld a, BANK(sBoxMon1Level)
-	call GetSRAMBank
-	ld a, [sBoxMon1Level]
-	ld [wCurPartyLevel], a
-	call CloseSRAM
-	call SetBoxMonCaughtData
-	ld a, BANK(sBoxMon1CaughtLocation)
-	call GetSRAMBank
-	ld hl, sBoxMon1CaughtLocation
-	ld a, [hl]
-	and CAUGHT_GENDER_MASK
-	ld b, NATIONAL_PARK
-	or b
-	ld [hl], a
-	call CloseSRAM
-	xor a
-	ld [wContestMon], a
-	ld a, BUGCONTEST_BOXED_MON
-	ld [wScriptVar], a
-	ret
-
-.DidntCatchAnything: ; 4db35
-	ld a, BUGCONTEST_NO_CATCH
-	ld [wScriptVar], a
-	ret
-
-GiveANickname_YesNo: ; 4db3b
-	ld hl, TextJump_GiveANickname
-	call PrintText
-	jp YesNoBox
-
-TextJump_GiveANickname: ; 0x4db44
-	; Give a nickname to the @  you received?
-	text_jump UnknownText_0x1c12fc
-	db "@"
-
-SetCaughtData: ; 4db49
-	ld a, [wPartyCount]
-	dec a
-	ld hl, wPartyMon1CaughtLevel
-	call GetPartyLocation
-SetBoxmonOrEggmonCaughtData: ; 4db53
-	ld a, [wTimeOfDay]
-	inc a
-	rrca
-	rrca
-	ld b, a
-	ld a, [wCurPartyLevel]
-	or b
-	ld [hli], a
-	ld a, [wMapGroup]
-	ld b, a
-	ld a, [wMapNumber]
-	ld c, a
-	cp MAP_POKECENTER_2F
-	jr nz, .NotPokecenter2F
-	ld a, b
-	cp GROUP_POKECENTER_2F
-	jr nz, .NotPokecenter2F
-
-	ld a, [wBackupMapGroup]
-	ld b, a
-	ld a, [wBackupMapNumber]
-	ld c, a
-
-.NotPokecenter2F:
-	call GetWorldMapLocation
-	ld b, a
-	ld a, [wPlayerGender]
-	rrca ; shift bit 0 (PLAYERGENDER_FEMALE_F) to bit 7 (CAUGHT_GENDER_MASK)
-	or b
-	ld [hl], a
-	ret
-
-SetBoxMonCaughtData: ; 4db83
-	ld a, BANK(sBoxMon1CaughtLevel)
-	call GetSRAMBank
-	ld hl, sBoxMon1CaughtLevel
-	call SetBoxmonOrEggmonCaughtData
-	call CloseSRAM
-	ret
-
-SetGiftBoxMonCaughtData: ; 4db92
-	push bc
-	ld a, BANK(sBoxMon1CaughtLevel)
-	call GetSRAMBank
-	ld hl, sBoxMon1CaughtLevel
-	pop bc
-	call SetGiftMonCaughtData
-	call CloseSRAM
-	ret
-
-SetGiftPartyMonCaughtData: ; 4dba3
-	ld a, [wPartyCount]
-	dec a
-	ld hl, wPartyMon1CaughtLevel
-	push bc
-	call GetPartyLocation
-	pop bc
-SetGiftMonCaughtData: ; 4dbaf
-	xor a
-	ld [hli], a
-	ld a, GIFT_LOCATION
-	rrc b
-	or b
-	ld [hl], a
-	ret
-
-SetEggMonCaughtData: ; 4dbb8 (13:5bb8)
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1CaughtLevel
-	call GetPartyLocation
-	ld a, [wCurPartyLevel]
-	push af
-	ld a, CAUGHT_EGG_LEVEL
-	ld [wCurPartyLevel], a
-	call SetBoxmonOrEggmonCaughtData
-	pop af
-	ld [wCurPartyLevel], a
-	ret
--- a/engine/cgb_layouts.asm
+++ /dev/null
@@ -1,1033 +1,0 @@
-; Replaces the functionality of sgb.asm to work with CGB hardware.
-
-CheckCGB: ; 8d55
-	ld a, [hCGB]
-	and a
-	ret
-; 8d59
-
-LoadSGBLayoutCGB: ; 8d59
-	ld a, b
-	cp SCGB_RAM
-	jr nz, .not_ram
-	ld a, [wSGBPredef]
-.not_ram
-	cp SCGB_PARTY_MENU_HP_PALS
-	jp z, CGB_ApplyPartyMenuHPPals
-	call ResetBGPals
-	ld l, a
-	ld h, 0
-	add hl, hl
-	ld de, .dw
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, .ReturnFromJumpTable
-	push de
-	jp hl
-; 8d79
-
-.ReturnFromJumpTable: ; 8d79
-	ret
-; 8d7a
-
-.dw ; 8d7a
-	dw _CGB_BattleGrayscale
-	dw _CGB_BattleColors
-	dw _CGB_PokegearPals
-	dw _CGB_StatsScreenHPPals
-	dw _CGB_Pokedex
-	dw _CGB_SlotMachine
-	dw _CGB06
-	dw _CGB_GSIntro
-	dw _CGB_Diploma
-	dw _CGB_MapPals
-	dw _CGB_PartyMenu
-	dw _CGB_Evolution
-	dw _CGB_GSTitleScreen
-	dw _CGB0d
-	dw _CGB_MoveList
-	dw _CGB0f
-	dw _CGB_PokedexSearchOption
-	dw _CGB11
-	dw _CGB_Pokepic
-	dw _CGB13
-	dw _CGB_PackPals
-	dw _CGB_TrainerCard
-	dw _CGB_PokedexUnownMode
-	dw _CGB_BillsPC
-	dw _CGB_UnownPuzzle
-	dw _CGB_GamefreakLogo
-	dw _CGB_PlayerOrMonFrontpicPals
-	dw _CGB_TradeTube
-	dw _CGB_TrainerOrMonFrontpicPals
-	dw _CGB_MysteryGift
-	dw _CGB1e
-; 8db8
-
-_CGB_BattleGrayscale: ; 8db8
-	ld hl, PalPacket_BattleGrayscale + 1
-	ld de, wBGPals1
-	ld c, 4
-	call CopyPalettes
-	ld hl, PalPacket_BattleGrayscale + 1
-	ld de, wBGPals1 palette PAL_BATTLE_BG_EXP
-	ld c, 4
-	call CopyPalettes
-	ld hl, PalPacket_BattleGrayscale + 1
-	ld de, wOBPals1
-	ld c, 2
-	call CopyPalettes
-	jr _CGB_FinishBattleScreenLayout
-
-_CGB_BattleColors: ; 8ddb
-	ld de, wBGPals1
-	call GetBattlemonBackpicPalettePointer
-	push hl
-	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_BG_PLAYER
-	call GetEnemyFrontpicPalettePointer
-	push hl
-	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_BG_ENEMY
-	ld a, [wEnemyHPPal]
-	ld l, a
-	ld h, $0
-	add hl, hl
-	add hl, hl
-	ld bc, HPBarPals
-	add hl, bc
-	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_BG_ENEMY_HP
-	ld a, [wPlayerHPPal]
-	ld l, a
-	ld h, $0
-	add hl, hl
-	add hl, hl
-	ld bc, HPBarPals
-	add hl, bc
-	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_BG_PLAYER_HP
-	ld hl, ExpBarPalette
-	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_BG_EXP
-	ld de, wOBPals1
-	pop hl
-	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_OB_ENEMY
-	pop hl
-	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_OB_PLAYER
-	ld a, SCGB_BATTLE_COLORS
-	ld [wSGBPredef], a
-	call ApplyPals
-_CGB_FinishBattleScreenLayout: ; 8e23
-	call InitPartyMenuBGPal7
-	hlcoord 0, 0, wAttrMap
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, PAL_BATTLE_BG_ENEMY_HP
-	call ByteFill
-	hlcoord 0, 4, wAttrMap
-	lb bc, 8, 10
-	ld a, PAL_BATTLE_BG_PLAYER
-	call FillBoxCGB
-	hlcoord 10, 0, wAttrMap
-	lb bc, 7, 10
-	ld a, PAL_BATTLE_BG_ENEMY
-	call FillBoxCGB
-	hlcoord 0, 0, wAttrMap
-	lb bc, 4, 10
-	ld a, PAL_BATTLE_BG_ENEMY_HP
-	call FillBoxCGB
-	hlcoord 10, 7, wAttrMap
-	lb bc, 5, 10
-	ld a, PAL_BATTLE_BG_PLAYER_HP
-	call FillBoxCGB
-	hlcoord 10, 11, wAttrMap
-	lb bc, 1, 9
-	ld a, PAL_BATTLE_BG_EXP
-	call FillBoxCGB
-	hlcoord 0, 12, wAttrMap
-	ld bc, 6 * SCREEN_WIDTH
-	ld a, PAL_BATTLE_BG_TEXT
-	call ByteFill
-	ld hl, BattleObjectPals
-	ld de, wOBPals1 palette PAL_BATTLE_OB_GRAY
-	ld bc, 6 palettes
-	ld a, BANK(wOBPals1)
-	call FarCopyWRAM
-	call ApplyAttrMap
-	ret
-; 8e85
-
-
-InitPartyMenuBGPal7: ; 8e85
-	farcall Function100dc0
-Mobile_InitPartyMenuBGPal7: ; 8e8b
-	ld hl, PartyMenuBGPalette
-	jr nc, .not_mobile
-	ld hl, PartyMenuBGMobilePalette
-.not_mobile
-	ld de, wBGPals1 palette 7
-	ld bc, 1 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	ret
-; 8e9f
-
-InitPartyMenuBGPal0: ; 8e9f
-	farcall Function100dc0
-	ld hl, PartyMenuBGPalette
-	jr nc, .not_mobile
-	ld hl, PartyMenuBGMobilePalette
-.not_mobile
-	ld de, wBGPals1 palette 0
-	ld bc, 1 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	ret
-; 8eb9
-
-_CGB_PokegearPals: ; 8eb9
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .male
-	ld hl, FemalePokegearPals
-	jr .got_pals
-
-.male
-	ld hl, MalePokegearPals
-.got_pals
-	ld de, wBGPals1
-	ld bc, 6 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 8edb
-
-_CGB_StatsScreenHPPals: ; 8edb
-	ld de, wBGPals1
-	ld a, [wCurHPPal]
-	ld l, a
-	ld h, $0
-	add hl, hl
-	add hl, hl
-	ld bc, HPBarPals
-	add hl, bc
-	call LoadPalette_White_Col1_Col2_Black ; hp palette
-	ld a, [wCurPartySpecies]
-	ld bc, wTempMonDVs
-	call GetPlayerOrMonPalettePointer
-	call LoadPalette_White_Col1_Col2_Black ; mon palette
-	ld hl, ExpBarPalette
-	call LoadPalette_White_Col1_Col2_Black ; exp palette
-	ld hl, StatsScreenPagePals
-	ld de, wBGPals1 palette 3
-	ld bc, 3 palettes ; pink, green, and blue page palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	call WipeAttrMap
-
-	hlcoord 0, 0, wAttrMap
-	lb bc, 8, SCREEN_WIDTH
-	ld a, $1 ; mon palette
-	call FillBoxCGB
-
-	hlcoord 10, 16, wAttrMap
-	ld bc, 10
-	ld a, $2 ; exp palette
-	call ByteFill
-
-	hlcoord 13, 5, wAttrMap
-	lb bc, 2, 2
-	ld a, $3 ; pink page palette
-	call FillBoxCGB
-
-	hlcoord 15, 5, wAttrMap
-	lb bc, 2, 2
-	ld a, $4 ; green page palette
-	call FillBoxCGB
-
-	hlcoord 17, 5, wAttrMap
-	lb bc, 2, 2
-	ld a, $5 ; blue page palette
-	call FillBoxCGB
-
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 8f52
-
-StatsScreenPagePals: ; 8f52
-INCLUDE "gfx/stats/pages.pal"
-; 8f6a
-
-StatsScreenPals: ; 8f6a
-INCLUDE "gfx/stats/stats.pal"
-; 8f70
-
-_CGB_Pokedex: ; 8f70
-	ld de, wBGPals1
-	ld a, PREDEFPAL_POKEDEX
-	call GetPredefPal
-	call LoadHLPaletteIntoDE ; dex interface palette
-	ld a, [wCurPartySpecies]
-	cp $ff
-	jr nz, .is_pokemon
-	ld hl, .PokedexQuestionMarkPalette
-	call LoadHLPaletteIntoDE ; green question mark palette
-	jr .got_palette
-
-.is_pokemon
-	call GetMonPalettePointer_
-	call LoadPalette_White_Col1_Col2_Black ; mon palette
-.got_palette
-	call WipeAttrMap
-	hlcoord 1, 1, wAttrMap
-	lb bc, 7, 7
-	ld a, $1 ; green question mark palette
-	call FillBoxCGB
-	call InitPartyMenuOBPals
-	ld hl, .PokedexCursorPalette
-	ld de, wOBPals1 palette 7 ; green cursor palette
-	ld bc, 1 palettes
-	ld a, BANK(wOBPals1)
-	call FarCopyWRAM
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 8fba
-
-.PokedexQuestionMarkPalette: ; 8fba
-INCLUDE "gfx/pokedex/question_mark.pal"
-; 8fc2
-
-.PokedexCursorPalette: ; 8fc2
-INCLUDE "gfx/pokedex/cursor.pal"
-; 8fca
-
-_CGB_BillsPC: ; 8fca
-	ld de, wBGPals1
-	ld a, PREDEFPAL_POKEDEX
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-	ld a, [wCurPartySpecies]
-	cp $ff
-	jr nz, .GetMonPalette
-	ld hl, .BillsPCOrangePalette
-	call LoadHLPaletteIntoDE
-	jr .Resume
-
-.GetMonPalette:
-	ld bc, wTempMonDVs
-	call GetPlayerOrMonPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-.Resume:
-	call WipeAttrMap
-	hlcoord 1, 4, wAttrMap
-	lb bc, 7, 7
-	ld a, $1
-	call FillBoxCGB
-	call InitPartyMenuOBPals
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 9009
-
-.Function9009: ; 9009
-	ld hl, .BillsPCOrangePalette
-	call LoadHLPaletteIntoDE
-	jr .asm_901a
-
-.unused
-	ld bc, wTempMonDVs
-	call GetPlayerOrMonPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-.asm_901a
-	call WipeAttrMap
-	hlcoord 1, 1, wAttrMap
-	lb bc, 7, 7
-	ld a, $1
-	call FillBoxCGB
-	call InitPartyMenuOBPals
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 9036
-
-.BillsPCOrangePalette: ; 9036
-INCLUDE "gfx/pc/orange.pal"
-; 903e
-
-_CGB_PokedexUnownMode: ; 903e
-	ld de, wBGPals1
-	ld a, PREDEFPAL_POKEDEX
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-	ld a, [wCurPartySpecies]
-	call GetMonPalettePointer_
-	call LoadPalette_White_Col1_Col2_Black
-	call WipeAttrMap
-	hlcoord 7, 5, wAttrMap
-	lb bc, 7, 7
-	ld a, $1
-	call FillBoxCGB
-	call InitPartyMenuOBPals
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 906e
-
-_CGB_SlotMachine: ; 906e
-	ld hl, SlotMachinePals
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	call WipeAttrMap
-	hlcoord 0, 2, wAttrMap
-	lb bc, 10, 3
-	ld a, $2
-	call FillBoxCGB
-	hlcoord 17, 2, wAttrMap
-	lb bc, 10, 3
-	ld a, $2
-	call FillBoxCGB
-	hlcoord 0, 4, wAttrMap
-	lb bc, 6, 3
-	ld a, $3
-	call FillBoxCGB
-	hlcoord 17, 4, wAttrMap
-	lb bc, 6, 3
-	ld a, $3
-	call FillBoxCGB
-	hlcoord 0, 6, wAttrMap
-	lb bc, 2, 3
-	ld a, $4
-	call FillBoxCGB
-	hlcoord 17, 6, wAttrMap
-	lb bc, 2, 3
-	ld a, $4
-	call FillBoxCGB
-	hlcoord 4, 2, wAttrMap
-	lb bc, 2, 12
-	ld a, $1
-	call FillBoxCGB
-	hlcoord 3, 2, wAttrMap
-	lb bc, 10, 1
-	ld a, $1
-	call FillBoxCGB
-	hlcoord 16, 2, wAttrMap
-	lb bc, 10, 1
-	ld a, $1
-	call FillBoxCGB
-	hlcoord 0, 12, wAttrMap
-	ld bc, $78
-	ld a, $7
-	call ByteFill
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 90f8
-
-_CGB06: ; 90f8
-	ld hl, PalPacket_SCGB_06 + 1
-	call CopyFourPalettes
-	call WipeAttrMap
-	ld de, wOBPals1
-	ld a, PREDEFPAL_PACK
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-	hlcoord 0, 6, wAttrMap
-	lb bc, 12, SCREEN_WIDTH
-	ld a, $1
-	call FillBoxCGB
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 9122
-
-_CGB_GSIntro: ; 9122
-	ld b, 0
-	ld hl, .Jumptable
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-; 912d
-
-.Jumptable: ; 912d
-	dw .ShellderLaprasScene
-	dw .JigglypuffPikachuScene
-	dw .StartersCharizardScene
-; 9133
-
-.ShellderLaprasScene: ; 9133
-	ld hl, .ShellderLaprasBGPalette
-	ld de, wBGPals1
-	call LoadHLPaletteIntoDE
-	ld hl, .ShellderLaprasOBPals
-	ld de, wOBPals1
-	ld bc, 2 palettes
-	ld a, BANK(wOBPals1)
-	call FarCopyWRAM
-	call WipeAttrMap
-	ret
-; 914e
-
-.ShellderLaprasBGPalette: ; 914e
-	RGB 19, 31, 19
-	RGB 18, 23, 31
-	RGB 11, 21, 28
-	RGB 04, 16, 24
-
-.ShellderLaprasOBPals: ; 9156
-	RGB 29, 29, 29
-	RGB 20, 19, 20
-	RGB 19, 06, 04
-	RGB 03, 04, 06
-
-	RGB 31, 31, 31
-	RGB 31, 31, 31
-	RGB 31, 00, 00
-	RGB 03, 04, 06
-; 9166
-
-.JigglypuffPikachuScene: ; 9166
-	ld de, wBGPals1
-	ld a, PREDEFPAL_GS_INTRO_JIGGLYPUFF_PIKACHU_BG
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-
-	ld de, wOBPals1
-	ld a, PREDEFPAL_GS_INTRO_JIGGLYPUFF_PIKACHU_OB
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-	call WipeAttrMap
-	ret
-; 9180
-
-.StartersCharizardScene: ; 9180
-	ld hl, PalPacket_Pack + 1
-	call CopyFourPalettes
-	ld de, wOBPals1
-	ld a, PREDEFPAL_GS_INTRO_STARTERS_TRANSITION
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-	call WipeAttrMap
-	ret
-; 9195
-
-_CGB11: ; 9195
-	ld hl, Palettes_SCGB_11
-	ld de, wBGPals1
-	ld bc, 5 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	call ApplyPals
-	call WipeAttrMap
-	call ApplyAttrMap
-	ret
-; 91ad
-
-_CGB_Diploma: ; 91ad
-	ld hl, DiplomaPalettes
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-
-	ld hl, PalPacket_Diploma + 1
-	call CopyFourPalettes
-	call WipeAttrMap
-	call ApplyAttrMap
-	ret
-; 91c8
-
-_CGB_MapPals: ; 91c8
-	call LoadMapPals
-	ld a, SCGB_MAPPALS
-	ld [wSGBPredef], a
-	ret
-; 91d1
-
-_CGB_PartyMenu: ; 91d1
-	ld hl, PalPacket_PartyMenu + 1
-	call CopyFourPalettes
-	call InitPartyMenuBGPal0
-	call InitPartyMenuBGPal7
-	call InitPartyMenuOBPals
-	call ApplyAttrMap
-	ret
-; 91e4
-
-_CGB_Evolution: ; 91e4
-	ld de, wBGPals1
-	ld a, c
-	and a
-	jr z, .pokemon
-	ld a, PREDEFPAL_BLACKOUT
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-	jr .got_palette
-
-.pokemon
-	ld hl, wPartyMon1DVs
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld c, l
-	ld b, h
-	ld a, [wPlayerHPPal]
-	call GetPlayerOrMonPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-	ld hl, BattleObjectPals
-	ld de, wOBPals1 palette PAL_BATTLE_OB_GRAY
-	ld bc, 6 palettes
-	ld a, BANK(wOBPals1)
-	call FarCopyWRAM
-
-.got_palette
-	call WipeAttrMap
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 9228
-
-_CGB_GSTitleScreen: ; 9228
-	ld hl, UnusedGSTitleBGPals
-	ld de, wBGPals1
-	ld bc, 5 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	ld hl, UnusedGSTitleOBPals
-	ld de, wOBPals1
-	ld bc, 2 palettes
-	ld a, BANK(wOBPals1)
-	call FarCopyWRAM
-	ld a, SCGB_DIPLOMA
-	ld [wSGBPredef], a
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 9251
-
-_CGB0d: ; 9251
-	ld hl, PalPacket_Diploma + 1
-	call CopyFourPalettes
-	call WipeAttrMap
-	call ApplyAttrMap
-	ret
-; 925e
-
-_CGB_UnownPuzzle: ; 925e
-	ld hl, PalPacket_UnownPuzzle + 1
-	call CopyFourPalettes
-	ld de, wOBPals1
-	ld a, PREDEFPAL_UNOWN_PUZZLE
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wOBPals1)
-	ld [rSVBK], a
-	ld hl, wOBPals1
-	ld a, LOW(palred 31 + palgreen 0 + palblue 0)
-	ld [hli], a
-	ld a, HIGH(palred 31 + palgreen 0 + palblue 0)
-	ld [hl], a
-	pop af
-	ld [rSVBK], a
-	call WipeAttrMap
-	call ApplyAttrMap
-	ret
-; 9289
-
-_CGB_TrainerCard: ; 9289
-	ld de, wBGPals1
-	xor a ; CHRIS
-	call GetTrainerPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-	ld a, FALKNER ; KRIS
-	call GetTrainerPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-	ld a, BUGSY
-	call GetTrainerPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-	ld a, WHITNEY
-	call GetTrainerPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-	ld a, MORTY
-	call GetTrainerPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-	ld a, CHUCK
-	call GetTrainerPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-	ld a, JASMINE
-	call GetTrainerPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-	ld a, PRYCE
-	call GetTrainerPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-	ld a, PREDEFPAL_CGB_BADGE
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-
-	; fill screen with opposite-gender palette for the card border
-	hlcoord 0, 0, wAttrMap
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, [wPlayerGender]
-	and a
-	ld a, $1 ; kris
-	jr z, .got_gender
-	ld a, $0 ; chris
-.got_gender
-	call ByteFill
-	; fill trainer sprite area with same-gender palette
-	hlcoord 14, 1, wAttrMap
-	lb bc, 7, 5
-	ld a, [wPlayerGender]
-	and a
-	ld a, $0 ; chris
-	jr z, .got_gender2
-	ld a, $1 ; kris
-.got_gender2
-	call FillBoxCGB
-	; top-right corner still uses the border's palette
-	hlcoord 18, 1, wAttrMap
-	ld [hl], $1
-	hlcoord 2, 11, wAttrMap
-	lb bc, 2, 4
-	ld a, $1 ; falkner
-	call FillBoxCGB
-	hlcoord 6, 11, wAttrMap
-	lb bc, 2, 4
-	ld a, $2 ; bugsy
-	call FillBoxCGB
-	hlcoord 10, 11, wAttrMap
-	lb bc, 2, 4
-	ld a, $3 ; whitney
-	call FillBoxCGB
-	hlcoord 14, 11, wAttrMap
-	lb bc, 2, 4
-	ld a, $4 ; morty
-	call FillBoxCGB
-	hlcoord 2, 14, wAttrMap
-	lb bc, 2, 4
-	ld a, $5 ; chuck
-	call FillBoxCGB
-	hlcoord 6, 14, wAttrMap
-	lb bc, 2, 4
-	ld a, $6 ; jasmine
-	call FillBoxCGB
-	hlcoord 10, 14, wAttrMap
-	lb bc, 2, 4
-	ld a, $7 ; pryce
-	call FillBoxCGB
-	; clair uses kris's palette
-	ld a, [wPlayerGender]
-	and a
-	push af
-	jr z, .got_gender3
-	hlcoord 14, 14, wAttrMap
-	lb bc, 2, 4
-	ld a, $1
-	call FillBoxCGB
-.got_gender3
-	pop af
-	ld c, $0
-	jr nz, .got_gender4
-	inc c
-.got_gender4
-	ld a, c
-	hlcoord 18, 1, wAttrMap
-	ld [hl], a
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 9373
-
-_CGB_MoveList: ; 9373
-	ld de, wBGPals1
-	ld a, PREDEFPAL_GOLDENROD
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-	ld a, [wPlayerHPPal]
-	ld l, a
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	ld bc, HPBarPals
-	add hl, bc
-	call LoadPalette_White_Col1_Col2_Black
-	call WipeAttrMap
-	hlcoord 11, 1, wAttrMap
-	lb bc, 2, 9
-	ld a, $1
-	call FillBoxCGB
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 93a6
-
-_CGB0f: ; 93a6
-	ld hl, PalPacket_SCGB_0F + 1
-	call CopyFourPalettes
-	call WipeAttrMap
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 93ba
-
-_CGB_PokedexSearchOption: ; 93ba
-	ld de, wBGPals1
-	ld a, PREDEFPAL_POKEDEX
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-	call WipeAttrMap
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 93d3
-
-_CGB_PackPals: ; 93d3
-; pack pals
-	ld a, [wBattleType]
-	cp BATTLETYPE_TUTORIAL
-	jr z, .tutorial_male
-
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .tutorial_male
-
-	ld hl, .KrisPackPals
-	jr .got_gender
-
-.tutorial_male
-	ld hl, .ChrisPackPals
-
-.got_gender
-	ld de, wBGPals1
-	ld bc, 8 palettes ; 6 palettes?
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	call WipeAttrMap
-	hlcoord 0, 0, wAttrMap
-	lb bc, 1, 10
-	ld a, $1
-	call FillBoxCGB
-	hlcoord 10, 0, wAttrMap
-	lb bc, 1, 10
-	ld a, $2
-	call FillBoxCGB
-	hlcoord 7, 2, wAttrMap
-	lb bc, 9, 1
-	ld a, $3
-	call FillBoxCGB
-	hlcoord 0, 7, wAttrMap
-	lb bc, 3, 5
-	ld a, $4
-	call FillBoxCGB
-	hlcoord 0, 3, wAttrMap
-	lb bc, 3, 5
-	ld a, $5
-	call FillBoxCGB
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 9439
-
-.ChrisPackPals: ; 9439
-INCLUDE "gfx/pack/pack.pal"
-; 9469
-
-.KrisPackPals: ; 9469
-INCLUDE "gfx/pack/pack_f.pal"
-; 9499
-
-_CGB_Pokepic: ; 9499
-	call _CGB_MapPals
-	ld de, SCREEN_WIDTH
-	hlcoord 0, 0, wAttrMap
-	ld a, [wMenuBorderTopCoord]
-.loop
-	and a
-	jr z, .found_top
-	dec a
-	add hl, de
-	jr .loop
-
-.found_top
-	ld a, [wMenuBorderLeftCoord]
-	ld e, a
-	ld d, $0
-	add hl, de
-	ld a, [wMenuBorderTopCoord]
-	ld b, a
-	ld a, [wMenuBorderBottomCoord]
-	inc a
-	sub b
-	ld b, a
-	ld a, [wMenuBorderLeftCoord]
-	ld c, a
-	ld a, [wMenuBorderRightCoord]
-	sub c
-	inc a
-	ld c, a
-	ld a, $0
-	call FillBoxCGB
-	call ApplyAttrMap
-	ret
-; 94d0
-
-_CGB13: ; 94d0
-	ld hl, PalPacket_SCGB_13 + 1
-	call CopyFourPalettes
-	call WipeAttrMap
-	hlcoord 0, 4, wAttrMap
-	lb bc, 10, SCREEN_WIDTH
-	ld a, $2
-	call FillBoxCGB
-	hlcoord 0, 6, wAttrMap
-	lb bc, 6, SCREEN_WIDTH
-	ld a, $1
-	call FillBoxCGB
-	call ApplyAttrMap
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 94fa
-
-_CGB_GamefreakLogo: ; 94fa
-	ld de, wBGPals1
-	ld a, PREDEFPAL_GAMEFREAK_LOGO
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-	ld hl, .Palette
-	ld de, wOBPals1
-	call LoadHLPaletteIntoDE
-	ld hl, .Palette
-	ld de, wOBPals1 palette 1
-	call LoadHLPaletteIntoDE
-	call WipeAttrMap
-	call ApplyAttrMap
-	call ApplyPals
-	ret
-; 9521
-
-.Palette: ; 9521
-INCLUDE "gfx/splash/logo.pal"
-; 9529
-
-_CGB_PlayerOrMonFrontpicPals: ; 9529
-	ld de, wBGPals1
-	ld a, [wCurPartySpecies]
-	ld bc, wTempMonDVs
-	call GetPlayerOrMonPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-	call WipeAttrMap
-	call ApplyAttrMap
-	call ApplyPals
-	ret
-; 9542
-
-_CGB1e: ; 9542
-	ld de, wBGPals1
-	ld a, [wCurPartySpecies]
-	call GetMonPalettePointer_
-	call LoadPalette_White_Col1_Col2_Black
-	call WipeAttrMap
-	call ApplyAttrMap
-	ret
-; 9555
-
-_CGB_TradeTube: ; 9555
-	ld hl, PalPacket_TradeTube + 1
-	call CopyFourPalettes
-	ld hl, PartyMenuOBPals
-	ld de, wOBPals1
-	ld bc, 1 palettes
-	ld a, BANK(wOBPals1)
-	call FarCopyWRAM
-	ld de, wOBPals1 palette 7
-	ld a, PREDEFPAL_TRADE_TUBE
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-	call WipeAttrMap
-	ret
-; 9578
-
-_CGB_TrainerOrMonFrontpicPals: ; 9578
-	ld de, wBGPals1
-	ld a, [wCurPartySpecies]
-	ld bc, wTempMonDVs
-	call GetFrontpicPalettePointer
-	call LoadPalette_White_Col1_Col2_Black
-	call WipeAttrMap
-	call ApplyAttrMap
-	call ApplyPals
-	ret
-; 9591
-
-_CGB_MysteryGift: ; 9591
-	ld hl, .Palettes
-	ld de, wBGPals1
-	ld bc, 2 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	call ApplyPals
-	call WipeAttrMap
-	hlcoord 3, 7, wAttrMap
-	lb bc, 8, 14
-	ld a, $1
-	call FillBoxCGB
-	hlcoord 1, 5, wAttrMap
-	lb bc, 1, 18
-	ld a, $1
-	call FillBoxCGB
-	hlcoord 1, 16, wAttrMap
-	lb bc, 1, 18
-	ld a, $1
-	call FillBoxCGB
-	hlcoord 0, 0, wAttrMap
-	lb bc, 17, 2
-	ld a, $1
-	call FillBoxCGB
-	hlcoord 18, 5, wAttrMap
-	lb bc, 12, 1
-	ld a, $1
-	call FillBoxCGB
-	call ApplyAttrMap
-	ret
-; 95e0
-
-.Palettes: ; 95e0
-INCLUDE "gfx/mystery_gift/mystery_gift.pal"
-; 95f0
--- a/engine/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/color.asm
+++ /dev/null
@@ -1,1356 +1,0 @@
-INCLUDE "engine/sgb_layouts.asm"
-
-SHINY_ATK_BIT EQU 5
-SHINY_DEF_VAL EQU 10
-SHINY_SPD_VAL EQU 10
-SHINY_SPC_VAL EQU 10
-
-CheckShininess:
-; Check if a mon is shiny by DVs at bc.
-; Return carry if shiny.
-
-	ld l, c
-	ld h, b
-
-; Attack
-	ld a, [hl]
-	and 1 << SHINY_ATK_BIT
-	jr z, .NotShiny
-
-; Defense
-	ld a, [hli]
-	and $f
-	cp  SHINY_DEF_VAL
-	jr nz, .NotShiny
-
-; Speed
-	ld a, [hl]
-	and $f0
-	cp  SHINY_SPD_VAL << 4
-	jr nz, .NotShiny
-
-; Special
-	ld a, [hl]
-	and $f
-	cp  SHINY_SPC_VAL
-	jr nz, .NotShiny
-
-.Shiny:
-	scf
-	ret
-
-.NotShiny:
-	and a
-	ret
-
-Unused_CheckContestMon:
-; Check a mon's DVs at hl in the bug catching contest.
-; Return carry if its DVs are good enough to place in the contest.
-
-; Attack
-	ld a, [hl]
-	cp 10 << 4
-	jr c, .Bad
-
-; Defense
-	ld a, [hli]
-	and $f
-	cp 10
-	jr c, .Bad
-
-; Speed
-	ld a, [hl]
-	cp 10 << 4
-	jr c, .Bad
-
-; Special
-	ld a, [hl]
-	and $f
-	cp 10
-	jr c, .Bad
-
-.Good:
-	scf
-	ret
-
-.Bad:
-	and a
-	ret
-
-Unreferenced_Function8aa4:
-	push de
-	push bc
-	ld hl, PalPacket_9ce6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	pop bc
-	pop de
-	ld a, c
-	ld [wSGBPals + 3], a
-	ld a, b
-	ld [wSGBPals + 4], a
-	ld a, e
-	ld [wSGBPals + 5], a
-	ld a, d
-	ld [wSGBPals + 6], a
-	ld hl, wSGBPals
-	call PushSGBPals_
-	ld hl, BlkPacket_9a86
-	call PushSGBPals_
-	ret
-
-InitPartyMenuPalettes:
-	ld hl, PalPacket_PartyMenu + 1
-	call CopyFourPalettes
-	call InitPartyMenuOBPals
-	call WipeAttrMap
-	ret
-
-; SGB layout for SCGB_PARTY_MENU_HP_PALS
-SGB_ApplyPartyMenuHPPals: ; 8ade
-	ld hl, wHPPals
-	ld a, [wSGBPals]
-	ld e, a
-	ld d, $0
-	add hl, de
-	ld e, l
-	ld d, h
-	ld a, [de]
-	and a
-	ld e, $5
-	jr z, .okay
-	dec a
-	ld e, $a
-	jr z, .okay
-	ld e, $f
-.okay
-	push de
-	ld hl, wSGBPals + 10
-	ld bc, $6
-	ld a, [wSGBPals]
-	call AddNTimes
-	pop de
-	ld [hl], e
-	ret
-
-Unreferenced_Function8b07:
-	call CheckCGB
-	ret z
-; CGB only
-	ld hl, .BGPal
-	ld de, wBGPals1
-	ld bc, 1 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-
-	ld hl, .OBPal
-	ld de, wOBPals1
-	ld bc, 1 palettes
-	ld a, BANK(wOBPals1)
-	call FarCopyWRAM
-
-	call ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-
-.BGPal:
-	RGB 31, 31, 31
-	RGB 18, 23, 31
-	RGB 15, 20, 31
-	RGB 00, 00, 00
-
-.OBPal:
-	RGB 31, 31, 31
-	RGB 31, 31, 12
-	RGB 08, 16, 28
-	RGB 00, 00, 00
-
-Unreferenced_Function8b3f:
-	call CheckCGB
-	ret nz
-	ld a, [hSGB]
-	and a
-	ret z
-	ld hl, BlkPacket_9a86
-	jp PushSGBPals_
-
-Unreferenced_Function8b4d:
-	call CheckCGB
-	jr nz, .cgb
-	ld a, [hSGB]
-	and a
-	ret z
-	ld hl, PalPacket_Function8b4d
-	jp PushSGBPals_
-
-.cgb
-	ld de, wOBPals1
-	ld a, PREDEFPAL_3B
-	call GetPredefPal
-	jp LoadHLPaletteIntoDE
-
-Unreferenced_Function8b67:
-	call CheckCGB
-	jr nz, .cgb
-	ld a, [hSGB]
-	and a
-	ret z
-	ld hl, PalPacket_Pack
-	jp PushSGBPals_
-
-.cgb
-	ld de, wOBPals1
-	ld a, PREDEFPAL_PACK
-	call GetPredefPal
-	jp LoadHLPaletteIntoDE
-
-Unreferenced_Function8b81:
-	call CheckCGB
-	jr nz, .cgb
-	ld a, [hSGB]
-	and a
-	ret z
-	ld a, c
-	push af
-	ld hl, PalPacket_9ce6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	pop af
-	call GetMonPalettePointer_
-	ld a, [hli]
-	ld [wSGBPals + 3], a
-	ld a, [hli]
-	ld [wSGBPals + 4], a
-	ld a, [hli]
-	ld [wSGBPals + 5], a
-	ld a, [hl]
-	ld [wSGBPals + 6], a
-	ld hl, wSGBPals
-	jp PushSGBPals_
-
-.cgb
-	ld de, wOBPals1
-	ld a, c
-	call GetMonPalettePointer_
-	call LoadPalette_White_Col1_Col2_Black
-	ret
-
-LoadTrainerClassPaletteAsNthBGPal:
-	ld a, [wTrainerClass]
-	call GetTrainerPalettePointer
-	ld a, e
-	jr got_palette_pointer_8bd7
-
-LoadMonPaletteAsNthBGPal:
-	ld a, [wCurPartySpecies]
-	call GetMonPalettePointer
-	ld a, e
-	bit 7, a
-	jr z, got_palette_pointer_8bd7
-	and $7f
-	inc hl
-	inc hl
-	inc hl
-	inc hl
-
-got_palette_pointer_8bd7
-	push hl
-	ld hl, wBGPals1
-	ld de, 1 palettes
-.loop
-	and a
-	jr z, .got_addr
-	add hl, de
-	dec a
-	jr .loop
-
-.got_addr
-	ld e, l
-	ld d, h
-	pop hl
-	call LoadPalette_White_Col1_Col2_Black
-	ret
-
-Unreferenced_Function8bec:
-	ld a, [hCGB]
-	and a
-	jr nz, .cgb
-	ld hl, wPlayerLightScreenCount
-	jp PushSGBPals_
-
-.cgb
-	ld a, [wEnemyLightScreenCount] ; col
-	ld c, a
-	ld a, [wEnemyReflectCount] ; row
-	hlcoord 0, 0, wAttrMap
-	ld de, SCREEN_WIDTH
-.loop
-	and a
-	jr z, .done
-	add hl, de
-	dec a
-	jr .loop
-
-.done
-	ld b, $0
-	add hl, bc
-	lb bc, 6, 4
-	ld a, [wEnemySafeguardCount] ; value
-	and $3
-	call FillBoxCGB
-	call CopyTilemapAtOnce
-	ret
-
-ApplyMonOrTrainerPals:
-	call CheckCGB
-	ret z
-	ld a, e
-	and a
-	jr z, .get_trainer
-	ld a, [wCurPartySpecies]
-	call GetMonPalettePointer_
-	jr .load_palettes
-
-.get_trainer
-	ld a, [wTrainerClass]
-	call GetTrainerPalettePointer
-
-.load_palettes
-	ld de, wBGPals1
-	call LoadPalette_White_Col1_Col2_Black
-	call WipeAttrMap
-	call ApplyAttrMap
-	call ApplyPals
-	ret
-
-ApplyHPBarPals:
-	ld a, [wWhichHPBar]
-	and a
-	jr z, .Enemy
-	cp $1
-	jr z, .Player
-	cp $2
-	jr z, .PartyMenu
-	ret
-
-.Enemy:
-	ld de, wBGPals2 palette PAL_BATTLE_BG_ENEMY_HP color 1
-	jr .okay
-
-.Player:
-	ld de, wBGPals2 palette PAL_BATTLE_BG_PLAYER_HP color 1
-
-.okay
-	ld l, c
-	ld h, $0
-	add hl, hl
-	add hl, hl
-	ld bc, HPBarPals
-	add hl, bc
-	ld bc, 4
-	ld a, BANK(wBGPals2)
-	call FarCopyWRAM
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-
-.PartyMenu:
-	ld e, c
-	inc e
-	hlcoord 11, 1, wAttrMap
-	ld bc, 2 * SCREEN_WIDTH
-	ld a, [wCurPartyMon]
-.loop
-	and a
-	jr z, .done
-	add hl, bc
-	dec a
-	jr .loop
-
-.done
-	lb bc, 2, 8
-	ld a, e
-	call FillBoxCGB
-	ret
-
-LoadStatsScreenPals:
-	call CheckCGB
-	ret z
-	ld hl, StatsScreenPals
-	ld b, 0
-	dec c
-	add hl, bc
-	add hl, bc
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld a, [hli]
-	ld [wBGPals1 palette 0], a
-	ld [wBGPals1 palette 2], a
-	ld a, [hl]
-	ld [wBGPals1 palette 0 + 1], a
-	ld [wBGPals1 palette 2 + 1], a
-	pop af
-	ld [rSVBK], a
-	call ApplyPals
-	ld a, $1
-	ret
-
-LoadMailPalettes:
-	ld l, e
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	add hl, hl
-	ld de, .MailPals
-	add hl, de
-	call CheckCGB
-	jr nz, .cgb
-	push hl
-	ld hl, PalPacket_9ce6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	pop hl
-	inc hl
-	inc hl
-	ld a, [hli]
-	ld [wSGBPals + 3], a
-	ld a, [hli]
-	ld [wSGBPals + 4], a
-	ld a, [hli]
-	ld [wSGBPals + 5], a
-	ld a, [hli]
-	ld [wSGBPals + 6], a
-	ld hl, wSGBPals
-	call PushSGBPals_
-	ld hl, BlkPacket_9a86
-	call PushSGBPals_
-	ret
-
-.cgb
-	ld de, wBGPals1
-	ld bc, 1 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	call ApplyPals
-	call WipeAttrMap
-	call ApplyAttrMap
-	ret
-
-.MailPals:
-INCLUDE "gfx/mail/mail.pal"
-
-INCLUDE "engine/cgb_layouts.asm"
-
-Unreferenced_Function95f0:
-	ld hl, .Palette
-	ld de, wBGPals1
-	ld bc, 1 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	call ApplyPals
-	call WipeAttrMap
-	call ApplyAttrMap
-	ret
-
-.Palette:
-	RGB 31, 31, 31
-	RGB 09, 31, 31
-	RGB 10, 12, 31
-	RGB 00, 03, 19
-
-CopyFourPalettes:
-	ld de, wBGPals1
-	ld c, 4
-
-CopyPalettes:
-.loop
-	push bc
-	ld a, [hli]
-	push hl
-	call GetPredefPal
-	call LoadHLPaletteIntoDE
-	pop hl
-	inc hl
-	pop bc
-	dec c
-	jr nz, .loop
-	ret
-
-GetPredefPal:
-	ld l, a
-	ld h, $0
-	add hl, hl
-	add hl, hl
-	add hl, hl
-	ld bc, PredefPals
-	add hl, bc
-	ret
-
-LoadHLPaletteIntoDE:
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wOBPals1)
-	ld [rSVBK], a
-	ld c, 1 palettes
-.loop
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec c
-	jr nz, .loop
-	pop af
-	ld [rSVBK], a
-	ret
-
-LoadPalette_White_Col1_Col2_Black:
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-
-	ld a, LOW(PALRGB_WHITE)
-	ld [de], a
-	inc de
-	ld a, HIGH(PALRGB_WHITE)
-	ld [de], a
-	inc de
-
-	ld c, 2 * PAL_COLOR_SIZE
-.loop
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec c
-	jr nz, .loop
-
-	xor a
-	ld [de], a
-	inc de
-	ld [de], a
-	inc de
-
-	pop af
-	ld [rSVBK], a
-	ret
-
-FillBoxCGB:
-.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
-
-ResetBGPals:
-	push af
-	push bc
-	push de
-	push hl
-
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-
-	ld hl, wBGPals1
-	ld c, 1 palettes
-.loop
-	ld a, $ff
-	ld [hli], a
-	ld [hli], a
-	ld [hli], a
-	ld [hli], a
-	xor a
-	ld [hli], a
-	ld [hli], a
-	ld [hli], a
-	ld [hli], a
-	dec c
-	jr nz, .loop
-
-	pop af
-	ld [rSVBK], a
-
-	pop hl
-	pop de
-	pop bc
-	pop af
-	ret
-
-WipeAttrMap:
-	hlcoord 0, 0, wAttrMap
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	xor a
-	call ByteFill
-	ret
-
-ApplyPals:
-	ld hl, wBGPals1
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	ld a, BANK(wGBCPalettes)
-	call FarCopyWRAM
-	ret
-
-ApplyAttrMap:
-	ld a, [rLCDC]
-	bit rLCDC_ENABLE, a
-	jr z, .UpdateVBank1
-	ld a, [hBGMapMode]
-	push af
-	ld a, $2
-	ld [hBGMapMode], a
-	call DelayFrame
-	call DelayFrame
-	call DelayFrame
-	call DelayFrame
-	pop af
-	ld [hBGMapMode], a
-	ret
-
-.UpdateVBank1:
-	hlcoord 0, 0, wAttrMap
-	debgcoord 0, 0
-	ld b, SCREEN_HEIGHT
-	ld a, $1
-	ld [rVBK], a
-.row
-	ld c, SCREEN_WIDTH
-.col
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec c
-	jr nz, .col
-	ld a, BG_MAP_WIDTH - SCREEN_WIDTH
-	add e
-	jr nc, .okay
-	inc d
-.okay
-	ld e, a
-	dec b
-	jr nz, .row
-	ld a, $0
-	ld [rVBK], a
-	ret
-
-; CGB layout for SCGB_PARTY_MENU_HP_PALS
-CGB_ApplyPartyMenuHPPals: ; 96f3
-	ld hl, wHPPals
-	ld a, [wSGBPals]
-	ld e, a
-	ld d, $0
-	add hl, de
-	ld e, l
-	ld d, h
-	ld a, [de]
-	inc a
-	ld e, a
-	hlcoord 11, 2, wAttrMap
-	ld bc, 2 * SCREEN_WIDTH
-	ld a, [wSGBPals]
-.loop
-	and a
-	jr z, .done
-	add hl, bc
-	dec a
-	jr .loop
-.done
-	lb bc, 2, 8
-	ld a, e
-	call FillBoxCGB
-	ret
-
-InitPartyMenuOBPals:
-	ld hl, PartyMenuOBPals
-	ld de, wOBPals1
-	ld bc, 2 palettes
-	ld a, BANK(wOBPals1)
-	call FarCopyWRAM
-	ret
-
-GetBattlemonBackpicPalettePointer:
-	push de
-	farcall GetPartyMonDVs
-	ld c, l
-	ld b, h
-	ld a, [wTempBattleMonSpecies]
-	call GetPlayerOrMonPalettePointer
-	pop de
-	ret
-
-GetEnemyFrontpicPalettePointer:
-	push de
-	farcall GetEnemyMonDVs
-	ld c, l
-	ld b, h
-	ld a, [wTempEnemyMonSpecies]
-	call GetFrontpicPalettePointer
-	pop de
-	ret
-
-GetPlayerOrMonPalettePointer:
-	and a
-	jp nz, GetMonNormalOrShinyPalettePointer
-	ld a, [wPlayerSpriteSetupFlags]
-	bit PLAYERSPRITESETUP_FEMALE_TO_MALE_F, a
-	jr nz, .male
-	ld a, [wPlayerGender]
-	and a
-	jr z, .male
-	ld hl, KrisPalette
-	ret
-
-.male
-	ld hl, PlayerPalette
-	ret
-
-GetFrontpicPalettePointer:
-	and a
-	jp nz, GetMonNormalOrShinyPalettePointer
-	ld a, [wTrainerClass]
-
-GetTrainerPalettePointer:
-	ld l, a
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	ld bc, TrainerPalettes
-	add hl, bc
-	ret
-
-GetMonPalettePointer_:
-	call GetMonPalettePointer
-	ret
-
-Unreferenced_Function9779:
-	ret
-	call CheckCGB
-	ret z
-	ld hl, BattleObjectPals
-	ld a, $90
-	ld [rOBPI], a
-	ld c, 6 palettes
-.loop
-	ld a, [hli]
-	ld [rOBPD], a
-	dec c
-	jr nz, .loop
-	ld hl, BattleObjectPals
-	ld de, wOBPals1 palette 2
-	ld bc, 2 palettes
-	ld a, BANK(wOBPals1)
-	call FarCopyWRAM
-	ret
-
-BattleObjectPals:
-INCLUDE "gfx/battle_anims/battle_anims.pal"
-
-Unreferenced_Function97cc:
-	call CheckCGB
-	ret z
-	ld a, $90
-	ld [rOBPI], a
-	ld a, PREDEFPAL_TRADE_TUBE
-	call GetPredefPal
-	call .PushPalette
-	ld a, PREDEFPAL_RB_GREENMON
-	call GetPredefPal
-	call .PushPalette
-	ret
-
-.PushPalette:
-	ld c, 1 palettes
-.loop
-	ld a, [hli]
-	ld [rOBPD], a
-	dec c
-	jr nz, .loop
-	ret
-
-GetMonPalettePointer:
-	ld l, a
-	ld h, $0
-	add hl, hl
-	add hl, hl
-	add hl, hl
-	ld bc, PokemonPalettes
-	add hl, bc
-	ret
-
-GetMonNormalOrShinyPalettePointer:
-	push bc
-	call GetMonPalettePointer
-	pop bc
-	push hl
-	call CheckShininess
-	pop hl
-	ret nc
-rept 4
-	inc hl
-endr
-	ret
-
-PushSGBPals_:
-	ld a, [wcfbe]
-	push af
-	set 7, a
-	ld [wcfbe], a
-	call PushSGBPals
-	pop af
-	ld [wcfbe], a
-	ret
-
-PushSGBPals:
-	ld a, [hl]
-	and $7
-	ret z
-	ld b, a
-.loop
-	push bc
-	xor a
-	ld [rJOYP], a
-	ld a, $30
-	ld [rJOYP], a
-	ld b, $10
-.loop2
-	ld e, $8
-	ld a, [hli]
-	ld d, a
-.loop3
-	bit 0, d
-	ld a, $10
-	jr nz, .okay
-	ld a, $20
-.okay
-	ld [rJOYP], a
-	ld a, $30
-	ld [rJOYP], a
-	rr d
-	dec e
-	jr nz, .loop3
-	dec b
-	jr nz, .loop2
-	ld a, $20
-	ld [rJOYP], a
-	ld a, $30
-	ld [rJOYP], a
-	call SGBDelayCycles
-	pop bc
-	dec b
-	jr nz, .loop
-	ret
-
-InitSGBBorder:
-	call CheckCGB
-	ret nz
-; SGB/DMG only
-	di
-	ld a, [wcfbe]
-	push af
-	set 7, a
-	ld [wcfbe], a
-	xor a
-	ld [rJOYP], a
-	ld [hSGB], a
-	call PushSGBBorderPalsAndWait
-	jr nc, .skip
-	ld a, $1
-	ld [hSGB], a
-	call _InitSGBBorderPals
-	call SGBBorder_PushBGPals
-	call SGBDelayCycles
-	call SGB_ClearVRAM
-	call PushSGBBorder
-	call SGBDelayCycles
-	call SGB_ClearVRAM
-	ld hl, MaskEnCancelPacket
-	call PushSGBPals
-
-.skip
-	pop af
-	ld [wcfbe], a
-	ei
-	ret
-
-InitCGBPals::
-	call CheckCGB
-	ret z
-; CGB only
-	ld a, BANK(vTiles3)
-	ld [rVBK], a
-	ld hl, vTiles3
-	ld bc, $200 tiles
-	xor a
-	call ByteFill
-	ld a, BANK(vTiles0)
-	ld [rVBK], a
-	ld a, 1 << rBGPI_AUTO_INCREMENT
-	ld [rBGPI], a
-	ld c, 4 * 8
-.bgpals_loop
-	ld a, LOW(PALRGB_WHITE)
-	ld [rBGPD], a
-	ld a, HIGH(PALRGB_WHITE)
-	ld [rBGPD], a
-	dec c
-	jr nz, .bgpals_loop
-	ld a, 1 << rOBPI_AUTO_INCREMENT
-	ld [rOBPI], a
-	ld c, 4 * 8
-.obpals_loop
-	ld a, LOW(PALRGB_WHITE)
-	ld [rOBPD], a
-	ld a, HIGH(PALRGB_WHITE)
-	ld [rOBPD], a
-	dec c
-	jr nz, .obpals_loop
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld hl, wBGPals1
-	call .LoadWhitePals
-	ld hl, wBGPals2
-	call .LoadWhitePals
-	pop af
-	ld [rSVBK], a
-	ret
-
-.LoadWhitePals:
-	ld c, 4 * 16
-.loop
-	ld a, LOW(PALRGB_WHITE)
-	ld [hli], a
-	ld a, HIGH(PALRGB_WHITE)
-	ld [hli], a
-	dec c
-	jr nz, .loop
-	ret
-
-_InitSGBBorderPals:
-	ld hl, .PacketPointerTable
-	ld c, 9
-.loop
-	push bc
-	ld a, [hli]
-	push hl
-	ld h, [hl]
-	ld l, a
-	call PushSGBPals
-	pop hl
-	inc hl
-	pop bc
-	dec c
-	jr nz, .loop
-	ret
-
-.PacketPointerTable:
-	dw MaskEnFreezePacket
-	dw DataSndPacket1
-	dw DataSndPacket2
-	dw DataSndPacket3
-	dw DataSndPacket4
-	dw DataSndPacket5
-	dw DataSndPacket6
-	dw DataSndPacket7
-	dw DataSndPacket8
-
-Unreferenced_Function9911:
-	di
-	xor a
-	ld [rJOYP], a
-	ld hl, MaskEnFreezePacket
-	call PushSGBPals
-	call PushSGBBorder
-	call SGBDelayCycles
-	call SGB_ClearVRAM
-	ld hl, MaskEnCancelPacket
-	call PushSGBPals
-	ei
-	ret
-
-PushSGBBorder:
-	call .LoadSGBBorderPointers
-	push de
-	call SGBBorder_YetMorePalPushing
-	pop hl
-	call SGBBorder_MorePalPushing
-	ret
-
-.LoadSGBBorderPointers:
-	ld hl, SGBBorder
-	ld de, SGBBorderMap
-	ret
-
-SGB_ClearVRAM:
-	ld hl, VRAM_Begin
-	ld bc, VRAM_End - VRAM_Begin
-	xor a
-	call ByteFill
-	ret
-
-PushSGBBorderPalsAndWait:
-	ld hl, MltReq2Packet
-	call PushSGBPals
-	call SGBDelayCycles
-	ld a, [rJOYP]
-	and $3
-	cp $3
-	jr nz, .carry
-	ld a, $20
-	ld [rJOYP], a
-	ld a, [rJOYP]
-	ld a, [rJOYP]
-	call SGBDelayCycles
-	call SGBDelayCycles
-	ld a, $30
-	ld [rJOYP], a
-	call SGBDelayCycles
-	call SGBDelayCycles
-	ld a, $10
-	ld [rJOYP], a
-rept 6
-	ld a, [rJOYP]
-endr
-	call SGBDelayCycles
-	call SGBDelayCycles
-	ld a, $30
-	ld [rJOYP], a
-	ld a, [rJOYP]
-	ld a, [rJOYP]
-	ld a, [rJOYP]
-	call SGBDelayCycles
-	call SGBDelayCycles
-	ld a, [rJOYP]
-	and $3
-	cp $3
-	jr nz, .carry
-	call .FinalPush
-	and a
-	ret
-
-.carry
-	call .FinalPush
-	scf
-	ret
-
-.FinalPush:
-	ld hl, MltReq1Packet
-	call PushSGBPals
-	jp SGBDelayCycles
-
-SGBBorder_PushBGPals:
-	call DisableLCD
-	ld a, %11100100
-	ld [rBGP], a
-	ld hl, PredefPals
-	ld de, vTiles1
-	ld bc, $100 tiles
-	call CopyData
-	call DrawDefaultTiles
-	ld a, LCDC_DEFAULT
-	ld [rLCDC], a
-	ld hl, PalTrnPacket
-	call PushSGBPals
-	xor a
-	ld [rBGP], a
-	ret
-
-SGBBorder_MorePalPushing:
-	call DisableLCD
-	ld a, $e4
-	ld [rBGP], a
-	ld de, vTiles1
-	ld bc, 20 tiles
-	call CopyData
-	ld b, 18
-.loop
-	push bc
-	ld bc, $c
-	call CopyData
-	ld bc, $28
-	call ClearBytes
-	ld bc, $c
-	call CopyData
-	pop bc
-	dec b
-	jr nz, .loop
-	ld bc, $140
-	call CopyData
-	ld bc, Start
-	call ClearBytes
-	ld bc, 16 palettes
-	call CopyData
-	call DrawDefaultTiles
-	ld a, LCDC_DEFAULT
-	ld [rLCDC], a
-	ld hl, PctTrnPacket
-	call PushSGBPals
-	xor a
-	ld [rBGP], a
-	ret
-
-SGBBorder_YetMorePalPushing:
-	call DisableLCD
-	ld a, %11100100
-	ld [rBGP], a
-	ld de, vTiles1
-	ld b, $80
-.loop
-	push bc
-	ld bc, 1 tiles
-	call CopyData
-	ld bc, 1 tiles
-	call ClearBytes
-	pop bc
-	dec b
-	jr nz, .loop
-	call DrawDefaultTiles
-	ld a, LCDC_DEFAULT
-	ld [rLCDC], a
-	ld hl, ChrTrnPacket
-	call PushSGBPals
-	xor a
-	ld [rBGP], a
-	ret
-
-CopyData: ; 0x9a52
-; copy bc bytes of data from hl to de
-.loop
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec bc
-	ld a, c
-	or b
-	jr nz, .loop
-	ret
-; 0x9a5b
-
-ClearBytes: ; 0x9a5b
-; clear bc bytes of data starting from de
-.loop
-	xor a
-	ld [de], a
-	inc de
-	dec bc
-	ld a, c
-	or b
-	jr nz, .loop
-	ret
-; 0x9a64
-
-DrawDefaultTiles: ; 0x9a64
-; Draw 240 tiles (2/3 of the screen) from tiles in VRAM
-	hlbgcoord 0, 0 ; BG Map 0
-	ld de, BG_MAP_WIDTH - SCREEN_WIDTH
-	ld a, $80 ; starting tile
-	ld c, 12 + 1
-.line
-	ld b, 20
-.tile
-	ld [hli], a
-	inc a
-	dec b
-	jr nz, .tile
-; next line
-	add hl, de
-	dec c
-	jr nz, .line
-	ret
-; 0x9a7a
-
-SGBDelayCycles:
-	ld de, 7000
-.wait
-	nop
-	nop
-	nop
-	dec de
-	ld a, d
-	or e
-	jr nz, .wait
-	ret
-
-INCLUDE "gfx/sgb/blk_packets.asm"
-INCLUDE "gfx/sgb/pal_packets.asm"
-INCLUDE "data/sgb_ctrl_packets.asm"
-
-PredefPals:
-INCLUDE "gfx/sgb/predef.pal"
-
-SGBBorderMap:
-; interleaved tile ids and palette ids
-INCBIN "gfx/sgb/sgb_border.bin"
-
-SGBBorderPalettes:
-INCLUDE "gfx/sgb/sgb_border.pal"
-
-SGBBorder:
-INCBIN "gfx/sgb/sgb_border.2bpp"
-
-HPBarPals:
-INCLUDE "gfx/battle/hp_bar.pal"
-
-ExpBarPalette:
-INCLUDE "gfx/battle/exp_bar.pal"
-
-INCLUDE "data/pokemon/palettes.asm"
-
-INCLUDE "data/trainers/palettes.asm"
-
-LoadMapPals:
-	farcall LoadSpecialMapPalette
-	jr c, .got_pals
-
-	; Which palette group is based on whether we're outside or inside
-	ld a, [wEnvironment]
-	and 7
-	ld e, a
-	ld d, 0
-	ld hl, EnvironmentColorsPointers
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	; Futher refine by time of day
-	ld a, [wTimeOfDayPal]
-	maskbits NUM_DAYTIMES
-	add a
-	add a
-	add a
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld e, l
-	ld d, h
-	; Switch to palettes WRAM bank
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld hl, wBGPals1
-	ld b, 8
-.outer_loop
-	ld a, [de] ; lookup index for TilesetBGPalette
-	push de
-	push hl
-	ld l, a
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	add hl, hl
-	ld de, TilesetBGPalette
-	add hl, de
-	ld e, l
-	ld d, h
-	pop hl
-	ld c, 1 palettes
-.inner_loop
-	ld a, [de]
-	inc de
-	ld [hli], a
-	dec c
-	jr nz, .inner_loop
-	pop de
-	inc de
-	dec b
-	jr nz, .outer_loop
-	pop af
-	ld [rSVBK], a
-
-.got_pals
-	ld a, [wTimeOfDayPal]
-	maskbits NUM_DAYTIMES
-	ld bc, 8 palettes
-	ld hl, MapObjectPals
-	call AddNTimes
-	ld de, wOBPals1
-	ld bc, 8 palettes
-	ld a, BANK(wOBPals1)
-	call FarCopyWRAM
-
-	ld a, [wEnvironment]
-	cp TOWN
-	jr z, .outside
-	cp ROUTE
-	ret nz
-.outside
-	ld a, [wMapGroup]
-	ld l, a
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	add hl, hl
-	ld de, RoofPals
-	add hl, de
-	ld a, [wTimeOfDayPal]
-	maskbits NUM_DAYTIMES
-	cp NITE_F
-	jr c, .morn_day
-rept 4
-	inc hl
-endr
-.morn_day
-	ld de, wBGPals1 palette PAL_BG_ROOF color 1
-	ld bc, 4
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	ret
-
-INCLUDE "data/maps/environment_colors.asm"
-
-PartyMenuBGMobilePalette:
-INCLUDE "gfx/stats/party_menu_bg_mobile.pal"
-
-PartyMenuBGPalette:
-INCLUDE "gfx/stats/party_menu_bg.pal"
-
-TilesetBGPalette:
-INCLUDE "gfx/tilesets/bg_tiles.pal"
-
-MapObjectPals::
-INCLUDE "gfx/overworld/npc_sprites.pal"
-
-RoofPals:
-INCLUDE "gfx/tilesets/roofs.pal"
-
-DiplomaPalettes:
-INCLUDE "gfx/diploma/diploma.pal"
-
-PartyMenuOBPals:
-INCLUDE "gfx/stats/party_menu_ob.pal"
-
-UnusedGSTitleBGPals:
-INCLUDE "gfx/title/unused_gs_bg.pal"
-
-UnusedGSTitleOBPals:
-INCLUDE "gfx/title/unused_gs_fg.pal"
-
-MalePokegearPals:
-INCLUDE "gfx/pokegear/pokegear.pal"
-
-FemalePokegearPals:
-INCLUDE "gfx/pokegear/pokegear_f.pal"
-
-Palettes_SCGB_11:
-INCLUDE "gfx/unknown/b789.pal"
-
-SlotMachinePals:
-INCLUDE "gfx/slots/slots.pal"
--- a/engine/credits.asm
+++ /dev/null
@@ -1,621 +1,0 @@
-INCLUDE "constants.asm"
-
-
-SECTION "Credits", ROMX
-
-Credits:: ; 109847
-	bit 6, b ; Hall Of Fame
-	ld a, $0
-	jr z, .okay
-	ld a, $40
-.okay
-	ld [wJumptableIndex], a
-
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wGBCPalettes)
-	ld [rSVBK], a
-
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-
-	ld hl, wCreditsFaux2bpp
-	ld c, $80
-	ld de, $ff00
-
-.load_loop
-	ld a, e
-	ld [hli], a
-	ld a, d
-	ld [hli], a
-	dec c
-	jr nz, .load_loop
-
-	ld de, CreditsBorderGFX
-	ld hl, vTiles2 tile $20
-	lb bc, BANK(CreditsBorderGFX), 9
-	call Request2bpp
-
-	ld de, CopyrightGFX
-	ld hl, vTiles2 tile $60
-	lb bc, BANK(CopyrightGFX), 29
-	call Request2bpp
-
-	ld de, TheEndGFX
-	ld hl, vTiles2 tile $40
-	lb bc, BANK(TheEndGFX), 16
-	call Request2bpp
-
-	ld a, $ff
-	ld [wCreditsBorderFrame], a
-	xor a
-	ld [wCreditsBorderMon], a
-
-	call Credits_LoadBorderGFX
-	ld e, l
-	ld d, h
-	ld hl, vTiles2
-	lb bc, BANK(CreditsMonsGFX), 16
-	call Request2bpp
-
-	call ConstructCreditsTilemap
-	xor a
-	ld [wCreditsLYOverride], a
-
-	ld hl, wLYOverrides
-	ld bc, $100
-	xor a
-	call ByteFill
-
-	ld a, rSCX - $ff00
-	ld [hLCDCPointer], a
-
-	call GetCreditsPalette
-	call SetPalettes
-	ld a, [hVBlank]
-	push af
-	ld a, $5
-	ld [hVBlank], a
-	ld a, $1
-	ld [hInMenu], a
-	xor a
-	ld [hBGMapMode], a
-	ld [wCreditsPos], a
-	ld [wCreditsUnusedCD21], a
-	ld [wCreditsTimer], a
-
-.execution_loop
-	call Credits_HandleBButton
-	call Credits_HandleAButton
-	jr nz, .exit_credits
-
-	call Credits_Jumptable
-	call DelayFrame
-	jr .execution_loop
-
-.exit_credits
-	call ClearBGPalettes
-	xor a
-	ld [hLCDCPointer], a
-	ld [hBGMapAddress], a
-	pop af
-	ld [hVBlank], a
-	pop af
-	ld [rSVBK], a
-	ret
-; 1098fd
-
-Credits_HandleAButton: ; 1098fd
-	ld a, [hJoypadDown]
-	and A_BUTTON
-	ret z
-	ld a, [wJumptableIndex]
-	bit 7, a
-	ret
-; 109908
-
-Credits_HandleBButton: ; 109908
-	ld a, [hJoypadDown]
-	and B_BUTTON
-	ret z
-	ld a, [wJumptableIndex]
-	bit 6, a
-	ret z
-	ld hl, wCreditsPos
-	ld a, [hli]
-	cp $d
-	jr nc, .okay
-	ld a, [hli]
-	and a
-	ret z
-.okay
-	ld hl, wCreditsTimer
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-	ret
-; 109926
-
-Credits_Jumptable: ; 109926
-	ld a, [wJumptableIndex]
-	and $f
-	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
-; 109937
-
-.Jumptable: ; 109937 (42:5937)
-	dw ParseCredits
-	dw Credits_Next
-	dw Credits_Next
-	dw Credits_PrepBGMapUpdate
-	dw Credits_UpdateGFXRequestPath
-	dw Credits_RequestGFX
-	dw Credits_LYOverride
-	dw Credits_Next
-	dw Credits_Next
-	dw Credits_Next
-	dw Credits_UpdateGFXRequestPath
-	dw Credits_RequestGFX
-	dw Credits_LoopBack
-
-Credits_Next: ; 109951 (42:5951)
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-Credits_LoopBack: ; 109956 (42:5956)
-	ld hl, wJumptableIndex
-	ld a, [hl]
-	and $f0
-	ld [hl], a
-	ret
-
-Credits_PrepBGMapUpdate: ; 10995e (42:595e)
-	xor a
-	ld [hBGMapMode], a
-	jp Credits_Next
-
-Credits_UpdateGFXRequestPath: ; 109964 (42:5964)
-	call Credits_LoadBorderGFX
-	ld a, l
-	ld [wRequested2bppSource], a
-	ld a, h
-	ld [wRequested2bppSource + 1], a
-	ld a, LOW(vTiles2)
-	ld [wRequested2bppDest], a
-	ld a, HIGH(vTiles2)
-	ld [wRequested2bppDest + 1], a
-	jr Credits_RequestGFX
-
-Credits_RequestGFX: ; 10997b (42:597b)
-	xor a
-	ld [hBGMapMode], a
-	ld a, $8
-	ld [wRequested2bpp], a
-	jp Credits_Next
-
-Credits_LYOverride: ; 109986 (42:5986)
-	ld a, [rLY]
-	cp $30
-	jr c, Credits_LYOverride
-	ld a, [wCreditsLYOverride]
-	dec a
-	dec a
-	ld [wCreditsLYOverride], a
-	ld hl, wLYOverrides + $1f
-	call .Fill
-	ld hl, wLYOverrides + $87
-	call .Fill
-	jp Credits_Next
-
-.Fill: ; 1099a3 (42:59a3)
-	ld c, $8
-.loop
-	ld [hli], a
-	dec c
-	jr nz, .loop
-	ret
-; 1099aa
-
-
-ParseCredits: ; 1099aa
-	ld hl, wJumptableIndex
-	bit 7, [hl]
-	jp nz, .done
-
-; Wait until the timer has run out to parse the next command.
-	ld hl, wCreditsTimer
-	ld a, [hl]
-	and a
-	jr z, .parse
-
-; One tick has passed.
-	dec [hl]
-	jp .done
-
-.parse
-; First, let's clear the current text display,
-; starting from line 5.
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 0, 5
-	ld bc, 20 * 12
-	ld a, " "
-	call ByteFill
-
-; Then read the script.
-
-.loop
-	call .get
-
-; Commands:
-	cp CREDITS_END
-	jp z, .end
-	cp CREDITS_WAIT
-	jr z, .wait
-	cp CREDITS_SCENE
-	jr z, .scene
-	cp CREDITS_CLEAR
-	jr z, .clear
-	cp CREDITS_MUSIC
-	jr z, .music
-	cp CREDITS_WAIT2
-	jr z, .wait2
-	cp CREDITS_THEEND
-	jr z, .theend
-
-; If it's not a command, it's a string identifier.
-
-	push af
-	ld e, a
-	ld d, 0
-	ld hl, CreditsStrings
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-	pop af
-
-; Strings spanning multiple lines have special cases.
-
-	cp COPYRIGHT
-	jr z, .copyright
-
-	cp STAFF
-	jr c, .staff
-
-; The rest start from line 6.
-
-	hlcoord 0, 6
-	jr .print
-
-.copyright
-	hlcoord 2, 6
-	jr .print
-
-.staff
-	hlcoord 0, 6
-
-.print
-; Print strings spaced every two lines.
-	call .get
-	ld bc, 20 * 2
-	call AddNTimes
-	call PlaceString
-	jr .loop
-
-.theend
-; Display "The End" graphic.
-	call Credits_TheEnd
-	jr .loop
-
-.scene
-; Update the scene number and corresponding palette.
-	call .get
-	ld [wCreditsBorderMon], a ; scene
-	xor a
-	ld [wCreditsBorderFrame], a ; frame
-	call GetCreditsPalette
-	call SetPalettes ; update hw pal registers
-	jr .loop
-
-.clear
-; Clear the banner.
-	ld a, $ff
-	ld [wCreditsBorderFrame], a ; frame
-	jr .loop
-
-.music
-; Play the credits music.
-	ld de, MUSIC_CREDITS
-	push de
-	ld de, MUSIC_NONE
-	call PlayMusic
-	call DelayFrame
-	pop de
-	call PlayMusic
-	jp .loop
-
-.wait2
-; Wait for some amount of ticks.
-	call .get
-	ld [wCreditsTimer], a
-	jr .done
-
-.wait
-; Wait for some amount of ticks, and do something else.
-	call .get
-	ld [wCreditsTimer], a
-
-	xor a
-	ld [hBGMapThird], a
-	ld a, 1
-	ld [hBGMapMode], a
-
-.done
-	jp Credits_Next
-
-.end
-; Stop execution.
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ld a, 32
-	ld [wMusicFade], a
-	ld a, LOW(MUSIC_POST_CREDITS)
-	ld [wMusicFadeID], a
-	ld a, HIGH(MUSIC_POST_CREDITS)
-	ld [wMusicFadeID + 1], a
-	ret
-
-.get
-; Get byte wCreditsPos from CreditsScript
-	push hl
-	push de
-	ld a, [wCreditsPos]
-	ld e, a
-	ld a, [wCreditsPos+1]
-	ld d, a
-	ld hl, CreditsScript
-	add hl, de
-
-	inc de
-	ld a, e
-	ld [wCreditsPos], a
-	ld a, d
-	ld [wCreditsPos+1], a
-	ld a, [hl]
-	pop de
-	pop hl
-	ret
-; 109a95
-
-
-ConstructCreditsTilemap: ; 109a95 (42:5a95)
-	xor a
-	ld [hBGMapMode], a
-	ld a, $c
-	ld [hBGMapAddress], a
-
-	ld a, $28
-	hlcoord 0, 0
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	call ByteFill
-
-	ld a, $7f
-	hlcoord 0, 4
-	ld bc, (SCREEN_HEIGHT - 4) * SCREEN_WIDTH
-	call ByteFill
-
-	hlcoord 0, 4
-	ld a, $24
-	call DrawCreditsBorder
-
-	hlcoord 0, 17
-	ld a, $20
-	call DrawCreditsBorder
-
-	hlcoord 0, 0, wAttrMap
-	ld bc, 4 * SCREEN_WIDTH
-	xor a
-	call ByteFill
-
-	hlcoord 0, 4, wAttrMap
-	ld bc, SCREEN_WIDTH
-	ld a, $1
-	call ByteFill
-
-	hlcoord 0, 5, wAttrMap
-	ld bc, 12 * SCREEN_WIDTH
-	ld a, $2
-	call ByteFill
-
-	hlcoord 0, 17, wAttrMap
-	ld bc, SCREEN_WIDTH
-	ld a, $1
-	call ByteFill
-
-	call WaitBGMap2
-	xor a
-	ld [hBGMapMode], a
-	ld [hBGMapAddress], a
-	hlcoord 0, 0
-	call .InitTopPortion
-	call WaitBGMap2
-	ret
-
-.InitTopPortion: ; 109aff (42:5aff)
-	ld b, 5
-.outer_loop
-	push hl
-	ld de, SCREEN_WIDTH - 3
-	ld c, 4
-	xor a
-.inner_loop
-rept 3
-	ld [hli], a
-	inc a
-endr
-	ld [hl], a
-	inc a
-	add hl, de
-	dec c
-	jr nz, .inner_loop
-	pop hl
-rept 4
-	inc hl
-endr
-	dec b
-	jr nz, .outer_loop
-	ret
-
-DrawCreditsBorder: ; 109b1d (42:5b1d)
-	ld c, SCREEN_WIDTH / 4
-.loop
-	push af
-rept 3
-	ld [hli], a
-	inc a
-endr
-	ld [hli], a
-	pop af
-	dec c
-	jr nz, .loop
-	ret
-
-GetCreditsPalette: ; 109b2c
-	call .GetPalAddress
-
-	push hl
-	ld a, 0
-	call .UpdatePals
-	pop hl
-	ret
-
-.GetPalAddress:
-; Each set of palette data is 24 bytes long.
-	ld a, [wCreditsBorderMon] ; scene
-	and %11
-	add a
-	add a ; * 8
-	add a
-	ld e, a
-	ld d, 0
-	ld hl, CreditsPalettes
-	add hl, de
-	add hl, de ; * 3
-	add hl, de
-	ret
-
-.UpdatePals:
-; Update the first three colors in both palette buffers.
-	push af
-	push hl
-	add LOW(wBGPals1)
-	ld e, a
-	ld a, 0
-	adc HIGH(wBGPals1)
-	ld d, a
-	ld bc, 24
-	call CopyBytes
-
-	pop hl
-	pop af
-	add LOW(wBGPals2)
-	ld e, a
-	ld a, 0
-	adc HIGH(wBGPals2)
-	ld d, a
-	ld bc, 24
-	call CopyBytes
-	ret
-
-CreditsPalettes:
-INCLUDE "gfx/credits/credits.pal"
-; 109bca
-
-Credits_LoadBorderGFX: ; 109bca (42:5bca)
-	ld hl, wCreditsBorderFrame
-	ld a, [hl]
-	cp $ff
-	jr z, .init
-
-	and %11
-	ld e, a
-	inc a
-	and %11
-	ld [hl], a
-	ld a, [wCreditsBorderMon]
-	and %11
-	add a
-	add a
-	add e
-	add a
-	ld e, a
-	ld d, 0
-	ld hl, .Frames
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ret
-
-.init
-	ld hl, wCreditsFaux2bpp
-	ret
-; 109bf1 (42:5bf1)
-
-.Frames: ; 109bf1
-	dw CreditsPichuGFX
-	dw CreditsPichuGFX     + 16 tiles
-	dw CreditsPichuGFX     + 32 tiles
-	dw CreditsPichuGFX     + 48 tiles
-	dw CreditsSmoochumGFX
-	dw CreditsSmoochumGFX  + 16 tiles
-	dw CreditsSmoochumGFX  + 32 tiles
-	dw CreditsSmoochumGFX  + 48 tiles
-	dw CreditsDittoGFX
-	dw CreditsDittoGFX     + 16 tiles
-	dw CreditsDittoGFX     + 32 tiles
-	dw CreditsDittoGFX     + 48 tiles
-	dw CreditsIgglybuffGFX
-	dw CreditsIgglybuffGFX + 16 tiles
-	dw CreditsIgglybuffGFX + 32 tiles
-	dw CreditsIgglybuffGFX + 48 tiles
-; 109c11
-
-Credits_TheEnd: ; 109c11 (42:5c11)
-	ld a, $40
-	hlcoord 6, 9
-	call .Load
-	hlcoord 6, 10
-.Load: ; 109c1c (42:5c1c)
-	ld c, 8
-.loop
-	ld [hli], a
-	inc a
-	dec c
-	jr nz, .loop
-	ret
-; 109c24 (42:5c24)
-
-
-CreditsBorderGFX:    INCBIN "gfx/credits/border.2bpp"
-
-CreditsMonsGFX:
-CreditsPichuGFX:     INCBIN "gfx/credits/pichu.2bpp"
-CreditsSmoochumGFX:  INCBIN "gfx/credits/smoochum.2bpp"
-CreditsDittoGFX:     INCBIN "gfx/credits/ditto.2bpp"
-CreditsIgglybuffGFX: INCBIN "gfx/credits/igglybuff.2bpp"
-
-INCLUDE "data/credits_script.asm"
-INCLUDE "data/credits_strings.asm"
--- a/engine/crystal_intro.asm
+++ /dev/null
@@ -1,2199 +1,0 @@
-Copyright_GFPresents: ; e4579
-	ld de, MUSIC_NONE
-	call PlayMusic
-	call ClearBGPalettes
-	call ClearTileMap
-	ld a, HIGH(vBGMap0)
-	ld [hBGMapAddress + 1], a
-	xor a ; LOW(vBGMap0)
-	ld [hBGMapAddress], a
-	ld [hJoyDown], a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld a, $90
-	ld [hWY], a
-	call WaitBGMap
-	ld b, SCGB_GAMEFREAK_LOGO
-	call GetSGBLayout
-	call SetPalettes
-	ld c, 10
-	call DelayFrames
-	callfar Copyright
-	call WaitBGMap
-	ld c, 100
-	call DelayFrames
-	call ClearTileMap
-	farcall GBCOnlyScreen
-	call .GetGFLogoGFX
-.joy_loop
-	call JoyTextDelay
-	ld a, [hJoyLast]
-	and BUTTONS
-	jr nz, .pressed_button
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .finish
-	call PlaceGameFreakPresents
-	farcall PlaySpriteAnimations
-	call DelayFrame
-	jr .joy_loop
-
-.pressed_button
-	call .StopGamefreakAnim
-	scf
-	ret
-
-.finish
-	call .StopGamefreakAnim
-	and a
-	ret
-; e45e8
-
-.GetGFLogoGFX: ; e45e8
-	ld de, GameFreakLogo
-	ld hl, vTiles2
-	lb bc, BANK(GameFreakLogo), 28
-	call Get1bpp
-
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wDecompressScratch)
-	ld [rSVBK], a
-
-	ld hl, IntroLogoGFX
-	ld de, wDecompressScratch
-	ld a, BANK(IntroLogoGFX)
-	call FarDecompress
-
-	ld hl, vTiles0
-	ld de, wDecompressScratch
-	lb bc, 1, 8 tiles
-	call Request2bpp
-
-	ld hl, vTiles1
-	ld de, wDecompressScratch + $80 tiles
-	lb bc, 1, 8 tiles
-	call Request2bpp
-
-	pop af
-	ld [rSVBK], a
-
-	farcall ClearSpriteAnims
-	depixel 10, 11, 4, 0
-	ld a, SPRITE_ANIM_INDEX_GAMEFREAK_LOGO
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], $a0
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $60
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld [hl], $30
-	xor a
-	ld [wJumptableIndex], a
-	ld [wIntroSceneFrameCounter], a
-	ld [wIntroSceneTimer], a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld a, $1
-	ld [hBGMapMode], a
-	ld a, $90
-	ld [hWY], a
-	lb de, %11100100, %11100100
-	call DmgToCgbObjPals
-	ret
-; e465e
-
-.StopGamefreakAnim: ; e465e
-	farcall ClearSpriteAnims
-	call ClearTileMap
-	call ClearSprites
-	ld c, 16
-	call DelayFrames
-	ret
-; e4670
-
-PlaceGameFreakPresents: ; e4670
-	ld a, [wJumptableIndex]
-	ld e, a
-	ld d, 0
-	ld hl, .dw
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-; e467f
-
-.dw ; e467f
-	dw PlaceGameFreakPresents_0
-	dw PlaceGameFreakPresents_1
-	dw PlaceGameFreakPresents_2
-	dw PlaceGameFreakPresents_3
-; e4687
-
-PlaceGameFreakPresents_AdvanceIndex: ; e4687
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-; e468c
-
-PlaceGameFreakPresents_0: ; e468c
-	ret
-; e468d
-
-PlaceGameFreakPresents_1: ; e468d
-	ld hl, wIntroSceneTimer
-	ld a, [hl]
-	cp $20
-	jr nc, .PlaceGameFreak
-	inc [hl]
-	ret
-
-.PlaceGameFreak:
-	ld [hl], 0
-	ld hl, .GAME_FREAK
-	decoord 5, 10
-	ld bc, .end - .GAME_FREAK
-	call CopyBytes
-	call PlaceGameFreakPresents_AdvanceIndex
-	ld de, SFX_GAME_FREAK_PRESENTS
-	call PlaySFX
-	ret
-; e46af
-
-.GAME_FREAK:
-	;  G  A  M  E   _  F  R  E  A  K
-	db 0, 1, 2, 3, 13, 4, 5, 3, 1, 6
-.end
-	db "@"
-; e46ba
-
-PlaceGameFreakPresents_2: ; e46ba
-	ld hl, wIntroSceneTimer
-	ld a, [hl]
-	cp $40
-	jr nc, .place_presents
-	inc [hl]
-	ret
-
-.place_presents
-	ld [hl], 0
-	ld hl, .presents
-	decoord 7, 11
-	ld bc, .end - .presents
-	call CopyBytes
-	call PlaceGameFreakPresents_AdvanceIndex
-	ret
-; e46d6
-
-.presents
-	db 7, 8, 9, 10, 11, 12
-.end
-	db "@"
-; e46dd
-
-PlaceGameFreakPresents_3: ; e46dd
-	ld hl, wIntroSceneTimer
-	ld a, [hl]
-	cp $80
-	jr nc, .finish
-	inc [hl]
-	ret
-
-.finish
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-; e46ed
-
-
-GameFreakLogoJumper: ; e46ed (39:46ed)
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld e, [hl]
-	ld d, 0
-	ld hl, GameFreakLogoScenes
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-GameFreakLogoScenes: ; e46fd (39:46fd)
-	dw GameFreakLogoScene1
-	dw GameFreakLogoScene2
-	dw GameFreakLogoScene3
-	dw GameFreakLogoScene4
-	dw GameFreakLogoScene5
-
-GameFreakLogoScene1: ; e4707 (39:4707)
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	inc [hl]
-	ret
-
-GameFreakLogoScene2: ; e470d (39:470d)
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .asm_e4747
-	ld d, a
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld a, [hl]
-	and %111111
-	cp %100000
-	jr nc, .asm_e4723
-	add %100000
-.asm_e4723
-	ld e, a
-	farcall BattleAnim_Sine_e
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], e
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld a, [hl]
-	dec [hl]
-	and $1f
-	ret nz
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	sub $30
-	ld [hl], a
-	ld de, SFX_DITTO_BOUNCE
-	call PlaySFX
-	ret
-
-.asm_e4747
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	inc [hl]
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld [hl], $0
-	ld de, SFX_DITTO_POP_UP
-	call PlaySFX
-	ret
-
-GameFreakLogoScene3: ; e4759 (39:4759)
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld a, [hl]
-	cp $20
-	jr nc, .asm_e4764
-	inc [hl]
-	ret
-
-.asm_e4764
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	inc [hl]
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld [hl], $0
-	ld de, SFX_DITTO_TRANSFORM
-	call PlaySFX
-	ret
-
-GameFreakLogoScene4: ; e4776 (39:4776)
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld a, [hl]
-	cp $40
-	jr z, .asm_e47a3
-	inc [hl]
-	srl a
-	srl a
-	ld e, a
-	ld d, $0
-	ld hl, GameFreakLogoPalettes
-	add hl, de
-	add hl, de
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wOBPals2)
-	ld [rSVBK], a
-	ld a, [hli]
-	ld [wOBPals2 + 12], a
-	ld a, [hli]
-	ld [wOBPals2 + 13], a
-	pop af
-	ld [rSVBK], a
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-
-.asm_e47a3
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	inc [hl]
-	call PlaceGameFreakPresents_AdvanceIndex
-GameFreakLogoScene5: ; e47ab (39:47ab)
-	ret
-; e47ac (39:47ac)
-
-GameFreakLogoPalettes: ; e47ac
-INCLUDE "gfx/intro/gamefreak_logo.pal"
-; e47cc
-
-GameFreakLogo: ; e47cc
-INCBIN "gfx/splash/logo1.1bpp"
-INCBIN "gfx/splash/logo2.1bpp"
-; e48ac
-
-CrystalIntro: ; e48ac
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wGBCPalettes)
-	ld [rSVBK], a
-	ld a, [hInMenu]
-	push af
-	ld a, [hVBlank]
-	push af
-	call .InitRAMAddrs
-.loop ; e48bc
-	call JoyTextDelay
-	ld a, [hJoyLast]
-	and BUTTONS
-	jr nz, .ShutOffMusic
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .done
-	call IntroSceneJumper
-	farcall PlaySpriteAnimations
-	call DelayFrame
-	jp .loop
-
-.ShutOffMusic:
-	ld de, MUSIC_NONE
-	call PlayMusic
-
-.done
-	call ClearBGPalettes
-	call ClearSprites
-	call ClearTileMap
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	pop af
-	ld [hVBlank], a
-	pop af
-	ld [hInMenu], a
-	pop af
-	ld [rSVBK], a
-	ret
-; e4901
-
-.InitRAMAddrs: ; e4901
-	xor a
-	ld [hVBlank], a
-	ld a, $1
-	ld [hInMenu], a
-	xor a
-	ld [hMapAnims], a
-	ld [wJumptableIndex], a
-	ret
-; e490f
-
-IntroSceneJumper: ; e490f
-	ld a, [wJumptableIndex]
-	ld e, a
-	ld d, 0
-	ld hl, IntroScenes
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-; e491e
-
-IntroScenes: ; e491e (39:491e)
-	dw IntroScene1
-	dw IntroScene2
-	dw IntroScene3
-	dw IntroScene4
-	dw IntroScene5
-	dw IntroScene6
-	dw IntroScene7
-	dw IntroScene8
-	dw IntroScene9
-	dw IntroScene10
-	dw IntroScene11
-	dw IntroScene12
-	dw IntroScene13
-	dw IntroScene14
-	dw IntroScene15
-	dw IntroScene16
-	dw IntroScene17
-	dw IntroScene18
-	dw IntroScene19
-	dw IntroScene20
-	dw IntroScene21
-	dw IntroScene22
-	dw IntroScene23
-	dw IntroScene24
-	dw IntroScene25
-	dw IntroScene26
-	dw IntroScene27
-	dw IntroScene28
-
-NextIntroScene: ; e4956 (39:4956)
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-IntroScene1: ; e495b (39:495b)
-; Setup the next scene.
-	call Intro_ClearBGPals
-	call ClearSprites
-	call ClearTileMap
-	xor a
-	ld [hBGMapMode], a
-	ld a, $1
-	ld [rVBK], a
-	ld hl, IntroTilemap001
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, $0
-	ld [rVBK], a
-	ld hl, IntroUnownsGFX
-	ld de, vTiles2 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-	ld hl, IntroPulseGFX
-	ld de, vTiles0 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-	ld hl, IntroTilemap002
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld hl, IntroPalette2
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	call CopyBytes
-	ld hl, IntroPalette2
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-	pop af
-	ld [rSVBK], a
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	farcall ClearSpriteAnims
-	call Intro_SetCGBPalUpdate
-	xor a
-	ld [wIntroSceneFrameCounter], a
-	ld [wIntroSceneTimer], a
-	call NextIntroScene
-	ret
-
-IntroScene2: ; e49d6 (39:49d6)
-; First Unown (A) fades in, pulses, then fades out.
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp $80
-	jr nc, .endscene
-	cp $60
-	jr nz, .DontPlaySound
-	push af
-	depixel 11, 11
-	call CrystalIntro_InitUnownAnim
-	ld de, SFX_INTRO_UNOWN_1
-	call PlaySFX
-	pop af
-.DontPlaySound:
-	ld [wIntroSceneTimer], a
-	xor a
-	call CrystalIntro_UnownFade
-	ret
-.endscene
-	call NextIntroScene
-	ret
-
-IntroScene3: ; e49fd (39:49fd)
-; More setup. Transition to the outdoor scene.
-	call Intro_ClearBGPals
-	call ClearSprites
-	call ClearTileMap
-	xor a
-	ld [hBGMapMode], a
-	ld a, $1
-	ld [rVBK], a
-	ld hl, IntroTilemap003
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, $0
-	ld [rVBK], a
-	ld hl, IntroBackgroundGFX
-	ld de, vTiles2 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-	ld hl, IntroTilemap004
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld hl, IntroPalette1
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	call CopyBytes
-	ld hl, IntroPalette1
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-	pop af
-	ld [rSVBK], a
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	call Intro_ResetLYOverrides
-	call Intro_SetCGBPalUpdate
-	xor a
-	ld [wIntroSceneFrameCounter], a
-	call NextIntroScene
-	ret
-
-IntroScene4: ; e4a69 (39:4a69)
-; Scroll the outdoor panorama for a bit.
-	call Intro_PerspectiveScrollBG
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	cp $80
-	jr z, .endscene
-	inc [hl]
-	ret
-
-.endscene
-	call NextIntroScene
-	ret
-
-IntroScene5: ; e4a7a (39:4a7a)
-; Go back to the Unown.
-	call Intro_ClearBGPals
-	call ClearSprites
-	call ClearTileMap
-	xor a
-	ld [hBGMapMode], a
-	ld [hLCDCPointer], a
-	ld a, $1
-	ld [rVBK], a
-	ld hl, IntroTilemap005
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, $0
-	ld [rVBK], a
-	ld hl, IntroUnownsGFX
-	ld de, vTiles2 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-	ld hl, IntroPulseGFX
-	ld de, vTiles0 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-	ld hl, IntroTilemap006
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld hl, IntroPalette2
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	call CopyBytes
-	ld hl, IntroPalette2
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-	pop af
-	ld [rSVBK], a
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	farcall ClearSpriteAnims
-	call Intro_SetCGBPalUpdate
-	xor a
-	ld [wIntroSceneFrameCounter], a
-	ld [wIntroSceneTimer], a
-	call NextIntroScene
-	ret
-
-IntroScene6: ; e4af7 (39:4af7)
-; Two more Unown (I, H) fade in.
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp $80
-	jr nc, .endscene
-	cp $60
-	jr z, .SecondUnown
-	cp $40
-	jr nc, .StopUnown
-	cp $20
-	jr z, .FirstUnown
-	jr .NoUnown
-
-.FirstUnown:
-	push af
-	depixel 7, 15
-	call CrystalIntro_InitUnownAnim
-	ld de, SFX_INTRO_UNOWN_2
-	call PlaySFX
-	pop af
-.NoUnown:
-	ld [wIntroSceneTimer], a
-	xor a
-	call CrystalIntro_UnownFade
-	ret
-
-.SecondUnown:
-	push af
-	depixel 14, 6
-	call CrystalIntro_InitUnownAnim
-	ld de, SFX_INTRO_UNOWN_1
-	call PlaySFX
-	pop af
-.StopUnown:
-	ld [wIntroSceneTimer], a
-	ld a, $1
-	call CrystalIntro_UnownFade
-	ret
-
-.endscene
-	call NextIntroScene
-	ret
-
-IntroScene7: ; e4b3f (39:4b3f)
-; Back to the outdoor scene.
-	call Intro_ClearBGPals
-	call ClearSprites
-	call ClearTileMap
-	xor a
-	ld [hBGMapMode], a
-
-	ld a, $1
-	ld [rVBK], a
-	ld hl, IntroTilemap003
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-
-	ld hl, IntroPichuWooperGFX
-	ld de, vTiles0 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-
-	ld a, $0
-	ld [rVBK], a
-	ld hl, IntroSuicuneRunGFX
-	ld de, vTiles0 tile $00
-	call Intro_DecompressRequest2bpp_255Tiles
-
-	ld hl, IntroBackgroundGFX
-	ld de, vTiles2 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-
-	ld hl, IntroTilemap004
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-
-	ld hl, IntroPalette1
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	call CopyBytes
-
-	ld hl, IntroPalette1
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-
-	pop af
-	ld [rSVBK], a
-
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	call Intro_ResetLYOverrides
-	farcall ClearSpriteAnims
-	depixel 13, 27, 4, 0
-	ld a, SPRITE_ANIM_INDEX_INTRO_SUICUNE
-	call _InitSpriteAnimStruct
-	ld a, $f0
-	ld [wGlobalAnimXOffset], a
-	call Intro_SetCGBPalUpdate
-	xor a
-	ld [wIntroSceneFrameCounter], a
-	ld [wIntroSceneTimer], a
-	call NextIntroScene
-	ret
-
-IntroScene8: ; e4bd3 (39:4bd3)
-; Scroll the scene, then show Suicune running across the screen.
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp $40
-	jr z, .suicune_sound
-	jr nc, .animate_suicune
-	call Intro_PerspectiveScrollBG
-	ret
-
-.suicune_sound
-	ld de, SFX_INTRO_SUICUNE_3
-	call PlaySFX
-.animate_suicune
-	ld a, [wGlobalAnimXOffset]
-	and a
-	jr z, .finish
-	sub $8
-	ld [wGlobalAnimXOffset], a
-	ret
-
-.finish
-	ld de, SFX_INTRO_SUICUNE_2
-	call PlaySFX
-	farcall DeinitializeAllSprites
-	call NextIntroScene
-	ret
-
-IntroScene9: ; e4c04 (39:4c04)
-; Set up the next scene (same bg).
-	xor a
-	ld [hLCDCPointer], a
-	call ClearSprites
-	hlcoord 0, 0, wAttrMap
-	; first 12 rows have palette 1
-	ld bc, 12 * SCREEN_WIDTH
-	ld a, $1
-	call ByteFill
-	; middle 3 rows have palette 2
-	ld bc, 3 * SCREEN_WIDTH
-	ld a, $2
-	call ByteFill
-	; last three rows have palette 3
-	ld bc, 3 * SCREEN_WIDTH
-	ld a, $3
-	call ByteFill
-	ld a, $2
-	ld [hBGMapMode], a
-	call DelayFrame
-	call DelayFrame
-	call DelayFrame
-	ld a, $c ; $980c
-	ld [hBGMapAddress], a
-	call DelayFrame
-	call DelayFrame
-	call DelayFrame
-	xor a
-	ld [hBGMapMode], a
-	ld [hBGMapAddress], a
-	ld [wGlobalAnimXOffset], a
-	xor a
-	ld [wIntroSceneFrameCounter], a
-	call NextIntroScene
-	ret
-
-IntroScene10: ; e4c4f (39:4c4f)
-; Wooper and Pichu enter.
-	call Intro_RustleGrass
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp $c0
-	jr z, .done
-	cp $20
-	jr z, .wooper
-	cp $40
-	jr z, .pichu
-	ret
-
-.pichu
-	depixel 21, 16, 1, 0
-	ld a, SPRITE_ANIM_INDEX_INTRO_PICHU
-	call _InitSpriteAnimStruct
-	ld de, SFX_INTRO_PICHU
-	call PlaySFX
-	ret
-
-.wooper
-	depixel 22, 6
-	ld a, SPRITE_ANIM_INDEX_INTRO_WOOPER
-	call _InitSpriteAnimStruct
-	ld de, SFX_INTRO_PICHU
-	call PlaySFX
-	ret
-.done
-	call NextIntroScene
-	ret
-
-IntroScene11: ; e4c86 (39:4c86)
-; Back to Unown again.
-	call Intro_ClearBGPals
-	call ClearSprites
-	call ClearTileMap
-	xor a
-	ld [hBGMapMode], a
-	ld [hLCDCPointer], a
-	ld a, $1
-	ld [rVBK], a
-	ld hl, IntroTilemap007
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, $0
-	ld [rVBK], a
-	ld hl, IntroUnownsGFX
-	ld de, vTiles2 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-	ld hl, IntroTilemap008
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld hl, IntroPalette2
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	call CopyBytes
-	ld hl, IntroPalette2
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-	pop af
-	ld [rSVBK], a
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	farcall ClearSpriteAnims
-	call Intro_SetCGBPalUpdate
-	xor a
-	ld [wIntroSceneFrameCounter], a
-	ld [wIntroSceneTimer], a
-	call NextIntroScene
-	ret
-
-IntroScene12: ; e4cfa (39:4cfa)
-; Even more Unown.
-	call .PlayUnownSound
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp $c0
-	jr nc, .done
-	cp $80
-	jr nc, .second_half
-; first half
-	ld c, a
-	and $1f
-	sla a
-	ld [wIntroSceneTimer], a
-	ld a, c
-	and $e0
-	srl a
-	swap a
-	call CrystalIntro_UnownFade
-	ret
-
-.second_half
-; double speed
-	ld c, a
-	and $f
-	sla a
-	sla a
-	ld [wIntroSceneTimer], a
-	ld a, c
-	and $70
-	or $40
-	swap a
-	call CrystalIntro_UnownFade
-	ret
-
-.done
-	call NextIntroScene
-	ret
-
-.PlayUnownSound: ; e4d36 (39:4d36)
-	ld a, [wIntroSceneFrameCounter]
-	ld c, a
-	ld hl, .UnownSounds
-.loop
-	ld a, [hli]
-	cp -1
-	ret z
-	cp c
-	jr z, .playsound
-	inc hl
-	inc hl
-	jr .loop
-.playsound
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-	push de
-	call SFXChannelsOff
-	pop de
-	call PlaySFX
-	ret
-; e4d54 (39:4d54)
-
-.UnownSounds: ; e4d54
-	dbw $00, SFX_INTRO_UNOWN_3
-	dbw $20, SFX_INTRO_UNOWN_2
-	dbw $40, SFX_INTRO_UNOWN_1
-	dbw $60, SFX_INTRO_UNOWN_2
-	dbw $80, SFX_INTRO_UNOWN_3
-	dbw $90, SFX_INTRO_UNOWN_2
-	dbw $a0, SFX_INTRO_UNOWN_1
-	dbw $b0, SFX_INTRO_UNOWN_2
-	db -1 ; e4d6d
-
-IntroScene13: ; e4d6d (39:4d6d)
-; Switch scenes again.
-	call Intro_ClearBGPals
-	call ClearSprites
-	call ClearTileMap
-	xor a
-	ld [hBGMapMode], a
-	ld a, $1
-	ld [rVBK], a
-	ld hl, IntroTilemap003
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, $0
-	ld [rVBK], a
-	ld hl, IntroSuicuneRunGFX
-	ld de, vTiles0 tile $00
-	call Intro_DecompressRequest2bpp_255Tiles
-	ld hl, IntroBackgroundGFX
-	ld de, vTiles2 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-	ld hl, IntroTilemap004
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld hl, IntroPalette1
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	call CopyBytes
-	ld hl, IntroPalette1
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-	pop af
-	ld [rSVBK], a
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	farcall ClearSpriteAnims
-	depixel 13, 11, 4, 0
-	ld a, SPRITE_ANIM_INDEX_INTRO_SUICUNE
-	call _InitSpriteAnimStruct
-	ld de, MUSIC_CRYSTAL_OPENING
-	call PlayMusic
-	xor a
-	ld [wGlobalAnimXOffset], a
-	call Intro_SetCGBPalUpdate
-	xor a
-	ld [wIntroSceneFrameCounter], a
-	ld [wIntroSceneTimer], a
-	call NextIntroScene
-	ret
-
-IntroScene14: ; e4dfa (39:4dfa)
-; Suicune runs then jumps.
-	ld a, [hSCX]
-	sub 10
-	ld [hSCX], a
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp $80
-	jr z, .done
-	cp $60
-	jr z, .jump
-	jr nc, .asm_e4e1a
-	cp $40
-	jr nc, .asm_e4e33
-	ret
-
-.jump
-	ld de, SFX_INTRO_SUICUNE_4
-	call PlaySFX
-
-.asm_e4e1a
-	ld a, $1
-	ld [wIntroSceneTimer], a
-	ld a, [wGlobalAnimXOffset]
-	cp $88
-	jr c, .asm_e4e2c
-	sub $8
-	ld [wGlobalAnimXOffset], a
-	ret
-
-.asm_e4e2c
-	farcall DeinitializeAllSprites
-	ret
-
-.asm_e4e33
-	ld a, [wGlobalAnimXOffset]
-	sub $2
-	ld [wGlobalAnimXOffset], a
-	ret
-
-.done
-	call NextIntroScene
-	ret
-
-IntroScene15: ; e4e40 (39:4e40)
-; Transition to a new scene.
-	call Intro_ClearBGPals
-	call ClearSprites
-	call ClearTileMap
-	xor a
-	ld [hBGMapMode], a
-	ld a, $1
-	ld [rVBK], a
-	ld hl, IntroTilemap009
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, $0
-	ld [rVBK], a
-	ld hl, IntroSuicuneJumpGFX
-	ld de, vTiles2 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-	ld hl, IntroUnownBackGFX
-	ld de, vTiles0 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-	ld de, IntroGrass4GFX
-	ld hl, vTiles1 tile $00
-	lb bc, BANK(IntroGrass4GFX), 1
-	call Request2bpp
-	ld hl, IntroTilemap010
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	call Intro_LoadTilemap
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld hl, IntroPalette5
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	call CopyBytes
-	ld hl, IntroPalette5
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-	pop af
-	ld [rSVBK], a
-	xor a
-	ld [hSCX], a
-	ld a, $90
-	ld [hSCY], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	farcall ClearSpriteAnims
-	call Intro_SetCGBPalUpdate
-	depixel 8, 5
-	ld a, SPRITE_ANIM_INDEX_INTRO_UNOWN_F
-	call _InitSpriteAnimStruct
-	depixel 12, 0
-	ld a, SPRITE_ANIM_INDEX_INTRO_SUICUNE_AWAY
-	call _InitSpriteAnimStruct
-	xor a
-	ld [wIntroSceneFrameCounter], a
-	ld [wIntroSceneTimer], a
-	call NextIntroScene
-	ret
-
-IntroScene16: ; e4edc (39:4edc)
-; Suicune shows its face. An Unown appears in front.
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp $80
-	jr nc, .done
-	call Intro_Scene16_AnimateSuicune
-	ld a, [hSCY]
-	and a
-	ret z
-	add 8
-	ld [hSCY], a
-	ret
-.done
-	call NextIntroScene
-	ret
-
-IntroScene17: ; e4ef5 (39:4ef5)
-; ...
-	call Intro_ClearBGPals
-	call ClearSprites
-	call ClearTileMap
-	xor a
-	ld [hBGMapMode], a
-	ld a, $1
-	ld [rVBK], a
-	ld hl, IntroTilemap011
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, $0
-	ld [rVBK], a
-	ld hl, IntroSuicuneCloseGFX
-	ld de, vTiles1 tile $00
-	call Intro_DecompressRequest2bpp_255Tiles
-	ld hl, IntroTilemap012
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld hl, IntroPalette4
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	call CopyBytes
-	ld hl, IntroPalette4
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-	pop af
-	ld [rSVBK], a
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	farcall ClearSpriteAnims
-	call Intro_SetCGBPalUpdate
-	xor a
-	ld [wIntroSceneFrameCounter], a
-	ld [wIntroSceneTimer], a
-	call NextIntroScene
-	ret
-
-IntroScene18: ; e4f67 (39:4f67)
-; Suicune close up.
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp $60
-	jr nc, .done
-	ld a, [hSCX]
-	cp $60
-	ret z
-	add 8
-	ld [hSCX], a
-	ret
-.done
-	call NextIntroScene
-	ret
-
-IntroScene19: ; e4f7e (39:4f7e)
-; More setup.
-	call Intro_ClearBGPals
-	call ClearSprites
-	call ClearTileMap
-	xor a
-	ld [hBGMapMode], a
-	ld a, $1
-	ld [rVBK], a
-	ld hl, IntroTilemap013
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, $0
-	ld [rVBK], a
-	ld hl, IntroSuicuneBackGFX
-	ld de, vTiles2 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-	ld hl, IntroUnownsGFX
-	ld de, vTiles1 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-	ld de, IntroGrass4GFX
-	ld hl, vTiles1 tile $7f
-	lb bc, BANK(IntroGrass4GFX), 1
-	call Request2bpp
-	ld hl, IntroTilemap014
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	call Intro_LoadTilemap
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld hl, IntroPalette5
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	call CopyBytes
-	ld hl, IntroPalette5
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-	pop af
-	ld [rSVBK], a
-	xor a
-	ld [hSCX], a
-	ld a, $d8
-	ld [hSCY], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	farcall ClearSpriteAnims
-	ld hl, wSpriteAnimDict
-	xor a
-	ld [hli], a
-	ld [hl], $7f
-	call Intro_SetCGBPalUpdate
-	depixel 12, 0
-	ld a, SPRITE_ANIM_INDEX_INTRO_SUICUNE_AWAY
-	call _InitSpriteAnimStruct
-	xor a
-	ld [wIntroSceneFrameCounter], a
-	ld [wIntroSceneTimer], a
-	call NextIntroScene
-	ret
-
-IntroScene20: ; e5019 (39:5019)
-; Suicune running away. A bunch of Unown appear.
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp $98
-	jr nc, .finished
-	cp $58
-	ret nc
-	cp $40
-	jr nc, .AppearUnown
-	cp $28
-	ret nc
-	ld a, [hSCY]
-	inc a
-	ld [hSCY], a
-	ret
-
-.AppearUnown:
-	sub $18
-	ld c, a
-	and $3
-	cp $3
-	ret nz
-	ld a, c
-	and $1c
-	srl a
-	srl a
-	ld [wIntroSceneTimer], a
-	xor a
-	call Intro_Scene20_AppearUnown
-	ret
-; e5049 (39:5049)
-; unused
-	ld a, c
-	and $1c
-	srl a
-	srl a
-	ld [wIntroSceneTimer], a
-	ld a, 1
-	call Intro_Scene20_AppearUnown
-	ret
-
-.finished
-	call NextIntroScene
-	ret
-
-IntroScene21: ; e505d (39:505d)
-; Suicune gets more distant and turns black.
-	call Intro_ColoredSuicuneFrameSwap
-	ld c, 3
-	call DelayFrames
-	xor a
-	ld [hBGMapMode], a
-	ld [wIntroSceneFrameCounter], a
-	ld [wIntroSceneTimer], a
-	call NextIntroScene
-	ret
-
-IntroScene22: ; e5072 (39:5072)
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp $8
-	jr nc, .done
-	ret
-.done
-	farcall DeinitializeAllSprites
-	call NextIntroScene
-	ret
-
-IntroScene23: ; e5086 (39:5086)
-	xor a
-	ld [wIntroSceneFrameCounter], a
-	call NextIntroScene
-	ret
-
-IntroScene24: ; e508e (39:508e)
-; Fade to white.
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp $20
-	jr nc, .done
-
-	ld c, a
-	and $3
-	ret nz
-
-	ld a, c
-	and $1c
-	sla a
-	call Intro_Scene24_ApplyPaletteFade
-	ret
-
-.done
-	ld a, $40
-	ld [wIntroSceneFrameCounter], a
-	call NextIntroScene
-	ret
-
-IntroScene25: ; e50ad (39:50ad)
-; Wait around a bit.
-	ld a, [wIntroSceneFrameCounter]
-	dec a
-	jr z, .done
-	ld [wIntroSceneFrameCounter], a
-	ret
-
-.done
-	call NextIntroScene
-	ret
-
-IntroScene26: ; e50bb (39:50bb)
-; Load the final scene.
-	call ClearBGPalettes
-	call ClearSprites
-	call ClearTileMap
-	xor a
-	ld [hBGMapMode], a
-	ld a, $1
-	ld [rVBK], a
-	ld hl, IntroTilemap015
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, $0
-	ld [rVBK], a
-	ld hl, IntroCrystalUnownsGFX
-	ld de, vTiles2 tile $00
-	call Intro_DecompressRequest2bpp_128Tiles
-	ld hl, IntroTilemap017
-	debgcoord 0, 0
-	call Intro_DecompressRequest2bpp_64Tiles
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld hl, IntroPalette3
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	call CopyBytes
-	ld hl, IntroPalette3
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-	pop af
-	ld [rSVBK], a
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	farcall ClearSpriteAnims
-	call Intro_SetCGBPalUpdate
-	xor a
-	ld [wIntroSceneFrameCounter], a
-	ld [wIntroSceneTimer], a
-	call NextIntroScene
-	ret
-
-IntroScene27: ; e512d (39:512d)
-; Spell out C R Y S T A L with Unown.
-	ld hl, wIntroSceneTimer
-	inc [hl]
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	inc [hl]
-	cp $80
-	jr nc, .done
-
-	ld c, a
-	and $f
-	ld [wIntroSceneTimer], a
-	ld a, c
-	and $70
-	swap a
-	call Intro_FadeUnownWordPals
-	ret
-
-.done
-	call NextIntroScene
-	ld a, $80
-	ld [wIntroSceneFrameCounter], a
-	ret
-
-IntroScene28: ; e5152 (39:5152)
-; Cut out when the music ends, and lead into the title screen.
-	ld hl, wIntroSceneFrameCounter
-	ld a, [hl]
-	and a
-	jr z, .done
-	dec [hl]
-	cp $18
-	jr z, .clear
-	cp $8
-	ret nz
-
-	ld de, SFX_UNKNOWN_CB
-	call PlaySFX
-	ret
-
-.clear
-	call ClearBGPalettes
-	ret
-
-.done
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-Intro_Scene24_ApplyPaletteFade: ; e5172 (39:5172)
-; load the (a)th palette from .FadePals to all wBGPals2
-	ld hl, .FadePals
-	add l
-	ld l, a
-	ld a, $0
-	adc h
-	ld h, a
-
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ld [rSVBK], a
-	ld de, wBGPals2
-	ld b, 8 ; number of BG pals
-.loop1
-	push hl
-	ld c, 1 palettes
-.loop2
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec c
-	jr nz, .loop2
-	pop hl
-	dec b
-	jr nz, .loop1
-	pop af
-	ld [rSVBK], a
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; e519c (39:519c)
-
-.FadePals: ; e519c
-INCLUDE "gfx/intro/fade.pal"
-; e51dc
-
-CrystalIntro_InitUnownAnim: ; e51dc (39:51dc)
-	push de
-	ld a, SPRITE_ANIM_INDEX_INTRO_UNOWN
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $8
-	ld a, SPRITE_ANIM_FRAMESET_INTRO_UNOWN_4
-	call ReinitSpriteAnimFrame
-	pop de
-
-	push de
-	ld a, SPRITE_ANIM_INDEX_INTRO_UNOWN
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $18
-	ld a, SPRITE_ANIM_FRAMESET_INTRO_UNOWN_3
-	call ReinitSpriteAnimFrame
-	pop de
-
-	push de
-	ld a, SPRITE_ANIM_INDEX_INTRO_UNOWN
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $28
-	ld a, SPRITE_ANIM_FRAMESET_INTRO_UNOWN_1
-	call ReinitSpriteAnimFrame
-	pop de
-
-	ld a, SPRITE_ANIM_INDEX_INTRO_UNOWN
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $38
-	ld a, SPRITE_ANIM_FRAMESET_INTRO_UNOWN_2
-	call ReinitSpriteAnimFrame
-	ret
-
-CrystalIntro_UnownFade: ; e5223 (39:5223)
-	add a
-	add a
-	add a
-	ld e, a
-	ld d, $0
-	ld hl, wBGPals2
-	add hl, de
-	inc hl
-	inc hl
-	ld a, [wIntroSceneTimer]
-	and %111111
-	cp %011111
-	jr z, .okay
-	jr c, .okay
-	ld c, a
-	ld a, %111111
-	sub c
-.okay
-
-	ld c, a
-	ld b, $0
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ld [rSVBK], a
-
-	push hl
-	push bc
-	ld hl, wBGPals2
-	ld bc, 8 palettes
-	xor a
-	call ByteFill
-	pop bc
-	pop hl
-
-	push hl
-	ld hl, .BWFade
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-	pop hl
-	ld a, e
-	ld [hli], a
-	ld a, d
-	ld [hli], a
-
-	push hl
-	ld hl, .BlackLBlueFade
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-	pop hl
-	ld a, e
-	ld [hli], a
-	ld a, d
-	ld [hli], a
-
-	push hl
-	ld hl, .BlackBlueFade
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-	pop hl
-	ld a, e
-	ld [hli], a
-	ld a, d
-	ld [hli], a
-
-	pop af
-	ld [rSVBK], a
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; e5288 (39:5288)
-
-.BWFade: ; e5288
-; Fade between black and white.
-hue = 0
-rept 32
-	RGB hue, hue, hue
-hue = hue + 1
-endr
-; e52c8
-
-.BlackLBlueFade: ; e52c8
-; Fade between black and light blue.
-hue = 0
-rept 32
-	RGB 0, hue / 2, hue
-hue = hue + 1
-endr
-; e5308
-
-.BlackBlueFade: ; e5308
-; Fade between black and blue.
-hue = 0
-rept 32
-	RGB 0, 0, hue
-hue = hue + 1
-endr
-; e5348
-
-Intro_Scene20_AppearUnown: ; e5348 (39:5348)
-; Spawn the palette for the nth Unown
-	and a
-	jr nz, .load_pal_2
-
-	ld hl, .pal1
-	jr .got_pointer
-
-.load_pal_2
-	ld hl, .pal2
-
-.got_pointer
-	ld a, [wIntroSceneTimer]
-	and $7
-	add a
-	add a
-	add a
-	ld c, a
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ld [rSVBK], a
-
-	push bc
-	ld de, wBGPals2
-
-	ld a, c
-	add e
-	ld e, a
-	ld a, $0
-	adc d
-	ld d, a
-
-	ld bc, 1 palettes
-	call CopyBytes
-	pop bc
-
-	ld de, wBGPals1
-	ld a, c
-	add e
-	ld e, a
-	ld a, $0
-	adc d
-	ld d, a
-
-	ld bc, 1 palettes
-	call CopyBytes
-
-	pop af
-	ld [rSVBK], a
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; e538d (39:538d)
-
-.pal1 ; e538d
-	RGB 24, 12, 09
-	RGB 31, 31, 31
-	RGB 12, 00, 31
-	RGB 00, 00, 00
-
-; e5395
-
-.pal2 ; e5395
-	RGB 24, 12, 09
-	RGB 31, 31, 31
-	RGB 31, 31, 31
-	RGB 31, 31, 31
-
-; e539d
-
-Intro_FadeUnownWordPals: ; e539d (39:539d)
-	add a
-	add a
-	add a
-	ld e, a
-	ld d, $0
-	ld hl, wBGPals2
-	add hl, de
-rept 4
-	inc hl
-endr
-	ld a, [wIntroSceneTimer]
-	add a
-	ld c, a
-	ld b, $0
-
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ld [rSVBK], a
-
-	push hl
-	ld hl, .FastFadePalettes
-	add hl, bc
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-	pop hl
-	ld a, e
-	ld [hli], a
-	ld a, d
-	ld [hli], a
-
-	push hl
-	ld hl, .SlowFadePalettes
-	add hl, bc
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-	pop hl
-	ld a, e
-	ld [hli], a
-	ld a, d
-	ld [hli], a
-
-	pop af
-	ld [rSVBK], a
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; e53db (39:53db)
-
-.FastFadePalettes: ; e53db
-hue = 31
-rept 8
-	RGB hue, hue, hue
-hue = hue + -1
-	RGB hue, hue, hue
-hue = hue + -2
-endr
-; e53fb
-
-.SlowFadePalettes: ; e53fb
-hue = 31
-rept 16
-	RGB hue, hue, hue
-hue = hue + -1
-endr
-; e541b
-
-Intro_LoadTilemap: ; e541b (39:541b)
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wDecompressScratch)
-	ld [rSVBK], a
-
-	ld hl, wDecompressScratch
-	decoord 0, 0
-	ld b, SCREEN_HEIGHT
-.row
-	ld c, SCREEN_WIDTH
-.col
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec c
-	jr nz, .col
-	ld a, BG_MAP_WIDTH - SCREEN_WIDTH
-	add l
-	ld l, a
-	ld a, 0
-	adc h
-	ld h, a
-	dec b
-	jr nz, .row
-
-	pop af
-	ld [rSVBK], a
-	ret
-
-Intro_Scene16_AnimateSuicune: ; e5441 (39:5441)
-	ld a, [wIntroSceneFrameCounter]
-	and $3
-	jr z, Intro_ColoredSuicuneFrameSwap
-	cp $3
-	jr z, .PrepareForSuicuneSwap
-	ret
-
-.PrepareForSuicuneSwap:
-	xor a
-	ld [hBGMapMode], a
-	ret
-
-Intro_ColoredSuicuneFrameSwap: ; e5451 (39:5451)
-	hlcoord 0, 0
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-.loop
-	ld a, [hl]
-	and a
-	jr z, .skip
-	cp $80
-	jr nc, .skip
-	xor $8
-	ld [hl], a
-.skip
-	inc hl
-	dec bc
-	ld a, c
-	or b
-	jr nz, .loop
-	ld a, $1
-	ld [hBGMapMode], a
-	ret
-
-Intro_RustleGrass: ; e546d (39:546d)
-	ld a, [wIntroSceneFrameCounter]
-	cp 36
-	ret nc
-	and $c
-	srl a
-	ld e, a
-	ld d, $0
-	ld hl, .RustlingGrassPointers
-	add hl, de
-	ld a, [hli]
-	ld [wRequested2bppSource], a
-	ld a, [hli]
-	ld [wRequested2bppSource + 1], a
-	ld a, LOW(vTiles2 tile $09)
-	ld [wRequested2bppDest], a
-	ld a, HIGH(vTiles2 tile $09)
-	ld [wRequested2bppDest + 1], a
-	ld a, 4
-	ld [wRequested2bppSize], a
-	ret
-; e5496 (39:5496)
-
-.RustlingGrassPointers: ; e5496
-	dw IntroGrass1GFX
-	dw IntroGrass2GFX
-	dw IntroGrass3GFX
-	dw IntroGrass2GFX
-; e549e
-
-Intro_SetCGBPalUpdate: ; e549e (39:549e)
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-
-Intro_ClearBGPals: ; e54a3 (39:54a3)
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ld [rSVBK], a
-
-	ld hl, wBGPals2
-	ld bc, 16 palettes
-	xor a
-	call ByteFill
-
-	pop af
-	ld [rSVBK], a
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	call DelayFrame
-	call DelayFrame
-	ret
-
-Intro_DecompressRequest2bpp_128Tiles: ; e54c2 (39:54c2)
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wDecompressScratch)
-	ld [rSVBK], a
-
-	push de
-	ld de, wDecompressScratch
-	call Decompress
-	pop hl
-
-	ld de, wDecompressScratch
-	lb bc, $01, $80
-	call Request2bpp
-
-	pop af
-	ld [rSVBK], a
-	ret
-
-Intro_DecompressRequest2bpp_255Tiles: ; e54de (39:54de)
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wDecompressScratch)
-	ld [rSVBK], a
-
-	push de
-	ld de, wDecompressScratch
-	call Decompress
-	pop hl
-
-	ld de, wDecompressScratch
-	lb bc, $01, $ff
-	call Request2bpp
-
-	pop af
-	ld [rSVBK], a
-	ret
-
-Intro_DecompressRequest2bpp_64Tiles: ; e54fa (39:54fa)
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wDecompressScratch)
-	ld [rSVBK], a
-
-	push de
-	ld de, wDecompressScratch
-	call Decompress
-	pop hl
-
-	ld de, wDecompressScratch
-	lb bc, $01, $40
-	call Request2bpp
-
-	pop af
-	ld [rSVBK], a
-	ret
-
-Intro_ResetLYOverrides: ; e5516 (39:5516)
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wLYOverrides)
-	ld [rSVBK], a
-
-	ld hl, wLYOverrides
-	ld bc, wLYOverridesEnd - wLYOverrides
-	xor a
-	call ByteFill
-
-	pop af
-	ld [rSVBK], a
-	ld a, rSCX - $ff00
-	ld [hLCDCPointer], a
-	ret
-
-Intro_PerspectiveScrollBG: ; e552f (39:552f)
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wLYOverrides)
-	ld [rSVBK], a
-	; Scroll the grass every frame.
-	; Scroll the trees every other frame and at half speed.
-	; This creates an illusion of perspective.
-	ld a, [wIntroSceneFrameCounter]
-	and $1
-	jr z, .skip
-	; trees in the back
-	ld hl, wLYOverrides
-	ld a, [hl]
-	inc a
-	ld bc, $5f
-	call ByteFill
-.skip
-	; grass in the front
-	ld hl, wLYOverrides + $5f
-	ld a, [hl]
-	inc a
-	inc a
-	ld bc, $31
-	call ByteFill
-	ld a, [wLYOverrides + 0]
-	ld [hSCX], a
-	pop af
-	ld [rSVBK], a
-	ret
-
-IntroSuicuneRunGFX: ; e555d
-INCBIN "gfx/intro/suicune_run.2bpp.lz"
-; e592d
-
-IntroPichuWooperGFX: ; e592d
-INCBIN "gfx/intro/pichu_wooper.2bpp.lz"
-; e5c7d
-
-IntroBackgroundGFX: ; e5c7d
-INCBIN "gfx/intro/background.2bpp.lz"
-; e5e6d
-
-IntroTilemap004: ; e5e6d
-INCBIN "gfx/intro/004.tilemap.lz"
-; e5ecd
-
-IntroTilemap003: ; e5ecd
-INCBIN "gfx/intro/003.tilemap.lz"
-; e5edd
-
-IntroPalette1: ; e5edd
-INCLUDE "gfx/intro/intro_1.pal"
-; e5f5d
-
-IntroUnownsGFX: ; e5f5d
-INCBIN "gfx/intro/unowns.2bpp.lz"
-; e634d
-
-IntroPulseGFX: ; e634d
-INCBIN "gfx/intro/pulse.2bpp.lz"
-; e63dd
-
-IntroTilemap002: ; e63dd
-INCBIN "gfx/intro/002.tilemap.lz"
-; e641d
-
-IntroTilemap001: ; e641d
-INCBIN "gfx/intro/001.tilemap.lz"
-; e642d
-
-IntroTilemap006: ; e642d
-INCBIN "gfx/intro/006.tilemap.lz"
-; e647d
-
-IntroTilemap005: ; e647d
-INCBIN "gfx/intro/005.tilemap.lz"
-; e649d
-
-IntroTilemap008: ; e649d
-INCBIN "gfx/intro/008.tilemap.lz"
-; e655d
-
-IntroTilemap007: ; e655d
-INCBIN "gfx/intro/007.tilemap.lz"
-; e65ad
-
-IntroPalette2: ; e65ad
-INCLUDE "gfx/intro/intro_2.pal"
-; e662d
-
-IntroCrystalUnownsGFX: ; e662d
-INCBIN "gfx/intro/crystal_unowns.2bpp.lz"
-; e672d
-
-IntroTilemap017: ; e672d
-INCBIN "gfx/intro/017.tilemap.lz"
-; e676d
-
-IntroTilemap015: ; e676d
-INCBIN "gfx/intro/015.tilemap.lz"
-; e679d
-
-IntroPalette3: ; e679d
-INCLUDE "gfx/intro/intro_3.pal"
-; e681d
-
-IntroSuicuneCloseGFX: ; e681d
-INCBIN "gfx/intro/suicune_close.2bpp.lz"
-; e6c3d
-
-IntroTilemap012: ; e6c3d
-INCBIN "gfx/intro/012.tilemap.lz"
-; e6d0d
-
-IntroTilemap011: ; e6d0d
-INCBIN "gfx/intro/011.tilemap.lz"
-; e6d6d
-
-IntroPalette4: ; e6d6d
-INCLUDE "gfx/intro/intro_4.pal"
-; e6ded
-
-IntroSuicuneJumpGFX: ; e6ded
-INCBIN "gfx/intro/suicune_jump.2bpp.lz"
-; e72ad
-
-IntroSuicuneBackGFX: ; e72ad
-INCBIN "gfx/intro/suicune_back.2bpp.lz"
-; e764d
-
-IntroTilemap010: ; e764d
-INCBIN "gfx/intro/010.tilemap.lz"
-; e76ad
-
-IntroTilemap009: ; e76ad
-INCBIN "gfx/intro/009.tilemap.lz"
-; e76bd
-
-IntroTilemap014: ; e76bd
-INCBIN "gfx/intro/014.tilemap.lz"
-; e778d
-
-IntroTilemap013: ; e778d
-INCBIN "gfx/intro/013.tilemap.lz"
-; e77dd
-
-IntroPalette5: ; e77dd
-INCLUDE "gfx/intro/intro_5.pal"
-
-IntroUnownBackGFX: ; e785d
-INCBIN "gfx/intro/unown_back.2bpp.lz"
-; e799d
-
-IntroGrass1GFX: ; e799d
-INCBIN "gfx/intro/grass1.2bpp"
-IntroGrass2GFX: ; e79dd
-INCBIN "gfx/intro/grass2.2bpp"
-IntroGrass3GFX: ; e7a1d
-INCBIN "gfx/intro/grass3.2bpp"
-IntroGrass4GFX: ; e7a5d
-INCBIN "gfx/intro/grass4.2bpp"
--- a/engine/crystal_layouts.asm
+++ /dev/null
@@ -1,325 +1,0 @@
-GetMysteryGift_MobileAdapterLayout: ; 4930f (mobile)
-	ld a, b
-	cp SCGB_RAM
-	jr nz, .not_ram
-	ld a, [wSGBPredef]
-.not_ram
-	push af
-	farcall ResetBGPals
-	pop af
-	ld l, a
-	ld h, 0
-	add hl, hl
-	ld de, .dw
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, .done
-	push de
-	jp hl
-.done
-	ret
-; 49330 (12:5330)
-
-.dw ; 49330
-	dw MG_Mobile_Layout00
-	dw MG_Mobile_Layout01
-	dw MG_Mobile_Layout02
-; 49336
-
-MG_Mobile_Layout_FillBox: ; 49336
-.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
-; 49346
-
-MG_Mobile_Layout_WipeAttrMap: ; 49346 (12:5346)
-	hlcoord 0, 0, wAttrMap
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	xor a
-	call ByteFill
-	ret
-
-MG_Mobile_Layout_LoadPals: ; 49351 (12:5351)
-	ld de, wBGPals1
-	ld hl, Palette_MysteryGiftMobile
-	ld bc, 5 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	ld de, wBGPals1 palette PAL_BG_TEXT
-	ld hl, Palette_TextBG7
-	ld bc, 1 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	ret
-
-MG_Mobile_Layout00: ; 4936e (12:536e)
-	call MG_Mobile_Layout_LoadPals
-	call MG_Mobile_Layout_WipeAttrMap
-	call MG_Mobile_Layout_CreatePalBoxes
-	farcall ApplyAttrMap
-	farcall ApplyPals
-	ret
-
-MG_Mobile_Layout_CreatePalBoxes: ; 49384 (12:5384)
-	hlcoord 0, 0, wAttrMap
-	lb bc, 4, 1
-	ld a, $1
-	call MG_Mobile_Layout_FillBox
-	lb bc, 2, 1
-	ld a, $2
-	call MG_Mobile_Layout_FillBox
-	lb bc, 6, 1
-	ld a, $3
-	call MG_Mobile_Layout_FillBox
-	hlcoord 1, 0, wAttrMap
-	ld a, $1
-	lb bc, 3, 18
-	call MG_Mobile_Layout_FillBox
-	lb bc, 2, 18
-	ld a, $2
-	call MG_Mobile_Layout_FillBox
-	lb bc, 12, 18
-	ld a, $3
-	call MG_Mobile_Layout_FillBox
-	hlcoord 19, 0, wAttrMap
-	lb bc, 4, 1
-	ld a, $1
-	call MG_Mobile_Layout_FillBox
-	lb bc, 2, 1
-	ld a, $2
-	call MG_Mobile_Layout_FillBox
-	lb bc, 6, 1
-	ld a, $3
-	call MG_Mobile_Layout_FillBox
-	hlcoord 0, 12, wAttrMap
-	ld bc, 6 * SCREEN_WIDTH
-	ld a, $7
-	call ByteFill
-	ret
-; 493e1 (12:53e1)
-
-Palette_MysteryGiftMobile: ; 493e1
-INCLUDE "gfx/mystery_gift/mg_mobile.pal"
-; 49409
-
-LoadOW_BGPal7:: ; 49409
-	ld hl, Palette_TextBG7
-	ld de, wBGPals1 palette PAL_BG_TEXT
-	ld bc, 1 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	ret
-; 49418
-
-Palette_TextBG7: ; 49418
-INCLUDE "gfx/font/bg_text.pal"
-; 49420
-
-Function49420:: ; 49420 (12:5420)
-	ld hl, MansionPalette1 + 8 palettes
-	ld de, wBGPals1 palette PAL_BG_ROOF
-	ld bc, 1 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	ret
-; 4942f (12:542f)
-
-MG_Mobile_Layout01: ; 4942f
-	call MG_Mobile_Layout_LoadPals
-	ld de, wBGPals1 palette PAL_BG_TEXT
-	ld hl, .Palette_49478
-	ld bc, 1 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	call MG_Mobile_Layout_WipeAttrMap
-	hlcoord 0, 0, wAttrMap
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	xor a
-	call ByteFill
-	hlcoord 0, 14, wAttrMap
-	ld bc, 4 * SCREEN_WIDTH
-	ld a, $7
-	call ByteFill
-	ld a, [wd002]
-	bit 6, a
-	jr z, .asm_49464
-	call Function49480
-	jr .asm_49467
-
-.asm_49464
-	call Function49496
-
-.asm_49467
-	farcall ApplyAttrMap
-	farcall ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ret
-; 49478
-
-.Palette_49478: ; 49478
-	RGB 31, 31, 31
-	RGB 26, 31, 00
-	RGB 20, 16, 03
-	RGB 00, 00, 00
-; 49480
-
-Function49480: ; 49480
-	hlcoord 0, 0, wAttrMap
-	lb bc, 4, SCREEN_WIDTH
-	ld a, $7
-	call MG_Mobile_Layout_FillBox
-	hlcoord 0, 2, wAttrMap
-	ld a, $4
-	ld [hl], a
-	hlcoord 19, 2, wAttrMap
-	ld [hl], a
-	ret
-; 49496
-
-Function49496: ; 49496
-	hlcoord 0, 0, wAttrMap
-	lb bc, 2, SCREEN_WIDTH
-	ld a, $7
-	call MG_Mobile_Layout_FillBox
-	hlcoord 0, 1, wAttrMap
-	ld a, $4
-	ld [hl], a
-	hlcoord 19, 1, wAttrMap
-	ld [hl], a
-	ret
-; 494ac
-
-INCLUDE "engine/tileset_palettes.asm"
-
-MG_Mobile_Layout02: ; 49706
-	ld hl, .Palette_49732
-	ld de, wBGPals1
-	ld bc, 1 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	farcall ApplyPals
-	call MG_Mobile_Layout_WipeAttrMap
-	farcall ApplyAttrMap
-	ld hl, .Palette_4973a
-	ld de, wOBPals1
-	ld bc, 1 palettes
-	ld a, BANK(wOBPals1)
-	call FarCopyWRAM
-	ret
-; 49732
-
-.Palette_49732: ; 49732
-	RGB 31, 31, 31
-	RGB 23, 16, 07
-	RGB 23, 07, 07
-	RGB 03, 07, 20
-; 4973a
-
-.Palette_4973a: ; 4973a
-	RGB 00, 00, 00
-	RGB 07, 05, 31
-	RGB 14, 18, 31
-	RGB 31, 31, 31
-; 49742
-
-Function49742: ; 49742
-	ld hl, .Palette_49757
-	ld de, wBGPals1
-	ld bc, 8 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	farcall ApplyPals
-	ret
-; 49757
-
-.Palette_49757: ; 49757
-INCLUDE "gfx/unknown/49757.pal"
-; 49797
-
-_InitMG_Mobile_LinkTradePalMap: ; 49797
-	hlcoord 0, 0, wAttrMap
-	lb bc, 16, 2
-	ld a, $4
-	call MG_Mobile_Layout_FillBox
-	ld a, $3
-	ldcoord_a 0, 1, wAttrMap
-	ldcoord_a 0, 14, wAttrMap
-	hlcoord 2, 0, wAttrMap
-	lb bc, 8, 18
-	ld a, $5
-	call MG_Mobile_Layout_FillBox
-	hlcoord 2, 8, wAttrMap
-	lb bc, 8, 18
-	ld a, $6
-	call MG_Mobile_Layout_FillBox
-	hlcoord 0, 16, wAttrMap
-	lb bc, 2, SCREEN_WIDTH
-	ld a, $4
-	call MG_Mobile_Layout_FillBox
-	ld a, $3
-	lb bc, 6, 1
-	hlcoord 6, 1, wAttrMap
-	call MG_Mobile_Layout_FillBox
-	ld a, $3
-	lb bc, 6, 1
-	hlcoord 17, 1, wAttrMap
-	call MG_Mobile_Layout_FillBox
-	ld a, $3
-	lb bc, 6, 1
-	hlcoord 6, 9, wAttrMap
-	call MG_Mobile_Layout_FillBox
-	ld a, $3
-	lb bc, 6, 1
-	hlcoord 17, 9, wAttrMap
-	call MG_Mobile_Layout_FillBox
-	ld a, $2
-	hlcoord 2, 16, wAttrMap
-	ld [hli], a
-	ld a, $7
-	ld [hli], a
-	ld [hli], a
-	ld [hli], a
-	ld a, $2
-	ld [hl], a
-	hlcoord 2, 17, wAttrMap
-	ld a, $3
-	ld bc, 6
-	call ByteFill
-	ret
-; 49811
-
-LoadTradeRoomBGPals: ; 49811
-	ld hl, TradeRoomPalette
-	ld de, wBGPals1 palette PAL_BG_GREEN
-	ld bc, 6 palettes
-	ld a, BANK(wBGPals1)
-	call FarCopyWRAM
-	farcall ApplyPals
-	ret
-; 49826
-
-TradeRoomPalette: ; 49826
-INCLUDE "gfx/trade/border.pal"
-; 49856
-
-InitMG_Mobile_LinkTradePalMap: ; 49856
-	call _InitMG_Mobile_LinkTradePalMap
-	ret
-; 4985a
-
-; unused
-INCLUDE "gfx/unknown/4985a.asm"
--- a/engine/decorations.asm
+++ /dev/null
@@ -1,1303 +1,0 @@
-InitDecorations: ; 26751 (9:6751)
-	ld a, DECO_FEATHERY_BED
-	ld [wDecoBed], a
-	ld a, DECO_TOWN_MAP
-	ld [wDecoPoster], a
-	ret
-
-_PlayerDecorationMenu: ; 0x2675c
-	ld a, [wWhichIndexSet]
-	push af
-	ld hl, .MenuHeader
-	call LoadMenuHeader
-	xor a
-	ld [wBuffer5], a
-	ld a, $1
-	ld [wBuffer6], a
-.top_loop
-	ld a, [wBuffer6]
-	ld [wMenuCursorBuffer], a
-	call .FindCategoriesWithOwnedDecos
-	call DoNthMenu
-	ld a, [wMenuCursorY]
-	ld [wBuffer6], a
-	jr c, .exit_menu
-	ld a, [wMenuSelection]
-	ld hl, .pointers
-	call MenuJumptable
-	jr nc, .top_loop
-
-.exit_menu
-	call ExitMenu
-	pop af
-	ld [wWhichIndexSet], a
-	ld a, [wBuffer5]
-	ld c, a
-	ret
-; 0x2679a
-
-.MenuHeader: ; 0x2679a
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 5, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
-	dw .MenuData
-	db 1 ; default option
-; 0x267a2
-
-.MenuData: ; 0x267a2
-	db STATICMENU_CURSOR | STATICMENU_WRAP ; flags
-	db 0 ; items
-	dw wd002
-	dw PlaceNthMenuStrings
-	dw .pointers
-; 0x267aa
-
-.pointers ; 267aa
-	dw DecoBedMenu, .bed
-	dw DecoCarpetMenu, .carpet
-	dw DecoPlantMenu, .plant
-	dw DecoPosterMenu, .poster
-	dw DecoConsoleMenu, .game
-	dw DecoOrnamentMenu, .ornament
-	dw DecoBigDollMenu, .big_doll
-	dw DecoExitMenu, .exit
-
-.bed      db "BED@"
-.carpet   db "CARPET@"
-.plant    db "PLANT@"
-.poster   db "POSTER@"
-.game     db "GAME CONSOLE@"
-.ornament db "ORNAMENT@"
-.big_doll db "BIG DOLL@"
-.exit     db "EXIT@"
-; 26806
-
-.FindCategoriesWithOwnedDecos: ; 26806
-	xor a
-	ld [wWhichIndexSet], a
-	call .ClearStringBuffer2
-	call .FindOwndDecos
-	ld a, 7
-	call .AppendToStringBuffer2
-	ld hl, wStringBuffer2
-	ld de, wd002
-	ld bc, ITEM_NAME_LENGTH
-	call CopyBytes
-	ret
-
-.ClearStringBuffer2: ; 26822 (9:6822)
-	ld hl, wStringBuffer2
-	xor a
-	ld [hli], a
-	ld bc, ITEM_NAME_LENGTH - 1
-	ld a, -1
-	call ByteFill
-	ret
-
-.AppendToStringBuffer2: ; 26830 (9:6830)
-	ld hl, wStringBuffer2
-	inc [hl]
-	ld e, [hl]
-	ld d, 0
-	add hl, de
-	ld [hl], a
-	ret
-
-.FindOwndDecos: ; 2683a (9:683a)
-	ld hl, .dw
-.loop
-	ld a, [hli]
-	ld e, a
-	ld a, [hli]
-	ld d, a
-	or e
-	jr z, .done
-	push hl
-	call _de_
-	pop hl
-	jr nc, .next
-	ld a, [hl]
-	push hl
-	call .AppendToStringBuffer2
-	pop hl
-.next
-	inc hl
-	jr .loop
-.done
-	ret
-; 26855 (9:6855)
-
-.dw ; 26855
-	dwb FindOwnedBeds, 0 ; bed
-	dwb FindOwnedCarpets, 1 ; carpet
-	dwb FindOwnedPlants, 2 ; plant
-	dwb FindOwnedPosters, 3 ; poster
-	dwb FindOwnedConsoles, 4 ; game console
-	dwb FindOwnedOrnaments, 5 ; ornament
-	dwb FindOwnedBigDolls, 6 ; big doll
-	dw 0 ; end
-; 2686c
-
-Deco_FillTempWithMinusOne: ; 2686c
-	xor a
-	ld hl, wd002
-	ld [hli], a
-	ld a, -1
-	ld bc, $10
-	call ByteFill
-	ret
-; 2687a
-
-CheckAllDecorationFlags: ; 2687a
-.loop
-	ld a, [hli]
-	cp -1
-	jr z, .done
-	push hl
-	push af
-	ld b, CHECK_FLAG
-	call DecorationFlagAction
-	ld a, c
-	and a
-	pop bc
-	ld a, b
-	call nz, AppendDecoIndex
-	pop hl
-	jr .loop
-
-.done
-	ret
-; 26891
-
-AppendDecoIndex: ; 26891
-	ld hl, wd002
-	inc [hl]
-	ld e, [hl]
-	ld d, $0
-	add hl, de
-	ld [hl], a
-	ret
-; 2689b
-
-FindOwnedDecosInCategory: ; 2689b
-	push bc
-	push hl
-	call Deco_FillTempWithMinusOne
-	pop hl
-	call CheckAllDecorationFlags
-	pop bc
-	ld a, [wd002]
-	and a
-	ret z
-
-	ld a, c
-	call AppendDecoIndex
-	ld a, 0
-	call AppendDecoIndex
-	scf
-	ret
-; 268b5
-
-DecoBedMenu: ; 268b5
-	call FindOwnedBeds
-	call PopulateDecoCategoryMenu
-	xor a
-	ret
-; 268bd
-
-FindOwnedBeds: ; 268bd
-	ld hl, .beds
-	ld c, BEDS
-	jp FindOwnedDecosInCategory
-; 268c5
-
-.beds ; 268c5
-	db DECO_FEATHERY_BED ; 2
-	db DECO_PINK_BED ; 3
-	db DECO_POLKADOT_BED ; 4
-	db DECO_PIKACHU_BED ; 5
-	db -1
-; 268ca
-
-DecoCarpetMenu: ; 268ca
-	call FindOwnedCarpets
-	call PopulateDecoCategoryMenu
-	xor a
-	ret
-; 268d2
-
-FindOwnedCarpets: ; 268d2
-	ld hl, .carpets
-	ld c, CARPETS
-	jp FindOwnedDecosInCategory
-; 268da
-
-.carpets ; 268da
-	db DECO_RED_CARPET ; 7
-	db DECO_BLUE_CARPET ; 8
-	db DECO_YELLOW_CARPET ; 9
-	db DECO_GREEN_CARPET ; a
-	db -1
-; 268df
-
-DecoPlantMenu: ; 268df
-	call FindOwnedPlants
-	call PopulateDecoCategoryMenu
-	xor a
-	ret
-; 268e7
-
-FindOwnedPlants: ; 268e7
-	ld hl, .plants
-	ld c, PLANTS
-	jp FindOwnedDecosInCategory
-; 268ef
-
-.plants ; 268ef
-	db DECO_MAGNAPLANT ; c
-	db DECO_TROPICPLANT ; d
-	db DECO_JUMBOPLANT ; e
-	db -1
-; 268f3
-
-DecoPosterMenu: ; 268f3
-	call FindOwnedPosters
-	call PopulateDecoCategoryMenu
-	xor a
-	ret
-; 268fb
-
-FindOwnedPosters: ; 268fb
-	ld hl, .posters
-	ld c, POSTERS
-	jp FindOwnedDecosInCategory
-; 26903
-
-.posters ; 26903
-	db DECO_TOWN_MAP ; 10
-	db DECO_PIKACHU_POSTER ; 11
-	db DECO_CLEFAIRY_POSTER ; 12
-	db DECO_JIGGLYPUFF_POSTER ; 13
-	db -1
-; 26908
-
-DecoConsoleMenu: ; 26908
-	call FindOwnedConsoles
-	call PopulateDecoCategoryMenu
-	xor a
-	ret
-; 26910
-
-FindOwnedConsoles: ; 26910
-	ld hl, .consoles
-	ld c, CONSOLES
-	jp FindOwnedDecosInCategory
-; 26918
-
-.consoles ; 26918
-	db DECO_FAMICOM ; 15
-	db DECO_SNES ; 16
-	db DECO_N64 ; 17
-	db DECO_VIRTUAL_BOY ; 18
-	db -1
-; 2691d
-
-DecoOrnamentMenu: ; 2691d
-	call FindOwnedOrnaments
-	call PopulateDecoCategoryMenu
-	xor a
-	ret
-; 26925
-
-FindOwnedOrnaments: ; 26925
-	ld hl, .ornaments
-	ld c, DOLLS
-	jp FindOwnedDecosInCategory
-; 2692d
-
-.ornaments ; 2692d
-	db DECO_PIKACHU_DOLL ; 1e
-	db DECO_SURF_PIKACHU_DOLL ; 1f
-	db DECO_CLEFAIRY_DOLL ; 20
-	db DECO_JIGGLYPUFF_DOLL ; 21
-	db DECO_BULBASAUR_DOLL ; 22
-	db DECO_CHARMANDER_DOLL ; 23
-	db DECO_SQUIRTLE_DOLL ; 24
-	db DECO_POLIWAG_DOLL ; 25
-	db DECO_DIGLETT_DOLL ; 26
-	db DECO_STARMIE_DOLL ; 27
-	db DECO_MAGIKARP_DOLL ; 28
-	db DECO_ODDISH_DOLL ; 29
-	db DECO_GENGAR_DOLL ; 2a
-	db DECO_SHELLDER_DOLL ; 2b
-	db DECO_GRIMER_DOLL ; 2c
-	db DECO_VOLTORB_DOLL ; 2d
-	db DECO_WEEDLE_DOLL ; 2e
-	db DECO_UNOWN_DOLL ; 2f
-	db DECO_GEODUDE_DOLL ; 30
-	db DECO_MACHOP_DOLL ; 31
-	db DECO_TENTACOOL_DOLL ; 32
-	db DECO_GOLD_TROPHY_DOLL ; 33
-	db DECO_SILVER_TROPHY_DOLL ; 34
-	db -1
-; 26945
-
-DecoBigDollMenu: ; 26945
-	call FindOwnedBigDolls
-	call PopulateDecoCategoryMenu
-	xor a
-	ret
-; 2694d
-
-FindOwnedBigDolls: ; 2694d
-	ld hl, .big_dolls
-	ld c, BIG_DOLLS
-	jp FindOwnedDecosInCategory
-; 26955
-
-.big_dolls ; 26955
-	db DECO_BIG_SNORLAX_DOLL ; 1a
-	db DECO_BIG_ONIX_DOLL ; 1b
-	db DECO_BIG_LAPRAS_DOLL ; 1c
-	db -1
-; 26959
-
-DecoExitMenu: ; 26959
-	scf
-	ret
-; 2695b
-
-PopulateDecoCategoryMenu: ; 2695b
-	ld a, [wd002]
-	and a
-	jr z, .empty
-	cp 8
-	jr nc, .beyond_eight
-	xor a
-	ld [wWhichIndexSet], a
-	ld hl, .NonscrollingMenuHeader
-	call LoadMenuHeader
-	call DoNthMenu
-	jr c, .no_action_1
-	call DoDecorationAction2
-
-.no_action_1
-	call ExitMenu
-	ret
-
-.beyond_eight
-	ld hl, wd002
-	ld e, [hl]
-	dec [hl]
-	ld d, 0
-	add hl, de
-	ld [hl], -1
-	call LoadStandardMenuHeader
-	ld hl, .ScrollingMenuHeader
-	call CopyMenuHeader
-	xor a
-	ld [hBGMapMode], a
-	call InitScrollingMenu
-	xor a
-	ld [wMenuScrollPosition], a
-	call ScrollingMenu
-	ld a, [wMenuJoypad]
-	cp 2
-	jr z, .no_action_2
-	call DoDecorationAction2
-
-.no_action_2
-	call ExitMenu
-	ret
-
-.empty
-	ld hl, .Text_nothing_to_choose
-	call MenuTextBoxBackup
-	ret
-; 269b0
-
-.Text_nothing_to_choose: ; 0x269b0
-	; There's nothing to choose.
-	text_jump UnknownText_0x1bc471
-	db "@"
-; 0x269b5
-
-.NonscrollingMenuHeader: ; 0x269b5
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
-	dw .NonscrollingMenuData
-	db 1 ; default option
-; 0x269bd
-
-.NonscrollingMenuData: ; 0x269bd
-	db STATICMENU_CURSOR | STATICMENU_WRAP ; flags
-	db 0 ; items
-	dw wd002
-	dw DecorationMenuFunction
-	dw DecorationAttributes
-; 0x269c5
-
-.ScrollingMenuHeader: ; 0x269c5
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 1, 1, SCREEN_WIDTH - 2, SCREEN_HEIGHT - 2
-	dw .ScrollingMenuData
-	db 1 ; default option
-; 0x269cd
-
-.ScrollingMenuData: ; 0x269cd
-	db SCROLLINGMENU_DISPLAY_ARROWS ; flags
-	db 8, 0 ; rows, columns
-	db 1 ; horizontal spacing
-	dbw 0, wd002 ; text pointer
-	dba DecorationMenuFunction
-	dbw 0, 0
-	dbw 0, 0
-; 269dd
-
-
-GetDecorationData: ; 269dd
-	ld hl, DecorationAttributes
-	ld bc, 6
-	call AddNTimes
-	ret
-; 269e7
-
-GetDecorationName: ; 269e7
-	push hl
-	call GetDecorationData
-	call GetDecoName
-	pop hl
-	call CopyName2
-	ret
-; 269f3
-
-DecorationMenuFunction: ; 269f3
-	ld a, [wMenuSelection]
-	push de
-	call GetDecorationData
-	call GetDecoName
-	pop hl
-	call PlaceString
-	ret
-; 26a02
-
-DoDecorationAction2: ; 26a02
-	ld a, [wMenuSelection]
-	call GetDecorationData
-	ld de, 2 ; function 2
-	add hl, de
-	ld a, [hl]
-	ld hl, .DecoActions
-	rst JumpTable
-	ret
-; 26a12
-
-.DecoActions: ; 26a12
-	dw DecoAction_nothing
-	dw DecoAction_setupbed
-	dw DecoAction_putawaybed
-	dw DecoAction_setupcarpet
-	dw DecoAction_putawaycarpet
-	dw DecoAction_setupplant
-	dw DecoAction_putawayplant
-	dw DecoAction_setupposter
-	dw DecoAction_putawayposter
-	dw DecoAction_setupconsole
-	dw DecoAction_putawayconsole
-	dw DecoAction_setupbigdoll
-	dw DecoAction_putawaybigdoll
-	dw DecoAction_setupornament
-	dw DecoAction_putawayornament
-; 26a30
-
-
-GetDecorationFlag: ; 26a30
-	call GetDecorationData
-	ld de, 3 ; event flag
-	add hl, de
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-	ret
-; 26a3b
-
-DecorationFlagAction: ; 26a3b
-	push bc
-	call GetDecorationFlag
-	pop bc
-	call EventFlagAction
-	ret
-; 26a44
-
-GetDecorationSprite: ; 26a44
-	ld a, c
-	call GetDecorationData
-	ld de, 5 ; sprite
-	add hl, de
-	ld a, [hl]
-	ld c, a
-	ret
-; 26a4f
-
-INCLUDE "data/decorations/attributes.asm"
-
-INCLUDE "data/decorations/names.asm"
-
-GetDecoName: ; 26c72
-	ld a, [hli]
-	ld e, [hl]
-	ld bc, wStringBuffer2
-	push bc
-	ld hl, .NameFunctions
-	rst JumpTable
-	pop de
-	ret
-; 26c7e
-
-.NameFunctions: ; 26c7e
-	dw .invalid
-	dw .plant
-	dw .bed
-	dw .carpet
-	dw .poster
-	dw .doll
-	dw .bigdoll
-; 26c8c
-
-
-.invalid ; 26c8c
-	ret
-; 26c8d
-
-.plant ; 26c8d
-	ld a, e
-	jr .getdeconame
-
-.bed ; 26c90
-	call .plant
-	ld a, _BED
-	jr .getdeconame
-
-.carpet ; 26c97
-	call .plant
-	ld a, _CARPET
-	jr .getdeconame
-
-.poster ; 26c9e
-	ld a, e
-	call .getpokename
-	ld a, _POSTER
-	jr .getdeconame
-
-.doll ; 26ca6
-	ld a, e
-	call .getpokename
-	ld a, _DOLL
-	jr .getdeconame
-
-.bigdoll ; 26cae
-	push de
-	ld a, BIG_
-	call .getdeconame
-	pop de
-	ld a, e
-	jr .getpokename
-
-.unused ; 26cb8
-	push de
-	call .getdeconame
-	pop de
-	ld a, e
-	jr .getdeconame
-
-.getpokename ; 26cc0
-	push bc
-	ld [wd265], a
-	call GetPokemonName
-	pop bc
-	jr .copy
-
-.getdeconame ; 26cca
-	call ._getdeconame
-	jr .copy
-
-._getdeconame ; 26ccf
-	push bc
-	ld hl, DecorationNames
-	call GetNthString
-	ld d, h
-	ld e, l
-	pop bc
-	ret
-
-.copy ; 26cda
-	ld h, b
-	ld l, c
-	call CopyName2
-	dec hl
-	ld b, h
-	ld c, l
-	ret
-; 26ce3
-
-DecoAction_nothing: ; 26ce3
-	scf
-	ret
-; 26ce5
-
-DecoAction_setupbed: ; 26ce5
-	ld hl, wDecoBed
-	jp DecoAction_TrySetItUp
-; 26ceb
-
-DecoAction_putawaybed: ; 26ceb
-	ld hl, wDecoBed
-	jp DecoAction_TryPutItAway
-; 26cf1
-
-DecoAction_setupcarpet: ; 26cf1
-	ld hl, wDecoCarpet
-	jp DecoAction_TrySetItUp
-; 26cf7
-
-DecoAction_putawaycarpet: ; 26cf7
-	ld hl, wDecoCarpet
-	jp DecoAction_TryPutItAway
-; 26cfd
-
-DecoAction_setupplant: ; 26cfd
-	ld hl, wDecoPlant
-	jp DecoAction_TrySetItUp
-; 26d03
-
-DecoAction_putawayplant: ; 26d03
-	ld hl, wDecoPlant
-	jp DecoAction_TryPutItAway
-; 26d09
-
-DecoAction_setupposter: ; 26d09
-	ld hl, wDecoPoster
-	jp DecoAction_TrySetItUp
-; 26d0f
-
-DecoAction_putawayposter: ; 26d0f
-	ld hl, wDecoPoster
-	jp DecoAction_TryPutItAway
-; 26d15
-
-DecoAction_setupconsole: ; 26d15
-	ld hl, wDecoConsole
-	jp DecoAction_TrySetItUp
-; 26d1b
-
-DecoAction_putawayconsole: ; 26d1b
-	ld hl, wDecoConsole
-	jp DecoAction_TryPutItAway
-; 26d21
-
-DecoAction_setupbigdoll: ; 26d21
-	ld hl, wDecoBigDoll
-	jp DecoAction_TrySetItUp
-; 26d27
-
-DecoAction_putawaybigdoll: ; 26d27
-	ld hl, wDecoBigDoll
-	jp DecoAction_TryPutItAway
-; 26d2d
-
-DecoAction_TrySetItUp: ; 26d2d
-	ld a, [hl]
-	ld [wBuffer1], a
-	push hl
-	call DecoAction_SetItUp
-	jr c, .failed
-	ld a, 1
-	ld [wBuffer5], a
-	pop hl
-	ld a, [wMenuSelection]
-	ld [hl], a
-	xor a
-	ret
-
-.failed
-	pop hl
-	xor a
-	ret
-; 26d46
-
-DecoAction_SetItUp: ; 26d46
-; See if there's anything of the same type already out
-	ld a, [wBuffer1]
-	and a
-	jr z, .nothingthere
-; See if that item is already out
-	ld b, a
-	ld a, [wMenuSelection]
-	cp b
-	jr z, .alreadythere
-; Put away the item that's already out, and set up the new one
-	ld a, [wMenuSelection]
-	ld hl, wStringBuffer4
-	call GetDecorationName
-	ld a, [wBuffer1]
-	ld hl, wStringBuffer3
-	call GetDecorationName
-	ld hl, DecoText_PutAwayAndSetUp
-	call MenuTextBoxBackup
-	xor a
-	ret
-
-.nothingthere
-	ld a, [wMenuSelection]
-	ld hl, wStringBuffer3
-	call GetDecorationName
-	ld hl, DecoText_SetUpTheDeco
-	call MenuTextBoxBackup
-	xor a
-	ret
-
-.alreadythere
-	ld hl, DecoText_AlreadySetUp
-	call MenuTextBoxBackup
-	scf
-	ret
-; 26d86
-
-DecoAction_TryPutItAway: ; 26d86
-; If there is no item of that type already set, there is nothing to put away.
-	ld a, [hl]
-	ld [wBuffer1], a
-	xor a
-	ld [hl], a
-	ld a, [wBuffer1]
-	and a
-	jr z, .nothingthere
-; Put it away.
-	ld a, $1
-	ld [wBuffer5], a
-	ld a, [wBuffer1]
-	ld [wMenuSelection], a
-	ld hl, wStringBuffer3
-	call GetDecorationName
-	ld hl, DecoText_PutAwayTheDeco
-	call MenuTextBoxBackup
-	xor a
-	ret
-
-.nothingthere
-	ld hl, DecoText_NothingToPutAway
-	call MenuTextBoxBackup
-	xor a
-	ret
-; 26db3
-
-DecoAction_setupornament: ; 26db3
-	ld hl, UnknownText_0x26e41
-	call DecoAction_AskWhichSide
-	jr c, .cancel
-	call DecoAction_SetItUp_Ornament
-	jr c, .cancel
-	ld a, $1
-	ld [wBuffer5], a
-	jr DecoAction_FinishUp_Ornament
-
-.cancel
-	xor a
-	ret
-
-DecoAction_putawayornament: ; 26dc9
-	ld hl, DecoText_WhichSide
-	call DecoAction_AskWhichSide
-	jr nc, .incave
-	xor a
-	ret
-
-.incave
-	call DecoAction_PutItAway_Ornament
-
-DecoAction_FinishUp_Ornament: ; 26dd6
-	call QueryWhichSide
-	ld a, [wSelectedDecoration]
-	ld [hl], a
-	ld a, [wOtherDecoration]
-	ld [de], a
-	xor a
-	ret
-; 26de3
-
-DecoAction_SetItUp_Ornament: ; 26de3
-	ld a, [wSelectedDecoration]
-	and a
-	jr z, .nothingthere
-	ld b, a
-	ld a, [wMenuSelection]
-	cp b
-	jr z, .failed
-	ld a, b
-	ld hl, wStringBuffer3
-	call GetDecorationName
-	ld a, [wMenuSelection]
-	ld hl, wStringBuffer4
-	call GetDecorationName
-	ld a, [wMenuSelection]
-	ld [wSelectedDecoration], a
-	call .getwhichside
-	ld hl, DecoText_PutAwayAndSetUp
-	call MenuTextBoxBackup
-	xor a
-	ret
-
-.nothingthere
-	ld a, [wMenuSelection]
-	ld [wSelectedDecoration], a
-	call .getwhichside
-	ld a, [wMenuSelection]
-	ld hl, wStringBuffer3
-	call GetDecorationName
-	ld hl, DecoText_SetUpTheDeco
-	call MenuTextBoxBackup
-	xor a
-	ret
-
-.failed
-	ld hl, DecoText_AlreadySetUp
-	call MenuTextBoxBackup
-	scf
-	ret
-; 26e33
-
-.getwhichside ; 26e33
-	ld a, [wMenuSelection]
-	ld b, a
-	ld a, [wOtherDecoration]
-	cp b
-	ret nz
-	xor a
-	ld [wOtherDecoration], a
-	ret
-; 26e41
-
-UnknownText_0x26e41: ; 0x26e41
-	; Which side do you want to put it on?
-	text_jump UnknownText_0x1bc48c
-	db "@"
-; 0x26e46
-
-DecoAction_PutItAway_Ornament: ; 26e46
-	ld a, [wSelectedDecoration]
-	and a
-	jr z, .nothingthere
-	ld hl, wStringBuffer3
-	call GetDecorationName
-	ld a, $1
-	ld [wBuffer5], a
-	xor a
-	ld [wSelectedDecoration], a
-	ld hl, DecoText_PutAwayTheDeco
-	call MenuTextBoxBackup
-	xor a
-	ret
-
-.nothingthere
-	ld hl, DecoText_NothingToPutAway
-	call MenuTextBoxBackup
-	xor a
-	ret
-; 26e6b
-
-DecoText_WhichSide: ; 0x26e6b
-	; Which side do you want to put away?
-	text_jump UnknownText_0x1bc4b2
-	db "@"
-; 0x26e70
-
-DecoAction_AskWhichSide: ; 26e70
-	call MenuTextBox
-	ld hl, MenuHeader_0x26eab
-	call GetMenu2
-	call ExitMenu
-	call CopyMenuData
-	jr c, .nope
-	ld a, [wMenuCursorY]
-	cp 3
-	jr z, .nope
-	ld [wBuffer2], a
-	call QueryWhichSide
-	ld a, [hl]
-	ld [wSelectedDecoration], a
-	ld a, [de]
-	ld [wOtherDecoration], a
-	xor a
-	ret
-
-.nope
-	scf
-	ret
-; 26e9a
-
-QueryWhichSide: ; 26e9a
-	ld hl, wDecoRightOrnament
-	ld de, wDecoLeftOrnament
-	ld a, [wBuffer2]
-	cp 1
-	ret z
-	push hl
-	ld h, d
-	ld l, e
-	pop de
-	ret
-; 26eab
-
-MenuHeader_0x26eab: ; 0x26eab
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 0, 0, 13, 7
-	dw MenuData_0x26eb3
-	db 1 ; default option
-; 0x26eb3
-
-MenuData_0x26eb3: ; 0x26eb3
-	db STATICMENU_CURSOR ; flags
-	db 3 ; items
-	db "RIGHT SIDE@"
-	db "LEFT SIDE@"
-	db "CANCEL@"
-; 0x26ed1
-
-DecoText_PutAwayTheDeco: ; 0x26ed1
-	; Put away the @ .
-	text_jump UnknownText_0x1bc4d7
-	db "@"
-; 0x26ed6
-
-DecoText_NothingToPutAway: ; 0x26ed6
-	; There's nothing to put away.
-	text_jump UnknownText_0x1bc4ec
-	db "@"
-; 0x26edb
-
-DecoText_SetUpTheDeco: ; 0x26edb
-	; Set up the @ .
-	text_jump UnknownText_0x1bc509
-	db "@"
-; 0x26ee0
-
-DecoText_PutAwayAndSetUp: ; 0x26ee0
-	; Put away the @ and set up the @ .
-	text_jump UnknownText_0x1bc51c
-	db "@"
-; 0x26ee5
-
-DecoText_AlreadySetUp: ; 0x26ee5
-	; That's already set up.
-	text_jump UnknownText_0x1bc546
-	db "@"
-; 0x26eea
-
-GetDecorationName_c_de: ; 26eea
-	ld a, c
-	ld h, d
-	ld l, e
-	call GetDecorationName
-	ret
-; 26ef1
-
-DecorationFlagAction_c: ; 26ef1
-	ld a, c
-	jp DecorationFlagAction
-; 26ef5
-
-
-GetDecorationName_c: ; 26ef5 (9:6ef5)
-	ld a, c
-	call GetDecorationID
-	ld hl, wStringBuffer1
-	push hl
-	call GetDecorationName
-	pop de
-	ret
-
-
-SetSpecificDecorationFlag: ; 26f02
-	ld a, c
-	call GetDecorationID
-	ld b, SET_FLAG
-	call DecorationFlagAction
-	ret
-; 26f0c
-
-GetDecorationID: ; 26f0c
-	push hl
-	push de
-	ld e, a
-	ld d, 0
-	ld hl, DecorationIDs
-	add hl, de
-	ld a, [hl]
-	pop de
-	pop hl
-	ret
-; 26f19
-
-SetAllDecorationFlags: ; 26f19
-	ld hl, DecorationIDs
-.loop
-	ld a, [hli]
-	cp -1
-	jr z, .done
-	push hl
-	ld b, SET_FLAG
-	call DecorationFlagAction
-	pop hl
-	jr .loop
-
-.done
-	ret
-; 26f2b
-
-INCLUDE "data/decorations/decorations.asm"
-
-DescribeDecoration:: ; 26f59
-	ld a, b
-	ld hl, .JumpTable
-	rst JumpTable
-	ret
-; 26f5f
-
-.JumpTable: ; 26f5f
-; entries correspond to DECODESC_* constants
-	dw DecorationDesc_Poster
-	dw DecorationDesc_LeftOrnament
-	dw DecorationDesc_RightOrnament
-	dw DecorationDesc_GiantOrnament
-	dw DecorationDesc_Console
-; 26f69
-
-DecorationDesc_Poster: ; 26f69
-	ld a, [wDecoPoster]
-	ld hl, DecorationDesc_PosterPointers
-	ld de, 3
-	call IsInArray
-	jr c, .nope
-	ld de, DecorationDesc_NullPoster
-	ld b, BANK(DecorationDesc_NullPoster)
-	ret
-
-.nope
-	ld b, BANK(DecorationDesc_TownMapPoster)
-	inc hl
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-	ret
-; 26f84
-
-DecorationDesc_PosterPointers: ; 26f84
-	dbw DECO_TOWN_MAP, DecorationDesc_TownMapPoster
-	dbw DECO_PIKACHU_POSTER, DecorationDesc_PikachuPoster
-	dbw DECO_CLEFAIRY_POSTER, DecorationDesc_ClefairyPoster
-	dbw DECO_JIGGLYPUFF_POSTER, DecorationDesc_JigglypuffPoster
-	db -1
-; 26f91
-
-DecorationDesc_TownMapPoster: ; 0x26f91
-	opentext
-	writetext .TownMapText
-	waitbutton
-	special OverworldTownMap
-	closetext
-	end
-; 0x26f9b
-
-.TownMapText: ; 0x26f9b
-	; It's the TOWN MAP.
-	text_jump UnknownText_0x1bc55d
-	db "@"
-; 0x26fa0
-
-DecorationDesc_PikachuPoster: ; 0x26fa0
-	jumptext .PikaPosterText
-; 0x26fa3
-
-.PikaPosterText: ; 0x26fa3
-	; It's a poster of a cute PIKACHU.
-	text_jump UnknownText_0x1bc570
-	db "@"
-; 0x26fa8
-
-DecorationDesc_ClefairyPoster: ; 0x26fa8
-	jumptext .ClefairyPosterText
-; 0x26fab
-
-.ClefairyPosterText: ; 0x26fab
-	; It's a poster of a cute CLEFAIRY.
-	text_jump UnknownText_0x1bc591
-	db "@"
-; 0x26fb0
-
-DecorationDesc_JigglypuffPoster: ; 0x26fb0
-	jumptext .JigglypuffPosterText
-; 0x26fb3
-
-.JigglypuffPosterText: ; 0x26fb3
-	; It's a poster of a cute JIGGLYPUFF.
-	text_jump UnknownText_0x1bc5b3
-	db "@"
-; 0x26fb8
-
-DecorationDesc_NullPoster: ; 26fb8
-	end
-; 26fb9
-
-DecorationDesc_LeftOrnament: ; 26fb9
-	ld a, [wDecoLeftOrnament]
-	jr DecorationDesc_OrnamentOrConsole
-
-DecorationDesc_RightOrnament: ; 26fbe
-	ld a, [wDecoRightOrnament]
-	jr DecorationDesc_OrnamentOrConsole
-
-DecorationDesc_Console: ; 26fc3
-	ld a, [wDecoConsole]
-	jr DecorationDesc_OrnamentOrConsole
-
-DecorationDesc_OrnamentOrConsole: ; 26fc8
-	ld c, a
-	ld de, wStringBuffer3
-	call GetDecorationName_c_de
-	ld b, BANK(.OrnamentConsoleScript)
-	ld de, .OrnamentConsoleScript
-	ret
-; 26fd5
-
-.OrnamentConsoleScript: ; 26fd5
-	jumptext .OrnamentConsoleText
-; 26fd8
-
-.OrnamentConsoleText: ; 0x26fd8
-	; It's an adorable @ .
-	text_jump UnknownText_0x1bc5d7
-	db "@"
-; 0x26fdd
-
-DecorationDesc_GiantOrnament: ; 26fdd
-	ld b, BANK(.BigDollScript)
-	ld de, .BigDollScript
-	ret
-; 26fe3
-
-.BigDollScript: ; 26fe3
-	jumptext .BigDollText
-; 26fe6
-
-.BigDollText: ; 0x26fe6
-	; A giant doll! It's fluffy and cuddly.
-	text_jump UnknownText_0x1bc5ef
-	db "@"
-; 0x26feb
-
-ToggleMaptileDecorations: ; 26feb
-	lb de, 0, 4
-	ld a, [wDecoBed]
-	call SetDecorationTile
-	lb de, 7, 4
-	ld a, [wDecoPlant]
-	call SetDecorationTile
-	lb de, 6, 0
-	ld a, [wDecoPoster]
-	call SetDecorationTile
-	call SetPosterVisibility
-	lb de, 0, 0
-	call PadCoords_de
-	ld a, [wDecoCarpet]
-	and a
-	ret z
-	call _GetDecorationSprite
-	ld [hl], a
-	push af
-	lb de, 0, 2
-	call PadCoords_de
-	pop af
-	inc a
-	ld [hli], a
-	inc a
-	ld [hli], a
-	dec a
-	ld [hl], a
-	ret
-; 27027
-
-SetPosterVisibility: ; 27027
-	ld b, SET_FLAG
-	ld a, [wDecoPoster]
-	and a
-	jr nz, .ok
-	ld b, RESET_FLAG
-
-.ok
-	ld de, EVENT_PLAYERS_ROOM_POSTER
-	jp EventFlagAction
-; 27037
-
-SetDecorationTile: ; 27037
-	push af
-	call PadCoords_de
-	pop af
-	and a
-	ret z
-	call _GetDecorationSprite
-	ld [hl], a
-	ret
-; 27043
-
-ToggleDecorationsVisibility: ; 27043
-	ld de, EVENT_PLAYERS_HOUSE_2F_CONSOLE
-	ld hl, wVariableSprites + SPRITE_CONSOLE - SPRITE_VARS
-	ld a, [wDecoConsole]
-	call ToggleDecorationVisibility
-	ld de, EVENT_PLAYERS_HOUSE_2F_DOLL_1
-	ld hl, wVariableSprites + SPRITE_DOLL_1 - SPRITE_VARS
-	ld a, [wDecoLeftOrnament]
-	call ToggleDecorationVisibility
-	ld de, EVENT_PLAYERS_HOUSE_2F_DOLL_2
-	ld hl, wVariableSprites + SPRITE_DOLL_2 - SPRITE_VARS
-	ld a, [wDecoRightOrnament]
-	call ToggleDecorationVisibility
-	ld de, EVENT_PLAYERS_HOUSE_2F_BIG_DOLL
-	ld hl, wVariableSprites + SPRITE_BIG_DOLL - SPRITE_VARS
-	ld a, [wDecoBigDoll]
-	call ToggleDecorationVisibility
-	ret
-; 27074
-
-ToggleDecorationVisibility: ; 27074
-	and a
-	jr z, .hide
-	call _GetDecorationSprite
-	ld [hl], a
-	ld b, RESET_FLAG
-	jp EventFlagAction
-
-.hide
-	ld b, SET_FLAG
-	jp EventFlagAction
-; 27085
-
-_GetDecorationSprite: ; 27085
-	ld c, a
-	push de
-	push hl
-	farcall GetDecorationSprite
-	pop hl
-	pop de
-	ld a, c
-	ret
-; 27092
-
-PadCoords_de: ; 27092
-	ld a, d
-	add 4
-	ld d, a
-	ld a, e
-	add 4
-	ld e, a
-	call GetBlockLocation
-	ret
--- a/engine/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/diploma.asm
+++ /dev/null
@@ -1,93 +1,0 @@
-_Diploma: ; 1dd702
-	call PlaceDiplomaOnScreen
-	call WaitPressAorB_BlinkCursor
-	ret
-; 1dd709
-
-PlaceDiplomaOnScreen: ; 1dd709
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	call DisableLCD
-	ld hl, DiplomaGFX
-	ld de, vTiles2
-	call Decompress
-	ld hl, DiplomaPage1Tilemap
-	decoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	call CopyBytes
-	ld de, .Player
-	hlcoord 2, 5
-	call PlaceString
-	ld de, .EmptyString
-	hlcoord 15, 5
-	call PlaceString
-	ld de, wPlayerName
-	hlcoord 9, 5
-	call PlaceString
-	ld de, .Certification
-	hlcoord 2, 8
-	call PlaceString
-	call EnableLCD
-	call WaitBGMap
-	ld b, SCGB_DIPLOMA
-	call GetSGBLayout
-	call SetPalettes
-	call DelayFrame
-	ret
-; 1dd760
-
-.Player:
-	db "PLAYER@"
-
-.EmptyString:
-	db "@"
-
-.Certification:
-	db   "This certifies"
-	next "that you have"
-	next "completed the"
-	next "new #DEX."
-	next "Congratulations!"
-	db   "@"
-; 1dd7ae
-
-PrintDiplomaPage2: ; 1dd7ae
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, $7f
-	call ByteFill
-	ld hl, DiplomaPage2Tilemap
-	decoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	call CopyBytes
-	ld de, .GameFreak
-	hlcoord 8, 0
-	call PlaceString
-	ld de, .PlayTime
-	hlcoord 3, 15
-	call PlaceString
-	hlcoord 12, 15
-	ld de, wGameTimeHours
-	lb bc, 2, 4
-	call PrintNum
-	ld [hl], $67 ; colon
-	inc hl
-	ld de, wGameTimeMinutes
-	lb bc, PRINTNUM_LEADINGZEROS | 1, 2
-	call PrintNum
-	ret
-; 1dd7f0
-
-.PlayTime: db "PLAY TIME@"
-.GameFreak: db "GAME FREAK@"
-; 1dd805
-
-DiplomaGFX: ; 1dd805
-INCBIN "gfx/diploma/diploma.2bpp.lz"
-
-DiplomaPage1Tilemap: ; 1ddc4b
-INCBIN "gfx/diploma/page1.tilemap"
-
-DiplomaPage2Tilemap: ; 1dddb3
-INCBIN "gfx/diploma/page2.tilemap"
--- a/engine/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/european_mail.asm
+++ /dev/null
@@ -1,129 +1,0 @@
-IsMailEuropean: ; 1de5c8
-; return 1 if French
-; return 2 if German
-; return 3 if Italian
-; return 4 if Spanish
-; return 0 if none of the above
-	ld c, $0
-	ld hl, sPartyMon1MailAuthorNationality - sPartyMon1Mail
-	add hl, de
-	ld a, [hli]
-	cp "E"
-	ret nz
-	ld a, [hli]
-	inc c
-	cp "F"
-	ret z
-	inc c
-	cp "G"
-	ret z
-	inc c
-	cp "I"
-	ret z
-	inc c
-	cp "S"
-	ret z
-	ld c, $0
-	ret
-
-; The regular font.
-StandardEnglishFont: ; 1de5e6
-INCBIN "gfx/font/english.1bpp"
-
-; An extended font.
-FrenchGermanFont: ; 1de9e6
-INCBIN "gfx/font/french_german.1bpp"
-
-; An even more extended font.
-SpanishItalianFont: ; 1dede6
-INCBIN "gfx/font/spanish_italian.1bpp"
-
-HandleFrenchGermanMail: ; 1df1e6
-; called if mail is french or german
-; fix 's 't 'v
-	ld b, sPartyMon1MailAuthor - sPartyMon1Mail
-	ld h, d
-	ld l, e
-.loop
-	ld a, [hl]
-	cp $dc ; 's in french/german font
-	jr nz, .check_intermediate_chars
-	ld a, "'s"
-	jr .replace
-
-.check_intermediate_chars
-	sub "'s"
-	jr c, .dont_replace
-	cp "'v" - "'s" + 1
-	jr nc, .dont_replace
-	add $cd
-
-.replace
-	ld [hl], a
-
-.dont_replace
-	inc hl
-	dec b
-	jr nz, .loop
-	ret
-
-LireLeCourrierAnglais:
-DeutenEnglischenPost: ; 1df203
-; Cette fonction convertit certains des caractères anglais pour
-; leur équivalent dans le jeu de caractères français.
-; Diese Funktion wandelt bestimmte englische Zeichen, um ihre
-; Entsprechung in der Deutschen-Zeichensatz.
-	ld b, sPartyMon1MailAuthor - sPartyMon1Mail
-	ld h, d
-	ld l, e
-.loop
-	ld a, [hl]
-	cp "'s"
-	jr nz, .check_intermediate_chars
-	ld a, $dc
-	jr .replace
-
-.check_intermediate_chars
-	sub $cd
-	jr c, .dont_replace
-	cp "'v" - "'s" + 1
-	jr nc, .dont_replace
-	add "'s"
-
-.replace
-	ld [hl], a
-
-.dont_replace
-	inc hl
-	dec b
-	jr nz, .loop
-	ret
-
-HandleSpanishItalianMail: ; 1df220
-LeerCorreosIngleses:
-LeggiPostaInglese:
-; This function converts certain characters between
-; the English and Spanish/Italian character sets.
-; Esta función convierte ciertos caracteres entre
-; el juego de caracteres Inglés y Español.
-; Questa funzione converte alcuni caratteri tra
-; l'inglese e il set di caratteri italiani.
-	ld b, sPartyMon1MailAuthor - sPartyMon1Mail
-	ld h, d
-	ld l, e
-.loop
-	ld a, [hl]
-	and $f0
-	cp $d0
-	jr nz, .dont_replace
-	ld a, [hl]
-	add $8
-	and $f
-	or $d0
-	ld [hl], a
-
-.dont_replace
-	inc hl
-	dec b
-	jr nz, .loop
-	ret
--- a/engine/events.asm
+++ /dev/null
@@ -1,1111 +1,0 @@
-INCLUDE "constants.asm"
-
-
-SECTION "Events", ROMX
-
-OverworldLoop:: ; 966b0
-	xor a
-	ld [wMapStatus], a
-.loop
-	ld a, [wMapStatus]
-	ld hl, .jumps
-	rst JumpTable
-	ld a, [wMapStatus]
-	cp 3 ; done
-	jr nz, .loop
-.done
-	ret
-
-.jumps
-	dw StartMap
-	dw EnterMap
-	dw HandleMap
-	dw .done
-; 966cb
-
-DisableEvents: ; 966cb
-	xor a
-	ld [wScriptFlags3], a
-	ret
-; 966d0
-
-EnableEvents:: ; 966d0
-	ld a, $ff
-	ld [wScriptFlags3], a
-	ret
-; 966d6
-
-CheckBit5_ScriptFlags3: ; 966d6
-	ld hl, wScriptFlags3
-	bit 5, [hl]
-	ret
-; 966dc
-
-DisableWarpsConnxns: ; 966dc
-	ld hl, wScriptFlags3
-	res 2, [hl]
-	ret
-; 966e2
-
-DisableCoordEvents: ; 966e2
-	ld hl, wScriptFlags3
-	res 1, [hl]
-	ret
-; 966e8
-
-DisableStepCount: ; 966e8
-	ld hl, wScriptFlags3
-	res 0, [hl]
-	ret
-; 966ee
-
-DisableWildEncounters: ; 966ee
-	ld hl, wScriptFlags3
-	res 4, [hl]
-	ret
-; 966f4
-
-EnableWarpsConnxns: ; 966f4
-	ld hl, wScriptFlags3
-	set 2, [hl]
-	ret
-; 966fa
-
-EnableCoordEvents: ; 966fa
-	ld hl, wScriptFlags3
-	set 1, [hl]
-	ret
-; 96700
-
-EnableStepCount: ; 96700
-	ld hl, wScriptFlags3
-	set 0, [hl]
-	ret
-; 96706
-
-EnableWildEncounters: ; 96706
-	ld hl, wScriptFlags3
-	set 4, [hl]
-	ret
-; 9670c
-
-CheckWarpConnxnScriptFlag: ; 9670c
-	ld hl, wScriptFlags3
-	bit 2, [hl]
-	ret
-; 96712
-
-CheckCoordEventScriptFlag: ; 96712
-	ld hl, wScriptFlags3
-	bit 1, [hl]
-	ret
-; 96718
-
-CheckStepCountScriptFlag: ; 96718
-	ld hl, wScriptFlags3
-	bit 0, [hl]
-	ret
-; 9671e
-
-CheckWildEncountersScriptFlag: ; 9671e
-	ld hl, wScriptFlags3
-	bit 4, [hl]
-	ret
-; 96724
-
-StartMap: ; 96724
-	xor a
-	ld [wScriptVar], a
-	xor a
-	ld [wScriptRunning], a
-	ld hl, wMapStatus
-	ld bc, wMapStatusEnd - wMapStatus
-	call ByteFill
-	farcall InitCallReceiveDelay
-	call ClearJoypad
-EnterMap: ; 9673e
-	xor a
-	ld [wXYComparePointer], a
-	ld [wXYComparePointer + 1], a
-	call SetUpFiveStepWildEncounterCooldown
-	farcall RunMapSetupScript
-	call DisableEvents
-
-	ld a, [hMapEntryMethod]
-	cp MAPSETUP_CONNECTION
-	jr nz, .dont_enable
-	call EnableEvents
-.dont_enable
-
-	ld a, [hMapEntryMethod]
-	cp MAPSETUP_RELOADMAP
-	jr nz, .dontresetpoison
-	xor a
-	ld [wPoisonStepCount], a
-.dontresetpoison
-
-	xor a ; end map entry
-	ld [hMapEntryMethod], a
-	ld a, 2 ; HandleMap
-	ld [wMapStatus], a
-	ret
-; 9676d
-
-UnusedWait30Frames: ; 9676d
-	ld c, 30
-	call DelayFrames
-	ret
-; 96773
-
-HandleMap: ; 96773
-	call ResetOverworldDelay
-	call HandleMapTimeAndJoypad
-	farcall HandleCmdQueue ; no need to farcall
-	call MapEvents
-
-; Not immediately entering a connected map will cause problems.
-	ld a, [wMapStatus]
-	cp 2 ; HandleMap
-	ret nz
-
-	call HandleMapObjects
-	call NextOverworldFrame
-	call HandleMapBackground
-	call CheckPlayerState
-	ret
-; 96795
-
-MapEvents: ; 96795
-	ld a, [wMapEventStatus]
-	ld hl, .jumps
-	rst JumpTable
-	ret
-
-.jumps
-	dw .events
-	dw .no_events
-; 967a1
-
-.events ; 967a1
-	call PlayerEvents
-	call DisableEvents
-	farcall ScriptEvents
-	ret
-; 967ae
-
-.no_events ; 967ae
-	ret
-; 967af
-
-MaxOverworldDelay: ; 967af
-	db 2
-; 967b0
-
-ResetOverworldDelay: ; 967b0
-	ld a, [MaxOverworldDelay]
-	ld [wOverworldDelay], a
-	ret
-; 967b7
-
-NextOverworldFrame: ; 967b7
-	ld a, [wOverworldDelay]
-	and a
-	ret z
-	ld c, a
-	call DelayFrames
-	ret
-; 967c1
-
-HandleMapTimeAndJoypad: ; 967c1
-	ld a, [wMapEventStatus]
-	cp 1 ; no events
-	ret z
-
-	call UpdateTime
-	call GetJoypad
-	call TimeOfDayPals
-	ret
-; 967d1
-
-HandleMapObjects: ; 967d1
-	farcall HandleNPCStep ; engine/map_objects.asm
-	farcall _HandlePlayerStep
-	call _CheckObjectEnteringVisibleRange
-	ret
-; 967e1
-
-HandleMapBackground: ; 967e1
-	farcall _UpdateSprites
-	farcall ScrollScreen
-	farcall PlaceMapNameSign
-	ret
-; 967f4
-
-CheckPlayerState: ; 967f4
-	ld a, [wPlayerStepFlags]
-	bit 5, a ; in the middle of step
-	jr z, .events
-	bit 6, a ; stopping step
-	jr z, .noevents
-	bit 4, a ; in midair
-	jr nz, .noevents
-	call EnableEvents
-.events
-	ld a, 0 ; events
-	ld [wMapEventStatus], a
-	ret
-
-.noevents
-	ld a, 1 ; no events
-	ld [wMapEventStatus], a
-	ret
-; 96812
-
-_CheckObjectEnteringVisibleRange: ; 96812
-	ld hl, wPlayerStepFlags
-	bit 6, [hl]
-	ret z
-	farcall CheckObjectEnteringVisibleRange
-	ret
-; 9681f
-
-PlayerEvents: ; 9681f
-	xor a
-; If there's already a player event, don't interrupt it.
-	ld a, [wScriptRunning]
-	and a
-	ret nz
-
-	call Dummy_CheckScriptFlags3Bit5 ; This is a waste of time
-
-	call CheckTrainerBattle3
-	jr c, .ok
-
-	call CheckTileEvent
-	jr c, .ok
-
-	call RunMemScript
-	jr c, .ok
-
-	call RunSceneScript
-	jr c, .ok
-
-	call CheckTimeEvents
-	jr c, .ok
-
-	call OWPlayerInput
-	jr c, .ok
-
-	xor a
-	ret
-
-.ok
-	push af
-	farcall EnableScriptMode
-	pop af
-
-	ld [wScriptRunning], a
-	call DoPlayerEvent
-	ld a, [wScriptRunning]
-	cp PLAYEREVENT_CONNECTION
-	jr z, .ok2
-	cp PLAYEREVENT_JOYCHANGEFACING
-	jr z, .ok2
-
-	xor a
-	ld [wLandmarkSignTimer], a
-
-.ok2
-	scf
-	ret
-; 96867
-
-CheckTrainerBattle3: ; 96867
-	nop
-	nop
-	call CheckTrainerBattle2
-	jr nc, .nope
-
-	ld a, PLAYEREVENT_SEENBYTRAINER
-	scf
-	ret
-
-.nope
-	xor a
-	ret
-; 96874
-
-CheckTileEvent: ; 96874
-; Check for warps, coord events, or wild battles.
-
-	call CheckWarpConnxnScriptFlag
-	jr z, .connections_disabled
-
-	farcall CheckMovingOffEdgeOfMap
-	jr c, .map_connection
-
-	call CheckWarpTile
-	jr c, .warp_tile
-
-.connections_disabled
-	call CheckCoordEventScriptFlag
-	jr z, .coord_events_disabled
-
-	call CheckCurrentMapCoordEvents
-	jr c, .coord_event
-
-.coord_events_disabled
-	call CheckStepCountScriptFlag
-	jr z, .step_count_disabled
-
-	call CountStep
-	ret c
-
-.step_count_disabled
-	call CheckWildEncountersScriptFlag
-	jr z, .ok
-
-	call RandomEncounter
-	ret c
-	jr .ok ; pointless
-
-.ok
-	xor a
-	ret
-
-.map_connection
-	ld a, PLAYEREVENT_CONNECTION
-	scf
-	ret
-
-.warp_tile
-	ld a, [wPlayerStandingTile]
-	call CheckPitTile
-	jr nz, .not_pit
-	ld a, PLAYEREVENT_FALL
-	scf
-	ret
-
-.not_pit
-	ld a, PLAYEREVENT_WARP
-	scf
-	ret
-
-.coord_event
-	ld hl, wCurCoordEventScriptAddr
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	call GetMapScriptsBank
-	call CallScript
-	ret
-; 968c7
-
-CheckWildEncounterCooldown:: ; 968c7
-	ld hl, wWildEncounterCooldown
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-	ret z
-	scf
-	ret
-; 968d1
-
-SetUpFiveStepWildEncounterCooldown: ; 968d1
-	ld a, 5
-	ld [wWildEncounterCooldown], a
-	ret
-; 968d7
-
-ret_968d7: ; 968d7
-	ret
-;968d8
-
-SetMinTwoStepWildEncounterCooldown: ; 968d8
-	ld a, [wWildEncounterCooldown]
-	cp 2
-	ret nc
-	ld a, 2
-	ld [wWildEncounterCooldown], a
-	ret
-; 968e4
-
-Dummy_CheckScriptFlags3Bit5: ; 968e4
-	call CheckBit5_ScriptFlags3
-	ret z
-	call ret_2f3e
-	ret
-; 968ec
-
-RunSceneScript: ; 968ec
-	ld a, [wCurrMapSceneScriptCount]
-	and a
-	jr z, .nope
-
-	ld c, a
-	call CheckScenes
-	cp c
-	jr nc, .nope
-
-	ld e, a
-	ld d, 0
-	ld hl, wCurrMapSceneScriptsPointer
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-rept 4
-	add hl, de
-endr
-
-	call GetMapScriptsBank
-	call GetFarHalfword
-	call GetMapScriptsBank
-	call CallScript
-
-	ld hl, wScriptFlags
-	res 3, [hl]
-
-	farcall EnableScriptMode
-	farcall ScriptEvents
-
-	ld hl, wScriptFlags
-	bit 3, [hl]
-	jr z, .nope
-
-	ld hl, wPriorityScriptAddr
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [wPriorityScriptBank]
-	call CallScript
-	scf
-	ret
-
-.nope
-	xor a
-	ret
-; 9693a
-
-CheckTimeEvents: ; 9693a
-	ld a, [wLinkMode]
-	and a
-	jr nz, .nothing
-
-	ld hl, wStatusFlags2
-	bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
-	jr z, .do_daily
-
-	farcall CheckBugContestTimer
-	jr c, .end_bug_contest
-	xor a
-	ret
-
-.do_daily
-	farcall CheckDailyResetTimer
-	farcall CheckPokerusTick
-	farcall CheckPhoneCall
-	ret c
-
-.nothing
-	xor a
-	ret
-
-.end_bug_contest
-	ld a, BANK(BugCatchingContestOverScript)
-	ld hl, BugCatchingContestOverScript
-	call CallScript
-	scf
-	ret
-; 96970
-
-.unused ; 96970
-	ld a, 8
-	scf
-	ret
-; 96974
-
-OWPlayerInput: ; 96974
-
-	call PlayerMovement
-	ret c
-	and a
-	jr nz, .NoAction
-
-; Can't perform button actions while sliding on ice.
-	farcall CheckStandingOnIce
-	jr c, .NoAction
-
-	call CheckAPressOW
-	jr c, .Action
-
-	call CheckMenuOW
-	jr c, .Action
-
-.NoAction:
-	xor a
-	ret
-
-.Action:
-	push af
-	farcall StopPlayerForEvent
-	pop af
-	scf
-	ret
-; 96999
-
-CheckAPressOW: ; 96999
-	ld a, [hJoyPressed]
-	and A_BUTTON
-	ret z
-	call TryObjectEvent
-	ret c
-	call TryBGEvent
-	ret c
-	call TryTileCollisionEvent
-	ret c
-	xor a
-	ret
-; 969ac
-
-PlayTalkObject: ; 969ac
-	push de
-	ld de, SFX_READ_TEXT_2
-	call PlaySFX
-	pop de
-	ret
-; 969b5
-
-TryObjectEvent: ; 969b5
-	farcall CheckFacingObject
-	jr c, .IsObject
-	xor a
-	ret
-
-.IsObject:
-	call PlayTalkObject
-	ld a, [hObjectStructIndexBuffer]
-	call GetObjectStruct
-	ld hl, OBJECT_MAP_OBJECT_INDEX
-	add hl, bc
-	ld a, [hl]
-	ld [hLastTalked], a
-
-	ld a, [hLastTalked]
-	call GetMapObject
-	ld hl, MAPOBJECT_COLOR
-	add hl, bc
-	ld a, [hl]
-	and %00001111
-
-; Bug: If IsInArray returns nc, data at bc will be executed as code.
-	push bc
-	ld de, 3
-	ld hl, .pointers
-	call IsInArray
-	jr nc, .nope_bugged
-	pop bc
-
-	inc hl
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-.nope_bugged
-	; pop bc
-	xor a
-	ret
-
-.pointers
-	dbw OBJECTTYPE_SCRIPT, .script
-	dbw OBJECTTYPE_ITEMBALL, .itemball
-	dbw OBJECTTYPE_TRAINER, .trainer
-	; the remaining four are dummy events
-	dbw OBJECTTYPE_3, .three
-	dbw OBJECTTYPE_4, .four
-	dbw OBJECTTYPE_5, .five
-	dbw OBJECTTYPE_6, .six
-	db -1
-; 96a04
-
-.script ; 96a04
-	ld hl, MAPOBJECT_SCRIPT_POINTER
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	call GetMapScriptsBank
-	call CallScript
-	ret
-; 96a12
-
-.itemball ; 96a12
-	ld hl, MAPOBJECT_SCRIPT_POINTER
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	call GetMapScriptsBank
-	ld de, wEngineBuffer1
-	ld bc, 2
-	call FarCopyBytes
-	ld a, PLAYEREVENT_ITEMBALL
-	scf
-	ret
-; 96a29
-
-.trainer ; 96a29
-	call TalkToTrainer
-	ld a, PLAYEREVENT_TALKTOTRAINER
-	scf
-	ret
-; 96a30
-
-.three ; 96a30
-	xor a
-	ret
-; 96a32
-
-.four ; 96a32
-	xor a
-	ret
-; 96a34
-
-.five ; 96a34
-	xor a
-	ret
-; 96a36
-
-.six ; 96a36
-	xor a
-	ret
-; 96a38
-
-TryBGEvent: ; 96a38
-	call CheckFacingBGEvent
-	jr c, .is_bg_event
-	xor a
-	ret
-
-.is_bg_event:
-	ld a, [wEngineBuffer3]
-	ld hl, .bg_events
-	rst JumpTable
-	ret
-
-.bg_events
-	dw .read
-	dw .up
-	dw .down
-	dw .right
-	dw .left
-	dw .ifset
-	dw .ifnotset
-	dw .itemifset
-	dw .copy
-; 96a59
-
-.up
-	ld b, OW_UP
-	jr .checkdir
-.down
-	ld b, OW_DOWN
-	jr .checkdir
-.right
-	ld b, OW_RIGHT
-	jr .checkdir
-.left
-	ld b, OW_LEFT
-	jr .checkdir
-
-.checkdir
-	ld a, [wPlayerDirection]
-	and %1100
-	cp b
-	jp nz, .dontread
-
-.read
-	call PlayTalkObject
-	ld hl, wEngineBuffer4
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	call GetMapScriptsBank
-	call CallScript
-	scf
-	ret
-
-.itemifset
-	call CheckBGEventFlag
-	jp nz, .dontread
-	call PlayTalkObject
-	call GetMapScriptsBank
-	ld de, wEngineBuffer1
-	ld bc, 3
-	call FarCopyBytes
-	ld a, BANK(HiddenItemScript)
-	ld hl, HiddenItemScript
-	call CallScript
-	scf
-	ret
-
-.copy
-	call CheckBGEventFlag
-	jr nz, .dontread
-	call GetMapScriptsBank
-	ld de, wEngineBuffer1
-	ld bc, 3
-	call FarCopyBytes
-	jr .dontread
-
-.ifset
-	call CheckBGEventFlag
-	jr z, .dontread
-	jr .thenread
-
-.ifnotset
-	call CheckBGEventFlag
-	jr nz, .dontread
-
-.thenread
-	push hl
-	call PlayTalkObject
-	pop hl
-	inc hl
-	inc hl
-	call GetMapScriptsBank
-	call GetFarHalfword
-	call GetMapScriptsBank
-	call CallScript
-	scf
-	ret
-
-.dontread
-	xor a
-	ret
-; 96ad8
-
-CheckBGEventFlag: ; 96ad8
-	ld hl, wEngineBuffer4
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	push hl
-	call GetMapScriptsBank
-	call GetFarHalfword
-	ld e, l
-	ld d, h
-	ld b, CHECK_FLAG
-	call EventFlagAction
-	ld a, c
-	and a
-	pop hl
-	ret
-; 96af0
-
-PlayerMovement: ; 96af0
-	farcall DoPlayerMovement
-	ld a, c
-	ld hl, .pointers
-	rst JumpTable
-	ld a, c
-	ret
-; 96afd
-
-.pointers
-	dw .zero
-	dw .one
-	dw .two
-	dw .three
-	dw .four
-	dw .five
-	dw .six
-	dw .seven
-
-.zero
-.four ; 96b0d
-	xor a
-	ld c, a
-	ret
-; 96b10
-
-.seven ; 96b10
-	call ret_968d7 ; mobile
-	xor a
-	ld c, a
-	ret
-; 96b16
-
-.one ; 96b16
-	ld a, 5
-	ld c, a
-	scf
-	ret
-; 96b1b
-
-.two ; 96b1b
-	ld a, 9
-	ld c, a
-	scf
-	ret
-; 96b20
-
-.three ; 96b20
-; force the player to move in some direction
-	ld a, BANK(Script_ForcedMovement)
-	ld hl, Script_ForcedMovement
-	call CallScript
-;	ld a, -1
-	ld c, a
-	scf
-	ret
-; 96b2b
-
-.five
-.six ; 96b2b
-	ld a, -1
-	ld c, a
-	and a
-	ret
-; 96b30
-
-CheckMenuOW: ; 96b30
-	xor a
-	ld [hMenuReturn], a
-	ld [hMenuReturn + 1], a
-	ld a, [hJoyPressed]
-
-	bit SELECT_F, a
-	jr nz, .Select
-
-	bit START_F, a
-	jr z, .NoMenu
-
-	ld a, BANK(StartMenuScript)
-	ld hl, StartMenuScript
-	call CallScript
-	scf
-	ret
-
-.NoMenu:
-	xor a
-	ret
-
-.Select:
-	call PlayTalkObject
-	ld a, BANK(SelectMenuScript)
-	ld hl, SelectMenuScript
-	call CallScript
-	scf
-	ret
-; 96b58
-
-StartMenuScript: ; 96b58
-	callasm StartMenu
-	jump StartMenuCallback
-; 96b5f
-
-SelectMenuScript: ; 96b5f
-	callasm SelectMenu
-	jump SelectMenuCallback
-; 96b66
-
-StartMenuCallback:
-SelectMenuCallback: ; 96b66
-	copybytetovar hMenuReturn
-	ifequal HMENURETURN_SCRIPT, .Script
-	ifequal HMENURETURN_ASM, .Asm
-	end
-; 96b72
-
-.Script: ; 96b72
-	ptjump wQueuedScriptBank
-; 96b75
-
-.Asm: ; 96b75
-	ptcallasm wQueuedScriptBank
-	end
-; 96b79
-
-CountStep: ; 96b79
-	; Don't count steps in link communication rooms.
-	ld a, [wLinkMode]
-	and a
-	jr nz, .done
-
-	; If there is a special phone call, don't count the step.
-	farcall CheckSpecialPhoneCall
-	jr c, .doscript
-
-	; If Repel wore off, don't count the step.
-	call DoRepelStep
-	jr c, .doscript
-
-	; Count the step for poison and total steps
-	ld hl, wPoisonStepCount
-	inc [hl]
-	ld hl, wStepCount
-	inc [hl]
-	; Every 256 steps, increase the happiness of all your Pokemon.
-	jr nz, .skip_happiness
-
-	farcall StepHappiness
-
-.skip_happiness
-	; Every 256 steps, offset from the happiness incrementor by 128 steps,
-	; decrease the hatch counter of all your eggs until you reach the first
-	; one that is ready to hatch.
-	ld a, [wStepCount]
-	cp $80
-	jr nz, .skip_egg
-
-	farcall DoEggStep
-	jr nz, .hatch
-
-.skip_egg
-	; Increase the EXP of (both) DayCare Pokemon by 1.
-	farcall DayCareStep
-
-	; Every four steps, deal damage to all Poisoned Pokemon
-	ld hl, wPoisonStepCount
-	ld a, [hl]
-	cp 4
-	jr c, .skip_poison
-	ld [hl], 0
-
-	farcall DoPoisonStep
-	jr c, .doscript
-
-.skip_poison
-	farcall DoBikeStep
-
-.done
-	xor a
-	ret
-
-.doscript
-	ld a, -1
-	scf
-	ret
-
-.hatch
-	ld a, 8
-	scf
-	ret
-; 96bd3
-
-; unused
-.unreferenced ; 96bd3
-	ld a, 7
-	scf
-	ret
-; 96bd7
-
-DoRepelStep: ; 96bd7
-	ld a, [wRepelEffect]
-	and a
-	ret z
-
-	dec a
-	ld [wRepelEffect], a
-	ret nz
-
-	ld a, BANK(RepelWoreOffScript)
-	ld hl, RepelWoreOffScript
-	call CallScript
-	scf
-	ret
-; 96beb
-
-DoPlayerEvent: ; 96beb
-	ld a, [wScriptRunning]
-	and a
-	ret z
-
-	cp PLAYEREVENT_MAPSCRIPT ; run script
-	ret z
-
-	cp NUM_PLAYER_EVENTS
-	ret nc
-
-	ld c, a
-	ld b, 0
-	ld hl, PlayerEventScriptPointers
-	add hl, bc
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld [wScriptBank], a
-	ld a, [hli]
-	ld [wScriptPos], a
-	ld a, [hl]
-	ld [wScriptPos + 1], a
-	ret
-; 96c0c
-
-PlayerEventScriptPointers: ; 96c0c
-	dba Invalid_0x96c2d          ; 0
-	dba SeenByTrainerScript      ; 1
-	dba TalkToTrainerScript      ; 2
-	dba FindItemInBallScript     ; 3
-	dba EdgeWarpScript           ; 4
-	dba WarpToNewMapScript       ; 5
-	dba FallIntoMapScript        ; 6
-	dba Script_OverworldWhiteout ; 7
-	dba HatchEggScript           ; 8
-	dba ChangeDirectionScript    ; 9
-	dba Invalid_0x96c2d          ; 10
-; 96c2d
-
-Invalid_0x96c2d: ; 96c2d
-	end
-; 96c2e
-
-; unused
-	end
-; 96c2f
-
-HatchEggScript: ; 96c2f
-	callasm OverworldHatchEgg
-	end
-; 96c34
-
-WarpToNewMapScript: ; 96c34
-	warpsound
-	newloadmap MAPSETUP_DOOR
-	end
-; 96c38
-
-FallIntoMapScript: ; 96c38
-	newloadmap MAPSETUP_FALL
-	playsound SFX_KINESIS
-	applymovement PLAYER, MovementData_0x96c48
-	playsound SFX_STRENGTH
-	scall LandAfterPitfallScript
-	end
-; 96c48
-
-MovementData_0x96c48: ; 96c48
-	skyfall
-	step_end
-; 96c4a
-
-LandAfterPitfallScript: ; 96c4a
-	earthquake 16
-	end
-; 96c4d
-
-EdgeWarpScript: ; 4
-	reloadandreturn MAPSETUP_CONNECTION
-; 96c4f
-
-ChangeDirectionScript: ; 9
-	deactivatefacing 3
-	callasm EnableWildEncounters
-	end
-; 96c56
-
-INCLUDE "engine/scripting.asm"
-
-INCLUDE "engine/events_2.asm"
--- /dev/null
+++ b/engine/events/diploma.asm
@@ -1,0 +1,93 @@
+_Diploma: ; 1dd702
+	call PlaceDiplomaOnScreen
+	call WaitPressAorB_BlinkCursor
+	ret
+; 1dd709
+
+PlaceDiplomaOnScreen: ; 1dd709
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	call DisableLCD
+	ld hl, DiplomaGFX
+	ld de, vTiles2
+	call Decompress
+	ld hl, DiplomaPage1Tilemap
+	decoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	call CopyBytes
+	ld de, .Player
+	hlcoord 2, 5
+	call PlaceString
+	ld de, .EmptyString
+	hlcoord 15, 5
+	call PlaceString
+	ld de, wPlayerName
+	hlcoord 9, 5
+	call PlaceString
+	ld de, .Certification
+	hlcoord 2, 8
+	call PlaceString
+	call EnableLCD
+	call WaitBGMap
+	ld b, SCGB_DIPLOMA
+	call GetSGBLayout
+	call SetPalettes
+	call DelayFrame
+	ret
+; 1dd760
+
+.Player:
+	db "PLAYER@"
+
+.EmptyString:
+	db "@"
+
+.Certification:
+	db   "This certifies"
+	next "that you have"
+	next "completed the"
+	next "new #DEX."
+	next "Congratulations!"
+	db   "@"
+; 1dd7ae
+
+PrintDiplomaPage2: ; 1dd7ae
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, $7f
+	call ByteFill
+	ld hl, DiplomaPage2Tilemap
+	decoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	call CopyBytes
+	ld de, .GameFreak
+	hlcoord 8, 0
+	call PlaceString
+	ld de, .PlayTime
+	hlcoord 3, 15
+	call PlaceString
+	hlcoord 12, 15
+	ld de, wGameTimeHours
+	lb bc, 2, 4
+	call PrintNum
+	ld [hl], $67 ; colon
+	inc hl
+	ld de, wGameTimeMinutes
+	lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+	call PrintNum
+	ret
+; 1dd7f0
+
+.PlayTime: db "PLAY TIME@"
+.GameFreak: db "GAME FREAK@"
+; 1dd805
+
+DiplomaGFX: ; 1dd805
+INCBIN "gfx/diploma/diploma.2bpp.lz"
+
+DiplomaPage1Tilemap: ; 1ddc4b
+INCBIN "gfx/diploma/page1.tilemap"
+
+DiplomaPage2Tilemap: ; 1dddb3
+INCBIN "gfx/diploma/page2.tilemap"
--- a/engine/events_2.asm
+++ /dev/null
@@ -1,650 +1,0 @@
-; More overworld event handling.
-
-
-WarpToSpawnPoint:: ; 97c28
-	ld hl, wStatusFlags2
-	res STATUSFLAGS2_SAFARI_GAME_F, [hl]
-	res STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
-	ret
-; 97c30
-
-RunMemScript:: ; 97c30
-; If there is no script here, we don't need to be here.
-	ld a, [wMapReentryScriptQueueFlag]
-	and a
-	ret z
-; Execute the script at (wMapReentryScriptBank):(wMapReentryScriptAddress).
-	ld hl, wMapReentryScriptAddress
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [wMapReentryScriptBank]
-	call CallScript
-	scf
-; Clear the buffer for the next script.
-	push af
-	xor a
-	ld hl, wMapReentryScriptQueueFlag
-	ld bc, 8
-	call ByteFill
-	pop af
-	ret
-; 97c4f
-
-LoadScriptBDE:: ; 97c4f
-; If there's already a script here, don't overwrite.
-	ld hl, wMapReentryScriptQueueFlag
-	ld a, [hl]
-	and a
-	ret nz
-; Set the flag
-	ld [hl], 1
-	inc hl
-; Load the script pointer b:de into (wMapReentryScriptBank):(wMapReentryScriptAddress)
-	ld [hl], b
-	inc hl
-	ld [hl], e
-	inc hl
-	ld [hl], d
-	scf
-	ret
-; 97c5f
-
-TryTileCollisionEvent:: ; 97c5f
-	call GetFacingTileCoord
-	ld [wEngineBuffer1], a
-	ld c, a
-	farcall CheckFacingTileForStdScript
-	jr c, .done
-
-	call CheckCutTreeTile
-	jr nz, .whirlpool
-	farcall TryCutOW
-	jr .done
-
-.whirlpool
-	ld a, [wEngineBuffer1]
-	call CheckWhirlpoolTile
-	jr nz, .waterfall
-	farcall TryWhirlpoolOW
-	jr .done
-
-.waterfall
-	ld a, [wEngineBuffer1]
-	call CheckWaterfallTile
-	jr nz, .headbutt
-	farcall TryWaterfallOW
-	jr .done
-
-.headbutt
-	ld a, [wEngineBuffer1]
-	call CheckHeadbuttTreeTile
-	jr nz, .surf
-	farcall TryHeadbuttOW
-	jr c, .done
-	jr .noevent
-
-.surf
-	farcall TrySurfOW
-	jr nc, .noevent
-	jr .done
-
-.noevent
-	xor a
-	ret
-
-.done
-	call PlayClickSFX
-	ld a, $ff
-	scf
-	ret
-; 97cc0
-
-
-RandomEncounter:: ; 97cc0
-; Random encounter
-
-	call CheckWildEncounterCooldown
-	jr c, .nope
-	call CanUseSweetScent
-	jr nc, .nope
-	ld hl, wStatusFlags2
-	bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
-	jr nz, .bug_contest
-	farcall TryWildEncounter
-	jr nz, .nope
-	jr .ok
-
-.bug_contest
-	call _TryWildEncounter_BugContest
-	jr nc, .nope
-	jr .ok_bug_contest
-
-.nope
-	ld a, 1
-	and a
-	ret
-
-.ok
-	ld a, BANK(WildBattleScript)
-	ld hl, WildBattleScript
-	jr .done
-
-.ok_bug_contest
-	ld a, BANK(BugCatchingContestBattleScript)
-	ld hl, BugCatchingContestBattleScript
-	jr .done
-
-.done
-	call CallScript
-	scf
-	ret
-; 97cf9
-
-WildBattleScript: ; 97cf9
-	randomwildmon
-	startbattle
-	reloadmapafterbattle
-	end
-; 97cfd
-
-CanUseSweetScent:: ; 97cfd
-	ld hl, wStatusFlags
-	bit STATUSFLAGS_NO_WILD_ENCOUNTERS_F, [hl]
-	jr nz, .no
-	ld a, [wEnvironment]
-	cp CAVE
-	jr z, .ice_check
-	cp DUNGEON
-	jr z, .ice_check
-	farcall CheckGrassCollision
-	jr nc, .no
-
-.ice_check
-	ld a, [wPlayerStandingTile]
-	call CheckIceTile
-	jr z, .no
-	scf
-	ret
-
-.no
-	and a
-	ret
-; 97d23
-
-_TryWildEncounter_BugContest: ; 97d23
-	call TryWildEncounter_BugContest
-	ret nc
-	call ChooseWildEncounter_BugContest
-	farcall CheckRepelEffect
-	ret
-; 97d31
-
-ChooseWildEncounter_BugContest:: ; 97d31
-; Pick a random mon out of ContestMons.
-
-.loop
-	call Random
-	cp 100 << 1
-	jr nc, .loop
-	srl a
-
-	ld hl, ContestMons
-	ld de, 4
-.CheckMon:
-	sub [hl]
-	jr c, .GotMon
-	add hl, de
-	jr .CheckMon
-
-.GotMon:
-	inc hl
-
-; Species
-	ld a, [hli]
-	ld [wTempWildMonSpecies], a
-
-; Min level
-	ld a, [hli]
-	ld d, a
-
-; Max level
-	ld a, [hl]
-
-	sub d
-	jr nz, .RandomLevel
-
-; If min and max are the same.
-	ld a, d
-	jr .GotLevel
-
-.RandomLevel:
-; Get a random level between the min and max.
-	ld c, a
-	inc c
-	call Random
-	ld a, [hRandomAdd]
-	call SimpleDivide
-	add d
-
-.GotLevel:
-	ld [wCurPartyLevel], a
-
-	xor a
-	ret
-; 97d64
-
-TryWildEncounter_BugContest: ; 97d64
-	ld a, [wPlayerStandingTile]
-	call CheckSuperTallGrassTile
-	ld b, 40 percent
-	jr z, .ok
-	ld b, 20 percent
-
-.ok
-	farcall ApplyMusicEffectOnEncounterRate
-	farcall ApplyCleanseTagEffectOnEncounterRate
-	call Random
-	ld a, [hRandomAdd]
-	cp b
-	ret c
-	ld a, 1
-	and a
-	ret
-; 97d87
-
-
-INCLUDE "data/wild/bug_contest_mons.asm"
-
-
-DoBikeStep:: ; 97db3
-	nop
-	nop
-	; If the bike shop owner doesn't have our number, or
-	; if we've already gotten the call, we don't have to
-	; be here.
-	ld hl, wStatusFlags2
-	bit STATUSFLAGS2_BIKE_SHOP_CALL_F, [hl]
-	jr z, .NoCall
-
-	; If we're not on the bike, we don't have to be here.
-	ld a, [wPlayerState]
-	cp PLAYER_BIKE
-	jr nz, .NoCall
-
-	; If we're not in an area of phone service, we don't
-	; have to be here.
-	call GetMapPhoneService
-	and a
-	jr nz, .NoCall
-
-	; Check the bike step count and check whether we've
-	; taken 65536 of them yet.
-	ld hl, wBikeStep
-	ld a, [hli]
-	ld d, a
-	ld e, [hl]
-	cp 255
-	jr nz, .increment
-	ld a, e
-	cp 255
-	jr z, .dont_increment
-
-.increment
-	inc de
-	ld [hl], e
-	dec hl
-	ld [hl], d
-
-.dont_increment
-	; If we've taken at least 1024 steps, have the bike
-	;  shop owner try to call us.
-	ld a, d
-	cp HIGH(1024)
-	jr c, .NoCall
-
-	; If a call has already been queued, don't overwrite
-	; that call.
-	ld a, [wSpecialPhoneCallID]
-	and a
-	jr nz, .NoCall
-
-	; Queue the call.
-	ld a, SPECIALCALL_BIKESHOP
-	ld [wSpecialPhoneCallID], a
-	xor a
-	ld [wSpecialPhoneCallID + 1], a
-	ld hl, wStatusFlags2
-	res STATUSFLAGS2_BIKE_SHOP_CALL_F, [hl]
-	scf
-	ret
-
-.NoCall:
-	xor a
-	ret
-; 97df9
-
-ClearCmdQueue:: ; 97df9
-	ld hl, wCmdQueue
-	ld de, 6
-	ld c, 4
-	xor a
-.loop
-	ld [hl], a
-	add hl, de
-	dec c
-	jr nz, .loop
-	ret
-; 97e08
-
-HandleCmdQueue:: ; 97e08
-	ld hl, wCmdQueue
-	xor a
-.loop
-	ld [hMapObjectIndexBuffer], a
-	ld a, [hl]
-	and a
-	jr z, .skip
-	push hl
-	ld b, h
-	ld c, l
-	call HandleQueuedCommand
-	pop hl
-
-.skip
-	ld de, CMDQUEUE_ENTRY_SIZE
-	add hl, de
-	ld a, [hMapObjectIndexBuffer]
-	inc a
-	cp CMDQUEUE_CAPACITY
-	jr nz, .loop
-	ret
-; 97e25
-
-Unreferenced_GetNthCmdQueueEntry: ; 97e25
-	ld hl, wCmdQueue
-	ld bc, CMDQUEUE_ENTRY_SIZE
-	call AddNTimes
-	ld b, h
-	ld c, l
-	ret
-; 97e31
-
-WriteCmdQueue:: ; 97e31
-	push bc
-	push de
-	call .GetNextEmptyEntry
-	ld d, h
-	ld e, l
-	pop hl
-	pop bc
-	ret c
-	ld a, b
-	ld bc, CMDQUEUE_ENTRY_SIZE - 1
-	call FarCopyBytes
-	xor a
-	ld [hl], a
-	ret
-; 97e45
-
-.GetNextEmptyEntry: ; 97e45
-	ld hl, wCmdQueue
-	ld de, CMDQUEUE_ENTRY_SIZE
-	ld c, CMDQUEUE_CAPACITY
-.loop
-	ld a, [hl]
-	and a
-	jr z, .done
-	add hl, de
-	dec c
-	jr nz, .loop
-	scf
-	ret
-
-.done
-	ld a, CMDQUEUE_CAPACITY
-	sub c
-	and a
-	ret
-; 97e5c
-
-DelCmdQueue:: ; 97e5c
-	ld hl, wCmdQueue
-	ld de, CMDQUEUE_ENTRY_SIZE
-	ld c, CMDQUEUE_CAPACITY
-.loop
-	ld a, [hl]
-	cp b
-	jr z, .done
-	add hl, de
-	dec c
-	jr nz, .loop
-	and a
-	ret
-
-.done
-	xor a
-	ld [hl], a
-	scf
-	ret
-; 97e72
-
-_DelCmdQueue: ; 97e72
-	ld hl, CMDQUEUE_TYPE
-	add hl, bc
-	ld [hl], 0
-	ret
-; 97e79
-
-HandleQueuedCommand: ; 97e79
-	ld hl, CMDQUEUE_TYPE
-	add hl, bc
-	ld a, [hl]
-	cp 5
-	jr c, .okay
-	xor a
-
-.okay
-	ld e, a
-	ld d, 0
-	ld hl, .Jumptable
-	add hl, de
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	push af
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	pop af
-	rst FarCall
-	ret
-; 97e94
-
-.Jumptable: ; 97e94
-	dba CmdQueue_Null
-	dba CmdQueue_Null2
-	dba CmdQueue_StoneTable
-	dba CmdQueue_Type3
-	dba CmdQueue_Type4
-; 97ea3
-
-CmdQueueAnonymousJumptable: ; 97ea3
-	ld hl, CMDQUEUE_05
-	add hl, bc
-	ld a, [hl]
-	pop hl
-	rst JumpTable
-	ret
-; 97eab
-
-CmdQueueAnonJT_Increment: ; 97eab
-	ld hl, CMDQUEUE_05
-	add hl, bc
-	inc [hl]
-	ret
-; 97eb1
-
-CmdQueueAnonJT_Decrement: ; 97eb1
-	ld hl, CMDQUEUE_05
-	add hl, bc
-	dec [hl]
-	ret
-; 97eb7
-
-CmdQueue_Null: ; 97eb7
-	ret
-; 97eb8
-
-CmdQueue_Null2: ; 97eb8
-	call ret_2f3e
-	ret
-; 97ebc
-
-CmdQueue_Type4: ; 97ebc
-	call CmdQueueAnonymousJumptable
-	; anonymous dw
-	dw .zero
-	dw .one
-; 97ec3
-
-.zero ; 97ec3
-	ld a, [hSCY]
-	ld hl, 4
-	add hl, bc
-	ld [hl], a
-	call CmdQueueAnonJT_Increment
-.one ; 97ecd
-	ld hl, 1
-	add hl, bc
-	ld a, [hl]
-	dec a
-	ld [hl], a
-	jr z, .finish
-	and $1
-	jr z, .add
-	ld hl, 2
-	add hl, bc
-	ld a, [hSCY]
-	sub [hl]
-	ld [hSCY], a
-	ret
-
-.add
-	ld hl, 2
-	add hl, bc
-	ld a, [hSCY]
-	add [hl]
-	ld [hSCY], a
-	ret
-
-.finish
-	ld hl, 4
-	add hl, bc
-	ld a, [hl]
-	ld [hSCY], a
-	call _DelCmdQueue
-	ret
-; 97ef9
-
-CmdQueue_Type3: ; 97ef9
-	call CmdQueueAnonymousJumptable
-	; anonymous dw
-	dw .zero
-	dw .one
-	dw .two
-; 97f02
-
-.zero ; 97f02
-	call .IsPlayerFacingDown
-	jr z, .PlayerNotFacingDown
-	call CmdQueueAnonJT_Increment
-.one ; 97f0a
-	call .IsPlayerFacingDown
-	jr z, .PlayerNotFacingDown
-	call CmdQueueAnonJT_Increment
-
-	ld hl, 2
-	add hl, bc
-	ld a, [hl]
-	ld [wd173], a
-	ret
-; 97f1b
-
-.two ; 97f1b
-	call .IsPlayerFacingDown
-	jr z, .PlayerNotFacingDown
-	call CmdQueueAnonJT_Decrement
-
-	ld hl, 3
-	add hl, bc
-	ld a, [hl]
-	ld [wd173], a
-	ret
-; 97f2c
-
-.PlayerNotFacingDown: ; 97f2c
-	ld a, $7f
-	ld [wd173], a
-	ld hl, 5
-	add hl, bc
-	ld [hl], 0
-	ret
-; 97f38
-
-.IsPlayerFacingDown: ; 97f38
-	push bc
-	ld bc, wPlayerStruct
-	call GetSpriteDirection
-	and a
-	pop bc
-	ret
-; 97f42
-
-CmdQueue_StoneTable: ; 97f42
-	ld de, wPlayerStruct
-	ld a, NUM_OBJECT_STRUCTS
-.loop
-	push af
-
-	ld hl, OBJECT_SPRITE
-	add hl, de
-	ld a, [hl]
-	and a
-	jr z, .next
-
-	ld hl, OBJECT_MOVEMENTTYPE
-	add hl, de
-	ld a, [hl]
-	cp SPRITEMOVEDATA_STRENGTH_BOULDER
-	jr nz, .next
-
-	ld hl, OBJECT_NEXT_TILE
-	add hl, de
-	ld a, [hl]
-	call CheckPitTile
-	jr nz, .next
-
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, de
-	ld a, [hl]
-	cp STANDING
-	jr nz, .next
-	call HandleStoneQueue
-	jr c, .fall_down_hole
-
-.next
-	ld hl, OBJECT_STRUCT_LENGTH
-	add hl, de
-	ld d, h
-	ld e, l
-
-	pop af
-	dec a
-	jr nz, .loop
-	ret
-
-.fall_down_hole
-	pop af
-	ret
-; 97f7e
--- a/engine/evolution_animation.asm
+++ /dev/null
@@ -1,368 +1,0 @@
-EvolutionAnimation: ; 4e5e1
-	push hl
-	push de
-	push bc
-	ld a, [wCurSpecies]
-	push af
-	ld a, [rOBP0]
-	push af
-	ld a, [wBaseDexNo]
-	push af
-
-	call .EvolutionAnimation
-
-	pop af
-	ld [wBaseDexNo], a
-	pop af
-	ld [rOBP0], a
-	pop af
-	ld [wCurSpecies], a
-	pop bc
-	pop de
-	pop hl
-
-	ld a, [wEvolutionCanceled]
-	and a
-	ret z
-
-	scf
-	ret
-; 4e607
-
-.EvolutionAnimation: ; 4e607
-	ld a, %11100100
-	ld [rOBP0], a
-
-	ld de, MUSIC_NONE
-	call PlayMusic
-
-	farcall ClearSpriteAnims
-
-	ld de, .GFX
-	ld hl, vTiles0
-	lb bc, BANK(.GFX), 8
-	call Request2bpp
-
-	xor a
-	ld [wLowHealthAlarm], a
-	call WaitBGMap
-	xor a
-	ld [hBGMapMode], a
-	ld a, [wEvolutionOldSpecies]
-	ld [wPlayerHPPal], a
-
-	ld c, $0
-	call .GetSGBLayout
-	ld a, [wEvolutionOldSpecies]
-	ld [wCurPartySpecies], a
-	ld [wCurSpecies], a
-	call .PlaceFrontpic
-
-	ld de, vTiles2
-	ld hl, vTiles2 tile $31
-	ld bc, 7 * 7
-	call Request2bpp
-
-	ld a, 7 * 7
-	ld [wEvolutionPicOffset], a
-	call .ReplaceFrontpic
-	ld a, [wEvolutionNewSpecies]
-	ld [wCurPartySpecies], a
-	ld [wCurSpecies], a
-	call .LoadFrontpic
-	ld a, [wEvolutionOldSpecies]
-	ld [wCurPartySpecies], a
-	ld [wCurSpecies], a
-
-	ld a, $1
-	ld [hBGMapMode], a
-	call .check_statused
-	jr c, .skip_cry
-
-	ld a, [wEvolutionOldSpecies]
-	call PlayMonCry
-
-.skip_cry
-	ld de, MUSIC_EVOLUTION
-	call PlayMusic
-
-	ld c, 80
-	call DelayFrames
-
-	ld c, $1
-	call .GetSGBLayout
-	call .AnimationSequence
-	jr c, .cancel_evo
-
-	ld a, -7 * 7
-	ld [wEvolutionPicOffset], a
-	call .ReplaceFrontpic
-	xor a
-	ld [wEvolutionCanceled], a
-
-	ld a, [wEvolutionNewSpecies]
-	ld [wPlayerHPPal], a
-
-	ld c, $0
-	call .GetSGBLayout
-	call .PlayEvolvedSFX
-	farcall ClearSpriteAnims
-	call .check_statused
-	jr c, .no_anim
-
-	ld a, [wBoxAlignment]
-	push af
-	ld a, $1
-	ld [wBoxAlignment], a
-	ld a, [wCurPartySpecies]
-	push af
-
-	ld a, [wPlayerHPPal]
-	ld [wCurPartySpecies], a
-	hlcoord 7, 2
-	ld d, $0
-	ld e, ANIM_MON_EVOLVE
-	predef AnimateFrontpic
-
-	pop af
-	ld [wCurPartySpecies], a
-	pop af
-	ld [wBoxAlignment], a
-	ret
-
-.no_anim
-	ret
-
-.cancel_evo
-	ld a, $1
-	ld [wEvolutionCanceled], a
-
-	ld a, [wEvolutionOldSpecies]
-	ld [wPlayerHPPal], a
-
-	ld c, $0
-	call .GetSGBLayout
-	call .PlayEvolvedSFX
-	farcall ClearSpriteAnims
-	call .check_statused
-	ret c
-
-	ld a, [wPlayerHPPal]
-	call PlayMonCry
-	ret
-; 4e703
-
-.GetSGBLayout: ; 4e703
-	ld b, SCGB_EVOLUTION
-	jp GetSGBLayout
-; 4e708
-
-.PlaceFrontpic: ; 4e708
-	call GetBaseData
-	hlcoord 7, 2
-	jp PrepMonFrontpic
-; 4e711
-
-.LoadFrontpic: ; 4e711
-	call GetBaseData
-	ld a, $1
-	ld [wBoxAlignment], a
-	ld de, vTiles2
-	predef GetAnimatedFrontpic
-	xor a
-	ld [wBoxAlignment], a
-	ret
-; 4e726
-
-.AnimationSequence: ; 4e726
-	call ClearJoypad
-	lb bc, 1, 2 * 7 ; flash b times, wait c frames in between
-.loop
-	push bc
-	call .WaitFrames_CheckPressedB
-	pop bc
-	jr c, .exit_sequence
-	push bc
-	call .Flash
-	pop bc
-	inc b
-	dec c
-	dec c
-	jr nz, .loop
-	and a
-	ret
-
-.exit_sequence
-	scf
-	ret
-; 4e741
-
-.Flash: ; 4e741
-	ld a, -7 * 7 ; new stage
-	ld [wEvolutionPicOffset], a
-	call .ReplaceFrontpic
-	ld a, 7 * 7 ; previous stage
-	ld [wEvolutionPicOffset], a
-	call .ReplaceFrontpic
-	dec b
-	jr nz, .Flash
-	ret
-; 4e755
-
-.ReplaceFrontpic: ; 4e755
-	push bc
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 7, 2
-	lb bc, 7, 7
-	ld de, SCREEN_WIDTH - 7
-.loop1
-	push bc
-.loop2
-	ld a, [wEvolutionPicOffset]
-	add [hl]
-	ld [hli], a
-	dec c
-	jr nz, .loop2
-	pop bc
-	add hl, de
-	dec b
-	jr nz, .loop1
-	ld a, $1
-	ld [hBGMapMode], a
-	call WaitBGMap
-	pop bc
-	ret
-; 4e779
-
-.WaitFrames_CheckPressedB: ; 4e779
-	call DelayFrame
-	push bc
-	call JoyTextDelay
-	ld a, [hJoyDown]
-	pop bc
-	and B_BUTTON
-	jr nz, .pressed_b
-.loop3
-	dec c
-	jr nz, .WaitFrames_CheckPressedB
-	and a
-	ret
-
-.pressed_b
-	ld a, [wForceEvolution]
-	and a
-	jr nz, .loop3
-	scf
-	ret
-; 4e794
-
-.check_statused ; 4e794
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1Species
-	call GetPartyLocation
-	ld b, h
-	ld c, l
-	farcall CheckFaintedFrzSlp
-	ret
-; 4e7a6
-
-.PlayEvolvedSFX: ; 4e7a6
-	ld a, [wEvolutionCanceled]
-	and a
-	ret nz
-	ld de, SFX_EVOLVED
-	call PlaySFX
-	ld hl, wJumptableIndex
-	ld a, [hl]
-	push af
-	ld [hl], $0
-.loop4
-	call .balls_of_light
-	jr nc, .done
-	call .AnimateBallsOfLight
-	jr .loop4
-
-.done
-	ld c, 32
-.loop5
-	call .AnimateBallsOfLight
-	dec c
-	jr nz, .loop5
-	pop af
-	ld [wJumptableIndex], a
-	ret
-; 4e7cf
-
-.balls_of_light ; 4e7cf
-	ld hl, wJumptableIndex
-	ld a, [hl]
-	cp 32
-	ret nc
-	ld d, a
-	inc [hl]
-	and $1
-	jr nz, .done_balls
-	ld e, $0
-	call .GenerateBallOfLight
-	ld e, $10
-	call .GenerateBallOfLight
-
-.done_balls
-	scf
-	ret
-; 4e7e8
-
-.GenerateBallOfLight: ; 4e7e8
-	push de
-	depixel 9, 11
-	ld a, SPRITE_ANIM_INDEX_EVOLUTION_BALL_OF_LIGHT
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld a, [wJumptableIndex]
-	and %1110
-	sla a
-	pop de
-	add e
-	ld [hl], a
-	ld hl, SPRITEANIMSTRUCT_TILE_ID
-	add hl, bc
-	ld [hl], $0
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $10
-	ret
-; 4e80c
-
-.AnimateBallsOfLight: ; 4e80c
-	push bc
-	callfar PlaySpriteAnimations
-	; a = (([hVBlankCounter] + 4) / 2) % NUM_PALETTES
-	ld a, [hVBlankCounter]
-	and %1110
-	srl a
-	inc a
-	inc a
-	and $7
-	ld b, a
-	ld hl, wVirtualOAMSprite00Attributes
-	ld c, NUM_SPRITE_OAM_STRUCTS
-.loop6
-	ld a, [hl]
-	or b
-	ld [hli], a ; attributes
-rept SPRITEOAMSTRUCT_LENGTH + -1
-	inc hl
-endr
-	dec c
-	jr nz, .loop6
-	pop bc
-	call DelayFrame
-	ret
-; 4e831
-
-
-.GFX:
-INCBIN "gfx/evo/bubble_large.2bpp"
-INCBIN "gfx/evo/bubble.2bpp"
--- a/engine/evolve.asm
+++ /dev/null
@@ -1,676 +1,0 @@
-EvolvePokemon: ; 421d8
-	ld hl, wEvolvableFlags
-	xor a
-	ld [hl], a
-	ld a, [wCurPartyMon]
-	ld c, a
-	ld b, SET_FLAG
-	call EvoFlagAction
-EvolveAfterBattle: ; 421e6
-	xor a
-	ld [wMonTriedToEvolve], a
-	dec a
-	ld [wCurPartyMon], a
-	push hl
-	push bc
-	push de
-	ld hl, wPartyCount
-
-	push hl
-
-EvolveAfterBattle_MasterLoop
-	ld hl, wCurPartyMon
-	inc [hl]
-
-	pop hl
-
-	inc hl
-	ld a, [hl]
-	cp $ff
-	jp z, .ReturnToMap
-
-	ld [wEvolutionOldSpecies], a
-
-	push hl
-	ld a, [wCurPartyMon]
-	ld c, a
-	ld hl, wEvolvableFlags
-	ld b, CHECK_FLAG
-	call EvoFlagAction
-	ld a, c
-	and a
-	jp z, EvolveAfterBattle_MasterLoop
-
-	ld a, [wEvolutionOldSpecies]
-	dec a
-	ld b, 0
-	ld c, a
-	ld hl, EvosAttacksPointers
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-
-	push hl
-	xor a
-	ld [wMonType], a
-	predef CopyMonToTempMon
-	pop hl
-
-.loop
-	ld a, [hli]
-	and a
-	jr z, EvolveAfterBattle_MasterLoop
-
-	ld b, a
-
-	cp EVOLVE_TRADE
-	jr z, .trade
-
-	ld a, [wLinkMode]
-	and a
-	jp nz, .dont_evolve_2
-
-	ld a, b
-	cp EVOLVE_ITEM
-	jp z, .item
-
-	ld a, [wForceEvolution]
-	and a
-	jp nz, .dont_evolve_2
-
-	ld a, b
-	cp EVOLVE_LEVEL
-	jp z, .level
-
-	cp EVOLVE_HAPPINESS
-	jr z, .happiness
-
-
-; EVOLVE_STAT
-	ld a, [wTempMonLevel]
-	cp [hl]
-	jp c, .dont_evolve_1
-
-	call IsMonHoldingEverstone
-	jp z, .dont_evolve_1
-
-	push hl
-	ld de, wTempMonAttack
-	ld hl, wTempMonDefense
-	ld c, 2
-	call StringCmp
-	ld a, ATK_EQ_DEF
-	jr z, .got_tyrogue_evo
-	ld a, ATK_LT_DEF
-	jr c, .got_tyrogue_evo
-	ld a, ATK_GT_DEF
-.got_tyrogue_evo
-	pop hl
-
-	inc hl
-	cp [hl]
-	jp nz, .dont_evolve_2
-
-	inc hl
-	jr .proceed
-
-
-.happiness
-	ld a, [wTempMonHappiness]
-	cp HAPPINESS_TO_EVOLVE
-	jp c, .dont_evolve_2
-
-	call IsMonHoldingEverstone
-	jp z, .dont_evolve_2
-
-	ld a, [hli]
-	cp TR_ANYTIME
-	jr z, .proceed
-	cp TR_MORNDAY
-	jr z, .happiness_daylight
-
-; TR_NITE
-	ld a, [wTimeOfDay]
-	cp NITE_F
-	jp nz, .dont_evolve_3
-	jr .proceed
-
-.happiness_daylight
-	ld a, [wTimeOfDay]
-	cp NITE_F
-	jp z, .dont_evolve_3
-	jr .proceed
-
-
-.trade
-	ld a, [wLinkMode]
-	and a
-	jp z, .dont_evolve_2
-
-	call IsMonHoldingEverstone
-	jp z, .dont_evolve_2
-
-	ld a, [hli]
-	ld b, a
-	inc a
-	jr z, .proceed
-
-	ld a, [wLinkMode]
-	cp LINK_TIMECAPSULE
-	jp z, .dont_evolve_3
-
-	ld a, [wTempMonItem]
-	cp b
-	jp nz, .dont_evolve_3
-
-	xor a
-	ld [wTempMonItem], a
-	jr .proceed
-
-
-.item
-	ld a, [hli]
-	ld b, a
-	ld a, [wCurItem]
-	cp b
-	jp nz, .dont_evolve_3
-
-	ld a, [wForceEvolution]
-	and a
-	jp z, .dont_evolve_3
-	ld a, [wLinkMode]
-	and a
-	jp nz, .dont_evolve_3
-	jr .proceed
-
-
-.level
-	ld a, [hli]
-	ld b, a
-	ld a, [wTempMonLevel]
-	cp b
-	jp c, .dont_evolve_3
-	call IsMonHoldingEverstone
-	jp z, .dont_evolve_3
-
-.proceed
-	ld a, [wTempMonLevel]
-	ld [wCurPartyLevel], a
-	ld a, $1
-	ld [wMonTriedToEvolve], a
-
-	push hl
-
-	ld a, [hl]
-	ld [wEvolutionNewSpecies], a
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMonNicknames
-	call GetNick
-	call CopyName1
-	ld hl, Text_WhatEvolving
-	call PrintText
-
-	ld c, 50
-	call DelayFrames
-
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 0, 0
-	lb bc, 12, 20
-	call ClearBox
-
-	ld a, $1
-	ld [hBGMapMode], a
-	call ClearSprites
-
-	farcall EvolutionAnimation
-
-	push af
-	call ClearSprites
-	pop af
-	jp c, CancelEvolution
-
-	ld hl, Text_CongratulationsYourPokemon
-	call PrintText
-
-	pop hl
-
-	ld a, [hl]
-	ld [wCurSpecies], a
-	ld [wTempMonSpecies], a
-	ld [wEvolutionNewSpecies], a
-	ld [wd265], a
-	call GetPokemonName
-
-	push hl
-	ld hl, Text_EvolvedIntoPKMN
-	call PrintTextBoxText
-	farcall StubbedTrainerRankings_MonsEvolved
-
-	ld de, MUSIC_NONE
-	call PlayMusic
-	ld de, SFX_CAUGHT_MON
-	call PlaySFX
-	call WaitSFX
-
-	ld c, 40
-	call DelayFrames
-
-	call ClearTileMap
-	call UpdateSpeciesNameIfNotNicknamed
-	call GetBaseData
-
-	ld hl, wTempMonExp + 2
-	ld de, wTempMonMaxHP
-	ld b, TRUE
-	predef CalcMonStats
-
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMons
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld e, l
-	ld d, h
-	ld bc, MON_MAXHP
-	add hl, bc
-	ld a, [hli]
-	ld b, a
-	ld c, [hl]
-	ld hl, wTempMonMaxHP + 1
-	ld a, [hld]
-	sub c
-	ld c, a
-	ld a, [hl]
-	sbc b
-	ld b, a
-	ld hl, wTempMonHP + 1
-	ld a, [hl]
-	add c
-	ld [hld], a
-	ld a, [hl]
-	adc b
-	ld [hl], a
-
-	ld hl, wTempMonSpecies
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call CopyBytes
-
-	ld a, [wCurSpecies]
-	ld [wd265], a
-	xor a
-	ld [wMonType], a
-	call LearnLevelMoves
-	ld a, [wd265]
-	dec a
-	call SetSeenAndCaughtMon
-
-	ld a, [wd265]
-	cp UNOWN
-	jr nz, .skip_unown
-
-	ld hl, wTempMonDVs
-	predef GetUnownLetter
-	callfar UpdateUnownDex
-
-.skip_unown
-	pop de
-	pop hl
-	ld a, [wTempMonSpecies]
-	ld [hl], a
-	push hl
-	ld l, e
-	ld h, d
-	jp EvolveAfterBattle_MasterLoop
-; 423f8
-
-.dont_evolve_1
-	inc hl
-.dont_evolve_2
-	inc hl
-.dont_evolve_3
-	inc hl
-	jp .loop
-
-; unused
-	pop hl
-.ReturnToMap:
-	pop de
-	pop bc
-	pop hl
-	ld a, [wLinkMode]
-	and a
-	ret nz
-	ld a, [wBattleMode]
-	and a
-	ret nz
-	ld a, [wMonTriedToEvolve]
-	and a
-	call nz, RestartMapMusic
-	ret
-; 42414
-
-UpdateSpeciesNameIfNotNicknamed: ; 42414
-	ld a, [wCurSpecies]
-	push af
-	ld a, [wBaseDexNo]
-	ld [wd265], a
-	call GetPokemonName
-	pop af
-	ld [wCurSpecies], a
-	ld hl, wStringBuffer1
-	ld de, wStringBuffer2
-.loop
-	ld a, [de]
-	inc de
-	cp [hl]
-	inc hl
-	ret nz
-	cp "@"
-	jr nz, .loop
-
-	ld a, [wCurPartyMon]
-	ld bc, MON_NAME_LENGTH
-	ld hl, wPartyMonNicknames
-	call AddNTimes
-	push hl
-	ld a, [wCurSpecies]
-	ld [wd265], a
-	call GetPokemonName
-	ld hl, wStringBuffer1
-	pop de
-	ld bc, MON_NAME_LENGTH
-	jp CopyBytes
-; 42454
-
-CancelEvolution: ; 42454
-	ld hl, Text_StoppedEvolving
-	call PrintText
-	call ClearTileMap
-	pop hl
-	jp EvolveAfterBattle_MasterLoop
-; 42461
-
-IsMonHoldingEverstone: ; 42461
-	push hl
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1Item
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [hl]
-	cp EVERSTONE
-	pop hl
-	ret
-; 42473
-
-Text_CongratulationsYourPokemon: ; 0x42473
-	; Congratulations! Your @ @
-	text_jump UnknownText_0x1c4b92
-	db "@"
-; 0x42478
-
-Text_EvolvedIntoPKMN: ; 0x42478
-	; evolved into @ !
-	text_jump UnknownText_0x1c4baf
-	db "@"
-; 0x4247d
-
-Text_StoppedEvolving: ; 0x4247d
-	; Huh? @ stopped evolving!
-	text_jump UnknownText_0x1c4bc5
-	db "@"
-; 0x42482
-
-Text_WhatEvolving: ; 0x42482
-	; What? @ is evolving!
-	text_jump UnknownText_0x1c4be3
-	db "@"
-; 0x42487
-
-
-LearnLevelMoves: ; 42487
-	ld a, [wd265]
-	ld [wCurPartySpecies], a
-	dec a
-	ld b, 0
-	ld c, a
-	ld hl, EvosAttacksPointers
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-
-.skip_evos
-	ld a, [hli]
-	and a
-	jr nz, .skip_evos
-
-.find_move
-	ld a, [hli]
-	and a
-	jr z, .done
-
-	ld b, a
-	ld a, [wCurPartyLevel]
-	cp b
-	ld a, [hli]
-	jr nz, .find_move
-
-	push hl
-	ld d, a
-	ld hl, wPartyMon1Moves
-	ld a, [wCurPartyMon]
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-
-	ld b, NUM_MOVES
-.check_move
-	ld a, [hli]
-	cp d
-	jr z, .has_move
-	dec b
-	jr nz, .check_move
-	jr .learn
-.has_move
-
-	pop hl
-	jr .find_move
-
-.learn
-	ld a, d
-	ld [wPutativeTMHMMove], a
-	ld [wd265], a
-	call GetMoveName
-	call CopyName1
-	predef LearnMove
-	pop hl
-	jr .find_move
-
-.done
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	ret
-; 424e1
-
-
-FillMoves: ; 424e1
-; Fill in moves at de for wCurPartySpecies at wCurPartyLevel
-
-	push hl
-	push de
-	push bc
-	ld hl, EvosAttacksPointers
-	ld b, 0
-	ld a, [wCurPartySpecies]
-	dec a
-	add a
-	rl b
-	ld c, a
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-.GoToAttacks:
-	ld a, [hli]
-	and a
-	jr nz, .GoToAttacks
-	jr .GetLevel
-
-.NextMove:
-	pop de
-.GetMove:
-	inc hl
-.GetLevel:
-	ld a, [hli]
-	and a
-	jp z, .done
-	ld b, a
-	ld a, [wCurPartyLevel]
-	cp b
-	jp c, .done
-	ld a, [wEvolutionOldSpecies]
-	and a
-	jr z, .CheckMove
-	ld a, [wd002]
-	cp b
-	jr nc, .GetMove
-
-.CheckMove:
-	push de
-	ld c, NUM_MOVES
-.CheckRepeat:
-	ld a, [de]
-	inc de
-	cp [hl]
-	jr z, .NextMove
-	dec c
-	jr nz, .CheckRepeat
-	pop de
-	push de
-	ld c, NUM_MOVES
-.CheckSlot:
-	ld a, [de]
-	and a
-	jr z, .LearnMove
-	inc de
-	dec c
-	jr nz, .CheckSlot
-	pop de
-	push de
-	push hl
-	ld h, d
-	ld l, e
-	call ShiftMoves
-	ld a, [wEvolutionOldSpecies]
-	and a
-	jr z, .ShiftedMove
-	push de
-	ld bc, wPartyMon1PP - (wPartyMon1Moves + NUM_MOVES - 1)
-	add hl, bc
-	ld d, h
-	ld e, l
-	call ShiftMoves
-	pop de
-
-.ShiftedMove:
-	pop hl
-
-.LearnMove:
-	ld a, [hl]
-	ld [de], a
-	ld a, [wEvolutionOldSpecies]
-	and a
-	jr z, .NextMove
-	push hl
-	ld a, [hl]
-	ld hl, MON_PP - MON_MOVES
-	add hl, de
-	push hl
-	dec a
-	ld hl, Moves + MOVE_PP
-	ld bc, MOVE_LENGTH
-	call AddNTimes
-	ld a, BANK(Moves)
-	call GetFarByte
-	pop hl
-	ld [hl], a
-	pop hl
-	jr .NextMove
-
-.done
-	pop bc
-	pop de
-	pop hl
-	ret
-; 4256e
-
-ShiftMoves: ; 4256e
-	ld c, NUM_MOVES - 1
-.loop
-	inc de
-	ld a, [de]
-	ld [hli], a
-	dec c
-	jr nz, .loop
-	ret
-; 42577
-
-
-EvoFlagAction: ; 42577
-	push de
-	ld d, $0
-	predef SmallFarFlagAction
-	pop de
-	ret
-; 42581
-
-GetPreEvolution: ; 42581
-; Find the first mon to evolve into wCurPartySpecies.
-
-; Return carry and the new species in wCurPartySpecies
-; if a pre-evolution is found.
-
-	ld c, 0
-.loop ; For each Pokemon...
-	ld hl, EvosAttacksPointers
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-.loop2 ; For each evolution...
-	ld a, [hli]
-	and a
-	jr z, .no_evolve ; If we jump, this Pokemon does not evolve into wCurPartySpecies.
-	cp EVOLVE_STAT ; This evolution type has the extra parameter of stat comparison.
-	jr nz, .not_tyrogue
-	inc hl
-
-.not_tyrogue
-	inc hl
-	ld a, [wCurPartySpecies]
-	cp [hl]
-	jr z, .found_preevo
-	inc hl
-	ld a, [hl]
-	and a
-	jr nz, .loop2
-
-.no_evolve
-	inc c
-	ld a, c
-	cp NUM_POKEMON
-	jr c, .loop
-	and a
-	ret
-
-.found_preevo
-	inc c
-	ld a, c
-	ld [wCurPartySpecies], a
-	scf
-	ret
-; 425b1
--- a/engine/experience.asm
+++ /dev/null
@@ -1,162 +1,0 @@
-CalcLevel: ; 50e1b
-	ld a, [wTempMonSpecies]
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld d, 1
-.next_level
-	inc d
-	ld a, d
-	cp LOW(MAX_LEVEL + 1)
-	jr z, .got_level
-	call CalcExpAtLevel
-	push hl
-	ld hl, wTempMonExp + 2
-	ld a, [hProduct + 3]
-	ld c, a
-	ld a, [hld]
-	sub c
-	ld a, [hProduct + 2]
-	ld c, a
-	ld a, [hld]
-	sbc c
-	ld a, [hProduct + 1]
-	ld c, a
-	ld a, [hl]
-	sbc c
-	pop hl
-	jr nc, .next_level
-
-.got_level
-	dec d
-	ret
-
-CalcExpAtLevel: ; 50e47
-; (a/b)*n**3 + c*n**2 + d*n - e
-	ld a, [wBaseGrowthRate]
-	add a
-	add a
-	ld c, a
-	ld b, 0
-	ld hl, GrowthRates
-	add hl, bc
-; Cube the level
-	call .LevelSquared
-	ld a, d
-	ld [hMultiplier], a
-	call Multiply
-
-; Multiply by a
-	ld a, [hl]
-	and $f0
-	swap a
-	ld [hMultiplier], a
-	call Multiply
-; Divide by b
-	ld a, [hli]
-	and $f
-	ld [hDivisor], a
-	ld b, 4
-	call Divide
-; Push the cubic term to the stack
-	ld a, [hQuotient + 0]
-	push af
-	ld a, [hQuotient + 1]
-	push af
-	ld a, [hQuotient + 2]
-	push af
-; Square the level and multiply by the lower 7 bits of c
-	call .LevelSquared
-	ld a, [hl]
-	and $7f
-	ld [hMultiplier], a
-	call Multiply
-; Push the absolute value of the quadratic term to the stack
-	ld a, [hProduct + 1]
-	push af
-	ld a, [hProduct + 2]
-	push af
-	ld a, [hProduct + 3]
-	push af
-	ld a, [hli]
-	push af
-; Multiply the level by d
-	xor a
-	ld [hMultiplicand + 0], a
-	ld [hMultiplicand + 1], a
-	ld a, d
-	ld [hMultiplicand + 2], a
-	ld a, [hli]
-	ld [hMultiplier], a
-	call Multiply
-; Subtract e
-	ld b, [hl]
-	ld a, [hProduct + 3]
-	sub b
-	ld [hMultiplicand + 2], a
-	ld b, $0
-	ld a, [hProduct + 2]
-	sbc b
-	ld [hMultiplicand + 1], a
-	ld a, [hProduct + 1]
-	sbc b
-	ld [hMultiplicand], a
-; If bit 7 of c is set, c is negative; otherwise, it's positive
-	pop af
-	and $80
-	jr nz, .subtract
-; Add c*n**2 to (d*n - e)
-	pop bc
-	ld a, [hProduct + 3]
-	add b
-	ld [hMultiplicand + 2], a
-	pop bc
-	ld a, [hProduct + 2]
-	adc b
-	ld [hMultiplicand + 1], a
-	pop bc
-	ld a, [hProduct + 1]
-	adc b
-	ld [hMultiplicand], a
-	jr .done_quadratic
-
-.subtract
-; Subtract c*n**2 from (d*n - e)
-	pop bc
-	ld a, [hProduct + 3]
-	sub b
-	ld [hMultiplicand + 2], a
-	pop bc
-	ld a, [hProduct + 2]
-	sbc b
-	ld [hMultiplicand + 1], a
-	pop bc
-	ld a, [hProduct + 1]
-	sbc b
-	ld [hMultiplicand], a
-
-.done_quadratic
-; Add (a/b)*n**3 to (d*n - e +/- c*n**2)
-	pop bc
-	ld a, [hProduct + 3]
-	add b
-	ld [hMultiplicand + 2], a
-	pop bc
-	ld a, [hProduct + 2]
-	adc b
-	ld [hMultiplicand + 1], a
-	pop bc
-	ld a, [hProduct + 1]
-	adc b
-	ld [hMultiplicand], a
-	ret
-
-.LevelSquared: ; 50eed
-	xor a
-	ld [hMultiplicand + 0], a
-	ld [hMultiplicand + 1], a
-	ld a, d
-	ld [hMultiplicand + 2], a
-	ld [hMultiplier], a
-	jp Multiply
-
-INCLUDE "data/growth_rates.asm"
--- /dev/null
+++ b/engine/game/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/game/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/game/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/game/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"
--- a/engine/gbc_only.asm
+++ /dev/null
@@ -1,149 +1,0 @@
-GBCOnlyScreen: ; 4ea82
-
-	ld a, [hCGB]
-	and a
-	ret nz
-
-	ld de, MUSIC_NONE
-	call PlayMusic
-
-	call ClearTileMap
-
-	ld hl, GBCOnlyGFX
-	ld de, wGBCOnlyDecompressBuffer
-	ld a, [rSVBK]
-	push af
-	ld a, 0 ; this has the same effect as selecting bank 1
-	ld [rSVBK], a
-	call Decompress
-	pop af
-	ld [rSVBK], a
-
-	ld de, wGBCOnlyDecompressBuffer
-	ld hl, vTiles2
-	lb bc, BANK(GBCOnlyGFX), 84
-	call Get2bpp
-
-	ld de, Font
-	ld hl, vTiles1
-	lb bc, BANK(Font), $80
-	call Get1bpp
-
-	call DrawGBCOnlyScreen
-
-	call WaitBGMap
-
-; better luck next time
-.loop
-	call DelayFrame
-	jr .loop
-; 4eac5
-
-
-DrawGBCOnlyScreen: ; 4eac5
-
-	call DrawGBCOnlyBorder
-
-	; Pokemon
-	hlcoord 3, 2
-	ld b, 14
-	ld c, 4
-	ld a, $8
-	call DrawGBCOnlyGraphic
-
-	; Crystal
-	hlcoord 5, 6
-	ld b, 10
-	ld c, 2
-	ld a, $40
-	call DrawGBCOnlyGraphic
-
-	ld de, GBCOnlyString
-	hlcoord 1, 10
-	call PlaceString
-
-	ret
-; 4eaea
-
-
-DrawGBCOnlyBorder: ; 4eaea
-
-	hlcoord 0, 0
-	ld [hl], 0 ; top-left
-
-	inc hl
-	ld a, 1 ; top
-	call .FillRow
-
-	ld [hl], 2 ; top-right
-
-	hlcoord 0, 1
-	ld a, 3 ; left
-	call .FillColumn
-
-	hlcoord 19, 1
-	ld a, 4 ; right
-	call .FillColumn
-
-	hlcoord 0, 17
-	ld [hl], 5 ; bottom-left
-
-	inc hl
-	ld a, 6 ; bottom
-	call .FillRow
-
-	ld [hl], 7 ; bottom-right
-	ret
-; 4eb15
-
-.FillRow: ; 4eb15
-	ld c, SCREEN_WIDTH - 2
-.next_column
-	ld [hli], a
-	dec c
-	jr nz, .next_column
-	ret
-; 4eb1c
-
-.FillColumn: ; 4eb1c
-	ld de, SCREEN_WIDTH
-	ld c, SCREEN_HEIGHT - 2
-.next_row
-	ld [hl], a
-	add hl, de
-	dec c
-	jr nz, .next_row
-	ret
-; 4eb27
-
-
-DrawGBCOnlyGraphic: ; 4eb27
-	ld de, SCREEN_WIDTH
-.y
-	push bc
-	push hl
-.x
-	ld [hli], a
-	inc a
-	dec b
-	jr nz, .x
-	pop hl
-	add hl, de
-	pop bc
-	dec c
-	jr nz, .y
-	ret
-; 4eb38
-
-
-GBCOnlyString: ; 4eb38
-	db   "This Game Pak is"
-	next "designed only for"
-	next "use on the"
-	next "Game Boy Color.@"
-; 4eb76
-
-
-GBCOnlyGFX: ; 4eb76
-INCBIN "gfx/sgb/gbc_only.2bpp.lz"
-; 4f0bc
--- /dev/null
+++ b/engine/gfx/cgb_layouts.asm
@@ -1,0 +1,1033 @@
+; Replaces the functionality of sgb.asm to work with CGB hardware.
+
+CheckCGB: ; 8d55
+	ld a, [hCGB]
+	and a
+	ret
+; 8d59
+
+LoadSGBLayoutCGB: ; 8d59
+	ld a, b
+	cp SCGB_RAM
+	jr nz, .not_ram
+	ld a, [wSGBPredef]
+.not_ram
+	cp SCGB_PARTY_MENU_HP_PALS
+	jp z, CGB_ApplyPartyMenuHPPals
+	call ResetBGPals
+	ld l, a
+	ld h, 0
+	add hl, hl
+	ld de, .dw
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, .ReturnFromJumpTable
+	push de
+	jp hl
+; 8d79
+
+.ReturnFromJumpTable: ; 8d79
+	ret
+; 8d7a
+
+.dw ; 8d7a
+	dw _CGB_BattleGrayscale
+	dw _CGB_BattleColors
+	dw _CGB_PokegearPals
+	dw _CGB_StatsScreenHPPals
+	dw _CGB_Pokedex
+	dw _CGB_SlotMachine
+	dw _CGB06
+	dw _CGB_GSIntro
+	dw _CGB_Diploma
+	dw _CGB_MapPals
+	dw _CGB_PartyMenu
+	dw _CGB_Evolution
+	dw _CGB_GSTitleScreen
+	dw _CGB0d
+	dw _CGB_MoveList
+	dw _CGB0f
+	dw _CGB_PokedexSearchOption
+	dw _CGB11
+	dw _CGB_Pokepic
+	dw _CGB13
+	dw _CGB_PackPals
+	dw _CGB_TrainerCard
+	dw _CGB_PokedexUnownMode
+	dw _CGB_BillsPC
+	dw _CGB_UnownPuzzle
+	dw _CGB_GamefreakLogo
+	dw _CGB_PlayerOrMonFrontpicPals
+	dw _CGB_TradeTube
+	dw _CGB_TrainerOrMonFrontpicPals
+	dw _CGB_MysteryGift
+	dw _CGB1e
+; 8db8
+
+_CGB_BattleGrayscale: ; 8db8
+	ld hl, PalPacket_BattleGrayscale + 1
+	ld de, wBGPals1
+	ld c, 4
+	call CopyPalettes
+	ld hl, PalPacket_BattleGrayscale + 1
+	ld de, wBGPals1 palette PAL_BATTLE_BG_EXP
+	ld c, 4
+	call CopyPalettes
+	ld hl, PalPacket_BattleGrayscale + 1
+	ld de, wOBPals1
+	ld c, 2
+	call CopyPalettes
+	jr _CGB_FinishBattleScreenLayout
+
+_CGB_BattleColors: ; 8ddb
+	ld de, wBGPals1
+	call GetBattlemonBackpicPalettePointer
+	push hl
+	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_BG_PLAYER
+	call GetEnemyFrontpicPalettePointer
+	push hl
+	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_BG_ENEMY
+	ld a, [wEnemyHPPal]
+	ld l, a
+	ld h, $0
+	add hl, hl
+	add hl, hl
+	ld bc, HPBarPals
+	add hl, bc
+	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_BG_ENEMY_HP
+	ld a, [wPlayerHPPal]
+	ld l, a
+	ld h, $0
+	add hl, hl
+	add hl, hl
+	ld bc, HPBarPals
+	add hl, bc
+	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_BG_PLAYER_HP
+	ld hl, ExpBarPalette
+	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_BG_EXP
+	ld de, wOBPals1
+	pop hl
+	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_OB_ENEMY
+	pop hl
+	call LoadPalette_White_Col1_Col2_Black ; PAL_BATTLE_OB_PLAYER
+	ld a, SCGB_BATTLE_COLORS
+	ld [wSGBPredef], a
+	call ApplyPals
+_CGB_FinishBattleScreenLayout: ; 8e23
+	call InitPartyMenuBGPal7
+	hlcoord 0, 0, wAttrMap
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, PAL_BATTLE_BG_ENEMY_HP
+	call ByteFill
+	hlcoord 0, 4, wAttrMap
+	lb bc, 8, 10
+	ld a, PAL_BATTLE_BG_PLAYER
+	call FillBoxCGB
+	hlcoord 10, 0, wAttrMap
+	lb bc, 7, 10
+	ld a, PAL_BATTLE_BG_ENEMY
+	call FillBoxCGB
+	hlcoord 0, 0, wAttrMap
+	lb bc, 4, 10
+	ld a, PAL_BATTLE_BG_ENEMY_HP
+	call FillBoxCGB
+	hlcoord 10, 7, wAttrMap
+	lb bc, 5, 10
+	ld a, PAL_BATTLE_BG_PLAYER_HP
+	call FillBoxCGB
+	hlcoord 10, 11, wAttrMap
+	lb bc, 1, 9
+	ld a, PAL_BATTLE_BG_EXP
+	call FillBoxCGB
+	hlcoord 0, 12, wAttrMap
+	ld bc, 6 * SCREEN_WIDTH
+	ld a, PAL_BATTLE_BG_TEXT
+	call ByteFill
+	ld hl, BattleObjectPals
+	ld de, wOBPals1 palette PAL_BATTLE_OB_GRAY
+	ld bc, 6 palettes
+	ld a, BANK(wOBPals1)
+	call FarCopyWRAM
+	call ApplyAttrMap
+	ret
+; 8e85
+
+
+InitPartyMenuBGPal7: ; 8e85
+	farcall Function100dc0
+Mobile_InitPartyMenuBGPal7: ; 8e8b
+	ld hl, PartyMenuBGPalette
+	jr nc, .not_mobile
+	ld hl, PartyMenuBGMobilePalette
+.not_mobile
+	ld de, wBGPals1 palette 7
+	ld bc, 1 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	ret
+; 8e9f
+
+InitPartyMenuBGPal0: ; 8e9f
+	farcall Function100dc0
+	ld hl, PartyMenuBGPalette
+	jr nc, .not_mobile
+	ld hl, PartyMenuBGMobilePalette
+.not_mobile
+	ld de, wBGPals1 palette 0
+	ld bc, 1 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	ret
+; 8eb9
+
+_CGB_PokegearPals: ; 8eb9
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .male
+	ld hl, FemalePokegearPals
+	jr .got_pals
+
+.male
+	ld hl, MalePokegearPals
+.got_pals
+	ld de, wBGPals1
+	ld bc, 6 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 8edb
+
+_CGB_StatsScreenHPPals: ; 8edb
+	ld de, wBGPals1
+	ld a, [wCurHPPal]
+	ld l, a
+	ld h, $0
+	add hl, hl
+	add hl, hl
+	ld bc, HPBarPals
+	add hl, bc
+	call LoadPalette_White_Col1_Col2_Black ; hp palette
+	ld a, [wCurPartySpecies]
+	ld bc, wTempMonDVs
+	call GetPlayerOrMonPalettePointer
+	call LoadPalette_White_Col1_Col2_Black ; mon palette
+	ld hl, ExpBarPalette
+	call LoadPalette_White_Col1_Col2_Black ; exp palette
+	ld hl, StatsScreenPagePals
+	ld de, wBGPals1 palette 3
+	ld bc, 3 palettes ; pink, green, and blue page palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	call WipeAttrMap
+
+	hlcoord 0, 0, wAttrMap
+	lb bc, 8, SCREEN_WIDTH
+	ld a, $1 ; mon palette
+	call FillBoxCGB
+
+	hlcoord 10, 16, wAttrMap
+	ld bc, 10
+	ld a, $2 ; exp palette
+	call ByteFill
+
+	hlcoord 13, 5, wAttrMap
+	lb bc, 2, 2
+	ld a, $3 ; pink page palette
+	call FillBoxCGB
+
+	hlcoord 15, 5, wAttrMap
+	lb bc, 2, 2
+	ld a, $4 ; green page palette
+	call FillBoxCGB
+
+	hlcoord 17, 5, wAttrMap
+	lb bc, 2, 2
+	ld a, $5 ; blue page palette
+	call FillBoxCGB
+
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 8f52
+
+StatsScreenPagePals: ; 8f52
+INCLUDE "gfx/stats/pages.pal"
+; 8f6a
+
+StatsScreenPals: ; 8f6a
+INCLUDE "gfx/stats/stats.pal"
+; 8f70
+
+_CGB_Pokedex: ; 8f70
+	ld de, wBGPals1
+	ld a, PREDEFPAL_POKEDEX
+	call GetPredefPal
+	call LoadHLPaletteIntoDE ; dex interface palette
+	ld a, [wCurPartySpecies]
+	cp $ff
+	jr nz, .is_pokemon
+	ld hl, .PokedexQuestionMarkPalette
+	call LoadHLPaletteIntoDE ; green question mark palette
+	jr .got_palette
+
+.is_pokemon
+	call GetMonPalettePointer_
+	call LoadPalette_White_Col1_Col2_Black ; mon palette
+.got_palette
+	call WipeAttrMap
+	hlcoord 1, 1, wAttrMap
+	lb bc, 7, 7
+	ld a, $1 ; green question mark palette
+	call FillBoxCGB
+	call InitPartyMenuOBPals
+	ld hl, .PokedexCursorPalette
+	ld de, wOBPals1 palette 7 ; green cursor palette
+	ld bc, 1 palettes
+	ld a, BANK(wOBPals1)
+	call FarCopyWRAM
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 8fba
+
+.PokedexQuestionMarkPalette: ; 8fba
+INCLUDE "gfx/pokedex/question_mark.pal"
+; 8fc2
+
+.PokedexCursorPalette: ; 8fc2
+INCLUDE "gfx/pokedex/cursor.pal"
+; 8fca
+
+_CGB_BillsPC: ; 8fca
+	ld de, wBGPals1
+	ld a, PREDEFPAL_POKEDEX
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+	ld a, [wCurPartySpecies]
+	cp $ff
+	jr nz, .GetMonPalette
+	ld hl, .BillsPCOrangePalette
+	call LoadHLPaletteIntoDE
+	jr .Resume
+
+.GetMonPalette:
+	ld bc, wTempMonDVs
+	call GetPlayerOrMonPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+.Resume:
+	call WipeAttrMap
+	hlcoord 1, 4, wAttrMap
+	lb bc, 7, 7
+	ld a, $1
+	call FillBoxCGB
+	call InitPartyMenuOBPals
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 9009
+
+.Function9009: ; 9009
+	ld hl, .BillsPCOrangePalette
+	call LoadHLPaletteIntoDE
+	jr .asm_901a
+
+.unused
+	ld bc, wTempMonDVs
+	call GetPlayerOrMonPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+.asm_901a
+	call WipeAttrMap
+	hlcoord 1, 1, wAttrMap
+	lb bc, 7, 7
+	ld a, $1
+	call FillBoxCGB
+	call InitPartyMenuOBPals
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 9036
+
+.BillsPCOrangePalette: ; 9036
+INCLUDE "gfx/pc/orange.pal"
+; 903e
+
+_CGB_PokedexUnownMode: ; 903e
+	ld de, wBGPals1
+	ld a, PREDEFPAL_POKEDEX
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+	ld a, [wCurPartySpecies]
+	call GetMonPalettePointer_
+	call LoadPalette_White_Col1_Col2_Black
+	call WipeAttrMap
+	hlcoord 7, 5, wAttrMap
+	lb bc, 7, 7
+	ld a, $1
+	call FillBoxCGB
+	call InitPartyMenuOBPals
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 906e
+
+_CGB_SlotMachine: ; 906e
+	ld hl, SlotMachinePals
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	call WipeAttrMap
+	hlcoord 0, 2, wAttrMap
+	lb bc, 10, 3
+	ld a, $2
+	call FillBoxCGB
+	hlcoord 17, 2, wAttrMap
+	lb bc, 10, 3
+	ld a, $2
+	call FillBoxCGB
+	hlcoord 0, 4, wAttrMap
+	lb bc, 6, 3
+	ld a, $3
+	call FillBoxCGB
+	hlcoord 17, 4, wAttrMap
+	lb bc, 6, 3
+	ld a, $3
+	call FillBoxCGB
+	hlcoord 0, 6, wAttrMap
+	lb bc, 2, 3
+	ld a, $4
+	call FillBoxCGB
+	hlcoord 17, 6, wAttrMap
+	lb bc, 2, 3
+	ld a, $4
+	call FillBoxCGB
+	hlcoord 4, 2, wAttrMap
+	lb bc, 2, 12
+	ld a, $1
+	call FillBoxCGB
+	hlcoord 3, 2, wAttrMap
+	lb bc, 10, 1
+	ld a, $1
+	call FillBoxCGB
+	hlcoord 16, 2, wAttrMap
+	lb bc, 10, 1
+	ld a, $1
+	call FillBoxCGB
+	hlcoord 0, 12, wAttrMap
+	ld bc, $78
+	ld a, $7
+	call ByteFill
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 90f8
+
+_CGB06: ; 90f8
+	ld hl, PalPacket_SCGB_06 + 1
+	call CopyFourPalettes
+	call WipeAttrMap
+	ld de, wOBPals1
+	ld a, PREDEFPAL_PACK
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+	hlcoord 0, 6, wAttrMap
+	lb bc, 12, SCREEN_WIDTH
+	ld a, $1
+	call FillBoxCGB
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 9122
+
+_CGB_GSIntro: ; 9122
+	ld b, 0
+	ld hl, .Jumptable
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+; 912d
+
+.Jumptable: ; 912d
+	dw .ShellderLaprasScene
+	dw .JigglypuffPikachuScene
+	dw .StartersCharizardScene
+; 9133
+
+.ShellderLaprasScene: ; 9133
+	ld hl, .ShellderLaprasBGPalette
+	ld de, wBGPals1
+	call LoadHLPaletteIntoDE
+	ld hl, .ShellderLaprasOBPals
+	ld de, wOBPals1
+	ld bc, 2 palettes
+	ld a, BANK(wOBPals1)
+	call FarCopyWRAM
+	call WipeAttrMap
+	ret
+; 914e
+
+.ShellderLaprasBGPalette: ; 914e
+	RGB 19, 31, 19
+	RGB 18, 23, 31
+	RGB 11, 21, 28
+	RGB 04, 16, 24
+
+.ShellderLaprasOBPals: ; 9156
+	RGB 29, 29, 29
+	RGB 20, 19, 20
+	RGB 19, 06, 04
+	RGB 03, 04, 06
+
+	RGB 31, 31, 31
+	RGB 31, 31, 31
+	RGB 31, 00, 00
+	RGB 03, 04, 06
+; 9166
+
+.JigglypuffPikachuScene: ; 9166
+	ld de, wBGPals1
+	ld a, PREDEFPAL_GS_INTRO_JIGGLYPUFF_PIKACHU_BG
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+
+	ld de, wOBPals1
+	ld a, PREDEFPAL_GS_INTRO_JIGGLYPUFF_PIKACHU_OB
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+	call WipeAttrMap
+	ret
+; 9180
+
+.StartersCharizardScene: ; 9180
+	ld hl, PalPacket_Pack + 1
+	call CopyFourPalettes
+	ld de, wOBPals1
+	ld a, PREDEFPAL_GS_INTRO_STARTERS_TRANSITION
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+	call WipeAttrMap
+	ret
+; 9195
+
+_CGB11: ; 9195
+	ld hl, Palettes_SCGB_11
+	ld de, wBGPals1
+	ld bc, 5 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	call ApplyPals
+	call WipeAttrMap
+	call ApplyAttrMap
+	ret
+; 91ad
+
+_CGB_Diploma: ; 91ad
+	ld hl, DiplomaPalettes
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+
+	ld hl, PalPacket_Diploma + 1
+	call CopyFourPalettes
+	call WipeAttrMap
+	call ApplyAttrMap
+	ret
+; 91c8
+
+_CGB_MapPals: ; 91c8
+	call LoadMapPals
+	ld a, SCGB_MAPPALS
+	ld [wSGBPredef], a
+	ret
+; 91d1
+
+_CGB_PartyMenu: ; 91d1
+	ld hl, PalPacket_PartyMenu + 1
+	call CopyFourPalettes
+	call InitPartyMenuBGPal0
+	call InitPartyMenuBGPal7
+	call InitPartyMenuOBPals
+	call ApplyAttrMap
+	ret
+; 91e4
+
+_CGB_Evolution: ; 91e4
+	ld de, wBGPals1
+	ld a, c
+	and a
+	jr z, .pokemon
+	ld a, PREDEFPAL_BLACKOUT
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+	jr .got_palette
+
+.pokemon
+	ld hl, wPartyMon1DVs
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld c, l
+	ld b, h
+	ld a, [wPlayerHPPal]
+	call GetPlayerOrMonPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+	ld hl, BattleObjectPals
+	ld de, wOBPals1 palette PAL_BATTLE_OB_GRAY
+	ld bc, 6 palettes
+	ld a, BANK(wOBPals1)
+	call FarCopyWRAM
+
+.got_palette
+	call WipeAttrMap
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 9228
+
+_CGB_GSTitleScreen: ; 9228
+	ld hl, UnusedGSTitleBGPals
+	ld de, wBGPals1
+	ld bc, 5 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	ld hl, UnusedGSTitleOBPals
+	ld de, wOBPals1
+	ld bc, 2 palettes
+	ld a, BANK(wOBPals1)
+	call FarCopyWRAM
+	ld a, SCGB_DIPLOMA
+	ld [wSGBPredef], a
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 9251
+
+_CGB0d: ; 9251
+	ld hl, PalPacket_Diploma + 1
+	call CopyFourPalettes
+	call WipeAttrMap
+	call ApplyAttrMap
+	ret
+; 925e
+
+_CGB_UnownPuzzle: ; 925e
+	ld hl, PalPacket_UnownPuzzle + 1
+	call CopyFourPalettes
+	ld de, wOBPals1
+	ld a, PREDEFPAL_UNOWN_PUZZLE
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wOBPals1)
+	ld [rSVBK], a
+	ld hl, wOBPals1
+	ld a, LOW(palred 31 + palgreen 0 + palblue 0)
+	ld [hli], a
+	ld a, HIGH(palred 31 + palgreen 0 + palblue 0)
+	ld [hl], a
+	pop af
+	ld [rSVBK], a
+	call WipeAttrMap
+	call ApplyAttrMap
+	ret
+; 9289
+
+_CGB_TrainerCard: ; 9289
+	ld de, wBGPals1
+	xor a ; CHRIS
+	call GetTrainerPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+	ld a, FALKNER ; KRIS
+	call GetTrainerPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+	ld a, BUGSY
+	call GetTrainerPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+	ld a, WHITNEY
+	call GetTrainerPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+	ld a, MORTY
+	call GetTrainerPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+	ld a, CHUCK
+	call GetTrainerPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+	ld a, JASMINE
+	call GetTrainerPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+	ld a, PRYCE
+	call GetTrainerPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+	ld a, PREDEFPAL_CGB_BADGE
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+
+	; fill screen with opposite-gender palette for the card border
+	hlcoord 0, 0, wAttrMap
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, [wPlayerGender]
+	and a
+	ld a, $1 ; kris
+	jr z, .got_gender
+	ld a, $0 ; chris
+.got_gender
+	call ByteFill
+	; fill trainer sprite area with same-gender palette
+	hlcoord 14, 1, wAttrMap
+	lb bc, 7, 5
+	ld a, [wPlayerGender]
+	and a
+	ld a, $0 ; chris
+	jr z, .got_gender2
+	ld a, $1 ; kris
+.got_gender2
+	call FillBoxCGB
+	; top-right corner still uses the border's palette
+	hlcoord 18, 1, wAttrMap
+	ld [hl], $1
+	hlcoord 2, 11, wAttrMap
+	lb bc, 2, 4
+	ld a, $1 ; falkner
+	call FillBoxCGB
+	hlcoord 6, 11, wAttrMap
+	lb bc, 2, 4
+	ld a, $2 ; bugsy
+	call FillBoxCGB
+	hlcoord 10, 11, wAttrMap
+	lb bc, 2, 4
+	ld a, $3 ; whitney
+	call FillBoxCGB
+	hlcoord 14, 11, wAttrMap
+	lb bc, 2, 4
+	ld a, $4 ; morty
+	call FillBoxCGB
+	hlcoord 2, 14, wAttrMap
+	lb bc, 2, 4
+	ld a, $5 ; chuck
+	call FillBoxCGB
+	hlcoord 6, 14, wAttrMap
+	lb bc, 2, 4
+	ld a, $6 ; jasmine
+	call FillBoxCGB
+	hlcoord 10, 14, wAttrMap
+	lb bc, 2, 4
+	ld a, $7 ; pryce
+	call FillBoxCGB
+	; clair uses kris's palette
+	ld a, [wPlayerGender]
+	and a
+	push af
+	jr z, .got_gender3
+	hlcoord 14, 14, wAttrMap
+	lb bc, 2, 4
+	ld a, $1
+	call FillBoxCGB
+.got_gender3
+	pop af
+	ld c, $0
+	jr nz, .got_gender4
+	inc c
+.got_gender4
+	ld a, c
+	hlcoord 18, 1, wAttrMap
+	ld [hl], a
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 9373
+
+_CGB_MoveList: ; 9373
+	ld de, wBGPals1
+	ld a, PREDEFPAL_GOLDENROD
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+	ld a, [wPlayerHPPal]
+	ld l, a
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	ld bc, HPBarPals
+	add hl, bc
+	call LoadPalette_White_Col1_Col2_Black
+	call WipeAttrMap
+	hlcoord 11, 1, wAttrMap
+	lb bc, 2, 9
+	ld a, $1
+	call FillBoxCGB
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 93a6
+
+_CGB0f: ; 93a6
+	ld hl, PalPacket_SCGB_0F + 1
+	call CopyFourPalettes
+	call WipeAttrMap
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 93ba
+
+_CGB_PokedexSearchOption: ; 93ba
+	ld de, wBGPals1
+	ld a, PREDEFPAL_POKEDEX
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+	call WipeAttrMap
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 93d3
+
+_CGB_PackPals: ; 93d3
+; pack pals
+	ld a, [wBattleType]
+	cp BATTLETYPE_TUTORIAL
+	jr z, .tutorial_male
+
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .tutorial_male
+
+	ld hl, .KrisPackPals
+	jr .got_gender
+
+.tutorial_male
+	ld hl, .ChrisPackPals
+
+.got_gender
+	ld de, wBGPals1
+	ld bc, 8 palettes ; 6 palettes?
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	call WipeAttrMap
+	hlcoord 0, 0, wAttrMap
+	lb bc, 1, 10
+	ld a, $1
+	call FillBoxCGB
+	hlcoord 10, 0, wAttrMap
+	lb bc, 1, 10
+	ld a, $2
+	call FillBoxCGB
+	hlcoord 7, 2, wAttrMap
+	lb bc, 9, 1
+	ld a, $3
+	call FillBoxCGB
+	hlcoord 0, 7, wAttrMap
+	lb bc, 3, 5
+	ld a, $4
+	call FillBoxCGB
+	hlcoord 0, 3, wAttrMap
+	lb bc, 3, 5
+	ld a, $5
+	call FillBoxCGB
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 9439
+
+.ChrisPackPals: ; 9439
+INCLUDE "gfx/pack/pack.pal"
+; 9469
+
+.KrisPackPals: ; 9469
+INCLUDE "gfx/pack/pack_f.pal"
+; 9499
+
+_CGB_Pokepic: ; 9499
+	call _CGB_MapPals
+	ld de, SCREEN_WIDTH
+	hlcoord 0, 0, wAttrMap
+	ld a, [wMenuBorderTopCoord]
+.loop
+	and a
+	jr z, .found_top
+	dec a
+	add hl, de
+	jr .loop
+
+.found_top
+	ld a, [wMenuBorderLeftCoord]
+	ld e, a
+	ld d, $0
+	add hl, de
+	ld a, [wMenuBorderTopCoord]
+	ld b, a
+	ld a, [wMenuBorderBottomCoord]
+	inc a
+	sub b
+	ld b, a
+	ld a, [wMenuBorderLeftCoord]
+	ld c, a
+	ld a, [wMenuBorderRightCoord]
+	sub c
+	inc a
+	ld c, a
+	ld a, $0
+	call FillBoxCGB
+	call ApplyAttrMap
+	ret
+; 94d0
+
+_CGB13: ; 94d0
+	ld hl, PalPacket_SCGB_13 + 1
+	call CopyFourPalettes
+	call WipeAttrMap
+	hlcoord 0, 4, wAttrMap
+	lb bc, 10, SCREEN_WIDTH
+	ld a, $2
+	call FillBoxCGB
+	hlcoord 0, 6, wAttrMap
+	lb bc, 6, SCREEN_WIDTH
+	ld a, $1
+	call FillBoxCGB
+	call ApplyAttrMap
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 94fa
+
+_CGB_GamefreakLogo: ; 94fa
+	ld de, wBGPals1
+	ld a, PREDEFPAL_GAMEFREAK_LOGO
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+	ld hl, .Palette
+	ld de, wOBPals1
+	call LoadHLPaletteIntoDE
+	ld hl, .Palette
+	ld de, wOBPals1 palette 1
+	call LoadHLPaletteIntoDE
+	call WipeAttrMap
+	call ApplyAttrMap
+	call ApplyPals
+	ret
+; 9521
+
+.Palette: ; 9521
+INCLUDE "gfx/splash/logo.pal"
+; 9529
+
+_CGB_PlayerOrMonFrontpicPals: ; 9529
+	ld de, wBGPals1
+	ld a, [wCurPartySpecies]
+	ld bc, wTempMonDVs
+	call GetPlayerOrMonPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+	call WipeAttrMap
+	call ApplyAttrMap
+	call ApplyPals
+	ret
+; 9542
+
+_CGB1e: ; 9542
+	ld de, wBGPals1
+	ld a, [wCurPartySpecies]
+	call GetMonPalettePointer_
+	call LoadPalette_White_Col1_Col2_Black
+	call WipeAttrMap
+	call ApplyAttrMap
+	ret
+; 9555
+
+_CGB_TradeTube: ; 9555
+	ld hl, PalPacket_TradeTube + 1
+	call CopyFourPalettes
+	ld hl, PartyMenuOBPals
+	ld de, wOBPals1
+	ld bc, 1 palettes
+	ld a, BANK(wOBPals1)
+	call FarCopyWRAM
+	ld de, wOBPals1 palette 7
+	ld a, PREDEFPAL_TRADE_TUBE
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+	call WipeAttrMap
+	ret
+; 9578
+
+_CGB_TrainerOrMonFrontpicPals: ; 9578
+	ld de, wBGPals1
+	ld a, [wCurPartySpecies]
+	ld bc, wTempMonDVs
+	call GetFrontpicPalettePointer
+	call LoadPalette_White_Col1_Col2_Black
+	call WipeAttrMap
+	call ApplyAttrMap
+	call ApplyPals
+	ret
+; 9591
+
+_CGB_MysteryGift: ; 9591
+	ld hl, .Palettes
+	ld de, wBGPals1
+	ld bc, 2 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	call ApplyPals
+	call WipeAttrMap
+	hlcoord 3, 7, wAttrMap
+	lb bc, 8, 14
+	ld a, $1
+	call FillBoxCGB
+	hlcoord 1, 5, wAttrMap
+	lb bc, 1, 18
+	ld a, $1
+	call FillBoxCGB
+	hlcoord 1, 16, wAttrMap
+	lb bc, 1, 18
+	ld a, $1
+	call FillBoxCGB
+	hlcoord 0, 0, wAttrMap
+	lb bc, 17, 2
+	ld a, $1
+	call FillBoxCGB
+	hlcoord 18, 5, wAttrMap
+	lb bc, 12, 1
+	ld a, $1
+	call FillBoxCGB
+	call ApplyAttrMap
+	ret
+; 95e0
+
+.Palettes: ; 95e0
+INCLUDE "gfx/mystery_gift/mystery_gift.pal"
+; 95f0
--- /dev/null
+++ b/engine/gfx/color.asm
@@ -1,0 +1,1356 @@
+INCLUDE "engine/gfx/sgb_layouts.asm"
+
+SHINY_ATK_BIT EQU 5
+SHINY_DEF_VAL EQU 10
+SHINY_SPD_VAL EQU 10
+SHINY_SPC_VAL EQU 10
+
+CheckShininess:
+; Check if a mon is shiny by DVs at bc.
+; Return carry if shiny.
+
+	ld l, c
+	ld h, b
+
+; Attack
+	ld a, [hl]
+	and 1 << SHINY_ATK_BIT
+	jr z, .NotShiny
+
+; Defense
+	ld a, [hli]
+	and $f
+	cp  SHINY_DEF_VAL
+	jr nz, .NotShiny
+
+; Speed
+	ld a, [hl]
+	and $f0
+	cp  SHINY_SPD_VAL << 4
+	jr nz, .NotShiny
+
+; Special
+	ld a, [hl]
+	and $f
+	cp  SHINY_SPC_VAL
+	jr nz, .NotShiny
+
+.Shiny:
+	scf
+	ret
+
+.NotShiny:
+	and a
+	ret
+
+Unused_CheckContestMon:
+; Check a mon's DVs at hl in the bug catching contest.
+; Return carry if its DVs are good enough to place in the contest.
+
+; Attack
+	ld a, [hl]
+	cp 10 << 4
+	jr c, .Bad
+
+; Defense
+	ld a, [hli]
+	and $f
+	cp 10
+	jr c, .Bad
+
+; Speed
+	ld a, [hl]
+	cp 10 << 4
+	jr c, .Bad
+
+; Special
+	ld a, [hl]
+	and $f
+	cp 10
+	jr c, .Bad
+
+.Good:
+	scf
+	ret
+
+.Bad:
+	and a
+	ret
+
+Unreferenced_Function8aa4:
+	push de
+	push bc
+	ld hl, PalPacket_9ce6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	pop bc
+	pop de
+	ld a, c
+	ld [wSGBPals + 3], a
+	ld a, b
+	ld [wSGBPals + 4], a
+	ld a, e
+	ld [wSGBPals + 5], a
+	ld a, d
+	ld [wSGBPals + 6], a
+	ld hl, wSGBPals
+	call PushSGBPals_
+	ld hl, BlkPacket_9a86
+	call PushSGBPals_
+	ret
+
+InitPartyMenuPalettes:
+	ld hl, PalPacket_PartyMenu + 1
+	call CopyFourPalettes
+	call InitPartyMenuOBPals
+	call WipeAttrMap
+	ret
+
+; SGB layout for SCGB_PARTY_MENU_HP_PALS
+SGB_ApplyPartyMenuHPPals: ; 8ade
+	ld hl, wHPPals
+	ld a, [wSGBPals]
+	ld e, a
+	ld d, $0
+	add hl, de
+	ld e, l
+	ld d, h
+	ld a, [de]
+	and a
+	ld e, $5
+	jr z, .okay
+	dec a
+	ld e, $a
+	jr z, .okay
+	ld e, $f
+.okay
+	push de
+	ld hl, wSGBPals + 10
+	ld bc, $6
+	ld a, [wSGBPals]
+	call AddNTimes
+	pop de
+	ld [hl], e
+	ret
+
+Unreferenced_Function8b07:
+	call CheckCGB
+	ret z
+; CGB only
+	ld hl, .BGPal
+	ld de, wBGPals1
+	ld bc, 1 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+
+	ld hl, .OBPal
+	ld de, wOBPals1
+	ld bc, 1 palettes
+	ld a, BANK(wOBPals1)
+	call FarCopyWRAM
+
+	call ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+
+.BGPal:
+	RGB 31, 31, 31
+	RGB 18, 23, 31
+	RGB 15, 20, 31
+	RGB 00, 00, 00
+
+.OBPal:
+	RGB 31, 31, 31
+	RGB 31, 31, 12
+	RGB 08, 16, 28
+	RGB 00, 00, 00
+
+Unreferenced_Function8b3f:
+	call CheckCGB
+	ret nz
+	ld a, [hSGB]
+	and a
+	ret z
+	ld hl, BlkPacket_9a86
+	jp PushSGBPals_
+
+Unreferenced_Function8b4d:
+	call CheckCGB
+	jr nz, .cgb
+	ld a, [hSGB]
+	and a
+	ret z
+	ld hl, PalPacket_Function8b4d
+	jp PushSGBPals_
+
+.cgb
+	ld de, wOBPals1
+	ld a, PREDEFPAL_3B
+	call GetPredefPal
+	jp LoadHLPaletteIntoDE
+
+Unreferenced_Function8b67:
+	call CheckCGB
+	jr nz, .cgb
+	ld a, [hSGB]
+	and a
+	ret z
+	ld hl, PalPacket_Pack
+	jp PushSGBPals_
+
+.cgb
+	ld de, wOBPals1
+	ld a, PREDEFPAL_PACK
+	call GetPredefPal
+	jp LoadHLPaletteIntoDE
+
+Unreferenced_Function8b81:
+	call CheckCGB
+	jr nz, .cgb
+	ld a, [hSGB]
+	and a
+	ret z
+	ld a, c
+	push af
+	ld hl, PalPacket_9ce6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	pop af
+	call GetMonPalettePointer_
+	ld a, [hli]
+	ld [wSGBPals + 3], a
+	ld a, [hli]
+	ld [wSGBPals + 4], a
+	ld a, [hli]
+	ld [wSGBPals + 5], a
+	ld a, [hl]
+	ld [wSGBPals + 6], a
+	ld hl, wSGBPals
+	jp PushSGBPals_
+
+.cgb
+	ld de, wOBPals1
+	ld a, c
+	call GetMonPalettePointer_
+	call LoadPalette_White_Col1_Col2_Black
+	ret
+
+LoadTrainerClassPaletteAsNthBGPal:
+	ld a, [wTrainerClass]
+	call GetTrainerPalettePointer
+	ld a, e
+	jr got_palette_pointer_8bd7
+
+LoadMonPaletteAsNthBGPal:
+	ld a, [wCurPartySpecies]
+	call GetMonPalettePointer
+	ld a, e
+	bit 7, a
+	jr z, got_palette_pointer_8bd7
+	and $7f
+	inc hl
+	inc hl
+	inc hl
+	inc hl
+
+got_palette_pointer_8bd7
+	push hl
+	ld hl, wBGPals1
+	ld de, 1 palettes
+.loop
+	and a
+	jr z, .got_addr
+	add hl, de
+	dec a
+	jr .loop
+
+.got_addr
+	ld e, l
+	ld d, h
+	pop hl
+	call LoadPalette_White_Col1_Col2_Black
+	ret
+
+Unreferenced_Function8bec:
+	ld a, [hCGB]
+	and a
+	jr nz, .cgb
+	ld hl, wPlayerLightScreenCount
+	jp PushSGBPals_
+
+.cgb
+	ld a, [wEnemyLightScreenCount] ; col
+	ld c, a
+	ld a, [wEnemyReflectCount] ; row
+	hlcoord 0, 0, wAttrMap
+	ld de, SCREEN_WIDTH
+.loop
+	and a
+	jr z, .done
+	add hl, de
+	dec a
+	jr .loop
+
+.done
+	ld b, $0
+	add hl, bc
+	lb bc, 6, 4
+	ld a, [wEnemySafeguardCount] ; value
+	and $3
+	call FillBoxCGB
+	call CopyTilemapAtOnce
+	ret
+
+ApplyMonOrTrainerPals:
+	call CheckCGB
+	ret z
+	ld a, e
+	and a
+	jr z, .get_trainer
+	ld a, [wCurPartySpecies]
+	call GetMonPalettePointer_
+	jr .load_palettes
+
+.get_trainer
+	ld a, [wTrainerClass]
+	call GetTrainerPalettePointer
+
+.load_palettes
+	ld de, wBGPals1
+	call LoadPalette_White_Col1_Col2_Black
+	call WipeAttrMap
+	call ApplyAttrMap
+	call ApplyPals
+	ret
+
+ApplyHPBarPals:
+	ld a, [wWhichHPBar]
+	and a
+	jr z, .Enemy
+	cp $1
+	jr z, .Player
+	cp $2
+	jr z, .PartyMenu
+	ret
+
+.Enemy:
+	ld de, wBGPals2 palette PAL_BATTLE_BG_ENEMY_HP color 1
+	jr .okay
+
+.Player:
+	ld de, wBGPals2 palette PAL_BATTLE_BG_PLAYER_HP color 1
+
+.okay
+	ld l, c
+	ld h, $0
+	add hl, hl
+	add hl, hl
+	ld bc, HPBarPals
+	add hl, bc
+	ld bc, 4
+	ld a, BANK(wBGPals2)
+	call FarCopyWRAM
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+
+.PartyMenu:
+	ld e, c
+	inc e
+	hlcoord 11, 1, wAttrMap
+	ld bc, 2 * SCREEN_WIDTH
+	ld a, [wCurPartyMon]
+.loop
+	and a
+	jr z, .done
+	add hl, bc
+	dec a
+	jr .loop
+
+.done
+	lb bc, 2, 8
+	ld a, e
+	call FillBoxCGB
+	ret
+
+LoadStatsScreenPals:
+	call CheckCGB
+	ret z
+	ld hl, StatsScreenPals
+	ld b, 0
+	dec c
+	add hl, bc
+	add hl, bc
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld a, [hli]
+	ld [wBGPals1 palette 0], a
+	ld [wBGPals1 palette 2], a
+	ld a, [hl]
+	ld [wBGPals1 palette 0 + 1], a
+	ld [wBGPals1 palette 2 + 1], a
+	pop af
+	ld [rSVBK], a
+	call ApplyPals
+	ld a, $1
+	ret
+
+LoadMailPalettes:
+	ld l, e
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	add hl, hl
+	ld de, .MailPals
+	add hl, de
+	call CheckCGB
+	jr nz, .cgb
+	push hl
+	ld hl, PalPacket_9ce6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	pop hl
+	inc hl
+	inc hl
+	ld a, [hli]
+	ld [wSGBPals + 3], a
+	ld a, [hli]
+	ld [wSGBPals + 4], a
+	ld a, [hli]
+	ld [wSGBPals + 5], a
+	ld a, [hli]
+	ld [wSGBPals + 6], a
+	ld hl, wSGBPals
+	call PushSGBPals_
+	ld hl, BlkPacket_9a86
+	call PushSGBPals_
+	ret
+
+.cgb
+	ld de, wBGPals1
+	ld bc, 1 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	call ApplyPals
+	call WipeAttrMap
+	call ApplyAttrMap
+	ret
+
+.MailPals:
+INCLUDE "gfx/mail/mail.pal"
+
+INCLUDE "engine/gfx/cgb_layouts.asm"
+
+Unreferenced_Function95f0:
+	ld hl, .Palette
+	ld de, wBGPals1
+	ld bc, 1 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	call ApplyPals
+	call WipeAttrMap
+	call ApplyAttrMap
+	ret
+
+.Palette:
+	RGB 31, 31, 31
+	RGB 09, 31, 31
+	RGB 10, 12, 31
+	RGB 00, 03, 19
+
+CopyFourPalettes:
+	ld de, wBGPals1
+	ld c, 4
+
+CopyPalettes:
+.loop
+	push bc
+	ld a, [hli]
+	push hl
+	call GetPredefPal
+	call LoadHLPaletteIntoDE
+	pop hl
+	inc hl
+	pop bc
+	dec c
+	jr nz, .loop
+	ret
+
+GetPredefPal:
+	ld l, a
+	ld h, $0
+	add hl, hl
+	add hl, hl
+	add hl, hl
+	ld bc, PredefPals
+	add hl, bc
+	ret
+
+LoadHLPaletteIntoDE:
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wOBPals1)
+	ld [rSVBK], a
+	ld c, 1 palettes
+.loop
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec c
+	jr nz, .loop
+	pop af
+	ld [rSVBK], a
+	ret
+
+LoadPalette_White_Col1_Col2_Black:
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+
+	ld a, LOW(PALRGB_WHITE)
+	ld [de], a
+	inc de
+	ld a, HIGH(PALRGB_WHITE)
+	ld [de], a
+	inc de
+
+	ld c, 2 * PAL_COLOR_SIZE
+.loop
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec c
+	jr nz, .loop
+
+	xor a
+	ld [de], a
+	inc de
+	ld [de], a
+	inc de
+
+	pop af
+	ld [rSVBK], a
+	ret
+
+FillBoxCGB:
+.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
+
+ResetBGPals:
+	push af
+	push bc
+	push de
+	push hl
+
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+
+	ld hl, wBGPals1
+	ld c, 1 palettes
+.loop
+	ld a, $ff
+	ld [hli], a
+	ld [hli], a
+	ld [hli], a
+	ld [hli], a
+	xor a
+	ld [hli], a
+	ld [hli], a
+	ld [hli], a
+	ld [hli], a
+	dec c
+	jr nz, .loop
+
+	pop af
+	ld [rSVBK], a
+
+	pop hl
+	pop de
+	pop bc
+	pop af
+	ret
+
+WipeAttrMap:
+	hlcoord 0, 0, wAttrMap
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	xor a
+	call ByteFill
+	ret
+
+ApplyPals:
+	ld hl, wBGPals1
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	ld a, BANK(wGBCPalettes)
+	call FarCopyWRAM
+	ret
+
+ApplyAttrMap:
+	ld a, [rLCDC]
+	bit rLCDC_ENABLE, a
+	jr z, .UpdateVBank1
+	ld a, [hBGMapMode]
+	push af
+	ld a, $2
+	ld [hBGMapMode], a
+	call DelayFrame
+	call DelayFrame
+	call DelayFrame
+	call DelayFrame
+	pop af
+	ld [hBGMapMode], a
+	ret
+
+.UpdateVBank1:
+	hlcoord 0, 0, wAttrMap
+	debgcoord 0, 0
+	ld b, SCREEN_HEIGHT
+	ld a, $1
+	ld [rVBK], a
+.row
+	ld c, SCREEN_WIDTH
+.col
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec c
+	jr nz, .col
+	ld a, BG_MAP_WIDTH - SCREEN_WIDTH
+	add e
+	jr nc, .okay
+	inc d
+.okay
+	ld e, a
+	dec b
+	jr nz, .row
+	ld a, $0
+	ld [rVBK], a
+	ret
+
+; CGB layout for SCGB_PARTY_MENU_HP_PALS
+CGB_ApplyPartyMenuHPPals: ; 96f3
+	ld hl, wHPPals
+	ld a, [wSGBPals]
+	ld e, a
+	ld d, $0
+	add hl, de
+	ld e, l
+	ld d, h
+	ld a, [de]
+	inc a
+	ld e, a
+	hlcoord 11, 2, wAttrMap
+	ld bc, 2 * SCREEN_WIDTH
+	ld a, [wSGBPals]
+.loop
+	and a
+	jr z, .done
+	add hl, bc
+	dec a
+	jr .loop
+.done
+	lb bc, 2, 8
+	ld a, e
+	call FillBoxCGB
+	ret
+
+InitPartyMenuOBPals:
+	ld hl, PartyMenuOBPals
+	ld de, wOBPals1
+	ld bc, 2 palettes
+	ld a, BANK(wOBPals1)
+	call FarCopyWRAM
+	ret
+
+GetBattlemonBackpicPalettePointer:
+	push de
+	farcall GetPartyMonDVs
+	ld c, l
+	ld b, h
+	ld a, [wTempBattleMonSpecies]
+	call GetPlayerOrMonPalettePointer
+	pop de
+	ret
+
+GetEnemyFrontpicPalettePointer:
+	push de
+	farcall GetEnemyMonDVs
+	ld c, l
+	ld b, h
+	ld a, [wTempEnemyMonSpecies]
+	call GetFrontpicPalettePointer
+	pop de
+	ret
+
+GetPlayerOrMonPalettePointer:
+	and a
+	jp nz, GetMonNormalOrShinyPalettePointer
+	ld a, [wPlayerSpriteSetupFlags]
+	bit PLAYERSPRITESETUP_FEMALE_TO_MALE_F, a
+	jr nz, .male
+	ld a, [wPlayerGender]
+	and a
+	jr z, .male
+	ld hl, KrisPalette
+	ret
+
+.male
+	ld hl, PlayerPalette
+	ret
+
+GetFrontpicPalettePointer:
+	and a
+	jp nz, GetMonNormalOrShinyPalettePointer
+	ld a, [wTrainerClass]
+
+GetTrainerPalettePointer:
+	ld l, a
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	ld bc, TrainerPalettes
+	add hl, bc
+	ret
+
+GetMonPalettePointer_:
+	call GetMonPalettePointer
+	ret
+
+Unreferenced_Function9779:
+	ret
+	call CheckCGB
+	ret z
+	ld hl, BattleObjectPals
+	ld a, $90
+	ld [rOBPI], a
+	ld c, 6 palettes
+.loop
+	ld a, [hli]
+	ld [rOBPD], a
+	dec c
+	jr nz, .loop
+	ld hl, BattleObjectPals
+	ld de, wOBPals1 palette 2
+	ld bc, 2 palettes
+	ld a, BANK(wOBPals1)
+	call FarCopyWRAM
+	ret
+
+BattleObjectPals:
+INCLUDE "gfx/battle_anims/battle_anims.pal"
+
+Unreferenced_Function97cc:
+	call CheckCGB
+	ret z
+	ld a, $90
+	ld [rOBPI], a
+	ld a, PREDEFPAL_TRADE_TUBE
+	call GetPredefPal
+	call .PushPalette
+	ld a, PREDEFPAL_RB_GREENMON
+	call GetPredefPal
+	call .PushPalette
+	ret
+
+.PushPalette:
+	ld c, 1 palettes
+.loop
+	ld a, [hli]
+	ld [rOBPD], a
+	dec c
+	jr nz, .loop
+	ret
+
+GetMonPalettePointer:
+	ld l, a
+	ld h, $0
+	add hl, hl
+	add hl, hl
+	add hl, hl
+	ld bc, PokemonPalettes
+	add hl, bc
+	ret
+
+GetMonNormalOrShinyPalettePointer:
+	push bc
+	call GetMonPalettePointer
+	pop bc
+	push hl
+	call CheckShininess
+	pop hl
+	ret nc
+rept 4
+	inc hl
+endr
+	ret
+
+PushSGBPals_:
+	ld a, [wcfbe]
+	push af
+	set 7, a
+	ld [wcfbe], a
+	call PushSGBPals
+	pop af
+	ld [wcfbe], a
+	ret
+
+PushSGBPals:
+	ld a, [hl]
+	and $7
+	ret z
+	ld b, a
+.loop
+	push bc
+	xor a
+	ld [rJOYP], a
+	ld a, $30
+	ld [rJOYP], a
+	ld b, $10
+.loop2
+	ld e, $8
+	ld a, [hli]
+	ld d, a
+.loop3
+	bit 0, d
+	ld a, $10
+	jr nz, .okay
+	ld a, $20
+.okay
+	ld [rJOYP], a
+	ld a, $30
+	ld [rJOYP], a
+	rr d
+	dec e
+	jr nz, .loop3
+	dec b
+	jr nz, .loop2
+	ld a, $20
+	ld [rJOYP], a
+	ld a, $30
+	ld [rJOYP], a
+	call SGBDelayCycles
+	pop bc
+	dec b
+	jr nz, .loop
+	ret
+
+InitSGBBorder:
+	call CheckCGB
+	ret nz
+; SGB/DMG only
+	di
+	ld a, [wcfbe]
+	push af
+	set 7, a
+	ld [wcfbe], a
+	xor a
+	ld [rJOYP], a
+	ld [hSGB], a
+	call PushSGBBorderPalsAndWait
+	jr nc, .skip
+	ld a, $1
+	ld [hSGB], a
+	call _InitSGBBorderPals
+	call SGBBorder_PushBGPals
+	call SGBDelayCycles
+	call SGB_ClearVRAM
+	call PushSGBBorder
+	call SGBDelayCycles
+	call SGB_ClearVRAM
+	ld hl, MaskEnCancelPacket
+	call PushSGBPals
+
+.skip
+	pop af
+	ld [wcfbe], a
+	ei
+	ret
+
+InitCGBPals::
+	call CheckCGB
+	ret z
+; CGB only
+	ld a, BANK(vTiles3)
+	ld [rVBK], a
+	ld hl, vTiles3
+	ld bc, $200 tiles
+	xor a
+	call ByteFill
+	ld a, BANK(vTiles0)
+	ld [rVBK], a
+	ld a, 1 << rBGPI_AUTO_INCREMENT
+	ld [rBGPI], a
+	ld c, 4 * 8
+.bgpals_loop
+	ld a, LOW(PALRGB_WHITE)
+	ld [rBGPD], a
+	ld a, HIGH(PALRGB_WHITE)
+	ld [rBGPD], a
+	dec c
+	jr nz, .bgpals_loop
+	ld a, 1 << rOBPI_AUTO_INCREMENT
+	ld [rOBPI], a
+	ld c, 4 * 8
+.obpals_loop
+	ld a, LOW(PALRGB_WHITE)
+	ld [rOBPD], a
+	ld a, HIGH(PALRGB_WHITE)
+	ld [rOBPD], a
+	dec c
+	jr nz, .obpals_loop
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld hl, wBGPals1
+	call .LoadWhitePals
+	ld hl, wBGPals2
+	call .LoadWhitePals
+	pop af
+	ld [rSVBK], a
+	ret
+
+.LoadWhitePals:
+	ld c, 4 * 16
+.loop
+	ld a, LOW(PALRGB_WHITE)
+	ld [hli], a
+	ld a, HIGH(PALRGB_WHITE)
+	ld [hli], a
+	dec c
+	jr nz, .loop
+	ret
+
+_InitSGBBorderPals:
+	ld hl, .PacketPointerTable
+	ld c, 9
+.loop
+	push bc
+	ld a, [hli]
+	push hl
+	ld h, [hl]
+	ld l, a
+	call PushSGBPals
+	pop hl
+	inc hl
+	pop bc
+	dec c
+	jr nz, .loop
+	ret
+
+.PacketPointerTable:
+	dw MaskEnFreezePacket
+	dw DataSndPacket1
+	dw DataSndPacket2
+	dw DataSndPacket3
+	dw DataSndPacket4
+	dw DataSndPacket5
+	dw DataSndPacket6
+	dw DataSndPacket7
+	dw DataSndPacket8
+
+Unreferenced_Function9911:
+	di
+	xor a
+	ld [rJOYP], a
+	ld hl, MaskEnFreezePacket
+	call PushSGBPals
+	call PushSGBBorder
+	call SGBDelayCycles
+	call SGB_ClearVRAM
+	ld hl, MaskEnCancelPacket
+	call PushSGBPals
+	ei
+	ret
+
+PushSGBBorder:
+	call .LoadSGBBorderPointers
+	push de
+	call SGBBorder_YetMorePalPushing
+	pop hl
+	call SGBBorder_MorePalPushing
+	ret
+
+.LoadSGBBorderPointers:
+	ld hl, SGBBorder
+	ld de, SGBBorderMap
+	ret
+
+SGB_ClearVRAM:
+	ld hl, VRAM_Begin
+	ld bc, VRAM_End - VRAM_Begin
+	xor a
+	call ByteFill
+	ret
+
+PushSGBBorderPalsAndWait:
+	ld hl, MltReq2Packet
+	call PushSGBPals
+	call SGBDelayCycles
+	ld a, [rJOYP]
+	and $3
+	cp $3
+	jr nz, .carry
+	ld a, $20
+	ld [rJOYP], a
+	ld a, [rJOYP]
+	ld a, [rJOYP]
+	call SGBDelayCycles
+	call SGBDelayCycles
+	ld a, $30
+	ld [rJOYP], a
+	call SGBDelayCycles
+	call SGBDelayCycles
+	ld a, $10
+	ld [rJOYP], a
+rept 6
+	ld a, [rJOYP]
+endr
+	call SGBDelayCycles
+	call SGBDelayCycles
+	ld a, $30
+	ld [rJOYP], a
+	ld a, [rJOYP]
+	ld a, [rJOYP]
+	ld a, [rJOYP]
+	call SGBDelayCycles
+	call SGBDelayCycles
+	ld a, [rJOYP]
+	and $3
+	cp $3
+	jr nz, .carry
+	call .FinalPush
+	and a
+	ret
+
+.carry
+	call .FinalPush
+	scf
+	ret
+
+.FinalPush:
+	ld hl, MltReq1Packet
+	call PushSGBPals
+	jp SGBDelayCycles
+
+SGBBorder_PushBGPals:
+	call DisableLCD
+	ld a, %11100100
+	ld [rBGP], a
+	ld hl, PredefPals
+	ld de, vTiles1
+	ld bc, $100 tiles
+	call CopyData
+	call DrawDefaultTiles
+	ld a, LCDC_DEFAULT
+	ld [rLCDC], a
+	ld hl, PalTrnPacket
+	call PushSGBPals
+	xor a
+	ld [rBGP], a
+	ret
+
+SGBBorder_MorePalPushing:
+	call DisableLCD
+	ld a, $e4
+	ld [rBGP], a
+	ld de, vTiles1
+	ld bc, 20 tiles
+	call CopyData
+	ld b, 18
+.loop
+	push bc
+	ld bc, $c
+	call CopyData
+	ld bc, $28
+	call ClearBytes
+	ld bc, $c
+	call CopyData
+	pop bc
+	dec b
+	jr nz, .loop
+	ld bc, $140
+	call CopyData
+	ld bc, Start
+	call ClearBytes
+	ld bc, 16 palettes
+	call CopyData
+	call DrawDefaultTiles
+	ld a, LCDC_DEFAULT
+	ld [rLCDC], a
+	ld hl, PctTrnPacket
+	call PushSGBPals
+	xor a
+	ld [rBGP], a
+	ret
+
+SGBBorder_YetMorePalPushing:
+	call DisableLCD
+	ld a, %11100100
+	ld [rBGP], a
+	ld de, vTiles1
+	ld b, $80
+.loop
+	push bc
+	ld bc, 1 tiles
+	call CopyData
+	ld bc, 1 tiles
+	call ClearBytes
+	pop bc
+	dec b
+	jr nz, .loop
+	call DrawDefaultTiles
+	ld a, LCDC_DEFAULT
+	ld [rLCDC], a
+	ld hl, ChrTrnPacket
+	call PushSGBPals
+	xor a
+	ld [rBGP], a
+	ret
+
+CopyData: ; 0x9a52
+; copy bc bytes of data from hl to de
+.loop
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec bc
+	ld a, c
+	or b
+	jr nz, .loop
+	ret
+; 0x9a5b
+
+ClearBytes: ; 0x9a5b
+; clear bc bytes of data starting from de
+.loop
+	xor a
+	ld [de], a
+	inc de
+	dec bc
+	ld a, c
+	or b
+	jr nz, .loop
+	ret
+; 0x9a64
+
+DrawDefaultTiles: ; 0x9a64
+; Draw 240 tiles (2/3 of the screen) from tiles in VRAM
+	hlbgcoord 0, 0 ; BG Map 0
+	ld de, BG_MAP_WIDTH - SCREEN_WIDTH
+	ld a, $80 ; starting tile
+	ld c, 12 + 1
+.line
+	ld b, 20
+.tile
+	ld [hli], a
+	inc a
+	dec b
+	jr nz, .tile
+; next line
+	add hl, de
+	dec c
+	jr nz, .line
+	ret
+; 0x9a7a
+
+SGBDelayCycles:
+	ld de, 7000
+.wait
+	nop
+	nop
+	nop
+	dec de
+	ld a, d
+	or e
+	jr nz, .wait
+	ret
+
+INCLUDE "gfx/sgb/blk_packets.asm"
+INCLUDE "gfx/sgb/pal_packets.asm"
+INCLUDE "data/sgb_ctrl_packets.asm"
+
+PredefPals:
+INCLUDE "gfx/sgb/predef.pal"
+
+SGBBorderMap:
+; interleaved tile ids and palette ids
+INCBIN "gfx/sgb/sgb_border.bin"
+
+SGBBorderPalettes:
+INCLUDE "gfx/sgb/sgb_border.pal"
+
+SGBBorder:
+INCBIN "gfx/sgb/sgb_border.2bpp"
+
+HPBarPals:
+INCLUDE "gfx/battle/hp_bar.pal"
+
+ExpBarPalette:
+INCLUDE "gfx/battle/exp_bar.pal"
+
+INCLUDE "data/pokemon/palettes.asm"
+
+INCLUDE "data/trainers/palettes.asm"
+
+LoadMapPals:
+	farcall LoadSpecialMapPalette
+	jr c, .got_pals
+
+	; Which palette group is based on whether we're outside or inside
+	ld a, [wEnvironment]
+	and 7
+	ld e, a
+	ld d, 0
+	ld hl, EnvironmentColorsPointers
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	; Futher refine by time of day
+	ld a, [wTimeOfDayPal]
+	maskbits NUM_DAYTIMES
+	add a
+	add a
+	add a
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld e, l
+	ld d, h
+	; Switch to palettes WRAM bank
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld hl, wBGPals1
+	ld b, 8
+.outer_loop
+	ld a, [de] ; lookup index for TilesetBGPalette
+	push de
+	push hl
+	ld l, a
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	add hl, hl
+	ld de, TilesetBGPalette
+	add hl, de
+	ld e, l
+	ld d, h
+	pop hl
+	ld c, 1 palettes
+.inner_loop
+	ld a, [de]
+	inc de
+	ld [hli], a
+	dec c
+	jr nz, .inner_loop
+	pop de
+	inc de
+	dec b
+	jr nz, .outer_loop
+	pop af
+	ld [rSVBK], a
+
+.got_pals
+	ld a, [wTimeOfDayPal]
+	maskbits NUM_DAYTIMES
+	ld bc, 8 palettes
+	ld hl, MapObjectPals
+	call AddNTimes
+	ld de, wOBPals1
+	ld bc, 8 palettes
+	ld a, BANK(wOBPals1)
+	call FarCopyWRAM
+
+	ld a, [wEnvironment]
+	cp TOWN
+	jr z, .outside
+	cp ROUTE
+	ret nz
+.outside
+	ld a, [wMapGroup]
+	ld l, a
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	add hl, hl
+	ld de, RoofPals
+	add hl, de
+	ld a, [wTimeOfDayPal]
+	maskbits NUM_DAYTIMES
+	cp NITE_F
+	jr c, .morn_day
+rept 4
+	inc hl
+endr
+.morn_day
+	ld de, wBGPals1 palette PAL_BG_ROOF color 1
+	ld bc, 4
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	ret
+
+INCLUDE "data/maps/environment_colors.asm"
+
+PartyMenuBGMobilePalette:
+INCLUDE "gfx/stats/party_menu_bg_mobile.pal"
+
+PartyMenuBGPalette:
+INCLUDE "gfx/stats/party_menu_bg.pal"
+
+TilesetBGPalette:
+INCLUDE "gfx/tilesets/bg_tiles.pal"
+
+MapObjectPals::
+INCLUDE "gfx/overworld/npc_sprites.pal"
+
+RoofPals:
+INCLUDE "gfx/tilesets/roofs.pal"
+
+DiplomaPalettes:
+INCLUDE "gfx/diploma/diploma.pal"
+
+PartyMenuOBPals:
+INCLUDE "gfx/stats/party_menu_ob.pal"
+
+UnusedGSTitleBGPals:
+INCLUDE "gfx/title/unused_gs_bg.pal"
+
+UnusedGSTitleOBPals:
+INCLUDE "gfx/title/unused_gs_fg.pal"
+
+MalePokegearPals:
+INCLUDE "gfx/pokegear/pokegear.pal"
+
+FemalePokegearPals:
+INCLUDE "gfx/pokegear/pokegear_f.pal"
+
+Palettes_SCGB_11:
+INCLUDE "gfx/unknown/b789.pal"
+
+SlotMachinePals:
+INCLUDE "gfx/slots/slots.pal"
--- /dev/null
+++ b/engine/gfx/crystal_layouts.asm
@@ -1,0 +1,325 @@
+GetMysteryGift_MobileAdapterLayout: ; 4930f (mobile)
+	ld a, b
+	cp SCGB_RAM
+	jr nz, .not_ram
+	ld a, [wSGBPredef]
+.not_ram
+	push af
+	farcall ResetBGPals
+	pop af
+	ld l, a
+	ld h, 0
+	add hl, hl
+	ld de, .dw
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, .done
+	push de
+	jp hl
+.done
+	ret
+; 49330 (12:5330)
+
+.dw ; 49330
+	dw MG_Mobile_Layout00
+	dw MG_Mobile_Layout01
+	dw MG_Mobile_Layout02
+; 49336
+
+MG_Mobile_Layout_FillBox: ; 49336
+.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
+; 49346
+
+MG_Mobile_Layout_WipeAttrMap: ; 49346 (12:5346)
+	hlcoord 0, 0, wAttrMap
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	xor a
+	call ByteFill
+	ret
+
+MG_Mobile_Layout_LoadPals: ; 49351 (12:5351)
+	ld de, wBGPals1
+	ld hl, Palette_MysteryGiftMobile
+	ld bc, 5 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	ld de, wBGPals1 palette PAL_BG_TEXT
+	ld hl, Palette_TextBG7
+	ld bc, 1 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	ret
+
+MG_Mobile_Layout00: ; 4936e (12:536e)
+	call MG_Mobile_Layout_LoadPals
+	call MG_Mobile_Layout_WipeAttrMap
+	call MG_Mobile_Layout_CreatePalBoxes
+	farcall ApplyAttrMap
+	farcall ApplyPals
+	ret
+
+MG_Mobile_Layout_CreatePalBoxes: ; 49384 (12:5384)
+	hlcoord 0, 0, wAttrMap
+	lb bc, 4, 1
+	ld a, $1
+	call MG_Mobile_Layout_FillBox
+	lb bc, 2, 1
+	ld a, $2
+	call MG_Mobile_Layout_FillBox
+	lb bc, 6, 1
+	ld a, $3
+	call MG_Mobile_Layout_FillBox
+	hlcoord 1, 0, wAttrMap
+	ld a, $1
+	lb bc, 3, 18
+	call MG_Mobile_Layout_FillBox
+	lb bc, 2, 18
+	ld a, $2
+	call MG_Mobile_Layout_FillBox
+	lb bc, 12, 18
+	ld a, $3
+	call MG_Mobile_Layout_FillBox
+	hlcoord 19, 0, wAttrMap
+	lb bc, 4, 1
+	ld a, $1
+	call MG_Mobile_Layout_FillBox
+	lb bc, 2, 1
+	ld a, $2
+	call MG_Mobile_Layout_FillBox
+	lb bc, 6, 1
+	ld a, $3
+	call MG_Mobile_Layout_FillBox
+	hlcoord 0, 12, wAttrMap
+	ld bc, 6 * SCREEN_WIDTH
+	ld a, $7
+	call ByteFill
+	ret
+; 493e1 (12:53e1)
+
+Palette_MysteryGiftMobile: ; 493e1
+INCLUDE "gfx/mystery_gift/mg_mobile.pal"
+; 49409
+
+LoadOW_BGPal7:: ; 49409
+	ld hl, Palette_TextBG7
+	ld de, wBGPals1 palette PAL_BG_TEXT
+	ld bc, 1 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	ret
+; 49418
+
+Palette_TextBG7: ; 49418
+INCLUDE "gfx/font/bg_text.pal"
+; 49420
+
+Function49420:: ; 49420 (12:5420)
+	ld hl, MansionPalette1 + 8 palettes
+	ld de, wBGPals1 palette PAL_BG_ROOF
+	ld bc, 1 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	ret
+; 4942f (12:542f)
+
+MG_Mobile_Layout01: ; 4942f
+	call MG_Mobile_Layout_LoadPals
+	ld de, wBGPals1 palette PAL_BG_TEXT
+	ld hl, .Palette_49478
+	ld bc, 1 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	call MG_Mobile_Layout_WipeAttrMap
+	hlcoord 0, 0, wAttrMap
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	xor a
+	call ByteFill
+	hlcoord 0, 14, wAttrMap
+	ld bc, 4 * SCREEN_WIDTH
+	ld a, $7
+	call ByteFill
+	ld a, [wd002]
+	bit 6, a
+	jr z, .asm_49464
+	call Function49480
+	jr .asm_49467
+
+.asm_49464
+	call Function49496
+
+.asm_49467
+	farcall ApplyAttrMap
+	farcall ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; 49478
+
+.Palette_49478: ; 49478
+	RGB 31, 31, 31
+	RGB 26, 31, 00
+	RGB 20, 16, 03
+	RGB 00, 00, 00
+; 49480
+
+Function49480: ; 49480
+	hlcoord 0, 0, wAttrMap
+	lb bc, 4, SCREEN_WIDTH
+	ld a, $7
+	call MG_Mobile_Layout_FillBox
+	hlcoord 0, 2, wAttrMap
+	ld a, $4
+	ld [hl], a
+	hlcoord 19, 2, wAttrMap
+	ld [hl], a
+	ret
+; 49496
+
+Function49496: ; 49496
+	hlcoord 0, 0, wAttrMap
+	lb bc, 2, SCREEN_WIDTH
+	ld a, $7
+	call MG_Mobile_Layout_FillBox
+	hlcoord 0, 1, wAttrMap
+	ld a, $4
+	ld [hl], a
+	hlcoord 19, 1, wAttrMap
+	ld [hl], a
+	ret
+; 494ac
+
+INCLUDE "engine/gfx/tileset_palettes.asm"
+
+MG_Mobile_Layout02: ; 49706
+	ld hl, .Palette_49732
+	ld de, wBGPals1
+	ld bc, 1 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	farcall ApplyPals
+	call MG_Mobile_Layout_WipeAttrMap
+	farcall ApplyAttrMap
+	ld hl, .Palette_4973a
+	ld de, wOBPals1
+	ld bc, 1 palettes
+	ld a, BANK(wOBPals1)
+	call FarCopyWRAM
+	ret
+; 49732
+
+.Palette_49732: ; 49732
+	RGB 31, 31, 31
+	RGB 23, 16, 07
+	RGB 23, 07, 07
+	RGB 03, 07, 20
+; 4973a
+
+.Palette_4973a: ; 4973a
+	RGB 00, 00, 00
+	RGB 07, 05, 31
+	RGB 14, 18, 31
+	RGB 31, 31, 31
+; 49742
+
+Function49742: ; 49742
+	ld hl, .Palette_49757
+	ld de, wBGPals1
+	ld bc, 8 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	farcall ApplyPals
+	ret
+; 49757
+
+.Palette_49757: ; 49757
+INCLUDE "gfx/unknown/49757.pal"
+; 49797
+
+_InitMG_Mobile_LinkTradePalMap: ; 49797
+	hlcoord 0, 0, wAttrMap
+	lb bc, 16, 2
+	ld a, $4
+	call MG_Mobile_Layout_FillBox
+	ld a, $3
+	ldcoord_a 0, 1, wAttrMap
+	ldcoord_a 0, 14, wAttrMap
+	hlcoord 2, 0, wAttrMap
+	lb bc, 8, 18
+	ld a, $5
+	call MG_Mobile_Layout_FillBox
+	hlcoord 2, 8, wAttrMap
+	lb bc, 8, 18
+	ld a, $6
+	call MG_Mobile_Layout_FillBox
+	hlcoord 0, 16, wAttrMap
+	lb bc, 2, SCREEN_WIDTH
+	ld a, $4
+	call MG_Mobile_Layout_FillBox
+	ld a, $3
+	lb bc, 6, 1
+	hlcoord 6, 1, wAttrMap
+	call MG_Mobile_Layout_FillBox
+	ld a, $3
+	lb bc, 6, 1
+	hlcoord 17, 1, wAttrMap
+	call MG_Mobile_Layout_FillBox
+	ld a, $3
+	lb bc, 6, 1
+	hlcoord 6, 9, wAttrMap
+	call MG_Mobile_Layout_FillBox
+	ld a, $3
+	lb bc, 6, 1
+	hlcoord 17, 9, wAttrMap
+	call MG_Mobile_Layout_FillBox
+	ld a, $2
+	hlcoord 2, 16, wAttrMap
+	ld [hli], a
+	ld a, $7
+	ld [hli], a
+	ld [hli], a
+	ld [hli], a
+	ld a, $2
+	ld [hl], a
+	hlcoord 2, 17, wAttrMap
+	ld a, $3
+	ld bc, 6
+	call ByteFill
+	ret
+; 49811
+
+LoadTradeRoomBGPals: ; 49811
+	ld hl, TradeRoomPalette
+	ld de, wBGPals1 palette PAL_BG_GREEN
+	ld bc, 6 palettes
+	ld a, BANK(wBGPals1)
+	call FarCopyWRAM
+	farcall ApplyPals
+	ret
+; 49826
+
+TradeRoomPalette: ; 49826
+INCLUDE "gfx/trade/border.pal"
+; 49856
+
+InitMG_Mobile_LinkTradePalMap: ; 49856
+	call _InitMG_Mobile_LinkTradePalMap
+	ret
+; 4985a
+
+; unused
+INCLUDE "gfx/unknown/4985a.asm"
--- /dev/null
+++ b/engine/gfx/evolution_animation.asm
@@ -1,0 +1,368 @@
+EvolutionAnimation: ; 4e5e1
+	push hl
+	push de
+	push bc
+	ld a, [wCurSpecies]
+	push af
+	ld a, [rOBP0]
+	push af
+	ld a, [wBaseDexNo]
+	push af
+
+	call .EvolutionAnimation
+
+	pop af
+	ld [wBaseDexNo], a
+	pop af
+	ld [rOBP0], a
+	pop af
+	ld [wCurSpecies], a
+	pop bc
+	pop de
+	pop hl
+
+	ld a, [wEvolutionCanceled]
+	and a
+	ret z
+
+	scf
+	ret
+; 4e607
+
+.EvolutionAnimation: ; 4e607
+	ld a, %11100100
+	ld [rOBP0], a
+
+	ld de, MUSIC_NONE
+	call PlayMusic
+
+	farcall ClearSpriteAnims
+
+	ld de, .GFX
+	ld hl, vTiles0
+	lb bc, BANK(.GFX), 8
+	call Request2bpp
+
+	xor a
+	ld [wLowHealthAlarm], a
+	call WaitBGMap
+	xor a
+	ld [hBGMapMode], a
+	ld a, [wEvolutionOldSpecies]
+	ld [wPlayerHPPal], a
+
+	ld c, $0
+	call .GetSGBLayout
+	ld a, [wEvolutionOldSpecies]
+	ld [wCurPartySpecies], a
+	ld [wCurSpecies], a
+	call .PlaceFrontpic
+
+	ld de, vTiles2
+	ld hl, vTiles2 tile $31
+	ld bc, 7 * 7
+	call Request2bpp
+
+	ld a, 7 * 7
+	ld [wEvolutionPicOffset], a
+	call .ReplaceFrontpic
+	ld a, [wEvolutionNewSpecies]
+	ld [wCurPartySpecies], a
+	ld [wCurSpecies], a
+	call .LoadFrontpic
+	ld a, [wEvolutionOldSpecies]
+	ld [wCurPartySpecies], a
+	ld [wCurSpecies], a
+
+	ld a, $1
+	ld [hBGMapMode], a
+	call .check_statused
+	jr c, .skip_cry
+
+	ld a, [wEvolutionOldSpecies]
+	call PlayMonCry
+
+.skip_cry
+	ld de, MUSIC_EVOLUTION
+	call PlayMusic
+
+	ld c, 80
+	call DelayFrames
+
+	ld c, $1
+	call .GetSGBLayout
+	call .AnimationSequence
+	jr c, .cancel_evo
+
+	ld a, -7 * 7
+	ld [wEvolutionPicOffset], a
+	call .ReplaceFrontpic
+	xor a
+	ld [wEvolutionCanceled], a
+
+	ld a, [wEvolutionNewSpecies]
+	ld [wPlayerHPPal], a
+
+	ld c, $0
+	call .GetSGBLayout
+	call .PlayEvolvedSFX
+	farcall ClearSpriteAnims
+	call .check_statused
+	jr c, .no_anim
+
+	ld a, [wBoxAlignment]
+	push af
+	ld a, $1
+	ld [wBoxAlignment], a
+	ld a, [wCurPartySpecies]
+	push af
+
+	ld a, [wPlayerHPPal]
+	ld [wCurPartySpecies], a
+	hlcoord 7, 2
+	ld d, $0
+	ld e, ANIM_MON_EVOLVE
+	predef AnimateFrontpic
+
+	pop af
+	ld [wCurPartySpecies], a
+	pop af
+	ld [wBoxAlignment], a
+	ret
+
+.no_anim
+	ret
+
+.cancel_evo
+	ld a, $1
+	ld [wEvolutionCanceled], a
+
+	ld a, [wEvolutionOldSpecies]
+	ld [wPlayerHPPal], a
+
+	ld c, $0
+	call .GetSGBLayout
+	call .PlayEvolvedSFX
+	farcall ClearSpriteAnims
+	call .check_statused
+	ret c
+
+	ld a, [wPlayerHPPal]
+	call PlayMonCry
+	ret
+; 4e703
+
+.GetSGBLayout: ; 4e703
+	ld b, SCGB_EVOLUTION
+	jp GetSGBLayout
+; 4e708
+
+.PlaceFrontpic: ; 4e708
+	call GetBaseData
+	hlcoord 7, 2
+	jp PrepMonFrontpic
+; 4e711
+
+.LoadFrontpic: ; 4e711
+	call GetBaseData
+	ld a, $1
+	ld [wBoxAlignment], a
+	ld de, vTiles2
+	predef GetAnimatedFrontpic
+	xor a
+	ld [wBoxAlignment], a
+	ret
+; 4e726
+
+.AnimationSequence: ; 4e726
+	call ClearJoypad
+	lb bc, 1, 2 * 7 ; flash b times, wait c frames in between
+.loop
+	push bc
+	call .WaitFrames_CheckPressedB
+	pop bc
+	jr c, .exit_sequence
+	push bc
+	call .Flash
+	pop bc
+	inc b
+	dec c
+	dec c
+	jr nz, .loop
+	and a
+	ret
+
+.exit_sequence
+	scf
+	ret
+; 4e741
+
+.Flash: ; 4e741
+	ld a, -7 * 7 ; new stage
+	ld [wEvolutionPicOffset], a
+	call .ReplaceFrontpic
+	ld a, 7 * 7 ; previous stage
+	ld [wEvolutionPicOffset], a
+	call .ReplaceFrontpic
+	dec b
+	jr nz, .Flash
+	ret
+; 4e755
+
+.ReplaceFrontpic: ; 4e755
+	push bc
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 7, 2
+	lb bc, 7, 7
+	ld de, SCREEN_WIDTH - 7
+.loop1
+	push bc
+.loop2
+	ld a, [wEvolutionPicOffset]
+	add [hl]
+	ld [hli], a
+	dec c
+	jr nz, .loop2
+	pop bc
+	add hl, de
+	dec b
+	jr nz, .loop1
+	ld a, $1
+	ld [hBGMapMode], a
+	call WaitBGMap
+	pop bc
+	ret
+; 4e779
+
+.WaitFrames_CheckPressedB: ; 4e779
+	call DelayFrame
+	push bc
+	call JoyTextDelay
+	ld a, [hJoyDown]
+	pop bc
+	and B_BUTTON
+	jr nz, .pressed_b
+.loop3
+	dec c
+	jr nz, .WaitFrames_CheckPressedB
+	and a
+	ret
+
+.pressed_b
+	ld a, [wForceEvolution]
+	and a
+	jr nz, .loop3
+	scf
+	ret
+; 4e794
+
+.check_statused ; 4e794
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1Species
+	call GetPartyLocation
+	ld b, h
+	ld c, l
+	farcall CheckFaintedFrzSlp
+	ret
+; 4e7a6
+
+.PlayEvolvedSFX: ; 4e7a6
+	ld a, [wEvolutionCanceled]
+	and a
+	ret nz
+	ld de, SFX_EVOLVED
+	call PlaySFX
+	ld hl, wJumptableIndex
+	ld a, [hl]
+	push af
+	ld [hl], $0
+.loop4
+	call .balls_of_light
+	jr nc, .done
+	call .AnimateBallsOfLight
+	jr .loop4
+
+.done
+	ld c, 32
+.loop5
+	call .AnimateBallsOfLight
+	dec c
+	jr nz, .loop5
+	pop af
+	ld [wJumptableIndex], a
+	ret
+; 4e7cf
+
+.balls_of_light ; 4e7cf
+	ld hl, wJumptableIndex
+	ld a, [hl]
+	cp 32
+	ret nc
+	ld d, a
+	inc [hl]
+	and $1
+	jr nz, .done_balls
+	ld e, $0
+	call .GenerateBallOfLight
+	ld e, $10
+	call .GenerateBallOfLight
+
+.done_balls
+	scf
+	ret
+; 4e7e8
+
+.GenerateBallOfLight: ; 4e7e8
+	push de
+	depixel 9, 11
+	ld a, SPRITE_ANIM_INDEX_EVOLUTION_BALL_OF_LIGHT
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld a, [wJumptableIndex]
+	and %1110
+	sla a
+	pop de
+	add e
+	ld [hl], a
+	ld hl, SPRITEANIMSTRUCT_TILE_ID
+	add hl, bc
+	ld [hl], $0
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $10
+	ret
+; 4e80c
+
+.AnimateBallsOfLight: ; 4e80c
+	push bc
+	callfar PlaySpriteAnimations
+	; a = (([hVBlankCounter] + 4) / 2) % NUM_PALETTES
+	ld a, [hVBlankCounter]
+	and %1110
+	srl a
+	inc a
+	inc a
+	and $7
+	ld b, a
+	ld hl, wVirtualOAMSprite00Attributes
+	ld c, NUM_SPRITE_OAM_STRUCTS
+.loop6
+	ld a, [hl]
+	or b
+	ld [hli], a ; attributes
+rept SPRITEOAMSTRUCT_LENGTH + -1
+	inc hl
+endr
+	dec c
+	jr nz, .loop6
+	pop bc
+	call DelayFrame
+	ret
+; 4e831
+
+
+.GFX:
+INCBIN "gfx/evo/bubble_large.2bpp"
+INCBIN "gfx/evo/bubble.2bpp"
--- /dev/null
+++ b/engine/gfx/gbc_only.asm
@@ -1,0 +1,149 @@
+GBCOnlyScreen: ; 4ea82
+
+	ld a, [hCGB]
+	and a
+	ret nz
+
+	ld de, MUSIC_NONE
+	call PlayMusic
+
+	call ClearTileMap
+
+	ld hl, GBCOnlyGFX
+	ld de, wGBCOnlyDecompressBuffer
+	ld a, [rSVBK]
+	push af
+	ld a, 0 ; this has the same effect as selecting bank 1
+	ld [rSVBK], a
+	call Decompress
+	pop af
+	ld [rSVBK], a
+
+	ld de, wGBCOnlyDecompressBuffer
+	ld hl, vTiles2
+	lb bc, BANK(GBCOnlyGFX), 84
+	call Get2bpp
+
+	ld de, Font
+	ld hl, vTiles1
+	lb bc, BANK(Font), $80
+	call Get1bpp
+
+	call DrawGBCOnlyScreen
+
+	call WaitBGMap
+
+; better luck next time
+.loop
+	call DelayFrame
+	jr .loop
+; 4eac5
+
+
+DrawGBCOnlyScreen: ; 4eac5
+
+	call DrawGBCOnlyBorder
+
+	; Pokemon
+	hlcoord 3, 2
+	ld b, 14
+	ld c, 4
+	ld a, $8
+	call DrawGBCOnlyGraphic
+
+	; Crystal
+	hlcoord 5, 6
+	ld b, 10
+	ld c, 2
+	ld a, $40
+	call DrawGBCOnlyGraphic
+
+	ld de, GBCOnlyString
+	hlcoord 1, 10
+	call PlaceString
+
+	ret
+; 4eaea
+
+
+DrawGBCOnlyBorder: ; 4eaea
+
+	hlcoord 0, 0
+	ld [hl], 0 ; top-left
+
+	inc hl
+	ld a, 1 ; top
+	call .FillRow
+
+	ld [hl], 2 ; top-right
+
+	hlcoord 0, 1
+	ld a, 3 ; left
+	call .FillColumn
+
+	hlcoord 19, 1
+	ld a, 4 ; right
+	call .FillColumn
+
+	hlcoord 0, 17
+	ld [hl], 5 ; bottom-left
+
+	inc hl
+	ld a, 6 ; bottom
+	call .FillRow
+
+	ld [hl], 7 ; bottom-right
+	ret
+; 4eb15
+
+.FillRow: ; 4eb15
+	ld c, SCREEN_WIDTH - 2
+.next_column
+	ld [hli], a
+	dec c
+	jr nz, .next_column
+	ret
+; 4eb1c
+
+.FillColumn: ; 4eb1c
+	ld de, SCREEN_WIDTH
+	ld c, SCREEN_HEIGHT - 2
+.next_row
+	ld [hl], a
+	add hl, de
+	dec c
+	jr nz, .next_row
+	ret
+; 4eb27
+
+
+DrawGBCOnlyGraphic: ; 4eb27
+	ld de, SCREEN_WIDTH
+.y
+	push bc
+	push hl
+.x
+	ld [hli], a
+	inc a
+	dec b
+	jr nz, .x
+	pop hl
+	add hl, de
+	pop bc
+	dec c
+	jr nz, .y
+	ret
+; 4eb38
+
+
+GBCOnlyString: ; 4eb38
+	db   "This Game Pak is"
+	next "designed only for"
+	next "use on the"
+	next "Game Boy Color.@"
+; 4eb76
+
+
+GBCOnlyGFX: ; 4eb76
+INCBIN "gfx/sgb/gbc_only.2bpp.lz"
+; 4f0bc
--- /dev/null
+++ b/engine/gfx/load_font.asm
@@ -1,0 +1,156 @@
+INCLUDE "gfx/font.asm"
+
+; This and the following two functions are unreferenced.
+; Debug, perhaps?
+Unreferenced_fb434:
+	db 0
+
+Unreferenced_Functionfb435: ; 4b435
+	ld a, [Unreferenced_fb434]
+	and a
+	jp nz, Get1bpp_2
+	jp Get1bpp
+; fb43f
+
+Unreferenced_Functionfb43f: ; fb43f
+	ld a, [Unreferenced_fb434]
+	and a
+	jp nz, Get2bpp_2
+	jp Get2bpp
+; End unreferenced block
+; fb449
+
+_LoadStandardFont:: ; fb449
+	ld de, Font
+	ld hl, vTiles1
+	lb bc, BANK(Font), 128 ; "A" to "9"
+	ld a, [rLCDC]
+	bit rLCDC_ENABLE, a
+	jp z, Copy1bpp
+
+	ld de, Font
+	ld hl, vTiles1
+	lb bc, BANK(Font), 32 ; "A" to "]"
+	call Get1bpp_2
+	ld de, Font + 32 * LEN_1BPP_TILE
+	ld hl, vTiles1 tile $20
+	lb bc, BANK(Font), 32 ; "a" to $bf
+	call Get1bpp_2
+	ld de, Font + 64 * LEN_1BPP_TILE
+	ld hl, vTiles1 tile $40
+	lb bc, BANK(Font), 32 ; "Ä" to "←"
+	call Get1bpp_2
+	ld de, Font + 96 * LEN_1BPP_TILE
+	ld hl, vTiles1 tile $60
+	lb bc, BANK(Font), 32 ; "'" to "9"
+	call Get1bpp_2
+	ret
+; fb48a
+
+_LoadFontsExtra1:: ; fb48a
+	ld de, FontsExtra_SolidBlackGFX
+	ld hl, vTiles2 tile "■" ; $60
+	lb bc, BANK(FontsExtra_SolidBlackGFX), 1
+	call Get1bpp_2
+	ld de, PokegearPhoneIconGFX
+	ld hl, vTiles2 tile "☎" ; $62
+	lb bc, BANK(PokegearPhoneIconGFX), 1
+	call Get2bpp_2
+	ld de, FontExtra + 3 tiles ; "<BOLD_D>"
+	ld hl, vTiles2 tile "<BOLD_D>"
+	lb bc, BANK(FontExtra), 22 ; "<BOLD_D>" to "ぉ"
+	call Get2bpp_2
+	jr LoadFrame
+; fb4b0
+
+_LoadFontsExtra2:: ; fb4b0
+	ld de, FontsExtra2_UpArrowGFX
+	ld hl, vTiles2 tile "▲" ; $61
+	ld b, BANK(FontsExtra2_UpArrowGFX)
+	ld c, 1
+	call Get2bpp_2
+	ret
+; fb4be
+
+_LoadFontsBattleExtra:: ; fb4be
+	ld de, FontBattleExtra
+	ld hl, vTiles2 tile $60
+	lb bc, BANK(FontBattleExtra), 25
+	call Get2bpp_2
+	jr LoadFrame
+; fb4cc
+
+LoadFrame: ; fb4cc
+	ld a, [wTextBoxFrame]
+	maskbits NUM_FRAMES
+	ld bc, 6 * LEN_1BPP_TILE
+	ld hl, Frames
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld hl, vTiles2 tile "┌" ; $79
+	lb bc, BANK(Frames), 6 ; "┌" to "┘"
+	call Get1bpp_2
+	ld hl, vTiles2 tile " " ; $7f
+	ld de, TextBoxSpaceGFX
+	lb bc, BANK(TextBoxSpaceGFX), 1
+	call Get1bpp_2
+	ret
+; fb4f2
+
+LoadBattleFontsHPBar: ; fb4f2
+	ld de, FontBattleExtra
+	ld hl, vTiles2 tile $60
+	lb bc, BANK(FontBattleExtra), 12
+	call Get2bpp_2
+	ld hl, vTiles2 tile $70
+	ld de, FontBattleExtra + 16 tiles ; "<DO>"
+	lb bc, BANK(FontBattleExtra), 3 ; "<DO>" to "『"
+	call Get2bpp_2
+	call LoadFrame
+
+LoadHPBar: ; fb50d
+	ld de, EnemyHPBarBorderGFX
+	ld hl, vTiles2 tile $6c
+	lb bc, BANK(EnemyHPBarBorderGFX), 4
+	call Get1bpp_2
+	ld de, HPExpBarBorderGFX
+	ld hl, vTiles2 tile $73
+	lb bc, BANK(HPExpBarBorderGFX), 6
+	call Get1bpp_2
+	ld de, ExpBarGFX
+	ld hl, vTiles2 tile $55
+	lb bc, BANK(ExpBarGFX), 9
+	call Get2bpp_2
+	ld de, MobilePhoneTilesGFX + 7 tiles ; mobile phone icon
+	ld hl, vTiles2 tile $5e
+	lb bc, BANK(MobilePhoneTilesGFX), 2
+	call Get2bpp_2
+	ret
+; fb53e
+
+StatsScreen_LoadFont: ; fb53e
+	call _LoadFontsBattleExtra
+	ld de, EnemyHPBarBorderGFX
+	ld hl, vTiles2 tile $6c
+	lb bc, BANK(EnemyHPBarBorderGFX), 4
+	call Get1bpp_2
+	ld de, HPExpBarBorderGFX
+	ld hl, vTiles2 tile $78
+	lb bc, BANK(HPExpBarBorderGFX), 1
+	call Get1bpp_2
+	ld de, HPExpBarBorderGFX + 3 * LEN_1BPP_TILE
+	ld hl, vTiles2 tile $76
+	lb bc, BANK(HPExpBarBorderGFX), 2
+	call Get1bpp_2
+	ld de, ExpBarGFX
+	ld hl, vTiles2 tile $55
+	lb bc, BANK(ExpBarGFX), 8
+	call Get2bpp_2
+LoadStatsScreenPageTilesGFX: ; fb571
+	ld de, StatsScreenPageTilesGFX
+	ld hl, vTiles2 tile $31
+	lb bc, BANK(StatsScreenPageTilesGFX), 17
+	call Get2bpp_2
+	ret
+; fb57e
--- /dev/null
+++ b/engine/gfx/load_pics.asm
@@ -1,0 +1,491 @@
+GetUnownLetter: ; 51040
+; Return Unown letter in wUnownLetter based on DVs at hl
+
+; Take the middle 2 bits of each DV and place them in order:
+;	atk  def  spd  spc
+;	.ww..xx.  .yy..zz.
+
+	; atk
+	ld a, [hl]
+	and %01100000
+	sla a
+	ld b, a
+	; def
+	ld a, [hli]
+	and %00000110
+	swap a
+	srl a
+	or b
+	ld b, a
+
+	; spd
+	ld a, [hl]
+	and %01100000
+	swap a
+	sla a
+	or b
+	ld b, a
+	; spc
+	ld a, [hl]
+	and %00000110
+	srl a
+	or b
+
+; Divide by 10 to get 0-25
+	ld [hDividend + 3], a
+	xor a
+	ld [hDividend], a
+	ld [hDividend + 1], a
+	ld [hDividend + 2], a
+	ld a, $ff / NUM_UNOWN + 1
+	ld [hDivisor], a
+	ld b, 4
+	call Divide
+
+; Increment to get 1-26
+	ld a, [hQuotient + 2]
+	inc a
+	ld [wUnownLetter], a
+	ret
+
+GetMonFrontpic: ; 51077
+	ld a, [wCurPartySpecies]
+	ld [wCurSpecies], a
+	call IsAPokemon
+	ret c
+	ld a, [rSVBK]
+	push af
+	call _GetFrontpic
+	pop af
+	ld [rSVBK], a
+	ret
+
+GetAnimatedFrontpic: ; 5108b
+	ld a, [wCurPartySpecies]
+	ld [wCurSpecies], a
+	call IsAPokemon
+	ret c
+	ld a, [rSVBK]
+	push af
+	xor a
+	ld [hBGMapMode], a
+	call _GetFrontpic
+	call GetAnimatedEnemyFrontpic
+	pop af
+	ld [rSVBK], a
+	ret
+
+_GetFrontpic: ; 510a5
+	push de
+	call GetBaseData
+	ld a, [wBasePicSize]
+	and $f
+	ld b, a
+	push bc
+	call GetFrontpicPointer
+	ld a, BANK(wDecompressEnemyFrontpic)
+	ld [rSVBK], a
+	ld a, b
+	ld de, wDecompressEnemyFrontpic
+	call FarDecompress
+	pop bc
+	ld hl, wDecompressScratch
+	ld de, wDecompressEnemyFrontpic
+	call PadFrontpic
+	pop hl
+	push hl
+	ld de, wDecompressScratch
+	ld c, 7 * 7
+	ld a, [hROMBank]
+	ld b, a
+	call Get2bpp
+	pop hl
+	ret
+
+GetFrontpicPointer: ; 510d7
+	ld a, [wCurPartySpecies]
+	cp UNOWN
+	jr z, .unown
+	ld a, [wCurPartySpecies]
+	ld d, BANK(PokemonPicPointers)
+	jr .ok
+
+.unown
+	ld a, [wUnownLetter]
+	ld d, BANK(UnownPicPointers)
+
+.ok
+	ld hl, PokemonPicPointers ; UnownPicPointers
+	dec a
+	ld bc, 6
+	call AddNTimes
+	ld a, d
+	call GetFarByte
+	call FixPicBank
+	push af
+	inc hl
+	ld a, d
+	call GetFarHalfword
+	pop bc
+	ret
+
+GetAnimatedEnemyFrontpic: ; 51103
+	ld a, BANK(vTiles3)
+	ld [rVBK], a
+	push hl
+	ld de, wDecompressScratch
+	ld c, 7 * 7
+	ld a, [hROMBank]
+	ld b, a
+	call Get2bpp
+	pop hl
+	ld de, 7 * 7 tiles
+	add hl, de
+	push hl
+	ld a, BANK(wBasePicSize)
+	ld hl, wBasePicSize
+	call GetFarWRAMByte
+	pop hl
+	and $f
+	ld de, wDecompressEnemyFrontpic + 5 * 5 tiles
+	ld c, 5 * 5
+	cp 5
+	jr z, .got_dims
+	ld de, wDecompressEnemyFrontpic + 6 * 6 tiles
+	ld c, 6 * 6
+	cp 6
+	jr z, .got_dims
+	ld de, wDecompressEnemyFrontpic + 7 * 7 tiles
+	ld c, 7 * 7
+.got_dims
+
+	push hl
+	push bc
+	call LoadFrontpicTiles
+	pop bc
+	pop hl
+	ld de, wDecompressScratch
+	ld a, [hROMBank]
+	ld b, a
+	call Get2bpp
+	xor a
+	ld [rVBK], a
+	ret
+
+LoadFrontpicTiles: ; 5114f
+	ld hl, wDecompressScratch
+	swap c
+	ld a, c
+	and $f
+	ld b, a
+	ld a, c
+	and $f0
+	ld c, a
+	push bc
+	call LoadOrientedFrontpic
+	pop bc
+.loop
+	push bc
+	ld c, 0
+	call LoadOrientedFrontpic
+	pop bc
+	dec b
+	jr nz, .loop
+	ret
+
+GetMonBackpic: ; 5116c
+	ld a, [wCurPartySpecies]
+	call IsAPokemon
+	ret c
+
+	ld a, [wCurPartySpecies]
+	ld b, a
+	ld a, [wUnownLetter]
+	ld c, a
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wDecompressScratch)
+	ld [rSVBK], a
+	push de
+
+	; These are assumed to be at the same address in their respective banks.
+	ld hl, PokemonPicPointers ; UnownPicPointers
+	ld a, b
+	ld d, BANK(PokemonPicPointers)
+	cp UNOWN
+	jr nz, .ok
+	ld a, c
+	ld d, BANK(UnownPicPointers)
+.ok
+	dec a
+	ld bc, 6
+	call AddNTimes
+	ld bc, 3
+	add hl, bc
+	ld a, d
+	call GetFarByte
+	call FixPicBank
+	push af
+	inc hl
+	ld a, d
+	call GetFarHalfword
+	ld de, wDecompressScratch
+	pop af
+	call FarDecompress
+	ld hl, wDecompressScratch
+	ld c, 6 * 6
+	call FixBackpicAlignment
+	pop hl
+	ld de, wDecompressScratch
+	ld a, [hROMBank]
+	ld b, a
+	call Get2bpp
+	pop af
+	ld [rSVBK], a
+	ret
+
+FixPicBank: ; 511c5
+; This is a thing for some reason.
+
+PICS_FIX EQU $36
+GLOBAL PICS_FIX
+
+	push hl
+	push bc
+	sub BANK(Pics_1) - PICS_FIX
+	ld c, a
+	ld b, 0
+	ld hl, .PicsBanks
+	add hl, bc
+	ld a, [hl]
+	pop bc
+	pop hl
+	ret
+
+.PicsBanks: ; 511d4
+	db BANK(Pics_1) + 0
+	db BANK(Pics_1) + 1
+	db BANK(Pics_1) + 2
+	db BANK(Pics_1) + 3
+	db BANK(Pics_1) + 4
+	db BANK(Pics_1) + 5
+	db BANK(Pics_1) + 6
+	db BANK(Pics_1) + 7
+	db BANK(Pics_1) + 8
+	db BANK(Pics_1) + 9
+	db BANK(Pics_1) + 10
+	db BANK(Pics_1) + 11
+	db BANK(Pics_1) + 12
+	db BANK(Pics_1) + 13
+	db BANK(Pics_1) + 14
+	db BANK(Pics_1) + 15
+	db BANK(Pics_1) + 16
+	db BANK(Pics_1) + 17
+	db BANK(Pics_1) + 18
+	db BANK(Pics_1) + 19
+	db BANK(Pics_1) + 20
+	db BANK(Pics_1) + 21
+	db BANK(Pics_1) + 22
+	db BANK(Pics_1) + 23
+
+Function511ec: ; 511ec
+	ld a, c
+	push de
+	ld hl, PokemonPicPointers
+	dec a
+	ld bc, 6
+	call AddNTimes
+	ld a, BANK(PokemonPicPointers)
+	call GetFarByte
+	call FixPicBank
+	push af
+	inc hl
+	ld a, BANK(PokemonPicPointers)
+	call GetFarHalfword
+	pop af
+	pop de
+	call FarDecompress
+	ret
+
+GetTrainerPic: ; 5120d
+	ld a, [wTrainerClass]
+	and a
+	ret z
+	cp NUM_TRAINER_CLASSES
+	ret nc
+	call WaitBGMap
+	xor a
+	ld [hBGMapMode], a
+	ld hl, TrainerPicPointers
+	ld a, [wTrainerClass]
+	dec a
+	ld bc, 3
+	call AddNTimes
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wDecompressScratch)
+	ld [rSVBK], a
+	push de
+	ld a, BANK(TrainerPicPointers)
+	call GetFarByte
+	call FixPicBank
+	push af
+	inc hl
+	ld a, BANK(TrainerPicPointers)
+	call GetFarHalfword
+	pop af
+	ld de, wDecompressScratch
+	call FarDecompress
+	pop hl
+	ld de, wDecompressScratch
+	ld c, 7 * 7
+	ld a, [hROMBank]
+	ld b, a
+	call Get2bpp
+	pop af
+	ld [rSVBK], a
+	call WaitBGMap
+	ld a, $1
+	ld [hBGMapMode], a
+	ret
+
+DecompressGet2bpp: ; 5125d
+; Decompress lz data from b:hl to scratch space at 6:d000, then copy it to address de.
+
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wDecompressScratch)
+	ld [rSVBK], a
+
+	push de
+	push bc
+	ld a, b
+	ld de, wDecompressScratch
+	call FarDecompress
+	pop bc
+	ld de, wDecompressScratch
+	pop hl
+	ld a, [hROMBank]
+	ld b, a
+	call Get2bpp
+
+	pop af
+	ld [rSVBK], a
+	ret
+
+FixBackpicAlignment: ; 5127c
+	push de
+	push bc
+	ld a, [wBoxAlignment]
+	and a
+	jr z, .keep_dims
+	ld a, c
+	cp 7 * 7
+	ld de, 7 * 7 tiles
+	jr z, .got_dims
+	cp 6 * 6
+	ld de, 6 * 6 tiles
+	jr z, .got_dims
+	ld de, 5 * 5 tiles
+
+.got_dims
+	ld a, [hl]
+	ld b, 0
+	ld c, 8
+.loop
+	rra
+	rl b
+	dec c
+	jr nz, .loop
+	ld a, b
+	ld [hli], a
+	dec de
+	ld a, e
+	or d
+	jr nz, .got_dims
+
+.keep_dims
+	pop bc
+	pop de
+	ret
+
+PadFrontpic: ; 512ab
+; pads frontpic to fill 7x7 box
+	ld a, b
+	cp 6
+	jr z, .six
+	cp 5
+	jr z, .five
+
+.seven_loop
+	ld c, $70
+	call LoadOrientedFrontpic
+	dec b
+	jr nz, .seven_loop
+	ret
+
+.six
+	ld c, $70
+	xor a
+	call .Fill
+.six_loop
+	ld c, $10
+	xor a
+	call .Fill
+	ld c, $60
+	call LoadOrientedFrontpic
+	dec b
+	jr nz, .six_loop
+	ret
+
+.five
+	ld c, $70
+	xor a
+	call .Fill
+.five_loop
+	ld c, $20
+	xor a
+	call .Fill
+	ld c, $50
+	call LoadOrientedFrontpic
+	dec b
+	jr nz, .five_loop
+	ld c, $70
+	xor a
+	call .Fill
+	ret
+
+.Fill:
+	ld [hli], a
+	dec c
+	jr nz, .Fill
+	ret
+
+LoadOrientedFrontpic: ; 512f2
+	ld a, [wBoxAlignment]
+	and a
+	jr nz, .x_flip
+.left_loop
+	ld a, [de]
+	inc de
+	ld [hli], a
+	dec c
+	jr nz, .left_loop
+	ret
+
+.x_flip
+	push bc
+.right_loop
+	ld a, [de]
+	inc de
+	ld b, a
+	xor a
+rept 8
+	rr b
+	rla
+endr
+	ld [hli], a
+	dec c
+	jr nz, .right_loop
+	pop bc
+	ret
--- /dev/null
+++ b/engine/gfx/map_palettes.asm
@@ -1,0 +1,86 @@
+SwapTextboxPalettes:: ; 4c000
+	hlcoord 0, 0
+	decoord 0, 0, wAttrMap
+	ld b, SCREEN_HEIGHT
+.loop
+	push bc
+	ld c, SCREEN_WIDTH
+.innerloop
+	ld a, [hl]
+	push hl
+	srl a
+	jr c, .UpperNybble
+	ld hl, wTilesetPalettes
+	add [hl]
+	ld l, a
+	ld a, [wTilesetPalettes + 1]
+	adc 0
+	ld h, a
+	ld a, [hl]
+	and $f
+	jr .next
+
+.UpperNybble:
+	ld hl, wTilesetPalettes
+	add [hl]
+	ld l, a
+	ld a, [wTilesetPalettes + 1]
+	adc 0
+	ld h, a
+	ld a, [hl]
+	swap a
+	and $f
+
+.next
+	pop hl
+	ld [de], a
+	res 7, [hl]
+	inc hl
+	inc de
+	dec c
+	jr nz, .innerloop
+	pop bc
+	dec b
+	jr nz, .loop
+	ret
+
+ScrollBGMapPalettes:: ; 4c03f
+	ld hl, wBGMapBuffer
+	ld de, wBGMapPalBuffer
+.loop
+	ld a, [hl]
+	push hl
+	srl a
+	jr c, .UpperNybble
+
+; .LowerNybble
+	ld hl, wTilesetPalettes
+	add [hl]
+	ld l, a
+	ld a, [wTilesetPalettes + 1]
+	adc 0
+	ld h, a
+	ld a, [hl]
+	and $f
+	jr .next
+
+.UpperNybble:
+	ld hl, wTilesetPalettes
+	add [hl]
+	ld l, a
+	ld a, [wTilesetPalettes + 1]
+	adc 0
+	ld h, a
+	ld a, [hl]
+	swap a
+	and $f
+
+.next
+	pop hl
+	ld [de], a
+	res 7, [hl]
+	inc hl
+	inc de
+	dec c
+	jr nz, .loop
+	ret
--- /dev/null
+++ b/engine/gfx/mapgroup_roofs.asm
@@ -1,0 +1,20 @@
+LoadMapGroupRoof:: ; 1c000
+	ld a, [wMapGroup]
+	ld e, a
+	ld d, 0
+	ld hl, MapGroupRoofs
+	add hl, de
+	ld a, [hl]
+	cp -1
+	ret z
+	ld hl, Roofs
+	ld bc, 9 tiles
+	call AddNTimes
+	ld de, vTiles2 tile $0a
+	ld bc, 9 tiles
+	call CopyBytes
+	ret
+; 1c021
+
+
+INCLUDE "data/maps/roofs.asm"
--- /dev/null
+++ b/engine/gfx/mon_icons.asm
@@ -1,0 +1,471 @@
+LoadOverworldMonIcon: ; 8e82b
+	ld a, e
+	call ReadMonMenuIcon
+	ld l, a
+	ld h, 0
+	add hl, hl
+	ld de, IconPointers
+	add hl, de
+	ld a, [hli]
+	ld e, a
+	ld d, [hl]
+	ld b, BANK(Icons)
+	ld c, 8
+	ret
+; 8e83f
+
+LoadMenuMonIcon: ; 8e83f
+	push hl
+	push de
+	push bc
+	call .LoadIcon
+	pop bc
+	pop de
+	pop hl
+	ret
+; 8e849
+
+.LoadIcon: ; 8e849
+	ld d, 0
+	ld hl, .Jumptable
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+; 8e854
+
+
+.Jumptable: ; 8e854 (23:6854)
+	dw PartyMenu_InitAnimatedMonIcon ; party menu
+	dw NamingScreen_InitAnimatedMonIcon ; naming screen
+	dw MoveList_InitAnimatedMonIcon ; moves (?)
+	dw Trade_LoadMonIconGFX ; trade
+	dw Mobile_InitAnimatedMonIcon ; mobile
+	dw Mobile_InitPartyMenuBGPal71 ; mobile
+	dw .GetPartyMenuMonIcon ; unused
+
+.GetPartyMenuMonIcon: ; 8e862 (23:6862)
+	call InitPartyMenuIcon
+	call .GetPartyMonItemGFX
+	call SetPartyMonIconAnimSpeed
+	ret
+
+.GetPartyMonItemGFX: ; 8e86c (23:686c)
+	push bc
+	ld a, [hObjectStructIndexBuffer]
+	ld hl, wPartyMon1Item
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	pop bc
+	ld a, [hl]
+	and a
+	jr z, .no_item
+	push hl
+	push bc
+	ld d, a
+	callfar ItemIsMail
+	pop bc
+	pop hl
+	jr c, .not_mail
+	ld a, $6
+	jr .got_tile
+.not_mail
+	ld a, $5
+	; jr .got_tile
+
+.no_item
+	ld a, $4
+.got_tile
+	ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+	add hl, bc
+	ld [hl], a
+	ret
+
+Mobile_InitAnimatedMonIcon: ; 8e898 (23:6898)
+	call PartyMenu_InitAnimatedMonIcon
+	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+	add hl, bc
+	ld a, SPRITE_ANIM_SEQ_NULL
+	ld [hl], a
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld a, 9 * 8
+	ld [hl], a
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	ld a, 9 * 8
+	ld [hl], a
+	ret
+
+Mobile_InitPartyMenuBGPal71: ; 8e8b1 (23:68b1)
+	call InitPartyMenuIcon
+	call SetPartyMonIconAnimSpeed
+	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+	add hl, bc
+	ld a, SPRITE_ANIM_SEQ_NULL
+	ld [hl], a
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld a, 3 * 8
+	ld [hl], a
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	ld a, 12 * 8
+	ld [hl], a
+	ld a, c
+	ld [wc608], a
+	ld a, b
+	ld [wc608 + 1], a
+	ret
+
+PartyMenu_InitAnimatedMonIcon: ; 8e8d5 (23:68d5)
+	call InitPartyMenuIcon
+	call .SpawnItemIcon
+	call SetPartyMonIconAnimSpeed
+	ret
+
+.SpawnItemIcon: ; 8e8df (23:68df)
+	push bc
+	ld a, [hObjectStructIndexBuffer]
+	ld hl, wPartyMon1Item
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	pop bc
+	ld a, [hl]
+	and a
+	ret z
+	push hl
+	push bc
+	ld d, a
+	callfar ItemIsMail
+	pop bc
+	pop hl
+	jr c, .mail
+	ld a, SPRITE_ANIM_FRAMESET_PARTY_MON_WITH_ITEM
+	jr .okay
+
+.mail
+	ld a, SPRITE_ANIM_FRAMESET_PARTY_MON_WITH_MAIL
+.okay
+	ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+	add hl, bc
+	ld [hl], a
+	ret
+
+InitPartyMenuIcon: ; 8e908 (23:6908)
+	ld a, [wCurIconTile]
+	push af
+	ld a, [hObjectStructIndexBuffer]
+	ld hl, wPartySpecies
+	ld e, a
+	ld d, $0
+	add hl, de
+	ld a, [hl]
+	call ReadMonMenuIcon
+	ld [wCurIcon], a
+	call GetMemIconGFX
+	ld a, [hObjectStructIndexBuffer]
+; y coord
+	add a
+	add a
+	add a
+	add a
+	add $1c
+	ld d, a
+; x coord
+	ld e, $10
+; type is partymon icon
+	ld a, SPRITE_ANIM_INDEX_PARTY_MON
+	call InitSpriteAnimStruct
+	pop af
+	ld hl, SPRITEANIMSTRUCT_TILE_ID
+	add hl, bc
+	ld [hl], a
+	ret
+
+SetPartyMonIconAnimSpeed: ; 8e936 (23:6936)
+	push bc
+	ld a, [hObjectStructIndexBuffer]
+	ld b, a
+	call .getspeed
+	ld a, b
+	pop bc
+	ld hl, SPRITEANIMSTRUCT_DURATIONOFFSET
+	add hl, bc
+	ld [hl], a
+	rlca
+	rlca
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld [hl], a
+	ret
+
+.getspeed ; 8e94c (23:694c)
+	farcall PlacePartymonHPBar
+	call GetHPPal
+	ld e, d
+	ld d, 0
+	ld hl, .speeds
+	add hl, de
+	ld b, [hl]
+	ret
+; 8e95e (23:695e)
+
+.speeds ; 8e95e
+	db $00 ; HP_GREEN
+	db $40 ; HP_YELLOW
+	db $80 ; HP_RED
+; 8e961
+
+NamingScreen_InitAnimatedMonIcon: ; 8e961 (23:6961)
+	ld a, [wd265]
+	call ReadMonMenuIcon
+	ld [wCurIcon], a
+	xor a
+	call GetIconGFX
+	depixel 4, 4, 4, 0
+	ld a, SPRITE_ANIM_INDEX_PARTY_MON
+	call InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+	add hl, bc
+	ld [hl], SPRITE_ANIM_SEQ_NULL
+	ret
+
+MoveList_InitAnimatedMonIcon: ; 8e97d (23:697d)
+	ld a, [wd265]
+	call ReadMonMenuIcon
+	ld [wCurIcon], a
+	xor a
+	call GetIconGFX
+	ld d, 3 * 8 + 2 ; depixel 3, 4, 2, 4
+	ld e, 4 * 8 + 4
+	ld a, SPRITE_ANIM_INDEX_PARTY_MON
+	call InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+	add hl, bc
+	ld [hl], SPRITE_ANIM_SEQ_NULL
+	ret
+
+Trade_LoadMonIconGFX: ; 8e99a (23:699a)
+	ld a, [wd265]
+	call ReadMonMenuIcon
+	ld [wCurIcon], a
+	ld a, $62
+	ld [wCurIconTile], a
+	call GetMemIconGFX
+	ret
+
+GetSpeciesIcon: ; 8e9ac
+; Load species icon into VRAM at tile a
+	push de
+	ld a, [wd265]
+	call ReadMonMenuIcon
+	ld [wCurIcon], a
+	pop de
+	ld a, e
+	call GetIconGFX
+	ret
+; 8e9bc
+
+
+FlyFunction_GetMonIcon: ; 8e9bc (23:69bc)
+	push de
+	ld a, [wd265]
+	call ReadMonMenuIcon
+	ld [wCurIcon], a
+	pop de
+	ld a, e
+	call GetIcon_a
+	ret
+; 8e9cc (23:69cc)
+
+Unreferenced_GetMonIcon2: ; 8e9cc
+	push de
+	ld a, [wd265]
+	call ReadMonMenuIcon
+	ld [wCurIcon], a
+	pop de
+	call GetIcon_de
+	ret
+; 8e9db
+
+GetMemIconGFX: ; 8e9db (23:69db)
+	ld a, [wCurIconTile]
+GetIconGFX: ; 8e9de
+	call GetIcon_a
+	ld de, 8 tiles
+	add hl, de
+	ld de, HeldItemIcons
+	lb bc, BANK(HeldItemIcons), 2
+	call GetGFXUnlessMobile
+	ld a, [wCurIconTile]
+	add 10
+	ld [wCurIconTile], a
+	ret
+
+HeldItemIcons:
+INCBIN "gfx/icons/mail.2bpp"
+INCBIN "gfx/icons/item.2bpp"
+; 8ea17
+
+GetIcon_de: ; 8ea17
+; Load icon graphics into VRAM starting from tile de.
+	ld l, e
+	ld h, d
+	jr GetIcon
+
+GetIcon_a: ; 8ea1b
+; Load icon graphics into VRAM starting from tile a.
+	ld l, a
+	ld h, 0
+
+GetIcon: ; 8ea1e
+; Load icon graphics into VRAM starting from tile hl.
+
+; One tile is 16 bytes long.
+rept 4
+	add hl, hl
+endr
+
+	ld de, vTiles0
+	add hl, de
+	push hl
+
+; The icons are contiguous, in order and of the same
+; size, so the pointer table is somewhat redundant.
+	ld a, [wCurIcon]
+	push hl
+	ld l, a
+	ld h, 0
+	add hl, hl
+	ld de, IconPointers
+	add hl, de
+	ld a, [hli]
+	ld e, a
+	ld d, [hl]
+	pop hl
+
+	lb bc, BANK(Icons), 8
+	call GetGFXUnlessMobile
+
+	pop hl
+	ret
+; 8ea3f
+
+GetGFXUnlessMobile: ; 8ea3f
+	ld a, [wLinkMode]
+	cp LINK_MOBILE
+	jp nz, Request2bpp
+	jp Get2bpp_2
+; 8ea4a
+
+FreezeMonIcons: ; 8ea4a
+	ld hl, wSpriteAnimationStructs
+	ld e, PARTY_LENGTH
+	ld a, [wMenuCursorY]
+	ld d, a
+.loop
+	ld a, [hl]
+	and a
+	jr z, .next
+	cp d
+	jr z, .loadwithtwo
+	ld a, SPRITE_ANIM_SEQ_NULL
+	jr .ok
+
+.loadwithtwo
+	ld a, SPRITE_ANIM_SEQ_PARTY_MON_SWITCH
+
+.ok
+	push hl
+	ld c, l
+	ld b, h
+	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+	add hl, bc
+	ld [hl], a
+	pop hl
+
+.next
+	ld bc, $10
+	add hl, bc
+	dec e
+	jr nz, .loop
+	ret
+; 8ea71
+
+UnfreezeMonIcons: ; 8ea71
+	ld hl, wSpriteAnimationStructs
+	ld e, PARTY_LENGTH
+.loop
+	ld a, [hl]
+	and a
+	jr z, .next
+	push hl
+	ld c, l
+	ld b, h
+	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+	add hl, bc
+	ld [hl], SPRITE_ANIM_SEQ_PARTY_MON
+	pop hl
+.next
+	ld bc, $10
+	add hl, bc
+	dec e
+	jr nz, .loop
+	ret
+; 8ea8c (23:6a8c)
+
+HoldSwitchmonIcon: ; 8ea8c
+	ld hl, wSpriteAnimationStructs
+	ld e, PARTY_LENGTH
+	ld a, [wSwitchMon]
+	ld d, a
+.loop
+	ld a, [hl]
+	and a
+	jr z, .next
+	cp d
+	jr z, .is_switchmon
+	ld a, SPRITE_ANIM_SEQ_PARTY_MON_SELECTED
+	jr .join_back
+
+.is_switchmon
+	ld a, SPRITE_ANIM_SEQ_PARTY_MON_SWITCH
+.join_back
+	push hl
+	ld c, l
+	ld b, h
+	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+	add hl, bc
+	ld [hl], a
+	pop hl
+.next
+	ld bc, $10
+	add hl, bc
+	dec e
+	jr nz, .loop
+	ret
+
+ReadMonMenuIcon: ; 8eab3
+	cp EGG
+	jr z, .egg
+	dec a
+	ld hl, MonMenuIcons
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld a, [hl]
+	ret
+.egg
+	ld a, ICON_EGG
+	ret
+; 8eac4
+
+
+INCLUDE "data/pokemon/menu_icons.asm"
+
+INCLUDE "data/icon_pointers.asm"
+
+INCLUDE "gfx/icons.asm"
--- /dev/null
+++ b/engine/gfx/pic_animation.asm
@@ -1,0 +1,1141 @@
+; Pic animation arrangement.
+
+Unused_AnimateMon_Slow_Normal: ; d0000
+	hlcoord 12, 0
+	ld a, [wBattleMode]
+	cp WILD_BATTLE
+	jr z, .wild
+	ld e, ANIM_MON_SLOW
+	ld d, $0
+	call AnimateFrontpic
+	ret
+
+.wild
+	ld e, ANIM_MON_NORMAL
+	ld d, $0
+	call AnimateFrontpic
+	ret
+; d001a
+
+AnimateMon_Menu: ; d001a
+	ld e, ANIM_MON_MENU
+	ld d, $0
+	call AnimateFrontpic
+	ret
+; d0022
+
+AnimateMon_Trade: ; d0022
+	ld e, ANIM_MON_TRADE
+	ld d, $0
+	call AnimateFrontpic
+	ret
+; d002a
+
+AnimateMon_Evolve: ; d002a
+	ld e, ANIM_MON_EVOLVE
+	ld d, $0
+	call AnimateFrontpic
+	ret
+; d0032
+
+AnimateMon_Hatch: ; d0032
+	ld e, ANIM_MON_HATCH
+	ld d, $0
+	call AnimateFrontpic
+	ret
+; d003a
+
+AnimateMon_Unused: ; d003a
+	ld e, ANIM_MON_UNUSED
+	ld d, $0
+	call AnimateFrontpic
+	ret
+; d0042
+
+pokeanim: MACRO
+	rept _NARG
+; Workaround for a bug where macro args can't come after the start of a symbol
+if !DEF(\1_POKEANIM)
+\1_POKEANIM EQUS "PokeAnim_\1_"
+endc
+	db (\1_POKEANIM - PokeAnim_SetupCommands) / 2
+	shift
+	endr
+	db (PokeAnim_Finish_ - PokeAnim_SetupCommands) / 2
+ENDM
+
+PokeAnims: ; d0042
+	dw .Slow
+	dw .Normal
+	dw .Menu
+	dw .Trade
+	dw .Evolve
+	dw .Hatch
+	dw .Unused ; same as .Menu
+	dw .Egg1
+	dw .Egg2
+
+.Slow:   pokeanim StereoCry, Setup2, Play
+.Normal: pokeanim StereoCry, Setup, Play
+.Menu:   pokeanim CryNoWait, Setup, Play, SetWait, Wait, Idle, Play
+.Trade:  pokeanim Idle, Play2, Idle, Play, SetWait, Wait, Cry, Setup, Play
+.Evolve: pokeanim Idle, Play, SetWait, Wait, CryNoWait, Setup, Play
+.Hatch:  pokeanim Idle, Play, CryNoWait, Setup, Play, SetWait, Wait, Idle, Play
+.Unused: pokeanim CryNoWait, Setup, Play, SetWait, Wait, Idle, Play
+.Egg1:   pokeanim Setup, Play
+.Egg2:   pokeanim Idle, Play
+
+
+AnimateFrontpic: ; d008e
+	call AnimateMon_CheckIfPokemon
+	ret c
+	call LoadMonAnimation
+.loop
+	call SetUpPokeAnim
+	push af
+	farcall HDMATransferTileMapToWRAMBank3
+	pop af
+	jr nc, .loop
+	ret
+; d00a3
+
+LoadMonAnimation: ; d00a3
+	push hl
+	ld c, e
+	ld b, 0
+	ld hl, PokeAnims
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld b, [hl]
+	ld c, a
+	pop hl
+	call PokeAnim_InitPicAttributes
+	ret
+; d00b4
+
+SetUpPokeAnim: ; d00b4
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wPokeAnimSceneIndex)
+	ld [rSVBK], a
+	ld a, [wPokeAnimSceneIndex]
+	ld c, a
+	ld b, 0
+	ld hl, wPokeAnimPointer
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	add hl, bc
+	ld a, [hl]
+	ld hl, PokeAnim_SetupCommands
+	rst JumpTable
+	ld a, [wPokeAnimSceneIndex]
+	ld c, a
+	pop af
+	ld [rSVBK], a
+	ld a, c
+	and $80
+	ret z
+	scf
+	ret
+; d00da
+
+PokeAnim_SetupCommands: ; d00da
+setup_command: MACRO
+\1_: dw \1
+ENDM
+	setup_command PokeAnim_Finish
+	setup_command PokeAnim_BasePic
+	setup_command PokeAnim_SetWait
+	setup_command PokeAnim_Wait
+	setup_command PokeAnim_Setup
+	setup_command PokeAnim_Setup2
+	setup_command PokeAnim_Idle
+	setup_command PokeAnim_Play
+	setup_command PokeAnim_Play2
+	setup_command PokeAnim_Cry
+	setup_command PokeAnim_CryNoWait
+	setup_command PokeAnim_StereoCry
+; d00f2
+
+PokeAnim_SetWait: ; d00f2
+	ld a, 18
+	ld [wPokeAnimWaitCounter], a
+	ld a, [wPokeAnimSceneIndex]
+	inc a
+	ld [wPokeAnimSceneIndex], a
+
+PokeAnim_Wait: ; d00fe
+	ld hl, wPokeAnimWaitCounter
+	dec [hl]
+	ret nz
+	ld a, [wPokeAnimSceneIndex]
+	inc a
+	ld [wPokeAnimSceneIndex], a
+	ret
+; d010b
+
+PokeAnim_Setup: ; d010b
+	ld c, FALSE
+	ld b, 0
+	call PokeAnim_InitAnim
+	call PokeAnim_SetVBank1
+	ld a, [wPokeAnimSceneIndex]
+	inc a
+	ld [wPokeAnimSceneIndex], a
+	ret
+; d011d
+
+PokeAnim_Setup2: ; d011d
+	ld c, FALSE
+	ld b, 4
+	call PokeAnim_InitAnim
+	call PokeAnim_SetVBank1
+	ld a, [wPokeAnimSceneIndex]
+	inc a
+	ld [wPokeAnimSceneIndex], a
+	ret
+; d012f
+
+PokeAnim_Idle: ; d012f
+	ld c, TRUE
+	ld b, 0
+	call PokeAnim_InitAnim
+	call PokeAnim_SetVBank1
+	ld a, [wPokeAnimSceneIndex]
+	inc a
+	ld [wPokeAnimSceneIndex], a
+	ret
+; d0141
+
+PokeAnim_Play: ; d0141
+	call PokeAnim_DoAnimScript
+	ld a, [wPokeAnimJumptableIndex]
+	bit 7, a
+	ret z
+	call PokeAnim_PlaceGraphic
+	ld a, [wPokeAnimSceneIndex]
+	inc a
+	ld [wPokeAnimSceneIndex], a
+	ret
+; d0155
+
+PokeAnim_Play2: ; d0155
+	call PokeAnim_DoAnimScript
+	ld a, [wPokeAnimJumptableIndex]
+	bit 7, a
+	ret z
+	ld a, [wPokeAnimSceneIndex]
+	inc a
+	ld [wPokeAnimSceneIndex], a
+	ret
+; d0166
+
+PokeAnim_BasePic: ; d0166
+	call PokeAnim_DeinitFrames
+	ld a, [wPokeAnimSceneIndex]
+	inc a
+	ld [wPokeAnimSceneIndex], a
+	ret
+; d0171
+
+PokeAnim_Finish: ; d0171
+	call PokeAnim_DeinitFrames
+	ld hl, wPokeAnimSceneIndex
+	set 7, [hl]
+	ret
+; d017a
+
+PokeAnim_Cry: ; d017a
+	ld a, [wPokeAnimSpecies]
+	call _PlayMonCry
+	ld a, [wPokeAnimSceneIndex]
+	inc a
+	ld [wPokeAnimSceneIndex], a
+	ret
+; d0188
+
+PokeAnim_CryNoWait: ; d0188
+	ld a, [wPokeAnimSpecies]
+	call PlayMonCry2
+	ld a, [wPokeAnimSceneIndex]
+	inc a
+	ld [wPokeAnimSceneIndex], a
+	ret
+; d0196
+
+PokeAnim_StereoCry: ; d0196
+	ld a, $f
+	ld [wCryTracks], a
+	ld a, [wPokeAnimSpecies]
+	call PlayStereoCry2
+	ld a, [wPokeAnimSceneIndex]
+	inc a
+	ld [wPokeAnimSceneIndex], a
+	ret
+; d01a9
+
+PokeAnim_DeinitFrames: ; d01a9
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wPokeAnimCoord)
+	ld [rSVBK], a
+	call PokeAnim_PlaceGraphic
+	farcall HDMATransferTileMapToWRAMBank3
+	call PokeAnim_SetVBank0
+	farcall HDMATransferAttrMapToWRAMBank3
+	pop af
+	ld [rSVBK], a
+	ret
+; d01c6
+
+AnimateMon_CheckIfPokemon: ; d01c6
+	ld a, [wCurPartySpecies]
+	cp EGG
+	jr z, .fail
+	call IsAPokemon
+	jr c, .fail
+	and a
+	ret
+
+.fail
+	scf
+	ret
+; d01d6
+
+PokeAnim_InitPicAttributes: ; d01d6
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wPokeAnimSceneIndex)
+	ld [rSVBK], a
+
+	push bc
+	push de
+	push hl
+	ld hl, wPokeAnimSceneIndex
+	ld bc, wPokeAnimStructEnd - wPokeAnimSceneIndex
+	xor a
+	call ByteFill
+	pop hl
+	pop de
+	pop bc
+
+; bc contains anim pointer
+	ld a, c
+	ld [wPokeAnimPointer], a
+	ld a, b
+	ld [wPokeAnimPointer + 1], a
+; hl contains tilemap coords
+	ld a, l
+	ld [wPokeAnimCoord], a
+	ld a, h
+	ld [wPokeAnimCoord + 1], a
+; d = start tile
+	ld a, d
+	ld [wPokeAnimGraphicStartTile], a
+
+	ld a, BANK(wCurPartySpecies)
+	ld hl, wCurPartySpecies
+	call GetFarWRAMByte
+	ld [wPokeAnimSpecies], a
+
+	ld a, BANK(wUnownLetter)
+	ld hl, wUnownLetter
+	call GetFarWRAMByte
+	ld [wPokeAnimUnownLetter], a
+
+	call PokeAnim_GetSpeciesOrUnown
+	ld [wPokeAnimSpeciesOrUnown], a
+
+	call PokeAnim_GetFrontpicDims
+	ld a, c
+	ld [wPokeAnimFrontpicHeight], a
+
+	pop af
+	ld [rSVBK], a
+	ret
+; d0228
+
+PokeAnim_InitAnim: ; d0228
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wPokeAnimIdleFlag)
+	ld [rSVBK], a
+	push bc
+	ld hl, wPokeAnimIdleFlag
+	ld bc, wPokeAnimStructEnd - wPokeAnimIdleFlag
+	xor a
+	call ByteFill
+	pop bc
+	ld a, b
+	ld [wPokeAnimSpeed], a
+	ld a, c
+	ld [wPokeAnimIdleFlag], a
+	call GetMonAnimPointer
+	call GetMonFramesPointer
+	call GetMonBitmaskPointer
+	pop af
+	ld [rSVBK], a
+	ret
+; d0250
+
+PokeAnim_DoAnimScript: ; d0250
+	xor a
+	ld [hBGMapMode], a
+.loop
+	ld a, [wPokeAnimJumptableIndex]
+	and $7f
+	ld hl, .Jumptable
+	rst JumpTable
+	ret
+; d025d
+
+.Jumptable: ; d025d
+	dw .RunAnim
+	dw .WaitAnim
+; d0261
+
+.RunAnim: ; d0261
+	call PokeAnim_GetPointer
+	ld a, [wPokeAnimCommand]
+	cp -1
+	jr z, PokeAnim_End
+	cp -2
+	jr z, .SetRepeat
+	cp -3
+	jr z, .DoRepeat
+	call PokeAnim_GetFrame
+	ld a, [wPokeAnimParameter]
+	call PokeAnim_GetDuration
+	ld [wPokeAnimWaitCounter], a
+	call PokeAnim_StartWaitAnim
+.WaitAnim: ; d0282
+	ld a, [wPokeAnimWaitCounter]
+	dec a
+	ld [wPokeAnimWaitCounter], a
+	ret nz
+	call PokeAnim_StopWaitAnim
+	ret
+; d028e
+
+.SetRepeat: ; d028e
+	ld a, [wPokeAnimParameter]
+	ld [wPokeAnimRepeatTimer], a
+	jr .loop
+; d0296
+
+.DoRepeat: ; d0296
+	ld a, [wPokeAnimRepeatTimer]
+	and a
+	ret z
+	dec a
+	ld [wPokeAnimRepeatTimer], a
+	ret z
+	ld a, [wPokeAnimParameter]
+	ld [wPokeAnimFrame], a
+	jr .loop
+; d02a8
+
+PokeAnim_End: ; d02a8
+	ld hl, wPokeAnimJumptableIndex
+	set 7, [hl]
+	ret
+; d02ae
+
+PokeAnim_GetDuration: ; d02ae
+; a * (1 + [wPokeAnimSpeed] / 16)
+	ld c, a
+	ld b, $0
+	ld hl, 0
+	ld a, [wPokeAnimSpeed]
+	call AddNTimes
+	ld a, h
+	swap a
+	and $f0
+	ld h, a
+	ld a, l
+	swap a
+	and $f
+	or h
+	add c
+	ret
+; d02c8
+
+PokeAnim_GetFrame: ; d02c8
+	call PokeAnim_PlaceGraphic
+	ld a, [wPokeAnimCommand]
+	and a
+	ret z
+	call PokeAnim_GetBitmaskIndex
+	push hl
+	call PokeAnim_CopyBitmaskToBuffer
+	pop hl
+	call PokeAnim_ConvertAndApplyBitmask
+	ret
+; d02dc
+
+PokeAnim_StartWaitAnim: ; d02dc
+	ld a, [wPokeAnimJumptableIndex]
+	inc a
+	ld [wPokeAnimJumptableIndex], a
+	ret
+; d02e4
+
+PokeAnim_StopWaitAnim: ; d02e4
+	ld a, [wPokeAnimJumptableIndex]
+	dec a
+	ld [wPokeAnimJumptableIndex], a
+	ret
+; d02ec
+
+PokeAnim_IsUnown: ; d02ec
+	ld a, [wPokeAnimSpecies]
+	cp UNOWN
+	ret
+; d02f2
+
+PokeAnim_IsEgg: ; d02f2
+	ld a, [wPokeAnimSpecies]
+	cp EGG
+	ret
+; d02f8
+
+PokeAnim_GetPointer: ; d02f8
+	push hl
+	ld a, [wPokeAnimFrame]
+	ld e, a
+	ld d, $0
+	ld hl, wPokeAnimPointerAddr
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	add hl, de
+	add hl, de
+	ld a, [wPokeAnimPointerBank]
+	call GetFarHalfword
+	ld a, l
+	ld [wPokeAnimCommand], a
+	ld a, h
+	ld [wPokeAnimParameter], a
+	ld hl, wPokeAnimFrame
+	inc [hl]
+	pop hl
+	ret
+; d031b
+
+PokeAnim_GetBitmaskIndex: ; d031b
+	ld a, [wPokeAnimCommand]
+	dec a
+	ld c, a
+	ld b, $0
+	ld hl, wPokeAnimFramesAddr
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	add hl, bc
+	add hl, bc
+	ld a, [wPokeAnimFramesBank]
+	call GetFarHalfword
+	ld a, [wPokeAnimFramesBank]
+	call GetFarByte
+	ld [wPokeAnimCurBitmask], a
+	inc hl
+	ret
+; d033b
+
+PokeAnim_CopyBitmaskToBuffer: ; d033b
+	call .GetSize
+	push bc
+	ld hl, wPokeAnimBitmaskAddr
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [wPokeAnimCurBitmask]
+	call AddNTimes
+	pop bc
+	ld de, wPokeAnimBitmaskBuffer
+	ld a, [wPokeAnimBitmaskBank]
+	call FarCopyBytes
+	ret
+; d0356
+
+.GetSize: ; d0356
+	push hl
+	ld a, [wPokeAnimFrontpicHeight]
+	sub 5 ; to get a number 0, 1, or 2
+	ld c, a
+	ld b, 0
+	ld hl, .Sizes
+	add hl, bc
+	ld c, [hl]
+	ld b, 0
+	pop hl
+	ret
+; d0368
+
+.Sizes: db 4, 5, 7
+
+poke_anim_box: MACRO
+y = 7
+rept \1
+x = 7 + -\1
+rept \1
+	db x + y
+x = x + 1
+endr
+y = y + 7
+endr
+ENDM
+
+PokeAnim_ConvertAndApplyBitmask: ; d036b
+	xor a
+	ld [wPokeAnimBitmaskCurBit], a
+	ld [wPokeAnimBitmaskCurRow], a
+	ld [wPokeAnimBitmaskCurCol], a
+.loop
+	push hl
+	call .IsCurBitSet
+	pop hl
+	ld a, b
+	and a
+	jr z, .next
+
+	ld a, [wPokeAnimFramesBank]
+	call GetFarByte
+	inc hl
+	push hl
+	call .ApplyFrame
+	pop hl
+
+.next
+	push hl
+	call .NextBit
+	pop hl
+	jr nc, .loop
+	ret
+; d0392
+
+.IsCurBitSet: ; d0392
+; which byte
+	ld a, [wPokeAnimBitmaskCurBit]
+	and $f8
+	rrca
+	rrca
+	rrca
+	ld e, a
+	ld d, 0
+	ld hl, wPokeAnimBitmaskBuffer
+	add hl, de
+	ld b, [hl]
+; which bit
+	ld a, [wPokeAnimBitmaskCurBit]
+	and $7
+	jr z, .skip
+
+	ld c, a
+	ld a, b
+.loop2
+	rrca
+	dec c
+	jr nz, .loop2
+	ld b, a
+
+.skip
+	xor a
+	bit 0, b
+	jr z, .finish
+	ld a, 1
+
+.finish
+	ld b, a
+	ld hl, wPokeAnimBitmaskCurBit
+	inc [hl]
+	ret
+; d03bd
+
+.ApplyFrame: ; d03bd
+	push af
+	call .GetCoord
+	pop af
+	push hl
+	call .GetTilemap
+	ld hl, wPokeAnimGraphicStartTile
+	add [hl]
+	pop hl
+	ld [hl], a
+	ret
+; d03cd
+
+.GetCoord: ; d03cd
+	call .GetStartCoord
+	ld a, [wPokeAnimBitmaskCurRow]
+	ld bc, SCREEN_WIDTH
+	call AddNTimes
+	ld a, [wBoxAlignment]
+	and a
+	jr nz, .go
+	ld a, [wPokeAnimBitmaskCurCol]
+	ld e, a
+	ld d, 0
+	add hl, de
+	jr .skip2
+
+.go
+	ld a, [wPokeAnimBitmaskCurCol]
+	ld e, a
+	ld a, l
+	sub e
+	ld l, a
+	ld a, h
+	sbc 0
+	ld h, a
+
+.skip2
+	ret
+; d03f4
+
+; unused
+	db 6, 5, 4
+
+.GetTilemap: ; d03f7
+	push af
+	ld a, [wPokeAnimFrontpicHeight]
+	cp 5
+	jr z, .check_add_24
+	cp 6
+	jr z, .check_add_13
+	pop af
+	ret
+
+.check_add_24
+	pop af
+	cp 5 * 5
+	jr nc, .add_24
+	push hl
+	push de
+	ld hl, ._5by5
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld a, [hl]
+	pop de
+	pop hl
+	ret
+
+.add_24
+	add 24
+	ret
+
+.check_add_13
+	pop af
+	cp 6 * 6
+	jr nc, .add_13
+	push hl
+	push de
+	ld hl, ._6by6
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld a, [hl]
+	pop de
+	pop hl
+	ret
+
+.add_13
+	add 13
+	ret
+; d042f
+
+._5by5:
+	poke_anim_box 5
+	; db  9, 10, 11, 12, 13
+	; db 16, 17, 18, 19, 20
+	; db 23, 24, 25, 26, 27
+	; db 30, 31, 32, 33, 34
+	; db 37, 38, 39, 40, 41
+
+._6by6:
+	poke_anim_box 6
+	; db  8,  9, 10, 11, 12, 13
+	; db 15, 16, 17, 18, 19, 20
+	; db 22, 23, 24, 25, 26, 27
+	; db 29, 30, 31, 32, 33, 34
+	; db 36, 37, 38, 39, 40, 41
+	; db 43, 44, 45, 46, 47, 48
+
+
+.GetStartCoord: ; d046c
+	ld hl, wPokeAnimCoord
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+
+	ld a, [wPokeAnimFrontpicHeight]
+	ld de, 0
+	ld bc, 6
+	cp 7
+	jr z, .okay
+	ld de, SCREEN_WIDTH + 1
+	ld bc, SCREEN_WIDTH + 5
+	cp 6
+	jr z, .okay
+	ld de, 2 * SCREEN_WIDTH + 1
+	ld bc, 2 * SCREEN_WIDTH + 5
+.okay
+
+	ld a, [wBoxAlignment]
+	and a
+	jr nz, .add_bc
+	add hl, de
+	ret
+
+.add_bc
+	add hl, bc
+	ret
+; d0499
+
+.NextBit: ; d0499
+	ld a, [wPokeAnimBitmaskCurRow]
+	inc a
+	ld [wPokeAnimBitmaskCurRow], a
+	ld c, a
+	ld a, [wPokeAnimFrontpicHeight]
+	cp c
+	jr nz, .no_carry
+	xor a
+	ld [wPokeAnimBitmaskCurRow], a
+	ld a, [wPokeAnimBitmaskCurCol]
+	inc a
+	ld [wPokeAnimBitmaskCurCol], a
+	ld c, a
+	ld a, [wPokeAnimFrontpicHeight]
+	cp c
+	jr nz, .no_carry
+	scf
+	ret
+
+.no_carry
+	xor a
+	ret
+; d04bd
+
+PokeAnim_PlaceGraphic: ; d04bd
+	call .ClearBox
+	ld a, [wBoxAlignment]
+	and a
+	jr nz, .flipped
+	ld de, 1
+	ld bc, 0
+	jr .okay
+
+.flipped
+	ld de, -1
+	ld bc, 6
+
+.okay
+	ld hl, wPokeAnimCoord
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	add hl, bc
+	ld c, 7
+	ld b, 7
+	ld a, [wPokeAnimGraphicStartTile]
+.loop
+	push bc
+	push hl
+	push de
+	ld de, SCREEN_WIDTH
+.loop2
+	ld [hl], a
+	inc a
+	add hl, de
+	dec b
+	jr nz, .loop2
+	pop de
+	pop hl
+	add hl, de
+	pop bc
+	dec c
+	jr nz, .loop
+	ret
+; d04f6
+
+.ClearBox: ; d04f6
+	ld hl, wPokeAnimCoord
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld b, 7
+	ld c, 7
+	call ClearBox
+	ret
+; d0504
+
+PokeAnim_SetVBank1: ; d0504
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wPokeAnimCoord)
+	ld [rSVBK], a
+	xor a
+	ld [hBGMapMode], a
+	call .SetFlag
+	farcall HDMATransferAttrMapToWRAMBank3
+	pop af
+	ld [rSVBK], a
+	ret
+; d051b
+
+.SetFlag: ; d051b
+	call PokeAnim_GetAttrMapCoord
+	ld b, 7
+	ld c, 7
+	ld de, SCREEN_WIDTH
+.row
+	push bc
+	push hl
+.col
+	ld a, [hl]
+	or 8
+	ld [hl], a
+	add hl, de
+	dec c
+	jr nz, .col
+	pop hl
+	inc hl
+	pop bc
+	dec b
+	jr nz, .row
+	ret
+; d0536
+
+PokeAnim_SetVBank0: ; d0536
+	call PokeAnim_GetAttrMapCoord
+	ld b, 7
+	ld c, 7
+	ld de, SCREEN_WIDTH
+.row
+	push bc
+	push hl
+.col
+	ld a, [hl]
+	and $f7
+	ld [hl], a
+	add hl, de
+	dec c
+	jr nz, .col
+	pop hl
+	inc hl
+	pop bc
+	dec b
+	jr nz, .row
+	ret
+; d0551
+
+PokeAnim_GetAttrMapCoord: ; d0551
+	ld hl, wPokeAnimCoord
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, wAttrMap - wTileMap
+	add hl, de
+	ret
+; d055c
+
+GetMonAnimPointer: ; d055c
+	call PokeAnim_IsEgg
+	jr z, .egg
+
+	ld c, BANK(UnownAnimations)
+	ld hl, UnownAnimationPointers
+	ld de, UnownAnimationIdlePointers
+	call PokeAnim_IsUnown
+	jr z, .unown
+	ld c, BANK(PicAnimations)
+	ld hl, AnimationPointers
+	ld de, AnimationIdlePointers
+.unown
+
+	ld a, [wPokeAnimIdleFlag]
+	and a
+	jr z, .idles
+	ld h, d
+	ld l, e
+.idles
+
+	ld a, [wPokeAnimSpeciesOrUnown]
+	dec a
+	ld e, a
+	ld d, 0
+	add hl, de
+	add hl, de
+	ld a, c
+	ld [wPokeAnimPointerBank], a
+	call GetFarHalfword
+	ld a, l
+	ld [wPokeAnimPointerAddr], a
+	ld a, h
+	ld [wPokeAnimPointerAddr + 1], a
+	ret
+
+.egg
+	ld hl, EggAnimation
+	ld c, BANK(EggAnimation)
+	ld a, [wPokeAnimIdleFlag]
+	and a
+	jr z, .idles_egg
+	ld hl, EggAnimationIdle
+	ld c, BANK(EggAnimationIdle)
+.idles_egg
+
+	ld a, c
+	ld [wPokeAnimPointerBank], a
+	ld a, l
+	ld [wPokeAnimPointerAddr], a
+	ld a, h
+	ld [wPokeAnimPointerAddr + 1], a
+	ret
+; d05b4
+
+PokeAnim_GetFrontpicDims: ; d05b4
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wCurPartySpecies)
+	ld [rSVBK], a
+	ld a, [wCurPartySpecies]
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld a, [wBasePicSize]
+	and $f
+	ld c, a
+	pop af
+	ld [rSVBK], a
+	ret
+; d05ce
+
+GetMonFramesPointer: ; d05ce
+	call PokeAnim_IsEgg
+	jr z, .egg
+
+	call PokeAnim_IsUnown
+	ld b, BANK(UnownFramesPointers)
+	ld c, BANK(UnownsFrames)
+	ld hl, UnownFramesPointers
+	jr z, .got_frames
+	ld a, [wPokeAnimSpecies]
+	cp JOHTO_POKEMON
+	ld b, BANK(FramesPointers)
+	ld c, BANK(KantoFrames)
+	ld hl, FramesPointers
+	jr c, .got_frames
+	ld c, BANK(JohtoFrames)
+.got_frames
+	ld a, c
+	ld [wPokeAnimFramesBank], a
+
+	ld a, [wPokeAnimSpeciesOrUnown]
+	dec a
+	ld e, a
+	ld d, 0
+	add hl, de
+	add hl, de
+	ld a, b
+	call GetFarHalfword
+	ld a, l
+	ld [wPokeAnimFramesAddr], a
+	ld a, h
+	ld [wPokeAnimFramesAddr + 1], a
+	ret
+
+.egg
+	ld hl, EggFrames
+	ld c, BANK(EggFrames)
+	ld a, c
+	ld [wPokeAnimFramesBank], a
+	ld a, l
+	ld [wPokeAnimFramesAddr], a
+	ld a, h
+	ld [wPokeAnimFramesAddr + 1], a
+	ret
+; d061b
+
+GetMonBitmaskPointer: ; d061b
+	call PokeAnim_IsEgg
+	jr z, .egg
+
+	call PokeAnim_IsUnown
+	ld a, BANK(UnownBitmasksPointers)
+	ld hl, UnownBitmasksPointers
+	jr z, .unown
+	ld a, BANK(BitmasksPointers)
+	ld hl, BitmasksPointers
+.unown
+	ld [wPokeAnimBitmaskBank], a
+
+	ld a, [wPokeAnimSpeciesOrUnown]
+	dec a
+	ld e, a
+	ld d, 0
+	add hl, de
+	add hl, de
+	ld a, [wPokeAnimBitmaskBank]
+	call GetFarHalfword
+	ld a, l
+	ld [wPokeAnimBitmaskAddr], a
+	ld a, h
+	ld [wPokeAnimBitmaskAddr + 1], a
+	ret
+
+.egg
+	ld c, BANK(EggBitmasks)
+	ld hl, EggBitmasks
+	ld a, c
+	ld [wPokeAnimBitmaskBank], a
+	ld a, l
+	ld [wPokeAnimBitmaskAddr], a
+	ld a, h
+	ld [wPokeAnimBitmaskAddr + 1], a
+	ret
+; d065c
+
+PokeAnim_GetSpeciesOrUnown: ; d065c
+	call PokeAnim_IsUnown
+	jr z, .unown
+	ld a, [wPokeAnimSpecies]
+	ret
+
+.unown
+	ld a, [wPokeAnimUnownLetter]
+	ret
+; d0669
+
+Unused_HOF_AnimateAlignedFrontpic: ; d0669
+	ld a, $1
+	ld [wBoxAlignment], a
+
+HOF_AnimateFrontpic: ; d066e
+	call AnimateMon_CheckIfPokemon
+	jr c, .fail
+	ld h, d
+	ld l, e
+	push bc
+	push hl
+	ld de, vTiles2
+	predef GetAnimatedFrontpic
+	pop hl
+	pop bc
+	ld d, 0
+	ld e, c
+	call AnimateFrontpic
+	xor a
+	ld [wBoxAlignment], a
+	ret
+
+.fail
+	xor a
+	ld [wBoxAlignment], a
+	inc a
+	ld [wCurPartySpecies], a
+	ret
+; d0695
--- /dev/null
+++ b/engine/gfx/player_gfx.asm
@@ -1,0 +1,224 @@
+Unreferenced_Function88248: ; 88248
+	ld c, CAL
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .okay
+	ld c, KAREN
+
+.okay
+	ld a, c
+	ld [wTrainerClass], a
+	ret
+
+MovePlayerPicRight: ; 88258
+	hlcoord 6, 4
+	ld de, 1
+	jr MovePlayerPic
+
+MovePlayerPicLeft: ; 88260
+	hlcoord 13, 4
+	ld de, -1
+	; fallthrough
+
+MovePlayerPic: ; 88266
+; Move player pic at hl by de * 7 tiles.
+	ld c, $8
+.loop
+	push bc
+	push hl
+	push de
+	xor a
+	ld [hBGMapMode], a
+	lb bc, 7, 7
+	predef PlaceGraphic
+	xor a
+	ld [hBGMapThird], a
+	call WaitBGMap
+	call DelayFrame
+	pop de
+	pop hl
+	add hl, de
+	pop bc
+	dec c
+	ret z
+	push hl
+	push bc
+	ld a, l
+	sub e
+	ld l, a
+	ld a, h
+	sbc d
+	ld h, a
+	lb bc, 7, 7
+	call ClearBox
+	pop bc
+	pop hl
+	jr .loop
+
+ShowPlayerNamingChoices: ; 88297
+	ld hl, ChrisNameMenuHeader
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .GotGender
+	ld hl, KrisNameMenuHeader
+.GotGender:
+	call LoadMenuHeader
+	call VerticalMenu
+	ld a, [wMenuCursorY]
+	dec a
+	call CopyNameFromMenu
+	call CloseWindow
+	ret
+
+INCLUDE "data/player_names.asm"
+
+GetPlayerNameArray: ; 88318 This Function is never called
+	ld hl, wPlayerName
+	ld de, MalePlayerNameArray
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .done
+	ld de, FemalePlayerNameArray
+
+.done
+	call InitName
+	ret
+
+GetPlayerIcon: ; 8832c
+; Get the player icon corresponding to gender
+
+; Male
+	ld de, ChrisSpriteGFX
+	ld b, BANK(ChrisSpriteGFX)
+
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .done
+
+; Female
+	ld de, KrisSpriteGFX
+	ld b, BANK(KrisSpriteGFX)
+
+.done
+	ret
+
+GetCardPic: ; 8833e
+	ld hl, ChrisCardPic
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .GotClass
+	ld hl, KrisCardPic
+.GotClass:
+	ld de, vTiles2 tile $00
+	ld bc, $23 tiles
+	ld a, BANK(ChrisCardPic) ; BANK(KrisCardPic)
+	call FarCopyBytes
+	ld hl, CardGFX
+	ld de, vTiles2 tile $23
+	ld bc, 6 tiles
+	ld a, BANK(CardGFX)
+	call FarCopyBytes
+	ret
+
+ChrisCardPic: ; 88365
+INCBIN "gfx/trainer_card/chris_card.2bpp"
+
+KrisCardPic: ; 88595
+INCBIN "gfx/trainer_card/kris_card.2bpp"
+
+CardGFX: ; 887c5
+INCBIN "gfx/trainer_card/trainer_card.2bpp"
+
+GetPlayerBackpic: ; 88825
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, GetChrisBackpic
+	call GetKrisBackpic
+	ret
+
+GetChrisBackpic: ; 88830
+	ld hl, ChrisBackpic
+	ld b, BANK(ChrisBackpic)
+	ld de, vTiles2 tile $31
+	ld c, 7 * 7
+	predef DecompressGet2bpp
+	ret
+
+HOF_LoadTrainerFrontpic: ; 88840
+	call WaitBGMap
+	xor a
+	ld [hBGMapMode], a
+	ld e, 0
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .GotClass
+	ld e, 1
+
+.GotClass:
+	ld a, e
+	ld [wTrainerClass], a
+	ld de, ChrisPic
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .GotPic
+	ld de, KrisPic
+
+.GotPic:
+	ld hl, vTiles2
+	ld b, BANK(ChrisPic) ; BANK(KrisPic)
+	ld c, 7 * 7
+	call Get2bpp
+	call WaitBGMap
+	ld a, $1
+	ld [hBGMapMode], a
+	ret
+
+DrawIntroPlayerPic: ; 88874
+; Draw the player pic at (6,4).
+
+; Get class
+	ld e, CHRIS
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .GotClass
+	ld e, KRIS
+.GotClass:
+	ld a, e
+	ld [wTrainerClass], a
+
+; Load pic
+	ld de, ChrisPic
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .GotPic
+	ld de, KrisPic
+.GotPic:
+	ld hl, vTiles2
+	ld b, BANK(ChrisPic) ; BANK(KrisPic)
+	ld c, 7 * 7 ; dimensions
+	call Get2bpp
+
+; Draw
+	xor a
+	ld [hGraphicStartTile], a
+	hlcoord 6, 4
+	lb bc, 7, 7
+	predef PlaceGraphic
+	ret
+
+ChrisPic: ; 888a9
+INCBIN "gfx/player/chris.2bpp"
+
+KrisPic: ; 88bb9
+INCBIN "gfx/player/kris.2bpp"
+
+GetKrisBackpic: ; 88ec9
+; Kris's backpic is uncompressed.
+	ld de, KrisBackpic
+	ld hl, vTiles2 tile $31
+	lb bc, BANK(KrisBackpic), 7 * 7 ; dimensions
+	call Get2bpp
+	ret
+
+KrisBackpic: ; 88ed6
+INCBIN "gfx/player/kris_back.2bpp"
--- /dev/null
+++ b/engine/gfx/sgb_layouts.asm
@@ -1,0 +1,605 @@
+LoadSGBLayout: ; 864c
+	call CheckCGB
+	jp nz, LoadSGBLayoutCGB
+
+	ld a, b
+	cp SCGB_RAM
+	jr nz, .not_ram
+	ld a, [wSGBPredef]
+.not_ram
+	cp SCGB_PARTY_MENU_HP_PALS
+	jp z, SGB_ApplyPartyMenuHPPals
+	ld l, a
+	ld h, 0
+	add hl, hl
+	ld de, .Jumptable
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, _LoadSGBLayout_ReturnFromJumpTable
+	push de
+	jp hl
+; 866f
+
+.Jumptable: ; 866f
+	dw .SGB_BattleGrayscale
+	dw .SGB_BattleColors
+	dw .SGB_PokegearPals
+	dw .SGB_StatsScreenHPPals
+	dw .SGB_Pokedex
+	dw .SGB_SlotMachine
+	dw .SGB06
+	dw .SGB_GSIntro
+	dw .SGB_Diploma
+	dw .SGB_MapPals
+	dw .SGB_PartyMenu
+	dw .SGB_Evolution
+	dw .SGB_GSTitleScreen
+	dw .SGB0d
+	dw .SGB_MoveList
+	dw .SGB0f
+	dw .SGB_PokedexSearchOption
+	dw .SGB11
+	dw .SGB12
+	dw .SGB13
+	dw .SGB_PackPals
+	dw .SGB_TrainerCard
+	dw .SGB_PokedexUnownMode
+	dw .SGB_BillsPC
+	dw .SGB_UnownPuzzle
+	dw .SGB_GamefreakLogo
+	dw .SGB_PlayerOrMonFrontpicPals
+	dw .SGB_TradeTube
+	dw .SGB_TrainerOrMonFrontpicPals
+	dw .SGB_MysteryGift
+	dw .SGB1e
+; 86ad
+
+.SGB_BattleGrayscale: ; 86ad
+	ld hl, PalPacket_BattleGrayscale
+	ld de, BlkPacket_Battle
+	ret
+; 86b4
+
+.SGB_BattleColors: ; 86b4
+	ld hl, BlkPacket_Battle
+	call PushSGBPals_
+
+	ld hl, PalPacket_9ce6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+
+	ld a, [wPlayerHPPal]
+	ld l, a
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	ld de, HPBarPals
+	add hl, de
+
+	ld a, [hli]
+	ld [wSGBPals + 3], a
+	ld a, [hli]
+	ld [wSGBPals + 4], a
+	ld a, [hli]
+	ld [wSGBPals + 5], a
+	ld a, [hl]
+	ld [wSGBPals + 6], a
+
+	ld a, [wEnemyHPPal]
+	ld l, a
+	ld h, 0
+	add hl, hl
+	add hl, hl
+
+	ld de, HPBarPals
+	add hl, de
+	ld a, [hli]
+	ld [wSGBPals + 9], a
+	ld a, [hli]
+	ld [wSGBPals + 10], a
+	ld a, [hli]
+	ld [wSGBPals + 11], a
+	ld a, [hl]
+	ld [wSGBPals + 12], a
+
+	ld hl, PalPacket_9cf6
+	ld de, wSGBPals + PALPACKET_LENGTH
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+
+	call GetBattlemonBackpicPalettePointer
+
+	ld a, [hli]
+	ld [wSGBPals + 19], a
+	ld a, [hli]
+	ld [wSGBPals + 20], a
+	ld a, [hli]
+	ld [wSGBPals + 21], a
+	ld a, [hl]
+	ld [wSGBPals + 22], a
+	call GetEnemyFrontpicPalettePointer
+	ld a, [hli]
+	ld [wSGBPals + 25], a
+	ld a, [hli]
+	ld [wSGBPals + 26], a
+	ld a, [hli]
+	ld [wSGBPals + 27], a
+	ld a, [hl]
+	ld [wSGBPals + 28], a
+
+	ld hl, wSGBPals
+	ld de, wSGBPals + PALPACKET_LENGTH
+	ld a, SCGB_BATTLE_COLORS
+	ld [wSGBPredef], a
+	ret
+; 873c
+
+.SGB_MoveList: ; 873c
+	ld hl, PalPacket_9bd6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+
+	ld hl, wSGBPals + 1
+	ld [hl], $10
+	inc hl
+	inc hl
+
+	ld a, [wPlayerHPPal]
+	add PREDEFPAL_HP_GREEN
+	ld [hl], a
+	ld hl, wSGBPals
+	ld de, BlkPacket_MoveList
+	ret
+; 875c
+
+.SGB_PokegearPals: ; 875c
+	ld hl, PalPacket_Pokegear
+	ld de, BlkPacket_9a86
+	ret
+; 8763
+
+.SGB_StatsScreenHPPals: ; 8763
+	ld hl, PalPacket_9ce6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	ld a, [wCurHPPal]
+	ld l, a
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	ld de, HPBarPals
+	add hl, de
+	ld a, [hli]
+	ld [wSGBPals + 3], a
+	ld a, [hli]
+	ld [wSGBPals + 4], a
+	ld a, [hli]
+	ld [wSGBPals + 5], a
+	ld a, [hl]
+	ld [wSGBPals + 6], a
+	ld a, [wCurPartySpecies]
+	ld bc, wTempMonDVs
+	call GetPlayerOrMonPalettePointer
+	ld a, [hli]
+	ld [wSGBPals + 9], a
+	ld a, [hli]
+	ld [wSGBPals + 10], a
+	ld a, [hli]
+	ld [wSGBPals + 11], a
+	ld a, [hl]
+	ld [wSGBPals + 12], a
+	ld hl, wSGBPals
+	ld de, BlkPacket_StatsScreen
+	ret
+; 87ab
+
+.SGB_PartyMenu: ; 87ab
+	ld hl, PalPacket_PartyMenu
+	ld de, wSGBPals + 1
+	ret
+; 87b2
+
+.SGB_Pokedex: ; 87b2
+	ld hl, PalPacket_9ce6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	ld hl, wSGBPals + 3
+	ld [hl], LOW(palred 31 + palgreen 20 + palblue 10)
+	inc hl
+	ld [hl], HIGH(palred 31 + palgreen 20 + palblue 10)
+	inc hl
+	ld [hl], LOW(palred 26 + palgreen 10 + palblue 6)
+	inc hl
+	ld [hl], HIGH(palred 26 + palgreen 10 + palblue 6)
+	ld a, [wCurPartySpecies]
+	call GetMonPalettePointer_
+	ld a, [hli]
+	ld [wSGBPals + 9], a
+	ld a, [hli]
+	ld [wSGBPals + 10], a
+	ld a, [hli]
+	ld [wSGBPals + 11], a
+	ld a, [hl]
+	ld [wSGBPals + 12], a
+	ld hl, wSGBPals
+	ld de, BlkPacket_Pokedex_PC
+	ret
+; 87e9
+
+.SGB_BillsPC: ; 87e9
+	ld hl, PalPacket_9ce6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	ld hl, wSGBPals + 3
+	ld [hl], LOW(palred 31 + palgreen 20 + palblue 10)
+	inc hl
+	ld [hl], HIGH(palred 31 + palgreen 20 + palblue 10)
+	inc hl
+	ld [hl], LOW(palred 26 + palgreen 10 + palblue 6)
+	inc hl
+	ld [hl], HIGH(palred 26 + palgreen 10 + palblue 6)
+	ld a, [wCurPartySpecies]
+	ld bc, wTempMonDVs
+	call GetPlayerOrMonPalettePointer
+	ld a, [hli]
+	ld [wSGBPals + 9], a
+	ld a, [hli]
+	ld [wSGBPals + 10], a
+	ld a, [hli]
+	ld [wSGBPals + 11], a
+	ld a, [hl]
+	ld [wSGBPals + 12], a
+	ld hl, wSGBPals
+	ld de, BlkPacket_Pokedex_PC
+	ret
+; 8823
+
+.SGB_PokedexUnownMode: ; 8823
+	call .SGB_Pokedex
+	ld de, BlkPacket_PokedexUnownMode
+	ret
+; 882a
+
+.SGB_PokedexSearchOption: ; 882a
+	ld hl, PalPacket_9ce6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	ld hl, wSGBPals + 3
+	ld [hl], LOW(palred 31 + palgreen 20 + palblue 10)
+	inc hl
+	ld [hl], HIGH(palred 31 + palgreen 20 + palblue 10)
+	inc hl
+	ld [hl], LOW(palred 26 + palgreen 10 + palblue 6)
+	inc hl
+	ld [hl], HIGH(palred 26 + palgreen 10 + palblue 6)
+	ld hl, wSGBPals
+	ld de, BlkPacket_9a86
+	ret
+; 884b
+
+.SGB_PackPals: ; 884b
+	ld hl, PalPacket_Pack
+	ld de, BlkPacket_9a86
+	ret
+; 8852
+
+.SGB_SlotMachine: ; 8852
+	ld hl, PalPacket_SlotMachine
+	ld de, BlkPacket_SlotMachine
+	ret
+; 8859
+
+.SGB06: ; 8859
+	ld hl, PalPacket_SCGB_06
+	ld de, BlkPacket_SCGB_06
+	ret
+; 8860
+
+.SGB_Diploma:
+.SGB_MysteryGift: ; 8860
+	ld hl, PalPacket_Diploma
+	ld de, BlkPacket_9a86
+	ret
+; 8867
+
+.SGB_GSIntro: ; 8867
+	ld b, 0
+	ld hl, .BlkPacketTable_GSIntro
+rept 4
+	add hl, bc
+endr
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	inc hl
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ret
+; 8878
+
+.BlkPacketTable_GSIntro: ; 8878
+	dw BlkPacket_9a86, PalPacket_GSIntroShellderLapras
+	dw BlkPacket_GSIntroJigglypuffPikachu, PalPacket_GSIntroJigglypuffPikachu
+	dw BlkPacket_9a86, PalPacket_GSIntroStartersTransition
+; 8884
+
+.SGB_GSTitleScreen: ; 8884
+	ld hl, PalPacket_GSTitleScreen
+	ld de, BlkPacket_GSTitleScreen
+	ld a, SCGB_DIPLOMA
+	ld [wSGBPredef], a
+	ret
+; 8890
+
+.SGB13: ; 8890
+	ld hl, PalPacket_SCGB_13
+	ld de, BlkPacket_SCGB_13
+	ret
+; 8897
+
+.SGB0f: ; 8897
+	ld hl, PalPacket_SCGB_0F
+	ld de, BlkPacket_9a86
+	ret
+; 889e
+
+.SGB11: ; 889e
+	ld hl, BlkPacket_9a86
+	ld de, wPlayerLightScreenCount ; ???
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	ld hl, PalPacket_SCGB_11
+	ld de, BlkPacket_9a86
+	ret
+; 88b1
+
+.SGB_MapPals: ; 88b1
+	ld hl, PalPacket_9bd6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	call .GetMapPalsIndex
+	ld hl, wSGBPals + 1
+	ld [hld], a
+	ld de, BlkPacket_9a86
+	ld a, SCGB_MAPPALS
+	ld [wSGBPredef], a
+	ret
+; 88cd
+
+.SGB_Evolution: ; 88cd
+	push bc
+	ld hl, PalPacket_9ce6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	pop bc
+	ld a, c
+	and a
+	jr z, .partymon
+	; Egg
+	ld hl, wSGBPals + 3
+	ld [hl], LOW(palred 7 + palgreen 7 + palblue 7)
+	inc hl
+	ld [hl], HIGH(palred 7 + palgreen 7 + palblue 7)
+	inc hl
+	ld [hl], LOW(palred 2 + palgreen 3 + palblue 3)
+	inc hl
+	ld [hl], HIGH(palred 2 + palgreen 3 + palblue 3)
+	jr .done
+
+.partymon
+	ld hl, wPartyMon1DVs
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld c, l
+	ld b, h
+	ld a, [wPlayerHPPal]
+	call GetPlayerOrMonPalettePointer
+	ld a, [hli]
+	ld [wSGBPals + 3], a
+	ld a, [hli]
+	ld [wSGBPals + 4], a
+	ld a, [hli]
+	ld [wSGBPals + 5], a
+	ld a, [hl]
+	ld [wSGBPals + 6], a
+
+.done
+	ld hl, wSGBPals
+	ld de, BlkPacket_9a86
+	ret
+; 891a
+
+.SGB0d:
+.SGB_TrainerCard: ; 891a
+	ld hl, PalPacket_Diploma
+	ld de, BlkPacket_9a86
+	ret
+; 8921
+
+.SGB_UnownPuzzle: ; 8921
+	ld hl, PalPacket_UnownPuzzle
+	ld de, BlkPacket_9a86
+	ret
+; 8928
+
+.SGB12: ; 8928
+	ld hl, PalPacket_9bd6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	ld hl, BlkPacket_9a86
+	ld de, wSGBPals + PALPACKET_LENGTH
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	call .GetMapPalsIndex
+	ld hl, wSGBPals + 1
+	ld [hl], a
+	ld hl, wSGBPals + 3
+	ld [hl], $2e
+	ld hl, wSGBPals + $13
+	ld a, 5
+	ld [hli], a
+	ld a, [wMenuBorderLeftCoord]
+	ld [hli], a
+	ld a, [wMenuBorderTopCoord]
+	ld [hli], a
+	ld a, [wMenuBorderRightCoord]
+	ld [hli], a
+	ld a, [wMenuBorderBottomCoord]
+	ld [hl], a
+	ld hl, wSGBPals
+	ld de, wSGBPals + PALPACKET_LENGTH
+	ret
+; 8969
+
+.SGB1e: ; 8969
+	ld hl, PalPacket_9ce6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	ld a, [wCurPartySpecies]
+	ld l, a
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	add hl, hl
+	ld de, PokemonPalettes
+	add hl, de
+	ld a, [wcf65]
+	and 3
+	sla a
+	sla a
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [hli]
+	ld [wSGBPals + 3], a
+	ld a, [hli]
+	ld [wSGBPals + 4], a
+	ld a, [hli]
+	ld [wSGBPals + 5], a
+	ld a, [hl]
+	ld [wSGBPals + 6], a
+	ld hl, wSGBPals
+	ld de, BlkPacket_9a86
+	ret
+; 89a6
+
+.SGB_GamefreakLogo: ; 89a6
+	ld hl, PalPacket_GamefreakLogo
+	ld de, BlkPacket_9a86
+	ret
+; 89ad
+
+.SGB_PlayerOrMonFrontpicPals: ; 89ad
+	ld hl, PalPacket_9ce6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	ld a, [wCurPartySpecies]
+	ld bc, wTempMonDVs
+	call GetPlayerOrMonPalettePointer
+	ld a, [hli]
+	ld [wSGBPals + 3], a
+	ld a, [hli]
+	ld [wSGBPals + 4], a
+	ld a, [hli]
+	ld [wSGBPals + 5], a
+	ld a, [hl]
+	ld [wSGBPals + 6], a
+	ld hl, wSGBPals
+	ld de, BlkPacket_9a86
+	ret
+; 89d9
+
+.SGB_TradeTube: ; 89d9
+	ld hl, PalPacket_TradeTube
+	ld de, BlkPacket_9a86
+	ret
+; 89e0
+
+.SGB_TrainerOrMonFrontpicPals: ; 89e0
+	ld hl, PalPacket_9ce6
+	ld de, wSGBPals
+	ld bc, PALPACKET_LENGTH
+	call CopyBytes
+	ld a, [wCurPartySpecies]
+	ld bc, wTempMonDVs
+	call GetFrontpicPalettePointer
+	ld a, [hli]
+	ld [wSGBPals + 3], a
+	ld a, [hli]
+	ld [wSGBPals + 4], a
+	ld a, [hli]
+	ld [wSGBPals + 5], a
+	ld a, [hl]
+	ld [wSGBPals + 6], a
+	ld hl, wSGBPals
+	ld de, BlkPacket_9a86
+	ret
+; 8a0c
+
+.GetMapPalsIndex: ; 8a0c
+	ld a, [wTimeOfDayPal]
+	cp NITE_F
+	jr c, .morn_day
+	ld a, PREDEFPAL_NITE
+	ret
+
+.morn_day
+	ld a, [wEnvironment]
+	cp ROUTE
+	jr z, .route
+	cp CAVE
+	jr z, .cave
+	cp DUNGEON
+	jr z, .cave
+	cp ENVIRONMENT_5
+	jr z, .perm5
+	cp GATE
+	jr z, .gate
+	ld a, [wMapGroup]
+	ld e, a
+	ld d, 0
+	ld hl, MapGroupRoofSGBPalInds
+	add hl, de
+	ld a, [hl]
+	ret
+
+.route
+	ld a, PREDEFPAL_00
+	ret
+
+.cave
+	ld a, PREDEFPAL_DUNGEONS
+	ret
+
+.perm5
+	ld a, PREDEFPAL_VERMILION
+	ret
+
+.gate
+	ld a, PREDEFPAL_PEWTER
+	ret
+; 8a45
+
+INCLUDE "data/maps/sgb_roof_pal_inds.asm"
+
+_LoadSGBLayout_ReturnFromJumpTable: ; 8a60
+	push de
+	call PushSGBPals_
+	pop hl
+	jp PushSGBPals_
+; 8a68
--- /dev/null
+++ b/engine/gfx/sprite_anims.asm
@@ -1,0 +1,889 @@
+DoAnimFrame: ; 8d24b
+	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+	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
+; 8d25b
+
+.Jumptable: ; 8d25b (23:525b)
+; entries correspond to SPRITE_ANIM_SEQ_* constants
+	dw .Null
+	dw .PartyMon
+	dw .PartyMonSwitch
+	dw .PartyMonSelected
+	dw .GSTitleTrail
+	dw .NamingScreenCursor
+	dw .GameFreakLogo
+	dw .GSIntroStar
+	dw .GSIntroSparkle
+	dw .SlotsGolem
+	dw .SlotsChansey
+	dw .SlotsChanseyEgg
+	dw .MailCursor
+	dw .UnusedCursor
+	dw .DummyGameCursor
+	dw .PokegearArrow
+	dw .TradePokeBall
+	dw .TradeTubeBulge
+	dw .TrademonInTube
+	dw .RevealNewMon
+	dw .RadioTuningKnob
+	dw .CutLeaves
+	dw .FlyFrom
+	dw .FlyLeaf
+	dw .FlyTo
+	dw .GSIntroHoOh
+	dw .EZChatCursor
+	dw .MobileTradeSentPulse
+	dw .MobileTradeOTPulse
+	dw .IntroSuicune
+	dw .IntroPichuWooper
+	dw .Celebi
+	dw .IntroUnown
+	dw .IntroUnownF
+	dw .IntroSuicuneAway
+
+.Null: ; 8d2a1 (23:52a1)
+	ret
+
+.PartyMon ; 8d2a2 (23:52a2)
+	ld a, [wMenuCursorY]
+
+	ld hl, SPRITEANIMSTRUCT_INDEX
+	add hl, bc
+	cp [hl]
+	jr z, .PartyMonSwitch
+
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld [hl], 8 * 2
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], $0
+	ret
+
+.PartyMonSwitch ; 8d2b9 (23:52b9)
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld [hl], 8 * 3
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	ld d, a
+	inc [hl]
+	and $f
+	ret nz
+
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld e, [hl]
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld a, d
+	and $10 ; bit 4
+	jr z, .load_zero
+	ld a, e
+	and a
+	jr z, .load_minus_two
+	cp $1
+	jr z, .load_minus_one
+.load_zero
+	xor a
+	ld [hl], a
+	ret
+
+.load_minus_one
+	ld a, -1
+	ld [hl], a
+	ret
+
+.load_minus_two
+	ld a, -2
+	ld [hl], a
+	ret
+
+.PartyMonSelected ; 8d2ea (23:52ea)
+	ld a, [wMenuCursorY]
+
+	ld hl, SPRITEANIMSTRUCT_INDEX
+	add hl, bc
+	cp [hl]
+	jr z, .three_offset_right
+
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld [hl], 8 * 2
+	ret
+
+.three_offset_right
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld [hl], 8 * 3
+	ret
+
+.GSTitleTrail ; 8d302 (23:5302)
+	call .AnonymousJumptable
+	jp hl
+; 8d306 (23:5306)
+
+; Anonymous dw (see .AnonymousJumptable)
+	dw .four_zero
+	dw .four_one
+; 8d30a
+
+.four_zero ; 8d30a
+	call .IncrementJumptableIndex
+
+	ld hl, SPRITEANIMSTRUCT_INDEX
+	add hl, bc
+	ld a, [hl]
+
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	and $3
+	ld [hl], a
+	inc [hl]
+	swap a
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], a
+
+.four_one ; 8d321
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld a, [hl]
+	cp $a4
+	jr nc, .asm_8d356
+
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	add $4
+
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld [hl], a
+
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	inc [hl]
+
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld a, [hl]
+	sla a
+	sla a
+	ld d, $2
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	add $3
+	ld [hl], a
+	call .Sprites_Sine
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.asm_8d356
+	call DeinitializeSprite
+	ret
+; 8d35a
+
+.GSIntroHoOh ; 8d35a (23:535a)
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	inc a
+	ld [hl], a
+	ld d, $2
+	call .Sprites_Sine
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.NamingScreenCursor ; 8d36c (23:536c)
+	callfar NamingScreen_AnimateCursor
+	ret
+
+.MailCursor ; 8d373 (23:5373)
+	callfar ComposeMail_AnimateCursor
+	ret
+
+.GameFreakLogo: ; 8d37a (23:537a)
+	callfar GameFreakLogoJumper
+	ret
+
+.GSIntroStar ; 8d381 (23:5381)
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .asm_8d3ba
+	dec [hl]
+	dec [hl]
+	ld d, a
+	and $1f
+	jr nz, .asm_8d395
+
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	dec [hl]
+.asm_8d395
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld a, [hl]
+	push af
+	push de
+	call .Sprites_Sine
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+	pop de
+	pop af
+	call .Sprites_Cosine
+
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld [hl], a
+
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld a, [hl]
+
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	add [hl]
+	ld [hl], a
+	ret
+
+.asm_8d3ba
+	ld a, $1
+	ld [wcf64], a
+	call DeinitializeSprite
+	ret
+
+.GSIntroSparkle ; 8d3c3 (23:53c3)
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hli]
+	or [hl]
+	jr z, .asm_8d41e
+
+	ld hl, SPRITEANIMSTRUCT_0F
+	add hl, bc
+	ld d, [hl]
+
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld a, [hl]
+	push af
+	push de
+	call .Sprites_Sine
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+	pop de
+	pop af
+	call .Sprites_Cosine
+
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld [hl], a
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+
+	ld hl, SPRITEANIMSTRUCT_0E
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	add hl, de
+	ld e, l
+	ld d, h
+
+	ld hl, SPRITEANIMSTRUCT_0E
+	add hl, bc
+	ld [hl], e
+	inc hl
+	ld [hl], d
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, -$10
+	add hl, de
+	ld e, l
+	ld d, h
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], e
+	inc hl
+	ld [hl], d
+
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld a, [hl]
+	xor $20
+	ld [hl], a
+	ret
+
+.asm_8d41e
+	call DeinitializeSprite
+	ret
+
+.SlotsGolem: ; 8d422 (23:5422)
+	callfar Slots_AnimateGolem
+	ret
+
+.SlotsChansey: ; 8d429 (23:5429)
+	callfar Slots_AnimateChansey
+	ld hl, wcf64
+	ld a, [hl]
+	cp $2
+	ret nz
+	ld [hl], $3
+	ld a, SPRITE_ANIM_FRAMESET_SLOTS_CHANSEY_2
+	call _ReinitSpriteAnimFrame
+	ret
+
+.SlotsChanseyEgg: ; 8d43e (23:543e)
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld a, [hl]
+	dec [hl]
+	ld e, a
+	and $1
+	jr z, .move_vertical
+
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld a, [hl]
+	cp 15 * 8
+	jr c, .move_right
+	call DeinitializeSprite
+	ld a, $4
+	ld [wcf64], a
+	ld de, SFX_PLACE_PUZZLE_PIECE_DOWN
+	call PlaySFX
+	ret
+
+.move_right
+	inc [hl]
+.move_vertical
+	ld a, e
+	ld d, $20
+	call .Sprites_Sine
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.UnusedCursor ; 8d46e (23:546e)
+	callfar ret_e00ed
+	ret
+
+.PokegearArrow ; 8d475 (23:5475)
+	callfar AnimatePokegearModeIndicatorArrow
+	ret
+
+.DummyGameCursor ; 8d47c (23:547c)
+	callfar DummyGame_InterpretJoypad_AnimateCursor
+	ret
+
+.TradePokeBall ; 8d483 (23:5483)
+	call .AnonymousJumptable
+	jp hl
+; 8d487 (23:5487)
+
+; Anonymous dw (see .AnonymousJumptable)
+	dw .TradePokeBall_zero
+	dw .TradePokeBall_one
+	dw .TradePokeBall_two
+	dw .TradePokeBall_three
+	dw .TradePokeBall_four
+	dw .TradePokeBall_five
+; 8d493
+
+.TradePokeBall_zero ; 8d493
+	ld a, SPRITE_ANIM_FRAMESET_TRADE_POKE_BALL_WOBBLE
+	call _ReinitSpriteAnimFrame
+
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld [hl], $2
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $20
+	ret
+; 8d4a5
+
+.TradePokeBall_two ; 8d4a5
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .asm_8d4af
+	dec [hl]
+	ret
+
+.asm_8d4af
+	call .IncrementJumptableIndex
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $40
+
+.TradePokeBall_three ; 8d4b8
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	cp $30
+	jr c, .asm_8d4cd
+	dec [hl]
+	ld d, $28
+	call .Sprites_Sine
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.asm_8d4cd
+	ld de, SFX_GOT_SAFARI_BALLS
+	call PlaySFX
+	jr .TradePokeBall_five
+; 8d4d5
+
+.TradePokeBall_one ; 8d4d5
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld [hl], $4
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $30
+
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld [hl], $24
+	ret
+; 8d4e8
+
+.TradePokeBall_four ; 8d4e8
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .asm_8d51c
+	ld d, a
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	call Sprites_Sine
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	inc [hl]
+	ld a, [hl]
+	and $3f
+	ret nz
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $20
+
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld a, [hl]
+	sub $c
+	ld [hl], a
+	ld de, SFX_SWITCH_POKEMON
+	call PlaySFX
+	ret
+
+.asm_8d51c
+	xor a
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+	call .IncrementJumptableIndex
+	ret
+
+.TradePokeBall_five ; 8d526
+	call DeinitializeSprite
+	ret
+; 8d52a
+
+.TradeTubeBulge ; 8d52a (23:552a)
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld a, [hl]
+	inc [hl]
+	inc [hl]
+	cp $b0
+	jr nc, .delete
+	and $3
+	ret nz
+	ld de, SFX_POKEBALLS_PLACED_ON_TABLE
+	call PlaySFX
+	ret
+
+.delete
+	call DeinitializeSprite
+	ret
+
+.TrademonInTube ; 8d543 (23:5543)
+	callfar TradeAnim_AnimateTrademonInTube
+	ret
+
+.RevealNewMon: ; 8d54a (23:554a)
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	cp $80
+	jr nc, .finish_EggShell
+	ld d, a
+	add $8
+	ld [hl], a
+
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld a, [hl]
+	xor $20
+	ld [hl], a
+
+	push af
+	push de
+	call .Sprites_Sine
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+
+	pop de
+	pop af
+	call .Sprites_Cosine
+
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.finish_EggShell
+	call DeinitializeSprite
+	ret
+
+.RadioTuningKnob: ; 8d578 (23:5578)
+	callfar AnimateTuningKnob
+	ret
+
+.CutLeaves ; 8d57f (23:557f)
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	ld hl, $80
+	add hl, de
+	ld e, l
+	ld d, h
+
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld [hl], e
+	inc hl
+	ld [hl], d
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	inc [hl]
+	inc [hl]
+	inc [hl]
+	push af
+	push de
+	call .Sprites_Sine
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+	pop de
+	pop af
+	call .Sprites_Cosine
+
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.FlyFrom: ; 8d5b0 (23:55b0)
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	ld a, [hl]
+	and a
+	ret z
+
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld a, [hl]
+	inc [hl]
+	cp $40
+	ret c
+
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	dec [hl]
+	dec [hl]
+
+	ld hl, SPRITEANIMSTRUCT_0F
+	add hl, bc
+	ld a, [hl]
+	ld d, a
+	cp $40
+	jr nc, .skip
+	add $8
+	ld [hl], a
+.skip
+	ld hl, SPRITEANIMSTRUCT_0E
+	add hl, bc
+	ld a, [hl]
+	inc [hl]
+	call .Sprites_Cosine
+
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.FlyLeaf: ; 8d5e2 (23:55e2)
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld a, [hl]
+	cp -9 * 8
+	jr nc, .delete_leaf
+	inc [hl]
+	inc [hl]
+
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	dec [hl]
+
+	ld d, $40
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	inc [hl]
+	call .Sprites_Cosine
+
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.delete_leaf
+	call DeinitializeSprite
+	ret
+
+.FlyTo: ; 8d607 (23:5607)
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	ld a, [hl]
+	cp 10 * 8 + 4
+	ret z
+
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	inc [hl]
+	inc [hl]
+
+	ld hl, SPRITEANIMSTRUCT_0F
+	add hl, bc
+	ld a, [hl]
+	ld d, a
+	and a
+	jr z, .asm_8d621
+	sub $2
+	ld [hl], a
+.asm_8d621
+	ld hl, SPRITEANIMSTRUCT_0E
+	add hl, bc
+	ld a, [hl]
+	inc [hl]
+	call .Sprites_Cosine
+
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.MobileTradeSentPulse ; 8d630 (23:5630)
+	farcall Function108bc7
+	ret
+
+.MobileTradeOTPulse ; 8d637 (23:5637)
+	farcall Function108be0
+	ret
+
+.IntroSuicune ; 8d63e (23:563e)
+	ld a, [wcf65]
+	and a
+	jr nz, .asm_8d645
+	ret
+.asm_8d645
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], $0
+
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld a, [hl]
+	add $2
+	ld [hl], a
+	xor $ff
+	inc a
+	ld d, $20
+	call .Sprites_Sine
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+	ld a, SPRITE_ANIM_FRAMESET_INTRO_SUICUNE_2
+	call _ReinitSpriteAnimFrame
+	ret
+
+.IntroPichuWooper ; 8d666 (23:5666)
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	cp $14
+	jr nc, .asm_8d67f
+	add $2
+	ld [hl], a
+	xor $ff
+	inc a
+	ld d, $20
+	call .Sprites_Sine
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+.asm_8d67f
+	ret
+
+.IntroUnown ; 8d680 (23:5680)
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld d, [hl]
+	inc [hl]
+	inc [hl]
+	inc [hl]
+
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	push af
+	push de
+	call .Sprites_Sine
+
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], a
+	pop de
+	pop af
+	call .Sprites_Cosine
+
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.IntroUnownF ; 8d6a2 (23:56a2)
+	ld a, [wcf64]
+	cp $40
+	ret nz
+	ld a, SPRITE_ANIM_FRAMESET_INTRO_UNOWN_F_2
+	call _ReinitSpriteAnimFrame
+	ret
+
+.IntroSuicuneAway ; 8d6ae (23:56ae)
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	ld a, [hl]
+	add $10
+	ld [hl], a
+	ret
+
+.EZChatCursor ; 8d6b7 (23:56b7)
+	farcall AnimateEZChatCursor
+	ret
+
+.Celebi ; 8d6be (23:56be)
+	farcall UpdateCelebiPosition
+	ret
+
+.AnonymousJumptable: ; 8d6c5 (23:56c5)
+	ld hl, sp+$0
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	inc de
+
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld l, [hl]
+	ld h, $0
+	add hl, hl
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ret
+; 8d6d8 (23:56d8)
+
+.IncrementJumptableIndex: ; 8d6d8
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	inc [hl]
+	ret
+; 8d6de
+
+.Sprites_Sine: ; 8d6de (23:56de)
+	call Sprites_Sine
+	ret
+
+.Sprites_Cosine: ; 8d6e2 (23:56e2)
+	call Sprites_Cosine
+	ret
+; 8d6e6 (23:56e6)
--- /dev/null
+++ b/engine/gfx/sprites.asm
@@ -1,0 +1,677 @@
+ClearSpriteAnims: ; 8cf53
+	ld hl, wSpriteAnimDict
+	ld bc, wSpriteAnimsEnd - wSpriteAnimDict
+.loop
+	ld [hl], $0
+	inc hl
+	dec bc
+	ld a, c
+	or b
+	jr nz, .loop
+	ret
+; 8cf62
+
+PlaySpriteAnimationsAndDelayFrame: ; 8cf62
+	call PlaySpriteAnimations
+	call DelayFrame
+	ret
+; 8cf69
+
+PlaySpriteAnimations: ; 8cf69
+	push hl
+	push de
+	push bc
+	push af
+
+	ld a, LOW(wVirtualOAM)
+	ld [wCurrSpriteOAMAddr], a
+	call DoNextFrameForAllSprites
+
+	pop af
+	pop bc
+	pop de
+	pop hl
+	ret
+; 8cf7a
+
+DoNextFrameForAllSprites: ; 8cf7a
+	ld hl, wSpriteAnimationStructs
+	ld e, NUM_SPRITE_ANIM_STRUCTS
+
+.loop
+	ld a, [hl]
+	and a
+	jr z, .next ; This struct is deinitialized.
+	ld c, l
+	ld b, h
+	push hl
+	push de
+	call DoAnimFrame ; Uses a massive dw
+	call UpdateAnimFrame
+	pop de
+	pop hl
+	jr c, .done
+
+.next
+	ld bc, SPRITEANIMSTRUCT_LENGTH
+	add hl, bc
+	dec e
+	jr nz, .loop
+
+	ld a, [wCurrSpriteOAMAddr]
+	ld l, a
+	ld h, HIGH(wVirtualOAM)
+
+.loop2 ; Clear (wVirtualOAM + [wCurrSpriteOAMAddr] --> wVirtualOAMEnd)
+	ld a, l
+	cp LOW(wVirtualOAMEnd)
+	jr nc, .done
+	xor a
+	ld [hli], a
+	jr .loop2
+
+.done
+	ret
+; 8cfa8
+
+DoNextFrameForFirst16Sprites: ; 8cfa8 (23:4fa8)
+	ld hl, wSpriteAnimationStructs
+	ld e, NUM_SPRITE_ANIM_STRUCTS
+
+.loop
+	ld a, [hl]
+	and a
+	jr z, .next
+	ld c, l
+	ld b, h
+	push hl
+	push de
+	call DoAnimFrame ; Uses a massive dw
+	call UpdateAnimFrame
+	pop de
+	pop hl
+	jr c, .done
+
+.next
+	ld bc, SPRITEANIMSTRUCT_LENGTH
+	add hl, bc
+	dec e
+	jr nz, .loop
+
+	ld a, [wCurrSpriteOAMAddr]
+	ld l, a
+	ld h, HIGH(wVirtualOAMSprite16)
+
+.loop2 ; Clear (wVirtualOAM + [wCurrSpriteOAMAddr] --> Sprites + $40)
+	ld a, l
+	cp LOW(wVirtualOAMSprite16)
+	jr nc, .done
+	xor a
+	ld [hli], a
+	jr .loop2
+
+.done
+	ret
+
+InitSpriteAnimStruct:: ; 8cfd6
+; Initialize animation a at pixel x=e, y=d
+; Find if there's any room in the wSpriteAnimationStructs array, which is 10x16
+	push de
+	push af
+	ld hl, wSpriteAnimationStructs
+	ld e, NUM_SPRITE_ANIM_STRUCTS
+.loop
+	ld a, [hl]
+	and a
+	jr z, .found
+	ld bc, SPRITEANIMSTRUCT_LENGTH
+	add hl, bc
+	dec e
+	jr nz, .loop
+; We've reached the end.  There is no more room here.
+; Return carry.
+	pop af
+	pop de
+	scf
+	ret
+
+.found
+; Back up the structure address to bc.
+	ld c, l
+	ld b, h
+; Value [wSpriteAnimCount] is initially set to -1. Set it to
+; the number of objects loaded into this array.
+	ld hl, wSpriteAnimCount
+	inc [hl]
+	ld a, [hl]
+	and a
+	jr nz, .initialized
+	inc [hl]
+
+.initialized
+; Get row a of SpriteAnimSeqData, copy the pointer into de
+	pop af
+	ld e, a
+	ld d, 0
+	ld hl, SpriteAnimSeqData
+	add hl, de
+	add hl, de
+	add hl, de
+	ld e, l
+	ld d, h
+; Set hl to the first field (field 0) in the current structure.
+	ld hl, SPRITEANIMSTRUCT_INDEX
+	add hl, bc
+; Load the index.
+	ld a, [wSpriteAnimCount]
+	ld [hli], a
+; Copy the table entry to the next two fields.
+	ld a, [de]
+	ld [hli], a
+	inc de
+	ld a, [de]
+	ld [hli], a
+	inc de
+; Look up the third field from the table in the wSpriteAnimDict array (10x2).
+; Take the value and load it in
+	ld a, [de]
+	call GetSpriteAnimVTile
+	ld [hli], a
+	pop de
+; Set hl to field 4 (X coordinate).  Kinda pointless, because we're presumably already here.
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+; Load the original value of de into here.
+	ld a, e
+	ld [hli], a
+	ld a, d
+	ld [hli], a
+; load 0 into the next four fields
+	xor a
+	ld [hli], a
+	ld [hli], a
+	xor a
+	ld [hli], a
+	ld [hli], a
+; load -1 into the next field
+	dec a
+	ld [hli], a
+; load 0 into the last five fields
+	xor a
+rept 4
+	ld [hli], a
+endr
+	ld [hl], a
+; back up the address of the first field to wSpriteAnimAddrBackup
+	ld a, c
+	ld [wSpriteAnimAddrBackup], a
+	ld a, b
+	ld [wSpriteAnimAddrBackup + 1], a
+	ret
+; 8d036
+
+DeinitializeSprite: ; 8d036
+; Clear the index field of the struct in bc.
+	ld hl, SPRITEANIMSTRUCT_INDEX
+	add hl, bc
+	ld [hl], $0
+	ret
+; 8d03d
+
+
+DeinitializeAllSprites: ; 8d03d (23:503d)
+; Clear the index field of every struct in the wSpriteAnimationStructs array.
+	ld hl, wSpriteAnimationStructs
+	ld bc, SPRITEANIMSTRUCT_LENGTH
+	ld e, NUM_SPRITE_ANIM_STRUCTS
+	xor a
+.loop
+	ld [hl], a
+	add hl, bc
+	dec e
+	jr nz, .loop
+	ret
+
+
+UpdateAnimFrame: ; 8d04c
+	call InitSpriteAnimBuffer ; init WRAM
+	call GetSpriteAnimFrame ; read from a memory array
+	cp -3
+	jr z, .done
+	cp -4
+	jr z, .delete
+	call GetFrameOAMPointer
+	; add byte to [wCurrAnimVTile]
+	ld a, [wCurrAnimVTile]
+	add [hl]
+	ld [wCurrAnimVTile], a
+	inc hl
+	; load pointer into hl
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	push bc
+	ld a, [wCurrSpriteOAMAddr]
+	ld e, a
+	ld d, HIGH(wVirtualOAM)
+	ld a, [hli]
+	ld c, a ; number of objects
+.loop
+	; first byte: y (px)
+	; [de] = [wCurrAnimYCoord] + [wCurrAnimYOffset] + [wGlobalAnimYOffset] + AddOrSubtractY([hl])
+	ld a, [wCurrAnimYCoord]
+	ld b, a
+	ld a, [wCurrAnimYOffset]
+	add b
+	ld b, a
+	ld a, [wGlobalAnimYOffset]
+	add b
+	ld b, a
+	call AddOrSubtractY
+	add b
+	ld [de], a
+	inc hl
+	inc de
+	; second byte: x (px)
+	; [de] = [wCurrAnimXCoord] + [wCurrAnimXOffset] + [wGlobalAnimXOffset] + AddOrSubtractX([hl])
+	ld a, [wCurrAnimXCoord]
+	ld b, a
+	ld a, [wCurrAnimXOffset]
+	add b
+	ld b, a
+	ld a, [wGlobalAnimXOffset]
+	add b
+	ld b, a
+	call AddOrSubtractX
+	add b
+	ld [de], a
+	inc hl
+	inc de
+	; third byte: vtile
+	; [de] = [wCurrAnimVTile] + [hl]
+	ld a, [wCurrAnimVTile]
+	add [hl]
+	ld [de], a
+	inc hl
+	inc de
+	; fourth byte: attributes
+	; [de] = GetSpriteOAMAttr([hl])
+	call GetSpriteOAMAttr
+	ld [de], a
+	inc hl
+	inc de
+	ld a, e
+	ld [wCurrSpriteOAMAddr], a
+	cp LOW(wVirtualOAMEnd)
+	jr nc, .reached_the_end
+	dec c
+	jr nz, .loop
+	pop bc
+	jr .done
+
+.delete
+	call DeinitializeSprite
+.done
+	and a
+	ret
+
+.reached_the_end
+	pop bc
+	scf
+	ret
+; 8d0be
+
+AddOrSubtractY: ; 8d0be
+	push hl
+	ld a, [hl]
+	ld hl, wCurrSpriteAddSubFlags
+	bit 6, [hl]
+	jr z, .ok
+	; 8 - a
+	add $8
+	xor $ff
+	inc a
+
+.ok
+	pop hl
+	ret
+; 8d0ce
+
+AddOrSubtractX: ; 8d0ce
+	push hl
+	ld a, [hl]
+	ld hl, wCurrSpriteAddSubFlags
+	bit 5, [hl] ; x flip
+	jr z, .ok
+	; 8 - a
+	add $8
+	xor $ff
+	inc a
+
+.ok
+	pop hl
+	ret
+; 8d0de
+
+GetSpriteOAMAttr: ; 8d0de
+	ld a, [wCurrSpriteAddSubFlags]
+	ld b, a
+	ld a, [hl]
+	xor b
+	and $e0
+	ld b, a
+	ld a, [hl]
+	and $1f
+	or b
+	ret
+; 8d0ec
+
+InitSpriteAnimBuffer: ; 8d0ec
+	xor a
+	ld [wCurrSpriteAddSubFlags], a
+	ld hl, SPRITEANIMSTRUCT_TILE_ID
+	add hl, bc
+	ld a, [hli]
+	ld [wCurrAnimVTile], a
+	ld a, [hli]
+	ld [wCurrAnimXCoord], a
+	ld a, [hli]
+	ld [wCurrAnimYCoord], a
+	ld a, [hli]
+	ld [wCurrAnimXOffset], a
+	ld a, [hli]
+	ld [wCurrAnimYOffset], a
+	ret
+; 8d109
+
+GetSpriteAnimVTile: ; 8d109
+; a = wSpriteAnimDict[a] if a in wSpriteAnimDict else 0
+; vTiles offset
+	push hl
+	push bc
+	ld hl, wSpriteAnimDict
+	ld b, a
+	ld c, NUM_SPRITE_ANIM_STRUCTS
+.loop
+	ld a, [hli]
+	cp b
+	jr z, .ok
+	inc hl
+	dec c
+	jr nz, .loop
+	xor a
+	jr .done
+
+.ok
+	ld a, [hl]
+
+.done
+	pop bc
+	pop hl
+	ret
+; 8d120
+
+_ReinitSpriteAnimFrame:: ; 8d120
+	ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+	add hl, bc
+	ld [hl], a
+	ld hl, SPRITEANIMSTRUCT_DURATION
+	add hl, bc
+	ld [hl], 0
+	ld hl, SPRITEANIMSTRUCT_FRAME
+	add hl, bc
+	ld [hl], -1
+	ret
+; 8d132
+
+
+GetSpriteAnimFrame: ; 8d132
+.loop
+	ld hl, SPRITEANIMSTRUCT_DURATION
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .next_frame ; finished the current sequence
+	dec [hl]
+	call .GetPointer ; load pointer from SpriteAnimFrameData
+	ld a, [hli]
+	push af
+	jr .okay
+
+.next_frame
+	ld hl, SPRITEANIMSTRUCT_FRAME
+	add hl, bc
+	inc [hl]
+	call .GetPointer ; load pointer from SpriteAnimFrameData
+	ld a, [hli]
+	cp dorestart_command
+	jr z, .restart
+	cp endanim_command
+	jr z, .repeat_last
+
+	push af
+	ld a, [hl]
+	push hl
+	and $3f
+	ld hl, SPRITEANIMSTRUCT_DURATIONOFFSET
+	add hl, bc
+	add [hl]
+	ld hl, SPRITEANIMSTRUCT_DURATION
+	add hl, bc
+	ld [hl], a
+	pop hl
+.okay
+	ld a, [hl]
+	and $c0
+	srl a
+	ld [wCurrSpriteAddSubFlags], a
+	pop af
+	ret
+
+.repeat_last
+	xor a
+	ld hl, SPRITEANIMSTRUCT_DURATION
+	add hl, bc
+	ld [hl], a
+
+	ld hl, SPRITEANIMSTRUCT_FRAME
+	add hl, bc
+	dec [hl]
+	dec [hl]
+	jr .loop
+
+.restart
+	xor a
+	ld hl, SPRITEANIMSTRUCT_DURATION
+	add hl, bc
+	ld [hl], a
+
+	dec a
+	ld hl, SPRITEANIMSTRUCT_FRAME
+	add hl, bc
+	ld [hl], a
+	jr .loop
+; 8d189
+
+.GetPointer: ; 8d189
+	; Get the data for the current frame for the current animation sequence
+
+	; SpriteAnimFrameData[SpriteAnim[SPRITEANIMSTRUCT_FRAMESET_ID]][SpriteAnim[SPRITEANIMSTRUCT_FRAME]]
+	ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+	add hl, bc
+	ld e, [hl]
+	ld d, 0
+	ld hl, SpriteAnimFrameData
+	add hl, de
+	add hl, de
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	ld hl, SPRITEANIMSTRUCT_FRAME
+	add hl, bc
+	ld l, [hl]
+	ld h, 0
+	add hl, hl
+	add hl, de
+	ret
+; 8d1a2
+
+GetFrameOAMPointer: ; 8d1a2
+; Load OAM data pointer
+	ld e, a
+	ld d, 0
+	ld hl, SpriteAnimOAMData
+	add hl, de
+	add hl, de
+	add hl, de
+	ret
+; 8d1ac
+
+Unreferenced_BrokenGetStdGraphics: ; 8d1ac
+	push hl
+	ld l, a
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	ld de, BrokenStdGFXPointers ; broken 2bpp pointers
+	add hl, de
+	ld c, [hl]
+	inc hl
+	ld b, [hl]
+	inc hl
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	pop hl
+	push bc
+	call Request2bpp
+	pop bc
+	ret
+; 8d1c4
+
+
+INCLUDE "data/sprite_anims/sequences.asm"
+
+INCLUDE "engine/gfx/sprite_anims.asm"
+
+INCLUDE "data/sprite_anims/framesets.asm"
+
+INCLUDE "data/sprite_anims/oam.asm"
+
+
+BrokenStdGFXPointers:
+	; tile count, bank, pointer
+	; (all pointers were dummied out to .deleted)
+	dbbw 128, $01, .deleted
+	dbbw 128, $01, .deleted
+	dbbw 128, $01, .deleted
+	dbbw 128, $01, .deleted
+	dbbw 16, $37, .deleted
+	dbbw 16, $11, .deleted
+	dbbw 16, $39, .deleted
+	dbbw 16, $24, .deleted
+	dbbw 16, $21, .deleted
+
+.deleted
+; 8e72a (23:672a)
+
+
+Sprites_Cosine: ; 8e72a
+; a = d * cos(a * pi/32)
+	add %010000 ; cos(x) = sin(x + pi/2)
+	; fallthrough
+Sprites_Sine: ; 8e72c
+; a = d * sin(a * pi/32)
+	calc_sine_wave
+
+
+AnimateEndOfExpBar: ; 8e79d
+	ld a, [hSGB]
+	ld de, EndOfExpBarGFX
+	and a
+	jr z, .load
+	ld de, SGBEndOfExpBarGFX
+
+.load
+	ld hl, vTiles0 tile $00
+	lb bc, BANK(EndOfExpBarGFX), 1
+	call Request2bpp
+	ld c, 8
+	ld d, 0
+.loop
+	push bc
+	call .AnimateFrame
+	call DelayFrame
+	pop bc
+	inc d
+	inc d
+	dec c
+	jr nz, .loop
+	call ClearSprites
+	ret
+; 8e7c6
+
+.AnimateFrame: ; 8e7c6
+	ld hl, wVirtualOAMSprite00
+	ld c, 8 ; number of animated circles
+.anim_loop
+	ld a, c
+	and a
+	ret z
+	dec c
+	ld a, c
+; multiply by 8
+	sla a
+	sla a
+	sla a
+	push af
+
+	push de
+	push hl
+	call Sprites_Sine
+	pop hl
+	pop de
+	add 13 * TILE_WIDTH
+	ld [hli], a ; y
+
+	pop af
+	push de
+	push hl
+	call Sprites_Cosine
+	pop hl
+	pop de
+	add 10 * TILE_WIDTH + 4
+	ld [hli], a ; x
+
+	ld a, $0
+	ld [hli], a ; tile id
+	ld a, PAL_BATTLE_OB_BLUE
+	ld [hli], a ; attributes
+	jr .anim_loop
+; 8e7f4
+
+EndOfExpBarGFX: ; 8e7f4
+INCBIN "gfx/battle/expbarend.2bpp"
+SGBEndOfExpBarGFX: ; 8e804
+INCBIN "gfx/battle/expbarend_sgb.2bpp"
+
+ClearSpriteAnims2: ; 8e814
+	push hl
+	push de
+	push bc
+	push af
+	ld hl, wSpriteAnimDict
+	ld bc, wSpriteAnimsEnd - wSpriteAnimDict
+.loop
+	ld [hl], 0
+	inc hl
+	dec bc
+	ld a, c
+	or b
+	jr nz, .loop
+	pop af
+	pop bc
+	pop de
+	pop hl
+	ret
+; 8e82b
--- /dev/null
+++ b/engine/gfx/tileset_anims.asm
@@ -1,0 +1,1060 @@
+_AnimateTileset:: ; fc000
+; Iterate over a given pointer array of
+; animation functions (one per frame).
+
+; Typically in wra1, vra0
+
+	ld a, [wTilesetAnim]
+	ld e, a
+	ld a, [wTilesetAnim + 1]
+	ld d, a
+
+	ld a, [hTileAnimFrame]
+	ld l, a
+	inc a
+	ld [hTileAnimFrame], a
+
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	add hl, de
+
+; 2-byte parameter
+; All functions take input de.
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	inc hl
+
+; Function address
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+
+	jp hl
+; fc01b
+
+Tileset0Anim: ; 0xfc01b
+TilesetJohtoModernAnim: ; 0xfc01b
+TilesetKantoAnim: ; 0xfc01b
+	dw vTiles2 tile $14, AnimateWaterTile
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  TileAnimationPalette
+	dw NULL,  WaitTileAnimation
+	dw NULL,  AnimateFlowerTile
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  StandingTileFrame8
+	dw NULL,  DoneTileAnimation
+; 0xfc047
+
+TilesetParkAnim: ; 0xfc047
+	dw vTiles2 tile $14, AnimateWaterTile
+	dw NULL,  WaitTileAnimation
+	dw vTiles2 tile $5f, AnimateFountain
+	dw NULL,  WaitTileAnimation
+	dw NULL,  TileAnimationPalette
+	dw NULL,  WaitTileAnimation
+	dw NULL,  AnimateFlowerTile
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  StandingTileFrame8
+	dw NULL,  DoneTileAnimation
+; 0xfc073
+
+TilesetForestAnim: ; 0xfc073
+	dw NULL,  ForestTreeLeftAnimation
+	dw NULL,  ForestTreeRightAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  ForestTreeLeftAnimation2
+	dw NULL,  ForestTreeRightAnimation2
+	dw NULL,  AnimateFlowerTile
+	dw vTiles2 tile $14, AnimateWaterTile
+	dw NULL,  TileAnimationPalette
+	dw NULL,  StandingTileFrame8
+	dw NULL,  DoneTileAnimation
+; 0xfc0a3
+
+TilesetJohtoAnim: ; 0xfc0a3
+	dw vTiles2 tile $14, AnimateWaterTile
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  TileAnimationPalette
+	dw NULL,  WaitTileAnimation
+	dw NULL,  AnimateFlowerTile
+	dw WhirlpoolFrames1, AnimateWhirlpoolTile
+	dw WhirlpoolFrames2, AnimateWhirlpoolTile
+	dw WhirlpoolFrames3, AnimateWhirlpoolTile
+	dw WhirlpoolFrames4, AnimateWhirlpoolTile
+	dw NULL,  WaitTileAnimation
+	dw NULL,  StandingTileFrame8
+	dw NULL,  DoneTileAnimation
+; 0xfc0d7
+
+UnusedTilesetAnim_fc0d7: ; 0xfc0d7
+	dw vTiles2 tile $03, WriteTileToBuffer
+	dw wTileAnimBuffer, ScrollTileRightLeft
+	dw vTiles2 tile $03, WriteTileFromBuffer
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  AnimateFlowerTile
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  DoneTileAnimation
+; 0xfc103
+
+UnusedTilesetAnim_fc103: ; 0xfc103
+	dw vTiles2 tile $14, WriteTileToBuffer
+	dw wTileAnimBuffer, ScrollTileRightLeft
+	dw vTiles2 tile $14, WriteTileFromBuffer
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  DoneTileAnimation
+; 0xfc12f
+
+TilesetPortAnim: ; 0xfc12f
+	dw vTiles2 tile $14, AnimateWaterTile
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  TileAnimationPalette
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  StandingTileFrame8
+	dw NULL,  DoneTileAnimation
+; 0xfc15f
+
+TilesetEliteFourRoomAnim: ; 0xfc15f
+	dw NULL,  LavaBubbleAnim2
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  LavaBubbleAnim1
+	dw NULL,  WaitTileAnimation
+	dw NULL,  StandingTileFrame8
+	dw NULL,  DoneTileAnimation
+; 0xfc17f
+
+UnusedTilesetAnim_fc17f: ; 0xfc17f
+	dw vTiles2 tile $53, WriteTileToBuffer
+	dw wTileAnimBuffer, ScrollTileDown
+	dw wTileAnimBuffer, ScrollTileDown
+	dw vTiles2 tile $53, WriteTileFromBuffer
+	dw vTiles2 tile $03, WriteTileToBuffer
+	dw wTileAnimBuffer, ScrollTileRightLeft
+	dw vTiles2 tile $03, WriteTileFromBuffer
+	dw vTiles2 tile $53, WriteTileToBuffer
+	dw wTileAnimBuffer, ScrollTileDown
+	dw wTileAnimBuffer, ScrollTileDown
+	dw vTiles2 tile $53, WriteTileFromBuffer
+	dw NULL,  DoneTileAnimation
+; 0xfc1af
+
+UnusedTilesetAnim_fc1af: ; 0xfc1af
+	dw vTiles2 tile $54, WriteTileToBuffer
+	dw wTileAnimBuffer, ScrollTileDown
+	dw wTileAnimBuffer, ScrollTileDown
+	dw vTiles2 tile $54, WriteTileFromBuffer
+	dw NULL,  WaitTileAnimation
+	dw vTiles2 tile $03, WriteTileToBuffer
+	dw wTileAnimBuffer, ScrollTileRightLeft
+	dw vTiles2 tile $03, WriteTileFromBuffer
+	dw NULL,  WaitTileAnimation
+	dw vTiles2 tile $54, WriteTileToBuffer
+	dw wTileAnimBuffer, ScrollTileDown
+	dw wTileAnimBuffer, ScrollTileDown
+	dw vTiles2 tile $54, WriteTileFromBuffer
+	dw NULL,  DoneTileAnimation
+; 0xfc1e7
+
+TilesetCaveAnim: ; 0xfc1e7
+TilesetDarkCaveAnim: ; 0xfc1e7
+	dw vTiles2 tile $14, WriteTileToBuffer
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw wTileAnimBuffer, ScrollTileRightLeft
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw vTiles2 tile $14, WriteTileFromBuffer
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw NULL,  TileAnimationPalette
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw vTiles2 tile $40, WriteTileToBuffer
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw wTileAnimBuffer, ScrollTileDown
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw wTileAnimBuffer, ScrollTileDown
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw wTileAnimBuffer, ScrollTileDown
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw vTiles2 tile $40, WriteTileFromBuffer
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw NULL,  DoneTileAnimation
+; 0xfc233
+
+TilesetIcePathAnim: ; 0xfc233
+	dw vTiles2 tile $35, WriteTileToBuffer
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw wTileAnimBuffer, ScrollTileRightLeft
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw vTiles2 tile $35, WriteTileFromBuffer
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw NULL,  TileAnimationPalette
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw vTiles2 tile $31, WriteTileToBuffer
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw wTileAnimBuffer, ScrollTileDown
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw wTileAnimBuffer, ScrollTileDown
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw wTileAnimBuffer, ScrollTileDown
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw vTiles2 tile $31, WriteTileFromBuffer
+	dw NULL,  FlickeringCaveEntrancePalette
+	dw NULL,  DoneTileAnimation
+; 0xfc27f
+
+TilesetTowerAnim: ; 0xfc27f
+	dw TowerPillarTilePointer9,  AnimateTowerPillarTile
+	dw TowerPillarTilePointer10, AnimateTowerPillarTile
+	dw TowerPillarTilePointer7,  AnimateTowerPillarTile
+	dw TowerPillarTilePointer8,  AnimateTowerPillarTile
+	dw TowerPillarTilePointer5,  AnimateTowerPillarTile
+	dw TowerPillarTilePointer6,  AnimateTowerPillarTile
+	dw TowerPillarTilePointer3,  AnimateTowerPillarTile
+	dw TowerPillarTilePointer4,  AnimateTowerPillarTile
+	dw TowerPillarTilePointer1,  AnimateTowerPillarTile
+	dw TowerPillarTilePointer2,  AnimateTowerPillarTile
+	dw NULL,  StandingTileFrame
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  DoneTileAnimation
+; 0xfc2bf
+
+UnusedTilesetAnim_fc2bf: ; 0xfc2bf
+	dw vTiles2 tile $4f, WriteTileToBuffer
+	dw wTileAnimBuffer, ScrollTileRightLeft
+	dw vTiles2 tile $4f, WriteTileFromBuffer
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  DoneTileAnimation
+; 0xfc2e7
+
+TilesetBattleTowerOutsideAnim: ; 0xfc2e7
+TilesetHouseAnim: ; 0xfc2e7
+TilesetPlayersHouseAnim: ; 0xfc2e7
+TilesetPokecenterAnim: ; 0xfc2e7
+TilesetGateAnim: ; 0xfc2e7
+TilesetLabAnim: ; 0xfc2e7
+TilesetFacilityAnim: ; 0xfc2e7
+TilesetMartAnim: ; 0xfc2e7
+TilesetMansionAnim: ; 0xfc2e7
+TilesetGameCornerAnim: ; 0xfc2e7
+TilesetTraditionalHouseAnim: ; 0xfc2e7
+TilesetTrainStationAnim: ; 0xfc2e7
+TilesetChampionsRoomAnim: ; 0xfc2e7
+TilesetLighthouseAnim: ; 0xfc2e7
+TilesetPlayersRoomAnim: ; 0xfc2e7
+TilesetPokeComCenterAnim: ; 0xfc2e7
+TilesetBattleTowerAnim: ; 0xfc2e7
+TilesetRuinsOfAlphAnim: ; 0xfc2e7
+TilesetRadioTowerAnim: ; 0xfc2e7
+TilesetUndergroundAnim: ; 0xfc2e7
+TilesetBetaWordRoomAnim: ; 0xfc2e7
+TilesetHoOhWordRoomAnim: ; 0xfc2e7
+TilesetKabutoWordRoomAnim: ; 0xfc2e7
+TilesetOmanyteWordRoomAnim: ; 0xfc2e7
+TilesetAerodactylWordRoomAnim: ; 0xfc2e7
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  WaitTileAnimation
+	dw NULL,  DoneTileAnimation
+; 0xfc2fb
+
+DoneTileAnimation: ; fc2fb
+; Reset the animation command loop.
+	xor a
+	ld [hTileAnimFrame], a
+
+WaitTileAnimation: ; fc2fe
+; Do nothing this frame.
+	ret
+; fc2ff
+
+StandingTileFrame8: ; fc2ff
+	ld a, [wTileAnimationTimer]
+	inc a
+	and %111
+	ld [wTileAnimationTimer], a
+	ret
+; fc309
+
+
+ScrollTileRightLeft: ; fc309
+; Scroll right for 4 ticks, then left for 4 ticks.
+	ld a, [wTileAnimationTimer]
+	inc a
+	and %111
+	ld [wTileAnimationTimer], a
+	and %100
+	jr nz, ScrollTileLeft
+	jr ScrollTileRight
+; fc318
+
+ScrollTileUpDown: ; fc318
+; Scroll up for 4 ticks, then down for 4 ticks.
+	ld a, [wTileAnimationTimer]
+	inc a
+	and %111
+	ld [wTileAnimationTimer], a
+	and %100
+	jr nz, ScrollTileDown
+	jr ScrollTileUp
+; fc327
+
+ScrollTileLeft: ; fc327
+	ld h, d
+	ld l, e
+	ld c, 4
+.loop
+rept 4
+	ld a, [hl]
+	rlca
+	ld [hli], a
+endr
+	dec c
+	jr nz, .loop
+	ret
+; fc33b
+
+ScrollTileRight: ; fc33b
+	ld h, d
+	ld l, e
+	ld c, 4
+.loop
+rept 4
+	ld a, [hl]
+	rrca
+	ld [hli], a
+endr
+	dec c
+	jr nz, .loop
+	ret
+; fc34f
+
+ScrollTileUp: ; fc34f
+	ld h, d
+	ld l, e
+	ld d, [hl]
+	inc hl
+	ld e, [hl]
+	ld bc, TILE_WIDTH * 2 - 2
+	add hl, bc
+	ld a, TILE_WIDTH / 2
+.loop
+	ld c, [hl]
+	ld [hl], e
+	dec hl
+	ld b, [hl]
+	ld [hl], d
+	dec hl
+	ld e, [hl]
+	ld [hl], c
+	dec hl
+	ld d, [hl]
+	ld [hl], b
+	dec hl
+	dec a
+	jr nz, .loop
+	ret
+; fc36a
+
+ScrollTileDown: ; fc36a
+	ld h, d
+	ld l, e
+	ld de, TILE_WIDTH * 2 - 2
+	push hl
+	add hl, de
+	ld d, [hl]
+	inc hl
+	ld e, [hl]
+	pop hl
+	ld a, TILE_WIDTH / 2
+.loop
+	ld b, [hl]
+	ld [hl], d
+	inc hl
+	ld c, [hl]
+	ld [hl], e
+	inc hl
+	ld d, [hl]
+	ld [hl], b
+	inc hl
+	ld e, [hl]
+	ld [hl], c
+	inc hl
+	dec a
+	jr nz, .loop
+	ret
+; fc387
+
+
+AnimateFountain: ; fc387
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+	ld hl, .frames
+	ld a, [wTileAnimationTimer]
+	and %111
+	add a
+	add l
+	ld l, a
+	jr nc, .okay
+	inc h
+.okay
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld sp, hl
+	ld l, e
+	ld h, d
+	jp WriteTile
+
+.frames
+	dw .frame1
+	dw .frame2
+	dw .frame3
+	dw .frame4
+	dw .frame3
+	dw .frame4
+	dw .frame5
+	dw .frame1
+
+.frame1 INCBIN "gfx/tilesets/fountain/1.2bpp"
+.frame2 INCBIN "gfx/tilesets/fountain/2.2bpp"
+.frame3 INCBIN "gfx/tilesets/fountain/3.2bpp"
+.frame4 INCBIN "gfx/tilesets/fountain/4.2bpp"
+.frame5 INCBIN "gfx/tilesets/fountain/5.2bpp"
+; fc402
+
+
+AnimateWaterTile: ; fc402
+; Draw a water tile for the current frame in VRAM tile at de.
+
+; Save sp in bc (see WriteTile).
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+
+	ld a, [wTileAnimationTimer]
+
+; 4 tile graphics, updated every other frame.
+	and %110
+
+; 2 x 8 = 16 bytes per tile
+	add a
+	add a
+	add a
+
+	add LOW(WaterTileFrames)
+	ld l, a
+	ld a, 0
+	adc HIGH(WaterTileFrames)
+	ld h, a
+
+; The stack now points to the start of the tile for this frame.
+	ld sp, hl
+
+	ld l, e
+	ld h, d
+
+	jp WriteTile
+; fc41c
+
+WaterTileFrames: ; fc41c
+	INCBIN "gfx/tilesets/water/water.2bpp"
+; fc45c
+
+
+ForestTreeLeftAnimation: ; fc45c
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+
+; Only during the Celebi event.
+	ld a, [wCelebiEvent]
+	bit CELEBIEVENT_FOREST_IS_RESTLESS_F, a
+	jr nz, .asm_fc46c
+	ld hl, ForestTreeLeftFrames
+	jr .asm_fc47d
+
+.asm_fc46c
+	ld a, [wTileAnimationTimer]
+	call GetForestTreeFrame
+	add a
+	add a
+	add a
+	add LOW(ForestTreeLeftFrames)
+	ld l, a
+	ld a, 0
+	adc HIGH(ForestTreeLeftFrames)
+	ld h, a
+
+.asm_fc47d
+	ld sp, hl
+	ld hl, vTiles2 tile $0c
+	jp WriteTile
+; fc484
+
+
+ForestTreeLeftFrames: ; fc484
+	INCBIN "gfx/tilesets/forest-tree/1.2bpp"
+	INCBIN "gfx/tilesets/forest-tree/2.2bpp"
+; fc4a4
+
+ForestTreeRightFrames: ; fc4a4
+	INCBIN "gfx/tilesets/forest-tree/3.2bpp"
+	INCBIN "gfx/tilesets/forest-tree/4.2bpp"
+; fc4c4
+
+
+ForestTreeRightAnimation: ; fc4c4
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+
+; Only during the Celebi event.
+	ld a, [wCelebiEvent]
+	bit CELEBIEVENT_FOREST_IS_RESTLESS_F, a
+	jr nz, .asm_fc4d4
+	ld hl, ForestTreeRightFrames
+	jr .asm_fc4eb
+
+.asm_fc4d4
+	ld a, [wTileAnimationTimer]
+	call GetForestTreeFrame
+	add a
+	add a
+	add a
+	add LOW(ForestTreeLeftFrames)
+	ld l, a
+	ld a, 0
+	adc HIGH(ForestTreeLeftFrames)
+	ld h, a
+	push bc
+	ld bc, ForestTreeRightFrames - ForestTreeLeftFrames
+	add hl, bc
+	pop bc
+
+.asm_fc4eb
+	ld sp, hl
+	ld hl, vTiles2 tile $0f
+	jp WriteTile
+; fc4f2
+
+
+ForestTreeLeftAnimation2: ; fc4f2
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+
+; Only during the Celebi event.
+	ld a, [wCelebiEvent]
+	bit CELEBIEVENT_FOREST_IS_RESTLESS_F, a
+	jr nz, .asm_fc502
+	ld hl, ForestTreeLeftFrames
+	jr .asm_fc515
+
+.asm_fc502
+	ld a, [wTileAnimationTimer]
+	call GetForestTreeFrame
+	xor 2
+	add a
+	add a
+	add a
+	add LOW(ForestTreeLeftFrames)
+	ld l, a
+	ld a, 0
+	adc HIGH(ForestTreeLeftFrames)
+	ld h, a
+
+.asm_fc515
+	ld sp, hl
+	ld hl, vTiles2 tile $0c
+	jp WriteTile
+; fc51c
+
+
+ForestTreeRightAnimation2: ; fc51c
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+
+; Only during the Celebi event.
+	ld a, [wCelebiEvent]
+	bit CELEBIEVENT_FOREST_IS_RESTLESS_F, a
+	jr nz, .asm_fc52c
+	ld hl, ForestTreeRightFrames
+	jr .asm_fc545
+
+.asm_fc52c
+	ld a, [wTileAnimationTimer]
+	call GetForestTreeFrame
+	xor 2
+	add a
+	add a
+	add a
+	add LOW(ForestTreeLeftFrames)
+	ld l, a
+	ld a, 0
+	adc HIGH(ForestTreeLeftFrames)
+	ld h, a
+	push bc
+	ld bc, ForestTreeRightFrames - ForestTreeLeftFrames
+	add hl, bc
+	pop bc
+
+.asm_fc545
+	ld sp, hl
+	ld hl, vTiles2 tile $0f
+	jp WriteTile
+; fc54c
+
+
+GetForestTreeFrame: ; fc54c
+; Return 0 if a is even, or 2 if odd.
+	and a
+	jr z, .even
+	cp 1
+	jr z, .odd
+	cp 2
+	jr z, .even
+	cp 3
+	jr z, .odd
+	cp 4
+	jr z, .even
+	cp 5
+	jr z, .odd
+	cp 6
+	jr z, .even
+.odd
+	ld a, 2
+	scf
+	ret
+.even
+	xor a
+	ret
+; fc56d
+
+
+AnimateFlowerTile: ; fc56d
+; No parameters.
+
+; Save sp in bc (see WriteTile).
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+
+; Alternate tile graphic every other frame
+	ld a, [wTileAnimationTimer]
+	and %10
+	ld e, a
+
+; CGB has different color mappings for flowers.
+	ld a, [hCGB]
+	and 1
+
+	add e
+	swap a
+	ld e, a
+	ld d, 0
+	ld hl, FlowerTileFrames
+	add hl, de
+	ld sp, hl
+
+	ld hl, vTiles2 tile $03
+
+	jp WriteTile
+; fc58c
+
+FlowerTileFrames: ; fc58c
+	INCBIN "gfx/tilesets/flower/dmg_1.2bpp"
+	INCBIN "gfx/tilesets/flower/cgb_1.2bpp"
+	INCBIN "gfx/tilesets/flower/dmg_2.2bpp"
+	INCBIN "gfx/tilesets/flower/cgb_2.2bpp"
+; fc5cc
+
+
+LavaBubbleAnim1: ; fc5cc
+; Splash in the bottom-right corner of the fountain.
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+	ld a, [wTileAnimationTimer]
+	and %110
+	srl a
+	inc a
+	inc a
+	and %011
+	swap a
+	ld e, a
+	ld d, 0
+	ld hl, LavaBubbleFrames
+	add hl, de
+	ld sp, hl
+	ld hl, vTiles2 tile $5b
+	jp WriteTile
+; fc5eb
+
+
+LavaBubbleAnim2: ; fc5eb
+; Splash in the top-left corner of the fountain.
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+	ld a, [wTileAnimationTimer]
+	and %110
+	add a
+	add a
+	add a
+	ld e, a
+	ld d, 0
+	ld hl, LavaBubbleFrames
+	add hl, de
+	ld sp, hl
+	ld hl, vTiles2 tile $38
+	jp WriteTile
+; fc605
+
+
+LavaBubbleFrames: ; fc605
+	INCBIN "gfx/tilesets/lava/1.2bpp"
+	INCBIN "gfx/tilesets/lava/2.2bpp"
+	INCBIN "gfx/tilesets/lava/3.2bpp"
+	INCBIN "gfx/tilesets/lava/4.2bpp"
+; fc645
+
+
+AnimateTowerPillarTile: ; fc645
+; Read from struct at de:
+; 	Destination (VRAM)
+;	Address of the first tile in the frame array
+
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+
+	ld a, [wTileAnimationTimer]
+	and %111
+
+; Get frame index a
+	ld hl, .frames
+	add l
+	ld l, a
+	ld a, 0
+	adc h
+	ld h, a
+	ld a, [hl]
+
+; Destination
+	ld l, e
+	ld h, d
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	inc hl
+
+; Add the frame index to the starting address
+	add [hl]
+	inc hl
+	ld h, [hl]
+	ld l, a
+	ld a, 0
+	adc h
+	ld h, a
+
+	ld sp, hl
+	ld l, e
+	ld h, d
+	jr WriteTile
+
+.frames
+	db $00, $10, $20, $30, $40, $30, $20, $10
+; fc673
+
+
+StandingTileFrame: ; fc673
+	ld hl, wTileAnimationTimer
+	inc [hl]
+	ret
+; fc678
+
+
+AnimateWhirlpoolTile: ; fc678
+; Update whirlpool tile using struct at de.
+
+; Struct:
+; 	VRAM address
+;	Address of the first tile
+
+; Only does one of 4 tiles at a time.
+
+; Save sp in bc (see WriteTile).
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+
+; de = VRAM address
+	ld l, e
+	ld h, d
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	inc hl
+; Tile address is now at hl.
+
+; Get the tile for this frame.
+	ld a, [wTileAnimationTimer]
+	and %11 ; 4 frames x2
+	swap a  ; * 16 bytes per tile
+
+	add [hl]
+	inc hl
+	ld h, [hl]
+	ld l, a
+	ld a, 0
+	adc h
+	ld h, a
+
+; The stack now points to the desired frame.
+	ld sp, hl
+
+	ld l, e
+	ld h, d
+
+	jr WriteTile
+; fc696
+
+
+WriteTileFromBuffer: ; fc696
+; Write tiledata at wTileAnimBuffer to de.
+; wTileAnimBuffer is loaded to sp for WriteTile.
+
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+
+	ld hl, wTileAnimBuffer
+	ld sp, hl
+
+	ld h, d
+	ld l, e
+	jr WriteTile
+; fc6a2
+
+
+WriteTileToBuffer: ; fc6a2
+; Write tiledata de to wTileAnimBuffer.
+; de is loaded to sp for WriteTile.
+
+	ld hl, sp+0
+	ld b, h
+	ld c, l
+
+	ld h, d
+	ld l, e
+	ld sp, hl
+
+	ld hl, wTileAnimBuffer
+
+	; fallthrough
+
+WriteTile: ; fc6ac
+; Write one 8x8 tile ($10 bytes) from sp to hl.
+
+; Warning: sp is saved in bc so we can abuse pop.
+; sp is restored to address bc. Save sp in bc before calling.
+
+	pop de
+	ld [hl], e
+	inc hl
+	ld [hl], d
+
+rept 7
+	pop de
+	inc hl
+	ld [hl], e
+	inc hl
+	ld [hl], d
+endr
+
+; restore sp
+	ld h, b
+	ld l, c
+	ld sp, hl
+	ret
+; fc6d7
+
+
+TileAnimationPalette: ; fc6d7
+; Transition between color values 0-2 for color 0 in palette 3.
+
+; No palette changes on DMG.
+	ld a, [hCGB]
+	and a
+	ret z
+
+; We don't want to mess with non-standard palettes.
+	ld a, [rBGP] ; BGP
+	cp %11100100
+	ret nz
+
+; Only update on even frames.
+	ld a, [wTileAnimationTimer]
+	ld l, a
+	and 1 ; odd
+	ret nz
+
+; Ready for BGPD input...
+
+	ld a, (1 << rBGPI_AUTO_INCREMENT) palette PAL_BG_WATER
+	ld [rBGPI], a
+
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+
+; Update color 0 in order 0 1 2 1
+	ld a, l
+	and %110 ; frames 0 2 4 6
+	jr z, .color0
+	cp %100 ; frame 4
+	jr z, .color2
+
+.color1
+	ld hl, wBGPals1 palette PAL_BG_WATER color 1
+	ld a, [hli]
+	ld [rBGPD], a
+	ld a, [hli]
+	ld [rBGPD], a
+	jr .end
+
+.color0
+	ld hl, wBGPals1 palette PAL_BG_WATER color 0
+	ld a, [hli]
+	ld [rBGPD], a
+	ld a, [hli]
+	ld [rBGPD], a
+	jr .end
+
+.color2
+	ld hl, wBGPals1 palette PAL_BG_WATER color 2
+	ld a, [hli]
+	ld [rBGPD], a
+	ld a, [hli]
+	ld [rBGPD], a
+
+.end
+	pop af
+	ld [rSVBK], a
+	ret
+; fc71e
+
+
+FlickeringCaveEntrancePalette: ; fc71e
+; No palette changes on DMG.
+	ld a, [hCGB]
+	and a
+	ret z
+; We don't want to mess with non-standard palettes.
+	ld a, [rBGP]
+	cp %11100100
+	ret nz
+; We only want to be here if we're in a dark cave.
+	ld a, [wTimeOfDayPalset]
+	cp %11111111 ; 3,3,3,3
+	ret nz
+
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+; Ready for BGPD input...
+	ld a, (1 << rBGPI_AUTO_INCREMENT) palette PAL_BG_YELLOW
+	ld [rBGPI], a
+	ld a, [hVBlankCounter]
+	and %10
+	jr nz, .bit1set
+	ld hl, wBGPals1 palette PAL_BG_YELLOW
+	jr .okay
+
+.bit1set
+	ld hl, wBGPals1 palette PAL_BG_YELLOW color 1
+
+.okay
+	ld a, [hli]
+	ld [rBGPD], a
+	ld a, [hli]
+	ld [rBGPD], a
+
+	pop af
+	ld [rSVBK], a
+	ret
+; fc750
+
+
+TowerPillarTilePointer1:  dw vTiles2 tile $2d, TowerPillarTile1
+TowerPillarTilePointer2:  dw vTiles2 tile $2f, TowerPillarTile2
+TowerPillarTilePointer3:  dw vTiles2 tile $3d, TowerPillarTile3
+TowerPillarTilePointer4:  dw vTiles2 tile $3f, TowerPillarTile4
+TowerPillarTilePointer5:  dw vTiles2 tile $3c, TowerPillarTile5
+TowerPillarTilePointer6:  dw vTiles2 tile $2c, TowerPillarTile6
+TowerPillarTilePointer7:  dw vTiles2 tile $4d, TowerPillarTile7
+TowerPillarTilePointer8:  dw vTiles2 tile $4f, TowerPillarTile8
+TowerPillarTilePointer9:  dw vTiles2 tile $5d, TowerPillarTile9
+TowerPillarTilePointer10: dw vTiles2 tile $5f, TowerPillarTile10
+
+TowerPillarTile1:  INCBIN "gfx/tilesets/tower-pillar/1.2bpp"
+TowerPillarTile2:  INCBIN "gfx/tilesets/tower-pillar/2.2bpp"
+TowerPillarTile3:  INCBIN "gfx/tilesets/tower-pillar/3.2bpp"
+TowerPillarTile4:  INCBIN "gfx/tilesets/tower-pillar/4.2bpp"
+TowerPillarTile5:  INCBIN "gfx/tilesets/tower-pillar/5.2bpp"
+TowerPillarTile6:  INCBIN "gfx/tilesets/tower-pillar/6.2bpp"
+TowerPillarTile7:  INCBIN "gfx/tilesets/tower-pillar/7.2bpp"
+TowerPillarTile8:  INCBIN "gfx/tilesets/tower-pillar/8.2bpp"
+TowerPillarTile9:  INCBIN "gfx/tilesets/tower-pillar/9.2bpp"
+TowerPillarTile10: INCBIN "gfx/tilesets/tower-pillar/10.2bpp"
+; fca98
+
+
+WhirlpoolFrames1: dw vTiles2 tile $32, WhirlpoolTiles1
+WhirlpoolFrames2: dw vTiles2 tile $33, WhirlpoolTiles2
+WhirlpoolFrames3: dw vTiles2 tile $42, WhirlpoolTiles3
+WhirlpoolFrames4: dw vTiles2 tile $43, WhirlpoolTiles4
+; fcaa8
+
+WhirlpoolTiles1: INCBIN "gfx/tilesets/whirlpool/1.2bpp"
+WhirlpoolTiles2: INCBIN "gfx/tilesets/whirlpool/2.2bpp"
+WhirlpoolTiles3: INCBIN "gfx/tilesets/whirlpool/3.2bpp"
+WhirlpoolTiles4: INCBIN "gfx/tilesets/whirlpool/4.2bpp"
+; fcba8
--- /dev/null
+++ b/engine/gfx/tileset_palettes.asm
@@ -1,0 +1,151 @@
+LoadSpecialMapPalette: ; 494ac
+	ld a, [wMapTileset]
+	cp TILESET_POKECOM_CENTER
+	jr z, .pokecom_2f
+	cp TILESET_BATTLE_TOWER
+	jr z, .battle_tower
+	cp TILESET_ICE_PATH
+	jr z, .ice_path
+	cp TILESET_HOUSE
+	jr z, .house
+	cp TILESET_RADIO_TOWER
+	jr z, .radio_tower
+	cp TILESET_MANSION
+	jr z, .mansion_mobile
+	jr .do_nothing
+
+.pokecom_2f
+	call LoadPokeComPalette
+	scf
+	ret
+
+.battle_tower
+	call LoadBattleTowerPalette
+	scf
+	ret
+
+.ice_path
+	ld a, [wEnvironment]
+	and $7
+	cp INDOOR ; Hall of Fame
+	jr z, .do_nothing
+	call LoadIcePathPalette
+	scf
+	ret
+
+.house
+	call LoadHousePalette
+	scf
+	ret
+
+.radio_tower
+	call LoadRadioTowerPalette
+	scf
+	ret
+
+.mansion_mobile
+	call LoadMansionPalette
+	scf
+	ret
+
+.do_nothing
+	and a
+	ret
+; 494f2
+
+LoadPokeComPalette: ; 494f2
+	ld a, BANK(wBGPals1)
+	ld de, wBGPals1
+	ld hl, PokeComPalette
+	ld bc, 8 palettes
+	call FarCopyWRAM
+	ret
+; 49501
+
+PokeComPalette: ; 49501
+INCLUDE "gfx/tilesets/pokecom_center.pal"
+; 49541
+
+LoadBattleTowerPalette: ; 49541
+	ld a, BANK(wBGPals1)
+	ld de, wBGPals1
+	ld hl, BattleTowerPalette
+	ld bc, 8 palettes
+	call FarCopyWRAM
+	ret
+; 49550
+
+BattleTowerPalette: ; 49550
+INCLUDE "gfx/tilesets/battle_tower.pal"
+; 49590
+
+LoadIcePathPalette: ; 49590
+	ld a, BANK(wBGPals1)
+	ld de, wBGPals1
+	ld hl, IcePathPalette
+	ld bc, 8 palettes
+	call FarCopyWRAM
+	ret
+; 4959f
+
+IcePathPalette: ; 4959f
+INCLUDE "gfx/tilesets/ice_path.pal"
+; 495df
+
+LoadHousePalette: ; 495df
+	ld a, BANK(wBGPals1)
+	ld de, wBGPals1
+	ld hl, HousePalette
+	ld bc, 8 palettes
+	call FarCopyWRAM
+	ret
+; 495ee
+
+HousePalette: ; 495ee
+INCLUDE "gfx/tilesets/house.pal"
+; 4962e
+
+LoadRadioTowerPalette: ; 4962e
+	ld a, BANK(wBGPals1)
+	ld de, wBGPals1
+	ld hl, RadioTowerPalette
+	ld bc, 8 palettes
+	call FarCopyWRAM
+	ret
+; 4963d
+
+RadioTowerPalette: ; 4963d
+INCLUDE "gfx/tilesets/radio_tower.pal"
+; 4967d
+
+MansionPalette1: ; 4967d
+INCLUDE "gfx/tilesets/mansion_1.pal"
+; 496c5
+
+LoadMansionPalette: ; 496c5
+	ld a, BANK(wBGPals1)
+	ld de, wBGPals1
+	ld hl, MansionPalette1
+	ld bc, 8 palettes
+	call FarCopyWRAM
+	ld a, BANK(wBGPals1)
+	ld de, wBGPals1 palette PAL_BG_YELLOW
+	ld hl, MansionPalette2
+	ld bc, 1 palettes
+	call FarCopyWRAM
+	ld a, BANK(wBGPals1)
+	ld de, wBGPals1 palette PAL_BG_WATER
+	ld hl, MansionPalette1 + 6 palettes
+	ld bc, 1 palettes
+	call FarCopyWRAM
+	ld a, BANK(wBGPals1)
+	ld de, wBGPals1 palette PAL_BG_ROOF
+	ld hl, MansionPalette1 + 8 palettes
+	ld bc, 1 palettes
+	call FarCopyWRAM
+	ret
+; 496fe
+
+MansionPalette2: ; 496fe
+INCLUDE "gfx/tilesets/mansion_2.pal"
+; 49706
--- /dev/null
+++ b/engine/gfx/timeofdaypals.asm
@@ -1,0 +1,415 @@
+DummyPredef35: ; 8c000
+DummyPredef36:
+	ret
+
+UpdateTimeOfDayPal:: ; 8c001
+	call UpdateTime
+	ld a, [wTimeOfDay]
+	ld [wCurTimeOfDay], a
+	call GetTimePalette
+	ld [wTimeOfDayPal], a
+	ret
+; 8c011
+
+
+_TimeOfDayPals:: ; 8c011
+; return carry if pals are changed
+
+; forced pals?
+	ld hl, wTimeOfDayPalFlags
+	bit 7, [hl]
+	jr nz, .dontchange
+
+; do we need to bother updating?
+	ld a, [wTimeOfDay]
+	ld hl, wCurTimeOfDay
+	cp [hl]
+	jr z, .dontchange
+
+; if so, the time of day has changed
+	ld a, [wTimeOfDay]
+	ld [wCurTimeOfDay], a
+
+; get palette id
+	call GetTimePalette
+
+; same palette as before?
+	ld hl, wTimeOfDayPal
+	cp [hl]
+	jr z, .dontchange
+
+; update palette id
+	ld [wTimeOfDayPal], a
+
+; save bg palette 7
+	ld hl, wBGPals1 palette PAL_BG_TEXT
+
+; save wram bank
+	ld a, [rSVBK]
+	ld b, a
+
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+
+; push palette
+	ld c, NUM_PAL_COLORS
+.push
+	ld d, [hl]
+	inc hl
+	ld e, [hl]
+	inc hl
+	push de
+	dec c
+	jr nz, .push
+
+; restore wram bank
+	ld a, b
+	ld [rSVBK], a
+
+
+; update sgb pals
+	ld b, SCGB_MAPPALS
+	call GetSGBLayout
+
+
+; restore bg palette 7
+	ld hl, wOBPals1 - 1 ; last byte in wBGPals1
+
+; save wram bank
+	ld a, [rSVBK]
+	ld d, a
+
+	ld a, BANK(wOBPals1)
+	ld [rSVBK], a
+
+; pop palette
+	ld e, NUM_PAL_COLORS
+.pop
+	pop bc
+	ld [hl], c
+	dec hl
+	ld [hl], b
+	dec hl
+	dec e
+	jr nz, .pop
+
+; restore wram bank
+	ld a, d
+	ld [rSVBK], a
+
+; update palettes
+	call _UpdateTimePals
+	call DelayFrame
+
+; successful change
+	scf
+	ret
+
+.dontchange
+; no change occurred
+	and a
+	ret
+; 8c070
+
+
+_UpdateTimePals:: ; 8c070
+	ld c, $9 ; normal
+	call GetTimePalFade
+	call DmgToCgbTimePals
+	ret
+; 8c079
+
+FadeInPalettes:: ; 8c079
+	ld c, $12
+	call GetTimePalFade
+	ld b, $4
+	call ConvertTimePalsDecHL
+	ret
+; 8c084
+
+FadeOutPalettes:: ; 8c084
+	call FillWhiteBGColor
+	ld c, $9
+	call GetTimePalFade
+	ld b, $4
+	call ConvertTimePalsIncHL
+	ret
+; 8c092
+
+BattleTowerFade: ; 8c092
+	call FillWhiteBGColor
+	ld c, $9
+	call GetTimePalFade
+	ld b, $4
+.asm_8c09c
+	call DmgToCgbTimePals
+	inc hl
+	inc hl
+	inc hl
+	ld c, $7
+	call DelayFrames
+	dec b
+	jr nz, .asm_8c09c
+	ret
+; 8c0ab
+
+FadeInQuickly: ; 8c0ab
+	ld c, $0
+	call GetTimePalFade
+	ld b, $4
+	call ConvertTimePalsIncHL
+	ret
+; 8c0b6
+
+FadeBlackQuickly: ; 8c0b6
+	ld c, $9
+	call GetTimePalFade
+	ld b, $4
+	call ConvertTimePalsDecHL
+	ret
+; 8c0c1
+
+
+FillWhiteBGColor: ; 8c0c1
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+
+	ld hl, wBGPals1
+	ld a, [hli]
+	ld e, a
+	ld a, [hli]
+	ld d, a
+	ld hl, wBGPals1 + 1 palettes
+	ld c, 6
+.loop
+	ld a, e
+	ld [hli], a
+	ld a, d
+	ld [hli], a
+rept 6
+	inc hl
+endr
+	dec c
+	jr nz, .loop
+
+	pop af
+	ld [rSVBK], a
+	ret
+; 8c0e5
+
+ReplaceTimeOfDayPals: ; 8c0e5
+	ld hl, .BrightnessLevels
+	ld a, [wMapTimeOfDay]
+	cp $4 ; Dark cave, needs Flash
+	jr z, .DarkCave
+	and $7
+	add l
+	ld l, a
+	ld a, $0
+	adc h
+	ld h, a
+	ld a, [hl]
+	ld [wTimeOfDayPalset], a
+	ret
+
+.DarkCave:
+	ld a, [wStatusFlags]
+	bit STATUSFLAGS_FLASH_F, a
+	jr nz, .UsedFlash
+	ld a, %11111111 ; 3, 3, 3, 3
+	ld [wTimeOfDayPalset], a
+	ret
+
+.UsedFlash:
+	ld a, %10101010 ; 2, 2, 2, 2
+	ld [wTimeOfDayPalset], a
+	ret
+; 8c10f (23:410f)
+
+.BrightnessLevels: ; 8c10f
+	dc 3, 2, 1, 0
+	dc 1, 1, 1, 1
+	dc 2, 2, 2, 2
+	dc 0, 0, 0, 0
+	dc 3, 3, 3, 3
+	dc 3, 2, 1, 0
+	dc 3, 2, 1, 0
+	dc 3, 2, 1, 0
+; 8c117
+
+GetTimePalette: ; 8c117
+	ld a, [wTimeOfDay]
+	ld e, a
+	ld d, 0
+	ld hl, .TimePalettes
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+; 8c126
+
+.TimePalettes:
+	dw .MorningPalette
+	dw .DayPalette
+	dw .NitePalette
+	dw .DarknessPalette
+
+.MorningPalette:
+	ld a, [wTimeOfDayPalset]
+	and %00000011 ; 0
+	ret
+
+.DayPalette:
+	ld a, [wTimeOfDayPalset]
+	and %00001100 ; 1
+	srl a
+	srl a
+	ret
+
+.NitePalette:
+	ld a, [wTimeOfDayPalset]
+	and %00110000 ; 2
+	swap a
+	ret
+
+.DarknessPalette:
+	ld a, [wTimeOfDayPalset]
+	and %11000000 ; 3
+	rlca
+	rlca
+	ret
+; 8c14e
+
+
+DmgToCgbTimePals: ; 8c14e
+	push hl
+	push de
+	ld a, [hli]
+	call DmgToCgbBGPals
+	ld a, [hli]
+	ld e, a
+	ld a, [hli]
+	ld d, a
+	call DmgToCgbObjPals
+	pop de
+	pop hl
+	ret
+; 8c15e
+
+ConvertTimePalsIncHL: ; 8c15e
+.loop
+	call DmgToCgbTimePals
+	inc hl
+	inc hl
+	inc hl
+	ld c, 2
+	call DelayFrames
+	dec b
+	jr nz, .loop
+	ret
+; 8c16d
+
+ConvertTimePalsDecHL: ; 8c16d
+.loop
+	call DmgToCgbTimePals
+	dec hl
+	dec hl
+	dec hl
+	ld c, 2
+	call DelayFrames
+	dec b
+	jr nz, .loop
+	ret
+; 8c17c
+
+
+GetTimePalFade: ; 8c17c
+; check cgb
+	ld a, [hCGB]
+	and a
+	jr nz, .cgb
+
+; else: dmg
+
+; index
+	ld a, [wTimeOfDayPal]
+	and %11
+
+; get fade table
+	push bc
+	ld c, a
+	ld b, $0
+	ld hl, .dmgfades
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	pop bc
+
+; get place in fade table
+	ld b, $0
+	add hl, bc
+	ret
+
+.cgb
+	ld hl, .cgbfade
+	ld b, $0
+	add hl, bc
+	ret
+
+.dmgfades
+	dw .morn
+	dw .day
+	dw .nite
+	dw .darkness
+
+.morn
+	db %11111111, %11111111, %11111111
+	db %11111110, %11111110, %11111110
+	db %11111001, %11100100, %11100100
+	db %11100100, %11010000, %11010000
+	db %10010000, %10000000, %10000000
+	db %01000000, %01000000, %01000000
+	db %00000000, %00000000, %00000000
+
+.day
+	db %11111111, %11111111, %11111111
+	db %11111110, %11111110, %11111110
+	db %11111001, %11100100, %11100100
+	db %11100100, %11010000, %11010000
+	db %10010000, %10000000, %10000000
+	db %01000000, %01000000, %01000000
+	db %00000000, %00000000, %00000000
+
+.nite
+	db %11111111, %11111111, %11111111
+	db %11111110, %11111110, %11111110
+	db %11111001, %11100100, %11100100
+	db %11101001, %11010000, %11010000
+	db %10010000, %10000000, %10000000
+	db %01000000, %01000000, %01000000
+	db %00000000, %00000000, %00000000
+
+.darkness
+	db %11111111, %11111111, %11111111
+	db %11111110, %11111110, %11111111
+	db %11111110, %11100100, %11111111
+	db %11111101, %11010000, %11111111
+	db %11111101, %10000000, %11111111
+	db %00000000, %01000000, %00000000
+	db %00000000, %00000000, %00000000
+
+.cgbfade
+	db %11111111, %11111111, %11111111
+	db %11111110, %11111110, %11111110
+	db %11111001, %11111001, %11111001
+	db %11100100, %11100100, %11100100
+	db %10010000, %10010000, %10010000
+	db %01000000, %01000000, %01000000
+	db %00000000, %00000000, %00000000
+; 8c20f
--- /dev/null
+++ b/engine/gfx/trade_animation.asm
@@ -1,0 +1,1646 @@
+TRADEANIM_RIGHT_ARROW EQU $ed
+TRADEANIM_LEFT_ARROW  EQU $ee
+
+; TradeAnim_TubeAnimJumptable.Jumptable indexes
+	const_def
+	const TRADEANIMSTATE_0 ; 0
+	const TRADEANIMSTATE_1 ; 1
+	const TRADEANIMSTATE_2 ; 2
+	const TRADEANIMSTATE_3 ; 3
+TRADEANIMJUMPTABLE_LENGTH EQU const_value
+
+TradeAnimation: ; 28f24
+	xor a
+	ld [wcf66], a
+	ld hl, wPlayerTrademonSenderName
+	ld de, wOTTrademonSenderName
+	call LinkTradeAnim_LoadTradePlayerNames
+	ld hl, wPlayerTrademonSpecies
+	ld de, wOTTrademonSpecies
+	call LinkTradeAnim_LoadTradeMonSpecies
+	ld de, .script
+	jr RunTradeAnimScript
+
+.script
+	tradeanim_setup_givemon_scroll
+	tradeanim_show_givemon_data
+	tradeanim_do_givemon_scroll
+	tradeanim_wait_80
+	tradeanim_wait_96
+	tradeanim_poof
+	tradeanim_rocking_ball
+	tradeanim_enter_link_tube
+	tradeanim_wait_anim
+	tradeanim_bulge_through_tube
+	tradeanim_wait_anim
+	tradeanim_textbox_scroll
+	tradeanim_give_trademon_sfx
+	tradeanim_tube_to_ot
+	tradeanim_sent_to_ot_text
+	tradeanim_scroll_out_right
+
+	tradeanim_ot_sends_text_1
+	tradeanim_ot_bids_farewell
+	tradeanim_wait_40
+	tradeanim_scroll_out_right
+	tradeanim_get_trademon_sfx
+	tradeanim_tube_to_player
+	tradeanim_enter_link_tube
+	tradeanim_drop_ball
+	tradeanim_exit_link_tube
+	tradeanim_wait_anim
+	tradeanim_show_getmon_data
+	tradeanim_poof
+	tradeanim_wait_anim
+	tradeanim_frontpic_scroll
+	tradeanim_animate_frontpic
+	tradeanim_wait_80_if_ot_egg
+	tradeanim_textbox_scroll
+	tradeanim_take_care_of_text
+	tradeanim_scroll_out_right
+	tradeanim_end
+
+TradeAnimationPlayer2: ; 28f63
+	xor a
+	ld [wcf66], a
+	ld hl, wOTTrademonSenderName
+	ld de, wPlayerTrademonSenderName
+	call LinkTradeAnim_LoadTradePlayerNames
+	ld hl, wOTTrademonSpecies
+	ld de, wPlayerTrademonSpecies
+	call LinkTradeAnim_LoadTradeMonSpecies
+	ld de, .script
+	jr RunTradeAnimScript
+
+.script
+	tradeanim_ot_sends_text_2
+	tradeanim_ot_bids_farewell
+	tradeanim_wait_40
+	tradeanim_scroll_out_right
+	tradeanim_get_trademon_sfx
+	tradeanim_tube_to_ot
+	tradeanim_enter_link_tube
+	tradeanim_drop_ball
+	tradeanim_exit_link_tube
+	tradeanim_wait_anim
+	tradeanim_show_getmon_data
+	tradeanim_poof
+	tradeanim_wait_anim
+	tradeanim_frontpic_scroll
+	tradeanim_animate_frontpic
+	tradeanim_wait_180_if_ot_egg
+	tradeanim_textbox_scroll
+	tradeanim_take_care_of_text
+	tradeanim_scroll_out_right
+
+	tradeanim_setup_givemon_scroll
+	tradeanim_show_givemon_data
+	tradeanim_do_givemon_scroll
+	tradeanim_wait_40
+	tradeanim_poof
+	tradeanim_rocking_ball
+	tradeanim_enter_link_tube
+	tradeanim_wait_anim
+	tradeanim_bulge_through_tube
+	tradeanim_wait_anim
+	tradeanim_textbox_scroll
+	tradeanim_give_trademon_sfx
+	tradeanim_tube_to_player
+	tradeanim_sent_to_ot_text
+	tradeanim_scroll_out_right
+	tradeanim_end
+
+RunTradeAnimScript: ; 28fa1
+	ld hl, wTradeAnimAddress
+	ld [hl], e
+	inc hl
+	ld [hl], d
+	ld a, [hMapAnims]
+	push af
+	xor a
+	ld [hMapAnims], a
+	ld hl, wVramState
+	ld a, [hl]
+	push af
+	res 0, [hl]
+	ld hl, wOptions
+	ld a, [hl]
+	push af
+	set 4, [hl]
+	call .TradeAnimLayout
+	ld a, [wcf66]
+	and a
+	jr nz, .anim_loop
+	ld de, MUSIC_EVOLUTION
+	call PlayMusic2
+.anim_loop
+	call DoTradeAnimation
+	jr nc, .anim_loop
+	pop af
+	ld [wOptions], a
+	pop af
+	ld [wVramState], a
+	pop af
+	ld [hMapAnims], a
+	ret
+
+; 28fdb
+
+.TradeAnimLayout: ; 28fdb
+	xor a
+	ld [wJumptableIndex], a
+	call ClearBGPalettes
+	call ClearSprites
+	call ClearTileMap
+	call DisableLCD
+	call LoadFontsBattleExtra
+	callfar ClearSpriteAnims
+	ld a, [hCGB]
+	and a
+	jr z, .NotCGB
+	ld a, $1
+	ld [rVBK], a
+	ld hl, vTiles0
+	ld bc, sScratch - vTiles0
+	xor a
+	call ByteFill
+	ld a, $0
+	ld [rVBK], a
+
+.NotCGB:
+	hlbgcoord 0, 0
+	ld bc, sScratch - vBGMap0
+	ld a, " "
+	call ByteFill
+	ld hl, TradeGameBoyLZ
+	ld de, vTiles2 tile $31
+	call Decompress
+	ld hl, TradeArrowGFX
+	ld de, vTiles0 tile TRADEANIM_RIGHT_ARROW
+	ld bc, 1 tiles
+	ld a, BANK(TradeArrowGFX)
+	call FarCopyBytes
+	ld hl, TradeArrowGFX + 1 tiles
+	ld de, vTiles0 tile TRADEANIM_LEFT_ARROW
+	ld bc, 1 tiles
+	ld a, BANK(TradeArrowGFX)
+	call FarCopyBytes
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	farcall GetTrademonFrontpic
+	call EnableLCD
+	call LoadTradeBallAndCableGFX
+	ld a, [wPlayerTrademonSpecies]
+	ld hl, wPlayerTrademonDVs
+	ld de, vTiles0
+	call TradeAnim_GetFrontpic
+	ld a, [wOTTrademonSpecies]
+	ld hl, wOTTrademonDVs
+	ld de, vTiles0 tile $31
+	call TradeAnim_GetFrontpic
+	ld a, [wPlayerTrademonSpecies]
+	ld de, wPlayerTrademonSpeciesName
+	call TradeAnim_GetNickname
+	ld a, [wOTTrademonSpecies]
+	ld de, wOTTrademonSpeciesName
+	call TradeAnim_GetNickname
+	call TradeAnim_NormalPals
+	ret
+
+; 29082
+
+DoTradeAnimation: ; 29082
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .finished
+	call .DoTradeAnimCommand
+	callfar PlaySpriteAnimations
+	ld hl, wcf65
+	inc [hl]
+	call DelayFrame
+	and a
+	ret
+
+.finished
+	call LoadStandardFont
+	scf
+	ret
+
+; 290a0
+
+.DoTradeAnimCommand: ; 290a0
+	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
+; 290af
+
+.JumpTable: ; 290af
+; entries correspond to macros/scripts/trade_anims.asm enumeration
+	dw TradeAnim_AdvanceScriptPointer ; 00
+	dw TradeAnim_ShowGivemonData      ; 01
+	dw TradeAnim_ShowGetmonData       ; 02
+	dw TradeAnim_EnterLinkTube1       ; 03
+	dw TradeAnim_EnterLinkTube2       ; 04
+	dw TradeAnim_ExitLinkTube         ; 05
+	dw TradeAnim_TubeToOT1            ; 06
+	dw TradeAnim_TubeToOT2            ; 07
+	dw TradeAnim_TubeToOT3            ; 08
+	dw TradeAnim_TubeToOT4            ; 09
+	dw TradeAnim_TubeToOT5            ; 0a
+	dw TradeAnim_TubeToOT6            ; 0b
+	dw TradeAnim_TubeToOT7            ; 0c
+	dw TradeAnim_TubeToOT8            ; 0d
+	dw TradeAnim_TubeToPlayer1        ; 0e
+	dw TradeAnim_TubeToPlayer2        ; 0f
+	dw TradeAnim_TubeToPlayer3        ; 10
+	dw TradeAnim_TubeToPlayer4        ; 11
+	dw TradeAnim_TubeToPlayer5        ; 12
+	dw TradeAnim_TubeToPlayer6        ; 13
+	dw TradeAnim_TubeToPlayer7        ; 14
+	dw TradeAnim_TubeToPlayer8        ; 15
+	dw TradeAnim_SentToOTText         ; 16
+	dw TradeAnim_OTBidsFarewell       ; 17
+	dw TradeAnim_TakeCareOfText       ; 18
+	dw TradeAnim_OTSendsText1         ; 19
+	dw TradeAnim_OTSendsText2         ; 1a
+	dw TradeAnim_SetupGivemonScroll   ; 1b
+	dw TradeAnim_DoGivemonScroll      ; 1c
+	dw TradeAnim_FrontpicScrollStart  ; 1d
+	dw TradeAnim_TextboxScrollStart   ; 1e
+	dw TradeAnim_ScrollOutRight       ; 1f
+	dw TradeAnim_ScrollOutRight2      ; 20
+	dw TraideAnim_Wait80              ; 21
+	dw TraideAnim_Wait40              ; 22
+	dw TradeAnim_RockingBall          ; 23
+	dw TradeAnim_DropBall             ; 24
+	dw TradeAnim_WaitAnim             ; 25
+	dw TradeAnim_WaitAnim2            ; 26
+	dw TradeAnim_Poof                 ; 27
+	dw TradeAnim_BulgeThroughTube     ; 28
+	dw TradeAnim_GiveTrademonSFX      ; 29
+	dw TradeAnim_GetTrademonSFX       ; 2a
+	dw TradeAnim_End                  ; 2b
+	dw TradeAnim_AnimateFrontpic      ; 2c
+	dw TraideAnim_Wait96              ; 2d
+	dw TraideAnim_Wait80IfOTEgg       ; 2e
+	dw TraideAnim_Wait180IfOTEgg      ; 2f
+; 2910f
+
+TradeAnim_IncrementJumptableIndex: ; 2910f
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+; 29114
+
+TradeAnim_AdvanceScriptPointer: ; 29114
+	ld hl, wTradeAnimAddress
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	ld a, [de]
+	ld [wJumptableIndex], a
+	inc de
+	ld [hl], d
+	dec hl
+	ld [hl], e
+	ret
+
+; 29123
+
+TradeAnim_End: ; 29123
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+; 29129
+
+TradeAnim_TubeToOT1: ; 29129
+	ld a, TRADEANIM_RIGHT_ARROW
+	call TradeAnim_PlaceTrademonStatsOnTubeAnim
+	ld a, [wLinkTradeSendmonSpecies]
+	ld [wd265], a
+	xor a
+	depixel 5, 11, 4, 0
+	ld b, $0
+	jr TradeAnim_InitTubeAnim
+
+TradeAnim_TubeToPlayer1: ; 2913c
+	ld a, TRADEANIM_LEFT_ARROW
+	call TradeAnim_PlaceTrademonStatsOnTubeAnim
+	ld a, [wLinkTradeGetmonSpecies]
+	ld [wd265], a
+	ld a, TRADEANIMSTATE_2
+	depixel 9, 18, 4, 4
+	ld b, $4
+TradeAnim_InitTubeAnim: ; 2914e
+	push bc
+	push de
+	push bc
+	push de
+
+	push af
+	call DisableLCD
+	callfar ClearSpriteAnims
+	hlbgcoord 20, 3
+	ld bc, 12
+	ld a, $60
+	call ByteFill
+	pop af
+
+	call TradeAnim_TubeAnimJumptable
+
+	xor a
+	ld [hSCX], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $70
+	ld [hWY], a
+	call EnableLCD
+	call LoadTradeBubbleGFX
+
+	pop de
+	ld a, SPRITE_ANIM_INDEX_TRADEMON_ICON
+	call _InitSpriteAnimStruct
+
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	pop bc
+	ld [hl], b
+
+	pop de
+	ld a, SPRITE_ANIM_INDEX_TRADEMON_BUBBLE
+	call _InitSpriteAnimStruct
+
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	pop bc
+	ld [hl], b
+
+	call WaitBGMap
+	ld b, SCGB_TRADE_TUBE
+	call GetSGBLayout
+	ld a, %11100100 ; 3,2,1,0
+	call DmgToCgbBGPals
+	ld a, %11010000
+	call DmgToCgbObjPal0
+
+	call TradeAnim_IncrementJumptableIndex
+	ld a, 92
+	ld [wFrameCounter], a
+	ret
+
+; 291af
+
+TradeAnim_TubeToOT2: ; 291af
+	call TradeAnim_FlashBGPals
+	ld a, [hSCX]
+	add $2
+	ld [hSCX], a
+	cp $50
+	ret nz
+	ld a, TRADEANIMSTATE_1
+	call TradeAnim_TubeAnimJumptable
+	call TradeAnim_IncrementJumptableIndex
+	ret
+
+; 291c4
+
+TradeAnim_TubeToOT3: ; 291c4
+	call TradeAnim_FlashBGPals
+	ld a, [hSCX]
+	add $2
+	ld [hSCX], a
+	cp $a0
+	ret nz
+	ld a, TRADEANIMSTATE_2
+	call TradeAnim_TubeAnimJumptable
+	call TradeAnim_IncrementJumptableIndex
+	ret
+
+; 291d9
+
+TradeAnim_TubeToOT4: ; 291d9
+	call TradeAnim_FlashBGPals
+	ld a, [hSCX]
+	add $2
+	ld [hSCX], a
+	and a
+	ret nz
+	call TradeAnim_IncrementJumptableIndex
+	ret
+
+; 291e8
+
+TradeAnim_TubeToPlayer3: ; 291e8
+	call TradeAnim_FlashBGPals
+	ld a, [hSCX]
+	sub $2
+	ld [hSCX], a
+	cp $b0
+	ret nz
+	ld a, TRADEANIMSTATE_1
+	call TradeAnim_TubeAnimJumptable
+	call TradeAnim_IncrementJumptableIndex
+	ret
+
+; 291fd
+
+TradeAnim_TubeToPlayer4: ; 291fd
+	call TradeAnim_FlashBGPals
+	ld a, [hSCX]
+	sub $2
+	ld [hSCX], a
+	cp $60
+	ret nz
+	xor a ; TRADEANIMSTATE_0
+	call TradeAnim_TubeAnimJumptable
+	call TradeAnim_IncrementJumptableIndex
+	ret
+
+; 29211
+
+TradeAnim_TubeToPlayer5: ; 29211
+	call TradeAnim_FlashBGPals
+	ld a, [hSCX]
+	sub $2
+	ld [hSCX], a
+	and a
+	ret nz
+	call TradeAnim_IncrementJumptableIndex
+	ret
+
+; 29220
+
+TradeAnim_TubeToOT6:
+TradeAnim_TubeToPlayer6: ; 29220
+	ld a, 128
+	ld [wFrameCounter], a
+	call TradeAnim_IncrementJumptableIndex
+	ret
+
+; 29229
+
+TradeAnim_TubeToOT8:
+TradeAnim_TubeToPlayer8: ; 29229
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	call DisableLCD
+	callfar ClearSpriteAnims
+	hlbgcoord 0, 0
+	ld bc, sScratch - vBGMap0
+	ld a, " "
+	call ByteFill
+	xor a
+	ld [hSCX], a
+	ld a, $90
+	ld [hWY], a
+	call EnableLCD
+	call LoadTradeBallAndCableGFX
+	call WaitBGMap
+	call TradeAnim_NormalPals
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 2925d
+
+TradeAnim_TubeToOT5:
+TradeAnim_TubeToOT7:
+TradeAnim_TubeToPlayer2:
+TradeAnim_TubeToPlayer7: ; 2925d
+	call TradeAnim_FlashBGPals
+	ld hl, wFrameCounter
+	ld a, [hl]
+	and a
+	jr z, .done
+	dec [hl]
+	ret
+
+.done
+	call TradeAnim_IncrementJumptableIndex
+	ret
+
+; 2926d
+
+TradeAnim_GiveTrademonSFX: ; 2926d
+	call TradeAnim_AdvanceScriptPointer
+	ld de, SFX_GIVE_TRADEMON
+	call PlaySFX
+	ret
+
+; 29277
+
+TradeAnim_GetTrademonSFX: ; 29277
+	call TradeAnim_AdvanceScriptPointer
+	ld de, SFX_GET_TRADEMON
+	call PlaySFX
+	ret
+
+; 29281
+
+TradeAnim_TubeAnimJumptable: ; 29281
+	maskbits TRADEANIMJUMPTABLE_LENGTH
+	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
+; 2928f
+
+.Jumptable: ; 2928f
+; entries correspond to TRADEANIMSTATE_* constants
+	dw .Zero
+	dw .One
+	dw .Two
+	dw .Three
+; 29297
+
+.Zero: ; 29297
+.Three: ; 29297
+	call TradeAnim_BlankTileMap
+	hlcoord 9, 3
+	ld [hl], $5b
+	inc hl
+	ld bc, 10
+	ld a, $60
+	call ByteFill
+	hlcoord 3, 2
+	call TradeAnim_CopyTradeGameBoyTilemap
+	ret
+
+; 292af
+
+.One: ; 292af
+	call TradeAnim_BlankTileMap
+	hlcoord 0, 3
+	ld bc, SCREEN_WIDTH
+	ld a, $60
+	call ByteFill
+	ret
+
+; 292be
+
+.Two: ; 292be
+	call TradeAnim_BlankTileMap
+	hlcoord 0, 3
+	ld bc, $11
+	ld a, $60
+	call ByteFill
+	hlcoord 17, 3
+	ld a, $5d
+	ld [hl], a
+
+	ld a, $61
+	ld de, SCREEN_WIDTH
+	ld c, $3
+.loop
+	add hl, de
+	ld [hl], a
+	dec c
+	jr nz, .loop
+
+	add hl, de
+	ld a, $5f
+	ld [hld], a
+	ld a, $5b
+	ld [hl], a
+	hlcoord 10, 6
+	call TradeAnim_CopyTradeGameBoyTilemap
+	ret
+
+; 292ec
+
+TradeAnim_CopyTradeGameBoyTilemap: ; 292ec
+	ld de, TradeGameBoyTilemap
+	lb bc, 8, 6
+	call TradeAnim_CopyBoxFromDEtoHL
+	ret
+
+; 292f6
+
+TradeAnim_PlaceTrademonStatsOnTubeAnim: ; 292f6
+	push af
+	call ClearBGPalettes
+	call WaitTop
+	ld a, HIGH(vBGMap1)
+	ld [hBGMapAddress + 1], a
+	call ClearTileMap
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH
+	ld a, "─"
+	call ByteFill
+	hlcoord 0, 1
+	ld de, wLinkPlayer1Name
+	call PlaceString
+	ld hl, wLinkPlayer2Name
+	ld de, 0
+.find_name_end_loop
+	ld a, [hli]
+	cp "@"
+	jr z, .done
+	dec de
+	jr .find_name_end_loop
+
+.done
+	hlcoord 0, 4
+	add hl, de
+	ld de, wLinkPlayer2Name
+	call PlaceString
+	hlcoord 7, 2
+	ld bc, 6
+	pop af
+	call ByteFill
+	call WaitBGMap
+	call WaitTop
+	ld a, HIGH(vBGMap0)
+	ld [hBGMapAddress + 1], a
+	call ClearTileMap
+	ret
+
+; 29348
+
+TradeAnim_EnterLinkTube1: ; 29348
+	call ClearTileMap
+	call WaitTop
+	ld a, $a0
+	ld [hSCX], a
+	call DelayFrame
+	hlcoord 8, 2
+	ld de, TradeLinkTubeTilemap
+	lb bc, 3, 12
+	call TradeAnim_CopyBoxFromDEtoHL
+	call WaitBGMap
+	ld b, SCGB_TRADE_TUBE
+	call GetSGBLayout
+	ld a, %11100100 ; 3,2,1,0
+	call DmgToCgbBGPals
+	lb de, %11100100, %11100100 ; 3,2,1,0, 3,2,1,0
+	call DmgToCgbObjPals
+	ld de, SFX_POTION
+	call PlaySFX
+	call TradeAnim_IncrementJumptableIndex
+	ret
+
+; 2937e
+
+TradeAnim_EnterLinkTube2: ; 2937e
+	ld a, [hSCX]
+	and a
+	jr z, .done
+	add $4
+	ld [hSCX], a
+	ret
+
+.done
+	ld c, 80
+	call DelayFrames
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 29391
+
+TradeAnim_ExitLinkTube: ; 29391
+	ld a, [hSCX]
+	cp $a0
+	jr z, .done
+	sub $4
+	ld [hSCX], a
+	ret
+
+.done
+	call ClearTileMap
+	xor a
+	ld [hSCX], a
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 293a6
+
+TradeAnim_SetupGivemonScroll: ; 293a6
+	ld a, $8f
+	ld [hWX], a
+	ld a, $88
+	ld [hSCX], a
+	ld a, $50
+	ld [hWY], a
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 293b6
+
+TradeAnim_DoGivemonScroll: ; 293b6
+	ld a, [hWX]
+	cp $7
+	jr z, .done
+	sub $4
+	ld [hWX], a
+	ld a, [hSCX]
+	sub $4
+	ld [hSCX], a
+	ret
+
+.done
+	ld a, $7
+	ld [hWX], a
+	xor a
+	ld [hSCX], a
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 293d2
+
+TradeAnim_FrontpicScrollStart: ; 293d2
+	ld a, $7
+	ld [hWX], a
+	ld a, $50
+	ld [hWY], a
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 293de
+
+TradeAnim_TextboxScrollStart: ; 293de
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 293ea
+
+TradeAnim_ScrollOutRight: ; 293ea
+	call WaitTop
+	ld a, HIGH(vBGMap1)
+	ld [hBGMapAddress + 1], a
+	call WaitBGMap
+	ld a, $7
+	ld [hWX], a
+	xor a
+	ld [hWY], a
+	call DelayFrame
+	call WaitTop
+	ld a, HIGH(vBGMap0)
+	ld [hBGMapAddress + 1], a
+	call ClearTileMap
+	call TradeAnim_IncrementJumptableIndex
+	ret
+
+; 2940c
+
+TradeAnim_ScrollOutRight2: ; 2940c
+	ld a, [hWX]
+	cp $a1
+	jr nc, .done
+	add $4
+	ld [hWX], a
+	ret
+
+.done
+	ld a, HIGH(vBGMap1)
+	ld [hBGMapAddress + 1], a
+	call WaitBGMap
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	ld a, HIGH(vBGMap0)
+	ld [hBGMapAddress + 1], a
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 2942e
+
+TradeAnim_ShowGivemonData: ; 2942e
+	call ShowPlayerTrademonStats
+	ld a, [wPlayerTrademonSpecies]
+	ld [wCurPartySpecies], a
+	ld a, [wPlayerTrademonDVs]
+	ld [wTempMonDVs], a
+	ld a, [wPlayerTrademonDVs + 1]
+	ld [wTempMonDVs + 1], a
+	ld b, SCGB_PLAYER_OR_MON_FRONTPIC_PALS
+	call GetSGBLayout
+	ld a, %11100100 ; 3,2,1,0
+	call DmgToCgbBGPals
+	call TradeAnim_ShowGivemonFrontpic
+
+	ld a, [wPlayerTrademonSpecies]
+	call GetCryIndex
+	jr c, .skip_cry
+	ld e, c
+	ld d, b
+	call PlayCry
+.skip_cry
+
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 29461
+
+TradeAnim_ShowGetmonData: ; 29461
+	call 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
+	call TradeAnim_ShowGetmonFrontpic
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 29487
+
+TradeAnim_AnimateFrontpic: ; 29487
+	farcall AnimateTrademonFrontpic
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 29491
+
+TradeAnim_GetFrontpic: ; 29491
+	push de
+	push af
+	predef GetUnownLetter
+	pop af
+	ld [wCurPartySpecies], a
+	ld [wCurSpecies], a
+	call GetBaseData
+	pop de
+	predef GetMonFrontpic
+	ret
+
+; 294a9
+
+TradeAnim_GetNickname: ; 294a9
+	push de
+	ld [wd265], a
+	call GetPokemonName
+	ld hl, wStringBuffer1
+	pop de
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ret
+
+; 294bb
+
+TradeAnim_ShowGivemonFrontpic: ; 294bb
+	ld de, vTiles0
+	jr TradeAnim_ShowFrontpic
+
+TradeAnim_ShowGetmonFrontpic: ; 294c0
+	ld de, vTiles0 tile $31
+TradeAnim_ShowFrontpic: ; 294c3
+	call DelayFrame
+	ld hl, vTiles2
+	lb bc, 10, $31
+	call Request2bpp
+	call WaitTop
+	call TradeAnim_BlankTileMap
+	hlcoord 7, 2
+	xor a
+	ld [hGraphicStartTile], a
+	lb bc, 7, 7
+	predef PlaceGraphic
+	call WaitBGMap
+	ret
+
+; 294e7
+
+TraideAnim_Wait80: ; 294e7
+	ld c, 80
+	call DelayFrames
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 294f0
+
+TraideAnim_Wait40: ; 294f0
+	ld c, 40
+	call DelayFrames
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 294f9
+
+TraideAnim_Wait96: ; 294f9
+	ld c, 96
+	call DelayFrames
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 29502
+
+TraideAnim_Wait80IfOTEgg: ; 29502
+	call IsOTTrademonEgg
+	ret nz
+	ld c, 80
+	call DelayFrames
+	ret
+
+; 2950c
+
+TraideAnim_Wait180IfOTEgg: ; 2950c
+	call IsOTTrademonEgg
+	ret nz
+	ld c, 180
+	call DelayFrames
+	ret
+
+; 29516
+
+IsOTTrademonEgg: ; 29516
+	call TradeAnim_AdvanceScriptPointer
+	ld a, [wOTTrademonSpecies]
+	cp EGG
+	ret
+
+; 2951f
+ShowPlayerTrademonStats: ; 2951f
+	ld de, wPlayerTrademonSpecies
+	ld a, [de]
+	cp EGG
+	jr z, TrademonStats_Egg
+	call TrademonStats_MonTemplate
+	ld de, wPlayerTrademonSpecies
+	call TrademonStats_PrintSpeciesNumber
+	ld de, wPlayerTrademonSpeciesName
+	call TrademonStats_PrintSpeciesName
+	ld a, [wPlayerTrademonCaughtData]
+	ld de, wPlayerTrademonOTName
+	call TrademonStats_PrintOTName
+	ld de, wPlayerTrademonID
+	call TrademonStats_PrintTrademonID
+	call TrademonStats_WaitBGMap
+	ret
+
+; 29549
+
+ShowOTTrademonStats: ; 29549
+	ld de, wOTTrademonSpecies
+	ld a, [de]
+	cp EGG
+	jr z, TrademonStats_Egg
+	call TrademonStats_MonTemplate
+	ld de, wOTTrademonSpecies
+	call TrademonStats_PrintSpeciesNumber
+	ld de, wOTTrademonSpeciesName
+	call TrademonStats_PrintSpeciesName
+	ld a, [wOTTrademonCaughtData]
+	ld de, wOTTrademonOTName
+	call TrademonStats_PrintOTName
+	ld de, wOTTrademonID
+	call TrademonStats_PrintTrademonID
+	call TrademonStats_WaitBGMap
+	ret
+
+; 29573
+
+TrademonStats_MonTemplate: ; 29573
+	call WaitTop
+	call TradeAnim_BlankTileMap
+	ld a, HIGH(vBGMap1)
+	ld [hBGMapAddress + 1], a
+	hlcoord 3, 0
+	ld b, $6
+	ld c, $d
+	call TextBox
+	hlcoord 4, 0
+	ld de, .OTMonData
+	call PlaceString
+	ret
+
+; 29591
+
+.OTMonData: ; 29591
+	db   "─── №."
+	next ""
+	next "OT/"
+	next "<ID>№.@"
+; 295a1
+
+TrademonStats_Egg: ; 295a1
+	call WaitTop
+	call TradeAnim_BlankTileMap
+	ld a, HIGH(vBGMap1)
+	ld [hBGMapAddress + 1], a
+	hlcoord 3, 0
+	ld b, 6
+	ld c, 13
+	call TextBox
+	hlcoord 4, 2
+	ld de, .EggData
+	call PlaceString
+	call TrademonStats_WaitBGMap
+	ret
+
+; 295c2
+
+.EggData: ; 295c2
+	db   "EGG"
+	next "OT/?????"
+	next "<ID>№.?????@"
+; 295d8
+
+TrademonStats_WaitBGMap: ; 295d8
+	call WaitBGMap
+	call WaitTop
+	ld a, HIGH(vBGMap0)
+	ld [hBGMapAddress + 1], a
+	ret
+
+; 295e3
+
+TrademonStats_PrintSpeciesNumber: ; 295e3
+	hlcoord 10, 0
+	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
+	call PrintNum
+	ld [hl], " "
+	ret
+
+; 295ef
+
+TrademonStats_PrintSpeciesName: ; 295ef
+	hlcoord 4, 2
+	call PlaceString
+	ret
+
+; 295f6
+
+TrademonStats_PrintOTName: ; 295f6
+	cp 3
+	jr c, .caught_gender_okay
+	xor a
+.caught_gender_okay
+	push af
+	hlcoord 7, 4
+	call PlaceString
+	inc bc
+	pop af
+	ld hl, .Gender
+	ld d, 0
+	ld e, a
+	add hl, de
+	ld a, [hl]
+	ld [bc], a
+	ret
+
+; 2960e
+
+.Gender: ; 2960e
+	db " ", "♂", "♀"
+; 29611
+
+TrademonStats_PrintTrademonID: ; 29611
+	hlcoord 7, 6
+	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+	call PrintNum
+	ret
+
+; 2961b
+
+TradeAnim_RockingBall: ; 2961b
+	depixel 10, 11, 4, 0
+	ld a, SPRITE_ANIM_INDEX_TRADE_POKE_BALL
+	call _InitSpriteAnimStruct
+	call TradeAnim_AdvanceScriptPointer
+	ld a, 32
+	ld [wFrameCounter], a
+	ret
+
+; 2962c
+
+TradeAnim_DropBall: ; 2962c
+	depixel 10, 11, 4, 0
+	ld a, SPRITE_ANIM_INDEX_TRADE_POKE_BALL
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld [hl], $1
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], $dc
+	call TradeAnim_AdvanceScriptPointer
+	ld a, 56
+	ld [wFrameCounter], a
+	ret
+
+; 29649
+
+TradeAnim_Poof: ; 29649
+	depixel 10, 11, 4, 0
+	ld a, SPRITE_ANIM_INDEX_TRADE_POOF
+	call _InitSpriteAnimStruct
+	call TradeAnim_AdvanceScriptPointer
+	ld a, 16
+	ld [wFrameCounter], a
+	ld de, SFX_BALL_POOF
+	call PlaySFX
+	ret
+
+; 29660
+
+TradeAnim_BulgeThroughTube: ; 29660
+	ld a, %11100100 ; 3,2,1,0
+	call DmgToCgbObjPal0
+	depixel 5, 11
+	ld a, SPRITE_ANIM_INDEX_TRADE_TUBE_BULGE
+	call _InitSpriteAnimStruct
+	call TradeAnim_AdvanceScriptPointer
+	ld a, 64
+	ld [wFrameCounter], a
+	ret
+
+; 29676
+
+TradeAnim_AnimateTrademonInTube: ; 29676 (a:5676)
+	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
+; 29686
+
+.Jumptable: ; 29686 (a:5686)
+	dw .InitTimer
+	dw .WaitTimer1
+	dw .MoveRight
+	dw .MoveDown
+	dw .MoveUp
+	dw .MoveLeft
+	dw .WaitTimer2
+; 2969a
+
+.JumptableNext: ; 29694 (a:5694)
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	inc [hl]
+	ret
+
+.InitTimer: ; 2969a (a:569a)
+	call .JumptableNext
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $80
+	ret
+
+.WaitTimer1: ; 296a4 (a:56a4)
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	dec [hl]
+	and a
+	ret nz
+	call .JumptableNext
+
+.MoveRight: ; 296af (a:56af)
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld a, [hl]
+	cp $94
+	jr nc, .done_move_right
+	inc [hl]
+	ret
+
+.done_move_right
+	call .JumptableNext
+
+.MoveDown: ; 296bd (a:56bd)
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	ld a, [hl]
+	cp $4c
+	jr nc, .done_move_down
+	inc [hl]
+	ret
+
+.done_move_down
+	ld hl, SPRITEANIMSTRUCT_INDEX
+	add hl, bc
+	ld [hl], $0
+	ret
+
+.MoveUp: ; 296cf (a:56cf)
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	ld a, [hl]
+	cp $2c
+	jr z, .done_move_up
+	dec [hl]
+	ret
+
+.done_move_up
+	call .JumptableNext
+
+.MoveLeft: ; 296dd (a:56dd)
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld a, [hl]
+	cp $58
+	jr z, .done_move_left
+	dec [hl]
+	ret
+
+.done_move_left
+	call .JumptableNext
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $80
+	ret
+
+.WaitTimer2: ; 296f2 (a:56f2)
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	dec [hl]
+	and a
+	ret nz
+	ld hl, SPRITEANIMSTRUCT_INDEX
+	add hl, bc
+	ld [hl], $0
+	ret
+
+; 29701 (a:5701)
+
+TradeAnim_SentToOTText: ; 29701
+	ld a, [wLinkMode]
+	cp LINK_TIMECAPSULE
+	jr z, .time_capsule
+	ld hl, .Text_MonName
+	call PrintText
+	ld c, 189
+	call DelayFrames
+	ld hl, .Text_WasSentTo
+	call PrintText
+	call TradeAnim_Wait80Frames
+	ld c, 128
+	call DelayFrames
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+.time_capsule
+	ld hl, .Text_WasSentTo
+	call PrintText
+	call TradeAnim_Wait80Frames
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 29732
+
+.Text_WasSentTo: ; 0x29732
+	; was sent to @ .
+	text_jump UnknownText_0x1bc6e9
+	db "@"
+; 0x29737
+
+.Text_MonName: ; 0x29737
+	;
+	text_jump UnknownText_0x1bc701
+	db "@"
+; 0x2973c
+
+TradeAnim_OTBidsFarewell: ; 2973c
+	ld hl, .Text_BidsFarewellToMon
+	call PrintText
+	call TradeAnim_Wait80Frames
+	ld hl, .Text_MonName
+	call PrintText
+	call TradeAnim_Wait80Frames
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 29752
+
+.Text_BidsFarewellToMon: ; 0x29752
+	; bids farewell to
+	text_jump UnknownText_0x1bc703
+	db "@"
+; 0x29757
+
+.Text_MonName: ; 0x29757
+	; .
+	text_jump UnknownText_0x1bc719
+	db "@"
+; 0x2975c
+
+TradeAnim_TakeCareOfText: ; 2975c
+	call WaitTop
+	hlcoord 0, 10
+	ld bc, 8 * SCREEN_WIDTH
+	ld a, " "
+	call ByteFill
+	call WaitBGMap
+	ld hl, .Text_TakeGoodCareOfMon
+	call PrintText
+	call TradeAnim_Wait80Frames
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 2977a
+
+.Text_TakeGoodCareOfMon: ; 0x2977a
+	; Take good care of @ .
+	text_jump UnknownText_0x1bc71f
+	db "@"
+; 0x2977f
+
+TradeAnim_OTSendsText1: ; 2977f
+	ld hl, .Text_ForYourMon
+	call PrintText
+	call TradeAnim_Wait80Frames
+	ld hl, .Text_OTSends
+	call PrintText
+	call TradeAnim_Wait80Frames
+	ld c, 14
+	call DelayFrames
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 2979a
+
+.Text_ForYourMon: ; 0x2979a
+	; For @ 's @ ,
+	text_jump UnknownText_0x1bc739
+	db "@"
+; 0x2979f
+
+.Text_OTSends: ; 0x2979f
+	; sends @ .
+	text_jump UnknownText_0x1bc74c
+	db "@"
+; 0x297a4
+
+TradeAnim_OTSendsText2: ; 297a4
+	ld hl, .Text_WillTrade
+	call PrintText
+	call TradeAnim_Wait80Frames
+	ld hl, .Text_ForYourMon
+	call PrintText
+	call TradeAnim_Wait80Frames
+	ld c, 14
+	call DelayFrames
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 297bf
+
+.Text_WillTrade: ; 0x297bf
+	; will trade @ @
+	text_jump UnknownText_0x1bc75e
+	db "@"
+; 0x297c4
+
+.Text_ForYourMon: ; 0x297c4
+	; for @ 's @ .
+	text_jump UnknownText_0x1bc774
+	db "@"
+; 0x297c9
+
+TradeAnim_Wait80Frames: ; 297c9
+	ld c, 80
+	call DelayFrames
+	ret
+
+; 297cf
+
+TradeAnim_BlankTileMap: ; 297cf
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, " "
+	call ByteFill
+	ret
+
+; 297db
+
+TradeAnim_CopyBoxFromDEtoHL: ; 297db
+.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
+
+; 297ed
+
+TradeAnim_NormalPals: ; 297ed
+	ld a, [hSGB]
+	and a
+	ld a, %11100100 ; 3,2,1,0
+	jr z, .not_sgb
+	ld a, $f0
+
+.not_sgb
+	call DmgToCgbObjPal0
+	ld a, %11100100 ; 3,2,1,0
+	call DmgToCgbBGPals
+	ret
+
+; 297ff
+
+LinkTradeAnim_LoadTradePlayerNames: ; 297ff
+	push de
+	ld de, wLinkPlayer1Name
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	pop hl
+	ld de, wLinkPlayer2Name
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ret
+
+; 29814
+
+LinkTradeAnim_LoadTradeMonSpecies: ; 29814
+	ld a, [hl]
+	ld [wLinkTradeSendmonSpecies], a
+	ld a, [de]
+	ld [wLinkTradeGetmonSpecies], a
+	ret
+
+; 2981d
+
+TradeAnim_FlashBGPals: ; 2981d
+	ld a, [wcf65]
+	and $7
+	ret nz
+	ld a, [rBGP]
+	xor %00111100
+	call DmgToCgbBGPals
+	ret
+
+; 2982b
+
+LoadTradeBallAndCableGFX: ; 2982b
+	call DelayFrame
+	ld de, TradeBallGFX
+	ld hl, vTiles0 tile $62
+	lb bc, BANK(TradeBallGFX), 6
+	call Request2bpp
+	ld de, TradePoofGFX
+	ld hl, vTiles0 tile $68
+	lb bc, BANK(TradePoofGFX), 12
+	call Request2bpp
+	ld de, TradeCableGFX
+	ld hl, vTiles0 tile $74
+	lb bc, BANK(TradeCableGFX), 4
+	call Request2bpp
+	xor a
+	ld hl, wSpriteAnimDict
+	ld [hli], a
+	ld [hl], $62
+	ret
+
+; 2985a
+
+LoadTradeBubbleGFX: ; 2985a
+	call DelayFrame
+	ld e, $3
+	callfar LoadMenuMonIcon
+	ld de, TradeBubbleGFX
+	ld hl, vTiles0 tile $72
+	lb bc, BANK(TradeBubbleGFX), 4
+	call Request2bpp
+	xor a
+	ld hl, wSpriteAnimDict
+	ld [hli], a
+	ld [hl], $62
+	ret
+
+; 29879
+
+TradeAnim_WaitAnim: ; 29879
+	ld hl, wFrameCounter
+	ld a, [hl]
+	and a
+	jr z, .done
+	dec [hl]
+	ret
+
+.done
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 29886
+
+TradeAnim_WaitAnim2: ; 29886
+	ld hl, wFrameCounter
+	ld a, [hl]
+	and a
+	jr z, .done
+	dec [hl]
+	ret
+
+.done
+	call TradeAnim_AdvanceScriptPointer
+	ret
+
+; 29893
+
+
+Unreferenced_DebugTrade: ; 29893
+; This function is not referenced.
+; It was meant for use in Japanese versions, so the
+; constant used for copy length was changed by accident.
+
+	ld hl, .DebugTradeData
+
+	ld a, [hli]
+	ld [wPlayerTrademonSpecies], a
+	ld de, wPlayerTrademonSenderName
+	ld c, NAME_LENGTH + 2 ; JP: NAME_LENGTH_JAPANESE + 2
+.loop1
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec c
+	jr nz, .loop1
+
+	ld a, [hli]
+	ld [wOTTrademonSpecies], a
+	ld de, wOTTrademonSenderName
+	ld c, NAME_LENGTH + 2 ; JP: NAME_LENGTH_JAPANESE + 2
+.loop2
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec c
+	jr nz, .loop2
+	ret
+
+; 298b5
+
+debugtrade: MACRO
+; species, ot name, ot id (?)
+	db \1, \2
+	dw \3
+ENDM
+
+.DebugTradeData: ; 298b5
+	debugtrade VENUSAUR, "ゲーフり@@", $0123 ; GAME FREAK
+	debugtrade CHARIZARD, "クりーチャ@", $0456 ; Creatures Inc.
+; 298c7
+
+
+TradeGameBoyTilemap: ; 298c7
+; 6x8
+	db $31, $32, $32, $32, $32, $33
+	db $34, $35, $36, $36, $37, $38
+	db $34, $39, $3a, $3a, $3b, $38
+	db $3c, $3d, $3e, $3e, $3f, $40
+	db $41, $42, $43, $43, $44, $45
+	db $46, $47, $43, $48, $49, $4a
+	db $41, $43, $4b, $4c, $4d, $4e
+	db $4f, $50, $50, $50, $51, $52
+; 297f7
+
+TradeLinkTubeTilemap: ; 297f7
+; 12x3
+	db $43, $55, $56, $53, $53, $53, $53, $53, $53, $53, $53, $53
+	db $43, $57, $58, $54, $54, $54, $54, $54, $54, $54, $54, $54
+	db $43, $59, $5a, $43, $43, $43, $43, $43, $43, $43, $43, $43
+; 2991b
+
+TradeArrowGFX:  INCBIN "gfx/trade/arrow.2bpp"
+TradeCableGFX:  INCBIN "gfx/trade/cable.2bpp"
+TradeBubbleGFX: INCBIN "gfx/trade/bubble.2bpp"
+TradeGameBoyLZ: INCBIN "gfx/trade/game_boy.2bpp.lz"
+TradeBallGFX:   INCBIN "gfx/trade/ball.2bpp"
+TradePoofGFX:   INCBIN "gfx/trade/poof.2bpp"
--- a/engine/health.asm
+++ /dev/null
@@ -1,110 +1,0 @@
-HealParty: ; c658
-	xor a
-	ld [wCurPartyMon], a
-	ld hl, wPartySpecies
-.loop
-	ld a, [hli]
-	cp -1
-	jr z, .done
-	cp EGG
-	jr z, .next
-
-	push hl
-	call HealPartyMon
-	pop hl
-
-.next
-	ld a, [wCurPartyMon]
-	inc a
-	ld [wCurPartyMon], a
-	jr .loop
-
-.done
-	ret
-
-HealPartyMon: ; c677
-	ld a, MON_SPECIES
-	call GetPartyParamLocation
-	ld d, h
-	ld e, l
-
-	ld hl, MON_STATUS
-	add hl, de
-	xor a
-	ld [hli], a
-	ld [hl], a
-
-	ld hl, MON_MAXHP
-	add hl, de
-
-	; bc = MON_HP
-	ld b, h
-	ld c, l
-	dec bc
-	dec bc
-
-	ld a, [hli]
-	ld [bc], a
-	inc bc
-	ld a, [hl]
-	ld [bc], a
-
-	farcall RestoreAllPP
-	ret
-
-ComputeHPBarPixels: ; c699
-; e = bc * (6 * 8) / de
-	ld a, b
-	or c
-	jr z, .zero
-	push hl
-	xor a
-	ld [hMultiplicand + 0], a
-	ld a, b
-	ld [hMultiplicand + 1], a
-	ld a, c
-	ld [hMultiplicand + 2], a
-	ld a, 6 * 8
-	ld [hMultiplier], a
-	call Multiply
-	; We need de to be under 256 because hDivisor is only 1 byte.
-	ld a, d
-	and a
-	jr z, .divide
-	; divide de and hProduct by 4
-	srl d
-	rr e
-	srl d
-	rr e
-	ld a, [hProduct + 2]
-	ld b, a
-	ld a, [hProduct + 3]
-	srl b
-	rr a
-	srl b
-	rr a
-	ld [hDividend + 3], a
-	ld a, b
-	ld [hDividend + 2], a
-.divide
-	ld a, e
-	ld [hDivisor], a
-	ld b, 4
-	call Divide
-	ld a, [hQuotient + 2]
-	ld e, a
-	pop hl
-	and a
-	ret nz
-	ld e, 1
-	ret
-
-.zero
-	ld e, 0
-	ret
-
-AnimateHPBar: ; c6e0
-	call WaitBGMap
-	call _AnimateHPBar
-	call WaitBGMap
-	ret
--- a/engine/init_hof_credits.asm
+++ /dev/null
@@ -1,79 +1,0 @@
-InitDisplayForHallOfFame: ; 4e881
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	call DisableLCD
-	call LoadStandardFont
-	call LoadFontsBattleExtra
-	hlbgcoord 0, 0
-	ld bc, vBGMap1 - vBGMap0
-	ld a, " "
-	call ByteFill
-	hlcoord 0, 0, wAttrMap
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	xor a
-	call ByteFill
-	xor a
-	ld [hSCY], a
-	ld [hSCX], a
-	call EnableLCD
-	ld hl, .SavingRecordDontTurnOff
-	call PrintText
-	call WaitBGMap2
-	call SetPalettes
-	ret
-
-.SavingRecordDontTurnOff: ; 0x4e8bd
-	; SAVING RECORD… DON'T TURN OFF!
-	text_jump UnknownText_0x1bd39e
-	db "@"
-
-InitDisplayForRedCredits: ; 4e8c2
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	call DisableLCD
-	call LoadStandardFont
-	call LoadFontsBattleExtra
-	hlbgcoord 0, 0
-	ld bc, vBGMap1 - vBGMap0
-	ld a, " "
-	call ByteFill
-	hlcoord 0, 0, wAttrMap
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	xor a
-	call ByteFill
-	ld hl, wBGPals1
-	ld c, 4 tiles
-.load_white_palettes
-	ld a, LOW(PALRGB_WHITE)
-	ld [hli], a
-	ld a, HIGH(PALRGB_WHITE)
-	ld [hli], a
-	dec c
-	jr nz, .load_white_palettes
-	xor a
-	ld [hSCY], a
-	ld [hSCX], a
-	call EnableLCD
-	call WaitBGMap2
-	call SetPalettes
-	ret
-
-ResetDisplayBetweenHallOfFameMons: ; 4e906
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wDecompressScratch)
-	ld [rSVBK], a
-	ld hl, wDecompressScratch
-	ld bc, wScratchAttrMap - wDecompressScratch
-	ld a, " "
-	call ByteFill
-	hlbgcoord 0, 0
-	ld de, wDecompressScratch
-	ld b, 0
-	ld c, 4 tiles
-	call Request2bpp
-	pop af
-	ld [rSVBK], a
-	ret
--- a/engine/init_map.asm
+++ /dev/null
@@ -1,103 +1,0 @@
-ReanchorBGMap_NoOAMUpdate:: ; 6454
-	call DelayFrame
-	ld a, [hOAMUpdate]
-	push af
-
-	ld a, $1
-	ld [hOAMUpdate], a
-	ld a, [hBGMapMode]
-	push af
-	xor a
-	ld [hBGMapMode], a
-
-	call .ReanchorBGMap
-
-	pop af
-	ld [hBGMapMode], a
-	pop af
-	ld [hOAMUpdate], a
-	ld hl, wVramState
-	set 6, [hl]
-	ret
-
-.ReanchorBGMap:
-	xor a
-	ld [hLCDCPointer], a
-	ld [hBGMapMode], a
-	ld a, $90
-	ld [hWY], a
-	call OverworldTextModeSwitch
-	ld a, HIGH(vBGMap1)
-	call .LoadBGMapAddrIntoHRAM
-	call _OpenAndCloseMenu_HDMATransferTileMapAndAttrMap
-	farcall LoadOW_BGPal7
-	farcall ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	xor a
-	ld [hBGMapMode], a
-	ld [hWY], a
-	farcall HDMATransfer_FillBGMap0WithBlack ; no need to farcall
-	ld a, HIGH(vBGMap0)
-	call .LoadBGMapAddrIntoHRAM
-	xor a ; LOW(vBGMap0)
-	ld [wBGMapAnchor], a
-	ld a, HIGH(vBGMap0)
-	ld [wBGMapAnchor + 1], a
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	call ApplyBGMapAnchorToObjects
-	ret
-
-.LoadBGMapAddrIntoHRAM: ; 64b9
-	ld [hBGMapAddress + 1], a
-	xor a
-	ld [hBGMapAddress], a
-	ret
-
-LoadFonts_NoOAMUpdate:: ; 64bf
-	ld a, [hOAMUpdate]
-	push af
-	ld a, $1
-	ld [hOAMUpdate], a
-
-	call .LoadGFX
-
-	pop af
-	ld [hOAMUpdate], a
-	ret
-
-.LoadGFX:
-	call LoadFontsExtra
-	ld a, $90
-	ld [hWY], a
-	call SafeUpdateSprites
-	call LoadStandardFont
-	ret
-
-HDMATransfer_FillBGMap0WithBlack: ; 64db
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wDecompressScratch)
-	ld [rSVBK], a
-
-	ld a, "■"
-	ld hl, wDecompressScratch
-	ld bc, wScratchAttrMap - wDecompressScratch
-	call ByteFill
-	ld a, HIGH(wDecompressScratch)
-	ld [rHDMA1], a
-	ld a, LOW(wDecompressScratch)
-	ld [rHDMA2], a
-	ld a, HIGH(vBGMap0 % $8000)
-	ld [rHDMA3], a
-	ld a, LOW(vBGMap0 % $8000)
-	ld [rHDMA4], a
-	ld a, $3f
-	ld [hDMATransfer], a
-	call DelayFrame
-
-	pop af
-	ld [rSVBK], a
-	ret
--- a/engine/landmarks.asm
+++ /dev/null
@@ -1,87 +1,0 @@
-GetLandmarkCoords: ; 0x1ca896
-; Return coordinates (d, e) of landmark e.
-	push hl
-	ld l, e
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	ld de, Landmarks
-	add hl, de
-	ld a, [hli]
-	ld e, a
-	ld d, [hl]
-	pop hl
-	ret
-; 0x1ca8a5
-
-
-GetLandmarkName:: ; 0x1ca8a5
-; Copy the name of landmark e to wStringBuffer1.
-	push hl
-	push de
-	push bc
-
-	ld l, e
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	ld de, Landmarks + 2
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-
-	ld de, wStringBuffer1
-	ld c, 18
-.copy
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec c
-	jr nz, .copy
-
-	pop bc
-	pop de
-	pop hl
-	ret
-; 0x1ca8c3
-
-
-INCLUDE "data/maps/landmarks.asm"
-
-
-RegionCheck: ; 0x1caea1
-; Checks if the player is in Kanto or Johto.
-; If in Johto, returns 0 in e.
-; If in Kanto, returns 1 in e.
-	ld a, [wMapGroup]
-	ld b, a
-	ld a, [wMapNumber]
-	ld c, a
-	call GetWorldMapLocation
-	cp FAST_SHIP ; S.S. Aqua
-	jr z, .johto
-	cp SPECIAL_MAP
-	jr nz, .checkagain
-
-; In a special map, get the backup map group / map id
-	ld a, [wBackupMapGroup]
-	ld b, a
-	ld a, [wBackupMapNumber]
-	ld c, a
-	call GetWorldMapLocation
-
-.checkagain
-	cp KANTO_LANDMARK
-	jr c, .johto
-
-; Victory Road area is considered to be Johto.
-	cp VICTORY_ROAD
-	jr c, .kanto
-
-.johto
-	ld e, JOHTO_REGION
-	ret
-.kanto
-	ld e, KANTO_REGION
-	ret
--- a/engine/learn.asm
+++ /dev/null
@@ -1,256 +1,0 @@
-LearnMove: ; 6508
-	call LoadTileMapToTempTileMap
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMonNicknames
-	call GetNick
-	ld hl, wStringBuffer1
-	ld de, wMonOrItemNameBuffer
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-
-.loop
-	ld hl, wPartyMon1Moves
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld d, h
-	ld e, l
-	ld b, NUM_MOVES
-; Get the first empty move slot.  This routine also serves to
-; determine whether the Pokemon learning the moves already has
-; all four slots occupied, in which case one would need to be
-; deleted.
-.next
-	ld a, [hl]
-	and a
-	jr z, .learn
-	inc hl
-	dec b
-	jr nz, .next
-; If we're here, we enter the routine for forgetting a move
-; to make room for the new move we're trying to learn.
-	push de
-	call ForgetMove
-	pop de
-	jp c, .cancel
-
-	push hl
-	push de
-	ld [wd265], a
-
-	ld b, a
-	ld a, [wBattleMode]
-	and a
-	jr z, .not_disabled
-	ld a, [wDisabledMove]
-	cp b
-	jr nz, .not_disabled
-	xor a
-	ld [wDisabledMove], a
-	ld [wPlayerDisableCount], a
-.not_disabled
-
-	call GetMoveName
-	ld hl, Text_1_2_and_Poof ; 1, 2 and…
-	call PrintText
-	pop de
-	pop hl
-
-.learn
-	ld a, [wPutativeTMHMMove]
-	ld [hl], a
-	ld bc, MON_PP - MON_MOVES
-	add hl, bc
-
-	push hl
-	push de
-	dec a
-	ld hl, Moves + MOVE_PP
-	ld bc, MOVE_LENGTH
-	call AddNTimes
-	ld a, BANK(Moves)
-	call GetFarByte
-	pop de
-	pop hl
-
-	ld [hl], a
-
-	ld a, [wBattleMode]
-	and a
-	jp z, .learned
-
-	ld a, [wCurPartyMon]
-	ld b, a
-	ld a, [wCurBattleMon]
-	cp b
-	jp nz, .learned
-
-	ld a, [wPlayerSubStatus5]
-	bit SUBSTATUS_TRANSFORMED, a
-	jp nz, .learned
-
-	ld h, d
-	ld l, e
-	ld de, wBattleMonMoves
-	ld bc, NUM_MOVES
-	call CopyBytes
-	ld bc, wPartyMon1PP - (wPartyMon1Moves + NUM_MOVES)
-	add hl, bc
-	ld de, wBattleMonPP
-	ld bc, NUM_MOVES
-	call CopyBytes
-	jp .learned
-
-.cancel
-	ld hl, Text_StopLearning ; Stop learning <MOVE>?
-	call PrintText
-	call YesNoBox
-	jp c, .loop
-
-	ld hl, Text_DidNotLearn ; <MON> did not learn <MOVE>.
-	call PrintText
-	ld b, 0
-	ret
-
-.learned
-	ld hl, Text_LearnedMove ; <MON> learned <MOVE>!
-	call PrintText
-	ld b, 1
-	ret
-; 65d3
-
-ForgetMove: ; 65d3
-	push hl
-	ld hl, Text_TryingToLearn
-	call PrintText
-	call YesNoBox
-	pop hl
-	ret c
-	ld bc, -NUM_MOVES
-	add hl, bc
-	push hl
-	ld de, wListMoves_MoveIndicesBuffer
-	ld bc, NUM_MOVES
-	call CopyBytes
-	pop hl
-.loop
-	push hl
-	ld hl, Text_ForgetWhich
-	call PrintText
-	hlcoord 5, 2
-	ld b, NUM_MOVES * 2
-	ld c, MOVE_NAME_LENGTH
-	call TextBox
-	hlcoord 5 + 2, 2 + 2
-	ld a, SCREEN_WIDTH * 2
-	ld [wBuffer1], a
-	predef ListMoves
-	; w2DMenuData
-	ld a, $4
-	ld [w2DMenuCursorInitY], a
-	ld a, $6
-	ld [w2DMenuCursorInitX], a
-	ld a, [wNumMoves]
-	inc a
-	ld [w2DMenuNumRows], a
-	ld a, $1
-	ld [w2DMenuNumCols], a
-	ld [wMenuCursorY], a
-	ld [wMenuCursorX], a
-	ld a, $3
-	ld [wMenuJoypadFilter], a
-	ld a, $20
-	ld [w2DMenuFlags1], a
-	xor a
-	ld [w2DMenuFlags2], a
-	ld a, $20
-	ld [w2DMenuCursorOffsets], a
-	call StaticMenuJoypad
-	push af
-	call Call_LoadTempTileMapToTileMap
-	pop af
-	pop hl
-	bit 1, a
-	jr nz, .cancel
-	push hl
-	ld a, [wMenuCursorY]
-	dec a
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [hl]
-	push af
-	push bc
-	call IsHMMove
-	pop bc
-	pop de
-	ld a, d
-	jr c, .hmmove
-	pop hl
-	add hl, bc
-	and a
-	ret
-
-.hmmove
-	ld hl, Text_CantForgetHM
-	call PrintText
-	pop hl
-	jr .loop
-
-.cancel
-	scf
-	ret
-; 666b
-
-Text_LearnedMove: ; 666b
-; <MON> learned <MOVE>!
-	text_jump UnknownText_0x1c5660
-	db "@"
-; 6670
-
-Text_ForgetWhich: ; 6670
-; Which move should be forgotten?
-	text_jump UnknownText_0x1c5678
-	db "@"
-; 6675
-
-Text_StopLearning: ; 6675
-; Stop learning <MOVE>?
-	text_jump UnknownText_0x1c5699
-	db "@"
-; 667a
-
-Text_DidNotLearn: ; 667a
-; <MON> did not learn <MOVE>.
-	text_jump UnknownText_0x1c56af
-	db "@"
-; 667f
-
-Text_TryingToLearn: ; 667f
-; <MON> is trying to learn <MOVE>. But <MON> can't learn more than
-; four moves. Delete an older move to make room for <MOVE>?
-	text_jump UnknownText_0x1c56c9
-	db "@"
-; 6684
-
-Text_1_2_and_Poof: ; 6684
-	text_jump UnknownText_0x1c5740 ; 1, 2 and…
-	start_asm
-	push de
-	ld de, SFX_SWITCH_POKEMON
-	call PlaySFX
-	pop de
-	ld hl, .PoofForgot
-	ret
-
-.PoofForgot:
-; Poof! <MON> forgot <MOVE>. And…
-	text_jump UnknownText_0x1c574e
-	db "@"
-; 669a
-
-Text_CantForgetHM: ; 669a
-; HM moves can't be forgotten now.
-	text_jump UnknownText_0x1c5772
-	db "@"
-; 669f
--- a/engine/link.asm
+++ /dev/null
@@ -1,2589 +1,0 @@
-LinkCommunications: ; 28000
-	call ClearBGPalettes
-	ld c, 80
-	call DelayFrames
-	call ClearScreen
-	call ClearSprites
-	call UpdateSprites
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld c, 80
-	call DelayFrames
-	call ClearScreen
-	call UpdateSprites
-	call LoadStandardFont
-	call LoadFontsBattleExtra
-	farcall LinkComms_LoadPleaseWaitTextboxBorderGFX
-	call WaitBGMap2
-	hlcoord 3, 8
-	ld b, 2
-	ld c, 12
-	ld d, h
-	ld e, l
-	farcall LinkTextbox2
-	hlcoord 4, 10
-	ld de, String_PleaseWait
-	call PlaceString
-	call SetTradeRoomBGPals
-	call WaitBGMap2
-	ld hl, wcf5d
-	xor a ; LOW($5000)
-	ld [hli], a
-	ld [hl], HIGH($5000)
-	ld a, [wLinkMode]
-	cp LINK_TIMECAPSULE
-	jp nz, Gen2ToGen2LinkComms
-
-Gen2ToGen1LinkComms: ; 2805d
-	call ClearLinkData
-	call Link_PrepPartyData_Gen1
-	call FixDataForLinkTransfer
-	xor a
-	ld [wPlayerLinkAction], a
-	call WaitLinkTransfer
-	ld a, [hSerialConnectionStatus]
-	cp USING_INTERNAL_CLOCK
-	jr nz, .player_1
-
-	ld c, 3
-	call DelayFrames
-	xor a
-	ld [hSerialSend], a
-	ld a, (0 << rSC_ON) | 1
-	ld [rSC], a
-	ld a, (1 << rSC_ON) | 1
-	ld [rSC], a
-
-	call DelayFrame
-	xor a
-	ld [hSerialSend], a
-	ld a, (0 << rSC_ON) | 1
-	ld [rSC], a
-	ld a, (1 << rSC_ON) | 1
-	ld [rSC], a
-
-.player_1
-	ld de, MUSIC_NONE
-	call PlayMusic
-	ld c, 3
-	call DelayFrames
-	xor a
-	ld [rIF], a
-	ld a, $8
-	ld [rIE], a
-	ld hl, wd1f3
-	ld de, wEnemyMonSpecies
-	ld bc, $11
-	call Serial_ExchangeBytes
-	ld a, SERIAL_NO_DATA_BYTE
-	ld [de], a
-	ld hl, wLinkData
-	ld de, wOTPlayerName
-	ld bc, $1a8
-	call Serial_ExchangeBytes
-	ld a, SERIAL_NO_DATA_BYTE
-	ld [de], a
-	ld hl, wMisc
-	ld de, wPlayerTrademonSpecies
-	ld bc, wPlayerTrademonSpecies - wMisc
-	call Serial_ExchangeBytes
-	xor a
-	ld [rIF], a
-	ld a, $1d
-	ld [rIE], a
-	call Link_CopyRandomNumbers
-	ld hl, wOTPlayerName
-	call Link_FindFirstNonControlCharacter_SkipZero
-	push hl
-	ld bc, NAME_LENGTH
-	add hl, bc
-	ld a, [hl]
-	pop hl
-	and a
-	jp z, Function28b22
-	cp $7
-	jp nc, Function28b22
-	ld de, wLinkData
-	ld bc, $1a2
-	call Link_CopyOTData
-	ld de, wPlayerTrademonSpecies
-	ld hl, wTimeCapsulePartyMon1Species
-	ld c, 2
-.loop
-	ld a, [de]
-	inc de
-	and a
-	jr z, .loop
-	cp SERIAL_PREAMBLE_BYTE
-	jr z, .loop
-	cp SERIAL_NO_DATA_BYTE
-	jr z, .loop
-	cp SERIAL_PATCH_LIST_PART_TERMINATOR
-	jr z, .next
-	push hl
-	push bc
-	ld b, 0
-	dec a
-	ld c, a
-	add hl, bc
-	ld a, SERIAL_NO_DATA_BYTE
-	ld [hl], a
-	pop bc
-	pop hl
-	jr .loop
-
-.next
-	ld hl, wc90f
-	dec c
-	jr nz, .loop
-	ld hl, wLinkPlayerName
-	ld de, wOTPlayerName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ld de, wOTPartyCount
-	ld a, [hli]
-	ld [de], a
-	inc de
-.party_loop
-	ld a, [hli]
-	cp -1
-	jr z, .done_party
-	ld [wd265], a
-	push hl
-	push de
-	callfar ConvertMon_1to2
-	pop de
-	pop hl
-	ld a, [wd265]
-	ld [de], a
-	inc de
-	jr .party_loop
-
-.done_party
-	ld [de], a
-	ld hl, wTimeCapsulePartyMon1Species
-	call Function2868a
-	ld a, LOW(wOTPartyMonOT)
-	ld [wUnusedD102], a
-	ld a, HIGH(wOTPartyMonOT)
-	ld [wUnusedD102 + 1], a
-	ld de, MUSIC_NONE
-	call PlayMusic
-	ld a, [hSerialConnectionStatus]
-	cp USING_INTERNAL_CLOCK
-	ld c, 66
-	call z, DelayFrames
-	ld de, MUSIC_ROUTE_30
-	call PlayMusic
-	jp InitTradeMenuDisplay
-; 28177
-
-Gen2ToGen2LinkComms: ; 28177
-	call ClearLinkData
-	call Link_PrepPartyData_Gen2
-	call FixDataForLinkTransfer
-	call Function29dba
-	ld a, [wScriptVar]
-	and a
-	jp z, LinkTimeout
-	ld a, [hSerialConnectionStatus]
-	cp USING_INTERNAL_CLOCK
-	jr nz, .Player1
-
-	ld c, 3
-	call DelayFrames
-	xor a
-	ld [hSerialSend], a
-	ld a, (0 << rSC_ON) | 1
-	ld [rSC], a
-	ld a, (1 << rSC_ON) | 1
-	ld [rSC], a
-
-	call DelayFrame
-	xor a
-	ld [hSerialSend], a
-	ld a, (0 << rSC_ON) | 1
-	ld [rSC], a
-	ld a, (1 << rSC_ON) | 1
-	ld [rSC], a
-
-.Player1:
-	ld de, MUSIC_NONE
-	call PlayMusic
-	ld c, 3
-	call DelayFrames
-	xor a
-	ld [rIF], a
-	ld a, $8
-	ld [rIE], a
-	ld hl, wd1f3
-	ld de, wEnemyMonSpecies
-	ld bc, $11
-	call Serial_ExchangeBytes
-	ld a, SERIAL_NO_DATA_BYTE
-	ld [de], a
-	ld hl, wLinkData
-	ld de, wOTPlayerName
-	ld bc, $1c2
-	call Serial_ExchangeBytes
-	ld a, SERIAL_NO_DATA_BYTE
-	ld [de], a
-	ld hl, wMisc
-	ld de, wPlayerTrademonSpecies
-	ld bc, $c8
-	call Serial_ExchangeBytes
-	ld a, [wLinkMode]
-	cp LINK_TRADECENTER
-	jr nz, .not_trading
-	ld hl, wc9f4
-	ld de, wcb84
-	ld bc, $186
-	call ExchangeBytes
-
-.not_trading
-	xor a
-	ld [rIF], a
-	ld a, $1d
-	ld [rIE], a
-	ld de, MUSIC_NONE
-	call PlayMusic
-	call Link_CopyRandomNumbers
-	ld hl, wOTPlayerName
-	call Link_FindFirstNonControlCharacter_SkipZero
-	ld de, wLinkData
-	ld bc, $1b9
-	call Link_CopyOTData
-	ld de, wPlayerTrademonSpecies
-	ld hl, wLinkPlayerPartyMon1Species
-	ld c, 2
-.loop1
-	ld a, [de]
-	inc de
-	and a
-	jr z, .loop1
-	cp SERIAL_PREAMBLE_BYTE
-	jr z, .loop1
-	cp SERIAL_NO_DATA_BYTE
-	jr z, .loop1
-	cp SERIAL_PATCH_LIST_PART_TERMINATOR
-	jr z, .next1
-	push hl
-	push bc
-	ld b, 0
-	dec a
-	ld c, a
-	add hl, bc
-	ld a, SERIAL_NO_DATA_BYTE
-	ld [hl], a
-	pop bc
-	pop hl
-	jr .loop1
-
-.next1
-	ld hl, wc90f
-	dec c
-	jr nz, .loop1
-	ld a, [wLinkMode]
-	cp LINK_TRADECENTER
-	jp nz, .skip_mail
-	ld hl, wcb84
-.loop2
-	ld a, [hli]
-	cp MAIL_MSG_LENGTH
-	jr nz, .loop2
-.loop3
-	ld a, [hli]
-	cp SERIAL_NO_DATA_BYTE
-	jr z, .loop3
-	cp MAIL_MSG_LENGTH
-	jr z, .loop3
-	dec hl
-	ld de, wcb84
-	ld bc, $190 ; 400
-	call CopyBytes
-	ld hl, wcb84
-	ld bc, $c6 ; 198
-.loop4
-	ld a, [hl]
-	cp MAIL_MSG_LENGTH + 1
-	jr nz, .okay1
-	ld [hl], SERIAL_NO_DATA_BYTE
-.okay1
-	inc hl
-	dec bc
-	ld a, b
-	or c
-	jr nz, .loop4
-	ld de, wcc9e
-.loop5
-	ld a, [de]
-	inc de
-	cp SERIAL_PATCH_LIST_PART_TERMINATOR
-	jr z, .start_copying_mail
-	ld hl, wcc4a
-	dec a
-	ld b, $0
-	ld c, a
-	add hl, bc
-	ld [hl], SERIAL_NO_DATA_BYTE
-	jr .loop5
-
-.start_copying_mail
-	ld hl, wcb84
-	ld de, wc9f4
-	ld b, PARTY_LENGTH
-.copy_mail_loop
-	push bc
-	ld bc, MAIL_MSG_LENGTH + 1
-	call CopyBytes
-	ld a, LOW(MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 1))
-	add e
-	ld e, a
-	ld a, HIGH(MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 1))
-	adc d
-	ld d, a
-	pop bc
-	dec b
-	jr nz, .copy_mail_loop
-	ld de, wc9f4
-	ld b, PARTY_LENGTH
-.copy_author_loop
-	push bc
-	ld a, LOW(MAIL_MSG_LENGTH + 1)
-	add e
-	ld e, a
-	ld a, HIGH(MAIL_MSG_LENGTH + 1)
-	adc d
-	ld d, a
-	ld bc, MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 1)
-	call CopyBytes
-	pop bc
-	dec b
-	jr nz, .copy_author_loop
-	ld b, PARTY_LENGTH
-	ld de, wc9f4
-.fix_mail_loop
-	push bc
-	push de
-	farcall IsMailEuropean
-	ld a, c
-	or a
-	jr z, .next
-	sub $3
-	jr nc, .skip
-	farcall DeutenEnglischenPost
-	jr .next
-
-.skip
-	cp $2
-	jr nc, .next
-	farcall HandleSpanishItalianMail
-
-.next
-	pop de
-	ld hl, MAIL_STRUCT_LENGTH
-	add hl, de
-	ld d, h
-	ld e, l
-	pop bc
-	dec b
-	jr nz, .fix_mail_loop
-	ld de, wcb0e
-	xor a
-	ld [de], a
-
-.skip_mail
-	ld hl, wLinkPlayerName
-	ld de, wOTPlayerName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ld de, wOTPartyCount
-	ld bc, 1 + PARTY_LENGTH + 1
-	call CopyBytes
-	ld de, wOTPlayerID
-	ld bc, 2
-	call CopyBytes
-	ld de, wOTPartyMons
-	ld bc, wOTPartyDataEnd - wOTPartyMons
-	call CopyBytes
-	ld a, LOW(wOTPartyMonOT)
-	ld [wUnusedD102], a
-	ld a, HIGH(wOTPartyMonOT)
-	ld [wUnusedD102 + 1], a
-	ld de, MUSIC_NONE
-	call PlayMusic
-	ld a, [hSerialConnectionStatus]
-	cp USING_INTERNAL_CLOCK
-	ld c, 66
-	call z, DelayFrames
-	ld a, [wLinkMode]
-	cp LINK_COLOSSEUM
-	jr nz, .ready_to_trade
-	ld a, CAL
-	ld [wOtherTrainerClass], a
-	call ClearScreen
-	farcall Link_WaitBGMap
-	ld hl, wOptions
-	ld a, [hl]
-	push af
-	and 1 << STEREO
-	or TEXT_DELAY_MED
-	ld [hl], a
-	ld hl, wOTPlayerName
-	ld de, wOTClassName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	call ReturnToMapFromSubmenu
-
-	; LET'S DO THIS
-	ld a, [wDisableTextAcceleration]
-	push af
-	ld a, 1
-	ld [wDisableTextAcceleration], a
-	ld a, [rIE]
-	push af
-	ld a, [rIF]
-	push af
-	xor a
-	ld [rIF], a
-	ld a, [rIE]
-	set 1, a
-	ld [rIE], a
-	pop af
-	ld [rIF], a
-
-	predef StartBattle
-
-	ld a, [rIF]
-	ld h, a
-	xor a
-	ld [rIF], a
-	pop af
-	ld [rIE], a
-	ld a, h
-	ld [rIF], a
-	pop af
-	ld [wDisableTextAcceleration], a
-	pop af
-	ld [wOptions], a
-	farcall LoadPokemonData
-	jp Function28b22
-
-.ready_to_trade
-	ld de, MUSIC_ROUTE_30
-	call PlayMusic
-	jp InitTradeMenuDisplay
-; 283b2
-
-LinkTimeout: ; 283b2
-	ld de, .TooMuchTimeHasElapsed
-	ld b, 10
-.loop
-	call DelayFrame
-	call LinkDataReceived
-	dec b
-	jr nz, .loop
-	xor a
-	ld [hld], a
-	ld [hl], a
-	ld [hVBlank], a
-	push de
-	hlcoord 0, 12
-	ld b, 4
-	ld c, 18
-	push de
-	ld d, h
-	ld e, l
-	farcall LinkTextbox2
-	pop de
-	pop hl
-	bccoord 1, 14
-	call PlaceHLTextAtBC
-	call RotateThreePalettesRight
-	call ClearScreen
-	ld b, SCGB_DIPLOMA
-	call GetSGBLayout
-	call WaitBGMap2
-	ret
-; 283ed
-
-.TooMuchTimeHasElapsed: ; 0x283ed
-	; Too much time has elapsed. Please try again.
-	text_jump UnknownText_0x1c4183
-	db "@"
-; 0x283f2
-
-ExchangeBytes: ; 283f2
-	ld a, TRUE
-	ld [hSerialIgnoringInitialData], a
-.loop
-	ld a, [hl]
-	ld [hSerialSend], a
-	call Serial_ExchangeByte
-	push bc
-	ld b, a
-	inc hl
-	ld a, 48
-.delay_cycles
-	dec a
-	jr nz, .delay_cycles
-	ld a, [hSerialIgnoringInitialData]
-	and a
-	ld a, b
-	pop bc
-	jr z, .load
-	dec hl
-	xor a
-	ld [hSerialIgnoringInitialData], a
-	jr .loop
-
-.load
-	ld [de], a
-	inc de
-	dec bc
-	ld a, b
-	or c
-	jr nz, .loop
-	ret
-; 28419
-
-String_PleaseWait: ; 28419
-	db "PLEASE WAIT!@"
-; 28426
-
-ClearLinkData: ; 28426
-	ld hl, wLinkData
-	ld bc, wLinkDataEnd - wLinkData
-.loop
-	xor a
-	ld [hli], a
-	dec bc
-	ld a, b
-	or c
-	jr nz, .loop
-	ret
-; 28434
-
-FixDataForLinkTransfer: ; 28434
-	ld hl, wd1f3
-	ld a, SERIAL_PREAMBLE_BYTE
-	ld b, wLinkBattleRNs - wd1f3
-.loop1
-	ld [hli], a
-	dec b
-	jr nz, .loop1
-	ld b, wTempEnemyMonSpecies - wLinkBattleRNs
-.loop2
-	call Random
-	cp SERIAL_PREAMBLE_BYTE
-	jr nc, .loop2
-	ld [hli], a
-	dec b
-	jr nz, .loop2
-	ld hl, wMisc
-	ld a, SERIAL_PREAMBLE_BYTE
-	ld [hli], a
-	ld [hli], a
-	ld [hli], a
-	ld b, $c8
-	xor a
-.loop3
-	ld [hli], a
-	dec b
-	jr nz, .loop3
-	ld hl, wTimeCapsulePartyMon1 - 1 + 6
-	ld de, wc612
-	lb bc, 0, 0
-.loop4
-	inc c
-	ld a, c
-	cp SERIAL_PREAMBLE_BYTE
-	jr z, .next1
-	ld a, b
-	dec a
-	jr nz, .next2
-	push bc
-	ld a, [wLinkMode]
-	cp LINK_TIMECAPSULE
-	ld b, $d
-	jr z, .got_value
-	ld b, $27
-.got_value
-	ld a, c
-	cp b
-	pop bc
-	jr z, .done
-.next2
-	inc hl
-	ld a, [hl]
-	cp SERIAL_NO_DATA_BYTE
-	jr nz, .loop4
-	ld a, c
-	ld [de], a
-	inc de
-	ld [hl], SERIAL_PATCH_LIST_PART_TERMINATOR
-	jr .loop4
-
-.next1
-	ld a, SERIAL_PATCH_LIST_PART_TERMINATOR
-	ld [de], a
-	inc de
-	lb bc, 1, 0
-	jr .loop4
-
-.done
-	ld a, SERIAL_PATCH_LIST_PART_TERMINATOR
-	ld [de], a
-	ret
-; 28499
-
-Link_PrepPartyData_Gen1: ; 28499
-	ld de, wLinkData
-	ld a, SERIAL_PREAMBLE_BYTE
-	ld b, PARTY_LENGTH
-.loop1
-	ld [de], a
-	inc de
-	dec b
-	jr nz, .loop1
-	ld hl, wPlayerName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	push de
-	ld hl, wPartyCount
-	ld a, [hli]
-	ld [de], a
-	inc de
-.loop2
-	ld a, [hli]
-	cp -1
-	jr z, .done_party
-	ld [wd265], a
-	push hl
-	push de
-	callfar ConvertMon_2to1
-	pop de
-	pop hl
-	ld a, [wd265]
-	ld [de], a
-	inc de
-	jr .loop2
-
-.done_party
-	ld [de], a
-	pop de
-	ld hl, 1 + PARTY_LENGTH + 1
-	add hl, de
-	ld d, h
-	ld e, l
-	ld hl, wPartyMon1Species
-	ld c, PARTY_LENGTH
-.mon_loop
-	push bc
-	call .ConvertPartyStruct2to1
-	ld bc, PARTYMON_STRUCT_LENGTH
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .mon_loop
-	ld hl, wPartyMonOT
-	call .copy_ot_nicks
-	ld hl, wPartyMonNicknames
-.copy_ot_nicks
-	ld bc, PARTY_LENGTH * NAME_LENGTH
-	jp CopyBytes
-; 284f6
-
-.ConvertPartyStruct2to1: ; 284f6
-	ld b, h
-	ld c, l
-	push de
-	push bc
-	ld a, [hl]
-	ld [wd265], a
-	callfar ConvertMon_2to1
-	pop bc
-	pop de
-	ld a, [wd265]
-	ld [de], a
-	inc de
-	ld hl, MON_HP
-	add hl, bc
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-	inc de
-	xor a
-	ld [de], a
-	inc de
-	ld hl, MON_STATUS
-	add hl, bc
-	ld a, [hl]
-	ld [de], a
-	inc de
-	ld a, [bc]
-	cp MAGNEMITE
-	jr z, .steel_type
-	cp MAGNETON
-	jr nz, .skip_steel
-
-.steel_type
-	ld a, ELECTRIC
-	ld [de], a
-	inc de
-	ld [de], a
-	inc de
-	jr .done_steel
-
-.skip_steel
-	push bc
-	dec a
-	ld hl, BaseData + BASE_TYPES
-	ld bc, BASE_DATA_SIZE
-	call AddNTimes
-	ld bc, BASE_CATCH_RATE - BASE_TYPES
-	ld a, BANK(BaseData)
-	call FarCopyBytes
-	pop bc
-
-.done_steel
-	push bc
-	ld hl, MON_ITEM
-	add hl, bc
-	ld bc, MON_HAPPINESS - MON_ITEM
-	call CopyBytes
-	pop bc
-
-	ld hl, MON_LEVEL
-	add hl, bc
-	ld a, [hl]
-	ld [de], a
-	ld [wCurPartyLevel], a
-	inc de
-
-	push bc
-	ld hl, MON_MAXHP
-	add hl, bc
-	ld bc, MON_SAT - MON_MAXHP
-	call CopyBytes
-	pop bc
-
-	push de
-	push bc
-
-	ld a, [bc]
-	dec a
-	push bc
-	ld b, 0
-	ld c, a
-	ld hl, KantoMonSpecials
-	add hl, bc
-	ld a, BANK(KantoMonSpecials)
-	call GetFarByte
-	ld [wBaseSpecialAttack], a
-	pop bc
-
-	ld hl, MON_STAT_EXP - 1
-	add hl, bc
-	ld c, STAT_SATK
-	ld b, TRUE
-	predef CalcMonStatC
-
-	pop bc
-	pop de
-
-	ld a, [hQuotient + 1]
-	ld [de], a
-	inc de
-	ld a, [hQuotient + 2]
-	ld [de], a
-	inc de
-	ld h, b
-	ld l, c
-	ret
-; 28595
-
-Link_PrepPartyData_Gen2: ; 28595
-	ld de, wLinkData
-	ld a, SERIAL_PREAMBLE_BYTE
-	ld b, PARTY_LENGTH
-.loop1
-	ld [de], a
-	inc de
-	dec b
-	jr nz, .loop1
-	ld hl, wPlayerName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ld hl, wPartyCount
-	ld bc, 1 + PARTY_LENGTH + 1
-	call CopyBytes
-	ld hl, wPlayerID
-	ld bc, 2
-	call CopyBytes
-	ld hl, wPartyMon1Species
-	ld bc, PARTY_LENGTH * PARTYMON_STRUCT_LENGTH
-	call CopyBytes
-	ld hl, wPartyMonOT
-	ld bc, PARTY_LENGTH * NAME_LENGTH
-	call CopyBytes
-	ld hl, wPartyMonNicknames
-	ld bc, PARTY_LENGTH * MON_NAME_LENGTH
-	call CopyBytes
-
-; Okay, we did all that.  Now, are we in the trade center?
-	ld a, [wLinkMode]
-	cp LINK_TRADECENTER
-	ret nz
-
-; Fill 5 bytes at wc9f4 with $20
-	ld de, wc9f4
-	ld a, $20
-	call Function28682
-
-; Copy all the mail messages to wc9f9
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	ld hl, sPartyMail
-	ld b, PARTY_LENGTH
-.loop2
-	push bc
-	ld bc, MAIL_MSG_LENGTH + 1
-	call CopyBytes
-	ld bc, sPartyMon1MailEnd - sPartyMon1MailAuthor
-	add hl, bc
-	pop bc
-	dec b
-	jr nz, .loop2
-; Copy the mail data to wcabf
-	ld hl, sPartyMail
-	ld b, PARTY_LENGTH
-.loop3
-	push bc
-	ld bc, MAIL_MSG_LENGTH + 1
-	add hl, bc
-	ld bc, sPartyMon1MailEnd - sPartyMon1MailAuthor
-	call CopyBytes
-	pop bc
-	dec b
-	jr nz, .loop3
-
-	ld b, PARTY_LENGTH
-	ld de, sPartyMail
-	ld hl, wc9f9
-.loop4
-	push bc
-	push hl
-	push de
-	push hl
-	farcall IsMailEuropean
-	pop de
-	ld a, c
-	or a
-	jr z, .next
-	sub $3
-	jr nc, .italian_spanish
-	farcall HandleFrenchGermanMail
-	jr .next
-
-.italian_spanish
-	cp $2
-	jr nc, .next
-	farcall HandleSpanishItalianMail
-
-.next
-	pop de
-	ld hl, MAIL_STRUCT_LENGTH
-	add hl, de
-	ld d, h
-	ld e, l
-	pop hl
-	ld bc, sPartyMon1MailAuthor - sPartyMon1Mail
-	add hl, bc
-	pop bc
-	dec b
-	jr nz, .loop4
-	call CloseSRAM
-	ld hl, wc9f9
-	ld bc, PARTY_LENGTH * (sPartyMon1MailAuthor - sPartyMon1Mail)
-.loop5
-	ld a, [hl]
-	cp SERIAL_NO_DATA_BYTE
-	jr nz, .skip2
-	ld [hl], sPartyMon1MailAuthor - sPartyMon1Mail
-
-.skip2
-	inc hl
-	dec bc
-	ld a, b
-	or c
-	jr nz, .loop5
-	ld hl, wcabf
-	ld de, wcb13
-	ld b, PARTY_LENGTH * (sPartyMon1MailEnd - sPartyMon1MailAuthor)
-	ld c, $0
-.loop6
-	inc c
-	ld a, [hl]
-	cp SERIAL_NO_DATA_BYTE
-	jr nz, .skip3
-	ld [hl], SERIAL_PATCH_LIST_PART_TERMINATOR
-	ld a, c
-	ld [de], a
-	inc de
-
-.skip3
-	inc hl
-	dec b
-	jr nz, .loop6
-	ld a, SERIAL_PATCH_LIST_PART_TERMINATOR
-	ld [de], a
-	ret
-; 28682
-
-Function28682: ; 28682
-	ld c, 5
-.loop
-	ld [de], a
-	inc de
-	dec c
-	jr nz, .loop
-	ret
-; 2868a
-
-Function2868a: ; 2868a
-	push hl
-	ld d, h
-	ld e, l
-	ld bc, wLinkOTPartyMonTypes
-	ld hl, wcbe8
-	ld a, c
-	ld [hli], a
-	ld [hl], b
-	ld hl, wOTPartyMon1Species
-	ld c, PARTY_LENGTH
-.loop
-	push bc
-	call .ConvertToGen2
-	pop bc
-	dec c
-	jr nz, .loop
-	pop hl
-	ld bc, PARTY_LENGTH * REDMON_STRUCT_LENGTH
-	add hl, bc
-	ld de, wOTPartyMonOT
-	ld bc, PARTY_LENGTH * NAME_LENGTH
-	call CopyBytes
-	ld de, wOTPartyMonNicknames
-	ld bc, PARTY_LENGTH * MON_NAME_LENGTH
-	jp CopyBytes
-; 286ba
-
-.ConvertToGen2: ; 286ba
-	ld b, h
-	ld c, l
-	ld a, [de]
-	inc de
-	push bc
-	push de
-	ld [wd265], a
-	callfar ConvertMon_1to2
-	pop de
-	pop bc
-	ld a, [wd265]
-	ld [bc], a
-	ld [wCurSpecies], a
-	ld hl, MON_HP
-	add hl, bc
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hl], a
-	inc de
-	ld hl, MON_STATUS
-	add hl, bc
-	ld a, [de]
-	inc de
-	ld [hl], a
-	ld hl, wcbe8
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [de]
-	ld [hli], a
-	inc de
-	ld a, [de]
-	ld [hli], a
-	inc de
-	ld a, l
-	ld [wcbe8], a
-	ld a, h
-	ld [wcbe8 + 1], a
-	push bc
-	ld hl, MON_ITEM
-	add hl, bc
-	push hl
-	ld h, d
-	ld l, e
-	pop de
-	push bc
-	ld a, [hli]
-	ld b, a
-	call TimeCapsule_ReplaceTeruSama
-	ld a, b
-	ld [de], a
-	inc de
-	pop bc
-	ld bc, $19
-	call CopyBytes
-	pop bc
-	ld d, h
-	ld e, l
-	ld hl, $1f
-	add hl, bc
-	ld a, [de]
-	inc de
-	ld [hl], a
-	ld [wCurPartyLevel], a
-	push bc
-	ld hl, $24
-	add hl, bc
-	push hl
-	ld h, d
-	ld l, e
-	pop de
-	ld bc, 8
-	call CopyBytes
-	pop bc
-	call GetBaseData
-	push de
-	push bc
-	ld d, h
-	ld e, l
-	ld hl, MON_STAT_EXP - 1
-	add hl, bc
-	ld c, STAT_SATK
-	ld b, TRUE
-	predef CalcMonStatC
-	pop bc
-	pop hl
-	ld a, [hQuotient + 1]
-	ld [hli], a
-	ld a, [hQuotient + 2]
-	ld [hli], a
-	push hl
-	push bc
-	ld hl, MON_STAT_EXP - 1
-	add hl, bc
-	ld c, STAT_SDEF
-	ld b, TRUE
-	predef CalcMonStatC
-	pop bc
-	pop hl
-	ld a, [hQuotient + 1]
-	ld [hli], a
-	ld a, [hQuotient + 2]
-	ld [hli], a
-	push hl
-	ld hl, $1b
-	add hl, bc
-	ld a, $46
-	ld [hli], a
-	xor a
-	ld [hli], a
-	ld [hli], a
-	ld [hl], a
-	pop hl
-	inc de
-	inc de
-	ret
-; 28771
-
-TimeCapsule_ReplaceTeruSama: ; 28771
-	ld a, b
-	and a
-	ret z
-	push hl
-	ld hl, TimeCapsule_CatchRateItems
-.loop
-	ld a, [hli]
-	and a
-	jr z, .end
-	cp b
-	jr z, .found
-	inc hl
-	jr .loop
-
-.found
-	ld b, [hl]
-
-.end
-	pop hl
-	ret
-
-
-INCLUDE "data/items/catch_rate_items.asm"
-
-
-Link_CopyOTData: ; 2879e
-.loop
-	ld a, [hli]
-	cp SERIAL_NO_DATA_BYTE
-	jr z, .loop
-	ld [de], a
-	inc de
-	dec bc
-	ld a, b
-	or c
-	jr nz, .loop
-	ret
-; 287ab
-
-Link_CopyRandomNumbers: ; 287ab
-	ld a, [hSerialConnectionStatus]
-	cp USING_INTERNAL_CLOCK
-	ret z
-	ld hl, wEnemyMonSpecies
-	call Link_FindFirstNonControlCharacter_AllowZero
-	ld de, wLinkBattleRNs
-	ld c, 10
-.loop
-	ld a, [hli]
-	cp SERIAL_NO_DATA_BYTE
-	jr z, .loop
-	cp SERIAL_PREAMBLE_BYTE
-	jr z, .loop
-	ld [de], a
-	inc de
-	dec c
-	jr nz, .loop
-	ret
-; 287ca
-
-Link_FindFirstNonControlCharacter_SkipZero: ; 287ca
-.loop
-	ld a, [hli]
-	and a
-	jr z, .loop
-	cp SERIAL_PREAMBLE_BYTE
-	jr z, .loop
-	cp SERIAL_NO_DATA_BYTE
-	jr z, .loop
-	dec hl
-	ret
-; 287d8
-
-Link_FindFirstNonControlCharacter_AllowZero: ; 287d8
-.loop
-	ld a, [hli]
-	cp SERIAL_PREAMBLE_BYTE
-	jr z, .loop
-	cp SERIAL_NO_DATA_BYTE
-	jr z, .loop
-	dec hl
-	ret
-; 287e3
-
-InitTradeMenuDisplay: ; 287e3
-	call ClearScreen
-	call LoadTradeScreenBorder
-	farcall InitTradeSpeciesList
-	xor a
-	ld hl, wOtherPlayerLinkMode
-	ld [hli], a
-	ld [hli], a
-	ld [hli], a
-	ld [hl], a
-	ld a, 1
-	ld [wMenuCursorY], a
-	inc a
-	ld [wPlayerLinkAction], a
-	jp LinkTrade_PlayerPartyMenu
-; 28803
-
-LinkTrade_OTPartyMenu: ; 28803
-	ld a, OTPARTYMON
-	ld [wMonType], a
-	ld a, A_BUTTON | D_UP | D_DOWN
-	ld [wMenuJoypadFilter], a
-	ld a, [wOTPartyCount]
-	ld [w2DMenuNumRows], a
-	ld a, 1
-	ld [w2DMenuNumCols], a
-	ld a, 9
-	ld [w2DMenuCursorInitY], a
-	ld a, 6
-	ld [w2DMenuCursorInitX], a
-	ld a, 1
-	ld [wMenuCursorX], a
-	ln a, 1, 0
-	ld [w2DMenuCursorOffsets], a
-	ld a, MENU_UNUSED_3
-	ld [w2DMenuFlags1], a
-	xor a
-	ld [w2DMenuFlags2], a
-
-LinkTradeOTPartymonMenuLoop: ; 28835
-	farcall LinkTradeMenu
-	ld a, d
-	and a
-	jp z, LinkTradePartiesMenuMasterLoop
-	bit A_BUTTON_F, a
-	jr z, .not_a_button
-	ld a, INIT_ENEMYOT_LIST
-	ld [wInitListType], a
-	callfar InitList
-	ld hl, wOTPartyMon1Species
-	farcall LinkMonStatsScreen
-	jp LinkTradePartiesMenuMasterLoop
-
-.not_a_button
-	bit D_UP_F, a
-	jr z, .not_d_up
-	ld a, [wMenuCursorY]
-	ld b, a
-	ld a, [wOTPartyCount]
-	cp b
-	jp nz, LinkTradePartiesMenuMasterLoop
-	xor a
-	ld [wMonType], a
-	call HideCursor
-	push hl
-	push bc
-	ld bc, NAME_LENGTH
-	add hl, bc
-	ld [hl], " "
-	pop bc
-	pop hl
-	ld a, [wPartyCount]
-	ld [wMenuCursorY], a
-	jr LinkTrade_PlayerPartyMenu
-
-.not_d_up
-	bit D_DOWN_F, a
-	jp z, LinkTradePartiesMenuMasterLoop
-	jp Function28ac9
-; 2888b
-
-LinkTrade_PlayerPartyMenu: ; 2888b
-	farcall InitMG_Mobile_LinkTradePalMap
-	xor a
-	ld [wMonType], a
-	ld a, A_BUTTON | D_UP | D_DOWN
-	ld [wMenuJoypadFilter], a
-	ld a, [wPartyCount]
-	ld [w2DMenuNumRows], a
-	ld a, 1
-	ld [w2DMenuNumCols], a
-	ld a, 1
-	ld [w2DMenuCursorInitY], a
-	ld a, 6
-	ld [w2DMenuCursorInitX], a
-	ld a, 1
-	ld [wMenuCursorX], a
-	ln a, 1, 0
-	ld [w2DMenuCursorOffsets], a
-	ld a, MENU_UNUSED_3
-	ld [w2DMenuFlags1], a
-	xor a
-	ld [w2DMenuFlags2], a
-	call WaitBGMap2
-
-LinkTradePartymonMenuLoop: ; 288c5
-	farcall LinkTradeMenu
-	ld a, d
-	and a
-	jr nz, .check_joypad
-	jp LinkTradePartiesMenuMasterLoop
-
-.check_joypad
-	bit A_BUTTON_F, a
-	jr z, .not_a_button
-	jp Function28926
-
-.not_a_button
-	bit D_DOWN_F, a
-	jr z, .not_d_down
-	ld a, [wMenuCursorY]
-	dec a
-	jp nz, LinkTradePartiesMenuMasterLoop
-	ld a, OTPARTYMON
-	ld [wMonType], a
-	call HideCursor
-	push hl
-	push bc
-	ld bc, NAME_LENGTH
-	add hl, bc
-	ld [hl], " "
-	pop bc
-	pop hl
-	ld a, 1
-	ld [wMenuCursorY], a
-	jp LinkTrade_OTPartyMenu
-
-.not_d_down
-	bit D_UP_F, a
-	jr z, LinkTradePartiesMenuMasterLoop
-	ld a, [wMenuCursorY]
-	ld b, a
-	ld a, [wPartyCount]
-	cp b
-	jr nz, LinkTradePartiesMenuMasterLoop
-	call HideCursor
-	push hl
-	push bc
-	ld bc, NAME_LENGTH
-	add hl, bc
-	ld [hl], " "
-	pop bc
-	pop hl
-	jp Function28ade
-; 2891c
-
-LinkTradePartiesMenuMasterLoop: ; 2891c
-	ld a, [wMonType]
-	and a
-	jp z, LinkTradePartymonMenuLoop ; PARTYMON
-	jp LinkTradeOTPartymonMenuLoop  ; OTPARTYMON
-; 28926
-
-Function28926: ; 28926
-	call LoadTileMapToTempTileMap
-	ld a, [wMenuCursorY]
-	push af
-	hlcoord 0, 15
-	ld b, 1
-	ld c, 18
-	call LinkTextboxAtHL
-	hlcoord 2, 16
-	ld de, .String_Stats_Trade
-	call PlaceString
-	farcall Link_WaitBGMap
-
-.joy_loop
-	ld a, " "
-	ldcoord_a 11, 16
-	ld a, A_BUTTON | B_BUTTON | D_RIGHT
-	ld [wMenuJoypadFilter], a
-	ld a, 1
-	ld [w2DMenuNumRows], a
-	ld a, 1
-	ld [w2DMenuNumCols], a
-	ld a, 16
-	ld [w2DMenuCursorInitY], a
-	ld a, 1
-	ld [w2DMenuCursorInitX], a
-	ld a, 1
-	ld [wMenuCursorY], a
-	ld [wMenuCursorX], a
-	ln a, 2, 0
-	ld [w2DMenuCursorOffsets], a
-	xor a
-	ld [w2DMenuFlags1], a
-	ld [w2DMenuFlags2], a
-	call ScrollingMenuJoypad
-	bit D_RIGHT_F, a
-	jr nz, .d_right
-	bit B_BUTTON_F, a
-	jr z, .show_stats
-.b_button
-	pop af
-	ld [wMenuCursorY], a
-	call Call_LoadTempTileMapToTileMap
-	jp LinkTrade_PlayerPartyMenu
-
-.d_right
-	ld a, " "
-	ldcoord_a 1, 16
-	ld a, A_BUTTON | B_BUTTON | D_LEFT
-	ld [wMenuJoypadFilter], a
-	ld a, 1
-	ld [w2DMenuNumRows], a
-	ld a, 1
-	ld [w2DMenuNumCols], a
-	ld a, 16
-	ld [w2DMenuCursorInitY], a
-	ld a, 11
-	ld [w2DMenuCursorInitX], a
-	ld a, 1
-	ld [wMenuCursorY], a
-	ld [wMenuCursorX], a
-	ln a, 2, 0
-	ld [w2DMenuCursorOffsets], a
-	xor a
-	ld [w2DMenuFlags1], a
-	ld [w2DMenuFlags2], a
-	call ScrollingMenuJoypad
-	bit D_LEFT_F, a
-	jp nz, .joy_loop
-	bit B_BUTTON_F, a
-	jr nz, .b_button
-	jr .try_trade
-
-.show_stats
-	pop af
-	ld [wMenuCursorY], a
-	ld a, INIT_PLAYEROT_LIST
-	ld [wInitListType], a
-	callfar InitList
-	farcall LinkMonStatsScreen
-	call Call_LoadTempTileMapToTileMap
-	hlcoord 6, 1
-	lb bc, 6, 1
-	ld a, " "
-	call LinkEngine_FillBox
-	hlcoord 17, 1
-	lb bc, 6, 1
-	ld a, " "
-	call LinkEngine_FillBox
-	jp LinkTrade_PlayerPartyMenu
-
-.try_trade
-	call PlaceHollowCursor
-	pop af
-	ld [wMenuCursorY], a
-	dec a
-	ld [wd002], a
-	ld [wPlayerLinkAction], a
-	farcall Function16d6ce
-	ld a, [wOtherPlayerLinkMode]
-	cp $f
-	jp z, InitTradeMenuDisplay
-	ld [wd003], a
-	call Function28b68
-	ld c, 100
-	call DelayFrames
-	farcall ValidateOTTrademon
-	jr c, .abnormal
-	farcall Functionfb5dd
-	jp nc, LinkTrade
-	xor a
-	ld [wcf57], a
-	ld [wOtherPlayerLinkAction], a
-	hlcoord 0, 12
-	ld b, 4
-	ld c, 18
-	call LinkTextboxAtHL
-	farcall Link_WaitBGMap
-	ld hl, .Text_CantTradeLastMon
-	bccoord 1, 14
-	call PlaceHLTextAtBC
-	jr .cancel_trade
-
-.abnormal
-	xor a
-	ld [wcf57], a
-	ld [wOtherPlayerLinkAction], a
-	ld a, [wd003]
-	ld hl, wOTPartySpecies
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [hl]
-	ld [wd265], a
-	call GetPokemonName
-	hlcoord 0, 12
-	ld b, 4
-	ld c, 18
-	call LinkTextboxAtHL
-	farcall Link_WaitBGMap
-	ld hl, .Text_Abnormal
-	bccoord 1, 14
-	call PlaceHLTextAtBC
-
-.cancel_trade
-	hlcoord 0, 12
-	ld b, 4
-	ld c, 18
-	call LinkTextboxAtHL
-	hlcoord 1, 14
-	ld de, String_TooBadTheTradeWasCanceled
-	call PlaceString
-	ld a, $1
-	ld [wPlayerLinkAction], a
-	farcall Function16d6ce
-	ld c, 100
-	call DelayFrames
-	jp InitTradeMenuDisplay
-; 28aaf
-
-
-.Text_CantTradeLastMon: ; 0x28aaf
-	; If you trade that #MON, you won't be able to battle.
-	text_jump UnknownText_0x1c41b1
-	db "@"
-; 0x28ab4
-
-.String_Stats_Trade: ; 28ab4
-	db "STATS     TRADE@"
-
-.Text_Abnormal: ; 0x28ac4
-	; Your friend's @  appears to be abnormal!
-	text_jump UnknownText_0x1c41e6
-	db "@"
-; 0x28ac9
-
-
-Function28ac9: ; 28ac9
-	ld a, [wMenuCursorY]
-	cp 1
-	jp nz, LinkTradePartiesMenuMasterLoop
-	call HideCursor
-	push hl
-	push bc
-	ld bc, NAME_LENGTH
-	add hl, bc
-	ld [hl], " "
-	pop bc
-	pop hl
-Function28ade: ; 28ade
-.loop1
-	ld a, "▶"
-	ldcoord_a 9, 17
-.loop2
-	call JoyTextDelay
-	ld a, [hJoyLast]
-	and a
-	jr z, .loop2
-	bit A_BUTTON_F, a
-	jr nz, .a_button
-	push af
-	ld a, " "
-	ldcoord_a 9, 17
-	pop af
-	bit D_UP_F, a
-	jr z, .d_up
-	ld a, [wOTPartyCount]
-	ld [wMenuCursorY], a
-	jp LinkTrade_OTPartyMenu
-
-.d_up
-	ld a, $1
-	ld [wMenuCursorY], a
-	jp LinkTrade_PlayerPartyMenu
-
-.a_button
-	ld a, "▷"
-	ldcoord_a 9, 17
-	ld a, $f
-	ld [wPlayerLinkAction], a
-	farcall Function16d6ce
-	ld a, [wOtherPlayerLinkMode]
-	cp $f
-	jr nz, .loop1
-Function28b22: ; 28b22
-	call RotateThreePalettesRight
-	call ClearScreen
-	ld b, SCGB_DIPLOMA
-	call GetSGBLayout
-	call WaitBGMap2
-	xor a
-	ld [wcfbb], a
-	xor a
-	ld [rSB], a
-	ld [hSerialSend], a
-	ld a, (0 << rSC_ON) | 1
-	ld [rSC], a
-	ld a, (1 << rSC_ON) | 1
-	ld [rSC], a
-	ret
-; 28b42
-
-Unreferenced_Function28b42: ; 28b42
-	hlcoord 0, 16
-	ld a, "┘"
-	ld bc, 2 * SCREEN_WIDTH
-	call ByteFill
-	hlcoord 1, 16
-	ld a, " "
-	ld bc, SCREEN_WIDTH - 2
-	call ByteFill
-	hlcoord 2, 16
-	ld de, .Cancel
-	jp PlaceString
-; 28b61
-
-.Cancel: ; 28b61
-	db "CANCEL@"
-; 28b68
-
-Function28b68: ; 28b68
-	ld a, [wOtherPlayerLinkMode]
-	hlcoord 6, 9
-	ld bc, SCREEN_WIDTH
-	call AddNTimes
-	ld [hl], "▷"
-	ret
-; 28b77
-
-LinkEngine_FillBox: ; 28b77
-.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
-; 28b87
-
-LinkTrade: ; 28b87
-	xor a
-	ld [wcf57], a
-	ld [wOtherPlayerLinkAction], a
-	hlcoord 0, 12
-	ld b, 4
-	ld c, 18
-	call LinkTextboxAtHL
-	farcall Link_WaitBGMap
-	ld a, [wd002]
-	ld hl, wPartySpecies
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [hl]
-	ld [wd265], a
-	call GetPokemonName
-	ld hl, wStringBuffer1
-	ld de, wd004
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-	ld a, [wd003]
-	ld hl, wOTPartySpecies
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [hl]
-	ld [wd265], a
-	call GetPokemonName
-	ld hl, UnknownText_0x28eb8
-	bccoord 1, 14
-	call PlaceHLTextAtBC
-	call LoadStandardMenuHeader
-	hlcoord 10, 7
-	ld b, 3
-	ld c, 7
-	call LinkTextboxAtHL
-	ld de, String28eab
-	hlcoord 12, 8
-	call PlaceString
-	ld a, 8
-	ld [w2DMenuCursorInitY], a
-	ld a, 11
-	ld [w2DMenuCursorInitX], a
-	ld a, 1
-	ld [w2DMenuNumCols], a
-	ld a, 2
-	ld [w2DMenuNumRows], a
-	xor a
-	ld [w2DMenuFlags1], a
-	ld [w2DMenuFlags2], a
-	ld a, $20
-	ld [w2DMenuCursorOffsets], a
-	ld a, A_BUTTON | B_BUTTON
-	ld [wMenuJoypadFilter], a
-	ld a, 1
-	ld [wMenuCursorY], a
-	ld [wMenuCursorX], a
-	farcall Link_WaitBGMap
-	call ScrollingMenuJoypad
-	push af
-	call Call_ExitMenu
-	call WaitBGMap2
-	pop af
-	bit 1, a
-	jr nz, .asm_28c33
-	ld a, [wMenuCursorY]
-	dec a
-	jr z, .asm_28c54
-
-.asm_28c33
-	ld a, $1
-	ld [wPlayerLinkAction], a
-	hlcoord 0, 12
-	ld b, 4
-	ld c, 18
-	call LinkTextboxAtHL
-	hlcoord 1, 14
-	ld de, String_TooBadTheTradeWasCanceled
-	call PlaceString
-	farcall Function16d6ce
-	jp Function28ea3
-
-.asm_28c54
-	ld a, $2
-	ld [wPlayerLinkAction], a
-	farcall Function16d6ce
-	ld a, [wOtherPlayerLinkMode]
-	dec a
-	jr nz, .asm_28c7b
-	hlcoord 0, 12
-	ld b, 4
-	ld c, 18
-	call LinkTextboxAtHL
-	hlcoord 1, 14
-	ld de, String_TooBadTheTradeWasCanceled
-	call PlaceString
-	jp Function28ea3
-
-.asm_28c7b
-	ld hl, sPartyMail
-	ld a, [wd002]
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	ld d, h
-	ld e, l
-	ld bc, MAIL_STRUCT_LENGTH
-	add hl, bc
-	ld a, [wd002]
-	ld c, a
-.asm_28c96
-	inc c
-	ld a, c
-	cp PARTY_LENGTH
-	jr z, .asm_28ca6
-	push bc
-	ld bc, MAIL_STRUCT_LENGTH
-	call CopyBytes
-	pop bc
-	jr .asm_28c96
-
-.asm_28ca6
-	ld hl, sPartyMail
-	ld a, [wPartyCount]
-	dec a
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	push hl
-	ld hl, wc9f4
-	ld a, [wd003]
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	pop de
-	ld bc, MAIL_STRUCT_LENGTH
-	call CopyBytes
-	call CloseSRAM
-	ld hl, wPlayerName
-	ld de, wPlayerTrademonSenderName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ld a, [wd002]
-	ld hl, wPartySpecies
-	ld b, 0
-	ld c, a
-	add hl, bc
-	ld a, [hl]
-	ld [wPlayerTrademonSpecies], a
-	push af
-	ld a, [wd002]
-	ld hl, wPartyMonOT
-	call SkipNames
-	ld de, wPlayerTrademonOTName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ld hl, wPartyMon1ID
-	ld a, [wd002]
-	call GetPartyLocation
-	ld a, [hli]
-	ld [wPlayerTrademonID], a
-	ld a, [hl]
-	ld [wPlayerTrademonID + 1], a
-	ld hl, wPartyMon1DVs
-	ld a, [wd002]
-	call GetPartyLocation
-	ld a, [hli]
-	ld [wPlayerTrademonDVs], a
-	ld a, [hl]
-	ld [wPlayerTrademonDVs + 1], a
-	ld a, [wd002]
-	ld hl, wPartyMon1Species
-	call GetPartyLocation
-	ld b, h
-	ld c, l
-	farcall GetCaughtGender
-	ld a, c
-	ld [wPlayerTrademonCaughtData], a
-	ld hl, wOTPlayerName
-	ld de, wOTTrademonSenderName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ld a, [wd003]
-	ld hl, wOTPartySpecies
-	ld b, 0
-	ld c, a
-	add hl, bc
-	ld a, [hl]
-	ld [wOTTrademonSpecies], a
-	ld a, [wd003]
-	ld hl, wOTPartyMonOT
-	call SkipNames
-	ld de, wOTTrademonOTName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ld hl, wOTPartyMon1ID
-	ld a, [wd003]
-	call GetPartyLocation
-	ld a, [hli]
-	ld [wOTTrademonID], a
-	ld a, [hl]
-	ld [wOTTrademonID + 1], a
-	ld hl, wOTPartyMon1DVs
-	ld a, [wd003]
-	call GetPartyLocation
-	ld a, [hli]
-	ld [wOTTrademonDVs], a
-	ld a, [hl]
-	ld [wOTTrademonDVs + 1], a
-	ld a, [wd003]
-	ld hl, wOTPartyMon1Species
-	call GetPartyLocation
-	ld b, h
-	ld c, l
-	farcall GetCaughtGender
-	ld a, c
-	ld [wOTTrademonCaughtData], a
-	ld a, [wd002]
-	ld [wCurPartyMon], a
-	ld hl, wPartySpecies
-	ld b, 0
-	ld c, a
-	add hl, bc
-	ld a, [hl]
-	ld [wd002], a
-	xor a ; REMOVE_PARTY
-	ld [wPokemonWithdrawDepositParameter], a
-	callfar RemoveMonFromPartyOrBox
-	ld a, [wPartyCount]
-	dec a
-	ld [wCurPartyMon], a
-	ld a, TRUE
-	ld [wForceEvolution], a
-	ld a, [wd003]
-	push af
-	ld hl, wOTPartySpecies
-	ld b, 0
-	ld c, a
-	add hl, bc
-	ld a, [hl]
-	ld [wd003], a
-	ld c, 100
-	call DelayFrames
-	call ClearTileMap
-	call LoadFontsBattleExtra
-	ld b, SCGB_DIPLOMA
-	call GetSGBLayout
-	ld a, [hSerialConnectionStatus]
-	cp USING_EXTERNAL_CLOCK
-	jr z, .player_2
-	predef TradeAnimation
-	jr .done_animation
-
-.player_2
-	predef TradeAnimationPlayer2
-
-.done_animation
-	pop af
-	ld c, a
-	ld [wCurPartyMon], a
-	ld hl, wOTPartySpecies
-	ld d, 0
-	ld e, a
-	add hl, de
-	ld a, [hl]
-	ld [wCurPartySpecies], a
-	ld hl, wOTPartyMon1Species
-	ld a, c
-	call GetPartyLocation
-	ld de, wTempMonSpecies
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call CopyBytes
-	predef AddTempmonToParty
-	ld a, [wPartyCount]
-	dec a
-	ld [wCurPartyMon], a
-	callfar EvolvePokemon
-	call ClearScreen
-	call LoadTradeScreenBorder
-	call SetTradeRoomBGPals
-	farcall Link_WaitBGMap
-	ld b, $1
-	pop af
-	ld c, a
-	cp MEW
-	jr z, .loop
-	ld a, [wCurPartySpecies]
-	cp MEW
-	jr z, .loop
-	ld b, $2
-	ld a, c
-	cp CELEBI
-	jr z, .loop
-	ld a, [wCurPartySpecies]
-	cp CELEBI
-	jr z, .loop
-	ld b, $0
-
-.loop
-	ld a, b
-	ld [wPlayerLinkAction], a
-	push bc
-	call Serial_PrintWaitingTextAndSyncAndExchangeNybble
-	pop bc
-	ld a, [wLinkMode]
-	cp LINK_TIMECAPSULE
-	jr z, .save
-	ld a, b
-	and a
-	jr z, .save
-	ld a, [wOtherPlayerLinkAction]
-	cp b
-	jr nz, .loop
-
-.save
-	farcall SaveAfterLinkTrade
-	farcall StubbedTrainerRankings_Trades
-	farcall BackupMobileEventIndex
-	ld c, 40
-	call DelayFrames
-	hlcoord 0, 12
-	ld b, 4
-	ld c, 18
-	call LinkTextboxAtHL
-	hlcoord 1, 14
-	ld de, String28ebd
-	call PlaceString
-	farcall Link_WaitBGMap
-	ld c, 50
-	call DelayFrames
-	ld a, [wLinkMode]
-	cp LINK_TIMECAPSULE
-	jp z, Gen2ToGen1LinkComms
-	jp Gen2ToGen2LinkComms
-; 28ea3
-
-Function28ea3: ; 28ea3
-	ld c, 100
-	call DelayFrames
-	jp InitTradeMenuDisplay
-; 28eab
-
-String28eab: ; 28eab
-	db   "TRADE"
-	next "CANCEL@"
-
-UnknownText_0x28eb8: ; 0x28eb8
-	; Trade @ for @ ?
-	text_jump UnknownText_0x1c4212
-	db "@"
-; 0x28ebd
-
-String28ebd: ; 28ebd
-	db   "Trade completed!@"
-
-String_TooBadTheTradeWasCanceled: ; 28ece
-	db   "Too bad! The trade"
-	next "was canceled!@"
-
-
-LinkTextboxAtHL: ; 28eef
-	ld d, h
-	ld e, l
-	farcall LinkTextbox
-	ret
-; 28ef8
-
-LoadTradeScreenBorder: ; 28ef8
-	farcall _LoadTradeScreenBorder
-	ret
-; 28eff
-
-SetTradeRoomBGPals: ; 28eff
-	farcall LoadTradeRoomBGPals_ ; just a nested farcall; so wasteful
-	call SetPalettes
-	ret
-; 28f09
-
-Unreferenced_Function28f09: ; 28f09
-	hlcoord 0, 0
-	ld b, 6
-	ld c, 18
-	call LinkTextboxAtHL
-	hlcoord 0, 8
-	ld b, 6
-	ld c, 18
-	call LinkTextboxAtHL
-	farcall PlaceTradePartnerNamesAndParty
-	ret
-; 28f24
-
-INCLUDE "engine/trade_animation.asm"
-
-CheckTimeCapsuleCompatibility: ; 29bfb
-; Checks to see if your party is compatible with the Gen 1 games.
-; Returns the following in wScriptVar:
-; 0: Party is okay
-; 1: At least one Pokémon was introduced in Gen 2
-; 2: At least one Pokémon has a move that was introduced in Gen 2
-; 3: At least one Pokémon is holding mail
-
-; If any party Pokémon was introduced in the Gen 2 games, don't let it in.
-	ld hl, wPartySpecies
-	ld b, PARTY_LENGTH
-.loop
-	ld a, [hli]
-	cp -1
-	jr z, .checkitem
-	cp JOHTO_POKEMON
-	jr nc, .mon_too_new
-	dec b
-	jr nz, .loop
-
-; If any party Pokémon is holding mail, don't let it in.
-.checkitem
-	ld a, [wPartyCount]
-	ld b, a
-	ld hl, wPartyMon1Item
-.itemloop
-	push hl
-	push bc
-	ld d, [hl]
-	farcall ItemIsMail
-	pop bc
-	pop hl
-	jr c, .mon_has_mail
-	ld de, PARTYMON_STRUCT_LENGTH
-	add hl, de
-	dec b
-	jr nz, .itemloop
-
-; If any party Pokémon has a move that was introduced in the Gen 2 games, don't let it in.
-	ld hl, wPartyMon1Moves
-	ld a, [wPartyCount]
-	ld b, a
-.move_loop
-	ld c, NUM_MOVES
-.move_next
-	ld a, [hli]
-	cp STRUGGLE + 1
-	jr nc, .move_too_new
-	dec c
-	jr nz, .move_next
-	ld de, wPartyMon2 - (wPartyMon1 + NUM_MOVES)
-	add hl, de
-	dec b
-	jr nz, .move_loop
-	xor a
-	jr .done
-
-.mon_too_new
-	ld [wd265], a
-	call GetPokemonName
-	ld a, $1
-	jr .done
-
-.move_too_new
-	push bc
-	ld [wd265], a
-	call GetMoveName
-	call CopyName1
-	pop bc
-	call Function29c67
-	ld a, $2
-	jr .done
-
-.mon_has_mail
-	call Function29c67
-	ld a, $3
-
-.done
-	ld [wScriptVar], a
-	ret
-; 29c67
-
-Function29c67: ; 29c67
-	ld a, [wPartyCount]
-	sub b
-	ld c, a
-	inc c
-	ld b, 0
-	ld hl, wPartyCount
-	add hl, bc
-	ld a, [hl]
-	ld [wd265], a
-	call GetPokemonName
-	ret
-; 29c7b
-
-EnterTimeCapsule: ; 29c7b
-	ld c, 10
-	call DelayFrames
-	ld a, $4
-	call Link_EnsureSync
-	ld c, 40
-	call DelayFrames
-	xor a
-	ld [hVBlank], a
-	inc a
-	ld [wLinkMode], a
-	ret
-; 29c92
-
-WaitForOtherPlayerToExit: ; 29c92
-	ld c, 3
-	call DelayFrames
-	ld a, CONNECTION_NOT_ESTABLISHED
-	ld [hSerialConnectionStatus], a
-	xor a
-	ld [rSB], a
-	ld [hSerialReceive], a
-	ld a, (0 << rSC_ON) | 1
-	ld [rSC], a
-	ld a, (1 << rSC_ON) | 1
-	ld [rSC], a
-	ld c, 3
-	call DelayFrames
-	xor a
-	ld [rSB], a
-	ld [hSerialReceive], a
-	ld a, (0 << rSC_ON) | 0
-	ld [rSC], a
-	ld a, (1 << rSC_ON) | 0
-	ld [rSC], a
-	ld c, 3
-	call DelayFrames
-	xor a
-	ld [rSB], a
-	ld [hSerialReceive], a
-	ld [rSC], a
-	ld c, 3
-	call DelayFrames
-	ld a, CONNECTION_NOT_ESTABLISHED
-	ld [hSerialConnectionStatus], a
-	ld a, [rIF]
-	push af
-	xor a
-	ld [rIF], a
-	ld a, $f
-	ld [rIE], a
-	pop af
-	ld [rIF], a
-	ld hl, wLinkTimeoutFrames
-	xor a
-	ld [hli], a
-	ld [hl], a
-	ld [hVBlank], a
-	ld [wLinkMode], a
-	ret
-; 29ce8
-
-SetBitsForLinkTradeRequest: ; 29ce8
-	ld a, LINK_TRADECENTER - 1
-	ld [wPlayerLinkAction], a
-	ld [wd265], a
-	ret
-; 29cf1
-
-SetBitsForBattleRequest: ; 29cf1
-	ld a, LINK_COLOSSEUM - 1
-	ld [wPlayerLinkAction], a
-	ld [wd265], a
-	ret
-; 29cfa
-
-SetBitsForTimeCapsuleRequest: ; 29cfa
-	ld a, $2
-	ld [rSB], a
-	xor a
-	ld [hSerialReceive], a
-	ld a, (0 << rSC_ON) | 0
-	ld [rSC], a
-	ld a, (1 << rSC_ON) | 0
-	ld [rSC], a
-	xor a ; LINK_TIMECAPSULE - 1
-	ld [wPlayerLinkAction], a
-	ld [wd265], a
-	ret
-; 29d11
-
-WaitForLinkedFriend: ; 29d11
-	ld a, [wPlayerLinkAction]
-	and a
-	jr z, .no_link_action
-	ld a, $2
-	ld [rSB], a
-	xor a
-	ld [hSerialReceive], a
-	ld a, (0 << rSC_ON) | 0
-	ld [rSC], a
-	ld a, (1 << rSC_ON) | 0
-	ld [rSC], a
-	call DelayFrame
-	call DelayFrame
-	call DelayFrame
-
-.no_link_action
-	ld a, $2
-	ld [wLinkTimeoutFrames + 1], a
-	ld a, $ff
-	ld [wLinkTimeoutFrames], a
-.loop
-	ld a, [hSerialConnectionStatus]
-	cp USING_INTERNAL_CLOCK
-	jr z, .connected
-	cp USING_EXTERNAL_CLOCK
-	jr z, .connected
-	ld a, CONNECTION_NOT_ESTABLISHED
-	ld [hSerialConnectionStatus], a
-	ld a, $2
-	ld [rSB], a
-	xor a
-	ld [hSerialReceive], a
-	ld a, (0 << rSC_ON) | 0
-	ld [rSC], a
-	ld a, (1 << rSC_ON) | 0
-	ld [rSC], a
-	ld a, [wLinkTimeoutFrames]
-	dec a
-	ld [wLinkTimeoutFrames], a
-	jr nz, .not_done
-	ld a, [wLinkTimeoutFrames + 1]
-	dec a
-	ld [wLinkTimeoutFrames + 1], a
-	jr z, .done
-
-.not_done
-	ld a, $1
-	ld [rSB], a
-	ld a, (0 << rSC_ON) | 1
-	ld [rSC], a
-	ld a, (1 << rSC_ON) | 1
-	ld [rSC], a
-	call DelayFrame
-	jr .loop
-
-.connected
-	call LinkDataReceived
-	call DelayFrame
-	call LinkDataReceived
-	ld c, 50
-	call DelayFrames
-	ld a, $1
-	ld [wScriptVar], a
-	ret
-
-.done
-	xor a
-	ld [wScriptVar], a
-	ret
-; 29d92
-
-CheckLinkTimeout: ; 29d92
-	ld a, $1
-	ld [wPlayerLinkAction], a
-	ld hl, wLinkTimeoutFrames
-	ld a, $3
-	ld [hli], a
-	xor a
-	ld [hl], a
-	call WaitBGMap
-	ld a, $2
-	ld [hVBlank], a
-	call DelayFrame
-	call DelayFrame
-	call Link_CheckCommunicationError
-	xor a
-	ld [hVBlank], a
-	ld a, [wScriptVar]
-	and a
-	ret nz
-	jp Link_ResetSerialRegistersAfterLinkClosure
-; 29dba
-
-Function29dba: ; 29dba
-	ld a, $5
-	ld [wPlayerLinkAction], a
-	ld hl, wLinkTimeoutFrames
-	ld a, $3
-	ld [hli], a
-	xor a
-	ld [hl], a
-	call WaitBGMap
-	ld a, $2
-	ld [hVBlank], a
-	call DelayFrame
-	call DelayFrame
-	call Link_CheckCommunicationError
-	ld a, [wScriptVar]
-	and a
-	jr z, .vblank
-	ld bc, -1
-.wait
-	dec bc
-	ld a, b
-	or c
-	jr nz, .wait
-	ld a, [wOtherPlayerLinkMode]
-	cp $5
-	jr nz, .script_var
-	ld a, $6
-	ld [wPlayerLinkAction], a
-	ld hl, wLinkTimeoutFrames
-	ld a, $1
-	ld [hli], a
-	ld [hl], $32
-	call Link_CheckCommunicationError
-	ld a, [wOtherPlayerLinkMode]
-	cp $6
-	jr z, .vblank
-
-.script_var
-	xor a
-	ld [wScriptVar], a
-	ret
-
-.vblank
-	xor a
-	ld [hVBlank], a
-	ret
-; 29e0c
-
-Link_CheckCommunicationError: ; 29e0c
-	xor a
-	ld [hSerialReceivedNewData], a
-	ld a, [wLinkTimeoutFrames]
-	ld h, a
-	ld a, [wLinkTimeoutFrames + 1]
-	ld l, a
-	push hl
-	call .CheckConnected
-	pop hl
-	jr nz, .load_true
-	call .AcknowledgeSerial
-	call .ConvertDW
-	call .CheckConnected
-	jr nz, .load_true
-	call .AcknowledgeSerial
-	xor a
-	jr .load_scriptvar
-
-.load_true
-	ld a, $1
-
-.load_scriptvar
-	ld [wScriptVar], a
-	ld hl, wLinkTimeoutFrames
-	xor a
-	ld [hli], a
-	ld [hl], a
-	ret
-; 29e3b
-
-.CheckConnected: ; 29e3b
-	call WaitLinkTransfer
-	ld hl, wLinkTimeoutFrames
-	ld a, [hli]
-	inc a
-	ret nz
-	ld a, [hl]
-	inc a
-	ret
-; 29e47
-
-.AcknowledgeSerial: ; 29e47
-	ld b, 10
-.loop
-	call DelayFrame
-	call LinkDataReceived
-	dec b
-	jr nz, .loop
-	ret
-; 29e53
-
-.ConvertDW: ; 29e53
-	; [wLinkTimeoutFrames] = ((hl - $100) / 4) + $100
-	;                      = (hl / 4) + $c0
-	dec h
-	srl h
-	rr l
-	srl h
-	rr l
-	inc h
-	ld a, h
-	ld [wLinkTimeoutFrames], a
-	ld a, l
-	ld [wLinkTimeoutFrames + 1], a
-	ret
-; 29e66
-
-TryQuickSave: ; 29e66
-	ld a, [wd265]
-	push af
-	farcall Link_SaveGame
-	ld a, TRUE
-	jr nc, .return_result
-	xor a ; FALSE
-.return_result
-	ld [wScriptVar], a
-	ld c, 30
-	call DelayFrames
-	pop af
-	ld [wd265], a
-	ret
-; 29e82
-
-CheckBothSelectedSameRoom: ; 29e82
-	ld a, [wd265]
-	call Link_EnsureSync
-	push af
-	call LinkDataReceived
-	call DelayFrame
-	call LinkDataReceived
-	pop af
-	ld b, a
-	ld a, [wd265]
-	cp b
-	jr nz, .fail
-	ld a, [wd265]
-	inc a
-	ld [wLinkMode], a
-	xor a
-	ld [hVBlank], a
-	ld a, TRUE
-	ld [wScriptVar], a
-	ret
-
-.fail
-	xor a ; FALSE
-	ld [wScriptVar], a
-	ret
-; 29eaf
-
-TimeCapsule: ; 29eaf
-	ld a, LINK_TIMECAPSULE
-	ld [wLinkMode], a
-	call DisableSpriteUpdates
-	callfar LinkCommunications
-	call EnableSpriteUpdates
-	xor a
-	ld [hVBlank], a
-	ret
-; 29ec4
-
-TradeCenter: ; 29ec4
-	ld a, LINK_TRADECENTER
-	ld [wLinkMode], a
-	call DisableSpriteUpdates
-	callfar LinkCommunications
-	call EnableSpriteUpdates
-	xor a
-	ld [hVBlank], a
-	ret
-; 29ed9
-
-Colosseum: ; 29ed9
-	ld a, LINK_COLOSSEUM
-	ld [wLinkMode], a
-	call DisableSpriteUpdates
-	callfar LinkCommunications
-	call EnableSpriteUpdates
-	xor a
-	ld [hVBlank], a
-	ret
-; 29eee
-
-CloseLink: ; 29eee
-	xor a
-	ld [wLinkMode], a
-	ld c, 3
-	call DelayFrames
-	jp Link_ResetSerialRegistersAfterLinkClosure
-; 29efa
-
-FailedLinkToPast: ; 29efa
-	ld c, 40
-	call DelayFrames
-	ld a, $e
-	jp Link_EnsureSync
-; 29f04
-
-Link_ResetSerialRegistersAfterLinkClosure: ; 29f04
-	ld c, 3
-	call DelayFrames
-	ld a, CONNECTION_NOT_ESTABLISHED
-	ld [hSerialConnectionStatus], a
-	ld a, $2
-	ld [rSB], a
-	xor a
-	ld [hSerialReceive], a
-	ld [rSC], a
-	ret
-; 29f17
-
-Link_EnsureSync: ; 29f17
-	add $d0
-	ld [wPlayerLinkAction], a
-	ld [wcf57], a
-	ld a, $2
-	ld [hVBlank], a
-	call DelayFrame
-	call DelayFrame
-.receive_loop
-	call Serial_ExchangeLinkMenuSelection
-	ld a, [wOtherPlayerLinkMode]
-	ld b, a
-	and $f0
-	cp $d0
-	jr z, .done
-	ld a, [wOtherPlayerLinkAction]
-	ld b, a
-	and $f0
-	cp $d0
-	jr nz, .receive_loop
-
-.done
-	xor a
-	ld [hVBlank], a
-	ld a, b
-	and $f
-	ret
-; 29f47
-
-CableClubCheckWhichChris: ; 29f47
-	ld a, [hSerialConnectionStatus]
-	cp USING_EXTERNAL_CLOCK
-	ld a, TRUE
-	jr z, .yes
-	dec a ; FALSE
-
-.yes
-	ld [wScriptVar], a
-	ret
-; 29f54
-
-Unreferenced_Gen1LinkCommsBorderGFX: ; 29f54
-INCBIN "gfx/trade/unused_gen_1_border_tiles.2bpp"
-; 29fe4
-
-Unreferenced_Function29fe4:
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	ld d, FALSE
-	ld b, CHECK_FLAG
-	predef SmallFarFlagAction
-	call CloseSRAM
-	ld a, c
-	and a
-	ret
--- /dev/null
+++ b/engine/link/link.asm
@@ -1,0 +1,2589 @@
+LinkCommunications: ; 28000
+	call ClearBGPalettes
+	ld c, 80
+	call DelayFrames
+	call ClearScreen
+	call ClearSprites
+	call UpdateSprites
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld c, 80
+	call DelayFrames
+	call ClearScreen
+	call UpdateSprites
+	call LoadStandardFont
+	call LoadFontsBattleExtra
+	farcall LinkComms_LoadPleaseWaitTextboxBorderGFX
+	call WaitBGMap2
+	hlcoord 3, 8
+	ld b, 2
+	ld c, 12
+	ld d, h
+	ld e, l
+	farcall LinkTextbox2
+	hlcoord 4, 10
+	ld de, String_PleaseWait
+	call PlaceString
+	call SetTradeRoomBGPals
+	call WaitBGMap2
+	ld hl, wcf5d
+	xor a ; LOW($5000)
+	ld [hli], a
+	ld [hl], HIGH($5000)
+	ld a, [wLinkMode]
+	cp LINK_TIMECAPSULE
+	jp nz, Gen2ToGen2LinkComms
+
+Gen2ToGen1LinkComms: ; 2805d
+	call ClearLinkData
+	call Link_PrepPartyData_Gen1
+	call FixDataForLinkTransfer
+	xor a
+	ld [wPlayerLinkAction], a
+	call WaitLinkTransfer
+	ld a, [hSerialConnectionStatus]
+	cp USING_INTERNAL_CLOCK
+	jr nz, .player_1
+
+	ld c, 3
+	call DelayFrames
+	xor a
+	ld [hSerialSend], a
+	ld a, (0 << rSC_ON) | 1
+	ld [rSC], a
+	ld a, (1 << rSC_ON) | 1
+	ld [rSC], a
+
+	call DelayFrame
+	xor a
+	ld [hSerialSend], a
+	ld a, (0 << rSC_ON) | 1
+	ld [rSC], a
+	ld a, (1 << rSC_ON) | 1
+	ld [rSC], a
+
+.player_1
+	ld de, MUSIC_NONE
+	call PlayMusic
+	ld c, 3
+	call DelayFrames
+	xor a
+	ld [rIF], a
+	ld a, $8
+	ld [rIE], a
+	ld hl, wd1f3
+	ld de, wEnemyMonSpecies
+	ld bc, $11
+	call Serial_ExchangeBytes
+	ld a, SERIAL_NO_DATA_BYTE
+	ld [de], a
+	ld hl, wLinkData
+	ld de, wOTPlayerName
+	ld bc, $1a8
+	call Serial_ExchangeBytes
+	ld a, SERIAL_NO_DATA_BYTE
+	ld [de], a
+	ld hl, wMisc
+	ld de, wPlayerTrademonSpecies
+	ld bc, wPlayerTrademonSpecies - wMisc
+	call Serial_ExchangeBytes
+	xor a
+	ld [rIF], a
+	ld a, $1d
+	ld [rIE], a
+	call Link_CopyRandomNumbers
+	ld hl, wOTPlayerName
+	call Link_FindFirstNonControlCharacter_SkipZero
+	push hl
+	ld bc, NAME_LENGTH
+	add hl, bc
+	ld a, [hl]
+	pop hl
+	and a
+	jp z, Function28b22
+	cp $7
+	jp nc, Function28b22
+	ld de, wLinkData
+	ld bc, $1a2
+	call Link_CopyOTData
+	ld de, wPlayerTrademonSpecies
+	ld hl, wTimeCapsulePartyMon1Species
+	ld c, 2
+.loop
+	ld a, [de]
+	inc de
+	and a
+	jr z, .loop
+	cp SERIAL_PREAMBLE_BYTE
+	jr z, .loop
+	cp SERIAL_NO_DATA_BYTE
+	jr z, .loop
+	cp SERIAL_PATCH_LIST_PART_TERMINATOR
+	jr z, .next
+	push hl
+	push bc
+	ld b, 0
+	dec a
+	ld c, a
+	add hl, bc
+	ld a, SERIAL_NO_DATA_BYTE
+	ld [hl], a
+	pop bc
+	pop hl
+	jr .loop
+
+.next
+	ld hl, wc90f
+	dec c
+	jr nz, .loop
+	ld hl, wLinkPlayerName
+	ld de, wOTPlayerName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ld de, wOTPartyCount
+	ld a, [hli]
+	ld [de], a
+	inc de
+.party_loop
+	ld a, [hli]
+	cp -1
+	jr z, .done_party
+	ld [wd265], a
+	push hl
+	push de
+	callfar ConvertMon_1to2
+	pop de
+	pop hl
+	ld a, [wd265]
+	ld [de], a
+	inc de
+	jr .party_loop
+
+.done_party
+	ld [de], a
+	ld hl, wTimeCapsulePartyMon1Species
+	call Function2868a
+	ld a, LOW(wOTPartyMonOT)
+	ld [wUnusedD102], a
+	ld a, HIGH(wOTPartyMonOT)
+	ld [wUnusedD102 + 1], a
+	ld de, MUSIC_NONE
+	call PlayMusic
+	ld a, [hSerialConnectionStatus]
+	cp USING_INTERNAL_CLOCK
+	ld c, 66
+	call z, DelayFrames
+	ld de, MUSIC_ROUTE_30
+	call PlayMusic
+	jp InitTradeMenuDisplay
+; 28177
+
+Gen2ToGen2LinkComms: ; 28177
+	call ClearLinkData
+	call Link_PrepPartyData_Gen2
+	call FixDataForLinkTransfer
+	call Function29dba
+	ld a, [wScriptVar]
+	and a
+	jp z, LinkTimeout
+	ld a, [hSerialConnectionStatus]
+	cp USING_INTERNAL_CLOCK
+	jr nz, .Player1
+
+	ld c, 3
+	call DelayFrames
+	xor a
+	ld [hSerialSend], a
+	ld a, (0 << rSC_ON) | 1
+	ld [rSC], a
+	ld a, (1 << rSC_ON) | 1
+	ld [rSC], a
+
+	call DelayFrame
+	xor a
+	ld [hSerialSend], a
+	ld a, (0 << rSC_ON) | 1
+	ld [rSC], a
+	ld a, (1 << rSC_ON) | 1
+	ld [rSC], a
+
+.Player1:
+	ld de, MUSIC_NONE
+	call PlayMusic
+	ld c, 3
+	call DelayFrames
+	xor a
+	ld [rIF], a
+	ld a, $8
+	ld [rIE], a
+	ld hl, wd1f3
+	ld de, wEnemyMonSpecies
+	ld bc, $11
+	call Serial_ExchangeBytes
+	ld a, SERIAL_NO_DATA_BYTE
+	ld [de], a
+	ld hl, wLinkData
+	ld de, wOTPlayerName
+	ld bc, $1c2
+	call Serial_ExchangeBytes
+	ld a, SERIAL_NO_DATA_BYTE
+	ld [de], a
+	ld hl, wMisc
+	ld de, wPlayerTrademonSpecies
+	ld bc, $c8
+	call Serial_ExchangeBytes
+	ld a, [wLinkMode]
+	cp LINK_TRADECENTER
+	jr nz, .not_trading
+	ld hl, wc9f4
+	ld de, wcb84
+	ld bc, $186
+	call ExchangeBytes
+
+.not_trading
+	xor a
+	ld [rIF], a
+	ld a, $1d
+	ld [rIE], a
+	ld de, MUSIC_NONE
+	call PlayMusic
+	call Link_CopyRandomNumbers
+	ld hl, wOTPlayerName
+	call Link_FindFirstNonControlCharacter_SkipZero
+	ld de, wLinkData
+	ld bc, $1b9
+	call Link_CopyOTData
+	ld de, wPlayerTrademonSpecies
+	ld hl, wLinkPlayerPartyMon1Species
+	ld c, 2
+.loop1
+	ld a, [de]
+	inc de
+	and a
+	jr z, .loop1
+	cp SERIAL_PREAMBLE_BYTE
+	jr z, .loop1
+	cp SERIAL_NO_DATA_BYTE
+	jr z, .loop1
+	cp SERIAL_PATCH_LIST_PART_TERMINATOR
+	jr z, .next1
+	push hl
+	push bc
+	ld b, 0
+	dec a
+	ld c, a
+	add hl, bc
+	ld a, SERIAL_NO_DATA_BYTE
+	ld [hl], a
+	pop bc
+	pop hl
+	jr .loop1
+
+.next1
+	ld hl, wc90f
+	dec c
+	jr nz, .loop1
+	ld a, [wLinkMode]
+	cp LINK_TRADECENTER
+	jp nz, .skip_mail
+	ld hl, wcb84
+.loop2
+	ld a, [hli]
+	cp MAIL_MSG_LENGTH
+	jr nz, .loop2
+.loop3
+	ld a, [hli]
+	cp SERIAL_NO_DATA_BYTE
+	jr z, .loop3
+	cp MAIL_MSG_LENGTH
+	jr z, .loop3
+	dec hl
+	ld de, wcb84
+	ld bc, $190 ; 400
+	call CopyBytes
+	ld hl, wcb84
+	ld bc, $c6 ; 198
+.loop4
+	ld a, [hl]
+	cp MAIL_MSG_LENGTH + 1
+	jr nz, .okay1
+	ld [hl], SERIAL_NO_DATA_BYTE
+.okay1
+	inc hl
+	dec bc
+	ld a, b
+	or c
+	jr nz, .loop4
+	ld de, wcc9e
+.loop5
+	ld a, [de]
+	inc de
+	cp SERIAL_PATCH_LIST_PART_TERMINATOR
+	jr z, .start_copying_mail
+	ld hl, wcc4a
+	dec a
+	ld b, $0
+	ld c, a
+	add hl, bc
+	ld [hl], SERIAL_NO_DATA_BYTE
+	jr .loop5
+
+.start_copying_mail
+	ld hl, wcb84
+	ld de, wc9f4
+	ld b, PARTY_LENGTH
+.copy_mail_loop
+	push bc
+	ld bc, MAIL_MSG_LENGTH + 1
+	call CopyBytes
+	ld a, LOW(MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 1))
+	add e
+	ld e, a
+	ld a, HIGH(MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 1))
+	adc d
+	ld d, a
+	pop bc
+	dec b
+	jr nz, .copy_mail_loop
+	ld de, wc9f4
+	ld b, PARTY_LENGTH
+.copy_author_loop
+	push bc
+	ld a, LOW(MAIL_MSG_LENGTH + 1)
+	add e
+	ld e, a
+	ld a, HIGH(MAIL_MSG_LENGTH + 1)
+	adc d
+	ld d, a
+	ld bc, MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 1)
+	call CopyBytes
+	pop bc
+	dec b
+	jr nz, .copy_author_loop
+	ld b, PARTY_LENGTH
+	ld de, wc9f4
+.fix_mail_loop
+	push bc
+	push de
+	farcall IsMailEuropean
+	ld a, c
+	or a
+	jr z, .next
+	sub $3
+	jr nc, .skip
+	farcall DeutenEnglischenPost
+	jr .next
+
+.skip
+	cp $2
+	jr nc, .next
+	farcall HandleSpanishItalianMail
+
+.next
+	pop de
+	ld hl, MAIL_STRUCT_LENGTH
+	add hl, de
+	ld d, h
+	ld e, l
+	pop bc
+	dec b
+	jr nz, .fix_mail_loop
+	ld de, wcb0e
+	xor a
+	ld [de], a
+
+.skip_mail
+	ld hl, wLinkPlayerName
+	ld de, wOTPlayerName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ld de, wOTPartyCount
+	ld bc, 1 + PARTY_LENGTH + 1
+	call CopyBytes
+	ld de, wOTPlayerID
+	ld bc, 2
+	call CopyBytes
+	ld de, wOTPartyMons
+	ld bc, wOTPartyDataEnd - wOTPartyMons
+	call CopyBytes
+	ld a, LOW(wOTPartyMonOT)
+	ld [wUnusedD102], a
+	ld a, HIGH(wOTPartyMonOT)
+	ld [wUnusedD102 + 1], a
+	ld de, MUSIC_NONE
+	call PlayMusic
+	ld a, [hSerialConnectionStatus]
+	cp USING_INTERNAL_CLOCK
+	ld c, 66
+	call z, DelayFrames
+	ld a, [wLinkMode]
+	cp LINK_COLOSSEUM
+	jr nz, .ready_to_trade
+	ld a, CAL
+	ld [wOtherTrainerClass], a
+	call ClearScreen
+	farcall Link_WaitBGMap
+	ld hl, wOptions
+	ld a, [hl]
+	push af
+	and 1 << STEREO
+	or TEXT_DELAY_MED
+	ld [hl], a
+	ld hl, wOTPlayerName
+	ld de, wOTClassName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	call ReturnToMapFromSubmenu
+
+	; LET'S DO THIS
+	ld a, [wDisableTextAcceleration]
+	push af
+	ld a, 1
+	ld [wDisableTextAcceleration], a
+	ld a, [rIE]
+	push af
+	ld a, [rIF]
+	push af
+	xor a
+	ld [rIF], a
+	ld a, [rIE]
+	set 1, a
+	ld [rIE], a
+	pop af
+	ld [rIF], a
+
+	predef StartBattle
+
+	ld a, [rIF]
+	ld h, a
+	xor a
+	ld [rIF], a
+	pop af
+	ld [rIE], a
+	ld a, h
+	ld [rIF], a
+	pop af
+	ld [wDisableTextAcceleration], a
+	pop af
+	ld [wOptions], a
+	farcall LoadPokemonData
+	jp Function28b22
+
+.ready_to_trade
+	ld de, MUSIC_ROUTE_30
+	call PlayMusic
+	jp InitTradeMenuDisplay
+; 283b2
+
+LinkTimeout: ; 283b2
+	ld de, .TooMuchTimeHasElapsed
+	ld b, 10
+.loop
+	call DelayFrame
+	call LinkDataReceived
+	dec b
+	jr nz, .loop
+	xor a
+	ld [hld], a
+	ld [hl], a
+	ld [hVBlank], a
+	push de
+	hlcoord 0, 12
+	ld b, 4
+	ld c, 18
+	push de
+	ld d, h
+	ld e, l
+	farcall LinkTextbox2
+	pop de
+	pop hl
+	bccoord 1, 14
+	call PlaceHLTextAtBC
+	call RotateThreePalettesRight
+	call ClearScreen
+	ld b, SCGB_DIPLOMA
+	call GetSGBLayout
+	call WaitBGMap2
+	ret
+; 283ed
+
+.TooMuchTimeHasElapsed: ; 0x283ed
+	; Too much time has elapsed. Please try again.
+	text_jump UnknownText_0x1c4183
+	db "@"
+; 0x283f2
+
+ExchangeBytes: ; 283f2
+	ld a, TRUE
+	ld [hSerialIgnoringInitialData], a
+.loop
+	ld a, [hl]
+	ld [hSerialSend], a
+	call Serial_ExchangeByte
+	push bc
+	ld b, a
+	inc hl
+	ld a, 48
+.delay_cycles
+	dec a
+	jr nz, .delay_cycles
+	ld a, [hSerialIgnoringInitialData]
+	and a
+	ld a, b
+	pop bc
+	jr z, .load
+	dec hl
+	xor a
+	ld [hSerialIgnoringInitialData], a
+	jr .loop
+
+.load
+	ld [de], a
+	inc de
+	dec bc
+	ld a, b
+	or c
+	jr nz, .loop
+	ret
+; 28419
+
+String_PleaseWait: ; 28419
+	db "PLEASE WAIT!@"
+; 28426
+
+ClearLinkData: ; 28426
+	ld hl, wLinkData
+	ld bc, wLinkDataEnd - wLinkData
+.loop
+	xor a
+	ld [hli], a
+	dec bc
+	ld a, b
+	or c
+	jr nz, .loop
+	ret
+; 28434
+
+FixDataForLinkTransfer: ; 28434
+	ld hl, wd1f3
+	ld a, SERIAL_PREAMBLE_BYTE
+	ld b, wLinkBattleRNs - wd1f3
+.loop1
+	ld [hli], a
+	dec b
+	jr nz, .loop1
+	ld b, wTempEnemyMonSpecies - wLinkBattleRNs
+.loop2
+	call Random
+	cp SERIAL_PREAMBLE_BYTE
+	jr nc, .loop2
+	ld [hli], a
+	dec b
+	jr nz, .loop2
+	ld hl, wMisc
+	ld a, SERIAL_PREAMBLE_BYTE
+	ld [hli], a
+	ld [hli], a
+	ld [hli], a
+	ld b, $c8
+	xor a
+.loop3
+	ld [hli], a
+	dec b
+	jr nz, .loop3
+	ld hl, wTimeCapsulePartyMon1 - 1 + 6
+	ld de, wc612
+	lb bc, 0, 0
+.loop4
+	inc c
+	ld a, c
+	cp SERIAL_PREAMBLE_BYTE
+	jr z, .next1
+	ld a, b
+	dec a
+	jr nz, .next2
+	push bc
+	ld a, [wLinkMode]
+	cp LINK_TIMECAPSULE
+	ld b, $d
+	jr z, .got_value
+	ld b, $27
+.got_value
+	ld a, c
+	cp b
+	pop bc
+	jr z, .done
+.next2
+	inc hl
+	ld a, [hl]
+	cp SERIAL_NO_DATA_BYTE
+	jr nz, .loop4
+	ld a, c
+	ld [de], a
+	inc de
+	ld [hl], SERIAL_PATCH_LIST_PART_TERMINATOR
+	jr .loop4
+
+.next1
+	ld a, SERIAL_PATCH_LIST_PART_TERMINATOR
+	ld [de], a
+	inc de
+	lb bc, 1, 0
+	jr .loop4
+
+.done
+	ld a, SERIAL_PATCH_LIST_PART_TERMINATOR
+	ld [de], a
+	ret
+; 28499
+
+Link_PrepPartyData_Gen1: ; 28499
+	ld de, wLinkData
+	ld a, SERIAL_PREAMBLE_BYTE
+	ld b, PARTY_LENGTH
+.loop1
+	ld [de], a
+	inc de
+	dec b
+	jr nz, .loop1
+	ld hl, wPlayerName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	push de
+	ld hl, wPartyCount
+	ld a, [hli]
+	ld [de], a
+	inc de
+.loop2
+	ld a, [hli]
+	cp -1
+	jr z, .done_party
+	ld [wd265], a
+	push hl
+	push de
+	callfar ConvertMon_2to1
+	pop de
+	pop hl
+	ld a, [wd265]
+	ld [de], a
+	inc de
+	jr .loop2
+
+.done_party
+	ld [de], a
+	pop de
+	ld hl, 1 + PARTY_LENGTH + 1
+	add hl, de
+	ld d, h
+	ld e, l
+	ld hl, wPartyMon1Species
+	ld c, PARTY_LENGTH
+.mon_loop
+	push bc
+	call .ConvertPartyStruct2to1
+	ld bc, PARTYMON_STRUCT_LENGTH
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .mon_loop
+	ld hl, wPartyMonOT
+	call .copy_ot_nicks
+	ld hl, wPartyMonNicknames
+.copy_ot_nicks
+	ld bc, PARTY_LENGTH * NAME_LENGTH
+	jp CopyBytes
+; 284f6
+
+.ConvertPartyStruct2to1: ; 284f6
+	ld b, h
+	ld c, l
+	push de
+	push bc
+	ld a, [hl]
+	ld [wd265], a
+	callfar ConvertMon_2to1
+	pop bc
+	pop de
+	ld a, [wd265]
+	ld [de], a
+	inc de
+	ld hl, MON_HP
+	add hl, bc
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+	inc de
+	xor a
+	ld [de], a
+	inc de
+	ld hl, MON_STATUS
+	add hl, bc
+	ld a, [hl]
+	ld [de], a
+	inc de
+	ld a, [bc]
+	cp MAGNEMITE
+	jr z, .steel_type
+	cp MAGNETON
+	jr nz, .skip_steel
+
+.steel_type
+	ld a, ELECTRIC
+	ld [de], a
+	inc de
+	ld [de], a
+	inc de
+	jr .done_steel
+
+.skip_steel
+	push bc
+	dec a
+	ld hl, BaseData + BASE_TYPES
+	ld bc, BASE_DATA_SIZE
+	call AddNTimes
+	ld bc, BASE_CATCH_RATE - BASE_TYPES
+	ld a, BANK(BaseData)
+	call FarCopyBytes
+	pop bc
+
+.done_steel
+	push bc
+	ld hl, MON_ITEM
+	add hl, bc
+	ld bc, MON_HAPPINESS - MON_ITEM
+	call CopyBytes
+	pop bc
+
+	ld hl, MON_LEVEL
+	add hl, bc
+	ld a, [hl]
+	ld [de], a
+	ld [wCurPartyLevel], a
+	inc de
+
+	push bc
+	ld hl, MON_MAXHP
+	add hl, bc
+	ld bc, MON_SAT - MON_MAXHP
+	call CopyBytes
+	pop bc
+
+	push de
+	push bc
+
+	ld a, [bc]
+	dec a
+	push bc
+	ld b, 0
+	ld c, a
+	ld hl, KantoMonSpecials
+	add hl, bc
+	ld a, BANK(KantoMonSpecials)
+	call GetFarByte
+	ld [wBaseSpecialAttack], a
+	pop bc
+
+	ld hl, MON_STAT_EXP - 1
+	add hl, bc
+	ld c, STAT_SATK
+	ld b, TRUE
+	predef CalcMonStatC
+
+	pop bc
+	pop de
+
+	ld a, [hQuotient + 1]
+	ld [de], a
+	inc de
+	ld a, [hQuotient + 2]
+	ld [de], a
+	inc de
+	ld h, b
+	ld l, c
+	ret
+; 28595
+
+Link_PrepPartyData_Gen2: ; 28595
+	ld de, wLinkData
+	ld a, SERIAL_PREAMBLE_BYTE
+	ld b, PARTY_LENGTH
+.loop1
+	ld [de], a
+	inc de
+	dec b
+	jr nz, .loop1
+	ld hl, wPlayerName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ld hl, wPartyCount
+	ld bc, 1 + PARTY_LENGTH + 1
+	call CopyBytes
+	ld hl, wPlayerID
+	ld bc, 2
+	call CopyBytes
+	ld hl, wPartyMon1Species
+	ld bc, PARTY_LENGTH * PARTYMON_STRUCT_LENGTH
+	call CopyBytes
+	ld hl, wPartyMonOT
+	ld bc, PARTY_LENGTH * NAME_LENGTH
+	call CopyBytes
+	ld hl, wPartyMonNicknames
+	ld bc, PARTY_LENGTH * MON_NAME_LENGTH
+	call CopyBytes
+
+; Okay, we did all that.  Now, are we in the trade center?
+	ld a, [wLinkMode]
+	cp LINK_TRADECENTER
+	ret nz
+
+; Fill 5 bytes at wc9f4 with $20
+	ld de, wc9f4
+	ld a, $20
+	call Function28682
+
+; Copy all the mail messages to wc9f9
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	ld hl, sPartyMail
+	ld b, PARTY_LENGTH
+.loop2
+	push bc
+	ld bc, MAIL_MSG_LENGTH + 1
+	call CopyBytes
+	ld bc, sPartyMon1MailEnd - sPartyMon1MailAuthor
+	add hl, bc
+	pop bc
+	dec b
+	jr nz, .loop2
+; Copy the mail data to wcabf
+	ld hl, sPartyMail
+	ld b, PARTY_LENGTH
+.loop3
+	push bc
+	ld bc, MAIL_MSG_LENGTH + 1
+	add hl, bc
+	ld bc, sPartyMon1MailEnd - sPartyMon1MailAuthor
+	call CopyBytes
+	pop bc
+	dec b
+	jr nz, .loop3
+
+	ld b, PARTY_LENGTH
+	ld de, sPartyMail
+	ld hl, wc9f9
+.loop4
+	push bc
+	push hl
+	push de
+	push hl
+	farcall IsMailEuropean
+	pop de
+	ld a, c
+	or a
+	jr z, .next
+	sub $3
+	jr nc, .italian_spanish
+	farcall HandleFrenchGermanMail
+	jr .next
+
+.italian_spanish
+	cp $2
+	jr nc, .next
+	farcall HandleSpanishItalianMail
+
+.next
+	pop de
+	ld hl, MAIL_STRUCT_LENGTH
+	add hl, de
+	ld d, h
+	ld e, l
+	pop hl
+	ld bc, sPartyMon1MailAuthor - sPartyMon1Mail
+	add hl, bc
+	pop bc
+	dec b
+	jr nz, .loop4
+	call CloseSRAM
+	ld hl, wc9f9
+	ld bc, PARTY_LENGTH * (sPartyMon1MailAuthor - sPartyMon1Mail)
+.loop5
+	ld a, [hl]
+	cp SERIAL_NO_DATA_BYTE
+	jr nz, .skip2
+	ld [hl], sPartyMon1MailAuthor - sPartyMon1Mail
+
+.skip2
+	inc hl
+	dec bc
+	ld a, b
+	or c
+	jr nz, .loop5
+	ld hl, wcabf
+	ld de, wcb13
+	ld b, PARTY_LENGTH * (sPartyMon1MailEnd - sPartyMon1MailAuthor)
+	ld c, $0
+.loop6
+	inc c
+	ld a, [hl]
+	cp SERIAL_NO_DATA_BYTE
+	jr nz, .skip3
+	ld [hl], SERIAL_PATCH_LIST_PART_TERMINATOR
+	ld a, c
+	ld [de], a
+	inc de
+
+.skip3
+	inc hl
+	dec b
+	jr nz, .loop6
+	ld a, SERIAL_PATCH_LIST_PART_TERMINATOR
+	ld [de], a
+	ret
+; 28682
+
+Function28682: ; 28682
+	ld c, 5
+.loop
+	ld [de], a
+	inc de
+	dec c
+	jr nz, .loop
+	ret
+; 2868a
+
+Function2868a: ; 2868a
+	push hl
+	ld d, h
+	ld e, l
+	ld bc, wLinkOTPartyMonTypes
+	ld hl, wcbe8
+	ld a, c
+	ld [hli], a
+	ld [hl], b
+	ld hl, wOTPartyMon1Species
+	ld c, PARTY_LENGTH
+.loop
+	push bc
+	call .ConvertToGen2
+	pop bc
+	dec c
+	jr nz, .loop
+	pop hl
+	ld bc, PARTY_LENGTH * REDMON_STRUCT_LENGTH
+	add hl, bc
+	ld de, wOTPartyMonOT
+	ld bc, PARTY_LENGTH * NAME_LENGTH
+	call CopyBytes
+	ld de, wOTPartyMonNicknames
+	ld bc, PARTY_LENGTH * MON_NAME_LENGTH
+	jp CopyBytes
+; 286ba
+
+.ConvertToGen2: ; 286ba
+	ld b, h
+	ld c, l
+	ld a, [de]
+	inc de
+	push bc
+	push de
+	ld [wd265], a
+	callfar ConvertMon_1to2
+	pop de
+	pop bc
+	ld a, [wd265]
+	ld [bc], a
+	ld [wCurSpecies], a
+	ld hl, MON_HP
+	add hl, bc
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hl], a
+	inc de
+	ld hl, MON_STATUS
+	add hl, bc
+	ld a, [de]
+	inc de
+	ld [hl], a
+	ld hl, wcbe8
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [de]
+	ld [hli], a
+	inc de
+	ld a, [de]
+	ld [hli], a
+	inc de
+	ld a, l
+	ld [wcbe8], a
+	ld a, h
+	ld [wcbe8 + 1], a
+	push bc
+	ld hl, MON_ITEM
+	add hl, bc
+	push hl
+	ld h, d
+	ld l, e
+	pop de
+	push bc
+	ld a, [hli]
+	ld b, a
+	call TimeCapsule_ReplaceTeruSama
+	ld a, b
+	ld [de], a
+	inc de
+	pop bc
+	ld bc, $19
+	call CopyBytes
+	pop bc
+	ld d, h
+	ld e, l
+	ld hl, $1f
+	add hl, bc
+	ld a, [de]
+	inc de
+	ld [hl], a
+	ld [wCurPartyLevel], a
+	push bc
+	ld hl, $24
+	add hl, bc
+	push hl
+	ld h, d
+	ld l, e
+	pop de
+	ld bc, 8
+	call CopyBytes
+	pop bc
+	call GetBaseData
+	push de
+	push bc
+	ld d, h
+	ld e, l
+	ld hl, MON_STAT_EXP - 1
+	add hl, bc
+	ld c, STAT_SATK
+	ld b, TRUE
+	predef CalcMonStatC
+	pop bc
+	pop hl
+	ld a, [hQuotient + 1]
+	ld [hli], a
+	ld a, [hQuotient + 2]
+	ld [hli], a
+	push hl
+	push bc
+	ld hl, MON_STAT_EXP - 1
+	add hl, bc
+	ld c, STAT_SDEF
+	ld b, TRUE
+	predef CalcMonStatC
+	pop bc
+	pop hl
+	ld a, [hQuotient + 1]
+	ld [hli], a
+	ld a, [hQuotient + 2]
+	ld [hli], a
+	push hl
+	ld hl, $1b
+	add hl, bc
+	ld a, $46
+	ld [hli], a
+	xor a
+	ld [hli], a
+	ld [hli], a
+	ld [hl], a
+	pop hl
+	inc de
+	inc de
+	ret
+; 28771
+
+TimeCapsule_ReplaceTeruSama: ; 28771
+	ld a, b
+	and a
+	ret z
+	push hl
+	ld hl, TimeCapsule_CatchRateItems
+.loop
+	ld a, [hli]
+	and a
+	jr z, .end
+	cp b
+	jr z, .found
+	inc hl
+	jr .loop
+
+.found
+	ld b, [hl]
+
+.end
+	pop hl
+	ret
+
+
+INCLUDE "data/items/catch_rate_items.asm"
+
+
+Link_CopyOTData: ; 2879e
+.loop
+	ld a, [hli]
+	cp SERIAL_NO_DATA_BYTE
+	jr z, .loop
+	ld [de], a
+	inc de
+	dec bc
+	ld a, b
+	or c
+	jr nz, .loop
+	ret
+; 287ab
+
+Link_CopyRandomNumbers: ; 287ab
+	ld a, [hSerialConnectionStatus]
+	cp USING_INTERNAL_CLOCK
+	ret z
+	ld hl, wEnemyMonSpecies
+	call Link_FindFirstNonControlCharacter_AllowZero
+	ld de, wLinkBattleRNs
+	ld c, 10
+.loop
+	ld a, [hli]
+	cp SERIAL_NO_DATA_BYTE
+	jr z, .loop
+	cp SERIAL_PREAMBLE_BYTE
+	jr z, .loop
+	ld [de], a
+	inc de
+	dec c
+	jr nz, .loop
+	ret
+; 287ca
+
+Link_FindFirstNonControlCharacter_SkipZero: ; 287ca
+.loop
+	ld a, [hli]
+	and a
+	jr z, .loop
+	cp SERIAL_PREAMBLE_BYTE
+	jr z, .loop
+	cp SERIAL_NO_DATA_BYTE
+	jr z, .loop
+	dec hl
+	ret
+; 287d8
+
+Link_FindFirstNonControlCharacter_AllowZero: ; 287d8
+.loop
+	ld a, [hli]
+	cp SERIAL_PREAMBLE_BYTE
+	jr z, .loop
+	cp SERIAL_NO_DATA_BYTE
+	jr z, .loop
+	dec hl
+	ret
+; 287e3
+
+InitTradeMenuDisplay: ; 287e3
+	call ClearScreen
+	call LoadTradeScreenBorder
+	farcall InitTradeSpeciesList
+	xor a
+	ld hl, wOtherPlayerLinkMode
+	ld [hli], a
+	ld [hli], a
+	ld [hli], a
+	ld [hl], a
+	ld a, 1
+	ld [wMenuCursorY], a
+	inc a
+	ld [wPlayerLinkAction], a
+	jp LinkTrade_PlayerPartyMenu
+; 28803
+
+LinkTrade_OTPartyMenu: ; 28803
+	ld a, OTPARTYMON
+	ld [wMonType], a
+	ld a, A_BUTTON | D_UP | D_DOWN
+	ld [wMenuJoypadFilter], a
+	ld a, [wOTPartyCount]
+	ld [w2DMenuNumRows], a
+	ld a, 1
+	ld [w2DMenuNumCols], a
+	ld a, 9
+	ld [w2DMenuCursorInitY], a
+	ld a, 6
+	ld [w2DMenuCursorInitX], a
+	ld a, 1
+	ld [wMenuCursorX], a
+	ln a, 1, 0
+	ld [w2DMenuCursorOffsets], a
+	ld a, MENU_UNUSED_3
+	ld [w2DMenuFlags1], a
+	xor a
+	ld [w2DMenuFlags2], a
+
+LinkTradeOTPartymonMenuLoop: ; 28835
+	farcall LinkTradeMenu
+	ld a, d
+	and a
+	jp z, LinkTradePartiesMenuMasterLoop
+	bit A_BUTTON_F, a
+	jr z, .not_a_button
+	ld a, INIT_ENEMYOT_LIST
+	ld [wInitListType], a
+	callfar InitList
+	ld hl, wOTPartyMon1Species
+	farcall LinkMonStatsScreen
+	jp LinkTradePartiesMenuMasterLoop
+
+.not_a_button
+	bit D_UP_F, a
+	jr z, .not_d_up
+	ld a, [wMenuCursorY]
+	ld b, a
+	ld a, [wOTPartyCount]
+	cp b
+	jp nz, LinkTradePartiesMenuMasterLoop
+	xor a
+	ld [wMonType], a
+	call HideCursor
+	push hl
+	push bc
+	ld bc, NAME_LENGTH
+	add hl, bc
+	ld [hl], " "
+	pop bc
+	pop hl
+	ld a, [wPartyCount]
+	ld [wMenuCursorY], a
+	jr LinkTrade_PlayerPartyMenu
+
+.not_d_up
+	bit D_DOWN_F, a
+	jp z, LinkTradePartiesMenuMasterLoop
+	jp Function28ac9
+; 2888b
+
+LinkTrade_PlayerPartyMenu: ; 2888b
+	farcall InitMG_Mobile_LinkTradePalMap
+	xor a
+	ld [wMonType], a
+	ld a, A_BUTTON | D_UP | D_DOWN
+	ld [wMenuJoypadFilter], a
+	ld a, [wPartyCount]
+	ld [w2DMenuNumRows], a
+	ld a, 1
+	ld [w2DMenuNumCols], a
+	ld a, 1
+	ld [w2DMenuCursorInitY], a
+	ld a, 6
+	ld [w2DMenuCursorInitX], a
+	ld a, 1
+	ld [wMenuCursorX], a
+	ln a, 1, 0
+	ld [w2DMenuCursorOffsets], a
+	ld a, MENU_UNUSED_3
+	ld [w2DMenuFlags1], a
+	xor a
+	ld [w2DMenuFlags2], a
+	call WaitBGMap2
+
+LinkTradePartymonMenuLoop: ; 288c5
+	farcall LinkTradeMenu
+	ld a, d
+	and a
+	jr nz, .check_joypad
+	jp LinkTradePartiesMenuMasterLoop
+
+.check_joypad
+	bit A_BUTTON_F, a
+	jr z, .not_a_button
+	jp Function28926
+
+.not_a_button
+	bit D_DOWN_F, a
+	jr z, .not_d_down
+	ld a, [wMenuCursorY]
+	dec a
+	jp nz, LinkTradePartiesMenuMasterLoop
+	ld a, OTPARTYMON
+	ld [wMonType], a
+	call HideCursor
+	push hl
+	push bc
+	ld bc, NAME_LENGTH
+	add hl, bc
+	ld [hl], " "
+	pop bc
+	pop hl
+	ld a, 1
+	ld [wMenuCursorY], a
+	jp LinkTrade_OTPartyMenu
+
+.not_d_down
+	bit D_UP_F, a
+	jr z, LinkTradePartiesMenuMasterLoop
+	ld a, [wMenuCursorY]
+	ld b, a
+	ld a, [wPartyCount]
+	cp b
+	jr nz, LinkTradePartiesMenuMasterLoop
+	call HideCursor
+	push hl
+	push bc
+	ld bc, NAME_LENGTH
+	add hl, bc
+	ld [hl], " "
+	pop bc
+	pop hl
+	jp Function28ade
+; 2891c
+
+LinkTradePartiesMenuMasterLoop: ; 2891c
+	ld a, [wMonType]
+	and a
+	jp z, LinkTradePartymonMenuLoop ; PARTYMON
+	jp LinkTradeOTPartymonMenuLoop  ; OTPARTYMON
+; 28926
+
+Function28926: ; 28926
+	call LoadTileMapToTempTileMap
+	ld a, [wMenuCursorY]
+	push af
+	hlcoord 0, 15
+	ld b, 1
+	ld c, 18
+	call LinkTextboxAtHL
+	hlcoord 2, 16
+	ld de, .String_Stats_Trade
+	call PlaceString
+	farcall Link_WaitBGMap
+
+.joy_loop
+	ld a, " "
+	ldcoord_a 11, 16
+	ld a, A_BUTTON | B_BUTTON | D_RIGHT
+	ld [wMenuJoypadFilter], a
+	ld a, 1
+	ld [w2DMenuNumRows], a
+	ld a, 1
+	ld [w2DMenuNumCols], a
+	ld a, 16
+	ld [w2DMenuCursorInitY], a
+	ld a, 1
+	ld [w2DMenuCursorInitX], a
+	ld a, 1
+	ld [wMenuCursorY], a
+	ld [wMenuCursorX], a
+	ln a, 2, 0
+	ld [w2DMenuCursorOffsets], a
+	xor a
+	ld [w2DMenuFlags1], a
+	ld [w2DMenuFlags2], a
+	call ScrollingMenuJoypad
+	bit D_RIGHT_F, a
+	jr nz, .d_right
+	bit B_BUTTON_F, a
+	jr z, .show_stats
+.b_button
+	pop af
+	ld [wMenuCursorY], a
+	call Call_LoadTempTileMapToTileMap
+	jp LinkTrade_PlayerPartyMenu
+
+.d_right
+	ld a, " "
+	ldcoord_a 1, 16
+	ld a, A_BUTTON | B_BUTTON | D_LEFT
+	ld [wMenuJoypadFilter], a
+	ld a, 1
+	ld [w2DMenuNumRows], a
+	ld a, 1
+	ld [w2DMenuNumCols], a
+	ld a, 16
+	ld [w2DMenuCursorInitY], a
+	ld a, 11
+	ld [w2DMenuCursorInitX], a
+	ld a, 1
+	ld [wMenuCursorY], a
+	ld [wMenuCursorX], a
+	ln a, 2, 0
+	ld [w2DMenuCursorOffsets], a
+	xor a
+	ld [w2DMenuFlags1], a
+	ld [w2DMenuFlags2], a
+	call ScrollingMenuJoypad
+	bit D_LEFT_F, a
+	jp nz, .joy_loop
+	bit B_BUTTON_F, a
+	jr nz, .b_button
+	jr .try_trade
+
+.show_stats
+	pop af
+	ld [wMenuCursorY], a
+	ld a, INIT_PLAYEROT_LIST
+	ld [wInitListType], a
+	callfar InitList
+	farcall LinkMonStatsScreen
+	call Call_LoadTempTileMapToTileMap
+	hlcoord 6, 1
+	lb bc, 6, 1
+	ld a, " "
+	call LinkEngine_FillBox
+	hlcoord 17, 1
+	lb bc, 6, 1
+	ld a, " "
+	call LinkEngine_FillBox
+	jp LinkTrade_PlayerPartyMenu
+
+.try_trade
+	call PlaceHollowCursor
+	pop af
+	ld [wMenuCursorY], a
+	dec a
+	ld [wd002], a
+	ld [wPlayerLinkAction], a
+	farcall Function16d6ce
+	ld a, [wOtherPlayerLinkMode]
+	cp $f
+	jp z, InitTradeMenuDisplay
+	ld [wd003], a
+	call Function28b68
+	ld c, 100
+	call DelayFrames
+	farcall ValidateOTTrademon
+	jr c, .abnormal
+	farcall Functionfb5dd
+	jp nc, LinkTrade
+	xor a
+	ld [wcf57], a
+	ld [wOtherPlayerLinkAction], a
+	hlcoord 0, 12
+	ld b, 4
+	ld c, 18
+	call LinkTextboxAtHL
+	farcall Link_WaitBGMap
+	ld hl, .Text_CantTradeLastMon
+	bccoord 1, 14
+	call PlaceHLTextAtBC
+	jr .cancel_trade
+
+.abnormal
+	xor a
+	ld [wcf57], a
+	ld [wOtherPlayerLinkAction], a
+	ld a, [wd003]
+	ld hl, wOTPartySpecies
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [hl]
+	ld [wd265], a
+	call GetPokemonName
+	hlcoord 0, 12
+	ld b, 4
+	ld c, 18
+	call LinkTextboxAtHL
+	farcall Link_WaitBGMap
+	ld hl, .Text_Abnormal
+	bccoord 1, 14
+	call PlaceHLTextAtBC
+
+.cancel_trade
+	hlcoord 0, 12
+	ld b, 4
+	ld c, 18
+	call LinkTextboxAtHL
+	hlcoord 1, 14
+	ld de, String_TooBadTheTradeWasCanceled
+	call PlaceString
+	ld a, $1
+	ld [wPlayerLinkAction], a
+	farcall Function16d6ce
+	ld c, 100
+	call DelayFrames
+	jp InitTradeMenuDisplay
+; 28aaf
+
+
+.Text_CantTradeLastMon: ; 0x28aaf
+	; If you trade that #MON, you won't be able to battle.
+	text_jump UnknownText_0x1c41b1
+	db "@"
+; 0x28ab4
+
+.String_Stats_Trade: ; 28ab4
+	db "STATS     TRADE@"
+
+.Text_Abnormal: ; 0x28ac4
+	; Your friend's @  appears to be abnormal!
+	text_jump UnknownText_0x1c41e6
+	db "@"
+; 0x28ac9
+
+
+Function28ac9: ; 28ac9
+	ld a, [wMenuCursorY]
+	cp 1
+	jp nz, LinkTradePartiesMenuMasterLoop
+	call HideCursor
+	push hl
+	push bc
+	ld bc, NAME_LENGTH
+	add hl, bc
+	ld [hl], " "
+	pop bc
+	pop hl
+Function28ade: ; 28ade
+.loop1
+	ld a, "▶"
+	ldcoord_a 9, 17
+.loop2
+	call JoyTextDelay
+	ld a, [hJoyLast]
+	and a
+	jr z, .loop2
+	bit A_BUTTON_F, a
+	jr nz, .a_button
+	push af
+	ld a, " "
+	ldcoord_a 9, 17
+	pop af
+	bit D_UP_F, a
+	jr z, .d_up
+	ld a, [wOTPartyCount]
+	ld [wMenuCursorY], a
+	jp LinkTrade_OTPartyMenu
+
+.d_up
+	ld a, $1
+	ld [wMenuCursorY], a
+	jp LinkTrade_PlayerPartyMenu
+
+.a_button
+	ld a, "▷"
+	ldcoord_a 9, 17
+	ld a, $f
+	ld [wPlayerLinkAction], a
+	farcall Function16d6ce
+	ld a, [wOtherPlayerLinkMode]
+	cp $f
+	jr nz, .loop1
+Function28b22: ; 28b22
+	call RotateThreePalettesRight
+	call ClearScreen
+	ld b, SCGB_DIPLOMA
+	call GetSGBLayout
+	call WaitBGMap2
+	xor a
+	ld [wcfbb], a
+	xor a
+	ld [rSB], a
+	ld [hSerialSend], a
+	ld a, (0 << rSC_ON) | 1
+	ld [rSC], a
+	ld a, (1 << rSC_ON) | 1
+	ld [rSC], a
+	ret
+; 28b42
+
+Unreferenced_Function28b42: ; 28b42
+	hlcoord 0, 16
+	ld a, "┘"
+	ld bc, 2 * SCREEN_WIDTH
+	call ByteFill
+	hlcoord 1, 16
+	ld a, " "
+	ld bc, SCREEN_WIDTH - 2
+	call ByteFill
+	hlcoord 2, 16
+	ld de, .Cancel
+	jp PlaceString
+; 28b61
+
+.Cancel: ; 28b61
+	db "CANCEL@"
+; 28b68
+
+Function28b68: ; 28b68
+	ld a, [wOtherPlayerLinkMode]
+	hlcoord 6, 9
+	ld bc, SCREEN_WIDTH
+	call AddNTimes
+	ld [hl], "▷"
+	ret
+; 28b77
+
+LinkEngine_FillBox: ; 28b77
+.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
+; 28b87
+
+LinkTrade: ; 28b87
+	xor a
+	ld [wcf57], a
+	ld [wOtherPlayerLinkAction], a
+	hlcoord 0, 12
+	ld b, 4
+	ld c, 18
+	call LinkTextboxAtHL
+	farcall Link_WaitBGMap
+	ld a, [wd002]
+	ld hl, wPartySpecies
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [hl]
+	ld [wd265], a
+	call GetPokemonName
+	ld hl, wStringBuffer1
+	ld de, wd004
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+	ld a, [wd003]
+	ld hl, wOTPartySpecies
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [hl]
+	ld [wd265], a
+	call GetPokemonName
+	ld hl, UnknownText_0x28eb8
+	bccoord 1, 14
+	call PlaceHLTextAtBC
+	call LoadStandardMenuHeader
+	hlcoord 10, 7
+	ld b, 3
+	ld c, 7
+	call LinkTextboxAtHL
+	ld de, String28eab
+	hlcoord 12, 8
+	call PlaceString
+	ld a, 8
+	ld [w2DMenuCursorInitY], a
+	ld a, 11
+	ld [w2DMenuCursorInitX], a
+	ld a, 1
+	ld [w2DMenuNumCols], a
+	ld a, 2
+	ld [w2DMenuNumRows], a
+	xor a
+	ld [w2DMenuFlags1], a
+	ld [w2DMenuFlags2], a
+	ld a, $20
+	ld [w2DMenuCursorOffsets], a
+	ld a, A_BUTTON | B_BUTTON
+	ld [wMenuJoypadFilter], a
+	ld a, 1
+	ld [wMenuCursorY], a
+	ld [wMenuCursorX], a
+	farcall Link_WaitBGMap
+	call ScrollingMenuJoypad
+	push af
+	call Call_ExitMenu
+	call WaitBGMap2
+	pop af
+	bit 1, a
+	jr nz, .asm_28c33
+	ld a, [wMenuCursorY]
+	dec a
+	jr z, .asm_28c54
+
+.asm_28c33
+	ld a, $1
+	ld [wPlayerLinkAction], a
+	hlcoord 0, 12
+	ld b, 4
+	ld c, 18
+	call LinkTextboxAtHL
+	hlcoord 1, 14
+	ld de, String_TooBadTheTradeWasCanceled
+	call PlaceString
+	farcall Function16d6ce
+	jp Function28ea3
+
+.asm_28c54
+	ld a, $2
+	ld [wPlayerLinkAction], a
+	farcall Function16d6ce
+	ld a, [wOtherPlayerLinkMode]
+	dec a
+	jr nz, .asm_28c7b
+	hlcoord 0, 12
+	ld b, 4
+	ld c, 18
+	call LinkTextboxAtHL
+	hlcoord 1, 14
+	ld de, String_TooBadTheTradeWasCanceled
+	call PlaceString
+	jp Function28ea3
+
+.asm_28c7b
+	ld hl, sPartyMail
+	ld a, [wd002]
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	ld d, h
+	ld e, l
+	ld bc, MAIL_STRUCT_LENGTH
+	add hl, bc
+	ld a, [wd002]
+	ld c, a
+.asm_28c96
+	inc c
+	ld a, c
+	cp PARTY_LENGTH
+	jr z, .asm_28ca6
+	push bc
+	ld bc, MAIL_STRUCT_LENGTH
+	call CopyBytes
+	pop bc
+	jr .asm_28c96
+
+.asm_28ca6
+	ld hl, sPartyMail
+	ld a, [wPartyCount]
+	dec a
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	push hl
+	ld hl, wc9f4
+	ld a, [wd003]
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	pop de
+	ld bc, MAIL_STRUCT_LENGTH
+	call CopyBytes
+	call CloseSRAM
+	ld hl, wPlayerName
+	ld de, wPlayerTrademonSenderName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ld a, [wd002]
+	ld hl, wPartySpecies
+	ld b, 0
+	ld c, a
+	add hl, bc
+	ld a, [hl]
+	ld [wPlayerTrademonSpecies], a
+	push af
+	ld a, [wd002]
+	ld hl, wPartyMonOT
+	call SkipNames
+	ld de, wPlayerTrademonOTName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ld hl, wPartyMon1ID
+	ld a, [wd002]
+	call GetPartyLocation
+	ld a, [hli]
+	ld [wPlayerTrademonID], a
+	ld a, [hl]
+	ld [wPlayerTrademonID + 1], a
+	ld hl, wPartyMon1DVs
+	ld a, [wd002]
+	call GetPartyLocation
+	ld a, [hli]
+	ld [wPlayerTrademonDVs], a
+	ld a, [hl]
+	ld [wPlayerTrademonDVs + 1], a
+	ld a, [wd002]
+	ld hl, wPartyMon1Species
+	call GetPartyLocation
+	ld b, h
+	ld c, l
+	farcall GetCaughtGender
+	ld a, c
+	ld [wPlayerTrademonCaughtData], a
+	ld hl, wOTPlayerName
+	ld de, wOTTrademonSenderName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ld a, [wd003]
+	ld hl, wOTPartySpecies
+	ld b, 0
+	ld c, a
+	add hl, bc
+	ld a, [hl]
+	ld [wOTTrademonSpecies], a
+	ld a, [wd003]
+	ld hl, wOTPartyMonOT
+	call SkipNames
+	ld de, wOTTrademonOTName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ld hl, wOTPartyMon1ID
+	ld a, [wd003]
+	call GetPartyLocation
+	ld a, [hli]
+	ld [wOTTrademonID], a
+	ld a, [hl]
+	ld [wOTTrademonID + 1], a
+	ld hl, wOTPartyMon1DVs
+	ld a, [wd003]
+	call GetPartyLocation
+	ld a, [hli]
+	ld [wOTTrademonDVs], a
+	ld a, [hl]
+	ld [wOTTrademonDVs + 1], a
+	ld a, [wd003]
+	ld hl, wOTPartyMon1Species
+	call GetPartyLocation
+	ld b, h
+	ld c, l
+	farcall GetCaughtGender
+	ld a, c
+	ld [wOTTrademonCaughtData], a
+	ld a, [wd002]
+	ld [wCurPartyMon], a
+	ld hl, wPartySpecies
+	ld b, 0
+	ld c, a
+	add hl, bc
+	ld a, [hl]
+	ld [wd002], a
+	xor a ; REMOVE_PARTY
+	ld [wPokemonWithdrawDepositParameter], a
+	callfar RemoveMonFromPartyOrBox
+	ld a, [wPartyCount]
+	dec a
+	ld [wCurPartyMon], a
+	ld a, TRUE
+	ld [wForceEvolution], a
+	ld a, [wd003]
+	push af
+	ld hl, wOTPartySpecies
+	ld b, 0
+	ld c, a
+	add hl, bc
+	ld a, [hl]
+	ld [wd003], a
+	ld c, 100
+	call DelayFrames
+	call ClearTileMap
+	call LoadFontsBattleExtra
+	ld b, SCGB_DIPLOMA
+	call GetSGBLayout
+	ld a, [hSerialConnectionStatus]
+	cp USING_EXTERNAL_CLOCK
+	jr z, .player_2
+	predef TradeAnimation
+	jr .done_animation
+
+.player_2
+	predef TradeAnimationPlayer2
+
+.done_animation
+	pop af
+	ld c, a
+	ld [wCurPartyMon], a
+	ld hl, wOTPartySpecies
+	ld d, 0
+	ld e, a
+	add hl, de
+	ld a, [hl]
+	ld [wCurPartySpecies], a
+	ld hl, wOTPartyMon1Species
+	ld a, c
+	call GetPartyLocation
+	ld de, wTempMonSpecies
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call CopyBytes
+	predef AddTempmonToParty
+	ld a, [wPartyCount]
+	dec a
+	ld [wCurPartyMon], a
+	callfar EvolvePokemon
+	call ClearScreen
+	call LoadTradeScreenBorder
+	call SetTradeRoomBGPals
+	farcall Link_WaitBGMap
+	ld b, $1
+	pop af
+	ld c, a
+	cp MEW
+	jr z, .loop
+	ld a, [wCurPartySpecies]
+	cp MEW
+	jr z, .loop
+	ld b, $2
+	ld a, c
+	cp CELEBI
+	jr z, .loop
+	ld a, [wCurPartySpecies]
+	cp CELEBI
+	jr z, .loop
+	ld b, $0
+
+.loop
+	ld a, b
+	ld [wPlayerLinkAction], a
+	push bc
+	call Serial_PrintWaitingTextAndSyncAndExchangeNybble
+	pop bc
+	ld a, [wLinkMode]
+	cp LINK_TIMECAPSULE
+	jr z, .save
+	ld a, b
+	and a
+	jr z, .save
+	ld a, [wOtherPlayerLinkAction]
+	cp b
+	jr nz, .loop
+
+.save
+	farcall SaveAfterLinkTrade
+	farcall StubbedTrainerRankings_Trades
+	farcall BackupMobileEventIndex
+	ld c, 40
+	call DelayFrames
+	hlcoord 0, 12
+	ld b, 4
+	ld c, 18
+	call LinkTextboxAtHL
+	hlcoord 1, 14
+	ld de, String28ebd
+	call PlaceString
+	farcall Link_WaitBGMap
+	ld c, 50
+	call DelayFrames
+	ld a, [wLinkMode]
+	cp LINK_TIMECAPSULE
+	jp z, Gen2ToGen1LinkComms
+	jp Gen2ToGen2LinkComms
+; 28ea3
+
+Function28ea3: ; 28ea3
+	ld c, 100
+	call DelayFrames
+	jp InitTradeMenuDisplay
+; 28eab
+
+String28eab: ; 28eab
+	db   "TRADE"
+	next "CANCEL@"
+
+UnknownText_0x28eb8: ; 0x28eb8
+	; Trade @ for @ ?
+	text_jump UnknownText_0x1c4212
+	db "@"
+; 0x28ebd
+
+String28ebd: ; 28ebd
+	db   "Trade completed!@"
+
+String_TooBadTheTradeWasCanceled: ; 28ece
+	db   "Too bad! The trade"
+	next "was canceled!@"
+
+
+LinkTextboxAtHL: ; 28eef
+	ld d, h
+	ld e, l
+	farcall LinkTextbox
+	ret
+; 28ef8
+
+LoadTradeScreenBorder: ; 28ef8
+	farcall _LoadTradeScreenBorder
+	ret
+; 28eff
+
+SetTradeRoomBGPals: ; 28eff
+	farcall LoadTradeRoomBGPals_ ; just a nested farcall; so wasteful
+	call SetPalettes
+	ret
+; 28f09
+
+Unreferenced_Function28f09: ; 28f09
+	hlcoord 0, 0
+	ld b, 6
+	ld c, 18
+	call LinkTextboxAtHL
+	hlcoord 0, 8
+	ld b, 6
+	ld c, 18
+	call LinkTextboxAtHL
+	farcall PlaceTradePartnerNamesAndParty
+	ret
+; 28f24
+
+INCLUDE "engine/gfx/trade_animation.asm"
+
+CheckTimeCapsuleCompatibility: ; 29bfb
+; Checks to see if your party is compatible with the Gen 1 games.
+; Returns the following in wScriptVar:
+; 0: Party is okay
+; 1: At least one Pokémon was introduced in Gen 2
+; 2: At least one Pokémon has a move that was introduced in Gen 2
+; 3: At least one Pokémon is holding mail
+
+; If any party Pokémon was introduced in the Gen 2 games, don't let it in.
+	ld hl, wPartySpecies
+	ld b, PARTY_LENGTH
+.loop
+	ld a, [hli]
+	cp -1
+	jr z, .checkitem
+	cp JOHTO_POKEMON
+	jr nc, .mon_too_new
+	dec b
+	jr nz, .loop
+
+; If any party Pokémon is holding mail, don't let it in.
+.checkitem
+	ld a, [wPartyCount]
+	ld b, a
+	ld hl, wPartyMon1Item
+.itemloop
+	push hl
+	push bc
+	ld d, [hl]
+	farcall ItemIsMail
+	pop bc
+	pop hl
+	jr c, .mon_has_mail
+	ld de, PARTYMON_STRUCT_LENGTH
+	add hl, de
+	dec b
+	jr nz, .itemloop
+
+; If any party Pokémon has a move that was introduced in the Gen 2 games, don't let it in.
+	ld hl, wPartyMon1Moves
+	ld a, [wPartyCount]
+	ld b, a
+.move_loop
+	ld c, NUM_MOVES
+.move_next
+	ld a, [hli]
+	cp STRUGGLE + 1
+	jr nc, .move_too_new
+	dec c
+	jr nz, .move_next
+	ld de, wPartyMon2 - (wPartyMon1 + NUM_MOVES)
+	add hl, de
+	dec b
+	jr nz, .move_loop
+	xor a
+	jr .done
+
+.mon_too_new
+	ld [wd265], a
+	call GetPokemonName
+	ld a, $1
+	jr .done
+
+.move_too_new
+	push bc
+	ld [wd265], a
+	call GetMoveName
+	call CopyName1
+	pop bc
+	call Function29c67
+	ld a, $2
+	jr .done
+
+.mon_has_mail
+	call Function29c67
+	ld a, $3
+
+.done
+	ld [wScriptVar], a
+	ret
+; 29c67
+
+Function29c67: ; 29c67
+	ld a, [wPartyCount]
+	sub b
+	ld c, a
+	inc c
+	ld b, 0
+	ld hl, wPartyCount
+	add hl, bc
+	ld a, [hl]
+	ld [wd265], a
+	call GetPokemonName
+	ret
+; 29c7b
+
+EnterTimeCapsule: ; 29c7b
+	ld c, 10
+	call DelayFrames
+	ld a, $4
+	call Link_EnsureSync
+	ld c, 40
+	call DelayFrames
+	xor a
+	ld [hVBlank], a
+	inc a
+	ld [wLinkMode], a
+	ret
+; 29c92
+
+WaitForOtherPlayerToExit: ; 29c92
+	ld c, 3
+	call DelayFrames
+	ld a, CONNECTION_NOT_ESTABLISHED
+	ld [hSerialConnectionStatus], a
+	xor a
+	ld [rSB], a
+	ld [hSerialReceive], a
+	ld a, (0 << rSC_ON) | 1
+	ld [rSC], a
+	ld a, (1 << rSC_ON) | 1
+	ld [rSC], a
+	ld c, 3
+	call DelayFrames
+	xor a
+	ld [rSB], a
+	ld [hSerialReceive], a
+	ld a, (0 << rSC_ON) | 0
+	ld [rSC], a
+	ld a, (1 << rSC_ON) | 0
+	ld [rSC], a
+	ld c, 3
+	call DelayFrames
+	xor a
+	ld [rSB], a
+	ld [hSerialReceive], a
+	ld [rSC], a
+	ld c, 3
+	call DelayFrames
+	ld a, CONNECTION_NOT_ESTABLISHED
+	ld [hSerialConnectionStatus], a
+	ld a, [rIF]
+	push af
+	xor a
+	ld [rIF], a
+	ld a, $f
+	ld [rIE], a
+	pop af
+	ld [rIF], a
+	ld hl, wLinkTimeoutFrames
+	xor a
+	ld [hli], a
+	ld [hl], a
+	ld [hVBlank], a
+	ld [wLinkMode], a
+	ret
+; 29ce8
+
+SetBitsForLinkTradeRequest: ; 29ce8
+	ld a, LINK_TRADECENTER - 1
+	ld [wPlayerLinkAction], a
+	ld [wd265], a
+	ret
+; 29cf1
+
+SetBitsForBattleRequest: ; 29cf1
+	ld a, LINK_COLOSSEUM - 1
+	ld [wPlayerLinkAction], a
+	ld [wd265], a
+	ret
+; 29cfa
+
+SetBitsForTimeCapsuleRequest: ; 29cfa
+	ld a, $2
+	ld [rSB], a
+	xor a
+	ld [hSerialReceive], a
+	ld a, (0 << rSC_ON) | 0
+	ld [rSC], a
+	ld a, (1 << rSC_ON) | 0
+	ld [rSC], a
+	xor a ; LINK_TIMECAPSULE - 1
+	ld [wPlayerLinkAction], a
+	ld [wd265], a
+	ret
+; 29d11
+
+WaitForLinkedFriend: ; 29d11
+	ld a, [wPlayerLinkAction]
+	and a
+	jr z, .no_link_action
+	ld a, $2
+	ld [rSB], a
+	xor a
+	ld [hSerialReceive], a
+	ld a, (0 << rSC_ON) | 0
+	ld [rSC], a
+	ld a, (1 << rSC_ON) | 0
+	ld [rSC], a
+	call DelayFrame
+	call DelayFrame
+	call DelayFrame
+
+.no_link_action
+	ld a, $2
+	ld [wLinkTimeoutFrames + 1], a
+	ld a, $ff
+	ld [wLinkTimeoutFrames], a
+.loop
+	ld a, [hSerialConnectionStatus]
+	cp USING_INTERNAL_CLOCK
+	jr z, .connected
+	cp USING_EXTERNAL_CLOCK
+	jr z, .connected
+	ld a, CONNECTION_NOT_ESTABLISHED
+	ld [hSerialConnectionStatus], a
+	ld a, $2
+	ld [rSB], a
+	xor a
+	ld [hSerialReceive], a
+	ld a, (0 << rSC_ON) | 0
+	ld [rSC], a
+	ld a, (1 << rSC_ON) | 0
+	ld [rSC], a
+	ld a, [wLinkTimeoutFrames]
+	dec a
+	ld [wLinkTimeoutFrames], a
+	jr nz, .not_done
+	ld a, [wLinkTimeoutFrames + 1]
+	dec a
+	ld [wLinkTimeoutFrames + 1], a
+	jr z, .done
+
+.not_done
+	ld a, $1
+	ld [rSB], a
+	ld a, (0 << rSC_ON) | 1
+	ld [rSC], a
+	ld a, (1 << rSC_ON) | 1
+	ld [rSC], a
+	call DelayFrame
+	jr .loop
+
+.connected
+	call LinkDataReceived
+	call DelayFrame
+	call LinkDataReceived
+	ld c, 50
+	call DelayFrames
+	ld a, $1
+	ld [wScriptVar], a
+	ret
+
+.done
+	xor a
+	ld [wScriptVar], a
+	ret
+; 29d92
+
+CheckLinkTimeout: ; 29d92
+	ld a, $1
+	ld [wPlayerLinkAction], a
+	ld hl, wLinkTimeoutFrames
+	ld a, $3
+	ld [hli], a
+	xor a
+	ld [hl], a
+	call WaitBGMap
+	ld a, $2
+	ld [hVBlank], a
+	call DelayFrame
+	call DelayFrame
+	call Link_CheckCommunicationError
+	xor a
+	ld [hVBlank], a
+	ld a, [wScriptVar]
+	and a
+	ret nz
+	jp Link_ResetSerialRegistersAfterLinkClosure
+; 29dba
+
+Function29dba: ; 29dba
+	ld a, $5
+	ld [wPlayerLinkAction], a
+	ld hl, wLinkTimeoutFrames
+	ld a, $3
+	ld [hli], a
+	xor a
+	ld [hl], a
+	call WaitBGMap
+	ld a, $2
+	ld [hVBlank], a
+	call DelayFrame
+	call DelayFrame
+	call Link_CheckCommunicationError
+	ld a, [wScriptVar]
+	and a
+	jr z, .vblank
+	ld bc, -1
+.wait
+	dec bc
+	ld a, b
+	or c
+	jr nz, .wait
+	ld a, [wOtherPlayerLinkMode]
+	cp $5
+	jr nz, .script_var
+	ld a, $6
+	ld [wPlayerLinkAction], a
+	ld hl, wLinkTimeoutFrames
+	ld a, $1
+	ld [hli], a
+	ld [hl], $32
+	call Link_CheckCommunicationError
+	ld a, [wOtherPlayerLinkMode]
+	cp $6
+	jr z, .vblank
+
+.script_var
+	xor a
+	ld [wScriptVar], a
+	ret
+
+.vblank
+	xor a
+	ld [hVBlank], a
+	ret
+; 29e0c
+
+Link_CheckCommunicationError: ; 29e0c
+	xor a
+	ld [hSerialReceivedNewData], a
+	ld a, [wLinkTimeoutFrames]
+	ld h, a
+	ld a, [wLinkTimeoutFrames + 1]
+	ld l, a
+	push hl
+	call .CheckConnected
+	pop hl
+	jr nz, .load_true
+	call .AcknowledgeSerial
+	call .ConvertDW
+	call .CheckConnected
+	jr nz, .load_true
+	call .AcknowledgeSerial
+	xor a
+	jr .load_scriptvar
+
+.load_true
+	ld a, $1
+
+.load_scriptvar
+	ld [wScriptVar], a
+	ld hl, wLinkTimeoutFrames
+	xor a
+	ld [hli], a
+	ld [hl], a
+	ret
+; 29e3b
+
+.CheckConnected: ; 29e3b
+	call WaitLinkTransfer
+	ld hl, wLinkTimeoutFrames
+	ld a, [hli]
+	inc a
+	ret nz
+	ld a, [hl]
+	inc a
+	ret
+; 29e47
+
+.AcknowledgeSerial: ; 29e47
+	ld b, 10
+.loop
+	call DelayFrame
+	call LinkDataReceived
+	dec b
+	jr nz, .loop
+	ret
+; 29e53
+
+.ConvertDW: ; 29e53
+	; [wLinkTimeoutFrames] = ((hl - $100) / 4) + $100
+	;                      = (hl / 4) + $c0
+	dec h
+	srl h
+	rr l
+	srl h
+	rr l
+	inc h
+	ld a, h
+	ld [wLinkTimeoutFrames], a
+	ld a, l
+	ld [wLinkTimeoutFrames + 1], a
+	ret
+; 29e66
+
+TryQuickSave: ; 29e66
+	ld a, [wd265]
+	push af
+	farcall Link_SaveGame
+	ld a, TRUE
+	jr nc, .return_result
+	xor a ; FALSE
+.return_result
+	ld [wScriptVar], a
+	ld c, 30
+	call DelayFrames
+	pop af
+	ld [wd265], a
+	ret
+; 29e82
+
+CheckBothSelectedSameRoom: ; 29e82
+	ld a, [wd265]
+	call Link_EnsureSync
+	push af
+	call LinkDataReceived
+	call DelayFrame
+	call LinkDataReceived
+	pop af
+	ld b, a
+	ld a, [wd265]
+	cp b
+	jr nz, .fail
+	ld a, [wd265]
+	inc a
+	ld [wLinkMode], a
+	xor a
+	ld [hVBlank], a
+	ld a, TRUE
+	ld [wScriptVar], a
+	ret
+
+.fail
+	xor a ; FALSE
+	ld [wScriptVar], a
+	ret
+; 29eaf
+
+TimeCapsule: ; 29eaf
+	ld a, LINK_TIMECAPSULE
+	ld [wLinkMode], a
+	call DisableSpriteUpdates
+	callfar LinkCommunications
+	call EnableSpriteUpdates
+	xor a
+	ld [hVBlank], a
+	ret
+; 29ec4
+
+TradeCenter: ; 29ec4
+	ld a, LINK_TRADECENTER
+	ld [wLinkMode], a
+	call DisableSpriteUpdates
+	callfar LinkCommunications
+	call EnableSpriteUpdates
+	xor a
+	ld [hVBlank], a
+	ret
+; 29ed9
+
+Colosseum: ; 29ed9
+	ld a, LINK_COLOSSEUM
+	ld [wLinkMode], a
+	call DisableSpriteUpdates
+	callfar LinkCommunications
+	call EnableSpriteUpdates
+	xor a
+	ld [hVBlank], a
+	ret
+; 29eee
+
+CloseLink: ; 29eee
+	xor a
+	ld [wLinkMode], a
+	ld c, 3
+	call DelayFrames
+	jp Link_ResetSerialRegistersAfterLinkClosure
+; 29efa
+
+FailedLinkToPast: ; 29efa
+	ld c, 40
+	call DelayFrames
+	ld a, $e
+	jp Link_EnsureSync
+; 29f04
+
+Link_ResetSerialRegistersAfterLinkClosure: ; 29f04
+	ld c, 3
+	call DelayFrames
+	ld a, CONNECTION_NOT_ESTABLISHED
+	ld [hSerialConnectionStatus], a
+	ld a, $2
+	ld [rSB], a
+	xor a
+	ld [hSerialReceive], a
+	ld [rSC], a
+	ret
+; 29f17
+
+Link_EnsureSync: ; 29f17
+	add $d0
+	ld [wPlayerLinkAction], a
+	ld [wcf57], a
+	ld a, $2
+	ld [hVBlank], a
+	call DelayFrame
+	call DelayFrame
+.receive_loop
+	call Serial_ExchangeLinkMenuSelection
+	ld a, [wOtherPlayerLinkMode]
+	ld b, a
+	and $f0
+	cp $d0
+	jr z, .done
+	ld a, [wOtherPlayerLinkAction]
+	ld b, a
+	and $f0
+	cp $d0
+	jr nz, .receive_loop
+
+.done
+	xor a
+	ld [hVBlank], a
+	ld a, b
+	and $f
+	ret
+; 29f47
+
+CableClubCheckWhichChris: ; 29f47
+	ld a, [hSerialConnectionStatus]
+	cp USING_EXTERNAL_CLOCK
+	ld a, TRUE
+	jr z, .yes
+	dec a ; FALSE
+
+.yes
+	ld [wScriptVar], a
+	ret
+; 29f54
+
+Unreferenced_Gen1LinkCommsBorderGFX: ; 29f54
+INCBIN "gfx/trade/unused_gen_1_border_tiles.2bpp"
+; 29fe4
+
+Unreferenced_Function29fe4:
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	ld d, FALSE
+	ld b, CHECK_FLAG
+	predef SmallFarFlagAction
+	call CloseSRAM
+	ld a, c
+	and a
+	ret
--- /dev/null
+++ b/engine/link/link_2.asm
@@ -1,0 +1,95 @@
+LinkMonStatsScreen: ; 4d319
+	ld a, [wMenuCursorY]
+	dec a
+	ld [wCurPartyMon], a
+	call LowVolume
+	predef StatsScreenInit
+	ld a, [wCurPartyMon]
+	inc a
+	ld [wMenuCursorY], a
+	call ClearScreen
+	call ClearBGPalettes
+	call MaxVolume
+	farcall LoadTradeScreenBorder
+	farcall Link_WaitBGMap
+	farcall InitTradeSpeciesList
+	farcall SetTradeRoomBGPals
+	call WaitBGMap2
+	ret
+
+Link_WaitBGMap: ; 4d354
+	call WaitBGMap
+	call WaitBGMap2
+	ret
+
+LinkTextbox2: ; 4d35b
+	ld h, d
+	ld l, e
+	push bc
+	push hl
+	call .PlaceBorder
+	pop hl
+	pop bc
+
+	ld de, wAttrMap - wTileMap
+	add hl, de
+	inc b
+	inc b
+	inc c
+	inc c
+	ld a, PAL_BG_TEXT
+.row
+	push bc
+	push hl
+.col
+	ld [hli], a
+	dec c
+	jr nz, .col
+	pop hl
+	ld de, SCREEN_WIDTH
+	add hl, de
+	pop bc
+	dec b
+	jr nz, .row
+	ret
+; 4d37e
+
+.PlaceBorder: ; 4d37e
+	push hl
+	ld a, $76
+	ld [hli], a
+	inc a
+	call .PlaceRow
+	inc a
+	ld [hl], a
+	pop hl
+	ld de, SCREEN_WIDTH
+	add hl, de
+.loop
+	push hl
+	ld a, "┌"
+	ld [hli], a
+	ld a, " "
+	call .PlaceRow
+	ld [hl], "─"
+	pop hl
+	ld de, SCREEN_WIDTH
+	add hl, de
+	dec b
+	jr nz, .loop
+
+	ld a, "┐"
+	ld [hli], a
+	ld a, "│"
+	call .PlaceRow
+	ld [hl], "└"
+	ret
+; 4d3ab
+
+.PlaceRow: ; 4d3ab
+	ld d, c
+.row_loop
+	ld [hli], a
+	dec d
+	jr nz, .row_loop
+	ret
--- /dev/null
+++ b/engine/link/link_trade.asm
@@ -1,0 +1,363 @@
+LinkCommsBorderGFX:
+INCBIN "gfx/trade/border_tiles.2bpp"
+; 16d421
+
+__LoadTradeScreenBorder: ; 16d421
+	ld de, LinkCommsBorderGFX
+	ld hl, vTiles2
+	lb bc, BANK(LinkCommsBorderGFX), 70
+	call Get2bpp
+	ret
+; 16d42e
+
+Function16d42e: ; 16d42e
+	ld hl, Tilemap_MobileTradeBorderFullscreen
+	decoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	call CopyBytes
+	ret
+; 16d43b
+
+Function16d43b: ; 16d43b
+	call LoadStandardMenuHeader
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	farcall __LoadTradeScreenBorder ; useless to farcall
+	farcall Function16d42e ; useless to farcall
+	ld b, SCGB_DIPLOMA
+	call GetSGBLayout
+	call SetPalettes
+	call WaitBGMap
+	call JoyWaitAorB
+	call Call_ExitMenu
+	ret
+; 16d465
+
+Tilemap_MobileTradeBorderFullscreen:
+INCBIN "gfx/trade/border_mobile_fullscreen.tilemap"
+
+Tilemap_CableTradeBorderTop:
+INCBIN "gfx/trade/border_cable_top.tilemap"
+
+Tilemap_CableTradeBorderBottom:
+INCBIN "gfx/trade/border_cable_bottom.tilemap"
+
+_LinkTextbox: ; 16d61d
+	ld h, d
+	ld l, e
+	push bc
+	push hl
+	call .PlaceBorder
+	pop hl
+	pop bc
+
+	ld de, wAttrMap - wTileMap
+	add hl, de
+	inc b
+	inc b
+	inc c
+	inc c
+	ld a, PAL_BG_TEXT
+.row
+	push bc
+	push hl
+.col
+	ld [hli], a
+	dec c
+	jr nz, .col
+	pop hl
+	ld de, SCREEN_WIDTH
+	add hl, de
+	pop bc
+	dec b
+	jr nz, .row
+	ret
+; 16d640
+
+.PlaceBorder ; 16d640
+	push hl
+	ld a, $30
+	ld [hli], a
+	inc a
+	call .PlaceRow
+	inc a
+	ld [hl], a
+	pop hl
+	ld de, SCREEN_WIDTH
+	add hl, de
+.loop
+	push hl
+	ld a, $33
+	ld [hli], a
+	ld a, " "
+	call .PlaceRow
+	ld [hl], $34
+	pop hl
+	ld de, SCREEN_WIDTH
+	add hl, de
+	dec b
+	jr nz, .loop
+
+	ld a, $35
+	ld [hli], a
+	ld a, $36
+	call .PlaceRow
+	ld [hl], $37
+	ret
+; 16d66d
+
+.PlaceRow ; 16d66d
+	ld d, c
+.row_loop
+	ld [hli], a
+	dec d
+	jr nz, .row_loop
+	ret
+; 16d673
+
+InitTradeSpeciesList: ; 16d673
+	call _LoadTradeScreenBorder
+	call Function16d6ae
+	farcall InitMG_Mobile_LinkTradePalMap
+	farcall PlaceTradePartnerNamesAndParty
+	hlcoord 10, 17
+	ld de, .CANCEL
+	call PlaceString
+	ret
+; 16d68f
+
+.CANCEL: ; 16d68f
+	db "CANCEL@"
+; 16d696
+
+_LoadTradeScreenBorder: ; 16d696
+	call __LoadTradeScreenBorder
+	ret
+; 16d69a
+
+
+LinkComms_LoadPleaseWaitTextboxBorderGFX: ; 16d69a
+	ld de, LinkCommsBorderGFX + $30 tiles
+	ld hl, vTiles2 tile $76
+	lb bc, BANK(LinkCommsBorderGFX), 8
+	call Get2bpp
+	ret
+; 16d6a7
+
+LoadTradeRoomBGPals_: ; 16d6a7
+	farcall LoadTradeRoomBGPals
+	ret
+; 16d6ae
+
+Function16d6ae: ; 16d6ae
+	call Function16d42e
+	ld hl, Tilemap_CableTradeBorderTop
+	decoord 0, 0
+	ld bc, 2 * SCREEN_WIDTH
+	call CopyBytes
+	ld hl, Tilemap_CableTradeBorderBottom
+	decoord 0, 16
+	ld bc, 2 * SCREEN_WIDTH
+	call CopyBytes
+	ret
+; 16d6ca
+
+LinkTextbox: ; 16d6ca
+	call _LinkTextbox
+	ret
+; 16d6ce
+
+Function16d6ce: ; 16d6ce
+	call LoadStandardMenuHeader
+	call Function16d6e1
+	farcall WaitLinkTransfer
+	call Call_ExitMenu
+	call WaitBGMap2
+	ret
+; 16d6e1
+
+Function16d6e1: ; 16d6e1
+	hlcoord 4, 10
+	ld b, 1
+	ld c, 10
+	predef LinkTextboxAtHL
+	hlcoord 5, 11
+	ld de, .Waiting
+	call PlaceString
+	call WaitBGMap
+	call WaitBGMap2
+	ld c, 50
+	jp DelayFrames
+; 16d701
+
+.Waiting: ; 16d701
+	db "WAITING..!@"
+; 16d70c
+
+LinkTradeMenu: ; 16d70c
+	call .MenuAction
+	call .GetJoypad
+	ret
+; 16d713
+
+.GetJoypad: ; 16d713
+	push bc
+	push af
+	ld a, [hJoyLast]
+	and D_PAD
+	ld b, a
+	ld a, [hJoyPressed]
+	and BUTTONS
+	or b
+	ld b, a
+	pop af
+	ld a, b
+	pop bc
+	ld d, a
+	ret
+; 16d725
+
+.MenuAction: ; 16d725
+	ld hl, w2DMenuFlags2
+	res 7, [hl]
+	ld a, [hBGMapMode]
+	push af
+	call .loop
+	pop af
+	ld [hBGMapMode], a
+	ret
+
+.loop
+	call .UpdateCursor
+	call .UpdateBGMapAndOAM
+	call .loop2
+	jr nc, .done
+	farcall _2DMenuInterpretJoypad
+	jr c, .done
+	ld a, [w2DMenuFlags1]
+	bit 7, a
+	jr nz, .done
+	call .GetJoypad
+	ld b, a
+	ld a, [wMenuJoypadFilter]
+	and b
+	jr z, .loop
+
+.done
+	ret
+; 16d759
+
+.UpdateBGMapAndOAM: ; 16d759
+	ld a, [hOAMUpdate]
+	push af
+	ld a, $1
+	ld [hOAMUpdate], a
+	call WaitBGMap
+	pop af
+	ld [hOAMUpdate], a
+	xor a
+	ld [hBGMapMode], a
+	ret
+
+.loop2
+	call RTC
+	call .TryAnims
+	ret c
+	ld a, [w2DMenuFlags1]
+	bit 7, a
+	jr z, .loop2
+	and a
+	ret
+; 16d77a
+
+.UpdateCursor: ; 16d77a
+	ld hl, wCursorCurrentTile
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [hl]
+	cp $1f
+	jr nz, .not_currently_selected
+	ld a, [wCursorOffCharacter]
+	ld [hl], a
+	push hl
+	push bc
+	ld bc, MON_NAME_LENGTH
+	add hl, bc
+	ld [hl], a
+	pop bc
+	pop hl
+
+.not_currently_selected
+	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, .skip
+.loop3
+	add c
+	dec b
+	jr nz, .loop3
+
+.skip
+	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, .skip2
+.loop4
+	add c
+	dec b
+	jr nz, .loop4
+
+.skip2
+	ld c, a
+	add hl, bc
+	ld a, [hl]
+	cp $1f
+	jr z, .cursor_already_there
+	ld [wCursorOffCharacter], a
+	ld [hl], $1f
+	push hl
+	push bc
+	ld bc, MON_NAME_LENGTH
+	add hl, bc
+	ld [hl], $1f
+	pop bc
+	pop hl
+.cursor_already_there
+	ld a, l
+	ld [wCursorCurrentTile], a
+	ld a, h
+	ld [wCursorCurrentTile + 1], a
+	ret
+; 16d7e7
+
+.TryAnims: ; 16d7e7
+	ld a, [w2DMenuFlags1]
+	bit 6, a
+	jr z, .skip_anims
+	farcall PlaySpriteAnimationsAndDelayFrame
+.skip_anims
+	call JoyTextDelay
+	call .GetJoypad
+	and a
+	ret z
+	scf
+	ret
+; 16d7fe
--- /dev/null
+++ b/engine/link/mystery_gift.asm
@@ -1,0 +1,1735 @@
+DoMysteryGift: ; 1048ba (41:48ba)
+	call ClearTileMap
+	call ClearSprites
+	call WaitBGMap
+	call InitMysteryGiftLayout
+	hlcoord 3, 8
+	ld de, .String_PressAToLink_BToCancel
+	call PlaceString
+	call WaitBGMap
+	farcall PrepMysteryGiftDataToSend
+	call MysteryGift_ClearTrainerData
+	ld a, $2
+	ld [wca01], a
+	ld a, $14
+	ld [wca02], a
+	ld a, [rIE]
+	push af
+
+	call Function104a95
+
+	ld d, a
+	xor a
+	ld [rIF], a
+	pop af
+	ld [rIE], a
+	push de
+	call ClearTileMap
+	call EnableLCD
+	call WaitBGMap
+	ld b, SCGB_DIPLOMA
+	call GetSGBLayout
+	call SetPalettes
+	pop de
+	hlcoord 2, 8
+	ld a, d
+	ld de, .Text_LinkCanceled ; Link has been canceled
+	cp $10
+	jp z, .LinkCanceled
+	cp $6c
+	jp nz, .CommunicationError
+	ld a, [wc900]
+	cp 3
+	jr z, .skip_checks
+	call .CheckAlreadyGotFiveGiftsToday
+	ld hl, .Text_MaxFiveGifts ; Only 5 gifts a day
+	jp nc, .PrintTextAndExit
+	call .CheckAlreadyGotAGiftFromThatPerson
+	ld hl, .Text_MaxOneGiftPerPerson ; Only one gift a day per person
+	jp c, .PrintTextAndExit
+.skip_checks
+	ld a, [wMysteryGiftPlayerBackupItem]
+	and a
+	jp nz, .GiftWaiting
+	ld a, [wMysteryGiftPartnerBackupItem]
+	and a
+	jp nz, .FriendNotReady
+	ld a, [wc900]
+	cp 3
+	jr z, .skip_append_save
+	call .AddMysteryGiftPartnerID
+	ld a, [wc900]
+	cp 4
+	jr z, .skip_append_save
+	call .SaveMysteryGiftTrainerName
+	farcall RestoreMobileEventIndex
+	farcall StubbedTrainerRankings_MysteryGift
+	farcall BackupMobileEventIndex
+.skip_append_save
+	ld a, [wMysteryGiftPartnerSentDeco]
+	and a
+	jr z, .item
+	ld a, [wMysteryGiftPartnerWhichDeco]
+	ld c, a
+	farcall MysteryGiftGetDecoration
+	push bc
+	call MysteryGift_CheckAndSetDecorationAlreadyReceived
+	pop bc
+	jr nz, .item
+	callfar GetDecorationName_c
+	ld h, d
+	ld l, e
+	ld de, wStringBuffer1
+	ld bc, ITEM_NAME_LENGTH
+	call CopyBytes
+	ld hl, .Text_SentToHome ; sent decoration to home
+	jr .PrintTextAndExit
+
+.item
+	call GetMysteryGiftBank
+	ld a, [wMysteryGiftPartnerWhichItem]
+	ld c, a
+	farcall MysteryGiftGetItemHeldEffect
+	ld a, c
+	ld [sBackupMysteryGiftItem], a
+	ld [wNamedObjectIndexBuffer], a
+	call CloseSRAM
+	call GetItemName
+	ld hl, .Text_Sent ; sent item
+	jr .PrintTextAndExit
+
+.LinkCanceled: ; 1049af (41:49af)
+	ld hl, .Text_LinkCanceled ; Link has been canceled
+	jr .PrintTextAndExit
+
+.CommunicationError: ; 1049b4 (41:49b4)
+	ld hl, .Text_CommunicationError ; Communication error
+	call PrintText
+	jp DoMysteryGift
+
+.GiftWaiting: ; 1049bd (41:49bd)
+	ld hl, .Text_ReceiveGiftAtCounter ; receive gift at counter
+	jr .PrintTextAndExit
+
+.FriendNotReady: ; 1049c2 (41:49c2)
+	ld hl, .Text_FriendNotReady ; friend not ready
+
+.PrintTextAndExit: ; 1049c5 (41:49c5)
+	call PrintText
+	ld a, LCDC_DEFAULT
+	ld [rLCDC], a
+	ret
+; 1049cd (41:49cd)
+
+.String_PressAToLink_BToCancel: ; 1049cd
+	db   "Press A to"
+	next "link IR-Device"
+	next "Press B to"
+	next "cancel it."
+	db   "@"
+; 1049fd
+
+.Text_LinkCanceled: ; 1049fd
+	text_jump UnknownText_0x1c0436
+	db "@"
+; 104a02
+
+.Text_CommunicationError: ; 104a02
+	text_jump UnknownText_0x1c0454
+	db "@"
+; 104a07
+
+.Text_ReceiveGiftAtCounter: ; 104a07
+	text_jump UnknownText_0x1c046a
+	db "@"
+; 104a0c
+
+.Text_FriendNotReady: ; 104a0c
+	text_jump UnknownText_0x1c048e
+	db "@"
+; 104a11
+
+.Text_MaxFiveGifts: ; 104a11
+	text_jump UnknownText_0x1c04a7
+	db "@"
+; 104a16
+
+.Text_MaxOneGiftPerPerson: ; 104a16
+	text_jump UnknownText_0x1c04c6
+	db "@"
+; 104a1b
+
+.Text_Sent: ; 104a1b
+	text_jump UnknownText_0x1c04e9
+	db "@"
+; 104a20
+
+.Text_SentToHome: ; 104a20
+	text_jump UnknownText_0x1c04fa
+	db "@"
+; 104a25
+
+.CheckAlreadyGotFiveGiftsToday: ; 104a25 (41:4a25)
+	call GetMysteryGiftBank
+	ld a, [sNumDailyMysteryGiftPartnerIDs]
+	cp $5
+	jp CloseSRAM
+
+.CheckAlreadyGotAGiftFromThatPerson: ; 104a30 (41:4a30)
+	call GetMysteryGiftBank
+	ld a, [wMysteryGiftPartnerID]
+	ld b, a
+	ld a, [wMysteryGiftPartnerID + 1]
+	ld c, a
+	ld a, [sNumDailyMysteryGiftPartnerIDs]
+	ld d, a
+	ld hl, sDailyMysteryGiftPartnerIDs
+.loop
+	ld a, d
+	and a
+	jr z, .No
+	ld a, [hli]
+	cp b
+	jr nz, .skip
+	ld a, [hl]
+	cp c
+	jr z, .Yes
+.skip
+	inc hl
+	dec d
+	jr .loop
+.Yes:
+	scf
+.No:
+	jp CloseSRAM
+
+.AddMysteryGiftPartnerID: ; 104a56 (41:4a56)
+	call GetMysteryGiftBank
+	ld hl, sNumDailyMysteryGiftPartnerIDs
+	ld a, [hl]
+	inc [hl]
+	ld hl, sDailyMysteryGiftPartnerIDs ; inc hl
+	ld e, a
+	ld d, $0
+	add hl, de
+	add hl, de
+	ld a, [wMysteryGiftPartnerID]
+	ld [hli], a
+	ld a, [wMysteryGiftPartnerID + 1]
+	ld [hl], a
+	jp CloseSRAM
+
+.SaveMysteryGiftTrainerName: ; 104a71 (41:4a71)
+	call GetMysteryGiftBank
+	ld a, $1
+	ld [sMysteryGiftTrainerHouseFlag], a
+	ld hl, wMysteryGiftPartnerName
+	ld de, sMysteryGiftPartnerName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ld a, $1
+	ld [de], a
+	inc de
+	ld hl, wMysteryGiftTrainerData
+	ld bc, (1 + 1 + NUM_MOVES) * PARTY_LENGTH + 2
+	call CopyBytes
+	jp CloseSRAM
+
+Function104a95: ; 104a95 (41:4a95)
+	di
+	farcall ClearChannels
+	call Function104d5e
+
+.loop2
+	call Function104d96
+	call Function104ddd
+	ld a, [hMGStatusFlags]
+	cp $10
+	jp z, Function104bd0
+	cp $6c
+	jr nz, .loop2
+
+	ld a, [hPrintNum9]
+	cp $2
+	jr z, Function104b22
+	ld hl, hPrintNum1
+	ld b, $1
+	call Function104d56
+	jr nz, .ly_loop
+	call Function104b49
+	jp nz, Function104bd0
+	jr Function104b0a
+	; Delay frame
+.ly_loop
+	ld a, [rLY]
+	cp LY_VBLANK
+	jr c, .ly_loop
+	ld c, LOW(rRP)
+	ld a, $c0
+	ld [$ff00+c], a
+	ld b, 240 ; This might have been intended as a 4-second timeout buffer.
+	          ; However, it is reset with each frame.
+.loop3
+	push bc
+	call MysteryGift_ReadJoypad
+
+	ld b, $2
+	ld c, LOW(rRP)
+	; Delay frame
+.ly_loop2
+	ld a, [$ff00+c]
+	and b
+	ld b, a
+	ld a, [rLY]
+	cp LY_VBLANK
+	jr nc, .ly_loop2
+.ly_loop3
+	ld a, [$ff00+c]
+	and b
+	ld b, a
+	ld a, [rLY]
+	cp LY_VBLANK
+	jr c, .ly_loop3
+
+	ld a, b
+	pop bc
+	dec b
+	jr z, .loop2 ; we never jump here
+	or a
+	jr nz, .loop2
+	; Check if we've pressed the B button
+	ld a, [hMGJoypadReleased]
+	bit B_BUTTON_F, a
+	jr z, .loop3
+	ld a, $10
+	ld [hMGStatusFlags], a
+	jp Function104bd0
+
+Function104b04: ; 104b04 (41:4b04)
+	call Function104b40
+	jp nz, Function104bd0
+Function104b0a: ; 104b0a (41:4b0a)
+	call Function104d38
+	jp nz, Function104bd0
+	call Function104b88
+	jp nz, Function104bd0
+	call Function104d43
+	jp nz, Function104bd0
+	call Function105033
+	jp Function104bd0
+
+Function104b22: ; 104b22 (41:4b22)
+	call Function104b88
+	jp nz, Function104bd0
+	call Function104d43
+	jp nz, Function104bd0
+	call Function104b40
+	jp nz, Function104bd0
+	call Function104d38
+	jp nz, Function104bd0
+	call Function10502e
+	jp Function104bd0
+
+Function104b40: ; 104b40 (41:4b40)
+	ld hl, hPrintNum1
+	ld b, $1
+	call Function104d56
+	ret nz
+
+Function104b49: ; 104b49 (41:4b49)
+	call Function105033
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret nz
+	ld a, [hPrintNum1]
+	cp $96
+	jp nz, Function104d32
+	ld a, $90
+	ld [hPrintNum1], a
+	call Function104d38
+	ret nz
+	ld hl, hPrintNum1
+	ld b, $1
+	call Function104d4e
+	ret nz
+	call Function10502e
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret nz
+	call Function104d43
+	ret nz
+	ld hl, wMysteryGiftTrainerData
+	ld a, [wca02]
+	ld b, a
+	call Function104d56
+	ret nz
+	call Function105033
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret
+
+Function104b88: ; 104b88 (41:4b88)
+	ld a, $96
+	ld [hPrintNum1], a
+	ld hl, hPrintNum1
+	ld b, $1
+	call Function104d4e
+	ret nz
+	call Function10502e
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret nz
+	call Function104d43
+	ret nz
+	ld hl, hPrintNum1
+	ld b, $1
+	call Function104d56
+	ret nz
+	call Function105033
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret nz
+	ld a, [hPrintNum1]
+	cp $90
+	jp nz, Function104d32
+	call Function104d38
+	ret nz
+	ld hl, wOverworldMap
+	ld a, [wca02]
+	ld b, a
+	call Function104d4e
+	ret nz
+	call Function10502e
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret
+
+Function104bd0: ; 104bd0 (41:4bd0)
+	nop
+	ld a, [hMGStatusFlags]
+	cp $10
+	jr z, .quit
+	cp $6c
+	jr nz, .quit
+	ld hl, wca01
+	dec [hl]
+	jr z, .quit
+	ld hl, wMysteryGiftTrainerData
+	ld de, wMysteryGiftPartnerData
+	ld bc, wMysteryGiftPartnerDataEnd - wMysteryGiftPartnerData
+	call CopyBytes
+	ld a, [wMysteryGiftTrainerData]
+	cp $3
+	jr nc, .quit
+	farcall StagePartyDataForMysteryGift
+	call MysteryGift_ClearTrainerData
+	ld a, $26
+	ld [wca02], a
+	ld a, [hPrintNum9]
+	cp $2
+	jr z, .asm_104c10
+	call Function104d43
+	jr nz, Function104bd0
+	jp Function104b04
+
+.asm_104c10
+	call Function104d38
+	jr nz, Function104bd0
+	jp Function104b22
+
+.quit
+	ld a, [hMGStatusFlags]
+	push af
+	call Function104da0
+	xor a
+	ld [rIF], a
+	ld a, [rIE]
+	or $1
+	ld [rIE], a
+	ei
+	call DelayFrame
+	pop af
+	ret
+
+Function104c2d: ; 104c2d (41:4c2d)
+	di
+	farcall ClearChannels
+	call Function104d5e
+.asm_104c37
+	call Function104d96
+	call Function104ddd
+	ld a, [hMGStatusFlags]
+	cp $10
+	jp z, Function104d1c
+	cp $6c
+	jr nz, .asm_104c37
+	ld a, [hPrintNum9]
+	cp $2
+	jr z, .asm_104c6c
+	call Function104c8a
+	jp nz, Function104d1c
+	call Function104d38
+	jp nz, Function104d1c
+	call Function104cd2
+	jp nz, Function104d1c
+	call Function104d43
+	jp nz, Function104d1c
+	call Function105033
+	jp Function104d1c
+.asm_104c6c
+	call Function104cd2
+	jp nz, Function104d1c
+	call Function104d43
+	jp nz, Function104d1c
+	call Function104c8a
+	jp nz, Function104d1c
+	call Function104d38
+	jp nz, Function104d1c
+	call Function10502e
+	jp Function104d1c
+
+Function104c8a: ; 104c8a (41:4c8a)
+	ld hl, hPrintNum1
+	ld b, $1
+	call Function104d56
+	ret nz
+	call Function105033
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret nz
+	ld a, [hPrintNum1]
+	cp $3c
+	jp nz, Function104d32
+	swap a
+	ld [hPrintNum1], a
+	call Function104d38
+	ret nz
+	ld hl, hPrintNum1
+	ld b, $1
+	call Function104d4e
+	ret nz
+	call Function10502e
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret nz
+	call Function104d43
+	ret nz
+	ld hl, wMysteryGiftTrainerData
+	ld a, [wca02]
+	ld b, a
+	call Function104d56
+	ret nz
+	call Function105033
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret
+
+Function104cd2: ; 104cd2 (41:4cd2)
+	ld a, $3c
+	ld [hPrintNum1], a
+	ld hl, hPrintNum1
+	ld b, $1
+	call Function104d4e
+	ret nz
+	call Function10502e
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret nz
+	call Function104d43
+	ret nz
+	ld hl, hPrintNum1
+	ld b, $1
+	call Function104d56
+	ret nz
+	call Function105033
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret nz
+	ld a, [hPrintNum1]
+	swap a
+	cp $3c
+	jp nz, Function104d32
+	call Function104d38
+	ret nz
+	ld hl, wOverworldMap
+	ld a, [wca02]
+	ld b, a
+	call Function104d4e
+	ret nz
+	call Function10502e
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret
+
+Function104d1c: ; 104d1c (41:4d1c)
+	nop
+	ld a, [hMGStatusFlags]
+	push af
+	call Function104da0
+	xor a
+	ld [rIF], a
+	ld a, [rIE]
+	or $1
+	ld [rIE], a
+	ei
+	call DelayFrame
+	pop af
+	ret
+
+Function104d32: ; 104d32 (41:4d32)
+	ld a, $80
+	ld [hMGStatusFlags], a
+	and a
+	ret
+
+Function104d38: ; 104d38 (41:4d38)
+	call Function104d96
+	call Function104e46
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret
+
+Function104d43: ; 104d43 (41:4d43)
+	call Function104d96
+	call Function104dfe
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret
+
+Function104d4e: ; 104d4e (41:4d4e)
+	call Function104e93
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret
+
+Function104d56: ; 104d56 (41:4d56)
+	call Function104f57
+	ld a, [hMGStatusFlags]
+	cp $6c
+	ret
+
+Function104d5e: ; 104d5e (41:4d5e)
+	call Function104d74
+	ld a, $4
+	ld [rIE], a
+	xor a
+	ld [rIF], a
+	call Function104d96
+	xor a
+	ld b, a
+.asm_104d6d
+	inc a
+	jr nz, .asm_104d6d
+	inc b
+	jr nz, .asm_104d6d
+	ret
+
+Function104d74: ; 104d74 (41:4d74)
+	xor a
+	ld [rTAC], a
+	ld a, $fe
+	ld [rTMA], a
+	ld [rTIMA], a
+	ld a, $2
+	ld [rTAC], a
+	or $4
+	ld [rTAC], a
+	ret
+
+Function104d86: ; 104d86 (41:4d86)
+	xor a
+	ld [rTAC], a
+	ld [rTMA], a
+	ld [rTIMA], a
+	ld a, $2
+	ld [rTAC], a
+	or $4
+	ld [rTAC], a
+	ret
+
+Function104d96: ; 104d96 (41:4d96)
+	ld a, $c0
+	call Function104e8c
+	ld a, $1
+	ld [hPrintNum9], a
+	ret
+
+Function104da0: ; 104da0 (41:4da0)
+	xor a
+	call Function104e8c
+	ld a, $2
+	ld [rTAC], a
+	ret
+
+Function104da9: ; 104da9 (41:4da9)
+	inc d
+	ret z
+	xor a
+	ld [rIF], a
+	halt
+	ld a, [$ff00+c]
+	bit 1, a
+	jr z, Function104da9
+	or a
+	ret
+
+Function104db7: ; 104db7 (41:4db7)
+	inc d
+	ret z
+	xor a
+	ld [rIF], a
+	halt
+	ld a, [$ff00+c]
+	bit 1, a
+	jr nz, Function104db7
+	or a
+	ret
+
+Function104dc5: ; 104dc5 (41:4dc5)
+	ld a, $c1
+	ld [$ff00+c], a
+.wait
+	dec d
+	ret z
+	xor a
+	ld [rIF], a
+	halt
+	jr .wait
+
+Function104dd1: ; 104dd1 (41:4dd1)
+	ld a, $c0
+	ld [$ff00+c], a
+.wait
+	dec d
+	ret z
+	xor a
+	ld [rIF], a
+	halt
+	jr .wait
+
+Function104ddd: ; 104ddd (41:4ddd)
+	ld d, $0
+	ld e, d
+	ld a, $1
+	ld [hPrintNum9], a
+.loop
+	call MysteryGift_ReadJoypad
+	ld b, $2
+	ld c, LOW(rRP)
+	ld a, [hMGJoypadReleased]
+	bit B_BUTTON_F, a
+	jr z, .next
+	ld a, $10
+	ld [hMGStatusFlags], a
+	ret
+
+.next
+	bit 0, a
+	jr nz, Function104e3a
+	ld a, [$ff00+c]
+	and b
+	jr nz, .loop
+
+Function104dfe: ; 104dfe (41:4dfe)
+	ld c, LOW(rRP)
+	ld d, $0
+	ld e, d
+	call Function104db7
+	jp z, Function104f42
+	ld d, e
+	call Function104da9
+	jp z, Function104f42
+	call Function104db7
+	jp z, Function104f42
+	call Function104da9
+	jp z, Function104f42
+	ld a, $6c
+	ld [hMGStatusFlags], a
+	ld d, $3d
+	call Function104dd1
+	ld d, $5
+	call Function104dc5
+	ld d, $15
+	call Function104dd1
+	ld d, $5
+	call Function104dc5
+	ld d, $5
+	call Function104dd1
+	ret
+
+Function104e3a: ; 104e3a (41:4e3a)
+	; Wait a random amount of time
+	call Random
+	ld e, a
+	and $f
+	ld d, a
+.loop
+	dec de
+	ld a, d
+	or e
+	jr nz, .loop
+Function104e46: ; 104e46 (41:4e46)
+	ld a, $2
+	ld [hPrintNum9], a
+	ld c, LOW(rRP)
+	ld d, $0
+	ld e, d
+	ld d, $3d
+	call Function104dd1
+	ld d, $5
+	call Function104dc5
+	ld d, $15
+	call Function104dd1
+	ld d, $5
+	call Function104dc5
+	ld d, $5
+	call Function104dd1
+	ld d, e
+	call Function104db7
+	jp z, Function104f42
+	ld d, e
+	call Function104da9
+	jp z, Function104f42
+	call Function104db7
+	jp z, Function104f42
+	call Function104da9
+	jp z, Function104f42
+	ld d, $3d
+	call Function104dd1
+	ld a, $6c
+	ld [hMGStatusFlags], a
+	ret
+
+Function104e8c: ; 104e8c (41:4e8c)
+	ld [rRP], a
+	ld a, $ff
+	ld [hMGStatusFlags], a
+	ret
+
+Function104e93: ; 104e93 (41:4e93)
+	xor a
+	ld [hPrintNum5], a
+	ld [hPrintNum6], a
+	push hl
+	push bc
+	ld c, LOW(rRP)
+	ld d, $3d
+	call Function104dd1
+	ld hl, hPrintNum2
+	ld a, $5a
+	ld [hli], a
+	ld [hl], b
+	dec hl
+	ld b, $2
+	call Function104ed6
+	pop bc
+	pop hl
+	call Function104ed6
+	ld a, [hPrintNum5]
+	ld [hPrintNum2], a
+	ld a, [hPrintNum6]
+	ld [hPrintNum3], a
+	push hl
+	ld hl, hPrintNum2
+	ld b, $2
+	call Function104ed6
+	ld hl, hMGStatusFlags
+	ld b, $1
+	call Function104faf
+	ld a, [hPrintNum2]
+	ld [hPrintNum5], a
+	ld a, [hPrintNum3]
+	ld [hPrintNum6], a
+	pop hl
+	ret
+
+Function104ed6: ; 104ed6 (41:4ed6)
+	ld c, LOW(rRP)
+	ld d, $5
+	call Function104dd1
+	ld d, $5
+	call Function104dc5
+	ld d, $15
+	call Function104dd1
+	ld a, b
+	cpl
+	ld b, a
+	ld a, $f4
+	ld [rTMA], a
+.asm_104eee
+	inc b
+	jr z, .asm_104f2e
+	ld a, $8
+	ld [hPrintNum4], a
+	ld a, [hli]
+	ld e, a
+	ld a, [hPrintNum5]
+	add e
+	ld [hPrintNum5], a
+	ld a, [hPrintNum6]
+	adc 0
+	ld [hPrintNum6], a
+.asm_104f02
+	xor a
+	ld [rIF], a
+	halt
+	ld a, $c1
+	ld [rRP], a
+	ld d, $1
+	ld a, e
+	rlca
+	ld e, a
+	jr nc, .asm_104f13
+	inc d
+.asm_104f13
+	ld a, [rTIMA]
+	cp $f8
+	jr c, .asm_104f13
+	ld a, $c0
+	ld [rRP], a
+	dec d
+	jr z, .asm_104f25
+	xor a
+	ld [rIF], a
+	halt
+.asm_104f25
+	ld a, [hPrintNum4]
+	dec a
+	jr z, .asm_104eee
+	ld [hPrintNum4], a
+	jr .asm_104f02
+.asm_104f2e
+	ld a, $fe
+	ld [rTMA], a
+	xor a
+	ld [rIF], a
+	halt
+	ld d, $5
+	call Function104dc5
+	ld d, $11
+	call Function104dd1
+	ret
+
+Function104f42: ; 104f42 (41:4f42)
+	ld a, [hMGStatusFlags]
+	or $2
+	ld [hMGStatusFlags], a
+	ret
+
+Function104f49: ; 104f49 (41:4f49)
+	ld a, [hMGStatusFlags]
+	or $1
+	ld [hMGStatusFlags], a
+	ret
+
+Function104f50: ; 104f50 (41:4f50)
+	ld a, [hMGStatusFlags]
+	or $80
+	ld [hMGStatusFlags], a
+	ret
+
+Function104f57: ; 104f57 (41:4f57)
+	xor a
+	ld [hPrintNum5], a
+	ld [hPrintNum6], a
+	push bc
+	push hl
+	ld hl, hPrintNum2
+	ld b, $2
+	call Function104faf
+	ld a, [hPrintNum3]
+	ld [hPrintNum8], a
+	ld b, a
+	pop hl
+	pop af
+	cp b
+	jp c, Function104f50
+	ld a, [hPrintNum2]
+	cp $5a
+	jp nz, Function104f50
+	call Function104faf
+	ld a, [hPrintNum5]
+	ld d, a
+	ld a, [hPrintNum6]
+	ld e, a
+	push hl
+	push de
+	ld hl, hPrintNum2
+	ld b, $2
+	call Function104faf
+	pop de
+	ld hl, hPrintNum2
+	ld a, [hli]
+	xor d
+	ld b, a
+	ld a, [hl]
+	xor e
+	or b
+	call nz, Function104f49
+	push de
+	ld d, $3d
+	call Function104dd1
+	ld hl, hMGStatusFlags
+	ld b, $1
+	call Function104ed6
+	pop de
+	pop hl
+	ld a, d
+	ld [hPrintNum5], a
+	ld a, e
+	ld [hPrintNum6], a
+	ret
+
+Function104faf: ; 104faf (41:4faf)
+	ld c, LOW(rRP)
+	ld d, $0
+	call Function104db7
+	jp z, Function104f42
+	ld d, $0
+	call Function104da9
+	jp z, Function104f42
+	ld d, $0
+	call Function104db7
+	jp z, Function104f42
+	ld a, b
+	cpl
+	ld b, a
+	xor a
+	ld [hMGJoypadPressed + 2], a
+	call Function104d86
+.asm_104fd2
+	inc b
+	jr z, .asm_10501a
+	ld a, $8
+	ld [hPrintNum4], a
+.asm_104fd9
+	ld d, $0
+.asm_104fdb
+	inc d
+	jr z, .asm_104fe5
+	ld a, [$ff00+c]
+	bit 1, a
+	jr z, .asm_104fdb
+	ld d, $0
+.asm_104fe5
+	inc d
+	jr z, .asm_104fed
+	ld a, [$ff00+c]
+	bit 1, a
+	jr nz, .asm_104fe5
+.asm_104fed
+	ld a, [hMGJoypadPressed + 2]
+	ld d, a
+	ld a, [rTIMA]
+	ld [hMGJoypadPressed + 2], a
+	sub d
+	cp $12
+	jr c, .asm_104ffd
+	set 0, e
+	jr .asm_104fff
+.asm_104ffd
+	res 0, e
+.asm_104fff
+	ld a, [hPrintNum4]
+	dec a
+	ld [hPrintNum4], a
+	jr z, .asm_10500b
+	ld a, e
+	rlca
+	ld e, a
+	jr .asm_104fd9
+.asm_10500b
+	ld a, e
+	ld [hli], a
+	ld a, [hPrintNum5]
+	add e
+	ld [hPrintNum5], a
+	ld a, [hPrintNum6]
+	adc 0
+	ld [hPrintNum6], a
+	jr .asm_104fd2
+.asm_10501a
+	call Function104d74
+	xor a
+	ld [rIF], a
+	ld d, $0
+	call Function104da9
+	jp z, Function104f42
+	ld d, $10
+	call Function104dd1
+	ret
+
+Function10502e: ; 10502e (41:502e)
+	ld b, $0
+	jp Function104e93
+
+Function105033: ; 105033 (41:5033)
+	ld b, $0
+	jp Function104f57
+
+MysteryGift_ReadJoypad: ; 105038 (41:5038)
+; We can only get four inputs at a time.
+; We take d-pad first for no particular reason.
+	ld a, R_DPAD
+	ld [rJOYP], a
+; Read twice to give the request time to take.
+	ld a, [rJOYP]
+	ld a, [rJOYP]
+
+; The Joypad register output is in the lo nybble (inversed).
+; We make the hi nybble of our new container d-pad input.
+	cpl
+	and $f
+	swap a
+
+; We'll keep this in b for now.
+	ld b, a
+
+; Buttons make 8 total inputs (A, B, Select, Start).
+; We can fit this into one byte.
+	ld a, R_BUTTONS
+	ld [rJOYP], a
+; Wait for input to stabilize.
+rept 6
+	ld a, [rJOYP]
+endr
+; Buttons take the lo nybble.
+	cpl
+	and $f
+	or b
+	ld c, a
+; To get the delta we xor the last frame's input with the new one.
+	ld a, [hMGJoypadPressed]
+	xor c
+; Released this frame:
+	and c
+	ld [hMGJoypadReleased], a
+; Pressed this frame:
+	ld a, c
+	ld [hMGJoypadPressed], a
+	ld a, $30
+; Reset the joypad register since we're done with it.
+	ld [rJOYP], a
+	ret
+
+MysteryGift_CheckAndSetDecorationAlreadyReceived: ; 105069 (41:5069)
+	call GetMysteryGiftBank
+	ld d, $0
+	ld b, CHECK_FLAG
+	ld hl, sMysteryGiftDecorationsReceived
+	predef_id SmallFarFlagAction
+	push hl
+	push bc
+	call Predef
+	call CloseSRAM
+	ld a, c
+	and a
+	pop bc
+	pop hl
+	ret nz
+	call GetMysteryGiftBank
+	ld b, SET_FLAG
+	predef SmallFarFlagAction
+	call CloseSRAM
+	xor a
+	ret
+
+MysteryGift_CopyReceivedDecosToPC: ; 105091 (41:5091)
+	call GetMysteryGiftBank
+	ld c, $0
+.loop
+	push bc
+	ld d, $0
+	ld b, CHECK_FLAG
+	ld hl, sMysteryGiftDecorationsReceived
+	predef SmallFarFlagAction
+	ld a, c
+	and a
+	pop bc
+	jr z, .skip
+	push bc
+	callfar SetSpecificDecorationFlag
+	pop bc
+.skip
+	inc c
+	ld a, c
+	cp TrophyIDs - DecorationIDs
+	jr c, .loop
+	jp CloseSRAM
+
+UnlockMysteryGift: ; 1050b9
+	call GetMysteryGiftBank
+	ld hl, sMysteryGiftUnlocked
+	ld a, [hl]
+	inc a
+	jr nz, .ok
+	ld [hld], a
+	ld [hl], a
+.ok
+	jp CloseSRAM
+; 1050c8
+
+Function1050c8: ; 1050c8
+	call GetMysteryGiftBank
+	ld a, [sNumDailyMysteryGiftPartnerIDs]
+	cp $ff
+	jr z, .okay
+	xor a
+	ld [sNumDailyMysteryGiftPartnerIDs], a
+.okay
+	jp CloseSRAM
+; 1050d9
+
+
+BackupMysteryGift: ; 1050d9
+	call GetMysteryGiftBank
+	ld hl, sMysteryGiftItem
+	ld de, sBackupMysteryGiftItem
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+	jp CloseSRAM
+; 1050ea
+
+
+RestoreMysteryGift: ; 1050ea (41:50ea)
+	call GetMysteryGiftBank
+	ld hl, sBackupMysteryGiftItem
+	ld de, sMysteryGiftItem
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+	jp CloseSRAM
+
+MysteryGift_ClearTrainerData: ; 1050fb (41:50fb)
+	ld hl, wMysteryGiftTrainerData
+	xor a
+	ld b, wMysteryGiftTrainerDataEnd - wMysteryGiftTrainerData
+.loop
+	ld [hli], a
+	dec b
+	jr nz, .loop
+	ret
+
+
+GetMysteryGiftBank: ; 105106
+	ld a, BANK(sBackupMysteryGiftItem)
+	jp GetSRAMBank
+; 10510b
+
+
+StagePartyDataForMysteryGift: ; 10510b (41:510b)
+; You will be sending this data to your mystery gift partner.
+; Structure is the same as a trainer with species and moves
+; defined.
+	ld a, BANK(sPokemonData)
+	call GetSRAMBank
+	ld de, wMysteryGiftStaging
+	ld bc, sPokemonData + wPartyMons - wPokemonData
+	ld hl, sPokemonData + wPartySpecies - wPokemonData
+.loop
+	ld a, [hli]
+	cp -1
+	jr z, .party_end
+	cp EGG
+	jr z, .next
+	push hl
+	; copy level
+	ld hl, MON_LEVEL
+	add hl, bc
+	ld a, [hl]
+	ld [de], a
+	inc de
+	; copy species
+	ld hl, MON_SPECIES
+	add hl, bc
+	ld a, [hl]
+	ld [de], a
+	inc de
+	; copy moves
+	ld hl, MON_MOVES
+	add hl, bc
+	push bc
+	ld bc, NUM_MOVES
+	call CopyBytes
+	pop bc
+	pop hl
+.next
+	push hl
+	ld hl, PARTYMON_STRUCT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	pop hl
+	jr .loop
+.party_end
+	ld a, -1
+	ld [de], a
+	ld a, $26
+	ld [wca00], a
+	jp CloseSRAM
+
+InitMysteryGiftLayout: ; 105153 (41:5153)
+	call ClearBGPalettes
+	call DisableLCD
+	ld hl, MysteryGiftGFX
+	ld de, vTiles2 tile $00
+	ld a, BANK(MysteryGiftGFX)
+	ld bc, MysteryGiftGFX.End - MysteryGiftGFX
+	call FarCopyBytes
+	hlcoord 0, 0
+	ld a, $42
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	call ByteFill
+	hlcoord 3, 7
+	lb bc, 9, 15
+	call ClearBox
+	hlcoord 0, 0
+	ld a, $0
+	ld [hli], a
+	inc a
+	ld [hl], a
+	hlcoord 0, 1
+	inc a
+	ld [hli], a
+	inc a
+	ld [hl], a
+	hlcoord 7, 1
+	ld a, $12
+	call .Load5GFX
+	hlcoord 2, 2
+	ld a, $17
+	call .Load16GFX
+	hlcoord 2, 3
+	ld a, $27
+	call .Load16GFX
+	hlcoord 9, 4
+	ld a, $37
+	ld [hli], a
+	inc a
+	ld [hl], a
+	hlcoord 1, 2
+	ld [hl], $4
+	hlcoord 1, 3
+	ld a, $5
+	call .Load14Column
+	ld a, $9
+	hlcoord 18, 5
+	call .Load11Column
+	hlcoord 2, 5
+	ld a, $b
+	call .Load16Row
+	hlcoord 2, 16
+	ld a, $7
+	call .Load16Row
+	hlcoord 2, 5
+	ld a, $d
+	call .Load5GFX
+	hlcoord 7, 5
+	ld [hl], $c
+	hlcoord 18, 5
+	ld [hl], $a
+	hlcoord 18, 16
+	ld [hl], $8
+	hlcoord 1, 16
+	ld [hl], $6
+	hlcoord 2, 6
+	ld a, $3a
+	call .Load16Row
+	hlcoord 2, 15
+	ld a, $40
+	call .Load16Row
+	hlcoord 2, 6
+	ld a, $3c
+	call .Load9Column
+	hlcoord 17, 6
+	ld a, $3e
+	call .Load9Column
+	hlcoord 2, 6
+	ld [hl], $39
+	hlcoord 17, 6
+	ld [hl], $3b
+	hlcoord 2, 15
+	ld [hl], $3f
+	hlcoord 17, 15
+	ld [hl], $41
+	call EnableLCD
+	call WaitBGMap
+	ld b, SCGB_MYSTERY_GIFT
+	call GetSGBLayout
+	call SetPalettes
+	ret
+
+.Load5GFX: ; 10522e (41:522e)
+	ld b,  5
+	jr .gfx_loop
+; 105232 (41:5232)
+
+.Unreferenced_Load6GFX:
+	ld b,  6
+	jr .gfx_loop
+
+.Load16GFX: ; 105236 (41:5236)
+	ld b, 16
+
+.gfx_loop ; 105238 (41:5238)
+	ld [hli], a
+	inc a
+	dec b
+	jr nz, .gfx_loop
+	ret
+
+.Load9Column: ; 10523e (41:523e)
+	ld b,  9
+	jr .col_loop
+
+.Load11Column: ; 105242 (41:5242)
+	ld b, 11
+	jr .col_loop
+
+.Load14Column: ; 105246 (41:5246)
+	ld b, 14
+
+.col_loop ; 105248 (41:5248)
+	ld [hl], a
+	ld de, SCREEN_WIDTH
+	add hl, de
+	dec b
+	jr nz, .col_loop
+	ret
+
+.Load16Row: ; 105251 (41:5251)
+	ld b, 16
+.row_loop
+	ld [hli], a
+	dec b
+	jr nz, .row_loop
+	ret
+
+MysteryGiftGFX: ; 105258
+INCBIN "gfx/mystery_gift/mystery_gift.2bpp"
+.End
+
+Function105688: ; 105688 (41:5688)
+	call ClearTileMap
+	call ClearSprites
+	call WaitBGMap
+	call Function1057d7
+	hlcoord 3, 8
+	ld de, String_PressAToLink_BToCancel_JP
+	call PlaceString
+	call WaitBGMap
+	call Function10578c
+	call MysteryGift_ClearTrainerData
+	ld a, $24
+	ld [wca02], a
+	ld a, [rIE]
+	push af
+	call Function104c2d
+	ld d, a
+	xor a
+	ld [rIF], a
+	pop af
+	ld [rIE], a
+	ld a, d
+	cp $10
+	jp z, Function105712
+	cp $6c
+	jp nz, Function10571a
+	call Function1056eb
+	ld c, 60
+	call DelayFrames
+	call Function105777
+	ld hl, Text_ReceivedCard
+	call PrintText
+	ld de, wMysteryGiftTrainerData
+	farcall Function8ac70
+	ld a, c
+	ld [wd265], a
+	ld hl, Text_CardNotRegistered
+	jr c, PrintTextAndExit_JP
+	ld hl, Text_ListedCardAsNumber
+	jr PrintTextAndExit_JP
+
+Function1056eb: ; 1056eb (41:56eb)
+	ld c, 16
+.loop
+	ld hl, wVirtualOAMSprite00YCoord
+	ld b, 8
+.dec_y_loop
+	dec [hl]
+rept SPRITEOAMSTRUCT_LENGTH
+	inc hl
+endr
+	dec b
+	jr nz, .dec_y_loop
+	ld hl, wVirtualOAMSprite08YCoord
+	ld b, 8
+.inc_y_loop
+	inc [hl]
+rept SPRITEOAMSTRUCT_LENGTH
+	inc hl
+endr
+	dec b
+	jr nz, .inc_y_loop
+	dec c
+	ret z
+	push bc
+	ld c, 4
+	call DelayFrames
+	pop bc
+	jr .loop
+
+Function105712: ; 105712 (41:5712)
+	call Function105777
+	ld hl, Text_MGLinkCanceled
+	jr PrintTextAndExit_JP
+
+Function10571a: ; 10571a (41:571a)
+	call Function105777
+	ld hl, Text_MGCommError
+	call PrintText
+	jp Function105688
+
+PrintTextAndExit_JP: ; 105726 (41:5726)
+	call PrintText
+	ld a, LCDC_DEFAULT
+	ld [rLCDC], a
+	ret
+; 10572e (41:572e)
+
+String_PressAToLink_BToCancel_JP: ; 10572e
+	db   "エーボタン<WO>おすと"
+	next "つうしん<PKMN>おこなわれるよ!"
+	next "ビーボタン<WO>おすと"
+	next "つうしん<WO>ちゅうし します"
+	db   "@"
+
+; 10575e
+
+Text_ReceivedCard: ; 10575e
+	text_jump UnknownText_0x1c051a
+	db "@"
+
+Text_ListedCardAsNumber: ; 105763
+	text_jump UnknownText_0x1c0531
+	db "@"
+
+Text_CardNotRegistered: ; 105768
+	text_jump UnknownText_0x1c0555
+	db "@"
+
+Text_MGLinkCanceled: ; 10576d
+	text_jump UnknownText_0x1c0573
+	db "@"
+
+Text_MGCommError: ; 105772
+	text_jump UnknownText_0x1c0591
+	db "@"
+; 105777
+
+Function105777: ; 105777 (41:5777)
+	call ClearSprites
+	call ClearTileMap
+	call EnableLCD
+	call WaitBGMap
+	ld b, SCGB_DIPLOMA
+	call GetSGBLayout
+	call SetPalettes
+	ret
+
+Function10578c: ; 10578c (41:578c)
+	ld de, wOverworldMap
+	ld a, BANK(sPlayerData)
+	call GetSRAMBank
+	ld hl, sPlayerData + wPlayerName - wPlayerData
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ld hl, sPlayerData + wPlayerID - wPlayerData
+	ld bc, 2
+	call CopyBytes
+	ld hl, sPlayerData + wSecretID - wPlayerData
+	ld bc, 2
+	call CopyBytes
+	call CloseSRAM
+	ld a, BANK(sCrystalData)
+	call GetSRAMBank
+	ld a, [sCrystalData + 0]
+	ld [de], a
+	inc de
+	ld a, 4 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
+	call GetSRAMBank
+	ld hl, $a603 ; address of MBC30 bank
+	ld bc, $8
+	call CopyBytes
+	ld hl, $a007 ; address of MBC30 bank
+	ld bc, $c
+	call CopyBytes
+	call CloseSRAM
+	ret
+
+Function1057d7: ; 1057d7 (41:57d7)
+	call ClearBGPalettes
+	call DisableLCD
+	ld hl, MysteryGiftJP_GFX
+	ld de, vTiles2 tile $00
+	ld a, BANK(MysteryGiftJP_GFX)
+	lb bc, 4, 0
+	call FarCopyBytes
+	ld hl, MysteryGiftJP_GFX + $40 tiles
+	ld de, vTiles0 tile $00
+	ld a, BANK(MysteryGiftJP_GFX)
+	ld bc, $80
+	call FarCopyBytes
+	hlcoord 0, 0
+	ld a, $3f
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	call ByteFill
+	hlcoord 3, 7
+	lb bc, 9, 15
+	call ClearBox
+	hlcoord 0, 0
+	ld a, $0
+	ld [hli], a
+	inc a
+	ld [hl], a
+	hlcoord 0, 1
+	inc a
+	ld [hli], a
+	inc a
+	ld [hl], a
+	hlcoord 4, 2
+	ld a, $13
+	call .Load11Row
+	hlcoord 4, 3
+	ld a, $1e
+	call .Load12Row
+	hlcoord 4, 4
+	ld a, $2a
+	call .Load12Row
+	hlcoord 1, 2
+	ld [hl], $4
+	hlcoord 1, 3
+	ld a, $5
+	call .Load14Column
+	ld a, $9
+	hlcoord 18, 5
+	call .Load11Column
+	hlcoord 2, 5
+	ld a, $b
+	call .Load16Row
+	hlcoord 2, 16
+	ld a, $7
+	call .Load16Row
+	hlcoord 2, 5
+	ld a, $d
+	call .Load6Row
+	hlcoord 8, 5
+	ld [hl], $c
+	hlcoord 18, 5
+	ld [hl], $a
+	hlcoord 18, 16
+	ld [hl], $8
+	hlcoord 1, 16
+	ld [hl], $6
+	hlcoord 2, 6
+	ld a, $37
+	call .Load16Row
+	hlcoord 2, 15
+	ld a, $3d
+	call .Load16Row
+	hlcoord 2, 6
+	ld a, $39
+	call .Load9Column
+	hlcoord 17, 6
+	ld a, $3b
+	call .Load9Column
+	hlcoord 2, 6
+	ld [hl], $36
+	hlcoord 17, 6
+	ld [hl], $38
+	hlcoord 2, 15
+	ld [hl], $3c
+	hlcoord 17, 15
+	ld [hl], $3e
+	ld de, wVirtualOAMSprite00
+	ld hl, .OAM_data
+	ld bc, 16 * SPRITEOAMSTRUCT_LENGTH
+	call CopyBytes
+	call EnableLCD
+	call WaitBGMap
+	ld b, $2
+	farcall GetMysteryGift_MobileAdapterLayout
+	jp SetPalettes
+
+.Load6Row: ; 1058c6 (41:58c6)
+	ld b,  6
+	jr .row_loop
+
+.Load11Row: ; 1058ca (41:58ca)
+	ld b, 11
+	jr .row_loop
+
+.Load12Row: ; 1058ce (41:58ce)
+	ld b, 12
+
+.row_loop ; 1058d0 (41:58d0)
+	ld [hli], a
+	inc a
+	dec b
+	jr nz, .row_loop
+	ret
+
+.Load9Column: ; 1058d6 (41:58d6)
+	ld b,  9
+	jr .column_loop
+
+.Load11Column: ; 1058da (41:58da)
+	ld b, 11
+	jr .column_loop
+
+.Load14Column: ; 1058de (41:58de)
+	ld b, 14
+
+.column_loop ; 1058e0 (41:58e0)
+	ld [hl], a
+	ld de, SCREEN_WIDTH
+	add hl, de
+	dec b
+	jr nz, .column_loop
+	ret
+
+.Load16Row: ; 1058e9 (41:58e9)
+	ld b, 16
+.row_loop_no_inc
+	ld [hli], a
+	dec b
+	jr nz, .row_loop_no_inc
+	ret
+; 1058f0 (41:58f0)
+
+.OAM_data: ; 1058f0
+	dsprite  2, 1,  6, 4, $00, 0
+	dsprite  2, 1,  7, 4, $01, 0
+	dsprite  2, 1,  8, 4, $02, 0
+	dsprite  2, 1,  9, 4, $03, 0
+	dsprite  3, 1,  6, 4, $04, 0
+	dsprite  3, 1,  7, 4, $05, 0
+	dsprite  3, 1,  8, 4, $06, 0
+	dsprite  3, 1,  9, 4, $07, 0
+	dsprite  0, 1, 11, 4, $00, 0
+	dsprite  0, 1, 12, 4, $01, 0
+	dsprite  0, 1, 13, 4, $02, 0
+	dsprite  0, 1, 14, 4, $03, 0
+	dsprite  1, 1, 11, 4, $04, 0
+	dsprite  1, 1, 12, 4, $05, 0
+	dsprite  1, 1, 13, 4, $06, 0
+	dsprite  1, 1, 14, 4, $07, 0
+
+; japanese mystery gift gfx
+MysteryGiftJP_GFX: ; 105930
+INCBIN "gfx/mystery_gift/mystery_gift_jp.2bpp"
--- /dev/null
+++ b/engine/link/mystery_gift_2.asm
@@ -1,0 +1,152 @@
+PrepMysteryGiftDataToSend: ; 2c642 (b:4642)
+	ld de, wMysteryGiftStaging
+	ld a, $1
+	ld [de], a
+	inc de ; wc801
+	ld a, BANK(sGameData)
+	call GetSRAMBank
+	ld hl, sPlayerData + wPlayerID - wPlayerData
+	ld a, [hli]
+	ld [de], a
+	ld b, a
+	inc de ; wc802
+	ld a, [hl]
+	ld [de], a
+	ld c, a
+	inc de ; wc803
+	push bc
+	ld hl, sPlayerData + wPlayerName - wPlayerData
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	push de ; wc80e
+	ld hl, sPokemonData + wPokedexCaught - wPokemonData
+	ld b, wEndPokedexCaught - wPokedexCaught
+	call CountSetBits
+	pop de
+	pop bc
+	ld a, [wd265]
+	ld [de], a
+	inc de ; wc80f
+	call CloseSRAM
+	call Random
+	and 1
+	ld [de], a
+	inc de ; wc810
+	call .RandomSample
+	ld [de], a
+	inc de ; wc811
+	ld a, c
+	ld c, b
+	ld b, a
+	call .RandomSample
+	ld [de], a
+	inc de ; wc812
+	ld a, BANK(sBackupMysteryGiftItem)
+	call GetSRAMBank
+	ld a, [sBackupMysteryGiftItem]
+	ld [de], a
+	inc de
+	ld a, [sBackupMysteryGiftItem + 1]
+	ld [de], a
+	ld a, $14
+	ld [wca00], a
+	call CloseSRAM
+	ld hl, wMysteryGiftStaging
+	ld de, wMysteryGiftPlayerData
+	ld bc, wMysteryGiftPlayerDataEnd - wMysteryGiftPlayerData
+	jp CopyBytes
+
+.RandomSample: ; 2c6ac (b:46ac)
+	push de
+	call Random
+	cp 10 percent
+	jr c, .tenpercent
+	call Random
+	and %111
+	ld d, a
+	rl d
+	ld e, $80
+.loop
+	rlc e
+	dec a
+	jr nz, .loop
+	ld a, e
+	and c
+	jr z, .skip
+	ld a, $1
+.skip
+	add d
+	jr .done
+
+.tenpercent
+	call Random
+	cp 20 percent - 1
+	jr c, .twopercent
+	call Random
+	and %011
+	ld d, a
+	rl d
+	ld e, $80
+.loop2
+	rlc e
+	dec a
+	jr nz, .loop2
+	ld a, e
+	and b
+	jr z, .skip2
+	ld a, $1
+.skip2
+	add d
+	add $10
+	jr .done
+
+.twopercent
+	call Random
+	cp 20 percent - 1
+	jr c, .pointfourpercent
+	ld a, b
+	swap a
+	and $7
+	add $18
+	jr .done
+
+.pointfourpercent
+	ld a, b
+	and $80
+	ld a, $20
+	jr z, .done
+	ld a, $21
+
+.done
+	pop de
+	ret
+
+MysteryGiftGetItemHeldEffect: ; 2c708 (b:4708)
+	ld a, c
+	cp MysteryGiftItems.End - MysteryGiftItems
+	jr nc, MysteryGiftFallbackItem
+	ld hl, MysteryGiftItems
+	ld b, 0
+	add hl, bc
+	ld c, [hl]
+	ret
+
+MysteryGiftGetDecoration: ; 2c715 (b:4715)
+	ld a, c
+	cp MysteryGiftDecos.End - MysteryGiftDecos
+	jr nc, MysteryGiftFallbackItem
+	ld hl, MysteryGiftDecos
+	ld b, 0
+	add hl, bc
+	ld c, [hl]
+	ret
+
+MysteryGiftFallbackItem: ; 2c722 (b:4722)
+	ld c, DECO_POLKADOT_BED ; GREAT_BALL
+	ret
+; 2c725 (b:4725)
+
+
+INCLUDE "data/items/mystery_gift_items.asm"
+
+INCLUDE "data/decorations/mystery_gift_decos.asm"
--- /dev/null
+++ b/engine/link/time_capsule.asm
@@ -1,0 +1,147 @@
+; These functions seem to be related to backwards compatibility
+
+ValidateOTTrademon: ; fb57e
+	ld a, [wd003]
+	ld hl, wOTPartyMon1Species
+	call GetPartyLocation
+	push hl
+	ld a, [wd003]
+	inc a
+	ld c, a
+	ld b, 0
+	ld hl, wOTPartyCount
+	add hl, bc
+	ld a, [hl]
+	pop hl
+	cp EGG
+	jr z, .matching_or_egg
+	cp [hl]
+	jr nz, .abnormal
+
+.matching_or_egg
+	ld b, h
+	ld c, l
+	ld hl, MON_LEVEL
+	add hl, bc
+	ld a, [hl]
+	cp MAX_LEVEL + 1
+	jr nc, .abnormal
+	ld a, [wLinkMode]
+	cp LINK_TIMECAPSULE
+	jr nz, .normal
+	ld hl, wOTPartySpecies
+	ld a, [wd003]
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [hl]
+
+	; Magnemite and Magneton's types changed
+	; from Electric to Electric/Steel.
+	cp MAGNEMITE
+	jr z, .normal
+	cp MAGNETON
+	jr z, .normal
+
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld hl, wLinkOTPartyMonTypes
+	add hl, bc
+	add hl, bc
+	ld a, [wBaseType1]
+	cp [hl]
+	jr nz, .abnormal
+	inc hl
+	ld a, [wBaseType2]
+	cp [hl]
+	jr nz, .abnormal
+
+.normal
+	and a
+	ret
+
+.abnormal
+	scf
+	ret
+; fb5dd
+
+Functionfb5dd: ; fb5dd
+	ld a, [wd002]
+	ld d, a
+	ld a, [wPartyCount]
+	ld b, a
+	ld c, $0
+.loop
+	ld a, c
+	cp d
+	jr z, .next
+	push bc
+	ld a, c
+	ld hl, wPartyMon1HP
+	call GetPartyLocation
+	pop bc
+	ld a, [hli]
+	or [hl]
+	jr nz, .done
+
+.next
+	inc c
+	dec b
+	jr nz, .loop
+	ld a, [wd003]
+	ld hl, wOTPartyMon1HP
+	call GetPartyLocation
+	ld a, [hli]
+	or [hl]
+	jr nz, .done
+	scf
+	ret
+
+.done
+	and a
+	ret
+; fb60d
+
+PlaceTradePartnerNamesAndParty: ; fb60d
+	hlcoord 4, 0
+	ld de, wPlayerName
+	call PlaceString
+	ld a, $14
+	ld [bc], a
+	hlcoord 4, 8
+	ld de, wOTPlayerName
+	call PlaceString
+	ld a, $14
+	ld [bc], a
+	hlcoord 7, 1
+	ld de, wPartySpecies
+	call .PlaceSpeciesNames
+	hlcoord 7, 9
+	ld de, wOTPartySpecies
+.PlaceSpeciesNames: ; fb634
+	ld c, $0
+.loop
+	ld a, [de]
+	cp -1
+	ret z
+	ld [wd265], a
+	push bc
+	push hl
+	push de
+	push hl
+	ld a, c
+	ld [hProduct], a
+	call GetPokemonName
+	pop hl
+	call PlaceString
+	pop de
+	inc de
+	pop hl
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	pop bc
+	inc c
+	jr .loop
+; fb656
+
+INCLUDE "data/pokemon/gen1_base_special.asm"
--- /dev/null
+++ b/engine/link/time_capsule_2.asm
@@ -1,0 +1,39 @@
+ConvertMon_2to1: ; fb8f1
+; Takes the Gen-2 Pokemon number stored in wd265, finds it in the Pokered_MonIndices table, and returns its index in wd265.
+	push bc
+	push hl
+	ld a, [wd265]
+	ld b, a
+	ld c, 0
+	ld hl, Pokered_MonIndices
+.loop
+	inc c
+	ld a, [hli]
+	cp b
+	jr nz, .loop
+	ld a, c
+	ld [wd265], a
+	pop hl
+	pop bc
+	ret
+; fb908
+
+ConvertMon_1to2: ; fb908
+; Takes the Gen-1 Pokemon number stored in wd265 and returns the corresponding value from Pokered_MonIndices in wd265.
+	push bc
+	push hl
+	ld a, [wd265]
+	dec a
+	ld hl, Pokered_MonIndices
+	ld b, 0
+	ld c, a
+	add hl, bc
+	ld a, [hl]
+	ld [wd265], a
+	pop hl
+	pop bc
+	ret
+; fb91c
+
+
+INCLUDE "data/pokemon/gen1_order.asm"
--- a/engine/link_2.asm
+++ /dev/null
@@ -1,95 +1,0 @@
-LinkMonStatsScreen: ; 4d319
-	ld a, [wMenuCursorY]
-	dec a
-	ld [wCurPartyMon], a
-	call LowVolume
-	predef StatsScreenInit
-	ld a, [wCurPartyMon]
-	inc a
-	ld [wMenuCursorY], a
-	call ClearScreen
-	call ClearBGPalettes
-	call MaxVolume
-	farcall LoadTradeScreenBorder
-	farcall Link_WaitBGMap
-	farcall InitTradeSpeciesList
-	farcall SetTradeRoomBGPals
-	call WaitBGMap2
-	ret
-
-Link_WaitBGMap: ; 4d354
-	call WaitBGMap
-	call WaitBGMap2
-	ret
-
-LinkTextbox2: ; 4d35b
-	ld h, d
-	ld l, e
-	push bc
-	push hl
-	call .PlaceBorder
-	pop hl
-	pop bc
-
-	ld de, wAttrMap - wTileMap
-	add hl, de
-	inc b
-	inc b
-	inc c
-	inc c
-	ld a, PAL_BG_TEXT
-.row
-	push bc
-	push hl
-.col
-	ld [hli], a
-	dec c
-	jr nz, .col
-	pop hl
-	ld de, SCREEN_WIDTH
-	add hl, de
-	pop bc
-	dec b
-	jr nz, .row
-	ret
-; 4d37e
-
-.PlaceBorder: ; 4d37e
-	push hl
-	ld a, $76
-	ld [hli], a
-	inc a
-	call .PlaceRow
-	inc a
-	ld [hl], a
-	pop hl
-	ld de, SCREEN_WIDTH
-	add hl, de
-.loop
-	push hl
-	ld a, "┌"
-	ld [hli], a
-	ld a, " "
-	call .PlaceRow
-	ld [hl], "─"
-	pop hl
-	ld de, SCREEN_WIDTH
-	add hl, de
-	dec b
-	jr nz, .loop
-
-	ld a, "┐"
-	ld [hli], a
-	ld a, "│"
-	call .PlaceRow
-	ld [hl], "└"
-	ret
-; 4d3ab
-
-.PlaceRow: ; 4d3ab
-	ld d, c
-.row_loop
-	ld [hli], a
-	dec d
-	jr nz, .row_loop
-	ret
--- a/engine/link_trade.asm
+++ /dev/null
@@ -1,363 +1,0 @@
-LinkCommsBorderGFX:
-INCBIN "gfx/trade/border_tiles.2bpp"
-; 16d421
-
-__LoadTradeScreenBorder: ; 16d421
-	ld de, LinkCommsBorderGFX
-	ld hl, vTiles2
-	lb bc, BANK(LinkCommsBorderGFX), 70
-	call Get2bpp
-	ret
-; 16d42e
-
-Function16d42e: ; 16d42e
-	ld hl, Tilemap_MobileTradeBorderFullscreen
-	decoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	call CopyBytes
-	ret
-; 16d43b
-
-Function16d43b: ; 16d43b
-	call LoadStandardMenuHeader
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	farcall __LoadTradeScreenBorder ; useless to farcall
-	farcall Function16d42e ; useless to farcall
-	ld b, SCGB_DIPLOMA
-	call GetSGBLayout
-	call SetPalettes
-	call WaitBGMap
-	call JoyWaitAorB
-	call Call_ExitMenu
-	ret
-; 16d465
-
-Tilemap_MobileTradeBorderFullscreen:
-INCBIN "gfx/trade/border_mobile_fullscreen.tilemap"
-
-Tilemap_CableTradeBorderTop:
-INCBIN "gfx/trade/border_cable_top.tilemap"
-
-Tilemap_CableTradeBorderBottom:
-INCBIN "gfx/trade/border_cable_bottom.tilemap"
-
-_LinkTextbox: ; 16d61d
-	ld h, d
-	ld l, e
-	push bc
-	push hl
-	call .PlaceBorder
-	pop hl
-	pop bc
-
-	ld de, wAttrMap - wTileMap
-	add hl, de
-	inc b
-	inc b
-	inc c
-	inc c
-	ld a, PAL_BG_TEXT
-.row
-	push bc
-	push hl
-.col
-	ld [hli], a
-	dec c
-	jr nz, .col
-	pop hl
-	ld de, SCREEN_WIDTH
-	add hl, de
-	pop bc
-	dec b
-	jr nz, .row
-	ret
-; 16d640
-
-.PlaceBorder ; 16d640
-	push hl
-	ld a, $30
-	ld [hli], a
-	inc a
-	call .PlaceRow
-	inc a
-	ld [hl], a
-	pop hl
-	ld de, SCREEN_WIDTH
-	add hl, de
-.loop
-	push hl
-	ld a, $33
-	ld [hli], a
-	ld a, " "
-	call .PlaceRow
-	ld [hl], $34
-	pop hl
-	ld de, SCREEN_WIDTH
-	add hl, de
-	dec b
-	jr nz, .loop
-
-	ld a, $35
-	ld [hli], a
-	ld a, $36
-	call .PlaceRow
-	ld [hl], $37
-	ret
-; 16d66d
-
-.PlaceRow ; 16d66d
-	ld d, c
-.row_loop
-	ld [hli], a
-	dec d
-	jr nz, .row_loop
-	ret
-; 16d673
-
-InitTradeSpeciesList: ; 16d673
-	call _LoadTradeScreenBorder
-	call Function16d6ae
-	farcall InitMG_Mobile_LinkTradePalMap
-	farcall PlaceTradePartnerNamesAndParty
-	hlcoord 10, 17
-	ld de, .CANCEL
-	call PlaceString
-	ret
-; 16d68f
-
-.CANCEL: ; 16d68f
-	db "CANCEL@"
-; 16d696
-
-_LoadTradeScreenBorder: ; 16d696
-	call __LoadTradeScreenBorder
-	ret
-; 16d69a
-
-
-LinkComms_LoadPleaseWaitTextboxBorderGFX: ; 16d69a
-	ld de, LinkCommsBorderGFX + $30 tiles
-	ld hl, vTiles2 tile $76
-	lb bc, BANK(LinkCommsBorderGFX), 8
-	call Get2bpp
-	ret
-; 16d6a7
-
-LoadTradeRoomBGPals_: ; 16d6a7
-	farcall LoadTradeRoomBGPals
-	ret
-; 16d6ae
-
-Function16d6ae: ; 16d6ae
-	call Function16d42e
-	ld hl, Tilemap_CableTradeBorderTop
-	decoord 0, 0
-	ld bc, 2 * SCREEN_WIDTH
-	call CopyBytes
-	ld hl, Tilemap_CableTradeBorderBottom
-	decoord 0, 16
-	ld bc, 2 * SCREEN_WIDTH
-	call CopyBytes
-	ret
-; 16d6ca
-
-LinkTextbox: ; 16d6ca
-	call _LinkTextbox
-	ret
-; 16d6ce
-
-Function16d6ce: ; 16d6ce
-	call LoadStandardMenuHeader
-	call Function16d6e1
-	farcall WaitLinkTransfer
-	call Call_ExitMenu
-	call WaitBGMap2
-	ret
-; 16d6e1
-
-Function16d6e1: ; 16d6e1
-	hlcoord 4, 10
-	ld b, 1
-	ld c, 10
-	predef LinkTextboxAtHL
-	hlcoord 5, 11
-	ld de, .Waiting
-	call PlaceString
-	call WaitBGMap
-	call WaitBGMap2
-	ld c, 50
-	jp DelayFrames
-; 16d701
-
-.Waiting: ; 16d701
-	db "WAITING..!@"
-; 16d70c
-
-LinkTradeMenu: ; 16d70c
-	call .MenuAction
-	call .GetJoypad
-	ret
-; 16d713
-
-.GetJoypad: ; 16d713
-	push bc
-	push af
-	ld a, [hJoyLast]
-	and D_PAD
-	ld b, a
-	ld a, [hJoyPressed]
-	and BUTTONS
-	or b
-	ld b, a
-	pop af
-	ld a, b
-	pop bc
-	ld d, a
-	ret
-; 16d725
-
-.MenuAction: ; 16d725
-	ld hl, w2DMenuFlags2
-	res 7, [hl]
-	ld a, [hBGMapMode]
-	push af
-	call .loop
-	pop af
-	ld [hBGMapMode], a
-	ret
-
-.loop
-	call .UpdateCursor
-	call .UpdateBGMapAndOAM
-	call .loop2
-	jr nc, .done
-	farcall _2DMenuInterpretJoypad
-	jr c, .done
-	ld a, [w2DMenuFlags1]
-	bit 7, a
-	jr nz, .done
-	call .GetJoypad
-	ld b, a
-	ld a, [wMenuJoypadFilter]
-	and b
-	jr z, .loop
-
-.done
-	ret
-; 16d759
-
-.UpdateBGMapAndOAM: ; 16d759
-	ld a, [hOAMUpdate]
-	push af
-	ld a, $1
-	ld [hOAMUpdate], a
-	call WaitBGMap
-	pop af
-	ld [hOAMUpdate], a
-	xor a
-	ld [hBGMapMode], a
-	ret
-
-.loop2
-	call RTC
-	call .TryAnims
-	ret c
-	ld a, [w2DMenuFlags1]
-	bit 7, a
-	jr z, .loop2
-	and a
-	ret
-; 16d77a
-
-.UpdateCursor: ; 16d77a
-	ld hl, wCursorCurrentTile
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [hl]
-	cp $1f
-	jr nz, .not_currently_selected
-	ld a, [wCursorOffCharacter]
-	ld [hl], a
-	push hl
-	push bc
-	ld bc, MON_NAME_LENGTH
-	add hl, bc
-	ld [hl], a
-	pop bc
-	pop hl
-
-.not_currently_selected
-	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, .skip
-.loop3
-	add c
-	dec b
-	jr nz, .loop3
-
-.skip
-	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, .skip2
-.loop4
-	add c
-	dec b
-	jr nz, .loop4
-
-.skip2
-	ld c, a
-	add hl, bc
-	ld a, [hl]
-	cp $1f
-	jr z, .cursor_already_there
-	ld [wCursorOffCharacter], a
-	ld [hl], $1f
-	push hl
-	push bc
-	ld bc, MON_NAME_LENGTH
-	add hl, bc
-	ld [hl], $1f
-	pop bc
-	pop hl
-.cursor_already_there
-	ld a, l
-	ld [wCursorCurrentTile], a
-	ld a, h
-	ld [wCursorCurrentTile + 1], a
-	ret
-; 16d7e7
-
-.TryAnims: ; 16d7e7
-	ld a, [w2DMenuFlags1]
-	bit 6, a
-	jr z, .skip_anims
-	farcall PlaySpriteAnimationsAndDelayFrame
-.skip_anims
-	call JoyTextDelay
-	call .GetJoypad
-	and a
-	ret z
-	scf
-	ret
-; 16d7fe
--- a/engine/load_font.asm
+++ /dev/null
@@ -1,156 +1,0 @@
-INCLUDE "gfx/font.asm"
-
-; This and the following two functions are unreferenced.
-; Debug, perhaps?
-Unreferenced_fb434:
-	db 0
-
-Unreferenced_Functionfb435: ; 4b435
-	ld a, [Unreferenced_fb434]
-	and a
-	jp nz, Get1bpp_2
-	jp Get1bpp
-; fb43f
-
-Unreferenced_Functionfb43f: ; fb43f
-	ld a, [Unreferenced_fb434]
-	and a
-	jp nz, Get2bpp_2
-	jp Get2bpp
-; End unreferenced block
-; fb449
-
-_LoadStandardFont:: ; fb449
-	ld de, Font
-	ld hl, vTiles1
-	lb bc, BANK(Font), 128 ; "A" to "9"
-	ld a, [rLCDC]
-	bit rLCDC_ENABLE, a
-	jp z, Copy1bpp
-
-	ld de, Font
-	ld hl, vTiles1
-	lb bc, BANK(Font), 32 ; "A" to "]"
-	call Get1bpp_2
-	ld de, Font + 32 * LEN_1BPP_TILE
-	ld hl, vTiles1 tile $20
-	lb bc, BANK(Font), 32 ; "a" to $bf
-	call Get1bpp_2
-	ld de, Font + 64 * LEN_1BPP_TILE
-	ld hl, vTiles1 tile $40
-	lb bc, BANK(Font), 32 ; "Ä" to "←"
-	call Get1bpp_2
-	ld de, Font + 96 * LEN_1BPP_TILE
-	ld hl, vTiles1 tile $60
-	lb bc, BANK(Font), 32 ; "'" to "9"
-	call Get1bpp_2
-	ret
-; fb48a
-
-_LoadFontsExtra1:: ; fb48a
-	ld de, FontsExtra_SolidBlackGFX
-	ld hl, vTiles2 tile "■" ; $60
-	lb bc, BANK(FontsExtra_SolidBlackGFX), 1
-	call Get1bpp_2
-	ld de, PokegearPhoneIconGFX
-	ld hl, vTiles2 tile "☎" ; $62
-	lb bc, BANK(PokegearPhoneIconGFX), 1
-	call Get2bpp_2
-	ld de, FontExtra + 3 tiles ; "<BOLD_D>"
-	ld hl, vTiles2 tile "<BOLD_D>"
-	lb bc, BANK(FontExtra), 22 ; "<BOLD_D>" to "ぉ"
-	call Get2bpp_2
-	jr LoadFrame
-; fb4b0
-
-_LoadFontsExtra2:: ; fb4b0
-	ld de, FontsExtra2_UpArrowGFX
-	ld hl, vTiles2 tile "▲" ; $61
-	ld b, BANK(FontsExtra2_UpArrowGFX)
-	ld c, 1
-	call Get2bpp_2
-	ret
-; fb4be
-
-_LoadFontsBattleExtra:: ; fb4be
-	ld de, FontBattleExtra
-	ld hl, vTiles2 tile $60
-	lb bc, BANK(FontBattleExtra), 25
-	call Get2bpp_2
-	jr LoadFrame
-; fb4cc
-
-LoadFrame: ; fb4cc
-	ld a, [wTextBoxFrame]
-	maskbits NUM_FRAMES
-	ld bc, 6 * LEN_1BPP_TILE
-	ld hl, Frames
-	call AddNTimes
-	ld d, h
-	ld e, l
-	ld hl, vTiles2 tile "┌" ; $79
-	lb bc, BANK(Frames), 6 ; "┌" to "┘"
-	call Get1bpp_2
-	ld hl, vTiles2 tile " " ; $7f
-	ld de, TextBoxSpaceGFX
-	lb bc, BANK(TextBoxSpaceGFX), 1
-	call Get1bpp_2
-	ret
-; fb4f2
-
-LoadBattleFontsHPBar: ; fb4f2
-	ld de, FontBattleExtra
-	ld hl, vTiles2 tile $60
-	lb bc, BANK(FontBattleExtra), 12
-	call Get2bpp_2
-	ld hl, vTiles2 tile $70
-	ld de, FontBattleExtra + 16 tiles ; "<DO>"
-	lb bc, BANK(FontBattleExtra), 3 ; "<DO>" to "『"
-	call Get2bpp_2
-	call LoadFrame
-
-LoadHPBar: ; fb50d
-	ld de, EnemyHPBarBorderGFX
-	ld hl, vTiles2 tile $6c
-	lb bc, BANK(EnemyHPBarBorderGFX), 4
-	call Get1bpp_2
-	ld de, HPExpBarBorderGFX
-	ld hl, vTiles2 tile $73
-	lb bc, BANK(HPExpBarBorderGFX), 6
-	call Get1bpp_2
-	ld de, ExpBarGFX
-	ld hl, vTiles2 tile $55
-	lb bc, BANK(ExpBarGFX), 9
-	call Get2bpp_2
-	ld de, MobilePhoneTilesGFX + 7 tiles ; mobile phone icon
-	ld hl, vTiles2 tile $5e
-	lb bc, BANK(MobilePhoneTilesGFX), 2
-	call Get2bpp_2
-	ret
-; fb53e
-
-StatsScreen_LoadFont: ; fb53e
-	call _LoadFontsBattleExtra
-	ld de, EnemyHPBarBorderGFX
-	ld hl, vTiles2 tile $6c
-	lb bc, BANK(EnemyHPBarBorderGFX), 4
-	call Get1bpp_2
-	ld de, HPExpBarBorderGFX
-	ld hl, vTiles2 tile $78
-	lb bc, BANK(HPExpBarBorderGFX), 1
-	call Get1bpp_2
-	ld de, HPExpBarBorderGFX + 3 * LEN_1BPP_TILE
-	ld hl, vTiles2 tile $76
-	lb bc, BANK(HPExpBarBorderGFX), 2
-	call Get1bpp_2
-	ld de, ExpBarGFX
-	ld hl, vTiles2 tile $55
-	lb bc, BANK(ExpBarGFX), 8
-	call Get2bpp_2
-LoadStatsScreenPageTilesGFX: ; fb571
-	ld de, StatsScreenPageTilesGFX
-	ld hl, vTiles2 tile $31
-	lb bc, BANK(StatsScreenPageTilesGFX), 17
-	call Get2bpp_2
-	ret
-; fb57e
--- a/engine/load_pics.asm
+++ /dev/null
@@ -1,491 +1,0 @@
-GetUnownLetter: ; 51040
-; Return Unown letter in wUnownLetter based on DVs at hl
-
-; Take the middle 2 bits of each DV and place them in order:
-;	atk  def  spd  spc
-;	.ww..xx.  .yy..zz.
-
-	; atk
-	ld a, [hl]
-	and %01100000
-	sla a
-	ld b, a
-	; def
-	ld a, [hli]
-	and %00000110
-	swap a
-	srl a
-	or b
-	ld b, a
-
-	; spd
-	ld a, [hl]
-	and %01100000
-	swap a
-	sla a
-	or b
-	ld b, a
-	; spc
-	ld a, [hl]
-	and %00000110
-	srl a
-	or b
-
-; Divide by 10 to get 0-25
-	ld [hDividend + 3], a
-	xor a
-	ld [hDividend], a
-	ld [hDividend + 1], a
-	ld [hDividend + 2], a
-	ld a, $ff / NUM_UNOWN + 1
-	ld [hDivisor], a
-	ld b, 4
-	call Divide
-
-; Increment to get 1-26
-	ld a, [hQuotient + 2]
-	inc a
-	ld [wUnownLetter], a
-	ret
-
-GetMonFrontpic: ; 51077
-	ld a, [wCurPartySpecies]
-	ld [wCurSpecies], a
-	call IsAPokemon
-	ret c
-	ld a, [rSVBK]
-	push af
-	call _GetFrontpic
-	pop af
-	ld [rSVBK], a
-	ret
-
-GetAnimatedFrontpic: ; 5108b
-	ld a, [wCurPartySpecies]
-	ld [wCurSpecies], a
-	call IsAPokemon
-	ret c
-	ld a, [rSVBK]
-	push af
-	xor a
-	ld [hBGMapMode], a
-	call _GetFrontpic
-	call GetAnimatedEnemyFrontpic
-	pop af
-	ld [rSVBK], a
-	ret
-
-_GetFrontpic: ; 510a5
-	push de
-	call GetBaseData
-	ld a, [wBasePicSize]
-	and $f
-	ld b, a
-	push bc
-	call GetFrontpicPointer
-	ld a, BANK(wDecompressEnemyFrontpic)
-	ld [rSVBK], a
-	ld a, b
-	ld de, wDecompressEnemyFrontpic
-	call FarDecompress
-	pop bc
-	ld hl, wDecompressScratch
-	ld de, wDecompressEnemyFrontpic
-	call PadFrontpic
-	pop hl
-	push hl
-	ld de, wDecompressScratch
-	ld c, 7 * 7
-	ld a, [hROMBank]
-	ld b, a
-	call Get2bpp
-	pop hl
-	ret
-
-GetFrontpicPointer: ; 510d7
-	ld a, [wCurPartySpecies]
-	cp UNOWN
-	jr z, .unown
-	ld a, [wCurPartySpecies]
-	ld d, BANK(PokemonPicPointers)
-	jr .ok
-
-.unown
-	ld a, [wUnownLetter]
-	ld d, BANK(UnownPicPointers)
-
-.ok
-	ld hl, PokemonPicPointers ; UnownPicPointers
-	dec a
-	ld bc, 6
-	call AddNTimes
-	ld a, d
-	call GetFarByte
-	call FixPicBank
-	push af
-	inc hl
-	ld a, d
-	call GetFarHalfword
-	pop bc
-	ret
-
-GetAnimatedEnemyFrontpic: ; 51103
-	ld a, BANK(vTiles3)
-	ld [rVBK], a
-	push hl
-	ld de, wDecompressScratch
-	ld c, 7 * 7
-	ld a, [hROMBank]
-	ld b, a
-	call Get2bpp
-	pop hl
-	ld de, 7 * 7 tiles
-	add hl, de
-	push hl
-	ld a, BANK(wBasePicSize)
-	ld hl, wBasePicSize
-	call GetFarWRAMByte
-	pop hl
-	and $f
-	ld de, wDecompressEnemyFrontpic + 5 * 5 tiles
-	ld c, 5 * 5
-	cp 5
-	jr z, .got_dims
-	ld de, wDecompressEnemyFrontpic + 6 * 6 tiles
-	ld c, 6 * 6
-	cp 6
-	jr z, .got_dims
-	ld de, wDecompressEnemyFrontpic + 7 * 7 tiles
-	ld c, 7 * 7
-.got_dims
-
-	push hl
-	push bc
-	call LoadFrontpicTiles
-	pop bc
-	pop hl
-	ld de, wDecompressScratch
-	ld a, [hROMBank]
-	ld b, a
-	call Get2bpp
-	xor a
-	ld [rVBK], a
-	ret
-
-LoadFrontpicTiles: ; 5114f
-	ld hl, wDecompressScratch
-	swap c
-	ld a, c
-	and $f
-	ld b, a
-	ld a, c
-	and $f0
-	ld c, a
-	push bc
-	call LoadOrientedFrontpic
-	pop bc
-.loop
-	push bc
-	ld c, 0
-	call LoadOrientedFrontpic
-	pop bc
-	dec b
-	jr nz, .loop
-	ret
-
-GetMonBackpic: ; 5116c
-	ld a, [wCurPartySpecies]
-	call IsAPokemon
-	ret c
-
-	ld a, [wCurPartySpecies]
-	ld b, a
-	ld a, [wUnownLetter]
-	ld c, a
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wDecompressScratch)
-	ld [rSVBK], a
-	push de
-
-	; These are assumed to be at the same address in their respective banks.
-	ld hl, PokemonPicPointers ; UnownPicPointers
-	ld a, b
-	ld d, BANK(PokemonPicPointers)
-	cp UNOWN
-	jr nz, .ok
-	ld a, c
-	ld d, BANK(UnownPicPointers)
-.ok
-	dec a
-	ld bc, 6
-	call AddNTimes
-	ld bc, 3
-	add hl, bc
-	ld a, d
-	call GetFarByte
-	call FixPicBank
-	push af
-	inc hl
-	ld a, d
-	call GetFarHalfword
-	ld de, wDecompressScratch
-	pop af
-	call FarDecompress
-	ld hl, wDecompressScratch
-	ld c, 6 * 6
-	call FixBackpicAlignment
-	pop hl
-	ld de, wDecompressScratch
-	ld a, [hROMBank]
-	ld b, a
-	call Get2bpp
-	pop af
-	ld [rSVBK], a
-	ret
-
-FixPicBank: ; 511c5
-; This is a thing for some reason.
-
-PICS_FIX EQU $36
-GLOBAL PICS_FIX
-
-	push hl
-	push bc
-	sub BANK(Pics_1) - PICS_FIX
-	ld c, a
-	ld b, 0
-	ld hl, .PicsBanks
-	add hl, bc
-	ld a, [hl]
-	pop bc
-	pop hl
-	ret
-
-.PicsBanks: ; 511d4
-	db BANK(Pics_1) + 0
-	db BANK(Pics_1) + 1
-	db BANK(Pics_1) + 2
-	db BANK(Pics_1) + 3
-	db BANK(Pics_1) + 4
-	db BANK(Pics_1) + 5
-	db BANK(Pics_1) + 6
-	db BANK(Pics_1) + 7
-	db BANK(Pics_1) + 8
-	db BANK(Pics_1) + 9
-	db BANK(Pics_1) + 10
-	db BANK(Pics_1) + 11
-	db BANK(Pics_1) + 12
-	db BANK(Pics_1) + 13
-	db BANK(Pics_1) + 14
-	db BANK(Pics_1) + 15
-	db BANK(Pics_1) + 16
-	db BANK(Pics_1) + 17
-	db BANK(Pics_1) + 18
-	db BANK(Pics_1) + 19
-	db BANK(Pics_1) + 20
-	db BANK(Pics_1) + 21
-	db BANK(Pics_1) + 22
-	db BANK(Pics_1) + 23
-
-Function511ec: ; 511ec
-	ld a, c
-	push de
-	ld hl, PokemonPicPointers
-	dec a
-	ld bc, 6
-	call AddNTimes
-	ld a, BANK(PokemonPicPointers)
-	call GetFarByte
-	call FixPicBank
-	push af
-	inc hl
-	ld a, BANK(PokemonPicPointers)
-	call GetFarHalfword
-	pop af
-	pop de
-	call FarDecompress
-	ret
-
-GetTrainerPic: ; 5120d
-	ld a, [wTrainerClass]
-	and a
-	ret z
-	cp NUM_TRAINER_CLASSES
-	ret nc
-	call WaitBGMap
-	xor a
-	ld [hBGMapMode], a
-	ld hl, TrainerPicPointers
-	ld a, [wTrainerClass]
-	dec a
-	ld bc, 3
-	call AddNTimes
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wDecompressScratch)
-	ld [rSVBK], a
-	push de
-	ld a, BANK(TrainerPicPointers)
-	call GetFarByte
-	call FixPicBank
-	push af
-	inc hl
-	ld a, BANK(TrainerPicPointers)
-	call GetFarHalfword
-	pop af
-	ld de, wDecompressScratch
-	call FarDecompress
-	pop hl
-	ld de, wDecompressScratch
-	ld c, 7 * 7
-	ld a, [hROMBank]
-	ld b, a
-	call Get2bpp
-	pop af
-	ld [rSVBK], a
-	call WaitBGMap
-	ld a, $1
-	ld [hBGMapMode], a
-	ret
-
-DecompressGet2bpp: ; 5125d
-; Decompress lz data from b:hl to scratch space at 6:d000, then copy it to address de.
-
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wDecompressScratch)
-	ld [rSVBK], a
-
-	push de
-	push bc
-	ld a, b
-	ld de, wDecompressScratch
-	call FarDecompress
-	pop bc
-	ld de, wDecompressScratch
-	pop hl
-	ld a, [hROMBank]
-	ld b, a
-	call Get2bpp
-
-	pop af
-	ld [rSVBK], a
-	ret
-
-FixBackpicAlignment: ; 5127c
-	push de
-	push bc
-	ld a, [wBoxAlignment]
-	and a
-	jr z, .keep_dims
-	ld a, c
-	cp 7 * 7
-	ld de, 7 * 7 tiles
-	jr z, .got_dims
-	cp 6 * 6
-	ld de, 6 * 6 tiles
-	jr z, .got_dims
-	ld de, 5 * 5 tiles
-
-.got_dims
-	ld a, [hl]
-	ld b, 0
-	ld c, 8
-.loop
-	rra
-	rl b
-	dec c
-	jr nz, .loop
-	ld a, b
-	ld [hli], a
-	dec de
-	ld a, e
-	or d
-	jr nz, .got_dims
-
-.keep_dims
-	pop bc
-	pop de
-	ret
-
-PadFrontpic: ; 512ab
-; pads frontpic to fill 7x7 box
-	ld a, b
-	cp 6
-	jr z, .six
-	cp 5
-	jr z, .five
-
-.seven_loop
-	ld c, $70
-	call LoadOrientedFrontpic
-	dec b
-	jr nz, .seven_loop
-	ret
-
-.six
-	ld c, $70
-	xor a
-	call .Fill
-.six_loop
-	ld c, $10
-	xor a
-	call .Fill
-	ld c, $60
-	call LoadOrientedFrontpic
-	dec b
-	jr nz, .six_loop
-	ret
-
-.five
-	ld c, $70
-	xor a
-	call .Fill
-.five_loop
-	ld c, $20
-	xor a
-	call .Fill
-	ld c, $50
-	call LoadOrientedFrontpic
-	dec b
-	jr nz, .five_loop
-	ld c, $70
-	xor a
-	call .Fill
-	ret
-
-.Fill:
-	ld [hli], a
-	dec c
-	jr nz, .Fill
-	ret
-
-LoadOrientedFrontpic: ; 512f2
-	ld a, [wBoxAlignment]
-	and a
-	jr nz, .x_flip
-.left_loop
-	ld a, [de]
-	inc de
-	ld [hli], a
-	dec c
-	jr nz, .left_loop
-	ret
-
-.x_flip
-	push bc
-.right_loop
-	ld a, [de]
-	inc de
-	ld b, a
-	xor a
-rept 8
-	rr b
-	rla
-endr
-	ld [hli], a
-	dec c
-	jr nz, .right_loop
-	pop bc
-	ret
--- a/engine/mail.asm
+++ /dev/null
@@ -1,587 +1,0 @@
-SendMailToPC: ; 4456e
-	ld a, MON_ITEM
-	call GetPartyParamLocation
-	ld d, [hl]
-	farcall ItemIsMail
-	jr nc, .full
-	call GetMailboxCount
-	cp MAILBOX_CAPACITY
-	jr nc, .full
-	ld bc, MAIL_STRUCT_LENGTH
-	ld hl, sMailbox
-	call AddNTimes
-	ld d, h
-	ld e, l
-	ld a, [wCurPartyMon]
-	ld bc, MAIL_STRUCT_LENGTH
-	ld hl, sPartyMail
-	call AddNTimes
-	push hl
-	ld a, BANK(sMailboxCount)
-	call GetSRAMBank
-	ld bc, MAIL_STRUCT_LENGTH
-	call CopyBytes
-	pop hl
-	xor a
-	ld bc, MAIL_STRUCT_LENGTH
-	call ByteFill
-	ld a, MON_ITEM
-	call GetPartyParamLocation
-	ld [hl], 0
-	ld hl, sMailboxCount
-	inc [hl]
-	call CloseSRAM
-	xor a
-	ret
-
-.full
-	scf
-	ret
-; 445c0
-
-DeleteMailFromPC: ; 445c0 (11:45c0)
-; Shift all mail messages in the mailbox
-	ld a, BANK(sMailboxCount)
-	call GetSRAMBank
-	ld a, b
-	push bc
-	ld hl, sMailbox
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	push hl
-	add hl, bc
-	pop de
-	pop bc
-.loop
-	ld a, b
-	cp MAILBOX_CAPACITY - 1
-	jr z, .done
-	push bc
-	ld bc, MAIL_STRUCT_LENGTH
-	call CopyBytes
-	pop bc
-	inc b
-	jr .loop
-.done
-	ld h, d
-	ld l, e
-	xor a
-	ld bc, MAIL_STRUCT_LENGTH
-	call ByteFill
-	ld hl, sMailboxCount
-	dec [hl]
-	jp CloseSRAM
-; 445f4 (11:45f4)
-
-ReadMailMessage: ; 445f4
-	ld a, b
-	ld hl, sMailbox
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	ld d, h
-	ld e, l
-	farcall ReadAnyMail
-	ret
-
-MoveMailFromPCToParty: ; 44607
-	ld a, BANK(sMailboxCount)
-	call GetSRAMBank
-	push bc
-	ld a, b
-	ld bc, MAIL_STRUCT_LENGTH
-	ld hl, sMailbox
-	call AddNTimes
-	push hl
-	ld a, [wCurPartyMon]
-	ld bc, MAIL_STRUCT_LENGTH
-	ld hl, sPartyMail
-	call AddNTimes
-	ld d, h
-	ld e, l
-	pop hl
-	push hl
-	ld bc, MAIL_STRUCT_LENGTH
-	call CopyBytes
-	pop hl
-	ld de, PARTYMON_STRUCT_LENGTH - MON_MOVES
-	add hl, de
-	ld d, [hl]
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1Item
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld [hl], d
-	call CloseSRAM
-	pop bc
-	jp DeleteMailFromPC
-; 44648 (11:4648)
-
-GetMailboxCount: ; 44648
-	ld a, BANK(sMailboxCount)
-	call GetSRAMBank
-	ld a, [sMailboxCount]
-	ld c, a
-	jp CloseSRAM
-; 44654
-
-CheckPokeItem:: ; 44654
-	push bc
-	push de
-	farcall SelectMonFromParty
-	ld a, POKEMAIL_REFUSED
-	jr c, .pop_return
-
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1Item
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld d, [hl]
-	farcall ItemIsMail
-	ld a, POKEMAIL_NO_MAIL
-	jr nc, .pop_return
-
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	ld a, [wCurPartyMon]
-	ld hl, sPartyMail
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	ld d, h
-	ld e, l
-	pop hl
-	pop bc
-
-; Compare the mail message, byte for byte, with the expected message.
-	ld a, MAIL_MSG_LENGTH
-	ld [wd265], a
-.loop
-	ld a, [de]
-	ld c, a
-	ld a, b
-	call GetFarByte
-	cp "@"
-	jr z, .done
-	cp c
-	ld a, POKEMAIL_WRONG_MAIL
-	jr nz, .close_sram_return
-	inc hl
-	inc de
-	ld a, [wd265]
-	dec a
-	ld [wd265], a
-	jr nz, .loop
-
-.done
-	farcall CheckCurPartyMonFainted
-	ld a, POKEMAIL_LAST_MON
-	jr c, .close_sram_return
-	xor a ; REMOVE_PARTY
-	ld [wPokemonWithdrawDepositParameter], a
-	farcall RemoveMonFromPartyOrBox
-	ld a, POKEMAIL_CORRECT
-
-.close_sram_return
-	call CloseSRAM
-	jr .return
-
-.pop_return
-	pop de
-	pop bc
-
-.return
-	ld [wScriptVar], a
-	ret
-; 446cc
-
-
-GivePokeItem:: ; 446cc
-	ld a, [wPartyCount]
-	dec a
-	push af
-	push bc
-	ld hl, wPartyMon1Item
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	pop bc
-	ld [hl], b
-	pop af
-	push bc
-	push af
-	ld hl, sPartyMail
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	ld d, h
-	ld e, l
-	ld hl, wd002
-	ld bc, MAIL_MSG_LENGTH + 1
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	call CopyBytes
-	pop af
-	push af
-	ld hl, wPartyMonOT
-	ld bc, NAME_LENGTH
-	call AddNTimes
-	ld bc, NAME_LENGTH - 1
-	call CopyBytes
-	pop af
-	ld hl, wPartyMon1ID
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-	inc de
-	ld a, [wCurPartySpecies]
-	ld [de], a
-	inc de
-	pop bc
-	ld a, b
-	ld [de], a
-	jp CloseSRAM
-; 44725
-
-
-BackupPartyMonMail: ; 44725
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	ld hl, sPartyMail
-	ld de, sPartyMailBackup
-	ld bc, 6 * MAIL_STRUCT_LENGTH
-	call CopyBytes
-	ld hl, sMailboxCount
-	ld de, sMailboxCountBackup
-	ld bc, 1 + 10 * MAIL_STRUCT_LENGTH
-	call CopyBytes
-	jp CloseSRAM
-; 44745
-
-RestorePartyMonMail: ; 44745 (11:4745)
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	ld hl, sPartyMailBackup
-	ld de, sPartyMail
-	ld bc, 6 * MAIL_STRUCT_LENGTH
-	call CopyBytes
-	ld hl, sMailboxCountBackup
-	ld de, sMailboxCount
-	ld bc, 1 + 10 * MAIL_STRUCT_LENGTH
-	call CopyBytes
-	jp CloseSRAM
-
-DeletePartyMonMail: ; 44765 (11:4765)
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	xor a
-	ld hl, sPartyMail
-	ld bc, 6 * MAIL_STRUCT_LENGTH
-	call ByteFill
-	xor a
-	ld hl, sMailboxCount
-	ld bc, 1 + 10 * MAIL_STRUCT_LENGTH
-	call ByteFill
-	jp CloseSRAM
-; 44781 (11:4781)
-
-
-IsAnyMonHoldingMail: ; 44781
-	ld a, [wPartyCount]
-	and a
-	jr z, .no_mons
-	ld e, a
-	ld hl, wPartyMon1Item
-.loop
-	ld d, [hl]
-	push hl
-	push de
-	farcall ItemIsMail
-	pop de
-	pop hl
-	ret c
-	ld bc, PARTYMON_STRUCT_LENGTH
-	add hl, bc
-	dec e
-	jr nz, .loop
-
-.no_mons
-	and a
-	ret
-; 447a0
-
-_PlayerMailBoxMenu: ; 0x447a0
-	call InitMail
-	jr z, .nomail
-	call LoadStandardMenuHeader
-	call MailboxPC
-	jp CloseWindow
-
-.nomail
-	ld hl, .EmptyMailboxText
-	jp MenuTextBoxBackup
-; 0x447b4
-
-.EmptyMailboxText: ; 0x447b4
-	text_jump _EmptyMailboxText
-	db "@"
-
-InitMail: ; 0x447b9
-; initialize wMailboxCount and beyond with incrementing values, one per mail
-; set z if no mail
-	ld a, BANK(sMailboxCount)
-	call GetSRAMBank
-	ld a, [sMailboxCount]
-	call CloseSRAM
-	ld hl, wMailboxCount
-	ld [hli], a
-	and a
-
-	jr z, .done ; if no mail, we're done
-
-	; load values in memory with incrementing values starting at wMailboxCount
-	ld b, a
-	ld a, 1
-.loop
-	ld [hli], a
-	inc a
-	dec b
-	jr nz, .loop
-.done
-	ld [hl], -1 ; terminate
-
-	ld a, [wMailboxCount]
-	and a
-	ret
-; 0x447da
-
-MailboxPC_GetMailAuthor: ; 0x447da
-	dec a
-	ld hl, sMailbox1Author
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	ld a, BANK(sMailboxCount)
-	call GetSRAMBank
-	ld de, wStringBuffer2
-	push de
-	ld bc, NAME_LENGTH - 1
-	call CopyBytes
-	ld a, "@"
-	ld [de], a
-	call CloseSRAM
-	pop de
-	ret
-; 0x447fb
-
-MailboxPC_PrintMailAuthor: ; 0x447fb
-	push de
-	ld a, [wMenuSelection]
-	call MailboxPC_GetMailAuthor
-	pop hl
-	jp PlaceString
-; 0x44806
-
-MailboxPC: ; 0x44806
-	xor a
-	ld [wCurMessageScrollPosition], a
-	ld a, 1
-	ld [wCurMessageIndex], a
-.loop
-	call InitMail
-	ld hl, .TopMenuHeader
-	call CopyMenuHeader
-	xor a
-	ld [hBGMapMode], a
-	call InitScrollingMenu
-	call UpdateSprites
-
-	ld a, [wCurMessageIndex]
-	ld [wMenuCursorBuffer], a
-	ld a, [wCurMessageScrollPosition]
-	ld [wMenuScrollPosition], a
-	call ScrollingMenu
-	ld a, [wMenuScrollPosition]
-	ld [wCurMessageScrollPosition], a
-	ld a, [wMenuCursorY]
-	ld [wCurMessageIndex], a
-
-	ld a, [wMenuJoypad]
-	cp B_BUTTON
-	jr z, .exit
-	call .Submenu
-	jr .loop
-
-.exit
-	xor a
-	ret
-; 0x4484a
-
-.Submenu: ; 0x4484a
-	ld hl, .SubMenuHeader
-	call LoadMenuHeader
-	call VerticalMenu
-	call ExitMenu
-	jr c, .subexit
-	ld a, [wMenuCursorY]
-	dec a
-	ld hl, .JumpTable
-	rst JumpTable
-
-.subexit
-	ret
-; 0x44861
-
-.JumpTable:
-	dw .ReadMail
-	dw .PutInPack
-	dw .AttachMail
-	dw .Cancel
-
-.ReadMail: ; 0x44869
-	call FadeToMenu
-	ld a, [wMenuSelection]
-	dec a
-	ld b, a
-	call ReadMailMessage
-	jp CloseSubmenu
-; 0x44877
-
-.PutInPack: ; 0x44877
-	ld hl, .MessageLostText
-	call MenuTextBox
-	call YesNoBox
-	call ExitMenu
-	ret c
-	ld a, [wMenuSelection]
-	dec a
-	call .GetMailType
-	ld a, 1
-	ld [wItemQuantityChangeBuffer], a
-	ld hl, wNumItems
-	call ReceiveItem
-	jr c, .put_in_bag
-	ld hl, .PackFullText
-	jp MenuTextBoxBackup
-
-.put_in_bag
-	ld a, [wMenuSelection]
-	dec a
-	ld b, a
-	call DeleteMailFromPC
-	ld hl, .PutAwayText
-	jp MenuTextBoxBackup
-; 0x448ac
-
-.PutAwayText: ; 0x448ac
-	text_jump ClearedMailPutAwayText
-	db "@"
-
-.PackFullText: ; 0x448b1
-	text_jump MailPackFullText
-	db "@"
-
-.MessageLostText: ; 0x448b6
-	text_jump MailMessageLostText
-	db "@"
-
-.GetMailType: ; 0x448bb
-	push af
-	ld a, BANK(sMailboxCount)
-	call GetSRAMBank
-	pop af
-	ld hl, sMailbox1Type
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [hl]
-	ld [wCurItem], a
-	jp CloseSRAM
-; 0x448d2
-
-.AttachMail: ; 0x448d2
-	call FadeToMenu
-	xor a
-	ld [wPartyMenuActionText], a
-	call ClearBGPalettes
-.try_again
-	farcall LoadPartyMenuGFX
-	farcall InitPartyMenuWithCancel
-	farcall InitPartyMenuGFX
-	farcall WritePartyMenuTilemap
-	farcall PrintPartyMenuText
-	call WaitBGMap
-	call SetPalettes
-	call DelayFrame
-	farcall PartyMenuSelect
-	jr c, .exit2
-	ld a, [wCurPartySpecies]
-	cp EGG
-	jr z, .egg
-	ld a, MON_ITEM
-	call GetPartyParamLocation
-	ld a, [hl]
-	and a
-	jr z, .attach_mail
-	ld hl, .HoldingMailText
-	call PrintText
-	jr .try_again
-
-.egg
-	ld hl, .EggText
-	call PrintText
-	jr .try_again
-
-.attach_mail
-	ld a, [wMenuSelection]
-	dec a
-	ld b, a
-	call MoveMailFromPCToParty
-	ld hl, .MailMovedText
-	call PrintText
-
-.exit2
-	jp CloseSubmenu
-; 0x4493c
-
-.HoldingMailText: ; 0x4493c
-	text_jump MailAlreadyHoldingItemText
-	db "@"
-
-.EggText: ; 0x44941
-	text_jump MailEggText
-	db "@"
-
-.MailMovedText: ; 0x44946
-	text_jump MailMovedFromBoxText
-	db "@"
-
-.Cancel:
-	ret
-
-.TopMenuHeader: ; 0x4494c
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 8, 1, SCREEN_WIDTH - 2, 10
-	dw .TopMenuData
-	db 1 ; default option
-
-.TopMenuData:
-	db SCROLLINGMENU_DISPLAY_ARROWS ; flags
-	db 4, 0 ; rows/columns?
-	db 1 ; horizontal spacing?
-	dbw 0, wMailboxCount ; text pointer
-	dba MailboxPC_PrintMailAuthor
-	dba NULL
-	dba NULL
-
-.SubMenuHeader: ; 0x44964
-	db MENU_BACKUP_TILES ; flags
-	menu_coords 0, 0, 13, 9
-	dw .SubMenuData
-	db 1 ; default option
-
-.SubMenuData:
-	db STATICMENU_CURSOR ; flags
-	db 4 ; items
-	db "READ MAIL@"
-	db "PUT IN PACK@"
-	db "ATTACH MAIL@"
-	db "CANCEL@"
--- a/engine/mail_2.asm
+++ /dev/null
@@ -1,949 +1,0 @@
-ReadPartyMonMail: ; b9229
-	ld a, [wCurPartyMon]
-	ld hl, sPartyMail
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	ld d, h
-	ld e, l
-ReadAnyMail: ; b9237
-	push de
-	call ClearBGPalettes
-	call ClearSprites
-	call ClearTileMap
-	call DisableLCD
-	call LoadFontsExtra
-	pop de
-	push de
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	farcall IsMailEuropean
-	call CloseSRAM
-	ld a, c
-	ld de, StandardEnglishFont
-	or a
-	jr z, .got_font
-	ld de, FrenchGermanFont
-	sub $3
-	jr c, .got_font
-	ld de, SpanishItalianFont
-
-.got_font
-	ld hl, vTiles1
-	lb bc, BANK(StandardEnglishFont), $80
-	call Get1bpp
-	pop de
-	call .LoadGFX
-	call EnableLCD
-	call WaitBGMap
-	ld a, [wBuffer3]
-	ld e, a
-	farcall LoadMailPalettes
-	call SetPalettes
-	xor a
-	ld [hJoyPressed], a
-	call .loop
-	call ClearBGPalettes
-	call DisableLCD
-	call LoadStandardFont
-	jp EnableLCD
-
-.loop
-	call GetJoypad
-	ld a, [hJoyPressed]
-	and A_BUTTON | B_BUTTON | START
-	jr z, .loop
-	and START
-	jr nz, .pressed_start
-	ret
-
-.pressed_start
-	ld a, [wJumptableIndex]
-	push af
-	callfar PrintMail ; printer
-	pop af
-	ld [wJumptableIndex], a
-	jr .loop
-; b92b8
-
-.LoadGFX: ; b92b8
-	ld h, d
-	ld l, e
-	push hl
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	ld de, sPartyMon1MailAuthorID - sPartyMon1Mail
-	add hl, de
-	ld a, [hli]
-	ld [wBuffer1], a
-	ld a, [hli]
-	ld [wBuffer2], a
-	ld a, [hli]
-	ld [wCurPartySpecies], a
-	ld b, [hl]
-	call CloseSRAM
-	ld hl, MailGFXPointers
-	ld c, 0
-.loop2
-	ld a, [hli]
-	cp b
-	jr z, .got_pointer
-	cp -1
-	jr z, .invalid
-	inc c
-	inc hl
-	inc hl
-	jr .loop2
-
-.invalid
-	ld hl, MailGFXPointers
-	inc hl
-
-.got_pointer
-	ld a, c
-	ld [wBuffer3], a
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, .done
-	pop bc
-	push de
-	jp hl
-.done
-	ret
-; b92f8
-
-MailGFXPointers: ; b92f8
-	dbw FLOWER_MAIL,  LoadFlowerMailGFX
-	dbw SURF_MAIL,    LoadSurfMailGFX
-	dbw LITEBLUEMAIL, LoadLiteBlueMailGFX
-	dbw PORTRAITMAIL, LoadPortraitMailGFX
-	dbw LOVELY_MAIL,  LoadLovelyMailGFX
-	dbw EON_MAIL,     LoadEonMailGFX
-	dbw MORPH_MAIL,   LoadMorphMailGFX
-	dbw BLUESKY_MAIL, LoadBlueSkyMailGFX
-	dbw MUSIC_MAIL,   LoadMusicMailGFX
-	dbw MIRAGE_MAIL,  LoadMirageMailGFX
-	db -1
-; b9317
-
-LoadSurfMailGFX: ; b9317
-	push bc
-	ld hl, vTiles2 tile $31
-	ld de, SurfMailBorderGFX
-	ld c, 8 * 8
-	call LoadMailGFX_Color2
-	ld de, MailLaprasGFX
-	ld c, 6 * 8
-	call LoadMailGFX_Color3
-	ld de, SurfMailWaveGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	jr FinishLoadingSurfLiteBlueMailGFX
-
-LoadLiteBlueMailGFX: ; b9335
-	push bc
-	ld hl, vTiles2 tile $31
-	ld de, LiteBlueMailBorderGFX
-	ld c, 8 * 8
-	call LoadMailGFX_Color2
-	ld de, MailDratiniGFX
-	ld c, 6 * 8
-	call LoadMailGFX_Color3
-	ld de, PortraitMailUnderlineGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-
-FinishLoadingSurfLiteBlueMailGFX: ; b9351
-	ld de, SurfLiteBlueMailSmallShapesGFX
-	ld c, 2 * 8
-	call LoadMailGFX_Color2
-	ld c, 2 * 8
-	call LoadMailGFX_Color1
-	ld de, SurfLiteBlueMailLargeShapesGFX
-	ld c, 8 * 8
-	call LoadMailGFX_Color1
-	ld c, 8 * 8
-	call LoadMailGFX_Color2
-
-	call DrawMailBorder
-	hlcoord 2, 15
-	ld a, $3f
-	call Mail_Draw16TileRow
-	ld a, $39
-	hlcoord 15, 14
-	call Mail_Draw3x2Graphic
-	ld a, $44
-	hlcoord 2, 2
-	call Mail_Draw2x2Graphic
-	hlcoord 15, 11
-	call Mail_Draw2x2Graphic
-	ld a, $4c
-	hlcoord 3, 12
-	call Mail_Draw2x2Graphic
-	hlcoord 15, 2
-	call Mail_Draw2x2Graphic
-	ld a, $50
-	hlcoord 6, 3
-	call Mail_Draw2x2Graphic
-	ld a, $40
-	hlcoord 13, 2
-	ld [hli], a
-	hlcoord 6, 14
-	ld [hl], a
-	ld a, $41
-	hlcoord 4, 5
-	ld [hli], a
-	hlcoord 17, 5
-	ld [hli], a
-	hlcoord 13, 12
-	ld [hl], a
-	ld a, $42
-	hlcoord 9, 2
-	ld [hli], a
-	hlcoord 14, 5
-	ld [hli], a
-	hlcoord 3, 10
-	ld [hl], a
-	ld a, $43
-	hlcoord 6, 11
-	ld [hli], a
-	pop hl
-	jp MailGFX_PlaceMessage
-; b93d2
-
-LoadEonMailGFX: ; b93d2
-	push bc
-	ld hl, vTiles2 tile $31
-	ld de, EonMailBorder1GFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	ld de, EonMailBorder2GFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color1
-	ld de, EonMailBorder2GFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color1
-	ld de, EonMailBorder1GFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	ld de, SurfMailBorderGFX + 6 * 8
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	ld de, MailEeveeGFX
-	ld c, 6 * 8
-	call LoadMailGFX_Color3
-	ld hl, vTiles2 tile $3d
-	ld de, MailLargeCircleGFX
-	ld c, 4 * 8
-	call LoadMailGFX_Color1
-	ld de, EonMailBorder2GFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-
-	ld a, $31
-	hlcoord 0, 0
-	call Mail_Place18TileAlternatingRow
-	hlcoord 1, 17
-	call Mail_Place18TileAlternatingRow
-	ld a, $33
-	hlcoord 0, 1
-	call Mail_Place16TileAlternatingColumn
-	hlcoord 19, 0
-	call Mail_Place16TileAlternatingColumn
-	hlcoord 2, 15
-	ld a, $35
-	call Mail_Draw16TileRow
-	inc a
-	hlcoord 15, 14
-	call Mail_Draw3x2Graphic
-	call LovelyEonMail_PlaceIcons
-	pop hl
-	jp MailGFX_PlaceMessage
-; b944b
-
-LoadLovelyMailGFX: ; b944b
-	push bc
-	ld hl, vTiles2 tile $31
-	ld de, LovelyMailBorderGFX
-	ld c, 5 * 8
-	call LoadMailGFX_Color2
-	ld de, MailPoliwagGFX
-	ld c, 6 * 8
-	call LoadMailGFX_Color3
-	ld de, LovelyMailUnderlineGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	ld de, LovelyMailLargeHeartGFX
-	ld c, 4 * 8
-	call LoadMailGFX_Color2
-	ld de, LovelyMailSmallHeartGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color1
-
-	call DrawMailBorder2
-	hlcoord 2, 15
-	ld a, $3c
-	call Mail_Draw16TileRow
-	ld a, $36
-	hlcoord 15, 14
-	call Mail_Draw3x2Graphic
-	call LovelyEonMail_PlaceIcons
-	pop hl
-	jp MailGFX_PlaceMessage
-; b9491
-
-LovelyEonMail_PlaceIcons: ; b9491
-	ld a, $3d
-	hlcoord 2, 2
-	call Mail_Draw2x2Graphic
-	hlcoord 16, 2
-	call Mail_Draw2x2Graphic
-	hlcoord 9, 4
-	call Mail_Draw2x2Graphic
-	hlcoord 2, 11
-	call Mail_Draw2x2Graphic
-	hlcoord 6, 12
-	call Mail_Draw2x2Graphic
-	hlcoord 12, 11
-	call Mail_Draw2x2Graphic
-	ld a, $41
-	hlcoord 5, 4
-	ld [hl], a
-	hlcoord 6, 2
-	ld [hl], a
-	hlcoord 12, 4
-	ld [hl], a
-	hlcoord 14, 2
-	ld [hl], a
-	hlcoord 3, 13
-	ld [hl], a
-	hlcoord 9, 11
-	ld [hl], a
-	hlcoord 16, 12
-	ld [hl], a
-	ret
-; b94d6
-
-LoadMorphMailGFX: ; b94d6
-	push bc
-	ld hl, vTiles2 tile $31
-	ld bc, 5 * 8
-	call MailGFX_GenerateMonochromeTilesColor2
-	ld de, MorphMailBorderCornerGFX + 3 * 8
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	ld de, MorphMailBorderCornerGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	ld de, MorphMailBorderGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	ld de, EonMailBorder1GFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color1
-	ld de, MorphMailDividerGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	ld de, MailDittoGFX
-	ld c, 6 * 8
-	call LoadMailGFX_Color3
-	call DrawMailBorder2
-	ld a, $31
-	hlcoord 1, 1
-	call Mail_Draw2x2Graphic
-	hlcoord 17, 15
-	call Mail_Draw2x2Graphic
-	hlcoord 1, 3
-	ld [hl], a
-	hlcoord 3, 1
-	ld [hl], a
-	hlcoord 16, 16
-	ld [hl], a
-	hlcoord 18, 14
-	ld [hl], a
-	ld a, $36
-	hlcoord 1, 4
-	ld [hl], a
-	hlcoord 2, 3
-	ld [hl], a
-	hlcoord 3, 2
-	ld [hl], a
-	hlcoord 4, 1
-	ld [hl], a
-	inc a
-	hlcoord 15, 16
-	ld [hl], a
-	hlcoord 16, 15
-	ld [hl], a
-	hlcoord 17, 14
-	ld [hl], a
-	hlcoord 18, 13
-	ld [hl], a
-	inc a
-	hlcoord 2, 15
-	ld b, $e
-	call Mail_DrawRowLoop
-	inc a
-	hlcoord 2, 11
-	call Mail_Draw16TileRow
-	hlcoord 2, 5
-	call Mail_Draw16TileRow
-	inc a
-	hlcoord 6, 1
-	call Mail_Draw13TileRow
-	hlcoord 1, 16
-	call Mail_Draw13TileRow
-	inc a
-	hlcoord 3, 13
-	call Mail_Draw3x2Graphic
-	pop hl
-	jp MailGFX_PlaceMessage
-; b9582
-
-LoadBlueSkyMailGFX: ; b9582
-	push bc
-	ld hl, vTiles2 tile $31
-	ld de, EonMailBorder1GFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	ld a, $ff
-	ld bc, 1 tiles
-	call ByteFill
-	ld de, BlueSkyMailGrassGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color3
-	ld de, MailDragoniteGFX
-	ld c, 23 * 8
-	call LoadMailGFX_Color3
-	ld de, MailCloudGFX
-	ld c, 6 * 8
-	call LoadMailGFX_Color1
-	ld de, FlowerMailBorderGFX + 6 * 8
-	ld c, 1 * 8
-	call LoadMailGFX_Color1
-	ld de, MailCloudGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color1
-	ld de, MailCloudGFX + 2 * 8
-	ld c, 2 * 8
-	call LoadMailGFX_Color1
-	ld de, MailCloudGFX + 5 * 8
-	ld c, 1 * 8
-	call LoadMailGFX_Color1
-
-	ld a, $31
-	hlcoord 0, 0
-	call Mail_DrawFullWidthBorder
-	hlcoord 0, 1
-	call Mail_DrawLeftRightBorder
-	hlcoord 19, 1
-	call Mail_DrawLeftRightBorder
-	inc a
-	hlcoord 0, 17
-	call Mail_DrawFullWidthBorder
-	inc a
-	hlcoord 0, 16
-	call Mail_DrawFullWidthBorder
-	inc a
-	hlcoord 2, 2
-	call Mail_Place6TileRow
-	hlcoord 3, 3
-	call Mail_Place6TileRow
-	hlcoord 4, 4
-	call Mail_Place6TileRow
-	dec hl
-	ld [hl], $7f
-	dec a
-	hlcoord 15, 14
-	call Mail_Draw2x2Graphic
-	add $4
-	hlcoord 15, 16
-	ld [hli], a
-	inc a
-	ld [hl], a
-	inc a
-	push af
-	hlcoord 12, 1
-	call Mail_Draw3x2Graphic
-	pop af
-	hlcoord 15, 4
-	call Mail_Draw3x2Graphic
-	inc a
-	hlcoord 2, 11
-	call Mail_Draw16TileRow
-	inc a
-	hlcoord 10, 3
-	call Mail_Draw2x2Graphic
-	pop hl
-	jp MailGFX_PlaceMessage
-; b9636
-
-Mail_Place6TileRow: ; b9636
-	ld b, $6
-.loop
-	ld [hli], a
-	inc a
-	dec b
-	jr nz, .loop
-	ret
-; b963e
-
-LoadFlowerMailGFX: ; b963e
-	push bc
-	ld hl, vTiles2 tile $31
-	ld de, FlowerMailBorderGFX
-	ld c, 8 * 8
-	call LoadMailGFX_Color1
-	ld de, MailOddishGFX
-	ld c, 4 * 8
-	call LoadMailGFX_Color3
-	ld de, FlowerMailBorderGFX + 6 * 8
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	ld de, FlowerMailFlowerGFX
-	ld c, 4 * 8
-	call LoadMailGFX_Color1
-	ld c, 4 * 8
-	call LoadMailGFX_Color2
-
-	call DrawMailBorder
-	hlcoord 2, 15
-	ld a, $3d ; underline
-	call Mail_Draw16TileRow
-	ld a, $39 ; oddish
-	hlcoord 16, 13
-	call Mail_Draw2x2Graphic
-	hlcoord 2, 13
-	call Mail_Draw2x2Graphic
-	ld a, $3e
-	hlcoord 2, 2
-	call Mail_Draw2x2Graphic
-	hlcoord 5, 3
-	call Mail_Draw2x2Graphic
-	hlcoord 10, 2
-	call Mail_Draw2x2Graphic
-	hlcoord 16, 3
-	call Mail_Draw2x2Graphic
-	hlcoord 5, 11
-	call Mail_Draw2x2Graphic
-	hlcoord 16, 10
-	call Mail_Draw2x2Graphic
-	ld a, $42
-	hlcoord 3, 4
-	call Mail_Draw2x2Graphic
-	hlcoord 12, 3
-	call Mail_Draw2x2Graphic
-	hlcoord 14, 2
-	call Mail_Draw2x2Graphic
-	hlcoord 2, 10
-	call Mail_Draw2x2Graphic
-	hlcoord 14, 11
-	call Mail_Draw2x2Graphic
-	pop hl
-	jp MailGFX_PlaceMessage
-; b96ca
-
-LoadPortraitMailGFX: ; b96ca
-	push bc
-	ld hl, vTiles2 tile $31
-	ld de, PortraitMailBorderGFX
-	ld c, 5 * 8
-	call LoadMailGFX_Color2
-	ld de, PortraitMailUnderlineGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	ld hl, vTiles2 tile $3d
-	ld de, PortraitMailLargePokeballGFX
-	ld c, 4 * 8
-	call LoadMailGFX_Color1
-	ld de, PortraitMailSmallPokeballGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-
-	call DrawMailBorder2
-	hlcoord 8, 15
-	ld a, $36
-	ld b, $a
-	call Mail_DrawRowLoop
-	call LovelyEonMail_PlaceIcons
-	ld a, $1
-	ld [wUnownLetter], a
-	hlcoord 1, 10
-	call PrepMonFrontpic
-	pop hl
-	jp MailGFX_PlaceMessage
-; b9710
-
-LoadMusicMailGFX: ; b9710
-	push bc
-	ld hl, vTiles2 tile $31
-	ld de, MusicMailBorderGFX
-	ld c, 4 * 8
-	call LoadMailGFX_Color2
-	ld de, MorphMailBorderGFX
-	ld c, 2 * 8
-	call LoadMailGFX_Color2
-	ld de, MailNatuGFX
-	ld c, 6 * 8
-	call LoadMailGFX_Color3
-	xor a
-	ld bc, 1 tiles
-	call ByteFill
-	ld de, MusicMailLargeNoteGFX
-	ld c, 3 * 8
-	call LoadMailGFX_Color1
-	ld de, MusicMailSmallNoteGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color1
-
-	ld a, $31
-	hlcoord 0, 0
-	call Mail_Place18TileAlternatingRow
-	hlcoord 1, 17
-	call Mail_Place18TileAlternatingRow
-	ld a, $33
-	hlcoord 0, 1
-	call Mail_Place16TileAlternatingColumn
-	hlcoord 19, 0
-	call Mail_Place16TileAlternatingColumn
-	ld a, $35
-	hlcoord 2, 15
-	call Mail_Place14TileAlternatingRow
-	ld a, $37
-	hlcoord 15, 14
-	call Mail_Draw3x2Graphic
-	call LovelyEonMail_PlaceIcons
-	pop hl
-	jp MailGFX_PlaceMessage
-; b9776
-
-LoadMirageMailGFX: ; b9776
-	push bc
-	ld hl, vTiles2 tile $31
-	ld bc, 5 * 8
-	call MailGFX_GenerateMonochromeTilesColor2
-	ld de, BlueSkyMailGrassGFX
-	ld c, 1 * 8
-	call LoadMailGFX_Color2
-	ld de, MailMewGFX
-	ld c, 18 * 8
-	call LoadMailGFX_Color2
-	ld de, LiteBlueMailBorderGFX + 1 * 8
-	ld c, 1 * 8
-	call LoadMailGFX_Color1
-	ld de, LiteBlueMailBorderGFX + 6 * 8
-	ld c, 1 * 8
-	call LoadMailGFX_Color1
-
-	call DrawMailBorder2
-	ld a, $36
-	hlcoord 1, 16
-	call Mail_DrawTopBottomBorder
-	inc a
-	hlcoord 15, 14
-	call Mail_Draw3x2Graphic
-	inc a
-	hlcoord 15, 16
-	ld [hli], a
-	inc a
-	ld [hl], a
-	ld a, $3f
-	hlcoord 1, 1
-	call Mail_Place18TileAlternatingRow
-	ld a, $41
-	hlcoord 0, 2
-	call Mail_Place14TileAlternatingColumn
-	ld a, $43
-	hlcoord 19, 2
-	call Mail_Place14TileAlternatingColumn
-	ld a, $45
-	hlcoord 0, 1
-	ld [hl], a
-	inc a
-	hlcoord 19, 1
-	ld [hl], a
-	inc a
-	hlcoord 0, 16
-	ld [hl], a
-	inc a
-	hlcoord 19, 16
-	ld [hl], a
-	inc a
-	hlcoord 2, 5
-	call Mail_Draw16TileRow
-	inc a
-	hlcoord 2, 11
-	call Mail_Draw16TileRow
-	pop hl
-	jp MailGFX_PlaceMessage
-; b97f8
-
-MailGFX_GenerateMonochromeTilesColor2: ; b97f8
-.loop
-	xor a
-	ld [hli], a
-	ld a, $ff
-	ld [hli], a
-	dec bc
-	ld a, b
-	or c
-	jr nz, .loop
-	ret
-; b9803
-
-MailGFX_PlaceMessage: ; b9803
-	ld bc, MAIL_STRUCT_LENGTH
-	ld de, wTempMail
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	call CopyBytes
-	call CloseSRAM
-	ld hl, wTempMailAuthor
-	ld de, wMonOrItemNameBuffer
-	ld bc, NAME_LENGTH - 1
-	call CopyBytes
-	ld a, "@"
-	ld [wTempMailAuthor], a
-	ld [wMonOrItemNameBuffer + NAME_LENGTH - 1], a
-	ld de, wTempMailMessage
-	hlcoord 2, 7
-	call PlaceString
-	ld de, wMonOrItemNameBuffer
-	ld a, [de]
-	and a
-	ret z
-	ld a, [wBuffer3]
-	hlcoord 8, 14
-	cp $3 ; PORTRAITMAIL
-	jr z, .place_author
-	hlcoord 6, 14
-	cp $6 ; MORPH_MAIL
-	jr z, .place_author
-	hlcoord 5, 14
-
-.place_author
-	jp PlaceString
-; b984e
-
-Unreferenced_Functionb984e: ; b984e
-.loop
-	ld a, [hl]
-	xor $ff
-	ld [hli], a
-	dec bc
-	ld a, b
-	or c
-	jr nz, .loop
-	ret
-; b9858
-
-DrawMailBorder: ; b9858
-	hlcoord 0, 0
-	ld a, $31
-	ld [hli], a
-	inc a
-	call Mail_DrawTopBottomBorder
-	inc a
-	ld [hli], a
-	inc a
-	call Mail_DrawLeftRightBorder
-	ld a, $36
-	ld [hli], a
-	inc a
-	call Mail_DrawTopBottomBorder
-	hlcoord 19, 1
-	ld a, $35
-	call Mail_DrawLeftRightBorder
-	ld a, $38
-	ld [hl], a
-	ret
-; b987b
-
-DrawMailBorder2: ; b987b
-	hlcoord 0, 0
-	ld a, $31
-	ld [hli], a
-	inc a
-	call Mail_DrawTopBottomBorder
-	ld [hl], $31
-	inc hl
-	inc a
-	call Mail_DrawLeftRightBorder
-	ld [hl], $31
-	inc hl
-	inc a
-	call Mail_DrawTopBottomBorder
-	hlcoord 19, 1
-	ld a, $35
-	call Mail_DrawLeftRightBorder
-	ld [hl], $31
-	ret
-; b989e
-
-Mail_Place14TileAlternatingRow: ; b989e
-	push af
-	ld b, 14 / 2
-	jr Mail_PlaceAlternatingRow
-
-Mail_Place16TileAlternatingRow: ; b98a3
-	push af
-	ld b, 16 / 2
-	jr Mail_PlaceAlternatingRow
-
-Mail_Place18TileAlternatingRow: ; b98a8
-	push af
-	ld b, 18 / 2
-
-Mail_PlaceAlternatingRow: ; b98ab
-.loop
-	ld [hli], a
-	inc a
-	ld [hli], a
-	dec a
-	dec b
-	jr nz, .loop
-	ld [hl], a
-	pop af
-	ret
-; b98b5
-
-Mail_Place14TileAlternatingColumn: ; b98b5
-	push af
-	ld b, 14 / 2
-	jr Mail_PlaceAlternatingColumn
-
-Mail_Place16TileAlternatingColumn: ; b98ba
-	push af
-	ld b, 16 / 2
-
-Mail_PlaceAlternatingColumn: ; b98bd
-.loop
-	ld [hl], a
-	ld de, SCREEN_WIDTH
-	add hl, de
-	inc a
-	ld [hl], a
-	add hl, de
-	dec a
-	dec b
-	jr nz, .loop
-	ld [hl], a
-	pop af
-	ret
-; b98cc
-
-Mail_Draw7TileRow: ; b98cc
-	ld b, $7
-	jr Mail_DrawRowLoop
-
-Mail_Draw13TileRow: ; b98d0
-	ld b, $d
-	jr Mail_DrawRowLoop
-
-Mail_Draw16TileRow: ; b98d4
-	ld b, $10
-	jr Mail_DrawRowLoop
-
-Mail_DrawTopBottomBorder: ; b98d8
-	ld b, SCREEN_WIDTH - 2
-	jr Mail_DrawRowLoop
-
-Mail_DrawFullWidthBorder: ; b98dc
-	ld b, SCREEN_WIDTH
-
-Mail_DrawRowLoop: ; b98de
-.loop
-	ld [hli], a
-	dec b
-	jr nz, .loop
-	ret
-; b98e3
-
-Mail_DrawLeftRightBorder: ; b98e3
-	ld b, SCREEN_HEIGHT - 2
-	ld de, SCREEN_WIDTH
-.loop
-	ld [hl], a
-	add hl, de
-	dec b
-	jr nz, .loop
-	ret
-; b98ee
-
-Mail_Draw2x2Graphic: ; b98ee
-	push af
-	ld [hli], a
-	inc a
-	ld [hl], a
-	ld bc, SCREEN_WIDTH - 1
-	add hl, bc
-	inc a
-	ld [hli], a
-	inc a
-	ld [hl], a
-	pop af
-	ret
-; b98fc
-
-Mail_Draw3x2Graphic: ; b98fc
-	ld [hli], a
-	inc a
-	ld [hli], a
-	inc a
-	ld [hl], a
-	ld bc, SCREEN_WIDTH - 2
-	add hl, bc
-	inc a
-	ld [hli], a
-	inc a
-	ld [hli], a
-	inc a
-	ld [hl], a
-	ret
-; b990c
-
-LoadMailGFX_Color1: ; b990c
-.loop
-	ld a, [de]
-	inc de
-	ld [hli], a
-	xor a
-	ld [hli], a
-	dec c
-	jr nz, .loop
-	ret
-; b9915
-
-LoadMailGFX_Color2: ; b9915
-.loop
-	xor a
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hli], a
-	dec c
-	jr nz, .loop
-	ret
-; b991e
-
-LoadMailGFX_Color3: ; b991e
-.loop
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld [hli], a
-	dec c
-	jr nz, .loop
-	ret
-; b9926
-
-INCLUDE "gfx/mail.asm"
-
-ItemIsMail: ; b9e76
-	ld a, d
-	ld hl, MailItems
-	ld de, 1
-	jp IsInArray
-; b9e80
-
-INCLUDE "data/items/mail_items.asm"
--- a/engine/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/map_object_action.asm
+++ /dev/null
@@ -1,313 +1,0 @@
-ObjectActionPairPointers: ; 445f
-; entries correspond to OBJECT_ACTION_* constants
-	dw SetFacingStanding,              SetFacingStanding
-	dw SetFacingStandAction,           SetFacingCurrent
-	dw SetFacingStepAction,            SetFacingCurrent
-	dw SetFacingBumpAction,            SetFacingCurrent
-	dw SetFacingCounterclockwiseSpin,  SetFacingCurrent
-	dw SetFacingCounterclockwiseSpin2, SetFacingStanding
-	dw SetFacingFish,                  SetFacingFish
-	dw SetFacingShadow,                SetFacingStanding
-	dw SetFacingEmote,                 SetFacingEmote
-	dw SetFacingBigDollSym,            SetFacingBigDollSym
-	dw SetFacingBounce,                SetFacingFreezeBounce
-	dw SetFacingWeirdTree,             SetFacingCurrent
-	dw SetFacingBigDollAsym,           SetFacingBigDollAsym
-	dw SetFacingBigDoll,               SetFacingBigDoll
-	dw SetFacingBoulderDust,           SetFacingStanding
-	dw SetFacingGrassShake,            SetFacingStanding
-	dw SetFacingSkyfall,               SetFacingCurrent
-; 44a3
-
-SetFacingStanding: ; 44a3
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], STANDING
-	ret
-; 44aa
-
-SetFacingCurrent: ; 44aa
-	call GetSpriteDirection
-	or FACING_STEP_DOWN_0 ; useless
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], a
-	ret
-; 44b5
-
-SetFacingStandAction: ; 44b5
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld a, [hl]
-	and 1
-	jr nz, SetFacingStepAction
-	jp SetFacingCurrent
-; 44c1
-
-SetFacingStepAction: ; 44c1
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	bit SLIDING, [hl]
-	jp nz, SetFacingCurrent
-
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld a, [hl]
-	inc a
-	and %00001111
-	ld [hl], a
-
-	rrca
-	rrca
-	and %00000011
-	ld d, a
-
-	call GetSpriteDirection
-	or FACING_STEP_DOWN_0 ; useless
-	or d
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], a
-	ret
-; 44e4
-
-SetFacingSkyfall: ; 44e4
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	bit SLIDING, [hl]
-	jp nz, SetFacingCurrent
-
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld a, [hl]
-	add 2
-	and %00001111
-	ld [hl], a
-
-	rrca
-	rrca
-	and %00000011
-	ld d, a
-
-	call GetSpriteDirection
-	or FACING_STEP_DOWN_0 ; useless
-	or d
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], a
-	ret
-; 4508
-
-SetFacingBumpAction: ; 4508
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	bit SLIDING, [hl]
-	jp nz, SetFacingCurrent
-
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	inc [hl]
-
-	ld a, [hl]
-	rrca
-	rrca
-	rrca
-	and %00000011
-	ld d, a
-
-	call GetSpriteDirection
-	or FACING_STEP_DOWN_0 ; useless
-	or d
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], a
-	ret
-; 4529
-
-SetFacingCounterclockwiseSpin: ; 4529
-	call CounterclockwiseSpinAction
-	ld hl, OBJECT_FACING
-	add hl, bc
-	ld a, [hl]
-	or FACING_STEP_DOWN_0 ; useless
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], a
-	ret
-; 4539
-
-SetFacingCounterclockwiseSpin2: ; 4539
-	call CounterclockwiseSpinAction
-	jp SetFacingStanding
-; 453f
-
-CounterclockwiseSpinAction: ; 453f
-; Here, OBJECT_STEP_FRAME consists of two 2-bit components,
-; using only bits 0,1 and 4,5.
-; bits 0,1 is a timer (4 overworld frames)
-; bits 4,5 determines the facing - the direction is counterclockwise.
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld a, [hl]
-	and %11110000
-	ld e, a
-
-	ld a, [hl]
-	inc a
-	and %00001111
-	ld d, a
-	cp 4
-	jr c, .ok
-
-	ld d, 0
-	ld a, e
-	add $10
-	and %00110000
-	ld e, a
-
-.ok
-	ld a, d
-	or e
-	ld [hl], a
-
-	swap e
-	ld d, 0
-	ld hl, .Directions
-	add hl, de
-	ld a, [hl]
-	ld hl, OBJECT_FACING
-	add hl, bc
-	ld [hl], a
-	ret
-; 456a
-
-.Directions: ; 456a
-	db OW_DOWN, OW_RIGHT, OW_UP, OW_LEFT
-; 456e
-
-SetFacingFish: ; 456e
-	call GetSpriteDirection
-	rrca
-	rrca
-	add FACING_FISH_DOWN
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], a
-	ret
-; 457b
-
-SetFacingShadow: ; 457b
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], FACING_SHADOW
-	ret
-; 4582
-
-SetFacingEmote: ; 4582 emote
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], FACING_EMOTE
-	ret
-; 4589
-
-SetFacingBigDollSym: ; 4589
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], FACING_BIG_DOLL_SYM
-	ret
-; 4590
-
-SetFacingBounce: ; 4590
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld a, [hl]
-	inc a
-	and %00001111
-	ld [hl], a
-	and %00001000
-	jr z, SetFacingFreezeBounce
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], FACING_STEP_UP_0
-	ret
-; 45a4
-
-SetFacingFreezeBounce: ; 45a4
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], FACING_STEP_DOWN_0
-	ret
-; 45ab
-
-SetFacingWeirdTree: ; 45ab
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld a, [hl]
-	inc a
-	ld [hl], a
-	and %00001100
-	rrca
-	rrca
-	add FACING_WEIRD_TREE_0
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], a
-	ret
-; 45be
-
-SetFacingBigDollAsym: ; 45be
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], FACING_BIG_DOLL_ASYM
-	ret
-; 45c5
-
-SetFacingBigDoll: ; 45c5
-	ld a, [wVariableSprites + SPRITE_BIG_DOLL - SPRITE_VARS]
-	ld d, FACING_BIG_DOLL_SYM ; symmetric
-	cp SPRITE_BIG_SNORLAX
-	jr z, .ok
-	cp SPRITE_BIG_LAPRAS
-	jr z, .ok
-	ld d, FACING_BIG_DOLL_ASYM ; asymmetric
-
-.ok
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], d
-	ret
-; 45da
-
-SetFacingBoulderDust: ; 45da
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	inc [hl]
-	ld a, [hl]
-
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	and 2
-	ld a, FACING_BOULDER_DUST_1
-	jr z, .ok
-	inc a ; FACING_BOULDER_DUST_2
-.ok
-	ld [hl], a
-	ret
-; 45ed
-
-SetFacingGrassShake: ; 45ed
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	inc [hl]
-	ld a, [hl]
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	and 4
-	ld a, FACING_GRASS_1
-	jr z, .ok
-	inc a ; FACING_GRASS_2
-
-.ok
-	ld [hl], a
-	ret
-; 4600
--- a/engine/map_objects.asm
+++ /dev/null
@@ -1,3123 +1,0 @@
-INCLUDE "data/sprites/facings.asm"
-
-INCLUDE "data/sprites/map_objects.asm"
-
-
-; 4357
-DeleteMapObject:: ; 4357
-	push bc
-	ld hl, OBJECT_MAP_OBJECT_INDEX
-	add hl, bc
-	ld a, [hl]
-	push af
-	ld h, b
-	ld l, c
-	ld bc, OBJECT_STRUCT_LENGTH
-	xor a
-	call ByteFill
-	pop af
-	cp -1
-	jr z, .ok
-	bit 7, a
-	jr nz, .ok
-	call GetMapObject
-	ld hl, OBJECT_SPRITE
-	add hl, bc
-	ld [hl], -1
-.ok
-	pop bc
-	ret
-; 437b
-
-Function437b: ; 437b
-	call .CheckObjectStillVisible
-	ret c
-	call .HandleStepType
-	call .HandleObjectAction
-	ret
-
-.CheckObjectStillVisible:
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	res 6, [hl]
-	ld a, [wXCoord]
-	ld e, a
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	add 1
-	sub e
-	jr c, .ok
-	cp MAPOBJECT_SCREEN_WIDTH
-	jr nc, .ok
-	ld a, [wYCoord]
-	ld e, a
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld a, [hl]
-	add 1
-	sub e
-	jr c, .ok
-	cp MAPOBJECT_SCREEN_HEIGHT
-	jr nc, .ok
-	jr .yes
-
-.ok
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	set 6, [hl]
-	ld a, [wXCoord]
-	ld e, a
-	ld hl, OBJECT_INIT_X
-	add hl, bc
-	ld a, [hl]
-	add 1
-	sub e
-	jr c, .ok2
-	cp MAPOBJECT_SCREEN_WIDTH
-	jr nc, .ok2
-	ld a, [wYCoord]
-	ld e, a
-	ld hl, OBJECT_INIT_Y
-	add hl, bc
-	ld a, [hl]
-	add 1
-	sub e
-	jr c, .ok2
-	cp MAPOBJECT_SCREEN_HEIGHT
-	jr nc, .ok2
-.yes
-	and a
-	ret
-
-.ok2
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	bit 1, [hl]
-	jr nz, .yes2
-	call DeleteMapObject
-	scf
-	ret
-
-.yes2
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	set 6, [hl]
-	and a
-	ret
-
-.HandleStepType:
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .zero
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	bit 5, [hl]
-	jr nz, .bit5
-	cp STEP_TYPE_SLEEP
-	jr z, .one
-	jr .ok3
-
-.zero
-	call ObjectMovementReset
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	bit 5, [hl]
-	jr nz, .bit5
-.one
-	call MapObjectMovementPattern
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld a, [hl]
-	and a
-	ret z
-	cp STEP_TYPE_SLEEP
-	ret z
-.ok3
-	ld hl, StepTypesJumptable
-	rst JumpTable
-	ret
-
-.bit5
-	ret
-
-.HandleObjectAction:
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	bit INVISIBLE, [hl]
-	jr nz, SetFacingStanding
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	bit 6, [hl]
-	jr nz, SetFacingStanding
-	bit 5, [hl]
-	jr nz, asm_4448
-	ld de, ObjectActionPairPointers ; use first column
-	jr _HandleObjectAction
-; 4440
-
-Function4440: ; 4440
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	bit INVISIBLE, [hl]
-	jr nz, SetFacingStanding
-asm_4448
-	ld de, ObjectActionPairPointers + 2 ; use second column
-	jr _HandleObjectAction
-; 444d
-
-_HandleObjectAction
-; call [4 * wObjectStructs[ObjInd, OBJECT_ACTION] + de]
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld a, [hl]
-	ld l, a
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	call _hl_
-	ret
-; 445f
-
-INCLUDE "engine/map_object_action.asm"
-
-CopyNextCoordsTileToStandingCoordsTile: ; 4600
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_MAP_X
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_MAP_Y
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_NEXT_TILE
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_STANDING_TILE
-	add hl, bc
-	ld [hl], a
-	call SetTallGrassFlags
-	ld hl, OBJECT_NEXT_TILE
-	add hl, bc
-	ld a, [hl]
-	call UselessAndA
-	ret
-; 462a
-
-Function462a: ; 462a
-	ld hl, OBJECT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_MAP_Y
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld [hl], a
-	ret
-; 463f
-
-UpdateTallGrassFlags: ; 463f
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	bit OVERHEAD, [hl]
-	jr z, .ok
-	ld hl, OBJECT_NEXT_TILE
-	add hl, bc
-	ld a, [hl]
-	call SetTallGrassFlags
-.ok
-	ld hl, OBJECT_NEXT_TILE
-	add hl, bc
-	ld a, [hl]
-	call UselessAndA
-	ret c ; never happens
-	ld hl, OBJECT_STANDING_TILE
-	add hl, bc
-	ld a, [hl]
-	call UselessAndA
-	ret
-; 4661
-
-SetTallGrassFlags: ; 4661
-	call CheckSuperTallGrassTile
-	jr z, .set
-	call CheckGrassTile
-	jr c, .reset
-.set
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	set OVERHEAD, [hl]
-	ret
-
-.reset
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	res OVERHEAD, [hl]
-	ret
-; 4679
-
-UselessAndA: ; 4679
-	and a
-	ret
-; 467b
-
-EndSpriteMovement: ; 467b
-	xor a
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
-	add hl, bc
-	ld [hli], a
-	ld [hli], a
-	ld [hli], a
-	ld [hl], a ; OBJECT_1E
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ret
-; 4690
-
-InitStep: ; 4690
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	bit FIXED_FACING, [hl]
-	jr nz, GetNextTile
-	add a
-	add a
-	and %00001100
-	ld hl, OBJECT_FACING
-	add hl, bc
-	ld [hl], a
-GetNextTile: ; 46a6
-	call GetStepVector
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-	ld a, d
-	call GetStepVectorSign
-	ld hl, OBJECT_MAP_X
-	add hl, bc
-	add [hl]
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld [hl], a
-	ld d, a
-	ld a, e
-	call GetStepVectorSign
-	ld hl, OBJECT_MAP_Y
-	add hl, bc
-	add [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld [hl], a
-	ld e, a
-	push bc
-	call GetCoordTile
-	pop bc
-	ld hl, OBJECT_NEXT_TILE
-	add hl, bc
-	ld [hl], a
-	ret
-; 46d7
-
-AddStepVector: ; 46d7
-	call GetStepVector
-	ld hl, OBJECT_SPRITE_X
-	add hl, bc
-	ld a, [hl]
-	add d
-	ld [hl], a
-	ld hl, OBJECT_SPRITE_Y
-	add hl, bc
-	ld a, [hl]
-	add e
-	ld [hl], a
-	ret
-; 46e9
-
-GetStepVector: ; 46e9
-; Return (x, y, duration, speed) in (d, e, a, h).
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld a, [hl]
-	and %00001111
-	add a
-	add a
-	ld l, a
-	ld h, 0
-	ld de, StepVectors
-	add hl, de
-	ld d, [hl]
-	inc hl
-	ld e, [hl]
-	inc hl
-	ld a, [hli]
-	ld h, [hl]
-	ret
-; 4700
-
-StepVectors: ; 4700
-; x,  y, duration, speed
-	; slow
-	db  0,  1, 16, 1
-	db  0, -1, 16, 1
-	db -1,  0, 16, 1
-	db  1,  0, 16, 1
-	; normal
-	db  0,  2,  8, 2
-	db  0, -2,  8, 2
-	db -2,  0,  8, 2
-	db  2,  0,  8, 2
-	; fast
-	db  0,  4,  4, 4
-	db  0, -4,  4, 4
-	db -4,  0,  4, 4
-	db  4,  0,  4, 4
-; 4730
-
-GetStepVectorSign: ; 4730
-	add a
-	ret z  ; 0 or 128
-	ld a, 1
-	ret nc ; 1 - 127
-	ld a, -1
-	ret    ; 129 - 255
-; 4738
-
-UpdatePlayerStep: ; 4738
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld a, [hl]
-	and %00000011
-	ld [wPlayerStepDirection], a
-	call AddStepVector
-	ld a, [wPlayerStepVectorX]
-	add d
-	ld [wPlayerStepVectorX], a
-	ld a, [wPlayerStepVectorY]
-	add e
-	ld [wPlayerStepVectorY], a
-	ld hl, wPlayerStepFlags
-	set 5, [hl]
-	ret
-; 4759
-
-Unreferenced_Function4759: ; 4759
-	push bc
-	ld e, a
-	ld d, 0
-	ld hl, OBJECT_MAP_OBJECT_INDEX
-	add hl, bc
-	ld a, [hl]
-	call GetMapObject
-	add hl, de
-	ld a, [hl]
-	pop bc
-	ret
-; 4769
-
-RestoreDefaultMovement: ; 4769
-	ld hl, OBJECT_MAP_OBJECT_INDEX
-	add hl, bc
-	ld a, [hl]
-	cp -1
-	jr z, .ok
-	push bc
-	call GetMapObject
-	ld hl, MAPOBJECT_MOVEMENT
-	add hl, bc
-	ld a, [hl]
-	pop bc
-	ret
-
-.ok
-	ld a, SPRITEMOVEFN_STANDING
-	ret
-; 4780
-
-ClearObjectMovementByteIndex: ; 4780
-	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
-	add hl, bc
-	ld [hl], 0
-	ret
-; 4787
-
-IncrementObjectMovementByteIndex: ; 4787
-	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
-	add hl, bc
-	inc [hl]
-	ret
-; 478d
-
-DecrementObjectMovementByteIndex: ; 478d
-	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
-	add hl, bc
-	dec [hl]
-	ret
-; 4793
-
-MovementAnonymousJumptable: ; 4793
-	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
-	add hl, bc
-	ld a, [hl]
-	pop hl
-	rst JumpTable
-	ret
-; 479b
-
-ClearObjectStructField1c: ; 479b
-	ld hl, OBJECT_1C
-	add hl, bc
-	ld [hl], 0
-	ret
-; 47a2
-
-IncrementObjectStructField1c: ; 47a2
-	ld hl, OBJECT_1C
-	add hl, bc
-	inc [hl]
-	ret
-; 47a8
-
-Field1cAnonymousJumptable: ; 47a8
-	ld hl, OBJECT_1C
-	add hl, bc
-	ld a, [hl]
-	pop hl
-	rst JumpTable
-	ret
-; 47b0
-
-GetValueObjectStructField1c: ; 47b0
-	ld hl, OBJECT_1C
-	add hl, bc
-	ld a, [hl]
-	ret
-; 47b6
-
-SetValueObjectStructField1c: ; 47b6
-	ld hl, OBJECT_1C
-	add hl, bc
-	ld [hl], a
-	ret
-; 47bc
-
-ObjectMovementReset: ; 47bc
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	push bc
-	call GetCoordTile
-	pop bc
-	ld hl, OBJECT_NEXT_TILE
-	add hl, bc
-	ld [hl], a
-	call CopyNextCoordsTileToStandingCoordsTile
-	call EndSpriteMovement
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 47dd
-
-MapObjectMovementPattern: ; 47dd
-	call ClearObjectStructField1c
-	call GetSpriteMovementFunction
-	ld a, [hl]
-	ld hl, .Pointers
-	rst JumpTable
-	ret
-
-.Pointers: ; 47e9
-; entries correspond to SPRITEMOVEFN_* constants
-	dw .Null_00 ; 00
-	dw .RandomWalkY ; 01
-	dw .RandomWalkX ; 02
-	dw .RandomWalkXY ; 03
-	dw .RandomSpin1 ; 04
-	dw .RandomSpin2 ; 05
-	dw .Standing ; 06
-	dw .ObeyDPad ; 07
-	dw .Movement08 ; 08
-	dw .Movement09 ; 09
-	dw .Movement0a ; 0a
-	dw .Movement0b ; 0b
-	dw .Movement0c ; 0c
-	dw .Movement0d ; 0d
-	dw .Movement0e ; 0e
-	dw .Follow ; 0f
-	dw .Script ; 10
-	dw .Strength ; 11
-	dw .FollowNotExact ; 12
-	dw .MovementShadow ; 13
-	dw .MovementEmote ; 14
-	dw .MovementBigStanding ; 15
-	dw .MovementBouncing ; 16
-	dw .MovementScreenShake ; 17
-	dw .MovementSpinClockwise ; 18
-	dw .MovementSpinCounterclockwise ; 19
-	dw .MovementBoulderDust ; 1a
-	dw .MovementShakingGrass ; 1b
-
-.Null_00:
-	ret
-
-.RandomWalkY:
-	call Random
-	ld a, [hRandomAdd]
-	and %00000001
-	jp .RandomWalkContinue
-
-.RandomWalkX:
-	call Random
-	ld a, [hRandomAdd]
-	and %00000001
-	or  %00000010
-	jp .RandomWalkContinue
-
-.RandomWalkXY:
-	call Random
-	ld a, [hRandomAdd]
-	and %00000011
-	jp .RandomWalkContinue
-
-.RandomSpin1:
-	call Random
-	ld a, [hRandomAdd]
-	and %00001100
-	ld hl, OBJECT_FACING
-	add hl, bc
-	ld [hl], a
-	jp RandomStepDuration_Slow
-
-.RandomSpin2:
-	ld hl, OBJECT_FACING
-	add hl, bc
-	ld a, [hl]
-	and %00001100
-	ld d, a
-	call Random
-	ld a, [hRandomAdd]
-	and %00001100
-	cp d
-	jr nz, .keep
-	xor %00001100
-.keep
-	ld [hl], a
-	jp RandomStepDuration_Fast
-
-.Standing:
-	call Function462a
-	call EndSpriteMovement
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STAND
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_05
-	ret
-
-.ObeyDPad:
-	ld hl, Function5000
-	jp HandleMovementData
-
-.Movement08:
-	ld hl, Function5015
-	jp HandleMovementData
-
-.Movement09:
-	ld hl, Function5026
-	jp HandleMovementData
-
-.Movement0a:
-	jp _GetMovementObject
-
-.Movement0b:
-	jp _GetMovementObject
-
-.Movement0c:
-	jp _GetMovementObject
-
-.Movement0d:
-	ld hl, Function5000
-	jp HandleMovementData
-
-.Movement0e:
-	jp _GetMovementObject
-
-.Follow:
-	ld hl, GetFollowerNextMovementByte
-	jp HandleMovementData
-
-.Script:
-	ld hl, GetMovementByte
-	jp HandleMovementData
-
-.Strength:
-	call MovementAnonymousJumptable
-	dw .Strength_Start
-	dw .Strength_Stop
-
-.Strength_Start:
-	ld hl, OBJECT_NEXT_TILE
-	add hl, bc
-	ld a, [hl]
-	call CheckPitTile
-	jr z, .on_pit
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	bit 2, [hl]
-	res 2, [hl]
-	jr z, .ok
-	ld hl, OBJECT_RANGE
-	add hl, bc
-	ld a, [hl]
-	and %00000011
-	or 0
-	call InitStep
-	call Function6ec1
-	jr c, .ok2
-	ld de, SFX_STRENGTH
-	call PlaySFX
-	call SpawnStrengthBoulderDust
-	call UpdateTallGrassFlags
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_0F
-	ret
-
-.ok2
-	call Function462a
-.ok
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ret
-
-.on_pit
-	call IncrementObjectMovementByteIndex
-.Strength_Stop:
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ret
-
-.FollowNotExact:
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	ld hl, OBJECT_RANGE
-	add hl, bc
-	ld a, [hl]
-	push bc
-	call GetObjectStruct
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld a, [hl]
-	cp STANDING
-	jr z, .standing
-	ld hl, OBJECT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	cp d
-	jr z, .equal
-	jr c, .less
-	ld a, 3
-	jr .done
-
-.less
-	ld a, 2
-	jr .done
-
-.equal
-	ld hl, OBJECT_MAP_Y
-	add hl, bc
-	ld a, [hl]
-	cp e
-	jr z, .standing
-	jr c, .less2
-	ld a, 0
-	jr .done
-
-.less2
-	ld a, 1
-.done
-	ld d, a
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld a, [hl]
-	and %00001100
-	or d
-	pop bc
-	jp NormalStep
-
-.standing
-	pop bc
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STAND
-	ret
-
-.MovementBigStanding:
-	call EndSpriteMovement
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_BIG_DOLL_SYM
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_04
-	ret
-
-.MovementBouncing:
-	call EndSpriteMovement
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_BOUNCE
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_04
-	ret
-
-.MovementSpinCounterclockwise:
-	call MovementAnonymousJumptable
-	dw .MovementSpinInit
-	dw .MovementSpinRepeat
-	dw .MovementSpinTurnLeft
-
-.MovementSpinClockwise:
-	call MovementAnonymousJumptable
-	dw .MovementSpinInit
-	dw .MovementSpinRepeat
-	dw .MovementSpinTurnRight
-
-.MovementSpinInit:
-	call EndSpriteMovement
-	call IncrementObjectMovementByteIndex
-.MovementSpinRepeat:
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STAND
-	ld hl, OBJECT_RANGE
-	add hl, bc
-	ld a, [hl]
-	ld a, $10
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_03
-	call IncrementObjectMovementByteIndex
-	ret
-
-.MovementSpinTurnLeft:
-	ld de, .DirectionData_Counterclockwise
-	call .MovementSpinNextFacing
-	jr .MovementSpinCounterclockwise
-
-.DirectionData_Counterclockwise: ; 49c0
-	db OW_RIGHT, OW_LEFT, OW_DOWN, OW_UP
-
-.MovementSpinTurnRight:
-	ld de, .DirectionData_Clockwise
-	call .MovementSpinNextFacing
-	jr .MovementSpinClockwise
-
-.DirectionData_Clockwise: ; 49cc
-	db OW_LEFT, OW_RIGHT, OW_UP, OW_DOWN
-
-.MovementSpinNextFacing:
-	ld hl, OBJECT_FACING
-	add hl, bc
-	ld a, [hl]
-	and %00001100
-	rrca
-	rrca
-	push hl
-	ld l, a
-	ld h, 0
-	add hl, de
-	ld a, [hl]
-	pop hl
-	ld [hl], a
-	call DecrementObjectMovementByteIndex
-	ret
-
-.MovementShadow:
-	call ._MovementShadow_Grass_Emote_BoulderDust
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_SHADOW
-	ld hl, OBJECT_STEP_DURATION
-	add hl, de
-	ld a, [hl]
-	inc a
-	add a
-	add 0
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, de
-	ld a, [hl]
-	maskbits NUM_DIRECTIONS
-	ld d, 1 * 8 + 6
-	cp DOWN
-	jr z, .ok_13
-	cp UP
-	jr z, .ok_13
-	ld d, 1 * 8 + 4
-.ok_13
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], d
-	ld hl, OBJECT_SPRITE_X_OFFSET
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_TRACKING_OBJECT
-	ret
-
-.MovementEmote:
-	call EndSpriteMovement
-	call ._MovementShadow_Grass_Emote_BoulderDust
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_EMOTE
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], -2 * 8
-	ld hl, OBJECT_SPRITE_X_OFFSET
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_TRACKING_OBJECT
-	ret
-
-.MovementBoulderDust:
-	call EndSpriteMovement
-	call ._MovementShadow_Grass_Emote_BoulderDust
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_BOULDER_DUST
-	ld hl, OBJECT_STEP_DURATION
-	add hl, de
-	ld a, [hl]
-	inc a
-	add a
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, de
-	ld a, [hl]
-	and %00000011
-	ld e, a
-	ld d, 0
-	ld hl, .data_4a81
-	add hl, de
-	add hl, de
-	ld d, [hl]
-	inc hl
-	ld e, [hl]
-	ld hl, OBJECT_SPRITE_X_OFFSET
-	add hl, bc
-	ld [hl], d
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], e
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_TRACKING_OBJECT
-	ret
-
-.data_4a81  ; 4a81
-	;   x,  y
-	db  0, -4
-	db  0,  8
-	db  6,  2
-	db -6,  2
-
-.MovementShakingGrass:
-	call EndSpriteMovement
-	call ._MovementShadow_Grass_Emote_BoulderDust
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_GRASS_SHAKE
-	ld hl, OBJECT_STEP_DURATION
-	add hl, de
-	ld a, [hl]
-	add -1
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_TRACKING_OBJECT
-	ret
-
-._MovementShadow_Grass_Emote_BoulderDust:
-	ld hl, OBJECT_RANGE
-	add hl, bc
-	ld a, [hl]
-	push bc
-	call GetObjectStruct
-	ld d, b
-	ld e, c
-	pop bc
-	ld hl, OBJECT_1D
-	add hl, bc
-	ld [hl], e
-	inc hl
-	ld [hl], d
-	ret
-
-.MovementScreenShake:
-	call EndSpriteMovement
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_00
-	ld hl, OBJECT_RANGE
-	add hl, bc
-	ld a, [hl]
-	call ._MovementScreenShake
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], e
-	ld hl, OBJECT_1E
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_15
-	ret
-
-._MovementScreenShake:
-	ld d, a
-	and %00111111
-	ld e, a
-	ld a, d
-	rlca
-	rlca
-	and %00000011
-	ld d, a
-	inc d
-	ld a, 1
-.loop
-	dec d
-	ret z
-	add a
-	jr .loop
-
-.RandomWalkContinue:
-	call InitStep
-	call Function6ec1 ; check whether the object can move in that direction
-	jr c, .NewDuration
-	call UpdateTallGrassFlags
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STEP
-	ld hl, wCenteredObject
-	ld a, [hMapObjectIndexBuffer]
-	cp [hl]
-	jr z, .load_6
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_07
-	ret
-
-.load_6
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_PLAYER_WALK
-	ret
-
-.NewDuration:
-	call EndSpriteMovement
-	call Function462a
-RandomStepDuration_Slow: ; 4b1d
-	call Random
-	ld a, [hRandomAdd]
-	and %01111111
-	jr SetRandomStepDuration
-; 4b26
-
-RandomStepDuration_Fast: ; 4b26
-	call Random
-	ld a, [hRandomAdd]
-	and %00011111
-SetRandomStepDuration: ; 4b2d
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STAND
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_03
-	ret
-; 4b45
-
-StepTypesJumptable: ; 4b45
-; entries correspond to STEP_TYPE_* constants
-	dw ObjectMovementReset ; 00
-	dw MapObjectMovementPattern ; 01
-	dw NPCStep ; 02
-	dw StepType03 ; 03
-	dw StepType04 ; 04
-	dw StepType05 ; 05
-	dw PlayerStep ; 06
-	dw StepType07 ; 07
-	dw NPCJump ; 08
-	dw PlayerJump ; 09
-	dw PlayerOrNPCTurnStep ; 0a
-	dw StepTypeBump ; 0b
-	dw TeleportFrom ; 0c
-	dw TeleportTo ; 0d
-	dw Skyfall ; 0e
-	dw StepType0f ; 0f
-	dw GotBiteStep ; 10
-	dw RockSmashStep ; 11
-	dw ReturnDigStep ; 12
-	dw StepTypeTrackingObject ; 13
-	dw StepType14 ; 14
-	dw StepType15 ; 15
-	dw StepType16 ; 16
-	dw StepType17 ; 17
-	dw StepType18 ; 18
-	dw SkyfallTop ; 19
-; 4b79
-
-WaitStep_InPlace: ; 4b79
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4b86
-
-NPCJump: ; 4b86
-	call Field1cAnonymousJumptable
-; anonymous dw
-	dw .Jump
-	dw .Land
-
-.Jump:
-	call AddStepVector
-	call UpdateJumpPosition
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	call CopyNextCoordsTileToStandingCoordsTile
-	call GetNextTile
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	res 3, [hl]
-	call IncrementObjectStructField1c
-	ret
-
-.Land:
-	call AddStepVector
-	call UpdateJumpPosition
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	call CopyNextCoordsTileToStandingCoordsTile
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4bbf
-
-PlayerJump: ; 4bbf
-	call Field1cAnonymousJumptable
-; anonymous dw
-	dw .initjump
-	dw .stepjump
-	dw .initland
-	dw .stepland
-
-.initjump
-	ld hl, wPlayerStepFlags
-	set 7, [hl]
-	call IncrementObjectStructField1c
-.stepjump
-	call UpdateJumpPosition
-	call UpdatePlayerStep
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	call CopyNextCoordsTileToStandingCoordsTile
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	res 3, [hl]
-	ld hl, wPlayerStepFlags
-	set 6, [hl]
-	set 4, [hl]
-	call IncrementObjectStructField1c
-	ret
-
-.initland
-	call GetNextTile
-	ld hl, wPlayerStepFlags
-	set 7, [hl]
-	call IncrementObjectStructField1c
-.stepland
-	call UpdateJumpPosition
-	call UpdatePlayerStep
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	ld hl, wPlayerStepFlags
-	set 6, [hl]
-	call CopyNextCoordsTileToStandingCoordsTile
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4c18
-
-TeleportFrom: ; 4c18
-	call Field1cAnonymousJumptable
-; anonymous dw
-	dw .InitSpin
-	dw .DoSpin
-	dw .InitSpinRise
-	dw .DoSpinRise
-; 4c23
-
-.InitSpin:
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], 16
-	call IncrementObjectStructField1c
-.DoSpin:
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_SPIN
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	call IncrementObjectStructField1c
-	ret
-
-.InitSpinRise:
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_1F
-	add hl, bc
-	ld [hl], $10
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], 16
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	res 3, [hl]
-	call IncrementObjectStructField1c
-.DoSpinRise:
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_SPIN
-	ld hl, OBJECT_1F
-	add hl, bc
-	inc [hl]
-	ld a, [hl]
-	ld d, $60
-	call Sine
-	ld a, h
-	sub $60
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4c89
-
-TeleportTo: ; 4c89
-	call Field1cAnonymousJumptable
-; anonymous dw
-	dw .InitWait
-	dw .DoWait
-	dw .InitDescent
-	dw .DoDescent
-	dw .InitFinalSpin
-	dw .DoFinalSpin
-	dw .FinishStep
-; 4c9a
-
-.InitWait:
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_00
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], 16
-	call IncrementObjectStructField1c
-	ret
-; 4caa
-
-.DoWait:
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	call IncrementObjectStructField1c
-.InitDescent:
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_1F
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], 16
-	call IncrementObjectStructField1c
-	ret
-; 4cc9
-
-.DoDescent:
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_SPIN
-	ld hl, OBJECT_1F
-	add hl, bc
-	inc [hl]
-	ld a, [hl]
-	ld d, $60
-	call Sine
-	ld a, h
-	sub $60
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	call IncrementObjectStructField1c
-.InitFinalSpin:
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], 16
-	call IncrementObjectStructField1c
-	ret
-; 4cf5
-
-.DoFinalSpin:
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_SPIN
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-.FinishStep:
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4d14
-
-Skyfall: ; 4d14
-	call Field1cAnonymousJumptable
-; anonymous dw
-	dw .Init
-	dw .Step
-	dw .Fall
-	dw .Finish
-; 4d1f
-
-.Init:
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_00
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], 16
-	call IncrementObjectStructField1c
-.Step:
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STEP
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_1F
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], 16
-	call IncrementObjectStructField1c
-.Fall:
-	ld hl, OBJECT_1F
-	add hl, bc
-	inc [hl]
-	ld a, [hl]
-	ld d, $60
-	call Sine
-	ld a, h
-	sub $60
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	call IncrementObjectStructField1c
-.Finish:
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4d7e
-
-GotBiteStep: ; 4d7e
-	call Field1cAnonymousJumptable
-; anonymous dw
-	dw .Init
-	dw .Run
-; 4d85
-
-.Init:
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], 8
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], 0
-	call IncrementObjectStructField1c
-.Run:
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld a, [hl]
-	xor 1
-	ld [hl], a
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4daf
-
-RockSmashStep: ; 4daf
-	call .Step
-	jp WaitStep_InPlace
-; 4db5
-
-.Step:
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld a, [hl]
-	and %00000001
-	ld a, OBJECT_ACTION_STAND
-	jr z, .yes
-	ld a, OBJECT_ACTION_00
-.yes
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], a
-	ret
-; 4dc8
-
-ReturnDigStep: ; 4dc8
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld a, [hl]
-	and %00000001
-	ld a, OBJECT_ACTION_SPIN
-	jr z, .yes
-	ld a, OBJECT_ACTION_SPIN_FLICKER
-.yes
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], a
-	jp WaitStep_InPlace
-; 4ddd
-
-StepType03: ; 4ddd
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4df0
-
-StepType18: ; 4df0
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	jp DeleteMapObject
-; 4dff
-
-StepTypeBump: ; 4dff
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4e0c
-
-StepType05: ; 4e0c
-	call Field1cAnonymousJumptable
-; anonymous dw
-	dw .Reset
-	dw StepType04
-
-.Reset:
-	call RestoreDefaultMovement
-	call GetInitialFacing
-	ld hl, OBJECT_FACING
-	add hl, bc
-	ld [hl], a
-	call IncrementObjectStructField1c
-StepType04: ; 4e21
-	call Stubbed_Function4fb2
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ret
-; 4e2b
-
-NPCStep: ; 4e2b
-	call Stubbed_Function4fb2
-	call AddStepVector
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	call CopyNextCoordsTileToStandingCoordsTile
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4e47
-
-StepType07: ; 4e47
-	call AddStepVector
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	call CopyNextCoordsTileToStandingCoordsTile
-	jp RandomStepDuration_Slow
-; 4e56
-
-PlayerStep: ; 4e56
-; AnimateStep?
-	call Field1cAnonymousJumptable
-; anonymous dw
-	dw .init
-	dw .step
-
-.init
-	ld hl, wPlayerStepFlags
-	set 7, [hl]
-	call IncrementObjectStructField1c
-.step
-	call UpdatePlayerStep
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	ld hl, wPlayerStepFlags
-	set 6, [hl]
-	call CopyNextCoordsTileToStandingCoordsTile
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4e83
-
-PlayerOrNPCTurnStep: ; 4e83
-	call Field1cAnonymousJumptable
-; anonymous dw
-	dw .init1
-	dw .step1
-	dw .init2
-	dw .step2
-
-.init1
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld a, [hl]
-	ld [hl], 2
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], 2
-	call IncrementObjectStructField1c
-.step1
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	call IncrementObjectStructField1c
-.init2
-	ld hl, OBJECT_1D ; new facing
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_FACING
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], 2
-	call IncrementObjectStructField1c
-.step2
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4ecd
-
-StepType0f: ; 4ecd
-	call AddStepVector
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	push bc
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	ld hl, OBJECT_MAP_OBJECT_INDEX
-	add hl, bc
-	ld a, [hl]
-	ld b, a
-	farcall CopyDECoordsToMapObject
-	pop bc
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	res 2, [hl]
-	call CopyNextCoordsTileToStandingCoordsTile
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4f04
-
-StepTypeTrackingObject: ; 4f04
-	ld hl, OBJECT_1D
-	add hl, bc
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	ld hl, OBJECT_SPRITE
-	add hl, de
-	ld a, [hl]
-	and a
-	jr z, .nope
-	ld hl, OBJECT_SPRITE_X
-	add hl, de
-	ld a, [hl]
-	ld hl, OBJECT_SPRITE_X
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_SPRITE_Y
-	add hl, de
-	ld a, [hl]
-	ld hl, OBJECT_SPRITE_Y
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-	ret nz
-.nope
-	jp DeleteMapObject
-; 4f33
-
-StepType14: ; 4f33
-StepType15: ; 4f33
-	call Field1cAnonymousJumptable
-; anonymous dw
-	dw .Init
-	dw .Run
-
-.Init:
-	xor a
-	ld hl, OBJECT_1D
-	add hl, bc
-	ld [hl], a
-	call IncrementObjectStructField1c
-.Run:
-	ld hl, OBJECT_1D
-	add hl, bc
-	ld d, [hl]
-	ld a, [wPlayerStepVectorY]
-	sub d
-	ld [wPlayerStepVectorY], a
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	jr z, .ok
-	ld a, [hl]
-	call .GetSign
-	ld hl, OBJECT_1D
-	add hl, bc
-	ld [hl], a
-	ld d, a
-	ld a, [wPlayerStepVectorY]
-	add d
-	ld [wPlayerStepVectorY], a
-	ret
-
-.ok
-	call DeleteMapObject
-	ret
-
-.GetSign:
-	ld hl, OBJECT_1E
-	add hl, bc
-	and 1
-	ld a, [hl]
-	ret z
-	cpl
-	inc a
-	ret
-; 4f77
-
-StepType16: ; 4f77
-	call Field1cAnonymousJumptable ; ????
-; 4f7a
-StepType17: ; 4f7a
-	call Field1cAnonymousJumptable
-; anonymous dw
-	dw .null
-	dw .null
-	dw .null
-.null
-; 4f83
-
-SkyfallTop: ; 4f83
-	call Field1cAnonymousJumptable
-; anonymous dw
-	dw .Init
-	dw .Run
-
-.Init:
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_SKYFALL
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], 16
-	call IncrementObjectStructField1c
-
-.Run:
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	dec [hl]
-	ret nz
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], $60
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld [hl], 0
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 4fb2
-
-Stubbed_Function4fb2:
-	ret
-	ld hl, OBJECT_1D
-	add hl, bc
-	inc [hl]
-	ld a, [hl]
-	srl a
-	srl a
-	and %00000111
-	ld l, a
-	ld h, 0
-	ld de, .y
-	add hl, de
-	ld a, [hl]
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.y ; 4fcd
-	db 0, -1, -2, -3, -4, -3, -2, -1
-; 4fd5
-UpdateJumpPosition: ; 4fd5
-	call GetStepVector
-	ld a, h
-	ld hl, OBJECT_1F
-	add hl, bc
-	ld e, [hl]
-	add e
-	ld [hl], a
-	nop
-	srl e
-	ld d, 0
-	ld hl, .y
-	add hl, de
-	ld a, [hl]
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.y ; 4ff0
-	db  -4,  -6,  -8, -10, -11, -12, -12, -12
-	db -11, -10,  -9,  -8,  -6,  -4,   0,   0
-; 5000
-Function5000: ; unscripted?
-; copy [wPlayerNextMovement] to [wPlayerMovement]
-	ld a, [wPlayerNextMovement]
-	ld hl, wPlayerMovement
-	ld [hl], a
-; load [wPlayerNextMovement] with movement_step_sleep
-	ld a, movement_step_sleep
-	ld [wPlayerNextMovement], a
-; recover the previous value of [wPlayerNextMovement]
-	ld a, [hl]
-	ret
-; 500e
-
-GetMovementByte:
-	ld hl, wMovementDataPointer
-	call _GetMovementByte
-	ret
-; 5015
-
-Function5015: ; 5015
-	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
-	add hl, bc
-	ld e, [hl]
-	inc [hl]
-	ld d, 0
-	ld hl, wc2e2
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	add hl, de
-	ld a, [hl]
-	ret
-; 5026
-
-Function5026: ; 5026
-	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
-	add hl, bc
-	ld e, [hl]
-	inc [hl]
-	ld d, 0
-	ld hl, wc2e6
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	add hl, de
-	ld a, [hl]
-	ret
-; 5037
-
-_GetMovementObject: ; 5037
-	ld hl, GetMovementObject
-	jp HandleMovementData
-; 503d
-
-GetMovementObject: ; 503d
-	ld a, [wMovementObject]
-	ret
-; 5041
-
-HandleMovementData: ; 5041
-	call .StorePointer
-.loop
-	xor a
-	ld [wMovementByteWasControlSwitch], a
-	call JumpMovementPointer
-	call DoMovementFunction
-	ld a, [wMovementByteWasControlSwitch]
-	and a
-	jr nz, .loop
-	ret
-
-.StorePointer:
-	ld a, l
-	ld [wMovementPointer], a
-	ld a, h
-	ld [wMovementPointer + 1], a
-	ret
-; 505e
-
-JumpMovementPointer: ; 505e
-	ld hl, wMovementPointer
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-; 5065
-
-ContinueReadingMovement: ; 5065
-	ld a, 1
-	ld [wMovementByteWasControlSwitch], a
-	ret
-; 506b
-
-DoMovementFunction: ; 506b
-	push af
-	call ApplyMovementToFollower
-	pop af
-	ld hl, MovementPointers
-	rst JumpTable
-	ret
-; 5075
-
-INCLUDE "engine/movement.asm"
-; 54b8
-
-ApplyMovementToFollower: ; 54b8
-	ld e, a
-	ld a, [wObjectFollow_Follower]
-	cp -1
-	ret z
-	ld a, [wObjectFollow_Leader]
-	ld d, a
-	ld a, [hMapObjectIndexBuffer]
-	cp d
-	ret nz
-	ld a, e
-	cp movement_step_sleep
-	ret z
-	cp movement_step_end
-	ret z
-	cp movement_step_4b
-	ret z
-	cp movement_step_bump
-	ret z
-	cp movement_slow_step
-	ret c
-	push af
-	ld hl, wFollowerMovementQueueLength
-	inc [hl]
-	ld e, [hl]
-	ld d, 0
-	ld hl, wFollowMovementQueue
-	add hl, de
-	pop af
-	ld [hl], a
-	ret
-; 54e6
-
-GetFollowerNextMovementByte: ; 54e6
-	ld hl, wFollowerMovementQueueLength
-	ld a, [hl]
-	and a
-	jr z, .done
-	cp -1
-	jr z, .done
-	dec [hl]
-	ld e, a
-	ld d, 0
-	ld hl, wFollowMovementQueue
-	add hl, de
-	inc e
-	ld a, -1
-.loop
-	ld d, [hl]
-	ld [hld], a
-	ld a, d
-	dec e
-	jr nz, .loop
-	ret
-
-.done
-	call .CancelFollowIfLeaderMissing
-	ret c
-	ld a, movement_step_sleep
-	ret
-
-.CancelFollowIfLeaderMissing:
-	ld a, [wObjectFollow_Leader]
-	cp -1
-	jr z, .nope
-	push bc
-	call GetObjectStruct
-	ld hl, OBJECT_SPRITE
-	add hl, bc
-	ld a, [hl]
-	pop bc
-	and a
-	jr z, .nope
-	and a
-	ret
-
-.nope
-	ld a, -1
-	ld [wObjectFollow_Follower], a
-	ld a, movement_step_end
-	scf
-	ret
-; 5529
-
-SpawnShadow: ; 5529
-	push bc
-	ld de, .ShadowObject
-	call CopyTempObjectData
-	call InitTempObject
-	pop bc
-	ret
-
-.ShadowObject:
-	; vtile, palette, movement
-	db $00, PAL_OW_SILVER, SPRITEMOVEDATA_SHADOW
-; 5538
-
-SpawnStrengthBoulderDust: ; 5538
-	push bc
-	ld de, .BoulderDustObject
-	call CopyTempObjectData
-	call InitTempObject
-	pop bc
-	ret
-
-.BoulderDustObject:
-	db $00, PAL_OW_SILVER, SPRITEMOVEDATA_BOULDERDUST
-; 5547
-
-SpawnEmote: ; 5547
-	push bc
-	ld de, .EmoteObject
-	call CopyTempObjectData
-	call InitTempObject
-	pop bc
-	ret
-
-.EmoteObject:
-	db $00, PAL_OW_SILVER, SPRITEMOVEDATA_EMOTE
-; 5556
-
-ShakeGrass: ; 5556
-	push bc
-	ld de, .data_5562
-	call CopyTempObjectData
-	call InitTempObject
-	pop bc
-	ret
-
-.data_5562
-	db $00, PAL_OW_TREE, SPRITEMOVEDATA_GRASS
-; 5565
-
-ShakeScreen: ; 5565
-	push bc
-	push af
-	ld de, .ScreenShakeObject
-	call CopyTempObjectData
-	pop af
-	ld [wTempObjectCopyRange], a
-	call InitTempObject
-	pop bc
-	ret
-
-.ScreenShakeObject:
-	db $00, PAL_OW_SILVER, SPRITEMOVEDATA_SCREENSHAKE
-; 5579
-DespawnEmote: ; 5579
-	push bc
-	ld a, [hMapObjectIndexBuffer]
-	ld c, a
-	call .DeleteEmote
-	pop bc
-	ret
-
-.DeleteEmote:
-	ld de, wObjectStructs
-	ld a, NUM_OBJECT_STRUCTS
-.loop
-	push af
-	ld hl, OBJECT_FLAGS1
-	add hl, de
-	bit EMOTE_OBJECT, [hl]
-	jr z, .next
-	ld hl, OBJECT_SPRITE
-	add hl, de
-	ld a, [hl]
-	and a
-	jr z, .next
-	push bc
-	xor a
-	ld bc, OBJECT_STRUCT_LENGTH
-	call ByteFill
-	pop bc
-.next
-	ld hl, OBJECT_STRUCT_LENGTH
-	add hl, de
-	ld d, h
-	ld e, l
-	pop af
-	dec a
-	jr nz, .loop
-	ret
-; 55ac
-
-InitTempObject: ; 55ac
-	call FindFirstEmptyObjectStruct
-	ret nc
-	ld d, h
-	ld e, l
-	farcall CopyTempObjectToObjectStruct
-	ret
-; 55b9
-
-CopyTempObjectData: ; 55b9
-; load into wTempObjectCopy:
-; -1, -1, [de], [de + 1], [de + 2], [hMapObjectIndexBuffer], [NextMapX], [NextMapY], -1
-; This spawns the object at the same place as whichever object is loaded into bc.
-	ld hl, wTempObjectCopyMapObjectIndex
-	ld [hl], -1
-	inc hl
-	ld [hl], -1
-	inc hl
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	ld [hli], a
-	ld a, [hMapObjectIndexBuffer]
-	ld [hli], a
-	push hl
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	pop hl
-	ld [hl], d
-	inc hl
-	ld [hl], e
-	inc hl
-	ld [hl], -1
-	ret
-; 55e0
-
-Function55e0:: ; 55e0
-	ld a, [wVramState]
-	bit 0, a
-	ret z
-	ld bc, wObjectStructs
-	xor a
-.loop
-	ld [hMapObjectIndexBuffer], a
-	call DoesObjectHaveASprite
-	jr z, .ok
-	call Function565c
-.ok
-	ld hl, OBJECT_STRUCT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	ld a, [hMapObjectIndexBuffer]
-	inc a
-	cp NUM_OBJECT_STRUCTS
-	jr nz, .loop
-	ret
-; 5602
-
-Function5602: ; 5602, called at battle start
-	call Function5645 ; clear sprites
-	ld a, PLAYER
-	call Function5629 ; respawn player
-	ld a, [wBattleScriptFlags]
-	bit 7, a
-	jr z, .ok
-	ld a, [hLastTalked]
-	and a
-	jr z, .ok
-	call Function5629 ; respawn opponent
-.ok
-	call _UpdateSprites
-	ret
-; 561d
-
-Function561d: ; 561d
-	call Function5645 ; clear sprites
-	ld a, PLAYER
-	call Function5629 ; respawn player
-	call _UpdateSprites
-	ret
-; 5629
-
-Function5629: ; 5629
-	cp NUM_OBJECTS
-	ret nc
-	call GetMapObject
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	cp -1
-	ret z
-	cp NUM_OBJECT_STRUCTS
-	ret nc
-	call GetObjectStruct
-	call DoesObjectHaveASprite
-	ret z
-	call Function5673
-	ret
-; 5645
-
-Function5645: ; 5645
-	xor a
-	ld bc, wObjectStructs
-.loop
-	ld [hMapObjectIndexBuffer], a
-	call SetFacing_Standing
-	ld hl, OBJECT_STRUCT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	ld a, [hMapObjectIndexBuffer]
-	inc a
-	cp NUM_OBJECT_STRUCTS
-	jr nz, .loop
-	ret
-; 565c
-
-Function565c: ; 565c
-	push bc
-	call Function56cd
-	pop bc
-	jr c, SetFacing_Standing
-	call Function56a3
-	jr c, SetFacing_Standing
-	call Function5688
-	farcall Function4440
-	xor a
-	ret
-; 5673
-
-Function5673: ; 5673
-	call Function56a3
-	jr c, SetFacing_Standing
-	farcall Function4440 ; no need to farcall
-	xor a
-	ret
-; 5680
-
-SetFacing_Standing: ; 5680
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld [hl], STANDING
-	scf
-	ret
-; 5688
-
-Function5688: ; 5688
-	push bc
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	call GetCoordTile
-	pop bc
-	ld hl, OBJECT_NEXT_TILE
-	add hl, bc
-	ld [hl], a
-	farcall UpdateTallGrassFlags ; no need to farcall
-	ret
-; 56a3
-
-Function56a3: ; 56a3
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	inc d
-	inc e
-	ld a, [wXCoord]
-	cp d
-	jr z, .equal_x
-	jr nc, .nope
-	add MAPOBJECT_SCREEN_WIDTH - 1
-	cp d
-	jr c, .nope
-.equal_x
-	ld a, [wYCoord]
-	cp e
-	jr z, .equal_y
-	jr nc, .nope
-	add MAPOBJECT_SCREEN_HEIGHT - 1
-	cp e
-	jr c, .nope
-.equal_y
-	xor a
-	ret
-
-.nope
-	scf
-	ret
-; 56cd
-
-Function56cd: ; 56cd
-	ld a, [wPlayerBGMapOffsetX]
-	ld d, a
-	ld hl, OBJECT_SPRITE_X_OFFSET
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_SPRITE_X
-	add hl, bc
-	add [hl]
-	add d
-	cp $f0
-	jr nc, .ok1
-	cp $a0
-	jp nc, .nope
-.ok1
-	and %00000111
-	ld d, 2
-	cp 4
-	jr c, .ok2
-	ld d, 3
-.ok2
-	ld a, [hl]
-	srl a
-	srl a
-	srl a
-	cp SCREEN_WIDTH
-	jr c, .ok3
-	sub BG_MAP_WIDTH
-.ok3
-	ld [hUsedSpriteIndex], a
-	ld a, [wPlayerBGMapOffsetY]
-	ld e, a
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_SPRITE_Y
-	add hl, bc
-	add [hl]
-	add e
-	cp $f0
-	jr nc, .ok4
-	cp $90
-	jr nc, .nope
-.ok4
-	and %00000111
-	ld e, 2
-	cp 4
-	jr c, .ok5
-	ld e, 3
-.ok5
-	ld a, [hl]
-	srl a
-	srl a
-	srl a
-	cp SCREEN_HEIGHT
-	jr c, .ok6
-	sub BG_MAP_HEIGHT
-.ok6
-	ld [hUsedSpriteTile], a
-	ld hl, OBJECT_PALETTE
-	add hl, bc
-	bit 7, [hl]
-	jr z, .ok7
-	ld a, d
-	add 2
-	ld d, a
-	ld a, e
-	add 2
-	ld e, a
-.ok7
-	ld a, d
-	ld [hFFBF], a
-.loop
-	ld a, [hFFBF]
-	ld d, a
-	ld a, [hUsedSpriteTile]
-	add e
-	dec a
-	cp SCREEN_HEIGHT
-	jr nc, .ok9
-	ld b, a
-.next
-	ld a, [hUsedSpriteIndex]
-	add d
-	dec a
-	cp SCREEN_WIDTH
-	jr nc, .ok8
-	ld c, a
-	push bc
-	call Coord2Tile
-	pop bc
-; NPCs disappear if standing on tile $60-$7f (or $e0-$ff),
-; since those IDs are for text characters and textbox frames.
-	ld a, [hl]
-	cp FIRST_REGULAR_TEXT_CHAR
-	jr nc, .nope
-.ok8
-	dec d
-	jr nz, .next
-.ok9
-	dec e
-	jr nz, .loop
-	and a
-	ret
-
-.nope
-	scf
-	ret
-; 576a
-
-HandleNPCStep:: ; 576a
-	call .ResetStepVector
-	call .DoStepsForAllObjects
-	ret
-
-.ResetStepVector:
-	xor a
-	ld [wPlayerStepVectorX], a
-	ld [wPlayerStepVectorY], a
-	ld [wPlayerStepFlags], a
-	ld a, -1
-	ld [wPlayerStepDirection], a
-	ret
-
-.DoStepsForAllObjects:
-	ld bc, wObjectStructs
-	xor a
-.loop
-	ld [hMapObjectIndexBuffer], a
-	call DoesObjectHaveASprite
-	jr z, .next
-	call Function437b
-.next
-	ld hl, OBJECT_STRUCT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	ld a, [hMapObjectIndexBuffer]
-	inc a
-	cp NUM_OBJECT_STRUCTS
-	jr nz, .loop
-	ret
-; 579d
-
-RefreshPlayerSprite: ; 579d
-	ld a, movement_step_sleep
-	ld [wPlayerNextMovement], a
-	ld [wPlayerMovement], a
-	xor a
-	ld [wPlayerTurningDirection], a
-	ld [wPlayerObjectStepFrame], a
-	call .TryResetPlayerAction
-	farcall CheckWarpFacingDown
-	call c, SpawnInFacingDown
-	call .SpawnInCustomFacing
-	ret
-; 57bc
-
-.TryResetPlayerAction: ; 57bc
-	ld hl, wPlayerSpriteSetupFlags
-	bit PLAYERSPRITESETUP_RESET_ACTION_F, [hl]
-	jr nz, .ok
-	ret
-
-.ok
-	ld a, OBJECT_ACTION_00
-	ld [wPlayerAction], a
-	ret
-; 57ca
-
-.SpawnInCustomFacing: ; 57ca
-	ld hl, wPlayerSpriteSetupFlags
-	bit PLAYERSPRITESETUP_CUSTOM_FACING_F, [hl]
-	ret z
-	ld a, [wPlayerSpriteSetupFlags]
-	and PLAYERSPRITESETUP_FACING_MASK
-	add a
-	add a
-	jr ContinueSpawnFacing
-; 57d9
-
-SpawnInFacingDown: ; 57d9
-	ld a, 0
-ContinueSpawnFacing: ; 57db
-	ld bc, wPlayerStruct
-	call SetSpriteDirection
-	ret
-; 57e2
-
-_SetPlayerPalette: ; 57e2
-	ld a, d
-	and %10000000
-	ret z
-	ld bc, 0 ; debug?
-	ld hl, OBJECT_FACING
-	add hl, bc
-	ld a, [hl]
-	or d
-	ld [hl], a
-	ld a, d
-	swap a
-	and %00000111
-	ld d, a
-	ld bc, wPlayerStruct
-	ld hl, OBJECT_PALETTE
-	add hl, bc
-	ld a, [hl]
-	and %11111000
-	or d
-	ld [hl], a
-	ret
-; 5803
-
-StartFollow:: ; 5803
-	push bc
-	ld a, b
-	call SetLeaderIfVisible
-	pop bc
-	ret c
-	ld a, c
-	call SetFollowerIfVisible
-	farcall QueueFollowerFirstStep
-	ret
-; 5815
-
-SetLeaderIfVisible: ; 5815
-	call CheckObjectVisibility
-	ret c
-	ld a, [hObjectStructIndexBuffer]
-	ld [wObjectFollow_Leader], a
-	ret
-; 581f
-
-StopFollow:: ; 581f
-	call ResetLeader
-	call ResetFollower
-	ret
-; 5826
-
-ResetLeader: ; 5826
-	ld a, -1
-	ld [wObjectFollow_Leader], a
-	ret
-; 582c
-
-SetFollowerIfVisible: ; 582c
-	push af
-	call ResetFollower
-	pop af
-	call CheckObjectVisibility
-	ret c
-	ld hl, OBJECT_MOVEMENTTYPE
-	add hl, bc
-	ld [hl], SPRITEMOVEDATA_FOLLOWING
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_00
-	ld a, [hObjectStructIndexBuffer]
-	ld [wObjectFollow_Follower], a
-	ret
-; 5847
-
-ResetFollower: ; 5847
-	ld a, [wObjectFollow_Follower]
-	cp -1
-	ret z
-	call GetObjectStruct
-	farcall Function58e3 ; no need to bankswitch
-	ld a, -1
-	ld [wObjectFollow_Follower], a
-	ret
-; 585c
-
-SetFlagsForMovement_1:: ; 585c
-	ld a, c
-	call CheckObjectVisibility
-	ret c
-	push bc
-	call Function587a
-	pop bc
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	res 5, [hl]
-	xor a
-	ret
-; 586e
-
-Function586e: ; 586e
-	call CheckObjectVisibility
-	ret c
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	set 5, [hl]
-	xor a
-	ret
-; 587a
-
-Function587a: ; 587a
-	ld bc, wObjectStructs
-	xor a
-.loop
-	push af
-	call DoesObjectHaveASprite
-	jr z, .next
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	set 5, [hl]
-.next
-	ld hl, OBJECT_STRUCT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	pop af
-	inc a
-	cp NUM_OBJECT_STRUCTS
-	jr nz, .loop
-	ret
-; 5897
-
-_SetFlagsForMovement_2:: ; 5897
-	ld a, [wObjectFollow_Leader]
-	cp -1
-	ret z
-	push bc
-	call GetObjectStruct
-	ld hl, OBJECT_MAP_OBJECT_INDEX
-	add hl, bc
-	ld a, [hl]
-	pop bc
-	cp c
-	ret nz
-	ld a, [wObjectFollow_Follower]
-	cp -1
-	ret z
-	call GetObjectStruct
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	res 5, [hl]
-	ret
-; 58b9
-
-Function58b9:: ; 58b9
-	push bc
-	ld bc, wObjectStructs
-	xor a
-.loop
-	push af
-	call DoesObjectHaveASprite
-	jr z, .next
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	res 5, [hl]
-.next
-	ld hl, OBJECT_STRUCT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	pop af
-	inc a
-	cp NUM_OBJECT_STRUCTS
-	jr nz, .loop
-	pop bc
-	ret
-; 58d8
-
-Function58d8: ; 58d8
-	call CheckObjectVisibility
-	ret c
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	res 5, [hl]
-	ret
-; 58e3
-
-Function58e3: ; 58e3
-	ld hl, OBJECT_MAP_OBJECT_INDEX
-	add hl, bc
-	ld a, [hl]
-	cp -1
-	jp z, Function5903 ; a jr would have been appropriate here
-	push bc
-	call GetMapObject
-	ld hl, MAPOBJECT_MOVEMENT
-	add hl, bc
-	ld a, [hl]
-	pop bc
-	ld hl, OBJECT_MOVEMENTTYPE
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_00
-	ret
-; 5903
-
-Function5903: ; 5903
-	call GetSpriteDirection
-	rrca
-	rrca
-	ld e, a
-	ld d, 0
-	ld hl, .standing_movefns
-	add hl, de
-	ld a, [hl]
-	ld hl, OBJECT_MOVEMENTTYPE
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_00
-	ret
-
-.standing_movefns
-	db SPRITEMOVEDATA_STANDING_DOWN
-	db SPRITEMOVEDATA_STANDING_UP
-	db SPRITEMOVEDATA_STANDING_LEFT
-	db SPRITEMOVEDATA_STANDING_RIGHT
-; 5920
-
-_UpdateSprites:: ; 5920
-	ld a, [wVramState]
-	bit 0, a
-	ret z
-	xor a
-	ld [hUsedSpriteIndex], a
-	ld a, [hOAMUpdate]
-	push af
-	ld a, 1
-	ld [hOAMUpdate], a
-	call InitSprites
-	call .fill
-	pop af
-	ld [hOAMUpdate], a
-	ret
-
-.fill
-	ld a, [wVramState]
-	bit 1, a
-	ld b, LOW(wVirtualOAMEnd)
-	jr z, .ok
-	ld b, 28 * SPRITEOAMSTRUCT_LENGTH
-.ok
-	ld a, [hUsedSpriteIndex]
-	cp b
-	ret nc
-	ld l, a
-	ld h, HIGH(wVirtualOAM)
-	ld de, SPRITEOAMSTRUCT_LENGTH
-	ld a, b
-	ld c, SCREEN_HEIGHT_PX + 2 * TILE_WIDTH
-.loop
-	ld [hl], c ; y
-	add hl, de
-	cp l
-	jr nz, .loop
-	ret
-; 5958
-
-ApplyBGMapAnchorToObjects: ; 5958
-	push hl
-	push de
-	push bc
-	ld a, [wPlayerBGMapOffsetX]
-	ld d, a
-	ld a, [wPlayerBGMapOffsetY]
-	ld e, a
-	ld bc, wObjectStructs
-	ld a, NUM_OBJECT_STRUCTS
-.loop
-	push af
-	call DoesObjectHaveASprite
-	jr z, .skip
-	ld hl, OBJECT_SPRITE_X
-	add hl, bc
-	ld a, [hl]
-	add d
-	ld [hl], a
-	ld hl, OBJECT_SPRITE_Y
-	add hl, bc
-	ld a, [hl]
-	add e
-	ld [hl], a
-.skip
-	ld hl, OBJECT_STRUCT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	pop af
-	dec a
-	jr nz, .loop
-	xor a
-	ld [wPlayerBGMapOffsetX], a
-	ld [wPlayerBGMapOffsetY], a
-	pop bc
-	pop de
-	pop hl
-	ret
-; 5991
-
-
-PRIORITY_LOW  EQU $10
-PRIORITY_NORM EQU $20
-PRIORITY_HIGH EQU $30
-
-InitSprites: ; 5991
-	call .DeterminePriorities
-	ld c, PRIORITY_HIGH
-	call .InitSpritesByPriority
-	ld c, PRIORITY_NORM
-	call .InitSpritesByPriority
-	ld c, PRIORITY_LOW
-	call .InitSpritesByPriority
-	ret
-
-.DeterminePriorities:
-	xor a
-	ld hl, wMovementPointer
-	ld bc, NUM_OBJECT_STRUCTS
-	call ByteFill
-	ld d, 0
-	ld bc, wObjectStructs
-	ld hl, wMovementPointer
-.loop
-	push hl
-	call DoesObjectHaveASprite
-	jr z, .skip
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld a, [hl]
-	cp STANDING
-	jr z, .skip
-; Define the sprite priority.
-	ld e, PRIORITY_LOW
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	bit LOW_PRIORITY, [hl]
-	jr nz, .add
-	ld e, PRIORITY_NORM
-	bit HIGH_PRIORITY, [hl]
-	jr z, .add
-	ld e, PRIORITY_HIGH
-	jr .add
-
-.skip
-	ld hl, OBJECT_STRUCT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	pop hl
-	jr .next
-
-.add
-	ld hl, OBJECT_STRUCT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	pop hl
-	ld a, d
-	or e
-	ld [hli], a
-.next
-	inc d
-	ld a, d
-	cp NUM_OBJECT_STRUCTS
-	jr nz, .loop
-	ret
-
-.InitSpritesByPriority:
-	ld hl, wMovementPointer
-.next_sprite
-	ld a, [hli]
-	ld d, a
-	and $f0
-	ret z
-	cp c
-	jr nz, .next_sprite
-	push bc
-	push hl
-	ld a, d
-	and $f
-	call .GetObjectStructPointer
-	call .InitSprite
-	pop hl
-	pop bc
-	jr .next_sprite
-
-.InitSprite:
-	ld hl, OBJECT_SPRITE_TILE
-	add hl, bc
-	ld a, [hl]
-	and %01111111
-	ld [hFFC1], a
-	xor a
-	bit 7, [hl]
-	jr nz, .skip1
-	or %00001000
-.skip1
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	ld e, [hl]
-	bit 7, e
-	jr z, .skip2
-	or %10000000
-.skip2
-	bit 4, e
-	jr z, .skip3
-	or %00010000
-.skip3
-	ld hl, OBJECT_PALETTE
-	add hl, bc
-	ld d, a
-	ld a, [hl]
-	and %00000111
-	or d
-	ld d, a
-	xor a
-	bit 3, e
-	jr z, .skip4
-	or %10000000
-.skip4
-	ld [hFFC2], a
-	ld hl, OBJECT_SPRITE_X
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_SPRITE_X_OFFSET
-	add hl, bc
-	add [hl]
-	add 8
-	ld e, a
-	ld a, [wPlayerBGMapOffsetX]
-	add e
-	ld [hFFBF], a
-	ld hl, OBJECT_SPRITE_Y
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_SPRITE_Y_OFFSET
-	add hl, bc
-	add [hl]
-	add 12
-	ld e, a
-	ld a, [wPlayerBGMapOffsetY]
-	add e
-	ld [hFFC0], a
-	ld hl, OBJECT_FACING_STEP
-	add hl, bc
-	ld a, [hl]
-	cp STANDING
-	jp z, .done
-	cp NUM_FACINGS
-	jp nc, .done
-	ld l, a
-	ld h, 0
-	add hl, hl
-	ld bc, Facings
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [hUsedSpriteIndex]
-	ld c, a
-	ld b, HIGH(wVirtualOAM)
-	ld a, [hli]
-	ld [hUsedSpriteTile], a
-	add c
-	cp LOW(wVirtualOAMEnd)
-	jr nc, .full
-.addsprite
-	ld a, [hFFC0]
-	add [hl]
-	inc hl
-	ld [bc], a ; y
-	inc c
-	ld a, [hFFBF]
-	add [hl]
-	inc hl
-	ld [bc], a ; x
-	inc c
-	ld e, [hl]
-	inc hl
-	ld a, [hFFC1]
-	bit 2, e
-	jr z, .nope1
-	xor a
-.nope1
-	add [hl]
-	inc hl
-	ld [bc], a ; tile id
-	inc c
-	ld a, e
-	bit 1, a
-	jr z, .nope2
-	ld a, [hFFC2]
-	or e
-.nope2
-	and OBP_NUM | X_FLIP | Y_FLIP | PRIORITY
-	or d
-	ld [bc], a ; attributes
-	inc c
-	ld a, [hUsedSpriteTile]
-	dec a
-	ld [hUsedSpriteTile], a
-	jr nz, .addsprite
-	ld a, c
-	ld [hUsedSpriteIndex], a
-.done
-	xor a
-	ret
-
-.full
-	scf
-	ret
-
-.GetObjectStructPointer:
-	ld c, a
-	ld b, 0
-	ld hl, .Addresses
-	add hl, bc
-	add hl, bc
-	ld c, [hl]
-	inc hl
-	ld b, [hl]
-	ret
-
-.Addresses: ; 5ace
-	dw wPlayerStruct
-	dw wObject1Struct
-	dw wObject2Struct
-	dw wObject3Struct
-	dw wObject4Struct
-	dw wObject5Struct
-	dw wObject6Struct
-	dw wObject7Struct
-	dw wObject8Struct
-	dw wObject9Struct
-	dw wObject10Struct
-	dw wObject11Struct
-	dw wObject12Struct
-; 5ae8
--- a/engine/map_objects_2.asm
+++ /dev/null
@@ -1,70 +1,0 @@
-LoadObjectMasks: ; 2454f
-	ld hl, wObjectMasks
-	xor a
-	ld bc, NUM_OBJECTS
-	call ByteFill
-	nop
-	ld bc, wMapObjects
-	ld de, wObjectMasks
-	xor a
-.loop
-	push af
-	push bc
-	push de
-	call GetObjectTimeMask
-	jr c, .next
-	call CheckObjectFlag
-.next
-	pop de
-	ld [de], a
-	inc de
-	pop bc
-	ld hl, OBJECT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	pop af
-	inc a
-	cp NUM_OBJECTS
-	jr nz, .loop
-	ret
-
-CheckObjectFlag: ; 2457d (9:457d)
-	ld hl, MAPOBJECT_SPRITE
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .masked
-	ld hl, MAPOBJECT_EVENT_FLAG
-	add hl, bc
-	ld a, [hli]
-	ld e, a
-	ld a, [hl]
-	ld d, a
-	cp -1
-	jr nz, .check
-	ld a, e
-	cp -1
-	jr z, .unmasked
-	jr .masked
-.check
-	ld b, CHECK_FLAG
-	call EventFlagAction
-	ld a, c
-	and a
-	jr nz, .masked
-.unmasked
-	xor a
-	ret
-
-.masked
-	ld a, -1
-	scf
-	ret
-
-GetObjectTimeMask: ; 245a7 (9:45a7)
-	call CheckObjectTime
-	ld a, -1
-	ret c
-	xor a
-	ret
--- a/engine/map_palettes.asm
+++ /dev/null
@@ -1,86 +1,0 @@
-SwapTextboxPalettes:: ; 4c000
-	hlcoord 0, 0
-	decoord 0, 0, wAttrMap
-	ld b, SCREEN_HEIGHT
-.loop
-	push bc
-	ld c, SCREEN_WIDTH
-.innerloop
-	ld a, [hl]
-	push hl
-	srl a
-	jr c, .UpperNybble
-	ld hl, wTilesetPalettes
-	add [hl]
-	ld l, a
-	ld a, [wTilesetPalettes + 1]
-	adc 0
-	ld h, a
-	ld a, [hl]
-	and $f
-	jr .next
-
-.UpperNybble:
-	ld hl, wTilesetPalettes
-	add [hl]
-	ld l, a
-	ld a, [wTilesetPalettes + 1]
-	adc 0
-	ld h, a
-	ld a, [hl]
-	swap a
-	and $f
-
-.next
-	pop hl
-	ld [de], a
-	res 7, [hl]
-	inc hl
-	inc de
-	dec c
-	jr nz, .innerloop
-	pop bc
-	dec b
-	jr nz, .loop
-	ret
-
-ScrollBGMapPalettes:: ; 4c03f
-	ld hl, wBGMapBuffer
-	ld de, wBGMapPalBuffer
-.loop
-	ld a, [hl]
-	push hl
-	srl a
-	jr c, .UpperNybble
-
-; .LowerNybble
-	ld hl, wTilesetPalettes
-	add [hl]
-	ld l, a
-	ld a, [wTilesetPalettes + 1]
-	adc 0
-	ld h, a
-	ld a, [hl]
-	and $f
-	jr .next
-
-.UpperNybble:
-	ld hl, wTilesetPalettes
-	add [hl]
-	ld l, a
-	ld a, [wTilesetPalettes + 1]
-	adc 0
-	ld h, a
-	ld a, [hl]
-	swap a
-	and $f
-
-.next
-	pop hl
-	ld [de], a
-	res 7, [hl]
-	inc hl
-	inc de
-	dec c
-	jr nz, .loop
-	ret
--- a/engine/map_setup.asm
+++ /dev/null
@@ -1,260 +1,0 @@
-RunMapSetupScript:: ; 15363
-	ld a, [hMapEntryMethod]
-	and $f
-	dec a
-	ld c, a
-	ld b, 0
-	ld hl, MapSetupScripts
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	call ReadMapSetupScript
-	ret
-; 15377
-
-INCLUDE "data/maps/setup_scripts.asm"
-
-ReadMapSetupScript: ; 1541d
-.loop
-	ld a, [hli]
-	cp -1
-	ret z
-
-	push hl
-
-	ld c, a
-	ld b, 0
-	ld hl, MapSetupCommands
-	add hl, bc
-	add hl, bc
-	add hl, bc
-
-	; bank
-	ld b, [hl]
-	inc hl
-
-	; address
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-
-	; Bit 7 of the bank indicates a parameter.
-	; This is left unused.
-	bit 7, b
-	jr z, .go
-
-	pop de
-	ld a, [de]
-	ld c, a
-	inc de
-	push de
-
-.go
-	ld a, b
-	and $7f
-	rst FarCall
-
-	pop hl
-	jr .loop
-; 15440
-
-MapSetupCommands: ; 15440
-; entries correspond to command indexes in constants/map_setup_constants.asm
-	dba EnableLCD ; 00
-	dba DisableLCD ; 01
-	dba MapSetup_Sound_Off ; 02
-	dba PlayMapMusic ; 03
-	dba RestartMapMusic ; 04
-	dba FadeToMapMusic ; 05
-	dba RotatePalettesRightMapAndMusic ; 06
-	dba EnterMapMusic ; 07
-	dba ForceMapMusic ; 08
-	dba FadeInMusic ; 09
-	dba LoadBlockData ; 0a (callback 1)
-	dba LoadNeighboringBlockData ; 0b
-	dba SaveScreen ; 0c
-	dba BufferScreen ; 0d
-	dba LoadGraphics ; 0e
-	dba LoadTileset ; 0f
-	dba LoadMapTimeOfDay ; 10
-	dba LoadMapPalettes ; 11
-	dba LoadWildMonData ; 12
-	dba RefreshMapSprites ; 13
-	dba HandleNewMap ; 14
-	dba InitCommandQueue ; 15
-	dba LoadObjectsRunCallback_02 ; 16
-	dba LoadSpawnPoint ; 17
-	dba EnterMapConnection ; 18
-	dba LoadWarpData ; 19
-	dba LoadMapAttributes ; 1a
-	dba LoadMapAttributes_SkipPeople ; 1b
-	dba ClearBGPalettes ; 1c
-	dba FadeOutPalettes ; 1d
-	dba FadeInPalettes ; 1e
-	dba GetCoordOfUpperLeftCorner ; 1f
-	dba RestoreFacingAfterWarp ; 20
-	dba SpawnInFacingDown ; 21
-	dba SpawnPlayer ; 22
-	dba RefreshPlayerCoords ; 23
-	dba DelayClearingOldSprites ; 24
-	dba DelayLoadingNewSprites ; 25
-	dba UpdateRoamMons ; 26
-	dba JumpRoamMons ; 27
-	dba FadeOldMapMusic ; 28
-	dba ActivateMapAnims ; 29
-	dba SuspendMapAnims ; 2a
-	dba RetainOldPalettes ; 2b
-	dba DontScrollText ; 2c
-	dba ReturnFromMapSetupScript ; 2d
-; 154ca
-
-
-DontScrollText: ; 154ca
-	xor a
-	ld [wDisableTextAcceleration], a
-	ret
-; 154cf
-
-ActivateMapAnims: ; 154cf
-	ld a, $1
-	ld [hMapAnims], a
-	ret
-; 154d3
-
-SuspendMapAnims: ; 154d3
-	xor a
-	ld [hMapAnims], a
-	ret
-; 154d7
-
-LoadObjectsRunCallback_02: ; 154d7
-	ld a, MAPCALLBACK_OBJECTS
-	call RunMapCallback
-	farcall LoadObjectMasks
-	farcall InitializeVisibleSprites
-	ret
-; 154ea (5:54ea)
-
-; unused
-	ret
-; 154eb
-
-DelayClearingOldSprites: ; 154eb
-	ld hl, wPlayerSpriteSetupFlags
-	set PLAYERSPRITESETUP_RESET_ACTION_F, [hl]
-	ret
-; 154f1
-
-DelayLoadingNewSprites: ; 154f1
-	ld hl, wPlayerSpriteSetupFlags
-	set PLAYERSPRITESETUP_SKIP_RELOAD_GFX_F, [hl]
-	ret
-
-CheckReplaceKrisSprite: ; 154f7
-	nop
-	call .CheckBiking
-	jr c, .ok
-	call .CheckSurfing
-	jr c, .ok
-	call .CheckSurfing2
-	jr c, .ok
-	ret
-
-.ok
-	call ReplaceKrisSprite
-	ret
-
-.CheckBiking: ; 1550c (5:550c)
-	and a
-	ld hl, wBikeFlags
-	bit BIKEFLAGS_ALWAYS_ON_BIKE_F, [hl]
-	ret z
-	ld a, PLAYER_BIKE
-	ld [wPlayerState], a
-	scf
-	ret
-
-.CheckSurfing2: ; 1551a (5:551a)
-	ld a, [wPlayerState]
-	cp PLAYER_NORMAL
-	jr z, .nope
-	cp PLAYER_SKATE
-	jr z, .nope
-	cp PLAYER_SURF
-	jr z, .surfing
-	cp PLAYER_SURF_PIKA
-	jr z, .surfing
-	call GetMapEnvironment
-	cp INDOOR
-	jr z, .checkbiking
-	cp ENVIRONMENT_5
-	jr z, .checkbiking
-	cp DUNGEON
-	jr z, .checkbiking
-	jr .nope
-.checkbiking
-	ld a, [wPlayerState]
-	cp PLAYER_BIKE
-	jr nz, .nope
-.surfing
-	ld a, PLAYER_NORMAL
-	ld [wPlayerState], a
-	scf
-	ret
-
-.nope
-	and a
-	ret
-
-.CheckSurfing: ; 1554e (5:554e)
-	call CheckOnWater
-	jr nz, .ret_nc
-	ld a, [wPlayerState]
-	cp PLAYER_SURF
-	jr z, ._surfing
-	cp PLAYER_SURF_PIKA
-	jr z, ._surfing
-	ld a, PLAYER_SURF
-	ld [wPlayerState], a
-._surfing
-	scf
-	ret
-.ret_nc
-	and a
-	ret
-; 15567
-
-FadeOldMapMusic: ; 15567
-	ld a, 6
-	call SkipMusic
-	ret
-; 1556d
-
-RetainOldPalettes: ; 1556d
-	farcall _UpdateTimePals
-	ret
-
-RotatePalettesRightMapAndMusic: ; 15574
-	ld e, 0
-	ld a, [wMusicFadeID]
-	ld d, 0
-	ld a, [wMusicFadeID + 1]
-	ld a, $4
-	ld [wMusicFade], a
-	call RotateThreePalettesRight
-	ret
-; 15587
-
-ForceMapMusic: ; 15587
-	ld a, [wPlayerState]
-	cp PLAYER_BIKE
-	jr nz, .notbiking
-	call VolumeOff
-	ld a, $88
-	ld [wMusicFade], a
-.notbiking
-	call TryRestartMapMusic
-	ret
-; 1559a
--- a/engine/mapgroup_roofs.asm
+++ /dev/null
@@ -1,20 +1,0 @@
-LoadMapGroupRoof:: ; 1c000
-	ld a, [wMapGroup]
-	ld e, a
-	ld d, 0
-	ld hl, MapGroupRoofs
-	add hl, de
-	ld a, [hl]
-	cp -1
-	ret z
-	ld hl, Roofs
-	ld bc, 9 tiles
-	call AddNTimes
-	ld de, vTiles2 tile $0a
-	ld bc, 9 tiles
-	call CopyBytes
-	ret
-; 1c021
-
-
-INCLUDE "data/maps/roofs.asm"
--- a/engine/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/math.asm
+++ /dev/null
@@ -1,196 +1,0 @@
-_Multiply:: ; 66de
-
-; hMultiplier is one byte.
-	ld a, 8
-	ld b, a
-
-	xor a
-	ld [hProduct], a
-	ld [hMathBuffer + 1], a
-	ld [hMathBuffer + 2], a
-	ld [hMathBuffer + 3], a
-	ld [hMathBuffer + 4], a
-
-
-.loop
-	ld a, [hMultiplier]
-	srl a
-	ld [hMultiplier], a
-	jr nc, .next
-
-	ld a, [hMathBuffer + 4]
-	ld c, a
-	ld a, [hMultiplicand + 2]
-	add c
-	ld [hMathBuffer + 4], a
-
-	ld a, [hMathBuffer + 3]
-	ld c, a
-	ld a, [hMultiplicand + 1]
-	adc c
-	ld [hMathBuffer + 3], a
-
-	ld a, [hMathBuffer + 2]
-	ld c, a
-	ld a, [hMultiplicand + 0]
-	adc c
-	ld [hMathBuffer + 2], a
-
-	ld a, [hMathBuffer + 1]
-	ld c, a
-	ld a, [hProduct]
-	adc c
-	ld [hMathBuffer + 1], a
-
-.next
-	dec b
-	jr z, .done
-
-
-; hMultiplicand <<= 1
-
-	ld a, [hMultiplicand + 2]
-	add a
-	ld [hMultiplicand + 2], a
-
-	ld a, [hMultiplicand + 1]
-	rla
-	ld [hMultiplicand + 1], a
-
-	ld a, [hMultiplicand + 0]
-	rla
-	ld [hMultiplicand + 0], a
-
-	ld a, [hProduct]
-	rla
-	ld [hProduct], a
-
-	jr .loop
-
-
-.done
-	ld a, [hMathBuffer + 4]
-	ld [hProduct + 3], a
-
-	ld a, [hMathBuffer + 3]
-	ld [hProduct + 2], a
-
-	ld a, [hMathBuffer + 2]
-	ld [hProduct + 1], a
-
-	ld a, [hMathBuffer + 1]
-	ld [hProduct + 0], a
-
-	ret
-; 673e
-
-
-_Divide:: ; 673e
-	xor a
-	ld [hMathBuffer + 0], a
-	ld [hMathBuffer + 1], a
-	ld [hMathBuffer + 2], a
-	ld [hMathBuffer + 3], a
-	ld [hMathBuffer + 4], a
-
-	ld a, 9
-	ld e, a
-
-.loop
-	ld a, [hMathBuffer + 0]
-	ld c, a
-	ld a, [hDividend + 1]
-	sub c
-	ld d, a
-
-	ld a, [hDivisor]
-	ld c, a
-	ld a, [hDividend + 0]
-	sbc c
-	jr c, .next
-
-	ld [hDividend + 0], a
-
-	ld a, d
-	ld [hDividend + 1], a
-
-	ld a, [hMathBuffer + 4]
-	inc a
-	ld [hMathBuffer + 4], a
-
-	jr .loop
-
-.next
-	ld a, b
-	cp 1
-	jr z, .done
-
-	ld a, [hMathBuffer + 4]
-	add a
-	ld [hMathBuffer + 4], a
-
-	ld a, [hMathBuffer + 3]
-	rla
-	ld [hMathBuffer + 3], a
-
-	ld a, [hMathBuffer + 2]
-	rla
-	ld [hMathBuffer + 2], a
-
-	ld a, [hMathBuffer + 1]
-	rla
-	ld [hMathBuffer + 1], a
-
-	dec e
-	jr nz, .next2
-
-	ld e, 8
-	ld a, [hMathBuffer + 0]
-	ld [hDivisor], a
-	xor a
-	ld [hMathBuffer + 0], a
-
-	ld a, [hDividend + 1]
-	ld [hDividend + 0], a
-
-	ld a, [hDividend + 2]
-	ld [hDividend + 1], a
-
-	ld a, [hDividend + 3]
-	ld [hDividend + 2], a
-
-.next2
-	ld a, e
-	cp 1
-	jr nz, .okay
-	dec b
-
-.okay
-	ld a, [hDivisor]
-	srl a
-	ld [hDivisor], a
-
-	ld a, [hMathBuffer + 0]
-	rr a
-	ld [hMathBuffer + 0], a
-
-	jr .loop
-
-.done
-	ld a, [hDividend + 1]
-	ld [hDivisor], a
-
-	ld a, [hMathBuffer + 4]
-	ld [hDividend + 3], a
-
-	ld a, [hMathBuffer + 3]
-	ld [hDividend + 2], a
-
-	ld a, [hMathBuffer + 2]
-	ld [hDividend + 1], a
-
-	ld a, [hMathBuffer + 1]
-	ld [hDividend + 0], a
-
-	ret
-; 67c1
--- a/engine/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
--- /dev/null
+++ b/engine/menu/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/menu/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/menu/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/menu/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/menu/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/menu/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/menu/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/menu/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/menu/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/menu/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/menu/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/menu/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/menu/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/menu/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/menu/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
--- /dev/null
+++ b/engine/menu/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/menu/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"
--- a/engine/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/mon_icons.asm
+++ /dev/null
@@ -1,471 +1,0 @@
-LoadOverworldMonIcon: ; 8e82b
-	ld a, e
-	call ReadMonMenuIcon
-	ld l, a
-	ld h, 0
-	add hl, hl
-	ld de, IconPointers
-	add hl, de
-	ld a, [hli]
-	ld e, a
-	ld d, [hl]
-	ld b, BANK(Icons)
-	ld c, 8
-	ret
-; 8e83f
-
-LoadMenuMonIcon: ; 8e83f
-	push hl
-	push de
-	push bc
-	call .LoadIcon
-	pop bc
-	pop de
-	pop hl
-	ret
-; 8e849
-
-.LoadIcon: ; 8e849
-	ld d, 0
-	ld hl, .Jumptable
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-; 8e854
-
-
-.Jumptable: ; 8e854 (23:6854)
-	dw PartyMenu_InitAnimatedMonIcon ; party menu
-	dw NamingScreen_InitAnimatedMonIcon ; naming screen
-	dw MoveList_InitAnimatedMonIcon ; moves (?)
-	dw Trade_LoadMonIconGFX ; trade
-	dw Mobile_InitAnimatedMonIcon ; mobile
-	dw Mobile_InitPartyMenuBGPal71 ; mobile
-	dw .GetPartyMenuMonIcon ; unused
-
-.GetPartyMenuMonIcon: ; 8e862 (23:6862)
-	call InitPartyMenuIcon
-	call .GetPartyMonItemGFX
-	call SetPartyMonIconAnimSpeed
-	ret
-
-.GetPartyMonItemGFX: ; 8e86c (23:686c)
-	push bc
-	ld a, [hObjectStructIndexBuffer]
-	ld hl, wPartyMon1Item
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	pop bc
-	ld a, [hl]
-	and a
-	jr z, .no_item
-	push hl
-	push bc
-	ld d, a
-	callfar ItemIsMail
-	pop bc
-	pop hl
-	jr c, .not_mail
-	ld a, $6
-	jr .got_tile
-.not_mail
-	ld a, $5
-	; jr .got_tile
-
-.no_item
-	ld a, $4
-.got_tile
-	ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
-	add hl, bc
-	ld [hl], a
-	ret
-
-Mobile_InitAnimatedMonIcon: ; 8e898 (23:6898)
-	call PartyMenu_InitAnimatedMonIcon
-	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
-	add hl, bc
-	ld a, SPRITE_ANIM_SEQ_NULL
-	ld [hl], a
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld a, 9 * 8
-	ld [hl], a
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	ld a, 9 * 8
-	ld [hl], a
-	ret
-
-Mobile_InitPartyMenuBGPal71: ; 8e8b1 (23:68b1)
-	call InitPartyMenuIcon
-	call SetPartyMonIconAnimSpeed
-	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
-	add hl, bc
-	ld a, SPRITE_ANIM_SEQ_NULL
-	ld [hl], a
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld a, 3 * 8
-	ld [hl], a
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	ld a, 12 * 8
-	ld [hl], a
-	ld a, c
-	ld [wc608], a
-	ld a, b
-	ld [wc608 + 1], a
-	ret
-
-PartyMenu_InitAnimatedMonIcon: ; 8e8d5 (23:68d5)
-	call InitPartyMenuIcon
-	call .SpawnItemIcon
-	call SetPartyMonIconAnimSpeed
-	ret
-
-.SpawnItemIcon: ; 8e8df (23:68df)
-	push bc
-	ld a, [hObjectStructIndexBuffer]
-	ld hl, wPartyMon1Item
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	pop bc
-	ld a, [hl]
-	and a
-	ret z
-	push hl
-	push bc
-	ld d, a
-	callfar ItemIsMail
-	pop bc
-	pop hl
-	jr c, .mail
-	ld a, SPRITE_ANIM_FRAMESET_PARTY_MON_WITH_ITEM
-	jr .okay
-
-.mail
-	ld a, SPRITE_ANIM_FRAMESET_PARTY_MON_WITH_MAIL
-.okay
-	ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
-	add hl, bc
-	ld [hl], a
-	ret
-
-InitPartyMenuIcon: ; 8e908 (23:6908)
-	ld a, [wCurIconTile]
-	push af
-	ld a, [hObjectStructIndexBuffer]
-	ld hl, wPartySpecies
-	ld e, a
-	ld d, $0
-	add hl, de
-	ld a, [hl]
-	call ReadMonMenuIcon
-	ld [wCurIcon], a
-	call GetMemIconGFX
-	ld a, [hObjectStructIndexBuffer]
-; y coord
-	add a
-	add a
-	add a
-	add a
-	add $1c
-	ld d, a
-; x coord
-	ld e, $10
-; type is partymon icon
-	ld a, SPRITE_ANIM_INDEX_PARTY_MON
-	call InitSpriteAnimStruct
-	pop af
-	ld hl, SPRITEANIMSTRUCT_TILE_ID
-	add hl, bc
-	ld [hl], a
-	ret
-
-SetPartyMonIconAnimSpeed: ; 8e936 (23:6936)
-	push bc
-	ld a, [hObjectStructIndexBuffer]
-	ld b, a
-	call .getspeed
-	ld a, b
-	pop bc
-	ld hl, SPRITEANIMSTRUCT_DURATIONOFFSET
-	add hl, bc
-	ld [hl], a
-	rlca
-	rlca
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld [hl], a
-	ret
-
-.getspeed ; 8e94c (23:694c)
-	farcall PlacePartymonHPBar
-	call GetHPPal
-	ld e, d
-	ld d, 0
-	ld hl, .speeds
-	add hl, de
-	ld b, [hl]
-	ret
-; 8e95e (23:695e)
-
-.speeds ; 8e95e
-	db $00 ; HP_GREEN
-	db $40 ; HP_YELLOW
-	db $80 ; HP_RED
-; 8e961
-
-NamingScreen_InitAnimatedMonIcon: ; 8e961 (23:6961)
-	ld a, [wd265]
-	call ReadMonMenuIcon
-	ld [wCurIcon], a
-	xor a
-	call GetIconGFX
-	depixel 4, 4, 4, 0
-	ld a, SPRITE_ANIM_INDEX_PARTY_MON
-	call InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
-	add hl, bc
-	ld [hl], SPRITE_ANIM_SEQ_NULL
-	ret
-
-MoveList_InitAnimatedMonIcon: ; 8e97d (23:697d)
-	ld a, [wd265]
-	call ReadMonMenuIcon
-	ld [wCurIcon], a
-	xor a
-	call GetIconGFX
-	ld d, 3 * 8 + 2 ; depixel 3, 4, 2, 4
-	ld e, 4 * 8 + 4
-	ld a, SPRITE_ANIM_INDEX_PARTY_MON
-	call InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
-	add hl, bc
-	ld [hl], SPRITE_ANIM_SEQ_NULL
-	ret
-
-Trade_LoadMonIconGFX: ; 8e99a (23:699a)
-	ld a, [wd265]
-	call ReadMonMenuIcon
-	ld [wCurIcon], a
-	ld a, $62
-	ld [wCurIconTile], a
-	call GetMemIconGFX
-	ret
-
-GetSpeciesIcon: ; 8e9ac
-; Load species icon into VRAM at tile a
-	push de
-	ld a, [wd265]
-	call ReadMonMenuIcon
-	ld [wCurIcon], a
-	pop de
-	ld a, e
-	call GetIconGFX
-	ret
-; 8e9bc
-
-
-FlyFunction_GetMonIcon: ; 8e9bc (23:69bc)
-	push de
-	ld a, [wd265]
-	call ReadMonMenuIcon
-	ld [wCurIcon], a
-	pop de
-	ld a, e
-	call GetIcon_a
-	ret
-; 8e9cc (23:69cc)
-
-Unreferenced_GetMonIcon2: ; 8e9cc
-	push de
-	ld a, [wd265]
-	call ReadMonMenuIcon
-	ld [wCurIcon], a
-	pop de
-	call GetIcon_de
-	ret
-; 8e9db
-
-GetMemIconGFX: ; 8e9db (23:69db)
-	ld a, [wCurIconTile]
-GetIconGFX: ; 8e9de
-	call GetIcon_a
-	ld de, 8 tiles
-	add hl, de
-	ld de, HeldItemIcons
-	lb bc, BANK(HeldItemIcons), 2
-	call GetGFXUnlessMobile
-	ld a, [wCurIconTile]
-	add 10
-	ld [wCurIconTile], a
-	ret
-
-HeldItemIcons:
-INCBIN "gfx/icons/mail.2bpp"
-INCBIN "gfx/icons/item.2bpp"
-; 8ea17
-
-GetIcon_de: ; 8ea17
-; Load icon graphics into VRAM starting from tile de.
-	ld l, e
-	ld h, d
-	jr GetIcon
-
-GetIcon_a: ; 8ea1b
-; Load icon graphics into VRAM starting from tile a.
-	ld l, a
-	ld h, 0
-
-GetIcon: ; 8ea1e
-; Load icon graphics into VRAM starting from tile hl.
-
-; One tile is 16 bytes long.
-rept 4
-	add hl, hl
-endr
-
-	ld de, vTiles0
-	add hl, de
-	push hl
-
-; The icons are contiguous, in order and of the same
-; size, so the pointer table is somewhat redundant.
-	ld a, [wCurIcon]
-	push hl
-	ld l, a
-	ld h, 0
-	add hl, hl
-	ld de, IconPointers
-	add hl, de
-	ld a, [hli]
-	ld e, a
-	ld d, [hl]
-	pop hl
-
-	lb bc, BANK(Icons), 8
-	call GetGFXUnlessMobile
-
-	pop hl
-	ret
-; 8ea3f
-
-GetGFXUnlessMobile: ; 8ea3f
-	ld a, [wLinkMode]
-	cp LINK_MOBILE
-	jp nz, Request2bpp
-	jp Get2bpp_2
-; 8ea4a
-
-FreezeMonIcons: ; 8ea4a
-	ld hl, wSpriteAnimationStructs
-	ld e, PARTY_LENGTH
-	ld a, [wMenuCursorY]
-	ld d, a
-.loop
-	ld a, [hl]
-	and a
-	jr z, .next
-	cp d
-	jr z, .loadwithtwo
-	ld a, SPRITE_ANIM_SEQ_NULL
-	jr .ok
-
-.loadwithtwo
-	ld a, SPRITE_ANIM_SEQ_PARTY_MON_SWITCH
-
-.ok
-	push hl
-	ld c, l
-	ld b, h
-	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
-	add hl, bc
-	ld [hl], a
-	pop hl
-
-.next
-	ld bc, $10
-	add hl, bc
-	dec e
-	jr nz, .loop
-	ret
-; 8ea71
-
-UnfreezeMonIcons: ; 8ea71
-	ld hl, wSpriteAnimationStructs
-	ld e, PARTY_LENGTH
-.loop
-	ld a, [hl]
-	and a
-	jr z, .next
-	push hl
-	ld c, l
-	ld b, h
-	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
-	add hl, bc
-	ld [hl], SPRITE_ANIM_SEQ_PARTY_MON
-	pop hl
-.next
-	ld bc, $10
-	add hl, bc
-	dec e
-	jr nz, .loop
-	ret
-; 8ea8c (23:6a8c)
-
-HoldSwitchmonIcon: ; 8ea8c
-	ld hl, wSpriteAnimationStructs
-	ld e, PARTY_LENGTH
-	ld a, [wSwitchMon]
-	ld d, a
-.loop
-	ld a, [hl]
-	and a
-	jr z, .next
-	cp d
-	jr z, .is_switchmon
-	ld a, SPRITE_ANIM_SEQ_PARTY_MON_SELECTED
-	jr .join_back
-
-.is_switchmon
-	ld a, SPRITE_ANIM_SEQ_PARTY_MON_SWITCH
-.join_back
-	push hl
-	ld c, l
-	ld b, h
-	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
-	add hl, bc
-	ld [hl], a
-	pop hl
-.next
-	ld bc, $10
-	add hl, bc
-	dec e
-	jr nz, .loop
-	ret
-
-ReadMonMenuIcon: ; 8eab3
-	cp EGG
-	jr z, .egg
-	dec a
-	ld hl, MonMenuIcons
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld a, [hl]
-	ret
-.egg
-	ld a, ICON_EGG
-	ret
-; 8eac4
-
-
-INCLUDE "data/pokemon/menu_icons.asm"
-
-INCLUDE "data/icon_pointers.asm"
-
-INCLUDE "gfx/icons.asm"
--- a/engine/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/mon_stats.asm
+++ /dev/null
@@ -1,485 +1,0 @@
-DrawPlayerHP: ; 50b0a
-	ld a, $1
-	jr DrawHP
-
-DrawEnemyHP: ; 50b0e
-	ld a, $2
-
-DrawHP: ; 50b10
-	ld [wWhichHPBar], a
-	push hl
-	push bc
-	; box mons have full HP
-	ld a, [wMonType]
-	cp BOXMON
-	jr z, .at_least_1_hp
-
-	ld a, [wTempMonHP]
-	ld b, a
-	ld a, [wTempMonHP + 1]
-	ld c, a
-
-; Any HP?
-	or b
-	jr nz, .at_least_1_hp
-
-	xor a
-	ld c, a
-	ld e, a
-	ld a, 6
-	ld d, a
-	jp .fainted
-
-.at_least_1_hp
-	ld a, [wTempMonMaxHP]
-	ld d, a
-	ld a, [wTempMonMaxHP + 1]
-	ld e, a
-	ld a, [wMonType]
-	cp BOXMON
-	jr nz, .not_boxmon
-
-	ld b, d
-	ld c, e
-
-.not_boxmon
-	predef ComputeHPBarPixels
-	ld a, 6
-	ld d, a
-	ld c, a
-
-.fainted
-	ld a, c
-	pop bc
-	ld c, a
-	pop hl
-	push de
-	push hl
-	push hl
-	call DrawBattleHPBar
-	pop hl
-
-; Print HP
-	bccoord 1, 1, 0
-	add hl, bc
-	ld de, wTempMonHP
-	ld a, [wMonType]
-	cp BOXMON
-	jr nz, .not_boxmon_2
-	ld de, wTempMonMaxHP
-.not_boxmon_2
-	lb bc, 2, 3
-	call PrintNum
-
-	ld a, "/"
-	ld [hli], a
-
-; Print max HP
-	ld de, wTempMonMaxHP
-	lb bc, 2, 3
-	call PrintNum
-	pop hl
-	pop de
-	ret
-
-PrintTempMonStats: ; 50b7b
-; Print wTempMon's stats at hl, with spacing bc.
-	push bc
-	push hl
-	ld de, .StatNames
-	call PlaceString
-	pop hl
-	pop bc
-	add hl, bc
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld de, wTempMonAttack
-	lb bc, 2, 3
-	call .PrintStat
-	ld de, wTempMonDefense
-	call .PrintStat
-	ld de, wTempMonSpclAtk
-	call .PrintStat
-	ld de, wTempMonSpclDef
-	call .PrintStat
-	ld de, wTempMonSpeed
-	jp PrintNum
-
-.PrintStat: ; 50bab
-	push hl
-	call PrintNum
-	pop hl
-	ld de, SCREEN_WIDTH * 2
-	add hl, de
-	ret
-
-.StatNames: ; 50bb5
-	db   "ATTACK"
-	next "DEFENSE"
-	next "SPCL.ATK"
-	next "SPCL.DEF"
-	next "SPEED"
-	next "@"
-
-GetGender: ; 50bdd
-; Return the gender of a given monster (wCurPartyMon/wCurOTMon/wCurWildMon).
-; When calling this function, a should be set to an appropriate wMonType value.
-
-; return values:
-; a = 1: f = nc|nz; male
-; a = 0: f = nc|z;  female
-;        f = c:  genderless
-
-; This is determined by comparing the Attack and Speed DVs
-; with the species' gender ratio.
-
-; Figure out what type of monster struct we're looking at.
-
-; 0: PartyMon
-	ld hl, wPartyMon1DVs
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, [wMonType]
-	and a
-	jr z, .PartyMon
-
-; 1: OTPartyMon
-	ld hl, wOTPartyMon1DVs
-	dec a
-	jr z, .PartyMon
-
-; 2: sBoxMon
-	ld hl, sBoxMon1DVs
-	ld bc, BOXMON_STRUCT_LENGTH
-	dec a
-	jr z, .sBoxMon
-
-; 3: Unknown
-	ld hl, wTempMonDVs
-	dec a
-	jr z, .DVs
-
-; else: WildMon
-	ld hl, wEnemyMonDVs
-	jr .DVs
-
-; Get our place in the party/box.
-
-.PartyMon:
-.sBoxMon
-	ld a, [wCurPartyMon]
-	call AddNTimes
-
-.DVs:
-
-; sBoxMon data is read directly from SRAM.
-	ld a, [wMonType]
-	cp BOXMON
-	ld a, BANK(sBox)
-	call z, GetSRAMBank
-
-; Attack DV
-	ld a, [hli]
-	and $f0
-	ld b, a
-; Speed DV
-	ld a, [hl]
-	and $f0
-	swap a
-
-; Put our DVs together.
-	or b
-	ld b, a
-
-; Close SRAM if we were dealing with a sBoxMon.
-	ld a, [wMonType]
-	cp BOXMON
-	call z, CloseSRAM
-
-; We need the gender ratio to do anything with this.
-	push bc
-	ld a, [wCurPartySpecies]
-	dec a
-	ld hl, BaseData + BASE_GENDER
-	ld bc, BASE_DATA_SIZE
-	call AddNTimes
-	pop bc
-
-	ld a, BANK(BaseData)
-	call GetFarByte
-
-; The higher the ratio, the more likely the monster is to be female.
-
-	cp GENDERLESS
-	jr z, .Genderless
-
-	and a ; GENDER_F0?
-	jr z, .Male
-
-	cp GENDER_F100
-	jr z, .Female
-
-; Values below the ratio are male, and vice versa.
-	cp b
-	jr c, .Male
-
-.Female:
-	xor a
-	ret
-
-.Male:
-	ld a, 1
-	and a
-	ret
-
-.Genderless:
-	scf
-	ret
-
-ListMovePP: ; 50c50
-	ld a, [wNumMoves]
-	inc a
-	ld c, a
-	ld a, NUM_MOVES
-	sub c
-	ld b, a
-	push hl
-	ld a, [wBuffer1]
-	ld e, a
-	ld d, $0
-	ld a, $3e ; P
-	call .load_loop
-	ld a, b
-	and a
-	jr z, .skip
-	ld c, a
-	ld a, "-"
-	call .load_loop
-
-.skip
-	pop hl
-	inc hl
-	inc hl
-	inc hl
-	ld d, h
-	ld e, l
-	ld hl, wTempMonMoves
-	ld b, 0
-.loop
-	ld a, [hli]
-	and a
-	jr z, .done
-	push bc
-	push hl
-	push de
-	ld hl, wMenuCursorY
-	ld a, [hl]
-	push af
-	ld [hl], b
-	push hl
-	callfar GetMaxPPOfMove
-	pop hl
-	pop af
-	ld [hl], a
-	pop de
-	pop hl
-	push hl
-	ld bc, wTempMonPP - (wTempMonMoves + 1)
-	add hl, bc
-	ld a, [hl]
-	and $3f
-	ld [wStringBuffer1 + 4], a
-	ld h, d
-	ld l, e
-	push hl
-	ld de, wStringBuffer1 + 4
-	lb bc, 1, 2
-	call PrintNum
-	ld a, "/"
-	ld [hli], a
-	ld de, wd265
-	lb bc, 1, 2
-	call PrintNum
-	pop hl
-	ld a, [wBuffer1]
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld d, h
-	ld e, l
-	pop hl
-	pop bc
-	inc b
-	ld a, b
-	cp NUM_MOVES
-	jr nz, .loop
-
-.done
-	ret
-
-.load_loop ; 50cc9
-	ld [hli], a
-	ld [hld], a
-	add hl, de
-	dec c
-	jr nz, .load_loop
-	ret
-
-Unreferenced_Function50cd0: ; 50cd0
-.loop
-	ld [hl], $32
-	inc hl
-	ld [hl], $3e
-	dec hl
-	add hl, de
-	dec c
-	jr nz, .loop
-	ret
-
-Unused_PlaceEnemyHPLevel:
-	push hl
-	push hl
-	ld hl, wPartyMonNicknames
-	ld a, [wCurPartyMon]
-	call GetNick
-	pop hl
-	call PlaceString
-	call CopyMonToTempMon
-	pop hl
-	ld a, [wCurPartySpecies]
-	cp EGG
-	jr z, .egg
-	push hl
-	ld bc, -12
-	add hl, bc
-	ld b, $0
-	call DrawEnemyHP
-	pop hl
-	ld bc, 5
-	add hl, bc
-	push de
-	call PrintLevel
-	pop de
-
-.egg
-	ret
-
-PlaceStatusString: ; 50d0a
-	push de
-	inc de
-	inc de
-	ld a, [de]
-	ld b, a
-	inc de
-	ld a, [de]
-	or b
-	pop de
-	jr nz, PlaceNonFaintStatus
-	push de
-	ld de, FntString
-	call CopyStatusString
-	pop de
-	ld a, $1
-	and a
-	ret
-
-FntString: ; 50d22
-	db "FNT@"
-
-CopyStatusString: ; 50d25
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	ld [hl], a
-	ret
-
-PlaceNonFaintStatus: ; 50d2e
-	push de
-	ld a, [de]
-	ld de, PsnString
-	bit PSN, a
-	jr nz, .place
-	ld de, BrnString
-	bit BRN, a
-	jr nz, .place
-	ld de, FrzString
-	bit FRZ, a
-	jr nz, .place
-	ld de, ParString
-	bit PAR, a
-	jr nz, .place
-	ld de, SlpString
-	and SLP
-	jr z, .no_status
-
-.place
-	call CopyStatusString
-	ld a, $1
-	and a
-
-.no_status
-	pop de
-	ret
-
-SlpString: db "SLP@"
-PsnString: db "PSN@"
-BrnString: db "BRN@"
-FrzString: db "FRZ@"
-ParString: db "PAR@"
-
-ListMoves: ; 50d6f
-; List moves at hl, spaced every [wBuffer1] tiles.
-	ld de, wListMoves_MoveIndicesBuffer
-	ld b, $0
-.moves_loop
-	ld a, [de]
-	inc de
-	and a
-	jr z, .no_more_moves
-	push de
-	push hl
-	push hl
-	ld [wCurSpecies], a
-	ld a, MOVE_NAME
-	ld [wNamedObjectTypeBuffer], a
-	call GetName
-	ld de, wStringBuffer1
-	pop hl
-	push bc
-	call PlaceString
-	pop bc
-	ld a, b
-	ld [wNumMoves], a
-	inc b
-	pop hl
-	push bc
-	ld a, [wBuffer1]
-	ld c, a
-	ld b, 0
-	add hl, bc
-	pop bc
-	pop de
-	ld a, b
-	cp NUM_MOVES
-	jr z, .done
-	jr .moves_loop
-
-.no_more_moves
-	ld a, b
-.nonmove_loop
-	push af
-	ld [hl], "-"
-	ld a, [wBuffer1]
-	ld c, a
-	ld b, 0
-	add hl, bc
-	pop af
-	inc a
-	cp NUM_MOVES
-	jr nz, .nonmove_loop
-
-.done
-	ret
--- a/engine/move_mon.asm
+++ /dev/null
@@ -1,1845 +1,0 @@
-TryAddMonToParty: ; d88c
-; Check if to copy wild mon or generate a new one
-	; Whose is it?
-	ld de, wPartyCount
-	ld a, [wMonType]
-	and $f
-	jr z, .getpartylocation ; PARTYMON
-	ld de, wOTPartyCount
-
-.getpartylocation
-	; Do we have room for it?
-	ld a, [de]
-	inc a
-	cp PARTY_LENGTH + 1
-	ret nc
-	; Increase the party count
-	ld [de], a
-	ld a, [de] ; Why are we doing this?
-	ld [hMoveMon], a ; HRAM backup
-	add e
-	ld e, a
-	jr nc, .loadspecies
-	inc d
-
-.loadspecies
-	; Load the species of the Pokemon into the party list.
-	; The terminator is usually here, but it'll be back.
-	ld a, [wCurPartySpecies]
-	ld [de], a
-	; Load the terminator into the next slot.
-	inc de
-	ld a, -1
-	ld [de], a
-	; Now let's load the OT name.
-	ld hl, wPartyMonOT
-	ld a, [wMonType]
-	and $f
-	jr z, .loadOTname
-	ld hl, wOTPartyMonOT
-
-.loadOTname
-	ld a, [hMoveMon] ; Restore index from backup
-	dec a
-	call SkipNames
-	ld d, h
-	ld e, l
-	ld hl, wPlayerName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	; Only initialize the nickname for party mon
-	ld a, [wMonType]
-	and a
-	jr nz, .skipnickname
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	call GetPokemonName
-	ld hl, wPartyMonNicknames
-	ld a, [hMoveMon]
-	dec a
-	call SkipNames
-	ld d, h
-	ld e, l
-	ld hl, wStringBuffer1
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-
-.skipnickname
-	ld hl, wPartyMon1Species
-	ld a, [wMonType]
-	and $f
-	jr z, .initializeStats
-	ld hl, wOTPartyMon1Species
-
-.initializeStats
-	ld a, [hMoveMon]
-	dec a
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-GeneratePartyMonStats: ; d906
-; wBattleMode specifies whether it's a wild mon or not.
-; wMonType specifies whether it's an opposing mon or not.
-; wCurPartySpecies/wCurPartyLevel specify the species and level.
-; hl points to the wPartyMon struct to fill.
-
-	ld e, l
-	ld d, h
-	push hl
-
-	; Initialize the species
-	ld a, [wCurPartySpecies]
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld a, [wBaseDexNo]
-	ld [de], a
-	inc de
-
-	; Copy the item if it's a wild mon
-	ld a, [wBattleMode]
-	and a
-	ld a, $0
-	jr z, .skipitem
-	ld a, [wEnemyMonItem]
-.skipitem
-	ld [de], a
-	inc de
-
-	; Copy the moves if it's a wild mon
-	push de
-	ld h, d
-	ld l, e
-	ld a, [wBattleMode]
-	and a
-	jr z, .randomlygeneratemoves
-	ld a, [wMonType]
-	and a
-	jr nz, .randomlygeneratemoves
-	ld de, wEnemyMonMoves
-	rept NUM_MOVES + -1
-	ld a, [de]
-	inc de
-	ld [hli], a
-	endr
-	ld a, [de]
-	ld [hl], a
-	jr .next
-
-.randomlygeneratemoves
-	xor a
-	rept NUM_MOVES + -1
-	ld [hli], a
-	endr
-	ld [hl], a
-	ld [wBuffer1], a
-	predef FillMoves
-
-.next
-	pop de
-rept NUM_MOVES
-	inc de
-endr
-
-	; Initialize ID.
-	ld a, [wPlayerID]
-	ld [de], a
-	inc de
-	ld a, [wPlayerID + 1]
-	ld [de], a
-	inc de
-
-	; Initialize Exp.
-	push de
-	ld a, [wCurPartyLevel]
-	ld d, a
-	callfar CalcExpAtLevel
-	pop de
-	ld a, [hProduct + 1]
-	ld [de], a
-	inc de
-	ld a, [hProduct + 2]
-	ld [de], a
-	inc de
-	ld a, [hProduct + 3]
-	ld [de], a
-	inc de
-
-	; Initialize stat experience.
-	xor a
-	ld b, MON_DVS - MON_STAT_EXP
-.loop
-	ld [de], a
-	inc de
-	dec b
-	jr nz, .loop
-
-	pop hl
-	push hl
-	ld a, [wMonType]
-	and $f
-	jr z, .registerpokedex
-
-	push hl
-	farcall GetTrainerDVs
-	pop hl
-	jr .initializeDVs
-
-.registerpokedex
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	dec a
-	push de
-	call CheckCaughtMon
-	ld a, [wd265]
-	dec a
-	call SetSeenAndCaughtMon
-	pop de
-
-	pop hl
-	push hl
-	ld a, [wBattleMode]
-	and a
-	jr nz, .copywildmonDVs
-
-	call Random
-	ld b, a
-	call Random
-	ld c, a
-.initializeDVs
-	ld a, b
-	ld [de], a
-	inc de
-	ld a, c
-	ld [de], a
-	inc de
-
-	; Initialize PP.
-	push hl
-	push de
-	inc hl
-	inc hl
-	call FillPP
-	pop de
-	pop hl
-rept 4
-	inc de
-endr
-
-	; Initialize happiness.
-	ld a, BASE_HAPPINESS
-	ld [de], a
-	inc de
-
-	xor a
-	; PokerusStatus
-	ld [de], a
-	inc de
-	; CaughtData/CaughtTime/CaughtLevel
-	ld [de], a
-	inc de
-	; CaughtGender/CaughtLocation
-	ld [de], a
-	inc de
-
-	; Initialize level.
-	ld a, [wCurPartyLevel]
-	ld [de], a
-	inc de
-
-	xor a
-	; Status
-	ld [de], a
-	inc de
-	; Unused
-	ld [de], a
-	inc de
-
-	; Initialize HP.
-	ld bc, MON_STAT_EXP - 1
-	add hl, bc
-	ld a, 1
-	ld c, a
-	ld b, FALSE
-	call CalcMonStatC
-	ld a, [hProduct + 2]
-	ld [de], a
-	inc de
-	ld a, [hProduct + 3]
-	ld [de], a
-	inc de
-	jr .initstats
-
-.copywildmonDVs
-	ld a, [wEnemyMonDVs]
-	ld [de], a
-	inc de
-	ld a, [wEnemyMonDVs + 1]
-	ld [de], a
-	inc de
-
-	push hl
-	ld hl, wEnemyMonPP
-	ld b, NUM_MOVES
-.wildmonpploop
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec b
-	jr nz, .wildmonpploop
-	pop hl
-
-	; Initialize happiness.
-	ld a, BASE_HAPPINESS
-	ld [de], a
-	inc de
-
-	xor a
-	; PokerusStatus
-	ld [de], a
-	inc de
-	; CaughtData/CaughtTime/CaughtLevel
-	ld [de], a
-	inc de
-	; CaughtGender/CaughtLocation
-	ld [de], a
-	inc de
-
-	; Initialize level.
-	ld a, [wCurPartyLevel]
-	ld [de], a
-	inc de
-
-	ld hl, wEnemyMonStatus
-	; Copy wEnemyMonStatus
-	ld a, [hli]
-	ld [de], a
-	inc de
-	; Copy EnemyMonUnused
-	ld a, [hli]
-	ld [de], a
-	inc de
-	; Copy wEnemyMonHP
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-	inc de
-
-.initstats
-	ld a, [wBattleMode]
-	dec a
-	jr nz, .generatestats
-	ld hl, wEnemyMonMaxHP
-	ld bc, PARTYMON_STRUCT_LENGTH - MON_MAXHP
-	call CopyBytes
-	pop hl
-	jr .registerunowndex
-
-.generatestats
-	pop hl
-	ld bc, MON_STAT_EXP - 1
-	add hl, bc
-	ld b, FALSE
-	call CalcMonStats
-
-.registerunowndex
-	ld a, [wMonType]
-	and $f
-	jr nz, .done
-	ld a, [wCurPartySpecies]
-	cp UNOWN
-	jr nz, .done
-	ld hl, wPartyMon1DVs
-	ld a, [wPartyCount]
-	dec a
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	predef GetUnownLetter
-	callfar UpdateUnownDex
-
-.done
-	scf ; When this function returns, the carry flag indicates success vs failure.
-	ret
-; da6d
-
-FillPP: ; da6d
-	push bc
-	ld b, NUM_MOVES
-.loop
-	ld a, [hli]
-	and a
-	jr z, .next
-	dec a
-	push hl
-	push de
-	push bc
-	ld hl, Moves
-	ld bc, MOVE_LENGTH
-	call AddNTimes
-	ld de, wStringBuffer1
-	ld a, BANK(Moves)
-	call FarCopyBytes
-	pop bc
-	pop de
-	pop hl
-	ld a, [wStringBuffer1 + MOVE_PP]
-
-.next
-	ld [de], a
-	inc de
-	dec b
-	jr nz, .loop
-	pop bc
-	ret
-; da96
-
-AddTempmonToParty: ; da96
-	ld hl, wPartyCount
-	ld a, [hl]
-	cp PARTY_LENGTH
-	scf
-	ret z
-
-	inc a
-	ld [hl], a
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [wCurPartySpecies]
-	ld [hli], a
-	ld [hl], $ff
-
-	ld hl, wPartyMon1Species
-	ld a, [wPartyCount]
-	dec a
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld e, l
-	ld d, h
-	ld hl, wTempMonSpecies
-	call CopyBytes
-
-	ld hl, wPartyMonOT
-	ld a, [wPartyCount]
-	dec a
-	call SkipNames
-	ld d, h
-	ld e, l
-	ld hl, wOTPartyMonOT
-	ld a, [wCurPartyMon]
-	call SkipNames
-	ld bc, NAME_LENGTH
-	call CopyBytes
-
-	ld hl, wPartyMonNicknames
-	ld a, [wPartyCount]
-	dec a
-	call SkipNames
-	ld d, h
-	ld e, l
-	ld hl, wOTPartyMonNicknames
-	ld a, [wCurPartyMon]
-	call SkipNames
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-
-	ld a, [wCurPartySpecies]
-	ld [wNamedObjectIndexBuffer], a
-	cp EGG
-	jr z, .egg
-	dec a
-	call SetSeenAndCaughtMon
-	ld hl, wPartyMon1Happiness
-	ld a, [wPartyCount]
-	dec a
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld [hl], BASE_HAPPINESS
-.egg
-
-	ld a, [wCurPartySpecies]
-	cp UNOWN
-	jr nz, .done
-	ld hl, wPartyMon1DVs
-	ld a, [wPartyCount]
-	dec a
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	predef GetUnownLetter
-	callfar UpdateUnownDex
-	ld a, [wFirstUnownSeen]
-	and a
-	jr nz, .done
-	ld a, [wUnownLetter]
-	ld [wFirstUnownSeen], a
-.done
-
-	and a
-	ret
-
-SendGetMonIntoFromBox: ; db3f
-; Sents/Gets mon into/from Box depending on Parameter
-; wPokemonWithdrawDepositParameter == 0: get mon into Party
-; wPokemonWithdrawDepositParameter == 1: sent mon into Box
-; wPokemonWithdrawDepositParameter == 2: get mon from DayCare
-; wPokemonWithdrawDepositParameter == 3: put mon into DayCare
-
-	ld a, BANK(sBoxCount)
-	call GetSRAMBank
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	jr z, .check_IfPartyIsFull
-	cp DAY_CARE_WITHDRAW
-	jr z, .check_IfPartyIsFull
-	cp DAY_CARE_DEPOSIT
-	ld hl, wBreedMon1Species
-	jr z, .breedmon
-
-	; we want to sent a mon into the Box
-	; so check if there's enough space
-	ld hl, sBoxCount
-	ld a, [hl]
-	cp MONS_PER_BOX
-	jr nz, .there_is_room
-	jp CloseSRAM_And_SetCarryFlag
-
-.check_IfPartyIsFull
-	ld hl, wPartyCount
-	ld a, [hl]
-	cp PARTY_LENGTH
-	jp z, CloseSRAM_And_SetCarryFlag
-
-.there_is_room
-	inc a
-	ld [hl], a
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [wPokemonWithdrawDepositParameter]
-	cp DAY_CARE_WITHDRAW
-	ld a, [wBreedMon1Species]
-	jr z, .okay1
-	ld a, [wCurPartySpecies]
-
-.okay1
-	ld [hli], a
-	ld [hl], $ff
-	ld a, [wPokemonWithdrawDepositParameter]
-	dec a
-	ld hl, wPartyMon1Species
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, [wPartyCount]
-	jr nz, .okay2
-	ld hl, sBoxMon1Species
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, [sBoxCount]
-
-.okay2
-	dec a ; wPartyCount - 1
-	call AddNTimes
-
-.breedmon
-	push hl
-	ld e, l
-	ld d, h
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	ld hl, sBoxMon1Species
-	ld bc, BOXMON_STRUCT_LENGTH
-	jr z, .okay3
-	cp DAY_CARE_WITHDRAW
-	ld hl, wBreedMon1Species
-	jr z, .okay4
-	ld hl, wPartyMon1Species
-	ld bc, PARTYMON_STRUCT_LENGTH
-
-.okay3
-	ld a, [wCurPartyMon]
-	call AddNTimes
-
-.okay4
-	ld bc, BOXMON_STRUCT_LENGTH
-	call CopyBytes
-	ld a, [wPokemonWithdrawDepositParameter]
-	cp DAY_CARE_DEPOSIT
-	ld de, wBreedMon1OT
-	jr z, .okay5
-	dec a
-	ld hl, wPartyMonOT
-	ld a, [wPartyCount]
-	jr nz, .okay6
-	ld hl, sBoxMonOT
-	ld a, [sBoxCount]
-
-.okay6
-	dec a
-	call SkipNames
-	ld d, h
-	ld e, l
-
-.okay5
-	ld hl, sBoxMonOT
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	jr z, .okay7
-	ld hl, wBreedMon1OT
-	cp DAY_CARE_WITHDRAW
-	jr z, .okay8
-	ld hl, wPartyMonOT
-
-.okay7
-	ld a, [wCurPartyMon]
-	call SkipNames
-
-.okay8
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ld a, [wPokemonWithdrawDepositParameter]
-	cp DAY_CARE_DEPOSIT
-	ld de, wBreedMon1Nick
-	jr z, .okay9
-	dec a
-	ld hl, wPartyMonNicknames
-	ld a, [wPartyCount]
-	jr nz, .okay10
-	ld hl, sBoxMonNicknames
-	ld a, [sBoxCount]
-
-.okay10
-	dec a
-	call SkipNames
-	ld d, h
-	ld e, l
-
-.okay9
-	ld hl, sBoxMonNicknames
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	jr z, .okay11
-	ld hl, wBreedMon1Nick
-	cp DAY_CARE_WITHDRAW
-	jr z, .okay12
-	ld hl, wPartyMonNicknames
-
-.okay11
-	ld a, [wCurPartyMon]
-	call SkipNames
-
-.okay12
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-	pop hl
-
-	ld a, [wPokemonWithdrawDepositParameter]
-	cp PC_DEPOSIT
-	jr z, .took_out_of_box
-	cp DAY_CARE_DEPOSIT
-	jp z, .CloseSRAM_And_ClearCarryFlag
-
-	push hl
-	srl a
-	add $2
-	ld [wMonType], a
-	predef CopyMonToTempMon
-	callfar CalcLevel
-	ld a, d
-	ld [wCurPartyLevel], a
-	pop hl
-
-	ld b, h
-	ld c, l
-	ld hl, MON_LEVEL
-	add hl, bc
-	ld [hl], a
-	ld hl, MON_MAXHP
-	add hl, bc
-	ld d, h
-	ld e, l
-	ld hl, MON_STAT_EXP - 1
-	add hl, bc
-
-	push bc
-	ld b, TRUE
-	call CalcMonStats
-	pop bc
-
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	jr nz, .CloseSRAM_And_ClearCarryFlag
-	ld hl, MON_STATUS
-	add hl, bc
-	xor a
-	ld [hl], a
-	ld hl, MON_HP
-	add hl, bc
-	ld d, h
-	ld e, l
-	ld a, [wCurPartySpecies]
-	cp EGG
-	jr z, .egg
-	inc hl
-	inc hl
-	ld a, [hli]
-	ld [de], a
-	ld a, [hl]
-	inc de
-	ld [de], a
-	jr .CloseSRAM_And_ClearCarryFlag
-
-.egg
-	xor a
-	ld [de], a
-	inc de
-	ld [de], a
-	jr .CloseSRAM_And_ClearCarryFlag
-
-.took_out_of_box
-	ld a, [sBoxCount]
-	dec a
-	ld b, a
-	call RestorePPofDepositedPokemon
-.CloseSRAM_And_ClearCarryFlag:
-	call CloseSRAM
-	and a
-	ret
-; dcb1
-
-CloseSRAM_And_SetCarryFlag: ; dcb1
-	call CloseSRAM
-	scf
-	ret
-; dcb6
-
-RestorePPofDepositedPokemon: ; dcb6
-	ld a, b
-	ld hl, sBoxMons
-	ld bc, BOXMON_STRUCT_LENGTH
-	call AddNTimes
-	ld b, h
-	ld c, l
-	ld hl, MON_PP
-	add hl, bc
-	push hl
-	push bc
-	ld de, wTempMonPP
-	ld bc, NUM_MOVES
-	call CopyBytes
-	pop bc
-	ld hl, MON_MOVES
-	add hl, bc
-	push hl
-	ld de, wTempMonMoves
-	ld bc, NUM_MOVES
-	call CopyBytes
-	pop hl
-	pop de
-
-	ld a, [wMenuCursorY]
-	push af
-	ld a, [wMonType]
-	push af
-	ld b, 0
-.loop
-	ld a, [hli]
-	and a
-	jr z, .done
-	ld [wTempMonMoves], a
-	ld a, BOXMON
-	ld [wMonType], a
-	ld a, b
-	ld [wMenuCursorY], a
-	push bc
-	push hl
-	push de
-	farcall GetMaxPPOfMove
-	pop de
-	pop hl
-	ld a, [wd265]
-	ld b, a
-	ld a, [de]
-	and %11000000
-	add b
-	ld [de], a
-	pop bc
-	inc de
-	inc b
-	ld a, b
-	cp NUM_MOVES
-	jr c, .loop
-
-.done
-	pop af
-	ld [wMonType], a
-	pop af
-	ld [wMenuCursorY], a
-	ret
-; dd21
-
-RetrieveMonFromDayCareMan: ; dd21
-	ld a, [wBreedMon1Species]
-	ld [wCurPartySpecies], a
-	ld de, SFX_TRANSACTION
-	call PlaySFX
-	call WaitSFX
-	call GetBreedMon1LevelGrowth
-	ld a, b
-	ld [wd002], a
-	ld a, e
-	ld [wCurPartyLevel], a
-	xor a
-	ld [wPokemonWithdrawDepositParameter], a
-	jp RetrieveBreedmon
-; dd42
-
-RetrieveMonFromDayCareLady: ; dd42
-	ld a, [wBreedMon2Species]
-	ld [wCurPartySpecies], a
-	ld de, SFX_TRANSACTION
-	call PlaySFX
-	call WaitSFX
-	call GetBreedMon2LevelGrowth
-	ld a, b
-	ld [wd002], a
-	ld a, e
-	ld [wCurPartyLevel], a
-	ld a, PC_DEPOSIT
-	ld [wPokemonWithdrawDepositParameter], a
-	jp RetrieveBreedmon
-; dd64
-
-RetrieveBreedmon: ; dd64
-	ld hl, wPartyCount
-	ld a, [hl]
-	cp PARTY_LENGTH
-	jr nz, .room_in_party
-	scf
-	ret
-
-.room_in_party
-	inc a
-	ld [hl], a
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	ld a, [wBreedMon1Species]
-	ld de, wBreedMon1Nick
-	jr z, .okay
-	ld a, [wBreedMon2Species]
-	ld de, wBreedMon2Nick
-
-.okay
-	ld [hli], a
-	ld [wCurSpecies], a
-	ld a, $ff
-	ld [hl], a
-	ld hl, wPartyMonNicknames
-	ld a, [wPartyCount]
-	dec a
-	call SkipNames
-	push hl
-	ld h, d
-	ld l, e
-	pop de
-	call CopyBytes
-	push hl
-	ld hl, wPartyMonOT
-	ld a, [wPartyCount]
-	dec a
-	call SkipNames
-	ld d, h
-	ld e, l
-	pop hl
-	call CopyBytes
-	push hl
-	call GetLastPartyMon
-	pop hl
-	ld bc, BOXMON_STRUCT_LENGTH
-	call CopyBytes
-	call GetBaseData
-	call GetLastPartyMon
-	ld b, d
-	ld c, e
-	ld hl, MON_LEVEL
-	add hl, bc
-	ld a, [wCurPartyLevel]
-	ld [hl], a
-	ld hl, MON_MAXHP
-	add hl, bc
-	ld d, h
-	ld e, l
-	ld hl, $a
-	add hl, bc
-	push bc
-	ld b, TRUE
-	call CalcMonStats
-	ld hl, wPartyMon1Moves
-	ld a, [wPartyCount]
-	dec a
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld d, h
-	ld e, l
-	ld a, $1
-	ld [wBuffer1], a
-	predef FillMoves
-	ld a, [wPartyCount]
-	dec a
-	ld [wCurPartyMon], a
-	farcall HealPartyMon
-	ld a, [wCurPartyLevel]
-	ld d, a
-	callfar CalcExpAtLevel
-	pop bc
-	ld hl, $8
-	add hl, bc
-	ld a, [hMultiplicand]
-	ld [hli], a
-	ld a, [hMultiplicand + 1]
-	ld [hli], a
-	ld a, [hMultiplicand + 2]
-	ld [hl], a
-	and a
-	ret
-; de1a
-
-GetLastPartyMon: ; de1a
-	ld a, [wPartyCount]
-	dec a
-	ld hl, wPartyMon1Species
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld d, h
-	ld e, l
-	ret
-; de2a
-
-DepositMonWithDayCareMan: ; de2a
-	ld de, wBreedMon1Nick
-	call DepositBreedmon
-	xor a ; REMOVE_PARTY
-	ld [wPokemonWithdrawDepositParameter], a
-	jp RemoveMonFromPartyOrBox
-; de37
-
-DepositMonWithDayCareLady: ; de37
-	ld de, wBreedMon2Nick
-	call DepositBreedmon
-	xor a ; REMOVE_PARTY
-	ld [wPokemonWithdrawDepositParameter], a
-	jp RemoveMonFromPartyOrBox
-; de44
-
-DepositBreedmon: ; de44
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMonNicknames
-	call SkipNames
-	call CopyBytes
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMonOT
-	call SkipNames
-	call CopyBytes
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1Species
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld bc, BOXMON_STRUCT_LENGTH
-	jp CopyBytes
-
-SendMonIntoBox: ; de6e
-; Sends the mon into one of Bills Boxes
-; the data comes mainly from 'wEnemyMon:'
-	ld a, BANK(sBoxCount)
-	call GetSRAMBank
-	ld de, sBoxCount
-	ld a, [de]
-	cp MONS_PER_BOX
-	jp nc, .full
-	inc a
-	ld [de], a
-
-	ld a, [wCurPartySpecies]
-	ld [wCurSpecies], a
-	ld c, a
-.loop
-	inc de
-	ld a, [de]
-	ld b, a
-	ld a, c
-	ld c, b
-	ld [de], a
-	inc a
-	jr nz, .loop
-
-	call GetBaseData
-	call ShiftBoxMon
-
-	ld hl, wPlayerName
-	ld de, sBoxMonOT
-	ld bc, NAME_LENGTH
-	call CopyBytes
-
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	call GetPokemonName
-
-	ld de, sBoxMonNicknames
-	ld hl, wStringBuffer1
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-
-	ld hl, wEnemyMon
-	ld de, sBoxMon1
-	ld bc, 1 + 1 + NUM_MOVES ; species + item + moves
-	call CopyBytes
-
-	ld hl, wPlayerID
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-	inc de
-	push de
-	ld a, [wCurPartyLevel]
-	ld d, a
-	callfar CalcExpAtLevel
-	pop de
-	ld a, [hProduct + 1]
-	ld [de], a
-	inc de
-	ld a, [hProduct + 2]
-	ld [de], a
-	inc de
-	ld a, [hProduct + 3]
-	ld [de], a
-	inc de
-
-	; Set all 5 Experience Values to 0
-	xor a
-	ld b, 2 * 5
-.loop2
-	ld [de], a
-	inc de
-	dec b
-	jr nz, .loop2
-
-	ld hl, wEnemyMonDVs
-	ld b, 2 + NUM_MOVES ; DVs and PP ; wEnemyMonHappiness - wEnemyMonDVs
-.loop3
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec b
-	jr nz, .loop3
-
-	ld a, BASE_HAPPINESS
-	ld [de], a
-	inc de
-	xor a
-	ld [de], a
-	inc de
-	ld [de], a
-	inc de
-	ld [de], a
-	inc de
-	ld a, [wCurPartyLevel]
-	ld [de], a
-	ld a, [wCurPartySpecies]
-	dec a
-	call SetSeenAndCaughtMon
-	ld a, [wCurPartySpecies]
-	cp UNOWN
-	jr nz, .not_unown
-	ld hl, sBoxMon1DVs
-	predef GetUnownLetter
-	callfar UpdateUnownDex
-
-.not_unown
-	ld hl, sBoxMon1Moves
-	ld de, wTempMonMoves
-	ld bc, NUM_MOVES
-	call CopyBytes
-
-	ld hl, sBoxMon1PP
-	ld de, wTempMonPP
-	ld bc, NUM_MOVES
-	call CopyBytes
-
-	ld b, 0
-	call RestorePPofDepositedPokemon
-
-	call CloseSRAM
-	scf
-	ret
-; df42
-
-.full ; df42
-	call CloseSRAM
-	and a
-	ret
-; df47
-
-ShiftBoxMon: ; df47
-	ld hl, sBoxMonOT
-	ld bc, NAME_LENGTH
-	call .shift
-
-	ld hl, sBoxMonNicknames
-	ld bc, MON_NAME_LENGTH
-	call .shift
-
-	ld hl, sBoxMons
-	ld bc, BOXMON_STRUCT_LENGTH
-
-.shift
-	ld a, [sBoxCount]
-	cp 2
-	ret c
-
-	push hl
-	call AddNTimes
-	dec hl
-	ld e, l
-	ld d, h
-	pop hl
-
-	ld a, [sBoxCount]
-	dec a
-	call AddNTimes
-	dec hl
-
-	push hl
-	ld a, [sBoxCount]
-	dec a
-	ld hl, 0
-	call AddNTimes
-	ld c, l
-	ld b, h
-	pop hl
-.loop
-	ld a, [hld]
-	ld [de], a
-	dec de
-	dec bc
-	ld a, c
-	or b
-	jr nz, .loop
-	ret
-; df8c
-
-GiveEgg:: ; df8c
-	ld a, [wCurPartySpecies]
-	push af
-	callfar GetPreEvolution
-	callfar GetPreEvolution
-	ld a, [wCurPartySpecies]
-	dec a
-
-; TryAddMonToParty sets Seen and Caught flags
-; when it is successful.  This routine will make
-; sure that we aren't newly setting flags.
-	push af
-	call CheckCaughtMon
-	pop af
-	push bc
-	call CheckSeenMon
-	push bc
-
-	call TryAddMonToParty
-
-; If we haven't caught this Pokemon before receiving
-; the Egg, reset the flag that was just set by
-; TryAddMonToParty.
-	pop bc
-	ld a, c
-	and a
-	jr nz, .skip_caught_flag
-	ld a, [wCurPartySpecies]
-	dec a
-	ld c, a
-	ld d, $0
-	ld hl, wPokedexCaught
-	ld b, RESET_FLAG
-	predef SmallFarFlagAction
-
-.skip_caught_flag
-; If we haven't seen this Pokemon before receiving
-; the Egg, reset the flag that was just set by
-; TryAddMonToParty.
-	pop bc
-	ld a, c
-	and a
-	jr nz, .skip_seen_flag
-	ld a, [wCurPartySpecies]
-	dec a
-	ld c, a
-	ld d, $0
-	ld hl, wPokedexSeen
-	ld b, RESET_FLAG
-	predef SmallFarFlagAction
-
-.skip_seen_flag
-	pop af
-	ld [wCurPartySpecies], a
-	ld a, [wPartyCount]
-	dec a
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld hl, wPartyMon1Species
-	call AddNTimes
-	ld a, [wCurPartySpecies]
-	ld [hl], a
-	ld hl, wPartyCount
-	ld a, [hl]
-	ld b, 0
-	ld c, a
-	add hl, bc
-	ld a, EGG
-	ld [hl], a
-	ld a, [wPartyCount]
-	dec a
-	ld hl, wPartyMonNicknames
-	call SkipNames
-	ld de, String_Egg
-	call CopyName2
-	ld a, [wPartyCount]
-	dec a
-	ld hl, wPartyMon1Happiness
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [wMonStatusFlags]
-	bit 1, a
-	ld a, 1
-	jr nz, .got_init_happiness
-	ld a, [wBaseEggSteps]
-
-.got_init_happiness
-	ld [hl], a
-	ld a, [wPartyCount]
-	dec a
-	ld hl, wPartyMon1HP
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	xor a
-	ld [hli], a
-	ld [hl], a
-	and a
-	ret
-; e035
-
-String_Egg: ; e035
-	db "EGG@"
-; e039
-
-RemoveMonFromPartyOrBox: ; e039
-	ld hl, wPartyCount
-
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	jr z, .okay
-
-	ld a, BANK(sBoxCount)
-	call GetSRAMBank
-	ld hl, sBoxCount
-
-.okay
-	ld a, [hl]
-	dec a
-	ld [hli], a
-	ld a, [wCurPartyMon]
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld e, l
-	ld d, h
-	inc de
-.loop
-	ld a, [de]
-	inc de
-	ld [hli], a
-	inc a
-	jr nz, .loop
-	ld hl, wPartyMonOT
-	ld d, PARTY_LENGTH - 1
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	jr z, .party
-	ld hl, sBoxMonOT
-	ld d, MONS_PER_BOX - 1
-
-.party
-	; If this is the last mon in our party (box),
-	; shift all the other mons up to close the gap.
-	ld a, [wCurPartyMon]
-	call SkipNames
-	ld a, [wCurPartyMon]
-	cp d
-	jr nz, .delete_inside
-	ld [hl], -1
-	jp .finish
-
-.delete_inside
-	; Shift the OT names
-	ld d, h
-	ld e, l
-	ld bc, MON_NAME_LENGTH
-	add hl, bc
-	ld bc, wPartyMonNicknames
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	jr z, .party2
-	ld bc, sBoxMonNicknames
-.party2
-	call CopyDataUntil
-	; Shift the struct
-	ld hl, wPartyMons
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	jr z, .party4
-	ld hl, sBoxMons
-	ld bc, BOXMON_STRUCT_LENGTH
-.party4
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld d, h
-	ld e, l
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	jr z, .party5
-	ld bc, BOXMON_STRUCT_LENGTH
-	add hl, bc
-	ld bc, sBoxMonOT
-	jr .copy
-
-.party5
-	ld bc, PARTYMON_STRUCT_LENGTH
-	add hl, bc
-	ld bc, wPartyMonOT
-.copy
-	call CopyDataUntil
-	; Shift the nicknames
-	ld hl, wPartyMonNicknames
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	jr z, .party6
-	ld hl, sBoxMonNicknames
-.party6
-	ld bc, MON_NAME_LENGTH
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld d, h
-	ld e, l
-	ld bc, MON_NAME_LENGTH
-	add hl, bc
-	ld bc, wPartyMonNicknamesEnd
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	jr z, .party7
-	ld bc, sBoxMonNicknamesEnd
-.party7
-	call CopyDataUntil
-	; Mail time!
-.finish
-	ld a, [wPokemonWithdrawDepositParameter]
-	and a
-	jp nz, CloseSRAM
-	ld a, [wLinkMode]
-	and a
-	ret nz
-	; Shift mail
-	ld a, BANK(sPartyMail)
-	call GetSRAMBank
-	; If this is the last mon in our party, no need to shift mail.
-	ld hl, wPartyCount
-	ld a, [wCurPartyMon]
-	cp [hl]
-	jr z, .close_sram
-	; Shift our mail messages up.
-	ld hl, sPartyMail
-	ld bc, MAIL_STRUCT_LENGTH
-	call AddNTimes
-	push hl
-	add hl, bc
-	pop de
-	ld a, [wCurPartyMon]
-	ld b, a
-.loop2
-	push bc
-	push hl
-	ld bc, MAIL_STRUCT_LENGTH
-	call CopyBytes
-	pop hl
-	push hl
-	ld bc, MAIL_STRUCT_LENGTH
-	add hl, bc
-	pop de
-	pop bc
-	inc b
-	ld a, [wPartyCount]
-	cp b
-	jr nz, .loop2
-.close_sram
-	jp CloseSRAM
-; e134
-
-
-ComputeNPCTrademonStats: ; e134
-	ld a, MON_LEVEL
-	call GetPartyParamLocation
-	ld a, [hl]
-	ld [MON_LEVEL], a ; wow
-	ld a, MON_SPECIES
-	call GetPartyParamLocation
-	ld a, [hl]
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld a, MON_MAXHP
-	call GetPartyParamLocation
-	ld d, h
-	ld e, l
-	push de
-	ld a, MON_STAT_EXP - 1
-	call GetPartyParamLocation
-	ld b, TRUE
-	call CalcMonStats
-	pop de
-	ld a, MON_HP
-	call GetPartyParamLocation
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	ld [hl], a
-	ret
-; e167
-
-CalcMonStats: ; e167
-; Calculates all 6 Stats of a mon
-; b: Take into account stat EXP if TRUE
-; 'c' counts from 1-6 and points with 'wBaseStats' to the base value
-; hl is the path to the Stat EXP
-; de points to where the final stats will be saved
-
-	ld c, $0
-.loop
-	inc c
-	call CalcMonStatC
-	ld a, [hMultiplicand + 1]
-	ld [de], a
-	inc de
-	ld a, [hMultiplicand + 2]
-	ld [de], a
-	inc de
-	ld a, c
-	cp STAT_SDEF
-	jr nz, .loop
-	ret
-; e17b
-
-CalcMonStatC: ; e17b
-; 'c' is 1-6 and points to the BaseStat
-; 1: HP
-; 2: Attack
-; 3: Defense
-; 4: Speed
-; 5: SpAtk
-; 6: SpDef
-	push hl
-	push de
-	push bc
-	ld a, b
-	ld d, a
-	push hl
-	ld hl, wBaseStats
-	dec hl ; has to be decreased, because 'c' begins with 1
-	ld b, $0
-	add hl, bc
-	ld a, [hl]
-	ld e, a
-	pop hl
-	push hl
-	ld a, c
-	cp STAT_SDEF
-	jr nz, .not_spdef
-	dec hl
-	dec hl
-
-.not_spdef
-	sla c
-	ld a, d
-	and a
-	jr z, .no_stat_exp
-	add hl, bc
-	push de
-	ld a, [hld]
-	ld e, a
-	ld d, [hl]
-	farcall GetSquareRoot
-	pop de
-
-.no_stat_exp
-	srl c
-	pop hl
-	push bc
-	ld bc, MON_DVS - MON_HP_EXP + 1
-	add hl, bc
-	pop bc
-	ld a, c
-	cp STAT_ATK
-	jr z, .Attack
-	cp STAT_DEF
-	jr z, .Defense
-	cp STAT_SPD
-	jr z, .Speed
-	cp STAT_SATK
-	jr z, .Special
-	cp STAT_SDEF
-	jr z, .Special
-; DV_HP = (DV_ATK & 1) << 3 + (DV_DEF & 1) << 2 + (DV_SPD & 1) << 1 + (DV_SPC & 1)
-	push bc
-	ld a, [hl]
-	swap a
-	and $1
-	add a
-	add a
-	add a
-	ld b, a
-	ld a, [hli]
-	and $1
-	add a
-	add a
-	add b
-	ld b, a
-	ld a, [hl]
-	swap a
-	and $1
-	add a
-	add b
-	ld b, a
-	ld a, [hl]
-	and $1
-	add b
-	pop bc
-	jr .GotDV
-
-.Attack:
-	ld a, [hl]
-	swap a
-	and $f
-	jr .GotDV
-
-.Defense:
-	ld a, [hl]
-	and $f
-	jr .GotDV
-
-.Speed:
-	inc hl
-	ld a, [hl]
-	swap a
-	and $f
-	jr .GotDV
-
-.Special:
-	inc hl
-	ld a, [hl]
-	and $f
-
-.GotDV:
-	ld d, 0
-	add e
-	ld e, a
-	jr nc, .no_overflow_1
-	inc d
-
-.no_overflow_1
-	sla e
-	rl d
-	srl b
-	srl b
-	ld a, b
-	add e
-	jr nc, .no_overflow_2
-	inc d
-
-.no_overflow_2
-	ld [hMultiplicand + 2], a
-	ld a, d
-	ld [hMultiplicand + 1], a
-	xor a
-	ld [hMultiplicand + 0], a
-	ld a, [wCurPartyLevel]
-	ld [hMultiplier], a
-	call Multiply
-	ld a, [hProduct + 1]
-	ld [hDividend + 0], a
-	ld a, [hProduct + 2]
-	ld [hDividend + 1], a
-	ld a, [hProduct + 3]
-	ld [hDividend + 2], a
-	ld a, 100
-	ld [hDivisor], a
-	ld a, 3
-	ld b, a
-	call Divide
-	ld a, c
-	cp STAT_HP
-	ld a, STAT_MIN_NORMAL
-	jr nz, .not_hp
-	ld a, [wCurPartyLevel]
-	ld b, a
-	ld a, [hQuotient + 2]
-	add b
-	ld [hMultiplicand + 2], a
-	jr nc, .no_overflow_3
-	ld a, [hQuotient + 1]
-	inc a
-	ld [hMultiplicand + 1], a
-
-.no_overflow_3
-	ld a, STAT_MIN_HP
-
-.not_hp
-	ld b, a
-	ld a, [hQuotient + 2]
-	add b
-	ld [hMultiplicand + 2], a
-	jr nc, .no_overflow_4
-	ld a, [hQuotient + 1]
-	inc a
-	ld [hMultiplicand + 1], a
-
-.no_overflow_4
-	ld a, [hQuotient + 1]
-	cp HIGH(MAX_STAT_VALUE + 1) + 1
-	jr nc, .max_stat
-	cp HIGH(MAX_STAT_VALUE + 1)
-	jr c, .stat_value_okay
-	ld a, [hQuotient + 2]
-	cp LOW(MAX_STAT_VALUE + 1)
-	jr c, .stat_value_okay
-
-.max_stat
-	ld a, HIGH(MAX_STAT_VALUE)
-	ld [hMultiplicand + 1], a
-	ld a, LOW(MAX_STAT_VALUE)
-	ld [hMultiplicand + 2], a
-
-.stat_value_okay
-	pop bc
-	pop de
-	pop hl
-	ret
-; e277
-
-GivePoke:: ; e277
-	push de
-	push bc
-	xor a ; PARTYMON
-	ld [wMonType], a
-	call TryAddMonToParty
-	jr nc, .failed
-	ld hl, wPartyMonNicknames
-	ld a, [wPartyCount]
-	dec a
-	ld [wCurPartyMon], a
-	call SkipNames
-	ld d, h
-	ld e, l
-	pop bc
-	ld a, b
-	ld b, 0
-	push bc
-	push de
-	push af
-	ld a, [wCurItem]
-	and a
-	jr z, .done
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1Item
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [wCurItem]
-	ld [hl], a
-	jr .done
-
-.failed
-	ld a, [wCurPartySpecies]
-	ld [wTempEnemyMonSpecies], a
-	callfar LoadEnemyMon
-	call SendMonIntoBox
-	jp nc, .FailedToGiveMon
-	ld a, BOXMON
-	ld [wMonType], a
-	xor a
-	ld [wCurPartyMon], a
-	ld de, wMonOrItemNameBuffer
-	pop bc
-	ld a, b
-	ld b, 1
-	push bc
-	push de
-	push af
-	ld a, [wCurItem]
-	and a
-	jr z, .done
-	ld a, [wCurItem]
-	ld [sBoxMon1Item], a
-
-.done
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	ld [wTempEnemyMonSpecies], a
-	call GetPokemonName
-	ld hl, wStringBuffer1
-	ld de, wMonOrItemNameBuffer
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-	pop af
-	and a
-	jp z, .wildmon
-	pop de
-	pop bc
-	pop hl
-	push bc
-	push hl
-	ld a, [wScriptBank]
-	call GetFarHalfword
-	ld bc, MON_NAME_LENGTH
-	ld a, [wScriptBank]
-	call FarCopyBytes
-	pop hl
-	inc hl
-	inc hl
-	ld a, [wScriptBank]
-	call GetFarHalfword
-	pop bc
-	ld a, b
-	and a
-	push de
-	push bc
-	jr nz, .send_to_box
-
-	push hl
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMonOT
-	call SkipNames
-	ld d, h
-	ld e, l
-	pop hl
-.otnameloop
-	ld a, [wScriptBank]
-	call GetFarByte
-	ld [de], a
-	inc hl
-	inc de
-	cp "@"
-	jr nz, .otnameloop
-	ld a, [wScriptBank]
-	call GetFarByte
-	ld b, a
-	push bc
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1ID
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, HIGH(01001)
-	ld [hli], a
-	ld [hl], LOW(01001)
-	pop bc
-	farcall SetGiftPartyMonCaughtData
-	jr .skip_nickname
-
-.send_to_box
-	ld a, BANK(sBoxMonOT)
-	call GetSRAMBank
-	ld de, sBoxMonOT
-.loop
-	ld a, [wScriptBank]
-	call GetFarByte
-	ld [de], a
-	inc hl
-	inc de
-	cp "@"
-	jr nz, .loop
-	ld a, [wScriptBank]
-	call GetFarByte
-	ld b, a
-	ld hl, sBoxMon1ID
-	call Random
-	ld [hli], a
-	call Random
-	ld [hl], a
-	call CloseSRAM
-	farcall SetGiftBoxMonCaughtData
-	jr .skip_nickname
-
-.wildmon
-	pop de
-	pop bc
-	push bc
-	push de
-	ld a, b
-	and a
-	jr z, .party
-	farcall SetBoxMonCaughtData
-	jr .set_caught_data
-
-.party
-	farcall SetCaughtData
-.set_caught_data
-	farcall GiveANickname_YesNo
-	pop de
-	jr c, .skip_nickname
-	call InitNickname
-
-.skip_nickname
-	pop bc
-	pop de
-	ld a, b
-	and a
-	ret z
-	ld hl, TextJump_WasSentToBillsPC
-	call PrintText
-	ld a, BANK(sBoxMonNicknames)
-	call GetSRAMBank
-	ld hl, wMonOrItemNameBuffer
-	ld de, sBoxMonNicknames
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-	call CloseSRAM
-	ld b, $1
-	ret
-; e3d4
-
-.FailedToGiveMon: ; e3d4
-	pop bc
-	pop de
-	ld b, $2
-	ret
-; e3d9
-
-TextJump_WasSentToBillsPC: ; 0xe3d9
-	; was sent to BILL's PC.
-	text_jump Text_WasSentToBillsPC
-	db "@"
-; 0xe3de
-
-InitNickname: ; e3de
-	push de
-	call LoadStandardMenuHeader
-	call DisableSpriteUpdates
-	pop de
-	push de
-	ld b, $0
-	farcall NamingScreen
-	pop hl
-	ld de, wStringBuffer1
-	call InitName
-	ld a, $4 ; ExitAllMenus is in bank 0, XXX could this be in bank 4 in pokered?
-	ld hl, ExitAllMenus
-	rst FarCall
-	ret
-; e3fd
--- a/engine/move_mon_wo_mail.asm
+++ /dev/null
@@ -1,133 +1,0 @@
-InsertPokemonIntoBox: ; 51322
-	ld a, BANK(sBoxCount)
-	call GetSRAMBank
-	ld hl, sBoxCount
-	call InsertSpeciesIntoBoxOrParty
-	ld a, [sBoxCount]
-	dec a
-	ld [wd265], a
-	ld hl, sBoxMonNicknames
-	ld bc, MON_NAME_LENGTH
-	ld de, wBufferMonNick
-	call InsertDataIntoBoxOrParty
-	ld a, [sBoxCount]
-	dec a
-	ld [wd265], a
-	ld hl, sBoxMonOT
-	ld bc, NAME_LENGTH
-	ld de, wBufferMonOT
-	call InsertDataIntoBoxOrParty
-	ld a, [sBoxCount]
-	dec a
-	ld [wd265], a
-	ld hl, sBoxMons
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld de, wBufferMon
-	call InsertDataIntoBoxOrParty
-	ld hl, wBufferMonMoves
-	ld de, wTempMonMoves
-	ld bc, NUM_MOVES
-	call CopyBytes
-	ld hl, wBufferMonPP
-	ld de, wTempMonPP
-	ld bc, NUM_MOVES
-	call CopyBytes
-	ld a, [wCurPartyMon]
-	ld b, a
-	farcall RestorePPofDepositedPokemon
-	jp CloseSRAM
-
-InsertPokemonIntoParty: ; 5138b
-	ld hl, wPartyCount
-	call InsertSpeciesIntoBoxOrParty
-	ld a, [wPartyCount]
-	dec a
-	ld [wd265], a
-	ld hl, wPartyMonNicknames
-	ld bc, MON_NAME_LENGTH
-	ld de, wBufferMonNick
-	call InsertDataIntoBoxOrParty
-	ld a, [wPartyCount]
-	dec a
-	ld [wd265], a
-	ld hl, wPartyMonOT
-	ld bc, NAME_LENGTH
-	ld de, wBufferMonOT
-	call InsertDataIntoBoxOrParty
-	ld a, [wPartyCount]
-	dec a
-	ld [wd265], a
-	ld hl, wPartyMons
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld de, wBufferMon
-	call InsertDataIntoBoxOrParty
-	ret
-
-InsertSpeciesIntoBoxOrParty: ; 513cb
-	inc [hl]
-	inc hl
-	ld a, [wCurPartyMon]
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [wCurPartySpecies]
-	ld c, a
-.loop
-	ld a, [hl]
-	ld [hl], c
-	inc hl
-	inc c
-	ld c, a
-	jr nz, .loop
-	ret
-
-InsertDataIntoBoxOrParty: ; 513e0
-	push de
-	push hl
-	push bc
-	ld a, [wd265]
-	dec a
-	call AddNTimes
-	push hl
-	add hl, bc
-	ld d, h
-	ld e, l
-	pop hl
-.loop
-	push bc
-	ld a, [wd265]
-	ld b, a
-	ld a, [wCurPartyMon]
-	cp b
-	pop bc
-	jr z, .insert
-	push hl
-	push de
-	push bc
-	call CopyBytes
-	pop bc
-	pop de
-	pop hl
-	push hl
-	ld a, l
-	sub c
-	ld l, a
-	ld a, h
-	sbc b
-	ld h, a
-	pop de
-	ld a, [wd265]
-	dec a
-	ld [wd265], a
-	jr .loop
-
-.insert
-	pop bc
-	pop hl
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld d, h
-	ld e, l
-	pop hl
-	call CopyBytes
-	ret
--- a/engine/movement.asm
+++ /dev/null
@@ -1,864 +1,0 @@
-MovementPointers: ; 5075
-; entries correspond to macros/scripts/movement.asm enumeration
-	dw Movement_turn_head_down        ; 00
-	dw Movement_turn_head_up          ; 01
-	dw Movement_turn_head_left        ; 02
-	dw Movement_turn_head_right       ; 03
-	dw Movement_turn_step_down        ; 04
-	dw Movement_turn_step_up          ; 05
-	dw Movement_turn_step_left        ; 06
-	dw Movement_turn_step_right       ; 07
-	dw Movement_slow_step_down        ; 08
-	dw Movement_slow_step_up          ; 09
-	dw Movement_slow_step_left        ; 0a
-	dw Movement_slow_step_right       ; 0b
-	dw Movement_step_down             ; 0c
-	dw Movement_step_up               ; 0d
-	dw Movement_step_left             ; 0e
-	dw Movement_step_right            ; 0f
-	dw Movement_big_step_down         ; 10
-	dw Movement_big_step_up           ; 11
-	dw Movement_big_step_left         ; 12
-	dw Movement_big_step_right        ; 13
-	dw Movement_slow_slide_step_down  ; 14
-	dw Movement_slow_slide_step_up    ; 15
-	dw Movement_slow_slide_step_left  ; 16
-	dw Movement_slow_slide_step_right ; 17
-	dw Movement_slide_step_down       ; 18
-	dw Movement_slide_step_up         ; 19
-	dw Movement_slide_step_left       ; 1a
-	dw Movement_slide_step_right      ; 1b
-	dw Movement_fast_slide_step_down  ; 1c
-	dw Movement_fast_slide_step_up    ; 1d
-	dw Movement_fast_slide_step_left  ; 1e
-	dw Movement_fast_slide_step_right ; 1f
-	dw Movement_turn_away_down        ; 20
-	dw Movement_turn_away_up          ; 21
-	dw Movement_turn_away_left        ; 22
-	dw Movement_turn_away_right       ; 23
-	dw Movement_turn_in_down          ; 24
-	dw Movement_turn_in_up            ; 25
-	dw Movement_turn_in_left          ; 26
-	dw Movement_turn_in_right         ; 27
-	dw Movement_turn_waterfall_down   ; 28
-	dw Movement_turn_waterfall_up     ; 29
-	dw Movement_turn_waterfall_left   ; 2a
-	dw Movement_turn_waterfall_right  ; 2b
-	dw Movement_slow_jump_step_down   ; 2c
-	dw Movement_slow_jump_step_up     ; 2d
-	dw Movement_slow_jump_step_left   ; 2e
-	dw Movement_slow_jump_step_right  ; 2f
-	dw Movement_jump_step_down        ; 30
-	dw Movement_jump_step_up          ; 31
-	dw Movement_jump_step_left        ; 32
-	dw Movement_jump_step_right       ; 33
-	dw Movement_fast_jump_step_down   ; 34
-	dw Movement_fast_jump_step_up     ; 35
-	dw Movement_fast_jump_step_left   ; 36
-	dw Movement_fast_jump_step_right  ; 37
-	dw Movement_remove_sliding        ; 38
-	dw Movement_set_sliding           ; 39
-	dw Movement_remove_fixed_facing   ; 3a
-	dw Movement_fix_facing            ; 3b
-	dw Movement_show_object           ; 3c
-	dw Movement_hide_object           ; 3d
-	dw Movement_step_sleep_1          ; 3e
-	dw Movement_step_sleep_2          ; 3f
-	dw Movement_step_sleep_3          ; 40
-	dw Movement_step_sleep_4          ; 41
-	dw Movement_step_sleep_5          ; 42
-	dw Movement_step_sleep_6          ; 43
-	dw Movement_step_sleep_7          ; 44
-	dw Movement_step_sleep_8          ; 45
-	dw Movement_step_sleep            ; 46
-	dw Movement_step_end              ; 47
-	dw Movement_48                    ; 48
-	dw Movement_remove_object         ; 49
-	dw Movement_step_loop             ; 4a
-	dw Movement_4b                    ; 4b
-	dw Movement_teleport_from         ; 4c
-	dw Movement_teleport_to           ; 4d
-	dw Movement_skyfall               ; 4e
-	dw Movement_step_dig              ; 4f
-	dw Movement_step_bump             ; 50
-	dw Movement_fish_got_bite         ; 51
-	dw Movement_fish_cast_rod         ; 52
-	dw Movement_hide_emote            ; 53
-	dw Movement_show_emote            ; 54
-	dw Movement_step_shake            ; 55
-	dw Movement_tree_shake            ; 56
-	dw Movement_rock_smash            ; 57
-	dw Movement_return_dig            ; 58
-	dw Movement_skyfall_top           ; 59
-; 5129
-
-
-Movement_teleport_from: ; 5129
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_TELEPORT_FROM
-	ret
-; 5130
-
-Movement_teleport_to: ; 5130
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_TELEPORT_TO
-	ret
-; 5137
-
-Movement_skyfall: ; 5137
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SKYFALL
-	ret
-; 513e
-
-Movement_skyfall_top: ; 513e
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SKYFALL_TOP
-	ret
-; 5145
-
-Movement_step_dig: ; 5145
-	call GetSpriteDirection
-	rlca
-	rlca
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_SPIN
-	call JumpMovementPointer
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_03
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ret
-; 516a
-
-Movement_return_dig: ; 516a
-	call GetSpriteDirection
-	rlca
-	rlca
-	ld hl, OBJECT_STEP_FRAME
-	add hl, bc
-	ld [hl], a
-	call JumpMovementPointer
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_RETURN_DIG
-	ret
-; 5189
-
-Movement_fish_got_bite: ; 5189
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_FISHING
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_GOT_BITE
-	ret
-; 5196
-
-Movement_rock_smash: ; 5196
-	call JumpMovementPointer
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STAND
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_ROCK_SMASH
-	ret
-; 51ab
-
-Movement_fish_cast_rod: ; 51ab
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_FISHING
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 51b8
-
-Movement_step_loop: ; 51b8
-	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
-	add hl, bc
-	ld [hl], $0
-	jp ContinueReadingMovement
-; 51c1
-
-Movement_step_end: ; 51c1
-	call RestoreDefaultMovement
-	ld hl, OBJECT_MOVEMENTTYPE
-	add hl, bc
-	ld [hl], a
-
-	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
-	add hl, bc
-	ld [hl], $0
-
-	ld hl, wVramState
-	res 7, [hl]
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_SLEEP
-	ret
-; 51db
-
-Movement_48: ; 51db
-	call RestoreDefaultMovement
-	ld hl, OBJECT_MOVEMENTTYPE
-	add hl, bc
-	ld [hl], a
-
-	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
-	add hl, bc
-	ld [hl], $0
-
-	call JumpMovementPointer
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_03
-
-	ld hl, wVramState
-	res 7, [hl]
-	ret
-; 51fd
-
-Movement_remove_object: ; 51fd
-	call DeleteMapObject
-	ld hl, wObjectFollow_Leader
-	ld a, [hMapObjectIndexBuffer]
-	cp [hl]
-	jr nz, .not_leading
-	ld [hl], -1
-
-.not_leading
-	ld hl, wVramState
-	res 7, [hl]
-	ret
-; 5210
-
-Movement_4b: ; 5210
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STAND
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_04
-
-	ld hl, wVramState
-	res 7, [hl]
-	ret
-; 5222
-
-Movement_step_sleep_1: ; 5222
-	ld a, 1
-	jr Movement_step_sleep_common
-
-Movement_step_sleep_2: ; 5226
-	ld a, 2
-	jr Movement_step_sleep_common
-
-Movement_step_sleep_3: ; 522a
-	ld a, 3
-	jr Movement_step_sleep_common
-
-Movement_step_sleep_4: ; 522e
-	ld a, 4
-	jr Movement_step_sleep_common
-
-Movement_step_sleep_5: ; 5232
-	ld a, 5
-	jr Movement_step_sleep_common
-
-Movement_step_sleep_6: ; 5236
-	ld a, 6
-	jr Movement_step_sleep_common
-
-Movement_step_sleep_7: ; 523a
-	ld a, 7
-	jr Movement_step_sleep_common
-
-Movement_step_sleep_8: ; 523e
-	ld a, 8
-	jr Movement_step_sleep_common
-
-Movement_step_sleep: ; 5242
-; parameters:
-;	duration (DecimalParam)
-
-	call JumpMovementPointer
-	jr Movement_step_sleep_common
-
-Movement_step_sleep_common: ; 5247
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_03
-
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STAND
-
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ret
-; 525f
-
-Movement_step_bump: ; 525f
-	ld a, 1
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_BUMP
-
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_BUMP
-
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ret
-; 5279
-
-Movement_tree_shake: ; 5279
-	ld a, 24
-	ld hl, OBJECT_STEP_DURATION
-	add hl, bc
-	ld [hl], a
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_03
-
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_WEIRD_TREE
-
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ret
-; 5293
-
-Movement_remove_sliding: ; 5293
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	res SLIDING, [hl]
-	jp ContinueReadingMovement
-; 529c
-
-Movement_set_sliding: ; 529c
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	set SLIDING, [hl]
-	jp ContinueReadingMovement
-; 52a5
-
-Movement_remove_fixed_facing: ; 52a5
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	res FIXED_FACING, [hl]
-	jp ContinueReadingMovement
-; 52ae
-
-Movement_fix_facing: ; 52ae
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	set FIXED_FACING, [hl]
-	jp ContinueReadingMovement
-; 52b7
-
-Movement_show_object: ; 52b7
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	res INVISIBLE, [hl]
-	jp ContinueReadingMovement
-; 52c0
-
-Movement_hide_object: ; 52c0
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	set INVISIBLE, [hl]
-	jp ContinueReadingMovement
-; 52c9
-
-Movement_hide_emote: ; 52c9
-	call DespawnEmote
-	jp ContinueReadingMovement
-; 52cf
-
-Movement_show_emote: ; 52cf
-	call SpawnEmote
-	jp ContinueReadingMovement
-; 52d5
-
-Movement_step_shake: ; 52d5
-; parameters:
-;	displacement (DecimalParam)
-
-	call JumpMovementPointer
-	call ShakeScreen
-	jp ContinueReadingMovement
-; 52de
-
-Movement_turn_head_down: ; 52de
-	ld a, OW_DOWN
-	jr TurnHead
-
-Movement_turn_head_up: ; 52e2
-	ld a, OW_UP
-	jr TurnHead
-
-Movement_turn_head_left: ; 52e6
-	ld a, OW_LEFT
-	jr TurnHead
-
-Movement_turn_head_right: ; 52ea
-	ld a, OW_RIGHT
-	jr TurnHead
-
-TurnHead: ; 52ee
-	ld hl, OBJECT_FACING
-	add hl, bc
-	ld [hl], a
-
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STAND
-
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld [hl], STANDING
-	ret
-; 5300
-
-Movement_slow_step_down: ; 5300
-	ld a, STEP_SLOW << 2 | DOWN
-	jp NormalStep
-; 5305
-
-Movement_slow_step_up: ; 5305
-	ld a, STEP_SLOW << 2 | UP
-	jp NormalStep
-; 530a
-
-Movement_slow_step_left: ; 530a
-	ld a, STEP_SLOW << 2 | LEFT
-	jp NormalStep
-; 530f
-
-Movement_slow_step_right: ; 530f
-	ld a, STEP_SLOW << 2 | RIGHT
-	jp NormalStep
-; 5314
-
-Movement_step_down: ; 5314
-	ld a, STEP_WALK << 2 | DOWN
-	jp NormalStep
-; 5319
-
-Movement_step_up: ; 5319
-	ld a, STEP_WALK << 2 | UP
-	jp NormalStep
-; 531e
-
-Movement_step_left: ; 531e
-	ld a, STEP_WALK << 2 | LEFT
-	jp NormalStep
-; 5323
-
-Movement_step_right: ; 5323
-	ld a, STEP_WALK << 2 | RIGHT
-	jp NormalStep
-; 5328
-
-Movement_big_step_down: ; 5328
-	ld a, STEP_BIKE << 2 | DOWN
-	jp NormalStep
-; 532d
-
-Movement_big_step_up: ; 532d
-	ld a, STEP_BIKE << 2 | UP
-	jp NormalStep
-; 5332
-
-Movement_big_step_left: ; 5332
-	ld a, STEP_BIKE << 2 | LEFT
-	jp NormalStep
-; 5337
-
-Movement_big_step_right: ; 5337
-	ld a, STEP_BIKE << 2 | RIGHT
-	jp NormalStep
-; 533c
-
-
-Movement_turn_away_down: ; 533c
-	ld a, STEP_SLOW << 2 | DOWN
-	jp TurningStep
-; 5341
-
-Movement_turn_away_up: ; 5341
-	ld a, STEP_SLOW << 2 | UP
-	jp TurningStep
-; 5346
-
-Movement_turn_away_left: ; 5346
-	ld a, STEP_SLOW << 2 | LEFT
-	jp TurningStep
-; 534b
-
-Movement_turn_away_right: ; 534b
-	ld a, STEP_SLOW << 2 | RIGHT
-	jp TurningStep
-; 5350
-
-Movement_turn_in_down: ; 5350
-	ld a, STEP_WALK << 2 | DOWN
-	jp TurningStep
-; 5355
-
-Movement_turn_in_up: ; 5355
-	ld a, STEP_WALK << 2 | UP
-	jp TurningStep
-; 535a
-
-Movement_turn_in_left: ; 535a
-	ld a, STEP_WALK << 2 | LEFT
-	jp TurningStep
-; 535f
-
-Movement_turn_in_right: ; 535f
-	ld a, STEP_WALK << 2 | RIGHT
-	jp TurningStep
-; 5364
-
-Movement_turn_waterfall_down: ; 5364
-	ld a, STEP_BIKE << 2 | DOWN
-	jp TurningStep
-; 5369
-
-Movement_turn_waterfall_up: ; 5369
-	ld a, STEP_BIKE << 2 | UP
-	jp TurningStep
-; 536e
-
-Movement_turn_waterfall_left: ; 536e
-	ld a, STEP_BIKE << 2 | LEFT
-	jp TurningStep
-; 5373
-
-Movement_turn_waterfall_right: ; 5373
-	ld a, STEP_BIKE << 2 | RIGHT
-	jp TurningStep
-; 5378
-
-
-Movement_slow_slide_step_down: ; 5378
-	ld a, STEP_SLOW << 2 | DOWN
-	jp SlideStep
-; 537d
-
-Movement_slow_slide_step_up: ; 537d
-	ld a, STEP_SLOW << 2 | UP
-	jp SlideStep
-; 5382
-
-Movement_slow_slide_step_left: ; 5382
-	ld a, STEP_SLOW << 2 | LEFT
-	jp SlideStep
-; 5387
-
-Movement_slow_slide_step_right: ; 5387
-	ld a, STEP_SLOW << 2 | RIGHT
-	jp SlideStep
-; 538c
-
-Movement_slide_step_down: ; 538c
-	ld a, STEP_WALK << 2 | DOWN
-	jp SlideStep
-; 5391
-
-Movement_slide_step_up: ; 5391
-	ld a, STEP_WALK << 2 | UP
-	jp SlideStep
-; 5396
-
-Movement_slide_step_left: ; 5396
-	ld a, STEP_WALK << 2 | LEFT
-	jp SlideStep
-; 539b
-
-Movement_slide_step_right: ; 539b
-	ld a, STEP_WALK << 2 | RIGHT
-	jp SlideStep
-; 53a0
-
-Movement_fast_slide_step_down: ; 53a0
-	ld a, STEP_BIKE << 2 | DOWN
-	jp SlideStep
-; 53a5
-
-Movement_fast_slide_step_up: ; 53a5
-	ld a, STEP_BIKE << 2 | UP
-	jp SlideStep
-; 53aa
-
-Movement_fast_slide_step_left: ; 53aa
-	ld a, STEP_BIKE << 2 | LEFT
-	jp SlideStep
-; 53af
-
-Movement_fast_slide_step_right: ; 53af
-	ld a, STEP_BIKE << 2 | RIGHT
-	jp SlideStep
-; 53b4
-
-
-Movement_slow_jump_step_down: ; 53b4
-	ld a, STEP_SLOW << 2 | DOWN
-	jp JumpStep
-; 53b9
-
-Movement_slow_jump_step_up: ; 53b9
-	ld a, STEP_SLOW << 2 | UP
-	jp JumpStep
-; 53be
-
-Movement_slow_jump_step_left: ; 53be
-	ld a, STEP_SLOW << 2 | LEFT
-	jp JumpStep
-; 53c3
-
-Movement_slow_jump_step_right: ; 53c3
-	ld a, STEP_SLOW << 2 | RIGHT
-	jp JumpStep
-; 53c8
-
-Movement_jump_step_down: ; 53c8
-	ld a, STEP_WALK << 2 | DOWN
-	jp JumpStep
-; 53cd
-
-Movement_jump_step_up: ; 53cd
-	ld a, STEP_WALK << 2 | UP
-	jp JumpStep
-; 53d2
-
-Movement_jump_step_left: ; 53d2
-	ld a, STEP_WALK << 2 | LEFT
-	jp JumpStep
-; 53d7
-
-Movement_jump_step_right: ; 53d7
-	ld a, STEP_WALK << 2 | RIGHT
-	jp JumpStep
-; 53dc
-
-Movement_fast_jump_step_down: ; 53dc
-	ld a, STEP_BIKE << 2 | DOWN
-	jp JumpStep
-; 53e1
-
-Movement_fast_jump_step_up: ; 53e1
-	ld a, STEP_BIKE << 2 | UP
-	jp JumpStep
-; 53e6
-
-Movement_fast_jump_step_left: ; 53e6
-	ld a, STEP_BIKE << 2 | LEFT
-	jp JumpStep
-; 53eb
-
-Movement_fast_jump_step_right: ; 53eb
-	ld a, STEP_BIKE << 2 | RIGHT
-	jp JumpStep
-; 53f0
-
-
-Movement_turn_step_down: ; 53f0
-	ld a, OW_DOWN
-	jr TurnStep
-
-Movement_turn_step_up: ; 53f4
-	ld a, OW_UP
-	jr TurnStep
-
-Movement_turn_step_left: ; 53f8
-	ld a, OW_LEFT
-	jr TurnStep
-
-Movement_turn_step_right: ; 53fc
-	ld a, OW_RIGHT
-	jr TurnStep
-
-TurnStep: ; 5400
-	ld hl, OBJECT_1D ; new facing
-	add hl, bc
-	ld [hl], a
-
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STEP
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_HALF_STEP
-	ret
-; 5412
-
-NormalStep: ; 5412
-	call InitStep
-	call UpdateTallGrassFlags
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STEP
-
-	ld hl, OBJECT_NEXT_TILE
-	add hl, bc
-	ld a, [hl]
-	call CheckSuperTallGrassTile
-	jr z, .shake_grass
-
-	call CheckGrassTile
-	jr c, .skip_grass
-
-.shake_grass
-	call ShakeGrass
-
-.skip_grass
-	ld hl, wCenteredObject
-	ld a, [hMapObjectIndexBuffer]
-	cp [hl]
-	jr z, .player
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_NPC_WALK
-	ret
-
-.player
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_PLAYER_WALK
-	ret
-; 5446
-
-TurningStep: ; 5446
-	call InitStep
-	call UpdateTallGrassFlags
-
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_SPIN
-
-	ld hl, wCenteredObject
-	ld a, [hMapObjectIndexBuffer]
-	cp [hl]
-	jr z, .player
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_NPC_WALK
-	ret
-
-.player
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_PLAYER_WALK
-	ret
-; 5468
-
-
-SlideStep: ; 5468
-	call InitStep
-	call UpdateTallGrassFlags
-
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STAND
-
-	ld hl, wCenteredObject
-	ld a, [hMapObjectIndexBuffer]
-	cp [hl]
-	jr z, .player
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_NPC_WALK
-	ret
-
-.player
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_PLAYER_WALK
-	ret
-; 548a
-
-
-JumpStep: ; 548a
-	call InitStep
-	ld hl, OBJECT_1F
-	add hl, bc
-	ld [hl], $0
-
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	res OVERHEAD, [hl]
-
-	ld hl, OBJECT_ACTION
-	add hl, bc
-	ld [hl], OBJECT_ACTION_STEP
-
-	call SpawnShadow
-
-	ld hl, wCenteredObject
-	ld a, [hMapObjectIndexBuffer]
-	cp [hl]
-	jr z, .player
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_NPC_JUMP
-	ret
-
-.player
-	ld hl, OBJECT_STEP_TYPE
-	add hl, bc
-	ld [hl], STEP_TYPE_PLAYER_JUMP
-	ret
-; 54b8
--- a/engine/mystery_gift.asm
+++ /dev/null
@@ -1,1735 +1,0 @@
-DoMysteryGift: ; 1048ba (41:48ba)
-	call ClearTileMap
-	call ClearSprites
-	call WaitBGMap
-	call InitMysteryGiftLayout
-	hlcoord 3, 8
-	ld de, .String_PressAToLink_BToCancel
-	call PlaceString
-	call WaitBGMap
-	farcall PrepMysteryGiftDataToSend
-	call MysteryGift_ClearTrainerData
-	ld a, $2
-	ld [wca01], a
-	ld a, $14
-	ld [wca02], a
-	ld a, [rIE]
-	push af
-
-	call Function104a95
-
-	ld d, a
-	xor a
-	ld [rIF], a
-	pop af
-	ld [rIE], a
-	push de
-	call ClearTileMap
-	call EnableLCD
-	call WaitBGMap
-	ld b, SCGB_DIPLOMA
-	call GetSGBLayout
-	call SetPalettes
-	pop de
-	hlcoord 2, 8
-	ld a, d
-	ld de, .Text_LinkCanceled ; Link has been canceled
-	cp $10
-	jp z, .LinkCanceled
-	cp $6c
-	jp nz, .CommunicationError
-	ld a, [wc900]
-	cp 3
-	jr z, .skip_checks
-	call .CheckAlreadyGotFiveGiftsToday
-	ld hl, .Text_MaxFiveGifts ; Only 5 gifts a day
-	jp nc, .PrintTextAndExit
-	call .CheckAlreadyGotAGiftFromThatPerson
-	ld hl, .Text_MaxOneGiftPerPerson ; Only one gift a day per person
-	jp c, .PrintTextAndExit
-.skip_checks
-	ld a, [wMysteryGiftPlayerBackupItem]
-	and a
-	jp nz, .GiftWaiting
-	ld a, [wMysteryGiftPartnerBackupItem]
-	and a
-	jp nz, .FriendNotReady
-	ld a, [wc900]
-	cp 3
-	jr z, .skip_append_save
-	call .AddMysteryGiftPartnerID
-	ld a, [wc900]
-	cp 4
-	jr z, .skip_append_save
-	call .SaveMysteryGiftTrainerName
-	farcall RestoreMobileEventIndex
-	farcall StubbedTrainerRankings_MysteryGift
-	farcall BackupMobileEventIndex
-.skip_append_save
-	ld a, [wMysteryGiftPartnerSentDeco]
-	and a
-	jr z, .item
-	ld a, [wMysteryGiftPartnerWhichDeco]
-	ld c, a
-	farcall MysteryGiftGetDecoration
-	push bc
-	call MysteryGift_CheckAndSetDecorationAlreadyReceived
-	pop bc
-	jr nz, .item
-	callfar GetDecorationName_c
-	ld h, d
-	ld l, e
-	ld de, wStringBuffer1
-	ld bc, ITEM_NAME_LENGTH
-	call CopyBytes
-	ld hl, .Text_SentToHome ; sent decoration to home
-	jr .PrintTextAndExit
-
-.item
-	call GetMysteryGiftBank
-	ld a, [wMysteryGiftPartnerWhichItem]
-	ld c, a
-	farcall MysteryGiftGetItemHeldEffect
-	ld a, c
-	ld [sBackupMysteryGiftItem], a
-	ld [wNamedObjectIndexBuffer], a
-	call CloseSRAM
-	call GetItemName
-	ld hl, .Text_Sent ; sent item
-	jr .PrintTextAndExit
-
-.LinkCanceled: ; 1049af (41:49af)
-	ld hl, .Text_LinkCanceled ; Link has been canceled
-	jr .PrintTextAndExit
-
-.CommunicationError: ; 1049b4 (41:49b4)
-	ld hl, .Text_CommunicationError ; Communication error
-	call PrintText
-	jp DoMysteryGift
-
-.GiftWaiting: ; 1049bd (41:49bd)
-	ld hl, .Text_ReceiveGiftAtCounter ; receive gift at counter
-	jr .PrintTextAndExit
-
-.FriendNotReady: ; 1049c2 (41:49c2)
-	ld hl, .Text_FriendNotReady ; friend not ready
-
-.PrintTextAndExit: ; 1049c5 (41:49c5)
-	call PrintText
-	ld a, LCDC_DEFAULT
-	ld [rLCDC], a
-	ret
-; 1049cd (41:49cd)
-
-.String_PressAToLink_BToCancel: ; 1049cd
-	db   "Press A to"
-	next "link IR-Device"
-	next "Press B to"
-	next "cancel it."
-	db   "@"
-; 1049fd
-
-.Text_LinkCanceled: ; 1049fd
-	text_jump UnknownText_0x1c0436
-	db "@"
-; 104a02
-
-.Text_CommunicationError: ; 104a02
-	text_jump UnknownText_0x1c0454
-	db "@"
-; 104a07
-
-.Text_ReceiveGiftAtCounter: ; 104a07
-	text_jump UnknownText_0x1c046a
-	db "@"
-; 104a0c
-
-.Text_FriendNotReady: ; 104a0c
-	text_jump UnknownText_0x1c048e
-	db "@"
-; 104a11
-
-.Text_MaxFiveGifts: ; 104a11
-	text_jump UnknownText_0x1c04a7
-	db "@"
-; 104a16
-
-.Text_MaxOneGiftPerPerson: ; 104a16
-	text_jump UnknownText_0x1c04c6
-	db "@"
-; 104a1b
-
-.Text_Sent: ; 104a1b
-	text_jump UnknownText_0x1c04e9
-	db "@"
-; 104a20
-
-.Text_SentToHome: ; 104a20
-	text_jump UnknownText_0x1c04fa
-	db "@"
-; 104a25
-
-.CheckAlreadyGotFiveGiftsToday: ; 104a25 (41:4a25)
-	call GetMysteryGiftBank
-	ld a, [sNumDailyMysteryGiftPartnerIDs]
-	cp $5
-	jp CloseSRAM
-
-.CheckAlreadyGotAGiftFromThatPerson: ; 104a30 (41:4a30)
-	call GetMysteryGiftBank
-	ld a, [wMysteryGiftPartnerID]
-	ld b, a
-	ld a, [wMysteryGiftPartnerID + 1]
-	ld c, a
-	ld a, [sNumDailyMysteryGiftPartnerIDs]
-	ld d, a
-	ld hl, sDailyMysteryGiftPartnerIDs
-.loop
-	ld a, d
-	and a
-	jr z, .No
-	ld a, [hli]
-	cp b
-	jr nz, .skip
-	ld a, [hl]
-	cp c
-	jr z, .Yes
-.skip
-	inc hl
-	dec d
-	jr .loop
-.Yes:
-	scf
-.No:
-	jp CloseSRAM
-
-.AddMysteryGiftPartnerID: ; 104a56 (41:4a56)
-	call GetMysteryGiftBank
-	ld hl, sNumDailyMysteryGiftPartnerIDs
-	ld a, [hl]
-	inc [hl]
-	ld hl, sDailyMysteryGiftPartnerIDs ; inc hl
-	ld e, a
-	ld d, $0
-	add hl, de
-	add hl, de
-	ld a, [wMysteryGiftPartnerID]
-	ld [hli], a
-	ld a, [wMysteryGiftPartnerID + 1]
-	ld [hl], a
-	jp CloseSRAM
-
-.SaveMysteryGiftTrainerName: ; 104a71 (41:4a71)
-	call GetMysteryGiftBank
-	ld a, $1
-	ld [sMysteryGiftTrainerHouseFlag], a
-	ld hl, wMysteryGiftPartnerName
-	ld de, sMysteryGiftPartnerName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ld a, $1
-	ld [de], a
-	inc de
-	ld hl, wMysteryGiftTrainerData
-	ld bc, (1 + 1 + NUM_MOVES) * PARTY_LENGTH + 2
-	call CopyBytes
-	jp CloseSRAM
-
-Function104a95: ; 104a95 (41:4a95)
-	di
-	farcall ClearChannels
-	call Function104d5e
-
-.loop2
-	call Function104d96
-	call Function104ddd
-	ld a, [hMGStatusFlags]
-	cp $10
-	jp z, Function104bd0
-	cp $6c
-	jr nz, .loop2
-
-	ld a, [hPrintNum9]
-	cp $2
-	jr z, Function104b22
-	ld hl, hPrintNum1
-	ld b, $1
-	call Function104d56
-	jr nz, .ly_loop
-	call Function104b49
-	jp nz, Function104bd0
-	jr Function104b0a
-	; Delay frame
-.ly_loop
-	ld a, [rLY]
-	cp LY_VBLANK
-	jr c, .ly_loop
-	ld c, LOW(rRP)
-	ld a, $c0
-	ld [$ff00+c], a
-	ld b, 240 ; This might have been intended as a 4-second timeout buffer.
-	          ; However, it is reset with each frame.
-.loop3
-	push bc
-	call MysteryGift_ReadJoypad
-
-	ld b, $2
-	ld c, LOW(rRP)
-	; Delay frame
-.ly_loop2
-	ld a, [$ff00+c]
-	and b
-	ld b, a
-	ld a, [rLY]
-	cp LY_VBLANK
-	jr nc, .ly_loop2
-.ly_loop3
-	ld a, [$ff00+c]
-	and b
-	ld b, a
-	ld a, [rLY]
-	cp LY_VBLANK
-	jr c, .ly_loop3
-
-	ld a, b
-	pop bc
-	dec b
-	jr z, .loop2 ; we never jump here
-	or a
-	jr nz, .loop2
-	; Check if we've pressed the B button
-	ld a, [hMGJoypadReleased]
-	bit B_BUTTON_F, a
-	jr z, .loop3
-	ld a, $10
-	ld [hMGStatusFlags], a
-	jp Function104bd0
-
-Function104b04: ; 104b04 (41:4b04)
-	call Function104b40
-	jp nz, Function104bd0
-Function104b0a: ; 104b0a (41:4b0a)
-	call Function104d38
-	jp nz, Function104bd0
-	call Function104b88
-	jp nz, Function104bd0
-	call Function104d43
-	jp nz, Function104bd0
-	call Function105033
-	jp Function104bd0
-
-Function104b22: ; 104b22 (41:4b22)
-	call Function104b88
-	jp nz, Function104bd0
-	call Function104d43
-	jp nz, Function104bd0
-	call Function104b40
-	jp nz, Function104bd0
-	call Function104d38
-	jp nz, Function104bd0
-	call Function10502e
-	jp Function104bd0
-
-Function104b40: ; 104b40 (41:4b40)
-	ld hl, hPrintNum1
-	ld b, $1
-	call Function104d56
-	ret nz
-
-Function104b49: ; 104b49 (41:4b49)
-	call Function105033
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret nz
-	ld a, [hPrintNum1]
-	cp $96
-	jp nz, Function104d32
-	ld a, $90
-	ld [hPrintNum1], a
-	call Function104d38
-	ret nz
-	ld hl, hPrintNum1
-	ld b, $1
-	call Function104d4e
-	ret nz
-	call Function10502e
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret nz
-	call Function104d43
-	ret nz
-	ld hl, wMysteryGiftTrainerData
-	ld a, [wca02]
-	ld b, a
-	call Function104d56
-	ret nz
-	call Function105033
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret
-
-Function104b88: ; 104b88 (41:4b88)
-	ld a, $96
-	ld [hPrintNum1], a
-	ld hl, hPrintNum1
-	ld b, $1
-	call Function104d4e
-	ret nz
-	call Function10502e
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret nz
-	call Function104d43
-	ret nz
-	ld hl, hPrintNum1
-	ld b, $1
-	call Function104d56
-	ret nz
-	call Function105033
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret nz
-	ld a, [hPrintNum1]
-	cp $90
-	jp nz, Function104d32
-	call Function104d38
-	ret nz
-	ld hl, wOverworldMap
-	ld a, [wca02]
-	ld b, a
-	call Function104d4e
-	ret nz
-	call Function10502e
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret
-
-Function104bd0: ; 104bd0 (41:4bd0)
-	nop
-	ld a, [hMGStatusFlags]
-	cp $10
-	jr z, .quit
-	cp $6c
-	jr nz, .quit
-	ld hl, wca01
-	dec [hl]
-	jr z, .quit
-	ld hl, wMysteryGiftTrainerData
-	ld de, wMysteryGiftPartnerData
-	ld bc, wMysteryGiftPartnerDataEnd - wMysteryGiftPartnerData
-	call CopyBytes
-	ld a, [wMysteryGiftTrainerData]
-	cp $3
-	jr nc, .quit
-	farcall StagePartyDataForMysteryGift
-	call MysteryGift_ClearTrainerData
-	ld a, $26
-	ld [wca02], a
-	ld a, [hPrintNum9]
-	cp $2
-	jr z, .asm_104c10
-	call Function104d43
-	jr nz, Function104bd0
-	jp Function104b04
-
-.asm_104c10
-	call Function104d38
-	jr nz, Function104bd0
-	jp Function104b22
-
-.quit
-	ld a, [hMGStatusFlags]
-	push af
-	call Function104da0
-	xor a
-	ld [rIF], a
-	ld a, [rIE]
-	or $1
-	ld [rIE], a
-	ei
-	call DelayFrame
-	pop af
-	ret
-
-Function104c2d: ; 104c2d (41:4c2d)
-	di
-	farcall ClearChannels
-	call Function104d5e
-.asm_104c37
-	call Function104d96
-	call Function104ddd
-	ld a, [hMGStatusFlags]
-	cp $10
-	jp z, Function104d1c
-	cp $6c
-	jr nz, .asm_104c37
-	ld a, [hPrintNum9]
-	cp $2
-	jr z, .asm_104c6c
-	call Function104c8a
-	jp nz, Function104d1c
-	call Function104d38
-	jp nz, Function104d1c
-	call Function104cd2
-	jp nz, Function104d1c
-	call Function104d43
-	jp nz, Function104d1c
-	call Function105033
-	jp Function104d1c
-.asm_104c6c
-	call Function104cd2
-	jp nz, Function104d1c
-	call Function104d43
-	jp nz, Function104d1c
-	call Function104c8a
-	jp nz, Function104d1c
-	call Function104d38
-	jp nz, Function104d1c
-	call Function10502e
-	jp Function104d1c
-
-Function104c8a: ; 104c8a (41:4c8a)
-	ld hl, hPrintNum1
-	ld b, $1
-	call Function104d56
-	ret nz
-	call Function105033
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret nz
-	ld a, [hPrintNum1]
-	cp $3c
-	jp nz, Function104d32
-	swap a
-	ld [hPrintNum1], a
-	call Function104d38
-	ret nz
-	ld hl, hPrintNum1
-	ld b, $1
-	call Function104d4e
-	ret nz
-	call Function10502e
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret nz
-	call Function104d43
-	ret nz
-	ld hl, wMysteryGiftTrainerData
-	ld a, [wca02]
-	ld b, a
-	call Function104d56
-	ret nz
-	call Function105033
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret
-
-Function104cd2: ; 104cd2 (41:4cd2)
-	ld a, $3c
-	ld [hPrintNum1], a
-	ld hl, hPrintNum1
-	ld b, $1
-	call Function104d4e
-	ret nz
-	call Function10502e
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret nz
-	call Function104d43
-	ret nz
-	ld hl, hPrintNum1
-	ld b, $1
-	call Function104d56
-	ret nz
-	call Function105033
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret nz
-	ld a, [hPrintNum1]
-	swap a
-	cp $3c
-	jp nz, Function104d32
-	call Function104d38
-	ret nz
-	ld hl, wOverworldMap
-	ld a, [wca02]
-	ld b, a
-	call Function104d4e
-	ret nz
-	call Function10502e
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret
-
-Function104d1c: ; 104d1c (41:4d1c)
-	nop
-	ld a, [hMGStatusFlags]
-	push af
-	call Function104da0
-	xor a
-	ld [rIF], a
-	ld a, [rIE]
-	or $1
-	ld [rIE], a
-	ei
-	call DelayFrame
-	pop af
-	ret
-
-Function104d32: ; 104d32 (41:4d32)
-	ld a, $80
-	ld [hMGStatusFlags], a
-	and a
-	ret
-
-Function104d38: ; 104d38 (41:4d38)
-	call Function104d96
-	call Function104e46
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret
-
-Function104d43: ; 104d43 (41:4d43)
-	call Function104d96
-	call Function104dfe
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret
-
-Function104d4e: ; 104d4e (41:4d4e)
-	call Function104e93
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret
-
-Function104d56: ; 104d56 (41:4d56)
-	call Function104f57
-	ld a, [hMGStatusFlags]
-	cp $6c
-	ret
-
-Function104d5e: ; 104d5e (41:4d5e)
-	call Function104d74
-	ld a, $4
-	ld [rIE], a
-	xor a
-	ld [rIF], a
-	call Function104d96
-	xor a
-	ld b, a
-.asm_104d6d
-	inc a
-	jr nz, .asm_104d6d
-	inc b
-	jr nz, .asm_104d6d
-	ret
-
-Function104d74: ; 104d74 (41:4d74)
-	xor a
-	ld [rTAC], a
-	ld a, $fe
-	ld [rTMA], a
-	ld [rTIMA], a
-	ld a, $2
-	ld [rTAC], a
-	or $4
-	ld [rTAC], a
-	ret
-
-Function104d86: ; 104d86 (41:4d86)
-	xor a
-	ld [rTAC], a
-	ld [rTMA], a
-	ld [rTIMA], a
-	ld a, $2
-	ld [rTAC], a
-	or $4
-	ld [rTAC], a
-	ret
-
-Function104d96: ; 104d96 (41:4d96)
-	ld a, $c0
-	call Function104e8c
-	ld a, $1
-	ld [hPrintNum9], a
-	ret
-
-Function104da0: ; 104da0 (41:4da0)
-	xor a
-	call Function104e8c
-	ld a, $2
-	ld [rTAC], a
-	ret
-
-Function104da9: ; 104da9 (41:4da9)
-	inc d
-	ret z
-	xor a
-	ld [rIF], a
-	halt
-	ld a, [$ff00+c]
-	bit 1, a
-	jr z, Function104da9
-	or a
-	ret
-
-Function104db7: ; 104db7 (41:4db7)
-	inc d
-	ret z
-	xor a
-	ld [rIF], a
-	halt
-	ld a, [$ff00+c]
-	bit 1, a
-	jr nz, Function104db7
-	or a
-	ret
-
-Function104dc5: ; 104dc5 (41:4dc5)
-	ld a, $c1
-	ld [$ff00+c], a
-.wait
-	dec d
-	ret z
-	xor a
-	ld [rIF], a
-	halt
-	jr .wait
-
-Function104dd1: ; 104dd1 (41:4dd1)
-	ld a, $c0
-	ld [$ff00+c], a
-.wait
-	dec d
-	ret z
-	xor a
-	ld [rIF], a
-	halt
-	jr .wait
-
-Function104ddd: ; 104ddd (41:4ddd)
-	ld d, $0
-	ld e, d
-	ld a, $1
-	ld [hPrintNum9], a
-.loop
-	call MysteryGift_ReadJoypad
-	ld b, $2
-	ld c, LOW(rRP)
-	ld a, [hMGJoypadReleased]
-	bit B_BUTTON_F, a
-	jr z, .next
-	ld a, $10
-	ld [hMGStatusFlags], a
-	ret
-
-.next
-	bit 0, a
-	jr nz, Function104e3a
-	ld a, [$ff00+c]
-	and b
-	jr nz, .loop
-
-Function104dfe: ; 104dfe (41:4dfe)
-	ld c, LOW(rRP)
-	ld d, $0
-	ld e, d
-	call Function104db7
-	jp z, Function104f42
-	ld d, e
-	call Function104da9
-	jp z, Function104f42
-	call Function104db7
-	jp z, Function104f42
-	call Function104da9
-	jp z, Function104f42
-	ld a, $6c
-	ld [hMGStatusFlags], a
-	ld d, $3d
-	call Function104dd1
-	ld d, $5
-	call Function104dc5
-	ld d, $15
-	call Function104dd1
-	ld d, $5
-	call Function104dc5
-	ld d, $5
-	call Function104dd1
-	ret
-
-Function104e3a: ; 104e3a (41:4e3a)
-	; Wait a random amount of time
-	call Random
-	ld e, a
-	and $f
-	ld d, a
-.loop
-	dec de
-	ld a, d
-	or e
-	jr nz, .loop
-Function104e46: ; 104e46 (41:4e46)
-	ld a, $2
-	ld [hPrintNum9], a
-	ld c, LOW(rRP)
-	ld d, $0
-	ld e, d
-	ld d, $3d
-	call Function104dd1
-	ld d, $5
-	call Function104dc5
-	ld d, $15
-	call Function104dd1
-	ld d, $5
-	call Function104dc5
-	ld d, $5
-	call Function104dd1
-	ld d, e
-	call Function104db7
-	jp z, Function104f42
-	ld d, e
-	call Function104da9
-	jp z, Function104f42
-	call Function104db7
-	jp z, Function104f42
-	call Function104da9
-	jp z, Function104f42
-	ld d, $3d
-	call Function104dd1
-	ld a, $6c
-	ld [hMGStatusFlags], a
-	ret
-
-Function104e8c: ; 104e8c (41:4e8c)
-	ld [rRP], a
-	ld a, $ff
-	ld [hMGStatusFlags], a
-	ret
-
-Function104e93: ; 104e93 (41:4e93)
-	xor a
-	ld [hPrintNum5], a
-	ld [hPrintNum6], a
-	push hl
-	push bc
-	ld c, LOW(rRP)
-	ld d, $3d
-	call Function104dd1
-	ld hl, hPrintNum2
-	ld a, $5a
-	ld [hli], a
-	ld [hl], b
-	dec hl
-	ld b, $2
-	call Function104ed6
-	pop bc
-	pop hl
-	call Function104ed6
-	ld a, [hPrintNum5]
-	ld [hPrintNum2], a
-	ld a, [hPrintNum6]
-	ld [hPrintNum3], a
-	push hl
-	ld hl, hPrintNum2
-	ld b, $2
-	call Function104ed6
-	ld hl, hMGStatusFlags
-	ld b, $1
-	call Function104faf
-	ld a, [hPrintNum2]
-	ld [hPrintNum5], a
-	ld a, [hPrintNum3]
-	ld [hPrintNum6], a
-	pop hl
-	ret
-
-Function104ed6: ; 104ed6 (41:4ed6)
-	ld c, LOW(rRP)
-	ld d, $5
-	call Function104dd1
-	ld d, $5
-	call Function104dc5
-	ld d, $15
-	call Function104dd1
-	ld a, b
-	cpl
-	ld b, a
-	ld a, $f4
-	ld [rTMA], a
-.asm_104eee
-	inc b
-	jr z, .asm_104f2e
-	ld a, $8
-	ld [hPrintNum4], a
-	ld a, [hli]
-	ld e, a
-	ld a, [hPrintNum5]
-	add e
-	ld [hPrintNum5], a
-	ld a, [hPrintNum6]
-	adc 0
-	ld [hPrintNum6], a
-.asm_104f02
-	xor a
-	ld [rIF], a
-	halt
-	ld a, $c1
-	ld [rRP], a
-	ld d, $1
-	ld a, e
-	rlca
-	ld e, a
-	jr nc, .asm_104f13
-	inc d
-.asm_104f13
-	ld a, [rTIMA]
-	cp $f8
-	jr c, .asm_104f13
-	ld a, $c0
-	ld [rRP], a
-	dec d
-	jr z, .asm_104f25
-	xor a
-	ld [rIF], a
-	halt
-.asm_104f25
-	ld a, [hPrintNum4]
-	dec a
-	jr z, .asm_104eee
-	ld [hPrintNum4], a
-	jr .asm_104f02
-.asm_104f2e
-	ld a, $fe
-	ld [rTMA], a
-	xor a
-	ld [rIF], a
-	halt
-	ld d, $5
-	call Function104dc5
-	ld d, $11
-	call Function104dd1
-	ret
-
-Function104f42: ; 104f42 (41:4f42)
-	ld a, [hMGStatusFlags]
-	or $2
-	ld [hMGStatusFlags], a
-	ret
-
-Function104f49: ; 104f49 (41:4f49)
-	ld a, [hMGStatusFlags]
-	or $1
-	ld [hMGStatusFlags], a
-	ret
-
-Function104f50: ; 104f50 (41:4f50)
-	ld a, [hMGStatusFlags]
-	or $80
-	ld [hMGStatusFlags], a
-	ret
-
-Function104f57: ; 104f57 (41:4f57)
-	xor a
-	ld [hPrintNum5], a
-	ld [hPrintNum6], a
-	push bc
-	push hl
-	ld hl, hPrintNum2
-	ld b, $2
-	call Function104faf
-	ld a, [hPrintNum3]
-	ld [hPrintNum8], a
-	ld b, a
-	pop hl
-	pop af
-	cp b
-	jp c, Function104f50
-	ld a, [hPrintNum2]
-	cp $5a
-	jp nz, Function104f50
-	call Function104faf
-	ld a, [hPrintNum5]
-	ld d, a
-	ld a, [hPrintNum6]
-	ld e, a
-	push hl
-	push de
-	ld hl, hPrintNum2
-	ld b, $2
-	call Function104faf
-	pop de
-	ld hl, hPrintNum2
-	ld a, [hli]
-	xor d
-	ld b, a
-	ld a, [hl]
-	xor e
-	or b
-	call nz, Function104f49
-	push de
-	ld d, $3d
-	call Function104dd1
-	ld hl, hMGStatusFlags
-	ld b, $1
-	call Function104ed6
-	pop de
-	pop hl
-	ld a, d
-	ld [hPrintNum5], a
-	ld a, e
-	ld [hPrintNum6], a
-	ret
-
-Function104faf: ; 104faf (41:4faf)
-	ld c, LOW(rRP)
-	ld d, $0
-	call Function104db7
-	jp z, Function104f42
-	ld d, $0
-	call Function104da9
-	jp z, Function104f42
-	ld d, $0
-	call Function104db7
-	jp z, Function104f42
-	ld a, b
-	cpl
-	ld b, a
-	xor a
-	ld [hMGJoypadPressed + 2], a
-	call Function104d86
-.asm_104fd2
-	inc b
-	jr z, .asm_10501a
-	ld a, $8
-	ld [hPrintNum4], a
-.asm_104fd9
-	ld d, $0
-.asm_104fdb
-	inc d
-	jr z, .asm_104fe5
-	ld a, [$ff00+c]
-	bit 1, a
-	jr z, .asm_104fdb
-	ld d, $0
-.asm_104fe5
-	inc d
-	jr z, .asm_104fed
-	ld a, [$ff00+c]
-	bit 1, a
-	jr nz, .asm_104fe5
-.asm_104fed
-	ld a, [hMGJoypadPressed + 2]
-	ld d, a
-	ld a, [rTIMA]
-	ld [hMGJoypadPressed + 2], a
-	sub d
-	cp $12
-	jr c, .asm_104ffd
-	set 0, e
-	jr .asm_104fff
-.asm_104ffd
-	res 0, e
-.asm_104fff
-	ld a, [hPrintNum4]
-	dec a
-	ld [hPrintNum4], a
-	jr z, .asm_10500b
-	ld a, e
-	rlca
-	ld e, a
-	jr .asm_104fd9
-.asm_10500b
-	ld a, e
-	ld [hli], a
-	ld a, [hPrintNum5]
-	add e
-	ld [hPrintNum5], a
-	ld a, [hPrintNum6]
-	adc 0
-	ld [hPrintNum6], a
-	jr .asm_104fd2
-.asm_10501a
-	call Function104d74
-	xor a
-	ld [rIF], a
-	ld d, $0
-	call Function104da9
-	jp z, Function104f42
-	ld d, $10
-	call Function104dd1
-	ret
-
-Function10502e: ; 10502e (41:502e)
-	ld b, $0
-	jp Function104e93
-
-Function105033: ; 105033 (41:5033)
-	ld b, $0
-	jp Function104f57
-
-MysteryGift_ReadJoypad: ; 105038 (41:5038)
-; We can only get four inputs at a time.
-; We take d-pad first for no particular reason.
-	ld a, R_DPAD
-	ld [rJOYP], a
-; Read twice to give the request time to take.
-	ld a, [rJOYP]
-	ld a, [rJOYP]
-
-; The Joypad register output is in the lo nybble (inversed).
-; We make the hi nybble of our new container d-pad input.
-	cpl
-	and $f
-	swap a
-
-; We'll keep this in b for now.
-	ld b, a
-
-; Buttons make 8 total inputs (A, B, Select, Start).
-; We can fit this into one byte.
-	ld a, R_BUTTONS
-	ld [rJOYP], a
-; Wait for input to stabilize.
-rept 6
-	ld a, [rJOYP]
-endr
-; Buttons take the lo nybble.
-	cpl
-	and $f
-	or b
-	ld c, a
-; To get the delta we xor the last frame's input with the new one.
-	ld a, [hMGJoypadPressed]
-	xor c
-; Released this frame:
-	and c
-	ld [hMGJoypadReleased], a
-; Pressed this frame:
-	ld a, c
-	ld [hMGJoypadPressed], a
-	ld a, $30
-; Reset the joypad register since we're done with it.
-	ld [rJOYP], a
-	ret
-
-MysteryGift_CheckAndSetDecorationAlreadyReceived: ; 105069 (41:5069)
-	call GetMysteryGiftBank
-	ld d, $0
-	ld b, CHECK_FLAG
-	ld hl, sMysteryGiftDecorationsReceived
-	predef_id SmallFarFlagAction
-	push hl
-	push bc
-	call Predef
-	call CloseSRAM
-	ld a, c
-	and a
-	pop bc
-	pop hl
-	ret nz
-	call GetMysteryGiftBank
-	ld b, SET_FLAG
-	predef SmallFarFlagAction
-	call CloseSRAM
-	xor a
-	ret
-
-MysteryGift_CopyReceivedDecosToPC: ; 105091 (41:5091)
-	call GetMysteryGiftBank
-	ld c, $0
-.loop
-	push bc
-	ld d, $0
-	ld b, CHECK_FLAG
-	ld hl, sMysteryGiftDecorationsReceived
-	predef SmallFarFlagAction
-	ld a, c
-	and a
-	pop bc
-	jr z, .skip
-	push bc
-	callfar SetSpecificDecorationFlag
-	pop bc
-.skip
-	inc c
-	ld a, c
-	cp TrophyIDs - DecorationIDs
-	jr c, .loop
-	jp CloseSRAM
-
-UnlockMysteryGift: ; 1050b9
-	call GetMysteryGiftBank
-	ld hl, sMysteryGiftUnlocked
-	ld a, [hl]
-	inc a
-	jr nz, .ok
-	ld [hld], a
-	ld [hl], a
-.ok
-	jp CloseSRAM
-; 1050c8
-
-Function1050c8: ; 1050c8
-	call GetMysteryGiftBank
-	ld a, [sNumDailyMysteryGiftPartnerIDs]
-	cp $ff
-	jr z, .okay
-	xor a
-	ld [sNumDailyMysteryGiftPartnerIDs], a
-.okay
-	jp CloseSRAM
-; 1050d9
-
-
-BackupMysteryGift: ; 1050d9
-	call GetMysteryGiftBank
-	ld hl, sMysteryGiftItem
-	ld de, sBackupMysteryGiftItem
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-	jp CloseSRAM
-; 1050ea
-
-
-RestoreMysteryGift: ; 1050ea (41:50ea)
-	call GetMysteryGiftBank
-	ld hl, sBackupMysteryGiftItem
-	ld de, sMysteryGiftItem
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-	jp CloseSRAM
-
-MysteryGift_ClearTrainerData: ; 1050fb (41:50fb)
-	ld hl, wMysteryGiftTrainerData
-	xor a
-	ld b, wMysteryGiftTrainerDataEnd - wMysteryGiftTrainerData
-.loop
-	ld [hli], a
-	dec b
-	jr nz, .loop
-	ret
-
-
-GetMysteryGiftBank: ; 105106
-	ld a, BANK(sBackupMysteryGiftItem)
-	jp GetSRAMBank
-; 10510b
-
-
-StagePartyDataForMysteryGift: ; 10510b (41:510b)
-; You will be sending this data to your mystery gift partner.
-; Structure is the same as a trainer with species and moves
-; defined.
-	ld a, BANK(sPokemonData)
-	call GetSRAMBank
-	ld de, wMysteryGiftStaging
-	ld bc, sPokemonData + wPartyMons - wPokemonData
-	ld hl, sPokemonData + wPartySpecies - wPokemonData
-.loop
-	ld a, [hli]
-	cp -1
-	jr z, .party_end
-	cp EGG
-	jr z, .next
-	push hl
-	; copy level
-	ld hl, MON_LEVEL
-	add hl, bc
-	ld a, [hl]
-	ld [de], a
-	inc de
-	; copy species
-	ld hl, MON_SPECIES
-	add hl, bc
-	ld a, [hl]
-	ld [de], a
-	inc de
-	; copy moves
-	ld hl, MON_MOVES
-	add hl, bc
-	push bc
-	ld bc, NUM_MOVES
-	call CopyBytes
-	pop bc
-	pop hl
-.next
-	push hl
-	ld hl, PARTYMON_STRUCT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	pop hl
-	jr .loop
-.party_end
-	ld a, -1
-	ld [de], a
-	ld a, $26
-	ld [wca00], a
-	jp CloseSRAM
-
-InitMysteryGiftLayout: ; 105153 (41:5153)
-	call ClearBGPalettes
-	call DisableLCD
-	ld hl, MysteryGiftGFX
-	ld de, vTiles2 tile $00
-	ld a, BANK(MysteryGiftGFX)
-	ld bc, MysteryGiftGFX.End - MysteryGiftGFX
-	call FarCopyBytes
-	hlcoord 0, 0
-	ld a, $42
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	call ByteFill
-	hlcoord 3, 7
-	lb bc, 9, 15
-	call ClearBox
-	hlcoord 0, 0
-	ld a, $0
-	ld [hli], a
-	inc a
-	ld [hl], a
-	hlcoord 0, 1
-	inc a
-	ld [hli], a
-	inc a
-	ld [hl], a
-	hlcoord 7, 1
-	ld a, $12
-	call .Load5GFX
-	hlcoord 2, 2
-	ld a, $17
-	call .Load16GFX
-	hlcoord 2, 3
-	ld a, $27
-	call .Load16GFX
-	hlcoord 9, 4
-	ld a, $37
-	ld [hli], a
-	inc a
-	ld [hl], a
-	hlcoord 1, 2
-	ld [hl], $4
-	hlcoord 1, 3
-	ld a, $5
-	call .Load14Column
-	ld a, $9
-	hlcoord 18, 5
-	call .Load11Column
-	hlcoord 2, 5
-	ld a, $b
-	call .Load16Row
-	hlcoord 2, 16
-	ld a, $7
-	call .Load16Row
-	hlcoord 2, 5
-	ld a, $d
-	call .Load5GFX
-	hlcoord 7, 5
-	ld [hl], $c
-	hlcoord 18, 5
-	ld [hl], $a
-	hlcoord 18, 16
-	ld [hl], $8
-	hlcoord 1, 16
-	ld [hl], $6
-	hlcoord 2, 6
-	ld a, $3a
-	call .Load16Row
-	hlcoord 2, 15
-	ld a, $40
-	call .Load16Row
-	hlcoord 2, 6
-	ld a, $3c
-	call .Load9Column
-	hlcoord 17, 6
-	ld a, $3e
-	call .Load9Column
-	hlcoord 2, 6
-	ld [hl], $39
-	hlcoord 17, 6
-	ld [hl], $3b
-	hlcoord 2, 15
-	ld [hl], $3f
-	hlcoord 17, 15
-	ld [hl], $41
-	call EnableLCD
-	call WaitBGMap
-	ld b, SCGB_MYSTERY_GIFT
-	call GetSGBLayout
-	call SetPalettes
-	ret
-
-.Load5GFX: ; 10522e (41:522e)
-	ld b,  5
-	jr .gfx_loop
-; 105232 (41:5232)
-
-.Unreferenced_Load6GFX:
-	ld b,  6
-	jr .gfx_loop
-
-.Load16GFX: ; 105236 (41:5236)
-	ld b, 16
-
-.gfx_loop ; 105238 (41:5238)
-	ld [hli], a
-	inc a
-	dec b
-	jr nz, .gfx_loop
-	ret
-
-.Load9Column: ; 10523e (41:523e)
-	ld b,  9
-	jr .col_loop
-
-.Load11Column: ; 105242 (41:5242)
-	ld b, 11
-	jr .col_loop
-
-.Load14Column: ; 105246 (41:5246)
-	ld b, 14
-
-.col_loop ; 105248 (41:5248)
-	ld [hl], a
-	ld de, SCREEN_WIDTH
-	add hl, de
-	dec b
-	jr nz, .col_loop
-	ret
-
-.Load16Row: ; 105251 (41:5251)
-	ld b, 16
-.row_loop
-	ld [hli], a
-	dec b
-	jr nz, .row_loop
-	ret
-
-MysteryGiftGFX: ; 105258
-INCBIN "gfx/mystery_gift/mystery_gift.2bpp"
-.End
-
-Function105688: ; 105688 (41:5688)
-	call ClearTileMap
-	call ClearSprites
-	call WaitBGMap
-	call Function1057d7
-	hlcoord 3, 8
-	ld de, String_PressAToLink_BToCancel_JP
-	call PlaceString
-	call WaitBGMap
-	call Function10578c
-	call MysteryGift_ClearTrainerData
-	ld a, $24
-	ld [wca02], a
-	ld a, [rIE]
-	push af
-	call Function104c2d
-	ld d, a
-	xor a
-	ld [rIF], a
-	pop af
-	ld [rIE], a
-	ld a, d
-	cp $10
-	jp z, Function105712
-	cp $6c
-	jp nz, Function10571a
-	call Function1056eb
-	ld c, 60
-	call DelayFrames
-	call Function105777
-	ld hl, Text_ReceivedCard
-	call PrintText
-	ld de, wMysteryGiftTrainerData
-	farcall Function8ac70
-	ld a, c
-	ld [wd265], a
-	ld hl, Text_CardNotRegistered
-	jr c, PrintTextAndExit_JP
-	ld hl, Text_ListedCardAsNumber
-	jr PrintTextAndExit_JP
-
-Function1056eb: ; 1056eb (41:56eb)
-	ld c, 16
-.loop
-	ld hl, wVirtualOAMSprite00YCoord
-	ld b, 8
-.dec_y_loop
-	dec [hl]
-rept SPRITEOAMSTRUCT_LENGTH
-	inc hl
-endr
-	dec b
-	jr nz, .dec_y_loop
-	ld hl, wVirtualOAMSprite08YCoord
-	ld b, 8
-.inc_y_loop
-	inc [hl]
-rept SPRITEOAMSTRUCT_LENGTH
-	inc hl
-endr
-	dec b
-	jr nz, .inc_y_loop
-	dec c
-	ret z
-	push bc
-	ld c, 4
-	call DelayFrames
-	pop bc
-	jr .loop
-
-Function105712: ; 105712 (41:5712)
-	call Function105777
-	ld hl, Text_MGLinkCanceled
-	jr PrintTextAndExit_JP
-
-Function10571a: ; 10571a (41:571a)
-	call Function105777
-	ld hl, Text_MGCommError
-	call PrintText
-	jp Function105688
-
-PrintTextAndExit_JP: ; 105726 (41:5726)
-	call PrintText
-	ld a, LCDC_DEFAULT
-	ld [rLCDC], a
-	ret
-; 10572e (41:572e)
-
-String_PressAToLink_BToCancel_JP: ; 10572e
-	db   "エーボタン<WO>おすと"
-	next "つうしん<PKMN>おこなわれるよ!"
-	next "ビーボタン<WO>おすと"
-	next "つうしん<WO>ちゅうし します"
-	db   "@"
-
-; 10575e
-
-Text_ReceivedCard: ; 10575e
-	text_jump UnknownText_0x1c051a
-	db "@"
-
-Text_ListedCardAsNumber: ; 105763
-	text_jump UnknownText_0x1c0531
-	db "@"
-
-Text_CardNotRegistered: ; 105768
-	text_jump UnknownText_0x1c0555
-	db "@"
-
-Text_MGLinkCanceled: ; 10576d
-	text_jump UnknownText_0x1c0573
-	db "@"
-
-Text_MGCommError: ; 105772
-	text_jump UnknownText_0x1c0591
-	db "@"
-; 105777
-
-Function105777: ; 105777 (41:5777)
-	call ClearSprites
-	call ClearTileMap
-	call EnableLCD
-	call WaitBGMap
-	ld b, SCGB_DIPLOMA
-	call GetSGBLayout
-	call SetPalettes
-	ret
-
-Function10578c: ; 10578c (41:578c)
-	ld de, wOverworldMap
-	ld a, BANK(sPlayerData)
-	call GetSRAMBank
-	ld hl, sPlayerData + wPlayerName - wPlayerData
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ld hl, sPlayerData + wPlayerID - wPlayerData
-	ld bc, 2
-	call CopyBytes
-	ld hl, sPlayerData + wSecretID - wPlayerData
-	ld bc, 2
-	call CopyBytes
-	call CloseSRAM
-	ld a, BANK(sCrystalData)
-	call GetSRAMBank
-	ld a, [sCrystalData + 0]
-	ld [de], a
-	inc de
-	ld a, 4 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
-	call GetSRAMBank
-	ld hl, $a603 ; address of MBC30 bank
-	ld bc, $8
-	call CopyBytes
-	ld hl, $a007 ; address of MBC30 bank
-	ld bc, $c
-	call CopyBytes
-	call CloseSRAM
-	ret
-
-Function1057d7: ; 1057d7 (41:57d7)
-	call ClearBGPalettes
-	call DisableLCD
-	ld hl, MysteryGiftJP_GFX
-	ld de, vTiles2 tile $00
-	ld a, BANK(MysteryGiftJP_GFX)
-	lb bc, 4, 0
-	call FarCopyBytes
-	ld hl, MysteryGiftJP_GFX + $40 tiles
-	ld de, vTiles0 tile $00
-	ld a, BANK(MysteryGiftJP_GFX)
-	ld bc, $80
-	call FarCopyBytes
-	hlcoord 0, 0
-	ld a, $3f
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	call ByteFill
-	hlcoord 3, 7
-	lb bc, 9, 15
-	call ClearBox
-	hlcoord 0, 0
-	ld a, $0
-	ld [hli], a
-	inc a
-	ld [hl], a
-	hlcoord 0, 1
-	inc a
-	ld [hli], a
-	inc a
-	ld [hl], a
-	hlcoord 4, 2
-	ld a, $13
-	call .Load11Row
-	hlcoord 4, 3
-	ld a, $1e
-	call .Load12Row
-	hlcoord 4, 4
-	ld a, $2a
-	call .Load12Row
-	hlcoord 1, 2
-	ld [hl], $4
-	hlcoord 1, 3
-	ld a, $5
-	call .Load14Column
-	ld a, $9
-	hlcoord 18, 5
-	call .Load11Column
-	hlcoord 2, 5
-	ld a, $b
-	call .Load16Row
-	hlcoord 2, 16
-	ld a, $7
-	call .Load16Row
-	hlcoord 2, 5
-	ld a, $d
-	call .Load6Row
-	hlcoord 8, 5
-	ld [hl], $c
-	hlcoord 18, 5
-	ld [hl], $a
-	hlcoord 18, 16
-	ld [hl], $8
-	hlcoord 1, 16
-	ld [hl], $6
-	hlcoord 2, 6
-	ld a, $37
-	call .Load16Row
-	hlcoord 2, 15
-	ld a, $3d
-	call .Load16Row
-	hlcoord 2, 6
-	ld a, $39
-	call .Load9Column
-	hlcoord 17, 6
-	ld a, $3b
-	call .Load9Column
-	hlcoord 2, 6
-	ld [hl], $36
-	hlcoord 17, 6
-	ld [hl], $38
-	hlcoord 2, 15
-	ld [hl], $3c
-	hlcoord 17, 15
-	ld [hl], $3e
-	ld de, wVirtualOAMSprite00
-	ld hl, .OAM_data
-	ld bc, 16 * SPRITEOAMSTRUCT_LENGTH
-	call CopyBytes
-	call EnableLCD
-	call WaitBGMap
-	ld b, $2
-	farcall GetMysteryGift_MobileAdapterLayout
-	jp SetPalettes
-
-.Load6Row: ; 1058c6 (41:58c6)
-	ld b,  6
-	jr .row_loop
-
-.Load11Row: ; 1058ca (41:58ca)
-	ld b, 11
-	jr .row_loop
-
-.Load12Row: ; 1058ce (41:58ce)
-	ld b, 12
-
-.row_loop ; 1058d0 (41:58d0)
-	ld [hli], a
-	inc a
-	dec b
-	jr nz, .row_loop
-	ret
-
-.Load9Column: ; 1058d6 (41:58d6)
-	ld b,  9
-	jr .column_loop
-
-.Load11Column: ; 1058da (41:58da)
-	ld b, 11
-	jr .column_loop
-
-.Load14Column: ; 1058de (41:58de)
-	ld b, 14
-
-.column_loop ; 1058e0 (41:58e0)
-	ld [hl], a
-	ld de, SCREEN_WIDTH
-	add hl, de
-	dec b
-	jr nz, .column_loop
-	ret
-
-.Load16Row: ; 1058e9 (41:58e9)
-	ld b, 16
-.row_loop_no_inc
-	ld [hli], a
-	dec b
-	jr nz, .row_loop_no_inc
-	ret
-; 1058f0 (41:58f0)
-
-.OAM_data: ; 1058f0
-	dsprite  2, 1,  6, 4, $00, 0
-	dsprite  2, 1,  7, 4, $01, 0
-	dsprite  2, 1,  8, 4, $02, 0
-	dsprite  2, 1,  9, 4, $03, 0
-	dsprite  3, 1,  6, 4, $04, 0
-	dsprite  3, 1,  7, 4, $05, 0
-	dsprite  3, 1,  8, 4, $06, 0
-	dsprite  3, 1,  9, 4, $07, 0
-	dsprite  0, 1, 11, 4, $00, 0
-	dsprite  0, 1, 12, 4, $01, 0
-	dsprite  0, 1, 13, 4, $02, 0
-	dsprite  0, 1, 14, 4, $03, 0
-	dsprite  1, 1, 11, 4, $04, 0
-	dsprite  1, 1, 12, 4, $05, 0
-	dsprite  1, 1, 13, 4, $06, 0
-	dsprite  1, 1, 14, 4, $07, 0
-
-; japanese mystery gift gfx
-MysteryGiftJP_GFX: ; 105930
-INCBIN "gfx/mystery_gift/mystery_gift_jp.2bpp"
--- a/engine/mystery_gift_2.asm
+++ /dev/null
@@ -1,152 +1,0 @@
-PrepMysteryGiftDataToSend: ; 2c642 (b:4642)
-	ld de, wMysteryGiftStaging
-	ld a, $1
-	ld [de], a
-	inc de ; wc801
-	ld a, BANK(sGameData)
-	call GetSRAMBank
-	ld hl, sPlayerData + wPlayerID - wPlayerData
-	ld a, [hli]
-	ld [de], a
-	ld b, a
-	inc de ; wc802
-	ld a, [hl]
-	ld [de], a
-	ld c, a
-	inc de ; wc803
-	push bc
-	ld hl, sPlayerData + wPlayerName - wPlayerData
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	push de ; wc80e
-	ld hl, sPokemonData + wPokedexCaught - wPokemonData
-	ld b, wEndPokedexCaught - wPokedexCaught
-	call CountSetBits
-	pop de
-	pop bc
-	ld a, [wd265]
-	ld [de], a
-	inc de ; wc80f
-	call CloseSRAM
-	call Random
-	and 1
-	ld [de], a
-	inc de ; wc810
-	call .RandomSample
-	ld [de], a
-	inc de ; wc811
-	ld a, c
-	ld c, b
-	ld b, a
-	call .RandomSample
-	ld [de], a
-	inc de ; wc812
-	ld a, BANK(sBackupMysteryGiftItem)
-	call GetSRAMBank
-	ld a, [sBackupMysteryGiftItem]
-	ld [de], a
-	inc de
-	ld a, [sBackupMysteryGiftItem + 1]
-	ld [de], a
-	ld a, $14
-	ld [wca00], a
-	call CloseSRAM
-	ld hl, wMysteryGiftStaging
-	ld de, wMysteryGiftPlayerData
-	ld bc, wMysteryGiftPlayerDataEnd - wMysteryGiftPlayerData
-	jp CopyBytes
-
-.RandomSample: ; 2c6ac (b:46ac)
-	push de
-	call Random
-	cp 10 percent
-	jr c, .tenpercent
-	call Random
-	and %111
-	ld d, a
-	rl d
-	ld e, $80
-.loop
-	rlc e
-	dec a
-	jr nz, .loop
-	ld a, e
-	and c
-	jr z, .skip
-	ld a, $1
-.skip
-	add d
-	jr .done
-
-.tenpercent
-	call Random
-	cp 20 percent - 1
-	jr c, .twopercent
-	call Random
-	and %011
-	ld d, a
-	rl d
-	ld e, $80
-.loop2
-	rlc e
-	dec a
-	jr nz, .loop2
-	ld a, e
-	and b
-	jr z, .skip2
-	ld a, $1
-.skip2
-	add d
-	add $10
-	jr .done
-
-.twopercent
-	call Random
-	cp 20 percent - 1
-	jr c, .pointfourpercent
-	ld a, b
-	swap a
-	and $7
-	add $18
-	jr .done
-
-.pointfourpercent
-	ld a, b
-	and $80
-	ld a, $20
-	jr z, .done
-	ld a, $21
-
-.done
-	pop de
-	ret
-
-MysteryGiftGetItemHeldEffect: ; 2c708 (b:4708)
-	ld a, c
-	cp MysteryGiftItems.End - MysteryGiftItems
-	jr nc, MysteryGiftFallbackItem
-	ld hl, MysteryGiftItems
-	ld b, 0
-	add hl, bc
-	ld c, [hl]
-	ret
-
-MysteryGiftGetDecoration: ; 2c715 (b:4715)
-	ld a, c
-	cp MysteryGiftDecos.End - MysteryGiftDecos
-	jr nc, MysteryGiftFallbackItem
-	ld hl, MysteryGiftDecos
-	ld b, 0
-	add hl, bc
-	ld c, [hl]
-	ret
-
-MysteryGiftFallbackItem: ; 2c722 (b:4722)
-	ld c, DECO_POLKADOT_BED ; GREAT_BALL
-	ret
-; 2c725 (b:4725)
-
-
-INCLUDE "data/items/mystery_gift_items.asm"
-
-INCLUDE "data/decorations/mystery_gift_decos.asm"
--- a/engine/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/npc_movement.asm
+++ /dev/null
@@ -1,573 +1,0 @@
-Function6ec1: ; 6ec1
-
-	ld hl, OBJECT_PALETTE
-	add hl, bc
-	bit 5, [hl]
-	jr z, .not_bit_5
-
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	bit 4, [hl] ; lost, uncomment next line to fix
-;	jr nz, .resume
-	push hl
-	push bc
-	call Function6f2c
-	pop bc
-	pop hl
-	ret c
-	jr .resume
-
-.not_bit_5
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	bit 4, [hl]
-	jr nz, .resume
-	push hl
-	push bc
-	call Function6f07
-	pop bc
-	pop hl
-	ret c
-
-.resume
-	bit 6, [hl]
-	jr nz, .bit_6
-
-	push hl
-	push bc
-	call WillObjectBumpIntoSomeoneElse
-	pop bc
-	pop hl
-	ret c
-
-.bit_6
-	bit 5, [hl]
-	jr nz, .bit_5
-	push hl
-	call HasObjectReachedMovementLimit
-	pop hl
-	ret c
-
-	push hl
-	call IsObjectMovingOffEdgeOfScreen
-	pop hl
-	ret c
-
-.bit_5
-	and a
-	ret
-; 6f07
-
-
-Function6f07: ; 6f07
-	call Function6f5f
-	ret c
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	ld hl, OBJECT_PALETTE
-	add hl, bc
-	bit OAM_PRIORITY, [hl]
-	jp nz, Function6fa1
-	ld hl, OBJECT_NEXT_TILE
-	add hl, bc
-	ld a, [hl]
-	ld d, a
-	call GetTileCollision
-	and a ; LANDTILE
-	jr z, Function6f3e
-	scf
-	ret
-; 6f2c
-
-Function6f2c: ; 6f2c
-	call Function6f5f
-	ret c
-	ld hl, OBJECT_NEXT_TILE
-	add hl, bc
-	ld a, [hl]
-	call GetTileCollision
-	cp WATERTILE
-	jr z, Function6f3e
-	scf
-	ret
-; 6f3e
-
-Function6f3e: ; 6f3e
-	ld hl, OBJECT_NEXT_TILE
-	add hl, bc
-	ld a, [hl]
-	call Function6f7f
-	ret nc
-	push af
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld a, [hl]
-	maskbits NUM_DIRECTIONS
-	ld e, a
-	ld d, 0
-	ld hl, .data_6f5b
-	add hl, de
-	pop af
-	and [hl]
-	ret z
-	scf
-	ret
-; 6f5b
-
-.data_6f5b
-	db DOWN_MASK, UP_MASK, RIGHT_MASK, LEFT_MASK
-; 6f5f
-
-Function6f5f: ; 6f5f
-	ld hl, OBJECT_STANDING_TILE
-	add hl, bc
-	ld a, [hl]
-	call Function6f7f
-	ret nc
-	push af
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	maskbits NUM_DIRECTIONS
-	ld e, a
-	ld d, 0
-	ld hl, .data_6f7b
-	add hl, de
-	pop af
-	and [hl]
-	ret z
-	scf
-	ret
-; 6f7b
-
-.data_6f7b
-	db UP_MASK, DOWN_MASK, LEFT_MASK, RIGHT_MASK
-; 6f7f
-
-Function6f7f: ; 6f7f
-	ld d, a
-	and $f0
-	cp $b0
-	jr z, .done
-	cp $c0
-	jr z, .done
-	xor a
-	ret
-
-.done
-	ld a, d
-	and 7
-	ld e, a
-	ld d, 0
-	ld hl, .data_6f99
-	add hl, de
-	ld a, [hl]
-	scf
-	ret
-; 6f99
-
-.data_6f99
-	db  8, 4, 1, 2
-	db 10, 6, 9, 5
-; 6fa1
-
-Function6fa1: ; 6fa1
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld a, [hl]
-	maskbits NUM_DIRECTIONS
-	jr z, .down
-	dec a
-	jr z, .up
-	dec a
-	jr z, .left
-	jr .right
-
-.down
-	inc e
-	push de
-	inc d
-	jr .continue
-
-.up
-	push de
-	inc d
-	jr .continue
-
-.left
-	push de
-	inc e
-	jr .continue
-
-.right
-	inc d
-	push de
-	inc e
-
-.continue
-	call GetCoordTile
-	call GetTileCollision
-	pop de
-	and a ; LANDTILE
-	jr nz, .not_land
-	call GetCoordTile
-	call GetTileCollision
-	and a ; LANDTILE
-	jr nz, .not_land
-	xor a
-	ret
-
-.not_land
-	scf
-	ret
-; 6fd9
-
-
-
-CheckFacingObject:: ; 6fd9
-
-	call GetFacingTileCoord
-
-; Double the distance for counter tiles.
-	call CheckCounterTile
-	jr nz, .asm_6ff1
-
-	ld a, [wPlayerStandingMapX]
-	sub d
-	cpl
-	inc a
-	add d
-	ld d, a
-
-	ld a, [wPlayerStandingMapY]
-	sub e
-	cpl
-	inc a
-	add e
-	ld e, a
-
-.asm_6ff1
-	ld bc, wObjectStructs ; redundant
-	ld a, 0
-	ld [hMapObjectIndexBuffer], a
-	call IsNPCAtCoord
-	ret nc
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld a, [hl]
-	cp STANDING
-	jr z, .standing
-	xor a
-	ret
-
-.standing
-	scf
-	ret
-; 7009
-
-
-WillObjectBumpIntoSomeoneElse: ; 7009
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	jr IsNPCAtCoord
-; 7015
-
-Unreferenced_Function7015:
-	ld a, [hMapObjectIndexBuffer]
-	call GetObjectStruct
-	call .CheckWillBeFacingNPC
-	call IsNPCAtCoord
-	ret
-
-.CheckWillBeFacingNPC: ; 7021
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	call GetSpriteDirection
-	and a
-	jr z, .down
-	cp OW_UP
-	jr z, .up
-	cp OW_LEFT
-	jr z, .left
-	inc d
-	ret
-
-.down
-	inc e
-	ret
-
-.up
-	dec e
-	ret
-
-.left
-	dec d
-	ret
-; 7041
-
-IsNPCAtCoord: ; 7041
-	ld bc, wObjectStructs
-	xor a
-.loop
-	ld [hObjectStructIndexBuffer], a
-	call DoesObjectHaveASprite
-	jr z, .next
-
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	bit 7, [hl]
-	jr nz, .next
-
-	ld hl, OBJECT_PALETTE
-	add hl, bc
-	bit 7, [hl]
-	jr z, .got
-
-	call Function7171
-	jr nc, .ok
-	jr .ok2
-
-.got
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	cp d
-	jr nz, .ok
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld a, [hl]
-	cp e
-	jr nz, .ok
-
-.ok2
-	ld a, [hMapObjectIndexBuffer]
-	ld l, a
-	ld a, [hObjectStructIndexBuffer]
-	cp l
-	jr nz, .setcarry
-
-.ok
-	ld hl, OBJECT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	cp d
-	jr nz, .next
-	ld hl, OBJECT_MAP_Y
-	add hl, bc
-	ld a, [hl]
-	cp e
-	jr nz, .next
-	ld a, [hMapObjectIndexBuffer]
-	ld l, a
-	ld a, [hObjectStructIndexBuffer]
-	cp l
-	jr nz, .setcarry
-
-.next
-	ld hl, OBJECT_STRUCT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	ld a, [hObjectStructIndexBuffer]
-	inc a
-	cp NUM_OBJECT_STRUCTS
-	jr nz, .loop
-	and a
-	ret
-
-.setcarry
-	scf
-	ret
-; 70a4
-
-HasObjectReachedMovementLimit: ; 70a4
-	ld hl, OBJECT_RADIUS
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .nope
-	and $f
-	jr z, .check_y
-	ld e, a
-	ld d, a
-	ld hl, OBJECT_INIT_X
-	add hl, bc
-	ld a, [hl]
-	sub d
-	ld d, a
-	ld a, [hl]
-	add e
-	ld e, a
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	cp d
-	jr z, .yes
-	cp e
-	jr z, .yes
-
-.check_y
-	ld hl, OBJECT_RADIUS
-	add hl, bc
-	ld a, [hl]
-	swap a
-	and $f
-	jr z, .nope
-	ld e, a
-	ld d, a
-	ld hl, OBJECT_INIT_Y
-	add hl, bc
-	ld a, [hl]
-	sub d
-	ld d, a
-	ld a, [hl]
-	add e
-	ld e, a
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld a, [hl]
-	cp d
-	jr z, .yes
-	cp e
-	jr z, .yes
-
-.nope
-	xor a
-	ret
-
-.yes
-	scf
-	ret
-; 70ed
-
-IsObjectMovingOffEdgeOfScreen: ; 70ed
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, [wXCoord]
-	cp [hl]
-	jr z, .check_y
-	jr nc, .yes
-	add $9
-	cp [hl]
-	jr c, .yes
-
-.check_y
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld a, [wYCoord]
-	cp [hl]
-	jr z, .nope
-	jr nc, .yes
-	add $8
-	cp [hl]
-	jr c, .yes
-
-.nope
-	and a
-	ret
-
-.yes
-	scf
-	ret
-; 7113
-
-Unreferenced_Function7113:
-	ld a, [wPlayerStandingMapX]
-	ld d, a
-	ld a, [wPlayerStandingMapY]
-	ld e, a
-	ld bc, wObjectStructs
-	xor a
-.loop
-	ld [hObjectStructIndexBuffer], a
-	call DoesObjectHaveASprite
-	jr z, .next
-	ld hl, OBJECT_MOVEMENTTYPE
-	add hl, bc
-	ld a, [hl]
-	cp SPRITEMOVEDATA_BIGDOLLSYM
-	jr nz, .not_snorlax
-	call Function7171
-	jr c, .yes
-	jr .next
-
-.not_snorlax
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld a, [hl]
-	cp e
-	jr nz, .check_current_coords
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	cp d
-	jr nz, .check_current_coords
-	ld a, [hObjectStructIndexBuffer]
-	cp $0
-	jr z, .next
-	jr .yes
-
-.check_current_coords
-	ld hl, OBJECT_MAP_Y
-	add hl, bc
-	ld a, [hl]
-	cp e
-	jr nz, .next
-	ld hl, OBJECT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	cp d
-	jr nz, .next
-	jr .yes
-
-.next
-	ld hl, OBJECT_STRUCT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	ld a, [hObjectStructIndexBuffer]
-	inc a
-	cp NUM_OBJECT_STRUCTS
-	jr nz, .loop
-	xor a
-	ret
-
-.yes
-	scf
-	ret
-; 7171
-
-
-Function7171: ; 7171
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, d
-	sub [hl]
-	jr c, .nope
-	cp $2
-	jr nc, .nope
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld a, e
-	sub [hl]
-	jr c, .nope
-	cp $2
-	jr nc, .nope
-	scf
-	ret
-
-.nope
-	and a
-	ret
-; 718d
--- a/engine/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/overworld.asm
+++ /dev/null
@@ -1,715 +1,0 @@
-GetEmote2bpp: ; 1412a
-	ld a, $1
-	ld [rVBK], a
-	call Get2bpp
-	xor a
-	ld [rVBK], a
-	ret
-; 14135
-
-_ReplaceKrisSprite:: ; 14135
-	call GetPlayerSprite
-	ld a, [wUsedSprites]
-	ld [hUsedSpriteIndex], a
-	ld a, [wUsedSprites + 1]
-	ld [hUsedSpriteTile], a
-	call GetUsedSprite
-	ret
-; 14146
-
-Function14146: ; mobile
-	ld hl, wSpriteFlags
-	ld a, [hl]
-	push af
-	res 7, [hl]
-	set 6, [hl]
-	call LoadUsedSpritesGFX
-	pop af
-	ld [wSpriteFlags], a
-	ret
-; 14157
-
-Function14157: ; mobile
-	ld hl, wSpriteFlags
-	ld a, [hl]
-	push af
-	set 7, [hl]
-	res 6, [hl]
-	call LoadUsedSpritesGFX
-	pop af
-	ld [wSpriteFlags], a
-	ret
-; 14168
-
-RefreshSprites:: ; 14168
-	call .Refresh
-	call LoadUsedSpritesGFX
-	ret
-; 1416f
-
-.Refresh: ; 1416f
-	xor a
-	ld bc, wUsedSpritesEnd - wUsedSprites
-	ld hl, wUsedSprites
-	call ByteFill
-	call GetPlayerSprite
-	call AddMapSprites
-	call LoadAndSortSprites
-	ret
-; 14183
-
-GetPlayerSprite: ; 14183
-; Get Chris or Kris's sprite.
-	ld hl, ChrisStateSprites
-	ld a, [wPlayerSpriteSetupFlags]
-	bit PLAYERSPRITESETUP_FEMALE_TO_MALE_F, a
-	jr nz, .go
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .go
-	ld hl, KrisStateSprites
-
-.go
-	ld a, [wPlayerState]
-	ld c, a
-.loop
-	ld a, [hli]
-	cp c
-	jr z, .good
-	inc hl
-	cp -1
-	jr nz, .loop
-
-; Any player state not in the array defaults to Chris's sprite.
-	xor a ; ld a, PLAYER_NORMAL
-	ld [wPlayerState], a
-	ld a, SPRITE_CHRIS
-	jr .finish
-
-.good
-	ld a, [hl]
-
-.finish
-	ld [wUsedSprites + 0], a
-	ld [wPlayerSprite], a
-	ld [wPlayerObjectSprite], a
-	ret
-
-INCLUDE "data/sprites/player_sprites.asm"
-
-
-AddMapSprites: ; 141c9
-	call GetMapEnvironment
-	call CheckOutdoorMap
-	jr z, .outdoor
-	call AddIndoorSprites
-	ret
-
-.outdoor
-	call AddOutdoorSprites
-	ret
-; 141d9
-
-
-AddIndoorSprites: ; 141d9
-	ld hl, wMap1ObjectSprite
-	ld a, 1
-.loop
-	push af
-	ld a, [hl]
-	call AddSpriteGFX
-	ld de, OBJECT_LENGTH
-	add hl, de
-	pop af
-	inc a
-	cp NUM_OBJECTS
-	jr nz, .loop
-	ret
-; 141ee
-
-
-AddOutdoorSprites: ; 141ee
-	ld a, [wMapGroup]
-	dec a
-	ld c, a
-	ld b, 0
-	ld hl, OutdoorSprites
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld c, MAX_OUTDOOR_SPRITES
-.loop
-	push bc
-	ld a, [hli]
-	call AddSpriteGFX
-	pop bc
-	dec c
-	jr nz, .loop
-	ret
-; 14209
-
-
-LoadUsedSpritesGFX: ; 14209
-	ld a, MAPCALLBACK_SPRITES
-	call RunMapCallback
-	call GetUsedSprites
-	call .LoadMiscTiles
-	ret
-; 14215
-
-.LoadMiscTiles: ; 14215
-	ld a, [wSpriteFlags]
-	bit 6, a
-	ret nz
-
-	ld c, EMOTE_SHADOW
-	farcall LoadEmote
-	call GetMapEnvironment
-	call CheckOutdoorMap
-	ld c, EMOTE_GRASS_RUSTLE
-	jr z, .outdoor
-	ld c, EMOTE_BOULDER_DUST
-.outdoor
-	farcall LoadEmote
-	ret
-; 14236
-
-
-
-SafeGetSprite: ; 14236
-	push hl
-	call GetSprite
-	pop hl
-	ret
-; 1423c
-
-GetSprite: ; 1423c
-	call GetMonSprite
-	ret c
-
-	ld hl, OverworldSprites + SPRITEDATA_ADDR
-	dec a
-	ld c, a
-	ld b, 0
-	ld a, NUM_SPRITEDATA_FIELDS
-	call AddNTimes
-	; load the address into de
-	ld a, [hli]
-	ld e, a
-	ld a, [hli]
-	ld d, a
-	; load the length into c
-	ld a, [hli]
-	swap a
-	ld c, a
-	; load the sprite bank into both b and h
-	ld b, [hl]
-	ld a, [hli]
-	; load the sprite type into l
-	ld l, [hl]
-	ld h, a
-	ret
-; 14259
-
-
-GetMonSprite: ; 14259
-; Return carry if a monster sprite was loaded.
-
-	cp SPRITE_POKEMON
-	jr c, .Normal
-	cp SPRITE_DAY_CARE_MON_1
-	jr z, .BreedMon1
-	cp SPRITE_DAY_CARE_MON_2
-	jr z, .BreedMon2
-	cp SPRITE_VARS
-	jr nc, .Variable
-	jr .Icon
-
-.Normal:
-	and a
-	ret
-
-.Icon:
-	sub SPRITE_POKEMON
-	ld e, a
-	ld d, 0
-	ld hl, SpriteMons
-	add hl, de
-	ld a, [hl]
-	jr .Mon
-
-.BreedMon1
-	ld a, [wBreedMon1Species]
-	jr .Mon
-
-.BreedMon2
-	ld a, [wBreedMon2Species]
-
-.Mon:
-	ld e, a
-	and a
-	jr z, .NoBreedmon
-
-	farcall LoadOverworldMonIcon
-
-	ld l, 1
-	ld h, 0
-	scf
-	ret
-
-.Variable:
-	sub SPRITE_VARS
-	ld e, a
-	ld d, 0
-	ld hl, wVariableSprites
-	add hl, de
-	ld a, [hl]
-	and a
-	jp nz, GetMonSprite
-
-.NoBreedmon:
-	ld a, 1
-	ld l, 1
-	ld h, 0
-	and a
-	ret
-; 142a7
-
-
-_DoesSpriteHaveFacings:: ; 142a7
-; Checks to see whether we can apply a facing to a sprite.
-; Returns carry unless the sprite is a Pokemon or a Still Sprite.
-	cp SPRITE_POKEMON
-	jr nc, .only_down
-
-	push hl
-	push bc
-	ld hl, OverworldSprites + SPRITEDATA_TYPE
-	dec a
-	ld c, a
-	ld b, 0
-	ld a, NUM_SPRITEDATA_FIELDS
-	call AddNTimes
-	ld a, [hl]
-	pop bc
-	pop hl
-	cp STILL_SPRITE
-	jr nz, .only_down
-	scf
-	ret
-
-.only_down
-	and a
-	ret
-; 142c4
-
-
-_GetSpritePalette:: ; 142c4
-	ld a, c
-	call GetMonSprite
-	jr c, .is_pokemon
-
-	ld hl, OverworldSprites + SPRITEDATA_PALETTE
-	dec a
-	ld c, a
-	ld b, 0
-	ld a, NUM_SPRITEDATA_FIELDS
-	call AddNTimes
-	ld c, [hl]
-	ret
-
-.is_pokemon
-	xor a
-	ld c, a
-	ret
-; 142db
-
-
-LoadAndSortSprites: ; 142db
-	call LoadSpriteGFX
-	call SortUsedSprites
-	call ArrangeUsedSprites
-	ret
-; 142e5
-
-
-AddSpriteGFX: ; 142e5
-; Add any new sprite ids to a list of graphics to be loaded.
-; Return carry if the list is full.
-
-	push hl
-	push bc
-	ld b, a
-	ld hl, wUsedSprites + 2
-	ld c, SPRITE_GFX_LIST_CAPACITY - 1
-.loop
-	ld a, [hl]
-	cp b
-	jr z, .exists
-	and a
-	jr z, .new
-	inc hl
-	inc hl
-	dec c
-	jr nz, .loop
-
-	pop bc
-	pop hl
-	scf
-	ret
-
-.exists
-	pop bc
-	pop hl
-	and a
-	ret
-
-.new
-	ld [hl], b
-	pop bc
-	pop hl
-	and a
-	ret
-; 14306
-
-
-LoadSpriteGFX: ; 14306
-; Bug: b is not preserved, so it's useless as a next count.
-; Uncomment the lines below to fix.
-
-	ld hl, wUsedSprites
-	ld b, SPRITE_GFX_LIST_CAPACITY
-.loop
-	ld a, [hli]
-	and a
-	jr z, .done
-	push hl
-	call .LoadSprite
-	pop hl
-	ld [hli], a
-	dec b
-	jr nz, .loop
-
-.done
-	ret
-
-.LoadSprite:
-	; push bc
-	call GetSprite
-	; pop bc
-	ld a, l
-	ret
-; 1431e
-
-
-SortUsedSprites: ; 1431e
-; Bubble-sort sprites by type.
-
-; Run backwards through wUsedSprites to find the last one.
-
-	ld c, SPRITE_GFX_LIST_CAPACITY
-	ld de, wUsedSprites + (SPRITE_GFX_LIST_CAPACITY - 1) * 2
-.FindLastSprite:
-	ld a, [de]
-	and a
-	jr nz, .FoundLastSprite
-	dec de
-	dec de
-	dec c
-	jr nz, .FindLastSprite
-.FoundLastSprite:
-	dec c
-	jr z, .quit
-
-; If the length of the current sprite is
-; higher than a later one, swap them.
-
-	inc de
-	ld hl, wUsedSprites + 1
-
-.CheckSprite:
-	push bc
-	push de
-	push hl
-
-.CheckFollowing:
-	ld a, [de]
-	cp [hl]
-	jr nc, .loop
-
-; Swap the two sprites.
-
-	ld b, a
-	ld a, [hl]
-	ld [hl], b
-	ld [de], a
-	dec de
-	dec hl
-	ld a, [de]
-	ld b, a
-	ld a, [hl]
-	ld [hl], b
-	ld [de], a
-	inc de
-	inc hl
-
-; Keep doing this until everything's in order.
-
-.loop
-	dec de
-	dec de
-	dec c
-	jr nz, .CheckFollowing
-
-	pop hl
-	inc hl
-	inc hl
-	pop de
-	pop bc
-	dec c
-	jr nz, .CheckSprite
-
-.quit
-	ret
-; 14355
-
-
-ArrangeUsedSprites: ; 14355
-; Get the length of each sprite and space them out in VRAM.
-; Crystal introduces a second table in VRAM bank 0.
-
-	ld hl, wUsedSprites
-	ld c, SPRITE_GFX_LIST_CAPACITY
-	ld b, 0
-.FirstTableLength:
-; Keep going until the end of the list.
-	ld a, [hli]
-	and a
-	jr z, .quit
-
-	ld a, [hl]
-	call GetSpriteLength
-
-; Spill over into the second table after $80 tiles.
-	add b
-	cp $80
-	jr z, .loop
-	jr nc, .SecondTable
-
-.loop
-	ld [hl], b
-	inc hl
-	ld b, a
-
-; Assumes the next table will be reached before c hits 0.
-	dec c
-	jr nz, .FirstTableLength
-
-.SecondTable:
-; The second tile table starts at tile $80.
-	ld b, $80
-	dec hl
-.SecondTableLength:
-; Keep going until the end of the list.
-	ld a, [hli]
-	and a
-	jr z, .quit
-
-	ld a, [hl]
-	call GetSpriteLength
-
-; There are only two tables, so don't go any further than that.
-	add b
-	jr c, .quit
-
-	ld [hl], b
-	ld b, a
-	inc hl
-
-	dec c
-	jr nz, .SecondTableLength
-
-.quit
-	ret
-; 14386
-
-
-GetSpriteLength: ; 14386
-; Return the length of sprite type a in tiles.
-
-	cp WALKING_SPRITE
-	jr z, .AnyDirection
-	cp STANDING_SPRITE
-	jr z, .AnyDirection
-	cp STILL_SPRITE
-	jr z, .OneDirection
-
-	ld a, 12
-	ret
-
-.AnyDirection:
-	ld a, 12
-	ret
-
-.OneDirection:
-	ld a, 4
-	ret
-; 1439b
-
-
-GetUsedSprites: ; 1439b
-	ld hl, wUsedSprites
-	ld c, SPRITE_GFX_LIST_CAPACITY
-
-.loop
-	ld a, [wSpriteFlags]
-	res 5, a
-	ld [wSpriteFlags], a
-
-	ld a, [hli]
-	and a
-	jr z, .done
-	ld [hUsedSpriteIndex], a
-
-	ld a, [hli]
-	ld [hUsedSpriteTile], a
-
-	bit 7, a
-	jr z, .dont_set
-
-	ld a, [wSpriteFlags]
-	set 5, a ; load VBank0
-	ld [wSpriteFlags], a
-
-.dont_set
-	push bc
-	push hl
-	call GetUsedSprite
-	pop hl
-	pop bc
-	dec c
-	jr nz, .loop
-
-.done
-	ret
-; 143c8
-
-GetUsedSprite: ; 143c8
-	ld a, [hUsedSpriteIndex]
-	call SafeGetSprite
-	ld a, [hUsedSpriteTile]
-	call .GetTileAddr
-	push hl
-	push de
-	push bc
-	ld a, [wSpriteFlags]
-	bit 7, a
-	jr nz, .skip
-	call .CopyToVram
-
-.skip
-	pop bc
-	ld l, c
-	ld h, $0
-rept 4
-	add hl, hl
-endr
-	pop de
-	add hl, de
-	ld d, h
-	ld e, l
-	pop hl
-
-	ld a, [wSpriteFlags]
-	bit 5, a
-	jr nz, .done
-	bit 6, a
-	jr nz, .done
-
-	ld a, [hUsedSpriteIndex]
-	call _DoesSpriteHaveFacings
-	jr c, .done
-
-	ld a, h
-	add $8
-	ld h, a
-	call .CopyToVram
-
-.done
-	ret
-; 14406
-
-.GetTileAddr: ; 14406
-; Return the address of tile (a) in (hl).
-	and $7f
-	ld l, a
-	ld h, 0
-rept 4
-	add hl, hl
-endr
-	ld a, l
-	add LOW(vTiles0)
-	ld l, a
-	ld a, h
-	adc HIGH(vTiles0)
-	ld h, a
-	ret
-; 14418
-
-.CopyToVram: ; 14418
-	ld a, [rVBK]
-	push af
-	ld a, [wSpriteFlags]
-	bit 5, a
-	ld a, $1
-	jr z, .bankswitch
-	ld a, $0
-
-.bankswitch
-	ld [rVBK], a
-	call Get2bpp
-	pop af
-	ld [rVBK], a
-	ret
-; 1442f
-
-LoadEmote:: ; 1442f
-; Get the address of the pointer to emote c.
-	ld a, c
-	ld bc, 6 ; sizeof(emote)
-	ld hl, Emotes
-	call AddNTimes
-; Load the emote address into de
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-; load the length of the emote (in tiles) into c
-	inc hl
-	ld c, [hl]
-	swap c
-; load the emote pointer bank into b
-	inc hl
-	ld b, [hl]
-; load the VRAM destination into hl
-	inc hl
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-; if the emote has a length of 0, do not proceed (error handling)
-	ld a, c
-	and a
-	ret z
-	call GetEmote2bpp
-	ret
-; 1444d
-
-
-INCLUDE "data/sprites/emotes.asm"
-
-INCLUDE "data/sprites/sprite_mons.asm"
-
-INCLUDE "data/maps/outdoor_sprites.asm"
-
-INCLUDE "data/sprites/sprites.asm"
--- /dev/null
+++ b/engine/overworld/decorations.asm
@@ -1,0 +1,1303 @@
+InitDecorations: ; 26751 (9:6751)
+	ld a, DECO_FEATHERY_BED
+	ld [wDecoBed], a
+	ld a, DECO_TOWN_MAP
+	ld [wDecoPoster], a
+	ret
+
+_PlayerDecorationMenu: ; 0x2675c
+	ld a, [wWhichIndexSet]
+	push af
+	ld hl, .MenuHeader
+	call LoadMenuHeader
+	xor a
+	ld [wBuffer5], a
+	ld a, $1
+	ld [wBuffer6], a
+.top_loop
+	ld a, [wBuffer6]
+	ld [wMenuCursorBuffer], a
+	call .FindCategoriesWithOwnedDecos
+	call DoNthMenu
+	ld a, [wMenuCursorY]
+	ld [wBuffer6], a
+	jr c, .exit_menu
+	ld a, [wMenuSelection]
+	ld hl, .pointers
+	call MenuJumptable
+	jr nc, .top_loop
+
+.exit_menu
+	call ExitMenu
+	pop af
+	ld [wWhichIndexSet], a
+	ld a, [wBuffer5]
+	ld c, a
+	ret
+; 0x2679a
+
+.MenuHeader: ; 0x2679a
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 5, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+	dw .MenuData
+	db 1 ; default option
+; 0x267a2
+
+.MenuData: ; 0x267a2
+	db STATICMENU_CURSOR | STATICMENU_WRAP ; flags
+	db 0 ; items
+	dw wd002
+	dw PlaceNthMenuStrings
+	dw .pointers
+; 0x267aa
+
+.pointers ; 267aa
+	dw DecoBedMenu, .bed
+	dw DecoCarpetMenu, .carpet
+	dw DecoPlantMenu, .plant
+	dw DecoPosterMenu, .poster
+	dw DecoConsoleMenu, .game
+	dw DecoOrnamentMenu, .ornament
+	dw DecoBigDollMenu, .big_doll
+	dw DecoExitMenu, .exit
+
+.bed      db "BED@"
+.carpet   db "CARPET@"
+.plant    db "PLANT@"
+.poster   db "POSTER@"
+.game     db "GAME CONSOLE@"
+.ornament db "ORNAMENT@"
+.big_doll db "BIG DOLL@"
+.exit     db "EXIT@"
+; 26806
+
+.FindCategoriesWithOwnedDecos: ; 26806
+	xor a
+	ld [wWhichIndexSet], a
+	call .ClearStringBuffer2
+	call .FindOwndDecos
+	ld a, 7
+	call .AppendToStringBuffer2
+	ld hl, wStringBuffer2
+	ld de, wd002
+	ld bc, ITEM_NAME_LENGTH
+	call CopyBytes
+	ret
+
+.ClearStringBuffer2: ; 26822 (9:6822)
+	ld hl, wStringBuffer2
+	xor a
+	ld [hli], a
+	ld bc, ITEM_NAME_LENGTH - 1
+	ld a, -1
+	call ByteFill
+	ret
+
+.AppendToStringBuffer2: ; 26830 (9:6830)
+	ld hl, wStringBuffer2
+	inc [hl]
+	ld e, [hl]
+	ld d, 0
+	add hl, de
+	ld [hl], a
+	ret
+
+.FindOwndDecos: ; 2683a (9:683a)
+	ld hl, .dw
+.loop
+	ld a, [hli]
+	ld e, a
+	ld a, [hli]
+	ld d, a
+	or e
+	jr z, .done
+	push hl
+	call _de_
+	pop hl
+	jr nc, .next
+	ld a, [hl]
+	push hl
+	call .AppendToStringBuffer2
+	pop hl
+.next
+	inc hl
+	jr .loop
+.done
+	ret
+; 26855 (9:6855)
+
+.dw ; 26855
+	dwb FindOwnedBeds, 0 ; bed
+	dwb FindOwnedCarpets, 1 ; carpet
+	dwb FindOwnedPlants, 2 ; plant
+	dwb FindOwnedPosters, 3 ; poster
+	dwb FindOwnedConsoles, 4 ; game console
+	dwb FindOwnedOrnaments, 5 ; ornament
+	dwb FindOwnedBigDolls, 6 ; big doll
+	dw 0 ; end
+; 2686c
+
+Deco_FillTempWithMinusOne: ; 2686c
+	xor a
+	ld hl, wd002
+	ld [hli], a
+	ld a, -1
+	ld bc, $10
+	call ByteFill
+	ret
+; 2687a
+
+CheckAllDecorationFlags: ; 2687a
+.loop
+	ld a, [hli]
+	cp -1
+	jr z, .done
+	push hl
+	push af
+	ld b, CHECK_FLAG
+	call DecorationFlagAction
+	ld a, c
+	and a
+	pop bc
+	ld a, b
+	call nz, AppendDecoIndex
+	pop hl
+	jr .loop
+
+.done
+	ret
+; 26891
+
+AppendDecoIndex: ; 26891
+	ld hl, wd002
+	inc [hl]
+	ld e, [hl]
+	ld d, $0
+	add hl, de
+	ld [hl], a
+	ret
+; 2689b
+
+FindOwnedDecosInCategory: ; 2689b
+	push bc
+	push hl
+	call Deco_FillTempWithMinusOne
+	pop hl
+	call CheckAllDecorationFlags
+	pop bc
+	ld a, [wd002]
+	and a
+	ret z
+
+	ld a, c
+	call AppendDecoIndex
+	ld a, 0
+	call AppendDecoIndex
+	scf
+	ret
+; 268b5
+
+DecoBedMenu: ; 268b5
+	call FindOwnedBeds
+	call PopulateDecoCategoryMenu
+	xor a
+	ret
+; 268bd
+
+FindOwnedBeds: ; 268bd
+	ld hl, .beds
+	ld c, BEDS
+	jp FindOwnedDecosInCategory
+; 268c5
+
+.beds ; 268c5
+	db DECO_FEATHERY_BED ; 2
+	db DECO_PINK_BED ; 3
+	db DECO_POLKADOT_BED ; 4
+	db DECO_PIKACHU_BED ; 5
+	db -1
+; 268ca
+
+DecoCarpetMenu: ; 268ca
+	call FindOwnedCarpets
+	call PopulateDecoCategoryMenu
+	xor a
+	ret
+; 268d2
+
+FindOwnedCarpets: ; 268d2
+	ld hl, .carpets
+	ld c, CARPETS
+	jp FindOwnedDecosInCategory
+; 268da
+
+.carpets ; 268da
+	db DECO_RED_CARPET ; 7
+	db DECO_BLUE_CARPET ; 8
+	db DECO_YELLOW_CARPET ; 9
+	db DECO_GREEN_CARPET ; a
+	db -1
+; 268df
+
+DecoPlantMenu: ; 268df
+	call FindOwnedPlants
+	call PopulateDecoCategoryMenu
+	xor a
+	ret
+; 268e7
+
+FindOwnedPlants: ; 268e7
+	ld hl, .plants
+	ld c, PLANTS
+	jp FindOwnedDecosInCategory
+; 268ef
+
+.plants ; 268ef
+	db DECO_MAGNAPLANT ; c
+	db DECO_TROPICPLANT ; d
+	db DECO_JUMBOPLANT ; e
+	db -1
+; 268f3
+
+DecoPosterMenu: ; 268f3
+	call FindOwnedPosters
+	call PopulateDecoCategoryMenu
+	xor a
+	ret
+; 268fb
+
+FindOwnedPosters: ; 268fb
+	ld hl, .posters
+	ld c, POSTERS
+	jp FindOwnedDecosInCategory
+; 26903
+
+.posters ; 26903
+	db DECO_TOWN_MAP ; 10
+	db DECO_PIKACHU_POSTER ; 11
+	db DECO_CLEFAIRY_POSTER ; 12
+	db DECO_JIGGLYPUFF_POSTER ; 13
+	db -1
+; 26908
+
+DecoConsoleMenu: ; 26908
+	call FindOwnedConsoles
+	call PopulateDecoCategoryMenu
+	xor a
+	ret
+; 26910
+
+FindOwnedConsoles: ; 26910
+	ld hl, .consoles
+	ld c, CONSOLES
+	jp FindOwnedDecosInCategory
+; 26918
+
+.consoles ; 26918
+	db DECO_FAMICOM ; 15
+	db DECO_SNES ; 16
+	db DECO_N64 ; 17
+	db DECO_VIRTUAL_BOY ; 18
+	db -1
+; 2691d
+
+DecoOrnamentMenu: ; 2691d
+	call FindOwnedOrnaments
+	call PopulateDecoCategoryMenu
+	xor a
+	ret
+; 26925
+
+FindOwnedOrnaments: ; 26925
+	ld hl, .ornaments
+	ld c, DOLLS
+	jp FindOwnedDecosInCategory
+; 2692d
+
+.ornaments ; 2692d
+	db DECO_PIKACHU_DOLL ; 1e
+	db DECO_SURF_PIKACHU_DOLL ; 1f
+	db DECO_CLEFAIRY_DOLL ; 20
+	db DECO_JIGGLYPUFF_DOLL ; 21
+	db DECO_BULBASAUR_DOLL ; 22
+	db DECO_CHARMANDER_DOLL ; 23
+	db DECO_SQUIRTLE_DOLL ; 24
+	db DECO_POLIWAG_DOLL ; 25
+	db DECO_DIGLETT_DOLL ; 26
+	db DECO_STARMIE_DOLL ; 27
+	db DECO_MAGIKARP_DOLL ; 28
+	db DECO_ODDISH_DOLL ; 29
+	db DECO_GENGAR_DOLL ; 2a
+	db DECO_SHELLDER_DOLL ; 2b
+	db DECO_GRIMER_DOLL ; 2c
+	db DECO_VOLTORB_DOLL ; 2d
+	db DECO_WEEDLE_DOLL ; 2e
+	db DECO_UNOWN_DOLL ; 2f
+	db DECO_GEODUDE_DOLL ; 30
+	db DECO_MACHOP_DOLL ; 31
+	db DECO_TENTACOOL_DOLL ; 32
+	db DECO_GOLD_TROPHY_DOLL ; 33
+	db DECO_SILVER_TROPHY_DOLL ; 34
+	db -1
+; 26945
+
+DecoBigDollMenu: ; 26945
+	call FindOwnedBigDolls
+	call PopulateDecoCategoryMenu
+	xor a
+	ret
+; 2694d
+
+FindOwnedBigDolls: ; 2694d
+	ld hl, .big_dolls
+	ld c, BIG_DOLLS
+	jp FindOwnedDecosInCategory
+; 26955
+
+.big_dolls ; 26955
+	db DECO_BIG_SNORLAX_DOLL ; 1a
+	db DECO_BIG_ONIX_DOLL ; 1b
+	db DECO_BIG_LAPRAS_DOLL ; 1c
+	db -1
+; 26959
+
+DecoExitMenu: ; 26959
+	scf
+	ret
+; 2695b
+
+PopulateDecoCategoryMenu: ; 2695b
+	ld a, [wd002]
+	and a
+	jr z, .empty
+	cp 8
+	jr nc, .beyond_eight
+	xor a
+	ld [wWhichIndexSet], a
+	ld hl, .NonscrollingMenuHeader
+	call LoadMenuHeader
+	call DoNthMenu
+	jr c, .no_action_1
+	call DoDecorationAction2
+
+.no_action_1
+	call ExitMenu
+	ret
+
+.beyond_eight
+	ld hl, wd002
+	ld e, [hl]
+	dec [hl]
+	ld d, 0
+	add hl, de
+	ld [hl], -1
+	call LoadStandardMenuHeader
+	ld hl, .ScrollingMenuHeader
+	call CopyMenuHeader
+	xor a
+	ld [hBGMapMode], a
+	call InitScrollingMenu
+	xor a
+	ld [wMenuScrollPosition], a
+	call ScrollingMenu
+	ld a, [wMenuJoypad]
+	cp 2
+	jr z, .no_action_2
+	call DoDecorationAction2
+
+.no_action_2
+	call ExitMenu
+	ret
+
+.empty
+	ld hl, .Text_nothing_to_choose
+	call MenuTextBoxBackup
+	ret
+; 269b0
+
+.Text_nothing_to_choose: ; 0x269b0
+	; There's nothing to choose.
+	text_jump UnknownText_0x1bc471
+	db "@"
+; 0x269b5
+
+.NonscrollingMenuHeader: ; 0x269b5
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+	dw .NonscrollingMenuData
+	db 1 ; default option
+; 0x269bd
+
+.NonscrollingMenuData: ; 0x269bd
+	db STATICMENU_CURSOR | STATICMENU_WRAP ; flags
+	db 0 ; items
+	dw wd002
+	dw DecorationMenuFunction
+	dw DecorationAttributes
+; 0x269c5
+
+.ScrollingMenuHeader: ; 0x269c5
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 1, 1, SCREEN_WIDTH - 2, SCREEN_HEIGHT - 2
+	dw .ScrollingMenuData
+	db 1 ; default option
+; 0x269cd
+
+.ScrollingMenuData: ; 0x269cd
+	db SCROLLINGMENU_DISPLAY_ARROWS ; flags
+	db 8, 0 ; rows, columns
+	db 1 ; horizontal spacing
+	dbw 0, wd002 ; text pointer
+	dba DecorationMenuFunction
+	dbw 0, 0
+	dbw 0, 0
+; 269dd
+
+
+GetDecorationData: ; 269dd
+	ld hl, DecorationAttributes
+	ld bc, 6
+	call AddNTimes
+	ret
+; 269e7
+
+GetDecorationName: ; 269e7
+	push hl
+	call GetDecorationData
+	call GetDecoName
+	pop hl
+	call CopyName2
+	ret
+; 269f3
+
+DecorationMenuFunction: ; 269f3
+	ld a, [wMenuSelection]
+	push de
+	call GetDecorationData
+	call GetDecoName
+	pop hl
+	call PlaceString
+	ret
+; 26a02
+
+DoDecorationAction2: ; 26a02
+	ld a, [wMenuSelection]
+	call GetDecorationData
+	ld de, 2 ; function 2
+	add hl, de
+	ld a, [hl]
+	ld hl, .DecoActions
+	rst JumpTable
+	ret
+; 26a12
+
+.DecoActions: ; 26a12
+	dw DecoAction_nothing
+	dw DecoAction_setupbed
+	dw DecoAction_putawaybed
+	dw DecoAction_setupcarpet
+	dw DecoAction_putawaycarpet
+	dw DecoAction_setupplant
+	dw DecoAction_putawayplant
+	dw DecoAction_setupposter
+	dw DecoAction_putawayposter
+	dw DecoAction_setupconsole
+	dw DecoAction_putawayconsole
+	dw DecoAction_setupbigdoll
+	dw DecoAction_putawaybigdoll
+	dw DecoAction_setupornament
+	dw DecoAction_putawayornament
+; 26a30
+
+
+GetDecorationFlag: ; 26a30
+	call GetDecorationData
+	ld de, 3 ; event flag
+	add hl, de
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+	ret
+; 26a3b
+
+DecorationFlagAction: ; 26a3b
+	push bc
+	call GetDecorationFlag
+	pop bc
+	call EventFlagAction
+	ret
+; 26a44
+
+GetDecorationSprite: ; 26a44
+	ld a, c
+	call GetDecorationData
+	ld de, 5 ; sprite
+	add hl, de
+	ld a, [hl]
+	ld c, a
+	ret
+; 26a4f
+
+INCLUDE "data/decorations/attributes.asm"
+
+INCLUDE "data/decorations/names.asm"
+
+GetDecoName: ; 26c72
+	ld a, [hli]
+	ld e, [hl]
+	ld bc, wStringBuffer2
+	push bc
+	ld hl, .NameFunctions
+	rst JumpTable
+	pop de
+	ret
+; 26c7e
+
+.NameFunctions: ; 26c7e
+	dw .invalid
+	dw .plant
+	dw .bed
+	dw .carpet
+	dw .poster
+	dw .doll
+	dw .bigdoll
+; 26c8c
+
+
+.invalid ; 26c8c
+	ret
+; 26c8d
+
+.plant ; 26c8d
+	ld a, e
+	jr .getdeconame
+
+.bed ; 26c90
+	call .plant
+	ld a, _BED
+	jr .getdeconame
+
+.carpet ; 26c97
+	call .plant
+	ld a, _CARPET
+	jr .getdeconame
+
+.poster ; 26c9e
+	ld a, e
+	call .getpokename
+	ld a, _POSTER
+	jr .getdeconame
+
+.doll ; 26ca6
+	ld a, e
+	call .getpokename
+	ld a, _DOLL
+	jr .getdeconame
+
+.bigdoll ; 26cae
+	push de
+	ld a, BIG_
+	call .getdeconame
+	pop de
+	ld a, e
+	jr .getpokename
+
+.unused ; 26cb8
+	push de
+	call .getdeconame
+	pop de
+	ld a, e
+	jr .getdeconame
+
+.getpokename ; 26cc0
+	push bc
+	ld [wd265], a
+	call GetPokemonName
+	pop bc
+	jr .copy
+
+.getdeconame ; 26cca
+	call ._getdeconame
+	jr .copy
+
+._getdeconame ; 26ccf
+	push bc
+	ld hl, DecorationNames
+	call GetNthString
+	ld d, h
+	ld e, l
+	pop bc
+	ret
+
+.copy ; 26cda
+	ld h, b
+	ld l, c
+	call CopyName2
+	dec hl
+	ld b, h
+	ld c, l
+	ret
+; 26ce3
+
+DecoAction_nothing: ; 26ce3
+	scf
+	ret
+; 26ce5
+
+DecoAction_setupbed: ; 26ce5
+	ld hl, wDecoBed
+	jp DecoAction_TrySetItUp
+; 26ceb
+
+DecoAction_putawaybed: ; 26ceb
+	ld hl, wDecoBed
+	jp DecoAction_TryPutItAway
+; 26cf1
+
+DecoAction_setupcarpet: ; 26cf1
+	ld hl, wDecoCarpet
+	jp DecoAction_TrySetItUp
+; 26cf7
+
+DecoAction_putawaycarpet: ; 26cf7
+	ld hl, wDecoCarpet
+	jp DecoAction_TryPutItAway
+; 26cfd
+
+DecoAction_setupplant: ; 26cfd
+	ld hl, wDecoPlant
+	jp DecoAction_TrySetItUp
+; 26d03
+
+DecoAction_putawayplant: ; 26d03
+	ld hl, wDecoPlant
+	jp DecoAction_TryPutItAway
+; 26d09
+
+DecoAction_setupposter: ; 26d09
+	ld hl, wDecoPoster
+	jp DecoAction_TrySetItUp
+; 26d0f
+
+DecoAction_putawayposter: ; 26d0f
+	ld hl, wDecoPoster
+	jp DecoAction_TryPutItAway
+; 26d15
+
+DecoAction_setupconsole: ; 26d15
+	ld hl, wDecoConsole
+	jp DecoAction_TrySetItUp
+; 26d1b
+
+DecoAction_putawayconsole: ; 26d1b
+	ld hl, wDecoConsole
+	jp DecoAction_TryPutItAway
+; 26d21
+
+DecoAction_setupbigdoll: ; 26d21
+	ld hl, wDecoBigDoll
+	jp DecoAction_TrySetItUp
+; 26d27
+
+DecoAction_putawaybigdoll: ; 26d27
+	ld hl, wDecoBigDoll
+	jp DecoAction_TryPutItAway
+; 26d2d
+
+DecoAction_TrySetItUp: ; 26d2d
+	ld a, [hl]
+	ld [wBuffer1], a
+	push hl
+	call DecoAction_SetItUp
+	jr c, .failed
+	ld a, 1
+	ld [wBuffer5], a
+	pop hl
+	ld a, [wMenuSelection]
+	ld [hl], a
+	xor a
+	ret
+
+.failed
+	pop hl
+	xor a
+	ret
+; 26d46
+
+DecoAction_SetItUp: ; 26d46
+; See if there's anything of the same type already out
+	ld a, [wBuffer1]
+	and a
+	jr z, .nothingthere
+; See if that item is already out
+	ld b, a
+	ld a, [wMenuSelection]
+	cp b
+	jr z, .alreadythere
+; Put away the item that's already out, and set up the new one
+	ld a, [wMenuSelection]
+	ld hl, wStringBuffer4
+	call GetDecorationName
+	ld a, [wBuffer1]
+	ld hl, wStringBuffer3
+	call GetDecorationName
+	ld hl, DecoText_PutAwayAndSetUp
+	call MenuTextBoxBackup
+	xor a
+	ret
+
+.nothingthere
+	ld a, [wMenuSelection]
+	ld hl, wStringBuffer3
+	call GetDecorationName
+	ld hl, DecoText_SetUpTheDeco
+	call MenuTextBoxBackup
+	xor a
+	ret
+
+.alreadythere
+	ld hl, DecoText_AlreadySetUp
+	call MenuTextBoxBackup
+	scf
+	ret
+; 26d86
+
+DecoAction_TryPutItAway: ; 26d86
+; If there is no item of that type already set, there is nothing to put away.
+	ld a, [hl]
+	ld [wBuffer1], a
+	xor a
+	ld [hl], a
+	ld a, [wBuffer1]
+	and a
+	jr z, .nothingthere
+; Put it away.
+	ld a, $1
+	ld [wBuffer5], a
+	ld a, [wBuffer1]
+	ld [wMenuSelection], a
+	ld hl, wStringBuffer3
+	call GetDecorationName
+	ld hl, DecoText_PutAwayTheDeco
+	call MenuTextBoxBackup
+	xor a
+	ret
+
+.nothingthere
+	ld hl, DecoText_NothingToPutAway
+	call MenuTextBoxBackup
+	xor a
+	ret
+; 26db3
+
+DecoAction_setupornament: ; 26db3
+	ld hl, UnknownText_0x26e41
+	call DecoAction_AskWhichSide
+	jr c, .cancel
+	call DecoAction_SetItUp_Ornament
+	jr c, .cancel
+	ld a, $1
+	ld [wBuffer5], a
+	jr DecoAction_FinishUp_Ornament
+
+.cancel
+	xor a
+	ret
+
+DecoAction_putawayornament: ; 26dc9
+	ld hl, DecoText_WhichSide
+	call DecoAction_AskWhichSide
+	jr nc, .incave
+	xor a
+	ret
+
+.incave
+	call DecoAction_PutItAway_Ornament
+
+DecoAction_FinishUp_Ornament: ; 26dd6
+	call QueryWhichSide
+	ld a, [wSelectedDecoration]
+	ld [hl], a
+	ld a, [wOtherDecoration]
+	ld [de], a
+	xor a
+	ret
+; 26de3
+
+DecoAction_SetItUp_Ornament: ; 26de3
+	ld a, [wSelectedDecoration]
+	and a
+	jr z, .nothingthere
+	ld b, a
+	ld a, [wMenuSelection]
+	cp b
+	jr z, .failed
+	ld a, b
+	ld hl, wStringBuffer3
+	call GetDecorationName
+	ld a, [wMenuSelection]
+	ld hl, wStringBuffer4
+	call GetDecorationName
+	ld a, [wMenuSelection]
+	ld [wSelectedDecoration], a
+	call .getwhichside
+	ld hl, DecoText_PutAwayAndSetUp
+	call MenuTextBoxBackup
+	xor a
+	ret
+
+.nothingthere
+	ld a, [wMenuSelection]
+	ld [wSelectedDecoration], a
+	call .getwhichside
+	ld a, [wMenuSelection]
+	ld hl, wStringBuffer3
+	call GetDecorationName
+	ld hl, DecoText_SetUpTheDeco
+	call MenuTextBoxBackup
+	xor a
+	ret
+
+.failed
+	ld hl, DecoText_AlreadySetUp
+	call MenuTextBoxBackup
+	scf
+	ret
+; 26e33
+
+.getwhichside ; 26e33
+	ld a, [wMenuSelection]
+	ld b, a
+	ld a, [wOtherDecoration]
+	cp b
+	ret nz
+	xor a
+	ld [wOtherDecoration], a
+	ret
+; 26e41
+
+UnknownText_0x26e41: ; 0x26e41
+	; Which side do you want to put it on?
+	text_jump UnknownText_0x1bc48c
+	db "@"
+; 0x26e46
+
+DecoAction_PutItAway_Ornament: ; 26e46
+	ld a, [wSelectedDecoration]
+	and a
+	jr z, .nothingthere
+	ld hl, wStringBuffer3
+	call GetDecorationName
+	ld a, $1
+	ld [wBuffer5], a
+	xor a
+	ld [wSelectedDecoration], a
+	ld hl, DecoText_PutAwayTheDeco
+	call MenuTextBoxBackup
+	xor a
+	ret
+
+.nothingthere
+	ld hl, DecoText_NothingToPutAway
+	call MenuTextBoxBackup
+	xor a
+	ret
+; 26e6b
+
+DecoText_WhichSide: ; 0x26e6b
+	; Which side do you want to put away?
+	text_jump UnknownText_0x1bc4b2
+	db "@"
+; 0x26e70
+
+DecoAction_AskWhichSide: ; 26e70
+	call MenuTextBox
+	ld hl, MenuHeader_0x26eab
+	call GetMenu2
+	call ExitMenu
+	call CopyMenuData
+	jr c, .nope
+	ld a, [wMenuCursorY]
+	cp 3
+	jr z, .nope
+	ld [wBuffer2], a
+	call QueryWhichSide
+	ld a, [hl]
+	ld [wSelectedDecoration], a
+	ld a, [de]
+	ld [wOtherDecoration], a
+	xor a
+	ret
+
+.nope
+	scf
+	ret
+; 26e9a
+
+QueryWhichSide: ; 26e9a
+	ld hl, wDecoRightOrnament
+	ld de, wDecoLeftOrnament
+	ld a, [wBuffer2]
+	cp 1
+	ret z
+	push hl
+	ld h, d
+	ld l, e
+	pop de
+	ret
+; 26eab
+
+MenuHeader_0x26eab: ; 0x26eab
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 0, 0, 13, 7
+	dw MenuData_0x26eb3
+	db 1 ; default option
+; 0x26eb3
+
+MenuData_0x26eb3: ; 0x26eb3
+	db STATICMENU_CURSOR ; flags
+	db 3 ; items
+	db "RIGHT SIDE@"
+	db "LEFT SIDE@"
+	db "CANCEL@"
+; 0x26ed1
+
+DecoText_PutAwayTheDeco: ; 0x26ed1
+	; Put away the @ .
+	text_jump UnknownText_0x1bc4d7
+	db "@"
+; 0x26ed6
+
+DecoText_NothingToPutAway: ; 0x26ed6
+	; There's nothing to put away.
+	text_jump UnknownText_0x1bc4ec
+	db "@"
+; 0x26edb
+
+DecoText_SetUpTheDeco: ; 0x26edb
+	; Set up the @ .
+	text_jump UnknownText_0x1bc509
+	db "@"
+; 0x26ee0
+
+DecoText_PutAwayAndSetUp: ; 0x26ee0
+	; Put away the @ and set up the @ .
+	text_jump UnknownText_0x1bc51c
+	db "@"
+; 0x26ee5
+
+DecoText_AlreadySetUp: ; 0x26ee5
+	; That's already set up.
+	text_jump UnknownText_0x1bc546
+	db "@"
+; 0x26eea
+
+GetDecorationName_c_de: ; 26eea
+	ld a, c
+	ld h, d
+	ld l, e
+	call GetDecorationName
+	ret
+; 26ef1
+
+DecorationFlagAction_c: ; 26ef1
+	ld a, c
+	jp DecorationFlagAction
+; 26ef5
+
+
+GetDecorationName_c: ; 26ef5 (9:6ef5)
+	ld a, c
+	call GetDecorationID
+	ld hl, wStringBuffer1
+	push hl
+	call GetDecorationName
+	pop de
+	ret
+
+
+SetSpecificDecorationFlag: ; 26f02
+	ld a, c
+	call GetDecorationID
+	ld b, SET_FLAG
+	call DecorationFlagAction
+	ret
+; 26f0c
+
+GetDecorationID: ; 26f0c
+	push hl
+	push de
+	ld e, a
+	ld d, 0
+	ld hl, DecorationIDs
+	add hl, de
+	ld a, [hl]
+	pop de
+	pop hl
+	ret
+; 26f19
+
+SetAllDecorationFlags: ; 26f19
+	ld hl, DecorationIDs
+.loop
+	ld a, [hli]
+	cp -1
+	jr z, .done
+	push hl
+	ld b, SET_FLAG
+	call DecorationFlagAction
+	pop hl
+	jr .loop
+
+.done
+	ret
+; 26f2b
+
+INCLUDE "data/decorations/decorations.asm"
+
+DescribeDecoration:: ; 26f59
+	ld a, b
+	ld hl, .JumpTable
+	rst JumpTable
+	ret
+; 26f5f
+
+.JumpTable: ; 26f5f
+; entries correspond to DECODESC_* constants
+	dw DecorationDesc_Poster
+	dw DecorationDesc_LeftOrnament
+	dw DecorationDesc_RightOrnament
+	dw DecorationDesc_GiantOrnament
+	dw DecorationDesc_Console
+; 26f69
+
+DecorationDesc_Poster: ; 26f69
+	ld a, [wDecoPoster]
+	ld hl, DecorationDesc_PosterPointers
+	ld de, 3
+	call IsInArray
+	jr c, .nope
+	ld de, DecorationDesc_NullPoster
+	ld b, BANK(DecorationDesc_NullPoster)
+	ret
+
+.nope
+	ld b, BANK(DecorationDesc_TownMapPoster)
+	inc hl
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+	ret
+; 26f84
+
+DecorationDesc_PosterPointers: ; 26f84
+	dbw DECO_TOWN_MAP, DecorationDesc_TownMapPoster
+	dbw DECO_PIKACHU_POSTER, DecorationDesc_PikachuPoster
+	dbw DECO_CLEFAIRY_POSTER, DecorationDesc_ClefairyPoster
+	dbw DECO_JIGGLYPUFF_POSTER, DecorationDesc_JigglypuffPoster
+	db -1
+; 26f91
+
+DecorationDesc_TownMapPoster: ; 0x26f91
+	opentext
+	writetext .TownMapText
+	waitbutton
+	special OverworldTownMap
+	closetext
+	end
+; 0x26f9b
+
+.TownMapText: ; 0x26f9b
+	; It's the TOWN MAP.
+	text_jump UnknownText_0x1bc55d
+	db "@"
+; 0x26fa0
+
+DecorationDesc_PikachuPoster: ; 0x26fa0
+	jumptext .PikaPosterText
+; 0x26fa3
+
+.PikaPosterText: ; 0x26fa3
+	; It's a poster of a cute PIKACHU.
+	text_jump UnknownText_0x1bc570
+	db "@"
+; 0x26fa8
+
+DecorationDesc_ClefairyPoster: ; 0x26fa8
+	jumptext .ClefairyPosterText
+; 0x26fab
+
+.ClefairyPosterText: ; 0x26fab
+	; It's a poster of a cute CLEFAIRY.
+	text_jump UnknownText_0x1bc591
+	db "@"
+; 0x26fb0
+
+DecorationDesc_JigglypuffPoster: ; 0x26fb0
+	jumptext .JigglypuffPosterText
+; 0x26fb3
+
+.JigglypuffPosterText: ; 0x26fb3
+	; It's a poster of a cute JIGGLYPUFF.
+	text_jump UnknownText_0x1bc5b3
+	db "@"
+; 0x26fb8
+
+DecorationDesc_NullPoster: ; 26fb8
+	end
+; 26fb9
+
+DecorationDesc_LeftOrnament: ; 26fb9
+	ld a, [wDecoLeftOrnament]
+	jr DecorationDesc_OrnamentOrConsole
+
+DecorationDesc_RightOrnament: ; 26fbe
+	ld a, [wDecoRightOrnament]
+	jr DecorationDesc_OrnamentOrConsole
+
+DecorationDesc_Console: ; 26fc3
+	ld a, [wDecoConsole]
+	jr DecorationDesc_OrnamentOrConsole
+
+DecorationDesc_OrnamentOrConsole: ; 26fc8
+	ld c, a
+	ld de, wStringBuffer3
+	call GetDecorationName_c_de
+	ld b, BANK(.OrnamentConsoleScript)
+	ld de, .OrnamentConsoleScript
+	ret
+; 26fd5
+
+.OrnamentConsoleScript: ; 26fd5
+	jumptext .OrnamentConsoleText
+; 26fd8
+
+.OrnamentConsoleText: ; 0x26fd8
+	; It's an adorable @ .
+	text_jump UnknownText_0x1bc5d7
+	db "@"
+; 0x26fdd
+
+DecorationDesc_GiantOrnament: ; 26fdd
+	ld b, BANK(.BigDollScript)
+	ld de, .BigDollScript
+	ret
+; 26fe3
+
+.BigDollScript: ; 26fe3
+	jumptext .BigDollText
+; 26fe6
+
+.BigDollText: ; 0x26fe6
+	; A giant doll! It's fluffy and cuddly.
+	text_jump UnknownText_0x1bc5ef
+	db "@"
+; 0x26feb
+
+ToggleMaptileDecorations: ; 26feb
+	lb de, 0, 4
+	ld a, [wDecoBed]
+	call SetDecorationTile
+	lb de, 7, 4
+	ld a, [wDecoPlant]
+	call SetDecorationTile
+	lb de, 6, 0
+	ld a, [wDecoPoster]
+	call SetDecorationTile
+	call SetPosterVisibility
+	lb de, 0, 0
+	call PadCoords_de
+	ld a, [wDecoCarpet]
+	and a
+	ret z
+	call _GetDecorationSprite
+	ld [hl], a
+	push af
+	lb de, 0, 2
+	call PadCoords_de
+	pop af
+	inc a
+	ld [hli], a
+	inc a
+	ld [hli], a
+	dec a
+	ld [hl], a
+	ret
+; 27027
+
+SetPosterVisibility: ; 27027
+	ld b, SET_FLAG
+	ld a, [wDecoPoster]
+	and a
+	jr nz, .ok
+	ld b, RESET_FLAG
+
+.ok
+	ld de, EVENT_PLAYERS_ROOM_POSTER
+	jp EventFlagAction
+; 27037
+
+SetDecorationTile: ; 27037
+	push af
+	call PadCoords_de
+	pop af
+	and a
+	ret z
+	call _GetDecorationSprite
+	ld [hl], a
+	ret
+; 27043
+
+ToggleDecorationsVisibility: ; 27043
+	ld de, EVENT_PLAYERS_HOUSE_2F_CONSOLE
+	ld hl, wVariableSprites + SPRITE_CONSOLE - SPRITE_VARS
+	ld a, [wDecoConsole]
+	call ToggleDecorationVisibility
+	ld de, EVENT_PLAYERS_HOUSE_2F_DOLL_1
+	ld hl, wVariableSprites + SPRITE_DOLL_1 - SPRITE_VARS
+	ld a, [wDecoLeftOrnament]
+	call ToggleDecorationVisibility
+	ld de, EVENT_PLAYERS_HOUSE_2F_DOLL_2
+	ld hl, wVariableSprites + SPRITE_DOLL_2 - SPRITE_VARS
+	ld a, [wDecoRightOrnament]
+	call ToggleDecorationVisibility
+	ld de, EVENT_PLAYERS_HOUSE_2F_BIG_DOLL
+	ld hl, wVariableSprites + SPRITE_BIG_DOLL - SPRITE_VARS
+	ld a, [wDecoBigDoll]
+	call ToggleDecorationVisibility
+	ret
+; 27074
+
+ToggleDecorationVisibility: ; 27074
+	and a
+	jr z, .hide
+	call _GetDecorationSprite
+	ld [hl], a
+	ld b, RESET_FLAG
+	jp EventFlagAction
+
+.hide
+	ld b, SET_FLAG
+	jp EventFlagAction
+; 27085
+
+_GetDecorationSprite: ; 27085
+	ld c, a
+	push de
+	push hl
+	farcall GetDecorationSprite
+	pop hl
+	pop de
+	ld a, c
+	ret
+; 27092
+
+PadCoords_de: ; 27092
+	ld a, d
+	add 4
+	ld d, a
+	ld a, e
+	add 4
+	ld e, a
+	call GetBlockLocation
+	ret
--- /dev/null
+++ b/engine/overworld/events.asm
@@ -1,0 +1,1111 @@
+INCLUDE "constants.asm"
+
+
+SECTION "Events", ROMX
+
+OverworldLoop:: ; 966b0
+	xor a
+	ld [wMapStatus], a
+.loop
+	ld a, [wMapStatus]
+	ld hl, .jumps
+	rst JumpTable
+	ld a, [wMapStatus]
+	cp 3 ; done
+	jr nz, .loop
+.done
+	ret
+
+.jumps
+	dw StartMap
+	dw EnterMap
+	dw HandleMap
+	dw .done
+; 966cb
+
+DisableEvents: ; 966cb
+	xor a
+	ld [wScriptFlags3], a
+	ret
+; 966d0
+
+EnableEvents:: ; 966d0
+	ld a, $ff
+	ld [wScriptFlags3], a
+	ret
+; 966d6
+
+CheckBit5_ScriptFlags3: ; 966d6
+	ld hl, wScriptFlags3
+	bit 5, [hl]
+	ret
+; 966dc
+
+DisableWarpsConnxns: ; 966dc
+	ld hl, wScriptFlags3
+	res 2, [hl]
+	ret
+; 966e2
+
+DisableCoordEvents: ; 966e2
+	ld hl, wScriptFlags3
+	res 1, [hl]
+	ret
+; 966e8
+
+DisableStepCount: ; 966e8
+	ld hl, wScriptFlags3
+	res 0, [hl]
+	ret
+; 966ee
+
+DisableWildEncounters: ; 966ee
+	ld hl, wScriptFlags3
+	res 4, [hl]
+	ret
+; 966f4
+
+EnableWarpsConnxns: ; 966f4
+	ld hl, wScriptFlags3
+	set 2, [hl]
+	ret
+; 966fa
+
+EnableCoordEvents: ; 966fa
+	ld hl, wScriptFlags3
+	set 1, [hl]
+	ret
+; 96700
+
+EnableStepCount: ; 96700
+	ld hl, wScriptFlags3
+	set 0, [hl]
+	ret
+; 96706
+
+EnableWildEncounters: ; 96706
+	ld hl, wScriptFlags3
+	set 4, [hl]
+	ret
+; 9670c
+
+CheckWarpConnxnScriptFlag: ; 9670c
+	ld hl, wScriptFlags3
+	bit 2, [hl]
+	ret
+; 96712
+
+CheckCoordEventScriptFlag: ; 96712
+	ld hl, wScriptFlags3
+	bit 1, [hl]
+	ret
+; 96718
+
+CheckStepCountScriptFlag: ; 96718
+	ld hl, wScriptFlags3
+	bit 0, [hl]
+	ret
+; 9671e
+
+CheckWildEncountersScriptFlag: ; 9671e
+	ld hl, wScriptFlags3
+	bit 4, [hl]
+	ret
+; 96724
+
+StartMap: ; 96724
+	xor a
+	ld [wScriptVar], a
+	xor a
+	ld [wScriptRunning], a
+	ld hl, wMapStatus
+	ld bc, wMapStatusEnd - wMapStatus
+	call ByteFill
+	farcall InitCallReceiveDelay
+	call ClearJoypad
+EnterMap: ; 9673e
+	xor a
+	ld [wXYComparePointer], a
+	ld [wXYComparePointer + 1], a
+	call SetUpFiveStepWildEncounterCooldown
+	farcall RunMapSetupScript
+	call DisableEvents
+
+	ld a, [hMapEntryMethod]
+	cp MAPSETUP_CONNECTION
+	jr nz, .dont_enable
+	call EnableEvents
+.dont_enable
+
+	ld a, [hMapEntryMethod]
+	cp MAPSETUP_RELOADMAP
+	jr nz, .dontresetpoison
+	xor a
+	ld [wPoisonStepCount], a
+.dontresetpoison
+
+	xor a ; end map entry
+	ld [hMapEntryMethod], a
+	ld a, 2 ; HandleMap
+	ld [wMapStatus], a
+	ret
+; 9676d
+
+UnusedWait30Frames: ; 9676d
+	ld c, 30
+	call DelayFrames
+	ret
+; 96773
+
+HandleMap: ; 96773
+	call ResetOverworldDelay
+	call HandleMapTimeAndJoypad
+	farcall HandleCmdQueue ; no need to farcall
+	call MapEvents
+
+; Not immediately entering a connected map will cause problems.
+	ld a, [wMapStatus]
+	cp 2 ; HandleMap
+	ret nz
+
+	call HandleMapObjects
+	call NextOverworldFrame
+	call HandleMapBackground
+	call CheckPlayerState
+	ret
+; 96795
+
+MapEvents: ; 96795
+	ld a, [wMapEventStatus]
+	ld hl, .jumps
+	rst JumpTable
+	ret
+
+.jumps
+	dw .events
+	dw .no_events
+; 967a1
+
+.events ; 967a1
+	call PlayerEvents
+	call DisableEvents
+	farcall ScriptEvents
+	ret
+; 967ae
+
+.no_events ; 967ae
+	ret
+; 967af
+
+MaxOverworldDelay: ; 967af
+	db 2
+; 967b0
+
+ResetOverworldDelay: ; 967b0
+	ld a, [MaxOverworldDelay]
+	ld [wOverworldDelay], a
+	ret
+; 967b7
+
+NextOverworldFrame: ; 967b7
+	ld a, [wOverworldDelay]
+	and a
+	ret z
+	ld c, a
+	call DelayFrames
+	ret
+; 967c1
+
+HandleMapTimeAndJoypad: ; 967c1
+	ld a, [wMapEventStatus]
+	cp 1 ; no events
+	ret z
+
+	call UpdateTime
+	call GetJoypad
+	call TimeOfDayPals
+	ret
+; 967d1
+
+HandleMapObjects: ; 967d1
+	farcall HandleNPCStep ; engine/map_objects.asm
+	farcall _HandlePlayerStep
+	call _CheckObjectEnteringVisibleRange
+	ret
+; 967e1
+
+HandleMapBackground: ; 967e1
+	farcall _UpdateSprites
+	farcall ScrollScreen
+	farcall PlaceMapNameSign
+	ret
+; 967f4
+
+CheckPlayerState: ; 967f4
+	ld a, [wPlayerStepFlags]
+	bit 5, a ; in the middle of step
+	jr z, .events
+	bit 6, a ; stopping step
+	jr z, .noevents
+	bit 4, a ; in midair
+	jr nz, .noevents
+	call EnableEvents
+.events
+	ld a, 0 ; events
+	ld [wMapEventStatus], a
+	ret
+
+.noevents
+	ld a, 1 ; no events
+	ld [wMapEventStatus], a
+	ret
+; 96812
+
+_CheckObjectEnteringVisibleRange: ; 96812
+	ld hl, wPlayerStepFlags
+	bit 6, [hl]
+	ret z
+	farcall CheckObjectEnteringVisibleRange
+	ret
+; 9681f
+
+PlayerEvents: ; 9681f
+	xor a
+; If there's already a player event, don't interrupt it.
+	ld a, [wScriptRunning]
+	and a
+	ret nz
+
+	call Dummy_CheckScriptFlags3Bit5 ; This is a waste of time
+
+	call CheckTrainerBattle3
+	jr c, .ok
+
+	call CheckTileEvent
+	jr c, .ok
+
+	call RunMemScript
+	jr c, .ok
+
+	call RunSceneScript
+	jr c, .ok
+
+	call CheckTimeEvents
+	jr c, .ok
+
+	call OWPlayerInput
+	jr c, .ok
+
+	xor a
+	ret
+
+.ok
+	push af
+	farcall EnableScriptMode
+	pop af
+
+	ld [wScriptRunning], a
+	call DoPlayerEvent
+	ld a, [wScriptRunning]
+	cp PLAYEREVENT_CONNECTION
+	jr z, .ok2
+	cp PLAYEREVENT_JOYCHANGEFACING
+	jr z, .ok2
+
+	xor a
+	ld [wLandmarkSignTimer], a
+
+.ok2
+	scf
+	ret
+; 96867
+
+CheckTrainerBattle3: ; 96867
+	nop
+	nop
+	call CheckTrainerBattle2
+	jr nc, .nope
+
+	ld a, PLAYEREVENT_SEENBYTRAINER
+	scf
+	ret
+
+.nope
+	xor a
+	ret
+; 96874
+
+CheckTileEvent: ; 96874
+; Check for warps, coord events, or wild battles.
+
+	call CheckWarpConnxnScriptFlag
+	jr z, .connections_disabled
+
+	farcall CheckMovingOffEdgeOfMap
+	jr c, .map_connection
+
+	call CheckWarpTile
+	jr c, .warp_tile
+
+.connections_disabled
+	call CheckCoordEventScriptFlag
+	jr z, .coord_events_disabled
+
+	call CheckCurrentMapCoordEvents
+	jr c, .coord_event
+
+.coord_events_disabled
+	call CheckStepCountScriptFlag
+	jr z, .step_count_disabled
+
+	call CountStep
+	ret c
+
+.step_count_disabled
+	call CheckWildEncountersScriptFlag
+	jr z, .ok
+
+	call RandomEncounter
+	ret c
+	jr .ok ; pointless
+
+.ok
+	xor a
+	ret
+
+.map_connection
+	ld a, PLAYEREVENT_CONNECTION
+	scf
+	ret
+
+.warp_tile
+	ld a, [wPlayerStandingTile]
+	call CheckPitTile
+	jr nz, .not_pit
+	ld a, PLAYEREVENT_FALL
+	scf
+	ret
+
+.not_pit
+	ld a, PLAYEREVENT_WARP
+	scf
+	ret
+
+.coord_event
+	ld hl, wCurCoordEventScriptAddr
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	call GetMapScriptsBank
+	call CallScript
+	ret
+; 968c7
+
+CheckWildEncounterCooldown:: ; 968c7
+	ld hl, wWildEncounterCooldown
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+	ret z
+	scf
+	ret
+; 968d1
+
+SetUpFiveStepWildEncounterCooldown: ; 968d1
+	ld a, 5
+	ld [wWildEncounterCooldown], a
+	ret
+; 968d7
+
+ret_968d7: ; 968d7
+	ret
+;968d8
+
+SetMinTwoStepWildEncounterCooldown: ; 968d8
+	ld a, [wWildEncounterCooldown]
+	cp 2
+	ret nc
+	ld a, 2
+	ld [wWildEncounterCooldown], a
+	ret
+; 968e4
+
+Dummy_CheckScriptFlags3Bit5: ; 968e4
+	call CheckBit5_ScriptFlags3
+	ret z
+	call ret_2f3e
+	ret
+; 968ec
+
+RunSceneScript: ; 968ec
+	ld a, [wCurrMapSceneScriptCount]
+	and a
+	jr z, .nope
+
+	ld c, a
+	call CheckScenes
+	cp c
+	jr nc, .nope
+
+	ld e, a
+	ld d, 0
+	ld hl, wCurrMapSceneScriptsPointer
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+rept 4
+	add hl, de
+endr
+
+	call GetMapScriptsBank
+	call GetFarHalfword
+	call GetMapScriptsBank
+	call CallScript
+
+	ld hl, wScriptFlags
+	res 3, [hl]
+
+	farcall EnableScriptMode
+	farcall ScriptEvents
+
+	ld hl, wScriptFlags
+	bit 3, [hl]
+	jr z, .nope
+
+	ld hl, wPriorityScriptAddr
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [wPriorityScriptBank]
+	call CallScript
+	scf
+	ret
+
+.nope
+	xor a
+	ret
+; 9693a
+
+CheckTimeEvents: ; 9693a
+	ld a, [wLinkMode]
+	and a
+	jr nz, .nothing
+
+	ld hl, wStatusFlags2
+	bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
+	jr z, .do_daily
+
+	farcall CheckBugContestTimer
+	jr c, .end_bug_contest
+	xor a
+	ret
+
+.do_daily
+	farcall CheckDailyResetTimer
+	farcall CheckPokerusTick
+	farcall CheckPhoneCall
+	ret c
+
+.nothing
+	xor a
+	ret
+
+.end_bug_contest
+	ld a, BANK(BugCatchingContestOverScript)
+	ld hl, BugCatchingContestOverScript
+	call CallScript
+	scf
+	ret
+; 96970
+
+.unused ; 96970
+	ld a, 8
+	scf
+	ret
+; 96974
+
+OWPlayerInput: ; 96974
+
+	call PlayerMovement
+	ret c
+	and a
+	jr nz, .NoAction
+
+; Can't perform button actions while sliding on ice.
+	farcall CheckStandingOnIce
+	jr c, .NoAction
+
+	call CheckAPressOW
+	jr c, .Action
+
+	call CheckMenuOW
+	jr c, .Action
+
+.NoAction:
+	xor a
+	ret
+
+.Action:
+	push af
+	farcall StopPlayerForEvent
+	pop af
+	scf
+	ret
+; 96999
+
+CheckAPressOW: ; 96999
+	ld a, [hJoyPressed]
+	and A_BUTTON
+	ret z
+	call TryObjectEvent
+	ret c
+	call TryBGEvent
+	ret c
+	call TryTileCollisionEvent
+	ret c
+	xor a
+	ret
+; 969ac
+
+PlayTalkObject: ; 969ac
+	push de
+	ld de, SFX_READ_TEXT_2
+	call PlaySFX
+	pop de
+	ret
+; 969b5
+
+TryObjectEvent: ; 969b5
+	farcall CheckFacingObject
+	jr c, .IsObject
+	xor a
+	ret
+
+.IsObject:
+	call PlayTalkObject
+	ld a, [hObjectStructIndexBuffer]
+	call GetObjectStruct
+	ld hl, OBJECT_MAP_OBJECT_INDEX
+	add hl, bc
+	ld a, [hl]
+	ld [hLastTalked], a
+
+	ld a, [hLastTalked]
+	call GetMapObject
+	ld hl, MAPOBJECT_COLOR
+	add hl, bc
+	ld a, [hl]
+	and %00001111
+
+; Bug: If IsInArray returns nc, data at bc will be executed as code.
+	push bc
+	ld de, 3
+	ld hl, .pointers
+	call IsInArray
+	jr nc, .nope_bugged
+	pop bc
+
+	inc hl
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+.nope_bugged
+	; pop bc
+	xor a
+	ret
+
+.pointers
+	dbw OBJECTTYPE_SCRIPT, .script
+	dbw OBJECTTYPE_ITEMBALL, .itemball
+	dbw OBJECTTYPE_TRAINER, .trainer
+	; the remaining four are dummy events
+	dbw OBJECTTYPE_3, .three
+	dbw OBJECTTYPE_4, .four
+	dbw OBJECTTYPE_5, .five
+	dbw OBJECTTYPE_6, .six
+	db -1
+; 96a04
+
+.script ; 96a04
+	ld hl, MAPOBJECT_SCRIPT_POINTER
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	call GetMapScriptsBank
+	call CallScript
+	ret
+; 96a12
+
+.itemball ; 96a12
+	ld hl, MAPOBJECT_SCRIPT_POINTER
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	call GetMapScriptsBank
+	ld de, wEngineBuffer1
+	ld bc, 2
+	call FarCopyBytes
+	ld a, PLAYEREVENT_ITEMBALL
+	scf
+	ret
+; 96a29
+
+.trainer ; 96a29
+	call TalkToTrainer
+	ld a, PLAYEREVENT_TALKTOTRAINER
+	scf
+	ret
+; 96a30
+
+.three ; 96a30
+	xor a
+	ret
+; 96a32
+
+.four ; 96a32
+	xor a
+	ret
+; 96a34
+
+.five ; 96a34
+	xor a
+	ret
+; 96a36
+
+.six ; 96a36
+	xor a
+	ret
+; 96a38
+
+TryBGEvent: ; 96a38
+	call CheckFacingBGEvent
+	jr c, .is_bg_event
+	xor a
+	ret
+
+.is_bg_event:
+	ld a, [wEngineBuffer3]
+	ld hl, .bg_events
+	rst JumpTable
+	ret
+
+.bg_events
+	dw .read
+	dw .up
+	dw .down
+	dw .right
+	dw .left
+	dw .ifset
+	dw .ifnotset
+	dw .itemifset
+	dw .copy
+; 96a59
+
+.up
+	ld b, OW_UP
+	jr .checkdir
+.down
+	ld b, OW_DOWN
+	jr .checkdir
+.right
+	ld b, OW_RIGHT
+	jr .checkdir
+.left
+	ld b, OW_LEFT
+	jr .checkdir
+
+.checkdir
+	ld a, [wPlayerDirection]
+	and %1100
+	cp b
+	jp nz, .dontread
+
+.read
+	call PlayTalkObject
+	ld hl, wEngineBuffer4
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	call GetMapScriptsBank
+	call CallScript
+	scf
+	ret
+
+.itemifset
+	call CheckBGEventFlag
+	jp nz, .dontread
+	call PlayTalkObject
+	call GetMapScriptsBank
+	ld de, wEngineBuffer1
+	ld bc, 3
+	call FarCopyBytes
+	ld a, BANK(HiddenItemScript)
+	ld hl, HiddenItemScript
+	call CallScript
+	scf
+	ret
+
+.copy
+	call CheckBGEventFlag
+	jr nz, .dontread
+	call GetMapScriptsBank
+	ld de, wEngineBuffer1
+	ld bc, 3
+	call FarCopyBytes
+	jr .dontread
+
+.ifset
+	call CheckBGEventFlag
+	jr z, .dontread
+	jr .thenread
+
+.ifnotset
+	call CheckBGEventFlag
+	jr nz, .dontread
+
+.thenread
+	push hl
+	call PlayTalkObject
+	pop hl
+	inc hl
+	inc hl
+	call GetMapScriptsBank
+	call GetFarHalfword
+	call GetMapScriptsBank
+	call CallScript
+	scf
+	ret
+
+.dontread
+	xor a
+	ret
+; 96ad8
+
+CheckBGEventFlag: ; 96ad8
+	ld hl, wEngineBuffer4
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	push hl
+	call GetMapScriptsBank
+	call GetFarHalfword
+	ld e, l
+	ld d, h
+	ld b, CHECK_FLAG
+	call EventFlagAction
+	ld a, c
+	and a
+	pop hl
+	ret
+; 96af0
+
+PlayerMovement: ; 96af0
+	farcall DoPlayerMovement
+	ld a, c
+	ld hl, .pointers
+	rst JumpTable
+	ld a, c
+	ret
+; 96afd
+
+.pointers
+	dw .zero
+	dw .one
+	dw .two
+	dw .three
+	dw .four
+	dw .five
+	dw .six
+	dw .seven
+
+.zero
+.four ; 96b0d
+	xor a
+	ld c, a
+	ret
+; 96b10
+
+.seven ; 96b10
+	call ret_968d7 ; mobile
+	xor a
+	ld c, a
+	ret
+; 96b16
+
+.one ; 96b16
+	ld a, 5
+	ld c, a
+	scf
+	ret
+; 96b1b
+
+.two ; 96b1b
+	ld a, 9
+	ld c, a
+	scf
+	ret
+; 96b20
+
+.three ; 96b20
+; force the player to move in some direction
+	ld a, BANK(Script_ForcedMovement)
+	ld hl, Script_ForcedMovement
+	call CallScript
+;	ld a, -1
+	ld c, a
+	scf
+	ret
+; 96b2b
+
+.five
+.six ; 96b2b
+	ld a, -1
+	ld c, a
+	and a
+	ret
+; 96b30
+
+CheckMenuOW: ; 96b30
+	xor a
+	ld [hMenuReturn], a
+	ld [hMenuReturn + 1], a
+	ld a, [hJoyPressed]
+
+	bit SELECT_F, a
+	jr nz, .Select
+
+	bit START_F, a
+	jr z, .NoMenu
+
+	ld a, BANK(StartMenuScript)
+	ld hl, StartMenuScript
+	call CallScript
+	scf
+	ret
+
+.NoMenu:
+	xor a
+	ret
+
+.Select:
+	call PlayTalkObject
+	ld a, BANK(SelectMenuScript)
+	ld hl, SelectMenuScript
+	call CallScript
+	scf
+	ret
+; 96b58
+
+StartMenuScript: ; 96b58
+	callasm StartMenu
+	jump StartMenuCallback
+; 96b5f
+
+SelectMenuScript: ; 96b5f
+	callasm SelectMenu
+	jump SelectMenuCallback
+; 96b66
+
+StartMenuCallback:
+SelectMenuCallback: ; 96b66
+	copybytetovar hMenuReturn
+	ifequal HMENURETURN_SCRIPT, .Script
+	ifequal HMENURETURN_ASM, .Asm
+	end
+; 96b72
+
+.Script: ; 96b72
+	ptjump wQueuedScriptBank
+; 96b75
+
+.Asm: ; 96b75
+	ptcallasm wQueuedScriptBank
+	end
+; 96b79
+
+CountStep: ; 96b79
+	; Don't count steps in link communication rooms.
+	ld a, [wLinkMode]
+	and a
+	jr nz, .done
+
+	; If there is a special phone call, don't count the step.
+	farcall CheckSpecialPhoneCall
+	jr c, .doscript
+
+	; If Repel wore off, don't count the step.
+	call DoRepelStep
+	jr c, .doscript
+
+	; Count the step for poison and total steps
+	ld hl, wPoisonStepCount
+	inc [hl]
+	ld hl, wStepCount
+	inc [hl]
+	; Every 256 steps, increase the happiness of all your Pokemon.
+	jr nz, .skip_happiness
+
+	farcall StepHappiness
+
+.skip_happiness
+	; Every 256 steps, offset from the happiness incrementor by 128 steps,
+	; decrease the hatch counter of all your eggs until you reach the first
+	; one that is ready to hatch.
+	ld a, [wStepCount]
+	cp $80
+	jr nz, .skip_egg
+
+	farcall DoEggStep
+	jr nz, .hatch
+
+.skip_egg
+	; Increase the EXP of (both) DayCare Pokemon by 1.
+	farcall DayCareStep
+
+	; Every four steps, deal damage to all Poisoned Pokemon
+	ld hl, wPoisonStepCount
+	ld a, [hl]
+	cp 4
+	jr c, .skip_poison
+	ld [hl], 0
+
+	farcall DoPoisonStep
+	jr c, .doscript
+
+.skip_poison
+	farcall DoBikeStep
+
+.done
+	xor a
+	ret
+
+.doscript
+	ld a, -1
+	scf
+	ret
+
+.hatch
+	ld a, 8
+	scf
+	ret
+; 96bd3
+
+; unused
+.unreferenced ; 96bd3
+	ld a, 7
+	scf
+	ret
+; 96bd7
+
+DoRepelStep: ; 96bd7
+	ld a, [wRepelEffect]
+	and a
+	ret z
+
+	dec a
+	ld [wRepelEffect], a
+	ret nz
+
+	ld a, BANK(RepelWoreOffScript)
+	ld hl, RepelWoreOffScript
+	call CallScript
+	scf
+	ret
+; 96beb
+
+DoPlayerEvent: ; 96beb
+	ld a, [wScriptRunning]
+	and a
+	ret z
+
+	cp PLAYEREVENT_MAPSCRIPT ; run script
+	ret z
+
+	cp NUM_PLAYER_EVENTS
+	ret nc
+
+	ld c, a
+	ld b, 0
+	ld hl, PlayerEventScriptPointers
+	add hl, bc
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld [wScriptBank], a
+	ld a, [hli]
+	ld [wScriptPos], a
+	ld a, [hl]
+	ld [wScriptPos + 1], a
+	ret
+; 96c0c
+
+PlayerEventScriptPointers: ; 96c0c
+	dba Invalid_0x96c2d          ; 0
+	dba SeenByTrainerScript      ; 1
+	dba TalkToTrainerScript      ; 2
+	dba FindItemInBallScript     ; 3
+	dba EdgeWarpScript           ; 4
+	dba WarpToNewMapScript       ; 5
+	dba FallIntoMapScript        ; 6
+	dba Script_OverworldWhiteout ; 7
+	dba HatchEggScript           ; 8
+	dba ChangeDirectionScript    ; 9
+	dba Invalid_0x96c2d          ; 10
+; 96c2d
+
+Invalid_0x96c2d: ; 96c2d
+	end
+; 96c2e
+
+; unused
+	end
+; 96c2f
+
+HatchEggScript: ; 96c2f
+	callasm OverworldHatchEgg
+	end
+; 96c34
+
+WarpToNewMapScript: ; 96c34
+	warpsound
+	newloadmap MAPSETUP_DOOR
+	end
+; 96c38
+
+FallIntoMapScript: ; 96c38
+	newloadmap MAPSETUP_FALL
+	playsound SFX_KINESIS
+	applymovement PLAYER, MovementData_0x96c48
+	playsound SFX_STRENGTH
+	scall LandAfterPitfallScript
+	end
+; 96c48
+
+MovementData_0x96c48: ; 96c48
+	skyfall
+	step_end
+; 96c4a
+
+LandAfterPitfallScript: ; 96c4a
+	earthquake 16
+	end
+; 96c4d
+
+EdgeWarpScript: ; 4
+	reloadandreturn MAPSETUP_CONNECTION
+; 96c4f
+
+ChangeDirectionScript: ; 9
+	deactivatefacing 3
+	callasm EnableWildEncounters
+	end
+; 96c56
+
+INCLUDE "engine/overworld/scripting.asm"
+
+INCLUDE "engine/overworld/events_2.asm"
--- /dev/null
+++ b/engine/overworld/events_2.asm
@@ -1,0 +1,650 @@
+; More overworld event handling.
+
+
+WarpToSpawnPoint:: ; 97c28
+	ld hl, wStatusFlags2
+	res STATUSFLAGS2_SAFARI_GAME_F, [hl]
+	res STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
+	ret
+; 97c30
+
+RunMemScript:: ; 97c30
+; If there is no script here, we don't need to be here.
+	ld a, [wMapReentryScriptQueueFlag]
+	and a
+	ret z
+; Execute the script at (wMapReentryScriptBank):(wMapReentryScriptAddress).
+	ld hl, wMapReentryScriptAddress
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [wMapReentryScriptBank]
+	call CallScript
+	scf
+; Clear the buffer for the next script.
+	push af
+	xor a
+	ld hl, wMapReentryScriptQueueFlag
+	ld bc, 8
+	call ByteFill
+	pop af
+	ret
+; 97c4f
+
+LoadScriptBDE:: ; 97c4f
+; If there's already a script here, don't overwrite.
+	ld hl, wMapReentryScriptQueueFlag
+	ld a, [hl]
+	and a
+	ret nz
+; Set the flag
+	ld [hl], 1
+	inc hl
+; Load the script pointer b:de into (wMapReentryScriptBank):(wMapReentryScriptAddress)
+	ld [hl], b
+	inc hl
+	ld [hl], e
+	inc hl
+	ld [hl], d
+	scf
+	ret
+; 97c5f
+
+TryTileCollisionEvent:: ; 97c5f
+	call GetFacingTileCoord
+	ld [wEngineBuffer1], a
+	ld c, a
+	farcall CheckFacingTileForStdScript
+	jr c, .done
+
+	call CheckCutTreeTile
+	jr nz, .whirlpool
+	farcall TryCutOW
+	jr .done
+
+.whirlpool
+	ld a, [wEngineBuffer1]
+	call CheckWhirlpoolTile
+	jr nz, .waterfall
+	farcall TryWhirlpoolOW
+	jr .done
+
+.waterfall
+	ld a, [wEngineBuffer1]
+	call CheckWaterfallTile
+	jr nz, .headbutt
+	farcall TryWaterfallOW
+	jr .done
+
+.headbutt
+	ld a, [wEngineBuffer1]
+	call CheckHeadbuttTreeTile
+	jr nz, .surf
+	farcall TryHeadbuttOW
+	jr c, .done
+	jr .noevent
+
+.surf
+	farcall TrySurfOW
+	jr nc, .noevent
+	jr .done
+
+.noevent
+	xor a
+	ret
+
+.done
+	call PlayClickSFX
+	ld a, $ff
+	scf
+	ret
+; 97cc0
+
+
+RandomEncounter:: ; 97cc0
+; Random encounter
+
+	call CheckWildEncounterCooldown
+	jr c, .nope
+	call CanUseSweetScent
+	jr nc, .nope
+	ld hl, wStatusFlags2
+	bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
+	jr nz, .bug_contest
+	farcall TryWildEncounter
+	jr nz, .nope
+	jr .ok
+
+.bug_contest
+	call _TryWildEncounter_BugContest
+	jr nc, .nope
+	jr .ok_bug_contest
+
+.nope
+	ld a, 1
+	and a
+	ret
+
+.ok
+	ld a, BANK(WildBattleScript)
+	ld hl, WildBattleScript
+	jr .done
+
+.ok_bug_contest
+	ld a, BANK(BugCatchingContestBattleScript)
+	ld hl, BugCatchingContestBattleScript
+	jr .done
+
+.done
+	call CallScript
+	scf
+	ret
+; 97cf9
+
+WildBattleScript: ; 97cf9
+	randomwildmon
+	startbattle
+	reloadmapafterbattle
+	end
+; 97cfd
+
+CanUseSweetScent:: ; 97cfd
+	ld hl, wStatusFlags
+	bit STATUSFLAGS_NO_WILD_ENCOUNTERS_F, [hl]
+	jr nz, .no
+	ld a, [wEnvironment]
+	cp CAVE
+	jr z, .ice_check
+	cp DUNGEON
+	jr z, .ice_check
+	farcall CheckGrassCollision
+	jr nc, .no
+
+.ice_check
+	ld a, [wPlayerStandingTile]
+	call CheckIceTile
+	jr z, .no
+	scf
+	ret
+
+.no
+	and a
+	ret
+; 97d23
+
+_TryWildEncounter_BugContest: ; 97d23
+	call TryWildEncounter_BugContest
+	ret nc
+	call ChooseWildEncounter_BugContest
+	farcall CheckRepelEffect
+	ret
+; 97d31
+
+ChooseWildEncounter_BugContest:: ; 97d31
+; Pick a random mon out of ContestMons.
+
+.loop
+	call Random
+	cp 100 << 1
+	jr nc, .loop
+	srl a
+
+	ld hl, ContestMons
+	ld de, 4
+.CheckMon:
+	sub [hl]
+	jr c, .GotMon
+	add hl, de
+	jr .CheckMon
+
+.GotMon:
+	inc hl
+
+; Species
+	ld a, [hli]
+	ld [wTempWildMonSpecies], a
+
+; Min level
+	ld a, [hli]
+	ld d, a
+
+; Max level
+	ld a, [hl]
+
+	sub d
+	jr nz, .RandomLevel
+
+; If min and max are the same.
+	ld a, d
+	jr .GotLevel
+
+.RandomLevel:
+; Get a random level between the min and max.
+	ld c, a
+	inc c
+	call Random
+	ld a, [hRandomAdd]
+	call SimpleDivide
+	add d
+
+.GotLevel:
+	ld [wCurPartyLevel], a
+
+	xor a
+	ret
+; 97d64
+
+TryWildEncounter_BugContest: ; 97d64
+	ld a, [wPlayerStandingTile]
+	call CheckSuperTallGrassTile
+	ld b, 40 percent
+	jr z, .ok
+	ld b, 20 percent
+
+.ok
+	farcall ApplyMusicEffectOnEncounterRate
+	farcall ApplyCleanseTagEffectOnEncounterRate
+	call Random
+	ld a, [hRandomAdd]
+	cp b
+	ret c
+	ld a, 1
+	and a
+	ret
+; 97d87
+
+
+INCLUDE "data/wild/bug_contest_mons.asm"
+
+
+DoBikeStep:: ; 97db3
+	nop
+	nop
+	; If the bike shop owner doesn't have our number, or
+	; if we've already gotten the call, we don't have to
+	; be here.
+	ld hl, wStatusFlags2
+	bit STATUSFLAGS2_BIKE_SHOP_CALL_F, [hl]
+	jr z, .NoCall
+
+	; If we're not on the bike, we don't have to be here.
+	ld a, [wPlayerState]
+	cp PLAYER_BIKE
+	jr nz, .NoCall
+
+	; If we're not in an area of phone service, we don't
+	; have to be here.
+	call GetMapPhoneService
+	and a
+	jr nz, .NoCall
+
+	; Check the bike step count and check whether we've
+	; taken 65536 of them yet.
+	ld hl, wBikeStep
+	ld a, [hli]
+	ld d, a
+	ld e, [hl]
+	cp 255
+	jr nz, .increment
+	ld a, e
+	cp 255
+	jr z, .dont_increment
+
+.increment
+	inc de
+	ld [hl], e
+	dec hl
+	ld [hl], d
+
+.dont_increment
+	; If we've taken at least 1024 steps, have the bike
+	;  shop owner try to call us.
+	ld a, d
+	cp HIGH(1024)
+	jr c, .NoCall
+
+	; If a call has already been queued, don't overwrite
+	; that call.
+	ld a, [wSpecialPhoneCallID]
+	and a
+	jr nz, .NoCall
+
+	; Queue the call.
+	ld a, SPECIALCALL_BIKESHOP
+	ld [wSpecialPhoneCallID], a
+	xor a
+	ld [wSpecialPhoneCallID + 1], a
+	ld hl, wStatusFlags2
+	res STATUSFLAGS2_BIKE_SHOP_CALL_F, [hl]
+	scf
+	ret
+
+.NoCall:
+	xor a
+	ret
+; 97df9
+
+ClearCmdQueue:: ; 97df9
+	ld hl, wCmdQueue
+	ld de, 6
+	ld c, 4
+	xor a
+.loop
+	ld [hl], a
+	add hl, de
+	dec c
+	jr nz, .loop
+	ret
+; 97e08
+
+HandleCmdQueue:: ; 97e08
+	ld hl, wCmdQueue
+	xor a
+.loop
+	ld [hMapObjectIndexBuffer], a
+	ld a, [hl]
+	and a
+	jr z, .skip
+	push hl
+	ld b, h
+	ld c, l
+	call HandleQueuedCommand
+	pop hl
+
+.skip
+	ld de, CMDQUEUE_ENTRY_SIZE
+	add hl, de
+	ld a, [hMapObjectIndexBuffer]
+	inc a
+	cp CMDQUEUE_CAPACITY
+	jr nz, .loop
+	ret
+; 97e25
+
+Unreferenced_GetNthCmdQueueEntry: ; 97e25
+	ld hl, wCmdQueue
+	ld bc, CMDQUEUE_ENTRY_SIZE
+	call AddNTimes
+	ld b, h
+	ld c, l
+	ret
+; 97e31
+
+WriteCmdQueue:: ; 97e31
+	push bc
+	push de
+	call .GetNextEmptyEntry
+	ld d, h
+	ld e, l
+	pop hl
+	pop bc
+	ret c
+	ld a, b
+	ld bc, CMDQUEUE_ENTRY_SIZE - 1
+	call FarCopyBytes
+	xor a
+	ld [hl], a
+	ret
+; 97e45
+
+.GetNextEmptyEntry: ; 97e45
+	ld hl, wCmdQueue
+	ld de, CMDQUEUE_ENTRY_SIZE
+	ld c, CMDQUEUE_CAPACITY
+.loop
+	ld a, [hl]
+	and a
+	jr z, .done
+	add hl, de
+	dec c
+	jr nz, .loop
+	scf
+	ret
+
+.done
+	ld a, CMDQUEUE_CAPACITY
+	sub c
+	and a
+	ret
+; 97e5c
+
+DelCmdQueue:: ; 97e5c
+	ld hl, wCmdQueue
+	ld de, CMDQUEUE_ENTRY_SIZE
+	ld c, CMDQUEUE_CAPACITY
+.loop
+	ld a, [hl]
+	cp b
+	jr z, .done
+	add hl, de
+	dec c
+	jr nz, .loop
+	and a
+	ret
+
+.done
+	xor a
+	ld [hl], a
+	scf
+	ret
+; 97e72
+
+_DelCmdQueue: ; 97e72
+	ld hl, CMDQUEUE_TYPE
+	add hl, bc
+	ld [hl], 0
+	ret
+; 97e79
+
+HandleQueuedCommand: ; 97e79
+	ld hl, CMDQUEUE_TYPE
+	add hl, bc
+	ld a, [hl]
+	cp 5
+	jr c, .okay
+	xor a
+
+.okay
+	ld e, a
+	ld d, 0
+	ld hl, .Jumptable
+	add hl, de
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	push af
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	pop af
+	rst FarCall
+	ret
+; 97e94
+
+.Jumptable: ; 97e94
+	dba CmdQueue_Null
+	dba CmdQueue_Null2
+	dba CmdQueue_StoneTable
+	dba CmdQueue_Type3
+	dba CmdQueue_Type4
+; 97ea3
+
+CmdQueueAnonymousJumptable: ; 97ea3
+	ld hl, CMDQUEUE_05
+	add hl, bc
+	ld a, [hl]
+	pop hl
+	rst JumpTable
+	ret
+; 97eab
+
+CmdQueueAnonJT_Increment: ; 97eab
+	ld hl, CMDQUEUE_05
+	add hl, bc
+	inc [hl]
+	ret
+; 97eb1
+
+CmdQueueAnonJT_Decrement: ; 97eb1
+	ld hl, CMDQUEUE_05
+	add hl, bc
+	dec [hl]
+	ret
+; 97eb7
+
+CmdQueue_Null: ; 97eb7
+	ret
+; 97eb8
+
+CmdQueue_Null2: ; 97eb8
+	call ret_2f3e
+	ret
+; 97ebc
+
+CmdQueue_Type4: ; 97ebc
+	call CmdQueueAnonymousJumptable
+	; anonymous dw
+	dw .zero
+	dw .one
+; 97ec3
+
+.zero ; 97ec3
+	ld a, [hSCY]
+	ld hl, 4
+	add hl, bc
+	ld [hl], a
+	call CmdQueueAnonJT_Increment
+.one ; 97ecd
+	ld hl, 1
+	add hl, bc
+	ld a, [hl]
+	dec a
+	ld [hl], a
+	jr z, .finish
+	and $1
+	jr z, .add
+	ld hl, 2
+	add hl, bc
+	ld a, [hSCY]
+	sub [hl]
+	ld [hSCY], a
+	ret
+
+.add
+	ld hl, 2
+	add hl, bc
+	ld a, [hSCY]
+	add [hl]
+	ld [hSCY], a
+	ret
+
+.finish
+	ld hl, 4
+	add hl, bc
+	ld a, [hl]
+	ld [hSCY], a
+	call _DelCmdQueue
+	ret
+; 97ef9
+
+CmdQueue_Type3: ; 97ef9
+	call CmdQueueAnonymousJumptable
+	; anonymous dw
+	dw .zero
+	dw .one
+	dw .two
+; 97f02
+
+.zero ; 97f02
+	call .IsPlayerFacingDown
+	jr z, .PlayerNotFacingDown
+	call CmdQueueAnonJT_Increment
+.one ; 97f0a
+	call .IsPlayerFacingDown
+	jr z, .PlayerNotFacingDown
+	call CmdQueueAnonJT_Increment
+
+	ld hl, 2
+	add hl, bc
+	ld a, [hl]
+	ld [wd173], a
+	ret
+; 97f1b
+
+.two ; 97f1b
+	call .IsPlayerFacingDown
+	jr z, .PlayerNotFacingDown
+	call CmdQueueAnonJT_Decrement
+
+	ld hl, 3
+	add hl, bc
+	ld a, [hl]
+	ld [wd173], a
+	ret
+; 97f2c
+
+.PlayerNotFacingDown: ; 97f2c
+	ld a, $7f
+	ld [wd173], a
+	ld hl, 5
+	add hl, bc
+	ld [hl], 0
+	ret
+; 97f38
+
+.IsPlayerFacingDown: ; 97f38
+	push bc
+	ld bc, wPlayerStruct
+	call GetSpriteDirection
+	and a
+	pop bc
+	ret
+; 97f42
+
+CmdQueue_StoneTable: ; 97f42
+	ld de, wPlayerStruct
+	ld a, NUM_OBJECT_STRUCTS
+.loop
+	push af
+
+	ld hl, OBJECT_SPRITE
+	add hl, de
+	ld a, [hl]
+	and a
+	jr z, .next
+
+	ld hl, OBJECT_MOVEMENTTYPE
+	add hl, de
+	ld a, [hl]
+	cp SPRITEMOVEDATA_STRENGTH_BOULDER
+	jr nz, .next
+
+	ld hl, OBJECT_NEXT_TILE
+	add hl, de
+	ld a, [hl]
+	call CheckPitTile
+	jr nz, .next
+
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, de
+	ld a, [hl]
+	cp STANDING
+	jr nz, .next
+	call HandleStoneQueue
+	jr c, .fall_down_hole
+
+.next
+	ld hl, OBJECT_STRUCT_LENGTH
+	add hl, de
+	ld d, h
+	ld e, l
+
+	pop af
+	dec a
+	jr nz, .loop
+	ret
+
+.fall_down_hole
+	pop af
+	ret
+; 97f7e
--- /dev/null
+++ b/engine/overworld/init_map.asm
@@ -1,0 +1,103 @@
+ReanchorBGMap_NoOAMUpdate:: ; 6454
+	call DelayFrame
+	ld a, [hOAMUpdate]
+	push af
+
+	ld a, $1
+	ld [hOAMUpdate], a
+	ld a, [hBGMapMode]
+	push af
+	xor a
+	ld [hBGMapMode], a
+
+	call .ReanchorBGMap
+
+	pop af
+	ld [hBGMapMode], a
+	pop af
+	ld [hOAMUpdate], a
+	ld hl, wVramState
+	set 6, [hl]
+	ret
+
+.ReanchorBGMap:
+	xor a
+	ld [hLCDCPointer], a
+	ld [hBGMapMode], a
+	ld a, $90
+	ld [hWY], a
+	call OverworldTextModeSwitch
+	ld a, HIGH(vBGMap1)
+	call .LoadBGMapAddrIntoHRAM
+	call _OpenAndCloseMenu_HDMATransferTileMapAndAttrMap
+	farcall LoadOW_BGPal7
+	farcall ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	xor a
+	ld [hBGMapMode], a
+	ld [hWY], a
+	farcall HDMATransfer_FillBGMap0WithBlack ; no need to farcall
+	ld a, HIGH(vBGMap0)
+	call .LoadBGMapAddrIntoHRAM
+	xor a ; LOW(vBGMap0)
+	ld [wBGMapAnchor], a
+	ld a, HIGH(vBGMap0)
+	ld [wBGMapAnchor + 1], a
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	call ApplyBGMapAnchorToObjects
+	ret
+
+.LoadBGMapAddrIntoHRAM: ; 64b9
+	ld [hBGMapAddress + 1], a
+	xor a
+	ld [hBGMapAddress], a
+	ret
+
+LoadFonts_NoOAMUpdate:: ; 64bf
+	ld a, [hOAMUpdate]
+	push af
+	ld a, $1
+	ld [hOAMUpdate], a
+
+	call .LoadGFX
+
+	pop af
+	ld [hOAMUpdate], a
+	ret
+
+.LoadGFX:
+	call LoadFontsExtra
+	ld a, $90
+	ld [hWY], a
+	call SafeUpdateSprites
+	call LoadStandardFont
+	ret
+
+HDMATransfer_FillBGMap0WithBlack: ; 64db
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wDecompressScratch)
+	ld [rSVBK], a
+
+	ld a, "■"
+	ld hl, wDecompressScratch
+	ld bc, wScratchAttrMap - wDecompressScratch
+	call ByteFill
+	ld a, HIGH(wDecompressScratch)
+	ld [rHDMA1], a
+	ld a, LOW(wDecompressScratch)
+	ld [rHDMA2], a
+	ld a, HIGH(vBGMap0 % $8000)
+	ld [rHDMA3], a
+	ld a, LOW(vBGMap0 % $8000)
+	ld [rHDMA4], a
+	ld a, $3f
+	ld [hDMATransfer], a
+	call DelayFrame
+
+	pop af
+	ld [rSVBK], a
+	ret
--- /dev/null
+++ b/engine/overworld/landmarks.asm
@@ -1,0 +1,87 @@
+GetLandmarkCoords: ; 0x1ca896
+; Return coordinates (d, e) of landmark e.
+	push hl
+	ld l, e
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	ld de, Landmarks
+	add hl, de
+	ld a, [hli]
+	ld e, a
+	ld d, [hl]
+	pop hl
+	ret
+; 0x1ca8a5
+
+
+GetLandmarkName:: ; 0x1ca8a5
+; Copy the name of landmark e to wStringBuffer1.
+	push hl
+	push de
+	push bc
+
+	ld l, e
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	ld de, Landmarks + 2
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+
+	ld de, wStringBuffer1
+	ld c, 18
+.copy
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec c
+	jr nz, .copy
+
+	pop bc
+	pop de
+	pop hl
+	ret
+; 0x1ca8c3
+
+
+INCLUDE "data/maps/landmarks.asm"
+
+
+RegionCheck: ; 0x1caea1
+; Checks if the player is in Kanto or Johto.
+; If in Johto, returns 0 in e.
+; If in Kanto, returns 1 in e.
+	ld a, [wMapGroup]
+	ld b, a
+	ld a, [wMapNumber]
+	ld c, a
+	call GetWorldMapLocation
+	cp FAST_SHIP ; S.S. Aqua
+	jr z, .johto
+	cp SPECIAL_MAP
+	jr nz, .checkagain
+
+; In a special map, get the backup map group / map id
+	ld a, [wBackupMapGroup]
+	ld b, a
+	ld a, [wBackupMapNumber]
+	ld c, a
+	call GetWorldMapLocation
+
+.checkagain
+	cp KANTO_LANDMARK
+	jr c, .johto
+
+; Victory Road area is considered to be Johto.
+	cp VICTORY_ROAD
+	jr c, .kanto
+
+.johto
+	ld e, JOHTO_REGION
+	ret
+.kanto
+	ld e, KANTO_REGION
+	ret
--- /dev/null
+++ b/engine/overworld/map_object_action.asm
@@ -1,0 +1,313 @@
+ObjectActionPairPointers: ; 445f
+; entries correspond to OBJECT_ACTION_* constants
+	dw SetFacingStanding,              SetFacingStanding
+	dw SetFacingStandAction,           SetFacingCurrent
+	dw SetFacingStepAction,            SetFacingCurrent
+	dw SetFacingBumpAction,            SetFacingCurrent
+	dw SetFacingCounterclockwiseSpin,  SetFacingCurrent
+	dw SetFacingCounterclockwiseSpin2, SetFacingStanding
+	dw SetFacingFish,                  SetFacingFish
+	dw SetFacingShadow,                SetFacingStanding
+	dw SetFacingEmote,                 SetFacingEmote
+	dw SetFacingBigDollSym,            SetFacingBigDollSym
+	dw SetFacingBounce,                SetFacingFreezeBounce
+	dw SetFacingWeirdTree,             SetFacingCurrent
+	dw SetFacingBigDollAsym,           SetFacingBigDollAsym
+	dw SetFacingBigDoll,               SetFacingBigDoll
+	dw SetFacingBoulderDust,           SetFacingStanding
+	dw SetFacingGrassShake,            SetFacingStanding
+	dw SetFacingSkyfall,               SetFacingCurrent
+; 44a3
+
+SetFacingStanding: ; 44a3
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], STANDING
+	ret
+; 44aa
+
+SetFacingCurrent: ; 44aa
+	call GetSpriteDirection
+	or FACING_STEP_DOWN_0 ; useless
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], a
+	ret
+; 44b5
+
+SetFacingStandAction: ; 44b5
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld a, [hl]
+	and 1
+	jr nz, SetFacingStepAction
+	jp SetFacingCurrent
+; 44c1
+
+SetFacingStepAction: ; 44c1
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	bit SLIDING, [hl]
+	jp nz, SetFacingCurrent
+
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld a, [hl]
+	inc a
+	and %00001111
+	ld [hl], a
+
+	rrca
+	rrca
+	and %00000011
+	ld d, a
+
+	call GetSpriteDirection
+	or FACING_STEP_DOWN_0 ; useless
+	or d
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], a
+	ret
+; 44e4
+
+SetFacingSkyfall: ; 44e4
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	bit SLIDING, [hl]
+	jp nz, SetFacingCurrent
+
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld a, [hl]
+	add 2
+	and %00001111
+	ld [hl], a
+
+	rrca
+	rrca
+	and %00000011
+	ld d, a
+
+	call GetSpriteDirection
+	or FACING_STEP_DOWN_0 ; useless
+	or d
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], a
+	ret
+; 4508
+
+SetFacingBumpAction: ; 4508
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	bit SLIDING, [hl]
+	jp nz, SetFacingCurrent
+
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	inc [hl]
+
+	ld a, [hl]
+	rrca
+	rrca
+	rrca
+	and %00000011
+	ld d, a
+
+	call GetSpriteDirection
+	or FACING_STEP_DOWN_0 ; useless
+	or d
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], a
+	ret
+; 4529
+
+SetFacingCounterclockwiseSpin: ; 4529
+	call CounterclockwiseSpinAction
+	ld hl, OBJECT_FACING
+	add hl, bc
+	ld a, [hl]
+	or FACING_STEP_DOWN_0 ; useless
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], a
+	ret
+; 4539
+
+SetFacingCounterclockwiseSpin2: ; 4539
+	call CounterclockwiseSpinAction
+	jp SetFacingStanding
+; 453f
+
+CounterclockwiseSpinAction: ; 453f
+; Here, OBJECT_STEP_FRAME consists of two 2-bit components,
+; using only bits 0,1 and 4,5.
+; bits 0,1 is a timer (4 overworld frames)
+; bits 4,5 determines the facing - the direction is counterclockwise.
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld a, [hl]
+	and %11110000
+	ld e, a
+
+	ld a, [hl]
+	inc a
+	and %00001111
+	ld d, a
+	cp 4
+	jr c, .ok
+
+	ld d, 0
+	ld a, e
+	add $10
+	and %00110000
+	ld e, a
+
+.ok
+	ld a, d
+	or e
+	ld [hl], a
+
+	swap e
+	ld d, 0
+	ld hl, .Directions
+	add hl, de
+	ld a, [hl]
+	ld hl, OBJECT_FACING
+	add hl, bc
+	ld [hl], a
+	ret
+; 456a
+
+.Directions: ; 456a
+	db OW_DOWN, OW_RIGHT, OW_UP, OW_LEFT
+; 456e
+
+SetFacingFish: ; 456e
+	call GetSpriteDirection
+	rrca
+	rrca
+	add FACING_FISH_DOWN
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], a
+	ret
+; 457b
+
+SetFacingShadow: ; 457b
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], FACING_SHADOW
+	ret
+; 4582
+
+SetFacingEmote: ; 4582 emote
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], FACING_EMOTE
+	ret
+; 4589
+
+SetFacingBigDollSym: ; 4589
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], FACING_BIG_DOLL_SYM
+	ret
+; 4590
+
+SetFacingBounce: ; 4590
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld a, [hl]
+	inc a
+	and %00001111
+	ld [hl], a
+	and %00001000
+	jr z, SetFacingFreezeBounce
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], FACING_STEP_UP_0
+	ret
+; 45a4
+
+SetFacingFreezeBounce: ; 45a4
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], FACING_STEP_DOWN_0
+	ret
+; 45ab
+
+SetFacingWeirdTree: ; 45ab
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld a, [hl]
+	inc a
+	ld [hl], a
+	and %00001100
+	rrca
+	rrca
+	add FACING_WEIRD_TREE_0
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], a
+	ret
+; 45be
+
+SetFacingBigDollAsym: ; 45be
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], FACING_BIG_DOLL_ASYM
+	ret
+; 45c5
+
+SetFacingBigDoll: ; 45c5
+	ld a, [wVariableSprites + SPRITE_BIG_DOLL - SPRITE_VARS]
+	ld d, FACING_BIG_DOLL_SYM ; symmetric
+	cp SPRITE_BIG_SNORLAX
+	jr z, .ok
+	cp SPRITE_BIG_LAPRAS
+	jr z, .ok
+	ld d, FACING_BIG_DOLL_ASYM ; asymmetric
+
+.ok
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], d
+	ret
+; 45da
+
+SetFacingBoulderDust: ; 45da
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	inc [hl]
+	ld a, [hl]
+
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	and 2
+	ld a, FACING_BOULDER_DUST_1
+	jr z, .ok
+	inc a ; FACING_BOULDER_DUST_2
+.ok
+	ld [hl], a
+	ret
+; 45ed
+
+SetFacingGrassShake: ; 45ed
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	inc [hl]
+	ld a, [hl]
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	and 4
+	ld a, FACING_GRASS_1
+	jr z, .ok
+	inc a ; FACING_GRASS_2
+
+.ok
+	ld [hl], a
+	ret
+; 4600
--- /dev/null
+++ b/engine/overworld/map_objects.asm
@@ -1,0 +1,3123 @@
+INCLUDE "data/sprites/facings.asm"
+
+INCLUDE "data/sprites/map_objects.asm"
+
+
+; 4357
+DeleteMapObject:: ; 4357
+	push bc
+	ld hl, OBJECT_MAP_OBJECT_INDEX
+	add hl, bc
+	ld a, [hl]
+	push af
+	ld h, b
+	ld l, c
+	ld bc, OBJECT_STRUCT_LENGTH
+	xor a
+	call ByteFill
+	pop af
+	cp -1
+	jr z, .ok
+	bit 7, a
+	jr nz, .ok
+	call GetMapObject
+	ld hl, OBJECT_SPRITE
+	add hl, bc
+	ld [hl], -1
+.ok
+	pop bc
+	ret
+; 437b
+
+Function437b: ; 437b
+	call .CheckObjectStillVisible
+	ret c
+	call .HandleStepType
+	call .HandleObjectAction
+	ret
+
+.CheckObjectStillVisible:
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	res 6, [hl]
+	ld a, [wXCoord]
+	ld e, a
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	add 1
+	sub e
+	jr c, .ok
+	cp MAPOBJECT_SCREEN_WIDTH
+	jr nc, .ok
+	ld a, [wYCoord]
+	ld e, a
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld a, [hl]
+	add 1
+	sub e
+	jr c, .ok
+	cp MAPOBJECT_SCREEN_HEIGHT
+	jr nc, .ok
+	jr .yes
+
+.ok
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	set 6, [hl]
+	ld a, [wXCoord]
+	ld e, a
+	ld hl, OBJECT_INIT_X
+	add hl, bc
+	ld a, [hl]
+	add 1
+	sub e
+	jr c, .ok2
+	cp MAPOBJECT_SCREEN_WIDTH
+	jr nc, .ok2
+	ld a, [wYCoord]
+	ld e, a
+	ld hl, OBJECT_INIT_Y
+	add hl, bc
+	ld a, [hl]
+	add 1
+	sub e
+	jr c, .ok2
+	cp MAPOBJECT_SCREEN_HEIGHT
+	jr nc, .ok2
+.yes
+	and a
+	ret
+
+.ok2
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	bit 1, [hl]
+	jr nz, .yes2
+	call DeleteMapObject
+	scf
+	ret
+
+.yes2
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	set 6, [hl]
+	and a
+	ret
+
+.HandleStepType:
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .zero
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	bit 5, [hl]
+	jr nz, .bit5
+	cp STEP_TYPE_SLEEP
+	jr z, .one
+	jr .ok3
+
+.zero
+	call ObjectMovementReset
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	bit 5, [hl]
+	jr nz, .bit5
+.one
+	call MapObjectMovementPattern
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld a, [hl]
+	and a
+	ret z
+	cp STEP_TYPE_SLEEP
+	ret z
+.ok3
+	ld hl, StepTypesJumptable
+	rst JumpTable
+	ret
+
+.bit5
+	ret
+
+.HandleObjectAction:
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	bit INVISIBLE, [hl]
+	jr nz, SetFacingStanding
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	bit 6, [hl]
+	jr nz, SetFacingStanding
+	bit 5, [hl]
+	jr nz, asm_4448
+	ld de, ObjectActionPairPointers ; use first column
+	jr _HandleObjectAction
+; 4440
+
+Function4440: ; 4440
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	bit INVISIBLE, [hl]
+	jr nz, SetFacingStanding
+asm_4448
+	ld de, ObjectActionPairPointers + 2 ; use second column
+	jr _HandleObjectAction
+; 444d
+
+_HandleObjectAction
+; call [4 * wObjectStructs[ObjInd, OBJECT_ACTION] + de]
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld a, [hl]
+	ld l, a
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	call _hl_
+	ret
+; 445f
+
+INCLUDE "engine/overworld/map_object_action.asm"
+
+CopyNextCoordsTileToStandingCoordsTile: ; 4600
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_MAP_X
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_MAP_Y
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_NEXT_TILE
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_STANDING_TILE
+	add hl, bc
+	ld [hl], a
+	call SetTallGrassFlags
+	ld hl, OBJECT_NEXT_TILE
+	add hl, bc
+	ld a, [hl]
+	call UselessAndA
+	ret
+; 462a
+
+Function462a: ; 462a
+	ld hl, OBJECT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_MAP_Y
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld [hl], a
+	ret
+; 463f
+
+UpdateTallGrassFlags: ; 463f
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	bit OVERHEAD, [hl]
+	jr z, .ok
+	ld hl, OBJECT_NEXT_TILE
+	add hl, bc
+	ld a, [hl]
+	call SetTallGrassFlags
+.ok
+	ld hl, OBJECT_NEXT_TILE
+	add hl, bc
+	ld a, [hl]
+	call UselessAndA
+	ret c ; never happens
+	ld hl, OBJECT_STANDING_TILE
+	add hl, bc
+	ld a, [hl]
+	call UselessAndA
+	ret
+; 4661
+
+SetTallGrassFlags: ; 4661
+	call CheckSuperTallGrassTile
+	jr z, .set
+	call CheckGrassTile
+	jr c, .reset
+.set
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	set OVERHEAD, [hl]
+	ret
+
+.reset
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	res OVERHEAD, [hl]
+	ret
+; 4679
+
+UselessAndA: ; 4679
+	and a
+	ret
+; 467b
+
+EndSpriteMovement: ; 467b
+	xor a
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+	add hl, bc
+	ld [hli], a
+	ld [hli], a
+	ld [hli], a
+	ld [hl], a ; OBJECT_1E
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ret
+; 4690
+
+InitStep: ; 4690
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	bit FIXED_FACING, [hl]
+	jr nz, GetNextTile
+	add a
+	add a
+	and %00001100
+	ld hl, OBJECT_FACING
+	add hl, bc
+	ld [hl], a
+GetNextTile: ; 46a6
+	call GetStepVector
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+	ld a, d
+	call GetStepVectorSign
+	ld hl, OBJECT_MAP_X
+	add hl, bc
+	add [hl]
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld [hl], a
+	ld d, a
+	ld a, e
+	call GetStepVectorSign
+	ld hl, OBJECT_MAP_Y
+	add hl, bc
+	add [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld [hl], a
+	ld e, a
+	push bc
+	call GetCoordTile
+	pop bc
+	ld hl, OBJECT_NEXT_TILE
+	add hl, bc
+	ld [hl], a
+	ret
+; 46d7
+
+AddStepVector: ; 46d7
+	call GetStepVector
+	ld hl, OBJECT_SPRITE_X
+	add hl, bc
+	ld a, [hl]
+	add d
+	ld [hl], a
+	ld hl, OBJECT_SPRITE_Y
+	add hl, bc
+	ld a, [hl]
+	add e
+	ld [hl], a
+	ret
+; 46e9
+
+GetStepVector: ; 46e9
+; Return (x, y, duration, speed) in (d, e, a, h).
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld a, [hl]
+	and %00001111
+	add a
+	add a
+	ld l, a
+	ld h, 0
+	ld de, StepVectors
+	add hl, de
+	ld d, [hl]
+	inc hl
+	ld e, [hl]
+	inc hl
+	ld a, [hli]
+	ld h, [hl]
+	ret
+; 4700
+
+StepVectors: ; 4700
+; x,  y, duration, speed
+	; slow
+	db  0,  1, 16, 1
+	db  0, -1, 16, 1
+	db -1,  0, 16, 1
+	db  1,  0, 16, 1
+	; normal
+	db  0,  2,  8, 2
+	db  0, -2,  8, 2
+	db -2,  0,  8, 2
+	db  2,  0,  8, 2
+	; fast
+	db  0,  4,  4, 4
+	db  0, -4,  4, 4
+	db -4,  0,  4, 4
+	db  4,  0,  4, 4
+; 4730
+
+GetStepVectorSign: ; 4730
+	add a
+	ret z  ; 0 or 128
+	ld a, 1
+	ret nc ; 1 - 127
+	ld a, -1
+	ret    ; 129 - 255
+; 4738
+
+UpdatePlayerStep: ; 4738
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld a, [hl]
+	and %00000011
+	ld [wPlayerStepDirection], a
+	call AddStepVector
+	ld a, [wPlayerStepVectorX]
+	add d
+	ld [wPlayerStepVectorX], a
+	ld a, [wPlayerStepVectorY]
+	add e
+	ld [wPlayerStepVectorY], a
+	ld hl, wPlayerStepFlags
+	set 5, [hl]
+	ret
+; 4759
+
+Unreferenced_Function4759: ; 4759
+	push bc
+	ld e, a
+	ld d, 0
+	ld hl, OBJECT_MAP_OBJECT_INDEX
+	add hl, bc
+	ld a, [hl]
+	call GetMapObject
+	add hl, de
+	ld a, [hl]
+	pop bc
+	ret
+; 4769
+
+RestoreDefaultMovement: ; 4769
+	ld hl, OBJECT_MAP_OBJECT_INDEX
+	add hl, bc
+	ld a, [hl]
+	cp -1
+	jr z, .ok
+	push bc
+	call GetMapObject
+	ld hl, MAPOBJECT_MOVEMENT
+	add hl, bc
+	ld a, [hl]
+	pop bc
+	ret
+
+.ok
+	ld a, SPRITEMOVEFN_STANDING
+	ret
+; 4780
+
+ClearObjectMovementByteIndex: ; 4780
+	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+	add hl, bc
+	ld [hl], 0
+	ret
+; 4787
+
+IncrementObjectMovementByteIndex: ; 4787
+	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+	add hl, bc
+	inc [hl]
+	ret
+; 478d
+
+DecrementObjectMovementByteIndex: ; 478d
+	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+	add hl, bc
+	dec [hl]
+	ret
+; 4793
+
+MovementAnonymousJumptable: ; 4793
+	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+	add hl, bc
+	ld a, [hl]
+	pop hl
+	rst JumpTable
+	ret
+; 479b
+
+ClearObjectStructField1c: ; 479b
+	ld hl, OBJECT_1C
+	add hl, bc
+	ld [hl], 0
+	ret
+; 47a2
+
+IncrementObjectStructField1c: ; 47a2
+	ld hl, OBJECT_1C
+	add hl, bc
+	inc [hl]
+	ret
+; 47a8
+
+Field1cAnonymousJumptable: ; 47a8
+	ld hl, OBJECT_1C
+	add hl, bc
+	ld a, [hl]
+	pop hl
+	rst JumpTable
+	ret
+; 47b0
+
+GetValueObjectStructField1c: ; 47b0
+	ld hl, OBJECT_1C
+	add hl, bc
+	ld a, [hl]
+	ret
+; 47b6
+
+SetValueObjectStructField1c: ; 47b6
+	ld hl, OBJECT_1C
+	add hl, bc
+	ld [hl], a
+	ret
+; 47bc
+
+ObjectMovementReset: ; 47bc
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	push bc
+	call GetCoordTile
+	pop bc
+	ld hl, OBJECT_NEXT_TILE
+	add hl, bc
+	ld [hl], a
+	call CopyNextCoordsTileToStandingCoordsTile
+	call EndSpriteMovement
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 47dd
+
+MapObjectMovementPattern: ; 47dd
+	call ClearObjectStructField1c
+	call GetSpriteMovementFunction
+	ld a, [hl]
+	ld hl, .Pointers
+	rst JumpTable
+	ret
+
+.Pointers: ; 47e9
+; entries correspond to SPRITEMOVEFN_* constants
+	dw .Null_00 ; 00
+	dw .RandomWalkY ; 01
+	dw .RandomWalkX ; 02
+	dw .RandomWalkXY ; 03
+	dw .RandomSpin1 ; 04
+	dw .RandomSpin2 ; 05
+	dw .Standing ; 06
+	dw .ObeyDPad ; 07
+	dw .Movement08 ; 08
+	dw .Movement09 ; 09
+	dw .Movement0a ; 0a
+	dw .Movement0b ; 0b
+	dw .Movement0c ; 0c
+	dw .Movement0d ; 0d
+	dw .Movement0e ; 0e
+	dw .Follow ; 0f
+	dw .Script ; 10
+	dw .Strength ; 11
+	dw .FollowNotExact ; 12
+	dw .MovementShadow ; 13
+	dw .MovementEmote ; 14
+	dw .MovementBigStanding ; 15
+	dw .MovementBouncing ; 16
+	dw .MovementScreenShake ; 17
+	dw .MovementSpinClockwise ; 18
+	dw .MovementSpinCounterclockwise ; 19
+	dw .MovementBoulderDust ; 1a
+	dw .MovementShakingGrass ; 1b
+
+.Null_00:
+	ret
+
+.RandomWalkY:
+	call Random
+	ld a, [hRandomAdd]
+	and %00000001
+	jp .RandomWalkContinue
+
+.RandomWalkX:
+	call Random
+	ld a, [hRandomAdd]
+	and %00000001
+	or  %00000010
+	jp .RandomWalkContinue
+
+.RandomWalkXY:
+	call Random
+	ld a, [hRandomAdd]
+	and %00000011
+	jp .RandomWalkContinue
+
+.RandomSpin1:
+	call Random
+	ld a, [hRandomAdd]
+	and %00001100
+	ld hl, OBJECT_FACING
+	add hl, bc
+	ld [hl], a
+	jp RandomStepDuration_Slow
+
+.RandomSpin2:
+	ld hl, OBJECT_FACING
+	add hl, bc
+	ld a, [hl]
+	and %00001100
+	ld d, a
+	call Random
+	ld a, [hRandomAdd]
+	and %00001100
+	cp d
+	jr nz, .keep
+	xor %00001100
+.keep
+	ld [hl], a
+	jp RandomStepDuration_Fast
+
+.Standing:
+	call Function462a
+	call EndSpriteMovement
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STAND
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_05
+	ret
+
+.ObeyDPad:
+	ld hl, Function5000
+	jp HandleMovementData
+
+.Movement08:
+	ld hl, Function5015
+	jp HandleMovementData
+
+.Movement09:
+	ld hl, Function5026
+	jp HandleMovementData
+
+.Movement0a:
+	jp _GetMovementObject
+
+.Movement0b:
+	jp _GetMovementObject
+
+.Movement0c:
+	jp _GetMovementObject
+
+.Movement0d:
+	ld hl, Function5000
+	jp HandleMovementData
+
+.Movement0e:
+	jp _GetMovementObject
+
+.Follow:
+	ld hl, GetFollowerNextMovementByte
+	jp HandleMovementData
+
+.Script:
+	ld hl, GetMovementByte
+	jp HandleMovementData
+
+.Strength:
+	call MovementAnonymousJumptable
+	dw .Strength_Start
+	dw .Strength_Stop
+
+.Strength_Start:
+	ld hl, OBJECT_NEXT_TILE
+	add hl, bc
+	ld a, [hl]
+	call CheckPitTile
+	jr z, .on_pit
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	bit 2, [hl]
+	res 2, [hl]
+	jr z, .ok
+	ld hl, OBJECT_RANGE
+	add hl, bc
+	ld a, [hl]
+	and %00000011
+	or 0
+	call InitStep
+	call Function6ec1
+	jr c, .ok2
+	ld de, SFX_STRENGTH
+	call PlaySFX
+	call SpawnStrengthBoulderDust
+	call UpdateTallGrassFlags
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_0F
+	ret
+
+.ok2
+	call Function462a
+.ok
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ret
+
+.on_pit
+	call IncrementObjectMovementByteIndex
+.Strength_Stop:
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ret
+
+.FollowNotExact:
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	ld hl, OBJECT_RANGE
+	add hl, bc
+	ld a, [hl]
+	push bc
+	call GetObjectStruct
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld a, [hl]
+	cp STANDING
+	jr z, .standing
+	ld hl, OBJECT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	cp d
+	jr z, .equal
+	jr c, .less
+	ld a, 3
+	jr .done
+
+.less
+	ld a, 2
+	jr .done
+
+.equal
+	ld hl, OBJECT_MAP_Y
+	add hl, bc
+	ld a, [hl]
+	cp e
+	jr z, .standing
+	jr c, .less2
+	ld a, 0
+	jr .done
+
+.less2
+	ld a, 1
+.done
+	ld d, a
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld a, [hl]
+	and %00001100
+	or d
+	pop bc
+	jp NormalStep
+
+.standing
+	pop bc
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STAND
+	ret
+
+.MovementBigStanding:
+	call EndSpriteMovement
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_BIG_DOLL_SYM
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_04
+	ret
+
+.MovementBouncing:
+	call EndSpriteMovement
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_BOUNCE
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_04
+	ret
+
+.MovementSpinCounterclockwise:
+	call MovementAnonymousJumptable
+	dw .MovementSpinInit
+	dw .MovementSpinRepeat
+	dw .MovementSpinTurnLeft
+
+.MovementSpinClockwise:
+	call MovementAnonymousJumptable
+	dw .MovementSpinInit
+	dw .MovementSpinRepeat
+	dw .MovementSpinTurnRight
+
+.MovementSpinInit:
+	call EndSpriteMovement
+	call IncrementObjectMovementByteIndex
+.MovementSpinRepeat:
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STAND
+	ld hl, OBJECT_RANGE
+	add hl, bc
+	ld a, [hl]
+	ld a, $10
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_03
+	call IncrementObjectMovementByteIndex
+	ret
+
+.MovementSpinTurnLeft:
+	ld de, .DirectionData_Counterclockwise
+	call .MovementSpinNextFacing
+	jr .MovementSpinCounterclockwise
+
+.DirectionData_Counterclockwise: ; 49c0
+	db OW_RIGHT, OW_LEFT, OW_DOWN, OW_UP
+
+.MovementSpinTurnRight:
+	ld de, .DirectionData_Clockwise
+	call .MovementSpinNextFacing
+	jr .MovementSpinClockwise
+
+.DirectionData_Clockwise: ; 49cc
+	db OW_LEFT, OW_RIGHT, OW_UP, OW_DOWN
+
+.MovementSpinNextFacing:
+	ld hl, OBJECT_FACING
+	add hl, bc
+	ld a, [hl]
+	and %00001100
+	rrca
+	rrca
+	push hl
+	ld l, a
+	ld h, 0
+	add hl, de
+	ld a, [hl]
+	pop hl
+	ld [hl], a
+	call DecrementObjectMovementByteIndex
+	ret
+
+.MovementShadow:
+	call ._MovementShadow_Grass_Emote_BoulderDust
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_SHADOW
+	ld hl, OBJECT_STEP_DURATION
+	add hl, de
+	ld a, [hl]
+	inc a
+	add a
+	add 0
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, de
+	ld a, [hl]
+	maskbits NUM_DIRECTIONS
+	ld d, 1 * 8 + 6
+	cp DOWN
+	jr z, .ok_13
+	cp UP
+	jr z, .ok_13
+	ld d, 1 * 8 + 4
+.ok_13
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], d
+	ld hl, OBJECT_SPRITE_X_OFFSET
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_TRACKING_OBJECT
+	ret
+
+.MovementEmote:
+	call EndSpriteMovement
+	call ._MovementShadow_Grass_Emote_BoulderDust
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_EMOTE
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], -2 * 8
+	ld hl, OBJECT_SPRITE_X_OFFSET
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_TRACKING_OBJECT
+	ret
+
+.MovementBoulderDust:
+	call EndSpriteMovement
+	call ._MovementShadow_Grass_Emote_BoulderDust
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_BOULDER_DUST
+	ld hl, OBJECT_STEP_DURATION
+	add hl, de
+	ld a, [hl]
+	inc a
+	add a
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, de
+	ld a, [hl]
+	and %00000011
+	ld e, a
+	ld d, 0
+	ld hl, .data_4a81
+	add hl, de
+	add hl, de
+	ld d, [hl]
+	inc hl
+	ld e, [hl]
+	ld hl, OBJECT_SPRITE_X_OFFSET
+	add hl, bc
+	ld [hl], d
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], e
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_TRACKING_OBJECT
+	ret
+
+.data_4a81  ; 4a81
+	;   x,  y
+	db  0, -4
+	db  0,  8
+	db  6,  2
+	db -6,  2
+
+.MovementShakingGrass:
+	call EndSpriteMovement
+	call ._MovementShadow_Grass_Emote_BoulderDust
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_GRASS_SHAKE
+	ld hl, OBJECT_STEP_DURATION
+	add hl, de
+	ld a, [hl]
+	add -1
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_TRACKING_OBJECT
+	ret
+
+._MovementShadow_Grass_Emote_BoulderDust:
+	ld hl, OBJECT_RANGE
+	add hl, bc
+	ld a, [hl]
+	push bc
+	call GetObjectStruct
+	ld d, b
+	ld e, c
+	pop bc
+	ld hl, OBJECT_1D
+	add hl, bc
+	ld [hl], e
+	inc hl
+	ld [hl], d
+	ret
+
+.MovementScreenShake:
+	call EndSpriteMovement
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_00
+	ld hl, OBJECT_RANGE
+	add hl, bc
+	ld a, [hl]
+	call ._MovementScreenShake
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], e
+	ld hl, OBJECT_1E
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_15
+	ret
+
+._MovementScreenShake:
+	ld d, a
+	and %00111111
+	ld e, a
+	ld a, d
+	rlca
+	rlca
+	and %00000011
+	ld d, a
+	inc d
+	ld a, 1
+.loop
+	dec d
+	ret z
+	add a
+	jr .loop
+
+.RandomWalkContinue:
+	call InitStep
+	call Function6ec1 ; check whether the object can move in that direction
+	jr c, .NewDuration
+	call UpdateTallGrassFlags
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STEP
+	ld hl, wCenteredObject
+	ld a, [hMapObjectIndexBuffer]
+	cp [hl]
+	jr z, .load_6
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_07
+	ret
+
+.load_6
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_PLAYER_WALK
+	ret
+
+.NewDuration:
+	call EndSpriteMovement
+	call Function462a
+RandomStepDuration_Slow: ; 4b1d
+	call Random
+	ld a, [hRandomAdd]
+	and %01111111
+	jr SetRandomStepDuration
+; 4b26
+
+RandomStepDuration_Fast: ; 4b26
+	call Random
+	ld a, [hRandomAdd]
+	and %00011111
+SetRandomStepDuration: ; 4b2d
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STAND
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_03
+	ret
+; 4b45
+
+StepTypesJumptable: ; 4b45
+; entries correspond to STEP_TYPE_* constants
+	dw ObjectMovementReset ; 00
+	dw MapObjectMovementPattern ; 01
+	dw NPCStep ; 02
+	dw StepType03 ; 03
+	dw StepType04 ; 04
+	dw StepType05 ; 05
+	dw PlayerStep ; 06
+	dw StepType07 ; 07
+	dw NPCJump ; 08
+	dw PlayerJump ; 09
+	dw PlayerOrNPCTurnStep ; 0a
+	dw StepTypeBump ; 0b
+	dw TeleportFrom ; 0c
+	dw TeleportTo ; 0d
+	dw Skyfall ; 0e
+	dw StepType0f ; 0f
+	dw GotBiteStep ; 10
+	dw RockSmashStep ; 11
+	dw ReturnDigStep ; 12
+	dw StepTypeTrackingObject ; 13
+	dw StepType14 ; 14
+	dw StepType15 ; 15
+	dw StepType16 ; 16
+	dw StepType17 ; 17
+	dw StepType18 ; 18
+	dw SkyfallTop ; 19
+; 4b79
+
+WaitStep_InPlace: ; 4b79
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4b86
+
+NPCJump: ; 4b86
+	call Field1cAnonymousJumptable
+; anonymous dw
+	dw .Jump
+	dw .Land
+
+.Jump:
+	call AddStepVector
+	call UpdateJumpPosition
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	call CopyNextCoordsTileToStandingCoordsTile
+	call GetNextTile
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	res 3, [hl]
+	call IncrementObjectStructField1c
+	ret
+
+.Land:
+	call AddStepVector
+	call UpdateJumpPosition
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	call CopyNextCoordsTileToStandingCoordsTile
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4bbf
+
+PlayerJump: ; 4bbf
+	call Field1cAnonymousJumptable
+; anonymous dw
+	dw .initjump
+	dw .stepjump
+	dw .initland
+	dw .stepland
+
+.initjump
+	ld hl, wPlayerStepFlags
+	set 7, [hl]
+	call IncrementObjectStructField1c
+.stepjump
+	call UpdateJumpPosition
+	call UpdatePlayerStep
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	call CopyNextCoordsTileToStandingCoordsTile
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	res 3, [hl]
+	ld hl, wPlayerStepFlags
+	set 6, [hl]
+	set 4, [hl]
+	call IncrementObjectStructField1c
+	ret
+
+.initland
+	call GetNextTile
+	ld hl, wPlayerStepFlags
+	set 7, [hl]
+	call IncrementObjectStructField1c
+.stepland
+	call UpdateJumpPosition
+	call UpdatePlayerStep
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	ld hl, wPlayerStepFlags
+	set 6, [hl]
+	call CopyNextCoordsTileToStandingCoordsTile
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4c18
+
+TeleportFrom: ; 4c18
+	call Field1cAnonymousJumptable
+; anonymous dw
+	dw .InitSpin
+	dw .DoSpin
+	dw .InitSpinRise
+	dw .DoSpinRise
+; 4c23
+
+.InitSpin:
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], 16
+	call IncrementObjectStructField1c
+.DoSpin:
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_SPIN
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	call IncrementObjectStructField1c
+	ret
+
+.InitSpinRise:
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_1F
+	add hl, bc
+	ld [hl], $10
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], 16
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	res 3, [hl]
+	call IncrementObjectStructField1c
+.DoSpinRise:
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_SPIN
+	ld hl, OBJECT_1F
+	add hl, bc
+	inc [hl]
+	ld a, [hl]
+	ld d, $60
+	call Sine
+	ld a, h
+	sub $60
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4c89
+
+TeleportTo: ; 4c89
+	call Field1cAnonymousJumptable
+; anonymous dw
+	dw .InitWait
+	dw .DoWait
+	dw .InitDescent
+	dw .DoDescent
+	dw .InitFinalSpin
+	dw .DoFinalSpin
+	dw .FinishStep
+; 4c9a
+
+.InitWait:
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_00
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], 16
+	call IncrementObjectStructField1c
+	ret
+; 4caa
+
+.DoWait:
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	call IncrementObjectStructField1c
+.InitDescent:
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_1F
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], 16
+	call IncrementObjectStructField1c
+	ret
+; 4cc9
+
+.DoDescent:
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_SPIN
+	ld hl, OBJECT_1F
+	add hl, bc
+	inc [hl]
+	ld a, [hl]
+	ld d, $60
+	call Sine
+	ld a, h
+	sub $60
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	call IncrementObjectStructField1c
+.InitFinalSpin:
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], 16
+	call IncrementObjectStructField1c
+	ret
+; 4cf5
+
+.DoFinalSpin:
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_SPIN
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+.FinishStep:
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4d14
+
+Skyfall: ; 4d14
+	call Field1cAnonymousJumptable
+; anonymous dw
+	dw .Init
+	dw .Step
+	dw .Fall
+	dw .Finish
+; 4d1f
+
+.Init:
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_00
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], 16
+	call IncrementObjectStructField1c
+.Step:
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STEP
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_1F
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], 16
+	call IncrementObjectStructField1c
+.Fall:
+	ld hl, OBJECT_1F
+	add hl, bc
+	inc [hl]
+	ld a, [hl]
+	ld d, $60
+	call Sine
+	ld a, h
+	sub $60
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	call IncrementObjectStructField1c
+.Finish:
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4d7e
+
+GotBiteStep: ; 4d7e
+	call Field1cAnonymousJumptable
+; anonymous dw
+	dw .Init
+	dw .Run
+; 4d85
+
+.Init:
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], 8
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], 0
+	call IncrementObjectStructField1c
+.Run:
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld a, [hl]
+	xor 1
+	ld [hl], a
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4daf
+
+RockSmashStep: ; 4daf
+	call .Step
+	jp WaitStep_InPlace
+; 4db5
+
+.Step:
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld a, [hl]
+	and %00000001
+	ld a, OBJECT_ACTION_STAND
+	jr z, .yes
+	ld a, OBJECT_ACTION_00
+.yes
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], a
+	ret
+; 4dc8
+
+ReturnDigStep: ; 4dc8
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld a, [hl]
+	and %00000001
+	ld a, OBJECT_ACTION_SPIN
+	jr z, .yes
+	ld a, OBJECT_ACTION_SPIN_FLICKER
+.yes
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], a
+	jp WaitStep_InPlace
+; 4ddd
+
+StepType03: ; 4ddd
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4df0
+
+StepType18: ; 4df0
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	jp DeleteMapObject
+; 4dff
+
+StepTypeBump: ; 4dff
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4e0c
+
+StepType05: ; 4e0c
+	call Field1cAnonymousJumptable
+; anonymous dw
+	dw .Reset
+	dw StepType04
+
+.Reset:
+	call RestoreDefaultMovement
+	call GetInitialFacing
+	ld hl, OBJECT_FACING
+	add hl, bc
+	ld [hl], a
+	call IncrementObjectStructField1c
+StepType04: ; 4e21
+	call Stubbed_Function4fb2
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ret
+; 4e2b
+
+NPCStep: ; 4e2b
+	call Stubbed_Function4fb2
+	call AddStepVector
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	call CopyNextCoordsTileToStandingCoordsTile
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4e47
+
+StepType07: ; 4e47
+	call AddStepVector
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	call CopyNextCoordsTileToStandingCoordsTile
+	jp RandomStepDuration_Slow
+; 4e56
+
+PlayerStep: ; 4e56
+; AnimateStep?
+	call Field1cAnonymousJumptable
+; anonymous dw
+	dw .init
+	dw .step
+
+.init
+	ld hl, wPlayerStepFlags
+	set 7, [hl]
+	call IncrementObjectStructField1c
+.step
+	call UpdatePlayerStep
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	ld hl, wPlayerStepFlags
+	set 6, [hl]
+	call CopyNextCoordsTileToStandingCoordsTile
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4e83
+
+PlayerOrNPCTurnStep: ; 4e83
+	call Field1cAnonymousJumptable
+; anonymous dw
+	dw .init1
+	dw .step1
+	dw .init2
+	dw .step2
+
+.init1
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld a, [hl]
+	ld [hl], 2
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], 2
+	call IncrementObjectStructField1c
+.step1
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	call IncrementObjectStructField1c
+.init2
+	ld hl, OBJECT_1D ; new facing
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_FACING
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], 2
+	call IncrementObjectStructField1c
+.step2
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4ecd
+
+StepType0f: ; 4ecd
+	call AddStepVector
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	push bc
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	ld hl, OBJECT_MAP_OBJECT_INDEX
+	add hl, bc
+	ld a, [hl]
+	ld b, a
+	farcall CopyDECoordsToMapObject
+	pop bc
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	res 2, [hl]
+	call CopyNextCoordsTileToStandingCoordsTile
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4f04
+
+StepTypeTrackingObject: ; 4f04
+	ld hl, OBJECT_1D
+	add hl, bc
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	ld hl, OBJECT_SPRITE
+	add hl, de
+	ld a, [hl]
+	and a
+	jr z, .nope
+	ld hl, OBJECT_SPRITE_X
+	add hl, de
+	ld a, [hl]
+	ld hl, OBJECT_SPRITE_X
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_SPRITE_Y
+	add hl, de
+	ld a, [hl]
+	ld hl, OBJECT_SPRITE_Y
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+	ret nz
+.nope
+	jp DeleteMapObject
+; 4f33
+
+StepType14: ; 4f33
+StepType15: ; 4f33
+	call Field1cAnonymousJumptable
+; anonymous dw
+	dw .Init
+	dw .Run
+
+.Init:
+	xor a
+	ld hl, OBJECT_1D
+	add hl, bc
+	ld [hl], a
+	call IncrementObjectStructField1c
+.Run:
+	ld hl, OBJECT_1D
+	add hl, bc
+	ld d, [hl]
+	ld a, [wPlayerStepVectorY]
+	sub d
+	ld [wPlayerStepVectorY], a
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	jr z, .ok
+	ld a, [hl]
+	call .GetSign
+	ld hl, OBJECT_1D
+	add hl, bc
+	ld [hl], a
+	ld d, a
+	ld a, [wPlayerStepVectorY]
+	add d
+	ld [wPlayerStepVectorY], a
+	ret
+
+.ok
+	call DeleteMapObject
+	ret
+
+.GetSign:
+	ld hl, OBJECT_1E
+	add hl, bc
+	and 1
+	ld a, [hl]
+	ret z
+	cpl
+	inc a
+	ret
+; 4f77
+
+StepType16: ; 4f77
+	call Field1cAnonymousJumptable ; ????
+; 4f7a
+StepType17: ; 4f7a
+	call Field1cAnonymousJumptable
+; anonymous dw
+	dw .null
+	dw .null
+	dw .null
+.null
+; 4f83
+
+SkyfallTop: ; 4f83
+	call Field1cAnonymousJumptable
+; anonymous dw
+	dw .Init
+	dw .Run
+
+.Init:
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_SKYFALL
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], 16
+	call IncrementObjectStructField1c
+
+.Run:
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	dec [hl]
+	ret nz
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], $60
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld [hl], 0
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 4fb2
+
+Stubbed_Function4fb2:
+	ret
+	ld hl, OBJECT_1D
+	add hl, bc
+	inc [hl]
+	ld a, [hl]
+	srl a
+	srl a
+	and %00000111
+	ld l, a
+	ld h, 0
+	ld de, .y
+	add hl, de
+	ld a, [hl]
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.y ; 4fcd
+	db 0, -1, -2, -3, -4, -3, -2, -1
+; 4fd5
+UpdateJumpPosition: ; 4fd5
+	call GetStepVector
+	ld a, h
+	ld hl, OBJECT_1F
+	add hl, bc
+	ld e, [hl]
+	add e
+	ld [hl], a
+	nop
+	srl e
+	ld d, 0
+	ld hl, .y
+	add hl, de
+	ld a, [hl]
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.y ; 4ff0
+	db  -4,  -6,  -8, -10, -11, -12, -12, -12
+	db -11, -10,  -9,  -8,  -6,  -4,   0,   0
+; 5000
+Function5000: ; unscripted?
+; copy [wPlayerNextMovement] to [wPlayerMovement]
+	ld a, [wPlayerNextMovement]
+	ld hl, wPlayerMovement
+	ld [hl], a
+; load [wPlayerNextMovement] with movement_step_sleep
+	ld a, movement_step_sleep
+	ld [wPlayerNextMovement], a
+; recover the previous value of [wPlayerNextMovement]
+	ld a, [hl]
+	ret
+; 500e
+
+GetMovementByte:
+	ld hl, wMovementDataPointer
+	call _GetMovementByte
+	ret
+; 5015
+
+Function5015: ; 5015
+	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+	add hl, bc
+	ld e, [hl]
+	inc [hl]
+	ld d, 0
+	ld hl, wc2e2
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	add hl, de
+	ld a, [hl]
+	ret
+; 5026
+
+Function5026: ; 5026
+	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+	add hl, bc
+	ld e, [hl]
+	inc [hl]
+	ld d, 0
+	ld hl, wc2e6
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	add hl, de
+	ld a, [hl]
+	ret
+; 5037
+
+_GetMovementObject: ; 5037
+	ld hl, GetMovementObject
+	jp HandleMovementData
+; 503d
+
+GetMovementObject: ; 503d
+	ld a, [wMovementObject]
+	ret
+; 5041
+
+HandleMovementData: ; 5041
+	call .StorePointer
+.loop
+	xor a
+	ld [wMovementByteWasControlSwitch], a
+	call JumpMovementPointer
+	call DoMovementFunction
+	ld a, [wMovementByteWasControlSwitch]
+	and a
+	jr nz, .loop
+	ret
+
+.StorePointer:
+	ld a, l
+	ld [wMovementPointer], a
+	ld a, h
+	ld [wMovementPointer + 1], a
+	ret
+; 505e
+
+JumpMovementPointer: ; 505e
+	ld hl, wMovementPointer
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+; 5065
+
+ContinueReadingMovement: ; 5065
+	ld a, 1
+	ld [wMovementByteWasControlSwitch], a
+	ret
+; 506b
+
+DoMovementFunction: ; 506b
+	push af
+	call ApplyMovementToFollower
+	pop af
+	ld hl, MovementPointers
+	rst JumpTable
+	ret
+; 5075
+
+INCLUDE "engine/overworld/movement.asm"
+; 54b8
+
+ApplyMovementToFollower: ; 54b8
+	ld e, a
+	ld a, [wObjectFollow_Follower]
+	cp -1
+	ret z
+	ld a, [wObjectFollow_Leader]
+	ld d, a
+	ld a, [hMapObjectIndexBuffer]
+	cp d
+	ret nz
+	ld a, e
+	cp movement_step_sleep
+	ret z
+	cp movement_step_end
+	ret z
+	cp movement_step_4b
+	ret z
+	cp movement_step_bump
+	ret z
+	cp movement_slow_step
+	ret c
+	push af
+	ld hl, wFollowerMovementQueueLength
+	inc [hl]
+	ld e, [hl]
+	ld d, 0
+	ld hl, wFollowMovementQueue
+	add hl, de
+	pop af
+	ld [hl], a
+	ret
+; 54e6
+
+GetFollowerNextMovementByte: ; 54e6
+	ld hl, wFollowerMovementQueueLength
+	ld a, [hl]
+	and a
+	jr z, .done
+	cp -1
+	jr z, .done
+	dec [hl]
+	ld e, a
+	ld d, 0
+	ld hl, wFollowMovementQueue
+	add hl, de
+	inc e
+	ld a, -1
+.loop
+	ld d, [hl]
+	ld [hld], a
+	ld a, d
+	dec e
+	jr nz, .loop
+	ret
+
+.done
+	call .CancelFollowIfLeaderMissing
+	ret c
+	ld a, movement_step_sleep
+	ret
+
+.CancelFollowIfLeaderMissing:
+	ld a, [wObjectFollow_Leader]
+	cp -1
+	jr z, .nope
+	push bc
+	call GetObjectStruct
+	ld hl, OBJECT_SPRITE
+	add hl, bc
+	ld a, [hl]
+	pop bc
+	and a
+	jr z, .nope
+	and a
+	ret
+
+.nope
+	ld a, -1
+	ld [wObjectFollow_Follower], a
+	ld a, movement_step_end
+	scf
+	ret
+; 5529
+
+SpawnShadow: ; 5529
+	push bc
+	ld de, .ShadowObject
+	call CopyTempObjectData
+	call InitTempObject
+	pop bc
+	ret
+
+.ShadowObject:
+	; vtile, palette, movement
+	db $00, PAL_OW_SILVER, SPRITEMOVEDATA_SHADOW
+; 5538
+
+SpawnStrengthBoulderDust: ; 5538
+	push bc
+	ld de, .BoulderDustObject
+	call CopyTempObjectData
+	call InitTempObject
+	pop bc
+	ret
+
+.BoulderDustObject:
+	db $00, PAL_OW_SILVER, SPRITEMOVEDATA_BOULDERDUST
+; 5547
+
+SpawnEmote: ; 5547
+	push bc
+	ld de, .EmoteObject
+	call CopyTempObjectData
+	call InitTempObject
+	pop bc
+	ret
+
+.EmoteObject:
+	db $00, PAL_OW_SILVER, SPRITEMOVEDATA_EMOTE
+; 5556
+
+ShakeGrass: ; 5556
+	push bc
+	ld de, .data_5562
+	call CopyTempObjectData
+	call InitTempObject
+	pop bc
+	ret
+
+.data_5562
+	db $00, PAL_OW_TREE, SPRITEMOVEDATA_GRASS
+; 5565
+
+ShakeScreen: ; 5565
+	push bc
+	push af
+	ld de, .ScreenShakeObject
+	call CopyTempObjectData
+	pop af
+	ld [wTempObjectCopyRange], a
+	call InitTempObject
+	pop bc
+	ret
+
+.ScreenShakeObject:
+	db $00, PAL_OW_SILVER, SPRITEMOVEDATA_SCREENSHAKE
+; 5579
+DespawnEmote: ; 5579
+	push bc
+	ld a, [hMapObjectIndexBuffer]
+	ld c, a
+	call .DeleteEmote
+	pop bc
+	ret
+
+.DeleteEmote:
+	ld de, wObjectStructs
+	ld a, NUM_OBJECT_STRUCTS
+.loop
+	push af
+	ld hl, OBJECT_FLAGS1
+	add hl, de
+	bit EMOTE_OBJECT, [hl]
+	jr z, .next
+	ld hl, OBJECT_SPRITE
+	add hl, de
+	ld a, [hl]
+	and a
+	jr z, .next
+	push bc
+	xor a
+	ld bc, OBJECT_STRUCT_LENGTH
+	call ByteFill
+	pop bc
+.next
+	ld hl, OBJECT_STRUCT_LENGTH
+	add hl, de
+	ld d, h
+	ld e, l
+	pop af
+	dec a
+	jr nz, .loop
+	ret
+; 55ac
+
+InitTempObject: ; 55ac
+	call FindFirstEmptyObjectStruct
+	ret nc
+	ld d, h
+	ld e, l
+	farcall CopyTempObjectToObjectStruct
+	ret
+; 55b9
+
+CopyTempObjectData: ; 55b9
+; load into wTempObjectCopy:
+; -1, -1, [de], [de + 1], [de + 2], [hMapObjectIndexBuffer], [NextMapX], [NextMapY], -1
+; This spawns the object at the same place as whichever object is loaded into bc.
+	ld hl, wTempObjectCopyMapObjectIndex
+	ld [hl], -1
+	inc hl
+	ld [hl], -1
+	inc hl
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	ld [hli], a
+	ld a, [hMapObjectIndexBuffer]
+	ld [hli], a
+	push hl
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	pop hl
+	ld [hl], d
+	inc hl
+	ld [hl], e
+	inc hl
+	ld [hl], -1
+	ret
+; 55e0
+
+Function55e0:: ; 55e0
+	ld a, [wVramState]
+	bit 0, a
+	ret z
+	ld bc, wObjectStructs
+	xor a
+.loop
+	ld [hMapObjectIndexBuffer], a
+	call DoesObjectHaveASprite
+	jr z, .ok
+	call Function565c
+.ok
+	ld hl, OBJECT_STRUCT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	ld a, [hMapObjectIndexBuffer]
+	inc a
+	cp NUM_OBJECT_STRUCTS
+	jr nz, .loop
+	ret
+; 5602
+
+Function5602: ; 5602, called at battle start
+	call Function5645 ; clear sprites
+	ld a, PLAYER
+	call Function5629 ; respawn player
+	ld a, [wBattleScriptFlags]
+	bit 7, a
+	jr z, .ok
+	ld a, [hLastTalked]
+	and a
+	jr z, .ok
+	call Function5629 ; respawn opponent
+.ok
+	call _UpdateSprites
+	ret
+; 561d
+
+Function561d: ; 561d
+	call Function5645 ; clear sprites
+	ld a, PLAYER
+	call Function5629 ; respawn player
+	call _UpdateSprites
+	ret
+; 5629
+
+Function5629: ; 5629
+	cp NUM_OBJECTS
+	ret nc
+	call GetMapObject
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	cp -1
+	ret z
+	cp NUM_OBJECT_STRUCTS
+	ret nc
+	call GetObjectStruct
+	call DoesObjectHaveASprite
+	ret z
+	call Function5673
+	ret
+; 5645
+
+Function5645: ; 5645
+	xor a
+	ld bc, wObjectStructs
+.loop
+	ld [hMapObjectIndexBuffer], a
+	call SetFacing_Standing
+	ld hl, OBJECT_STRUCT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	ld a, [hMapObjectIndexBuffer]
+	inc a
+	cp NUM_OBJECT_STRUCTS
+	jr nz, .loop
+	ret
+; 565c
+
+Function565c: ; 565c
+	push bc
+	call Function56cd
+	pop bc
+	jr c, SetFacing_Standing
+	call Function56a3
+	jr c, SetFacing_Standing
+	call Function5688
+	farcall Function4440
+	xor a
+	ret
+; 5673
+
+Function5673: ; 5673
+	call Function56a3
+	jr c, SetFacing_Standing
+	farcall Function4440 ; no need to farcall
+	xor a
+	ret
+; 5680
+
+SetFacing_Standing: ; 5680
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld [hl], STANDING
+	scf
+	ret
+; 5688
+
+Function5688: ; 5688
+	push bc
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	call GetCoordTile
+	pop bc
+	ld hl, OBJECT_NEXT_TILE
+	add hl, bc
+	ld [hl], a
+	farcall UpdateTallGrassFlags ; no need to farcall
+	ret
+; 56a3
+
+Function56a3: ; 56a3
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	inc d
+	inc e
+	ld a, [wXCoord]
+	cp d
+	jr z, .equal_x
+	jr nc, .nope
+	add MAPOBJECT_SCREEN_WIDTH - 1
+	cp d
+	jr c, .nope
+.equal_x
+	ld a, [wYCoord]
+	cp e
+	jr z, .equal_y
+	jr nc, .nope
+	add MAPOBJECT_SCREEN_HEIGHT - 1
+	cp e
+	jr c, .nope
+.equal_y
+	xor a
+	ret
+
+.nope
+	scf
+	ret
+; 56cd
+
+Function56cd: ; 56cd
+	ld a, [wPlayerBGMapOffsetX]
+	ld d, a
+	ld hl, OBJECT_SPRITE_X_OFFSET
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_SPRITE_X
+	add hl, bc
+	add [hl]
+	add d
+	cp $f0
+	jr nc, .ok1
+	cp $a0
+	jp nc, .nope
+.ok1
+	and %00000111
+	ld d, 2
+	cp 4
+	jr c, .ok2
+	ld d, 3
+.ok2
+	ld a, [hl]
+	srl a
+	srl a
+	srl a
+	cp SCREEN_WIDTH
+	jr c, .ok3
+	sub BG_MAP_WIDTH
+.ok3
+	ld [hUsedSpriteIndex], a
+	ld a, [wPlayerBGMapOffsetY]
+	ld e, a
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_SPRITE_Y
+	add hl, bc
+	add [hl]
+	add e
+	cp $f0
+	jr nc, .ok4
+	cp $90
+	jr nc, .nope
+.ok4
+	and %00000111
+	ld e, 2
+	cp 4
+	jr c, .ok5
+	ld e, 3
+.ok5
+	ld a, [hl]
+	srl a
+	srl a
+	srl a
+	cp SCREEN_HEIGHT
+	jr c, .ok6
+	sub BG_MAP_HEIGHT
+.ok6
+	ld [hUsedSpriteTile], a
+	ld hl, OBJECT_PALETTE
+	add hl, bc
+	bit 7, [hl]
+	jr z, .ok7
+	ld a, d
+	add 2
+	ld d, a
+	ld a, e
+	add 2
+	ld e, a
+.ok7
+	ld a, d
+	ld [hFFBF], a
+.loop
+	ld a, [hFFBF]
+	ld d, a
+	ld a, [hUsedSpriteTile]
+	add e
+	dec a
+	cp SCREEN_HEIGHT
+	jr nc, .ok9
+	ld b, a
+.next
+	ld a, [hUsedSpriteIndex]
+	add d
+	dec a
+	cp SCREEN_WIDTH
+	jr nc, .ok8
+	ld c, a
+	push bc
+	call Coord2Tile
+	pop bc
+; NPCs disappear if standing on tile $60-$7f (or $e0-$ff),
+; since those IDs are for text characters and textbox frames.
+	ld a, [hl]
+	cp FIRST_REGULAR_TEXT_CHAR
+	jr nc, .nope
+.ok8
+	dec d
+	jr nz, .next
+.ok9
+	dec e
+	jr nz, .loop
+	and a
+	ret
+
+.nope
+	scf
+	ret
+; 576a
+
+HandleNPCStep:: ; 576a
+	call .ResetStepVector
+	call .DoStepsForAllObjects
+	ret
+
+.ResetStepVector:
+	xor a
+	ld [wPlayerStepVectorX], a
+	ld [wPlayerStepVectorY], a
+	ld [wPlayerStepFlags], a
+	ld a, -1
+	ld [wPlayerStepDirection], a
+	ret
+
+.DoStepsForAllObjects:
+	ld bc, wObjectStructs
+	xor a
+.loop
+	ld [hMapObjectIndexBuffer], a
+	call DoesObjectHaveASprite
+	jr z, .next
+	call Function437b
+.next
+	ld hl, OBJECT_STRUCT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	ld a, [hMapObjectIndexBuffer]
+	inc a
+	cp NUM_OBJECT_STRUCTS
+	jr nz, .loop
+	ret
+; 579d
+
+RefreshPlayerSprite: ; 579d
+	ld a, movement_step_sleep
+	ld [wPlayerNextMovement], a
+	ld [wPlayerMovement], a
+	xor a
+	ld [wPlayerTurningDirection], a
+	ld [wPlayerObjectStepFrame], a
+	call .TryResetPlayerAction
+	farcall CheckWarpFacingDown
+	call c, SpawnInFacingDown
+	call .SpawnInCustomFacing
+	ret
+; 57bc
+
+.TryResetPlayerAction: ; 57bc
+	ld hl, wPlayerSpriteSetupFlags
+	bit PLAYERSPRITESETUP_RESET_ACTION_F, [hl]
+	jr nz, .ok
+	ret
+
+.ok
+	ld a, OBJECT_ACTION_00
+	ld [wPlayerAction], a
+	ret
+; 57ca
+
+.SpawnInCustomFacing: ; 57ca
+	ld hl, wPlayerSpriteSetupFlags
+	bit PLAYERSPRITESETUP_CUSTOM_FACING_F, [hl]
+	ret z
+	ld a, [wPlayerSpriteSetupFlags]
+	and PLAYERSPRITESETUP_FACING_MASK
+	add a
+	add a
+	jr ContinueSpawnFacing
+; 57d9
+
+SpawnInFacingDown: ; 57d9
+	ld a, 0
+ContinueSpawnFacing: ; 57db
+	ld bc, wPlayerStruct
+	call SetSpriteDirection
+	ret
+; 57e2
+
+_SetPlayerPalette: ; 57e2
+	ld a, d
+	and %10000000
+	ret z
+	ld bc, 0 ; debug?
+	ld hl, OBJECT_FACING
+	add hl, bc
+	ld a, [hl]
+	or d
+	ld [hl], a
+	ld a, d
+	swap a
+	and %00000111
+	ld d, a
+	ld bc, wPlayerStruct
+	ld hl, OBJECT_PALETTE
+	add hl, bc
+	ld a, [hl]
+	and %11111000
+	or d
+	ld [hl], a
+	ret
+; 5803
+
+StartFollow:: ; 5803
+	push bc
+	ld a, b
+	call SetLeaderIfVisible
+	pop bc
+	ret c
+	ld a, c
+	call SetFollowerIfVisible
+	farcall QueueFollowerFirstStep
+	ret
+; 5815
+
+SetLeaderIfVisible: ; 5815
+	call CheckObjectVisibility
+	ret c
+	ld a, [hObjectStructIndexBuffer]
+	ld [wObjectFollow_Leader], a
+	ret
+; 581f
+
+StopFollow:: ; 581f
+	call ResetLeader
+	call ResetFollower
+	ret
+; 5826
+
+ResetLeader: ; 5826
+	ld a, -1
+	ld [wObjectFollow_Leader], a
+	ret
+; 582c
+
+SetFollowerIfVisible: ; 582c
+	push af
+	call ResetFollower
+	pop af
+	call CheckObjectVisibility
+	ret c
+	ld hl, OBJECT_MOVEMENTTYPE
+	add hl, bc
+	ld [hl], SPRITEMOVEDATA_FOLLOWING
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_00
+	ld a, [hObjectStructIndexBuffer]
+	ld [wObjectFollow_Follower], a
+	ret
+; 5847
+
+ResetFollower: ; 5847
+	ld a, [wObjectFollow_Follower]
+	cp -1
+	ret z
+	call GetObjectStruct
+	farcall Function58e3 ; no need to bankswitch
+	ld a, -1
+	ld [wObjectFollow_Follower], a
+	ret
+; 585c
+
+SetFlagsForMovement_1:: ; 585c
+	ld a, c
+	call CheckObjectVisibility
+	ret c
+	push bc
+	call Function587a
+	pop bc
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	res 5, [hl]
+	xor a
+	ret
+; 586e
+
+Function586e: ; 586e
+	call CheckObjectVisibility
+	ret c
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	set 5, [hl]
+	xor a
+	ret
+; 587a
+
+Function587a: ; 587a
+	ld bc, wObjectStructs
+	xor a
+.loop
+	push af
+	call DoesObjectHaveASprite
+	jr z, .next
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	set 5, [hl]
+.next
+	ld hl, OBJECT_STRUCT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	pop af
+	inc a
+	cp NUM_OBJECT_STRUCTS
+	jr nz, .loop
+	ret
+; 5897
+
+_SetFlagsForMovement_2:: ; 5897
+	ld a, [wObjectFollow_Leader]
+	cp -1
+	ret z
+	push bc
+	call GetObjectStruct
+	ld hl, OBJECT_MAP_OBJECT_INDEX
+	add hl, bc
+	ld a, [hl]
+	pop bc
+	cp c
+	ret nz
+	ld a, [wObjectFollow_Follower]
+	cp -1
+	ret z
+	call GetObjectStruct
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	res 5, [hl]
+	ret
+; 58b9
+
+Function58b9:: ; 58b9
+	push bc
+	ld bc, wObjectStructs
+	xor a
+.loop
+	push af
+	call DoesObjectHaveASprite
+	jr z, .next
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	res 5, [hl]
+.next
+	ld hl, OBJECT_STRUCT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	pop af
+	inc a
+	cp NUM_OBJECT_STRUCTS
+	jr nz, .loop
+	pop bc
+	ret
+; 58d8
+
+Function58d8: ; 58d8
+	call CheckObjectVisibility
+	ret c
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	res 5, [hl]
+	ret
+; 58e3
+
+Function58e3: ; 58e3
+	ld hl, OBJECT_MAP_OBJECT_INDEX
+	add hl, bc
+	ld a, [hl]
+	cp -1
+	jp z, Function5903 ; a jr would have been appropriate here
+	push bc
+	call GetMapObject
+	ld hl, MAPOBJECT_MOVEMENT
+	add hl, bc
+	ld a, [hl]
+	pop bc
+	ld hl, OBJECT_MOVEMENTTYPE
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_00
+	ret
+; 5903
+
+Function5903: ; 5903
+	call GetSpriteDirection
+	rrca
+	rrca
+	ld e, a
+	ld d, 0
+	ld hl, .standing_movefns
+	add hl, de
+	ld a, [hl]
+	ld hl, OBJECT_MOVEMENTTYPE
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_00
+	ret
+
+.standing_movefns
+	db SPRITEMOVEDATA_STANDING_DOWN
+	db SPRITEMOVEDATA_STANDING_UP
+	db SPRITEMOVEDATA_STANDING_LEFT
+	db SPRITEMOVEDATA_STANDING_RIGHT
+; 5920
+
+_UpdateSprites:: ; 5920
+	ld a, [wVramState]
+	bit 0, a
+	ret z
+	xor a
+	ld [hUsedSpriteIndex], a
+	ld a, [hOAMUpdate]
+	push af
+	ld a, 1
+	ld [hOAMUpdate], a
+	call InitSprites
+	call .fill
+	pop af
+	ld [hOAMUpdate], a
+	ret
+
+.fill
+	ld a, [wVramState]
+	bit 1, a
+	ld b, LOW(wVirtualOAMEnd)
+	jr z, .ok
+	ld b, 28 * SPRITEOAMSTRUCT_LENGTH
+.ok
+	ld a, [hUsedSpriteIndex]
+	cp b
+	ret nc
+	ld l, a
+	ld h, HIGH(wVirtualOAM)
+	ld de, SPRITEOAMSTRUCT_LENGTH
+	ld a, b
+	ld c, SCREEN_HEIGHT_PX + 2 * TILE_WIDTH
+.loop
+	ld [hl], c ; y
+	add hl, de
+	cp l
+	jr nz, .loop
+	ret
+; 5958
+
+ApplyBGMapAnchorToObjects: ; 5958
+	push hl
+	push de
+	push bc
+	ld a, [wPlayerBGMapOffsetX]
+	ld d, a
+	ld a, [wPlayerBGMapOffsetY]
+	ld e, a
+	ld bc, wObjectStructs
+	ld a, NUM_OBJECT_STRUCTS
+.loop
+	push af
+	call DoesObjectHaveASprite
+	jr z, .skip
+	ld hl, OBJECT_SPRITE_X
+	add hl, bc
+	ld a, [hl]
+	add d
+	ld [hl], a
+	ld hl, OBJECT_SPRITE_Y
+	add hl, bc
+	ld a, [hl]
+	add e
+	ld [hl], a
+.skip
+	ld hl, OBJECT_STRUCT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	pop af
+	dec a
+	jr nz, .loop
+	xor a
+	ld [wPlayerBGMapOffsetX], a
+	ld [wPlayerBGMapOffsetY], a
+	pop bc
+	pop de
+	pop hl
+	ret
+; 5991
+
+
+PRIORITY_LOW  EQU $10
+PRIORITY_NORM EQU $20
+PRIORITY_HIGH EQU $30
+
+InitSprites: ; 5991
+	call .DeterminePriorities
+	ld c, PRIORITY_HIGH
+	call .InitSpritesByPriority
+	ld c, PRIORITY_NORM
+	call .InitSpritesByPriority
+	ld c, PRIORITY_LOW
+	call .InitSpritesByPriority
+	ret
+
+.DeterminePriorities:
+	xor a
+	ld hl, wMovementPointer
+	ld bc, NUM_OBJECT_STRUCTS
+	call ByteFill
+	ld d, 0
+	ld bc, wObjectStructs
+	ld hl, wMovementPointer
+.loop
+	push hl
+	call DoesObjectHaveASprite
+	jr z, .skip
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld a, [hl]
+	cp STANDING
+	jr z, .skip
+; Define the sprite priority.
+	ld e, PRIORITY_LOW
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	bit LOW_PRIORITY, [hl]
+	jr nz, .add
+	ld e, PRIORITY_NORM
+	bit HIGH_PRIORITY, [hl]
+	jr z, .add
+	ld e, PRIORITY_HIGH
+	jr .add
+
+.skip
+	ld hl, OBJECT_STRUCT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	pop hl
+	jr .next
+
+.add
+	ld hl, OBJECT_STRUCT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	pop hl
+	ld a, d
+	or e
+	ld [hli], a
+.next
+	inc d
+	ld a, d
+	cp NUM_OBJECT_STRUCTS
+	jr nz, .loop
+	ret
+
+.InitSpritesByPriority:
+	ld hl, wMovementPointer
+.next_sprite
+	ld a, [hli]
+	ld d, a
+	and $f0
+	ret z
+	cp c
+	jr nz, .next_sprite
+	push bc
+	push hl
+	ld a, d
+	and $f
+	call .GetObjectStructPointer
+	call .InitSprite
+	pop hl
+	pop bc
+	jr .next_sprite
+
+.InitSprite:
+	ld hl, OBJECT_SPRITE_TILE
+	add hl, bc
+	ld a, [hl]
+	and %01111111
+	ld [hFFC1], a
+	xor a
+	bit 7, [hl]
+	jr nz, .skip1
+	or %00001000
+.skip1
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	ld e, [hl]
+	bit 7, e
+	jr z, .skip2
+	or %10000000
+.skip2
+	bit 4, e
+	jr z, .skip3
+	or %00010000
+.skip3
+	ld hl, OBJECT_PALETTE
+	add hl, bc
+	ld d, a
+	ld a, [hl]
+	and %00000111
+	or d
+	ld d, a
+	xor a
+	bit 3, e
+	jr z, .skip4
+	or %10000000
+.skip4
+	ld [hFFC2], a
+	ld hl, OBJECT_SPRITE_X
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_SPRITE_X_OFFSET
+	add hl, bc
+	add [hl]
+	add 8
+	ld e, a
+	ld a, [wPlayerBGMapOffsetX]
+	add e
+	ld [hFFBF], a
+	ld hl, OBJECT_SPRITE_Y
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_SPRITE_Y_OFFSET
+	add hl, bc
+	add [hl]
+	add 12
+	ld e, a
+	ld a, [wPlayerBGMapOffsetY]
+	add e
+	ld [hFFC0], a
+	ld hl, OBJECT_FACING_STEP
+	add hl, bc
+	ld a, [hl]
+	cp STANDING
+	jp z, .done
+	cp NUM_FACINGS
+	jp nc, .done
+	ld l, a
+	ld h, 0
+	add hl, hl
+	ld bc, Facings
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [hUsedSpriteIndex]
+	ld c, a
+	ld b, HIGH(wVirtualOAM)
+	ld a, [hli]
+	ld [hUsedSpriteTile], a
+	add c
+	cp LOW(wVirtualOAMEnd)
+	jr nc, .full
+.addsprite
+	ld a, [hFFC0]
+	add [hl]
+	inc hl
+	ld [bc], a ; y
+	inc c
+	ld a, [hFFBF]
+	add [hl]
+	inc hl
+	ld [bc], a ; x
+	inc c
+	ld e, [hl]
+	inc hl
+	ld a, [hFFC1]
+	bit 2, e
+	jr z, .nope1
+	xor a
+.nope1
+	add [hl]
+	inc hl
+	ld [bc], a ; tile id
+	inc c
+	ld a, e
+	bit 1, a
+	jr z, .nope2
+	ld a, [hFFC2]
+	or e
+.nope2
+	and OBP_NUM | X_FLIP | Y_FLIP | PRIORITY
+	or d
+	ld [bc], a ; attributes
+	inc c
+	ld a, [hUsedSpriteTile]
+	dec a
+	ld [hUsedSpriteTile], a
+	jr nz, .addsprite
+	ld a, c
+	ld [hUsedSpriteIndex], a
+.done
+	xor a
+	ret
+
+.full
+	scf
+	ret
+
+.GetObjectStructPointer:
+	ld c, a
+	ld b, 0
+	ld hl, .Addresses
+	add hl, bc
+	add hl, bc
+	ld c, [hl]
+	inc hl
+	ld b, [hl]
+	ret
+
+.Addresses: ; 5ace
+	dw wPlayerStruct
+	dw wObject1Struct
+	dw wObject2Struct
+	dw wObject3Struct
+	dw wObject4Struct
+	dw wObject5Struct
+	dw wObject6Struct
+	dw wObject7Struct
+	dw wObject8Struct
+	dw wObject9Struct
+	dw wObject10Struct
+	dw wObject11Struct
+	dw wObject12Struct
+; 5ae8
--- /dev/null
+++ b/engine/overworld/map_objects_2.asm
@@ -1,0 +1,70 @@
+LoadObjectMasks: ; 2454f
+	ld hl, wObjectMasks
+	xor a
+	ld bc, NUM_OBJECTS
+	call ByteFill
+	nop
+	ld bc, wMapObjects
+	ld de, wObjectMasks
+	xor a
+.loop
+	push af
+	push bc
+	push de
+	call GetObjectTimeMask
+	jr c, .next
+	call CheckObjectFlag
+.next
+	pop de
+	ld [de], a
+	inc de
+	pop bc
+	ld hl, OBJECT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	pop af
+	inc a
+	cp NUM_OBJECTS
+	jr nz, .loop
+	ret
+
+CheckObjectFlag: ; 2457d (9:457d)
+	ld hl, MAPOBJECT_SPRITE
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .masked
+	ld hl, MAPOBJECT_EVENT_FLAG
+	add hl, bc
+	ld a, [hli]
+	ld e, a
+	ld a, [hl]
+	ld d, a
+	cp -1
+	jr nz, .check
+	ld a, e
+	cp -1
+	jr z, .unmasked
+	jr .masked
+.check
+	ld b, CHECK_FLAG
+	call EventFlagAction
+	ld a, c
+	and a
+	jr nz, .masked
+.unmasked
+	xor a
+	ret
+
+.masked
+	ld a, -1
+	scf
+	ret
+
+GetObjectTimeMask: ; 245a7 (9:45a7)
+	call CheckObjectTime
+	ld a, -1
+	ret c
+	xor a
+	ret
--- /dev/null
+++ b/engine/overworld/map_setup.asm
@@ -1,0 +1,260 @@
+RunMapSetupScript:: ; 15363
+	ld a, [hMapEntryMethod]
+	and $f
+	dec a
+	ld c, a
+	ld b, 0
+	ld hl, MapSetupScripts
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	call ReadMapSetupScript
+	ret
+; 15377
+
+INCLUDE "data/maps/setup_scripts.asm"
+
+ReadMapSetupScript: ; 1541d
+.loop
+	ld a, [hli]
+	cp -1
+	ret z
+
+	push hl
+
+	ld c, a
+	ld b, 0
+	ld hl, MapSetupCommands
+	add hl, bc
+	add hl, bc
+	add hl, bc
+
+	; bank
+	ld b, [hl]
+	inc hl
+
+	; address
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+
+	; Bit 7 of the bank indicates a parameter.
+	; This is left unused.
+	bit 7, b
+	jr z, .go
+
+	pop de
+	ld a, [de]
+	ld c, a
+	inc de
+	push de
+
+.go
+	ld a, b
+	and $7f
+	rst FarCall
+
+	pop hl
+	jr .loop
+; 15440
+
+MapSetupCommands: ; 15440
+; entries correspond to command indexes in constants/map_setup_constants.asm
+	dba EnableLCD ; 00
+	dba DisableLCD ; 01
+	dba MapSetup_Sound_Off ; 02
+	dba PlayMapMusic ; 03
+	dba RestartMapMusic ; 04
+	dba FadeToMapMusic ; 05
+	dba RotatePalettesRightMapAndMusic ; 06
+	dba EnterMapMusic ; 07
+	dba ForceMapMusic ; 08
+	dba FadeInMusic ; 09
+	dba LoadBlockData ; 0a (callback 1)
+	dba LoadNeighboringBlockData ; 0b
+	dba SaveScreen ; 0c
+	dba BufferScreen ; 0d
+	dba LoadGraphics ; 0e
+	dba LoadTileset ; 0f
+	dba LoadMapTimeOfDay ; 10
+	dba LoadMapPalettes ; 11
+	dba LoadWildMonData ; 12
+	dba RefreshMapSprites ; 13
+	dba HandleNewMap ; 14
+	dba InitCommandQueue ; 15
+	dba LoadObjectsRunCallback_02 ; 16
+	dba LoadSpawnPoint ; 17
+	dba EnterMapConnection ; 18
+	dba LoadWarpData ; 19
+	dba LoadMapAttributes ; 1a
+	dba LoadMapAttributes_SkipPeople ; 1b
+	dba ClearBGPalettes ; 1c
+	dba FadeOutPalettes ; 1d
+	dba FadeInPalettes ; 1e
+	dba GetCoordOfUpperLeftCorner ; 1f
+	dba RestoreFacingAfterWarp ; 20
+	dba SpawnInFacingDown ; 21
+	dba SpawnPlayer ; 22
+	dba RefreshPlayerCoords ; 23
+	dba DelayClearingOldSprites ; 24
+	dba DelayLoadingNewSprites ; 25
+	dba UpdateRoamMons ; 26
+	dba JumpRoamMons ; 27
+	dba FadeOldMapMusic ; 28
+	dba ActivateMapAnims ; 29
+	dba SuspendMapAnims ; 2a
+	dba RetainOldPalettes ; 2b
+	dba DontScrollText ; 2c
+	dba ReturnFromMapSetupScript ; 2d
+; 154ca
+
+
+DontScrollText: ; 154ca
+	xor a
+	ld [wDisableTextAcceleration], a
+	ret
+; 154cf
+
+ActivateMapAnims: ; 154cf
+	ld a, $1
+	ld [hMapAnims], a
+	ret
+; 154d3
+
+SuspendMapAnims: ; 154d3
+	xor a
+	ld [hMapAnims], a
+	ret
+; 154d7
+
+LoadObjectsRunCallback_02: ; 154d7
+	ld a, MAPCALLBACK_OBJECTS
+	call RunMapCallback
+	farcall LoadObjectMasks
+	farcall InitializeVisibleSprites
+	ret
+; 154ea (5:54ea)
+
+; unused
+	ret
+; 154eb
+
+DelayClearingOldSprites: ; 154eb
+	ld hl, wPlayerSpriteSetupFlags
+	set PLAYERSPRITESETUP_RESET_ACTION_F, [hl]
+	ret
+; 154f1
+
+DelayLoadingNewSprites: ; 154f1
+	ld hl, wPlayerSpriteSetupFlags
+	set PLAYERSPRITESETUP_SKIP_RELOAD_GFX_F, [hl]
+	ret
+
+CheckReplaceKrisSprite: ; 154f7
+	nop
+	call .CheckBiking
+	jr c, .ok
+	call .CheckSurfing
+	jr c, .ok
+	call .CheckSurfing2
+	jr c, .ok
+	ret
+
+.ok
+	call ReplaceKrisSprite
+	ret
+
+.CheckBiking: ; 1550c (5:550c)
+	and a
+	ld hl, wBikeFlags
+	bit BIKEFLAGS_ALWAYS_ON_BIKE_F, [hl]
+	ret z
+	ld a, PLAYER_BIKE
+	ld [wPlayerState], a
+	scf
+	ret
+
+.CheckSurfing2: ; 1551a (5:551a)
+	ld a, [wPlayerState]
+	cp PLAYER_NORMAL
+	jr z, .nope
+	cp PLAYER_SKATE
+	jr z, .nope
+	cp PLAYER_SURF
+	jr z, .surfing
+	cp PLAYER_SURF_PIKA
+	jr z, .surfing
+	call GetMapEnvironment
+	cp INDOOR
+	jr z, .checkbiking
+	cp ENVIRONMENT_5
+	jr z, .checkbiking
+	cp DUNGEON
+	jr z, .checkbiking
+	jr .nope
+.checkbiking
+	ld a, [wPlayerState]
+	cp PLAYER_BIKE
+	jr nz, .nope
+.surfing
+	ld a, PLAYER_NORMAL
+	ld [wPlayerState], a
+	scf
+	ret
+
+.nope
+	and a
+	ret
+
+.CheckSurfing: ; 1554e (5:554e)
+	call CheckOnWater
+	jr nz, .ret_nc
+	ld a, [wPlayerState]
+	cp PLAYER_SURF
+	jr z, ._surfing
+	cp PLAYER_SURF_PIKA
+	jr z, ._surfing
+	ld a, PLAYER_SURF
+	ld [wPlayerState], a
+._surfing
+	scf
+	ret
+.ret_nc
+	and a
+	ret
+; 15567
+
+FadeOldMapMusic: ; 15567
+	ld a, 6
+	call SkipMusic
+	ret
+; 1556d
+
+RetainOldPalettes: ; 1556d
+	farcall _UpdateTimePals
+	ret
+
+RotatePalettesRightMapAndMusic: ; 15574
+	ld e, 0
+	ld a, [wMusicFadeID]
+	ld d, 0
+	ld a, [wMusicFadeID + 1]
+	ld a, $4
+	ld [wMusicFade], a
+	call RotateThreePalettesRight
+	ret
+; 15587
+
+ForceMapMusic: ; 15587
+	ld a, [wPlayerState]
+	cp PLAYER_BIKE
+	jr nz, .notbiking
+	call VolumeOff
+	ld a, $88
+	ld [wMusicFade], a
+.notbiking
+	call TryRestartMapMusic
+	ret
+; 1559a
--- /dev/null
+++ b/engine/overworld/movement.asm
@@ -1,0 +1,864 @@
+MovementPointers: ; 5075
+; entries correspond to macros/scripts/movement.asm enumeration
+	dw Movement_turn_head_down        ; 00
+	dw Movement_turn_head_up          ; 01
+	dw Movement_turn_head_left        ; 02
+	dw Movement_turn_head_right       ; 03
+	dw Movement_turn_step_down        ; 04
+	dw Movement_turn_step_up          ; 05
+	dw Movement_turn_step_left        ; 06
+	dw Movement_turn_step_right       ; 07
+	dw Movement_slow_step_down        ; 08
+	dw Movement_slow_step_up          ; 09
+	dw Movement_slow_step_left        ; 0a
+	dw Movement_slow_step_right       ; 0b
+	dw Movement_step_down             ; 0c
+	dw Movement_step_up               ; 0d
+	dw Movement_step_left             ; 0e
+	dw Movement_step_right            ; 0f
+	dw Movement_big_step_down         ; 10
+	dw Movement_big_step_up           ; 11
+	dw Movement_big_step_left         ; 12
+	dw Movement_big_step_right        ; 13
+	dw Movement_slow_slide_step_down  ; 14
+	dw Movement_slow_slide_step_up    ; 15
+	dw Movement_slow_slide_step_left  ; 16
+	dw Movement_slow_slide_step_right ; 17
+	dw Movement_slide_step_down       ; 18
+	dw Movement_slide_step_up         ; 19
+	dw Movement_slide_step_left       ; 1a
+	dw Movement_slide_step_right      ; 1b
+	dw Movement_fast_slide_step_down  ; 1c
+	dw Movement_fast_slide_step_up    ; 1d
+	dw Movement_fast_slide_step_left  ; 1e
+	dw Movement_fast_slide_step_right ; 1f
+	dw Movement_turn_away_down        ; 20
+	dw Movement_turn_away_up          ; 21
+	dw Movement_turn_away_left        ; 22
+	dw Movement_turn_away_right       ; 23
+	dw Movement_turn_in_down          ; 24
+	dw Movement_turn_in_up            ; 25
+	dw Movement_turn_in_left          ; 26
+	dw Movement_turn_in_right         ; 27
+	dw Movement_turn_waterfall_down   ; 28
+	dw Movement_turn_waterfall_up     ; 29
+	dw Movement_turn_waterfall_left   ; 2a
+	dw Movement_turn_waterfall_right  ; 2b
+	dw Movement_slow_jump_step_down   ; 2c
+	dw Movement_slow_jump_step_up     ; 2d
+	dw Movement_slow_jump_step_left   ; 2e
+	dw Movement_slow_jump_step_right  ; 2f
+	dw Movement_jump_step_down        ; 30
+	dw Movement_jump_step_up          ; 31
+	dw Movement_jump_step_left        ; 32
+	dw Movement_jump_step_right       ; 33
+	dw Movement_fast_jump_step_down   ; 34
+	dw Movement_fast_jump_step_up     ; 35
+	dw Movement_fast_jump_step_left   ; 36
+	dw Movement_fast_jump_step_right  ; 37
+	dw Movement_remove_sliding        ; 38
+	dw Movement_set_sliding           ; 39
+	dw Movement_remove_fixed_facing   ; 3a
+	dw Movement_fix_facing            ; 3b
+	dw Movement_show_object           ; 3c
+	dw Movement_hide_object           ; 3d
+	dw Movement_step_sleep_1          ; 3e
+	dw Movement_step_sleep_2          ; 3f
+	dw Movement_step_sleep_3          ; 40
+	dw Movement_step_sleep_4          ; 41
+	dw Movement_step_sleep_5          ; 42
+	dw Movement_step_sleep_6          ; 43
+	dw Movement_step_sleep_7          ; 44
+	dw Movement_step_sleep_8          ; 45
+	dw Movement_step_sleep            ; 46
+	dw Movement_step_end              ; 47
+	dw Movement_48                    ; 48
+	dw Movement_remove_object         ; 49
+	dw Movement_step_loop             ; 4a
+	dw Movement_4b                    ; 4b
+	dw Movement_teleport_from         ; 4c
+	dw Movement_teleport_to           ; 4d
+	dw Movement_skyfall               ; 4e
+	dw Movement_step_dig              ; 4f
+	dw Movement_step_bump             ; 50
+	dw Movement_fish_got_bite         ; 51
+	dw Movement_fish_cast_rod         ; 52
+	dw Movement_hide_emote            ; 53
+	dw Movement_show_emote            ; 54
+	dw Movement_step_shake            ; 55
+	dw Movement_tree_shake            ; 56
+	dw Movement_rock_smash            ; 57
+	dw Movement_return_dig            ; 58
+	dw Movement_skyfall_top           ; 59
+; 5129
+
+
+Movement_teleport_from: ; 5129
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_TELEPORT_FROM
+	ret
+; 5130
+
+Movement_teleport_to: ; 5130
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_TELEPORT_TO
+	ret
+; 5137
+
+Movement_skyfall: ; 5137
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SKYFALL
+	ret
+; 513e
+
+Movement_skyfall_top: ; 513e
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SKYFALL_TOP
+	ret
+; 5145
+
+Movement_step_dig: ; 5145
+	call GetSpriteDirection
+	rlca
+	rlca
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_SPIN
+	call JumpMovementPointer
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_03
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ret
+; 516a
+
+Movement_return_dig: ; 516a
+	call GetSpriteDirection
+	rlca
+	rlca
+	ld hl, OBJECT_STEP_FRAME
+	add hl, bc
+	ld [hl], a
+	call JumpMovementPointer
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_RETURN_DIG
+	ret
+; 5189
+
+Movement_fish_got_bite: ; 5189
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_FISHING
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_GOT_BITE
+	ret
+; 5196
+
+Movement_rock_smash: ; 5196
+	call JumpMovementPointer
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STAND
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_ROCK_SMASH
+	ret
+; 51ab
+
+Movement_fish_cast_rod: ; 51ab
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_FISHING
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 51b8
+
+Movement_step_loop: ; 51b8
+	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+	add hl, bc
+	ld [hl], $0
+	jp ContinueReadingMovement
+; 51c1
+
+Movement_step_end: ; 51c1
+	call RestoreDefaultMovement
+	ld hl, OBJECT_MOVEMENTTYPE
+	add hl, bc
+	ld [hl], a
+
+	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+	add hl, bc
+	ld [hl], $0
+
+	ld hl, wVramState
+	res 7, [hl]
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_SLEEP
+	ret
+; 51db
+
+Movement_48: ; 51db
+	call RestoreDefaultMovement
+	ld hl, OBJECT_MOVEMENTTYPE
+	add hl, bc
+	ld [hl], a
+
+	ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+	add hl, bc
+	ld [hl], $0
+
+	call JumpMovementPointer
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_03
+
+	ld hl, wVramState
+	res 7, [hl]
+	ret
+; 51fd
+
+Movement_remove_object: ; 51fd
+	call DeleteMapObject
+	ld hl, wObjectFollow_Leader
+	ld a, [hMapObjectIndexBuffer]
+	cp [hl]
+	jr nz, .not_leading
+	ld [hl], -1
+
+.not_leading
+	ld hl, wVramState
+	res 7, [hl]
+	ret
+; 5210
+
+Movement_4b: ; 5210
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STAND
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_04
+
+	ld hl, wVramState
+	res 7, [hl]
+	ret
+; 5222
+
+Movement_step_sleep_1: ; 5222
+	ld a, 1
+	jr Movement_step_sleep_common
+
+Movement_step_sleep_2: ; 5226
+	ld a, 2
+	jr Movement_step_sleep_common
+
+Movement_step_sleep_3: ; 522a
+	ld a, 3
+	jr Movement_step_sleep_common
+
+Movement_step_sleep_4: ; 522e
+	ld a, 4
+	jr Movement_step_sleep_common
+
+Movement_step_sleep_5: ; 5232
+	ld a, 5
+	jr Movement_step_sleep_common
+
+Movement_step_sleep_6: ; 5236
+	ld a, 6
+	jr Movement_step_sleep_common
+
+Movement_step_sleep_7: ; 523a
+	ld a, 7
+	jr Movement_step_sleep_common
+
+Movement_step_sleep_8: ; 523e
+	ld a, 8
+	jr Movement_step_sleep_common
+
+Movement_step_sleep: ; 5242
+; parameters:
+;	duration (DecimalParam)
+
+	call JumpMovementPointer
+	jr Movement_step_sleep_common
+
+Movement_step_sleep_common: ; 5247
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_03
+
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STAND
+
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ret
+; 525f
+
+Movement_step_bump: ; 525f
+	ld a, 1
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_BUMP
+
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_BUMP
+
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ret
+; 5279
+
+Movement_tree_shake: ; 5279
+	ld a, 24
+	ld hl, OBJECT_STEP_DURATION
+	add hl, bc
+	ld [hl], a
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_03
+
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_WEIRD_TREE
+
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ret
+; 5293
+
+Movement_remove_sliding: ; 5293
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	res SLIDING, [hl]
+	jp ContinueReadingMovement
+; 529c
+
+Movement_set_sliding: ; 529c
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	set SLIDING, [hl]
+	jp ContinueReadingMovement
+; 52a5
+
+Movement_remove_fixed_facing: ; 52a5
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	res FIXED_FACING, [hl]
+	jp ContinueReadingMovement
+; 52ae
+
+Movement_fix_facing: ; 52ae
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	set FIXED_FACING, [hl]
+	jp ContinueReadingMovement
+; 52b7
+
+Movement_show_object: ; 52b7
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	res INVISIBLE, [hl]
+	jp ContinueReadingMovement
+; 52c0
+
+Movement_hide_object: ; 52c0
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	set INVISIBLE, [hl]
+	jp ContinueReadingMovement
+; 52c9
+
+Movement_hide_emote: ; 52c9
+	call DespawnEmote
+	jp ContinueReadingMovement
+; 52cf
+
+Movement_show_emote: ; 52cf
+	call SpawnEmote
+	jp ContinueReadingMovement
+; 52d5
+
+Movement_step_shake: ; 52d5
+; parameters:
+;	displacement (DecimalParam)
+
+	call JumpMovementPointer
+	call ShakeScreen
+	jp ContinueReadingMovement
+; 52de
+
+Movement_turn_head_down: ; 52de
+	ld a, OW_DOWN
+	jr TurnHead
+
+Movement_turn_head_up: ; 52e2
+	ld a, OW_UP
+	jr TurnHead
+
+Movement_turn_head_left: ; 52e6
+	ld a, OW_LEFT
+	jr TurnHead
+
+Movement_turn_head_right: ; 52ea
+	ld a, OW_RIGHT
+	jr TurnHead
+
+TurnHead: ; 52ee
+	ld hl, OBJECT_FACING
+	add hl, bc
+	ld [hl], a
+
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STAND
+
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld [hl], STANDING
+	ret
+; 5300
+
+Movement_slow_step_down: ; 5300
+	ld a, STEP_SLOW << 2 | DOWN
+	jp NormalStep
+; 5305
+
+Movement_slow_step_up: ; 5305
+	ld a, STEP_SLOW << 2 | UP
+	jp NormalStep
+; 530a
+
+Movement_slow_step_left: ; 530a
+	ld a, STEP_SLOW << 2 | LEFT
+	jp NormalStep
+; 530f
+
+Movement_slow_step_right: ; 530f
+	ld a, STEP_SLOW << 2 | RIGHT
+	jp NormalStep
+; 5314
+
+Movement_step_down: ; 5314
+	ld a, STEP_WALK << 2 | DOWN
+	jp NormalStep
+; 5319
+
+Movement_step_up: ; 5319
+	ld a, STEP_WALK << 2 | UP
+	jp NormalStep
+; 531e
+
+Movement_step_left: ; 531e
+	ld a, STEP_WALK << 2 | LEFT
+	jp NormalStep
+; 5323
+
+Movement_step_right: ; 5323
+	ld a, STEP_WALK << 2 | RIGHT
+	jp NormalStep
+; 5328
+
+Movement_big_step_down: ; 5328
+	ld a, STEP_BIKE << 2 | DOWN
+	jp NormalStep
+; 532d
+
+Movement_big_step_up: ; 532d
+	ld a, STEP_BIKE << 2 | UP
+	jp NormalStep
+; 5332
+
+Movement_big_step_left: ; 5332
+	ld a, STEP_BIKE << 2 | LEFT
+	jp NormalStep
+; 5337
+
+Movement_big_step_right: ; 5337
+	ld a, STEP_BIKE << 2 | RIGHT
+	jp NormalStep
+; 533c
+
+
+Movement_turn_away_down: ; 533c
+	ld a, STEP_SLOW << 2 | DOWN
+	jp TurningStep
+; 5341
+
+Movement_turn_away_up: ; 5341
+	ld a, STEP_SLOW << 2 | UP
+	jp TurningStep
+; 5346
+
+Movement_turn_away_left: ; 5346
+	ld a, STEP_SLOW << 2 | LEFT
+	jp TurningStep
+; 534b
+
+Movement_turn_away_right: ; 534b
+	ld a, STEP_SLOW << 2 | RIGHT
+	jp TurningStep
+; 5350
+
+Movement_turn_in_down: ; 5350
+	ld a, STEP_WALK << 2 | DOWN
+	jp TurningStep
+; 5355
+
+Movement_turn_in_up: ; 5355
+	ld a, STEP_WALK << 2 | UP
+	jp TurningStep
+; 535a
+
+Movement_turn_in_left: ; 535a
+	ld a, STEP_WALK << 2 | LEFT
+	jp TurningStep
+; 535f
+
+Movement_turn_in_right: ; 535f
+	ld a, STEP_WALK << 2 | RIGHT
+	jp TurningStep
+; 5364
+
+Movement_turn_waterfall_down: ; 5364
+	ld a, STEP_BIKE << 2 | DOWN
+	jp TurningStep
+; 5369
+
+Movement_turn_waterfall_up: ; 5369
+	ld a, STEP_BIKE << 2 | UP
+	jp TurningStep
+; 536e
+
+Movement_turn_waterfall_left: ; 536e
+	ld a, STEP_BIKE << 2 | LEFT
+	jp TurningStep
+; 5373
+
+Movement_turn_waterfall_right: ; 5373
+	ld a, STEP_BIKE << 2 | RIGHT
+	jp TurningStep
+; 5378
+
+
+Movement_slow_slide_step_down: ; 5378
+	ld a, STEP_SLOW << 2 | DOWN
+	jp SlideStep
+; 537d
+
+Movement_slow_slide_step_up: ; 537d
+	ld a, STEP_SLOW << 2 | UP
+	jp SlideStep
+; 5382
+
+Movement_slow_slide_step_left: ; 5382
+	ld a, STEP_SLOW << 2 | LEFT
+	jp SlideStep
+; 5387
+
+Movement_slow_slide_step_right: ; 5387
+	ld a, STEP_SLOW << 2 | RIGHT
+	jp SlideStep
+; 538c
+
+Movement_slide_step_down: ; 538c
+	ld a, STEP_WALK << 2 | DOWN
+	jp SlideStep
+; 5391
+
+Movement_slide_step_up: ; 5391
+	ld a, STEP_WALK << 2 | UP
+	jp SlideStep
+; 5396
+
+Movement_slide_step_left: ; 5396
+	ld a, STEP_WALK << 2 | LEFT
+	jp SlideStep
+; 539b
+
+Movement_slide_step_right: ; 539b
+	ld a, STEP_WALK << 2 | RIGHT
+	jp SlideStep
+; 53a0
+
+Movement_fast_slide_step_down: ; 53a0
+	ld a, STEP_BIKE << 2 | DOWN
+	jp SlideStep
+; 53a5
+
+Movement_fast_slide_step_up: ; 53a5
+	ld a, STEP_BIKE << 2 | UP
+	jp SlideStep
+; 53aa
+
+Movement_fast_slide_step_left: ; 53aa
+	ld a, STEP_BIKE << 2 | LEFT
+	jp SlideStep
+; 53af
+
+Movement_fast_slide_step_right: ; 53af
+	ld a, STEP_BIKE << 2 | RIGHT
+	jp SlideStep
+; 53b4
+
+
+Movement_slow_jump_step_down: ; 53b4
+	ld a, STEP_SLOW << 2 | DOWN
+	jp JumpStep
+; 53b9
+
+Movement_slow_jump_step_up: ; 53b9
+	ld a, STEP_SLOW << 2 | UP
+	jp JumpStep
+; 53be
+
+Movement_slow_jump_step_left: ; 53be
+	ld a, STEP_SLOW << 2 | LEFT
+	jp JumpStep
+; 53c3
+
+Movement_slow_jump_step_right: ; 53c3
+	ld a, STEP_SLOW << 2 | RIGHT
+	jp JumpStep
+; 53c8
+
+Movement_jump_step_down: ; 53c8
+	ld a, STEP_WALK << 2 | DOWN
+	jp JumpStep
+; 53cd
+
+Movement_jump_step_up: ; 53cd
+	ld a, STEP_WALK << 2 | UP
+	jp JumpStep
+; 53d2
+
+Movement_jump_step_left: ; 53d2
+	ld a, STEP_WALK << 2 | LEFT
+	jp JumpStep
+; 53d7
+
+Movement_jump_step_right: ; 53d7
+	ld a, STEP_WALK << 2 | RIGHT
+	jp JumpStep
+; 53dc
+
+Movement_fast_jump_step_down: ; 53dc
+	ld a, STEP_BIKE << 2 | DOWN
+	jp JumpStep
+; 53e1
+
+Movement_fast_jump_step_up: ; 53e1
+	ld a, STEP_BIKE << 2 | UP
+	jp JumpStep
+; 53e6
+
+Movement_fast_jump_step_left: ; 53e6
+	ld a, STEP_BIKE << 2 | LEFT
+	jp JumpStep
+; 53eb
+
+Movement_fast_jump_step_right: ; 53eb
+	ld a, STEP_BIKE << 2 | RIGHT
+	jp JumpStep
+; 53f0
+
+
+Movement_turn_step_down: ; 53f0
+	ld a, OW_DOWN
+	jr TurnStep
+
+Movement_turn_step_up: ; 53f4
+	ld a, OW_UP
+	jr TurnStep
+
+Movement_turn_step_left: ; 53f8
+	ld a, OW_LEFT
+	jr TurnStep
+
+Movement_turn_step_right: ; 53fc
+	ld a, OW_RIGHT
+	jr TurnStep
+
+TurnStep: ; 5400
+	ld hl, OBJECT_1D ; new facing
+	add hl, bc
+	ld [hl], a
+
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STEP
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_HALF_STEP
+	ret
+; 5412
+
+NormalStep: ; 5412
+	call InitStep
+	call UpdateTallGrassFlags
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STEP
+
+	ld hl, OBJECT_NEXT_TILE
+	add hl, bc
+	ld a, [hl]
+	call CheckSuperTallGrassTile
+	jr z, .shake_grass
+
+	call CheckGrassTile
+	jr c, .skip_grass
+
+.shake_grass
+	call ShakeGrass
+
+.skip_grass
+	ld hl, wCenteredObject
+	ld a, [hMapObjectIndexBuffer]
+	cp [hl]
+	jr z, .player
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_NPC_WALK
+	ret
+
+.player
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_PLAYER_WALK
+	ret
+; 5446
+
+TurningStep: ; 5446
+	call InitStep
+	call UpdateTallGrassFlags
+
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_SPIN
+
+	ld hl, wCenteredObject
+	ld a, [hMapObjectIndexBuffer]
+	cp [hl]
+	jr z, .player
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_NPC_WALK
+	ret
+
+.player
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_PLAYER_WALK
+	ret
+; 5468
+
+
+SlideStep: ; 5468
+	call InitStep
+	call UpdateTallGrassFlags
+
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STAND
+
+	ld hl, wCenteredObject
+	ld a, [hMapObjectIndexBuffer]
+	cp [hl]
+	jr z, .player
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_NPC_WALK
+	ret
+
+.player
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_PLAYER_WALK
+	ret
+; 548a
+
+
+JumpStep: ; 548a
+	call InitStep
+	ld hl, OBJECT_1F
+	add hl, bc
+	ld [hl], $0
+
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	res OVERHEAD, [hl]
+
+	ld hl, OBJECT_ACTION
+	add hl, bc
+	ld [hl], OBJECT_ACTION_STEP
+
+	call SpawnShadow
+
+	ld hl, wCenteredObject
+	ld a, [hMapObjectIndexBuffer]
+	cp [hl]
+	jr z, .player
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_NPC_JUMP
+	ret
+
+.player
+	ld hl, OBJECT_STEP_TYPE
+	add hl, bc
+	ld [hl], STEP_TYPE_PLAYER_JUMP
+	ret
+; 54b8
--- /dev/null
+++ b/engine/overworld/npc_movement.asm
@@ -1,0 +1,573 @@
+Function6ec1: ; 6ec1
+
+	ld hl, OBJECT_PALETTE
+	add hl, bc
+	bit 5, [hl]
+	jr z, .not_bit_5
+
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	bit 4, [hl] ; lost, uncomment next line to fix
+;	jr nz, .resume
+	push hl
+	push bc
+	call Function6f2c
+	pop bc
+	pop hl
+	ret c
+	jr .resume
+
+.not_bit_5
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	bit 4, [hl]
+	jr nz, .resume
+	push hl
+	push bc
+	call Function6f07
+	pop bc
+	pop hl
+	ret c
+
+.resume
+	bit 6, [hl]
+	jr nz, .bit_6
+
+	push hl
+	push bc
+	call WillObjectBumpIntoSomeoneElse
+	pop bc
+	pop hl
+	ret c
+
+.bit_6
+	bit 5, [hl]
+	jr nz, .bit_5
+	push hl
+	call HasObjectReachedMovementLimit
+	pop hl
+	ret c
+
+	push hl
+	call IsObjectMovingOffEdgeOfScreen
+	pop hl
+	ret c
+
+.bit_5
+	and a
+	ret
+; 6f07
+
+
+Function6f07: ; 6f07
+	call Function6f5f
+	ret c
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	ld hl, OBJECT_PALETTE
+	add hl, bc
+	bit OAM_PRIORITY, [hl]
+	jp nz, Function6fa1
+	ld hl, OBJECT_NEXT_TILE
+	add hl, bc
+	ld a, [hl]
+	ld d, a
+	call GetTileCollision
+	and a ; LANDTILE
+	jr z, Function6f3e
+	scf
+	ret
+; 6f2c
+
+Function6f2c: ; 6f2c
+	call Function6f5f
+	ret c
+	ld hl, OBJECT_NEXT_TILE
+	add hl, bc
+	ld a, [hl]
+	call GetTileCollision
+	cp WATERTILE
+	jr z, Function6f3e
+	scf
+	ret
+; 6f3e
+
+Function6f3e: ; 6f3e
+	ld hl, OBJECT_NEXT_TILE
+	add hl, bc
+	ld a, [hl]
+	call Function6f7f
+	ret nc
+	push af
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld a, [hl]
+	maskbits NUM_DIRECTIONS
+	ld e, a
+	ld d, 0
+	ld hl, .data_6f5b
+	add hl, de
+	pop af
+	and [hl]
+	ret z
+	scf
+	ret
+; 6f5b
+
+.data_6f5b
+	db DOWN_MASK, UP_MASK, RIGHT_MASK, LEFT_MASK
+; 6f5f
+
+Function6f5f: ; 6f5f
+	ld hl, OBJECT_STANDING_TILE
+	add hl, bc
+	ld a, [hl]
+	call Function6f7f
+	ret nc
+	push af
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	maskbits NUM_DIRECTIONS
+	ld e, a
+	ld d, 0
+	ld hl, .data_6f7b
+	add hl, de
+	pop af
+	and [hl]
+	ret z
+	scf
+	ret
+; 6f7b
+
+.data_6f7b
+	db UP_MASK, DOWN_MASK, LEFT_MASK, RIGHT_MASK
+; 6f7f
+
+Function6f7f: ; 6f7f
+	ld d, a
+	and $f0
+	cp $b0
+	jr z, .done
+	cp $c0
+	jr z, .done
+	xor a
+	ret
+
+.done
+	ld a, d
+	and 7
+	ld e, a
+	ld d, 0
+	ld hl, .data_6f99
+	add hl, de
+	ld a, [hl]
+	scf
+	ret
+; 6f99
+
+.data_6f99
+	db  8, 4, 1, 2
+	db 10, 6, 9, 5
+; 6fa1
+
+Function6fa1: ; 6fa1
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld a, [hl]
+	maskbits NUM_DIRECTIONS
+	jr z, .down
+	dec a
+	jr z, .up
+	dec a
+	jr z, .left
+	jr .right
+
+.down
+	inc e
+	push de
+	inc d
+	jr .continue
+
+.up
+	push de
+	inc d
+	jr .continue
+
+.left
+	push de
+	inc e
+	jr .continue
+
+.right
+	inc d
+	push de
+	inc e
+
+.continue
+	call GetCoordTile
+	call GetTileCollision
+	pop de
+	and a ; LANDTILE
+	jr nz, .not_land
+	call GetCoordTile
+	call GetTileCollision
+	and a ; LANDTILE
+	jr nz, .not_land
+	xor a
+	ret
+
+.not_land
+	scf
+	ret
+; 6fd9
+
+
+
+CheckFacingObject:: ; 6fd9
+
+	call GetFacingTileCoord
+
+; Double the distance for counter tiles.
+	call CheckCounterTile
+	jr nz, .asm_6ff1
+
+	ld a, [wPlayerStandingMapX]
+	sub d
+	cpl
+	inc a
+	add d
+	ld d, a
+
+	ld a, [wPlayerStandingMapY]
+	sub e
+	cpl
+	inc a
+	add e
+	ld e, a
+
+.asm_6ff1
+	ld bc, wObjectStructs ; redundant
+	ld a, 0
+	ld [hMapObjectIndexBuffer], a
+	call IsNPCAtCoord
+	ret nc
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld a, [hl]
+	cp STANDING
+	jr z, .standing
+	xor a
+	ret
+
+.standing
+	scf
+	ret
+; 7009
+
+
+WillObjectBumpIntoSomeoneElse: ; 7009
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	jr IsNPCAtCoord
+; 7015
+
+Unreferenced_Function7015:
+	ld a, [hMapObjectIndexBuffer]
+	call GetObjectStruct
+	call .CheckWillBeFacingNPC
+	call IsNPCAtCoord
+	ret
+
+.CheckWillBeFacingNPC: ; 7021
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	call GetSpriteDirection
+	and a
+	jr z, .down
+	cp OW_UP
+	jr z, .up
+	cp OW_LEFT
+	jr z, .left
+	inc d
+	ret
+
+.down
+	inc e
+	ret
+
+.up
+	dec e
+	ret
+
+.left
+	dec d
+	ret
+; 7041
+
+IsNPCAtCoord: ; 7041
+	ld bc, wObjectStructs
+	xor a
+.loop
+	ld [hObjectStructIndexBuffer], a
+	call DoesObjectHaveASprite
+	jr z, .next
+
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	bit 7, [hl]
+	jr nz, .next
+
+	ld hl, OBJECT_PALETTE
+	add hl, bc
+	bit 7, [hl]
+	jr z, .got
+
+	call Function7171
+	jr nc, .ok
+	jr .ok2
+
+.got
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	cp d
+	jr nz, .ok
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld a, [hl]
+	cp e
+	jr nz, .ok
+
+.ok2
+	ld a, [hMapObjectIndexBuffer]
+	ld l, a
+	ld a, [hObjectStructIndexBuffer]
+	cp l
+	jr nz, .setcarry
+
+.ok
+	ld hl, OBJECT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	cp d
+	jr nz, .next
+	ld hl, OBJECT_MAP_Y
+	add hl, bc
+	ld a, [hl]
+	cp e
+	jr nz, .next
+	ld a, [hMapObjectIndexBuffer]
+	ld l, a
+	ld a, [hObjectStructIndexBuffer]
+	cp l
+	jr nz, .setcarry
+
+.next
+	ld hl, OBJECT_STRUCT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	ld a, [hObjectStructIndexBuffer]
+	inc a
+	cp NUM_OBJECT_STRUCTS
+	jr nz, .loop
+	and a
+	ret
+
+.setcarry
+	scf
+	ret
+; 70a4
+
+HasObjectReachedMovementLimit: ; 70a4
+	ld hl, OBJECT_RADIUS
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .nope
+	and $f
+	jr z, .check_y
+	ld e, a
+	ld d, a
+	ld hl, OBJECT_INIT_X
+	add hl, bc
+	ld a, [hl]
+	sub d
+	ld d, a
+	ld a, [hl]
+	add e
+	ld e, a
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	cp d
+	jr z, .yes
+	cp e
+	jr z, .yes
+
+.check_y
+	ld hl, OBJECT_RADIUS
+	add hl, bc
+	ld a, [hl]
+	swap a
+	and $f
+	jr z, .nope
+	ld e, a
+	ld d, a
+	ld hl, OBJECT_INIT_Y
+	add hl, bc
+	ld a, [hl]
+	sub d
+	ld d, a
+	ld a, [hl]
+	add e
+	ld e, a
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld a, [hl]
+	cp d
+	jr z, .yes
+	cp e
+	jr z, .yes
+
+.nope
+	xor a
+	ret
+
+.yes
+	scf
+	ret
+; 70ed
+
+IsObjectMovingOffEdgeOfScreen: ; 70ed
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, [wXCoord]
+	cp [hl]
+	jr z, .check_y
+	jr nc, .yes
+	add $9
+	cp [hl]
+	jr c, .yes
+
+.check_y
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld a, [wYCoord]
+	cp [hl]
+	jr z, .nope
+	jr nc, .yes
+	add $8
+	cp [hl]
+	jr c, .yes
+
+.nope
+	and a
+	ret
+
+.yes
+	scf
+	ret
+; 7113
+
+Unreferenced_Function7113:
+	ld a, [wPlayerStandingMapX]
+	ld d, a
+	ld a, [wPlayerStandingMapY]
+	ld e, a
+	ld bc, wObjectStructs
+	xor a
+.loop
+	ld [hObjectStructIndexBuffer], a
+	call DoesObjectHaveASprite
+	jr z, .next
+	ld hl, OBJECT_MOVEMENTTYPE
+	add hl, bc
+	ld a, [hl]
+	cp SPRITEMOVEDATA_BIGDOLLSYM
+	jr nz, .not_snorlax
+	call Function7171
+	jr c, .yes
+	jr .next
+
+.not_snorlax
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld a, [hl]
+	cp e
+	jr nz, .check_current_coords
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	cp d
+	jr nz, .check_current_coords
+	ld a, [hObjectStructIndexBuffer]
+	cp $0
+	jr z, .next
+	jr .yes
+
+.check_current_coords
+	ld hl, OBJECT_MAP_Y
+	add hl, bc
+	ld a, [hl]
+	cp e
+	jr nz, .next
+	ld hl, OBJECT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	cp d
+	jr nz, .next
+	jr .yes
+
+.next
+	ld hl, OBJECT_STRUCT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	ld a, [hObjectStructIndexBuffer]
+	inc a
+	cp NUM_OBJECT_STRUCTS
+	jr nz, .loop
+	xor a
+	ret
+
+.yes
+	scf
+	ret
+; 7171
+
+
+Function7171: ; 7171
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, d
+	sub [hl]
+	jr c, .nope
+	cp $2
+	jr nc, .nope
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld a, e
+	sub [hl]
+	jr c, .nope
+	cp $2
+	jr nc, .nope
+	scf
+	ret
+
+.nope
+	and a
+	ret
+; 718d
--- /dev/null
+++ b/engine/overworld/overworld.asm
@@ -1,0 +1,715 @@
+GetEmote2bpp: ; 1412a
+	ld a, $1
+	ld [rVBK], a
+	call Get2bpp
+	xor a
+	ld [rVBK], a
+	ret
+; 14135
+
+_ReplaceKrisSprite:: ; 14135
+	call GetPlayerSprite
+	ld a, [wUsedSprites]
+	ld [hUsedSpriteIndex], a
+	ld a, [wUsedSprites + 1]
+	ld [hUsedSpriteTile], a
+	call GetUsedSprite
+	ret
+; 14146
+
+Function14146: ; mobile
+	ld hl, wSpriteFlags
+	ld a, [hl]
+	push af
+	res 7, [hl]
+	set 6, [hl]
+	call LoadUsedSpritesGFX
+	pop af
+	ld [wSpriteFlags], a
+	ret
+; 14157
+
+Function14157: ; mobile
+	ld hl, wSpriteFlags
+	ld a, [hl]
+	push af
+	set 7, [hl]
+	res 6, [hl]
+	call LoadUsedSpritesGFX
+	pop af
+	ld [wSpriteFlags], a
+	ret
+; 14168
+
+RefreshSprites:: ; 14168
+	call .Refresh
+	call LoadUsedSpritesGFX
+	ret
+; 1416f
+
+.Refresh: ; 1416f
+	xor a
+	ld bc, wUsedSpritesEnd - wUsedSprites
+	ld hl, wUsedSprites
+	call ByteFill
+	call GetPlayerSprite
+	call AddMapSprites
+	call LoadAndSortSprites
+	ret
+; 14183
+
+GetPlayerSprite: ; 14183
+; Get Chris or Kris's sprite.
+	ld hl, ChrisStateSprites
+	ld a, [wPlayerSpriteSetupFlags]
+	bit PLAYERSPRITESETUP_FEMALE_TO_MALE_F, a
+	jr nz, .go
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .go
+	ld hl, KrisStateSprites
+
+.go
+	ld a, [wPlayerState]
+	ld c, a
+.loop
+	ld a, [hli]
+	cp c
+	jr z, .good
+	inc hl
+	cp -1
+	jr nz, .loop
+
+; Any player state not in the array defaults to Chris's sprite.
+	xor a ; ld a, PLAYER_NORMAL
+	ld [wPlayerState], a
+	ld a, SPRITE_CHRIS
+	jr .finish
+
+.good
+	ld a, [hl]
+
+.finish
+	ld [wUsedSprites + 0], a
+	ld [wPlayerSprite], a
+	ld [wPlayerObjectSprite], a
+	ret
+
+INCLUDE "data/sprites/player_sprites.asm"
+
+
+AddMapSprites: ; 141c9
+	call GetMapEnvironment
+	call CheckOutdoorMap
+	jr z, .outdoor
+	call AddIndoorSprites
+	ret
+
+.outdoor
+	call AddOutdoorSprites
+	ret
+; 141d9
+
+
+AddIndoorSprites: ; 141d9
+	ld hl, wMap1ObjectSprite
+	ld a, 1
+.loop
+	push af
+	ld a, [hl]
+	call AddSpriteGFX
+	ld de, OBJECT_LENGTH
+	add hl, de
+	pop af
+	inc a
+	cp NUM_OBJECTS
+	jr nz, .loop
+	ret
+; 141ee
+
+
+AddOutdoorSprites: ; 141ee
+	ld a, [wMapGroup]
+	dec a
+	ld c, a
+	ld b, 0
+	ld hl, OutdoorSprites
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld c, MAX_OUTDOOR_SPRITES
+.loop
+	push bc
+	ld a, [hli]
+	call AddSpriteGFX
+	pop bc
+	dec c
+	jr nz, .loop
+	ret
+; 14209
+
+
+LoadUsedSpritesGFX: ; 14209
+	ld a, MAPCALLBACK_SPRITES
+	call RunMapCallback
+	call GetUsedSprites
+	call .LoadMiscTiles
+	ret
+; 14215
+
+.LoadMiscTiles: ; 14215
+	ld a, [wSpriteFlags]
+	bit 6, a
+	ret nz
+
+	ld c, EMOTE_SHADOW
+	farcall LoadEmote
+	call GetMapEnvironment
+	call CheckOutdoorMap
+	ld c, EMOTE_GRASS_RUSTLE
+	jr z, .outdoor
+	ld c, EMOTE_BOULDER_DUST
+.outdoor
+	farcall LoadEmote
+	ret
+; 14236
+
+
+
+SafeGetSprite: ; 14236
+	push hl
+	call GetSprite
+	pop hl
+	ret
+; 1423c
+
+GetSprite: ; 1423c
+	call GetMonSprite
+	ret c
+
+	ld hl, OverworldSprites + SPRITEDATA_ADDR
+	dec a
+	ld c, a
+	ld b, 0
+	ld a, NUM_SPRITEDATA_FIELDS
+	call AddNTimes
+	; load the address into de
+	ld a, [hli]
+	ld e, a
+	ld a, [hli]
+	ld d, a
+	; load the length into c
+	ld a, [hli]
+	swap a
+	ld c, a
+	; load the sprite bank into both b and h
+	ld b, [hl]
+	ld a, [hli]
+	; load the sprite type into l
+	ld l, [hl]
+	ld h, a
+	ret
+; 14259
+
+
+GetMonSprite: ; 14259
+; Return carry if a monster sprite was loaded.
+
+	cp SPRITE_POKEMON
+	jr c, .Normal
+	cp SPRITE_DAY_CARE_MON_1
+	jr z, .BreedMon1
+	cp SPRITE_DAY_CARE_MON_2
+	jr z, .BreedMon2
+	cp SPRITE_VARS
+	jr nc, .Variable
+	jr .Icon
+
+.Normal:
+	and a
+	ret
+
+.Icon:
+	sub SPRITE_POKEMON
+	ld e, a
+	ld d, 0
+	ld hl, SpriteMons
+	add hl, de
+	ld a, [hl]
+	jr .Mon
+
+.BreedMon1
+	ld a, [wBreedMon1Species]
+	jr .Mon
+
+.BreedMon2
+	ld a, [wBreedMon2Species]
+
+.Mon:
+	ld e, a
+	and a
+	jr z, .NoBreedmon
+
+	farcall LoadOverworldMonIcon
+
+	ld l, 1
+	ld h, 0
+	scf
+	ret
+
+.Variable:
+	sub SPRITE_VARS
+	ld e, a
+	ld d, 0
+	ld hl, wVariableSprites
+	add hl, de
+	ld a, [hl]
+	and a
+	jp nz, GetMonSprite
+
+.NoBreedmon:
+	ld a, 1
+	ld l, 1
+	ld h, 0
+	and a
+	ret
+; 142a7
+
+
+_DoesSpriteHaveFacings:: ; 142a7
+; Checks to see whether we can apply a facing to a sprite.
+; Returns carry unless the sprite is a Pokemon or a Still Sprite.
+	cp SPRITE_POKEMON
+	jr nc, .only_down
+
+	push hl
+	push bc
+	ld hl, OverworldSprites + SPRITEDATA_TYPE
+	dec a
+	ld c, a
+	ld b, 0
+	ld a, NUM_SPRITEDATA_FIELDS
+	call AddNTimes
+	ld a, [hl]
+	pop bc
+	pop hl
+	cp STILL_SPRITE
+	jr nz, .only_down
+	scf
+	ret
+
+.only_down
+	and a
+	ret
+; 142c4
+
+
+_GetSpritePalette:: ; 142c4
+	ld a, c
+	call GetMonSprite
+	jr c, .is_pokemon
+
+	ld hl, OverworldSprites + SPRITEDATA_PALETTE
+	dec a
+	ld c, a
+	ld b, 0
+	ld a, NUM_SPRITEDATA_FIELDS
+	call AddNTimes
+	ld c, [hl]
+	ret
+
+.is_pokemon
+	xor a
+	ld c, a
+	ret
+; 142db
+
+
+LoadAndSortSprites: ; 142db
+	call LoadSpriteGFX
+	call SortUsedSprites
+	call ArrangeUsedSprites
+	ret
+; 142e5
+
+
+AddSpriteGFX: ; 142e5
+; Add any new sprite ids to a list of graphics to be loaded.
+; Return carry if the list is full.
+
+	push hl
+	push bc
+	ld b, a
+	ld hl, wUsedSprites + 2
+	ld c, SPRITE_GFX_LIST_CAPACITY - 1
+.loop
+	ld a, [hl]
+	cp b
+	jr z, .exists
+	and a
+	jr z, .new
+	inc hl
+	inc hl
+	dec c
+	jr nz, .loop
+
+	pop bc
+	pop hl
+	scf
+	ret
+
+.exists
+	pop bc
+	pop hl
+	and a
+	ret
+
+.new
+	ld [hl], b
+	pop bc
+	pop hl
+	and a
+	ret
+; 14306
+
+
+LoadSpriteGFX: ; 14306
+; Bug: b is not preserved, so it's useless as a next count.
+; Uncomment the lines below to fix.
+
+	ld hl, wUsedSprites
+	ld b, SPRITE_GFX_LIST_CAPACITY
+.loop
+	ld a, [hli]
+	and a
+	jr z, .done
+	push hl
+	call .LoadSprite
+	pop hl
+	ld [hli], a
+	dec b
+	jr nz, .loop
+
+.done
+	ret
+
+.LoadSprite:
+	; push bc
+	call GetSprite
+	; pop bc
+	ld a, l
+	ret
+; 1431e
+
+
+SortUsedSprites: ; 1431e
+; Bubble-sort sprites by type.
+
+; Run backwards through wUsedSprites to find the last one.
+
+	ld c, SPRITE_GFX_LIST_CAPACITY
+	ld de, wUsedSprites + (SPRITE_GFX_LIST_CAPACITY - 1) * 2
+.FindLastSprite:
+	ld a, [de]
+	and a
+	jr nz, .FoundLastSprite
+	dec de
+	dec de
+	dec c
+	jr nz, .FindLastSprite
+.FoundLastSprite:
+	dec c
+	jr z, .quit
+
+; If the length of the current sprite is
+; higher than a later one, swap them.
+
+	inc de
+	ld hl, wUsedSprites + 1
+
+.CheckSprite:
+	push bc
+	push de
+	push hl
+
+.CheckFollowing:
+	ld a, [de]
+	cp [hl]
+	jr nc, .loop
+
+; Swap the two sprites.
+
+	ld b, a
+	ld a, [hl]
+	ld [hl], b
+	ld [de], a
+	dec de
+	dec hl
+	ld a, [de]
+	ld b, a
+	ld a, [hl]
+	ld [hl], b
+	ld [de], a
+	inc de
+	inc hl
+
+; Keep doing this until everything's in order.
+
+.loop
+	dec de
+	dec de
+	dec c
+	jr nz, .CheckFollowing
+
+	pop hl
+	inc hl
+	inc hl
+	pop de
+	pop bc
+	dec c
+	jr nz, .CheckSprite
+
+.quit
+	ret
+; 14355
+
+
+ArrangeUsedSprites: ; 14355
+; Get the length of each sprite and space them out in VRAM.
+; Crystal introduces a second table in VRAM bank 0.
+
+	ld hl, wUsedSprites
+	ld c, SPRITE_GFX_LIST_CAPACITY
+	ld b, 0
+.FirstTableLength:
+; Keep going until the end of the list.
+	ld a, [hli]
+	and a
+	jr z, .quit
+
+	ld a, [hl]
+	call GetSpriteLength
+
+; Spill over into the second table after $80 tiles.
+	add b
+	cp $80
+	jr z, .loop
+	jr nc, .SecondTable
+
+.loop
+	ld [hl], b
+	inc hl
+	ld b, a
+
+; Assumes the next table will be reached before c hits 0.
+	dec c
+	jr nz, .FirstTableLength
+
+.SecondTable:
+; The second tile table starts at tile $80.
+	ld b, $80
+	dec hl
+.SecondTableLength:
+; Keep going until the end of the list.
+	ld a, [hli]
+	and a
+	jr z, .quit
+
+	ld a, [hl]
+	call GetSpriteLength
+
+; There are only two tables, so don't go any further than that.
+	add b
+	jr c, .quit
+
+	ld [hl], b
+	ld b, a
+	inc hl
+
+	dec c
+	jr nz, .SecondTableLength
+
+.quit
+	ret
+; 14386
+
+
+GetSpriteLength: ; 14386
+; Return the length of sprite type a in tiles.
+
+	cp WALKING_SPRITE
+	jr z, .AnyDirection
+	cp STANDING_SPRITE
+	jr z, .AnyDirection
+	cp STILL_SPRITE
+	jr z, .OneDirection
+
+	ld a, 12
+	ret
+
+.AnyDirection:
+	ld a, 12
+	ret
+
+.OneDirection:
+	ld a, 4
+	ret
+; 1439b
+
+
+GetUsedSprites: ; 1439b
+	ld hl, wUsedSprites
+	ld c, SPRITE_GFX_LIST_CAPACITY
+
+.loop
+	ld a, [wSpriteFlags]
+	res 5, a
+	ld [wSpriteFlags], a
+
+	ld a, [hli]
+	and a
+	jr z, .done
+	ld [hUsedSpriteIndex], a
+
+	ld a, [hli]
+	ld [hUsedSpriteTile], a
+
+	bit 7, a
+	jr z, .dont_set
+
+	ld a, [wSpriteFlags]
+	set 5, a ; load VBank0
+	ld [wSpriteFlags], a
+
+.dont_set
+	push bc
+	push hl
+	call GetUsedSprite
+	pop hl
+	pop bc
+	dec c
+	jr nz, .loop
+
+.done
+	ret
+; 143c8
+
+GetUsedSprite: ; 143c8
+	ld a, [hUsedSpriteIndex]
+	call SafeGetSprite
+	ld a, [hUsedSpriteTile]
+	call .GetTileAddr
+	push hl
+	push de
+	push bc
+	ld a, [wSpriteFlags]
+	bit 7, a
+	jr nz, .skip
+	call .CopyToVram
+
+.skip
+	pop bc
+	ld l, c
+	ld h, $0
+rept 4
+	add hl, hl
+endr
+	pop de
+	add hl, de
+	ld d, h
+	ld e, l
+	pop hl
+
+	ld a, [wSpriteFlags]
+	bit 5, a
+	jr nz, .done
+	bit 6, a
+	jr nz, .done
+
+	ld a, [hUsedSpriteIndex]
+	call _DoesSpriteHaveFacings
+	jr c, .done
+
+	ld a, h
+	add $8
+	ld h, a
+	call .CopyToVram
+
+.done
+	ret
+; 14406
+
+.GetTileAddr: ; 14406
+; Return the address of tile (a) in (hl).
+	and $7f
+	ld l, a
+	ld h, 0
+rept 4
+	add hl, hl
+endr
+	ld a, l
+	add LOW(vTiles0)
+	ld l, a
+	ld a, h
+	adc HIGH(vTiles0)
+	ld h, a
+	ret
+; 14418
+
+.CopyToVram: ; 14418
+	ld a, [rVBK]
+	push af
+	ld a, [wSpriteFlags]
+	bit 5, a
+	ld a, $1
+	jr z, .bankswitch
+	ld a, $0
+
+.bankswitch
+	ld [rVBK], a
+	call Get2bpp
+	pop af
+	ld [rVBK], a
+	ret
+; 1442f
+
+LoadEmote:: ; 1442f
+; Get the address of the pointer to emote c.
+	ld a, c
+	ld bc, 6 ; sizeof(emote)
+	ld hl, Emotes
+	call AddNTimes
+; Load the emote address into de
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+; load the length of the emote (in tiles) into c
+	inc hl
+	ld c, [hl]
+	swap c
+; load the emote pointer bank into b
+	inc hl
+	ld b, [hl]
+; load the VRAM destination into hl
+	inc hl
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+; if the emote has a length of 0, do not proceed (error handling)
+	ld a, c
+	and a
+	ret z
+	call GetEmote2bpp
+	ret
+; 1444d
+
+
+INCLUDE "data/sprites/emotes.asm"
+
+INCLUDE "data/sprites/sprite_mons.asm"
+
+INCLUDE "data/maps/outdoor_sprites.asm"
+
+INCLUDE "data/sprites/sprites.asm"
--- /dev/null
+++ b/engine/overworld/player_movement.asm
@@ -1,0 +1,851 @@
+DoPlayerMovement:: ; 80000
+
+	call .GetDPad
+	ld a, movement_step_sleep
+	ld [wMovementAnimation], a
+	xor a
+	ld [wd041], a
+	call .TranslateIntoMovement
+	ld c, a
+	ld a, [wMovementAnimation]
+	ld [wPlayerNextMovement], a
+	ret
+
+.GetDPad:
+
+	ld a, [hJoyDown]
+	ld [wCurInput], a
+
+; Standing downhill instead moves down.
+
+	ld hl, wBikeFlags
+	bit BIKEFLAGS_DOWNHILL_F, [hl]
+	ret z
+
+	ld c, a
+	and D_PAD
+	ret nz
+
+	ld a, c
+	or D_DOWN
+	ld [wCurInput], a
+	ret
+; 8002d
+
+.TranslateIntoMovement:
+	ld a, [wPlayerState]
+	cp PLAYER_NORMAL
+	jr z, .Normal
+	cp PLAYER_SURF
+	jr z, .Surf
+	cp PLAYER_SURF_PIKA
+	jr z, .Surf
+	cp PLAYER_BIKE
+	jr z, .Normal
+	cp PLAYER_SKATE
+	jr z, .Ice
+
+.Normal:
+	call .CheckForced
+	call .GetAction
+	call .CheckTile
+	ret c
+	call .CheckTurning
+	ret c
+	call .TryStep
+	ret c
+	call .TryJump
+	ret c
+	call .CheckWarp
+	ret c
+	jr .NotMoving
+
+.Surf:
+	call .CheckForced
+	call .GetAction
+	call .CheckTile
+	ret c
+	call .CheckTurning
+	ret c
+	call .TrySurf
+	ret c
+	jr .NotMoving
+
+.Ice:
+	call .CheckForced
+	call .GetAction
+	call .CheckTile
+	ret c
+	call .CheckTurning
+	ret c
+	call .TryStep
+	ret c
+	call .TryJump
+	ret c
+	call .CheckWarp
+	ret c
+	ld a, [wWalkingDirection]
+	cp STANDING
+	jr z, .HitWall
+	call .BumpSound
+.HitWall:
+	call .StandInPlace
+	xor a
+	ret
+
+.NotMoving:
+	ld a, [wWalkingDirection]
+	cp STANDING
+	jr z, .Standing
+
+; Walking into an edge warp won't bump.
+	ld a, [wEngineBuffer4]
+	and a
+	jr nz, .CantMove
+	call .BumpSound
+.CantMove:
+	call ._WalkInPlace
+	xor a
+	ret
+
+.Standing:
+	call .StandInPlace
+	xor a
+	ret
+; 800b7
+
+.CheckTile: ; 800b7
+; Tiles such as waterfalls and warps move the player
+; in a given direction, overriding input.
+
+	ld a, [wPlayerStandingTile]
+	ld c, a
+	call CheckWhirlpoolTile
+	jr c, .not_whirlpool
+	ld a, 3
+	scf
+	ret
+
+.not_whirlpool
+	and $f0
+	cp HI_NYBBLE_CURRENT
+	jr z, .water
+	cp HI_NYBBLE_WALK
+	jr z, .land1
+	cp HI_NYBBLE_WALK_ALT
+	jr z, .land2
+	cp HI_NYBBLE_WARPS
+	jr z, .warps
+	jr .no_walk
+
+.water
+	ld a, c
+	maskbits NUM_DIRECTIONS
+	ld c, a
+	ld b, 0
+	ld hl, .water_table
+	add hl, bc
+	ld a, [hl]
+	ld [wWalkingDirection], a
+	jr .continue_walk
+
+.water_table
+	db RIGHT ; COLL_WATERFALL_RIGHT
+	db LEFT  ; COLL_WATERFALL_LEFT
+	db UP    ; COLL_WATERFALL_UP
+	db DOWN  ; COLL_WATERFALL
+
+.land1
+	ld a, c
+	and 7
+	ld c, a
+	ld b, 0
+	ld hl, .land1_table
+	add hl, bc
+	ld a, [hl]
+	cp STANDING
+	jr z, .no_walk
+	ld [wWalkingDirection], a
+	jr .continue_walk
+
+.land1_table
+	db STANDING ; COLL_BRAKE
+	db RIGHT    ; COLL_WALK_RIGHT
+	db LEFT     ; COLL_WALK_LEFT
+	db UP       ; COLL_WALK_UP
+	db DOWN     ; COLL_WALK_DOWN
+	db STANDING ; COLL_BRAKE_45
+	db STANDING ; COLL_BRAKE_46
+	db STANDING ; COLL_BRAKE_47
+
+.land2
+	ld a, c
+	and 7
+	ld c, a
+	ld b, 0
+	ld hl, .land2_table
+	add hl, bc
+	ld a, [hl]
+	cp STANDING
+	jr z, .no_walk
+	ld [wWalkingDirection], a
+	jr .continue_walk
+
+.land2_table
+	db RIGHT    ; COLL_WALK_RIGHT_ALT
+	db LEFT     ; COLL_WALK_LEFT_ALT
+	db UP       ; COLL_WALK_UP_ALT
+	db DOWN     ; COLL_WALK_DOWN_ALT
+	db STANDING ; COLL_BRAKE_ALT
+	db STANDING ; COLL_BRAKE_55
+	db STANDING ; COLL_BRAKE_56
+	db STANDING ; COLL_BRAKE_57
+
+.warps
+	ld a, c
+	cp COLL_DOOR
+	jr z, .down
+	cp COLL_DOOR_79
+	jr z, .down
+	cp COLL_STAIRCASE
+	jr z, .down
+	cp COLL_CAVE
+	jr nz, .no_walk
+
+.down
+	ld a, DOWN
+	ld [wWalkingDirection], a
+	jr .continue_walk
+
+.no_walk
+	xor a
+	ret
+
+.continue_walk
+	ld a, STEP_WALK
+	call .DoStep
+	ld a, 5
+	scf
+	ret
+; 80147
+
+.CheckTurning: ; 80147
+; If the player is turning, change direction first. This also lets
+; the player change facing without moving by tapping a direction.
+
+	ld a, [wPlayerTurningDirection]
+	cp 0
+	jr nz, .not_turning
+	ld a, [wWalkingDirection]
+	cp STANDING
+	jr z, .not_turning
+
+	ld e, a
+	ld a, [wPlayerDirection]
+	rrca
+	rrca
+	maskbits NUM_DIRECTIONS
+	cp e
+	jr z, .not_turning
+
+	ld a, STEP_TURN
+	call .DoStep
+	ld a, 2
+	scf
+	ret
+
+.not_turning
+	xor a
+	ret
+; 8016b
+
+.TryStep: ; 8016b
+
+; Surfing actually calls .TrySurf directly instead of passing through here.
+	ld a, [wPlayerState]
+	cp PLAYER_SURF
+	jr z, .TrySurf
+	cp PLAYER_SURF_PIKA
+	jr z, .TrySurf
+
+	call .CheckLandPerms
+	jr c, .bump
+
+	call .CheckNPC
+	and a
+	jr z, .bump
+	cp 2
+	jr z, .bump
+
+	ld a, [wPlayerStandingTile]
+	call CheckIceTile
+	jr nc, .ice
+
+; Downhill riding is slower when not moving down.
+	call .BikeCheck
+	jr nz, .walk
+
+	ld hl, wBikeFlags
+	bit BIKEFLAGS_DOWNHILL_F, [hl]
+	jr z, .fast
+
+	ld a, [wWalkingDirection]
+	cp DOWN
+	jr z, .fast
+
+	ld a, STEP_WALK
+	call .DoStep
+	scf
+	ret
+
+.fast
+	ld a, STEP_BIKE
+	call .DoStep
+	scf
+	ret
+
+.walk
+	ld a, STEP_WALK
+	call .DoStep
+	scf
+	ret
+
+.ice
+	ld a, STEP_ICE
+	call .DoStep
+	scf
+	ret
+
+; unused
+	xor a
+	ret
+
+.bump
+	xor a
+	ret
+; 801c0
+
+.TrySurf: ; 801c0
+
+	call .CheckSurfPerms
+	ld [wd040], a
+	jr c, .surf_bump
+
+	call .CheckNPC
+	ld [wd03f], a
+	and a
+	jr z, .surf_bump
+	cp 2
+	jr z, .surf_bump
+
+	ld a, [wd040]
+	and a
+	jr nz, .ExitWater
+
+	ld a, STEP_WALK
+	call .DoStep
+	scf
+	ret
+
+.ExitWater:
+	call .GetOutOfWater
+	call PlayMapMusic
+	ld a, STEP_WALK
+	call .DoStep
+	ld a, 6
+	scf
+	ret
+
+.surf_bump
+	xor a
+	ret
+; 801f3
+
+.TryJump: ; 801f3
+	ld a, [wPlayerStandingTile]
+	ld e, a
+	and $f0
+	cp HI_NYBBLE_LEDGES
+	jr nz, .DontJump
+
+	ld a, e
+	and 7
+	ld e, a
+	ld d, 0
+	ld hl, .data_8021e
+	add hl, de
+	ld a, [wFacingDirection]
+	and [hl]
+	jr z, .DontJump
+
+	ld de, SFX_JUMP_OVER_LEDGE
+	call PlaySFX
+	ld a, STEP_LEDGE
+	call .DoStep
+	ld a, 7
+	scf
+	ret
+
+.DontJump:
+	xor a
+	ret
+
+.data_8021e
+	db FACE_RIGHT             ; COLL_HOP_RIGHT
+	db FACE_LEFT              ; COLL_HOP_LEFT
+	db FACE_UP                ; COLL_HOP_UP
+	db FACE_DOWN              ; COLL_HOP_DOWN
+	db FACE_RIGHT | FACE_DOWN ; COLL_HOP_DOWN_RIGHT
+	db FACE_DOWN | FACE_LEFT  ; COLL_HOP_DOWN_LEFT
+	db FACE_UP | FACE_RIGHT   ; COLL_HOP_UP_RIGHT
+	db FACE_UP | FACE_LEFT    ; COLL_HOP_UP_LEFT
+; 80226
+
+.CheckWarp: ; 80226
+
+; Bug: Since no case is made for STANDING here, it will check
+; [.edgewarps + $ff]. This resolves to $3e at $8035a.
+; This causes wd041 to be nonzero when standing on tile $3e,
+; making bumps silent.
+
+	ld a, [wWalkingDirection]
+	; cp STANDING
+	; jr z, .not_warp
+	ld e, a
+	ld d, 0
+	ld hl, .EdgeWarps
+	add hl, de
+	ld a, [wPlayerStandingTile]
+	cp [hl]
+	jr nz, .not_warp
+
+	ld a, 1
+	ld [wd041], a
+	ld a, [wWalkingDirection]
+	; This is in the wrong place.
+	cp STANDING
+	jr z, .not_warp
+
+	ld e, a
+	ld a, [wPlayerDirection]
+	rrca
+	rrca
+	maskbits NUM_DIRECTIONS
+	cp e
+	jr nz, .not_warp
+	call WarpCheck
+	jr nc, .not_warp
+
+	call .StandInPlace
+	scf
+	ld a, 1
+	ret
+
+.not_warp
+	xor a
+	ret
+
+.EdgeWarps:
+	db COLL_WARP_CARPET_DOWN
+	db COLL_WARP_CARPET_UP
+	db COLL_WARP_CARPET_LEFT
+	db COLL_WARP_CARPET_RIGHT
+; 8025f
+
+.DoStep:
+	ld e, a
+	ld d, 0
+	ld hl, .Steps
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+
+	ld a, [wWalkingDirection]
+	ld e, a
+	cp STANDING
+	jp z, .StandInPlace
+
+	add hl, de
+	ld a, [hl]
+	ld [wMovementAnimation], a
+
+	ld hl, .FinishFacing
+	add hl, de
+	ld a, [hl]
+	ld [wPlayerTurningDirection], a
+
+	ld a, 4
+	ret
+
+.Steps:
+	dw .SlowStep
+	dw .NormalStep
+	dw .FastStep
+	dw .JumpStep
+	dw .SlideStep
+	dw .TurningStep
+	dw .BackJumpStep
+	dw .FinishFacing
+
+.SlowStep:
+	slow_step DOWN
+	slow_step UP
+	slow_step LEFT
+	slow_step RIGHT
+.NormalStep:
+	step DOWN
+	step UP
+	step LEFT
+	step RIGHT
+.FastStep:
+	big_step DOWN
+	big_step UP
+	big_step LEFT
+	big_step RIGHT
+.JumpStep:
+	jump_step DOWN
+	jump_step UP
+	jump_step LEFT
+	jump_step RIGHT
+.SlideStep:
+	fast_slide_step DOWN
+	fast_slide_step UP
+	fast_slide_step LEFT
+	fast_slide_step RIGHT
+.BackJumpStep:
+	jump_step UP
+	jump_step DOWN
+	jump_step RIGHT
+	jump_step LEFT
+.TurningStep:
+	turn_step DOWN
+	turn_step UP
+	turn_step LEFT
+	turn_step RIGHT
+.FinishFacing:
+	db $80 + DOWN
+	db $80 + UP
+	db $80 + LEFT
+	db $80 + RIGHT
+; 802b3
+
+.StandInPlace: ; 802b3
+	ld a, 0
+	ld [wPlayerTurningDirection], a
+	ld a, movement_step_sleep
+	ld [wMovementAnimation], a
+	xor a
+	ret
+; 802bf
+
+._WalkInPlace: ; 802bf
+	ld a, 0
+	ld [wPlayerTurningDirection], a
+	ld a, movement_step_bump
+	ld [wMovementAnimation], a
+	xor a
+	ret
+; 802cb
+
+.CheckForced: ; 802cb
+; When sliding on ice, input is forced to remain in the same direction.
+
+	call CheckStandingOnIce
+	ret nc
+
+	ld a, [wPlayerTurningDirection]
+	cp 0
+	ret z
+
+	maskbits NUM_DIRECTIONS
+	ld e, a
+	ld d, 0
+	ld hl, .forced_dpad
+	add hl, de
+	ld a, [wCurInput]
+	and BUTTONS
+	or [hl]
+	ld [wCurInput], a
+	ret
+
+.forced_dpad
+	db D_DOWN, D_UP, D_LEFT, D_RIGHT
+; 802ec
+
+.GetAction: ; 802ec
+; Poll player input and update movement info.
+
+	ld hl, .table
+	ld de, .table2 - .table1
+	ld a, [wCurInput]
+	bit D_DOWN_F, a
+	jr nz, .d_down
+	bit D_UP_F, a
+	jr nz, .d_up
+	bit D_LEFT_F, a
+	jr nz, .d_left
+	bit D_RIGHT_F, a
+	jr nz, .d_right
+; Standing
+	jr .update
+
+.d_down 	add hl, de
+.d_up   	add hl, de
+.d_left 	add hl, de
+.d_right	add hl, de
+
+.update
+	ld a, [hli]
+	ld [wWalkingDirection], a
+	ld a, [hli]
+	ld [wFacingDirection], a
+	ld a, [hli]
+	ld [wWalkingX], a
+	ld a, [hli]
+	ld [wWalkingY], a
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [hl]
+	ld [wWalkingTile], a
+	ret
+
+.table
+; struct:
+;	walk direction
+;	facing
+;	x movement
+;	y movement
+;	tile collision pointer
+.table1
+	db STANDING, FACE_CURRENT, 0, 0
+	dw wPlayerStandingTile
+.table2
+	db RIGHT, FACE_RIGHT,  1,  0
+	dw wTileRight
+	db LEFT,  FACE_LEFT,  -1,  0
+	dw wTileLeft
+	db UP,    FACE_UP,     0, -1
+	dw wTileUp
+	db DOWN,  FACE_DOWN,   0,  1
+	dw wTileDown
+; 80341
+
+.CheckNPC: ; 80341
+; Returns 0 if there is an NPC in front that you can't move
+; Returns 1 if there is no NPC in front
+; Returns 2 if there is a movable NPC in front
+	ld a, 0
+	ld [hMapObjectIndexBuffer], a
+; Load the next X coordinate into d
+	ld a, [wPlayerStandingMapX]
+	ld d, a
+	ld a, [wWalkingX]
+	add d
+	ld d, a
+; Load the next Y coordinate into e
+	ld a, [wPlayerStandingMapY]
+	ld e, a
+	ld a, [wWalkingY]
+	add e
+	ld e, a
+; Find an object struct with coordinates equal to d,e
+	ld bc, wObjectStructs ; redundant
+	farcall IsNPCAtCoord
+	jr nc, .is_npc
+	call .CheckStrengthBoulder
+	jr c, .no_bump
+
+	xor a
+	ret
+
+.is_npc
+	ld a, 1
+	ret
+
+.no_bump
+	ld a, 2
+	ret
+; 8036f
+
+.CheckStrengthBoulder: ; 8036f
+
+	ld hl, wBikeFlags
+	bit BIKEFLAGS_STRENGTH_ACTIVE_F, [hl]
+	jr z, .not_boulder
+
+	ld hl, OBJECT_DIRECTION_WALKING
+	add hl, bc
+	ld a, [hl]
+	cp STANDING
+	jr nz, .not_boulder
+
+	ld hl, OBJECT_PALETTE
+	add hl, bc
+	bit 6, [hl]
+	jr z, .not_boulder
+
+	ld hl, OBJECT_FLAGS2
+	add hl, bc
+	set 2, [hl]
+
+	ld a, [wWalkingDirection]
+	ld d, a
+	ld hl, OBJECT_RANGE
+	add hl, bc
+	ld a, [hl]
+	and $fc
+	or d
+	ld [hl], a
+
+	scf
+	ret
+
+.not_boulder
+	xor a
+	ret
+; 8039e
+
+.CheckLandPerms: ; 8039e
+; Return 0 if walking onto land and tile permissions allow it.
+; Otherwise, return carry.
+
+	ld a, [wTilePermissions]
+	ld d, a
+	ld a, [wFacingDirection]
+	and d
+	jr nz, .NotWalkable
+
+	ld a, [wWalkingTile]
+	call .CheckWalkable
+	jr c, .NotWalkable
+
+	xor a
+	ret
+
+.NotWalkable:
+	scf
+	ret
+; 803b4
+
+.CheckSurfPerms: ; 803b4
+; Return 0 if moving in water, or 1 if moving onto land.
+; Otherwise, return carry.
+
+	ld a, [wTilePermissions]
+	ld d, a
+	ld a, [wFacingDirection]
+	and d
+	jr nz, .NotSurfable
+
+	ld a, [wWalkingTile]
+	call .CheckSurfable
+	jr c, .NotSurfable
+
+	and a
+	ret
+
+.NotSurfable:
+	scf
+	ret
+; 803ca
+
+.BikeCheck: ; 803ca
+	ld a, [wPlayerState]
+	cp PLAYER_BIKE
+	ret z
+	cp PLAYER_SKATE
+	ret
+; 803d3
+
+.CheckWalkable: ; 803d3
+; Return 0 if tile a is land. Otherwise, return carry.
+
+	call GetTileCollision
+	and a ; LANDTILE?
+	ret z
+	scf
+	ret
+; 803da
+
+.CheckSurfable: ; 803da
+; Return 0 if tile a is water, or 1 if land.
+; Otherwise, return carry.
+
+	call GetTileCollision
+	cp WATERTILE
+	jr z, .Water
+
+; Can walk back onto land from water.
+	and a ; LANDTILE?
+	jr z, .Land
+
+	jr .Neither
+
+.Water:
+	xor a
+	ret
+
+.Land:
+	ld a, 1
+	and a
+	ret
+
+.Neither:
+	scf
+	ret
+; 803ee
+
+.BumpSound: ; 803ee
+
+	call CheckSFX
+	ret c
+	ld de, SFX_BUMP
+	call PlaySFX
+	ret
+; 803f9
+
+.GetOutOfWater: ; 803f9
+	push bc
+	ld a, PLAYER_NORMAL
+	ld [wPlayerState], a
+	call ReplaceKrisSprite ; UpdateSprites
+	pop bc
+	ret
+; 80404
+
+CheckStandingOnIce:: ; 80404
+	ld a, [wPlayerTurningDirection]
+	cp 0
+	jr z, .not_ice
+	cp $f0
+	jr z, .not_ice
+	ld a, [wPlayerStandingTile]
+	call CheckIceTile
+	jr nc, .yep
+	ld a, [wPlayerState]
+	cp PLAYER_SKATE
+	jr nz, .not_ice
+
+.yep
+	scf
+	ret
+
+.not_ice
+	and a
+	ret
+; 80422
+
+StopPlayerForEvent:: ; 80422
+	ld hl, wPlayerNextMovement
+	ld a, movement_step_sleep
+	cp [hl]
+	ret z
+
+	ld [hl], a
+	ld a, 0
+	ld [wPlayerTurningDirection], a
+	ret
+; 80430
--- /dev/null
+++ b/engine/overworld/player_object.asm
@@ -1,0 +1,856 @@
+BlankScreen: ; 8000
+	call DisableSpriteUpdates
+	xor a
+	ld [hBGMapMode], a
+	call ClearBGPalettes
+	call ClearSprites
+	hlcoord 0, 0
+	ld bc, wTileMapEnd - wTileMap
+	ld a, " "
+	call ByteFill
+	hlcoord 0, 0, wAttrMap
+	ld bc, wAttrMapEnd - wAttrMap
+	ld a, $7
+	call ByteFill
+	call WaitBGMap2
+	call SetPalettes
+	ret
+
+SpawnPlayer: ; 8029
+	ld a, -1
+	ld [wObjectFollow_Leader], a
+	ld [wObjectFollow_Follower], a
+	ld a, $0
+	ld hl, PlayerObjectTemplate
+	call CopyPlayerObjectTemplate
+	ld b, $0
+	call PlayerSpawn_ConvertCoords
+	ld a, PLAYER_OBJECT
+	call GetMapObject
+	ld hl, MAPOBJECT_COLOR
+	add hl, bc
+	ln e, PAL_NPC_RED, OBJECTTYPE_SCRIPT
+	ld a, [wPlayerSpriteSetupFlags]
+	bit PLAYERSPRITESETUP_FEMALE_TO_MALE_F, a
+	jr nz, .ok
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .ok
+	ln e, PAL_NPC_BLUE, OBJECTTYPE_SCRIPT
+
+.ok
+	ld [hl], e
+	ld a, PLAYER_OBJECT
+	ld [hMapObjectIndexBuffer], a
+	ld bc, wMapObjects
+	ld a, PLAYER_OBJECT
+	ld [hObjectStructIndexBuffer], a
+	ld de, wObjectStructs
+	call CopyMapObjectToObjectStruct
+	ld a, PLAYER
+	ld [wCenteredObject], a
+	ret
+
+PlayerObjectTemplate: ; 8071
+; A dummy map object used to initialize the player object.
+; Shorter than the actual amount copied by two bytes.
+; Said bytes seem to be unused.
+	object_event -4, -4, SPRITE_CHRIS, SPRITEMOVEDATA_PLAYER, 15, 15, -1, -1, 0, OBJECTTYPE_SCRIPT, 0, 0, -1
+
+CopyDECoordsToMapObject:: ; 807e
+	push de
+	ld a, b
+	call GetMapObject
+	pop de
+	ld hl, MAPOBJECT_X_COORD
+	add hl, bc
+	ld [hl], d
+	ld hl, MAPOBJECT_Y_COORD
+	add hl, bc
+	ld [hl], e
+	ret
+
+PlayerSpawn_ConvertCoords: ; 808f
+	push bc
+	ld a, [wXCoord]
+	add 4
+	ld d, a
+	ld a, [wYCoord]
+	add 4
+	ld e, a
+	pop bc
+	call CopyDECoordsToMapObject
+	ret
+
+WriteObjectXY:: ; 80a1
+	ld a, b
+	call CheckObjectVisibility
+	ret c
+
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	ld a, [hMapObjectIndexBuffer]
+	ld b, a
+	call CopyDECoordsToMapObject
+	and a
+	ret
+
+RefreshPlayerCoords: ; 80b8
+	ld a, [wXCoord]
+	add 4
+	ld d, a
+	ld hl, wPlayerStandingMapX
+	sub [hl]
+	ld [hl], d
+	ld hl, wMapObjects + MAPOBJECT_X_COORD
+	ld [hl], d
+	ld hl, wPlayerLastMapX
+	ld [hl], d
+	ld d, a
+	ld a, [wYCoord]
+	add 4
+	ld e, a
+	ld hl, wPlayerStandingMapY
+	sub [hl]
+	ld [hl], e
+	ld hl, wMapObjects + MAPOBJECT_Y_COORD
+	ld [hl], e
+	ld hl, wPlayerLastMapY
+	ld [hl], e
+	ld e, a
+	ld a, [wObjectFollow_Leader]
+	cp $0
+	ret nz ; wtf
+	ret
+
+CopyObjectStruct:: ; 80e7
+	call CheckObjectMask
+	and a
+	ret nz ; masked
+
+	ld hl, wObjectStructs + OBJECT_STRUCT_LENGTH * 1
+	ld a, 1
+	ld de, OBJECT_STRUCT_LENGTH
+.loop
+	ld [hObjectStructIndexBuffer], a
+	ld a, [hl]
+	and a
+	jr z, .done
+	add hl, de
+	ld a, [hObjectStructIndexBuffer]
+	inc a
+	cp NUM_OBJECT_STRUCTS
+	jr nz, .loop
+	scf
+	ret ; overflow
+
+.done
+	ld d, h
+	ld e, l
+	call CopyMapObjectToObjectStruct
+	ld hl, wVramState
+	bit 7, [hl]
+	ret z
+
+	ld hl, OBJECT_FLAGS2
+	add hl, de
+	set 5, [hl]
+	ret
+
+CopyMapObjectToObjectStruct: ; 8116
+	call .CopyMapObjectToTempObject
+	call CopyTempObjectToObjectStruct
+	ret
+
+.CopyMapObjectToTempObject: ; 811d
+	ld a, [hObjectStructIndexBuffer]
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld [hl], a
+
+	ld a, [hMapObjectIndexBuffer]
+	ld [wTempObjectCopyMapObjectIndex], a
+
+	ld hl, MAPOBJECT_SPRITE
+	add hl, bc
+	ld a, [hl]
+	ld [wTempObjectCopySprite], a
+
+	call GetSpriteVTile
+	ld [wTempObjectCopySpriteVTile], a
+
+	ld a, [hl]
+	call GetSpritePalette
+	ld [wTempObjectCopyPalette], a
+
+	ld hl, MAPOBJECT_COLOR
+	add hl, bc
+	ld a, [hl]
+	and $f0
+	jr z, .skip_color_override
+	swap a
+	and PALETTE_MASK
+	ld [wTempObjectCopyPalette], a
+
+.skip_color_override
+	ld hl, MAPOBJECT_MOVEMENT
+	add hl, bc
+	ld a, [hl]
+	ld [wTempObjectCopyMovement], a
+
+	ld hl, MAPOBJECT_RANGE
+	add hl, bc
+	ld a, [hl]
+	ld [wTempObjectCopyRange], a
+
+	ld hl, MAPOBJECT_X_COORD
+	add hl, bc
+	ld a, [hl]
+	ld [wTempObjectCopyX], a
+
+	ld hl, MAPOBJECT_Y_COORD
+	add hl, bc
+	ld a, [hl]
+	ld [wTempObjectCopyY], a
+
+	ld hl, MAPOBJECT_RADIUS
+	add hl, bc
+	ld a, [hl]
+	ld [wTempObjectCopyRadius], a
+	ret
+
+InitializeVisibleSprites: ; 8177
+	ld bc, wMapObjects + OBJECT_LENGTH
+	ld a, 1
+.loop
+	ld [hMapObjectIndexBuffer], a
+	ld hl, MAPOBJECT_SPRITE
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .next
+
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	cp -1
+	jr nz, .next
+
+	ld a, [wXCoord]
+	ld d, a
+	ld a, [wYCoord]
+	ld e, a
+
+	ld hl, MAPOBJECT_X_COORD
+	add hl, bc
+	ld a, [hl]
+	add 1
+	sub d
+	jr c, .next
+
+	cp MAPOBJECT_SCREEN_WIDTH
+	jr nc, .next
+
+	ld hl, MAPOBJECT_Y_COORD
+	add hl, bc
+	ld a, [hl]
+	add 1
+	sub e
+	jr c, .next
+
+	cp MAPOBJECT_SCREEN_HEIGHT
+	jr nc, .next
+
+	push bc
+	call CopyObjectStruct
+	pop bc
+	jp c, .ret
+
+.next
+	ld hl, OBJECT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	ld a, [hMapObjectIndexBuffer]
+	inc a
+	cp NUM_OBJECTS
+	jr nz, .loop
+	ret
+
+.ret ; 81c9
+	ret
+
+CheckObjectEnteringVisibleRange:: ; 81ca
+	nop
+	ld a, [wPlayerStepDirection]
+	cp STANDING
+	ret z
+	ld hl, .dw
+	rst JumpTable
+	ret
+
+.dw ; 81d6
+	dw .Down
+	dw .Up
+	dw .Left
+	dw .Right
+
+.Up: ; 81de
+	ld a, [wYCoord]
+	sub 1
+	jr .Vertical
+
+.Down: ; 81e5
+	ld a, [wYCoord]
+	add 9
+.Vertical: ; 81ea
+	ld d, a
+	ld a, [wXCoord]
+	ld e, a
+	ld bc, wMapObjects + OBJECT_LENGTH
+	ld a, 1
+.loop_v
+	ld [hMapObjectIndexBuffer], a
+	ld hl, MAPOBJECT_SPRITE
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .next_v
+	ld hl, MAPOBJECT_Y_COORD
+	add hl, bc
+	ld a, d
+	cp [hl]
+	jr nz, .next_v
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	cp -1
+	jr nz, .next_v
+	ld hl, MAPOBJECT_X_COORD
+	add hl, bc
+	ld a, [hl]
+	add 1
+	sub e
+	jr c, .next_v
+	cp MAPOBJECT_SCREEN_WIDTH
+	jr nc, .next_v
+	push de
+	push bc
+	call CopyObjectStruct
+	pop bc
+	pop de
+
+.next_v
+	ld hl, OBJECT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	ld a, [hMapObjectIndexBuffer]
+	inc a
+	cp NUM_OBJECTS
+	jr nz, .loop_v
+	ret
+
+.Left: ; 8232
+	ld a, [wXCoord]
+	sub 1
+	jr .Horizontal
+
+.Right: ; 8239
+	ld a, [wXCoord]
+	add 10
+.Horizontal: ; 823e
+	ld e, a
+	ld a, [wYCoord]
+	ld d, a
+	ld bc, wMapObjects + OBJECT_LENGTH
+	ld a, 1
+.loop_h
+	ld [hMapObjectIndexBuffer], a
+	ld hl, MAPOBJECT_SPRITE
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .next_h
+	ld hl, MAPOBJECT_X_COORD
+	add hl, bc
+	ld a, e
+	cp [hl]
+	jr nz, .next_h
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	cp -1
+	jr nz, .next_h
+	ld hl, MAPOBJECT_Y_COORD
+	add hl, bc
+	ld a, [hl]
+	add 1
+	sub d
+	jr c, .next_h
+	cp MAPOBJECT_SCREEN_HEIGHT
+	jr nc, .next_h
+	push de
+	push bc
+	call CopyObjectStruct
+	pop bc
+	pop de
+
+.next_h
+	ld hl, OBJECT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	ld a, [hMapObjectIndexBuffer]
+	inc a
+	cp NUM_OBJECTS
+	jr nz, .loop_h
+	ret
+
+CopyTempObjectToObjectStruct: ; 8286
+	ld a, [wTempObjectCopyMapObjectIndex]
+	ld hl, OBJECT_MAP_OBJECT_INDEX
+	add hl, de
+	ld [hl], a
+
+	ld a, [wTempObjectCopyMovement]
+	call CopySpriteMovementData
+
+	ld a, [wTempObjectCopyPalette]
+	ld hl, OBJECT_PALETTE
+	add hl, de
+	or [hl]
+	ld [hl], a
+
+	ld a, [wTempObjectCopyY]
+	call .InitYCoord
+
+	ld a, [wTempObjectCopyX]
+	call .InitXCoord
+
+	ld a, [wTempObjectCopySprite]
+	ld hl, OBJECT_SPRITE
+	add hl, de
+	ld [hl], a
+
+	ld a, [wTempObjectCopySpriteVTile]
+	ld hl, OBJECT_SPRITE_TILE
+	add hl, de
+	ld [hl], a
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, de
+	ld [hl], STEP_TYPE_00
+
+	ld hl, OBJECT_FACING_STEP
+	add hl, de
+	ld [hl], STANDING
+
+	ld a, [wTempObjectCopyRadius]
+	call .InitRadius
+
+	ld a, [wTempObjectCopyRange]
+	ld hl, OBJECT_RANGE
+	add hl, de
+	ld [hl], a
+
+	and a
+	ret
+
+.InitYCoord: ; 82d5
+	ld hl, OBJECT_INIT_Y
+	add hl, de
+	ld [hl], a
+
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, de
+	ld [hl], a
+
+	ld hl, wYCoord
+	sub [hl]
+	and $f
+	swap a
+	ld hl, wPlayerBGMapOffsetY
+	sub [hl]
+	ld hl, OBJECT_SPRITE_Y
+	add hl, de
+	ld [hl], a
+	ret
+
+.InitXCoord: ; 82f1
+	ld hl, OBJECT_INIT_X
+	add hl, de
+	ld [hl], a
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, de
+	ld [hl], a
+	ld hl, wXCoord
+	sub [hl]
+	and $f
+	swap a
+	ld hl, wPlayerBGMapOffsetX
+	sub [hl]
+	ld hl, OBJECT_SPRITE_X
+	add hl, de
+	ld [hl], a
+	ret
+
+.InitRadius: ; 830d
+	ld h, a
+	inc a
+	and $f
+	ld l, a
+	ld a, h
+	add $10
+	and $f0
+	or l
+	ld hl, OBJECT_RADIUS
+	add hl, de
+	ld [hl], a
+	ret
+
+TrainerWalkToPlayer: ; 831e
+	ld a, [hLastTalked]
+	call InitMovementBuffer
+	ld a, movement_step_sleep
+	call AppendToMovementBuffer
+	ld a, [wd03f]
+	dec a
+	jr z, .TerminateStep
+	ld a, [hLastTalked]
+	ld b, a
+	ld c, PLAYER
+	ld d, 1
+	call .GetPathToPlayer
+	call DecrementMovementBufferCount
+
+.TerminateStep:
+	ld a, movement_step_end
+	call AppendToMovementBuffer
+	ret
+
+.GetPathToPlayer: ; 8341
+	push de
+	push bc
+; get player object struct, load to de
+	ld a, c
+	call GetMapObject
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	call GetObjectStruct
+	ld d, b
+	ld e, c
+
+; get last talked object struct, load to bc
+	pop bc
+	ld a, b
+	call GetMapObject
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	call GetObjectStruct
+
+; get last talked coords, load to bc
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld c, [hl]
+	ld b, a
+
+; get player coords, load to de
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, de
+	ld a, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, de
+	ld e, [hl]
+	ld d, a
+
+	pop af
+	call ComputePathToWalkToPlayer
+	ret
+
+SurfStartStep: ; 8379
+	call InitMovementBuffer
+	call .GetMovementData
+	call AppendToMovementBuffer
+	ld a, movement_step_end
+	call AppendToMovementBuffer
+	ret
+
+.GetMovementData: ; 8388
+	ld a, [wPlayerDirection]
+	srl a
+	srl a
+	maskbits NUM_DIRECTIONS
+	ld e, a
+	ld d, 0
+	ld hl, .movement_data
+	add hl, de
+	ld a, [hl]
+	ret
+
+.movement_data
+	slow_step DOWN
+	slow_step UP
+	slow_step LEFT
+	slow_step RIGHT
+
+FollowNotExact:: ; 839e
+	push bc
+	ld a, c
+	call CheckObjectVisibility
+	ld d, b
+	ld e, c
+	pop bc
+	ret c
+
+	ld a, b
+	call CheckObjectVisibility
+	ret c
+
+; object 2 is now in bc, object 1 is now in de
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld c, [hl]
+	ld b, a
+
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, de
+	ld a, [hl]
+	cp b
+	jr z, .same_x
+	jr c, .to_the_left
+	inc b
+	jr .continue
+
+.to_the_left
+	dec b
+	jr .continue
+
+.same_x
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, de
+	ld a, [hl]
+	cp c
+	jr z, .continue
+	jr c, .below
+	inc c
+	jr .continue
+
+.below
+	dec c
+
+.continue
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, de
+	ld [hl], b
+	ld a, b
+	ld hl, wXCoord
+	sub [hl]
+	and $f
+	swap a
+	ld hl, wPlayerBGMapOffsetX
+	sub [hl]
+	ld hl, OBJECT_SPRITE_X
+	add hl, de
+	ld [hl], a
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, de
+	ld [hl], c
+	ld a, c
+	ld hl, wYCoord
+	sub [hl]
+	and $f
+	swap a
+	ld hl, wPlayerBGMapOffsetY
+	sub [hl]
+	ld hl, OBJECT_SPRITE_Y
+	add hl, de
+	ld [hl], a
+	ld a, [hObjectStructIndexBuffer]
+	ld hl, OBJECT_RANGE
+	add hl, de
+	ld [hl], a
+	ld hl, OBJECT_MOVEMENTTYPE
+	add hl, de
+	ld [hl], SPRITEMOVEDATA_FOLLOWNOTEXACT
+	ld hl, OBJECT_STEP_TYPE
+	add hl, de
+	ld [hl], STEP_TYPE_00
+	ret
+
+GetRelativeFacing:: ; 8417
+; Determines which way map object e would have to turn to face map object d.  Returns carry if it's impossible for whatever reason.
+	ld a, d
+	call GetMapObject
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	cp NUM_OBJECT_STRUCTS
+	jr nc, .carry
+	ld d, a
+	ld a, e
+	call GetMapObject
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	cp NUM_OBJECT_STRUCTS
+	jr nc, .carry
+	ld e, a
+	call .GetFacing_e_relativeto_d
+	ret
+
+.carry
+	scf
+	ret
+
+.GetFacing_e_relativeto_d: ; 8439
+; Determines which way object e would have to turn to face object d.  Returns carry if it's impossible.
+; load the coordinates of object d into bc
+	ld a, d
+	call GetObjectStruct
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld c, [hl]
+	ld b, a
+	push bc
+; load the coordinates of object e into de
+	ld a, e
+	call GetObjectStruct
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	pop bc
+; |x1 - x2|
+	ld a, b
+	sub d
+	jr z, .same_x_1
+	jr nc, .b_right_of_d_1
+	cpl
+	inc a
+
+.b_right_of_d_1
+; |y1 - y2|
+	ld h, a
+	ld a, c
+	sub e
+	jr z, .same_y_1
+	jr nc, .c_below_e_1
+	cpl
+	inc a
+
+.c_below_e_1
+; |y1 - y2| - |x1 - x2|
+	sub h
+	jr c, .same_y_1
+
+.same_x_1
+; compare the y coordinates
+	ld a, c
+	cp e
+	jr z, .same_x_and_y
+	jr c, .c_directly_below_e
+; c directly above e
+	ld d, DOWN
+	and a
+	ret
+
+.c_directly_below_e
+	ld d, UP
+	and a
+	ret
+
+.same_y_1
+	ld a, b
+	cp d
+	jr z, .same_x_and_y
+	jr c, .b_directly_right_of_d
+; b directly left of d
+	ld d, RIGHT
+	and a
+	ret
+
+.b_directly_right_of_d
+	ld d, LEFT
+	and a
+	ret
+
+.same_x_and_y
+	scf
+	ret
+
+QueueFollowerFirstStep: ; 848a
+	call .QueueFirstStep
+	jr c, .same
+	ld [wFollowMovementQueue], a
+	xor a
+	ld [wFollowerMovementQueueLength], a
+	ret
+
+.same
+	ld a, -1
+	ld [wFollowerMovementQueueLength], a
+	ret
+
+.QueueFirstStep:
+	ld a, [wObjectFollow_Leader]
+	call GetObjectStruct
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	ld a, [wObjectFollow_Follower]
+	call GetObjectStruct
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, d
+	cp [hl]
+	jr z, .check_y
+	jr c, .left
+	and a
+	ld a, movement_step + RIGHT
+	ret
+
+.left
+	and a
+	ld a, movement_step + LEFT
+	ret
+
+.check_y
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld a, e
+	cp [hl]
+	jr z, .same_xy
+	jr c, .up
+	and a
+	ld a, movement_step + DOWN
+	ret
+
+.up
+	and a
+	ld a, movement_step + UP
+	ret
+
+.same_xy
+	scf
+	ret
--- /dev/null
+++ b/engine/overworld/player_step.asm
@@ -1,0 +1,270 @@
+_HandlePlayerStep:: ; d497 (3:5497)
+	ld a, [wPlayerStepFlags]
+	and a
+	ret z
+	bit 7, a ; starting step
+	jr nz, .update_overworld_map
+	bit 6, a ; finishing step
+	jr nz, .update_player_coords
+	bit 5, a ; ongoing step
+	jr nz, .finish
+	ret
+
+.update_overworld_map
+	ld a, 4
+	ld [wHandlePlayerStep], a
+	call UpdateOverworldMap
+	jr .finish
+
+.update_player_coords
+	call UpdatePlayerCoords
+	jr .finish
+
+.finish
+	call HandlePlayerStep
+	ld a, [wPlayerStepVectorX]
+	ld d, a
+	ld a, [wPlayerStepVectorY]
+	ld e, a
+	ld a, [wPlayerBGMapOffsetX]
+	sub d
+	ld [wPlayerBGMapOffsetX], a
+	ld a, [wPlayerBGMapOffsetY]
+	sub e
+	ld [wPlayerBGMapOffsetY], a
+	ret
+
+ScrollScreen:: ; d4d2 (3:54d2)
+	ld a, [wPlayerStepVectorX]
+	ld d, a
+	ld a, [wPlayerStepVectorY]
+	ld e, a
+	ld a, [hSCX]
+	add d
+	ld [hSCX], a
+	ld a, [hSCY]
+	add e
+	ld [hSCY], a
+	ret
+
+HandlePlayerStep: ; d4e5 (3:54e5)
+	ld hl, wHandlePlayerStep
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+	ld a, [hl]
+	ld hl, .Jumptable
+	rst JumpTable
+	ret
+
+.Jumptable: ; d4f2 (3:54f2)
+	dw GetMovementPermissions
+	dw BufferScreen
+	dw .mobile
+	dw .fail2
+; The rest are never used.  Ever.
+	dw .fail1
+	dw .fail1
+	dw .fail1
+	dw .fail1
+	dw .fail1
+	dw .fail1
+	dw .fail1
+
+.fail1 ; d508 (3:5508)
+	ret
+
+.mobile ; d509 (3:5509)
+	farcall StubbedTrainerRankings_StepCount
+	ret
+
+.fail2 ; d510 (3:5510)
+	ret
+
+UpdatePlayerCoords: ; d511 (3:5511)
+	ld a, [wPlayerStepDirection]
+	and a
+	jr nz, .check_step_down
+	ld hl, wYCoord
+	inc [hl]
+	ret
+
+.check_step_down
+	cp UP
+	jr nz, .check_step_left
+	ld hl, wYCoord
+	dec [hl]
+	ret
+
+.check_step_left
+	cp LEFT
+	jr nz, .check_step_right
+	ld hl, wXCoord
+	dec [hl]
+	ret
+
+.check_step_right
+	cp RIGHT
+	ret nz
+	ld hl, wXCoord
+	inc [hl]
+	ret
+
+UpdateOverworldMap: ; d536 (3:5536)
+	ld a, [wPlayerStepDirection]
+	and a
+	jr z, .step_down
+	cp UP
+	jr z, .step_up
+	cp LEFT
+	jr z, .step_left
+	cp RIGHT
+	jr z, .step_right
+	ret
+
+.step_down
+	call .ScrollOverworldMapDown
+	call LoadMapPart
+	call ScrollMapUp
+	ret
+
+.step_up
+	call .ScrollOverworldMapUp
+	call LoadMapPart
+	call ScrollMapDown
+	ret
+
+.step_left
+	call .ScrollOverworldMapLeft
+	call LoadMapPart
+	call ScrollMapRight
+	ret
+
+.step_right
+	call .ScrollOverworldMapRight
+	call LoadMapPart
+	call ScrollMapLeft
+	ret
+
+.ScrollOverworldMapDown: ; d571 (3:5571)
+	ld a, [wBGMapAnchor]
+	add 2 * BG_MAP_WIDTH
+	ld [wBGMapAnchor], a
+	jr nc, .not_overflowed
+	ld a, [wBGMapAnchor + 1]
+	inc a
+	and %11
+	or HIGH(vBGMap0)
+	ld [wBGMapAnchor + 1], a
+.not_overflowed
+	ld hl, wMetatileStandingY
+	inc [hl]
+	ld a, [hl]
+	cp 2 ; was 1
+	jr nz, .done_down
+	ld [hl], 0
+	call .Add6ToOverworldMapAnchor
+.done_down
+	ret
+
+.Add6ToOverworldMapAnchor: ; d595 (3:5595)
+	ld hl, wOverworldMapAnchor
+	ld a, [wMapWidth]
+	add 6
+	add [hl]
+	ld [hli], a
+	ret nc
+	inc [hl]
+	ret
+
+.ScrollOverworldMapUp: ; d5a2 (3:55a2)
+	ld a, [wBGMapAnchor]
+	sub 2 * BG_MAP_WIDTH
+	ld [wBGMapAnchor], a
+	jr nc, .not_underflowed
+	ld a, [wBGMapAnchor + 1]
+	dec a
+	and %11
+	or HIGH(vBGMap0)
+	ld [wBGMapAnchor + 1], a
+.not_underflowed
+	ld hl, wMetatileStandingY
+	dec [hl]
+	ld a, [hl]
+	cp -1 ; was 0
+	jr nz, .done_up
+	ld [hl], $1
+	call .Sub6FromOverworldMapAnchor
+.done_up
+	ret
+
+.Sub6FromOverworldMapAnchor: ; d5c6 (3:55c6)
+	ld hl, wOverworldMapAnchor
+	ld a, [wMapWidth]
+	add 6
+	ld b, a
+	ld a, [hl]
+	sub b
+	ld [hli], a
+	ret nc
+	dec [hl]
+	ret
+
+.ScrollOverworldMapLeft: ; d5d5 (3:55d5)
+	ld a, [wBGMapAnchor]
+	ld e, a
+	and $e0
+	ld d, a
+	ld a, e
+	sub $2
+	and $1f
+	or d
+	ld [wBGMapAnchor], a
+	ld hl, wMetatileStandingX
+	dec [hl]
+	ld a, [hl]
+	cp -1
+	jr nz, .done_left
+	ld [hl], 1
+	call .DecrementwOverworldMapAnchor
+.done_left
+	ret
+
+.DecrementwOverworldMapAnchor: ; d5f4 (3:55f4)
+	ld hl, wOverworldMapAnchor
+	ld a, [hl]
+	sub 1
+	ld [hli], a
+	ret nc
+	dec [hl]
+	ret
+
+.ScrollOverworldMapRight: ; d5fe (3:55fe)
+	ld a, [wBGMapAnchor]
+	ld e, a
+	and $e0
+	ld d, a
+	ld a, e
+	add $2
+	and $1f
+	or d
+	ld [wBGMapAnchor], a
+	ld hl, wMetatileStandingX
+	inc [hl]
+	ld a, [hl]
+	cp 2
+	jr nz, .done_right
+	ld [hl], 0
+	call .IncrementwOverworldMapAnchor
+.done_right
+	ret
+
+.IncrementwOverworldMapAnchor: ; d61d (3:561d)
+	ld hl, wOverworldMapAnchor
+	ld a, [hl]
+	add 1
+	ld [hli], a
+	ret nc
+	inc [hl]
+	ret
--- /dev/null
+++ b/engine/overworld/scripting.asm
@@ -1,0 +1,2857 @@
+; Event scripting commands.
+
+
+EnableScriptMode::
+	push af
+	ld a, SCRIPT_READ
+	ld [wScriptMode], a
+	pop af
+	ret
+
+ScriptEvents::
+	call StartScript
+.loop
+	ld a, [wScriptMode]
+	ld hl, .modes
+	rst JumpTable
+	call CheckScript
+	jr nz, .loop
+	ret
+
+.modes
+	dw EndScript
+	dw RunScriptCommand
+	dw WaitScriptMovement
+	dw WaitScript
+
+EndScript:
+	call StopScript
+	ret
+
+WaitScript:
+	call StopScript
+
+	ld hl, wScriptDelay
+	dec [hl]
+	ret nz
+
+	farcall Function58b9
+
+	ld a, SCRIPT_READ
+	ld [wScriptMode], a
+	call StartScript
+	ret
+
+WaitScriptMovement:
+	call StopScript
+
+	ld hl, wVramState
+	bit 7, [hl]
+	ret nz
+
+	farcall Function58b9
+
+	ld a, SCRIPT_READ
+	ld [wScriptMode], a
+	call StartScript
+	ret
+
+RunScriptCommand:
+	call GetScriptByte
+	ld hl, ScriptCommandTable
+	rst JumpTable
+	ret
+
+
+ScriptCommandTable:
+; entries correspond to macros/scripts/events.asm enumeration
+	dw Script_scall                      ; 00
+	dw Script_farscall                   ; 01
+	dw Script_ptcall                     ; 02
+	dw Script_jump                       ; 03
+	dw Script_farjump                    ; 04
+	dw Script_ptjump                     ; 05
+	dw Script_ifequal                    ; 06
+	dw Script_ifnotequal                 ; 07
+	dw Script_iffalse                    ; 08
+	dw Script_iftrue                     ; 09
+	dw Script_ifgreater                  ; 0a
+	dw Script_ifless                     ; 0b
+	dw Script_jumpstd                    ; 0c
+	dw Script_callstd                    ; 0d
+	dw Script_callasm                    ; 0e
+	dw Script_special                    ; 0f
+	dw Script_ptcallasm                  ; 10
+	dw Script_checkmapscene              ; 11
+	dw Script_setmapscene                ; 12
+	dw Script_checkscene                 ; 13
+	dw Script_setscene                   ; 14
+	dw Script_writebyte                  ; 15
+	dw Script_addvar                     ; 16
+	dw Script_random                     ; 17
+	dw Script_checkver                   ; 18
+	dw Script_copybytetovar              ; 19
+	dw Script_copyvartobyte              ; 1a
+	dw Script_loadvar                    ; 1b
+	dw Script_checkcode                  ; 1c
+	dw Script_writevarcode               ; 1d
+	dw Script_writecode                  ; 1e
+	dw Script_giveitem                   ; 1f
+	dw Script_takeitem                   ; 20
+	dw Script_checkitem                  ; 21
+	dw Script_givemoney                  ; 22
+	dw Script_takemoney                  ; 23
+	dw Script_checkmoney                 ; 24
+	dw Script_givecoins                  ; 25
+	dw Script_takecoins                  ; 26
+	dw Script_checkcoins                 ; 27
+	dw Script_addcellnum                 ; 28
+	dw Script_delcellnum                 ; 29
+	dw Script_checkcellnum               ; 2a
+	dw Script_checktime                  ; 2b
+	dw Script_checkpoke                  ; 2c
+	dw Script_givepoke                   ; 2d
+	dw Script_giveegg                    ; 2e
+	dw Script_givepokeitem               ; 2f
+	dw Script_checkpokeitem              ; 30
+	dw Script_checkevent                 ; 31
+	dw Script_clearevent                 ; 32
+	dw Script_setevent                   ; 33
+	dw Script_checkflag                  ; 34
+	dw Script_clearflag                  ; 35
+	dw Script_setflag                    ; 36
+	dw Script_wildon                     ; 37
+	dw Script_wildoff                    ; 38
+	dw Script_xycompare                  ; 39
+	dw Script_warpmod                    ; 3a
+	dw Script_blackoutmod                ; 3b
+	dw Script_warp                       ; 3c
+	dw Script_readmoney                  ; 3d
+	dw Script_readcoins                  ; 3e
+	dw Script_vartomem                   ; 3f
+	dw Script_pokenamemem                ; 40
+	dw Script_itemtotext                 ; 41
+	dw Script_mapnametotext              ; 42
+	dw Script_trainertotext              ; 43
+	dw Script_stringtotext               ; 44
+	dw Script_itemnotify                 ; 45
+	dw Script_pocketisfull               ; 46
+	dw Script_opentext                   ; 47
+	dw Script_refreshscreen              ; 48
+	dw Script_closetext                  ; 49
+	dw Script_loadbytec2cf               ; 4a
+	dw Script_farwritetext               ; 4b
+	dw Script_writetext                  ; 4c
+	dw Script_repeattext                 ; 4d
+	dw Script_yesorno                    ; 4e
+	dw Script_loadmenu                   ; 4f
+	dw Script_closewindow                ; 50
+	dw Script_jumptextfaceplayer         ; 51
+if _CRYSTAL
+	dw Script_farjumptext                ; 52
+endc
+	dw Script_jumptext                   ; 53
+	dw Script_waitbutton                 ; 54
+	dw Script_buttonsound                ; 55
+	dw Script_pokepic                    ; 56
+	dw Script_closepokepic               ; 57
+	dw Script__2dmenu                    ; 58
+	dw Script_verticalmenu               ; 59
+	dw Script_loadpikachudata            ; 5a
+	dw Script_randomwildmon              ; 5b
+	dw Script_loadmemtrainer             ; 5c
+	dw Script_loadwildmon                ; 5d
+	dw Script_loadtrainer                ; 5e
+	dw Script_startbattle                ; 5f
+	dw Script_reloadmapafterbattle       ; 60
+	dw Script_catchtutorial              ; 61
+	dw Script_trainertext                ; 62
+	dw Script_trainerflagaction          ; 63
+	dw Script_winlosstext                ; 64
+	dw Script_scripttalkafter            ; 65
+	dw Script_endifjustbattled           ; 66
+	dw Script_checkjustbattled           ; 67
+	dw Script_setlasttalked              ; 68
+	dw Script_applymovement              ; 69
+	dw Script_applymovement2             ; 6a
+	dw Script_faceplayer                 ; 6b
+	dw Script_faceobject                 ; 6c
+	dw Script_variablesprite             ; 6d
+	dw Script_disappear                  ; 6e
+	dw Script_appear                     ; 6f
+	dw Script_follow                     ; 70
+	dw Script_stopfollow                 ; 71
+	dw Script_moveobject                 ; 72
+	dw Script_writeobjectxy              ; 73
+	dw Script_loademote                  ; 74
+	dw Script_showemote                  ; 75
+	dw Script_turnobject                 ; 76
+	dw Script_follownotexact             ; 77
+	dw Script_earthquake                 ; 78
+	dw Script_changemap                  ; 79
+	dw Script_changeblock                ; 7a
+	dw Script_reloadmap                  ; 7b
+	dw Script_reloadmappart              ; 7c
+	dw Script_writecmdqueue              ; 7d
+	dw Script_delcmdqueue                ; 7e
+	dw Script_playmusic                  ; 7f
+	dw Script_encountermusic             ; 80
+	dw Script_musicfadeout               ; 81
+	dw Script_playmapmusic               ; 82
+	dw Script_dontrestartmapmusic        ; 83
+	dw Script_cry                        ; 84
+	dw Script_playsound                  ; 85
+	dw Script_waitsfx                    ; 86
+	dw Script_warpsound                  ; 87
+	dw Script_specialsound               ; 88
+	dw Script_passtoengine               ; 89
+	dw Script_newloadmap                 ; 8a
+	dw Script_pause                      ; 8b
+	dw Script_deactivatefacing           ; 8c
+	dw Script_priorityjump               ; 8d
+	dw Script_warpcheck                  ; 8e
+	dw Script_ptpriorityjump             ; 8f
+	dw Script_return                     ; 90
+	dw Script_end                        ; 91
+	dw Script_reloadandreturn            ; 92
+	dw Script_endall                     ; 93
+	dw Script_pokemart                   ; 94
+	dw Script_elevator                   ; 95
+	dw Script_trade                      ; 96
+	dw Script_askforphonenumber          ; 97
+	dw Script_phonecall                  ; 98
+	dw Script_hangup                     ; 99
+	dw Script_describedecoration         ; 9a
+	dw Script_fruittree                  ; 9b
+	dw Script_specialphonecall           ; 9c
+	dw Script_checkphonecall             ; 9d
+	dw Script_verbosegiveitem            ; 9e
+	dw Script_verbosegiveitem2           ; 9f
+	dw Script_swarm                      ; a0
+	dw Script_halloffame                 ; a1
+	dw Script_credits                    ; a2
+	dw Script_warpfacing                 ; a3
+	dw Script_battletowertext            ; a4
+	dw Script_landmarktotext             ; a5
+	dw Script_trainerclassname           ; a6
+	dw Script_name                       ; a7
+	dw Script_wait                       ; a8
+	dw Script_checksave                  ; a9
+
+StartScript:
+	ld hl, wScriptFlags
+	set SCRIPT_RUNNING, [hl]
+	ret
+
+CheckScript:
+	ld hl, wScriptFlags
+	bit SCRIPT_RUNNING, [hl]
+	ret
+
+StopScript:
+	ld hl, wScriptFlags
+	res SCRIPT_RUNNING, [hl]
+	ret
+
+Script_callasm:
+; script command 0xe
+; parameters: asm
+
+	call GetScriptByte
+	ld b, a
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	ld a, b
+	rst FarCall
+	ret
+
+Script_special:
+; script command 0xf
+; parameters: predefined_script
+
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	farcall Special
+	ret
+
+Script_ptcallasm:
+; script command 0x10
+; parameters: asm
+
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	ld b, [hl]
+	inc hl
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, b
+	rst FarCall
+	ret
+
+Script_jumptextfaceplayer:
+; script command 0x51
+; parameters: text_pointer
+
+	ld a, [wScriptBank]
+	ld [wScriptTextBank], a
+	call GetScriptByte
+	ld [wScriptTextAddr], a
+	call GetScriptByte
+	ld [wScriptTextAddr + 1], a
+	ld b, BANK(JumpTextFacePlayerScript)
+	ld hl, JumpTextFacePlayerScript
+	jp ScriptJump
+
+Script_jumptext:
+; script command 0x53
+; parameters: text_pointer
+
+	ld a, [wScriptBank]
+	ld [wScriptTextBank], a
+	call GetScriptByte
+	ld [wScriptTextAddr], a
+	call GetScriptByte
+	ld [wScriptTextAddr + 1], a
+	ld b, BANK(JumpTextScript)
+	ld hl, JumpTextScript
+	jp ScriptJump
+
+JumpTextFacePlayerScript:
+	faceplayer
+JumpTextScript:
+	opentext
+	repeattext -1, -1
+	waitbutton
+	closetext
+	end
+
+
+if _CRYSTAL
+
+Script_farjumptext:
+; script command 0x52
+; parameters: text_pointer
+
+	call GetScriptByte
+	ld [wScriptTextBank], a
+	call GetScriptByte
+	ld [wScriptTextAddr], a
+	call GetScriptByte
+	ld [wScriptTextAddr + 1], a
+	ld b, BANK(JumpTextScript)
+	ld hl, JumpTextScript
+	jp ScriptJump
+
+endc
+
+
+Script_writetext:
+; script command 0x4c
+; parameters: text_pointer
+
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	ld a, [wScriptBank]
+	ld b, a
+	call MapTextbox
+	ret
+
+Script_farwritetext:
+; script command 0x4b
+; parameters: text_pointer
+
+	call GetScriptByte
+	ld b, a
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	call MapTextbox
+	ret
+
+Script_repeattext:
+; script command 0x4d
+; parameters: byte, byte
+
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	cp -1
+	jr nz, .done
+	ld a, l
+	cp -1
+	jr nz, .done
+	ld hl, wScriptTextBank
+	ld a, [hli]
+	ld b, a
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	call MapTextbox
+	ret
+
+.done
+	ret
+
+Script_waitbutton:
+; script command 0x54
+
+	jp WaitButton
+
+Script_buttonsound:
+; script command 0x55
+
+	ld a, [hOAMUpdate]
+	push af
+	ld a, $1
+	ld [hOAMUpdate], a
+	call WaitBGMap
+	call ButtonSound
+	pop af
+	ld [hOAMUpdate], a
+	ret
+
+Script_yesorno:
+; script command 0x4e
+
+	call YesNoBox
+	ld a, FALSE
+	jr c, .no
+	ld a, TRUE
+.no
+	ld [wScriptVar], a
+	ret
+
+Script_loadmenu:
+; script command 0x4f
+; parameters: menu_header
+
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	ld de, LoadMenuHeader
+	ld a, [wScriptBank]
+	call Call_a_de
+	call UpdateSprites
+	ret
+
+Script_closewindow:
+; script command 0x50
+
+	call CloseWindow
+	call UpdateSprites
+	ret
+
+Script_pokepic:
+; script command 0x56
+; parameters: pokemon
+
+	call GetScriptByte
+	and a
+	jr nz, .ok
+	ld a, [wScriptVar]
+.ok
+	ld [wCurPartySpecies], a
+	farcall Pokepic
+	ret
+
+Script_closepokepic:
+; script command 0x57
+
+	farcall ClosePokepic
+	ret
+
+Script_verticalmenu:
+; script command 0x59
+
+	ld a, [wScriptBank]
+	ld hl, VerticalMenu
+	rst FarCall
+	ld a, [wMenuCursorY]
+	jr nc, .ok
+	xor a
+.ok
+	ld [wScriptVar], a
+	ret
+
+Script__2dmenu:
+; script command 0x58
+
+	ld a, [wScriptBank]
+	ld hl, _2DMenu
+	rst FarCall
+	ld a, [wMenuCursorBuffer]
+	jr nc, .ok
+	xor a
+.ok
+	ld [wScriptVar], a
+	ret
+
+Script_battletowertext:
+; script command 0xa4
+; parameters: pointer, memory
+
+	call SetUpTextBox
+	call GetScriptByte
+	ld c, a
+	farcall BattleTowerText
+	ret
+
+Script_verbosegiveitem:
+; script command 0x9e
+; parameters: item, quantity
+
+	call Script_giveitem
+	call CurItemName
+	ld de, wStringBuffer1
+	ld a, 1
+	call CopyConvertedText
+	ld b, BANK(GiveItemScript)
+	ld de, GiveItemScript
+	jp ScriptCall
+
+
+ret_96f76:
+	ret
+
+GiveItemScript:
+	callasm ret_96f76
+	writetext ReceivedItemText
+	iffalse .Full
+	waitsfx
+	specialsound
+	waitbutton
+	itemnotify
+	end
+
+.Full:
+	buttonsound
+	pocketisfull
+	end
+
+ReceivedItemText:
+	text_jump UnknownText_0x1c4719
+	db "@"
+
+
+Script_verbosegiveitem2:
+; script command 0x9f
+; parameters: item, var
+
+	call GetScriptByte
+	cp -1
+	jr nz, .ok
+	ld a, [wScriptVar]
+.ok
+	ld [wCurItem], a
+	call GetScriptByte
+	call GetVarAction
+	ld a, [de]
+	ld [wItemQuantityChangeBuffer], a
+	ld hl, wNumItems
+	call ReceiveItem
+	ld a, TRUE
+	jr c, .ok2
+	xor a
+.ok2
+	ld [wScriptVar], a
+	call CurItemName
+	ld de, wStringBuffer1
+	ld a, 1
+	call CopyConvertedText
+	ld b, BANK(GiveItemScript)
+	ld de, GiveItemScript
+	jp ScriptCall
+
+Script_itemnotify:
+; script command 0x45
+
+	call GetPocketName
+	call CurItemName
+	ld b, BANK(PutItemInPocketText)
+	ld hl, PutItemInPocketText
+	call MapTextbox
+	ret
+
+Script_pocketisfull:
+; script command 0x46
+
+	call GetPocketName
+	call CurItemName
+	ld b, BANK(PocketIsFullText)
+	ld hl, PocketIsFullText
+	call MapTextbox
+	ret
+
+Script_specialsound:
+; script command 0x88
+
+	farcall CheckItemPocket
+	ld a, [wItemAttributeParamBuffer]
+	cp TM_HM
+	ld de, SFX_GET_TM
+	jr z, .play
+	ld de, SFX_ITEM
+.play
+	call PlaySFX
+	call WaitSFX
+	ret
+
+
+GetPocketName:
+	farcall CheckItemPocket
+	ld a, [wItemAttributeParamBuffer]
+	dec a
+	ld hl, .Pockets
+	maskbits NUM_POCKETS
+	add a
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+	ld hl, wStringBuffer3
+	call CopyName2
+	ret
+
+.Pockets:
+	dw .Item
+	dw .Key
+	dw .Ball
+	dw .TM
+
+.Item:
+	db "ITEM POCKET@"
+.Key:
+	db "KEY POCKET@"
+.Ball:
+	db "BALL POCKET@"
+.TM:
+	db "TM POCKET@"
+
+CurItemName:
+	ld a, [wCurItem]
+	ld [wd265], a
+	call GetItemName
+	ret
+
+
+PutItemInPocketText:
+	text_jump UnknownText_0x1c472c
+	db "@"
+
+PocketIsFullText:
+	text_jump UnknownText_0x1c474b
+	db "@"
+
+
+Script_pokemart:
+; script command 0x94
+; parameters: dialog_id, mart_id
+
+	call GetScriptByte
+	ld c, a
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld a, [wScriptBank]
+	ld b, a
+	farcall OpenMartDialog
+	ret
+
+Script_elevator:
+; script command 0x95
+; parameters: floor_list_pointer
+
+	xor a
+	ld [wScriptVar], a
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld a, [wScriptBank]
+	ld b, a
+	farcall Elevator
+	ret c
+	ld a, TRUE
+	ld [wScriptVar], a
+	ret
+
+Script_trade:
+; script command 0x96
+; parameters: trade_id
+
+	call GetScriptByte
+	ld e, a
+	farcall NPCTrade
+	ret
+
+Script_phonecall:
+; script command 0x98
+; parameters: caller_name
+
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld a, [wScriptBank]
+	ld b, a
+	farcall PhoneCall
+	ret
+
+Script_hangup:
+; script command 0x99
+
+	farcall HangUp
+	ret
+
+Script_askforphonenumber:
+; script command 0x97
+; parameters: number
+
+	call YesNoBox
+	jr c, .refused
+	call GetScriptByte
+	ld c, a
+	farcall AddPhoneNumber
+	jr c, .phonefull
+	xor a ; PHONE_CONTACT_GOT
+	jr .done
+.phonefull
+	ld a, PHONE_CONTACTS_FULL
+	jr .done
+.refused
+	call GetScriptByte
+	ld a, PHONE_CONTACT_REFUSED
+.done
+	ld [wScriptVar], a
+	ret
+
+Script_describedecoration:
+; script command 0x9a
+; parameters: byte
+
+	call GetScriptByte
+	ld b, a
+	farcall DescribeDecoration
+	ld h, d
+	ld l, e
+	jp ScriptJump
+
+Script_fruittree:
+; script command 0x9b
+; parameters: tree_id
+
+	call GetScriptByte
+	ld [wCurFruitTree], a
+	ld b, BANK(FruitTreeScript)
+	ld hl, FruitTreeScript
+	jp ScriptJump
+
+Script_swarm:
+; script command 0xa0
+; parameters: flag, map_group, map_id
+
+	call GetScriptByte
+	ld c, a
+	call GetScriptByte
+	ld d, a
+	call GetScriptByte
+	ld e, a
+	farcall StoreSwarmMapIndices
+	ret
+
+Script_trainertext:
+; script command 0x62
+; parameters: which_text
+
+	call GetScriptByte
+	ld c, a
+	ld b, 0
+	ld hl, wWalkingX
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [wEngineBuffer1]
+	ld b, a
+	call MapTextbox
+	ret
+
+Script_scripttalkafter:
+; script command 0x65
+
+	ld hl, wScriptAfterPointer
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [wEngineBuffer1]
+	ld b, a
+	jp ScriptJump
+
+Script_trainerflagaction:
+; script command 0x63
+; parameters: action
+
+	xor a
+	ld [wScriptVar], a
+	ld hl, wd041
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	call GetScriptByte
+	ld b, a
+	call EventFlagAction
+	ld a, c
+	and a
+	ret z
+	ld a, TRUE
+	ld [wScriptVar], a
+	ret
+
+Script_winlosstext:
+; script command 0x64
+; parameters: win_text_pointer, loss_text_pointer
+
+	ld hl, wWinTextPointer
+	call GetScriptByte
+	ld [hli], a
+	call GetScriptByte
+	ld [hli], a
+	ld hl, wLossTextPointer
+	call GetScriptByte
+	ld [hli], a
+	call GetScriptByte
+	ld [hli], a
+	ret
+
+Script_endifjustbattled:
+; script command 0x66
+
+	ld a, [wRunningTrainerBattleScript]
+	and a
+	ret z
+	jp Script_end
+
+Script_checkjustbattled:
+; script command 0x67
+
+	ld a, TRUE
+	ld [wScriptVar], a
+	ld a, [wRunningTrainerBattleScript]
+	and a
+	ret nz
+	xor a
+	ld [wScriptVar], a
+	ret
+
+Script_encountermusic:
+; script command 0x80
+
+	ld a, [wOtherTrainerClass]
+	ld e, a
+	farcall PlayTrainerEncounterMusic
+	ret
+
+Script_playmapmusic:
+; script command 0x82
+
+	call PlayMapMusic
+	ret
+
+Script_playmusic:
+; script command 0x7f
+; parameters: music_pointer
+
+	ld de, MUSIC_NONE
+	call PlayMusic
+	xor a
+	ld [wMusicFade], a
+	call MaxVolume
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	call PlayMusic
+	ret
+
+Script_musicfadeout:
+; script command 0x81
+; parameters: music, fadetime
+
+	call GetScriptByte
+	ld [wMusicFadeID], a
+	call GetScriptByte
+	ld [wMusicFadeID + 1], a
+	call GetScriptByte
+	and $ff ^ (1 << MUSIC_FADE_IN_F)
+	ld [wMusicFade], a
+	ret
+
+Script_playsound:
+; script command 0x85
+; parameters: sound_pointer
+
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	call PlaySFX
+	ret
+
+Script_waitsfx:
+; script command 0x86
+
+	call WaitSFX
+	ret
+
+Script_warpsound:
+; script command 0x87
+
+	farcall GetWarpSFX
+	call PlaySFX
+	ret
+
+Script_cry:
+; script command 0x84
+; parameters: cry_id
+
+	call GetScriptByte
+	push af
+	call GetScriptByte
+	pop af
+	and a
+	jr nz, .ok
+	ld a, [wScriptVar]
+.ok
+	call PlayMonCry
+	ret
+
+GetScriptObject:
+	and a ; PLAYER?
+	ret z
+	cp LAST_TALKED
+	ret z
+	dec a
+	ret
+
+Script_setlasttalked:
+; script command 0x68
+; parameters: object_id
+
+	call GetScriptByte
+	call GetScriptObject
+	ld [hLastTalked], a
+	ret
+
+Script_applymovement:
+; script command 0x69
+; parameters: object_id, data
+
+	call GetScriptByte
+	call GetScriptObject
+	ld c, a
+
+ApplyMovement:
+	push bc
+	ld a, c
+	farcall SetFlagsForMovement_1
+	pop bc
+
+	push bc
+	call SetFlagsForMovement_2
+	pop bc
+
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	ld a, [wScriptBank]
+	ld b, a
+	call GetMovementData
+	ret c
+
+	ld a, SCRIPT_WAIT_MOVEMENT
+	ld [wScriptMode], a
+	call StopScript
+	ret
+
+SetFlagsForMovement_2:
+	farcall _SetFlagsForMovement_2
+	ret
+
+Script_applymovement2:
+; script command 0x6a
+; parameters: data
+; apply movement to last talked
+
+	ld a, [hLastTalked]
+	ld c, a
+	jp ApplyMovement
+
+Script_faceplayer:
+; script command 0x6b
+
+	ld a, [hLastTalked]
+	and a
+	ret z
+	ld d, $0
+	ld a, [hLastTalked]
+	ld e, a
+	farcall GetRelativeFacing
+	ld a, d
+	add a
+	add a
+	ld e, a
+	ld a, [hLastTalked]
+	ld d, a
+	call ApplyObjectFacing
+	ret
+
+Script_faceobject:
+; script command 0x6c
+; parameters: object1, object2
+
+	call GetScriptByte
+	call GetScriptObject
+	cp LAST_TALKED
+	jr c, .ok
+	ld a, [hLastTalked]
+.ok
+	ld e, a
+	call GetScriptByte
+	call GetScriptObject
+	cp LAST_TALKED
+	jr nz, .ok2
+	ld a, [hLastTalked]
+.ok2
+	ld d, a
+	push de
+	farcall GetRelativeFacing
+	pop bc
+	ret c
+	ld a, d
+	add a
+	add a
+	ld e, a
+	ld d, c
+	call ApplyObjectFacing
+	ret
+
+Script_turnobject:
+; script command 0x76
+; parameters: object_id, facing
+
+	call GetScriptByte
+	call GetScriptObject
+	cp LAST_TALKED
+	jr nz, .ok
+	ld a, [hLastTalked]
+.ok
+	ld d, a
+	call GetScriptByte
+	add a
+	add a
+	ld e, a
+	call ApplyObjectFacing
+	ret
+
+ApplyObjectFacing:
+	ld a, d
+	push de
+	call CheckObjectVisibility
+	jr c, .not_visible
+	ld hl, OBJECT_SPRITE
+	add hl, bc
+	ld a, [hl]
+	push bc
+	call DoesSpriteHaveFacings
+	pop bc
+	jr c, .not_visible ; STILL_SPRITE
+	ld hl, OBJECT_FLAGS1
+	add hl, bc
+	bit FIXED_FACING, [hl]
+	jr nz, .not_visible
+	pop de
+	ld a, e
+	call SetSpriteDirection
+	ld hl, wVramState
+	bit 6, [hl]
+	jr nz, .text_state
+	call .DisableTextTiles
+.text_state
+	call UpdateSprites
+	ret
+
+.not_visible
+	pop de
+	scf
+	ret
+
+.DisableTextTiles:
+	call LoadMapPart
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+.loop
+	res 7, [hl]
+	inc hl
+	dec bc
+	ld a, b
+	or c
+	jr nz, .loop
+	ret
+
+Script_variablesprite:
+; script command 0x6d
+; parameters: byte, sprite
+
+	call GetScriptByte
+	ld e, a
+	ld d, $0
+	ld hl, wVariableSprites
+	add hl, de
+	call GetScriptByte
+	ld [hl], a
+	ret
+
+Script_appear:
+; script command 0x6f
+; parameters: object_id
+
+	call GetScriptByte
+	call GetScriptObject
+	call _CopyObjectStruct
+	ld a, [hMapObjectIndexBuffer]
+	ld b, 0 ; clear
+	call ApplyEventActionAppearDisappear
+	ret
+
+Script_disappear:
+; script command 0x6e
+; parameters: object_id
+
+	call GetScriptByte
+	call GetScriptObject
+	cp LAST_TALKED
+	jr nz, .ok
+	ld a, [hLastTalked]
+.ok
+	call DeleteObjectStruct
+	ld a, [hMapObjectIndexBuffer]
+	ld b, 1 ; set
+	call ApplyEventActionAppearDisappear
+	farcall _UpdateSprites
+	ret
+
+ApplyEventActionAppearDisappear:
+	push bc
+	call GetMapObject
+	ld hl, MAPOBJECT_EVENT_FLAG
+	add hl, bc
+	pop bc
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	ld a, -1
+	cp e
+	jr nz, .okay
+	cp d
+	jr nz, .okay
+	xor a
+	ret
+.okay
+	call EventFlagAction
+	ret
+
+Script_follow:
+; script command 0x70
+; parameters: object2, object1
+
+	call GetScriptByte
+	call GetScriptObject
+	ld b, a
+	call GetScriptByte
+	call GetScriptObject
+	ld c, a
+	farcall StartFollow
+	ret
+
+Script_stopfollow:
+; script command 0x71
+
+	farcall StopFollow
+	ret
+
+Script_moveobject:
+; script command 0x72
+; parameters: object id, x, y
+
+	call GetScriptByte
+	call GetScriptObject
+	ld b, a
+	call GetScriptByte
+	add 4
+	ld d, a
+	call GetScriptByte
+	add 4
+	ld e, a
+	farcall CopyDECoordsToMapObject
+	ret
+
+Script_writeobjectxy:
+; script command 0x73
+; parameters: object_id
+
+	call GetScriptByte
+	call GetScriptObject
+	cp LAST_TALKED
+	jr nz, .ok
+	ld a, [hLastTalked]
+.ok
+	ld b, a
+	farcall WriteObjectXY
+	ret
+
+Script_follownotexact:
+; script command 0x77
+; parameters: object2, object1
+
+	call GetScriptByte
+	call GetScriptObject
+	ld b, a
+	call GetScriptByte
+	call GetScriptObject
+	ld c, a
+	farcall FollowNotExact
+	ret
+
+Script_loademote:
+; script command 0x74
+; parameters: bubble
+
+	call GetScriptByte
+	cp -1
+	jr nz, .not_var_emote
+	ld a, [wScriptVar]
+.not_var_emote
+	ld c, a
+	farcall LoadEmote
+	ret
+
+Script_showemote:
+; script command 0x75
+; parameters: bubble, object_id, time
+
+	call GetScriptByte
+	ld [wScriptVar], a
+	call GetScriptByte
+	call GetScriptObject
+	cp LAST_TALKED
+	jr z, .ok
+	ld [hLastTalked], a
+.ok
+	call GetScriptByte
+	ld [wScriptDelay], a
+	ld b, BANK(ShowEmoteScript)
+	ld de, ShowEmoteScript
+	jp ScriptCall
+
+ShowEmoteScript:
+	loademote EMOTE_MEM
+	applymovement2 .Show
+	pause 0
+	applymovement2 .Hide
+	end
+
+.Show:
+	show_emote
+	step_sleep 1
+	step_end
+
+.Hide:
+	hide_emote
+	step_sleep 1
+	step_end
+
+
+Script_earthquake:
+; script command 0x78
+; parameters: param
+
+	ld hl, EarthquakeMovement
+	ld de, wEarthquakeMovementDataBuffer
+	ld bc, EarthquakeMovement.End - EarthquakeMovement
+	call CopyBytes
+	call GetScriptByte
+	ld [wEarthquakeMovementDataBuffer + 1], a
+	and %00111111
+	ld [wEarthquakeMovementDataBuffer + 3], a
+	ld b, BANK(.script)
+	ld de, .script
+	jp ScriptCall
+
+.script
+	applymovement PLAYER, wEarthquakeMovementDataBuffer
+	end
+
+EarthquakeMovement:
+	step_shake 16 ; the 16 gets overwritten with the script byte
+	step_sleep 16 ; the 16 gets overwritten with the lower 6 bits of the script byte
+	step_end
+.End
+
+
+Script_loadpikachudata:
+; script command 0x5a
+
+	ld a, PIKACHU
+	ld [wTempWildMonSpecies], a
+	ld a, 5
+	ld [wCurPartyLevel], a
+	ret
+
+Script_randomwildmon:
+; script command 0x5b
+
+	xor a
+	ld [wBattleScriptFlags], a
+	ret
+
+Script_loadmemtrainer:
+; script command 0x5c
+
+	ld a, (1 << 7) | 1
+	ld [wBattleScriptFlags], a
+	ld a, [wTempTrainerClass]
+	ld [wOtherTrainerClass], a
+	ld a, [wTempTrainerID]
+	ld [wOtherTrainerID], a
+	ret
+
+Script_loadwildmon:
+; script command 0x5d
+; parameters: pokemon, level
+
+	ld a, (1 << 7)
+	ld [wBattleScriptFlags], a
+	call GetScriptByte
+	ld [wTempWildMonSpecies], a
+	call GetScriptByte
+	ld [wCurPartyLevel], a
+	ret
+
+Script_loadtrainer:
+; script command 0x5e
+; parameters: trainer_group, trainer_id
+
+	ld a, (1 << 7) | 1
+	ld [wBattleScriptFlags], a
+	call GetScriptByte
+	ld [wOtherTrainerClass], a
+	call GetScriptByte
+	ld [wOtherTrainerID], a
+	ret
+
+Script_startbattle:
+; script command 0x5f
+
+	call BufferScreen
+	predef StartBattle
+	ld a, [wBattleResult]
+	and $3f
+	ld [wScriptVar], a
+	ret
+
+Script_catchtutorial:
+; script command 0x61
+; parameters: byte
+
+	call GetScriptByte
+	ld [wBattleType], a
+	call BufferScreen
+	farcall CatchTutorial
+	jp Script_reloadmap
+
+Script_reloadmapafterbattle:
+; script command 0x60
+
+	ld hl, wBattleScriptFlags
+	ld d, [hl]
+	ld [hl], $0
+	ld a, [wBattleResult]
+	and $3f
+	cp $1
+	jr nz, .notblackedout
+	ld b, BANK(Script_BattleWhiteout)
+	ld hl, Script_BattleWhiteout
+	jp ScriptJump
+
+.notblackedout
+	bit 0, d
+	jr z, .was_wild
+	farcall MomTriesToBuySomething
+	jr .done
+
+.was_wild
+	ld a, [wBattleResult]
+	bit 7, a
+	jr z, .done
+	ld b, BANK(Script_SpecialBillCall)
+	ld de, Script_SpecialBillCall
+	farcall LoadScriptBDE
+.done
+	jp Script_reloadmap
+
+Script_reloadmap:
+; script command 0x7b
+
+	xor a
+	ld [wBattleScriptFlags], a
+	ld a, MAPSETUP_RELOADMAP
+	ld [hMapEntryMethod], a
+	ld a, $1
+	call LoadMapStatus
+	call StopScript
+	ret
+
+Script_scall:
+; script command 0x0
+; parameters: pointer
+
+	ld a, [wScriptBank]
+	ld b, a
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	jr ScriptCall
+
+Script_farscall:
+; script command 0x1
+; parameters: pointer
+
+	call GetScriptByte
+	ld b, a
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	jr ScriptCall
+
+Script_ptcall:
+; script command 0x2
+; parameters: pointer
+
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	ld b, [hl]
+	inc hl
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	; fallthrough
+
+ScriptCall:
+; Bug: The script stack has a capacity of 5 scripts, yet there is
+; nothing to stop you from pushing a sixth script.  The high part
+; of the script address can then be overwritten by modifications
+; to wScriptDelay, causing the script to return to the rst/interrupt
+; space.
+
+	push de
+	ld hl, wScriptStackSize
+	ld e, [hl]
+	inc [hl]
+	ld d, $0
+	ld hl, wScriptStack
+	add hl, de
+	add hl, de
+	add hl, de
+	pop de
+	ld a, [wScriptBank]
+	ld [hli], a
+	ld a, [wScriptPos]
+	ld [hli], a
+	ld a, [wScriptPos + 1]
+	ld [hl], a
+	ld a, b
+	ld [wScriptBank], a
+	ld a, e
+	ld [wScriptPos], a
+	ld a, d
+	ld [wScriptPos + 1], a
+	ret
+
+CallCallback::
+	ld a, [wScriptBank]
+	or $80
+	ld [wScriptBank], a
+	jp ScriptCall
+
+Script_jump:
+; script command 0x3
+; parameters: pointer
+
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	ld a, [wScriptBank]
+	ld b, a
+	jp ScriptJump
+
+Script_farjump:
+; script command 0x4
+; parameters: pointer
+
+	call GetScriptByte
+	ld b, a
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	jp ScriptJump
+
+Script_ptjump:
+; script command 0x5
+; parameters: pointer
+
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	ld b, [hl]
+	inc hl
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp ScriptJump
+
+Script_iffalse:
+; script command 0x8
+; parameters: pointer
+
+	ld a, [wScriptVar]
+	and a
+	jp nz, SkipTwoScriptBytes
+	jp Script_jump
+
+Script_iftrue:
+; script command 0x9
+; parameters: pointer
+
+	ld a, [wScriptVar]
+	and a
+	jp nz, Script_jump
+	jp SkipTwoScriptBytes
+
+Script_ifequal:
+; script command 0x6
+; parameters: byte, pointer
+
+	call GetScriptByte
+	ld hl, wScriptVar
+	cp [hl]
+	jr z, Script_jump
+	jr SkipTwoScriptBytes
+
+Script_ifnotequal:
+; script command 0x7
+; parameters: byte, pointer
+
+	call GetScriptByte
+	ld hl, wScriptVar
+	cp [hl]
+	jr nz, Script_jump
+	jr SkipTwoScriptBytes
+
+Script_ifgreater:
+; script command 0xa
+; parameters: byte, pointer
+
+	ld a, [wScriptVar]
+	ld b, a
+	call GetScriptByte
+	cp b
+	jr c, Script_jump
+	jr SkipTwoScriptBytes
+
+Script_ifless:
+; script command 0xb
+; parameters: byte, pointer
+
+	call GetScriptByte
+	ld b, a
+	ld a, [wScriptVar]
+	cp b
+	jr c, Script_jump
+	jr SkipTwoScriptBytes
+
+Script_jumpstd:
+; script command 0xc
+; parameters: predefined_script
+
+	call StdScript
+	jr ScriptJump
+
+Script_callstd:
+; script command 0xd
+; parameters: predefined_script
+
+	call StdScript
+	ld d, h
+	ld e, l
+	jp ScriptCall
+
+StdScript:
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld hl, StdScripts
+	add hl, de
+	add hl, de
+	add hl, de
+	ld a, BANK(StdScripts)
+	call GetFarByte
+	ld b, a
+	inc hl
+	ld a, BANK(StdScripts)
+	call GetFarHalfword
+	ret
+
+SkipTwoScriptBytes:
+	call GetScriptByte
+	call GetScriptByte
+	ret
+
+ScriptJump:
+	ld a, b
+	ld [wScriptBank], a
+	ld a, l
+	ld [wScriptPos], a
+	ld a, h
+	ld [wScriptPos + 1], a
+	ret
+
+Script_priorityjump:
+; script command 0x8d
+; parameters: pointer
+
+	ld a, [wScriptBank]
+	ld [wPriorityScriptBank], a
+	call GetScriptByte
+	ld [wPriorityScriptAddr], a
+	call GetScriptByte
+	ld [wPriorityScriptAddr + 1], a
+	ld hl, wScriptFlags
+	set 3, [hl]
+	ret
+
+Script_checkscene:
+; script command 0x13
+
+	call CheckScenes
+	jr z, .no_scene
+	ld [wScriptVar], a
+	ret
+
+.no_scene
+	ld a, $ff
+	ld [wScriptVar], a
+	ret
+
+Script_checkmapscene:
+; script command 0x11
+; parameters: map_group, map_id
+
+	call GetScriptByte
+	ld b, a
+	call GetScriptByte
+	ld c, a
+	call GetMapSceneID
+	ld a, d
+	or e
+	jr z, .no_scene
+	ld a, [de]
+	ld [wScriptVar], a
+	ret
+
+.no_scene
+	ld a, $ff
+	ld [wScriptVar], a
+	ret
+
+Script_setscene:
+; script command 0x14
+; parameters: scene_id
+
+	ld a, [wMapGroup]
+	ld b, a
+	ld a, [wMapNumber]
+	ld c, a
+	jr DoScene
+
+Script_setmapscene:
+; script command 0x12
+; parameters: map_group, map_id, scene_id
+
+	call GetScriptByte
+	ld b, a
+	call GetScriptByte
+	ld c, a
+DoScene:
+	call GetMapSceneID
+	ld a, d
+	or e
+	jr z, .no_scene
+	call GetScriptByte
+	ld [de], a
+.no_scene
+	ret
+
+Script_copybytetovar:
+; script command 0x19
+; parameters: address
+
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	ld a, [hl]
+	ld [wScriptVar], a
+	ret
+
+Script_copyvartobyte:
+; script command 0x1a
+; parameters: address
+
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	ld a, [wScriptVar]
+	ld [hl], a
+	ret
+
+Script_loadvar:
+; script command 0x1b
+; parameters: address, value
+
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	call GetScriptByte
+	ld [hl], a
+	ret
+
+Script_writebyte:
+; script command 0x15
+; parameters: value
+
+	call GetScriptByte
+	ld [wScriptVar], a
+	ret
+
+Script_addvar:
+; script command 0x16
+; parameters: value
+
+	call GetScriptByte
+	ld hl, wScriptVar
+	add [hl]
+	ld [hl], a
+	ret
+
+Script_random:
+; script command 0x17
+; parameters: input
+
+	call GetScriptByte
+	ld [wScriptVar], a
+	and a
+	ret z
+
+	ld c, a
+	call .Divide256byC
+	and a
+	jr z, .no_restriction ; 256 % b == 0
+	ld b, a
+	xor a
+	sub b
+	ld b, a
+.loop
+	push bc
+	call Random
+	pop bc
+	ld a, [hRandomAdd]
+	cp b
+	jr nc, .loop
+	jr .finish
+
+.no_restriction
+	push bc
+	call Random
+	pop bc
+	ld a, [hRandomAdd]
+
+.finish
+	push af
+	ld a, [wScriptVar]
+	ld c, a
+	pop af
+	call SimpleDivide
+	ld [wScriptVar], a
+	ret
+
+.Divide256byC:
+	xor a
+	ld b, a
+	sub c
+.mod_loop
+	inc b
+	sub c
+	jr nc, .mod_loop
+	dec b
+	add c
+	ret
+
+Script_checkcode:
+; script command 0x1c
+; parameters: variable_id
+
+	call GetScriptByte
+	call GetVarAction
+	ld a, [de]
+	ld [wScriptVar], a
+	ret
+
+Script_writevarcode:
+; script command 0x1d
+; parameters: variable_id
+
+	call GetScriptByte
+	call GetVarAction
+	ld a, [wScriptVar]
+	ld [de], a
+	ret
+
+Script_writecode:
+; script command 0x1e
+; parameters: variable_id, value
+
+	call GetScriptByte
+	call GetVarAction
+	call GetScriptByte
+	ld [de], a
+	ret
+
+GetVarAction:
+	ld c, a
+	farcall _GetVarAction
+	ret
+
+Script_checkver:
+; script command 0x18
+
+	ld a, [.gs_version]
+	ld [wScriptVar], a
+	ret
+
+.gs_version:
+	db GS_VERSION
+
+Script_pokenamemem:
+; script command 0x40
+; parameters: pokemon (0 aka USE_SCRIPT_VAR to use wScriptVar), memory
+
+	call GetScriptByte
+	and a
+	jr nz, .gotit
+	ld a, [wScriptVar]
+.gotit
+	ld [wd265], a
+	call GetPokemonName
+	ld de, wStringBuffer1
+
+ConvertMemToText:
+	call GetScriptByte
+	cp NUM_MEM_BUFFERS
+	jr c, .ok
+	xor a
+.ok
+
+CopyConvertedText:
+	ld hl, wStringBuffer3
+	ld bc, wStringBuffer4 - wStringBuffer3
+	call AddNTimes
+	call CopyName2
+	ret
+
+Script_itemtotext:
+; script command 0x41
+; parameters: item (0 aka USE_SCRIPT_VAR to use wScriptVar), memory
+
+	call GetScriptByte
+	and a ; USE_SCRIPT_VAR
+	jr nz, .ok
+	ld a, [wScriptVar]
+.ok
+	ld [wd265], a
+	call GetItemName
+	ld de, wStringBuffer1
+	jr ConvertMemToText
+
+Script_mapnametotext:
+; script command 0x42
+; parameters: memory
+
+	ld a, [wMapGroup]
+	ld b, a
+	ld a, [wMapNumber]
+	ld c, a
+	call GetWorldMapLocation
+
+ConvertLandmarkToText:
+	ld e, a
+	farcall GetLandmarkName
+	ld de, wStringBuffer1
+	jp ConvertMemToText
+
+Script_landmarktotext:
+; script command 0xa5
+; parameters: id, memory
+
+	call GetScriptByte
+	jr ConvertLandmarkToText
+
+Script_trainertotext:
+; script command 0x43
+; parameters: trainer_id, trainer_group, memory
+
+	call GetScriptByte
+	ld c, a
+	call GetScriptByte
+	ld b, a
+	farcall GetTrainerName
+	jr ConvertMemToText
+
+Script_name:
+; script command 0xa7
+; parameters: type, id, memory
+
+	call GetScriptByte
+	ld [wNamedObjectTypeBuffer], a
+
+ContinueToGetName:
+	call GetScriptByte
+	ld [wCurSpecies], a
+	call GetName
+	ld de, wStringBuffer1
+	jp ConvertMemToText
+
+Script_trainerclassname:
+; script command 0xa6
+; parameters: id, memory
+
+	ld a, TRAINER_NAME
+	ld [wNamedObjectTypeBuffer], a
+	jr ContinueToGetName
+
+Script_readmoney:
+; script command 0x3d
+; parameters: account, memory
+
+	call ResetStringBuffer1
+	call GetMoneyAccount
+	ld hl, wStringBuffer1
+	lb bc, PRINTNUM_RIGHTALIGN | 3, 6
+	call PrintNum
+	ld de, wStringBuffer1
+	jp ConvertMemToText
+
+Script_readcoins:
+; script command 0x3e
+; parameters: memory
+
+	call ResetStringBuffer1
+	ld hl, wStringBuffer1
+	ld de, wCoins
+	lb bc, PRINTNUM_RIGHTALIGN | 2, 6
+	call PrintNum
+	ld de, wStringBuffer1
+	jp ConvertMemToText
+
+Script_vartomem:
+; script command 0x3f
+; parameters: memory
+
+	call ResetStringBuffer1
+	ld de, wScriptVar
+	ld hl, wStringBuffer1
+	lb bc, PRINTNUM_RIGHTALIGN | 1, 3
+	call PrintNum
+	ld de, wStringBuffer1
+	jp ConvertMemToText
+
+ResetStringBuffer1:
+	ld hl, wStringBuffer1
+	ld bc, NAME_LENGTH
+	ld a, "@"
+	call ByteFill
+	ret
+
+Script_stringtotext:
+; script command 0x44
+; parameters: text_pointer, memory
+
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld a, [wScriptBank]
+	ld hl, CopyName1
+	rst FarCall
+	ld de, wStringBuffer2
+	jp ConvertMemToText
+
+Script_givepokeitem:
+; script command 0x2f
+; parameters: pointer
+
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	ld a, [wScriptBank]
+	call GetFarByte
+	ld b, a
+	push bc
+	inc hl
+	ld bc, MAIL_MSG_LENGTH
+	ld de, wd002
+	ld a, [wScriptBank]
+	call FarCopyBytes
+	pop bc
+	farcall GivePokeItem
+	ret
+
+Script_checkpokeitem:
+; script command 0x30
+; parameters: pointer
+
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld a, [wScriptBank]
+	ld b, a
+	farcall CheckPokeItem
+	ret
+
+Script_giveitem:
+; script command 0x1f
+; parameters: item, quantity
+
+	call GetScriptByte
+	cp ITEM_FROM_MEM
+	jr nz, .ok
+	ld a, [wScriptVar]
+.ok
+	ld [wCurItem], a
+	call GetScriptByte
+	ld [wItemQuantityChangeBuffer], a
+	ld hl, wNumItems
+	call ReceiveItem
+	jr nc, .full
+	ld a, TRUE
+	ld [wScriptVar], a
+	ret
+.full
+	xor a
+	ld [wScriptVar], a
+	ret
+
+Script_takeitem:
+; script command 0x20
+; parameters: item, quantity
+
+	xor a
+	ld [wScriptVar], a
+	call GetScriptByte
+	ld [wCurItem], a
+	call GetScriptByte
+	ld [wItemQuantityChangeBuffer], a
+	ld a, -1
+	ld [wCurItemQuantity], a
+	ld hl, wNumItems
+	call TossItem
+	ret nc
+	ld a, TRUE
+	ld [wScriptVar], a
+	ret
+
+Script_checkitem:
+; script command 0x21
+; parameters: item
+
+	xor a
+	ld [wScriptVar], a
+	call GetScriptByte
+	ld [wCurItem], a
+	ld hl, wNumItems
+	call CheckItem
+	ret nc
+	ld a, TRUE
+	ld [wScriptVar], a
+	ret
+
+Script_givemoney:
+; script command 0x22
+; parameters: account, money
+
+	call GetMoneyAccount
+	call LoadMoneyAmountToMem
+	farcall GiveMoney
+	ret
+
+Script_takemoney:
+; script command 0x23
+; parameters: account, money
+
+	call GetMoneyAccount
+	call LoadMoneyAmountToMem
+	farcall TakeMoney
+	ret
+
+Script_checkmoney:
+; script command 0x24
+; parameters: account, money
+
+	call GetMoneyAccount
+	call LoadMoneyAmountToMem
+	farcall CompareMoney
+
+CompareMoneyAction:
+	jr c, .less
+	jr z, .exact
+	ld a, HAVE_MORE
+	jr .done
+.exact
+	ld a, HAVE_AMOUNT
+	jr .done
+.less
+	ld a, HAVE_LESS
+.done
+	ld [wScriptVar], a
+	ret
+
+GetMoneyAccount:
+	call GetScriptByte
+	and a
+	ld de, wMoney ; YOUR_MONEY
+	ret z
+	ld de, wMomsMoney ; MOMS_MONEY
+	ret
+
+LoadMoneyAmountToMem:
+	ld bc, hMoneyTemp
+	push bc
+	call GetScriptByte
+	ld [bc], a
+	inc bc
+	call GetScriptByte
+	ld [bc], a
+	inc bc
+	call GetScriptByte
+	ld [bc], a
+	pop bc
+	ret
+
+Script_givecoins:
+; script command 0x25
+; parameters: coins
+
+	call LoadCoinAmountToMem
+	farcall GiveCoins
+	ret
+
+Script_takecoins:
+; script command 0x26
+; parameters: coins
+
+	call LoadCoinAmountToMem
+	farcall TakeCoins
+	ret
+
+Script_checkcoins:
+; script command 0x27
+; parameters: coins
+
+	call LoadCoinAmountToMem
+	farcall CheckCoins
+	jr CompareMoneyAction
+
+LoadCoinAmountToMem:
+	call GetScriptByte
+	ld [hMoneyTemp + 1], a
+	call GetScriptByte
+	ld [hMoneyTemp], a
+	ld bc, hMoneyTemp
+	ret
+
+Script_checktime:
+; script command 0x2b
+; parameters: time
+
+	xor a
+	ld [wScriptVar], a
+	farcall CheckTime
+	call GetScriptByte
+	and c
+	ret z
+	ld a, TRUE
+	ld [wScriptVar], a
+	ret
+
+Script_checkpoke:
+; script command 0x2c
+; parameters: pokemon
+
+	xor a
+	ld [wScriptVar], a
+	call GetScriptByte
+	ld hl, wPartySpecies
+	ld de, 1
+	call IsInArray
+	ret nc
+	ld a, TRUE
+	ld [wScriptVar], a
+	ret
+
+Script_addcellnum:
+; script command 0x28
+; parameters: person
+
+	xor a
+	ld [wScriptVar], a
+	call GetScriptByte
+	ld c, a
+	farcall AddPhoneNumber
+	ret nc
+	ld a, TRUE
+	ld [wScriptVar], a
+	ret
+
+Script_delcellnum:
+; script command 0x29
+; parameters: person
+
+	xor a
+	ld [wScriptVar], a
+	call GetScriptByte
+	ld c, a
+	farcall DelCellNum
+	ret nc
+	ld a, TRUE
+	ld [wScriptVar], a
+	ret
+
+Script_checkcellnum:
+; script command 0x2a
+; parameters: person
+; returns false if the cell number is not in your phone
+
+	xor a
+	ld [wScriptVar], a
+	call GetScriptByte
+	ld c, a
+	farcall CheckCellNum
+	ret nc
+	ld a, TRUE
+	ld [wScriptVar], a
+	ret
+
+Script_specialphonecall:
+; script command 0x9c
+; parameters: call_id
+
+	call GetScriptByte
+	ld [wSpecialPhoneCallID], a
+	call GetScriptByte
+	ld [wSpecialPhoneCallID + 1], a
+	ret
+
+Script_checkphonecall:
+; script command 0x9d
+; returns false if no special phone call is stored
+
+	ld a, [wSpecialPhoneCallID]
+	and a
+	jr z, .ok
+	ld a, TRUE
+.ok
+	ld [wScriptVar], a
+	ret
+
+Script_givepoke:
+; script command 0x2d
+; parameters: pokemon, level, item, trainer, trainer_name_pointer, pkmn_nickname
+
+	call GetScriptByte
+	ld [wCurPartySpecies], a
+	call GetScriptByte
+	ld [wCurPartyLevel], a
+	call GetScriptByte
+	ld [wCurItem], a
+	call GetScriptByte
+	and a
+	ld b, a
+	jr z, .ok
+	ld hl, wScriptPos
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	call GetScriptByte
+	call GetScriptByte
+	call GetScriptByte
+	call GetScriptByte
+.ok
+	farcall GivePoke
+	ld a, b
+	ld [wScriptVar], a
+	ret
+
+Script_giveegg:
+; script command 0x2e
+; parameters: pokemon, level
+; if no room in the party, return 0 in wScriptVar; else, return 2
+
+	xor a ; PARTYMON
+	ld [wScriptVar], a
+	ld [wMonType], a
+	call GetScriptByte
+	ld [wCurPartySpecies], a
+	call GetScriptByte
+	ld [wCurPartyLevel], a
+	farcall GiveEgg
+	ret nc
+	ld a, 2
+	ld [wScriptVar], a
+	ret
+
+Script_setevent:
+; script command 0x33
+; parameters: bit_number
+
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld b, SET_FLAG
+	call EventFlagAction
+	ret
+
+Script_clearevent:
+; script command 0x32
+; parameters: bit_number
+
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld b, RESET_FLAG
+	call EventFlagAction
+	ret
+
+Script_checkevent:
+; script command 0x31
+; parameters: bit_number
+
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld b, CHECK_FLAG
+	call EventFlagAction
+	ld a, c
+	and a
+	jr z, .false
+	ld a, TRUE
+.false
+	ld [wScriptVar], a
+	ret
+
+Script_setflag:
+; script command 0x36
+; parameters: bit_number
+
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld b, SET_FLAG
+	call _EngineFlagAction
+	ret
+
+Script_clearflag:
+; script command 0x35
+; parameters: bit_number
+
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld b, RESET_FLAG
+	call _EngineFlagAction
+	ret
+
+Script_checkflag:
+; script command 0x34
+; parameters: bit_number
+
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld b, CHECK_FLAG
+	call _EngineFlagAction
+	ld a, c
+	and a
+	jr z, .false
+	ld a, TRUE
+.false
+	ld [wScriptVar], a
+	ret
+
+_EngineFlagAction:
+	farcall EngineFlagAction
+	ret
+
+Script_wildoff:
+; script command 0x38
+
+	ld hl, wStatusFlags
+	set STATUSFLAGS_NO_WILD_ENCOUNTERS_F, [hl]
+	ret
+
+Script_wildon:
+; script command 0x37
+
+	ld hl, wStatusFlags
+	res STATUSFLAGS_NO_WILD_ENCOUNTERS_F, [hl]
+	ret
+
+Script_xycompare:
+; script command 0x39
+; parameters: pointer
+
+	call GetScriptByte
+	ld [wXYComparePointer], a
+	call GetScriptByte
+	ld [wXYComparePointer + 1], a
+	ret
+
+Script_warpfacing:
+; script command 0xa3
+; parameters: facing, map_group, map_id, x, y
+
+	call GetScriptByte
+	maskbits NUM_DIRECTIONS
+	ld c, a
+	ld a, [wPlayerSpriteSetupFlags]
+	set PLAYERSPRITESETUP_CUSTOM_FACING_F, a
+	or c
+	ld [wPlayerSpriteSetupFlags], a
+; fall through
+
+Script_warp:
+; script command 0x3c
+; parameters: map_group, map_id, x, y
+
+; This seems to be some sort of error handling case.
+	call GetScriptByte
+	and a
+	jr z, .not_ok
+	ld [wMapGroup], a
+	call GetScriptByte
+	ld [wMapNumber], a
+	call GetScriptByte
+	ld [wXCoord], a
+	call GetScriptByte
+	ld [wYCoord], a
+	ld a, -1
+	ld [wDefaultSpawnpoint], a
+	ld a, MAPSETUP_WARP
+	ld [hMapEntryMethod], a
+	ld a, 1
+	call LoadMapStatus
+	call StopScript
+	ret
+
+.not_ok
+	call GetScriptByte
+	call GetScriptByte
+	call GetScriptByte
+	ld a, -1
+	ld [wDefaultSpawnpoint], a
+	ld a, MAPSETUP_BADWARP
+	ld [hMapEntryMethod], a
+	ld a, 1
+	call LoadMapStatus
+	call StopScript
+	ret
+
+Script_warpmod:
+; script command 0x3a
+; parameters: warp_id, map_group, map_id
+
+	call GetScriptByte
+	ld [wBackupWarpNumber], a
+	call GetScriptByte
+	ld [wBackupMapGroup], a
+	call GetScriptByte
+	ld [wBackupMapNumber], a
+	ret
+
+Script_blackoutmod:
+; script command 0x3b
+; parameters: map_group, map_id
+
+	call GetScriptByte
+	ld [wLastSpawnMapGroup], a
+	call GetScriptByte
+	ld [wLastSpawnMapNumber], a
+	ret
+
+Script_dontrestartmapmusic:
+; script command 0x83
+
+	ld a, 1
+	ld [wDontPlayMapMusicOnReload], a
+	ret
+
+Script_writecmdqueue:
+; script command 0x7d
+; parameters: queue_pointer
+
+	call GetScriptByte
+	ld e, a
+	call GetScriptByte
+	ld d, a
+	ld a, [wScriptBank]
+	ld b, a
+	farcall WriteCmdQueue ; no need to farcall
+	ret
+
+Script_delcmdqueue:
+; script command 0x7e
+; parameters: byte
+
+	xor a
+	ld [wScriptVar], a
+	call GetScriptByte
+	ld b, a
+	farcall DelCmdQueue ; no need to farcall
+	ret c
+	ld a, 1
+	ld [wScriptVar], a
+	ret
+
+Script_changemap:
+; script command 0x79
+; parameters: map_data_pointer
+
+	call GetScriptByte
+	ld [wMapBlocksBank], a
+	call GetScriptByte
+	ld [wMapBlocksPointer], a
+	call GetScriptByte
+	ld [wMapBlocksPointer + 1], a
+	call ChangeMap
+	call BufferScreen
+	ret
+
+Script_changeblock:
+; script command 0x7a
+; parameters: x, y, block
+
+	call GetScriptByte
+	add 4
+	ld d, a
+	call GetScriptByte
+	add 4
+	ld e, a
+	call GetBlockLocation
+	call GetScriptByte
+	ld [hl], a
+	call BufferScreen
+	ret
+
+Script_reloadmappart::
+; script command 0x7c
+
+	xor a
+	ld [hBGMapMode], a
+	call OverworldTextModeSwitch
+	call GetMovementPermissions
+	farcall ReloadMapPart
+	call UpdateSprites
+	ret
+
+Script_warpcheck:
+; script command 0x8e
+
+	call WarpCheck
+	ret nc
+	farcall EnableEvents
+	ret
+
+Script_enableevents:
+; unused
+	farcall EnableEvents
+	ret
+
+Script_newloadmap:
+; script command 0x8a
+; parameters: which_method
+
+	call GetScriptByte
+	ld [hMapEntryMethod], a
+	ld a, 1
+	call LoadMapStatus
+	call StopScript
+	ret
+
+Script_reloadandreturn:
+; script command 0x92
+
+	call Script_newloadmap
+	jp Script_end
+
+Script_opentext:
+; script command 0x47
+
+	call OpenText
+	ret
+
+Script_refreshscreen:
+; script command 0x48
+; parameters: dummy
+
+	call RefreshScreen
+	call GetScriptByte
+	ret
+
+Script_loadbytec2cf:
+; script command 0x4a
+; parameters: byte
+
+	call GetScriptByte
+	ld [wc2cf], a
+	ret
+
+	db closetext_command ; unused
+
+Script_closetext:
+; script command 0x49
+
+	call _OpenAndCloseMenu_HDMATransferTileMapAndAttrMap
+	call CloseText
+	ret
+
+
+Script_passtoengine:
+; script command 0x89
+; parameters: data_pointer
+
+	call GetScriptByte
+	push af
+	call GetScriptByte
+	ld l, a
+	call GetScriptByte
+	ld h, a
+	pop af
+	call StartAutoInput
+	ret
+
+Script_pause:
+; script command 0x8b
+; parameters: length
+
+	call GetScriptByte
+	and a
+	jr z, .loop
+	ld [wScriptDelay], a
+.loop
+	ld c, 2
+	call DelayFrames
+	ld hl, wScriptDelay
+	dec [hl]
+	jr nz, .loop
+	ret
+
+Script_deactivatefacing:
+; script command 0x8c
+; parameters: time
+
+	call GetScriptByte
+	and a
+	jr z, .no_time
+	ld [wScriptDelay], a
+.no_time
+	ld a, SCRIPT_WAIT
+	ld [wScriptMode], a
+	call StopScript
+	ret
+
+Script_ptpriorityjump:
+; script command 0x8f
+; parameters: pointer
+
+	call StopScript
+	jp Script_jump
+
+Script_end:
+; script command 0x91
+
+	call ExitScriptSubroutine
+	jr c, .resume
+	ret
+
+.resume
+	xor a
+	ld [wScriptRunning], a
+	ld a, SCRIPT_OFF
+	ld [wScriptMode], a
+	ld hl, wScriptFlags
+	res 0, [hl]
+	call StopScript
+	ret
+
+Script_return:
+; script command 0x90
+
+	call ExitScriptSubroutine
+	jr c, .dummy
+.dummy
+	ld hl, wScriptFlags
+	res 0, [hl]
+	call StopScript
+	ret
+
+ExitScriptSubroutine:
+; Return carry if there's no parent to return to.
+
+	ld hl, wScriptStackSize
+	ld a, [hl]
+	and a
+	jr z, .done
+	dec [hl]
+	ld e, [hl]
+	ld d, $0
+	ld hl, wScriptStack
+	add hl, de
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld b, a
+	and " "
+	ld [wScriptBank], a
+	ld a, [hli]
+	ld e, a
+	ld [wScriptPos], a
+	ld a, [hl]
+	ld d, a
+	ld [wScriptPos + 1], a
+	and a
+	ret
+.done
+	scf
+	ret
+
+Script_endall:
+; script command 0x93
+
+	xor a
+	ld [wScriptStackSize], a
+	ld [wScriptRunning], a
+	ld a, SCRIPT_OFF
+	ld [wScriptMode], a
+	ld hl, wScriptFlags
+	res 0, [hl]
+	call StopScript
+	ret
+
+Script_halloffame:
+; script command 0xa1
+
+	ld hl, wGameTimerPause
+	res GAMETIMERPAUSE_TIMER_PAUSED_F, [hl]
+	farcall StubbedTrainerRankings_HallOfFame
+	farcall StubbedTrainerRankings_HallOfFame2
+	farcall HallOfFame
+	ld hl, wGameTimerPause
+	set GAMETIMERPAUSE_TIMER_PAUSED_F, [hl]
+	jr ReturnFromCredits
+
+Script_credits:
+; script command 0xa2
+
+	farcall RedCredits
+ReturnFromCredits:
+	call Script_endall
+	ld a, $3
+	call LoadMapStatus
+	call StopScript
+	ret
+
+Script_wait:
+; script command 0xa8
+; parameters: unknown
+
+	push bc
+	call GetScriptByte
+.loop
+	push af
+	ld c, 6
+	call DelayFrames
+	pop af
+	dec a
+	jr nz, .loop
+	pop bc
+	ret
+
+Script_checksave:
+; script command 0xa9
+
+	farcall CheckSave
+	ld a, c
+	ld [wScriptVar], a
+	ret
+
+
+; unused
+	ld a, [.byte]
+	ld [wScriptVar], a
+	ret
+
+.byte
+	db 0
--- /dev/null
+++ b/engine/overworld/select_menu.asm
@@ -1,0 +1,191 @@
+SelectMenu:: ; 13327
+
+	call CheckRegisteredItem
+	jr c, .NotRegistered
+	jp UseRegisteredItem
+
+.NotRegistered:
+	call OpenText
+	ld b, BANK(ItemMayBeRegisteredText)
+	ld hl, ItemMayBeRegisteredText
+	call MapTextbox
+	call WaitButton
+	jp CloseText
+; 13340
+
+
+ItemMayBeRegisteredText: ; 13340
+	text_jump UnknownText_0x1c1cf3
+	db "@"
+; 13345
+
+
+CheckRegisteredItem: ; 13345
+
+	ld a, [wWhichRegisteredItem]
+	and a
+	jr z, .NoRegisteredItem
+	and REGISTERED_POCKET
+	rlca
+	rlca
+	ld hl, .Pockets
+	rst JumpTable
+	ret
+
+.Pockets:
+; entries correspond to *_POCKET constants
+	dw .CheckItem
+	dw .CheckBall
+	dw .CheckKeyItem
+	dw .CheckTMHM
+
+.CheckItem:
+	ld hl, wNumItems
+	call .CheckRegisteredNo
+	jr c, .NoRegisteredItem
+	inc hl
+	ld e, a
+	ld d, 0
+	add hl, de
+	add hl, de
+	call .IsSameItem
+	jr c, .NoRegisteredItem
+	and a
+	ret
+
+.CheckKeyItem:
+	ld a, [wRegisteredItem]
+	ld hl, wKeyItems
+	ld de, 1
+	call IsInArray
+	jr nc, .NoRegisteredItem
+	ld a, [wRegisteredItem]
+	ld [wCurItem], a
+	and a
+	ret
+
+.CheckBall:
+	ld hl, wNumBalls
+	call .CheckRegisteredNo
+	jr nc, .NoRegisteredItem
+	inc hl
+	ld e, a
+	ld d, 0
+	add hl, de
+	add hl, de
+	call .IsSameItem
+	jr c, .NoRegisteredItem
+	ret
+
+.CheckTMHM:
+	jr .NoRegisteredItem
+
+.NoRegisteredItem:
+	xor a
+	ld [wWhichRegisteredItem], a
+	ld [wRegisteredItem], a
+	scf
+	ret
+; 133a6
+
+
+.CheckRegisteredNo: ; 133a6
+	ld a, [wWhichRegisteredItem]
+	and REGISTERED_NUMBER
+	dec a
+	cp [hl]
+	jr nc, .NotEnoughItems
+	ld [wCurItemQuantity], a
+	and a
+	ret
+
+.NotEnoughItems:
+	scf
+	ret
+; 133b6
+
+
+.IsSameItem: ; 133b6
+	ld a, [wRegisteredItem]
+	cp [hl]
+	jr nz, .NotSameItem
+	ld [wCurItem], a
+	and a
+	ret
+
+.NotSameItem:
+	scf
+	ret
+; 133c3
+
+
+UseRegisteredItem: ; 133c3
+
+	farcall CheckItemMenu
+	ld a, [wItemAttributeParamBuffer]
+	ld hl, .SwitchTo
+	rst JumpTable
+	ret
+
+.SwitchTo:
+; entries correspond to ITEMMENU_* constants
+	dw .CantUse
+	dw .NoFunction
+	dw .NoFunction
+	dw .NoFunction
+	dw .Current
+	dw .Party
+	dw .Overworld
+; 133df
+
+.NoFunction: ; 133df
+	call OpenText
+	call CantUseItem
+	call CloseText
+	and a
+	ret
+; 133ea
+
+.Current: ; 133ea
+	call OpenText
+	call DoItemEffect
+	call CloseText
+	and a
+	ret
+; 133f5
+
+.Party: ; 133f5
+	call RefreshScreen
+	call FadeToMenu
+	call DoItemEffect
+	call CloseSubmenu
+	call CloseText
+	and a
+	ret
+; 13406
+
+.Overworld: ; 13406
+	call RefreshScreen
+	ld a, 1
+	ld [wUsingItemWithSelect], a
+	call DoItemEffect
+	xor a
+	ld [wUsingItemWithSelect], a
+	ld a, [wItemEffectSucceeded]
+	cp 1
+	jr nz, ._cantuse
+	scf
+	ld a, HMENURETURN_SCRIPT
+	ld [hMenuReturn], a
+	ret
+; 13422
+
+.CantUse: ; 13422
+	call RefreshScreen
+
+._cantuse
+	call CantUseItem
+	call CloseText
+	and a
+	ret
+; 1342d
--- /dev/null
+++ b/engine/overworld/spawn_points.asm
@@ -1,0 +1,62 @@
+INCLUDE "data/maps/spawn_points.asm"
+
+
+LoadSpawnPoint: ; 1531f
+	; loads the spawn point in wDefaultSpawnpoint
+	push hl
+	push de
+	ld a, [wDefaultSpawnpoint]
+	cp SPAWN_N_A
+	jr z, .spawn_n_a
+	ld l, a
+	ld h, 0
+	add hl, hl
+	add hl, hl
+	ld de, SpawnPoints
+	add hl, de
+	ld a, [hli]
+	ld [wMapGroup], a
+	ld a, [hli]
+	ld [wMapNumber], a
+	ld a, [hli]
+	ld [wXCoord], a
+	ld a, [hli]
+	ld [wYCoord], a
+.spawn_n_a
+	pop de
+	pop hl
+	ret
+; 15344
+
+
+IsSpawnPoint: ; 15344
+; Checks if the map loaded in de is a spawn point.  Returns carry if it's a spawn point.
+	ld hl, SpawnPoints
+	ld c, 0
+.loop
+	ld a, [hl]
+	cp SPAWN_N_A
+	jr z, .nope
+	cp d
+	jr nz, .next
+	inc hl
+	ld a, [hld]
+	cp e
+	jr z, .yes
+
+.next
+	push bc
+	ld bc, 4 ; length of a spawn table entry
+	add hl, bc
+	pop bc
+	inc c
+	jr .loop
+
+.nope
+	and a
+	ret
+
+.yes
+	scf
+	ret
+; 15363
--- /dev/null
+++ b/engine/overworld/tile_events.asm
@@ -1,0 +1,110 @@
+CheckWarpCollision:: ; 1499a
+; Is this tile a warp?
+	ld a, [wPlayerStandingTile]
+	cp COLL_PIT
+	jr z, .warp
+	cp COLL_PIT_68
+	jr z, .warp
+	and $f0
+	cp HI_NYBBLE_WARPS
+	jr z, .warp
+	and a
+	ret
+
+.warp
+	scf
+	ret
+; 149af
+
+CheckDirectionalWarp:: ; 149af
+; If this is a directional warp, clear carry (press the designated button to warp).
+; Else, set carry (immediate warp).
+	ld a, [wPlayerStandingTile]
+	cp COLL_WARP_CARPET_DOWN
+	jr z, .directional
+	cp COLL_WARP_CARPET_LEFT
+	jr z, .directional
+	cp COLL_WARP_CARPET_UP
+	jr z, .directional
+	cp COLL_WARP_CARPET_RIGHT
+	jr z, .directional
+	scf
+	ret
+
+.directional
+	xor a
+	ret
+; 149c6
+
+CheckWarpFacingDown: ; 149c6
+	ld de, 1
+	ld hl, .blocks
+	ld a, [wPlayerStandingTile]
+	call IsInArray
+	ret
+; 149d3
+
+.blocks ; 149d3
+	db COLL_DOOR
+	db COLL_DOOR_79
+	db COLL_STAIRCASE
+	db COLL_STAIRCASE_73
+	db COLL_CAVE
+	db COLL_CAVE_74
+	db COLL_WARP_PANEL
+	db COLL_DOOR_75
+	db COLL_DOOR_7D
+	db -1
+; 149dd
+
+CheckGrassCollision:: ; 149dd
+	ld a, [wPlayerStandingTile]
+	ld hl, .blocks
+	ld de, 1
+	call IsInArray
+	ret
+; 149ea
+
+.blocks ; 149ea
+	db COLL_CUT_08
+	db COLL_TALL_GRASS
+	db COLL_LONG_GRASS
+	db COLL_CUT_28
+	db COLL_WATER
+	db COLL_GRASS_48
+	db COLL_GRASS_49
+	db COLL_GRASS_4A
+	db COLL_GRASS_4B
+	db COLL_GRASS_4C
+	db -1
+; 149f5
+
+CheckCutCollision: ; 149f5
+	ld a, c
+	ld hl, .blocks
+	ld de, 1
+	call IsInArray
+	ret
+; 14a00
+
+.blocks ; 14a00
+	db COLL_CUT_TREE
+	db COLL_CUT_TREE_1A
+	db COLL_TALL_GRASS_10
+	db COLL_TALL_GRASS
+	db COLL_LONG_GRASS
+	db COLL_LONG_GRASS_1C
+	db -1
+; 14a07
+
+GetWarpSFX:: ; 14a07
+	ld a, [wPlayerStandingTile]
+	ld de, SFX_ENTER_DOOR
+	cp COLL_DOOR
+	ret z
+	ld de, SFX_WARP_TO
+	cp COLL_WARP_PANEL
+	ret z
+	ld de, SFX_EXIT_BUILDING
+	ret
+; 14a1a
--- /dev/null
+++ b/engine/overworld/time.asm
@@ -1,0 +1,465 @@
+_InitializeStartDay: ; 113d6
+	call InitializeStartDay
+	ret
+; 113da
+
+ClearDailyTimers: ; 113da
+	xor a
+	ld [wLuckyNumberDayBuffer], a
+	ld [wUnusedTwoDayTimer], a
+	ld [wDailyResetTimer], a
+	ret
+; 113e5
+
+InitCallReceiveDelay:: ; 113e5
+	xor a
+	ld [wTimeCyclesSinceLastCall], a
+
+NextCallReceiveDelay: ; 113e9
+	ld a, [wTimeCyclesSinceLastCall]
+	cp 3
+	jr c, .okay
+	ld a, 3
+
+.okay
+	ld e, a
+	ld d, 0
+	ld hl, .ReceiveCallDelays
+	add hl, de
+	ld a, [hl]
+	jp RestartReceiveCallDelay
+; 113fd
+
+.ReceiveCallDelays:
+	db 20, 10, 5, 3
+; 11401
+
+CheckReceiveCallTimer: ; 11401
+	call CheckReceiveCallDelay ; check timer
+	ret nc
+	ld hl, wTimeCyclesSinceLastCall
+	ld a, [hl]
+	cp 3
+	jr nc, .ok
+	inc [hl]
+
+.ok
+	call NextCallReceiveDelay ; restart timer
+	scf
+	ret
+; 11413
+
+InitOneDayCountdown: ; 11413
+	ld a, 1
+
+InitNDaysCountdown: ; 11415
+	ld [hl], a
+	push hl
+	call UpdateTime
+	pop hl
+	inc hl
+	call CopyDayToHL
+	ret
+; 11420
+
+CheckDayDependentEventHL: ; 11420
+	inc hl
+	push hl
+	call CalcDaysSince
+	call GetDaysSince
+	pop hl
+	dec hl
+	call UpdateTimeRemaining
+	ret
+; 1142e
+
+RestartReceiveCallDelay: ; 1142e
+	ld hl, wReceiveCallDelay_MinsRemaining
+	ld [hl], a
+	call UpdateTime
+	ld hl, wReceiveCallDelay_StartTime
+	call CopyDayHourMinToHL
+	ret
+; 1143c
+
+CheckReceiveCallDelay: ; 1143c
+	ld hl, wReceiveCallDelay_StartTime
+	call CalcMinsHoursDaysSince
+	call GetMinutesSinceIfLessThan60
+	ld hl, wReceiveCallDelay_MinsRemaining
+	call UpdateTimeRemaining
+	ret
+; 1144c
+
+RestartDailyResetTimer: ; 1144c
+	ld hl, wDailyResetTimer
+	jp InitOneDayCountdown
+; 11452
+
+CheckDailyResetTimer:: ; 11452
+	ld hl, wDailyResetTimer
+	call CheckDayDependentEventHL
+	ret nc
+	xor a
+	ld hl, wDailyFlags
+	ld [hli], a ; wDailyFlags
+	ld [hli], a ; wWeeklyFlags
+	ld [hli], a ; wSwarmFlags
+	ld [hl], a  ; wSwarmFlags + 1
+	ld hl, wDailyRematchFlags
+rept 4
+	ld [hli], a
+endr
+	ld hl, wDailyPhoneItemFlags
+rept 4
+	ld [hli], a
+endr
+	ld hl, wDailyPhoneTimeOfDayFlags
+rept 4
+	ld [hli], a
+endr
+	ld hl, wKenjiBreakTimer
+	ld a, [hl]
+	and a
+	jr z, .RestartKenjiBreakCountdown
+	dec [hl]
+	jr nz, .DontRestartKenjiBreakCountdown
+.RestartKenjiBreakCountdown:
+	call SampleKenjiBreakCountdown
+.DontRestartKenjiBreakCountdown:
+	jr RestartDailyResetTimer
+; 11485
+
+SampleKenjiBreakCountdown: ; 11485
+; Generate a random number between 3 and 6
+	call Random
+	and %11
+	add 3
+	ld [wKenjiBreakTimer], a
+	ret
+; 11490
+
+StartBugContestTimer: ; 11490
+	ld a, BUG_CONTEST_MINUTES
+	ld [wBugContestMinsRemaining], a
+	ld a, BUG_CONTEST_SECONDS
+	ld [wBugContestSecsRemaining], a
+	call UpdateTime
+	ld hl, wBugContestStartTime
+	call CopyDayHourMinSecToHL
+	ret
+; 114a4
+
+
+CheckBugContestTimer:: ; 114a4 (4:54a4)
+	ld hl, wBugContestStartTime
+	call CalcSecsMinsHoursDaysSince
+	ld a, [wDaysSince]
+	and a
+	jr nz, .timed_out
+	ld a, [wHoursSince]
+	and a
+	jr nz, .timed_out
+	ld a, [wSecondsSince]
+	ld b, a
+	ld a, [wBugContestSecsRemaining]
+	sub b
+	jr nc, .okay
+	add 60
+
+.okay
+	ld [wBugContestSecsRemaining], a
+	ld a, [wMinutesSince]
+	ld b, a
+	ld a, [wBugContestMinsRemaining]
+	sbc b
+	ld [wBugContestMinsRemaining], a
+	jr c, .timed_out
+	and a
+	ret
+
+.timed_out
+	xor a
+	ld [wBugContestMinsRemaining], a
+	ld [wBugContestSecsRemaining], a
+	scf
+	ret
+
+
+InitializeStartDay: ; 114dd
+	call UpdateTime
+	ld hl, wTimerEventStartDay
+	call CopyDayToHL
+	ret
+; 114e7
+
+CheckPokerusTick:: ; 114e7
+	ld hl, wTimerEventStartDay
+	call CalcDaysSince
+	call GetDaysSince
+	and a
+	jr z, .done ; not even a day has passed since game start
+	ld b, a
+	farcall ApplyPokerusTick
+.done
+	xor a
+	ret
+; 114fc
+
+SetUnusedTwoDayTimer: ; 114fc
+	ld a, 2
+	ld hl, wUnusedTwoDayTimer
+	ld [hl], a
+	call UpdateTime
+	ld hl, wUnusedTwoDayTimerStartDate
+	call CopyDayToHL
+	ret
+; 1150c
+
+CheckUnusedTwoDayTimer: ; 1150c
+	ld hl, wUnusedTwoDayTimerStartDate
+	call CalcDaysSince
+	call GetDaysSince
+	ld hl, wUnusedTwoDayTimer
+	call UpdateTimeRemaining
+	ret
+; 1151c
+
+; unused
+	ld hl, wDailyFlags
+	set DAILYFLAGS_FISH_SWARM_F, [hl]
+	ret
+; 11522
+
+; unused
+	and a
+	ld hl, wDailyFlags
+	bit DAILYFLAGS_FISH_SWARM_F, [hl]
+	ret nz
+	scf
+	ret
+; 1152b
+
+RestartLuckyNumberCountdown: ; 1152b
+	call .GetDaysUntilNextFriday
+	ld hl, wLuckyNumberDayBuffer
+	jp InitNDaysCountdown
+; 11534
+
+.GetDaysUntilNextFriday: ; 11534
+	call GetWeekday
+	ld c, a
+	ld a, FRIDAY
+	sub c
+	jr z, .friday_saturday
+	jr nc, .earlier ; could have done "ret nc"
+
+.friday_saturday
+	add 7
+
+.earlier
+	ret
+; 11542
+
+_CheckLuckyNumberShowFlag: ; 11542
+	ld hl, wLuckyNumberDayBuffer
+	jp CheckDayDependentEventHL
+; 11548
+
+DoMysteryGiftIfDayHasPassed: ; 11548
+	ld a, BANK(sMysteryGiftTimer)
+	call GetSRAMBank
+	ld hl, sMysteryGiftTimer
+	ld a, [hli]
+	ld [wBuffer1], a
+	ld a, [hl]
+	ld [wBuffer2], a
+	call CloseSRAM
+
+	ld hl, wBuffer1
+	call CheckDayDependentEventHL
+	jr nc, .not_timed_out
+	ld hl, wBuffer1
+	call InitOneDayCountdown
+	call CloseSRAM
+	farcall Function1050c8
+
+.not_timed_out
+	ld a, BANK(sMysteryGiftTimer)
+	call GetSRAMBank
+	ld hl, wBuffer1
+	ld a, [hli]
+	ld [sMysteryGiftTimer], a
+	ld a, [hl]
+	ld [sMysteryGiftTimer + 1], a
+	call CloseSRAM
+	ret
+; 11586
+
+UpdateTimeRemaining: ; 11586
+; If the amount of time elapsed exceeds the capacity of its
+; unit, skip this part.
+	cp -1
+	jr z, .set_carry
+	ld c, a
+	ld a, [hl] ; time remaining
+	sub c
+	jr nc, .ok
+	xor a
+
+.ok
+	ld [hl], a
+	jr z, .set_carry
+	xor a
+	ret
+
+.set_carry
+	xor a
+	ld [hl], a
+	scf
+	ret
+; 11599
+
+GetSecondsSinceIfLessThan60: ; 11599
+	ld a, [wDaysSince]
+	and a
+	jr nz, GetTimeElapsed_ExceedsUnitLimit
+	ld a, [wHoursSince]
+	and a
+	jr nz, GetTimeElapsed_ExceedsUnitLimit
+	ld a, [wMinutesSince]
+	jr nz, GetTimeElapsed_ExceedsUnitLimit
+	ld a, [wSecondsSince]
+	ret
+; 115ae
+
+GetMinutesSinceIfLessThan60: ; 115ae
+	ld a, [wDaysSince]
+	and a
+	jr nz, GetTimeElapsed_ExceedsUnitLimit
+	ld a, [wHoursSince]
+	and a
+	jr nz, GetTimeElapsed_ExceedsUnitLimit
+	ld a, [wMinutesSince]
+	ret
+; 115be
+
+GetHoursSinceIfLessThan24: ; 115be
+	ld a, [wDaysSince]
+	and a
+	jr nz, GetTimeElapsed_ExceedsUnitLimit
+	ld a, [wHoursSince]
+	ret
+; 115c8
+
+GetDaysSince: ; 115c8
+	ld a, [wDaysSince]
+	ret
+; 115cc
+
+GetTimeElapsed_ExceedsUnitLimit: ; 115cc
+	ld a, -1
+	ret
+; 115cf
+
+CalcDaysSince: ; 115cf
+	xor a
+	jr _CalcDaysSince
+; 115d2
+
+CalcHoursDaysSince: ; 115d2
+	inc hl
+	xor a
+	jr _CalcHoursDaysSince
+; 115d6
+
+CalcMinsHoursDaysSince: ; 115d6
+	inc hl
+	inc hl
+	xor a
+	jr _CalcMinsHoursDaysSince
+; 115db
+
+CalcSecsMinsHoursDaysSince: ; 115db
+	inc hl
+	inc hl
+	inc hl
+	ld a, [hSeconds]
+	ld c, a
+	sub [hl]
+	jr nc, .skip
+	add 60
+.skip
+	ld [hl], c ; current seconds
+	dec hl
+	ld [wSecondsSince], a ; seconds since
+
+_CalcMinsHoursDaysSince: ; 115eb
+	ld a, [hMinutes]
+	ld c, a
+	sbc [hl]
+	jr nc, .skip
+	add 60
+.skip
+	ld [hl], c ; current minutes
+	dec hl
+	ld [wMinutesSince], a ; minutes since
+
+_CalcHoursDaysSince: ; 115f8
+	ld a, [hHours]
+	ld c, a
+	sbc [hl]
+	jr nc, .skip
+	add 24
+.skip
+	ld [hl], c ; current hours
+	dec hl
+	ld [wHoursSince], a ; hours since
+
+_CalcDaysSince:
+	ld a, [wCurDay]
+	ld c, a
+	sbc [hl]
+	jr nc, .skip
+	add 20 * 7
+.skip
+	ld [hl], c ; current days
+	ld [wDaysSince], a ; days since
+	ret
+; 11613
+
+CopyDayHourMinSecToHL: ; 11613
+	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
+; 11621
+
+CopyDayToHL: ; 11621
+	ld a, [wCurDay]
+	ld [hl], a
+	ret
+; 11626
+
+CopyDayHourToHL: ; 11626
+	ld a, [wCurDay]
+	ld [hli], a
+	ld a, [hHours]
+	ld [hli], a
+	ret
+; 1162e
+
+CopyDayHourMinToHL: ; 1162e
+	ld a, [wCurDay]
+	ld [hli], a
+	ld a, [hHours]
+	ld [hli], a
+	ld a, [hMinutes]
+	ld [hli], a
+	ret
+; 11639
--- /dev/null
+++ b/engine/overworld/variables.asm
@@ -1,0 +1,151 @@
+_GetVarAction:: ; 80648 (20:4648)
+	ld a, c
+	cp NUM_VARS
+	jr c, .valid
+	xor a
+.valid
+	ld c, a
+	ld b, 0
+	ld hl, .VarActionTable
+	add hl, bc
+	add hl, bc
+	add hl, bc
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	inc hl
+	ld b, [hl]
+	ld a, b
+	and RETVAR_EXECUTE
+	jr nz, .call
+	ld a, b
+	and RETVAR_ADDR_DE
+	ret nz
+	ld a, [de]
+	jr .loadstringbuffer2
+
+.call
+	call _de_
+	ret
+
+.loadstringbuffer2 ; 8066c (20:466c)
+	ld de, wStringBuffer2
+	ld [de], a
+	ret
+; 80671 (20:4671)
+
+.VarActionTable: ; 80671
+; entries correspond to VAR_* constants
+	; RETVAR_STRBUF2: copy [de] to wStringBuffer2
+	; RETVAR_ADDR_DE: return address in de
+	; RETVAR_EXECUTE: call function
+	dwb wStringBuffer2,                 RETVAR_STRBUF2
+	dwb wPartyCount,                    RETVAR_STRBUF2
+	dwb .BattleResult,                  RETVAR_EXECUTE
+	dwb wBattleType,                    RETVAR_ADDR_DE
+	dwb wTimeOfDay,                     RETVAR_STRBUF2
+	dwb .CountCaughtMons,               RETVAR_EXECUTE
+	dwb .CountSeenMons,                 RETVAR_EXECUTE
+	dwb .CountBadges,                   RETVAR_EXECUTE
+	dwb wPlayerState,                   RETVAR_ADDR_DE
+	dwb .PlayerFacing,                  RETVAR_EXECUTE
+	dwb hHours,                         RETVAR_STRBUF2
+	dwb .DayOfWeek,                     RETVAR_EXECUTE
+	dwb wMapGroup,                      RETVAR_STRBUF2
+	dwb wMapNumber,                     RETVAR_STRBUF2
+	dwb .UnownCaught,                   RETVAR_EXECUTE
+	dwb wEnvironment,                   RETVAR_STRBUF2
+	dwb .BoxFreeSpace,                  RETVAR_EXECUTE
+	dwb wBugContestMinsRemaining,       RETVAR_STRBUF2
+	dwb wXCoord,                        RETVAR_STRBUF2
+	dwb wYCoord,                        RETVAR_STRBUF2
+	dwb wSpecialPhoneCallID,            RETVAR_STRBUF2
+	dwb wNrOfBeatenBattleTowerTrainers, RETVAR_STRBUF2
+	dwb wKurtApricornQuantity,          RETVAR_STRBUF2
+	dwb wCurrentCaller,                 RETVAR_ADDR_DE
+	dwb wBlueCardBalance,               RETVAR_ADDR_DE
+	dwb wBuenasPassword,                RETVAR_ADDR_DE
+	dwb wKenjiBreakTimer,               RETVAR_STRBUF2
+	dwb NULL,                           RETVAR_STRBUF2
+; 806c5
+
+.CountCaughtMons: ; 806c5
+; Caught mons.
+	ld hl, wPokedexCaught
+	ld b, wEndPokedexCaught - wPokedexCaught
+	call CountSetBits
+	ld a, [wd265]
+	jp .loadstringbuffer2
+; 806d3
+
+.CountSeenMons: ; 806d3
+; Seen mons.
+	ld hl, wPokedexSeen
+	ld b, wEndPokedexSeen - wPokedexSeen
+	call CountSetBits
+	ld a, [wd265]
+	jp .loadstringbuffer2
+; 806e1
+
+.CountBadges: ; 806e1
+; Number of owned badges.
+	ld hl, wBadges
+	ld b, 2
+	call CountSetBits
+	ld a, [wd265]
+	jp .loadstringbuffer2
+; 806ef
+
+.PlayerFacing: ; 806ef
+; The direction the player is facing.
+	ld a, [wPlayerDirection]
+	and $c
+	rrca
+	rrca
+	jp .loadstringbuffer2
+; 806f9
+
+.DayOfWeek: ; 806f9
+; The day of the week.
+	call GetWeekday
+	jp .loadstringbuffer2
+; 806ff
+
+.UnownCaught: ; 806ff
+; Number of unique Unown caught.
+	call .count
+	ld a, b
+	jp .loadstringbuffer2
+
+.count
+	ld hl, wUnownDex
+	ld b, 0
+.loop
+	ld a, [hli]
+	and a
+	ret z
+	inc b
+	ld a, b
+	cp NUM_UNOWN
+	jr c, .loop
+	ret
+; 80715
+
+.BoxFreeSpace: ; 80715
+; Remaining slots in the current box.
+	ld a, BANK(sBoxCount)
+	call GetSRAMBank
+	ld hl, sBoxCount
+	ld a, MONS_PER_BOX
+	sub [hl]
+	ld b, a
+	call CloseSRAM
+	ld a, b
+	jp .loadstringbuffer2
+; 80728
+
+.BattleResult: ; 80728
+	ld a, [wBattleResult]
+	and $3f
+	jp .loadstringbuffer2
+; 80730
--- /dev/null
+++ b/engine/overworld/warp_connection.asm
@@ -1,0 +1,439 @@
+
+HandleNewMap: ; 1045b0
+	call Clearwc7e8
+	call ResetMapBufferEventFlags
+	call ResetFlashIfOutOfCave
+	call GetCurrentMapSceneID
+	call ResetBikeFlags
+	ld a, MAPCALLBACK_NEWMAP
+	call RunMapCallback
+InitCommandQueue: ; 1045c4
+	farcall ClearCmdQueue
+	ld a, MAPCALLBACK_CMDQUEUE
+	call RunMapCallback
+	call GetMapTimeOfDay
+	ld [wMapTimeOfDay], a
+	ret
+
+
+EnterMapConnection: ; 1045d6
+; Return carry if a connection has been entered.
+	ld a, [wPlayerStepDirection]
+	and a
+	jp z, .south
+	cp UP
+	jp z, .north
+	cp LEFT
+	jp z, .west
+	cp RIGHT
+	jp z, .east
+	ret
+
+.west
+	ld a, [wWestConnectedMapGroup]
+	ld [wMapGroup], a
+	ld a, [wWestConnectedMapNumber]
+	ld [wMapNumber], a
+	ld a, [wWestConnectionStripXOffset]
+	ld [wXCoord], a
+	ld a, [wWestConnectionStripYOffset]
+	ld hl, wYCoord
+	add [hl]
+	ld [hl], a
+	ld c, a
+	ld hl, wWestConnectionWindow
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	srl c
+	jr z, .skip_to_load
+	ld a, [wWestConnectedMapWidth]
+	add 6
+	ld e, a
+	ld d, 0
+
+.loop
+	add hl, de
+	dec c
+	jr nz, .loop
+
+.skip_to_load
+	ld a, l
+	ld [wOverworldMapAnchor], a
+	ld a, h
+	ld [wOverworldMapAnchor + 1], a
+	jp .done
+
+.east
+	ld a, [wEastConnectedMapGroup]
+	ld [wMapGroup], a
+	ld a, [wEastConnectedMapNumber]
+	ld [wMapNumber], a
+	ld a, [wEastConnectionStripXOffset]
+	ld [wXCoord], a
+	ld a, [wEastConnectionStripYOffset]
+	ld hl, wYCoord
+	add [hl]
+	ld [hl], a
+	ld c, a
+	ld hl, wEastConnectionWindow
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	srl c
+	jr z, .skip_to_load2
+	ld a, [wEastConnectedMapWidth]
+	add 6
+	ld e, a
+	ld d, 0
+
+.loop2
+	add hl, de
+	dec c
+	jr nz, .loop2
+
+.skip_to_load2
+	ld a, l
+	ld [wOverworldMapAnchor], a
+	ld a, h
+	ld [wOverworldMapAnchor + 1], a
+	jp .done
+
+.north
+	ld a, [wNorthConnectedMapGroup]
+	ld [wMapGroup], a
+	ld a, [wNorthConnectedMapNumber]
+	ld [wMapNumber], a
+	ld a, [wNorthConnectionStripYOffset]
+	ld [wYCoord], a
+	ld a, [wNorthConnectionStripXOffset]
+	ld hl, wXCoord
+	add [hl]
+	ld [hl], a
+	ld c, a
+	ld hl, wNorthConnectionWindow
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld b, 0
+	srl c
+	add hl, bc
+	ld a, l
+	ld [wOverworldMapAnchor], a
+	ld a, h
+	ld [wOverworldMapAnchor + 1], a
+	jp .done
+
+.south
+	ld a, [wSouthConnectedMapGroup]
+	ld [wMapGroup], a
+	ld a, [wSouthConnectedMapNumber]
+	ld [wMapNumber], a
+	ld a, [wSouthConnectionStripYOffset]
+	ld [wYCoord], a
+	ld a, [wSouthConnectionStripXOffset]
+	ld hl, wXCoord
+	add [hl]
+	ld [hl], a
+	ld c, a
+	ld hl, wSouthConnectionWindow
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld b, 0
+	srl c
+	add hl, bc
+	ld a, l
+	ld [wOverworldMapAnchor], a
+	ld a, h
+	ld [wOverworldMapAnchor + 1], a
+.done
+	scf
+	ret
+; 1046c6
+
+LoadWarpData: ; 1046c6
+	call .SaveDigWarp
+	call .SetSpawn
+	ld a, [wNextWarp]
+	ld [wWarpNumber], a
+	ld a, [wNextMapGroup]
+	ld [wMapGroup], a
+	ld a, [wNextMapNumber]
+	ld [wMapNumber], a
+	ret
+
+.SaveDigWarp: ; 1046df (41:46df)
+	call GetMapEnvironment
+	call CheckOutdoorMap
+	ret nz
+	ld a, [wNextMapGroup]
+	ld b, a
+	ld a, [wNextMapNumber]
+	ld c, a
+	call GetAnyMapEnvironment
+	call CheckIndoorMap
+	ret nz
+
+; MOUNT_MOON_SQUARE and TIN_TOWER_ROOF are outdoor maps within indoor maps.
+; Dig and Escape Rope should not take you to them.
+	ld a, [wPrevMapGroup]
+	cp GROUP_MOUNT_MOON_SQUARE ; GROUP_TIN_TOWER_ROOF
+	jr nz, .not_mt_moon_or_tin_tower
+	ld a, [wPrevMapNumber]
+	cp MAP_MOUNT_MOON_SQUARE
+	ret z
+	cp MAP_TIN_TOWER_ROOF
+	ret z
+.not_mt_moon_or_tin_tower
+
+	ld a, [wPrevWarp]
+	ld [wDigWarpNumber], a
+	ld a, [wPrevMapGroup]
+	ld [wDigMapGroup], a
+	ld a, [wPrevMapNumber]
+	ld [wDigMapNumber], a
+	ret
+
+.SetSpawn: ; 104718 (41:4718)
+	call GetMapEnvironment
+	call CheckOutdoorMap
+	ret nz
+	ld a, [wNextMapGroup]
+	ld b, a
+	ld a, [wNextMapNumber]
+	ld c, a
+	call GetAnyMapEnvironment
+	call CheckIndoorMap
+	ret nz
+	ld a, [wNextMapGroup]
+	ld b, a
+	ld a, [wNextMapNumber]
+	ld c, a
+
+; Respawn in Pokémon Centers.
+	call GetAnyMapTileset
+	ld a, c
+	cp TILESET_POKECENTER
+	jr z, .pokecenter_pokecom
+	cp TILESET_POKECOM_CENTER
+	jr z, .pokecenter_pokecom
+	ret
+.pokecenter_pokecom
+
+	ld a, [wPrevMapGroup]
+	ld [wLastSpawnMapGroup], a
+	ld a, [wPrevMapNumber]
+	ld [wLastSpawnMapNumber], a
+	ret
+
+LoadMapTimeOfDay: ; 104750
+	ld hl, wVramState
+	res 6, [hl]
+	ld a, $1
+	ld [wSpriteUpdatesEnabled], a
+	farcall ReplaceTimeOfDayPals
+	farcall UpdateTimeOfDayPal
+	call OverworldTextModeSwitch
+	call .ClearBGMap
+	call .PushAttrMap
+	ret
+
+.ClearBGMap: ; 104770 (41:4770)
+	ld a, HIGH(vBGMap0)
+	ld [wBGMapAnchor + 1], a
+	xor a ; LOW(vBGMap0)
+	ld [wBGMapAnchor], a
+	ld [hSCY], a
+	ld [hSCX], a
+	farcall ApplyBGMapAnchorToObjects
+
+	ld a, [rVBK]
+	push af
+	ld a, $1
+	ld [rVBK], a
+
+	xor a
+	ld bc, vBGMap1 - vBGMap0
+	hlbgcoord 0, 0
+	call ByteFill
+
+	pop af
+	ld [rVBK], a
+
+	ld a, "■"
+	ld bc, vBGMap1 - vBGMap0
+	hlbgcoord 0, 0
+	call ByteFill
+	ret
+
+.PushAttrMap: ; 1047a3 (41:47a3)
+	decoord 0, 0
+	call .copy
+	ld a, [hCGB]
+	and a
+	ret z
+
+	decoord 0, 0, wAttrMap
+	ld a, $1
+	ld [rVBK], a
+.copy
+	hlbgcoord 0, 0
+	ld c, SCREEN_WIDTH
+	ld b, SCREEN_HEIGHT
+.row
+	push bc
+.column
+	ld a, [de]
+	inc de
+	ld [hli], a
+	dec c
+	jr nz, .column
+	ld bc, BG_MAP_WIDTH - SCREEN_WIDTH
+	add hl, bc
+	pop bc
+	dec b
+	jr nz, .row
+	ld a, $0
+	ld [rVBK], a
+	ret
+
+LoadGraphics: ; 1047cf
+	call LoadTileset
+	call LoadTilesetGFX
+	xor a
+	ld [hMapAnims], a
+	xor a
+	ld [hTileAnimFrame], a
+	farcall RefreshSprites
+	call LoadFontsExtra
+	farcall LoadOverworldFont
+	ret
+
+LoadMapPalettes: ; 1047eb
+	ld b, SCGB_MAPPALS
+	jp GetSGBLayout
+; 1047f0
+
+RefreshMapSprites: ; 1047f0
+	call ClearSprites
+	farcall ReturnFromMapSetupScript
+	call GetMovementPermissions
+	farcall RefreshPlayerSprite
+	farcall CheckReplaceKrisSprite
+	ld hl, wPlayerSpriteSetupFlags
+	bit PLAYERSPRITESETUP_SKIP_RELOAD_GFX_F, [hl]
+	jr nz, .skip
+	ld hl, wVramState
+	set 0, [hl]
+	call SafeUpdateSprites
+.skip
+	ld a, [wPlayerSpriteSetupFlags]
+	and %00011100
+	ld [wPlayerSpriteSetupFlags], a
+	ret
+
+CheckMovingOffEdgeOfMap:: ; 104820 (41:4820)
+	ld a, [wPlayerStepDirection]
+	cp STANDING
+	ret z
+	and a ; DOWN
+	jr z, .down
+	cp UP
+	jr z, .up
+	cp LEFT
+	jr z, .left
+	cp RIGHT
+	jr z, .right
+	and a
+	ret
+
+.down
+	ld a, [wPlayerStandingMapY]
+	sub 4
+	ld b, a
+	ld a, [wMapHeight]
+	add a
+	cp b
+	jr z, .ok
+	and a
+	ret
+
+.up
+	ld a, [wPlayerStandingMapY]
+	sub 4
+	cp -1
+	jr z, .ok
+	and a
+	ret
+
+.left
+	ld a, [wPlayerStandingMapX]
+	sub 4
+	cp -1
+	jr z, .ok
+	and a
+	ret
+
+.right
+	ld a, [wPlayerStandingMapX]
+	sub 4
+	ld b, a
+	ld a, [wMapWidth]
+	add a
+	cp b
+	jr z, .ok
+	and a
+	ret
+
+.ok
+	scf
+	ret
+
+
+GetCoordOfUpperLeftCorner:: ; 10486d
+	ld hl, wOverworldMap
+	ld a, [wXCoord]
+	bit 0, a
+	jr nz, .increment_then_halve1
+	srl a
+	add $1
+	jr .resume
+
+.increment_then_halve1
+	add $1
+	srl a
+
+.resume
+	ld c, a
+	ld b, $0
+	add hl, bc
+	ld a, [wMapWidth]
+	add $6
+	ld c, a
+	ld b, $0
+	ld a, [wYCoord]
+	bit 0, a
+	jr nz, .increment_then_halve2
+	srl a
+	add $1
+	jr .resume2
+
+.increment_then_halve2
+	add $1
+	srl a
+
+.resume2
+	call AddNTimes
+	ld a, l
+	ld [wOverworldMapAnchor], a
+	ld a, h
+	ld [wOverworldMapAnchor + 1], a
+	ld a, [wYCoord]
+	and $1
+	ld [wMetatileStandingY], a
+	ld a, [wXCoord]
+	and $1
+	ld [wMetatileStandingX], a
+	ret
+; 1048ba
--- /dev/null
+++ b/engine/overworld/wildmons.asm
@@ -1,0 +1,1000 @@
+LoadWildMonData: ; 29ff8
+	call _GrassWildmonLookup
+	jr c, .copy
+	ld hl, wMornEncounterRate
+	xor a
+	ld [hli], a
+	ld [hli], a
+	ld [hl], a
+	jr .done_copy
+
+.copy
+	inc hl
+	inc hl
+	ld de, wMornEncounterRate
+	ld bc, 3
+	call CopyBytes
+.done_copy
+	call _WaterWildmonLookup
+	ld a, 0
+	jr nc, .no_copy
+	inc hl
+	inc hl
+	ld a, [hl]
+.no_copy
+	ld [wWaterEncounterRate], a
+	ret
+
+FindNest: ; 2a01f
+; Parameters:
+; e: 0 = Johto, 1 = Kanto
+; wNamedObjectIndexBuffer: species
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	xor a
+	call ByteFill
+	ld a, e
+	and a
+	jr nz, .kanto
+	decoord 0, 0
+	ld hl, JohtoGrassWildMons
+	call .FindGrass
+	ld hl, JohtoWaterWildMons
+	call .FindWater
+	call .RoamMon1
+	call .RoamMon2
+	ret
+
+.kanto
+	decoord 0, 0
+	ld hl, KantoGrassWildMons
+	call .FindGrass
+	ld hl, KantoWaterWildMons
+	jp .FindWater
+; 2a052
+
+.FindGrass: ; 2a052
+	ld a, [hl]
+	cp -1
+	ret z
+	push hl
+	ld a, [hli]
+	ld b, a
+	ld a, [hli]
+	ld c, a
+	inc hl
+	inc hl
+	inc hl
+	ld a, NUM_GRASSMON * 3
+	call .SearchMapForMon
+	jr nc, .next_grass
+	ld [de], a
+	inc de
+
+.next_grass
+	pop hl
+	ld bc, GRASS_WILDDATA_LENGTH
+	add hl, bc
+	jr .FindGrass
+; 2a06e
+
+.FindWater: ; 2a06e
+	ld a, [hl]
+	cp -1
+	ret z
+	push hl
+	ld a, [hli]
+	ld b, a
+	ld a, [hli]
+	ld c, a
+	inc hl
+	ld a, 3
+	call .SearchMapForMon
+	jr nc, .next_water
+	ld [de], a
+	inc de
+
+.next_water
+	pop hl
+	ld bc, 3 * 3
+	add hl, bc
+	jr .FindWater
+; 2a088
+
+.SearchMapForMon: ; 2a088
+	inc hl
+.ScanMapLoop:
+	push af
+	ld a, [wNamedObjectIndexBuffer]
+	cp [hl]
+	jr z, .found
+	inc hl
+	inc hl
+	pop af
+	dec a
+	jr nz, .ScanMapLoop
+	and a
+	ret
+
+.found
+	pop af
+	jp .AppendNest
+; 2a09c
+
+.AppendNest: ; 2a09c
+	push de
+	call GetWorldMapLocation
+	ld c, a
+	hlcoord 0, 0
+	ld de, SCREEN_WIDTH * SCREEN_HEIGHT
+.AppendNestLoop:
+	ld a, [hli]
+	cp c
+	jr z, .found_nest
+	dec de
+	ld a, e
+	or d
+	jr nz, .AppendNestLoop
+	ld a, c
+	pop de
+	scf
+	ret
+
+.found_nest
+	pop de
+	and a
+	ret
+; 2a0b7
+
+.RoamMon1: ; 2a0b7
+	ld a, [wRoamMon1Species]
+	ld b, a
+	ld a, [wNamedObjectIndexBuffer]
+	cp b
+	ret nz
+	ld a, [wRoamMon1MapGroup]
+	ld b, a
+	ld a, [wRoamMon1MapNumber]
+	ld c, a
+	call .AppendNest
+	ret nc
+	ld [de], a
+	inc de
+	ret
+; 2a0cf
+
+.RoamMon2: ; 2a0cf
+	ld a, [wRoamMon2Species]
+	ld b, a
+	ld a, [wNamedObjectIndexBuffer]
+	cp b
+	ret nz
+	ld a, [wRoamMon2MapGroup]
+	ld b, a
+	ld a, [wRoamMon2MapNumber]
+	ld c, a
+	call .AppendNest
+	ret nc
+	ld [de], a
+	inc de
+	ret
+; 2a0e7
+
+TryWildEncounter:: ; 2a0e7
+; Try to trigger a wild encounter.
+	call .EncounterRate
+	jr nc, .no_battle
+	call ChooseWildEncounter
+	jr nz, .no_battle
+	call CheckRepelEffect
+	jr nc, .no_battle
+	xor a
+	ret
+
+.no_battle
+	xor a ; BATTLETYPE_NORMAL
+	ld [wTempWildMonSpecies], a
+	ld [wBattleType], a
+	ld a, 1
+	and a
+	ret
+; 2a103
+
+.EncounterRate: ; 2a103
+	call GetMapEncounterRate
+	call ApplyMusicEffectOnEncounterRate
+	call ApplyCleanseTagEffectOnEncounterRate
+	call Random
+	cp b
+	ret
+; 2a111
+
+GetMapEncounterRate: ; 2a111
+	ld hl, wMornEncounterRate
+	call CheckOnWater
+	ld a, wWaterEncounterRate - wMornEncounterRate
+	jr z, .ok
+	ld a, [wTimeOfDay]
+.ok
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld b, [hl]
+	ret
+; 2a124
+
+ApplyMusicEffectOnEncounterRate:: ; 2a124
+; Pokemon March and Ruins of Alph signal double encounter rate.
+; Pokemon Lullaby halves encounter rate.
+	ld a, [wMapMusic]
+	cp MUSIC_POKEMON_MARCH
+	jr z, .double
+	cp MUSIC_RUINS_OF_ALPH_RADIO
+	jr z, .double
+	cp MUSIC_POKEMON_LULLABY
+	ret nz
+	srl b
+	ret
+
+.double
+	sla b
+	ret
+; 2a138
+
+ApplyCleanseTagEffectOnEncounterRate:: ; 2a138
+; Cleanse Tag halves encounter rate.
+	ld hl, wPartyMon1Item
+	ld de, PARTYMON_STRUCT_LENGTH
+	ld a, [wPartyCount]
+	ld c, a
+.loop
+	ld a, [hl]
+	cp CLEANSE_TAG
+	jr z, .cleansetag
+	add hl, de
+	dec c
+	jr nz, .loop
+	ret
+
+.cleansetag
+	srl b
+	ret
+; 2a14f
+
+ChooseWildEncounter: ; 2a14f
+	call LoadWildMonDataPointer
+	jp nc, .nowildbattle
+	call CheckEncounterRoamMon
+	jp c, .startwildbattle
+
+	inc hl
+	inc hl
+	inc hl
+	call CheckOnWater
+	ld de, WaterMonProbTable
+	jr z, .watermon
+	inc hl
+	inc hl
+	ld a, [wTimeOfDay]
+	ld bc, $e
+	call AddNTimes
+	ld de, GrassMonProbTable
+
+.watermon
+; hl contains the pointer to the wild mon data, let's save that to the stack
+	push hl
+.randomloop
+	call Random
+	cp 100
+	jr nc, .randomloop
+	inc a ; 1 <= a <= 100
+	ld b, a
+	ld h, d
+	ld l, e
+; This next loop chooses which mon to load up.
+.prob_bracket_loop
+	ld a, [hli]
+	cp b
+	jr nc, .got_it
+	inc hl
+	jr .prob_bracket_loop
+
+.got_it
+	ld c, [hl]
+	ld b, 0
+	pop hl
+	add hl, bc ; this selects our mon
+	ld a, [hli]
+	ld b, a
+; If the Pokemon is encountered by surfing, we need to give the levels some variety.
+	call CheckOnWater
+	jr nz, .ok
+; Check if we buff the wild mon, and by how much.
+	call Random
+	cp 35 percent
+	jr c, .ok
+	inc b
+	cp 65 percent
+	jr c, .ok
+	inc b
+	cp 85 percent
+	jr c, .ok
+	inc b
+	cp 95 percent
+	jr c, .ok
+	inc b
+; Store the level
+.ok
+	ld a, b
+	ld [wCurPartyLevel], a
+	ld b, [hl]
+	; ld a, b
+	call ValidateTempWildMonSpecies
+	jr c, .nowildbattle
+
+	ld a, b ; This is in the wrong place.
+	cp UNOWN
+	jr nz, .done
+
+	ld a, [wUnlockedUnowns]
+	and a
+	jr z, .nowildbattle
+
+.done
+	jr .loadwildmon
+
+.nowildbattle
+	ld a, 1
+	and a
+	ret
+
+.loadwildmon
+	ld a, b
+	ld [wTempWildMonSpecies], a
+
+.startwildbattle
+	xor a
+	ret
+; 2a1cb
+
+INCLUDE "data/wild/probabilities.asm"
+
+CheckRepelEffect:: ; 2a1df
+; If there is no active Repel, there's no need to be here.
+	ld a, [wRepelEffect]
+	and a
+	jr z, .encounter
+; Get the first Pokemon in your party that isn't fainted.
+	ld hl, wPartyMon1HP
+	ld bc, PARTYMON_STRUCT_LENGTH - 1
+.loop
+	ld a, [hli]
+	or [hl]
+	jr nz, .ok
+	add hl, bc
+	jr .loop
+
+.ok
+; to PartyMonLevel
+rept 4
+	dec hl
+endr
+
+	ld a, [wCurPartyLevel]
+	cp [hl]
+	jr nc, .encounter
+	and a
+	ret
+
+.encounter
+	scf
+	ret
+; 2a200
+
+LoadWildMonDataPointer: ; 2a200
+	call CheckOnWater
+	jr z, _WaterWildmonLookup
+
+_GrassWildmonLookup: ; 2a205
+	ld hl, SwarmGrassWildMons
+	ld bc, GRASS_WILDDATA_LENGTH
+	call _SwarmWildmonCheck
+	ret c
+	ld hl, JohtoGrassWildMons
+	ld de, KantoGrassWildMons
+	call _JohtoWildmonCheck
+	ld bc, GRASS_WILDDATA_LENGTH
+	jr _NormalWildmonOK
+
+_WaterWildmonLookup: ; 2a21d
+	ld hl, SwarmWaterWildMons
+	ld bc, WATER_WILDDATA_LENGTH
+	call _SwarmWildmonCheck
+	ret c
+	ld hl, JohtoWaterWildMons
+	ld de, KantoWaterWildMons
+	call _JohtoWildmonCheck
+	ld bc, WATER_WILDDATA_LENGTH
+	jr _NormalWildmonOK
+
+_JohtoWildmonCheck
+	call IsInJohto
+	and a
+	ret z
+	ld h, d
+	ld l, e
+	ret
+
+_SwarmWildmonCheck
+	call CopyCurrMapDE
+	push hl
+	ld hl, wSwarmFlags
+	bit SWARMFLAGS_DUNSPARCE_SWARM_F, [hl]
+	pop hl
+	jr z, .CheckYanma
+	ld a, [wDunsparceMapGroup]
+	cp d
+	jr nz, .CheckYanma
+	ld a, [wDunsparceMapNumber]
+	cp e
+	jr nz, .CheckYanma
+	call LookUpWildmonsForMapDE
+	jr nc, _NoSwarmWildmon
+	scf
+	ret
+
+.CheckYanma:
+	push hl
+	ld hl, wSwarmFlags
+	bit SWARMFLAGS_YANMA_SWARM_F, [hl]
+	pop hl
+	jr z, _NoSwarmWildmon
+	ld a, [wYanmaMapGroup]
+	cp d
+	jr nz, _NoSwarmWildmon
+	ld a, [wYanmaMapNumber]
+	cp e
+	jr nz, _NoSwarmWildmon
+	call LookUpWildmonsForMapDE
+	jr nc, _NoSwarmWildmon
+	scf
+	ret
+
+_NoSwarmWildmon
+	and a
+	ret
+
+_NormalWildmonOK
+	call CopyCurrMapDE
+	jr LookUpWildmonsForMapDE
+; 2a27f
+
+CopyCurrMapDE: ; 2a27f
+	ld a, [wMapGroup]
+	ld d, a
+	ld a, [wMapNumber]
+	ld e, a
+	ret
+; 2a288
+
+LookUpWildmonsForMapDE: ; 2a288
+.loop
+	push hl
+	ld a, [hl]
+	inc a
+	jr z, .nope
+	ld a, d
+	cp [hl]
+	jr nz, .next
+	inc hl
+	ld a, e
+	cp [hl]
+	jr z, .yup
+
+.next
+	pop hl
+	add hl, bc
+	jr .loop
+
+.nope
+	pop hl
+	and a
+	ret
+
+.yup
+	pop hl
+	scf
+	ret
+; 2a2a0
+
+
+InitRoamMons: ; 2a2a0
+; initialize wRoamMon structs
+
+; species
+	ld a, RAIKOU
+	ld [wRoamMon1Species], a
+	ld a, ENTEI
+	ld [wRoamMon2Species], a
+
+; level
+	ld a, 40
+	ld [wRoamMon1Level], a
+	ld [wRoamMon2Level], a
+
+; raikou starting map
+	ld a, GROUP_ROUTE_42
+	ld [wRoamMon1MapGroup], a
+	ld a, MAP_ROUTE_42
+	ld [wRoamMon1MapNumber], a
+
+; entei starting map
+	ld a, GROUP_ROUTE_37
+	ld [wRoamMon2MapGroup], a
+	ld a, MAP_ROUTE_37
+	ld [wRoamMon2MapNumber], a
+
+; hp
+	xor a ; generate new stats
+	ld [wRoamMon1HP], a
+	ld [wRoamMon2HP], a
+
+	ret
+; 2a2ce
+
+
+CheckEncounterRoamMon: ; 2a2ce
+	push hl
+; Don't trigger an encounter if we're on water.
+	call CheckOnWater
+	jr z, .DontEncounterRoamMon
+; Load the current map group and number to de
+	call CopyCurrMapDE
+; Randomly select a beast.
+	call Random
+	cp 100 ; 25/64 chance
+	jr nc, .DontEncounterRoamMon
+	and %00000011 ; Of that, a 3/4 chance.  Running total: 75/256, or around 29.3%.
+	jr z, .DontEncounterRoamMon
+	dec a ; 1/3 chance that it's Entei, 1/3 chance that it's Raikou
+; Compare its current location with yours
+	ld hl, wRoamMon1MapGroup
+	ld c, a
+	ld b, 0
+	ld a, 7 ; length of the roam_struct
+	call AddNTimes
+	ld a, d
+	cp [hl]
+	jr nz, .DontEncounterRoamMon
+	inc hl
+	ld a, e
+	cp [hl]
+	jr nz, .DontEncounterRoamMon
+; We've decided to take on a beast, so stage its information for battle.
+	dec hl
+	dec hl
+	dec hl
+	ld a, [hli]
+	ld [wTempWildMonSpecies], a
+	ld a, [hl]
+	ld [wCurPartyLevel], a
+	ld a, BATTLETYPE_ROAMING
+	ld [wBattleType], a
+
+	pop hl
+	scf
+	ret
+
+.DontEncounterRoamMon:
+	pop hl
+	and a
+	ret
+; 2a30d
+
+
+UpdateRoamMons: ; 2a30d
+	ld a, [wRoamMon1MapGroup]
+	cp GROUP_N_A
+	jr z, .SkipRaikou
+	ld b, a
+	ld a, [wRoamMon1MapNumber]
+	ld c, a
+	call .Update
+	ld a, b
+	ld [wRoamMon1MapGroup], a
+	ld a, c
+	ld [wRoamMon1MapNumber], a
+
+.SkipRaikou:
+	ld a, [wRoamMon2MapGroup]
+	cp GROUP_N_A
+	jr z, .SkipEntei
+	ld b, a
+	ld a, [wRoamMon2MapNumber]
+	ld c, a
+	call .Update
+	ld a, b
+	ld [wRoamMon2MapGroup], a
+	ld a, c
+	ld [wRoamMon2MapNumber], a
+
+.SkipEntei:
+	ld a, [wRoamMon3MapGroup]
+	cp GROUP_N_A
+	jr z, .Finished
+	ld b, a
+	ld a, [wRoamMon3MapNumber]
+	ld c, a
+	call .Update
+	ld a, b
+	ld [wRoamMon3MapGroup], a
+	ld a, c
+	ld [wRoamMon3MapNumber], a
+
+.Finished:
+	jp _BackUpMapIndices
+; 2a355
+
+
+.Update: ; 2a355
+	ld hl, RoamMaps
+.loop
+; Are we at the end of the table?
+	ld a, [hl]
+	cp -1
+	ret z
+; Is this the correct entry?
+	ld a, b
+	cp [hl]
+	jr nz, .next
+	inc hl
+	ld a, c
+	cp [hl]
+	jr z, .yes
+; We don't have the correct entry yet, so let's continue.  A 0 terminates each entry.
+.next
+	ld a, [hli]
+	and a
+	jr nz, .next
+	jr .loop
+
+; We have the correct entry now, so let's choose a random map from it.
+.yes
+	inc hl
+	ld d, h
+	ld e, l
+.update_loop
+	ld h, d
+	ld l, e
+; Choose which map to warp to.
+	call Random
+	and %00011111 ; 1/8n chance it moves to a completely random map, where n is the number of roaming connections from the current map.
+	jr z, JumpRoamMon
+	and %11
+	cp [hl]
+	jr nc, .update_loop ; invalid index, try again
+	inc hl
+	ld c, a
+	ld b, $0
+	add hl, bc
+	add hl, bc
+	ld a, [wRoamMons_LastMapGroup]
+	cp [hl]
+	jr nz, .done
+	inc hl
+	ld a, [wRoamMons_LastMapNumber]
+	cp [hl]
+	jr z, .update_loop
+	dec hl
+
+.done
+	ld a, [hli]
+	ld b, a
+	ld c, [hl]
+	ret
+
+JumpRoamMons: ; 2a394
+	ld a, [wRoamMon1MapGroup]
+	cp GROUP_N_A
+	jr z, .SkipRaikou
+	call JumpRoamMon
+	ld a, b
+	ld [wRoamMon1MapGroup], a
+	ld a, c
+	ld [wRoamMon1MapNumber], a
+
+.SkipRaikou:
+	ld a, [wRoamMon2MapGroup]
+	cp GROUP_N_A
+	jr z, .SkipEntei
+	call JumpRoamMon
+	ld a, b
+	ld [wRoamMon2MapGroup], a
+	ld a, c
+	ld [wRoamMon2MapNumber], a
+
+.SkipEntei:
+	ld a, [wRoamMon3MapGroup]
+	cp GROUP_N_A
+	jr z, .Finished
+	call JumpRoamMon
+	ld a, b
+	ld [wRoamMon3MapGroup], a
+	ld a, c
+	ld [wRoamMon3MapNumber], a
+
+.Finished:
+	jp _BackUpMapIndices
+
+JumpRoamMon: ; 2a3cd
+.loop
+	ld hl, RoamMaps
+.innerloop1                   ; This loop happens to be unnecessary.
+	call Random               ; Choose a random number.
+	maskbits NUM_ROAMMON_MAPS ; Mask the number to limit it between 0 and 15.
+	cp NUM_ROAMMON_MAPS       ; If the number is not less than 16, try again.
+	jr nc, .innerloop1        ; I'm sure you can guess why this check is bogus.
+	inc a
+	ld b, a
+.innerloop2 ; Loop to get hl to the address of the chosen roam map.
+	dec b
+	jr z, .ok
+.innerloop3 ; Loop to skip the current roam map, which is terminated by a 0.
+	ld a, [hli]
+	and a
+	jr nz, .innerloop3
+	jr .innerloop2
+; Check to see if the selected map is the one the player is currently in.  If so, try again.
+.ok
+	ld a, [wMapGroup]
+	cp [hl]
+	jr nz, .done
+	inc hl
+	ld a, [wMapNumber]
+	cp [hl]
+	jr z, .loop
+	dec hl
+; Return the map group and number in bc.
+.done
+	ld a, [hli]
+	ld b, a
+	ld c, [hl]
+	ret
+; 2a3f6
+
+_BackUpMapIndices: ; 2a3f6
+	ld a, [wRoamMons_CurrentMapNumber]
+	ld [wRoamMons_LastMapNumber], a
+	ld a, [wRoamMons_CurrentMapGroup]
+	ld [wRoamMons_LastMapGroup], a
+	ld a, [wMapNumber]
+	ld [wRoamMons_CurrentMapNumber], a
+	ld a, [wMapGroup]
+	ld [wRoamMons_CurrentMapGroup], a
+	ret
+; 2a40f
+
+
+INCLUDE "data/wild/roammon_maps.asm"
+
+
+ValidateTempWildMonSpecies: ; 2a4a0
+; Due to a development oversight, this function is called with the wild Pokemon's level, not its species, in a.
+	and a
+	jr z, .nowildmon ; = 0
+	cp NUM_POKEMON + 1 ; 252
+	jr nc, .nowildmon ; >= 252
+	and a ; 1 <= Species <= 251
+	ret
+
+.nowildmon
+	scf
+	ret
+; 2a4ab
+
+; Finds a rare wild Pokemon in the route of the trainer calling, then checks if it's been Seen already.
+; The trainer will then tell you about the Pokemon if you haven't seen it.
+RandomUnseenWildMon: ; 2a4ab
+	farcall GetCallerLocation
+	ld d, b
+	ld e, c
+	ld hl, JohtoGrassWildMons
+	ld bc, GRASS_WILDDATA_LENGTH
+	call LookUpWildmonsForMapDE
+	jr c, .GetGrassmon
+	ld hl, KantoGrassWildMons
+	call LookUpWildmonsForMapDE
+	jr nc, .done
+
+.GetGrassmon:
+	push hl
+	ld bc, 5 + 4 * 2 ; Location of the level of the 5th wild Pokemon in that map
+	add hl, bc
+	ld a, [wTimeOfDay]
+	ld bc, NUM_GRASSMON * 2
+	call AddNTimes
+.randloop1
+	call Random
+	and %11
+	jr z, .randloop1
+	dec a
+	ld c, a
+	ld b, $0
+	add hl, bc
+	add hl, bc
+; We now have the pointer to one of the last (rarest) three wild Pokemon found in that area.
+	inc hl
+	ld c, [hl] ; Contains the species index of this rare Pokemon
+	pop hl
+	ld de, 5 + 0 * 2
+	add hl, de
+	inc hl ; Species index of the most common Pokemon on that route
+	ld b, 4
+.loop2
+	ld a, [hli]
+	cp c ; Compare this most common Pokemon with the rare one stored in c.
+	jr z, .done
+	inc hl
+	dec b
+	jr nz, .loop2
+; This Pokemon truly is rare.
+	push bc
+	dec c
+	ld a, c
+	call CheckSeenMon
+	pop bc
+	jr nz, .done
+; Since we haven't seen it, have the caller tell us about it.
+	ld de, wStringBuffer1
+	call CopyName1
+	ld a, c
+	ld [wNamedObjectIndexBuffer], a
+	call GetPokemonName
+	ld hl, .SawRareMonText
+	call PrintText
+	xor a
+	ld [wScriptVar], a
+	ret
+
+.done
+	ld a, $1
+	ld [wScriptVar], a
+	ret
+
+.SawRareMonText:
+	; I just saw some rare @  in @ . I'll call you if I see another rare #MON, OK?
+	text_jump UnknownText_0x1bd34b
+	db "@"
+; 0x2a51f
+
+RandomPhoneWildMon: ; 2a51f
+	farcall GetCallerLocation
+	ld d, b
+	ld e, c
+	ld hl, JohtoGrassWildMons
+	ld bc, GRASS_WILDDATA_LENGTH
+	call LookUpWildmonsForMapDE
+	jr c, .ok
+	ld hl, KantoGrassWildMons
+	call LookUpWildmonsForMapDE
+
+.ok
+	ld bc, 5 + 0 * 2
+	add hl, bc
+	ld a, [wTimeOfDay]
+	inc a
+	ld bc, NUM_GRASSMON * 2
+.loop
+	dec a
+	jr z, .done
+	add hl, bc
+	jr .loop
+
+.done
+	call Random
+	and %11
+	ld c, a
+	ld b, $0
+	add hl, bc
+	add hl, bc
+	inc hl
+	ld a, [hl]
+	ld [wNamedObjectIndexBuffer], a
+	call GetPokemonName
+	ld hl, wStringBuffer1
+	ld de, wStringBuffer4
+	ld bc, MON_NAME_LENGTH
+	jp CopyBytes
+; 2a567
+
+RandomPhoneMon: ; 2a567
+; Get a random monster owned by the trainer who's calling.
+	farcall GetCallerLocation
+	ld hl, TrainerGroups
+	ld a, d
+	dec a
+	ld c, a
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	ld a, BANK(TrainerGroups)
+	call GetFarHalfword
+
+.skip_trainer
+	dec e
+	jr z, .skipped
+.skip
+	ld a, BANK(Trainers)
+	call GetFarByte
+	inc hl
+	cp -1
+	jr nz, .skip
+	jr .skip_trainer
+.skipped
+
+.skip_name
+	ld a, BANK(Trainers)
+	call GetFarByte
+	inc hl
+	cp "@"
+	jr nz, .skip_name
+
+	ld a, BANK(Trainers)
+	call GetFarByte
+	inc hl
+	ld bc, 2 ; level, species
+	cp TRAINERTYPE_NORMAL
+	jr z, .got_mon_length
+	ld bc, 2 + NUM_MOVES ; level, species, moves
+	cp TRAINERTYPE_MOVES
+	jr z, .got_mon_length
+	ld bc, 2 + 1 ; level, species, item
+	cp TRAINERTYPE_ITEM
+	jr z, .got_mon_length
+	; TRAINERTYPE_ITEM_MOVES
+	ld bc, 2 + 1 + NUM_MOVES ; level, species, item, moves
+.got_mon_length
+
+	ld e, 0
+	push hl
+.count_mon
+	inc e
+	add hl, bc
+	ld a, BANK(Trainers)
+	call GetFarByte
+	cp -1
+	jr nz, .count_mon
+	pop hl
+
+.rand
+	call Random
+	maskbits PARTY_LENGTH
+	cp e
+	jr nc, .rand
+
+	inc a
+.get_mon
+	dec a
+	jr z, .got_mon
+	add hl, bc
+	jr .get_mon
+.got_mon
+
+	inc hl ; species
+	ld a, BANK(Trainers)
+	call GetFarByte
+	ld [wNamedObjectIndexBuffer], a
+	call GetPokemonName
+	ld hl, wStringBuffer1
+	ld de, wStringBuffer4
+	ld bc, MON_NAME_LENGTH
+	jp CopyBytes
+; 2a5e9
+
+
+INCLUDE "data/wild/johto_grass.asm"
+INCLUDE "data/wild/johto_water.asm"
+INCLUDE "data/wild/kanto_grass.asm"
+INCLUDE "data/wild/kanto_water.asm"
+INCLUDE "data/wild/swarm_grass.asm"
+INCLUDE "data/wild/swarm_water.asm"
--- a/engine/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/party_menu.asm
+++ /dev/null
@@ -1,932 +1,0 @@
-SelectMonFromParty: ; 50000
-	call DisableSpriteUpdates
-	xor a
-	ld [wPartyMenuActionText], a
-	call ClearBGPalettes
-	call InitPartyMenuLayout
-	call WaitBGMap
-	call SetPalettes
-	call DelayFrame
-	call PartyMenuSelect
-	call ReturnToMapWithSpeechTextbox
-	ret
-; 5001d
-
-
-SelectTradeOrDayCareMon: ; 5001d
-	ld a, b
-	ld [wPartyMenuActionText], a
-	call DisableSpriteUpdates
-	call ClearBGPalettes
-	call InitPartyMenuLayout
-	call WaitBGMap
-	ld b, SCGB_PARTY_MENU
-	call GetSGBLayout
-	call SetPalettes
-	call DelayFrame
-	call PartyMenuSelect
-	call ReturnToMapWithSpeechTextbox
-	ret
-; 5003f
-
-InitPartyMenuLayout: ; 5003f
-	call LoadPartyMenuGFX
-	call InitPartyMenuWithCancel
-	call InitPartyMenuGFX
-	call WritePartyMenuTilemap
-	call PrintPartyMenuText
-	ret
-; 5004f
-
-LoadPartyMenuGFX: ; 5004f
-	call LoadFontsBattleExtra
-	callfar InitPartyMenuPalettes ; engine/color.asm
-	callfar ClearSpriteAnims2
-	ret
-; 5005f
-
-
-WritePartyMenuTilemap: ; 0x5005f
-	ld hl, wOptions
-	ld a, [hl]
-	push af
-	set NO_TEXT_SCROLL, [hl]
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, " "
-	call ByteFill ; blank the tilemap
-	call GetPartyMenuQualityIndexes
-.loop
-	ld a, [hli]
-	cp -1
-	jr z, .end
-	push hl
-	ld hl, .Jumptable
-	rst JumpTable
-	pop hl
-	jr .loop
-.end
-	pop af
-	ld [wOptions], a
-	ret
-; 0x50089
-
-.Jumptable: ; 50089
-; entries correspond to PARTYMENUQUALITY_* constants
-	dw PlacePartyNicknames
-	dw PlacePartyHPBar
-	dw PlacePartyMenuHPDigits
-	dw PlacePartyMonLevel
-	dw PlacePartyMonStatus
-	dw PlacePartyMonTMHMCompatibility
-	dw PlacePartyMonEvoStoneCompatibility
-	dw PlacePartyMonGender
-	dw PlacePartyMonMobileBattleSelection
-; 5009b
-
-PlacePartyNicknames: ; 5009b
-	hlcoord 3, 1
-	ld a, [wPartyCount]
-	and a
-	jr z, .end
-	ld c, a
-	ld b, $0
-.loop
-	push bc
-	push hl
-	push hl
-	ld hl, wPartyMonNicknames
-	ld a, b
-	call GetNick
-	pop hl
-	call PlaceString
-	pop hl
-	ld de, 2 * SCREEN_WIDTH
-	add hl, de
-	pop bc
-	inc b
-	dec c
-	jr nz, .loop
-
-.end
-	dec hl
-	dec hl
-	ld de, .CANCEL
-	call PlaceString
-	ret
-; 500c8
-
-.CANCEL: ; 500c8
-	db "CANCEL@"
-; 500cf
-
-
-PlacePartyHPBar: ; 500cf
-	xor a
-	ld [wSGBPals], a
-	ld a, [wPartyCount]
-	and a
-	ret z
-	ld c, a
-	ld b, $0
-	hlcoord 11, 2
-.loop
-	push bc
-	push hl
-	call PartyMenuCheckEgg
-	jr z, .skip
-	push hl
-	call PlacePartymonHPBar
-	pop hl
-	ld d, $6
-	ld b, $0
-	call DrawBattleHPBar
-	ld hl, wHPPals
-	ld a, [wSGBPals]
-	ld c, a
-	ld b, $0
-	add hl, bc
-	call SetHPPal
-	ld b, SCGB_PARTY_MENU_HP_PALS
-	call GetSGBLayout
-.skip
-	ld hl, wSGBPals
-	inc [hl]
-	pop hl
-	ld de, 2 * SCREEN_WIDTH
-	add hl, de
-	pop bc
-	inc b
-	dec c
-	jr nz, .loop
-	ld b, SCGB_PARTY_MENU
-	call GetSGBLayout
-	ret
-; 50117
-
-PlacePartymonHPBar: ; 50117
-	ld a, b
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld hl, wPartyMon1HP
-	call AddNTimes
-	ld a, [hli]
-	or [hl]
-	jr nz, .not_fainted
-	xor a
-	ld e, a
-	ld c, a
-	ret
-
-.not_fainted
-	dec hl
-	ld a, [hli]
-	ld b, a
-	ld a, [hli]
-	ld c, a
-	ld a, [hli]
-	ld d, a
-	ld a, [hli]
-	ld e, a
-	predef ComputeHPBarPixels
-	ret
-; 50138
-
-PlacePartyMenuHPDigits: ; 50138
-	ld a, [wPartyCount]
-	and a
-	ret z
-	ld c, a
-	ld b, $0
-	hlcoord 13, 1
-.loop
-	push bc
-	push hl
-	call PartyMenuCheckEgg
-	jr z, .next
-	push hl
-	ld a, b
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld hl, wPartyMon1HP
-	call AddNTimes
-	ld e, l
-	ld d, h
-	pop hl
-	push de
-	lb bc, 2, 3
-	call PrintNum
-	pop de
-	ld a, "/"
-	ld [hli], a
-	inc de
-	inc de
-	lb bc, 2, 3
-	call PrintNum
-
-.next
-	pop hl
-	ld de, 2 * SCREEN_WIDTH
-	add hl, de
-	pop bc
-	inc b
-	dec c
-	jr nz, .loop
-	ret
-; 50176
-
-PlacePartyMonLevel: ; 50176
-	ld a, [wPartyCount]
-	and a
-	ret z
-	ld c, a
-	ld b, 0
-	hlcoord 8, 2
-.loop
-	push bc
-	push hl
-	call PartyMenuCheckEgg
-	jr z, .next
-	push hl
-	ld a, b
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld hl, wPartyMon1Level
-	call AddNTimes
-	ld e, l
-	ld d, h
-	pop hl
-	ld a, [de]
-	cp 100 ; This is distinct from MAX_LEVEL.
-	jr nc, .ThreeDigits
-	ld a, "<LV>"
-	ld [hli], a
-	lb bc, PRINTNUM_RIGHTALIGN | 1, 2
-	; jr .okay
-.ThreeDigits:
-	lb bc, PRINTNUM_RIGHTALIGN | 1, 3
-; .okay
-	call PrintNum
-
-.next
-	pop hl
-	ld de, SCREEN_WIDTH * 2
-	add hl, de
-	pop bc
-	inc b
-	dec c
-	jr nz, .loop
-	ret
-; 501b2
-
-PlacePartyMonStatus: ; 501b2
-	ld a, [wPartyCount]
-	and a
-	ret z
-	ld c, a
-	ld b, 0
-	hlcoord 5, 2
-.loop
-	push bc
-	push hl
-	call PartyMenuCheckEgg
-	jr z, .next
-	push hl
-	ld a, b
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld hl, wPartyMon1Status
-	call AddNTimes
-	ld e, l
-	ld d, h
-	pop hl
-	call PlaceStatusString
-
-.next
-	pop hl
-	ld de, SCREEN_WIDTH * 2
-	add hl, de
-	pop bc
-	inc b
-	dec c
-	jr nz, .loop
-	ret
-; 501e0
-
-PlacePartyMonTMHMCompatibility: ; 501e0
-	ld a, [wPartyCount]
-	and a
-	ret z
-	ld c, a
-	ld b, 0
-	hlcoord 12, 2
-.loop
-	push bc
-	push hl
-	call PartyMenuCheckEgg
-	jr z, .next
-	push hl
-	ld hl, wPartySpecies
-	ld e, b
-	ld d, 0
-	add hl, de
-	ld a, [hl]
-	ld [wCurPartySpecies], a
-	predef CanLearnTMHMMove
-	pop hl
-	call .PlaceAbleNotAble
-	call PlaceString
-
-.next
-	pop hl
-	ld de, SCREEN_WIDTH * 2
-	add hl, de
-	pop bc
-	inc b
-	dec c
-	jr nz, .loop
-	ret
-; 50215
-
-.PlaceAbleNotAble: ; 50215
-	ld a, c
-	and a
-	jr nz, .able
-	ld de, .string_not_able
-	ret
-
-.able
-	ld de, .string_able
-	ret
-; 50221
-
-.string_able ; 50221
-	db "ABLE@"
-; 50226
-
-.string_not_able ; 50226
-	db "NOT ABLE@"
-; 5022f
-
-
-PlacePartyMonEvoStoneCompatibility: ; 5022f
-	ld a, [wPartyCount]
-	and a
-	ret z
-	ld c, a
-	ld b, 0
-	hlcoord 12, 2
-.loop
-	push bc
-	push hl
-	call PartyMenuCheckEgg
-	jr z, .next
-	push hl
-	ld a, b
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld hl, wPartyMon1Species
-	call AddNTimes
-	ld a, [hl]
-	dec a
-	ld e, a
-	ld d, 0
-	ld hl, EvosAttacksPointers
-	add hl, de
-	add hl, de
-	call .DetermineCompatibility
-	pop hl
-	call PlaceString
-
-.next
-	pop hl
-	ld de, 2 * SCREEN_WIDTH
-	add hl, de
-	pop bc
-	inc b
-	dec c
-	jr nz, .loop
-	ret
-; 50268
-
-.DetermineCompatibility: ; 50268
-	ld de, wStringBuffer1
-	ld a, BANK(EvosAttacksPointers)
-	ld bc, 2
-	call FarCopyBytes
-	ld hl, wStringBuffer1
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, wStringBuffer1
-	ld a, BANK(EvosAttacks)
-	ld bc, 10
-	call FarCopyBytes
-	ld hl, wStringBuffer1
-.loop2
-	ld a, [hli]
-	and a
-	jr z, .nope
-	inc hl
-	inc hl
-	cp EVOLVE_ITEM
-	jr nz, .loop2
-	dec hl
-	dec hl
-	ld a, [wCurItem]
-	cp [hl]
-	inc hl
-	inc hl
-	jr nz, .loop2
-	ld de, .string_able
-	ret
-
-.nope
-	ld de, .string_not_able
-	ret
-; 502a3
-
-.string_able ; 502a3
-	db "ABLE@"
-; 502a8
-.string_not_able ; 502a8
-	db "NOT ABLE@"
-; 502b1
-
-
-PlacePartyMonGender: ; 502b1
-	ld a, [wPartyCount]
-	and a
-	ret z
-	ld c, a
-	ld b, 0
-	hlcoord 12, 2
-.loop
-	push bc
-	push hl
-	call PartyMenuCheckEgg
-	jr z, .next
-	ld [wCurPartySpecies], a
-	push hl
-	ld a, b
-	ld [wCurPartyMon], a
-	xor a
-	ld [wMonType], a
-	call GetGender
-	ld de, .unknown
-	jr c, .got_gender
-	ld de, .male
-	jr nz, .got_gender
-	ld de, .female
-
-.got_gender
-	pop hl
-	call PlaceString
-
-.next
-	pop hl
-	ld de, 2 * SCREEN_WIDTH
-	add hl, de
-	pop bc
-	inc b
-	dec c
-	jr nz, .loop
-	ret
-; 502ee
-
-.male ; 502ee
-	db "♂…MALE@"
-; 502f5
-
-.female ; 502f5
-	db "♀…FEMALE@"
-; 502fe
-
-.unknown ; 502fe
-	db "…UNKNOWN@"
-; 50307
-
-
-PlacePartyMonMobileBattleSelection: ; 50307
-	ld a, [wPartyCount]
-	and a
-	ret z
-	ld c, a
-	ld b, 0
-	hlcoord 12, 1
-.loop
-	push bc
-	push hl
-	ld de, .String_Sanka_Shinai
-	call PlaceString
-	pop hl
-	ld de, 2 * SCREEN_WIDTH
-	add hl, de
-	pop bc
-	inc b
-	dec c
-	jr nz, .loop
-	ld a, l
-	ld e, MON_NAME_LENGTH
-	sub e
-	ld l, a
-	ld a, h
-	sbc $0
-	ld h, a
-	ld de, .String_Kettei_Yameru
-	call PlaceString
-	ld b, $3
-	ld c, $0
-	ld hl, wd002
-	ld a, [hl]
-.loop2
-	push hl
-	push bc
-	hlcoord 12, 1
-.loop3
-	and a
-	jr z, .done
-	ld de, 2 * SCREEN_WIDTH
-	add hl, de
-	dec a
-	jr .loop3
-
-.done
-	ld de, .String_Banme
-	push hl
-	call PlaceString
-	pop hl
-	pop bc
-	push bc
-	push hl
-	ld a, c
-	ld hl, .Strings_1_2_3
-	call GetNthString
-	ld d, h
-	ld e, l
-	pop hl
-	call PlaceString
-	pop bc
-	pop hl
-	inc hl
-	ld a, [hl]
-	inc c
-	dec b
-	ret z
-	jr .loop2
-; 5036b
-
-.String_Banme: ; 5036b
-	db " ばんめ  @" ; Place
-; 50372
-.String_Sanka_Shinai: ; 50372
-	db "さんかしない@" ; Cancel
-; 50379
-.String_Kettei_Yameru: ; 50379
-	db "けってい  やめる@" ; Quit
-; 50383
-.Strings_1_2_3: ; 50383
-	db "1@", "2@", "3@" ; 1st, 2nd, 3rd
-; 50389
-
-
-PartyMenuCheckEgg: ; 50389
-	ld a, LOW(wPartySpecies)
-	add b
-	ld e, a
-	ld a, HIGH(wPartySpecies)
-	adc 0
-	ld d, a
-	ld a, [de]
-	cp EGG
-	ret
-; 50396
-
-GetPartyMenuQualityIndexes: ; 50396
-	ld a, [wPartyMenuActionText]
-	and $f0
-	jr nz, .skip
-	ld a, [wPartyMenuActionText]
-	and $f
-	ld e, a
-	ld d, 0
-	ld hl, PartyMenuQualityPointers
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ret
-
-.skip
-	ld hl, PartyMenuQualityPointers.Default
-	ret
-; 503b2
-
-INCLUDE "data/party_menu_qualities.asm"
-
-
-InitPartyMenuGFX: ; 503e0
-	ld hl, wPartyCount
-	ld a, [hli]
-	and a
-	ret z
-	ld c, a
-	xor a
-	ld [hObjectStructIndexBuffer], a
-.loop
-	push bc
-	push hl
-	ld hl, LoadMenuMonIcon
-	ld a, BANK(LoadMenuMonIcon)
-	ld e, $0
-	rst FarCall
-	ld a, [hObjectStructIndexBuffer]
-	inc a
-	ld [hObjectStructIndexBuffer], a
-	pop hl
-	pop bc
-	dec c
-	jr nz, .loop
-	callfar PlaySpriteAnimations
-	ret
-; 50405
-
-InitPartyMenuWithCancel: ; 50405
-; with cancel
-	xor a
-	ld [wSwitchMon], a
-	ld de, PartyMenuAttributes
-	call SetMenuAttributes
-	ld a, [wPartyCount]
-	inc a
-	ld [w2DMenuNumRows], a ; list length
-	dec a
-	ld b, a
-	ld a, [wPartyMenuCursor]
-	and a
-	jr z, .skip
-	inc b
-	cp b
-	jr c, .done
-
-.skip
-	ld a, 1
-
-.done
-	ld [wMenuCursorY], a
-	ld a, A_BUTTON | B_BUTTON
-	ld [wMenuJoypadFilter], a
-	ret
-; 5042d
-
-InitPartyMenuNoCancel: ; 0x5042d
-; no cancel
-	ld de, PartyMenuAttributes
-	call SetMenuAttributes
-	ld a, [wPartyCount]
-	ld [w2DMenuNumRows], a ; list length
-	ld b, a
-	ld a, [wPartyMenuCursor]
-	and a
-	jr z, .skip
-	inc b
-	cp b
-	jr c, .done
-.skip
-	ld a, 1
-.done
-	ld [wMenuCursorY], a
-	ld a, A_BUTTON | B_BUTTON
-	ld [wMenuJoypadFilter], a
-	ret
-; 5044f (14:444f)
-
-PartyMenuAttributes: ; 5044f
-; cursor y
-; cursor x
-; num rows
-; num cols
-; bit 6: animate sprites  bit 5: wrap around
-; ?
-; distance between items (hi: y, lo: x)
-; allowed buttons (mask)
-	db 1, 0
-	db 0, 1
-	db $60, $00
-	dn 2, 0
-	db 0
-; 50457
-
-PartyMenuSelect: ; 0x50457
-; sets carry if exitted menu.
-	call StaticMenuJoypad
-	call PlaceHollowCursor
-	ld a, [wPartyCount]
-	inc a
-	ld b, a
-	ld a, [wMenuCursorY] ; menu selection?
-	cp b
-	jr z, .exitmenu ; CANCEL
-	ld [wPartyMenuCursor], a
-	ld a, [hJoyLast]
-	ld b, a
-	bit B_BUTTON_F, b
-	jr nz, .exitmenu ; B button
-	ld a, [wMenuCursorY]
-	dec a
-	ld [wCurPartyMon], a
-	ld c, a
-	ld b, $0
-	ld hl, wPartySpecies
-	add hl, bc
-	ld a, [hl]
-	ld [wCurPartySpecies], a
-
-	ld de, SFX_READ_TEXT_2
-	call PlaySFX
-	call WaitSFX
-	and a
-	ret
-
-.exitmenu
-	ld de, SFX_READ_TEXT_2
-	call PlaySFX
-	call WaitSFX
-	scf
-	ret
-; 0x5049a
-
-
-PrintPartyMenuText: ; 5049a
-	hlcoord 0, 14
-	lb bc, 2, 18
-	call TextBox
-	ld a, [wPartyCount]
-	and a
-	jr nz, .haspokemon
-	ld de, YouHaveNoPKMNString
-	jr .gotstring
-.haspokemon ; 504ae
-	ld a, [wPartyMenuActionText]
-	and $f ; drop high nibble
-	ld hl, PartyMenuStrings
-	ld e, a
-	ld d, $0
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-.gotstring ; 504be
-	ld a, [wOptions]
-	push af
-	set 4, a ; disable text delay
-	ld [wOptions], a
-	hlcoord 1, 16 ; Coord
-	call PlaceString
-	pop af
-	ld [wOptions], a
-	ret
-; 0x504d2
-
-PartyMenuStrings: ; 0x504d2
-	dw ChooseAMonString
-	dw UseOnWhichPKMNString
-	dw WhichPKMNString
-	dw TeachWhichPKMNString
-	dw MoveToWhereString
-	dw UseOnWhichPKMNString
-	dw ChooseAMonString ; Probably used to be ChooseAFemalePKMNString
-	dw ChooseAMonString ; Probably used to be ChooseAMalePKMNString
-	dw ToWhichPKMNString
-
-ChooseAMonString: ; 0x504e4
-	db "Choose a #MON.@"
-
-UseOnWhichPKMNString: ; 0x504f3
-	db "Use on which <PK><MN>?@"
-
-WhichPKMNString: ; 0x50504
-	db "Which <PK><MN>?@"
-
-TeachWhichPKMNString: ; 0x5050e
-	db "Teach which <PK><MN>?@"
-
-MoveToWhereString: ; 0x5051e
-	db "Move to where?@"
-
-ChooseAFemalePKMNString: ; 0x5052d
-; unused
-	db "Choose a ♀<PK><MN>.@"
-
-ChooseAMalePKMNString: ; 0x5053b
-; unused
-	db "Choose a ♂<PK><MN>.@"
-
-ToWhichPKMNString: ; 0x50549
-	db "To which <PK><MN>?@"
-
-YouHaveNoPKMNString: ; 0x50556
-	db "You have no <PK><MN>!@"
-
-PrintPartyMenuActionText: ; 50566
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMonNicknames
-	call GetNick
-	ld a, [wPartyMenuActionText]
-	and $f
-	ld hl, .MenuActionTexts
-	call .PrintText
-	ret
-; 5057b
-
-.MenuActionTexts: ; 5057b
-; entries correspond to PARTYMENUTEXT_* constants
-	dw .Text_CuredOfPoison
-	dw .Text_BurnWasHealed
-	dw .Text_Defrosted
-	dw .Text_WokeUp
-	dw .Text_RidOfParalysis
-	dw .Text_RecoveredSomeHP
-	dw .Text_HealthReturned
-	dw .Text_Revitalized
-	dw .Text_GrewToLevel
-	dw .Text_CameToItsSenses
-; 5058f
-
-.Text_RecoveredSomeHP: ; 0x5058f
-	; recovered @ HP!
-	text_jump UnknownText_0x1bc0a2
-	db "@"
-; 0x50594
-
-.Text_CuredOfPoison: ; 0x50594
-	; 's cured of poison.
-	text_jump UnknownText_0x1bc0bb
-	db "@"
-; 0x50599
-
-.Text_RidOfParalysis: ; 0x50599
-	; 's rid of paralysis.
-	text_jump UnknownText_0x1bc0d2
-	db "@"
-; 0x5059e
-
-.Text_BurnWasHealed: ; 0x5059e
-	; 's burn was healed.
-	text_jump UnknownText_0x1bc0ea
-	db "@"
-; 0x505a3
-
-.Text_Defrosted: ; 0x505a3
-	; was defrosted.
-	text_jump UnknownText_0x1bc101
-	db "@"
-; 0x505a8
-
-.Text_WokeUp: ; 0x505a8
-	; woke up.
-	text_jump UnknownText_0x1bc115
-	db "@"
-; 0x505ad
-
-.Text_HealthReturned: ; 0x505ad
-	; 's health returned.
-	text_jump UnknownText_0x1bc123
-	db "@"
-; 0x505b2
-
-.Text_Revitalized: ; 0x505b2
-	; is revitalized.
-	text_jump UnknownText_0x1bc13a
-	db "@"
-; 0x505b7
-
-.Text_GrewToLevel: ; 0x505b7
-	; grew to level @ !@ @
-	text_jump UnknownText_0x1bc14f
-	db "@"
-; 0x505bc
-
-.Text_CameToItsSenses: ; 0x505bc
-	; came to its senses.
-	text_jump UnknownText_0x1bc16e
-	db "@"
-; 0x505c1
-
-
-.PrintText: ; 505c1
-	ld e, a
-	ld d, 0
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [wOptions]
-	push af
-	set NO_TEXT_SCROLL, a
-	ld [wOptions], a
-	call PrintText
-	pop af
-	ld [wOptions], a
-	ret
-; 505da
--- a/engine/pic_animation.asm
+++ /dev/null
@@ -1,1141 +1,0 @@
-; Pic animation arrangement.
-
-Unused_AnimateMon_Slow_Normal: ; d0000
-	hlcoord 12, 0
-	ld a, [wBattleMode]
-	cp WILD_BATTLE
-	jr z, .wild
-	ld e, ANIM_MON_SLOW
-	ld d, $0
-	call AnimateFrontpic
-	ret
-
-.wild
-	ld e, ANIM_MON_NORMAL
-	ld d, $0
-	call AnimateFrontpic
-	ret
-; d001a
-
-AnimateMon_Menu: ; d001a
-	ld e, ANIM_MON_MENU
-	ld d, $0
-	call AnimateFrontpic
-	ret
-; d0022
-
-AnimateMon_Trade: ; d0022
-	ld e, ANIM_MON_TRADE
-	ld d, $0
-	call AnimateFrontpic
-	ret
-; d002a
-
-AnimateMon_Evolve: ; d002a
-	ld e, ANIM_MON_EVOLVE
-	ld d, $0
-	call AnimateFrontpic
-	ret
-; d0032
-
-AnimateMon_Hatch: ; d0032
-	ld e, ANIM_MON_HATCH
-	ld d, $0
-	call AnimateFrontpic
-	ret
-; d003a
-
-AnimateMon_Unused: ; d003a
-	ld e, ANIM_MON_UNUSED
-	ld d, $0
-	call AnimateFrontpic
-	ret
-; d0042
-
-pokeanim: MACRO
-	rept _NARG
-; Workaround for a bug where macro args can't come after the start of a symbol
-if !DEF(\1_POKEANIM)
-\1_POKEANIM EQUS "PokeAnim_\1_"
-endc
-	db (\1_POKEANIM - PokeAnim_SetupCommands) / 2
-	shift
-	endr
-	db (PokeAnim_Finish_ - PokeAnim_SetupCommands) / 2
-ENDM
-
-PokeAnims: ; d0042
-	dw .Slow
-	dw .Normal
-	dw .Menu
-	dw .Trade
-	dw .Evolve
-	dw .Hatch
-	dw .Unused ; same as .Menu
-	dw .Egg1
-	dw .Egg2
-
-.Slow:   pokeanim StereoCry, Setup2, Play
-.Normal: pokeanim StereoCry, Setup, Play
-.Menu:   pokeanim CryNoWait, Setup, Play, SetWait, Wait, Idle, Play
-.Trade:  pokeanim Idle, Play2, Idle, Play, SetWait, Wait, Cry, Setup, Play
-.Evolve: pokeanim Idle, Play, SetWait, Wait, CryNoWait, Setup, Play
-.Hatch:  pokeanim Idle, Play, CryNoWait, Setup, Play, SetWait, Wait, Idle, Play
-.Unused: pokeanim CryNoWait, Setup, Play, SetWait, Wait, Idle, Play
-.Egg1:   pokeanim Setup, Play
-.Egg2:   pokeanim Idle, Play
-
-
-AnimateFrontpic: ; d008e
-	call AnimateMon_CheckIfPokemon
-	ret c
-	call LoadMonAnimation
-.loop
-	call SetUpPokeAnim
-	push af
-	farcall HDMATransferTileMapToWRAMBank3
-	pop af
-	jr nc, .loop
-	ret
-; d00a3
-
-LoadMonAnimation: ; d00a3
-	push hl
-	ld c, e
-	ld b, 0
-	ld hl, PokeAnims
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld b, [hl]
-	ld c, a
-	pop hl
-	call PokeAnim_InitPicAttributes
-	ret
-; d00b4
-
-SetUpPokeAnim: ; d00b4
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wPokeAnimSceneIndex)
-	ld [rSVBK], a
-	ld a, [wPokeAnimSceneIndex]
-	ld c, a
-	ld b, 0
-	ld hl, wPokeAnimPointer
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	add hl, bc
-	ld a, [hl]
-	ld hl, PokeAnim_SetupCommands
-	rst JumpTable
-	ld a, [wPokeAnimSceneIndex]
-	ld c, a
-	pop af
-	ld [rSVBK], a
-	ld a, c
-	and $80
-	ret z
-	scf
-	ret
-; d00da
-
-PokeAnim_SetupCommands: ; d00da
-setup_command: MACRO
-\1_: dw \1
-ENDM
-	setup_command PokeAnim_Finish
-	setup_command PokeAnim_BasePic
-	setup_command PokeAnim_SetWait
-	setup_command PokeAnim_Wait
-	setup_command PokeAnim_Setup
-	setup_command PokeAnim_Setup2
-	setup_command PokeAnim_Idle
-	setup_command PokeAnim_Play
-	setup_command PokeAnim_Play2
-	setup_command PokeAnim_Cry
-	setup_command PokeAnim_CryNoWait
-	setup_command PokeAnim_StereoCry
-; d00f2
-
-PokeAnim_SetWait: ; d00f2
-	ld a, 18
-	ld [wPokeAnimWaitCounter], a
-	ld a, [wPokeAnimSceneIndex]
-	inc a
-	ld [wPokeAnimSceneIndex], a
-
-PokeAnim_Wait: ; d00fe
-	ld hl, wPokeAnimWaitCounter
-	dec [hl]
-	ret nz
-	ld a, [wPokeAnimSceneIndex]
-	inc a
-	ld [wPokeAnimSceneIndex], a
-	ret
-; d010b
-
-PokeAnim_Setup: ; d010b
-	ld c, FALSE
-	ld b, 0
-	call PokeAnim_InitAnim
-	call PokeAnim_SetVBank1
-	ld a, [wPokeAnimSceneIndex]
-	inc a
-	ld [wPokeAnimSceneIndex], a
-	ret
-; d011d
-
-PokeAnim_Setup2: ; d011d
-	ld c, FALSE
-	ld b, 4
-	call PokeAnim_InitAnim
-	call PokeAnim_SetVBank1
-	ld a, [wPokeAnimSceneIndex]
-	inc a
-	ld [wPokeAnimSceneIndex], a
-	ret
-; d012f
-
-PokeAnim_Idle: ; d012f
-	ld c, TRUE
-	ld b, 0
-	call PokeAnim_InitAnim
-	call PokeAnim_SetVBank1
-	ld a, [wPokeAnimSceneIndex]
-	inc a
-	ld [wPokeAnimSceneIndex], a
-	ret
-; d0141
-
-PokeAnim_Play: ; d0141
-	call PokeAnim_DoAnimScript
-	ld a, [wPokeAnimJumptableIndex]
-	bit 7, a
-	ret z
-	call PokeAnim_PlaceGraphic
-	ld a, [wPokeAnimSceneIndex]
-	inc a
-	ld [wPokeAnimSceneIndex], a
-	ret
-; d0155
-
-PokeAnim_Play2: ; d0155
-	call PokeAnim_DoAnimScript
-	ld a, [wPokeAnimJumptableIndex]
-	bit 7, a
-	ret z
-	ld a, [wPokeAnimSceneIndex]
-	inc a
-	ld [wPokeAnimSceneIndex], a
-	ret
-; d0166
-
-PokeAnim_BasePic: ; d0166
-	call PokeAnim_DeinitFrames
-	ld a, [wPokeAnimSceneIndex]
-	inc a
-	ld [wPokeAnimSceneIndex], a
-	ret
-; d0171
-
-PokeAnim_Finish: ; d0171
-	call PokeAnim_DeinitFrames
-	ld hl, wPokeAnimSceneIndex
-	set 7, [hl]
-	ret
-; d017a
-
-PokeAnim_Cry: ; d017a
-	ld a, [wPokeAnimSpecies]
-	call _PlayMonCry
-	ld a, [wPokeAnimSceneIndex]
-	inc a
-	ld [wPokeAnimSceneIndex], a
-	ret
-; d0188
-
-PokeAnim_CryNoWait: ; d0188
-	ld a, [wPokeAnimSpecies]
-	call PlayMonCry2
-	ld a, [wPokeAnimSceneIndex]
-	inc a
-	ld [wPokeAnimSceneIndex], a
-	ret
-; d0196
-
-PokeAnim_StereoCry: ; d0196
-	ld a, $f
-	ld [wCryTracks], a
-	ld a, [wPokeAnimSpecies]
-	call PlayStereoCry2
-	ld a, [wPokeAnimSceneIndex]
-	inc a
-	ld [wPokeAnimSceneIndex], a
-	ret
-; d01a9
-
-PokeAnim_DeinitFrames: ; d01a9
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wPokeAnimCoord)
-	ld [rSVBK], a
-	call PokeAnim_PlaceGraphic
-	farcall HDMATransferTileMapToWRAMBank3
-	call PokeAnim_SetVBank0
-	farcall HDMATransferAttrMapToWRAMBank3
-	pop af
-	ld [rSVBK], a
-	ret
-; d01c6
-
-AnimateMon_CheckIfPokemon: ; d01c6
-	ld a, [wCurPartySpecies]
-	cp EGG
-	jr z, .fail
-	call IsAPokemon
-	jr c, .fail
-	and a
-	ret
-
-.fail
-	scf
-	ret
-; d01d6
-
-PokeAnim_InitPicAttributes: ; d01d6
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wPokeAnimSceneIndex)
-	ld [rSVBK], a
-
-	push bc
-	push de
-	push hl
-	ld hl, wPokeAnimSceneIndex
-	ld bc, wPokeAnimStructEnd - wPokeAnimSceneIndex
-	xor a
-	call ByteFill
-	pop hl
-	pop de
-	pop bc
-
-; bc contains anim pointer
-	ld a, c
-	ld [wPokeAnimPointer], a
-	ld a, b
-	ld [wPokeAnimPointer + 1], a
-; hl contains tilemap coords
-	ld a, l
-	ld [wPokeAnimCoord], a
-	ld a, h
-	ld [wPokeAnimCoord + 1], a
-; d = start tile
-	ld a, d
-	ld [wPokeAnimGraphicStartTile], a
-
-	ld a, BANK(wCurPartySpecies)
-	ld hl, wCurPartySpecies
-	call GetFarWRAMByte
-	ld [wPokeAnimSpecies], a
-
-	ld a, BANK(wUnownLetter)
-	ld hl, wUnownLetter
-	call GetFarWRAMByte
-	ld [wPokeAnimUnownLetter], a
-
-	call PokeAnim_GetSpeciesOrUnown
-	ld [wPokeAnimSpeciesOrUnown], a
-
-	call PokeAnim_GetFrontpicDims
-	ld a, c
-	ld [wPokeAnimFrontpicHeight], a
-
-	pop af
-	ld [rSVBK], a
-	ret
-; d0228
-
-PokeAnim_InitAnim: ; d0228
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wPokeAnimIdleFlag)
-	ld [rSVBK], a
-	push bc
-	ld hl, wPokeAnimIdleFlag
-	ld bc, wPokeAnimStructEnd - wPokeAnimIdleFlag
-	xor a
-	call ByteFill
-	pop bc
-	ld a, b
-	ld [wPokeAnimSpeed], a
-	ld a, c
-	ld [wPokeAnimIdleFlag], a
-	call GetMonAnimPointer
-	call GetMonFramesPointer
-	call GetMonBitmaskPointer
-	pop af
-	ld [rSVBK], a
-	ret
-; d0250
-
-PokeAnim_DoAnimScript: ; d0250
-	xor a
-	ld [hBGMapMode], a
-.loop
-	ld a, [wPokeAnimJumptableIndex]
-	and $7f
-	ld hl, .Jumptable
-	rst JumpTable
-	ret
-; d025d
-
-.Jumptable: ; d025d
-	dw .RunAnim
-	dw .WaitAnim
-; d0261
-
-.RunAnim: ; d0261
-	call PokeAnim_GetPointer
-	ld a, [wPokeAnimCommand]
-	cp -1
-	jr z, PokeAnim_End
-	cp -2
-	jr z, .SetRepeat
-	cp -3
-	jr z, .DoRepeat
-	call PokeAnim_GetFrame
-	ld a, [wPokeAnimParameter]
-	call PokeAnim_GetDuration
-	ld [wPokeAnimWaitCounter], a
-	call PokeAnim_StartWaitAnim
-.WaitAnim: ; d0282
-	ld a, [wPokeAnimWaitCounter]
-	dec a
-	ld [wPokeAnimWaitCounter], a
-	ret nz
-	call PokeAnim_StopWaitAnim
-	ret
-; d028e
-
-.SetRepeat: ; d028e
-	ld a, [wPokeAnimParameter]
-	ld [wPokeAnimRepeatTimer], a
-	jr .loop
-; d0296
-
-.DoRepeat: ; d0296
-	ld a, [wPokeAnimRepeatTimer]
-	and a
-	ret z
-	dec a
-	ld [wPokeAnimRepeatTimer], a
-	ret z
-	ld a, [wPokeAnimParameter]
-	ld [wPokeAnimFrame], a
-	jr .loop
-; d02a8
-
-PokeAnim_End: ; d02a8
-	ld hl, wPokeAnimJumptableIndex
-	set 7, [hl]
-	ret
-; d02ae
-
-PokeAnim_GetDuration: ; d02ae
-; a * (1 + [wPokeAnimSpeed] / 16)
-	ld c, a
-	ld b, $0
-	ld hl, 0
-	ld a, [wPokeAnimSpeed]
-	call AddNTimes
-	ld a, h
-	swap a
-	and $f0
-	ld h, a
-	ld a, l
-	swap a
-	and $f
-	or h
-	add c
-	ret
-; d02c8
-
-PokeAnim_GetFrame: ; d02c8
-	call PokeAnim_PlaceGraphic
-	ld a, [wPokeAnimCommand]
-	and a
-	ret z
-	call PokeAnim_GetBitmaskIndex
-	push hl
-	call PokeAnim_CopyBitmaskToBuffer
-	pop hl
-	call PokeAnim_ConvertAndApplyBitmask
-	ret
-; d02dc
-
-PokeAnim_StartWaitAnim: ; d02dc
-	ld a, [wPokeAnimJumptableIndex]
-	inc a
-	ld [wPokeAnimJumptableIndex], a
-	ret
-; d02e4
-
-PokeAnim_StopWaitAnim: ; d02e4
-	ld a, [wPokeAnimJumptableIndex]
-	dec a
-	ld [wPokeAnimJumptableIndex], a
-	ret
-; d02ec
-
-PokeAnim_IsUnown: ; d02ec
-	ld a, [wPokeAnimSpecies]
-	cp UNOWN
-	ret
-; d02f2
-
-PokeAnim_IsEgg: ; d02f2
-	ld a, [wPokeAnimSpecies]
-	cp EGG
-	ret
-; d02f8
-
-PokeAnim_GetPointer: ; d02f8
-	push hl
-	ld a, [wPokeAnimFrame]
-	ld e, a
-	ld d, $0
-	ld hl, wPokeAnimPointerAddr
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	add hl, de
-	add hl, de
-	ld a, [wPokeAnimPointerBank]
-	call GetFarHalfword
-	ld a, l
-	ld [wPokeAnimCommand], a
-	ld a, h
-	ld [wPokeAnimParameter], a
-	ld hl, wPokeAnimFrame
-	inc [hl]
-	pop hl
-	ret
-; d031b
-
-PokeAnim_GetBitmaskIndex: ; d031b
-	ld a, [wPokeAnimCommand]
-	dec a
-	ld c, a
-	ld b, $0
-	ld hl, wPokeAnimFramesAddr
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	add hl, bc
-	add hl, bc
-	ld a, [wPokeAnimFramesBank]
-	call GetFarHalfword
-	ld a, [wPokeAnimFramesBank]
-	call GetFarByte
-	ld [wPokeAnimCurBitmask], a
-	inc hl
-	ret
-; d033b
-
-PokeAnim_CopyBitmaskToBuffer: ; d033b
-	call .GetSize
-	push bc
-	ld hl, wPokeAnimBitmaskAddr
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [wPokeAnimCurBitmask]
-	call AddNTimes
-	pop bc
-	ld de, wPokeAnimBitmaskBuffer
-	ld a, [wPokeAnimBitmaskBank]
-	call FarCopyBytes
-	ret
-; d0356
-
-.GetSize: ; d0356
-	push hl
-	ld a, [wPokeAnimFrontpicHeight]
-	sub 5 ; to get a number 0, 1, or 2
-	ld c, a
-	ld b, 0
-	ld hl, .Sizes
-	add hl, bc
-	ld c, [hl]
-	ld b, 0
-	pop hl
-	ret
-; d0368
-
-.Sizes: db 4, 5, 7
-
-poke_anim_box: MACRO
-y = 7
-rept \1
-x = 7 + -\1
-rept \1
-	db x + y
-x = x + 1
-endr
-y = y + 7
-endr
-ENDM
-
-PokeAnim_ConvertAndApplyBitmask: ; d036b
-	xor a
-	ld [wPokeAnimBitmaskCurBit], a
-	ld [wPokeAnimBitmaskCurRow], a
-	ld [wPokeAnimBitmaskCurCol], a
-.loop
-	push hl
-	call .IsCurBitSet
-	pop hl
-	ld a, b
-	and a
-	jr z, .next
-
-	ld a, [wPokeAnimFramesBank]
-	call GetFarByte
-	inc hl
-	push hl
-	call .ApplyFrame
-	pop hl
-
-.next
-	push hl
-	call .NextBit
-	pop hl
-	jr nc, .loop
-	ret
-; d0392
-
-.IsCurBitSet: ; d0392
-; which byte
-	ld a, [wPokeAnimBitmaskCurBit]
-	and $f8
-	rrca
-	rrca
-	rrca
-	ld e, a
-	ld d, 0
-	ld hl, wPokeAnimBitmaskBuffer
-	add hl, de
-	ld b, [hl]
-; which bit
-	ld a, [wPokeAnimBitmaskCurBit]
-	and $7
-	jr z, .skip
-
-	ld c, a
-	ld a, b
-.loop2
-	rrca
-	dec c
-	jr nz, .loop2
-	ld b, a
-
-.skip
-	xor a
-	bit 0, b
-	jr z, .finish
-	ld a, 1
-
-.finish
-	ld b, a
-	ld hl, wPokeAnimBitmaskCurBit
-	inc [hl]
-	ret
-; d03bd
-
-.ApplyFrame: ; d03bd
-	push af
-	call .GetCoord
-	pop af
-	push hl
-	call .GetTilemap
-	ld hl, wPokeAnimGraphicStartTile
-	add [hl]
-	pop hl
-	ld [hl], a
-	ret
-; d03cd
-
-.GetCoord: ; d03cd
-	call .GetStartCoord
-	ld a, [wPokeAnimBitmaskCurRow]
-	ld bc, SCREEN_WIDTH
-	call AddNTimes
-	ld a, [wBoxAlignment]
-	and a
-	jr nz, .go
-	ld a, [wPokeAnimBitmaskCurCol]
-	ld e, a
-	ld d, 0
-	add hl, de
-	jr .skip2
-
-.go
-	ld a, [wPokeAnimBitmaskCurCol]
-	ld e, a
-	ld a, l
-	sub e
-	ld l, a
-	ld a, h
-	sbc 0
-	ld h, a
-
-.skip2
-	ret
-; d03f4
-
-; unused
-	db 6, 5, 4
-
-.GetTilemap: ; d03f7
-	push af
-	ld a, [wPokeAnimFrontpicHeight]
-	cp 5
-	jr z, .check_add_24
-	cp 6
-	jr z, .check_add_13
-	pop af
-	ret
-
-.check_add_24
-	pop af
-	cp 5 * 5
-	jr nc, .add_24
-	push hl
-	push de
-	ld hl, ._5by5
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld a, [hl]
-	pop de
-	pop hl
-	ret
-
-.add_24
-	add 24
-	ret
-
-.check_add_13
-	pop af
-	cp 6 * 6
-	jr nc, .add_13
-	push hl
-	push de
-	ld hl, ._6by6
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld a, [hl]
-	pop de
-	pop hl
-	ret
-
-.add_13
-	add 13
-	ret
-; d042f
-
-._5by5:
-	poke_anim_box 5
-	; db  9, 10, 11, 12, 13
-	; db 16, 17, 18, 19, 20
-	; db 23, 24, 25, 26, 27
-	; db 30, 31, 32, 33, 34
-	; db 37, 38, 39, 40, 41
-
-._6by6:
-	poke_anim_box 6
-	; db  8,  9, 10, 11, 12, 13
-	; db 15, 16, 17, 18, 19, 20
-	; db 22, 23, 24, 25, 26, 27
-	; db 29, 30, 31, 32, 33, 34
-	; db 36, 37, 38, 39, 40, 41
-	; db 43, 44, 45, 46, 47, 48
-
-
-.GetStartCoord: ; d046c
-	ld hl, wPokeAnimCoord
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-
-	ld a, [wPokeAnimFrontpicHeight]
-	ld de, 0
-	ld bc, 6
-	cp 7
-	jr z, .okay
-	ld de, SCREEN_WIDTH + 1
-	ld bc, SCREEN_WIDTH + 5
-	cp 6
-	jr z, .okay
-	ld de, 2 * SCREEN_WIDTH + 1
-	ld bc, 2 * SCREEN_WIDTH + 5
-.okay
-
-	ld a, [wBoxAlignment]
-	and a
-	jr nz, .add_bc
-	add hl, de
-	ret
-
-.add_bc
-	add hl, bc
-	ret
-; d0499
-
-.NextBit: ; d0499
-	ld a, [wPokeAnimBitmaskCurRow]
-	inc a
-	ld [wPokeAnimBitmaskCurRow], a
-	ld c, a
-	ld a, [wPokeAnimFrontpicHeight]
-	cp c
-	jr nz, .no_carry
-	xor a
-	ld [wPokeAnimBitmaskCurRow], a
-	ld a, [wPokeAnimBitmaskCurCol]
-	inc a
-	ld [wPokeAnimBitmaskCurCol], a
-	ld c, a
-	ld a, [wPokeAnimFrontpicHeight]
-	cp c
-	jr nz, .no_carry
-	scf
-	ret
-
-.no_carry
-	xor a
-	ret
-; d04bd
-
-PokeAnim_PlaceGraphic: ; d04bd
-	call .ClearBox
-	ld a, [wBoxAlignment]
-	and a
-	jr nz, .flipped
-	ld de, 1
-	ld bc, 0
-	jr .okay
-
-.flipped
-	ld de, -1
-	ld bc, 6
-
-.okay
-	ld hl, wPokeAnimCoord
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	add hl, bc
-	ld c, 7
-	ld b, 7
-	ld a, [wPokeAnimGraphicStartTile]
-.loop
-	push bc
-	push hl
-	push de
-	ld de, SCREEN_WIDTH
-.loop2
-	ld [hl], a
-	inc a
-	add hl, de
-	dec b
-	jr nz, .loop2
-	pop de
-	pop hl
-	add hl, de
-	pop bc
-	dec c
-	jr nz, .loop
-	ret
-; d04f6
-
-.ClearBox: ; d04f6
-	ld hl, wPokeAnimCoord
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld b, 7
-	ld c, 7
-	call ClearBox
-	ret
-; d0504
-
-PokeAnim_SetVBank1: ; d0504
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wPokeAnimCoord)
-	ld [rSVBK], a
-	xor a
-	ld [hBGMapMode], a
-	call .SetFlag
-	farcall HDMATransferAttrMapToWRAMBank3
-	pop af
-	ld [rSVBK], a
-	ret
-; d051b
-
-.SetFlag: ; d051b
-	call PokeAnim_GetAttrMapCoord
-	ld b, 7
-	ld c, 7
-	ld de, SCREEN_WIDTH
-.row
-	push bc
-	push hl
-.col
-	ld a, [hl]
-	or 8
-	ld [hl], a
-	add hl, de
-	dec c
-	jr nz, .col
-	pop hl
-	inc hl
-	pop bc
-	dec b
-	jr nz, .row
-	ret
-; d0536
-
-PokeAnim_SetVBank0: ; d0536
-	call PokeAnim_GetAttrMapCoord
-	ld b, 7
-	ld c, 7
-	ld de, SCREEN_WIDTH
-.row
-	push bc
-	push hl
-.col
-	ld a, [hl]
-	and $f7
-	ld [hl], a
-	add hl, de
-	dec c
-	jr nz, .col
-	pop hl
-	inc hl
-	pop bc
-	dec b
-	jr nz, .row
-	ret
-; d0551
-
-PokeAnim_GetAttrMapCoord: ; d0551
-	ld hl, wPokeAnimCoord
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, wAttrMap - wTileMap
-	add hl, de
-	ret
-; d055c
-
-GetMonAnimPointer: ; d055c
-	call PokeAnim_IsEgg
-	jr z, .egg
-
-	ld c, BANK(UnownAnimations)
-	ld hl, UnownAnimationPointers
-	ld de, UnownAnimationIdlePointers
-	call PokeAnim_IsUnown
-	jr z, .unown
-	ld c, BANK(PicAnimations)
-	ld hl, AnimationPointers
-	ld de, AnimationIdlePointers
-.unown
-
-	ld a, [wPokeAnimIdleFlag]
-	and a
-	jr z, .idles
-	ld h, d
-	ld l, e
-.idles
-
-	ld a, [wPokeAnimSpeciesOrUnown]
-	dec a
-	ld e, a
-	ld d, 0
-	add hl, de
-	add hl, de
-	ld a, c
-	ld [wPokeAnimPointerBank], a
-	call GetFarHalfword
-	ld a, l
-	ld [wPokeAnimPointerAddr], a
-	ld a, h
-	ld [wPokeAnimPointerAddr + 1], a
-	ret
-
-.egg
-	ld hl, EggAnimation
-	ld c, BANK(EggAnimation)
-	ld a, [wPokeAnimIdleFlag]
-	and a
-	jr z, .idles_egg
-	ld hl, EggAnimationIdle
-	ld c, BANK(EggAnimationIdle)
-.idles_egg
-
-	ld a, c
-	ld [wPokeAnimPointerBank], a
-	ld a, l
-	ld [wPokeAnimPointerAddr], a
-	ld a, h
-	ld [wPokeAnimPointerAddr + 1], a
-	ret
-; d05b4
-
-PokeAnim_GetFrontpicDims: ; d05b4
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wCurPartySpecies)
-	ld [rSVBK], a
-	ld a, [wCurPartySpecies]
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld a, [wBasePicSize]
-	and $f
-	ld c, a
-	pop af
-	ld [rSVBK], a
-	ret
-; d05ce
-
-GetMonFramesPointer: ; d05ce
-	call PokeAnim_IsEgg
-	jr z, .egg
-
-	call PokeAnim_IsUnown
-	ld b, BANK(UnownFramesPointers)
-	ld c, BANK(UnownsFrames)
-	ld hl, UnownFramesPointers
-	jr z, .got_frames
-	ld a, [wPokeAnimSpecies]
-	cp JOHTO_POKEMON
-	ld b, BANK(FramesPointers)
-	ld c, BANK(KantoFrames)
-	ld hl, FramesPointers
-	jr c, .got_frames
-	ld c, BANK(JohtoFrames)
-.got_frames
-	ld a, c
-	ld [wPokeAnimFramesBank], a
-
-	ld a, [wPokeAnimSpeciesOrUnown]
-	dec a
-	ld e, a
-	ld d, 0
-	add hl, de
-	add hl, de
-	ld a, b
-	call GetFarHalfword
-	ld a, l
-	ld [wPokeAnimFramesAddr], a
-	ld a, h
-	ld [wPokeAnimFramesAddr + 1], a
-	ret
-
-.egg
-	ld hl, EggFrames
-	ld c, BANK(EggFrames)
-	ld a, c
-	ld [wPokeAnimFramesBank], a
-	ld a, l
-	ld [wPokeAnimFramesAddr], a
-	ld a, h
-	ld [wPokeAnimFramesAddr + 1], a
-	ret
-; d061b
-
-GetMonBitmaskPointer: ; d061b
-	call PokeAnim_IsEgg
-	jr z, .egg
-
-	call PokeAnim_IsUnown
-	ld a, BANK(UnownBitmasksPointers)
-	ld hl, UnownBitmasksPointers
-	jr z, .unown
-	ld a, BANK(BitmasksPointers)
-	ld hl, BitmasksPointers
-.unown
-	ld [wPokeAnimBitmaskBank], a
-
-	ld a, [wPokeAnimSpeciesOrUnown]
-	dec a
-	ld e, a
-	ld d, 0
-	add hl, de
-	add hl, de
-	ld a, [wPokeAnimBitmaskBank]
-	call GetFarHalfword
-	ld a, l
-	ld [wPokeAnimBitmaskAddr], a
-	ld a, h
-	ld [wPokeAnimBitmaskAddr + 1], a
-	ret
-
-.egg
-	ld c, BANK(EggBitmasks)
-	ld hl, EggBitmasks
-	ld a, c
-	ld [wPokeAnimBitmaskBank], a
-	ld a, l
-	ld [wPokeAnimBitmaskAddr], a
-	ld a, h
-	ld [wPokeAnimBitmaskAddr + 1], a
-	ret
-; d065c
-
-PokeAnim_GetSpeciesOrUnown: ; d065c
-	call PokeAnim_IsUnown
-	jr z, .unown
-	ld a, [wPokeAnimSpecies]
-	ret
-
-.unown
-	ld a, [wPokeAnimUnownLetter]
-	ret
-; d0669
-
-Unused_HOF_AnimateAlignedFrontpic: ; d0669
-	ld a, $1
-	ld [wBoxAlignment], a
-
-HOF_AnimateFrontpic: ; d066e
-	call AnimateMon_CheckIfPokemon
-	jr c, .fail
-	ld h, d
-	ld l, e
-	push bc
-	push hl
-	ld de, vTiles2
-	predef GetAnimatedFrontpic
-	pop hl
-	pop bc
-	ld d, 0
-	ld e, c
-	call AnimateFrontpic
-	xor a
-	ld [wBoxAlignment], a
-	ret
-
-.fail
-	xor a
-	ld [wBoxAlignment], a
-	inc a
-	ld [wCurPartySpecies], a
-	ret
-; d0695
--- a/engine/player_gfx.asm
+++ /dev/null
@@ -1,224 +1,0 @@
-Unreferenced_Function88248: ; 88248
-	ld c, CAL
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .okay
-	ld c, KAREN
-
-.okay
-	ld a, c
-	ld [wTrainerClass], a
-	ret
-
-MovePlayerPicRight: ; 88258
-	hlcoord 6, 4
-	ld de, 1
-	jr MovePlayerPic
-
-MovePlayerPicLeft: ; 88260
-	hlcoord 13, 4
-	ld de, -1
-	; fallthrough
-
-MovePlayerPic: ; 88266
-; Move player pic at hl by de * 7 tiles.
-	ld c, $8
-.loop
-	push bc
-	push hl
-	push de
-	xor a
-	ld [hBGMapMode], a
-	lb bc, 7, 7
-	predef PlaceGraphic
-	xor a
-	ld [hBGMapThird], a
-	call WaitBGMap
-	call DelayFrame
-	pop de
-	pop hl
-	add hl, de
-	pop bc
-	dec c
-	ret z
-	push hl
-	push bc
-	ld a, l
-	sub e
-	ld l, a
-	ld a, h
-	sbc d
-	ld h, a
-	lb bc, 7, 7
-	call ClearBox
-	pop bc
-	pop hl
-	jr .loop
-
-ShowPlayerNamingChoices: ; 88297
-	ld hl, ChrisNameMenuHeader
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .GotGender
-	ld hl, KrisNameMenuHeader
-.GotGender:
-	call LoadMenuHeader
-	call VerticalMenu
-	ld a, [wMenuCursorY]
-	dec a
-	call CopyNameFromMenu
-	call CloseWindow
-	ret
-
-INCLUDE "data/player_names.asm"
-
-GetPlayerNameArray: ; 88318 This Function is never called
-	ld hl, wPlayerName
-	ld de, MalePlayerNameArray
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .done
-	ld de, FemalePlayerNameArray
-
-.done
-	call InitName
-	ret
-
-GetPlayerIcon: ; 8832c
-; Get the player icon corresponding to gender
-
-; Male
-	ld de, ChrisSpriteGFX
-	ld b, BANK(ChrisSpriteGFX)
-
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .done
-
-; Female
-	ld de, KrisSpriteGFX
-	ld b, BANK(KrisSpriteGFX)
-
-.done
-	ret
-
-GetCardPic: ; 8833e
-	ld hl, ChrisCardPic
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .GotClass
-	ld hl, KrisCardPic
-.GotClass:
-	ld de, vTiles2 tile $00
-	ld bc, $23 tiles
-	ld a, BANK(ChrisCardPic) ; BANK(KrisCardPic)
-	call FarCopyBytes
-	ld hl, CardGFX
-	ld de, vTiles2 tile $23
-	ld bc, 6 tiles
-	ld a, BANK(CardGFX)
-	call FarCopyBytes
-	ret
-
-ChrisCardPic: ; 88365
-INCBIN "gfx/trainer_card/chris_card.2bpp"
-
-KrisCardPic: ; 88595
-INCBIN "gfx/trainer_card/kris_card.2bpp"
-
-CardGFX: ; 887c5
-INCBIN "gfx/trainer_card/trainer_card.2bpp"
-
-GetPlayerBackpic: ; 88825
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, GetChrisBackpic
-	call GetKrisBackpic
-	ret
-
-GetChrisBackpic: ; 88830
-	ld hl, ChrisBackpic
-	ld b, BANK(ChrisBackpic)
-	ld de, vTiles2 tile $31
-	ld c, 7 * 7
-	predef DecompressGet2bpp
-	ret
-
-HOF_LoadTrainerFrontpic: ; 88840
-	call WaitBGMap
-	xor a
-	ld [hBGMapMode], a
-	ld e, 0
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .GotClass
-	ld e, 1
-
-.GotClass:
-	ld a, e
-	ld [wTrainerClass], a
-	ld de, ChrisPic
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .GotPic
-	ld de, KrisPic
-
-.GotPic:
-	ld hl, vTiles2
-	ld b, BANK(ChrisPic) ; BANK(KrisPic)
-	ld c, 7 * 7
-	call Get2bpp
-	call WaitBGMap
-	ld a, $1
-	ld [hBGMapMode], a
-	ret
-
-DrawIntroPlayerPic: ; 88874
-; Draw the player pic at (6,4).
-
-; Get class
-	ld e, CHRIS
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .GotClass
-	ld e, KRIS
-.GotClass:
-	ld a, e
-	ld [wTrainerClass], a
-
-; Load pic
-	ld de, ChrisPic
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .GotPic
-	ld de, KrisPic
-.GotPic:
-	ld hl, vTiles2
-	ld b, BANK(ChrisPic) ; BANK(KrisPic)
-	ld c, 7 * 7 ; dimensions
-	call Get2bpp
-
-; Draw
-	xor a
-	ld [hGraphicStartTile], a
-	hlcoord 6, 4
-	lb bc, 7, 7
-	predef PlaceGraphic
-	ret
-
-ChrisPic: ; 888a9
-INCBIN "gfx/player/chris.2bpp"
-
-KrisPic: ; 88bb9
-INCBIN "gfx/player/kris.2bpp"
-
-GetKrisBackpic: ; 88ec9
-; Kris's backpic is uncompressed.
-	ld de, KrisBackpic
-	ld hl, vTiles2 tile $31
-	lb bc, BANK(KrisBackpic), 7 * 7 ; dimensions
-	call Get2bpp
-	ret
-
-KrisBackpic: ; 88ed6
-INCBIN "gfx/player/kris_back.2bpp"
--- a/engine/player_movement.asm
+++ /dev/null
@@ -1,851 +1,0 @@
-DoPlayerMovement:: ; 80000
-
-	call .GetDPad
-	ld a, movement_step_sleep
-	ld [wMovementAnimation], a
-	xor a
-	ld [wd041], a
-	call .TranslateIntoMovement
-	ld c, a
-	ld a, [wMovementAnimation]
-	ld [wPlayerNextMovement], a
-	ret
-
-.GetDPad:
-
-	ld a, [hJoyDown]
-	ld [wCurInput], a
-
-; Standing downhill instead moves down.
-
-	ld hl, wBikeFlags
-	bit BIKEFLAGS_DOWNHILL_F, [hl]
-	ret z
-
-	ld c, a
-	and D_PAD
-	ret nz
-
-	ld a, c
-	or D_DOWN
-	ld [wCurInput], a
-	ret
-; 8002d
-
-.TranslateIntoMovement:
-	ld a, [wPlayerState]
-	cp PLAYER_NORMAL
-	jr z, .Normal
-	cp PLAYER_SURF
-	jr z, .Surf
-	cp PLAYER_SURF_PIKA
-	jr z, .Surf
-	cp PLAYER_BIKE
-	jr z, .Normal
-	cp PLAYER_SKATE
-	jr z, .Ice
-
-.Normal:
-	call .CheckForced
-	call .GetAction
-	call .CheckTile
-	ret c
-	call .CheckTurning
-	ret c
-	call .TryStep
-	ret c
-	call .TryJump
-	ret c
-	call .CheckWarp
-	ret c
-	jr .NotMoving
-
-.Surf:
-	call .CheckForced
-	call .GetAction
-	call .CheckTile
-	ret c
-	call .CheckTurning
-	ret c
-	call .TrySurf
-	ret c
-	jr .NotMoving
-
-.Ice:
-	call .CheckForced
-	call .GetAction
-	call .CheckTile
-	ret c
-	call .CheckTurning
-	ret c
-	call .TryStep
-	ret c
-	call .TryJump
-	ret c
-	call .CheckWarp
-	ret c
-	ld a, [wWalkingDirection]
-	cp STANDING
-	jr z, .HitWall
-	call .BumpSound
-.HitWall:
-	call .StandInPlace
-	xor a
-	ret
-
-.NotMoving:
-	ld a, [wWalkingDirection]
-	cp STANDING
-	jr z, .Standing
-
-; Walking into an edge warp won't bump.
-	ld a, [wEngineBuffer4]
-	and a
-	jr nz, .CantMove
-	call .BumpSound
-.CantMove:
-	call ._WalkInPlace
-	xor a
-	ret
-
-.Standing:
-	call .StandInPlace
-	xor a
-	ret
-; 800b7
-
-.CheckTile: ; 800b7
-; Tiles such as waterfalls and warps move the player
-; in a given direction, overriding input.
-
-	ld a, [wPlayerStandingTile]
-	ld c, a
-	call CheckWhirlpoolTile
-	jr c, .not_whirlpool
-	ld a, 3
-	scf
-	ret
-
-.not_whirlpool
-	and $f0
-	cp HI_NYBBLE_CURRENT
-	jr z, .water
-	cp HI_NYBBLE_WALK
-	jr z, .land1
-	cp HI_NYBBLE_WALK_ALT
-	jr z, .land2
-	cp HI_NYBBLE_WARPS
-	jr z, .warps
-	jr .no_walk
-
-.water
-	ld a, c
-	maskbits NUM_DIRECTIONS
-	ld c, a
-	ld b, 0
-	ld hl, .water_table
-	add hl, bc
-	ld a, [hl]
-	ld [wWalkingDirection], a
-	jr .continue_walk
-
-.water_table
-	db RIGHT ; COLL_WATERFALL_RIGHT
-	db LEFT  ; COLL_WATERFALL_LEFT
-	db UP    ; COLL_WATERFALL_UP
-	db DOWN  ; COLL_WATERFALL
-
-.land1
-	ld a, c
-	and 7
-	ld c, a
-	ld b, 0
-	ld hl, .land1_table
-	add hl, bc
-	ld a, [hl]
-	cp STANDING
-	jr z, .no_walk
-	ld [wWalkingDirection], a
-	jr .continue_walk
-
-.land1_table
-	db STANDING ; COLL_BRAKE
-	db RIGHT    ; COLL_WALK_RIGHT
-	db LEFT     ; COLL_WALK_LEFT
-	db UP       ; COLL_WALK_UP
-	db DOWN     ; COLL_WALK_DOWN
-	db STANDING ; COLL_BRAKE_45
-	db STANDING ; COLL_BRAKE_46
-	db STANDING ; COLL_BRAKE_47
-
-.land2
-	ld a, c
-	and 7
-	ld c, a
-	ld b, 0
-	ld hl, .land2_table
-	add hl, bc
-	ld a, [hl]
-	cp STANDING
-	jr z, .no_walk
-	ld [wWalkingDirection], a
-	jr .continue_walk
-
-.land2_table
-	db RIGHT    ; COLL_WALK_RIGHT_ALT
-	db LEFT     ; COLL_WALK_LEFT_ALT
-	db UP       ; COLL_WALK_UP_ALT
-	db DOWN     ; COLL_WALK_DOWN_ALT
-	db STANDING ; COLL_BRAKE_ALT
-	db STANDING ; COLL_BRAKE_55
-	db STANDING ; COLL_BRAKE_56
-	db STANDING ; COLL_BRAKE_57
-
-.warps
-	ld a, c
-	cp COLL_DOOR
-	jr z, .down
-	cp COLL_DOOR_79
-	jr z, .down
-	cp COLL_STAIRCASE
-	jr z, .down
-	cp COLL_CAVE
-	jr nz, .no_walk
-
-.down
-	ld a, DOWN
-	ld [wWalkingDirection], a
-	jr .continue_walk
-
-.no_walk
-	xor a
-	ret
-
-.continue_walk
-	ld a, STEP_WALK
-	call .DoStep
-	ld a, 5
-	scf
-	ret
-; 80147
-
-.CheckTurning: ; 80147
-; If the player is turning, change direction first. This also lets
-; the player change facing without moving by tapping a direction.
-
-	ld a, [wPlayerTurningDirection]
-	cp 0
-	jr nz, .not_turning
-	ld a, [wWalkingDirection]
-	cp STANDING
-	jr z, .not_turning
-
-	ld e, a
-	ld a, [wPlayerDirection]
-	rrca
-	rrca
-	maskbits NUM_DIRECTIONS
-	cp e
-	jr z, .not_turning
-
-	ld a, STEP_TURN
-	call .DoStep
-	ld a, 2
-	scf
-	ret
-
-.not_turning
-	xor a
-	ret
-; 8016b
-
-.TryStep: ; 8016b
-
-; Surfing actually calls .TrySurf directly instead of passing through here.
-	ld a, [wPlayerState]
-	cp PLAYER_SURF
-	jr z, .TrySurf
-	cp PLAYER_SURF_PIKA
-	jr z, .TrySurf
-
-	call .CheckLandPerms
-	jr c, .bump
-
-	call .CheckNPC
-	and a
-	jr z, .bump
-	cp 2
-	jr z, .bump
-
-	ld a, [wPlayerStandingTile]
-	call CheckIceTile
-	jr nc, .ice
-
-; Downhill riding is slower when not moving down.
-	call .BikeCheck
-	jr nz, .walk
-
-	ld hl, wBikeFlags
-	bit BIKEFLAGS_DOWNHILL_F, [hl]
-	jr z, .fast
-
-	ld a, [wWalkingDirection]
-	cp DOWN
-	jr z, .fast
-
-	ld a, STEP_WALK
-	call .DoStep
-	scf
-	ret
-
-.fast
-	ld a, STEP_BIKE
-	call .DoStep
-	scf
-	ret
-
-.walk
-	ld a, STEP_WALK
-	call .DoStep
-	scf
-	ret
-
-.ice
-	ld a, STEP_ICE
-	call .DoStep
-	scf
-	ret
-
-; unused
-	xor a
-	ret
-
-.bump
-	xor a
-	ret
-; 801c0
-
-.TrySurf: ; 801c0
-
-	call .CheckSurfPerms
-	ld [wd040], a
-	jr c, .surf_bump
-
-	call .CheckNPC
-	ld [wd03f], a
-	and a
-	jr z, .surf_bump
-	cp 2
-	jr z, .surf_bump
-
-	ld a, [wd040]
-	and a
-	jr nz, .ExitWater
-
-	ld a, STEP_WALK
-	call .DoStep
-	scf
-	ret
-
-.ExitWater:
-	call .GetOutOfWater
-	call PlayMapMusic
-	ld a, STEP_WALK
-	call .DoStep
-	ld a, 6
-	scf
-	ret
-
-.surf_bump
-	xor a
-	ret
-; 801f3
-
-.TryJump: ; 801f3
-	ld a, [wPlayerStandingTile]
-	ld e, a
-	and $f0
-	cp HI_NYBBLE_LEDGES
-	jr nz, .DontJump
-
-	ld a, e
-	and 7
-	ld e, a
-	ld d, 0
-	ld hl, .data_8021e
-	add hl, de
-	ld a, [wFacingDirection]
-	and [hl]
-	jr z, .DontJump
-
-	ld de, SFX_JUMP_OVER_LEDGE
-	call PlaySFX
-	ld a, STEP_LEDGE
-	call .DoStep
-	ld a, 7
-	scf
-	ret
-
-.DontJump:
-	xor a
-	ret
-
-.data_8021e
-	db FACE_RIGHT             ; COLL_HOP_RIGHT
-	db FACE_LEFT              ; COLL_HOP_LEFT
-	db FACE_UP                ; COLL_HOP_UP
-	db FACE_DOWN              ; COLL_HOP_DOWN
-	db FACE_RIGHT | FACE_DOWN ; COLL_HOP_DOWN_RIGHT
-	db FACE_DOWN | FACE_LEFT  ; COLL_HOP_DOWN_LEFT
-	db FACE_UP | FACE_RIGHT   ; COLL_HOP_UP_RIGHT
-	db FACE_UP | FACE_LEFT    ; COLL_HOP_UP_LEFT
-; 80226
-
-.CheckWarp: ; 80226
-
-; Bug: Since no case is made for STANDING here, it will check
-; [.edgewarps + $ff]. This resolves to $3e at $8035a.
-; This causes wd041 to be nonzero when standing on tile $3e,
-; making bumps silent.
-
-	ld a, [wWalkingDirection]
-	; cp STANDING
-	; jr z, .not_warp
-	ld e, a
-	ld d, 0
-	ld hl, .EdgeWarps
-	add hl, de
-	ld a, [wPlayerStandingTile]
-	cp [hl]
-	jr nz, .not_warp
-
-	ld a, 1
-	ld [wd041], a
-	ld a, [wWalkingDirection]
-	; This is in the wrong place.
-	cp STANDING
-	jr z, .not_warp
-
-	ld e, a
-	ld a, [wPlayerDirection]
-	rrca
-	rrca
-	maskbits NUM_DIRECTIONS
-	cp e
-	jr nz, .not_warp
-	call WarpCheck
-	jr nc, .not_warp
-
-	call .StandInPlace
-	scf
-	ld a, 1
-	ret
-
-.not_warp
-	xor a
-	ret
-
-.EdgeWarps:
-	db COLL_WARP_CARPET_DOWN
-	db COLL_WARP_CARPET_UP
-	db COLL_WARP_CARPET_LEFT
-	db COLL_WARP_CARPET_RIGHT
-; 8025f
-
-.DoStep:
-	ld e, a
-	ld d, 0
-	ld hl, .Steps
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-
-	ld a, [wWalkingDirection]
-	ld e, a
-	cp STANDING
-	jp z, .StandInPlace
-
-	add hl, de
-	ld a, [hl]
-	ld [wMovementAnimation], a
-
-	ld hl, .FinishFacing
-	add hl, de
-	ld a, [hl]
-	ld [wPlayerTurningDirection], a
-
-	ld a, 4
-	ret
-
-.Steps:
-	dw .SlowStep
-	dw .NormalStep
-	dw .FastStep
-	dw .JumpStep
-	dw .SlideStep
-	dw .TurningStep
-	dw .BackJumpStep
-	dw .FinishFacing
-
-.SlowStep:
-	slow_step DOWN
-	slow_step UP
-	slow_step LEFT
-	slow_step RIGHT
-.NormalStep:
-	step DOWN
-	step UP
-	step LEFT
-	step RIGHT
-.FastStep:
-	big_step DOWN
-	big_step UP
-	big_step LEFT
-	big_step RIGHT
-.JumpStep:
-	jump_step DOWN
-	jump_step UP
-	jump_step LEFT
-	jump_step RIGHT
-.SlideStep:
-	fast_slide_step DOWN
-	fast_slide_step UP
-	fast_slide_step LEFT
-	fast_slide_step RIGHT
-.BackJumpStep:
-	jump_step UP
-	jump_step DOWN
-	jump_step RIGHT
-	jump_step LEFT
-.TurningStep:
-	turn_step DOWN
-	turn_step UP
-	turn_step LEFT
-	turn_step RIGHT
-.FinishFacing:
-	db $80 + DOWN
-	db $80 + UP
-	db $80 + LEFT
-	db $80 + RIGHT
-; 802b3
-
-.StandInPlace: ; 802b3
-	ld a, 0
-	ld [wPlayerTurningDirection], a
-	ld a, movement_step_sleep
-	ld [wMovementAnimation], a
-	xor a
-	ret
-; 802bf
-
-._WalkInPlace: ; 802bf
-	ld a, 0
-	ld [wPlayerTurningDirection], a
-	ld a, movement_step_bump
-	ld [wMovementAnimation], a
-	xor a
-	ret
-; 802cb
-
-.CheckForced: ; 802cb
-; When sliding on ice, input is forced to remain in the same direction.
-
-	call CheckStandingOnIce
-	ret nc
-
-	ld a, [wPlayerTurningDirection]
-	cp 0
-	ret z
-
-	maskbits NUM_DIRECTIONS
-	ld e, a
-	ld d, 0
-	ld hl, .forced_dpad
-	add hl, de
-	ld a, [wCurInput]
-	and BUTTONS
-	or [hl]
-	ld [wCurInput], a
-	ret
-
-.forced_dpad
-	db D_DOWN, D_UP, D_LEFT, D_RIGHT
-; 802ec
-
-.GetAction: ; 802ec
-; Poll player input and update movement info.
-
-	ld hl, .table
-	ld de, .table2 - .table1
-	ld a, [wCurInput]
-	bit D_DOWN_F, a
-	jr nz, .d_down
-	bit D_UP_F, a
-	jr nz, .d_up
-	bit D_LEFT_F, a
-	jr nz, .d_left
-	bit D_RIGHT_F, a
-	jr nz, .d_right
-; Standing
-	jr .update
-
-.d_down 	add hl, de
-.d_up   	add hl, de
-.d_left 	add hl, de
-.d_right	add hl, de
-
-.update
-	ld a, [hli]
-	ld [wWalkingDirection], a
-	ld a, [hli]
-	ld [wFacingDirection], a
-	ld a, [hli]
-	ld [wWalkingX], a
-	ld a, [hli]
-	ld [wWalkingY], a
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [hl]
-	ld [wWalkingTile], a
-	ret
-
-.table
-; struct:
-;	walk direction
-;	facing
-;	x movement
-;	y movement
-;	tile collision pointer
-.table1
-	db STANDING, FACE_CURRENT, 0, 0
-	dw wPlayerStandingTile
-.table2
-	db RIGHT, FACE_RIGHT,  1,  0
-	dw wTileRight
-	db LEFT,  FACE_LEFT,  -1,  0
-	dw wTileLeft
-	db UP,    FACE_UP,     0, -1
-	dw wTileUp
-	db DOWN,  FACE_DOWN,   0,  1
-	dw wTileDown
-; 80341
-
-.CheckNPC: ; 80341
-; Returns 0 if there is an NPC in front that you can't move
-; Returns 1 if there is no NPC in front
-; Returns 2 if there is a movable NPC in front
-	ld a, 0
-	ld [hMapObjectIndexBuffer], a
-; Load the next X coordinate into d
-	ld a, [wPlayerStandingMapX]
-	ld d, a
-	ld a, [wWalkingX]
-	add d
-	ld d, a
-; Load the next Y coordinate into e
-	ld a, [wPlayerStandingMapY]
-	ld e, a
-	ld a, [wWalkingY]
-	add e
-	ld e, a
-; Find an object struct with coordinates equal to d,e
-	ld bc, wObjectStructs ; redundant
-	farcall IsNPCAtCoord
-	jr nc, .is_npc
-	call .CheckStrengthBoulder
-	jr c, .no_bump
-
-	xor a
-	ret
-
-.is_npc
-	ld a, 1
-	ret
-
-.no_bump
-	ld a, 2
-	ret
-; 8036f
-
-.CheckStrengthBoulder: ; 8036f
-
-	ld hl, wBikeFlags
-	bit BIKEFLAGS_STRENGTH_ACTIVE_F, [hl]
-	jr z, .not_boulder
-
-	ld hl, OBJECT_DIRECTION_WALKING
-	add hl, bc
-	ld a, [hl]
-	cp STANDING
-	jr nz, .not_boulder
-
-	ld hl, OBJECT_PALETTE
-	add hl, bc
-	bit 6, [hl]
-	jr z, .not_boulder
-
-	ld hl, OBJECT_FLAGS2
-	add hl, bc
-	set 2, [hl]
-
-	ld a, [wWalkingDirection]
-	ld d, a
-	ld hl, OBJECT_RANGE
-	add hl, bc
-	ld a, [hl]
-	and $fc
-	or d
-	ld [hl], a
-
-	scf
-	ret
-
-.not_boulder
-	xor a
-	ret
-; 8039e
-
-.CheckLandPerms: ; 8039e
-; Return 0 if walking onto land and tile permissions allow it.
-; Otherwise, return carry.
-
-	ld a, [wTilePermissions]
-	ld d, a
-	ld a, [wFacingDirection]
-	and d
-	jr nz, .NotWalkable
-
-	ld a, [wWalkingTile]
-	call .CheckWalkable
-	jr c, .NotWalkable
-
-	xor a
-	ret
-
-.NotWalkable:
-	scf
-	ret
-; 803b4
-
-.CheckSurfPerms: ; 803b4
-; Return 0 if moving in water, or 1 if moving onto land.
-; Otherwise, return carry.
-
-	ld a, [wTilePermissions]
-	ld d, a
-	ld a, [wFacingDirection]
-	and d
-	jr nz, .NotSurfable
-
-	ld a, [wWalkingTile]
-	call .CheckSurfable
-	jr c, .NotSurfable
-
-	and a
-	ret
-
-.NotSurfable:
-	scf
-	ret
-; 803ca
-
-.BikeCheck: ; 803ca
-	ld a, [wPlayerState]
-	cp PLAYER_BIKE
-	ret z
-	cp PLAYER_SKATE
-	ret
-; 803d3
-
-.CheckWalkable: ; 803d3
-; Return 0 if tile a is land. Otherwise, return carry.
-
-	call GetTileCollision
-	and a ; LANDTILE?
-	ret z
-	scf
-	ret
-; 803da
-
-.CheckSurfable: ; 803da
-; Return 0 if tile a is water, or 1 if land.
-; Otherwise, return carry.
-
-	call GetTileCollision
-	cp WATERTILE
-	jr z, .Water
-
-; Can walk back onto land from water.
-	and a ; LANDTILE?
-	jr z, .Land
-
-	jr .Neither
-
-.Water:
-	xor a
-	ret
-
-.Land:
-	ld a, 1
-	and a
-	ret
-
-.Neither:
-	scf
-	ret
-; 803ee
-
-.BumpSound: ; 803ee
-
-	call CheckSFX
-	ret c
-	ld de, SFX_BUMP
-	call PlaySFX
-	ret
-; 803f9
-
-.GetOutOfWater: ; 803f9
-	push bc
-	ld a, PLAYER_NORMAL
-	ld [wPlayerState], a
-	call ReplaceKrisSprite ; UpdateSprites
-	pop bc
-	ret
-; 80404
-
-CheckStandingOnIce:: ; 80404
-	ld a, [wPlayerTurningDirection]
-	cp 0
-	jr z, .not_ice
-	cp $f0
-	jr z, .not_ice
-	ld a, [wPlayerStandingTile]
-	call CheckIceTile
-	jr nc, .yep
-	ld a, [wPlayerState]
-	cp PLAYER_SKATE
-	jr nz, .not_ice
-
-.yep
-	scf
-	ret
-
-.not_ice
-	and a
-	ret
-; 80422
-
-StopPlayerForEvent:: ; 80422
-	ld hl, wPlayerNextMovement
-	ld a, movement_step_sleep
-	cp [hl]
-	ret z
-
-	ld [hl], a
-	ld a, 0
-	ld [wPlayerTurningDirection], a
-	ret
-; 80430
--- a/engine/player_object.asm
+++ /dev/null
@@ -1,856 +1,0 @@
-BlankScreen: ; 8000
-	call DisableSpriteUpdates
-	xor a
-	ld [hBGMapMode], a
-	call ClearBGPalettes
-	call ClearSprites
-	hlcoord 0, 0
-	ld bc, wTileMapEnd - wTileMap
-	ld a, " "
-	call ByteFill
-	hlcoord 0, 0, wAttrMap
-	ld bc, wAttrMapEnd - wAttrMap
-	ld a, $7
-	call ByteFill
-	call WaitBGMap2
-	call SetPalettes
-	ret
-
-SpawnPlayer: ; 8029
-	ld a, -1
-	ld [wObjectFollow_Leader], a
-	ld [wObjectFollow_Follower], a
-	ld a, $0
-	ld hl, PlayerObjectTemplate
-	call CopyPlayerObjectTemplate
-	ld b, $0
-	call PlayerSpawn_ConvertCoords
-	ld a, PLAYER_OBJECT
-	call GetMapObject
-	ld hl, MAPOBJECT_COLOR
-	add hl, bc
-	ln e, PAL_NPC_RED, OBJECTTYPE_SCRIPT
-	ld a, [wPlayerSpriteSetupFlags]
-	bit PLAYERSPRITESETUP_FEMALE_TO_MALE_F, a
-	jr nz, .ok
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .ok
-	ln e, PAL_NPC_BLUE, OBJECTTYPE_SCRIPT
-
-.ok
-	ld [hl], e
-	ld a, PLAYER_OBJECT
-	ld [hMapObjectIndexBuffer], a
-	ld bc, wMapObjects
-	ld a, PLAYER_OBJECT
-	ld [hObjectStructIndexBuffer], a
-	ld de, wObjectStructs
-	call CopyMapObjectToObjectStruct
-	ld a, PLAYER
-	ld [wCenteredObject], a
-	ret
-
-PlayerObjectTemplate: ; 8071
-; A dummy map object used to initialize the player object.
-; Shorter than the actual amount copied by two bytes.
-; Said bytes seem to be unused.
-	object_event -4, -4, SPRITE_CHRIS, SPRITEMOVEDATA_PLAYER, 15, 15, -1, -1, 0, OBJECTTYPE_SCRIPT, 0, 0, -1
-
-CopyDECoordsToMapObject:: ; 807e
-	push de
-	ld a, b
-	call GetMapObject
-	pop de
-	ld hl, MAPOBJECT_X_COORD
-	add hl, bc
-	ld [hl], d
-	ld hl, MAPOBJECT_Y_COORD
-	add hl, bc
-	ld [hl], e
-	ret
-
-PlayerSpawn_ConvertCoords: ; 808f
-	push bc
-	ld a, [wXCoord]
-	add 4
-	ld d, a
-	ld a, [wYCoord]
-	add 4
-	ld e, a
-	pop bc
-	call CopyDECoordsToMapObject
-	ret
-
-WriteObjectXY:: ; 80a1
-	ld a, b
-	call CheckObjectVisibility
-	ret c
-
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	ld a, [hMapObjectIndexBuffer]
-	ld b, a
-	call CopyDECoordsToMapObject
-	and a
-	ret
-
-RefreshPlayerCoords: ; 80b8
-	ld a, [wXCoord]
-	add 4
-	ld d, a
-	ld hl, wPlayerStandingMapX
-	sub [hl]
-	ld [hl], d
-	ld hl, wMapObjects + MAPOBJECT_X_COORD
-	ld [hl], d
-	ld hl, wPlayerLastMapX
-	ld [hl], d
-	ld d, a
-	ld a, [wYCoord]
-	add 4
-	ld e, a
-	ld hl, wPlayerStandingMapY
-	sub [hl]
-	ld [hl], e
-	ld hl, wMapObjects + MAPOBJECT_Y_COORD
-	ld [hl], e
-	ld hl, wPlayerLastMapY
-	ld [hl], e
-	ld e, a
-	ld a, [wObjectFollow_Leader]
-	cp $0
-	ret nz ; wtf
-	ret
-
-CopyObjectStruct:: ; 80e7
-	call CheckObjectMask
-	and a
-	ret nz ; masked
-
-	ld hl, wObjectStructs + OBJECT_STRUCT_LENGTH * 1
-	ld a, 1
-	ld de, OBJECT_STRUCT_LENGTH
-.loop
-	ld [hObjectStructIndexBuffer], a
-	ld a, [hl]
-	and a
-	jr z, .done
-	add hl, de
-	ld a, [hObjectStructIndexBuffer]
-	inc a
-	cp NUM_OBJECT_STRUCTS
-	jr nz, .loop
-	scf
-	ret ; overflow
-
-.done
-	ld d, h
-	ld e, l
-	call CopyMapObjectToObjectStruct
-	ld hl, wVramState
-	bit 7, [hl]
-	ret z
-
-	ld hl, OBJECT_FLAGS2
-	add hl, de
-	set 5, [hl]
-	ret
-
-CopyMapObjectToObjectStruct: ; 8116
-	call .CopyMapObjectToTempObject
-	call CopyTempObjectToObjectStruct
-	ret
-
-.CopyMapObjectToTempObject: ; 811d
-	ld a, [hObjectStructIndexBuffer]
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld [hl], a
-
-	ld a, [hMapObjectIndexBuffer]
-	ld [wTempObjectCopyMapObjectIndex], a
-
-	ld hl, MAPOBJECT_SPRITE
-	add hl, bc
-	ld a, [hl]
-	ld [wTempObjectCopySprite], a
-
-	call GetSpriteVTile
-	ld [wTempObjectCopySpriteVTile], a
-
-	ld a, [hl]
-	call GetSpritePalette
-	ld [wTempObjectCopyPalette], a
-
-	ld hl, MAPOBJECT_COLOR
-	add hl, bc
-	ld a, [hl]
-	and $f0
-	jr z, .skip_color_override
-	swap a
-	and PALETTE_MASK
-	ld [wTempObjectCopyPalette], a
-
-.skip_color_override
-	ld hl, MAPOBJECT_MOVEMENT
-	add hl, bc
-	ld a, [hl]
-	ld [wTempObjectCopyMovement], a
-
-	ld hl, MAPOBJECT_RANGE
-	add hl, bc
-	ld a, [hl]
-	ld [wTempObjectCopyRange], a
-
-	ld hl, MAPOBJECT_X_COORD
-	add hl, bc
-	ld a, [hl]
-	ld [wTempObjectCopyX], a
-
-	ld hl, MAPOBJECT_Y_COORD
-	add hl, bc
-	ld a, [hl]
-	ld [wTempObjectCopyY], a
-
-	ld hl, MAPOBJECT_RADIUS
-	add hl, bc
-	ld a, [hl]
-	ld [wTempObjectCopyRadius], a
-	ret
-
-InitializeVisibleSprites: ; 8177
-	ld bc, wMapObjects + OBJECT_LENGTH
-	ld a, 1
-.loop
-	ld [hMapObjectIndexBuffer], a
-	ld hl, MAPOBJECT_SPRITE
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .next
-
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	cp -1
-	jr nz, .next
-
-	ld a, [wXCoord]
-	ld d, a
-	ld a, [wYCoord]
-	ld e, a
-
-	ld hl, MAPOBJECT_X_COORD
-	add hl, bc
-	ld a, [hl]
-	add 1
-	sub d
-	jr c, .next
-
-	cp MAPOBJECT_SCREEN_WIDTH
-	jr nc, .next
-
-	ld hl, MAPOBJECT_Y_COORD
-	add hl, bc
-	ld a, [hl]
-	add 1
-	sub e
-	jr c, .next
-
-	cp MAPOBJECT_SCREEN_HEIGHT
-	jr nc, .next
-
-	push bc
-	call CopyObjectStruct
-	pop bc
-	jp c, .ret
-
-.next
-	ld hl, OBJECT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	ld a, [hMapObjectIndexBuffer]
-	inc a
-	cp NUM_OBJECTS
-	jr nz, .loop
-	ret
-
-.ret ; 81c9
-	ret
-
-CheckObjectEnteringVisibleRange:: ; 81ca
-	nop
-	ld a, [wPlayerStepDirection]
-	cp STANDING
-	ret z
-	ld hl, .dw
-	rst JumpTable
-	ret
-
-.dw ; 81d6
-	dw .Down
-	dw .Up
-	dw .Left
-	dw .Right
-
-.Up: ; 81de
-	ld a, [wYCoord]
-	sub 1
-	jr .Vertical
-
-.Down: ; 81e5
-	ld a, [wYCoord]
-	add 9
-.Vertical: ; 81ea
-	ld d, a
-	ld a, [wXCoord]
-	ld e, a
-	ld bc, wMapObjects + OBJECT_LENGTH
-	ld a, 1
-.loop_v
-	ld [hMapObjectIndexBuffer], a
-	ld hl, MAPOBJECT_SPRITE
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .next_v
-	ld hl, MAPOBJECT_Y_COORD
-	add hl, bc
-	ld a, d
-	cp [hl]
-	jr nz, .next_v
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	cp -1
-	jr nz, .next_v
-	ld hl, MAPOBJECT_X_COORD
-	add hl, bc
-	ld a, [hl]
-	add 1
-	sub e
-	jr c, .next_v
-	cp MAPOBJECT_SCREEN_WIDTH
-	jr nc, .next_v
-	push de
-	push bc
-	call CopyObjectStruct
-	pop bc
-	pop de
-
-.next_v
-	ld hl, OBJECT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	ld a, [hMapObjectIndexBuffer]
-	inc a
-	cp NUM_OBJECTS
-	jr nz, .loop_v
-	ret
-
-.Left: ; 8232
-	ld a, [wXCoord]
-	sub 1
-	jr .Horizontal
-
-.Right: ; 8239
-	ld a, [wXCoord]
-	add 10
-.Horizontal: ; 823e
-	ld e, a
-	ld a, [wYCoord]
-	ld d, a
-	ld bc, wMapObjects + OBJECT_LENGTH
-	ld a, 1
-.loop_h
-	ld [hMapObjectIndexBuffer], a
-	ld hl, MAPOBJECT_SPRITE
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .next_h
-	ld hl, MAPOBJECT_X_COORD
-	add hl, bc
-	ld a, e
-	cp [hl]
-	jr nz, .next_h
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	cp -1
-	jr nz, .next_h
-	ld hl, MAPOBJECT_Y_COORD
-	add hl, bc
-	ld a, [hl]
-	add 1
-	sub d
-	jr c, .next_h
-	cp MAPOBJECT_SCREEN_HEIGHT
-	jr nc, .next_h
-	push de
-	push bc
-	call CopyObjectStruct
-	pop bc
-	pop de
-
-.next_h
-	ld hl, OBJECT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	ld a, [hMapObjectIndexBuffer]
-	inc a
-	cp NUM_OBJECTS
-	jr nz, .loop_h
-	ret
-
-CopyTempObjectToObjectStruct: ; 8286
-	ld a, [wTempObjectCopyMapObjectIndex]
-	ld hl, OBJECT_MAP_OBJECT_INDEX
-	add hl, de
-	ld [hl], a
-
-	ld a, [wTempObjectCopyMovement]
-	call CopySpriteMovementData
-
-	ld a, [wTempObjectCopyPalette]
-	ld hl, OBJECT_PALETTE
-	add hl, de
-	or [hl]
-	ld [hl], a
-
-	ld a, [wTempObjectCopyY]
-	call .InitYCoord
-
-	ld a, [wTempObjectCopyX]
-	call .InitXCoord
-
-	ld a, [wTempObjectCopySprite]
-	ld hl, OBJECT_SPRITE
-	add hl, de
-	ld [hl], a
-
-	ld a, [wTempObjectCopySpriteVTile]
-	ld hl, OBJECT_SPRITE_TILE
-	add hl, de
-	ld [hl], a
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, de
-	ld [hl], STEP_TYPE_00
-
-	ld hl, OBJECT_FACING_STEP
-	add hl, de
-	ld [hl], STANDING
-
-	ld a, [wTempObjectCopyRadius]
-	call .InitRadius
-
-	ld a, [wTempObjectCopyRange]
-	ld hl, OBJECT_RANGE
-	add hl, de
-	ld [hl], a
-
-	and a
-	ret
-
-.InitYCoord: ; 82d5
-	ld hl, OBJECT_INIT_Y
-	add hl, de
-	ld [hl], a
-
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, de
-	ld [hl], a
-
-	ld hl, wYCoord
-	sub [hl]
-	and $f
-	swap a
-	ld hl, wPlayerBGMapOffsetY
-	sub [hl]
-	ld hl, OBJECT_SPRITE_Y
-	add hl, de
-	ld [hl], a
-	ret
-
-.InitXCoord: ; 82f1
-	ld hl, OBJECT_INIT_X
-	add hl, de
-	ld [hl], a
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, de
-	ld [hl], a
-	ld hl, wXCoord
-	sub [hl]
-	and $f
-	swap a
-	ld hl, wPlayerBGMapOffsetX
-	sub [hl]
-	ld hl, OBJECT_SPRITE_X
-	add hl, de
-	ld [hl], a
-	ret
-
-.InitRadius: ; 830d
-	ld h, a
-	inc a
-	and $f
-	ld l, a
-	ld a, h
-	add $10
-	and $f0
-	or l
-	ld hl, OBJECT_RADIUS
-	add hl, de
-	ld [hl], a
-	ret
-
-TrainerWalkToPlayer: ; 831e
-	ld a, [hLastTalked]
-	call InitMovementBuffer
-	ld a, movement_step_sleep
-	call AppendToMovementBuffer
-	ld a, [wd03f]
-	dec a
-	jr z, .TerminateStep
-	ld a, [hLastTalked]
-	ld b, a
-	ld c, PLAYER
-	ld d, 1
-	call .GetPathToPlayer
-	call DecrementMovementBufferCount
-
-.TerminateStep:
-	ld a, movement_step_end
-	call AppendToMovementBuffer
-	ret
-
-.GetPathToPlayer: ; 8341
-	push de
-	push bc
-; get player object struct, load to de
-	ld a, c
-	call GetMapObject
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	call GetObjectStruct
-	ld d, b
-	ld e, c
-
-; get last talked object struct, load to bc
-	pop bc
-	ld a, b
-	call GetMapObject
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	call GetObjectStruct
-
-; get last talked coords, load to bc
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld c, [hl]
-	ld b, a
-
-; get player coords, load to de
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, de
-	ld a, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, de
-	ld e, [hl]
-	ld d, a
-
-	pop af
-	call ComputePathToWalkToPlayer
-	ret
-
-SurfStartStep: ; 8379
-	call InitMovementBuffer
-	call .GetMovementData
-	call AppendToMovementBuffer
-	ld a, movement_step_end
-	call AppendToMovementBuffer
-	ret
-
-.GetMovementData: ; 8388
-	ld a, [wPlayerDirection]
-	srl a
-	srl a
-	maskbits NUM_DIRECTIONS
-	ld e, a
-	ld d, 0
-	ld hl, .movement_data
-	add hl, de
-	ld a, [hl]
-	ret
-
-.movement_data
-	slow_step DOWN
-	slow_step UP
-	slow_step LEFT
-	slow_step RIGHT
-
-FollowNotExact:: ; 839e
-	push bc
-	ld a, c
-	call CheckObjectVisibility
-	ld d, b
-	ld e, c
-	pop bc
-	ret c
-
-	ld a, b
-	call CheckObjectVisibility
-	ret c
-
-; object 2 is now in bc, object 1 is now in de
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld c, [hl]
-	ld b, a
-
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, de
-	ld a, [hl]
-	cp b
-	jr z, .same_x
-	jr c, .to_the_left
-	inc b
-	jr .continue
-
-.to_the_left
-	dec b
-	jr .continue
-
-.same_x
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, de
-	ld a, [hl]
-	cp c
-	jr z, .continue
-	jr c, .below
-	inc c
-	jr .continue
-
-.below
-	dec c
-
-.continue
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, de
-	ld [hl], b
-	ld a, b
-	ld hl, wXCoord
-	sub [hl]
-	and $f
-	swap a
-	ld hl, wPlayerBGMapOffsetX
-	sub [hl]
-	ld hl, OBJECT_SPRITE_X
-	add hl, de
-	ld [hl], a
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, de
-	ld [hl], c
-	ld a, c
-	ld hl, wYCoord
-	sub [hl]
-	and $f
-	swap a
-	ld hl, wPlayerBGMapOffsetY
-	sub [hl]
-	ld hl, OBJECT_SPRITE_Y
-	add hl, de
-	ld [hl], a
-	ld a, [hObjectStructIndexBuffer]
-	ld hl, OBJECT_RANGE
-	add hl, de
-	ld [hl], a
-	ld hl, OBJECT_MOVEMENTTYPE
-	add hl, de
-	ld [hl], SPRITEMOVEDATA_FOLLOWNOTEXACT
-	ld hl, OBJECT_STEP_TYPE
-	add hl, de
-	ld [hl], STEP_TYPE_00
-	ret
-
-GetRelativeFacing:: ; 8417
-; Determines which way map object e would have to turn to face map object d.  Returns carry if it's impossible for whatever reason.
-	ld a, d
-	call GetMapObject
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	cp NUM_OBJECT_STRUCTS
-	jr nc, .carry
-	ld d, a
-	ld a, e
-	call GetMapObject
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	cp NUM_OBJECT_STRUCTS
-	jr nc, .carry
-	ld e, a
-	call .GetFacing_e_relativeto_d
-	ret
-
-.carry
-	scf
-	ret
-
-.GetFacing_e_relativeto_d: ; 8439
-; Determines which way object e would have to turn to face object d.  Returns carry if it's impossible.
-; load the coordinates of object d into bc
-	ld a, d
-	call GetObjectStruct
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld c, [hl]
-	ld b, a
-	push bc
-; load the coordinates of object e into de
-	ld a, e
-	call GetObjectStruct
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	pop bc
-; |x1 - x2|
-	ld a, b
-	sub d
-	jr z, .same_x_1
-	jr nc, .b_right_of_d_1
-	cpl
-	inc a
-
-.b_right_of_d_1
-; |y1 - y2|
-	ld h, a
-	ld a, c
-	sub e
-	jr z, .same_y_1
-	jr nc, .c_below_e_1
-	cpl
-	inc a
-
-.c_below_e_1
-; |y1 - y2| - |x1 - x2|
-	sub h
-	jr c, .same_y_1
-
-.same_x_1
-; compare the y coordinates
-	ld a, c
-	cp e
-	jr z, .same_x_and_y
-	jr c, .c_directly_below_e
-; c directly above e
-	ld d, DOWN
-	and a
-	ret
-
-.c_directly_below_e
-	ld d, UP
-	and a
-	ret
-
-.same_y_1
-	ld a, b
-	cp d
-	jr z, .same_x_and_y
-	jr c, .b_directly_right_of_d
-; b directly left of d
-	ld d, RIGHT
-	and a
-	ret
-
-.b_directly_right_of_d
-	ld d, LEFT
-	and a
-	ret
-
-.same_x_and_y
-	scf
-	ret
-
-QueueFollowerFirstStep: ; 848a
-	call .QueueFirstStep
-	jr c, .same
-	ld [wFollowMovementQueue], a
-	xor a
-	ld [wFollowerMovementQueueLength], a
-	ret
-
-.same
-	ld a, -1
-	ld [wFollowerMovementQueueLength], a
-	ret
-
-.QueueFirstStep:
-	ld a, [wObjectFollow_Leader]
-	call GetObjectStruct
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	ld a, [wObjectFollow_Follower]
-	call GetObjectStruct
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, d
-	cp [hl]
-	jr z, .check_y
-	jr c, .left
-	and a
-	ld a, movement_step + RIGHT
-	ret
-
-.left
-	and a
-	ld a, movement_step + LEFT
-	ret
-
-.check_y
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld a, e
-	cp [hl]
-	jr z, .same_xy
-	jr c, .up
-	and a
-	ld a, movement_step + DOWN
-	ret
-
-.up
-	and a
-	ld a, movement_step + UP
-	ret
-
-.same_xy
-	scf
-	ret
--- a/engine/player_step.asm
+++ /dev/null
@@ -1,270 +1,0 @@
-_HandlePlayerStep:: ; d497 (3:5497)
-	ld a, [wPlayerStepFlags]
-	and a
-	ret z
-	bit 7, a ; starting step
-	jr nz, .update_overworld_map
-	bit 6, a ; finishing step
-	jr nz, .update_player_coords
-	bit 5, a ; ongoing step
-	jr nz, .finish
-	ret
-
-.update_overworld_map
-	ld a, 4
-	ld [wHandlePlayerStep], a
-	call UpdateOverworldMap
-	jr .finish
-
-.update_player_coords
-	call UpdatePlayerCoords
-	jr .finish
-
-.finish
-	call HandlePlayerStep
-	ld a, [wPlayerStepVectorX]
-	ld d, a
-	ld a, [wPlayerStepVectorY]
-	ld e, a
-	ld a, [wPlayerBGMapOffsetX]
-	sub d
-	ld [wPlayerBGMapOffsetX], a
-	ld a, [wPlayerBGMapOffsetY]
-	sub e
-	ld [wPlayerBGMapOffsetY], a
-	ret
-
-ScrollScreen:: ; d4d2 (3:54d2)
-	ld a, [wPlayerStepVectorX]
-	ld d, a
-	ld a, [wPlayerStepVectorY]
-	ld e, a
-	ld a, [hSCX]
-	add d
-	ld [hSCX], a
-	ld a, [hSCY]
-	add e
-	ld [hSCY], a
-	ret
-
-HandlePlayerStep: ; d4e5 (3:54e5)
-	ld hl, wHandlePlayerStep
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-	ld a, [hl]
-	ld hl, .Jumptable
-	rst JumpTable
-	ret
-
-.Jumptable: ; d4f2 (3:54f2)
-	dw GetMovementPermissions
-	dw BufferScreen
-	dw .mobile
-	dw .fail2
-; The rest are never used.  Ever.
-	dw .fail1
-	dw .fail1
-	dw .fail1
-	dw .fail1
-	dw .fail1
-	dw .fail1
-	dw .fail1
-
-.fail1 ; d508 (3:5508)
-	ret
-
-.mobile ; d509 (3:5509)
-	farcall StubbedTrainerRankings_StepCount
-	ret
-
-.fail2 ; d510 (3:5510)
-	ret
-
-UpdatePlayerCoords: ; d511 (3:5511)
-	ld a, [wPlayerStepDirection]
-	and a
-	jr nz, .check_step_down
-	ld hl, wYCoord
-	inc [hl]
-	ret
-
-.check_step_down
-	cp UP
-	jr nz, .check_step_left
-	ld hl, wYCoord
-	dec [hl]
-	ret
-
-.check_step_left
-	cp LEFT
-	jr nz, .check_step_right
-	ld hl, wXCoord
-	dec [hl]
-	ret
-
-.check_step_right
-	cp RIGHT
-	ret nz
-	ld hl, wXCoord
-	inc [hl]
-	ret
-
-UpdateOverworldMap: ; d536 (3:5536)
-	ld a, [wPlayerStepDirection]
-	and a
-	jr z, .step_down
-	cp UP
-	jr z, .step_up
-	cp LEFT
-	jr z, .step_left
-	cp RIGHT
-	jr z, .step_right
-	ret
-
-.step_down
-	call .ScrollOverworldMapDown
-	call LoadMapPart
-	call ScrollMapUp
-	ret
-
-.step_up
-	call .ScrollOverworldMapUp
-	call LoadMapPart
-	call ScrollMapDown
-	ret
-
-.step_left
-	call .ScrollOverworldMapLeft
-	call LoadMapPart
-	call ScrollMapRight
-	ret
-
-.step_right
-	call .ScrollOverworldMapRight
-	call LoadMapPart
-	call ScrollMapLeft
-	ret
-
-.ScrollOverworldMapDown: ; d571 (3:5571)
-	ld a, [wBGMapAnchor]
-	add 2 * BG_MAP_WIDTH
-	ld [wBGMapAnchor], a
-	jr nc, .not_overflowed
-	ld a, [wBGMapAnchor + 1]
-	inc a
-	and %11
-	or HIGH(vBGMap0)
-	ld [wBGMapAnchor + 1], a
-.not_overflowed
-	ld hl, wMetatileStandingY
-	inc [hl]
-	ld a, [hl]
-	cp 2 ; was 1
-	jr nz, .done_down
-	ld [hl], 0
-	call .Add6ToOverworldMapAnchor
-.done_down
-	ret
-
-.Add6ToOverworldMapAnchor: ; d595 (3:5595)
-	ld hl, wOverworldMapAnchor
-	ld a, [wMapWidth]
-	add 6
-	add [hl]
-	ld [hli], a
-	ret nc
-	inc [hl]
-	ret
-
-.ScrollOverworldMapUp: ; d5a2 (3:55a2)
-	ld a, [wBGMapAnchor]
-	sub 2 * BG_MAP_WIDTH
-	ld [wBGMapAnchor], a
-	jr nc, .not_underflowed
-	ld a, [wBGMapAnchor + 1]
-	dec a
-	and %11
-	or HIGH(vBGMap0)
-	ld [wBGMapAnchor + 1], a
-.not_underflowed
-	ld hl, wMetatileStandingY
-	dec [hl]
-	ld a, [hl]
-	cp -1 ; was 0
-	jr nz, .done_up
-	ld [hl], $1
-	call .Sub6FromOverworldMapAnchor
-.done_up
-	ret
-
-.Sub6FromOverworldMapAnchor: ; d5c6 (3:55c6)
-	ld hl, wOverworldMapAnchor
-	ld a, [wMapWidth]
-	add 6
-	ld b, a
-	ld a, [hl]
-	sub b
-	ld [hli], a
-	ret nc
-	dec [hl]
-	ret
-
-.ScrollOverworldMapLeft: ; d5d5 (3:55d5)
-	ld a, [wBGMapAnchor]
-	ld e, a
-	and $e0
-	ld d, a
-	ld a, e
-	sub $2
-	and $1f
-	or d
-	ld [wBGMapAnchor], a
-	ld hl, wMetatileStandingX
-	dec [hl]
-	ld a, [hl]
-	cp -1
-	jr nz, .done_left
-	ld [hl], 1
-	call .DecrementwOverworldMapAnchor
-.done_left
-	ret
-
-.DecrementwOverworldMapAnchor: ; d5f4 (3:55f4)
-	ld hl, wOverworldMapAnchor
-	ld a, [hl]
-	sub 1
-	ld [hli], a
-	ret nc
-	dec [hl]
-	ret
-
-.ScrollOverworldMapRight: ; d5fe (3:55fe)
-	ld a, [wBGMapAnchor]
-	ld e, a
-	and $e0
-	ld d, a
-	ld a, e
-	add $2
-	and $1f
-	or d
-	ld [wBGMapAnchor], a
-	ld hl, wMetatileStandingX
-	inc [hl]
-	ld a, [hl]
-	cp 2
-	jr nz, .done_right
-	ld [hl], 0
-	call .IncrementwOverworldMapAnchor
-.done_right
-	ret
-
-.IncrementwOverworldMapAnchor: ; d61d (3:561d)
-	ld hl, wOverworldMapAnchor
-	ld a, [hl]
-	add 1
-	ld [hli], a
-	ret nc
-	inc [hl]
-	ret
--- a/engine/pokegear.asm
+++ /dev/null
@@ -1,3097 +1,0 @@
-; Pokégear cards
-	const_def
-	const POKEGEARCARD_CLOCK ; 0
-	const POKEGEARCARD_MAP   ; 1
-	const POKEGEARCARD_PHONE ; 2
-	const POKEGEARCARD_RADIO ; 3
-NUM_POKEGEAR_CARDS EQU const_value
-
-; PokegearJumptable.Jumptable indexes
-	const_def
-	const POKEGEARSTATE_CLOCKINIT       ; 0
-	const POKEGEARSTATE_CLOCKJOYPAD     ; 1
-	const POKEGEARSTATE_MAPCHECKREGION  ; 2
-	const POKEGEARSTATE_JOHTOMAPINIT    ; 3
-	const POKEGEARSTATE_JOHTOMAPJOYPAD  ; 4
-	const POKEGEARSTATE_KANTOMAPINIT    ; 5
-	const POKEGEARSTATE_KANTOMAPJOYPAD  ; 6
-	const POKEGEARSTATE_PHONEINIT       ; 7
-	const POKEGEARSTATE_PHONEJOYPAD     ; 8
-	const POKEGEARSTATE_MAKEPHONECALL   ; 9
-	const POKEGEARSTATE_FINISHPHONECALL ; a
-	const POKEGEARSTATE_RADIOINIT       ; b
-	const POKEGEARSTATE_RADIOJOYPAD     ; c
-
-PokeGear: ; 90b8d (24:4b8d)
-	ld hl, wOptions
-	ld a, [hl]
-	push af
-	set NO_TEXT_SCROLL, [hl]
-	ld a, [hInMenu]
-	push af
-	ld a, $1
-	ld [hInMenu], a
-	ld a, [wVramState]
-	push af
-	xor a
-	ld [wVramState], a
-	call .InitTilemap
-	call DelayFrame
-.loop
-	call UpdateTime
-	call JoyTextDelay
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .done
-	call PokegearJumptable
-	farcall PlaySpriteAnimations
-	call DelayFrame
-	jr .loop
-
-.done
-	ld de, SFX_READ_TEXT_2
-	call PlaySFX
-	call WaitSFX
-	pop af
-	ld [wVramState], a
-	pop af
-	ld [hInMenu], a
-	pop af
-	ld [wOptions], a
-	call ClearBGPalettes
-	xor a ; LOW(vBGMap0)
-	ld [hBGMapAddress], a
-	ld a, HIGH(vBGMap0)
-	ld [hBGMapAddress + 1], a
-	ld a, $90
-	ld [hWY], a
-	call ExitPokegearRadio_HandleMusic
-	ret
-
-.InitTilemap: ; 90bea (24:4bea)
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	call DisableLCD
-	xor a
-	ld [hSCY], a
-	ld [hSCX], a
-	ld a, $7
-	ld [hWX], a
-	call Pokegear_LoadGFX
-	farcall ClearSpriteAnims
-	call InitPokegearModeIndicatorArrow
-	ld a, 8
-	call SkipMusic
-	ld a, LCDC_DEFAULT
-	ld [rLCDC], a
-	call TownMap_InitCursorAndPlayerIconPositions
-	xor a
-	ld [wJumptableIndex], a ; POKEGEARSTATE_CLOCKINIT
-	ld [wPokegearCard], a ; POKEGEARCARD_CLOCK
-	ld [wPokegearMapRegion], a ; JOHTO_REGION
-	ld [wcf66], a
-	ld [wPokegearPhoneScrollPosition], a
-	ld [wPokegearPhoneCursorPosition], a
-	ld [wPokegearPhoneSelectedPerson], a
-	ld [wPokegearRadioChannelBank], a
-	ld [wPokegearRadioChannelAddr], a
-	ld [wPokegearRadioChannelAddr + 1], a
-	call Pokegear_InitJumptableIndices
-	call InitPokegearTilemap
-	ld b, SCGB_POKEGEAR_PALS
-	call GetSGBLayout
-	call SetPalettes
-	ld a, [hCGB]
-	and a
-	ret z
-	ld a, %11100100
-	call DmgToCgbObjPal0
-	ret
-
-Pokegear_LoadGFX: ; 90c4e
-	call ClearVBank1
-	ld hl, TownMapGFX
-	ld de, vTiles2
-	ld a, BANK(TownMapGFX)
-	call FarDecompress
-	ld hl, PokegearGFX
-	ld de, vTiles2 tile $30
-	ld a, BANK(PokegearGFX)
-	call FarDecompress
-	ld hl, PokegearSpritesGFX
-	ld de, vTiles0
-	ld a, BANK(PokegearSpritesGFX)
-	call Decompress
-	ld a, [wMapGroup]
-	ld b, a
-	ld a, [wMapNumber]
-	ld c, a
-	call GetWorldMapLocation
-	cp FAST_SHIP
-	jr z, .ssaqua
-	farcall GetPlayerIcon
-	push de
-	ld h, d
-	ld l, e
-	ld a, b
-	; standing sprite
-	push af
-	ld de, vTiles0 tile $10
-	ld bc, 4 tiles
-	call FarCopyBytes
-	pop af
-	pop hl
-	; walking sprite
-	ld de, 12 tiles
-	add hl, de
-	ld de, vTiles0 tile $14
-	ld bc, 4 tiles
-	call FarCopyBytes
-	ret
-
-.ssaqua
-	ld hl, FastShipGFX
-	ld de, vTiles0 tile $10
-	ld bc, 8 tiles
-	call CopyBytes
-	ret
-
-; 90cb2
-
-FastShipGFX: ; 90cb2
-INCBIN "gfx/pokegear/fast_ship.2bpp"
-; 90d32
-
-InitPokegearModeIndicatorArrow: ; 90d32 (24:4d32)
-	depixel 4, 2, 4, 0
-	ld a, SPRITE_ANIM_INDEX_POKEGEAR_ARROW
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_TILE_ID
-	add hl, bc
-	ld [hl], $0
-	ret
-
-AnimatePokegearModeIndicatorArrow: ; 90d41 (24:4d41)
-	ld hl, wPokegearCard
-	ld e, [hl]
-	ld d, 0
-	ld hl, .XCoords
-	add hl, de
-	ld a, [hl]
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-; 90d52 (24:4d52)
-
-.XCoords: ; 90d52
-	db $00 ; POKEGEARCARD_CLOCK
-	db $10 ; POKEGEARCARD_MAP
-	db $20 ; POKEGEARCARD_PHONE
-	db $30 ; POKEGEARCARD_RADIO
-; 90d56
-
-TownMap_GetCurrentLandmark: ; 90d56
-	ld a, [wMapGroup]
-	ld b, a
-	ld a, [wMapNumber]
-	ld c, a
-	call GetWorldMapLocation
-	cp SPECIAL_MAP
-	ret nz
-	ld a, [wBackupMapGroup]
-	ld b, a
-	ld a, [wBackupMapNumber]
-	ld c, a
-	call GetWorldMapLocation
-	ret
-
-; 90d70
-
-TownMap_InitCursorAndPlayerIconPositions: ; 90d70 (24:4d70)
-	ld a, [wMapGroup]
-	ld b, a
-	ld a, [wMapNumber]
-	ld c, a
-	call GetWorldMapLocation
-	cp FAST_SHIP
-	jr z, .FastShip
-	cp SPECIAL_MAP
-	jr nz, .LoadLandmark
-	ld a, [wBackupMapGroup]
-	ld b, a
-	ld a, [wBackupMapNumber]
-	ld c, a
-	call GetWorldMapLocation
-.LoadLandmark:
-	ld [wPokegearMapPlayerIconLandmark], a
-	ld [wPokegearMapCursorLandmark], a
-	ret
-
-.FastShip:
-	ld [wPokegearMapPlayerIconLandmark], a
-	ld a, NEW_BARK_TOWN
-	ld [wPokegearMapCursorLandmark], a
-	ret
-
-Pokegear_InitJumptableIndices: ; 90d9e (24:4d9e)
-	ld a, POKEGEARSTATE_CLOCKINIT
-	ld [wJumptableIndex], a
-	xor a ; POKEGEARCARD_CLOCK
-	ld [wPokegearCard], a
-	ret
-
-InitPokegearTilemap: ; 90da8 (24:4da8)
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, $4f
-	call ByteFill
-	ld a, [wPokegearCard]
-	maskbits NUM_POKEGEAR_CARDS
-	add a
-	ld e, a
-	ld d, 0
-	ld hl, .Jumptable
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, .return_from_jumptable
-	push de
-	jp hl
-
-.return_from_jumptable
-	call Pokegear_FinishTilemap
-	farcall TownMapPals
-	ld a, [wPokegearMapRegion]
-	and a
-	jr nz, .kanto_0
-	xor a ; LOW(vBGMap0)
-	ld [hBGMapAddress], a
-	ld a, HIGH(vBGMap0)
-	ld [hBGMapAddress + 1], a
-	call .UpdateBGMap
-	ld a, $90
-	jr .finish
-
-.kanto_0
-	xor a ; LOW(vBGMap1)
-	ld [hBGMapAddress], a
-	ld a, HIGH(vBGMap1)
-	ld [hBGMapAddress + 1], a
-	call .UpdateBGMap
-	xor a
-.finish
-	ld [hWY], a
-	; swap region maps
-	ld a, [wPokegearMapRegion]
-	maskbits NUM_REGIONS
-	xor 1
-	ld [wPokegearMapRegion], a
-	ret
-
-.UpdateBGMap: ; 90e00 (24:4e00)
-	ld a, [hCGB]
-	and a
-	jr z, .dmg
-	ld a, $2
-	ld [hBGMapMode], a
-	ld c, 3
-	call DelayFrames
-.dmg
-	call WaitBGMap
-	ret
-
-; 90e12 (24:4e12)
-
-.Jumptable: ; 90e12
-; entries correspond to POKEGEARCARD_* constants
-	dw .Clock
-	dw .Map
-	dw .Phone
-	dw .Radio
-; 90e1a
-
-.Clock: ; 90e1a
-	ld de, ClockTilemapRLE
-	call Pokegear_LoadTilemapRLE
-	hlcoord 12, 1
-	ld de, .switch
-	call PlaceString
-	hlcoord 0, 12
-	lb bc, 4, 18
-	call TextBox
-	call Pokegear_UpdateClock
-	ret
-
-; 90e36 (24:4e36)
-
-.switch
-	db " SWITCH▶@"
-; 90e3f
-
-.Map: ; 90e3f
-	ld a, [wPokegearMapPlayerIconLandmark]
-	cp FAST_SHIP
-	jr z, .johto
-	cp KANTO_LANDMARK
-	jr nc, .kanto
-.johto
-	ld e, 0
-	jr .ok
-
-.kanto
-	ld e, 1
-.ok
-	farcall PokegearMap
-	ld a, $07
-	ld bc, $12
-	hlcoord 1, 2
-	call ByteFill
-	hlcoord 0, 2
-	ld [hl], $06
-	hlcoord 19, 2
-	ld [hl], $17
-	ld a, [wPokegearMapCursorLandmark]
-	call PokegearMap_UpdateLandmarkName
-	ret
-
-; 90e72
-
-.Radio: ; 90e72
-	ld de, RadioTilemapRLE
-	call Pokegear_LoadTilemapRLE
-	hlcoord 0, 12
-	lb bc, 4, 18
-	call TextBox
-	ret
-
-; 90e82
-
-.Phone: ; 90e82
-	ld de, PhoneTilemapRLE
-	call Pokegear_LoadTilemapRLE
-	hlcoord 0, 12
-	lb bc, 4, 18
-	call TextBox
-	call .PlacePhoneBars
-	call PokegearPhone_UpdateDisplayList
-	ret
-
-; 90e98
-
-.PlacePhoneBars: ; 90e98 (24:4e98)
-	hlcoord 17, 1
-	ld a, $3c
-	ld [hli], a
-	inc a
-	ld [hl], a
-	hlcoord 17, 2
-	inc a
-	ld [hli], a
-	call GetMapPhoneService
-	and a
-	ret nz
-	hlcoord 18, 2
-	ld [hl], $3f
-	ret
-
-Pokegear_FinishTilemap: ; 90eb0 (24:4eb0)
-	hlcoord 0, 0
-	ld bc, $8
-	ld a, $4f
-	call ByteFill
-	hlcoord 0, 1
-	ld bc, $8
-	ld a, $4f
-	call ByteFill
-	ld de, wPokegearFlags
-	ld a, [de]
-	bit POKEGEAR_MAP_CARD_F, a
-	call nz, .PlaceMapIcon
-	ld a, [de]
-	bit POKEGEAR_PHONE_CARD_F, a
-	call nz, .PlacePhoneIcon
-	ld a, [de]
-	bit POKEGEAR_RADIO_CARD_F, a
-	call nz, .PlaceRadioIcon
-	hlcoord 0, 0
-	ld a, $46
-	call .PlacePokegearCardIcon
-	ret
-
-.PlaceMapIcon: ; 90ee4 (24:4ee4)
-	hlcoord 2, 0
-	ld a, $40
-	jr .PlacePokegearCardIcon
-
-.PlacePhoneIcon: ; 90eeb (24:4eeb)
-	hlcoord 4, 0
-	ld a, $44
-	jr .PlacePokegearCardIcon
-
-.PlaceRadioIcon: ; 90ef2 (24:4ef2)
-	hlcoord 6, 0
-	ld a, $42
-.PlacePokegearCardIcon: ; 90ef7 (24:4ef7)
-	ld [hli], a
-	inc a
-	ld [hld], a
-	ld bc, $14
-	add hl, bc
-	add $f
-	ld [hli], a
-	inc a
-	ld [hld], a
-	ret
-
-PokegearJumptable: ; 90f04 (24:4f04)
-	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: ; 90f13 (24:4f13)
-; entries correspond to POKEGEARSTATE_* constants
-	dw PokegearClock_Init
-	dw PokegearClock_Joypad
-	dw PokegearMap_CheckRegion
-	dw PokegearMap_Init
-	dw PokegearMap_JohtoMap
-	dw PokegearMap_Init
-	dw PokegearMap_KantoMap
-	dw PokegearPhone_Init
-	dw PokegearPhone_Joypad
-	dw PokegearPhone_MakePhoneCall
-	dw PokegearPhone_FinishPhoneCall
-	dw PokegearRadio_Init
-	dw PokegearRadio_Joypad
-
-PokegearClock_Init: ; 90f2d (24:4f2d)
-	call InitPokegearTilemap
-	ld hl, PokegearText_PressAnyButtonToExit
-	call PrintText
-	ld hl, wJumptableIndex
-	inc [hl]
-	call ExitPokegearRadio_HandleMusic
-	ret
-
-PokegearClock_Joypad: ; 90f3e (24:4f3e)
-	call .UpdateClock
-	ld hl, hJoyLast
-	ld a, [hl]
-	and A_BUTTON | B_BUTTON | START | SELECT
-	jr nz, .quit
-	ld a, [hl]
-	and D_RIGHT
-	ret z
-	ld a, [wPokegearFlags]
-	bit POKEGEAR_MAP_CARD_F, a
-	jr z, .no_map_card
-	ld c, POKEGEARSTATE_MAPCHECKREGION
-	ld b, POKEGEARCARD_MAP
-	jr .done
-
-.no_map_card
-	ld a, [wPokegearFlags]
-	bit POKEGEAR_PHONE_CARD_F, a
-	jr z, .no_phone_card
-	ld c, POKEGEARSTATE_PHONEINIT
-	ld b, POKEGEARCARD_PHONE
-	jr .done
-
-.no_phone_card
-	ld a, [wPokegearFlags]
-	bit POKEGEAR_RADIO_CARD_F, a
-	ret z
-	ld c, POKEGEARSTATE_RADIOINIT
-	ld b, POKEGEARCARD_RADIO
-.done
-	call Pokegear_SwitchPage
-	ret
-
-.quit
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-.UpdateClock: ; 90f7b (24:4f7b)
-	xor a
-	ld [hBGMapMode], a
-	call Pokegear_UpdateClock
-	ld a, $1
-	ld [hBGMapMode], a
-	ret
-
-Pokegear_UpdateClock: ; 90f86 (24:4f86)
-	hlcoord 3, 5
-	lb bc, 5, 14
-	call ClearBox
-	ld a, [hHours]
-	ld b, a
-	ld a, [hMinutes]
-	ld c, a
-	decoord 6, 8
-	farcall PrintHoursMins
-	ld hl, .DayText
-	bccoord 6, 6
-	call PlaceHLTextAtBC
-	ret
-
-; 90fa8 (24:4fa8)
-	db "ごぜん@"
-	db "ごご@"
-
-.DayText: ; 0x90faf
-	text_jump UnknownText_0x1c5821
-	db "@"
-
-; 0x90fb4
-
-PokegearMap_CheckRegion: ; 90fb4 (24:4fb4)
-	ld a, [wPokegearMapPlayerIconLandmark]
-	cp FAST_SHIP
-	jr z, .johto
-	cp KANTO_LANDMARK
-	jr nc, .kanto
-.johto
-	ld a, POKEGEARSTATE_JOHTOMAPINIT
-	jr .done
-	ret
-
-.kanto
-	ld a, POKEGEARSTATE_KANTOMAPINIT
-.done
-	ld [wJumptableIndex], a
-	call ExitPokegearRadio_HandleMusic
-	ret
-
-PokegearMap_Init: ; 90fcd (24:4fcd)
-	call InitPokegearTilemap
-	ld a, [wPokegearMapPlayerIconLandmark]
-	call PokegearMap_InitPlayerIcon
-	ld a, [wPokegearMapCursorLandmark]
-	call PokegearMap_InitCursor
-	ld a, c
-	ld [wPokegearMapCursorObjectPointer], a
-	ld a, b
-	ld [wPokegearMapCursorObjectPointer + 1], a
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-PokegearMap_KantoMap: ; 90fe9 (24:4fe9)
-	call TownMap_GetKantoLandmarkLimits
-	jr PokegearMap_ContinueMap
-
-PokegearMap_JohtoMap: ; 90fee (24:4fee)
-	ld d, SILVER_CAVE
-	ld e, NEW_BARK_TOWN
-PokegearMap_ContinueMap: ; 90ff2 (24:4ff2)
-	ld hl, hJoyLast
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .cancel
-	ld a, [hl]
-	and D_RIGHT
-	jr nz, .right
-	ld a, [hl]
-	and D_LEFT
-	jr nz, .left
-	call .DPad
-	ret
-
-.right
-	ld a, [wPokegearFlags]
-	bit POKEGEAR_PHONE_CARD_F, a
-	jr z, .no_phone
-	ld c, POKEGEARSTATE_PHONEINIT
-	ld b, POKEGEARCARD_PHONE
-	jr .done
-
-.no_phone
-	ld a, [wPokegearFlags]
-	bit POKEGEAR_RADIO_CARD_F, a
-	ret z
-	ld c, POKEGEARSTATE_RADIOINIT
-	ld b, POKEGEARCARD_RADIO
-	jr .done
-
-.left
-	ld c, POKEGEARSTATE_CLOCKINIT
-	ld b, POKEGEARCARD_CLOCK
-.done
-	call Pokegear_SwitchPage
-	ret
-
-.cancel
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-.DPad: ; 9102f (24:502f)
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_UP
-	jr nz, .up
-	ld a, [hl]
-	and D_DOWN
-	jr nz, .down
-	ret
-
-.up
-	ld hl, wPokegearMapCursorLandmark
-	ld a, [hl]
-	cp d
-	jr c, .wrap_around_up
-	ld a, e
-	dec a
-	ld [hl], a
-.wrap_around_up
-	inc [hl]
-	jr .done_dpad
-
-.down
-	ld hl, wPokegearMapCursorLandmark
-	ld a, [hl]
-	cp e
-	jr nz, .wrap_around_down
-	ld a, d
-	inc a
-	ld [hl], a
-.wrap_around_down
-	dec [hl]
-.done_dpad
-	ld a, [wPokegearMapCursorLandmark]
-	call PokegearMap_UpdateLandmarkName
-	ld a, [wPokegearMapCursorObjectPointer]
-	ld c, a
-	ld a, [wPokegearMapCursorObjectPointer + 1]
-	ld b, a
-	ld a, [wPokegearMapCursorLandmark]
-	call PokegearMap_UpdateCursorPosition
-	ret
-
-PokegearMap_InitPlayerIcon: ; 9106a
-	push af
-	depixel 0, 0
-	ld b, SPRITE_ANIM_INDEX_RED_WALK
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .got_gender
-	ld b, SPRITE_ANIM_INDEX_BLUE_WALK
-.got_gender
-	ld a, b
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_TILE_ID
-	add hl, bc
-	ld [hl], $10
-	pop af
-	ld e, a
-	push bc
-	farcall GetLandmarkCoords
-	pop bc
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld [hl], e
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	ld [hl], d
-	ret
-
-; 91098
-
-PokegearMap_InitCursor: ; 91098
-	push af
-	depixel 0, 0
-	ld a, SPRITE_ANIM_INDEX_POKEGEAR_ARROW
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_TILE_ID
-	add hl, bc
-	ld [hl], $04
-	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
-	add hl, bc
-	ld [hl], SPRITE_ANIM_SEQ_NULL
-	pop af
-	push bc
-	call PokegearMap_UpdateCursorPosition
-	pop bc
-	ret
-
-; 910b4
-
-PokegearMap_UpdateLandmarkName: ; 910b4
-	push af
-	hlcoord 8, 0
-	lb bc, 2, 12
-	call ClearBox
-	pop af
-	ld e, a
-	push de
-	farcall GetLandmarkName
-	pop de
-	farcall TownMap_ConvertLineBreakCharacters
-	hlcoord 8, 0
-	ld [hl], $34
-	ret
-
-; 910d4
-
-PokegearMap_UpdateCursorPosition: ; 910d4
-	push bc
-	ld e, a
-	farcall GetLandmarkCoords
-	pop bc
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld [hl], e
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	ld [hl], d
-	ret
-
-; 910e8
-
-TownMap_GetKantoLandmarkLimits: ; 910e8
-	ld a, [wStatusFlags]
-	bit STATUSFLAGS_HALL_OF_FAME_F, a
-	jr z, .not_hof
-	ld d, ROUTE_28
-	ld e, PALLET_TOWN
-	ret
-
-.not_hof
-	ld d, ROUTE_28
-	ld e, VICTORY_ROAD
-	ret
-
-; 910f9
-
-PokegearRadio_Init: ; 910f9 (24:50f9)
-	call InitPokegearTilemap
-	depixel 4, 10, 4, 4
-	ld a, SPRITE_ANIM_INDEX_RADIO_TUNING_KNOB
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_TILE_ID
-	add hl, bc
-	ld [hl], $08
-	call _UpdateRadioStation
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-PokegearRadio_Joypad: ; 91112 (24:5112)
-	ld hl, hJoyLast
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .cancel
-	ld a, [hl]
-	and D_LEFT
-	jr nz, .left
-	ld a, [wPokegearRadioChannelAddr]
-	ld l, a
-	ld a, [wPokegearRadioChannelAddr + 1]
-	ld h, a
-	ld a, [wPokegearRadioChannelBank]
-	and a
-	ret z
-	rst FarCall
-	ret
-
-.left
-	ld a, [wPokegearFlags]
-	bit POKEGEAR_PHONE_CARD_F, a
-	jr z, .no_phone
-	ld c, POKEGEARSTATE_PHONEINIT
-	ld b, POKEGEARCARD_PHONE
-	jr .switch_page
-
-.no_phone
-	ld a, [wPokegearFlags]
-	bit POKEGEAR_MAP_CARD_F, a
-	jr z, .no_map
-	ld c, POKEGEARSTATE_MAPCHECKREGION
-	ld b, POKEGEARCARD_MAP
-	jr .switch_page
-
-.no_map
-	ld c, POKEGEARSTATE_CLOCKINIT
-	ld b, POKEGEARCARD_CLOCK
-.switch_page
-	call Pokegear_SwitchPage
-	ret
-
-.cancel
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-PokegearPhone_Init: ; 91156 (24:5156)
-	ld hl, wJumptableIndex
-	inc [hl]
-	xor a
-	ld [wPokegearPhoneScrollPosition], a
-	ld [wPokegearPhoneCursorPosition], a
-	ld [wPokegearPhoneSelectedPerson], a
-	call InitPokegearTilemap
-	call ExitPokegearRadio_HandleMusic
-	ld hl, PokegearText_WhomToCall
-	call PrintText
-	ret
-
-PokegearPhone_Joypad: ; 91171 (24:5171)
-	ld hl, hJoyPressed
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .b
-	ld a, [hl]
-	and A_BUTTON
-	jr nz, .a
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_LEFT
-	jr nz, .left
-	ld a, [hl]
-	and D_RIGHT
-	jr nz, .right
-	call PokegearPhone_GetDPad
-	ret
-
-.left
-	ld a, [wPokegearFlags]
-	bit POKEGEAR_MAP_CARD_F, a
-	jr z, .no_map
-	ld c, POKEGEARSTATE_MAPCHECKREGION
-	ld b, POKEGEARCARD_MAP
-	jr .switch_page
-
-.no_map
-	ld c, POKEGEARSTATE_CLOCKINIT
-	ld b, POKEGEARCARD_CLOCK
-	jr .switch_page
-
-.right
-	ld a, [wPokegearFlags]
-	bit POKEGEAR_RADIO_CARD_F, a
-	ret z
-	ld c, POKEGEARSTATE_RADIOINIT
-	ld b, POKEGEARCARD_RADIO
-.switch_page
-	call Pokegear_SwitchPage
-	ret
-
-.b
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-.a
-	ld hl, wPhoneList
-	ld a, [wPokegearPhoneScrollPosition]
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld a, [wPokegearPhoneCursorPosition]
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld a, [hl]
-	and a
-	ret z
-	ld [wPokegearPhoneSelectedPerson], a
-	hlcoord 1, 4
-	ld a, [wPokegearPhoneCursorPosition]
-	ld bc, 20 * 2
-	call AddNTimes
-	ld [hl], "▷"
-	call PokegearPhoneContactSubmenu
-	jr c, .quit_submenu
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-.quit_submenu
-	ld a, POKEGEARSTATE_PHONEJOYPAD
-	ld [wJumptableIndex], a
-	ret
-
-PokegearPhone_MakePhoneCall: ; 911eb (24:51eb)
-	call GetMapPhoneService
-	and a
-	jr nz, .no_service
-	ld hl, wOptions
-	res NO_TEXT_SCROLL, [hl]
-	xor a
-	ld [hInMenu], a
-	ld de, SFX_CALL
-	call PlaySFX
-	ld hl, .dotdotdot
-	call PrintText
-	call WaitSFX
-	ld de, SFX_CALL
-	call PlaySFX
-	ld hl, .dotdotdot
-	call PrintText
-	call WaitSFX
-	ld a, [wPokegearPhoneSelectedPerson]
-	ld b, a
-	call Function90199
-	ld c, 10
-	call DelayFrames
-	ld hl, wOptions
-	set NO_TEXT_SCROLL, [hl]
-	ld a, $1
-	ld [hInMenu], a
-	call PokegearPhone_UpdateCursor
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-.no_service
-	farcall Phone_NoSignal
-	ld hl, .OutOfServiceArea
-	call PrintText
-	ld a, POKEGEARSTATE_PHONEJOYPAD
-	ld [wJumptableIndex], a
-	ld hl, PokegearText_WhomToCall
-	call PrintText
-	ret
-
-; 9124c (24:524c)
-
-.dotdotdot ; 0x9124c
-	;
-	text_jump UnknownText_0x1c5824
-	db "@"
-
-; 0x91251
-
-.OutOfServiceArea: ; 0x91251
-	; You're out of the service area.
-	text_jump UnknownText_0x1c5827
-	db "@"
-
-; 0x91256
-
-PokegearPhone_FinishPhoneCall: ; 91256 (24:5256)
-	ld a, [hJoyPressed]
-	and A_BUTTON | B_BUTTON
-	ret z
-	farcall HangUp
-	ld a, POKEGEARSTATE_PHONEJOYPAD
-	ld [wJumptableIndex], a
-	ld hl, PokegearText_WhomToCall
-	call PrintText
-	ret
-
-PokegearPhone_GetDPad: ; 9126d (24:526d)
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_UP
-	jr nz, .up
-	ld a, [hl]
-	and D_DOWN
-	jr nz, .down
-	ret
-
-.up
-	ld hl, wPokegearPhoneCursorPosition
-	ld a, [hl]
-	and a
-	jr z, .scroll_page_up
-	dec [hl]
-	jr .done_joypad_same_page
-
-.scroll_page_up
-	ld hl, wPokegearPhoneScrollPosition
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-	jr .done_joypad_update_page
-
-.down
-	ld hl, wPokegearPhoneCursorPosition
-	ld a, [hl]
-	cp 3
-	jr nc, .scroll_page_down
-	inc [hl]
-	jr .done_joypad_same_page
-
-.scroll_page_down
-	ld hl, wPokegearPhoneScrollPosition
-	ld a, [hl]
-	cp 6
-	ret nc
-	inc [hl]
-	jr .done_joypad_update_page
-
-.done_joypad_same_page
-	xor a
-	ld [hBGMapMode], a
-	call PokegearPhone_UpdateCursor
-	call WaitBGMap
-	ret
-
-.done_joypad_update_page
-	xor a
-	ld [hBGMapMode], a
-	call PokegearPhone_UpdateDisplayList
-	call WaitBGMap
-	ret
-
-PokegearPhone_UpdateCursor: ; 912b7 (24:52b7)
-	ld a, " "
-	hlcoord 1, 4
-	ld [hl], a
-	hlcoord 1, 6
-	ld [hl], a
-	hlcoord 1, 8
-	ld [hl], a
-	hlcoord 1, 10
-	ld [hl], a
-	hlcoord 1, 4
-	ld a, [wPokegearPhoneCursorPosition]
-	ld bc, 2 * SCREEN_WIDTH
-	call AddNTimes
-	ld [hl], "▶"
-	ret
-
-PokegearPhone_UpdateDisplayList: ; 912d8 (24:52d8)
-	hlcoord 1, 3
-	ld b, 9
-	ld a, " "
-.row
-	ld c, 18
-.col
-	ld [hli], a
-	dec c
-	jr nz, .col
-	inc hl
-	inc hl
-	dec b
-	jr nz, .row
-	ld a, [wPokegearPhoneScrollPosition]
-	ld e, a
-	ld d, $0
-	ld hl, wPhoneList
-	add hl, de
-	xor a
-	ld [wPokegearPhoneLoadNameBuffer], a
-.loop
-	ld a, [hli]
-	push hl
-	push af
-	hlcoord 2, 4
-	ld a, [wPokegearPhoneLoadNameBuffer]
-	ld bc, 2 * SCREEN_WIDTH
-	call AddNTimes
-	ld d, h
-	ld e, l
-	pop af
-	ld b, a
-	call Function90380
-	pop hl
-	ld a, [wPokegearPhoneLoadNameBuffer]
-	inc a
-	ld [wPokegearPhoneLoadNameBuffer], a
-	cp 4
-	jr c, .loop
-	call PokegearPhone_UpdateCursor
-	ret
-
-; 9131e (24:531e)
-
-PokegearPhone_DeletePhoneNumber: ; 9131e
-	ld hl, wPhoneList
-	ld a, [wPokegearPhoneScrollPosition]
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld a, [wPokegearPhoneCursorPosition]
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld [hl], 0
-	ld hl, wPhoneList
-	ld c, CONTACT_LIST_SIZE
-.loop
-	ld a, [hli]
-	and a
-	jr nz, .skip
-	ld a, [hld]
-	ld [hli], a
-	ld [hl], 0
-.skip
-	dec c
-	jr nz, .loop
-	ret
-
-; 91342
-
-PokegearPhoneContactSubmenu: ; 91342 (24:5342)
-	ld hl, wPhoneList
-	ld a, [wPokegearPhoneScrollPosition]
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld a, [wPokegearPhoneCursorPosition]
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld c, [hl]
-	farcall CheckCanDeletePhoneNumber
-	ld a, c
-	and a
-	jr z, .cant_delete
-	ld hl, .CallDeleteCancelJumptable
-	ld de, .CallDeleteCancelStrings
-	jr .got_menu_data
-
-.cant_delete
-	ld hl, .CallCancelJumptable
-	ld de, .CallCancelStrings
-.got_menu_data
-	xor a
-	ld [hBGMapMode], a
-	push hl
-	push de
-	ld a, [de]
-	ld l, a
-	inc de
-	ld a, [de]
-	ld h, a
-	inc de
-	push hl
-	ld bc, hBGMapAddress + 1
-	add hl, bc
-	ld a, [de]
-	inc de
-	sla a
-	ld b, a
-	ld c, 8
-	push de
-	call TextBox
-	pop de
-	pop hl
-	inc hl
-	call PlaceString
-	pop de
-	xor a
-	ld [wPokegearPhoneSubmenuCursor], a
-	call .UpdateCursor
-	call WaitBGMap
-.loop
-	push de
-	call JoyTextDelay
-	pop de
-	ld hl, hJoyPressed
-	ld a, [hl]
-	and D_UP
-	jr nz, .d_up
-	ld a, [hl]
-	and D_DOWN
-	jr nz, .d_down
-	ld a, [hl]
-	and A_BUTTON | B_BUTTON
-	jr nz, .a_b
-	call DelayFrame
-	jr .loop
-
-.d_up
-	ld hl, wPokegearPhoneSubmenuCursor
-	ld a, [hl]
-	and a
-	jr z, .loop
-	dec [hl]
-	call .UpdateCursor
-	jr .loop
-
-.d_down
-	ld hl, 2
-	add hl, de
-	ld a, [wPokegearPhoneSubmenuCursor]
-	inc a
-	cp [hl]
-	jr nc, .loop
-	ld [wPokegearPhoneSubmenuCursor], a
-	call .UpdateCursor
-	jr .loop
-
-.a_b
-	xor a
-	ld [hBGMapMode], a
-	call PokegearPhone_UpdateDisplayList
-	ld a, $1
-	ld [hBGMapMode], a
-	pop hl
-	ld a, [hJoyPressed]
-	and B_BUTTON
-	jr nz, .Cancel
-	ld a, [wPokegearPhoneSubmenuCursor]
-	ld e, a
-	ld d, 0
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-.Cancel: ; 913f1
-	ld hl, PokegearText_WhomToCall
-	call PrintText
-	scf
-	ret
-
-; 913f9 (24:53f9)
-
-.Delete: ; 913f9
-	ld hl, PokegearText_DeleteStoredNumber
-	call MenuTextBox
-	call YesNoBox
-	call ExitMenu
-	jr c, .CancelDelete
-	call PokegearPhone_DeletePhoneNumber
-	xor a
-	ld [hBGMapMode], a
-	call PokegearPhone_UpdateDisplayList
-	ld hl, PokegearText_WhomToCall
-	call PrintText
-	call WaitBGMap
-.CancelDelete:
-	scf
-	ret
-
-; 9141b
-
-.Call: ; 9141b
-	and a
-	ret
-
-; 9141d
-
-.UpdateCursor: ; 9141d (24:541d)
-	push de
-	ld a, [de]
-	inc de
-	ld l, a
-	ld a, [de]
-	inc de
-	ld h, a
-	ld a, [de]
-	ld c, a
-	push hl
-	ld a, " "
-	ld de, SCREEN_WIDTH * 2
-.clear_column
-	ld [hl], a
-	add hl, de
-	dec c
-	jr nz, .clear_column
-	pop hl
-	ld a, [wPokegearPhoneSubmenuCursor]
-	ld bc, SCREEN_WIDTH  * 2
-	call AddNTimes
-	ld [hl], "▶"
-	pop de
-	ret
-
-; 9143f (24:543f)
-
-.CallDeleteCancelStrings: ; 9143f
-	dwcoord 10, 6
-	db 3
-	db   "CALL"
-	next "DELETE"
-	next "CANCEL"
-	db   "@"
-; 91455
-
-.CallDeleteCancelJumptable: ; 91455
-	dw .Call
-	dw .Delete
-	dw .Cancel
-
-; 9145b
-
-.CallCancelStrings: ; 9145b
-	dwcoord 10, 8
-	db 2
-	db   "CALL"
-	next "CANCEL"
-	db   "@"
-; 9146a
-
-.CallCancelJumptable: ; 9146a
-	dw .Call
-	dw .Cancel
-
-; 9146e
-
-; unused
-	ld a, [hHours]
-	cp 12
-	jr c, .am
-	sub 12
-	ld [wd265], a
-	scf
-	ret
-
-.am
-	ld [wd265], a
-	and a
-	ret
-
-; 91480
-
-Pokegear_SwitchPage: ; 91480 (24:5480)
-	ld de, SFX_READ_TEXT_2
-	call PlaySFX
-	ld a, c
-	ld [wJumptableIndex], a
-	ld a, b
-	ld [wPokegearCard], a
-	call DeleteSpriteAnimStruct2ToEnd
-	ret
-
-ExitPokegearRadio_HandleMusic: ; 91492
-	ld a, [wPokegearRadioMusicPlaying]
-	cp RESTART_MAP_MUSIC
-	jr z, .restart_map_music
-	cp ENTER_MAP_MUSIC
-	call z, EnterMapMusic
-	xor a
-	ld [wPokegearRadioMusicPlaying], a
-	ret
-
-.restart_map_music
-	call RestartMapMusic
-	xor a
-	ld [wPokegearRadioMusicPlaying], a
-	ret
-
-; 914ab
-
-DeleteSpriteAnimStruct2ToEnd: ; 914ab (24:54ab)
-	ld hl, wSpriteAnim2
-	ld bc, wSpriteAnimationStructsEnd - wSpriteAnim2
-	xor a
-	call ByteFill
-	ld a, 2
-	ld [wSpriteAnimCount], a
-	ret
-
-Pokegear_LoadTilemapRLE: ; 914bb (24:54bb)
-	; Format: repeat count, tile ID
-	; Terminated with -1
-	hlcoord 0, 0
-.loop
-	ld a, [de]
-	cp -1
-	ret z
-	ld b, a
-	inc de
-	ld a, [de]
-	ld c, a
-	inc de
-	ld a, b
-.load
-	ld [hli], a
-	dec c
-	jr nz, .load
-	jr .loop
-
-; 914ce (24:54ce)
-
-PokegearText_WhomToCall: ; 0x914ce
-	; Whom do you want to call?
-	text_jump UnknownText_0x1c5847
-	db "@"
-
-; 0x914d3
-
-PokegearText_PressAnyButtonToExit: ; 0x914d3
-	; Press any button to exit.
-	text_jump UnknownText_0x1c5862
-	db "@"
-
-; 0x914d8
-
-PokegearText_DeleteStoredNumber: ; 0x914d8
-	; Delete this stored phone number?
-	text_jump UnknownText_0x1c587d
-	db "@"
-
-; 0x914dd
-
-PokegearSpritesGFX: ; 914dd
-INCBIN "gfx/pokegear/pokegear_sprites.2bpp.lz"
-; 9150d
-
-RadioTilemapRLE: ; 9150d
-INCBIN "gfx/pokegear/radio.tilemap.rle"
-PhoneTilemapRLE: ; 9158a
-INCBIN "gfx/pokegear/phone.tilemap.rle"
-ClockTilemapRLE: ; 915db
-INCBIN "gfx/pokegear/clock.tilemap.rle"
-; 9163e
-
-_UpdateRadioStation: ; 9163e (24:563e)
-	jr UpdateRadioStation
-
-; called from engine/sprite_anims.asm
-
-AnimateTuningKnob: ; 91640 (24:5640)
-	push bc
-	call .TuningKnob
-	pop bc
-	ld a, [wRadioTuningKnob]
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.TuningKnob: ; 9164e (24:564e)
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, .down
-	ld a, [hl]
-	and D_UP
-	jr nz, .up
-	ret
-
-.down
-	ld hl, wRadioTuningKnob
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-	dec [hl]
-	jr .update
-
-.up
-	ld hl, wRadioTuningKnob
-	ld a, [hl]
-	cp 80
-	ret nc
-	inc [hl]
-	inc [hl]
-.update
-UpdateRadioStation: ; 9166f (24:566f)
-	ld hl, wRadioTuningKnob
-	ld d, [hl]
-	ld hl, RadioChannels
-.loop
-	ld a, [hli]
-	cp -1
-	jr z, .nostation
-	cp d
-	jr z, .foundstation
-	inc hl
-	inc hl
-	jr .loop
-
-.nostation
-	call NoRadioStation
-	ret
-
-.foundstation
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, .returnafterstation
-	push de
-	jp hl
-
-.returnafterstation
-	ld a, [wPokegearRadioChannelBank]
-	and a
-	ret z
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 2, 9
-	call PlaceString
-	ld a, $1
-	ld [hBGMapMode], a
-	ret
-
-; 916a1 (24:56a1)
-
-; unused
-	ld [wPokegearRadioChannelBank], a
-	ld a, [hli]
-	ld [wPokegearRadioChannelAddr], a
-	ld a, [hli]
-	ld [wPokegearRadioChannelAddr + 1], a
-	ret
-
-; 916ad
-
-RadioChannels:
-; entries correspond to constants/radio_constants.asm
-
-; frequency value given here = 4 × ingame_frequency − 2
-	dbw 16, .PKMNTalkAndPokedexShow
-	dbw 28, .PokemonMusic
-	dbw 32, .LuckyChannel
-	dbw 40, .BuenasPassword
-	dbw 52, .RuinsOfAlphRadio
-	dbw 64, .PlacesAndPeople
-	dbw 72, .LetsAllSing
-	dbw 78, .PokeFluteRadio
-	dbw 80, .EvolutionRadio
-	db -1
-
-.PKMNTalkAndPokedexShow:
-; Pokédex Show in the morning
-
-; Oak's Pokémon Talk in the afternoon and evening
-	call .InJohto
-	jr nc, .NoSignal
-	ld a, [wTimeOfDay]
-	and a
-	jp z, LoadStation_PokedexShow
-	jp LoadStation_OaksPokemonTalk
-
-.PokemonMusic:
-	call .InJohto
-	jr nc, .NoSignal
-	jp LoadStation_PokemonMusic
-
-.LuckyChannel:
-	call .InJohto
-	jr nc, .NoSignal
-	jp LoadStation_LuckyChannel
-
-.BuenasPassword:
-	call .InJohto
-	jr nc, .NoSignal
-	jp LoadStation_BuenasPassword
-
-.RuinsOfAlphRadio:
-	ld a, [wPokegearMapPlayerIconLandmark]
-	cp RUINS_OF_ALPH
-	jr nz, .NoSignal
-	jp LoadStation_UnownRadio
-
-.PlacesAndPeople:
-	call .InJohto
-	jr c, .NoSignal
-	ld a, [wPokegearFlags]
-	bit POKEGEAR_EXPN_CARD_F, a
-	jr z, .NoSignal
-	jp LoadStation_PlacesAndPeople
-
-.LetsAllSing:
-	call .InJohto
-	jr c, .NoSignal
-	ld a, [wPokegearFlags]
-	bit POKEGEAR_EXPN_CARD_F, a
-	jr z, .NoSignal
-	jp LoadStation_LetsAllSing
-
-.PokeFluteRadio:
-	call .InJohto
-	jr c, .NoSignal
-	ld a, [wPokegearFlags]
-	bit POKEGEAR_EXPN_CARD_F, a
-	jr z, .NoSignal
-	jp LoadStation_PokeFluteRadio
-
-.EvolutionRadio:
-; This station airs in the Lake of Rage area when Rocket are still in Mahogany.
-	ld a, [wStatusFlags]
-	bit STATUSFLAGS_ROCKET_SIGNAL_F, a
-	jr z, .NoSignal
-	ld a, [wPokegearMapPlayerIconLandmark]
-	cp MAHOGANY_TOWN
-	jr z, .ok
-	cp ROUTE_43
-	jr z, .ok
-	cp LAKE_OF_RAGE
-	jr nz, .NoSignal
-.ok
-	jp LoadStation_EvolutionRadio
-
-.NoSignal:
-	call NoRadioStation
-	ret
-
-.InJohto:
-; if in Johto or on the S.S. Aqua, set carry
-
-; otherwise clear carry
-	ld a, [wPokegearMapPlayerIconLandmark]
-	cp FAST_SHIP
-	jr z, .johto
-	cp KANTO_LANDMARK
-	jr c, .johto
-.kanto
-	and a
-	ret
-
-.johto
-	scf
-	ret
-
-LoadStation_OaksPokemonTalk: ; 91753 (24:5753)
-	xor a ; OAKS_POKEMON_TALK
-	ld [wCurrentRadioLine], a
-	ld [wNumRadioLinesPrinted], a
-	ld a, BANK(PlayRadioShow)
-	ld hl, PlayRadioShow
-	call Radio_BackUpFarCallParams
-	ld de, OaksPKMNTalkName
-	ret
-
-LoadStation_PokedexShow: ; 91766 (24:5766)
-	ld a, POKEDEX_SHOW
-	ld [wCurrentRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	ld a, BANK(PlayRadioShow)
-	ld hl, PlayRadioShow
-	call Radio_BackUpFarCallParams
-	ld de, PokedexShowName
-	ret
-
-LoadStation_PokemonMusic: ; 9177b (24:577b)
-	ld a, POKEMON_MUSIC
-	ld [wCurrentRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	ld a, BANK(PlayRadioShow)
-	ld hl, PlayRadioShow
-	call Radio_BackUpFarCallParams
-	ld de, PokemonMusicName
-	ret
-
-LoadStation_LuckyChannel: ; 91790 (24:5790)
-	ld a, LUCKY_CHANNEL
-	ld [wCurrentRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	ld a, BANK(PlayRadioShow)
-	ld hl, PlayRadioShow
-	call Radio_BackUpFarCallParams
-	ld de, LuckyChannelName
-	ret
-
-LoadStation_BuenasPassword: ; 917a5 (24:57a5)
-	ld a, BUENAS_PASSWORD
-	ld [wCurrentRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	ld a, BANK(PlayRadioShow)
-	ld hl, PlayRadioShow
-	call Radio_BackUpFarCallParams
-	ld de, NotBuenasPasswordName
-	ld a, [wStatusFlags2]
-	bit STATUSFLAGS2_ROCKETS_IN_RADIO_TOWER_F, a
-	ret z
-	ld de, BuenasPasswordName
-	ret
-
-; 917c3 (24:57c3)
-
-BuenasPasswordName:    db "BUENA'S PASSWORD@"
-NotBuenasPasswordName: db "@"
-
-LoadStation_UnownRadio: ; 917d5 (24:57d5)
-	ld a, UNOWN_RADIO
-	ld [wCurrentRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	ld a, BANK(PlayRadioShow)
-	ld hl, PlayRadioShow
-	call Radio_BackUpFarCallParams
-	ld de, UnownStationName
-	ret
-
-LoadStation_PlacesAndPeople: ; 917ea (24:57ea)
-	ld a, PLACES_AND_PEOPLE
-	ld [wCurrentRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	ld a, BANK(PlayRadioShow)
-	ld hl, PlayRadioShow
-	call Radio_BackUpFarCallParams
-	ld de, PlacesAndPeopleName
-	ret
-
-LoadStation_LetsAllSing: ; 917ff (24:57ff)
-	ld a, LETS_ALL_SING
-	ld [wCurrentRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	ld a, BANK(PlayRadioShow)
-	ld hl, PlayRadioShow
-	call Radio_BackUpFarCallParams
-	ld de, LetsAllSingName
-	ret
-
-; 91814 (24:5814)
-
-LoadStation_RocketRadio: ; 91814
-	ld a, ROCKET_RADIO
-	ld [wCurrentRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	ld a, BANK(PlayRadioShow)
-	ld hl, PlayRadioShow
-	call Radio_BackUpFarCallParams
-	ld de, LetsAllSingName
-	ret
-
-; 91829
-
-LoadStation_PokeFluteRadio: ; 91829 (24:5829)
-	ld a, POKE_FLUTE_RADIO
-	ld [wCurrentRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	ld a, BANK(PlayRadioShow)
-	ld hl, PlayRadioShow
-	call Radio_BackUpFarCallParams
-	ld de, PokeFluteStationName
-	ret
-
-LoadStation_EvolutionRadio: ; 9183e (24:583e)
-	ld a, EVOLUTION_RADIO
-	ld [wCurrentRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	ld a, BANK(PlayRadioShow)
-	ld hl, PlayRadioShow
-	call Radio_BackUpFarCallParams
-	ld de, UnownStationName
-	ret
-
-; 91853 (24:5853)
-
-Unreferenced_LoadStation: ; 91853
-	ret
-
-RadioMusicRestartDE: ; 91854 (24:5854)
-	push de
-	ld a, e
-	ld [wPokegearRadioMusicPlaying], a
-	ld de, MUSIC_NONE
-	call PlayMusic
-	pop de
-	ld a, e
-	ld [wMapMusic], a
-	call PlayMusic
-	ret
-
-RadioMusicRestartPokemonChannel: ; 91868 (24:5868)
-	push de
-	ld a, RESTART_MAP_MUSIC
-	ld [wPokegearRadioMusicPlaying], a
-	ld de, MUSIC_NONE
-	call PlayMusic
-	pop de
-	ld de, MUSIC_POKEMON_CHANNEL
-	call PlayMusic
-	ret
-
-Radio_BackUpFarCallParams: ; 9187c (24:587c)
-	ld [wPokegearRadioChannelBank], a
-	ld a, l
-	ld [wPokegearRadioChannelAddr], a
-	ld a, h
-	ld [wPokegearRadioChannelAddr + 1], a
-	ret
-
-NoRadioStation: ; 91888 (24:5888)
-	call NoRadioMusic
-	call NoRadioName
-	xor a
-	ld [wPokegearRadioChannelBank], a
-	ld [wPokegearRadioChannelAddr], a
-	ld [wPokegearRadioChannelAddr + 1], a
-	ld a, $1
-	ld [hBGMapMode], a
-	ret
-
-NoRadioMusic: ; 9189d (24:589d)
-	ld de, MUSIC_NONE
-	call PlayMusic
-	ld a, ENTER_MAP_MUSIC
-	ld [wPokegearRadioMusicPlaying], a
-	ret
-
-NoRadioName: ; 918a9 (24:58a9)
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 1, 8
-	lb bc, 3, 18
-	call ClearBox
-	hlcoord 0, 12
-	lb bc, 4, 18
-	call TextBox
-	ret
-
-; 918bf
-
-OaksPKMNTalkName:     db "OAK's <PK><MN> Talk@"
-PokedexShowName:      db "#DEX Show@"
-PokemonMusicName:     db "#MON Music@"
-LuckyChannelName:     db "Lucky Channel@"
-UnownStationName:     db "?????@"
-
-PlacesAndPeopleName:  db "Places & People@"
-LetsAllSingName:      db "Let's All Sing!@"
-PokeFluteStationName: db "# FLUTE@"
-; 9191c
-
-_TownMap: ; 9191c
-	ld hl, wOptions
-	ld a, [hl]
-	push af
-	set NO_TEXT_SCROLL, [hl]
-
-	ld a, [hInMenu]
-	push af
-	ld a, $1
-	ld [hInMenu], a
-
-	ld a, [wVramState]
-	push af
-	xor a
-	ld [wVramState], a
-
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	call DisableLCD
-	call Pokegear_LoadGFX
-	farcall ClearSpriteAnims
-	ld a, 8
-	call SkipMusic
-	ld a, LCDC_DEFAULT
-	ld [rLCDC], a
-	call TownMap_GetCurrentLandmark
-	ld [wTownMapPlayerIconLandmark], a
-	ld [wTownMapCursorLandmark], a
-	xor a
-	ld [hBGMapMode], a
-	call .InitTilemap
-	call WaitBGMap2
-	ld a, [wTownMapPlayerIconLandmark]
-	call PokegearMap_InitPlayerIcon
-	ld a, [wTownMapCursorLandmark]
-	call PokegearMap_InitCursor
-	ld a, c
-	ld [wTownMapCursorObjectPointer], a
-	ld a, b
-	ld [wTownMapCursorObjectPointer + 1], a
-	ld b, SCGB_POKEGEAR_PALS
-	call GetSGBLayout
-	call SetPalettes
-	ld a, [hCGB]
-	and a
-	jr z, .dmg
-	ld a, %11100100
-	call DmgToCgbObjPal0
-	call DelayFrame
-
-.dmg
-	ld a, [wTownMapPlayerIconLandmark]
-	cp KANTO_LANDMARK
-	jr nc, .kanto
-	ld d, KANTO_LANDMARK - 1
-	ld e, 1
-	call .loop
-	jr .resume
-
-.kanto
-	call TownMap_GetKantoLandmarkLimits
-	call .loop
-
-.resume
-	pop af
-	ld [wVramState], a
-	pop af
-	ld [hInMenu], a
-	pop af
-	ld [wOptions], a
-	call ClearBGPalettes
-	ret
-
-.loop
-	call JoyTextDelay
-	ld hl, hJoyPressed
-	ld a, [hl]
-	and B_BUTTON
-	ret nz
-
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_UP
-	jr nz, .pressed_up
-
-	ld a, [hl]
-	and D_DOWN
-	jr nz, .pressed_down
-.loop2
-	push de
-	farcall PlaySpriteAnimations
-	pop de
-	call DelayFrame
-	jr .loop
-
-.pressed_up
-	ld hl, wTownMapCursorLandmark
-	ld a, [hl]
-	cp d
-	jr c, .okay
-	ld a, e
-	dec a
-	ld [hl], a
-
-.okay
-	inc [hl]
-	jr .next
-
-.pressed_down
-	ld hl, wTownMapCursorLandmark
-	ld a, [hl]
-	cp e
-	jr nz, .okay2
-	ld a, d
-	inc a
-	ld [hl], a
-
-.okay2
-	dec [hl]
-
-.next
-	push de
-	ld a, [wTownMapCursorLandmark]
-	call PokegearMap_UpdateLandmarkName
-	ld a, [wTownMapCursorObjectPointer]
-	ld c, a
-	ld a, [wTownMapCursorObjectPointer + 1]
-	ld b, a
-	ld a, [wTownMapCursorLandmark]
-	call PokegearMap_UpdateCursorPosition
-	pop de
-	jr .loop2
-; 91a04
-
-.InitTilemap: ; 91a04
-	ld a, [wTownMapPlayerIconLandmark]
-	cp KANTO_LANDMARK
-	jr nc, .kanto2
-	ld e, JOHTO_REGION
-	jr .okay_tilemap
-
-.kanto2
-	ld e, KANTO_REGION
-.okay_tilemap
-	farcall PokegearMap
-	ld a, $07
-	ld bc, 6
-	hlcoord 1, 0
-	call ByteFill
-	hlcoord 0, 0
-	ld [hl], $06
-	hlcoord 7, 0
-	ld [hl], $17
-	hlcoord 7, 1
-	ld [hl], $16
-	hlcoord 7, 2
-	ld [hl], $26
-	ld a, $07
-	ld bc, NAME_LENGTH
-	hlcoord 8, 2
-	call ByteFill
-	hlcoord 19, 2
-	ld [hl], $17
-	ld a, [wTownMapCursorLandmark]
-	call PokegearMap_UpdateLandmarkName
-	farcall TownMapPals
-	ret
-; 91a53
-
-PlayRadio: ; 91a53
-	ld hl, wOptions
-	ld a, [hl]
-	push af
-	set NO_TEXT_SCROLL, [hl]
-	call .PlayStation
-	ld c, 100
-	call DelayFrames
-.loop
-	call JoyTextDelay
-	ld a, [hJoyPressed]
-	and A_BUTTON | B_BUTTON
-	jr nz, .stop
-	ld a, [wPokegearRadioChannelAddr]
-	ld l, a
-	ld a, [wPokegearRadioChannelAddr + 1]
-	ld h, a
-	ld a, [wPokegearRadioChannelBank]
-	and a
-	jr z, .zero
-	rst FarCall
-.zero
-	call DelayFrame
-	jr .loop
-
-.stop
-	pop af
-	ld [wOptions], a
-	call ExitPokegearRadio_HandleMusic
-	ret
-
-; 91a87
-
-.PlayStation: ; 91a87
-	ld a, ENTER_MAP_MUSIC
-	ld [wPokegearRadioMusicPlaying], a
-	ld hl, .StationPointers
-	ld d, 0
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, .jump_return
-	push de
-	jp hl
-
-.jump_return
-	push de
-	hlcoord 0, 12
-	lb bc, 4, 18
-	call TextBox
-	hlcoord 1, 14
-	ld [hl], $72
-	pop de
-	hlcoord 2, 14
-	call PlaceString
-	ld h, b
-	ld l, c
-	ld [hl], $73
-	call WaitBGMap
-	ret
-
-; 91ab9
-
-.StationPointers: ; 91ab9
-; entries correspond to MAPRADIO_* constants
-	dw .OakOrPnP
-	dw LoadStation_OaksPokemonTalk
-	dw LoadStation_PokedexShow
-	dw LoadStation_PokemonMusic
-	dw LoadStation_LuckyChannel
-	dw LoadStation_UnownRadio
-	dw LoadStation_PlacesAndPeople
-	dw LoadStation_LetsAllSing
-	dw LoadStation_RocketRadio
-
-; 91acb
-
-.OakOrPnP: ; 91acb
-	call IsInJohto
-	and a
-	jr nz, .kanto
-	call UpdateTime
-	ld a, [wTimeOfDay]
-	and a
-	jp z, LoadStation_PokedexShow
-	jp LoadStation_OaksPokemonTalk
-
-.kanto
-	jp LoadStation_PlacesAndPeople
-
-; 91ae1
-
-PokegearMap: ; 91ae1
-	ld a, e
-	and a
-	jr nz, .kanto
-	call LoadTownMapGFX
-	call FillJohtoMap
-	ret
-
-.kanto
-	call LoadTownMapGFX
-	call FillKantoMap
-	ret
-
-; 91af3
-
-_FlyMap: ; 91af3
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	ld hl, hInMenu
-	ld a, [hl]
-	push af
-	ld [hl], $1
-	xor a
-	ld [hBGMapMode], a
-	farcall ClearSpriteAnims
-	call LoadTownMapGFX
-	ld de, FlyMapLabelBorderGFX
-	ld hl, vTiles2 tile $30
-	lb bc, BANK(FlyMapLabelBorderGFX), 6
-	call Request1bpp
-	call FlyMap
-	call ret_91c8f
-	ld b, SCGB_POKEGEAR_PALS
-	call GetSGBLayout
-	call SetPalettes
-.loop
-	call JoyTextDelay
-	ld hl, hJoyPressed
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .pressedB
-	ld a, [hl]
-	and A_BUTTON
-	jr nz, .pressedA
-	call FlyMapScroll
-	call GetMapCursorCoordinates
-	farcall PlaySpriteAnimations
-	call DelayFrame
-	jr .loop
-
-.pressedB
-	ld a, -1
-	jr .exit
-
-.pressedA
-	ld a, [wTownMapPlayerIconLandmark]
-	ld l, a
-	ld h, 0
-	add hl, hl
-	ld de, Flypoints + 1
-	add hl, de
-	ld a, [hl]
-.exit
-	ld [wTownMapPlayerIconLandmark], a
-	pop af
-	ld [hInMenu], a
-	call ClearBGPalettes
-	ld a, $90
-	ld [hWY], a
-	xor a ; LOW(vBGMap0)
-	ld [hBGMapAddress], a
-	ld a, HIGH(vBGMap0)
-	ld [hBGMapAddress + 1], a
-	ld a, [wTownMapPlayerIconLandmark]
-	ld e, a
-	ret
-
-; 91b73
-
-FlyMapScroll: ; 91b73
-	ld a, [wStartFlypoint]
-	ld e, a
-	ld a, [wEndFlypoint]
-	ld d, a
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_UP
-	jr nz, .ScrollNext
-	ld a, [hl]
-	and D_DOWN
-	jr nz, .ScrollPrev
-	ret
-
-.ScrollNext:
-	ld hl, wTownMapPlayerIconLandmark
-	ld a, [hl]
-	cp d
-	jr nz, .NotAtEndYet
-	ld a, e
-	dec a
-	ld [hl], a
-.NotAtEndYet:
-	inc [hl]
-	call CheckIfVisitedFlypoint
-	jr z, .ScrollNext
-	jr .Finally
-
-.ScrollPrev:
-	ld hl, wTownMapPlayerIconLandmark
-	ld a, [hl]
-	cp e
-	jr nz, .NotAtStartYet
-	ld a, d
-	inc a
-	ld [hl], a
-.NotAtStartYet:
-	dec [hl]
-	call CheckIfVisitedFlypoint
-	jr z, .ScrollPrev
-.Finally:
-	call TownMapBubble
-	call WaitBGMap
-	xor a
-	ld [hBGMapMode], a
-	ret
-
-; 91bb5
-
-TownMapBubble: ; 91bb5
-; Draw the bubble containing the location text in the town map HUD
-
-; Top-left corner
-	hlcoord 1, 0
-	ld a, $30
-	ld [hli], a
-; Top row
-	ld bc, 16
-	ld a, " "
-	call ByteFill
-; Top-right corner
-	ld a, $31
-	ld [hl], a
-	hlcoord 1, 1
-
-; Middle row
-	ld bc, 18
-	ld a, " "
-	call ByteFill
-
-; Bottom-left corner
-	hlcoord 1, 2
-	ld a, $32
-	ld [hli], a
-; Bottom row
-	ld bc, 16
-	ld a, " "
-	call ByteFill
-; Bottom-right corner
-	ld a, $33
-	ld [hl], a
-
-; Print "Where?"
-	hlcoord 2, 0
-	ld de, .Where
-	call PlaceString
-; Print the name of the default flypoint
-	call .Name
-; Up/down arrows
-	hlcoord 18, 1
-	ld [hl], $34
-	ret
-
-.Where:
-	db "Where?@"
-
-.Name:
-; We need the map location of the default flypoint
-	ld a, [wTownMapPlayerIconLandmark]
-	ld l, a
-	ld h, 0
-	add hl, hl ; two bytes per flypoint
-	ld de, Flypoints
-	add hl, de
-	ld e, [hl]
-	farcall GetLandmarkName
-	hlcoord 2, 1
-	ld de, wStringBuffer1
-	call PlaceString
-	ret
-
-; 91c17
-
-GetMapCursorCoordinates: ; 91c17
-	ld a, [wTownMapPlayerIconLandmark]
-	ld l, a
-	ld h, 0
-	add hl, hl
-	ld de, Flypoints
-	add hl, de
-	ld e, [hl]
-	farcall GetLandmarkCoords
-	ld a, [wTownMapCursorCoordinates]
-	ld c, a
-	ld a, [wTownMapCursorCoordinates + 1]
-	ld b, a
-	ld hl, 4
-	add hl, bc
-	ld [hl], e
-	ld hl, 5
-	add hl, bc
-	ld [hl], d
-	ret
-
-; 91c3c
-
-CheckIfVisitedFlypoint: ; 91c3c
-; Check if the flypoint loaded in [hl] has been visited yet.
-	push bc
-	push de
-	push hl
-	ld l, [hl]
-	ld h, 0
-	add hl, hl
-	ld de, Flypoints + 1
-	add hl, de
-	ld c, [hl]
-	call HasVisitedSpawn
-	pop hl
-	pop de
-	pop bc
-	and a
-	ret
-
-; 91c50
-
-HasVisitedSpawn: ; 91c50
-; Check if spawn point c has been visited.
-	ld hl, wVisitedSpawns
-	ld b, CHECK_FLAG
-	ld d, 0
-	predef SmallFarFlagAction
-	ld a, c
-	ret
-
-; 91c5e
-
-INCLUDE "data/maps/flypoints.asm"
-
-ret_91c8f: ; 91c8f
-	ret
-
-; 91c90
-
-FlyMap: ; 91c90
-	ld a, [wMapGroup]
-	ld b, a
-	ld a, [wMapNumber]
-	ld c, a
-	call GetWorldMapLocation
-; If we're not in a valid location, i.e. Pokecenter floor 2F,
-; the backup map information is used.
-	cp SPECIAL_MAP
-	jr nz, .CheckRegion
-	ld a, [wBackupMapGroup]
-	ld b, a
-	ld a, [wBackupMapNumber]
-	ld c, a
-	call GetWorldMapLocation
-.CheckRegion:
-; The first 46 locations are part of Johto. The rest are in Kanto.
-	cp KANTO_LANDMARK
-	jr nc, .KantoFlyMap
-.JohtoFlyMap:
-; Note that .NoKanto should be modified in tandem with this branch
-	push af
-; Start from New Bark Town
-	ld a, FLY_NEW_BARK
-	ld [wTownMapPlayerIconLandmark], a
-; Flypoints begin at New Bark Town...
-	ld [wStartFlypoint], a
-; ..and end at Silver Cave.
-	ld a, FLY_MT_SILVER
-	ld [wEndFlypoint], a
-; Fill out the map
-	call FillJohtoMap
-	call .MapHud
-	pop af
-	call TownMapPlayerIcon
-	ret
-
-.KantoFlyMap:
-; The event that there are no flypoints enabled in a map is not
-; accounted for. As a result, if you attempt to select a flypoint
-; when there are none enabled, the game will crash. Additionally,
-; the flypoint selection has a default starting point that
-; can be flown to even if none are enabled.
-; To prevent both of these things from happening when the player
-; enters Kanto, fly access is restricted until Indigo Plateau is
-; visited and its flypoint enabled.
-	push af
-	ld c, SPAWN_INDIGO
-	call HasVisitedSpawn
-	and a
-	jr z, .NoKanto
-; Kanto's map is only loaded if we've visited Indigo Plateau
-
-; Flypoints begin at Pallet Town...
-	ld a, FLY_PALLET
-	ld [wStartFlypoint], a
-; ...and end at Indigo Plateau
-	ld a, FLY_INDIGO
-	ld [wEndFlypoint], a
-; Because Indigo Plateau is the first flypoint the player
-; visits, it's made the default flypoint.
-	ld [wTownMapPlayerIconLandmark], a
-; Fill out the map
-	call FillKantoMap
-	call .MapHud
-	pop af
-	call TownMapPlayerIcon
-	ret
-
-.NoKanto:
-; If Indigo Plateau hasn't been visited, we use Johto's map instead
-
-; Start from New Bark Town
-	ld a, FLY_NEW_BARK
-	ld [wTownMapPlayerIconLandmark], a
-; Flypoints begin at New Bark Town...
-	ld [wStartFlypoint], a
-; ..and end at Silver Cave
-	ld a, FLY_MT_SILVER
-	ld [wEndFlypoint], a
-	call FillJohtoMap
-	pop af
-.MapHud:
-	call TownMapBubble
-	call TownMapPals
-	hlbgcoord 0, 0 ; BG Map 0
-	call TownMapBGUpdate
-	call TownMapMon
-	ld a, c
-	ld [wTownMapCursorCoordinates], a
-	ld a, b
-	ld [wTownMapCursorCoordinates + 1], a
-	ret
-
-; 91d11
-
-Pokedex_GetArea: ; 91d11
-; e: Current landmark
-	ld a, [wTownMapPlayerIconLandmark]
-	push af
-	ld a, [wTownMapCursorLandmark]
-	push af
-	ld a, e
-	ld [wTownMapPlayerIconLandmark], a
-	call ClearSprites
-	xor a
-	ld [hBGMapMode], a
-	ld a, $1
-	ld [hInMenu], a
-	ld de, PokedexNestIconGFX
-	ld hl, vTiles0 tile $7f
-	lb bc, BANK(PokedexNestIconGFX), 1
-	call Request2bpp
-	call .GetPlayerOrFastShipIcon
-	ld hl, vTiles0 tile $78
-	ld c, 4
-	call Request2bpp
-	call LoadTownMapGFX
-	call FillKantoMap
-	call .PlaceString_MonsNest
-	call TownMapPals
-	hlbgcoord 0, 0, vBGMap1
-	call TownMapBGUpdate
-	call FillJohtoMap
-	call .PlaceString_MonsNest
-	call TownMapPals
-	hlbgcoord 0, 0
-	call TownMapBGUpdate
-	ld b, SCGB_POKEGEAR_PALS
-	call GetSGBLayout
-	call SetPalettes
-	xor a
-	ld [hBGMapMode], a
-	xor a ; JOHTO_REGION
-	call .GetAndPlaceNest
-.loop
-	call JoyTextDelay
-	ld hl, hJoyPressed
-	ld a, [hl]
-	and A_BUTTON | B_BUTTON
-	jr nz, .a_b
-	ld a, [hJoypadDown]
-	and SELECT
-	jr nz, .select
-	call .LeftRightInput
-	call .BlinkNestIcons
-	jr .next
-
-.select
-	call .HideNestsShowPlayer
-.next
-	call DelayFrame
-	jr .loop
-
-.a_b
-	call ClearSprites
-	pop af
-	ld [wTownMapCursorLandmark], a
-	pop af
-	ld [wTownMapPlayerIconLandmark], a
-	ret
-
-; 91d9b
-
-.LeftRightInput: ; 91d9b
-	ld a, [hl]
-	and D_LEFT
-	jr nz, .left
-	ld a, [hl]
-	and D_RIGHT
-	jr nz, .right
-	ret
-
-.left
-	ld a, [hWY]
-	cp $90
-	ret z
-	call ClearSprites
-	ld a, $90
-	ld [hWY], a
-	xor a ; JOHTO_REGION
-	call .GetAndPlaceNest
-	ret
-
-.right
-	ld a, [wStatusFlags]
-	bit STATUSFLAGS_HALL_OF_FAME_F, a
-	ret z
-	ld a, [hWY]
-	and a
-	ret z
-	call ClearSprites
-	xor a
-	ld [hWY], a
-	ld a, KANTO_REGION
-	call .GetAndPlaceNest
-	ret
-
-; 91dcd
-
-.BlinkNestIcons: ; 91dcd
-	ld a, [hVBlankCounter]
-	ld e, a
-	and $f
-	ret nz
-	ld a, e
-	and $10
-	jr nz, .copy_sprites
-	call ClearSprites
-	ret
-
-.copy_sprites
-	hlcoord 0, 0
-	ld de, wVirtualOAM
-	ld bc, wVirtualOAMEnd - wVirtualOAM
-	call CopyBytes
-	ret
-
-; 91de9
-
-.PlaceString_MonsNest: ; 91de9
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH
-	ld a, " "
-	call ByteFill
-	hlcoord 0, 1
-	ld a, $6
-	ld [hli], a
-	ld bc, SCREEN_WIDTH - 2
-	ld a, $7
-	call ByteFill
-	ld [hl], $17
-	call GetPokemonName
-	hlcoord 2, 0
-	call PlaceString
-	ld h, b
-	ld l, c
-	ld de, .String_SNest
-	call PlaceString
-	ret
-
-; 91e16
-
-.String_SNest:
-	db "'S NEST@"
-; 91e1e
-
-.GetAndPlaceNest: ; 91e1e
-	ld [wTownMapCursorLandmark], a
-	ld e, a
-	farcall FindNest ; load nest landmarks into wTileMap[0,0]
-	decoord 0, 0
-	ld hl, wVirtualOAMSprite00
-.nestloop
-	ld a, [de]
-	and a
-	jr z, .done_nest
-	push de
-	ld e, a
-	push hl
-	farcall GetLandmarkCoords
-	pop hl
-	; load into OAM
-	ld a, d
-	sub 4
-	ld [hli], a ; y
-	ld a, e
-	sub 4
-	ld [hli], a ; x
-	ld a, $7f ; nest icon
-	ld [hli], a ; tile id
-	xor a
-	ld [hli], a ; attributes
-	; next
-	pop de
-	inc de
-	jr .nestloop
-
-.done_nest
-	ld hl, wVirtualOAM
-	decoord 0, 0
-	ld bc, wVirtualOAMEnd - wVirtualOAM
-	call CopyBytes
-	ret
-
-; 91e5a
-
-.HideNestsShowPlayer: ; 91e5a
-	call .CheckPlayerLocation
-	ret c
-	ld a, [wTownMapPlayerIconLandmark]
-	ld e, a
-	farcall GetLandmarkCoords
-	ld c, e
-	ld b, d
-	ld de, .PlayerOAM
-	ld hl, wVirtualOAMSprite00
-.ShowPlayerLoop:
-	ld a, [de]
-	cp $80
-	jr z, .clear_oam
-	add b
-	ld [hli], a ; y
-	inc de
-	ld a, [de]
-	add c
-	ld [hli], a ; x
-	inc de
-	ld a, [de]
-	add $78 ; where the player's sprite is loaded
-	ld [hli], a ; tile id
-	inc de
-	push bc
-	ld c, PAL_OW_RED
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .male
-	inc c ; PAL_OW_BLUE
-.male
-	ld a, c
-	ld [hli], a ; attributes
-	pop bc
-	jr .ShowPlayerLoop
-
-.clear_oam
-	ld hl, wVirtualOAMSprite04
-	ld bc, wVirtualOAMEnd - wVirtualOAMSprite04
-	xor a
-	call ByteFill
-	ret
-
-; 91e9c
-
-.PlayerOAM: ; 91e9c
-	; y pxl, x pxl, tile offset
-	db -1 * 8, -1 * 8, 0 ; top left
-	db -1 * 8,  0 * 8, 1 ; top right
-	db  0 * 8, -1 * 8, 2 ; bottom left
-	db  0 * 8,  0 * 8, 3 ; bottom right
-	db $80 ; terminator
-; 91ea9
-
-.CheckPlayerLocation: ; 91ea9
-; Don't show the player's sprite if you're
-; not in the same region as what's currently
-; on the screen.
-	ld a, [wTownMapPlayerIconLandmark]
-	cp FAST_SHIP
-	jr z, .johto
-	cp KANTO_LANDMARK
-	jr c, .johto
-.kanto
-	ld a, [wTownMapCursorLandmark]
-	and a
-	jr z, .clear
-	jr .ok
-
-.johto
-	ld a, [wTownMapCursorLandmark]
-	and a
-	jr nz, .clear
-.ok
-	and a
-	ret
-
-.clear
-	ld hl, wVirtualOAM
-	ld bc, wVirtualOAMEnd - wVirtualOAM
-	xor a
-	call ByteFill
-	scf
-	ret
-
-; 91ed0
-
-.GetPlayerOrFastShipIcon: ; 91ed0
-	ld a, [wTownMapPlayerIconLandmark]
-	cp FAST_SHIP
-	jr z, .FastShip
-	farcall GetPlayerIcon
-	ret
-
-.FastShip:
-	ld de, FastShipGFX
-	ld b, BANK(FastShipGFX)
-	ret
-
-; 91ee4
-
-TownMapBGUpdate: ; 91ee4
-; Update BG Map tiles and attributes
-
-; BG Map address
-	ld a, l
-	ld [hBGMapAddress], a
-	ld a, h
-	ld [hBGMapAddress + 1], a
-; Only update palettes on CGB
-	ld a, [hCGB]
-	and a
-	jr z, .tiles
-; BG Map mode 2 (palettes)
-	ld a, 2
-	ld [hBGMapMode], a
-; The BG Map is updated in thirds, so we wait
-
-; 3 frames to update the whole screen's palettes.
-	ld c, 3
-	call DelayFrames
-.tiles
-; Update BG Map tiles
-	call WaitBGMap
-; Turn off BG Map update
-	xor a
-	ld [hBGMapMode], a
-	ret
-
-; 91eff
-
-FillJohtoMap: ; 91eff
-	ld de, JohtoMap
-	jr FillTownMap
-
-FillKantoMap: ; 91f04
-	ld de, KantoMap
-FillTownMap: ; 91f07
-	hlcoord 0, 0
-.loop
-	ld a, [de]
-	cp -1
-	ret z
-	ld a, [de]
-	ld [hli], a
-	inc de
-	jr .loop
-
-; 91f13
-
-TownMapPals: ; 91f13
-; Assign palettes based on tile ids
-	hlcoord 0, 0
-	decoord 0, 0, wAttrMap
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-.loop
-; Current tile
-	ld a, [hli]
-	push hl
-; The palette map covers tiles $00 to $5f; $60 and above use palette 0
-	cp $60
-	jr nc, .pal0
-
-; The palette data is condensed to nybbles, least-significant first.
-	ld hl, .PalMap
-	srl a
-	jr c, .odd
-; Even-numbered tile ids take the bottom nybble...
-	add l
-	ld l, a
-	ld a, h
-	adc 0
-	ld h, a
-	ld a, [hl]
-	and PALETTE_MASK
-	jr .update
-
-.odd
-; ...and odd ids take the top.
-	add l
-	ld l, a
-	ld a, h
-	adc 0
-	ld h, a
-	ld a, [hl]
-	swap a
-	and PALETTE_MASK
-	jr .update
-
-.pal0
-	xor a
-.update
-	pop hl
-	ld [de], a
-	inc de
-	dec bc
-	ld a, b
-	or c
-	jr nz, .loop
-	ret
-
-.PalMap:
-INCLUDE "gfx/pokegear/town_map_palette_map.asm"
-; 91f7b
-
-TownMapMon: ; 91f7b
-; Draw the FlyMon icon at town map location
-
-; Get FlyMon species
-	ld a, [wCurPartyMon]
-	ld hl, wPartySpecies
-	ld e, a
-	ld d, $0
-	add hl, de
-	ld a, [hl]
-	ld [wd265], a
-; Get FlyMon icon
-	ld e, $08 ; starting tile in VRAM
-	farcall GetSpeciesIcon
-; Animation/palette
-	depixel 0, 0
-	ld a, SPRITE_ANIM_INDEX_PARTY_MON
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_TILE_ID
-	add hl, bc
-	ld [hl], $08
-	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
-	add hl, bc
-	ld [hl], SPRITE_ANIM_SEQ_NULL
-	ret
-
-; 91fa6
-
-TownMapPlayerIcon: ; 91fa6
-; Draw the player icon at town map location in a
-	push af
-	farcall GetPlayerIcon
-; Standing icon
-	ld hl, vTiles0 tile $10
-	ld c, 4 ; # tiles
-	call Request2bpp
-; Walking icon
-	ld hl, $c0
-	add hl, de
-	ld d, h
-	ld e, l
-	ld hl, vTiles0 tile $14
-	ld c, 4 ; # tiles
-	ld a, BANK(ChrisSpriteGFX) ; does nothing
-	call Request2bpp
-; Animation/palette
-	depixel 0, 0
-	ld b, SPRITE_ANIM_INDEX_RED_WALK ; Male
-	ld a, [wPlayerGender]
-	bit PLAYERGENDER_FEMALE_F, a
-	jr z, .got_gender
-	ld b, SPRITE_ANIM_INDEX_BLUE_WALK ; Female
-.got_gender
-	ld a, b
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_TILE_ID
-	add hl, bc
-	ld [hl], $10
-	pop af
-	ld e, a
-	push bc
-	farcall GetLandmarkCoords
-	pop bc
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld [hl], e
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	ld [hl], d
-	ret
-
-; 0x91ff2
-
-LoadTownMapGFX: ; 91ff2
-	ld hl, TownMapGFX
-	ld de, vTiles2
-	lb bc, BANK(TownMapGFX), 48
-	call DecompressRequest2bpp
-	ret
-
-; 91fff
-
-JohtoMap: ; 91fff
-INCBIN "gfx/pokegear/johto.bin"
-; 92168
-
-KantoMap: ; 92168
-INCBIN "gfx/pokegear/kanto.bin"
-; 922d1
-
-PokedexNestIconGFX: ; 922d1
-INCBIN "gfx/pokegear/dexmap_nest_icon.2bpp"
-FlyMapLabelBorderGFX: ; 922e1
-INCBIN "gfx/pokegear/flymap_label_border.1bpp"
-
-Unreferenced_Function92311:
-	xor a
-	ld [wTownMapPlayerIconLandmark], a
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	ld hl, hInMenu
-	ld a, [hl]
-	push af
-	ld [hl], $1
-	xor a
-	ld [hBGMapMode], a
-	farcall ClearSpriteAnims
-	call LoadTownMapGFX
-	ld de, FlyMapLabelBorderGFX
-	ld hl, vTiles2 tile $30
-	lb bc, BANK(FlyMapLabelBorderGFX), 6
-	call Request1bpp
-	call FillKantoMap
-	call TownMapBubble
-	call TownMapPals
-	hlbgcoord 0, 0, vBGMap1
-	call TownMapBGUpdate
-	call FillJohtoMap
-	call TownMapBubble
-	call TownMapPals
-	hlbgcoord 0, 0
-	call TownMapBGUpdate
-	call TownMapMon
-	ld a, c
-	ld [wTownMapCursorCoordinates], a
-	ld a, b
-	ld [wTownMapCursorCoordinates + 1], a
-	ld b, SCGB_POKEGEAR_PALS
-	call GetSGBLayout
-	call SetPalettes
-.loop
-	call JoyTextDelay
-	ld hl, hJoyPressed
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .pressedB
-	ld a, [hl]
-	and A_BUTTON
-	jr nz, .pressedA
-	call .HandleDPad
-	call GetMapCursorCoordinates
-	farcall PlaySpriteAnimations
-	call DelayFrame
-	jr .loop
-
-.pressedB
-	ld a, -1
-	jr .finished_a_b
-
-.pressedA
-	ld a, [wTownMapPlayerIconLandmark]
-	ld l, a
-	ld h, 0
-	add hl, hl
-	ld de, Flypoints + 1
-	add hl, de
-	ld a, [hl]
-.finished_a_b
-	ld [wTownMapPlayerIconLandmark], a
-	pop af
-	ld [hInMenu], a
-	call ClearBGPalettes
-	ld a, $90
-	ld [hWY], a
-	xor a ; LOW(vBGMap0)
-	ld [hBGMapAddress], a
-	ld a, HIGH(vBGMap0)
-	ld [hBGMapAddress + 1], a
-	ld a, [wTownMapPlayerIconLandmark]
-	ld e, a
-	ret
-
-; 923b8
-
-.HandleDPad: ; 923b8
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN | D_RIGHT
-	jr nz, .down_right
-	ld a, [hl]
-	and D_UP | D_LEFT
-	jr nz, .up_left
-	ret
-
-.down_right
-	ld hl, wTownMapPlayerIconLandmark
-	ld a, [hl]
-	cp FLY_INDIGO
-	jr c, .okay_dr
-	ld [hl], -1
-.okay_dr
-	inc [hl]
-	jr .continue
-
-.up_left
-	ld hl, wTownMapPlayerIconLandmark
-	ld a, [hl]
-	and a
-	jr nz, .okay_ul
-	ld [hl], FLY_INDIGO + 1
-.okay_ul
-	dec [hl]
-.continue
-	ld a, [wTownMapPlayerIconLandmark]
-	cp KANTO_FLYPOINT
-	jr c, .johto
-	call FillKantoMap
-	xor a
-	ld b, $9c
-	jr .finish
-
-.johto
-	call FillJohtoMap
-	ld a, $90
-	ld b, $98
-.finish
-	ld [hWY], a
-	ld a, b
-	ld [hBGMapAddress + 1], a
-	call TownMapBubble
-	call WaitBGMap
-	xor a
-	ld [hBGMapMode], a
-	ret
-
-; 92402
--- /dev/null
+++ b/engine/pokegear/pokegear.asm
@@ -1,0 +1,3097 @@
+; Pokégear cards
+	const_def
+	const POKEGEARCARD_CLOCK ; 0
+	const POKEGEARCARD_MAP   ; 1
+	const POKEGEARCARD_PHONE ; 2
+	const POKEGEARCARD_RADIO ; 3
+NUM_POKEGEAR_CARDS EQU const_value
+
+; PokegearJumptable.Jumptable indexes
+	const_def
+	const POKEGEARSTATE_CLOCKINIT       ; 0
+	const POKEGEARSTATE_CLOCKJOYPAD     ; 1
+	const POKEGEARSTATE_MAPCHECKREGION  ; 2
+	const POKEGEARSTATE_JOHTOMAPINIT    ; 3
+	const POKEGEARSTATE_JOHTOMAPJOYPAD  ; 4
+	const POKEGEARSTATE_KANTOMAPINIT    ; 5
+	const POKEGEARSTATE_KANTOMAPJOYPAD  ; 6
+	const POKEGEARSTATE_PHONEINIT       ; 7
+	const POKEGEARSTATE_PHONEJOYPAD     ; 8
+	const POKEGEARSTATE_MAKEPHONECALL   ; 9
+	const POKEGEARSTATE_FINISHPHONECALL ; a
+	const POKEGEARSTATE_RADIOINIT       ; b
+	const POKEGEARSTATE_RADIOJOYPAD     ; c
+
+PokeGear: ; 90b8d (24:4b8d)
+	ld hl, wOptions
+	ld a, [hl]
+	push af
+	set NO_TEXT_SCROLL, [hl]
+	ld a, [hInMenu]
+	push af
+	ld a, $1
+	ld [hInMenu], a
+	ld a, [wVramState]
+	push af
+	xor a
+	ld [wVramState], a
+	call .InitTilemap
+	call DelayFrame
+.loop
+	call UpdateTime
+	call JoyTextDelay
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .done
+	call PokegearJumptable
+	farcall PlaySpriteAnimations
+	call DelayFrame
+	jr .loop
+
+.done
+	ld de, SFX_READ_TEXT_2
+	call PlaySFX
+	call WaitSFX
+	pop af
+	ld [wVramState], a
+	pop af
+	ld [hInMenu], a
+	pop af
+	ld [wOptions], a
+	call ClearBGPalettes
+	xor a ; LOW(vBGMap0)
+	ld [hBGMapAddress], a
+	ld a, HIGH(vBGMap0)
+	ld [hBGMapAddress + 1], a
+	ld a, $90
+	ld [hWY], a
+	call ExitPokegearRadio_HandleMusic
+	ret
+
+.InitTilemap: ; 90bea (24:4bea)
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	call DisableLCD
+	xor a
+	ld [hSCY], a
+	ld [hSCX], a
+	ld a, $7
+	ld [hWX], a
+	call Pokegear_LoadGFX
+	farcall ClearSpriteAnims
+	call InitPokegearModeIndicatorArrow
+	ld a, 8
+	call SkipMusic
+	ld a, LCDC_DEFAULT
+	ld [rLCDC], a
+	call TownMap_InitCursorAndPlayerIconPositions
+	xor a
+	ld [wJumptableIndex], a ; POKEGEARSTATE_CLOCKINIT
+	ld [wPokegearCard], a ; POKEGEARCARD_CLOCK
+	ld [wPokegearMapRegion], a ; JOHTO_REGION
+	ld [wcf66], a
+	ld [wPokegearPhoneScrollPosition], a
+	ld [wPokegearPhoneCursorPosition], a
+	ld [wPokegearPhoneSelectedPerson], a
+	ld [wPokegearRadioChannelBank], a
+	ld [wPokegearRadioChannelAddr], a
+	ld [wPokegearRadioChannelAddr + 1], a
+	call Pokegear_InitJumptableIndices
+	call InitPokegearTilemap
+	ld b, SCGB_POKEGEAR_PALS
+	call GetSGBLayout
+	call SetPalettes
+	ld a, [hCGB]
+	and a
+	ret z
+	ld a, %11100100
+	call DmgToCgbObjPal0
+	ret
+
+Pokegear_LoadGFX: ; 90c4e
+	call ClearVBank1
+	ld hl, TownMapGFX
+	ld de, vTiles2
+	ld a, BANK(TownMapGFX)
+	call FarDecompress
+	ld hl, PokegearGFX
+	ld de, vTiles2 tile $30
+	ld a, BANK(PokegearGFX)
+	call FarDecompress
+	ld hl, PokegearSpritesGFX
+	ld de, vTiles0
+	ld a, BANK(PokegearSpritesGFX)
+	call Decompress
+	ld a, [wMapGroup]
+	ld b, a
+	ld a, [wMapNumber]
+	ld c, a
+	call GetWorldMapLocation
+	cp FAST_SHIP
+	jr z, .ssaqua
+	farcall GetPlayerIcon
+	push de
+	ld h, d
+	ld l, e
+	ld a, b
+	; standing sprite
+	push af
+	ld de, vTiles0 tile $10
+	ld bc, 4 tiles
+	call FarCopyBytes
+	pop af
+	pop hl
+	; walking sprite
+	ld de, 12 tiles
+	add hl, de
+	ld de, vTiles0 tile $14
+	ld bc, 4 tiles
+	call FarCopyBytes
+	ret
+
+.ssaqua
+	ld hl, FastShipGFX
+	ld de, vTiles0 tile $10
+	ld bc, 8 tiles
+	call CopyBytes
+	ret
+
+; 90cb2
+
+FastShipGFX: ; 90cb2
+INCBIN "gfx/pokegear/fast_ship.2bpp"
+; 90d32
+
+InitPokegearModeIndicatorArrow: ; 90d32 (24:4d32)
+	depixel 4, 2, 4, 0
+	ld a, SPRITE_ANIM_INDEX_POKEGEAR_ARROW
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_TILE_ID
+	add hl, bc
+	ld [hl], $0
+	ret
+
+AnimatePokegearModeIndicatorArrow: ; 90d41 (24:4d41)
+	ld hl, wPokegearCard
+	ld e, [hl]
+	ld d, 0
+	ld hl, .XCoords
+	add hl, de
+	ld a, [hl]
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+; 90d52 (24:4d52)
+
+.XCoords: ; 90d52
+	db $00 ; POKEGEARCARD_CLOCK
+	db $10 ; POKEGEARCARD_MAP
+	db $20 ; POKEGEARCARD_PHONE
+	db $30 ; POKEGEARCARD_RADIO
+; 90d56
+
+TownMap_GetCurrentLandmark: ; 90d56
+	ld a, [wMapGroup]
+	ld b, a
+	ld a, [wMapNumber]
+	ld c, a
+	call GetWorldMapLocation
+	cp SPECIAL_MAP
+	ret nz
+	ld a, [wBackupMapGroup]
+	ld b, a
+	ld a, [wBackupMapNumber]
+	ld c, a
+	call GetWorldMapLocation
+	ret
+
+; 90d70
+
+TownMap_InitCursorAndPlayerIconPositions: ; 90d70 (24:4d70)
+	ld a, [wMapGroup]
+	ld b, a
+	ld a, [wMapNumber]
+	ld c, a
+	call GetWorldMapLocation
+	cp FAST_SHIP
+	jr z, .FastShip
+	cp SPECIAL_MAP
+	jr nz, .LoadLandmark
+	ld a, [wBackupMapGroup]
+	ld b, a
+	ld a, [wBackupMapNumber]
+	ld c, a
+	call GetWorldMapLocation
+.LoadLandmark:
+	ld [wPokegearMapPlayerIconLandmark], a
+	ld [wPokegearMapCursorLandmark], a
+	ret
+
+.FastShip:
+	ld [wPokegearMapPlayerIconLandmark], a
+	ld a, NEW_BARK_TOWN
+	ld [wPokegearMapCursorLandmark], a
+	ret
+
+Pokegear_InitJumptableIndices: ; 90d9e (24:4d9e)
+	ld a, POKEGEARSTATE_CLOCKINIT
+	ld [wJumptableIndex], a
+	xor a ; POKEGEARCARD_CLOCK
+	ld [wPokegearCard], a
+	ret
+
+InitPokegearTilemap: ; 90da8 (24:4da8)
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, $4f
+	call ByteFill
+	ld a, [wPokegearCard]
+	maskbits NUM_POKEGEAR_CARDS
+	add a
+	ld e, a
+	ld d, 0
+	ld hl, .Jumptable
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, .return_from_jumptable
+	push de
+	jp hl
+
+.return_from_jumptable
+	call Pokegear_FinishTilemap
+	farcall TownMapPals
+	ld a, [wPokegearMapRegion]
+	and a
+	jr nz, .kanto_0
+	xor a ; LOW(vBGMap0)
+	ld [hBGMapAddress], a
+	ld a, HIGH(vBGMap0)
+	ld [hBGMapAddress + 1], a
+	call .UpdateBGMap
+	ld a, $90
+	jr .finish
+
+.kanto_0
+	xor a ; LOW(vBGMap1)
+	ld [hBGMapAddress], a
+	ld a, HIGH(vBGMap1)
+	ld [hBGMapAddress + 1], a
+	call .UpdateBGMap
+	xor a
+.finish
+	ld [hWY], a
+	; swap region maps
+	ld a, [wPokegearMapRegion]
+	maskbits NUM_REGIONS
+	xor 1
+	ld [wPokegearMapRegion], a
+	ret
+
+.UpdateBGMap: ; 90e00 (24:4e00)
+	ld a, [hCGB]
+	and a
+	jr z, .dmg
+	ld a, $2
+	ld [hBGMapMode], a
+	ld c, 3
+	call DelayFrames
+.dmg
+	call WaitBGMap
+	ret
+
+; 90e12 (24:4e12)
+
+.Jumptable: ; 90e12
+; entries correspond to POKEGEARCARD_* constants
+	dw .Clock
+	dw .Map
+	dw .Phone
+	dw .Radio
+; 90e1a
+
+.Clock: ; 90e1a
+	ld de, ClockTilemapRLE
+	call Pokegear_LoadTilemapRLE
+	hlcoord 12, 1
+	ld de, .switch
+	call PlaceString
+	hlcoord 0, 12
+	lb bc, 4, 18
+	call TextBox
+	call Pokegear_UpdateClock
+	ret
+
+; 90e36 (24:4e36)
+
+.switch
+	db " SWITCH▶@"
+; 90e3f
+
+.Map: ; 90e3f
+	ld a, [wPokegearMapPlayerIconLandmark]
+	cp FAST_SHIP
+	jr z, .johto
+	cp KANTO_LANDMARK
+	jr nc, .kanto
+.johto
+	ld e, 0
+	jr .ok
+
+.kanto
+	ld e, 1
+.ok
+	farcall PokegearMap
+	ld a, $07
+	ld bc, $12
+	hlcoord 1, 2
+	call ByteFill
+	hlcoord 0, 2
+	ld [hl], $06
+	hlcoord 19, 2
+	ld [hl], $17
+	ld a, [wPokegearMapCursorLandmark]
+	call PokegearMap_UpdateLandmarkName
+	ret
+
+; 90e72
+
+.Radio: ; 90e72
+	ld de, RadioTilemapRLE
+	call Pokegear_LoadTilemapRLE
+	hlcoord 0, 12
+	lb bc, 4, 18
+	call TextBox
+	ret
+
+; 90e82
+
+.Phone: ; 90e82
+	ld de, PhoneTilemapRLE
+	call Pokegear_LoadTilemapRLE
+	hlcoord 0, 12
+	lb bc, 4, 18
+	call TextBox
+	call .PlacePhoneBars
+	call PokegearPhone_UpdateDisplayList
+	ret
+
+; 90e98
+
+.PlacePhoneBars: ; 90e98 (24:4e98)
+	hlcoord 17, 1
+	ld a, $3c
+	ld [hli], a
+	inc a
+	ld [hl], a
+	hlcoord 17, 2
+	inc a
+	ld [hli], a
+	call GetMapPhoneService
+	and a
+	ret nz
+	hlcoord 18, 2
+	ld [hl], $3f
+	ret
+
+Pokegear_FinishTilemap: ; 90eb0 (24:4eb0)
+	hlcoord 0, 0
+	ld bc, $8
+	ld a, $4f
+	call ByteFill
+	hlcoord 0, 1
+	ld bc, $8
+	ld a, $4f
+	call ByteFill
+	ld de, wPokegearFlags
+	ld a, [de]
+	bit POKEGEAR_MAP_CARD_F, a
+	call nz, .PlaceMapIcon
+	ld a, [de]
+	bit POKEGEAR_PHONE_CARD_F, a
+	call nz, .PlacePhoneIcon
+	ld a, [de]
+	bit POKEGEAR_RADIO_CARD_F, a
+	call nz, .PlaceRadioIcon
+	hlcoord 0, 0
+	ld a, $46
+	call .PlacePokegearCardIcon
+	ret
+
+.PlaceMapIcon: ; 90ee4 (24:4ee4)
+	hlcoord 2, 0
+	ld a, $40
+	jr .PlacePokegearCardIcon
+
+.PlacePhoneIcon: ; 90eeb (24:4eeb)
+	hlcoord 4, 0
+	ld a, $44
+	jr .PlacePokegearCardIcon
+
+.PlaceRadioIcon: ; 90ef2 (24:4ef2)
+	hlcoord 6, 0
+	ld a, $42
+.PlacePokegearCardIcon: ; 90ef7 (24:4ef7)
+	ld [hli], a
+	inc a
+	ld [hld], a
+	ld bc, $14
+	add hl, bc
+	add $f
+	ld [hli], a
+	inc a
+	ld [hld], a
+	ret
+
+PokegearJumptable: ; 90f04 (24:4f04)
+	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: ; 90f13 (24:4f13)
+; entries correspond to POKEGEARSTATE_* constants
+	dw PokegearClock_Init
+	dw PokegearClock_Joypad
+	dw PokegearMap_CheckRegion
+	dw PokegearMap_Init
+	dw PokegearMap_JohtoMap
+	dw PokegearMap_Init
+	dw PokegearMap_KantoMap
+	dw PokegearPhone_Init
+	dw PokegearPhone_Joypad
+	dw PokegearPhone_MakePhoneCall
+	dw PokegearPhone_FinishPhoneCall
+	dw PokegearRadio_Init
+	dw PokegearRadio_Joypad
+
+PokegearClock_Init: ; 90f2d (24:4f2d)
+	call InitPokegearTilemap
+	ld hl, PokegearText_PressAnyButtonToExit
+	call PrintText
+	ld hl, wJumptableIndex
+	inc [hl]
+	call ExitPokegearRadio_HandleMusic
+	ret
+
+PokegearClock_Joypad: ; 90f3e (24:4f3e)
+	call .UpdateClock
+	ld hl, hJoyLast
+	ld a, [hl]
+	and A_BUTTON | B_BUTTON | START | SELECT
+	jr nz, .quit
+	ld a, [hl]
+	and D_RIGHT
+	ret z
+	ld a, [wPokegearFlags]
+	bit POKEGEAR_MAP_CARD_F, a
+	jr z, .no_map_card
+	ld c, POKEGEARSTATE_MAPCHECKREGION
+	ld b, POKEGEARCARD_MAP
+	jr .done
+
+.no_map_card
+	ld a, [wPokegearFlags]
+	bit POKEGEAR_PHONE_CARD_F, a
+	jr z, .no_phone_card
+	ld c, POKEGEARSTATE_PHONEINIT
+	ld b, POKEGEARCARD_PHONE
+	jr .done
+
+.no_phone_card
+	ld a, [wPokegearFlags]
+	bit POKEGEAR_RADIO_CARD_F, a
+	ret z
+	ld c, POKEGEARSTATE_RADIOINIT
+	ld b, POKEGEARCARD_RADIO
+.done
+	call Pokegear_SwitchPage
+	ret
+
+.quit
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+.UpdateClock: ; 90f7b (24:4f7b)
+	xor a
+	ld [hBGMapMode], a
+	call Pokegear_UpdateClock
+	ld a, $1
+	ld [hBGMapMode], a
+	ret
+
+Pokegear_UpdateClock: ; 90f86 (24:4f86)
+	hlcoord 3, 5
+	lb bc, 5, 14
+	call ClearBox
+	ld a, [hHours]
+	ld b, a
+	ld a, [hMinutes]
+	ld c, a
+	decoord 6, 8
+	farcall PrintHoursMins
+	ld hl, .DayText
+	bccoord 6, 6
+	call PlaceHLTextAtBC
+	ret
+
+; 90fa8 (24:4fa8)
+	db "ごぜん@"
+	db "ごご@"
+
+.DayText: ; 0x90faf
+	text_jump UnknownText_0x1c5821
+	db "@"
+
+; 0x90fb4
+
+PokegearMap_CheckRegion: ; 90fb4 (24:4fb4)
+	ld a, [wPokegearMapPlayerIconLandmark]
+	cp FAST_SHIP
+	jr z, .johto
+	cp KANTO_LANDMARK
+	jr nc, .kanto
+.johto
+	ld a, POKEGEARSTATE_JOHTOMAPINIT
+	jr .done
+	ret
+
+.kanto
+	ld a, POKEGEARSTATE_KANTOMAPINIT
+.done
+	ld [wJumptableIndex], a
+	call ExitPokegearRadio_HandleMusic
+	ret
+
+PokegearMap_Init: ; 90fcd (24:4fcd)
+	call InitPokegearTilemap
+	ld a, [wPokegearMapPlayerIconLandmark]
+	call PokegearMap_InitPlayerIcon
+	ld a, [wPokegearMapCursorLandmark]
+	call PokegearMap_InitCursor
+	ld a, c
+	ld [wPokegearMapCursorObjectPointer], a
+	ld a, b
+	ld [wPokegearMapCursorObjectPointer + 1], a
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+PokegearMap_KantoMap: ; 90fe9 (24:4fe9)
+	call TownMap_GetKantoLandmarkLimits
+	jr PokegearMap_ContinueMap
+
+PokegearMap_JohtoMap: ; 90fee (24:4fee)
+	ld d, SILVER_CAVE
+	ld e, NEW_BARK_TOWN
+PokegearMap_ContinueMap: ; 90ff2 (24:4ff2)
+	ld hl, hJoyLast
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .cancel
+	ld a, [hl]
+	and D_RIGHT
+	jr nz, .right
+	ld a, [hl]
+	and D_LEFT
+	jr nz, .left
+	call .DPad
+	ret
+
+.right
+	ld a, [wPokegearFlags]
+	bit POKEGEAR_PHONE_CARD_F, a
+	jr z, .no_phone
+	ld c, POKEGEARSTATE_PHONEINIT
+	ld b, POKEGEARCARD_PHONE
+	jr .done
+
+.no_phone
+	ld a, [wPokegearFlags]
+	bit POKEGEAR_RADIO_CARD_F, a
+	ret z
+	ld c, POKEGEARSTATE_RADIOINIT
+	ld b, POKEGEARCARD_RADIO
+	jr .done
+
+.left
+	ld c, POKEGEARSTATE_CLOCKINIT
+	ld b, POKEGEARCARD_CLOCK
+.done
+	call Pokegear_SwitchPage
+	ret
+
+.cancel
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+.DPad: ; 9102f (24:502f)
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_UP
+	jr nz, .up
+	ld a, [hl]
+	and D_DOWN
+	jr nz, .down
+	ret
+
+.up
+	ld hl, wPokegearMapCursorLandmark
+	ld a, [hl]
+	cp d
+	jr c, .wrap_around_up
+	ld a, e
+	dec a
+	ld [hl], a
+.wrap_around_up
+	inc [hl]
+	jr .done_dpad
+
+.down
+	ld hl, wPokegearMapCursorLandmark
+	ld a, [hl]
+	cp e
+	jr nz, .wrap_around_down
+	ld a, d
+	inc a
+	ld [hl], a
+.wrap_around_down
+	dec [hl]
+.done_dpad
+	ld a, [wPokegearMapCursorLandmark]
+	call PokegearMap_UpdateLandmarkName
+	ld a, [wPokegearMapCursorObjectPointer]
+	ld c, a
+	ld a, [wPokegearMapCursorObjectPointer + 1]
+	ld b, a
+	ld a, [wPokegearMapCursorLandmark]
+	call PokegearMap_UpdateCursorPosition
+	ret
+
+PokegearMap_InitPlayerIcon: ; 9106a
+	push af
+	depixel 0, 0
+	ld b, SPRITE_ANIM_INDEX_RED_WALK
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .got_gender
+	ld b, SPRITE_ANIM_INDEX_BLUE_WALK
+.got_gender
+	ld a, b
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_TILE_ID
+	add hl, bc
+	ld [hl], $10
+	pop af
+	ld e, a
+	push bc
+	farcall GetLandmarkCoords
+	pop bc
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld [hl], e
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	ld [hl], d
+	ret
+
+; 91098
+
+PokegearMap_InitCursor: ; 91098
+	push af
+	depixel 0, 0
+	ld a, SPRITE_ANIM_INDEX_POKEGEAR_ARROW
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_TILE_ID
+	add hl, bc
+	ld [hl], $04
+	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+	add hl, bc
+	ld [hl], SPRITE_ANIM_SEQ_NULL
+	pop af
+	push bc
+	call PokegearMap_UpdateCursorPosition
+	pop bc
+	ret
+
+; 910b4
+
+PokegearMap_UpdateLandmarkName: ; 910b4
+	push af
+	hlcoord 8, 0
+	lb bc, 2, 12
+	call ClearBox
+	pop af
+	ld e, a
+	push de
+	farcall GetLandmarkName
+	pop de
+	farcall TownMap_ConvertLineBreakCharacters
+	hlcoord 8, 0
+	ld [hl], $34
+	ret
+
+; 910d4
+
+PokegearMap_UpdateCursorPosition: ; 910d4
+	push bc
+	ld e, a
+	farcall GetLandmarkCoords
+	pop bc
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld [hl], e
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	ld [hl], d
+	ret
+
+; 910e8
+
+TownMap_GetKantoLandmarkLimits: ; 910e8
+	ld a, [wStatusFlags]
+	bit STATUSFLAGS_HALL_OF_FAME_F, a
+	jr z, .not_hof
+	ld d, ROUTE_28
+	ld e, PALLET_TOWN
+	ret
+
+.not_hof
+	ld d, ROUTE_28
+	ld e, VICTORY_ROAD
+	ret
+
+; 910f9
+
+PokegearRadio_Init: ; 910f9 (24:50f9)
+	call InitPokegearTilemap
+	depixel 4, 10, 4, 4
+	ld a, SPRITE_ANIM_INDEX_RADIO_TUNING_KNOB
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_TILE_ID
+	add hl, bc
+	ld [hl], $08
+	call _UpdateRadioStation
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+PokegearRadio_Joypad: ; 91112 (24:5112)
+	ld hl, hJoyLast
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .cancel
+	ld a, [hl]
+	and D_LEFT
+	jr nz, .left
+	ld a, [wPokegearRadioChannelAddr]
+	ld l, a
+	ld a, [wPokegearRadioChannelAddr + 1]
+	ld h, a
+	ld a, [wPokegearRadioChannelBank]
+	and a
+	ret z
+	rst FarCall
+	ret
+
+.left
+	ld a, [wPokegearFlags]
+	bit POKEGEAR_PHONE_CARD_F, a
+	jr z, .no_phone
+	ld c, POKEGEARSTATE_PHONEINIT
+	ld b, POKEGEARCARD_PHONE
+	jr .switch_page
+
+.no_phone
+	ld a, [wPokegearFlags]
+	bit POKEGEAR_MAP_CARD_F, a
+	jr z, .no_map
+	ld c, POKEGEARSTATE_MAPCHECKREGION
+	ld b, POKEGEARCARD_MAP
+	jr .switch_page
+
+.no_map
+	ld c, POKEGEARSTATE_CLOCKINIT
+	ld b, POKEGEARCARD_CLOCK
+.switch_page
+	call Pokegear_SwitchPage
+	ret
+
+.cancel
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+PokegearPhone_Init: ; 91156 (24:5156)
+	ld hl, wJumptableIndex
+	inc [hl]
+	xor a
+	ld [wPokegearPhoneScrollPosition], a
+	ld [wPokegearPhoneCursorPosition], a
+	ld [wPokegearPhoneSelectedPerson], a
+	call InitPokegearTilemap
+	call ExitPokegearRadio_HandleMusic
+	ld hl, PokegearText_WhomToCall
+	call PrintText
+	ret
+
+PokegearPhone_Joypad: ; 91171 (24:5171)
+	ld hl, hJoyPressed
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .b
+	ld a, [hl]
+	and A_BUTTON
+	jr nz, .a
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_LEFT
+	jr nz, .left
+	ld a, [hl]
+	and D_RIGHT
+	jr nz, .right
+	call PokegearPhone_GetDPad
+	ret
+
+.left
+	ld a, [wPokegearFlags]
+	bit POKEGEAR_MAP_CARD_F, a
+	jr z, .no_map
+	ld c, POKEGEARSTATE_MAPCHECKREGION
+	ld b, POKEGEARCARD_MAP
+	jr .switch_page
+
+.no_map
+	ld c, POKEGEARSTATE_CLOCKINIT
+	ld b, POKEGEARCARD_CLOCK
+	jr .switch_page
+
+.right
+	ld a, [wPokegearFlags]
+	bit POKEGEAR_RADIO_CARD_F, a
+	ret z
+	ld c, POKEGEARSTATE_RADIOINIT
+	ld b, POKEGEARCARD_RADIO
+.switch_page
+	call Pokegear_SwitchPage
+	ret
+
+.b
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+.a
+	ld hl, wPhoneList
+	ld a, [wPokegearPhoneScrollPosition]
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld a, [wPokegearPhoneCursorPosition]
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld a, [hl]
+	and a
+	ret z
+	ld [wPokegearPhoneSelectedPerson], a
+	hlcoord 1, 4
+	ld a, [wPokegearPhoneCursorPosition]
+	ld bc, 20 * 2
+	call AddNTimes
+	ld [hl], "▷"
+	call PokegearPhoneContactSubmenu
+	jr c, .quit_submenu
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+.quit_submenu
+	ld a, POKEGEARSTATE_PHONEJOYPAD
+	ld [wJumptableIndex], a
+	ret
+
+PokegearPhone_MakePhoneCall: ; 911eb (24:51eb)
+	call GetMapPhoneService
+	and a
+	jr nz, .no_service
+	ld hl, wOptions
+	res NO_TEXT_SCROLL, [hl]
+	xor a
+	ld [hInMenu], a
+	ld de, SFX_CALL
+	call PlaySFX
+	ld hl, .dotdotdot
+	call PrintText
+	call WaitSFX
+	ld de, SFX_CALL
+	call PlaySFX
+	ld hl, .dotdotdot
+	call PrintText
+	call WaitSFX
+	ld a, [wPokegearPhoneSelectedPerson]
+	ld b, a
+	call Function90199
+	ld c, 10
+	call DelayFrames
+	ld hl, wOptions
+	set NO_TEXT_SCROLL, [hl]
+	ld a, $1
+	ld [hInMenu], a
+	call PokegearPhone_UpdateCursor
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+.no_service
+	farcall Phone_NoSignal
+	ld hl, .OutOfServiceArea
+	call PrintText
+	ld a, POKEGEARSTATE_PHONEJOYPAD
+	ld [wJumptableIndex], a
+	ld hl, PokegearText_WhomToCall
+	call PrintText
+	ret
+
+; 9124c (24:524c)
+
+.dotdotdot ; 0x9124c
+	;
+	text_jump UnknownText_0x1c5824
+	db "@"
+
+; 0x91251
+
+.OutOfServiceArea: ; 0x91251
+	; You're out of the service area.
+	text_jump UnknownText_0x1c5827
+	db "@"
+
+; 0x91256
+
+PokegearPhone_FinishPhoneCall: ; 91256 (24:5256)
+	ld a, [hJoyPressed]
+	and A_BUTTON | B_BUTTON
+	ret z
+	farcall HangUp
+	ld a, POKEGEARSTATE_PHONEJOYPAD
+	ld [wJumptableIndex], a
+	ld hl, PokegearText_WhomToCall
+	call PrintText
+	ret
+
+PokegearPhone_GetDPad: ; 9126d (24:526d)
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_UP
+	jr nz, .up
+	ld a, [hl]
+	and D_DOWN
+	jr nz, .down
+	ret
+
+.up
+	ld hl, wPokegearPhoneCursorPosition
+	ld a, [hl]
+	and a
+	jr z, .scroll_page_up
+	dec [hl]
+	jr .done_joypad_same_page
+
+.scroll_page_up
+	ld hl, wPokegearPhoneScrollPosition
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+	jr .done_joypad_update_page
+
+.down
+	ld hl, wPokegearPhoneCursorPosition
+	ld a, [hl]
+	cp 3
+	jr nc, .scroll_page_down
+	inc [hl]
+	jr .done_joypad_same_page
+
+.scroll_page_down
+	ld hl, wPokegearPhoneScrollPosition
+	ld a, [hl]
+	cp 6
+	ret nc
+	inc [hl]
+	jr .done_joypad_update_page
+
+.done_joypad_same_page
+	xor a
+	ld [hBGMapMode], a
+	call PokegearPhone_UpdateCursor
+	call WaitBGMap
+	ret
+
+.done_joypad_update_page
+	xor a
+	ld [hBGMapMode], a
+	call PokegearPhone_UpdateDisplayList
+	call WaitBGMap
+	ret
+
+PokegearPhone_UpdateCursor: ; 912b7 (24:52b7)
+	ld a, " "
+	hlcoord 1, 4
+	ld [hl], a
+	hlcoord 1, 6
+	ld [hl], a
+	hlcoord 1, 8
+	ld [hl], a
+	hlcoord 1, 10
+	ld [hl], a
+	hlcoord 1, 4
+	ld a, [wPokegearPhoneCursorPosition]
+	ld bc, 2 * SCREEN_WIDTH
+	call AddNTimes
+	ld [hl], "▶"
+	ret
+
+PokegearPhone_UpdateDisplayList: ; 912d8 (24:52d8)
+	hlcoord 1, 3
+	ld b, 9
+	ld a, " "
+.row
+	ld c, 18
+.col
+	ld [hli], a
+	dec c
+	jr nz, .col
+	inc hl
+	inc hl
+	dec b
+	jr nz, .row
+	ld a, [wPokegearPhoneScrollPosition]
+	ld e, a
+	ld d, $0
+	ld hl, wPhoneList
+	add hl, de
+	xor a
+	ld [wPokegearPhoneLoadNameBuffer], a
+.loop
+	ld a, [hli]
+	push hl
+	push af
+	hlcoord 2, 4
+	ld a, [wPokegearPhoneLoadNameBuffer]
+	ld bc, 2 * SCREEN_WIDTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	pop af
+	ld b, a
+	call Function90380
+	pop hl
+	ld a, [wPokegearPhoneLoadNameBuffer]
+	inc a
+	ld [wPokegearPhoneLoadNameBuffer], a
+	cp 4
+	jr c, .loop
+	call PokegearPhone_UpdateCursor
+	ret
+
+; 9131e (24:531e)
+
+PokegearPhone_DeletePhoneNumber: ; 9131e
+	ld hl, wPhoneList
+	ld a, [wPokegearPhoneScrollPosition]
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld a, [wPokegearPhoneCursorPosition]
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld [hl], 0
+	ld hl, wPhoneList
+	ld c, CONTACT_LIST_SIZE
+.loop
+	ld a, [hli]
+	and a
+	jr nz, .skip
+	ld a, [hld]
+	ld [hli], a
+	ld [hl], 0
+.skip
+	dec c
+	jr nz, .loop
+	ret
+
+; 91342
+
+PokegearPhoneContactSubmenu: ; 91342 (24:5342)
+	ld hl, wPhoneList
+	ld a, [wPokegearPhoneScrollPosition]
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld a, [wPokegearPhoneCursorPosition]
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld c, [hl]
+	farcall CheckCanDeletePhoneNumber
+	ld a, c
+	and a
+	jr z, .cant_delete
+	ld hl, .CallDeleteCancelJumptable
+	ld de, .CallDeleteCancelStrings
+	jr .got_menu_data
+
+.cant_delete
+	ld hl, .CallCancelJumptable
+	ld de, .CallCancelStrings
+.got_menu_data
+	xor a
+	ld [hBGMapMode], a
+	push hl
+	push de
+	ld a, [de]
+	ld l, a
+	inc de
+	ld a, [de]
+	ld h, a
+	inc de
+	push hl
+	ld bc, hBGMapAddress + 1
+	add hl, bc
+	ld a, [de]
+	inc de
+	sla a
+	ld b, a
+	ld c, 8
+	push de
+	call TextBox
+	pop de
+	pop hl
+	inc hl
+	call PlaceString
+	pop de
+	xor a
+	ld [wPokegearPhoneSubmenuCursor], a
+	call .UpdateCursor
+	call WaitBGMap
+.loop
+	push de
+	call JoyTextDelay
+	pop de
+	ld hl, hJoyPressed
+	ld a, [hl]
+	and D_UP
+	jr nz, .d_up
+	ld a, [hl]
+	and D_DOWN
+	jr nz, .d_down
+	ld a, [hl]
+	and A_BUTTON | B_BUTTON
+	jr nz, .a_b
+	call DelayFrame
+	jr .loop
+
+.d_up
+	ld hl, wPokegearPhoneSubmenuCursor
+	ld a, [hl]
+	and a
+	jr z, .loop
+	dec [hl]
+	call .UpdateCursor
+	jr .loop
+
+.d_down
+	ld hl, 2
+	add hl, de
+	ld a, [wPokegearPhoneSubmenuCursor]
+	inc a
+	cp [hl]
+	jr nc, .loop
+	ld [wPokegearPhoneSubmenuCursor], a
+	call .UpdateCursor
+	jr .loop
+
+.a_b
+	xor a
+	ld [hBGMapMode], a
+	call PokegearPhone_UpdateDisplayList
+	ld a, $1
+	ld [hBGMapMode], a
+	pop hl
+	ld a, [hJoyPressed]
+	and B_BUTTON
+	jr nz, .Cancel
+	ld a, [wPokegearPhoneSubmenuCursor]
+	ld e, a
+	ld d, 0
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+.Cancel: ; 913f1
+	ld hl, PokegearText_WhomToCall
+	call PrintText
+	scf
+	ret
+
+; 913f9 (24:53f9)
+
+.Delete: ; 913f9
+	ld hl, PokegearText_DeleteStoredNumber
+	call MenuTextBox
+	call YesNoBox
+	call ExitMenu
+	jr c, .CancelDelete
+	call PokegearPhone_DeletePhoneNumber
+	xor a
+	ld [hBGMapMode], a
+	call PokegearPhone_UpdateDisplayList
+	ld hl, PokegearText_WhomToCall
+	call PrintText
+	call WaitBGMap
+.CancelDelete:
+	scf
+	ret
+
+; 9141b
+
+.Call: ; 9141b
+	and a
+	ret
+
+; 9141d
+
+.UpdateCursor: ; 9141d (24:541d)
+	push de
+	ld a, [de]
+	inc de
+	ld l, a
+	ld a, [de]
+	inc de
+	ld h, a
+	ld a, [de]
+	ld c, a
+	push hl
+	ld a, " "
+	ld de, SCREEN_WIDTH * 2
+.clear_column
+	ld [hl], a
+	add hl, de
+	dec c
+	jr nz, .clear_column
+	pop hl
+	ld a, [wPokegearPhoneSubmenuCursor]
+	ld bc, SCREEN_WIDTH  * 2
+	call AddNTimes
+	ld [hl], "▶"
+	pop de
+	ret
+
+; 9143f (24:543f)
+
+.CallDeleteCancelStrings: ; 9143f
+	dwcoord 10, 6
+	db 3
+	db   "CALL"
+	next "DELETE"
+	next "CANCEL"
+	db   "@"
+; 91455
+
+.CallDeleteCancelJumptable: ; 91455
+	dw .Call
+	dw .Delete
+	dw .Cancel
+
+; 9145b
+
+.CallCancelStrings: ; 9145b
+	dwcoord 10, 8
+	db 2
+	db   "CALL"
+	next "CANCEL"
+	db   "@"
+; 9146a
+
+.CallCancelJumptable: ; 9146a
+	dw .Call
+	dw .Cancel
+
+; 9146e
+
+; unused
+	ld a, [hHours]
+	cp 12
+	jr c, .am
+	sub 12
+	ld [wd265], a
+	scf
+	ret
+
+.am
+	ld [wd265], a
+	and a
+	ret
+
+; 91480
+
+Pokegear_SwitchPage: ; 91480 (24:5480)
+	ld de, SFX_READ_TEXT_2
+	call PlaySFX
+	ld a, c
+	ld [wJumptableIndex], a
+	ld a, b
+	ld [wPokegearCard], a
+	call DeleteSpriteAnimStruct2ToEnd
+	ret
+
+ExitPokegearRadio_HandleMusic: ; 91492
+	ld a, [wPokegearRadioMusicPlaying]
+	cp RESTART_MAP_MUSIC
+	jr z, .restart_map_music
+	cp ENTER_MAP_MUSIC
+	call z, EnterMapMusic
+	xor a
+	ld [wPokegearRadioMusicPlaying], a
+	ret
+
+.restart_map_music
+	call RestartMapMusic
+	xor a
+	ld [wPokegearRadioMusicPlaying], a
+	ret
+
+; 914ab
+
+DeleteSpriteAnimStruct2ToEnd: ; 914ab (24:54ab)
+	ld hl, wSpriteAnim2
+	ld bc, wSpriteAnimationStructsEnd - wSpriteAnim2
+	xor a
+	call ByteFill
+	ld a, 2
+	ld [wSpriteAnimCount], a
+	ret
+
+Pokegear_LoadTilemapRLE: ; 914bb (24:54bb)
+	; Format: repeat count, tile ID
+	; Terminated with -1
+	hlcoord 0, 0
+.loop
+	ld a, [de]
+	cp -1
+	ret z
+	ld b, a
+	inc de
+	ld a, [de]
+	ld c, a
+	inc de
+	ld a, b
+.load
+	ld [hli], a
+	dec c
+	jr nz, .load
+	jr .loop
+
+; 914ce (24:54ce)
+
+PokegearText_WhomToCall: ; 0x914ce
+	; Whom do you want to call?
+	text_jump UnknownText_0x1c5847
+	db "@"
+
+; 0x914d3
+
+PokegearText_PressAnyButtonToExit: ; 0x914d3
+	; Press any button to exit.
+	text_jump UnknownText_0x1c5862
+	db "@"
+
+; 0x914d8
+
+PokegearText_DeleteStoredNumber: ; 0x914d8
+	; Delete this stored phone number?
+	text_jump UnknownText_0x1c587d
+	db "@"
+
+; 0x914dd
+
+PokegearSpritesGFX: ; 914dd
+INCBIN "gfx/pokegear/pokegear_sprites.2bpp.lz"
+; 9150d
+
+RadioTilemapRLE: ; 9150d
+INCBIN "gfx/pokegear/radio.tilemap.rle"
+PhoneTilemapRLE: ; 9158a
+INCBIN "gfx/pokegear/phone.tilemap.rle"
+ClockTilemapRLE: ; 915db
+INCBIN "gfx/pokegear/clock.tilemap.rle"
+; 9163e
+
+_UpdateRadioStation: ; 9163e (24:563e)
+	jr UpdateRadioStation
+
+; called from engine/sprite_anims.asm
+
+AnimateTuningKnob: ; 91640 (24:5640)
+	push bc
+	call .TuningKnob
+	pop bc
+	ld a, [wRadioTuningKnob]
+	ld hl, SPRITEANIMSTRUCT_XOFFSET
+	add hl, bc
+	ld [hl], a
+	ret
+
+.TuningKnob: ; 9164e (24:564e)
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, .down
+	ld a, [hl]
+	and D_UP
+	jr nz, .up
+	ret
+
+.down
+	ld hl, wRadioTuningKnob
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+	dec [hl]
+	jr .update
+
+.up
+	ld hl, wRadioTuningKnob
+	ld a, [hl]
+	cp 80
+	ret nc
+	inc [hl]
+	inc [hl]
+.update
+UpdateRadioStation: ; 9166f (24:566f)
+	ld hl, wRadioTuningKnob
+	ld d, [hl]
+	ld hl, RadioChannels
+.loop
+	ld a, [hli]
+	cp -1
+	jr z, .nostation
+	cp d
+	jr z, .foundstation
+	inc hl
+	inc hl
+	jr .loop
+
+.nostation
+	call NoRadioStation
+	ret
+
+.foundstation
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, .returnafterstation
+	push de
+	jp hl
+
+.returnafterstation
+	ld a, [wPokegearRadioChannelBank]
+	and a
+	ret z
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 2, 9
+	call PlaceString
+	ld a, $1
+	ld [hBGMapMode], a
+	ret
+
+; 916a1 (24:56a1)
+
+; unused
+	ld [wPokegearRadioChannelBank], a
+	ld a, [hli]
+	ld [wPokegearRadioChannelAddr], a
+	ld a, [hli]
+	ld [wPokegearRadioChannelAddr + 1], a
+	ret
+
+; 916ad
+
+RadioChannels:
+; entries correspond to constants/radio_constants.asm
+
+; frequency value given here = 4 × ingame_frequency − 2
+	dbw 16, .PKMNTalkAndPokedexShow
+	dbw 28, .PokemonMusic
+	dbw 32, .LuckyChannel
+	dbw 40, .BuenasPassword
+	dbw 52, .RuinsOfAlphRadio
+	dbw 64, .PlacesAndPeople
+	dbw 72, .LetsAllSing
+	dbw 78, .PokeFluteRadio
+	dbw 80, .EvolutionRadio
+	db -1
+
+.PKMNTalkAndPokedexShow:
+; Pokédex Show in the morning
+
+; Oak's Pokémon Talk in the afternoon and evening
+	call .InJohto
+	jr nc, .NoSignal
+	ld a, [wTimeOfDay]
+	and a
+	jp z, LoadStation_PokedexShow
+	jp LoadStation_OaksPokemonTalk
+
+.PokemonMusic:
+	call .InJohto
+	jr nc, .NoSignal
+	jp LoadStation_PokemonMusic
+
+.LuckyChannel:
+	call .InJohto
+	jr nc, .NoSignal
+	jp LoadStation_LuckyChannel
+
+.BuenasPassword:
+	call .InJohto
+	jr nc, .NoSignal
+	jp LoadStation_BuenasPassword
+
+.RuinsOfAlphRadio:
+	ld a, [wPokegearMapPlayerIconLandmark]
+	cp RUINS_OF_ALPH
+	jr nz, .NoSignal
+	jp LoadStation_UnownRadio
+
+.PlacesAndPeople:
+	call .InJohto
+	jr c, .NoSignal
+	ld a, [wPokegearFlags]
+	bit POKEGEAR_EXPN_CARD_F, a
+	jr z, .NoSignal
+	jp LoadStation_PlacesAndPeople
+
+.LetsAllSing:
+	call .InJohto
+	jr c, .NoSignal
+	ld a, [wPokegearFlags]
+	bit POKEGEAR_EXPN_CARD_F, a
+	jr z, .NoSignal
+	jp LoadStation_LetsAllSing
+
+.PokeFluteRadio:
+	call .InJohto
+	jr c, .NoSignal
+	ld a, [wPokegearFlags]
+	bit POKEGEAR_EXPN_CARD_F, a
+	jr z, .NoSignal
+	jp LoadStation_PokeFluteRadio
+
+.EvolutionRadio:
+; This station airs in the Lake of Rage area when Rocket are still in Mahogany.
+	ld a, [wStatusFlags]
+	bit STATUSFLAGS_ROCKET_SIGNAL_F, a
+	jr z, .NoSignal
+	ld a, [wPokegearMapPlayerIconLandmark]
+	cp MAHOGANY_TOWN
+	jr z, .ok
+	cp ROUTE_43
+	jr z, .ok
+	cp LAKE_OF_RAGE
+	jr nz, .NoSignal
+.ok
+	jp LoadStation_EvolutionRadio
+
+.NoSignal:
+	call NoRadioStation
+	ret
+
+.InJohto:
+; if in Johto or on the S.S. Aqua, set carry
+
+; otherwise clear carry
+	ld a, [wPokegearMapPlayerIconLandmark]
+	cp FAST_SHIP
+	jr z, .johto
+	cp KANTO_LANDMARK
+	jr c, .johto
+.kanto
+	and a
+	ret
+
+.johto
+	scf
+	ret
+
+LoadStation_OaksPokemonTalk: ; 91753 (24:5753)
+	xor a ; OAKS_POKEMON_TALK
+	ld [wCurrentRadioLine], a
+	ld [wNumRadioLinesPrinted], a
+	ld a, BANK(PlayRadioShow)
+	ld hl, PlayRadioShow
+	call Radio_BackUpFarCallParams
+	ld de, OaksPKMNTalkName
+	ret
+
+LoadStation_PokedexShow: ; 91766 (24:5766)
+	ld a, POKEDEX_SHOW
+	ld [wCurrentRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	ld a, BANK(PlayRadioShow)
+	ld hl, PlayRadioShow
+	call Radio_BackUpFarCallParams
+	ld de, PokedexShowName
+	ret
+
+LoadStation_PokemonMusic: ; 9177b (24:577b)
+	ld a, POKEMON_MUSIC
+	ld [wCurrentRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	ld a, BANK(PlayRadioShow)
+	ld hl, PlayRadioShow
+	call Radio_BackUpFarCallParams
+	ld de, PokemonMusicName
+	ret
+
+LoadStation_LuckyChannel: ; 91790 (24:5790)
+	ld a, LUCKY_CHANNEL
+	ld [wCurrentRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	ld a, BANK(PlayRadioShow)
+	ld hl, PlayRadioShow
+	call Radio_BackUpFarCallParams
+	ld de, LuckyChannelName
+	ret
+
+LoadStation_BuenasPassword: ; 917a5 (24:57a5)
+	ld a, BUENAS_PASSWORD
+	ld [wCurrentRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	ld a, BANK(PlayRadioShow)
+	ld hl, PlayRadioShow
+	call Radio_BackUpFarCallParams
+	ld de, NotBuenasPasswordName
+	ld a, [wStatusFlags2]
+	bit STATUSFLAGS2_ROCKETS_IN_RADIO_TOWER_F, a
+	ret z
+	ld de, BuenasPasswordName
+	ret
+
+; 917c3 (24:57c3)
+
+BuenasPasswordName:    db "BUENA'S PASSWORD@"
+NotBuenasPasswordName: db "@"
+
+LoadStation_UnownRadio: ; 917d5 (24:57d5)
+	ld a, UNOWN_RADIO
+	ld [wCurrentRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	ld a, BANK(PlayRadioShow)
+	ld hl, PlayRadioShow
+	call Radio_BackUpFarCallParams
+	ld de, UnownStationName
+	ret
+
+LoadStation_PlacesAndPeople: ; 917ea (24:57ea)
+	ld a, PLACES_AND_PEOPLE
+	ld [wCurrentRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	ld a, BANK(PlayRadioShow)
+	ld hl, PlayRadioShow
+	call Radio_BackUpFarCallParams
+	ld de, PlacesAndPeopleName
+	ret
+
+LoadStation_LetsAllSing: ; 917ff (24:57ff)
+	ld a, LETS_ALL_SING
+	ld [wCurrentRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	ld a, BANK(PlayRadioShow)
+	ld hl, PlayRadioShow
+	call Radio_BackUpFarCallParams
+	ld de, LetsAllSingName
+	ret
+
+; 91814 (24:5814)
+
+LoadStation_RocketRadio: ; 91814
+	ld a, ROCKET_RADIO
+	ld [wCurrentRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	ld a, BANK(PlayRadioShow)
+	ld hl, PlayRadioShow
+	call Radio_BackUpFarCallParams
+	ld de, LetsAllSingName
+	ret
+
+; 91829
+
+LoadStation_PokeFluteRadio: ; 91829 (24:5829)
+	ld a, POKE_FLUTE_RADIO
+	ld [wCurrentRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	ld a, BANK(PlayRadioShow)
+	ld hl, PlayRadioShow
+	call Radio_BackUpFarCallParams
+	ld de, PokeFluteStationName
+	ret
+
+LoadStation_EvolutionRadio: ; 9183e (24:583e)
+	ld a, EVOLUTION_RADIO
+	ld [wCurrentRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	ld a, BANK(PlayRadioShow)
+	ld hl, PlayRadioShow
+	call Radio_BackUpFarCallParams
+	ld de, UnownStationName
+	ret
+
+; 91853 (24:5853)
+
+Unreferenced_LoadStation: ; 91853
+	ret
+
+RadioMusicRestartDE: ; 91854 (24:5854)
+	push de
+	ld a, e
+	ld [wPokegearRadioMusicPlaying], a
+	ld de, MUSIC_NONE
+	call PlayMusic
+	pop de
+	ld a, e
+	ld [wMapMusic], a
+	call PlayMusic
+	ret
+
+RadioMusicRestartPokemonChannel: ; 91868 (24:5868)
+	push de
+	ld a, RESTART_MAP_MUSIC
+	ld [wPokegearRadioMusicPlaying], a
+	ld de, MUSIC_NONE
+	call PlayMusic
+	pop de
+	ld de, MUSIC_POKEMON_CHANNEL
+	call PlayMusic
+	ret
+
+Radio_BackUpFarCallParams: ; 9187c (24:587c)
+	ld [wPokegearRadioChannelBank], a
+	ld a, l
+	ld [wPokegearRadioChannelAddr], a
+	ld a, h
+	ld [wPokegearRadioChannelAddr + 1], a
+	ret
+
+NoRadioStation: ; 91888 (24:5888)
+	call NoRadioMusic
+	call NoRadioName
+	xor a
+	ld [wPokegearRadioChannelBank], a
+	ld [wPokegearRadioChannelAddr], a
+	ld [wPokegearRadioChannelAddr + 1], a
+	ld a, $1
+	ld [hBGMapMode], a
+	ret
+
+NoRadioMusic: ; 9189d (24:589d)
+	ld de, MUSIC_NONE
+	call PlayMusic
+	ld a, ENTER_MAP_MUSIC
+	ld [wPokegearRadioMusicPlaying], a
+	ret
+
+NoRadioName: ; 918a9 (24:58a9)
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 1, 8
+	lb bc, 3, 18
+	call ClearBox
+	hlcoord 0, 12
+	lb bc, 4, 18
+	call TextBox
+	ret
+
+; 918bf
+
+OaksPKMNTalkName:     db "OAK's <PK><MN> Talk@"
+PokedexShowName:      db "#DEX Show@"
+PokemonMusicName:     db "#MON Music@"
+LuckyChannelName:     db "Lucky Channel@"
+UnownStationName:     db "?????@"
+
+PlacesAndPeopleName:  db "Places & People@"
+LetsAllSingName:      db "Let's All Sing!@"
+PokeFluteStationName: db "# FLUTE@"
+; 9191c
+
+_TownMap: ; 9191c
+	ld hl, wOptions
+	ld a, [hl]
+	push af
+	set NO_TEXT_SCROLL, [hl]
+
+	ld a, [hInMenu]
+	push af
+	ld a, $1
+	ld [hInMenu], a
+
+	ld a, [wVramState]
+	push af
+	xor a
+	ld [wVramState], a
+
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	call DisableLCD
+	call Pokegear_LoadGFX
+	farcall ClearSpriteAnims
+	ld a, 8
+	call SkipMusic
+	ld a, LCDC_DEFAULT
+	ld [rLCDC], a
+	call TownMap_GetCurrentLandmark
+	ld [wTownMapPlayerIconLandmark], a
+	ld [wTownMapCursorLandmark], a
+	xor a
+	ld [hBGMapMode], a
+	call .InitTilemap
+	call WaitBGMap2
+	ld a, [wTownMapPlayerIconLandmark]
+	call PokegearMap_InitPlayerIcon
+	ld a, [wTownMapCursorLandmark]
+	call PokegearMap_InitCursor
+	ld a, c
+	ld [wTownMapCursorObjectPointer], a
+	ld a, b
+	ld [wTownMapCursorObjectPointer + 1], a
+	ld b, SCGB_POKEGEAR_PALS
+	call GetSGBLayout
+	call SetPalettes
+	ld a, [hCGB]
+	and a
+	jr z, .dmg
+	ld a, %11100100
+	call DmgToCgbObjPal0
+	call DelayFrame
+
+.dmg
+	ld a, [wTownMapPlayerIconLandmark]
+	cp KANTO_LANDMARK
+	jr nc, .kanto
+	ld d, KANTO_LANDMARK - 1
+	ld e, 1
+	call .loop
+	jr .resume
+
+.kanto
+	call TownMap_GetKantoLandmarkLimits
+	call .loop
+
+.resume
+	pop af
+	ld [wVramState], a
+	pop af
+	ld [hInMenu], a
+	pop af
+	ld [wOptions], a
+	call ClearBGPalettes
+	ret
+
+.loop
+	call JoyTextDelay
+	ld hl, hJoyPressed
+	ld a, [hl]
+	and B_BUTTON
+	ret nz
+
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_UP
+	jr nz, .pressed_up
+
+	ld a, [hl]
+	and D_DOWN
+	jr nz, .pressed_down
+.loop2
+	push de
+	farcall PlaySpriteAnimations
+	pop de
+	call DelayFrame
+	jr .loop
+
+.pressed_up
+	ld hl, wTownMapCursorLandmark
+	ld a, [hl]
+	cp d
+	jr c, .okay
+	ld a, e
+	dec a
+	ld [hl], a
+
+.okay
+	inc [hl]
+	jr .next
+
+.pressed_down
+	ld hl, wTownMapCursorLandmark
+	ld a, [hl]
+	cp e
+	jr nz, .okay2
+	ld a, d
+	inc a
+	ld [hl], a
+
+.okay2
+	dec [hl]
+
+.next
+	push de
+	ld a, [wTownMapCursorLandmark]
+	call PokegearMap_UpdateLandmarkName
+	ld a, [wTownMapCursorObjectPointer]
+	ld c, a
+	ld a, [wTownMapCursorObjectPointer + 1]
+	ld b, a
+	ld a, [wTownMapCursorLandmark]
+	call PokegearMap_UpdateCursorPosition
+	pop de
+	jr .loop2
+; 91a04
+
+.InitTilemap: ; 91a04
+	ld a, [wTownMapPlayerIconLandmark]
+	cp KANTO_LANDMARK
+	jr nc, .kanto2
+	ld e, JOHTO_REGION
+	jr .okay_tilemap
+
+.kanto2
+	ld e, KANTO_REGION
+.okay_tilemap
+	farcall PokegearMap
+	ld a, $07
+	ld bc, 6
+	hlcoord 1, 0
+	call ByteFill
+	hlcoord 0, 0
+	ld [hl], $06
+	hlcoord 7, 0
+	ld [hl], $17
+	hlcoord 7, 1
+	ld [hl], $16
+	hlcoord 7, 2
+	ld [hl], $26
+	ld a, $07
+	ld bc, NAME_LENGTH
+	hlcoord 8, 2
+	call ByteFill
+	hlcoord 19, 2
+	ld [hl], $17
+	ld a, [wTownMapCursorLandmark]
+	call PokegearMap_UpdateLandmarkName
+	farcall TownMapPals
+	ret
+; 91a53
+
+PlayRadio: ; 91a53
+	ld hl, wOptions
+	ld a, [hl]
+	push af
+	set NO_TEXT_SCROLL, [hl]
+	call .PlayStation
+	ld c, 100
+	call DelayFrames
+.loop
+	call JoyTextDelay
+	ld a, [hJoyPressed]
+	and A_BUTTON | B_BUTTON
+	jr nz, .stop
+	ld a, [wPokegearRadioChannelAddr]
+	ld l, a
+	ld a, [wPokegearRadioChannelAddr + 1]
+	ld h, a
+	ld a, [wPokegearRadioChannelBank]
+	and a
+	jr z, .zero
+	rst FarCall
+.zero
+	call DelayFrame
+	jr .loop
+
+.stop
+	pop af
+	ld [wOptions], a
+	call ExitPokegearRadio_HandleMusic
+	ret
+
+; 91a87
+
+.PlayStation: ; 91a87
+	ld a, ENTER_MAP_MUSIC
+	ld [wPokegearRadioMusicPlaying], a
+	ld hl, .StationPointers
+	ld d, 0
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, .jump_return
+	push de
+	jp hl
+
+.jump_return
+	push de
+	hlcoord 0, 12
+	lb bc, 4, 18
+	call TextBox
+	hlcoord 1, 14
+	ld [hl], $72
+	pop de
+	hlcoord 2, 14
+	call PlaceString
+	ld h, b
+	ld l, c
+	ld [hl], $73
+	call WaitBGMap
+	ret
+
+; 91ab9
+
+.StationPointers: ; 91ab9
+; entries correspond to MAPRADIO_* constants
+	dw .OakOrPnP
+	dw LoadStation_OaksPokemonTalk
+	dw LoadStation_PokedexShow
+	dw LoadStation_PokemonMusic
+	dw LoadStation_LuckyChannel
+	dw LoadStation_UnownRadio
+	dw LoadStation_PlacesAndPeople
+	dw LoadStation_LetsAllSing
+	dw LoadStation_RocketRadio
+
+; 91acb
+
+.OakOrPnP: ; 91acb
+	call IsInJohto
+	and a
+	jr nz, .kanto
+	call UpdateTime
+	ld a, [wTimeOfDay]
+	and a
+	jp z, LoadStation_PokedexShow
+	jp LoadStation_OaksPokemonTalk
+
+.kanto
+	jp LoadStation_PlacesAndPeople
+
+; 91ae1
+
+PokegearMap: ; 91ae1
+	ld a, e
+	and a
+	jr nz, .kanto
+	call LoadTownMapGFX
+	call FillJohtoMap
+	ret
+
+.kanto
+	call LoadTownMapGFX
+	call FillKantoMap
+	ret
+
+; 91af3
+
+_FlyMap: ; 91af3
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	ld hl, hInMenu
+	ld a, [hl]
+	push af
+	ld [hl], $1
+	xor a
+	ld [hBGMapMode], a
+	farcall ClearSpriteAnims
+	call LoadTownMapGFX
+	ld de, FlyMapLabelBorderGFX
+	ld hl, vTiles2 tile $30
+	lb bc, BANK(FlyMapLabelBorderGFX), 6
+	call Request1bpp
+	call FlyMap
+	call ret_91c8f
+	ld b, SCGB_POKEGEAR_PALS
+	call GetSGBLayout
+	call SetPalettes
+.loop
+	call JoyTextDelay
+	ld hl, hJoyPressed
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .pressedB
+	ld a, [hl]
+	and A_BUTTON
+	jr nz, .pressedA
+	call FlyMapScroll
+	call GetMapCursorCoordinates
+	farcall PlaySpriteAnimations
+	call DelayFrame
+	jr .loop
+
+.pressedB
+	ld a, -1
+	jr .exit
+
+.pressedA
+	ld a, [wTownMapPlayerIconLandmark]
+	ld l, a
+	ld h, 0
+	add hl, hl
+	ld de, Flypoints + 1
+	add hl, de
+	ld a, [hl]
+.exit
+	ld [wTownMapPlayerIconLandmark], a
+	pop af
+	ld [hInMenu], a
+	call ClearBGPalettes
+	ld a, $90
+	ld [hWY], a
+	xor a ; LOW(vBGMap0)
+	ld [hBGMapAddress], a
+	ld a, HIGH(vBGMap0)
+	ld [hBGMapAddress + 1], a
+	ld a, [wTownMapPlayerIconLandmark]
+	ld e, a
+	ret
+
+; 91b73
+
+FlyMapScroll: ; 91b73
+	ld a, [wStartFlypoint]
+	ld e, a
+	ld a, [wEndFlypoint]
+	ld d, a
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_UP
+	jr nz, .ScrollNext
+	ld a, [hl]
+	and D_DOWN
+	jr nz, .ScrollPrev
+	ret
+
+.ScrollNext:
+	ld hl, wTownMapPlayerIconLandmark
+	ld a, [hl]
+	cp d
+	jr nz, .NotAtEndYet
+	ld a, e
+	dec a
+	ld [hl], a
+.NotAtEndYet:
+	inc [hl]
+	call CheckIfVisitedFlypoint
+	jr z, .ScrollNext
+	jr .Finally
+
+.ScrollPrev:
+	ld hl, wTownMapPlayerIconLandmark
+	ld a, [hl]
+	cp e
+	jr nz, .NotAtStartYet
+	ld a, d
+	inc a
+	ld [hl], a
+.NotAtStartYet:
+	dec [hl]
+	call CheckIfVisitedFlypoint
+	jr z, .ScrollPrev
+.Finally:
+	call TownMapBubble
+	call WaitBGMap
+	xor a
+	ld [hBGMapMode], a
+	ret
+
+; 91bb5
+
+TownMapBubble: ; 91bb5
+; Draw the bubble containing the location text in the town map HUD
+
+; Top-left corner
+	hlcoord 1, 0
+	ld a, $30
+	ld [hli], a
+; Top row
+	ld bc, 16
+	ld a, " "
+	call ByteFill
+; Top-right corner
+	ld a, $31
+	ld [hl], a
+	hlcoord 1, 1
+
+; Middle row
+	ld bc, 18
+	ld a, " "
+	call ByteFill
+
+; Bottom-left corner
+	hlcoord 1, 2
+	ld a, $32
+	ld [hli], a
+; Bottom row
+	ld bc, 16
+	ld a, " "
+	call ByteFill
+; Bottom-right corner
+	ld a, $33
+	ld [hl], a
+
+; Print "Where?"
+	hlcoord 2, 0
+	ld de, .Where
+	call PlaceString
+; Print the name of the default flypoint
+	call .Name
+; Up/down arrows
+	hlcoord 18, 1
+	ld [hl], $34
+	ret
+
+.Where:
+	db "Where?@"
+
+.Name:
+; We need the map location of the default flypoint
+	ld a, [wTownMapPlayerIconLandmark]
+	ld l, a
+	ld h, 0
+	add hl, hl ; two bytes per flypoint
+	ld de, Flypoints
+	add hl, de
+	ld e, [hl]
+	farcall GetLandmarkName
+	hlcoord 2, 1
+	ld de, wStringBuffer1
+	call PlaceString
+	ret
+
+; 91c17
+
+GetMapCursorCoordinates: ; 91c17
+	ld a, [wTownMapPlayerIconLandmark]
+	ld l, a
+	ld h, 0
+	add hl, hl
+	ld de, Flypoints
+	add hl, de
+	ld e, [hl]
+	farcall GetLandmarkCoords
+	ld a, [wTownMapCursorCoordinates]
+	ld c, a
+	ld a, [wTownMapCursorCoordinates + 1]
+	ld b, a
+	ld hl, 4
+	add hl, bc
+	ld [hl], e
+	ld hl, 5
+	add hl, bc
+	ld [hl], d
+	ret
+
+; 91c3c
+
+CheckIfVisitedFlypoint: ; 91c3c
+; Check if the flypoint loaded in [hl] has been visited yet.
+	push bc
+	push de
+	push hl
+	ld l, [hl]
+	ld h, 0
+	add hl, hl
+	ld de, Flypoints + 1
+	add hl, de
+	ld c, [hl]
+	call HasVisitedSpawn
+	pop hl
+	pop de
+	pop bc
+	and a
+	ret
+
+; 91c50
+
+HasVisitedSpawn: ; 91c50
+; Check if spawn point c has been visited.
+	ld hl, wVisitedSpawns
+	ld b, CHECK_FLAG
+	ld d, 0
+	predef SmallFarFlagAction
+	ld a, c
+	ret
+
+; 91c5e
+
+INCLUDE "data/maps/flypoints.asm"
+
+ret_91c8f: ; 91c8f
+	ret
+
+; 91c90
+
+FlyMap: ; 91c90
+	ld a, [wMapGroup]
+	ld b, a
+	ld a, [wMapNumber]
+	ld c, a
+	call GetWorldMapLocation
+; If we're not in a valid location, i.e. Pokecenter floor 2F,
+; the backup map information is used.
+	cp SPECIAL_MAP
+	jr nz, .CheckRegion
+	ld a, [wBackupMapGroup]
+	ld b, a
+	ld a, [wBackupMapNumber]
+	ld c, a
+	call GetWorldMapLocation
+.CheckRegion:
+; The first 46 locations are part of Johto. The rest are in Kanto.
+	cp KANTO_LANDMARK
+	jr nc, .KantoFlyMap
+.JohtoFlyMap:
+; Note that .NoKanto should be modified in tandem with this branch
+	push af
+; Start from New Bark Town
+	ld a, FLY_NEW_BARK
+	ld [wTownMapPlayerIconLandmark], a
+; Flypoints begin at New Bark Town...
+	ld [wStartFlypoint], a
+; ..and end at Silver Cave.
+	ld a, FLY_MT_SILVER
+	ld [wEndFlypoint], a
+; Fill out the map
+	call FillJohtoMap
+	call .MapHud
+	pop af
+	call TownMapPlayerIcon
+	ret
+
+.KantoFlyMap:
+; The event that there are no flypoints enabled in a map is not
+; accounted for. As a result, if you attempt to select a flypoint
+; when there are none enabled, the game will crash. Additionally,
+; the flypoint selection has a default starting point that
+; can be flown to even if none are enabled.
+; To prevent both of these things from happening when the player
+; enters Kanto, fly access is restricted until Indigo Plateau is
+; visited and its flypoint enabled.
+	push af
+	ld c, SPAWN_INDIGO
+	call HasVisitedSpawn
+	and a
+	jr z, .NoKanto
+; Kanto's map is only loaded if we've visited Indigo Plateau
+
+; Flypoints begin at Pallet Town...
+	ld a, FLY_PALLET
+	ld [wStartFlypoint], a
+; ...and end at Indigo Plateau
+	ld a, FLY_INDIGO
+	ld [wEndFlypoint], a
+; Because Indigo Plateau is the first flypoint the player
+; visits, it's made the default flypoint.
+	ld [wTownMapPlayerIconLandmark], a
+; Fill out the map
+	call FillKantoMap
+	call .MapHud
+	pop af
+	call TownMapPlayerIcon
+	ret
+
+.NoKanto:
+; If Indigo Plateau hasn't been visited, we use Johto's map instead
+
+; Start from New Bark Town
+	ld a, FLY_NEW_BARK
+	ld [wTownMapPlayerIconLandmark], a
+; Flypoints begin at New Bark Town...
+	ld [wStartFlypoint], a
+; ..and end at Silver Cave
+	ld a, FLY_MT_SILVER
+	ld [wEndFlypoint], a
+	call FillJohtoMap
+	pop af
+.MapHud:
+	call TownMapBubble
+	call TownMapPals
+	hlbgcoord 0, 0 ; BG Map 0
+	call TownMapBGUpdate
+	call TownMapMon
+	ld a, c
+	ld [wTownMapCursorCoordinates], a
+	ld a, b
+	ld [wTownMapCursorCoordinates + 1], a
+	ret
+
+; 91d11
+
+Pokedex_GetArea: ; 91d11
+; e: Current landmark
+	ld a, [wTownMapPlayerIconLandmark]
+	push af
+	ld a, [wTownMapCursorLandmark]
+	push af
+	ld a, e
+	ld [wTownMapPlayerIconLandmark], a
+	call ClearSprites
+	xor a
+	ld [hBGMapMode], a
+	ld a, $1
+	ld [hInMenu], a
+	ld de, PokedexNestIconGFX
+	ld hl, vTiles0 tile $7f
+	lb bc, BANK(PokedexNestIconGFX), 1
+	call Request2bpp
+	call .GetPlayerOrFastShipIcon
+	ld hl, vTiles0 tile $78
+	ld c, 4
+	call Request2bpp
+	call LoadTownMapGFX
+	call FillKantoMap
+	call .PlaceString_MonsNest
+	call TownMapPals
+	hlbgcoord 0, 0, vBGMap1
+	call TownMapBGUpdate
+	call FillJohtoMap
+	call .PlaceString_MonsNest
+	call TownMapPals
+	hlbgcoord 0, 0
+	call TownMapBGUpdate
+	ld b, SCGB_POKEGEAR_PALS
+	call GetSGBLayout
+	call SetPalettes
+	xor a
+	ld [hBGMapMode], a
+	xor a ; JOHTO_REGION
+	call .GetAndPlaceNest
+.loop
+	call JoyTextDelay
+	ld hl, hJoyPressed
+	ld a, [hl]
+	and A_BUTTON | B_BUTTON
+	jr nz, .a_b
+	ld a, [hJoypadDown]
+	and SELECT
+	jr nz, .select
+	call .LeftRightInput
+	call .BlinkNestIcons
+	jr .next
+
+.select
+	call .HideNestsShowPlayer
+.next
+	call DelayFrame
+	jr .loop
+
+.a_b
+	call ClearSprites
+	pop af
+	ld [wTownMapCursorLandmark], a
+	pop af
+	ld [wTownMapPlayerIconLandmark], a
+	ret
+
+; 91d9b
+
+.LeftRightInput: ; 91d9b
+	ld a, [hl]
+	and D_LEFT
+	jr nz, .left
+	ld a, [hl]
+	and D_RIGHT
+	jr nz, .right
+	ret
+
+.left
+	ld a, [hWY]
+	cp $90
+	ret z
+	call ClearSprites
+	ld a, $90
+	ld [hWY], a
+	xor a ; JOHTO_REGION
+	call .GetAndPlaceNest
+	ret
+
+.right
+	ld a, [wStatusFlags]
+	bit STATUSFLAGS_HALL_OF_FAME_F, a
+	ret z
+	ld a, [hWY]
+	and a
+	ret z
+	call ClearSprites
+	xor a
+	ld [hWY], a
+	ld a, KANTO_REGION
+	call .GetAndPlaceNest
+	ret
+
+; 91dcd
+
+.BlinkNestIcons: ; 91dcd
+	ld a, [hVBlankCounter]
+	ld e, a
+	and $f
+	ret nz
+	ld a, e
+	and $10
+	jr nz, .copy_sprites
+	call ClearSprites
+	ret
+
+.copy_sprites
+	hlcoord 0, 0
+	ld de, wVirtualOAM
+	ld bc, wVirtualOAMEnd - wVirtualOAM
+	call CopyBytes
+	ret
+
+; 91de9
+
+.PlaceString_MonsNest: ; 91de9
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH
+	ld a, " "
+	call ByteFill
+	hlcoord 0, 1
+	ld a, $6
+	ld [hli], a
+	ld bc, SCREEN_WIDTH - 2
+	ld a, $7
+	call ByteFill
+	ld [hl], $17
+	call GetPokemonName
+	hlcoord 2, 0
+	call PlaceString
+	ld h, b
+	ld l, c
+	ld de, .String_SNest
+	call PlaceString
+	ret
+
+; 91e16
+
+.String_SNest:
+	db "'S NEST@"
+; 91e1e
+
+.GetAndPlaceNest: ; 91e1e
+	ld [wTownMapCursorLandmark], a
+	ld e, a
+	farcall FindNest ; load nest landmarks into wTileMap[0,0]
+	decoord 0, 0
+	ld hl, wVirtualOAMSprite00
+.nestloop
+	ld a, [de]
+	and a
+	jr z, .done_nest
+	push de
+	ld e, a
+	push hl
+	farcall GetLandmarkCoords
+	pop hl
+	; load into OAM
+	ld a, d
+	sub 4
+	ld [hli], a ; y
+	ld a, e
+	sub 4
+	ld [hli], a ; x
+	ld a, $7f ; nest icon
+	ld [hli], a ; tile id
+	xor a
+	ld [hli], a ; attributes
+	; next
+	pop de
+	inc de
+	jr .nestloop
+
+.done_nest
+	ld hl, wVirtualOAM
+	decoord 0, 0
+	ld bc, wVirtualOAMEnd - wVirtualOAM
+	call CopyBytes
+	ret
+
+; 91e5a
+
+.HideNestsShowPlayer: ; 91e5a
+	call .CheckPlayerLocation
+	ret c
+	ld a, [wTownMapPlayerIconLandmark]
+	ld e, a
+	farcall GetLandmarkCoords
+	ld c, e
+	ld b, d
+	ld de, .PlayerOAM
+	ld hl, wVirtualOAMSprite00
+.ShowPlayerLoop:
+	ld a, [de]
+	cp $80
+	jr z, .clear_oam
+	add b
+	ld [hli], a ; y
+	inc de
+	ld a, [de]
+	add c
+	ld [hli], a ; x
+	inc de
+	ld a, [de]
+	add $78 ; where the player's sprite is loaded
+	ld [hli], a ; tile id
+	inc de
+	push bc
+	ld c, PAL_OW_RED
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .male
+	inc c ; PAL_OW_BLUE
+.male
+	ld a, c
+	ld [hli], a ; attributes
+	pop bc
+	jr .ShowPlayerLoop
+
+.clear_oam
+	ld hl, wVirtualOAMSprite04
+	ld bc, wVirtualOAMEnd - wVirtualOAMSprite04
+	xor a
+	call ByteFill
+	ret
+
+; 91e9c
+
+.PlayerOAM: ; 91e9c
+	; y pxl, x pxl, tile offset
+	db -1 * 8, -1 * 8, 0 ; top left
+	db -1 * 8,  0 * 8, 1 ; top right
+	db  0 * 8, -1 * 8, 2 ; bottom left
+	db  0 * 8,  0 * 8, 3 ; bottom right
+	db $80 ; terminator
+; 91ea9
+
+.CheckPlayerLocation: ; 91ea9
+; Don't show the player's sprite if you're
+; not in the same region as what's currently
+; on the screen.
+	ld a, [wTownMapPlayerIconLandmark]
+	cp FAST_SHIP
+	jr z, .johto
+	cp KANTO_LANDMARK
+	jr c, .johto
+.kanto
+	ld a, [wTownMapCursorLandmark]
+	and a
+	jr z, .clear
+	jr .ok
+
+.johto
+	ld a, [wTownMapCursorLandmark]
+	and a
+	jr nz, .clear
+.ok
+	and a
+	ret
+
+.clear
+	ld hl, wVirtualOAM
+	ld bc, wVirtualOAMEnd - wVirtualOAM
+	xor a
+	call ByteFill
+	scf
+	ret
+
+; 91ed0
+
+.GetPlayerOrFastShipIcon: ; 91ed0
+	ld a, [wTownMapPlayerIconLandmark]
+	cp FAST_SHIP
+	jr z, .FastShip
+	farcall GetPlayerIcon
+	ret
+
+.FastShip:
+	ld de, FastShipGFX
+	ld b, BANK(FastShipGFX)
+	ret
+
+; 91ee4
+
+TownMapBGUpdate: ; 91ee4
+; Update BG Map tiles and attributes
+
+; BG Map address
+	ld a, l
+	ld [hBGMapAddress], a
+	ld a, h
+	ld [hBGMapAddress + 1], a
+; Only update palettes on CGB
+	ld a, [hCGB]
+	and a
+	jr z, .tiles
+; BG Map mode 2 (palettes)
+	ld a, 2
+	ld [hBGMapMode], a
+; The BG Map is updated in thirds, so we wait
+
+; 3 frames to update the whole screen's palettes.
+	ld c, 3
+	call DelayFrames
+.tiles
+; Update BG Map tiles
+	call WaitBGMap
+; Turn off BG Map update
+	xor a
+	ld [hBGMapMode], a
+	ret
+
+; 91eff
+
+FillJohtoMap: ; 91eff
+	ld de, JohtoMap
+	jr FillTownMap
+
+FillKantoMap: ; 91f04
+	ld de, KantoMap
+FillTownMap: ; 91f07
+	hlcoord 0, 0
+.loop
+	ld a, [de]
+	cp -1
+	ret z
+	ld a, [de]
+	ld [hli], a
+	inc de
+	jr .loop
+
+; 91f13
+
+TownMapPals: ; 91f13
+; Assign palettes based on tile ids
+	hlcoord 0, 0
+	decoord 0, 0, wAttrMap
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+.loop
+; Current tile
+	ld a, [hli]
+	push hl
+; The palette map covers tiles $00 to $5f; $60 and above use palette 0
+	cp $60
+	jr nc, .pal0
+
+; The palette data is condensed to nybbles, least-significant first.
+	ld hl, .PalMap
+	srl a
+	jr c, .odd
+; Even-numbered tile ids take the bottom nybble...
+	add l
+	ld l, a
+	ld a, h
+	adc 0
+	ld h, a
+	ld a, [hl]
+	and PALETTE_MASK
+	jr .update
+
+.odd
+; ...and odd ids take the top.
+	add l
+	ld l, a
+	ld a, h
+	adc 0
+	ld h, a
+	ld a, [hl]
+	swap a
+	and PALETTE_MASK
+	jr .update
+
+.pal0
+	xor a
+.update
+	pop hl
+	ld [de], a
+	inc de
+	dec bc
+	ld a, b
+	or c
+	jr nz, .loop
+	ret
+
+.PalMap:
+INCLUDE "gfx/pokegear/town_map_palette_map.asm"
+; 91f7b
+
+TownMapMon: ; 91f7b
+; Draw the FlyMon icon at town map location
+
+; Get FlyMon species
+	ld a, [wCurPartyMon]
+	ld hl, wPartySpecies
+	ld e, a
+	ld d, $0
+	add hl, de
+	ld a, [hl]
+	ld [wd265], a
+; Get FlyMon icon
+	ld e, $08 ; starting tile in VRAM
+	farcall GetSpeciesIcon
+; Animation/palette
+	depixel 0, 0
+	ld a, SPRITE_ANIM_INDEX_PARTY_MON
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_TILE_ID
+	add hl, bc
+	ld [hl], $08
+	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
+	add hl, bc
+	ld [hl], SPRITE_ANIM_SEQ_NULL
+	ret
+
+; 91fa6
+
+TownMapPlayerIcon: ; 91fa6
+; Draw the player icon at town map location in a
+	push af
+	farcall GetPlayerIcon
+; Standing icon
+	ld hl, vTiles0 tile $10
+	ld c, 4 ; # tiles
+	call Request2bpp
+; Walking icon
+	ld hl, $c0
+	add hl, de
+	ld d, h
+	ld e, l
+	ld hl, vTiles0 tile $14
+	ld c, 4 ; # tiles
+	ld a, BANK(ChrisSpriteGFX) ; does nothing
+	call Request2bpp
+; Animation/palette
+	depixel 0, 0
+	ld b, SPRITE_ANIM_INDEX_RED_WALK ; Male
+	ld a, [wPlayerGender]
+	bit PLAYERGENDER_FEMALE_F, a
+	jr z, .got_gender
+	ld b, SPRITE_ANIM_INDEX_BLUE_WALK ; Female
+.got_gender
+	ld a, b
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_TILE_ID
+	add hl, bc
+	ld [hl], $10
+	pop af
+	ld e, a
+	push bc
+	farcall GetLandmarkCoords
+	pop bc
+	ld hl, SPRITEANIMSTRUCT_XCOORD
+	add hl, bc
+	ld [hl], e
+	ld hl, SPRITEANIMSTRUCT_YCOORD
+	add hl, bc
+	ld [hl], d
+	ret
+
+; 0x91ff2
+
+LoadTownMapGFX: ; 91ff2
+	ld hl, TownMapGFX
+	ld de, vTiles2
+	lb bc, BANK(TownMapGFX), 48
+	call DecompressRequest2bpp
+	ret
+
+; 91fff
+
+JohtoMap: ; 91fff
+INCBIN "gfx/pokegear/johto.bin"
+; 92168
+
+KantoMap: ; 92168
+INCBIN "gfx/pokegear/kanto.bin"
+; 922d1
+
+PokedexNestIconGFX: ; 922d1
+INCBIN "gfx/pokegear/dexmap_nest_icon.2bpp"
+FlyMapLabelBorderGFX: ; 922e1
+INCBIN "gfx/pokegear/flymap_label_border.1bpp"
+
+Unreferenced_Function92311:
+	xor a
+	ld [wTownMapPlayerIconLandmark], a
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	ld hl, hInMenu
+	ld a, [hl]
+	push af
+	ld [hl], $1
+	xor a
+	ld [hBGMapMode], a
+	farcall ClearSpriteAnims
+	call LoadTownMapGFX
+	ld de, FlyMapLabelBorderGFX
+	ld hl, vTiles2 tile $30
+	lb bc, BANK(FlyMapLabelBorderGFX), 6
+	call Request1bpp
+	call FillKantoMap
+	call TownMapBubble
+	call TownMapPals
+	hlbgcoord 0, 0, vBGMap1
+	call TownMapBGUpdate
+	call FillJohtoMap
+	call TownMapBubble
+	call TownMapPals
+	hlbgcoord 0, 0
+	call TownMapBGUpdate
+	call TownMapMon
+	ld a, c
+	ld [wTownMapCursorCoordinates], a
+	ld a, b
+	ld [wTownMapCursorCoordinates + 1], a
+	ld b, SCGB_POKEGEAR_PALS
+	call GetSGBLayout
+	call SetPalettes
+.loop
+	call JoyTextDelay
+	ld hl, hJoyPressed
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .pressedB
+	ld a, [hl]
+	and A_BUTTON
+	jr nz, .pressedA
+	call .HandleDPad
+	call GetMapCursorCoordinates
+	farcall PlaySpriteAnimations
+	call DelayFrame
+	jr .loop
+
+.pressedB
+	ld a, -1
+	jr .finished_a_b
+
+.pressedA
+	ld a, [wTownMapPlayerIconLandmark]
+	ld l, a
+	ld h, 0
+	add hl, hl
+	ld de, Flypoints + 1
+	add hl, de
+	ld a, [hl]
+.finished_a_b
+	ld [wTownMapPlayerIconLandmark], a
+	pop af
+	ld [hInMenu], a
+	call ClearBGPalettes
+	ld a, $90
+	ld [hWY], a
+	xor a ; LOW(vBGMap0)
+	ld [hBGMapAddress], a
+	ld a, HIGH(vBGMap0)
+	ld [hBGMapAddress + 1], a
+	ld a, [wTownMapPlayerIconLandmark]
+	ld e, a
+	ret
+
+; 923b8
+
+.HandleDPad: ; 923b8
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN | D_RIGHT
+	jr nz, .down_right
+	ld a, [hl]
+	and D_UP | D_LEFT
+	jr nz, .up_left
+	ret
+
+.down_right
+	ld hl, wTownMapPlayerIconLandmark
+	ld a, [hl]
+	cp FLY_INDIGO
+	jr c, .okay_dr
+	ld [hl], -1
+.okay_dr
+	inc [hl]
+	jr .continue
+
+.up_left
+	ld hl, wTownMapPlayerIconLandmark
+	ld a, [hl]
+	and a
+	jr nz, .okay_ul
+	ld [hl], FLY_INDIGO + 1
+.okay_ul
+	dec [hl]
+.continue
+	ld a, [wTownMapPlayerIconLandmark]
+	cp KANTO_FLYPOINT
+	jr c, .johto
+	call FillKantoMap
+	xor a
+	ld b, $9c
+	jr .finish
+
+.johto
+	call FillJohtoMap
+	ld a, $90
+	ld b, $98
+.finish
+	ld [hWY], a
+	ld a, b
+	ld [hBGMapAddress + 1], a
+	call TownMapBubble
+	call WaitBGMap
+	xor a
+	ld [hBGMapMode], a
+	ret
+
+; 92402
--- /dev/null
+++ b/engine/pokegear/radio.asm
@@ -1,0 +1,1932 @@
+PlayRadioShow:
+; If we're already in the radio program proper, we don't need to be here.
+	ld a, [wCurrentRadioLine]
+	cp POKE_FLUTE_RADIO
+	jr nc, .ok
+; If Team Rocket is not occupying the radio tower, we don't need to be here.
+	ld a, [wStatusFlags2]
+	bit STATUSFLAGS2_ROCKETS_IN_RADIO_TOWER_F, a
+	jr z, .ok
+; If we're in Kanto, we don't need to be here.
+	call IsInJohto
+	and a
+	jr nz, .ok
+; Team Rocket broadcasts on all stations.
+	ld a, ROCKET_RADIO
+	ld [wCurrentRadioLine], a
+.ok
+; Jump to the currently loaded station.  The index to which we need to jump is in wCurrentRadioLine.
+	ld a, [wCurrentRadioLine]
+	ld e, a
+	ld d, 0
+	ld hl, RadioJumptable
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+RadioJumptable:
+; entries correspond to constants/radio_constants.asm
+	dw OaksPKMNTalk1  ; $00
+	dw PokedexShow1 ; $01
+	dw BenMonMusic1  ; $02
+	dw LuckyNumberShow1 ; $03
+	dw BuenasPassword1 ; $04
+	dw PeoplePlaces1 ; $05
+	dw FernMonMusic1 ; $06
+	dw RocketRadio1 ; $07
+	dw PokeFluteRadio ; $08
+	dw UnownRadio ; $09
+	dw EvolutionRadio ; $0a
+; OaksPKMNTalk
+	dw OaksPKMNTalk2  ; $0b
+	dw OaksPKMNTalk3  ; $0c
+	dw OaksPKMNTalk4  ; $0d
+	dw OaksPKMNTalk5  ; $0e
+	dw OaksPKMNTalk6  ; $0f
+	dw OaksPKMNTalk7  ; $10
+	dw OaksPKMNTalk8  ; $11
+	dw OaksPKMNTalk9  ; $12
+	dw PokedexShow2 ; $13
+	dw PokedexShow3 ; $14
+	dw PokedexShow4 ; $15
+	dw PokedexShow5 ; $16
+; Ben Music
+	dw BenMonMusic2  ; $17
+	dw BenMonMusic3  ; $18
+	dw BenFernMusic4 ; $19
+	dw BenFernMusic5 ; $1a
+	dw BenFernMusic6 ; $1b
+	dw BenFernMusic7 ; $1c
+	dw FernMonMusic2 ; $1d
+; Lucky Number Show
+	dw LuckyNumberShow2 ; $1e
+	dw LuckyNumberShow3 ; $1f
+	dw LuckyNumberShow4 ; $20
+	dw LuckyNumberShow5 ; $21
+	dw LuckyNumberShow6 ; $22
+	dw LuckyNumberShow7 ; $23
+	dw LuckyNumberShow8 ; $24
+	dw LuckyNumberShow9 ; $25
+	dw LuckyNumberShow10 ; $26
+	dw LuckyNumberShow11 ; $27
+	dw LuckyNumberShow12 ; $28
+	dw LuckyNumberShow13 ; $29
+	dw LuckyNumberShow14 ; $2a
+	dw LuckyNumberShow15 ; $2b
+; People & Places
+	dw PeoplePlaces2 ; $2c
+	dw PeoplePlaces3 ; $2d
+	dw PeoplePlaces4 ; $2e
+	dw PeoplePlaces5 ; $2f
+	dw PeoplePlaces6 ; $30
+	dw PeoplePlaces7 ; $31
+; Rocket Radio
+	dw RocketRadio2 ; $32
+	dw RocketRadio3 ; $33
+	dw RocketRadio4 ; $34
+	dw RocketRadio5 ; $35
+	dw RocketRadio6 ; $36
+	dw RocketRadio7 ; $37
+	dw RocketRadio8 ; $38
+	dw RocketRadio9 ; $39
+	dw RocketRadio10 ; $3a
+; More Pokemon Channel stuff
+	dw OaksPKMNTalk10 ; $3b
+	dw OaksPKMNTalk11 ; $3c
+	dw OaksPKMNTalk12 ; $3d
+	dw OaksPKMNTalk13 ; $3e
+	dw OaksPKMNTalk14 ; $3f
+; Buenas Password
+	dw BuenasPassword2 ; $40
+	dw BuenasPassword3 ; $41
+	dw BuenasPassword4 ; $42
+	dw BuenasPassword5 ; $43
+	dw BuenasPassword6 ; $44
+	dw BuenasPassword7 ; $45
+	dw BuenasPassword8 ; $46
+	dw BuenasPassword9 ; $47
+	dw BuenasPassword10 ; $48
+	dw BuenasPassword11 ; $49
+	dw BuenasPassword12 ; $4a
+	dw BuenasPassword13 ; $4b
+	dw BuenasPassword14 ; $4c
+	dw BuenasPassword15 ; $4d
+	dw BuenasPassword16 ; $4e
+	dw BuenasPassword17 ; $4f
+	dw BuenasPassword18 ; $50
+	dw BuenasPassword19 ; $51
+	dw BuenasPassword20 ; $52
+	dw BuenasPassword21 ; $53
+	dw RadioScroll ; $54
+; More Pokemon Channel stuff
+	dw PokedexShow6 ; $55
+	dw PokedexShow7 ; $56
+	dw PokedexShow8 ; $57
+
+
+PrintRadioLine:
+	ld [wNextRadioLine], a
+	ld hl, wRadioText
+	ld a, [wNumRadioLinesPrinted]
+	cp 2
+	jr nc, .print
+	inc hl
+	ld [hl], TX_START
+	inc a
+	ld [wNumRadioLinesPrinted], a
+	cp 2
+	jr nz, .print
+	bccoord 1, 16
+	call PlaceHLTextAtBC
+	jr .skip
+.print
+	call PrintTextBoxText
+.skip
+	ld a, RADIO_SCROLL
+	ld [wCurrentRadioLine], a
+	ld a, 100
+	ld [wRadioTextDelay], a
+	ret
+
+ReplacePeriodsWithSpaces:
+	push hl
+	ld b, SCREEN_WIDTH * 2
+.loop
+	ld a, [hl]
+	cp "."
+	jr nz, .next
+	ld [hl], " "
+
+.next
+	inc hl
+	dec b
+	jr nz, .loop
+	pop hl
+	ret
+
+RadioScroll:
+	ld hl, wRadioTextDelay
+	ld a, [hl]
+	and a
+	jr z, .proceed
+	dec [hl]
+	ret
+.proceed
+	ld a, [wNextRadioLine]
+	ld [wCurrentRadioLine], a
+	ld a, [wNumRadioLinesPrinted]
+	cp 1
+	call nz, CopyBottomLineToTopLine
+	jp ClearBottomLine
+
+OaksPKMNTalk1:
+	ld a, 5
+	ld [wOaksPKMNTalkSegmentCounter], a
+	call StartRadioStation
+	ld hl, OPT_IntroText1
+	ld a, OAKS_POKEMON_TALK_2
+	jp NextRadioLine
+
+OaksPKMNTalk2:
+	ld hl, OPT_IntroText2
+	ld a, OAKS_POKEMON_TALK_3
+	jp NextRadioLine
+
+OaksPKMNTalk3:
+	ld hl, OPT_IntroText3
+	ld a, OAKS_POKEMON_TALK_4
+	jp NextRadioLine
+
+OaksPKMNTalk4:
+; Choose a random route, and a random Pokemon from that route.
+.sample
+	call Random
+	and %11111
+	cp (OaksPKMNTalkRoutes.End - OaksPKMNTalkRoutes) / 2
+	jr nc, .sample
+	; We now have a number between 0 and 14.
+	ld hl, OaksPKMNTalkRoutes
+	ld c, a
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	ld b, [hl]
+	inc hl
+	ld c, [hl]
+	; bc now contains the chosen map's group and number indices.
+	push bc
+
+	; Search the JohtoGrassWildMons array for the chosen map.
+	ld hl, JohtoGrassWildMons
+.loop
+	ld a, BANK(JohtoGrassWildMons)
+	call GetFarByte
+	cp -1
+	jr z, .overflow
+	inc hl
+	cp b
+	jr nz, .next
+	ld a, BANK(JohtoGrassWildMons)
+	call GetFarByte
+	cp c
+	jr z, .done
+.next
+	dec hl
+	ld de, GRASS_WILDDATA_LENGTH
+	add hl, de
+	jr .loop
+
+.done
+	; Point hl to the list of morning Pokémon., skipping percentages
+rept 4
+	inc hl
+endr
+	; Generate a number, either 0, 1, or 2, to choose a time of day.
+.loop2
+	call Random
+	maskbits NUM_DAYTIMES
+	cp DARKNESS_F
+	jr z, .loop2
+
+	ld bc, 2 * NUM_GRASSMON
+	call AddNTimes
+.loop3
+	; Choose one of the middle three Pokemon.
+	call Random
+	and NUM_GRASSMON
+	cp 2
+	jr c, .loop3
+	cp 5
+	jr nc, .loop3
+	ld e, a
+	ld d, 0
+	add hl, de
+	add hl, de
+	inc hl ; skip level
+	ld a, BANK(JohtoGrassWildMons)
+	call GetFarByte
+	ld [wNamedObjectIndexBuffer], a
+	ld [wCurPartySpecies], a
+	call GetPokemonName
+	ld hl, wStringBuffer1
+	ld de, wMonOrItemNameBuffer
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+
+	; Now that we've chosen our wild Pokemon,
+	; let's recover the map index info and get its name.
+	pop bc
+	call GetWorldMapLocation
+	ld e, a
+	farcall GetLandmarkName
+	ld hl, OPT_OakText1
+	call CopyRadioTextToRAM
+	ld a, OAKS_POKEMON_TALK_5
+	jp PrintRadioLine
+
+.overflow
+	pop bc
+	ld a, OAKS_POKEMON_TALK
+	jp PrintRadioLine
+
+INCLUDE "data/radio/oaks_pkmn_talk_routes.asm"
+
+OaksPKMNTalk5:
+	ld hl, OPT_OakText2
+	ld a, OAKS_POKEMON_TALK_6
+	jp NextRadioLine
+
+OaksPKMNTalk6:
+	ld hl, OPT_OakText3
+	ld a, OAKS_POKEMON_TALK_7
+	jp NextRadioLine
+
+OPT_IntroText1:
+	; MARY: PROF.OAK'S
+	text_jump _OPT_IntroText1
+	db "@"
+
+OPT_IntroText2:
+	; #MON TALK!
+	text_jump _OPT_IntroText2
+	db "@"
+
+OPT_IntroText3:
+	; With me, MARY!
+	text_jump _OPT_IntroText3
+	db "@"
+
+OPT_OakText1:
+	; OAK: @ @
+	text_jump _OPT_OakText1
+	db "@"
+
+OPT_OakText2:
+	; may be seen around
+	text_jump _OPT_OakText2
+	db "@"
+
+OPT_OakText3:
+	; @ .
+	text_jump _OPT_OakText3
+	db "@"
+
+OaksPKMNTalk7:
+	ld a, [wCurPartySpecies]
+	ld [wNamedObjectIndexBuffer], a
+	call GetPokemonName
+	ld hl, OPT_MaryText1
+	ld a, OAKS_POKEMON_TALK_8
+	jp NextRadioLine
+
+OPT_MaryText1:
+	; MARY: @ 's
+	text_jump _OPT_MaryText1
+	db "@"
+
+OaksPKMNTalk8:
+	; 0-15 are all valid indexes into .Adverbs,
+	; so no need for a retry loop
+	call Random
+	maskbits NUM_OAKS_POKEMON_TALK_ADVERBS
+	ld e, a
+	ld d, 0
+	ld hl, .Adverbs
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, OAKS_POKEMON_TALK_9
+	jp NextRadioLine
+
+.Adverbs:
+; there are NUM_OAKS_POKEMON_TALK_ADVERBS entries
+	dw .sweetadorably
+	dw .wigglyslickly
+	dw .aptlynamed
+	dw .undeniablykindof
+	dw .unbearably
+	dw .wowimpressively
+	dw .almostpoisonously
+	dw .sensually
+	dw .mischievously
+	dw .topically
+	dw .addictively
+	dw .looksinwater
+	dw .evolutionmustbe
+	dw .provocatively
+	dw .flippedout
+	dw .heartmeltingly
+
+.sweetadorably
+	; sweet and adorably
+	text_jump OPT_SweetAdorably
+	db "@"
+
+.wigglyslickly
+	; wiggly and slickly
+	text_jump OPT_WigglySlickly
+	db "@"
+
+.aptlynamed
+	; aptly named and
+	text_jump OPT_AptlyNamed
+	db "@"
+
+.undeniablykindof
+	; undeniably kind of
+	text_jump OPT_UndeniablyKindOf
+	db "@"
+
+.unbearably
+	; so, so unbearably
+	text_jump OPT_Unbearably
+	db "@"
+
+.wowimpressively
+	; wow, impressively
+	text_jump OPT_WowImpressively
+	db "@"
+
+.almostpoisonously
+	; almost poisonously
+	text_jump OPT_AlmostPoisonously
+	db "@"
+
+.sensually
+	; ooh, so sensually
+	text_jump OPT_Sensually
+	db "@"
+
+.mischievously
+	; so mischievously
+	text_jump OPT_Mischievously
+	db "@"
+
+.topically
+	; so very topically
+	text_jump OPT_Topically
+	db "@"
+
+.addictively
+	; sure addictively
+	text_jump OPT_Addictively
+	db "@"
+
+.looksinwater
+	; looks in water is
+	text_jump OPT_LooksInWater
+	db "@"
+
+.evolutionmustbe
+	; evolution must be
+	text_jump OPT_EvolutionMustBe
+	db "@"
+
+.provocatively
+	; provocatively
+	text_jump OPT_Provocatively
+	db "@"
+
+.flippedout
+	; so flipped out and
+	text_jump OPT_FlippedOut
+	db "@"
+
+.heartmeltingly
+	; heart-meltingly
+	text_jump OPT_HeartMeltingly
+	db "@"
+
+OaksPKMNTalk9:
+	; 0-15 are all valid indexes into .Adjectives,
+	; so no need for a retry loop
+	call Random
+	maskbits NUM_OAKS_POKEMON_TALK_ADJECTIVES
+	ld e, a
+	ld d, 0
+	ld hl, .Adjectives
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [wOaksPKMNTalkSegmentCounter]
+	dec a
+	ld [wOaksPKMNTalkSegmentCounter], a
+	ld a, OAKS_POKEMON_TALK_4
+	jr nz, .ok
+	ld a, 5
+	ld [wOaksPKMNTalkSegmentCounter], a
+	ld a, OAKS_POKEMON_TALK_10
+.ok
+	jp NextRadioLine
+
+.Adjectives:
+; there are NUM_OAKS_POKEMON_TALK_ADJECTIVES entries
+	dw .cute
+	dw .weird
+	dw .pleasant
+	dw .boldsortof
+	dw .frightening
+	dw .suavedebonair
+	dw .powerful
+	dw .exciting
+	dw .groovy
+	dw .inspiring
+	dw .friendly
+	dw .hothothot
+	dw .stimulating
+	dw .guarded
+	dw .lovely
+	dw .speedy
+
+.cute
+	; cute.
+	text_jump OPT_Cute
+	db "@"
+
+.weird
+	; weird.
+	text_jump OPT_Weird
+	db "@"
+
+.pleasant
+	; pleasant.
+	text_jump OPT_Pleasant
+	db "@"
+
+.boldsortof
+	; bold, sort of.
+	text_jump OPT_BoldSortOf
+	db "@"
+
+.frightening
+	; frightening.
+	text_jump OPT_Frightening
+	db "@"
+
+.suavedebonair
+	; suave & debonair!
+	text_jump OPT_SuaveDebonair
+	db "@"
+
+.powerful
+	; powerful.
+	text_jump OPT_Powerful
+	db "@"
+
+.exciting
+	; exciting.
+	text_jump OPT_Exciting
+	db "@"
+
+.groovy
+	; groovy!
+	text_jump OPT_Groovy
+	db "@"
+
+.inspiring
+	; inspiring.
+	text_jump OPT_Inspiring
+	db "@"
+
+.friendly
+	; friendly.
+	text_jump OPT_Friendly
+	db "@"
+
+.hothothot
+	; hot, hot, hot!
+	text_jump OPT_HotHotHot
+	db "@"
+
+.stimulating
+	; stimulating.
+	text_jump OPT_Stimulating
+	db "@"
+
+.guarded
+	; guarded.
+	text_jump OPT_Guarded
+	db "@"
+
+.lovely
+	; lovely.
+	text_jump OPT_Lovely
+	db "@"
+
+.speedy
+	; speedy.
+	text_jump OPT_Speedy
+	db "@"
+
+OaksPKMNTalk10:
+	farcall RadioMusicRestartPokemonChannel
+	ld hl, OPT_RestartText
+	call PrintText
+	call WaitBGMap
+	ld hl, OPT_PokemonChannelText
+	call PrintText
+	ld a, OAKS_POKEMON_TALK_11
+	ld [wCurrentRadioLine], a
+	ld a, 100
+	ld [wRadioTextDelay], a
+	ret
+
+OPT_PokemonChannelText:
+	; #MON
+	text_jump _OPT_PokemonChannelText
+	db "@"
+
+OPT_RestartText:
+	db "@"
+
+OaksPKMNTalk11:
+	ld hl, wRadioTextDelay
+	dec [hl]
+	ret nz
+	hlcoord 9, 14
+	ld de, .pokemon_string
+	ld a, OAKS_POKEMON_TALK_12
+	jp PlaceRadioString
+
+.pokemon_string
+	db "#MON@"
+
+OaksPKMNTalk12:
+	ld hl, wRadioTextDelay
+	dec [hl]
+	ret nz
+	hlcoord 1, 16
+	ld de, .pokemon_channel_string
+	ld a, OAKS_POKEMON_TALK_13
+	jp PlaceRadioString
+
+.pokemon_channel_string
+	db "#MON Channel@"
+
+OaksPKMNTalk13:
+	ld hl, wRadioTextDelay
+	dec [hl]
+	ret nz
+	hlcoord 12, 16
+	ld de, .terminator
+	ld a, OAKS_POKEMON_TALK_14
+	jp PlaceRadioString
+
+.terminator
+	db "@"
+
+OaksPKMNTalk14:
+	ld hl, wRadioTextDelay
+	dec [hl]
+	ret nz
+	ld de, MUSIC_POKEMON_TALK
+	callfar RadioMusicRestartDE
+	ld hl, .terminator
+	call PrintText
+	ld a, OAKS_POKEMON_TALK_4
+	ld [wNextRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	ld a, RADIO_SCROLL
+	ld [wCurrentRadioLine], a
+	ld a, 10
+	ld [wRadioTextDelay], a
+	ret
+
+.terminator
+	db "@"
+
+PlaceRadioString:
+	ld [wCurrentRadioLine], a
+	ld a, 100
+	ld [wRadioTextDelay], a
+	jp PlaceString
+
+CopyBottomLineToTopLine:
+	hlcoord 0, 15
+	decoord 0, 13
+	ld bc, SCREEN_WIDTH * 2
+	jp CopyBytes
+
+ClearBottomLine:
+	hlcoord 1, 15
+	ld bc, SCREEN_WIDTH - 2
+	ld a, " "
+	call ByteFill
+	hlcoord 1, 16
+	ld bc, SCREEN_WIDTH - 2
+	ld a, " "
+	jp ByteFill
+
+PokedexShow_GetDexEntryBank:
+	push hl
+	push de
+	ld a, [wCurPartySpecies]
+	dec a
+	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)
+
+PokedexShow1:
+	call StartRadioStation
+.loop
+	call Random
+	cp NUM_POKEMON
+	jr nc, .loop
+	ld c, a
+	push bc
+	ld a, c
+	call CheckCaughtMon
+	pop bc
+	jr z, .loop
+	inc c
+	ld a, c
+	ld [wCurPartySpecies], a
+	ld [wNamedObjectIndexBuffer], a
+	call GetPokemonName
+	ld hl, PokedexShowText
+	ld a, POKEDEX_SHOW_2
+	jp NextRadioLine
+
+PokedexShow2:
+	ld a, [wCurPartySpecies]
+	dec a
+	ld hl, PokedexDataPointerTable
+	ld c, a
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	ld a, BANK(PokedexDataPointerTable)
+	call GetFarHalfword
+	call PokedexShow_GetDexEntryBank
+	push af
+	push hl
+	call CopyDexEntryPart1
+	dec hl
+	ld [hl], "<DONE>"
+	ld hl, wPokedexShowPointerAddr
+	call CopyRadioTextToRAM
+	pop hl
+	pop af
+	call CopyDexEntryPart2
+rept 4
+	inc hl
+endr
+	ld a, l
+	ld [wPokedexShowPointerAddr], a
+	ld a, h
+	ld [wPokedexShowPointerAddr + 1], a
+	ld a, POKEDEX_SHOW_3
+	jp PrintRadioLine
+
+PokedexShow3:
+	call CopyDexEntry
+	ld a, POKEDEX_SHOW_4
+	jp PrintRadioLine
+
+PokedexShow4:
+	call CopyDexEntry
+	ld a, POKEDEX_SHOW_5
+	jp PrintRadioLine
+
+PokedexShow5:
+	call CopyDexEntry
+	ld a, POKEDEX_SHOW_6
+	jp PrintRadioLine
+
+PokedexShow6:
+	call CopyDexEntry
+	ld a, POKEDEX_SHOW_7
+	jp PrintRadioLine
+
+PokedexShow7:
+	call CopyDexEntry
+	ld a, POKEDEX_SHOW_8
+	jp PrintRadioLine
+
+PokedexShow8:
+	call CopyDexEntry
+	ld a, POKEDEX_SHOW
+	jp PrintRadioLine
+
+CopyDexEntry:
+	ld a, [wPokedexShowPointerAddr]
+	ld l, a
+	ld a, [wPokedexShowPointerAddr + 1]
+	ld h, a
+	ld a, [wPokedexShowPointerBank]
+	push af
+	push hl
+	call CopyDexEntryPart1
+	dec hl
+	ld [hl], "<DONE>"
+	ld hl, wPokedexShowPointerAddr
+	call CopyRadioTextToRAM
+	pop hl
+	pop af
+	call CopyDexEntryPart2
+	ret
+
+CopyDexEntryPart1:
+	ld de, wPokedexShowPointerBank
+	ld bc, SCREEN_WIDTH - 1
+	call FarCopyBytes
+	ld hl, wPokedexShowPointerAddr
+	ld [hl], TX_START
+	inc hl
+	ld [hl], "<LINE>"
+	inc hl
+.loop
+	ld a, [hli]
+	cp "@"
+	ret z
+	cp "<NEXT>"
+	ret z
+	cp "<DEXEND>"
+	ret z
+	jr .loop
+
+CopyDexEntryPart2:
+	ld d, a
+.loop
+	ld a, d
+	call GetFarByte
+	inc hl
+	cp "@"
+	jr z, .okay
+	cp "<NEXT>"
+	jr z, .okay
+	cp "<DEXEND>"
+	jr nz, .loop
+.okay
+	ld a, l
+	ld [wPokedexShowPointerAddr], a
+	ld a, h
+	ld [wPokedexShowPointerAddr + 1], a
+	ld a, d
+	ld [wPokedexShowPointerBank], a
+	ret
+
+PokedexShowText:
+	; @ @
+	text_jump _PokedexShowText
+	db "@"
+
+BenMonMusic1:
+	call StartPokemonMusicChannel
+	ld hl, BenIntroText1
+	ld a, POKEMON_MUSIC_2
+	jp NextRadioLine
+
+BenMonMusic2:
+	ld hl, BenIntroText2
+	ld a, POKEMON_MUSIC_3
+	jp NextRadioLine
+
+BenMonMusic3:
+	ld hl, BenIntroText3
+	ld a, POKEMON_MUSIC_4
+	jp NextRadioLine
+
+FernMonMusic1:
+	call StartPokemonMusicChannel
+	ld hl, FernIntroText1
+	ld a, LETS_ALL_SING_2
+	jp NextRadioLine
+
+FernMonMusic2:
+	ld hl, FernIntroMusic2
+	ld a, POKEMON_MUSIC_4
+	jp NextRadioLine
+
+BenFernMusic4:
+	ld hl, BenFernText1
+	ld a, POKEMON_MUSIC_5
+	jp NextRadioLine
+
+BenFernMusic5:
+	call GetWeekday
+	and 1
+	ld hl, BenFernText2A
+	jr z, .SunTueThurSun
+	ld hl, BenFernText2B
+.SunTueThurSun:
+	ld a, POKEMON_MUSIC_6
+	jp NextRadioLine
+
+BenFernMusic6:
+	call GetWeekday
+	and 1
+	ld hl, BenFernText3A
+	jr z, .SunTueThurSun
+	ld hl, BenFernText3B
+.SunTueThurSun:
+	ld a, POKEMON_MUSIC_7
+	jp NextRadioLine
+
+BenFernMusic7:
+	ret
+
+StartPokemonMusicChannel:
+	call RadioTerminator
+	call PrintText
+	ld de, MUSIC_POKEMON_MARCH
+	call GetWeekday
+	and 1
+	jr z, .SunTueThurSun
+	ld de, MUSIC_POKEMON_LULLABY
+.SunTueThurSun:
+	callfar RadioMusicRestartDE
+	ret
+
+BenIntroText1:
+	; BEN: #MON MUSIC
+	text_jump _BenIntroText1
+	db "@"
+
+BenIntroText2:
+	; CHANNEL!
+	text_jump _BenIntroText2
+	db "@"
+
+BenIntroText3:
+	; It's me, DJ BEN!
+	text_jump _BenIntroText3
+	db "@"
+
+FernIntroText1:
+	; FERN: #MUSIC!
+	text_jump _FernIntroText1
+	db "@"
+
+FernIntroMusic2:
+	; With DJ FERN!
+	text_jump _FernIntroText2
+	db "@"
+
+BenFernText1:
+	; Today's @ ,
+	text_jump _BenFernText1
+	db "@"
+
+BenFernText2A:
+	; so let us jam to
+	text_jump _BenFernText2A
+	db "@"
+
+BenFernText2B:
+	; so chill out to
+	text_jump _BenFernText2B
+	db "@"
+
+BenFernText3A:
+	; #MON March!
+	text_jump _BenFernText3A
+	db "@"
+
+BenFernText3B:
+	; #MON Lullaby!
+	text_jump _BenFernText3B
+	db "@"
+
+LuckyNumberShow1:
+	call StartRadioStation
+	callfar CheckLuckyNumberShowFlag
+	jr nc, .dontreset
+	callfar ResetLuckyNumberShowFlag
+.dontreset
+	ld hl, LC_Text1
+	ld a, LUCKY_NUMBER_SHOW_2
+	jp NextRadioLine
+
+LuckyNumberShow2:
+	ld hl, LC_Text2
+	ld a, LUCKY_NUMBER_SHOW_3
+	jp NextRadioLine
+
+LuckyNumberShow3:
+	ld hl, LC_Text3
+	ld a, LUCKY_NUMBER_SHOW_4
+	jp NextRadioLine
+
+LuckyNumberShow4:
+	ld hl, LC_Text4
+	ld a, LUCKY_NUMBER_SHOW_5
+	jp NextRadioLine
+
+LuckyNumberShow5:
+	ld hl, LC_Text5
+	ld a, LUCKY_NUMBER_SHOW_6
+	jp NextRadioLine
+
+LuckyNumberShow6:
+	ld hl, LC_Text6
+	ld a, LUCKY_NUMBER_SHOW_7
+	jp NextRadioLine
+
+LuckyNumberShow7:
+	ld hl, LC_Text7
+	ld a, LUCKY_NUMBER_SHOW_8
+	jp NextRadioLine
+
+LuckyNumberShow8:
+	ld hl, wStringBuffer1
+	ld de, wLuckyIDNumber
+	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+	call PrintNum
+	ld a, "@"
+	ld [wStringBuffer1 + 5], a
+	ld hl, LC_Text8
+	ld a, LUCKY_NUMBER_SHOW_9
+	jp NextRadioLine
+
+LuckyNumberShow9:
+	ld hl, LC_Text9
+	ld a, LUCKY_NUMBER_SHOW_10
+	jp NextRadioLine
+
+LuckyNumberShow10:
+	ld hl, LC_Text7
+	ld a, LUCKY_NUMBER_SHOW_11
+	jp NextRadioLine
+
+LuckyNumberShow11:
+	ld hl, LC_Text8
+	ld a, LUCKY_NUMBER_SHOW_12
+	jp NextRadioLine
+
+LuckyNumberShow12:
+	ld hl, LC_Text10
+	ld a, LUCKY_NUMBER_SHOW_13
+	jp NextRadioLine
+
+LuckyNumberShow13:
+	ld hl, LC_Text11
+	call Random
+	and a
+	ld a, LUCKY_CHANNEL
+	jr nz, .okay
+	ld a, LUCKY_NUMBER_SHOW_14
+.okay
+	jp NextRadioLine
+
+LuckyNumberShow14:
+	ld hl, LC_DragText1
+	ld a, LUCKY_NUMBER_SHOW_15
+	jp NextRadioLine
+
+LuckyNumberShow15:
+	ld hl, LC_DragText2
+	ld a, LUCKY_CHANNEL
+	jp NextRadioLine
+
+LC_Text1:
+	; REED: Yeehaw! How
+	text_jump _LC_Text1
+	db "@"
+
+LC_Text2:
+	; y'all doin' now?
+	text_jump _LC_Text2
+	db "@"
+
+LC_Text3:
+	; Whether you're up
+	text_jump _LC_Text3
+	db "@"
+
+LC_Text4:
+	; or way down low,
+	text_jump _LC_Text4
+	db "@"
+
+LC_Text5:
+	; don't you miss the
+	text_jump _LC_Text5
+	db "@"
+
+LC_Text6:
+	; LUCKY NUMBER SHOW!
+	text_jump _LC_Text6
+	db "@"
+
+LC_Text7:
+	; This week's Lucky
+	text_jump _LC_Text7
+	db "@"
+
+LC_Text8:
+	; Number is @ !
+	text_jump _LC_Text8
+	db "@"
+
+LC_Text9:
+	; I'll repeat that!
+	text_jump _LC_Text9
+	db "@"
+
+LC_Text10:
+	; Match it and go to
+	text_jump _LC_Text10
+	db "@"
+
+LC_Text11:
+	; the RADIO TOWER!
+	text_jump _LC_Text11
+	db "@"
+
+LC_DragText1:
+	; …Repeating myself
+	text_jump _LC_DragText1
+	db "@"
+
+LC_DragText2:
+	; gets to be a drag…
+	text_jump _LC_DragText2
+	db "@"
+
+PeoplePlaces1:
+	call StartRadioStation
+	ld hl, PnP_Text1
+	ld a, PLACES_AND_PEOPLE_2
+	jp NextRadioLine
+
+PeoplePlaces2:
+	ld hl, PnP_Text2
+	ld a, PLACES_AND_PEOPLE_3
+	jp NextRadioLine
+
+PeoplePlaces3:
+	ld hl, PnP_Text3
+	call Random
+	cp 49 percent - 1
+	ld a, PLACES_AND_PEOPLE_4 ; People
+	jr c, .ok
+	ld a, PLACES_AND_PEOPLE_6 ; Places
+.ok
+	jp NextRadioLine
+
+PnP_Text1:
+	; PLACES AND PEOPLE!
+	text_jump _PnP_Text1
+	db "@"
+
+PnP_Text2:
+	; Brought to you by
+	text_jump _PnP_Text2
+	db "@"
+
+PnP_Text3:
+	; me, DJ LILY!
+	text_jump _PnP_Text3
+	db "@"
+
+PeoplePlaces4: ; People
+	call Random
+	maskbits NUM_TRAINER_CLASSES
+	inc a
+	cp NUM_TRAINER_CLASSES - 1
+	jr nc, PeoplePlaces4
+	push af
+	ld hl, PnP_HiddenPeople
+	ld a, [wStatusFlags]
+	bit STATUSFLAGS_HALL_OF_FAME_F, a
+	jr z, .ok
+	ld hl, PnP_HiddenPeople_BeatE4
+	ld a, [wKantoBadges]
+	cp %11111111 ; all badges
+	jr nz, .ok
+	ld hl, PnP_HiddenPeople_BeatKanto
+.ok
+	pop af
+	ld c, a
+	ld de, 1
+	push bc
+	call IsInArray
+	pop bc
+	jr c, PeoplePlaces4
+	push bc
+	callfar GetTrainerClassName
+	ld de, wStringBuffer1
+	call CopyName1
+	pop bc
+	ld b, 1
+	callfar GetTrainerName
+	ld hl, PnP_Text4
+	ld a, PLACES_AND_PEOPLE_5
+	jp NextRadioLine
+
+INCLUDE "data/radio/pnp_hidden_people.asm"
+
+PnP_Text4:
+	; @  @ @
+	text_jump _PnP_Text4
+	db "@"
+
+PeoplePlaces5:
+	; 0-15 are all valid indexes into .Adjectives,
+	; so no need for a retry loop
+	call Random
+	maskbits NUM_PNP_PEOPLE_ADJECTIVES
+	ld e, a
+	ld d, 0
+	ld hl, .Adjectives
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	call Random
+	cp 4 percent
+	ld a, PLACES_AND_PEOPLE
+	jr c, .ok
+	call Random
+	cp 49 percent - 1
+	ld a, PLACES_AND_PEOPLE_4 ; People
+	jr c, .ok
+	ld a, PLACES_AND_PEOPLE_6 ; Places
+.ok
+	jp NextRadioLine
+
+.Adjectives:
+; there are NUM_PNP_PEOPLE_ADJECTIVES entries
+	dw PnP_cute
+	dw PnP_lazy
+	dw PnP_happy
+	dw PnP_noisy
+	dw PnP_precocious
+	dw PnP_bold
+	dw PnP_picky
+	dw PnP_sortofok
+	dw PnP_soso
+	dw PnP_great
+	dw PnP_mytype
+	dw PnP_cool
+	dw PnP_inspiring
+	dw PnP_weird
+	dw PnP_rightforme
+	dw PnP_odd
+
+PnP_cute:
+	; is cute.
+	text_jump _PnP_cute
+	db "@"
+
+PnP_lazy:
+	; is sort of lazy.
+	text_jump _PnP_lazy
+	db "@"
+
+PnP_happy:
+	; is always happy.
+	text_jump _PnP_happy
+	db "@"
+
+PnP_noisy:
+	; is quite noisy.
+	text_jump _PnP_noisy
+	db "@"
+
+PnP_precocious:
+	; is precocious.
+	text_jump _PnP_precocious
+	db "@"
+
+PnP_bold:
+	; is somewhat bold.
+	text_jump _PnP_bold
+	db "@"
+
+PnP_picky:
+	; is too picky!
+	text_jump _PnP_picky
+	db "@"
+
+PnP_sortofok:
+	; is sort of OK.
+	text_jump _PnP_sortofok
+	db "@"
+
+PnP_soso:
+	; is just so-so.
+	text_jump _PnP_soso
+	db "@"
+
+PnP_great:
+	; is actually great.
+	text_jump _PnP_great
+	db "@"
+
+PnP_mytype:
+	; is just my type.
+	text_jump _PnP_mytype
+	db "@"
+
+PnP_cool:
+	; is so cool, no?
+	text_jump _PnP_cool
+	db "@"
+
+PnP_inspiring:
+	; is inspiring!
+	text_jump _PnP_inspiring
+	db "@"
+
+PnP_weird:
+	; is kind of weird.
+	text_jump _PnP_weird
+	db "@"
+
+PnP_rightforme:
+	; is right for me?
+	text_jump _PnP_rightforme
+	db "@"
+
+PnP_odd:
+	; is definitely odd!
+	text_jump _PnP_odd
+	db "@"
+
+PeoplePlaces6: ; Places
+	call Random
+	cp (PnP_HiddenPlaces.End - PnP_HiddenPlaces) / 2
+	jr nc, PeoplePlaces6
+	ld hl, PnP_HiddenPlaces
+	ld c, a
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	ld b, [hl]
+	inc hl
+	ld c, [hl]
+	call GetWorldMapLocation
+	ld e, a
+	farcall GetLandmarkName
+	ld hl, PnP_Text5
+	ld a, PLACES_AND_PEOPLE_7
+	jp NextRadioLine
+
+INCLUDE "data/radio/pnp_hidden_places.asm"
+
+PnP_Text5:
+	; @ @
+	text_jump _PnP_Text5
+	db "@"
+
+PeoplePlaces7:
+	; 0-15 are all valid indexes into .Adjectives,
+	; so no need for a retry loop
+	call Random
+	maskbits NUM_PNP_PLACES_ADJECTIVES
+	ld e, a
+	ld d, 0
+	ld hl, .Adjectives
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	call CopyRadioTextToRAM
+	call Random
+	cp 4 percent
+	ld a, PLACES_AND_PEOPLE
+	jr c, .ok
+	call Random
+	cp 49 percent - 1
+	ld a, PLACES_AND_PEOPLE_4 ; People
+	jr c, .ok
+	ld a, PLACES_AND_PEOPLE_6 ; Places
+.ok
+	jp PrintRadioLine
+
+.Adjectives:
+; there are NUM_PNP_PLACES_ADJECTIVES entries
+	dw PnP_cute
+	dw PnP_lazy
+	dw PnP_happy
+	dw PnP_noisy
+	dw PnP_precocious
+	dw PnP_bold
+	dw PnP_picky
+	dw PnP_sortofok
+	dw PnP_soso
+	dw PnP_great
+	dw PnP_mytype
+	dw PnP_cool
+	dw PnP_inspiring
+	dw PnP_weird
+	dw PnP_rightforme
+	dw PnP_odd
+
+RocketRadio1:
+	call StartRadioStation
+	ld hl, RocketRadioText1
+	ld a, ROCKET_RADIO_2
+	jp NextRadioLine
+
+RocketRadio2:
+	ld hl, RocketRadioText2
+	ld a, ROCKET_RADIO_3
+	jp NextRadioLine
+
+RocketRadio3:
+	ld hl, RocketRadioText3
+	ld a, ROCKET_RADIO_4
+	jp NextRadioLine
+
+RocketRadio4:
+	ld hl, RocketRadioText4
+	ld a, ROCKET_RADIO_5
+	jp NextRadioLine
+
+RocketRadio5:
+	ld hl, RocketRadioText5
+	ld a, ROCKET_RADIO_6
+	jp NextRadioLine
+
+RocketRadio6:
+	ld hl, RocketRadioText6
+	ld a, ROCKET_RADIO_7
+	jp NextRadioLine
+
+RocketRadio7:
+	ld hl, RocketRadioText7
+	ld a, ROCKET_RADIO_8
+	jp NextRadioLine
+
+RocketRadio8:
+	ld hl, RocketRadioText8
+	ld a, ROCKET_RADIO_9
+	jp NextRadioLine
+
+RocketRadio9:
+	ld hl, RocketRadioText9
+	ld a, ROCKET_RADIO_10
+	jp NextRadioLine
+
+RocketRadio10:
+	ld hl, RocketRadioText10
+	ld a, ROCKET_RADIO
+	jp NextRadioLine
+
+RocketRadioText1:
+	; … …Ahem, we are
+	text_jump _RocketRadioText1
+	db "@"
+
+RocketRadioText2:
+	; TEAM ROCKET!
+	text_jump _RocketRadioText2
+	db "@"
+
+RocketRadioText3:
+	; After three years
+	text_jump _RocketRadioText3
+	db "@"
+
+RocketRadioText4:
+	; of preparation, we
+	text_jump _RocketRadioText4
+	db "@"
+
+RocketRadioText5:
+	; have risen again
+	text_jump _RocketRadioText5
+	db "@"
+
+RocketRadioText6:
+	; from the ashes!
+	text_jump _RocketRadioText6
+	db "@"
+
+RocketRadioText7:
+	; GIOVANNI! @ Can you
+	text_jump _RocketRadioText7
+	db "@"
+
+RocketRadioText8:
+	; hear?@  We did it!
+	text_jump _RocketRadioText8
+	db "@"
+
+RocketRadioText9:
+	; @ Where is our boss?
+	text_jump _RocketRadioText9
+	db "@"
+
+RocketRadioText10:
+	; @ Is he listening?
+	text_jump _RocketRadioText10
+	db "@"
+
+PokeFluteRadio:
+	call StartRadioStation
+	ld a, 1
+	ld [wNumRadioLinesPrinted], a
+	ret
+
+UnownRadio:
+	call StartRadioStation
+	ld a, 1
+	ld [wNumRadioLinesPrinted], a
+	ret
+
+EvolutionRadio:
+	call StartRadioStation
+	ld a, 1
+	ld [wNumRadioLinesPrinted], a
+	ret
+
+BuenasPassword1:
+; Determine if we need to be here
+	call BuenasPasswordCheckTime
+	jp nc, .PlayPassword
+	ld a, [wNumRadioLinesPrinted]
+	and a
+	jp z, BuenasPassword20
+	jp BuenasPassword8
+
+.PlayPassword:
+	call StartRadioStation
+	ld a, [hBGMapMode]
+	push af
+	xor a
+	ld [hBGMapMode], a
+	ld de, BuenasPasswordChannelName
+	hlcoord 2, 9
+	call PlaceString
+	pop af
+	ld [hBGMapMode], a
+	ld hl, BuenaRadioText1
+	ld a, BUENAS_PASSWORD_2
+	jp NextRadioLine
+
+BuenasPassword2:
+	ld hl, BuenaRadioText2
+	ld a, BUENAS_PASSWORD_3
+	jp NextRadioLine
+
+BuenasPassword3:
+	call BuenasPasswordCheckTime
+	ld hl, BuenaRadioText3
+	jp c, BuenasPasswordAfterMidnight
+	ld a, BUENAS_PASSWORD_4
+	jp NextRadioLine
+
+BuenasPassword4:
+	call BuenasPasswordCheckTime
+	jp c, BuenasPassword8
+	ld a, [wBuenasPassword]
+; If we already generated the password today, we don't need to generate a new one.
+	ld hl, wWeeklyFlags
+	bit WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
+	jr nz, .AlreadyGotIt
+; There are only 11 groups to choose from.
+.greater_than_11
+	call Random
+	maskbits NUM_PASSWORD_CATEGORIES
+	cp NUM_PASSWORD_CATEGORIES
+	jr nc, .greater_than_11
+; Store it in the high nybble of e.
+	swap a
+	ld e, a
+; For each group, choose one of the three passwords.
+.greater_than_three
+	call Random
+	maskbits NUM_PASSWORDS_PER_CATEGORY
+	cp NUM_PASSWORDS_PER_CATEGORY
+	jr nc, .greater_than_three
+; The high nybble of wBuenasPassword will now contain the password group index, and the low nybble contains the actual password.
+	add e
+	ld [wBuenasPassword], a
+; Set the flag so that we don't generate a new password this week.
+	ld hl, wWeeklyFlags
+	set WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
+.AlreadyGotIt:
+	ld c, a
+	call GetBuenasPassword
+	ld hl, BuenaRadioText4
+	ld a, BUENAS_PASSWORD_5
+	jp NextRadioLine
+
+GetBuenasPassword:
+; The password indices are held in c.  High nybble contains the group index, low nybble contains the word index.
+; Load the password group pointer in hl.
+	ld a, c
+	swap a
+	and $f
+	ld hl, BuenasPasswordTable
+	ld d, 0
+	ld e, a
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+; Get the password type and store it in b.
+	ld a, [hli]
+	ld b, a
+	push hl
+	inc hl
+; Get the password index.
+	ld a, c
+	and $f
+	ld c, a
+	push hl
+	ld hl, .StringFunctionJumpTable
+	ld e, b
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	pop de ; de now contains the pointer to the value of this week's password, in Blue Card Points.
+	call _hl_
+	pop hl
+	ld c, [hl]
+	ret
+
+.StringFunctionJumpTable:
+; entries correspond to BUENA_* constants
+	dw .Mon       ; BUENA_MON
+	dw .Item      ; BUENA_ITEM
+	dw .Move      ; BUENA_MOVE
+	dw .RawString ; BUENA_STRING
+
+.Mon:
+	call .GetTheIndex
+	call GetPokemonName
+	ret
+
+.Item:
+	call .GetTheIndex
+	call GetItemName
+	ret
+
+.Move:
+	call .GetTheIndex
+	call GetMoveName
+	ret
+
+.GetTheIndex:
+	ld h, 0
+	ld l, c
+	add hl, de
+	ld a, [hl]
+	ld [wNamedObjectIndexBuffer], a
+	ret
+
+.RawString:
+; Get the string from the table...
+	ld a, c
+	and a
+	jr z, .skip
+.read_loop
+	ld a, [de]
+	inc de
+	cp "@"
+	jr nz, .read_loop
+	dec c
+	jr nz, .read_loop
+; ... and copy it into wStringBuffer1.
+.skip
+	ld hl, wStringBuffer1
+.copy_loop
+	ld a, [de]
+	inc de
+	ld [hli], a
+	cp "@"
+	jr nz, .copy_loop
+	ld de, wStringBuffer1
+	ret
+
+INCLUDE "data/radio/buenas_passwords.asm"
+
+BuenasPassword5:
+	ld hl, BuenaRadioText5
+	ld a, BUENAS_PASSWORD_6
+	jp NextRadioLine
+
+BuenasPassword6:
+	ld hl, BuenaRadioText6
+	ld a, BUENAS_PASSWORD_7
+	jp NextRadioLine
+
+BuenasPassword7:
+	call BuenasPasswordCheckTime
+	ld hl, BuenaRadioText7
+	jr c, BuenasPasswordAfterMidnight
+	ld a, BUENAS_PASSWORD
+	jp NextRadioLine
+
+BuenasPasswordAfterMidnight:
+	push hl
+	ld hl, wWeeklyFlags
+	res WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
+	pop hl
+	ld a, BUENAS_PASSWORD_8
+	jp NextRadioLine
+
+BuenasPassword8:
+	ld hl, wWeeklyFlags
+	res WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
+	ld hl, BuenaRadioMidnightText10
+	ld a, BUENAS_PASSWORD_9
+	jp NextRadioLine
+
+BuenasPassword9:
+	ld hl, BuenaRadioMidnightText1
+	ld a, BUENAS_PASSWORD_10
+	jp NextRadioLine
+
+BuenasPassword10:
+	ld hl, BuenaRadioMidnightText2
+	ld a, BUENAS_PASSWORD_11
+	jp NextRadioLine
+
+BuenasPassword11:
+	ld hl, BuenaRadioMidnightText3
+	ld a, BUENAS_PASSWORD_12
+	jp NextRadioLine
+
+BuenasPassword12:
+	ld hl, BuenaRadioMidnightText4
+	ld a, BUENAS_PASSWORD_13
+	jp NextRadioLine
+
+BuenasPassword13:
+	ld hl, BuenaRadioMidnightText5
+	ld a, BUENAS_PASSWORD_14
+	jp NextRadioLine
+
+BuenasPassword14:
+	ld hl, BuenaRadioMidnightText6
+	ld a, BUENAS_PASSWORD_15
+	jp NextRadioLine
+
+BuenasPassword15:
+	ld hl, BuenaRadioMidnightText7
+	ld a, BUENAS_PASSWORD_16
+	jp NextRadioLine
+
+BuenasPassword16:
+	ld hl, BuenaRadioMidnightText8
+	ld a, BUENAS_PASSWORD_17
+	jp NextRadioLine
+
+BuenasPassword17:
+	ld hl, BuenaRadioMidnightText9
+	ld a, BUENAS_PASSWORD_18
+	jp NextRadioLine
+
+BuenasPassword18:
+	ld hl, BuenaRadioMidnightText10
+	ld a, BUENAS_PASSWORD_19
+	jp NextRadioLine
+
+BuenasPassword19:
+	ld hl, BuenaRadioMidnightText10
+	ld a, BUENAS_PASSWORD_20
+	jp NextRadioLine
+
+BuenasPassword20:
+	ld a, [hBGMapMode]
+	push af
+	farcall NoRadioMusic
+	farcall NoRadioName
+	pop af
+	ld [hBGMapMode], a
+	ld hl, wWeeklyFlags
+	res WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
+	ld a, BUENAS_PASSWORD
+	ld [wCurrentRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	ld hl, BuenaOffTheAirText
+	ld a, BUENAS_PASSWORD_21
+	jp NextRadioLine
+
+BuenasPassword21:
+	ld a, BUENAS_PASSWORD
+	ld [wCurrentRadioLine], a
+	xor a
+	ld [wNumRadioLinesPrinted], a
+	call BuenasPasswordCheckTime
+	jp nc, BuenasPassword1
+	ld hl, BuenaOffTheAirText
+	ld a, BUENAS_PASSWORD_21
+	jp NextRadioLine
+
+BuenasPasswordCheckTime:
+	call UpdateTime
+	ld a, [hHours]
+	cp NITE_HOUR
+	ret
+
+BuenasPasswordChannelName:
+	db "BUENA'S PASSWORD@"
+
+BuenaRadioText1:
+	; BUENA: BUENA here!
+	text_jump _BuenaRadioText1
+	db "@"
+
+BuenaRadioText2:
+	; Today's password!
+	text_jump _BuenaRadioText2
+	db "@"
+
+BuenaRadioText3:
+	; Let me think… It's
+	text_jump _BuenaRadioText3
+	db "@"
+
+BuenaRadioText4:
+	; @ !
+	text_jump _BuenaRadioText4
+	db "@"
+
+BuenaRadioText5:
+	; Don't forget it!
+	text_jump _BuenaRadioText5
+	db "@"
+
+BuenaRadioText6:
+	; I'm in GOLDENROD's
+	text_jump _BuenaRadioText6
+	db "@"
+
+BuenaRadioText7:
+	; RADIO TOWER!
+	text_jump _BuenaRadioText7
+	db "@"
+
+BuenaRadioMidnightText1:
+	; BUENA: Oh my…
+	text_jump _BuenaRadioMidnightText1
+	db "@"
+
+BuenaRadioMidnightText2:
+	; It's midnight! I
+	text_jump _BuenaRadioMidnightText2
+	db "@"
+
+BuenaRadioMidnightText3:
+	; have to shut down!
+	text_jump _BuenaRadioMidnightText3
+	db "@"
+
+BuenaRadioMidnightText4:
+	; Thanks for tuning
+	text_jump _BuenaRadioMidnightText4
+	db "@"
+
+BuenaRadioMidnightText5:
+	; in to the end! But
+	text_jump _BuenaRadioMidnightText5
+	db "@"
+
+BuenaRadioMidnightText6:
+	; don't stay up too
+	text_jump _BuenaRadioMidnightText6
+	db "@"
+
+BuenaRadioMidnightText7:
+	; late! Presented to
+	text_jump _BuenaRadioMidnightText7
+	db "@"
+
+BuenaRadioMidnightText8:
+	; you by DJ BUENA!
+	text_jump _BuenaRadioMidnightText8
+	db "@"
+
+BuenaRadioMidnightText9:
+	; I'm outta here!
+	text_jump _BuenaRadioMidnightText9
+	db "@"
+
+BuenaRadioMidnightText10:
+	; …
+	text_jump _BuenaRadioMidnightText10
+	db "@"
+
+BuenaOffTheAirText:
+	;
+	text_jump _BuenaOffTheAirText
+	db "@"
+
+CopyRadioTextToRAM:
+	ld a, [hl]
+	cp TX_FAR
+	jp z, FarCopyRadioText
+	ld de, wRadioText
+	ld bc, SCREEN_WIDTH * 2
+	jp CopyBytes
+
+StartRadioStation:
+	ld a, [wNumRadioLinesPrinted]
+	and a
+	ret nz
+	call RadioTerminator
+	call PrintText
+	ld hl, RadioChannelSongs
+	ld a, [wCurrentRadioLine]
+	ld c, a
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	callfar RadioMusicRestartDE
+	ret
+
+INCLUDE "data/radio/channel_music.asm"
+
+NextRadioLine:
+	push af
+	call CopyRadioTextToRAM
+	pop af
+	jp PrintRadioLine
--- /dev/null
+++ b/engine/pokemon/billspc.asm
@@ -1,0 +1,2618 @@
+_DepositPKMN: ; e2391 (38:6391)
+	ld hl, wOptions
+	ld a, [hl]
+	push af
+	set 4, [hl]
+	ld a, [wVramState]
+	push af
+	xor a
+	ld [wVramState], a
+	ld a, [hInMenu]
+	push af
+	ld a, $1
+	ld [hInMenu], a
+	xor a
+	ld [hMapAnims], a
+	call BillsPC_InitRAM
+	xor a
+	ld [wBillsPC_LoadedBox], a
+	call DelayFrame
+.loop
+	call JoyTextDelay
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .done
+	call .RunJumptable
+	call DelayFrame
+	jr .loop
+.done
+	call ClearSprites
+	pop af
+	ld [hInMenu], a
+	pop af
+	ld [wVramState], a
+	pop af
+	ld [wOptions], a
+	ret
+
+.RunJumptable: ; e23d5 (38:63d5)
+	ld a, [wJumptableIndex]
+	ld hl, .Jumptable
+	call BillsPC_Jumptable
+	jp hl
+
+.Jumptable: ; e23df (38:63df)
+	dw .Init
+	dw .HandleJoypad
+	dw .WhatsUp
+	dw .Submenu
+	dw BillsPC_EndJumptableLoop
+
+.Init: ; e23e9 (38:63e9)
+	xor a
+	ld [hBGMapMode], a
+	call ClearSprites
+	call CopyBoxmonSpecies
+	call BillsPC_BoxName
+	ld de, PCString_ChooseaPKMN
+	call BillsPC_PlaceString
+	ld a, $5
+	ld [wBillsPC_NumMonsOnScreen], a
+	call BillsPC_RefreshTextboxes
+	call PCMonInfo
+	ld a, $ff
+	ld [wCurPartySpecies], a
+	ld a, SCGB_BILLS_PC
+	call BillsPC_ApplyPalettes
+	call WaitBGMap
+	call BillsPC_UpdateSelectionCursor
+	call BillsPC_IncrementJumptableIndex
+	ret
+
+.HandleJoypad: ; e241a (38:641a)
+	ld hl, hJoyPressed ; $ffa7
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .b_button
+	ld a, [hl]
+	and A_BUTTON
+	jr nz, .a_button
+	call Withdraw_UpDown
+	and a
+	ret z
+	call BillsPC_UpdateSelectionCursor
+	xor a
+	ld [hBGMapMode], a
+	call BillsPC_RefreshTextboxes
+	call PCMonInfo
+	ld a, $1
+	ld [hBGMapMode], a
+	call DelayFrame
+	call DelayFrame
+	ret
+
+.a_button
+	call BillsPC_GetSelectedPokemonSpecies
+	and a
+	ret z
+	cp -1
+	jr z, .b_button
+	ld a, $2
+	ld [wJumptableIndex], a
+	ret
+; e2452 (38:6452)
+
+.go_back
+	ld hl, wJumptableIndex
+	dec [hl]
+	ret
+
+.b_button
+	ld a, $4
+	ld [wJumptableIndex], a
+	ret
+
+.WhatsUp: ; e245d (38:645d)
+	xor a
+	ld [hBGMapMode], a
+	call ClearSprites
+	call BillsPC_GetSelectedPokemonSpecies
+	ld [wCurPartySpecies], a
+	ld a, SCGB_BILLS_PC
+	call BillsPC_ApplyPalettes
+	ld de, PCString_WhatsUp
+	call BillsPC_PlaceString
+	ld a, $1
+	ld [wMenuCursorY], a
+	call BillsPC_IncrementJumptableIndex
+	ret
+
+.Submenu: ; e247d (38:647d)
+	ld hl, BillsPCDepositMenuHeader
+	call CopyMenuHeader
+	ld a, [wMenuCursorY]
+	call StoreTo_wMenuCursorBuffer
+	call VerticalMenu
+	jp c, BillsPCDepositFuncCancel
+	ld a, [wMenuCursorY]
+	dec a
+	and %11
+	ld e, a
+	ld d, 0
+	ld hl, BillsPCDepositJumptable
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+BillsPCDepositJumptable: ; e24a1 (38:64a1)
+	dw BillsPCDepositFuncDeposit ; Deposit Pokemon
+	dw BillsPCDepositFuncStats ; Pokemon Stats
+	dw BillsPCDepositFuncRelease ; Release Pokemon
+	dw BillsPCDepositFuncCancel ; Cancel
+
+
+BillsPCDepositFuncDeposit: ; e24a9 (38:64a9)
+	call BillsPC_CheckMail_PreventBlackout
+	jp c, BillsPCDepositFuncCancel
+	call DepositPokemon
+	jr c, .box_full
+	ld a, $0
+	ld [wJumptableIndex], a
+	xor a
+	ld [wBillsPC_CursorPosition], a
+	ld [wBillsPC_ScrollPosition], a
+	ret
+
+.box_full
+	ld de, PCString_WhatsUp
+	call BillsPC_PlaceString
+	ret
+
+BillsPCDepositFuncStats: ; e24c8 (38:64c8)
+	call LoadStandardMenuHeader
+	call BillsPC_StatsScreen
+	call ExitMenu
+	call PCMonInfo
+	call BillsPC_GetSelectedPokemonSpecies
+	ld [wCurPartySpecies], a
+	ld a, SCGB_BILLS_PC
+	call BillsPC_ApplyPalettes
+	ret
+
+BillsPCDepositFuncRelease: ; e24e0 (38:64e0)
+	call BillsPC_CheckMail_PreventBlackout
+	jr c, BillsPCDepositFuncCancel
+	call BillsPC_IsMonAnEgg
+	jr c, BillsPCDepositFuncCancel
+	ld a, [wMenuCursorY]
+	push af
+	ld de, PCString_ReleasePKMN
+	call BillsPC_PlaceString
+	call LoadStandardMenuHeader
+	lb bc, 14, 11
+	call PlaceYesNoBox
+	ld a, [wMenuCursorY]
+	dec a
+	call ExitMenu
+	and a
+	jr nz, .failed_release
+	ld a, [wBillsPC_CursorPosition]
+	ld hl, wBillsPC_ScrollPosition
+	add [hl]
+	ld [wCurPartyMon], a
+	xor a ; REMOVE_PARTY
+	ld [wPokemonWithdrawDepositParameter], a
+	farcall RemoveMonFromPartyOrBox
+	call ReleasePKMN_ByePKMN
+	ld a, $0
+	ld [wJumptableIndex], a
+	xor a
+	ld [wBillsPC_CursorPosition], a
+	ld [wBillsPC_ScrollPosition], a
+	pop af
+	ret
+
+.failed_release
+	ld de, PCString_WhatsUp
+	call BillsPC_PlaceString
+	pop af
+	ld [wMenuCursorY], a
+	ret
+
+BillsPCDepositFuncCancel: ; e2537 (38:6537)
+	ld a, $0
+	ld [wJumptableIndex], a
+	ret
+; e253d (38:653d)
+
+BillsPCDepositMenuHeader: ; 0xe253d (38:653d)
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 9, 4, SCREEN_WIDTH - 1, 13
+	dw .MenuData
+	db 1 ; default option
+; 0xe2545
+
+.MenuData: ; 0xe2545 (38:6545)
+	db STATICMENU_CURSOR ; flags
+	db 4 ; items
+	db "DEPOSIT@"
+	db "STATS@"
+	db "RELEASE@"
+	db "CANCEL@"
+; 0xe2564 (38:6564)
+
+Unreferenced_BillsPCClearThreeBoxes: ; e2564
+	hlcoord 0, 0
+	ld b,  4
+	ld c,  8
+	call ClearBox
+	hlcoord 0, 4
+	ld b, 10
+	ld c,  9
+	call ClearBox
+	hlcoord 0, 14
+	ld b,  2
+	ld c,  8
+	call ClearBox
+	ret
+; e2583
+
+_WithdrawPKMN: ; e2583 (38:6583)
+	ld hl, wOptions
+	ld a, [hl]
+	push af
+	set 4, [hl]
+	ld a, [wVramState]
+	push af
+	xor a
+	ld [wVramState], a
+	ld a, [hInMenu]
+	push af
+	ld a, $1
+	ld [hInMenu], a
+	xor a
+	ld [hMapAnims], a
+	call BillsPC_InitRAM
+	ld a, NUM_BOXES + 1
+	ld [wBillsPC_LoadedBox], a
+	call DelayFrame
+.loop
+	call JoyTextDelay
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .done
+	call .RunJumptable
+	call DelayFrame
+	jr .loop
+.done
+	call ClearSprites
+	pop af
+	ld [hInMenu], a
+	pop af
+	ld [wVramState], a
+	pop af
+	ld [wOptions], a
+	ret
+
+.RunJumptable: ; e25c8 (38:65c8)
+	ld a, [wJumptableIndex]
+	ld hl, .Jumptable
+	call BillsPC_Jumptable
+	jp hl
+
+.Jumptable: ; e25d2 (38:65d2)
+	dw .Init
+	dw .Joypad
+	dw .PrepSubmenu
+	dw BillsPC_Withdraw
+	dw BillsPC_EndJumptableLoop
+
+.Init: ; e25dc (38:65dc)
+	ld a, NUM_BOXES + 1
+	ld [wBillsPC_LoadedBox], a
+	xor a
+	ld [hBGMapMode], a
+	call ClearSprites
+	call CopyBoxmonSpecies
+	call BillsPC_BoxName
+	ld de, PCString_ChooseaPKMN
+	call BillsPC_PlaceString
+	ld a, $5
+	ld [wBillsPC_NumMonsOnScreen], a
+	call BillsPC_RefreshTextboxes
+	call PCMonInfo
+	ld a, $ff
+	ld [wCurPartySpecies], a
+	ld a, SCGB_BILLS_PC
+	call BillsPC_ApplyPalettes
+	call WaitBGMap
+	call BillsPC_UpdateSelectionCursor
+	call BillsPC_IncrementJumptableIndex
+	ret
+
+.Joypad: ; e2612 (38:6612)
+	ld hl, hJoyPressed ; $ffa7
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .b_button
+	ld a, [hl]
+	and A_BUTTON
+	jr nz, .a_button
+	call Withdraw_UpDown
+	and a
+	ret z
+	call BillsPC_UpdateSelectionCursor
+	xor a
+	ld [hBGMapMode], a
+	call BillsPC_RefreshTextboxes
+	call PCMonInfo
+	ld a, $1
+	ld [hBGMapMode], a
+	call DelayFrame
+	call DelayFrame
+	ret
+.a_button
+	call BillsPC_GetSelectedPokemonSpecies
+	and a
+	ret z
+	cp -1
+	jr z, .b_button
+	ld a, $2
+	ld [wJumptableIndex], a
+	ret ; e264a (38:664a)
+
+.unused
+	ld hl, wJumptableIndex
+	dec [hl]
+	ret
+
+.b_button
+	ld a, $4
+	ld [wJumptableIndex], a
+	ret
+; e2655
+
+.PrepSubmenu: ; e2655 (38:6655)
+	xor a
+	ld [hBGMapMode], a
+	call ClearSprites
+	call BillsPC_GetSelectedPokemonSpecies
+	ld [wCurPartySpecies], a
+	ld a, SCGB_BILLS_PC
+	call BillsPC_ApplyPalettes
+	ld de, PCString_WhatsUp
+	call BillsPC_PlaceString
+	ld a, $1
+	ld [wMenuCursorY], a
+	call BillsPC_IncrementJumptableIndex
+	ret
+
+BillsPC_Withdraw: ; e2675 (38:6675)
+	ld hl, .MenuHeader
+	call CopyMenuHeader
+	ld a, [wMenuCursorY]
+	call StoreTo_wMenuCursorBuffer
+	call VerticalMenu
+	jp c, .cancel
+	ld a, [wMenuCursorY]
+	dec a
+	and %11
+	ld e, a
+	ld d, 0
+	ld hl, .dw
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+.dw ; e2699 (38:6699) #mark
+	dw .withdraw ; Withdraw
+	dw .stats ; Stats
+	dw .release ; Release
+	dw .cancel ; Cancel
+
+
+.withdraw ; e26a1 (38:66a1)
+	call BillsPC_CheckMail_PreventBlackout
+	jp c, .cancel
+	call TryWithdrawPokemon
+	jr c, .FailedWithdraw
+	ld a, $0
+	ld [wJumptableIndex], a
+	xor a
+	ld [wBillsPC_CursorPosition], a
+	ld [wBillsPC_ScrollPosition], a
+	ret
+.FailedWithdraw:
+	ld de, PCString_WhatsUp
+	call BillsPC_PlaceString
+	ret
+
+.stats ; e26c0 (38:66c0)
+	call LoadStandardMenuHeader
+	call BillsPC_StatsScreen
+	call ExitMenu
+	call PCMonInfo
+	call BillsPC_GetSelectedPokemonSpecies
+	ld [wCurPartySpecies], a
+	ld a, SCGB_BILLS_PC
+	call BillsPC_ApplyPalettes
+	ret
+
+.release ; e26d8 (38:66d8)
+	ld a, [wMenuCursorY]
+	push af
+	call BillsPC_IsMonAnEgg
+	jr c, .FailedRelease
+	ld de, PCString_ReleasePKMN
+	call BillsPC_PlaceString
+	call LoadStandardMenuHeader
+	lb bc, 14, 11
+	call PlaceYesNoBox
+	ld a, [wMenuCursorY]
+	dec a
+	call ExitMenu
+	and a
+	jr nz, .FailedRelease
+	ld a, [wBillsPC_CursorPosition]
+	ld hl, wBillsPC_ScrollPosition
+	add [hl]
+	ld [wCurPartyMon], a
+	ld a, REMOVE_BOX
+	ld [wPokemonWithdrawDepositParameter], a
+	farcall RemoveMonFromPartyOrBox
+	call ReleasePKMN_ByePKMN
+	ld a, $0
+	ld [wJumptableIndex], a
+	xor a
+	ld [wBillsPC_CursorPosition], a
+	ld [wBillsPC_ScrollPosition], a
+	pop af
+	ret
+.FailedRelease:
+	ld de, PCString_WhatsUp
+	call BillsPC_PlaceString
+	pop af
+	ld [wMenuCursorY], a
+	ret
+
+.cancel ; e272b (38:672b)
+	ld a, $0
+	ld [wJumptableIndex], a
+	ret
+; e2731 (38:6731)
+
+.MenuHeader: ; 0xe2731
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 9, 4, SCREEN_WIDTH - 1, 13
+	dw .MenuData
+	db 1 ; default option
+; 0xe2739
+
+.MenuData: ; 0xe2739
+	db STATICMENU_CURSOR ; flags
+	db 4 ; items
+	db "WITHDRAW@"
+	db "STATS@"
+	db "RELEASE@"
+	db "CANCEL@"
+; 0xe2759
+
+_MovePKMNWithoutMail: ; e2759
+	ld hl, wOptions
+	ld a, [hl]
+	push af
+	set 4, [hl]
+	ld a, [wVramState]
+	push af
+	xor a
+	ld [wVramState], a
+	ld a, [hInMenu]
+	push af
+	ld a, $1
+	ld [hInMenu], a
+	xor a
+	ld [hMapAnims], a
+	call BillsPC_InitRAM
+	ld a, [wCurBox]
+	and $f
+	inc a
+	ld [wBillsPC_LoadedBox], a
+	call DelayFrame
+.asm_e2781
+	call JoyTextDelay
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .asm_e2793
+	call .RunJumptable
+	call DelayFrame
+	jr .asm_e2781
+
+.asm_e2793
+	call ClearSprites
+	pop af
+	ld [hInMenu], a
+	pop af
+	ld [wVramState], a
+	pop af
+	ld [wOptions], a
+	ret
+; e27a2
+
+.RunJumptable: ; e27a2
+	ld a, [wJumptableIndex]
+	ld hl, .Jumptable
+	call BillsPC_Jumptable
+	jp hl
+; e27ac
+
+.Jumptable: ; e27ac
+	dw .Init
+	dw .Joypad
+	dw .PrepSubmenu
+	dw .MoveMonWOMailSubmenu
+	dw .PrepInsertCursor
+	dw .Joypad2
+	dw BillsPC_EndJumptableLoop
+; e27ba
+
+.Init: ; e27ba
+	xor a
+	ld [hBGMapMode], a
+	call ClearSprites
+	call CopyBoxmonSpecies
+	ld de, PCString_ChooseaPKMN
+	call BillsPC_PlaceString
+	ld a, 5
+	ld [wBillsPC_NumMonsOnScreen], a
+	call BillsPC_RefreshTextboxes
+	call BillsPC_MoveMonWOMail_BoxNameAndArrows
+	call PCMonInfo
+	ld a, $ff
+	ld [wCurPartySpecies], a
+	ld a, SCGB_BILLS_PC
+	call BillsPC_ApplyPalettes
+	call WaitBGMap
+	call BillsPC_UpdateSelectionCursor
+	call BillsPC_IncrementJumptableIndex
+	ret
+; e27eb
+
+.Joypad: ; e27eb
+	ld hl, hJoyPressed
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .b_button
+	ld a, [hl]
+	and A_BUTTON
+	jr nz, .a_button
+	call MoveMonWithoutMail_DPad
+	jr c, .d_pad
+	and a
+	ret z
+	call BillsPC_UpdateSelectionCursor
+	xor a
+	ld [hBGMapMode], a
+	call BillsPC_RefreshTextboxes
+	call PCMonInfo
+	ld a, $1
+	ld [hBGMapMode], a
+	call DelayFrame
+	call DelayFrame
+	ret
+
+.d_pad
+	xor a
+	ld [wBillsPC_CursorPosition], a
+	ld [wBillsPC_ScrollPosition], a
+	ld a, $0
+	ld [wJumptableIndex], a
+	ret
+
+.a_button
+	call BillsPC_GetSelectedPokemonSpecies
+	and a
+	ret z
+	cp -1
+	jr z, .b_button
+	ld a, $2
+	ld [wJumptableIndex], a
+	ret
+
+.unused
+	ld hl, wJumptableIndex
+	dec [hl]
+	ret
+
+.b_button
+	ld a, $6
+	ld [wJumptableIndex], a
+	ret
+; e283d
+
+.PrepSubmenu: ; e283d
+	xor a
+	ld [hBGMapMode], a
+	call ClearSprites
+	call BillsPC_GetSelectedPokemonSpecies
+	ld [wCurPartySpecies], a
+	ld a, SCGB_BILLS_PC
+	call BillsPC_ApplyPalettes
+	ld de, PCString_WhatsUp
+	call BillsPC_PlaceString
+	ld a, $1
+	ld [wMenuCursorY], a
+	call BillsPC_IncrementJumptableIndex
+	ret
+; e285d
+
+.MoveMonWOMailSubmenu: ; e285d
+	ld hl, .MenuHeader
+	call CopyMenuHeader
+	ld a, [wMenuCursorY]
+	call StoreTo_wMenuCursorBuffer
+	call VerticalMenu
+	jp c, .Cancel
+	ld a, [wMenuCursorY]
+	dec a
+	and %11
+	ld e, a
+	ld d, 0
+	ld hl, .Jumptable2
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+; e2881
+
+.Jumptable2: ; e2881
+	dw .Move
+	dw .Stats
+	dw .Cancel
+; e2887
+
+.Move: ; e2887
+	call BillsPC_CheckMail_PreventBlackout
+	jp c, .Cancel
+	ld a, [wBillsPC_ScrollPosition]
+	ld [wBillsPC_BackupScrollPosition], a
+	ld a, [wBillsPC_CursorPosition]
+	ld [wBillsPC_BackupCursorPosition], a
+	ld a, [wBillsPC_LoadedBox]
+	ld [wBillsPC_BackupLoadedBox], a
+	ld a, $4
+	ld [wJumptableIndex], a
+	ret
+; e28a5
+
+.Stats: ; e28a5
+	call LoadStandardMenuHeader
+	call BillsPC_StatsScreen
+	call ExitMenu
+	call PCMonInfo
+	call BillsPC_GetSelectedPokemonSpecies
+	ld [wCurPartySpecies], a
+	ld a, SCGB_BILLS_PC
+	call BillsPC_ApplyPalettes
+	ret
+; e28bd
+
+.Cancel: ; e28bd
+	ld a, $0
+	ld [wJumptableIndex], a
+	ret
+; e28c3
+
+.MenuHeader: ; 0xe28c3
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 9, 4, SCREEN_WIDTH - 1, 13
+	dw .MenuData
+	db 1 ; default option
+; 0xe28cb
+
+.MenuData: ; 0xe28cb
+	db STATICMENU_CURSOR ; flags
+	db 3 ; items
+	db "MOVE@"
+	db "STATS@"
+	db "CANCEL@"
+; 0xe28df
+
+.PrepInsertCursor: ; e28df
+	xor a
+	ld [hBGMapMode], a
+	call CopyBoxmonSpecies
+	ld de, PCString_MoveToWhere
+	call BillsPC_PlaceString
+	ld a, $5
+	ld [wBillsPC_NumMonsOnScreen], a
+	call BillsPC_RefreshTextboxes
+	call BillsPC_MoveMonWOMail_BoxNameAndArrows
+	call ClearSprites
+	call BillsPC_UpdateInsertCursor
+	call WaitBGMap
+	call BillsPC_IncrementJumptableIndex
+	ret
+; e2903
+
+.Joypad2: ; e2903
+	ld hl, hJoyPressed
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .b_button_2
+	ld a, [hl]
+	and A_BUTTON
+	jr nz, .a_button_2
+	call MoveMonWithoutMail_DPad_2
+	jr c, .dpad_2
+	and a
+	ret z
+	call BillsPC_UpdateInsertCursor
+	xor a
+	ld [hBGMapMode], a
+	call BillsPC_RefreshTextboxes
+	ld a, $1
+	ld [hBGMapMode], a
+	call DelayFrame
+	call DelayFrame
+	ret
+
+.dpad_2
+	xor a
+	ld [wBillsPC_CursorPosition], a
+	ld [wBillsPC_ScrollPosition], a
+	ld a, $4
+	ld [wJumptableIndex], a
+	ret
+
+.a_button_2
+	call BillsPC_CheckSpaceInDestination
+	jr c, .no_space
+	call MovePKMNWitoutMail_InsertMon
+	ld a, $0
+	ld [wJumptableIndex], a
+	ret
+
+.no_space
+	ld hl, wJumptableIndex
+	dec [hl]
+	ret
+
+.b_button_2
+	ld a, [wBillsPC_BackupScrollPosition]
+	ld [wBillsPC_ScrollPosition], a
+	ld a, [wBillsPC_BackupCursorPosition]
+	ld [wBillsPC_CursorPosition], a
+	ld a, [wBillsPC_BackupLoadedBox]
+	ld [wBillsPC_LoadedBox], a
+	ld a, $0
+	ld [wJumptableIndex], a
+	ret
+; e2963
+
+BillsPC_InitRAM: ; e2963 (38:6963)
+	call ClearBGPalettes
+	call ClearSprites
+	call ClearTileMap
+	call BillsPC_InitGFX
+	ld hl, wBillsPCPokemonList
+	ld bc, $338
+	xor a
+	call ByteFill
+	xor a
+	ld [wJumptableIndex], a
+	ld [wcf64], a
+	ld [wcf65], a
+	ld [wcf66], a
+	ld [wBillsPC_CursorPosition], a
+	ld [wBillsPC_ScrollPosition], a
+	ret
+
+BillsPC_IncrementJumptableIndex: ; e298d (38:698d)
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+BillsPC_EndJumptableLoop: ; e2992 (38:6992)
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+_StatsScreenDPad: ; e2998 (38:6998)
+	ld a, [wBillsPC_NumMonsOnScreen]
+	ld d, a
+	ld a, [wBillsPC_NumMonsInBox]
+	and a
+	jr z, .empty
+	dec a
+	cp $1
+	jr z, .empty
+	ld e, a
+	ld a, [hl]
+	and D_UP
+	jr nz, BillsPC_PressUp
+	ld a, [hl]
+	and D_DOWN
+	jr nz, BillsPC_PressDown
+.empty
+	jp BillsPC_JoypadDidNothing
+
+Withdraw_UpDown: ; e29b5 (38:69b5)
+	ld hl, hJoyLast
+	ld a, [wBillsPC_NumMonsOnScreen]
+	ld d, a
+	ld a, [wBillsPC_NumMonsInBox]
+	ld e, a
+	and a
+	jr z, .empty
+	ld a, [hl]
+	and D_UP
+	jr nz, BillsPC_PressUp
+	ld a, [hl]
+	and D_DOWN
+	jr nz, BillsPC_PressDown
+.empty
+	jp BillsPC_JoypadDidNothing
+; e29d0 (38:69d0)
+
+MoveMonWithoutMail_DPad: ; e29d0
+	ld hl, hJoyLast
+	ld a, [wBillsPC_NumMonsOnScreen]
+	ld d, a
+	ld a, [wBillsPC_NumMonsInBox]
+	ld e, a
+	and a
+	jr z, .check_left_right
+	ld a, [hl]
+	and D_UP
+	jr nz, BillsPC_PressUp
+	ld a, [hl]
+	and D_DOWN
+	jr nz, BillsPC_PressDown
+
+.check_left_right
+	ld a, [hl]
+	and D_LEFT
+	jr nz, BillsPC_PressLeft
+	ld a, [hl]
+	and D_RIGHT
+	jr nz, BillsPC_PressRight
+	jr BillsPC_JoypadDidNothing
+
+MoveMonWithoutMail_DPad_2: ; e29f4
+	ld hl, hJoyLast
+	ld a, [wBillsPC_NumMonsOnScreen]
+	ld d, a
+	ld a, [wBillsPC_NumMonsInBox]
+	ld e, a
+	and a
+	jr z, .check_left_right
+
+	ld a, [hl]
+	and D_UP
+	jr nz, BillsPC_PressUp
+	ld a, [hl]
+	and D_DOWN
+	jr nz, BillsPC_PressDown
+
+.check_left_right
+	ld a, [hl]
+	and D_LEFT
+	jr nz, BillsPC_PressLeft
+	ld a, [hl]
+	and D_RIGHT
+	jr nz, BillsPC_PressRight
+	jr BillsPC_JoypadDidNothing
+
+BillsPC_PressUp: ; e2a18 (38:6a18)
+	ld hl, wBillsPC_CursorPosition
+	ld a, [hl]
+	and a
+	jr z, .top
+	dec [hl]
+	jr BillsPC_UpDownDidSomething
+
+.top
+	ld hl, wBillsPC_ScrollPosition
+	ld a, [hl]
+	and a
+	jr z, BillsPC_JoypadDidNothing
+	dec [hl]
+	jr BillsPC_UpDownDidSomething
+
+BillsPC_PressDown: ; e2a2c (38:6a2c)
+	ld a, [wBillsPC_CursorPosition]
+	ld hl, wBillsPC_ScrollPosition
+	add [hl]
+	inc a
+	cp e
+	jr nc, BillsPC_JoypadDidNothing
+
+	ld hl, wBillsPC_CursorPosition
+	ld a, [hl]
+	inc a
+	cp d
+	jr nc, .not_bottom
+	inc [hl]
+	jr BillsPC_UpDownDidSomething
+
+.not_bottom
+	ld hl, wBillsPC_ScrollPosition
+	inc [hl]
+	jr BillsPC_UpDownDidSomething
+; e2a48 (38:6a48)
+
+BillsPC_PressLeft: ; e2a48
+	ld hl, wBillsPC_LoadedBox
+	ld a, [hl]
+	and a
+	jr z, .wrap_around
+	dec [hl]
+	jr BillsPC_LeftRightDidSomething
+
+.wrap_around
+	ld [hl], NUM_BOXES
+	jr BillsPC_LeftRightDidSomething
+
+BillsPC_PressRight: ; e2a56
+	ld hl, wBillsPC_LoadedBox
+	ld a, [hl]
+	cp NUM_BOXES
+	jr z, .wrap_around
+	inc [hl]
+	jr BillsPC_LeftRightDidSomething
+
+.wrap_around
+	ld [hl], 0
+	jr BillsPC_LeftRightDidSomething
+
+BillsPC_JoypadDidNothing: ; e2a65 (38:6a65)
+	xor a
+	and a
+	ret
+
+BillsPC_UpDownDidSomething: ; e2a68 (38:6a68)
+	ld a, TRUE
+	and a
+	ret
+; e2a6c (38:6a6c)
+
+BillsPC_LeftRightDidSomething: ; e2a6c
+	scf
+	ret
+; e2a6e
+
+BillsPC_PlaceString: ; e2a6e (38:6a6e)
+	push de
+	hlcoord 0, 15
+	lb bc, 1, 18
+	call TextBox
+	pop de
+	hlcoord 1, 16
+	call PlaceString
+	ret
+; e2a80 (38:6a80)
+
+BillsPC_MoveMonWOMail_BoxNameAndArrows: ; e2a80
+	call BillsPC_BoxName
+	hlcoord 8, 1
+	ld [hl], $5f
+	hlcoord 19, 1
+	ld [hl], $5e
+	ret
+; e2a8e
+
+BillsPC_BoxName: ; e2a8e (38:6a8e)
+	hlcoord 8, 0
+	lb bc, 1, 10
+	call TextBox
+
+	ld a, [wBillsPC_LoadedBox]
+	and a
+	jr z, .party
+
+	cp NUM_BOXES + 1
+	jr nz, .gotbox
+
+	ld a, [wCurBox]
+	inc a
+.gotbox
+	dec a
+	ld hl, wBoxNames
+	ld bc, BOX_NAME_LENGTH
+	call AddNTimes
+	ld e, l
+	ld d, h
+	jr .print
+
+.party
+	ld de, .PartyPKMN
+.print
+	hlcoord 10, 1
+	call PlaceString
+	ret
+; e2abd (38:6abd)
+
+.PartyPKMN:
+	db "PARTY <PK><MN>@"
+; e2ac6
+
+PCMonInfo: ; e2ac6 (38:6ac6)
+; Display a monster's pic and
+; attributes when highlighting
+; it in a PC menu.
+
+; Includes the neat cascading
+; effect when showing the pic.
+
+; Example: Species, level, gender,
+; whether it's holding an item.
+
+	hlcoord 0, 0
+	lb bc, 15, 8
+	call ClearBox
+
+	hlcoord 8, 14
+	lb bc, 1, 3
+	call ClearBox
+
+	call BillsPC_GetSelectedPokemonSpecies
+	and a
+	ret z
+	cp -1
+	ret z
+
+	ld [wd265], a
+	hlcoord 1, 4
+	xor a
+	ld b, 7
+.row
+	ld c, 7
+	push af
+	push hl
+.col
+	ld [hli], a
+	add 7
+	dec c
+	jr nz, .col
+	pop hl
+	ld de, SCREEN_WIDTH
+	add hl, de
+	pop af
+	inc a
+	dec b
+	jr nz, .row
+
+	call BillsPC_LoadMonStats
+	ld a, [wd265]
+	ld [wCurPartySpecies], a
+	ld [wCurSpecies], a
+	ld hl, wTempMonDVs
+	predef GetUnownLetter
+	call GetBaseData
+	ld de, vTiles2 tile $00
+	predef GetMonFrontpic
+	xor a
+	ld [wBillsPC_MonHasMail], a
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	cp EGG
+	ret z
+
+	call GetBasePokemonName
+	hlcoord 1, 14
+	call PlaceString
+
+	hlcoord 1, 12
+	call PrintLevel
+
+	ld a, $3
+	ld [wMonType], a
+	farcall GetGender
+	jr c, .skip_gender
+	ld a, "♂"
+	jr nz, .printgender
+	ld a, "♀"
+.printgender
+	hlcoord 5, 12
+	ld [hl], a
+.skip_gender
+
+	ld a, [wTempMonItem]
+	and a
+	ret z
+
+	ld d, a
+	callfar ItemIsMail
+	jr c, .mail
+	ld a, $5d ; item icon
+	jr .printitem
+.mail
+	ld a, $1
+	ld [wBillsPC_MonHasMail], a
+	ld a, $5c ; mail icon
+.printitem
+	hlcoord 7, 12
+	ld [hl], a
+	ret
+
+BillsPC_LoadMonStats: ; e2b6d (38:6b6d)
+	ld a, [wBillsPC_CursorPosition]
+	ld hl, wBillsPC_ScrollPosition
+	add [hl]
+	ld e, a
+	ld d, $0
+	ld hl, wBillsPCPokemonList + 1 ; box number
+	add hl, de
+	add hl, de
+	add hl, de
+	ld a, [hl]
+	and a
+	jr z, .party
+	cp NUM_BOXES + 1
+	jr z, .sBox
+	ld b, a
+	call GetBoxPointer
+	ld a, b
+	call GetSRAMBank
+	push hl
+	ld bc, sBoxMon1Level - sBox
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, e
+	call AddNTimes
+	ld a, [hl]
+	ld [wTempMonLevel], a
+	pop hl
+	push hl
+	ld bc, sBoxMon1Item - sBox
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, e
+	call AddNTimes
+	ld a, [hl]
+	ld [wTempMonItem], a
+	pop hl
+	ld bc, sBoxMon1DVs - sBox
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, e
+	call AddNTimes
+	ld de, wTempMonDVs
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+	call CloseSRAM
+	ret
+
+.party
+	ld hl, wPartyMon1Level
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, e
+	call AddNTimes
+	ld a, [hl]
+	ld [wTempMonLevel], a
+	ld hl, wPartyMon1Item
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, e
+	call AddNTimes
+	ld a, [hl]
+	ld [wTempMonItem], a
+	ld hl, wPartyMon1DVs
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, e
+	call AddNTimes
+	ld de, wTempMonDVs
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+	ret
+
+.sBox
+	ld a, BANK(sBox)
+	call GetSRAMBank
+	ld hl, sBoxMon1Level
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, e
+	call AddNTimes
+	ld a, [hl]
+	ld [wTempMonLevel], a
+
+	ld hl, sBoxMon1Item
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, e
+	call AddNTimes
+	ld a, [hl]
+	ld [wTempMonItem], a
+
+	ld hl, sBoxMon1DVs
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, e
+	call AddNTimes
+	ld de, wTempMonDVs
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+
+	call CloseSRAM
+	ret
+
+BillsPC_RefreshTextboxes: ; e2c2c (38:6c2c)
+	hlcoord 8, 2
+	lb bc, 10, 10
+	call TextBox
+
+	hlcoord 8, 2
+	ld [hl], "└"
+	hlcoord 19, 2
+	ld [hl], "┘"
+
+	ld a, [wBillsPC_ScrollPosition]
+	ld e, a
+	ld d, 0
+	ld hl, wBillsPCPokemonList
+	add hl, de
+	add hl, de
+	add hl, de
+	ld e, l
+	ld d, h
+	hlcoord 9, 4
+	ld a, [wBillsPC_NumMonsOnScreen]
+.loop
+	push af
+	push de
+	push hl
+	call .PlaceNickname
+	pop hl
+	ld de, 2 * SCREEN_WIDTH
+	add hl, de
+	pop de
+	inc de
+	inc de
+	inc de
+	pop af
+	dec a
+	jr nz, .loop
+	ret
+; e2c67 (38:6c67)
+
+.CancelString:
+	db "CANCEL@"
+; e2c6e
+
+.PlaceNickname: ; e2c6e (38:6c6e)
+	ld a, [de]
+	and a
+	ret z
+	cp -1
+	jr nz, .get_nickname
+	ld de, .CancelString
+	call PlaceString
+	ret
+
+.get_nickname
+	inc de
+	ld a, [de]
+	ld b, a
+	inc de
+	ld a, [de]
+	ld e, a
+	ld a, b
+	and a
+	jr z, .party
+	cp NUM_BOXES + 1
+	jr z, .sBox
+	push hl
+	call GetBoxPointer
+	ld a, b
+	call GetSRAMBank
+	push hl
+	ld bc, sBoxMons - sBox
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, e
+	call AddNTimes
+	ld a, [hl]
+	pop hl
+	and a
+	jr z, .boxfail
+	ld bc, sBoxMonNicknames - sBox
+	add hl, bc
+	ld bc, MON_NAME_LENGTH
+	ld a, e
+	call AddNTimes
+	ld de, wStringBuffer1
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+	call CloseSRAM
+	pop hl
+	ld de, wStringBuffer1
+	call PlaceString
+	ret
+
+.boxfail
+	call CloseSRAM
+	pop hl
+	jr .placeholder_string
+
+.party
+	push hl
+	ld hl, wPartySpecies
+	ld d, $0
+	add hl, de
+	ld a, [hl]
+	and a
+	jr z, .partyfail
+	ld hl, wPartyMonNicknames
+	ld bc, MON_NAME_LENGTH
+	ld a, e
+	call AddNTimes
+	ld de, wStringBuffer1
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+	pop hl
+	ld de, wStringBuffer1
+	call PlaceString
+	ret
+
+.partyfail
+	pop hl
+	jr .placeholder_string
+
+.sBox
+	push hl
+	ld a, BANK(sBox)
+	call GetSRAMBank
+	ld hl, sBoxSpecies
+	ld d, $0
+	add hl, de
+	ld a, [hl]
+	and a
+	jr z, .sBoxFail
+	ld hl, sBoxMonNicknames
+	ld bc, MON_NAME_LENGTH
+	ld a, e
+	call AddNTimes
+	ld de, wStringBuffer1
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+	call CloseSRAM
+	pop hl
+	ld de, wStringBuffer1
+	call PlaceString
+	ret
+
+.sBoxFail
+	call CloseSRAM
+	pop hl
+.placeholder_string
+	ld de, .Placeholder
+	call PlaceString
+	ret
+; e2d2a (38:6d2a)
+
+.Placeholder:
+	db "-----@"
+; e2d30
+
+copy_box_data: MACRO
+.loop\@
+	ld a, [hl]
+	cp -1
+	jr z, .done\@
+	and a
+	jr z, .done\@
+	ld [de], a
+	inc de
+	ld a, [wBillsPC_LoadedBox]
+	ld [de], a
+	inc de
+	ld a, [wd003]
+	ld [de], a
+	inc a
+	ld [wd003], a
+	inc de
+	inc hl
+	ld a, [wd004]
+	inc a
+	ld [wd004], a
+	jr .loop\@
+
+.done\@
+if \1
+	call CloseSRAM
+endc
+	ld a, -1
+	ld [de], a
+	ld a, [wd004]
+	inc a
+	ld [wBillsPC_NumMonsInBox], a
+ENDM
+
+CopyBoxmonSpecies: ; e2d30 (38:6d30)
+	xor a
+	ld hl, wBillsPCPokemonList
+	ld bc, 3 * 30
+	call ByteFill
+	ld de, wBillsPCPokemonList
+	xor a
+	ld [wd003], a
+	ld [wd004], a
+	ld a, [wBillsPC_LoadedBox]
+	and a
+	jr z, .party
+	cp NUM_BOXES + 1
+	jr z, .sBox
+	ld b, a
+	call GetBoxPointer
+	ld a, b
+	call GetSRAMBank
+	inc hl
+	copy_box_data 1
+	ret
+
+.party
+	ld hl, wPartySpecies
+	copy_box_data 0
+	ret
+
+.sBox
+	ld a, BANK(sBox)
+	call GetSRAMBank
+	ld hl, sBoxSpecies
+	copy_box_data 1
+	ret
+
+BillsPC_GetSelectedPokemonSpecies: ; e2def (38:6def)
+	ld a, [wBillsPC_CursorPosition]
+	ld hl, wBillsPC_ScrollPosition
+	add [hl]
+	ld e, a
+	ld d, $0
+	ld hl, wBillsPCPokemonList
+	add hl, de
+	add hl, de
+	add hl, de
+	ld a, [hl]
+	ret
+
+BillsPC_UpdateSelectionCursor: ; e2e01 (38:6e01)
+	ld a, [wBillsPC_NumMonsInBox]
+	and a
+	jr nz, .place_cursor
+	call ClearSprites
+	ret
+
+.place_cursor
+	ld hl, .OAM
+	ld de, wVirtualOAMSprite00
+.loop
+	ld a, [hl]
+	cp -1
+	ret z
+	ld a, [wBillsPC_CursorPosition]
+	and $7
+	swap a
+	add [hl]
+	inc hl
+	ld [de], a ; y
+	inc de
+rept SPRITEOAMSTRUCT_LENGTH + -1
+	ld a, [hli]
+	ld [de], a
+	inc de
+endr
+	jr .loop
+; e2e2b (38:6e2b)
+
+.OAM: ; e2e2b
+	dsprite 4, 6, 10, 0, $00, 0
+	dsprite 4, 6, 11, 0, $00, 0
+	dsprite 4, 6, 12, 0, $00, 0
+	dsprite 4, 6, 13, 0, $00, 0
+	dsprite 4, 6, 14, 0, $00, 0
+	dsprite 4, 6, 15, 0, $00, 0
+	dsprite 4, 6, 16, 0, $00, 0
+	dsprite 4, 6, 17, 0, $00, 0
+	dsprite 4, 6, 18, 0, $00, 0
+	dsprite 4, 6, 18, 7, $00, 0
+	dsprite 7, 1, 10, 0, $00, 0 | Y_FLIP
+	dsprite 7, 1, 11, 0, $00, 0 | Y_FLIP
+	dsprite 7, 1, 12, 0, $00, 0 | Y_FLIP
+	dsprite 7, 1, 13, 0, $00, 0 | Y_FLIP
+	dsprite 7, 1, 14, 0, $00, 0 | Y_FLIP
+	dsprite 7, 1, 15, 0, $00, 0 | Y_FLIP
+	dsprite 7, 1, 16, 0, $00, 0 | Y_FLIP
+	dsprite 7, 1, 17, 0, $00, 0 | Y_FLIP
+	dsprite 7, 1, 18, 0, $00, 0 | Y_FLIP
+	dsprite 7, 1, 18, 7, $00, 0 | Y_FLIP
+	dsprite 5, 6,  9, 6, $01, 0
+	dsprite 6, 1,  9, 6, $01, 0 | Y_FLIP
+	dsprite 5, 6, 19, 1, $01, 0 | X_FLIP
+	dsprite 6, 1, 19, 1, $01, 0 | X_FLIP | Y_FLIP
+	db -1
+; e2e8c
+
+BillsPC_UpdateInsertCursor: ; e2e8c
+	ld hl, .OAM
+	ld de, wVirtualOAMSprite00
+.loop
+	ld a, [hl]
+	cp -1
+	ret z
+	ld a, [wBillsPC_CursorPosition]
+	and $7
+	swap a
+	add [hl]
+	inc hl
+	ld [de], a ; y
+	inc de
+rept SPRITEOAMSTRUCT_LENGTH + -1
+	ld a, [hli]
+	ld [de], a
+	inc de
+endr
+	jr .loop
+; e2eac
+
+.OAM: ; e2eac
+	dsprite 4, 7, 10, 0, $06, 0
+	dsprite 5, 3, 11, 0, $00, 0 | Y_FLIP
+	dsprite 5, 3, 12, 0, $00, 0 | Y_FLIP
+	dsprite 5, 3, 13, 0, $00, 0 | Y_FLIP
+	dsprite 5, 3, 14, 0, $00, 0 | Y_FLIP
+	dsprite 5, 3, 15, 0, $00, 0 | Y_FLIP
+	dsprite 5, 3, 16, 0, $00, 0 | Y_FLIP
+	dsprite 5, 3, 17, 0, $00, 0 | Y_FLIP
+	dsprite 5, 3, 18, 0, $00, 0 | Y_FLIP
+	dsprite 4, 7, 19, 0, $07, 0
+	db -1
+; e2ed5
+
+Unreferenced_BillsPC_FillBox: ; e2ed5
+.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
+; e2ee5
+
+BillsPC_CheckSpaceInDestination: ; e2ee5
+; If moving within a box, no need to be here.
+	ld hl, wBillsPC_LoadedBox
+	ld a, [wBillsPC_BackupLoadedBox]
+	cp [hl]
+	jr z, .same_box
+
+; Exceeding box or party capacity is a big no-no.
+	ld a, [wBillsPC_LoadedBox]
+	and a
+	jr z, .party
+	ld e, MONS_PER_BOX + 1
+	jr .compare
+
+.party
+	ld e, PARTY_LENGTH + 1
+.compare
+	ld a, [wBillsPC_NumMonsInBox]
+	cp e
+	jr nc, .no_room
+.same_box
+	and a
+	ret
+
+.no_room
+	ld de, PCString_TheresNoRoom
+	call BillsPC_PlaceString
+	ld de, SFX_WRONG
+	call WaitPlaySFX
+	call WaitSFX
+	ld c, 50
+	call DelayFrames
+	scf
+	ret
+; e2f18
+
+BillsPC_CheckMail_PreventBlackout: ; e2f18 (38:6f18)
+	ld a, [wBillsPC_LoadedBox]
+	and a
+	jr nz, .Okay
+	ld a, [wBillsPC_NumMonsInBox]
+	cp $3
+	jr c, .ItsYourLastPokemon
+	ld a, [wBillsPC_CursorPosition]
+	ld hl, wBillsPC_ScrollPosition
+	add [hl]
+	ld [wCurPartyMon], a
+	farcall CheckCurPartyMonFainted
+	jr c, .AllOthersFainted
+	ld a, [wBillsPC_MonHasMail]
+	and a
+	jr nz, .HasMail
+.Okay:
+	and a
+	ret
+
+.HasMail:
+	ld de, PCString_RemoveMail
+	jr .NotOkay
+
+.AllOthersFainted:
+	ld de, PCString_NoMoreUsablePKMN
+	jr .NotOkay
+
+.ItsYourLastPokemon:
+	ld de, PCString_ItsYourLastPKMN
+.NotOkay:
+	call BillsPC_PlaceString
+	ld de, SFX_WRONG
+	call WaitPlaySFX
+	call WaitSFX
+	ld c, 50
+	call DelayFrames
+	scf
+	ret
+
+BillsPC_IsMonAnEgg: ; e2f5f (38:6f5f)
+	ld a, [wCurPartySpecies]
+	cp EGG
+	jr z, .egg
+	and a
+	ret
+
+.egg
+	ld de, PCString_NoReleasingEGGS
+	call BillsPC_PlaceString
+	ld de, SFX_WRONG
+	call WaitPlaySFX
+	call WaitSFX
+	ld c, 50
+	call DelayFrames
+	scf
+	ret
+
+BillsPC_StatsScreen: ; e2f7e (38:6f7e)
+	call LowVolume
+	call BillsPC_CopyMon
+	ld a, $3
+	ld [wMonType], a
+	predef StatsScreenInit
+	call BillsPC_InitGFX
+	call MaxVolume
+	ret
+
+StatsScreenDPad: ; e2f95 (38:6f95)
+	ld hl, hJoyPressed ; $ffa7
+	ld a, [hl]
+	and A_BUTTON | B_BUTTON | D_RIGHT | D_LEFT
+	ld [wMenuJoypad], a
+	jr nz, .pressed_a_b_right_left
+	ld a, [hl]
+	and D_DOWN | D_UP
+	ld [wMenuJoypad], a
+	jr nz, .pressed_down_up
+	jr .pressed_a_b_right_left
+
+.pressed_down_up
+	call _StatsScreenDPad
+	and a
+	jr z, .did_nothing
+	call BillsPC_GetSelectedPokemonSpecies
+	ld [wd265], a
+	call BillsPC_LoadMonStats
+	ld a, [wd265]
+	ld [wCurPartySpecies], a
+	ld [wCurSpecies], a
+	ld hl, wTempMonDVs
+	predef GetUnownLetter
+	call GetBaseData
+	call BillsPC_CopyMon
+.pressed_a_b_right_left
+	ret
+
+.did_nothing
+	xor a
+	ld [wMenuJoypad], a
+	ret
+
+BillsPC_CopyMon: ; e2fd6 (38:6fd6)
+	ld a, [wBillsPC_CursorPosition]
+	ld hl, wBillsPC_ScrollPosition
+	add [hl]
+	ld [wCurPartyMon], a
+	ld a, [wBillsPC_LoadedBox]
+	and a
+	jr z, .party
+	cp NUM_BOXES + 1
+	jr nz, .box
+	ld a, BANK(sBox)
+	call GetSRAMBank
+	ld hl, sBoxSpecies
+	call CopySpeciesToTemp
+	ld hl, sBoxMonNicknames
+	call CopyNicknameToTemp
+	ld hl, sBoxMonOT
+	call CopyOTNameToTemp
+	ld hl, sBoxMons
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld de, wBufferMon
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call CopyBytes
+	call CloseSRAM
+	farcall CalcBufferMonStats
+	ret
+
+.party
+	ld hl, wPartySpecies
+	call CopySpeciesToTemp
+	ld hl, wPartyMonNicknames
+	call CopyNicknameToTemp
+	ld hl, wPartyMonOT
+	call CopyOTNameToTemp
+	ld hl, wPartyMon1
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld de, wBufferMon
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call CopyBytes
+	ret
+
+.box
+	ld b, a
+	call GetBoxPointer
+	ld a, b
+	call GetSRAMBank
+	push hl
+	inc hl
+	call CopySpeciesToTemp
+	pop hl
+	push hl
+	ld bc, sBoxMonNicknames - sBox
+	add hl, bc
+	call CopyNicknameToTemp
+	pop hl
+	push hl
+	ld bc, sBoxMonOT - sBox
+	add hl, bc
+	call CopyOTNameToTemp
+	pop hl
+	ld bc, sBoxMons - sBox
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	call CopyMonToTemp
+	call CloseSRAM
+	farcall CalcBufferMonStats
+	ret
+
+DepositPokemon: ; e307c (38:707c)
+	ld a, [wBillsPC_CursorPosition]
+	ld hl, wBillsPC_ScrollPosition
+	add [hl]
+	ld [wCurPartyMon], a
+	ld hl, wPartyMonNicknames
+	ld a, [wCurPartyMon]
+	call GetNick
+	ld a, PC_DEPOSIT
+	ld [wPokemonWithdrawDepositParameter], a
+	predef SendGetMonIntoFromBox
+	jr c, .asm_boxisfull
+	xor a ; REMOVE_PARTY
+	ld [wPokemonWithdrawDepositParameter], a
+	farcall RemoveMonFromPartyOrBox
+	ld a, [wCurPartySpecies]
+	call PlayMonCry
+	hlcoord 0, 0
+	lb bc, 15, 8
+	call ClearBox
+	hlcoord 8, 14
+	lb bc, 1, 3
+	call ClearBox
+	hlcoord 0, 15
+	lb bc, 1, 18
+	call TextBox
+	call WaitBGMap
+	hlcoord 1, 16
+	ld de, PCString_Stored
+	call PlaceString
+	ld l, c
+	ld h, b
+	ld de, wStringBuffer1
+	call PlaceString
+	ld a, "!"
+	ld [bc], a
+	ld c, 50
+	call DelayFrames
+	and a
+	ret
+
+.asm_boxisfull
+	ld de, PCString_BoxFull
+	call BillsPC_PlaceString
+	ld de, SFX_WRONG
+	call WaitPlaySFX
+	call WaitSFX
+	ld c, 50
+	call DelayFrames
+	scf
+	ret
+
+TryWithdrawPokemon: ; e30fa (38:70fa)
+	ld a, [wBillsPC_CursorPosition]
+	ld hl, wBillsPC_ScrollPosition
+	add [hl]
+	ld [wCurPartyMon], a
+	ld a, BANK(sBoxMonNicknames)
+	call GetSRAMBank
+	ld a, [wCurPartyMon]
+	ld hl, sBoxMonNicknames
+	call GetNick
+	call CloseSRAM
+	xor a
+	ld [wPokemonWithdrawDepositParameter], a
+	predef SendGetMonIntoFromBox
+	jr c, .PartyFull
+	ld a, REMOVE_BOX
+	ld [wPokemonWithdrawDepositParameter], a
+	farcall RemoveMonFromPartyOrBox
+	ld a, [wCurPartySpecies]
+	call PlayMonCry
+	hlcoord 0, 0
+	lb bc, 15, 8
+	call ClearBox
+	hlcoord 8, 14
+	lb bc, 1, 3
+	call ClearBox
+	hlcoord 0, 15
+	lb bc, 1, 18
+	call TextBox
+	call WaitBGMap
+	hlcoord 1, 16
+	ld de, PCString_Got
+	call PlaceString
+	ld l, c
+	ld h, b
+	ld de, wStringBuffer1
+	call PlaceString
+	ld a, $e7
+	ld [bc], a
+	ld c, 50
+	call DelayFrames
+	and a
+	ret
+
+.PartyFull:
+	ld de, PCString_PartyFull
+	call BillsPC_PlaceString
+	ld de, SFX_WRONG
+	call WaitPlaySFX
+	call WaitSFX
+	ld c, 50
+	call DelayFrames
+	scf
+	ret
+
+
+ReleasePKMN_ByePKMN: ; e3180 (38:7180)
+	hlcoord 0, 0
+	lb bc, 15, 8
+	call ClearBox
+	hlcoord 8, 14
+	lb bc, 1, 3
+	call ClearBox
+	hlcoord 0, 15
+	lb bc, 1, 18
+	call TextBox
+
+	call WaitBGMap
+	ld a, [wCurPartySpecies]
+	call GetCryIndex
+	jr c, .skip_cry
+	ld e, c
+	ld d, b
+	call PlayCry
+.skip_cry
+
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	call GetPokemonName
+	hlcoord 1, 16
+	ld de, PCString_ReleasedPKMN
+	call PlaceString
+	ld c, 80
+	call DelayFrames
+	hlcoord 0, 15
+	lb bc, 1, 18
+	call TextBox
+	hlcoord 1, 16
+	ld de, PCString_Bye
+	call PlaceString
+	ld l, c
+	ld h, b
+	inc hl
+	ld de, wStringBuffer1
+	call PlaceString
+	ld l, c
+	ld h, b
+	ld [hl], $e7
+	ld c, 50
+	call DelayFrames
+	ret
+; e31e7 (38:71e7)
+
+MovePKMNWitoutMail_InsertMon: ; e31e7
+	push hl
+	push de
+	push bc
+	push af
+	hlcoord 0, 15
+	lb bc, 1, 18
+	call TextBox
+	hlcoord 1, 16
+	ld de, .Saving_LeaveOn
+	call PlaceString
+	ld c, 20
+	call DelayFrames
+	pop af
+	pop bc
+	pop de
+	pop hl
+	ld a, [wCurBox]
+	push af
+	ld bc, 0
+	ld a, [wBillsPC_BackupLoadedBox]
+	and a
+	jr nz, .moving_from_box
+	set 0, c
+
+.moving_from_box
+	ld a, [wBillsPC_LoadedBox]
+	and a
+	jr nz, .moving_to_box
+	set 1, c
+
+.moving_to_box
+	ld hl, .Jumptable
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, .dw_return
+	push de
+	jp hl
+; e322a
+
+.dw_return ; e322a
+	pop af
+	ld e, a
+	farcall MoveMonWOMail_InsertMon_SaveGame
+	ret
+; e3233
+
+.Saving_LeaveOn:
+	db "Saving… Leave ON!@"
+; e3245
+
+.Jumptable: ; e3245
+	dw .BoxToBox
+	dw .PartyToBox
+	dw .BoxToParty
+	dw .PartyToParty
+; e324d
+
+.BoxToBox: ; e324d
+	ld hl, wBillsPC_BackupLoadedBox
+	ld a, [wBillsPC_LoadedBox]
+	cp [hl]
+	jr z, .same_box
+	call .CopyFromBox
+	call .CopyToBox
+	ret
+
+.same_box
+	call .CopyFromBox
+	call .CheckTrivialMove
+	call .CopyToBox
+	ret
+; e3267
+
+.PartyToBox: ; e3267
+	call .CopyFromParty
+	ld a, $1
+	ld [wGameLogicPaused], a
+	farcall SaveGameData
+	xor a
+	ld [wGameLogicPaused], a
+	call .CopyToBox
+	ret
+; e327d
+
+.BoxToParty: ; e327d
+	call .CopyFromBox
+	call .CopyToParty
+	ret
+; e3284
+
+.PartyToParty: ; e3284
+	call .CopyFromParty
+	call .CheckTrivialMove
+	call .CopyToParty
+	ret
+; e328e
+
+.CheckTrivialMove: ; e328e
+	ld a, [wBillsPC_CursorPosition]
+	ld hl, wBillsPC_ScrollPosition
+	add [hl]
+	ld e, a
+	ld a, [wBillsPC_BackupCursorPosition]
+	ld hl, wBillsPC_BackupScrollPosition
+	add [hl]
+	cp e
+	ret nc
+	ld hl, wBillsPC_CursorPosition
+	ld a, [hl]
+	and a
+	jr z, .top_of_screen
+	dec [hl]
+	ret
+
+.top_of_screen
+	ld hl, wBillsPC_ScrollPosition
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+	ret
+; e32b0
+
+.CopyFromBox: ; e32b0
+	ld a, [wBillsPC_BackupLoadedBox]
+	dec a
+	ld e, a
+	farcall MoveMonWOMail_SaveGame
+	ld a, [wBillsPC_BackupCursorPosition]
+	ld hl, wBillsPC_BackupScrollPosition
+	add [hl]
+	ld [wCurPartyMon], a
+	ld a, BANK(sBox)
+	call GetSRAMBank
+	ld hl, sBoxSpecies
+	call CopySpeciesToTemp
+	ld hl, sBoxMonNicknames
+	call CopyNicknameToTemp
+	ld hl, sBoxMonOT
+	call CopyOTNameToTemp
+	ld hl, sBoxMons
+	ld bc, BOXMON_STRUCT_LENGTH
+	call CopyMonToTemp
+	call CloseSRAM
+	farcall CalcBufferMonStats
+	ld a, REMOVE_BOX
+	ld [wPokemonWithdrawDepositParameter], a
+	farcall RemoveMonFromPartyOrBox
+	ret
+; e32fa
+
+.CopyToBox: ; e32fa
+	ld a, [wBillsPC_LoadedBox]
+	dec a
+	ld e, a
+	farcall MoveMonWOMail_SaveGame
+	ld a, [wBillsPC_CursorPosition]
+	ld hl, wBillsPC_ScrollPosition
+	add [hl]
+	ld [wCurPartyMon], a
+	farcall InsertPokemonIntoBox
+	ret
+; e3316
+
+.CopyFromParty: ; e3316
+	ld a, [wBillsPC_BackupCursorPosition]
+	ld hl, wBillsPC_BackupScrollPosition
+	add [hl]
+	ld [wCurPartyMon], a
+	ld hl, wPartySpecies
+	call CopySpeciesToTemp
+	ld hl, wPartyMonNicknames
+	call CopyNicknameToTemp
+	ld hl, wPartyMonOT
+	call CopyOTNameToTemp
+	ld hl, wPartyMon1Species
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call CopyMonToTemp
+	xor a ; REMOVE_PARTY
+	ld [wPokemonWithdrawDepositParameter], a
+	farcall RemoveMonFromPartyOrBox
+	ret
+; e3346
+
+.CopyToParty: ; e3346
+	ld a, [wBillsPC_CursorPosition]
+	ld hl, wBillsPC_ScrollPosition
+	add [hl]
+	ld [wCurPartyMon], a
+	farcall InsertPokemonIntoParty
+	ret
+; e3357
+
+CopySpeciesToTemp: ; e3357 (38:7357)
+	ld a, [wCurPartyMon]
+	ld c, a
+	ld b, $0
+	add hl, bc
+	ld a, [hl]
+	ld [wCurPartySpecies], a
+	ret
+
+CopyNicknameToTemp: ; e3363 (38:7363)
+	ld bc, MON_NAME_LENGTH
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld de, wBufferMonNick
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+	ret
+
+CopyOTNameToTemp: ; e3376 (38:7376)
+	ld bc, NAME_LENGTH
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld de, wBufferMonOT
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ret
+
+CopyMonToTemp: ; e3389 (38:7389)
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld de, wBufferMon
+	call CopyBytes
+	ret
+
+GetBoxPointer: ; e3396 (38:7396)
+	dec b
+	ld c, b
+	ld b, 0
+	ld hl, .boxes
+	add hl, bc
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld b, a
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ret
+; e33a6 (38:73a6)
+
+.boxes ; e33a6
+	;  bank, address
+	dba sBox1
+	dba sBox2
+	dba sBox3
+	dba sBox4
+	dba sBox5
+	dba sBox6
+	dba sBox7
+	dba sBox8
+	dba sBox9
+	dba sBox10
+	dba sBox11
+	dba sBox12
+	dba sBox13
+	dba sBox14
+; e33d0
+
+BillsPC_ApplyPalettes: ; e33d0 (38:73d0)
+	ld b, a
+	call GetSGBLayout
+	ld a, %11100100
+	call DmgToCgbBGPals
+	ld a, %11111100
+	call DmgToCgbObjPal0
+	ret
+
+BillsPC_Jumptable: ; e33df (38:73df)
+	ld e, a
+	ld d, $0
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ret
+
+BillsPC_InitGFX: ; e33e8 (38:73e8)
+	call DisableLCD
+	ld hl, vTiles2 tile $00
+	ld bc, $31 tiles
+	xor a
+	call ByteFill
+	call LoadStandardFont
+	call LoadFontsBattleExtra
+	ld hl, PCMailGFX
+	ld de, vTiles2 tile $5c
+	ld bc, 4 tiles
+	call CopyBytes
+	ld hl, PCSelectLZ
+	ld de, vTiles0 tile $00
+	call Decompress
+	ld a, 6
+	call SkipMusic
+	call EnableLCD
+	ret
+; e3419 (38:7419)
+
+PCSelectLZ: INCBIN "gfx/pc/pc.2bpp.lz"
+PCMailGFX:  INCBIN "gfx/pc/pc_mail.2bpp"
+; e34dd
+
+PCString_ChooseaPKMN: db "Choose a <PK><MN>.@"
+PCString_WhatsUp: db "What's up?@"
+PCString_ReleasePKMN: db "Release <PK><MN>?@"
+PCString_MoveToWhere: db "Move to where?@"
+PCString_ItsYourLastPKMN: db "It's your last <PK><MN>!@"
+PCString_TheresNoRoom: db "There's no room!@"
+PCString_NoMoreUsablePKMN: db "No more usable <PK><MN>!@"
+PCString_RemoveMail: db "Remove MAIL.@"
+PCString_ReleasedPKMN: db "Released <PK><MN>.@"
+PCString_Bye: db "Bye,@"
+PCString_Stored: db "Stored @"
+PCString_Got: db "Got @"
+PCString_Non: db "Non.@"
+PCString_BoxFull: db "The BOX is full.@"
+PCString_PartyFull: db "The party's full!@"
+PCString_NoReleasingEGGS: db "No releasing EGGS!@"
+; e35aa
+
+
+_ChangeBox: ; e35aa (38:75aa)
+	call LoadStandardMenuHeader
+	call BillsPC_ClearTilemap
+.loop
+	xor a
+	ld [hBGMapMode], a
+	call BillsPC_PrintBoxName
+	call BillsPC_PlaceChooseABoxString
+	ld hl, _ChangeBox_MenuHeader
+	call CopyMenuHeader
+	xor a
+	ld [wMenuScrollPosition], a
+	hlcoord 0, 4
+	lb bc, 8, 9
+	call TextBox
+	call ScrollingMenu
+	ld a, [wMenuJoypad]
+	cp B_BUTTON
+	jr z, .done
+	call BillsPC_PlaceWhatsUpString
+	call BillsPC_ChangeBoxSubmenu
+	jr .loop
+.done
+	call CloseWindow
+	ret
+
+BillsPC_ClearTilemap: ; e35e2 (38:75e2)
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, " "
+	call ByteFill
+	ret
+; e35f1 (38:75f1)
+
+_ChangeBox_MenuHeader: ; 0xe35f1
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 1, 5, 9, 12
+	dw .MenuData
+	db 1 ; default option
+; 0xe35f9
+
+.MenuData ; 0xe35f9
+	db MENU_UNUSED_1 | MENU_UNUSED_3 ; flags
+	db 4, 0
+	db 1
+	dba .boxes
+	dba .boxnames
+	dba NULL
+	dba BillsPC_PrintBoxCountAndCapacity
+; e3609
+
+.boxes ; e3609
+	db NUM_BOXES
+x = 1
+rept NUM_BOXES
+	db x
+x = x + 1
+endr
+	db -1
+; e3619
+
+.boxnames ; e3619
+	push de
+	ld a, [wMenuSelection]
+	dec a
+	call GetBoxName
+	pop hl
+	call PlaceString
+	ret
+; e3626
+
+GetBoxName: ; e3626 (38:7626)
+	ld bc, BOX_NAME_LENGTH
+	ld hl, wBoxNames
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ret
+; e3632 (38:7632)
+
+BillsPC_PrintBoxCountAndCapacity: ; e3632
+	hlcoord 11, 7
+	lb bc, 5, 7
+	call TextBox
+	ld a, [wMenuSelection]
+	cp -1
+	ret z
+	hlcoord 12, 9
+	ld de, .Pokemon
+	call PlaceString
+	call GetBoxCount
+	ld [wd265], a
+	hlcoord 13, 11
+	ld de, wd265
+	lb bc, 1, 2
+	call PrintNum
+	ld de, .out_of_20
+	call PlaceString
+	ret
+; e3663
+
+.Pokemon: ; e3663
+	db "#MON@"
+; e3668
+
+.out_of_20 ; e3668
+	; db "/20@"
+	db "/"
+	db "0" + MONS_PER_BOX / 10 ; "2"
+	db "0" + MONS_PER_BOX % 10 ; "0"
+	db "@"
+; e366c
+
+GetBoxCount: ; e366c (38:766c)
+	ld a, [wCurBox]
+	ld c, a
+	ld a, [wMenuSelection]
+	dec a
+	cp c
+	jr z, .activebox
+	ld c, a
+	ld b, 0
+	ld hl, .boxbanks
+	add hl, bc
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld b, a
+	call GetSRAMBank
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [hl]
+	call CloseSRAM
+	ld c, a
+	ld a, [wSavedAtLeastOnce]
+	and a
+	jr z, .newfile
+	ld a, c
+	ret
+
+.newfile
+	xor a
+	ret
+
+.activebox
+	ld a, BANK(sBoxCount)
+	ld b, a
+	call GetSRAMBank
+	ld hl, sBoxCount
+	ld a, [hl]
+	call CloseSRAM
+	ret
+; e36a5 (38:76a5)
+
+.boxbanks ; e36a5
+	dba sBox1
+	dba sBox2
+	dba sBox3
+	dba sBox4
+	dba sBox5
+	dba sBox6
+	dba sBox7
+	dba sBox8
+	dba sBox9
+	dba sBox10
+	dba sBox11
+	dba sBox12
+	dba sBox13
+	dba sBox14
+; e36cf
+
+BillsPC_PrintBoxName: ; e36cf (38:76cf)
+	hlcoord 0, 0
+	ld b, 2
+	ld c, 18
+	call TextBox
+	hlcoord 1, 2
+	ld de, .Current
+	call PlaceString
+	ld a, [wCurBox]
+	and $f
+	call GetBoxName
+	hlcoord 11, 2
+	call PlaceString
+	ret
+; e36f1 (38:76f1)
+
+.Current: ; e36f1
+	db "CURRENT@"
+; e36f9
+
+BillsPC_ChangeBoxSubmenu: ; e36f9 (38:76f9)
+	ld hl, .MenuHeader
+	call LoadMenuHeader
+	call VerticalMenu
+	call ExitMenu
+	ret c
+	ld a, [wMenuCursorY]
+	cp $1
+	jr z, .Switch
+	cp $2
+	jr z, .Name
+	cp $3
+	jr z, .Print
+	and a
+	ret
+
+.Print:
+	call GetBoxCount
+	and a
+	jr z, .EmptyBox
+	ld e, l
+	ld d, h
+	ld a, [wMenuSelection]
+	dec a
+	ld c, a
+	farcall PrintPCBox
+	call BillsPC_ClearTilemap
+	and a
+	ret
+
+.EmptyBox:
+	call BillsPC_PlaceEmptyBoxString_SFX
+	and a
+	ret
+
+.Switch:
+	ld a, [wMenuSelection]
+	dec a
+	ld e, a
+	ld a, [wCurBox]
+	cp e
+	ret z
+	farcall ChangeBoxSaveGame
+	ret
+
+.Name:
+	ld b, $4 ; box
+	ld de, wd002
+	farcall NamingScreen
+	call ClearTileMap
+	call LoadStandardFont
+	call LoadFontsBattleExtra
+	ld a, [wMenuSelection]
+	dec a
+	call GetBoxName
+	ld e, l
+	ld d, h
+	ld hl, wd002
+	ld c, BOX_NAME_LENGTH - 1
+	call InitString
+	ld a, [wMenuSelection]
+	dec a
+	call GetBoxName
+	ld de, wd002
+	call CopyName2
+	ret
+; e3778 (38:7778)
+
+	hlcoord 11, 7 ; unused
+
+.MenuHeader: ; 0xe377b
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 11, 4, SCREEN_WIDTH - 1, 13
+	dw .MenuData
+	db 1 ; default option
+; 0xe3783
+
+.MenuData: ; 0xe3783
+	db STATICMENU_CURSOR ; flags
+	db 4 ; items
+	db "SWITCH@"
+	db "NAME@"
+	db "PRINT@"
+	db "QUIT@"
+; 0xe379c
+
+BillsPC_PlaceChooseABoxString: ; e379c (38:779c)
+	ld de, .ChooseABox
+	jr BillsPC_PlaceChangeBoxString
+; e37a1 (38:77a1)
+
+.ChooseABox: ; e37a1
+	db "Choose a BOX.@"
+; e37af
+
+BillsPC_PlaceWhatsUpString: ; e37af (38:77af)
+	ld de, .WhatsUp
+	jr BillsPC_PlaceChangeBoxString
+; e37b4 (38:77b4)
+
+.WhatsUp: ; e37b4
+	db "What's up?@"
+; e37be
+
+BillsPC_PlaceEmptyBoxString_SFX: ; e37be (38:77be)
+	ld de, .NoMonString
+	call BillsPC_PlaceChangeBoxString
+	ld de, SFX_WRONG
+	call WaitPlaySFX
+	call WaitSFX
+	ld c, 50
+	call DelayFrames
+	ret
+; e37d3 (38:77d3)
+
+.NoMonString: ; e37d3
+	db "There's no #MON.@"
+; e37e3
+
+BillsPC_PlaceChangeBoxString: ; e37e3 (38:77e3)
+	push de
+	hlcoord 0, 14
+	lb bc, 2, 18
+	call TextBox
+	pop de
+	hlcoord 1, 16
+	call PlaceString
+	ld a, $1
+	ld [hBGMapMode], a
+	ret
--- /dev/null
+++ b/engine/pokemon/billspctop.asm
@@ -1,0 +1,387 @@
+_BillsPC: ; e3fd
+	call .CheckCanUsePC
+	ret c
+	call .LogIn
+	call .UseBillsPC
+	jp .LogOut
+
+.CheckCanUsePC: ; e40a (3:640a)
+	ld a, [wPartyCount]
+	and a
+	ret nz
+	ld hl, .Text_GottaHavePokemon
+	call MenuTextBoxBackup
+	scf
+	ret
+
+.Text_GottaHavePokemon: ; 0xe417
+	; You gotta have #MON to call!
+	text_jump UnknownText_0x1c1006
+	db "@"
+
+.LogIn: ; e41c (3:641c)
+	xor a
+	ld [hBGMapMode], a
+	call LoadStandardMenuHeader
+	call ClearPCItemScreen
+	ld hl, wOptions
+	ld a, [hl]
+	push af
+	set NO_TEXT_SCROLL, [hl]
+	ld hl, .Text_What
+	call PrintText
+	pop af
+	ld [wOptions], a
+	call LoadFontsBattleExtra
+	ret
+
+.Text_What: ; 0xe43a
+	; What?
+	text_jump UnknownText_0x1c1024
+	db "@"
+
+.LogOut: ; e43f (3:643f)
+	call CloseSubmenu
+	ret
+
+.UseBillsPC: ; e443 (3:6443)
+	ld hl, .MenuHeader
+	call LoadMenuHeader
+	ld a, $1
+.loop
+	ld [wMenuCursorBuffer], a
+	call SetPalettes
+	xor a
+	ld [wWhichIndexSet], a
+	ld [hBGMapMode], a
+	call DoNthMenu
+	jr c, .cancel
+	ld a, [wMenuCursorBuffer]
+	push af
+	ld a, [wMenuSelection]
+	ld hl, .Jumptable
+	rst JumpTable
+	pop bc
+	ld a, b
+	jr nc, .loop
+.cancel
+	call CloseWindow
+	ret
+
+.MenuHeader: ; 0xe46f
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+	dw .MenuData
+	db 1 ; default option
+
+.MenuData: ; 0xe477
+	db STATICMENU_CURSOR ; flags
+	db 0 ; items
+	dw .items
+	dw PlaceMenuStrings
+	dw .strings
+
+.strings ; e47f
+	db "WITHDRAW <PK><MN>@"
+	db "DEPOSIT <PK><MN>@"
+	db "CHANGE BOX@"
+	db "MOVE <PK><MN> W/O MAIL@"
+	db "SEE YA!@"
+
+.Jumptable: ; e4ba (3:64ba)
+	dw BillsPC_WithdrawMenu
+	dw BillsPC_DepositMenu
+	dw BillsPC_ChangeBoxMenu
+	dw BillsPC_MovePKMNMenu
+	dw BillsPC_SeeYa
+
+.items ; e4c4
+	db 5
+	db 0 ; WITHDRAW
+	db 1;  DEPOSIT
+	db 2 ; CHANGE BOX
+	db 3 ; MOVE PKMN
+	db 4 ; SEE YA!
+	db -1
+
+BillsPC_SeeYa: ; e4cb
+	scf
+	ret
+
+BillsPC_MovePKMNMenu: ; e4cd
+	call LoadStandardMenuHeader
+	farcall IsAnyMonHoldingMail
+	jr nc, .no_mail
+	ld hl, .Text_MonHoldingMail
+	call PrintText
+	jr .quit
+
+.no_mail
+	farcall StartMoveMonWOMail_SaveGame
+	jr c, .quit
+	farcall _MovePKMNWithoutMail
+	call ReturnToMapFromSubmenu
+	call ClearPCItemScreen
+
+.quit
+	call CloseWindow
+	and a
+	ret
+
+.Text_MonHoldingMail: ; 0xe4f9
+	; There is a #MON holding MAIL. Please remove the MAIL.
+	text_jump UnknownText_0x1c102b
+	db "@"
+
+BillsPC_DepositMenu: ; e4fe (3:64fe)
+	call LoadStandardMenuHeader
+	farcall _DepositPKMN
+	call ReturnToMapFromSubmenu
+	call ClearPCItemScreen
+	call CloseWindow
+	and a
+	ret
+
+Unreferenced_Functione512:
+	ld a, [wPartyCount]
+	and a
+	jr z, .no_mon
+	cp 2
+	jr c, .only_one_mon
+	and a
+	ret
+
+.no_mon
+	ld hl, .Text_NoMon
+	call MenuTextBoxBackup
+	scf
+	ret
+
+.only_one_mon
+	ld hl, .Text_ItsYourLastMon
+	call MenuTextBoxBackup
+	scf
+	ret
+
+.Text_NoMon: ; 0xe52e
+	; You don't have a single #MON!
+	text_jump UnknownText_0x1c1062
+	db "@"
+
+.Text_ItsYourLastMon: ; 0xe533
+	; You can't deposit your last #MON!
+	text_jump UnknownText_0x1c1080
+	db "@"
+
+CheckCurPartyMonFainted: ; e538
+	ld hl, wPartyMon1HP
+	ld de, PARTYMON_STRUCT_LENGTH
+	ld b, $0
+.loop
+	ld a, [wCurPartyMon]
+	cp b
+	jr z, .skip
+	ld a, [hli]
+	or [hl]
+	jr nz, .notfainted
+	dec hl
+
+.skip
+	inc b
+	ld a, [wPartyCount]
+	cp b
+	jr z, .done
+	add hl, de
+	jr .loop
+
+.done
+	scf
+	ret
+
+.notfainted
+	and a
+	ret
+
+BillsPC_WithdrawMenu: ; e559 (3:6559)
+	call LoadStandardMenuHeader
+	farcall _WithdrawPKMN
+	call ReturnToMapFromSubmenu
+	call ClearPCItemScreen
+	call CloseWindow
+	and a
+	ret
+
+Unreferenced_Functione56d:
+	ld a, [wPartyCount]
+	cp PARTY_LENGTH
+	jr nc, .asm_e576
+	and a
+	ret
+
+.asm_e576
+	ld hl, UnknownText_0xe57e
+	call MenuTextBoxBackup
+	scf
+	ret
+
+UnknownText_0xe57e: ; 0xe57e
+	; You can't take any more #MON.
+	text_jump UnknownText_0x1c10a2
+	db "@"
+
+BillsPC_ChangeBoxMenu: ; e583 (3:6583)
+	farcall _ChangeBox
+	and a
+	ret
+
+ClearPCItemScreen: ; e58b
+	call DisableSpriteUpdates
+	xor a
+	ld [hBGMapMode], a
+	call ClearBGPalettes
+	call ClearSprites
+	hlcoord 0, 0
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	ld a, " "
+	call ByteFill
+	hlcoord 0, 0
+	lb bc, 10, 18
+	call TextBox
+	hlcoord 0, 12
+	lb bc, 4, 18
+	call TextBox
+	call WaitBGMap2
+	call SetPalettes ; load regular palettes?
+	ret
+
+CopyBoxmonToTempMon: ; e5bb
+	ld a, [wCurPartyMon]
+	ld hl, sBoxMon1Species
+	ld bc, BOXMON_STRUCT_LENGTH
+	call AddNTimes
+	ld de, wTempMonSpecies
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, BANK(sBoxMon1Species)
+	call GetSRAMBank
+	call CopyBytes
+	call CloseSRAM
+	ret
+
+Unreferenced_Functione5d9:
+	ld a, [wCurBox]
+	cp b
+	jr z, .same_box
+	ld a, b
+	ld hl, .BoxAddrs
+	ld bc, 3
+	call AddNTimes
+	ld a, [hli]
+	push af
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	pop af
+	jr .okay
+
+.same_box
+	ld a, BANK(sBoxCount)
+	ld hl, sBoxCount
+
+.okay
+	call GetSRAMBank
+	ld a, [hl]
+	ld bc, 1 + MONS_PER_BOX + 1
+	add hl, bc
+	ld b, a
+	ld c, $0
+	ld de, wc608
+	ld a, b
+	and a
+	jr z, .empty_box
+.loop
+	push hl
+	push bc
+	ld a, c
+	ld bc, 0
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [hl]
+	ld [de], a
+	inc de
+	ld [wCurSpecies], a
+	call GetBaseData
+	pop bc
+	pop hl
+
+	push hl
+	push bc
+	ld a, c
+	ld bc, MONS_PER_BOX * (BOXMON_STRUCT_LENGTH + NAME_LENGTH)
+	add hl, bc
+	call SkipNames
+	call CopyBytes
+	pop bc
+	pop hl
+
+	push hl
+	push bc
+	ld a, c
+	ld bc, MON_LEVEL
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [hl]
+	ld [de], a
+	inc de
+	pop bc
+	pop hl
+
+	push hl
+	push bc
+	ld a, c
+	ld bc, MON_DVS
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [hli]
+	and $f0
+	ld b, a
+	ld a, [hl]
+	and $f0
+	swap a
+	or b
+	ld b, a
+	ld a, [wBaseGender]
+	cp b
+	ld a, $1
+	jr c, .okay2
+	xor a
+.okay2
+	ld [de], a
+	inc de
+	pop bc
+	pop hl
+
+	inc c
+	dec b
+	jr nz, .loop
+.empty_box
+	call CloseSRAM
+	ret
+
+.BoxAddrs: ; e66e
+	dba sBox1
+	dba sBox2
+	dba sBox3
+	dba sBox4
+	dba sBox5
+	dba sBox6
+	dba sBox7
+	dba sBox8
+	dba sBox9
+	dba sBox10
+	dba sBox11
+	dba sBox12
+	dba sBox13
+	dba sBox14
--- /dev/null
+++ b/engine/pokemon/breeding.asm
@@ -1,0 +1,994 @@
+CheckBreedmonCompatibility: ; 16e1d
+	call .CheckBreedingGroupCompatibility
+	ld c, $0
+	jp nc, .done
+	ld a, [wBreedMon1Species]
+	ld [wCurPartySpecies], a
+	ld a, [wBreedMon1DVs]
+	ld [wTempMonDVs], a
+	ld a, [wBreedMon1DVs + 1]
+	ld [wTempMonDVs + 1], a
+	ld a, TEMPMON
+	ld [wMonType], a
+	predef GetGender
+	jr c, .genderless
+	ld b, $1
+	jr nz, .breedmon2
+	inc b
+
+.breedmon2
+	push bc
+	ld a, [wBreedMon2Species]
+	ld [wCurPartySpecies], a
+	ld a, [wBreedMon2DVs]
+	ld [wTempMonDVs], a
+	ld a, [wBreedMon2DVs + 1]
+	ld [wTempMonDVs + 1], a
+	ld a, $3
+	ld [wMonType], a
+	predef GetGender
+	pop bc
+	jr c, .genderless
+	ld a, $1
+	jr nz, .compare_gender
+	inc a
+
+.compare_gender
+	cp b
+	jr nz, .compute
+
+.genderless
+	ld c, $0
+	ld a, [wBreedMon1Species]
+	cp DITTO
+	jr z, .ditto1
+	ld a, [wBreedMon2Species]
+	cp DITTO
+	jr nz, .done
+	jr .compute
+
+.ditto1
+	ld a, [wBreedMon2Species]
+	cp DITTO
+	jr z, .done
+
+.compute
+	call .CheckDVs
+	ld c, 255
+	jp z, .done
+	ld a, [wBreedMon2Species]
+	ld b, a
+	ld a, [wBreedMon1Species]
+	cp b
+	ld c, 254
+	jr z, .compare_ids
+	ld c, 128
+.compare_ids
+	; Speed up
+	ld a, [wBreedMon1ID]
+	ld b, a
+	ld a, [wBreedMon2ID]
+	cp b
+	jr nz, .done
+	ld a, [wBreedMon1ID + 1]
+	ld b, a
+	ld a, [wBreedMon2ID + 1]
+	cp b
+	jr nz, .done
+	ld a, c
+	sub 77
+	ld c, a
+
+.done
+	ld a, c
+	ld [wd265], a
+	ret
+; 16ebc
+
+
+.CheckDVs: ; 16ebc (5:6ebc)
+; If Defense DVs match and the lower 3 bits of the Special DVs match,
+; avoid breeding
+	ld a, [wBreedMon1DVs]
+	and %1111
+	ld b, a
+	ld a, [wBreedMon2DVs]
+	and %1111
+	cp b
+	ret nz
+	ld a, [wBreedMon1DVs + 1]
+	and %111
+	ld b, a
+	ld a, [wBreedMon2DVs + 1]
+	and %111
+	cp b
+	ret
+; 16ed6
+
+.CheckBreedingGroupCompatibility: ; 16ed6
+; If either mon is in the No Eggs group,
+; they are not compatible.
+	ld a, [wBreedMon2Species]
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld a, [wBaseEggGroups]
+	cp EGG_NONE * $11
+	jr z, .Incompatible
+
+	ld a, [wBreedMon1Species]
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld a, [wBaseEggGroups]
+	cp EGG_NONE * $11
+	jr z, .Incompatible
+
+; Ditto is automatically compatible with everything.
+; If not Ditto, load the breeding groups into b/c and d/e.
+	ld a, [wBreedMon2Species]
+	cp DITTO
+	jr z, .Compatible
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld a, [wBaseEggGroups]
+	push af
+	and $f
+	ld b, a
+	pop af
+	and $f0
+	swap a
+	ld c, a
+
+	ld a, [wBreedMon1Species]
+	cp DITTO
+	jr z, .Compatible
+	ld [wCurSpecies], a
+	push bc
+	call GetBaseData
+	pop bc
+	ld a, [wBaseEggGroups]
+	push af
+	and $f
+	ld d, a
+	pop af
+	and $f0
+	swap a
+	ld e, a
+
+	ld a, d
+	cp b
+	jr z, .Compatible
+	cp c
+	jr z, .Compatible
+
+	ld a, e
+	cp b
+	jr z, .Compatible
+	cp c
+	jr z, .Compatible
+
+.Incompatible:
+	and a
+	ret
+
+.Compatible:
+	scf
+	ret
+; 16f3e
+
+DoEggStep:: ; 16f3e
+	ld de, wPartySpecies
+	ld hl, wPartyMon1Happiness
+	ld c, 0
+.loop
+	ld a, [de]
+	inc de
+	cp -1
+	ret z
+	cp EGG
+	jr nz, .next
+	dec [hl]
+	jr nz, .next
+	ld a, 1
+	and a
+	ret
+
+.next
+	push de
+	ld de, PARTYMON_STRUCT_LENGTH
+	add hl, de
+	pop de
+	jr .loop
+; 16f5e
+
+OverworldHatchEgg:: ; 16f5e
+	call RefreshScreen
+	call LoadStandardMenuHeader
+	call HatchEggs
+	call ExitAllMenus
+	call RestartMapMusic
+	jp CloseText
+; 16f70
+
+HatchEggs: ; 16f70 (5:6f70)
+	ld de, wPartySpecies
+	ld hl, wPartyMon1Happiness
+	xor a
+	ld [wCurPartyMon], a
+
+.loop ; 16f7a (5:6f7a)
+	ld a, [de]
+	inc de
+	cp -1
+	jp z, .done
+	push de
+	push hl
+	cp EGG
+	jp nz, .next
+	ld a, [hl]
+	and a
+	jp nz, .next
+	ld [hl], $78
+
+	push de
+
+	farcall SetEggMonCaughtData
+	farcall StubbedTrainerRankings_EggsHatched
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1Species
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [hl]
+	ld [wCurPartySpecies], a
+	dec a
+	call SetSeenAndCaughtMon
+
+	ld a, [wCurPartySpecies]
+	cp TOGEPI
+	jr nz, .nottogepi
+	; set the event flag for hatching togepi
+	ld de, EVENT_TOGEPI_HATCHED
+	ld b, SET_FLAG
+	call EventFlagAction
+.nottogepi
+
+	pop de
+
+	ld a, [wCurPartySpecies]
+	dec de
+	ld [de], a
+	ld [wd265], a
+	ld [wCurSpecies], a
+	call GetPokemonName
+	xor a
+	ld [wd26b], a
+	call GetBaseData
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	push hl
+	ld bc, MON_MAXHP
+	add hl, bc
+	ld d, h
+	ld e, l
+	pop hl
+	push hl
+	ld bc, MON_LEVEL
+	add hl, bc
+	ld a, [hl]
+	ld [wCurPartyLevel], a
+	pop hl
+	push hl
+	ld bc, MON_STATUS
+	add hl, bc
+	xor a
+	ld [hli], a
+	ld [hl], a
+	pop hl
+	push hl
+	ld bc, MON_STAT_EXP - 1
+	add hl, bc
+	ld b, FALSE
+	predef CalcMonStats
+	pop bc
+	ld hl, MON_MAXHP
+	add hl, bc
+	ld d, h
+	ld e, l
+	ld hl, MON_HP
+	add hl, bc
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	ld [hl], a
+	ld hl, MON_ID
+	add hl, bc
+	ld a, [wPlayerID]
+	ld [hli], a
+	ld a, [wPlayerID + 1]
+	ld [hl], a
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMonOT
+	ld bc, NAME_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld hl, wPlayerName
+	call CopyBytes
+	ld hl, .Text_HatchEgg
+	call PrintText
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMonNicknames
+	ld bc, MON_NAME_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	push de
+	ld hl, .Text_NicknameHatchling
+	call PrintText
+	call YesNoBox
+	pop de
+	jr c, .nonickname
+
+	ld a, $1
+	ld [wd26b], a
+	xor a
+	ld [wMonType], a
+	push de
+	ld b, $0
+	farcall NamingScreen
+	pop hl
+	ld de, wStringBuffer1
+	call InitName
+	jr .next
+
+.nonickname
+	ld hl, wStringBuffer1
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+
+.next ; 1707d (5:707d)
+	ld hl, wCurPartyMon
+	inc [hl]
+	pop hl
+	ld de, PARTYMON_STRUCT_LENGTH
+	add hl, de
+	pop de
+	jp .loop
+
+.done ; 1708a (5:708a)
+	ret
+; 1708b (5:708b)
+
+.Text_HatchEgg: ; 0x1708b
+	; Huh? @ @
+	text_jump UnknownText_0x1c0db0
+	start_asm
+	ld hl, wVramState
+	res 0, [hl]
+	push hl
+	push de
+	push bc
+	ld a, [wCurPartySpecies]
+	push af
+	call EggHatch_AnimationSequence
+	ld hl, .ClearTextbox
+	call PrintText
+	pop af
+	ld [wCurPartySpecies], a
+	pop bc
+	pop de
+	pop hl
+	ld hl, .CameOutOfItsEgg
+	ret
+; 170b0 (5:70b0)
+
+.ClearTextbox: ; 0x170b0
+	;
+	text_jump UnknownText_0x1c0db8
+	db "@"
+; 0x170b5
+
+.CameOutOfItsEgg: ; 0x170b5
+	; came out of its EGG!@ @
+	text_jump UnknownText_0x1c0dba
+	db "@"
+; 0x170ba
+
+.Text_NicknameHatchling: ; 0x170ba
+	; Give a nickname to @ ?
+	text_jump UnknownText_0x1c0dd8
+	db "@"
+; 0x170bf
+
+InitEggMoves: ; 170bf
+	call GetHeritableMoves
+	ld d, h
+	ld e, l
+	ld b, NUM_MOVES
+.loop
+	ld a, [de]
+	and a
+	jr z, .done
+	ld hl, wEggMonMoves
+	ld c, NUM_MOVES
+.next
+	ld a, [de]
+	cp [hl]
+	jr z, .skip
+	inc hl
+	dec c
+	jr nz, .next
+	call GetEggMove
+	jr nc, .skip
+	call LoadEggMove
+
+.skip
+	inc de
+	dec b
+	jr nz, .loop
+
+.done
+	ret
+; 170e4
+
+GetEggMove: ; 170e4
+	push bc
+	ld a, [wEggMonSpecies]
+	dec a
+	ld c, a
+	ld b, 0
+	ld hl, EggMovePointers
+	add hl, bc
+	add hl, bc
+	ld a, BANK(EggMovePointers)
+	call GetFarHalfword
+.loop
+	ld a, BANK(EggMoves)
+	call GetFarByte
+	cp -1
+	jr z, .reached_end
+	ld b, a
+	ld a, [de]
+	cp b
+	jr z, .done_carry
+	inc hl
+	jr .loop
+
+.reached_end
+	call GetBreedmonMovePointer
+	ld b, NUM_MOVES
+.loop2
+	ld a, [de]
+	cp [hl]
+	jr z, .found_eggmove
+	inc hl
+	dec b
+	jr z, .inherit_tmhm
+	jr .loop2
+
+.found_eggmove
+	ld a, [wEggMonSpecies]
+	dec a
+	ld c, a
+	ld b, 0
+	ld hl, EvosAttacksPointers
+	add hl, bc
+	add hl, bc
+	ld a, BANK(EvosAttacksPointers)
+	call GetFarHalfword
+.loop3
+	ld a, BANK(EvosAttacks)
+	call GetFarByte
+	inc hl
+	and a
+	jr nz, .loop3
+.loop4
+	ld a, BANK(EvosAttacks)
+	call GetFarByte
+	and a
+	jr z, .inherit_tmhm
+	inc hl
+	ld a, BANK(EvosAttacks)
+	call GetFarByte
+	ld b, a
+	ld a, [de]
+	cp b
+	jr z, .done_carry
+	inc hl
+	jr .loop4
+
+.inherit_tmhm
+	ld hl, TMHMMoves
+.loop5
+	ld a, BANK(TMHMMoves)
+	call GetFarByte
+	inc hl
+	and a
+	jr z, .done
+	ld b, a
+	ld a, [de]
+	cp b
+	jr nz, .loop5
+	ld [wPutativeTMHMMove], a
+	predef CanLearnTMHMMove
+	ld a, c
+	and a
+	jr z, .done
+
+.done_carry
+	pop bc
+	scf
+	ret
+
+.done
+	pop bc
+	and a
+	ret
+; 17169
+
+LoadEggMove: ; 17169
+	push de
+	push bc
+	ld a, [de]
+	ld b, a
+	ld hl, wEggMonMoves
+	ld c, NUM_MOVES
+.loop
+	ld a, [hli]
+	and a
+	jr z, .done
+	dec c
+	jr nz, .loop
+	ld de, wEggMonMoves
+	ld hl, wEggMonMoves + 1
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hli]
+	ld [de], a
+
+.done
+	dec hl
+	ld [hl], b
+	ld hl, wEggMonMoves
+	ld de, wEggMonPP
+	predef FillPP
+	pop bc
+	pop de
+	ret
+; 17197
+
+GetHeritableMoves: ; 17197
+	ld hl, wBreedMon2Moves
+	ld a, [wBreedMon1Species]
+	cp DITTO
+	jr z, .ditto1
+	ld a, [wBreedMon2Species]
+	cp DITTO
+	jr z, .ditto2
+	ld a, [wBreedMotherOrNonDitto]
+	and a
+	ret z
+	ld hl, wBreedMon1Moves
+	ret
+
+.ditto1
+	ld a, [wCurPartySpecies]
+	push af
+	ld a, [wBreedMon2Species]
+	ld [wCurPartySpecies], a
+	ld a, [wBreedMon2DVs]
+	ld [wTempMonDVs], a
+	ld a, [wBreedMon2DVs + 1]
+	ld [wTempMonDVs + 1], a
+	ld a, TEMPMON
+	ld [wMonType], a
+	predef GetGender
+	jr c, .inherit_mon2_moves
+	jr nz, .inherit_mon2_moves
+	jr .inherit_mon1_moves
+
+.ditto2
+	ld a, [wCurPartySpecies]
+	push af
+	ld a, [wBreedMon1Species]
+	ld [wCurPartySpecies], a
+	ld a, [wBreedMon1DVs]
+	ld [wTempMonDVs], a
+	ld a, [wBreedMon1DVs + 1]
+	ld [wTempMonDVs + 1], a
+	ld a, TEMPMON
+	ld [wMonType], a
+	predef GetGender
+	jr c, .inherit_mon1_moves
+	jr nz, .inherit_mon1_moves
+
+.inherit_mon2_moves
+	ld hl, wBreedMon2Moves
+	pop af
+	ld [wCurPartySpecies], a
+	ret
+
+.inherit_mon1_moves
+	ld hl, wBreedMon1Moves
+	pop af
+	ld [wCurPartySpecies], a
+	ret
+; 1720b
+
+GetBreedmonMovePointer: ; 1720b
+	ld hl, wBreedMon1Moves
+	ld a, [wBreedMon1Species]
+	cp DITTO
+	ret z
+	ld a, [wBreedMon2Species]
+	cp DITTO
+	jr z, .ditto
+	ld a, [wBreedMotherOrNonDitto]
+	and a
+	ret z
+
+.ditto
+	ld hl, wBreedMon2Moves
+	ret
+; 17224
+
+
+GetEggFrontpic: ; 17224 (5:7224)
+	push de
+	ld [wCurPartySpecies], a
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld hl, wBattleMonDVs
+	predef GetUnownLetter
+	pop de
+	predef_jump GetMonFrontpic
+
+GetHatchlingFrontpic: ; 1723c (5:723c)
+	push de
+	ld [wCurPartySpecies], a
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld hl, wBattleMonDVs
+	predef GetUnownLetter
+	pop de
+	predef_jump GetAnimatedFrontpic
+
+Hatch_UpdateFrontpicBGMapCenter: ; 17254 (5:7254)
+	push af
+	call WaitTop
+	push hl
+	push bc
+	hlcoord 0, 0
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	ld a, " "
+	call ByteFill
+	pop bc
+	pop hl
+	ld a, b
+	ld [hBGMapAddress + 1], a
+	ld a, c
+	ld [hGraphicStartTile], a
+	lb bc, 7, 7
+	predef PlaceGraphic
+	pop af
+	call Hatch_LoadFrontpicPal
+	call SetPalettes
+	jp WaitBGMap
+
+EggHatch_DoAnimFrame: ; 1727f (5:727f)
+	push hl
+	push de
+	push bc
+	callfar PlaySpriteAnimations
+	call DelayFrame
+	pop bc
+	pop de
+	pop hl
+	ret
+
+EggHatch_AnimationSequence: ; 1728f (5:728f)
+	ld a, [wd265]
+	ld [wJumptableIndex], a
+	ld a, [wCurSpecies]
+	push af
+	ld de, MUSIC_NONE
+	call PlayMusic
+	farcall BlankScreen
+	call DisableLCD
+	ld hl, EggHatchGFX
+	ld de, vTiles0 tile $00
+	ld bc, 2 tiles
+	ld a, BANK(EggHatchGFX)
+	call FarCopyBytes
+	farcall ClearSpriteAnims
+	ld de, vTiles2 tile $00
+	ld a, [wJumptableIndex]
+	call GetHatchlingFrontpic
+	ld de, vTiles2 tile $31
+	ld a, EGG
+	call GetEggFrontpic
+	ld de, MUSIC_EVOLUTION
+	call PlayMusic
+	call EnableLCD
+	hlcoord 7, 4
+	ld b, HIGH(vBGMap0)
+	ld c, $31 ; Egg tiles start here
+	ld a, EGG
+	call Hatch_UpdateFrontpicBGMapCenter
+	ld c, 80
+	call DelayFrames
+	xor a
+	ld [wFrameCounter], a
+	ld a, [hSCX]
+	ld b, a
+.outerloop
+	ld hl, wFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp 8
+	jr nc, .done
+	ld e, [hl]
+.loop
+; wobble e times
+	ld a, 2
+	ld [hSCX], a
+	ld a, -2
+	ld [wGlobalAnimXOffset], a
+	call EggHatch_DoAnimFrame
+	ld c, 2
+	call DelayFrames
+	ld a, -2
+	ld [hSCX], a
+	ld a, 2
+	ld [wGlobalAnimXOffset], a
+	call EggHatch_DoAnimFrame
+	ld c, 2
+	call DelayFrames
+	dec e
+	jr nz, .loop
+	ld c, 16
+	call DelayFrames
+	call EggHatch_CrackShell
+	jr .outerloop
+
+.done
+	ld de, SFX_EGG_HATCH
+	call PlaySFX
+	xor a
+	ld [hSCX], a
+	ld [wGlobalAnimXOffset], a
+	call ClearSprites
+	call Hatch_InitShellFragments
+	hlcoord 6, 3
+	ld b, HIGH(vBGMap0)
+	ld c, $00 ; Hatchling tiles start here
+	ld a, [wJumptableIndex]
+	call Hatch_UpdateFrontpicBGMapCenter
+	call Hatch_ShellFragmentLoop
+	call WaitSFX
+	ld a, [wJumptableIndex]
+	ld [wCurPartySpecies], a
+	hlcoord 6, 3
+	ld d, $0
+	ld e, ANIM_MON_HATCH
+	predef AnimateFrontpic
+	pop af
+	ld [wCurSpecies], a
+	ret
+
+Hatch_LoadFrontpicPal: ; 17363 (5:7363)
+	ld [wPlayerHPPal], a
+	ld b, SCGB_EVOLUTION
+	ld c, $0
+	jp GetSGBLayout
+
+EggHatch_CrackShell: ; 1736d (5:736d)
+	ld a, [wFrameCounter]
+	dec a
+	and $7
+	cp $7
+	ret z
+	srl a
+	ret nc
+	swap a
+	srl a
+	add 9 * 8 + 4
+	ld d, a
+	ld e, 11 * 8
+	ld a, SPRITE_ANIM_INDEX_EGG_CRACK
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_TILE_ID
+	add hl, bc
+	ld [hl], $0
+	ld de, SFX_EGG_CRACK
+	jp PlaySFX
+; 17393 (5:7393)
+
+EggHatchGFX: ; 17393
+INCBIN "gfx/evo/egg_hatch.2bpp"
+; 173b3
+
+Hatch_InitShellFragments: ; 173b3 (5:73b3)
+	farcall ClearSpriteAnims
+	ld hl, .SpriteData
+.loop
+	ld a, [hli]
+	cp -1
+	jr z, .done
+	ld e, a
+	ld a, [hli]
+	ld d, a
+	ld a, [hli]
+	ld c, a
+	ld a, [hli]
+	ld b, a
+	push hl
+	push bc
+
+	ld a, SPRITE_ANIM_INDEX_EGG_HATCH
+	call _InitSpriteAnimStruct
+
+	ld hl, SPRITEANIMSTRUCT_TILE_ID
+	add hl, bc
+	ld [hl], $0
+
+	pop de
+	ld a, e
+	ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
+	add hl, bc
+	add [hl]
+	ld [hl], a
+
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld [hl], d
+
+	pop hl
+	jr .loop
+.done
+	ld de, SFX_EGG_HATCH
+	call PlaySFX
+	call EggHatch_DoAnimFrame
+	ret
+; 173ef (5:73ef)
+
+shell_fragment: MACRO
+; y tile, y pxl, x tile, x pxl, frameset offset, ???
+	db (\1 * 8) % $100 + \2, (\3 * 8) % $100 + \4, \5 - SPRITE_ANIM_FRAMESET_EGG_HATCH_1, \6
+ENDM
+
+.SpriteData: ; 173ef
+	shell_fragment 10, 4,  9, 0, SPRITE_ANIM_FRAMESET_EGG_HATCH_1, $3c
+	shell_fragment 11, 4,  9, 0, SPRITE_ANIM_FRAMESET_EGG_HATCH_2, $04
+	shell_fragment 10, 4, 10, 0, SPRITE_ANIM_FRAMESET_EGG_HATCH_1, $30
+	shell_fragment 11, 4, 10, 0, SPRITE_ANIM_FRAMESET_EGG_HATCH_2, $10
+	shell_fragment 10, 4, 11, 0, SPRITE_ANIM_FRAMESET_EGG_HATCH_3, $24
+	shell_fragment 11, 4, 11, 0, SPRITE_ANIM_FRAMESET_EGG_HATCH_4, $1c
+	shell_fragment 10, 0,  9, 4, SPRITE_ANIM_FRAMESET_EGG_HATCH_1, $36
+	shell_fragment 12, 0,  9, 4, SPRITE_ANIM_FRAMESET_EGG_HATCH_2, $0a
+	shell_fragment 10, 0, 10, 4, SPRITE_ANIM_FRAMESET_EGG_HATCH_3, $2a
+	shell_fragment 12, 0, 10, 4, SPRITE_ANIM_FRAMESET_EGG_HATCH_4, $16
+	db -1
+; 17418
+
+Hatch_ShellFragmentLoop: ; 17418 (5:7418)
+	ld c, 129
+.loop
+	call EggHatch_DoAnimFrame
+	dec c
+	jr nz, .loop
+	ret
+
+DayCareMon1: ; 17421
+	ld hl, DayCareMon1Text
+	call PrintText
+	ld a, [wBreedMon1Species]
+	call PlayMonCry
+	ld a, [wDayCareLady]
+	bit DAYCARELADY_HAS_MON_F, a
+	jr z, DayCareMonCursor
+	call ButtonSound
+	ld hl, wBreedMon2Nick
+	call DayCareMonCompatibilityText
+	jp PrintText
+
+DayCareMon2: ; 17440
+	ld hl, DayCareMon2Text
+	call PrintText
+	ld a, [wBreedMon2Species]
+	call PlayMonCry
+	ld a, [wDayCareMan]
+	bit DAYCAREMAN_HAS_MON_F, a
+	jr z, DayCareMonCursor
+	call ButtonSound
+	ld hl, wBreedMon1Nick
+	call DayCareMonCompatibilityText
+	jp PrintText
+
+DayCareMonCursor: ; 1745f
+	jp WaitPressAorB_BlinkCursor
+; 17462
+
+DayCareMon2Text: ; 0x17462
+	; It's @ that was left with the DAY-CARE LADY.
+	text_jump UnknownText_0x1c0df3
+	db "@"
+; 0x17467
+
+DayCareMon1Text: ; 0x17467
+	; It's @ that was left with the DAY-CARE MAN.
+	text_jump UnknownText_0x1c0e24
+	db "@"
+; 0x1746c
+
+DayCareMonCompatibilityText: ; 1746c
+	push bc
+	ld de, wStringBuffer1
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	call CheckBreedmonCompatibility
+	pop bc
+	ld a, [wd265]
+	ld hl, .AllAlone
+	cp -1
+	jr z, .done
+	ld hl, .Incompatible
+	and a
+	jr z, .done
+	ld hl, .HighCompatibility
+	cp 230
+	jr nc, .done
+	cp 70
+	ld hl, .ModerateCompatibility
+	jr nc, .done
+	ld hl, .SlightCompatibility
+
+.done
+	ret
+; 1749c
+
+.AllAlone: ; 0x1749c
+	; It's brimming with energy.
+	text_jump UnknownText_0x1c0e54
+	db "@"
+; 0x174a1
+
+.Incompatible: ; 0x174a1
+	; It has no interest in @ .
+	text_jump UnknownText_0x1c0e6f
+	db "@"
+; 0x174a6
+
+.HighCompatibility: ; 0x174a6
+	; It appears to care for @ .
+	text_jump UnknownText_0x1c0e8d
+	db "@"
+; 0x174ab
+
+.ModerateCompatibility: ; 0x174ab
+	; It's friendly with @ .
+	text_jump UnknownText_0x1c0eac
+	db "@"
+; 0x174b0
+
+.SlightCompatibility: ; 0x174b0
+	; It shows interest in @ .
+	text_jump UnknownText_0x1c0ec6
+	db "@"
+; 0x174b5
+
+Unreferenced_DayCareMonPrintEmptyString: ; 174b5
+	ld hl, .string
+	ret
+; 174b9
+
+.string ; 174b9
+	db "@"
+; 174ba
+
--- /dev/null
+++ b/engine/pokemon/caught_data.asm
@@ -1,0 +1,247 @@
+CheckPartyFullAfterContest: ; 4d9e5
+	ld a, [wContestMon]
+	and a
+	jp z, .DidntCatchAnything
+	ld [wCurPartySpecies], a
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld hl, wPartyCount
+	ld a, [hl]
+	cp PARTY_LENGTH
+	jp nc, .TryAddToBox
+	inc a
+	ld [hl], a
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [wContestMon]
+	ld [hli], a
+	ld [wCurSpecies], a
+	ld a, -1
+	ld [hl], a
+	ld hl, wPartyMon1Species
+	ld a, [wPartyCount]
+	dec a
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld hl, wContestMon
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call CopyBytes
+	ld a, [wPartyCount]
+	dec a
+	ld hl, wPartyMonOT
+	call SkipNames
+	ld d, h
+	ld e, l
+	ld hl, wPlayerName
+	call CopyBytes
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	call GetPokemonName
+	ld hl, wStringBuffer1
+	ld de, wMonOrItemNameBuffer
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+	call GiveANickname_YesNo
+	jr c, .Party_SkipNickname
+	ld a, [wPartyCount]
+	dec a
+	ld [wCurPartyMon], a
+	xor a
+	ld [wMonType], a
+	ld de, wMonOrItemNameBuffer
+	callfar InitNickname
+
+.Party_SkipNickname:
+	ld a, [wPartyCount]
+	dec a
+	ld hl, wPartyMonNicknames
+	call SkipNames
+	ld d, h
+	ld e, l
+	ld hl, wMonOrItemNameBuffer
+	call CopyBytes
+	ld a, [wPartyCount]
+	dec a
+	ld hl, wPartyMon1Level
+	call GetPartyLocation
+	ld a, [hl]
+	ld [wCurPartyLevel], a
+	call SetCaughtData
+	ld a, [wPartyCount]
+	dec a
+	ld hl, wPartyMon1CaughtLocation
+	call GetPartyLocation
+	ld a, [hl]
+	and CAUGHT_GENDER_MASK
+	ld b, NATIONAL_PARK
+	or b
+	ld [hl], a
+	xor a
+	ld [wContestMon], a
+	and a ; BUGCONTEST_CAUGHT_MON
+	ld [wScriptVar], a
+	ret
+
+.TryAddToBox: ; 4daa3
+	ld a, BANK(sBoxCount)
+	call GetSRAMBank
+	ld hl, sBoxCount
+	ld a, [hl]
+	cp MONS_PER_BOX
+	call CloseSRAM
+	jr nc, .BoxFull
+	xor a
+	ld [wCurPartyMon], a
+	ld hl, wContestMon
+	ld de, wBufferMon
+	ld bc, BOXMON_STRUCT_LENGTH
+	call CopyBytes
+	ld hl, wPlayerName
+	ld de, wBufferMonOT
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	callfar InsertPokemonIntoBox
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	call GetPokemonName
+	call GiveANickname_YesNo
+	ld hl, wStringBuffer1
+	jr c, .Box_SkipNickname
+	ld a, BOXMON
+	ld [wMonType], a
+	ld de, wMonOrItemNameBuffer
+	callfar InitNickname
+	ld hl, wMonOrItemNameBuffer
+
+.Box_SkipNickname:
+	ld a, BANK(sBoxMonNicknames)
+	call GetSRAMBank
+	ld de, sBoxMonNicknames
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+	call CloseSRAM
+
+.BoxFull:
+	ld a, BANK(sBoxMon1Level)
+	call GetSRAMBank
+	ld a, [sBoxMon1Level]
+	ld [wCurPartyLevel], a
+	call CloseSRAM
+	call SetBoxMonCaughtData
+	ld a, BANK(sBoxMon1CaughtLocation)
+	call GetSRAMBank
+	ld hl, sBoxMon1CaughtLocation
+	ld a, [hl]
+	and CAUGHT_GENDER_MASK
+	ld b, NATIONAL_PARK
+	or b
+	ld [hl], a
+	call CloseSRAM
+	xor a
+	ld [wContestMon], a
+	ld a, BUGCONTEST_BOXED_MON
+	ld [wScriptVar], a
+	ret
+
+.DidntCatchAnything: ; 4db35
+	ld a, BUGCONTEST_NO_CATCH
+	ld [wScriptVar], a
+	ret
+
+GiveANickname_YesNo: ; 4db3b
+	ld hl, TextJump_GiveANickname
+	call PrintText
+	jp YesNoBox
+
+TextJump_GiveANickname: ; 0x4db44
+	; Give a nickname to the @  you received?
+	text_jump UnknownText_0x1c12fc
+	db "@"
+
+SetCaughtData: ; 4db49
+	ld a, [wPartyCount]
+	dec a
+	ld hl, wPartyMon1CaughtLevel
+	call GetPartyLocation
+SetBoxmonOrEggmonCaughtData: ; 4db53
+	ld a, [wTimeOfDay]
+	inc a
+	rrca
+	rrca
+	ld b, a
+	ld a, [wCurPartyLevel]
+	or b
+	ld [hli], a
+	ld a, [wMapGroup]
+	ld b, a
+	ld a, [wMapNumber]
+	ld c, a
+	cp MAP_POKECENTER_2F
+	jr nz, .NotPokecenter2F
+	ld a, b
+	cp GROUP_POKECENTER_2F
+	jr nz, .NotPokecenter2F
+
+	ld a, [wBackupMapGroup]
+	ld b, a
+	ld a, [wBackupMapNumber]
+	ld c, a
+
+.NotPokecenter2F:
+	call GetWorldMapLocation
+	ld b, a
+	ld a, [wPlayerGender]
+	rrca ; shift bit 0 (PLAYERGENDER_FEMALE_F) to bit 7 (CAUGHT_GENDER_MASK)
+	or b
+	ld [hl], a
+	ret
+
+SetBoxMonCaughtData: ; 4db83
+	ld a, BANK(sBoxMon1CaughtLevel)
+	call GetSRAMBank
+	ld hl, sBoxMon1CaughtLevel
+	call SetBoxmonOrEggmonCaughtData
+	call CloseSRAM
+	ret
+
+SetGiftBoxMonCaughtData: ; 4db92
+	push bc
+	ld a, BANK(sBoxMon1CaughtLevel)
+	call GetSRAMBank
+	ld hl, sBoxMon1CaughtLevel
+	pop bc
+	call SetGiftMonCaughtData
+	call CloseSRAM
+	ret
+
+SetGiftPartyMonCaughtData: ; 4dba3
+	ld a, [wPartyCount]
+	dec a
+	ld hl, wPartyMon1CaughtLevel
+	push bc
+	call GetPartyLocation
+	pop bc
+SetGiftMonCaughtData: ; 4dbaf
+	xor a
+	ld [hli], a
+	ld a, GIFT_LOCATION
+	rrc b
+	or b
+	ld [hl], a
+	ret
+
+SetEggMonCaughtData: ; 4dbb8 (13:5bb8)
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1CaughtLevel
+	call GetPartyLocation
+	ld a, [wCurPartyLevel]
+	push af
+	ld a, CAUGHT_EGG_LEVEL
+	ld [wCurPartyLevel], a
+	call SetBoxmonOrEggmonCaughtData
+	pop af
+	ld [wCurPartyLevel], a
+	ret
--- /dev/null
+++ b/engine/pokemon/european_mail.asm
@@ -1,0 +1,129 @@
+IsMailEuropean: ; 1de5c8
+; return 1 if French
+; return 2 if German
+; return 3 if Italian
+; return 4 if Spanish
+; return 0 if none of the above
+	ld c, $0
+	ld hl, sPartyMon1MailAuthorNationality - sPartyMon1Mail
+	add hl, de
+	ld a, [hli]
+	cp "E"
+	ret nz
+	ld a, [hli]
+	inc c
+	cp "F"
+	ret z
+	inc c
+	cp "G"
+	ret z
+	inc c
+	cp "I"
+	ret z
+	inc c
+	cp "S"
+	ret z
+	ld c, $0
+	ret
+
+; The regular font.
+StandardEnglishFont: ; 1de5e6
+INCBIN "gfx/font/english.1bpp"
+
+; An extended font.
+FrenchGermanFont: ; 1de9e6
+INCBIN "gfx/font/french_german.1bpp"
+
+; An even more extended font.
+SpanishItalianFont: ; 1dede6
+INCBIN "gfx/font/spanish_italian.1bpp"
+
+HandleFrenchGermanMail: ; 1df1e6
+; called if mail is french or german
+; fix 's 't 'v
+	ld b, sPartyMon1MailAuthor - sPartyMon1Mail
+	ld h, d
+	ld l, e
+.loop
+	ld a, [hl]
+	cp $dc ; 's in french/german font
+	jr nz, .check_intermediate_chars
+	ld a, "'s"
+	jr .replace
+
+.check_intermediate_chars
+	sub "'s"
+	jr c, .dont_replace
+	cp "'v" - "'s" + 1
+	jr nc, .dont_replace
+	add $cd
+
+.replace
+	ld [hl], a
+
+.dont_replace
+	inc hl
+	dec b
+	jr nz, .loop
+	ret
+
+LireLeCourrierAnglais:
+DeutenEnglischenPost: ; 1df203
+; Cette fonction convertit certains des caractères anglais pour
+; leur équivalent dans le jeu de caractères français.
+; Diese Funktion wandelt bestimmte englische Zeichen, um ihre
+; Entsprechung in der Deutschen-Zeichensatz.
+	ld b, sPartyMon1MailAuthor - sPartyMon1Mail
+	ld h, d
+	ld l, e
+.loop
+	ld a, [hl]
+	cp "'s"
+	jr nz, .check_intermediate_chars
+	ld a, $dc
+	jr .replace
+
+.check_intermediate_chars
+	sub $cd
+	jr c, .dont_replace
+	cp "'v" - "'s" + 1
+	jr nc, .dont_replace
+	add "'s"
+
+.replace
+	ld [hl], a
+
+.dont_replace
+	inc hl
+	dec b
+	jr nz, .loop
+	ret
+
+HandleSpanishItalianMail: ; 1df220
+LeerCorreosIngleses:
+LeggiPostaInglese:
+; This function converts certain characters between
+; the English and Spanish/Italian character sets.
+; Esta función convierte ciertos caracteres entre
+; el juego de caracteres Inglés y Español.
+; Questa funzione converte alcuni caratteri tra
+; l'inglese e il set di caratteri italiani.
+	ld b, sPartyMon1MailAuthor - sPartyMon1Mail
+	ld h, d
+	ld l, e
+.loop
+	ld a, [hl]
+	and $f0
+	cp $d0
+	jr nz, .dont_replace
+	ld a, [hl]
+	add $8
+	and $f
+	or $d0
+	ld [hl], a
+
+.dont_replace
+	inc hl
+	dec b
+	jr nz, .loop
+	ret
--- /dev/null
+++ b/engine/pokemon/evolve.asm
@@ -1,0 +1,676 @@
+EvolvePokemon: ; 421d8
+	ld hl, wEvolvableFlags
+	xor a
+	ld [hl], a
+	ld a, [wCurPartyMon]
+	ld c, a
+	ld b, SET_FLAG
+	call EvoFlagAction
+EvolveAfterBattle: ; 421e6
+	xor a
+	ld [wMonTriedToEvolve], a
+	dec a
+	ld [wCurPartyMon], a
+	push hl
+	push bc
+	push de
+	ld hl, wPartyCount
+
+	push hl
+
+EvolveAfterBattle_MasterLoop
+	ld hl, wCurPartyMon
+	inc [hl]
+
+	pop hl
+
+	inc hl
+	ld a, [hl]
+	cp $ff
+	jp z, .ReturnToMap
+
+	ld [wEvolutionOldSpecies], a
+
+	push hl
+	ld a, [wCurPartyMon]
+	ld c, a
+	ld hl, wEvolvableFlags
+	ld b, CHECK_FLAG
+	call EvoFlagAction
+	ld a, c
+	and a
+	jp z, EvolveAfterBattle_MasterLoop
+
+	ld a, [wEvolutionOldSpecies]
+	dec a
+	ld b, 0
+	ld c, a
+	ld hl, EvosAttacksPointers
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+
+	push hl
+	xor a
+	ld [wMonType], a
+	predef CopyMonToTempMon
+	pop hl
+
+.loop
+	ld a, [hli]
+	and a
+	jr z, EvolveAfterBattle_MasterLoop
+
+	ld b, a
+
+	cp EVOLVE_TRADE
+	jr z, .trade
+
+	ld a, [wLinkMode]
+	and a
+	jp nz, .dont_evolve_2
+
+	ld a, b
+	cp EVOLVE_ITEM
+	jp z, .item
+
+	ld a, [wForceEvolution]
+	and a
+	jp nz, .dont_evolve_2
+
+	ld a, b
+	cp EVOLVE_LEVEL
+	jp z, .level
+
+	cp EVOLVE_HAPPINESS
+	jr z, .happiness
+
+
+; EVOLVE_STAT
+	ld a, [wTempMonLevel]
+	cp [hl]
+	jp c, .dont_evolve_1
+
+	call IsMonHoldingEverstone
+	jp z, .dont_evolve_1
+
+	push hl
+	ld de, wTempMonAttack
+	ld hl, wTempMonDefense
+	ld c, 2
+	call StringCmp
+	ld a, ATK_EQ_DEF
+	jr z, .got_tyrogue_evo
+	ld a, ATK_LT_DEF
+	jr c, .got_tyrogue_evo
+	ld a, ATK_GT_DEF
+.got_tyrogue_evo
+	pop hl
+
+	inc hl
+	cp [hl]
+	jp nz, .dont_evolve_2
+
+	inc hl
+	jr .proceed
+
+
+.happiness
+	ld a, [wTempMonHappiness]
+	cp HAPPINESS_TO_EVOLVE
+	jp c, .dont_evolve_2
+
+	call IsMonHoldingEverstone
+	jp z, .dont_evolve_2
+
+	ld a, [hli]
+	cp TR_ANYTIME
+	jr z, .proceed
+	cp TR_MORNDAY
+	jr z, .happiness_daylight
+
+; TR_NITE
+	ld a, [wTimeOfDay]
+	cp NITE_F
+	jp nz, .dont_evolve_3
+	jr .proceed
+
+.happiness_daylight
+	ld a, [wTimeOfDay]
+	cp NITE_F
+	jp z, .dont_evolve_3
+	jr .proceed
+
+
+.trade
+	ld a, [wLinkMode]
+	and a
+	jp z, .dont_evolve_2
+
+	call IsMonHoldingEverstone
+	jp z, .dont_evolve_2
+
+	ld a, [hli]
+	ld b, a
+	inc a
+	jr z, .proceed
+
+	ld a, [wLinkMode]
+	cp LINK_TIMECAPSULE
+	jp z, .dont_evolve_3
+
+	ld a, [wTempMonItem]
+	cp b
+	jp nz, .dont_evolve_3
+
+	xor a
+	ld [wTempMonItem], a
+	jr .proceed
+
+
+.item
+	ld a, [hli]
+	ld b, a
+	ld a, [wCurItem]
+	cp b
+	jp nz, .dont_evolve_3
+
+	ld a, [wForceEvolution]
+	and a
+	jp z, .dont_evolve_3
+	ld a, [wLinkMode]
+	and a
+	jp nz, .dont_evolve_3
+	jr .proceed
+
+
+.level
+	ld a, [hli]
+	ld b, a
+	ld a, [wTempMonLevel]
+	cp b
+	jp c, .dont_evolve_3
+	call IsMonHoldingEverstone
+	jp z, .dont_evolve_3
+
+.proceed
+	ld a, [wTempMonLevel]
+	ld [wCurPartyLevel], a
+	ld a, $1
+	ld [wMonTriedToEvolve], a
+
+	push hl
+
+	ld a, [hl]
+	ld [wEvolutionNewSpecies], a
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMonNicknames
+	call GetNick
+	call CopyName1
+	ld hl, Text_WhatEvolving
+	call PrintText
+
+	ld c, 50
+	call DelayFrames
+
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 0, 0
+	lb bc, 12, 20
+	call ClearBox
+
+	ld a, $1
+	ld [hBGMapMode], a
+	call ClearSprites
+
+	farcall EvolutionAnimation
+
+	push af
+	call ClearSprites
+	pop af
+	jp c, CancelEvolution
+
+	ld hl, Text_CongratulationsYourPokemon
+	call PrintText
+
+	pop hl
+
+	ld a, [hl]
+	ld [wCurSpecies], a
+	ld [wTempMonSpecies], a
+	ld [wEvolutionNewSpecies], a
+	ld [wd265], a
+	call GetPokemonName
+
+	push hl
+	ld hl, Text_EvolvedIntoPKMN
+	call PrintTextBoxText
+	farcall StubbedTrainerRankings_MonsEvolved
+
+	ld de, MUSIC_NONE
+	call PlayMusic
+	ld de, SFX_CAUGHT_MON
+	call PlaySFX
+	call WaitSFX
+
+	ld c, 40
+	call DelayFrames
+
+	call ClearTileMap
+	call UpdateSpeciesNameIfNotNicknamed
+	call GetBaseData
+
+	ld hl, wTempMonExp + 2
+	ld de, wTempMonMaxHP
+	ld b, TRUE
+	predef CalcMonStats
+
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMons
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld e, l
+	ld d, h
+	ld bc, MON_MAXHP
+	add hl, bc
+	ld a, [hli]
+	ld b, a
+	ld c, [hl]
+	ld hl, wTempMonMaxHP + 1
+	ld a, [hld]
+	sub c
+	ld c, a
+	ld a, [hl]
+	sbc b
+	ld b, a
+	ld hl, wTempMonHP + 1
+	ld a, [hl]
+	add c
+	ld [hld], a
+	ld a, [hl]
+	adc b
+	ld [hl], a
+
+	ld hl, wTempMonSpecies
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call CopyBytes
+
+	ld a, [wCurSpecies]
+	ld [wd265], a
+	xor a
+	ld [wMonType], a
+	call LearnLevelMoves
+	ld a, [wd265]
+	dec a
+	call SetSeenAndCaughtMon
+
+	ld a, [wd265]
+	cp UNOWN
+	jr nz, .skip_unown
+
+	ld hl, wTempMonDVs
+	predef GetUnownLetter
+	callfar UpdateUnownDex
+
+.skip_unown
+	pop de
+	pop hl
+	ld a, [wTempMonSpecies]
+	ld [hl], a
+	push hl
+	ld l, e
+	ld h, d
+	jp EvolveAfterBattle_MasterLoop
+; 423f8
+
+.dont_evolve_1
+	inc hl
+.dont_evolve_2
+	inc hl
+.dont_evolve_3
+	inc hl
+	jp .loop
+
+; unused
+	pop hl
+.ReturnToMap:
+	pop de
+	pop bc
+	pop hl
+	ld a, [wLinkMode]
+	and a
+	ret nz
+	ld a, [wBattleMode]
+	and a
+	ret nz
+	ld a, [wMonTriedToEvolve]
+	and a
+	call nz, RestartMapMusic
+	ret
+; 42414
+
+UpdateSpeciesNameIfNotNicknamed: ; 42414
+	ld a, [wCurSpecies]
+	push af
+	ld a, [wBaseDexNo]
+	ld [wd265], a
+	call GetPokemonName
+	pop af
+	ld [wCurSpecies], a
+	ld hl, wStringBuffer1
+	ld de, wStringBuffer2
+.loop
+	ld a, [de]
+	inc de
+	cp [hl]
+	inc hl
+	ret nz
+	cp "@"
+	jr nz, .loop
+
+	ld a, [wCurPartyMon]
+	ld bc, MON_NAME_LENGTH
+	ld hl, wPartyMonNicknames
+	call AddNTimes
+	push hl
+	ld a, [wCurSpecies]
+	ld [wd265], a
+	call GetPokemonName
+	ld hl, wStringBuffer1
+	pop de
+	ld bc, MON_NAME_LENGTH
+	jp CopyBytes
+; 42454
+
+CancelEvolution: ; 42454
+	ld hl, Text_StoppedEvolving
+	call PrintText
+	call ClearTileMap
+	pop hl
+	jp EvolveAfterBattle_MasterLoop
+; 42461
+
+IsMonHoldingEverstone: ; 42461
+	push hl
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1Item
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [hl]
+	cp EVERSTONE
+	pop hl
+	ret
+; 42473
+
+Text_CongratulationsYourPokemon: ; 0x42473
+	; Congratulations! Your @ @
+	text_jump UnknownText_0x1c4b92
+	db "@"
+; 0x42478
+
+Text_EvolvedIntoPKMN: ; 0x42478
+	; evolved into @ !
+	text_jump UnknownText_0x1c4baf
+	db "@"
+; 0x4247d
+
+Text_StoppedEvolving: ; 0x4247d
+	; Huh? @ stopped evolving!
+	text_jump UnknownText_0x1c4bc5
+	db "@"
+; 0x42482
+
+Text_WhatEvolving: ; 0x42482
+	; What? @ is evolving!
+	text_jump UnknownText_0x1c4be3
+	db "@"
+; 0x42487
+
+
+LearnLevelMoves: ; 42487
+	ld a, [wd265]
+	ld [wCurPartySpecies], a
+	dec a
+	ld b, 0
+	ld c, a
+	ld hl, EvosAttacksPointers
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+
+.skip_evos
+	ld a, [hli]
+	and a
+	jr nz, .skip_evos
+
+.find_move
+	ld a, [hli]
+	and a
+	jr z, .done
+
+	ld b, a
+	ld a, [wCurPartyLevel]
+	cp b
+	ld a, [hli]
+	jr nz, .find_move
+
+	push hl
+	ld d, a
+	ld hl, wPartyMon1Moves
+	ld a, [wCurPartyMon]
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+
+	ld b, NUM_MOVES
+.check_move
+	ld a, [hli]
+	cp d
+	jr z, .has_move
+	dec b
+	jr nz, .check_move
+	jr .learn
+.has_move
+
+	pop hl
+	jr .find_move
+
+.learn
+	ld a, d
+	ld [wPutativeTMHMMove], a
+	ld [wd265], a
+	call GetMoveName
+	call CopyName1
+	predef LearnMove
+	pop hl
+	jr .find_move
+
+.done
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	ret
+; 424e1
+
+
+FillMoves: ; 424e1
+; Fill in moves at de for wCurPartySpecies at wCurPartyLevel
+
+	push hl
+	push de
+	push bc
+	ld hl, EvosAttacksPointers
+	ld b, 0
+	ld a, [wCurPartySpecies]
+	dec a
+	add a
+	rl b
+	ld c, a
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+.GoToAttacks:
+	ld a, [hli]
+	and a
+	jr nz, .GoToAttacks
+	jr .GetLevel
+
+.NextMove:
+	pop de
+.GetMove:
+	inc hl
+.GetLevel:
+	ld a, [hli]
+	and a
+	jp z, .done
+	ld b, a
+	ld a, [wCurPartyLevel]
+	cp b
+	jp c, .done
+	ld a, [wEvolutionOldSpecies]
+	and a
+	jr z, .CheckMove
+	ld a, [wd002]
+	cp b
+	jr nc, .GetMove
+
+.CheckMove:
+	push de
+	ld c, NUM_MOVES
+.CheckRepeat:
+	ld a, [de]
+	inc de
+	cp [hl]
+	jr z, .NextMove
+	dec c
+	jr nz, .CheckRepeat
+	pop de
+	push de
+	ld c, NUM_MOVES
+.CheckSlot:
+	ld a, [de]
+	and a
+	jr z, .LearnMove
+	inc de
+	dec c
+	jr nz, .CheckSlot
+	pop de
+	push de
+	push hl
+	ld h, d
+	ld l, e
+	call ShiftMoves
+	ld a, [wEvolutionOldSpecies]
+	and a
+	jr z, .ShiftedMove
+	push de
+	ld bc, wPartyMon1PP - (wPartyMon1Moves + NUM_MOVES - 1)
+	add hl, bc
+	ld d, h
+	ld e, l
+	call ShiftMoves
+	pop de
+
+.ShiftedMove:
+	pop hl
+
+.LearnMove:
+	ld a, [hl]
+	ld [de], a
+	ld a, [wEvolutionOldSpecies]
+	and a
+	jr z, .NextMove
+	push hl
+	ld a, [hl]
+	ld hl, MON_PP - MON_MOVES
+	add hl, de
+	push hl
+	dec a
+	ld hl, Moves + MOVE_PP
+	ld bc, MOVE_LENGTH
+	call AddNTimes
+	ld a, BANK(Moves)
+	call GetFarByte
+	pop hl
+	ld [hl], a
+	pop hl
+	jr .NextMove
+
+.done
+	pop bc
+	pop de
+	pop hl
+	ret
+; 4256e
+
+ShiftMoves: ; 4256e
+	ld c, NUM_MOVES - 1
+.loop
+	inc de
+	ld a, [de]
+	ld [hli], a
+	dec c
+	jr nz, .loop
+	ret
+; 42577
+
+
+EvoFlagAction: ; 42577
+	push de
+	ld d, $0
+	predef SmallFarFlagAction
+	pop de
+	ret
+; 42581
+
+GetPreEvolution: ; 42581
+; Find the first mon to evolve into wCurPartySpecies.
+
+; Return carry and the new species in wCurPartySpecies
+; if a pre-evolution is found.
+
+	ld c, 0
+.loop ; For each Pokemon...
+	ld hl, EvosAttacksPointers
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+.loop2 ; For each evolution...
+	ld a, [hli]
+	and a
+	jr z, .no_evolve ; If we jump, this Pokemon does not evolve into wCurPartySpecies.
+	cp EVOLVE_STAT ; This evolution type has the extra parameter of stat comparison.
+	jr nz, .not_tyrogue
+	inc hl
+
+.not_tyrogue
+	inc hl
+	ld a, [wCurPartySpecies]
+	cp [hl]
+	jr z, .found_preevo
+	inc hl
+	ld a, [hl]
+	and a
+	jr nz, .loop2
+
+.no_evolve
+	inc c
+	ld a, c
+	cp NUM_POKEMON
+	jr c, .loop
+	and a
+	ret
+
+.found_preevo
+	inc c
+	ld a, c
+	ld [wCurPartySpecies], a
+	scf
+	ret
+; 425b1
--- /dev/null
+++ b/engine/pokemon/experience.asm
@@ -1,0 +1,162 @@
+CalcLevel: ; 50e1b
+	ld a, [wTempMonSpecies]
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld d, 1
+.next_level
+	inc d
+	ld a, d
+	cp LOW(MAX_LEVEL + 1)
+	jr z, .got_level
+	call CalcExpAtLevel
+	push hl
+	ld hl, wTempMonExp + 2
+	ld a, [hProduct + 3]
+	ld c, a
+	ld a, [hld]
+	sub c
+	ld a, [hProduct + 2]
+	ld c, a
+	ld a, [hld]
+	sbc c
+	ld a, [hProduct + 1]
+	ld c, a
+	ld a, [hl]
+	sbc c
+	pop hl
+	jr nc, .next_level
+
+.got_level
+	dec d
+	ret
+
+CalcExpAtLevel: ; 50e47
+; (a/b)*n**3 + c*n**2 + d*n - e
+	ld a, [wBaseGrowthRate]
+	add a
+	add a
+	ld c, a
+	ld b, 0
+	ld hl, GrowthRates
+	add hl, bc
+; Cube the level
+	call .LevelSquared
+	ld a, d
+	ld [hMultiplier], a
+	call Multiply
+
+; Multiply by a
+	ld a, [hl]
+	and $f0
+	swap a
+	ld [hMultiplier], a
+	call Multiply
+; Divide by b
+	ld a, [hli]
+	and $f
+	ld [hDivisor], a
+	ld b, 4
+	call Divide
+; Push the cubic term to the stack
+	ld a, [hQuotient + 0]
+	push af
+	ld a, [hQuotient + 1]
+	push af
+	ld a, [hQuotient + 2]
+	push af
+; Square the level and multiply by the lower 7 bits of c
+	call .LevelSquared
+	ld a, [hl]
+	and $7f
+	ld [hMultiplier], a
+	call Multiply
+; Push the absolute value of the quadratic term to the stack
+	ld a, [hProduct + 1]
+	push af
+	ld a, [hProduct + 2]
+	push af
+	ld a, [hProduct + 3]
+	push af
+	ld a, [hli]
+	push af
+; Multiply the level by d
+	xor a
+	ld [hMultiplicand + 0], a
+	ld [hMultiplicand + 1], a
+	ld a, d
+	ld [hMultiplicand + 2], a
+	ld a, [hli]
+	ld [hMultiplier], a
+	call Multiply
+; Subtract e
+	ld b, [hl]
+	ld a, [hProduct + 3]
+	sub b
+	ld [hMultiplicand + 2], a
+	ld b, $0
+	ld a, [hProduct + 2]
+	sbc b
+	ld [hMultiplicand + 1], a
+	ld a, [hProduct + 1]
+	sbc b
+	ld [hMultiplicand], a
+; If bit 7 of c is set, c is negative; otherwise, it's positive
+	pop af
+	and $80
+	jr nz, .subtract
+; Add c*n**2 to (d*n - e)
+	pop bc
+	ld a, [hProduct + 3]
+	add b
+	ld [hMultiplicand + 2], a
+	pop bc
+	ld a, [hProduct + 2]
+	adc b
+	ld [hMultiplicand + 1], a
+	pop bc
+	ld a, [hProduct + 1]
+	adc b
+	ld [hMultiplicand], a
+	jr .done_quadratic
+
+.subtract
+; Subtract c*n**2 from (d*n - e)
+	pop bc
+	ld a, [hProduct + 3]
+	sub b
+	ld [hMultiplicand + 2], a
+	pop bc
+	ld a, [hProduct + 2]
+	sbc b
+	ld [hMultiplicand + 1], a
+	pop bc
+	ld a, [hProduct + 1]
+	sbc b
+	ld [hMultiplicand], a
+
+.done_quadratic
+; Add (a/b)*n**3 to (d*n - e +/- c*n**2)
+	pop bc
+	ld a, [hProduct + 3]
+	add b
+	ld [hMultiplicand + 2], a
+	pop bc
+	ld a, [hProduct + 2]
+	adc b
+	ld [hMultiplicand + 1], a
+	pop bc
+	ld a, [hProduct + 1]
+	adc b
+	ld [hMultiplicand], a
+	ret
+
+.LevelSquared: ; 50eed
+	xor a
+	ld [hMultiplicand + 0], a
+	ld [hMultiplicand + 1], a
+	ld a, d
+	ld [hMultiplicand + 2], a
+	ld [hMultiplier], a
+	jp Multiply
+
+INCLUDE "data/growth_rates.asm"
--- /dev/null
+++ b/engine/pokemon/health.asm
@@ -1,0 +1,110 @@
+HealParty: ; c658
+	xor a
+	ld [wCurPartyMon], a
+	ld hl, wPartySpecies
+.loop
+	ld a, [hli]
+	cp -1
+	jr z, .done
+	cp EGG
+	jr z, .next
+
+	push hl
+	call HealPartyMon
+	pop hl
+
+.next
+	ld a, [wCurPartyMon]
+	inc a
+	ld [wCurPartyMon], a
+	jr .loop
+
+.done
+	ret
+
+HealPartyMon: ; c677
+	ld a, MON_SPECIES
+	call GetPartyParamLocation
+	ld d, h
+	ld e, l
+
+	ld hl, MON_STATUS
+	add hl, de
+	xor a
+	ld [hli], a
+	ld [hl], a
+
+	ld hl, MON_MAXHP
+	add hl, de
+
+	; bc = MON_HP
+	ld b, h
+	ld c, l
+	dec bc
+	dec bc
+
+	ld a, [hli]
+	ld [bc], a
+	inc bc
+	ld a, [hl]
+	ld [bc], a
+
+	farcall RestoreAllPP
+	ret
+
+ComputeHPBarPixels: ; c699
+; e = bc * (6 * 8) / de
+	ld a, b
+	or c
+	jr z, .zero
+	push hl
+	xor a
+	ld [hMultiplicand + 0], a
+	ld a, b
+	ld [hMultiplicand + 1], a
+	ld a, c
+	ld [hMultiplicand + 2], a
+	ld a, 6 * 8
+	ld [hMultiplier], a
+	call Multiply
+	; We need de to be under 256 because hDivisor is only 1 byte.
+	ld a, d
+	and a
+	jr z, .divide
+	; divide de and hProduct by 4
+	srl d
+	rr e
+	srl d
+	rr e
+	ld a, [hProduct + 2]
+	ld b, a
+	ld a, [hProduct + 3]
+	srl b
+	rr a
+	srl b
+	rr a
+	ld [hDividend + 3], a
+	ld a, b
+	ld [hDividend + 2], a
+.divide
+	ld a, e
+	ld [hDivisor], a
+	ld b, 4
+	call Divide
+	ld a, [hQuotient + 2]
+	ld e, a
+	pop hl
+	and a
+	ret nz
+	ld e, 1
+	ret
+
+.zero
+	ld e, 0
+	ret
+
+AnimateHPBar: ; c6e0
+	call WaitBGMap
+	call _AnimateHPBar
+	call WaitBGMap
+	ret
--- /dev/null
+++ b/engine/pokemon/learn.asm
@@ -1,0 +1,256 @@
+LearnMove: ; 6508
+	call LoadTileMapToTempTileMap
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMonNicknames
+	call GetNick
+	ld hl, wStringBuffer1
+	ld de, wMonOrItemNameBuffer
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+
+.loop
+	ld hl, wPartyMon1Moves
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld b, NUM_MOVES
+; Get the first empty move slot.  This routine also serves to
+; determine whether the Pokemon learning the moves already has
+; all four slots occupied, in which case one would need to be
+; deleted.
+.next
+	ld a, [hl]
+	and a
+	jr z, .learn
+	inc hl
+	dec b
+	jr nz, .next
+; If we're here, we enter the routine for forgetting a move
+; to make room for the new move we're trying to learn.
+	push de
+	call ForgetMove
+	pop de
+	jp c, .cancel
+
+	push hl
+	push de
+	ld [wd265], a
+
+	ld b, a
+	ld a, [wBattleMode]
+	and a
+	jr z, .not_disabled
+	ld a, [wDisabledMove]
+	cp b
+	jr nz, .not_disabled
+	xor a
+	ld [wDisabledMove], a
+	ld [wPlayerDisableCount], a
+.not_disabled
+
+	call GetMoveName
+	ld hl, Text_1_2_and_Poof ; 1, 2 and…
+	call PrintText
+	pop de
+	pop hl
+
+.learn
+	ld a, [wPutativeTMHMMove]
+	ld [hl], a
+	ld bc, MON_PP - MON_MOVES
+	add hl, bc
+
+	push hl
+	push de
+	dec a
+	ld hl, Moves + MOVE_PP
+	ld bc, MOVE_LENGTH
+	call AddNTimes
+	ld a, BANK(Moves)
+	call GetFarByte
+	pop de
+	pop hl
+
+	ld [hl], a
+
+	ld a, [wBattleMode]
+	and a
+	jp z, .learned
+
+	ld a, [wCurPartyMon]
+	ld b, a
+	ld a, [wCurBattleMon]
+	cp b
+	jp nz, .learned
+
+	ld a, [wPlayerSubStatus5]
+	bit SUBSTATUS_TRANSFORMED, a
+	jp nz, .learned
+
+	ld h, d
+	ld l, e
+	ld de, wBattleMonMoves
+	ld bc, NUM_MOVES
+	call CopyBytes
+	ld bc, wPartyMon1PP - (wPartyMon1Moves + NUM_MOVES)
+	add hl, bc
+	ld de, wBattleMonPP
+	ld bc, NUM_MOVES
+	call CopyBytes
+	jp .learned
+
+.cancel
+	ld hl, Text_StopLearning ; Stop learning <MOVE>?
+	call PrintText
+	call YesNoBox
+	jp c, .loop
+
+	ld hl, Text_DidNotLearn ; <MON> did not learn <MOVE>.
+	call PrintText
+	ld b, 0
+	ret
+
+.learned
+	ld hl, Text_LearnedMove ; <MON> learned <MOVE>!
+	call PrintText
+	ld b, 1
+	ret
+; 65d3
+
+ForgetMove: ; 65d3
+	push hl
+	ld hl, Text_TryingToLearn
+	call PrintText
+	call YesNoBox
+	pop hl
+	ret c
+	ld bc, -NUM_MOVES
+	add hl, bc
+	push hl
+	ld de, wListMoves_MoveIndicesBuffer
+	ld bc, NUM_MOVES
+	call CopyBytes
+	pop hl
+.loop
+	push hl
+	ld hl, Text_ForgetWhich
+	call PrintText
+	hlcoord 5, 2
+	ld b, NUM_MOVES * 2
+	ld c, MOVE_NAME_LENGTH
+	call TextBox
+	hlcoord 5 + 2, 2 + 2
+	ld a, SCREEN_WIDTH * 2
+	ld [wBuffer1], a
+	predef ListMoves
+	; w2DMenuData
+	ld a, $4
+	ld [w2DMenuCursorInitY], a
+	ld a, $6
+	ld [w2DMenuCursorInitX], a
+	ld a, [wNumMoves]
+	inc a
+	ld [w2DMenuNumRows], a
+	ld a, $1
+	ld [w2DMenuNumCols], a
+	ld [wMenuCursorY], a
+	ld [wMenuCursorX], a
+	ld a, $3
+	ld [wMenuJoypadFilter], a
+	ld a, $20
+	ld [w2DMenuFlags1], a
+	xor a
+	ld [w2DMenuFlags2], a
+	ld a, $20
+	ld [w2DMenuCursorOffsets], a
+	call StaticMenuJoypad
+	push af
+	call Call_LoadTempTileMapToTileMap
+	pop af
+	pop hl
+	bit 1, a
+	jr nz, .cancel
+	push hl
+	ld a, [wMenuCursorY]
+	dec a
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [hl]
+	push af
+	push bc
+	call IsHMMove
+	pop bc
+	pop de
+	ld a, d
+	jr c, .hmmove
+	pop hl
+	add hl, bc
+	and a
+	ret
+
+.hmmove
+	ld hl, Text_CantForgetHM
+	call PrintText
+	pop hl
+	jr .loop
+
+.cancel
+	scf
+	ret
+; 666b
+
+Text_LearnedMove: ; 666b
+; <MON> learned <MOVE>!
+	text_jump UnknownText_0x1c5660
+	db "@"
+; 6670
+
+Text_ForgetWhich: ; 6670
+; Which move should be forgotten?
+	text_jump UnknownText_0x1c5678
+	db "@"
+; 6675
+
+Text_StopLearning: ; 6675
+; Stop learning <MOVE>?
+	text_jump UnknownText_0x1c5699
+	db "@"
+; 667a
+
+Text_DidNotLearn: ; 667a
+; <MON> did not learn <MOVE>.
+	text_jump UnknownText_0x1c56af
+	db "@"
+; 667f
+
+Text_TryingToLearn: ; 667f
+; <MON> is trying to learn <MOVE>. But <MON> can't learn more than
+; four moves. Delete an older move to make room for <MOVE>?
+	text_jump UnknownText_0x1c56c9
+	db "@"
+; 6684
+
+Text_1_2_and_Poof: ; 6684
+	text_jump UnknownText_0x1c5740 ; 1, 2 and…
+	start_asm
+	push de
+	ld de, SFX_SWITCH_POKEMON
+	call PlaySFX
+	pop de
+	ld hl, .PoofForgot
+	ret
+
+.PoofForgot:
+; Poof! <MON> forgot <MOVE>. And…
+	text_jump UnknownText_0x1c574e
+	db "@"
+; 669a
+
+Text_CantForgetHM: ; 669a
+; HM moves can't be forgotten now.
+	text_jump UnknownText_0x1c5772
+	db "@"
+; 669f
--- /dev/null
+++ b/engine/pokemon/mail.asm
@@ -1,0 +1,587 @@
+SendMailToPC: ; 4456e
+	ld a, MON_ITEM
+	call GetPartyParamLocation
+	ld d, [hl]
+	farcall ItemIsMail
+	jr nc, .full
+	call GetMailboxCount
+	cp MAILBOX_CAPACITY
+	jr nc, .full
+	ld bc, MAIL_STRUCT_LENGTH
+	ld hl, sMailbox
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld a, [wCurPartyMon]
+	ld bc, MAIL_STRUCT_LENGTH
+	ld hl, sPartyMail
+	call AddNTimes
+	push hl
+	ld a, BANK(sMailboxCount)
+	call GetSRAMBank
+	ld bc, MAIL_STRUCT_LENGTH
+	call CopyBytes
+	pop hl
+	xor a
+	ld bc, MAIL_STRUCT_LENGTH
+	call ByteFill
+	ld a, MON_ITEM
+	call GetPartyParamLocation
+	ld [hl], 0
+	ld hl, sMailboxCount
+	inc [hl]
+	call CloseSRAM
+	xor a
+	ret
+
+.full
+	scf
+	ret
+; 445c0
+
+DeleteMailFromPC: ; 445c0 (11:45c0)
+; Shift all mail messages in the mailbox
+	ld a, BANK(sMailboxCount)
+	call GetSRAMBank
+	ld a, b
+	push bc
+	ld hl, sMailbox
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	push hl
+	add hl, bc
+	pop de
+	pop bc
+.loop
+	ld a, b
+	cp MAILBOX_CAPACITY - 1
+	jr z, .done
+	push bc
+	ld bc, MAIL_STRUCT_LENGTH
+	call CopyBytes
+	pop bc
+	inc b
+	jr .loop
+.done
+	ld h, d
+	ld l, e
+	xor a
+	ld bc, MAIL_STRUCT_LENGTH
+	call ByteFill
+	ld hl, sMailboxCount
+	dec [hl]
+	jp CloseSRAM
+; 445f4 (11:45f4)
+
+ReadMailMessage: ; 445f4
+	ld a, b
+	ld hl, sMailbox
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	farcall ReadAnyMail
+	ret
+
+MoveMailFromPCToParty: ; 44607
+	ld a, BANK(sMailboxCount)
+	call GetSRAMBank
+	push bc
+	ld a, b
+	ld bc, MAIL_STRUCT_LENGTH
+	ld hl, sMailbox
+	call AddNTimes
+	push hl
+	ld a, [wCurPartyMon]
+	ld bc, MAIL_STRUCT_LENGTH
+	ld hl, sPartyMail
+	call AddNTimes
+	ld d, h
+	ld e, l
+	pop hl
+	push hl
+	ld bc, MAIL_STRUCT_LENGTH
+	call CopyBytes
+	pop hl
+	ld de, PARTYMON_STRUCT_LENGTH - MON_MOVES
+	add hl, de
+	ld d, [hl]
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1Item
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld [hl], d
+	call CloseSRAM
+	pop bc
+	jp DeleteMailFromPC
+; 44648 (11:4648)
+
+GetMailboxCount: ; 44648
+	ld a, BANK(sMailboxCount)
+	call GetSRAMBank
+	ld a, [sMailboxCount]
+	ld c, a
+	jp CloseSRAM
+; 44654
+
+CheckPokeItem:: ; 44654
+	push bc
+	push de
+	farcall SelectMonFromParty
+	ld a, POKEMAIL_REFUSED
+	jr c, .pop_return
+
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1Item
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld d, [hl]
+	farcall ItemIsMail
+	ld a, POKEMAIL_NO_MAIL
+	jr nc, .pop_return
+
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	ld a, [wCurPartyMon]
+	ld hl, sPartyMail
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	pop hl
+	pop bc
+
+; Compare the mail message, byte for byte, with the expected message.
+	ld a, MAIL_MSG_LENGTH
+	ld [wd265], a
+.loop
+	ld a, [de]
+	ld c, a
+	ld a, b
+	call GetFarByte
+	cp "@"
+	jr z, .done
+	cp c
+	ld a, POKEMAIL_WRONG_MAIL
+	jr nz, .close_sram_return
+	inc hl
+	inc de
+	ld a, [wd265]
+	dec a
+	ld [wd265], a
+	jr nz, .loop
+
+.done
+	farcall CheckCurPartyMonFainted
+	ld a, POKEMAIL_LAST_MON
+	jr c, .close_sram_return
+	xor a ; REMOVE_PARTY
+	ld [wPokemonWithdrawDepositParameter], a
+	farcall RemoveMonFromPartyOrBox
+	ld a, POKEMAIL_CORRECT
+
+.close_sram_return
+	call CloseSRAM
+	jr .return
+
+.pop_return
+	pop de
+	pop bc
+
+.return
+	ld [wScriptVar], a
+	ret
+; 446cc
+
+
+GivePokeItem:: ; 446cc
+	ld a, [wPartyCount]
+	dec a
+	push af
+	push bc
+	ld hl, wPartyMon1Item
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	pop bc
+	ld [hl], b
+	pop af
+	push bc
+	push af
+	ld hl, sPartyMail
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld hl, wd002
+	ld bc, MAIL_MSG_LENGTH + 1
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	call CopyBytes
+	pop af
+	push af
+	ld hl, wPartyMonOT
+	ld bc, NAME_LENGTH
+	call AddNTimes
+	ld bc, NAME_LENGTH - 1
+	call CopyBytes
+	pop af
+	ld hl, wPartyMon1ID
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+	inc de
+	ld a, [wCurPartySpecies]
+	ld [de], a
+	inc de
+	pop bc
+	ld a, b
+	ld [de], a
+	jp CloseSRAM
+; 44725
+
+
+BackupPartyMonMail: ; 44725
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	ld hl, sPartyMail
+	ld de, sPartyMailBackup
+	ld bc, 6 * MAIL_STRUCT_LENGTH
+	call CopyBytes
+	ld hl, sMailboxCount
+	ld de, sMailboxCountBackup
+	ld bc, 1 + 10 * MAIL_STRUCT_LENGTH
+	call CopyBytes
+	jp CloseSRAM
+; 44745
+
+RestorePartyMonMail: ; 44745 (11:4745)
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	ld hl, sPartyMailBackup
+	ld de, sPartyMail
+	ld bc, 6 * MAIL_STRUCT_LENGTH
+	call CopyBytes
+	ld hl, sMailboxCountBackup
+	ld de, sMailboxCount
+	ld bc, 1 + 10 * MAIL_STRUCT_LENGTH
+	call CopyBytes
+	jp CloseSRAM
+
+DeletePartyMonMail: ; 44765 (11:4765)
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	xor a
+	ld hl, sPartyMail
+	ld bc, 6 * MAIL_STRUCT_LENGTH
+	call ByteFill
+	xor a
+	ld hl, sMailboxCount
+	ld bc, 1 + 10 * MAIL_STRUCT_LENGTH
+	call ByteFill
+	jp CloseSRAM
+; 44781 (11:4781)
+
+
+IsAnyMonHoldingMail: ; 44781
+	ld a, [wPartyCount]
+	and a
+	jr z, .no_mons
+	ld e, a
+	ld hl, wPartyMon1Item
+.loop
+	ld d, [hl]
+	push hl
+	push de
+	farcall ItemIsMail
+	pop de
+	pop hl
+	ret c
+	ld bc, PARTYMON_STRUCT_LENGTH
+	add hl, bc
+	dec e
+	jr nz, .loop
+
+.no_mons
+	and a
+	ret
+; 447a0
+
+_PlayerMailBoxMenu: ; 0x447a0
+	call InitMail
+	jr z, .nomail
+	call LoadStandardMenuHeader
+	call MailboxPC
+	jp CloseWindow
+
+.nomail
+	ld hl, .EmptyMailboxText
+	jp MenuTextBoxBackup
+; 0x447b4
+
+.EmptyMailboxText: ; 0x447b4
+	text_jump _EmptyMailboxText
+	db "@"
+
+InitMail: ; 0x447b9
+; initialize wMailboxCount and beyond with incrementing values, one per mail
+; set z if no mail
+	ld a, BANK(sMailboxCount)
+	call GetSRAMBank
+	ld a, [sMailboxCount]
+	call CloseSRAM
+	ld hl, wMailboxCount
+	ld [hli], a
+	and a
+
+	jr z, .done ; if no mail, we're done
+
+	; load values in memory with incrementing values starting at wMailboxCount
+	ld b, a
+	ld a, 1
+.loop
+	ld [hli], a
+	inc a
+	dec b
+	jr nz, .loop
+.done
+	ld [hl], -1 ; terminate
+
+	ld a, [wMailboxCount]
+	and a
+	ret
+; 0x447da
+
+MailboxPC_GetMailAuthor: ; 0x447da
+	dec a
+	ld hl, sMailbox1Author
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	ld a, BANK(sMailboxCount)
+	call GetSRAMBank
+	ld de, wStringBuffer2
+	push de
+	ld bc, NAME_LENGTH - 1
+	call CopyBytes
+	ld a, "@"
+	ld [de], a
+	call CloseSRAM
+	pop de
+	ret
+; 0x447fb
+
+MailboxPC_PrintMailAuthor: ; 0x447fb
+	push de
+	ld a, [wMenuSelection]
+	call MailboxPC_GetMailAuthor
+	pop hl
+	jp PlaceString
+; 0x44806
+
+MailboxPC: ; 0x44806
+	xor a
+	ld [wCurMessageScrollPosition], a
+	ld a, 1
+	ld [wCurMessageIndex], a
+.loop
+	call InitMail
+	ld hl, .TopMenuHeader
+	call CopyMenuHeader
+	xor a
+	ld [hBGMapMode], a
+	call InitScrollingMenu
+	call UpdateSprites
+
+	ld a, [wCurMessageIndex]
+	ld [wMenuCursorBuffer], a
+	ld a, [wCurMessageScrollPosition]
+	ld [wMenuScrollPosition], a
+	call ScrollingMenu
+	ld a, [wMenuScrollPosition]
+	ld [wCurMessageScrollPosition], a
+	ld a, [wMenuCursorY]
+	ld [wCurMessageIndex], a
+
+	ld a, [wMenuJoypad]
+	cp B_BUTTON
+	jr z, .exit
+	call .Submenu
+	jr .loop
+
+.exit
+	xor a
+	ret
+; 0x4484a
+
+.Submenu: ; 0x4484a
+	ld hl, .SubMenuHeader
+	call LoadMenuHeader
+	call VerticalMenu
+	call ExitMenu
+	jr c, .subexit
+	ld a, [wMenuCursorY]
+	dec a
+	ld hl, .JumpTable
+	rst JumpTable
+
+.subexit
+	ret
+; 0x44861
+
+.JumpTable:
+	dw .ReadMail
+	dw .PutInPack
+	dw .AttachMail
+	dw .Cancel
+
+.ReadMail: ; 0x44869
+	call FadeToMenu
+	ld a, [wMenuSelection]
+	dec a
+	ld b, a
+	call ReadMailMessage
+	jp CloseSubmenu
+; 0x44877
+
+.PutInPack: ; 0x44877
+	ld hl, .MessageLostText
+	call MenuTextBox
+	call YesNoBox
+	call ExitMenu
+	ret c
+	ld a, [wMenuSelection]
+	dec a
+	call .GetMailType
+	ld a, 1
+	ld [wItemQuantityChangeBuffer], a
+	ld hl, wNumItems
+	call ReceiveItem
+	jr c, .put_in_bag
+	ld hl, .PackFullText
+	jp MenuTextBoxBackup
+
+.put_in_bag
+	ld a, [wMenuSelection]
+	dec a
+	ld b, a
+	call DeleteMailFromPC
+	ld hl, .PutAwayText
+	jp MenuTextBoxBackup
+; 0x448ac
+
+.PutAwayText: ; 0x448ac
+	text_jump ClearedMailPutAwayText
+	db "@"
+
+.PackFullText: ; 0x448b1
+	text_jump MailPackFullText
+	db "@"
+
+.MessageLostText: ; 0x448b6
+	text_jump MailMessageLostText
+	db "@"
+
+.GetMailType: ; 0x448bb
+	push af
+	ld a, BANK(sMailboxCount)
+	call GetSRAMBank
+	pop af
+	ld hl, sMailbox1Type
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [hl]
+	ld [wCurItem], a
+	jp CloseSRAM
+; 0x448d2
+
+.AttachMail: ; 0x448d2
+	call FadeToMenu
+	xor a
+	ld [wPartyMenuActionText], a
+	call ClearBGPalettes
+.try_again
+	farcall LoadPartyMenuGFX
+	farcall InitPartyMenuWithCancel
+	farcall InitPartyMenuGFX
+	farcall WritePartyMenuTilemap
+	farcall PrintPartyMenuText
+	call WaitBGMap
+	call SetPalettes
+	call DelayFrame
+	farcall PartyMenuSelect
+	jr c, .exit2
+	ld a, [wCurPartySpecies]
+	cp EGG
+	jr z, .egg
+	ld a, MON_ITEM
+	call GetPartyParamLocation
+	ld a, [hl]
+	and a
+	jr z, .attach_mail
+	ld hl, .HoldingMailText
+	call PrintText
+	jr .try_again
+
+.egg
+	ld hl, .EggText
+	call PrintText
+	jr .try_again
+
+.attach_mail
+	ld a, [wMenuSelection]
+	dec a
+	ld b, a
+	call MoveMailFromPCToParty
+	ld hl, .MailMovedText
+	call PrintText
+
+.exit2
+	jp CloseSubmenu
+; 0x4493c
+
+.HoldingMailText: ; 0x4493c
+	text_jump MailAlreadyHoldingItemText
+	db "@"
+
+.EggText: ; 0x44941
+	text_jump MailEggText
+	db "@"
+
+.MailMovedText: ; 0x44946
+	text_jump MailMovedFromBoxText
+	db "@"
+
+.Cancel:
+	ret
+
+.TopMenuHeader: ; 0x4494c
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 8, 1, SCREEN_WIDTH - 2, 10
+	dw .TopMenuData
+	db 1 ; default option
+
+.TopMenuData:
+	db SCROLLINGMENU_DISPLAY_ARROWS ; flags
+	db 4, 0 ; rows/columns?
+	db 1 ; horizontal spacing?
+	dbw 0, wMailboxCount ; text pointer
+	dba MailboxPC_PrintMailAuthor
+	dba NULL
+	dba NULL
+
+.SubMenuHeader: ; 0x44964
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 0, 0, 13, 9
+	dw .SubMenuData
+	db 1 ; default option
+
+.SubMenuData:
+	db STATICMENU_CURSOR ; flags
+	db 4 ; items
+	db "READ MAIL@"
+	db "PUT IN PACK@"
+	db "ATTACH MAIL@"
+	db "CANCEL@"
--- /dev/null
+++ b/engine/pokemon/mail_2.asm
@@ -1,0 +1,949 @@
+ReadPartyMonMail: ; b9229
+	ld a, [wCurPartyMon]
+	ld hl, sPartyMail
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+ReadAnyMail: ; b9237
+	push de
+	call ClearBGPalettes
+	call ClearSprites
+	call ClearTileMap
+	call DisableLCD
+	call LoadFontsExtra
+	pop de
+	push de
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	farcall IsMailEuropean
+	call CloseSRAM
+	ld a, c
+	ld de, StandardEnglishFont
+	or a
+	jr z, .got_font
+	ld de, FrenchGermanFont
+	sub $3
+	jr c, .got_font
+	ld de, SpanishItalianFont
+
+.got_font
+	ld hl, vTiles1
+	lb bc, BANK(StandardEnglishFont), $80
+	call Get1bpp
+	pop de
+	call .LoadGFX
+	call EnableLCD
+	call WaitBGMap
+	ld a, [wBuffer3]
+	ld e, a
+	farcall LoadMailPalettes
+	call SetPalettes
+	xor a
+	ld [hJoyPressed], a
+	call .loop
+	call ClearBGPalettes
+	call DisableLCD
+	call LoadStandardFont
+	jp EnableLCD
+
+.loop
+	call GetJoypad
+	ld a, [hJoyPressed]
+	and A_BUTTON | B_BUTTON | START
+	jr z, .loop
+	and START
+	jr nz, .pressed_start
+	ret
+
+.pressed_start
+	ld a, [wJumptableIndex]
+	push af
+	callfar PrintMail ; printer
+	pop af
+	ld [wJumptableIndex], a
+	jr .loop
+; b92b8
+
+.LoadGFX: ; b92b8
+	ld h, d
+	ld l, e
+	push hl
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	ld de, sPartyMon1MailAuthorID - sPartyMon1Mail
+	add hl, de
+	ld a, [hli]
+	ld [wBuffer1], a
+	ld a, [hli]
+	ld [wBuffer2], a
+	ld a, [hli]
+	ld [wCurPartySpecies], a
+	ld b, [hl]
+	call CloseSRAM
+	ld hl, MailGFXPointers
+	ld c, 0
+.loop2
+	ld a, [hli]
+	cp b
+	jr z, .got_pointer
+	cp -1
+	jr z, .invalid
+	inc c
+	inc hl
+	inc hl
+	jr .loop2
+
+.invalid
+	ld hl, MailGFXPointers
+	inc hl
+
+.got_pointer
+	ld a, c
+	ld [wBuffer3], a
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, .done
+	pop bc
+	push de
+	jp hl
+.done
+	ret
+; b92f8
+
+MailGFXPointers: ; b92f8
+	dbw FLOWER_MAIL,  LoadFlowerMailGFX
+	dbw SURF_MAIL,    LoadSurfMailGFX
+	dbw LITEBLUEMAIL, LoadLiteBlueMailGFX
+	dbw PORTRAITMAIL, LoadPortraitMailGFX
+	dbw LOVELY_MAIL,  LoadLovelyMailGFX
+	dbw EON_MAIL,     LoadEonMailGFX
+	dbw MORPH_MAIL,   LoadMorphMailGFX
+	dbw BLUESKY_MAIL, LoadBlueSkyMailGFX
+	dbw MUSIC_MAIL,   LoadMusicMailGFX
+	dbw MIRAGE_MAIL,  LoadMirageMailGFX
+	db -1
+; b9317
+
+LoadSurfMailGFX: ; b9317
+	push bc
+	ld hl, vTiles2 tile $31
+	ld de, SurfMailBorderGFX
+	ld c, 8 * 8
+	call LoadMailGFX_Color2
+	ld de, MailLaprasGFX
+	ld c, 6 * 8
+	call LoadMailGFX_Color3
+	ld de, SurfMailWaveGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	jr FinishLoadingSurfLiteBlueMailGFX
+
+LoadLiteBlueMailGFX: ; b9335
+	push bc
+	ld hl, vTiles2 tile $31
+	ld de, LiteBlueMailBorderGFX
+	ld c, 8 * 8
+	call LoadMailGFX_Color2
+	ld de, MailDratiniGFX
+	ld c, 6 * 8
+	call LoadMailGFX_Color3
+	ld de, PortraitMailUnderlineGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+
+FinishLoadingSurfLiteBlueMailGFX: ; b9351
+	ld de, SurfLiteBlueMailSmallShapesGFX
+	ld c, 2 * 8
+	call LoadMailGFX_Color2
+	ld c, 2 * 8
+	call LoadMailGFX_Color1
+	ld de, SurfLiteBlueMailLargeShapesGFX
+	ld c, 8 * 8
+	call LoadMailGFX_Color1
+	ld c, 8 * 8
+	call LoadMailGFX_Color2
+
+	call DrawMailBorder
+	hlcoord 2, 15
+	ld a, $3f
+	call Mail_Draw16TileRow
+	ld a, $39
+	hlcoord 15, 14
+	call Mail_Draw3x2Graphic
+	ld a, $44
+	hlcoord 2, 2
+	call Mail_Draw2x2Graphic
+	hlcoord 15, 11
+	call Mail_Draw2x2Graphic
+	ld a, $4c
+	hlcoord 3, 12
+	call Mail_Draw2x2Graphic
+	hlcoord 15, 2
+	call Mail_Draw2x2Graphic
+	ld a, $50
+	hlcoord 6, 3
+	call Mail_Draw2x2Graphic
+	ld a, $40
+	hlcoord 13, 2
+	ld [hli], a
+	hlcoord 6, 14
+	ld [hl], a
+	ld a, $41
+	hlcoord 4, 5
+	ld [hli], a
+	hlcoord 17, 5
+	ld [hli], a
+	hlcoord 13, 12
+	ld [hl], a
+	ld a, $42
+	hlcoord 9, 2
+	ld [hli], a
+	hlcoord 14, 5
+	ld [hli], a
+	hlcoord 3, 10
+	ld [hl], a
+	ld a, $43
+	hlcoord 6, 11
+	ld [hli], a
+	pop hl
+	jp MailGFX_PlaceMessage
+; b93d2
+
+LoadEonMailGFX: ; b93d2
+	push bc
+	ld hl, vTiles2 tile $31
+	ld de, EonMailBorder1GFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	ld de, EonMailBorder2GFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color1
+	ld de, EonMailBorder2GFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color1
+	ld de, EonMailBorder1GFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	ld de, SurfMailBorderGFX + 6 * 8
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	ld de, MailEeveeGFX
+	ld c, 6 * 8
+	call LoadMailGFX_Color3
+	ld hl, vTiles2 tile $3d
+	ld de, MailLargeCircleGFX
+	ld c, 4 * 8
+	call LoadMailGFX_Color1
+	ld de, EonMailBorder2GFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+
+	ld a, $31
+	hlcoord 0, 0
+	call Mail_Place18TileAlternatingRow
+	hlcoord 1, 17
+	call Mail_Place18TileAlternatingRow
+	ld a, $33
+	hlcoord 0, 1
+	call Mail_Place16TileAlternatingColumn
+	hlcoord 19, 0
+	call Mail_Place16TileAlternatingColumn
+	hlcoord 2, 15
+	ld a, $35
+	call Mail_Draw16TileRow
+	inc a
+	hlcoord 15, 14
+	call Mail_Draw3x2Graphic
+	call LovelyEonMail_PlaceIcons
+	pop hl
+	jp MailGFX_PlaceMessage
+; b944b
+
+LoadLovelyMailGFX: ; b944b
+	push bc
+	ld hl, vTiles2 tile $31
+	ld de, LovelyMailBorderGFX
+	ld c, 5 * 8
+	call LoadMailGFX_Color2
+	ld de, MailPoliwagGFX
+	ld c, 6 * 8
+	call LoadMailGFX_Color3
+	ld de, LovelyMailUnderlineGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	ld de, LovelyMailLargeHeartGFX
+	ld c, 4 * 8
+	call LoadMailGFX_Color2
+	ld de, LovelyMailSmallHeartGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color1
+
+	call DrawMailBorder2
+	hlcoord 2, 15
+	ld a, $3c
+	call Mail_Draw16TileRow
+	ld a, $36
+	hlcoord 15, 14
+	call Mail_Draw3x2Graphic
+	call LovelyEonMail_PlaceIcons
+	pop hl
+	jp MailGFX_PlaceMessage
+; b9491
+
+LovelyEonMail_PlaceIcons: ; b9491
+	ld a, $3d
+	hlcoord 2, 2
+	call Mail_Draw2x2Graphic
+	hlcoord 16, 2
+	call Mail_Draw2x2Graphic
+	hlcoord 9, 4
+	call Mail_Draw2x2Graphic
+	hlcoord 2, 11
+	call Mail_Draw2x2Graphic
+	hlcoord 6, 12
+	call Mail_Draw2x2Graphic
+	hlcoord 12, 11
+	call Mail_Draw2x2Graphic
+	ld a, $41
+	hlcoord 5, 4
+	ld [hl], a
+	hlcoord 6, 2
+	ld [hl], a
+	hlcoord 12, 4
+	ld [hl], a
+	hlcoord 14, 2
+	ld [hl], a
+	hlcoord 3, 13
+	ld [hl], a
+	hlcoord 9, 11
+	ld [hl], a
+	hlcoord 16, 12
+	ld [hl], a
+	ret
+; b94d6
+
+LoadMorphMailGFX: ; b94d6
+	push bc
+	ld hl, vTiles2 tile $31
+	ld bc, 5 * 8
+	call MailGFX_GenerateMonochromeTilesColor2
+	ld de, MorphMailBorderCornerGFX + 3 * 8
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	ld de, MorphMailBorderCornerGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	ld de, MorphMailBorderGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	ld de, EonMailBorder1GFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color1
+	ld de, MorphMailDividerGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	ld de, MailDittoGFX
+	ld c, 6 * 8
+	call LoadMailGFX_Color3
+	call DrawMailBorder2
+	ld a, $31
+	hlcoord 1, 1
+	call Mail_Draw2x2Graphic
+	hlcoord 17, 15
+	call Mail_Draw2x2Graphic
+	hlcoord 1, 3
+	ld [hl], a
+	hlcoord 3, 1
+	ld [hl], a
+	hlcoord 16, 16
+	ld [hl], a
+	hlcoord 18, 14
+	ld [hl], a
+	ld a, $36
+	hlcoord 1, 4
+	ld [hl], a
+	hlcoord 2, 3
+	ld [hl], a
+	hlcoord 3, 2
+	ld [hl], a
+	hlcoord 4, 1
+	ld [hl], a
+	inc a
+	hlcoord 15, 16
+	ld [hl], a
+	hlcoord 16, 15
+	ld [hl], a
+	hlcoord 17, 14
+	ld [hl], a
+	hlcoord 18, 13
+	ld [hl], a
+	inc a
+	hlcoord 2, 15
+	ld b, $e
+	call Mail_DrawRowLoop
+	inc a
+	hlcoord 2, 11
+	call Mail_Draw16TileRow
+	hlcoord 2, 5
+	call Mail_Draw16TileRow
+	inc a
+	hlcoord 6, 1
+	call Mail_Draw13TileRow
+	hlcoord 1, 16
+	call Mail_Draw13TileRow
+	inc a
+	hlcoord 3, 13
+	call Mail_Draw3x2Graphic
+	pop hl
+	jp MailGFX_PlaceMessage
+; b9582
+
+LoadBlueSkyMailGFX: ; b9582
+	push bc
+	ld hl, vTiles2 tile $31
+	ld de, EonMailBorder1GFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	ld a, $ff
+	ld bc, 1 tiles
+	call ByteFill
+	ld de, BlueSkyMailGrassGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color3
+	ld de, MailDragoniteGFX
+	ld c, 23 * 8
+	call LoadMailGFX_Color3
+	ld de, MailCloudGFX
+	ld c, 6 * 8
+	call LoadMailGFX_Color1
+	ld de, FlowerMailBorderGFX + 6 * 8
+	ld c, 1 * 8
+	call LoadMailGFX_Color1
+	ld de, MailCloudGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color1
+	ld de, MailCloudGFX + 2 * 8
+	ld c, 2 * 8
+	call LoadMailGFX_Color1
+	ld de, MailCloudGFX + 5 * 8
+	ld c, 1 * 8
+	call LoadMailGFX_Color1
+
+	ld a, $31
+	hlcoord 0, 0
+	call Mail_DrawFullWidthBorder
+	hlcoord 0, 1
+	call Mail_DrawLeftRightBorder
+	hlcoord 19, 1
+	call Mail_DrawLeftRightBorder
+	inc a
+	hlcoord 0, 17
+	call Mail_DrawFullWidthBorder
+	inc a
+	hlcoord 0, 16
+	call Mail_DrawFullWidthBorder
+	inc a
+	hlcoord 2, 2
+	call Mail_Place6TileRow
+	hlcoord 3, 3
+	call Mail_Place6TileRow
+	hlcoord 4, 4
+	call Mail_Place6TileRow
+	dec hl
+	ld [hl], $7f
+	dec a
+	hlcoord 15, 14
+	call Mail_Draw2x2Graphic
+	add $4
+	hlcoord 15, 16
+	ld [hli], a
+	inc a
+	ld [hl], a
+	inc a
+	push af
+	hlcoord 12, 1
+	call Mail_Draw3x2Graphic
+	pop af
+	hlcoord 15, 4
+	call Mail_Draw3x2Graphic
+	inc a
+	hlcoord 2, 11
+	call Mail_Draw16TileRow
+	inc a
+	hlcoord 10, 3
+	call Mail_Draw2x2Graphic
+	pop hl
+	jp MailGFX_PlaceMessage
+; b9636
+
+Mail_Place6TileRow: ; b9636
+	ld b, $6
+.loop
+	ld [hli], a
+	inc a
+	dec b
+	jr nz, .loop
+	ret
+; b963e
+
+LoadFlowerMailGFX: ; b963e
+	push bc
+	ld hl, vTiles2 tile $31
+	ld de, FlowerMailBorderGFX
+	ld c, 8 * 8
+	call LoadMailGFX_Color1
+	ld de, MailOddishGFX
+	ld c, 4 * 8
+	call LoadMailGFX_Color3
+	ld de, FlowerMailBorderGFX + 6 * 8
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	ld de, FlowerMailFlowerGFX
+	ld c, 4 * 8
+	call LoadMailGFX_Color1
+	ld c, 4 * 8
+	call LoadMailGFX_Color2
+
+	call DrawMailBorder
+	hlcoord 2, 15
+	ld a, $3d ; underline
+	call Mail_Draw16TileRow
+	ld a, $39 ; oddish
+	hlcoord 16, 13
+	call Mail_Draw2x2Graphic
+	hlcoord 2, 13
+	call Mail_Draw2x2Graphic
+	ld a, $3e
+	hlcoord 2, 2
+	call Mail_Draw2x2Graphic
+	hlcoord 5, 3
+	call Mail_Draw2x2Graphic
+	hlcoord 10, 2
+	call Mail_Draw2x2Graphic
+	hlcoord 16, 3
+	call Mail_Draw2x2Graphic
+	hlcoord 5, 11
+	call Mail_Draw2x2Graphic
+	hlcoord 16, 10
+	call Mail_Draw2x2Graphic
+	ld a, $42
+	hlcoord 3, 4
+	call Mail_Draw2x2Graphic
+	hlcoord 12, 3
+	call Mail_Draw2x2Graphic
+	hlcoord 14, 2
+	call Mail_Draw2x2Graphic
+	hlcoord 2, 10
+	call Mail_Draw2x2Graphic
+	hlcoord 14, 11
+	call Mail_Draw2x2Graphic
+	pop hl
+	jp MailGFX_PlaceMessage
+; b96ca
+
+LoadPortraitMailGFX: ; b96ca
+	push bc
+	ld hl, vTiles2 tile $31
+	ld de, PortraitMailBorderGFX
+	ld c, 5 * 8
+	call LoadMailGFX_Color2
+	ld de, PortraitMailUnderlineGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	ld hl, vTiles2 tile $3d
+	ld de, PortraitMailLargePokeballGFX
+	ld c, 4 * 8
+	call LoadMailGFX_Color1
+	ld de, PortraitMailSmallPokeballGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+
+	call DrawMailBorder2
+	hlcoord 8, 15
+	ld a, $36
+	ld b, $a
+	call Mail_DrawRowLoop
+	call LovelyEonMail_PlaceIcons
+	ld a, $1
+	ld [wUnownLetter], a
+	hlcoord 1, 10
+	call PrepMonFrontpic
+	pop hl
+	jp MailGFX_PlaceMessage
+; b9710
+
+LoadMusicMailGFX: ; b9710
+	push bc
+	ld hl, vTiles2 tile $31
+	ld de, MusicMailBorderGFX
+	ld c, 4 * 8
+	call LoadMailGFX_Color2
+	ld de, MorphMailBorderGFX
+	ld c, 2 * 8
+	call LoadMailGFX_Color2
+	ld de, MailNatuGFX
+	ld c, 6 * 8
+	call LoadMailGFX_Color3
+	xor a
+	ld bc, 1 tiles
+	call ByteFill
+	ld de, MusicMailLargeNoteGFX
+	ld c, 3 * 8
+	call LoadMailGFX_Color1
+	ld de, MusicMailSmallNoteGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color1
+
+	ld a, $31
+	hlcoord 0, 0
+	call Mail_Place18TileAlternatingRow
+	hlcoord 1, 17
+	call Mail_Place18TileAlternatingRow
+	ld a, $33
+	hlcoord 0, 1
+	call Mail_Place16TileAlternatingColumn
+	hlcoord 19, 0
+	call Mail_Place16TileAlternatingColumn
+	ld a, $35
+	hlcoord 2, 15
+	call Mail_Place14TileAlternatingRow
+	ld a, $37
+	hlcoord 15, 14
+	call Mail_Draw3x2Graphic
+	call LovelyEonMail_PlaceIcons
+	pop hl
+	jp MailGFX_PlaceMessage
+; b9776
+
+LoadMirageMailGFX: ; b9776
+	push bc
+	ld hl, vTiles2 tile $31
+	ld bc, 5 * 8
+	call MailGFX_GenerateMonochromeTilesColor2
+	ld de, BlueSkyMailGrassGFX
+	ld c, 1 * 8
+	call LoadMailGFX_Color2
+	ld de, MailMewGFX
+	ld c, 18 * 8
+	call LoadMailGFX_Color2
+	ld de, LiteBlueMailBorderGFX + 1 * 8
+	ld c, 1 * 8
+	call LoadMailGFX_Color1
+	ld de, LiteBlueMailBorderGFX + 6 * 8
+	ld c, 1 * 8
+	call LoadMailGFX_Color1
+
+	call DrawMailBorder2
+	ld a, $36
+	hlcoord 1, 16
+	call Mail_DrawTopBottomBorder
+	inc a
+	hlcoord 15, 14
+	call Mail_Draw3x2Graphic
+	inc a
+	hlcoord 15, 16
+	ld [hli], a
+	inc a
+	ld [hl], a
+	ld a, $3f
+	hlcoord 1, 1
+	call Mail_Place18TileAlternatingRow
+	ld a, $41
+	hlcoord 0, 2
+	call Mail_Place14TileAlternatingColumn
+	ld a, $43
+	hlcoord 19, 2
+	call Mail_Place14TileAlternatingColumn
+	ld a, $45
+	hlcoord 0, 1
+	ld [hl], a
+	inc a
+	hlcoord 19, 1
+	ld [hl], a
+	inc a
+	hlcoord 0, 16
+	ld [hl], a
+	inc a
+	hlcoord 19, 16
+	ld [hl], a
+	inc a
+	hlcoord 2, 5
+	call Mail_Draw16TileRow
+	inc a
+	hlcoord 2, 11
+	call Mail_Draw16TileRow
+	pop hl
+	jp MailGFX_PlaceMessage
+; b97f8
+
+MailGFX_GenerateMonochromeTilesColor2: ; b97f8
+.loop
+	xor a
+	ld [hli], a
+	ld a, $ff
+	ld [hli], a
+	dec bc
+	ld a, b
+	or c
+	jr nz, .loop
+	ret
+; b9803
+
+MailGFX_PlaceMessage: ; b9803
+	ld bc, MAIL_STRUCT_LENGTH
+	ld de, wTempMail
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	call CopyBytes
+	call CloseSRAM
+	ld hl, wTempMailAuthor
+	ld de, wMonOrItemNameBuffer
+	ld bc, NAME_LENGTH - 1
+	call CopyBytes
+	ld a, "@"
+	ld [wTempMailAuthor], a
+	ld [wMonOrItemNameBuffer + NAME_LENGTH - 1], a
+	ld de, wTempMailMessage
+	hlcoord 2, 7
+	call PlaceString
+	ld de, wMonOrItemNameBuffer
+	ld a, [de]
+	and a
+	ret z
+	ld a, [wBuffer3]
+	hlcoord 8, 14
+	cp $3 ; PORTRAITMAIL
+	jr z, .place_author
+	hlcoord 6, 14
+	cp $6 ; MORPH_MAIL
+	jr z, .place_author
+	hlcoord 5, 14
+
+.place_author
+	jp PlaceString
+; b984e
+
+Unreferenced_Functionb984e: ; b984e
+.loop
+	ld a, [hl]
+	xor $ff
+	ld [hli], a
+	dec bc
+	ld a, b
+	or c
+	jr nz, .loop
+	ret
+; b9858
+
+DrawMailBorder: ; b9858
+	hlcoord 0, 0
+	ld a, $31
+	ld [hli], a
+	inc a
+	call Mail_DrawTopBottomBorder
+	inc a
+	ld [hli], a
+	inc a
+	call Mail_DrawLeftRightBorder
+	ld a, $36
+	ld [hli], a
+	inc a
+	call Mail_DrawTopBottomBorder
+	hlcoord 19, 1
+	ld a, $35
+	call Mail_DrawLeftRightBorder
+	ld a, $38
+	ld [hl], a
+	ret
+; b987b
+
+DrawMailBorder2: ; b987b
+	hlcoord 0, 0
+	ld a, $31
+	ld [hli], a
+	inc a
+	call Mail_DrawTopBottomBorder
+	ld [hl], $31
+	inc hl
+	inc a
+	call Mail_DrawLeftRightBorder
+	ld [hl], $31
+	inc hl
+	inc a
+	call Mail_DrawTopBottomBorder
+	hlcoord 19, 1
+	ld a, $35
+	call Mail_DrawLeftRightBorder
+	ld [hl], $31
+	ret
+; b989e
+
+Mail_Place14TileAlternatingRow: ; b989e
+	push af
+	ld b, 14 / 2
+	jr Mail_PlaceAlternatingRow
+
+Mail_Place16TileAlternatingRow: ; b98a3
+	push af
+	ld b, 16 / 2
+	jr Mail_PlaceAlternatingRow
+
+Mail_Place18TileAlternatingRow: ; b98a8
+	push af
+	ld b, 18 / 2
+
+Mail_PlaceAlternatingRow: ; b98ab
+.loop
+	ld [hli], a
+	inc a
+	ld [hli], a
+	dec a
+	dec b
+	jr nz, .loop
+	ld [hl], a
+	pop af
+	ret
+; b98b5
+
+Mail_Place14TileAlternatingColumn: ; b98b5
+	push af
+	ld b, 14 / 2
+	jr Mail_PlaceAlternatingColumn
+
+Mail_Place16TileAlternatingColumn: ; b98ba
+	push af
+	ld b, 16 / 2
+
+Mail_PlaceAlternatingColumn: ; b98bd
+.loop
+	ld [hl], a
+	ld de, SCREEN_WIDTH
+	add hl, de
+	inc a
+	ld [hl], a
+	add hl, de
+	dec a
+	dec b
+	jr nz, .loop
+	ld [hl], a
+	pop af
+	ret
+; b98cc
+
+Mail_Draw7TileRow: ; b98cc
+	ld b, $7
+	jr Mail_DrawRowLoop
+
+Mail_Draw13TileRow: ; b98d0
+	ld b, $d
+	jr Mail_DrawRowLoop
+
+Mail_Draw16TileRow: ; b98d4
+	ld b, $10
+	jr Mail_DrawRowLoop
+
+Mail_DrawTopBottomBorder: ; b98d8
+	ld b, SCREEN_WIDTH - 2
+	jr Mail_DrawRowLoop
+
+Mail_DrawFullWidthBorder: ; b98dc
+	ld b, SCREEN_WIDTH
+
+Mail_DrawRowLoop: ; b98de
+.loop
+	ld [hli], a
+	dec b
+	jr nz, .loop
+	ret
+; b98e3
+
+Mail_DrawLeftRightBorder: ; b98e3
+	ld b, SCREEN_HEIGHT - 2
+	ld de, SCREEN_WIDTH
+.loop
+	ld [hl], a
+	add hl, de
+	dec b
+	jr nz, .loop
+	ret
+; b98ee
+
+Mail_Draw2x2Graphic: ; b98ee
+	push af
+	ld [hli], a
+	inc a
+	ld [hl], a
+	ld bc, SCREEN_WIDTH - 1
+	add hl, bc
+	inc a
+	ld [hli], a
+	inc a
+	ld [hl], a
+	pop af
+	ret
+; b98fc
+
+Mail_Draw3x2Graphic: ; b98fc
+	ld [hli], a
+	inc a
+	ld [hli], a
+	inc a
+	ld [hl], a
+	ld bc, SCREEN_WIDTH - 2
+	add hl, bc
+	inc a
+	ld [hli], a
+	inc a
+	ld [hli], a
+	inc a
+	ld [hl], a
+	ret
+; b990c
+
+LoadMailGFX_Color1: ; b990c
+.loop
+	ld a, [de]
+	inc de
+	ld [hli], a
+	xor a
+	ld [hli], a
+	dec c
+	jr nz, .loop
+	ret
+; b9915
+
+LoadMailGFX_Color2: ; b9915
+.loop
+	xor a
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hli], a
+	dec c
+	jr nz, .loop
+	ret
+; b991e
+
+LoadMailGFX_Color3: ; b991e
+.loop
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld [hli], a
+	dec c
+	jr nz, .loop
+	ret
+; b9926
+
+INCLUDE "gfx/mail.asm"
+
+ItemIsMail: ; b9e76
+	ld a, d
+	ld hl, MailItems
+	ld de, 1
+	jp IsInArray
+; b9e80
+
+INCLUDE "data/items/mail_items.asm"
--- /dev/null
+++ b/engine/pokemon/mon_stats.asm
@@ -1,0 +1,485 @@
+DrawPlayerHP: ; 50b0a
+	ld a, $1
+	jr DrawHP
+
+DrawEnemyHP: ; 50b0e
+	ld a, $2
+
+DrawHP: ; 50b10
+	ld [wWhichHPBar], a
+	push hl
+	push bc
+	; box mons have full HP
+	ld a, [wMonType]
+	cp BOXMON
+	jr z, .at_least_1_hp
+
+	ld a, [wTempMonHP]
+	ld b, a
+	ld a, [wTempMonHP + 1]
+	ld c, a
+
+; Any HP?
+	or b
+	jr nz, .at_least_1_hp
+
+	xor a
+	ld c, a
+	ld e, a
+	ld a, 6
+	ld d, a
+	jp .fainted
+
+.at_least_1_hp
+	ld a, [wTempMonMaxHP]
+	ld d, a
+	ld a, [wTempMonMaxHP + 1]
+	ld e, a
+	ld a, [wMonType]
+	cp BOXMON
+	jr nz, .not_boxmon
+
+	ld b, d
+	ld c, e
+
+.not_boxmon
+	predef ComputeHPBarPixels
+	ld a, 6
+	ld d, a
+	ld c, a
+
+.fainted
+	ld a, c
+	pop bc
+	ld c, a
+	pop hl
+	push de
+	push hl
+	push hl
+	call DrawBattleHPBar
+	pop hl
+
+; Print HP
+	bccoord 1, 1, 0
+	add hl, bc
+	ld de, wTempMonHP
+	ld a, [wMonType]
+	cp BOXMON
+	jr nz, .not_boxmon_2
+	ld de, wTempMonMaxHP
+.not_boxmon_2
+	lb bc, 2, 3
+	call PrintNum
+
+	ld a, "/"
+	ld [hli], a
+
+; Print max HP
+	ld de, wTempMonMaxHP
+	lb bc, 2, 3
+	call PrintNum
+	pop hl
+	pop de
+	ret
+
+PrintTempMonStats: ; 50b7b
+; Print wTempMon's stats at hl, with spacing bc.
+	push bc
+	push hl
+	ld de, .StatNames
+	call PlaceString
+	pop hl
+	pop bc
+	add hl, bc
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld de, wTempMonAttack
+	lb bc, 2, 3
+	call .PrintStat
+	ld de, wTempMonDefense
+	call .PrintStat
+	ld de, wTempMonSpclAtk
+	call .PrintStat
+	ld de, wTempMonSpclDef
+	call .PrintStat
+	ld de, wTempMonSpeed
+	jp PrintNum
+
+.PrintStat: ; 50bab
+	push hl
+	call PrintNum
+	pop hl
+	ld de, SCREEN_WIDTH * 2
+	add hl, de
+	ret
+
+.StatNames: ; 50bb5
+	db   "ATTACK"
+	next "DEFENSE"
+	next "SPCL.ATK"
+	next "SPCL.DEF"
+	next "SPEED"
+	next "@"
+
+GetGender: ; 50bdd
+; Return the gender of a given monster (wCurPartyMon/wCurOTMon/wCurWildMon).
+; When calling this function, a should be set to an appropriate wMonType value.
+
+; return values:
+; a = 1: f = nc|nz; male
+; a = 0: f = nc|z;  female
+;        f = c:  genderless
+
+; This is determined by comparing the Attack and Speed DVs
+; with the species' gender ratio.
+
+; Figure out what type of monster struct we're looking at.
+
+; 0: PartyMon
+	ld hl, wPartyMon1DVs
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, [wMonType]
+	and a
+	jr z, .PartyMon
+
+; 1: OTPartyMon
+	ld hl, wOTPartyMon1DVs
+	dec a
+	jr z, .PartyMon
+
+; 2: sBoxMon
+	ld hl, sBoxMon1DVs
+	ld bc, BOXMON_STRUCT_LENGTH
+	dec a
+	jr z, .sBoxMon
+
+; 3: Unknown
+	ld hl, wTempMonDVs
+	dec a
+	jr z, .DVs
+
+; else: WildMon
+	ld hl, wEnemyMonDVs
+	jr .DVs
+
+; Get our place in the party/box.
+
+.PartyMon:
+.sBoxMon
+	ld a, [wCurPartyMon]
+	call AddNTimes
+
+.DVs:
+
+; sBoxMon data is read directly from SRAM.
+	ld a, [wMonType]
+	cp BOXMON
+	ld a, BANK(sBox)
+	call z, GetSRAMBank
+
+; Attack DV
+	ld a, [hli]
+	and $f0
+	ld b, a
+; Speed DV
+	ld a, [hl]
+	and $f0
+	swap a
+
+; Put our DVs together.
+	or b
+	ld b, a
+
+; Close SRAM if we were dealing with a sBoxMon.
+	ld a, [wMonType]
+	cp BOXMON
+	call z, CloseSRAM
+
+; We need the gender ratio to do anything with this.
+	push bc
+	ld a, [wCurPartySpecies]
+	dec a
+	ld hl, BaseData + BASE_GENDER
+	ld bc, BASE_DATA_SIZE
+	call AddNTimes
+	pop bc
+
+	ld a, BANK(BaseData)
+	call GetFarByte
+
+; The higher the ratio, the more likely the monster is to be female.
+
+	cp GENDERLESS
+	jr z, .Genderless
+
+	and a ; GENDER_F0?
+	jr z, .Male
+
+	cp GENDER_F100
+	jr z, .Female
+
+; Values below the ratio are male, and vice versa.
+	cp b
+	jr c, .Male
+
+.Female:
+	xor a
+	ret
+
+.Male:
+	ld a, 1
+	and a
+	ret
+
+.Genderless:
+	scf
+	ret
+
+ListMovePP: ; 50c50
+	ld a, [wNumMoves]
+	inc a
+	ld c, a
+	ld a, NUM_MOVES
+	sub c
+	ld b, a
+	push hl
+	ld a, [wBuffer1]
+	ld e, a
+	ld d, $0
+	ld a, $3e ; P
+	call .load_loop
+	ld a, b
+	and a
+	jr z, .skip
+	ld c, a
+	ld a, "-"
+	call .load_loop
+
+.skip
+	pop hl
+	inc hl
+	inc hl
+	inc hl
+	ld d, h
+	ld e, l
+	ld hl, wTempMonMoves
+	ld b, 0
+.loop
+	ld a, [hli]
+	and a
+	jr z, .done
+	push bc
+	push hl
+	push de
+	ld hl, wMenuCursorY
+	ld a, [hl]
+	push af
+	ld [hl], b
+	push hl
+	callfar GetMaxPPOfMove
+	pop hl
+	pop af
+	ld [hl], a
+	pop de
+	pop hl
+	push hl
+	ld bc, wTempMonPP - (wTempMonMoves + 1)
+	add hl, bc
+	ld a, [hl]
+	and $3f
+	ld [wStringBuffer1 + 4], a
+	ld h, d
+	ld l, e
+	push hl
+	ld de, wStringBuffer1 + 4
+	lb bc, 1, 2
+	call PrintNum
+	ld a, "/"
+	ld [hli], a
+	ld de, wd265
+	lb bc, 1, 2
+	call PrintNum
+	pop hl
+	ld a, [wBuffer1]
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld d, h
+	ld e, l
+	pop hl
+	pop bc
+	inc b
+	ld a, b
+	cp NUM_MOVES
+	jr nz, .loop
+
+.done
+	ret
+
+.load_loop ; 50cc9
+	ld [hli], a
+	ld [hld], a
+	add hl, de
+	dec c
+	jr nz, .load_loop
+	ret
+
+Unreferenced_Function50cd0: ; 50cd0
+.loop
+	ld [hl], $32
+	inc hl
+	ld [hl], $3e
+	dec hl
+	add hl, de
+	dec c
+	jr nz, .loop
+	ret
+
+Unused_PlaceEnemyHPLevel:
+	push hl
+	push hl
+	ld hl, wPartyMonNicknames
+	ld a, [wCurPartyMon]
+	call GetNick
+	pop hl
+	call PlaceString
+	call CopyMonToTempMon
+	pop hl
+	ld a, [wCurPartySpecies]
+	cp EGG
+	jr z, .egg
+	push hl
+	ld bc, -12
+	add hl, bc
+	ld b, $0
+	call DrawEnemyHP
+	pop hl
+	ld bc, 5
+	add hl, bc
+	push de
+	call PrintLevel
+	pop de
+
+.egg
+	ret
+
+PlaceStatusString: ; 50d0a
+	push de
+	inc de
+	inc de
+	ld a, [de]
+	ld b, a
+	inc de
+	ld a, [de]
+	or b
+	pop de
+	jr nz, PlaceNonFaintStatus
+	push de
+	ld de, FntString
+	call CopyStatusString
+	pop de
+	ld a, $1
+	and a
+	ret
+
+FntString: ; 50d22
+	db "FNT@"
+
+CopyStatusString: ; 50d25
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	ld [hl], a
+	ret
+
+PlaceNonFaintStatus: ; 50d2e
+	push de
+	ld a, [de]
+	ld de, PsnString
+	bit PSN, a
+	jr nz, .place
+	ld de, BrnString
+	bit BRN, a
+	jr nz, .place
+	ld de, FrzString
+	bit FRZ, a
+	jr nz, .place
+	ld de, ParString
+	bit PAR, a
+	jr nz, .place
+	ld de, SlpString
+	and SLP
+	jr z, .no_status
+
+.place
+	call CopyStatusString
+	ld a, $1
+	and a
+
+.no_status
+	pop de
+	ret
+
+SlpString: db "SLP@"
+PsnString: db "PSN@"
+BrnString: db "BRN@"
+FrzString: db "FRZ@"
+ParString: db "PAR@"
+
+ListMoves: ; 50d6f
+; List moves at hl, spaced every [wBuffer1] tiles.
+	ld de, wListMoves_MoveIndicesBuffer
+	ld b, $0
+.moves_loop
+	ld a, [de]
+	inc de
+	and a
+	jr z, .no_more_moves
+	push de
+	push hl
+	push hl
+	ld [wCurSpecies], a
+	ld a, MOVE_NAME
+	ld [wNamedObjectTypeBuffer], a
+	call GetName
+	ld de, wStringBuffer1
+	pop hl
+	push bc
+	call PlaceString
+	pop bc
+	ld a, b
+	ld [wNumMoves], a
+	inc b
+	pop hl
+	push bc
+	ld a, [wBuffer1]
+	ld c, a
+	ld b, 0
+	add hl, bc
+	pop bc
+	pop de
+	ld a, b
+	cp NUM_MOVES
+	jr z, .done
+	jr .moves_loop
+
+.no_more_moves
+	ld a, b
+.nonmove_loop
+	push af
+	ld [hl], "-"
+	ld a, [wBuffer1]
+	ld c, a
+	ld b, 0
+	add hl, bc
+	pop af
+	inc a
+	cp NUM_MOVES
+	jr nz, .nonmove_loop
+
+.done
+	ret
--- /dev/null
+++ b/engine/pokemon/move_mon.asm
@@ -1,0 +1,1845 @@
+TryAddMonToParty: ; d88c
+; Check if to copy wild mon or generate a new one
+	; Whose is it?
+	ld de, wPartyCount
+	ld a, [wMonType]
+	and $f
+	jr z, .getpartylocation ; PARTYMON
+	ld de, wOTPartyCount
+
+.getpartylocation
+	; Do we have room for it?
+	ld a, [de]
+	inc a
+	cp PARTY_LENGTH + 1
+	ret nc
+	; Increase the party count
+	ld [de], a
+	ld a, [de] ; Why are we doing this?
+	ld [hMoveMon], a ; HRAM backup
+	add e
+	ld e, a
+	jr nc, .loadspecies
+	inc d
+
+.loadspecies
+	; Load the species of the Pokemon into the party list.
+	; The terminator is usually here, but it'll be back.
+	ld a, [wCurPartySpecies]
+	ld [de], a
+	; Load the terminator into the next slot.
+	inc de
+	ld a, -1
+	ld [de], a
+	; Now let's load the OT name.
+	ld hl, wPartyMonOT
+	ld a, [wMonType]
+	and $f
+	jr z, .loadOTname
+	ld hl, wOTPartyMonOT
+
+.loadOTname
+	ld a, [hMoveMon] ; Restore index from backup
+	dec a
+	call SkipNames
+	ld d, h
+	ld e, l
+	ld hl, wPlayerName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	; Only initialize the nickname for party mon
+	ld a, [wMonType]
+	and a
+	jr nz, .skipnickname
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	call GetPokemonName
+	ld hl, wPartyMonNicknames
+	ld a, [hMoveMon]
+	dec a
+	call SkipNames
+	ld d, h
+	ld e, l
+	ld hl, wStringBuffer1
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+
+.skipnickname
+	ld hl, wPartyMon1Species
+	ld a, [wMonType]
+	and $f
+	jr z, .initializeStats
+	ld hl, wOTPartyMon1Species
+
+.initializeStats
+	ld a, [hMoveMon]
+	dec a
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+GeneratePartyMonStats: ; d906
+; wBattleMode specifies whether it's a wild mon or not.
+; wMonType specifies whether it's an opposing mon or not.
+; wCurPartySpecies/wCurPartyLevel specify the species and level.
+; hl points to the wPartyMon struct to fill.
+
+	ld e, l
+	ld d, h
+	push hl
+
+	; Initialize the species
+	ld a, [wCurPartySpecies]
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld a, [wBaseDexNo]
+	ld [de], a
+	inc de
+
+	; Copy the item if it's a wild mon
+	ld a, [wBattleMode]
+	and a
+	ld a, $0
+	jr z, .skipitem
+	ld a, [wEnemyMonItem]
+.skipitem
+	ld [de], a
+	inc de
+
+	; Copy the moves if it's a wild mon
+	push de
+	ld h, d
+	ld l, e
+	ld a, [wBattleMode]
+	and a
+	jr z, .randomlygeneratemoves
+	ld a, [wMonType]
+	and a
+	jr nz, .randomlygeneratemoves
+	ld de, wEnemyMonMoves
+	rept NUM_MOVES + -1
+	ld a, [de]
+	inc de
+	ld [hli], a
+	endr
+	ld a, [de]
+	ld [hl], a
+	jr .next
+
+.randomlygeneratemoves
+	xor a
+	rept NUM_MOVES + -1
+	ld [hli], a
+	endr
+	ld [hl], a
+	ld [wBuffer1], a
+	predef FillMoves
+
+.next
+	pop de
+rept NUM_MOVES
+	inc de
+endr
+
+	; Initialize ID.
+	ld a, [wPlayerID]
+	ld [de], a
+	inc de
+	ld a, [wPlayerID + 1]
+	ld [de], a
+	inc de
+
+	; Initialize Exp.
+	push de
+	ld a, [wCurPartyLevel]
+	ld d, a
+	callfar CalcExpAtLevel
+	pop de
+	ld a, [hProduct + 1]
+	ld [de], a
+	inc de
+	ld a, [hProduct + 2]
+	ld [de], a
+	inc de
+	ld a, [hProduct + 3]
+	ld [de], a
+	inc de
+
+	; Initialize stat experience.
+	xor a
+	ld b, MON_DVS - MON_STAT_EXP
+.loop
+	ld [de], a
+	inc de
+	dec b
+	jr nz, .loop
+
+	pop hl
+	push hl
+	ld a, [wMonType]
+	and $f
+	jr z, .registerpokedex
+
+	push hl
+	farcall GetTrainerDVs
+	pop hl
+	jr .initializeDVs
+
+.registerpokedex
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	dec a
+	push de
+	call CheckCaughtMon
+	ld a, [wd265]
+	dec a
+	call SetSeenAndCaughtMon
+	pop de
+
+	pop hl
+	push hl
+	ld a, [wBattleMode]
+	and a
+	jr nz, .copywildmonDVs
+
+	call Random
+	ld b, a
+	call Random
+	ld c, a
+.initializeDVs
+	ld a, b
+	ld [de], a
+	inc de
+	ld a, c
+	ld [de], a
+	inc de
+
+	; Initialize PP.
+	push hl
+	push de
+	inc hl
+	inc hl
+	call FillPP
+	pop de
+	pop hl
+rept 4
+	inc de
+endr
+
+	; Initialize happiness.
+	ld a, BASE_HAPPINESS
+	ld [de], a
+	inc de
+
+	xor a
+	; PokerusStatus
+	ld [de], a
+	inc de
+	; CaughtData/CaughtTime/CaughtLevel
+	ld [de], a
+	inc de
+	; CaughtGender/CaughtLocation
+	ld [de], a
+	inc de
+
+	; Initialize level.
+	ld a, [wCurPartyLevel]
+	ld [de], a
+	inc de
+
+	xor a
+	; Status
+	ld [de], a
+	inc de
+	; Unused
+	ld [de], a
+	inc de
+
+	; Initialize HP.
+	ld bc, MON_STAT_EXP - 1
+	add hl, bc
+	ld a, 1
+	ld c, a
+	ld b, FALSE
+	call CalcMonStatC
+	ld a, [hProduct + 2]
+	ld [de], a
+	inc de
+	ld a, [hProduct + 3]
+	ld [de], a
+	inc de
+	jr .initstats
+
+.copywildmonDVs
+	ld a, [wEnemyMonDVs]
+	ld [de], a
+	inc de
+	ld a, [wEnemyMonDVs + 1]
+	ld [de], a
+	inc de
+
+	push hl
+	ld hl, wEnemyMonPP
+	ld b, NUM_MOVES
+.wildmonpploop
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec b
+	jr nz, .wildmonpploop
+	pop hl
+
+	; Initialize happiness.
+	ld a, BASE_HAPPINESS
+	ld [de], a
+	inc de
+
+	xor a
+	; PokerusStatus
+	ld [de], a
+	inc de
+	; CaughtData/CaughtTime/CaughtLevel
+	ld [de], a
+	inc de
+	; CaughtGender/CaughtLocation
+	ld [de], a
+	inc de
+
+	; Initialize level.
+	ld a, [wCurPartyLevel]
+	ld [de], a
+	inc de
+
+	ld hl, wEnemyMonStatus
+	; Copy wEnemyMonStatus
+	ld a, [hli]
+	ld [de], a
+	inc de
+	; Copy EnemyMonUnused
+	ld a, [hli]
+	ld [de], a
+	inc de
+	; Copy wEnemyMonHP
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+	inc de
+
+.initstats
+	ld a, [wBattleMode]
+	dec a
+	jr nz, .generatestats
+	ld hl, wEnemyMonMaxHP
+	ld bc, PARTYMON_STRUCT_LENGTH - MON_MAXHP
+	call CopyBytes
+	pop hl
+	jr .registerunowndex
+
+.generatestats
+	pop hl
+	ld bc, MON_STAT_EXP - 1
+	add hl, bc
+	ld b, FALSE
+	call CalcMonStats
+
+.registerunowndex
+	ld a, [wMonType]
+	and $f
+	jr nz, .done
+	ld a, [wCurPartySpecies]
+	cp UNOWN
+	jr nz, .done
+	ld hl, wPartyMon1DVs
+	ld a, [wPartyCount]
+	dec a
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	predef GetUnownLetter
+	callfar UpdateUnownDex
+
+.done
+	scf ; When this function returns, the carry flag indicates success vs failure.
+	ret
+; da6d
+
+FillPP: ; da6d
+	push bc
+	ld b, NUM_MOVES
+.loop
+	ld a, [hli]
+	and a
+	jr z, .next
+	dec a
+	push hl
+	push de
+	push bc
+	ld hl, Moves
+	ld bc, MOVE_LENGTH
+	call AddNTimes
+	ld de, wStringBuffer1
+	ld a, BANK(Moves)
+	call FarCopyBytes
+	pop bc
+	pop de
+	pop hl
+	ld a, [wStringBuffer1 + MOVE_PP]
+
+.next
+	ld [de], a
+	inc de
+	dec b
+	jr nz, .loop
+	pop bc
+	ret
+; da96
+
+AddTempmonToParty: ; da96
+	ld hl, wPartyCount
+	ld a, [hl]
+	cp PARTY_LENGTH
+	scf
+	ret z
+
+	inc a
+	ld [hl], a
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [wCurPartySpecies]
+	ld [hli], a
+	ld [hl], $ff
+
+	ld hl, wPartyMon1Species
+	ld a, [wPartyCount]
+	dec a
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld e, l
+	ld d, h
+	ld hl, wTempMonSpecies
+	call CopyBytes
+
+	ld hl, wPartyMonOT
+	ld a, [wPartyCount]
+	dec a
+	call SkipNames
+	ld d, h
+	ld e, l
+	ld hl, wOTPartyMonOT
+	ld a, [wCurPartyMon]
+	call SkipNames
+	ld bc, NAME_LENGTH
+	call CopyBytes
+
+	ld hl, wPartyMonNicknames
+	ld a, [wPartyCount]
+	dec a
+	call SkipNames
+	ld d, h
+	ld e, l
+	ld hl, wOTPartyMonNicknames
+	ld a, [wCurPartyMon]
+	call SkipNames
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+
+	ld a, [wCurPartySpecies]
+	ld [wNamedObjectIndexBuffer], a
+	cp EGG
+	jr z, .egg
+	dec a
+	call SetSeenAndCaughtMon
+	ld hl, wPartyMon1Happiness
+	ld a, [wPartyCount]
+	dec a
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld [hl], BASE_HAPPINESS
+.egg
+
+	ld a, [wCurPartySpecies]
+	cp UNOWN
+	jr nz, .done
+	ld hl, wPartyMon1DVs
+	ld a, [wPartyCount]
+	dec a
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	predef GetUnownLetter
+	callfar UpdateUnownDex
+	ld a, [wFirstUnownSeen]
+	and a
+	jr nz, .done
+	ld a, [wUnownLetter]
+	ld [wFirstUnownSeen], a
+.done
+
+	and a
+	ret
+
+SendGetMonIntoFromBox: ; db3f
+; Sents/Gets mon into/from Box depending on Parameter
+; wPokemonWithdrawDepositParameter == 0: get mon into Party
+; wPokemonWithdrawDepositParameter == 1: sent mon into Box
+; wPokemonWithdrawDepositParameter == 2: get mon from DayCare
+; wPokemonWithdrawDepositParameter == 3: put mon into DayCare
+
+	ld a, BANK(sBoxCount)
+	call GetSRAMBank
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	jr z, .check_IfPartyIsFull
+	cp DAY_CARE_WITHDRAW
+	jr z, .check_IfPartyIsFull
+	cp DAY_CARE_DEPOSIT
+	ld hl, wBreedMon1Species
+	jr z, .breedmon
+
+	; we want to sent a mon into the Box
+	; so check if there's enough space
+	ld hl, sBoxCount
+	ld a, [hl]
+	cp MONS_PER_BOX
+	jr nz, .there_is_room
+	jp CloseSRAM_And_SetCarryFlag
+
+.check_IfPartyIsFull
+	ld hl, wPartyCount
+	ld a, [hl]
+	cp PARTY_LENGTH
+	jp z, CloseSRAM_And_SetCarryFlag
+
+.there_is_room
+	inc a
+	ld [hl], a
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [wPokemonWithdrawDepositParameter]
+	cp DAY_CARE_WITHDRAW
+	ld a, [wBreedMon1Species]
+	jr z, .okay1
+	ld a, [wCurPartySpecies]
+
+.okay1
+	ld [hli], a
+	ld [hl], $ff
+	ld a, [wPokemonWithdrawDepositParameter]
+	dec a
+	ld hl, wPartyMon1Species
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, [wPartyCount]
+	jr nz, .okay2
+	ld hl, sBoxMon1Species
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, [sBoxCount]
+
+.okay2
+	dec a ; wPartyCount - 1
+	call AddNTimes
+
+.breedmon
+	push hl
+	ld e, l
+	ld d, h
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	ld hl, sBoxMon1Species
+	ld bc, BOXMON_STRUCT_LENGTH
+	jr z, .okay3
+	cp DAY_CARE_WITHDRAW
+	ld hl, wBreedMon1Species
+	jr z, .okay4
+	ld hl, wPartyMon1Species
+	ld bc, PARTYMON_STRUCT_LENGTH
+
+.okay3
+	ld a, [wCurPartyMon]
+	call AddNTimes
+
+.okay4
+	ld bc, BOXMON_STRUCT_LENGTH
+	call CopyBytes
+	ld a, [wPokemonWithdrawDepositParameter]
+	cp DAY_CARE_DEPOSIT
+	ld de, wBreedMon1OT
+	jr z, .okay5
+	dec a
+	ld hl, wPartyMonOT
+	ld a, [wPartyCount]
+	jr nz, .okay6
+	ld hl, sBoxMonOT
+	ld a, [sBoxCount]
+
+.okay6
+	dec a
+	call SkipNames
+	ld d, h
+	ld e, l
+
+.okay5
+	ld hl, sBoxMonOT
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	jr z, .okay7
+	ld hl, wBreedMon1OT
+	cp DAY_CARE_WITHDRAW
+	jr z, .okay8
+	ld hl, wPartyMonOT
+
+.okay7
+	ld a, [wCurPartyMon]
+	call SkipNames
+
+.okay8
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ld a, [wPokemonWithdrawDepositParameter]
+	cp DAY_CARE_DEPOSIT
+	ld de, wBreedMon1Nick
+	jr z, .okay9
+	dec a
+	ld hl, wPartyMonNicknames
+	ld a, [wPartyCount]
+	jr nz, .okay10
+	ld hl, sBoxMonNicknames
+	ld a, [sBoxCount]
+
+.okay10
+	dec a
+	call SkipNames
+	ld d, h
+	ld e, l
+
+.okay9
+	ld hl, sBoxMonNicknames
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	jr z, .okay11
+	ld hl, wBreedMon1Nick
+	cp DAY_CARE_WITHDRAW
+	jr z, .okay12
+	ld hl, wPartyMonNicknames
+
+.okay11
+	ld a, [wCurPartyMon]
+	call SkipNames
+
+.okay12
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+	pop hl
+
+	ld a, [wPokemonWithdrawDepositParameter]
+	cp PC_DEPOSIT
+	jr z, .took_out_of_box
+	cp DAY_CARE_DEPOSIT
+	jp z, .CloseSRAM_And_ClearCarryFlag
+
+	push hl
+	srl a
+	add $2
+	ld [wMonType], a
+	predef CopyMonToTempMon
+	callfar CalcLevel
+	ld a, d
+	ld [wCurPartyLevel], a
+	pop hl
+
+	ld b, h
+	ld c, l
+	ld hl, MON_LEVEL
+	add hl, bc
+	ld [hl], a
+	ld hl, MON_MAXHP
+	add hl, bc
+	ld d, h
+	ld e, l
+	ld hl, MON_STAT_EXP - 1
+	add hl, bc
+
+	push bc
+	ld b, TRUE
+	call CalcMonStats
+	pop bc
+
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	jr nz, .CloseSRAM_And_ClearCarryFlag
+	ld hl, MON_STATUS
+	add hl, bc
+	xor a
+	ld [hl], a
+	ld hl, MON_HP
+	add hl, bc
+	ld d, h
+	ld e, l
+	ld a, [wCurPartySpecies]
+	cp EGG
+	jr z, .egg
+	inc hl
+	inc hl
+	ld a, [hli]
+	ld [de], a
+	ld a, [hl]
+	inc de
+	ld [de], a
+	jr .CloseSRAM_And_ClearCarryFlag
+
+.egg
+	xor a
+	ld [de], a
+	inc de
+	ld [de], a
+	jr .CloseSRAM_And_ClearCarryFlag
+
+.took_out_of_box
+	ld a, [sBoxCount]
+	dec a
+	ld b, a
+	call RestorePPofDepositedPokemon
+.CloseSRAM_And_ClearCarryFlag:
+	call CloseSRAM
+	and a
+	ret
+; dcb1
+
+CloseSRAM_And_SetCarryFlag: ; dcb1
+	call CloseSRAM
+	scf
+	ret
+; dcb6
+
+RestorePPofDepositedPokemon: ; dcb6
+	ld a, b
+	ld hl, sBoxMons
+	ld bc, BOXMON_STRUCT_LENGTH
+	call AddNTimes
+	ld b, h
+	ld c, l
+	ld hl, MON_PP
+	add hl, bc
+	push hl
+	push bc
+	ld de, wTempMonPP
+	ld bc, NUM_MOVES
+	call CopyBytes
+	pop bc
+	ld hl, MON_MOVES
+	add hl, bc
+	push hl
+	ld de, wTempMonMoves
+	ld bc, NUM_MOVES
+	call CopyBytes
+	pop hl
+	pop de
+
+	ld a, [wMenuCursorY]
+	push af
+	ld a, [wMonType]
+	push af
+	ld b, 0
+.loop
+	ld a, [hli]
+	and a
+	jr z, .done
+	ld [wTempMonMoves], a
+	ld a, BOXMON
+	ld [wMonType], a
+	ld a, b
+	ld [wMenuCursorY], a
+	push bc
+	push hl
+	push de
+	farcall GetMaxPPOfMove
+	pop de
+	pop hl
+	ld a, [wd265]
+	ld b, a
+	ld a, [de]
+	and %11000000
+	add b
+	ld [de], a
+	pop bc
+	inc de
+	inc b
+	ld a, b
+	cp NUM_MOVES
+	jr c, .loop
+
+.done
+	pop af
+	ld [wMonType], a
+	pop af
+	ld [wMenuCursorY], a
+	ret
+; dd21
+
+RetrieveMonFromDayCareMan: ; dd21
+	ld a, [wBreedMon1Species]
+	ld [wCurPartySpecies], a
+	ld de, SFX_TRANSACTION
+	call PlaySFX
+	call WaitSFX
+	call GetBreedMon1LevelGrowth
+	ld a, b
+	ld [wd002], a
+	ld a, e
+	ld [wCurPartyLevel], a
+	xor a
+	ld [wPokemonWithdrawDepositParameter], a
+	jp RetrieveBreedmon
+; dd42
+
+RetrieveMonFromDayCareLady: ; dd42
+	ld a, [wBreedMon2Species]
+	ld [wCurPartySpecies], a
+	ld de, SFX_TRANSACTION
+	call PlaySFX
+	call WaitSFX
+	call GetBreedMon2LevelGrowth
+	ld a, b
+	ld [wd002], a
+	ld a, e
+	ld [wCurPartyLevel], a
+	ld a, PC_DEPOSIT
+	ld [wPokemonWithdrawDepositParameter], a
+	jp RetrieveBreedmon
+; dd64
+
+RetrieveBreedmon: ; dd64
+	ld hl, wPartyCount
+	ld a, [hl]
+	cp PARTY_LENGTH
+	jr nz, .room_in_party
+	scf
+	ret
+
+.room_in_party
+	inc a
+	ld [hl], a
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	ld a, [wBreedMon1Species]
+	ld de, wBreedMon1Nick
+	jr z, .okay
+	ld a, [wBreedMon2Species]
+	ld de, wBreedMon2Nick
+
+.okay
+	ld [hli], a
+	ld [wCurSpecies], a
+	ld a, $ff
+	ld [hl], a
+	ld hl, wPartyMonNicknames
+	ld a, [wPartyCount]
+	dec a
+	call SkipNames
+	push hl
+	ld h, d
+	ld l, e
+	pop de
+	call CopyBytes
+	push hl
+	ld hl, wPartyMonOT
+	ld a, [wPartyCount]
+	dec a
+	call SkipNames
+	ld d, h
+	ld e, l
+	pop hl
+	call CopyBytes
+	push hl
+	call GetLastPartyMon
+	pop hl
+	ld bc, BOXMON_STRUCT_LENGTH
+	call CopyBytes
+	call GetBaseData
+	call GetLastPartyMon
+	ld b, d
+	ld c, e
+	ld hl, MON_LEVEL
+	add hl, bc
+	ld a, [wCurPartyLevel]
+	ld [hl], a
+	ld hl, MON_MAXHP
+	add hl, bc
+	ld d, h
+	ld e, l
+	ld hl, $a
+	add hl, bc
+	push bc
+	ld b, TRUE
+	call CalcMonStats
+	ld hl, wPartyMon1Moves
+	ld a, [wPartyCount]
+	dec a
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld a, $1
+	ld [wBuffer1], a
+	predef FillMoves
+	ld a, [wPartyCount]
+	dec a
+	ld [wCurPartyMon], a
+	farcall HealPartyMon
+	ld a, [wCurPartyLevel]
+	ld d, a
+	callfar CalcExpAtLevel
+	pop bc
+	ld hl, $8
+	add hl, bc
+	ld a, [hMultiplicand]
+	ld [hli], a
+	ld a, [hMultiplicand + 1]
+	ld [hli], a
+	ld a, [hMultiplicand + 2]
+	ld [hl], a
+	and a
+	ret
+; de1a
+
+GetLastPartyMon: ; de1a
+	ld a, [wPartyCount]
+	dec a
+	ld hl, wPartyMon1Species
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ret
+; de2a
+
+DepositMonWithDayCareMan: ; de2a
+	ld de, wBreedMon1Nick
+	call DepositBreedmon
+	xor a ; REMOVE_PARTY
+	ld [wPokemonWithdrawDepositParameter], a
+	jp RemoveMonFromPartyOrBox
+; de37
+
+DepositMonWithDayCareLady: ; de37
+	ld de, wBreedMon2Nick
+	call DepositBreedmon
+	xor a ; REMOVE_PARTY
+	ld [wPokemonWithdrawDepositParameter], a
+	jp RemoveMonFromPartyOrBox
+; de44
+
+DepositBreedmon: ; de44
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMonNicknames
+	call SkipNames
+	call CopyBytes
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMonOT
+	call SkipNames
+	call CopyBytes
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1Species
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld bc, BOXMON_STRUCT_LENGTH
+	jp CopyBytes
+
+SendMonIntoBox: ; de6e
+; Sends the mon into one of Bills Boxes
+; the data comes mainly from 'wEnemyMon:'
+	ld a, BANK(sBoxCount)
+	call GetSRAMBank
+	ld de, sBoxCount
+	ld a, [de]
+	cp MONS_PER_BOX
+	jp nc, .full
+	inc a
+	ld [de], a
+
+	ld a, [wCurPartySpecies]
+	ld [wCurSpecies], a
+	ld c, a
+.loop
+	inc de
+	ld a, [de]
+	ld b, a
+	ld a, c
+	ld c, b
+	ld [de], a
+	inc a
+	jr nz, .loop
+
+	call GetBaseData
+	call ShiftBoxMon
+
+	ld hl, wPlayerName
+	ld de, sBoxMonOT
+	ld bc, NAME_LENGTH
+	call CopyBytes
+
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	call GetPokemonName
+
+	ld de, sBoxMonNicknames
+	ld hl, wStringBuffer1
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+
+	ld hl, wEnemyMon
+	ld de, sBoxMon1
+	ld bc, 1 + 1 + NUM_MOVES ; species + item + moves
+	call CopyBytes
+
+	ld hl, wPlayerID
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+	inc de
+	push de
+	ld a, [wCurPartyLevel]
+	ld d, a
+	callfar CalcExpAtLevel
+	pop de
+	ld a, [hProduct + 1]
+	ld [de], a
+	inc de
+	ld a, [hProduct + 2]
+	ld [de], a
+	inc de
+	ld a, [hProduct + 3]
+	ld [de], a
+	inc de
+
+	; Set all 5 Experience Values to 0
+	xor a
+	ld b, 2 * 5
+.loop2
+	ld [de], a
+	inc de
+	dec b
+	jr nz, .loop2
+
+	ld hl, wEnemyMonDVs
+	ld b, 2 + NUM_MOVES ; DVs and PP ; wEnemyMonHappiness - wEnemyMonDVs
+.loop3
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec b
+	jr nz, .loop3
+
+	ld a, BASE_HAPPINESS
+	ld [de], a
+	inc de
+	xor a
+	ld [de], a
+	inc de
+	ld [de], a
+	inc de
+	ld [de], a
+	inc de
+	ld a, [wCurPartyLevel]
+	ld [de], a
+	ld a, [wCurPartySpecies]
+	dec a
+	call SetSeenAndCaughtMon
+	ld a, [wCurPartySpecies]
+	cp UNOWN
+	jr nz, .not_unown
+	ld hl, sBoxMon1DVs
+	predef GetUnownLetter
+	callfar UpdateUnownDex
+
+.not_unown
+	ld hl, sBoxMon1Moves
+	ld de, wTempMonMoves
+	ld bc, NUM_MOVES
+	call CopyBytes
+
+	ld hl, sBoxMon1PP
+	ld de, wTempMonPP
+	ld bc, NUM_MOVES
+	call CopyBytes
+
+	ld b, 0
+	call RestorePPofDepositedPokemon
+
+	call CloseSRAM
+	scf
+	ret
+; df42
+
+.full ; df42
+	call CloseSRAM
+	and a
+	ret
+; df47
+
+ShiftBoxMon: ; df47
+	ld hl, sBoxMonOT
+	ld bc, NAME_LENGTH
+	call .shift
+
+	ld hl, sBoxMonNicknames
+	ld bc, MON_NAME_LENGTH
+	call .shift
+
+	ld hl, sBoxMons
+	ld bc, BOXMON_STRUCT_LENGTH
+
+.shift
+	ld a, [sBoxCount]
+	cp 2
+	ret c
+
+	push hl
+	call AddNTimes
+	dec hl
+	ld e, l
+	ld d, h
+	pop hl
+
+	ld a, [sBoxCount]
+	dec a
+	call AddNTimes
+	dec hl
+
+	push hl
+	ld a, [sBoxCount]
+	dec a
+	ld hl, 0
+	call AddNTimes
+	ld c, l
+	ld b, h
+	pop hl
+.loop
+	ld a, [hld]
+	ld [de], a
+	dec de
+	dec bc
+	ld a, c
+	or b
+	jr nz, .loop
+	ret
+; df8c
+
+GiveEgg:: ; df8c
+	ld a, [wCurPartySpecies]
+	push af
+	callfar GetPreEvolution
+	callfar GetPreEvolution
+	ld a, [wCurPartySpecies]
+	dec a
+
+; TryAddMonToParty sets Seen and Caught flags
+; when it is successful.  This routine will make
+; sure that we aren't newly setting flags.
+	push af
+	call CheckCaughtMon
+	pop af
+	push bc
+	call CheckSeenMon
+	push bc
+
+	call TryAddMonToParty
+
+; If we haven't caught this Pokemon before receiving
+; the Egg, reset the flag that was just set by
+; TryAddMonToParty.
+	pop bc
+	ld a, c
+	and a
+	jr nz, .skip_caught_flag
+	ld a, [wCurPartySpecies]
+	dec a
+	ld c, a
+	ld d, $0
+	ld hl, wPokedexCaught
+	ld b, RESET_FLAG
+	predef SmallFarFlagAction
+
+.skip_caught_flag
+; If we haven't seen this Pokemon before receiving
+; the Egg, reset the flag that was just set by
+; TryAddMonToParty.
+	pop bc
+	ld a, c
+	and a
+	jr nz, .skip_seen_flag
+	ld a, [wCurPartySpecies]
+	dec a
+	ld c, a
+	ld d, $0
+	ld hl, wPokedexSeen
+	ld b, RESET_FLAG
+	predef SmallFarFlagAction
+
+.skip_seen_flag
+	pop af
+	ld [wCurPartySpecies], a
+	ld a, [wPartyCount]
+	dec a
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld hl, wPartyMon1Species
+	call AddNTimes
+	ld a, [wCurPartySpecies]
+	ld [hl], a
+	ld hl, wPartyCount
+	ld a, [hl]
+	ld b, 0
+	ld c, a
+	add hl, bc
+	ld a, EGG
+	ld [hl], a
+	ld a, [wPartyCount]
+	dec a
+	ld hl, wPartyMonNicknames
+	call SkipNames
+	ld de, String_Egg
+	call CopyName2
+	ld a, [wPartyCount]
+	dec a
+	ld hl, wPartyMon1Happiness
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [wMonStatusFlags]
+	bit 1, a
+	ld a, 1
+	jr nz, .got_init_happiness
+	ld a, [wBaseEggSteps]
+
+.got_init_happiness
+	ld [hl], a
+	ld a, [wPartyCount]
+	dec a
+	ld hl, wPartyMon1HP
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	xor a
+	ld [hli], a
+	ld [hl], a
+	and a
+	ret
+; e035
+
+String_Egg: ; e035
+	db "EGG@"
+; e039
+
+RemoveMonFromPartyOrBox: ; e039
+	ld hl, wPartyCount
+
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	jr z, .okay
+
+	ld a, BANK(sBoxCount)
+	call GetSRAMBank
+	ld hl, sBoxCount
+
+.okay
+	ld a, [hl]
+	dec a
+	ld [hli], a
+	ld a, [wCurPartyMon]
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld e, l
+	ld d, h
+	inc de
+.loop
+	ld a, [de]
+	inc de
+	ld [hli], a
+	inc a
+	jr nz, .loop
+	ld hl, wPartyMonOT
+	ld d, PARTY_LENGTH - 1
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	jr z, .party
+	ld hl, sBoxMonOT
+	ld d, MONS_PER_BOX - 1
+
+.party
+	; If this is the last mon in our party (box),
+	; shift all the other mons up to close the gap.
+	ld a, [wCurPartyMon]
+	call SkipNames
+	ld a, [wCurPartyMon]
+	cp d
+	jr nz, .delete_inside
+	ld [hl], -1
+	jp .finish
+
+.delete_inside
+	; Shift the OT names
+	ld d, h
+	ld e, l
+	ld bc, MON_NAME_LENGTH
+	add hl, bc
+	ld bc, wPartyMonNicknames
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	jr z, .party2
+	ld bc, sBoxMonNicknames
+.party2
+	call CopyDataUntil
+	; Shift the struct
+	ld hl, wPartyMons
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	jr z, .party4
+	ld hl, sBoxMons
+	ld bc, BOXMON_STRUCT_LENGTH
+.party4
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	jr z, .party5
+	ld bc, BOXMON_STRUCT_LENGTH
+	add hl, bc
+	ld bc, sBoxMonOT
+	jr .copy
+
+.party5
+	ld bc, PARTYMON_STRUCT_LENGTH
+	add hl, bc
+	ld bc, wPartyMonOT
+.copy
+	call CopyDataUntil
+	; Shift the nicknames
+	ld hl, wPartyMonNicknames
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	jr z, .party6
+	ld hl, sBoxMonNicknames
+.party6
+	ld bc, MON_NAME_LENGTH
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld bc, MON_NAME_LENGTH
+	add hl, bc
+	ld bc, wPartyMonNicknamesEnd
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	jr z, .party7
+	ld bc, sBoxMonNicknamesEnd
+.party7
+	call CopyDataUntil
+	; Mail time!
+.finish
+	ld a, [wPokemonWithdrawDepositParameter]
+	and a
+	jp nz, CloseSRAM
+	ld a, [wLinkMode]
+	and a
+	ret nz
+	; Shift mail
+	ld a, BANK(sPartyMail)
+	call GetSRAMBank
+	; If this is the last mon in our party, no need to shift mail.
+	ld hl, wPartyCount
+	ld a, [wCurPartyMon]
+	cp [hl]
+	jr z, .close_sram
+	; Shift our mail messages up.
+	ld hl, sPartyMail
+	ld bc, MAIL_STRUCT_LENGTH
+	call AddNTimes
+	push hl
+	add hl, bc
+	pop de
+	ld a, [wCurPartyMon]
+	ld b, a
+.loop2
+	push bc
+	push hl
+	ld bc, MAIL_STRUCT_LENGTH
+	call CopyBytes
+	pop hl
+	push hl
+	ld bc, MAIL_STRUCT_LENGTH
+	add hl, bc
+	pop de
+	pop bc
+	inc b
+	ld a, [wPartyCount]
+	cp b
+	jr nz, .loop2
+.close_sram
+	jp CloseSRAM
+; e134
+
+
+ComputeNPCTrademonStats: ; e134
+	ld a, MON_LEVEL
+	call GetPartyParamLocation
+	ld a, [hl]
+	ld [MON_LEVEL], a ; wow
+	ld a, MON_SPECIES
+	call GetPartyParamLocation
+	ld a, [hl]
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld a, MON_MAXHP
+	call GetPartyParamLocation
+	ld d, h
+	ld e, l
+	push de
+	ld a, MON_STAT_EXP - 1
+	call GetPartyParamLocation
+	ld b, TRUE
+	call CalcMonStats
+	pop de
+	ld a, MON_HP
+	call GetPartyParamLocation
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	ld [hl], a
+	ret
+; e167
+
+CalcMonStats: ; e167
+; Calculates all 6 Stats of a mon
+; b: Take into account stat EXP if TRUE
+; 'c' counts from 1-6 and points with 'wBaseStats' to the base value
+; hl is the path to the Stat EXP
+; de points to where the final stats will be saved
+
+	ld c, $0
+.loop
+	inc c
+	call CalcMonStatC
+	ld a, [hMultiplicand + 1]
+	ld [de], a
+	inc de
+	ld a, [hMultiplicand + 2]
+	ld [de], a
+	inc de
+	ld a, c
+	cp STAT_SDEF
+	jr nz, .loop
+	ret
+; e17b
+
+CalcMonStatC: ; e17b
+; 'c' is 1-6 and points to the BaseStat
+; 1: HP
+; 2: Attack
+; 3: Defense
+; 4: Speed
+; 5: SpAtk
+; 6: SpDef
+	push hl
+	push de
+	push bc
+	ld a, b
+	ld d, a
+	push hl
+	ld hl, wBaseStats
+	dec hl ; has to be decreased, because 'c' begins with 1
+	ld b, $0
+	add hl, bc
+	ld a, [hl]
+	ld e, a
+	pop hl
+	push hl
+	ld a, c
+	cp STAT_SDEF
+	jr nz, .not_spdef
+	dec hl
+	dec hl
+
+.not_spdef
+	sla c
+	ld a, d
+	and a
+	jr z, .no_stat_exp
+	add hl, bc
+	push de
+	ld a, [hld]
+	ld e, a
+	ld d, [hl]
+	farcall GetSquareRoot
+	pop de
+
+.no_stat_exp
+	srl c
+	pop hl
+	push bc
+	ld bc, MON_DVS - MON_HP_EXP + 1
+	add hl, bc
+	pop bc
+	ld a, c
+	cp STAT_ATK
+	jr z, .Attack
+	cp STAT_DEF
+	jr z, .Defense
+	cp STAT_SPD
+	jr z, .Speed
+	cp STAT_SATK
+	jr z, .Special
+	cp STAT_SDEF
+	jr z, .Special
+; DV_HP = (DV_ATK & 1) << 3 + (DV_DEF & 1) << 2 + (DV_SPD & 1) << 1 + (DV_SPC & 1)
+	push bc
+	ld a, [hl]
+	swap a
+	and $1
+	add a
+	add a
+	add a
+	ld b, a
+	ld a, [hli]
+	and $1
+	add a
+	add a
+	add b
+	ld b, a
+	ld a, [hl]
+	swap a
+	and $1
+	add a
+	add b
+	ld b, a
+	ld a, [hl]
+	and $1
+	add b
+	pop bc
+	jr .GotDV
+
+.Attack:
+	ld a, [hl]
+	swap a
+	and $f
+	jr .GotDV
+
+.Defense:
+	ld a, [hl]
+	and $f
+	jr .GotDV
+
+.Speed:
+	inc hl
+	ld a, [hl]
+	swap a
+	and $f
+	jr .GotDV
+
+.Special:
+	inc hl
+	ld a, [hl]
+	and $f
+
+.GotDV:
+	ld d, 0
+	add e
+	ld e, a
+	jr nc, .no_overflow_1
+	inc d
+
+.no_overflow_1
+	sla e
+	rl d
+	srl b
+	srl b
+	ld a, b
+	add e
+	jr nc, .no_overflow_2
+	inc d
+
+.no_overflow_2
+	ld [hMultiplicand + 2], a
+	ld a, d
+	ld [hMultiplicand + 1], a
+	xor a
+	ld [hMultiplicand + 0], a
+	ld a, [wCurPartyLevel]
+	ld [hMultiplier], a
+	call Multiply
+	ld a, [hProduct + 1]
+	ld [hDividend + 0], a
+	ld a, [hProduct + 2]
+	ld [hDividend + 1], a
+	ld a, [hProduct + 3]
+	ld [hDividend + 2], a
+	ld a, 100
+	ld [hDivisor], a
+	ld a, 3
+	ld b, a
+	call Divide
+	ld a, c
+	cp STAT_HP
+	ld a, STAT_MIN_NORMAL
+	jr nz, .not_hp
+	ld a, [wCurPartyLevel]
+	ld b, a
+	ld a, [hQuotient + 2]
+	add b
+	ld [hMultiplicand + 2], a
+	jr nc, .no_overflow_3
+	ld a, [hQuotient + 1]
+	inc a
+	ld [hMultiplicand + 1], a
+
+.no_overflow_3
+	ld a, STAT_MIN_HP
+
+.not_hp
+	ld b, a
+	ld a, [hQuotient + 2]
+	add b
+	ld [hMultiplicand + 2], a
+	jr nc, .no_overflow_4
+	ld a, [hQuotient + 1]
+	inc a
+	ld [hMultiplicand + 1], a
+
+.no_overflow_4
+	ld a, [hQuotient + 1]
+	cp HIGH(MAX_STAT_VALUE + 1) + 1
+	jr nc, .max_stat
+	cp HIGH(MAX_STAT_VALUE + 1)
+	jr c, .stat_value_okay
+	ld a, [hQuotient + 2]
+	cp LOW(MAX_STAT_VALUE + 1)
+	jr c, .stat_value_okay
+
+.max_stat
+	ld a, HIGH(MAX_STAT_VALUE)
+	ld [hMultiplicand + 1], a
+	ld a, LOW(MAX_STAT_VALUE)
+	ld [hMultiplicand + 2], a
+
+.stat_value_okay
+	pop bc
+	pop de
+	pop hl
+	ret
+; e277
+
+GivePoke:: ; e277
+	push de
+	push bc
+	xor a ; PARTYMON
+	ld [wMonType], a
+	call TryAddMonToParty
+	jr nc, .failed
+	ld hl, wPartyMonNicknames
+	ld a, [wPartyCount]
+	dec a
+	ld [wCurPartyMon], a
+	call SkipNames
+	ld d, h
+	ld e, l
+	pop bc
+	ld a, b
+	ld b, 0
+	push bc
+	push de
+	push af
+	ld a, [wCurItem]
+	and a
+	jr z, .done
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1Item
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [wCurItem]
+	ld [hl], a
+	jr .done
+
+.failed
+	ld a, [wCurPartySpecies]
+	ld [wTempEnemyMonSpecies], a
+	callfar LoadEnemyMon
+	call SendMonIntoBox
+	jp nc, .FailedToGiveMon
+	ld a, BOXMON
+	ld [wMonType], a
+	xor a
+	ld [wCurPartyMon], a
+	ld de, wMonOrItemNameBuffer
+	pop bc
+	ld a, b
+	ld b, 1
+	push bc
+	push de
+	push af
+	ld a, [wCurItem]
+	and a
+	jr z, .done
+	ld a, [wCurItem]
+	ld [sBoxMon1Item], a
+
+.done
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	ld [wTempEnemyMonSpecies], a
+	call GetPokemonName
+	ld hl, wStringBuffer1
+	ld de, wMonOrItemNameBuffer
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+	pop af
+	and a
+	jp z, .wildmon
+	pop de
+	pop bc
+	pop hl
+	push bc
+	push hl
+	ld a, [wScriptBank]
+	call GetFarHalfword
+	ld bc, MON_NAME_LENGTH
+	ld a, [wScriptBank]
+	call FarCopyBytes
+	pop hl
+	inc hl
+	inc hl
+	ld a, [wScriptBank]
+	call GetFarHalfword
+	pop bc
+	ld a, b
+	and a
+	push de
+	push bc
+	jr nz, .send_to_box
+
+	push hl
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMonOT
+	call SkipNames
+	ld d, h
+	ld e, l
+	pop hl
+.otnameloop
+	ld a, [wScriptBank]
+	call GetFarByte
+	ld [de], a
+	inc hl
+	inc de
+	cp "@"
+	jr nz, .otnameloop
+	ld a, [wScriptBank]
+	call GetFarByte
+	ld b, a
+	push bc
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1ID
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, HIGH(01001)
+	ld [hli], a
+	ld [hl], LOW(01001)
+	pop bc
+	farcall SetGiftPartyMonCaughtData
+	jr .skip_nickname
+
+.send_to_box
+	ld a, BANK(sBoxMonOT)
+	call GetSRAMBank
+	ld de, sBoxMonOT
+.loop
+	ld a, [wScriptBank]
+	call GetFarByte
+	ld [de], a
+	inc hl
+	inc de
+	cp "@"
+	jr nz, .loop
+	ld a, [wScriptBank]
+	call GetFarByte
+	ld b, a
+	ld hl, sBoxMon1ID
+	call Random
+	ld [hli], a
+	call Random
+	ld [hl], a
+	call CloseSRAM
+	farcall SetGiftBoxMonCaughtData
+	jr .skip_nickname
+
+.wildmon
+	pop de
+	pop bc
+	push bc
+	push de
+	ld a, b
+	and a
+	jr z, .party
+	farcall SetBoxMonCaughtData
+	jr .set_caught_data
+
+.party
+	farcall SetCaughtData
+.set_caught_data
+	farcall GiveANickname_YesNo
+	pop de
+	jr c, .skip_nickname
+	call InitNickname
+
+.skip_nickname
+	pop bc
+	pop de
+	ld a, b
+	and a
+	ret z
+	ld hl, TextJump_WasSentToBillsPC
+	call PrintText
+	ld a, BANK(sBoxMonNicknames)
+	call GetSRAMBank
+	ld hl, wMonOrItemNameBuffer
+	ld de, sBoxMonNicknames
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+	call CloseSRAM
+	ld b, $1
+	ret
+; e3d4
+
+.FailedToGiveMon: ; e3d4
+	pop bc
+	pop de
+	ld b, $2
+	ret
+; e3d9
+
+TextJump_WasSentToBillsPC: ; 0xe3d9
+	; was sent to BILL's PC.
+	text_jump Text_WasSentToBillsPC
+	db "@"
+; 0xe3de
+
+InitNickname: ; e3de
+	push de
+	call LoadStandardMenuHeader
+	call DisableSpriteUpdates
+	pop de
+	push de
+	ld b, $0
+	farcall NamingScreen
+	pop hl
+	ld de, wStringBuffer1
+	call InitName
+	ld a, $4 ; ExitAllMenus is in bank 0, XXX could this be in bank 4 in pokered?
+	ld hl, ExitAllMenus
+	rst FarCall
+	ret
+; e3fd
--- /dev/null
+++ b/engine/pokemon/move_mon_wo_mail.asm
@@ -1,0 +1,133 @@
+InsertPokemonIntoBox: ; 51322
+	ld a, BANK(sBoxCount)
+	call GetSRAMBank
+	ld hl, sBoxCount
+	call InsertSpeciesIntoBoxOrParty
+	ld a, [sBoxCount]
+	dec a
+	ld [wd265], a
+	ld hl, sBoxMonNicknames
+	ld bc, MON_NAME_LENGTH
+	ld de, wBufferMonNick
+	call InsertDataIntoBoxOrParty
+	ld a, [sBoxCount]
+	dec a
+	ld [wd265], a
+	ld hl, sBoxMonOT
+	ld bc, NAME_LENGTH
+	ld de, wBufferMonOT
+	call InsertDataIntoBoxOrParty
+	ld a, [sBoxCount]
+	dec a
+	ld [wd265], a
+	ld hl, sBoxMons
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld de, wBufferMon
+	call InsertDataIntoBoxOrParty
+	ld hl, wBufferMonMoves
+	ld de, wTempMonMoves
+	ld bc, NUM_MOVES
+	call CopyBytes
+	ld hl, wBufferMonPP
+	ld de, wTempMonPP
+	ld bc, NUM_MOVES
+	call CopyBytes
+	ld a, [wCurPartyMon]
+	ld b, a
+	farcall RestorePPofDepositedPokemon
+	jp CloseSRAM
+
+InsertPokemonIntoParty: ; 5138b
+	ld hl, wPartyCount
+	call InsertSpeciesIntoBoxOrParty
+	ld a, [wPartyCount]
+	dec a
+	ld [wd265], a
+	ld hl, wPartyMonNicknames
+	ld bc, MON_NAME_LENGTH
+	ld de, wBufferMonNick
+	call InsertDataIntoBoxOrParty
+	ld a, [wPartyCount]
+	dec a
+	ld [wd265], a
+	ld hl, wPartyMonOT
+	ld bc, NAME_LENGTH
+	ld de, wBufferMonOT
+	call InsertDataIntoBoxOrParty
+	ld a, [wPartyCount]
+	dec a
+	ld [wd265], a
+	ld hl, wPartyMons
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld de, wBufferMon
+	call InsertDataIntoBoxOrParty
+	ret
+
+InsertSpeciesIntoBoxOrParty: ; 513cb
+	inc [hl]
+	inc hl
+	ld a, [wCurPartyMon]
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [wCurPartySpecies]
+	ld c, a
+.loop
+	ld a, [hl]
+	ld [hl], c
+	inc hl
+	inc c
+	ld c, a
+	jr nz, .loop
+	ret
+
+InsertDataIntoBoxOrParty: ; 513e0
+	push de
+	push hl
+	push bc
+	ld a, [wd265]
+	dec a
+	call AddNTimes
+	push hl
+	add hl, bc
+	ld d, h
+	ld e, l
+	pop hl
+.loop
+	push bc
+	ld a, [wd265]
+	ld b, a
+	ld a, [wCurPartyMon]
+	cp b
+	pop bc
+	jr z, .insert
+	push hl
+	push de
+	push bc
+	call CopyBytes
+	pop bc
+	pop de
+	pop hl
+	push hl
+	ld a, l
+	sub c
+	ld l, a
+	ld a, h
+	sbc b
+	ld h, a
+	pop de
+	ld a, [wd265]
+	dec a
+	ld [wd265], a
+	jr .loop
+
+.insert
+	pop bc
+	pop hl
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld d, h
+	ld e, l
+	pop hl
+	call CopyBytes
+	ret
--- /dev/null
+++ b/engine/pokemon/party_menu.asm
@@ -1,0 +1,932 @@
+SelectMonFromParty: ; 50000
+	call DisableSpriteUpdates
+	xor a
+	ld [wPartyMenuActionText], a
+	call ClearBGPalettes
+	call InitPartyMenuLayout
+	call WaitBGMap
+	call SetPalettes
+	call DelayFrame
+	call PartyMenuSelect
+	call ReturnToMapWithSpeechTextbox
+	ret
+; 5001d
+
+
+SelectTradeOrDayCareMon: ; 5001d
+	ld a, b
+	ld [wPartyMenuActionText], a
+	call DisableSpriteUpdates
+	call ClearBGPalettes
+	call InitPartyMenuLayout
+	call WaitBGMap
+	ld b, SCGB_PARTY_MENU
+	call GetSGBLayout
+	call SetPalettes
+	call DelayFrame
+	call PartyMenuSelect
+	call ReturnToMapWithSpeechTextbox
+	ret
+; 5003f
+
+InitPartyMenuLayout: ; 5003f
+	call LoadPartyMenuGFX
+	call InitPartyMenuWithCancel
+	call InitPartyMenuGFX
+	call WritePartyMenuTilemap
+	call PrintPartyMenuText
+	ret
+; 5004f
+
+LoadPartyMenuGFX: ; 5004f
+	call LoadFontsBattleExtra
+	callfar InitPartyMenuPalettes ; engine/color.asm
+	callfar ClearSpriteAnims2
+	ret
+; 5005f
+
+
+WritePartyMenuTilemap: ; 0x5005f
+	ld hl, wOptions
+	ld a, [hl]
+	push af
+	set NO_TEXT_SCROLL, [hl]
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, " "
+	call ByteFill ; blank the tilemap
+	call GetPartyMenuQualityIndexes
+.loop
+	ld a, [hli]
+	cp -1
+	jr z, .end
+	push hl
+	ld hl, .Jumptable
+	rst JumpTable
+	pop hl
+	jr .loop
+.end
+	pop af
+	ld [wOptions], a
+	ret
+; 0x50089
+
+.Jumptable: ; 50089
+; entries correspond to PARTYMENUQUALITY_* constants
+	dw PlacePartyNicknames
+	dw PlacePartyHPBar
+	dw PlacePartyMenuHPDigits
+	dw PlacePartyMonLevel
+	dw PlacePartyMonStatus
+	dw PlacePartyMonTMHMCompatibility
+	dw PlacePartyMonEvoStoneCompatibility
+	dw PlacePartyMonGender
+	dw PlacePartyMonMobileBattleSelection
+; 5009b
+
+PlacePartyNicknames: ; 5009b
+	hlcoord 3, 1
+	ld a, [wPartyCount]
+	and a
+	jr z, .end
+	ld c, a
+	ld b, $0
+.loop
+	push bc
+	push hl
+	push hl
+	ld hl, wPartyMonNicknames
+	ld a, b
+	call GetNick
+	pop hl
+	call PlaceString
+	pop hl
+	ld de, 2 * SCREEN_WIDTH
+	add hl, de
+	pop bc
+	inc b
+	dec c
+	jr nz, .loop
+
+.end
+	dec hl
+	dec hl
+	ld de, .CANCEL
+	call PlaceString
+	ret
+; 500c8
+
+.CANCEL: ; 500c8
+	db "CANCEL@"
+; 500cf
+
+
+PlacePartyHPBar: ; 500cf
+	xor a
+	ld [wSGBPals], a
+	ld a, [wPartyCount]
+	and a
+	ret z
+	ld c, a
+	ld b, $0
+	hlcoord 11, 2
+.loop
+	push bc
+	push hl
+	call PartyMenuCheckEgg
+	jr z, .skip
+	push hl
+	call PlacePartymonHPBar
+	pop hl
+	ld d, $6
+	ld b, $0
+	call DrawBattleHPBar
+	ld hl, wHPPals
+	ld a, [wSGBPals]
+	ld c, a
+	ld b, $0
+	add hl, bc
+	call SetHPPal
+	ld b, SCGB_PARTY_MENU_HP_PALS
+	call GetSGBLayout
+.skip
+	ld hl, wSGBPals
+	inc [hl]
+	pop hl
+	ld de, 2 * SCREEN_WIDTH
+	add hl, de
+	pop bc
+	inc b
+	dec c
+	jr nz, .loop
+	ld b, SCGB_PARTY_MENU
+	call GetSGBLayout
+	ret
+; 50117
+
+PlacePartymonHPBar: ; 50117
+	ld a, b
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld hl, wPartyMon1HP
+	call AddNTimes
+	ld a, [hli]
+	or [hl]
+	jr nz, .not_fainted
+	xor a
+	ld e, a
+	ld c, a
+	ret
+
+.not_fainted
+	dec hl
+	ld a, [hli]
+	ld b, a
+	ld a, [hli]
+	ld c, a
+	ld a, [hli]
+	ld d, a
+	ld a, [hli]
+	ld e, a
+	predef ComputeHPBarPixels
+	ret
+; 50138
+
+PlacePartyMenuHPDigits: ; 50138
+	ld a, [wPartyCount]
+	and a
+	ret z
+	ld c, a
+	ld b, $0
+	hlcoord 13, 1
+.loop
+	push bc
+	push hl
+	call PartyMenuCheckEgg
+	jr z, .next
+	push hl
+	ld a, b
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld hl, wPartyMon1HP
+	call AddNTimes
+	ld e, l
+	ld d, h
+	pop hl
+	push de
+	lb bc, 2, 3
+	call PrintNum
+	pop de
+	ld a, "/"
+	ld [hli], a
+	inc de
+	inc de
+	lb bc, 2, 3
+	call PrintNum
+
+.next
+	pop hl
+	ld de, 2 * SCREEN_WIDTH
+	add hl, de
+	pop bc
+	inc b
+	dec c
+	jr nz, .loop
+	ret
+; 50176
+
+PlacePartyMonLevel: ; 50176
+	ld a, [wPartyCount]
+	and a
+	ret z
+	ld c, a
+	ld b, 0
+	hlcoord 8, 2
+.loop
+	push bc
+	push hl
+	call PartyMenuCheckEgg
+	jr z, .next
+	push hl
+	ld a, b
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld hl, wPartyMon1Level
+	call AddNTimes
+	ld e, l
+	ld d, h
+	pop hl
+	ld a, [de]
+	cp 100 ; This is distinct from MAX_LEVEL.
+	jr nc, .ThreeDigits
+	ld a, "<LV>"
+	ld [hli], a
+	lb bc, PRINTNUM_RIGHTALIGN | 1, 2
+	; jr .okay
+.ThreeDigits:
+	lb bc, PRINTNUM_RIGHTALIGN | 1, 3
+; .okay
+	call PrintNum
+
+.next
+	pop hl
+	ld de, SCREEN_WIDTH * 2
+	add hl, de
+	pop bc
+	inc b
+	dec c
+	jr nz, .loop
+	ret
+; 501b2
+
+PlacePartyMonStatus: ; 501b2
+	ld a, [wPartyCount]
+	and a
+	ret z
+	ld c, a
+	ld b, 0
+	hlcoord 5, 2
+.loop
+	push bc
+	push hl
+	call PartyMenuCheckEgg
+	jr z, .next
+	push hl
+	ld a, b
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld hl, wPartyMon1Status
+	call AddNTimes
+	ld e, l
+	ld d, h
+	pop hl
+	call PlaceStatusString
+
+.next
+	pop hl
+	ld de, SCREEN_WIDTH * 2
+	add hl, de
+	pop bc
+	inc b
+	dec c
+	jr nz, .loop
+	ret
+; 501e0
+
+PlacePartyMonTMHMCompatibility: ; 501e0
+	ld a, [wPartyCount]
+	and a
+	ret z
+	ld c, a
+	ld b, 0
+	hlcoord 12, 2
+.loop
+	push bc
+	push hl
+	call PartyMenuCheckEgg
+	jr z, .next
+	push hl
+	ld hl, wPartySpecies
+	ld e, b
+	ld d, 0
+	add hl, de
+	ld a, [hl]
+	ld [wCurPartySpecies], a
+	predef CanLearnTMHMMove
+	pop hl
+	call .PlaceAbleNotAble
+	call PlaceString
+
+.next
+	pop hl
+	ld de, SCREEN_WIDTH * 2
+	add hl, de
+	pop bc
+	inc b
+	dec c
+	jr nz, .loop
+	ret
+; 50215
+
+.PlaceAbleNotAble: ; 50215
+	ld a, c
+	and a
+	jr nz, .able
+	ld de, .string_not_able
+	ret
+
+.able
+	ld de, .string_able
+	ret
+; 50221
+
+.string_able ; 50221
+	db "ABLE@"
+; 50226
+
+.string_not_able ; 50226
+	db "NOT ABLE@"
+; 5022f
+
+
+PlacePartyMonEvoStoneCompatibility: ; 5022f
+	ld a, [wPartyCount]
+	and a
+	ret z
+	ld c, a
+	ld b, 0
+	hlcoord 12, 2
+.loop
+	push bc
+	push hl
+	call PartyMenuCheckEgg
+	jr z, .next
+	push hl
+	ld a, b
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld hl, wPartyMon1Species
+	call AddNTimes
+	ld a, [hl]
+	dec a
+	ld e, a
+	ld d, 0
+	ld hl, EvosAttacksPointers
+	add hl, de
+	add hl, de
+	call .DetermineCompatibility
+	pop hl
+	call PlaceString
+
+.next
+	pop hl
+	ld de, 2 * SCREEN_WIDTH
+	add hl, de
+	pop bc
+	inc b
+	dec c
+	jr nz, .loop
+	ret
+; 50268
+
+.DetermineCompatibility: ; 50268
+	ld de, wStringBuffer1
+	ld a, BANK(EvosAttacksPointers)
+	ld bc, 2
+	call FarCopyBytes
+	ld hl, wStringBuffer1
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, wStringBuffer1
+	ld a, BANK(EvosAttacks)
+	ld bc, 10
+	call FarCopyBytes
+	ld hl, wStringBuffer1
+.loop2
+	ld a, [hli]
+	and a
+	jr z, .nope
+	inc hl
+	inc hl
+	cp EVOLVE_ITEM
+	jr nz, .loop2
+	dec hl
+	dec hl
+	ld a, [wCurItem]
+	cp [hl]
+	inc hl
+	inc hl
+	jr nz, .loop2
+	ld de, .string_able
+	ret
+
+.nope
+	ld de, .string_not_able
+	ret
+; 502a3
+
+.string_able ; 502a3
+	db "ABLE@"
+; 502a8
+.string_not_able ; 502a8
+	db "NOT ABLE@"
+; 502b1
+
+
+PlacePartyMonGender: ; 502b1
+	ld a, [wPartyCount]
+	and a
+	ret z
+	ld c, a
+	ld b, 0
+	hlcoord 12, 2
+.loop
+	push bc
+	push hl
+	call PartyMenuCheckEgg
+	jr z, .next
+	ld [wCurPartySpecies], a
+	push hl
+	ld a, b
+	ld [wCurPartyMon], a
+	xor a
+	ld [wMonType], a
+	call GetGender
+	ld de, .unknown
+	jr c, .got_gender
+	ld de, .male
+	jr nz, .got_gender
+	ld de, .female
+
+.got_gender
+	pop hl
+	call PlaceString
+
+.next
+	pop hl
+	ld de, 2 * SCREEN_WIDTH
+	add hl, de
+	pop bc
+	inc b
+	dec c
+	jr nz, .loop
+	ret
+; 502ee
+
+.male ; 502ee
+	db "♂…MALE@"
+; 502f5
+
+.female ; 502f5
+	db "♀…FEMALE@"
+; 502fe
+
+.unknown ; 502fe
+	db "…UNKNOWN@"
+; 50307
+
+
+PlacePartyMonMobileBattleSelection: ; 50307
+	ld a, [wPartyCount]
+	and a
+	ret z
+	ld c, a
+	ld b, 0
+	hlcoord 12, 1
+.loop
+	push bc
+	push hl
+	ld de, .String_Sanka_Shinai
+	call PlaceString
+	pop hl
+	ld de, 2 * SCREEN_WIDTH
+	add hl, de
+	pop bc
+	inc b
+	dec c
+	jr nz, .loop
+	ld a, l
+	ld e, MON_NAME_LENGTH
+	sub e
+	ld l, a
+	ld a, h
+	sbc $0
+	ld h, a
+	ld de, .String_Kettei_Yameru
+	call PlaceString
+	ld b, $3
+	ld c, $0
+	ld hl, wd002
+	ld a, [hl]
+.loop2
+	push hl
+	push bc
+	hlcoord 12, 1
+.loop3
+	and a
+	jr z, .done
+	ld de, 2 * SCREEN_WIDTH
+	add hl, de
+	dec a
+	jr .loop3
+
+.done
+	ld de, .String_Banme
+	push hl
+	call PlaceString
+	pop hl
+	pop bc
+	push bc
+	push hl
+	ld a, c
+	ld hl, .Strings_1_2_3
+	call GetNthString
+	ld d, h
+	ld e, l
+	pop hl
+	call PlaceString
+	pop bc
+	pop hl
+	inc hl
+	ld a, [hl]
+	inc c
+	dec b
+	ret z
+	jr .loop2
+; 5036b
+
+.String_Banme: ; 5036b
+	db " ばんめ  @" ; Place
+; 50372
+.String_Sanka_Shinai: ; 50372
+	db "さんかしない@" ; Cancel
+; 50379
+.String_Kettei_Yameru: ; 50379
+	db "けってい  やめる@" ; Quit
+; 50383
+.Strings_1_2_3: ; 50383
+	db "1@", "2@", "3@" ; 1st, 2nd, 3rd
+; 50389
+
+
+PartyMenuCheckEgg: ; 50389
+	ld a, LOW(wPartySpecies)
+	add b
+	ld e, a
+	ld a, HIGH(wPartySpecies)
+	adc 0
+	ld d, a
+	ld a, [de]
+	cp EGG
+	ret
+; 50396
+
+GetPartyMenuQualityIndexes: ; 50396
+	ld a, [wPartyMenuActionText]
+	and $f0
+	jr nz, .skip
+	ld a, [wPartyMenuActionText]
+	and $f
+	ld e, a
+	ld d, 0
+	ld hl, PartyMenuQualityPointers
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ret
+
+.skip
+	ld hl, PartyMenuQualityPointers.Default
+	ret
+; 503b2
+
+INCLUDE "data/party_menu_qualities.asm"
+
+
+InitPartyMenuGFX: ; 503e0
+	ld hl, wPartyCount
+	ld a, [hli]
+	and a
+	ret z
+	ld c, a
+	xor a
+	ld [hObjectStructIndexBuffer], a
+.loop
+	push bc
+	push hl
+	ld hl, LoadMenuMonIcon
+	ld a, BANK(LoadMenuMonIcon)
+	ld e, $0
+	rst FarCall
+	ld a, [hObjectStructIndexBuffer]
+	inc a
+	ld [hObjectStructIndexBuffer], a
+	pop hl
+	pop bc
+	dec c
+	jr nz, .loop
+	callfar PlaySpriteAnimations
+	ret
+; 50405
+
+InitPartyMenuWithCancel: ; 50405
+; with cancel
+	xor a
+	ld [wSwitchMon], a
+	ld de, PartyMenuAttributes
+	call SetMenuAttributes
+	ld a, [wPartyCount]
+	inc a
+	ld [w2DMenuNumRows], a ; list length
+	dec a
+	ld b, a
+	ld a, [wPartyMenuCursor]
+	and a
+	jr z, .skip
+	inc b
+	cp b
+	jr c, .done
+
+.skip
+	ld a, 1
+
+.done
+	ld [wMenuCursorY], a
+	ld a, A_BUTTON | B_BUTTON
+	ld [wMenuJoypadFilter], a
+	ret
+; 5042d
+
+InitPartyMenuNoCancel: ; 0x5042d
+; no cancel
+	ld de, PartyMenuAttributes
+	call SetMenuAttributes
+	ld a, [wPartyCount]
+	ld [w2DMenuNumRows], a ; list length
+	ld b, a
+	ld a, [wPartyMenuCursor]
+	and a
+	jr z, .skip
+	inc b
+	cp b
+	jr c, .done
+.skip
+	ld a, 1
+.done
+	ld [wMenuCursorY], a
+	ld a, A_BUTTON | B_BUTTON
+	ld [wMenuJoypadFilter], a
+	ret
+; 5044f (14:444f)
+
+PartyMenuAttributes: ; 5044f
+; cursor y
+; cursor x
+; num rows
+; num cols
+; bit 6: animate sprites  bit 5: wrap around
+; ?
+; distance between items (hi: y, lo: x)
+; allowed buttons (mask)
+	db 1, 0
+	db 0, 1
+	db $60, $00
+	dn 2, 0
+	db 0
+; 50457
+
+PartyMenuSelect: ; 0x50457
+; sets carry if exitted menu.
+	call StaticMenuJoypad
+	call PlaceHollowCursor
+	ld a, [wPartyCount]
+	inc a
+	ld b, a
+	ld a, [wMenuCursorY] ; menu selection?
+	cp b
+	jr z, .exitmenu ; CANCEL
+	ld [wPartyMenuCursor], a
+	ld a, [hJoyLast]
+	ld b, a
+	bit B_BUTTON_F, b
+	jr nz, .exitmenu ; B button
+	ld a, [wMenuCursorY]
+	dec a
+	ld [wCurPartyMon], a
+	ld c, a
+	ld b, $0
+	ld hl, wPartySpecies
+	add hl, bc
+	ld a, [hl]
+	ld [wCurPartySpecies], a
+
+	ld de, SFX_READ_TEXT_2
+	call PlaySFX
+	call WaitSFX
+	and a
+	ret
+
+.exitmenu
+	ld de, SFX_READ_TEXT_2
+	call PlaySFX
+	call WaitSFX
+	scf
+	ret
+; 0x5049a
+
+
+PrintPartyMenuText: ; 5049a
+	hlcoord 0, 14
+	lb bc, 2, 18
+	call TextBox
+	ld a, [wPartyCount]
+	and a
+	jr nz, .haspokemon
+	ld de, YouHaveNoPKMNString
+	jr .gotstring
+.haspokemon ; 504ae
+	ld a, [wPartyMenuActionText]
+	and $f ; drop high nibble
+	ld hl, PartyMenuStrings
+	ld e, a
+	ld d, $0
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+.gotstring ; 504be
+	ld a, [wOptions]
+	push af
+	set 4, a ; disable text delay
+	ld [wOptions], a
+	hlcoord 1, 16 ; Coord
+	call PlaceString
+	pop af
+	ld [wOptions], a
+	ret
+; 0x504d2
+
+PartyMenuStrings: ; 0x504d2
+	dw ChooseAMonString
+	dw UseOnWhichPKMNString
+	dw WhichPKMNString
+	dw TeachWhichPKMNString
+	dw MoveToWhereString
+	dw UseOnWhichPKMNString
+	dw ChooseAMonString ; Probably used to be ChooseAFemalePKMNString
+	dw ChooseAMonString ; Probably used to be ChooseAMalePKMNString
+	dw ToWhichPKMNString
+
+ChooseAMonString: ; 0x504e4
+	db "Choose a #MON.@"
+
+UseOnWhichPKMNString: ; 0x504f3
+	db "Use on which <PK><MN>?@"
+
+WhichPKMNString: ; 0x50504
+	db "Which <PK><MN>?@"
+
+TeachWhichPKMNString: ; 0x5050e
+	db "Teach which <PK><MN>?@"
+
+MoveToWhereString: ; 0x5051e
+	db "Move to where?@"
+
+ChooseAFemalePKMNString: ; 0x5052d
+; unused
+	db "Choose a ♀<PK><MN>.@"
+
+ChooseAMalePKMNString: ; 0x5053b
+; unused
+	db "Choose a ♂<PK><MN>.@"
+
+ToWhichPKMNString: ; 0x50549
+	db "To which <PK><MN>?@"
+
+YouHaveNoPKMNString: ; 0x50556
+	db "You have no <PK><MN>!@"
+
+PrintPartyMenuActionText: ; 50566
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMonNicknames
+	call GetNick
+	ld a, [wPartyMenuActionText]
+	and $f
+	ld hl, .MenuActionTexts
+	call .PrintText
+	ret
+; 5057b
+
+.MenuActionTexts: ; 5057b
+; entries correspond to PARTYMENUTEXT_* constants
+	dw .Text_CuredOfPoison
+	dw .Text_BurnWasHealed
+	dw .Text_Defrosted
+	dw .Text_WokeUp
+	dw .Text_RidOfParalysis
+	dw .Text_RecoveredSomeHP
+	dw .Text_HealthReturned
+	dw .Text_Revitalized
+	dw .Text_GrewToLevel
+	dw .Text_CameToItsSenses
+; 5058f
+
+.Text_RecoveredSomeHP: ; 0x5058f
+	; recovered @ HP!
+	text_jump UnknownText_0x1bc0a2
+	db "@"
+; 0x50594
+
+.Text_CuredOfPoison: ; 0x50594
+	; 's cured of poison.
+	text_jump UnknownText_0x1bc0bb
+	db "@"
+; 0x50599
+
+.Text_RidOfParalysis: ; 0x50599
+	; 's rid of paralysis.
+	text_jump UnknownText_0x1bc0d2
+	db "@"
+; 0x5059e
+
+.Text_BurnWasHealed: ; 0x5059e
+	; 's burn was healed.
+	text_jump UnknownText_0x1bc0ea
+	db "@"
+; 0x505a3
+
+.Text_Defrosted: ; 0x505a3
+	; was defrosted.
+	text_jump UnknownText_0x1bc101
+	db "@"
+; 0x505a8
+
+.Text_WokeUp: ; 0x505a8
+	; woke up.
+	text_jump UnknownText_0x1bc115
+	db "@"
+; 0x505ad
+
+.Text_HealthReturned: ; 0x505ad
+	; 's health returned.
+	text_jump UnknownText_0x1bc123
+	db "@"
+; 0x505b2
+
+.Text_Revitalized: ; 0x505b2
+	; is revitalized.
+	text_jump UnknownText_0x1bc13a
+	db "@"
+; 0x505b7
+
+.Text_GrewToLevel: ; 0x505b7
+	; grew to level @ !@ @
+	text_jump UnknownText_0x1bc14f
+	db "@"
+; 0x505bc
+
+.Text_CameToItsSenses: ; 0x505bc
+	; came to its senses.
+	text_jump UnknownText_0x1bc16e
+	db "@"
+; 0x505c1
+
+
+.PrintText: ; 505c1
+	ld e, a
+	ld d, 0
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [wOptions]
+	push af
+	set NO_TEXT_SCROLL, a
+	ld [wOptions], a
+	call PrintText
+	pop af
+	ld [wOptions], a
+	ret
+; 505da
--- /dev/null
+++ b/engine/pokemon/search.asm
@@ -1,0 +1,276 @@
+BeastsCheck: ; 0x4a6e8
+; Check if the player owns all three legendary beasts.
+; They must exist in either party or PC, and have the player's OT and ID.
+; Return the result in wScriptVar.
+
+	ld a, RAIKOU
+	ld [wScriptVar], a
+	call CheckOwnMonAnywhere
+	jr nc, .notexist
+
+	ld a, ENTEI
+	ld [wScriptVar], a
+	call CheckOwnMonAnywhere
+	jr nc, .notexist
+
+	ld a, SUICUNE
+	ld [wScriptVar], a
+	call CheckOwnMonAnywhere
+	jr nc, .notexist
+
+	; they exist
+	ld a, 1
+	ld [wScriptVar], a
+	ret
+
+.notexist
+	xor a
+	ld [wScriptVar], a
+	ret
+
+
+MonCheck: ; 0x4a711
+; Check if the player owns any Pokémon of the species in wScriptVar.
+; Return the result in wScriptVar.
+
+	call CheckOwnMonAnywhere
+	jr c, .exists
+
+	; doesn't exist
+	xor a
+	ld [wScriptVar], a
+	ret
+
+.exists
+	ld a, 1
+	ld [wScriptVar], a
+	ret
+
+
+CheckOwnMonAnywhere: ; 0x4a721
+; Check if the player owns any monsters of the species in wScriptVar.
+; It must exist in either party or PC, and have the player's OT and ID.
+
+	; If there are no monsters in the party,
+	; the player must not own any yet.
+	ld a, [wPartyCount]
+	and a
+	ret z
+
+	ld d, a
+	ld e, 0
+	ld hl, wPartyMon1Species
+	ld bc, wPartyMonOT
+
+	; Run CheckOwnMon on each Pokémon in the party.
+.partymon
+	call CheckOwnMon
+	ret c ; found!
+
+	push bc
+	ld bc, PARTYMON_STRUCT_LENGTH
+	add hl, bc
+	pop bc
+	call UpdateOTPointer
+	dec d
+	jr nz, .partymon
+
+	; Run CheckOwnMon on each Pokémon in the PC.
+	ld a, BANK(sBoxCount)
+	call GetSRAMBank
+	ld a, [sBoxCount]
+	and a
+	jr z, .boxes
+
+	ld d, a
+	ld hl, sBoxMon1Species
+	ld bc, sBoxMonOT
+.openboxmon
+	call CheckOwnMon
+	jr nc, .loop
+
+	; found!
+	call CloseSRAM
+	ret
+
+.loop
+	push bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	add hl, bc
+	pop bc
+	call UpdateOTPointer
+	dec d
+	jr nz, .openboxmon
+
+	; Run CheckOwnMon on each monster in the other 13 PC boxes.
+.boxes
+	call CloseSRAM
+
+	ld c, 0
+.box
+	; Don't search the current box again.
+	ld a, [wCurBox]
+	and $f
+	cp c
+	jr z, .loopbox
+
+	; Load the box.
+	ld hl, BoxAddressTable1
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	call GetSRAMBank
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+
+	; Number of monsters in the box
+	ld a, [hl]
+	and a
+	jr z, .loopbox
+
+	push bc
+
+	push hl
+	ld de, sBoxMons - sBoxCount
+	add hl, de
+	ld d, h
+	ld e, l
+	pop hl
+	push de
+	ld de, sBoxMonOT - sBoxCount
+	add hl, de
+	ld b, h
+	ld c, l
+	pop hl
+
+	ld d, a
+
+.boxmon
+	call CheckOwnMon
+	jr nc, .loopboxmon
+
+	; found!
+	pop bc
+	call CloseSRAM
+	ret
+
+.loopboxmon
+	push bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	add hl, bc
+	pop bc
+	call UpdateOTPointer
+	dec d
+	jr nz, .boxmon
+	pop bc
+
+.loopbox
+	inc c
+	ld a, c
+	cp NUM_BOXES
+	jr c, .box
+
+	; not found
+	call CloseSRAM
+	and a
+	ret
+
+
+CheckOwnMon: ; 0x4a7ba
+; Check if a Pokémon belongs to the player and is of a specific species.
+
+; inputs:
+; hl, pointer to PartyMonNSpecies
+; bc, pointer to PartyMonNOT
+; wScriptVar should contain the species we're looking for
+
+; outputs:
+; sets carry if monster matches species, ID, and OT name.
+
+	push bc
+	push hl
+	push de
+	ld d, b
+	ld e, c
+
+; check species
+	ld a, [wScriptVar] ; species we're looking for
+	ld b, [hl] ; species we have
+	cp b
+	jr nz, .notfound ; species doesn't match
+
+; check ID number
+	ld bc, MON_ID
+	add hl, bc ; now hl points to ID number
+	ld a, [wPlayerID]
+	cp [hl]
+	jr nz, .notfound ; ID doesn't match
+	inc hl
+	ld a, [wPlayerID + 1]
+	cp [hl]
+	jr nz, .notfound ; ID doesn't match
+
+; check OT
+; This only checks five characters, which is fine for the Japanese version,
+; but in the English version the player name is 7 characters, so this is wrong.
+
+	ld hl, wPlayerName
+
+rept NAME_LENGTH_JAPANESE + -2 ; should be PLAYER_NAME_LENGTH + -2
+	ld a, [de]
+	cp [hl]
+	jr nz, .notfound
+	cp "@"
+	jr z, .found ; reached end of string
+	inc hl
+	inc de
+endr
+
+	ld a, [de]
+	cp [hl]
+	jr z, .found
+
+.notfound
+	pop de
+	pop hl
+	pop bc
+	and a
+	ret
+
+.found
+	pop de
+	pop hl
+	pop bc
+	scf
+	ret
+; 0x4a810
+
+BoxAddressTable1: ; 4a810
+	dba sBox1
+	dba sBox2
+	dba sBox3
+	dba sBox4
+	dba sBox5
+	dba sBox6
+	dba sBox7
+	dba sBox8
+	dba sBox9
+	dba sBox10
+	dba sBox11
+	dba sBox12
+	dba sBox13
+	dba sBox14
+; 4a83a
+
+UpdateOTPointer: ; 0x4a83a
+	push hl
+	ld hl, NAME_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	pop hl
+	ret
+; 0x4a843
--- /dev/null
+++ b/engine/pokemon/search2.asm
@@ -1,0 +1,134 @@
+_FindPartyMonAboveLevel: ; 4dbd2
+	ld hl, wPartyMon1Level
+	call FindAboveLevel
+	ret
+
+_FindPartyMonAtLeastThatHappy: ; 4dbd9
+	ld hl, wPartyMon1Happiness
+	call FindAtLeastThatHappy
+	ret
+
+_FindPartyMonThatSpecies: ; 4dbe0
+	ld hl, wPartyMon1Species
+	jp FindThatSpecies
+
+_FindPartyMonThatSpeciesYourTrainerID: ; 4dbe6
+	ld hl, wPartyMon1Species
+	call FindThatSpecies
+	ret z
+	ld a, c
+	ld hl, wPartyMon1ID
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [wPlayerID]
+	cp [hl]
+	jr nz, .nope
+	inc hl
+	ld a, [wPlayerID + 1]
+	cp [hl]
+	jr nz, .nope
+	ld a, $1
+	and a
+	ret
+
+.nope
+	xor a
+	ret
+
+FindAtLeastThatHappy: ; 4dc0a
+; Sets the bits for the Pokemon that have a happiness greater than or equal to b.
+; The lowest bits are used.  Sets z if no Pokemon in your party is at least that happy.
+	ld c, $0
+	ld a, [wPartyCount]
+	ld d, a
+.loop
+	ld a, d
+	dec a
+	push hl
+	push bc
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	pop bc
+	ld a, b
+	cp [hl]
+	pop hl
+	jr z, .greater_equal
+	jr nc, .lower
+
+.greater_equal
+	ld a, c
+	or $1
+	ld c, a
+
+.lower
+	sla c
+	dec d
+	jr nz, .loop
+	call RetroactivelyIgnoreEggs
+	ld a, c
+	and a
+	ret
+
+FindAboveLevel: ; 4dc31
+	ld c, $0
+	ld a, [wPartyCount]
+	ld d, a
+.loop
+	ld a, d
+	dec a
+	push hl
+	push bc
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	pop bc
+	ld a, b
+	cp [hl]
+	pop hl
+	jr c, .greater
+	ld a, c
+	or $1
+	ld c, a
+
+.greater
+	sla c
+	dec d
+	jr nz, .loop
+	call RetroactivelyIgnoreEggs
+	ld a, c
+	and a
+	ret
+
+FindThatSpecies: ; 4dc56
+; Find species b in your party.
+; If you have no Pokemon, returns c = -1 and z.
+; If that species is in your party, returns its location in c, and nz.
+; Otherwise, returns z.
+	ld c, -1
+	ld hl, wPartySpecies
+.loop
+	ld a, [hli]
+	cp -1
+	ret z
+	inc c
+	cp b
+	jr nz, .loop
+	ld a, $1
+	and a
+	ret
+
+RetroactivelyIgnoreEggs: ; 4dc67
+	ld e, -2
+	ld hl, wPartySpecies
+.loop
+	ld a, [hli]
+	cp -1
+	ret z
+	cp EGG
+	jr nz, .skip_notegg
+	ld a, c
+	and e
+	ld c, a
+
+.skip_notegg
+	rlc e
+	jr .loop
--- /dev/null
+++ b/engine/pokemon/stats_screen.asm
@@ -1,0 +1,1173 @@
+	const_def 1
+	const PINK_PAGE  ; 1
+	const GREEN_PAGE ; 2
+	const BLUE_PAGE  ; 3
+NUM_STAT_PAGES EQU const_value + -1
+
+BattleStatsScreenInit: ; 4dc7b (13:5c7b)
+	ld a, [wLinkMode]
+	cp LINK_MOBILE
+	jr nz, StatsScreenInit
+
+	ld a, [wBattleMode]
+	and a
+	jr z, StatsScreenInit
+	jr _MobileStatsScreenInit
+
+StatsScreenInit: ; 4dc8a
+	ld hl, StatsScreenMain
+	jr StatsScreenInit_gotaddress
+
+_MobileStatsScreenInit: ; 4dc8f
+	ld hl, StatsScreenMobile
+	jr StatsScreenInit_gotaddress
+
+StatsScreenInit_gotaddress: ; 4dc94
+	ld a, [hMapAnims]
+	push af
+	xor a
+	ld [hMapAnims], a ; disable overworld tile animations
+	ld a, [wBoxAlignment] ; whether sprite is to be mirrorred
+	push af
+	ld a, [wJumptableIndex]
+	ld b, a
+	ld a, [wcf64]
+	ld c, a
+
+	push bc
+	push hl
+	call ClearBGPalettes
+	call ClearTileMap
+	call UpdateSprites
+	farcall StatsScreen_LoadFont
+	pop hl
+	call _hl_
+	call ClearBGPalettes
+	call ClearTileMap
+	pop bc
+
+	; restore old values
+	ld a, b
+	ld [wJumptableIndex], a
+	ld a, c
+	ld [wcf64], a
+	pop af
+	ld [wBoxAlignment], a
+	pop af
+	ld [hMapAnims], a
+	ret
+; 0x4dcd2
+
+StatsScreenMain: ; 0x4dcd2
+	xor a
+	ld [wJumptableIndex], a
+	; stupid interns
+	ld [wcf64], a
+	ld a, [wcf64]
+	and %11111100
+	or 1
+	ld [wcf64], a
+.loop ; 4dce3
+	ld a, [wJumptableIndex]
+	and $ff ^ (1 << 7)
+	ld hl, StatsScreenPointerTable
+	rst JumpTable
+	call StatsScreen_WaitAnim ; check for keys?
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr z, .loop
+	ret
+; 0x4dcf7
+
+StatsScreenMobile: ; 4dcf7
+	xor a
+	ld [wJumptableIndex], a
+	; stupid interns
+	ld [wcf64], a
+	ld a, [wcf64]
+	and %11111100
+	or 1
+	ld [wcf64], a
+.loop
+	farcall Mobile_SetOverworldDelay
+	ld a, [wJumptableIndex]
+	and $ff ^ (1 << 7)
+	ld hl, StatsScreenPointerTable
+	rst JumpTable
+	call StatsScreen_WaitAnim
+	farcall MobileComms_CheckInactivityTimer
+	jr c, .exit
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr z, .loop
+
+.exit
+	ret
+; 4dd2a
+
+StatsScreenPointerTable: ; 4dd2a
+	dw MonStatsInit       ; regular pokémon
+	dw EggStatsInit       ; egg
+	dw StatsScreenWaitCry
+	dw EggStatsJoypad
+	dw StatsScreen_LoadPage
+	dw StatsScreenWaitCry
+	dw MonStatsJoypad
+	dw StatsScreen_Exit
+; 4dd3a
+
+
+StatsScreen_WaitAnim: ; 4dd3a (13:5d3a)
+	ld hl, wcf64
+	bit 6, [hl]
+	jr nz, .try_anim
+	bit 5, [hl]
+	jr nz, .finish
+	call DelayFrame
+	ret
+
+.try_anim
+	farcall SetUpPokeAnim
+	jr nc, .finish
+	ld hl, wcf64
+	res 6, [hl]
+.finish
+	ld hl, wcf64
+	res 5, [hl]
+	farcall HDMATransferTileMapToWRAMBank3
+	ret
+
+StatsScreen_SetJumptableIndex: ; 4dd62 (13:5d62)
+	ld a, [wJumptableIndex]
+	and $80
+	or h
+	ld [wJumptableIndex], a
+	ret
+
+StatsScreen_Exit: ; 4dd6c (13:5d6c)
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+MonStatsInit: ; 4dd72 (13:5d72)
+	ld hl, wcf64
+	res 6, [hl]
+	call ClearBGPalettes
+	call ClearTileMap
+	farcall HDMATransferTileMapToWRAMBank3
+	call StatsScreen_CopyToTempMon
+	ld a, [wCurPartySpecies]
+	cp EGG
+	jr z, .egg
+	call StatsScreen_InitUpperHalf
+	ld hl, wcf64
+	set 4, [hl]
+	ld h, 4
+	call StatsScreen_SetJumptableIndex
+	ret
+
+.egg
+	ld h, 1
+	call StatsScreen_SetJumptableIndex
+	ret
+
+EggStatsInit: ; 4dda1
+	call EggStatsScreen
+	ld a, [wJumptableIndex]
+	inc a
+	ld [wJumptableIndex], a
+	ret
+; 0x4ddac
+
+
+EggStatsJoypad: ; 4ddac (13:5dac)
+	call StatsScreen_GetJoypad
+	jr nc, .check
+	ld h, 0
+	call StatsScreen_SetJumptableIndex
+	ret
+
+.check
+	bit A_BUTTON_F, a
+	jr nz, .quit
+	and D_DOWN | D_UP | A_BUTTON | B_BUTTON
+	jp StatsScreen_JoypadAction
+
+.quit
+	ld h, 7
+	call StatsScreen_SetJumptableIndex
+	ret
+
+StatsScreen_LoadPage: ; 4ddc6 (13:5dc6)
+	call StatsScreen_LoadGFX
+	ld hl, wcf64
+	res 4, [hl]
+	ld a, [wJumptableIndex]
+	inc a
+	ld [wJumptableIndex], a
+	ret
+
+MonStatsJoypad: ; 4ddd6 (13:5dd6)
+	call StatsScreen_GetJoypad
+	jr nc, .next
+	ld h, 0
+	call StatsScreen_SetJumptableIndex
+	ret
+
+.next
+	and D_DOWN | D_UP | D_LEFT | D_RIGHT | A_BUTTON | B_BUTTON
+	jp StatsScreen_JoypadAction
+
+StatsScreenWaitCry: ; 4dde6 (13:5de6)
+	call IsSFXPlaying
+	ret nc
+	ld a, [wJumptableIndex]
+	inc a
+	ld [wJumptableIndex], a
+	ret
+
+StatsScreen_CopyToTempMon: ; 4ddf2 (13:5df2)
+	ld a, [wMonType]
+	cp TEMPMON
+	jr nz, .breedmon
+	ld a, [wBufferMonSpecies]
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld hl, wBufferMon
+	ld de, wTempMon
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call CopyBytes
+	jr .done
+
+.breedmon
+	farcall CopyMonToTempMon
+	ld a, [wCurPartySpecies]
+	cp EGG
+	jr z, .done
+	ld a, [wMonType]
+	cp BOXMON
+	jr c, .done
+	farcall CalcTempmonStats
+.done
+	and a
+	ret
+
+StatsScreen_GetJoypad: ; 4de2c (13:5e2c)
+	call GetJoypad
+	ld a, [wMonType]
+	cp TEMPMON
+	jr nz, .notbreedmon
+	push hl
+	push de
+	push bc
+	farcall StatsScreenDPad
+	pop bc
+	pop de
+	pop hl
+	ld a, [wMenuJoypad]
+	and D_DOWN | D_UP
+	jr nz, .set_carry
+	ld a, [wMenuJoypad]
+	jr .clear_flags
+
+.notbreedmon
+	ld a, [hJoyPressed]
+.clear_flags
+	and a
+	ret
+
+.set_carry
+	scf
+	ret
+
+StatsScreen_JoypadAction: ; 4de54 (13:5e54)
+	push af
+	ld a, [wcf64]
+	maskbits NUM_STAT_PAGES
+	ld c, a
+	pop af
+	bit B_BUTTON_F, a
+	jp nz, .b_button
+	bit D_LEFT_F, a
+	jr nz, .d_left
+	bit D_RIGHT_F, a
+	jr nz, .d_right
+	bit A_BUTTON_F, a
+	jr nz, .a_button
+	bit D_UP_F, a
+	jr nz, .d_up
+	bit D_DOWN_F, a
+	jr nz, .d_down
+	jr .done
+
+.d_down
+	ld a, [wMonType]
+	cp BOXMON
+	jr nc, .done
+	and a
+	ld a, [wPartyCount]
+	jr z, .next_mon
+	ld a, [wOTPartyCount]
+.next_mon
+	ld b, a
+	ld a, [wCurPartyMon]
+	inc a
+	cp b
+	jr z, .done
+	ld [wCurPartyMon], a
+	ld b, a
+	ld a, [wMonType]
+	and a
+	jr nz, .load_mon
+	ld a, b
+	inc a
+	ld [wPartyMenuCursor], a
+	jr .load_mon
+
+.d_up
+	ld a, [wCurPartyMon]
+	and a
+	jr z, .done
+	dec a
+	ld [wCurPartyMon], a
+	ld b, a
+	ld a, [wMonType]
+	and a
+	jr nz, .load_mon
+	ld a, b
+	inc a
+	ld [wPartyMenuCursor], a
+	jr .load_mon
+
+.a_button
+	ld a, c
+	cp BLUE_PAGE ; last page
+	jr z, .b_button
+.d_right
+	inc c
+	ld a, BLUE_PAGE ; last page
+	cp c
+	jr nc, .set_page
+	ld c, PINK_PAGE ; first page
+	jr .set_page
+
+.d_left
+	dec c
+	jr nz, .set_page
+	ld c, BLUE_PAGE ; last page
+	jr .set_page
+
+.done
+	ret
+
+.set_page
+	ld a, [wcf64]
+	and %11111100
+	or c
+	ld [wcf64], a
+	ld h, 4
+	call StatsScreen_SetJumptableIndex
+	ret
+
+.load_mon
+	ld h, 0
+	call StatsScreen_SetJumptableIndex
+	ret
+
+.b_button ; 4dee4 (13:5ee4)
+	ld h, 7
+	call StatsScreen_SetJumptableIndex
+	ret
+
+StatsScreen_InitUpperHalf: ; 4deea (13:5eea)
+	call .PlaceHPBar
+	xor a
+	ld [hBGMapMode], a
+	ld a, [wBaseDexNo]
+	ld [wd265], a
+	ld [wCurSpecies], a
+	hlcoord 8, 0
+	ld [hl], "№"
+	inc hl
+	ld [hl], "."
+	inc hl
+	hlcoord 10, 0
+	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
+	ld de, wd265
+	call PrintNum
+	hlcoord 14, 0
+	call PrintLevel
+	ld hl, .NicknamePointers
+	call GetNicknamePointer
+	call CopyNickname
+	hlcoord 8, 2
+	call PlaceString
+	hlcoord 18, 0
+	call .PlaceGenderChar
+	hlcoord 9, 4
+	ld a, "/"
+	ld [hli], a
+	ld a, [wBaseDexNo]
+	ld [wd265], a
+	call GetPokemonName
+	call PlaceString
+	call StatsScreen_PlaceHorizontalDivider
+	call StatsScreen_PlacePageSwitchArrows
+	call StatsScreen_PlaceShinyIcon
+	ret
+
+.PlaceHPBar: ; 4df45 (13:5f45)
+	ld hl, wTempMonHP
+	ld a, [hli]
+	ld b, a
+	ld c, [hl]
+	ld hl, wTempMonMaxHP
+	ld a, [hli]
+	ld d, a
+	ld e, [hl]
+	farcall ComputeHPBarPixels
+	ld hl, wCurHPPal
+	call SetHPPal
+	ld b, SCGB_STATS_SCREEN_HP_PALS
+	call GetSGBLayout
+	call DelayFrame
+	ret
+
+.PlaceGenderChar: ; 4df66 (13:5f66)
+	push hl
+	farcall GetGender
+	pop hl
+	ret c
+	ld a, "♂"
+	jr nz, .got_gender
+	ld a, "♀"
+.got_gender
+	ld [hl], a
+	ret
+; 4df77 (13:5f77)
+
+.NicknamePointers: ; 4df77
+	dw wPartyMonNicknames
+	dw wOTPartyMonNicknames
+	dw sBoxMonNicknames
+	dw wBufferMonNick
+; 4df7f
+
+Unreferenced_Function4df7f: ; 4df7f
+	hlcoord 7, 0
+	ld bc, SCREEN_WIDTH
+	ld d, SCREEN_HEIGHT
+.loop
+	ld a, $31 ; vertical divider
+	ld [hl], a
+	add hl, bc
+	dec d
+	jr nz, .loop
+	ret
+; 4df8f
+
+StatsScreen_PlaceHorizontalDivider: ; 4df8f (13:5f8f)
+	hlcoord 0, 7
+	ld b, SCREEN_WIDTH
+	ld a, $62 ; horizontal divider (empty HP/exp bar)
+.loop
+	ld [hli], a
+	dec b
+	jr nz, .loop
+	ret
+
+StatsScreen_PlacePageSwitchArrows: ; 4df9b (13:5f9b)
+	hlcoord 12, 6
+	ld [hl], "◀"
+	hlcoord 19, 6
+	ld [hl], "▶"
+	ret
+
+StatsScreen_PlaceShinyIcon: ; 4dfa6 (13:5fa6)
+	ld bc, wTempMonDVs
+	farcall CheckShininess
+	ret nc
+	hlcoord 19, 0
+	ld [hl], "⁂"
+	ret
+
+StatsScreen_LoadGFX: ; 4dfb6 (13:5fb6)
+	ld a, [wBaseDexNo]
+	ld [wd265], a
+	ld [wCurSpecies], a
+	xor a
+	ld [hBGMapMode], a
+	call .ClearBox
+	call .PageTilemap
+	call .LoadPals
+	ld hl, wcf64
+	bit 4, [hl]
+	jr nz, .place_frontpic
+	call SetPalettes
+	ret
+
+.place_frontpic
+	call StatsScreen_PlaceFrontpic
+	ret
+
+.ClearBox: ; 4dfda (13:5fda)
+	ld a, [wcf64]
+	maskbits NUM_STAT_PAGES
+	ld c, a
+	call StatsScreen_LoadPageIndicators
+	hlcoord 0, 8
+	lb bc, 10, 20
+	call ClearBox
+	ret
+
+.LoadPals: ; 4dfed (13:5fed)
+	ld a, [wcf64]
+	maskbits NUM_STAT_PAGES
+	ld c, a
+	farcall LoadStatsScreenPals
+	call DelayFrame
+	ld hl, wcf64
+	set 5, [hl]
+	ret
+
+.PageTilemap: ; 4e002 (13:6002)
+	ld a, [wcf64]
+	maskbits NUM_STAT_PAGES
+	dec a
+	ld hl, .Jumptable
+	rst JumpTable
+	ret
+
+.Jumptable: ; 4e00d (13:600d)
+; entries correspond to *_PAGE constants
+	dw .PinkPage
+	dw .GreenPage
+	dw .BluePage
+
+.PinkPage: ; 4e013 (13:6013)
+	hlcoord 0, 9
+	ld b, $0
+	predef DrawPlayerHP
+	hlcoord 8, 9
+	ld [hl], $41 ; right HP/exp bar end cap
+	ld de, .Status_Type
+	hlcoord 0, 12
+	call PlaceString
+	ld a, [wTempMonPokerusStatus]
+	ld b, a
+	and $f
+	jr nz, .HasPokerus
+	ld a, b
+	and $f0
+	jr z, .NotImmuneToPkrs
+	hlcoord 8, 8
+	ld [hl], "." ; Pokérus immunity dot
+.NotImmuneToPkrs:
+	ld a, [wMonType]
+	cp BOXMON
+	jr z, .StatusOK
+	hlcoord 6, 13
+	push hl
+	ld de, wTempMonStatus
+	predef PlaceStatusString
+	pop hl
+	jr nz, .done_status
+	jr .StatusOK
+.HasPokerus:
+	ld de, .PkrsStr
+	hlcoord 1, 13
+	call PlaceString
+	jr .done_status
+.StatusOK:
+	ld de, .OK_str
+	call PlaceString
+.done_status
+	hlcoord 1, 15
+	predef PrintMonTypes
+	hlcoord 9, 8
+	ld de, SCREEN_WIDTH
+	ld b, 10
+	ld a, $31 ; vertical divider
+.vertical_divider
+	ld [hl], a
+	add hl, de
+	dec b
+	jr nz, .vertical_divider
+	ld de, .ExpPointStr
+	hlcoord 10, 9
+	call PlaceString
+	hlcoord 17, 14
+	call .PrintNextLevel
+	hlcoord 13, 10
+	lb bc, 3, 7
+	ld de, wTempMonExp
+	call PrintNum
+	call .CalcExpToNextLevel
+	hlcoord 13, 13
+	lb bc, 3, 7
+	ld de, wBuffer1
+	call PrintNum
+	ld de, .LevelUpStr
+	hlcoord 10, 12
+	call PlaceString
+	ld de, .ToStr
+	hlcoord 14, 14
+	call PlaceString
+	hlcoord 11, 16
+	ld a, [wTempMonLevel]
+	ld b, a
+	ld de, wTempMonExp + 2
+	predef FillInExpBar
+	hlcoord 10, 16
+	ld [hl], $40 ; left exp bar end cap
+	hlcoord 19, 16
+	ld [hl], $41 ; right exp bar end cap
+	ret
+
+.PrintNextLevel: ; 4e0d3 (13:60d3)
+	ld a, [wTempMonLevel]
+	push af
+	cp MAX_LEVEL
+	jr z, .AtMaxLevel
+	inc a
+	ld [wTempMonLevel], a
+.AtMaxLevel:
+	call PrintLevel
+	pop af
+	ld [wTempMonLevel], a
+	ret
+
+.CalcExpToNextLevel: ; 4e0e7 (13:60e7)
+	ld a, [wTempMonLevel]
+	cp MAX_LEVEL
+	jr z, .AlreadyAtMaxLevel
+	inc a
+	ld d, a
+	farcall CalcExpAtLevel
+	ld hl, wTempMonExp + 2
+	ld hl, wTempMonExp + 2
+	ld a, [hQuotient + 2]
+	sub [hl]
+	dec hl
+	ld [wBuffer3], a
+	ld a, [hQuotient + 1]
+	sbc [hl]
+	dec hl
+	ld [wBuffer2], a
+	ld a, [hQuotient]
+	sbc [hl]
+	ld [wBuffer1], a
+	ret
+
+.AlreadyAtMaxLevel:
+	ld hl, wBuffer1
+	xor a
+	ld [hli], a
+	ld [hli], a
+	ld [hl], a
+	ret
+; 4e119 (13:6119)
+
+.Status_Type: ; 4e119
+	db   "STATUS/"
+	next "TYPE/@"
+; 4e127
+
+.OK_str: ; 4e127
+	db "OK @"
+; 4e12b
+
+.ExpPointStr: ; 4e12b
+	db "EXP POINTS@"
+; 4e136
+
+.LevelUpStr: ; 4e136
+	db "LEVEL UP@"
+; 4e13f
+
+.ToStr: ; 4e13f
+	db "TO@"
+; 4e142
+
+.PkrsStr: ; 4e142
+	db "#RUS@"
+; 4e147
+
+.GreenPage: ; 4e147 (13:6147)
+	ld de, .Item
+	hlcoord 0, 8
+	call PlaceString
+	call .GetItemName
+	hlcoord 8, 8
+	call PlaceString
+	ld de, .Move
+	hlcoord 0, 10
+	call PlaceString
+	ld hl, wTempMonMoves
+	ld de, wListMoves_MoveIndicesBuffer
+	ld bc, NUM_MOVES
+	call CopyBytes
+	hlcoord 8, 10
+	ld a, SCREEN_WIDTH * 2
+	ld [wBuffer1], a
+	predef ListMoves
+	hlcoord 12, 11
+	ld a, SCREEN_WIDTH * 2
+	ld [wBuffer1], a
+	predef ListMovePP
+	ret
+
+.GetItemName: ; 4e189 (13:6189)
+	ld de, .ThreeDashes
+	ld a, [wTempMonItem]
+	and a
+	ret z
+	ld b, a
+	farcall TimeCapsule_ReplaceTeruSama
+	ld a, b
+	ld [wd265], a
+	call GetItemName
+	ret
+; 4e1a0 (13:61a0)
+
+.Item: ; 4e1a0
+	db "ITEM@"
+; 4e1a5
+
+.ThreeDashes: ; 4e1a5
+	db "---@"
+; 4e1a9
+
+.Move: ; 4e1a9
+	db "MOVE@"
+; 4e1ae
+
+.BluePage: ; 4e1ae (13:61ae)
+	call .PlaceOTInfo
+	hlcoord 10, 8
+	ld de, SCREEN_WIDTH
+	ld b, 10
+	ld a, $31 ; vertical divider
+.BluePageVerticalDivider:
+	ld [hl], a
+	add hl, de
+	dec b
+	jr nz, .BluePageVerticalDivider
+	hlcoord 11, 8
+	ld bc, 6
+	predef PrintTempMonStats
+	ret
+
+.PlaceOTInfo: ; 4e1cc (13:61cc)
+	ld de, IDNoString
+	hlcoord 0, 9
+	call PlaceString
+	ld de, OTString
+	hlcoord 0, 12
+	call PlaceString
+	hlcoord 2, 10
+	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+	ld de, wTempMonID
+	call PrintNum
+	ld hl, .OTNamePointers
+	call GetNicknamePointer
+	call CopyNickname
+	farcall CheckNickErrors
+	hlcoord 2, 13
+	call PlaceString
+	ld a, [wTempMonCaughtGender]
+	and a
+	jr z, .done
+	cp $7f
+	jr z, .done
+	and $80
+	ld a, "♂"
+	jr z, .got_gender
+	ld a, "♀"
+.got_gender
+	hlcoord 9, 13
+	ld [hl], a
+.done
+	ret
+; 4e216 (13:6216)
+
+.OTNamePointers: ; 4e216
+	dw wPartyMonOT
+	dw wOTPartyMonOT
+	dw sBoxMonOT
+	dw wBufferMonOT
+; 4e21e
+
+IDNoString: ; 4e21e
+	db "<ID>№.@"
+
+OTString: ; 4e222
+	db "OT/@"
+; 4e226
+
+
+StatsScreen_PlaceFrontpic: ; 4e226 (13:6226)
+	ld hl, wTempMonDVs
+	predef GetUnownLetter
+	call StatsScreen_GetAnimationParam
+	jr c, .egg
+	and a
+	jr z, .no_cry
+	jr .cry
+
+.egg
+	call .AnimateEgg
+	call SetPalettes
+	ret
+
+.no_cry
+	call .AnimateMon
+	call SetPalettes
+	ret
+
+.cry
+	call SetPalettes
+	call .AnimateMon
+	ld a, [wCurPartySpecies]
+	call PlayMonCry2
+	ret
+
+.AnimateMon: ; 4e253 (13:6253)
+	ld hl, wcf64
+	set 5, [hl]
+	ld a, [wCurPartySpecies]
+	cp UNOWN
+	jr z, .unown
+	hlcoord 0, 0
+	call PrepMonFrontpic
+	ret
+
+.unown
+	xor a
+	ld [wBoxAlignment], a
+	hlcoord 0, 0
+	call _PrepMonFrontpic
+	ret
+
+.AnimateEgg: ; 4e271 (13:6271)
+	ld a, [wCurPartySpecies]
+	cp UNOWN
+	jr z, .unownegg
+	ld a, TRUE
+	ld [wBoxAlignment], a
+	call .get_animation
+	ret
+
+.unownegg
+	xor a
+	ld [wBoxAlignment], a
+	call .get_animation
+	ret
+
+.get_animation ; 4e289 (13:6289)
+	ld a, [wCurPartySpecies]
+	call IsAPokemon
+	ret c
+	call StatsScreen_LoadTextBoxSpaceGFX
+	ld de, vTiles2 tile $00
+	predef GetAnimatedFrontpic
+	hlcoord 0, 0
+	ld d, $0
+	ld e, ANIM_MON_MENU
+	predef LoadMonAnimation
+	ld hl, wcf64
+	set 6, [hl]
+	ret
+
+StatsScreen_GetAnimationParam: ; 4e2ad (13:62ad)
+	ld a, [wMonType]
+	ld hl, .Jumptable
+	rst JumpTable
+	ret
+
+.Jumptable: ; 4e2b5 (13:62b5)
+	dw .PartyMon
+	dw .OTPartyMon
+	dw .BoxMon
+	dw .Tempmon
+	dw .Wildmon
+
+.PartyMon: ; 4e2bf (13:62bf)
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMon1
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld b, h
+	ld c, l
+	jr .CheckEggFaintedFrzSlp
+
+.OTPartyMon: ; 4e2cf (13:62cf)
+	xor a
+	ret
+
+.BoxMon: ; 4e2d1 (13:62d1)
+	ld hl, sBoxMons
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld b, h
+	ld c, l
+	ld a, BANK(sBoxMons)
+	call GetSRAMBank
+	call .CheckEggFaintedFrzSlp
+	push af
+	call CloseSRAM
+	pop af
+	ret
+
+.Tempmon: ; 4e2ed (13:62ed)
+	ld bc, wTempMonSpecies
+	jr .CheckEggFaintedFrzSlp ; utterly pointless
+
+.CheckEggFaintedFrzSlp: ; 4e2f2 (13:62f2)
+	ld a, [wCurPartySpecies]
+	cp EGG
+	jr z, .egg
+	call CheckFaintedFrzSlp
+	jr c, .FaintedFrzSlp
+.egg
+	xor a
+	scf
+	ret
+
+.Wildmon: ; 4e301 (13:6301)
+	ld a, $1
+	and a
+	ret
+
+.FaintedFrzSlp: ; 4e305 (13:6305)
+	xor a
+	ret
+
+StatsScreen_LoadTextBoxSpaceGFX: ; 4e307 (13:6307)
+	nop
+	push hl
+	push de
+	push bc
+	push af
+	call DelayFrame
+	ld a, [rVBK]
+	push af
+	ld a, $1
+	ld [rVBK], a
+	ld de, TextBoxSpaceGFX
+	lb bc, BANK(TextBoxSpaceGFX), 1
+	ld hl, vTiles2 tile " "
+	call Get2bpp
+	pop af
+	ld [rVBK], a
+	pop af
+	pop bc
+	pop de
+	pop hl
+	ret
+; 4e32a (13:632a)
+
+Unreferenced_4e32a: ; 4e32a
+; A blank space tile?
+	ds 16
+; 4e33a
+
+EggStatsScreen: ; 4e33a
+	xor a
+	ld [hBGMapMode], a
+	ld hl, wCurHPPal
+	call SetHPPal
+	ld b, SCGB_STATS_SCREEN_HP_PALS
+	call GetSGBLayout
+	call StatsScreen_PlaceHorizontalDivider
+	ld de, EggString
+	hlcoord 8, 1
+	call PlaceString
+	ld de, IDNoString
+	hlcoord 8, 3
+	call PlaceString
+	ld de, OTString
+	hlcoord 8, 5
+	call PlaceString
+	ld de, FiveQMarkString
+	hlcoord 11, 3
+	call PlaceString
+	ld de, FiveQMarkString
+	hlcoord 11, 5
+	call PlaceString
+	ld a, [wTempMonHappiness] ; egg status
+	ld de, EggSoonString
+	cp $6
+	jr c, .picked
+	ld de, EggCloseString
+	cp $b
+	jr c, .picked
+	ld de, EggMoreTimeString
+	cp $29
+	jr c, .picked
+	ld de, EggALotMoreTimeString
+.picked
+	hlcoord 1, 9
+	call PlaceString
+	ld hl, wcf64
+	set 5, [hl]
+	call SetPalettes ; pals
+	call DelayFrame
+	hlcoord 0, 0
+	call PrepMonFrontpic
+	farcall HDMATransferTileMapToWRAMBank3
+	call StatsScreen_AnimateEgg
+
+	ld a, [wTempMonHappiness]
+	cp 6
+	ret nc
+	ld de, SFX_2_BOOPS
+	call PlaySFX
+	ret
+; 0x4e3c0
+
+EggString: ; 4e3c0
+	db "EGG@"
+
+FiveQMarkString: ; 4e3c4
+	db "?????@"
+
+EggSoonString: ; 0x4e3ca
+	db   "It's making sounds"
+	next "inside. It's going"
+	next "to hatch soon!@"
+
+EggCloseString: ; 0x4e3fd
+	db   "It moves around"
+	next "inside sometimes."
+	next "It must be close"
+	next "to hatching.@"
+
+EggMoreTimeString: ; 0x4e43d
+	db   "Wonder what's"
+	next "inside? It needs"
+	next "more time, though.@"
+
+EggALotMoreTimeString: ; 0x4e46e
+	db   "This EGG needs a"
+	next "lot more time to"
+	next "hatch.@"
+; 0x4e497
+
+
+StatsScreen_AnimateEgg: ; 4e497 (13:6497)
+	call StatsScreen_GetAnimationParam
+	ret nc
+	ld a, [wTempMonHappiness]
+	ld e, $7
+	cp 6
+	jr c, .animate
+	ld e, $8
+	cp 11
+	jr c, .animate
+	ret
+
+.animate
+	push de
+	ld a, $1
+	ld [wBoxAlignment], a
+	call StatsScreen_LoadTextBoxSpaceGFX
+	ld de, vTiles2 tile $00
+	predef GetAnimatedFrontpic
+	pop de
+	hlcoord 0, 0
+	ld d, $0
+	predef LoadMonAnimation
+	ld hl, wcf64
+	set 6, [hl]
+	ret
+
+StatsScreen_LoadPageIndicators: ; 4e4cd (13:64cd)
+	hlcoord 13, 5
+	ld a, $36 ; first of 4 small square tiles
+	call .load_square
+	hlcoord 15, 5
+	ld a, $36 ; " " " "
+	call .load_square
+	hlcoord 17, 5
+	ld a, $36 ; " " " "
+	call .load_square
+	ld a, c
+	cp GREEN_PAGE
+	ld a, $3a ; first of 4 large square tiles
+	hlcoord 13, 5 ; PINK_PAGE (< GREEN_PAGE)
+	jr c, .load_square
+	hlcoord 15, 5 ; GREEN_PAGE (= GREEN_PAGE)
+	jr z, .load_square
+	hlcoord 17, 5 ; BLUE_PAGE (> GREEN_PAGE)
+.load_square ; 4e4f7 (13:64f7)
+	push bc
+	ld [hli], a
+	inc a
+	ld [hld], a
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	inc a
+	ld [hli], a
+	inc a
+	ld [hl], a
+	pop bc
+	ret
+
+CopyNickname: ; 4e505 (13:6505)
+	ld de, wStringBuffer1
+	ld bc, MON_NAME_LENGTH
+	jr .okay ; utterly pointless
+.okay
+	ld a, [wMonType]
+	cp BOXMON
+	jr nz, .partymon
+	ld a, BANK(sBoxMonNicknames)
+	call GetSRAMBank
+	push de
+	call CopyBytes
+	pop de
+	call CloseSRAM
+	ret
+
+.partymon
+	push de
+	call CopyBytes
+	pop de
+	ret
+
+GetNicknamePointer: ; 4e528 (13:6528)
+	ld a, [wMonType]
+	add a
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [wMonType]
+	cp TEMPMON
+	ret z
+	ld a, [wCurPartyMon]
+	jp SkipNames
+
+
+CheckFaintedFrzSlp: ; 4e53f
+	ld hl, MON_HP
+	add hl, bc
+	ld a, [hli]
+	or [hl]
+	jr z, .fainted_frz_slp
+	ld hl, MON_STATUS
+	add hl, bc
+	ld a, [hl]
+	and 1 << FRZ | SLP
+	jr nz, .fainted_frz_slp
+	and a
+	ret
+
+.fainted_frz_slp
+	scf
+	ret
+; 4e554
--- /dev/null
+++ b/engine/pokemon/tempmon.asm
@@ -1,0 +1,127 @@
+CopyMonToTempMon: ; 5084a
+; gets the BaseData of a mon
+; and copies the party_struct to wTempMon
+
+	ld a, [wCurPartyMon]
+	ld e, a
+	call GetMonSpecies
+	ld a, [wCurPartySpecies]
+	ld [wCurSpecies], a
+	call GetBaseData
+
+	ld a, [wMonType]
+	ld hl, wPartyMon1Species
+	ld bc, PARTYMON_STRUCT_LENGTH
+	and a
+	jr z, .copywholestruct
+	ld hl, wOTPartyMon1Species
+	ld bc, PARTYMON_STRUCT_LENGTH
+	cp OTPARTYMON
+	jr z, .copywholestruct
+	ld bc, BOXMON_STRUCT_LENGTH
+	callfar CopyBoxmonToTempMon
+	jr .done
+
+.copywholestruct
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld de, wTempMon
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call CopyBytes
+
+.done
+	ret
+
+CalcBufferMonStats: ; 5088b
+	ld bc, wBufferMon
+	jr _TempMonStatsCalculation
+
+CalcTempmonStats: ; 50890
+	ld bc, wTempMon
+_TempMonStatsCalculation: ; 50893
+	ld hl, MON_LEVEL
+	add hl, bc
+	ld a, [hl]
+	ld [wCurPartyLevel], a
+	ld hl, MON_MAXHP
+	add hl, bc
+	ld d, h
+	ld e, l
+	ld hl, MON_STAT_EXP - 1
+	add hl, bc
+	push bc
+	ld b, TRUE
+	predef CalcMonStats
+	pop bc
+	ld hl, MON_HP
+	add hl, bc
+	ld d, h
+	ld e, l
+	ld a, [wCurPartySpecies]
+	cp EGG
+	jr nz, .not_egg
+	xor a
+	ld [de], a
+	inc de
+	ld [de], a
+	jr .zero_status
+
+.not_egg
+	push bc
+	ld hl, MON_MAXHP
+	add hl, bc
+	ld bc, 2
+	call CopyBytes
+	pop bc
+
+.zero_status
+	ld hl, MON_STATUS
+	add hl, bc
+	xor a
+	ld [hli], a
+	ld [hl], a
+	ret
+
+GetMonSpecies: ; 508d5
+; [wMonType] has the type of the mon
+; e = Nr. of mon (i.e. [wCurPartyMon])
+
+	ld a, [wMonType]
+	and a ; PARTYMON
+	jr z, .partymon
+	cp OTPARTYMON
+	jr z, .otpartymon
+	cp BOXMON
+	jr z, .boxmon
+	cp TEMPMON
+	jr z, .breedmon
+	; WILDMON
+
+.partymon
+	ld hl, wPartySpecies
+	jr .done
+
+.otpartymon
+	ld hl, wOTPartySpecies
+	jr .done
+
+.boxmon
+	ld a, BANK(sBoxSpecies)
+	call GetSRAMBank
+	ld hl, sBoxSpecies
+	call .done
+	call CloseSRAM
+	ret
+
+.breedmon
+	ld a, [wBreedMon1Species]
+	jr .done2
+
+.done
+	ld d, 0
+	add hl, de
+	ld a, [hl]
+
+.done2
+	ld [wCurPartySpecies], a
+	ret
--- /dev/null
+++ b/engine/pokemon/tmhm.asm
@@ -1,0 +1,589 @@
+TMHMPocket: ; 2c76f (b:476f)
+	ld a, $1
+	ld [hInMenu], a
+	call TMHM_PocketLoop
+	ld a, $0
+	ld [hInMenu], a
+	ret nc
+	call PlaceHollowCursor
+	call WaitBGMap
+	ld a, [wCurItem]
+	dec a
+	ld [wCurItemQuantity], a
+	ld hl, wTMsHMs
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [hl]
+	ld [wItemQuantityBuffer], a
+	call .ConvertItemToTMHMNumber
+	scf
+	ret
+
+.ConvertItemToTMHMNumber: ; 2c798 (b:4798)
+	ld a, [wCurItem]
+	ld c, a
+	callfar GetNumberedTMHM
+	ld a, c
+	ld [wCurItem], a
+	ret
+
+ConvertCurItemIntoCurTMHM: ; 2c7a7 (b:47a7)
+	ld a, [wCurItem]
+	ld c, a
+	callfar GetTMHMNumber
+	ld a, c
+	ld [wCurTMHM], a
+	ret
+
+GetTMHMItemMove: ; 2c7b6 (b:47b6)
+	call ConvertCurItemIntoCurTMHM
+	predef GetTMHMMove
+	ret
+
+AskTeachTMHM: ; 2c7bf (b:47bf)
+	ld hl, wOptions
+	ld a, [hl]
+	push af
+	res NO_TEXT_SCROLL, [hl]
+	ld a, [wCurItem]
+	cp TM01
+	jr c, .NotTMHM
+	call GetTMHMItemMove
+	ld a, [wCurTMHM]
+	ld [wPutativeTMHMMove], a
+	call GetMoveName
+	call CopyName1
+	ld hl, Text_BootedTM ; Booted up a TM
+	ld a, [wCurItem]
+	cp HM01
+	jr c, .TM
+	ld hl, Text_BootedHM ; Booted up an HM
+.TM:
+	call PrintText
+	ld hl, Text_ItContained
+	call PrintText
+	call YesNoBox
+.NotTMHM:
+	pop bc
+	ld a, b
+	ld [wOptions], a
+	ret
+
+ChooseMonToLearnTMHM: ; 2c7fb
+	ld hl, wStringBuffer2
+	ld de, wTMHMMoveNameBackup
+	ld bc, 12
+	call CopyBytes
+	call ClearBGPalettes
+ChooseMonToLearnTMHM_NoRefresh: ; 2c80a
+	farcall LoadPartyMenuGFX
+	farcall InitPartyMenuWithCancel
+	farcall InitPartyMenuGFX
+	ld a, PARTYMENUACTION_TEACH_TMHM
+	ld [wPartyMenuActionText], a
+.loopback
+	farcall WritePartyMenuTilemap
+	farcall PrintPartyMenuText
+	call WaitBGMap
+	call SetPalettes
+	call DelayFrame
+	farcall PartyMenuSelect
+	push af
+	ld a, [wCurPartySpecies]
+	cp EGG
+	pop bc ; now contains the former contents of af
+	jr z, .egg
+	push bc
+	ld hl, wTMHMMoveNameBackup
+	ld de, wStringBuffer2
+	ld bc, 12
+	call CopyBytes
+	pop af ; now contains the original contents of af
+	ret
+
+.egg
+	push hl
+	push de
+	push bc
+	push af
+	ld de, SFX_WRONG
+	call PlaySFX
+	call WaitSFX
+	pop af
+	pop bc
+	pop de
+	pop hl
+	jr .loopback
+; 2c867
+
+TeachTMHM: ; 2c867
+	predef CanLearnTMHMMove
+
+	push bc
+	ld a, [wCurPartyMon]
+	ld hl, wPartyMonNicknames
+	call GetNick
+	pop bc
+
+	ld a, c
+	and a
+	jr nz, .compatible
+	push de
+	ld de, SFX_WRONG
+	call PlaySFX
+	pop de
+	ld hl, Text_TMHMNotCompatible
+	call PrintText
+	jr .nope
+
+.compatible
+	callfar KnowsMove
+	jr c, .nope
+
+	predef LearnMove
+	ld a, b
+	and a
+	jr z, .nope
+
+	farcall StubbedTrainerRankings_TMsHMsTaught
+	ld a, [wCurItem]
+	call IsHM
+	ret c
+
+	ld c, HAPPINESS_LEARNMOVE
+	callfar ChangeHappiness
+	call ConsumeTM
+	jr .learned_move
+
+.nope
+	and a
+	ret
+
+.unused
+	ld a, 2
+	ld [wItemEffectSucceeded], a
+.learned_move
+	scf
+	ret
+; 2c8bf (b:48bf)
+
+Text_BootedTM: ; 0x2c8bf
+	; Booted up a TM.
+	text_jump UnknownText_0x1c0373
+	db "@"
+; 0x2c8c4
+
+Text_BootedHM: ; 0x2c8c4
+	; Booted up an HM.
+	text_jump UnknownText_0x1c0384
+	db "@"
+; 0x2c8c9
+
+Text_ItContained: ; 0x2c8c9
+	; It contained @ . Teach @ to a #MON?
+	text_jump UnknownText_0x1c0396
+	db "@"
+; 0x2c8ce
+
+Text_TMHMNotCompatible: ; 0x2c8ce
+	; is not compatible with @ . It can't learn @ .
+	text_jump UnknownText_0x1c03c2
+	db "@"
+; 0x2c8d3
+
+TMHM_PocketLoop: ; 2c8d3 (b:48d3)
+	xor a
+	ld [hBGMapMode], a
+	call TMHM_DisplayPocketItems
+	ld a, 2
+	ld [w2DMenuCursorInitY], a
+	ld a, 7
+	ld [w2DMenuCursorInitX], a
+	ld a, 1
+	ld [w2DMenuNumCols], a
+	ld a, 5
+	sub d
+	inc a
+	cp 6
+	jr nz, .okay
+	dec a
+.okay
+	ld [w2DMenuNumRows], a
+	ld a, $c
+	ld [w2DMenuFlags1], a
+	xor a
+	ld [w2DMenuFlags2], a
+	ld a, $20
+	ld [w2DMenuCursorOffsets], a
+	ld a, A_BUTTON | B_BUTTON | D_UP | D_DOWN | D_LEFT | D_RIGHT
+	ld [wMenuJoypadFilter], a
+	ld a, [wTMHMPocketCursor]
+	inc a
+	ld [wMenuCursorY], a
+	ld a, $1
+	ld [wMenuCursorX], a
+	jr TMHM_ShowTMMoveDescription
+
+TMHM_JoypadLoop: ; 2c915 (b:4915)
+	call TMHM_DisplayPocketItems
+	call StaticMenuJoypad
+	ld b, a
+	ld a, [wMenuCursorY]
+	dec a
+	ld [wTMHMPocketCursor], a
+	xor a
+	ld [hBGMapMode], a
+	ld a, [w2DMenuFlags2]
+	bit 7, a
+	jp nz, TMHM_ScrollPocket
+	ld a, b
+	ld [wMenuJoypad], a
+	bit A_BUTTON_F, a
+	jp nz, TMHM_ChooseTMorHM
+	bit B_BUTTON_F, a
+	jp nz, TMHM_ExitPack
+	bit D_RIGHT_F, a
+	jp nz, TMHM_ExitPocket
+	bit D_LEFT_F, a
+	jp nz, TMHM_ExitPocket
+TMHM_ShowTMMoveDescription: ; 2c946 (b:4946)
+	call TMHM_CheckHoveringOverCancel
+	jp nc, TMHM_ExitPocket
+	hlcoord 0, 12
+	ld b, 4
+	ld c, SCREEN_WIDTH - 2
+	call TextBox
+	ld a, [wCurItem]
+	cp NUM_TMS + NUM_HMS + 1
+	jr nc, TMHM_JoypadLoop
+	ld [wd265], a
+	predef GetTMHMMove
+	ld a, [wd265]
+	ld [wCurSpecies], a
+	hlcoord 1, 14
+	call PrintMoveDesc
+	jp TMHM_JoypadLoop
+
+TMHM_ChooseTMorHM: ; 2c974 (b:4974)
+	call TMHM_PlaySFX_ReadText2
+	call CountTMsHMs ; This stores the count to wd265.
+	ld a, [wMenuCursorY]
+	dec a
+	ld b, a
+	ld a, [wTMHMPocketScrollPosition]
+	add b
+	ld b, a
+	ld a, [wd265]
+	cp b
+	jr z, _TMHM_ExitPack ; our cursor was hovering over CANCEL
+TMHM_CheckHoveringOverCancel: ; 2c98a (b:498a)
+	call TMHM_GetCurrentPocketPosition
+	ld a, [wMenuCursorY]
+	ld b, a
+.loop
+	inc c
+	ld a, c
+	cp NUM_TMS + NUM_HMS + 1
+	jr nc, .okay
+	ld a, [hli]
+	and a
+	jr z, .loop
+	dec b
+	jr nz, .loop
+	ld a, c
+.okay
+	ld [wCurItem], a
+	cp -1
+	ret
+
+TMHM_ExitPack: ; 2c9a5 (b:49a5)
+	call TMHM_PlaySFX_ReadText2
+_TMHM_ExitPack: ; 2c9a8 (b:49a8)
+	ld a, $2
+	ld [wMenuJoypad], a
+	and a
+	ret
+
+TMHM_ExitPocket: ; 2c9af (b:49af)
+	and a
+	ret
+
+TMHM_ScrollPocket: ; 2c9b1 (b:49b1)
+	ld a, b
+	bit 7, a
+	jr nz, .skip
+	ld hl, wTMHMPocketScrollPosition
+	ld a, [hl]
+	and a
+	jp z, TMHM_JoypadLoop
+	dec [hl]
+	call TMHM_DisplayPocketItems
+	jp TMHM_ShowTMMoveDescription
+
+.skip
+	call TMHM_GetCurrentPocketPosition
+	ld b, 5
+.loop
+	inc c
+	ld a, c
+	cp NUM_TMS + NUM_HMS + 1
+	jp nc, TMHM_JoypadLoop
+	ld a, [hli]
+	and a
+	jr z, .loop
+	dec b
+	jr nz, .loop
+	ld hl, wTMHMPocketScrollPosition
+	inc [hl]
+	call TMHM_DisplayPocketItems
+	jp TMHM_ShowTMMoveDescription
+
+TMHM_DisplayPocketItems: ; 2c9e2 (b:49e2)
+	ld a, [wBattleType]
+	cp BATTLETYPE_TUTORIAL
+	jp z, Tutorial_TMHMPocket
+
+	hlcoord 5, 2
+	lb bc, 10, 15
+	ld a, " "
+	call ClearBox
+	call TMHM_GetCurrentPocketPosition
+	ld d, $5
+.loop2
+	inc c
+	ld a, c
+	cp NUM_TMS + NUM_HMS + 1
+	jr nc, .NotTMHM
+	ld a, [hli]
+	and a
+	jr z, .loop2
+	ld b, a
+	ld a, c
+	ld [wd265], a
+	push hl
+	push de
+	push bc
+	call TMHMPocket_GetCurrentLineCoord
+	push hl
+	ld a, [wd265]
+	cp NUM_TMS + 1
+	jr nc, .HM
+	ld de, wd265
+	lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+	call PrintNum
+	jr .okay
+
+.HM:
+	push af
+	sub NUM_TMS
+	ld [wd265], a
+	ld [hl], "H"
+	inc hl
+	ld de, wd265
+	lb bc, PRINTNUM_RIGHTALIGN | 1, 2
+	call PrintNum
+	pop af
+	ld [wd265], a
+.okay
+	predef GetTMHMMove
+	ld a, [wd265]
+	ld [wPutativeTMHMMove], a
+	call GetMoveName
+	pop hl
+	ld bc, 3
+	add hl, bc
+	push hl
+	call PlaceString
+	pop hl
+	pop bc
+	ld a, c
+	push bc
+	cp NUM_TMS + 1
+	jr nc, .hm2
+	ld bc, SCREEN_WIDTH + 9
+	add hl, bc
+	ld [hl], "×"
+	inc hl
+	ld a, "0" ; why are we doing this?
+	pop bc
+	push bc
+	ld a, b
+	ld [wd265], a
+	ld de, wd265
+	lb bc, 1, 2
+	call PrintNum
+.hm2
+	pop bc
+	pop de
+	pop hl
+	dec d
+	jr nz, .loop2
+	jr .done
+
+.NotTMHM:
+	call TMHMPocket_GetCurrentLineCoord
+	inc hl
+	inc hl
+	inc hl
+	push de
+	ld de, TMHM_String_Cancel
+	call PlaceString
+	pop de
+.done
+	ret
+
+TMHMPocket_GetCurrentLineCoord: ; 2ca86 (b:4a86)
+	hlcoord 5, 0
+	ld bc, 2 * SCREEN_WIDTH
+	ld a, 6
+	sub d
+	ld e, a
+	; AddNTimes
+.loop
+	add hl, bc
+	dec e
+	jr nz, .loop
+	ret
+; 2ca95 (b:4a95)
+
+Unreferenced_Function2ca95: ; 2ca95
+	pop hl
+	ld bc, 3
+	add hl, bc
+	predef GetTMHMMove
+	ld a, [wd265]
+	ld [wPutativeTMHMMove], a
+	call GetMoveName
+	push hl
+	call PlaceString
+	pop hl
+	ret
+; 2caae
+
+TMHM_String_Cancel: ; 2caae
+	db "CANCEL@"
+; 2cab5
+
+TMHM_GetCurrentPocketPosition: ; 2cab5 (b:4ab5)
+	ld hl, wTMsHMs
+	ld a, [wTMHMPocketScrollPosition]
+	ld b, a
+	inc b
+	ld c, 0
+.loop
+	inc c
+	ld a, [hli]
+	and a
+	jr z, .loop
+	dec b
+	jr nz, .loop
+	dec hl
+	dec c
+	ret
+
+Tutorial_TMHMPocket: ; 2caca (b:4aca)
+	hlcoord 9, 3
+	push de
+	ld de, TMHM_String_Cancel
+	call PlaceString
+	pop de
+	ret
+
+TMHM_PlaySFX_ReadText2: ; 2cad6 (b:4ad6)
+	push de
+	ld de, SFX_READ_TEXT_2
+	call PlaySFX
+	pop de
+	ret
+; 2cadf (b:4adf)
+
+Unreferenced_Function2cadf: ; 2cadf
+	call ConvertCurItemIntoCurTMHM
+	call .CheckHaveRoomForTMHM
+	ld hl, .NoRoomText
+	jr nc, .print
+	ld hl, .ReceivedText
+.print
+	jp PrintText
+; 2caf0
+
+.NoRoomText: ; 0x2caf0
+	; You have no room for any more @ S.
+	text_jump UnknownText_0x1c03fa
+	db "@"
+; 0x2caf5
+
+.ReceivedText: ; 0x2caf5
+	; You received @ !
+	text_jump UnknownText_0x1c0421
+	db "@"
+; 0x2cafa
+
+.CheckHaveRoomForTMHM: ; 2cafa
+	ld a, [wd265]
+	dec a
+	ld hl, wTMsHMs
+	ld b, 0
+	ld c, a
+	add hl, bc
+	ld a, [hl]
+	inc a
+	cp NUM_TMS * 2
+	ret nc
+	ld [hl], a
+	ret
+; 2cb0c
+
+ConsumeTM: ; 2cb0c (b:4b0c)
+	call ConvertCurItemIntoCurTMHM
+	ld a, [wd265]
+	dec a
+	ld hl, wTMsHMs
+	ld b, 0
+	ld c, a
+	add hl, bc
+	ld a, [hl]
+	and a
+	ret z
+	dec a
+	ld [hl], a
+	ret nz
+	ld a, [wTMHMPocketScrollPosition]
+	and a
+	ret z
+	dec a
+	ld [wTMHMPocketScrollPosition], a
+	ret
+
+CountTMsHMs: ; 2cb2a (b:4b2a)
+	ld b, 0
+	ld c, NUM_TMS + NUM_HMS
+	ld hl, wTMsHMs
+.loop
+	ld a, [hli]
+	and a
+	jr z, .skip
+	inc b
+.skip
+	dec c
+	jr nz, .loop
+	ld a, b
+	ld [wd265], a
+	ret
+
+PrintMoveDesc: ; 2cb3e
+	push hl
+	ld hl, MoveDescriptions
+	ld a, [wCurSpecies]
+	dec a
+	ld c, a
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld e, a
+	ld d, [hl]
+	pop hl
+	jp PlaceString
+; 2cb52
--- /dev/null
+++ b/engine/pokemon/types.asm
@@ -1,0 +1,99 @@
+PrintMonTypes: ; 5090d
+; Print one or both types of [wCurSpecies]
+; on the stats screen at hl.
+
+	push hl
+	call GetBaseData
+	pop hl
+
+	push hl
+	ld a, [wBaseType1]
+	call .Print
+
+	; Single-typed monsters really
+	; have two of the same type.
+	ld a, [wBaseType1]
+	ld b, a
+	ld a, [wBaseType2]
+	cp b
+	pop hl
+	jr z, .hide_type_2
+
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+
+.Print:
+	ld b, a
+	jr PrintType
+
+.hide_type_2
+	; Erase any type name that was here before.
+	; Seems to be pointless in localized versions.
+	ld a, " "
+	ld bc, SCREEN_WIDTH - 3
+	add hl, bc
+	ld [hl], a
+	inc bc
+	add hl, bc
+	ld bc, NAME_LENGTH_JAPANESE - 1
+	jp ByteFill
+; 5093a
+
+
+PrintMoveType: ; 5093a
+; Print the type of move b at hl.
+
+	push hl
+	ld a, b
+	dec a
+	ld bc, MOVE_LENGTH
+	ld hl, Moves
+	call AddNTimes
+	ld de, wStringBuffer1
+	ld a, BANK(Moves)
+	call FarCopyBytes
+	ld a, [wStringBuffer1 + MOVE_TYPE]
+	pop hl
+
+	ld b, a
+
+
+PrintType: ; 50953
+; Print type b at hl.
+
+	ld a, b
+
+	push hl
+	add a
+	ld hl, TypeNames
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld a, [hli]
+	ld e, a
+	ld d, [hl]
+	pop hl
+
+	jp PlaceString
+; 50964
+
+
+GetTypeName: ; 50964
+; Copy the name of type [wd265] to wStringBuffer1.
+
+	ld a, [wd265]
+	ld hl, TypeNames
+	ld e, a
+	ld d, 0
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, wStringBuffer1
+	ld bc, MOVE_NAME_LENGTH
+	jp CopyBytes
+; 5097b
+
+
+INCLUDE "data/types/names.asm"
--- a/engine/print_party.asm
+++ /dev/null
@@ -1,364 +1,0 @@
-PRINTPARTY_HP EQUS "\"◀\"" ; $71
-
-PrintPage1: ; 1dc1b0
-	hlcoord 0, 0
-	decoord 0, 0, wPrinterTileMapBuffer
-	ld bc, 17 * SCREEN_WIDTH
-	call CopyBytes
-	hlcoord 17, 1, wPrinterTileMapBuffer
-	ld a, $62
-	ld [hli], a
-	inc a
-	ld [hl], a
-	hlcoord 17, 2, wPrinterTileMapBuffer
-	ld a, $64
-	ld [hli], a
-	inc a
-	ld [hl], a
-	hlcoord 1, 9, wPrinterTileMapBuffer
-	ld a, " "
-	ld [hli], a
-	ld [hl], a
-	hlcoord 1, 10, wPrinterTileMapBuffer
-	ld a, $61
-	ld [hli], a
-	ld [hl], a
-	hlcoord 2, 11, wPrinterTileMapBuffer
-	lb bc, 5, 18
-	call ClearBox
-	ld a, [wd265]
-	dec a
-	call CheckCaughtMon
-	push af
-	ld a, [wd265]
-	ld b, a
-	ld c, 1 ; get page 1
-	farcall GetDexEntryPagePointer
-	pop af
-	ld a, b
-	hlcoord 1, 11, wPrinterTileMapBuffer
-	call nz, FarString
-	hlcoord 19, 0, wPrinterTileMapBuffer
-	ld [hl], $35
-	ld de, SCREEN_WIDTH
-	add hl, de
-	ld b, $f
-.column_loop
-	ld [hl], $37
-	add hl, de
-	dec b
-	jr nz, .column_loop
-	ld [hl], $3a
-	ret
-; 1dc213
-
-PrintPage2: ; 1dc213
-	hlcoord 0, 0, wPrinterTileMapBuffer
-	ld bc, 8 * SCREEN_WIDTH
-	ld a, " "
-	call ByteFill
-	hlcoord 0, 0, wPrinterTileMapBuffer
-	ld a, $36
-	ld b, 6
-	call .FillColumn
-	hlcoord 19, 0, wPrinterTileMapBuffer
-	ld a, $37
-	ld b, 6
-	call .FillColumn
-	hlcoord 0, 6, wPrinterTileMapBuffer
-	ld [hl], $38
-	inc hl
-	ld a, $39
-	ld bc, SCREEN_HEIGHT
-	call ByteFill
-	ld [hl], $3a
-	hlcoord 0, 7, wPrinterTileMapBuffer
-	ld bc, SCREEN_WIDTH
-	ld a, $32
-	call ByteFill
-	ld a, [wd265]
-	dec a
-	call CheckCaughtMon
-	push af
-	ld a, [wd265]
-	ld b, a
-	ld c, 2 ; get page 2
-	farcall GetDexEntryPagePointer
-	pop af
-	hlcoord 1, 1, wPrinterTileMapBuffer
-	ld a, b
-	call nz, FarString
-	ret
-; 1dc26a
-
-.FillColumn: ; 1dc26a
-	push de
-	ld de, SCREEN_WIDTH
-.column_loop
-	ld [hl], a
-	add hl, de
-	dec b
-	jr nz, .column_loop
-	pop de
-	ret
-; 1dc275
-
-GBPrinterStrings:
-GBPrinterString_Null: db "@"
-GBPrinterString_CheckingLink: next " CHECKING LINK...@"
-GBPrinterString_Transmitting: next "  TRANSMITTING...@"
-GBPrinterString_Printing: next "    PRINTING...@"
-GBPrinterString_PrinterError1:
-	db   " Printer Error 1"
-	next ""
-	next "Check the Game Boy"
-	next "Printer Manual."
-	db   "@"
-GBPrinterString_PrinterError2:
-	db   " Printer Error 2"
-	next ""
-	next "Check the Game Boy"
-	next "Printer Manual."
-	db   "@"
-GBPrinterString_PrinterError3:
-	db   " Printer Error 3"
-	next ""
-	next "Check the Game Boy"
-	next "Printer Manual."
-	db   "@"
-GBPrinterString_PrinterError4:
-	db   " Printer Error 4"
-	next ""
-	next "Check the Game Boy"
-	next "Printer Manual."
-	db   "@"
-; 1dc381
-
-PrintPartyMonPage1: ; 1dc381
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	xor a
-	ld [hBGMapMode], a
-	call LoadFontsBattleExtra
-
-	ld de, GBPrinterHPIcon
-	ld hl, vTiles2 tile PRINTPARTY_HP
-	lb bc, BANK(GBPrinterHPIcon), 1
-	call Request1bpp
-
-	ld de, GBPrinterLvIcon
-	ld hl, vTiles2 tile "<LV>"
-	lb bc, BANK(GBPrinterLvIcon), 1
-	call Request1bpp
-
-	ld de, StatsScreenPageTilesGFX + 14 tiles ; shiny icon
-	ld hl, vTiles2 tile "⁂"
-	lb bc, BANK(StatsScreenPageTilesGFX), 1
-	call Get2bpp
-
-	xor a
-	ld [wMonType], a
-	farcall CopyMonToTempMon
-	hlcoord 0, 7
-	ld b, 9
-	ld c, 18
-	call TextBox
-	hlcoord 8, 2
-	ld a, [wTempMonLevel]
-	call PrintLevel_Force3Digits
-	hlcoord 12, 2
-	ld [hl], PRINTPARTY_HP
-	inc hl
-	ld de, wTempMonMaxHP
-	lb bc, 2, 3
-	call PrintNum
-	ld a, [wCurPartySpecies]
-	ld [wd265], a
-	ld [wCurSpecies], a
-	ld hl, wPartyMonNicknames
-	call Function1dc50e
-	hlcoord 8, 4
-	call PlaceString
-	hlcoord 9, 6
-	ld [hl], "/"
-	call GetPokemonName
-	hlcoord 10, 6
-	call PlaceString
-	hlcoord 8, 0
-	ld [hl], "№"
-	inc hl
-	ld [hl], "."
-	inc hl
-	ld de, wd265
-	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
-	call PrintNum
-	hlcoord 1, 9
-	ld de, String1dc550
-	call PlaceString
-	ld hl, wPartyMonOT
-	call Function1dc50e
-	hlcoord 4, 9
-	call PlaceString
-	hlcoord 1, 11
-	ld de, String1dc559
-	call PlaceString
-	hlcoord 4, 11
-	ld de, wTempMonID
-	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
-	call PrintNum
-	hlcoord 1, 14
-	ld de, String1dc554
-	call PlaceString
-	hlcoord 7, 14
-	ld a, [wTempMonMoves + 0]
-	call Function1dc51a
-	call Function1dc52c
-	ld hl, wTempMonDVs
-	predef GetUnownLetter
-	ld hl, wBoxAlignment
-	xor a
-	ld [hl], a
-	ld a, [wCurPartySpecies]
-	cp UNOWN
-	jr z, .asm_1dc469
-	inc [hl]
-
-.asm_1dc469
-	hlcoord 0, 0
-	call _PrepMonFrontpic
-	call WaitBGMap
-	ld b, SCGB_STATS_SCREEN_HP_PALS
-	call GetSGBLayout
-	call SetPalettes
-	ret
-; 1dc47b
-
-PrintPartyMonPage2: ; 1dc47b
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	xor a
-	ld [hBGMapMode], a
-	call LoadFontsBattleExtra
-	xor a
-	ld [wMonType], a
-	farcall CopyMonToTempMon
-	hlcoord 0, 0
-	ld b, 15
-	ld c, 18
-	call TextBox
-	ld bc, SCREEN_WIDTH
-	decoord 0, 0
-	hlcoord 0, 1
-	call CopyBytes
-	hlcoord 7, 0
-	ld a, [wTempMonMoves + 1]
-	call Function1dc51a
-	hlcoord 7, 2
-	ld a, [wTempMonMoves + 2]
-	call Function1dc51a
-	hlcoord 7, 4
-	ld a, [wTempMonMoves + 3]
-	call Function1dc51a
-	hlcoord 7, 7
-	ld de, String1dc55d
-	call PlaceString
-	hlcoord 16, 7
-	ld de, wTempMonAttack
-	call .PrintTempMonStats
-	hlcoord 16, 9
-	ld de, wTempMonDefense
-	call .PrintTempMonStats
-	hlcoord 16, 11
-	ld de, wTempMonSpclAtk
-	call .PrintTempMonStats
-	hlcoord 16, 13
-	ld de, wTempMonSpclDef
-	call .PrintTempMonStats
-	hlcoord 16, 15
-	ld de, wTempMonSpeed
-	call .PrintTempMonStats
-	call WaitBGMap
-	ld b, SCGB_STATS_SCREEN_HP_PALS
-	call GetSGBLayout
-	call SetPalettes
-	ret
-; 1dc507
-
-.PrintTempMonStats: ; 1dc507
-	lb bc, 2, 3
-	call PrintNum
-	ret
-; 1dc50e
-
-Function1dc50e: ; 1dc50e
-	ld bc, NAME_LENGTH
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld e, l
-	ld d, h
-	ret
-; 1dc51a
-
-Function1dc51a: ; 1dc51a
-	and a
-	jr z, .no_move
-
-	ld [wd265], a
-	call GetMoveName
-	jr .got_string
-
-.no_move
-	ld de, String1dc584
-
-.got_string
-	call PlaceString
-	ret
-; 1dc52c
-
-Function1dc52c: ; 1dc52c
-	farcall GetGender
-	ld a, " "
-	jr c, .got_gender
-	ld a, "♂"
-	jr nz, .got_gender
-	ld a, "♀"
-
-.got_gender
-	hlcoord 17, 2
-	ld [hl], a
-	ld bc, wTempMonDVs
-	farcall CheckShininess
-	ret nc
-	hlcoord 18, 2
-	ld [hl], "⁂"
-	ret
-; 1dc550
-
-String1dc550: ; 1dc550
-	db "OT/@"
-
-String1dc554: ; 1dc554
-	db "MOVE@"
-
-String1dc559: ; 1dc559
-	db "<ID>№.@"
-
-String1dc55d: ; 1dc55d
-	db   "ATTACK"
-	next "DEFENSE"
-	next "SPCL.ATK"
-	next "SPCL.DEF"
-	next "SPEED"
-	db   "@"
-
-String1dc584: ; 1dc584
-	db "------------@"
-; 1dc591
-
-GBPrinterHPIcon: ; 1dc591
-INCBIN "gfx/printer/hp.1bpp"
-
-GBPrinterLvIcon: ; 1dc599
-INCBIN "gfx/printer/lv.1bpp"
--- a/engine/printer.asm
+++ /dev/null
@@ -1,949 +1,0 @@
-INCLUDE "engine/printer_serial.asm"
-
-SendScreenToPrinter: ; 843f0
-.loop
-	call JoyTextDelay
-	call CheckCancelPrint
-	jr c, .cancel
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .finished
-	call PrinterJumptableIteration
-	call CheckPrinterStatus
-	call PlacePrinterStatusString
-	call DelayFrame
-	jr .loop
-
-.finished
-	and a
-	ret
-
-.cancel
-	scf
-	ret
-; 84411
-
-Printer_CleanUpAfterSend: ; 84411
-	xor a
-	ld [wPrinterConnectionOpen], a
-	ld [wPrinterOpcode], a
-	ret
-; 84419
-
-Printer_PrepareTileMapForPrint: ; 84419
-	push af
-	call Printer_StartTransmission
-	pop af
-	ld [wcbfa], a
-	call Printer_CopyTileMapToBuffer
-	ret
-; 84425
-
-Printer_ExitPrinter: ; 84425
-	call ReturnToMapFromSubmenu
-	call Printer_RestartMapMusic
-	ret
-; 8442c
-
-PrintDexEntry: ; 8442c
-	ld a, [wPrinterQueueLength]
-	push af
-
-	ld hl, vTiles1
-	ld de, FontInversed
-	lb bc, BANK(FontInversed), $80
-	call Request1bpp
-
-	xor a
-	ld [hPrinter], a
-	call Printer_PlayMusic
-
-	ld a, [rIE]
-	push af
-	xor a
-	ld [rIF], a
-	ld a, $9
-	ld [rIE], a
-
-	call Printer_StartTransmission
-	ld a, $10
-	ld [wcbfa], a
-	farcall PrintPage1
-	call ClearTileMap
-	ld a, %11100100
-	call DmgToCgbBGPals
-	call DelayFrame
-
-	ld hl, hVBlank
-	ld a, [hl]
-	push af
-	ld [hl], $4
-
-	ld a, 8 ; 16 rows
-	ld [wPrinterQueueLength], a
-	call Printer_ResetJoypadRegisters
-	call SendScreenToPrinter
-	jr c, .skip_second_page ; canceled or got an error
-
-	call Printer_CleanUpAfterSend
-	ld c, 12
-	call DelayFrames
-	xor a
-	ld [hBGMapMode], a
-
-	call Printer_StartTransmission
-	ld a, $3
-	ld [wcbfa], a
-	farcall PrintPage2
-	call Printer_ResetJoypadRegisters
-	ld a, 4
-	ld [wPrinterQueueLength], a
-	call SendScreenToPrinter
-
-.skip_second_page
-	pop af
-	ld [hVBlank], a
-	call Printer_CleanUpAfterSend
-
-	xor a
-	ld [rIF], a
-	pop af
-	ld [rIE], a
-
-	call Printer_ExitPrinter
-	ld c, 8
-.low_volume_delay_frames
-	call LowVolume
-	call DelayFrame
-	dec c
-	jr nz, .low_volume_delay_frames
-
-	pop af
-	ld [wPrinterQueueLength], a
-	ret
-; 844bc
-
-PrintPCBox: ; 844bc (21:44bc)
-	ld a, [wPrinterQueueLength]
-	push af
-	ld a, 18 / 2
-	ld [wPrinterQueueLength], a
-
-	ld a, e
-	ld [wAddrOfBoxToPrint], a
-	ld a, d
-	ld [wAddrOfBoxToPrint + 1], a
-	ld a, b
-	ld [wBankOfBoxToPrint], a
-	ld a, c
-	ld [wWhichBoxToPrint], a
-
-	xor a
-	ld [hPrinter], a
-	ld [wFinishedPrintingBox], a
-	call Printer_PlayMusic
-
-	ld a, [rIE]
-	push af
-	xor a
-	ld [rIF], a
-	ld a, %1001
-	ld [rIE], a
-
-	ld hl, hVBlank
-	ld a, [hl]
-	push af
-	ld [hl], %0100
-
-	xor a
-	ld [hBGMapMode], a
-	call PrintPCBox_Page1
-	ld a, $10 ; to be loaded to wcbfa
-	call Printer_PrepareTileMapForPrint
-	call Printer_ResetRegistersAndStartDataSend
-	jr c, .cancel
-
-	call Printer_CleanUpAfterSend
-	ld c, 12
-	call DelayFrames
-	xor a
-	ld [hBGMapMode], a
-	call PrintPCBox_Page2
-	ld a, $0 ; to be loaded to wcbfa
-	call Printer_PrepareTileMapForPrint
-	call Printer_ResetRegistersAndStartDataSend
-	jr c, .cancel
-
-	call Printer_CleanUpAfterSend
-	ld c, 12
-	call DelayFrames
-
-	xor a
-	ld [hBGMapMode], a
-	call PrintPCBox_Page3
-	ld a, $0 ; to be loaded to wcbfa
-	call Printer_PrepareTileMapForPrint
-	call Printer_ResetRegistersAndStartDataSend
-	jr c, .cancel
-
-	call Printer_CleanUpAfterSend
-	ld c, 12
-	call DelayFrames
-
-	xor a
-	ld [hBGMapMode], a
-	call PrintPCBox_Page4
-	ld a, $3 ; to be loaded to wcbfa
-	call Printer_PrepareTileMapForPrint
-	call Printer_ResetRegistersAndStartDataSend
-.cancel
-	pop af
-	ld [hVBlank], a
-	call Printer_CleanUpAfterSend
-
-	xor a
-	ld [rIF], a
-	pop af
-	ld [rIE], a
-	call Printer_ExitPrinter
-
-	pop af
-	ld [wPrinterQueueLength], a
-	ret
-
-Printer_ResetRegistersAndStartDataSend: ; 84559 (21:4559)
-	call Printer_ResetJoypadRegisters
-	call SendScreenToPrinter
-	ret
-
-PrintUnownStamp: ; 84560
-	ld a, [wPrinterQueueLength]
-	push af
-	xor a
-	ld [hPrinter], a
-	call Printer_PlayMusic
-	ld a, [rIE]
-	push af
-	xor a
-	ld [rIF], a
-	ld a, $9
-	ld [rIE], a
-	ld hl, hVBlank
-	ld a, [hl]
-	push af
-	ld [hl], $4
-	xor a
-	ld [hBGMapMode], a
-	call LoadTileMapToTempTileMap
-	farcall PlaceUnownPrinterFrontpic
-	ld a, $0 ; to be loaded to wcbfa
-	call Printer_PrepareTileMapForPrint
-	call Call_LoadTempTileMapToTileMap
-	call Printer_ResetJoypadRegisters
-	ld a, 18 / 2
-	ld [wPrinterQueueLength], a
-.loop
-	call JoyTextDelay
-	call CheckCancelPrint
-	jr c, .done
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .done
-	call PrinterJumptableIteration
-	ld a, [wJumptableIndex]
-	cp $2
-	jr nc, .check_status
-	ld a, 6 / 2
-	ld [wPrinterRowIndex], a
-
-.check_status
-	call CheckPrinterStatus
-	call PlacePrinterStatusString
-	call DelayFrame
-	jr .loop
-
-.done
-	pop af
-	ld [hVBlank], a
-	call Printer_CleanUpAfterSend
-	call Call_LoadTempTileMapToTileMap
-	xor a
-	ld [rIF], a
-	pop af
-	ld [rIE], a
-	pop af
-	ld [wPrinterQueueLength], a
-	ret
-; 845d4
-
-PrintMail: ; 845d4
-	call PrintMail_
-	call Printer_ExitPrinter
-	ret
-; 845db
-
-PrintMail_: ; 845db
-	ld a, [wPrinterQueueLength]
-	push af
-	xor a
-	ld [hPrinter], a
-	call Printer_PlayMusic
-
-	ld a, [rIE]
-	push af
-	xor a
-	ld [rIF], a
-	ld a, %1001
-	ld [rIE], a
-
-	xor a
-	ld [hBGMapMode], a
-
-	ld a, $13 ; to be loaded to wcbfa
-	call Printer_PrepareTileMapForPrint
-	ld hl, hVBlank
-	ld a, [hl]
-	push af
-	ld [hl], %0100
-
-	ld a, 18 / 2
-	ld [wPrinterQueueLength], a
-	call SendScreenToPrinter
-
-	pop af
-	ld [hVBlank], a
-	call Printer_CleanUpAfterSend
-	call Printer_CopyBufferToTileMap
-
-	xor a
-	ld [rIF], a
-	pop af
-	ld [rIE], a
-
-	pop af
-	ld [wPrinterQueueLength], a
-	ret
-; 8461a
-
-PrintPartymon: ; 8461a
-	ld a, [wPrinterQueueLength]
-	push af
-	xor a
-	ld [hPrinter], a
-	call Printer_PlayMusic
-
-	ld a, [rIE]
-	push af
-	xor a
-	ld [rIF], a
-	ld a, %1001
-	ld [rIE], a
-
-	xor a
-	ld [hBGMapMode], a
-	farcall PrintPartyMonPage1
-	ld a, $10 ; to be loaded to wcbfa
-	call Printer_PrepareTileMapForPrint
-
-	ld hl, hVBlank
-	ld a, [hl]
-	push af
-	ld [hl], %0100
-
-	ld a, 16 / 2
-	ld [wPrinterQueueLength], a
-	call Printer_ResetJoypadRegisters
-	call SendScreenToPrinter
-	jr c, .cancel
-
-	call Printer_CleanUpAfterSend
-	ld c, 12
-	call DelayFrames
-
-	xor a
-	ld [hBGMapMode], a
-	farcall PrintPartyMonPage2
-	ld a, $3 ; to be loaded to wcbfa
-	call Printer_PrepareTileMapForPrint
-
-	ld a, 18 / 2
-	ld [wPrinterQueueLength], a
-	call Printer_ResetJoypadRegisters
-	call SendScreenToPrinter
-.cancel
-	pop af
-	ld [hVBlank], a
-	call Printer_CleanUpAfterSend
-
-	call Printer_CopyBufferToTileMap
-	xor a
-	ld [rIF], a
-	pop af
-	ld [rIE], a
-	call Printer_ExitPrinter
-
-	pop af
-	ld [wPrinterQueueLength], a
-	ret
-; 84688
-
-_PrintDiploma: ; 84688
-	ld a, [wPrinterQueueLength]
-	push af
-
-	farcall PlaceDiplomaOnScreen
-
-	xor a
-	ld [hPrinter], a
-	call Printer_PlayMusic
-
-	ld a, [rIE]
-	push af
-	xor a
-	ld [rIF], a
-	ld a, %1001
-	ld [rIE], a
-
-	ld hl, hVBlank
-	ld a, [hl]
-	push af
-	ld [hl], %0100
-
-	ld a, $10 ; to be loaded to wcbfa
-	call Printer_PrepareTileMapForPrint
-	call Printer_ResetJoypadRegisters
-
-	ld a, 18 / 2
-	ld [wPrinterQueueLength], a
-	call SendScreenToPrinter
-	jr c, .cancel
-	call Printer_CleanUpAfterSend
-	ld c, 12
-	call DelayFrames
-
-	call LoadTileMapToTempTileMap
-	xor a
-	ld [hBGMapMode], a
-
-	farcall PrintDiplomaPage2
-
-	ld a, $3 ; to be loaded to wcbfa
-	call Printer_PrepareTileMapForPrint
-	call Call_LoadTempTileMapToTileMap
-	call Printer_ResetJoypadRegisters
-
-	ld a, 18 / 2
-	ld [wPrinterQueueLength], a
-	call SendScreenToPrinter
-.cancel
-	pop af
-	ld [hVBlank], a
-	call Printer_CleanUpAfterSend
-
-	xor a
-	ld [rIF], a
-	pop af
-	ld [rIE], a
-	call Printer_ExitPrinter
-
-	pop af
-	ld [wPrinterQueueLength], a
-	ret
-; 846f6
-
-CheckCancelPrint: ; 846f6
-	ld a, [hJoyDown]
-	and B_BUTTON
-	jr nz, .pressed_b
-	and a
-	ret
-
-.pressed_b
-	ld a, [wca80]
-	cp $c
-	jr nz, .cancel
-.loop
-	ld a, [wPrinterOpcode]
-	and a
-	jr nz, .loop
-	ld a, $16 ; cancel
-	ld [wPrinterOpcode], a
-	ld a, $88
-	ld [rSB], a
-	ld a, $1
-	ld [rSC], a
-	ld a, $81
-	ld [rSC], a
-.loop2
-	ld a, [wPrinterOpcode]
-	and a
-	jr nz, .loop2
-
-.cancel
-	ld a, $1
-	ld [hPrinter], a
-	scf
-	ret
-; 84728
-
-Printer_CopyTileMapToBuffer: ; 84728
-	hlcoord 0, 0
-	ld de, wPrinterTileMapBuffer
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	call CopyBytes
-	ret
-; 84735
-
-Printer_CopyBufferToTileMap: ; 84735
-	ld hl, wPrinterTileMapBuffer
-	decoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	call CopyBytes
-	ret
-; 84742
-
-Printer_ResetJoypadRegisters: ; 84742
-	xor a
-	ld [hJoyReleased], a
-	ld [hJoyPressed], a
-	ld [hJoyDown], a
-	ld [hJoyLast], a
-	ret
-; 8474c
-
-Printer_PlayMusic: ; 8474c
-	ld de, MUSIC_PRINTER
-	call PlayMusic2
-	ret
-; 84753
-
-Printer_RestartMapMusic: ; 84753
-	call RestartMapMusic
-	ret
-; 84757
-
-CheckPrinterStatus: ; 84757
-; Check for printer errors
-; If [ca88] == -1, we're disconnected
-	ld a, [wPrinterHandshake]
-	cp -1
-	jr nz, .printer_connected
-	ld a, [wPrinterStatusFlags]
-	cp -1
-	jr z, .error_2
-.printer_connected
-; ca89 contains printer status flags
-	ld a, [wPrinterStatusFlags]
-	and %11100000
-	ret z ; no error
-
-	bit 7, a
-	jr nz, .error_1
-	bit 6, a
-	jr nz, .error_4
-	; paper error
-	ld a, PRINTER_ERROR_3
-	jr .load_text_index
-
-.error_4
-	; temperature error
-	ld a, PRINTER_ERROR_4
-	jr .load_text_index
-
-.error_1
-	; printer battery low
-	ld a, PRINTER_ERROR_1
-	jr .load_text_index
-
-.error_2
-	; connection error
-	ld a, PRINTER_ERROR_2
-.load_text_index
-	ld [wPrinterStatus], a
-	ret
-; 84785
-
-PlacePrinterStatusString: ; 84785
-; Print nonzero printer status
-	ld a, [wPrinterStatus]
-	and a
-	ret z
-	push af
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 0, 5
-	lb bc, 10, 18
-	call TextBox
-	pop af
-	ld e, a
-	ld d, 0
-	ld hl, PrinterStatusStringPointers
-	add hl, de
-	add hl, de
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	hlcoord 1, 7
-	ld a, BANK(GBPrinterStrings)
-	call FarString
-	hlcoord 2, 15
-	ld de, String_PressBToCancel
-	call PlaceString
-	ld a, $1
-	ld [hBGMapMode], a
-	xor a
-	ld [wPrinterStatus], a
-	ret
-; 847bd
-
-Unreferenced_Function847bd: ; 847bd
-	ld a, [wPrinterStatus]
-	and a
-	ret z
-	push af
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 2, 4
-	lb bc, 13, 16
-	call ClearBox
-	pop af
-	ld e, a
-	ld d, 0
-	ld hl, PrinterStatusStringPointers
-	add hl, de
-	add hl, de
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	hlcoord 4, 7
-	ld a, BANK(GBPrinterStrings)
-	call FarString
-	hlcoord 4, 15
-	ld de, String_PressBToCancel
-	call PlaceString
-	ld a, $1
-	ld [hBGMapMode], a
-	xor a
-	ld [wPrinterStatus], a
-	ret
-; 847f5
-
-String_PressBToCancel:
-	db "Press B to Cancel@"
-; 84807
-
-PrinterStatusStringPointers: ; 84807
-	dw GBPrinterString_Null ; @
-	dw GBPrinterString_CheckingLink ; CHECKING LINK
-	dw GBPrinterString_Transmitting ; TRANSMITTING
-	dw GBPrinterString_Printing ; PRINTING
-	dw GBPrinterString_PrinterError1 ; error 1
-	dw GBPrinterString_PrinterError2 ; error 2
-	dw GBPrinterString_PrinterError3 ; error 3
-	dw GBPrinterString_PrinterError4 ; error 4
-; 84817
-
-PrintPCBox_Page1: ; 84817 (21:4817)
-	xor a
-	ld [wWhichBoxMonToPrint], a
-	hlcoord 0, 0
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	ld a, " "
-	call ByteFill
-	call Printer_PlaceEmptyBoxSlotString
-
-	hlcoord 0, 0
-	ld bc, 9 * SCREEN_WIDTH
-	ld a, " "
-	call ByteFill
-
-	call Printer_PlaceSideBorders
-	call Printer_PlaceTopBorder
-
-	hlcoord 4, 3
-	ld de, .String_PokemonList
-	call PlaceString
-
-	ld a, [wWhichBoxToPrint]
-	ld bc, BOX_NAME_LENGTH
-	ld hl, wBoxNames
-	call AddNTimes
-	ld d, h
-	ld e, l
-	hlcoord 6, 5
-	call PlaceString
-	ld a, 1
-	call Printer_GetBoxMonSpecies
-	hlcoord 2, 9
-	ld c, 3
-	call Printer_PrintBoxListSegment
-	ret
-; 84865 (21:4865)
-
-.String_PokemonList:
-	db "#MON LIST@"
-; 8486f
-
-PrintPCBox_Page2: ; 8486f (21:486f)
-	hlcoord 0, 0
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	ld a, " "
-	call ByteFill
-	call Printer_PlaceEmptyBoxSlotString
-	call Printer_PlaceSideBorders
-	ld a, [wFinishedPrintingBox]
-	and a
-	ret nz
-	ld a, 4
-	call Printer_GetBoxMonSpecies
-	hlcoord 2, 0
-	ld c, 6
-	call Printer_PrintBoxListSegment
-	ret
-
-PrintPCBox_Page3: ; 84893 (21:4893)
-	hlcoord 0, 0
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	ld a, " "
-	call ByteFill
-	call Printer_PlaceEmptyBoxSlotString
-	call Printer_PlaceSideBorders
-	ld a, [wFinishedPrintingBox]
-	and a
-	ret nz
-	ld a, 10
-	call Printer_GetBoxMonSpecies
-	hlcoord 2, 0
-	ld c, 6
-	call Printer_PrintBoxListSegment
-	ret
-
-PrintPCBox_Page4: ; 848b7 (21:48b7)
-	hlcoord 0, 0
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	ld a, " "
-	call ByteFill
-	call Printer_PlaceEmptyBoxSlotString
-	hlcoord 1, 15
-	lb bc, 2, 18
-	call ClearBox
-	call Printer_PlaceSideBorders
-	call Printer_PlaceBottomBorders
-	ld a, [wFinishedPrintingBox]
-	and a
-	ret nz
-	ld a, 16
-	call Printer_GetBoxMonSpecies
-	hlcoord 2, 0
-	ld c, 5
-	call Printer_PrintBoxListSegment
-	ret
-
-Printer_PrintBoxListSegment: ; 848e7 (21:48e7)
-	ld a, [wBankOfBoxToPrint]
-	call GetSRAMBank
-.loop
-	ld a, c
-	and a
-	jp z, .max_length
-	dec c
-	ld a, [de]
-	cp $ff
-	jp z, .finish
-	ld [wd265], a
-	ld [wCurPartySpecies], a
-
-	push bc
-	push hl
-	push de
-
-	push hl
-	ld bc, 16
-	ld a, " "
-	call ByteFill
-	pop hl
-
-	push hl
-	call GetBasePokemonName
-	pop hl
-
-	push hl
-	call PlaceString
-	ld a, [wCurPartySpecies]
-	cp EGG
-	pop hl
-	jr z, .ok2
-
-	ld bc, MON_NAME_LENGTH
-	add hl, bc
-	call Printer_GetMonGender
-	ld bc, SCREEN_WIDTH - MON_NAME_LENGTH
-	add hl, bc
-	ld a, "/"
-	ld [hli], a
-
-	push hl
-	ld bc, 14
-	ld a, " "
-	call ByteFill
-	pop hl
-
-	push hl
-	ld a, [wAddrOfBoxToPrint]
-	ld l, a
-	ld a, [wAddrOfBoxToPrint + 1]
-	ld h, a
-	ld bc, sBoxMonNicknames - sBox
-	add hl, bc
-	ld bc, MON_NAME_LENGTH
-	ld a, [wWhichBoxMonToPrint]
-	call AddNTimes
-	ld e, l
-	ld d, h
-	pop hl
-
-	push hl
-	call PlaceString
-	pop hl
-
-	ld bc, MON_NAME_LENGTH
-	add hl, bc
-	push hl
-	ld a, [wAddrOfBoxToPrint]
-	ld l, a
-	ld a, [wAddrOfBoxToPrint + 1]
-	ld h, a
-	ld bc, 2 + MONS_PER_BOX + MON_LEVEL
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, [wWhichBoxMonToPrint]
-	call AddNTimes
-	ld a, [hl]
-	pop hl
-	call PrintLevel_Force3Digits
-.ok2
-	ld hl, wWhichBoxMonToPrint
-	inc [hl]
-	pop de
-	pop hl
-	ld bc, 3 * SCREEN_WIDTH
-	add hl, bc
-	pop bc
-	inc de
-	jp .loop
-
-.finish
-	ld a, $1
-	ld [wFinishedPrintingBox], a
-.max_length
-	call CloseSRAM
-	ret
-
-Printer_GetMonGender: ; 8498a (21:498a)
-	push hl
-	ld a, [wAddrOfBoxToPrint]
-	ld l, a
-	ld a, [wAddrOfBoxToPrint + 1]
-	ld h, a
-	ld bc, $2b
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, [wWhichBoxMonToPrint]
-	call AddNTimes
-	ld de, wTempMonDVs
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hli]
-	ld [de], a
-	ld a, [wWhichBoxMonToPrint]
-	ld [wCurPartyMon], a
-	ld a, TEMPMON
-	ld [wMonType], a
-	farcall GetGender
-	ld a, " "
-	jr c, .got_gender
-	ld a, "♂"
-	jr nz, .got_gender
-	ld a, "♀"
-.got_gender
-	pop hl
-	ld [hli], a
-	ret
-
-Printer_GetBoxMonSpecies: ; 849c6 (21:49c6)
-	push hl
-	ld e, a
-	ld d, $0
-	ld a, [wAddrOfBoxToPrint]
-	ld l, a
-	ld a, [wAddrOfBoxToPrint + 1]
-	ld h, a
-	add hl, de
-	ld e, l
-	ld d, h
-	pop hl
-	ret
-
-Printer_PlaceTopBorder: ; 849d7 (21:49d7)
-	hlcoord 0, 0
-	ld a, "┌"
-	ld [hli], a
-	ld a, "─"
-	ld c, SCREEN_WIDTH - 2
-.loop
-	ld [hli], a
-	dec c
-	jr nz, .loop
-	ld a, "┐"
-	ld [hl], a
-	ret
-
-Printer_PlaceSideBorders: ; 849e9 (21:49e9)
-	hlcoord 0, 0
-	ld de, SCREEN_WIDTH - 1
-	ld c, SCREEN_HEIGHT
-.loop
-	ld a, "│"
-	ld [hl], a
-	add hl, de
-	ld a, "│"
-	ld [hli], a
-	dec c
-	jr nz, .loop
-	ret
-
-Printer_PlaceBottomBorders: ; 849fc (21:49fc)
-	hlcoord 0, 17
-	ld a, "└"
-	ld [hli], a
-	ld a, "─"
-	ld c, SCREEN_WIDTH - 2
-.loop
-	ld [hli], a
-	dec c
-	jr nz, .loop
-	ld a, "┘"
-	ld [hl], a
-	ret
-
-Printer_PlaceEmptyBoxSlotString: ; 84a0e (21:4a0e)
-	hlcoord 2, 0
-	ld c, $6
-.loop
-	push bc
-	push hl
-	ld de, String84a25
-	call PlaceString
-	pop hl
-	ld bc, 3 * SCREEN_WIDTH
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .loop
-	ret
-; 84a25 (21:4a25)
-
-String84a25: ; 84a25
-	db "  ------@"
-; 84a2e
--- /dev/null
+++ b/engine/printer/print_party.asm
@@ -1,0 +1,364 @@
+PRINTPARTY_HP EQUS "\"◀\"" ; $71
+
+PrintPage1: ; 1dc1b0
+	hlcoord 0, 0
+	decoord 0, 0, wPrinterTileMapBuffer
+	ld bc, 17 * SCREEN_WIDTH
+	call CopyBytes
+	hlcoord 17, 1, wPrinterTileMapBuffer
+	ld a, $62
+	ld [hli], a
+	inc a
+	ld [hl], a
+	hlcoord 17, 2, wPrinterTileMapBuffer
+	ld a, $64
+	ld [hli], a
+	inc a
+	ld [hl], a
+	hlcoord 1, 9, wPrinterTileMapBuffer
+	ld a, " "
+	ld [hli], a
+	ld [hl], a
+	hlcoord 1, 10, wPrinterTileMapBuffer
+	ld a, $61
+	ld [hli], a
+	ld [hl], a
+	hlcoord 2, 11, wPrinterTileMapBuffer
+	lb bc, 5, 18
+	call ClearBox
+	ld a, [wd265]
+	dec a
+	call CheckCaughtMon
+	push af
+	ld a, [wd265]
+	ld b, a
+	ld c, 1 ; get page 1
+	farcall GetDexEntryPagePointer
+	pop af
+	ld a, b
+	hlcoord 1, 11, wPrinterTileMapBuffer
+	call nz, FarString
+	hlcoord 19, 0, wPrinterTileMapBuffer
+	ld [hl], $35
+	ld de, SCREEN_WIDTH
+	add hl, de
+	ld b, $f
+.column_loop
+	ld [hl], $37
+	add hl, de
+	dec b
+	jr nz, .column_loop
+	ld [hl], $3a
+	ret
+; 1dc213
+
+PrintPage2: ; 1dc213
+	hlcoord 0, 0, wPrinterTileMapBuffer
+	ld bc, 8 * SCREEN_WIDTH
+	ld a, " "
+	call ByteFill
+	hlcoord 0, 0, wPrinterTileMapBuffer
+	ld a, $36
+	ld b, 6
+	call .FillColumn
+	hlcoord 19, 0, wPrinterTileMapBuffer
+	ld a, $37
+	ld b, 6
+	call .FillColumn
+	hlcoord 0, 6, wPrinterTileMapBuffer
+	ld [hl], $38
+	inc hl
+	ld a, $39
+	ld bc, SCREEN_HEIGHT
+	call ByteFill
+	ld [hl], $3a
+	hlcoord 0, 7, wPrinterTileMapBuffer
+	ld bc, SCREEN_WIDTH
+	ld a, $32
+	call ByteFill
+	ld a, [wd265]
+	dec a
+	call CheckCaughtMon
+	push af
+	ld a, [wd265]
+	ld b, a
+	ld c, 2 ; get page 2
+	farcall GetDexEntryPagePointer
+	pop af
+	hlcoord 1, 1, wPrinterTileMapBuffer
+	ld a, b
+	call nz, FarString
+	ret
+; 1dc26a
+
+.FillColumn: ; 1dc26a
+	push de
+	ld de, SCREEN_WIDTH
+.column_loop
+	ld [hl], a
+	add hl, de
+	dec b
+	jr nz, .column_loop
+	pop de
+	ret
+; 1dc275
+
+GBPrinterStrings:
+GBPrinterString_Null: db "@"
+GBPrinterString_CheckingLink: next " CHECKING LINK...@"
+GBPrinterString_Transmitting: next "  TRANSMITTING...@"
+GBPrinterString_Printing: next "    PRINTING...@"
+GBPrinterString_PrinterError1:
+	db   " Printer Error 1"
+	next ""
+	next "Check the Game Boy"
+	next "Printer Manual."
+	db   "@"
+GBPrinterString_PrinterError2:
+	db   " Printer Error 2"
+	next ""
+	next "Check the Game Boy"
+	next "Printer Manual."
+	db   "@"
+GBPrinterString_PrinterError3:
+	db   " Printer Error 3"
+	next ""
+	next "Check the Game Boy"
+	next "Printer Manual."
+	db   "@"
+GBPrinterString_PrinterError4:
+	db   " Printer Error 4"
+	next ""
+	next "Check the Game Boy"
+	next "Printer Manual."
+	db   "@"
+; 1dc381
+
+PrintPartyMonPage1: ; 1dc381
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	xor a
+	ld [hBGMapMode], a
+	call LoadFontsBattleExtra
+
+	ld de, GBPrinterHPIcon
+	ld hl, vTiles2 tile PRINTPARTY_HP
+	lb bc, BANK(GBPrinterHPIcon), 1
+	call Request1bpp
+
+	ld de, GBPrinterLvIcon
+	ld hl, vTiles2 tile "<LV>"
+	lb bc, BANK(GBPrinterLvIcon), 1
+	call Request1bpp
+
+	ld de, StatsScreenPageTilesGFX + 14 tiles ; shiny icon
+	ld hl, vTiles2 tile "⁂"
+	lb bc, BANK(StatsScreenPageTilesGFX), 1
+	call Get2bpp
+
+	xor a
+	ld [wMonType], a
+	farcall CopyMonToTempMon
+	hlcoord 0, 7
+	ld b, 9
+	ld c, 18
+	call TextBox
+	hlcoord 8, 2
+	ld a, [wTempMonLevel]
+	call PrintLevel_Force3Digits
+	hlcoord 12, 2
+	ld [hl], PRINTPARTY_HP
+	inc hl
+	ld de, wTempMonMaxHP
+	lb bc, 2, 3
+	call PrintNum
+	ld a, [wCurPartySpecies]
+	ld [wd265], a
+	ld [wCurSpecies], a
+	ld hl, wPartyMonNicknames
+	call Function1dc50e
+	hlcoord 8, 4
+	call PlaceString
+	hlcoord 9, 6
+	ld [hl], "/"
+	call GetPokemonName
+	hlcoord 10, 6
+	call PlaceString
+	hlcoord 8, 0
+	ld [hl], "№"
+	inc hl
+	ld [hl], "."
+	inc hl
+	ld de, wd265
+	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
+	call PrintNum
+	hlcoord 1, 9
+	ld de, String1dc550
+	call PlaceString
+	ld hl, wPartyMonOT
+	call Function1dc50e
+	hlcoord 4, 9
+	call PlaceString
+	hlcoord 1, 11
+	ld de, String1dc559
+	call PlaceString
+	hlcoord 4, 11
+	ld de, wTempMonID
+	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+	call PrintNum
+	hlcoord 1, 14
+	ld de, String1dc554
+	call PlaceString
+	hlcoord 7, 14
+	ld a, [wTempMonMoves + 0]
+	call Function1dc51a
+	call Function1dc52c
+	ld hl, wTempMonDVs
+	predef GetUnownLetter
+	ld hl, wBoxAlignment
+	xor a
+	ld [hl], a
+	ld a, [wCurPartySpecies]
+	cp UNOWN
+	jr z, .asm_1dc469
+	inc [hl]
+
+.asm_1dc469
+	hlcoord 0, 0
+	call _PrepMonFrontpic
+	call WaitBGMap
+	ld b, SCGB_STATS_SCREEN_HP_PALS
+	call GetSGBLayout
+	call SetPalettes
+	ret
+; 1dc47b
+
+PrintPartyMonPage2: ; 1dc47b
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	xor a
+	ld [hBGMapMode], a
+	call LoadFontsBattleExtra
+	xor a
+	ld [wMonType], a
+	farcall CopyMonToTempMon
+	hlcoord 0, 0
+	ld b, 15
+	ld c, 18
+	call TextBox
+	ld bc, SCREEN_WIDTH
+	decoord 0, 0
+	hlcoord 0, 1
+	call CopyBytes
+	hlcoord 7, 0
+	ld a, [wTempMonMoves + 1]
+	call Function1dc51a
+	hlcoord 7, 2
+	ld a, [wTempMonMoves + 2]
+	call Function1dc51a
+	hlcoord 7, 4
+	ld a, [wTempMonMoves + 3]
+	call Function1dc51a
+	hlcoord 7, 7
+	ld de, String1dc55d
+	call PlaceString
+	hlcoord 16, 7
+	ld de, wTempMonAttack
+	call .PrintTempMonStats
+	hlcoord 16, 9
+	ld de, wTempMonDefense
+	call .PrintTempMonStats
+	hlcoord 16, 11
+	ld de, wTempMonSpclAtk
+	call .PrintTempMonStats
+	hlcoord 16, 13
+	ld de, wTempMonSpclDef
+	call .PrintTempMonStats
+	hlcoord 16, 15
+	ld de, wTempMonSpeed
+	call .PrintTempMonStats
+	call WaitBGMap
+	ld b, SCGB_STATS_SCREEN_HP_PALS
+	call GetSGBLayout
+	call SetPalettes
+	ret
+; 1dc507
+
+.PrintTempMonStats: ; 1dc507
+	lb bc, 2, 3
+	call PrintNum
+	ret
+; 1dc50e
+
+Function1dc50e: ; 1dc50e
+	ld bc, NAME_LENGTH
+	ld a, [wCurPartyMon]
+	call AddNTimes
+	ld e, l
+	ld d, h
+	ret
+; 1dc51a
+
+Function1dc51a: ; 1dc51a
+	and a
+	jr z, .no_move
+
+	ld [wd265], a
+	call GetMoveName
+	jr .got_string
+
+.no_move
+	ld de, String1dc584
+
+.got_string
+	call PlaceString
+	ret
+; 1dc52c
+
+Function1dc52c: ; 1dc52c
+	farcall GetGender
+	ld a, " "
+	jr c, .got_gender
+	ld a, "♂"
+	jr nz, .got_gender
+	ld a, "♀"
+
+.got_gender
+	hlcoord 17, 2
+	ld [hl], a
+	ld bc, wTempMonDVs
+	farcall CheckShininess
+	ret nc
+	hlcoord 18, 2
+	ld [hl], "⁂"
+	ret
+; 1dc550
+
+String1dc550: ; 1dc550
+	db "OT/@"
+
+String1dc554: ; 1dc554
+	db "MOVE@"
+
+String1dc559: ; 1dc559
+	db "<ID>№.@"
+
+String1dc55d: ; 1dc55d
+	db   "ATTACK"
+	next "DEFENSE"
+	next "SPCL.ATK"
+	next "SPCL.DEF"
+	next "SPEED"
+	db   "@"
+
+String1dc584: ; 1dc584
+	db "------------@"
+; 1dc591
+
+GBPrinterHPIcon: ; 1dc591
+INCBIN "gfx/printer/hp.1bpp"
+
+GBPrinterLvIcon: ; 1dc599
+INCBIN "gfx/printer/lv.1bpp"
--- /dev/null
+++ b/engine/printer/printer.asm
@@ -1,0 +1,949 @@
+INCLUDE "engine/printer/printer_serial.asm"
+
+SendScreenToPrinter: ; 843f0
+.loop
+	call JoyTextDelay
+	call CheckCancelPrint
+	jr c, .cancel
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .finished
+	call PrinterJumptableIteration
+	call CheckPrinterStatus
+	call PlacePrinterStatusString
+	call DelayFrame
+	jr .loop
+
+.finished
+	and a
+	ret
+
+.cancel
+	scf
+	ret
+; 84411
+
+Printer_CleanUpAfterSend: ; 84411
+	xor a
+	ld [wPrinterConnectionOpen], a
+	ld [wPrinterOpcode], a
+	ret
+; 84419
+
+Printer_PrepareTileMapForPrint: ; 84419
+	push af
+	call Printer_StartTransmission
+	pop af
+	ld [wcbfa], a
+	call Printer_CopyTileMapToBuffer
+	ret
+; 84425
+
+Printer_ExitPrinter: ; 84425
+	call ReturnToMapFromSubmenu
+	call Printer_RestartMapMusic
+	ret
+; 8442c
+
+PrintDexEntry: ; 8442c
+	ld a, [wPrinterQueueLength]
+	push af
+
+	ld hl, vTiles1
+	ld de, FontInversed
+	lb bc, BANK(FontInversed), $80
+	call Request1bpp
+
+	xor a
+	ld [hPrinter], a
+	call Printer_PlayMusic
+
+	ld a, [rIE]
+	push af
+	xor a
+	ld [rIF], a
+	ld a, $9
+	ld [rIE], a
+
+	call Printer_StartTransmission
+	ld a, $10
+	ld [wcbfa], a
+	farcall PrintPage1
+	call ClearTileMap
+	ld a, %11100100
+	call DmgToCgbBGPals
+	call DelayFrame
+
+	ld hl, hVBlank
+	ld a, [hl]
+	push af
+	ld [hl], $4
+
+	ld a, 8 ; 16 rows
+	ld [wPrinterQueueLength], a
+	call Printer_ResetJoypadRegisters
+	call SendScreenToPrinter
+	jr c, .skip_second_page ; canceled or got an error
+
+	call Printer_CleanUpAfterSend
+	ld c, 12
+	call DelayFrames
+	xor a
+	ld [hBGMapMode], a
+
+	call Printer_StartTransmission
+	ld a, $3
+	ld [wcbfa], a
+	farcall PrintPage2
+	call Printer_ResetJoypadRegisters
+	ld a, 4
+	ld [wPrinterQueueLength], a
+	call SendScreenToPrinter
+
+.skip_second_page
+	pop af
+	ld [hVBlank], a
+	call Printer_CleanUpAfterSend
+
+	xor a
+	ld [rIF], a
+	pop af
+	ld [rIE], a
+
+	call Printer_ExitPrinter
+	ld c, 8
+.low_volume_delay_frames
+	call LowVolume
+	call DelayFrame
+	dec c
+	jr nz, .low_volume_delay_frames
+
+	pop af
+	ld [wPrinterQueueLength], a
+	ret
+; 844bc
+
+PrintPCBox: ; 844bc (21:44bc)
+	ld a, [wPrinterQueueLength]
+	push af
+	ld a, 18 / 2
+	ld [wPrinterQueueLength], a
+
+	ld a, e
+	ld [wAddrOfBoxToPrint], a
+	ld a, d
+	ld [wAddrOfBoxToPrint + 1], a
+	ld a, b
+	ld [wBankOfBoxToPrint], a
+	ld a, c
+	ld [wWhichBoxToPrint], a
+
+	xor a
+	ld [hPrinter], a
+	ld [wFinishedPrintingBox], a
+	call Printer_PlayMusic
+
+	ld a, [rIE]
+	push af
+	xor a
+	ld [rIF], a
+	ld a, %1001
+	ld [rIE], a
+
+	ld hl, hVBlank
+	ld a, [hl]
+	push af
+	ld [hl], %0100
+
+	xor a
+	ld [hBGMapMode], a
+	call PrintPCBox_Page1
+	ld a, $10 ; to be loaded to wcbfa
+	call Printer_PrepareTileMapForPrint
+	call Printer_ResetRegistersAndStartDataSend
+	jr c, .cancel
+
+	call Printer_CleanUpAfterSend
+	ld c, 12
+	call DelayFrames
+	xor a
+	ld [hBGMapMode], a
+	call PrintPCBox_Page2
+	ld a, $0 ; to be loaded to wcbfa
+	call Printer_PrepareTileMapForPrint
+	call Printer_ResetRegistersAndStartDataSend
+	jr c, .cancel
+
+	call Printer_CleanUpAfterSend
+	ld c, 12
+	call DelayFrames
+
+	xor a
+	ld [hBGMapMode], a
+	call PrintPCBox_Page3
+	ld a, $0 ; to be loaded to wcbfa
+	call Printer_PrepareTileMapForPrint
+	call Printer_ResetRegistersAndStartDataSend
+	jr c, .cancel
+
+	call Printer_CleanUpAfterSend
+	ld c, 12
+	call DelayFrames
+
+	xor a
+	ld [hBGMapMode], a
+	call PrintPCBox_Page4
+	ld a, $3 ; to be loaded to wcbfa
+	call Printer_PrepareTileMapForPrint
+	call Printer_ResetRegistersAndStartDataSend
+.cancel
+	pop af
+	ld [hVBlank], a
+	call Printer_CleanUpAfterSend
+
+	xor a
+	ld [rIF], a
+	pop af
+	ld [rIE], a
+	call Printer_ExitPrinter
+
+	pop af
+	ld [wPrinterQueueLength], a
+	ret
+
+Printer_ResetRegistersAndStartDataSend: ; 84559 (21:4559)
+	call Printer_ResetJoypadRegisters
+	call SendScreenToPrinter
+	ret
+
+PrintUnownStamp: ; 84560
+	ld a, [wPrinterQueueLength]
+	push af
+	xor a
+	ld [hPrinter], a
+	call Printer_PlayMusic
+	ld a, [rIE]
+	push af
+	xor a
+	ld [rIF], a
+	ld a, $9
+	ld [rIE], a
+	ld hl, hVBlank
+	ld a, [hl]
+	push af
+	ld [hl], $4
+	xor a
+	ld [hBGMapMode], a
+	call LoadTileMapToTempTileMap
+	farcall PlaceUnownPrinterFrontpic
+	ld a, $0 ; to be loaded to wcbfa
+	call Printer_PrepareTileMapForPrint
+	call Call_LoadTempTileMapToTileMap
+	call Printer_ResetJoypadRegisters
+	ld a, 18 / 2
+	ld [wPrinterQueueLength], a
+.loop
+	call JoyTextDelay
+	call CheckCancelPrint
+	jr c, .done
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .done
+	call PrinterJumptableIteration
+	ld a, [wJumptableIndex]
+	cp $2
+	jr nc, .check_status
+	ld a, 6 / 2
+	ld [wPrinterRowIndex], a
+
+.check_status
+	call CheckPrinterStatus
+	call PlacePrinterStatusString
+	call DelayFrame
+	jr .loop
+
+.done
+	pop af
+	ld [hVBlank], a
+	call Printer_CleanUpAfterSend
+	call Call_LoadTempTileMapToTileMap
+	xor a
+	ld [rIF], a
+	pop af
+	ld [rIE], a
+	pop af
+	ld [wPrinterQueueLength], a
+	ret
+; 845d4
+
+PrintMail: ; 845d4
+	call PrintMail_
+	call Printer_ExitPrinter
+	ret
+; 845db
+
+PrintMail_: ; 845db
+	ld a, [wPrinterQueueLength]
+	push af
+	xor a
+	ld [hPrinter], a
+	call Printer_PlayMusic
+
+	ld a, [rIE]
+	push af
+	xor a
+	ld [rIF], a
+	ld a, %1001
+	ld [rIE], a
+
+	xor a
+	ld [hBGMapMode], a
+
+	ld a, $13 ; to be loaded to wcbfa
+	call Printer_PrepareTileMapForPrint
+	ld hl, hVBlank
+	ld a, [hl]
+	push af
+	ld [hl], %0100
+
+	ld a, 18 / 2
+	ld [wPrinterQueueLength], a
+	call SendScreenToPrinter
+
+	pop af
+	ld [hVBlank], a
+	call Printer_CleanUpAfterSend
+	call Printer_CopyBufferToTileMap
+
+	xor a
+	ld [rIF], a
+	pop af
+	ld [rIE], a
+
+	pop af
+	ld [wPrinterQueueLength], a
+	ret
+; 8461a
+
+PrintPartymon: ; 8461a
+	ld a, [wPrinterQueueLength]
+	push af
+	xor a
+	ld [hPrinter], a
+	call Printer_PlayMusic
+
+	ld a, [rIE]
+	push af
+	xor a
+	ld [rIF], a
+	ld a, %1001
+	ld [rIE], a
+
+	xor a
+	ld [hBGMapMode], a
+	farcall PrintPartyMonPage1
+	ld a, $10 ; to be loaded to wcbfa
+	call Printer_PrepareTileMapForPrint
+
+	ld hl, hVBlank
+	ld a, [hl]
+	push af
+	ld [hl], %0100
+
+	ld a, 16 / 2
+	ld [wPrinterQueueLength], a
+	call Printer_ResetJoypadRegisters
+	call SendScreenToPrinter
+	jr c, .cancel
+
+	call Printer_CleanUpAfterSend
+	ld c, 12
+	call DelayFrames
+
+	xor a
+	ld [hBGMapMode], a
+	farcall PrintPartyMonPage2
+	ld a, $3 ; to be loaded to wcbfa
+	call Printer_PrepareTileMapForPrint
+
+	ld a, 18 / 2
+	ld [wPrinterQueueLength], a
+	call Printer_ResetJoypadRegisters
+	call SendScreenToPrinter
+.cancel
+	pop af
+	ld [hVBlank], a
+	call Printer_CleanUpAfterSend
+
+	call Printer_CopyBufferToTileMap
+	xor a
+	ld [rIF], a
+	pop af
+	ld [rIE], a
+	call Printer_ExitPrinter
+
+	pop af
+	ld [wPrinterQueueLength], a
+	ret
+; 84688
+
+_PrintDiploma: ; 84688
+	ld a, [wPrinterQueueLength]
+	push af
+
+	farcall PlaceDiplomaOnScreen
+
+	xor a
+	ld [hPrinter], a
+	call Printer_PlayMusic
+
+	ld a, [rIE]
+	push af
+	xor a
+	ld [rIF], a
+	ld a, %1001
+	ld [rIE], a
+
+	ld hl, hVBlank
+	ld a, [hl]
+	push af
+	ld [hl], %0100
+
+	ld a, $10 ; to be loaded to wcbfa
+	call Printer_PrepareTileMapForPrint
+	call Printer_ResetJoypadRegisters
+
+	ld a, 18 / 2
+	ld [wPrinterQueueLength], a
+	call SendScreenToPrinter
+	jr c, .cancel
+	call Printer_CleanUpAfterSend
+	ld c, 12
+	call DelayFrames
+
+	call LoadTileMapToTempTileMap
+	xor a
+	ld [hBGMapMode], a
+
+	farcall PrintDiplomaPage2
+
+	ld a, $3 ; to be loaded to wcbfa
+	call Printer_PrepareTileMapForPrint
+	call Call_LoadTempTileMapToTileMap
+	call Printer_ResetJoypadRegisters
+
+	ld a, 18 / 2
+	ld [wPrinterQueueLength], a
+	call SendScreenToPrinter
+.cancel
+	pop af
+	ld [hVBlank], a
+	call Printer_CleanUpAfterSend
+
+	xor a
+	ld [rIF], a
+	pop af
+	ld [rIE], a
+	call Printer_ExitPrinter
+
+	pop af
+	ld [wPrinterQueueLength], a
+	ret
+; 846f6
+
+CheckCancelPrint: ; 846f6
+	ld a, [hJoyDown]
+	and B_BUTTON
+	jr nz, .pressed_b
+	and a
+	ret
+
+.pressed_b
+	ld a, [wca80]
+	cp $c
+	jr nz, .cancel
+.loop
+	ld a, [wPrinterOpcode]
+	and a
+	jr nz, .loop
+	ld a, $16 ; cancel
+	ld [wPrinterOpcode], a
+	ld a, $88
+	ld [rSB], a
+	ld a, $1
+	ld [rSC], a
+	ld a, $81
+	ld [rSC], a
+.loop2
+	ld a, [wPrinterOpcode]
+	and a
+	jr nz, .loop2
+
+.cancel
+	ld a, $1
+	ld [hPrinter], a
+	scf
+	ret
+; 84728
+
+Printer_CopyTileMapToBuffer: ; 84728
+	hlcoord 0, 0
+	ld de, wPrinterTileMapBuffer
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	call CopyBytes
+	ret
+; 84735
+
+Printer_CopyBufferToTileMap: ; 84735
+	ld hl, wPrinterTileMapBuffer
+	decoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	call CopyBytes
+	ret
+; 84742
+
+Printer_ResetJoypadRegisters: ; 84742
+	xor a
+	ld [hJoyReleased], a
+	ld [hJoyPressed], a
+	ld [hJoyDown], a
+	ld [hJoyLast], a
+	ret
+; 8474c
+
+Printer_PlayMusic: ; 8474c
+	ld de, MUSIC_PRINTER
+	call PlayMusic2
+	ret
+; 84753
+
+Printer_RestartMapMusic: ; 84753
+	call RestartMapMusic
+	ret
+; 84757
+
+CheckPrinterStatus: ; 84757
+; Check for printer errors
+; If [ca88] == -1, we're disconnected
+	ld a, [wPrinterHandshake]
+	cp -1
+	jr nz, .printer_connected
+	ld a, [wPrinterStatusFlags]
+	cp -1
+	jr z, .error_2
+.printer_connected
+; ca89 contains printer status flags
+	ld a, [wPrinterStatusFlags]
+	and %11100000
+	ret z ; no error
+
+	bit 7, a
+	jr nz, .error_1
+	bit 6, a
+	jr nz, .error_4
+	; paper error
+	ld a, PRINTER_ERROR_3
+	jr .load_text_index
+
+.error_4
+	; temperature error
+	ld a, PRINTER_ERROR_4
+	jr .load_text_index
+
+.error_1
+	; printer battery low
+	ld a, PRINTER_ERROR_1
+	jr .load_text_index
+
+.error_2
+	; connection error
+	ld a, PRINTER_ERROR_2
+.load_text_index
+	ld [wPrinterStatus], a
+	ret
+; 84785
+
+PlacePrinterStatusString: ; 84785
+; Print nonzero printer status
+	ld a, [wPrinterStatus]
+	and a
+	ret z
+	push af
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 0, 5
+	lb bc, 10, 18
+	call TextBox
+	pop af
+	ld e, a
+	ld d, 0
+	ld hl, PrinterStatusStringPointers
+	add hl, de
+	add hl, de
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	hlcoord 1, 7
+	ld a, BANK(GBPrinterStrings)
+	call FarString
+	hlcoord 2, 15
+	ld de, String_PressBToCancel
+	call PlaceString
+	ld a, $1
+	ld [hBGMapMode], a
+	xor a
+	ld [wPrinterStatus], a
+	ret
+; 847bd
+
+Unreferenced_Function847bd: ; 847bd
+	ld a, [wPrinterStatus]
+	and a
+	ret z
+	push af
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 2, 4
+	lb bc, 13, 16
+	call ClearBox
+	pop af
+	ld e, a
+	ld d, 0
+	ld hl, PrinterStatusStringPointers
+	add hl, de
+	add hl, de
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	hlcoord 4, 7
+	ld a, BANK(GBPrinterStrings)
+	call FarString
+	hlcoord 4, 15
+	ld de, String_PressBToCancel
+	call PlaceString
+	ld a, $1
+	ld [hBGMapMode], a
+	xor a
+	ld [wPrinterStatus], a
+	ret
+; 847f5
+
+String_PressBToCancel:
+	db "Press B to Cancel@"
+; 84807
+
+PrinterStatusStringPointers: ; 84807
+	dw GBPrinterString_Null ; @
+	dw GBPrinterString_CheckingLink ; CHECKING LINK
+	dw GBPrinterString_Transmitting ; TRANSMITTING
+	dw GBPrinterString_Printing ; PRINTING
+	dw GBPrinterString_PrinterError1 ; error 1
+	dw GBPrinterString_PrinterError2 ; error 2
+	dw GBPrinterString_PrinterError3 ; error 3
+	dw GBPrinterString_PrinterError4 ; error 4
+; 84817
+
+PrintPCBox_Page1: ; 84817 (21:4817)
+	xor a
+	ld [wWhichBoxMonToPrint], a
+	hlcoord 0, 0
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	ld a, " "
+	call ByteFill
+	call Printer_PlaceEmptyBoxSlotString
+
+	hlcoord 0, 0
+	ld bc, 9 * SCREEN_WIDTH
+	ld a, " "
+	call ByteFill
+
+	call Printer_PlaceSideBorders
+	call Printer_PlaceTopBorder
+
+	hlcoord 4, 3
+	ld de, .String_PokemonList
+	call PlaceString
+
+	ld a, [wWhichBoxToPrint]
+	ld bc, BOX_NAME_LENGTH
+	ld hl, wBoxNames
+	call AddNTimes
+	ld d, h
+	ld e, l
+	hlcoord 6, 5
+	call PlaceString
+	ld a, 1
+	call Printer_GetBoxMonSpecies
+	hlcoord 2, 9
+	ld c, 3
+	call Printer_PrintBoxListSegment
+	ret
+; 84865 (21:4865)
+
+.String_PokemonList:
+	db "#MON LIST@"
+; 8486f
+
+PrintPCBox_Page2: ; 8486f (21:486f)
+	hlcoord 0, 0
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	ld a, " "
+	call ByteFill
+	call Printer_PlaceEmptyBoxSlotString
+	call Printer_PlaceSideBorders
+	ld a, [wFinishedPrintingBox]
+	and a
+	ret nz
+	ld a, 4
+	call Printer_GetBoxMonSpecies
+	hlcoord 2, 0
+	ld c, 6
+	call Printer_PrintBoxListSegment
+	ret
+
+PrintPCBox_Page3: ; 84893 (21:4893)
+	hlcoord 0, 0
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	ld a, " "
+	call ByteFill
+	call Printer_PlaceEmptyBoxSlotString
+	call Printer_PlaceSideBorders
+	ld a, [wFinishedPrintingBox]
+	and a
+	ret nz
+	ld a, 10
+	call Printer_GetBoxMonSpecies
+	hlcoord 2, 0
+	ld c, 6
+	call Printer_PrintBoxListSegment
+	ret
+
+PrintPCBox_Page4: ; 848b7 (21:48b7)
+	hlcoord 0, 0
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	ld a, " "
+	call ByteFill
+	call Printer_PlaceEmptyBoxSlotString
+	hlcoord 1, 15
+	lb bc, 2, 18
+	call ClearBox
+	call Printer_PlaceSideBorders
+	call Printer_PlaceBottomBorders
+	ld a, [wFinishedPrintingBox]
+	and a
+	ret nz
+	ld a, 16
+	call Printer_GetBoxMonSpecies
+	hlcoord 2, 0
+	ld c, 5
+	call Printer_PrintBoxListSegment
+	ret
+
+Printer_PrintBoxListSegment: ; 848e7 (21:48e7)
+	ld a, [wBankOfBoxToPrint]
+	call GetSRAMBank
+.loop
+	ld a, c
+	and a
+	jp z, .max_length
+	dec c
+	ld a, [de]
+	cp $ff
+	jp z, .finish
+	ld [wd265], a
+	ld [wCurPartySpecies], a
+
+	push bc
+	push hl
+	push de
+
+	push hl
+	ld bc, 16
+	ld a, " "
+	call ByteFill
+	pop hl
+
+	push hl
+	call GetBasePokemonName
+	pop hl
+
+	push hl
+	call PlaceString
+	ld a, [wCurPartySpecies]
+	cp EGG
+	pop hl
+	jr z, .ok2
+
+	ld bc, MON_NAME_LENGTH
+	add hl, bc
+	call Printer_GetMonGender
+	ld bc, SCREEN_WIDTH - MON_NAME_LENGTH
+	add hl, bc
+	ld a, "/"
+	ld [hli], a
+
+	push hl
+	ld bc, 14
+	ld a, " "
+	call ByteFill
+	pop hl
+
+	push hl
+	ld a, [wAddrOfBoxToPrint]
+	ld l, a
+	ld a, [wAddrOfBoxToPrint + 1]
+	ld h, a
+	ld bc, sBoxMonNicknames - sBox
+	add hl, bc
+	ld bc, MON_NAME_LENGTH
+	ld a, [wWhichBoxMonToPrint]
+	call AddNTimes
+	ld e, l
+	ld d, h
+	pop hl
+
+	push hl
+	call PlaceString
+	pop hl
+
+	ld bc, MON_NAME_LENGTH
+	add hl, bc
+	push hl
+	ld a, [wAddrOfBoxToPrint]
+	ld l, a
+	ld a, [wAddrOfBoxToPrint + 1]
+	ld h, a
+	ld bc, 2 + MONS_PER_BOX + MON_LEVEL
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, [wWhichBoxMonToPrint]
+	call AddNTimes
+	ld a, [hl]
+	pop hl
+	call PrintLevel_Force3Digits
+.ok2
+	ld hl, wWhichBoxMonToPrint
+	inc [hl]
+	pop de
+	pop hl
+	ld bc, 3 * SCREEN_WIDTH
+	add hl, bc
+	pop bc
+	inc de
+	jp .loop
+
+.finish
+	ld a, $1
+	ld [wFinishedPrintingBox], a
+.max_length
+	call CloseSRAM
+	ret
+
+Printer_GetMonGender: ; 8498a (21:498a)
+	push hl
+	ld a, [wAddrOfBoxToPrint]
+	ld l, a
+	ld a, [wAddrOfBoxToPrint + 1]
+	ld h, a
+	ld bc, $2b
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, [wWhichBoxMonToPrint]
+	call AddNTimes
+	ld de, wTempMonDVs
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hli]
+	ld [de], a
+	ld a, [wWhichBoxMonToPrint]
+	ld [wCurPartyMon], a
+	ld a, TEMPMON
+	ld [wMonType], a
+	farcall GetGender
+	ld a, " "
+	jr c, .got_gender
+	ld a, "♂"
+	jr nz, .got_gender
+	ld a, "♀"
+.got_gender
+	pop hl
+	ld [hli], a
+	ret
+
+Printer_GetBoxMonSpecies: ; 849c6 (21:49c6)
+	push hl
+	ld e, a
+	ld d, $0
+	ld a, [wAddrOfBoxToPrint]
+	ld l, a
+	ld a, [wAddrOfBoxToPrint + 1]
+	ld h, a
+	add hl, de
+	ld e, l
+	ld d, h
+	pop hl
+	ret
+
+Printer_PlaceTopBorder: ; 849d7 (21:49d7)
+	hlcoord 0, 0
+	ld a, "┌"
+	ld [hli], a
+	ld a, "─"
+	ld c, SCREEN_WIDTH - 2
+.loop
+	ld [hli], a
+	dec c
+	jr nz, .loop
+	ld a, "┐"
+	ld [hl], a
+	ret
+
+Printer_PlaceSideBorders: ; 849e9 (21:49e9)
+	hlcoord 0, 0
+	ld de, SCREEN_WIDTH - 1
+	ld c, SCREEN_HEIGHT
+.loop
+	ld a, "│"
+	ld [hl], a
+	add hl, de
+	ld a, "│"
+	ld [hli], a
+	dec c
+	jr nz, .loop
+	ret
+
+Printer_PlaceBottomBorders: ; 849fc (21:49fc)
+	hlcoord 0, 17
+	ld a, "└"
+	ld [hli], a
+	ld a, "─"
+	ld c, SCREEN_WIDTH - 2
+.loop
+	ld [hli], a
+	dec c
+	jr nz, .loop
+	ld a, "┘"
+	ld [hl], a
+	ret
+
+Printer_PlaceEmptyBoxSlotString: ; 84a0e (21:4a0e)
+	hlcoord 2, 0
+	ld c, $6
+.loop
+	push bc
+	push hl
+	ld de, String84a25
+	call PlaceString
+	pop hl
+	ld bc, 3 * SCREEN_WIDTH
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .loop
+	ret
+; 84a25 (21:4a25)
+
+String84a25: ; 84a25
+	db "  ------@"
+; 84a2e
--- /dev/null
+++ b/engine/printer/printer_serial.asm
@@ -1,0 +1,640 @@
+Printer_StartTransmission: ; 84000
+	ld hl, wGameboyPrinterRAM
+	ld bc, wGameboyPrinterRAMEnd - wGameboyPrinterRAM
+	xor a
+	call Printer_ByteFill
+	xor a
+	ld [rSB], a
+	ld [rSC], a
+	ld [wPrinterOpcode], a
+	ld hl, wPrinterConnectionOpen
+	set 0, [hl]
+	ld a, [wGBPrinter]
+	ld [wGBPrinterSettings], a
+	xor a
+	ld [wJumptableIndex], a
+	ret
+; 84022
+
+PrinterJumptableIteration: ; 84022
+	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
+; 84031
+
+.Jumptable: ; 84031 (21:4031)
+	dw Print_InitPrinterHandshake ; 00
+	dw Printer_CheckConnectionStatus ; 01
+	dw Printer_WaitSerial ; 02
+	dw Printer_StartTransmittingTilemap ; 03
+	dw Printer_TransmissionLoop ; 04
+	dw Printer_WaitSerialAndLoopBack2 ; 05
+
+	dw Printer_EndTilemapTransmission ; 06
+	dw Printer_TransmissionLoop ; 07
+	dw Printer_WaitSerial ; 08
+	dw Printer_SignalSendHeader ; 09
+	dw Printer_TransmissionLoop ; 0a
+	dw Printer_WaitSerial ; 0b
+	dw Printer_WaitUntilFinished ; 0c
+	dw Printer_Quit ; 0d
+
+	dw Printer_NextSection_ ; 0e
+	dw Printer_WaitSerial ; 0f
+	dw Printer_SignalLoopBack ; 10
+	dw Printer_SectionOne ; 11
+	dw Printer_WaitLoopBack ; 12
+	dw Printer_WaitLoopBack_ ; 13
+
+Printer_NextSection: ; 84059 (21:4059)
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+Printer_PrevSection: ; 8405e (21:405e)
+	ld hl, wJumptableIndex
+	dec [hl]
+	ret
+
+Printer_Quit: ; 84063 (21:4063)
+	xor a
+	ld [wPrinterStatusFlags], a
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+Printer_NextSection_: ; 8406d (21:406d)
+	call Printer_NextSection
+	ret
+
+Printer_SectionOne: ; 84071 (21:4071)
+	ld a, $1
+	ld [wJumptableIndex], a
+	ret
+
+Print_InitPrinterHandshake: ; 84077 (21:4077)
+	call Printer_ResetData
+	ld hl, PrinterDataPacket1
+	call Printer_CopyPacket
+	xor a
+	ld [wPrinterSendByteCounter], a
+	ld [wPrinterSendByteCounter + 1], a
+	ld a, [wPrinterQueueLength]
+	ld [wPrinterRowIndex], a
+	call Printer_NextSection
+	call Printer_WaitHandshake
+	ld a, PRINTER_STATUS_CHECKING
+	ld [wPrinterStatus], a
+	ret
+
+Printer_StartTransmittingTilemap: ; 84099 (21:4099)
+	call Printer_ResetData
+	; check ???
+	ld hl, wPrinterRowIndex
+	ld a, [hl]
+	and a
+	jr z, Printer_EndTilemapTransmission
+	; send packet 3
+	ld hl, PrinterDataPacket3 ; signal start of transmission
+	call Printer_CopyPacket
+	; prepare to send 40 tiles
+	call Printer_Convert2RowsTo2bpp
+	ld a, LOW(40 tiles)
+	ld [wPrinterSendByteCounter], a
+	ld a, HIGH(40 tiles)
+	ld [wPrinterSendByteCounter + 1], a
+	; compute the checksum
+	call Printer_ComputeChecksum
+	call Printer_NextSection
+	call Printer_WaitHandshake
+	ld a, PRINTER_STATUS_TRANSMITTING
+	ld [wPrinterStatus], a
+	ret
+
+Printer_EndTilemapTransmission: ; 840c5 (21:40c5)
+	; ensure that we go from here to routine 7
+	ld a, $6
+	ld [wJumptableIndex], a
+	; send packet 4
+	ld hl, PrinterDataPacket4 ; signal no transmission
+	call Printer_CopyPacket
+	; send no tile data
+	xor a
+	ld [wPrinterSendByteCounter], a
+	ld [wPrinterSendByteCounter + 1], a
+	call Printer_NextSection
+	call Printer_WaitHandshake
+	ret
+
+Printer_SignalSendHeader: ; 840de (21:40de)
+	call Printer_ResetData
+	ld hl, PrinterDataPacket2 ; signal request print
+	call Printer_CopyPacket
+	; prepare to send 1 tile
+	call Printer_StageHeaderForSend
+	ld a, LOW(4)
+	ld [wPrinterSendByteCounter], a
+	ld a, HIGH(4)
+	ld [wPrinterSendByteCounter + 1], a
+	; compute the checksum
+	call Printer_ComputeChecksum
+	call Printer_NextSection
+	call Printer_WaitHandshake
+	ld a, PRINTER_STATUS_PRINTING
+	ld [wPrinterStatus], a
+	ret
+
+Printer_SignalLoopBack: ; 84103 (21:4103)
+	call Printer_ResetData
+	; send packet 1
+	ld hl, PrinterDataPacket1 ; signal no transmission
+	call Printer_CopyPacket
+	; send no tile data
+	xor a
+	ld [wPrinterSendByteCounter], a
+	ld [wPrinterSendByteCounter + 1], a
+	ld a, [wPrinterQueueLength]
+	ld [wPrinterRowIndex], a
+	call Printer_NextSection
+	call Printer_WaitHandshake
+	ret
+
+Printer_WaitSerial: ; 84120 (21:4120)
+	ld hl, wPrinterSerialFrameDelay
+	inc [hl]
+	ld a, [hl]
+	cp $6
+	ret c
+	xor a
+	ld [hl], a
+	call Printer_NextSection
+	ret
+
+Printer_WaitSerialAndLoopBack2: ; 8412e (21:412e)
+	ld hl, wPrinterSerialFrameDelay
+	inc [hl]
+	ld a, [hl]
+	cp $6
+	ret c
+	xor a
+	ld [hl], a
+	ld hl, wPrinterRowIndex
+	dec [hl]
+	call Printer_PrevSection
+	call Printer_PrevSection
+	ret
+
+Printer_CheckConnectionStatus: ; 84143 (21:4143)
+	ld a, [wPrinterOpcode]
+	and a
+	ret nz
+	ld a, [wPrinterHandshake]
+	cp $ff
+	jr nz, .printer_connected
+	ld a, [wPrinterStatusFlags]
+	cp $ff
+	jr z, .printer_error
+
+.printer_connected
+	ld a, [wPrinterHandshake]
+	cp $81
+	jr nz, .printer_error
+	ld a, [wPrinterStatusFlags]
+	cp $0
+	jr nz, .printer_error
+	ld hl, wPrinterConnectionOpen
+	set 1, [hl]
+	ld a, $5
+	ld [wHandshakeFrameDelay], a
+	call Printer_NextSection
+	ret
+
+.printer_error
+	ld a, $ff
+	ld [wPrinterHandshake], a
+	ld [wPrinterStatusFlags], a
+	ld a, $e
+	ld [wJumptableIndex], a
+	ret
+
+Printer_TransmissionLoop: ; 84180 (21:4180)
+	ld a, [wPrinterOpcode]
+	and a
+	ret nz
+	ld a, [wPrinterStatusFlags]
+	and $f0
+	jr nz, .enter_wait_loop
+	ld a, [wPrinterStatusFlags]
+	and $1
+	jr nz, .cycle_back
+	call Printer_NextSection
+	ret
+
+.cycle_back
+	call Printer_PrevSection
+	ret
+
+.enter_wait_loop
+	ld a, $12 ; Printer_WaitLoopBack
+	ld [wJumptableIndex], a
+	ret
+
+Printer_WaitUntilFinished: ; 841a1 (21:41a1)
+	ld a, [wPrinterOpcode]
+	and a
+	ret nz
+	ld a, [wPrinterStatusFlags]
+	and $f3
+	ret nz
+	call Printer_NextSection
+	ret
+
+Printer_WaitLoopBack: ; 841b0 (21:41b0)
+	call Printer_NextSection
+Printer_WaitLoopBack_: ; 841b3 (21:41b3)
+	ld a, [wPrinterOpcode]
+	and a
+	ret nz
+	ld a, [wPrinterStatusFlags]
+	and $f0
+	ret nz
+	xor a
+	ld [wJumptableIndex], a
+	ret
+
+Printer_WaitHandshake: ; 841c3 (21:41c3)
+.loop
+	ld a, [wPrinterOpcode]
+	and a
+	jr nz, .loop
+	xor a
+	ld [wPrinterSendByteOffset], a
+	ld [wPrinterSendByteOffset + 1], a
+	ld a, $1
+	ld [wPrinterOpcode], a
+	ld a, $88
+	ld [rSB], a
+	ld a, $1
+	ld [rSC], a
+	ld a, $81
+	ld [rSC], a
+	ret
+
+Printer_CopyPacket: ; 841e2 (21:41e2)
+	ld a, [hli]
+	ld [wPrinterData], a
+	ld a, [hli]
+	ld [wPrinterData + 1], a
+	ld a, [hli]
+	ld [wPrinterData + 2], a
+	ld a, [hli]
+	ld [wPrinterData + 3], a
+	ld a, [hli]
+	ld [wPrinterChecksum], a
+	ld a, [hl]
+	ld [wPrinterChecksum + 1], a
+	ret
+
+Printer_ResetData: ; 841fb (21:41fb)
+	xor a
+	ld hl, wPrinterData
+	ld [hli], a
+	ld [hli], a
+	ld [hli], a
+	ld [hl], a
+	ld hl, wPrinterChecksum
+	ld [hli], a
+	ld [hl], a
+	xor a
+	ld [wPrinterSendByteCounter], a
+	ld [wPrinterSendByteCounter + 1], a
+	ld hl, wGameboyPrinterRAM
+	ld bc, wGameboyPrinter2bppSourceEnd - wGameboyPrinter2bppSource
+	call Printer_ByteFill
+	ret
+
+Printer_ComputeChecksum: ; 84219 (21:4219)
+	ld hl, 0
+	ld bc, 4
+	ld de, wPrinterData
+	call .ComputeChecksum
+	ld a, [wPrinterSendByteCounter]
+	ld c, a
+	ld a, [wPrinterSendByteCounter + 1]
+	ld b, a
+	ld de, wGameboyPrinterRAM
+	call .ComputeChecksum
+	ld a, l
+	ld [wPrinterChecksum], a
+	ld a, h
+	ld [wPrinterChecksum + 1], a
+	ret
+
+.ComputeChecksum: ; 8423c (21:423c)
+.loop
+	ld a, [de]
+	inc de
+	add l
+	jr nc, .no_overflow
+	inc h
+.no_overflow
+	ld l, a
+	dec bc
+	ld a, c
+	or b
+	jr nz, .loop
+	ret
+
+Printer_StageHeaderForSend: ; 84249 (21:4249)
+	ld a, $1
+	ld [wGameboyPrinter2bppSource + 0], a
+	ld a, [wcbfa]
+	ld [wGameboyPrinter2bppSource + 1], a
+	ld a, %11100100
+	ld [wGameboyPrinter2bppSource + 2], a
+	ld a, [wGBPrinterSettings]
+	ld [wGameboyPrinter2bppSource + 3], a
+	ret
+
+Printer_Convert2RowsTo2bpp: ; 84260 (21:4260)
+	; de = wPrinterTileMapBuffer + 2 * SCREEN_WIDTH * ([wPrinterQueueLength] - [wPrinterRowIndex])
+	ld a, [wPrinterRowIndex]
+	xor $ff
+	ld d, a
+	ld a, [wPrinterQueueLength]
+	inc a
+	add d
+	ld hl, wPrinterTileMapBuffer
+	ld de, 2 * SCREEN_WIDTH
+.loop1
+	and a
+	jr z, .okay1
+	add hl, de
+	dec a
+	jr .loop1
+.okay1
+	ld e, l
+	ld d, h
+	ld hl, wGameboyPrinter2bppSource
+	ld c, 2 * SCREEN_WIDTH
+.loop2
+	ld a, [de]
+	inc de
+	push bc
+	push de
+	push hl
+	; convert tile index to vram address
+	swap a
+	ld d, a
+	and $f0
+	ld e, a
+	ld a, d
+	and $f
+	ld d, a
+	and $8
+	ld a, d
+	jr nz, .vtiles_8xxx
+	or $90
+	jr .got_vtile_addr
+
+.vtiles_8xxx
+	or $80
+.got_vtile_addr
+	ld d, a
+	; copy 1 vtile to hl
+	lb bc, BANK(Printer_Convert2RowsTo2bpp), 1
+	call Request2bpp
+	pop hl
+	ld de, 1 tiles
+	add hl, de
+	pop de
+	pop bc
+	dec c
+	jr nz, .loop2
+	ret
+
+Printer_ByteFill: ; 842ab
+	push de
+	ld e, a
+.loop
+	ld [hl], e
+	inc hl
+	dec bc
+	ld a, c
+	or b
+	jr nz, .loop
+	ld a, e
+	pop de
+	ret
+; 842b7
+
+PrinterDataPacket1:
+	db  1, 0, $00, 0
+	dw 1
+PrinterDataPacket2:
+	db  2, 0, $04, 0
+	dw 0
+PrinterDataPacket3:
+	db  4, 0, $80, 2
+	dw 0
+PrinterDataPacket4:
+	db  4, 0, $00, 0
+	dw 4
+PrinterDataPacket5: ; unused
+	db  8, 0, $00, 0
+	dw 8
+PrinterDataPacket6: ; unused
+	db 15, 0, $00, 0
+	dw 15
+; 842db
+
+_PrinterReceive:: ; 842db
+	ld a, [wPrinterOpcode]
+	add a
+	ld e, a
+	ld d, 0
+	ld hl, .Jumptable
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+; 842ea
+
+.Jumptable: ; 842ea (21:42ea)
+	dw Printer_DoNothing ; 00
+
+	dw Printer_Send0x33 ; 01
+	dw Printer_SendPrinterData1 ; 02
+	dw Printer_SendPrinterData2 ; 03
+	dw Printer_SendPrinterData3 ; 04
+	dw Printer_SendPrinterData4 ; 05
+	dw Printer_SendNextByte ; 06
+	dw Printer_SendwPrinterChecksumLo ; 07
+	dw Printer_SendwPrinterChecksumHi ; 08
+	dw Printer_Send0x00 ; 09
+	dw Printer_ReceiveTowPrinterHandshakeAndSend0x00 ; 0a
+	dw Printer_ReceiveTowPrinterStatusFlagsAndExitSendLoop ; 0b
+
+	dw Printer_Send0x33 ; 0c triggered by AskSerial
+	dw Printer_Send0x0f ; 0d
+	dw Printer_Send0x00_ ; 0e
+	dw Printer_Send0x00_ ; 0f
+	dw Printer_Send0x00_ ; 10
+	dw Printer_Send0x0f ; 11
+	dw Printer_Send0x00_ ; 12
+	dw Printer_Send0x00 ; 13
+	dw Printer_ReceiveTowPrinterHandshakeAndSend0x00 ; 14
+	dw Printer_ReceiveTowPrinterStatusFlagsAndExitSendLoop_ ; 15
+
+	dw Printer_Send0x33 ; 16 triggered by pressing B
+	dw Printer_Send0x08 ; 17
+	dw Printer_Send0x00_ ; 18
+	dw Printer_Send0x00_ ; 19
+	dw Printer_Send0x00_ ; 1a
+	dw Printer_Send0x08 ; 1b
+	dw Printer_Send0x00_ ; 1c
+	dw Printer_Send0x00 ; 1d
+	dw Printer_ReceiveTowPrinterHandshakeAndSend0x00 ; 1e
+	dw Printer_ReceiveTowPrinterStatusFlagsAndExitSendLoop ; 1f
+
+Printer_NextInstruction: ; 8432a (21:432a)
+	ld hl, wPrinterOpcode
+	inc [hl]
+	ret
+
+Printer_DoNothing: ; 8432f (21:432f)
+	ret
+
+Printer_Send0x33: ; 84330 (21:4330)
+	ld a, $33
+	call Printer_SerialSend
+	call Printer_NextInstruction
+	ret
+
+Printer_SendPrinterData1: ; 84339 (21:4339)
+	ld a, [wPrinterData]
+	call Printer_SerialSend
+	call Printer_NextInstruction
+	ret
+
+Printer_SendPrinterData2: ; 84343 (21:4343)
+	ld a, [wPrinterData + 1]
+	call Printer_SerialSend
+	call Printer_NextInstruction
+	ret
+
+Printer_SendPrinterData3: ; 8434d (21:434d)
+	ld a, [wPrinterData + 2]
+	call Printer_SerialSend
+	call Printer_NextInstruction
+	ret
+
+Printer_SendPrinterData4: ; 84357 (21:4357)
+	ld a, [wPrinterData + 3]
+	call Printer_SerialSend
+	call Printer_NextInstruction
+	ret
+
+Printer_SendNextByte: ; 84361 (21:4361)
+	; decrement 16-bit counter
+	ld hl, wPrinterSendByteCounter
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+	or d
+	jr z, .done
+	dec de
+	ld [hl], d
+	dec hl
+	ld [hl], e
+
+	ld a, [wPrinterSendByteOffset]
+	ld e, a
+	ld a, [wPrinterSendByteOffset + 1]
+	ld d, a
+	ld hl, wGameboyPrinterRAM
+	add hl, de
+	inc de
+	ld a, e
+	ld [wPrinterSendByteOffset], a
+	ld a, d
+	ld [wPrinterSendByteOffset + 1], a
+	ld a, [hl]
+	call Printer_SerialSend
+	ret
+
+.done
+	call Printer_NextInstruction
+Printer_SendwPrinterChecksumLo: ; 8438b (21:438b)
+	ld a, [wPrinterChecksum]
+	call Printer_SerialSend
+	call Printer_NextInstruction
+	ret
+
+Printer_SendwPrinterChecksumHi: ; 84395 (21:4395)
+	ld a, [wPrinterChecksum + 1]
+	call Printer_SerialSend
+	call Printer_NextInstruction
+	ret
+
+Printer_Send0x00: ; 8439f (21:439f)
+	ld a, $0
+	call Printer_SerialSend
+	call Printer_NextInstruction
+	ret
+
+Printer_ReceiveTowPrinterHandshakeAndSend0x00: ; 843a8 (21:43a8)
+	ld a, [rSB]
+	ld [wPrinterHandshake], a
+	ld a, $0
+	call Printer_SerialSend
+	call Printer_NextInstruction
+	ret
+
+Printer_ReceiveTowPrinterStatusFlagsAndExitSendLoop: ; 843b6 (21:43b6)
+	ld a, [rSB]
+	ld [wPrinterStatusFlags], a
+	xor a
+	ld [wPrinterOpcode], a
+	ret
+
+Printer_Send0x0f: ; 843c0 (21:43c0)
+	ld a, $f
+	call Printer_SerialSend
+	call Printer_NextInstruction
+	ret
+
+Printer_Send0x00_: ; 843c9 (21:43c9)
+	ld a, $0
+	call Printer_SerialSend
+	call Printer_NextInstruction
+	ret
+
+Printer_Send0x08: ; 843d2 (21:43d2)
+	ld a, $8
+	call Printer_SerialSend
+	call Printer_NextInstruction
+	ret
+
+Printer_SerialSend: ; 843db (21:43db)
+	ld [rSB], a
+	ld a, $1 ; switch to internal clock
+	ld [rSC], a
+	ld a, $81 ; start transfer
+	ld [rSC], a
+	ret
+
+Printer_ReceiveTowPrinterStatusFlagsAndExitSendLoop_: ; 843e6 (21:43e6)
+	ld a, [rSB]
+	ld [wPrinterStatusFlags], a
+	xor a
+	ld [wPrinterOpcode], a
+	ret
--- a/engine/printer_serial.asm
+++ /dev/null
@@ -1,640 +1,0 @@
-Printer_StartTransmission: ; 84000
-	ld hl, wGameboyPrinterRAM
-	ld bc, wGameboyPrinterRAMEnd - wGameboyPrinterRAM
-	xor a
-	call Printer_ByteFill
-	xor a
-	ld [rSB], a
-	ld [rSC], a
-	ld [wPrinterOpcode], a
-	ld hl, wPrinterConnectionOpen
-	set 0, [hl]
-	ld a, [wGBPrinter]
-	ld [wGBPrinterSettings], a
-	xor a
-	ld [wJumptableIndex], a
-	ret
-; 84022
-
-PrinterJumptableIteration: ; 84022
-	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
-; 84031
-
-.Jumptable: ; 84031 (21:4031)
-	dw Print_InitPrinterHandshake ; 00
-	dw Printer_CheckConnectionStatus ; 01
-	dw Printer_WaitSerial ; 02
-	dw Printer_StartTransmittingTilemap ; 03
-	dw Printer_TransmissionLoop ; 04
-	dw Printer_WaitSerialAndLoopBack2 ; 05
-
-	dw Printer_EndTilemapTransmission ; 06
-	dw Printer_TransmissionLoop ; 07
-	dw Printer_WaitSerial ; 08
-	dw Printer_SignalSendHeader ; 09
-	dw Printer_TransmissionLoop ; 0a
-	dw Printer_WaitSerial ; 0b
-	dw Printer_WaitUntilFinished ; 0c
-	dw Printer_Quit ; 0d
-
-	dw Printer_NextSection_ ; 0e
-	dw Printer_WaitSerial ; 0f
-	dw Printer_SignalLoopBack ; 10
-	dw Printer_SectionOne ; 11
-	dw Printer_WaitLoopBack ; 12
-	dw Printer_WaitLoopBack_ ; 13
-
-Printer_NextSection: ; 84059 (21:4059)
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-Printer_PrevSection: ; 8405e (21:405e)
-	ld hl, wJumptableIndex
-	dec [hl]
-	ret
-
-Printer_Quit: ; 84063 (21:4063)
-	xor a
-	ld [wPrinterStatusFlags], a
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-Printer_NextSection_: ; 8406d (21:406d)
-	call Printer_NextSection
-	ret
-
-Printer_SectionOne: ; 84071 (21:4071)
-	ld a, $1
-	ld [wJumptableIndex], a
-	ret
-
-Print_InitPrinterHandshake: ; 84077 (21:4077)
-	call Printer_ResetData
-	ld hl, PrinterDataPacket1
-	call Printer_CopyPacket
-	xor a
-	ld [wPrinterSendByteCounter], a
-	ld [wPrinterSendByteCounter + 1], a
-	ld a, [wPrinterQueueLength]
-	ld [wPrinterRowIndex], a
-	call Printer_NextSection
-	call Printer_WaitHandshake
-	ld a, PRINTER_STATUS_CHECKING
-	ld [wPrinterStatus], a
-	ret
-
-Printer_StartTransmittingTilemap: ; 84099 (21:4099)
-	call Printer_ResetData
-	; check ???
-	ld hl, wPrinterRowIndex
-	ld a, [hl]
-	and a
-	jr z, Printer_EndTilemapTransmission
-	; send packet 3
-	ld hl, PrinterDataPacket3 ; signal start of transmission
-	call Printer_CopyPacket
-	; prepare to send 40 tiles
-	call Printer_Convert2RowsTo2bpp
-	ld a, LOW(40 tiles)
-	ld [wPrinterSendByteCounter], a
-	ld a, HIGH(40 tiles)
-	ld [wPrinterSendByteCounter + 1], a
-	; compute the checksum
-	call Printer_ComputeChecksum
-	call Printer_NextSection
-	call Printer_WaitHandshake
-	ld a, PRINTER_STATUS_TRANSMITTING
-	ld [wPrinterStatus], a
-	ret
-
-Printer_EndTilemapTransmission: ; 840c5 (21:40c5)
-	; ensure that we go from here to routine 7
-	ld a, $6
-	ld [wJumptableIndex], a
-	; send packet 4
-	ld hl, PrinterDataPacket4 ; signal no transmission
-	call Printer_CopyPacket
-	; send no tile data
-	xor a
-	ld [wPrinterSendByteCounter], a
-	ld [wPrinterSendByteCounter + 1], a
-	call Printer_NextSection
-	call Printer_WaitHandshake
-	ret
-
-Printer_SignalSendHeader: ; 840de (21:40de)
-	call Printer_ResetData
-	ld hl, PrinterDataPacket2 ; signal request print
-	call Printer_CopyPacket
-	; prepare to send 1 tile
-	call Printer_StageHeaderForSend
-	ld a, LOW(4)
-	ld [wPrinterSendByteCounter], a
-	ld a, HIGH(4)
-	ld [wPrinterSendByteCounter + 1], a
-	; compute the checksum
-	call Printer_ComputeChecksum
-	call Printer_NextSection
-	call Printer_WaitHandshake
-	ld a, PRINTER_STATUS_PRINTING
-	ld [wPrinterStatus], a
-	ret
-
-Printer_SignalLoopBack: ; 84103 (21:4103)
-	call Printer_ResetData
-	; send packet 1
-	ld hl, PrinterDataPacket1 ; signal no transmission
-	call Printer_CopyPacket
-	; send no tile data
-	xor a
-	ld [wPrinterSendByteCounter], a
-	ld [wPrinterSendByteCounter + 1], a
-	ld a, [wPrinterQueueLength]
-	ld [wPrinterRowIndex], a
-	call Printer_NextSection
-	call Printer_WaitHandshake
-	ret
-
-Printer_WaitSerial: ; 84120 (21:4120)
-	ld hl, wPrinterSerialFrameDelay
-	inc [hl]
-	ld a, [hl]
-	cp $6
-	ret c
-	xor a
-	ld [hl], a
-	call Printer_NextSection
-	ret
-
-Printer_WaitSerialAndLoopBack2: ; 8412e (21:412e)
-	ld hl, wPrinterSerialFrameDelay
-	inc [hl]
-	ld a, [hl]
-	cp $6
-	ret c
-	xor a
-	ld [hl], a
-	ld hl, wPrinterRowIndex
-	dec [hl]
-	call Printer_PrevSection
-	call Printer_PrevSection
-	ret
-
-Printer_CheckConnectionStatus: ; 84143 (21:4143)
-	ld a, [wPrinterOpcode]
-	and a
-	ret nz
-	ld a, [wPrinterHandshake]
-	cp $ff
-	jr nz, .printer_connected
-	ld a, [wPrinterStatusFlags]
-	cp $ff
-	jr z, .printer_error
-
-.printer_connected
-	ld a, [wPrinterHandshake]
-	cp $81
-	jr nz, .printer_error
-	ld a, [wPrinterStatusFlags]
-	cp $0
-	jr nz, .printer_error
-	ld hl, wPrinterConnectionOpen
-	set 1, [hl]
-	ld a, $5
-	ld [wHandshakeFrameDelay], a
-	call Printer_NextSection
-	ret
-
-.printer_error
-	ld a, $ff
-	ld [wPrinterHandshake], a
-	ld [wPrinterStatusFlags], a
-	ld a, $e
-	ld [wJumptableIndex], a
-	ret
-
-Printer_TransmissionLoop: ; 84180 (21:4180)
-	ld a, [wPrinterOpcode]
-	and a
-	ret nz
-	ld a, [wPrinterStatusFlags]
-	and $f0
-	jr nz, .enter_wait_loop
-	ld a, [wPrinterStatusFlags]
-	and $1
-	jr nz, .cycle_back
-	call Printer_NextSection
-	ret
-
-.cycle_back
-	call Printer_PrevSection
-	ret
-
-.enter_wait_loop
-	ld a, $12 ; Printer_WaitLoopBack
-	ld [wJumptableIndex], a
-	ret
-
-Printer_WaitUntilFinished: ; 841a1 (21:41a1)
-	ld a, [wPrinterOpcode]
-	and a
-	ret nz
-	ld a, [wPrinterStatusFlags]
-	and $f3
-	ret nz
-	call Printer_NextSection
-	ret
-
-Printer_WaitLoopBack: ; 841b0 (21:41b0)
-	call Printer_NextSection
-Printer_WaitLoopBack_: ; 841b3 (21:41b3)
-	ld a, [wPrinterOpcode]
-	and a
-	ret nz
-	ld a, [wPrinterStatusFlags]
-	and $f0
-	ret nz
-	xor a
-	ld [wJumptableIndex], a
-	ret
-
-Printer_WaitHandshake: ; 841c3 (21:41c3)
-.loop
-	ld a, [wPrinterOpcode]
-	and a
-	jr nz, .loop
-	xor a
-	ld [wPrinterSendByteOffset], a
-	ld [wPrinterSendByteOffset + 1], a
-	ld a, $1
-	ld [wPrinterOpcode], a
-	ld a, $88
-	ld [rSB], a
-	ld a, $1
-	ld [rSC], a
-	ld a, $81
-	ld [rSC], a
-	ret
-
-Printer_CopyPacket: ; 841e2 (21:41e2)
-	ld a, [hli]
-	ld [wPrinterData], a
-	ld a, [hli]
-	ld [wPrinterData + 1], a
-	ld a, [hli]
-	ld [wPrinterData + 2], a
-	ld a, [hli]
-	ld [wPrinterData + 3], a
-	ld a, [hli]
-	ld [wPrinterChecksum], a
-	ld a, [hl]
-	ld [wPrinterChecksum + 1], a
-	ret
-
-Printer_ResetData: ; 841fb (21:41fb)
-	xor a
-	ld hl, wPrinterData
-	ld [hli], a
-	ld [hli], a
-	ld [hli], a
-	ld [hl], a
-	ld hl, wPrinterChecksum
-	ld [hli], a
-	ld [hl], a
-	xor a
-	ld [wPrinterSendByteCounter], a
-	ld [wPrinterSendByteCounter + 1], a
-	ld hl, wGameboyPrinterRAM
-	ld bc, wGameboyPrinter2bppSourceEnd - wGameboyPrinter2bppSource
-	call Printer_ByteFill
-	ret
-
-Printer_ComputeChecksum: ; 84219 (21:4219)
-	ld hl, 0
-	ld bc, 4
-	ld de, wPrinterData
-	call .ComputeChecksum
-	ld a, [wPrinterSendByteCounter]
-	ld c, a
-	ld a, [wPrinterSendByteCounter + 1]
-	ld b, a
-	ld de, wGameboyPrinterRAM
-	call .ComputeChecksum
-	ld a, l
-	ld [wPrinterChecksum], a
-	ld a, h
-	ld [wPrinterChecksum + 1], a
-	ret
-
-.ComputeChecksum: ; 8423c (21:423c)
-.loop
-	ld a, [de]
-	inc de
-	add l
-	jr nc, .no_overflow
-	inc h
-.no_overflow
-	ld l, a
-	dec bc
-	ld a, c
-	or b
-	jr nz, .loop
-	ret
-
-Printer_StageHeaderForSend: ; 84249 (21:4249)
-	ld a, $1
-	ld [wGameboyPrinter2bppSource + 0], a
-	ld a, [wcbfa]
-	ld [wGameboyPrinter2bppSource + 1], a
-	ld a, %11100100
-	ld [wGameboyPrinter2bppSource + 2], a
-	ld a, [wGBPrinterSettings]
-	ld [wGameboyPrinter2bppSource + 3], a
-	ret
-
-Printer_Convert2RowsTo2bpp: ; 84260 (21:4260)
-	; de = wPrinterTileMapBuffer + 2 * SCREEN_WIDTH * ([wPrinterQueueLength] - [wPrinterRowIndex])
-	ld a, [wPrinterRowIndex]
-	xor $ff
-	ld d, a
-	ld a, [wPrinterQueueLength]
-	inc a
-	add d
-	ld hl, wPrinterTileMapBuffer
-	ld de, 2 * SCREEN_WIDTH
-.loop1
-	and a
-	jr z, .okay1
-	add hl, de
-	dec a
-	jr .loop1
-.okay1
-	ld e, l
-	ld d, h
-	ld hl, wGameboyPrinter2bppSource
-	ld c, 2 * SCREEN_WIDTH
-.loop2
-	ld a, [de]
-	inc de
-	push bc
-	push de
-	push hl
-	; convert tile index to vram address
-	swap a
-	ld d, a
-	and $f0
-	ld e, a
-	ld a, d
-	and $f
-	ld d, a
-	and $8
-	ld a, d
-	jr nz, .vtiles_8xxx
-	or $90
-	jr .got_vtile_addr
-
-.vtiles_8xxx
-	or $80
-.got_vtile_addr
-	ld d, a
-	; copy 1 vtile to hl
-	lb bc, BANK(Printer_Convert2RowsTo2bpp), 1
-	call Request2bpp
-	pop hl
-	ld de, 1 tiles
-	add hl, de
-	pop de
-	pop bc
-	dec c
-	jr nz, .loop2
-	ret
-
-Printer_ByteFill: ; 842ab
-	push de
-	ld e, a
-.loop
-	ld [hl], e
-	inc hl
-	dec bc
-	ld a, c
-	or b
-	jr nz, .loop
-	ld a, e
-	pop de
-	ret
-; 842b7
-
-PrinterDataPacket1:
-	db  1, 0, $00, 0
-	dw 1
-PrinterDataPacket2:
-	db  2, 0, $04, 0
-	dw 0
-PrinterDataPacket3:
-	db  4, 0, $80, 2
-	dw 0
-PrinterDataPacket4:
-	db  4, 0, $00, 0
-	dw 4
-PrinterDataPacket5: ; unused
-	db  8, 0, $00, 0
-	dw 8
-PrinterDataPacket6: ; unused
-	db 15, 0, $00, 0
-	dw 15
-; 842db
-
-_PrinterReceive:: ; 842db
-	ld a, [wPrinterOpcode]
-	add a
-	ld e, a
-	ld d, 0
-	ld hl, .Jumptable
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-; 842ea
-
-.Jumptable: ; 842ea (21:42ea)
-	dw Printer_DoNothing ; 00
-
-	dw Printer_Send0x33 ; 01
-	dw Printer_SendPrinterData1 ; 02
-	dw Printer_SendPrinterData2 ; 03
-	dw Printer_SendPrinterData3 ; 04
-	dw Printer_SendPrinterData4 ; 05
-	dw Printer_SendNextByte ; 06
-	dw Printer_SendwPrinterChecksumLo ; 07
-	dw Printer_SendwPrinterChecksumHi ; 08
-	dw Printer_Send0x00 ; 09
-	dw Printer_ReceiveTowPrinterHandshakeAndSend0x00 ; 0a
-	dw Printer_ReceiveTowPrinterStatusFlagsAndExitSendLoop ; 0b
-
-	dw Printer_Send0x33 ; 0c triggered by AskSerial
-	dw Printer_Send0x0f ; 0d
-	dw Printer_Send0x00_ ; 0e
-	dw Printer_Send0x00_ ; 0f
-	dw Printer_Send0x00_ ; 10
-	dw Printer_Send0x0f ; 11
-	dw Printer_Send0x00_ ; 12
-	dw Printer_Send0x00 ; 13
-	dw Printer_ReceiveTowPrinterHandshakeAndSend0x00 ; 14
-	dw Printer_ReceiveTowPrinterStatusFlagsAndExitSendLoop_ ; 15
-
-	dw Printer_Send0x33 ; 16 triggered by pressing B
-	dw Printer_Send0x08 ; 17
-	dw Printer_Send0x00_ ; 18
-	dw Printer_Send0x00_ ; 19
-	dw Printer_Send0x00_ ; 1a
-	dw Printer_Send0x08 ; 1b
-	dw Printer_Send0x00_ ; 1c
-	dw Printer_Send0x00 ; 1d
-	dw Printer_ReceiveTowPrinterHandshakeAndSend0x00 ; 1e
-	dw Printer_ReceiveTowPrinterStatusFlagsAndExitSendLoop ; 1f
-
-Printer_NextInstruction: ; 8432a (21:432a)
-	ld hl, wPrinterOpcode
-	inc [hl]
-	ret
-
-Printer_DoNothing: ; 8432f (21:432f)
-	ret
-
-Printer_Send0x33: ; 84330 (21:4330)
-	ld a, $33
-	call Printer_SerialSend
-	call Printer_NextInstruction
-	ret
-
-Printer_SendPrinterData1: ; 84339 (21:4339)
-	ld a, [wPrinterData]
-	call Printer_SerialSend
-	call Printer_NextInstruction
-	ret
-
-Printer_SendPrinterData2: ; 84343 (21:4343)
-	ld a, [wPrinterData + 1]
-	call Printer_SerialSend
-	call Printer_NextInstruction
-	ret
-
-Printer_SendPrinterData3: ; 8434d (21:434d)
-	ld a, [wPrinterData + 2]
-	call Printer_SerialSend
-	call Printer_NextInstruction
-	ret
-
-Printer_SendPrinterData4: ; 84357 (21:4357)
-	ld a, [wPrinterData + 3]
-	call Printer_SerialSend
-	call Printer_NextInstruction
-	ret
-
-Printer_SendNextByte: ; 84361 (21:4361)
-	; decrement 16-bit counter
-	ld hl, wPrinterSendByteCounter
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-	or d
-	jr z, .done
-	dec de
-	ld [hl], d
-	dec hl
-	ld [hl], e
-
-	ld a, [wPrinterSendByteOffset]
-	ld e, a
-	ld a, [wPrinterSendByteOffset + 1]
-	ld d, a
-	ld hl, wGameboyPrinterRAM
-	add hl, de
-	inc de
-	ld a, e
-	ld [wPrinterSendByteOffset], a
-	ld a, d
-	ld [wPrinterSendByteOffset + 1], a
-	ld a, [hl]
-	call Printer_SerialSend
-	ret
-
-.done
-	call Printer_NextInstruction
-Printer_SendwPrinterChecksumLo: ; 8438b (21:438b)
-	ld a, [wPrinterChecksum]
-	call Printer_SerialSend
-	call Printer_NextInstruction
-	ret
-
-Printer_SendwPrinterChecksumHi: ; 84395 (21:4395)
-	ld a, [wPrinterChecksum + 1]
-	call Printer_SerialSend
-	call Printer_NextInstruction
-	ret
-
-Printer_Send0x00: ; 8439f (21:439f)
-	ld a, $0
-	call Printer_SerialSend
-	call Printer_NextInstruction
-	ret
-
-Printer_ReceiveTowPrinterHandshakeAndSend0x00: ; 843a8 (21:43a8)
-	ld a, [rSB]
-	ld [wPrinterHandshake], a
-	ld a, $0
-	call Printer_SerialSend
-	call Printer_NextInstruction
-	ret
-
-Printer_ReceiveTowPrinterStatusFlagsAndExitSendLoop: ; 843b6 (21:43b6)
-	ld a, [rSB]
-	ld [wPrinterStatusFlags], a
-	xor a
-	ld [wPrinterOpcode], a
-	ret
-
-Printer_Send0x0f: ; 843c0 (21:43c0)
-	ld a, $f
-	call Printer_SerialSend
-	call Printer_NextInstruction
-	ret
-
-Printer_Send0x00_: ; 843c9 (21:43c9)
-	ld a, $0
-	call Printer_SerialSend
-	call Printer_NextInstruction
-	ret
-
-Printer_Send0x08: ; 843d2 (21:43d2)
-	ld a, $8
-	call Printer_SerialSend
-	call Printer_NextInstruction
-	ret
-
-Printer_SerialSend: ; 843db (21:43db)
-	ld [rSB], a
-	ld a, $1 ; switch to internal clock
-	ld [rSC], a
-	ld a, $81 ; start transfer
-	ld [rSC], a
-	ret
-
-Printer_ReceiveTowPrinterStatusFlagsAndExitSendLoop_: ; 843e6 (21:43e6)
-	ld a, [rSB]
-	ld [wPrinterStatusFlags], a
-	xor a
-	ld [wPrinterOpcode], a
-	ret
--- a/engine/printnum.asm
+++ /dev/null
@@ -1,300 +1,0 @@
-_PrintNum:: ; c4c7
-; Print c digits of the b-byte value from de to hl.
-; Allows 2 to 7 digits. For 1-digit numbers, add
-; the value to char "0" instead of calling PrintNum.
-; Some extra flags can be given in bits 5-7 of b.
-; Bit 5: money if set (unless left-aligned without leading zeros)
-; Bit 6: right-aligned if set
-; Bit 7: print leading zeros if set
-
-	push bc
-
-	bit 5, b
-	jr z, .main
-	bit 7, b
-	jr nz, .moneyflag
-	bit 6, b
-	jr z, .main
-
-.moneyflag ; 101xxxxx or 011xxxxx
-	ld a, "¥"
-	ld [hli], a
-	res 5, b ; 100xxxxx or 010xxxxx
-
-.main
-	xor a
-	ld [hPrintNum1], a
-	ld [hPrintNum2], a
-	ld [hPrintNum3], a
-	ld a, b
-	and $f
-	cp 1
-	jr z, .byte
-	cp 2
-	jr z, .word
-; maximum 3 bytes
-.long
-	ld a, [de]
-	ld [hPrintNum2], a
-	inc de
-	ld a, [de]
-	ld [hPrintNum3], a
-	inc de
-	ld a, [de]
-	ld [hPrintNum4], a
-	jr .start
-
-.word
-	ld a, [de]
-	ld [hPrintNum3], a
-	inc de
-	ld a, [de]
-	ld [hPrintNum4], a
-	jr .start
-
-.byte
-	ld a, [de]
-	ld [hPrintNum4], a
-
-.start
-	push de
-
-	ld d, b
-	ld a, c
-	swap a
-	and $f
-	ld e, a
-	ld a, c
-	and $f
-	ld b, a
-	ld c, 0
-	cp 2
-	jr z, .two
-	cp 3
-	jr z, .three
-	cp 4
-	jr z, .four
-	cp 5
-	jr z, .five
-	cp 6
-	jr z, .six
-
-.seven
-	ld a, HIGH(1000000 >> 8)
-	ld [hPrintNum5], a
-	ld a, HIGH(1000000) ; mid
-	ld [hPrintNum6], a
-	ld a, LOW(1000000)
-	ld [hPrintNum7], a
-	call .PrintDigit
-	call .AdvancePointer
-
-.six
-	ld a, HIGH(100000 >> 8)
-	ld [hPrintNum5], a
-	ld a, HIGH(100000) ; mid
-	ld [hPrintNum6], a
-	ld a, LOW(100000)
-	ld [hPrintNum7], a
-	call .PrintDigit
-	call .AdvancePointer
-
-.five
-	xor a ; HIGH(10000 >> 8)
-	ld [hPrintNum5], a
-	ld a, HIGH(10000) ; mid
-	ld [hPrintNum6], a
-	ld a, LOW(10000)
-	ld [hPrintNum7], a
-	call .PrintDigit
-	call .AdvancePointer
-
-.four
-	xor a ; HIGH(1000 >> 8)
-	ld [hPrintNum5], a
-	ld a, HIGH(1000) ; mid
-	ld [hPrintNum6], a
-	ld a, LOW(1000)
-	ld [hPrintNum7], a
-	call .PrintDigit
-	call .AdvancePointer
-
-.three
-	xor a ; HIGH(100 >> 8)
-	ld [hPrintNum5], a
-	xor a ; HIGH(100) ; mid
-	ld [hPrintNum6], a
-	ld a, LOW(100)
-	ld [hPrintNum7], a
-	call .PrintDigit
-	call .AdvancePointer
-
-.two
-	dec e
-	jr nz, .two_skip
-	ld a, "0"
-	ld [hPrintNum1], a
-.two_skip
-
-	ld c, 0
-	ld a, [hPrintNum4]
-.mod_10
-	cp 10
-	jr c, .modded_10
-	sub 10
-	inc c
-	jr .mod_10
-.modded_10
-
-	ld b, a
-	ld a, [hPrintNum1]
-	or c
-	jr nz, .money
-	call .PrintLeadingZero
-	jr .money_leading_zero
-
-.money
-	call .PrintYen
-	push af
-	ld a, "0"
-	add c
-	ld [hl], a
-	pop af
-	ld [hPrintNum1], a
-	inc e
-	dec e
-	jr nz, .money_leading_zero
-	inc hl
-	ld [hl], "<DOT>"
-
-.money_leading_zero
-	call .AdvancePointer
-	call .PrintYen
-	ld a, "0"
-	add b
-	ld [hli], a
-
-	pop de
-	pop bc
-	ret
-
-.PrintYen: ; c5ba
-	push af
-	ld a, [hPrintNum1]
-	and a
-	jr nz, .stop
-	bit 5, d
-	jr z, .stop
-	ld a, "¥"
-	ld [hli], a
-	res 5, d
-
-.stop
-	pop af
-	ret
-
-.PrintDigit: ; c5cb (3:45cb)
-	dec e
-	jr nz, .ok
-	ld a, "0"
-	ld [hPrintNum1], a
-.ok
-	ld c, 0
-.loop
-	ld a, [hPrintNum5]
-	ld b, a
-	ld a, [hPrintNum2]
-	ld [hPrintNum8], a
-	cp b
-	jr c, .skip1
-	sub b
-	ld [hPrintNum2], a
-	ld a, [hPrintNum6]
-	ld b, a
-	ld a, [hPrintNum3]
-	ld [hPrintNum9], a
-	cp b
-	jr nc, .skip2
-	ld a, [hPrintNum2]
-	or 0
-	jr z, .skip3
-	dec a
-	ld [hPrintNum2], a
-	ld a, [hPrintNum3]
-.skip2
-	sub b
-	ld [hPrintNum3], a
-	ld a, [hPrintNum7]
-	ld b, a
-	ld a, [hPrintNum4]
-	ld [hPrintNum10], a
-	cp b
-	jr nc, .skip4
-	ld a, [hPrintNum3]
-	and a
-	jr nz, .skip5
-	ld a, [hPrintNum2]
-	and a
-	jr z, .skip6
-	dec a
-	ld [hPrintNum2], a
-	xor a
-.skip5
-	dec a
-	ld [hPrintNum3], a
-	ld a, [hPrintNum4]
-.skip4
-	sub b
-	ld [hPrintNum4], a
-	inc c
-	jr .loop
-.skip6
-	ld a, [hPrintNum9]
-	ld [hPrintNum3], a
-.skip3
-	ld a, [hPrintNum8]
-	ld [hPrintNum2], a
-.skip1
-	ld a, [hPrintNum1]
-	or c
-	jr z, .PrintLeadingZero
-	ld a, [hPrintNum1]
-	and a
-	jr nz, .done
-	bit 5, d
-	jr z, .done
-	ld a, "¥"
-	ld [hli], a
-	res 5, d
-.done
-	ld a, "0"
-	add c
-	ld [hl], a
-	ld [hPrintNum1], a
-	inc e
-	dec e
-	ret nz
-	inc hl
-	ld [hl], "<DOT>"
-	ret
-
-.PrintLeadingZero: ; c644
-; prints a leading zero unless they are turned off in the flags
-	bit 7, d ; print leading zeroes?
-	ret z
-	ld [hl], "0"
-	ret
-
-.AdvancePointer: ; c64a
-; increments the pointer unless leading zeroes are not being printed,
-; the number is left-aligned, and no nonzero digits have been printed yet
-	bit 7, d ; print leading zeroes?
-	jr nz, .inc
-	bit 6, d ; left alignment or right alignment?
-	jr z, .inc
-	ld a, [hPrintNum1]
-	and a
-	ret z
-.inc
-	inc hl
-	ret
--- a/engine/radio.asm
+++ /dev/null
@@ -1,1932 +1,0 @@
-PlayRadioShow:
-; If we're already in the radio program proper, we don't need to be here.
-	ld a, [wCurrentRadioLine]
-	cp POKE_FLUTE_RADIO
-	jr nc, .ok
-; If Team Rocket is not occupying the radio tower, we don't need to be here.
-	ld a, [wStatusFlags2]
-	bit STATUSFLAGS2_ROCKETS_IN_RADIO_TOWER_F, a
-	jr z, .ok
-; If we're in Kanto, we don't need to be here.
-	call IsInJohto
-	and a
-	jr nz, .ok
-; Team Rocket broadcasts on all stations.
-	ld a, ROCKET_RADIO
-	ld [wCurrentRadioLine], a
-.ok
-; Jump to the currently loaded station.  The index to which we need to jump is in wCurrentRadioLine.
-	ld a, [wCurrentRadioLine]
-	ld e, a
-	ld d, 0
-	ld hl, RadioJumptable
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-RadioJumptable:
-; entries correspond to constants/radio_constants.asm
-	dw OaksPKMNTalk1  ; $00
-	dw PokedexShow1 ; $01
-	dw BenMonMusic1  ; $02
-	dw LuckyNumberShow1 ; $03
-	dw BuenasPassword1 ; $04
-	dw PeoplePlaces1 ; $05
-	dw FernMonMusic1 ; $06
-	dw RocketRadio1 ; $07
-	dw PokeFluteRadio ; $08
-	dw UnownRadio ; $09
-	dw EvolutionRadio ; $0a
-; OaksPKMNTalk
-	dw OaksPKMNTalk2  ; $0b
-	dw OaksPKMNTalk3  ; $0c
-	dw OaksPKMNTalk4  ; $0d
-	dw OaksPKMNTalk5  ; $0e
-	dw OaksPKMNTalk6  ; $0f
-	dw OaksPKMNTalk7  ; $10
-	dw OaksPKMNTalk8  ; $11
-	dw OaksPKMNTalk9  ; $12
-	dw PokedexShow2 ; $13
-	dw PokedexShow3 ; $14
-	dw PokedexShow4 ; $15
-	dw PokedexShow5 ; $16
-; Ben Music
-	dw BenMonMusic2  ; $17
-	dw BenMonMusic3  ; $18
-	dw BenFernMusic4 ; $19
-	dw BenFernMusic5 ; $1a
-	dw BenFernMusic6 ; $1b
-	dw BenFernMusic7 ; $1c
-	dw FernMonMusic2 ; $1d
-; Lucky Number Show
-	dw LuckyNumberShow2 ; $1e
-	dw LuckyNumberShow3 ; $1f
-	dw LuckyNumberShow4 ; $20
-	dw LuckyNumberShow5 ; $21
-	dw LuckyNumberShow6 ; $22
-	dw LuckyNumberShow7 ; $23
-	dw LuckyNumberShow8 ; $24
-	dw LuckyNumberShow9 ; $25
-	dw LuckyNumberShow10 ; $26
-	dw LuckyNumberShow11 ; $27
-	dw LuckyNumberShow12 ; $28
-	dw LuckyNumberShow13 ; $29
-	dw LuckyNumberShow14 ; $2a
-	dw LuckyNumberShow15 ; $2b
-; People & Places
-	dw PeoplePlaces2 ; $2c
-	dw PeoplePlaces3 ; $2d
-	dw PeoplePlaces4 ; $2e
-	dw PeoplePlaces5 ; $2f
-	dw PeoplePlaces6 ; $30
-	dw PeoplePlaces7 ; $31
-; Rocket Radio
-	dw RocketRadio2 ; $32
-	dw RocketRadio3 ; $33
-	dw RocketRadio4 ; $34
-	dw RocketRadio5 ; $35
-	dw RocketRadio6 ; $36
-	dw RocketRadio7 ; $37
-	dw RocketRadio8 ; $38
-	dw RocketRadio9 ; $39
-	dw RocketRadio10 ; $3a
-; More Pokemon Channel stuff
-	dw OaksPKMNTalk10 ; $3b
-	dw OaksPKMNTalk11 ; $3c
-	dw OaksPKMNTalk12 ; $3d
-	dw OaksPKMNTalk13 ; $3e
-	dw OaksPKMNTalk14 ; $3f
-; Buenas Password
-	dw BuenasPassword2 ; $40
-	dw BuenasPassword3 ; $41
-	dw BuenasPassword4 ; $42
-	dw BuenasPassword5 ; $43
-	dw BuenasPassword6 ; $44
-	dw BuenasPassword7 ; $45
-	dw BuenasPassword8 ; $46
-	dw BuenasPassword9 ; $47
-	dw BuenasPassword10 ; $48
-	dw BuenasPassword11 ; $49
-	dw BuenasPassword12 ; $4a
-	dw BuenasPassword13 ; $4b
-	dw BuenasPassword14 ; $4c
-	dw BuenasPassword15 ; $4d
-	dw BuenasPassword16 ; $4e
-	dw BuenasPassword17 ; $4f
-	dw BuenasPassword18 ; $50
-	dw BuenasPassword19 ; $51
-	dw BuenasPassword20 ; $52
-	dw BuenasPassword21 ; $53
-	dw RadioScroll ; $54
-; More Pokemon Channel stuff
-	dw PokedexShow6 ; $55
-	dw PokedexShow7 ; $56
-	dw PokedexShow8 ; $57
-
-
-PrintRadioLine:
-	ld [wNextRadioLine], a
-	ld hl, wRadioText
-	ld a, [wNumRadioLinesPrinted]
-	cp 2
-	jr nc, .print
-	inc hl
-	ld [hl], TX_START
-	inc a
-	ld [wNumRadioLinesPrinted], a
-	cp 2
-	jr nz, .print
-	bccoord 1, 16
-	call PlaceHLTextAtBC
-	jr .skip
-.print
-	call PrintTextBoxText
-.skip
-	ld a, RADIO_SCROLL
-	ld [wCurrentRadioLine], a
-	ld a, 100
-	ld [wRadioTextDelay], a
-	ret
-
-ReplacePeriodsWithSpaces:
-	push hl
-	ld b, SCREEN_WIDTH * 2
-.loop
-	ld a, [hl]
-	cp "."
-	jr nz, .next
-	ld [hl], " "
-
-.next
-	inc hl
-	dec b
-	jr nz, .loop
-	pop hl
-	ret
-
-RadioScroll:
-	ld hl, wRadioTextDelay
-	ld a, [hl]
-	and a
-	jr z, .proceed
-	dec [hl]
-	ret
-.proceed
-	ld a, [wNextRadioLine]
-	ld [wCurrentRadioLine], a
-	ld a, [wNumRadioLinesPrinted]
-	cp 1
-	call nz, CopyBottomLineToTopLine
-	jp ClearBottomLine
-
-OaksPKMNTalk1:
-	ld a, 5
-	ld [wOaksPKMNTalkSegmentCounter], a
-	call StartRadioStation
-	ld hl, OPT_IntroText1
-	ld a, OAKS_POKEMON_TALK_2
-	jp NextRadioLine
-
-OaksPKMNTalk2:
-	ld hl, OPT_IntroText2
-	ld a, OAKS_POKEMON_TALK_3
-	jp NextRadioLine
-
-OaksPKMNTalk3:
-	ld hl, OPT_IntroText3
-	ld a, OAKS_POKEMON_TALK_4
-	jp NextRadioLine
-
-OaksPKMNTalk4:
-; Choose a random route, and a random Pokemon from that route.
-.sample
-	call Random
-	and %11111
-	cp (OaksPKMNTalkRoutes.End - OaksPKMNTalkRoutes) / 2
-	jr nc, .sample
-	; We now have a number between 0 and 14.
-	ld hl, OaksPKMNTalkRoutes
-	ld c, a
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	ld b, [hl]
-	inc hl
-	ld c, [hl]
-	; bc now contains the chosen map's group and number indices.
-	push bc
-
-	; Search the JohtoGrassWildMons array for the chosen map.
-	ld hl, JohtoGrassWildMons
-.loop
-	ld a, BANK(JohtoGrassWildMons)
-	call GetFarByte
-	cp -1
-	jr z, .overflow
-	inc hl
-	cp b
-	jr nz, .next
-	ld a, BANK(JohtoGrassWildMons)
-	call GetFarByte
-	cp c
-	jr z, .done
-.next
-	dec hl
-	ld de, GRASS_WILDDATA_LENGTH
-	add hl, de
-	jr .loop
-
-.done
-	; Point hl to the list of morning Pokémon., skipping percentages
-rept 4
-	inc hl
-endr
-	; Generate a number, either 0, 1, or 2, to choose a time of day.
-.loop2
-	call Random
-	maskbits NUM_DAYTIMES
-	cp DARKNESS_F
-	jr z, .loop2
-
-	ld bc, 2 * NUM_GRASSMON
-	call AddNTimes
-.loop3
-	; Choose one of the middle three Pokemon.
-	call Random
-	and NUM_GRASSMON
-	cp 2
-	jr c, .loop3
-	cp 5
-	jr nc, .loop3
-	ld e, a
-	ld d, 0
-	add hl, de
-	add hl, de
-	inc hl ; skip level
-	ld a, BANK(JohtoGrassWildMons)
-	call GetFarByte
-	ld [wNamedObjectIndexBuffer], a
-	ld [wCurPartySpecies], a
-	call GetPokemonName
-	ld hl, wStringBuffer1
-	ld de, wMonOrItemNameBuffer
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-
-	; Now that we've chosen our wild Pokemon,
-	; let's recover the map index info and get its name.
-	pop bc
-	call GetWorldMapLocation
-	ld e, a
-	farcall GetLandmarkName
-	ld hl, OPT_OakText1
-	call CopyRadioTextToRAM
-	ld a, OAKS_POKEMON_TALK_5
-	jp PrintRadioLine
-
-.overflow
-	pop bc
-	ld a, OAKS_POKEMON_TALK
-	jp PrintRadioLine
-
-INCLUDE "data/radio/oaks_pkmn_talk_routes.asm"
-
-OaksPKMNTalk5:
-	ld hl, OPT_OakText2
-	ld a, OAKS_POKEMON_TALK_6
-	jp NextRadioLine
-
-OaksPKMNTalk6:
-	ld hl, OPT_OakText3
-	ld a, OAKS_POKEMON_TALK_7
-	jp NextRadioLine
-
-OPT_IntroText1:
-	; MARY: PROF.OAK'S
-	text_jump _OPT_IntroText1
-	db "@"
-
-OPT_IntroText2:
-	; #MON TALK!
-	text_jump _OPT_IntroText2
-	db "@"
-
-OPT_IntroText3:
-	; With me, MARY!
-	text_jump _OPT_IntroText3
-	db "@"
-
-OPT_OakText1:
-	; OAK: @ @
-	text_jump _OPT_OakText1
-	db "@"
-
-OPT_OakText2:
-	; may be seen around
-	text_jump _OPT_OakText2
-	db "@"
-
-OPT_OakText3:
-	; @ .
-	text_jump _OPT_OakText3
-	db "@"
-
-OaksPKMNTalk7:
-	ld a, [wCurPartySpecies]
-	ld [wNamedObjectIndexBuffer], a
-	call GetPokemonName
-	ld hl, OPT_MaryText1
-	ld a, OAKS_POKEMON_TALK_8
-	jp NextRadioLine
-
-OPT_MaryText1:
-	; MARY: @ 's
-	text_jump _OPT_MaryText1
-	db "@"
-
-OaksPKMNTalk8:
-	; 0-15 are all valid indexes into .Adverbs,
-	; so no need for a retry loop
-	call Random
-	maskbits NUM_OAKS_POKEMON_TALK_ADVERBS
-	ld e, a
-	ld d, 0
-	ld hl, .Adverbs
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, OAKS_POKEMON_TALK_9
-	jp NextRadioLine
-
-.Adverbs:
-; there are NUM_OAKS_POKEMON_TALK_ADVERBS entries
-	dw .sweetadorably
-	dw .wigglyslickly
-	dw .aptlynamed
-	dw .undeniablykindof
-	dw .unbearably
-	dw .wowimpressively
-	dw .almostpoisonously
-	dw .sensually
-	dw .mischievously
-	dw .topically
-	dw .addictively
-	dw .looksinwater
-	dw .evolutionmustbe
-	dw .provocatively
-	dw .flippedout
-	dw .heartmeltingly
-
-.sweetadorably
-	; sweet and adorably
-	text_jump OPT_SweetAdorably
-	db "@"
-
-.wigglyslickly
-	; wiggly and slickly
-	text_jump OPT_WigglySlickly
-	db "@"
-
-.aptlynamed
-	; aptly named and
-	text_jump OPT_AptlyNamed
-	db "@"
-
-.undeniablykindof
-	; undeniably kind of
-	text_jump OPT_UndeniablyKindOf
-	db "@"
-
-.unbearably
-	; so, so unbearably
-	text_jump OPT_Unbearably
-	db "@"
-
-.wowimpressively
-	; wow, impressively
-	text_jump OPT_WowImpressively
-	db "@"
-
-.almostpoisonously
-	; almost poisonously
-	text_jump OPT_AlmostPoisonously
-	db "@"
-
-.sensually
-	; ooh, so sensually
-	text_jump OPT_Sensually
-	db "@"
-
-.mischievously
-	; so mischievously
-	text_jump OPT_Mischievously
-	db "@"
-
-.topically
-	; so very topically
-	text_jump OPT_Topically
-	db "@"
-
-.addictively
-	; sure addictively
-	text_jump OPT_Addictively
-	db "@"
-
-.looksinwater
-	; looks in water is
-	text_jump OPT_LooksInWater
-	db "@"
-
-.evolutionmustbe
-	; evolution must be
-	text_jump OPT_EvolutionMustBe
-	db "@"
-
-.provocatively
-	; provocatively
-	text_jump OPT_Provocatively
-	db "@"
-
-.flippedout
-	; so flipped out and
-	text_jump OPT_FlippedOut
-	db "@"
-
-.heartmeltingly
-	; heart-meltingly
-	text_jump OPT_HeartMeltingly
-	db "@"
-
-OaksPKMNTalk9:
-	; 0-15 are all valid indexes into .Adjectives,
-	; so no need for a retry loop
-	call Random
-	maskbits NUM_OAKS_POKEMON_TALK_ADJECTIVES
-	ld e, a
-	ld d, 0
-	ld hl, .Adjectives
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [wOaksPKMNTalkSegmentCounter]
-	dec a
-	ld [wOaksPKMNTalkSegmentCounter], a
-	ld a, OAKS_POKEMON_TALK_4
-	jr nz, .ok
-	ld a, 5
-	ld [wOaksPKMNTalkSegmentCounter], a
-	ld a, OAKS_POKEMON_TALK_10
-.ok
-	jp NextRadioLine
-
-.Adjectives:
-; there are NUM_OAKS_POKEMON_TALK_ADJECTIVES entries
-	dw .cute
-	dw .weird
-	dw .pleasant
-	dw .boldsortof
-	dw .frightening
-	dw .suavedebonair
-	dw .powerful
-	dw .exciting
-	dw .groovy
-	dw .inspiring
-	dw .friendly
-	dw .hothothot
-	dw .stimulating
-	dw .guarded
-	dw .lovely
-	dw .speedy
-
-.cute
-	; cute.
-	text_jump OPT_Cute
-	db "@"
-
-.weird
-	; weird.
-	text_jump OPT_Weird
-	db "@"
-
-.pleasant
-	; pleasant.
-	text_jump OPT_Pleasant
-	db "@"
-
-.boldsortof
-	; bold, sort of.
-	text_jump OPT_BoldSortOf
-	db "@"
-
-.frightening
-	; frightening.
-	text_jump OPT_Frightening
-	db "@"
-
-.suavedebonair
-	; suave & debonair!
-	text_jump OPT_SuaveDebonair
-	db "@"
-
-.powerful
-	; powerful.
-	text_jump OPT_Powerful
-	db "@"
-
-.exciting
-	; exciting.
-	text_jump OPT_Exciting
-	db "@"
-
-.groovy
-	; groovy!
-	text_jump OPT_Groovy
-	db "@"
-
-.inspiring
-	; inspiring.
-	text_jump OPT_Inspiring
-	db "@"
-
-.friendly
-	; friendly.
-	text_jump OPT_Friendly
-	db "@"
-
-.hothothot
-	; hot, hot, hot!
-	text_jump OPT_HotHotHot
-	db "@"
-
-.stimulating
-	; stimulating.
-	text_jump OPT_Stimulating
-	db "@"
-
-.guarded
-	; guarded.
-	text_jump OPT_Guarded
-	db "@"
-
-.lovely
-	; lovely.
-	text_jump OPT_Lovely
-	db "@"
-
-.speedy
-	; speedy.
-	text_jump OPT_Speedy
-	db "@"
-
-OaksPKMNTalk10:
-	farcall RadioMusicRestartPokemonChannel
-	ld hl, OPT_RestartText
-	call PrintText
-	call WaitBGMap
-	ld hl, OPT_PokemonChannelText
-	call PrintText
-	ld a, OAKS_POKEMON_TALK_11
-	ld [wCurrentRadioLine], a
-	ld a, 100
-	ld [wRadioTextDelay], a
-	ret
-
-OPT_PokemonChannelText:
-	; #MON
-	text_jump _OPT_PokemonChannelText
-	db "@"
-
-OPT_RestartText:
-	db "@"
-
-OaksPKMNTalk11:
-	ld hl, wRadioTextDelay
-	dec [hl]
-	ret nz
-	hlcoord 9, 14
-	ld de, .pokemon_string
-	ld a, OAKS_POKEMON_TALK_12
-	jp PlaceRadioString
-
-.pokemon_string
-	db "#MON@"
-
-OaksPKMNTalk12:
-	ld hl, wRadioTextDelay
-	dec [hl]
-	ret nz
-	hlcoord 1, 16
-	ld de, .pokemon_channel_string
-	ld a, OAKS_POKEMON_TALK_13
-	jp PlaceRadioString
-
-.pokemon_channel_string
-	db "#MON Channel@"
-
-OaksPKMNTalk13:
-	ld hl, wRadioTextDelay
-	dec [hl]
-	ret nz
-	hlcoord 12, 16
-	ld de, .terminator
-	ld a, OAKS_POKEMON_TALK_14
-	jp PlaceRadioString
-
-.terminator
-	db "@"
-
-OaksPKMNTalk14:
-	ld hl, wRadioTextDelay
-	dec [hl]
-	ret nz
-	ld de, MUSIC_POKEMON_TALK
-	callfar RadioMusicRestartDE
-	ld hl, .terminator
-	call PrintText
-	ld a, OAKS_POKEMON_TALK_4
-	ld [wNextRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	ld a, RADIO_SCROLL
-	ld [wCurrentRadioLine], a
-	ld a, 10
-	ld [wRadioTextDelay], a
-	ret
-
-.terminator
-	db "@"
-
-PlaceRadioString:
-	ld [wCurrentRadioLine], a
-	ld a, 100
-	ld [wRadioTextDelay], a
-	jp PlaceString
-
-CopyBottomLineToTopLine:
-	hlcoord 0, 15
-	decoord 0, 13
-	ld bc, SCREEN_WIDTH * 2
-	jp CopyBytes
-
-ClearBottomLine:
-	hlcoord 1, 15
-	ld bc, SCREEN_WIDTH - 2
-	ld a, " "
-	call ByteFill
-	hlcoord 1, 16
-	ld bc, SCREEN_WIDTH - 2
-	ld a, " "
-	jp ByteFill
-
-PokedexShow_GetDexEntryBank:
-	push hl
-	push de
-	ld a, [wCurPartySpecies]
-	dec a
-	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)
-
-PokedexShow1:
-	call StartRadioStation
-.loop
-	call Random
-	cp NUM_POKEMON
-	jr nc, .loop
-	ld c, a
-	push bc
-	ld a, c
-	call CheckCaughtMon
-	pop bc
-	jr z, .loop
-	inc c
-	ld a, c
-	ld [wCurPartySpecies], a
-	ld [wNamedObjectIndexBuffer], a
-	call GetPokemonName
-	ld hl, PokedexShowText
-	ld a, POKEDEX_SHOW_2
-	jp NextRadioLine
-
-PokedexShow2:
-	ld a, [wCurPartySpecies]
-	dec a
-	ld hl, PokedexDataPointerTable
-	ld c, a
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	ld a, BANK(PokedexDataPointerTable)
-	call GetFarHalfword
-	call PokedexShow_GetDexEntryBank
-	push af
-	push hl
-	call CopyDexEntryPart1
-	dec hl
-	ld [hl], "<DONE>"
-	ld hl, wPokedexShowPointerAddr
-	call CopyRadioTextToRAM
-	pop hl
-	pop af
-	call CopyDexEntryPart2
-rept 4
-	inc hl
-endr
-	ld a, l
-	ld [wPokedexShowPointerAddr], a
-	ld a, h
-	ld [wPokedexShowPointerAddr + 1], a
-	ld a, POKEDEX_SHOW_3
-	jp PrintRadioLine
-
-PokedexShow3:
-	call CopyDexEntry
-	ld a, POKEDEX_SHOW_4
-	jp PrintRadioLine
-
-PokedexShow4:
-	call CopyDexEntry
-	ld a, POKEDEX_SHOW_5
-	jp PrintRadioLine
-
-PokedexShow5:
-	call CopyDexEntry
-	ld a, POKEDEX_SHOW_6
-	jp PrintRadioLine
-
-PokedexShow6:
-	call CopyDexEntry
-	ld a, POKEDEX_SHOW_7
-	jp PrintRadioLine
-
-PokedexShow7:
-	call CopyDexEntry
-	ld a, POKEDEX_SHOW_8
-	jp PrintRadioLine
-
-PokedexShow8:
-	call CopyDexEntry
-	ld a, POKEDEX_SHOW
-	jp PrintRadioLine
-
-CopyDexEntry:
-	ld a, [wPokedexShowPointerAddr]
-	ld l, a
-	ld a, [wPokedexShowPointerAddr + 1]
-	ld h, a
-	ld a, [wPokedexShowPointerBank]
-	push af
-	push hl
-	call CopyDexEntryPart1
-	dec hl
-	ld [hl], "<DONE>"
-	ld hl, wPokedexShowPointerAddr
-	call CopyRadioTextToRAM
-	pop hl
-	pop af
-	call CopyDexEntryPart2
-	ret
-
-CopyDexEntryPart1:
-	ld de, wPokedexShowPointerBank
-	ld bc, SCREEN_WIDTH - 1
-	call FarCopyBytes
-	ld hl, wPokedexShowPointerAddr
-	ld [hl], TX_START
-	inc hl
-	ld [hl], "<LINE>"
-	inc hl
-.loop
-	ld a, [hli]
-	cp "@"
-	ret z
-	cp "<NEXT>"
-	ret z
-	cp "<DEXEND>"
-	ret z
-	jr .loop
-
-CopyDexEntryPart2:
-	ld d, a
-.loop
-	ld a, d
-	call GetFarByte
-	inc hl
-	cp "@"
-	jr z, .okay
-	cp "<NEXT>"
-	jr z, .okay
-	cp "<DEXEND>"
-	jr nz, .loop
-.okay
-	ld a, l
-	ld [wPokedexShowPointerAddr], a
-	ld a, h
-	ld [wPokedexShowPointerAddr + 1], a
-	ld a, d
-	ld [wPokedexShowPointerBank], a
-	ret
-
-PokedexShowText:
-	; @ @
-	text_jump _PokedexShowText
-	db "@"
-
-BenMonMusic1:
-	call StartPokemonMusicChannel
-	ld hl, BenIntroText1
-	ld a, POKEMON_MUSIC_2
-	jp NextRadioLine
-
-BenMonMusic2:
-	ld hl, BenIntroText2
-	ld a, POKEMON_MUSIC_3
-	jp NextRadioLine
-
-BenMonMusic3:
-	ld hl, BenIntroText3
-	ld a, POKEMON_MUSIC_4
-	jp NextRadioLine
-
-FernMonMusic1:
-	call StartPokemonMusicChannel
-	ld hl, FernIntroText1
-	ld a, LETS_ALL_SING_2
-	jp NextRadioLine
-
-FernMonMusic2:
-	ld hl, FernIntroMusic2
-	ld a, POKEMON_MUSIC_4
-	jp NextRadioLine
-
-BenFernMusic4:
-	ld hl, BenFernText1
-	ld a, POKEMON_MUSIC_5
-	jp NextRadioLine
-
-BenFernMusic5:
-	call GetWeekday
-	and 1
-	ld hl, BenFernText2A
-	jr z, .SunTueThurSun
-	ld hl, BenFernText2B
-.SunTueThurSun:
-	ld a, POKEMON_MUSIC_6
-	jp NextRadioLine
-
-BenFernMusic6:
-	call GetWeekday
-	and 1
-	ld hl, BenFernText3A
-	jr z, .SunTueThurSun
-	ld hl, BenFernText3B
-.SunTueThurSun:
-	ld a, POKEMON_MUSIC_7
-	jp NextRadioLine
-
-BenFernMusic7:
-	ret
-
-StartPokemonMusicChannel:
-	call RadioTerminator
-	call PrintText
-	ld de, MUSIC_POKEMON_MARCH
-	call GetWeekday
-	and 1
-	jr z, .SunTueThurSun
-	ld de, MUSIC_POKEMON_LULLABY
-.SunTueThurSun:
-	callfar RadioMusicRestartDE
-	ret
-
-BenIntroText1:
-	; BEN: #MON MUSIC
-	text_jump _BenIntroText1
-	db "@"
-
-BenIntroText2:
-	; CHANNEL!
-	text_jump _BenIntroText2
-	db "@"
-
-BenIntroText3:
-	; It's me, DJ BEN!
-	text_jump _BenIntroText3
-	db "@"
-
-FernIntroText1:
-	; FERN: #MUSIC!
-	text_jump _FernIntroText1
-	db "@"
-
-FernIntroMusic2:
-	; With DJ FERN!
-	text_jump _FernIntroText2
-	db "@"
-
-BenFernText1:
-	; Today's @ ,
-	text_jump _BenFernText1
-	db "@"
-
-BenFernText2A:
-	; so let us jam to
-	text_jump _BenFernText2A
-	db "@"
-
-BenFernText2B:
-	; so chill out to
-	text_jump _BenFernText2B
-	db "@"
-
-BenFernText3A:
-	; #MON March!
-	text_jump _BenFernText3A
-	db "@"
-
-BenFernText3B:
-	; #MON Lullaby!
-	text_jump _BenFernText3B
-	db "@"
-
-LuckyNumberShow1:
-	call StartRadioStation
-	callfar CheckLuckyNumberShowFlag
-	jr nc, .dontreset
-	callfar ResetLuckyNumberShowFlag
-.dontreset
-	ld hl, LC_Text1
-	ld a, LUCKY_NUMBER_SHOW_2
-	jp NextRadioLine
-
-LuckyNumberShow2:
-	ld hl, LC_Text2
-	ld a, LUCKY_NUMBER_SHOW_3
-	jp NextRadioLine
-
-LuckyNumberShow3:
-	ld hl, LC_Text3
-	ld a, LUCKY_NUMBER_SHOW_4
-	jp NextRadioLine
-
-LuckyNumberShow4:
-	ld hl, LC_Text4
-	ld a, LUCKY_NUMBER_SHOW_5
-	jp NextRadioLine
-
-LuckyNumberShow5:
-	ld hl, LC_Text5
-	ld a, LUCKY_NUMBER_SHOW_6
-	jp NextRadioLine
-
-LuckyNumberShow6:
-	ld hl, LC_Text6
-	ld a, LUCKY_NUMBER_SHOW_7
-	jp NextRadioLine
-
-LuckyNumberShow7:
-	ld hl, LC_Text7
-	ld a, LUCKY_NUMBER_SHOW_8
-	jp NextRadioLine
-
-LuckyNumberShow8:
-	ld hl, wStringBuffer1
-	ld de, wLuckyIDNumber
-	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
-	call PrintNum
-	ld a, "@"
-	ld [wStringBuffer1 + 5], a
-	ld hl, LC_Text8
-	ld a, LUCKY_NUMBER_SHOW_9
-	jp NextRadioLine
-
-LuckyNumberShow9:
-	ld hl, LC_Text9
-	ld a, LUCKY_NUMBER_SHOW_10
-	jp NextRadioLine
-
-LuckyNumberShow10:
-	ld hl, LC_Text7
-	ld a, LUCKY_NUMBER_SHOW_11
-	jp NextRadioLine
-
-LuckyNumberShow11:
-	ld hl, LC_Text8
-	ld a, LUCKY_NUMBER_SHOW_12
-	jp NextRadioLine
-
-LuckyNumberShow12:
-	ld hl, LC_Text10
-	ld a, LUCKY_NUMBER_SHOW_13
-	jp NextRadioLine
-
-LuckyNumberShow13:
-	ld hl, LC_Text11
-	call Random
-	and a
-	ld a, LUCKY_CHANNEL
-	jr nz, .okay
-	ld a, LUCKY_NUMBER_SHOW_14
-.okay
-	jp NextRadioLine
-
-LuckyNumberShow14:
-	ld hl, LC_DragText1
-	ld a, LUCKY_NUMBER_SHOW_15
-	jp NextRadioLine
-
-LuckyNumberShow15:
-	ld hl, LC_DragText2
-	ld a, LUCKY_CHANNEL
-	jp NextRadioLine
-
-LC_Text1:
-	; REED: Yeehaw! How
-	text_jump _LC_Text1
-	db "@"
-
-LC_Text2:
-	; y'all doin' now?
-	text_jump _LC_Text2
-	db "@"
-
-LC_Text3:
-	; Whether you're up
-	text_jump _LC_Text3
-	db "@"
-
-LC_Text4:
-	; or way down low,
-	text_jump _LC_Text4
-	db "@"
-
-LC_Text5:
-	; don't you miss the
-	text_jump _LC_Text5
-	db "@"
-
-LC_Text6:
-	; LUCKY NUMBER SHOW!
-	text_jump _LC_Text6
-	db "@"
-
-LC_Text7:
-	; This week's Lucky
-	text_jump _LC_Text7
-	db "@"
-
-LC_Text8:
-	; Number is @ !
-	text_jump _LC_Text8
-	db "@"
-
-LC_Text9:
-	; I'll repeat that!
-	text_jump _LC_Text9
-	db "@"
-
-LC_Text10:
-	; Match it and go to
-	text_jump _LC_Text10
-	db "@"
-
-LC_Text11:
-	; the RADIO TOWER!
-	text_jump _LC_Text11
-	db "@"
-
-LC_DragText1:
-	; …Repeating myself
-	text_jump _LC_DragText1
-	db "@"
-
-LC_DragText2:
-	; gets to be a drag…
-	text_jump _LC_DragText2
-	db "@"
-
-PeoplePlaces1:
-	call StartRadioStation
-	ld hl, PnP_Text1
-	ld a, PLACES_AND_PEOPLE_2
-	jp NextRadioLine
-
-PeoplePlaces2:
-	ld hl, PnP_Text2
-	ld a, PLACES_AND_PEOPLE_3
-	jp NextRadioLine
-
-PeoplePlaces3:
-	ld hl, PnP_Text3
-	call Random
-	cp 49 percent - 1
-	ld a, PLACES_AND_PEOPLE_4 ; People
-	jr c, .ok
-	ld a, PLACES_AND_PEOPLE_6 ; Places
-.ok
-	jp NextRadioLine
-
-PnP_Text1:
-	; PLACES AND PEOPLE!
-	text_jump _PnP_Text1
-	db "@"
-
-PnP_Text2:
-	; Brought to you by
-	text_jump _PnP_Text2
-	db "@"
-
-PnP_Text3:
-	; me, DJ LILY!
-	text_jump _PnP_Text3
-	db "@"
-
-PeoplePlaces4: ; People
-	call Random
-	maskbits NUM_TRAINER_CLASSES
-	inc a
-	cp NUM_TRAINER_CLASSES - 1
-	jr nc, PeoplePlaces4
-	push af
-	ld hl, PnP_HiddenPeople
-	ld a, [wStatusFlags]
-	bit STATUSFLAGS_HALL_OF_FAME_F, a
-	jr z, .ok
-	ld hl, PnP_HiddenPeople_BeatE4
-	ld a, [wKantoBadges]
-	cp %11111111 ; all badges
-	jr nz, .ok
-	ld hl, PnP_HiddenPeople_BeatKanto
-.ok
-	pop af
-	ld c, a
-	ld de, 1
-	push bc
-	call IsInArray
-	pop bc
-	jr c, PeoplePlaces4
-	push bc
-	callfar GetTrainerClassName
-	ld de, wStringBuffer1
-	call CopyName1
-	pop bc
-	ld b, 1
-	callfar GetTrainerName
-	ld hl, PnP_Text4
-	ld a, PLACES_AND_PEOPLE_5
-	jp NextRadioLine
-
-INCLUDE "data/radio/pnp_hidden_people.asm"
-
-PnP_Text4:
-	; @  @ @
-	text_jump _PnP_Text4
-	db "@"
-
-PeoplePlaces5:
-	; 0-15 are all valid indexes into .Adjectives,
-	; so no need for a retry loop
-	call Random
-	maskbits NUM_PNP_PEOPLE_ADJECTIVES
-	ld e, a
-	ld d, 0
-	ld hl, .Adjectives
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	call Random
-	cp 4 percent
-	ld a, PLACES_AND_PEOPLE
-	jr c, .ok
-	call Random
-	cp 49 percent - 1
-	ld a, PLACES_AND_PEOPLE_4 ; People
-	jr c, .ok
-	ld a, PLACES_AND_PEOPLE_6 ; Places
-.ok
-	jp NextRadioLine
-
-.Adjectives:
-; there are NUM_PNP_PEOPLE_ADJECTIVES entries
-	dw PnP_cute
-	dw PnP_lazy
-	dw PnP_happy
-	dw PnP_noisy
-	dw PnP_precocious
-	dw PnP_bold
-	dw PnP_picky
-	dw PnP_sortofok
-	dw PnP_soso
-	dw PnP_great
-	dw PnP_mytype
-	dw PnP_cool
-	dw PnP_inspiring
-	dw PnP_weird
-	dw PnP_rightforme
-	dw PnP_odd
-
-PnP_cute:
-	; is cute.
-	text_jump _PnP_cute
-	db "@"
-
-PnP_lazy:
-	; is sort of lazy.
-	text_jump _PnP_lazy
-	db "@"
-
-PnP_happy:
-	; is always happy.
-	text_jump _PnP_happy
-	db "@"
-
-PnP_noisy:
-	; is quite noisy.
-	text_jump _PnP_noisy
-	db "@"
-
-PnP_precocious:
-	; is precocious.
-	text_jump _PnP_precocious
-	db "@"
-
-PnP_bold:
-	; is somewhat bold.
-	text_jump _PnP_bold
-	db "@"
-
-PnP_picky:
-	; is too picky!
-	text_jump _PnP_picky
-	db "@"
-
-PnP_sortofok:
-	; is sort of OK.
-	text_jump _PnP_sortofok
-	db "@"
-
-PnP_soso:
-	; is just so-so.
-	text_jump _PnP_soso
-	db "@"
-
-PnP_great:
-	; is actually great.
-	text_jump _PnP_great
-	db "@"
-
-PnP_mytype:
-	; is just my type.
-	text_jump _PnP_mytype
-	db "@"
-
-PnP_cool:
-	; is so cool, no?
-	text_jump _PnP_cool
-	db "@"
-
-PnP_inspiring:
-	; is inspiring!
-	text_jump _PnP_inspiring
-	db "@"
-
-PnP_weird:
-	; is kind of weird.
-	text_jump _PnP_weird
-	db "@"
-
-PnP_rightforme:
-	; is right for me?
-	text_jump _PnP_rightforme
-	db "@"
-
-PnP_odd:
-	; is definitely odd!
-	text_jump _PnP_odd
-	db "@"
-
-PeoplePlaces6: ; Places
-	call Random
-	cp (PnP_HiddenPlaces.End - PnP_HiddenPlaces) / 2
-	jr nc, PeoplePlaces6
-	ld hl, PnP_HiddenPlaces
-	ld c, a
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	ld b, [hl]
-	inc hl
-	ld c, [hl]
-	call GetWorldMapLocation
-	ld e, a
-	farcall GetLandmarkName
-	ld hl, PnP_Text5
-	ld a, PLACES_AND_PEOPLE_7
-	jp NextRadioLine
-
-INCLUDE "data/radio/pnp_hidden_places.asm"
-
-PnP_Text5:
-	; @ @
-	text_jump _PnP_Text5
-	db "@"
-
-PeoplePlaces7:
-	; 0-15 are all valid indexes into .Adjectives,
-	; so no need for a retry loop
-	call Random
-	maskbits NUM_PNP_PLACES_ADJECTIVES
-	ld e, a
-	ld d, 0
-	ld hl, .Adjectives
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	call CopyRadioTextToRAM
-	call Random
-	cp 4 percent
-	ld a, PLACES_AND_PEOPLE
-	jr c, .ok
-	call Random
-	cp 49 percent - 1
-	ld a, PLACES_AND_PEOPLE_4 ; People
-	jr c, .ok
-	ld a, PLACES_AND_PEOPLE_6 ; Places
-.ok
-	jp PrintRadioLine
-
-.Adjectives:
-; there are NUM_PNP_PLACES_ADJECTIVES entries
-	dw PnP_cute
-	dw PnP_lazy
-	dw PnP_happy
-	dw PnP_noisy
-	dw PnP_precocious
-	dw PnP_bold
-	dw PnP_picky
-	dw PnP_sortofok
-	dw PnP_soso
-	dw PnP_great
-	dw PnP_mytype
-	dw PnP_cool
-	dw PnP_inspiring
-	dw PnP_weird
-	dw PnP_rightforme
-	dw PnP_odd
-
-RocketRadio1:
-	call StartRadioStation
-	ld hl, RocketRadioText1
-	ld a, ROCKET_RADIO_2
-	jp NextRadioLine
-
-RocketRadio2:
-	ld hl, RocketRadioText2
-	ld a, ROCKET_RADIO_3
-	jp NextRadioLine
-
-RocketRadio3:
-	ld hl, RocketRadioText3
-	ld a, ROCKET_RADIO_4
-	jp NextRadioLine
-
-RocketRadio4:
-	ld hl, RocketRadioText4
-	ld a, ROCKET_RADIO_5
-	jp NextRadioLine
-
-RocketRadio5:
-	ld hl, RocketRadioText5
-	ld a, ROCKET_RADIO_6
-	jp NextRadioLine
-
-RocketRadio6:
-	ld hl, RocketRadioText6
-	ld a, ROCKET_RADIO_7
-	jp NextRadioLine
-
-RocketRadio7:
-	ld hl, RocketRadioText7
-	ld a, ROCKET_RADIO_8
-	jp NextRadioLine
-
-RocketRadio8:
-	ld hl, RocketRadioText8
-	ld a, ROCKET_RADIO_9
-	jp NextRadioLine
-
-RocketRadio9:
-	ld hl, RocketRadioText9
-	ld a, ROCKET_RADIO_10
-	jp NextRadioLine
-
-RocketRadio10:
-	ld hl, RocketRadioText10
-	ld a, ROCKET_RADIO
-	jp NextRadioLine
-
-RocketRadioText1:
-	; … …Ahem, we are
-	text_jump _RocketRadioText1
-	db "@"
-
-RocketRadioText2:
-	; TEAM ROCKET!
-	text_jump _RocketRadioText2
-	db "@"
-
-RocketRadioText3:
-	; After three years
-	text_jump _RocketRadioText3
-	db "@"
-
-RocketRadioText4:
-	; of preparation, we
-	text_jump _RocketRadioText4
-	db "@"
-
-RocketRadioText5:
-	; have risen again
-	text_jump _RocketRadioText5
-	db "@"
-
-RocketRadioText6:
-	; from the ashes!
-	text_jump _RocketRadioText6
-	db "@"
-
-RocketRadioText7:
-	; GIOVANNI! @ Can you
-	text_jump _RocketRadioText7
-	db "@"
-
-RocketRadioText8:
-	; hear?@  We did it!
-	text_jump _RocketRadioText8
-	db "@"
-
-RocketRadioText9:
-	; @ Where is our boss?
-	text_jump _RocketRadioText9
-	db "@"
-
-RocketRadioText10:
-	; @ Is he listening?
-	text_jump _RocketRadioText10
-	db "@"
-
-PokeFluteRadio:
-	call StartRadioStation
-	ld a, 1
-	ld [wNumRadioLinesPrinted], a
-	ret
-
-UnownRadio:
-	call StartRadioStation
-	ld a, 1
-	ld [wNumRadioLinesPrinted], a
-	ret
-
-EvolutionRadio:
-	call StartRadioStation
-	ld a, 1
-	ld [wNumRadioLinesPrinted], a
-	ret
-
-BuenasPassword1:
-; Determine if we need to be here
-	call BuenasPasswordCheckTime
-	jp nc, .PlayPassword
-	ld a, [wNumRadioLinesPrinted]
-	and a
-	jp z, BuenasPassword20
-	jp BuenasPassword8
-
-.PlayPassword:
-	call StartRadioStation
-	ld a, [hBGMapMode]
-	push af
-	xor a
-	ld [hBGMapMode], a
-	ld de, BuenasPasswordChannelName
-	hlcoord 2, 9
-	call PlaceString
-	pop af
-	ld [hBGMapMode], a
-	ld hl, BuenaRadioText1
-	ld a, BUENAS_PASSWORD_2
-	jp NextRadioLine
-
-BuenasPassword2:
-	ld hl, BuenaRadioText2
-	ld a, BUENAS_PASSWORD_3
-	jp NextRadioLine
-
-BuenasPassword3:
-	call BuenasPasswordCheckTime
-	ld hl, BuenaRadioText3
-	jp c, BuenasPasswordAfterMidnight
-	ld a, BUENAS_PASSWORD_4
-	jp NextRadioLine
-
-BuenasPassword4:
-	call BuenasPasswordCheckTime
-	jp c, BuenasPassword8
-	ld a, [wBuenasPassword]
-; If we already generated the password today, we don't need to generate a new one.
-	ld hl, wWeeklyFlags
-	bit WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
-	jr nz, .AlreadyGotIt
-; There are only 11 groups to choose from.
-.greater_than_11
-	call Random
-	maskbits NUM_PASSWORD_CATEGORIES
-	cp NUM_PASSWORD_CATEGORIES
-	jr nc, .greater_than_11
-; Store it in the high nybble of e.
-	swap a
-	ld e, a
-; For each group, choose one of the three passwords.
-.greater_than_three
-	call Random
-	maskbits NUM_PASSWORDS_PER_CATEGORY
-	cp NUM_PASSWORDS_PER_CATEGORY
-	jr nc, .greater_than_three
-; The high nybble of wBuenasPassword will now contain the password group index, and the low nybble contains the actual password.
-	add e
-	ld [wBuenasPassword], a
-; Set the flag so that we don't generate a new password this week.
-	ld hl, wWeeklyFlags
-	set WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
-.AlreadyGotIt:
-	ld c, a
-	call GetBuenasPassword
-	ld hl, BuenaRadioText4
-	ld a, BUENAS_PASSWORD_5
-	jp NextRadioLine
-
-GetBuenasPassword:
-; The password indices are held in c.  High nybble contains the group index, low nybble contains the word index.
-; Load the password group pointer in hl.
-	ld a, c
-	swap a
-	and $f
-	ld hl, BuenasPasswordTable
-	ld d, 0
-	ld e, a
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-; Get the password type and store it in b.
-	ld a, [hli]
-	ld b, a
-	push hl
-	inc hl
-; Get the password index.
-	ld a, c
-	and $f
-	ld c, a
-	push hl
-	ld hl, .StringFunctionJumpTable
-	ld e, b
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	pop de ; de now contains the pointer to the value of this week's password, in Blue Card Points.
-	call _hl_
-	pop hl
-	ld c, [hl]
-	ret
-
-.StringFunctionJumpTable:
-; entries correspond to BUENA_* constants
-	dw .Mon       ; BUENA_MON
-	dw .Item      ; BUENA_ITEM
-	dw .Move      ; BUENA_MOVE
-	dw .RawString ; BUENA_STRING
-
-.Mon:
-	call .GetTheIndex
-	call GetPokemonName
-	ret
-
-.Item:
-	call .GetTheIndex
-	call GetItemName
-	ret
-
-.Move:
-	call .GetTheIndex
-	call GetMoveName
-	ret
-
-.GetTheIndex:
-	ld h, 0
-	ld l, c
-	add hl, de
-	ld a, [hl]
-	ld [wNamedObjectIndexBuffer], a
-	ret
-
-.RawString:
-; Get the string from the table...
-	ld a, c
-	and a
-	jr z, .skip
-.read_loop
-	ld a, [de]
-	inc de
-	cp "@"
-	jr nz, .read_loop
-	dec c
-	jr nz, .read_loop
-; ... and copy it into wStringBuffer1.
-.skip
-	ld hl, wStringBuffer1
-.copy_loop
-	ld a, [de]
-	inc de
-	ld [hli], a
-	cp "@"
-	jr nz, .copy_loop
-	ld de, wStringBuffer1
-	ret
-
-INCLUDE "data/radio/buenas_passwords.asm"
-
-BuenasPassword5:
-	ld hl, BuenaRadioText5
-	ld a, BUENAS_PASSWORD_6
-	jp NextRadioLine
-
-BuenasPassword6:
-	ld hl, BuenaRadioText6
-	ld a, BUENAS_PASSWORD_7
-	jp NextRadioLine
-
-BuenasPassword7:
-	call BuenasPasswordCheckTime
-	ld hl, BuenaRadioText7
-	jr c, BuenasPasswordAfterMidnight
-	ld a, BUENAS_PASSWORD
-	jp NextRadioLine
-
-BuenasPasswordAfterMidnight:
-	push hl
-	ld hl, wWeeklyFlags
-	res WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
-	pop hl
-	ld a, BUENAS_PASSWORD_8
-	jp NextRadioLine
-
-BuenasPassword8:
-	ld hl, wWeeklyFlags
-	res WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
-	ld hl, BuenaRadioMidnightText10
-	ld a, BUENAS_PASSWORD_9
-	jp NextRadioLine
-
-BuenasPassword9:
-	ld hl, BuenaRadioMidnightText1
-	ld a, BUENAS_PASSWORD_10
-	jp NextRadioLine
-
-BuenasPassword10:
-	ld hl, BuenaRadioMidnightText2
-	ld a, BUENAS_PASSWORD_11
-	jp NextRadioLine
-
-BuenasPassword11:
-	ld hl, BuenaRadioMidnightText3
-	ld a, BUENAS_PASSWORD_12
-	jp NextRadioLine
-
-BuenasPassword12:
-	ld hl, BuenaRadioMidnightText4
-	ld a, BUENAS_PASSWORD_13
-	jp NextRadioLine
-
-BuenasPassword13:
-	ld hl, BuenaRadioMidnightText5
-	ld a, BUENAS_PASSWORD_14
-	jp NextRadioLine
-
-BuenasPassword14:
-	ld hl, BuenaRadioMidnightText6
-	ld a, BUENAS_PASSWORD_15
-	jp NextRadioLine
-
-BuenasPassword15:
-	ld hl, BuenaRadioMidnightText7
-	ld a, BUENAS_PASSWORD_16
-	jp NextRadioLine
-
-BuenasPassword16:
-	ld hl, BuenaRadioMidnightText8
-	ld a, BUENAS_PASSWORD_17
-	jp NextRadioLine
-
-BuenasPassword17:
-	ld hl, BuenaRadioMidnightText9
-	ld a, BUENAS_PASSWORD_18
-	jp NextRadioLine
-
-BuenasPassword18:
-	ld hl, BuenaRadioMidnightText10
-	ld a, BUENAS_PASSWORD_19
-	jp NextRadioLine
-
-BuenasPassword19:
-	ld hl, BuenaRadioMidnightText10
-	ld a, BUENAS_PASSWORD_20
-	jp NextRadioLine
-
-BuenasPassword20:
-	ld a, [hBGMapMode]
-	push af
-	farcall NoRadioMusic
-	farcall NoRadioName
-	pop af
-	ld [hBGMapMode], a
-	ld hl, wWeeklyFlags
-	res WEEKLYFLAGS_BUENAS_PASSWORD_F, [hl]
-	ld a, BUENAS_PASSWORD
-	ld [wCurrentRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	ld hl, BuenaOffTheAirText
-	ld a, BUENAS_PASSWORD_21
-	jp NextRadioLine
-
-BuenasPassword21:
-	ld a, BUENAS_PASSWORD
-	ld [wCurrentRadioLine], a
-	xor a
-	ld [wNumRadioLinesPrinted], a
-	call BuenasPasswordCheckTime
-	jp nc, BuenasPassword1
-	ld hl, BuenaOffTheAirText
-	ld a, BUENAS_PASSWORD_21
-	jp NextRadioLine
-
-BuenasPasswordCheckTime:
-	call UpdateTime
-	ld a, [hHours]
-	cp NITE_HOUR
-	ret
-
-BuenasPasswordChannelName:
-	db "BUENA'S PASSWORD@"
-
-BuenaRadioText1:
-	; BUENA: BUENA here!
-	text_jump _BuenaRadioText1
-	db "@"
-
-BuenaRadioText2:
-	; Today's password!
-	text_jump _BuenaRadioText2
-	db "@"
-
-BuenaRadioText3:
-	; Let me think… It's
-	text_jump _BuenaRadioText3
-	db "@"
-
-BuenaRadioText4:
-	; @ !
-	text_jump _BuenaRadioText4
-	db "@"
-
-BuenaRadioText5:
-	; Don't forget it!
-	text_jump _BuenaRadioText5
-	db "@"
-
-BuenaRadioText6:
-	; I'm in GOLDENROD's
-	text_jump _BuenaRadioText6
-	db "@"
-
-BuenaRadioText7:
-	; RADIO TOWER!
-	text_jump _BuenaRadioText7
-	db "@"
-
-BuenaRadioMidnightText1:
-	; BUENA: Oh my…
-	text_jump _BuenaRadioMidnightText1
-	db "@"
-
-BuenaRadioMidnightText2:
-	; It's midnight! I
-	text_jump _BuenaRadioMidnightText2
-	db "@"
-
-BuenaRadioMidnightText3:
-	; have to shut down!
-	text_jump _BuenaRadioMidnightText3
-	db "@"
-
-BuenaRadioMidnightText4:
-	; Thanks for tuning
-	text_jump _BuenaRadioMidnightText4
-	db "@"
-
-BuenaRadioMidnightText5:
-	; in to the end! But
-	text_jump _BuenaRadioMidnightText5
-	db "@"
-
-BuenaRadioMidnightText6:
-	; don't stay up too
-	text_jump _BuenaRadioMidnightText6
-	db "@"
-
-BuenaRadioMidnightText7:
-	; late! Presented to
-	text_jump _BuenaRadioMidnightText7
-	db "@"
-
-BuenaRadioMidnightText8:
-	; you by DJ BUENA!
-	text_jump _BuenaRadioMidnightText8
-	db "@"
-
-BuenaRadioMidnightText9:
-	; I'm outta here!
-	text_jump _BuenaRadioMidnightText9
-	db "@"
-
-BuenaRadioMidnightText10:
-	; …
-	text_jump _BuenaRadioMidnightText10
-	db "@"
-
-BuenaOffTheAirText:
-	;
-	text_jump _BuenaOffTheAirText
-	db "@"
-
-CopyRadioTextToRAM:
-	ld a, [hl]
-	cp TX_FAR
-	jp z, FarCopyRadioText
-	ld de, wRadioText
-	ld bc, SCREEN_WIDTH * 2
-	jp CopyBytes
-
-StartRadioStation:
-	ld a, [wNumRadioLinesPrinted]
-	and a
-	ret nz
-	call RadioTerminator
-	call PrintText
-	ld hl, RadioChannelSongs
-	ld a, [wCurrentRadioLine]
-	ld c, a
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	callfar RadioMusicRestartDE
-	ret
-
-INCLUDE "data/radio/channel_music.asm"
-
-NextRadioLine:
-	push af
-	call CopyRadioTextToRAM
-	pop af
-	jp PrintRadioLine
--- /dev/null
+++ b/engine/routines/math.asm
@@ -1,0 +1,196 @@
+_Multiply:: ; 66de
+
+; hMultiplier is one byte.
+	ld a, 8
+	ld b, a
+
+	xor a
+	ld [hProduct], a
+	ld [hMathBuffer + 1], a
+	ld [hMathBuffer + 2], a
+	ld [hMathBuffer + 3], a
+	ld [hMathBuffer + 4], a
+
+
+.loop
+	ld a, [hMultiplier]
+	srl a
+	ld [hMultiplier], a
+	jr nc, .next
+
+	ld a, [hMathBuffer + 4]
+	ld c, a
+	ld a, [hMultiplicand + 2]
+	add c
+	ld [hMathBuffer + 4], a
+
+	ld a, [hMathBuffer + 3]
+	ld c, a
+	ld a, [hMultiplicand + 1]
+	adc c
+	ld [hMathBuffer + 3], a
+
+	ld a, [hMathBuffer + 2]
+	ld c, a
+	ld a, [hMultiplicand + 0]
+	adc c
+	ld [hMathBuffer + 2], a
+
+	ld a, [hMathBuffer + 1]
+	ld c, a
+	ld a, [hProduct]
+	adc c
+	ld [hMathBuffer + 1], a
+
+.next
+	dec b
+	jr z, .done
+
+
+; hMultiplicand <<= 1
+
+	ld a, [hMultiplicand + 2]
+	add a
+	ld [hMultiplicand + 2], a
+
+	ld a, [hMultiplicand + 1]
+	rla
+	ld [hMultiplicand + 1], a
+
+	ld a, [hMultiplicand + 0]
+	rla
+	ld [hMultiplicand + 0], a
+
+	ld a, [hProduct]
+	rla
+	ld [hProduct], a
+
+	jr .loop
+
+
+.done
+	ld a, [hMathBuffer + 4]
+	ld [hProduct + 3], a
+
+	ld a, [hMathBuffer + 3]
+	ld [hProduct + 2], a
+
+	ld a, [hMathBuffer + 2]
+	ld [hProduct + 1], a
+
+	ld a, [hMathBuffer + 1]
+	ld [hProduct + 0], a
+
+	ret
+; 673e
+
+
+_Divide:: ; 673e
+	xor a
+	ld [hMathBuffer + 0], a
+	ld [hMathBuffer + 1], a
+	ld [hMathBuffer + 2], a
+	ld [hMathBuffer + 3], a
+	ld [hMathBuffer + 4], a
+
+	ld a, 9
+	ld e, a
+
+.loop
+	ld a, [hMathBuffer + 0]
+	ld c, a
+	ld a, [hDividend + 1]
+	sub c
+	ld d, a
+
+	ld a, [hDivisor]
+	ld c, a
+	ld a, [hDividend + 0]
+	sbc c
+	jr c, .next
+
+	ld [hDividend + 0], a
+
+	ld a, d
+	ld [hDividend + 1], a
+
+	ld a, [hMathBuffer + 4]
+	inc a
+	ld [hMathBuffer + 4], a
+
+	jr .loop
+
+.next
+	ld a, b
+	cp 1
+	jr z, .done
+
+	ld a, [hMathBuffer + 4]
+	add a
+	ld [hMathBuffer + 4], a
+
+	ld a, [hMathBuffer + 3]
+	rla
+	ld [hMathBuffer + 3], a
+
+	ld a, [hMathBuffer + 2]
+	rla
+	ld [hMathBuffer + 2], a
+
+	ld a, [hMathBuffer + 1]
+	rla
+	ld [hMathBuffer + 1], a
+
+	dec e
+	jr nz, .next2
+
+	ld e, 8
+	ld a, [hMathBuffer + 0]
+	ld [hDivisor], a
+	xor a
+	ld [hMathBuffer + 0], a
+
+	ld a, [hDividend + 1]
+	ld [hDividend + 0], a
+
+	ld a, [hDividend + 2]
+	ld [hDividend + 1], a
+
+	ld a, [hDividend + 3]
+	ld [hDividend + 2], a
+
+.next2
+	ld a, e
+	cp 1
+	jr nz, .okay
+	dec b
+
+.okay
+	ld a, [hDivisor]
+	srl a
+	ld [hDivisor], a
+
+	ld a, [hMathBuffer + 0]
+	rr a
+	ld [hMathBuffer + 0], a
+
+	jr .loop
+
+.done
+	ld a, [hDividend + 1]
+	ld [hDivisor], a
+
+	ld a, [hMathBuffer + 4]
+	ld [hDividend + 3], a
+
+	ld a, [hMathBuffer + 3]
+	ld [hDividend + 2], a
+
+	ld a, [hMathBuffer + 2]
+	ld [hDividend + 1], a
+
+	ld a, [hMathBuffer + 1]
+	ld [hDividend + 0], a
+
+	ret
+; 67c1
--- /dev/null
+++ b/engine/routines/printnum.asm
@@ -1,0 +1,300 @@
+_PrintNum:: ; c4c7
+; Print c digits of the b-byte value from de to hl.
+; Allows 2 to 7 digits. For 1-digit numbers, add
+; the value to char "0" instead of calling PrintNum.
+; Some extra flags can be given in bits 5-7 of b.
+; Bit 5: money if set (unless left-aligned without leading zeros)
+; Bit 6: right-aligned if set
+; Bit 7: print leading zeros if set
+
+	push bc
+
+	bit 5, b
+	jr z, .main
+	bit 7, b
+	jr nz, .moneyflag
+	bit 6, b
+	jr z, .main
+
+.moneyflag ; 101xxxxx or 011xxxxx
+	ld a, "¥"
+	ld [hli], a
+	res 5, b ; 100xxxxx or 010xxxxx
+
+.main
+	xor a
+	ld [hPrintNum1], a
+	ld [hPrintNum2], a
+	ld [hPrintNum3], a
+	ld a, b
+	and $f
+	cp 1
+	jr z, .byte
+	cp 2
+	jr z, .word
+; maximum 3 bytes
+.long
+	ld a, [de]
+	ld [hPrintNum2], a
+	inc de
+	ld a, [de]
+	ld [hPrintNum3], a
+	inc de
+	ld a, [de]
+	ld [hPrintNum4], a
+	jr .start
+
+.word
+	ld a, [de]
+	ld [hPrintNum3], a
+	inc de
+	ld a, [de]
+	ld [hPrintNum4], a
+	jr .start
+
+.byte
+	ld a, [de]
+	ld [hPrintNum4], a
+
+.start
+	push de
+
+	ld d, b
+	ld a, c
+	swap a
+	and $f
+	ld e, a
+	ld a, c
+	and $f
+	ld b, a
+	ld c, 0
+	cp 2
+	jr z, .two
+	cp 3
+	jr z, .three
+	cp 4
+	jr z, .four
+	cp 5
+	jr z, .five
+	cp 6
+	jr z, .six
+
+.seven
+	ld a, HIGH(1000000 >> 8)
+	ld [hPrintNum5], a
+	ld a, HIGH(1000000) ; mid
+	ld [hPrintNum6], a
+	ld a, LOW(1000000)
+	ld [hPrintNum7], a
+	call .PrintDigit
+	call .AdvancePointer
+
+.six
+	ld a, HIGH(100000 >> 8)
+	ld [hPrintNum5], a
+	ld a, HIGH(100000) ; mid
+	ld [hPrintNum6], a
+	ld a, LOW(100000)
+	ld [hPrintNum7], a
+	call .PrintDigit
+	call .AdvancePointer
+
+.five
+	xor a ; HIGH(10000 >> 8)
+	ld [hPrintNum5], a
+	ld a, HIGH(10000) ; mid
+	ld [hPrintNum6], a
+	ld a, LOW(10000)
+	ld [hPrintNum7], a
+	call .PrintDigit
+	call .AdvancePointer
+
+.four
+	xor a ; HIGH(1000 >> 8)
+	ld [hPrintNum5], a
+	ld a, HIGH(1000) ; mid
+	ld [hPrintNum6], a
+	ld a, LOW(1000)
+	ld [hPrintNum7], a
+	call .PrintDigit
+	call .AdvancePointer
+
+.three
+	xor a ; HIGH(100 >> 8)
+	ld [hPrintNum5], a
+	xor a ; HIGH(100) ; mid
+	ld [hPrintNum6], a
+	ld a, LOW(100)
+	ld [hPrintNum7], a
+	call .PrintDigit
+	call .AdvancePointer
+
+.two
+	dec e
+	jr nz, .two_skip
+	ld a, "0"
+	ld [hPrintNum1], a
+.two_skip
+
+	ld c, 0
+	ld a, [hPrintNum4]
+.mod_10
+	cp 10
+	jr c, .modded_10
+	sub 10
+	inc c
+	jr .mod_10
+.modded_10
+
+	ld b, a
+	ld a, [hPrintNum1]
+	or c
+	jr nz, .money
+	call .PrintLeadingZero
+	jr .money_leading_zero
+
+.money
+	call .PrintYen
+	push af
+	ld a, "0"
+	add c
+	ld [hl], a
+	pop af
+	ld [hPrintNum1], a
+	inc e
+	dec e
+	jr nz, .money_leading_zero
+	inc hl
+	ld [hl], "<DOT>"
+
+.money_leading_zero
+	call .AdvancePointer
+	call .PrintYen
+	ld a, "0"
+	add b
+	ld [hli], a
+
+	pop de
+	pop bc
+	ret
+
+.PrintYen: ; c5ba
+	push af
+	ld a, [hPrintNum1]
+	and a
+	jr nz, .stop
+	bit 5, d
+	jr z, .stop
+	ld a, "¥"
+	ld [hli], a
+	res 5, d
+
+.stop
+	pop af
+	ret
+
+.PrintDigit: ; c5cb (3:45cb)
+	dec e
+	jr nz, .ok
+	ld a, "0"
+	ld [hPrintNum1], a
+.ok
+	ld c, 0
+.loop
+	ld a, [hPrintNum5]
+	ld b, a
+	ld a, [hPrintNum2]
+	ld [hPrintNum8], a
+	cp b
+	jr c, .skip1
+	sub b
+	ld [hPrintNum2], a
+	ld a, [hPrintNum6]
+	ld b, a
+	ld a, [hPrintNum3]
+	ld [hPrintNum9], a
+	cp b
+	jr nc, .skip2
+	ld a, [hPrintNum2]
+	or 0
+	jr z, .skip3
+	dec a
+	ld [hPrintNum2], a
+	ld a, [hPrintNum3]
+.skip2
+	sub b
+	ld [hPrintNum3], a
+	ld a, [hPrintNum7]
+	ld b, a
+	ld a, [hPrintNum4]
+	ld [hPrintNum10], a
+	cp b
+	jr nc, .skip4
+	ld a, [hPrintNum3]
+	and a
+	jr nz, .skip5
+	ld a, [hPrintNum2]
+	and a
+	jr z, .skip6
+	dec a
+	ld [hPrintNum2], a
+	xor a
+.skip5
+	dec a
+	ld [hPrintNum3], a
+	ld a, [hPrintNum4]
+.skip4
+	sub b
+	ld [hPrintNum4], a
+	inc c
+	jr .loop
+.skip6
+	ld a, [hPrintNum9]
+	ld [hPrintNum3], a
+.skip3
+	ld a, [hPrintNum8]
+	ld [hPrintNum2], a
+.skip1
+	ld a, [hPrintNum1]
+	or c
+	jr z, .PrintLeadingZero
+	ld a, [hPrintNum1]
+	and a
+	jr nz, .done
+	bit 5, d
+	jr z, .done
+	ld a, "¥"
+	ld [hli], a
+	res 5, d
+.done
+	ld a, "0"
+	add c
+	ld [hl], a
+	ld [hPrintNum1], a
+	inc e
+	dec e
+	ret nz
+	inc hl
+	ld [hl], "<DOT>"
+	ret
+
+.PrintLeadingZero: ; c644
+; prints a leading zero unless they are turned off in the flags
+	bit 7, d ; print leading zeroes?
+	ret z
+	ld [hl], "0"
+	ret
+
+.AdvancePointer: ; c64a
+; increments the pointer unless leading zeroes are not being printed,
+; the number is left-aligned, and no nonzero digits have been printed yet
+	bit 7, d ; print leading zeroes?
+	jr nz, .inc
+	bit 6, d ; left alignment or right alignment?
+	jr z, .inc
+	ld a, [hPrintNum1]
+	and a
+	ret z
+.inc
+	inc hl
+	ret
--- a/engine/scripting.asm
+++ /dev/null
@@ -1,2857 +1,0 @@
-; Event scripting commands.
-
-
-EnableScriptMode::
-	push af
-	ld a, SCRIPT_READ
-	ld [wScriptMode], a
-	pop af
-	ret
-
-ScriptEvents::
-	call StartScript
-.loop
-	ld a, [wScriptMode]
-	ld hl, .modes
-	rst JumpTable
-	call CheckScript
-	jr nz, .loop
-	ret
-
-.modes
-	dw EndScript
-	dw RunScriptCommand
-	dw WaitScriptMovement
-	dw WaitScript
-
-EndScript:
-	call StopScript
-	ret
-
-WaitScript:
-	call StopScript
-
-	ld hl, wScriptDelay
-	dec [hl]
-	ret nz
-
-	farcall Function58b9
-
-	ld a, SCRIPT_READ
-	ld [wScriptMode], a
-	call StartScript
-	ret
-
-WaitScriptMovement:
-	call StopScript
-
-	ld hl, wVramState
-	bit 7, [hl]
-	ret nz
-
-	farcall Function58b9
-
-	ld a, SCRIPT_READ
-	ld [wScriptMode], a
-	call StartScript
-	ret
-
-RunScriptCommand:
-	call GetScriptByte
-	ld hl, ScriptCommandTable
-	rst JumpTable
-	ret
-
-
-ScriptCommandTable:
-; entries correspond to macros/scripts/events.asm enumeration
-	dw Script_scall                      ; 00
-	dw Script_farscall                   ; 01
-	dw Script_ptcall                     ; 02
-	dw Script_jump                       ; 03
-	dw Script_farjump                    ; 04
-	dw Script_ptjump                     ; 05
-	dw Script_ifequal                    ; 06
-	dw Script_ifnotequal                 ; 07
-	dw Script_iffalse                    ; 08
-	dw Script_iftrue                     ; 09
-	dw Script_ifgreater                  ; 0a
-	dw Script_ifless                     ; 0b
-	dw Script_jumpstd                    ; 0c
-	dw Script_callstd                    ; 0d
-	dw Script_callasm                    ; 0e
-	dw Script_special                    ; 0f
-	dw Script_ptcallasm                  ; 10
-	dw Script_checkmapscene              ; 11
-	dw Script_setmapscene                ; 12
-	dw Script_checkscene                 ; 13
-	dw Script_setscene                   ; 14
-	dw Script_writebyte                  ; 15
-	dw Script_addvar                     ; 16
-	dw Script_random                     ; 17
-	dw Script_checkver                   ; 18
-	dw Script_copybytetovar              ; 19
-	dw Script_copyvartobyte              ; 1a
-	dw Script_loadvar                    ; 1b
-	dw Script_checkcode                  ; 1c
-	dw Script_writevarcode               ; 1d
-	dw Script_writecode                  ; 1e
-	dw Script_giveitem                   ; 1f
-	dw Script_takeitem                   ; 20
-	dw Script_checkitem                  ; 21
-	dw Script_givemoney                  ; 22
-	dw Script_takemoney                  ; 23
-	dw Script_checkmoney                 ; 24
-	dw Script_givecoins                  ; 25
-	dw Script_takecoins                  ; 26
-	dw Script_checkcoins                 ; 27
-	dw Script_addcellnum                 ; 28
-	dw Script_delcellnum                 ; 29
-	dw Script_checkcellnum               ; 2a
-	dw Script_checktime                  ; 2b
-	dw Script_checkpoke                  ; 2c
-	dw Script_givepoke                   ; 2d
-	dw Script_giveegg                    ; 2e
-	dw Script_givepokeitem               ; 2f
-	dw Script_checkpokeitem              ; 30
-	dw Script_checkevent                 ; 31
-	dw Script_clearevent                 ; 32
-	dw Script_setevent                   ; 33
-	dw Script_checkflag                  ; 34
-	dw Script_clearflag                  ; 35
-	dw Script_setflag                    ; 36
-	dw Script_wildon                     ; 37
-	dw Script_wildoff                    ; 38
-	dw Script_xycompare                  ; 39
-	dw Script_warpmod                    ; 3a
-	dw Script_blackoutmod                ; 3b
-	dw Script_warp                       ; 3c
-	dw Script_readmoney                  ; 3d
-	dw Script_readcoins                  ; 3e
-	dw Script_vartomem                   ; 3f
-	dw Script_pokenamemem                ; 40
-	dw Script_itemtotext                 ; 41
-	dw Script_mapnametotext              ; 42
-	dw Script_trainertotext              ; 43
-	dw Script_stringtotext               ; 44
-	dw Script_itemnotify                 ; 45
-	dw Script_pocketisfull               ; 46
-	dw Script_opentext                   ; 47
-	dw Script_refreshscreen              ; 48
-	dw Script_closetext                  ; 49
-	dw Script_loadbytec2cf               ; 4a
-	dw Script_farwritetext               ; 4b
-	dw Script_writetext                  ; 4c
-	dw Script_repeattext                 ; 4d
-	dw Script_yesorno                    ; 4e
-	dw Script_loadmenu                   ; 4f
-	dw Script_closewindow                ; 50
-	dw Script_jumptextfaceplayer         ; 51
-if _CRYSTAL
-	dw Script_farjumptext                ; 52
-endc
-	dw Script_jumptext                   ; 53
-	dw Script_waitbutton                 ; 54
-	dw Script_buttonsound                ; 55
-	dw Script_pokepic                    ; 56
-	dw Script_closepokepic               ; 57
-	dw Script__2dmenu                    ; 58
-	dw Script_verticalmenu               ; 59
-	dw Script_loadpikachudata            ; 5a
-	dw Script_randomwildmon              ; 5b
-	dw Script_loadmemtrainer             ; 5c
-	dw Script_loadwildmon                ; 5d
-	dw Script_loadtrainer                ; 5e
-	dw Script_startbattle                ; 5f
-	dw Script_reloadmapafterbattle       ; 60
-	dw Script_catchtutorial              ; 61
-	dw Script_trainertext                ; 62
-	dw Script_trainerflagaction          ; 63
-	dw Script_winlosstext                ; 64
-	dw Script_scripttalkafter            ; 65
-	dw Script_endifjustbattled           ; 66
-	dw Script_checkjustbattled           ; 67
-	dw Script_setlasttalked              ; 68
-	dw Script_applymovement              ; 69
-	dw Script_applymovement2             ; 6a
-	dw Script_faceplayer                 ; 6b
-	dw Script_faceobject                 ; 6c
-	dw Script_variablesprite             ; 6d
-	dw Script_disappear                  ; 6e
-	dw Script_appear                     ; 6f
-	dw Script_follow                     ; 70
-	dw Script_stopfollow                 ; 71
-	dw Script_moveobject                 ; 72
-	dw Script_writeobjectxy              ; 73
-	dw Script_loademote                  ; 74
-	dw Script_showemote                  ; 75
-	dw Script_turnobject                 ; 76
-	dw Script_follownotexact             ; 77
-	dw Script_earthquake                 ; 78
-	dw Script_changemap                  ; 79
-	dw Script_changeblock                ; 7a
-	dw Script_reloadmap                  ; 7b
-	dw Script_reloadmappart              ; 7c
-	dw Script_writecmdqueue              ; 7d
-	dw Script_delcmdqueue                ; 7e
-	dw Script_playmusic                  ; 7f
-	dw Script_encountermusic             ; 80
-	dw Script_musicfadeout               ; 81
-	dw Script_playmapmusic               ; 82
-	dw Script_dontrestartmapmusic        ; 83
-	dw Script_cry                        ; 84
-	dw Script_playsound                  ; 85
-	dw Script_waitsfx                    ; 86
-	dw Script_warpsound                  ; 87
-	dw Script_specialsound               ; 88
-	dw Script_passtoengine               ; 89
-	dw Script_newloadmap                 ; 8a
-	dw Script_pause                      ; 8b
-	dw Script_deactivatefacing           ; 8c
-	dw Script_priorityjump               ; 8d
-	dw Script_warpcheck                  ; 8e
-	dw Script_ptpriorityjump             ; 8f
-	dw Script_return                     ; 90
-	dw Script_end                        ; 91
-	dw Script_reloadandreturn            ; 92
-	dw Script_endall                     ; 93
-	dw Script_pokemart                   ; 94
-	dw Script_elevator                   ; 95
-	dw Script_trade                      ; 96
-	dw Script_askforphonenumber          ; 97
-	dw Script_phonecall                  ; 98
-	dw Script_hangup                     ; 99
-	dw Script_describedecoration         ; 9a
-	dw Script_fruittree                  ; 9b
-	dw Script_specialphonecall           ; 9c
-	dw Script_checkphonecall             ; 9d
-	dw Script_verbosegiveitem            ; 9e
-	dw Script_verbosegiveitem2           ; 9f
-	dw Script_swarm                      ; a0
-	dw Script_halloffame                 ; a1
-	dw Script_credits                    ; a2
-	dw Script_warpfacing                 ; a3
-	dw Script_battletowertext            ; a4
-	dw Script_landmarktotext             ; a5
-	dw Script_trainerclassname           ; a6
-	dw Script_name                       ; a7
-	dw Script_wait                       ; a8
-	dw Script_checksave                  ; a9
-
-StartScript:
-	ld hl, wScriptFlags
-	set SCRIPT_RUNNING, [hl]
-	ret
-
-CheckScript:
-	ld hl, wScriptFlags
-	bit SCRIPT_RUNNING, [hl]
-	ret
-
-StopScript:
-	ld hl, wScriptFlags
-	res SCRIPT_RUNNING, [hl]
-	ret
-
-Script_callasm:
-; script command 0xe
-; parameters: asm
-
-	call GetScriptByte
-	ld b, a
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	ld a, b
-	rst FarCall
-	ret
-
-Script_special:
-; script command 0xf
-; parameters: predefined_script
-
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	farcall Special
-	ret
-
-Script_ptcallasm:
-; script command 0x10
-; parameters: asm
-
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	ld b, [hl]
-	inc hl
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, b
-	rst FarCall
-	ret
-
-Script_jumptextfaceplayer:
-; script command 0x51
-; parameters: text_pointer
-
-	ld a, [wScriptBank]
-	ld [wScriptTextBank], a
-	call GetScriptByte
-	ld [wScriptTextAddr], a
-	call GetScriptByte
-	ld [wScriptTextAddr + 1], a
-	ld b, BANK(JumpTextFacePlayerScript)
-	ld hl, JumpTextFacePlayerScript
-	jp ScriptJump
-
-Script_jumptext:
-; script command 0x53
-; parameters: text_pointer
-
-	ld a, [wScriptBank]
-	ld [wScriptTextBank], a
-	call GetScriptByte
-	ld [wScriptTextAddr], a
-	call GetScriptByte
-	ld [wScriptTextAddr + 1], a
-	ld b, BANK(JumpTextScript)
-	ld hl, JumpTextScript
-	jp ScriptJump
-
-JumpTextFacePlayerScript:
-	faceplayer
-JumpTextScript:
-	opentext
-	repeattext -1, -1
-	waitbutton
-	closetext
-	end
-
-
-if _CRYSTAL
-
-Script_farjumptext:
-; script command 0x52
-; parameters: text_pointer
-
-	call GetScriptByte
-	ld [wScriptTextBank], a
-	call GetScriptByte
-	ld [wScriptTextAddr], a
-	call GetScriptByte
-	ld [wScriptTextAddr + 1], a
-	ld b, BANK(JumpTextScript)
-	ld hl, JumpTextScript
-	jp ScriptJump
-
-endc
-
-
-Script_writetext:
-; script command 0x4c
-; parameters: text_pointer
-
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	ld a, [wScriptBank]
-	ld b, a
-	call MapTextbox
-	ret
-
-Script_farwritetext:
-; script command 0x4b
-; parameters: text_pointer
-
-	call GetScriptByte
-	ld b, a
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	call MapTextbox
-	ret
-
-Script_repeattext:
-; script command 0x4d
-; parameters: byte, byte
-
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	cp -1
-	jr nz, .done
-	ld a, l
-	cp -1
-	jr nz, .done
-	ld hl, wScriptTextBank
-	ld a, [hli]
-	ld b, a
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	call MapTextbox
-	ret
-
-.done
-	ret
-
-Script_waitbutton:
-; script command 0x54
-
-	jp WaitButton
-
-Script_buttonsound:
-; script command 0x55
-
-	ld a, [hOAMUpdate]
-	push af
-	ld a, $1
-	ld [hOAMUpdate], a
-	call WaitBGMap
-	call ButtonSound
-	pop af
-	ld [hOAMUpdate], a
-	ret
-
-Script_yesorno:
-; script command 0x4e
-
-	call YesNoBox
-	ld a, FALSE
-	jr c, .no
-	ld a, TRUE
-.no
-	ld [wScriptVar], a
-	ret
-
-Script_loadmenu:
-; script command 0x4f
-; parameters: menu_header
-
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	ld de, LoadMenuHeader
-	ld a, [wScriptBank]
-	call Call_a_de
-	call UpdateSprites
-	ret
-
-Script_closewindow:
-; script command 0x50
-
-	call CloseWindow
-	call UpdateSprites
-	ret
-
-Script_pokepic:
-; script command 0x56
-; parameters: pokemon
-
-	call GetScriptByte
-	and a
-	jr nz, .ok
-	ld a, [wScriptVar]
-.ok
-	ld [wCurPartySpecies], a
-	farcall Pokepic
-	ret
-
-Script_closepokepic:
-; script command 0x57
-
-	farcall ClosePokepic
-	ret
-
-Script_verticalmenu:
-; script command 0x59
-
-	ld a, [wScriptBank]
-	ld hl, VerticalMenu
-	rst FarCall
-	ld a, [wMenuCursorY]
-	jr nc, .ok
-	xor a
-.ok
-	ld [wScriptVar], a
-	ret
-
-Script__2dmenu:
-; script command 0x58
-
-	ld a, [wScriptBank]
-	ld hl, _2DMenu
-	rst FarCall
-	ld a, [wMenuCursorBuffer]
-	jr nc, .ok
-	xor a
-.ok
-	ld [wScriptVar], a
-	ret
-
-Script_battletowertext:
-; script command 0xa4
-; parameters: pointer, memory
-
-	call SetUpTextBox
-	call GetScriptByte
-	ld c, a
-	farcall BattleTowerText
-	ret
-
-Script_verbosegiveitem:
-; script command 0x9e
-; parameters: item, quantity
-
-	call Script_giveitem
-	call CurItemName
-	ld de, wStringBuffer1
-	ld a, 1
-	call CopyConvertedText
-	ld b, BANK(GiveItemScript)
-	ld de, GiveItemScript
-	jp ScriptCall
-
-
-ret_96f76:
-	ret
-
-GiveItemScript:
-	callasm ret_96f76
-	writetext ReceivedItemText
-	iffalse .Full
-	waitsfx
-	specialsound
-	waitbutton
-	itemnotify
-	end
-
-.Full:
-	buttonsound
-	pocketisfull
-	end
-
-ReceivedItemText:
-	text_jump UnknownText_0x1c4719
-	db "@"
-
-
-Script_verbosegiveitem2:
-; script command 0x9f
-; parameters: item, var
-
-	call GetScriptByte
-	cp -1
-	jr nz, .ok
-	ld a, [wScriptVar]
-.ok
-	ld [wCurItem], a
-	call GetScriptByte
-	call GetVarAction
-	ld a, [de]
-	ld [wItemQuantityChangeBuffer], a
-	ld hl, wNumItems
-	call ReceiveItem
-	ld a, TRUE
-	jr c, .ok2
-	xor a
-.ok2
-	ld [wScriptVar], a
-	call CurItemName
-	ld de, wStringBuffer1
-	ld a, 1
-	call CopyConvertedText
-	ld b, BANK(GiveItemScript)
-	ld de, GiveItemScript
-	jp ScriptCall
-
-Script_itemnotify:
-; script command 0x45
-
-	call GetPocketName
-	call CurItemName
-	ld b, BANK(PutItemInPocketText)
-	ld hl, PutItemInPocketText
-	call MapTextbox
-	ret
-
-Script_pocketisfull:
-; script command 0x46
-
-	call GetPocketName
-	call CurItemName
-	ld b, BANK(PocketIsFullText)
-	ld hl, PocketIsFullText
-	call MapTextbox
-	ret
-
-Script_specialsound:
-; script command 0x88
-
-	farcall CheckItemPocket
-	ld a, [wItemAttributeParamBuffer]
-	cp TM_HM
-	ld de, SFX_GET_TM
-	jr z, .play
-	ld de, SFX_ITEM
-.play
-	call PlaySFX
-	call WaitSFX
-	ret
-
-
-GetPocketName:
-	farcall CheckItemPocket
-	ld a, [wItemAttributeParamBuffer]
-	dec a
-	ld hl, .Pockets
-	maskbits NUM_POCKETS
-	add a
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-	ld hl, wStringBuffer3
-	call CopyName2
-	ret
-
-.Pockets:
-	dw .Item
-	dw .Key
-	dw .Ball
-	dw .TM
-
-.Item:
-	db "ITEM POCKET@"
-.Key:
-	db "KEY POCKET@"
-.Ball:
-	db "BALL POCKET@"
-.TM:
-	db "TM POCKET@"
-
-CurItemName:
-	ld a, [wCurItem]
-	ld [wd265], a
-	call GetItemName
-	ret
-
-
-PutItemInPocketText:
-	text_jump UnknownText_0x1c472c
-	db "@"
-
-PocketIsFullText:
-	text_jump UnknownText_0x1c474b
-	db "@"
-
-
-Script_pokemart:
-; script command 0x94
-; parameters: dialog_id, mart_id
-
-	call GetScriptByte
-	ld c, a
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld a, [wScriptBank]
-	ld b, a
-	farcall OpenMartDialog
-	ret
-
-Script_elevator:
-; script command 0x95
-; parameters: floor_list_pointer
-
-	xor a
-	ld [wScriptVar], a
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld a, [wScriptBank]
-	ld b, a
-	farcall Elevator
-	ret c
-	ld a, TRUE
-	ld [wScriptVar], a
-	ret
-
-Script_trade:
-; script command 0x96
-; parameters: trade_id
-
-	call GetScriptByte
-	ld e, a
-	farcall NPCTrade
-	ret
-
-Script_phonecall:
-; script command 0x98
-; parameters: caller_name
-
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld a, [wScriptBank]
-	ld b, a
-	farcall PhoneCall
-	ret
-
-Script_hangup:
-; script command 0x99
-
-	farcall HangUp
-	ret
-
-Script_askforphonenumber:
-; script command 0x97
-; parameters: number
-
-	call YesNoBox
-	jr c, .refused
-	call GetScriptByte
-	ld c, a
-	farcall AddPhoneNumber
-	jr c, .phonefull
-	xor a ; PHONE_CONTACT_GOT
-	jr .done
-.phonefull
-	ld a, PHONE_CONTACTS_FULL
-	jr .done
-.refused
-	call GetScriptByte
-	ld a, PHONE_CONTACT_REFUSED
-.done
-	ld [wScriptVar], a
-	ret
-
-Script_describedecoration:
-; script command 0x9a
-; parameters: byte
-
-	call GetScriptByte
-	ld b, a
-	farcall DescribeDecoration
-	ld h, d
-	ld l, e
-	jp ScriptJump
-
-Script_fruittree:
-; script command 0x9b
-; parameters: tree_id
-
-	call GetScriptByte
-	ld [wCurFruitTree], a
-	ld b, BANK(FruitTreeScript)
-	ld hl, FruitTreeScript
-	jp ScriptJump
-
-Script_swarm:
-; script command 0xa0
-; parameters: flag, map_group, map_id
-
-	call GetScriptByte
-	ld c, a
-	call GetScriptByte
-	ld d, a
-	call GetScriptByte
-	ld e, a
-	farcall StoreSwarmMapIndices
-	ret
-
-Script_trainertext:
-; script command 0x62
-; parameters: which_text
-
-	call GetScriptByte
-	ld c, a
-	ld b, 0
-	ld hl, wWalkingX
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [wEngineBuffer1]
-	ld b, a
-	call MapTextbox
-	ret
-
-Script_scripttalkafter:
-; script command 0x65
-
-	ld hl, wScriptAfterPointer
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [wEngineBuffer1]
-	ld b, a
-	jp ScriptJump
-
-Script_trainerflagaction:
-; script command 0x63
-; parameters: action
-
-	xor a
-	ld [wScriptVar], a
-	ld hl, wd041
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	call GetScriptByte
-	ld b, a
-	call EventFlagAction
-	ld a, c
-	and a
-	ret z
-	ld a, TRUE
-	ld [wScriptVar], a
-	ret
-
-Script_winlosstext:
-; script command 0x64
-; parameters: win_text_pointer, loss_text_pointer
-
-	ld hl, wWinTextPointer
-	call GetScriptByte
-	ld [hli], a
-	call GetScriptByte
-	ld [hli], a
-	ld hl, wLossTextPointer
-	call GetScriptByte
-	ld [hli], a
-	call GetScriptByte
-	ld [hli], a
-	ret
-
-Script_endifjustbattled:
-; script command 0x66
-
-	ld a, [wRunningTrainerBattleScript]
-	and a
-	ret z
-	jp Script_end
-
-Script_checkjustbattled:
-; script command 0x67
-
-	ld a, TRUE
-	ld [wScriptVar], a
-	ld a, [wRunningTrainerBattleScript]
-	and a
-	ret nz
-	xor a
-	ld [wScriptVar], a
-	ret
-
-Script_encountermusic:
-; script command 0x80
-
-	ld a, [wOtherTrainerClass]
-	ld e, a
-	farcall PlayTrainerEncounterMusic
-	ret
-
-Script_playmapmusic:
-; script command 0x82
-
-	call PlayMapMusic
-	ret
-
-Script_playmusic:
-; script command 0x7f
-; parameters: music_pointer
-
-	ld de, MUSIC_NONE
-	call PlayMusic
-	xor a
-	ld [wMusicFade], a
-	call MaxVolume
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	call PlayMusic
-	ret
-
-Script_musicfadeout:
-; script command 0x81
-; parameters: music, fadetime
-
-	call GetScriptByte
-	ld [wMusicFadeID], a
-	call GetScriptByte
-	ld [wMusicFadeID + 1], a
-	call GetScriptByte
-	and $ff ^ (1 << MUSIC_FADE_IN_F)
-	ld [wMusicFade], a
-	ret
-
-Script_playsound:
-; script command 0x85
-; parameters: sound_pointer
-
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	call PlaySFX
-	ret
-
-Script_waitsfx:
-; script command 0x86
-
-	call WaitSFX
-	ret
-
-Script_warpsound:
-; script command 0x87
-
-	farcall GetWarpSFX
-	call PlaySFX
-	ret
-
-Script_cry:
-; script command 0x84
-; parameters: cry_id
-
-	call GetScriptByte
-	push af
-	call GetScriptByte
-	pop af
-	and a
-	jr nz, .ok
-	ld a, [wScriptVar]
-.ok
-	call PlayMonCry
-	ret
-
-GetScriptObject:
-	and a ; PLAYER?
-	ret z
-	cp LAST_TALKED
-	ret z
-	dec a
-	ret
-
-Script_setlasttalked:
-; script command 0x68
-; parameters: object_id
-
-	call GetScriptByte
-	call GetScriptObject
-	ld [hLastTalked], a
-	ret
-
-Script_applymovement:
-; script command 0x69
-; parameters: object_id, data
-
-	call GetScriptByte
-	call GetScriptObject
-	ld c, a
-
-ApplyMovement:
-	push bc
-	ld a, c
-	farcall SetFlagsForMovement_1
-	pop bc
-
-	push bc
-	call SetFlagsForMovement_2
-	pop bc
-
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	ld a, [wScriptBank]
-	ld b, a
-	call GetMovementData
-	ret c
-
-	ld a, SCRIPT_WAIT_MOVEMENT
-	ld [wScriptMode], a
-	call StopScript
-	ret
-
-SetFlagsForMovement_2:
-	farcall _SetFlagsForMovement_2
-	ret
-
-Script_applymovement2:
-; script command 0x6a
-; parameters: data
-; apply movement to last talked
-
-	ld a, [hLastTalked]
-	ld c, a
-	jp ApplyMovement
-
-Script_faceplayer:
-; script command 0x6b
-
-	ld a, [hLastTalked]
-	and a
-	ret z
-	ld d, $0
-	ld a, [hLastTalked]
-	ld e, a
-	farcall GetRelativeFacing
-	ld a, d
-	add a
-	add a
-	ld e, a
-	ld a, [hLastTalked]
-	ld d, a
-	call ApplyObjectFacing
-	ret
-
-Script_faceobject:
-; script command 0x6c
-; parameters: object1, object2
-
-	call GetScriptByte
-	call GetScriptObject
-	cp LAST_TALKED
-	jr c, .ok
-	ld a, [hLastTalked]
-.ok
-	ld e, a
-	call GetScriptByte
-	call GetScriptObject
-	cp LAST_TALKED
-	jr nz, .ok2
-	ld a, [hLastTalked]
-.ok2
-	ld d, a
-	push de
-	farcall GetRelativeFacing
-	pop bc
-	ret c
-	ld a, d
-	add a
-	add a
-	ld e, a
-	ld d, c
-	call ApplyObjectFacing
-	ret
-
-Script_turnobject:
-; script command 0x76
-; parameters: object_id, facing
-
-	call GetScriptByte
-	call GetScriptObject
-	cp LAST_TALKED
-	jr nz, .ok
-	ld a, [hLastTalked]
-.ok
-	ld d, a
-	call GetScriptByte
-	add a
-	add a
-	ld e, a
-	call ApplyObjectFacing
-	ret
-
-ApplyObjectFacing:
-	ld a, d
-	push de
-	call CheckObjectVisibility
-	jr c, .not_visible
-	ld hl, OBJECT_SPRITE
-	add hl, bc
-	ld a, [hl]
-	push bc
-	call DoesSpriteHaveFacings
-	pop bc
-	jr c, .not_visible ; STILL_SPRITE
-	ld hl, OBJECT_FLAGS1
-	add hl, bc
-	bit FIXED_FACING, [hl]
-	jr nz, .not_visible
-	pop de
-	ld a, e
-	call SetSpriteDirection
-	ld hl, wVramState
-	bit 6, [hl]
-	jr nz, .text_state
-	call .DisableTextTiles
-.text_state
-	call UpdateSprites
-	ret
-
-.not_visible
-	pop de
-	scf
-	ret
-
-.DisableTextTiles:
-	call LoadMapPart
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-.loop
-	res 7, [hl]
-	inc hl
-	dec bc
-	ld a, b
-	or c
-	jr nz, .loop
-	ret
-
-Script_variablesprite:
-; script command 0x6d
-; parameters: byte, sprite
-
-	call GetScriptByte
-	ld e, a
-	ld d, $0
-	ld hl, wVariableSprites
-	add hl, de
-	call GetScriptByte
-	ld [hl], a
-	ret
-
-Script_appear:
-; script command 0x6f
-; parameters: object_id
-
-	call GetScriptByte
-	call GetScriptObject
-	call _CopyObjectStruct
-	ld a, [hMapObjectIndexBuffer]
-	ld b, 0 ; clear
-	call ApplyEventActionAppearDisappear
-	ret
-
-Script_disappear:
-; script command 0x6e
-; parameters: object_id
-
-	call GetScriptByte
-	call GetScriptObject
-	cp LAST_TALKED
-	jr nz, .ok
-	ld a, [hLastTalked]
-.ok
-	call DeleteObjectStruct
-	ld a, [hMapObjectIndexBuffer]
-	ld b, 1 ; set
-	call ApplyEventActionAppearDisappear
-	farcall _UpdateSprites
-	ret
-
-ApplyEventActionAppearDisappear:
-	push bc
-	call GetMapObject
-	ld hl, MAPOBJECT_EVENT_FLAG
-	add hl, bc
-	pop bc
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	ld a, -1
-	cp e
-	jr nz, .okay
-	cp d
-	jr nz, .okay
-	xor a
-	ret
-.okay
-	call EventFlagAction
-	ret
-
-Script_follow:
-; script command 0x70
-; parameters: object2, object1
-
-	call GetScriptByte
-	call GetScriptObject
-	ld b, a
-	call GetScriptByte
-	call GetScriptObject
-	ld c, a
-	farcall StartFollow
-	ret
-
-Script_stopfollow:
-; script command 0x71
-
-	farcall StopFollow
-	ret
-
-Script_moveobject:
-; script command 0x72
-; parameters: object id, x, y
-
-	call GetScriptByte
-	call GetScriptObject
-	ld b, a
-	call GetScriptByte
-	add 4
-	ld d, a
-	call GetScriptByte
-	add 4
-	ld e, a
-	farcall CopyDECoordsToMapObject
-	ret
-
-Script_writeobjectxy:
-; script command 0x73
-; parameters: object_id
-
-	call GetScriptByte
-	call GetScriptObject
-	cp LAST_TALKED
-	jr nz, .ok
-	ld a, [hLastTalked]
-.ok
-	ld b, a
-	farcall WriteObjectXY
-	ret
-
-Script_follownotexact:
-; script command 0x77
-; parameters: object2, object1
-
-	call GetScriptByte
-	call GetScriptObject
-	ld b, a
-	call GetScriptByte
-	call GetScriptObject
-	ld c, a
-	farcall FollowNotExact
-	ret
-
-Script_loademote:
-; script command 0x74
-; parameters: bubble
-
-	call GetScriptByte
-	cp -1
-	jr nz, .not_var_emote
-	ld a, [wScriptVar]
-.not_var_emote
-	ld c, a
-	farcall LoadEmote
-	ret
-
-Script_showemote:
-; script command 0x75
-; parameters: bubble, object_id, time
-
-	call GetScriptByte
-	ld [wScriptVar], a
-	call GetScriptByte
-	call GetScriptObject
-	cp LAST_TALKED
-	jr z, .ok
-	ld [hLastTalked], a
-.ok
-	call GetScriptByte
-	ld [wScriptDelay], a
-	ld b, BANK(ShowEmoteScript)
-	ld de, ShowEmoteScript
-	jp ScriptCall
-
-ShowEmoteScript:
-	loademote EMOTE_MEM
-	applymovement2 .Show
-	pause 0
-	applymovement2 .Hide
-	end
-
-.Show:
-	show_emote
-	step_sleep 1
-	step_end
-
-.Hide:
-	hide_emote
-	step_sleep 1
-	step_end
-
-
-Script_earthquake:
-; script command 0x78
-; parameters: param
-
-	ld hl, EarthquakeMovement
-	ld de, wEarthquakeMovementDataBuffer
-	ld bc, EarthquakeMovement.End - EarthquakeMovement
-	call CopyBytes
-	call GetScriptByte
-	ld [wEarthquakeMovementDataBuffer + 1], a
-	and %00111111
-	ld [wEarthquakeMovementDataBuffer + 3], a
-	ld b, BANK(.script)
-	ld de, .script
-	jp ScriptCall
-
-.script
-	applymovement PLAYER, wEarthquakeMovementDataBuffer
-	end
-
-EarthquakeMovement:
-	step_shake 16 ; the 16 gets overwritten with the script byte
-	step_sleep 16 ; the 16 gets overwritten with the lower 6 bits of the script byte
-	step_end
-.End
-
-
-Script_loadpikachudata:
-; script command 0x5a
-
-	ld a, PIKACHU
-	ld [wTempWildMonSpecies], a
-	ld a, 5
-	ld [wCurPartyLevel], a
-	ret
-
-Script_randomwildmon:
-; script command 0x5b
-
-	xor a
-	ld [wBattleScriptFlags], a
-	ret
-
-Script_loadmemtrainer:
-; script command 0x5c
-
-	ld a, (1 << 7) | 1
-	ld [wBattleScriptFlags], a
-	ld a, [wTempTrainerClass]
-	ld [wOtherTrainerClass], a
-	ld a, [wTempTrainerID]
-	ld [wOtherTrainerID], a
-	ret
-
-Script_loadwildmon:
-; script command 0x5d
-; parameters: pokemon, level
-
-	ld a, (1 << 7)
-	ld [wBattleScriptFlags], a
-	call GetScriptByte
-	ld [wTempWildMonSpecies], a
-	call GetScriptByte
-	ld [wCurPartyLevel], a
-	ret
-
-Script_loadtrainer:
-; script command 0x5e
-; parameters: trainer_group, trainer_id
-
-	ld a, (1 << 7) | 1
-	ld [wBattleScriptFlags], a
-	call GetScriptByte
-	ld [wOtherTrainerClass], a
-	call GetScriptByte
-	ld [wOtherTrainerID], a
-	ret
-
-Script_startbattle:
-; script command 0x5f
-
-	call BufferScreen
-	predef StartBattle
-	ld a, [wBattleResult]
-	and $3f
-	ld [wScriptVar], a
-	ret
-
-Script_catchtutorial:
-; script command 0x61
-; parameters: byte
-
-	call GetScriptByte
-	ld [wBattleType], a
-	call BufferScreen
-	farcall CatchTutorial
-	jp Script_reloadmap
-
-Script_reloadmapafterbattle:
-; script command 0x60
-
-	ld hl, wBattleScriptFlags
-	ld d, [hl]
-	ld [hl], $0
-	ld a, [wBattleResult]
-	and $3f
-	cp $1
-	jr nz, .notblackedout
-	ld b, BANK(Script_BattleWhiteout)
-	ld hl, Script_BattleWhiteout
-	jp ScriptJump
-
-.notblackedout
-	bit 0, d
-	jr z, .was_wild
-	farcall MomTriesToBuySomething
-	jr .done
-
-.was_wild
-	ld a, [wBattleResult]
-	bit 7, a
-	jr z, .done
-	ld b, BANK(Script_SpecialBillCall)
-	ld de, Script_SpecialBillCall
-	farcall LoadScriptBDE
-.done
-	jp Script_reloadmap
-
-Script_reloadmap:
-; script command 0x7b
-
-	xor a
-	ld [wBattleScriptFlags], a
-	ld a, MAPSETUP_RELOADMAP
-	ld [hMapEntryMethod], a
-	ld a, $1
-	call LoadMapStatus
-	call StopScript
-	ret
-
-Script_scall:
-; script command 0x0
-; parameters: pointer
-
-	ld a, [wScriptBank]
-	ld b, a
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	jr ScriptCall
-
-Script_farscall:
-; script command 0x1
-; parameters: pointer
-
-	call GetScriptByte
-	ld b, a
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	jr ScriptCall
-
-Script_ptcall:
-; script command 0x2
-; parameters: pointer
-
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	ld b, [hl]
-	inc hl
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	; fallthrough
-
-ScriptCall:
-; Bug: The script stack has a capacity of 5 scripts, yet there is
-; nothing to stop you from pushing a sixth script.  The high part
-; of the script address can then be overwritten by modifications
-; to wScriptDelay, causing the script to return to the rst/interrupt
-; space.
-
-	push de
-	ld hl, wScriptStackSize
-	ld e, [hl]
-	inc [hl]
-	ld d, $0
-	ld hl, wScriptStack
-	add hl, de
-	add hl, de
-	add hl, de
-	pop de
-	ld a, [wScriptBank]
-	ld [hli], a
-	ld a, [wScriptPos]
-	ld [hli], a
-	ld a, [wScriptPos + 1]
-	ld [hl], a
-	ld a, b
-	ld [wScriptBank], a
-	ld a, e
-	ld [wScriptPos], a
-	ld a, d
-	ld [wScriptPos + 1], a
-	ret
-
-CallCallback::
-	ld a, [wScriptBank]
-	or $80
-	ld [wScriptBank], a
-	jp ScriptCall
-
-Script_jump:
-; script command 0x3
-; parameters: pointer
-
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	ld a, [wScriptBank]
-	ld b, a
-	jp ScriptJump
-
-Script_farjump:
-; script command 0x4
-; parameters: pointer
-
-	call GetScriptByte
-	ld b, a
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	jp ScriptJump
-
-Script_ptjump:
-; script command 0x5
-; parameters: pointer
-
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	ld b, [hl]
-	inc hl
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp ScriptJump
-
-Script_iffalse:
-; script command 0x8
-; parameters: pointer
-
-	ld a, [wScriptVar]
-	and a
-	jp nz, SkipTwoScriptBytes
-	jp Script_jump
-
-Script_iftrue:
-; script command 0x9
-; parameters: pointer
-
-	ld a, [wScriptVar]
-	and a
-	jp nz, Script_jump
-	jp SkipTwoScriptBytes
-
-Script_ifequal:
-; script command 0x6
-; parameters: byte, pointer
-
-	call GetScriptByte
-	ld hl, wScriptVar
-	cp [hl]
-	jr z, Script_jump
-	jr SkipTwoScriptBytes
-
-Script_ifnotequal:
-; script command 0x7
-; parameters: byte, pointer
-
-	call GetScriptByte
-	ld hl, wScriptVar
-	cp [hl]
-	jr nz, Script_jump
-	jr SkipTwoScriptBytes
-
-Script_ifgreater:
-; script command 0xa
-; parameters: byte, pointer
-
-	ld a, [wScriptVar]
-	ld b, a
-	call GetScriptByte
-	cp b
-	jr c, Script_jump
-	jr SkipTwoScriptBytes
-
-Script_ifless:
-; script command 0xb
-; parameters: byte, pointer
-
-	call GetScriptByte
-	ld b, a
-	ld a, [wScriptVar]
-	cp b
-	jr c, Script_jump
-	jr SkipTwoScriptBytes
-
-Script_jumpstd:
-; script command 0xc
-; parameters: predefined_script
-
-	call StdScript
-	jr ScriptJump
-
-Script_callstd:
-; script command 0xd
-; parameters: predefined_script
-
-	call StdScript
-	ld d, h
-	ld e, l
-	jp ScriptCall
-
-StdScript:
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld hl, StdScripts
-	add hl, de
-	add hl, de
-	add hl, de
-	ld a, BANK(StdScripts)
-	call GetFarByte
-	ld b, a
-	inc hl
-	ld a, BANK(StdScripts)
-	call GetFarHalfword
-	ret
-
-SkipTwoScriptBytes:
-	call GetScriptByte
-	call GetScriptByte
-	ret
-
-ScriptJump:
-	ld a, b
-	ld [wScriptBank], a
-	ld a, l
-	ld [wScriptPos], a
-	ld a, h
-	ld [wScriptPos + 1], a
-	ret
-
-Script_priorityjump:
-; script command 0x8d
-; parameters: pointer
-
-	ld a, [wScriptBank]
-	ld [wPriorityScriptBank], a
-	call GetScriptByte
-	ld [wPriorityScriptAddr], a
-	call GetScriptByte
-	ld [wPriorityScriptAddr + 1], a
-	ld hl, wScriptFlags
-	set 3, [hl]
-	ret
-
-Script_checkscene:
-; script command 0x13
-
-	call CheckScenes
-	jr z, .no_scene
-	ld [wScriptVar], a
-	ret
-
-.no_scene
-	ld a, $ff
-	ld [wScriptVar], a
-	ret
-
-Script_checkmapscene:
-; script command 0x11
-; parameters: map_group, map_id
-
-	call GetScriptByte
-	ld b, a
-	call GetScriptByte
-	ld c, a
-	call GetMapSceneID
-	ld a, d
-	or e
-	jr z, .no_scene
-	ld a, [de]
-	ld [wScriptVar], a
-	ret
-
-.no_scene
-	ld a, $ff
-	ld [wScriptVar], a
-	ret
-
-Script_setscene:
-; script command 0x14
-; parameters: scene_id
-
-	ld a, [wMapGroup]
-	ld b, a
-	ld a, [wMapNumber]
-	ld c, a
-	jr DoScene
-
-Script_setmapscene:
-; script command 0x12
-; parameters: map_group, map_id, scene_id
-
-	call GetScriptByte
-	ld b, a
-	call GetScriptByte
-	ld c, a
-DoScene:
-	call GetMapSceneID
-	ld a, d
-	or e
-	jr z, .no_scene
-	call GetScriptByte
-	ld [de], a
-.no_scene
-	ret
-
-Script_copybytetovar:
-; script command 0x19
-; parameters: address
-
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	ld a, [hl]
-	ld [wScriptVar], a
-	ret
-
-Script_copyvartobyte:
-; script command 0x1a
-; parameters: address
-
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	ld a, [wScriptVar]
-	ld [hl], a
-	ret
-
-Script_loadvar:
-; script command 0x1b
-; parameters: address, value
-
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	call GetScriptByte
-	ld [hl], a
-	ret
-
-Script_writebyte:
-; script command 0x15
-; parameters: value
-
-	call GetScriptByte
-	ld [wScriptVar], a
-	ret
-
-Script_addvar:
-; script command 0x16
-; parameters: value
-
-	call GetScriptByte
-	ld hl, wScriptVar
-	add [hl]
-	ld [hl], a
-	ret
-
-Script_random:
-; script command 0x17
-; parameters: input
-
-	call GetScriptByte
-	ld [wScriptVar], a
-	and a
-	ret z
-
-	ld c, a
-	call .Divide256byC
-	and a
-	jr z, .no_restriction ; 256 % b == 0
-	ld b, a
-	xor a
-	sub b
-	ld b, a
-.loop
-	push bc
-	call Random
-	pop bc
-	ld a, [hRandomAdd]
-	cp b
-	jr nc, .loop
-	jr .finish
-
-.no_restriction
-	push bc
-	call Random
-	pop bc
-	ld a, [hRandomAdd]
-
-.finish
-	push af
-	ld a, [wScriptVar]
-	ld c, a
-	pop af
-	call SimpleDivide
-	ld [wScriptVar], a
-	ret
-
-.Divide256byC:
-	xor a
-	ld b, a
-	sub c
-.mod_loop
-	inc b
-	sub c
-	jr nc, .mod_loop
-	dec b
-	add c
-	ret
-
-Script_checkcode:
-; script command 0x1c
-; parameters: variable_id
-
-	call GetScriptByte
-	call GetVarAction
-	ld a, [de]
-	ld [wScriptVar], a
-	ret
-
-Script_writevarcode:
-; script command 0x1d
-; parameters: variable_id
-
-	call GetScriptByte
-	call GetVarAction
-	ld a, [wScriptVar]
-	ld [de], a
-	ret
-
-Script_writecode:
-; script command 0x1e
-; parameters: variable_id, value
-
-	call GetScriptByte
-	call GetVarAction
-	call GetScriptByte
-	ld [de], a
-	ret
-
-GetVarAction:
-	ld c, a
-	farcall _GetVarAction
-	ret
-
-Script_checkver:
-; script command 0x18
-
-	ld a, [.gs_version]
-	ld [wScriptVar], a
-	ret
-
-.gs_version:
-	db GS_VERSION
-
-Script_pokenamemem:
-; script command 0x40
-; parameters: pokemon (0 aka USE_SCRIPT_VAR to use wScriptVar), memory
-
-	call GetScriptByte
-	and a
-	jr nz, .gotit
-	ld a, [wScriptVar]
-.gotit
-	ld [wd265], a
-	call GetPokemonName
-	ld de, wStringBuffer1
-
-ConvertMemToText:
-	call GetScriptByte
-	cp NUM_MEM_BUFFERS
-	jr c, .ok
-	xor a
-.ok
-
-CopyConvertedText:
-	ld hl, wStringBuffer3
-	ld bc, wStringBuffer4 - wStringBuffer3
-	call AddNTimes
-	call CopyName2
-	ret
-
-Script_itemtotext:
-; script command 0x41
-; parameters: item (0 aka USE_SCRIPT_VAR to use wScriptVar), memory
-
-	call GetScriptByte
-	and a ; USE_SCRIPT_VAR
-	jr nz, .ok
-	ld a, [wScriptVar]
-.ok
-	ld [wd265], a
-	call GetItemName
-	ld de, wStringBuffer1
-	jr ConvertMemToText
-
-Script_mapnametotext:
-; script command 0x42
-; parameters: memory
-
-	ld a, [wMapGroup]
-	ld b, a
-	ld a, [wMapNumber]
-	ld c, a
-	call GetWorldMapLocation
-
-ConvertLandmarkToText:
-	ld e, a
-	farcall GetLandmarkName
-	ld de, wStringBuffer1
-	jp ConvertMemToText
-
-Script_landmarktotext:
-; script command 0xa5
-; parameters: id, memory
-
-	call GetScriptByte
-	jr ConvertLandmarkToText
-
-Script_trainertotext:
-; script command 0x43
-; parameters: trainer_id, trainer_group, memory
-
-	call GetScriptByte
-	ld c, a
-	call GetScriptByte
-	ld b, a
-	farcall GetTrainerName
-	jr ConvertMemToText
-
-Script_name:
-; script command 0xa7
-; parameters: type, id, memory
-
-	call GetScriptByte
-	ld [wNamedObjectTypeBuffer], a
-
-ContinueToGetName:
-	call GetScriptByte
-	ld [wCurSpecies], a
-	call GetName
-	ld de, wStringBuffer1
-	jp ConvertMemToText
-
-Script_trainerclassname:
-; script command 0xa6
-; parameters: id, memory
-
-	ld a, TRAINER_NAME
-	ld [wNamedObjectTypeBuffer], a
-	jr ContinueToGetName
-
-Script_readmoney:
-; script command 0x3d
-; parameters: account, memory
-
-	call ResetStringBuffer1
-	call GetMoneyAccount
-	ld hl, wStringBuffer1
-	lb bc, PRINTNUM_RIGHTALIGN | 3, 6
-	call PrintNum
-	ld de, wStringBuffer1
-	jp ConvertMemToText
-
-Script_readcoins:
-; script command 0x3e
-; parameters: memory
-
-	call ResetStringBuffer1
-	ld hl, wStringBuffer1
-	ld de, wCoins
-	lb bc, PRINTNUM_RIGHTALIGN | 2, 6
-	call PrintNum
-	ld de, wStringBuffer1
-	jp ConvertMemToText
-
-Script_vartomem:
-; script command 0x3f
-; parameters: memory
-
-	call ResetStringBuffer1
-	ld de, wScriptVar
-	ld hl, wStringBuffer1
-	lb bc, PRINTNUM_RIGHTALIGN | 1, 3
-	call PrintNum
-	ld de, wStringBuffer1
-	jp ConvertMemToText
-
-ResetStringBuffer1:
-	ld hl, wStringBuffer1
-	ld bc, NAME_LENGTH
-	ld a, "@"
-	call ByteFill
-	ret
-
-Script_stringtotext:
-; script command 0x44
-; parameters: text_pointer, memory
-
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld a, [wScriptBank]
-	ld hl, CopyName1
-	rst FarCall
-	ld de, wStringBuffer2
-	jp ConvertMemToText
-
-Script_givepokeitem:
-; script command 0x2f
-; parameters: pointer
-
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	ld a, [wScriptBank]
-	call GetFarByte
-	ld b, a
-	push bc
-	inc hl
-	ld bc, MAIL_MSG_LENGTH
-	ld de, wd002
-	ld a, [wScriptBank]
-	call FarCopyBytes
-	pop bc
-	farcall GivePokeItem
-	ret
-
-Script_checkpokeitem:
-; script command 0x30
-; parameters: pointer
-
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld a, [wScriptBank]
-	ld b, a
-	farcall CheckPokeItem
-	ret
-
-Script_giveitem:
-; script command 0x1f
-; parameters: item, quantity
-
-	call GetScriptByte
-	cp ITEM_FROM_MEM
-	jr nz, .ok
-	ld a, [wScriptVar]
-.ok
-	ld [wCurItem], a
-	call GetScriptByte
-	ld [wItemQuantityChangeBuffer], a
-	ld hl, wNumItems
-	call ReceiveItem
-	jr nc, .full
-	ld a, TRUE
-	ld [wScriptVar], a
-	ret
-.full
-	xor a
-	ld [wScriptVar], a
-	ret
-
-Script_takeitem:
-; script command 0x20
-; parameters: item, quantity
-
-	xor a
-	ld [wScriptVar], a
-	call GetScriptByte
-	ld [wCurItem], a
-	call GetScriptByte
-	ld [wItemQuantityChangeBuffer], a
-	ld a, -1
-	ld [wCurItemQuantity], a
-	ld hl, wNumItems
-	call TossItem
-	ret nc
-	ld a, TRUE
-	ld [wScriptVar], a
-	ret
-
-Script_checkitem:
-; script command 0x21
-; parameters: item
-
-	xor a
-	ld [wScriptVar], a
-	call GetScriptByte
-	ld [wCurItem], a
-	ld hl, wNumItems
-	call CheckItem
-	ret nc
-	ld a, TRUE
-	ld [wScriptVar], a
-	ret
-
-Script_givemoney:
-; script command 0x22
-; parameters: account, money
-
-	call GetMoneyAccount
-	call LoadMoneyAmountToMem
-	farcall GiveMoney
-	ret
-
-Script_takemoney:
-; script command 0x23
-; parameters: account, money
-
-	call GetMoneyAccount
-	call LoadMoneyAmountToMem
-	farcall TakeMoney
-	ret
-
-Script_checkmoney:
-; script command 0x24
-; parameters: account, money
-
-	call GetMoneyAccount
-	call LoadMoneyAmountToMem
-	farcall CompareMoney
-
-CompareMoneyAction:
-	jr c, .less
-	jr z, .exact
-	ld a, HAVE_MORE
-	jr .done
-.exact
-	ld a, HAVE_AMOUNT
-	jr .done
-.less
-	ld a, HAVE_LESS
-.done
-	ld [wScriptVar], a
-	ret
-
-GetMoneyAccount:
-	call GetScriptByte
-	and a
-	ld de, wMoney ; YOUR_MONEY
-	ret z
-	ld de, wMomsMoney ; MOMS_MONEY
-	ret
-
-LoadMoneyAmountToMem:
-	ld bc, hMoneyTemp
-	push bc
-	call GetScriptByte
-	ld [bc], a
-	inc bc
-	call GetScriptByte
-	ld [bc], a
-	inc bc
-	call GetScriptByte
-	ld [bc], a
-	pop bc
-	ret
-
-Script_givecoins:
-; script command 0x25
-; parameters: coins
-
-	call LoadCoinAmountToMem
-	farcall GiveCoins
-	ret
-
-Script_takecoins:
-; script command 0x26
-; parameters: coins
-
-	call LoadCoinAmountToMem
-	farcall TakeCoins
-	ret
-
-Script_checkcoins:
-; script command 0x27
-; parameters: coins
-
-	call LoadCoinAmountToMem
-	farcall CheckCoins
-	jr CompareMoneyAction
-
-LoadCoinAmountToMem:
-	call GetScriptByte
-	ld [hMoneyTemp + 1], a
-	call GetScriptByte
-	ld [hMoneyTemp], a
-	ld bc, hMoneyTemp
-	ret
-
-Script_checktime:
-; script command 0x2b
-; parameters: time
-
-	xor a
-	ld [wScriptVar], a
-	farcall CheckTime
-	call GetScriptByte
-	and c
-	ret z
-	ld a, TRUE
-	ld [wScriptVar], a
-	ret
-
-Script_checkpoke:
-; script command 0x2c
-; parameters: pokemon
-
-	xor a
-	ld [wScriptVar], a
-	call GetScriptByte
-	ld hl, wPartySpecies
-	ld de, 1
-	call IsInArray
-	ret nc
-	ld a, TRUE
-	ld [wScriptVar], a
-	ret
-
-Script_addcellnum:
-; script command 0x28
-; parameters: person
-
-	xor a
-	ld [wScriptVar], a
-	call GetScriptByte
-	ld c, a
-	farcall AddPhoneNumber
-	ret nc
-	ld a, TRUE
-	ld [wScriptVar], a
-	ret
-
-Script_delcellnum:
-; script command 0x29
-; parameters: person
-
-	xor a
-	ld [wScriptVar], a
-	call GetScriptByte
-	ld c, a
-	farcall DelCellNum
-	ret nc
-	ld a, TRUE
-	ld [wScriptVar], a
-	ret
-
-Script_checkcellnum:
-; script command 0x2a
-; parameters: person
-; returns false if the cell number is not in your phone
-
-	xor a
-	ld [wScriptVar], a
-	call GetScriptByte
-	ld c, a
-	farcall CheckCellNum
-	ret nc
-	ld a, TRUE
-	ld [wScriptVar], a
-	ret
-
-Script_specialphonecall:
-; script command 0x9c
-; parameters: call_id
-
-	call GetScriptByte
-	ld [wSpecialPhoneCallID], a
-	call GetScriptByte
-	ld [wSpecialPhoneCallID + 1], a
-	ret
-
-Script_checkphonecall:
-; script command 0x9d
-; returns false if no special phone call is stored
-
-	ld a, [wSpecialPhoneCallID]
-	and a
-	jr z, .ok
-	ld a, TRUE
-.ok
-	ld [wScriptVar], a
-	ret
-
-Script_givepoke:
-; script command 0x2d
-; parameters: pokemon, level, item, trainer, trainer_name_pointer, pkmn_nickname
-
-	call GetScriptByte
-	ld [wCurPartySpecies], a
-	call GetScriptByte
-	ld [wCurPartyLevel], a
-	call GetScriptByte
-	ld [wCurItem], a
-	call GetScriptByte
-	and a
-	ld b, a
-	jr z, .ok
-	ld hl, wScriptPos
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	call GetScriptByte
-	call GetScriptByte
-	call GetScriptByte
-	call GetScriptByte
-.ok
-	farcall GivePoke
-	ld a, b
-	ld [wScriptVar], a
-	ret
-
-Script_giveegg:
-; script command 0x2e
-; parameters: pokemon, level
-; if no room in the party, return 0 in wScriptVar; else, return 2
-
-	xor a ; PARTYMON
-	ld [wScriptVar], a
-	ld [wMonType], a
-	call GetScriptByte
-	ld [wCurPartySpecies], a
-	call GetScriptByte
-	ld [wCurPartyLevel], a
-	farcall GiveEgg
-	ret nc
-	ld a, 2
-	ld [wScriptVar], a
-	ret
-
-Script_setevent:
-; script command 0x33
-; parameters: bit_number
-
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld b, SET_FLAG
-	call EventFlagAction
-	ret
-
-Script_clearevent:
-; script command 0x32
-; parameters: bit_number
-
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld b, RESET_FLAG
-	call EventFlagAction
-	ret
-
-Script_checkevent:
-; script command 0x31
-; parameters: bit_number
-
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld b, CHECK_FLAG
-	call EventFlagAction
-	ld a, c
-	and a
-	jr z, .false
-	ld a, TRUE
-.false
-	ld [wScriptVar], a
-	ret
-
-Script_setflag:
-; script command 0x36
-; parameters: bit_number
-
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld b, SET_FLAG
-	call _EngineFlagAction
-	ret
-
-Script_clearflag:
-; script command 0x35
-; parameters: bit_number
-
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld b, RESET_FLAG
-	call _EngineFlagAction
-	ret
-
-Script_checkflag:
-; script command 0x34
-; parameters: bit_number
-
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld b, CHECK_FLAG
-	call _EngineFlagAction
-	ld a, c
-	and a
-	jr z, .false
-	ld a, TRUE
-.false
-	ld [wScriptVar], a
-	ret
-
-_EngineFlagAction:
-	farcall EngineFlagAction
-	ret
-
-Script_wildoff:
-; script command 0x38
-
-	ld hl, wStatusFlags
-	set STATUSFLAGS_NO_WILD_ENCOUNTERS_F, [hl]
-	ret
-
-Script_wildon:
-; script command 0x37
-
-	ld hl, wStatusFlags
-	res STATUSFLAGS_NO_WILD_ENCOUNTERS_F, [hl]
-	ret
-
-Script_xycompare:
-; script command 0x39
-; parameters: pointer
-
-	call GetScriptByte
-	ld [wXYComparePointer], a
-	call GetScriptByte
-	ld [wXYComparePointer + 1], a
-	ret
-
-Script_warpfacing:
-; script command 0xa3
-; parameters: facing, map_group, map_id, x, y
-
-	call GetScriptByte
-	maskbits NUM_DIRECTIONS
-	ld c, a
-	ld a, [wPlayerSpriteSetupFlags]
-	set PLAYERSPRITESETUP_CUSTOM_FACING_F, a
-	or c
-	ld [wPlayerSpriteSetupFlags], a
-; fall through
-
-Script_warp:
-; script command 0x3c
-; parameters: map_group, map_id, x, y
-
-; This seems to be some sort of error handling case.
-	call GetScriptByte
-	and a
-	jr z, .not_ok
-	ld [wMapGroup], a
-	call GetScriptByte
-	ld [wMapNumber], a
-	call GetScriptByte
-	ld [wXCoord], a
-	call GetScriptByte
-	ld [wYCoord], a
-	ld a, -1
-	ld [wDefaultSpawnpoint], a
-	ld a, MAPSETUP_WARP
-	ld [hMapEntryMethod], a
-	ld a, 1
-	call LoadMapStatus
-	call StopScript
-	ret
-
-.not_ok
-	call GetScriptByte
-	call GetScriptByte
-	call GetScriptByte
-	ld a, -1
-	ld [wDefaultSpawnpoint], a
-	ld a, MAPSETUP_BADWARP
-	ld [hMapEntryMethod], a
-	ld a, 1
-	call LoadMapStatus
-	call StopScript
-	ret
-
-Script_warpmod:
-; script command 0x3a
-; parameters: warp_id, map_group, map_id
-
-	call GetScriptByte
-	ld [wBackupWarpNumber], a
-	call GetScriptByte
-	ld [wBackupMapGroup], a
-	call GetScriptByte
-	ld [wBackupMapNumber], a
-	ret
-
-Script_blackoutmod:
-; script command 0x3b
-; parameters: map_group, map_id
-
-	call GetScriptByte
-	ld [wLastSpawnMapGroup], a
-	call GetScriptByte
-	ld [wLastSpawnMapNumber], a
-	ret
-
-Script_dontrestartmapmusic:
-; script command 0x83
-
-	ld a, 1
-	ld [wDontPlayMapMusicOnReload], a
-	ret
-
-Script_writecmdqueue:
-; script command 0x7d
-; parameters: queue_pointer
-
-	call GetScriptByte
-	ld e, a
-	call GetScriptByte
-	ld d, a
-	ld a, [wScriptBank]
-	ld b, a
-	farcall WriteCmdQueue ; no need to farcall
-	ret
-
-Script_delcmdqueue:
-; script command 0x7e
-; parameters: byte
-
-	xor a
-	ld [wScriptVar], a
-	call GetScriptByte
-	ld b, a
-	farcall DelCmdQueue ; no need to farcall
-	ret c
-	ld a, 1
-	ld [wScriptVar], a
-	ret
-
-Script_changemap:
-; script command 0x79
-; parameters: map_data_pointer
-
-	call GetScriptByte
-	ld [wMapBlocksBank], a
-	call GetScriptByte
-	ld [wMapBlocksPointer], a
-	call GetScriptByte
-	ld [wMapBlocksPointer + 1], a
-	call ChangeMap
-	call BufferScreen
-	ret
-
-Script_changeblock:
-; script command 0x7a
-; parameters: x, y, block
-
-	call GetScriptByte
-	add 4
-	ld d, a
-	call GetScriptByte
-	add 4
-	ld e, a
-	call GetBlockLocation
-	call GetScriptByte
-	ld [hl], a
-	call BufferScreen
-	ret
-
-Script_reloadmappart::
-; script command 0x7c
-
-	xor a
-	ld [hBGMapMode], a
-	call OverworldTextModeSwitch
-	call GetMovementPermissions
-	farcall ReloadMapPart
-	call UpdateSprites
-	ret
-
-Script_warpcheck:
-; script command 0x8e
-
-	call WarpCheck
-	ret nc
-	farcall EnableEvents
-	ret
-
-Script_enableevents:
-; unused
-	farcall EnableEvents
-	ret
-
-Script_newloadmap:
-; script command 0x8a
-; parameters: which_method
-
-	call GetScriptByte
-	ld [hMapEntryMethod], a
-	ld a, 1
-	call LoadMapStatus
-	call StopScript
-	ret
-
-Script_reloadandreturn:
-; script command 0x92
-
-	call Script_newloadmap
-	jp Script_end
-
-Script_opentext:
-; script command 0x47
-
-	call OpenText
-	ret
-
-Script_refreshscreen:
-; script command 0x48
-; parameters: dummy
-
-	call RefreshScreen
-	call GetScriptByte
-	ret
-
-Script_loadbytec2cf:
-; script command 0x4a
-; parameters: byte
-
-	call GetScriptByte
-	ld [wc2cf], a
-	ret
-
-	db closetext_command ; unused
-
-Script_closetext:
-; script command 0x49
-
-	call _OpenAndCloseMenu_HDMATransferTileMapAndAttrMap
-	call CloseText
-	ret
-
-
-Script_passtoengine:
-; script command 0x89
-; parameters: data_pointer
-
-	call GetScriptByte
-	push af
-	call GetScriptByte
-	ld l, a
-	call GetScriptByte
-	ld h, a
-	pop af
-	call StartAutoInput
-	ret
-
-Script_pause:
-; script command 0x8b
-; parameters: length
-
-	call GetScriptByte
-	and a
-	jr z, .loop
-	ld [wScriptDelay], a
-.loop
-	ld c, 2
-	call DelayFrames
-	ld hl, wScriptDelay
-	dec [hl]
-	jr nz, .loop
-	ret
-
-Script_deactivatefacing:
-; script command 0x8c
-; parameters: time
-
-	call GetScriptByte
-	and a
-	jr z, .no_time
-	ld [wScriptDelay], a
-.no_time
-	ld a, SCRIPT_WAIT
-	ld [wScriptMode], a
-	call StopScript
-	ret
-
-Script_ptpriorityjump:
-; script command 0x8f
-; parameters: pointer
-
-	call StopScript
-	jp Script_jump
-
-Script_end:
-; script command 0x91
-
-	call ExitScriptSubroutine
-	jr c, .resume
-	ret
-
-.resume
-	xor a
-	ld [wScriptRunning], a
-	ld a, SCRIPT_OFF
-	ld [wScriptMode], a
-	ld hl, wScriptFlags
-	res 0, [hl]
-	call StopScript
-	ret
-
-Script_return:
-; script command 0x90
-
-	call ExitScriptSubroutine
-	jr c, .dummy
-.dummy
-	ld hl, wScriptFlags
-	res 0, [hl]
-	call StopScript
-	ret
-
-ExitScriptSubroutine:
-; Return carry if there's no parent to return to.
-
-	ld hl, wScriptStackSize
-	ld a, [hl]
-	and a
-	jr z, .done
-	dec [hl]
-	ld e, [hl]
-	ld d, $0
-	ld hl, wScriptStack
-	add hl, de
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld b, a
-	and " "
-	ld [wScriptBank], a
-	ld a, [hli]
-	ld e, a
-	ld [wScriptPos], a
-	ld a, [hl]
-	ld d, a
-	ld [wScriptPos + 1], a
-	and a
-	ret
-.done
-	scf
-	ret
-
-Script_endall:
-; script command 0x93
-
-	xor a
-	ld [wScriptStackSize], a
-	ld [wScriptRunning], a
-	ld a, SCRIPT_OFF
-	ld [wScriptMode], a
-	ld hl, wScriptFlags
-	res 0, [hl]
-	call StopScript
-	ret
-
-Script_halloffame:
-; script command 0xa1
-
-	ld hl, wGameTimerPause
-	res GAMETIMERPAUSE_TIMER_PAUSED_F, [hl]
-	farcall StubbedTrainerRankings_HallOfFame
-	farcall StubbedTrainerRankings_HallOfFame2
-	farcall HallOfFame
-	ld hl, wGameTimerPause
-	set GAMETIMERPAUSE_TIMER_PAUSED_F, [hl]
-	jr ReturnFromCredits
-
-Script_credits:
-; script command 0xa2
-
-	farcall RedCredits
-ReturnFromCredits:
-	call Script_endall
-	ld a, $3
-	call LoadMapStatus
-	call StopScript
-	ret
-
-Script_wait:
-; script command 0xa8
-; parameters: unknown
-
-	push bc
-	call GetScriptByte
-.loop
-	push af
-	ld c, 6
-	call DelayFrames
-	pop af
-	dec a
-	jr nz, .loop
-	pop bc
-	ret
-
-Script_checksave:
-; script command 0xa9
-
-	farcall CheckSave
-	ld a, c
-	ld [wScriptVar], a
-	ret
-
-
-; unused
-	ld a, [.byte]
-	ld [wScriptVar], a
-	ret
-
-.byte
-	db 0
--- a/engine/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/search.asm
+++ /dev/null
@@ -1,276 +1,0 @@
-BeastsCheck: ; 0x4a6e8
-; Check if the player owns all three legendary beasts.
-; They must exist in either party or PC, and have the player's OT and ID.
-; Return the result in wScriptVar.
-
-	ld a, RAIKOU
-	ld [wScriptVar], a
-	call CheckOwnMonAnywhere
-	jr nc, .notexist
-
-	ld a, ENTEI
-	ld [wScriptVar], a
-	call CheckOwnMonAnywhere
-	jr nc, .notexist
-
-	ld a, SUICUNE
-	ld [wScriptVar], a
-	call CheckOwnMonAnywhere
-	jr nc, .notexist
-
-	; they exist
-	ld a, 1
-	ld [wScriptVar], a
-	ret
-
-.notexist
-	xor a
-	ld [wScriptVar], a
-	ret
-
-
-MonCheck: ; 0x4a711
-; Check if the player owns any Pokémon of the species in wScriptVar.
-; Return the result in wScriptVar.
-
-	call CheckOwnMonAnywhere
-	jr c, .exists
-
-	; doesn't exist
-	xor a
-	ld [wScriptVar], a
-	ret
-
-.exists
-	ld a, 1
-	ld [wScriptVar], a
-	ret
-
-
-CheckOwnMonAnywhere: ; 0x4a721
-; Check if the player owns any monsters of the species in wScriptVar.
-; It must exist in either party or PC, and have the player's OT and ID.
-
-	; If there are no monsters in the party,
-	; the player must not own any yet.
-	ld a, [wPartyCount]
-	and a
-	ret z
-
-	ld d, a
-	ld e, 0
-	ld hl, wPartyMon1Species
-	ld bc, wPartyMonOT
-
-	; Run CheckOwnMon on each Pokémon in the party.
-.partymon
-	call CheckOwnMon
-	ret c ; found!
-
-	push bc
-	ld bc, PARTYMON_STRUCT_LENGTH
-	add hl, bc
-	pop bc
-	call UpdateOTPointer
-	dec d
-	jr nz, .partymon
-
-	; Run CheckOwnMon on each Pokémon in the PC.
-	ld a, BANK(sBoxCount)
-	call GetSRAMBank
-	ld a, [sBoxCount]
-	and a
-	jr z, .boxes
-
-	ld d, a
-	ld hl, sBoxMon1Species
-	ld bc, sBoxMonOT
-.openboxmon
-	call CheckOwnMon
-	jr nc, .loop
-
-	; found!
-	call CloseSRAM
-	ret
-
-.loop
-	push bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	add hl, bc
-	pop bc
-	call UpdateOTPointer
-	dec d
-	jr nz, .openboxmon
-
-	; Run CheckOwnMon on each monster in the other 13 PC boxes.
-.boxes
-	call CloseSRAM
-
-	ld c, 0
-.box
-	; Don't search the current box again.
-	ld a, [wCurBox]
-	and $f
-	cp c
-	jr z, .loopbox
-
-	; Load the box.
-	ld hl, BoxAddressTable1
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	call GetSRAMBank
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-
-	; Number of monsters in the box
-	ld a, [hl]
-	and a
-	jr z, .loopbox
-
-	push bc
-
-	push hl
-	ld de, sBoxMons - sBoxCount
-	add hl, de
-	ld d, h
-	ld e, l
-	pop hl
-	push de
-	ld de, sBoxMonOT - sBoxCount
-	add hl, de
-	ld b, h
-	ld c, l
-	pop hl
-
-	ld d, a
-
-.boxmon
-	call CheckOwnMon
-	jr nc, .loopboxmon
-
-	; found!
-	pop bc
-	call CloseSRAM
-	ret
-
-.loopboxmon
-	push bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	add hl, bc
-	pop bc
-	call UpdateOTPointer
-	dec d
-	jr nz, .boxmon
-	pop bc
-
-.loopbox
-	inc c
-	ld a, c
-	cp NUM_BOXES
-	jr c, .box
-
-	; not found
-	call CloseSRAM
-	and a
-	ret
-
-
-CheckOwnMon: ; 0x4a7ba
-; Check if a Pokémon belongs to the player and is of a specific species.
-
-; inputs:
-; hl, pointer to PartyMonNSpecies
-; bc, pointer to PartyMonNOT
-; wScriptVar should contain the species we're looking for
-
-; outputs:
-; sets carry if monster matches species, ID, and OT name.
-
-	push bc
-	push hl
-	push de
-	ld d, b
-	ld e, c
-
-; check species
-	ld a, [wScriptVar] ; species we're looking for
-	ld b, [hl] ; species we have
-	cp b
-	jr nz, .notfound ; species doesn't match
-
-; check ID number
-	ld bc, MON_ID
-	add hl, bc ; now hl points to ID number
-	ld a, [wPlayerID]
-	cp [hl]
-	jr nz, .notfound ; ID doesn't match
-	inc hl
-	ld a, [wPlayerID + 1]
-	cp [hl]
-	jr nz, .notfound ; ID doesn't match
-
-; check OT
-; This only checks five characters, which is fine for the Japanese version,
-; but in the English version the player name is 7 characters, so this is wrong.
-
-	ld hl, wPlayerName
-
-rept NAME_LENGTH_JAPANESE + -2 ; should be PLAYER_NAME_LENGTH + -2
-	ld a, [de]
-	cp [hl]
-	jr nz, .notfound
-	cp "@"
-	jr z, .found ; reached end of string
-	inc hl
-	inc de
-endr
-
-	ld a, [de]
-	cp [hl]
-	jr z, .found
-
-.notfound
-	pop de
-	pop hl
-	pop bc
-	and a
-	ret
-
-.found
-	pop de
-	pop hl
-	pop bc
-	scf
-	ret
-; 0x4a810
-
-BoxAddressTable1: ; 4a810
-	dba sBox1
-	dba sBox2
-	dba sBox3
-	dba sBox4
-	dba sBox5
-	dba sBox6
-	dba sBox7
-	dba sBox8
-	dba sBox9
-	dba sBox10
-	dba sBox11
-	dba sBox12
-	dba sBox13
-	dba sBox14
-; 4a83a
-
-UpdateOTPointer: ; 0x4a83a
-	push hl
-	ld hl, NAME_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	pop hl
-	ret
-; 0x4a843
--- a/engine/search2.asm
+++ /dev/null
@@ -1,134 +1,0 @@
-_FindPartyMonAboveLevel: ; 4dbd2
-	ld hl, wPartyMon1Level
-	call FindAboveLevel
-	ret
-
-_FindPartyMonAtLeastThatHappy: ; 4dbd9
-	ld hl, wPartyMon1Happiness
-	call FindAtLeastThatHappy
-	ret
-
-_FindPartyMonThatSpecies: ; 4dbe0
-	ld hl, wPartyMon1Species
-	jp FindThatSpecies
-
-_FindPartyMonThatSpeciesYourTrainerID: ; 4dbe6
-	ld hl, wPartyMon1Species
-	call FindThatSpecies
-	ret z
-	ld a, c
-	ld hl, wPartyMon1ID
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [wPlayerID]
-	cp [hl]
-	jr nz, .nope
-	inc hl
-	ld a, [wPlayerID + 1]
-	cp [hl]
-	jr nz, .nope
-	ld a, $1
-	and a
-	ret
-
-.nope
-	xor a
-	ret
-
-FindAtLeastThatHappy: ; 4dc0a
-; Sets the bits for the Pokemon that have a happiness greater than or equal to b.
-; The lowest bits are used.  Sets z if no Pokemon in your party is at least that happy.
-	ld c, $0
-	ld a, [wPartyCount]
-	ld d, a
-.loop
-	ld a, d
-	dec a
-	push hl
-	push bc
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	pop bc
-	ld a, b
-	cp [hl]
-	pop hl
-	jr z, .greater_equal
-	jr nc, .lower
-
-.greater_equal
-	ld a, c
-	or $1
-	ld c, a
-
-.lower
-	sla c
-	dec d
-	jr nz, .loop
-	call RetroactivelyIgnoreEggs
-	ld a, c
-	and a
-	ret
-
-FindAboveLevel: ; 4dc31
-	ld c, $0
-	ld a, [wPartyCount]
-	ld d, a
-.loop
-	ld a, d
-	dec a
-	push hl
-	push bc
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	pop bc
-	ld a, b
-	cp [hl]
-	pop hl
-	jr c, .greater
-	ld a, c
-	or $1
-	ld c, a
-
-.greater
-	sla c
-	dec d
-	jr nz, .loop
-	call RetroactivelyIgnoreEggs
-	ld a, c
-	and a
-	ret
-
-FindThatSpecies: ; 4dc56
-; Find species b in your party.
-; If you have no Pokemon, returns c = -1 and z.
-; If that species is in your party, returns its location in c, and nz.
-; Otherwise, returns z.
-	ld c, -1
-	ld hl, wPartySpecies
-.loop
-	ld a, [hli]
-	cp -1
-	ret z
-	inc c
-	cp b
-	jr nz, .loop
-	ld a, $1
-	and a
-	ret
-
-RetroactivelyIgnoreEggs: ; 4dc67
-	ld e, -2
-	ld hl, wPartySpecies
-.loop
-	ld a, [hli]
-	cp -1
-	ret z
-	cp EGG
-	jr nz, .skip_notegg
-	ld a, c
-	and e
-	ld c, a
-
-.skip_notegg
-	rlc e
-	jr .loop
--- a/engine/select_menu.asm
+++ /dev/null
@@ -1,191 +1,0 @@
-SelectMenu:: ; 13327
-
-	call CheckRegisteredItem
-	jr c, .NotRegistered
-	jp UseRegisteredItem
-
-.NotRegistered:
-	call OpenText
-	ld b, BANK(ItemMayBeRegisteredText)
-	ld hl, ItemMayBeRegisteredText
-	call MapTextbox
-	call WaitButton
-	jp CloseText
-; 13340
-
-
-ItemMayBeRegisteredText: ; 13340
-	text_jump UnknownText_0x1c1cf3
-	db "@"
-; 13345
-
-
-CheckRegisteredItem: ; 13345
-
-	ld a, [wWhichRegisteredItem]
-	and a
-	jr z, .NoRegisteredItem
-	and REGISTERED_POCKET
-	rlca
-	rlca
-	ld hl, .Pockets
-	rst JumpTable
-	ret
-
-.Pockets:
-; entries correspond to *_POCKET constants
-	dw .CheckItem
-	dw .CheckBall
-	dw .CheckKeyItem
-	dw .CheckTMHM
-
-.CheckItem:
-	ld hl, wNumItems
-	call .CheckRegisteredNo
-	jr c, .NoRegisteredItem
-	inc hl
-	ld e, a
-	ld d, 0
-	add hl, de
-	add hl, de
-	call .IsSameItem
-	jr c, .NoRegisteredItem
-	and a
-	ret
-
-.CheckKeyItem:
-	ld a, [wRegisteredItem]
-	ld hl, wKeyItems
-	ld de, 1
-	call IsInArray
-	jr nc, .NoRegisteredItem
-	ld a, [wRegisteredItem]
-	ld [wCurItem], a
-	and a
-	ret
-
-.CheckBall:
-	ld hl, wNumBalls
-	call .CheckRegisteredNo
-	jr nc, .NoRegisteredItem
-	inc hl
-	ld e, a
-	ld d, 0
-	add hl, de
-	add hl, de
-	call .IsSameItem
-	jr c, .NoRegisteredItem
-	ret
-
-.CheckTMHM:
-	jr .NoRegisteredItem
-
-.NoRegisteredItem:
-	xor a
-	ld [wWhichRegisteredItem], a
-	ld [wRegisteredItem], a
-	scf
-	ret
-; 133a6
-
-
-.CheckRegisteredNo: ; 133a6
-	ld a, [wWhichRegisteredItem]
-	and REGISTERED_NUMBER
-	dec a
-	cp [hl]
-	jr nc, .NotEnoughItems
-	ld [wCurItemQuantity], a
-	and a
-	ret
-
-.NotEnoughItems:
-	scf
-	ret
-; 133b6
-
-
-.IsSameItem: ; 133b6
-	ld a, [wRegisteredItem]
-	cp [hl]
-	jr nz, .NotSameItem
-	ld [wCurItem], a
-	and a
-	ret
-
-.NotSameItem:
-	scf
-	ret
-; 133c3
-
-
-UseRegisteredItem: ; 133c3
-
-	farcall CheckItemMenu
-	ld a, [wItemAttributeParamBuffer]
-	ld hl, .SwitchTo
-	rst JumpTable
-	ret
-
-.SwitchTo:
-; entries correspond to ITEMMENU_* constants
-	dw .CantUse
-	dw .NoFunction
-	dw .NoFunction
-	dw .NoFunction
-	dw .Current
-	dw .Party
-	dw .Overworld
-; 133df
-
-.NoFunction: ; 133df
-	call OpenText
-	call CantUseItem
-	call CloseText
-	and a
-	ret
-; 133ea
-
-.Current: ; 133ea
-	call OpenText
-	call DoItemEffect
-	call CloseText
-	and a
-	ret
-; 133f5
-
-.Party: ; 133f5
-	call RefreshScreen
-	call FadeToMenu
-	call DoItemEffect
-	call CloseSubmenu
-	call CloseText
-	and a
-	ret
-; 13406
-
-.Overworld: ; 13406
-	call RefreshScreen
-	ld a, 1
-	ld [wUsingItemWithSelect], a
-	call DoItemEffect
-	xor a
-	ld [wUsingItemWithSelect], a
-	ld a, [wItemEffectSucceeded]
-	cp 1
-	jr nz, ._cantuse
-	scf
-	ld a, HMENURETURN_SCRIPT
-	ld [hMenuReturn], a
-	ret
-; 13422
-
-.CantUse: ; 13422
-	call RefreshScreen
-
-._cantuse
-	call CantUseItem
-	call CloseText
-	and a
-	ret
-; 1342d
--- a/engine/sgb_layouts.asm
+++ /dev/null
@@ -1,605 +1,0 @@
-LoadSGBLayout: ; 864c
-	call CheckCGB
-	jp nz, LoadSGBLayoutCGB
-
-	ld a, b
-	cp SCGB_RAM
-	jr nz, .not_ram
-	ld a, [wSGBPredef]
-.not_ram
-	cp SCGB_PARTY_MENU_HP_PALS
-	jp z, SGB_ApplyPartyMenuHPPals
-	ld l, a
-	ld h, 0
-	add hl, hl
-	ld de, .Jumptable
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, _LoadSGBLayout_ReturnFromJumpTable
-	push de
-	jp hl
-; 866f
-
-.Jumptable: ; 866f
-	dw .SGB_BattleGrayscale
-	dw .SGB_BattleColors
-	dw .SGB_PokegearPals
-	dw .SGB_StatsScreenHPPals
-	dw .SGB_Pokedex
-	dw .SGB_SlotMachine
-	dw .SGB06
-	dw .SGB_GSIntro
-	dw .SGB_Diploma
-	dw .SGB_MapPals
-	dw .SGB_PartyMenu
-	dw .SGB_Evolution
-	dw .SGB_GSTitleScreen
-	dw .SGB0d
-	dw .SGB_MoveList
-	dw .SGB0f
-	dw .SGB_PokedexSearchOption
-	dw .SGB11
-	dw .SGB12
-	dw .SGB13
-	dw .SGB_PackPals
-	dw .SGB_TrainerCard
-	dw .SGB_PokedexUnownMode
-	dw .SGB_BillsPC
-	dw .SGB_UnownPuzzle
-	dw .SGB_GamefreakLogo
-	dw .SGB_PlayerOrMonFrontpicPals
-	dw .SGB_TradeTube
-	dw .SGB_TrainerOrMonFrontpicPals
-	dw .SGB_MysteryGift
-	dw .SGB1e
-; 86ad
-
-.SGB_BattleGrayscale: ; 86ad
-	ld hl, PalPacket_BattleGrayscale
-	ld de, BlkPacket_Battle
-	ret
-; 86b4
-
-.SGB_BattleColors: ; 86b4
-	ld hl, BlkPacket_Battle
-	call PushSGBPals_
-
-	ld hl, PalPacket_9ce6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-
-	ld a, [wPlayerHPPal]
-	ld l, a
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	ld de, HPBarPals
-	add hl, de
-
-	ld a, [hli]
-	ld [wSGBPals + 3], a
-	ld a, [hli]
-	ld [wSGBPals + 4], a
-	ld a, [hli]
-	ld [wSGBPals + 5], a
-	ld a, [hl]
-	ld [wSGBPals + 6], a
-
-	ld a, [wEnemyHPPal]
-	ld l, a
-	ld h, 0
-	add hl, hl
-	add hl, hl
-
-	ld de, HPBarPals
-	add hl, de
-	ld a, [hli]
-	ld [wSGBPals + 9], a
-	ld a, [hli]
-	ld [wSGBPals + 10], a
-	ld a, [hli]
-	ld [wSGBPals + 11], a
-	ld a, [hl]
-	ld [wSGBPals + 12], a
-
-	ld hl, PalPacket_9cf6
-	ld de, wSGBPals + PALPACKET_LENGTH
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-
-	call GetBattlemonBackpicPalettePointer
-
-	ld a, [hli]
-	ld [wSGBPals + 19], a
-	ld a, [hli]
-	ld [wSGBPals + 20], a
-	ld a, [hli]
-	ld [wSGBPals + 21], a
-	ld a, [hl]
-	ld [wSGBPals + 22], a
-	call GetEnemyFrontpicPalettePointer
-	ld a, [hli]
-	ld [wSGBPals + 25], a
-	ld a, [hli]
-	ld [wSGBPals + 26], a
-	ld a, [hli]
-	ld [wSGBPals + 27], a
-	ld a, [hl]
-	ld [wSGBPals + 28], a
-
-	ld hl, wSGBPals
-	ld de, wSGBPals + PALPACKET_LENGTH
-	ld a, SCGB_BATTLE_COLORS
-	ld [wSGBPredef], a
-	ret
-; 873c
-
-.SGB_MoveList: ; 873c
-	ld hl, PalPacket_9bd6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-
-	ld hl, wSGBPals + 1
-	ld [hl], $10
-	inc hl
-	inc hl
-
-	ld a, [wPlayerHPPal]
-	add PREDEFPAL_HP_GREEN
-	ld [hl], a
-	ld hl, wSGBPals
-	ld de, BlkPacket_MoveList
-	ret
-; 875c
-
-.SGB_PokegearPals: ; 875c
-	ld hl, PalPacket_Pokegear
-	ld de, BlkPacket_9a86
-	ret
-; 8763
-
-.SGB_StatsScreenHPPals: ; 8763
-	ld hl, PalPacket_9ce6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	ld a, [wCurHPPal]
-	ld l, a
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	ld de, HPBarPals
-	add hl, de
-	ld a, [hli]
-	ld [wSGBPals + 3], a
-	ld a, [hli]
-	ld [wSGBPals + 4], a
-	ld a, [hli]
-	ld [wSGBPals + 5], a
-	ld a, [hl]
-	ld [wSGBPals + 6], a
-	ld a, [wCurPartySpecies]
-	ld bc, wTempMonDVs
-	call GetPlayerOrMonPalettePointer
-	ld a, [hli]
-	ld [wSGBPals + 9], a
-	ld a, [hli]
-	ld [wSGBPals + 10], a
-	ld a, [hli]
-	ld [wSGBPals + 11], a
-	ld a, [hl]
-	ld [wSGBPals + 12], a
-	ld hl, wSGBPals
-	ld de, BlkPacket_StatsScreen
-	ret
-; 87ab
-
-.SGB_PartyMenu: ; 87ab
-	ld hl, PalPacket_PartyMenu
-	ld de, wSGBPals + 1
-	ret
-; 87b2
-
-.SGB_Pokedex: ; 87b2
-	ld hl, PalPacket_9ce6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	ld hl, wSGBPals + 3
-	ld [hl], LOW(palred 31 + palgreen 20 + palblue 10)
-	inc hl
-	ld [hl], HIGH(palred 31 + palgreen 20 + palblue 10)
-	inc hl
-	ld [hl], LOW(palred 26 + palgreen 10 + palblue 6)
-	inc hl
-	ld [hl], HIGH(palred 26 + palgreen 10 + palblue 6)
-	ld a, [wCurPartySpecies]
-	call GetMonPalettePointer_
-	ld a, [hli]
-	ld [wSGBPals + 9], a
-	ld a, [hli]
-	ld [wSGBPals + 10], a
-	ld a, [hli]
-	ld [wSGBPals + 11], a
-	ld a, [hl]
-	ld [wSGBPals + 12], a
-	ld hl, wSGBPals
-	ld de, BlkPacket_Pokedex_PC
-	ret
-; 87e9
-
-.SGB_BillsPC: ; 87e9
-	ld hl, PalPacket_9ce6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	ld hl, wSGBPals + 3
-	ld [hl], LOW(palred 31 + palgreen 20 + palblue 10)
-	inc hl
-	ld [hl], HIGH(palred 31 + palgreen 20 + palblue 10)
-	inc hl
-	ld [hl], LOW(palred 26 + palgreen 10 + palblue 6)
-	inc hl
-	ld [hl], HIGH(palred 26 + palgreen 10 + palblue 6)
-	ld a, [wCurPartySpecies]
-	ld bc, wTempMonDVs
-	call GetPlayerOrMonPalettePointer
-	ld a, [hli]
-	ld [wSGBPals + 9], a
-	ld a, [hli]
-	ld [wSGBPals + 10], a
-	ld a, [hli]
-	ld [wSGBPals + 11], a
-	ld a, [hl]
-	ld [wSGBPals + 12], a
-	ld hl, wSGBPals
-	ld de, BlkPacket_Pokedex_PC
-	ret
-; 8823
-
-.SGB_PokedexUnownMode: ; 8823
-	call .SGB_Pokedex
-	ld de, BlkPacket_PokedexUnownMode
-	ret
-; 882a
-
-.SGB_PokedexSearchOption: ; 882a
-	ld hl, PalPacket_9ce6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	ld hl, wSGBPals + 3
-	ld [hl], LOW(palred 31 + palgreen 20 + palblue 10)
-	inc hl
-	ld [hl], HIGH(palred 31 + palgreen 20 + palblue 10)
-	inc hl
-	ld [hl], LOW(palred 26 + palgreen 10 + palblue 6)
-	inc hl
-	ld [hl], HIGH(palred 26 + palgreen 10 + palblue 6)
-	ld hl, wSGBPals
-	ld de, BlkPacket_9a86
-	ret
-; 884b
-
-.SGB_PackPals: ; 884b
-	ld hl, PalPacket_Pack
-	ld de, BlkPacket_9a86
-	ret
-; 8852
-
-.SGB_SlotMachine: ; 8852
-	ld hl, PalPacket_SlotMachine
-	ld de, BlkPacket_SlotMachine
-	ret
-; 8859
-
-.SGB06: ; 8859
-	ld hl, PalPacket_SCGB_06
-	ld de, BlkPacket_SCGB_06
-	ret
-; 8860
-
-.SGB_Diploma:
-.SGB_MysteryGift: ; 8860
-	ld hl, PalPacket_Diploma
-	ld de, BlkPacket_9a86
-	ret
-; 8867
-
-.SGB_GSIntro: ; 8867
-	ld b, 0
-	ld hl, .BlkPacketTable_GSIntro
-rept 4
-	add hl, bc
-endr
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	inc hl
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ret
-; 8878
-
-.BlkPacketTable_GSIntro: ; 8878
-	dw BlkPacket_9a86, PalPacket_GSIntroShellderLapras
-	dw BlkPacket_GSIntroJigglypuffPikachu, PalPacket_GSIntroJigglypuffPikachu
-	dw BlkPacket_9a86, PalPacket_GSIntroStartersTransition
-; 8884
-
-.SGB_GSTitleScreen: ; 8884
-	ld hl, PalPacket_GSTitleScreen
-	ld de, BlkPacket_GSTitleScreen
-	ld a, SCGB_DIPLOMA
-	ld [wSGBPredef], a
-	ret
-; 8890
-
-.SGB13: ; 8890
-	ld hl, PalPacket_SCGB_13
-	ld de, BlkPacket_SCGB_13
-	ret
-; 8897
-
-.SGB0f: ; 8897
-	ld hl, PalPacket_SCGB_0F
-	ld de, BlkPacket_9a86
-	ret
-; 889e
-
-.SGB11: ; 889e
-	ld hl, BlkPacket_9a86
-	ld de, wPlayerLightScreenCount ; ???
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	ld hl, PalPacket_SCGB_11
-	ld de, BlkPacket_9a86
-	ret
-; 88b1
-
-.SGB_MapPals: ; 88b1
-	ld hl, PalPacket_9bd6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	call .GetMapPalsIndex
-	ld hl, wSGBPals + 1
-	ld [hld], a
-	ld de, BlkPacket_9a86
-	ld a, SCGB_MAPPALS
-	ld [wSGBPredef], a
-	ret
-; 88cd
-
-.SGB_Evolution: ; 88cd
-	push bc
-	ld hl, PalPacket_9ce6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	pop bc
-	ld a, c
-	and a
-	jr z, .partymon
-	; Egg
-	ld hl, wSGBPals + 3
-	ld [hl], LOW(palred 7 + palgreen 7 + palblue 7)
-	inc hl
-	ld [hl], HIGH(palred 7 + palgreen 7 + palblue 7)
-	inc hl
-	ld [hl], LOW(palred 2 + palgreen 3 + palblue 3)
-	inc hl
-	ld [hl], HIGH(palred 2 + palgreen 3 + palblue 3)
-	jr .done
-
-.partymon
-	ld hl, wPartyMon1DVs
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld c, l
-	ld b, h
-	ld a, [wPlayerHPPal]
-	call GetPlayerOrMonPalettePointer
-	ld a, [hli]
-	ld [wSGBPals + 3], a
-	ld a, [hli]
-	ld [wSGBPals + 4], a
-	ld a, [hli]
-	ld [wSGBPals + 5], a
-	ld a, [hl]
-	ld [wSGBPals + 6], a
-
-.done
-	ld hl, wSGBPals
-	ld de, BlkPacket_9a86
-	ret
-; 891a
-
-.SGB0d:
-.SGB_TrainerCard: ; 891a
-	ld hl, PalPacket_Diploma
-	ld de, BlkPacket_9a86
-	ret
-; 8921
-
-.SGB_UnownPuzzle: ; 8921
-	ld hl, PalPacket_UnownPuzzle
-	ld de, BlkPacket_9a86
-	ret
-; 8928
-
-.SGB12: ; 8928
-	ld hl, PalPacket_9bd6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	ld hl, BlkPacket_9a86
-	ld de, wSGBPals + PALPACKET_LENGTH
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	call .GetMapPalsIndex
-	ld hl, wSGBPals + 1
-	ld [hl], a
-	ld hl, wSGBPals + 3
-	ld [hl], $2e
-	ld hl, wSGBPals + $13
-	ld a, 5
-	ld [hli], a
-	ld a, [wMenuBorderLeftCoord]
-	ld [hli], a
-	ld a, [wMenuBorderTopCoord]
-	ld [hli], a
-	ld a, [wMenuBorderRightCoord]
-	ld [hli], a
-	ld a, [wMenuBorderBottomCoord]
-	ld [hl], a
-	ld hl, wSGBPals
-	ld de, wSGBPals + PALPACKET_LENGTH
-	ret
-; 8969
-
-.SGB1e: ; 8969
-	ld hl, PalPacket_9ce6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	ld a, [wCurPartySpecies]
-	ld l, a
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	add hl, hl
-	ld de, PokemonPalettes
-	add hl, de
-	ld a, [wcf65]
-	and 3
-	sla a
-	sla a
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [hli]
-	ld [wSGBPals + 3], a
-	ld a, [hli]
-	ld [wSGBPals + 4], a
-	ld a, [hli]
-	ld [wSGBPals + 5], a
-	ld a, [hl]
-	ld [wSGBPals + 6], a
-	ld hl, wSGBPals
-	ld de, BlkPacket_9a86
-	ret
-; 89a6
-
-.SGB_GamefreakLogo: ; 89a6
-	ld hl, PalPacket_GamefreakLogo
-	ld de, BlkPacket_9a86
-	ret
-; 89ad
-
-.SGB_PlayerOrMonFrontpicPals: ; 89ad
-	ld hl, PalPacket_9ce6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	ld a, [wCurPartySpecies]
-	ld bc, wTempMonDVs
-	call GetPlayerOrMonPalettePointer
-	ld a, [hli]
-	ld [wSGBPals + 3], a
-	ld a, [hli]
-	ld [wSGBPals + 4], a
-	ld a, [hli]
-	ld [wSGBPals + 5], a
-	ld a, [hl]
-	ld [wSGBPals + 6], a
-	ld hl, wSGBPals
-	ld de, BlkPacket_9a86
-	ret
-; 89d9
-
-.SGB_TradeTube: ; 89d9
-	ld hl, PalPacket_TradeTube
-	ld de, BlkPacket_9a86
-	ret
-; 89e0
-
-.SGB_TrainerOrMonFrontpicPals: ; 89e0
-	ld hl, PalPacket_9ce6
-	ld de, wSGBPals
-	ld bc, PALPACKET_LENGTH
-	call CopyBytes
-	ld a, [wCurPartySpecies]
-	ld bc, wTempMonDVs
-	call GetFrontpicPalettePointer
-	ld a, [hli]
-	ld [wSGBPals + 3], a
-	ld a, [hli]
-	ld [wSGBPals + 4], a
-	ld a, [hli]
-	ld [wSGBPals + 5], a
-	ld a, [hl]
-	ld [wSGBPals + 6], a
-	ld hl, wSGBPals
-	ld de, BlkPacket_9a86
-	ret
-; 8a0c
-
-.GetMapPalsIndex: ; 8a0c
-	ld a, [wTimeOfDayPal]
-	cp NITE_F
-	jr c, .morn_day
-	ld a, PREDEFPAL_NITE
-	ret
-
-.morn_day
-	ld a, [wEnvironment]
-	cp ROUTE
-	jr z, .route
-	cp CAVE
-	jr z, .cave
-	cp DUNGEON
-	jr z, .cave
-	cp ENVIRONMENT_5
-	jr z, .perm5
-	cp GATE
-	jr z, .gate
-	ld a, [wMapGroup]
-	ld e, a
-	ld d, 0
-	ld hl, MapGroupRoofSGBPalInds
-	add hl, de
-	ld a, [hl]
-	ret
-
-.route
-	ld a, PREDEFPAL_00
-	ret
-
-.cave
-	ld a, PREDEFPAL_DUNGEONS
-	ret
-
-.perm5
-	ld a, PREDEFPAL_VERMILION
-	ret
-
-.gate
-	ld a, PREDEFPAL_PEWTER
-	ret
-; 8a45
-
-INCLUDE "data/maps/sgb_roof_pal_inds.asm"
-
-_LoadSGBLayout_ReturnFromJumpTable: ; 8a60
-	push de
-	call PushSGBPals_
-	pop hl
-	jp PushSGBPals_
-; 8a68
--- a/engine/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/spawn_points.asm
+++ /dev/null
@@ -1,62 +1,0 @@
-INCLUDE "data/maps/spawn_points.asm"
-
-
-LoadSpawnPoint: ; 1531f
-	; loads the spawn point in wDefaultSpawnpoint
-	push hl
-	push de
-	ld a, [wDefaultSpawnpoint]
-	cp SPAWN_N_A
-	jr z, .spawn_n_a
-	ld l, a
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	ld de, SpawnPoints
-	add hl, de
-	ld a, [hli]
-	ld [wMapGroup], a
-	ld a, [hli]
-	ld [wMapNumber], a
-	ld a, [hli]
-	ld [wXCoord], a
-	ld a, [hli]
-	ld [wYCoord], a
-.spawn_n_a
-	pop de
-	pop hl
-	ret
-; 15344
-
-
-IsSpawnPoint: ; 15344
-; Checks if the map loaded in de is a spawn point.  Returns carry if it's a spawn point.
-	ld hl, SpawnPoints
-	ld c, 0
-.loop
-	ld a, [hl]
-	cp SPAWN_N_A
-	jr z, .nope
-	cp d
-	jr nz, .next
-	inc hl
-	ld a, [hld]
-	cp e
-	jr z, .yes
-
-.next
-	push bc
-	ld bc, 4 ; length of a spawn table entry
-	add hl, bc
-	pop bc
-	inc c
-	jr .loop
-
-.nope
-	and a
-	ret
-
-.yes
-	scf
-	ret
-; 15363
--- a/engine/sprite_anims.asm
+++ /dev/null
@@ -1,889 +1,0 @@
-DoAnimFrame: ; 8d24b
-	ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
-	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
-; 8d25b
-
-.Jumptable: ; 8d25b (23:525b)
-; entries correspond to SPRITE_ANIM_SEQ_* constants
-	dw .Null
-	dw .PartyMon
-	dw .PartyMonSwitch
-	dw .PartyMonSelected
-	dw .GSTitleTrail
-	dw .NamingScreenCursor
-	dw .GameFreakLogo
-	dw .GSIntroStar
-	dw .GSIntroSparkle
-	dw .SlotsGolem
-	dw .SlotsChansey
-	dw .SlotsChanseyEgg
-	dw .MailCursor
-	dw .UnusedCursor
-	dw .DummyGameCursor
-	dw .PokegearArrow
-	dw .TradePokeBall
-	dw .TradeTubeBulge
-	dw .TrademonInTube
-	dw .RevealNewMon
-	dw .RadioTuningKnob
-	dw .CutLeaves
-	dw .FlyFrom
-	dw .FlyLeaf
-	dw .FlyTo
-	dw .GSIntroHoOh
-	dw .EZChatCursor
-	dw .MobileTradeSentPulse
-	dw .MobileTradeOTPulse
-	dw .IntroSuicune
-	dw .IntroPichuWooper
-	dw .Celebi
-	dw .IntroUnown
-	dw .IntroUnownF
-	dw .IntroSuicuneAway
-
-.Null: ; 8d2a1 (23:52a1)
-	ret
-
-.PartyMon ; 8d2a2 (23:52a2)
-	ld a, [wMenuCursorY]
-
-	ld hl, SPRITEANIMSTRUCT_INDEX
-	add hl, bc
-	cp [hl]
-	jr z, .PartyMonSwitch
-
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld [hl], 8 * 2
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], $0
-	ret
-
-.PartyMonSwitch ; 8d2b9 (23:52b9)
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld [hl], 8 * 3
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	ld d, a
-	inc [hl]
-	and $f
-	ret nz
-
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld e, [hl]
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld a, d
-	and $10 ; bit 4
-	jr z, .load_zero
-	ld a, e
-	and a
-	jr z, .load_minus_two
-	cp $1
-	jr z, .load_minus_one
-.load_zero
-	xor a
-	ld [hl], a
-	ret
-
-.load_minus_one
-	ld a, -1
-	ld [hl], a
-	ret
-
-.load_minus_two
-	ld a, -2
-	ld [hl], a
-	ret
-
-.PartyMonSelected ; 8d2ea (23:52ea)
-	ld a, [wMenuCursorY]
-
-	ld hl, SPRITEANIMSTRUCT_INDEX
-	add hl, bc
-	cp [hl]
-	jr z, .three_offset_right
-
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld [hl], 8 * 2
-	ret
-
-.three_offset_right
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld [hl], 8 * 3
-	ret
-
-.GSTitleTrail ; 8d302 (23:5302)
-	call .AnonymousJumptable
-	jp hl
-; 8d306 (23:5306)
-
-; Anonymous dw (see .AnonymousJumptable)
-	dw .four_zero
-	dw .four_one
-; 8d30a
-
-.four_zero ; 8d30a
-	call .IncrementJumptableIndex
-
-	ld hl, SPRITEANIMSTRUCT_INDEX
-	add hl, bc
-	ld a, [hl]
-
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	and $3
-	ld [hl], a
-	inc [hl]
-	swap a
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], a
-
-.four_one ; 8d321
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld a, [hl]
-	cp $a4
-	jr nc, .asm_8d356
-
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	add $4
-
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld [hl], a
-
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	inc [hl]
-
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld a, [hl]
-	sla a
-	sla a
-	ld d, $2
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	add $3
-	ld [hl], a
-	call .Sprites_Sine
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.asm_8d356
-	call DeinitializeSprite
-	ret
-; 8d35a
-
-.GSIntroHoOh ; 8d35a (23:535a)
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	inc a
-	ld [hl], a
-	ld d, $2
-	call .Sprites_Sine
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.NamingScreenCursor ; 8d36c (23:536c)
-	callfar NamingScreen_AnimateCursor
-	ret
-
-.MailCursor ; 8d373 (23:5373)
-	callfar ComposeMail_AnimateCursor
-	ret
-
-.GameFreakLogo: ; 8d37a (23:537a)
-	callfar GameFreakLogoJumper
-	ret
-
-.GSIntroStar ; 8d381 (23:5381)
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .asm_8d3ba
-	dec [hl]
-	dec [hl]
-	ld d, a
-	and $1f
-	jr nz, .asm_8d395
-
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	dec [hl]
-.asm_8d395
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld a, [hl]
-	push af
-	push de
-	call .Sprites_Sine
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-	pop de
-	pop af
-	call .Sprites_Cosine
-
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld [hl], a
-
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld a, [hl]
-
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	add [hl]
-	ld [hl], a
-	ret
-
-.asm_8d3ba
-	ld a, $1
-	ld [wcf64], a
-	call DeinitializeSprite
-	ret
-
-.GSIntroSparkle ; 8d3c3 (23:53c3)
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hli]
-	or [hl]
-	jr z, .asm_8d41e
-
-	ld hl, SPRITEANIMSTRUCT_0F
-	add hl, bc
-	ld d, [hl]
-
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld a, [hl]
-	push af
-	push de
-	call .Sprites_Sine
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-	pop de
-	pop af
-	call .Sprites_Cosine
-
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld [hl], a
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-
-	ld hl, SPRITEANIMSTRUCT_0E
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	add hl, de
-	ld e, l
-	ld d, h
-
-	ld hl, SPRITEANIMSTRUCT_0E
-	add hl, bc
-	ld [hl], e
-	inc hl
-	ld [hl], d
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, -$10
-	add hl, de
-	ld e, l
-	ld d, h
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], e
-	inc hl
-	ld [hl], d
-
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld a, [hl]
-	xor $20
-	ld [hl], a
-	ret
-
-.asm_8d41e
-	call DeinitializeSprite
-	ret
-
-.SlotsGolem: ; 8d422 (23:5422)
-	callfar Slots_AnimateGolem
-	ret
-
-.SlotsChansey: ; 8d429 (23:5429)
-	callfar Slots_AnimateChansey
-	ld hl, wcf64
-	ld a, [hl]
-	cp $2
-	ret nz
-	ld [hl], $3
-	ld a, SPRITE_ANIM_FRAMESET_SLOTS_CHANSEY_2
-	call _ReinitSpriteAnimFrame
-	ret
-
-.SlotsChanseyEgg: ; 8d43e (23:543e)
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld a, [hl]
-	dec [hl]
-	ld e, a
-	and $1
-	jr z, .move_vertical
-
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld a, [hl]
-	cp 15 * 8
-	jr c, .move_right
-	call DeinitializeSprite
-	ld a, $4
-	ld [wcf64], a
-	ld de, SFX_PLACE_PUZZLE_PIECE_DOWN
-	call PlaySFX
-	ret
-
-.move_right
-	inc [hl]
-.move_vertical
-	ld a, e
-	ld d, $20
-	call .Sprites_Sine
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.UnusedCursor ; 8d46e (23:546e)
-	callfar ret_e00ed
-	ret
-
-.PokegearArrow ; 8d475 (23:5475)
-	callfar AnimatePokegearModeIndicatorArrow
-	ret
-
-.DummyGameCursor ; 8d47c (23:547c)
-	callfar DummyGame_InterpretJoypad_AnimateCursor
-	ret
-
-.TradePokeBall ; 8d483 (23:5483)
-	call .AnonymousJumptable
-	jp hl
-; 8d487 (23:5487)
-
-; Anonymous dw (see .AnonymousJumptable)
-	dw .TradePokeBall_zero
-	dw .TradePokeBall_one
-	dw .TradePokeBall_two
-	dw .TradePokeBall_three
-	dw .TradePokeBall_four
-	dw .TradePokeBall_five
-; 8d493
-
-.TradePokeBall_zero ; 8d493
-	ld a, SPRITE_ANIM_FRAMESET_TRADE_POKE_BALL_WOBBLE
-	call _ReinitSpriteAnimFrame
-
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld [hl], $2
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $20
-	ret
-; 8d4a5
-
-.TradePokeBall_two ; 8d4a5
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .asm_8d4af
-	dec [hl]
-	ret
-
-.asm_8d4af
-	call .IncrementJumptableIndex
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $40
-
-.TradePokeBall_three ; 8d4b8
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	cp $30
-	jr c, .asm_8d4cd
-	dec [hl]
-	ld d, $28
-	call .Sprites_Sine
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.asm_8d4cd
-	ld de, SFX_GOT_SAFARI_BALLS
-	call PlaySFX
-	jr .TradePokeBall_five
-; 8d4d5
-
-.TradePokeBall_one ; 8d4d5
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld [hl], $4
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $30
-
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld [hl], $24
-	ret
-; 8d4e8
-
-.TradePokeBall_four ; 8d4e8
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .asm_8d51c
-	ld d, a
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	call Sprites_Sine
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	inc [hl]
-	ld a, [hl]
-	and $3f
-	ret nz
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $20
-
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld a, [hl]
-	sub $c
-	ld [hl], a
-	ld de, SFX_SWITCH_POKEMON
-	call PlaySFX
-	ret
-
-.asm_8d51c
-	xor a
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-	call .IncrementJumptableIndex
-	ret
-
-.TradePokeBall_five ; 8d526
-	call DeinitializeSprite
-	ret
-; 8d52a
-
-.TradeTubeBulge ; 8d52a (23:552a)
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld a, [hl]
-	inc [hl]
-	inc [hl]
-	cp $b0
-	jr nc, .delete
-	and $3
-	ret nz
-	ld de, SFX_POKEBALLS_PLACED_ON_TABLE
-	call PlaySFX
-	ret
-
-.delete
-	call DeinitializeSprite
-	ret
-
-.TrademonInTube ; 8d543 (23:5543)
-	callfar TradeAnim_AnimateTrademonInTube
-	ret
-
-.RevealNewMon: ; 8d54a (23:554a)
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	cp $80
-	jr nc, .finish_EggShell
-	ld d, a
-	add $8
-	ld [hl], a
-
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld a, [hl]
-	xor $20
-	ld [hl], a
-
-	push af
-	push de
-	call .Sprites_Sine
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-
-	pop de
-	pop af
-	call .Sprites_Cosine
-
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.finish_EggShell
-	call DeinitializeSprite
-	ret
-
-.RadioTuningKnob: ; 8d578 (23:5578)
-	callfar AnimateTuningKnob
-	ret
-
-.CutLeaves ; 8d57f (23:557f)
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	ld hl, $80
-	add hl, de
-	ld e, l
-	ld d, h
-
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld [hl], e
-	inc hl
-	ld [hl], d
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	inc [hl]
-	inc [hl]
-	inc [hl]
-	push af
-	push de
-	call .Sprites_Sine
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-	pop de
-	pop af
-	call .Sprites_Cosine
-
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.FlyFrom: ; 8d5b0 (23:55b0)
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	ld a, [hl]
-	and a
-	ret z
-
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld a, [hl]
-	inc [hl]
-	cp $40
-	ret c
-
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	dec [hl]
-	dec [hl]
-
-	ld hl, SPRITEANIMSTRUCT_0F
-	add hl, bc
-	ld a, [hl]
-	ld d, a
-	cp $40
-	jr nc, .skip
-	add $8
-	ld [hl], a
-.skip
-	ld hl, SPRITEANIMSTRUCT_0E
-	add hl, bc
-	ld a, [hl]
-	inc [hl]
-	call .Sprites_Cosine
-
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.FlyLeaf: ; 8d5e2 (23:55e2)
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld a, [hl]
-	cp -9 * 8
-	jr nc, .delete_leaf
-	inc [hl]
-	inc [hl]
-
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	dec [hl]
-
-	ld d, $40
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	inc [hl]
-	call .Sprites_Cosine
-
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.delete_leaf
-	call DeinitializeSprite
-	ret
-
-.FlyTo: ; 8d607 (23:5607)
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	ld a, [hl]
-	cp 10 * 8 + 4
-	ret z
-
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	inc [hl]
-	inc [hl]
-
-	ld hl, SPRITEANIMSTRUCT_0F
-	add hl, bc
-	ld a, [hl]
-	ld d, a
-	and a
-	jr z, .asm_8d621
-	sub $2
-	ld [hl], a
-.asm_8d621
-	ld hl, SPRITEANIMSTRUCT_0E
-	add hl, bc
-	ld a, [hl]
-	inc [hl]
-	call .Sprites_Cosine
-
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.MobileTradeSentPulse ; 8d630 (23:5630)
-	farcall Function108bc7
-	ret
-
-.MobileTradeOTPulse ; 8d637 (23:5637)
-	farcall Function108be0
-	ret
-
-.IntroSuicune ; 8d63e (23:563e)
-	ld a, [wcf65]
-	and a
-	jr nz, .asm_8d645
-	ret
-.asm_8d645
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], $0
-
-	ld hl, SPRITEANIMSTRUCT_0D
-	add hl, bc
-	ld a, [hl]
-	add $2
-	ld [hl], a
-	xor $ff
-	inc a
-	ld d, $20
-	call .Sprites_Sine
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-	ld a, SPRITE_ANIM_FRAMESET_INTRO_SUICUNE_2
-	call _ReinitSpriteAnimFrame
-	ret
-
-.IntroPichuWooper ; 8d666 (23:5666)
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	cp $14
-	jr nc, .asm_8d67f
-	add $2
-	ld [hl], a
-	xor $ff
-	inc a
-	ld d, $20
-	call .Sprites_Sine
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-.asm_8d67f
-	ret
-
-.IntroUnown ; 8d680 (23:5680)
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld d, [hl]
-	inc [hl]
-	inc [hl]
-	inc [hl]
-
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	push af
-	push de
-	call .Sprites_Sine
-
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], a
-	pop de
-	pop af
-	call .Sprites_Cosine
-
-	ld hl, SPRITEANIMSTRUCT_XOFFSET
-	add hl, bc
-	ld [hl], a
-	ret
-
-.IntroUnownF ; 8d6a2 (23:56a2)
-	ld a, [wcf64]
-	cp $40
-	ret nz
-	ld a, SPRITE_ANIM_FRAMESET_INTRO_UNOWN_F_2
-	call _ReinitSpriteAnimFrame
-	ret
-
-.IntroSuicuneAway ; 8d6ae (23:56ae)
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	ld a, [hl]
-	add $10
-	ld [hl], a
-	ret
-
-.EZChatCursor ; 8d6b7 (23:56b7)
-	farcall AnimateEZChatCursor
-	ret
-
-.Celebi ; 8d6be (23:56be)
-	farcall UpdateCelebiPosition
-	ret
-
-.AnonymousJumptable: ; 8d6c5 (23:56c5)
-	ld hl, sp+$0
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	inc de
-
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld l, [hl]
-	ld h, $0
-	add hl, hl
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ret
-; 8d6d8 (23:56d8)
-
-.IncrementJumptableIndex: ; 8d6d8
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	inc [hl]
-	ret
-; 8d6de
-
-.Sprites_Sine: ; 8d6de (23:56de)
-	call Sprites_Sine
-	ret
-
-.Sprites_Cosine: ; 8d6e2 (23:56e2)
-	call Sprites_Cosine
-	ret
-; 8d6e6 (23:56e6)
--- a/engine/sprites.asm
+++ /dev/null
@@ -1,677 +1,0 @@
-ClearSpriteAnims: ; 8cf53
-	ld hl, wSpriteAnimDict
-	ld bc, wSpriteAnimsEnd - wSpriteAnimDict
-.loop
-	ld [hl], $0
-	inc hl
-	dec bc
-	ld a, c
-	or b
-	jr nz, .loop
-	ret
-; 8cf62
-
-PlaySpriteAnimationsAndDelayFrame: ; 8cf62
-	call PlaySpriteAnimations
-	call DelayFrame
-	ret
-; 8cf69
-
-PlaySpriteAnimations: ; 8cf69
-	push hl
-	push de
-	push bc
-	push af
-
-	ld a, LOW(wVirtualOAM)
-	ld [wCurrSpriteOAMAddr], a
-	call DoNextFrameForAllSprites
-
-	pop af
-	pop bc
-	pop de
-	pop hl
-	ret
-; 8cf7a
-
-DoNextFrameForAllSprites: ; 8cf7a
-	ld hl, wSpriteAnimationStructs
-	ld e, NUM_SPRITE_ANIM_STRUCTS
-
-.loop
-	ld a, [hl]
-	and a
-	jr z, .next ; This struct is deinitialized.
-	ld c, l
-	ld b, h
-	push hl
-	push de
-	call DoAnimFrame ; Uses a massive dw
-	call UpdateAnimFrame
-	pop de
-	pop hl
-	jr c, .done
-
-.next
-	ld bc, SPRITEANIMSTRUCT_LENGTH
-	add hl, bc
-	dec e
-	jr nz, .loop
-
-	ld a, [wCurrSpriteOAMAddr]
-	ld l, a
-	ld h, HIGH(wVirtualOAM)
-
-.loop2 ; Clear (wVirtualOAM + [wCurrSpriteOAMAddr] --> wVirtualOAMEnd)
-	ld a, l
-	cp LOW(wVirtualOAMEnd)
-	jr nc, .done
-	xor a
-	ld [hli], a
-	jr .loop2
-
-.done
-	ret
-; 8cfa8
-
-DoNextFrameForFirst16Sprites: ; 8cfa8 (23:4fa8)
-	ld hl, wSpriteAnimationStructs
-	ld e, NUM_SPRITE_ANIM_STRUCTS
-
-.loop
-	ld a, [hl]
-	and a
-	jr z, .next
-	ld c, l
-	ld b, h
-	push hl
-	push de
-	call DoAnimFrame ; Uses a massive dw
-	call UpdateAnimFrame
-	pop de
-	pop hl
-	jr c, .done
-
-.next
-	ld bc, SPRITEANIMSTRUCT_LENGTH
-	add hl, bc
-	dec e
-	jr nz, .loop
-
-	ld a, [wCurrSpriteOAMAddr]
-	ld l, a
-	ld h, HIGH(wVirtualOAMSprite16)
-
-.loop2 ; Clear (wVirtualOAM + [wCurrSpriteOAMAddr] --> Sprites + $40)
-	ld a, l
-	cp LOW(wVirtualOAMSprite16)
-	jr nc, .done
-	xor a
-	ld [hli], a
-	jr .loop2
-
-.done
-	ret
-
-InitSpriteAnimStruct:: ; 8cfd6
-; Initialize animation a at pixel x=e, y=d
-; Find if there's any room in the wSpriteAnimationStructs array, which is 10x16
-	push de
-	push af
-	ld hl, wSpriteAnimationStructs
-	ld e, NUM_SPRITE_ANIM_STRUCTS
-.loop
-	ld a, [hl]
-	and a
-	jr z, .found
-	ld bc, SPRITEANIMSTRUCT_LENGTH
-	add hl, bc
-	dec e
-	jr nz, .loop
-; We've reached the end.  There is no more room here.
-; Return carry.
-	pop af
-	pop de
-	scf
-	ret
-
-.found
-; Back up the structure address to bc.
-	ld c, l
-	ld b, h
-; Value [wSpriteAnimCount] is initially set to -1. Set it to
-; the number of objects loaded into this array.
-	ld hl, wSpriteAnimCount
-	inc [hl]
-	ld a, [hl]
-	and a
-	jr nz, .initialized
-	inc [hl]
-
-.initialized
-; Get row a of SpriteAnimSeqData, copy the pointer into de
-	pop af
-	ld e, a
-	ld d, 0
-	ld hl, SpriteAnimSeqData
-	add hl, de
-	add hl, de
-	add hl, de
-	ld e, l
-	ld d, h
-; Set hl to the first field (field 0) in the current structure.
-	ld hl, SPRITEANIMSTRUCT_INDEX
-	add hl, bc
-; Load the index.
-	ld a, [wSpriteAnimCount]
-	ld [hli], a
-; Copy the table entry to the next two fields.
-	ld a, [de]
-	ld [hli], a
-	inc de
-	ld a, [de]
-	ld [hli], a
-	inc de
-; Look up the third field from the table in the wSpriteAnimDict array (10x2).
-; Take the value and load it in
-	ld a, [de]
-	call GetSpriteAnimVTile
-	ld [hli], a
-	pop de
-; Set hl to field 4 (X coordinate).  Kinda pointless, because we're presumably already here.
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-; Load the original value of de into here.
-	ld a, e
-	ld [hli], a
-	ld a, d
-	ld [hli], a
-; load 0 into the next four fields
-	xor a
-	ld [hli], a
-	ld [hli], a
-	xor a
-	ld [hli], a
-	ld [hli], a
-; load -1 into the next field
-	dec a
-	ld [hli], a
-; load 0 into the last five fields
-	xor a
-rept 4
-	ld [hli], a
-endr
-	ld [hl], a
-; back up the address of the first field to wSpriteAnimAddrBackup
-	ld a, c
-	ld [wSpriteAnimAddrBackup], a
-	ld a, b
-	ld [wSpriteAnimAddrBackup + 1], a
-	ret
-; 8d036
-
-DeinitializeSprite: ; 8d036
-; Clear the index field of the struct in bc.
-	ld hl, SPRITEANIMSTRUCT_INDEX
-	add hl, bc
-	ld [hl], $0
-	ret
-; 8d03d
-
-
-DeinitializeAllSprites: ; 8d03d (23:503d)
-; Clear the index field of every struct in the wSpriteAnimationStructs array.
-	ld hl, wSpriteAnimationStructs
-	ld bc, SPRITEANIMSTRUCT_LENGTH
-	ld e, NUM_SPRITE_ANIM_STRUCTS
-	xor a
-.loop
-	ld [hl], a
-	add hl, bc
-	dec e
-	jr nz, .loop
-	ret
-
-
-UpdateAnimFrame: ; 8d04c
-	call InitSpriteAnimBuffer ; init WRAM
-	call GetSpriteAnimFrame ; read from a memory array
-	cp -3
-	jr z, .done
-	cp -4
-	jr z, .delete
-	call GetFrameOAMPointer
-	; add byte to [wCurrAnimVTile]
-	ld a, [wCurrAnimVTile]
-	add [hl]
-	ld [wCurrAnimVTile], a
-	inc hl
-	; load pointer into hl
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	push bc
-	ld a, [wCurrSpriteOAMAddr]
-	ld e, a
-	ld d, HIGH(wVirtualOAM)
-	ld a, [hli]
-	ld c, a ; number of objects
-.loop
-	; first byte: y (px)
-	; [de] = [wCurrAnimYCoord] + [wCurrAnimYOffset] + [wGlobalAnimYOffset] + AddOrSubtractY([hl])
-	ld a, [wCurrAnimYCoord]
-	ld b, a
-	ld a, [wCurrAnimYOffset]
-	add b
-	ld b, a
-	ld a, [wGlobalAnimYOffset]
-	add b
-	ld b, a
-	call AddOrSubtractY
-	add b
-	ld [de], a
-	inc hl
-	inc de
-	; second byte: x (px)
-	; [de] = [wCurrAnimXCoord] + [wCurrAnimXOffset] + [wGlobalAnimXOffset] + AddOrSubtractX([hl])
-	ld a, [wCurrAnimXCoord]
-	ld b, a
-	ld a, [wCurrAnimXOffset]
-	add b
-	ld b, a
-	ld a, [wGlobalAnimXOffset]
-	add b
-	ld b, a
-	call AddOrSubtractX
-	add b
-	ld [de], a
-	inc hl
-	inc de
-	; third byte: vtile
-	; [de] = [wCurrAnimVTile] + [hl]
-	ld a, [wCurrAnimVTile]
-	add [hl]
-	ld [de], a
-	inc hl
-	inc de
-	; fourth byte: attributes
-	; [de] = GetSpriteOAMAttr([hl])
-	call GetSpriteOAMAttr
-	ld [de], a
-	inc hl
-	inc de
-	ld a, e
-	ld [wCurrSpriteOAMAddr], a
-	cp LOW(wVirtualOAMEnd)
-	jr nc, .reached_the_end
-	dec c
-	jr nz, .loop
-	pop bc
-	jr .done
-
-.delete
-	call DeinitializeSprite
-.done
-	and a
-	ret
-
-.reached_the_end
-	pop bc
-	scf
-	ret
-; 8d0be
-
-AddOrSubtractY: ; 8d0be
-	push hl
-	ld a, [hl]
-	ld hl, wCurrSpriteAddSubFlags
-	bit 6, [hl]
-	jr z, .ok
-	; 8 - a
-	add $8
-	xor $ff
-	inc a
-
-.ok
-	pop hl
-	ret
-; 8d0ce
-
-AddOrSubtractX: ; 8d0ce
-	push hl
-	ld a, [hl]
-	ld hl, wCurrSpriteAddSubFlags
-	bit 5, [hl] ; x flip
-	jr z, .ok
-	; 8 - a
-	add $8
-	xor $ff
-	inc a
-
-.ok
-	pop hl
-	ret
-; 8d0de
-
-GetSpriteOAMAttr: ; 8d0de
-	ld a, [wCurrSpriteAddSubFlags]
-	ld b, a
-	ld a, [hl]
-	xor b
-	and $e0
-	ld b, a
-	ld a, [hl]
-	and $1f
-	or b
-	ret
-; 8d0ec
-
-InitSpriteAnimBuffer: ; 8d0ec
-	xor a
-	ld [wCurrSpriteAddSubFlags], a
-	ld hl, SPRITEANIMSTRUCT_TILE_ID
-	add hl, bc
-	ld a, [hli]
-	ld [wCurrAnimVTile], a
-	ld a, [hli]
-	ld [wCurrAnimXCoord], a
-	ld a, [hli]
-	ld [wCurrAnimYCoord], a
-	ld a, [hli]
-	ld [wCurrAnimXOffset], a
-	ld a, [hli]
-	ld [wCurrAnimYOffset], a
-	ret
-; 8d109
-
-GetSpriteAnimVTile: ; 8d109
-; a = wSpriteAnimDict[a] if a in wSpriteAnimDict else 0
-; vTiles offset
-	push hl
-	push bc
-	ld hl, wSpriteAnimDict
-	ld b, a
-	ld c, NUM_SPRITE_ANIM_STRUCTS
-.loop
-	ld a, [hli]
-	cp b
-	jr z, .ok
-	inc hl
-	dec c
-	jr nz, .loop
-	xor a
-	jr .done
-
-.ok
-	ld a, [hl]
-
-.done
-	pop bc
-	pop hl
-	ret
-; 8d120
-
-_ReinitSpriteAnimFrame:: ; 8d120
-	ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
-	add hl, bc
-	ld [hl], a
-	ld hl, SPRITEANIMSTRUCT_DURATION
-	add hl, bc
-	ld [hl], 0
-	ld hl, SPRITEANIMSTRUCT_FRAME
-	add hl, bc
-	ld [hl], -1
-	ret
-; 8d132
-
-
-GetSpriteAnimFrame: ; 8d132
-.loop
-	ld hl, SPRITEANIMSTRUCT_DURATION
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .next_frame ; finished the current sequence
-	dec [hl]
-	call .GetPointer ; load pointer from SpriteAnimFrameData
-	ld a, [hli]
-	push af
-	jr .okay
-
-.next_frame
-	ld hl, SPRITEANIMSTRUCT_FRAME
-	add hl, bc
-	inc [hl]
-	call .GetPointer ; load pointer from SpriteAnimFrameData
-	ld a, [hli]
-	cp dorestart_command
-	jr z, .restart
-	cp endanim_command
-	jr z, .repeat_last
-
-	push af
-	ld a, [hl]
-	push hl
-	and $3f
-	ld hl, SPRITEANIMSTRUCT_DURATIONOFFSET
-	add hl, bc
-	add [hl]
-	ld hl, SPRITEANIMSTRUCT_DURATION
-	add hl, bc
-	ld [hl], a
-	pop hl
-.okay
-	ld a, [hl]
-	and $c0
-	srl a
-	ld [wCurrSpriteAddSubFlags], a
-	pop af
-	ret
-
-.repeat_last
-	xor a
-	ld hl, SPRITEANIMSTRUCT_DURATION
-	add hl, bc
-	ld [hl], a
-
-	ld hl, SPRITEANIMSTRUCT_FRAME
-	add hl, bc
-	dec [hl]
-	dec [hl]
-	jr .loop
-
-.restart
-	xor a
-	ld hl, SPRITEANIMSTRUCT_DURATION
-	add hl, bc
-	ld [hl], a
-
-	dec a
-	ld hl, SPRITEANIMSTRUCT_FRAME
-	add hl, bc
-	ld [hl], a
-	jr .loop
-; 8d189
-
-.GetPointer: ; 8d189
-	; Get the data for the current frame for the current animation sequence
-
-	; SpriteAnimFrameData[SpriteAnim[SPRITEANIMSTRUCT_FRAMESET_ID]][SpriteAnim[SPRITEANIMSTRUCT_FRAME]]
-	ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
-	add hl, bc
-	ld e, [hl]
-	ld d, 0
-	ld hl, SpriteAnimFrameData
-	add hl, de
-	add hl, de
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	ld hl, SPRITEANIMSTRUCT_FRAME
-	add hl, bc
-	ld l, [hl]
-	ld h, 0
-	add hl, hl
-	add hl, de
-	ret
-; 8d1a2
-
-GetFrameOAMPointer: ; 8d1a2
-; Load OAM data pointer
-	ld e, a
-	ld d, 0
-	ld hl, SpriteAnimOAMData
-	add hl, de
-	add hl, de
-	add hl, de
-	ret
-; 8d1ac
-
-Unreferenced_BrokenGetStdGraphics: ; 8d1ac
-	push hl
-	ld l, a
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	ld de, BrokenStdGFXPointers ; broken 2bpp pointers
-	add hl, de
-	ld c, [hl]
-	inc hl
-	ld b, [hl]
-	inc hl
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	pop hl
-	push bc
-	call Request2bpp
-	pop bc
-	ret
-; 8d1c4
-
-
-INCLUDE "data/sprite_anims/sequences.asm"
-
-INCLUDE "engine/sprite_anims.asm"
-
-INCLUDE "data/sprite_anims/framesets.asm"
-
-INCLUDE "data/sprite_anims/oam.asm"
-
-
-BrokenStdGFXPointers:
-	; tile count, bank, pointer
-	; (all pointers were dummied out to .deleted)
-	dbbw 128, $01, .deleted
-	dbbw 128, $01, .deleted
-	dbbw 128, $01, .deleted
-	dbbw 128, $01, .deleted
-	dbbw 16, $37, .deleted
-	dbbw 16, $11, .deleted
-	dbbw 16, $39, .deleted
-	dbbw 16, $24, .deleted
-	dbbw 16, $21, .deleted
-
-.deleted
-; 8e72a (23:672a)
-
-
-Sprites_Cosine: ; 8e72a
-; a = d * cos(a * pi/32)
-	add %010000 ; cos(x) = sin(x + pi/2)
-	; fallthrough
-Sprites_Sine: ; 8e72c
-; a = d * sin(a * pi/32)
-	calc_sine_wave
-
-
-AnimateEndOfExpBar: ; 8e79d
-	ld a, [hSGB]
-	ld de, EndOfExpBarGFX
-	and a
-	jr z, .load
-	ld de, SGBEndOfExpBarGFX
-
-.load
-	ld hl, vTiles0 tile $00
-	lb bc, BANK(EndOfExpBarGFX), 1
-	call Request2bpp
-	ld c, 8
-	ld d, 0
-.loop
-	push bc
-	call .AnimateFrame
-	call DelayFrame
-	pop bc
-	inc d
-	inc d
-	dec c
-	jr nz, .loop
-	call ClearSprites
-	ret
-; 8e7c6
-
-.AnimateFrame: ; 8e7c6
-	ld hl, wVirtualOAMSprite00
-	ld c, 8 ; number of animated circles
-.anim_loop
-	ld a, c
-	and a
-	ret z
-	dec c
-	ld a, c
-; multiply by 8
-	sla a
-	sla a
-	sla a
-	push af
-
-	push de
-	push hl
-	call Sprites_Sine
-	pop hl
-	pop de
-	add 13 * TILE_WIDTH
-	ld [hli], a ; y
-
-	pop af
-	push de
-	push hl
-	call Sprites_Cosine
-	pop hl
-	pop de
-	add 10 * TILE_WIDTH + 4
-	ld [hli], a ; x
-
-	ld a, $0
-	ld [hli], a ; tile id
-	ld a, PAL_BATTLE_OB_BLUE
-	ld [hli], a ; attributes
-	jr .anim_loop
-; 8e7f4
-
-EndOfExpBarGFX: ; 8e7f4
-INCBIN "gfx/battle/expbarend.2bpp"
-SGBEndOfExpBarGFX: ; 8e804
-INCBIN "gfx/battle/expbarend_sgb.2bpp"
-
-ClearSpriteAnims2: ; 8e814
-	push hl
-	push de
-	push bc
-	push af
-	ld hl, wSpriteAnimDict
-	ld bc, wSpriteAnimsEnd - wSpriteAnimDict
-.loop
-	ld [hl], 0
-	inc hl
-	dec bc
-	ld a, c
-	or b
-	jr nz, .loop
-	pop af
-	pop bc
-	pop de
-	pop hl
-	ret
-; 8e82b
--- a/engine/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/stats_screen.asm
+++ /dev/null
@@ -1,1173 +1,0 @@
-	const_def 1
-	const PINK_PAGE  ; 1
-	const GREEN_PAGE ; 2
-	const BLUE_PAGE  ; 3
-NUM_STAT_PAGES EQU const_value + -1
-
-BattleStatsScreenInit: ; 4dc7b (13:5c7b)
-	ld a, [wLinkMode]
-	cp LINK_MOBILE
-	jr nz, StatsScreenInit
-
-	ld a, [wBattleMode]
-	and a
-	jr z, StatsScreenInit
-	jr _MobileStatsScreenInit
-
-StatsScreenInit: ; 4dc8a
-	ld hl, StatsScreenMain
-	jr StatsScreenInit_gotaddress
-
-_MobileStatsScreenInit: ; 4dc8f
-	ld hl, StatsScreenMobile
-	jr StatsScreenInit_gotaddress
-
-StatsScreenInit_gotaddress: ; 4dc94
-	ld a, [hMapAnims]
-	push af
-	xor a
-	ld [hMapAnims], a ; disable overworld tile animations
-	ld a, [wBoxAlignment] ; whether sprite is to be mirrorred
-	push af
-	ld a, [wJumptableIndex]
-	ld b, a
-	ld a, [wcf64]
-	ld c, a
-
-	push bc
-	push hl
-	call ClearBGPalettes
-	call ClearTileMap
-	call UpdateSprites
-	farcall StatsScreen_LoadFont
-	pop hl
-	call _hl_
-	call ClearBGPalettes
-	call ClearTileMap
-	pop bc
-
-	; restore old values
-	ld a, b
-	ld [wJumptableIndex], a
-	ld a, c
-	ld [wcf64], a
-	pop af
-	ld [wBoxAlignment], a
-	pop af
-	ld [hMapAnims], a
-	ret
-; 0x4dcd2
-
-StatsScreenMain: ; 0x4dcd2
-	xor a
-	ld [wJumptableIndex], a
-	; stupid interns
-	ld [wcf64], a
-	ld a, [wcf64]
-	and %11111100
-	or 1
-	ld [wcf64], a
-.loop ; 4dce3
-	ld a, [wJumptableIndex]
-	and $ff ^ (1 << 7)
-	ld hl, StatsScreenPointerTable
-	rst JumpTable
-	call StatsScreen_WaitAnim ; check for keys?
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr z, .loop
-	ret
-; 0x4dcf7
-
-StatsScreenMobile: ; 4dcf7
-	xor a
-	ld [wJumptableIndex], a
-	; stupid interns
-	ld [wcf64], a
-	ld a, [wcf64]
-	and %11111100
-	or 1
-	ld [wcf64], a
-.loop
-	farcall Mobile_SetOverworldDelay
-	ld a, [wJumptableIndex]
-	and $ff ^ (1 << 7)
-	ld hl, StatsScreenPointerTable
-	rst JumpTable
-	call StatsScreen_WaitAnim
-	farcall MobileComms_CheckInactivityTimer
-	jr c, .exit
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr z, .loop
-
-.exit
-	ret
-; 4dd2a
-
-StatsScreenPointerTable: ; 4dd2a
-	dw MonStatsInit       ; regular pokémon
-	dw EggStatsInit       ; egg
-	dw StatsScreenWaitCry
-	dw EggStatsJoypad
-	dw StatsScreen_LoadPage
-	dw StatsScreenWaitCry
-	dw MonStatsJoypad
-	dw StatsScreen_Exit
-; 4dd3a
-
-
-StatsScreen_WaitAnim: ; 4dd3a (13:5d3a)
-	ld hl, wcf64
-	bit 6, [hl]
-	jr nz, .try_anim
-	bit 5, [hl]
-	jr nz, .finish
-	call DelayFrame
-	ret
-
-.try_anim
-	farcall SetUpPokeAnim
-	jr nc, .finish
-	ld hl, wcf64
-	res 6, [hl]
-.finish
-	ld hl, wcf64
-	res 5, [hl]
-	farcall HDMATransferTileMapToWRAMBank3
-	ret
-
-StatsScreen_SetJumptableIndex: ; 4dd62 (13:5d62)
-	ld a, [wJumptableIndex]
-	and $80
-	or h
-	ld [wJumptableIndex], a
-	ret
-
-StatsScreen_Exit: ; 4dd6c (13:5d6c)
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-MonStatsInit: ; 4dd72 (13:5d72)
-	ld hl, wcf64
-	res 6, [hl]
-	call ClearBGPalettes
-	call ClearTileMap
-	farcall HDMATransferTileMapToWRAMBank3
-	call StatsScreen_CopyToTempMon
-	ld a, [wCurPartySpecies]
-	cp EGG
-	jr z, .egg
-	call StatsScreen_InitUpperHalf
-	ld hl, wcf64
-	set 4, [hl]
-	ld h, 4
-	call StatsScreen_SetJumptableIndex
-	ret
-
-.egg
-	ld h, 1
-	call StatsScreen_SetJumptableIndex
-	ret
-
-EggStatsInit: ; 4dda1
-	call EggStatsScreen
-	ld a, [wJumptableIndex]
-	inc a
-	ld [wJumptableIndex], a
-	ret
-; 0x4ddac
-
-
-EggStatsJoypad: ; 4ddac (13:5dac)
-	call StatsScreen_GetJoypad
-	jr nc, .check
-	ld h, 0
-	call StatsScreen_SetJumptableIndex
-	ret
-
-.check
-	bit A_BUTTON_F, a
-	jr nz, .quit
-	and D_DOWN | D_UP | A_BUTTON | B_BUTTON
-	jp StatsScreen_JoypadAction
-
-.quit
-	ld h, 7
-	call StatsScreen_SetJumptableIndex
-	ret
-
-StatsScreen_LoadPage: ; 4ddc6 (13:5dc6)
-	call StatsScreen_LoadGFX
-	ld hl, wcf64
-	res 4, [hl]
-	ld a, [wJumptableIndex]
-	inc a
-	ld [wJumptableIndex], a
-	ret
-
-MonStatsJoypad: ; 4ddd6 (13:5dd6)
-	call StatsScreen_GetJoypad
-	jr nc, .next
-	ld h, 0
-	call StatsScreen_SetJumptableIndex
-	ret
-
-.next
-	and D_DOWN | D_UP | D_LEFT | D_RIGHT | A_BUTTON | B_BUTTON
-	jp StatsScreen_JoypadAction
-
-StatsScreenWaitCry: ; 4dde6 (13:5de6)
-	call IsSFXPlaying
-	ret nc
-	ld a, [wJumptableIndex]
-	inc a
-	ld [wJumptableIndex], a
-	ret
-
-StatsScreen_CopyToTempMon: ; 4ddf2 (13:5df2)
-	ld a, [wMonType]
-	cp TEMPMON
-	jr nz, .breedmon
-	ld a, [wBufferMonSpecies]
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld hl, wBufferMon
-	ld de, wTempMon
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call CopyBytes
-	jr .done
-
-.breedmon
-	farcall CopyMonToTempMon
-	ld a, [wCurPartySpecies]
-	cp EGG
-	jr z, .done
-	ld a, [wMonType]
-	cp BOXMON
-	jr c, .done
-	farcall CalcTempmonStats
-.done
-	and a
-	ret
-
-StatsScreen_GetJoypad: ; 4de2c (13:5e2c)
-	call GetJoypad
-	ld a, [wMonType]
-	cp TEMPMON
-	jr nz, .notbreedmon
-	push hl
-	push de
-	push bc
-	farcall StatsScreenDPad
-	pop bc
-	pop de
-	pop hl
-	ld a, [wMenuJoypad]
-	and D_DOWN | D_UP
-	jr nz, .set_carry
-	ld a, [wMenuJoypad]
-	jr .clear_flags
-
-.notbreedmon
-	ld a, [hJoyPressed]
-.clear_flags
-	and a
-	ret
-
-.set_carry
-	scf
-	ret
-
-StatsScreen_JoypadAction: ; 4de54 (13:5e54)
-	push af
-	ld a, [wcf64]
-	maskbits NUM_STAT_PAGES
-	ld c, a
-	pop af
-	bit B_BUTTON_F, a
-	jp nz, .b_button
-	bit D_LEFT_F, a
-	jr nz, .d_left
-	bit D_RIGHT_F, a
-	jr nz, .d_right
-	bit A_BUTTON_F, a
-	jr nz, .a_button
-	bit D_UP_F, a
-	jr nz, .d_up
-	bit D_DOWN_F, a
-	jr nz, .d_down
-	jr .done
-
-.d_down
-	ld a, [wMonType]
-	cp BOXMON
-	jr nc, .done
-	and a
-	ld a, [wPartyCount]
-	jr z, .next_mon
-	ld a, [wOTPartyCount]
-.next_mon
-	ld b, a
-	ld a, [wCurPartyMon]
-	inc a
-	cp b
-	jr z, .done
-	ld [wCurPartyMon], a
-	ld b, a
-	ld a, [wMonType]
-	and a
-	jr nz, .load_mon
-	ld a, b
-	inc a
-	ld [wPartyMenuCursor], a
-	jr .load_mon
-
-.d_up
-	ld a, [wCurPartyMon]
-	and a
-	jr z, .done
-	dec a
-	ld [wCurPartyMon], a
-	ld b, a
-	ld a, [wMonType]
-	and a
-	jr nz, .load_mon
-	ld a, b
-	inc a
-	ld [wPartyMenuCursor], a
-	jr .load_mon
-
-.a_button
-	ld a, c
-	cp BLUE_PAGE ; last page
-	jr z, .b_button
-.d_right
-	inc c
-	ld a, BLUE_PAGE ; last page
-	cp c
-	jr nc, .set_page
-	ld c, PINK_PAGE ; first page
-	jr .set_page
-
-.d_left
-	dec c
-	jr nz, .set_page
-	ld c, BLUE_PAGE ; last page
-	jr .set_page
-
-.done
-	ret
-
-.set_page
-	ld a, [wcf64]
-	and %11111100
-	or c
-	ld [wcf64], a
-	ld h, 4
-	call StatsScreen_SetJumptableIndex
-	ret
-
-.load_mon
-	ld h, 0
-	call StatsScreen_SetJumptableIndex
-	ret
-
-.b_button ; 4dee4 (13:5ee4)
-	ld h, 7
-	call StatsScreen_SetJumptableIndex
-	ret
-
-StatsScreen_InitUpperHalf: ; 4deea (13:5eea)
-	call .PlaceHPBar
-	xor a
-	ld [hBGMapMode], a
-	ld a, [wBaseDexNo]
-	ld [wd265], a
-	ld [wCurSpecies], a
-	hlcoord 8, 0
-	ld [hl], "№"
-	inc hl
-	ld [hl], "."
-	inc hl
-	hlcoord 10, 0
-	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
-	ld de, wd265
-	call PrintNum
-	hlcoord 14, 0
-	call PrintLevel
-	ld hl, .NicknamePointers
-	call GetNicknamePointer
-	call CopyNickname
-	hlcoord 8, 2
-	call PlaceString
-	hlcoord 18, 0
-	call .PlaceGenderChar
-	hlcoord 9, 4
-	ld a, "/"
-	ld [hli], a
-	ld a, [wBaseDexNo]
-	ld [wd265], a
-	call GetPokemonName
-	call PlaceString
-	call StatsScreen_PlaceHorizontalDivider
-	call StatsScreen_PlacePageSwitchArrows
-	call StatsScreen_PlaceShinyIcon
-	ret
-
-.PlaceHPBar: ; 4df45 (13:5f45)
-	ld hl, wTempMonHP
-	ld a, [hli]
-	ld b, a
-	ld c, [hl]
-	ld hl, wTempMonMaxHP
-	ld a, [hli]
-	ld d, a
-	ld e, [hl]
-	farcall ComputeHPBarPixels
-	ld hl, wCurHPPal
-	call SetHPPal
-	ld b, SCGB_STATS_SCREEN_HP_PALS
-	call GetSGBLayout
-	call DelayFrame
-	ret
-
-.PlaceGenderChar: ; 4df66 (13:5f66)
-	push hl
-	farcall GetGender
-	pop hl
-	ret c
-	ld a, "♂"
-	jr nz, .got_gender
-	ld a, "♀"
-.got_gender
-	ld [hl], a
-	ret
-; 4df77 (13:5f77)
-
-.NicknamePointers: ; 4df77
-	dw wPartyMonNicknames
-	dw wOTPartyMonNicknames
-	dw sBoxMonNicknames
-	dw wBufferMonNick
-; 4df7f
-
-Unreferenced_Function4df7f: ; 4df7f
-	hlcoord 7, 0
-	ld bc, SCREEN_WIDTH
-	ld d, SCREEN_HEIGHT
-.loop
-	ld a, $31 ; vertical divider
-	ld [hl], a
-	add hl, bc
-	dec d
-	jr nz, .loop
-	ret
-; 4df8f
-
-StatsScreen_PlaceHorizontalDivider: ; 4df8f (13:5f8f)
-	hlcoord 0, 7
-	ld b, SCREEN_WIDTH
-	ld a, $62 ; horizontal divider (empty HP/exp bar)
-.loop
-	ld [hli], a
-	dec b
-	jr nz, .loop
-	ret
-
-StatsScreen_PlacePageSwitchArrows: ; 4df9b (13:5f9b)
-	hlcoord 12, 6
-	ld [hl], "◀"
-	hlcoord 19, 6
-	ld [hl], "▶"
-	ret
-
-StatsScreen_PlaceShinyIcon: ; 4dfa6 (13:5fa6)
-	ld bc, wTempMonDVs
-	farcall CheckShininess
-	ret nc
-	hlcoord 19, 0
-	ld [hl], "⁂"
-	ret
-
-StatsScreen_LoadGFX: ; 4dfb6 (13:5fb6)
-	ld a, [wBaseDexNo]
-	ld [wd265], a
-	ld [wCurSpecies], a
-	xor a
-	ld [hBGMapMode], a
-	call .ClearBox
-	call .PageTilemap
-	call .LoadPals
-	ld hl, wcf64
-	bit 4, [hl]
-	jr nz, .place_frontpic
-	call SetPalettes
-	ret
-
-.place_frontpic
-	call StatsScreen_PlaceFrontpic
-	ret
-
-.ClearBox: ; 4dfda (13:5fda)
-	ld a, [wcf64]
-	maskbits NUM_STAT_PAGES
-	ld c, a
-	call StatsScreen_LoadPageIndicators
-	hlcoord 0, 8
-	lb bc, 10, 20
-	call ClearBox
-	ret
-
-.LoadPals: ; 4dfed (13:5fed)
-	ld a, [wcf64]
-	maskbits NUM_STAT_PAGES
-	ld c, a
-	farcall LoadStatsScreenPals
-	call DelayFrame
-	ld hl, wcf64
-	set 5, [hl]
-	ret
-
-.PageTilemap: ; 4e002 (13:6002)
-	ld a, [wcf64]
-	maskbits NUM_STAT_PAGES
-	dec a
-	ld hl, .Jumptable
-	rst JumpTable
-	ret
-
-.Jumptable: ; 4e00d (13:600d)
-; entries correspond to *_PAGE constants
-	dw .PinkPage
-	dw .GreenPage
-	dw .BluePage
-
-.PinkPage: ; 4e013 (13:6013)
-	hlcoord 0, 9
-	ld b, $0
-	predef DrawPlayerHP
-	hlcoord 8, 9
-	ld [hl], $41 ; right HP/exp bar end cap
-	ld de, .Status_Type
-	hlcoord 0, 12
-	call PlaceString
-	ld a, [wTempMonPokerusStatus]
-	ld b, a
-	and $f
-	jr nz, .HasPokerus
-	ld a, b
-	and $f0
-	jr z, .NotImmuneToPkrs
-	hlcoord 8, 8
-	ld [hl], "." ; Pokérus immunity dot
-.NotImmuneToPkrs:
-	ld a, [wMonType]
-	cp BOXMON
-	jr z, .StatusOK
-	hlcoord 6, 13
-	push hl
-	ld de, wTempMonStatus
-	predef PlaceStatusString
-	pop hl
-	jr nz, .done_status
-	jr .StatusOK
-.HasPokerus:
-	ld de, .PkrsStr
-	hlcoord 1, 13
-	call PlaceString
-	jr .done_status
-.StatusOK:
-	ld de, .OK_str
-	call PlaceString
-.done_status
-	hlcoord 1, 15
-	predef PrintMonTypes
-	hlcoord 9, 8
-	ld de, SCREEN_WIDTH
-	ld b, 10
-	ld a, $31 ; vertical divider
-.vertical_divider
-	ld [hl], a
-	add hl, de
-	dec b
-	jr nz, .vertical_divider
-	ld de, .ExpPointStr
-	hlcoord 10, 9
-	call PlaceString
-	hlcoord 17, 14
-	call .PrintNextLevel
-	hlcoord 13, 10
-	lb bc, 3, 7
-	ld de, wTempMonExp
-	call PrintNum
-	call .CalcExpToNextLevel
-	hlcoord 13, 13
-	lb bc, 3, 7
-	ld de, wBuffer1
-	call PrintNum
-	ld de, .LevelUpStr
-	hlcoord 10, 12
-	call PlaceString
-	ld de, .ToStr
-	hlcoord 14, 14
-	call PlaceString
-	hlcoord 11, 16
-	ld a, [wTempMonLevel]
-	ld b, a
-	ld de, wTempMonExp + 2
-	predef FillInExpBar
-	hlcoord 10, 16
-	ld [hl], $40 ; left exp bar end cap
-	hlcoord 19, 16
-	ld [hl], $41 ; right exp bar end cap
-	ret
-
-.PrintNextLevel: ; 4e0d3 (13:60d3)
-	ld a, [wTempMonLevel]
-	push af
-	cp MAX_LEVEL
-	jr z, .AtMaxLevel
-	inc a
-	ld [wTempMonLevel], a
-.AtMaxLevel:
-	call PrintLevel
-	pop af
-	ld [wTempMonLevel], a
-	ret
-
-.CalcExpToNextLevel: ; 4e0e7 (13:60e7)
-	ld a, [wTempMonLevel]
-	cp MAX_LEVEL
-	jr z, .AlreadyAtMaxLevel
-	inc a
-	ld d, a
-	farcall CalcExpAtLevel
-	ld hl, wTempMonExp + 2
-	ld hl, wTempMonExp + 2
-	ld a, [hQuotient + 2]
-	sub [hl]
-	dec hl
-	ld [wBuffer3], a
-	ld a, [hQuotient + 1]
-	sbc [hl]
-	dec hl
-	ld [wBuffer2], a
-	ld a, [hQuotient]
-	sbc [hl]
-	ld [wBuffer1], a
-	ret
-
-.AlreadyAtMaxLevel:
-	ld hl, wBuffer1
-	xor a
-	ld [hli], a
-	ld [hli], a
-	ld [hl], a
-	ret
-; 4e119 (13:6119)
-
-.Status_Type: ; 4e119
-	db   "STATUS/"
-	next "TYPE/@"
-; 4e127
-
-.OK_str: ; 4e127
-	db "OK @"
-; 4e12b
-
-.ExpPointStr: ; 4e12b
-	db "EXP POINTS@"
-; 4e136
-
-.LevelUpStr: ; 4e136
-	db "LEVEL UP@"
-; 4e13f
-
-.ToStr: ; 4e13f
-	db "TO@"
-; 4e142
-
-.PkrsStr: ; 4e142
-	db "#RUS@"
-; 4e147
-
-.GreenPage: ; 4e147 (13:6147)
-	ld de, .Item
-	hlcoord 0, 8
-	call PlaceString
-	call .GetItemName
-	hlcoord 8, 8
-	call PlaceString
-	ld de, .Move
-	hlcoord 0, 10
-	call PlaceString
-	ld hl, wTempMonMoves
-	ld de, wListMoves_MoveIndicesBuffer
-	ld bc, NUM_MOVES
-	call CopyBytes
-	hlcoord 8, 10
-	ld a, SCREEN_WIDTH * 2
-	ld [wBuffer1], a
-	predef ListMoves
-	hlcoord 12, 11
-	ld a, SCREEN_WIDTH * 2
-	ld [wBuffer1], a
-	predef ListMovePP
-	ret
-
-.GetItemName: ; 4e189 (13:6189)
-	ld de, .ThreeDashes
-	ld a, [wTempMonItem]
-	and a
-	ret z
-	ld b, a
-	farcall TimeCapsule_ReplaceTeruSama
-	ld a, b
-	ld [wd265], a
-	call GetItemName
-	ret
-; 4e1a0 (13:61a0)
-
-.Item: ; 4e1a0
-	db "ITEM@"
-; 4e1a5
-
-.ThreeDashes: ; 4e1a5
-	db "---@"
-; 4e1a9
-
-.Move: ; 4e1a9
-	db "MOVE@"
-; 4e1ae
-
-.BluePage: ; 4e1ae (13:61ae)
-	call .PlaceOTInfo
-	hlcoord 10, 8
-	ld de, SCREEN_WIDTH
-	ld b, 10
-	ld a, $31 ; vertical divider
-.BluePageVerticalDivider:
-	ld [hl], a
-	add hl, de
-	dec b
-	jr nz, .BluePageVerticalDivider
-	hlcoord 11, 8
-	ld bc, 6
-	predef PrintTempMonStats
-	ret
-
-.PlaceOTInfo: ; 4e1cc (13:61cc)
-	ld de, IDNoString
-	hlcoord 0, 9
-	call PlaceString
-	ld de, OTString
-	hlcoord 0, 12
-	call PlaceString
-	hlcoord 2, 10
-	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
-	ld de, wTempMonID
-	call PrintNum
-	ld hl, .OTNamePointers
-	call GetNicknamePointer
-	call CopyNickname
-	farcall CheckNickErrors
-	hlcoord 2, 13
-	call PlaceString
-	ld a, [wTempMonCaughtGender]
-	and a
-	jr z, .done
-	cp $7f
-	jr z, .done
-	and $80
-	ld a, "♂"
-	jr z, .got_gender
-	ld a, "♀"
-.got_gender
-	hlcoord 9, 13
-	ld [hl], a
-.done
-	ret
-; 4e216 (13:6216)
-
-.OTNamePointers: ; 4e216
-	dw wPartyMonOT
-	dw wOTPartyMonOT
-	dw sBoxMonOT
-	dw wBufferMonOT
-; 4e21e
-
-IDNoString: ; 4e21e
-	db "<ID>№.@"
-
-OTString: ; 4e222
-	db "OT/@"
-; 4e226
-
-
-StatsScreen_PlaceFrontpic: ; 4e226 (13:6226)
-	ld hl, wTempMonDVs
-	predef GetUnownLetter
-	call StatsScreen_GetAnimationParam
-	jr c, .egg
-	and a
-	jr z, .no_cry
-	jr .cry
-
-.egg
-	call .AnimateEgg
-	call SetPalettes
-	ret
-
-.no_cry
-	call .AnimateMon
-	call SetPalettes
-	ret
-
-.cry
-	call SetPalettes
-	call .AnimateMon
-	ld a, [wCurPartySpecies]
-	call PlayMonCry2
-	ret
-
-.AnimateMon: ; 4e253 (13:6253)
-	ld hl, wcf64
-	set 5, [hl]
-	ld a, [wCurPartySpecies]
-	cp UNOWN
-	jr z, .unown
-	hlcoord 0, 0
-	call PrepMonFrontpic
-	ret
-
-.unown
-	xor a
-	ld [wBoxAlignment], a
-	hlcoord 0, 0
-	call _PrepMonFrontpic
-	ret
-
-.AnimateEgg: ; 4e271 (13:6271)
-	ld a, [wCurPartySpecies]
-	cp UNOWN
-	jr z, .unownegg
-	ld a, TRUE
-	ld [wBoxAlignment], a
-	call .get_animation
-	ret
-
-.unownegg
-	xor a
-	ld [wBoxAlignment], a
-	call .get_animation
-	ret
-
-.get_animation ; 4e289 (13:6289)
-	ld a, [wCurPartySpecies]
-	call IsAPokemon
-	ret c
-	call StatsScreen_LoadTextBoxSpaceGFX
-	ld de, vTiles2 tile $00
-	predef GetAnimatedFrontpic
-	hlcoord 0, 0
-	ld d, $0
-	ld e, ANIM_MON_MENU
-	predef LoadMonAnimation
-	ld hl, wcf64
-	set 6, [hl]
-	ret
-
-StatsScreen_GetAnimationParam: ; 4e2ad (13:62ad)
-	ld a, [wMonType]
-	ld hl, .Jumptable
-	rst JumpTable
-	ret
-
-.Jumptable: ; 4e2b5 (13:62b5)
-	dw .PartyMon
-	dw .OTPartyMon
-	dw .BoxMon
-	dw .Tempmon
-	dw .Wildmon
-
-.PartyMon: ; 4e2bf (13:62bf)
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMon1
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld b, h
-	ld c, l
-	jr .CheckEggFaintedFrzSlp
-
-.OTPartyMon: ; 4e2cf (13:62cf)
-	xor a
-	ret
-
-.BoxMon: ; 4e2d1 (13:62d1)
-	ld hl, sBoxMons
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld b, h
-	ld c, l
-	ld a, BANK(sBoxMons)
-	call GetSRAMBank
-	call .CheckEggFaintedFrzSlp
-	push af
-	call CloseSRAM
-	pop af
-	ret
-
-.Tempmon: ; 4e2ed (13:62ed)
-	ld bc, wTempMonSpecies
-	jr .CheckEggFaintedFrzSlp ; utterly pointless
-
-.CheckEggFaintedFrzSlp: ; 4e2f2 (13:62f2)
-	ld a, [wCurPartySpecies]
-	cp EGG
-	jr z, .egg
-	call CheckFaintedFrzSlp
-	jr c, .FaintedFrzSlp
-.egg
-	xor a
-	scf
-	ret
-
-.Wildmon: ; 4e301 (13:6301)
-	ld a, $1
-	and a
-	ret
-
-.FaintedFrzSlp: ; 4e305 (13:6305)
-	xor a
-	ret
-
-StatsScreen_LoadTextBoxSpaceGFX: ; 4e307 (13:6307)
-	nop
-	push hl
-	push de
-	push bc
-	push af
-	call DelayFrame
-	ld a, [rVBK]
-	push af
-	ld a, $1
-	ld [rVBK], a
-	ld de, TextBoxSpaceGFX
-	lb bc, BANK(TextBoxSpaceGFX), 1
-	ld hl, vTiles2 tile " "
-	call Get2bpp
-	pop af
-	ld [rVBK], a
-	pop af
-	pop bc
-	pop de
-	pop hl
-	ret
-; 4e32a (13:632a)
-
-Unreferenced_4e32a: ; 4e32a
-; A blank space tile?
-	ds 16
-; 4e33a
-
-EggStatsScreen: ; 4e33a
-	xor a
-	ld [hBGMapMode], a
-	ld hl, wCurHPPal
-	call SetHPPal
-	ld b, SCGB_STATS_SCREEN_HP_PALS
-	call GetSGBLayout
-	call StatsScreen_PlaceHorizontalDivider
-	ld de, EggString
-	hlcoord 8, 1
-	call PlaceString
-	ld de, IDNoString
-	hlcoord 8, 3
-	call PlaceString
-	ld de, OTString
-	hlcoord 8, 5
-	call PlaceString
-	ld de, FiveQMarkString
-	hlcoord 11, 3
-	call PlaceString
-	ld de, FiveQMarkString
-	hlcoord 11, 5
-	call PlaceString
-	ld a, [wTempMonHappiness] ; egg status
-	ld de, EggSoonString
-	cp $6
-	jr c, .picked
-	ld de, EggCloseString
-	cp $b
-	jr c, .picked
-	ld de, EggMoreTimeString
-	cp $29
-	jr c, .picked
-	ld de, EggALotMoreTimeString
-.picked
-	hlcoord 1, 9
-	call PlaceString
-	ld hl, wcf64
-	set 5, [hl]
-	call SetPalettes ; pals
-	call DelayFrame
-	hlcoord 0, 0
-	call PrepMonFrontpic
-	farcall HDMATransferTileMapToWRAMBank3
-	call StatsScreen_AnimateEgg
-
-	ld a, [wTempMonHappiness]
-	cp 6
-	ret nc
-	ld de, SFX_2_BOOPS
-	call PlaySFX
-	ret
-; 0x4e3c0
-
-EggString: ; 4e3c0
-	db "EGG@"
-
-FiveQMarkString: ; 4e3c4
-	db "?????@"
-
-EggSoonString: ; 0x4e3ca
-	db   "It's making sounds"
-	next "inside. It's going"
-	next "to hatch soon!@"
-
-EggCloseString: ; 0x4e3fd
-	db   "It moves around"
-	next "inside sometimes."
-	next "It must be close"
-	next "to hatching.@"
-
-EggMoreTimeString: ; 0x4e43d
-	db   "Wonder what's"
-	next "inside? It needs"
-	next "more time, though.@"
-
-EggALotMoreTimeString: ; 0x4e46e
-	db   "This EGG needs a"
-	next "lot more time to"
-	next "hatch.@"
-; 0x4e497
-
-
-StatsScreen_AnimateEgg: ; 4e497 (13:6497)
-	call StatsScreen_GetAnimationParam
-	ret nc
-	ld a, [wTempMonHappiness]
-	ld e, $7
-	cp 6
-	jr c, .animate
-	ld e, $8
-	cp 11
-	jr c, .animate
-	ret
-
-.animate
-	push de
-	ld a, $1
-	ld [wBoxAlignment], a
-	call StatsScreen_LoadTextBoxSpaceGFX
-	ld de, vTiles2 tile $00
-	predef GetAnimatedFrontpic
-	pop de
-	hlcoord 0, 0
-	ld d, $0
-	predef LoadMonAnimation
-	ld hl, wcf64
-	set 6, [hl]
-	ret
-
-StatsScreen_LoadPageIndicators: ; 4e4cd (13:64cd)
-	hlcoord 13, 5
-	ld a, $36 ; first of 4 small square tiles
-	call .load_square
-	hlcoord 15, 5
-	ld a, $36 ; " " " "
-	call .load_square
-	hlcoord 17, 5
-	ld a, $36 ; " " " "
-	call .load_square
-	ld a, c
-	cp GREEN_PAGE
-	ld a, $3a ; first of 4 large square tiles
-	hlcoord 13, 5 ; PINK_PAGE (< GREEN_PAGE)
-	jr c, .load_square
-	hlcoord 15, 5 ; GREEN_PAGE (= GREEN_PAGE)
-	jr z, .load_square
-	hlcoord 17, 5 ; BLUE_PAGE (> GREEN_PAGE)
-.load_square ; 4e4f7 (13:64f7)
-	push bc
-	ld [hli], a
-	inc a
-	ld [hld], a
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	inc a
-	ld [hli], a
-	inc a
-	ld [hl], a
-	pop bc
-	ret
-
-CopyNickname: ; 4e505 (13:6505)
-	ld de, wStringBuffer1
-	ld bc, MON_NAME_LENGTH
-	jr .okay ; utterly pointless
-.okay
-	ld a, [wMonType]
-	cp BOXMON
-	jr nz, .partymon
-	ld a, BANK(sBoxMonNicknames)
-	call GetSRAMBank
-	push de
-	call CopyBytes
-	pop de
-	call CloseSRAM
-	ret
-
-.partymon
-	push de
-	call CopyBytes
-	pop de
-	ret
-
-GetNicknamePointer: ; 4e528 (13:6528)
-	ld a, [wMonType]
-	add a
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [wMonType]
-	cp TEMPMON
-	ret z
-	ld a, [wCurPartyMon]
-	jp SkipNames
-
-
-CheckFaintedFrzSlp: ; 4e53f
-	ld hl, MON_HP
-	add hl, bc
-	ld a, [hli]
-	or [hl]
-	jr z, .fainted_frz_slp
-	ld hl, MON_STATUS
-	add hl, bc
-	ld a, [hl]
-	and 1 << FRZ | SLP
-	jr nz, .fainted_frz_slp
-	and a
-	ret
-
-.fainted_frz_slp
-	scf
-	ret
-; 4e554
--- a/engine/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/tempmon.asm
+++ /dev/null
@@ -1,127 +1,0 @@
-CopyMonToTempMon: ; 5084a
-; gets the BaseData of a mon
-; and copies the party_struct to wTempMon
-
-	ld a, [wCurPartyMon]
-	ld e, a
-	call GetMonSpecies
-	ld a, [wCurPartySpecies]
-	ld [wCurSpecies], a
-	call GetBaseData
-
-	ld a, [wMonType]
-	ld hl, wPartyMon1Species
-	ld bc, PARTYMON_STRUCT_LENGTH
-	and a
-	jr z, .copywholestruct
-	ld hl, wOTPartyMon1Species
-	ld bc, PARTYMON_STRUCT_LENGTH
-	cp OTPARTYMON
-	jr z, .copywholestruct
-	ld bc, BOXMON_STRUCT_LENGTH
-	callfar CopyBoxmonToTempMon
-	jr .done
-
-.copywholestruct
-	ld a, [wCurPartyMon]
-	call AddNTimes
-	ld de, wTempMon
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call CopyBytes
-
-.done
-	ret
-
-CalcBufferMonStats: ; 5088b
-	ld bc, wBufferMon
-	jr _TempMonStatsCalculation
-
-CalcTempmonStats: ; 50890
-	ld bc, wTempMon
-_TempMonStatsCalculation: ; 50893
-	ld hl, MON_LEVEL
-	add hl, bc
-	ld a, [hl]
-	ld [wCurPartyLevel], a
-	ld hl, MON_MAXHP
-	add hl, bc
-	ld d, h
-	ld e, l
-	ld hl, MON_STAT_EXP - 1
-	add hl, bc
-	push bc
-	ld b, TRUE
-	predef CalcMonStats
-	pop bc
-	ld hl, MON_HP
-	add hl, bc
-	ld d, h
-	ld e, l
-	ld a, [wCurPartySpecies]
-	cp EGG
-	jr nz, .not_egg
-	xor a
-	ld [de], a
-	inc de
-	ld [de], a
-	jr .zero_status
-
-.not_egg
-	push bc
-	ld hl, MON_MAXHP
-	add hl, bc
-	ld bc, 2
-	call CopyBytes
-	pop bc
-
-.zero_status
-	ld hl, MON_STATUS
-	add hl, bc
-	xor a
-	ld [hli], a
-	ld [hl], a
-	ret
-
-GetMonSpecies: ; 508d5
-; [wMonType] has the type of the mon
-; e = Nr. of mon (i.e. [wCurPartyMon])
-
-	ld a, [wMonType]
-	and a ; PARTYMON
-	jr z, .partymon
-	cp OTPARTYMON
-	jr z, .otpartymon
-	cp BOXMON
-	jr z, .boxmon
-	cp TEMPMON
-	jr z, .breedmon
-	; WILDMON
-
-.partymon
-	ld hl, wPartySpecies
-	jr .done
-
-.otpartymon
-	ld hl, wOTPartySpecies
-	jr .done
-
-.boxmon
-	ld a, BANK(sBoxSpecies)
-	call GetSRAMBank
-	ld hl, sBoxSpecies
-	call .done
-	call CloseSRAM
-	ret
-
-.breedmon
-	ld a, [wBreedMon1Species]
-	jr .done2
-
-.done
-	ld d, 0
-	add hl, de
-	ld a, [hl]
-
-.done2
-	ld [wCurPartySpecies], a
-	ret
--- a/engine/tile_events.asm
+++ /dev/null
@@ -1,110 +1,0 @@
-CheckWarpCollision:: ; 1499a
-; Is this tile a warp?
-	ld a, [wPlayerStandingTile]
-	cp COLL_PIT
-	jr z, .warp
-	cp COLL_PIT_68
-	jr z, .warp
-	and $f0
-	cp HI_NYBBLE_WARPS
-	jr z, .warp
-	and a
-	ret
-
-.warp
-	scf
-	ret
-; 149af
-
-CheckDirectionalWarp:: ; 149af
-; If this is a directional warp, clear carry (press the designated button to warp).
-; Else, set carry (immediate warp).
-	ld a, [wPlayerStandingTile]
-	cp COLL_WARP_CARPET_DOWN
-	jr z, .directional
-	cp COLL_WARP_CARPET_LEFT
-	jr z, .directional
-	cp COLL_WARP_CARPET_UP
-	jr z, .directional
-	cp COLL_WARP_CARPET_RIGHT
-	jr z, .directional
-	scf
-	ret
-
-.directional
-	xor a
-	ret
-; 149c6
-
-CheckWarpFacingDown: ; 149c6
-	ld de, 1
-	ld hl, .blocks
-	ld a, [wPlayerStandingTile]
-	call IsInArray
-	ret
-; 149d3
-
-.blocks ; 149d3
-	db COLL_DOOR
-	db COLL_DOOR_79
-	db COLL_STAIRCASE
-	db COLL_STAIRCASE_73
-	db COLL_CAVE
-	db COLL_CAVE_74
-	db COLL_WARP_PANEL
-	db COLL_DOOR_75
-	db COLL_DOOR_7D
-	db -1
-; 149dd
-
-CheckGrassCollision:: ; 149dd
-	ld a, [wPlayerStandingTile]
-	ld hl, .blocks
-	ld de, 1
-	call IsInArray
-	ret
-; 149ea
-
-.blocks ; 149ea
-	db COLL_CUT_08
-	db COLL_TALL_GRASS
-	db COLL_LONG_GRASS
-	db COLL_CUT_28
-	db COLL_WATER
-	db COLL_GRASS_48
-	db COLL_GRASS_49
-	db COLL_GRASS_4A
-	db COLL_GRASS_4B
-	db COLL_GRASS_4C
-	db -1
-; 149f5
-
-CheckCutCollision: ; 149f5
-	ld a, c
-	ld hl, .blocks
-	ld de, 1
-	call IsInArray
-	ret
-; 14a00
-
-.blocks ; 14a00
-	db COLL_CUT_TREE
-	db COLL_CUT_TREE_1A
-	db COLL_TALL_GRASS_10
-	db COLL_TALL_GRASS
-	db COLL_LONG_GRASS
-	db COLL_LONG_GRASS_1C
-	db -1
-; 14a07
-
-GetWarpSFX:: ; 14a07
-	ld a, [wPlayerStandingTile]
-	ld de, SFX_ENTER_DOOR
-	cp COLL_DOOR
-	ret z
-	ld de, SFX_WARP_TO
-	cp COLL_WARP_PANEL
-	ret z
-	ld de, SFX_EXIT_BUILDING
-	ret
-; 14a1a
--- a/engine/tileset_anims.asm
+++ /dev/null
@@ -1,1060 +1,0 @@
-_AnimateTileset:: ; fc000
-; Iterate over a given pointer array of
-; animation functions (one per frame).
-
-; Typically in wra1, vra0
-
-	ld a, [wTilesetAnim]
-	ld e, a
-	ld a, [wTilesetAnim + 1]
-	ld d, a
-
-	ld a, [hTileAnimFrame]
-	ld l, a
-	inc a
-	ld [hTileAnimFrame], a
-
-	ld h, 0
-	add hl, hl
-	add hl, hl
-	add hl, de
-
-; 2-byte parameter
-; All functions take input de.
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	inc hl
-
-; Function address
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-
-	jp hl
-; fc01b
-
-Tileset0Anim: ; 0xfc01b
-TilesetJohtoModernAnim: ; 0xfc01b
-TilesetKantoAnim: ; 0xfc01b
-	dw vTiles2 tile $14, AnimateWaterTile
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  TileAnimationPalette
-	dw NULL,  WaitTileAnimation
-	dw NULL,  AnimateFlowerTile
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  StandingTileFrame8
-	dw NULL,  DoneTileAnimation
-; 0xfc047
-
-TilesetParkAnim: ; 0xfc047
-	dw vTiles2 tile $14, AnimateWaterTile
-	dw NULL,  WaitTileAnimation
-	dw vTiles2 tile $5f, AnimateFountain
-	dw NULL,  WaitTileAnimation
-	dw NULL,  TileAnimationPalette
-	dw NULL,  WaitTileAnimation
-	dw NULL,  AnimateFlowerTile
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  StandingTileFrame8
-	dw NULL,  DoneTileAnimation
-; 0xfc073
-
-TilesetForestAnim: ; 0xfc073
-	dw NULL,  ForestTreeLeftAnimation
-	dw NULL,  ForestTreeRightAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  ForestTreeLeftAnimation2
-	dw NULL,  ForestTreeRightAnimation2
-	dw NULL,  AnimateFlowerTile
-	dw vTiles2 tile $14, AnimateWaterTile
-	dw NULL,  TileAnimationPalette
-	dw NULL,  StandingTileFrame8
-	dw NULL,  DoneTileAnimation
-; 0xfc0a3
-
-TilesetJohtoAnim: ; 0xfc0a3
-	dw vTiles2 tile $14, AnimateWaterTile
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  TileAnimationPalette
-	dw NULL,  WaitTileAnimation
-	dw NULL,  AnimateFlowerTile
-	dw WhirlpoolFrames1, AnimateWhirlpoolTile
-	dw WhirlpoolFrames2, AnimateWhirlpoolTile
-	dw WhirlpoolFrames3, AnimateWhirlpoolTile
-	dw WhirlpoolFrames4, AnimateWhirlpoolTile
-	dw NULL,  WaitTileAnimation
-	dw NULL,  StandingTileFrame8
-	dw NULL,  DoneTileAnimation
-; 0xfc0d7
-
-UnusedTilesetAnim_fc0d7: ; 0xfc0d7
-	dw vTiles2 tile $03, WriteTileToBuffer
-	dw wTileAnimBuffer, ScrollTileRightLeft
-	dw vTiles2 tile $03, WriteTileFromBuffer
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  AnimateFlowerTile
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  DoneTileAnimation
-; 0xfc103
-
-UnusedTilesetAnim_fc103: ; 0xfc103
-	dw vTiles2 tile $14, WriteTileToBuffer
-	dw wTileAnimBuffer, ScrollTileRightLeft
-	dw vTiles2 tile $14, WriteTileFromBuffer
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  DoneTileAnimation
-; 0xfc12f
-
-TilesetPortAnim: ; 0xfc12f
-	dw vTiles2 tile $14, AnimateWaterTile
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  TileAnimationPalette
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  StandingTileFrame8
-	dw NULL,  DoneTileAnimation
-; 0xfc15f
-
-TilesetEliteFourRoomAnim: ; 0xfc15f
-	dw NULL,  LavaBubbleAnim2
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  LavaBubbleAnim1
-	dw NULL,  WaitTileAnimation
-	dw NULL,  StandingTileFrame8
-	dw NULL,  DoneTileAnimation
-; 0xfc17f
-
-UnusedTilesetAnim_fc17f: ; 0xfc17f
-	dw vTiles2 tile $53, WriteTileToBuffer
-	dw wTileAnimBuffer, ScrollTileDown
-	dw wTileAnimBuffer, ScrollTileDown
-	dw vTiles2 tile $53, WriteTileFromBuffer
-	dw vTiles2 tile $03, WriteTileToBuffer
-	dw wTileAnimBuffer, ScrollTileRightLeft
-	dw vTiles2 tile $03, WriteTileFromBuffer
-	dw vTiles2 tile $53, WriteTileToBuffer
-	dw wTileAnimBuffer, ScrollTileDown
-	dw wTileAnimBuffer, ScrollTileDown
-	dw vTiles2 tile $53, WriteTileFromBuffer
-	dw NULL,  DoneTileAnimation
-; 0xfc1af
-
-UnusedTilesetAnim_fc1af: ; 0xfc1af
-	dw vTiles2 tile $54, WriteTileToBuffer
-	dw wTileAnimBuffer, ScrollTileDown
-	dw wTileAnimBuffer, ScrollTileDown
-	dw vTiles2 tile $54, WriteTileFromBuffer
-	dw NULL,  WaitTileAnimation
-	dw vTiles2 tile $03, WriteTileToBuffer
-	dw wTileAnimBuffer, ScrollTileRightLeft
-	dw vTiles2 tile $03, WriteTileFromBuffer
-	dw NULL,  WaitTileAnimation
-	dw vTiles2 tile $54, WriteTileToBuffer
-	dw wTileAnimBuffer, ScrollTileDown
-	dw wTileAnimBuffer, ScrollTileDown
-	dw vTiles2 tile $54, WriteTileFromBuffer
-	dw NULL,  DoneTileAnimation
-; 0xfc1e7
-
-TilesetCaveAnim: ; 0xfc1e7
-TilesetDarkCaveAnim: ; 0xfc1e7
-	dw vTiles2 tile $14, WriteTileToBuffer
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw wTileAnimBuffer, ScrollTileRightLeft
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw vTiles2 tile $14, WriteTileFromBuffer
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw NULL,  TileAnimationPalette
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw vTiles2 tile $40, WriteTileToBuffer
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw wTileAnimBuffer, ScrollTileDown
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw wTileAnimBuffer, ScrollTileDown
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw wTileAnimBuffer, ScrollTileDown
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw vTiles2 tile $40, WriteTileFromBuffer
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw NULL,  DoneTileAnimation
-; 0xfc233
-
-TilesetIcePathAnim: ; 0xfc233
-	dw vTiles2 tile $35, WriteTileToBuffer
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw wTileAnimBuffer, ScrollTileRightLeft
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw vTiles2 tile $35, WriteTileFromBuffer
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw NULL,  TileAnimationPalette
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw vTiles2 tile $31, WriteTileToBuffer
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw wTileAnimBuffer, ScrollTileDown
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw wTileAnimBuffer, ScrollTileDown
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw wTileAnimBuffer, ScrollTileDown
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw vTiles2 tile $31, WriteTileFromBuffer
-	dw NULL,  FlickeringCaveEntrancePalette
-	dw NULL,  DoneTileAnimation
-; 0xfc27f
-
-TilesetTowerAnim: ; 0xfc27f
-	dw TowerPillarTilePointer9,  AnimateTowerPillarTile
-	dw TowerPillarTilePointer10, AnimateTowerPillarTile
-	dw TowerPillarTilePointer7,  AnimateTowerPillarTile
-	dw TowerPillarTilePointer8,  AnimateTowerPillarTile
-	dw TowerPillarTilePointer5,  AnimateTowerPillarTile
-	dw TowerPillarTilePointer6,  AnimateTowerPillarTile
-	dw TowerPillarTilePointer3,  AnimateTowerPillarTile
-	dw TowerPillarTilePointer4,  AnimateTowerPillarTile
-	dw TowerPillarTilePointer1,  AnimateTowerPillarTile
-	dw TowerPillarTilePointer2,  AnimateTowerPillarTile
-	dw NULL,  StandingTileFrame
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  DoneTileAnimation
-; 0xfc2bf
-
-UnusedTilesetAnim_fc2bf: ; 0xfc2bf
-	dw vTiles2 tile $4f, WriteTileToBuffer
-	dw wTileAnimBuffer, ScrollTileRightLeft
-	dw vTiles2 tile $4f, WriteTileFromBuffer
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  DoneTileAnimation
-; 0xfc2e7
-
-TilesetBattleTowerOutsideAnim: ; 0xfc2e7
-TilesetHouseAnim: ; 0xfc2e7
-TilesetPlayersHouseAnim: ; 0xfc2e7
-TilesetPokecenterAnim: ; 0xfc2e7
-TilesetGateAnim: ; 0xfc2e7
-TilesetLabAnim: ; 0xfc2e7
-TilesetFacilityAnim: ; 0xfc2e7
-TilesetMartAnim: ; 0xfc2e7
-TilesetMansionAnim: ; 0xfc2e7
-TilesetGameCornerAnim: ; 0xfc2e7
-TilesetTraditionalHouseAnim: ; 0xfc2e7
-TilesetTrainStationAnim: ; 0xfc2e7
-TilesetChampionsRoomAnim: ; 0xfc2e7
-TilesetLighthouseAnim: ; 0xfc2e7
-TilesetPlayersRoomAnim: ; 0xfc2e7
-TilesetPokeComCenterAnim: ; 0xfc2e7
-TilesetBattleTowerAnim: ; 0xfc2e7
-TilesetRuinsOfAlphAnim: ; 0xfc2e7
-TilesetRadioTowerAnim: ; 0xfc2e7
-TilesetUndergroundAnim: ; 0xfc2e7
-TilesetBetaWordRoomAnim: ; 0xfc2e7
-TilesetHoOhWordRoomAnim: ; 0xfc2e7
-TilesetKabutoWordRoomAnim: ; 0xfc2e7
-TilesetOmanyteWordRoomAnim: ; 0xfc2e7
-TilesetAerodactylWordRoomAnim: ; 0xfc2e7
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  WaitTileAnimation
-	dw NULL,  DoneTileAnimation
-; 0xfc2fb
-
-DoneTileAnimation: ; fc2fb
-; Reset the animation command loop.
-	xor a
-	ld [hTileAnimFrame], a
-
-WaitTileAnimation: ; fc2fe
-; Do nothing this frame.
-	ret
-; fc2ff
-
-StandingTileFrame8: ; fc2ff
-	ld a, [wTileAnimationTimer]
-	inc a
-	and %111
-	ld [wTileAnimationTimer], a
-	ret
-; fc309
-
-
-ScrollTileRightLeft: ; fc309
-; Scroll right for 4 ticks, then left for 4 ticks.
-	ld a, [wTileAnimationTimer]
-	inc a
-	and %111
-	ld [wTileAnimationTimer], a
-	and %100
-	jr nz, ScrollTileLeft
-	jr ScrollTileRight
-; fc318
-
-ScrollTileUpDown: ; fc318
-; Scroll up for 4 ticks, then down for 4 ticks.
-	ld a, [wTileAnimationTimer]
-	inc a
-	and %111
-	ld [wTileAnimationTimer], a
-	and %100
-	jr nz, ScrollTileDown
-	jr ScrollTileUp
-; fc327
-
-ScrollTileLeft: ; fc327
-	ld h, d
-	ld l, e
-	ld c, 4
-.loop
-rept 4
-	ld a, [hl]
-	rlca
-	ld [hli], a
-endr
-	dec c
-	jr nz, .loop
-	ret
-; fc33b
-
-ScrollTileRight: ; fc33b
-	ld h, d
-	ld l, e
-	ld c, 4
-.loop
-rept 4
-	ld a, [hl]
-	rrca
-	ld [hli], a
-endr
-	dec c
-	jr nz, .loop
-	ret
-; fc34f
-
-ScrollTileUp: ; fc34f
-	ld h, d
-	ld l, e
-	ld d, [hl]
-	inc hl
-	ld e, [hl]
-	ld bc, TILE_WIDTH * 2 - 2
-	add hl, bc
-	ld a, TILE_WIDTH / 2
-.loop
-	ld c, [hl]
-	ld [hl], e
-	dec hl
-	ld b, [hl]
-	ld [hl], d
-	dec hl
-	ld e, [hl]
-	ld [hl], c
-	dec hl
-	ld d, [hl]
-	ld [hl], b
-	dec hl
-	dec a
-	jr nz, .loop
-	ret
-; fc36a
-
-ScrollTileDown: ; fc36a
-	ld h, d
-	ld l, e
-	ld de, TILE_WIDTH * 2 - 2
-	push hl
-	add hl, de
-	ld d, [hl]
-	inc hl
-	ld e, [hl]
-	pop hl
-	ld a, TILE_WIDTH / 2
-.loop
-	ld b, [hl]
-	ld [hl], d
-	inc hl
-	ld c, [hl]
-	ld [hl], e
-	inc hl
-	ld d, [hl]
-	ld [hl], b
-	inc hl
-	ld e, [hl]
-	ld [hl], c
-	inc hl
-	dec a
-	jr nz, .loop
-	ret
-; fc387
-
-
-AnimateFountain: ; fc387
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-	ld hl, .frames
-	ld a, [wTileAnimationTimer]
-	and %111
-	add a
-	add l
-	ld l, a
-	jr nc, .okay
-	inc h
-.okay
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld sp, hl
-	ld l, e
-	ld h, d
-	jp WriteTile
-
-.frames
-	dw .frame1
-	dw .frame2
-	dw .frame3
-	dw .frame4
-	dw .frame3
-	dw .frame4
-	dw .frame5
-	dw .frame1
-
-.frame1 INCBIN "gfx/tilesets/fountain/1.2bpp"
-.frame2 INCBIN "gfx/tilesets/fountain/2.2bpp"
-.frame3 INCBIN "gfx/tilesets/fountain/3.2bpp"
-.frame4 INCBIN "gfx/tilesets/fountain/4.2bpp"
-.frame5 INCBIN "gfx/tilesets/fountain/5.2bpp"
-; fc402
-
-
-AnimateWaterTile: ; fc402
-; Draw a water tile for the current frame in VRAM tile at de.
-
-; Save sp in bc (see WriteTile).
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-
-	ld a, [wTileAnimationTimer]
-
-; 4 tile graphics, updated every other frame.
-	and %110
-
-; 2 x 8 = 16 bytes per tile
-	add a
-	add a
-	add a
-
-	add LOW(WaterTileFrames)
-	ld l, a
-	ld a, 0
-	adc HIGH(WaterTileFrames)
-	ld h, a
-
-; The stack now points to the start of the tile for this frame.
-	ld sp, hl
-
-	ld l, e
-	ld h, d
-
-	jp WriteTile
-; fc41c
-
-WaterTileFrames: ; fc41c
-	INCBIN "gfx/tilesets/water/water.2bpp"
-; fc45c
-
-
-ForestTreeLeftAnimation: ; fc45c
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-
-; Only during the Celebi event.
-	ld a, [wCelebiEvent]
-	bit CELEBIEVENT_FOREST_IS_RESTLESS_F, a
-	jr nz, .asm_fc46c
-	ld hl, ForestTreeLeftFrames
-	jr .asm_fc47d
-
-.asm_fc46c
-	ld a, [wTileAnimationTimer]
-	call GetForestTreeFrame
-	add a
-	add a
-	add a
-	add LOW(ForestTreeLeftFrames)
-	ld l, a
-	ld a, 0
-	adc HIGH(ForestTreeLeftFrames)
-	ld h, a
-
-.asm_fc47d
-	ld sp, hl
-	ld hl, vTiles2 tile $0c
-	jp WriteTile
-; fc484
-
-
-ForestTreeLeftFrames: ; fc484
-	INCBIN "gfx/tilesets/forest-tree/1.2bpp"
-	INCBIN "gfx/tilesets/forest-tree/2.2bpp"
-; fc4a4
-
-ForestTreeRightFrames: ; fc4a4
-	INCBIN "gfx/tilesets/forest-tree/3.2bpp"
-	INCBIN "gfx/tilesets/forest-tree/4.2bpp"
-; fc4c4
-
-
-ForestTreeRightAnimation: ; fc4c4
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-
-; Only during the Celebi event.
-	ld a, [wCelebiEvent]
-	bit CELEBIEVENT_FOREST_IS_RESTLESS_F, a
-	jr nz, .asm_fc4d4
-	ld hl, ForestTreeRightFrames
-	jr .asm_fc4eb
-
-.asm_fc4d4
-	ld a, [wTileAnimationTimer]
-	call GetForestTreeFrame
-	add a
-	add a
-	add a
-	add LOW(ForestTreeLeftFrames)
-	ld l, a
-	ld a, 0
-	adc HIGH(ForestTreeLeftFrames)
-	ld h, a
-	push bc
-	ld bc, ForestTreeRightFrames - ForestTreeLeftFrames
-	add hl, bc
-	pop bc
-
-.asm_fc4eb
-	ld sp, hl
-	ld hl, vTiles2 tile $0f
-	jp WriteTile
-; fc4f2
-
-
-ForestTreeLeftAnimation2: ; fc4f2
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-
-; Only during the Celebi event.
-	ld a, [wCelebiEvent]
-	bit CELEBIEVENT_FOREST_IS_RESTLESS_F, a
-	jr nz, .asm_fc502
-	ld hl, ForestTreeLeftFrames
-	jr .asm_fc515
-
-.asm_fc502
-	ld a, [wTileAnimationTimer]
-	call GetForestTreeFrame
-	xor 2
-	add a
-	add a
-	add a
-	add LOW(ForestTreeLeftFrames)
-	ld l, a
-	ld a, 0
-	adc HIGH(ForestTreeLeftFrames)
-	ld h, a
-
-.asm_fc515
-	ld sp, hl
-	ld hl, vTiles2 tile $0c
-	jp WriteTile
-; fc51c
-
-
-ForestTreeRightAnimation2: ; fc51c
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-
-; Only during the Celebi event.
-	ld a, [wCelebiEvent]
-	bit CELEBIEVENT_FOREST_IS_RESTLESS_F, a
-	jr nz, .asm_fc52c
-	ld hl, ForestTreeRightFrames
-	jr .asm_fc545
-
-.asm_fc52c
-	ld a, [wTileAnimationTimer]
-	call GetForestTreeFrame
-	xor 2
-	add a
-	add a
-	add a
-	add LOW(ForestTreeLeftFrames)
-	ld l, a
-	ld a, 0
-	adc HIGH(ForestTreeLeftFrames)
-	ld h, a
-	push bc
-	ld bc, ForestTreeRightFrames - ForestTreeLeftFrames
-	add hl, bc
-	pop bc
-
-.asm_fc545
-	ld sp, hl
-	ld hl, vTiles2 tile $0f
-	jp WriteTile
-; fc54c
-
-
-GetForestTreeFrame: ; fc54c
-; Return 0 if a is even, or 2 if odd.
-	and a
-	jr z, .even
-	cp 1
-	jr z, .odd
-	cp 2
-	jr z, .even
-	cp 3
-	jr z, .odd
-	cp 4
-	jr z, .even
-	cp 5
-	jr z, .odd
-	cp 6
-	jr z, .even
-.odd
-	ld a, 2
-	scf
-	ret
-.even
-	xor a
-	ret
-; fc56d
-
-
-AnimateFlowerTile: ; fc56d
-; No parameters.
-
-; Save sp in bc (see WriteTile).
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-
-; Alternate tile graphic every other frame
-	ld a, [wTileAnimationTimer]
-	and %10
-	ld e, a
-
-; CGB has different color mappings for flowers.
-	ld a, [hCGB]
-	and 1
-
-	add e
-	swap a
-	ld e, a
-	ld d, 0
-	ld hl, FlowerTileFrames
-	add hl, de
-	ld sp, hl
-
-	ld hl, vTiles2 tile $03
-
-	jp WriteTile
-; fc58c
-
-FlowerTileFrames: ; fc58c
-	INCBIN "gfx/tilesets/flower/dmg_1.2bpp"
-	INCBIN "gfx/tilesets/flower/cgb_1.2bpp"
-	INCBIN "gfx/tilesets/flower/dmg_2.2bpp"
-	INCBIN "gfx/tilesets/flower/cgb_2.2bpp"
-; fc5cc
-
-
-LavaBubbleAnim1: ; fc5cc
-; Splash in the bottom-right corner of the fountain.
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-	ld a, [wTileAnimationTimer]
-	and %110
-	srl a
-	inc a
-	inc a
-	and %011
-	swap a
-	ld e, a
-	ld d, 0
-	ld hl, LavaBubbleFrames
-	add hl, de
-	ld sp, hl
-	ld hl, vTiles2 tile $5b
-	jp WriteTile
-; fc5eb
-
-
-LavaBubbleAnim2: ; fc5eb
-; Splash in the top-left corner of the fountain.
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-	ld a, [wTileAnimationTimer]
-	and %110
-	add a
-	add a
-	add a
-	ld e, a
-	ld d, 0
-	ld hl, LavaBubbleFrames
-	add hl, de
-	ld sp, hl
-	ld hl, vTiles2 tile $38
-	jp WriteTile
-; fc605
-
-
-LavaBubbleFrames: ; fc605
-	INCBIN "gfx/tilesets/lava/1.2bpp"
-	INCBIN "gfx/tilesets/lava/2.2bpp"
-	INCBIN "gfx/tilesets/lava/3.2bpp"
-	INCBIN "gfx/tilesets/lava/4.2bpp"
-; fc645
-
-
-AnimateTowerPillarTile: ; fc645
-; Read from struct at de:
-; 	Destination (VRAM)
-;	Address of the first tile in the frame array
-
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-
-	ld a, [wTileAnimationTimer]
-	and %111
-
-; Get frame index a
-	ld hl, .frames
-	add l
-	ld l, a
-	ld a, 0
-	adc h
-	ld h, a
-	ld a, [hl]
-
-; Destination
-	ld l, e
-	ld h, d
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	inc hl
-
-; Add the frame index to the starting address
-	add [hl]
-	inc hl
-	ld h, [hl]
-	ld l, a
-	ld a, 0
-	adc h
-	ld h, a
-
-	ld sp, hl
-	ld l, e
-	ld h, d
-	jr WriteTile
-
-.frames
-	db $00, $10, $20, $30, $40, $30, $20, $10
-; fc673
-
-
-StandingTileFrame: ; fc673
-	ld hl, wTileAnimationTimer
-	inc [hl]
-	ret
-; fc678
-
-
-AnimateWhirlpoolTile: ; fc678
-; Update whirlpool tile using struct at de.
-
-; Struct:
-; 	VRAM address
-;	Address of the first tile
-
-; Only does one of 4 tiles at a time.
-
-; Save sp in bc (see WriteTile).
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-
-; de = VRAM address
-	ld l, e
-	ld h, d
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	inc hl
-; Tile address is now at hl.
-
-; Get the tile for this frame.
-	ld a, [wTileAnimationTimer]
-	and %11 ; 4 frames x2
-	swap a  ; * 16 bytes per tile
-
-	add [hl]
-	inc hl
-	ld h, [hl]
-	ld l, a
-	ld a, 0
-	adc h
-	ld h, a
-
-; The stack now points to the desired frame.
-	ld sp, hl
-
-	ld l, e
-	ld h, d
-
-	jr WriteTile
-; fc696
-
-
-WriteTileFromBuffer: ; fc696
-; Write tiledata at wTileAnimBuffer to de.
-; wTileAnimBuffer is loaded to sp for WriteTile.
-
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-
-	ld hl, wTileAnimBuffer
-	ld sp, hl
-
-	ld h, d
-	ld l, e
-	jr WriteTile
-; fc6a2
-
-
-WriteTileToBuffer: ; fc6a2
-; Write tiledata de to wTileAnimBuffer.
-; de is loaded to sp for WriteTile.
-
-	ld hl, sp+0
-	ld b, h
-	ld c, l
-
-	ld h, d
-	ld l, e
-	ld sp, hl
-
-	ld hl, wTileAnimBuffer
-
-	; fallthrough
-
-WriteTile: ; fc6ac
-; Write one 8x8 tile ($10 bytes) from sp to hl.
-
-; Warning: sp is saved in bc so we can abuse pop.
-; sp is restored to address bc. Save sp in bc before calling.
-
-	pop de
-	ld [hl], e
-	inc hl
-	ld [hl], d
-
-rept 7
-	pop de
-	inc hl
-	ld [hl], e
-	inc hl
-	ld [hl], d
-endr
-
-; restore sp
-	ld h, b
-	ld l, c
-	ld sp, hl
-	ret
-; fc6d7
-
-
-TileAnimationPalette: ; fc6d7
-; Transition between color values 0-2 for color 0 in palette 3.
-
-; No palette changes on DMG.
-	ld a, [hCGB]
-	and a
-	ret z
-
-; We don't want to mess with non-standard palettes.
-	ld a, [rBGP] ; BGP
-	cp %11100100
-	ret nz
-
-; Only update on even frames.
-	ld a, [wTileAnimationTimer]
-	ld l, a
-	and 1 ; odd
-	ret nz
-
-; Ready for BGPD input...
-
-	ld a, (1 << rBGPI_AUTO_INCREMENT) palette PAL_BG_WATER
-	ld [rBGPI], a
-
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-
-; Update color 0 in order 0 1 2 1
-	ld a, l
-	and %110 ; frames 0 2 4 6
-	jr z, .color0
-	cp %100 ; frame 4
-	jr z, .color2
-
-.color1
-	ld hl, wBGPals1 palette PAL_BG_WATER color 1
-	ld a, [hli]
-	ld [rBGPD], a
-	ld a, [hli]
-	ld [rBGPD], a
-	jr .end
-
-.color0
-	ld hl, wBGPals1 palette PAL_BG_WATER color 0
-	ld a, [hli]
-	ld [rBGPD], a
-	ld a, [hli]
-	ld [rBGPD], a
-	jr .end
-
-.color2
-	ld hl, wBGPals1 palette PAL_BG_WATER color 2
-	ld a, [hli]
-	ld [rBGPD], a
-	ld a, [hli]
-	ld [rBGPD], a
-
-.end
-	pop af
-	ld [rSVBK], a
-	ret
-; fc71e
-
-
-FlickeringCaveEntrancePalette: ; fc71e
-; No palette changes on DMG.
-	ld a, [hCGB]
-	and a
-	ret z
-; We don't want to mess with non-standard palettes.
-	ld a, [rBGP]
-	cp %11100100
-	ret nz
-; We only want to be here if we're in a dark cave.
-	ld a, [wTimeOfDayPalset]
-	cp %11111111 ; 3,3,3,3
-	ret nz
-
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-; Ready for BGPD input...
-	ld a, (1 << rBGPI_AUTO_INCREMENT) palette PAL_BG_YELLOW
-	ld [rBGPI], a
-	ld a, [hVBlankCounter]
-	and %10
-	jr nz, .bit1set
-	ld hl, wBGPals1 palette PAL_BG_YELLOW
-	jr .okay
-
-.bit1set
-	ld hl, wBGPals1 palette PAL_BG_YELLOW color 1
-
-.okay
-	ld a, [hli]
-	ld [rBGPD], a
-	ld a, [hli]
-	ld [rBGPD], a
-
-	pop af
-	ld [rSVBK], a
-	ret
-; fc750
-
-
-TowerPillarTilePointer1:  dw vTiles2 tile $2d, TowerPillarTile1
-TowerPillarTilePointer2:  dw vTiles2 tile $2f, TowerPillarTile2
-TowerPillarTilePointer3:  dw vTiles2 tile $3d, TowerPillarTile3
-TowerPillarTilePointer4:  dw vTiles2 tile $3f, TowerPillarTile4
-TowerPillarTilePointer5:  dw vTiles2 tile $3c, TowerPillarTile5
-TowerPillarTilePointer6:  dw vTiles2 tile $2c, TowerPillarTile6
-TowerPillarTilePointer7:  dw vTiles2 tile $4d, TowerPillarTile7
-TowerPillarTilePointer8:  dw vTiles2 tile $4f, TowerPillarTile8
-TowerPillarTilePointer9:  dw vTiles2 tile $5d, TowerPillarTile9
-TowerPillarTilePointer10: dw vTiles2 tile $5f, TowerPillarTile10
-
-TowerPillarTile1:  INCBIN "gfx/tilesets/tower-pillar/1.2bpp"
-TowerPillarTile2:  INCBIN "gfx/tilesets/tower-pillar/2.2bpp"
-TowerPillarTile3:  INCBIN "gfx/tilesets/tower-pillar/3.2bpp"
-TowerPillarTile4:  INCBIN "gfx/tilesets/tower-pillar/4.2bpp"
-TowerPillarTile5:  INCBIN "gfx/tilesets/tower-pillar/5.2bpp"
-TowerPillarTile6:  INCBIN "gfx/tilesets/tower-pillar/6.2bpp"
-TowerPillarTile7:  INCBIN "gfx/tilesets/tower-pillar/7.2bpp"
-TowerPillarTile8:  INCBIN "gfx/tilesets/tower-pillar/8.2bpp"
-TowerPillarTile9:  INCBIN "gfx/tilesets/tower-pillar/9.2bpp"
-TowerPillarTile10: INCBIN "gfx/tilesets/tower-pillar/10.2bpp"
-; fca98
-
-
-WhirlpoolFrames1: dw vTiles2 tile $32, WhirlpoolTiles1
-WhirlpoolFrames2: dw vTiles2 tile $33, WhirlpoolTiles2
-WhirlpoolFrames3: dw vTiles2 tile $42, WhirlpoolTiles3
-WhirlpoolFrames4: dw vTiles2 tile $43, WhirlpoolTiles4
-; fcaa8
-
-WhirlpoolTiles1: INCBIN "gfx/tilesets/whirlpool/1.2bpp"
-WhirlpoolTiles2: INCBIN "gfx/tilesets/whirlpool/2.2bpp"
-WhirlpoolTiles3: INCBIN "gfx/tilesets/whirlpool/3.2bpp"
-WhirlpoolTiles4: INCBIN "gfx/tilesets/whirlpool/4.2bpp"
-; fcba8
--- a/engine/tileset_palettes.asm
+++ /dev/null
@@ -1,151 +1,0 @@
-LoadSpecialMapPalette: ; 494ac
-	ld a, [wMapTileset]
-	cp TILESET_POKECOM_CENTER
-	jr z, .pokecom_2f
-	cp TILESET_BATTLE_TOWER
-	jr z, .battle_tower
-	cp TILESET_ICE_PATH
-	jr z, .ice_path
-	cp TILESET_HOUSE
-	jr z, .house
-	cp TILESET_RADIO_TOWER
-	jr z, .radio_tower
-	cp TILESET_MANSION
-	jr z, .mansion_mobile
-	jr .do_nothing
-
-.pokecom_2f
-	call LoadPokeComPalette
-	scf
-	ret
-
-.battle_tower
-	call LoadBattleTowerPalette
-	scf
-	ret
-
-.ice_path
-	ld a, [wEnvironment]
-	and $7
-	cp INDOOR ; Hall of Fame
-	jr z, .do_nothing
-	call LoadIcePathPalette
-	scf
-	ret
-
-.house
-	call LoadHousePalette
-	scf
-	ret
-
-.radio_tower
-	call LoadRadioTowerPalette
-	scf
-	ret
-
-.mansion_mobile
-	call LoadMansionPalette
-	scf
-	ret
-
-.do_nothing
-	and a
-	ret
-; 494f2
-
-LoadPokeComPalette: ; 494f2
-	ld a, BANK(wBGPals1)
-	ld de, wBGPals1
-	ld hl, PokeComPalette
-	ld bc, 8 palettes
-	call FarCopyWRAM
-	ret
-; 49501
-
-PokeComPalette: ; 49501
-INCLUDE "gfx/tilesets/pokecom_center.pal"
-; 49541
-
-LoadBattleTowerPalette: ; 49541
-	ld a, BANK(wBGPals1)
-	ld de, wBGPals1
-	ld hl, BattleTowerPalette
-	ld bc, 8 palettes
-	call FarCopyWRAM
-	ret
-; 49550
-
-BattleTowerPalette: ; 49550
-INCLUDE "gfx/tilesets/battle_tower.pal"
-; 49590
-
-LoadIcePathPalette: ; 49590
-	ld a, BANK(wBGPals1)
-	ld de, wBGPals1
-	ld hl, IcePathPalette
-	ld bc, 8 palettes
-	call FarCopyWRAM
-	ret
-; 4959f
-
-IcePathPalette: ; 4959f
-INCLUDE "gfx/tilesets/ice_path.pal"
-; 495df
-
-LoadHousePalette: ; 495df
-	ld a, BANK(wBGPals1)
-	ld de, wBGPals1
-	ld hl, HousePalette
-	ld bc, 8 palettes
-	call FarCopyWRAM
-	ret
-; 495ee
-
-HousePalette: ; 495ee
-INCLUDE "gfx/tilesets/house.pal"
-; 4962e
-
-LoadRadioTowerPalette: ; 4962e
-	ld a, BANK(wBGPals1)
-	ld de, wBGPals1
-	ld hl, RadioTowerPalette
-	ld bc, 8 palettes
-	call FarCopyWRAM
-	ret
-; 4963d
-
-RadioTowerPalette: ; 4963d
-INCLUDE "gfx/tilesets/radio_tower.pal"
-; 4967d
-
-MansionPalette1: ; 4967d
-INCLUDE "gfx/tilesets/mansion_1.pal"
-; 496c5
-
-LoadMansionPalette: ; 496c5
-	ld a, BANK(wBGPals1)
-	ld de, wBGPals1
-	ld hl, MansionPalette1
-	ld bc, 8 palettes
-	call FarCopyWRAM
-	ld a, BANK(wBGPals1)
-	ld de, wBGPals1 palette PAL_BG_YELLOW
-	ld hl, MansionPalette2
-	ld bc, 1 palettes
-	call FarCopyWRAM
-	ld a, BANK(wBGPals1)
-	ld de, wBGPals1 palette PAL_BG_WATER
-	ld hl, MansionPalette1 + 6 palettes
-	ld bc, 1 palettes
-	call FarCopyWRAM
-	ld a, BANK(wBGPals1)
-	ld de, wBGPals1 palette PAL_BG_ROOF
-	ld hl, MansionPalette1 + 8 palettes
-	ld bc, 1 palettes
-	call FarCopyWRAM
-	ret
-; 496fe
-
-MansionPalette2: ; 496fe
-INCLUDE "gfx/tilesets/mansion_2.pal"
-; 49706
--- a/engine/time.asm
+++ /dev/null
@@ -1,465 +1,0 @@
-_InitializeStartDay: ; 113d6
-	call InitializeStartDay
-	ret
-; 113da
-
-ClearDailyTimers: ; 113da
-	xor a
-	ld [wLuckyNumberDayBuffer], a
-	ld [wUnusedTwoDayTimer], a
-	ld [wDailyResetTimer], a
-	ret
-; 113e5
-
-InitCallReceiveDelay:: ; 113e5
-	xor a
-	ld [wTimeCyclesSinceLastCall], a
-
-NextCallReceiveDelay: ; 113e9
-	ld a, [wTimeCyclesSinceLastCall]
-	cp 3
-	jr c, .okay
-	ld a, 3
-
-.okay
-	ld e, a
-	ld d, 0
-	ld hl, .ReceiveCallDelays
-	add hl, de
-	ld a, [hl]
-	jp RestartReceiveCallDelay
-; 113fd
-
-.ReceiveCallDelays:
-	db 20, 10, 5, 3
-; 11401
-
-CheckReceiveCallTimer: ; 11401
-	call CheckReceiveCallDelay ; check timer
-	ret nc
-	ld hl, wTimeCyclesSinceLastCall
-	ld a, [hl]
-	cp 3
-	jr nc, .ok
-	inc [hl]
-
-.ok
-	call NextCallReceiveDelay ; restart timer
-	scf
-	ret
-; 11413
-
-InitOneDayCountdown: ; 11413
-	ld a, 1
-
-InitNDaysCountdown: ; 11415
-	ld [hl], a
-	push hl
-	call UpdateTime
-	pop hl
-	inc hl
-	call CopyDayToHL
-	ret
-; 11420
-
-CheckDayDependentEventHL: ; 11420
-	inc hl
-	push hl
-	call CalcDaysSince
-	call GetDaysSince
-	pop hl
-	dec hl
-	call UpdateTimeRemaining
-	ret
-; 1142e
-
-RestartReceiveCallDelay: ; 1142e
-	ld hl, wReceiveCallDelay_MinsRemaining
-	ld [hl], a
-	call UpdateTime
-	ld hl, wReceiveCallDelay_StartTime
-	call CopyDayHourMinToHL
-	ret
-; 1143c
-
-CheckReceiveCallDelay: ; 1143c
-	ld hl, wReceiveCallDelay_StartTime
-	call CalcMinsHoursDaysSince
-	call GetMinutesSinceIfLessThan60
-	ld hl, wReceiveCallDelay_MinsRemaining
-	call UpdateTimeRemaining
-	ret
-; 1144c
-
-RestartDailyResetTimer: ; 1144c
-	ld hl, wDailyResetTimer
-	jp InitOneDayCountdown
-; 11452
-
-CheckDailyResetTimer:: ; 11452
-	ld hl, wDailyResetTimer
-	call CheckDayDependentEventHL
-	ret nc
-	xor a
-	ld hl, wDailyFlags
-	ld [hli], a ; wDailyFlags
-	ld [hli], a ; wWeeklyFlags
-	ld [hli], a ; wSwarmFlags
-	ld [hl], a  ; wSwarmFlags + 1
-	ld hl, wDailyRematchFlags
-rept 4
-	ld [hli], a
-endr
-	ld hl, wDailyPhoneItemFlags
-rept 4
-	ld [hli], a
-endr
-	ld hl, wDailyPhoneTimeOfDayFlags
-rept 4
-	ld [hli], a
-endr
-	ld hl, wKenjiBreakTimer
-	ld a, [hl]
-	and a
-	jr z, .RestartKenjiBreakCountdown
-	dec [hl]
-	jr nz, .DontRestartKenjiBreakCountdown
-.RestartKenjiBreakCountdown:
-	call SampleKenjiBreakCountdown
-.DontRestartKenjiBreakCountdown:
-	jr RestartDailyResetTimer
-; 11485
-
-SampleKenjiBreakCountdown: ; 11485
-; Generate a random number between 3 and 6
-	call Random
-	and %11
-	add 3
-	ld [wKenjiBreakTimer], a
-	ret
-; 11490
-
-StartBugContestTimer: ; 11490
-	ld a, BUG_CONTEST_MINUTES
-	ld [wBugContestMinsRemaining], a
-	ld a, BUG_CONTEST_SECONDS
-	ld [wBugContestSecsRemaining], a
-	call UpdateTime
-	ld hl, wBugContestStartTime
-	call CopyDayHourMinSecToHL
-	ret
-; 114a4
-
-
-CheckBugContestTimer:: ; 114a4 (4:54a4)
-	ld hl, wBugContestStartTime
-	call CalcSecsMinsHoursDaysSince
-	ld a, [wDaysSince]
-	and a
-	jr nz, .timed_out
-	ld a, [wHoursSince]
-	and a
-	jr nz, .timed_out
-	ld a, [wSecondsSince]
-	ld b, a
-	ld a, [wBugContestSecsRemaining]
-	sub b
-	jr nc, .okay
-	add 60
-
-.okay
-	ld [wBugContestSecsRemaining], a
-	ld a, [wMinutesSince]
-	ld b, a
-	ld a, [wBugContestMinsRemaining]
-	sbc b
-	ld [wBugContestMinsRemaining], a
-	jr c, .timed_out
-	and a
-	ret
-
-.timed_out
-	xor a
-	ld [wBugContestMinsRemaining], a
-	ld [wBugContestSecsRemaining], a
-	scf
-	ret
-
-
-InitializeStartDay: ; 114dd
-	call UpdateTime
-	ld hl, wTimerEventStartDay
-	call CopyDayToHL
-	ret
-; 114e7
-
-CheckPokerusTick:: ; 114e7
-	ld hl, wTimerEventStartDay
-	call CalcDaysSince
-	call GetDaysSince
-	and a
-	jr z, .done ; not even a day has passed since game start
-	ld b, a
-	farcall ApplyPokerusTick
-.done
-	xor a
-	ret
-; 114fc
-
-SetUnusedTwoDayTimer: ; 114fc
-	ld a, 2
-	ld hl, wUnusedTwoDayTimer
-	ld [hl], a
-	call UpdateTime
-	ld hl, wUnusedTwoDayTimerStartDate
-	call CopyDayToHL
-	ret
-; 1150c
-
-CheckUnusedTwoDayTimer: ; 1150c
-	ld hl, wUnusedTwoDayTimerStartDate
-	call CalcDaysSince
-	call GetDaysSince
-	ld hl, wUnusedTwoDayTimer
-	call UpdateTimeRemaining
-	ret
-; 1151c
-
-; unused
-	ld hl, wDailyFlags
-	set DAILYFLAGS_FISH_SWARM_F, [hl]
-	ret
-; 11522
-
-; unused
-	and a
-	ld hl, wDailyFlags
-	bit DAILYFLAGS_FISH_SWARM_F, [hl]
-	ret nz
-	scf
-	ret
-; 1152b
-
-RestartLuckyNumberCountdown: ; 1152b
-	call .GetDaysUntilNextFriday
-	ld hl, wLuckyNumberDayBuffer
-	jp InitNDaysCountdown
-; 11534
-
-.GetDaysUntilNextFriday: ; 11534
-	call GetWeekday
-	ld c, a
-	ld a, FRIDAY
-	sub c
-	jr z, .friday_saturday
-	jr nc, .earlier ; could have done "ret nc"
-
-.friday_saturday
-	add 7
-
-.earlier
-	ret
-; 11542
-
-_CheckLuckyNumberShowFlag: ; 11542
-	ld hl, wLuckyNumberDayBuffer
-	jp CheckDayDependentEventHL
-; 11548
-
-DoMysteryGiftIfDayHasPassed: ; 11548
-	ld a, BANK(sMysteryGiftTimer)
-	call GetSRAMBank
-	ld hl, sMysteryGiftTimer
-	ld a, [hli]
-	ld [wBuffer1], a
-	ld a, [hl]
-	ld [wBuffer2], a
-	call CloseSRAM
-
-	ld hl, wBuffer1
-	call CheckDayDependentEventHL
-	jr nc, .not_timed_out
-	ld hl, wBuffer1
-	call InitOneDayCountdown
-	call CloseSRAM
-	farcall Function1050c8
-
-.not_timed_out
-	ld a, BANK(sMysteryGiftTimer)
-	call GetSRAMBank
-	ld hl, wBuffer1
-	ld a, [hli]
-	ld [sMysteryGiftTimer], a
-	ld a, [hl]
-	ld [sMysteryGiftTimer + 1], a
-	call CloseSRAM
-	ret
-; 11586
-
-UpdateTimeRemaining: ; 11586
-; If the amount of time elapsed exceeds the capacity of its
-; unit, skip this part.
-	cp -1
-	jr z, .set_carry
-	ld c, a
-	ld a, [hl] ; time remaining
-	sub c
-	jr nc, .ok
-	xor a
-
-.ok
-	ld [hl], a
-	jr z, .set_carry
-	xor a
-	ret
-
-.set_carry
-	xor a
-	ld [hl], a
-	scf
-	ret
-; 11599
-
-GetSecondsSinceIfLessThan60: ; 11599
-	ld a, [wDaysSince]
-	and a
-	jr nz, GetTimeElapsed_ExceedsUnitLimit
-	ld a, [wHoursSince]
-	and a
-	jr nz, GetTimeElapsed_ExceedsUnitLimit
-	ld a, [wMinutesSince]
-	jr nz, GetTimeElapsed_ExceedsUnitLimit
-	ld a, [wSecondsSince]
-	ret
-; 115ae
-
-GetMinutesSinceIfLessThan60: ; 115ae
-	ld a, [wDaysSince]
-	and a
-	jr nz, GetTimeElapsed_ExceedsUnitLimit
-	ld a, [wHoursSince]
-	and a
-	jr nz, GetTimeElapsed_ExceedsUnitLimit
-	ld a, [wMinutesSince]
-	ret
-; 115be
-
-GetHoursSinceIfLessThan24: ; 115be
-	ld a, [wDaysSince]
-	and a
-	jr nz, GetTimeElapsed_ExceedsUnitLimit
-	ld a, [wHoursSince]
-	ret
-; 115c8
-
-GetDaysSince: ; 115c8
-	ld a, [wDaysSince]
-	ret
-; 115cc
-
-GetTimeElapsed_ExceedsUnitLimit: ; 115cc
-	ld a, -1
-	ret
-; 115cf
-
-CalcDaysSince: ; 115cf
-	xor a
-	jr _CalcDaysSince
-; 115d2
-
-CalcHoursDaysSince: ; 115d2
-	inc hl
-	xor a
-	jr _CalcHoursDaysSince
-; 115d6
-
-CalcMinsHoursDaysSince: ; 115d6
-	inc hl
-	inc hl
-	xor a
-	jr _CalcMinsHoursDaysSince
-; 115db
-
-CalcSecsMinsHoursDaysSince: ; 115db
-	inc hl
-	inc hl
-	inc hl
-	ld a, [hSeconds]
-	ld c, a
-	sub [hl]
-	jr nc, .skip
-	add 60
-.skip
-	ld [hl], c ; current seconds
-	dec hl
-	ld [wSecondsSince], a ; seconds since
-
-_CalcMinsHoursDaysSince: ; 115eb
-	ld a, [hMinutes]
-	ld c, a
-	sbc [hl]
-	jr nc, .skip
-	add 60
-.skip
-	ld [hl], c ; current minutes
-	dec hl
-	ld [wMinutesSince], a ; minutes since
-
-_CalcHoursDaysSince: ; 115f8
-	ld a, [hHours]
-	ld c, a
-	sbc [hl]
-	jr nc, .skip
-	add 24
-.skip
-	ld [hl], c ; current hours
-	dec hl
-	ld [wHoursSince], a ; hours since
-
-_CalcDaysSince:
-	ld a, [wCurDay]
-	ld c, a
-	sbc [hl]
-	jr nc, .skip
-	add 20 * 7
-.skip
-	ld [hl], c ; current days
-	ld [wDaysSince], a ; days since
-	ret
-; 11613
-
-CopyDayHourMinSecToHL: ; 11613
-	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
-; 11621
-
-CopyDayToHL: ; 11621
-	ld a, [wCurDay]
-	ld [hl], a
-	ret
-; 11626
-
-CopyDayHourToHL: ; 11626
-	ld a, [wCurDay]
-	ld [hli], a
-	ld a, [hHours]
-	ld [hli], a
-	ret
-; 1162e
-
-CopyDayHourMinToHL: ; 1162e
-	ld a, [wCurDay]
-	ld [hli], a
-	ld a, [hHours]
-	ld [hli], a
-	ld a, [hMinutes]
-	ld [hli], a
-	ret
-; 11639
--- a/engine/time_capsule.asm
+++ /dev/null
@@ -1,147 +1,0 @@
-; These functions seem to be related to backwards compatibility
-
-ValidateOTTrademon: ; fb57e
-	ld a, [wd003]
-	ld hl, wOTPartyMon1Species
-	call GetPartyLocation
-	push hl
-	ld a, [wd003]
-	inc a
-	ld c, a
-	ld b, 0
-	ld hl, wOTPartyCount
-	add hl, bc
-	ld a, [hl]
-	pop hl
-	cp EGG
-	jr z, .matching_or_egg
-	cp [hl]
-	jr nz, .abnormal
-
-.matching_or_egg
-	ld b, h
-	ld c, l
-	ld hl, MON_LEVEL
-	add hl, bc
-	ld a, [hl]
-	cp MAX_LEVEL + 1
-	jr nc, .abnormal
-	ld a, [wLinkMode]
-	cp LINK_TIMECAPSULE
-	jr nz, .normal
-	ld hl, wOTPartySpecies
-	ld a, [wd003]
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [hl]
-
-	; Magnemite and Magneton's types changed
-	; from Electric to Electric/Steel.
-	cp MAGNEMITE
-	jr z, .normal
-	cp MAGNETON
-	jr z, .normal
-
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld hl, wLinkOTPartyMonTypes
-	add hl, bc
-	add hl, bc
-	ld a, [wBaseType1]
-	cp [hl]
-	jr nz, .abnormal
-	inc hl
-	ld a, [wBaseType2]
-	cp [hl]
-	jr nz, .abnormal
-
-.normal
-	and a
-	ret
-
-.abnormal
-	scf
-	ret
-; fb5dd
-
-Functionfb5dd: ; fb5dd
-	ld a, [wd002]
-	ld d, a
-	ld a, [wPartyCount]
-	ld b, a
-	ld c, $0
-.loop
-	ld a, c
-	cp d
-	jr z, .next
-	push bc
-	ld a, c
-	ld hl, wPartyMon1HP
-	call GetPartyLocation
-	pop bc
-	ld a, [hli]
-	or [hl]
-	jr nz, .done
-
-.next
-	inc c
-	dec b
-	jr nz, .loop
-	ld a, [wd003]
-	ld hl, wOTPartyMon1HP
-	call GetPartyLocation
-	ld a, [hli]
-	or [hl]
-	jr nz, .done
-	scf
-	ret
-
-.done
-	and a
-	ret
-; fb60d
-
-PlaceTradePartnerNamesAndParty: ; fb60d
-	hlcoord 4, 0
-	ld de, wPlayerName
-	call PlaceString
-	ld a, $14
-	ld [bc], a
-	hlcoord 4, 8
-	ld de, wOTPlayerName
-	call PlaceString
-	ld a, $14
-	ld [bc], a
-	hlcoord 7, 1
-	ld de, wPartySpecies
-	call .PlaceSpeciesNames
-	hlcoord 7, 9
-	ld de, wOTPartySpecies
-.PlaceSpeciesNames: ; fb634
-	ld c, $0
-.loop
-	ld a, [de]
-	cp -1
-	ret z
-	ld [wd265], a
-	push bc
-	push hl
-	push de
-	push hl
-	ld a, c
-	ld [hProduct], a
-	call GetPokemonName
-	pop hl
-	call PlaceString
-	pop de
-	inc de
-	pop hl
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	pop bc
-	inc c
-	jr .loop
-; fb656
-
-INCLUDE "data/pokemon/gen1_base_special.asm"
--- a/engine/time_capsule_2.asm
+++ /dev/null
@@ -1,39 +1,0 @@
-ConvertMon_2to1: ; fb8f1
-; Takes the Gen-2 Pokemon number stored in wd265, finds it in the Pokered_MonIndices table, and returns its index in wd265.
-	push bc
-	push hl
-	ld a, [wd265]
-	ld b, a
-	ld c, 0
-	ld hl, Pokered_MonIndices
-.loop
-	inc c
-	ld a, [hli]
-	cp b
-	jr nz, .loop
-	ld a, c
-	ld [wd265], a
-	pop hl
-	pop bc
-	ret
-; fb908
-
-ConvertMon_1to2: ; fb908
-; Takes the Gen-1 Pokemon number stored in wd265 and returns the corresponding value from Pokered_MonIndices in wd265.
-	push bc
-	push hl
-	ld a, [wd265]
-	dec a
-	ld hl, Pokered_MonIndices
-	ld b, 0
-	ld c, a
-	add hl, bc
-	ld a, [hl]
-	ld [wd265], a
-	pop hl
-	pop bc
-	ret
-; fb91c
-
-
-INCLUDE "data/pokemon/gen1_order.asm"
--- a/engine/timeofdaypals.asm
+++ /dev/null
@@ -1,415 +1,0 @@
-DummyPredef35: ; 8c000
-DummyPredef36:
-	ret
-
-UpdateTimeOfDayPal:: ; 8c001
-	call UpdateTime
-	ld a, [wTimeOfDay]
-	ld [wCurTimeOfDay], a
-	call GetTimePalette
-	ld [wTimeOfDayPal], a
-	ret
-; 8c011
-
-
-_TimeOfDayPals:: ; 8c011
-; return carry if pals are changed
-
-; forced pals?
-	ld hl, wTimeOfDayPalFlags
-	bit 7, [hl]
-	jr nz, .dontchange
-
-; do we need to bother updating?
-	ld a, [wTimeOfDay]
-	ld hl, wCurTimeOfDay
-	cp [hl]
-	jr z, .dontchange
-
-; if so, the time of day has changed
-	ld a, [wTimeOfDay]
-	ld [wCurTimeOfDay], a
-
-; get palette id
-	call GetTimePalette
-
-; same palette as before?
-	ld hl, wTimeOfDayPal
-	cp [hl]
-	jr z, .dontchange
-
-; update palette id
-	ld [wTimeOfDayPal], a
-
-; save bg palette 7
-	ld hl, wBGPals1 palette PAL_BG_TEXT
-
-; save wram bank
-	ld a, [rSVBK]
-	ld b, a
-
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-
-; push palette
-	ld c, NUM_PAL_COLORS
-.push
-	ld d, [hl]
-	inc hl
-	ld e, [hl]
-	inc hl
-	push de
-	dec c
-	jr nz, .push
-
-; restore wram bank
-	ld a, b
-	ld [rSVBK], a
-
-
-; update sgb pals
-	ld b, SCGB_MAPPALS
-	call GetSGBLayout
-
-
-; restore bg palette 7
-	ld hl, wOBPals1 - 1 ; last byte in wBGPals1
-
-; save wram bank
-	ld a, [rSVBK]
-	ld d, a
-
-	ld a, BANK(wOBPals1)
-	ld [rSVBK], a
-
-; pop palette
-	ld e, NUM_PAL_COLORS
-.pop
-	pop bc
-	ld [hl], c
-	dec hl
-	ld [hl], b
-	dec hl
-	dec e
-	jr nz, .pop
-
-; restore wram bank
-	ld a, d
-	ld [rSVBK], a
-
-; update palettes
-	call _UpdateTimePals
-	call DelayFrame
-
-; successful change
-	scf
-	ret
-
-.dontchange
-; no change occurred
-	and a
-	ret
-; 8c070
-
-
-_UpdateTimePals:: ; 8c070
-	ld c, $9 ; normal
-	call GetTimePalFade
-	call DmgToCgbTimePals
-	ret
-; 8c079
-
-FadeInPalettes:: ; 8c079
-	ld c, $12
-	call GetTimePalFade
-	ld b, $4
-	call ConvertTimePalsDecHL
-	ret
-; 8c084
-
-FadeOutPalettes:: ; 8c084
-	call FillWhiteBGColor
-	ld c, $9
-	call GetTimePalFade
-	ld b, $4
-	call ConvertTimePalsIncHL
-	ret
-; 8c092
-
-BattleTowerFade: ; 8c092
-	call FillWhiteBGColor
-	ld c, $9
-	call GetTimePalFade
-	ld b, $4
-.asm_8c09c
-	call DmgToCgbTimePals
-	inc hl
-	inc hl
-	inc hl
-	ld c, $7
-	call DelayFrames
-	dec b
-	jr nz, .asm_8c09c
-	ret
-; 8c0ab
-
-FadeInQuickly: ; 8c0ab
-	ld c, $0
-	call GetTimePalFade
-	ld b, $4
-	call ConvertTimePalsIncHL
-	ret
-; 8c0b6
-
-FadeBlackQuickly: ; 8c0b6
-	ld c, $9
-	call GetTimePalFade
-	ld b, $4
-	call ConvertTimePalsDecHL
-	ret
-; 8c0c1
-
-
-FillWhiteBGColor: ; 8c0c1
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-
-	ld hl, wBGPals1
-	ld a, [hli]
-	ld e, a
-	ld a, [hli]
-	ld d, a
-	ld hl, wBGPals1 + 1 palettes
-	ld c, 6
-.loop
-	ld a, e
-	ld [hli], a
-	ld a, d
-	ld [hli], a
-rept 6
-	inc hl
-endr
-	dec c
-	jr nz, .loop
-
-	pop af
-	ld [rSVBK], a
-	ret
-; 8c0e5
-
-ReplaceTimeOfDayPals: ; 8c0e5
-	ld hl, .BrightnessLevels
-	ld a, [wMapTimeOfDay]
-	cp $4 ; Dark cave, needs Flash
-	jr z, .DarkCave
-	and $7
-	add l
-	ld l, a
-	ld a, $0
-	adc h
-	ld h, a
-	ld a, [hl]
-	ld [wTimeOfDayPalset], a
-	ret
-
-.DarkCave:
-	ld a, [wStatusFlags]
-	bit STATUSFLAGS_FLASH_F, a
-	jr nz, .UsedFlash
-	ld a, %11111111 ; 3, 3, 3, 3
-	ld [wTimeOfDayPalset], a
-	ret
-
-.UsedFlash:
-	ld a, %10101010 ; 2, 2, 2, 2
-	ld [wTimeOfDayPalset], a
-	ret
-; 8c10f (23:410f)
-
-.BrightnessLevels: ; 8c10f
-	dc 3, 2, 1, 0
-	dc 1, 1, 1, 1
-	dc 2, 2, 2, 2
-	dc 0, 0, 0, 0
-	dc 3, 3, 3, 3
-	dc 3, 2, 1, 0
-	dc 3, 2, 1, 0
-	dc 3, 2, 1, 0
-; 8c117
-
-GetTimePalette: ; 8c117
-	ld a, [wTimeOfDay]
-	ld e, a
-	ld d, 0
-	ld hl, .TimePalettes
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-; 8c126
-
-.TimePalettes:
-	dw .MorningPalette
-	dw .DayPalette
-	dw .NitePalette
-	dw .DarknessPalette
-
-.MorningPalette:
-	ld a, [wTimeOfDayPalset]
-	and %00000011 ; 0
-	ret
-
-.DayPalette:
-	ld a, [wTimeOfDayPalset]
-	and %00001100 ; 1
-	srl a
-	srl a
-	ret
-
-.NitePalette:
-	ld a, [wTimeOfDayPalset]
-	and %00110000 ; 2
-	swap a
-	ret
-
-.DarknessPalette:
-	ld a, [wTimeOfDayPalset]
-	and %11000000 ; 3
-	rlca
-	rlca
-	ret
-; 8c14e
-
-
-DmgToCgbTimePals: ; 8c14e
-	push hl
-	push de
-	ld a, [hli]
-	call DmgToCgbBGPals
-	ld a, [hli]
-	ld e, a
-	ld a, [hli]
-	ld d, a
-	call DmgToCgbObjPals
-	pop de
-	pop hl
-	ret
-; 8c15e
-
-ConvertTimePalsIncHL: ; 8c15e
-.loop
-	call DmgToCgbTimePals
-	inc hl
-	inc hl
-	inc hl
-	ld c, 2
-	call DelayFrames
-	dec b
-	jr nz, .loop
-	ret
-; 8c16d
-
-ConvertTimePalsDecHL: ; 8c16d
-.loop
-	call DmgToCgbTimePals
-	dec hl
-	dec hl
-	dec hl
-	ld c, 2
-	call DelayFrames
-	dec b
-	jr nz, .loop
-	ret
-; 8c17c
-
-
-GetTimePalFade: ; 8c17c
-; check cgb
-	ld a, [hCGB]
-	and a
-	jr nz, .cgb
-
-; else: dmg
-
-; index
-	ld a, [wTimeOfDayPal]
-	and %11
-
-; get fade table
-	push bc
-	ld c, a
-	ld b, $0
-	ld hl, .dmgfades
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	pop bc
-
-; get place in fade table
-	ld b, $0
-	add hl, bc
-	ret
-
-.cgb
-	ld hl, .cgbfade
-	ld b, $0
-	add hl, bc
-	ret
-
-.dmgfades
-	dw .morn
-	dw .day
-	dw .nite
-	dw .darkness
-
-.morn
-	db %11111111, %11111111, %11111111
-	db %11111110, %11111110, %11111110
-	db %11111001, %11100100, %11100100
-	db %11100100, %11010000, %11010000
-	db %10010000, %10000000, %10000000
-	db %01000000, %01000000, %01000000
-	db %00000000, %00000000, %00000000
-
-.day
-	db %11111111, %11111111, %11111111
-	db %11111110, %11111110, %11111110
-	db %11111001, %11100100, %11100100
-	db %11100100, %11010000, %11010000
-	db %10010000, %10000000, %10000000
-	db %01000000, %01000000, %01000000
-	db %00000000, %00000000, %00000000
-
-.nite
-	db %11111111, %11111111, %11111111
-	db %11111110, %11111110, %11111110
-	db %11111001, %11100100, %11100100
-	db %11101001, %11010000, %11010000
-	db %10010000, %10000000, %10000000
-	db %01000000, %01000000, %01000000
-	db %00000000, %00000000, %00000000
-
-.darkness
-	db %11111111, %11111111, %11111111
-	db %11111110, %11111110, %11111111
-	db %11111110, %11100100, %11111111
-	db %11111101, %11010000, %11111111
-	db %11111101, %10000000, %11111111
-	db %00000000, %01000000, %00000000
-	db %00000000, %00000000, %00000000
-
-.cgbfade
-	db %11111111, %11111111, %11111111
-	db %11111110, %11111110, %11111110
-	db %11111001, %11111001, %11111001
-	db %11100100, %11100100, %11100100
-	db %10010000, %10010000, %10010000
-	db %01000000, %01000000, %01000000
-	db %00000000, %00000000, %00000000
-; 8c20f
--- a/engine/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/title.asm
+++ /dev/null
@@ -1,402 +1,0 @@
-_TitleScreen: ; 10ed67
-
-	call ClearBGPalettes
-	call ClearSprites
-	call ClearTileMap
-
-; Turn BG Map update off
-	xor a
-	ld [hBGMapMode], a
-
-; Reset timing variables
-	ld hl, wJumptableIndex
-	ld [hli], a ; wJumptableIndex
-	ld [hli], a ; wIntroSceneFrameCounter
-	ld [hli], a ; wTitleScreenTimer
-	ld [hl], a  ; wTitleScreenTimer + 1
-
-; Turn LCD off
-	call DisableLCD
-
-
-; VRAM bank 1
-	ld a, 1
-	ld [rVBK], a
-
-
-; Decompress running Suicune gfx
-	ld hl, TitleSuicuneGFX
-	ld de, vTiles1
-	call Decompress
-
-
-; Clear screen palettes
-	hlbgcoord 0, 0
-	ld bc, 20 * BG_MAP_WIDTH
-	xor a
-	call ByteFill
-
-
-; Fill tile palettes:
-
-; BG Map 1:
-
-; line 0 (copyright)
-	hlbgcoord 0, 0, vBGMap1
-	ld bc, BG_MAP_WIDTH
-	ld a, 7 ; palette
-	call ByteFill
-
-
-; BG Map 0:
-
-; Apply logo gradient:
-
-; lines 3-4
-	hlbgcoord 0, 3
-	ld bc, 2 * BG_MAP_WIDTH
-	ld a, 2
-	call ByteFill
-; line 5
-	hlbgcoord 0, 5
-	ld bc, BG_MAP_WIDTH
-	ld a, 3
-	call ByteFill
-; line 6
-	hlbgcoord 0, 6
-	ld bc, BG_MAP_WIDTH
-	ld a, 4
-	call ByteFill
-; line 7
-	hlbgcoord 0, 7
-	ld bc, BG_MAP_WIDTH
-	ld a, 5
-	call ByteFill
-; lines 8-9
-	hlbgcoord 0, 8
-	ld bc, 2 * BG_MAP_WIDTH
-	ld a, 6
-	call ByteFill
-
-
-; 'CRYSTAL VERSION'
-	hlbgcoord 5, 9
-	ld bc, NAME_LENGTH ; length of version text
-	ld a, 1
-	call ByteFill
-
-; Suicune gfx
-	hlbgcoord 0, 12
-	ld bc, 6 * BG_MAP_WIDTH ; the rest of the screen
-	ld a, 0 | VRAM_BANK_1
-	call ByteFill
-
-
-; Back to VRAM bank 0
-	ld a, $0
-	ld [rVBK], a
-
-
-; Decompress logo
-	ld hl, TitleLogoGFX
-	ld de, vTiles1
-	call Decompress
-
-; Decompress background crystal
-	ld hl, TitleCrystalGFX
-	ld de, vTiles0
-	call Decompress
-
-
-; Clear screen tiles
-	hlbgcoord 0, 0
-	ld bc, 64 * BG_MAP_WIDTH
-	ld a, " "
-	call ByteFill
-
-; Draw Pokemon logo
-	hlcoord 0, 3
-	lb bc, 7, 20
-	ld d, $80
-	ld e, $14
-	call DrawTitleGraphic
-
-; Draw copyright text
-	hlbgcoord 3, 0, vBGMap1
-	lb bc, 1, 13
-	ld d, $c
-	ld e, $10
-	call DrawTitleGraphic
-
-; Initialize running Suicune?
-	ld d, $0
-	call LoadSuicuneFrame
-
-; Initialize background crystal
-	call InitializeBackground
-
-; Save WRAM bank
-	ld a, [rSVBK]
-	push af
-; WRAM bank 5
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-
-; Update palette colors
-	ld hl, TitleScreenPalettes
-	ld de, wBGPals1
-	ld bc, 16 palettes
-	call CopyBytes
-
-	ld hl, TitleScreenPalettes
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-
-; Restore WRAM bank
-	pop af
-	ld [rSVBK], a
-
-
-; LY/SCX trickery starts here
-
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wLYOverrides)
-	ld [rSVBK], a
-
-; Make alternating lines come in from opposite sides
-
-; (This part is actually totally pointless, you can't
-;  see anything until these values are overwritten!)
-
-	ld b, 80 / 2 ; alternate for 80 lines
-	ld hl, wLYOverrides
-.loop
-; $00 is the middle position
-	ld [hl], +112 ; coming from the left
-	inc hl
-	ld [hl], -112 ; coming from the right
-	inc hl
-	dec b
-	jr nz, .loop
-
-; Make sure the rest of the buffer is empty
-	ld hl, wLYOverrides + 80
-	xor a
-	ld bc, wLYOverridesEnd - (wLYOverrides + 80)
-	call ByteFill
-
-; Let LCD Stat know we're messing around with SCX
-	ld a, rSCX - $ff00
-	ld [hLCDCPointer], a
-
-	pop af
-	ld [rSVBK], a
-
-
-; Reset audio
-	call ChannelsOff
-	call EnableLCD
-
-; Set sprite size to 8x16
-	ld a, [rLCDC]
-	set rLCDC_SPRITE_SIZE, a
-	ld [rLCDC], a
-
-	ld a, +112
-	ld [hSCX], a
-	ld a, 8
-	ld [hSCY], a
-	ld a, 7
-	ld [hWX], a
-	ld a, -112
-	ld [hWY], a
-
-	ld a, $1
-	ld [hCGBPalUpdate], a
-
-; Update BG Map 0 (bank 0)
-	ld [hBGMapMode], a
-
-	xor a
-	ld [wBGPals1 + 2], a
-
-; Play starting sound effect
-	call SFXChannelsOff
-	ld de, SFX_TITLE_SCREEN_ENTRANCE
-	call PlaySFX
-
-	ret
-; 10eea7
-
-SuicuneFrameIterator: ; 10eea7
-	ld hl, wBGPals1 + 2
-	ld a, [hl]
-	ld c, a
-	inc [hl]
-
-; Only do this once every eight frames
-	and %111
-	ret nz
-
-	ld a, c
-	and %11000
-	sla a
-	swap a
-	ld e, a
-	ld d, $0
-	ld hl, .Frames
-	add hl, de
-	ld d, [hl]
-	xor a
-	ld [hBGMapMode], a
-	call LoadSuicuneFrame
-	ld a, $1
-	ld [hBGMapMode], a
-	ld a, $3
-	ld [hBGMapThird], a
-	ret
-; 10eece
-
-.Frames: ; 10eece
-	db $80 ; vTiles4 tile $00
-	db $88 ; vTiles4 tile $08
-	db $00 ; vTiles5 tile $00
-	db $08 ; vTiles5 tile $08
-; 10eed2
-
-
-LoadSuicuneFrame: ; 10eed2
-	hlcoord 6, 12
-	ld b, 6
-.bgrows
-	ld c, 8
-.col
-	ld a, d
-	ld [hli], a
-	inc d
-	dec c
-	jr nz, .col
-	ld a, SCREEN_WIDTH - 8
-	add l
-	ld l, a
-	ld a, 0
-	adc h
-	ld h, a
-	ld a, 8
-	add d
-	ld d, a
-	dec b
-	jr nz, .bgrows
-	ret
-; 10eeef
-
-DrawTitleGraphic: ; 10eeef
-; input:
-;   hl: draw location
-;   b: height
-;   c: width
-;   d: tile to start drawing from
-;   e: number of tiles to advance for each bgrows
-.bgrows
-	push de
-	push bc
-	push hl
-.col
-	ld a, d
-	ld [hli], a
-	inc d
-	dec c
-	jr nz, .col
-	pop hl
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	pop bc
-	pop de
-	ld a, e
-	add d
-	ld d, a
-	dec b
-	jr nz, .bgrows
-	ret
-; 10ef06
-
-InitializeBackground: ; 10ef06
-	ld hl, wVirtualOAMSprite00
-	ld d, -$22
-	ld e, $0
-	ld c, 5
-.loop
-	push bc
-	call .InitColumn
-	pop bc
-	ld a, $10
-	add d
-	ld d, a
-	dec c
-	jr nz, .loop
-	ret
-; 10ef1c
-
-.InitColumn: ; 10ef1c
-	ld c, $6
-	ld b, $40
-.loop2
-	ld a, d
-	ld [hli], a ; y
-	ld a, b
-	ld [hli], a ; x
-	add $8
-	ld b, a
-	ld a, e
-	ld [hli], a ; tile id
-	inc e
-	inc e
-	ld a, 0 | PRIORITY
-	ld [hli], a ; attributes
-	dec c
-	jr nz, .loop2
-	ret
-; 10ef32
-
-
-AnimateTitleCrystal: ; 10ef32
-; Move the title screen crystal downward until it's fully visible
-
-; Stop at y=6
-; y is really from the bottom of the sprite, which is two tiles high
-	ld hl, wVirtualOAMSprite00YCoord
-	ld a, [hl]
-	cp 6 + 2 * TILE_WIDTH
-	ret z
-
-; Move all 30 parts of the crystal down by 2
-	ld c, 30
-.loop
-	ld a, [hl]
-	add 2
-	ld [hli], a ; y
-rept SPRITEOAMSTRUCT_LENGTH + -1
-	inc hl
-endr
-	dec c
-	jr nz, .loop
-
-	ret
-; 10ef46
-
-TitleSuicuneGFX: ; 10ef46
-INCBIN "gfx/title/suicune.2bpp.lz"
-; 10f326
-
-TitleLogoGFX: ; 10f326
-INCBIN "gfx/title/logo.2bpp.lz"
-; 10fcee
-
-TitleCrystalGFX: ; 10fcee
-INCBIN "gfx/title/crystal.2bpp.lz"
-; 10fede
-
-TitleScreenPalettes:
-INCLUDE "gfx/title/title.pal"
--- /dev/null
+++ b/engine/title/credits.asm
@@ -1,0 +1,621 @@
+INCLUDE "constants.asm"
+
+
+SECTION "Credits", ROMX
+
+Credits:: ; 109847
+	bit 6, b ; Hall Of Fame
+	ld a, $0
+	jr z, .okay
+	ld a, $40
+.okay
+	ld [wJumptableIndex], a
+
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wGBCPalettes)
+	ld [rSVBK], a
+
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+
+	ld hl, wCreditsFaux2bpp
+	ld c, $80
+	ld de, $ff00
+
+.load_loop
+	ld a, e
+	ld [hli], a
+	ld a, d
+	ld [hli], a
+	dec c
+	jr nz, .load_loop
+
+	ld de, CreditsBorderGFX
+	ld hl, vTiles2 tile $20
+	lb bc, BANK(CreditsBorderGFX), 9
+	call Request2bpp
+
+	ld de, CopyrightGFX
+	ld hl, vTiles2 tile $60
+	lb bc, BANK(CopyrightGFX), 29
+	call Request2bpp
+
+	ld de, TheEndGFX
+	ld hl, vTiles2 tile $40
+	lb bc, BANK(TheEndGFX), 16
+	call Request2bpp
+
+	ld a, $ff
+	ld [wCreditsBorderFrame], a
+	xor a
+	ld [wCreditsBorderMon], a
+
+	call Credits_LoadBorderGFX
+	ld e, l
+	ld d, h
+	ld hl, vTiles2
+	lb bc, BANK(CreditsMonsGFX), 16
+	call Request2bpp
+
+	call ConstructCreditsTilemap
+	xor a
+	ld [wCreditsLYOverride], a
+
+	ld hl, wLYOverrides
+	ld bc, $100
+	xor a
+	call ByteFill
+
+	ld a, rSCX - $ff00
+	ld [hLCDCPointer], a
+
+	call GetCreditsPalette
+	call SetPalettes
+	ld a, [hVBlank]
+	push af
+	ld a, $5
+	ld [hVBlank], a
+	ld a, $1
+	ld [hInMenu], a
+	xor a
+	ld [hBGMapMode], a
+	ld [wCreditsPos], a
+	ld [wCreditsUnusedCD21], a
+	ld [wCreditsTimer], a
+
+.execution_loop
+	call Credits_HandleBButton
+	call Credits_HandleAButton
+	jr nz, .exit_credits
+
+	call Credits_Jumptable
+	call DelayFrame
+	jr .execution_loop
+
+.exit_credits
+	call ClearBGPalettes
+	xor a
+	ld [hLCDCPointer], a
+	ld [hBGMapAddress], a
+	pop af
+	ld [hVBlank], a
+	pop af
+	ld [rSVBK], a
+	ret
+; 1098fd
+
+Credits_HandleAButton: ; 1098fd
+	ld a, [hJoypadDown]
+	and A_BUTTON
+	ret z
+	ld a, [wJumptableIndex]
+	bit 7, a
+	ret
+; 109908
+
+Credits_HandleBButton: ; 109908
+	ld a, [hJoypadDown]
+	and B_BUTTON
+	ret z
+	ld a, [wJumptableIndex]
+	bit 6, a
+	ret z
+	ld hl, wCreditsPos
+	ld a, [hli]
+	cp $d
+	jr nc, .okay
+	ld a, [hli]
+	and a
+	ret z
+.okay
+	ld hl, wCreditsTimer
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+	ret
+; 109926
+
+Credits_Jumptable: ; 109926
+	ld a, [wJumptableIndex]
+	and $f
+	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
+; 109937
+
+.Jumptable: ; 109937 (42:5937)
+	dw ParseCredits
+	dw Credits_Next
+	dw Credits_Next
+	dw Credits_PrepBGMapUpdate
+	dw Credits_UpdateGFXRequestPath
+	dw Credits_RequestGFX
+	dw Credits_LYOverride
+	dw Credits_Next
+	dw Credits_Next
+	dw Credits_Next
+	dw Credits_UpdateGFXRequestPath
+	dw Credits_RequestGFX
+	dw Credits_LoopBack
+
+Credits_Next: ; 109951 (42:5951)
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+Credits_LoopBack: ; 109956 (42:5956)
+	ld hl, wJumptableIndex
+	ld a, [hl]
+	and $f0
+	ld [hl], a
+	ret
+
+Credits_PrepBGMapUpdate: ; 10995e (42:595e)
+	xor a
+	ld [hBGMapMode], a
+	jp Credits_Next
+
+Credits_UpdateGFXRequestPath: ; 109964 (42:5964)
+	call Credits_LoadBorderGFX
+	ld a, l
+	ld [wRequested2bppSource], a
+	ld a, h
+	ld [wRequested2bppSource + 1], a
+	ld a, LOW(vTiles2)
+	ld [wRequested2bppDest], a
+	ld a, HIGH(vTiles2)
+	ld [wRequested2bppDest + 1], a
+	jr Credits_RequestGFX
+
+Credits_RequestGFX: ; 10997b (42:597b)
+	xor a
+	ld [hBGMapMode], a
+	ld a, $8
+	ld [wRequested2bpp], a
+	jp Credits_Next
+
+Credits_LYOverride: ; 109986 (42:5986)
+	ld a, [rLY]
+	cp $30
+	jr c, Credits_LYOverride
+	ld a, [wCreditsLYOverride]
+	dec a
+	dec a
+	ld [wCreditsLYOverride], a
+	ld hl, wLYOverrides + $1f
+	call .Fill
+	ld hl, wLYOverrides + $87
+	call .Fill
+	jp Credits_Next
+
+.Fill: ; 1099a3 (42:59a3)
+	ld c, $8
+.loop
+	ld [hli], a
+	dec c
+	jr nz, .loop
+	ret
+; 1099aa
+
+
+ParseCredits: ; 1099aa
+	ld hl, wJumptableIndex
+	bit 7, [hl]
+	jp nz, .done
+
+; Wait until the timer has run out to parse the next command.
+	ld hl, wCreditsTimer
+	ld a, [hl]
+	and a
+	jr z, .parse
+
+; One tick has passed.
+	dec [hl]
+	jp .done
+
+.parse
+; First, let's clear the current text display,
+; starting from line 5.
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 0, 5
+	ld bc, 20 * 12
+	ld a, " "
+	call ByteFill
+
+; Then read the script.
+
+.loop
+	call .get
+
+; Commands:
+	cp CREDITS_END
+	jp z, .end
+	cp CREDITS_WAIT
+	jr z, .wait
+	cp CREDITS_SCENE
+	jr z, .scene
+	cp CREDITS_CLEAR
+	jr z, .clear
+	cp CREDITS_MUSIC
+	jr z, .music
+	cp CREDITS_WAIT2
+	jr z, .wait2
+	cp CREDITS_THEEND
+	jr z, .theend
+
+; If it's not a command, it's a string identifier.
+
+	push af
+	ld e, a
+	ld d, 0
+	ld hl, CreditsStrings
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+	pop af
+
+; Strings spanning multiple lines have special cases.
+
+	cp COPYRIGHT
+	jr z, .copyright
+
+	cp STAFF
+	jr c, .staff
+
+; The rest start from line 6.
+
+	hlcoord 0, 6
+	jr .print
+
+.copyright
+	hlcoord 2, 6
+	jr .print
+
+.staff
+	hlcoord 0, 6
+
+.print
+; Print strings spaced every two lines.
+	call .get
+	ld bc, 20 * 2
+	call AddNTimes
+	call PlaceString
+	jr .loop
+
+.theend
+; Display "The End" graphic.
+	call Credits_TheEnd
+	jr .loop
+
+.scene
+; Update the scene number and corresponding palette.
+	call .get
+	ld [wCreditsBorderMon], a ; scene
+	xor a
+	ld [wCreditsBorderFrame], a ; frame
+	call GetCreditsPalette
+	call SetPalettes ; update hw pal registers
+	jr .loop
+
+.clear
+; Clear the banner.
+	ld a, $ff
+	ld [wCreditsBorderFrame], a ; frame
+	jr .loop
+
+.music
+; Play the credits music.
+	ld de, MUSIC_CREDITS
+	push de
+	ld de, MUSIC_NONE
+	call PlayMusic
+	call DelayFrame
+	pop de
+	call PlayMusic
+	jp .loop
+
+.wait2
+; Wait for some amount of ticks.
+	call .get
+	ld [wCreditsTimer], a
+	jr .done
+
+.wait
+; Wait for some amount of ticks, and do something else.
+	call .get
+	ld [wCreditsTimer], a
+
+	xor a
+	ld [hBGMapThird], a
+	ld a, 1
+	ld [hBGMapMode], a
+
+.done
+	jp Credits_Next
+
+.end
+; Stop execution.
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ld a, 32
+	ld [wMusicFade], a
+	ld a, LOW(MUSIC_POST_CREDITS)
+	ld [wMusicFadeID], a
+	ld a, HIGH(MUSIC_POST_CREDITS)
+	ld [wMusicFadeID + 1], a
+	ret
+
+.get
+; Get byte wCreditsPos from CreditsScript
+	push hl
+	push de
+	ld a, [wCreditsPos]
+	ld e, a
+	ld a, [wCreditsPos+1]
+	ld d, a
+	ld hl, CreditsScript
+	add hl, de
+
+	inc de
+	ld a, e
+	ld [wCreditsPos], a
+	ld a, d
+	ld [wCreditsPos+1], a
+	ld a, [hl]
+	pop de
+	pop hl
+	ret
+; 109a95
+
+
+ConstructCreditsTilemap: ; 109a95 (42:5a95)
+	xor a
+	ld [hBGMapMode], a
+	ld a, $c
+	ld [hBGMapAddress], a
+
+	ld a, $28
+	hlcoord 0, 0
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	call ByteFill
+
+	ld a, $7f
+	hlcoord 0, 4
+	ld bc, (SCREEN_HEIGHT - 4) * SCREEN_WIDTH
+	call ByteFill
+
+	hlcoord 0, 4
+	ld a, $24
+	call DrawCreditsBorder
+
+	hlcoord 0, 17
+	ld a, $20
+	call DrawCreditsBorder
+
+	hlcoord 0, 0, wAttrMap
+	ld bc, 4 * SCREEN_WIDTH
+	xor a
+	call ByteFill
+
+	hlcoord 0, 4, wAttrMap
+	ld bc, SCREEN_WIDTH
+	ld a, $1
+	call ByteFill
+
+	hlcoord 0, 5, wAttrMap
+	ld bc, 12 * SCREEN_WIDTH
+	ld a, $2
+	call ByteFill
+
+	hlcoord 0, 17, wAttrMap
+	ld bc, SCREEN_WIDTH
+	ld a, $1
+	call ByteFill
+
+	call WaitBGMap2
+	xor a
+	ld [hBGMapMode], a
+	ld [hBGMapAddress], a
+	hlcoord 0, 0
+	call .InitTopPortion
+	call WaitBGMap2
+	ret
+
+.InitTopPortion: ; 109aff (42:5aff)
+	ld b, 5
+.outer_loop
+	push hl
+	ld de, SCREEN_WIDTH - 3
+	ld c, 4
+	xor a
+.inner_loop
+rept 3
+	ld [hli], a
+	inc a
+endr
+	ld [hl], a
+	inc a
+	add hl, de
+	dec c
+	jr nz, .inner_loop
+	pop hl
+rept 4
+	inc hl
+endr
+	dec b
+	jr nz, .outer_loop
+	ret
+
+DrawCreditsBorder: ; 109b1d (42:5b1d)
+	ld c, SCREEN_WIDTH / 4
+.loop
+	push af
+rept 3
+	ld [hli], a
+	inc a
+endr
+	ld [hli], a
+	pop af
+	dec c
+	jr nz, .loop
+	ret
+
+GetCreditsPalette: ; 109b2c
+	call .GetPalAddress
+
+	push hl
+	ld a, 0
+	call .UpdatePals
+	pop hl
+	ret
+
+.GetPalAddress:
+; Each set of palette data is 24 bytes long.
+	ld a, [wCreditsBorderMon] ; scene
+	and %11
+	add a
+	add a ; * 8
+	add a
+	ld e, a
+	ld d, 0
+	ld hl, CreditsPalettes
+	add hl, de
+	add hl, de ; * 3
+	add hl, de
+	ret
+
+.UpdatePals:
+; Update the first three colors in both palette buffers.
+	push af
+	push hl
+	add LOW(wBGPals1)
+	ld e, a
+	ld a, 0
+	adc HIGH(wBGPals1)
+	ld d, a
+	ld bc, 24
+	call CopyBytes
+
+	pop hl
+	pop af
+	add LOW(wBGPals2)
+	ld e, a
+	ld a, 0
+	adc HIGH(wBGPals2)
+	ld d, a
+	ld bc, 24
+	call CopyBytes
+	ret
+
+CreditsPalettes:
+INCLUDE "gfx/credits/credits.pal"
+; 109bca
+
+Credits_LoadBorderGFX: ; 109bca (42:5bca)
+	ld hl, wCreditsBorderFrame
+	ld a, [hl]
+	cp $ff
+	jr z, .init
+
+	and %11
+	ld e, a
+	inc a
+	and %11
+	ld [hl], a
+	ld a, [wCreditsBorderMon]
+	and %11
+	add a
+	add a
+	add e
+	add a
+	ld e, a
+	ld d, 0
+	ld hl, .Frames
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ret
+
+.init
+	ld hl, wCreditsFaux2bpp
+	ret
+; 109bf1 (42:5bf1)
+
+.Frames: ; 109bf1
+	dw CreditsPichuGFX
+	dw CreditsPichuGFX     + 16 tiles
+	dw CreditsPichuGFX     + 32 tiles
+	dw CreditsPichuGFX     + 48 tiles
+	dw CreditsSmoochumGFX
+	dw CreditsSmoochumGFX  + 16 tiles
+	dw CreditsSmoochumGFX  + 32 tiles
+	dw CreditsSmoochumGFX  + 48 tiles
+	dw CreditsDittoGFX
+	dw CreditsDittoGFX     + 16 tiles
+	dw CreditsDittoGFX     + 32 tiles
+	dw CreditsDittoGFX     + 48 tiles
+	dw CreditsIgglybuffGFX
+	dw CreditsIgglybuffGFX + 16 tiles
+	dw CreditsIgglybuffGFX + 32 tiles
+	dw CreditsIgglybuffGFX + 48 tiles
+; 109c11
+
+Credits_TheEnd: ; 109c11 (42:5c11)
+	ld a, $40
+	hlcoord 6, 9
+	call .Load
+	hlcoord 6, 10
+.Load: ; 109c1c (42:5c1c)
+	ld c, 8
+.loop
+	ld [hli], a
+	inc a
+	dec c
+	jr nz, .loop
+	ret
+; 109c24 (42:5c24)
+
+
+CreditsBorderGFX:    INCBIN "gfx/credits/border.2bpp"
+
+CreditsMonsGFX:
+CreditsPichuGFX:     INCBIN "gfx/credits/pichu.2bpp"
+CreditsSmoochumGFX:  INCBIN "gfx/credits/smoochum.2bpp"
+CreditsDittoGFX:     INCBIN "gfx/credits/ditto.2bpp"
+CreditsIgglybuffGFX: INCBIN "gfx/credits/igglybuff.2bpp"
+
+INCLUDE "data/credits_script.asm"
+INCLUDE "data/credits_strings.asm"
--- /dev/null
+++ b/engine/title/crystal_intro.asm
@@ -1,0 +1,2199 @@
+Copyright_GFPresents: ; e4579
+	ld de, MUSIC_NONE
+	call PlayMusic
+	call ClearBGPalettes
+	call ClearTileMap
+	ld a, HIGH(vBGMap0)
+	ld [hBGMapAddress + 1], a
+	xor a ; LOW(vBGMap0)
+	ld [hBGMapAddress], a
+	ld [hJoyDown], a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld a, $90
+	ld [hWY], a
+	call WaitBGMap
+	ld b, SCGB_GAMEFREAK_LOGO
+	call GetSGBLayout
+	call SetPalettes
+	ld c, 10
+	call DelayFrames
+	callfar Copyright
+	call WaitBGMap
+	ld c, 100
+	call DelayFrames
+	call ClearTileMap
+	farcall GBCOnlyScreen
+	call .GetGFLogoGFX
+.joy_loop
+	call JoyTextDelay
+	ld a, [hJoyLast]
+	and BUTTONS
+	jr nz, .pressed_button
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .finish
+	call PlaceGameFreakPresents
+	farcall PlaySpriteAnimations
+	call DelayFrame
+	jr .joy_loop
+
+.pressed_button
+	call .StopGamefreakAnim
+	scf
+	ret
+
+.finish
+	call .StopGamefreakAnim
+	and a
+	ret
+; e45e8
+
+.GetGFLogoGFX: ; e45e8
+	ld de, GameFreakLogo
+	ld hl, vTiles2
+	lb bc, BANK(GameFreakLogo), 28
+	call Get1bpp
+
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wDecompressScratch)
+	ld [rSVBK], a
+
+	ld hl, IntroLogoGFX
+	ld de, wDecompressScratch
+	ld a, BANK(IntroLogoGFX)
+	call FarDecompress
+
+	ld hl, vTiles0
+	ld de, wDecompressScratch
+	lb bc, 1, 8 tiles
+	call Request2bpp
+
+	ld hl, vTiles1
+	ld de, wDecompressScratch + $80 tiles
+	lb bc, 1, 8 tiles
+	call Request2bpp
+
+	pop af
+	ld [rSVBK], a
+
+	farcall ClearSpriteAnims
+	depixel 10, 11, 4, 0
+	ld a, SPRITE_ANIM_INDEX_GAMEFREAK_LOGO
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], $a0
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $60
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld [hl], $30
+	xor a
+	ld [wJumptableIndex], a
+	ld [wIntroSceneFrameCounter], a
+	ld [wIntroSceneTimer], a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld a, $1
+	ld [hBGMapMode], a
+	ld a, $90
+	ld [hWY], a
+	lb de, %11100100, %11100100
+	call DmgToCgbObjPals
+	ret
+; e465e
+
+.StopGamefreakAnim: ; e465e
+	farcall ClearSpriteAnims
+	call ClearTileMap
+	call ClearSprites
+	ld c, 16
+	call DelayFrames
+	ret
+; e4670
+
+PlaceGameFreakPresents: ; e4670
+	ld a, [wJumptableIndex]
+	ld e, a
+	ld d, 0
+	ld hl, .dw
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+; e467f
+
+.dw ; e467f
+	dw PlaceGameFreakPresents_0
+	dw PlaceGameFreakPresents_1
+	dw PlaceGameFreakPresents_2
+	dw PlaceGameFreakPresents_3
+; e4687
+
+PlaceGameFreakPresents_AdvanceIndex: ; e4687
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+; e468c
+
+PlaceGameFreakPresents_0: ; e468c
+	ret
+; e468d
+
+PlaceGameFreakPresents_1: ; e468d
+	ld hl, wIntroSceneTimer
+	ld a, [hl]
+	cp $20
+	jr nc, .PlaceGameFreak
+	inc [hl]
+	ret
+
+.PlaceGameFreak:
+	ld [hl], 0
+	ld hl, .GAME_FREAK
+	decoord 5, 10
+	ld bc, .end - .GAME_FREAK
+	call CopyBytes
+	call PlaceGameFreakPresents_AdvanceIndex
+	ld de, SFX_GAME_FREAK_PRESENTS
+	call PlaySFX
+	ret
+; e46af
+
+.GAME_FREAK:
+	;  G  A  M  E   _  F  R  E  A  K
+	db 0, 1, 2, 3, 13, 4, 5, 3, 1, 6
+.end
+	db "@"
+; e46ba
+
+PlaceGameFreakPresents_2: ; e46ba
+	ld hl, wIntroSceneTimer
+	ld a, [hl]
+	cp $40
+	jr nc, .place_presents
+	inc [hl]
+	ret
+
+.place_presents
+	ld [hl], 0
+	ld hl, .presents
+	decoord 7, 11
+	ld bc, .end - .presents
+	call CopyBytes
+	call PlaceGameFreakPresents_AdvanceIndex
+	ret
+; e46d6
+
+.presents
+	db 7, 8, 9, 10, 11, 12
+.end
+	db "@"
+; e46dd
+
+PlaceGameFreakPresents_3: ; e46dd
+	ld hl, wIntroSceneTimer
+	ld a, [hl]
+	cp $80
+	jr nc, .finish
+	inc [hl]
+	ret
+
+.finish
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+; e46ed
+
+
+GameFreakLogoJumper: ; e46ed (39:46ed)
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	ld e, [hl]
+	ld d, 0
+	ld hl, GameFreakLogoScenes
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+GameFreakLogoScenes: ; e46fd (39:46fd)
+	dw GameFreakLogoScene1
+	dw GameFreakLogoScene2
+	dw GameFreakLogoScene3
+	dw GameFreakLogoScene4
+	dw GameFreakLogoScene5
+
+GameFreakLogoScene1: ; e4707 (39:4707)
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	inc [hl]
+	ret
+
+GameFreakLogoScene2: ; e470d (39:470d)
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .asm_e4747
+	ld d, a
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld a, [hl]
+	and %111111
+	cp %100000
+	jr nc, .asm_e4723
+	add %100000
+.asm_e4723
+	ld e, a
+	farcall BattleAnim_Sine_e
+	ld hl, SPRITEANIMSTRUCT_YOFFSET
+	add hl, bc
+	ld [hl], e
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld a, [hl]
+	dec [hl]
+	and $1f
+	ret nz
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld a, [hl]
+	sub $30
+	ld [hl], a
+	ld de, SFX_DITTO_BOUNCE
+	call PlaySFX
+	ret
+
+.asm_e4747
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	inc [hl]
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld [hl], $0
+	ld de, SFX_DITTO_POP_UP
+	call PlaySFX
+	ret
+
+GameFreakLogoScene3: ; e4759 (39:4759)
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld a, [hl]
+	cp $20
+	jr nc, .asm_e4764
+	inc [hl]
+	ret
+
+.asm_e4764
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	inc [hl]
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld [hl], $0
+	ld de, SFX_DITTO_TRANSFORM
+	call PlaySFX
+	ret
+
+GameFreakLogoScene4: ; e4776 (39:4776)
+	ld hl, SPRITEANIMSTRUCT_0D
+	add hl, bc
+	ld a, [hl]
+	cp $40
+	jr z, .asm_e47a3
+	inc [hl]
+	srl a
+	srl a
+	ld e, a
+	ld d, $0
+	ld hl, GameFreakLogoPalettes
+	add hl, de
+	add hl, de
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wOBPals2)
+	ld [rSVBK], a
+	ld a, [hli]
+	ld [wOBPals2 + 12], a
+	ld a, [hli]
+	ld [wOBPals2 + 13], a
+	pop af
+	ld [rSVBK], a
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+
+.asm_e47a3
+	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+	add hl, bc
+	inc [hl]
+	call PlaceGameFreakPresents_AdvanceIndex
+GameFreakLogoScene5: ; e47ab (39:47ab)
+	ret
+; e47ac (39:47ac)
+
+GameFreakLogoPalettes: ; e47ac
+INCLUDE "gfx/intro/gamefreak_logo.pal"
+; e47cc
+
+GameFreakLogo: ; e47cc
+INCBIN "gfx/splash/logo1.1bpp"
+INCBIN "gfx/splash/logo2.1bpp"
+; e48ac
+
+CrystalIntro: ; e48ac
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wGBCPalettes)
+	ld [rSVBK], a
+	ld a, [hInMenu]
+	push af
+	ld a, [hVBlank]
+	push af
+	call .InitRAMAddrs
+.loop ; e48bc
+	call JoyTextDelay
+	ld a, [hJoyLast]
+	and BUTTONS
+	jr nz, .ShutOffMusic
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .done
+	call IntroSceneJumper
+	farcall PlaySpriteAnimations
+	call DelayFrame
+	jp .loop
+
+.ShutOffMusic:
+	ld de, MUSIC_NONE
+	call PlayMusic
+
+.done
+	call ClearBGPalettes
+	call ClearSprites
+	call ClearTileMap
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	pop af
+	ld [hVBlank], a
+	pop af
+	ld [hInMenu], a
+	pop af
+	ld [rSVBK], a
+	ret
+; e4901
+
+.InitRAMAddrs: ; e4901
+	xor a
+	ld [hVBlank], a
+	ld a, $1
+	ld [hInMenu], a
+	xor a
+	ld [hMapAnims], a
+	ld [wJumptableIndex], a
+	ret
+; e490f
+
+IntroSceneJumper: ; e490f
+	ld a, [wJumptableIndex]
+	ld e, a
+	ld d, 0
+	ld hl, IntroScenes
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+; e491e
+
+IntroScenes: ; e491e (39:491e)
+	dw IntroScene1
+	dw IntroScene2
+	dw IntroScene3
+	dw IntroScene4
+	dw IntroScene5
+	dw IntroScene6
+	dw IntroScene7
+	dw IntroScene8
+	dw IntroScene9
+	dw IntroScene10
+	dw IntroScene11
+	dw IntroScene12
+	dw IntroScene13
+	dw IntroScene14
+	dw IntroScene15
+	dw IntroScene16
+	dw IntroScene17
+	dw IntroScene18
+	dw IntroScene19
+	dw IntroScene20
+	dw IntroScene21
+	dw IntroScene22
+	dw IntroScene23
+	dw IntroScene24
+	dw IntroScene25
+	dw IntroScene26
+	dw IntroScene27
+	dw IntroScene28
+
+NextIntroScene: ; e4956 (39:4956)
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+IntroScene1: ; e495b (39:495b)
+; Setup the next scene.
+	call Intro_ClearBGPals
+	call ClearSprites
+	call ClearTileMap
+	xor a
+	ld [hBGMapMode], a
+	ld a, $1
+	ld [rVBK], a
+	ld hl, IntroTilemap001
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, $0
+	ld [rVBK], a
+	ld hl, IntroUnownsGFX
+	ld de, vTiles2 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+	ld hl, IntroPulseGFX
+	ld de, vTiles0 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+	ld hl, IntroTilemap002
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld hl, IntroPalette2
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	call CopyBytes
+	ld hl, IntroPalette2
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+	pop af
+	ld [rSVBK], a
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	farcall ClearSpriteAnims
+	call Intro_SetCGBPalUpdate
+	xor a
+	ld [wIntroSceneFrameCounter], a
+	ld [wIntroSceneTimer], a
+	call NextIntroScene
+	ret
+
+IntroScene2: ; e49d6 (39:49d6)
+; First Unown (A) fades in, pulses, then fades out.
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp $80
+	jr nc, .endscene
+	cp $60
+	jr nz, .DontPlaySound
+	push af
+	depixel 11, 11
+	call CrystalIntro_InitUnownAnim
+	ld de, SFX_INTRO_UNOWN_1
+	call PlaySFX
+	pop af
+.DontPlaySound:
+	ld [wIntroSceneTimer], a
+	xor a
+	call CrystalIntro_UnownFade
+	ret
+.endscene
+	call NextIntroScene
+	ret
+
+IntroScene3: ; e49fd (39:49fd)
+; More setup. Transition to the outdoor scene.
+	call Intro_ClearBGPals
+	call ClearSprites
+	call ClearTileMap
+	xor a
+	ld [hBGMapMode], a
+	ld a, $1
+	ld [rVBK], a
+	ld hl, IntroTilemap003
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, $0
+	ld [rVBK], a
+	ld hl, IntroBackgroundGFX
+	ld de, vTiles2 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+	ld hl, IntroTilemap004
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld hl, IntroPalette1
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	call CopyBytes
+	ld hl, IntroPalette1
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+	pop af
+	ld [rSVBK], a
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	call Intro_ResetLYOverrides
+	call Intro_SetCGBPalUpdate
+	xor a
+	ld [wIntroSceneFrameCounter], a
+	call NextIntroScene
+	ret
+
+IntroScene4: ; e4a69 (39:4a69)
+; Scroll the outdoor panorama for a bit.
+	call Intro_PerspectiveScrollBG
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	cp $80
+	jr z, .endscene
+	inc [hl]
+	ret
+
+.endscene
+	call NextIntroScene
+	ret
+
+IntroScene5: ; e4a7a (39:4a7a)
+; Go back to the Unown.
+	call Intro_ClearBGPals
+	call ClearSprites
+	call ClearTileMap
+	xor a
+	ld [hBGMapMode], a
+	ld [hLCDCPointer], a
+	ld a, $1
+	ld [rVBK], a
+	ld hl, IntroTilemap005
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, $0
+	ld [rVBK], a
+	ld hl, IntroUnownsGFX
+	ld de, vTiles2 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+	ld hl, IntroPulseGFX
+	ld de, vTiles0 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+	ld hl, IntroTilemap006
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld hl, IntroPalette2
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	call CopyBytes
+	ld hl, IntroPalette2
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+	pop af
+	ld [rSVBK], a
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	farcall ClearSpriteAnims
+	call Intro_SetCGBPalUpdate
+	xor a
+	ld [wIntroSceneFrameCounter], a
+	ld [wIntroSceneTimer], a
+	call NextIntroScene
+	ret
+
+IntroScene6: ; e4af7 (39:4af7)
+; Two more Unown (I, H) fade in.
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp $80
+	jr nc, .endscene
+	cp $60
+	jr z, .SecondUnown
+	cp $40
+	jr nc, .StopUnown
+	cp $20
+	jr z, .FirstUnown
+	jr .NoUnown
+
+.FirstUnown:
+	push af
+	depixel 7, 15
+	call CrystalIntro_InitUnownAnim
+	ld de, SFX_INTRO_UNOWN_2
+	call PlaySFX
+	pop af
+.NoUnown:
+	ld [wIntroSceneTimer], a
+	xor a
+	call CrystalIntro_UnownFade
+	ret
+
+.SecondUnown:
+	push af
+	depixel 14, 6
+	call CrystalIntro_InitUnownAnim
+	ld de, SFX_INTRO_UNOWN_1
+	call PlaySFX
+	pop af
+.StopUnown:
+	ld [wIntroSceneTimer], a
+	ld a, $1
+	call CrystalIntro_UnownFade
+	ret
+
+.endscene
+	call NextIntroScene
+	ret
+
+IntroScene7: ; e4b3f (39:4b3f)
+; Back to the outdoor scene.
+	call Intro_ClearBGPals
+	call ClearSprites
+	call ClearTileMap
+	xor a
+	ld [hBGMapMode], a
+
+	ld a, $1
+	ld [rVBK], a
+	ld hl, IntroTilemap003
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+
+	ld hl, IntroPichuWooperGFX
+	ld de, vTiles0 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+
+	ld a, $0
+	ld [rVBK], a
+	ld hl, IntroSuicuneRunGFX
+	ld de, vTiles0 tile $00
+	call Intro_DecompressRequest2bpp_255Tiles
+
+	ld hl, IntroBackgroundGFX
+	ld de, vTiles2 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+
+	ld hl, IntroTilemap004
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+
+	ld hl, IntroPalette1
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	call CopyBytes
+
+	ld hl, IntroPalette1
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+
+	pop af
+	ld [rSVBK], a
+
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	call Intro_ResetLYOverrides
+	farcall ClearSpriteAnims
+	depixel 13, 27, 4, 0
+	ld a, SPRITE_ANIM_INDEX_INTRO_SUICUNE
+	call _InitSpriteAnimStruct
+	ld a, $f0
+	ld [wGlobalAnimXOffset], a
+	call Intro_SetCGBPalUpdate
+	xor a
+	ld [wIntroSceneFrameCounter], a
+	ld [wIntroSceneTimer], a
+	call NextIntroScene
+	ret
+
+IntroScene8: ; e4bd3 (39:4bd3)
+; Scroll the scene, then show Suicune running across the screen.
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp $40
+	jr z, .suicune_sound
+	jr nc, .animate_suicune
+	call Intro_PerspectiveScrollBG
+	ret
+
+.suicune_sound
+	ld de, SFX_INTRO_SUICUNE_3
+	call PlaySFX
+.animate_suicune
+	ld a, [wGlobalAnimXOffset]
+	and a
+	jr z, .finish
+	sub $8
+	ld [wGlobalAnimXOffset], a
+	ret
+
+.finish
+	ld de, SFX_INTRO_SUICUNE_2
+	call PlaySFX
+	farcall DeinitializeAllSprites
+	call NextIntroScene
+	ret
+
+IntroScene9: ; e4c04 (39:4c04)
+; Set up the next scene (same bg).
+	xor a
+	ld [hLCDCPointer], a
+	call ClearSprites
+	hlcoord 0, 0, wAttrMap
+	; first 12 rows have palette 1
+	ld bc, 12 * SCREEN_WIDTH
+	ld a, $1
+	call ByteFill
+	; middle 3 rows have palette 2
+	ld bc, 3 * SCREEN_WIDTH
+	ld a, $2
+	call ByteFill
+	; last three rows have palette 3
+	ld bc, 3 * SCREEN_WIDTH
+	ld a, $3
+	call ByteFill
+	ld a, $2
+	ld [hBGMapMode], a
+	call DelayFrame
+	call DelayFrame
+	call DelayFrame
+	ld a, $c ; $980c
+	ld [hBGMapAddress], a
+	call DelayFrame
+	call DelayFrame
+	call DelayFrame
+	xor a
+	ld [hBGMapMode], a
+	ld [hBGMapAddress], a
+	ld [wGlobalAnimXOffset], a
+	xor a
+	ld [wIntroSceneFrameCounter], a
+	call NextIntroScene
+	ret
+
+IntroScene10: ; e4c4f (39:4c4f)
+; Wooper and Pichu enter.
+	call Intro_RustleGrass
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp $c0
+	jr z, .done
+	cp $20
+	jr z, .wooper
+	cp $40
+	jr z, .pichu
+	ret
+
+.pichu
+	depixel 21, 16, 1, 0
+	ld a, SPRITE_ANIM_INDEX_INTRO_PICHU
+	call _InitSpriteAnimStruct
+	ld de, SFX_INTRO_PICHU
+	call PlaySFX
+	ret
+
+.wooper
+	depixel 22, 6
+	ld a, SPRITE_ANIM_INDEX_INTRO_WOOPER
+	call _InitSpriteAnimStruct
+	ld de, SFX_INTRO_PICHU
+	call PlaySFX
+	ret
+.done
+	call NextIntroScene
+	ret
+
+IntroScene11: ; e4c86 (39:4c86)
+; Back to Unown again.
+	call Intro_ClearBGPals
+	call ClearSprites
+	call ClearTileMap
+	xor a
+	ld [hBGMapMode], a
+	ld [hLCDCPointer], a
+	ld a, $1
+	ld [rVBK], a
+	ld hl, IntroTilemap007
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, $0
+	ld [rVBK], a
+	ld hl, IntroUnownsGFX
+	ld de, vTiles2 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+	ld hl, IntroTilemap008
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld hl, IntroPalette2
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	call CopyBytes
+	ld hl, IntroPalette2
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+	pop af
+	ld [rSVBK], a
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	farcall ClearSpriteAnims
+	call Intro_SetCGBPalUpdate
+	xor a
+	ld [wIntroSceneFrameCounter], a
+	ld [wIntroSceneTimer], a
+	call NextIntroScene
+	ret
+
+IntroScene12: ; e4cfa (39:4cfa)
+; Even more Unown.
+	call .PlayUnownSound
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp $c0
+	jr nc, .done
+	cp $80
+	jr nc, .second_half
+; first half
+	ld c, a
+	and $1f
+	sla a
+	ld [wIntroSceneTimer], a
+	ld a, c
+	and $e0
+	srl a
+	swap a
+	call CrystalIntro_UnownFade
+	ret
+
+.second_half
+; double speed
+	ld c, a
+	and $f
+	sla a
+	sla a
+	ld [wIntroSceneTimer], a
+	ld a, c
+	and $70
+	or $40
+	swap a
+	call CrystalIntro_UnownFade
+	ret
+
+.done
+	call NextIntroScene
+	ret
+
+.PlayUnownSound: ; e4d36 (39:4d36)
+	ld a, [wIntroSceneFrameCounter]
+	ld c, a
+	ld hl, .UnownSounds
+.loop
+	ld a, [hli]
+	cp -1
+	ret z
+	cp c
+	jr z, .playsound
+	inc hl
+	inc hl
+	jr .loop
+.playsound
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+	push de
+	call SFXChannelsOff
+	pop de
+	call PlaySFX
+	ret
+; e4d54 (39:4d54)
+
+.UnownSounds: ; e4d54
+	dbw $00, SFX_INTRO_UNOWN_3
+	dbw $20, SFX_INTRO_UNOWN_2
+	dbw $40, SFX_INTRO_UNOWN_1
+	dbw $60, SFX_INTRO_UNOWN_2
+	dbw $80, SFX_INTRO_UNOWN_3
+	dbw $90, SFX_INTRO_UNOWN_2
+	dbw $a0, SFX_INTRO_UNOWN_1
+	dbw $b0, SFX_INTRO_UNOWN_2
+	db -1 ; e4d6d
+
+IntroScene13: ; e4d6d (39:4d6d)
+; Switch scenes again.
+	call Intro_ClearBGPals
+	call ClearSprites
+	call ClearTileMap
+	xor a
+	ld [hBGMapMode], a
+	ld a, $1
+	ld [rVBK], a
+	ld hl, IntroTilemap003
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, $0
+	ld [rVBK], a
+	ld hl, IntroSuicuneRunGFX
+	ld de, vTiles0 tile $00
+	call Intro_DecompressRequest2bpp_255Tiles
+	ld hl, IntroBackgroundGFX
+	ld de, vTiles2 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+	ld hl, IntroTilemap004
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld hl, IntroPalette1
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	call CopyBytes
+	ld hl, IntroPalette1
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+	pop af
+	ld [rSVBK], a
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	farcall ClearSpriteAnims
+	depixel 13, 11, 4, 0
+	ld a, SPRITE_ANIM_INDEX_INTRO_SUICUNE
+	call _InitSpriteAnimStruct
+	ld de, MUSIC_CRYSTAL_OPENING
+	call PlayMusic
+	xor a
+	ld [wGlobalAnimXOffset], a
+	call Intro_SetCGBPalUpdate
+	xor a
+	ld [wIntroSceneFrameCounter], a
+	ld [wIntroSceneTimer], a
+	call NextIntroScene
+	ret
+
+IntroScene14: ; e4dfa (39:4dfa)
+; Suicune runs then jumps.
+	ld a, [hSCX]
+	sub 10
+	ld [hSCX], a
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp $80
+	jr z, .done
+	cp $60
+	jr z, .jump
+	jr nc, .asm_e4e1a
+	cp $40
+	jr nc, .asm_e4e33
+	ret
+
+.jump
+	ld de, SFX_INTRO_SUICUNE_4
+	call PlaySFX
+
+.asm_e4e1a
+	ld a, $1
+	ld [wIntroSceneTimer], a
+	ld a, [wGlobalAnimXOffset]
+	cp $88
+	jr c, .asm_e4e2c
+	sub $8
+	ld [wGlobalAnimXOffset], a
+	ret
+
+.asm_e4e2c
+	farcall DeinitializeAllSprites
+	ret
+
+.asm_e4e33
+	ld a, [wGlobalAnimXOffset]
+	sub $2
+	ld [wGlobalAnimXOffset], a
+	ret
+
+.done
+	call NextIntroScene
+	ret
+
+IntroScene15: ; e4e40 (39:4e40)
+; Transition to a new scene.
+	call Intro_ClearBGPals
+	call ClearSprites
+	call ClearTileMap
+	xor a
+	ld [hBGMapMode], a
+	ld a, $1
+	ld [rVBK], a
+	ld hl, IntroTilemap009
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, $0
+	ld [rVBK], a
+	ld hl, IntroSuicuneJumpGFX
+	ld de, vTiles2 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+	ld hl, IntroUnownBackGFX
+	ld de, vTiles0 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+	ld de, IntroGrass4GFX
+	ld hl, vTiles1 tile $00
+	lb bc, BANK(IntroGrass4GFX), 1
+	call Request2bpp
+	ld hl, IntroTilemap010
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	call Intro_LoadTilemap
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld hl, IntroPalette5
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	call CopyBytes
+	ld hl, IntroPalette5
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+	pop af
+	ld [rSVBK], a
+	xor a
+	ld [hSCX], a
+	ld a, $90
+	ld [hSCY], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	farcall ClearSpriteAnims
+	call Intro_SetCGBPalUpdate
+	depixel 8, 5
+	ld a, SPRITE_ANIM_INDEX_INTRO_UNOWN_F
+	call _InitSpriteAnimStruct
+	depixel 12, 0
+	ld a, SPRITE_ANIM_INDEX_INTRO_SUICUNE_AWAY
+	call _InitSpriteAnimStruct
+	xor a
+	ld [wIntroSceneFrameCounter], a
+	ld [wIntroSceneTimer], a
+	call NextIntroScene
+	ret
+
+IntroScene16: ; e4edc (39:4edc)
+; Suicune shows its face. An Unown appears in front.
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp $80
+	jr nc, .done
+	call Intro_Scene16_AnimateSuicune
+	ld a, [hSCY]
+	and a
+	ret z
+	add 8
+	ld [hSCY], a
+	ret
+.done
+	call NextIntroScene
+	ret
+
+IntroScene17: ; e4ef5 (39:4ef5)
+; ...
+	call Intro_ClearBGPals
+	call ClearSprites
+	call ClearTileMap
+	xor a
+	ld [hBGMapMode], a
+	ld a, $1
+	ld [rVBK], a
+	ld hl, IntroTilemap011
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, $0
+	ld [rVBK], a
+	ld hl, IntroSuicuneCloseGFX
+	ld de, vTiles1 tile $00
+	call Intro_DecompressRequest2bpp_255Tiles
+	ld hl, IntroTilemap012
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld hl, IntroPalette4
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	call CopyBytes
+	ld hl, IntroPalette4
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+	pop af
+	ld [rSVBK], a
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	farcall ClearSpriteAnims
+	call Intro_SetCGBPalUpdate
+	xor a
+	ld [wIntroSceneFrameCounter], a
+	ld [wIntroSceneTimer], a
+	call NextIntroScene
+	ret
+
+IntroScene18: ; e4f67 (39:4f67)
+; Suicune close up.
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp $60
+	jr nc, .done
+	ld a, [hSCX]
+	cp $60
+	ret z
+	add 8
+	ld [hSCX], a
+	ret
+.done
+	call NextIntroScene
+	ret
+
+IntroScene19: ; e4f7e (39:4f7e)
+; More setup.
+	call Intro_ClearBGPals
+	call ClearSprites
+	call ClearTileMap
+	xor a
+	ld [hBGMapMode], a
+	ld a, $1
+	ld [rVBK], a
+	ld hl, IntroTilemap013
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, $0
+	ld [rVBK], a
+	ld hl, IntroSuicuneBackGFX
+	ld de, vTiles2 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+	ld hl, IntroUnownsGFX
+	ld de, vTiles1 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+	ld de, IntroGrass4GFX
+	ld hl, vTiles1 tile $7f
+	lb bc, BANK(IntroGrass4GFX), 1
+	call Request2bpp
+	ld hl, IntroTilemap014
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	call Intro_LoadTilemap
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld hl, IntroPalette5
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	call CopyBytes
+	ld hl, IntroPalette5
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+	pop af
+	ld [rSVBK], a
+	xor a
+	ld [hSCX], a
+	ld a, $d8
+	ld [hSCY], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	farcall ClearSpriteAnims
+	ld hl, wSpriteAnimDict
+	xor a
+	ld [hli], a
+	ld [hl], $7f
+	call Intro_SetCGBPalUpdate
+	depixel 12, 0
+	ld a, SPRITE_ANIM_INDEX_INTRO_SUICUNE_AWAY
+	call _InitSpriteAnimStruct
+	xor a
+	ld [wIntroSceneFrameCounter], a
+	ld [wIntroSceneTimer], a
+	call NextIntroScene
+	ret
+
+IntroScene20: ; e5019 (39:5019)
+; Suicune running away. A bunch of Unown appear.
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp $98
+	jr nc, .finished
+	cp $58
+	ret nc
+	cp $40
+	jr nc, .AppearUnown
+	cp $28
+	ret nc
+	ld a, [hSCY]
+	inc a
+	ld [hSCY], a
+	ret
+
+.AppearUnown:
+	sub $18
+	ld c, a
+	and $3
+	cp $3
+	ret nz
+	ld a, c
+	and $1c
+	srl a
+	srl a
+	ld [wIntroSceneTimer], a
+	xor a
+	call Intro_Scene20_AppearUnown
+	ret
+; e5049 (39:5049)
+; unused
+	ld a, c
+	and $1c
+	srl a
+	srl a
+	ld [wIntroSceneTimer], a
+	ld a, 1
+	call Intro_Scene20_AppearUnown
+	ret
+
+.finished
+	call NextIntroScene
+	ret
+
+IntroScene21: ; e505d (39:505d)
+; Suicune gets more distant and turns black.
+	call Intro_ColoredSuicuneFrameSwap
+	ld c, 3
+	call DelayFrames
+	xor a
+	ld [hBGMapMode], a
+	ld [wIntroSceneFrameCounter], a
+	ld [wIntroSceneTimer], a
+	call NextIntroScene
+	ret
+
+IntroScene22: ; e5072 (39:5072)
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp $8
+	jr nc, .done
+	ret
+.done
+	farcall DeinitializeAllSprites
+	call NextIntroScene
+	ret
+
+IntroScene23: ; e5086 (39:5086)
+	xor a
+	ld [wIntroSceneFrameCounter], a
+	call NextIntroScene
+	ret
+
+IntroScene24: ; e508e (39:508e)
+; Fade to white.
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp $20
+	jr nc, .done
+
+	ld c, a
+	and $3
+	ret nz
+
+	ld a, c
+	and $1c
+	sla a
+	call Intro_Scene24_ApplyPaletteFade
+	ret
+
+.done
+	ld a, $40
+	ld [wIntroSceneFrameCounter], a
+	call NextIntroScene
+	ret
+
+IntroScene25: ; e50ad (39:50ad)
+; Wait around a bit.
+	ld a, [wIntroSceneFrameCounter]
+	dec a
+	jr z, .done
+	ld [wIntroSceneFrameCounter], a
+	ret
+
+.done
+	call NextIntroScene
+	ret
+
+IntroScene26: ; e50bb (39:50bb)
+; Load the final scene.
+	call ClearBGPalettes
+	call ClearSprites
+	call ClearTileMap
+	xor a
+	ld [hBGMapMode], a
+	ld a, $1
+	ld [rVBK], a
+	ld hl, IntroTilemap015
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, $0
+	ld [rVBK], a
+	ld hl, IntroCrystalUnownsGFX
+	ld de, vTiles2 tile $00
+	call Intro_DecompressRequest2bpp_128Tiles
+	ld hl, IntroTilemap017
+	debgcoord 0, 0
+	call Intro_DecompressRequest2bpp_64Tiles
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld hl, IntroPalette3
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	call CopyBytes
+	ld hl, IntroPalette3
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+	pop af
+	ld [rSVBK], a
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	ld a, $7
+	ld [hWX], a
+	ld a, $90
+	ld [hWY], a
+	farcall ClearSpriteAnims
+	call Intro_SetCGBPalUpdate
+	xor a
+	ld [wIntroSceneFrameCounter], a
+	ld [wIntroSceneTimer], a
+	call NextIntroScene
+	ret
+
+IntroScene27: ; e512d (39:512d)
+; Spell out C R Y S T A L with Unown.
+	ld hl, wIntroSceneTimer
+	inc [hl]
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	inc [hl]
+	cp $80
+	jr nc, .done
+
+	ld c, a
+	and $f
+	ld [wIntroSceneTimer], a
+	ld a, c
+	and $70
+	swap a
+	call Intro_FadeUnownWordPals
+	ret
+
+.done
+	call NextIntroScene
+	ld a, $80
+	ld [wIntroSceneFrameCounter], a
+	ret
+
+IntroScene28: ; e5152 (39:5152)
+; Cut out when the music ends, and lead into the title screen.
+	ld hl, wIntroSceneFrameCounter
+	ld a, [hl]
+	and a
+	jr z, .done
+	dec [hl]
+	cp $18
+	jr z, .clear
+	cp $8
+	ret nz
+
+	ld de, SFX_UNKNOWN_CB
+	call PlaySFX
+	ret
+
+.clear
+	call ClearBGPalettes
+	ret
+
+.done
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+Intro_Scene24_ApplyPaletteFade: ; e5172 (39:5172)
+; load the (a)th palette from .FadePals to all wBGPals2
+	ld hl, .FadePals
+	add l
+	ld l, a
+	ld a, $0
+	adc h
+	ld h, a
+
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ld [rSVBK], a
+	ld de, wBGPals2
+	ld b, 8 ; number of BG pals
+.loop1
+	push hl
+	ld c, 1 palettes
+.loop2
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec c
+	jr nz, .loop2
+	pop hl
+	dec b
+	jr nz, .loop1
+	pop af
+	ld [rSVBK], a
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; e519c (39:519c)
+
+.FadePals: ; e519c
+INCLUDE "gfx/intro/fade.pal"
+; e51dc
+
+CrystalIntro_InitUnownAnim: ; e51dc (39:51dc)
+	push de
+	ld a, SPRITE_ANIM_INDEX_INTRO_UNOWN
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $8
+	ld a, SPRITE_ANIM_FRAMESET_INTRO_UNOWN_4
+	call ReinitSpriteAnimFrame
+	pop de
+
+	push de
+	ld a, SPRITE_ANIM_INDEX_INTRO_UNOWN
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $18
+	ld a, SPRITE_ANIM_FRAMESET_INTRO_UNOWN_3
+	call ReinitSpriteAnimFrame
+	pop de
+
+	push de
+	ld a, SPRITE_ANIM_INDEX_INTRO_UNOWN
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $28
+	ld a, SPRITE_ANIM_FRAMESET_INTRO_UNOWN_1
+	call ReinitSpriteAnimFrame
+	pop de
+
+	ld a, SPRITE_ANIM_INDEX_INTRO_UNOWN
+	call _InitSpriteAnimStruct
+	ld hl, SPRITEANIMSTRUCT_0C
+	add hl, bc
+	ld [hl], $38
+	ld a, SPRITE_ANIM_FRAMESET_INTRO_UNOWN_2
+	call ReinitSpriteAnimFrame
+	ret
+
+CrystalIntro_UnownFade: ; e5223 (39:5223)
+	add a
+	add a
+	add a
+	ld e, a
+	ld d, $0
+	ld hl, wBGPals2
+	add hl, de
+	inc hl
+	inc hl
+	ld a, [wIntroSceneTimer]
+	and %111111
+	cp %011111
+	jr z, .okay
+	jr c, .okay
+	ld c, a
+	ld a, %111111
+	sub c
+.okay
+
+	ld c, a
+	ld b, $0
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ld [rSVBK], a
+
+	push hl
+	push bc
+	ld hl, wBGPals2
+	ld bc, 8 palettes
+	xor a
+	call ByteFill
+	pop bc
+	pop hl
+
+	push hl
+	ld hl, .BWFade
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+	pop hl
+	ld a, e
+	ld [hli], a
+	ld a, d
+	ld [hli], a
+
+	push hl
+	ld hl, .BlackLBlueFade
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+	pop hl
+	ld a, e
+	ld [hli], a
+	ld a, d
+	ld [hli], a
+
+	push hl
+	ld hl, .BlackBlueFade
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+	pop hl
+	ld a, e
+	ld [hli], a
+	ld a, d
+	ld [hli], a
+
+	pop af
+	ld [rSVBK], a
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; e5288 (39:5288)
+
+.BWFade: ; e5288
+; Fade between black and white.
+hue = 0
+rept 32
+	RGB hue, hue, hue
+hue = hue + 1
+endr
+; e52c8
+
+.BlackLBlueFade: ; e52c8
+; Fade between black and light blue.
+hue = 0
+rept 32
+	RGB 0, hue / 2, hue
+hue = hue + 1
+endr
+; e5308
+
+.BlackBlueFade: ; e5308
+; Fade between black and blue.
+hue = 0
+rept 32
+	RGB 0, 0, hue
+hue = hue + 1
+endr
+; e5348
+
+Intro_Scene20_AppearUnown: ; e5348 (39:5348)
+; Spawn the palette for the nth Unown
+	and a
+	jr nz, .load_pal_2
+
+	ld hl, .pal1
+	jr .got_pointer
+
+.load_pal_2
+	ld hl, .pal2
+
+.got_pointer
+	ld a, [wIntroSceneTimer]
+	and $7
+	add a
+	add a
+	add a
+	ld c, a
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ld [rSVBK], a
+
+	push bc
+	ld de, wBGPals2
+
+	ld a, c
+	add e
+	ld e, a
+	ld a, $0
+	adc d
+	ld d, a
+
+	ld bc, 1 palettes
+	call CopyBytes
+	pop bc
+
+	ld de, wBGPals1
+	ld a, c
+	add e
+	ld e, a
+	ld a, $0
+	adc d
+	ld d, a
+
+	ld bc, 1 palettes
+	call CopyBytes
+
+	pop af
+	ld [rSVBK], a
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; e538d (39:538d)
+
+.pal1 ; e538d
+	RGB 24, 12, 09
+	RGB 31, 31, 31
+	RGB 12, 00, 31
+	RGB 00, 00, 00
+
+; e5395
+
+.pal2 ; e5395
+	RGB 24, 12, 09
+	RGB 31, 31, 31
+	RGB 31, 31, 31
+	RGB 31, 31, 31
+
+; e539d
+
+Intro_FadeUnownWordPals: ; e539d (39:539d)
+	add a
+	add a
+	add a
+	ld e, a
+	ld d, $0
+	ld hl, wBGPals2
+	add hl, de
+rept 4
+	inc hl
+endr
+	ld a, [wIntroSceneTimer]
+	add a
+	ld c, a
+	ld b, $0
+
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ld [rSVBK], a
+
+	push hl
+	ld hl, .FastFadePalettes
+	add hl, bc
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+	pop hl
+	ld a, e
+	ld [hli], a
+	ld a, d
+	ld [hli], a
+
+	push hl
+	ld hl, .SlowFadePalettes
+	add hl, bc
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+	pop hl
+	ld a, e
+	ld [hli], a
+	ld a, d
+	ld [hli], a
+
+	pop af
+	ld [rSVBK], a
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+; e53db (39:53db)
+
+.FastFadePalettes: ; e53db
+hue = 31
+rept 8
+	RGB hue, hue, hue
+hue = hue + -1
+	RGB hue, hue, hue
+hue = hue + -2
+endr
+; e53fb
+
+.SlowFadePalettes: ; e53fb
+hue = 31
+rept 16
+	RGB hue, hue, hue
+hue = hue + -1
+endr
+; e541b
+
+Intro_LoadTilemap: ; e541b (39:541b)
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wDecompressScratch)
+	ld [rSVBK], a
+
+	ld hl, wDecompressScratch
+	decoord 0, 0
+	ld b, SCREEN_HEIGHT
+.row
+	ld c, SCREEN_WIDTH
+.col
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec c
+	jr nz, .col
+	ld a, BG_MAP_WIDTH - SCREEN_WIDTH
+	add l
+	ld l, a
+	ld a, 0
+	adc h
+	ld h, a
+	dec b
+	jr nz, .row
+
+	pop af
+	ld [rSVBK], a
+	ret
+
+Intro_Scene16_AnimateSuicune: ; e5441 (39:5441)
+	ld a, [wIntroSceneFrameCounter]
+	and $3
+	jr z, Intro_ColoredSuicuneFrameSwap
+	cp $3
+	jr z, .PrepareForSuicuneSwap
+	ret
+
+.PrepareForSuicuneSwap:
+	xor a
+	ld [hBGMapMode], a
+	ret
+
+Intro_ColoredSuicuneFrameSwap: ; e5451 (39:5451)
+	hlcoord 0, 0
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+.loop
+	ld a, [hl]
+	and a
+	jr z, .skip
+	cp $80
+	jr nc, .skip
+	xor $8
+	ld [hl], a
+.skip
+	inc hl
+	dec bc
+	ld a, c
+	or b
+	jr nz, .loop
+	ld a, $1
+	ld [hBGMapMode], a
+	ret
+
+Intro_RustleGrass: ; e546d (39:546d)
+	ld a, [wIntroSceneFrameCounter]
+	cp 36
+	ret nc
+	and $c
+	srl a
+	ld e, a
+	ld d, $0
+	ld hl, .RustlingGrassPointers
+	add hl, de
+	ld a, [hli]
+	ld [wRequested2bppSource], a
+	ld a, [hli]
+	ld [wRequested2bppSource + 1], a
+	ld a, LOW(vTiles2 tile $09)
+	ld [wRequested2bppDest], a
+	ld a, HIGH(vTiles2 tile $09)
+	ld [wRequested2bppDest + 1], a
+	ld a, 4
+	ld [wRequested2bppSize], a
+	ret
+; e5496 (39:5496)
+
+.RustlingGrassPointers: ; e5496
+	dw IntroGrass1GFX
+	dw IntroGrass2GFX
+	dw IntroGrass3GFX
+	dw IntroGrass2GFX
+; e549e
+
+Intro_SetCGBPalUpdate: ; e549e (39:549e)
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ret
+
+Intro_ClearBGPals: ; e54a3 (39:54a3)
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ld [rSVBK], a
+
+	ld hl, wBGPals2
+	ld bc, 16 palettes
+	xor a
+	call ByteFill
+
+	pop af
+	ld [rSVBK], a
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	call DelayFrame
+	call DelayFrame
+	ret
+
+Intro_DecompressRequest2bpp_128Tiles: ; e54c2 (39:54c2)
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wDecompressScratch)
+	ld [rSVBK], a
+
+	push de
+	ld de, wDecompressScratch
+	call Decompress
+	pop hl
+
+	ld de, wDecompressScratch
+	lb bc, $01, $80
+	call Request2bpp
+
+	pop af
+	ld [rSVBK], a
+	ret
+
+Intro_DecompressRequest2bpp_255Tiles: ; e54de (39:54de)
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wDecompressScratch)
+	ld [rSVBK], a
+
+	push de
+	ld de, wDecompressScratch
+	call Decompress
+	pop hl
+
+	ld de, wDecompressScratch
+	lb bc, $01, $ff
+	call Request2bpp
+
+	pop af
+	ld [rSVBK], a
+	ret
+
+Intro_DecompressRequest2bpp_64Tiles: ; e54fa (39:54fa)
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wDecompressScratch)
+	ld [rSVBK], a
+
+	push de
+	ld de, wDecompressScratch
+	call Decompress
+	pop hl
+
+	ld de, wDecompressScratch
+	lb bc, $01, $40
+	call Request2bpp
+
+	pop af
+	ld [rSVBK], a
+	ret
+
+Intro_ResetLYOverrides: ; e5516 (39:5516)
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wLYOverrides)
+	ld [rSVBK], a
+
+	ld hl, wLYOverrides
+	ld bc, wLYOverridesEnd - wLYOverrides
+	xor a
+	call ByteFill
+
+	pop af
+	ld [rSVBK], a
+	ld a, rSCX - $ff00
+	ld [hLCDCPointer], a
+	ret
+
+Intro_PerspectiveScrollBG: ; e552f (39:552f)
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wLYOverrides)
+	ld [rSVBK], a
+	; Scroll the grass every frame.
+	; Scroll the trees every other frame and at half speed.
+	; This creates an illusion of perspective.
+	ld a, [wIntroSceneFrameCounter]
+	and $1
+	jr z, .skip
+	; trees in the back
+	ld hl, wLYOverrides
+	ld a, [hl]
+	inc a
+	ld bc, $5f
+	call ByteFill
+.skip
+	; grass in the front
+	ld hl, wLYOverrides + $5f
+	ld a, [hl]
+	inc a
+	inc a
+	ld bc, $31
+	call ByteFill
+	ld a, [wLYOverrides + 0]
+	ld [hSCX], a
+	pop af
+	ld [rSVBK], a
+	ret
+
+IntroSuicuneRunGFX: ; e555d
+INCBIN "gfx/intro/suicune_run.2bpp.lz"
+; e592d
+
+IntroPichuWooperGFX: ; e592d
+INCBIN "gfx/intro/pichu_wooper.2bpp.lz"
+; e5c7d
+
+IntroBackgroundGFX: ; e5c7d
+INCBIN "gfx/intro/background.2bpp.lz"
+; e5e6d
+
+IntroTilemap004: ; e5e6d
+INCBIN "gfx/intro/004.tilemap.lz"
+; e5ecd
+
+IntroTilemap003: ; e5ecd
+INCBIN "gfx/intro/003.tilemap.lz"
+; e5edd
+
+IntroPalette1: ; e5edd
+INCLUDE "gfx/intro/intro_1.pal"
+; e5f5d
+
+IntroUnownsGFX: ; e5f5d
+INCBIN "gfx/intro/unowns.2bpp.lz"
+; e634d
+
+IntroPulseGFX: ; e634d
+INCBIN "gfx/intro/pulse.2bpp.lz"
+; e63dd
+
+IntroTilemap002: ; e63dd
+INCBIN "gfx/intro/002.tilemap.lz"
+; e641d
+
+IntroTilemap001: ; e641d
+INCBIN "gfx/intro/001.tilemap.lz"
+; e642d
+
+IntroTilemap006: ; e642d
+INCBIN "gfx/intro/006.tilemap.lz"
+; e647d
+
+IntroTilemap005: ; e647d
+INCBIN "gfx/intro/005.tilemap.lz"
+; e649d
+
+IntroTilemap008: ; e649d
+INCBIN "gfx/intro/008.tilemap.lz"
+; e655d
+
+IntroTilemap007: ; e655d
+INCBIN "gfx/intro/007.tilemap.lz"
+; e65ad
+
+IntroPalette2: ; e65ad
+INCLUDE "gfx/intro/intro_2.pal"
+; e662d
+
+IntroCrystalUnownsGFX: ; e662d
+INCBIN "gfx/intro/crystal_unowns.2bpp.lz"
+; e672d
+
+IntroTilemap017: ; e672d
+INCBIN "gfx/intro/017.tilemap.lz"
+; e676d
+
+IntroTilemap015: ; e676d
+INCBIN "gfx/intro/015.tilemap.lz"
+; e679d
+
+IntroPalette3: ; e679d
+INCLUDE "gfx/intro/intro_3.pal"
+; e681d
+
+IntroSuicuneCloseGFX: ; e681d
+INCBIN "gfx/intro/suicune_close.2bpp.lz"
+; e6c3d
+
+IntroTilemap012: ; e6c3d
+INCBIN "gfx/intro/012.tilemap.lz"
+; e6d0d
+
+IntroTilemap011: ; e6d0d
+INCBIN "gfx/intro/011.tilemap.lz"
+; e6d6d
+
+IntroPalette4: ; e6d6d
+INCLUDE "gfx/intro/intro_4.pal"
+; e6ded
+
+IntroSuicuneJumpGFX: ; e6ded
+INCBIN "gfx/intro/suicune_jump.2bpp.lz"
+; e72ad
+
+IntroSuicuneBackGFX: ; e72ad
+INCBIN "gfx/intro/suicune_back.2bpp.lz"
+; e764d
+
+IntroTilemap010: ; e764d
+INCBIN "gfx/intro/010.tilemap.lz"
+; e76ad
+
+IntroTilemap009: ; e76ad
+INCBIN "gfx/intro/009.tilemap.lz"
+; e76bd
+
+IntroTilemap014: ; e76bd
+INCBIN "gfx/intro/014.tilemap.lz"
+; e778d
+
+IntroTilemap013: ; e778d
+INCBIN "gfx/intro/013.tilemap.lz"
+; e77dd
+
+IntroPalette5: ; e77dd
+INCLUDE "gfx/intro/intro_5.pal"
+
+IntroUnownBackGFX: ; e785d
+INCBIN "gfx/intro/unown_back.2bpp.lz"
+; e799d
+
+IntroGrass1GFX: ; e799d
+INCBIN "gfx/intro/grass1.2bpp"
+IntroGrass2GFX: ; e79dd
+INCBIN "gfx/intro/grass2.2bpp"
+IntroGrass3GFX: ; e7a1d
+INCBIN "gfx/intro/grass3.2bpp"
+IntroGrass4GFX: ; e7a5d
+INCBIN "gfx/intro/grass4.2bpp"
--- /dev/null
+++ b/engine/title/init_hof_credits.asm
@@ -1,0 +1,79 @@
+InitDisplayForHallOfFame: ; 4e881
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	call DisableLCD
+	call LoadStandardFont
+	call LoadFontsBattleExtra
+	hlbgcoord 0, 0
+	ld bc, vBGMap1 - vBGMap0
+	ld a, " "
+	call ByteFill
+	hlcoord 0, 0, wAttrMap
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	xor a
+	call ByteFill
+	xor a
+	ld [hSCY], a
+	ld [hSCX], a
+	call EnableLCD
+	ld hl, .SavingRecordDontTurnOff
+	call PrintText
+	call WaitBGMap2
+	call SetPalettes
+	ret
+
+.SavingRecordDontTurnOff: ; 0x4e8bd
+	; SAVING RECORD… DON'T TURN OFF!
+	text_jump UnknownText_0x1bd39e
+	db "@"
+
+InitDisplayForRedCredits: ; 4e8c2
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	call DisableLCD
+	call LoadStandardFont
+	call LoadFontsBattleExtra
+	hlbgcoord 0, 0
+	ld bc, vBGMap1 - vBGMap0
+	ld a, " "
+	call ByteFill
+	hlcoord 0, 0, wAttrMap
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	xor a
+	call ByteFill
+	ld hl, wBGPals1
+	ld c, 4 tiles
+.load_white_palettes
+	ld a, LOW(PALRGB_WHITE)
+	ld [hli], a
+	ld a, HIGH(PALRGB_WHITE)
+	ld [hli], a
+	dec c
+	jr nz, .load_white_palettes
+	xor a
+	ld [hSCY], a
+	ld [hSCX], a
+	call EnableLCD
+	call WaitBGMap2
+	call SetPalettes
+	ret
+
+ResetDisplayBetweenHallOfFameMons: ; 4e906
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wDecompressScratch)
+	ld [rSVBK], a
+	ld hl, wDecompressScratch
+	ld bc, wScratchAttrMap - wDecompressScratch
+	ld a, " "
+	call ByteFill
+	hlbgcoord 0, 0
+	ld de, wDecompressScratch
+	ld b, 0
+	ld c, 4 tiles
+	call Request2bpp
+	pop af
+	ld [rSVBK], a
+	ret
--- /dev/null
+++ b/engine/title/title.asm
@@ -1,0 +1,402 @@
+_TitleScreen: ; 10ed67
+
+	call ClearBGPalettes
+	call ClearSprites
+	call ClearTileMap
+
+; Turn BG Map update off
+	xor a
+	ld [hBGMapMode], a
+
+; Reset timing variables
+	ld hl, wJumptableIndex
+	ld [hli], a ; wJumptableIndex
+	ld [hli], a ; wIntroSceneFrameCounter
+	ld [hli], a ; wTitleScreenTimer
+	ld [hl], a  ; wTitleScreenTimer + 1
+
+; Turn LCD off
+	call DisableLCD
+
+
+; VRAM bank 1
+	ld a, 1
+	ld [rVBK], a
+
+
+; Decompress running Suicune gfx
+	ld hl, TitleSuicuneGFX
+	ld de, vTiles1
+	call Decompress
+
+
+; Clear screen palettes
+	hlbgcoord 0, 0
+	ld bc, 20 * BG_MAP_WIDTH
+	xor a
+	call ByteFill
+
+
+; Fill tile palettes:
+
+; BG Map 1:
+
+; line 0 (copyright)
+	hlbgcoord 0, 0, vBGMap1
+	ld bc, BG_MAP_WIDTH
+	ld a, 7 ; palette
+	call ByteFill
+
+
+; BG Map 0:
+
+; Apply logo gradient:
+
+; lines 3-4
+	hlbgcoord 0, 3
+	ld bc, 2 * BG_MAP_WIDTH
+	ld a, 2
+	call ByteFill
+; line 5
+	hlbgcoord 0, 5
+	ld bc, BG_MAP_WIDTH
+	ld a, 3
+	call ByteFill
+; line 6
+	hlbgcoord 0, 6
+	ld bc, BG_MAP_WIDTH
+	ld a, 4
+	call ByteFill
+; line 7
+	hlbgcoord 0, 7
+	ld bc, BG_MAP_WIDTH
+	ld a, 5
+	call ByteFill
+; lines 8-9
+	hlbgcoord 0, 8
+	ld bc, 2 * BG_MAP_WIDTH
+	ld a, 6
+	call ByteFill
+
+
+; 'CRYSTAL VERSION'
+	hlbgcoord 5, 9
+	ld bc, NAME_LENGTH ; length of version text
+	ld a, 1
+	call ByteFill
+
+; Suicune gfx
+	hlbgcoord 0, 12
+	ld bc, 6 * BG_MAP_WIDTH ; the rest of the screen
+	ld a, 0 | VRAM_BANK_1
+	call ByteFill
+
+
+; Back to VRAM bank 0
+	ld a, $0
+	ld [rVBK], a
+
+
+; Decompress logo
+	ld hl, TitleLogoGFX
+	ld de, vTiles1
+	call Decompress
+
+; Decompress background crystal
+	ld hl, TitleCrystalGFX
+	ld de, vTiles0
+	call Decompress
+
+
+; Clear screen tiles
+	hlbgcoord 0, 0
+	ld bc, 64 * BG_MAP_WIDTH
+	ld a, " "
+	call ByteFill
+
+; Draw Pokemon logo
+	hlcoord 0, 3
+	lb bc, 7, 20
+	ld d, $80
+	ld e, $14
+	call DrawTitleGraphic
+
+; Draw copyright text
+	hlbgcoord 3, 0, vBGMap1
+	lb bc, 1, 13
+	ld d, $c
+	ld e, $10
+	call DrawTitleGraphic
+
+; Initialize running Suicune?
+	ld d, $0
+	call LoadSuicuneFrame
+
+; Initialize background crystal
+	call InitializeBackground
+
+; Save WRAM bank
+	ld a, [rSVBK]
+	push af
+; WRAM bank 5
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+
+; Update palette colors
+	ld hl, TitleScreenPalettes
+	ld de, wBGPals1
+	ld bc, 16 palettes
+	call CopyBytes
+
+	ld hl, TitleScreenPalettes
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+
+; Restore WRAM bank
+	pop af
+	ld [rSVBK], a
+
+
+; LY/SCX trickery starts here
+
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wLYOverrides)
+	ld [rSVBK], a
+
+; Make alternating lines come in from opposite sides
+
+; (This part is actually totally pointless, you can't
+;  see anything until these values are overwritten!)
+
+	ld b, 80 / 2 ; alternate for 80 lines
+	ld hl, wLYOverrides
+.loop
+; $00 is the middle position
+	ld [hl], +112 ; coming from the left
+	inc hl
+	ld [hl], -112 ; coming from the right
+	inc hl
+	dec b
+	jr nz, .loop
+
+; Make sure the rest of the buffer is empty
+	ld hl, wLYOverrides + 80
+	xor a
+	ld bc, wLYOverridesEnd - (wLYOverrides + 80)
+	call ByteFill
+
+; Let LCD Stat know we're messing around with SCX
+	ld a, rSCX - $ff00
+	ld [hLCDCPointer], a
+
+	pop af
+	ld [rSVBK], a
+
+
+; Reset audio
+	call ChannelsOff
+	call EnableLCD
+
+; Set sprite size to 8x16
+	ld a, [rLCDC]
+	set rLCDC_SPRITE_SIZE, a
+	ld [rLCDC], a
+
+	ld a, +112
+	ld [hSCX], a
+	ld a, 8
+	ld [hSCY], a
+	ld a, 7
+	ld [hWX], a
+	ld a, -112
+	ld [hWY], a
+
+	ld a, $1
+	ld [hCGBPalUpdate], a
+
+; Update BG Map 0 (bank 0)
+	ld [hBGMapMode], a
+
+	xor a
+	ld [wBGPals1 + 2], a
+
+; Play starting sound effect
+	call SFXChannelsOff
+	ld de, SFX_TITLE_SCREEN_ENTRANCE
+	call PlaySFX
+
+	ret
+; 10eea7
+
+SuicuneFrameIterator: ; 10eea7
+	ld hl, wBGPals1 + 2
+	ld a, [hl]
+	ld c, a
+	inc [hl]
+
+; Only do this once every eight frames
+	and %111
+	ret nz
+
+	ld a, c
+	and %11000
+	sla a
+	swap a
+	ld e, a
+	ld d, $0
+	ld hl, .Frames
+	add hl, de
+	ld d, [hl]
+	xor a
+	ld [hBGMapMode], a
+	call LoadSuicuneFrame
+	ld a, $1
+	ld [hBGMapMode], a
+	ld a, $3
+	ld [hBGMapThird], a
+	ret
+; 10eece
+
+.Frames: ; 10eece
+	db $80 ; vTiles4 tile $00
+	db $88 ; vTiles4 tile $08
+	db $00 ; vTiles5 tile $00
+	db $08 ; vTiles5 tile $08
+; 10eed2
+
+
+LoadSuicuneFrame: ; 10eed2
+	hlcoord 6, 12
+	ld b, 6
+.bgrows
+	ld c, 8
+.col
+	ld a, d
+	ld [hli], a
+	inc d
+	dec c
+	jr nz, .col
+	ld a, SCREEN_WIDTH - 8
+	add l
+	ld l, a
+	ld a, 0
+	adc h
+	ld h, a
+	ld a, 8
+	add d
+	ld d, a
+	dec b
+	jr nz, .bgrows
+	ret
+; 10eeef
+
+DrawTitleGraphic: ; 10eeef
+; input:
+;   hl: draw location
+;   b: height
+;   c: width
+;   d: tile to start drawing from
+;   e: number of tiles to advance for each bgrows
+.bgrows
+	push de
+	push bc
+	push hl
+.col
+	ld a, d
+	ld [hli], a
+	inc d
+	dec c
+	jr nz, .col
+	pop hl
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	pop bc
+	pop de
+	ld a, e
+	add d
+	ld d, a
+	dec b
+	jr nz, .bgrows
+	ret
+; 10ef06
+
+InitializeBackground: ; 10ef06
+	ld hl, wVirtualOAMSprite00
+	ld d, -$22
+	ld e, $0
+	ld c, 5
+.loop
+	push bc
+	call .InitColumn
+	pop bc
+	ld a, $10
+	add d
+	ld d, a
+	dec c
+	jr nz, .loop
+	ret
+; 10ef1c
+
+.InitColumn: ; 10ef1c
+	ld c, $6
+	ld b, $40
+.loop2
+	ld a, d
+	ld [hli], a ; y
+	ld a, b
+	ld [hli], a ; x
+	add $8
+	ld b, a
+	ld a, e
+	ld [hli], a ; tile id
+	inc e
+	inc e
+	ld a, 0 | PRIORITY
+	ld [hli], a ; attributes
+	dec c
+	jr nz, .loop2
+	ret
+; 10ef32
+
+
+AnimateTitleCrystal: ; 10ef32
+; Move the title screen crystal downward until it's fully visible
+
+; Stop at y=6
+; y is really from the bottom of the sprite, which is two tiles high
+	ld hl, wVirtualOAMSprite00YCoord
+	ld a, [hl]
+	cp 6 + 2 * TILE_WIDTH
+	ret z
+
+; Move all 30 parts of the crystal down by 2
+	ld c, 30
+.loop
+	ld a, [hl]
+	add 2
+	ld [hli], a ; y
+rept SPRITEOAMSTRUCT_LENGTH + -1
+	inc hl
+endr
+	dec c
+	jr nz, .loop
+
+	ret
+; 10ef46
+
+TitleSuicuneGFX: ; 10ef46
+INCBIN "gfx/title/suicune.2bpp.lz"
+; 10f326
+
+TitleLogoGFX: ; 10f326
+INCBIN "gfx/title/logo.2bpp.lz"
+; 10fcee
+
+TitleCrystalGFX: ; 10fcee
+INCBIN "gfx/title/crystal.2bpp.lz"
+; 10fede
+
+TitleScreenPalettes:
+INCLUDE "gfx/title/title.pal"
--- /dev/null
+++ b/engine/title/unused_title.asm
@@ -1,0 +1,178 @@
+UnusedTitleScreen: ; 10c000
+
+	call ClearBGPalettes
+	call ClearTileMap
+	call DisableLCD
+
+; Turn BG Map update off
+	xor a
+	ld [hBGMapMode], a
+
+; Reset timing variables
+	ld hl, wJumptableIndex
+	ld [hli], a ; wJumptableIndex
+	ld [hli], a ; wIntroSceneFrameCounter
+	ld [hli], a ; wTitleScreenTimer
+	ld [hl], a  ; wTitleScreenTimer + 1
+
+	ld hl, UnusedTitleBG_GFX
+	ld de, vTiles2
+	ld bc, vBGMap0 - vTiles2
+	call CopyBytes
+
+	ld hl, UnusedTitleBG_GFX + $80 tiles
+	ld de, vTiles1
+	ld bc, vTiles2 - vTiles1
+	call CopyBytes
+
+	ld hl, UnusedTitleFG_GFX
+	ld de, vTiles0
+	ld bc, vTiles1 - vTiles0
+	call CopyBytes
+
+	ld hl, UnusedTitleBG_Tilemap
+	debgcoord 0, 0
+	ld bc, BG_MAP_WIDTH * BG_MAP_HEIGHT
+.copy
+	ld a, 0
+	ld [rVBK], a
+	ld a, [hli]
+	ld [de], a
+	ld a, 1
+	ld [rVBK], a
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec bc
+	ld a, b
+	or c
+	jr nz, .copy
+
+	ld hl, UnusedTitleFG_OAM
+	ld de, wVirtualOAMSprite00
+	ld bc, SPRITEOAMSTRUCT_LENGTH * NUM_SPRITE_OAM_STRUCTS
+	call CopyBytes
+
+	call EnableLCD
+	ld a, [rLCDC]
+	set rLCDC_SPRITES_ENABLE, a
+	set rLCDC_SPRITE_SIZE, a
+	ld [rLCDC], a
+
+	call DelayFrame
+
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+
+	ld hl, UnusedTitleBG_Palettes
+	ld de, wBGPals1
+	ld bc, 8 palettes
+	call CopyBytes
+
+	ld hl, UnusedTitleFG_Palettes
+	ld de, wOBPals1
+	ld bc, 8 palettes
+	call CopyBytes
+
+	ld hl, UnusedTitleBG_Palettes
+	ld de, wBGPals2
+	ld bc, 8 palettes
+	call CopyBytes
+
+	ld hl, UnusedTitleFG_Palettes
+	ld de, wOBPals2
+	ld bc, 8 palettes
+	call CopyBytes
+
+	pop af
+	ld [rSVBK], a
+
+	ld a, $1
+	ld [hCGBPalUpdate], a
+
+	ld de, MUSIC_TITLE
+	call PlayMusic
+
+	ret
+; 10c0b1
+
+UnusedTitleBG_GFX: ; 10c0b1
+INCBIN "gfx/title/old_bg.2bpp"
+; 10d0b1
+
+UnusedTitleBG_Tilemap: ; 10d0b1
+; 32x32 (alternating tiles and attributes)
+INCBIN "gfx/title/old_bg.tilemap"
+; 10d8b1
+
+UnusedTitleBG_Palettes: ; 10d8b1
+INCLUDE "gfx/title/old_bg.pal"
+; 10dab1
+
+UnusedTitleFG_GFX: ; 10dab1
+INCBIN "gfx/title/old_fg.2bpp"
+; 10eab1
+
+UnusedTitleFG_Palettes: ; 10eab1
+INCLUDE "gfx/title/old_fg.pal"
+; 10ecb1
+
+UnusedTitleFG_OAM: ; 10ecb1
+	dsprite  3,  0,  7,  0, $00, 1
+	dsprite  3,  0,  8,  0, $02, 1
+	dsprite  3,  0,  9,  0, $04, 1
+	dsprite  3,  0, 10,  0, $06, 1
+	dsprite  3,  0, 11,  0, $08, 1
+	dsprite  3,  0, 12,  0, $0a, 1
+	dsprite  3,  0, 13,  0, $0c, 1
+	dsprite  3,  0, 14,  0, $0e, 1
+	dsprite  5,  0,  7,  0, $10, 0
+	dsprite  5,  0,  8,  0, $12, 0
+	dsprite  5,  0,  9,  0, $14, 0
+	dsprite  5,  0, 10,  0, $16, 0
+	dsprite  5,  0, 11,  0, $18, 0
+	dsprite  5,  0, 12,  0, $1a, 0
+	dsprite  5,  0, 13,  0, $1c, 0
+	dsprite  5,  0, 14,  0, $1e, 0
+	dsprite  7,  0,  7,  0, $20, 0
+	dsprite  7,  0,  8,  0, $22, 0
+	dsprite  7,  0,  9,  0, $24, 0
+	dsprite  7,  0, 10,  0, $26, 0
+	dsprite  7,  0, 11,  0, $28, 0
+	dsprite  7,  0, 12,  0, $2a, 0
+	dsprite  7,  0, 13,  0, $2c, 0
+	dsprite  7,  0, 14,  0, $2e, 0
+	dsprite  9,  0,  7,  0, $30, 2
+	dsprite  9,  0,  8,  0, $32, 2
+	dsprite  9,  0,  9,  0, $34, 2
+	dsprite  9,  0, 10,  0, $36, 2
+	dsprite  9,  0, 11,  0, $38, 2
+	dsprite  9,  0, 12,  0, $3a, 2
+	dsprite  9,  0, 13,  0, $3c, 2
+	dsprite  9,  0, 14,  0, $3e, 2
+	dsprite 11,  0,  7,  0, $40, 1
+	dsprite 11,  0,  8,  0, $42, 1
+	dsprite 11,  0,  9,  0, $44, 1
+	dsprite 11,  0, 10,  0, $46, 1
+	dsprite 11,  0, 11,  0, $48, 1
+	dsprite 11,  0, 12,  0, $4a, 1
+	dsprite 11,  0, 13,  0, $4c, 1
+	dsprite 11,  0, 14,  0, $4e, 1
+; 10ed51
+
+Function10ed51: ; 10ed51
+	call _TitleScreen
+.loop
+	call JoyTextDelay
+	ld a, [hJoyLast]
+	ld b, a
+	and 1
+	jr nz, .done
+	call SuicuneFrameIterator
+	call DelayFrame
+	jr .loop
+.done
+	ret
+; 10ed67
--- a/engine/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/tmhm2.asm
+++ /dev/null
@@ -1,589 +1,0 @@
-TMHMPocket: ; 2c76f (b:476f)
-	ld a, $1
-	ld [hInMenu], a
-	call TMHM_PocketLoop
-	ld a, $0
-	ld [hInMenu], a
-	ret nc
-	call PlaceHollowCursor
-	call WaitBGMap
-	ld a, [wCurItem]
-	dec a
-	ld [wCurItemQuantity], a
-	ld hl, wTMsHMs
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [hl]
-	ld [wItemQuantityBuffer], a
-	call .ConvertItemToTMHMNumber
-	scf
-	ret
-
-.ConvertItemToTMHMNumber: ; 2c798 (b:4798)
-	ld a, [wCurItem]
-	ld c, a
-	callfar GetNumberedTMHM
-	ld a, c
-	ld [wCurItem], a
-	ret
-
-ConvertCurItemIntoCurTMHM: ; 2c7a7 (b:47a7)
-	ld a, [wCurItem]
-	ld c, a
-	callfar GetTMHMNumber
-	ld a, c
-	ld [wCurTMHM], a
-	ret
-
-GetTMHMItemMove: ; 2c7b6 (b:47b6)
-	call ConvertCurItemIntoCurTMHM
-	predef GetTMHMMove
-	ret
-
-AskTeachTMHM: ; 2c7bf (b:47bf)
-	ld hl, wOptions
-	ld a, [hl]
-	push af
-	res NO_TEXT_SCROLL, [hl]
-	ld a, [wCurItem]
-	cp TM01
-	jr c, .NotTMHM
-	call GetTMHMItemMove
-	ld a, [wCurTMHM]
-	ld [wPutativeTMHMMove], a
-	call GetMoveName
-	call CopyName1
-	ld hl, Text_BootedTM ; Booted up a TM
-	ld a, [wCurItem]
-	cp HM01
-	jr c, .TM
-	ld hl, Text_BootedHM ; Booted up an HM
-.TM:
-	call PrintText
-	ld hl, Text_ItContained
-	call PrintText
-	call YesNoBox
-.NotTMHM:
-	pop bc
-	ld a, b
-	ld [wOptions], a
-	ret
-
-ChooseMonToLearnTMHM: ; 2c7fb
-	ld hl, wStringBuffer2
-	ld de, wTMHMMoveNameBackup
-	ld bc, 12
-	call CopyBytes
-	call ClearBGPalettes
-ChooseMonToLearnTMHM_NoRefresh: ; 2c80a
-	farcall LoadPartyMenuGFX
-	farcall InitPartyMenuWithCancel
-	farcall InitPartyMenuGFX
-	ld a, PARTYMENUACTION_TEACH_TMHM
-	ld [wPartyMenuActionText], a
-.loopback
-	farcall WritePartyMenuTilemap
-	farcall PrintPartyMenuText
-	call WaitBGMap
-	call SetPalettes
-	call DelayFrame
-	farcall PartyMenuSelect
-	push af
-	ld a, [wCurPartySpecies]
-	cp EGG
-	pop bc ; now contains the former contents of af
-	jr z, .egg
-	push bc
-	ld hl, wTMHMMoveNameBackup
-	ld de, wStringBuffer2
-	ld bc, 12
-	call CopyBytes
-	pop af ; now contains the original contents of af
-	ret
-
-.egg
-	push hl
-	push de
-	push bc
-	push af
-	ld de, SFX_WRONG
-	call PlaySFX
-	call WaitSFX
-	pop af
-	pop bc
-	pop de
-	pop hl
-	jr .loopback
-; 2c867
-
-TeachTMHM: ; 2c867
-	predef CanLearnTMHMMove
-
-	push bc
-	ld a, [wCurPartyMon]
-	ld hl, wPartyMonNicknames
-	call GetNick
-	pop bc
-
-	ld a, c
-	and a
-	jr nz, .compatible
-	push de
-	ld de, SFX_WRONG
-	call PlaySFX
-	pop de
-	ld hl, Text_TMHMNotCompatible
-	call PrintText
-	jr .nope
-
-.compatible
-	callfar KnowsMove
-	jr c, .nope
-
-	predef LearnMove
-	ld a, b
-	and a
-	jr z, .nope
-
-	farcall StubbedTrainerRankings_TMsHMsTaught
-	ld a, [wCurItem]
-	call IsHM
-	ret c
-
-	ld c, HAPPINESS_LEARNMOVE
-	callfar ChangeHappiness
-	call ConsumeTM
-	jr .learned_move
-
-.nope
-	and a
-	ret
-
-.unused
-	ld a, 2
-	ld [wItemEffectSucceeded], a
-.learned_move
-	scf
-	ret
-; 2c8bf (b:48bf)
-
-Text_BootedTM: ; 0x2c8bf
-	; Booted up a TM.
-	text_jump UnknownText_0x1c0373
-	db "@"
-; 0x2c8c4
-
-Text_BootedHM: ; 0x2c8c4
-	; Booted up an HM.
-	text_jump UnknownText_0x1c0384
-	db "@"
-; 0x2c8c9
-
-Text_ItContained: ; 0x2c8c9
-	; It contained @ . Teach @ to a #MON?
-	text_jump UnknownText_0x1c0396
-	db "@"
-; 0x2c8ce
-
-Text_TMHMNotCompatible: ; 0x2c8ce
-	; is not compatible with @ . It can't learn @ .
-	text_jump UnknownText_0x1c03c2
-	db "@"
-; 0x2c8d3
-
-TMHM_PocketLoop: ; 2c8d3 (b:48d3)
-	xor a
-	ld [hBGMapMode], a
-	call TMHM_DisplayPocketItems
-	ld a, 2
-	ld [w2DMenuCursorInitY], a
-	ld a, 7
-	ld [w2DMenuCursorInitX], a
-	ld a, 1
-	ld [w2DMenuNumCols], a
-	ld a, 5
-	sub d
-	inc a
-	cp 6
-	jr nz, .okay
-	dec a
-.okay
-	ld [w2DMenuNumRows], a
-	ld a, $c
-	ld [w2DMenuFlags1], a
-	xor a
-	ld [w2DMenuFlags2], a
-	ld a, $20
-	ld [w2DMenuCursorOffsets], a
-	ld a, A_BUTTON | B_BUTTON | D_UP | D_DOWN | D_LEFT | D_RIGHT
-	ld [wMenuJoypadFilter], a
-	ld a, [wTMHMPocketCursor]
-	inc a
-	ld [wMenuCursorY], a
-	ld a, $1
-	ld [wMenuCursorX], a
-	jr TMHM_ShowTMMoveDescription
-
-TMHM_JoypadLoop: ; 2c915 (b:4915)
-	call TMHM_DisplayPocketItems
-	call StaticMenuJoypad
-	ld b, a
-	ld a, [wMenuCursorY]
-	dec a
-	ld [wTMHMPocketCursor], a
-	xor a
-	ld [hBGMapMode], a
-	ld a, [w2DMenuFlags2]
-	bit 7, a
-	jp nz, TMHM_ScrollPocket
-	ld a, b
-	ld [wMenuJoypad], a
-	bit A_BUTTON_F, a
-	jp nz, TMHM_ChooseTMorHM
-	bit B_BUTTON_F, a
-	jp nz, TMHM_ExitPack
-	bit D_RIGHT_F, a
-	jp nz, TMHM_ExitPocket
-	bit D_LEFT_F, a
-	jp nz, TMHM_ExitPocket
-TMHM_ShowTMMoveDescription: ; 2c946 (b:4946)
-	call TMHM_CheckHoveringOverCancel
-	jp nc, TMHM_ExitPocket
-	hlcoord 0, 12
-	ld b, 4
-	ld c, SCREEN_WIDTH - 2
-	call TextBox
-	ld a, [wCurItem]
-	cp NUM_TMS + NUM_HMS + 1
-	jr nc, TMHM_JoypadLoop
-	ld [wd265], a
-	predef GetTMHMMove
-	ld a, [wd265]
-	ld [wCurSpecies], a
-	hlcoord 1, 14
-	call PrintMoveDesc
-	jp TMHM_JoypadLoop
-
-TMHM_ChooseTMorHM: ; 2c974 (b:4974)
-	call TMHM_PlaySFX_ReadText2
-	call CountTMsHMs ; This stores the count to wd265.
-	ld a, [wMenuCursorY]
-	dec a
-	ld b, a
-	ld a, [wTMHMPocketScrollPosition]
-	add b
-	ld b, a
-	ld a, [wd265]
-	cp b
-	jr z, _TMHM_ExitPack ; our cursor was hovering over CANCEL
-TMHM_CheckHoveringOverCancel: ; 2c98a (b:498a)
-	call TMHM_GetCurrentPocketPosition
-	ld a, [wMenuCursorY]
-	ld b, a
-.loop
-	inc c
-	ld a, c
-	cp NUM_TMS + NUM_HMS + 1
-	jr nc, .okay
-	ld a, [hli]
-	and a
-	jr z, .loop
-	dec b
-	jr nz, .loop
-	ld a, c
-.okay
-	ld [wCurItem], a
-	cp -1
-	ret
-
-TMHM_ExitPack: ; 2c9a5 (b:49a5)
-	call TMHM_PlaySFX_ReadText2
-_TMHM_ExitPack: ; 2c9a8 (b:49a8)
-	ld a, $2
-	ld [wMenuJoypad], a
-	and a
-	ret
-
-TMHM_ExitPocket: ; 2c9af (b:49af)
-	and a
-	ret
-
-TMHM_ScrollPocket: ; 2c9b1 (b:49b1)
-	ld a, b
-	bit 7, a
-	jr nz, .skip
-	ld hl, wTMHMPocketScrollPosition
-	ld a, [hl]
-	and a
-	jp z, TMHM_JoypadLoop
-	dec [hl]
-	call TMHM_DisplayPocketItems
-	jp TMHM_ShowTMMoveDescription
-
-.skip
-	call TMHM_GetCurrentPocketPosition
-	ld b, 5
-.loop
-	inc c
-	ld a, c
-	cp NUM_TMS + NUM_HMS + 1
-	jp nc, TMHM_JoypadLoop
-	ld a, [hli]
-	and a
-	jr z, .loop
-	dec b
-	jr nz, .loop
-	ld hl, wTMHMPocketScrollPosition
-	inc [hl]
-	call TMHM_DisplayPocketItems
-	jp TMHM_ShowTMMoveDescription
-
-TMHM_DisplayPocketItems: ; 2c9e2 (b:49e2)
-	ld a, [wBattleType]
-	cp BATTLETYPE_TUTORIAL
-	jp z, Tutorial_TMHMPocket
-
-	hlcoord 5, 2
-	lb bc, 10, 15
-	ld a, " "
-	call ClearBox
-	call TMHM_GetCurrentPocketPosition
-	ld d, $5
-.loop2
-	inc c
-	ld a, c
-	cp NUM_TMS + NUM_HMS + 1
-	jr nc, .NotTMHM
-	ld a, [hli]
-	and a
-	jr z, .loop2
-	ld b, a
-	ld a, c
-	ld [wd265], a
-	push hl
-	push de
-	push bc
-	call TMHMPocket_GetCurrentLineCoord
-	push hl
-	ld a, [wd265]
-	cp NUM_TMS + 1
-	jr nc, .HM
-	ld de, wd265
-	lb bc, PRINTNUM_LEADINGZEROS | 1, 2
-	call PrintNum
-	jr .okay
-
-.HM:
-	push af
-	sub NUM_TMS
-	ld [wd265], a
-	ld [hl], "H"
-	inc hl
-	ld de, wd265
-	lb bc, PRINTNUM_RIGHTALIGN | 1, 2
-	call PrintNum
-	pop af
-	ld [wd265], a
-.okay
-	predef GetTMHMMove
-	ld a, [wd265]
-	ld [wPutativeTMHMMove], a
-	call GetMoveName
-	pop hl
-	ld bc, 3
-	add hl, bc
-	push hl
-	call PlaceString
-	pop hl
-	pop bc
-	ld a, c
-	push bc
-	cp NUM_TMS + 1
-	jr nc, .hm2
-	ld bc, SCREEN_WIDTH + 9
-	add hl, bc
-	ld [hl], "×"
-	inc hl
-	ld a, "0" ; why are we doing this?
-	pop bc
-	push bc
-	ld a, b
-	ld [wd265], a
-	ld de, wd265
-	lb bc, 1, 2
-	call PrintNum
-.hm2
-	pop bc
-	pop de
-	pop hl
-	dec d
-	jr nz, .loop2
-	jr .done
-
-.NotTMHM:
-	call TMHMPocket_GetCurrentLineCoord
-	inc hl
-	inc hl
-	inc hl
-	push de
-	ld de, TMHM_String_Cancel
-	call PlaceString
-	pop de
-.done
-	ret
-
-TMHMPocket_GetCurrentLineCoord: ; 2ca86 (b:4a86)
-	hlcoord 5, 0
-	ld bc, 2 * SCREEN_WIDTH
-	ld a, 6
-	sub d
-	ld e, a
-	; AddNTimes
-.loop
-	add hl, bc
-	dec e
-	jr nz, .loop
-	ret
-; 2ca95 (b:4a95)
-
-Unreferenced_Function2ca95: ; 2ca95
-	pop hl
-	ld bc, 3
-	add hl, bc
-	predef GetTMHMMove
-	ld a, [wd265]
-	ld [wPutativeTMHMMove], a
-	call GetMoveName
-	push hl
-	call PlaceString
-	pop hl
-	ret
-; 2caae
-
-TMHM_String_Cancel: ; 2caae
-	db "CANCEL@"
-; 2cab5
-
-TMHM_GetCurrentPocketPosition: ; 2cab5 (b:4ab5)
-	ld hl, wTMsHMs
-	ld a, [wTMHMPocketScrollPosition]
-	ld b, a
-	inc b
-	ld c, 0
-.loop
-	inc c
-	ld a, [hli]
-	and a
-	jr z, .loop
-	dec b
-	jr nz, .loop
-	dec hl
-	dec c
-	ret
-
-Tutorial_TMHMPocket: ; 2caca (b:4aca)
-	hlcoord 9, 3
-	push de
-	ld de, TMHM_String_Cancel
-	call PlaceString
-	pop de
-	ret
-
-TMHM_PlaySFX_ReadText2: ; 2cad6 (b:4ad6)
-	push de
-	ld de, SFX_READ_TEXT_2
-	call PlaySFX
-	pop de
-	ret
-; 2cadf (b:4adf)
-
-Unreferenced_Function2cadf: ; 2cadf
-	call ConvertCurItemIntoCurTMHM
-	call .CheckHaveRoomForTMHM
-	ld hl, .NoRoomText
-	jr nc, .print
-	ld hl, .ReceivedText
-.print
-	jp PrintText
-; 2caf0
-
-.NoRoomText: ; 0x2caf0
-	; You have no room for any more @ S.
-	text_jump UnknownText_0x1c03fa
-	db "@"
-; 0x2caf5
-
-.ReceivedText: ; 0x2caf5
-	; You received @ !
-	text_jump UnknownText_0x1c0421
-	db "@"
-; 0x2cafa
-
-.CheckHaveRoomForTMHM: ; 2cafa
-	ld a, [wd265]
-	dec a
-	ld hl, wTMsHMs
-	ld b, 0
-	ld c, a
-	add hl, bc
-	ld a, [hl]
-	inc a
-	cp NUM_TMS * 2
-	ret nc
-	ld [hl], a
-	ret
-; 2cb0c
-
-ConsumeTM: ; 2cb0c (b:4b0c)
-	call ConvertCurItemIntoCurTMHM
-	ld a, [wd265]
-	dec a
-	ld hl, wTMsHMs
-	ld b, 0
-	ld c, a
-	add hl, bc
-	ld a, [hl]
-	and a
-	ret z
-	dec a
-	ld [hl], a
-	ret nz
-	ld a, [wTMHMPocketScrollPosition]
-	and a
-	ret z
-	dec a
-	ld [wTMHMPocketScrollPosition], a
-	ret
-
-CountTMsHMs: ; 2cb2a (b:4b2a)
-	ld b, 0
-	ld c, NUM_TMS + NUM_HMS
-	ld hl, wTMsHMs
-.loop
-	ld a, [hli]
-	and a
-	jr z, .skip
-	inc b
-.skip
-	dec c
-	jr nz, .loop
-	ld a, b
-	ld [wd265], a
-	ret
-
-PrintMoveDesc: ; 2cb3e
-	push hl
-	ld hl, MoveDescriptions
-	ld a, [wCurSpecies]
-	dec a
-	ld c, a
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld e, a
-	ld d, [hl]
-	pop hl
-	jp PlaceString
-; 2cb52
--- a/engine/trade_animation.asm
+++ /dev/null
@@ -1,1646 +1,0 @@
-TRADEANIM_RIGHT_ARROW EQU $ed
-TRADEANIM_LEFT_ARROW  EQU $ee
-
-; TradeAnim_TubeAnimJumptable.Jumptable indexes
-	const_def
-	const TRADEANIMSTATE_0 ; 0
-	const TRADEANIMSTATE_1 ; 1
-	const TRADEANIMSTATE_2 ; 2
-	const TRADEANIMSTATE_3 ; 3
-TRADEANIMJUMPTABLE_LENGTH EQU const_value
-
-TradeAnimation: ; 28f24
-	xor a
-	ld [wcf66], a
-	ld hl, wPlayerTrademonSenderName
-	ld de, wOTTrademonSenderName
-	call LinkTradeAnim_LoadTradePlayerNames
-	ld hl, wPlayerTrademonSpecies
-	ld de, wOTTrademonSpecies
-	call LinkTradeAnim_LoadTradeMonSpecies
-	ld de, .script
-	jr RunTradeAnimScript
-
-.script
-	tradeanim_setup_givemon_scroll
-	tradeanim_show_givemon_data
-	tradeanim_do_givemon_scroll
-	tradeanim_wait_80
-	tradeanim_wait_96
-	tradeanim_poof
-	tradeanim_rocking_ball
-	tradeanim_enter_link_tube
-	tradeanim_wait_anim
-	tradeanim_bulge_through_tube
-	tradeanim_wait_anim
-	tradeanim_textbox_scroll
-	tradeanim_give_trademon_sfx
-	tradeanim_tube_to_ot
-	tradeanim_sent_to_ot_text
-	tradeanim_scroll_out_right
-
-	tradeanim_ot_sends_text_1
-	tradeanim_ot_bids_farewell
-	tradeanim_wait_40
-	tradeanim_scroll_out_right
-	tradeanim_get_trademon_sfx
-	tradeanim_tube_to_player
-	tradeanim_enter_link_tube
-	tradeanim_drop_ball
-	tradeanim_exit_link_tube
-	tradeanim_wait_anim
-	tradeanim_show_getmon_data
-	tradeanim_poof
-	tradeanim_wait_anim
-	tradeanim_frontpic_scroll
-	tradeanim_animate_frontpic
-	tradeanim_wait_80_if_ot_egg
-	tradeanim_textbox_scroll
-	tradeanim_take_care_of_text
-	tradeanim_scroll_out_right
-	tradeanim_end
-
-TradeAnimationPlayer2: ; 28f63
-	xor a
-	ld [wcf66], a
-	ld hl, wOTTrademonSenderName
-	ld de, wPlayerTrademonSenderName
-	call LinkTradeAnim_LoadTradePlayerNames
-	ld hl, wOTTrademonSpecies
-	ld de, wPlayerTrademonSpecies
-	call LinkTradeAnim_LoadTradeMonSpecies
-	ld de, .script
-	jr RunTradeAnimScript
-
-.script
-	tradeanim_ot_sends_text_2
-	tradeanim_ot_bids_farewell
-	tradeanim_wait_40
-	tradeanim_scroll_out_right
-	tradeanim_get_trademon_sfx
-	tradeanim_tube_to_ot
-	tradeanim_enter_link_tube
-	tradeanim_drop_ball
-	tradeanim_exit_link_tube
-	tradeanim_wait_anim
-	tradeanim_show_getmon_data
-	tradeanim_poof
-	tradeanim_wait_anim
-	tradeanim_frontpic_scroll
-	tradeanim_animate_frontpic
-	tradeanim_wait_180_if_ot_egg
-	tradeanim_textbox_scroll
-	tradeanim_take_care_of_text
-	tradeanim_scroll_out_right
-
-	tradeanim_setup_givemon_scroll
-	tradeanim_show_givemon_data
-	tradeanim_do_givemon_scroll
-	tradeanim_wait_40
-	tradeanim_poof
-	tradeanim_rocking_ball
-	tradeanim_enter_link_tube
-	tradeanim_wait_anim
-	tradeanim_bulge_through_tube
-	tradeanim_wait_anim
-	tradeanim_textbox_scroll
-	tradeanim_give_trademon_sfx
-	tradeanim_tube_to_player
-	tradeanim_sent_to_ot_text
-	tradeanim_scroll_out_right
-	tradeanim_end
-
-RunTradeAnimScript: ; 28fa1
-	ld hl, wTradeAnimAddress
-	ld [hl], e
-	inc hl
-	ld [hl], d
-	ld a, [hMapAnims]
-	push af
-	xor a
-	ld [hMapAnims], a
-	ld hl, wVramState
-	ld a, [hl]
-	push af
-	res 0, [hl]
-	ld hl, wOptions
-	ld a, [hl]
-	push af
-	set 4, [hl]
-	call .TradeAnimLayout
-	ld a, [wcf66]
-	and a
-	jr nz, .anim_loop
-	ld de, MUSIC_EVOLUTION
-	call PlayMusic2
-.anim_loop
-	call DoTradeAnimation
-	jr nc, .anim_loop
-	pop af
-	ld [wOptions], a
-	pop af
-	ld [wVramState], a
-	pop af
-	ld [hMapAnims], a
-	ret
-
-; 28fdb
-
-.TradeAnimLayout: ; 28fdb
-	xor a
-	ld [wJumptableIndex], a
-	call ClearBGPalettes
-	call ClearSprites
-	call ClearTileMap
-	call DisableLCD
-	call LoadFontsBattleExtra
-	callfar ClearSpriteAnims
-	ld a, [hCGB]
-	and a
-	jr z, .NotCGB
-	ld a, $1
-	ld [rVBK], a
-	ld hl, vTiles0
-	ld bc, sScratch - vTiles0
-	xor a
-	call ByteFill
-	ld a, $0
-	ld [rVBK], a
-
-.NotCGB:
-	hlbgcoord 0, 0
-	ld bc, sScratch - vBGMap0
-	ld a, " "
-	call ByteFill
-	ld hl, TradeGameBoyLZ
-	ld de, vTiles2 tile $31
-	call Decompress
-	ld hl, TradeArrowGFX
-	ld de, vTiles0 tile TRADEANIM_RIGHT_ARROW
-	ld bc, 1 tiles
-	ld a, BANK(TradeArrowGFX)
-	call FarCopyBytes
-	ld hl, TradeArrowGFX + 1 tiles
-	ld de, vTiles0 tile TRADEANIM_LEFT_ARROW
-	ld bc, 1 tiles
-	ld a, BANK(TradeArrowGFX)
-	call FarCopyBytes
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	farcall GetTrademonFrontpic
-	call EnableLCD
-	call LoadTradeBallAndCableGFX
-	ld a, [wPlayerTrademonSpecies]
-	ld hl, wPlayerTrademonDVs
-	ld de, vTiles0
-	call TradeAnim_GetFrontpic
-	ld a, [wOTTrademonSpecies]
-	ld hl, wOTTrademonDVs
-	ld de, vTiles0 tile $31
-	call TradeAnim_GetFrontpic
-	ld a, [wPlayerTrademonSpecies]
-	ld de, wPlayerTrademonSpeciesName
-	call TradeAnim_GetNickname
-	ld a, [wOTTrademonSpecies]
-	ld de, wOTTrademonSpeciesName
-	call TradeAnim_GetNickname
-	call TradeAnim_NormalPals
-	ret
-
-; 29082
-
-DoTradeAnimation: ; 29082
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .finished
-	call .DoTradeAnimCommand
-	callfar PlaySpriteAnimations
-	ld hl, wcf65
-	inc [hl]
-	call DelayFrame
-	and a
-	ret
-
-.finished
-	call LoadStandardFont
-	scf
-	ret
-
-; 290a0
-
-.DoTradeAnimCommand: ; 290a0
-	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
-; 290af
-
-.JumpTable: ; 290af
-; entries correspond to macros/scripts/trade_anims.asm enumeration
-	dw TradeAnim_AdvanceScriptPointer ; 00
-	dw TradeAnim_ShowGivemonData      ; 01
-	dw TradeAnim_ShowGetmonData       ; 02
-	dw TradeAnim_EnterLinkTube1       ; 03
-	dw TradeAnim_EnterLinkTube2       ; 04
-	dw TradeAnim_ExitLinkTube         ; 05
-	dw TradeAnim_TubeToOT1            ; 06
-	dw TradeAnim_TubeToOT2            ; 07
-	dw TradeAnim_TubeToOT3            ; 08
-	dw TradeAnim_TubeToOT4            ; 09
-	dw TradeAnim_TubeToOT5            ; 0a
-	dw TradeAnim_TubeToOT6            ; 0b
-	dw TradeAnim_TubeToOT7            ; 0c
-	dw TradeAnim_TubeToOT8            ; 0d
-	dw TradeAnim_TubeToPlayer1        ; 0e
-	dw TradeAnim_TubeToPlayer2        ; 0f
-	dw TradeAnim_TubeToPlayer3        ; 10
-	dw TradeAnim_TubeToPlayer4        ; 11
-	dw TradeAnim_TubeToPlayer5        ; 12
-	dw TradeAnim_TubeToPlayer6        ; 13
-	dw TradeAnim_TubeToPlayer7        ; 14
-	dw TradeAnim_TubeToPlayer8        ; 15
-	dw TradeAnim_SentToOTText         ; 16
-	dw TradeAnim_OTBidsFarewell       ; 17
-	dw TradeAnim_TakeCareOfText       ; 18
-	dw TradeAnim_OTSendsText1         ; 19
-	dw TradeAnim_OTSendsText2         ; 1a
-	dw TradeAnim_SetupGivemonScroll   ; 1b
-	dw TradeAnim_DoGivemonScroll      ; 1c
-	dw TradeAnim_FrontpicScrollStart  ; 1d
-	dw TradeAnim_TextboxScrollStart   ; 1e
-	dw TradeAnim_ScrollOutRight       ; 1f
-	dw TradeAnim_ScrollOutRight2      ; 20
-	dw TraideAnim_Wait80              ; 21
-	dw TraideAnim_Wait40              ; 22
-	dw TradeAnim_RockingBall          ; 23
-	dw TradeAnim_DropBall             ; 24
-	dw TradeAnim_WaitAnim             ; 25
-	dw TradeAnim_WaitAnim2            ; 26
-	dw TradeAnim_Poof                 ; 27
-	dw TradeAnim_BulgeThroughTube     ; 28
-	dw TradeAnim_GiveTrademonSFX      ; 29
-	dw TradeAnim_GetTrademonSFX       ; 2a
-	dw TradeAnim_End                  ; 2b
-	dw TradeAnim_AnimateFrontpic      ; 2c
-	dw TraideAnim_Wait96              ; 2d
-	dw TraideAnim_Wait80IfOTEgg       ; 2e
-	dw TraideAnim_Wait180IfOTEgg      ; 2f
-; 2910f
-
-TradeAnim_IncrementJumptableIndex: ; 2910f
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-; 29114
-
-TradeAnim_AdvanceScriptPointer: ; 29114
-	ld hl, wTradeAnimAddress
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	ld a, [de]
-	ld [wJumptableIndex], a
-	inc de
-	ld [hl], d
-	dec hl
-	ld [hl], e
-	ret
-
-; 29123
-
-TradeAnim_End: ; 29123
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-; 29129
-
-TradeAnim_TubeToOT1: ; 29129
-	ld a, TRADEANIM_RIGHT_ARROW
-	call TradeAnim_PlaceTrademonStatsOnTubeAnim
-	ld a, [wLinkTradeSendmonSpecies]
-	ld [wd265], a
-	xor a
-	depixel 5, 11, 4, 0
-	ld b, $0
-	jr TradeAnim_InitTubeAnim
-
-TradeAnim_TubeToPlayer1: ; 2913c
-	ld a, TRADEANIM_LEFT_ARROW
-	call TradeAnim_PlaceTrademonStatsOnTubeAnim
-	ld a, [wLinkTradeGetmonSpecies]
-	ld [wd265], a
-	ld a, TRADEANIMSTATE_2
-	depixel 9, 18, 4, 4
-	ld b, $4
-TradeAnim_InitTubeAnim: ; 2914e
-	push bc
-	push de
-	push bc
-	push de
-
-	push af
-	call DisableLCD
-	callfar ClearSpriteAnims
-	hlbgcoord 20, 3
-	ld bc, 12
-	ld a, $60
-	call ByteFill
-	pop af
-
-	call TradeAnim_TubeAnimJumptable
-
-	xor a
-	ld [hSCX], a
-	ld a, $7
-	ld [hWX], a
-	ld a, $70
-	ld [hWY], a
-	call EnableLCD
-	call LoadTradeBubbleGFX
-
-	pop de
-	ld a, SPRITE_ANIM_INDEX_TRADEMON_ICON
-	call _InitSpriteAnimStruct
-
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	pop bc
-	ld [hl], b
-
-	pop de
-	ld a, SPRITE_ANIM_INDEX_TRADEMON_BUBBLE
-	call _InitSpriteAnimStruct
-
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	pop bc
-	ld [hl], b
-
-	call WaitBGMap
-	ld b, SCGB_TRADE_TUBE
-	call GetSGBLayout
-	ld a, %11100100 ; 3,2,1,0
-	call DmgToCgbBGPals
-	ld a, %11010000
-	call DmgToCgbObjPal0
-
-	call TradeAnim_IncrementJumptableIndex
-	ld a, 92
-	ld [wFrameCounter], a
-	ret
-
-; 291af
-
-TradeAnim_TubeToOT2: ; 291af
-	call TradeAnim_FlashBGPals
-	ld a, [hSCX]
-	add $2
-	ld [hSCX], a
-	cp $50
-	ret nz
-	ld a, TRADEANIMSTATE_1
-	call TradeAnim_TubeAnimJumptable
-	call TradeAnim_IncrementJumptableIndex
-	ret
-
-; 291c4
-
-TradeAnim_TubeToOT3: ; 291c4
-	call TradeAnim_FlashBGPals
-	ld a, [hSCX]
-	add $2
-	ld [hSCX], a
-	cp $a0
-	ret nz
-	ld a, TRADEANIMSTATE_2
-	call TradeAnim_TubeAnimJumptable
-	call TradeAnim_IncrementJumptableIndex
-	ret
-
-; 291d9
-
-TradeAnim_TubeToOT4: ; 291d9
-	call TradeAnim_FlashBGPals
-	ld a, [hSCX]
-	add $2
-	ld [hSCX], a
-	and a
-	ret nz
-	call TradeAnim_IncrementJumptableIndex
-	ret
-
-; 291e8
-
-TradeAnim_TubeToPlayer3: ; 291e8
-	call TradeAnim_FlashBGPals
-	ld a, [hSCX]
-	sub $2
-	ld [hSCX], a
-	cp $b0
-	ret nz
-	ld a, TRADEANIMSTATE_1
-	call TradeAnim_TubeAnimJumptable
-	call TradeAnim_IncrementJumptableIndex
-	ret
-
-; 291fd
-
-TradeAnim_TubeToPlayer4: ; 291fd
-	call TradeAnim_FlashBGPals
-	ld a, [hSCX]
-	sub $2
-	ld [hSCX], a
-	cp $60
-	ret nz
-	xor a ; TRADEANIMSTATE_0
-	call TradeAnim_TubeAnimJumptable
-	call TradeAnim_IncrementJumptableIndex
-	ret
-
-; 29211
-
-TradeAnim_TubeToPlayer5: ; 29211
-	call TradeAnim_FlashBGPals
-	ld a, [hSCX]
-	sub $2
-	ld [hSCX], a
-	and a
-	ret nz
-	call TradeAnim_IncrementJumptableIndex
-	ret
-
-; 29220
-
-TradeAnim_TubeToOT6:
-TradeAnim_TubeToPlayer6: ; 29220
-	ld a, 128
-	ld [wFrameCounter], a
-	call TradeAnim_IncrementJumptableIndex
-	ret
-
-; 29229
-
-TradeAnim_TubeToOT8:
-TradeAnim_TubeToPlayer8: ; 29229
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	call DisableLCD
-	callfar ClearSpriteAnims
-	hlbgcoord 0, 0
-	ld bc, sScratch - vBGMap0
-	ld a, " "
-	call ByteFill
-	xor a
-	ld [hSCX], a
-	ld a, $90
-	ld [hWY], a
-	call EnableLCD
-	call LoadTradeBallAndCableGFX
-	call WaitBGMap
-	call TradeAnim_NormalPals
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 2925d
-
-TradeAnim_TubeToOT5:
-TradeAnim_TubeToOT7:
-TradeAnim_TubeToPlayer2:
-TradeAnim_TubeToPlayer7: ; 2925d
-	call TradeAnim_FlashBGPals
-	ld hl, wFrameCounter
-	ld a, [hl]
-	and a
-	jr z, .done
-	dec [hl]
-	ret
-
-.done
-	call TradeAnim_IncrementJumptableIndex
-	ret
-
-; 2926d
-
-TradeAnim_GiveTrademonSFX: ; 2926d
-	call TradeAnim_AdvanceScriptPointer
-	ld de, SFX_GIVE_TRADEMON
-	call PlaySFX
-	ret
-
-; 29277
-
-TradeAnim_GetTrademonSFX: ; 29277
-	call TradeAnim_AdvanceScriptPointer
-	ld de, SFX_GET_TRADEMON
-	call PlaySFX
-	ret
-
-; 29281
-
-TradeAnim_TubeAnimJumptable: ; 29281
-	maskbits TRADEANIMJUMPTABLE_LENGTH
-	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
-; 2928f
-
-.Jumptable: ; 2928f
-; entries correspond to TRADEANIMSTATE_* constants
-	dw .Zero
-	dw .One
-	dw .Two
-	dw .Three
-; 29297
-
-.Zero: ; 29297
-.Three: ; 29297
-	call TradeAnim_BlankTileMap
-	hlcoord 9, 3
-	ld [hl], $5b
-	inc hl
-	ld bc, 10
-	ld a, $60
-	call ByteFill
-	hlcoord 3, 2
-	call TradeAnim_CopyTradeGameBoyTilemap
-	ret
-
-; 292af
-
-.One: ; 292af
-	call TradeAnim_BlankTileMap
-	hlcoord 0, 3
-	ld bc, SCREEN_WIDTH
-	ld a, $60
-	call ByteFill
-	ret
-
-; 292be
-
-.Two: ; 292be
-	call TradeAnim_BlankTileMap
-	hlcoord 0, 3
-	ld bc, $11
-	ld a, $60
-	call ByteFill
-	hlcoord 17, 3
-	ld a, $5d
-	ld [hl], a
-
-	ld a, $61
-	ld de, SCREEN_WIDTH
-	ld c, $3
-.loop
-	add hl, de
-	ld [hl], a
-	dec c
-	jr nz, .loop
-
-	add hl, de
-	ld a, $5f
-	ld [hld], a
-	ld a, $5b
-	ld [hl], a
-	hlcoord 10, 6
-	call TradeAnim_CopyTradeGameBoyTilemap
-	ret
-
-; 292ec
-
-TradeAnim_CopyTradeGameBoyTilemap: ; 292ec
-	ld de, TradeGameBoyTilemap
-	lb bc, 8, 6
-	call TradeAnim_CopyBoxFromDEtoHL
-	ret
-
-; 292f6
-
-TradeAnim_PlaceTrademonStatsOnTubeAnim: ; 292f6
-	push af
-	call ClearBGPalettes
-	call WaitTop
-	ld a, HIGH(vBGMap1)
-	ld [hBGMapAddress + 1], a
-	call ClearTileMap
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH
-	ld a, "─"
-	call ByteFill
-	hlcoord 0, 1
-	ld de, wLinkPlayer1Name
-	call PlaceString
-	ld hl, wLinkPlayer2Name
-	ld de, 0
-.find_name_end_loop
-	ld a, [hli]
-	cp "@"
-	jr z, .done
-	dec de
-	jr .find_name_end_loop
-
-.done
-	hlcoord 0, 4
-	add hl, de
-	ld de, wLinkPlayer2Name
-	call PlaceString
-	hlcoord 7, 2
-	ld bc, 6
-	pop af
-	call ByteFill
-	call WaitBGMap
-	call WaitTop
-	ld a, HIGH(vBGMap0)
-	ld [hBGMapAddress + 1], a
-	call ClearTileMap
-	ret
-
-; 29348
-
-TradeAnim_EnterLinkTube1: ; 29348
-	call ClearTileMap
-	call WaitTop
-	ld a, $a0
-	ld [hSCX], a
-	call DelayFrame
-	hlcoord 8, 2
-	ld de, TradeLinkTubeTilemap
-	lb bc, 3, 12
-	call TradeAnim_CopyBoxFromDEtoHL
-	call WaitBGMap
-	ld b, SCGB_TRADE_TUBE
-	call GetSGBLayout
-	ld a, %11100100 ; 3,2,1,0
-	call DmgToCgbBGPals
-	lb de, %11100100, %11100100 ; 3,2,1,0, 3,2,1,0
-	call DmgToCgbObjPals
-	ld de, SFX_POTION
-	call PlaySFX
-	call TradeAnim_IncrementJumptableIndex
-	ret
-
-; 2937e
-
-TradeAnim_EnterLinkTube2: ; 2937e
-	ld a, [hSCX]
-	and a
-	jr z, .done
-	add $4
-	ld [hSCX], a
-	ret
-
-.done
-	ld c, 80
-	call DelayFrames
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 29391
-
-TradeAnim_ExitLinkTube: ; 29391
-	ld a, [hSCX]
-	cp $a0
-	jr z, .done
-	sub $4
-	ld [hSCX], a
-	ret
-
-.done
-	call ClearTileMap
-	xor a
-	ld [hSCX], a
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 293a6
-
-TradeAnim_SetupGivemonScroll: ; 293a6
-	ld a, $8f
-	ld [hWX], a
-	ld a, $88
-	ld [hSCX], a
-	ld a, $50
-	ld [hWY], a
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 293b6
-
-TradeAnim_DoGivemonScroll: ; 293b6
-	ld a, [hWX]
-	cp $7
-	jr z, .done
-	sub $4
-	ld [hWX], a
-	ld a, [hSCX]
-	sub $4
-	ld [hSCX], a
-	ret
-
-.done
-	ld a, $7
-	ld [hWX], a
-	xor a
-	ld [hSCX], a
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 293d2
-
-TradeAnim_FrontpicScrollStart: ; 293d2
-	ld a, $7
-	ld [hWX], a
-	ld a, $50
-	ld [hWY], a
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 293de
-
-TradeAnim_TextboxScrollStart: ; 293de
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 293ea
-
-TradeAnim_ScrollOutRight: ; 293ea
-	call WaitTop
-	ld a, HIGH(vBGMap1)
-	ld [hBGMapAddress + 1], a
-	call WaitBGMap
-	ld a, $7
-	ld [hWX], a
-	xor a
-	ld [hWY], a
-	call DelayFrame
-	call WaitTop
-	ld a, HIGH(vBGMap0)
-	ld [hBGMapAddress + 1], a
-	call ClearTileMap
-	call TradeAnim_IncrementJumptableIndex
-	ret
-
-; 2940c
-
-TradeAnim_ScrollOutRight2: ; 2940c
-	ld a, [hWX]
-	cp $a1
-	jr nc, .done
-	add $4
-	ld [hWX], a
-	ret
-
-.done
-	ld a, HIGH(vBGMap1)
-	ld [hBGMapAddress + 1], a
-	call WaitBGMap
-	ld a, $7
-	ld [hWX], a
-	ld a, $90
-	ld [hWY], a
-	ld a, HIGH(vBGMap0)
-	ld [hBGMapAddress + 1], a
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 2942e
-
-TradeAnim_ShowGivemonData: ; 2942e
-	call ShowPlayerTrademonStats
-	ld a, [wPlayerTrademonSpecies]
-	ld [wCurPartySpecies], a
-	ld a, [wPlayerTrademonDVs]
-	ld [wTempMonDVs], a
-	ld a, [wPlayerTrademonDVs + 1]
-	ld [wTempMonDVs + 1], a
-	ld b, SCGB_PLAYER_OR_MON_FRONTPIC_PALS
-	call GetSGBLayout
-	ld a, %11100100 ; 3,2,1,0
-	call DmgToCgbBGPals
-	call TradeAnim_ShowGivemonFrontpic
-
-	ld a, [wPlayerTrademonSpecies]
-	call GetCryIndex
-	jr c, .skip_cry
-	ld e, c
-	ld d, b
-	call PlayCry
-.skip_cry
-
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 29461
-
-TradeAnim_ShowGetmonData: ; 29461
-	call 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
-	call TradeAnim_ShowGetmonFrontpic
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 29487
-
-TradeAnim_AnimateFrontpic: ; 29487
-	farcall AnimateTrademonFrontpic
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 29491
-
-TradeAnim_GetFrontpic: ; 29491
-	push de
-	push af
-	predef GetUnownLetter
-	pop af
-	ld [wCurPartySpecies], a
-	ld [wCurSpecies], a
-	call GetBaseData
-	pop de
-	predef GetMonFrontpic
-	ret
-
-; 294a9
-
-TradeAnim_GetNickname: ; 294a9
-	push de
-	ld [wd265], a
-	call GetPokemonName
-	ld hl, wStringBuffer1
-	pop de
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ret
-
-; 294bb
-
-TradeAnim_ShowGivemonFrontpic: ; 294bb
-	ld de, vTiles0
-	jr TradeAnim_ShowFrontpic
-
-TradeAnim_ShowGetmonFrontpic: ; 294c0
-	ld de, vTiles0 tile $31
-TradeAnim_ShowFrontpic: ; 294c3
-	call DelayFrame
-	ld hl, vTiles2
-	lb bc, 10, $31
-	call Request2bpp
-	call WaitTop
-	call TradeAnim_BlankTileMap
-	hlcoord 7, 2
-	xor a
-	ld [hGraphicStartTile], a
-	lb bc, 7, 7
-	predef PlaceGraphic
-	call WaitBGMap
-	ret
-
-; 294e7
-
-TraideAnim_Wait80: ; 294e7
-	ld c, 80
-	call DelayFrames
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 294f0
-
-TraideAnim_Wait40: ; 294f0
-	ld c, 40
-	call DelayFrames
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 294f9
-
-TraideAnim_Wait96: ; 294f9
-	ld c, 96
-	call DelayFrames
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 29502
-
-TraideAnim_Wait80IfOTEgg: ; 29502
-	call IsOTTrademonEgg
-	ret nz
-	ld c, 80
-	call DelayFrames
-	ret
-
-; 2950c
-
-TraideAnim_Wait180IfOTEgg: ; 2950c
-	call IsOTTrademonEgg
-	ret nz
-	ld c, 180
-	call DelayFrames
-	ret
-
-; 29516
-
-IsOTTrademonEgg: ; 29516
-	call TradeAnim_AdvanceScriptPointer
-	ld a, [wOTTrademonSpecies]
-	cp EGG
-	ret
-
-; 2951f
-ShowPlayerTrademonStats: ; 2951f
-	ld de, wPlayerTrademonSpecies
-	ld a, [de]
-	cp EGG
-	jr z, TrademonStats_Egg
-	call TrademonStats_MonTemplate
-	ld de, wPlayerTrademonSpecies
-	call TrademonStats_PrintSpeciesNumber
-	ld de, wPlayerTrademonSpeciesName
-	call TrademonStats_PrintSpeciesName
-	ld a, [wPlayerTrademonCaughtData]
-	ld de, wPlayerTrademonOTName
-	call TrademonStats_PrintOTName
-	ld de, wPlayerTrademonID
-	call TrademonStats_PrintTrademonID
-	call TrademonStats_WaitBGMap
-	ret
-
-; 29549
-
-ShowOTTrademonStats: ; 29549
-	ld de, wOTTrademonSpecies
-	ld a, [de]
-	cp EGG
-	jr z, TrademonStats_Egg
-	call TrademonStats_MonTemplate
-	ld de, wOTTrademonSpecies
-	call TrademonStats_PrintSpeciesNumber
-	ld de, wOTTrademonSpeciesName
-	call TrademonStats_PrintSpeciesName
-	ld a, [wOTTrademonCaughtData]
-	ld de, wOTTrademonOTName
-	call TrademonStats_PrintOTName
-	ld de, wOTTrademonID
-	call TrademonStats_PrintTrademonID
-	call TrademonStats_WaitBGMap
-	ret
-
-; 29573
-
-TrademonStats_MonTemplate: ; 29573
-	call WaitTop
-	call TradeAnim_BlankTileMap
-	ld a, HIGH(vBGMap1)
-	ld [hBGMapAddress + 1], a
-	hlcoord 3, 0
-	ld b, $6
-	ld c, $d
-	call TextBox
-	hlcoord 4, 0
-	ld de, .OTMonData
-	call PlaceString
-	ret
-
-; 29591
-
-.OTMonData: ; 29591
-	db   "─── №."
-	next ""
-	next "OT/"
-	next "<ID>№.@"
-; 295a1
-
-TrademonStats_Egg: ; 295a1
-	call WaitTop
-	call TradeAnim_BlankTileMap
-	ld a, HIGH(vBGMap1)
-	ld [hBGMapAddress + 1], a
-	hlcoord 3, 0
-	ld b, 6
-	ld c, 13
-	call TextBox
-	hlcoord 4, 2
-	ld de, .EggData
-	call PlaceString
-	call TrademonStats_WaitBGMap
-	ret
-
-; 295c2
-
-.EggData: ; 295c2
-	db   "EGG"
-	next "OT/?????"
-	next "<ID>№.?????@"
-; 295d8
-
-TrademonStats_WaitBGMap: ; 295d8
-	call WaitBGMap
-	call WaitTop
-	ld a, HIGH(vBGMap0)
-	ld [hBGMapAddress + 1], a
-	ret
-
-; 295e3
-
-TrademonStats_PrintSpeciesNumber: ; 295e3
-	hlcoord 10, 0
-	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
-	call PrintNum
-	ld [hl], " "
-	ret
-
-; 295ef
-
-TrademonStats_PrintSpeciesName: ; 295ef
-	hlcoord 4, 2
-	call PlaceString
-	ret
-
-; 295f6
-
-TrademonStats_PrintOTName: ; 295f6
-	cp 3
-	jr c, .caught_gender_okay
-	xor a
-.caught_gender_okay
-	push af
-	hlcoord 7, 4
-	call PlaceString
-	inc bc
-	pop af
-	ld hl, .Gender
-	ld d, 0
-	ld e, a
-	add hl, de
-	ld a, [hl]
-	ld [bc], a
-	ret
-
-; 2960e
-
-.Gender: ; 2960e
-	db " ", "♂", "♀"
-; 29611
-
-TrademonStats_PrintTrademonID: ; 29611
-	hlcoord 7, 6
-	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
-	call PrintNum
-	ret
-
-; 2961b
-
-TradeAnim_RockingBall: ; 2961b
-	depixel 10, 11, 4, 0
-	ld a, SPRITE_ANIM_INDEX_TRADE_POKE_BALL
-	call _InitSpriteAnimStruct
-	call TradeAnim_AdvanceScriptPointer
-	ld a, 32
-	ld [wFrameCounter], a
-	ret
-
-; 2962c
-
-TradeAnim_DropBall: ; 2962c
-	depixel 10, 11, 4, 0
-	ld a, SPRITE_ANIM_INDEX_TRADE_POKE_BALL
-	call _InitSpriteAnimStruct
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	ld [hl], $1
-	ld hl, SPRITEANIMSTRUCT_YOFFSET
-	add hl, bc
-	ld [hl], $dc
-	call TradeAnim_AdvanceScriptPointer
-	ld a, 56
-	ld [wFrameCounter], a
-	ret
-
-; 29649
-
-TradeAnim_Poof: ; 29649
-	depixel 10, 11, 4, 0
-	ld a, SPRITE_ANIM_INDEX_TRADE_POOF
-	call _InitSpriteAnimStruct
-	call TradeAnim_AdvanceScriptPointer
-	ld a, 16
-	ld [wFrameCounter], a
-	ld de, SFX_BALL_POOF
-	call PlaySFX
-	ret
-
-; 29660
-
-TradeAnim_BulgeThroughTube: ; 29660
-	ld a, %11100100 ; 3,2,1,0
-	call DmgToCgbObjPal0
-	depixel 5, 11
-	ld a, SPRITE_ANIM_INDEX_TRADE_TUBE_BULGE
-	call _InitSpriteAnimStruct
-	call TradeAnim_AdvanceScriptPointer
-	ld a, 64
-	ld [wFrameCounter], a
-	ret
-
-; 29676
-
-TradeAnim_AnimateTrademonInTube: ; 29676 (a:5676)
-	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
-; 29686
-
-.Jumptable: ; 29686 (a:5686)
-	dw .InitTimer
-	dw .WaitTimer1
-	dw .MoveRight
-	dw .MoveDown
-	dw .MoveUp
-	dw .MoveLeft
-	dw .WaitTimer2
-; 2969a
-
-.JumptableNext: ; 29694 (a:5694)
-	ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
-	add hl, bc
-	inc [hl]
-	ret
-
-.InitTimer: ; 2969a (a:569a)
-	call .JumptableNext
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $80
-	ret
-
-.WaitTimer1: ; 296a4 (a:56a4)
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	dec [hl]
-	and a
-	ret nz
-	call .JumptableNext
-
-.MoveRight: ; 296af (a:56af)
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld a, [hl]
-	cp $94
-	jr nc, .done_move_right
-	inc [hl]
-	ret
-
-.done_move_right
-	call .JumptableNext
-
-.MoveDown: ; 296bd (a:56bd)
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	ld a, [hl]
-	cp $4c
-	jr nc, .done_move_down
-	inc [hl]
-	ret
-
-.done_move_down
-	ld hl, SPRITEANIMSTRUCT_INDEX
-	add hl, bc
-	ld [hl], $0
-	ret
-
-.MoveUp: ; 296cf (a:56cf)
-	ld hl, SPRITEANIMSTRUCT_YCOORD
-	add hl, bc
-	ld a, [hl]
-	cp $2c
-	jr z, .done_move_up
-	dec [hl]
-	ret
-
-.done_move_up
-	call .JumptableNext
-
-.MoveLeft: ; 296dd (a:56dd)
-	ld hl, SPRITEANIMSTRUCT_XCOORD
-	add hl, bc
-	ld a, [hl]
-	cp $58
-	jr z, .done_move_left
-	dec [hl]
-	ret
-
-.done_move_left
-	call .JumptableNext
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld [hl], $80
-	ret
-
-.WaitTimer2: ; 296f2 (a:56f2)
-	ld hl, SPRITEANIMSTRUCT_0C
-	add hl, bc
-	ld a, [hl]
-	dec [hl]
-	and a
-	ret nz
-	ld hl, SPRITEANIMSTRUCT_INDEX
-	add hl, bc
-	ld [hl], $0
-	ret
-
-; 29701 (a:5701)
-
-TradeAnim_SentToOTText: ; 29701
-	ld a, [wLinkMode]
-	cp LINK_TIMECAPSULE
-	jr z, .time_capsule
-	ld hl, .Text_MonName
-	call PrintText
-	ld c, 189
-	call DelayFrames
-	ld hl, .Text_WasSentTo
-	call PrintText
-	call TradeAnim_Wait80Frames
-	ld c, 128
-	call DelayFrames
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-.time_capsule
-	ld hl, .Text_WasSentTo
-	call PrintText
-	call TradeAnim_Wait80Frames
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 29732
-
-.Text_WasSentTo: ; 0x29732
-	; was sent to @ .
-	text_jump UnknownText_0x1bc6e9
-	db "@"
-; 0x29737
-
-.Text_MonName: ; 0x29737
-	;
-	text_jump UnknownText_0x1bc701
-	db "@"
-; 0x2973c
-
-TradeAnim_OTBidsFarewell: ; 2973c
-	ld hl, .Text_BidsFarewellToMon
-	call PrintText
-	call TradeAnim_Wait80Frames
-	ld hl, .Text_MonName
-	call PrintText
-	call TradeAnim_Wait80Frames
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 29752
-
-.Text_BidsFarewellToMon: ; 0x29752
-	; bids farewell to
-	text_jump UnknownText_0x1bc703
-	db "@"
-; 0x29757
-
-.Text_MonName: ; 0x29757
-	; .
-	text_jump UnknownText_0x1bc719
-	db "@"
-; 0x2975c
-
-TradeAnim_TakeCareOfText: ; 2975c
-	call WaitTop
-	hlcoord 0, 10
-	ld bc, 8 * SCREEN_WIDTH
-	ld a, " "
-	call ByteFill
-	call WaitBGMap
-	ld hl, .Text_TakeGoodCareOfMon
-	call PrintText
-	call TradeAnim_Wait80Frames
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 2977a
-
-.Text_TakeGoodCareOfMon: ; 0x2977a
-	; Take good care of @ .
-	text_jump UnknownText_0x1bc71f
-	db "@"
-; 0x2977f
-
-TradeAnim_OTSendsText1: ; 2977f
-	ld hl, .Text_ForYourMon
-	call PrintText
-	call TradeAnim_Wait80Frames
-	ld hl, .Text_OTSends
-	call PrintText
-	call TradeAnim_Wait80Frames
-	ld c, 14
-	call DelayFrames
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 2979a
-
-.Text_ForYourMon: ; 0x2979a
-	; For @ 's @ ,
-	text_jump UnknownText_0x1bc739
-	db "@"
-; 0x2979f
-
-.Text_OTSends: ; 0x2979f
-	; sends @ .
-	text_jump UnknownText_0x1bc74c
-	db "@"
-; 0x297a4
-
-TradeAnim_OTSendsText2: ; 297a4
-	ld hl, .Text_WillTrade
-	call PrintText
-	call TradeAnim_Wait80Frames
-	ld hl, .Text_ForYourMon
-	call PrintText
-	call TradeAnim_Wait80Frames
-	ld c, 14
-	call DelayFrames
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 297bf
-
-.Text_WillTrade: ; 0x297bf
-	; will trade @ @
-	text_jump UnknownText_0x1bc75e
-	db "@"
-; 0x297c4
-
-.Text_ForYourMon: ; 0x297c4
-	; for @ 's @ .
-	text_jump UnknownText_0x1bc774
-	db "@"
-; 0x297c9
-
-TradeAnim_Wait80Frames: ; 297c9
-	ld c, 80
-	call DelayFrames
-	ret
-
-; 297cf
-
-TradeAnim_BlankTileMap: ; 297cf
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, " "
-	call ByteFill
-	ret
-
-; 297db
-
-TradeAnim_CopyBoxFromDEtoHL: ; 297db
-.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
-
-; 297ed
-
-TradeAnim_NormalPals: ; 297ed
-	ld a, [hSGB]
-	and a
-	ld a, %11100100 ; 3,2,1,0
-	jr z, .not_sgb
-	ld a, $f0
-
-.not_sgb
-	call DmgToCgbObjPal0
-	ld a, %11100100 ; 3,2,1,0
-	call DmgToCgbBGPals
-	ret
-
-; 297ff
-
-LinkTradeAnim_LoadTradePlayerNames: ; 297ff
-	push de
-	ld de, wLinkPlayer1Name
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	pop hl
-	ld de, wLinkPlayer2Name
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ret
-
-; 29814
-
-LinkTradeAnim_LoadTradeMonSpecies: ; 29814
-	ld a, [hl]
-	ld [wLinkTradeSendmonSpecies], a
-	ld a, [de]
-	ld [wLinkTradeGetmonSpecies], a
-	ret
-
-; 2981d
-
-TradeAnim_FlashBGPals: ; 2981d
-	ld a, [wcf65]
-	and $7
-	ret nz
-	ld a, [rBGP]
-	xor %00111100
-	call DmgToCgbBGPals
-	ret
-
-; 2982b
-
-LoadTradeBallAndCableGFX: ; 2982b
-	call DelayFrame
-	ld de, TradeBallGFX
-	ld hl, vTiles0 tile $62
-	lb bc, BANK(TradeBallGFX), 6
-	call Request2bpp
-	ld de, TradePoofGFX
-	ld hl, vTiles0 tile $68
-	lb bc, BANK(TradePoofGFX), 12
-	call Request2bpp
-	ld de, TradeCableGFX
-	ld hl, vTiles0 tile $74
-	lb bc, BANK(TradeCableGFX), 4
-	call Request2bpp
-	xor a
-	ld hl, wSpriteAnimDict
-	ld [hli], a
-	ld [hl], $62
-	ret
-
-; 2985a
-
-LoadTradeBubbleGFX: ; 2985a
-	call DelayFrame
-	ld e, $3
-	callfar LoadMenuMonIcon
-	ld de, TradeBubbleGFX
-	ld hl, vTiles0 tile $72
-	lb bc, BANK(TradeBubbleGFX), 4
-	call Request2bpp
-	xor a
-	ld hl, wSpriteAnimDict
-	ld [hli], a
-	ld [hl], $62
-	ret
-
-; 29879
-
-TradeAnim_WaitAnim: ; 29879
-	ld hl, wFrameCounter
-	ld a, [hl]
-	and a
-	jr z, .done
-	dec [hl]
-	ret
-
-.done
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 29886
-
-TradeAnim_WaitAnim2: ; 29886
-	ld hl, wFrameCounter
-	ld a, [hl]
-	and a
-	jr z, .done
-	dec [hl]
-	ret
-
-.done
-	call TradeAnim_AdvanceScriptPointer
-	ret
-
-; 29893
-
-
-Unreferenced_DebugTrade: ; 29893
-; This function is not referenced.
-; It was meant for use in Japanese versions, so the
-; constant used for copy length was changed by accident.
-
-	ld hl, .DebugTradeData
-
-	ld a, [hli]
-	ld [wPlayerTrademonSpecies], a
-	ld de, wPlayerTrademonSenderName
-	ld c, NAME_LENGTH + 2 ; JP: NAME_LENGTH_JAPANESE + 2
-.loop1
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec c
-	jr nz, .loop1
-
-	ld a, [hli]
-	ld [wOTTrademonSpecies], a
-	ld de, wOTTrademonSenderName
-	ld c, NAME_LENGTH + 2 ; JP: NAME_LENGTH_JAPANESE + 2
-.loop2
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec c
-	jr nz, .loop2
-	ret
-
-; 298b5
-
-debugtrade: MACRO
-; species, ot name, ot id (?)
-	db \1, \2
-	dw \3
-ENDM
-
-.DebugTradeData: ; 298b5
-	debugtrade VENUSAUR, "ゲーフり@@", $0123 ; GAME FREAK
-	debugtrade CHARIZARD, "クりーチャ@", $0456 ; Creatures Inc.
-; 298c7
-
-
-TradeGameBoyTilemap: ; 298c7
-; 6x8
-	db $31, $32, $32, $32, $32, $33
-	db $34, $35, $36, $36, $37, $38
-	db $34, $39, $3a, $3a, $3b, $38
-	db $3c, $3d, $3e, $3e, $3f, $40
-	db $41, $42, $43, $43, $44, $45
-	db $46, $47, $43, $48, $49, $4a
-	db $41, $43, $4b, $4c, $4d, $4e
-	db $4f, $50, $50, $50, $51, $52
-; 297f7
-
-TradeLinkTubeTilemap: ; 297f7
-; 12x3
-	db $43, $55, $56, $53, $53, $53, $53, $53, $53, $53, $53, $53
-	db $43, $57, $58, $54, $54, $54, $54, $54, $54, $54, $54, $54
-	db $43, $59, $5a, $43, $43, $43, $43, $43, $43, $43, $43, $43
-; 2991b
-
-TradeArrowGFX:  INCBIN "gfx/trade/arrow.2bpp"
-TradeCableGFX:  INCBIN "gfx/trade/cable.2bpp"
-TradeBubbleGFX: INCBIN "gfx/trade/bubble.2bpp"
-TradeGameBoyLZ: INCBIN "gfx/trade/game_boy.2bpp.lz"
-TradeBallGFX:   INCBIN "gfx/trade/ball.2bpp"
-TradePoofGFX:   INCBIN "gfx/trade/poof.2bpp"
--- a/engine/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"
--- a/engine/types.asm
+++ /dev/null
@@ -1,99 +1,0 @@
-PrintMonTypes: ; 5090d
-; Print one or both types of [wCurSpecies]
-; on the stats screen at hl.
-
-	push hl
-	call GetBaseData
-	pop hl
-
-	push hl
-	ld a, [wBaseType1]
-	call .Print
-
-	; Single-typed monsters really
-	; have two of the same type.
-	ld a, [wBaseType1]
-	ld b, a
-	ld a, [wBaseType2]
-	cp b
-	pop hl
-	jr z, .hide_type_2
-
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-
-.Print:
-	ld b, a
-	jr PrintType
-
-.hide_type_2
-	; Erase any type name that was here before.
-	; Seems to be pointless in localized versions.
-	ld a, " "
-	ld bc, SCREEN_WIDTH - 3
-	add hl, bc
-	ld [hl], a
-	inc bc
-	add hl, bc
-	ld bc, NAME_LENGTH_JAPANESE - 1
-	jp ByteFill
-; 5093a
-
-
-PrintMoveType: ; 5093a
-; Print the type of move b at hl.
-
-	push hl
-	ld a, b
-	dec a
-	ld bc, MOVE_LENGTH
-	ld hl, Moves
-	call AddNTimes
-	ld de, wStringBuffer1
-	ld a, BANK(Moves)
-	call FarCopyBytes
-	ld a, [wStringBuffer1 + MOVE_TYPE]
-	pop hl
-
-	ld b, a
-
-
-PrintType: ; 50953
-; Print type b at hl.
-
-	ld a, b
-
-	push hl
-	add a
-	ld hl, TypeNames
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld a, [hli]
-	ld e, a
-	ld d, [hl]
-	pop hl
-
-	jp PlaceString
-; 50964
-
-
-GetTypeName: ; 50964
-; Copy the name of type [wd265] to wStringBuffer1.
-
-	ld a, [wd265]
-	ld hl, TypeNames
-	ld e, a
-	ld d, 0
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, wStringBuffer1
-	ld bc, MOVE_NAME_LENGTH
-	jp CopyBytes
-; 5097b
-
-
-INCLUDE "data/types/names.asm"
--- a/engine/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"
--- a/engine/unused_title.asm
+++ /dev/null
@@ -1,178 +1,0 @@
-UnusedTitleScreen: ; 10c000
-
-	call ClearBGPalettes
-	call ClearTileMap
-	call DisableLCD
-
-; Turn BG Map update off
-	xor a
-	ld [hBGMapMode], a
-
-; Reset timing variables
-	ld hl, wJumptableIndex
-	ld [hli], a ; wJumptableIndex
-	ld [hli], a ; wIntroSceneFrameCounter
-	ld [hli], a ; wTitleScreenTimer
-	ld [hl], a  ; wTitleScreenTimer + 1
-
-	ld hl, UnusedTitleBG_GFX
-	ld de, vTiles2
-	ld bc, vBGMap0 - vTiles2
-	call CopyBytes
-
-	ld hl, UnusedTitleBG_GFX + $80 tiles
-	ld de, vTiles1
-	ld bc, vTiles2 - vTiles1
-	call CopyBytes
-
-	ld hl, UnusedTitleFG_GFX
-	ld de, vTiles0
-	ld bc, vTiles1 - vTiles0
-	call CopyBytes
-
-	ld hl, UnusedTitleBG_Tilemap
-	debgcoord 0, 0
-	ld bc, BG_MAP_WIDTH * BG_MAP_HEIGHT
-.copy
-	ld a, 0
-	ld [rVBK], a
-	ld a, [hli]
-	ld [de], a
-	ld a, 1
-	ld [rVBK], a
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec bc
-	ld a, b
-	or c
-	jr nz, .copy
-
-	ld hl, UnusedTitleFG_OAM
-	ld de, wVirtualOAMSprite00
-	ld bc, SPRITEOAMSTRUCT_LENGTH * NUM_SPRITE_OAM_STRUCTS
-	call CopyBytes
-
-	call EnableLCD
-	ld a, [rLCDC]
-	set rLCDC_SPRITES_ENABLE, a
-	set rLCDC_SPRITE_SIZE, a
-	ld [rLCDC], a
-
-	call DelayFrame
-
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-
-	ld hl, UnusedTitleBG_Palettes
-	ld de, wBGPals1
-	ld bc, 8 palettes
-	call CopyBytes
-
-	ld hl, UnusedTitleFG_Palettes
-	ld de, wOBPals1
-	ld bc, 8 palettes
-	call CopyBytes
-
-	ld hl, UnusedTitleBG_Palettes
-	ld de, wBGPals2
-	ld bc, 8 palettes
-	call CopyBytes
-
-	ld hl, UnusedTitleFG_Palettes
-	ld de, wOBPals2
-	ld bc, 8 palettes
-	call CopyBytes
-
-	pop af
-	ld [rSVBK], a
-
-	ld a, $1
-	ld [hCGBPalUpdate], a
-
-	ld de, MUSIC_TITLE
-	call PlayMusic
-
-	ret
-; 10c0b1
-
-UnusedTitleBG_GFX: ; 10c0b1
-INCBIN "gfx/title/old_bg.2bpp"
-; 10d0b1
-
-UnusedTitleBG_Tilemap: ; 10d0b1
-; 32x32 (alternating tiles and attributes)
-INCBIN "gfx/title/old_bg.tilemap"
-; 10d8b1
-
-UnusedTitleBG_Palettes: ; 10d8b1
-INCLUDE "gfx/title/old_bg.pal"
-; 10dab1
-
-UnusedTitleFG_GFX: ; 10dab1
-INCBIN "gfx/title/old_fg.2bpp"
-; 10eab1
-
-UnusedTitleFG_Palettes: ; 10eab1
-INCLUDE "gfx/title/old_fg.pal"
-; 10ecb1
-
-UnusedTitleFG_OAM: ; 10ecb1
-	dsprite  3,  0,  7,  0, $00, 1
-	dsprite  3,  0,  8,  0, $02, 1
-	dsprite  3,  0,  9,  0, $04, 1
-	dsprite  3,  0, 10,  0, $06, 1
-	dsprite  3,  0, 11,  0, $08, 1
-	dsprite  3,  0, 12,  0, $0a, 1
-	dsprite  3,  0, 13,  0, $0c, 1
-	dsprite  3,  0, 14,  0, $0e, 1
-	dsprite  5,  0,  7,  0, $10, 0
-	dsprite  5,  0,  8,  0, $12, 0
-	dsprite  5,  0,  9,  0, $14, 0
-	dsprite  5,  0, 10,  0, $16, 0
-	dsprite  5,  0, 11,  0, $18, 0
-	dsprite  5,  0, 12,  0, $1a, 0
-	dsprite  5,  0, 13,  0, $1c, 0
-	dsprite  5,  0, 14,  0, $1e, 0
-	dsprite  7,  0,  7,  0, $20, 0
-	dsprite  7,  0,  8,  0, $22, 0
-	dsprite  7,  0,  9,  0, $24, 0
-	dsprite  7,  0, 10,  0, $26, 0
-	dsprite  7,  0, 11,  0, $28, 0
-	dsprite  7,  0, 12,  0, $2a, 0
-	dsprite  7,  0, 13,  0, $2c, 0
-	dsprite  7,  0, 14,  0, $2e, 0
-	dsprite  9,  0,  7,  0, $30, 2
-	dsprite  9,  0,  8,  0, $32, 2
-	dsprite  9,  0,  9,  0, $34, 2
-	dsprite  9,  0, 10,  0, $36, 2
-	dsprite  9,  0, 11,  0, $38, 2
-	dsprite  9,  0, 12,  0, $3a, 2
-	dsprite  9,  0, 13,  0, $3c, 2
-	dsprite  9,  0, 14,  0, $3e, 2
-	dsprite 11,  0,  7,  0, $40, 1
-	dsprite 11,  0,  8,  0, $42, 1
-	dsprite 11,  0,  9,  0, $44, 1
-	dsprite 11,  0, 10,  0, $46, 1
-	dsprite 11,  0, 11,  0, $48, 1
-	dsprite 11,  0, 12,  0, $4a, 1
-	dsprite 11,  0, 13,  0, $4c, 1
-	dsprite 11,  0, 14,  0, $4e, 1
-; 10ed51
-
-Function10ed51: ; 10ed51
-	call _TitleScreen
-.loop
-	call JoyTextDelay
-	ld a, [hJoyLast]
-	ld b, a
-	and 1
-	jr nz, .done
-	call SuicuneFrameIterator
-	call DelayFrame
-	jr .loop
-.done
-	ret
-; 10ed67
--- a/engine/variables.asm
+++ /dev/null
@@ -1,151 +1,0 @@
-_GetVarAction:: ; 80648 (20:4648)
-	ld a, c
-	cp NUM_VARS
-	jr c, .valid
-	xor a
-.valid
-	ld c, a
-	ld b, 0
-	ld hl, .VarActionTable
-	add hl, bc
-	add hl, bc
-	add hl, bc
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	inc hl
-	ld b, [hl]
-	ld a, b
-	and RETVAR_EXECUTE
-	jr nz, .call
-	ld a, b
-	and RETVAR_ADDR_DE
-	ret nz
-	ld a, [de]
-	jr .loadstringbuffer2
-
-.call
-	call _de_
-	ret
-
-.loadstringbuffer2 ; 8066c (20:466c)
-	ld de, wStringBuffer2
-	ld [de], a
-	ret
-; 80671 (20:4671)
-
-.VarActionTable: ; 80671
-; entries correspond to VAR_* constants
-	; RETVAR_STRBUF2: copy [de] to wStringBuffer2
-	; RETVAR_ADDR_DE: return address in de
-	; RETVAR_EXECUTE: call function
-	dwb wStringBuffer2,                 RETVAR_STRBUF2
-	dwb wPartyCount,                    RETVAR_STRBUF2
-	dwb .BattleResult,                  RETVAR_EXECUTE
-	dwb wBattleType,                    RETVAR_ADDR_DE
-	dwb wTimeOfDay,                     RETVAR_STRBUF2
-	dwb .CountCaughtMons,               RETVAR_EXECUTE
-	dwb .CountSeenMons,                 RETVAR_EXECUTE
-	dwb .CountBadges,                   RETVAR_EXECUTE
-	dwb wPlayerState,                   RETVAR_ADDR_DE
-	dwb .PlayerFacing,                  RETVAR_EXECUTE
-	dwb hHours,                         RETVAR_STRBUF2
-	dwb .DayOfWeek,                     RETVAR_EXECUTE
-	dwb wMapGroup,                      RETVAR_STRBUF2
-	dwb wMapNumber,                     RETVAR_STRBUF2
-	dwb .UnownCaught,                   RETVAR_EXECUTE
-	dwb wEnvironment,                   RETVAR_STRBUF2
-	dwb .BoxFreeSpace,                  RETVAR_EXECUTE
-	dwb wBugContestMinsRemaining,       RETVAR_STRBUF2
-	dwb wXCoord,                        RETVAR_STRBUF2
-	dwb wYCoord,                        RETVAR_STRBUF2
-	dwb wSpecialPhoneCallID,            RETVAR_STRBUF2
-	dwb wNrOfBeatenBattleTowerTrainers, RETVAR_STRBUF2
-	dwb wKurtApricornQuantity,          RETVAR_STRBUF2
-	dwb wCurrentCaller,                 RETVAR_ADDR_DE
-	dwb wBlueCardBalance,               RETVAR_ADDR_DE
-	dwb wBuenasPassword,                RETVAR_ADDR_DE
-	dwb wKenjiBreakTimer,               RETVAR_STRBUF2
-	dwb NULL,                           RETVAR_STRBUF2
-; 806c5
-
-.CountCaughtMons: ; 806c5
-; Caught mons.
-	ld hl, wPokedexCaught
-	ld b, wEndPokedexCaught - wPokedexCaught
-	call CountSetBits
-	ld a, [wd265]
-	jp .loadstringbuffer2
-; 806d3
-
-.CountSeenMons: ; 806d3
-; Seen mons.
-	ld hl, wPokedexSeen
-	ld b, wEndPokedexSeen - wPokedexSeen
-	call CountSetBits
-	ld a, [wd265]
-	jp .loadstringbuffer2
-; 806e1
-
-.CountBadges: ; 806e1
-; Number of owned badges.
-	ld hl, wBadges
-	ld b, 2
-	call CountSetBits
-	ld a, [wd265]
-	jp .loadstringbuffer2
-; 806ef
-
-.PlayerFacing: ; 806ef
-; The direction the player is facing.
-	ld a, [wPlayerDirection]
-	and $c
-	rrca
-	rrca
-	jp .loadstringbuffer2
-; 806f9
-
-.DayOfWeek: ; 806f9
-; The day of the week.
-	call GetWeekday
-	jp .loadstringbuffer2
-; 806ff
-
-.UnownCaught: ; 806ff
-; Number of unique Unown caught.
-	call .count
-	ld a, b
-	jp .loadstringbuffer2
-
-.count
-	ld hl, wUnownDex
-	ld b, 0
-.loop
-	ld a, [hli]
-	and a
-	ret z
-	inc b
-	ld a, b
-	cp NUM_UNOWN
-	jr c, .loop
-	ret
-; 80715
-
-.BoxFreeSpace: ; 80715
-; Remaining slots in the current box.
-	ld a, BANK(sBoxCount)
-	call GetSRAMBank
-	ld hl, sBoxCount
-	ld a, MONS_PER_BOX
-	sub [hl]
-	ld b, a
-	call CloseSRAM
-	ld a, b
-	jp .loadstringbuffer2
-; 80728
-
-.BattleResult: ; 80728
-	ld a, [wBattleResult]
-	and $3f
-	jp .loadstringbuffer2
-; 80730
--- a/engine/warp_connection.asm
+++ /dev/null
@@ -1,439 +1,0 @@
-
-HandleNewMap: ; 1045b0
-	call Clearwc7e8
-	call ResetMapBufferEventFlags
-	call ResetFlashIfOutOfCave
-	call GetCurrentMapSceneID
-	call ResetBikeFlags
-	ld a, MAPCALLBACK_NEWMAP
-	call RunMapCallback
-InitCommandQueue: ; 1045c4
-	farcall ClearCmdQueue
-	ld a, MAPCALLBACK_CMDQUEUE
-	call RunMapCallback
-	call GetMapTimeOfDay
-	ld [wMapTimeOfDay], a
-	ret
-
-
-EnterMapConnection: ; 1045d6
-; Return carry if a connection has been entered.
-	ld a, [wPlayerStepDirection]
-	and a
-	jp z, .south
-	cp UP
-	jp z, .north
-	cp LEFT
-	jp z, .west
-	cp RIGHT
-	jp z, .east
-	ret
-
-.west
-	ld a, [wWestConnectedMapGroup]
-	ld [wMapGroup], a
-	ld a, [wWestConnectedMapNumber]
-	ld [wMapNumber], a
-	ld a, [wWestConnectionStripXOffset]
-	ld [wXCoord], a
-	ld a, [wWestConnectionStripYOffset]
-	ld hl, wYCoord
-	add [hl]
-	ld [hl], a
-	ld c, a
-	ld hl, wWestConnectionWindow
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	srl c
-	jr z, .skip_to_load
-	ld a, [wWestConnectedMapWidth]
-	add 6
-	ld e, a
-	ld d, 0
-
-.loop
-	add hl, de
-	dec c
-	jr nz, .loop
-
-.skip_to_load
-	ld a, l
-	ld [wOverworldMapAnchor], a
-	ld a, h
-	ld [wOverworldMapAnchor + 1], a
-	jp .done
-
-.east
-	ld a, [wEastConnectedMapGroup]
-	ld [wMapGroup], a
-	ld a, [wEastConnectedMapNumber]
-	ld [wMapNumber], a
-	ld a, [wEastConnectionStripXOffset]
-	ld [wXCoord], a
-	ld a, [wEastConnectionStripYOffset]
-	ld hl, wYCoord
-	add [hl]
-	ld [hl], a
-	ld c, a
-	ld hl, wEastConnectionWindow
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	srl c
-	jr z, .skip_to_load2
-	ld a, [wEastConnectedMapWidth]
-	add 6
-	ld e, a
-	ld d, 0
-
-.loop2
-	add hl, de
-	dec c
-	jr nz, .loop2
-
-.skip_to_load2
-	ld a, l
-	ld [wOverworldMapAnchor], a
-	ld a, h
-	ld [wOverworldMapAnchor + 1], a
-	jp .done
-
-.north
-	ld a, [wNorthConnectedMapGroup]
-	ld [wMapGroup], a
-	ld a, [wNorthConnectedMapNumber]
-	ld [wMapNumber], a
-	ld a, [wNorthConnectionStripYOffset]
-	ld [wYCoord], a
-	ld a, [wNorthConnectionStripXOffset]
-	ld hl, wXCoord
-	add [hl]
-	ld [hl], a
-	ld c, a
-	ld hl, wNorthConnectionWindow
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld b, 0
-	srl c
-	add hl, bc
-	ld a, l
-	ld [wOverworldMapAnchor], a
-	ld a, h
-	ld [wOverworldMapAnchor + 1], a
-	jp .done
-
-.south
-	ld a, [wSouthConnectedMapGroup]
-	ld [wMapGroup], a
-	ld a, [wSouthConnectedMapNumber]
-	ld [wMapNumber], a
-	ld a, [wSouthConnectionStripYOffset]
-	ld [wYCoord], a
-	ld a, [wSouthConnectionStripXOffset]
-	ld hl, wXCoord
-	add [hl]
-	ld [hl], a
-	ld c, a
-	ld hl, wSouthConnectionWindow
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld b, 0
-	srl c
-	add hl, bc
-	ld a, l
-	ld [wOverworldMapAnchor], a
-	ld a, h
-	ld [wOverworldMapAnchor + 1], a
-.done
-	scf
-	ret
-; 1046c6
-
-LoadWarpData: ; 1046c6
-	call .SaveDigWarp
-	call .SetSpawn
-	ld a, [wNextWarp]
-	ld [wWarpNumber], a
-	ld a, [wNextMapGroup]
-	ld [wMapGroup], a
-	ld a, [wNextMapNumber]
-	ld [wMapNumber], a
-	ret
-
-.SaveDigWarp: ; 1046df (41:46df)
-	call GetMapEnvironment
-	call CheckOutdoorMap
-	ret nz
-	ld a, [wNextMapGroup]
-	ld b, a
-	ld a, [wNextMapNumber]
-	ld c, a
-	call GetAnyMapEnvironment
-	call CheckIndoorMap
-	ret nz
-
-; MOUNT_MOON_SQUARE and TIN_TOWER_ROOF are outdoor maps within indoor maps.
-; Dig and Escape Rope should not take you to them.
-	ld a, [wPrevMapGroup]
-	cp GROUP_MOUNT_MOON_SQUARE ; GROUP_TIN_TOWER_ROOF
-	jr nz, .not_mt_moon_or_tin_tower
-	ld a, [wPrevMapNumber]
-	cp MAP_MOUNT_MOON_SQUARE
-	ret z
-	cp MAP_TIN_TOWER_ROOF
-	ret z
-.not_mt_moon_or_tin_tower
-
-	ld a, [wPrevWarp]
-	ld [wDigWarpNumber], a
-	ld a, [wPrevMapGroup]
-	ld [wDigMapGroup], a
-	ld a, [wPrevMapNumber]
-	ld [wDigMapNumber], a
-	ret
-
-.SetSpawn: ; 104718 (41:4718)
-	call GetMapEnvironment
-	call CheckOutdoorMap
-	ret nz
-	ld a, [wNextMapGroup]
-	ld b, a
-	ld a, [wNextMapNumber]
-	ld c, a
-	call GetAnyMapEnvironment
-	call CheckIndoorMap
-	ret nz
-	ld a, [wNextMapGroup]
-	ld b, a
-	ld a, [wNextMapNumber]
-	ld c, a
-
-; Respawn in Pokémon Centers.
-	call GetAnyMapTileset
-	ld a, c
-	cp TILESET_POKECENTER
-	jr z, .pokecenter_pokecom
-	cp TILESET_POKECOM_CENTER
-	jr z, .pokecenter_pokecom
-	ret
-.pokecenter_pokecom
-
-	ld a, [wPrevMapGroup]
-	ld [wLastSpawnMapGroup], a
-	ld a, [wPrevMapNumber]
-	ld [wLastSpawnMapNumber], a
-	ret
-
-LoadMapTimeOfDay: ; 104750
-	ld hl, wVramState
-	res 6, [hl]
-	ld a, $1
-	ld [wSpriteUpdatesEnabled], a
-	farcall ReplaceTimeOfDayPals
-	farcall UpdateTimeOfDayPal
-	call OverworldTextModeSwitch
-	call .ClearBGMap
-	call .PushAttrMap
-	ret
-
-.ClearBGMap: ; 104770 (41:4770)
-	ld a, HIGH(vBGMap0)
-	ld [wBGMapAnchor + 1], a
-	xor a ; LOW(vBGMap0)
-	ld [wBGMapAnchor], a
-	ld [hSCY], a
-	ld [hSCX], a
-	farcall ApplyBGMapAnchorToObjects
-
-	ld a, [rVBK]
-	push af
-	ld a, $1
-	ld [rVBK], a
-
-	xor a
-	ld bc, vBGMap1 - vBGMap0
-	hlbgcoord 0, 0
-	call ByteFill
-
-	pop af
-	ld [rVBK], a
-
-	ld a, "■"
-	ld bc, vBGMap1 - vBGMap0
-	hlbgcoord 0, 0
-	call ByteFill
-	ret
-
-.PushAttrMap: ; 1047a3 (41:47a3)
-	decoord 0, 0
-	call .copy
-	ld a, [hCGB]
-	and a
-	ret z
-
-	decoord 0, 0, wAttrMap
-	ld a, $1
-	ld [rVBK], a
-.copy
-	hlbgcoord 0, 0
-	ld c, SCREEN_WIDTH
-	ld b, SCREEN_HEIGHT
-.row
-	push bc
-.column
-	ld a, [de]
-	inc de
-	ld [hli], a
-	dec c
-	jr nz, .column
-	ld bc, BG_MAP_WIDTH - SCREEN_WIDTH
-	add hl, bc
-	pop bc
-	dec b
-	jr nz, .row
-	ld a, $0
-	ld [rVBK], a
-	ret
-
-LoadGraphics: ; 1047cf
-	call LoadTileset
-	call LoadTilesetGFX
-	xor a
-	ld [hMapAnims], a
-	xor a
-	ld [hTileAnimFrame], a
-	farcall RefreshSprites
-	call LoadFontsExtra
-	farcall LoadOverworldFont
-	ret
-
-LoadMapPalettes: ; 1047eb
-	ld b, SCGB_MAPPALS
-	jp GetSGBLayout
-; 1047f0
-
-RefreshMapSprites: ; 1047f0
-	call ClearSprites
-	farcall ReturnFromMapSetupScript
-	call GetMovementPermissions
-	farcall RefreshPlayerSprite
-	farcall CheckReplaceKrisSprite
-	ld hl, wPlayerSpriteSetupFlags
-	bit PLAYERSPRITESETUP_SKIP_RELOAD_GFX_F, [hl]
-	jr nz, .skip
-	ld hl, wVramState
-	set 0, [hl]
-	call SafeUpdateSprites
-.skip
-	ld a, [wPlayerSpriteSetupFlags]
-	and %00011100
-	ld [wPlayerSpriteSetupFlags], a
-	ret
-
-CheckMovingOffEdgeOfMap:: ; 104820 (41:4820)
-	ld a, [wPlayerStepDirection]
-	cp STANDING
-	ret z
-	and a ; DOWN
-	jr z, .down
-	cp UP
-	jr z, .up
-	cp LEFT
-	jr z, .left
-	cp RIGHT
-	jr z, .right
-	and a
-	ret
-
-.down
-	ld a, [wPlayerStandingMapY]
-	sub 4
-	ld b, a
-	ld a, [wMapHeight]
-	add a
-	cp b
-	jr z, .ok
-	and a
-	ret
-
-.up
-	ld a, [wPlayerStandingMapY]
-	sub 4
-	cp -1
-	jr z, .ok
-	and a
-	ret
-
-.left
-	ld a, [wPlayerStandingMapX]
-	sub 4
-	cp -1
-	jr z, .ok
-	and a
-	ret
-
-.right
-	ld a, [wPlayerStandingMapX]
-	sub 4
-	ld b, a
-	ld a, [wMapWidth]
-	add a
-	cp b
-	jr z, .ok
-	and a
-	ret
-
-.ok
-	scf
-	ret
-
-
-GetCoordOfUpperLeftCorner:: ; 10486d
-	ld hl, wOverworldMap
-	ld a, [wXCoord]
-	bit 0, a
-	jr nz, .increment_then_halve1
-	srl a
-	add $1
-	jr .resume
-
-.increment_then_halve1
-	add $1
-	srl a
-
-.resume
-	ld c, a
-	ld b, $0
-	add hl, bc
-	ld a, [wMapWidth]
-	add $6
-	ld c, a
-	ld b, $0
-	ld a, [wYCoord]
-	bit 0, a
-	jr nz, .increment_then_halve2
-	srl a
-	add $1
-	jr .resume2
-
-.increment_then_halve2
-	add $1
-	srl a
-
-.resume2
-	call AddNTimes
-	ld a, l
-	ld [wOverworldMapAnchor], a
-	ld a, h
-	ld [wOverworldMapAnchor + 1], a
-	ld a, [wYCoord]
-	and $1
-	ld [wMetatileStandingY], a
-	ld a, [wXCoord]
-	and $1
-	ld [wMetatileStandingX], a
-	ret
-; 1048ba
--- a/engine/wildmons.asm
+++ /dev/null
@@ -1,1000 +1,0 @@
-LoadWildMonData: ; 29ff8
-	call _GrassWildmonLookup
-	jr c, .copy
-	ld hl, wMornEncounterRate
-	xor a
-	ld [hli], a
-	ld [hli], a
-	ld [hl], a
-	jr .done_copy
-
-.copy
-	inc hl
-	inc hl
-	ld de, wMornEncounterRate
-	ld bc, 3
-	call CopyBytes
-.done_copy
-	call _WaterWildmonLookup
-	ld a, 0
-	jr nc, .no_copy
-	inc hl
-	inc hl
-	ld a, [hl]
-.no_copy
-	ld [wWaterEncounterRate], a
-	ret
-
-FindNest: ; 2a01f
-; Parameters:
-; e: 0 = Johto, 1 = Kanto
-; wNamedObjectIndexBuffer: species
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	xor a
-	call ByteFill
-	ld a, e
-	and a
-	jr nz, .kanto
-	decoord 0, 0
-	ld hl, JohtoGrassWildMons
-	call .FindGrass
-	ld hl, JohtoWaterWildMons
-	call .FindWater
-	call .RoamMon1
-	call .RoamMon2
-	ret
-
-.kanto
-	decoord 0, 0
-	ld hl, KantoGrassWildMons
-	call .FindGrass
-	ld hl, KantoWaterWildMons
-	jp .FindWater
-; 2a052
-
-.FindGrass: ; 2a052
-	ld a, [hl]
-	cp -1
-	ret z
-	push hl
-	ld a, [hli]
-	ld b, a
-	ld a, [hli]
-	ld c, a
-	inc hl
-	inc hl
-	inc hl
-	ld a, NUM_GRASSMON * 3
-	call .SearchMapForMon
-	jr nc, .next_grass
-	ld [de], a
-	inc de
-
-.next_grass
-	pop hl
-	ld bc, GRASS_WILDDATA_LENGTH
-	add hl, bc
-	jr .FindGrass
-; 2a06e
-
-.FindWater: ; 2a06e
-	ld a, [hl]
-	cp -1
-	ret z
-	push hl
-	ld a, [hli]
-	ld b, a
-	ld a, [hli]
-	ld c, a
-	inc hl
-	ld a, 3
-	call .SearchMapForMon
-	jr nc, .next_water
-	ld [de], a
-	inc de
-
-.next_water
-	pop hl
-	ld bc, 3 * 3
-	add hl, bc
-	jr .FindWater
-; 2a088
-
-.SearchMapForMon: ; 2a088
-	inc hl
-.ScanMapLoop:
-	push af
-	ld a, [wNamedObjectIndexBuffer]
-	cp [hl]
-	jr z, .found
-	inc hl
-	inc hl
-	pop af
-	dec a
-	jr nz, .ScanMapLoop
-	and a
-	ret
-
-.found
-	pop af
-	jp .AppendNest
-; 2a09c
-
-.AppendNest: ; 2a09c
-	push de
-	call GetWorldMapLocation
-	ld c, a
-	hlcoord 0, 0
-	ld de, SCREEN_WIDTH * SCREEN_HEIGHT
-.AppendNestLoop:
-	ld a, [hli]
-	cp c
-	jr z, .found_nest
-	dec de
-	ld a, e
-	or d
-	jr nz, .AppendNestLoop
-	ld a, c
-	pop de
-	scf
-	ret
-
-.found_nest
-	pop de
-	and a
-	ret
-; 2a0b7
-
-.RoamMon1: ; 2a0b7
-	ld a, [wRoamMon1Species]
-	ld b, a
-	ld a, [wNamedObjectIndexBuffer]
-	cp b
-	ret nz
-	ld a, [wRoamMon1MapGroup]
-	ld b, a
-	ld a, [wRoamMon1MapNumber]
-	ld c, a
-	call .AppendNest
-	ret nc
-	ld [de], a
-	inc de
-	ret
-; 2a0cf
-
-.RoamMon2: ; 2a0cf
-	ld a, [wRoamMon2Species]
-	ld b, a
-	ld a, [wNamedObjectIndexBuffer]
-	cp b
-	ret nz
-	ld a, [wRoamMon2MapGroup]
-	ld b, a
-	ld a, [wRoamMon2MapNumber]
-	ld c, a
-	call .AppendNest
-	ret nc
-	ld [de], a
-	inc de
-	ret
-; 2a0e7
-
-TryWildEncounter:: ; 2a0e7
-; Try to trigger a wild encounter.
-	call .EncounterRate
-	jr nc, .no_battle
-	call ChooseWildEncounter
-	jr nz, .no_battle
-	call CheckRepelEffect
-	jr nc, .no_battle
-	xor a
-	ret
-
-.no_battle
-	xor a ; BATTLETYPE_NORMAL
-	ld [wTempWildMonSpecies], a
-	ld [wBattleType], a
-	ld a, 1
-	and a
-	ret
-; 2a103
-
-.EncounterRate: ; 2a103
-	call GetMapEncounterRate
-	call ApplyMusicEffectOnEncounterRate
-	call ApplyCleanseTagEffectOnEncounterRate
-	call Random
-	cp b
-	ret
-; 2a111
-
-GetMapEncounterRate: ; 2a111
-	ld hl, wMornEncounterRate
-	call CheckOnWater
-	ld a, wWaterEncounterRate - wMornEncounterRate
-	jr z, .ok
-	ld a, [wTimeOfDay]
-.ok
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld b, [hl]
-	ret
-; 2a124
-
-ApplyMusicEffectOnEncounterRate:: ; 2a124
-; Pokemon March and Ruins of Alph signal double encounter rate.
-; Pokemon Lullaby halves encounter rate.
-	ld a, [wMapMusic]
-	cp MUSIC_POKEMON_MARCH
-	jr z, .double
-	cp MUSIC_RUINS_OF_ALPH_RADIO
-	jr z, .double
-	cp MUSIC_POKEMON_LULLABY
-	ret nz
-	srl b
-	ret
-
-.double
-	sla b
-	ret
-; 2a138
-
-ApplyCleanseTagEffectOnEncounterRate:: ; 2a138
-; Cleanse Tag halves encounter rate.
-	ld hl, wPartyMon1Item
-	ld de, PARTYMON_STRUCT_LENGTH
-	ld a, [wPartyCount]
-	ld c, a
-.loop
-	ld a, [hl]
-	cp CLEANSE_TAG
-	jr z, .cleansetag
-	add hl, de
-	dec c
-	jr nz, .loop
-	ret
-
-.cleansetag
-	srl b
-	ret
-; 2a14f
-
-ChooseWildEncounter: ; 2a14f
-	call LoadWildMonDataPointer
-	jp nc, .nowildbattle
-	call CheckEncounterRoamMon
-	jp c, .startwildbattle
-
-	inc hl
-	inc hl
-	inc hl
-	call CheckOnWater
-	ld de, WaterMonProbTable
-	jr z, .watermon
-	inc hl
-	inc hl
-	ld a, [wTimeOfDay]
-	ld bc, $e
-	call AddNTimes
-	ld de, GrassMonProbTable
-
-.watermon
-; hl contains the pointer to the wild mon data, let's save that to the stack
-	push hl
-.randomloop
-	call Random
-	cp 100
-	jr nc, .randomloop
-	inc a ; 1 <= a <= 100
-	ld b, a
-	ld h, d
-	ld l, e
-; This next loop chooses which mon to load up.
-.prob_bracket_loop
-	ld a, [hli]
-	cp b
-	jr nc, .got_it
-	inc hl
-	jr .prob_bracket_loop
-
-.got_it
-	ld c, [hl]
-	ld b, 0
-	pop hl
-	add hl, bc ; this selects our mon
-	ld a, [hli]
-	ld b, a
-; If the Pokemon is encountered by surfing, we need to give the levels some variety.
-	call CheckOnWater
-	jr nz, .ok
-; Check if we buff the wild mon, and by how much.
-	call Random
-	cp 35 percent
-	jr c, .ok
-	inc b
-	cp 65 percent
-	jr c, .ok
-	inc b
-	cp 85 percent
-	jr c, .ok
-	inc b
-	cp 95 percent
-	jr c, .ok
-	inc b
-; Store the level
-.ok
-	ld a, b
-	ld [wCurPartyLevel], a
-	ld b, [hl]
-	; ld a, b
-	call ValidateTempWildMonSpecies
-	jr c, .nowildbattle
-
-	ld a, b ; This is in the wrong place.
-	cp UNOWN
-	jr nz, .done
-
-	ld a, [wUnlockedUnowns]
-	and a
-	jr z, .nowildbattle
-
-.done
-	jr .loadwildmon
-
-.nowildbattle
-	ld a, 1
-	and a
-	ret
-
-.loadwildmon
-	ld a, b
-	ld [wTempWildMonSpecies], a
-
-.startwildbattle
-	xor a
-	ret
-; 2a1cb
-
-INCLUDE "data/wild/probabilities.asm"
-
-CheckRepelEffect:: ; 2a1df
-; If there is no active Repel, there's no need to be here.
-	ld a, [wRepelEffect]
-	and a
-	jr z, .encounter
-; Get the first Pokemon in your party that isn't fainted.
-	ld hl, wPartyMon1HP
-	ld bc, PARTYMON_STRUCT_LENGTH - 1
-.loop
-	ld a, [hli]
-	or [hl]
-	jr nz, .ok
-	add hl, bc
-	jr .loop
-
-.ok
-; to PartyMonLevel
-rept 4
-	dec hl
-endr
-
-	ld a, [wCurPartyLevel]
-	cp [hl]
-	jr nc, .encounter
-	and a
-	ret
-
-.encounter
-	scf
-	ret
-; 2a200
-
-LoadWildMonDataPointer: ; 2a200
-	call CheckOnWater
-	jr z, _WaterWildmonLookup
-
-_GrassWildmonLookup: ; 2a205
-	ld hl, SwarmGrassWildMons
-	ld bc, GRASS_WILDDATA_LENGTH
-	call _SwarmWildmonCheck
-	ret c
-	ld hl, JohtoGrassWildMons
-	ld de, KantoGrassWildMons
-	call _JohtoWildmonCheck
-	ld bc, GRASS_WILDDATA_LENGTH
-	jr _NormalWildmonOK
-
-_WaterWildmonLookup: ; 2a21d
-	ld hl, SwarmWaterWildMons
-	ld bc, WATER_WILDDATA_LENGTH
-	call _SwarmWildmonCheck
-	ret c
-	ld hl, JohtoWaterWildMons
-	ld de, KantoWaterWildMons
-	call _JohtoWildmonCheck
-	ld bc, WATER_WILDDATA_LENGTH
-	jr _NormalWildmonOK
-
-_JohtoWildmonCheck
-	call IsInJohto
-	and a
-	ret z
-	ld h, d
-	ld l, e
-	ret
-
-_SwarmWildmonCheck
-	call CopyCurrMapDE
-	push hl
-	ld hl, wSwarmFlags
-	bit SWARMFLAGS_DUNSPARCE_SWARM_F, [hl]
-	pop hl
-	jr z, .CheckYanma
-	ld a, [wDunsparceMapGroup]
-	cp d
-	jr nz, .CheckYanma
-	ld a, [wDunsparceMapNumber]
-	cp e
-	jr nz, .CheckYanma
-	call LookUpWildmonsForMapDE
-	jr nc, _NoSwarmWildmon
-	scf
-	ret
-
-.CheckYanma:
-	push hl
-	ld hl, wSwarmFlags
-	bit SWARMFLAGS_YANMA_SWARM_F, [hl]
-	pop hl
-	jr z, _NoSwarmWildmon
-	ld a, [wYanmaMapGroup]
-	cp d
-	jr nz, _NoSwarmWildmon
-	ld a, [wYanmaMapNumber]
-	cp e
-	jr nz, _NoSwarmWildmon
-	call LookUpWildmonsForMapDE
-	jr nc, _NoSwarmWildmon
-	scf
-	ret
-
-_NoSwarmWildmon
-	and a
-	ret
-
-_NormalWildmonOK
-	call CopyCurrMapDE
-	jr LookUpWildmonsForMapDE
-; 2a27f
-
-CopyCurrMapDE: ; 2a27f
-	ld a, [wMapGroup]
-	ld d, a
-	ld a, [wMapNumber]
-	ld e, a
-	ret
-; 2a288
-
-LookUpWildmonsForMapDE: ; 2a288
-.loop
-	push hl
-	ld a, [hl]
-	inc a
-	jr z, .nope
-	ld a, d
-	cp [hl]
-	jr nz, .next
-	inc hl
-	ld a, e
-	cp [hl]
-	jr z, .yup
-
-.next
-	pop hl
-	add hl, bc
-	jr .loop
-
-.nope
-	pop hl
-	and a
-	ret
-
-.yup
-	pop hl
-	scf
-	ret
-; 2a2a0
-
-
-InitRoamMons: ; 2a2a0
-; initialize wRoamMon structs
-
-; species
-	ld a, RAIKOU
-	ld [wRoamMon1Species], a
-	ld a, ENTEI
-	ld [wRoamMon2Species], a
-
-; level
-	ld a, 40
-	ld [wRoamMon1Level], a
-	ld [wRoamMon2Level], a
-
-; raikou starting map
-	ld a, GROUP_ROUTE_42
-	ld [wRoamMon1MapGroup], a
-	ld a, MAP_ROUTE_42
-	ld [wRoamMon1MapNumber], a
-
-; entei starting map
-	ld a, GROUP_ROUTE_37
-	ld [wRoamMon2MapGroup], a
-	ld a, MAP_ROUTE_37
-	ld [wRoamMon2MapNumber], a
-
-; hp
-	xor a ; generate new stats
-	ld [wRoamMon1HP], a
-	ld [wRoamMon2HP], a
-
-	ret
-; 2a2ce
-
-
-CheckEncounterRoamMon: ; 2a2ce
-	push hl
-; Don't trigger an encounter if we're on water.
-	call CheckOnWater
-	jr z, .DontEncounterRoamMon
-; Load the current map group and number to de
-	call CopyCurrMapDE
-; Randomly select a beast.
-	call Random
-	cp 100 ; 25/64 chance
-	jr nc, .DontEncounterRoamMon
-	and %00000011 ; Of that, a 3/4 chance.  Running total: 75/256, or around 29.3%.
-	jr z, .DontEncounterRoamMon
-	dec a ; 1/3 chance that it's Entei, 1/3 chance that it's Raikou
-; Compare its current location with yours
-	ld hl, wRoamMon1MapGroup
-	ld c, a
-	ld b, 0
-	ld a, 7 ; length of the roam_struct
-	call AddNTimes
-	ld a, d
-	cp [hl]
-	jr nz, .DontEncounterRoamMon
-	inc hl
-	ld a, e
-	cp [hl]
-	jr nz, .DontEncounterRoamMon
-; We've decided to take on a beast, so stage its information for battle.
-	dec hl
-	dec hl
-	dec hl
-	ld a, [hli]
-	ld [wTempWildMonSpecies], a
-	ld a, [hl]
-	ld [wCurPartyLevel], a
-	ld a, BATTLETYPE_ROAMING
-	ld [wBattleType], a
-
-	pop hl
-	scf
-	ret
-
-.DontEncounterRoamMon:
-	pop hl
-	and a
-	ret
-; 2a30d
-
-
-UpdateRoamMons: ; 2a30d
-	ld a, [wRoamMon1MapGroup]
-	cp GROUP_N_A
-	jr z, .SkipRaikou
-	ld b, a
-	ld a, [wRoamMon1MapNumber]
-	ld c, a
-	call .Update
-	ld a, b
-	ld [wRoamMon1MapGroup], a
-	ld a, c
-	ld [wRoamMon1MapNumber], a
-
-.SkipRaikou:
-	ld a, [wRoamMon2MapGroup]
-	cp GROUP_N_A
-	jr z, .SkipEntei
-	ld b, a
-	ld a, [wRoamMon2MapNumber]
-	ld c, a
-	call .Update
-	ld a, b
-	ld [wRoamMon2MapGroup], a
-	ld a, c
-	ld [wRoamMon2MapNumber], a
-
-.SkipEntei:
-	ld a, [wRoamMon3MapGroup]
-	cp GROUP_N_A
-	jr z, .Finished
-	ld b, a
-	ld a, [wRoamMon3MapNumber]
-	ld c, a
-	call .Update
-	ld a, b
-	ld [wRoamMon3MapGroup], a
-	ld a, c
-	ld [wRoamMon3MapNumber], a
-
-.Finished:
-	jp _BackUpMapIndices
-; 2a355
-
-
-.Update: ; 2a355
-	ld hl, RoamMaps
-.loop
-; Are we at the end of the table?
-	ld a, [hl]
-	cp -1
-	ret z
-; Is this the correct entry?
-	ld a, b
-	cp [hl]
-	jr nz, .next
-	inc hl
-	ld a, c
-	cp [hl]
-	jr z, .yes
-; We don't have the correct entry yet, so let's continue.  A 0 terminates each entry.
-.next
-	ld a, [hli]
-	and a
-	jr nz, .next
-	jr .loop
-
-; We have the correct entry now, so let's choose a random map from it.
-.yes
-	inc hl
-	ld d, h
-	ld e, l
-.update_loop
-	ld h, d
-	ld l, e
-; Choose which map to warp to.
-	call Random
-	and %00011111 ; 1/8n chance it moves to a completely random map, where n is the number of roaming connections from the current map.
-	jr z, JumpRoamMon
-	and %11
-	cp [hl]
-	jr nc, .update_loop ; invalid index, try again
-	inc hl
-	ld c, a
-	ld b, $0
-	add hl, bc
-	add hl, bc
-	ld a, [wRoamMons_LastMapGroup]
-	cp [hl]
-	jr nz, .done
-	inc hl
-	ld a, [wRoamMons_LastMapNumber]
-	cp [hl]
-	jr z, .update_loop
-	dec hl
-
-.done
-	ld a, [hli]
-	ld b, a
-	ld c, [hl]
-	ret
-
-JumpRoamMons: ; 2a394
-	ld a, [wRoamMon1MapGroup]
-	cp GROUP_N_A
-	jr z, .SkipRaikou
-	call JumpRoamMon
-	ld a, b
-	ld [wRoamMon1MapGroup], a
-	ld a, c
-	ld [wRoamMon1MapNumber], a
-
-.SkipRaikou:
-	ld a, [wRoamMon2MapGroup]
-	cp GROUP_N_A
-	jr z, .SkipEntei
-	call JumpRoamMon
-	ld a, b
-	ld [wRoamMon2MapGroup], a
-	ld a, c
-	ld [wRoamMon2MapNumber], a
-
-.SkipEntei:
-	ld a, [wRoamMon3MapGroup]
-	cp GROUP_N_A
-	jr z, .Finished
-	call JumpRoamMon
-	ld a, b
-	ld [wRoamMon3MapGroup], a
-	ld a, c
-	ld [wRoamMon3MapNumber], a
-
-.Finished:
-	jp _BackUpMapIndices
-
-JumpRoamMon: ; 2a3cd
-.loop
-	ld hl, RoamMaps
-.innerloop1                   ; This loop happens to be unnecessary.
-	call Random               ; Choose a random number.
-	maskbits NUM_ROAMMON_MAPS ; Mask the number to limit it between 0 and 15.
-	cp NUM_ROAMMON_MAPS       ; If the number is not less than 16, try again.
-	jr nc, .innerloop1        ; I'm sure you can guess why this check is bogus.
-	inc a
-	ld b, a
-.innerloop2 ; Loop to get hl to the address of the chosen roam map.
-	dec b
-	jr z, .ok
-.innerloop3 ; Loop to skip the current roam map, which is terminated by a 0.
-	ld a, [hli]
-	and a
-	jr nz, .innerloop3
-	jr .innerloop2
-; Check to see if the selected map is the one the player is currently in.  If so, try again.
-.ok
-	ld a, [wMapGroup]
-	cp [hl]
-	jr nz, .done
-	inc hl
-	ld a, [wMapNumber]
-	cp [hl]
-	jr z, .loop
-	dec hl
-; Return the map group and number in bc.
-.done
-	ld a, [hli]
-	ld b, a
-	ld c, [hl]
-	ret
-; 2a3f6
-
-_BackUpMapIndices: ; 2a3f6
-	ld a, [wRoamMons_CurrentMapNumber]
-	ld [wRoamMons_LastMapNumber], a
-	ld a, [wRoamMons_CurrentMapGroup]
-	ld [wRoamMons_LastMapGroup], a
-	ld a, [wMapNumber]
-	ld [wRoamMons_CurrentMapNumber], a
-	ld a, [wMapGroup]
-	ld [wRoamMons_CurrentMapGroup], a
-	ret
-; 2a40f
-
-
-INCLUDE "data/wild/roammon_maps.asm"
-
-
-ValidateTempWildMonSpecies: ; 2a4a0
-; Due to a development oversight, this function is called with the wild Pokemon's level, not its species, in a.
-	and a
-	jr z, .nowildmon ; = 0
-	cp NUM_POKEMON + 1 ; 252
-	jr nc, .nowildmon ; >= 252
-	and a ; 1 <= Species <= 251
-	ret
-
-.nowildmon
-	scf
-	ret
-; 2a4ab
-
-; Finds a rare wild Pokemon in the route of the trainer calling, then checks if it's been Seen already.
-; The trainer will then tell you about the Pokemon if you haven't seen it.
-RandomUnseenWildMon: ; 2a4ab
-	farcall GetCallerLocation
-	ld d, b
-	ld e, c
-	ld hl, JohtoGrassWildMons
-	ld bc, GRASS_WILDDATA_LENGTH
-	call LookUpWildmonsForMapDE
-	jr c, .GetGrassmon
-	ld hl, KantoGrassWildMons
-	call LookUpWildmonsForMapDE
-	jr nc, .done
-
-.GetGrassmon:
-	push hl
-	ld bc, 5 + 4 * 2 ; Location of the level of the 5th wild Pokemon in that map
-	add hl, bc
-	ld a, [wTimeOfDay]
-	ld bc, NUM_GRASSMON * 2
-	call AddNTimes
-.randloop1
-	call Random
-	and %11
-	jr z, .randloop1
-	dec a
-	ld c, a
-	ld b, $0
-	add hl, bc
-	add hl, bc
-; We now have the pointer to one of the last (rarest) three wild Pokemon found in that area.
-	inc hl
-	ld c, [hl] ; Contains the species index of this rare Pokemon
-	pop hl
-	ld de, 5 + 0 * 2
-	add hl, de
-	inc hl ; Species index of the most common Pokemon on that route
-	ld b, 4
-.loop2
-	ld a, [hli]
-	cp c ; Compare this most common Pokemon with the rare one stored in c.
-	jr z, .done
-	inc hl
-	dec b
-	jr nz, .loop2
-; This Pokemon truly is rare.
-	push bc
-	dec c
-	ld a, c
-	call CheckSeenMon
-	pop bc
-	jr nz, .done
-; Since we haven't seen it, have the caller tell us about it.
-	ld de, wStringBuffer1
-	call CopyName1
-	ld a, c
-	ld [wNamedObjectIndexBuffer], a
-	call GetPokemonName
-	ld hl, .SawRareMonText
-	call PrintText
-	xor a
-	ld [wScriptVar], a
-	ret
-
-.done
-	ld a, $1
-	ld [wScriptVar], a
-	ret
-
-.SawRareMonText:
-	; I just saw some rare @  in @ . I'll call you if I see another rare #MON, OK?
-	text_jump UnknownText_0x1bd34b
-	db "@"
-; 0x2a51f
-
-RandomPhoneWildMon: ; 2a51f
-	farcall GetCallerLocation
-	ld d, b
-	ld e, c
-	ld hl, JohtoGrassWildMons
-	ld bc, GRASS_WILDDATA_LENGTH
-	call LookUpWildmonsForMapDE
-	jr c, .ok
-	ld hl, KantoGrassWildMons
-	call LookUpWildmonsForMapDE
-
-.ok
-	ld bc, 5 + 0 * 2
-	add hl, bc
-	ld a, [wTimeOfDay]
-	inc a
-	ld bc, NUM_GRASSMON * 2
-.loop
-	dec a
-	jr z, .done
-	add hl, bc
-	jr .loop
-
-.done
-	call Random
-	and %11
-	ld c, a
-	ld b, $0
-	add hl, bc
-	add hl, bc
-	inc hl
-	ld a, [hl]
-	ld [wNamedObjectIndexBuffer], a
-	call GetPokemonName
-	ld hl, wStringBuffer1
-	ld de, wStringBuffer4
-	ld bc, MON_NAME_LENGTH
-	jp CopyBytes
-; 2a567
-
-RandomPhoneMon: ; 2a567
-; Get a random monster owned by the trainer who's calling.
-	farcall GetCallerLocation
-	ld hl, TrainerGroups
-	ld a, d
-	dec a
-	ld c, a
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	ld a, BANK(TrainerGroups)
-	call GetFarHalfword
-
-.skip_trainer
-	dec e
-	jr z, .skipped
-.skip
-	ld a, BANK(Trainers)
-	call GetFarByte
-	inc hl
-	cp -1
-	jr nz, .skip
-	jr .skip_trainer
-.skipped
-
-.skip_name
-	ld a, BANK(Trainers)
-	call GetFarByte
-	inc hl
-	cp "@"
-	jr nz, .skip_name
-
-	ld a, BANK(Trainers)
-	call GetFarByte
-	inc hl
-	ld bc, 2 ; level, species
-	cp TRAINERTYPE_NORMAL
-	jr z, .got_mon_length
-	ld bc, 2 + NUM_MOVES ; level, species, moves
-	cp TRAINERTYPE_MOVES
-	jr z, .got_mon_length
-	ld bc, 2 + 1 ; level, species, item
-	cp TRAINERTYPE_ITEM
-	jr z, .got_mon_length
-	; TRAINERTYPE_ITEM_MOVES
-	ld bc, 2 + 1 + NUM_MOVES ; level, species, item, moves
-.got_mon_length
-
-	ld e, 0
-	push hl
-.count_mon
-	inc e
-	add hl, bc
-	ld a, BANK(Trainers)
-	call GetFarByte
-	cp -1
-	jr nz, .count_mon
-	pop hl
-
-.rand
-	call Random
-	maskbits PARTY_LENGTH
-	cp e
-	jr nc, .rand
-
-	inc a
-.get_mon
-	dec a
-	jr z, .got_mon
-	add hl, bc
-	jr .get_mon
-.got_mon
-
-	inc hl ; species
-	ld a, BANK(Trainers)
-	call GetFarByte
-	ld [wNamedObjectIndexBuffer], a
-	call GetPokemonName
-	ld hl, wStringBuffer1
-	ld de, wStringBuffer4
-	ld bc, MON_NAME_LENGTH
-	jp CopyBytes
-; 2a5e9
-
-
-INCLUDE "data/wild/johto_grass.asm"
-INCLUDE "data/wild/johto_water.asm"
-INCLUDE "data/wild/kanto_grass.asm"
-INCLUDE "data/wild/kanto_water.asm"
-INCLUDE "data/wild/swarm_grass.asm"
-INCLUDE "data/wild/swarm_water.asm"
--- a/main.asm
+++ b/main.asm
@@ -5,14 +5,14 @@
 
 INCLUDE "engine/routines/placewaitingtext.asm"
 INCLUDE "engine/routines/loadpushoam.asm"
-INCLUDE "engine/map_objects.asm"
+INCLUDE "engine/overworld/map_objects.asm"
 INCLUDE "engine/intro_menu.asm"
-INCLUDE "engine/init_map.asm"
-INCLUDE "engine/learn.asm"
+INCLUDE "engine/overworld/init_map.asm"
+INCLUDE "engine/pokemon/learn.asm"
 INCLUDE "engine/routines/checknickerrors.asm"
-INCLUDE "engine/math.asm"
+INCLUDE "engine/routines/math.asm"
 INCLUDE "data/items/attributes.asm"
-INCLUDE "engine/npc_movement.asm"
+INCLUDE "engine/overworld/npc_movement.asm"
 INCLUDE "engine/events/happiness_egg.asm"
 INCLUDE "engine/events/specials_2.asm"
 
@@ -19,10 +19,10 @@
 
 SECTION "bank2", ROMX
 
-INCLUDE "engine/player_object.asm"
+INCLUDE "engine/overworld/player_object.asm"
 INCLUDE "engine/routines/sine.asm"
 INCLUDE "engine/predef.asm"
-INCLUDE "engine/color.asm"
+INCLUDE "engine/gfx/color.asm"
 
 
 SECTION "bank3", ROMX
@@ -29,14 +29,14 @@
 
 INCLUDE "engine/routines/checktime.asm"
 INCLUDE "engine/events/specials.asm"
-INCLUDE "engine/printnum.asm"
-INCLUDE "engine/health.asm"
+INCLUDE "engine/routines/printnum.asm"
+INCLUDE "engine/pokemon/health.asm"
 INCLUDE "engine/events/overworld.asm"
 INCLUDE "engine/items.asm"
-INCLUDE "engine/player_step.asm"
+INCLUDE "engine/overworld/player_step.asm"
 INCLUDE "engine/battle/anim_hp_bar.asm"
-INCLUDE "engine/move_mon.asm"
-INCLUDE "engine/billspctop.asm"
+INCLUDE "engine/pokemon/move_mon.asm"
+INCLUDE "engine/pokemon/billspctop.asm"
 INCLUDE "engine/routines/getbreedmonlevelgrowth.asm"
 INCLUDE "engine/events/bug_contest/caught_mon.asm"
 INCLUDE "engine/item_effects.asm"
@@ -46,17 +46,17 @@
 
 SECTION "bank4", ROMX
 
-INCLUDE "engine/pack.asm"
-INCLUDE "engine/time.asm"
-INCLUDE "engine/tmhm.asm"
-INCLUDE "engine/naming_screen.asm"
+INCLUDE "engine/menu/pack.asm"
+INCLUDE "engine/overworld/time.asm"
+INCLUDE "engine/menu/tmhm.asm"
+INCLUDE "engine/menu/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/start_menu.asm"
-INCLUDE "engine/select_menu.asm"
+INCLUDE "engine/menu/start_menu.asm"
+INCLUDE "engine/overworld/select_menu.asm"
 INCLUDE "engine/events/elevator.asm"
 INCLUDE "engine/events/bug_contest/contest.asm"
 INCLUDE "engine/events/misc_scripts_2.asm"
@@ -71,13 +71,13 @@
 SECTION "bank5", ROMX
 
 INCLUDE "engine/rtc.asm"
-INCLUDE "engine/overworld.asm"
-INCLUDE "engine/tile_events.asm"
+INCLUDE "engine/overworld/overworld.asm"
+INCLUDE "engine/overworld/tile_events.asm"
 INCLUDE "engine/save.asm"
-INCLUDE "engine/spawn_points.asm"
-INCLUDE "engine/map_setup.asm"
+INCLUDE "engine/overworld/spawn_points.asm"
+INCLUDE "engine/overworld/map_setup.asm"
 INCLUDE "engine/events/pokecenter_pc.asm"
-INCLUDE "engine/mart.asm"
+INCLUDE "engine/menu/mart.asm"
 INCLUDE "engine/money.asm"
 INCLUDE "data/items/marts.asm"
 INCLUDE "engine/events/mom.asm"
@@ -84,36 +84,36 @@
 INCLUDE "engine/events/daycare.asm"
 INCLUDE "engine/events/print_unown.asm"
 INCLUDE "engine/events/print_photo.asm"
-INCLUDE "engine/breeding.asm"
+INCLUDE "engine/pokemon/breeding.asm"
 INCLUDE "gfx/tilesets.asm"
 
 
 SECTION "Roofs", ROMX
 
-INCLUDE "engine/mapgroup_roofs.asm"
+INCLUDE "engine/gfx/mapgroup_roofs.asm"
 
 
 SECTION "Clock Reset", ROMX
 
-INCLUDE "engine/clock_reset.asm"
+INCLUDE "engine/menu/clock_reset.asm"
 
 
 SECTION "bank9", ROMX
 
 INCLUDE "data/text_buffers.asm"
-INCLUDE "engine/menu.asm"
+INCLUDE "engine/menu/menu.asm"
 INCLUDE "engine/routines/updateitemdescription.asm"
 INCLUDE "engine/events/pokepic.asm"
-INCLUDE "engine/map_objects_2.asm"
-INCLUDE "engine/scrolling_menu.asm"
-INCLUDE "engine/switch_items.asm"
-INCLUDE "engine/menu_2.asm"
-INCLUDE "engine/mon_menu.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/battle/menu.asm"
-INCLUDE "engine/buy_sell_toss.asm"
-INCLUDE "engine/trainer_card.asm"
+INCLUDE "engine/menu/buy_sell_toss.asm"
+INCLUDE "engine/menu/trainer_card.asm"
 INCLUDE "engine/events/prof_oaks_pc.asm"
-INCLUDE "engine/decorations.asm"
+INCLUDE "engine/overworld/decorations.asm"
 INCLUDE "engine/routines/leveluphappinessmod.asm"
 INCLUDE "engine/battle/read_trainer_dvs.asm"
 INCLUDE "data/trainers/dvs.asm"
@@ -126,8 +126,8 @@
 
 SECTION "bankA", ROMX
 
-INCLUDE "engine/link.asm"
-INCLUDE "engine/wildmons.asm"
+INCLUDE "engine/link/link.asm"
+INCLUDE "engine/overworld/wildmons.asm"
 INCLUDE "engine/battle/link_result.asm"
 
 ChrisBackpic: ; 2ba1a
@@ -143,8 +143,8 @@
 INCLUDE "data/trainers/class_names.asm"
 INCLUDE "engine/battle/ai/redundant.asm"
 INCLUDE "engine/events/move_deleter.asm"
-INCLUDE "engine/mystery_gift_2.asm"
-INCLUDE "engine/tmhm2.asm"
+INCLUDE "engine/link/mystery_gift_2.asm"
+INCLUDE "engine/pokemon/tmhm.asm"
 INCLUDE "data/moves/descriptions.asm"
 INCLUDE "engine/events/pokerus/pokerus.asm"
 INCLUDE "engine/battle/start_battle.asm"
@@ -177,7 +177,7 @@
 
 INCLUDE "engine/pokedex/pokedex.asm"
 INCLUDE "data/moves/moves.asm"
-INCLUDE "engine/evolve.asm"
+INCLUDE "engine/pokemon/evolve.asm"
 
 
 SECTION "bank11", ROMX
@@ -186,7 +186,7 @@
 INCLUDE "engine/battle/ai/move.asm"
 INCLUDE "engine/pokedex/pokedex_2.asm"
 INCLUDE "data/pokemon/dex_entry_pointers.asm"
-INCLUDE "engine/mail.asm"
+INCLUDE "engine/pokemon/mail.asm"
 
 
 SECTION "Crystal Features 1", ROMX
@@ -194,11 +194,11 @@
 INCLUDE "engine/init_gender.asm"
 INCLUDE "engine/routines/drawkrispackgfx.asm"
 INCLUDE "engine/events/move_tutor.asm"
-INCLUDE "engine/crystal_layouts.asm"
+INCLUDE "engine/gfx/crystal_layouts.asm"
 INCLUDE "engine/events/celebi.asm"
-INCLUDE "engine/main_menu.asm"
+INCLUDE "engine/menu/main_menu.asm"
 INCLUDE "mobile/mobile_menu.asm"
-INCLUDE "engine/search.asm"
+INCLUDE "engine/pokemon/search.asm"
 INCLUDE "mobile/mobile_12_2.asm"
 INCLUDE "engine/events/buena_menu.asm"
 
@@ -205,7 +205,7 @@
 
 SECTION "bank13", ROMX
 
-INCLUDE "engine/map_palettes.asm"
+INCLUDE "engine/gfx/map_palettes.asm"
 INCLUDE "gfx/tileset_palette_maps.asm"
 INCLUDE "data/collision_permissions.asm"
 INCLUDE "engine/routines/emptyallsrambanks.asm"
@@ -221,30 +221,30 @@
 Shrink2Pic: ; 4d2d9
 INCBIN "gfx/new_game/shrink2.2bpp.lz"
 
-INCLUDE "engine/link_2.asm"
-INCLUDE "engine/delete_save_change_clock.asm"
+INCLUDE "engine/link/link_2.asm"
+INCLUDE "engine/menu/delete_save_change_clock.asm"
 INCLUDE "data/tilesets.asm"
 INCLUDE "engine/routines/flagpredef.asm"
 INCLUDE "engine/routines/trademonfrontpic.asm"
 INCLUDE "engine/events/pokerus/check_pokerus.asm"
 INCLUDE "engine/events/lucky_number.asm"
-INCLUDE "engine/caught_data.asm"
-INCLUDE "engine/search2.asm"
-INCLUDE "engine/stats_screen.asm"
+INCLUDE "engine/pokemon/caught_data.asm"
+INCLUDE "engine/pokemon/search2.asm"
+INCLUDE "engine/pokemon/stats_screen.asm"
 INCLUDE "engine/events/catch_tutorial.asm"
-INCLUDE "engine/evolution_animation.asm"
-INCLUDE "engine/init_hof_credits.asm"
+INCLUDE "engine/gfx/evolution_animation.asm"
+INCLUDE "engine/title/init_hof_credits.asm"
 INCLUDE "engine/events/battle_tower/get_trainer_class.asm"
 INCLUDE "engine/battle/sliding_intro.asm"
 INCLUDE "mobile/print_opp_message.asm"
 INCLUDE "engine/battle/checkbattlescene.asm"
-INCLUDE "engine/gbc_only.asm"
+INCLUDE "engine/gfx/gbc_only.asm"
 INCLUDE "engine/events/poke_seer.asm"
 
 
 SECTION "bank14", ROMX
 
-INCLUDE "engine/party_menu.asm"
+INCLUDE "engine/pokemon/party_menu.asm"
 INCLUDE "engine/events/poisonstep.asm"
 INCLUDE "engine/events/sweet_scent.asm"
 INCLUDE "engine/events/squirtbottle.asm"
@@ -251,15 +251,15 @@
 INCLUDE "engine/events/card_key.asm"
 INCLUDE "engine/events/basement_key.asm"
 INCLUDE "engine/events/sacred_ash.asm"
-INCLUDE "engine/tempmon.asm"
-INCLUDE "engine/types.asm"
+INCLUDE "engine/pokemon/tempmon.asm"
+INCLUDE "engine/pokemon/types.asm"
 INCLUDE "engine/routines/unreferenced_getgen1trainerclassname.asm"
-INCLUDE "engine/mon_stats.asm"
+INCLUDE "engine/pokemon/mon_stats.asm"
 INCLUDE "engine/routines/initlist.asm"
-INCLUDE "engine/experience.asm"
+INCLUDE "engine/pokemon/experience.asm"
 INCLUDE "engine/routines/switchpartymons.asm"
-INCLUDE "engine/load_pics.asm"
-INCLUDE "engine/move_mon_wo_mail.asm"
+INCLUDE "engine/gfx/load_pics.asm"
+INCLUDE "engine/pokemon/move_mon_wo_mail.asm"
 INCLUDE "data/pokemon/base_stats.asm"
 INCLUDE "data/pokemon/names.asm"
 INCLUDE "data/unused_53d84.asm"
@@ -276,9 +276,9 @@
 
 SECTION "bank20", ROMX
 
-INCLUDE "engine/player_movement.asm"
+INCLUDE "engine/overworld/player_movement.asm"
 INCLUDE "engine/engine_flags.asm"
-INCLUDE "engine/variables.asm"
+INCLUDE "engine/overworld/variables.asm"
 INCLUDE "data/text/battle.asm"
 INCLUDE "engine/debug.asm"
 
@@ -285,7 +285,7 @@
 
 SECTION "bank21", ROMX
 
-INCLUDE "engine/printer.asm"
+INCLUDE "engine/printer/printer.asm"
 INCLUDE "gfx/battle_anims.asm"
 INCLUDE "engine/events/halloffame.asm"
 
@@ -293,7 +293,7 @@
 SECTION "Crystal Features 2", ROMX
 
 INCLUDE "engine/events/kurt.asm"
-INCLUDE "engine/player_gfx.asm"
+INCLUDE "engine/gfx/player_gfx.asm"
 INCLUDE "mobile/mobile_22.asm"
 INCLUDE "engine/events/unown_walls.asm"
 INCLUDE "engine/events/buena.asm"
@@ -304,22 +304,22 @@
 
 SECTION "bank23", ROMX
 
-INCLUDE "engine/timeofdaypals.asm"
+INCLUDE "engine/gfx/timeofdaypals.asm"
 INCLUDE "engine/battle/battle_transition.asm"
 INCLUDE "engine/events/field_moves.asm"
 INCLUDE "engine/events/magnet_train.asm"
 INCLUDE "engine/battle/battlestart_copytilemapatonce.asm"
-INCLUDE "engine/sprites.asm"
-INCLUDE "engine/mon_icons.asm"
+INCLUDE "engine/gfx/sprites.asm"
+INCLUDE "engine/gfx/mon_icons.asm"
 
 
 SECTION "bank24", ROMX
 
 INCLUDE "engine/phone/phone.asm"
-INCLUDE "engine/timeset.asm"
-INCLUDE "engine/pokegear.asm"
+INCLUDE "engine/menu/timeset.asm"
+INCLUDE "engine/pokegear/pokegear.asm"
 INCLUDE "engine/events/fish.asm"
-INCLUDE "engine/slot_machine.asm"
+INCLUDE "engine/game/slot_machine.asm"
 
 
 SECTION "Phone Engine", ROMX
@@ -356,8 +356,8 @@
 INCLUDE "engine/events/checkforhiddenitems.asm"
 INCLUDE "engine/events/treemons.asm"
 INCLUDE "engine/events/loadfishinggfx.asm"
-INCLUDE "engine/radio.asm"
-INCLUDE "engine/mail_2.asm"
+INCLUDE "engine/pokegear/radio.asm"
+INCLUDE "engine/pokemon/mail_2.asm"
 
 
 SECTION "bank2F", ROMX
@@ -393,7 +393,7 @@
 
 SECTION "Pic Animations 1", ROMX
 
-INCLUDE "engine/pic_animation.asm"
+INCLUDE "engine/gfx/pic_animation.asm"
 INCLUDE "gfx/pokemon/anim_pointers.asm"
 INCLUDE "gfx/pokemon/anims.asm"
 INCLUDE "gfx/pokemon/idle_pointers.asm"
@@ -430,10 +430,10 @@
 SECTION "bank38", ROMX
 
 INCLUDE "engine/events/print_unown_2.asm"
-INCLUDE "engine/card_flip.asm"
-INCLUDE "engine/unown_puzzle.asm"
-INCLUDE "engine/dummy_game.asm"
-INCLUDE "engine/billspc.asm"
+INCLUDE "engine/game/card_flip.asm"
+INCLUDE "engine/game/unown_puzzle.asm"
+INCLUDE "engine/game/dummy_game.asm"
+INCLUDE "engine/pokemon/billspc.asm"
 
 
 SECTION "bank39", ROMX
@@ -441,18 +441,18 @@
 CopyrightGFX:: ; e4000
 INCBIN "gfx/splash/copyright.2bpp"
 
-INCLUDE "engine/options_menu.asm"
-INCLUDE "engine/crystal_intro.asm"
+INCLUDE "engine/menu/options_menu.asm"
+INCLUDE "engine/title/crystal_intro.asm"
 
 
 SECTION "bank3E", ROMX
 
-INCLUDE "engine/load_font.asm"
-INCLUDE "engine/time_capsule.asm"
+INCLUDE "engine/gfx/load_font.asm"
+INCLUDE "engine/link/time_capsule.asm"
 INCLUDE "engine/events/name_rater.asm"
 INCLUDE "engine/routines/playslowcry.asm"
 INCLUDE "engine/pokedex/newpokedexentry.asm"
-INCLUDE "engine/time_capsule_2.asm"
+INCLUDE "engine/link/time_capsule_2.asm"
 INCLUDE "engine/pokedex/unown_dex.asm"
 INCLUDE "engine/events/magikarp.asm"
 INCLUDE "engine/battle/hidden_power.asm"
@@ -461,7 +461,7 @@
 
 SECTION "bank3F", ROMX
 
-INCLUDE "engine/tileset_anims.asm"
+INCLUDE "engine/gfx/tileset_anims.asm"
 INCLUDE "engine/events/npc_trade.asm"
 INCLUDE "engine/events/mom_phone.asm"
 
@@ -473,8 +473,8 @@
 
 INCLUDE "engine/dma_transfer.asm"
 INCLUDE "gfx/emotes.asm"
-INCLUDE "engine/warp_connection.asm"
-INCLUDE "engine/mystery_gift.asm"
+INCLUDE "engine/overworld/warp_connection.asm"
+INCLUDE "engine/link/mystery_gift.asm"
 INCLUDE "engine/battle/used_move_text.asm"
 INCLUDE "mobile/mobile_41.asm"
 INCLUDE "engine/routines/loadoverworldfont.asm"
@@ -493,8 +493,8 @@
 
 SECTION "Title", ROMX
 
-INCLUDE "engine/unused_title.asm"
-INCLUDE "engine/title.asm"
+INCLUDE "engine/title/unused_title.asm"
+INCLUDE "engine/title/title.asm"
 
 
 INCLUDE "mobile/mobile_45.asm"
@@ -511,7 +511,7 @@
 SECTION "bank5B", ROMX
 
 INCLUDE "mobile/mobile_5b.asm"
-INCLUDE "engine/link_trade.asm"
+INCLUDE "engine/link/link_trade.asm"
 
 
 SECTION "Mobile 5C", ROMX
@@ -569,7 +569,7 @@
 INCLUDE "engine/routines/printitemdescription.asm"
 INCLUDE "data/items/descriptions.asm"
 INCLUDE "data/moves/names.asm"
-INCLUDE "engine/landmarks.asm"
+INCLUDE "engine/overworld/landmarks.asm"
 
 
 SECTION "bank77", ROMX
@@ -577,13 +577,13 @@
 UnownFont: ; 1dc000
 INCBIN "gfx/font/unown_font.2bpp"
 
-INCLUDE "engine/print_party.asm"
+INCLUDE "engine/printer/print_party.asm"
 
 
 SECTION "bank77_2", ROMX
 
 INCLUDE "engine/routines/printhoursmins.asm"
-INCLUDE "engine/diploma.asm"
+INCLUDE "engine/events/diploma.asm"
 INCLUDE "engine/pokedex/pokedex_3.asm"
 INCLUDE "engine/events/catch_tutorial_input.asm"
 INCLUDE "engine/routines/townmap_convertlinebreakcharacters.asm"
@@ -591,7 +591,7 @@
 PokegearGFX: ; 1de2e4
 INCBIN "gfx/pokegear/pokegear.2bpp.lz"
 
-INCLUDE "engine/european_mail.asm"
+INCLUDE "engine/pokemon/european_mail.asm"
 
 
 SECTION "Battle Tower Text", ROMX