shithub: pokecrystal

Download patch

ref: 0d9241889fc8a2f047b9fd6db25e55de1e721877
parent: 60e21a86638cad5fd25133cda1c545461304d902
author: mid-kid <esteve.varela@gmail.com>
date: Sun Mar 25 12:18:33 EDT 2018

Organize the engine/ directory, take 3

Renamed `title` to `movies`.
Moved some functions from `engine/routines/` to their fitting
directories, and cleaned up the base `engine/` directory.
Moved `engine/pokemon/tmhm.asm` back to `engine/items/`.

Made a new subdirectory:
* engine/tilesets: Contains all map-related graphics routines.

--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,7 @@
 data/pokemon/dex_entries.o \
 data/pokemon/egg_moves.o \
 data/pokemon/evos_attacks.o \
-engine/title/credits.o \
+engine/movie/credits.o \
 engine/overworld/events.o \
 gfx/pics.o \
 gfx/sprites.o \
--- a/engine/debug.asm
+++ /dev/null
@@ -1,1447 +1,0 @@
-	const_def $6a
-	const DEBUGTEST_UP_ARROW ; $6a
-	const DEBUGTEST_TICKS    ; $6b
-	const DEBUGTEST_WHITE    ; $6c
-	const DEBUGTEST_LIGHT    ; $6d
-	const DEBUGTEST_DARK     ; $6e
-	const DEBUGTEST_BLACK    ; $6f
-	const DEBUGTEST_0        ; $70
-	const DEBUGTEST_1        ; $71
-	const DEBUGTEST_2        ; $72
-	const DEBUGTEST_3        ; $73
-	const DEBUGTEST_4        ; $74
-	const DEBUGTEST_5        ; $75
-	const DEBUGTEST_6        ; $76
-	const DEBUGTEST_7        ; $77
-	const DEBUGTEST_8        ; $78
-	const DEBUGTEST_9        ; $79
-	const DEBUGTEST_A        ; $7a
-	const DEBUGTEST_B        ; $7b
-	const DEBUGTEST_C        ; $7c
-	const DEBUGTEST_D        ; $7d
-	const DEBUGTEST_E        ; $7e
-	const DEBUGTEST_F        ; $7f
-
-ColorTest: ; 818ac
-; A debug menu to test monster and trainer palettes at runtime.
-
-	ld a, [hCGB]
-	and a
-	jr nz, .asm_818b5
-	ld a, [hSGB]
-	and a
-	ret z
-
-.asm_818b5
-	ld a, [hInMenu]
-	push af
-	ld a, $1
-	ld [hInMenu], a
-	call DisableLCD
-	call Function81948
-	call Function8197c
-	call Function819a7
-	call Function818f4
-	call EnableLCD
-	ld de, MUSIC_NONE
-	call PlayMusic
-	xor a
-	ld [wJumptableIndex], a
-	ld [wcf66], a
-	ld [wd003], a
-.asm_818de
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .asm_818f0
-	call Function81a74
-	call Function81f5e
-	call DelayFrame
-	jr .asm_818de
-
-.asm_818f0
-	pop af
-	ld [hInMenu], a
-	ret
-; 818f4
-
-Function818f4: ; 818f4
-	ld a, [wd002]
-	and a
-	jr nz, Function81911
-	ld hl, PokemonPalettes
-
-Function818fd: ; 818fd
-	ld de, wOverworldMap
-	ld c, NUM_POKEMON + 1
-.asm_81902
-	push bc
-	push hl
-	call Function81928
-	pop hl
-	ld bc, 8
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .asm_81902
-	ret
-
-Function81911: ; 81911
-	ld hl, TrainerPalettes
-	ld de, wOverworldMap
-	ld c, NUM_TRAINER_CLASSES
-.asm_81919
-	push bc
-	push hl
-	call Function81928
-	pop hl
-	ld bc, 4
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .asm_81919
-	ret
-; 81928
-
-Function81928: ; 81928
-	ld a, BANK(PokemonPalettes) ; BANK(TrainerPalettes)
-	call GetFarByte
-	ld [de], a
-	inc de
-	inc hl
-	ld a, BANK(PokemonPalettes) ; BANK(TrainerPalettes)
-	call GetFarByte
-	ld [de], a
-	inc de
-	inc hl
-	ld a, BANK(PokemonPalettes) ; BANK(TrainerPalettes)
-	call GetFarByte
-	ld [de], a
-	inc de
-	inc hl
-	ld a, BANK(PokemonPalettes) ; BANK(TrainerPalettes)
-	call GetFarByte
-	ld [de], a
-	inc de
-	ret
-; 81948
-
-Function81948: ; 81948
-	ld a, $1
-	ld [rVBK], a
-	ld hl, vTiles0
-	ld bc, sScratch - vTiles0
-	xor a
-	call ByteFill
-	ld a, $0
-	ld [rVBK], a
-	ld hl, vTiles0
-	ld bc, sScratch - vTiles0
-	xor a
-	call ByteFill
-	hlcoord 0, 0, wAttrMap
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	xor a
-	call ByteFill
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	xor a
-	call ByteFill
-	call ClearSprites
-	ret
-; 8197c
-
-Function8197c: ; 8197c
-	ld hl, DebugColorTestGFX + 1 tiles
-	ld de, vTiles2 tile DEBUGTEST_UP_ARROW
-	ld bc, 22 tiles
-	call CopyBytes
-	ld hl, DebugColorTestGFX
-	ld de, vTiles0
-	ld bc, 1 tiles
-	call CopyBytes
-	call LoadStandardFont
-	ld hl, vTiles1
-	lb bc, 8, 0
-.asm_8199d
-	ld a, [hl]
-	xor $ff
-	ld [hli], a
-	dec bc
-	ld a, c
-	or b
-	jr nz, .asm_8199d
-	ret
-; 819a7
-
-Function819a7: ; 819a7
-	ld a, [hCGB]
-	and a
-	ret z
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ld [rSVBK], a
-	ld hl, Palette_DebugBG
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-	ld a, 1 << rBGPI_AUTO_INCREMENT
-	ld [rBGPI], a
-	ld hl, Palette_DebugBG
-	ld c, 8 palettes
-	xor a
-.asm_819c8
-	ld [rBGPD], a
-	dec c
-	jr nz, .asm_819c8
-	ld a, 1 << rOBPI_AUTO_INCREMENT
-	ld [rOBPI], a
-	ld hl, Palette_DebugOB
-	ld c, 8 palettes
-.asm_819d6
-	ld a, [hli]
-	ld [rOBPD], a
-	dec c
-	jr nz, .asm_819d6
-	ld a, $94
-	ld [wc608], a
-	ld a, $52
-	ld [wc608 + 1], a
-	ld a, $4a
-	ld [wc608 + 2], a
-	ld a, $29
-	ld [wc608 + 3], a
-	pop af
-	ld [rSVBK], a
-	ret
-; 819f4
-
-Palette_DebugBG: ; 819f4
-INCLUDE "gfx/debug/bg.pal"
-
-Palette_DebugOB: ; 81a34
-INCLUDE "gfx/debug/ob.pal"
-; 81a74
-
-Function81a74: ; 81a74
-	call JoyTextDelay
-	ld a, [wJumptableIndex]
-	cp $4
-	jr nc, .asm_81a8b
-	ld hl, hJoyLast
-	ld a, [hl]
-	and SELECT
-	jr nz, .asm_81a9a
-	ld a, [hl]
-	and START
-	jr nz, .asm_81aab
-
-.asm_81a8b
-	ld a, [wJumptableIndex]
-	ld e, a
-	ld d, 0
-	ld hl, Jumptable_81acf
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-.asm_81a9a
-	call Function81eca
-	call Function81ac3
-	ld e, a
-	ld a, [wcf66]
-	inc a
-	cp e
-	jr c, .asm_81aba
-	xor a
-	jr .asm_81aba
-
-.asm_81aab
-	call Function81eca
-	ld a, [wcf66]
-	dec a
-	cp $ff
-	jr nz, .asm_81aba
-	call Function81ac3
-	dec a
-
-.asm_81aba
-	ld [wcf66], a
-	ld a, $0
-	ld [wJumptableIndex], a
-	ret
-; 81ac3
-
-Function81ac3: ; 81ac3
-; Looping back around the pic set.
-	ld a, [wd002]
-	and a
-	jr nz, .asm_81acc
-	ld a, NUM_POKEMON ; CELEBI
-	ret
-
-.asm_81acc
-	ld a, NUM_TRAINER_CLASSES - 1 ; MYSTICALMAN
-	ret
-; 81acf
-
-Jumptable_81acf: ; 81acf
-	dw Function81adb
-	dw Function81c18
-	dw Function81c33
-	dw Function81cc2
-	dw Function81d8e
-	dw Function81daf
-; 81adb
-
-Function81adb: ; 81adb
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, DEBUGTEST_BLACK
-	call ByteFill
-	hlcoord 1, 3
-	lb bc, 7, 18
-	ld a, DEBUGTEST_WHITE
-	call Bank20_FillBoxWithByte
-	hlcoord 11, 0
-	lb bc, 2, 3
-	ld a, DEBUGTEST_LIGHT
-	call Bank20_FillBoxWithByte
-	hlcoord 16, 0
-	lb bc, 2, 3
-	ld a, DEBUGTEST_DARK
-	call Bank20_FillBoxWithByte
-	call Function81bc0
-	call Function81bf4
-	ld a, [wcf66]
-	inc a
-	ld [wCurPartySpecies], a
-	ld [wd265], a
-	hlcoord 0, 1
-	ld de, wd265
-	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
-	call PrintNum
-	ld a, [wd002]
-	and a
-	jr nz, .asm_81b7a
-	ld a, $1
-	ld [wUnownLetter], a
-	call GetPokemonName
-	hlcoord 4, 1
-	call PlaceString
-	xor a
-	ld [wBoxAlignment], a
-	hlcoord 12, 3
-	call _PrepMonFrontpic
-	ld de, vTiles2 tile $31
-	predef GetMonBackpic
-	ld a, $31
-	ld [hGraphicStartTile], a
-	hlcoord 2, 4
-	lb bc, 6, 6
-	predef PlaceGraphic
-	ld a, [wd003]
-	and a
-	jr z, .asm_81b66
-	ld de, String_81baf
-	jr .asm_81b69
-
-.asm_81b66
-	ld de, String_81bb4
-
-.asm_81b69
-	hlcoord 7, 17
-	call PlaceString
-	hlcoord 0, 17
-	ld de, String_81bb9
-	call PlaceString
-	jr .asm_81ba9
-
-.asm_81b7a
-	ld a, [wd265]
-	ld [wTrainerClass], a
-	callfar GetTrainerAttributes
-	ld de, wStringBuffer1
-	hlcoord 4, 1
-	call PlaceString
-	ld de, vTiles2
-	callfar GetTrainerPic
-	xor a
-	ld [wTempEnemyMonSpecies], a
-	ld [hGraphicStartTile], a
-	hlcoord 2, 3
-	lb bc, 7, 7
-	predef PlaceGraphic
-
-.asm_81ba9
-	ld a, $1
-	ld [wJumptableIndex], a
-	ret
-; 81baf
-
-String_81baf: db "レア", DEBUGTEST_BLACK, DEBUGTEST_BLACK, "@" ; rare (shiny)
-String_81bb4: db "ノーマル@" ; normal
-String_81bb9: db DEBUGTEST_A, "きりかえ▶@" ; (A) switches
-; 81bc0
-
-Function81bc0: ; 81bc0
-	decoord 0, 11, wAttrMap
-	hlcoord 2, 11
-	ld a, $1
-	call Function81bde
-	decoord 0, 13, wAttrMap
-	hlcoord 2, 13
-	ld a, $2
-	call Function81bde
-	decoord 0, 15, wAttrMap
-	hlcoord 2, 15
-	ld a, $3
-
-Function81bde: ; 81bde
-	push af
-	ld a, DEBUGTEST_UP_ARROW
-	ld [hli], a
-	ld bc, $f
-	ld a, DEBUGTEST_TICKS
-	call ByteFill
-	ld l, e
-	ld h, d
-	pop af
-	ld bc, $28
-	call ByteFill
-	ret
-; 81bf4
-
-Function81bf4: ; 81bf4
-	ld a, [wcf66]
-	inc a
-	ld l, a
-	ld h, $0
-	add hl, hl
-	add hl, hl
-	ld de, wOverworldMap
-	add hl, de
-	ld de, wc608
-	ld bc, 4
-	call CopyBytes
-	xor a
-	ld [wcf64], a
-	ld [wcf65], a
-	ld de, wc608
-	call Function81ea5
-	ret
-; 81c18
-
-Function81c18: ; 81c18
-	ld a, [hCGB]
-	and a
-	jr z, .asm_81c2a
-	ld a, $2
-	ld [hBGMapMode], a
-	call DelayFrame
-	call DelayFrame
-	call DelayFrame
-
-.asm_81c2a
-	call WaitBGMap
-	ld a, $2
-	ld [wJumptableIndex], a
-	ret
-; 81c33
-
-Function81c33: ; 81c33
-	ld a, [hCGB]
-	and a
-	jr z, .asm_81c69
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ld [rSVBK], a
-	ld hl, wBGPals2
-	ld de, wc608
-	ld c, $1
-	call Function81ee3
-	hlcoord 10, 2
-	ld de, wc608
-	call Function81ca7
-	hlcoord 15, 2
-	ld de, wc608 + 2
-	call Function81ca7
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	ld a, $3
-	ld [wJumptableIndex], a
-	pop af
-	ld [rSVBK], a
-	ret
-
-.asm_81c69
-	ld hl, wSGBPals
-	ld a, 1
-	ld [hli], a
-	ld a, LOW(PALRGB_WHITE)
-	ld [hli], a
-	ld a, HIGH(PALRGB_WHITE)
-	ld [hli], a
-	ld a, [wc608]
-	ld [hli], a
-	ld a, [wc608 + 1]
-	ld [hli], a
-	ld a, [wc608 + 2]
-	ld [hli], a
-	ld a, [wc608 + 3]
-	ld [hli], a
-	xor a
-	ld [hli], a
-	ld [hli], a
-	ld [hl], a
-	ld hl, wSGBPals
-	call Function81f0c
-	hlcoord 10, 2
-	ld de, wc608
-	call Function81ca7
-	hlcoord 15, 2
-	ld de, wc608 + 2
-	call Function81ca7
-	ld a, $3
-	ld [wJumptableIndex], a
-	ret
-; 81ca7
-
-Function81ca7: ; 81ca7
-	inc hl
-	inc hl
-	inc hl
-	ld a, [de]
-	call Function81cbc
-	ld a, [de]
-	swap a
-	call Function81cbc
-	inc de
-	ld a, [de]
-	call Function81cbc
-	ld a, [de]
-	swap a
-
-Function81cbc: ; 81cbc
-	and $f
-	add DEBUGTEST_0
-	ld [hld], a
-	ret
-; 81cc2
-
-Function81cc2: ; 81cc2
-	ld a, [hJoyLast]
-	and B_BUTTON
-	jr nz, .asm_81cdf
-	ld a, [hJoyLast]
-	and A_BUTTON
-	jr nz, .asm_81ce5
-	ld a, [wcf64]
-	and $3
-	ld e, a
-	ld d, 0
-	ld hl, Jumptable_81d02
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-.asm_81cdf
-	ld a, $4
-	ld [wJumptableIndex], a
-	ret
-
-.asm_81ce5
-	ld a, [wd002]
-	and a
-	ret nz
-	ld a, [wd003]
-	xor $4
-	ld [wd003], a
-	ld c, a
-	ld b, 0
-	ld hl, PokemonPalettes
-	add hl, bc
-	call Function818fd
-	ld a, $0
-	ld [wJumptableIndex], a
-	ret
-; 81d02
-
-Jumptable_81d02: ; 81d02
-	dw Function81d0a
-	dw Function81d34
-	dw Function81d46
-	dw Function81d58
-; 81d0a
-
-Function81d0a: ; 81d0a
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, Function81d89
-	ld a, [hl]
-	and D_LEFT
-	jr nz, .asm_81d1d
-	ld a, [hl]
-	and D_RIGHT
-	jr nz, .asm_81d28
-	ret
-
-.asm_81d1d
-	xor a
-	ld [wcf65], a
-	ld de, wc608
-	call Function81ea5
-	ret
-
-.asm_81d28
-	ld a, $1
-	ld [wcf65], a
-	ld de, wc608 + 2
-	call Function81ea5
-	ret
-
-Function81d34: ; 81d34
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, Function81d89
-	ld a, [hl]
-	and D_UP
-	jr nz, Function81d84
-	ld hl, wc608 + 10
-	jr Function81d63
-
-Function81d46: ; 81d46
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, Function81d89
-	ld a, [hl]
-	and D_UP
-	jr nz, Function81d84
-	ld hl, wc608 + 11
-	jr Function81d63
-
-Function81d58: ; 81d58
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_UP
-	jr nz, Function81d84
-	ld hl, wc608 + 12
-
-Function81d63: ; 81d63
-	ld a, [hJoyLast]
-	and D_RIGHT
-	jr nz, Function81d70
-	ld a, [hJoyLast]
-	and D_LEFT
-	jr nz, Function81d77
-	ret
-
-Function81d70: ; 81d70
-	ld a, [hl]
-	cp $1f
-	ret nc
-	inc [hl]
-	jr Function81d7b
-
-Function81d77: ; 81d77
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-
-Function81d7b: ; 81d7b
-	call Function81e67
-	ld a, $2
-	ld [wJumptableIndex], a
-	ret
-
-Function81d84: ; 81d84
-	ld hl, wcf64
-	dec [hl]
-	ret
-
-Function81d89: ; 81d89
-	ld hl, wcf64
-	inc [hl]
-	ret
-; 81d8e
-
-Function81d8e: ; 81d8e
-	hlcoord 0, 10
-	ld bc, $a0
-	ld a, DEBUGTEST_BLACK
-	call ByteFill
-	hlcoord 2, 12
-	ld de, String_81fcd
-	call PlaceString
-	xor a
-	ld [wd004], a
-	call Function81df4
-	ld a, $5
-	ld [wJumptableIndex], a
-	ret
-; 81daf
-
-Function81daf: ; 81daf
-	ld hl, hJoyPressed
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .asm_81dbb
-	call Function81dc7
-	ret
-
-.asm_81dbb
-	ld a, $0
-	ld [wJumptableIndex], a
-	ret
-; 81dc1
-
-Function81dc1: ; 81dc1
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-; 81dc7
-
-Function81dc7: ; 81dc7
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_UP
-	jr nz, .asm_81dd5
-	ld a, [hl]
-	and D_DOWN
-	jr nz, .asm_81de2
-	ret
-
-.asm_81dd5
-	ld a, [wd004]
-	cp $3b
-	jr z, .asm_81ddf
-	inc a
-	jr .asm_81ded
-
-.asm_81ddf
-	xor a
-	jr .asm_81ded
-
-.asm_81de2
-	ld a, [wd004]
-	and a
-	jr z, .asm_81deb
-	dec a
-	jr .asm_81ded
-
-.asm_81deb
-	ld a, $3b
-
-.asm_81ded
-	ld [wd004], a
-	call Function81df4
-	ret
-; 81df4
-
-Function81df4: ; 81df4
-	hlcoord 10, 11
-	call Function81e5e
-	hlcoord 10, 12
-	call Function81e5e
-	hlcoord 10, 13
-	call Function81e5e
-	hlcoord 10, 14
-	call Function81e5e
-	ld a, [wd004]
-	inc a
-	ld [wd265], a
-	predef GetTMHMMove
-	ld a, [wd265]
-	ld [wPutativeTMHMMove], a
-	call GetMoveName
-	hlcoord 10, 12
-	call PlaceString
-	ld a, [wd004]
-	call Function81e55
-	ld [wCurItem], a
-	predef CanLearnTMHMMove
-	ld a, c
-	and a
-	ld de, String_81e46
-	jr nz, .asm_81e3f
-	ld de, String_81e4d
-
-.asm_81e3f
-	hlcoord 10, 14
-	call PlaceString
-	ret
-; 81e46
-
-String_81e46: db "おぼえられる@" ; can be taught
-String_81e4d: db "おぼえられない@" ; cannot be taught
-; 81e55
-
-Function81e55: ; 81e55
-	cp $32
-	jr c, .asm_81e5b
-	inc a
-	inc a
-
-.asm_81e5b
-	add $bf
-	ret
-; 81e5e
-
-Function81e5e: ; 81e5e
-	ld bc, 10
-	ld a, DEBUGTEST_BLACK
-	call ByteFill
-	ret
-; 81e67
-
-Function81e67: ; 81e67
-	ld a, [wc608 + 10]
-	and $1f
-	ld e, a
-	ld a, [wc608 + 11]
-	and $7
-	sla a
-	swap a
-	or e
-	ld e, a
-	ld a, [wc608 + 11]
-	and $18
-	sla a
-	swap a
-	ld d, a
-	ld a, [wc608 + 12]
-	and $1f
-	sla a
-	sla a
-	or d
-	ld d, a
-	ld a, [wcf65]
-	and a
-	jr z, .asm_81e9c
-	ld a, e
-	ld [wc608 + 2], a
-	ld a, d
-	ld [wc608 + 3], a
-	ret
-
-.asm_81e9c
-	ld a, e
-	ld [wc608], a
-	ld a, d
-	ld [wc608 + 1], a
-	ret
-; 81ea5
-
-Function81ea5: ; 81ea5
-	ld a, [de]
-	and $1f
-	ld [wc608 + 10], a
-	ld a, [de]
-	and $e0
-	swap a
-	srl a
-	ld b, a
-	inc de
-	ld a, [de]
-	and $3
-	swap a
-	srl a
-	or b
-	ld [wc608 + 11], a
-	ld a, [de]
-	and $7c
-	srl a
-	srl a
-	ld [wc608 + 12], a
-	ret
-; 81eca
-
-Function81eca: ; 81eca
-	ld a, [wcf66]
-	inc a
-	ld l, a
-	ld h, $0
-	add hl, hl
-	add hl, hl
-	ld de, wOverworldMap
-	add hl, de
-	ld e, l
-	ld d, h
-	ld hl, wc608
-	ld bc, 4
-	call CopyBytes
-	ret
-; 81ee3
-
-Function81ee3: ; 81ee3
-.asm_81ee3
-	ld a, LOW(PALRGB_WHITE)
-	ld [hli], a
-	ld a, HIGH(PALRGB_WHITE)
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hli], a
-	xor a
-	ld [hli], a
-	ld [hli], a
-	dec c
-	jr nz, .asm_81ee3
-	ret
-; 81efc
-
-Bank20_FillBoxWithByte: ; 81efc
-; For some reason, we have another copy of FillBoxWithByte here
-.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
-; 81f0c
-
-Function81f0c: ; 81f0c
-	ld a, [wcfbe]
-	push af
-	set 7, a
-	ld [wcfbe], a
-	call Function81f1d
-	pop af
-	ld [wcfbe], a
-	ret
-; 81f1d
-
-Function81f1d: ; 81f1d
-	ld a, [hl]
-	and $7
-	ret z
-	ld b, a
-.asm_81f22
-	push bc
-	xor a
-	ld [rJOYP], a
-	ld a, $30
-	ld [rJOYP], a
-	ld b, $10
-.asm_81f2c
-	ld e, $8
-	ld a, [hli]
-	ld d, a
-.asm_81f30
-	bit 0, d
-	ld a, $10
-	jr nz, .asm_81f38
-	ld a, $20
-
-.asm_81f38
-	ld [rJOYP], a
-	ld a, $30
-	ld [rJOYP], a
-	rr d
-	dec e
-	jr nz, .asm_81f30
-	dec b
-	jr nz, .asm_81f2c
-	ld a, $20
-	ld [rJOYP], a
-	ld a, $30
-	ld [rJOYP], a
-	ld de, 7000
-.asm_81f51
-	nop
-	nop
-	nop
-	dec de
-	ld a, d
-	or e
-	jr nz, .asm_81f51
-	pop bc
-	dec b
-	jr nz, .asm_81f22
-	ret
-; 81f5e
-
-Function81f5e: ; 81f5e
-	ld a, DEBUGTEST_BLACK
-	hlcoord 10, 0
-	ld [hl], a
-	hlcoord 15, 0
-	ld [hl], a
-	hlcoord 1, 11
-	ld [hl], a
-	hlcoord 1, 13
-	ld [hl], a
-	hlcoord 1, 15
-	ld [hl], a
-	ld a, [wJumptableIndex]
-	cp $3
-	jr nz, .asm_81fc9
-	ld a, [wcf64]
-	and a
-	jr z, .asm_81f8d
-	dec a
-	hlcoord 1, 11
-	ld bc, 2 * SCREEN_WIDTH
-	call AddNTimes
-	ld [hl], $ed
-
-.asm_81f8d
-	ld a, [wcf65]
-	and a
-	jr z, .asm_81f98
-	hlcoord 15, 0
-	jr .asm_81f9b
-
-.asm_81f98
-	hlcoord 10, 0
-
-.asm_81f9b
-	ld [hl], $ed
-	ld b, $70
-	ld c, $5
-	ld hl, wVirtualOAM
-	ld de, wc608 + 10
-	call .asm_81fb7
-	ld de, wc608 + 11
-	call .asm_81fb7
-	ld de, wc608 + 12
-	call .asm_81fb7
-	ret
-
-.asm_81fb7
-	ld a, b
-	ld [hli], a ; y
-	ld a, [de]
-	add a
-	add a
-	add 3 * TILE_WIDTH
-	ld [hli], a ; x
-	xor a
-	ld [hli], a ; tile id
-	ld a, c
-	ld [hli], a ; attributes
-	ld a, 2 * TILE_WIDTH
-	add b
-	ld b, a
-	inc c
-	ret
-
-.asm_81fc9
-	call ClearSprites
-	ret
-; 81fcd
-
-String_81fcd: ; 81fcd
-	db   "おわりますか?" ; Are you finished?
-	next "はい<DOT><DOT><DOT>", DEBUGTEST_A ; YES...(A)
-	next "いいえ<DOT><DOT>", DEBUGTEST_B ; NO..(B)
-	db   "@"
-; 81fe3
-
-DebugColorTestGFX:
-INCBIN "gfx/debug/color_test.2bpp"
-
-
-TilesetColorTest:
-	ret
-	xor a
-	ld [wJumptableIndex], a
-	ld [wcf64], a
-	ld [wcf65], a
-	ld [wcf66], a
-	ld [hMapAnims], a
-	call ClearSprites
-	call OverworldTextModeSwitch
-	call WaitBGMap2
-	xor a
-	ld [hBGMapMode], a
-	ld de, DebugColorTestGFX + 1 tiles
-	ld hl, vTiles2 tile DEBUGTEST_UP_ARROW
-	lb bc, BANK(DebugColorTestGFX), 22
-	call Request2bpp
-	ld de, DebugColorTestGFX
-	ld hl, vTiles1
-	lb bc, BANK(DebugColorTestGFX), 1
-	call Request2bpp
-	ld a, HIGH(vBGMap1)
-	ld [hBGMapAddress + 1], a
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, DEBUGTEST_BLACK
-	call ByteFill
-	hlcoord 0, 0, wAttrMap
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, $7
-	call ByteFill
-	ld de, $15
-	ld a, DEBUGTEST_WHITE
-	call Function821d2
-	ld de, $1a
-	ld a, DEBUGTEST_LIGHT
-	call Function821d2
-	ld de, $1f
-	ld a, DEBUGTEST_DARK
-	call Function821d2
-	ld de, $24
-	ld a, DEBUGTEST_BLACK
-	call Function821d2
-	call Function821f4
-	call Function8220f
-	call WaitBGMap2
-	ld [wJumptableIndex], a
-	ld a, $40
-	ld [hWY], a
-	ret
-; 821d2
-
-Function821d2: ; 821d2
-	hlcoord 0, 0
-	call Function821de
-
-Function821d8: ; 821d8
-	ld a, [wcf64]
-	hlcoord 0, 0, wAttrMap
-
-Function821de: ; 821de
-	add hl, de
-rept 4
-	ld [hli], a
-endr
-	ld bc, $10
-	add hl, bc
-rept 4
-	ld [hli], a
-endr
-	ld bc, $10
-	add hl, bc
-rept 4
-	ld [hli], a
-endr
-	ret
-; 821f4
-
-Function821f4: ; 821f4
-	hlcoord 2, 4
-	call Function82203
-	hlcoord 2, 6
-	call Function82203
-	hlcoord 2, 8
-
-Function82203: ; 82203
-	ld a, DEBUGTEST_UP_ARROW
-	ld [hli], a
-	ld bc, $10 - 1
-	ld a, DEBUGTEST_TICKS
-	call ByteFill
-	ret
-; 8220f
-
-Function8220f: ; 8220f
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ld [rSVBK], a
-	ld a, [wcf64]
-	ld l, a
-	ld h, $0
-	add hl, hl
-	add hl, hl
-	add hl, hl
-	ld de, wBGPals1
-	add hl, de
-	ld de, wc608
-	ld bc, 8
-	call CopyBytes
-	ld de, wc608
-	call Function81ea5
-	pop af
-	ld [rSVBK], a
-	ret
-; 82236
-
-
-Function82236: ; 82236
-	ld hl, hJoyLast
-	ld a, [hl]
-	and SELECT
-	jr nz, .loop7
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .asm_82299
-	call Function822f0
-	ret
-
-.loop7
-	ld hl, wcf64
-	ld a, [hl]
-	inc a
-	and $7
-	cp $7
-	jr nz, .asm_82253
-	xor a
-
-.asm_82253
-	ld [hl], a
-	ld de, $15
-	call Function821d8
-	ld de, $1a
-	call Function821d8
-	ld de, $1f
-	call Function821d8
-	ld de, $24
-	call Function821d8
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ld [rSVBK], a
-	ld hl, wBGPals2
-	ld a, [wcf64]
-	ld bc, 1 palettes
-	call AddNTimes
-	ld de, wc608
-	ld bc, 1 palettes
-	call CopyBytes
-	pop af
-	ld [rSVBK], a
-	ld a, $2
-	ld [hBGMapMode], a
-	ld c, 3
-	call DelayFrames
-	ld a, $1
-	ld [hBGMapMode], a
-	ret
-
-.asm_82299
-	call ClearSprites
-	ld a, [hWY]
-	xor $d0
-	ld [hWY], a
-	ret
-; 822a3
-
-Function822a3: ; 822a3
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ld [rSVBK], a
-	ld hl, wBGPals2
-	ld a, [wcf64]
-	ld bc, 1 palettes
-	call AddNTimes
-	ld e, l
-	ld d, h
-	ld hl, wc608
-	ld bc, 1 palettes
-	call CopyBytes
-	hlcoord 1, 0
-	ld de, wc608
-	call Function81ca7
-	hlcoord 6, 0
-	ld de, wc608 + 2
-	call Function81ca7
-	hlcoord 11, 0
-	ld de, wc608 + 4
-	call Function81ca7
-	hlcoord 16, 0
-	ld de, wc608 + 6
-	call Function81ca7
-	pop af
-	ld [rSVBK], a
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	call DelayFrame
-	ret
-; 822f0
-
-Function822f0: ; 822f0
-	ld a, [wcf65]
-	and 3
-	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
-; 82301
-
-.dw ; 82301
-	dw Function82309
-	dw Function82339
-	dw Function8234b
-	dw Function8235d
-; 82309
-
-Function82309: ; 82309
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, Function8238c
-	ld a, [hl]
-	and D_LEFT
-	jr nz, .asm_8231c
-	ld a, [hl]
-	and D_RIGHT
-	jr nz, .asm_82322
-	ret
-
-.asm_8231c
-	ld a, [wcf66]
-	dec a
-	jr .asm_82326
-
-.asm_82322
-	ld a, [wcf66]
-	inc a
-
-.asm_82326
-	and $3
-	ld [wcf66], a
-	ld e, a
-	ld d, $0
-	ld hl, wc608
-	add hl, de
-	add hl, de
-	ld e, l
-	ld d, h
-	call Function81ea5
-	ret
-
-Function82339: ; 82338
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, Function8238c
-	ld a, [hl]
-	and D_UP
-	jr nz, Function82387
-	ld hl, wc608 + 10
-	jr Function82368
-
-Function8234b: ; 8234b
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, Function8238c
-	ld a, [hl]
-	and D_UP
-	jr nz, Function82387
-	ld hl, wc608 + 11
-	jr Function82368
-
-Function8235d: ; 8235d
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_UP
-	jr nz, Function82387
-	ld hl, wc608 + 12
-
-Function82368: ; 82368
-	ld a, [hJoyLast]
-	and D_RIGHT
-	jr nz, .asm_82375
-	ld a, [hJoyLast]
-	and D_LEFT
-	jr nz, .asm_8237c
-	ret
-
-.asm_82375
-	ld a, [hl]
-	cp $1f
-	ret nc
-	inc [hl]
-	jr .asm_82380
-
-.asm_8237c
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-
-.asm_82380
-	call Function82391
-	call Function822a3
-	ret
-
-Function82387: ; 82387
-	ld hl, wcf65
-	dec [hl]
-	ret
-
-Function8238c: ; 8238c
-	ld hl, wcf65
-	inc [hl]
-	ret
-; 82391
-
-Function82391: ; 82391
-	ld a, [wc608 + 10]
-	and $1f
-	ld e, a
-	ld a, [wc608 + 11]
-	and $7
-	sla a
-	swap a
-	or e
-	ld e, a
-	ld a, [wc608 + 11]
-	and $18
-	sla a
-	swap a
-	ld d, a
-	ld a, [wc608 + 12]
-	and $1f
-	sla a
-	sla a
-	or d
-	ld d, a
-	ld a, [wcf66]
-	ld c, a
-	ld b, $0
-	ld hl, wc608
-	add hl, bc
-	add hl, bc
-	ld a, e
-	ld [hli], a
-	ld [hl], d
-	ret
-; 823c6
-
-Function823c6: ; 823c6
-	ret
-
-Function823c7: ; 823c7
-	ret
-; 823c8
--- a/engine/dma_transfer.asm
+++ /dev/null
@@ -1,626 +1,0 @@
-HDMATransferAttrMapAndTileMapToWRAMBank3:: ; 104000
-	ld hl, .Function
-	jp CallInSafeGFXMode
-
-.Function:
-	decoord 0, 0, wAttrMap
-	ld hl, wScratchAttrMap
-	call PadAttrMapForHDMATransfer
-	decoord 0, 0
-	ld hl, wScratchTileMap
-	call PadTilemapForHDMATransfer
-	ld a, $0
-	ld [rVBK], a
-	ld hl, wScratchTileMap
-	call HDMATransferToWRAMBank3
-	ld a, $1
-	ld [rVBK], a
-	ld hl, wScratchAttrMap
-	call HDMATransferToWRAMBank3
-	ret
-; 10402d
-
-HDMATransferTileMapToWRAMBank3:: ; 10402d
-	ld hl, .Function
-	jp CallInSafeGFXMode
-
-.Function:
-	decoord 0, 0
-	ld hl, wScratchTileMap
-	call PadTilemapForHDMATransfer
-	ld a, $0
-	ld [rVBK], a
-	ld hl, wScratchTileMap
-	call HDMATransferToWRAMBank3
-	ret
-; 104047
-
-HDMATransferAttrMapToWRAMBank3: ; 104047
-	ld hl, .Function
-	jp CallInSafeGFXMode
-
-.Function:
-	decoord 0, 0, wAttrMap
-	ld hl, wScratchAttrMap
-	call PadAttrMapForHDMATransfer
-	ld a, $1
-	ld [rVBK], a
-	ld hl, wScratchAttrMap
-	call HDMATransferToWRAMBank3
-	ret
-; 104061
-
-ReloadMapPart:: ; 104061
-	ld hl, .Function
-	jp CallInSafeGFXMode
-
-.Function:
-	decoord 0, 0, wAttrMap
-	ld hl, wScratchAttrMap
-	call PadAttrMapForHDMATransfer
-	decoord 0, 0
-	ld hl, wScratchTileMap
-	call PadTilemapForHDMATransfer
-	call DelayFrame
-
-	di
-	ld a, [rVBK]
-	push af
-	ld a, $1
-	ld [rVBK], a
-	ld hl, wScratchAttrMap
-	call HDMATransfer_Wait127Scanlines_toBGMap
-	ld a, $0
-	ld [rVBK], a
-	ld hl, wScratchTileMap
-	call HDMATransfer_Wait127Scanlines_toBGMap
-	pop af
-	ld [rVBK], a
-	ei
-
-	ret
-
-Mobile_ReloadMapPart: ; 104099
-	ld hl, ReloadMapPart ; useless
-	ld hl, .Function
-	jp CallInSafeGFXMode
-
-.Function:
-	decoord 0, 0, wAttrMap
-	ld hl, wScratchAttrMap
-	call PadAttrMapForHDMATransfer
-	decoord 0, 0
-	ld hl, wScratchTileMap
-	call PadTilemapForHDMATransfer
-	call DelayFrame
-
-	di
-	ld a, [rVBK]
-	push af
-	ld a, $1
-	ld [rVBK], a
-	ld hl, wScratchAttrMap
-	call HDMATransfer_NoDI
-	ld a, $0
-	ld [rVBK], a
-	ld hl, wScratchTileMap
-	call HDMATransfer_NoDI
-	pop af
-	ld [rVBK], a
-	ei
-
-	ret
-; 1040d4
-
-; unused
-	ld hl, .unreferenced_1040da
-	jp CallInSafeGFXMode
-
-.unreferenced_1040da
-	ld a, $1
-	ld [rVBK], a
-	ld a, BANK(w3_d800)
-	ld [rSVBK], a
-	ld de, w3_d800
-	ld a, [hBGMapAddress + 1]
-	ld [rHDMA1], a
-	ld a, [hBGMapAddress]
-	ld [rHDMA2], a
-	ld a, d
-	ld [rHDMA3], a
-	ld a, e
-	ld [rHDMA4], a
-	ld a, $23
-	ld [hDMATransfer], a
-	call WaitDMATransfer
-	ret
-; 1040fb
-
-; unused
-	ld hl, .unreferenced_104101
-	jp CallInSafeGFXMode
-
-.unreferenced_104101
-	ld a, $1
-	ld [rVBK], a
-	ld a, BANK(w3_d800)
-	ld [rSVBK], a
-	ld hl, w3_d800
-	call HDMATransferToWRAMBank3
-	ret
-; 104110
-
-OpenAndCloseMenu_HDMATransferTileMapAndAttrMap:: ; 104110
-; OpenText
-	ld hl, .Function
-	jp CallInSafeGFXMode
-
-.Function:
-	; Transfer wAttrMap and Tilemap to BGMap
-	; Fill vBGAttrs with $00
-	; Fill vBGTiles with " "
-	decoord 0, 0, wAttrMap
-	ld hl, wScratchAttrMap
-	call PadAttrMapForHDMATransfer
-	decoord 0, 0
-	ld hl, wScratchTileMap
-	call PadTilemapForHDMATransfer
-	call DelayFrame
-
-	di
-	ld a, [rVBK]
-	push af
-	ld a, $1
-	ld [rVBK], a
-	ld hl, wScratchAttrMap
-	call HDMATransfer_Wait123Scanlines_toBGMap
-	ld a, $0
-	ld [rVBK], a
-	ld hl, wScratchTileMap
-	call HDMATransfer_Wait123Scanlines_toBGMap
-	pop af
-	ld [rVBK], a
-	ei
-	ret
-; 104148
-
-Mobile_OpenAndCloseMenu_HDMATransferTileMapAndAttrMap: ; 104148 (41:4148)
-	ld hl, .Function
-	jp CallInSafeGFXMode
-
-.Function:
-	; Transfer wAttrMap and Tilemap to BGMap
-	; Fill vBGAttrs with $00
-	; Fill vBGTiles with $ff
-	decoord 0, 0, wAttrMap
-	ld hl, wScratchAttrMap
-	call PadAttrMapForHDMATransfer
-	ld c, $ff
-	decoord 0, 0
-	ld hl, wScratchTileMap
-	call PadMapForHDMATransfer
-
-	ld a, $1
-	ld [rVBK], a
-	ld hl, wScratchAttrMap
-	call HDMATransfer_Wait127Scanlines_toBGMap
-	ld a, $0
-	ld [rVBK], a
-	ld hl, wScratchTileMap
-	call HDMATransfer_Wait127Scanlines_toBGMap
-	ret
-; 104177
-
-CallInSafeGFXMode: ; 104177
-	ld a, [hBGMapMode]
-	push af
-	ld a, [hMapAnims]
-	push af
-	xor a
-	ld [hBGMapMode], a
-	ld [hMapAnims], a
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wScratchTileMap)
-	ld [rSVBK], a
-	ld a, [rVBK]
-	push af
-
-	call ._hl_
-
-	pop af
-	ld [rVBK], a
-	pop af
-	ld [rSVBK], a
-	pop af
-	ld [hMapAnims], a
-	pop af
-	ld [hBGMapMode], a
-	ret
-; 10419c
-
-._hl_ ; 10419c
-	jp hl
-; 10419d
-
-
-HDMATransferToWRAMBank3: ; 10419d (41:419d)
-	call _LoadHDMAParameters
-	ld a, $23
-	ld [hDMATransfer], a
-
-WaitDMATransfer: ; 104a14
-.loop
-	call DelayFrame
-	ld a, [hDMATransfer]
-	and a
-	jr nz, .loop
-	ret
-
-HDMATransfer_Wait127Scanlines_toBGMap: ; 1041ad (41:41ad)
-; HDMA transfer from hl to [hBGMapAddress]
-; hBGMapAddress -> de
-; 2 * SCREEN_HEIGHT -> c
-	ld a, [hBGMapAddress + 1]
-	ld d, a
-	ld a, [hBGMapAddress]
-	ld e, a
-	ld c, 2 * SCREEN_HEIGHT
-	jr HDMATransfer_Wait127Scanlines
-
-HDMATransfer_Wait123Scanlines_toBGMap: ; 1041b7 (41:41b7)
-; HDMA transfer from hl to [hBGMapAddress]
-; hBGMapAddress -> de
-; 2 * SCREEN_HEIGHT -> c
-; $7b --> b
-	ld a, [hBGMapAddress + 1]
-	ld d, a
-	ld a, [hBGMapAddress]
-	ld e, a
-	ld c, 2 * SCREEN_HEIGHT
-	jr HDMATransfer_Wait123Scanlines
-; 1041c1 (41:41c1)
-
-HDMATransfer_NoDI: ; 1041c1
-; HDMA transfer from hl to [hBGMapAddress]
-; [hBGMapAddress] --> de
-; 2 * SCREEN_HEIGHT --> c
-	ld a, [hBGMapAddress + 1]
-	ld d, a
-	ld a, [hBGMapAddress]
-	ld e, a
-	ld c, 2 * SCREEN_HEIGHT
-
-	; [rHDMA1, rHDMA2] = hl & $fff0
-	ld a, h
-	ld [rHDMA1], a
-	ld a, l
-	and $f0
-	ld [rHDMA2], a
-	; [rHDMA3, rHDMA4] = de & $1ff0
-	ld a, d
-	and $1f
-	ld [rHDMA3], a
-	ld a, e
-	and $f0
-	ld [rHDMA4], a
-	; b = c | %10000000
-	ld a, c
-	dec c
-	or $80
-	ld b, a
-	; d = $7f - c + 1
-	ld a, $7f
-	sub c
-	ld d, a
-	; while [rLY] >= d: pass
-.loop1
-	ld a, [rLY]
-	cp d
-	jr nc, .loop1
-	; while not [rSTAT] & 3: pass
-.loop2
-	ld a, [rSTAT]
-	and $3
-	jr z, .loop2
-	; load the 5th byte of HDMA
-	ld a, b
-	ld [rHDMA5], a
-	; wait until rLY advances (c + 1) times
-	ld a, [rLY]
-	inc c
-	ld hl, rLY
-.loop3
-	cp [hl]
-	jr z, .loop3
-	ld a, [hl]
-	dec c
-	jr nz, .loop3
-	ld hl, rHDMA5
-	res 7, [hl]
-	ret
-; 104205
-
-HDMATransfer_Wait123Scanlines:
-	ld b, $7b
-	jr _continue_HDMATransfer
-
-
-HDMATransfer_Wait127Scanlines:
-	ld b, $7f
-_continue_HDMATransfer:
-; a lot of waiting around for hardware registers
-	; [rHDMA1, rHDMA2] = hl & $fff0
-	ld a, h
-	ld [rHDMA1], a
-	ld a, l
-	and $f0 ; high nybble
-	ld [rHDMA2], a
-	; [rHDMA3, rHDMA4] = de & $1ff0
-	ld a, d
-	and $1f ; lower 5 bits
-	ld [rHDMA3], a
-	ld a, e
-	and $f0 ; high nybble
-	ld [rHDMA4], a
-	; e = c | %10000000
-	ld a, c
-	dec c
-	or $80
-	ld e, a
-	; d = b - c + 1
-	ld a, b
-	sub c
-	ld d, a
-	; while [rLY] >= d: pass
-.ly_loop
-	ld a, [rLY]
-	cp d
-	jr nc, .ly_loop
-
-	di
-	; while [rSTAT] & 3: pass
-.rstat_loop_1
-	ld a, [rSTAT]
-	and $3
-	jr nz, .rstat_loop_1
-	; while not [rSTAT] & 3: pass
-.rstat_loop_2
-	ld a, [rSTAT]
-	and $3
-	jr z, .rstat_loop_2
-	; load the 5th byte of HDMA
-	ld a, e
-	ld [rHDMA5], a
-	; wait until rLY advances (c + 1) times
-	ld a, [rLY]
-	inc c
-	ld hl, rLY
-.final_ly_loop
-	cp [hl]
-	jr z, .final_ly_loop
-	ld a, [hl]
-	dec c
-	jr nz, .final_ly_loop
-	ld hl, rHDMA5
-	res 7, [hl]
-	ei
-
-	ret
-; 10424e
-
-
-_LoadHDMAParameters: ; 10424e (41:424e)
-	ld a, h
-	ld [rHDMA1], a
-	ld a, l
-	ld [rHDMA2], a
-	ld a, [hBGMapAddress + 1]
-	and $1f
-	ld [rHDMA3], a
-	ld a, [hBGMapAddress]
-	ld [rHDMA4], a
-	ret
-
-PadTilemapForHDMATransfer: ; 10425f (41:425f)
-	ld c, " "
-	jr PadMapForHDMATransfer
-
-PadAttrMapForHDMATransfer: ; 104263 (41:4263)
-	ld c, $0
-
-PadMapForHDMATransfer: ; 104265 (41:4265)
-; pad a 20x18 map to 32x18 for HDMA transfer
-; back up the padding value in c to hMapObjectIndexBuffer
-	ld a, [hMapObjectIndexBuffer]
-	push af
-	ld a, c
-	ld [hMapObjectIndexBuffer], a
-
-; for each row on the screen
-	ld c, SCREEN_HEIGHT
-.loop1
-; for each tile in the row
-	ld b, SCREEN_WIDTH
-.loop2
-; copy from de to hl
-	ld a, [de]
-	inc de
-	ld [hli], a
-	dec b
-	jr nz, .loop2
-
-; load the original padding value of c into hl for 32 - 20 = 12 rows
-	ld a, [hMapObjectIndexBuffer]
-	ld b, BG_MAP_WIDTH - SCREEN_WIDTH
-.loop3
-	ld [hli], a
-	dec b
-	jr nz, .loop3
-
-	dec c
-	jr nz, .loop1
-
-; restore the original value of hMapObjectIndexBuffer
-	pop af
-	ld [hMapObjectIndexBuffer], a
-	ret
-
-
-_Get2bpp:: ; 104284
-	; 2bpp when [rLCDC] & $80
-	; switch to WRAM bank 6
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wScratchTileMap)
-	ld [rSVBK], a
-
-	push bc
-	push hl
-
-	; Copy c tiles of the 2bpp from b:de to wScratchTileMap
-	ld a, b ; bank
-	ld l, c ; number of tiles
-	ld h, $0
-	; multiply by 16 (16 bytes of a 2bpp = 8 x 8 tile)
-	add hl, hl
-	add hl, hl
-	add hl, hl
-	add hl, hl
-	ld b, h
-	ld c, l
-	ld h, d ; address
-	ld l, e
-	ld de, wScratchTileMap
-	call FarCopyBytes
-
-	pop hl
-	pop bc
-
-	push bc
-	call DelayFrame
-	pop bc
-
-	ld d, h
-	ld e, l
-	ld hl, wScratchTileMap
-	call HDMATransfer_Wait127Scanlines
-
-	; restore the previous bank
-	pop af
-	ld [rSVBK], a
-	ret
-; 1042b2
-
-_Get1bpp:: ; 1042b2
-	; 1bpp when [rLCDC] & $80
-.loop
-	ld a, c
-	cp $10
-	jp c, .bankswitch
-	jp z, .bankswitch
-	push bc
-	push hl
-	push de
-	ld c, $10
-	call .bankswitch
-	pop de
-	ld hl, $80
-	add hl, de
-	ld d, h
-	ld e, l
-	pop hl
-	lb bc, 1, 0
-	add hl, bc
-	pop bc
-	ld a, c
-	sub $10
-	ld c, a
-	jr .loop
-; 1042d6
-
-.bankswitch ; 1042d6
-	ld a, [rSVBK]
-	push af
-	ld a, BANK(wScratchTileMap)
-	ld [rSVBK], a
-
-	push bc
-	push hl
-
-	ld a, b
-	ld l, c
-	ld h, $0
-	add hl, hl ; multiply by 8
-	add hl, hl ; multiply by 8
-	add hl, hl ; multiply by 8
-	ld c, l
-	ld b, h
-	ld h, d
-	ld l, e
-	ld de, wScratchTileMap
-	call FarCopyBytesDouble_DoubleBankSwitch
-
-	pop hl
-	pop bc
-
-	push bc
-	call DelayFrame
-	pop bc
-
-	ld d, h
-	ld e, l
-	ld hl, wScratchTileMap
-	call HDMATransfer_Wait127Scanlines
-
-	pop af
-	ld [rSVBK], a
-	ret
-; 104303
-
-HDMATransfer_OnlyTopFourRows: ; 104303
-	ld hl, .Function
-	jp CallInSafeGFXMode
-; 104309
-
-.Function:
-	ld hl, wScratchTileMap
-	decoord 0, 0
-	call .Copy
-	ld hl, wScratchTileMap + $80
-	decoord 0, 0, wAttrMap
-	call .Copy
-	ld a, $1
-	ld [rVBK], a
-	ld c, $8
-	ld hl, wScratchTileMap + $80
-	debgcoord 0, 0, vBGMap1
-	call HDMATransfer_Wait127Scanlines
-	ld a, $0
-	ld [rVBK], a
-	ld c, $8
-	ld hl, wScratchTileMap
-	debgcoord 0, 0, vBGMap1
-	call HDMATransfer_Wait127Scanlines
-	ret
-
-.Copy: ; 10433a (41:433a)
-	ld b, 4
-.outer_loop
-	ld c, SCREEN_WIDTH
-.inner_loop
-	ld a, [de]
-	ld [hli], a
-	inc de
-	dec c
-	jr nz, .inner_loop
-	ld a, l
-	add BG_MAP_WIDTH - SCREEN_WIDTH
-	ld l, a
-	ld a, h
-	adc 0
-	ld h, a
-	dec b
-	jr nz, .outer_loop
-	ret
-; 104350
--- a/engine/engine_flags.asm
+++ /dev/null
@@ -1,86 +1,0 @@
-EngineFlagAction:: ; 80430
-; Do action b on engine flag de
-;
-;   b = 0: reset flag
-;     = 1: set flag
-;     > 1: check flag, result in c
-;
-; Setting/resetting does not return a result.
-
-
-; 16-bit flag ids are considered invalid, but it's nice
-; to know that the infrastructure is there.
-
-	ld a, d
-	cp 0
-	jr z, .ceiling
-	jr c, .read ; cp 0 can't set carry!
-	jr .invalid
-
-; There are only $a2 engine flags, so
-; anything beyond that is invalid too.
-
-.ceiling
-	ld a, e
-	cp NUM_ENGINE_FLAGS
-	jr c, .read
-
-; Invalid flags are treated as flag 00.
-
-.invalid
-	xor a
-	ld e, a
-	ld d, a
-
-; Get this flag's location.
-
-.read
-	ld hl, EngineFlags
-; location
-	add hl, de
-	add hl, de
-; bit
-	add hl, de
-
-; location
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	inc hl
-; bit
-	ld c, [hl]
-
-; What are we doing with this flag?
-
-	ld a, b
-	cp 1
-	jr c, .reset ; b = 0
-	jr z, .set   ; b = 1
-
-; Return the given flag in c.
-.check
-	ld a, [de]
-	and c
-	ld c, a
-	ret
-
-; Set the given flag.
-.set
-	ld a, [de]
-	or c
-	ld [de], a
-	ret
-
-; Reset the given flag.
-.reset
-	ld a, c
-	cpl ; AND all bits except the one in question
-	ld c, a
-	ld a, [de]
-	and c
-	ld [de], a
-	ret
-; 80462
-
-
-INCLUDE "data/engine_flags.asm"
--- /dev/null
+++ b/engine/events/checksave.asm
@@ -1,0 +1,20 @@
+CheckSave:: ; 4cffe
+	ld a, BANK(sCheckValue1) ; BANK(sCheckValue2)
+	call GetSRAMBank
+	ld a, [sCheckValue1]
+	ld b, a
+	ld a, [sCheckValue2]
+	ld c, a
+	call CloseSRAM
+	ld a, b
+	cp SAVE_CHECK_VALUE_1
+	jr nz, .ok
+	ld a, c
+	cp SAVE_CHECK_VALUE_2
+	jr nz, .ok
+	ld c, $1
+	ret
+
+.ok
+	ld c, $0
+	ret
--- /dev/null
+++ b/engine/events/checktime.asm
@@ -1,0 +1,19 @@
+CheckTime:: ; c000
+	ld a, [wTimeOfDay]
+	ld hl, .TimeOfDayTable
+	ld de, 2
+	call IsInArray
+	inc hl
+	ld c, [hl]
+	ret c
+
+	xor a
+	ld c, a
+	ret
+
+.TimeOfDayTable: ; c012
+	db MORN_F, MORN
+	db DAY_F,  DAY
+	db NITE_F, NITE
+	db NITE_F, NITE
+	db -1
--- /dev/null
+++ b/engine/events/engine_flags.asm
@@ -1,0 +1,86 @@
+EngineFlagAction:: ; 80430
+; Do action b on engine flag de
+;
+;   b = 0: reset flag
+;     = 1: set flag
+;     > 1: check flag, result in c
+;
+; Setting/resetting does not return a result.
+
+
+; 16-bit flag ids are considered invalid, but it's nice
+; to know that the infrastructure is there.
+
+	ld a, d
+	cp 0
+	jr z, .ceiling
+	jr c, .read ; cp 0 can't set carry!
+	jr .invalid
+
+; There are only $a2 engine flags, so
+; anything beyond that is invalid too.
+
+.ceiling
+	ld a, e
+	cp NUM_ENGINE_FLAGS
+	jr c, .read
+
+; Invalid flags are treated as flag 00.
+
+.invalid
+	xor a
+	ld e, a
+	ld d, a
+
+; Get this flag's location.
+
+.read
+	ld hl, EngineFlags
+; location
+	add hl, de
+	add hl, de
+; bit
+	add hl, de
+
+; location
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	inc hl
+; bit
+	ld c, [hl]
+
+; What are we doing with this flag?
+
+	ld a, b
+	cp 1
+	jr c, .reset ; b = 0
+	jr z, .set   ; b = 1
+
+; Return the given flag in c.
+.check
+	ld a, [de]
+	and c
+	ld c, a
+	ret
+
+; Set the given flag.
+.set
+	ld a, [de]
+	or c
+	ld [de], a
+	ret
+
+; Reset the given flag.
+.reset
+	ld a, c
+	cpl ; AND all bits except the one in question
+	ld c, a
+	ld a, [de]
+	and c
+	ld [de], a
+	ret
+; 80462
+
+
+INCLUDE "data/engine_flags.asm"
--- /dev/null
+++ b/engine/events/money.asm
@@ -1,0 +1,221 @@
+GiveMoney:: ; 15fd7
+	ld a, 3
+	call AddMoney
+	ld bc, MaxMoney
+	ld a, 3
+	call CompareMoney
+	jr z, .not_maxed_out
+	jr c, .not_maxed_out
+	ld hl, MaxMoney
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hli]
+	ld [de], a
+	scf
+	ret
+
+.not_maxed_out
+	and a
+	ret
+; 15ff7
+
+MaxMoney: ; 15ff7
+	dt MAX_MONEY
+; 15ffa
+
+
+TakeMoney:: ; 15ffa
+	ld a, 3
+	call SubtractMoney
+	jr nc, .okay
+	; leave with 0 money
+	xor a
+	ld [de], a
+	inc de
+	ld [de], a
+	inc de
+	ld [de], a
+	scf
+	ret
+
+.okay
+	and a
+	ret
+; 1600b
+
+CompareMoney:: ; 1600b
+	ld a, 3
+CompareFunds: ; 1600d
+; a: number of bytes
+; bc: start addr of amount (big-endian)
+; de: start addr of account (big-endian)
+	push hl
+	push de
+	push bc
+	ld h, b
+	ld l, c
+	ld c, 0
+	ld b, a
+.loop1
+	dec a
+	jr z, .done
+	inc de
+	inc hl
+	jr .loop1
+
+.done
+	and a
+.loop2
+	ld a, [de]
+	sbc [hl]
+	jr z, .okay
+	inc c
+
+.okay
+	dec de
+	dec hl
+	dec b
+	jr nz, .loop2
+	jr c, .set_carry
+	ld a, c
+	and a
+	jr .skip_carry
+
+.set_carry
+	ld a, 1
+	and a
+	scf
+.skip_carry
+	pop bc
+	pop de
+	pop hl
+	ret
+; 16035
+
+SubtractMoney: ; 16035
+	ld a, 3
+SubtractFunds: ; 16037
+; a: number of bytes
+; bc: start addr of amount (big-endian)
+; de: start addr of account (big-endian)
+	push hl
+	push de
+	push bc
+	ld h, b
+	ld l, c
+	ld b, a
+	ld c, 0
+.loop
+	dec a
+	jr z, .done
+	inc de
+	inc hl
+	jr .loop
+
+.done
+	and a
+.loop2
+	ld a, [de]
+	sbc [hl]
+	ld [de], a
+	dec de
+	dec hl
+	dec b
+	jr nz, .loop2
+	pop bc
+	pop de
+	pop hl
+	ret
+; 16053
+
+AddMoney: ; 16053
+	ld a, 3
+AddFunds: ; 16055
+; a: number of bytes
+; bc: start addr of amount (big-endian)
+; de: start addr of account (big-endian)
+	push hl
+	push de
+	push bc
+
+	ld h, b
+	ld l, c
+	ld b, a
+.loop1
+	dec a
+	jr z, .done
+	inc de
+	inc hl
+	jr .loop1
+
+.done
+	and a
+.loop2
+	ld a, [de]
+	adc [hl]
+	ld [de], a
+	dec de
+	dec hl
+	dec b
+	jr nz, .loop2
+
+	pop bc
+	pop de
+	pop hl
+	ret
+; 1606f
+
+GiveCoins:: ; 1606f
+	ld a, 2
+	ld de, wCoins
+	call AddFunds
+	ld a, 2
+	ld bc, .maxcoins
+	call CompareFunds
+	jr c, .not_maxed
+	ld hl, .maxcoins
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hli]
+	ld [de], a
+	scf
+	ret
+
+.not_maxed
+	and a
+	ret
+; 1608d
+
+.maxcoins ; 1608d
+	bigdw MAX_COINS
+; 1608f
+
+
+TakeCoins:: ; 1608f
+	ld a, 2
+	ld de, wCoins
+	call SubtractFunds
+	jr nc, .okay
+	; leave with 0 coins
+	xor a
+	ld [de], a
+	inc de
+	ld [de], a
+	scf
+	ret
+
+.okay
+	and a
+	ret
+; 160a1
+
+CheckCoins:: ; 160a1
+	ld a, 2
+	ld de, wCoins
+	jp CompareFunds
+; 160a9
--- /dev/null
+++ b/engine/events/playslowcry.asm
@@ -1,0 +1,31 @@
+PlaySlowCry: ; fb841
+	ld a, [wScriptVar]
+	call LoadCry
+	jr c, .done
+
+	ld hl, wCryPitch
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld bc, -$140
+	add hl, bc
+	ld a, l
+	ld [wCryPitch], a
+	ld a, h
+	ld [wCryPitch + 1], a
+	ld hl, wCryLength
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld bc, $60
+	add hl, bc
+	ld a, l
+	ld [wCryLength], a
+	ld a, h
+	ld [wCryLength + 1], a
+	farcall _PlayCry
+	call WaitSFX
+
+.done
+	ret
+; fb877
--- a/engine/gfx/crystal_layouts.asm
+++ b/engine/gfx/crystal_layouts.asm
@@ -203,7 +203,7 @@
 	ret
 ; 494ac
 
-INCLUDE "engine/gfx/tileset_palettes.asm"
+INCLUDE "engine/tilesets/tileset_palettes.asm"
 
 MG_Mobile_Layout02: ; 49706
 	ld hl, .Palette_49732
--- /dev/null
+++ b/engine/gfx/dma_transfer.asm
@@ -1,0 +1,626 @@
+HDMATransferAttrMapAndTileMapToWRAMBank3:: ; 104000
+	ld hl, .Function
+	jp CallInSafeGFXMode
+
+.Function:
+	decoord 0, 0, wAttrMap
+	ld hl, wScratchAttrMap
+	call PadAttrMapForHDMATransfer
+	decoord 0, 0
+	ld hl, wScratchTileMap
+	call PadTilemapForHDMATransfer
+	ld a, $0
+	ld [rVBK], a
+	ld hl, wScratchTileMap
+	call HDMATransferToWRAMBank3
+	ld a, $1
+	ld [rVBK], a
+	ld hl, wScratchAttrMap
+	call HDMATransferToWRAMBank3
+	ret
+; 10402d
+
+HDMATransferTileMapToWRAMBank3:: ; 10402d
+	ld hl, .Function
+	jp CallInSafeGFXMode
+
+.Function:
+	decoord 0, 0
+	ld hl, wScratchTileMap
+	call PadTilemapForHDMATransfer
+	ld a, $0
+	ld [rVBK], a
+	ld hl, wScratchTileMap
+	call HDMATransferToWRAMBank3
+	ret
+; 104047
+
+HDMATransferAttrMapToWRAMBank3: ; 104047
+	ld hl, .Function
+	jp CallInSafeGFXMode
+
+.Function:
+	decoord 0, 0, wAttrMap
+	ld hl, wScratchAttrMap
+	call PadAttrMapForHDMATransfer
+	ld a, $1
+	ld [rVBK], a
+	ld hl, wScratchAttrMap
+	call HDMATransferToWRAMBank3
+	ret
+; 104061
+
+ReloadMapPart:: ; 104061
+	ld hl, .Function
+	jp CallInSafeGFXMode
+
+.Function:
+	decoord 0, 0, wAttrMap
+	ld hl, wScratchAttrMap
+	call PadAttrMapForHDMATransfer
+	decoord 0, 0
+	ld hl, wScratchTileMap
+	call PadTilemapForHDMATransfer
+	call DelayFrame
+
+	di
+	ld a, [rVBK]
+	push af
+	ld a, $1
+	ld [rVBK], a
+	ld hl, wScratchAttrMap
+	call HDMATransfer_Wait127Scanlines_toBGMap
+	ld a, $0
+	ld [rVBK], a
+	ld hl, wScratchTileMap
+	call HDMATransfer_Wait127Scanlines_toBGMap
+	pop af
+	ld [rVBK], a
+	ei
+
+	ret
+
+Mobile_ReloadMapPart: ; 104099
+	ld hl, ReloadMapPart ; useless
+	ld hl, .Function
+	jp CallInSafeGFXMode
+
+.Function:
+	decoord 0, 0, wAttrMap
+	ld hl, wScratchAttrMap
+	call PadAttrMapForHDMATransfer
+	decoord 0, 0
+	ld hl, wScratchTileMap
+	call PadTilemapForHDMATransfer
+	call DelayFrame
+
+	di
+	ld a, [rVBK]
+	push af
+	ld a, $1
+	ld [rVBK], a
+	ld hl, wScratchAttrMap
+	call HDMATransfer_NoDI
+	ld a, $0
+	ld [rVBK], a
+	ld hl, wScratchTileMap
+	call HDMATransfer_NoDI
+	pop af
+	ld [rVBK], a
+	ei
+
+	ret
+; 1040d4
+
+; unused
+	ld hl, .unreferenced_1040da
+	jp CallInSafeGFXMode
+
+.unreferenced_1040da
+	ld a, $1
+	ld [rVBK], a
+	ld a, BANK(w3_d800)
+	ld [rSVBK], a
+	ld de, w3_d800
+	ld a, [hBGMapAddress + 1]
+	ld [rHDMA1], a
+	ld a, [hBGMapAddress]
+	ld [rHDMA2], a
+	ld a, d
+	ld [rHDMA3], a
+	ld a, e
+	ld [rHDMA4], a
+	ld a, $23
+	ld [hDMATransfer], a
+	call WaitDMATransfer
+	ret
+; 1040fb
+
+; unused
+	ld hl, .unreferenced_104101
+	jp CallInSafeGFXMode
+
+.unreferenced_104101
+	ld a, $1
+	ld [rVBK], a
+	ld a, BANK(w3_d800)
+	ld [rSVBK], a
+	ld hl, w3_d800
+	call HDMATransferToWRAMBank3
+	ret
+; 104110
+
+OpenAndCloseMenu_HDMATransferTileMapAndAttrMap:: ; 104110
+; OpenText
+	ld hl, .Function
+	jp CallInSafeGFXMode
+
+.Function:
+	; Transfer wAttrMap and Tilemap to BGMap
+	; Fill vBGAttrs with $00
+	; Fill vBGTiles with " "
+	decoord 0, 0, wAttrMap
+	ld hl, wScratchAttrMap
+	call PadAttrMapForHDMATransfer
+	decoord 0, 0
+	ld hl, wScratchTileMap
+	call PadTilemapForHDMATransfer
+	call DelayFrame
+
+	di
+	ld a, [rVBK]
+	push af
+	ld a, $1
+	ld [rVBK], a
+	ld hl, wScratchAttrMap
+	call HDMATransfer_Wait123Scanlines_toBGMap
+	ld a, $0
+	ld [rVBK], a
+	ld hl, wScratchTileMap
+	call HDMATransfer_Wait123Scanlines_toBGMap
+	pop af
+	ld [rVBK], a
+	ei
+	ret
+; 104148
+
+Mobile_OpenAndCloseMenu_HDMATransferTileMapAndAttrMap: ; 104148 (41:4148)
+	ld hl, .Function
+	jp CallInSafeGFXMode
+
+.Function:
+	; Transfer wAttrMap and Tilemap to BGMap
+	; Fill vBGAttrs with $00
+	; Fill vBGTiles with $ff
+	decoord 0, 0, wAttrMap
+	ld hl, wScratchAttrMap
+	call PadAttrMapForHDMATransfer
+	ld c, $ff
+	decoord 0, 0
+	ld hl, wScratchTileMap
+	call PadMapForHDMATransfer
+
+	ld a, $1
+	ld [rVBK], a
+	ld hl, wScratchAttrMap
+	call HDMATransfer_Wait127Scanlines_toBGMap
+	ld a, $0
+	ld [rVBK], a
+	ld hl, wScratchTileMap
+	call HDMATransfer_Wait127Scanlines_toBGMap
+	ret
+; 104177
+
+CallInSafeGFXMode: ; 104177
+	ld a, [hBGMapMode]
+	push af
+	ld a, [hMapAnims]
+	push af
+	xor a
+	ld [hBGMapMode], a
+	ld [hMapAnims], a
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wScratchTileMap)
+	ld [rSVBK], a
+	ld a, [rVBK]
+	push af
+
+	call ._hl_
+
+	pop af
+	ld [rVBK], a
+	pop af
+	ld [rSVBK], a
+	pop af
+	ld [hMapAnims], a
+	pop af
+	ld [hBGMapMode], a
+	ret
+; 10419c
+
+._hl_ ; 10419c
+	jp hl
+; 10419d
+
+
+HDMATransferToWRAMBank3: ; 10419d (41:419d)
+	call _LoadHDMAParameters
+	ld a, $23
+	ld [hDMATransfer], a
+
+WaitDMATransfer: ; 104a14
+.loop
+	call DelayFrame
+	ld a, [hDMATransfer]
+	and a
+	jr nz, .loop
+	ret
+
+HDMATransfer_Wait127Scanlines_toBGMap: ; 1041ad (41:41ad)
+; HDMA transfer from hl to [hBGMapAddress]
+; hBGMapAddress -> de
+; 2 * SCREEN_HEIGHT -> c
+	ld a, [hBGMapAddress + 1]
+	ld d, a
+	ld a, [hBGMapAddress]
+	ld e, a
+	ld c, 2 * SCREEN_HEIGHT
+	jr HDMATransfer_Wait127Scanlines
+
+HDMATransfer_Wait123Scanlines_toBGMap: ; 1041b7 (41:41b7)
+; HDMA transfer from hl to [hBGMapAddress]
+; hBGMapAddress -> de
+; 2 * SCREEN_HEIGHT -> c
+; $7b --> b
+	ld a, [hBGMapAddress + 1]
+	ld d, a
+	ld a, [hBGMapAddress]
+	ld e, a
+	ld c, 2 * SCREEN_HEIGHT
+	jr HDMATransfer_Wait123Scanlines
+; 1041c1 (41:41c1)
+
+HDMATransfer_NoDI: ; 1041c1
+; HDMA transfer from hl to [hBGMapAddress]
+; [hBGMapAddress] --> de
+; 2 * SCREEN_HEIGHT --> c
+	ld a, [hBGMapAddress + 1]
+	ld d, a
+	ld a, [hBGMapAddress]
+	ld e, a
+	ld c, 2 * SCREEN_HEIGHT
+
+	; [rHDMA1, rHDMA2] = hl & $fff0
+	ld a, h
+	ld [rHDMA1], a
+	ld a, l
+	and $f0
+	ld [rHDMA2], a
+	; [rHDMA3, rHDMA4] = de & $1ff0
+	ld a, d
+	and $1f
+	ld [rHDMA3], a
+	ld a, e
+	and $f0
+	ld [rHDMA4], a
+	; b = c | %10000000
+	ld a, c
+	dec c
+	or $80
+	ld b, a
+	; d = $7f - c + 1
+	ld a, $7f
+	sub c
+	ld d, a
+	; while [rLY] >= d: pass
+.loop1
+	ld a, [rLY]
+	cp d
+	jr nc, .loop1
+	; while not [rSTAT] & 3: pass
+.loop2
+	ld a, [rSTAT]
+	and $3
+	jr z, .loop2
+	; load the 5th byte of HDMA
+	ld a, b
+	ld [rHDMA5], a
+	; wait until rLY advances (c + 1) times
+	ld a, [rLY]
+	inc c
+	ld hl, rLY
+.loop3
+	cp [hl]
+	jr z, .loop3
+	ld a, [hl]
+	dec c
+	jr nz, .loop3
+	ld hl, rHDMA5
+	res 7, [hl]
+	ret
+; 104205
+
+HDMATransfer_Wait123Scanlines:
+	ld b, $7b
+	jr _continue_HDMATransfer
+
+
+HDMATransfer_Wait127Scanlines:
+	ld b, $7f
+_continue_HDMATransfer:
+; a lot of waiting around for hardware registers
+	; [rHDMA1, rHDMA2] = hl & $fff0
+	ld a, h
+	ld [rHDMA1], a
+	ld a, l
+	and $f0 ; high nybble
+	ld [rHDMA2], a
+	; [rHDMA3, rHDMA4] = de & $1ff0
+	ld a, d
+	and $1f ; lower 5 bits
+	ld [rHDMA3], a
+	ld a, e
+	and $f0 ; high nybble
+	ld [rHDMA4], a
+	; e = c | %10000000
+	ld a, c
+	dec c
+	or $80
+	ld e, a
+	; d = b - c + 1
+	ld a, b
+	sub c
+	ld d, a
+	; while [rLY] >= d: pass
+.ly_loop
+	ld a, [rLY]
+	cp d
+	jr nc, .ly_loop
+
+	di
+	; while [rSTAT] & 3: pass
+.rstat_loop_1
+	ld a, [rSTAT]
+	and $3
+	jr nz, .rstat_loop_1
+	; while not [rSTAT] & 3: pass
+.rstat_loop_2
+	ld a, [rSTAT]
+	and $3
+	jr z, .rstat_loop_2
+	; load the 5th byte of HDMA
+	ld a, e
+	ld [rHDMA5], a
+	; wait until rLY advances (c + 1) times
+	ld a, [rLY]
+	inc c
+	ld hl, rLY
+.final_ly_loop
+	cp [hl]
+	jr z, .final_ly_loop
+	ld a, [hl]
+	dec c
+	jr nz, .final_ly_loop
+	ld hl, rHDMA5
+	res 7, [hl]
+	ei
+
+	ret
+; 10424e
+
+
+_LoadHDMAParameters: ; 10424e (41:424e)
+	ld a, h
+	ld [rHDMA1], a
+	ld a, l
+	ld [rHDMA2], a
+	ld a, [hBGMapAddress + 1]
+	and $1f
+	ld [rHDMA3], a
+	ld a, [hBGMapAddress]
+	ld [rHDMA4], a
+	ret
+
+PadTilemapForHDMATransfer: ; 10425f (41:425f)
+	ld c, " "
+	jr PadMapForHDMATransfer
+
+PadAttrMapForHDMATransfer: ; 104263 (41:4263)
+	ld c, $0
+
+PadMapForHDMATransfer: ; 104265 (41:4265)
+; pad a 20x18 map to 32x18 for HDMA transfer
+; back up the padding value in c to hMapObjectIndexBuffer
+	ld a, [hMapObjectIndexBuffer]
+	push af
+	ld a, c
+	ld [hMapObjectIndexBuffer], a
+
+; for each row on the screen
+	ld c, SCREEN_HEIGHT
+.loop1
+; for each tile in the row
+	ld b, SCREEN_WIDTH
+.loop2
+; copy from de to hl
+	ld a, [de]
+	inc de
+	ld [hli], a
+	dec b
+	jr nz, .loop2
+
+; load the original padding value of c into hl for 32 - 20 = 12 rows
+	ld a, [hMapObjectIndexBuffer]
+	ld b, BG_MAP_WIDTH - SCREEN_WIDTH
+.loop3
+	ld [hli], a
+	dec b
+	jr nz, .loop3
+
+	dec c
+	jr nz, .loop1
+
+; restore the original value of hMapObjectIndexBuffer
+	pop af
+	ld [hMapObjectIndexBuffer], a
+	ret
+
+
+_Get2bpp:: ; 104284
+	; 2bpp when [rLCDC] & $80
+	; switch to WRAM bank 6
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wScratchTileMap)
+	ld [rSVBK], a
+
+	push bc
+	push hl
+
+	; Copy c tiles of the 2bpp from b:de to wScratchTileMap
+	ld a, b ; bank
+	ld l, c ; number of tiles
+	ld h, $0
+	; multiply by 16 (16 bytes of a 2bpp = 8 x 8 tile)
+	add hl, hl
+	add hl, hl
+	add hl, hl
+	add hl, hl
+	ld b, h
+	ld c, l
+	ld h, d ; address
+	ld l, e
+	ld de, wScratchTileMap
+	call FarCopyBytes
+
+	pop hl
+	pop bc
+
+	push bc
+	call DelayFrame
+	pop bc
+
+	ld d, h
+	ld e, l
+	ld hl, wScratchTileMap
+	call HDMATransfer_Wait127Scanlines
+
+	; restore the previous bank
+	pop af
+	ld [rSVBK], a
+	ret
+; 1042b2
+
+_Get1bpp:: ; 1042b2
+	; 1bpp when [rLCDC] & $80
+.loop
+	ld a, c
+	cp $10
+	jp c, .bankswitch
+	jp z, .bankswitch
+	push bc
+	push hl
+	push de
+	ld c, $10
+	call .bankswitch
+	pop de
+	ld hl, $80
+	add hl, de
+	ld d, h
+	ld e, l
+	pop hl
+	lb bc, 1, 0
+	add hl, bc
+	pop bc
+	ld a, c
+	sub $10
+	ld c, a
+	jr .loop
+; 1042d6
+
+.bankswitch ; 1042d6
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wScratchTileMap)
+	ld [rSVBK], a
+
+	push bc
+	push hl
+
+	ld a, b
+	ld l, c
+	ld h, $0
+	add hl, hl ; multiply by 8
+	add hl, hl ; multiply by 8
+	add hl, hl ; multiply by 8
+	ld c, l
+	ld b, h
+	ld h, d
+	ld l, e
+	ld de, wScratchTileMap
+	call FarCopyBytesDouble_DoubleBankSwitch
+
+	pop hl
+	pop bc
+
+	push bc
+	call DelayFrame
+	pop bc
+
+	ld d, h
+	ld e, l
+	ld hl, wScratchTileMap
+	call HDMATransfer_Wait127Scanlines
+
+	pop af
+	ld [rSVBK], a
+	ret
+; 104303
+
+HDMATransfer_OnlyTopFourRows: ; 104303
+	ld hl, .Function
+	jp CallInSafeGFXMode
+; 104309
+
+.Function:
+	ld hl, wScratchTileMap
+	decoord 0, 0
+	call .Copy
+	ld hl, wScratchTileMap + $80
+	decoord 0, 0, wAttrMap
+	call .Copy
+	ld a, $1
+	ld [rVBK], a
+	ld c, $8
+	ld hl, wScratchTileMap + $80
+	debgcoord 0, 0, vBGMap1
+	call HDMATransfer_Wait127Scanlines
+	ld a, $0
+	ld [rVBK], a
+	ld c, $8
+	ld hl, wScratchTileMap
+	debgcoord 0, 0, vBGMap1
+	call HDMATransfer_Wait127Scanlines
+	ret
+
+.Copy: ; 10433a (41:433a)
+	ld b, 4
+.outer_loop
+	ld c, SCREEN_WIDTH
+.inner_loop
+	ld a, [de]
+	ld [hli], a
+	inc de
+	dec c
+	jr nz, .inner_loop
+	ld a, l
+	add BG_MAP_WIDTH - SCREEN_WIDTH
+	ld l, a
+	ld a, h
+	adc 0
+	ld h, a
+	dec b
+	jr nz, .outer_loop
+	ret
+; 104350
--- a/engine/gfx/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/gfx/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/loadpushoam.asm
@@ -1,0 +1,21 @@
+WriteOAMDMACodeToHRAM:: ; 4031
+	ld c, hTransferVirtualOAM - $ff00
+	ld b, .PushOAMEnd - .PushOAM
+	ld hl, .PushOAM
+.loop
+	ld a, [hli]
+	ld [$ff00+c], a
+	inc c
+	dec b
+	jr nz, .loop
+	ret
+
+.PushOAM: ; 403f
+	ld a, HIGH(wVirtualOAM)
+	ld [rDMA], a
+	ld a, NUM_SPRITE_OAM_STRUCTS
+.pushoam_loop
+	dec a
+	jr nz, .pushoam_loop
+	ret
+.PushOAMEnd
--- a/engine/gfx/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/gfx/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/gfx/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/gfx/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/gfx/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/gfx/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/items/tmhm.asm
+++ b/engine/items/tmhm.asm
@@ -1,49 +1,589 @@
-CanLearnTMHMMove: ; 11639
+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]
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld hl, wBaseTMHM
+	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
 
-	ld a, [wPutativeTMHMMove]
+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 c, 0
-	ld hl, TMHMMoves
+	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, .end
-	cp b
-	jr z, .asm_11659
+	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
-	jr .loop
+	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
 
-.asm_11659
+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 b, CHECK_FLAG
+	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 d, 0
-	predef SmallFarFlagAction
+	ld de, TMHM_String_Cancel
+	call PlaceString
 	pop de
+.done
 	ret
 
-.end
+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
-; 1166a
 
-GetTMHMMove: ; 1166a
+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, TMHMMoves
+	ld hl, wTMsHMs
 	ld b, 0
 	ld c, a
 	add hl, bc
 	ld a, [hl]
-	ld [wd265], a
+	inc a
+	cp NUM_TMS * 2
+	ret nc
+	ld [hl], a
 	ret
-; 1167a
+; 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
 
-INCLUDE "data/moves/tmhm_moves.asm"
+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/items/tmhm2.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"
--- a/engine/link/link.asm
+++ b/engine/link/link.asm
@@ -2029,7 +2029,7 @@
 	ret
 ; 28f24
 
-INCLUDE "engine/gfx/trade_animation.asm"
+INCLUDE "engine/movie/trade_animation.asm"
 
 CheckTimeCapsuleCompatibility: ; 29bfb
 ; Checks to see if your party is compatible with the Gen 1 games.
--- /dev/null
+++ b/engine/link/placewaitingtext.asm
@@ -1,0 +1,24 @@
+PlaceWaitingText:: ; 4000
+	hlcoord 3, 10
+	ld b, 1
+	ld c, 11
+
+	ld a, [wBattleMode]
+	and a
+	jr z, .notinbattle
+
+	call TextBox
+	jr .proceed
+
+.notinbattle
+	predef LinkTextboxAtHL
+
+.proceed
+	hlcoord 4, 11
+	ld de, .Waiting
+	call PlaceString
+	ld c, 50
+	jp DelayFrames
+
+.Waiting: ; 4025
+	db "Waiting...!@"
--- /dev/null
+++ b/engine/menus/debug.asm
@@ -1,0 +1,1447 @@
+	const_def $6a
+	const DEBUGTEST_UP_ARROW ; $6a
+	const DEBUGTEST_TICKS    ; $6b
+	const DEBUGTEST_WHITE    ; $6c
+	const DEBUGTEST_LIGHT    ; $6d
+	const DEBUGTEST_DARK     ; $6e
+	const DEBUGTEST_BLACK    ; $6f
+	const DEBUGTEST_0        ; $70
+	const DEBUGTEST_1        ; $71
+	const DEBUGTEST_2        ; $72
+	const DEBUGTEST_3        ; $73
+	const DEBUGTEST_4        ; $74
+	const DEBUGTEST_5        ; $75
+	const DEBUGTEST_6        ; $76
+	const DEBUGTEST_7        ; $77
+	const DEBUGTEST_8        ; $78
+	const DEBUGTEST_9        ; $79
+	const DEBUGTEST_A        ; $7a
+	const DEBUGTEST_B        ; $7b
+	const DEBUGTEST_C        ; $7c
+	const DEBUGTEST_D        ; $7d
+	const DEBUGTEST_E        ; $7e
+	const DEBUGTEST_F        ; $7f
+
+ColorTest: ; 818ac
+; A debug menu to test monster and trainer palettes at runtime.
+
+	ld a, [hCGB]
+	and a
+	jr nz, .asm_818b5
+	ld a, [hSGB]
+	and a
+	ret z
+
+.asm_818b5
+	ld a, [hInMenu]
+	push af
+	ld a, $1
+	ld [hInMenu], a
+	call DisableLCD
+	call Function81948
+	call Function8197c
+	call Function819a7
+	call Function818f4
+	call EnableLCD
+	ld de, MUSIC_NONE
+	call PlayMusic
+	xor a
+	ld [wJumptableIndex], a
+	ld [wcf66], a
+	ld [wd003], a
+.asm_818de
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .asm_818f0
+	call Function81a74
+	call Function81f5e
+	call DelayFrame
+	jr .asm_818de
+
+.asm_818f0
+	pop af
+	ld [hInMenu], a
+	ret
+; 818f4
+
+Function818f4: ; 818f4
+	ld a, [wd002]
+	and a
+	jr nz, Function81911
+	ld hl, PokemonPalettes
+
+Function818fd: ; 818fd
+	ld de, wOverworldMap
+	ld c, NUM_POKEMON + 1
+.asm_81902
+	push bc
+	push hl
+	call Function81928
+	pop hl
+	ld bc, 8
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .asm_81902
+	ret
+
+Function81911: ; 81911
+	ld hl, TrainerPalettes
+	ld de, wOverworldMap
+	ld c, NUM_TRAINER_CLASSES
+.asm_81919
+	push bc
+	push hl
+	call Function81928
+	pop hl
+	ld bc, 4
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .asm_81919
+	ret
+; 81928
+
+Function81928: ; 81928
+	ld a, BANK(PokemonPalettes) ; BANK(TrainerPalettes)
+	call GetFarByte
+	ld [de], a
+	inc de
+	inc hl
+	ld a, BANK(PokemonPalettes) ; BANK(TrainerPalettes)
+	call GetFarByte
+	ld [de], a
+	inc de
+	inc hl
+	ld a, BANK(PokemonPalettes) ; BANK(TrainerPalettes)
+	call GetFarByte
+	ld [de], a
+	inc de
+	inc hl
+	ld a, BANK(PokemonPalettes) ; BANK(TrainerPalettes)
+	call GetFarByte
+	ld [de], a
+	inc de
+	ret
+; 81948
+
+Function81948: ; 81948
+	ld a, $1
+	ld [rVBK], a
+	ld hl, vTiles0
+	ld bc, sScratch - vTiles0
+	xor a
+	call ByteFill
+	ld a, $0
+	ld [rVBK], a
+	ld hl, vTiles0
+	ld bc, sScratch - vTiles0
+	xor a
+	call ByteFill
+	hlcoord 0, 0, wAttrMap
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	xor a
+	call ByteFill
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	xor a
+	call ByteFill
+	call ClearSprites
+	ret
+; 8197c
+
+Function8197c: ; 8197c
+	ld hl, DebugColorTestGFX + 1 tiles
+	ld de, vTiles2 tile DEBUGTEST_UP_ARROW
+	ld bc, 22 tiles
+	call CopyBytes
+	ld hl, DebugColorTestGFX
+	ld de, vTiles0
+	ld bc, 1 tiles
+	call CopyBytes
+	call LoadStandardFont
+	ld hl, vTiles1
+	lb bc, 8, 0
+.asm_8199d
+	ld a, [hl]
+	xor $ff
+	ld [hli], a
+	dec bc
+	ld a, c
+	or b
+	jr nz, .asm_8199d
+	ret
+; 819a7
+
+Function819a7: ; 819a7
+	ld a, [hCGB]
+	and a
+	ret z
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ld [rSVBK], a
+	ld hl, Palette_DebugBG
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+	ld a, 1 << rBGPI_AUTO_INCREMENT
+	ld [rBGPI], a
+	ld hl, Palette_DebugBG
+	ld c, 8 palettes
+	xor a
+.asm_819c8
+	ld [rBGPD], a
+	dec c
+	jr nz, .asm_819c8
+	ld a, 1 << rOBPI_AUTO_INCREMENT
+	ld [rOBPI], a
+	ld hl, Palette_DebugOB
+	ld c, 8 palettes
+.asm_819d6
+	ld a, [hli]
+	ld [rOBPD], a
+	dec c
+	jr nz, .asm_819d6
+	ld a, $94
+	ld [wc608], a
+	ld a, $52
+	ld [wc608 + 1], a
+	ld a, $4a
+	ld [wc608 + 2], a
+	ld a, $29
+	ld [wc608 + 3], a
+	pop af
+	ld [rSVBK], a
+	ret
+; 819f4
+
+Palette_DebugBG: ; 819f4
+INCLUDE "gfx/debug/bg.pal"
+
+Palette_DebugOB: ; 81a34
+INCLUDE "gfx/debug/ob.pal"
+; 81a74
+
+Function81a74: ; 81a74
+	call JoyTextDelay
+	ld a, [wJumptableIndex]
+	cp $4
+	jr nc, .asm_81a8b
+	ld hl, hJoyLast
+	ld a, [hl]
+	and SELECT
+	jr nz, .asm_81a9a
+	ld a, [hl]
+	and START
+	jr nz, .asm_81aab
+
+.asm_81a8b
+	ld a, [wJumptableIndex]
+	ld e, a
+	ld d, 0
+	ld hl, Jumptable_81acf
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+.asm_81a9a
+	call Function81eca
+	call Function81ac3
+	ld e, a
+	ld a, [wcf66]
+	inc a
+	cp e
+	jr c, .asm_81aba
+	xor a
+	jr .asm_81aba
+
+.asm_81aab
+	call Function81eca
+	ld a, [wcf66]
+	dec a
+	cp $ff
+	jr nz, .asm_81aba
+	call Function81ac3
+	dec a
+
+.asm_81aba
+	ld [wcf66], a
+	ld a, $0
+	ld [wJumptableIndex], a
+	ret
+; 81ac3
+
+Function81ac3: ; 81ac3
+; Looping back around the pic set.
+	ld a, [wd002]
+	and a
+	jr nz, .asm_81acc
+	ld a, NUM_POKEMON ; CELEBI
+	ret
+
+.asm_81acc
+	ld a, NUM_TRAINER_CLASSES - 1 ; MYSTICALMAN
+	ret
+; 81acf
+
+Jumptable_81acf: ; 81acf
+	dw Function81adb
+	dw Function81c18
+	dw Function81c33
+	dw Function81cc2
+	dw Function81d8e
+	dw Function81daf
+; 81adb
+
+Function81adb: ; 81adb
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, DEBUGTEST_BLACK
+	call ByteFill
+	hlcoord 1, 3
+	lb bc, 7, 18
+	ld a, DEBUGTEST_WHITE
+	call Bank20_FillBoxWithByte
+	hlcoord 11, 0
+	lb bc, 2, 3
+	ld a, DEBUGTEST_LIGHT
+	call Bank20_FillBoxWithByte
+	hlcoord 16, 0
+	lb bc, 2, 3
+	ld a, DEBUGTEST_DARK
+	call Bank20_FillBoxWithByte
+	call Function81bc0
+	call Function81bf4
+	ld a, [wcf66]
+	inc a
+	ld [wCurPartySpecies], a
+	ld [wd265], a
+	hlcoord 0, 1
+	ld de, wd265
+	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
+	call PrintNum
+	ld a, [wd002]
+	and a
+	jr nz, .asm_81b7a
+	ld a, $1
+	ld [wUnownLetter], a
+	call GetPokemonName
+	hlcoord 4, 1
+	call PlaceString
+	xor a
+	ld [wBoxAlignment], a
+	hlcoord 12, 3
+	call _PrepMonFrontpic
+	ld de, vTiles2 tile $31
+	predef GetMonBackpic
+	ld a, $31
+	ld [hGraphicStartTile], a
+	hlcoord 2, 4
+	lb bc, 6, 6
+	predef PlaceGraphic
+	ld a, [wd003]
+	and a
+	jr z, .asm_81b66
+	ld de, String_81baf
+	jr .asm_81b69
+
+.asm_81b66
+	ld de, String_81bb4
+
+.asm_81b69
+	hlcoord 7, 17
+	call PlaceString
+	hlcoord 0, 17
+	ld de, String_81bb9
+	call PlaceString
+	jr .asm_81ba9
+
+.asm_81b7a
+	ld a, [wd265]
+	ld [wTrainerClass], a
+	callfar GetTrainerAttributes
+	ld de, wStringBuffer1
+	hlcoord 4, 1
+	call PlaceString
+	ld de, vTiles2
+	callfar GetTrainerPic
+	xor a
+	ld [wTempEnemyMonSpecies], a
+	ld [hGraphicStartTile], a
+	hlcoord 2, 3
+	lb bc, 7, 7
+	predef PlaceGraphic
+
+.asm_81ba9
+	ld a, $1
+	ld [wJumptableIndex], a
+	ret
+; 81baf
+
+String_81baf: db "レア", DEBUGTEST_BLACK, DEBUGTEST_BLACK, "@" ; rare (shiny)
+String_81bb4: db "ノーマル@" ; normal
+String_81bb9: db DEBUGTEST_A, "きりかえ▶@" ; (A) switches
+; 81bc0
+
+Function81bc0: ; 81bc0
+	decoord 0, 11, wAttrMap
+	hlcoord 2, 11
+	ld a, $1
+	call Function81bde
+	decoord 0, 13, wAttrMap
+	hlcoord 2, 13
+	ld a, $2
+	call Function81bde
+	decoord 0, 15, wAttrMap
+	hlcoord 2, 15
+	ld a, $3
+
+Function81bde: ; 81bde
+	push af
+	ld a, DEBUGTEST_UP_ARROW
+	ld [hli], a
+	ld bc, $f
+	ld a, DEBUGTEST_TICKS
+	call ByteFill
+	ld l, e
+	ld h, d
+	pop af
+	ld bc, $28
+	call ByteFill
+	ret
+; 81bf4
+
+Function81bf4: ; 81bf4
+	ld a, [wcf66]
+	inc a
+	ld l, a
+	ld h, $0
+	add hl, hl
+	add hl, hl
+	ld de, wOverworldMap
+	add hl, de
+	ld de, wc608
+	ld bc, 4
+	call CopyBytes
+	xor a
+	ld [wcf64], a
+	ld [wcf65], a
+	ld de, wc608
+	call Function81ea5
+	ret
+; 81c18
+
+Function81c18: ; 81c18
+	ld a, [hCGB]
+	and a
+	jr z, .asm_81c2a
+	ld a, $2
+	ld [hBGMapMode], a
+	call DelayFrame
+	call DelayFrame
+	call DelayFrame
+
+.asm_81c2a
+	call WaitBGMap
+	ld a, $2
+	ld [wJumptableIndex], a
+	ret
+; 81c33
+
+Function81c33: ; 81c33
+	ld a, [hCGB]
+	and a
+	jr z, .asm_81c69
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ld [rSVBK], a
+	ld hl, wBGPals2
+	ld de, wc608
+	ld c, $1
+	call Function81ee3
+	hlcoord 10, 2
+	ld de, wc608
+	call Function81ca7
+	hlcoord 15, 2
+	ld de, wc608 + 2
+	call Function81ca7
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	ld a, $3
+	ld [wJumptableIndex], a
+	pop af
+	ld [rSVBK], a
+	ret
+
+.asm_81c69
+	ld hl, wSGBPals
+	ld a, 1
+	ld [hli], a
+	ld a, LOW(PALRGB_WHITE)
+	ld [hli], a
+	ld a, HIGH(PALRGB_WHITE)
+	ld [hli], a
+	ld a, [wc608]
+	ld [hli], a
+	ld a, [wc608 + 1]
+	ld [hli], a
+	ld a, [wc608 + 2]
+	ld [hli], a
+	ld a, [wc608 + 3]
+	ld [hli], a
+	xor a
+	ld [hli], a
+	ld [hli], a
+	ld [hl], a
+	ld hl, wSGBPals
+	call Function81f0c
+	hlcoord 10, 2
+	ld de, wc608
+	call Function81ca7
+	hlcoord 15, 2
+	ld de, wc608 + 2
+	call Function81ca7
+	ld a, $3
+	ld [wJumptableIndex], a
+	ret
+; 81ca7
+
+Function81ca7: ; 81ca7
+	inc hl
+	inc hl
+	inc hl
+	ld a, [de]
+	call Function81cbc
+	ld a, [de]
+	swap a
+	call Function81cbc
+	inc de
+	ld a, [de]
+	call Function81cbc
+	ld a, [de]
+	swap a
+
+Function81cbc: ; 81cbc
+	and $f
+	add DEBUGTEST_0
+	ld [hld], a
+	ret
+; 81cc2
+
+Function81cc2: ; 81cc2
+	ld a, [hJoyLast]
+	and B_BUTTON
+	jr nz, .asm_81cdf
+	ld a, [hJoyLast]
+	and A_BUTTON
+	jr nz, .asm_81ce5
+	ld a, [wcf64]
+	and $3
+	ld e, a
+	ld d, 0
+	ld hl, Jumptable_81d02
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+.asm_81cdf
+	ld a, $4
+	ld [wJumptableIndex], a
+	ret
+
+.asm_81ce5
+	ld a, [wd002]
+	and a
+	ret nz
+	ld a, [wd003]
+	xor $4
+	ld [wd003], a
+	ld c, a
+	ld b, 0
+	ld hl, PokemonPalettes
+	add hl, bc
+	call Function818fd
+	ld a, $0
+	ld [wJumptableIndex], a
+	ret
+; 81d02
+
+Jumptable_81d02: ; 81d02
+	dw Function81d0a
+	dw Function81d34
+	dw Function81d46
+	dw Function81d58
+; 81d0a
+
+Function81d0a: ; 81d0a
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, Function81d89
+	ld a, [hl]
+	and D_LEFT
+	jr nz, .asm_81d1d
+	ld a, [hl]
+	and D_RIGHT
+	jr nz, .asm_81d28
+	ret
+
+.asm_81d1d
+	xor a
+	ld [wcf65], a
+	ld de, wc608
+	call Function81ea5
+	ret
+
+.asm_81d28
+	ld a, $1
+	ld [wcf65], a
+	ld de, wc608 + 2
+	call Function81ea5
+	ret
+
+Function81d34: ; 81d34
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, Function81d89
+	ld a, [hl]
+	and D_UP
+	jr nz, Function81d84
+	ld hl, wc608 + 10
+	jr Function81d63
+
+Function81d46: ; 81d46
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, Function81d89
+	ld a, [hl]
+	and D_UP
+	jr nz, Function81d84
+	ld hl, wc608 + 11
+	jr Function81d63
+
+Function81d58: ; 81d58
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_UP
+	jr nz, Function81d84
+	ld hl, wc608 + 12
+
+Function81d63: ; 81d63
+	ld a, [hJoyLast]
+	and D_RIGHT
+	jr nz, Function81d70
+	ld a, [hJoyLast]
+	and D_LEFT
+	jr nz, Function81d77
+	ret
+
+Function81d70: ; 81d70
+	ld a, [hl]
+	cp $1f
+	ret nc
+	inc [hl]
+	jr Function81d7b
+
+Function81d77: ; 81d77
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+
+Function81d7b: ; 81d7b
+	call Function81e67
+	ld a, $2
+	ld [wJumptableIndex], a
+	ret
+
+Function81d84: ; 81d84
+	ld hl, wcf64
+	dec [hl]
+	ret
+
+Function81d89: ; 81d89
+	ld hl, wcf64
+	inc [hl]
+	ret
+; 81d8e
+
+Function81d8e: ; 81d8e
+	hlcoord 0, 10
+	ld bc, $a0
+	ld a, DEBUGTEST_BLACK
+	call ByteFill
+	hlcoord 2, 12
+	ld de, String_81fcd
+	call PlaceString
+	xor a
+	ld [wd004], a
+	call Function81df4
+	ld a, $5
+	ld [wJumptableIndex], a
+	ret
+; 81daf
+
+Function81daf: ; 81daf
+	ld hl, hJoyPressed
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .asm_81dbb
+	call Function81dc7
+	ret
+
+.asm_81dbb
+	ld a, $0
+	ld [wJumptableIndex], a
+	ret
+; 81dc1
+
+Function81dc1: ; 81dc1
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+; 81dc7
+
+Function81dc7: ; 81dc7
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_UP
+	jr nz, .asm_81dd5
+	ld a, [hl]
+	and D_DOWN
+	jr nz, .asm_81de2
+	ret
+
+.asm_81dd5
+	ld a, [wd004]
+	cp $3b
+	jr z, .asm_81ddf
+	inc a
+	jr .asm_81ded
+
+.asm_81ddf
+	xor a
+	jr .asm_81ded
+
+.asm_81de2
+	ld a, [wd004]
+	and a
+	jr z, .asm_81deb
+	dec a
+	jr .asm_81ded
+
+.asm_81deb
+	ld a, $3b
+
+.asm_81ded
+	ld [wd004], a
+	call Function81df4
+	ret
+; 81df4
+
+Function81df4: ; 81df4
+	hlcoord 10, 11
+	call Function81e5e
+	hlcoord 10, 12
+	call Function81e5e
+	hlcoord 10, 13
+	call Function81e5e
+	hlcoord 10, 14
+	call Function81e5e
+	ld a, [wd004]
+	inc a
+	ld [wd265], a
+	predef GetTMHMMove
+	ld a, [wd265]
+	ld [wPutativeTMHMMove], a
+	call GetMoveName
+	hlcoord 10, 12
+	call PlaceString
+	ld a, [wd004]
+	call Function81e55
+	ld [wCurItem], a
+	predef CanLearnTMHMMove
+	ld a, c
+	and a
+	ld de, String_81e46
+	jr nz, .asm_81e3f
+	ld de, String_81e4d
+
+.asm_81e3f
+	hlcoord 10, 14
+	call PlaceString
+	ret
+; 81e46
+
+String_81e46: db "おぼえられる@" ; can be taught
+String_81e4d: db "おぼえられない@" ; cannot be taught
+; 81e55
+
+Function81e55: ; 81e55
+	cp $32
+	jr c, .asm_81e5b
+	inc a
+	inc a
+
+.asm_81e5b
+	add $bf
+	ret
+; 81e5e
+
+Function81e5e: ; 81e5e
+	ld bc, 10
+	ld a, DEBUGTEST_BLACK
+	call ByteFill
+	ret
+; 81e67
+
+Function81e67: ; 81e67
+	ld a, [wc608 + 10]
+	and $1f
+	ld e, a
+	ld a, [wc608 + 11]
+	and $7
+	sla a
+	swap a
+	or e
+	ld e, a
+	ld a, [wc608 + 11]
+	and $18
+	sla a
+	swap a
+	ld d, a
+	ld a, [wc608 + 12]
+	and $1f
+	sla a
+	sla a
+	or d
+	ld d, a
+	ld a, [wcf65]
+	and a
+	jr z, .asm_81e9c
+	ld a, e
+	ld [wc608 + 2], a
+	ld a, d
+	ld [wc608 + 3], a
+	ret
+
+.asm_81e9c
+	ld a, e
+	ld [wc608], a
+	ld a, d
+	ld [wc608 + 1], a
+	ret
+; 81ea5
+
+Function81ea5: ; 81ea5
+	ld a, [de]
+	and $1f
+	ld [wc608 + 10], a
+	ld a, [de]
+	and $e0
+	swap a
+	srl a
+	ld b, a
+	inc de
+	ld a, [de]
+	and $3
+	swap a
+	srl a
+	or b
+	ld [wc608 + 11], a
+	ld a, [de]
+	and $7c
+	srl a
+	srl a
+	ld [wc608 + 12], a
+	ret
+; 81eca
+
+Function81eca: ; 81eca
+	ld a, [wcf66]
+	inc a
+	ld l, a
+	ld h, $0
+	add hl, hl
+	add hl, hl
+	ld de, wOverworldMap
+	add hl, de
+	ld e, l
+	ld d, h
+	ld hl, wc608
+	ld bc, 4
+	call CopyBytes
+	ret
+; 81ee3
+
+Function81ee3: ; 81ee3
+.asm_81ee3
+	ld a, LOW(PALRGB_WHITE)
+	ld [hli], a
+	ld a, HIGH(PALRGB_WHITE)
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hli], a
+	xor a
+	ld [hli], a
+	ld [hli], a
+	dec c
+	jr nz, .asm_81ee3
+	ret
+; 81efc
+
+Bank20_FillBoxWithByte: ; 81efc
+; For some reason, we have another copy of FillBoxWithByte here
+.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
+; 81f0c
+
+Function81f0c: ; 81f0c
+	ld a, [wcfbe]
+	push af
+	set 7, a
+	ld [wcfbe], a
+	call Function81f1d
+	pop af
+	ld [wcfbe], a
+	ret
+; 81f1d
+
+Function81f1d: ; 81f1d
+	ld a, [hl]
+	and $7
+	ret z
+	ld b, a
+.asm_81f22
+	push bc
+	xor a
+	ld [rJOYP], a
+	ld a, $30
+	ld [rJOYP], a
+	ld b, $10
+.asm_81f2c
+	ld e, $8
+	ld a, [hli]
+	ld d, a
+.asm_81f30
+	bit 0, d
+	ld a, $10
+	jr nz, .asm_81f38
+	ld a, $20
+
+.asm_81f38
+	ld [rJOYP], a
+	ld a, $30
+	ld [rJOYP], a
+	rr d
+	dec e
+	jr nz, .asm_81f30
+	dec b
+	jr nz, .asm_81f2c
+	ld a, $20
+	ld [rJOYP], a
+	ld a, $30
+	ld [rJOYP], a
+	ld de, 7000
+.asm_81f51
+	nop
+	nop
+	nop
+	dec de
+	ld a, d
+	or e
+	jr nz, .asm_81f51
+	pop bc
+	dec b
+	jr nz, .asm_81f22
+	ret
+; 81f5e
+
+Function81f5e: ; 81f5e
+	ld a, DEBUGTEST_BLACK
+	hlcoord 10, 0
+	ld [hl], a
+	hlcoord 15, 0
+	ld [hl], a
+	hlcoord 1, 11
+	ld [hl], a
+	hlcoord 1, 13
+	ld [hl], a
+	hlcoord 1, 15
+	ld [hl], a
+	ld a, [wJumptableIndex]
+	cp $3
+	jr nz, .asm_81fc9
+	ld a, [wcf64]
+	and a
+	jr z, .asm_81f8d
+	dec a
+	hlcoord 1, 11
+	ld bc, 2 * SCREEN_WIDTH
+	call AddNTimes
+	ld [hl], $ed
+
+.asm_81f8d
+	ld a, [wcf65]
+	and a
+	jr z, .asm_81f98
+	hlcoord 15, 0
+	jr .asm_81f9b
+
+.asm_81f98
+	hlcoord 10, 0
+
+.asm_81f9b
+	ld [hl], $ed
+	ld b, $70
+	ld c, $5
+	ld hl, wVirtualOAM
+	ld de, wc608 + 10
+	call .asm_81fb7
+	ld de, wc608 + 11
+	call .asm_81fb7
+	ld de, wc608 + 12
+	call .asm_81fb7
+	ret
+
+.asm_81fb7
+	ld a, b
+	ld [hli], a ; y
+	ld a, [de]
+	add a
+	add a
+	add 3 * TILE_WIDTH
+	ld [hli], a ; x
+	xor a
+	ld [hli], a ; tile id
+	ld a, c
+	ld [hli], a ; attributes
+	ld a, 2 * TILE_WIDTH
+	add b
+	ld b, a
+	inc c
+	ret
+
+.asm_81fc9
+	call ClearSprites
+	ret
+; 81fcd
+
+String_81fcd: ; 81fcd
+	db   "おわりますか?" ; Are you finished?
+	next "はい<DOT><DOT><DOT>", DEBUGTEST_A ; YES...(A)
+	next "いいえ<DOT><DOT>", DEBUGTEST_B ; NO..(B)
+	db   "@"
+; 81fe3
+
+DebugColorTestGFX:
+INCBIN "gfx/debug/color_test.2bpp"
+
+
+TilesetColorTest:
+	ret
+	xor a
+	ld [wJumptableIndex], a
+	ld [wcf64], a
+	ld [wcf65], a
+	ld [wcf66], a
+	ld [hMapAnims], a
+	call ClearSprites
+	call OverworldTextModeSwitch
+	call WaitBGMap2
+	xor a
+	ld [hBGMapMode], a
+	ld de, DebugColorTestGFX + 1 tiles
+	ld hl, vTiles2 tile DEBUGTEST_UP_ARROW
+	lb bc, BANK(DebugColorTestGFX), 22
+	call Request2bpp
+	ld de, DebugColorTestGFX
+	ld hl, vTiles1
+	lb bc, BANK(DebugColorTestGFX), 1
+	call Request2bpp
+	ld a, HIGH(vBGMap1)
+	ld [hBGMapAddress + 1], a
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, DEBUGTEST_BLACK
+	call ByteFill
+	hlcoord 0, 0, wAttrMap
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, $7
+	call ByteFill
+	ld de, $15
+	ld a, DEBUGTEST_WHITE
+	call Function821d2
+	ld de, $1a
+	ld a, DEBUGTEST_LIGHT
+	call Function821d2
+	ld de, $1f
+	ld a, DEBUGTEST_DARK
+	call Function821d2
+	ld de, $24
+	ld a, DEBUGTEST_BLACK
+	call Function821d2
+	call Function821f4
+	call Function8220f
+	call WaitBGMap2
+	ld [wJumptableIndex], a
+	ld a, $40
+	ld [hWY], a
+	ret
+; 821d2
+
+Function821d2: ; 821d2
+	hlcoord 0, 0
+	call Function821de
+
+Function821d8: ; 821d8
+	ld a, [wcf64]
+	hlcoord 0, 0, wAttrMap
+
+Function821de: ; 821de
+	add hl, de
+rept 4
+	ld [hli], a
+endr
+	ld bc, $10
+	add hl, bc
+rept 4
+	ld [hli], a
+endr
+	ld bc, $10
+	add hl, bc
+rept 4
+	ld [hli], a
+endr
+	ret
+; 821f4
+
+Function821f4: ; 821f4
+	hlcoord 2, 4
+	call Function82203
+	hlcoord 2, 6
+	call Function82203
+	hlcoord 2, 8
+
+Function82203: ; 82203
+	ld a, DEBUGTEST_UP_ARROW
+	ld [hli], a
+	ld bc, $10 - 1
+	ld a, DEBUGTEST_TICKS
+	call ByteFill
+	ret
+; 8220f
+
+Function8220f: ; 8220f
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ld [rSVBK], a
+	ld a, [wcf64]
+	ld l, a
+	ld h, $0
+	add hl, hl
+	add hl, hl
+	add hl, hl
+	ld de, wBGPals1
+	add hl, de
+	ld de, wc608
+	ld bc, 8
+	call CopyBytes
+	ld de, wc608
+	call Function81ea5
+	pop af
+	ld [rSVBK], a
+	ret
+; 82236
+
+
+Function82236: ; 82236
+	ld hl, hJoyLast
+	ld a, [hl]
+	and SELECT
+	jr nz, .loop7
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .asm_82299
+	call Function822f0
+	ret
+
+.loop7
+	ld hl, wcf64
+	ld a, [hl]
+	inc a
+	and $7
+	cp $7
+	jr nz, .asm_82253
+	xor a
+
+.asm_82253
+	ld [hl], a
+	ld de, $15
+	call Function821d8
+	ld de, $1a
+	call Function821d8
+	ld de, $1f
+	call Function821d8
+	ld de, $24
+	call Function821d8
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ld [rSVBK], a
+	ld hl, wBGPals2
+	ld a, [wcf64]
+	ld bc, 1 palettes
+	call AddNTimes
+	ld de, wc608
+	ld bc, 1 palettes
+	call CopyBytes
+	pop af
+	ld [rSVBK], a
+	ld a, $2
+	ld [hBGMapMode], a
+	ld c, 3
+	call DelayFrames
+	ld a, $1
+	ld [hBGMapMode], a
+	ret
+
+.asm_82299
+	call ClearSprites
+	ld a, [hWY]
+	xor $d0
+	ld [hWY], a
+	ret
+; 822a3
+
+Function822a3: ; 822a3
+	ld a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ld [rSVBK], a
+	ld hl, wBGPals2
+	ld a, [wcf64]
+	ld bc, 1 palettes
+	call AddNTimes
+	ld e, l
+	ld d, h
+	ld hl, wc608
+	ld bc, 1 palettes
+	call CopyBytes
+	hlcoord 1, 0
+	ld de, wc608
+	call Function81ca7
+	hlcoord 6, 0
+	ld de, wc608 + 2
+	call Function81ca7
+	hlcoord 11, 0
+	ld de, wc608 + 4
+	call Function81ca7
+	hlcoord 16, 0
+	ld de, wc608 + 6
+	call Function81ca7
+	pop af
+	ld [rSVBK], a
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	call DelayFrame
+	ret
+; 822f0
+
+Function822f0: ; 822f0
+	ld a, [wcf65]
+	and 3
+	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
+; 82301
+
+.dw ; 82301
+	dw Function82309
+	dw Function82339
+	dw Function8234b
+	dw Function8235d
+; 82309
+
+Function82309: ; 82309
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, Function8238c
+	ld a, [hl]
+	and D_LEFT
+	jr nz, .asm_8231c
+	ld a, [hl]
+	and D_RIGHT
+	jr nz, .asm_82322
+	ret
+
+.asm_8231c
+	ld a, [wcf66]
+	dec a
+	jr .asm_82326
+
+.asm_82322
+	ld a, [wcf66]
+	inc a
+
+.asm_82326
+	and $3
+	ld [wcf66], a
+	ld e, a
+	ld d, $0
+	ld hl, wc608
+	add hl, de
+	add hl, de
+	ld e, l
+	ld d, h
+	call Function81ea5
+	ret
+
+Function82339: ; 82338
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, Function8238c
+	ld a, [hl]
+	and D_UP
+	jr nz, Function82387
+	ld hl, wc608 + 10
+	jr Function82368
+
+Function8234b: ; 8234b
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, Function8238c
+	ld a, [hl]
+	and D_UP
+	jr nz, Function82387
+	ld hl, wc608 + 11
+	jr Function82368
+
+Function8235d: ; 8235d
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_UP
+	jr nz, Function82387
+	ld hl, wc608 + 12
+
+Function82368: ; 82368
+	ld a, [hJoyLast]
+	and D_RIGHT
+	jr nz, .asm_82375
+	ld a, [hJoyLast]
+	and D_LEFT
+	jr nz, .asm_8237c
+	ret
+
+.asm_82375
+	ld a, [hl]
+	cp $1f
+	ret nc
+	inc [hl]
+	jr .asm_82380
+
+.asm_8237c
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+
+.asm_82380
+	call Function82391
+	call Function822a3
+	ret
+
+Function82387: ; 82387
+	ld hl, wcf65
+	dec [hl]
+	ret
+
+Function8238c: ; 8238c
+	ld hl, wcf65
+	inc [hl]
+	ret
+; 82391
+
+Function82391: ; 82391
+	ld a, [wc608 + 10]
+	and $1f
+	ld e, a
+	ld a, [wc608 + 11]
+	and $7
+	sla a
+	swap a
+	or e
+	ld e, a
+	ld a, [wc608 + 11]
+	and $18
+	sla a
+	swap a
+	ld d, a
+	ld a, [wc608 + 12]
+	and $1f
+	sla a
+	sla a
+	or d
+	ld d, a
+	ld a, [wcf66]
+	ld c, a
+	ld b, $0
+	ld hl, wc608
+	add hl, bc
+	add hl, bc
+	ld a, e
+	ld [hli], a
+	ld [hl], d
+	ret
+; 823c6
+
+Function823c6: ; 823c6
+	ret
+
+Function823c7: ; 823c7
+	ret
+; 823c8
--- /dev/null
+++ b/engine/menus/save.asm
@@ -1,0 +1,1210 @@
+SaveMenu: ; 14a1a
+	call LoadStandardMenuHeader
+	farcall DisplaySaveInfoOnSave
+	call SpeechTextBox
+	call UpdateSprites
+	farcall SaveMenu_CopyTilemapAtOnce
+	ld hl, Text_WouldYouLikeToSaveTheGame
+	call SaveTheGame_yesorno
+	jr nz, .refused
+	call AskOverwriteSaveFile
+	jr c, .refused
+	call PauseGameLogic
+	call _SavingDontTurnOffThePower
+	call ResumeGameLogic
+	call ExitMenu
+	and a
+	ret
+
+.refused
+	call ExitMenu
+	call ret_d90
+	farcall SaveMenu_CopyTilemapAtOnce
+	scf
+	ret
+
+SaveAfterLinkTrade: ; 14a58
+	call PauseGameLogic
+	farcall StageRTCTimeForSave
+	farcall BackupMysteryGift
+	call SavePokemonData
+	call SaveChecksum
+	call SaveBackupPokemonData
+	call SaveBackupChecksum
+	farcall BackupPartyMonMail
+	farcall SaveRTC
+	call ResumeGameLogic
+	ret
+; 14a83
+
+
+ChangeBoxSaveGame: ; 14a83 (5:4a83)
+	push de
+	ld hl, Text_SaveOnBoxSwitch
+	call MenuTextBox
+	call YesNoBox
+	call ExitMenu
+	jr c, .refused
+	call AskOverwriteSaveFile
+	jr c, .refused
+	call PauseGameLogic
+	call SavingDontTurnOffThePower
+	call SaveBox
+	pop de
+	ld a, e
+	ld [wCurBox], a
+	call LoadBox
+	call SavedTheGame
+	call ResumeGameLogic
+	and a
+	ret
+.refused
+	pop de
+	ret
+
+Link_SaveGame: ; 14ab2
+	call AskOverwriteSaveFile
+	jr c, .refused
+	call PauseGameLogic
+	call _SavingDontTurnOffThePower
+	call ResumeGameLogic
+	and a
+
+.refused
+	ret
+; 14ac2
+
+MoveMonWOMail_SaveGame: ; 14ac2
+	call PauseGameLogic
+	push de
+	call SaveBox
+	pop de
+	ld a, e
+	ld [wCurBox], a
+	call LoadBox
+	call ResumeGameLogic
+	ret
+; 14ad5
+
+MoveMonWOMail_InsertMon_SaveGame: ; 14ad5
+	call PauseGameLogic
+	push de
+	call SaveBox
+	pop de
+	ld a, e
+	ld [wCurBox], a
+	ld a, $1
+	ld [wSaveFileExists], a
+	farcall StageRTCTimeForSave
+	farcall BackupMysteryGift
+	call ValidateSave
+	call SaveOptions
+	call SavePlayerData
+	call SavePokemonData
+	call SaveChecksum
+	call ValidateBackupSave
+	call SaveBackupOptions
+	call SaveBackupPlayerData
+	call SaveBackupPokemonData
+	call SaveBackupChecksum
+	farcall BackupPartyMonMail
+	farcall BackupMobileEventIndex
+	farcall SaveRTC
+	call LoadBox
+	call ResumeGameLogic
+	ld de, SFX_SAVE
+	call PlaySFX
+	ld c, 24
+	call DelayFrames
+	ret
+; 14b34
+
+StartMoveMonWOMail_SaveGame: ; 14b34
+	ld hl, Text_SaveOnMoveMonWOMail
+	call MenuTextBox
+	call YesNoBox
+	call ExitMenu
+	jr c, .refused
+	call AskOverwriteSaveFile
+	jr c, .refused
+	call PauseGameLogic
+	call _SavingDontTurnOffThePower
+	call ResumeGameLogic
+	and a
+	ret
+
+.refused
+	scf
+	ret
+; 14b54
+
+PauseGameLogic: ; 14b54
+	ld a, $1
+	ld [wGameLogicPaused], a
+	ret
+; 14b5a
+
+ResumeGameLogic: ; 14b5a
+	xor a
+	ld [wGameLogicPaused], a
+	ret
+; 14b5f
+
+
+AddHallOfFameEntry: ; 14b5f
+	ld a, BANK(sHallOfFame)
+	call GetSRAMBank
+	ld hl, sHallOfFame + HOF_LENGTH * (NUM_HOF_TEAMS - 1) - 1
+	ld de, sHallOfFame + HOF_LENGTH * NUM_HOF_TEAMS - 1
+	ld bc, HOF_LENGTH * (NUM_HOF_TEAMS - 1)
+.loop
+	ld a, [hld]
+	ld [de], a
+	dec de
+	dec bc
+	ld a, c
+	or b
+	jr nz, .loop
+	ld hl, wOverworldMap
+	ld de, sHallOfFame
+	ld bc, HOF_LENGTH
+	call CopyBytes
+	call CloseSRAM
+	ret
+; 14b85
+
+SaveGameData: ; 14b85
+	call SaveGameData_
+	ret
+; 14b89
+
+AskOverwriteSaveFile: ; 14b89
+	ld a, [wSaveFileExists]
+	and a
+	jr z, .erase
+	call CompareLoadedAndSavedPlayerID
+	jr z, .yoursavefile
+	ld hl, Text_AnotherSaveFile
+	call SaveTheGame_yesorno
+	jr nz, .refused
+	jr .erase
+
+.yoursavefile
+	ld hl, Text_AlreadyASaveFile
+	call SaveTheGame_yesorno
+	jr nz, .refused
+	jr .ok
+
+.erase
+	call ErasePreviousSave
+
+.ok
+	and a
+	ret
+
+.refused
+	scf
+	ret
+; 14baf
+
+SaveTheGame_yesorno: ; 14baf
+	ld b, BANK(Text_WouldYouLikeToSaveTheGame)
+	call MapTextbox
+	call LoadMenuTextBox
+	lb bc, 0, 7
+	call PlaceYesNoBox
+	ld a, [wMenuCursorY]
+	dec a
+	call CloseWindow
+	push af
+	call ret_d90
+	pop af
+	and a
+	ret
+; 14bcb
+
+CompareLoadedAndSavedPlayerID: ; 14bcb
+	ld a, BANK(sPlayerData)
+	call GetSRAMBank
+	ld hl, sPlayerData + (wPlayerID - wPlayerData)
+	ld a, [hli]
+	ld c, [hl]
+	ld b, a
+	call CloseSRAM
+	ld a, [wPlayerID]
+	cp b
+	ret nz
+	ld a, [wPlayerID + 1]
+	cp c
+	ret
+; 14be3
+
+_SavingDontTurnOffThePower: ; 14be3
+	call SavingDontTurnOffThePower
+SavedTheGame: ; 14be6
+	call SaveGameData_
+	; wait 32 frames
+	ld c, $20
+	call DelayFrames
+	; copy the original text speed setting to the stack
+	ld a, [wOptions]
+	push af
+	; set text speed super slow
+	ld a, 3
+	ld [wOptions], a
+	; <PLAYER> saved the game!
+	ld hl, Text_PlayerSavedTheGame
+	call PrintText
+	; restore the original text speed setting
+	pop af
+	ld [wOptions], a
+	ld de, SFX_SAVE
+	call WaitPlaySFX
+	call WaitSFX
+	; wait 30 frames
+	ld c, $1e
+	call DelayFrames
+	ret
+; 14c10
+
+
+SaveGameData_: ; 14c10
+	ld a, 1
+	ld [wSaveFileExists], a
+	farcall StageRTCTimeForSave
+	farcall BackupMysteryGift
+	call ValidateSave
+	call SaveOptions
+	call SavePlayerData
+	call SavePokemonData
+	call SaveBox
+	call SaveChecksum
+	call ValidateBackupSave
+	call SaveBackupOptions
+	call SaveBackupPlayerData
+	call SaveBackupPokemonData
+	call SaveBackupChecksum
+	call UpdateStackTop
+	farcall BackupPartyMonMail
+	farcall BackupMobileEventIndex
+	farcall SaveRTC
+	ld a, BANK(sBattleTowerChallengeState)
+	call GetSRAMBank
+	ld a, [sBattleTowerChallengeState]
+	cp BATTLETOWER_RECEIVED_REWARD
+	jr nz, .ok
+	xor a
+	ld [sBattleTowerChallengeState], a
+.ok
+	call CloseSRAM
+	ret
+; 14c6b
+
+UpdateStackTop: ; 14c6b
+; sStackTop appears to be unused.
+; It could have been used to debug stack overflow during saving.
+	call FindStackTop
+	ld a, BANK(sStackTop)
+	call GetSRAMBank
+	ld a, [sStackTop + 0]
+	ld e, a
+	ld a, [sStackTop + 1]
+	ld d, a
+	or e
+	jr z, .update
+	ld a, e
+	sub l
+	ld a, d
+	sbc h
+	jr c, .done
+
+.update
+	ld a, l
+	ld [sStackTop + 0], a
+	ld a, h
+	ld [sStackTop + 1], a
+
+.done
+	call CloseSRAM
+	ret
+; 14c90
+
+FindStackTop: ; 14c90
+; Find the furthest point that sp has traversed to.
+; This is distinct from the current value of sp.
+	ld hl, wStack - $ff
+.loop
+	ld a, [hl]
+	or a
+	ret nz
+	inc hl
+	jr .loop
+; 14c99
+
+SavingDontTurnOffThePower: ; 14c99
+	; Prevent joypad interrupts
+	xor a
+	ld [hJoypadReleased], a
+	ld [hJoypadPressed], a
+	ld [hJoypadSum], a
+	ld [hJoypadDown], a
+	; Save the text speed setting to the stack
+	ld a, [wOptions]
+	push af
+	; Set the text speed to super slow
+	ld a, $3
+	ld [wOptions], a
+	; SAVING... DON'T TURN OFF THE POWER.
+	ld hl, Text_SavingDontTurnOffThePower
+	call PrintText
+	; Restore the text speed setting
+	pop af
+	ld [wOptions], a
+	; Wait for 16 frames
+	ld c, $10
+	call DelayFrames
+	ret
+; 14cbb
+
+
+ErasePreviousSave: ; 14cbb
+	call EraseBoxes
+	call EraseHallOfFame
+	call EraseLinkBattleStats
+	call EraseMysteryGift
+	call SaveData
+	call EraseBattleTowerStatus
+	ld a, BANK(sStackTop)
+	call GetSRAMBank
+	xor a
+	ld [sStackTop + 0], a
+	ld [sStackTop + 1], a
+	call CloseSRAM
+	ld a, $1
+	ld [wSavedAtLeastOnce], a
+	ret
+; 14ce2
+
+EraseLinkBattleStats: ; 14ce2
+	ld a, BANK(sLinkBattleStats)
+	call GetSRAMBank
+	ld hl, sLinkBattleStats
+	ld bc, sLinkBattleStatsEnd - sLinkBattleStats
+	xor a
+	call ByteFill
+	jp CloseSRAM
+; 14cf4
+
+EraseMysteryGift: ; 14cf4
+	ld a, BANK(sBackupMysteryGiftItem)
+	call GetSRAMBank
+	ld hl, sBackupMysteryGiftItem
+	ld bc, sBackupMysteryGiftItemEnd - sBackupMysteryGiftItem
+	xor a
+	call ByteFill
+	jp CloseSRAM
+; 14d06
+
+EraseHallOfFame: ; 14d06
+	ld a, BANK(sHallOfFame)
+	call GetSRAMBank
+	ld hl, sHallOfFame
+	ld bc, sHallOfFameEnd - sHallOfFame
+	xor a
+	call ByteFill
+	jp CloseSRAM
+; 14d18
+
+Unreferenced_Function14d18: ; 14d18
+; copy .Data to SRA4:a007
+	ld a, 4 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
+	call GetSRAMBank
+	ld hl, .Data
+	ld de, $a007 ; address of MBC30 bank
+	ld bc, .DataEnd - .Data
+	call CopyBytes
+	jp CloseSRAM
+; 14d2c
+
+.Data: ; 14d2c
+	db $0d, $02, $00, $05, $00, $00
+	db $22, $02, $01, $05, $00, $00
+	db $03, $04, $05, $08, $03, $05
+	db $0e, $06, $03, $02, $00, $00
+	db $39, $07, $07, $04, $00, $05
+	db $04, $07, $01, $05, $00, $00
+	db $0f, $05, $14, $07, $05, $05
+	db $11, $0c, $0c, $06, $06, $04
+; 14d5c
+.DataEnd
+
+EraseBattleTowerStatus: ; 14d5c
+	ld a, BANK(sBattleTowerChallengeState)
+	call GetSRAMBank
+	xor a
+	ld [sBattleTowerChallengeState], a
+	jp CloseSRAM
+; 14d68
+
+SaveData: ; 14d68
+	call _SaveData
+	ret
+; 14d6c
+
+Unreferenced_Function14d6c: ; 14d6c
+	ld a, 4 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
+	call GetSRAMBank
+	ld a, [$a60b] ; address of MBC30 bank
+	ld b, $0
+	and a
+	jr z, .ok
+	ld b, $2
+
+.ok
+	ld a, b
+	ld [$a60b], a ; address of MBC30 bank
+	call CloseSRAM
+	ret
+; 14d83
+
+Unreferenced_Function14d83: ; 14d83
+	ld a, 4 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
+	call GetSRAMBank
+	xor a
+	ld [$a60c], a ; address of MBC30 bank
+	ld [$a60d], a ; address of MBC30 bank
+	call CloseSRAM
+	ret
+; 14d93
+
+Unreferenced_Function14d93: ; 14d93
+	ld a, 7 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
+	call GetSRAMBank
+	xor a
+	ld [$a000], a ; address of MBC30 bank
+	call CloseSRAM
+	ret
+; 14da0
+
+
+HallOfFame_InitSaveIfNeeded: ; 14da0
+	ld a, [wSavedAtLeastOnce]
+	and a
+	ret nz
+	call ErasePreviousSave
+	ret
+; 14da9
+
+ValidateSave: ; 14da9
+	ld a, BANK(sCheckValue1) ; BANK(sCheckValue2)
+	call GetSRAMBank
+	ld a, SAVE_CHECK_VALUE_1
+	ld [sCheckValue1], a
+	ld a, SAVE_CHECK_VALUE_2
+	ld [sCheckValue2], a
+	jp CloseSRAM
+; 14dbb
+
+SaveOptions: ; 14dbb
+	ld a, BANK(sOptions)
+	call GetSRAMBank
+	ld hl, wOptions
+	ld de, sOptions
+	ld bc, wOptionsEnd - wOptions
+	call CopyBytes
+	ld a, [wOptions]
+	and $ff ^ (1 << NO_TEXT_SCROLL)
+	ld [sOptions], a
+	jp CloseSRAM
+; 14dd7
+
+SavePlayerData: ; 14dd7
+	ld a, BANK(sPlayerData)
+	call GetSRAMBank
+	ld hl, wPlayerData
+	ld de, sPlayerData
+	ld bc, wPlayerDataEnd - wPlayerData
+	call CopyBytes
+	ld hl, wCurrMapData
+	ld de, sCurrMapData
+	ld bc, wCurrMapDataEnd - wCurrMapData
+	call CopyBytes
+	jp CloseSRAM
+; 14df7
+
+SavePokemonData: ; 14df7
+	ld a, BANK(sPokemonData)
+	call GetSRAMBank
+	ld hl, wPokemonData
+	ld de, sPokemonData
+	ld bc, wPokemonDataEnd - wPokemonData
+	call CopyBytes
+	call CloseSRAM
+	ret
+; 14e0c
+
+SaveBox: ; 14e0c
+	call GetBoxAddress
+	call SaveBoxAddress
+	ret
+; 14e13
+
+SaveChecksum: ; 14e13
+	ld hl, sGameData
+	ld bc, sGameDataEnd - sGameData
+	ld a, BANK(sGameData)
+	call GetSRAMBank
+	call Checksum
+	ld a, e
+	ld [sChecksum + 0], a
+	ld a, d
+	ld [sChecksum + 1], a
+	call CloseSRAM
+	ret
+; 14e2d
+
+ValidateBackupSave: ; 14e2d
+	ld a, BANK(sBackupCheckValue1) ; BANK(sBackupCheckValue2)
+	call GetSRAMBank
+	ld a, SAVE_CHECK_VALUE_1
+	ld [sBackupCheckValue1], a
+	ld a, SAVE_CHECK_VALUE_2
+	ld [sBackupCheckValue2], a
+	call CloseSRAM
+	ret
+; 14e40
+
+SaveBackupOptions: ; 14e40
+	ld a, BANK(sBackupOptions)
+	call GetSRAMBank
+	ld hl, wOptions
+	ld de, sBackupOptions
+	ld bc, wOptionsEnd - wOptions
+	call CopyBytes
+	call CloseSRAM
+	ret
+; 14e55
+
+SaveBackupPlayerData: ; 14e55
+	ld a, BANK(sBackupPlayerData)
+	call GetSRAMBank
+	ld hl, wPlayerData
+	ld de, sBackupPlayerData
+	ld bc, wPlayerDataEnd - wPlayerData
+	call CopyBytes
+	ld hl, wCurrMapData
+	ld de, sBackupCurrMapData
+	ld bc, wCurrMapDataEnd - wCurrMapData
+	call CopyBytes
+	call CloseSRAM
+	ret
+; 14e76
+
+SaveBackupPokemonData: ; 14e76
+	ld a, BANK(sBackupPokemonData)
+	call GetSRAMBank
+	ld hl, wPokemonData
+	ld de, sBackupPokemonData
+	ld bc, wPokemonDataEnd - wPokemonData
+	call CopyBytes
+	call CloseSRAM
+	ret
+; 14e8b
+
+SaveBackupChecksum: ; 14e8b
+	ld hl, sBackupGameData
+	ld bc, sBackupGameDataEnd - sBackupGameData
+	ld a, BANK(sBackupGameData)
+	call GetSRAMBank
+	call Checksum
+	ld a, e
+	ld [sBackupChecksum + 0], a
+	ld a, d
+	ld [sBackupChecksum + 1], a
+	call CloseSRAM
+	ret
+; 14ea5
+
+
+TryLoadSaveFile: ; 14ea5 (5:4ea5)
+	call VerifyChecksum
+	jr nz, .backup
+	call LoadPlayerData
+	call LoadPokemonData
+	call LoadBox
+	farcall RestorePartyMonMail
+	farcall RestoreMobileEventIndex
+	farcall RestoreMysteryGift
+	call ValidateBackupSave
+	call SaveBackupOptions
+	call SaveBackupPlayerData
+	call SaveBackupPokemonData
+	call SaveBackupChecksum
+	and a
+	ret
+
+.backup
+	call VerifyBackupChecksum
+	jr nz, .corrupt
+	call LoadBackupPlayerData
+	call LoadBackupPokemonData
+	call LoadBox
+	farcall RestorePartyMonMail
+	farcall RestoreMobileEventIndex
+	farcall RestoreMysteryGift
+	call ValidateSave
+	call SaveOptions
+	call SavePlayerData
+	call SavePokemonData
+	call SaveChecksum
+	and a
+	ret
+
+.corrupt
+	ld a, [wOptions]
+	push af
+	set NO_TEXT_SCROLL, a
+	ld [wOptions], a
+	ld hl, Text_SaveFileCorrupted
+	call PrintText
+	pop af
+	ld [wOptions], a
+	scf
+	ret
+
+
+TryLoadSaveData: ; 14f1c
+	xor a
+	ld [wSaveFileExists], a
+	call CheckPrimarySaveFile
+	ld a, [wSaveFileExists]
+	and a
+	jr z, .backup
+
+	ld a, BANK(sPlayerData)
+	call GetSRAMBank
+	ld hl, sPlayerData + wStartDay - wPlayerData
+	ld de, wStartDay
+	ld bc, 8
+	call CopyBytes
+	ld hl, sPlayerData + wStatusFlags - wPlayerData
+	ld de, wStatusFlags
+	ld a, [hl]
+	ld [de], a
+	call CloseSRAM
+	ret
+
+.backup
+	call CheckBackupSaveFile
+	ld a, [wSaveFileExists]
+	and a
+	jr z, .corrupt
+
+	ld a, BANK(sBackupPlayerData)
+	call GetSRAMBank
+	ld hl, sBackupPlayerData + wStartDay - wPlayerData
+	ld de, wStartDay
+	ld bc, 8
+	call CopyBytes
+	ld hl, sBackupPlayerData + wStatusFlags - wPlayerData
+	ld de, wStatusFlags
+	ld a, [hl]
+	ld [de], a
+	call CloseSRAM
+	ret
+
+.corrupt
+	ld hl, DefaultOptions
+	ld de, wOptions
+	ld bc, wOptionsEnd - wOptions
+	call CopyBytes
+	call PanicResetClock
+	ret
+; 14f7c
+
+
+INCLUDE "data/default_options.asm"
+
+
+CheckPrimarySaveFile: ; 14f84
+	ld a, BANK(sCheckValue1) ; BANK(sCheckValue2)
+	call GetSRAMBank
+	ld a, [sCheckValue1]
+	cp SAVE_CHECK_VALUE_1
+	jr nz, .nope
+	ld a, [sCheckValue2]
+	cp SAVE_CHECK_VALUE_2
+	jr nz, .nope
+	ld hl, sOptions
+	ld de, wOptions
+	ld bc, wOptionsEnd - wOptions
+	call CopyBytes
+	call CloseSRAM
+	ld a, $1
+	ld [wSaveFileExists], a
+
+.nope
+	call CloseSRAM
+	ret
+; 14faf
+
+CheckBackupSaveFile: ; 14faf
+	ld a, BANK(sBackupCheckValue1) ; BANK(sBackupCheckValue2)
+	call GetSRAMBank
+	ld a, [sBackupCheckValue1]
+	cp SAVE_CHECK_VALUE_1
+	jr nz, .nope
+	ld a, [sBackupCheckValue2]
+	cp SAVE_CHECK_VALUE_2
+	jr nz, .nope
+	ld hl, sBackupOptions
+	ld de, wOptions
+	ld bc, wOptionsEnd - wOptions
+	call CopyBytes
+	ld a, $2
+	ld [wSaveFileExists], a
+
+.nope
+	call CloseSRAM
+	ret
+; 14fd7
+
+
+LoadPlayerData: ; 14fd7 (5:4fd7)
+	ld a, BANK(sPlayerData)
+	call GetSRAMBank
+	ld hl, sPlayerData
+	ld de, wPlayerData
+	ld bc, wPlayerDataEnd - wPlayerData
+	call CopyBytes
+	ld hl, sCurrMapData
+	ld de, wCurrMapData
+	ld bc, wCurrMapDataEnd - wCurrMapData
+	call CopyBytes
+	call CloseSRAM
+	ld a, BANK(sBattleTowerChallengeState)
+	call GetSRAMBank
+	ld a, [sBattleTowerChallengeState]
+	cp BATTLETOWER_RECEIVED_REWARD
+	jr nz, .not_4
+	ld a, BATTLETOWER_WON_CHALLENGE
+	ld [sBattleTowerChallengeState], a
+.not_4
+	call CloseSRAM
+	ret
+
+LoadPokemonData: ; 1500c
+	ld a, BANK(sPokemonData)
+	call GetSRAMBank
+	ld hl, sPokemonData
+	ld de, wPokemonData
+	ld bc, wPokemonDataEnd - wPokemonData
+	call CopyBytes
+	call CloseSRAM
+	ret
+; 15021
+
+LoadBox: ; 15021 (5:5021)
+	call GetBoxAddress
+	call LoadBoxAddress
+	ret
+
+VerifyChecksum: ; 15028 (5:5028)
+	ld hl, sGameData
+	ld bc, sGameDataEnd - sGameData
+	ld a, BANK(sGameData)
+	call GetSRAMBank
+	call Checksum
+	ld a, [sChecksum + 0]
+	cp e
+	jr nz, .fail
+	ld a, [sChecksum + 1]
+	cp d
+.fail
+	push af
+	call CloseSRAM
+	pop af
+	ret
+
+LoadBackupPlayerData: ; 15046 (5:5046)
+	ld a, BANK(sBackupPlayerData)
+	call GetSRAMBank
+	ld hl, sBackupPlayerData
+	ld de, wPlayerData
+	ld bc, wPlayerDataEnd - wPlayerData
+	call CopyBytes
+	ld hl, sBackupCurrMapData
+	ld de, wCurrMapData
+	ld bc, wCurrMapDataEnd - wCurrMapData
+	call CopyBytes
+	call CloseSRAM
+	ret
+
+LoadBackupPokemonData: ; 15067 (5:5067)
+	ld a, BANK(sBackupPokemonData)
+	call GetSRAMBank
+	ld hl, sBackupPokemonData
+	ld de, wPokemonData
+	ld bc, wPokemonDataEnd - wPokemonData
+	call CopyBytes
+	call CloseSRAM
+	ret
+
+VerifyBackupChecksum: ; 1507c (5:507c)
+	ld hl, sBackupGameData
+	ld bc, sBackupGameDataEnd - sBackupGameData
+	ld a, BANK(sBackupGameData)
+	call GetSRAMBank
+	call Checksum
+	ld a, [sBackupChecksum + 0]
+	cp e
+	jr nz, .fail
+	ld a, [sBackupChecksum + 1]
+	cp d
+.fail
+	push af
+	call CloseSRAM
+	pop af
+	ret
+
+
+_SaveData: ; 1509a
+	; This is called within two scenarios:
+	;   a) ErasePreviousSave (the process of erasing the save from a previous game file)
+	;   b) unused mobile functionality
+	; It is not part of a regular save.
+
+	ld a, BANK(sCrystalData)
+	call GetSRAMBank
+	ld hl, wCrystalData
+	ld de, sCrystalData
+	ld bc, wCrystalDataEnd - wCrystalData
+	call CopyBytes
+
+	; This block originally had some mobile functionality, but since we're still in
+	; BANK(sCrystalData), it instead overwrites the sixteen wEventFlags starting at 1:a603 with
+	; garbage from wd479. This isn't an issue, since ErasePreviousSave is followed by a regular
+	; save that unwrites the garbage.
+
+	ld hl, wd479
+	ld a, [hli]
+	ld [$a60e + 0], a
+	ld a, [hli]
+	ld [$a60e + 1], a
+
+	jp CloseSRAM
+
+
+_LoadData: ; 150b9
+	ld a, BANK(sCrystalData)
+	call GetSRAMBank
+	ld hl, sCrystalData
+	ld de, wCrystalData
+	ld bc, wCrystalDataEnd - wCrystalData
+	call CopyBytes
+
+	; This block originally had some mobile functionality to mirror _SaveData above, but instead it
+	; (harmlessly) writes the aforementioned wEventFlags to the unused wd479.
+
+	ld hl, wd479
+	ld a, [$a60e + 0]
+	ld [hli], a
+	ld a, [$a60e + 1]
+	ld [hli], a
+
+	jp CloseSRAM
+
+
+GetBoxAddress: ; 150d8
+	ld a, [wCurBox]
+	cp NUM_BOXES
+	jr c, .ok
+	xor a
+	ld [wCurBox], a
+
+.ok
+	ld e, a
+	ld d, 0
+	ld hl, BoxAddresses
+rept 5
+	add hl, de
+endr
+	ld a, [hli]
+	push af
+	ld a, [hli]
+	ld e, a
+	ld a, [hli]
+	ld d, a
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	pop af
+	ret
+; 150f9
+
+SaveBoxAddress: ; 150f9
+; Save box via wMisc.
+; We do this in three steps because the size of wMisc is less than
+; the size of sBox.
+	push hl
+; Load the first part of the active box.
+	push af
+	push de
+	ld a, BANK(sBox)
+	call GetSRAMBank
+	ld hl, sBox
+	ld de, wMisc
+	ld bc, (wMiscEnd - wMisc)
+	call CopyBytes
+	call CloseSRAM
+	pop de
+	pop af
+; Save it to the target box.
+	push af
+	push de
+	call GetSRAMBank
+	ld hl, wMisc
+	ld bc, (wMiscEnd - wMisc)
+	call CopyBytes
+	call CloseSRAM
+
+; Load the second part of the active box.
+	ld a, BANK(sBox)
+	call GetSRAMBank
+	ld hl, sBox + (wMiscEnd - wMisc)
+	ld de, wMisc
+	ld bc, (wMiscEnd - wMisc)
+	call CopyBytes
+	call CloseSRAM
+	pop de
+	pop af
+
+	ld hl, (wMiscEnd - wMisc)
+	add hl, de
+	ld e, l
+	ld d, h
+; Save it to the next part of the target box.
+	push af
+	push de
+	call GetSRAMBank
+	ld hl, wMisc
+	ld bc, (wMiscEnd - wMisc)
+	call CopyBytes
+	call CloseSRAM
+
+; Load the third and final part of the active box.
+	ld a, BANK(sBox)
+	call GetSRAMBank
+	ld hl, sBox + (wMiscEnd - wMisc) * 2
+	ld de, wMisc
+	ld bc, sBoxEnd - (sBox + (wMiscEnd - wMisc) * 2) ; $8e
+	call CopyBytes
+	call CloseSRAM
+	pop de
+	pop af
+
+	ld hl, (wMiscEnd - wMisc)
+	add hl, de
+	ld e, l
+	ld d, h
+; Save it to the final part of the target box.
+	call GetSRAMBank
+	ld hl, wMisc
+	ld bc, sBoxEnd - (sBox + (wMiscEnd - wMisc) * 2) ; $8e
+	call CopyBytes
+	call CloseSRAM
+
+	pop hl
+	ret
+; 1517d
+
+
+LoadBoxAddress: ; 1517d (5:517d)
+; Load box via wMisc.
+; We do this in three steps because the size of wMisc is less than
+; the size of sBox.
+	push hl
+	ld l, e
+	ld h, d
+; Load part 1
+	push af
+	push hl
+	call GetSRAMBank
+	ld de, wMisc
+	ld bc, (wMiscEnd - wMisc)
+	call CopyBytes
+	call CloseSRAM
+	ld a, BANK(sBox)
+	call GetSRAMBank
+	ld hl, wMisc
+	ld de, sBox
+	ld bc, (wMiscEnd - wMisc)
+	call CopyBytes
+	call CloseSRAM
+	pop hl
+	pop af
+
+	ld de, (wMiscEnd - wMisc)
+	add hl, de
+; Load part 2
+	push af
+	push hl
+	call GetSRAMBank
+	ld de, wMisc
+	ld bc, (wMiscEnd - wMisc)
+	call CopyBytes
+	call CloseSRAM
+	ld a, BANK(sBox)
+	call GetSRAMBank
+	ld hl, wMisc
+	ld de, sBox + (wMiscEnd - wMisc)
+	ld bc, (wMiscEnd - wMisc)
+	call CopyBytes
+	call CloseSRAM
+	pop hl
+	pop af
+; Load part 3
+	ld de, (wMiscEnd - wMisc)
+	add hl, de
+	call GetSRAMBank
+	ld de, wMisc
+	ld bc, sBoxEnd - (sBox + (wMiscEnd - wMisc) * 2) ; $8e
+	call CopyBytes
+	call CloseSRAM
+	ld a, BANK(sBox)
+	call GetSRAMBank
+	ld hl, wMisc
+	ld de, sBox + (wMiscEnd - wMisc) * 2
+	ld bc, sBoxEnd - (sBox + (wMiscEnd - wMisc) * 2) ; $8e
+	call CopyBytes
+	call CloseSRAM
+
+	pop hl
+	ret
+
+
+EraseBoxes: ; 151fb
+	ld hl, BoxAddresses
+	ld c, NUM_BOXES
+.next
+	push bc
+	ld a, [hli]
+	call GetSRAMBank
+	ld a, [hli]
+	ld e, a
+	ld a, [hli]
+	ld d, a
+	xor a
+	ld [de], a
+	inc de
+	ld a, -1
+	ld [de], a
+	inc de
+	ld bc, sBoxEnd - (sBox + 2)
+.clear
+	xor a
+	ld [de], a
+	inc de
+	dec bc
+	ld a, b
+	or c
+	jr nz, .clear
+	ld a, [hli]
+	ld e, a
+	ld a, [hli]
+	ld d, a
+	ld a, -1
+	ld [de], a
+	inc de
+	xor a
+	ld [de], a
+	call CloseSRAM
+	pop bc
+	dec c
+	jr nz, .next
+	ret
+; 1522d
+
+BoxAddresses: ; 1522d
+; dbww bank, address, address
+	dbww BANK(sBox1),  sBox1,  sBox1End
+	dbww BANK(sBox2),  sBox2,  sBox2End
+	dbww BANK(sBox3),  sBox3,  sBox3End
+	dbww BANK(sBox4),  sBox4,  sBox4End
+	dbww BANK(sBox5),  sBox5,  sBox5End
+	dbww BANK(sBox6),  sBox6,  sBox6End
+	dbww BANK(sBox7),  sBox7,  sBox7End
+	dbww BANK(sBox8),  sBox8,  sBox8End
+	dbww BANK(sBox9),  sBox9,  sBox9End
+	dbww BANK(sBox10), sBox10, sBox10End
+	dbww BANK(sBox11), sBox11, sBox11End
+	dbww BANK(sBox12), sBox12, sBox12End
+	dbww BANK(sBox13), sBox13, sBox13End
+	dbww BANK(sBox14), sBox14, sBox14End
+; 15273
+
+
+Checksum: ; 15273
+	ld de, 0
+.loop
+	ld a, [hli]
+	add e
+	ld e, a
+	ld a, 0
+	adc d
+	ld d, a
+	dec bc
+	ld a, b
+	or c
+	jr nz, .loop
+	ret
+; 15283
+
+
+Text_WouldYouLikeToSaveTheGame: ; 0x15283
+	; Would you like to save the game?
+	text_jump UnknownText_0x1c454b
+	db "@"
+; 0x15288
+
+Text_SavingDontTurnOffThePower: ; 0x15288
+	; SAVING… DON'T TURN OFF THE POWER.
+	text_jump UnknownText_0x1c456d
+	db "@"
+; 0x1528d
+
+Text_PlayerSavedTheGame: ; 0x1528d
+	; saved the game.
+	text_jump UnknownText_0x1c4590
+	db "@"
+; 0x15292
+
+Text_AlreadyASaveFile: ; 0x15292
+	; There is already a save file. Is it OK to overwrite?
+	text_jump UnknownText_0x1c45a3
+	db "@"
+; 0x15297
+
+Text_AnotherSaveFile: ; 0x15297
+	; There is another save file. Is it OK to overwrite?
+	text_jump UnknownText_0x1c45d9
+	db "@"
+; 0x1529c
+
+Text_SaveFileCorrupted: ; 0x1529c
+	; The save file is corrupted!
+	text_jump UnknownText_0x1c460d
+	db "@"
+; 0x152a1
+
+Text_SaveOnBoxSwitch: ; 0x152a1
+	; When you change a #MON BOX, data will be saved. OK?
+	text_jump UnknownText_0x1c462a
+	db "@"
+; 0x152a6
+
+Text_SaveOnMoveMonWOMail: ; 0x152a6
+	; Each time you move a #MON, data will be saved. OK?
+	text_jump UnknownText_0x1c465f
+	db "@"
+; 0x152ab
--- /dev/null
+++ b/engine/menus/savemenu_copytilemapatonce.asm
@@ -1,0 +1,77 @@
+SaveMenu_CopyTilemapAtOnce: ; 4cf45 (13:4f45)
+	ld a, [hCGB]
+	and a
+	jp z, WaitBGMap
+
+; The following is a modified version of CopyTilemapAtOnce.
+	ld a, [hBGMapMode]
+	push af
+	xor a
+	ld [hBGMapMode], a
+	ld a, [hMapAnims]
+	push af
+	xor a
+	ld [hMapAnims], a
+.WaitLY:
+	ld a, [rLY]
+	cp $60
+	jr c, .WaitLY
+
+	di
+	ld a, BANK(vBGMap2)
+	ld [rVBK], a
+	hlcoord 0, 0, wAttrMap
+	call .CopyTilemapAtOnce
+	ld a, BANK(vBGMap0)
+	ld [rVBK], a
+	hlcoord 0, 0
+	call .CopyTilemapAtOnce
+.WaitLY2:
+	ld a, [rLY]
+	cp $60
+	jr c, .WaitLY2
+	ei
+
+	pop af
+	ld [hMapAnims], a
+	pop af
+	ld [hBGMapMode], a
+	ret
+
+.CopyTilemapAtOnce: ; 4cf80 (13:4f80)
+	ld [hSPBuffer], sp ; $ffd9
+	ld sp, hl
+	ld a, [hBGMapAddress + 1]
+	ld h, a
+	ld l, 0
+	ld a, SCREEN_HEIGHT
+	ld [hTilesPerCycle], a
+	ld b, 1 << 1
+	ld c, LOW(rSTAT)
+
+.loop
+rept SCREEN_WIDTH / 2
+	pop de
+.loop\@
+	ld a, [$ff00+c]
+	and b
+	jr nz, .loop\@
+	ld [hl], e
+	inc l
+	ld [hl], d
+	inc l
+endr
+
+	ld de, BG_MAP_WIDTH - SCREEN_WIDTH
+	add hl, de
+	ld a, [hTilesPerCycle]
+	dec a
+	ld [hTilesPerCycle], a
+	jr nz, .loop
+
+	ld a, [hSPBuffer]
+	ld l, a
+	ld a, [hSPBuffer + 1]
+	ld h, a
+	ld sp, hl
+	ret
--- a/engine/money.asm
+++ /dev/null
@@ -1,221 +1,0 @@
-GiveMoney:: ; 15fd7
-	ld a, 3
-	call AddMoney
-	ld bc, MaxMoney
-	ld a, 3
-	call CompareMoney
-	jr z, .not_maxed_out
-	jr c, .not_maxed_out
-	ld hl, MaxMoney
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hli]
-	ld [de], a
-	scf
-	ret
-
-.not_maxed_out
-	and a
-	ret
-; 15ff7
-
-MaxMoney: ; 15ff7
-	dt MAX_MONEY
-; 15ffa
-
-
-TakeMoney:: ; 15ffa
-	ld a, 3
-	call SubtractMoney
-	jr nc, .okay
-	; leave with 0 money
-	xor a
-	ld [de], a
-	inc de
-	ld [de], a
-	inc de
-	ld [de], a
-	scf
-	ret
-
-.okay
-	and a
-	ret
-; 1600b
-
-CompareMoney:: ; 1600b
-	ld a, 3
-CompareFunds: ; 1600d
-; a: number of bytes
-; bc: start addr of amount (big-endian)
-; de: start addr of account (big-endian)
-	push hl
-	push de
-	push bc
-	ld h, b
-	ld l, c
-	ld c, 0
-	ld b, a
-.loop1
-	dec a
-	jr z, .done
-	inc de
-	inc hl
-	jr .loop1
-
-.done
-	and a
-.loop2
-	ld a, [de]
-	sbc [hl]
-	jr z, .okay
-	inc c
-
-.okay
-	dec de
-	dec hl
-	dec b
-	jr nz, .loop2
-	jr c, .set_carry
-	ld a, c
-	and a
-	jr .skip_carry
-
-.set_carry
-	ld a, 1
-	and a
-	scf
-.skip_carry
-	pop bc
-	pop de
-	pop hl
-	ret
-; 16035
-
-SubtractMoney: ; 16035
-	ld a, 3
-SubtractFunds: ; 16037
-; a: number of bytes
-; bc: start addr of amount (big-endian)
-; de: start addr of account (big-endian)
-	push hl
-	push de
-	push bc
-	ld h, b
-	ld l, c
-	ld b, a
-	ld c, 0
-.loop
-	dec a
-	jr z, .done
-	inc de
-	inc hl
-	jr .loop
-
-.done
-	and a
-.loop2
-	ld a, [de]
-	sbc [hl]
-	ld [de], a
-	dec de
-	dec hl
-	dec b
-	jr nz, .loop2
-	pop bc
-	pop de
-	pop hl
-	ret
-; 16053
-
-AddMoney: ; 16053
-	ld a, 3
-AddFunds: ; 16055
-; a: number of bytes
-; bc: start addr of amount (big-endian)
-; de: start addr of account (big-endian)
-	push hl
-	push de
-	push bc
-
-	ld h, b
-	ld l, c
-	ld b, a
-.loop1
-	dec a
-	jr z, .done
-	inc de
-	inc hl
-	jr .loop1
-
-.done
-	and a
-.loop2
-	ld a, [de]
-	adc [hl]
-	ld [de], a
-	dec de
-	dec hl
-	dec b
-	jr nz, .loop2
-
-	pop bc
-	pop de
-	pop hl
-	ret
-; 1606f
-
-GiveCoins:: ; 1606f
-	ld a, 2
-	ld de, wCoins
-	call AddFunds
-	ld a, 2
-	ld bc, .maxcoins
-	call CompareFunds
-	jr c, .not_maxed
-	ld hl, .maxcoins
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hli]
-	ld [de], a
-	scf
-	ret
-
-.not_maxed
-	and a
-	ret
-; 1608d
-
-.maxcoins ; 1608d
-	bigdw MAX_COINS
-; 1608f
-
-
-TakeCoins:: ; 1608f
-	ld a, 2
-	ld de, wCoins
-	call SubtractFunds
-	jr nc, .okay
-	; leave with 0 coins
-	xor a
-	ld [de], a
-	inc de
-	ld [de], a
-	scf
-	ret
-
-.okay
-	and a
-	ret
-; 160a1
-
-CheckCoins:: ; 160a1
-	ld a, 2
-	ld de, wCoins
-	jp CompareFunds
-; 160a9
--- /dev/null
+++ b/engine/movie/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/movie/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/movie/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/movie/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/movie/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/movie/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/movie/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"
--- /dev/null
+++ b/engine/movie/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
--- /dev/null
+++ b/engine/phone/phonering_copytilemapatonce.asm
@@ -1,0 +1,80 @@
+PhoneRing_CopyTilemapAtOnce: ; 4d188
+	ld a, [hCGB]
+	and a
+	jp z, WaitBGMap
+	ld a, [wSpriteUpdatesEnabled]
+	cp $0
+	jp z, WaitBGMap
+
+; What follows is a modified version of CopyTilemapAtOnce.
+	ld a, [hBGMapMode]
+	push af
+	xor a
+	ld [hBGMapMode], a
+	ld a, [hMapAnims]
+	push af
+	xor a
+	ld [hMapAnims], a
+.wait
+	ld a, [rLY]
+	cp LY_VBLANK - 1
+	jr c, .wait
+
+	di
+	ld a, BANK(vBGMap2)
+	ld [rVBK], a
+	hlcoord 0, 0, wAttrMap
+	call .CopyTilemapAtOnce
+	ld a, BANK(vBGMap0)
+	ld [rVBK], a
+	hlcoord 0, 0
+	call .CopyTilemapAtOnce
+.wait2
+	ld a, [rLY]
+	cp LY_VBLANK - 1
+	jr c, .wait2
+	ei
+
+	pop af
+	ld [hMapAnims], a
+	pop af
+	ld [hBGMapMode], a
+	ret
+
+.CopyTilemapAtOnce: ; 4d1cb
+	ld [hSPBuffer], sp
+	ld sp, hl
+	ld a, [hBGMapAddress + 1]
+	ld h, a
+	ld l, 0
+	ld a, SCREEN_HEIGHT
+	ld [hTilesPerCycle], a
+	ld b, 1 << 1 ; not in v/hblank
+	ld c, LOW(rSTAT)
+
+.loop
+rept SCREEN_WIDTH / 2
+	pop de
+.loop\@
+	ld a, [$ff00+c]
+	and b
+	jr nz, .loop\@
+	ld [hl], e
+	inc l
+	ld [hl], d
+	inc l
+endr
+
+	ld de, BG_MAP_WIDTH - SCREEN_WIDTH
+	add hl, de
+	ld a, [hTilesPerCycle]
+	dec a
+	ld [hTilesPerCycle], a
+	jr nz, .loop
+
+	ld a, [hSPBuffer]
+	ld l, a
+	ld a, [hSPBuffer + 1]
+	ld h, a
+	ld sp, hl
+	ret
--- /dev/null
+++ b/engine/pokegear/townmap_convertlinebreakcharacters.asm
@@ -1,0 +1,21 @@
+TownMap_ConvertLineBreakCharacters: ; 1de2c5
+	ld hl, wStringBuffer1
+.loop
+	ld a, [hl]
+	cp "@"
+	jr z, .end
+	cp "%"
+	jr z, .line_break
+	cp "¯"
+	jr z, .line_break
+	inc hl
+	jr .loop
+
+.line_break
+	ld [hl], "<LNBRK>"
+
+.end
+	ld de, wStringBuffer1
+	hlcoord 9, 0
+	call PlaceString
+	ret
--- /dev/null
+++ b/engine/pokemon/checknickerrors.asm
@@ -1,0 +1,74 @@
+CheckNickErrors:: ; 669f
+; error-check monster nick before use
+; must be a peace offering to gamesharkers
+
+; input: de = nick location
+
+	push bc
+	push de
+	ld b, MON_NAME_LENGTH
+
+.checkchar
+; end of nick?
+	ld a, [de]
+	cp "@" ; terminator
+	jr z, .end
+
+; check if this char is a text command
+	ld hl, .textcommands
+	dec hl
+.loop
+; next entry
+	inc hl
+; reached end of commands table?
+	ld a, [hl]
+	cp -1
+	jr z, .done
+
+; is the current char between this value (inclusive)...
+	ld a, [de]
+	cp [hl]
+	inc hl
+	jr c, .loop
+; ...and this one?
+	cp [hl]
+	jr nc, .loop
+
+; replace it with a "?"
+	ld a, "?"
+	ld [de], a
+	jr .loop
+
+.done
+; next char
+	inc de
+; reached end of nick without finding a terminator?
+	dec b
+	jr nz, .checkchar
+
+; change nick to "?@"
+	pop de
+	push de
+	ld a, "?"
+	ld [de], a
+	inc de
+	ld a, "@"
+	ld [de], a
+.end
+; if the nick has any errors at this point it's out of our hands
+	pop de
+	pop bc
+	ret
+
+.textcommands ; 66cf
+; table defining which characters are actually text commands
+; format:
+	;      ≥           <
+	db TX_START,   TX_BOX    + 1
+	db "<PLAY_G>", "<JP_18>" + 1
+	db "<NI>",     "<NO>"    + 1
+	db "<ROUTE>",  "<GREEN>" + 1
+	db "<ENEMY>",  "<ENEMY>" + 1
+	db "<MOM>",    "<TM>"    + 1
+	db "<ROCKET>", "┘"       + 1
+	db -1 ; end
--- /dev/null
+++ b/engine/pokemon/correcterrorsinplayerparty.asm
@@ -1,0 +1,229 @@
+Unreferenced_CorrectErrorsInPlayerParty:
+	ld hl, wPartyCount
+	ld a, [hl]
+	and a
+	ret z
+
+	cp PARTY_LENGTH + 1
+	jr c, .party_length_okay
+	ld a, PARTY_LENGTH
+	ld [hl], a
+.party_length_okay
+	inc hl
+
+	ld b, a
+	ld c, 0
+.loop1
+	ld a, [hl]
+	and a
+	jr z, .invalid_species
+	cp NUM_POKEMON + 1
+	jr z, .invalid_species
+	cp EGG + 1
+	jr c, .next_species
+
+.invalid_species
+	ld [hl], SMEARGLE
+	push hl
+	push bc
+	ld a, c
+	ld hl, wPartyMon1Species
+	call GetPartyLocation
+	ld [hl], SMEARGLE
+	pop bc
+	pop hl
+
+.next_species
+	inc hl
+	inc c
+	dec b
+	jr nz, .loop1
+	ld [hl], $ff
+
+	ld hl, wPartyMon1
+	ld a, [wPartyCount]
+	ld d, a
+	ld e, 0
+.loop2
+	push de
+	push hl
+	ld b, h
+	ld c, l
+	ld a, [hl]
+	and a
+	jr z, .invalid_species_2
+	cp NUM_POKEMON + 1
+	jr c, .check_level
+
+.invalid_species_2
+	ld [hl], SMEARGLE
+	push de
+	ld d, 0
+	ld hl, wPartySpecies
+	add hl, de
+	pop de
+	ld a, SMEARGLE
+	ld [hl], a
+
+.check_level
+	ld [wCurSpecies], a
+	call GetBaseData
+	ld hl, MON_LEVEL
+	add hl, bc
+	ld a, [hl]
+	cp MIN_LEVEL
+	ld a, MIN_LEVEL
+	jr c, .invalid_level
+	ld a, [hl]
+	cp MAX_LEVEL
+	jr c, .load_level
+	ld a, MAX_LEVEL
+.invalid_level
+	ld [hl], a
+.load_level
+	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
+	ld b, TRUE
+	predef CalcMonStats
+	pop hl
+	ld bc, PARTYMON_STRUCT_LENGTH
+	add hl, bc
+	pop de
+	inc e
+	dec d
+	jr nz, .loop2
+
+	ld de, wPartyMonNicknames
+	ld a, [wPartyCount]
+	ld b, a
+	ld c, 0
+.loop3
+	push bc
+	call .GetLengthOfStringWith6CharCap
+	push de
+	farcall CheckStringForErrors
+	pop hl
+	pop bc
+	jr nc, .valid_nickname
+
+	push bc
+	push hl
+	ld hl, wPartySpecies
+	push bc
+	ld b, 0
+	add hl, bc
+	pop bc
+	ld a, [hl]
+	cp EGG
+	ld hl, .TAMAGO
+	jr z, .got_nickname
+	ld [wd265], a
+	call GetPokemonName
+	ld hl, wStringBuffer1
+.got_nickname
+	pop de
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+	pop bc
+
+.valid_nickname
+	inc c
+	dec b
+	jr nz, .loop3
+
+	ld de, wPartyMonOT
+	ld a, [wPartyCount]
+	ld b, a
+	ld c, 0
+.loop4
+	push bc
+	call .GetLengthOfStringWith6CharCap
+	push de
+	farcall CheckStringForErrors
+	pop hl
+	jr nc, .valid_ot_name
+	ld d, h
+	ld e, l
+	ld hl, wPlayerName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+.valid_ot_name
+	pop bc
+	inc c
+	dec b
+	jr nz, .loop4
+
+	ld hl, wPartyMon1Moves
+	ld a, [wPartyCount]
+	ld b, a
+.loop5
+	push hl
+	ld c, NUM_MOVES
+	ld a, [hl]
+	and a
+	jr z, .invalid_move
+	cp NUM_ATTACKS + 1
+	jr c, .moves_loop
+.invalid_move
+	ld [hl], POUND
+
+.moves_loop
+	ld a, [hl]
+	and a
+	jr z, .fill_invalid_moves
+	cp NUM_ATTACKS + 1
+	jr c, .next_move
+
+.fill_invalid_moves
+	xor a
+	ld [hli], a
+	dec c
+	jr nz, .fill_invalid_moves
+	jr .next_pokemon
+
+.next_move
+	inc hl
+	dec c
+	jr nz, .moves_loop
+
+.next_pokemon
+	pop hl
+	push bc
+	ld bc, PARTYMON_STRUCT_LENGTH
+	add hl, bc
+	pop bc
+	dec b
+	jr nz, .loop5
+	ret
+; 13b6b
+
+.TAMAGO: ; 13b6b
+	db "タマゴ@@@"
+; 13b71
+
+.GetLengthOfStringWith6CharCap: ; 13b71
+	push de
+	ld c, 1
+	ld b, NAME_LENGTH_JAPANESE
+.search_loop
+	ld a, [de]
+	cp "@"
+	jr z, .done
+	inc de
+	inc c
+	dec b
+	jr nz, .search_loop
+	dec c
+	dec de
+	ld a, "@"
+	ld [de], a
+.done
+	pop de
+	ret
+; 13b87
--- a/engine/pokemon/tmhm.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/predef.asm
+++ /dev/null
@@ -1,29 +1,0 @@
-GetPredefPointer:: ; 854b
-; Return the bank and address of wPredefID in a and wPredefAddress.
-
-; Save hl for later (back in Predef)
-	ld a, h
-	ld [wPredefTemp], a
-	ld a, l
-	ld [wPredefTemp + 1], a
-
-	push de
-	ld a, [wPredefID]
-	ld e, a
-	ld d, 0
-	ld hl, PredefPointers
-	add hl, de
-	add hl, de
-	add hl, de
-	pop de
-
-	ld a, [hli]
-	ld [wPredefAddress + 1], a
-	ld a, [hli]
-	ld [wPredefAddress], a
-	ld a, [hl]
-
-	ret
-; 856b
-
-INCLUDE "data/predef_pointers.asm"
--- a/engine/routines/checknickerrors.asm
+++ /dev/null
@@ -1,74 +1,0 @@
-CheckNickErrors:: ; 669f
-; error-check monster nick before use
-; must be a peace offering to gamesharkers
-
-; input: de = nick location
-
-	push bc
-	push de
-	ld b, MON_NAME_LENGTH
-
-.checkchar
-; end of nick?
-	ld a, [de]
-	cp "@" ; terminator
-	jr z, .end
-
-; check if this char is a text command
-	ld hl, .textcommands
-	dec hl
-.loop
-; next entry
-	inc hl
-; reached end of commands table?
-	ld a, [hl]
-	cp -1
-	jr z, .done
-
-; is the current char between this value (inclusive)...
-	ld a, [de]
-	cp [hl]
-	inc hl
-	jr c, .loop
-; ...and this one?
-	cp [hl]
-	jr nc, .loop
-
-; replace it with a "?"
-	ld a, "?"
-	ld [de], a
-	jr .loop
-
-.done
-; next char
-	inc de
-; reached end of nick without finding a terminator?
-	dec b
-	jr nz, .checkchar
-
-; change nick to "?@"
-	pop de
-	push de
-	ld a, "?"
-	ld [de], a
-	inc de
-	ld a, "@"
-	ld [de], a
-.end
-; if the nick has any errors at this point it's out of our hands
-	pop de
-	pop bc
-	ret
-
-.textcommands ; 66cf
-; table defining which characters are actually text commands
-; format:
-	;      ≥           <
-	db TX_START,   TX_BOX    + 1
-	db "<PLAY_G>", "<JP_18>" + 1
-	db "<NI>",     "<NO>"    + 1
-	db "<ROUTE>",  "<GREEN>" + 1
-	db "<ENEMY>",  "<ENEMY>" + 1
-	db "<MOM>",    "<TM>"    + 1
-	db "<ROCKET>", "┘"       + 1
-	db -1 ; end
--- a/engine/routines/checksave.asm
+++ /dev/null
@@ -1,20 +1,0 @@
-CheckSave:: ; 4cffe
-	ld a, BANK(sCheckValue1) ; BANK(sCheckValue2)
-	call GetSRAMBank
-	ld a, [sCheckValue1]
-	ld b, a
-	ld a, [sCheckValue2]
-	ld c, a
-	call CloseSRAM
-	ld a, b
-	cp SAVE_CHECK_VALUE_1
-	jr nz, .ok
-	ld a, c
-	cp SAVE_CHECK_VALUE_2
-	jr nz, .ok
-	ld c, $1
-	ret
-
-.ok
-	ld c, $0
-	ret
--- a/engine/routines/checktime.asm
+++ /dev/null
@@ -1,19 +1,0 @@
-CheckTime:: ; c000
-	ld a, [wTimeOfDay]
-	ld hl, .TimeOfDayTable
-	ld de, 2
-	call IsInArray
-	inc hl
-	ld c, [hl]
-	ret c
-
-	xor a
-	ld c, a
-	ret
-
-.TimeOfDayTable: ; c012
-	db MORN_F, MORN
-	db DAY_F,  DAY
-	db NITE_F, NITE
-	db NITE_F, NITE
-	db -1
--- a/engine/routines/correcterrorsinplayerparty.asm
+++ /dev/null
@@ -1,229 +1,0 @@
-Unreferenced_CorrectErrorsInPlayerParty:
-	ld hl, wPartyCount
-	ld a, [hl]
-	and a
-	ret z
-
-	cp PARTY_LENGTH + 1
-	jr c, .party_length_okay
-	ld a, PARTY_LENGTH
-	ld [hl], a
-.party_length_okay
-	inc hl
-
-	ld b, a
-	ld c, 0
-.loop1
-	ld a, [hl]
-	and a
-	jr z, .invalid_species
-	cp NUM_POKEMON + 1
-	jr z, .invalid_species
-	cp EGG + 1
-	jr c, .next_species
-
-.invalid_species
-	ld [hl], SMEARGLE
-	push hl
-	push bc
-	ld a, c
-	ld hl, wPartyMon1Species
-	call GetPartyLocation
-	ld [hl], SMEARGLE
-	pop bc
-	pop hl
-
-.next_species
-	inc hl
-	inc c
-	dec b
-	jr nz, .loop1
-	ld [hl], $ff
-
-	ld hl, wPartyMon1
-	ld a, [wPartyCount]
-	ld d, a
-	ld e, 0
-.loop2
-	push de
-	push hl
-	ld b, h
-	ld c, l
-	ld a, [hl]
-	and a
-	jr z, .invalid_species_2
-	cp NUM_POKEMON + 1
-	jr c, .check_level
-
-.invalid_species_2
-	ld [hl], SMEARGLE
-	push de
-	ld d, 0
-	ld hl, wPartySpecies
-	add hl, de
-	pop de
-	ld a, SMEARGLE
-	ld [hl], a
-
-.check_level
-	ld [wCurSpecies], a
-	call GetBaseData
-	ld hl, MON_LEVEL
-	add hl, bc
-	ld a, [hl]
-	cp MIN_LEVEL
-	ld a, MIN_LEVEL
-	jr c, .invalid_level
-	ld a, [hl]
-	cp MAX_LEVEL
-	jr c, .load_level
-	ld a, MAX_LEVEL
-.invalid_level
-	ld [hl], a
-.load_level
-	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
-	ld b, TRUE
-	predef CalcMonStats
-	pop hl
-	ld bc, PARTYMON_STRUCT_LENGTH
-	add hl, bc
-	pop de
-	inc e
-	dec d
-	jr nz, .loop2
-
-	ld de, wPartyMonNicknames
-	ld a, [wPartyCount]
-	ld b, a
-	ld c, 0
-.loop3
-	push bc
-	call .GetLengthOfStringWith6CharCap
-	push de
-	farcall CheckStringForErrors
-	pop hl
-	pop bc
-	jr nc, .valid_nickname
-
-	push bc
-	push hl
-	ld hl, wPartySpecies
-	push bc
-	ld b, 0
-	add hl, bc
-	pop bc
-	ld a, [hl]
-	cp EGG
-	ld hl, .TAMAGO
-	jr z, .got_nickname
-	ld [wd265], a
-	call GetPokemonName
-	ld hl, wStringBuffer1
-.got_nickname
-	pop de
-	ld bc, MON_NAME_LENGTH
-	call CopyBytes
-	pop bc
-
-.valid_nickname
-	inc c
-	dec b
-	jr nz, .loop3
-
-	ld de, wPartyMonOT
-	ld a, [wPartyCount]
-	ld b, a
-	ld c, 0
-.loop4
-	push bc
-	call .GetLengthOfStringWith6CharCap
-	push de
-	farcall CheckStringForErrors
-	pop hl
-	jr nc, .valid_ot_name
-	ld d, h
-	ld e, l
-	ld hl, wPlayerName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-.valid_ot_name
-	pop bc
-	inc c
-	dec b
-	jr nz, .loop4
-
-	ld hl, wPartyMon1Moves
-	ld a, [wPartyCount]
-	ld b, a
-.loop5
-	push hl
-	ld c, NUM_MOVES
-	ld a, [hl]
-	and a
-	jr z, .invalid_move
-	cp NUM_ATTACKS + 1
-	jr c, .moves_loop
-.invalid_move
-	ld [hl], POUND
-
-.moves_loop
-	ld a, [hl]
-	and a
-	jr z, .fill_invalid_moves
-	cp NUM_ATTACKS + 1
-	jr c, .next_move
-
-.fill_invalid_moves
-	xor a
-	ld [hli], a
-	dec c
-	jr nz, .fill_invalid_moves
-	jr .next_pokemon
-
-.next_move
-	inc hl
-	dec c
-	jr nz, .moves_loop
-
-.next_pokemon
-	pop hl
-	push bc
-	ld bc, PARTYMON_STRUCT_LENGTH
-	add hl, bc
-	pop bc
-	dec b
-	jr nz, .loop5
-	ret
-; 13b6b
-
-.TAMAGO: ; 13b6b
-	db "タマゴ@@@"
-; 13b71
-
-.GetLengthOfStringWith6CharCap: ; 13b71
-	push de
-	ld c, 1
-	ld b, NAME_LENGTH_JAPANESE
-.search_loop
-	ld a, [de]
-	cp "@"
-	jr z, .done
-	inc de
-	inc c
-	dec b
-	jr nz, .search_loop
-	dec c
-	dec de
-	ld a, "@"
-	ld [de], a
-.done
-	pop de
-	ret
-; 13b87
--- a/engine/routines/loadpushoam.asm
+++ /dev/null
@@ -1,21 +1,0 @@
-WriteOAMDMACodeToHRAM:: ; 4031
-	ld c, hTransferVirtualOAM - $ff00
-	ld b, .PushOAMEnd - .PushOAM
-	ld hl, .PushOAM
-.loop
-	ld a, [hli]
-	ld [$ff00+c], a
-	inc c
-	dec b
-	jr nz, .loop
-	ret
-
-.PushOAM: ; 403f
-	ld a, HIGH(wVirtualOAM)
-	ld [rDMA], a
-	ld a, NUM_SPRITE_OAM_STRUCTS
-.pushoam_loop
-	dec a
-	jr nz, .pushoam_loop
-	ret
-.PushOAMEnd
--- a/engine/routines/phonering_copytilemapatonce.asm
+++ /dev/null
@@ -1,80 +1,0 @@
-PhoneRing_CopyTilemapAtOnce: ; 4d188
-	ld a, [hCGB]
-	and a
-	jp z, WaitBGMap
-	ld a, [wSpriteUpdatesEnabled]
-	cp $0
-	jp z, WaitBGMap
-
-; What follows is a modified version of CopyTilemapAtOnce.
-	ld a, [hBGMapMode]
-	push af
-	xor a
-	ld [hBGMapMode], a
-	ld a, [hMapAnims]
-	push af
-	xor a
-	ld [hMapAnims], a
-.wait
-	ld a, [rLY]
-	cp LY_VBLANK - 1
-	jr c, .wait
-
-	di
-	ld a, BANK(vBGMap2)
-	ld [rVBK], a
-	hlcoord 0, 0, wAttrMap
-	call .CopyTilemapAtOnce
-	ld a, BANK(vBGMap0)
-	ld [rVBK], a
-	hlcoord 0, 0
-	call .CopyTilemapAtOnce
-.wait2
-	ld a, [rLY]
-	cp LY_VBLANK - 1
-	jr c, .wait2
-	ei
-
-	pop af
-	ld [hMapAnims], a
-	pop af
-	ld [hBGMapMode], a
-	ret
-
-.CopyTilemapAtOnce: ; 4d1cb
-	ld [hSPBuffer], sp
-	ld sp, hl
-	ld a, [hBGMapAddress + 1]
-	ld h, a
-	ld l, 0
-	ld a, SCREEN_HEIGHT
-	ld [hTilesPerCycle], a
-	ld b, 1 << 1 ; not in v/hblank
-	ld c, LOW(rSTAT)
-
-.loop
-rept SCREEN_WIDTH / 2
-	pop de
-.loop\@
-	ld a, [$ff00+c]
-	and b
-	jr nz, .loop\@
-	ld [hl], e
-	inc l
-	ld [hl], d
-	inc l
-endr
-
-	ld de, BG_MAP_WIDTH - SCREEN_WIDTH
-	add hl, de
-	ld a, [hTilesPerCycle]
-	dec a
-	ld [hTilesPerCycle], a
-	jr nz, .loop
-
-	ld a, [hSPBuffer]
-	ld l, a
-	ld a, [hSPBuffer + 1]
-	ld h, a
-	ld sp, hl
-	ret
--- a/engine/routines/placewaitingtext.asm
+++ /dev/null
@@ -1,24 +1,0 @@
-PlaceWaitingText:: ; 4000
-	hlcoord 3, 10
-	ld b, 1
-	ld c, 11
-
-	ld a, [wBattleMode]
-	and a
-	jr z, .notinbattle
-
-	call TextBox
-	jr .proceed
-
-.notinbattle
-	predef LinkTextboxAtHL
-
-.proceed
-	hlcoord 4, 11
-	ld de, .Waiting
-	call PlaceString
-	ld c, 50
-	jp DelayFrames
-
-.Waiting: ; 4025
-	db "Waiting...!@"
--- a/engine/routines/playslowcry.asm
+++ /dev/null
@@ -1,31 +1,0 @@
-PlaySlowCry: ; fb841
-	ld a, [wScriptVar]
-	call LoadCry
-	jr c, .done
-
-	ld hl, wCryPitch
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld bc, -$140
-	add hl, bc
-	ld a, l
-	ld [wCryPitch], a
-	ld a, h
-	ld [wCryPitch + 1], a
-	ld hl, wCryLength
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld bc, $60
-	add hl, bc
-	ld a, l
-	ld [wCryLength], a
-	ld a, h
-	ld [wCryLength + 1], a
-	farcall _PlayCry
-	call WaitSFX
-
-.done
-	ret
-; fb877
--- /dev/null
+++ b/engine/routines/predef.asm
@@ -1,0 +1,29 @@
+GetPredefPointer:: ; 854b
+; Return the bank and address of wPredefID in a and wPredefAddress.
+
+; Save hl for later (back in Predef)
+	ld a, h
+	ld [wPredefTemp], a
+	ld a, l
+	ld [wPredefTemp + 1], a
+
+	push de
+	ld a, [wPredefID]
+	ld e, a
+	ld d, 0
+	ld hl, PredefPointers
+	add hl, de
+	add hl, de
+	add hl, de
+	pop de
+
+	ld a, [hli]
+	ld [wPredefAddress + 1], a
+	ld a, [hli]
+	ld [wPredefAddress], a
+	ld a, [hl]
+
+	ret
+; 856b
+
+INCLUDE "data/predef_pointers.asm"
--- a/engine/routines/savemenu_copytilemapatonce.asm
+++ /dev/null
@@ -1,77 +1,0 @@
-SaveMenu_CopyTilemapAtOnce: ; 4cf45 (13:4f45)
-	ld a, [hCGB]
-	and a
-	jp z, WaitBGMap
-
-; The following is a modified version of CopyTilemapAtOnce.
-	ld a, [hBGMapMode]
-	push af
-	xor a
-	ld [hBGMapMode], a
-	ld a, [hMapAnims]
-	push af
-	xor a
-	ld [hMapAnims], a
-.WaitLY:
-	ld a, [rLY]
-	cp $60
-	jr c, .WaitLY
-
-	di
-	ld a, BANK(vBGMap2)
-	ld [rVBK], a
-	hlcoord 0, 0, wAttrMap
-	call .CopyTilemapAtOnce
-	ld a, BANK(vBGMap0)
-	ld [rVBK], a
-	hlcoord 0, 0
-	call .CopyTilemapAtOnce
-.WaitLY2:
-	ld a, [rLY]
-	cp $60
-	jr c, .WaitLY2
-	ei
-
-	pop af
-	ld [hMapAnims], a
-	pop af
-	ld [hBGMapMode], a
-	ret
-
-.CopyTilemapAtOnce: ; 4cf80 (13:4f80)
-	ld [hSPBuffer], sp ; $ffd9
-	ld sp, hl
-	ld a, [hBGMapAddress + 1]
-	ld h, a
-	ld l, 0
-	ld a, SCREEN_HEIGHT
-	ld [hTilesPerCycle], a
-	ld b, 1 << 1
-	ld c, LOW(rSTAT)
-
-.loop
-rept SCREEN_WIDTH / 2
-	pop de
-.loop\@
-	ld a, [$ff00+c]
-	and b
-	jr nz, .loop\@
-	ld [hl], e
-	inc l
-	ld [hl], d
-	inc l
-endr
-
-	ld de, BG_MAP_WIDTH - SCREEN_WIDTH
-	add hl, de
-	ld a, [hTilesPerCycle]
-	dec a
-	ld [hTilesPerCycle], a
-	jr nz, .loop
-
-	ld a, [hSPBuffer]
-	ld l, a
-	ld a, [hSPBuffer + 1]
-	ld h, a
-	ld sp, hl
-	ret
--- a/engine/routines/townmap_convertlinebreakcharacters.asm
+++ /dev/null
@@ -1,21 +1,0 @@
-TownMap_ConvertLineBreakCharacters: ; 1de2c5
-	ld hl, wStringBuffer1
-.loop
-	ld a, [hl]
-	cp "@"
-	jr z, .end
-	cp "%"
-	jr z, .line_break
-	cp "¯"
-	jr z, .line_break
-	inc hl
-	jr .loop
-
-.line_break
-	ld [hl], "<LNBRK>"
-
-.end
-	ld de, wStringBuffer1
-	hlcoord 9, 0
-	call PlaceString
-	ret
--- a/engine/save.asm
+++ /dev/null
@@ -1,1210 +1,0 @@
-SaveMenu: ; 14a1a
-	call LoadStandardMenuHeader
-	farcall DisplaySaveInfoOnSave
-	call SpeechTextBox
-	call UpdateSprites
-	farcall SaveMenu_CopyTilemapAtOnce
-	ld hl, Text_WouldYouLikeToSaveTheGame
-	call SaveTheGame_yesorno
-	jr nz, .refused
-	call AskOverwriteSaveFile
-	jr c, .refused
-	call PauseGameLogic
-	call _SavingDontTurnOffThePower
-	call ResumeGameLogic
-	call ExitMenu
-	and a
-	ret
-
-.refused
-	call ExitMenu
-	call ret_d90
-	farcall SaveMenu_CopyTilemapAtOnce
-	scf
-	ret
-
-SaveAfterLinkTrade: ; 14a58
-	call PauseGameLogic
-	farcall StageRTCTimeForSave
-	farcall BackupMysteryGift
-	call SavePokemonData
-	call SaveChecksum
-	call SaveBackupPokemonData
-	call SaveBackupChecksum
-	farcall BackupPartyMonMail
-	farcall SaveRTC
-	call ResumeGameLogic
-	ret
-; 14a83
-
-
-ChangeBoxSaveGame: ; 14a83 (5:4a83)
-	push de
-	ld hl, Text_SaveOnBoxSwitch
-	call MenuTextBox
-	call YesNoBox
-	call ExitMenu
-	jr c, .refused
-	call AskOverwriteSaveFile
-	jr c, .refused
-	call PauseGameLogic
-	call SavingDontTurnOffThePower
-	call SaveBox
-	pop de
-	ld a, e
-	ld [wCurBox], a
-	call LoadBox
-	call SavedTheGame
-	call ResumeGameLogic
-	and a
-	ret
-.refused
-	pop de
-	ret
-
-Link_SaveGame: ; 14ab2
-	call AskOverwriteSaveFile
-	jr c, .refused
-	call PauseGameLogic
-	call _SavingDontTurnOffThePower
-	call ResumeGameLogic
-	and a
-
-.refused
-	ret
-; 14ac2
-
-MoveMonWOMail_SaveGame: ; 14ac2
-	call PauseGameLogic
-	push de
-	call SaveBox
-	pop de
-	ld a, e
-	ld [wCurBox], a
-	call LoadBox
-	call ResumeGameLogic
-	ret
-; 14ad5
-
-MoveMonWOMail_InsertMon_SaveGame: ; 14ad5
-	call PauseGameLogic
-	push de
-	call SaveBox
-	pop de
-	ld a, e
-	ld [wCurBox], a
-	ld a, $1
-	ld [wSaveFileExists], a
-	farcall StageRTCTimeForSave
-	farcall BackupMysteryGift
-	call ValidateSave
-	call SaveOptions
-	call SavePlayerData
-	call SavePokemonData
-	call SaveChecksum
-	call ValidateBackupSave
-	call SaveBackupOptions
-	call SaveBackupPlayerData
-	call SaveBackupPokemonData
-	call SaveBackupChecksum
-	farcall BackupPartyMonMail
-	farcall BackupMobileEventIndex
-	farcall SaveRTC
-	call LoadBox
-	call ResumeGameLogic
-	ld de, SFX_SAVE
-	call PlaySFX
-	ld c, 24
-	call DelayFrames
-	ret
-; 14b34
-
-StartMoveMonWOMail_SaveGame: ; 14b34
-	ld hl, Text_SaveOnMoveMonWOMail
-	call MenuTextBox
-	call YesNoBox
-	call ExitMenu
-	jr c, .refused
-	call AskOverwriteSaveFile
-	jr c, .refused
-	call PauseGameLogic
-	call _SavingDontTurnOffThePower
-	call ResumeGameLogic
-	and a
-	ret
-
-.refused
-	scf
-	ret
-; 14b54
-
-PauseGameLogic: ; 14b54
-	ld a, $1
-	ld [wGameLogicPaused], a
-	ret
-; 14b5a
-
-ResumeGameLogic: ; 14b5a
-	xor a
-	ld [wGameLogicPaused], a
-	ret
-; 14b5f
-
-
-AddHallOfFameEntry: ; 14b5f
-	ld a, BANK(sHallOfFame)
-	call GetSRAMBank
-	ld hl, sHallOfFame + HOF_LENGTH * (NUM_HOF_TEAMS - 1) - 1
-	ld de, sHallOfFame + HOF_LENGTH * NUM_HOF_TEAMS - 1
-	ld bc, HOF_LENGTH * (NUM_HOF_TEAMS - 1)
-.loop
-	ld a, [hld]
-	ld [de], a
-	dec de
-	dec bc
-	ld a, c
-	or b
-	jr nz, .loop
-	ld hl, wOverworldMap
-	ld de, sHallOfFame
-	ld bc, HOF_LENGTH
-	call CopyBytes
-	call CloseSRAM
-	ret
-; 14b85
-
-SaveGameData: ; 14b85
-	call SaveGameData_
-	ret
-; 14b89
-
-AskOverwriteSaveFile: ; 14b89
-	ld a, [wSaveFileExists]
-	and a
-	jr z, .erase
-	call CompareLoadedAndSavedPlayerID
-	jr z, .yoursavefile
-	ld hl, Text_AnotherSaveFile
-	call SaveTheGame_yesorno
-	jr nz, .refused
-	jr .erase
-
-.yoursavefile
-	ld hl, Text_AlreadyASaveFile
-	call SaveTheGame_yesorno
-	jr nz, .refused
-	jr .ok
-
-.erase
-	call ErasePreviousSave
-
-.ok
-	and a
-	ret
-
-.refused
-	scf
-	ret
-; 14baf
-
-SaveTheGame_yesorno: ; 14baf
-	ld b, BANK(Text_WouldYouLikeToSaveTheGame)
-	call MapTextbox
-	call LoadMenuTextBox
-	lb bc, 0, 7
-	call PlaceYesNoBox
-	ld a, [wMenuCursorY]
-	dec a
-	call CloseWindow
-	push af
-	call ret_d90
-	pop af
-	and a
-	ret
-; 14bcb
-
-CompareLoadedAndSavedPlayerID: ; 14bcb
-	ld a, BANK(sPlayerData)
-	call GetSRAMBank
-	ld hl, sPlayerData + (wPlayerID - wPlayerData)
-	ld a, [hli]
-	ld c, [hl]
-	ld b, a
-	call CloseSRAM
-	ld a, [wPlayerID]
-	cp b
-	ret nz
-	ld a, [wPlayerID + 1]
-	cp c
-	ret
-; 14be3
-
-_SavingDontTurnOffThePower: ; 14be3
-	call SavingDontTurnOffThePower
-SavedTheGame: ; 14be6
-	call SaveGameData_
-	; wait 32 frames
-	ld c, $20
-	call DelayFrames
-	; copy the original text speed setting to the stack
-	ld a, [wOptions]
-	push af
-	; set text speed super slow
-	ld a, 3
-	ld [wOptions], a
-	; <PLAYER> saved the game!
-	ld hl, Text_PlayerSavedTheGame
-	call PrintText
-	; restore the original text speed setting
-	pop af
-	ld [wOptions], a
-	ld de, SFX_SAVE
-	call WaitPlaySFX
-	call WaitSFX
-	; wait 30 frames
-	ld c, $1e
-	call DelayFrames
-	ret
-; 14c10
-
-
-SaveGameData_: ; 14c10
-	ld a, 1
-	ld [wSaveFileExists], a
-	farcall StageRTCTimeForSave
-	farcall BackupMysteryGift
-	call ValidateSave
-	call SaveOptions
-	call SavePlayerData
-	call SavePokemonData
-	call SaveBox
-	call SaveChecksum
-	call ValidateBackupSave
-	call SaveBackupOptions
-	call SaveBackupPlayerData
-	call SaveBackupPokemonData
-	call SaveBackupChecksum
-	call UpdateStackTop
-	farcall BackupPartyMonMail
-	farcall BackupMobileEventIndex
-	farcall SaveRTC
-	ld a, BANK(sBattleTowerChallengeState)
-	call GetSRAMBank
-	ld a, [sBattleTowerChallengeState]
-	cp BATTLETOWER_RECEIVED_REWARD
-	jr nz, .ok
-	xor a
-	ld [sBattleTowerChallengeState], a
-.ok
-	call CloseSRAM
-	ret
-; 14c6b
-
-UpdateStackTop: ; 14c6b
-; sStackTop appears to be unused.
-; It could have been used to debug stack overflow during saving.
-	call FindStackTop
-	ld a, BANK(sStackTop)
-	call GetSRAMBank
-	ld a, [sStackTop + 0]
-	ld e, a
-	ld a, [sStackTop + 1]
-	ld d, a
-	or e
-	jr z, .update
-	ld a, e
-	sub l
-	ld a, d
-	sbc h
-	jr c, .done
-
-.update
-	ld a, l
-	ld [sStackTop + 0], a
-	ld a, h
-	ld [sStackTop + 1], a
-
-.done
-	call CloseSRAM
-	ret
-; 14c90
-
-FindStackTop: ; 14c90
-; Find the furthest point that sp has traversed to.
-; This is distinct from the current value of sp.
-	ld hl, wStack - $ff
-.loop
-	ld a, [hl]
-	or a
-	ret nz
-	inc hl
-	jr .loop
-; 14c99
-
-SavingDontTurnOffThePower: ; 14c99
-	; Prevent joypad interrupts
-	xor a
-	ld [hJoypadReleased], a
-	ld [hJoypadPressed], a
-	ld [hJoypadSum], a
-	ld [hJoypadDown], a
-	; Save the text speed setting to the stack
-	ld a, [wOptions]
-	push af
-	; Set the text speed to super slow
-	ld a, $3
-	ld [wOptions], a
-	; SAVING... DON'T TURN OFF THE POWER.
-	ld hl, Text_SavingDontTurnOffThePower
-	call PrintText
-	; Restore the text speed setting
-	pop af
-	ld [wOptions], a
-	; Wait for 16 frames
-	ld c, $10
-	call DelayFrames
-	ret
-; 14cbb
-
-
-ErasePreviousSave: ; 14cbb
-	call EraseBoxes
-	call EraseHallOfFame
-	call EraseLinkBattleStats
-	call EraseMysteryGift
-	call SaveData
-	call EraseBattleTowerStatus
-	ld a, BANK(sStackTop)
-	call GetSRAMBank
-	xor a
-	ld [sStackTop + 0], a
-	ld [sStackTop + 1], a
-	call CloseSRAM
-	ld a, $1
-	ld [wSavedAtLeastOnce], a
-	ret
-; 14ce2
-
-EraseLinkBattleStats: ; 14ce2
-	ld a, BANK(sLinkBattleStats)
-	call GetSRAMBank
-	ld hl, sLinkBattleStats
-	ld bc, sLinkBattleStatsEnd - sLinkBattleStats
-	xor a
-	call ByteFill
-	jp CloseSRAM
-; 14cf4
-
-EraseMysteryGift: ; 14cf4
-	ld a, BANK(sBackupMysteryGiftItem)
-	call GetSRAMBank
-	ld hl, sBackupMysteryGiftItem
-	ld bc, sBackupMysteryGiftItemEnd - sBackupMysteryGiftItem
-	xor a
-	call ByteFill
-	jp CloseSRAM
-; 14d06
-
-EraseHallOfFame: ; 14d06
-	ld a, BANK(sHallOfFame)
-	call GetSRAMBank
-	ld hl, sHallOfFame
-	ld bc, sHallOfFameEnd - sHallOfFame
-	xor a
-	call ByteFill
-	jp CloseSRAM
-; 14d18
-
-Unreferenced_Function14d18: ; 14d18
-; copy .Data to SRA4:a007
-	ld a, 4 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
-	call GetSRAMBank
-	ld hl, .Data
-	ld de, $a007 ; address of MBC30 bank
-	ld bc, .DataEnd - .Data
-	call CopyBytes
-	jp CloseSRAM
-; 14d2c
-
-.Data: ; 14d2c
-	db $0d, $02, $00, $05, $00, $00
-	db $22, $02, $01, $05, $00, $00
-	db $03, $04, $05, $08, $03, $05
-	db $0e, $06, $03, $02, $00, $00
-	db $39, $07, $07, $04, $00, $05
-	db $04, $07, $01, $05, $00, $00
-	db $0f, $05, $14, $07, $05, $05
-	db $11, $0c, $0c, $06, $06, $04
-; 14d5c
-.DataEnd
-
-EraseBattleTowerStatus: ; 14d5c
-	ld a, BANK(sBattleTowerChallengeState)
-	call GetSRAMBank
-	xor a
-	ld [sBattleTowerChallengeState], a
-	jp CloseSRAM
-; 14d68
-
-SaveData: ; 14d68
-	call _SaveData
-	ret
-; 14d6c
-
-Unreferenced_Function14d6c: ; 14d6c
-	ld a, 4 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
-	call GetSRAMBank
-	ld a, [$a60b] ; address of MBC30 bank
-	ld b, $0
-	and a
-	jr z, .ok
-	ld b, $2
-
-.ok
-	ld a, b
-	ld [$a60b], a ; address of MBC30 bank
-	call CloseSRAM
-	ret
-; 14d83
-
-Unreferenced_Function14d83: ; 14d83
-	ld a, 4 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
-	call GetSRAMBank
-	xor a
-	ld [$a60c], a ; address of MBC30 bank
-	ld [$a60d], a ; address of MBC30 bank
-	call CloseSRAM
-	ret
-; 14d93
-
-Unreferenced_Function14d93: ; 14d93
-	ld a, 7 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
-	call GetSRAMBank
-	xor a
-	ld [$a000], a ; address of MBC30 bank
-	call CloseSRAM
-	ret
-; 14da0
-
-
-HallOfFame_InitSaveIfNeeded: ; 14da0
-	ld a, [wSavedAtLeastOnce]
-	and a
-	ret nz
-	call ErasePreviousSave
-	ret
-; 14da9
-
-ValidateSave: ; 14da9
-	ld a, BANK(sCheckValue1) ; BANK(sCheckValue2)
-	call GetSRAMBank
-	ld a, SAVE_CHECK_VALUE_1
-	ld [sCheckValue1], a
-	ld a, SAVE_CHECK_VALUE_2
-	ld [sCheckValue2], a
-	jp CloseSRAM
-; 14dbb
-
-SaveOptions: ; 14dbb
-	ld a, BANK(sOptions)
-	call GetSRAMBank
-	ld hl, wOptions
-	ld de, sOptions
-	ld bc, wOptionsEnd - wOptions
-	call CopyBytes
-	ld a, [wOptions]
-	and $ff ^ (1 << NO_TEXT_SCROLL)
-	ld [sOptions], a
-	jp CloseSRAM
-; 14dd7
-
-SavePlayerData: ; 14dd7
-	ld a, BANK(sPlayerData)
-	call GetSRAMBank
-	ld hl, wPlayerData
-	ld de, sPlayerData
-	ld bc, wPlayerDataEnd - wPlayerData
-	call CopyBytes
-	ld hl, wCurrMapData
-	ld de, sCurrMapData
-	ld bc, wCurrMapDataEnd - wCurrMapData
-	call CopyBytes
-	jp CloseSRAM
-; 14df7
-
-SavePokemonData: ; 14df7
-	ld a, BANK(sPokemonData)
-	call GetSRAMBank
-	ld hl, wPokemonData
-	ld de, sPokemonData
-	ld bc, wPokemonDataEnd - wPokemonData
-	call CopyBytes
-	call CloseSRAM
-	ret
-; 14e0c
-
-SaveBox: ; 14e0c
-	call GetBoxAddress
-	call SaveBoxAddress
-	ret
-; 14e13
-
-SaveChecksum: ; 14e13
-	ld hl, sGameData
-	ld bc, sGameDataEnd - sGameData
-	ld a, BANK(sGameData)
-	call GetSRAMBank
-	call Checksum
-	ld a, e
-	ld [sChecksum + 0], a
-	ld a, d
-	ld [sChecksum + 1], a
-	call CloseSRAM
-	ret
-; 14e2d
-
-ValidateBackupSave: ; 14e2d
-	ld a, BANK(sBackupCheckValue1) ; BANK(sBackupCheckValue2)
-	call GetSRAMBank
-	ld a, SAVE_CHECK_VALUE_1
-	ld [sBackupCheckValue1], a
-	ld a, SAVE_CHECK_VALUE_2
-	ld [sBackupCheckValue2], a
-	call CloseSRAM
-	ret
-; 14e40
-
-SaveBackupOptions: ; 14e40
-	ld a, BANK(sBackupOptions)
-	call GetSRAMBank
-	ld hl, wOptions
-	ld de, sBackupOptions
-	ld bc, wOptionsEnd - wOptions
-	call CopyBytes
-	call CloseSRAM
-	ret
-; 14e55
-
-SaveBackupPlayerData: ; 14e55
-	ld a, BANK(sBackupPlayerData)
-	call GetSRAMBank
-	ld hl, wPlayerData
-	ld de, sBackupPlayerData
-	ld bc, wPlayerDataEnd - wPlayerData
-	call CopyBytes
-	ld hl, wCurrMapData
-	ld de, sBackupCurrMapData
-	ld bc, wCurrMapDataEnd - wCurrMapData
-	call CopyBytes
-	call CloseSRAM
-	ret
-; 14e76
-
-SaveBackupPokemonData: ; 14e76
-	ld a, BANK(sBackupPokemonData)
-	call GetSRAMBank
-	ld hl, wPokemonData
-	ld de, sBackupPokemonData
-	ld bc, wPokemonDataEnd - wPokemonData
-	call CopyBytes
-	call CloseSRAM
-	ret
-; 14e8b
-
-SaveBackupChecksum: ; 14e8b
-	ld hl, sBackupGameData
-	ld bc, sBackupGameDataEnd - sBackupGameData
-	ld a, BANK(sBackupGameData)
-	call GetSRAMBank
-	call Checksum
-	ld a, e
-	ld [sBackupChecksum + 0], a
-	ld a, d
-	ld [sBackupChecksum + 1], a
-	call CloseSRAM
-	ret
-; 14ea5
-
-
-TryLoadSaveFile: ; 14ea5 (5:4ea5)
-	call VerifyChecksum
-	jr nz, .backup
-	call LoadPlayerData
-	call LoadPokemonData
-	call LoadBox
-	farcall RestorePartyMonMail
-	farcall RestoreMobileEventIndex
-	farcall RestoreMysteryGift
-	call ValidateBackupSave
-	call SaveBackupOptions
-	call SaveBackupPlayerData
-	call SaveBackupPokemonData
-	call SaveBackupChecksum
-	and a
-	ret
-
-.backup
-	call VerifyBackupChecksum
-	jr nz, .corrupt
-	call LoadBackupPlayerData
-	call LoadBackupPokemonData
-	call LoadBox
-	farcall RestorePartyMonMail
-	farcall RestoreMobileEventIndex
-	farcall RestoreMysteryGift
-	call ValidateSave
-	call SaveOptions
-	call SavePlayerData
-	call SavePokemonData
-	call SaveChecksum
-	and a
-	ret
-
-.corrupt
-	ld a, [wOptions]
-	push af
-	set NO_TEXT_SCROLL, a
-	ld [wOptions], a
-	ld hl, Text_SaveFileCorrupted
-	call PrintText
-	pop af
-	ld [wOptions], a
-	scf
-	ret
-
-
-TryLoadSaveData: ; 14f1c
-	xor a
-	ld [wSaveFileExists], a
-	call CheckPrimarySaveFile
-	ld a, [wSaveFileExists]
-	and a
-	jr z, .backup
-
-	ld a, BANK(sPlayerData)
-	call GetSRAMBank
-	ld hl, sPlayerData + wStartDay - wPlayerData
-	ld de, wStartDay
-	ld bc, 8
-	call CopyBytes
-	ld hl, sPlayerData + wStatusFlags - wPlayerData
-	ld de, wStatusFlags
-	ld a, [hl]
-	ld [de], a
-	call CloseSRAM
-	ret
-
-.backup
-	call CheckBackupSaveFile
-	ld a, [wSaveFileExists]
-	and a
-	jr z, .corrupt
-
-	ld a, BANK(sBackupPlayerData)
-	call GetSRAMBank
-	ld hl, sBackupPlayerData + wStartDay - wPlayerData
-	ld de, wStartDay
-	ld bc, 8
-	call CopyBytes
-	ld hl, sBackupPlayerData + wStatusFlags - wPlayerData
-	ld de, wStatusFlags
-	ld a, [hl]
-	ld [de], a
-	call CloseSRAM
-	ret
-
-.corrupt
-	ld hl, DefaultOptions
-	ld de, wOptions
-	ld bc, wOptionsEnd - wOptions
-	call CopyBytes
-	call PanicResetClock
-	ret
-; 14f7c
-
-
-INCLUDE "data/default_options.asm"
-
-
-CheckPrimarySaveFile: ; 14f84
-	ld a, BANK(sCheckValue1) ; BANK(sCheckValue2)
-	call GetSRAMBank
-	ld a, [sCheckValue1]
-	cp SAVE_CHECK_VALUE_1
-	jr nz, .nope
-	ld a, [sCheckValue2]
-	cp SAVE_CHECK_VALUE_2
-	jr nz, .nope
-	ld hl, sOptions
-	ld de, wOptions
-	ld bc, wOptionsEnd - wOptions
-	call CopyBytes
-	call CloseSRAM
-	ld a, $1
-	ld [wSaveFileExists], a
-
-.nope
-	call CloseSRAM
-	ret
-; 14faf
-
-CheckBackupSaveFile: ; 14faf
-	ld a, BANK(sBackupCheckValue1) ; BANK(sBackupCheckValue2)
-	call GetSRAMBank
-	ld a, [sBackupCheckValue1]
-	cp SAVE_CHECK_VALUE_1
-	jr nz, .nope
-	ld a, [sBackupCheckValue2]
-	cp SAVE_CHECK_VALUE_2
-	jr nz, .nope
-	ld hl, sBackupOptions
-	ld de, wOptions
-	ld bc, wOptionsEnd - wOptions
-	call CopyBytes
-	ld a, $2
-	ld [wSaveFileExists], a
-
-.nope
-	call CloseSRAM
-	ret
-; 14fd7
-
-
-LoadPlayerData: ; 14fd7 (5:4fd7)
-	ld a, BANK(sPlayerData)
-	call GetSRAMBank
-	ld hl, sPlayerData
-	ld de, wPlayerData
-	ld bc, wPlayerDataEnd - wPlayerData
-	call CopyBytes
-	ld hl, sCurrMapData
-	ld de, wCurrMapData
-	ld bc, wCurrMapDataEnd - wCurrMapData
-	call CopyBytes
-	call CloseSRAM
-	ld a, BANK(sBattleTowerChallengeState)
-	call GetSRAMBank
-	ld a, [sBattleTowerChallengeState]
-	cp BATTLETOWER_RECEIVED_REWARD
-	jr nz, .not_4
-	ld a, BATTLETOWER_WON_CHALLENGE
-	ld [sBattleTowerChallengeState], a
-.not_4
-	call CloseSRAM
-	ret
-
-LoadPokemonData: ; 1500c
-	ld a, BANK(sPokemonData)
-	call GetSRAMBank
-	ld hl, sPokemonData
-	ld de, wPokemonData
-	ld bc, wPokemonDataEnd - wPokemonData
-	call CopyBytes
-	call CloseSRAM
-	ret
-; 15021
-
-LoadBox: ; 15021 (5:5021)
-	call GetBoxAddress
-	call LoadBoxAddress
-	ret
-
-VerifyChecksum: ; 15028 (5:5028)
-	ld hl, sGameData
-	ld bc, sGameDataEnd - sGameData
-	ld a, BANK(sGameData)
-	call GetSRAMBank
-	call Checksum
-	ld a, [sChecksum + 0]
-	cp e
-	jr nz, .fail
-	ld a, [sChecksum + 1]
-	cp d
-.fail
-	push af
-	call CloseSRAM
-	pop af
-	ret
-
-LoadBackupPlayerData: ; 15046 (5:5046)
-	ld a, BANK(sBackupPlayerData)
-	call GetSRAMBank
-	ld hl, sBackupPlayerData
-	ld de, wPlayerData
-	ld bc, wPlayerDataEnd - wPlayerData
-	call CopyBytes
-	ld hl, sBackupCurrMapData
-	ld de, wCurrMapData
-	ld bc, wCurrMapDataEnd - wCurrMapData
-	call CopyBytes
-	call CloseSRAM
-	ret
-
-LoadBackupPokemonData: ; 15067 (5:5067)
-	ld a, BANK(sBackupPokemonData)
-	call GetSRAMBank
-	ld hl, sBackupPokemonData
-	ld de, wPokemonData
-	ld bc, wPokemonDataEnd - wPokemonData
-	call CopyBytes
-	call CloseSRAM
-	ret
-
-VerifyBackupChecksum: ; 1507c (5:507c)
-	ld hl, sBackupGameData
-	ld bc, sBackupGameDataEnd - sBackupGameData
-	ld a, BANK(sBackupGameData)
-	call GetSRAMBank
-	call Checksum
-	ld a, [sBackupChecksum + 0]
-	cp e
-	jr nz, .fail
-	ld a, [sBackupChecksum + 1]
-	cp d
-.fail
-	push af
-	call CloseSRAM
-	pop af
-	ret
-
-
-_SaveData: ; 1509a
-	; This is called within two scenarios:
-	;   a) ErasePreviousSave (the process of erasing the save from a previous game file)
-	;   b) unused mobile functionality
-	; It is not part of a regular save.
-
-	ld a, BANK(sCrystalData)
-	call GetSRAMBank
-	ld hl, wCrystalData
-	ld de, sCrystalData
-	ld bc, wCrystalDataEnd - wCrystalData
-	call CopyBytes
-
-	; This block originally had some mobile functionality, but since we're still in
-	; BANK(sCrystalData), it instead overwrites the sixteen wEventFlags starting at 1:a603 with
-	; garbage from wd479. This isn't an issue, since ErasePreviousSave is followed by a regular
-	; save that unwrites the garbage.
-
-	ld hl, wd479
-	ld a, [hli]
-	ld [$a60e + 0], a
-	ld a, [hli]
-	ld [$a60e + 1], a
-
-	jp CloseSRAM
-
-
-_LoadData: ; 150b9
-	ld a, BANK(sCrystalData)
-	call GetSRAMBank
-	ld hl, sCrystalData
-	ld de, wCrystalData
-	ld bc, wCrystalDataEnd - wCrystalData
-	call CopyBytes
-
-	; This block originally had some mobile functionality to mirror _SaveData above, but instead it
-	; (harmlessly) writes the aforementioned wEventFlags to the unused wd479.
-
-	ld hl, wd479
-	ld a, [$a60e + 0]
-	ld [hli], a
-	ld a, [$a60e + 1]
-	ld [hli], a
-
-	jp CloseSRAM
-
-
-GetBoxAddress: ; 150d8
-	ld a, [wCurBox]
-	cp NUM_BOXES
-	jr c, .ok
-	xor a
-	ld [wCurBox], a
-
-.ok
-	ld e, a
-	ld d, 0
-	ld hl, BoxAddresses
-rept 5
-	add hl, de
-endr
-	ld a, [hli]
-	push af
-	ld a, [hli]
-	ld e, a
-	ld a, [hli]
-	ld d, a
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	pop af
-	ret
-; 150f9
-
-SaveBoxAddress: ; 150f9
-; Save box via wMisc.
-; We do this in three steps because the size of wMisc is less than
-; the size of sBox.
-	push hl
-; Load the first part of the active box.
-	push af
-	push de
-	ld a, BANK(sBox)
-	call GetSRAMBank
-	ld hl, sBox
-	ld de, wMisc
-	ld bc, (wMiscEnd - wMisc)
-	call CopyBytes
-	call CloseSRAM
-	pop de
-	pop af
-; Save it to the target box.
-	push af
-	push de
-	call GetSRAMBank
-	ld hl, wMisc
-	ld bc, (wMiscEnd - wMisc)
-	call CopyBytes
-	call CloseSRAM
-
-; Load the second part of the active box.
-	ld a, BANK(sBox)
-	call GetSRAMBank
-	ld hl, sBox + (wMiscEnd - wMisc)
-	ld de, wMisc
-	ld bc, (wMiscEnd - wMisc)
-	call CopyBytes
-	call CloseSRAM
-	pop de
-	pop af
-
-	ld hl, (wMiscEnd - wMisc)
-	add hl, de
-	ld e, l
-	ld d, h
-; Save it to the next part of the target box.
-	push af
-	push de
-	call GetSRAMBank
-	ld hl, wMisc
-	ld bc, (wMiscEnd - wMisc)
-	call CopyBytes
-	call CloseSRAM
-
-; Load the third and final part of the active box.
-	ld a, BANK(sBox)
-	call GetSRAMBank
-	ld hl, sBox + (wMiscEnd - wMisc) * 2
-	ld de, wMisc
-	ld bc, sBoxEnd - (sBox + (wMiscEnd - wMisc) * 2) ; $8e
-	call CopyBytes
-	call CloseSRAM
-	pop de
-	pop af
-
-	ld hl, (wMiscEnd - wMisc)
-	add hl, de
-	ld e, l
-	ld d, h
-; Save it to the final part of the target box.
-	call GetSRAMBank
-	ld hl, wMisc
-	ld bc, sBoxEnd - (sBox + (wMiscEnd - wMisc) * 2) ; $8e
-	call CopyBytes
-	call CloseSRAM
-
-	pop hl
-	ret
-; 1517d
-
-
-LoadBoxAddress: ; 1517d (5:517d)
-; Load box via wMisc.
-; We do this in three steps because the size of wMisc is less than
-; the size of sBox.
-	push hl
-	ld l, e
-	ld h, d
-; Load part 1
-	push af
-	push hl
-	call GetSRAMBank
-	ld de, wMisc
-	ld bc, (wMiscEnd - wMisc)
-	call CopyBytes
-	call CloseSRAM
-	ld a, BANK(sBox)
-	call GetSRAMBank
-	ld hl, wMisc
-	ld de, sBox
-	ld bc, (wMiscEnd - wMisc)
-	call CopyBytes
-	call CloseSRAM
-	pop hl
-	pop af
-
-	ld de, (wMiscEnd - wMisc)
-	add hl, de
-; Load part 2
-	push af
-	push hl
-	call GetSRAMBank
-	ld de, wMisc
-	ld bc, (wMiscEnd - wMisc)
-	call CopyBytes
-	call CloseSRAM
-	ld a, BANK(sBox)
-	call GetSRAMBank
-	ld hl, wMisc
-	ld de, sBox + (wMiscEnd - wMisc)
-	ld bc, (wMiscEnd - wMisc)
-	call CopyBytes
-	call CloseSRAM
-	pop hl
-	pop af
-; Load part 3
-	ld de, (wMiscEnd - wMisc)
-	add hl, de
-	call GetSRAMBank
-	ld de, wMisc
-	ld bc, sBoxEnd - (sBox + (wMiscEnd - wMisc) * 2) ; $8e
-	call CopyBytes
-	call CloseSRAM
-	ld a, BANK(sBox)
-	call GetSRAMBank
-	ld hl, wMisc
-	ld de, sBox + (wMiscEnd - wMisc) * 2
-	ld bc, sBoxEnd - (sBox + (wMiscEnd - wMisc) * 2) ; $8e
-	call CopyBytes
-	call CloseSRAM
-
-	pop hl
-	ret
-
-
-EraseBoxes: ; 151fb
-	ld hl, BoxAddresses
-	ld c, NUM_BOXES
-.next
-	push bc
-	ld a, [hli]
-	call GetSRAMBank
-	ld a, [hli]
-	ld e, a
-	ld a, [hli]
-	ld d, a
-	xor a
-	ld [de], a
-	inc de
-	ld a, -1
-	ld [de], a
-	inc de
-	ld bc, sBoxEnd - (sBox + 2)
-.clear
-	xor a
-	ld [de], a
-	inc de
-	dec bc
-	ld a, b
-	or c
-	jr nz, .clear
-	ld a, [hli]
-	ld e, a
-	ld a, [hli]
-	ld d, a
-	ld a, -1
-	ld [de], a
-	inc de
-	xor a
-	ld [de], a
-	call CloseSRAM
-	pop bc
-	dec c
-	jr nz, .next
-	ret
-; 1522d
-
-BoxAddresses: ; 1522d
-; dbww bank, address, address
-	dbww BANK(sBox1),  sBox1,  sBox1End
-	dbww BANK(sBox2),  sBox2,  sBox2End
-	dbww BANK(sBox3),  sBox3,  sBox3End
-	dbww BANK(sBox4),  sBox4,  sBox4End
-	dbww BANK(sBox5),  sBox5,  sBox5End
-	dbww BANK(sBox6),  sBox6,  sBox6End
-	dbww BANK(sBox7),  sBox7,  sBox7End
-	dbww BANK(sBox8),  sBox8,  sBox8End
-	dbww BANK(sBox9),  sBox9,  sBox9End
-	dbww BANK(sBox10), sBox10, sBox10End
-	dbww BANK(sBox11), sBox11, sBox11End
-	dbww BANK(sBox12), sBox12, sBox12End
-	dbww BANK(sBox13), sBox13, sBox13End
-	dbww BANK(sBox14), sBox14, sBox14End
-; 15273
-
-
-Checksum: ; 15273
-	ld de, 0
-.loop
-	ld a, [hli]
-	add e
-	ld e, a
-	ld a, 0
-	adc d
-	ld d, a
-	dec bc
-	ld a, b
-	or c
-	jr nz, .loop
-	ret
-; 15283
-
-
-Text_WouldYouLikeToSaveTheGame: ; 0x15283
-	; Would you like to save the game?
-	text_jump UnknownText_0x1c454b
-	db "@"
-; 0x15288
-
-Text_SavingDontTurnOffThePower: ; 0x15288
-	; SAVING… DON'T TURN OFF THE POWER.
-	text_jump UnknownText_0x1c456d
-	db "@"
-; 0x1528d
-
-Text_PlayerSavedTheGame: ; 0x1528d
-	; saved the game.
-	text_jump UnknownText_0x1c4590
-	db "@"
-; 0x15292
-
-Text_AlreadyASaveFile: ; 0x15292
-	; There is already a save file. Is it OK to overwrite?
-	text_jump UnknownText_0x1c45a3
-	db "@"
-; 0x15297
-
-Text_AnotherSaveFile: ; 0x15297
-	; There is another save file. Is it OK to overwrite?
-	text_jump UnknownText_0x1c45d9
-	db "@"
-; 0x1529c
-
-Text_SaveFileCorrupted: ; 0x1529c
-	; The save file is corrupted!
-	text_jump UnknownText_0x1c460d
-	db "@"
-; 0x152a1
-
-Text_SaveOnBoxSwitch: ; 0x152a1
-	; When you change a #MON BOX, data will be saved. OK?
-	text_jump UnknownText_0x1c462a
-	db "@"
-; 0x152a6
-
-Text_SaveOnMoveMonWOMail: ; 0x152a6
-	; Each time you move a #MON, data will be saved. OK?
-	text_jump UnknownText_0x1c465f
-	db "@"
-; 0x152ab
--- /dev/null
+++ b/engine/tilesets/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/tilesets/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/tilesets/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/tilesets/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/tilesets/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
--- a/engine/title/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/title/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/title/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/title/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"
--- a/engine/title/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/main.asm
+++ b/main.asm
@@ -3,13 +3,13 @@
 
 SECTION "bank1", ROMX
 
-INCLUDE "engine/routines/placewaitingtext.asm"
-INCLUDE "engine/routines/loadpushoam.asm"
+INCLUDE "engine/link/placewaitingtext.asm"
+INCLUDE "engine/gfx/loadpushoam.asm"
 INCLUDE "engine/overworld/map_objects.asm"
 INCLUDE "engine/menus/intro_menu.asm"
 INCLUDE "engine/overworld/init_map.asm"
 INCLUDE "engine/pokemon/learn.asm"
-INCLUDE "engine/routines/checknickerrors.asm"
+INCLUDE "engine/pokemon/checknickerrors.asm"
 INCLUDE "engine/routines/math.asm"
 INCLUDE "data/items/attributes.asm"
 INCLUDE "engine/overworld/npc_movement.asm"
@@ -21,13 +21,13 @@
 
 INCLUDE "engine/overworld/player_object.asm"
 INCLUDE "engine/routines/sine.asm"
-INCLUDE "engine/predef.asm"
+INCLUDE "engine/routines/predef.asm"
 INCLUDE "engine/gfx/color.asm"
 
 
 SECTION "bank3", ROMX
 
-INCLUDE "engine/routines/checktime.asm"
+INCLUDE "engine/events/checktime.asm"
 INCLUDE "engine/events/specials.asm"
 INCLUDE "engine/routines/printnum.asm"
 INCLUDE "engine/pokemon/health.asm"
@@ -48,7 +48,7 @@
 
 INCLUDE "engine/items/pack.asm"
 INCLUDE "engine/overworld/time.asm"
-INCLUDE "engine/items/tmhm.asm"
+INCLUDE "engine/items/tmhm2.asm"
 INCLUDE "engine/menus/naming_screen.asm"
 INCLUDE "engine/events/misc_scripts.asm"
 INCLUDE "engine/events/heal_machine_anim.asm"
@@ -64,7 +64,7 @@
 INCLUDE "engine/events/bug_contest/judging.asm"
 INCLUDE "engine/events/pokerus/apply_pokerus_tick.asm"
 INCLUDE "engine/events/bug_contest/contest_2.asm"
-INCLUDE "engine/routines/correcterrorsinplayerparty.asm"
+INCLUDE "engine/pokemon/correcterrorsinplayerparty.asm"
 INCLUDE "engine/routines/getsquareroot.asm"
 
 
@@ -73,12 +73,12 @@
 INCLUDE "engine/rtc/rtc.asm"
 INCLUDE "engine/overworld/overworld.asm"
 INCLUDE "engine/overworld/tile_events.asm"
-INCLUDE "engine/save.asm"
+INCLUDE "engine/menus/save.asm"
 INCLUDE "engine/overworld/spawn_points.asm"
 INCLUDE "engine/overworld/map_setup.asm"
 INCLUDE "engine/events/pokecenter_pc.asm"
 INCLUDE "engine/items/mart.asm"
-INCLUDE "engine/money.asm"
+INCLUDE "engine/events/money.asm"
 INCLUDE "data/items/marts.asm"
 INCLUDE "engine/events/mom.asm"
 INCLUDE "engine/events/daycare.asm"
@@ -90,7 +90,7 @@
 
 SECTION "Roofs", ROMX
 
-INCLUDE "engine/gfx/mapgroup_roofs.asm"
+INCLUDE "engine/tilesets/mapgroup_roofs.asm"
 
 
 SECTION "Clock Reset", ROMX
@@ -144,7 +144,7 @@
 INCLUDE "engine/battle/ai/redundant.asm"
 INCLUDE "engine/events/move_deleter.asm"
 INCLUDE "engine/link/mystery_gift_2.asm"
-INCLUDE "engine/pokemon/tmhm.asm"
+INCLUDE "engine/items/tmhm.asm"
 INCLUDE "data/moves/descriptions.asm"
 INCLUDE "engine/events/pokerus/pokerus.asm"
 INCLUDE "engine/battle/start_battle.asm"
@@ -205,15 +205,15 @@
 
 SECTION "bank13", ROMX
 
-INCLUDE "engine/gfx/map_palettes.asm"
+INCLUDE "engine/tilesets/map_palettes.asm"
 INCLUDE "gfx/tileset_palette_maps.asm"
 INCLUDE "data/collision_permissions.asm"
 INCLUDE "engine/routines/emptyallsrambanks.asm"
-INCLUDE "engine/routines/savemenu_copytilemapatonce.asm"
-INCLUDE "engine/routines/checksave.asm"
+INCLUDE "engine/menus/savemenu_copytilemapatonce.asm"
+INCLUDE "engine/events/checksave.asm"
 INCLUDE "data/maps/scenes.asm"
 INCLUDE "engine/overworld/loadmappart.asm"
-INCLUDE "engine/routines/phonering_copytilemapatonce.asm"
+INCLUDE "engine/phone/phonering_copytilemapatonce.asm"
 
 Shrink1Pic: ; 4d249
 INCBIN "gfx/new_game/shrink1.2bpp.lz"
@@ -232,13 +232,13 @@
 INCLUDE "engine/pokemon/search2.asm"
 INCLUDE "engine/pokemon/stats_screen.asm"
 INCLUDE "engine/events/catch_tutorial.asm"
-INCLUDE "engine/gfx/evolution_animation.asm"
-INCLUDE "engine/title/init_hof_credits.asm"
+INCLUDE "engine/movie/evolution_animation.asm"
+INCLUDE "engine/movie/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/gfx/gbc_only.asm"
+INCLUDE "engine/movie/gbc_only.asm"
 INCLUDE "engine/events/poke_seer.asm"
 
 
@@ -277,10 +277,10 @@
 SECTION "bank20", ROMX
 
 INCLUDE "engine/overworld/player_movement.asm"
-INCLUDE "engine/engine_flags.asm"
+INCLUDE "engine/events/engine_flags.asm"
 INCLUDE "engine/overworld/variables.asm"
 INCLUDE "data/text/battle.asm"
-INCLUDE "engine/debug.asm"
+INCLUDE "engine/menus/debug.asm"
 
 
 SECTION "bank21", ROMX
@@ -304,7 +304,7 @@
 
 SECTION "bank23", ROMX
 
-INCLUDE "engine/gfx/timeofdaypals.asm"
+INCLUDE "engine/tilesets/timeofdaypals.asm"
 INCLUDE "engine/battle/battle_transition.asm"
 INCLUDE "engine/events/field_moves.asm"
 INCLUDE "engine/events/magnet_train.asm"
@@ -442,7 +442,7 @@
 INCBIN "gfx/splash/copyright.2bpp"
 
 INCLUDE "engine/menus/options_menu.asm"
-INCLUDE "engine/title/crystal_intro.asm"
+INCLUDE "engine/movie/crystal_intro.asm"
 
 
 SECTION "bank3E", ROMX
@@ -450,7 +450,7 @@
 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/events/playslowcry.asm"
 INCLUDE "engine/pokedex/newpokedexentry.asm"
 INCLUDE "engine/link/time_capsule_2.asm"
 INCLUDE "engine/pokedex/unown_dex.asm"
@@ -461,7 +461,7 @@
 
 SECTION "bank3F", ROMX
 
-INCLUDE "engine/gfx/tileset_anims.asm"
+INCLUDE "engine/tilesets/tileset_anims.asm"
 INCLUDE "engine/events/npc_trade.asm"
 INCLUDE "engine/events/mom_phone.asm"
 
@@ -471,7 +471,7 @@
 
 SECTION "bank41", ROMX
 
-INCLUDE "engine/dma_transfer.asm"
+INCLUDE "engine/gfx/dma_transfer.asm"
 INCLUDE "gfx/emotes.asm"
 INCLUDE "engine/overworld/warp_connection.asm"
 INCLUDE "engine/link/mystery_gift.asm"
@@ -493,8 +493,8 @@
 
 SECTION "Title", ROMX
 
-INCLUDE "engine/title/unused_title.asm"
-INCLUDE "engine/title/title.asm"
+INCLUDE "engine/movie/unused_title.asm"
+INCLUDE "engine/movie/title.asm"
 
 
 INCLUDE "mobile/mobile_45.asm"
@@ -586,7 +586,7 @@
 INCLUDE "engine/events/diploma.asm"
 INCLUDE "engine/pokedex/pokedex_3.asm"
 INCLUDE "engine/events/catch_tutorial_input.asm"
-INCLUDE "engine/routines/townmap_convertlinebreakcharacters.asm"
+INCLUDE "engine/pokegear/townmap_convertlinebreakcharacters.asm"
 
 PokegearGFX: ; 1de2e4
 INCBIN "gfx/pokegear/pokegear.2bpp.lz"