shithub: pokecrystal

Download patch

ref: 1038ebca5e2638ecbce1052c1dad7474372a7fd5
parent: 606817f18b67a7d033adad31cbbea19d2e05e98e
author: Remy Oukaour <[email protected]>
date: Fri Dec 15 15:10:54 EST 2017

Move more contiguous related code blocks from main.asm to engine/ and events/

--- a/battle/moves/move_descriptions.asm
+++ b/battle/moves/move_descriptions.asm
@@ -1,4 +1,5 @@
-; MoveDescriptions: ; 2cb52
+MoveDescriptions:: ; 2cb52
+; entries correspond to move ids (see constants/move_constants.asm)
 	dw PoundDescription
 	dw KarateChopDescription
 	dw DoubleslapDescription
--- a/battle/moves/move_effects.asm
+++ b/battle/moves/move_effects.asm
@@ -1,3 +1,5 @@
+MoveEffects: ; 2732e
+
 NormalHit:
 	checkobedience
 	usedmovetext
--- a/battle/moves/move_effects_pointers.asm
+++ b/battle/moves/move_effects_pointers.asm
@@ -1,3 +1,4 @@
+MoveEffectsPointers: ; 271f4
 ; entries correspond to EFFECT_* constants
 	dw NormalHit
 	dw DoSleep
--- a/engine/battle_start.asm
+++ /dev/null
@@ -1,864 +1,0 @@
-Predef_StartBattle: ; 8c20f
-	call .InitGFX
-	ld a, [rBGP]
-	ld [wBGP], a
-	ld a, [rOBP0]
-	ld [wOBP0], a
-	ld a, [rOBP1]
-	ld [wOBP1], a
-	call DelayFrame
-	ld hl, hVBlank
-	ld a, [hl]
-	push af
-	ld [hl], $1
-
-.loop
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .done
-	call FlashyTransitionToBattle
-	call DelayFrame
-	jr .loop
-
-.done
-	ld a, [rSVBK]
-	push af
-	ld a, $5
-	ld [rSVBK], a
-
-	ld hl, UnknBGPals
-	ld bc, 8 palettes
-	xor a
-	call ByteFill
-
-	pop af
-	ld [rSVBK], a
-
-	ld a, %11111111
-	ld [wBGP], a
-	call DmgToCgbBGPals
-	call DelayFrame
-	xor a
-	ld [hLCDCPointer], a
-	ld [hLYOverrideStart], a
-	ld [hLYOverrideEnd], a
-	ld [hSCY], a
-
-	ld a, $1
-	ld [rSVBK], a
-	pop af
-	ld [hVBlank], a
-	call DelayFrame
-	ret
-; 8c26d
-
-.InitGFX: ; 8c26d
-	ld a, [wLinkMode]
-	cp LINK_MOBILE
-	jr z, .mobile
-	callba ReanchorBGMap_NoOAMUpdate
-	call UpdateSprites
-	call DelayFrame
-	call .NonMobile_LoadPokeballTiles
-	call BattleStart_LoadEDTile
-	jr .resume
-
-.mobile
-	call LoadTrainerBattlePokeballTiles
-
-.resume
-	ld a, SCREEN_HEIGHT_PX
-	ld [hWY], a
-	call DelayFrame
-	xor a
-	ld [hBGMapMode], a
-	ld hl, wJumptableIndex
-	xor a
-	ld [hli], a
-	ld [hli], a
-	ld [hl], a
-	call WipeLYOverrides
-	ret
-; 8c2a0
-
-.NonMobile_LoadPokeballTiles: ; 8c2a0
-	call LoadTrainerBattlePokeballTiles
-	hlbgcoord 0, 0
-	call ConvertTrainerBattlePokeballTilesTo2bpp
-	ret
-; 8c2aa
-
-LoadTrainerBattlePokeballTiles:
-; Load the tiles used in the Pokeball Graphic that fills the screen
-; at the start of every Trainer battle.
-	ld de, TrainerBattlePokeballTiles
-	ld hl, VTiles1 tile $7e
-	ld b, BANK(TrainerBattlePokeballTiles)
-	ld c, 2
-	call Request2bpp
-
-	ld a, [rVBK]
-	push af
-	ld a, $1
-	ld [rVBK], a
-
-	ld de, TrainerBattlePokeballTiles
-	ld hl, VTiles4 tile $7e
-	ld b, BANK(TrainerBattlePokeballTiles)
-	ld c, 2
-	call Request2bpp
-
-	pop af
-	ld [rVBK], a
-	ret
-; 8c2cf
-
-ConvertTrainerBattlePokeballTilesTo2bpp: ; 8c2cf
-	ld a, [rSVBK]
-	push af
-	ld a, $6
-	ld [rSVBK], a
-	push hl
-	ld hl, wDecompressScratch
-	ld bc, $28 tiles
-
-.loop
-	ld [hl], -1
-	inc hl
-	dec bc
-	ld a, c
-	or b
-	jr nz, .loop
-
-	pop hl
-	ld de, wDecompressScratch
-	ld b, BANK(ConvertTrainerBattlePokeballTilesTo2bpp) ; BANK(@)
-	ld c, $28
-	call Request2bpp
-	pop af
-	ld [rSVBK], a
-	ret
-; 8c2f4
-
-TrainerBattlePokeballTiles: ; 8c2f4
-INCBIN "gfx/overworld/trainer_battle_pokeball_tiles.2bpp"
-
-
-FlashyTransitionToBattle: ; 8c314
-	jumptable .dw, wJumptableIndex
-; 8c323
-
-.dw ; 8c323 (23:4323)
-	dw StartTrainerBattle_DetermineWhichAnimation ; 00
-
-	; Animation 1: cave
-	dw StartTrainerBattle_LoadPokeBallGraphics ; 01
-	dw StartTrainerBattle_SetUpBGMap ; 02
-	dw StartTrainerBattle_Flash ; 03
-	dw StartTrainerBattle_Flash ; 04
-	dw StartTrainerBattle_Flash ; 05
-	dw StartTrainerBattle_NextScene ; 06
-	dw StartTrainerBattle_SetUpForWavyOutro ; 07
-	dw StartTrainerBattle_SineWave ; 08
-
-	; Animation 2: cave, stronger
-	dw StartTrainerBattle_LoadPokeBallGraphics ; 09
-	dw StartTrainerBattle_SetUpBGMap ; 0a
-	dw StartTrainerBattle_Flash ; 0b
-	dw StartTrainerBattle_Flash ; 0c
-	dw StartTrainerBattle_Flash ; 0d
-	dw StartTrainerBattle_NextScene ; 0e
-	; There is no setup for this one
-	dw StartTrainerBattle_ZoomToBlack ; 0f
-
-	; Animation 3: no cave
-	dw StartTrainerBattle_LoadPokeBallGraphics ; 10
-	dw StartTrainerBattle_SetUpBGMap ; 11
-	dw StartTrainerBattle_Flash ; 12
-	dw StartTrainerBattle_Flash ; 13
-	dw StartTrainerBattle_Flash ; 14
-	dw StartTrainerBattle_NextScene ; 15
-	dw StartTrainerBattle_SetUpForSpinOutro ; 16
-	dw StartTrainerBattle_SpinToBlack ; 17
-
-	; Animation 4: no cave, stronger
-	dw StartTrainerBattle_LoadPokeBallGraphics ; 18
-	dw StartTrainerBattle_SetUpBGMap ; 19
-	dw StartTrainerBattle_Flash ; 1a
-	dw StartTrainerBattle_Flash ; 1b
-	dw StartTrainerBattle_Flash ; 1c
-	dw StartTrainerBattle_NextScene ; 1d
-	dw StartTrainerBattle_SetUpForRandomScatterOutro ; 1e
-	dw StartTrainerBattle_SpeckleToBlack ; 1f
-
-	; All animations jump to here.
-	dw StartTrainerBattle_Finish ; 20
-
-
-StartTrainerBattle_DetermineWhichAnimation: ; 8c365 (23:4365)
-; The screen flashes a different number of times depending on the level of
-; your lead Pokemon relative to the opponent's.
-; BUG: BattleMonLevel and EnemyMonLevel are not set at this point, so whatever
-; values happen to be there will determine the animation.
-	ld de, 0
-	ld a, [BattleMonLevel]
-	add 3
-	ld hl, EnemyMonLevel
-	cp [hl]
-	jr nc, .okay
-	set 0, e
-.okay
-	ld a, [wPermission]
-	cp CAVE
-	jr z, .okay2
-	cp PERM_5
-	jr z, .okay2
-	cp DUNGEON
-	jr z, .okay2
-	set 1, e
-.okay2
-	ld hl, .StartingPoints
-	add hl, de
-	ld a, [hl]
-	ld [wJumptableIndex], a
-	ret
-; 8c38f (23:438f)
-
-.StartingPoints: ; 8c38f
-	db 1,  9
-	db 16, 24
-; 8c393
-
-StartTrainerBattle_Finish: ; 8c393 (23:4393)
-	call ClearSprites
-	ld a, $80
-	ld [wJumptableIndex], a
-	ret
-
-StartTrainerBattle_NextScene: ; 8c39c (23:439c)
-	ld hl, wJumptableIndex
-	inc [hl]
-	ret
-
-StartTrainerBattle_SetUpBGMap: ; 8c3a1 (23:43a1)
-	call StartTrainerBattle_NextScene
-	xor a
-	ld [wcf64], a
-	ld [hBGMapMode], a
-	ret
-
-StartTrainerBattle_Flash: ; 8c3ab (23:43ab)
-	call .DoFlashAnimation
-	ret nc
-	call StartTrainerBattle_NextScene
-	ret
-
-.DoFlashAnimation: ; 8c3b3 (23:43b3)
-	ld a, [wTimeOfDayPalset]
-	cp %11111111 ; dark cave
-	jr z, .done
-	ld hl, wcf64
-	ld a, [hl]
-	inc [hl]
-	srl a
-	ld e, a
-	ld d, 0
-	ld hl, .pals
-	add hl, de
-	ld a, [hl]
-	cp %00000001
-	jr z, .done
-	ld [wBGP], a
-	call DmgToCgbBGPals
-	and a
-	ret
-
-.done
-	xor a
-	ld [wcf64], a
-	scf
-	ret
-; 8c3db (23:43db)
-
-.pals ; 8c3db
-	db %11111001 ; 3321
-	db %11111110 ; 3332
-	db %11111111 ; 3333
-	db %11111110 ; 3332
-	db %11111001 ; 3321
-	db %11100100 ; 3210
-	db %10010000 ; 2100
-	db %01000000 ; 1000
-	db %00000000 ; 0000
-	db %01000000 ; 1000
-	db %10010000 ; 2100
-	db %11100100 ; 3210
-	db %00000001 ; 0001
-; 8c3e8
-
-StartTrainerBattle_SetUpForWavyOutro: ; 8c3e8 (23:43e8)
-	callba Function5602
-	ld a, $5 ; BANK(LYOverrides)
-	ld [rSVBK], a
-
-	call StartTrainerBattle_NextScene
-
-	ld a, rSCX - $ff00
-	ld [hLCDCPointer], a
-	xor a
-	ld [hLYOverrideStart], a
-	ld a, $90
-	ld [hLYOverrideEnd], a
-	xor a
-	ld [wcf64], a
-	ld [wcf65], a
-	ret
-
-StartTrainerBattle_SineWave: ; 8c408 (23:4408)
-	ld a, [wcf64]
-	cp $60
-	jr nc, .end
-	call .DoSineWave
-	ret
-
-.end
-	ld a, $20
-	ld [wJumptableIndex], a
-	ret
-
-.DoSineWave: ; 8c419 (23:4419)
-	ld hl, wcf65
-	ld a, [hl]
-	inc [hl]
-	ld hl, wcf64
-	ld d, [hl]
-	add [hl]
-	ld [hl], a
-	ld a, LYOverridesEnd - LYOverrides
-	ld bc, LYOverrides
-	ld e, $0
-
-.loop
-	push af
-	push de
-	ld a, e
-	call StartTrainerBattle_DrawSineWave
-	ld [bc], a
-	inc bc
-	pop de
-	ld a, e
-	add $2
-	ld e, a
-	pop af
-	dec a
-	jr nz, .loop
-	ret
-
-StartTrainerBattle_SetUpForSpinOutro: ; 8c43d (23:443d)
-	callba Function5602
-	ld a, $5 ; BANK(LYOverrides)
-	ld [rSVBK], a
-	call StartTrainerBattle_NextScene
-	xor a
-	ld [wcf64], a
-	ret
-
-StartTrainerBattle_SpinToBlack: ; 8c44f (23:444f)
-	xor a
-	ld [hBGMapMode], a
-	ld a, [wcf64]
-	ld e, a
-	ld d, 0
-	ld hl, .spintable
-rept 5
-	add hl, de
-endr
-	ld a, [hli]
-	cp -1
-	jr z, .end
-	ld [wcf65], a
-	call .load
-	ld a, $1
-	ld [hBGMapMode], a
-	call DelayFrame
-	call DelayFrame
-	ld hl, wcf64
-	inc [hl]
-	ret
-
-.end
-	ld a, $1
-	ld [hBGMapMode], a
-	call DelayFrame
-	call DelayFrame
-	call DelayFrame
-	xor a
-	ld [hBGMapMode], a
-	ld a, $20
-	ld [wJumptableIndex], a
-	ret
-; 8c490 (23:4490)
-
-; quadrants
-	const_def
-	const UPPER_LEFT
-	const UPPER_RIGHT
-	const LOWER_LEFT
-	const LOWER_RIGHT
-
-.spintable ; 8c490
-spintable_entry: MACRO
-	db \1
-	dw .wedge\2
-	dwcoord \3, \4
-ENDM
-	spintable_entry UPPER_LEFT,  1,  1,  6
-	spintable_entry UPPER_LEFT,  2,  0,  3
-	spintable_entry UPPER_LEFT,  3,  1,  0
-	spintable_entry UPPER_LEFT,  4,  5,  0
-	spintable_entry UPPER_LEFT,  5,  9,  0
-	spintable_entry UPPER_RIGHT, 5, 10,  0
-	spintable_entry UPPER_RIGHT, 4, 14,  0
-	spintable_entry UPPER_RIGHT, 3, 18,  0
-	spintable_entry UPPER_RIGHT, 2, 19,  3
-	spintable_entry UPPER_RIGHT, 1, 18,  6
-	spintable_entry LOWER_RIGHT, 1, 18, 11
-	spintable_entry LOWER_RIGHT, 2, 19, 14
-	spintable_entry LOWER_RIGHT, 3, 18, 17
-	spintable_entry LOWER_RIGHT, 4, 14, 17
-	spintable_entry LOWER_RIGHT, 5, 10, 17
-	spintable_entry LOWER_LEFT,  5,  9, 17
-	spintable_entry LOWER_LEFT,  4,  5, 17
-	spintable_entry LOWER_LEFT,  3,  1, 17
-	spintable_entry LOWER_LEFT,  2,  0, 14
-	spintable_entry LOWER_LEFT,  1,  1, 11
-	db -1
-; 8c4f5
-
-.load ; 8c4f5 (23:44f5)
-	ld a, [hli]
-	ld e, a
-	ld a, [hli]
-	ld d, a
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-.loop
-	push hl
-	ld a, [de]
-	ld c, a
-	inc de
-.loop1
-	ld [hl], $ff
-	ld a, [wcf65]
-	bit 0, a
-	jr z, .leftside
-	inc hl
-	jr .okay1
-.leftside
-	dec hl
-.okay1
-	dec c
-	jr nz, .loop1
-	pop hl
-	ld a, [wcf65]
-	bit 1, a
-	ld bc, SCREEN_WIDTH
-	jr z, .upper
-	ld bc, -SCREEN_WIDTH
-.upper
-	add hl, bc
-	ld a, [de]
-	inc de
-	cp -1
-	ret z
-	and a
-	jr z, .loop
-	ld c, a
-.loop2
-	ld a, [wcf65]
-	bit 0, a
-	jr z, .leftside2
-	dec hl
-	jr .okay2
-.leftside2
-	inc hl
-.okay2
-	dec c
-	jr nz, .loop2
-	jr .loop
-; 8c538 (23:4538)
-
-.wedge1 db 2, 3, 5, 4, 9, -1
-.wedge2 db 1, 1, 2, 2, 4, 2, 4, 2, 3, -1
-.wedge3 db 2, 1, 3, 1, 4, 1, 4, 1, 4, 1, 3, 1, 2, 1, 1, 1, 1, -1
-.wedge4 db 4, 1, 4, 0, 3, 1, 3, 0, 2, 1, 2, 0, 1, -1
-.wedge5 db 4, 0, 3, 0, 3, 0, 2, 0, 2, 0, 1, 0, 1, 0, 1, -1
-; 8c578
-
-StartTrainerBattle_SetUpForRandomScatterOutro: ; 8c578 (23:4578)
-	callba Function5602
-	ld a, $5 ; BANK(LYOverrides)
-	ld [rSVBK], a
-	call StartTrainerBattle_NextScene
-	ld a, $10
-	ld [wcf64], a
-	ld a, $1
-	ld [hBGMapMode], a
-	ret
-
-StartTrainerBattle_SpeckleToBlack: ; 8c58f (23:458f)
-	ld hl, wcf64
-	ld a, [hl]
-	and a
-	jr z, .done
-	dec [hl]
-	ld c, $c
-.loop
-	push bc
-	call .BlackOutRandomTile
-	pop bc
-	dec c
-	jr nz, .loop
-	ret
-
-.done
-	ld a, $1
-	ld [hBGMapMode], a
-	call DelayFrame
-	call DelayFrame
-	call DelayFrame
-	xor a
-	ld [hBGMapMode], a
-	ld a, $20
-	ld [wJumptableIndex], a
-	ret
-
-.BlackOutRandomTile: ; 8c5b8 (23:45b8)
-.y_loop
-	call Random
-	cp SCREEN_HEIGHT
-	jr nc, .y_loop
-	ld b, a
-
-.x_loop
-	call Random
-	cp SCREEN_WIDTH
-	jr nc, .x_loop
-	ld c, a
-
-	hlcoord 0, -1
-	ld de, SCREEN_WIDTH
-	inc b
-
-.row_loop
-	add hl, de
-	dec b
-	jr nz, .row_loop
-	add hl, bc
-
-; If the tile has already been blacked out,
-; sample a new tile
-	ld a, [hl]
-	cp $ff
-	jr z, .y_loop
-	ld [hl], $ff
-	ret
-
-StartTrainerBattle_LoadPokeBallGraphics: ; 8c5dc (23:45dc)
-	ld a, [OtherTrainerClass]
-	and a
-	jp z, .nextscene ; don't need to be here if wild
-
-	xor a
-	ld [hBGMapMode], a
-	hlcoord 0, 0, AttrMap
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	inc b
-	inc c
-	jr .enter_loop_midway
-
-.loop
-; set all pals to 7
-	ld a, [hl]
-	or %00000111
-	ld [hli], a
-.enter_loop_midway
-	dec c
-	jr nz, .loop
-	dec b
-	jr nz, .loop
-
-	call .loadpokeballgfx ; ld a, [OtherTrainerClass] \ ld de, PokeBallTransition \ ret
-	hlcoord 2, 1
-
-	ld b, SCREEN_WIDTH - 4
-.loop2
-	push hl
-	ld c, 2
-.loop3
-	push hl
-	ld a, [de]
-	inc de
-.loop4
-; Loading is done bit by bit
-	and a
-	jr z, .done
-	sla a
-	jr nc, .no_load
-	ld [hl], $fe
-.no_load
-	inc hl
-	jr .loop4
-
-.done
-	pop hl
-	push bc
-	ld bc, (SCREEN_WIDTH - 4) / 2
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .loop3
-
-	pop hl
-	push bc
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	pop bc
-	dec b
-	jr nz, .loop2
-
-	ld a, [hCGB]
-	and a
-	jr nz, .cgb
-	ld a, $1
-	ld [hBGMapMode], a
-	call DelayFrame
-	call DelayFrame
-	jr .nextscene
-
-.cgb
-	ld hl, .daypals
-	ld a, [TimeOfDayPal]
-	and (1 << 2) - 1
-	cp 3
-	jr nz, .daytime
-	ld hl, .nightpals
-.daytime
-	ld a, [rSVBK]
-	push af
-	ld a, $5 ; WRAM5 = palettes
-	ld [rSVBK], a
-	call .copypals
-	push hl
-	ld de, UnknBGPals palette PAL_BG_TEXT
-	ld bc, 1 palettes
-	call CopyBytes
-	pop hl
-	ld de, BGPals palette PAL_BG_TEXT
-	ld bc, 1 palettes
-	call CopyBytes
-	pop af
-	ld [rSVBK], a
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	call DelayFrame
-	call BattleStart_LoadEDTile
-
-.nextscene ; 8c673 (23:4673)
-	call StartTrainerBattle_NextScene
-	ret
-
-.copypals ; 8c677 (23:4677)
-	ld de, UnknBGPals palette PAL_BG_TEXT
-	call .copy
-	ld de, BGPals palette PAL_BG_TEXT
-	call .copy
-	ld de, UnknOBPals palette PAL_OW_TREE
-	call .copy
-	ld de, OBPals palette PAL_OW_TREE
-	call .copy
-	ld de, UnknOBPals palette PAL_OW_ROCK
-	call .copy
-	ld de, OBPals palette PAL_OW_ROCK
-
-.copy ; 8c698 (23:4698)
-	push hl
-	ld bc, 1 palettes
-	call CopyBytes
-	pop hl
-	ret
-; 8c6a1 (23:46a1)
-
-.daypals ; 8c6a1
-	RGB 31, 18, 29
-	RGB 31, 11, 15
-	RGB 31, 05, 05
-	RGB 07, 07, 07
-; 8c6a9
-
-.nightpals ; 8c6a9
-	RGB 31, 18, 29
-	RGB 31, 05, 05
-	RGB 31, 05, 05
-	RGB 31, 05, 05
-
-.loadpokeballgfx
-	ld a, [OtherTrainerClass]
-	ld de, PokeBallTransition
-	ret
-
-PokeBallTransition:
-	db %00000011, %11000000
-	db %00001111, %11110000
-	db %00111100, %00111100
-	db %00110000, %00001100
-	db %01100000, %00000110
-	db %01100011, %11000110
-	db %11000110, %01100011
-	db %11111100, %00111111
-	db %11111100, %00111111
-	db %11000110, %01100011
-	db %01100011, %11000110
-	db %01100000, %00000110
-	db %00110000, %00001100
-	db %00111100, %00111100
-	db %00001111, %11110000
-	db %00000011, %11000000
-
-WipeLYOverrides: ; 8c6d8
-	ld a, [rSVBK]
-	push af
-	ld a, $5
-	ld [rSVBK], a
-
-	ld hl, LYOverrides
-	call .wipe
-	ld hl, LYOverridesBackup
-	call .wipe
-
-	pop af
-	ld [rSVBK], a
-	ret
-; 8c6ef
-
-.wipe ; 8c6ef
-	xor a
-	ld c, SCREEN_HEIGHT_PX
-.loop
-	ld [hli], a
-	dec c
-	jr nz, .loop
-	ret
-; 8c6f7
-
-
-StartTrainerBattle_DrawSineWave: ; 8c6f7 (23:46f7)
-	and (1 << 6) - 1
-	cp 1 << 5
-	jr nc, .okay
-	call .DoSineWave
-	ld a, h
-	ret
-
-.okay
-	and (1 << 5) - 1
-	call .DoSineWave
-	ld a, h
-	xor -1 ; cpl
-	inc a
-	ret
-
-.DoSineWave: ; 8c70c (23:470c)
-	ld e, a
-	ld a, d
-	ld d, 0
-	ld hl, .sinewave
-	add hl, de
-	add hl, de
-	ld e, [hl]
-	inc hl
-	ld d, [hl]
-	ld hl, 0
-.loop
-	srl a
-	jr nc, .skip
-	add hl, de
-.skip
-	sla e
-	rl d
-	and a
-	jr nz, .loop
-	ret
-; 8c728 (23:4728)
-
-.sinewave ; 8c728
-	sine_wave $100
-; 8c768
-
-StartTrainerBattle_ZoomToBlack: ; 8c768 (23:4768)
-	callba Function5602
-	ld de, .boxes
-
-.loop
-	ld a, [de]
-	cp -1
-	jr z, .done
-	inc de
-	ld c, a
-	ld a, [de]
-	inc de
-	ld b, a
-	ld a, [de]
-	inc de
-	ld l, a
-	ld a, [de]
-	inc de
-	ld h, a
-	xor a
-	ld [hBGMapMode], a
-	call .Copy
-	call WaitBGMap
-	jr .loop
-
-.done
-	ld a, $20
-	ld [wJumptableIndex], a
-	ret
-; 8c792 (23:4792)
-
-.boxes ; 8c792
-zoombox: macro
-; width, height, start y, start x
-	db \1, \2
-	dwcoord \3, \4
-endm
-	zoombox  4,  2,  8, 8
-	zoombox  6,  4,  7, 7
-	zoombox  8,  6,  6, 6
-	zoombox 10,  8,  5, 5
-	zoombox 12, 10,  4, 4
-	zoombox 14, 12,  3, 3
-	zoombox 16, 14,  2, 2
-	zoombox 18, 16,  1, 1
-	zoombox 20, 18,  0, 0
-	db -1
-; 8c7b7
-
-.Copy: ; 8c7b7 (23:47b7)
-	ld a, $ff
-.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
-; 8c7c9 (23:47c9)
--- /dev/null
+++ b/engine/battle_transition.asm
@@ -1,0 +1,873 @@
+Predef_StartBattle: ; 8c20f
+	call .InitGFX
+	ld a, [rBGP]
+	ld [wBGP], a
+	ld a, [rOBP0]
+	ld [wOBP0], a
+	ld a, [rOBP1]
+	ld [wOBP1], a
+	call DelayFrame
+	ld hl, hVBlank
+	ld a, [hl]
+	push af
+	ld [hl], $1
+
+.loop
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .done
+	call FlashyTransitionToBattle
+	call DelayFrame
+	jr .loop
+
+.done
+	ld a, [rSVBK]
+	push af
+	ld a, $5
+	ld [rSVBK], a
+
+	ld hl, UnknBGPals
+	ld bc, 8 palettes
+	xor a
+	call ByteFill
+
+	pop af
+	ld [rSVBK], a
+
+	ld a, %11111111
+	ld [wBGP], a
+	call DmgToCgbBGPals
+	call DelayFrame
+	xor a
+	ld [hLCDCPointer], a
+	ld [hLYOverrideStart], a
+	ld [hLYOverrideEnd], a
+	ld [hSCY], a
+
+	ld a, $1
+	ld [rSVBK], a
+	pop af
+	ld [hVBlank], a
+	call DelayFrame
+	ret
+; 8c26d
+
+.InitGFX: ; 8c26d
+	ld a, [wLinkMode]
+	cp LINK_MOBILE
+	jr z, .mobile
+	callba ReanchorBGMap_NoOAMUpdate
+	call UpdateSprites
+	call DelayFrame
+	call .NonMobile_LoadPokeballTiles
+	call BattleStart_LoadEDTile
+	jr .resume
+
+.mobile
+	call LoadTrainerBattlePokeballTiles
+
+.resume
+	ld a, SCREEN_HEIGHT_PX
+	ld [hWY], a
+	call DelayFrame
+	xor a
+	ld [hBGMapMode], a
+	ld hl, wJumptableIndex
+	xor a
+	ld [hli], a
+	ld [hli], a
+	ld [hl], a
+	call WipeLYOverrides
+	ret
+; 8c2a0
+
+.NonMobile_LoadPokeballTiles: ; 8c2a0
+	call LoadTrainerBattlePokeballTiles
+	hlbgcoord 0, 0
+	call ConvertTrainerBattlePokeballTilesTo2bpp
+	ret
+; 8c2aa
+
+LoadTrainerBattlePokeballTiles:
+; Load the tiles used in the Pokeball Graphic that fills the screen
+; at the start of every Trainer battle.
+	ld de, TrainerBattlePokeballTiles
+	ld hl, VTiles1 tile $7e
+	ld b, BANK(TrainerBattlePokeballTiles)
+	ld c, 2
+	call Request2bpp
+
+	ld a, [rVBK]
+	push af
+	ld a, $1
+	ld [rVBK], a
+
+	ld de, TrainerBattlePokeballTiles
+	ld hl, VTiles4 tile $7e
+	ld b, BANK(TrainerBattlePokeballTiles)
+	ld c, 2
+	call Request2bpp
+
+	pop af
+	ld [rVBK], a
+	ret
+; 8c2cf
+
+ConvertTrainerBattlePokeballTilesTo2bpp: ; 8c2cf
+	ld a, [rSVBK]
+	push af
+	ld a, $6
+	ld [rSVBK], a
+	push hl
+	ld hl, wDecompressScratch
+	ld bc, $28 tiles
+
+.loop
+	ld [hl], -1
+	inc hl
+	dec bc
+	ld a, c
+	or b
+	jr nz, .loop
+
+	pop hl
+	ld de, wDecompressScratch
+	ld b, BANK(ConvertTrainerBattlePokeballTilesTo2bpp) ; BANK(@)
+	ld c, $28
+	call Request2bpp
+	pop af
+	ld [rSVBK], a
+	ret
+; 8c2f4
+
+TrainerBattlePokeballTiles: ; 8c2f4
+INCBIN "gfx/overworld/trainer_battle_pokeball_tiles.2bpp"
+
+
+FlashyTransitionToBattle: ; 8c314
+	jumptable .dw, wJumptableIndex
+; 8c323
+
+.dw ; 8c323 (23:4323)
+	dw StartTrainerBattle_DetermineWhichAnimation ; 00
+
+	; Animation 1: cave
+	dw StartTrainerBattle_LoadPokeBallGraphics ; 01
+	dw StartTrainerBattle_SetUpBGMap ; 02
+	dw StartTrainerBattle_Flash ; 03
+	dw StartTrainerBattle_Flash ; 04
+	dw StartTrainerBattle_Flash ; 05
+	dw StartTrainerBattle_NextScene ; 06
+	dw StartTrainerBattle_SetUpForWavyOutro ; 07
+	dw StartTrainerBattle_SineWave ; 08
+
+	; Animation 2: cave, stronger
+	dw StartTrainerBattle_LoadPokeBallGraphics ; 09
+	dw StartTrainerBattle_SetUpBGMap ; 0a
+	dw StartTrainerBattle_Flash ; 0b
+	dw StartTrainerBattle_Flash ; 0c
+	dw StartTrainerBattle_Flash ; 0d
+	dw StartTrainerBattle_NextScene ; 0e
+	; There is no setup for this one
+	dw StartTrainerBattle_ZoomToBlack ; 0f
+
+	; Animation 3: no cave
+	dw StartTrainerBattle_LoadPokeBallGraphics ; 10
+	dw StartTrainerBattle_SetUpBGMap ; 11
+	dw StartTrainerBattle_Flash ; 12
+	dw StartTrainerBattle_Flash ; 13
+	dw StartTrainerBattle_Flash ; 14
+	dw StartTrainerBattle_NextScene ; 15
+	dw StartTrainerBattle_SetUpForSpinOutro ; 16
+	dw StartTrainerBattle_SpinToBlack ; 17
+
+	; Animation 4: no cave, stronger
+	dw StartTrainerBattle_LoadPokeBallGraphics ; 18
+	dw StartTrainerBattle_SetUpBGMap ; 19
+	dw StartTrainerBattle_Flash ; 1a
+	dw StartTrainerBattle_Flash ; 1b
+	dw StartTrainerBattle_Flash ; 1c
+	dw StartTrainerBattle_NextScene ; 1d
+	dw StartTrainerBattle_SetUpForRandomScatterOutro ; 1e
+	dw StartTrainerBattle_SpeckleToBlack ; 1f
+
+	; All animations jump to here.
+	dw StartTrainerBattle_Finish ; 20
+
+
+StartTrainerBattle_DetermineWhichAnimation: ; 8c365 (23:4365)
+; The screen flashes a different number of times depending on the level of
+; your lead Pokemon relative to the opponent's.
+; BUG: BattleMonLevel and EnemyMonLevel are not set at this point, so whatever
+; values happen to be there will determine the animation.
+	ld de, 0
+	ld a, [BattleMonLevel]
+	add 3
+	ld hl, EnemyMonLevel
+	cp [hl]
+	jr nc, .okay
+	set 0, e
+.okay
+	ld a, [wPermission]
+	cp CAVE
+	jr z, .okay2
+	cp PERM_5
+	jr z, .okay2
+	cp DUNGEON
+	jr z, .okay2
+	set 1, e
+.okay2
+	ld hl, .StartingPoints
+	add hl, de
+	ld a, [hl]
+	ld [wJumptableIndex], a
+	ret
+; 8c38f (23:438f)
+
+.StartingPoints: ; 8c38f
+	db 1,  9
+	db 16, 24
+; 8c393
+
+StartTrainerBattle_Finish: ; 8c393 (23:4393)
+	call ClearSprites
+	ld a, $80
+	ld [wJumptableIndex], a
+	ret
+
+StartTrainerBattle_NextScene: ; 8c39c (23:439c)
+	ld hl, wJumptableIndex
+	inc [hl]
+	ret
+
+StartTrainerBattle_SetUpBGMap: ; 8c3a1 (23:43a1)
+	call StartTrainerBattle_NextScene
+	xor a
+	ld [wcf64], a
+	ld [hBGMapMode], a
+	ret
+
+StartTrainerBattle_Flash: ; 8c3ab (23:43ab)
+	call .DoFlashAnimation
+	ret nc
+	call StartTrainerBattle_NextScene
+	ret
+
+.DoFlashAnimation: ; 8c3b3 (23:43b3)
+	ld a, [wTimeOfDayPalset]
+	cp %11111111 ; dark cave
+	jr z, .done
+	ld hl, wcf64
+	ld a, [hl]
+	inc [hl]
+	srl a
+	ld e, a
+	ld d, 0
+	ld hl, .pals
+	add hl, de
+	ld a, [hl]
+	cp %00000001
+	jr z, .done
+	ld [wBGP], a
+	call DmgToCgbBGPals
+	and a
+	ret
+
+.done
+	xor a
+	ld [wcf64], a
+	scf
+	ret
+; 8c3db (23:43db)
+
+.pals ; 8c3db
+	db %11111001 ; 3321
+	db %11111110 ; 3332
+	db %11111111 ; 3333
+	db %11111110 ; 3332
+	db %11111001 ; 3321
+	db %11100100 ; 3210
+	db %10010000 ; 2100
+	db %01000000 ; 1000
+	db %00000000 ; 0000
+	db %01000000 ; 1000
+	db %10010000 ; 2100
+	db %11100100 ; 3210
+	db %00000001 ; 0001
+; 8c3e8
+
+StartTrainerBattle_SetUpForWavyOutro: ; 8c3e8 (23:43e8)
+	callba Function5602
+	ld a, $5 ; BANK(LYOverrides)
+	ld [rSVBK], a
+
+	call StartTrainerBattle_NextScene
+
+	ld a, rSCX - $ff00
+	ld [hLCDCPointer], a
+	xor a
+	ld [hLYOverrideStart], a
+	ld a, $90
+	ld [hLYOverrideEnd], a
+	xor a
+	ld [wcf64], a
+	ld [wcf65], a
+	ret
+
+StartTrainerBattle_SineWave: ; 8c408 (23:4408)
+	ld a, [wcf64]
+	cp $60
+	jr nc, .end
+	call .DoSineWave
+	ret
+
+.end
+	ld a, $20
+	ld [wJumptableIndex], a
+	ret
+
+.DoSineWave: ; 8c419 (23:4419)
+	ld hl, wcf65
+	ld a, [hl]
+	inc [hl]
+	ld hl, wcf64
+	ld d, [hl]
+	add [hl]
+	ld [hl], a
+	ld a, LYOverridesEnd - LYOverrides
+	ld bc, LYOverrides
+	ld e, $0
+
+.loop
+	push af
+	push de
+	ld a, e
+	call StartTrainerBattle_DrawSineWave
+	ld [bc], a
+	inc bc
+	pop de
+	ld a, e
+	add $2
+	ld e, a
+	pop af
+	dec a
+	jr nz, .loop
+	ret
+
+StartTrainerBattle_SetUpForSpinOutro: ; 8c43d (23:443d)
+	callba Function5602
+	ld a, $5 ; BANK(LYOverrides)
+	ld [rSVBK], a
+	call StartTrainerBattle_NextScene
+	xor a
+	ld [wcf64], a
+	ret
+
+StartTrainerBattle_SpinToBlack: ; 8c44f (23:444f)
+	xor a
+	ld [hBGMapMode], a
+	ld a, [wcf64]
+	ld e, a
+	ld d, 0
+	ld hl, .spintable
+rept 5
+	add hl, de
+endr
+	ld a, [hli]
+	cp -1
+	jr z, .end
+	ld [wcf65], a
+	call .load
+	ld a, $1
+	ld [hBGMapMode], a
+	call DelayFrame
+	call DelayFrame
+	ld hl, wcf64
+	inc [hl]
+	ret
+
+.end
+	ld a, $1
+	ld [hBGMapMode], a
+	call DelayFrame
+	call DelayFrame
+	call DelayFrame
+	xor a
+	ld [hBGMapMode], a
+	ld a, $20
+	ld [wJumptableIndex], a
+	ret
+; 8c490 (23:4490)
+
+; quadrants
+	const_def
+	const UPPER_LEFT
+	const UPPER_RIGHT
+	const LOWER_LEFT
+	const LOWER_RIGHT
+
+.spintable ; 8c490
+spintable_entry: MACRO
+	db \1
+	dw .wedge\2
+	dwcoord \3, \4
+ENDM
+	spintable_entry UPPER_LEFT,  1,  1,  6
+	spintable_entry UPPER_LEFT,  2,  0,  3
+	spintable_entry UPPER_LEFT,  3,  1,  0
+	spintable_entry UPPER_LEFT,  4,  5,  0
+	spintable_entry UPPER_LEFT,  5,  9,  0
+	spintable_entry UPPER_RIGHT, 5, 10,  0
+	spintable_entry UPPER_RIGHT, 4, 14,  0
+	spintable_entry UPPER_RIGHT, 3, 18,  0
+	spintable_entry UPPER_RIGHT, 2, 19,  3
+	spintable_entry UPPER_RIGHT, 1, 18,  6
+	spintable_entry LOWER_RIGHT, 1, 18, 11
+	spintable_entry LOWER_RIGHT, 2, 19, 14
+	spintable_entry LOWER_RIGHT, 3, 18, 17
+	spintable_entry LOWER_RIGHT, 4, 14, 17
+	spintable_entry LOWER_RIGHT, 5, 10, 17
+	spintable_entry LOWER_LEFT,  5,  9, 17
+	spintable_entry LOWER_LEFT,  4,  5, 17
+	spintable_entry LOWER_LEFT,  3,  1, 17
+	spintable_entry LOWER_LEFT,  2,  0, 14
+	spintable_entry LOWER_LEFT,  1,  1, 11
+	db -1
+; 8c4f5
+
+.load ; 8c4f5 (23:44f5)
+	ld a, [hli]
+	ld e, a
+	ld a, [hli]
+	ld d, a
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+.loop
+	push hl
+	ld a, [de]
+	ld c, a
+	inc de
+.loop1
+	ld [hl], $ff
+	ld a, [wcf65]
+	bit 0, a
+	jr z, .leftside
+	inc hl
+	jr .okay1
+.leftside
+	dec hl
+.okay1
+	dec c
+	jr nz, .loop1
+	pop hl
+	ld a, [wcf65]
+	bit 1, a
+	ld bc, SCREEN_WIDTH
+	jr z, .upper
+	ld bc, -SCREEN_WIDTH
+.upper
+	add hl, bc
+	ld a, [de]
+	inc de
+	cp -1
+	ret z
+	and a
+	jr z, .loop
+	ld c, a
+.loop2
+	ld a, [wcf65]
+	bit 0, a
+	jr z, .leftside2
+	dec hl
+	jr .okay2
+.leftside2
+	inc hl
+.okay2
+	dec c
+	jr nz, .loop2
+	jr .loop
+; 8c538 (23:4538)
+
+.wedge1 db 2, 3, 5, 4, 9, -1
+.wedge2 db 1, 1, 2, 2, 4, 2, 4, 2, 3, -1
+.wedge3 db 2, 1, 3, 1, 4, 1, 4, 1, 4, 1, 3, 1, 2, 1, 1, 1, 1, -1
+.wedge4 db 4, 1, 4, 0, 3, 1, 3, 0, 2, 1, 2, 0, 1, -1
+.wedge5 db 4, 0, 3, 0, 3, 0, 2, 0, 2, 0, 1, 0, 1, 0, 1, -1
+; 8c578
+
+StartTrainerBattle_SetUpForRandomScatterOutro: ; 8c578 (23:4578)
+	callba Function5602
+	ld a, $5 ; BANK(LYOverrides)
+	ld [rSVBK], a
+	call StartTrainerBattle_NextScene
+	ld a, $10
+	ld [wcf64], a
+	ld a, $1
+	ld [hBGMapMode], a
+	ret
+
+StartTrainerBattle_SpeckleToBlack: ; 8c58f (23:458f)
+	ld hl, wcf64
+	ld a, [hl]
+	and a
+	jr z, .done
+	dec [hl]
+	ld c, $c
+.loop
+	push bc
+	call .BlackOutRandomTile
+	pop bc
+	dec c
+	jr nz, .loop
+	ret
+
+.done
+	ld a, $1
+	ld [hBGMapMode], a
+	call DelayFrame
+	call DelayFrame
+	call DelayFrame
+	xor a
+	ld [hBGMapMode], a
+	ld a, $20
+	ld [wJumptableIndex], a
+	ret
+
+.BlackOutRandomTile: ; 8c5b8 (23:45b8)
+.y_loop
+	call Random
+	cp SCREEN_HEIGHT
+	jr nc, .y_loop
+	ld b, a
+
+.x_loop
+	call Random
+	cp SCREEN_WIDTH
+	jr nc, .x_loop
+	ld c, a
+
+	hlcoord 0, -1
+	ld de, SCREEN_WIDTH
+	inc b
+
+.row_loop
+	add hl, de
+	dec b
+	jr nz, .row_loop
+	add hl, bc
+
+; If the tile has already been blacked out,
+; sample a new tile
+	ld a, [hl]
+	cp $ff
+	jr z, .y_loop
+	ld [hl], $ff
+	ret
+
+StartTrainerBattle_LoadPokeBallGraphics: ; 8c5dc (23:45dc)
+	ld a, [OtherTrainerClass]
+	and a
+	jp z, .nextscene ; don't need to be here if wild
+
+	xor a
+	ld [hBGMapMode], a
+	hlcoord 0, 0, AttrMap
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	inc b
+	inc c
+	jr .enter_loop_midway
+
+.loop
+; set all pals to 7
+	ld a, [hl]
+	or %00000111
+	ld [hli], a
+.enter_loop_midway
+	dec c
+	jr nz, .loop
+	dec b
+	jr nz, .loop
+
+	call .loadpokeballgfx ; ld a, [OtherTrainerClass] \ ld de, PokeBallTransition \ ret
+	hlcoord 2, 1
+
+	ld b, SCREEN_WIDTH - 4
+.loop2
+	push hl
+	ld c, 2
+.loop3
+	push hl
+	ld a, [de]
+	inc de
+.loop4
+; Loading is done bit by bit
+	and a
+	jr z, .done
+	sla a
+	jr nc, .no_load
+	ld [hl], $fe
+.no_load
+	inc hl
+	jr .loop4
+
+.done
+	pop hl
+	push bc
+	ld bc, (SCREEN_WIDTH - 4) / 2
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .loop3
+
+	pop hl
+	push bc
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	pop bc
+	dec b
+	jr nz, .loop2
+
+	ld a, [hCGB]
+	and a
+	jr nz, .cgb
+	ld a, $1
+	ld [hBGMapMode], a
+	call DelayFrame
+	call DelayFrame
+	jr .nextscene
+
+.cgb
+	ld hl, .daypals
+	ld a, [TimeOfDayPal]
+	and (1 << 2) - 1
+	cp 3
+	jr nz, .daytime
+	ld hl, .nightpals
+.daytime
+	ld a, [rSVBK]
+	push af
+	ld a, $5 ; WRAM5 = palettes
+	ld [rSVBK], a
+	call .copypals
+	push hl
+	ld de, UnknBGPals palette PAL_BG_TEXT
+	ld bc, 1 palettes
+	call CopyBytes
+	pop hl
+	ld de, BGPals palette PAL_BG_TEXT
+	ld bc, 1 palettes
+	call CopyBytes
+	pop af
+	ld [rSVBK], a
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	call DelayFrame
+	call BattleStart_LoadEDTile
+
+.nextscene ; 8c673 (23:4673)
+	call StartTrainerBattle_NextScene
+	ret
+
+.copypals ; 8c677 (23:4677)
+	ld de, UnknBGPals palette PAL_BG_TEXT
+	call .copy
+	ld de, BGPals palette PAL_BG_TEXT
+	call .copy
+	ld de, UnknOBPals palette PAL_OW_TREE
+	call .copy
+	ld de, OBPals palette PAL_OW_TREE
+	call .copy
+	ld de, UnknOBPals palette PAL_OW_ROCK
+	call .copy
+	ld de, OBPals palette PAL_OW_ROCK
+
+.copy ; 8c698 (23:4698)
+	push hl
+	ld bc, 1 palettes
+	call CopyBytes
+	pop hl
+	ret
+; 8c6a1 (23:46a1)
+
+.daypals ; 8c6a1
+	RGB 31, 18, 29
+	RGB 31, 11, 15
+	RGB 31, 05, 05
+	RGB 07, 07, 07
+; 8c6a9
+
+.nightpals ; 8c6a9
+	RGB 31, 18, 29
+	RGB 31, 05, 05
+	RGB 31, 05, 05
+	RGB 31, 05, 05
+
+.loadpokeballgfx
+	ld a, [OtherTrainerClass]
+	ld de, PokeBallTransition
+	ret
+
+PokeBallTransition:
+	db %00000011, %11000000
+	db %00001111, %11110000
+	db %00111100, %00111100
+	db %00110000, %00001100
+	db %01100000, %00000110
+	db %01100011, %11000110
+	db %11000110, %01100011
+	db %11111100, %00111111
+	db %11111100, %00111111
+	db %11000110, %01100011
+	db %01100011, %11000110
+	db %01100000, %00000110
+	db %00110000, %00001100
+	db %00111100, %00111100
+	db %00001111, %11110000
+	db %00000011, %11000000
+
+WipeLYOverrides: ; 8c6d8
+	ld a, [rSVBK]
+	push af
+	ld a, $5
+	ld [rSVBK], a
+
+	ld hl, LYOverrides
+	call .wipe
+	ld hl, LYOverridesBackup
+	call .wipe
+
+	pop af
+	ld [rSVBK], a
+	ret
+; 8c6ef
+
+.wipe ; 8c6ef
+	xor a
+	ld c, SCREEN_HEIGHT_PX
+.loop
+	ld [hli], a
+	dec c
+	jr nz, .loop
+	ret
+; 8c6f7
+
+
+StartTrainerBattle_DrawSineWave: ; 8c6f7 (23:46f7)
+	and (1 << 6) - 1
+	cp 1 << 5
+	jr nc, .okay
+	call .DoSineWave
+	ld a, h
+	ret
+
+.okay
+	and (1 << 5) - 1
+	call .DoSineWave
+	ld a, h
+	xor -1 ; cpl
+	inc a
+	ret
+
+.DoSineWave: ; 8c70c (23:470c)
+	ld e, a
+	ld a, d
+	ld d, 0
+	ld hl, .sinewave
+	add hl, de
+	add hl, de
+	ld e, [hl]
+	inc hl
+	ld d, [hl]
+	ld hl, 0
+.loop
+	srl a
+	jr nc, .skip
+	add hl, de
+.skip
+	sla e
+	rl d
+	and a
+	jr nz, .loop
+	ret
+; 8c728 (23:4728)
+
+.sinewave ; 8c728
+	sine_wave $100
+; 8c768
+
+StartTrainerBattle_ZoomToBlack: ; 8c768 (23:4768)
+	callba Function5602
+	ld de, .boxes
+
+.loop
+	ld a, [de]
+	cp -1
+	jr z, .done
+	inc de
+	ld c, a
+	ld a, [de]
+	inc de
+	ld b, a
+	ld a, [de]
+	inc de
+	ld l, a
+	ld a, [de]
+	inc de
+	ld h, a
+	xor a
+	ld [hBGMapMode], a
+	call .Copy
+	call WaitBGMap
+	jr .loop
+
+.done
+	ld a, $20
+	ld [wJumptableIndex], a
+	ret
+; 8c792 (23:4792)
+
+.boxes ; 8c792
+zoombox: macro
+; width, height, start y, start x
+	db \1, \2
+	dwcoord \3, \4
+endm
+	zoombox  4,  2,  8, 8
+	zoombox  6,  4,  7, 7
+	zoombox  8,  6,  6, 6
+	zoombox 10,  8,  5, 5
+	zoombox 12, 10,  4, 4
+	zoombox 14, 12,  3, 3
+	zoombox 16, 14,  2, 2
+	zoombox 18, 16,  1, 1
+	zoombox 20, 18,  0, 0
+	db -1
+; 8c7b7
+
+.Copy: ; 8c7b7 (23:47b7)
+	ld a, $ff
+.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
+; 8c7c9 (23:47c9)
+
+Function8c7c9:
+; XXX
+	ld a, $1
+	ld [hBGMapMode], a
+	call WaitBGMap
+	xor a
+	ld [hBGMapMode], a
+	ret
--- /dev/null
+++ b/engine/caught_data.asm
@@ -1,0 +1,247 @@
+CheckPartyFullAfterContest: ; 4d9e5
+	ld a, [wContestMon]
+	and a
+	jp z, .DidntCatchAnything
+	ld [CurPartySpecies], a
+	ld [CurSpecies], a
+	call GetBaseData
+	ld hl, PartyCount
+	ld a, [hl]
+	cp 6
+	jp nc, .TryAddToBox
+	inc a
+	ld [hl], a
+	ld c, a
+	ld b, $0
+	add hl, bc
+	ld a, [wContestMon]
+	ld [hli], a
+	ld [CurSpecies], a
+	ld a, $ff
+	ld [hl], a
+	ld hl, PartyMon1Species
+	ld a, [PartyCount]
+	dec a
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld hl, wContestMon
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call CopyBytes
+	ld a, [PartyCount]
+	dec a
+	ld hl, PartyMonOT
+	call SkipNames
+	ld d, h
+	ld e, l
+	ld hl, PlayerName
+	call CopyBytes
+	ld a, [CurPartySpecies]
+	ld [wd265], a
+	call GetPokemonName
+	ld hl, StringBuffer1
+	ld de, wMonOrItemNameBuffer
+	ld bc, PKMN_NAME_LENGTH
+	call CopyBytes
+	call GiveANickname_YesNo
+	jr c, .Party_SkipNickname
+	ld a, [PartyCount]
+	dec a
+	ld [CurPartyMon], a
+	xor a
+	ld [MonType], a
+	ld de, wMonOrItemNameBuffer
+	callab InitNickname
+
+.Party_SkipNickname:
+	ld a, [PartyCount]
+	dec a
+	ld hl, PartyMonNicknames
+	call SkipNames
+	ld d, h
+	ld e, l
+	ld hl, wMonOrItemNameBuffer
+	call CopyBytes
+	ld a, [PartyCount]
+	dec a
+	ld hl, PartyMon1Level
+	call GetPartyLocation
+	ld a, [hl]
+	ld [CurPartyLevel], a
+	call SetCaughtData
+	ld a, [PartyCount]
+	dec a
+	ld hl, PartyMon1CaughtLocation
+	call GetPartyLocation
+	ld a, [hl]
+	and $80
+	ld b, $13
+	or b
+	ld [hl], a
+	xor a
+	ld [wContestMon], a
+	and a
+	ld [ScriptVar], a
+	ret
+
+.TryAddToBox: ; 4daa3
+	ld a, BANK(sBoxCount)
+	call GetSRAMBank
+	ld hl, sBoxCount
+	ld a, [hl]
+	cp MONS_PER_BOX
+	call CloseSRAM
+	jr nc, .BoxFull
+	xor a
+	ld [CurPartyMon], a
+	ld hl, wContestMon
+	ld de, wBufferMon
+	ld bc, BOXMON_STRUCT_LENGTH
+	call CopyBytes
+	ld hl, PlayerName
+	ld de, wBufferMonOT
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	callab InsertPokemonIntoBox
+	ld a, [CurPartySpecies]
+	ld [wd265], a
+	call GetPokemonName
+	call GiveANickname_YesNo
+	ld hl, StringBuffer1
+	jr c, .Box_SkipNickname
+	ld a, BOXMON
+	ld [MonType], a
+	ld de, wMonOrItemNameBuffer
+	callab InitNickname
+	ld hl, wMonOrItemNameBuffer
+
+.Box_SkipNickname:
+	ld a, BANK(sBoxMonNicknames)
+	call GetSRAMBank
+	ld de, sBoxMonNicknames
+	ld bc, PKMN_NAME_LENGTH
+	call CopyBytes
+	call CloseSRAM
+
+.BoxFull:
+	ld a, BANK(sBoxMon1Level)
+	call GetSRAMBank
+	ld a, [sBoxMon1Level]
+	ld [CurPartyLevel], a
+	call CloseSRAM
+	call SetBoxMonCaughtData
+	ld a, BANK(sBoxMon1CaughtLocation)
+	call GetSRAMBank
+	ld hl, sBoxMon1CaughtLocation
+	ld a, [hl]
+	and $80
+	ld b, $13
+	or b
+	ld [hl], a
+	call CloseSRAM
+	xor a
+	ld [wContestMon], a
+	ld a, $1
+	ld [ScriptVar], a
+	ret
+
+.DidntCatchAnything: ; 4db35
+	ld a, $2
+	ld [ScriptVar], a
+	ret
+
+GiveANickname_YesNo: ; 4db3b
+	ld hl, TextJump_GiveANickname
+	call PrintText
+	jp YesNoBox
+
+TextJump_GiveANickname: ; 0x4db44
+	; Give a nickname to the @  you received?
+	text_jump UnknownText_0x1c12fc
+	db "@"
+
+SetCaughtData: ; 4db49
+	ld a, [PartyCount]
+	dec a
+	ld hl, PartyMon1CaughtLevel
+	call GetPartyLocation
+SetBoxmonOrEggmonCaughtData: ; 4db53
+	ld a, [TimeOfDay]
+	inc a
+	rrca
+	rrca
+	ld b, a
+	ld a, [CurPartyLevel]
+	or b
+	ld [hli], a
+	ld a, [MapGroup]
+	ld b, a
+	ld a, [MapNumber]
+	ld c, a
+	cp MAP_POKECENTER_2F
+	jr nz, .NotPokecenter2F
+	ld a, b
+	cp GROUP_POKECENTER_2F
+	jr nz, .NotPokecenter2F
+
+	ld a, [BackupMapGroup]
+	ld b, a
+	ld a, [BackupMapNumber]
+	ld c, a
+
+.NotPokecenter2F:
+	call GetWorldMapLocation
+	ld b, a
+	ld a, [PlayerGender]
+	rrca
+	or b
+	ld [hl], a
+	ret
+
+SetBoxMonCaughtData: ; 4db83
+	ld a, BANK(sBoxMon1CaughtLevel)
+	call GetSRAMBank
+	ld hl, sBoxMon1CaughtLevel
+	call SetBoxmonOrEggmonCaughtData
+	call CloseSRAM
+	ret
+
+SetGiftBoxMonCaughtData: ; 4db92
+	push bc
+	ld a, BANK(sBoxMon1CaughtLevel)
+	call GetSRAMBank
+	ld hl, sBoxMon1CaughtLevel
+	pop bc
+	call SetGiftMonCaughtData
+	call CloseSRAM
+	ret
+
+SetGiftPartyMonCaughtData: ; 4dba3
+	ld a, [PartyCount]
+	dec a
+	ld hl, PartyMon1CaughtLevel
+	push bc
+	call GetPartyLocation
+	pop bc
+SetGiftMonCaughtData: ; 4dbaf
+	xor a
+	ld [hli], a
+	ld a, $7e
+	rrc b
+	or b
+	ld [hl], a
+	ret
+
+SetEggMonCaughtData: ; 4dbb8 (13:5bb8)
+	ld a, [CurPartyMon]
+	ld hl, PartyMon1CaughtLevel
+	call GetPartyLocation
+	ld a, [CurPartyLevel]
+	push af
+	ld a, $1
+	ld [CurPartyLevel], a
+	call SetBoxmonOrEggmonCaughtData
+	pop af
+	ld [CurPartyLevel], a
+	ret
--- /dev/null
+++ b/engine/check_nick_errors.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, PKMN_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 "<START>",  TX_BOX    + 1
+	db "<PLAY_G>", $18       + 1
+	db $1d,        "%"       + 1
+	db $35,        "<GREEN>" + 1
+	db "<ENEMY>",  "<ENEMY>" + 1
+	db "<MOM>",    "<TM>"    + 1
+	db "<ROCKET>", "┘"       + 1
+	db -1 ; end
--- /dev/null
+++ b/engine/check_time.asm
@@ -1,0 +1,19 @@
+CheckTime:: ; c000
+	ld a, [TimeOfDay]
+	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/collision_stdscripts.asm
@@ -1,0 +1,29 @@
+CheckFacingTileForStd:: ; 1365b
+; Checks to see if the tile you're facing has a std script associated with it.  If so, executes the script and returns carry.
+	ld a, c
+	ld de, 3
+	ld hl, TileCollisionStdScripts
+	call IsInArray
+	jr nc, .notintable
+
+	ld a, jumpstd_command
+	ld [wJumpStdScriptBuffer], a
+	inc hl
+	ld a, [hli]
+	ld [wJumpStdScriptBuffer + 1], a
+	ld a, [hli]
+	ld [wJumpStdScriptBuffer + 2], a
+	ld a, BANK(Script_JumpStdFromRAM)
+	ld hl, Script_JumpStdFromRAM
+	call CallScript
+	scf
+	ret
+
+.notintable
+	xor a
+	ret
+
+INCLUDE "data/collision_stdscripts.asm"
+
+Script_JumpStdFromRAM: ; 0x1369a
+	jump wJumpStdScriptBuffer
--- /dev/null
+++ b/engine/consume_held_item.asm
@@ -1,0 +1,80 @@
+ConsumeHeldItem: ; 27192
+	push hl
+	push de
+	push bc
+	ld a, [hBattleTurn]
+	and a
+	ld hl, OTPartyMon1Item
+	ld de, EnemyMonItem
+	ld a, [CurOTMon]
+	jr z, .theirturn
+	ld hl, PartyMon1Item
+	ld de, BattleMonItem
+	ld a, [CurBattleMon]
+
+.theirturn
+	push hl
+	push af
+	ld a, [de]
+	ld b, a
+	callba GetItemHeldEffect
+	ld hl, .ConsumableEffects
+.loop
+	ld a, [hli]
+	cp b
+	jr z, .ok
+	inc a
+	jr nz, .loop
+	pop af
+	pop hl
+	pop bc
+	pop de
+	pop hl
+	ret
+
+.ok
+	xor a
+	ld [de], a
+	pop af
+	pop hl
+	call GetPartyLocation
+	ld a, [hBattleTurn]
+	and a
+	jr nz, .ourturn
+	ld a, [wBattleMode]
+	dec a
+	jr z, .done
+
+.ourturn
+	ld [hl], $0
+
+.done
+	pop bc
+	pop de
+	pop hl
+	ret
+
+.ConsumableEffects: ; 271de
+; Consumable items?
+	db HELD_BERRY
+	db HELD_2
+	db HELD_5
+	db HELD_HEAL_POISON
+	db HELD_HEAL_FREEZE
+	db HELD_HEAL_BURN
+	db HELD_HEAL_SLEEP
+	db HELD_HEAL_PARALYZE
+	db HELD_HEAL_STATUS
+	db HELD_30
+	db HELD_ATTACK_UP
+	db HELD_DEFENSE_UP
+	db HELD_SPEED_UP
+	db HELD_SP_ATTACK_UP
+	db HELD_SP_DEFENSE_UP
+	db HELD_ACCURACY_UP
+	db HELD_EVASION_UP
+	db HELD_38
+	db HELD_71
+	db HELD_ESCAPE
+	db HELD_CRITICAL_UP
+	db -1
--- a/engine/crystal_colors.asm
+++ b/engine/crystal_colors.asm
@@ -612,3 +612,13 @@
 	call _InitMG_Mobile_LinkTradePalMap
 	ret
 ; 4985a
+
+Unknown_4985a: ; unreferenced
+	db $ab, $03, $57, $24, $ac, $0e, $13, $32
+	db $be, $30, $5b, $4c, $47, $60, $ed, $f2
+	db $ab, $03, $55, $26, $aa, $0a, $13, $3a
+	db $be, $28, $33, $24, $6e, $71, $df, $b0
+	db $a8, $00, $e5, $e0, $9a, $fc, $f4, $2c
+	db $fe, $4c, $a3, $5e, $c6, $3a, $ab, $4d
+	db $a8, $00, $b5, $b0, $de, $e8, $fc, $1c
+	db $ba, $66, $f7, $0e, $ba, $5e, $43, $bd
--- /dev/null
+++ b/engine/european_mail.asm
@@ -1,0 +1,129 @@
+IsMailEuropean: ; 1de5c8
+; return 1 if French
+; return 2 if German
+; return 3 if Italian
+; return 4 if Spanish
+; return 0 if none of the above
+	ld c, $0
+	ld hl, sPartyMon1MailAuthorNationality - sPartyMon1Mail
+	add hl, de
+	ld a, [hli]
+	cp "E"
+	ret nz
+	ld a, [hli]
+	inc c
+	cp "F"
+	ret z
+	inc c
+	cp "G"
+	ret z
+	inc c
+	cp "I"
+	ret z
+	inc c
+	cp "S"
+	ret z
+	ld c, $0
+	ret
+
+; The regular font.
+StandardEnglishFont: ; 1de5e6
+INCBIN "gfx/font/english.1bpp"
+
+; An extended font.
+FrenchGermanFont: ; 1de9e6
+INCBIN "gfx/font/french_german.1bpp"
+
+; An even more extended font.
+SpanishItalianFont: ; 1dede6
+INCBIN "gfx/font/spanish_italian.1bpp"
+
+HandleFrenchGermanMail: ; 1df1e6
+; called if mail is french or german
+; fix 's 't 'v
+	ld b, sPartyMon1MailAuthor - sPartyMon1Mail
+	ld h, d
+	ld l, e
+.loop
+	ld a, [hl]
+	cp $dc ; 's in french/german font
+	jr nz, .check_intermediate_chars
+	ld a, "'s"
+	jr .replace
+
+.check_intermediate_chars
+	sub "'s"
+	jr c, .dont_replace
+	cp "'v" - "'s" + 1
+	jr nc, .dont_replace
+	add $cd
+
+.replace
+	ld [hl], a
+
+.dont_replace
+	inc hl
+	dec b
+	jr nz, .loop
+	ret
+
+LireLeCourrierAnglais:
+DeutenEnglischenPost: ; 1df203
+; Cette fonction convertit certains des caractères anglais pour
+; leur équivalent dans le jeu de caractères français.
+; Diese Funktion wandelt bestimmte englische Zeichen, um ihre
+; Entsprechung in der Deutschen-Zeichensatz.
+	ld b, sPartyMon1MailAuthor - sPartyMon1Mail
+	ld h, d
+	ld l, e
+.loop
+	ld a, [hl]
+	cp "'s"
+	jr nz, .check_intermediate_chars
+	ld a, $dc
+	jr .replace
+
+.check_intermediate_chars
+	sub $cd
+	jr c, .dont_replace
+	cp "'v" - "'s" + 1
+	jr nc, .dont_replace
+	add "'s"
+
+.replace
+	ld [hl], a
+
+.dont_replace
+	inc hl
+	dec b
+	jr nz, .loop
+	ret
+
+HandleSpanishItalianMail: ; 1df220
+LeerCorreosIngleses:
+LeggiPostaInglese:
+; This function converts certain characters between
+; the English and Spanish/Italian character sets.
+; Esta función convierte ciertos caracteres entre
+; el juego de caracteres Inglés y Español.
+; Questa funzione converte alcuni caratteri tra
+; l'inglese e il set di caratteri italiani.
+	ld b, sPartyMon1MailAuthor - sPartyMon1Mail
+	ld h, d
+	ld l, e
+.loop
+	ld a, [hl]
+	and $f0
+	cp $d0
+	jr nz, .dont_replace
+	ld a, [hl]
+	add $8
+	and $f
+	or $d0
+	ld [hl], a
+
+.dont_replace
+	inc hl
+	dec b
+	jr nz, .loop
+	ret
--- /dev/null
+++ b/engine/experience.asm
@@ -1,0 +1,162 @@
+CalcLevel: ; 50e1b
+	ld a, [TempMonSpecies]
+	ld [CurSpecies], a
+	call GetBaseData
+	ld d, 1
+.next_level
+	inc d
+	ld a, d
+	cp (MAX_LEVEL + 1) % $100
+	jr z, .got_level
+	call CalcExpAtLevel
+	push hl
+	ld hl, TempMonExp + 2
+	ld a, [hProduct + 3]
+	ld c, a
+	ld a, [hld]
+	sub c
+	ld a, [hProduct + 2]
+	ld c, a
+	ld a, [hld]
+	sbc c
+	ld a, [hProduct + 1]
+	ld c, a
+	ld a, [hl]
+	sbc c
+	pop hl
+	jr nc, .next_level
+
+.got_level
+	dec d
+	ret
+
+CalcExpAtLevel: ; 50e47
+; (a/b)*n**3 + c*n**2 + d*n - e
+	ld a, [BaseGrowthRate]
+	add a
+	add a
+	ld c, a
+	ld b, 0
+	ld hl, GrowthRates
+	add hl, bc
+; Cube the level
+	call .LevelSquared
+	ld a, d
+	ld [hMultiplier], a
+	call Multiply
+
+; Multiply by a
+	ld a, [hl]
+	and $f0
+	swap a
+	ld [hMultiplier], a
+	call Multiply
+; Divide by b
+	ld a, [hli]
+	and $f
+	ld [hDivisor], a
+	ld b, 4
+	call Divide
+; Push the cubic term to the stack
+	ld a, [hQuotient + 0]
+	push af
+	ld a, [hQuotient + 1]
+	push af
+	ld a, [hQuotient + 2]
+	push af
+; Square the level and multiply by the lower 7 bits of c
+	call .LevelSquared
+	ld a, [hl]
+	and $7f
+	ld [hMultiplier], a
+	call Multiply
+; Push the absolute value of the quadratic term to the stack
+	ld a, [hProduct + 1]
+	push af
+	ld a, [hProduct + 2]
+	push af
+	ld a, [hProduct + 3]
+	push af
+	ld a, [hli]
+	push af
+; Multiply the level by d
+	xor a
+	ld [hMultiplicand + 0], a
+	ld [hMultiplicand + 1], a
+	ld a, d
+	ld [hMultiplicand + 2], a
+	ld a, [hli]
+	ld [hMultiplier], a
+	call Multiply
+; Subtract e
+	ld b, [hl]
+	ld a, [hProduct + 3]
+	sub b
+	ld [hMultiplicand + 2], a
+	ld b, $0
+	ld a, [hProduct + 2]
+	sbc b
+	ld [hMultiplicand + 1], a
+	ld a, [hProduct + 1]
+	sbc b
+	ld [hMultiplicand], a
+; If bit 7 of c is set, c is negative; otherwise, it's positive
+	pop af
+	and $80
+	jr nz, .subtract
+; Add c*n**2 to (d*n - e)
+	pop bc
+	ld a, [hProduct + 3]
+	add b
+	ld [hMultiplicand + 2], a
+	pop bc
+	ld a, [hProduct + 2]
+	adc b
+	ld [hMultiplicand + 1], a
+	pop bc
+	ld a, [hProduct + 1]
+	adc b
+	ld [hMultiplicand], a
+	jr .done_quadratic
+
+.subtract
+; Subtract c*n**2 from (d*n - e)
+	pop bc
+	ld a, [hProduct + 3]
+	sub b
+	ld [hMultiplicand + 2], a
+	pop bc
+	ld a, [hProduct + 2]
+	sbc b
+	ld [hMultiplicand + 1], a
+	pop bc
+	ld a, [hProduct + 1]
+	sbc b
+	ld [hMultiplicand], a
+
+.done_quadratic
+; Add (a/b)*n**3 to (d*n - e +/- c*n**2)
+	pop bc
+	ld a, [hProduct + 3]
+	add b
+	ld [hMultiplicand + 2], a
+	pop bc
+	ld a, [hProduct + 2]
+	adc b
+	ld [hMultiplicand + 1], a
+	pop bc
+	ld a, [hProduct + 1]
+	adc b
+	ld [hMultiplicand], a
+	ret
+
+.LevelSquared: ; 50eed
+	xor a
+	ld [hMultiplicand + 0], a
+	ld [hMultiplicand + 1], a
+	ld a, d
+	ld [hMultiplicand + 2], a
+	ld [hMultiplier], a
+	jp Multiply
+
+INCLUDE "data/growth_rates.asm"
--- /dev/null
+++ b/engine/init_map.asm
@@ -1,0 +1,103 @@
+ReanchorBGMap_NoOAMUpdate:: ; 6454
+	call DelayFrame
+	ld a, [hOAMUpdate]
+	push af
+
+	ld a, $1
+	ld [hOAMUpdate], a
+	ld a, [hBGMapMode]
+	push af
+	xor a
+	ld [hBGMapMode], a
+
+	call .ReanchorBGMap
+
+	pop af
+	ld [hBGMapMode], a
+	pop af
+	ld [hOAMUpdate], a
+	ld hl, VramState
+	set 6, [hl]
+	ret
+
+.ReanchorBGMap:
+	xor a
+	ld [hLCDCPointer], a
+	ld [hBGMapMode], a
+	ld a, $90
+	ld [hWY], a
+	call OverworldTextModeSwitch
+	ld a, VBGMap1 / $100
+	call .LoadBGMapAddrIntoHRAM
+	call _OpenAndCloseMenu_HDMATransferTileMapAndAttrMap
+	callba LoadOW_BGPal7
+	callba ApplyPals
+	ld a, $1
+	ld [hCGBPalUpdate], a
+	xor a
+	ld [hBGMapMode], a
+	ld [hWY], a
+	callba HDMATransfer_FillBGMap0WithBlack ; no need to farcall
+	ld a, VBGMap0 / $100
+	call .LoadBGMapAddrIntoHRAM
+	xor a
+	ld [wBGMapAnchor], a
+	ld a, VBGMap0 / $100
+	ld [wBGMapAnchor + 1], a
+	xor a
+	ld [hSCX], a
+	ld [hSCY], a
+	call ApplyBGMapAnchorToObjects
+	ret
+
+.LoadBGMapAddrIntoHRAM: ; 64b9
+	ld [hBGMapAddress + 1], a
+	xor a
+	ld [hBGMapAddress], a
+	ret
+
+LoadFonts_NoOAMUpdate:: ; 64bf
+	ld a, [hOAMUpdate]
+	push af
+	ld a, $1
+	ld [hOAMUpdate], a
+
+	call .LoadGFX
+
+	pop af
+	ld [hOAMUpdate], a
+	ret
+
+.LoadGFX:
+	call LoadFontsExtra
+	ld a, $90
+	ld [hWY], a
+	call SafeUpdateSprites
+	call LoadStandardFont
+	ret
+
+HDMATransfer_FillBGMap0WithBlack: ; 64db
+	ld a, [rSVBK]
+	push af
+	ld a, $6
+	ld [rSVBK], a
+
+	ld a, "<BLACK>" ; $60
+	ld hl, wDecompressScratch
+	ld bc, wScratchAttrMap - wDecompressScratch
+	call ByteFill
+	ld a, wDecompressScratch / $100
+	ld [rHDMA1], a
+	ld a, wDecompressScratch % $100
+	ld [rHDMA2], a
+	ld a, (VBGMap0 % $8000) / $100
+	ld [rHDMA3], a
+	ld a, (VBGMap0 % $8000) % $100
+	ld [rHDMA4], a
+	ld a, $3f
+	ld [hDMATransfer], a
+	call DelayFrame
+
+	pop af
+	ld [rSVBK], a
+	ret
--- a/engine/map_objects.asm
+++ b/engine/map_objects.asm
@@ -1,6 +1,4 @@
-
 INCLUDE "data/facings.asm"
-
 
 INCLUDE "data/map_objects.asm"
 
--- /dev/null
+++ b/engine/map_objects_2.asm
@@ -1,0 +1,70 @@
+LoadObjectMasks: ; 2454f
+	ld hl, wObjectMasks
+	xor a
+	ld bc, NUM_OBJECTS
+	call ByteFill
+	nop
+	ld bc, MapObjects
+	ld de, wObjectMasks
+	xor a
+.loop
+	push af
+	push bc
+	push de
+	call GetObjectTimeMask
+	jr c, .next
+	call CheckObjectFlag
+.next
+	pop de
+	ld [de], a
+	inc de
+	pop bc
+	ld hl, OBJECT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	pop af
+	inc a
+	cp NUM_OBJECTS
+	jr nz, .loop
+	ret
+
+CheckObjectFlag: ; 2457d (9:457d)
+	ld hl, MAPOBJECT_SPRITE
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .masked
+	ld hl, MAPOBJECT_EVENT_FLAG
+	add hl, bc
+	ld a, [hli]
+	ld e, a
+	ld a, [hl]
+	ld d, a
+	cp -1
+	jr nz, .check
+	ld a, e
+	cp -1
+	jr z, .unmasked
+	jr .masked
+.check
+	ld b, CHECK_FLAG
+	call EventFlagAction
+	ld a, c
+	and a
+	jr nz, .masked
+.unmasked
+	xor a
+	ret
+
+.masked
+	ld a, -1
+	scf
+	ret
+
+GetObjectTimeMask: ; 245a7 (9:45a7)
+	call CheckObjectTime
+	ld a, -1
+	ret c
+	xor a
+	ret
--- /dev/null
+++ b/engine/map_palettes.asm
@@ -1,0 +1,86 @@
+SwapTextboxPalettes:: ; 4c000
+	hlcoord 0, 0
+	decoord 0, 0, AttrMap
+	ld b, SCREEN_HEIGHT
+.loop
+	push bc
+	ld c, SCREEN_WIDTH
+.innerloop
+	ld a, [hl]
+	push hl
+	srl a
+	jr c, .UpperNybble
+	ld hl, TilesetPalettes
+	add [hl]
+	ld l, a
+	ld a, [TilesetPalettes + 1]
+	adc $0
+	ld h, a
+	ld a, [hl]
+	and $f
+	jr .next
+
+.UpperNybble:
+	ld hl, TilesetPalettes
+	add [hl]
+	ld l, a
+	ld a, [TilesetPalettes + 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, BGMapBuffer
+	ld de, BGMapPalBuffer
+.loop
+	ld a, [hl]
+	push hl
+	srl a
+	jr c, .UpperNybble
+
+; .LowerNybble
+	ld hl, TilesetPalettes
+	add [hl]
+	ld l, a
+	ld a, [TilesetPalettes + 1]
+	adc $0
+	ld h, a
+	ld a, [hl]
+	and $f
+	jr .next
+
+.UpperNybble:
+	ld hl, TilesetPalettes
+	add [hl]
+	ld l, a
+	ld a, [TilesetPalettes + 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/menu_2.asm
@@ -1,0 +1,263 @@
+PlaceMenuItemName: ; 0x24ab4
+	push de
+	ld a, [MenuSelection]
+	ld [wNamedObjectIndexBuffer], a
+	call GetItemName
+	pop hl
+	call PlaceString
+	ret
+
+PlaceMenuItemQuantity: ; 0x24ac3
+	push de
+	ld a, [MenuSelection]
+	ld [CurItem], a
+	callba _CheckTossableItem
+	ld a, [wItemAttributeParamBuffer]
+	pop hl
+	and a
+	jr nz, .done
+	ld de, $15
+	add hl, de
+	ld [hl], "×"
+	inc hl
+	ld de, MenuSelectionQuantity
+	lb bc, 1, 2
+	call PrintNum
+
+.done
+	ret
+
+PlaceMoneyTopRight: ; 24ae8
+	ld hl, MenuDataHeader_0x24b15
+	call CopyMenuDataHeader
+	jr PlaceMoneyDataHeader
+
+PlaceMoneyBottomLeft: ; 24af0
+	ld hl, MenuDataHeader_0x24b1d
+	call CopyMenuDataHeader
+	jr PlaceMoneyDataHeader
+
+PlaceMoneyAtTopLeftOfTextbox: ; 24af8
+	ld hl, MenuDataHeader_0x24b15
+	lb de, 0, 11
+	call OffsetMenuDataHeader
+
+PlaceMoneyDataHeader: ; 24b01
+	call MenuBox
+	call MenuBoxCoord2Tile
+	ld de, SCREEN_WIDTH + 1
+	add hl, de
+	ld de, Money
+	lb bc, PRINTNUM_MONEY | 3, 6
+	call PrintNum
+	ret
+
+MenuDataHeader_0x24b15: ; 0x24b15
+	db $40 ; flags
+	db 00, 11 ; start coords
+	db 02, 19 ; end coords
+	dw NULL
+	db 1 ; default option
+
+MenuDataHeader_0x24b1d: ; 0x24b1d
+	db $40 ; flags
+	db 11, 00 ; start coords
+	db 13, 08 ; end coords
+	dw NULL
+	db 1 ; default option
+
+Special_DisplayCoinCaseBalance: ; 24b25
+	; Place a text box of size 1x7 at 11, 0.
+	hlcoord 11, 0
+	ld b, 1
+	ld c, 7
+	call TextBox
+	hlcoord 12, 0
+	ld de, CoinString
+	call PlaceString
+	hlcoord 17, 1
+	ld de, ShowMoney_TerminatorString
+	call PlaceString
+	ld de, Coins
+	lb bc, 2, 4
+	hlcoord 13, 1
+	call PrintNum
+	ret
+
+Special_DisplayMoneyAndCoinBalance: ; 24b4e
+	hlcoord 5, 0
+	ld b, 3
+	ld c, 13
+	call TextBox
+	hlcoord 6, 1
+	ld de, MoneyString
+	call PlaceString
+	hlcoord 12, 1
+	ld de, Money
+	lb bc, PRINTNUM_MONEY | 3, 6
+	call PrintNum
+	hlcoord 6, 3
+	ld de, CoinString
+	call PlaceString
+	hlcoord 15, 3
+	ld de, Coins
+	lb bc, 2, 4
+	call PrintNum
+	ret
+
+MoneyString: ; 24b83
+	db "MONEY@"
+CoinString: ; 24b89
+	db "COIN@"
+ShowMoney_TerminatorString: ; 24b8e
+	db "@"
+
+Function24b8f: ; 24b8f
+; unreferenced, related to safari?
+	ld hl, Options
+	ld a, [hl]
+	push af
+	set NO_TEXT_SCROLL, [hl]
+	hlcoord 0, 0
+	ld b, 3
+	ld c, 7
+	call TextBox
+	hlcoord 1, 1
+	ld de, wSafariTimeRemaining
+	lb bc, 2, 3
+	call PrintNum
+	hlcoord 4, 1
+	ld de, .slash_500
+	call PlaceString
+	hlcoord 1, 3
+	ld de, .booru_ko
+	call PlaceString
+	hlcoord 5, 3
+	ld de, wSafariBallsRemaining
+	lb bc, 1, 2
+	call PrintNum
+	pop af
+	ld [Options], a
+	ret
+
+.slash_500 ; 24bcf
+	db "/500@"
+.booru_ko ; 24bd4
+	db "ボール   こ@"
+
+StartMenu_DrawBugContestStatusBox: ; 24bdc
+	hlcoord 0, 0
+	ld b, 5
+	ld c, 17
+	call TextBox
+	ret
+
+StartMenu_PrintBugContestStatus: ; 24be7
+	ld hl, Options
+	ld a, [hl]
+	push af
+	set NO_TEXT_SCROLL, [hl]
+	call StartMenu_DrawBugContestStatusBox
+	hlcoord 1, 5
+	ld de, .Balls_EN
+	call PlaceString
+	hlcoord 8, 5
+	ld de, wParkBallsRemaining
+	lb bc, PRINTNUM_RIGHTALIGN | 1, 2
+	call PrintNum
+	hlcoord 1, 1
+	ld de, .CAUGHT
+	call PlaceString
+	ld a, [wContestMon]
+	and a
+	ld de, .None
+	jr z, .no_contest_mon
+	ld [wd265], a
+	call GetPokemonName
+
+.no_contest_mon
+	hlcoord 8, 1
+	call PlaceString
+	ld a, [wContestMon]
+	and a
+	jr z, .skip_level
+	hlcoord 1, 3
+	ld de, .LEVEL
+	call PlaceString
+	ld a, [wContestMonLevel]
+	ld h, b
+	ld l, c
+	inc hl
+	ld c, 3
+	call Print8BitNumRightAlign
+
+.skip_level
+	pop af
+	ld [Options], a
+	ret
+
+.Balls_JP: ; 24c43
+	db "ボール   こ@"
+.CAUGHT: ; 24c4b
+	db "CAUGHT@"
+.Balls_EN: ; 24c52
+	db "BALLS:@"
+.None: ; 24c59
+	db "None@"
+.LEVEL: ; 24c5e
+	db "LEVEL@"
+
+FindApricornsInBag: ; 24c64
+; Checks the bag for Apricorns.
+	ld hl, Buffer1
+	xor a
+	ld [hli], a
+	dec a
+	ld bc, 10
+	call ByteFill
+
+	ld hl, .ApricornBalls
+.loop
+	ld a, [hl]
+	cp -1
+	jr z, .done
+	push hl
+	ld [CurItem], a
+	ld hl, NumItems
+	call CheckItem
+	pop hl
+	jr nc, .nope
+	ld a, [hl]
+	call .addtobuffer
+.nope
+	inc hl
+	inc hl
+	jr .loop
+
+.done
+	ld a, [Buffer1]
+	and a
+	ret nz
+	scf
+	ret
+
+.addtobuffer ; 24c94
+	push hl
+	ld hl, Buffer1
+	inc [hl]
+	ld e, [hl]
+	ld d, 0
+	add hl, de
+	ld [hl], a
+	pop hl
+	ret
+
+.ApricornBalls: ; 24ca0
+	db RED_APRICORN, LEVEL_BALL
+	db BLU_APRICORN, LURE_BALL
+	db YLW_APRICORN, MOON_BALL
+	db GRN_APRICORN, FRIEND_BALL
+	db WHT_APRICORN, FAST_BALL
+	db BLK_APRICORN, HEAVY_BALL
+	db PNK_APRICORN, LOVE_BALL
+	db -1
--- /dev/null
+++ b/engine/mon_stats.asm
@@ -1,0 +1,486 @@
+DrawPlayerHP: ; 50b0a
+	ld a, $1
+	jr DrawHP
+
+DrawEnemyHP: ; 50b0e
+	ld a, $2
+
+DrawHP: ; 50b10
+	ld [wWhichHPBar], a
+	push hl
+	push bc
+	; box mons have full HP
+	ld a, [MonType]
+	cp BOXMON
+	jr z, .at_least_1_hp
+
+	ld a, [TempMonHP]
+	ld b, a
+	ld a, [TempMonHP + 1]
+	ld c, a
+
+; Any HP?
+	or b
+	jr nz, .at_least_1_hp
+
+	xor a
+	ld c, a
+	ld e, a
+	ld a, 6
+	ld d, a
+	jp .fainted
+
+.at_least_1_hp
+	ld a, [TempMonMaxHP]
+	ld d, a
+	ld a, [TempMonMaxHP + 1]
+	ld e, a
+	ld a, [MonType]
+	cp BOXMON
+	jr nz, .not_boxmon
+
+	ld b, d
+	ld c, e
+
+.not_boxmon
+	predef ComputeHPBarPixels
+	ld a, 6
+	ld d, a
+	ld c, a
+
+.fainted
+	ld a, c
+	pop bc
+	ld c, a
+	pop hl
+	push de
+	push hl
+	push hl
+	call DrawBattleHPBar
+	pop hl
+
+; Print HP
+	bccoord 1, 1, 0
+	add hl, bc
+	ld de, TempMonHP
+	ld a, [MonType]
+	cp BOXMON
+	jr nz, .not_boxmon_2
+	ld de, TempMonMaxHP
+.not_boxmon_2
+	lb bc, 2, 3
+	call PrintNum
+
+	ld a, "/"
+	ld [hli], a
+
+; Print max HP
+	ld de, TempMonMaxHP
+	lb bc, 2, 3
+	call PrintNum
+	pop hl
+	pop de
+	ret
+
+PrintTempMonStats: ; 50b7b
+; Print TempMon's stats at hl, with spacing bc.
+	push bc
+	push hl
+	ld de, .StatNames
+	call PlaceString
+	pop hl
+	pop bc
+	add hl, bc
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	ld de, TempMonAttack
+	lb bc, 2, 3
+	call .PrintStat
+	ld de, TempMonDefense
+	call .PrintStat
+	ld de, TempMonSpclAtk
+	call .PrintStat
+	ld de, TempMonSpclDef
+	call .PrintStat
+	ld de, TempMonSpeed
+	jp PrintNum
+
+.PrintStat: ; 50bab
+	push hl
+	call PrintNum
+	pop hl
+	ld de, SCREEN_WIDTH * 2
+	add hl, de
+	ret
+
+.StatNames: ; 50bb5
+	db   "ATTACK"
+	next "DEFENSE"
+	next "SPCL.ATK"
+	next "SPCL.DEF"
+	next "SPEED"
+	next "@"
+
+GetGender: ; 50bdd
+; Return the gender of a given monster (CurPartyMon/CurOTMon/CurWildMon).
+; When calling this function, a should be set to an appropriate MonType value.
+
+; return values:
+; a = 1: f = nc|nz; male
+; a = 0: f = nc|z;  female
+;        f = c:  genderless
+
+; This is determined by comparing the Attack and Speed DVs
+; with the species' gender ratio.
+
+; Figure out what type of monster struct we're looking at.
+
+; 0: PartyMon
+	ld hl, PartyMon1DVs
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, [MonType]
+	and a
+	jr z, .PartyMon
+
+; 1: OTPartyMon
+	ld hl, OTPartyMon1DVs
+	dec a
+	jr z, .PartyMon
+
+; 2: sBoxMon
+	ld hl, sBoxMon1DVs
+	ld bc, BOXMON_STRUCT_LENGTH
+	dec a
+	jr z, .sBoxMon
+
+; 3: Unknown
+	ld hl, TempMonDVs
+	dec a
+	jr z, .DVs
+
+; else: WildMon
+	ld hl, EnemyMonDVs
+	jr .DVs
+
+; Get our place in the party/box.
+
+.PartyMon:
+.sBoxMon
+	ld a, [CurPartyMon]
+	call AddNTimes
+
+.DVs:
+
+; sBoxMon data is read directly from SRAM.
+	ld a, [MonType]
+	cp BOXMON
+	ld a, 1
+	call z, GetSRAMBank
+
+; Attack DV
+	ld a, [hli]
+	and $f0
+	ld b, a
+; Speed DV
+	ld a, [hl]
+	and $f0
+	swap a
+
+; Put our DVs together.
+	or b
+	ld b, a
+
+; Close SRAM if we were dealing with a sBoxMon.
+	ld a, [MonType]
+	cp BOXMON
+	call z, CloseSRAM
+
+; We need the gender ratio to do anything with this.
+	push bc
+	ld a, [CurPartySpecies]
+	dec a
+	ld hl, BaseData + BASE_GENDER
+	ld bc, BASE_DATA_SIZE
+	call AddNTimes
+	pop bc
+
+	ld a, BANK(BaseData)
+	call GetFarByte
+
+; The higher the ratio, the more likely the monster is to be female.
+
+	cp GENDERLESS
+	jr z, .Genderless
+
+	and a ; GENDER_F0?
+	jr z, .Male
+
+	cp GENDER_F100
+	jr z, .Female
+
+; Values below the ratio are male, and vice versa.
+	cp b
+	jr c, .Male
+
+.Female:
+	xor a
+	ret
+
+.Male:
+	ld a, 1
+	and a
+	ret
+
+.Genderless:
+	scf
+	ret
+
+ListMovePP: ; 50c50
+	ld a, [wNumMoves]
+	inc a
+	ld c, a
+	ld a, NUM_MOVES
+	sub c
+	ld b, a
+	push hl
+	ld a, [Buffer1]
+	ld e, a
+	ld d, $0
+	ld a, $3e ; P
+	call .load_loop
+	ld a, b
+	and a
+	jr z, .skip
+	ld c, a
+	ld a, "-"
+	call .load_loop
+
+.skip
+	pop hl
+	inc hl
+	inc hl
+	inc hl
+	ld d, h
+	ld e, l
+	ld hl, TempMonMoves
+	ld b, 0
+.loop
+	ld a, [hli]
+	and a
+	jr z, .done
+	push bc
+	push hl
+	push de
+	ld hl, wMenuCursorY
+	ld a, [hl]
+	push af
+	ld [hl], b
+	push hl
+	callab GetMaxPPOfMove
+	pop hl
+	pop af
+	ld [hl], a
+	pop de
+	pop hl
+	push hl
+	ld bc, TempMonPP - (TempMonMoves + 1)
+	add hl, bc
+	ld a, [hl]
+	and $3f
+	ld [StringBuffer1 + 4], a
+	ld h, d
+	ld l, e
+	push hl
+	ld de, StringBuffer1 + 4
+	lb bc, 1, 2
+	call PrintNum
+	ld a, "/"
+	ld [hli], a
+	ld de, wd265
+	lb bc, 1, 2
+	call PrintNum
+	pop hl
+	ld a, [Buffer1]
+	ld e, a
+	ld d, 0
+	add hl, de
+	ld d, h
+	ld e, l
+	pop hl
+	pop bc
+	inc b
+	ld a, b
+	cp NUM_MOVES
+	jr nz, .loop
+
+.done
+	ret
+
+.load_loop ; 50cc9
+	ld [hli], a
+	ld [hld], a
+	add hl, de
+	dec c
+	jr nz, .load_loop
+	ret
+
+Function50cd0: ; 50cd0
+; XXX
+.loop
+	ld [hl], $32
+	inc hl
+	ld [hl], $3e
+	dec hl
+	add hl, de
+	dec c
+	jr nz, .loop
+	ret
+
+Predef22: ; unreferenced predef
+	push hl
+	push hl
+	ld hl, PartyMonNicknames
+	ld a, [CurPartyMon]
+	call GetNick
+	pop hl
+	call PlaceString
+	call CopyPkmnToTempMon
+	pop hl
+	ld a, [CurPartySpecies]
+	cp EGG
+	jr z, .egg
+	push hl
+	ld bc, -12
+	add hl, bc
+	ld b, $0
+	call DrawEnemyHP
+	pop hl
+	ld bc, 5
+	add hl, bc
+	push de
+	call PrintLevel
+	pop de
+
+.egg
+	ret
+
+PlaceStatusString: ; 50d0a
+	push de
+	inc de
+	inc de
+	ld a, [de]
+	ld b, a
+	inc de
+	ld a, [de]
+	or b
+	pop de
+	jr nz, PlaceNonFaintStatus
+	push de
+	ld de, FntString
+	call CopyStatusString
+	pop de
+	ld a, $1
+	and a
+	ret
+
+FntString: ; 50d22
+	db "FNT@"
+
+CopyStatusString: ; 50d25
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	ld [hl], a
+	ret
+
+PlaceNonFaintStatus: ; 50d2e
+	push de
+	ld a, [de]
+	ld de, PsnString
+	bit PSN, a
+	jr nz, .place
+	ld de, BrnString
+	bit BRN, a
+	jr nz, .place
+	ld de, FrzString
+	bit FRZ, a
+	jr nz, .place
+	ld de, ParString
+	bit PAR, a
+	jr nz, .place
+	ld de, SlpString
+	and SLP
+	jr z, .no_status
+
+.place
+	call CopyStatusString
+	ld a, $1
+	and a
+
+.no_status
+	pop de
+	ret
+
+SlpString: db "SLP@"
+PsnString: db "PSN@"
+BrnString: db "BRN@"
+FrzString: db "FRZ@"
+ParString: db "PAR@"
+
+ListMoves: ; 50d6f
+; List moves at hl, spaced every [Buffer1] tiles.
+	ld de, wListMoves_MoveIndicesBuffer
+	ld b, $0
+.moves_loop
+	ld a, [de]
+	inc de
+	and a
+	jr z, .no_more_moves
+	push de
+	push hl
+	push hl
+	ld [CurSpecies], a
+	ld a, MOVE_NAME
+	ld [wNamedObjectTypeBuffer], a
+	call GetName
+	ld de, StringBuffer1
+	pop hl
+	push bc
+	call PlaceString
+	pop bc
+	ld a, b
+	ld [wNumMoves], a
+	inc b
+	pop hl
+	push bc
+	ld a, [Buffer1]
+	ld c, a
+	ld b, 0
+	add hl, bc
+	pop bc
+	pop de
+	ld a, b
+	cp NUM_MOVES
+	jr z, .done
+	jr .moves_loop
+
+.no_more_moves
+	ld a, b
+.nonmove_loop
+	push af
+	ld [hl], "-"
+	ld a, [Buffer1]
+	ld c, a
+	ld b, 0
+	add hl, bc
+	pop af
+	inc a
+	cp NUM_MOVES
+	jr nz, .nonmove_loop
+
+.done
+	ret
--- /dev/null
+++ b/engine/player_gfx.asm
@@ -1,0 +1,263 @@
+Function88248: ; 88248
+; XXX
+	ld c, CAL
+	ld a, [PlayerGender]
+	bit 0, a
+	jr z, .okay
+	ld c, KAREN
+
+.okay
+	ld a, c
+	ld [TrainerClass], a
+	ret
+
+MovePlayerPicRight: ; 88258
+	hlcoord 6, 4
+	ld de, 1
+	jr MovePlayerPic
+
+MovePlayerPicLeft: ; 88260
+	hlcoord 13, 4
+	ld de, -1
+	; fallthrough
+
+MovePlayerPic: ; 88266
+; Move player pic at hl by de * 7 tiles.
+	ld c, $8
+.loop
+	push bc
+	push hl
+	push de
+	xor a
+	ld [hBGMapMode], a
+	lb bc, 7, 7
+	predef PlaceGraphic
+	xor a
+	ld [hBGMapThird], a
+	call WaitBGMap
+	call DelayFrame
+	pop de
+	pop hl
+	add hl, de
+	pop bc
+	dec c
+	ret z
+	push hl
+	push bc
+	ld a, l
+	sub e
+	ld l, a
+	ld a, h
+	sbc d
+	ld h, a
+	lb bc, 7, 7
+	call ClearBox
+	pop bc
+	pop hl
+	jr .loop
+
+ShowPlayerNamingChoices: ; 88297
+	ld hl, ChrisNameMenuHeader
+	ld a, [PlayerGender]
+	bit 0, a
+	jr z, .GotGender
+	ld hl, KrisNameMenuHeader
+.GotGender:
+	call LoadMenuDataHeader
+	call VerticalMenu
+	ld a, [wMenuCursorY]
+	dec a
+	call CopyNameFromMenu
+	call CloseWindow
+	ret
+
+ChrisNameMenuHeader: ; 882b5
+	db $40 ; flags
+	db 00, 00 ; start coords
+	db 11, 10 ; end coords
+	dw .MaleNames
+	db 1 ; ????
+	db 0 ; default option
+
+.MaleNames: ; 882be
+	db $91 ; flags
+	db 5 ; items
+	db "NEW NAME@"
+MalePlayerNameArray: ; 882c9
+	db "CHRIS@"
+	db "MAT@"
+	db "ALLAN@"
+	db "JON@"
+	db 2 ; displacement
+	db " NAME @" ; title
+
+KrisNameMenuHeader: ; 882e5
+	db $40 ; flags
+	db 00, 00 ; start coords
+	db 11, 10 ; end coords
+	dw .FemaleNames
+	db 1 ; ????
+	db 0 ; default option
+
+.FemaleNames: ; 882ee
+	db $91 ; flags
+	db 5 ; items
+	db "NEW NAME@"
+FemalePlayerNameArray: ; 882f9
+	db "KRIS@"
+	db "AMANDA@"
+	db "JUANA@"
+	db "JODI@"
+	db 2 ; displacement
+	db " NAME @" ; title
+
+GetPlayerNameArray: ; 88318 This Function is never called
+	ld hl, PlayerName
+	ld de, MalePlayerNameArray
+	ld a, [PlayerGender]
+	bit 0, a
+	jr z, .done
+	ld de, FemalePlayerNameArray
+
+.done
+	call InitName
+	ret
+
+GetPlayerIcon: ; 8832c
+; Get the player icon corresponding to gender
+
+; Male
+	ld de, ChrisSpriteGFX
+	ld b, BANK(ChrisSpriteGFX)
+
+	ld a, [PlayerGender]
+	bit 0, a
+	jr z, .done
+
+; Female
+	ld de, KrisSpriteGFX
+	ld b, BANK(KrisSpriteGFX)
+
+.done
+	ret
+
+GetCardPic: ; 8833e
+	ld hl, ChrisCardPic
+	ld a, [PlayerGender]
+	bit 0, a
+	jr z, .GotClass
+	ld hl, KrisCardPic
+.GotClass:
+	ld de, VTiles2 tile $00
+	ld bc, $23 tiles
+	ld a, BANK(ChrisCardPic) ; BANK(KrisCardPic)
+	call FarCopyBytes
+	ld hl, CardGFX
+	ld de, VTiles2 tile $23
+	ld bc, 6 tiles
+	ld a, BANK(CardGFX)
+	call FarCopyBytes
+	ret
+
+ChrisCardPic: ; 88365
+INCBIN "gfx/trainer_card/chris_card.2bpp"
+
+KrisCardPic: ; 88595
+INCBIN "gfx/trainer_card/kris_card.2bpp"
+
+CardGFX: ; 887c5
+INCBIN "gfx/trainer_card/trainer_card.2bpp"
+
+GetPlayerBackpic: ; 88825
+	ld a, [PlayerGender]
+	bit 0, a
+	jr z, GetChrisBackpic
+	call GetKrisBackpic
+	ret
+
+GetChrisBackpic: ; 88830
+	ld hl, ChrisBackpic
+	ld b, BANK(ChrisBackpic)
+	ld de, VTiles2 tile $31
+	ld c, 7 * 7
+	predef DecompressPredef
+	ret
+
+HOF_LoadTrainerFrontpic: ; 88840
+	call WaitBGMap
+	xor a
+	ld [hBGMapMode], a
+	ld e, 0
+	ld a, [PlayerGender]
+	bit 0, a
+	jr z, .GotClass
+	ld e, 1
+
+.GotClass:
+	ld a, e
+	ld [TrainerClass], a
+	ld de, ChrisPic
+	ld a, [PlayerGender]
+	bit 0, a
+	jr z, .GotPic
+	ld de, KrisPic
+
+.GotPic:
+	ld hl, VTiles2
+	ld b, BANK(ChrisPic) ; BANK(KrisPic)
+	ld c, 7 * 7
+	call Get2bpp
+	call WaitBGMap
+	ld a, $1
+	ld [hBGMapMode], a
+	ret
+
+DrawIntroPlayerPic: ; 88874
+; Draw the player pic at (6,4).
+
+; Get class
+	ld e, CHRIS
+	ld a, [PlayerGender]
+	bit 0, a
+	jr z, .GotClass
+	ld e, KRIS
+.GotClass:
+	ld a, e
+	ld [TrainerClass], a
+
+; Load pic
+	ld de, ChrisPic
+	ld a, [PlayerGender]
+	bit 0, a
+	jr z, .GotPic
+	ld de, KrisPic
+.GotPic:
+	ld hl, VTiles2
+	ld b, BANK(ChrisPic) ; BANK(KrisPic)
+	ld c, 7 * 7 ; dimensions
+	call Get2bpp
+
+; Draw
+	xor a
+	ld [hGraphicStartTile], a
+	hlcoord 6, 4
+	lb bc, 7, 7
+	predef PlaceGraphic
+	ret
+
+ChrisPic: ; 888a9
+INCBIN "gfx/player/chris.2bpp"
+
+KrisPic: ; 88bb9
+INCBIN "gfx/player/kris.2bpp"
+
+GetKrisBackpic: ; 88ec9
+; Kris's backpic is uncompressed.
+	ld de, KrisBackpic
+	ld hl, VTiles2 tile $31
+	lb bc, BANK(KrisBackpic), 7 * 7 ; dimensions
+	call Get2bpp
+	ret
+
+KrisBackpic: ; 88ed6
+INCBIN "gfx/player/kris_back.2bpp"
--- /dev/null
+++ b/engine/pokedex_3.asm
@@ -1,0 +1,162 @@
+LoadSGBPokedexGFX: ; 1ddf1c
+	ld hl, SGBPokedexGFX_LZ
+	ld de, VTiles2 tile $31
+	call Decompress
+	ret
+
+LoadSGBPokedexGFX2: ; 1ddf26 (77:5f26)
+	ld hl, SGBPokedexGFX_LZ
+	ld de, VTiles2 tile $31
+	lb bc, BANK(SGBPokedexGFX_LZ), $3a
+	call DecompressRequest2bpp
+	ret
+
+SGBPokedexGFX_LZ: ; 1ddf33
+INCBIN "gfx/pokedex/sgb.2bpp.lz"
+
+LoadQuestionMarkPic: ; 1de0d7
+	ld hl, .QuestionMarkLZ
+	ld de, sScratch
+	call Decompress
+	ret
+
+.QuestionMarkLZ: ; 1de0e1
+INCBIN "gfx/pics/questionmark/front.2bpp.lz"
+
+DrawPokedexListWindow: ; 1de171 (77:6171)
+	ld a, $32
+	hlcoord 0, 17
+	ld bc, 12
+	call ByteFill
+	hlcoord 0, 1
+	lb bc, 15, 11
+	call ClearBox
+	ld a, $34
+	hlcoord 0, 0
+	ld bc, 11
+	call ByteFill
+	ld a, $39
+	hlcoord 0, 16
+	ld bc, 11
+	call ByteFill
+	hlcoord 5, 0
+	ld [hl], $3f
+	hlcoord 5, 16
+	ld [hl], $40
+	ld a, [wCurrentDexMode]
+	cp DEXMODE_OLD
+	jr z, .OldMode
+; scroll bar
+	hlcoord 11, 0
+	ld [hl], $50
+	ld a, $51
+	hlcoord 11, 1
+	ld b, SCREEN_HEIGHT - 3
+	call Bank77_FillColumn
+	ld [hl], $52
+	jr .Done
+
+.OldMode:
+; no scroll bar
+	hlcoord 11, 0
+	ld [hl], $66
+	ld a, $67
+	hlcoord 11, 1
+	ld b, SCREEN_HEIGHT - 3
+	call Bank77_FillColumn
+	ld [hl], $68
+.Done:
+	ret
+
+DrawPokedexSearchResultsWindow: ; 1de1d1 (77:61d1)
+	ld a, $34
+	hlcoord 0, 0
+	ld bc, 11
+	call ByteFill
+	ld a, $39
+	hlcoord 0, 10
+	ld bc, 11
+	call ByteFill
+	hlcoord 5, 0
+	ld [hl], $3f
+	hlcoord 5, 10
+	ld [hl], $40
+	hlcoord 11, 0
+	ld [hl], $66
+	ld a, $67
+	hlcoord 11, 1
+	ld b, SCREEN_HEIGHT / 2
+	call Bank77_FillColumn
+	ld [hl], $68
+	ld a, $34
+	hlcoord 0, 11
+	ld bc, 11
+	call ByteFill
+	ld a, $39
+	hlcoord 0, 17
+	ld bc, 11
+	call ByteFill
+	hlcoord 11, 11
+	ld [hl], $66
+	ld a, $67
+	hlcoord 11, 12
+	ld b, 5
+	call Bank77_FillColumn
+	ld [hl], $68
+	hlcoord 0, 12
+	lb bc, 5, 11
+	call ClearBox
+	ld de, .esults_D
+	hlcoord 0, 12
+	call PlaceString
+	ret
+
+.esults_D ; 1de23c
+; (SEARCH R)
+	db   "ESULTS"
+	next ""
+; (### FOUN)
+	next "D!@"
+
+DrawDexEntryScreenRightEdge: ; 1de247
+	ld a, [hBGMapAddress]
+	ld l, a
+	ld a, [hBGMapAddress + 1]
+	ld h, a
+	push hl
+	inc hl
+	ld a, l
+	ld [hBGMapAddress], a
+	ld a, h
+	ld [hBGMapAddress + 1], a
+	hlcoord 19, 0
+	ld [hl], $66
+	hlcoord 19, 1
+	ld a, $67
+	ld b, 15
+	call Bank77_FillColumn
+	ld [hl], $68
+	hlcoord 19, 17
+	ld [hl], $3c
+	xor a
+	ld b, SCREEN_HEIGHT
+	hlcoord 19, 0, AttrMap
+	call Bank77_FillColumn
+	call WaitBGMap2
+	pop hl
+	ld a, l
+	ld [hBGMapAddress], a
+	ld a, h
+	ld [hBGMapAddress + 1], a
+	ret
+
+Bank77_FillColumn: ; 1de27f
+	push de
+	ld de, SCREEN_WIDTH
+.loop
+	ld [hl], a
+	add hl, de
+	dec b
+	jr nz, .loop
+	pop de
+	ret
--- /dev/null
+++ b/engine/pokerus.asm
@@ -1,0 +1,160 @@
+GivePokerusAndConvertBerries: ; 2ed44
+	call ConvertBerriesToBerryJuice
+	ld hl, PartyMon1PokerusStatus
+	ld a, [PartyCount]
+	ld b, a
+	ld de, PARTYMON_STRUCT_LENGTH
+; Check to see if any of your Pokemon already has Pokerus.
+; If so, sample its spread through your party.
+; This means that you cannot get Pokerus de novo while
+; a party member has an active infection.
+.loopMons
+	ld a, [hl]
+	and $f
+	jr nz, .TrySpreadPokerus
+	add hl, de
+	dec b
+	jr nz, .loopMons
+
+; If we haven't been to Goldenrod City at least once,
+; prevent the contraction of Pokerus.
+	ld hl, StatusFlags2
+	bit 6, [hl]
+	ret z
+	call Random
+	ld a, [hRandomAdd]
+	and a
+	ret nz
+	ld a, [hRandomSub]
+	cp $3
+	ret nc                 ; 3/65536 chance (00 00, 00 01 or 00 02)
+	ld a, [PartyCount]
+	ld b, a
+.randomMonSelectLoop
+	call Random
+	and $7
+	cp b
+	jr nc, .randomMonSelectLoop
+	ld hl, PartyMon1PokerusStatus
+	call GetPartyLocation  ; get pokerus byte of random mon
+	ld a, [hl]
+	and $f0
+	ret nz                 ; if it already has pokerus, do nothing
+.randomPokerusLoop         ; Simultaneously sample the strain and duration
+	call Random
+	and a
+	jr z, .randomPokerusLoop
+	ld b, a
+	and $f0
+	jr z, .load_pkrs
+	ld a, b
+	and $7
+	inc a
+.load_pkrs
+	ld b, a ; this should come before the label
+	swap b
+	and $3
+	inc a
+	add b
+	ld [hl], a
+	ret
+
+.TrySpreadPokerus:
+	call Random
+	cp 1 + 33 percent
+	ret nc              ; 1/3 chance
+
+	ld a, [PartyCount]
+	cp 1
+	ret z               ; only one mon, nothing to do
+
+	ld c, [hl]
+	ld a, b
+	cp 2
+	jr c, .checkPreviousMonsLoop    ; no more mons after this one, go backwards
+
+	call Random
+	cp 1 + 50 percent
+	jr c, .checkPreviousMonsLoop    ; 1/2 chance, go backwards
+.checkFollowingMonsLoop
+	add hl, de
+	ld a, [hl]
+	and a
+	jr z, .infectMon
+	ld c, a
+	and $3
+	ret z               ; if mon has cured pokerus, stop searching
+	dec b               ; go on to next mon
+	ld a, b
+	cp 1
+	jr nz, .checkFollowingMonsLoop ; no more mons left
+	ret
+
+.checkPreviousMonsLoop
+	ld a, [PartyCount]
+	cp b
+	ret z               ; no more mons
+	ld a, l
+	sub e
+	ld l, a
+	ld a, h
+	sbc d
+	ld h, a
+	ld a, [hl]
+	and a
+	jr z, .infectMon
+	ld c, a
+	and $3
+	ret z               ; if mon has cured pokerus, stop searching
+	inc b               ; go on to next mon
+	jr .checkPreviousMonsLoop
+
+.infectMon
+	ld a, c
+	and $f0
+	ld b, a
+	ld a, c
+	swap a
+	and $3
+	inc a
+	add b
+	ld [hl], a
+	ret
+
+; any berry held by a Shuckle may be converted to berry juice
+ConvertBerriesToBerryJuice: ; 2ede6
+	ld hl, StatusFlags2
+	bit 6, [hl]
+	ret z
+	call Random
+	cp $10
+	ret nc              ; 1/16 chance
+	ld hl, PartyMons
+	ld a, [PartyCount]
+.partyMonLoop
+	push af
+	push hl
+	ld a, [hl]
+	cp SHUCKLE
+	jr nz, .loopMon
+	ld bc, MON_ITEM
+	add hl, bc
+	ld a, [hl]
+	cp BERRY
+	jr z, .convertToJuice
+
+.loopMon
+	pop hl
+	ld bc, PARTYMON_STRUCT_LENGTH
+	add hl, bc
+	pop af
+	dec a
+	jr nz, .partyMonLoop
+	ret
+
+.convertToJuice
+	ld a, BERRY_JUICE
+	ld [hl], a
+	pop hl
+	pop af
+	ret
--- /dev/null
+++ b/engine/pokerus_tick.asm
@@ -1,0 +1,26 @@
+ApplyPokerusTick: ; 13988
+; decreases all pokemon's pokerus counter by b. if the lower nybble reaches zero, the pokerus is cured.
+	ld hl, PartyMon1PokerusStatus ; PartyMon1 + MON_PKRS
+	ld a, [PartyCount]
+	and a
+	ret z ; make sure it's not wasting time on an empty party
+	ld c, a
+.loop
+	ld a, [hl]
+	and $f ; lower nybble is the number of days remaining
+	jr z, .next ; if already 0, skip
+	sub b ; subtract the number of days
+	jr nc, .ok ; max(result, 0)
+	xor a
+.ok
+	ld d, a ; back up this value because we need to preserve the strain (upper nybble)
+	ld a, [hl]
+	and $f0
+	add d
+	ld [hl], a ; this prevents a cured pokemon from recontracting pokerus
+.next
+	ld de, PARTYMON_STRUCT_LENGTH
+	add hl, de
+	dec c
+	jr nz, .loop
+	ret
--- /dev/null
+++ b/engine/square_root.asm
@@ -1,0 +1,30 @@
+GetSquareRoot: ; 13b87
+; Return the square root of de in b.
+
+; Rather than calculating the result, we take the index of the
+; first value in a table of squares that isn't lower than de.
+
+	ld hl, Squares
+	ld b, 0
+.loop
+; Make sure we don't go past the end of the table.
+	inc b
+	ld a, b
+	cp $ff
+	ret z
+
+; Iterate over the table until b**2 >= de.
+	ld a, [hli]
+	sub e
+	ld a, [hli]
+	sbc d
+
+	jr c, .loop
+	ret
+
+Squares: ; 13b98
+root	set 1
+	rept $ff
+	dw root*root
+root	set root+1
+	endr
--- /dev/null
+++ b/engine/start_battle.asm
@@ -1,0 +1,197 @@
+ShowLinkBattleParticipants: ; 2ee18
+; If we're not in a communications room,
+; we don't need to be here.
+	ld a, [wLinkMode]
+	and a
+	ret z
+
+	callba _ShowLinkBattleParticipants
+	ld c, 150
+	call DelayFrames
+	call ClearTileMap
+	call ClearSprites
+	ret
+
+FindFirstAliveMonAndStartBattle: ; 2ee2f
+	xor a
+	ld [hMapAnims], a
+	call DelayFrame
+	ld b, 6
+	ld hl, PartyMon1HP
+	ld de, PARTYMON_STRUCT_LENGTH - 1
+
+.loop
+	ld a, [hli]
+	or [hl]
+	jr nz, .okay
+	add hl, de
+	dec b
+	jr nz, .loop
+
+.okay
+	ld de, MON_LEVEL - MON_HP
+	add hl, de
+	ld a, [hl]
+	ld [BattleMonLevel], a
+	predef Predef_StartBattle
+	callba _LoadBattleFontsHPBar
+	ld a, 1
+	ld [hBGMapMode], a
+	call ClearSprites
+	call ClearTileMap
+	xor a
+	ld [hBGMapMode], a
+	ld [hWY], a
+	ld [rWY], a
+	ld [hMapAnims], a
+	ret
+
+PlayBattleMusic: ; 2ee6c
+	push hl
+	push de
+	push bc
+
+	xor a
+	ld [MusicFade], a
+	ld de, MUSIC_NONE
+	call PlayMusic
+	call DelayFrame
+	call MaxVolume
+
+	ld a, [BattleType]
+	cp BATTLETYPE_SUICUNE
+	ld de, MUSIC_SUICUNE_BATTLE
+	jp z, .done
+	cp BATTLETYPE_ROAMING
+	jp z, .done
+
+	; Are we fighting a trainer?
+	ld a, [OtherTrainerClass]
+	and a
+	jr nz, .trainermusic
+
+	callba RegionCheck
+	ld a, e
+	and a
+	jr nz, .kantowild
+
+	ld de, MUSIC_JOHTO_WILD_BATTLE
+	ld a, [TimeOfDay]
+	cp NITE_F
+	jr nz, .done
+	ld de, MUSIC_JOHTO_WILD_BATTLE_NIGHT
+	jr .done
+
+.kantowild
+	ld de, MUSIC_KANTO_WILD_BATTLE
+	jr .done
+
+.trainermusic
+	ld de, MUSIC_CHAMPION_BATTLE
+	cp CHAMPION
+	jr z, .done
+	cp RED
+	jr z, .done
+
+	; really, they should have included admins and scientists here too...
+	ld de, MUSIC_ROCKET_BATTLE
+	cp GRUNTM
+	jr z, .done
+	cp GRUNTF
+	jr z, .done
+
+	ld de, MUSIC_KANTO_GYM_LEADER_BATTLE
+	callba IsKantoGymLeader
+	jr c, .done
+
+	ld de, MUSIC_JOHTO_GYM_LEADER_BATTLE
+	callba IsJohtoGymLeader
+	jr c, .done
+
+	ld de, MUSIC_RIVAL_BATTLE
+	ld a, [OtherTrainerClass]
+	cp RIVAL1
+	jr z, .done
+	cp RIVAL2
+	jr nz, .othertrainer
+
+	ld a, [OtherTrainerID]
+	cp RIVAL2_2_CHIKORITA ; Rival in Indigo Plateau
+	jr c, .done
+	ld de, MUSIC_CHAMPION_BATTLE
+	jr .done
+
+.othertrainer
+	ld a, [wLinkMode]
+	and a
+	jr nz, .johtotrainer
+
+	callba RegionCheck
+	ld a, e
+	and a
+	jr nz, .kantotrainer
+
+.johtotrainer
+	ld de, MUSIC_JOHTO_TRAINER_BATTLE
+	jr .done
+
+.kantotrainer
+	ld de, MUSIC_KANTO_TRAINER_BATTLE
+
+.done
+	call PlayMusic
+
+	pop bc
+	pop de
+	pop hl
+	ret
+
+ClearBattleRAM: ; 2ef18
+	xor a
+	ld [wPlayerAction], a
+	ld [wBattleResult], a
+
+	ld hl, wPartyMenuCursor
+	ld [hli], a
+	ld [hli], a
+	ld [hli], a
+	ld [hl], a
+
+	ld [wMenuScrollPosition], a
+	ld [CriticalHit], a
+	ld [BattleMonSpecies], a
+	ld [wBattleParticipantsNotFainted], a
+	ld [CurBattleMon], a
+	ld [wForcedSwitch], a
+	ld [TimeOfDayPal], a
+	ld [PlayerTurnsTaken], a
+	ld [EnemyTurnsTaken], a
+	ld [EvolvableFlags], a
+
+	ld hl, PlayerHPPal
+	ld [hli], a
+	ld [hl], a
+
+	ld hl, BattleMonDVs
+	ld [hli], a
+	ld [hl], a
+
+	ld hl, EnemyMonDVs
+	ld [hli], a
+	ld [hl], a
+
+; Clear the entire BattleMons area
+	ld hl, wBattle
+	ld bc, wBattleEnd - wBattle
+	xor a
+	call ByteFill
+
+	callab ResetEnemyStatLevels
+
+	call ClearWindowData
+
+	ld hl, hBGMapAddress
+	xor a
+	ld [hli], a
+	ld [hl], VBGMap0 / $100
+	ret
--- a/engine/timeofdaypals.asm
+++ b/engine/timeofdaypals.asm
@@ -1,3 +1,7 @@
+Predef35: ; 8c000
+Predef36:
+	ret
+
 UpdateTimeOfDayPal:: ; 8c001
 	call UpdateTime
 	ld a, [TimeOfDay]
--- /dev/null
+++ b/engine/trainer_scripts.asm
@@ -1,0 +1,31 @@
+TalkToTrainerScript:: ; 0xbe66a
+	faceplayer
+	trainerflagaction CHECK_FLAG
+	iftrue AlreadyBeatenTrainerScript
+	loadmemtrainer
+	encountermusic
+	jump StartBattleWithMapTrainerScript
+
+SeenByTrainerScript:: ; 0xbe675
+	loadmemtrainer
+	encountermusic
+	showemote EMOTE_SHOCK, LAST_TALKED, 30
+	callasm TrainerWalkToPlayer
+	applymovement2 MovementBuffer
+	writepersonxy LAST_TALKED
+	faceperson PLAYER, LAST_TALKED
+	jump StartBattleWithMapTrainerScript
+
+StartBattleWithMapTrainerScript: ; 0xbe68a
+	opentext
+	trainertext $0
+	waitbutton
+	closetext
+	loadmemtrainer
+	startbattle
+	reloadmapafterbattle
+	trainerflagaction SET_FLAG
+	loadvar wRunningTrainerBattleScript, -1
+
+AlreadyBeatenTrainerScript:
+	scripttalkafter
--- /dev/null
+++ b/engine/unused_correct_party.asm
@@ -1,0 +1,229 @@
+CorrectErrorsInPlayerParty: ; unreferenced
+	ld hl, PartyCount
+	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, PartyMon1Species
+	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, PartyMon1
+	ld a, [PartyCount]
+	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, PartySpecies
+	add hl, de
+	pop de
+	ld a, SMEARGLE
+	ld [hl], a
+
+.check_level
+	ld [CurSpecies], 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 [CurPartyLevel], 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, $1
+	predef CalcPkmnStats
+	pop hl
+	ld bc, PARTYMON_STRUCT_LENGTH
+	add hl, bc
+	pop de
+	inc e
+	dec d
+	jr nz, .loop2
+
+	ld de, PartyMonNicknames
+	ld a, [PartyCount]
+	ld b, a
+	ld c, 0
+.loop3
+	push bc
+	call .GetLengthOfStringWith6CharCap
+	push de
+	callba CheckStringForErrors
+	pop hl
+	pop bc
+	jr nc, .valid_nickname
+
+	push bc
+	push hl
+	ld hl, PartySpecies
+	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, StringBuffer1
+.got_nickname
+	pop de
+	ld bc, PKMN_NAME_LENGTH
+	call CopyBytes
+	pop bc
+
+.valid_nickname
+	inc c
+	dec b
+	jr nz, .loop3
+
+	ld de, PartyMonOT
+	ld a, [PartyCount]
+	ld b, a
+	ld c, 0
+.loop4
+	push bc
+	call .GetLengthOfStringWith6CharCap
+	push de
+	callba CheckStringForErrors
+	pop hl
+	jr nc, .valid_ot_name
+	ld d, h
+	ld e, l
+	ld hl, PlayerName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+.valid_ot_name
+	pop bc
+	inc c
+	dec b
+	jr nz, .loop4
+
+	ld hl, PartyMon1Moves
+	ld a, [PartyCount]
+	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
--- /dev/null
+++ b/event/bug_contest.asm
@@ -1,0 +1,43 @@
+Special_GiveParkBalls: ; 135db
+	xor a
+	ld [wContestMon], a
+	ld a, 20
+	ld [wParkBallsRemaining], a
+	callba StartBugContestTimer
+	ret
+
+BugCatchingContestBattleScript:: ; 0x135eb
+	writecode VAR_BATTLETYPE, BATTLETYPE_CONTEST
+	randomwildmon
+	startbattle
+	reloadmapafterbattle
+	copybytetovar wParkBallsRemaining
+	iffalse BugCatchingContestOutOfBallsScript
+	end
+
+BugCatchingContestOverScript:: ; 0x135f8
+	playsound SFX_ELEVATOR_END
+	opentext
+	writetext BugCatchingContestText_BeeepTimesUp
+	waitbutton
+	jump BugCatchingContestReturnToGateScript
+
+BugCatchingContestOutOfBallsScript: ; 0x13603
+	playsound SFX_ELEVATOR_END
+	opentext
+	writetext BugCatchingContestText_ContestIsOver
+	waitbutton
+
+BugCatchingContestReturnToGateScript: ; 0x1360b
+	closetext
+	jumpstd bugcontestresultswarp
+
+BugCatchingContestText_BeeepTimesUp: ; 0x1360f
+	; ANNOUNCER: BEEEP! Time's up!
+	text_jump UnknownText_0x1bd2ca
+	db "@"
+
+BugCatchingContestText_ContestIsOver: ; 0x13614
+	; ANNOUNCER: The Contest is over!
+	text_jump UnknownText_0x1bd2e7
+	db "@"
--- /dev/null
+++ b/event/bug_contest_mon_stats.asm
@@ -1,0 +1,107 @@
+DisplayCaughtContestMonStats: ; cc000
+	call ClearBGPalettes
+	call ClearTileMap
+	call ClearSprites
+	call LoadFontsBattleExtra
+
+	ld hl, Options
+	ld a, [hl]
+	push af
+	set 4, [hl]
+
+	hlcoord 0, 0
+	ld b, 4
+	ld c, 13
+	call TextBox
+
+	hlcoord 0, 6
+	ld b, 4
+	ld c, 13
+	call TextBox
+
+	hlcoord 2, 0
+	ld de, .Stock
+	call PlaceString
+
+	hlcoord 2, 6
+	ld de, .This
+	call PlaceString
+
+	hlcoord 5, 4
+	ld de, .Health
+	call PlaceString
+
+	hlcoord 5, 10
+	ld de, .Health
+	call PlaceString
+
+	ld a, [wContestMon]
+	ld [wd265], a
+	call GetPokemonName
+	ld de, StringBuffer1
+	hlcoord 1, 2
+	call PlaceString
+
+	ld h, b
+	ld l, c
+	ld a, [wContestMonLevel]
+	ld [TempMonLevel], a
+	call PrintLevel
+
+	ld de, EnemyMonNick
+	hlcoord 1, 8
+	call PlaceString
+
+	ld h, b
+	ld l, c
+	ld a, [EnemyMonLevel]
+	ld [TempMonLevel], a
+	call PrintLevel
+
+	hlcoord 11, 4
+	ld de, wContestMonMaxHP
+	lb bc, 2, 3
+	call PrintNum
+
+	hlcoord 11, 10
+	ld de, EnemyMonMaxHP
+	call PrintNum
+
+	ld hl, SwitchMonText
+	call PrintText
+
+	pop af
+	ld [Options], a
+
+	call WaitBGMap
+	ld b, SCGB_DIPLOMA
+	call GetSGBLayout
+	call SetPalettes
+	ret
+
+.Health:
+	db "HEALTH@"
+.Stock:
+	db " STOCK ", $4a, " @"
+.This:
+	db " THIS ", $4a, "  @"
+
+SwitchMonText: ; cc0c2
+	; Switch #MON?
+	text_jump UnknownText_0x1c10cf
+	db "@"
+
+DisplayAlreadyCaughtText: ; cc0c7
+	call GetPokemonName
+	ld hl, .AlreadyCaughtText
+	jp PrintText
+
+.AlreadyCaughtText: ; 0xcc0d0
+	; You already caught a @ .
+	text_jump UnknownText_0x1c10dd
+	db "@"
+
+Predef2F:
+Predef38:
+Predef39: ; cc0d5
+	ret
--- /dev/null
+++ b/event/catch_tutorial.asm
@@ -1,0 +1,81 @@
+CatchTutorial:: ; 4e554
+	ld a, [BattleType]
+	dec a
+	ld c, a
+	ld hl, .dw
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+.dw ; 4e564 (13:6564)
+	dw .DudeTutorial
+	dw .DudeTutorial
+	dw .DudeTutorial
+
+.DudeTutorial: ; 4e56a (13:656a)
+; Back up your name to your Mom's name.
+	ld hl, PlayerName
+	ld de, MomsName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+; Copy Dude's name to your name
+	ld hl, .Dude
+	ld de, PlayerName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+
+	call .LoadDudeData
+
+	xor a
+	ld [hJoyDown], a
+	ld [hJoyPressed], a
+	ld a, [Options]
+	push af
+	and $f8
+	add $3
+	ld [Options], a
+	ld hl, .AutoInput
+	ld a, BANK(.AutoInput)
+	call StartAutoInput
+	callab StartBattle
+	call StopAutoInput
+	pop af
+
+	ld [Options], a
+	ld hl, MomsName
+	ld de, PlayerName
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	ret
+
+.LoadDudeData: ; 4e5b7 (13:65b7)
+	ld hl, wDudeNumItems
+	ld [hl], 1
+	inc hl
+	ld [hl], POTION
+	inc hl
+	ld [hl], 1
+	inc hl
+	ld [hl], -1
+	ld hl, wDudeNumKeyItems
+	ld [hl], 0
+	inc hl
+	ld [hl], -1
+	ld hl, wDudeNumBalls
+	ld a, 1
+	ld [hli], a
+	ld a, POKE_BALL ; 5
+	ld [hli], a
+	ld [hli], a
+	ld [hl], -1
+	ret
+
+.Dude: ; 4e5da
+	db "DUDE@"
+
+.AutoInput: ; 4e5df
+	db NO_INPUT, $ff ; end
--- /dev/null
+++ b/event/catch_tutorial_input.asm
@@ -1,0 +1,43 @@
+_DudeAutoInput_A:: ; 1de28a
+	ld hl, DudeAutoInput_A
+	jr _DudeAutoInput
+
+_DudeAutoInput_RightA: ; 1de28f
+	ld hl, DudeAutoInput_RightA
+	jr _DudeAutoInput
+
+_DudeAutoInput_DownA: ; 1de294
+	ld hl, DudeAutoInput_DownA
+	jr _DudeAutoInput
+
+_DudeAutoInput: ; 1de299
+	ld a, BANK(DudeAutoInputs)
+	call StartAutoInput
+	ret
+
+DudeAutoInputs:
+
+DudeAutoInput_A: ; 1de29f
+	db NO_INPUT, $50
+	db A_BUTTON, $00
+	db NO_INPUT, $ff ; end
+
+DudeAutoInput_RightA: ; 1de2a5
+	db NO_INPUT, $08
+	db D_RIGHT,  $00
+	db NO_INPUT, $08
+	db A_BUTTON, $00
+	db NO_INPUT, $ff ; end
+
+DudeAutoInput_DownA: ; 1de2af
+	db NO_INPUT, $fe
+	db NO_INPUT, $fe
+	db NO_INPUT, $fe
+	db NO_INPUT, $fe
+	db D_DOWN,   $00
+	db NO_INPUT, $fe
+	db NO_INPUT, $fe
+	db NO_INPUT, $fe
+	db NO_INPUT, $fe
+	db A_BUTTON, $00
+	db NO_INPUT, $ff ; end
--- /dev/null
+++ b/event/hidden_items.asm
@@ -1,0 +1,51 @@
+RepelWoreOffScript:: ; 0x13619
+	opentext
+	writetext .text
+	waitbutton
+	closetext
+	end
+
+.text ; 0x13620
+	; REPEL's effect wore off.
+	text_jump UnknownText_0x1bd308
+	db "@"
+
+HiddenItemScript:: ; 0x13625
+	opentext
+	copybytetovar EngineBuffer3
+	itemtotext 0, 0
+	writetext .found_text
+	giveitem ITEM_FROM_MEM
+	iffalse .bag_full
+	callasm SetMemEvent
+	specialsound
+	itemnotify
+	jump .finish
+
+.bag_full ; 0x1363e
+	buttonsound
+	writetext .no_room_text
+	waitbutton
+
+.finish ; 13643
+	closetext
+	end
+
+.found_text ; 0x13645
+	; found @ !
+	text_jump UnknownText_0x1bd321
+	db "@"
+
+.no_room_text ; 0x1364a
+	; But   has no space left…
+	text_jump UnknownText_0x1bd331
+	db "@"
+
+SetMemEvent: ; 1364f
+	ld hl, EngineBuffer1
+	ld a, [hli]
+	ld d, [hl]
+	ld e, a
+	ld b, SET_FLAG
+	call EventFlagAction
+	ret
--- /dev/null
+++ b/event/lucky_number.asm
@@ -1,0 +1,226 @@
+Special_CheckForLuckyNumberWinners: ; 4d87a
+	xor a
+	ld [ScriptVar], a
+	ld [wFoundMatchingIDInParty], a
+	ld a, [PartyCount]
+	and a
+	ret z
+	ld d, a
+	ld hl, PartyMon1ID
+	ld bc, PartySpecies
+.PartyLoop:
+	ld a, [bc]
+	inc bc
+	cp EGG
+	call nz, .CompareLuckyNumberToMonID
+	push bc
+	ld bc, PARTYMON_STRUCT_LENGTH
+	add hl, bc
+	pop bc
+	dec d
+	jr nz, .PartyLoop
+	ld a, BANK(sBox)
+	call GetSRAMBank
+	ld a, [sBoxCount]
+	and a
+	jr z, .SkipOpenBox
+	ld d, a
+	ld hl, sBoxMon1ID
+	ld bc, sBoxSpecies
+.OpenBoxLoop:
+	ld a, [bc]
+	inc bc
+	cp EGG
+	jr z, .SkipOpenBoxMon
+	call .CompareLuckyNumberToMonID
+	jr nc, .SkipOpenBoxMon
+	ld a, 1
+	ld [wFoundMatchingIDInParty], a
+
+.SkipOpenBoxMon:
+	push bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	add hl, bc
+	pop bc
+	dec d
+	jr nz, .OpenBoxLoop
+
+.SkipOpenBox:
+	call CloseSRAM
+	ld c, $0
+.BoxesLoop:
+	ld a, [wCurBox]
+	and $f
+	cp c
+	jr z, .SkipBox
+	ld hl, .BoxBankAddresses
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	call GetSRAMBank
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a ; hl now contains the address of the loaded box in SRAM
+	ld a, [hl]
+	and a
+	jr z, .SkipBox ; no mons in this box
+	push bc
+	ld b, h
+	ld c, l
+	inc bc
+	ld de, sBoxMon1ID - sBox
+	add hl, de
+	ld d, a
+.BoxNLoop:
+	ld a, [bc]
+	inc bc
+	cp EGG
+	jr z, .SkipBoxMon
+
+	call .CompareLuckyNumberToMonID ; sets ScriptVar and CurPartySpecies appropriately
+	jr nc, .SkipBoxMon
+	ld a, 1
+	ld [wFoundMatchingIDInParty], a
+
+.SkipBoxMon:
+	push bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	add hl, bc
+	pop bc
+	dec d
+	jr nz, .BoxNLoop
+	pop bc
+
+.SkipBox:
+	inc c
+	ld a, c
+	cp NUM_BOXES
+	jr c, .BoxesLoop
+
+	call CloseSRAM
+	ld a, [ScriptVar]
+	and a
+	ret z ; found nothing
+	callba TrainerRankings_LuckyNumberShow
+	ld a, [wFoundMatchingIDInParty]
+	and a
+	push af
+	ld a, [CurPartySpecies]
+	ld [wNamedObjectIndexBuffer], a
+	call GetPokemonName
+	ld hl, .FoundPartymonText
+	pop af
+	jr z, .print
+	ld hl, .FoundBoxmonText
+
+.print
+	jp PrintText
+
+.CompareLuckyNumberToMonID: ; 4d939
+	push bc
+	push de
+	push hl
+	ld d, h
+	ld e, l
+	ld hl, Buffer1
+	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+	call PrintNum
+	ld hl, LuckyNumberDigit1Buffer
+	ld de, wLuckyIDNumber
+	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+	call PrintNum
+	ld b, 5
+	ld c, 0
+	ld hl, LuckyNumberDigit5Buffer
+	ld de, Buffer5
+.loop
+	ld a, [de]
+	cp [hl]
+	jr nz, .done
+	dec de
+	dec hl
+	inc c
+	dec b
+	jr nz, .loop
+
+.done
+	pop hl
+	push hl
+	ld de, -6
+	add hl, de
+	ld a, [hl]
+	pop hl
+	pop de
+	push af
+	ld a, c
+	ld b, 1
+	cp 5
+	jr z, .okay
+	ld b, 2
+	cp 3
+	jr nc, .okay
+	ld b, 3
+	cp 2
+	jr nz, .nomatch
+
+.okay
+	inc b
+	ld a, [ScriptVar]
+	and a
+	jr z, .bettermatch
+	cp b
+	jr c, .nomatch
+
+.bettermatch
+	dec b
+	ld a, b
+	ld [ScriptVar], a
+	pop bc
+	ld a, b
+	ld [CurPartySpecies], a
+	pop bc
+	scf
+	ret
+
+.nomatch
+	pop bc
+	pop bc
+	and a
+	ret
+
+.BoxBankAddresses: ; 4d99f
+	dba sBox1
+	dba sBox2
+	dba sBox3
+	dba sBox4
+	dba sBox5
+	dba sBox6
+	dba sBox7
+	dba sBox8
+	dba sBox9
+	dba sBox10
+	dba sBox11
+	dba sBox12
+	dba sBox13
+	dba sBox14
+
+.FoundPartymonText: ; 0x4d9c9
+	; Congratulations! We have a match with the ID number of @  in your party.
+	text_jump UnknownText_0x1c1261
+	db "@"
+
+.FoundBoxmonText: ; 0x4d9ce
+	; Congratulations! We have a match with the ID number of @  in your PC BOX.
+	text_jump UnknownText_0x1c12ae
+	db "@"
+
+Special_PrintTodaysLuckyNumber: ; 4d9d3
+	ld hl, StringBuffer3
+	ld de, wLuckyIDNumber
+	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
+	call PrintNum
+	ld a, "@"
+	ld [StringBuffer3 + 5], a
+	ret
--- /dev/null
+++ b/event/move_tutor.asm
@@ -1,0 +1,103 @@
+Special_MoveTutor: ; 4925b
+	call FadeToMenu
+	call ClearBGPalettes
+	call ClearScreen
+	call DelayFrame
+	ld b, SCGB_PACKPALS
+	call GetSGBLayout
+	xor a
+	ld [wItemAttributeParamBuffer], a
+	call .GetMoveTutorMove
+	ld [wd265], a
+	ld [wPutativeTMHMMove], a
+	call GetMoveName
+	call CopyName1
+	callba ChooseMonToLearnTMHM
+	jr c, .cancel
+	jr .enter_loop
+
+.loop
+	callba ChooseMonToLearnTMHM_NoRefresh
+	jr c, .cancel
+.enter_loop
+	call CheckCanLearnMoveTutorMove
+	jr nc, .loop
+	xor a
+	ld [ScriptVar], a
+	jr .quit
+
+.cancel
+	ld a, -1
+	ld [ScriptVar], a
+.quit
+	call CloseSubmenu
+	ret
+
+.GetMoveTutorMove: ; 492a5
+	ld a, [ScriptVar]
+	cp 1
+	jr z, .flamethrower
+	cp 2
+	jr z, .thunderbolt
+	ld a, ICE_BEAM
+	ret
+
+.flamethrower
+	ld a, FLAMETHROWER
+	ret
+
+.thunderbolt
+	ld a, THUNDERBOLT
+	ret
+
+CheckCanLearnMoveTutorMove: ; 492b9
+	ld hl, .MenuDataHeader
+	call LoadMenuDataHeader
+
+	predef CanLearnTMHMMove
+
+	push bc
+	ld a, [CurPartyMon]
+	ld hl, PartyMonNicknames
+	call GetNick
+	pop bc
+
+	ld a, c
+	and a
+	jr nz, .can_learn
+	push de
+	ld de, SFX_WRONG
+	call PlaySFX
+	pop de
+	ld a, BANK(Text_TMHMNotCompatible)
+	ld hl, Text_TMHMNotCompatible
+	call FarPrintText
+	jr .didnt_learn
+
+.can_learn
+	callab KnowsMove
+	jr c, .didnt_learn
+
+	predef LearnMove
+	ld a, b
+	and a
+	jr z, .didnt_learn
+
+	ld c, HAPPINESS_LEARNMOVE
+	callab ChangeHappiness
+	jr .learned
+
+.didnt_learn
+	call ExitMenu
+	and a
+	ret
+
+.learned
+	call ExitMenu
+	scf
+	ret
+
+.MenuDataHeader: ; 0x4930a
+	db $40 ; flags
+	db 12, 00 ; start coords
+	db 17, 19 ; end coords
--- a/event/special.asm
+++ b/event/special.asm
@@ -229,3 +229,7 @@
 	ld de, StringBuffer3
 	ld bc, PKMN_NAME_LENGTH
 	jp CopyBytes
+
+Predef1: ; 747a
+; not used
+	ret
--- /dev/null
+++ b/gfx/overworld_font.asm
@@ -1,0 +1,17 @@
+LoadOverworldFont:: ; 106594
+	ld de, .font
+	ld hl, VTiles1
+	lb bc, BANK(.font), $80
+	call Get2bpp
+	ld de, .space
+	ld hl, VTiles2 tile $7f
+	lb bc, BANK(.space), 1
+	call Get2bpp
+	ret
+; 1065ad
+
+.font
+INCBIN "gfx/font/overworld.2bpp"
+
+.space
+INCBIN "gfx/font/space.2bpp"
--- a/main.asm
+++ b/main.asm
@@ -51,190 +51,10 @@
 PushOAMEnd
 
 INCLUDE "engine/map_objects.asm"
-
 INCLUDE "engine/intro_menu.asm"
-
-ReanchorBGMap_NoOAMUpdate:: ; 6454
-	call DelayFrame
-	ld a, [hOAMUpdate]
-	push af
-
-	ld a, $1
-	ld [hOAMUpdate], a
-	ld a, [hBGMapMode]
-	push af
-	xor a
-	ld [hBGMapMode], a
-
-	call .ReanchorBGMap
-
-	pop af
-	ld [hBGMapMode], a
-	pop af
-	ld [hOAMUpdate], a
-	ld hl, VramState
-	set 6, [hl]
-	ret
-
-.ReanchorBGMap:
-	xor a
-	ld [hLCDCPointer], a
-	ld [hBGMapMode], a
-	ld a, $90
-	ld [hWY], a
-	call OverworldTextModeSwitch
-	ld a, VBGMap1 / $100
-	call .LoadBGMapAddrIntoHRAM
-	call _OpenAndCloseMenu_HDMATransferTileMapAndAttrMap
-	callba LoadOW_BGPal7
-	callba ApplyPals
-	ld a, $1
-	ld [hCGBPalUpdate], a
-	xor a
-	ld [hBGMapMode], a
-	ld [hWY], a
-	callba HDMATransfer_FillBGMap0WithBlack ; no need to farcall
-	ld a, VBGMap0 / $100
-	call .LoadBGMapAddrIntoHRAM
-	xor a
-	ld [wBGMapAnchor], a
-	ld a, VBGMap0 / $100
-	ld [wBGMapAnchor + 1], a
-	xor a
-	ld [hSCX], a
-	ld [hSCY], a
-	call ApplyBGMapAnchorToObjects
-	ret
-
-.LoadBGMapAddrIntoHRAM: ; 64b9
-	ld [hBGMapAddress + 1], a
-	xor a
-	ld [hBGMapAddress], a
-	ret
-
-LoadFonts_NoOAMUpdate:: ; 64bf
-	ld a, [hOAMUpdate]
-	push af
-	ld a, $1
-	ld [hOAMUpdate], a
-
-	call .LoadGFX
-
-	pop af
-	ld [hOAMUpdate], a
-	ret
-
-.LoadGFX:
-	call LoadFontsExtra
-	ld a, $90
-	ld [hWY], a
-	call SafeUpdateSprites
-	call LoadStandardFont
-	ret
-
-HDMATransfer_FillBGMap0WithBlack: ; 64db
-	ld a, [rSVBK]
-	push af
-	ld a, $6
-	ld [rSVBK], a
-
-	ld a, "<BLACK>" ; $60
-	ld hl, wDecompressScratch
-	ld bc, wScratchAttrMap - wDecompressScratch
-	call ByteFill
-	ld a, wDecompressScratch / $100
-	ld [rHDMA1], a
-	ld a, wDecompressScratch % $100
-	ld [rHDMA2], a
-	ld a, (VBGMap0 % $8000) / $100
-	ld [rHDMA3], a
-	ld a, (VBGMap0 % $8000) % $100
-	ld [rHDMA4], a
-	ld a, $3f
-	ld [hDMATransfer], a
-	call DelayFrame
-
-	pop af
-	ld [rSVBK], a
-	ret
-
+INCLUDE "engine/init_map.asm"
 INCLUDE "engine/learn.asm"
-
-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, PKMN_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 "<START>",  TX_BOX    + 1
-	db "<PLAY_G>", $18       + 1
-	db $1d,        "%"       + 1
-	db $35,        "<GREEN>" + 1
-	db "<ENEMY>",  "<ENEMY>" + 1
-	db "<MOM>",    "<TM>"    + 1
-	db "<ROCKET>", "┘"       + 1
-	db -1 ; end
-
+INCLUDE "engine/check_nick_errors.asm"
 INCLUDE "engine/math.asm"
 INCLUDE "data/items/item_attributes.asm"
 INCLUDE "engine/npc_movement.asm"
@@ -241,11 +61,7 @@
 INCLUDE "event/happiness_egg.asm"
 INCLUDE "event/special.asm"
 
-Predef1: ; 747a
-; not used
-	ret
 
-
 SECTION "bank2", ROMX
 
 INCLUDE "engine/player_object.asm"
@@ -256,26 +72,7 @@
 
 SECTION "bank3", ROMX
 
-CheckTime:: ; c000
-	ld a, [TimeOfDay]
-	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
-
+INCLUDE "engine/check_time.asm"
 INCLUDE "engine/specials.asm"
 INCLUDE "engine/printnum.asm"
 INCLUDE "engine/health.asm"
@@ -405,426 +202,16 @@
 INCLUDE "engine/startmenu.asm"
 INCLUDE "engine/selectmenu.asm"
 INCLUDE "event/elevator.asm"
-
-Special_GiveParkBalls: ; 135db
-	xor a
-	ld [wContestMon], a
-	ld a, 20
-	ld [wParkBallsRemaining], a
-	callba StartBugContestTimer
-	ret
-
-BugCatchingContestBattleScript:: ; 0x135eb
-	writecode VAR_BATTLETYPE, BATTLETYPE_CONTEST
-	randomwildmon
-	startbattle
-	reloadmapafterbattle
-	copybytetovar wParkBallsRemaining
-	iffalse BugCatchingContestOutOfBallsScript
-	end
-
-BugCatchingContestOverScript:: ; 0x135f8
-	playsound SFX_ELEVATOR_END
-	opentext
-	writetext BugCatchingContestText_BeeepTimesUp
-	waitbutton
-	jump BugCatchingContestReturnToGateScript
-
-BugCatchingContestOutOfBallsScript: ; 0x13603
-	playsound SFX_ELEVATOR_END
-	opentext
-	writetext BugCatchingContestText_ContestIsOver
-	waitbutton
-
-BugCatchingContestReturnToGateScript: ; 0x1360b
-	closetext
-	jumpstd bugcontestresultswarp
-
-BugCatchingContestText_BeeepTimesUp: ; 0x1360f
-	; ANNOUNCER: BEEEP! Time's up!
-	text_jump UnknownText_0x1bd2ca
-	db "@"
-
-BugCatchingContestText_ContestIsOver: ; 0x13614
-	; ANNOUNCER: The Contest is over!
-	text_jump UnknownText_0x1bd2e7
-	db "@"
-
-RepelWoreOffScript:: ; 0x13619
-	opentext
-	writetext .text
-	waitbutton
-	closetext
-	end
-
-.text ; 0x13620
-	; REPEL's effect wore off.
-	text_jump UnknownText_0x1bd308
-	db "@"
-
-HiddenItemScript:: ; 0x13625
-	opentext
-	copybytetovar EngineBuffer3
-	itemtotext 0, 0
-	writetext .found_text
-	giveitem ITEM_FROM_MEM
-	iffalse .bag_full
-	callasm SetMemEvent
-	specialsound
-	itemnotify
-	jump .finish
-
-.bag_full ; 0x1363e
-	buttonsound
-	writetext .no_room_text
-	waitbutton
-
-.finish ; 13643
-	closetext
-	end
-
-.found_text ; 0x13645
-	; found @ !
-	text_jump UnknownText_0x1bd321
-	db "@"
-
-.no_room_text ; 0x1364a
-	; But   has no space left…
-	text_jump UnknownText_0x1bd331
-	db "@"
-
-SetMemEvent: ; 1364f
-	ld hl, EngineBuffer1
-	ld a, [hli]
-	ld d, [hl]
-	ld e, a
-	ld b, SET_FLAG
-	call EventFlagAction
-	ret
-
-CheckFacingTileForStd:: ; 1365b
-; Checks to see if the tile you're facing has a std script associated with it.  If so, executes the script and returns carry.
-	ld a, c
-	ld de, 3
-	ld hl, TileCollisionStdScripts
-	call IsInArray
-	jr nc, .notintable
-
-	ld a, jumpstd_command
-	ld [wJumpStdScriptBuffer], a
-	inc hl
-	ld a, [hli]
-	ld [wJumpStdScriptBuffer + 1], a
-	ld a, [hli]
-	ld [wJumpStdScriptBuffer + 2], a
-	ld a, BANK(Script_JumpStdFromRAM)
-	ld hl, Script_JumpStdFromRAM
-	call CallScript
-	scf
-	ret
-
-.notintable
-	xor a
-	ret
-
-INCLUDE "data/collision_stdscripts.asm"
-
-Script_JumpStdFromRAM: ; 0x1369a
-	jump wJumpStdScriptBuffer
-
+INCLUDE "event/bug_contest.asm"
+INCLUDE "event/hidden_items.asm"
+INCLUDE "engine/collision_stdscripts.asm"
 INCLUDE "event/bug_contest_judging.asm"
-
-ApplyPokerusTick: ; 13988
-; decreases all pokemon's pokerus counter by b. if the lower nybble reaches zero, the pokerus is cured.
-	ld hl, PartyMon1PokerusStatus ; PartyMon1 + MON_PKRS
-	ld a, [PartyCount]
-	and a
-	ret z ; make sure it's not wasting time on an empty party
-	ld c, a
-.loop
-	ld a, [hl]
-	and $f ; lower nybble is the number of days remaining
-	jr z, .next ; if already 0, skip
-	sub b ; subtract the number of days
-	jr nc, .ok ; max(result, 0)
-	xor a
-.ok
-	ld d, a ; back up this value because we need to preserve the strain (upper nybble)
-	ld a, [hl]
-	and $f0
-	add d
-	ld [hl], a ; this prevents a cured pokemon from recontracting pokerus
-.next
-	ld de, PARTYMON_STRUCT_LENGTH
-	add hl, de
-	dec c
-	jr nz, .loop
-	ret
-
+INCLUDE "engine/pokerus_tick.asm"
 INCLUDE "event/bug_contest_2.asm"
+INCLUDE "engine/unused_correct_party.asm"
+INCLUDE "engine/square_root.asm"
 
-CorrectErrorsInPlayerParty: ; unreferenced
-	ld hl, PartyCount
-	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, PartyMon1Species
-	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, PartyMon1
-	ld a, [PartyCount]
-	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, PartySpecies
-	add hl, de
-	pop de
-	ld a, SMEARGLE
-	ld [hl], a
-
-.check_level
-	ld [CurSpecies], 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 [CurPartyLevel], 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, $1
-	predef CalcPkmnStats
-	pop hl
-	ld bc, PARTYMON_STRUCT_LENGTH
-	add hl, bc
-	pop de
-	inc e
-	dec d
-	jr nz, .loop2
-
-	ld de, PartyMonNicknames
-	ld a, [PartyCount]
-	ld b, a
-	ld c, 0
-.loop3
-	push bc
-	call .GetLengthOfStringWith6CharCap
-	push de
-	callba CheckStringForErrors
-	pop hl
-	pop bc
-	jr nc, .valid_nickname
-
-	push bc
-	push hl
-	ld hl, PartySpecies
-	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, StringBuffer1
-.got_nickname
-	pop de
-	ld bc, PKMN_NAME_LENGTH
-	call CopyBytes
-	pop bc
-
-.valid_nickname
-	inc c
-	dec b
-	jr nz, .loop3
-
-	ld de, PartyMonOT
-	ld a, [PartyCount]
-	ld b, a
-	ld c, 0
-.loop4
-	push bc
-	call .GetLengthOfStringWith6CharCap
-	push de
-	callba CheckStringForErrors
-	pop hl
-	jr nc, .valid_ot_name
-	ld d, h
-	ld e, l
-	ld hl, PlayerName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-.valid_ot_name
-	pop bc
-	inc c
-	dec b
-	jr nz, .loop4
-
-	ld hl, PartyMon1Moves
-	ld a, [PartyCount]
-	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
-
-GetSquareRoot: ; 13b87
-; Return the square root of de in b.
-
-; Rather than calculating the result, we take the index of the
-; first value in a table of squares that isn't lower than de.
-
-	ld hl, Squares
-	ld b, 0
-.loop
-; Make sure we don't go past the end of the table.
-	inc b
-	ld a, b
-	cp $ff
-	ret z
-
-; Iterate over the table until b**2 >= de.
-	ld a, [hli]
-	sub e
-	ld a, [hli]
-	sbc d
-
-	jr c, .loop
-	ret
-
-Squares: ; 13b98
-root	set 1
-	rept $ff
-	dw root*root
-root	set root+1
-	endr
-
-
 SECTION "bank5", ROMX
 
 INCLUDE "engine/rtc.asm"
@@ -841,8 +228,6 @@
 INCLUDE "event/daycare.asm"
 INCLUDE "event/photo.asm"
 INCLUDE "engine/breeding.asm"
-
-
 INCLUDE "tilesets/data.asm"
 
 
@@ -879,345 +264,10 @@
 	ret
 
 INCLUDE "engine/pokepic.asm"
-
-LoadObjectMasks: ; 2454f
-	ld hl, wObjectMasks
-	xor a
-	ld bc, NUM_OBJECTS
-	call ByteFill
-	nop
-	ld bc, MapObjects
-	ld de, wObjectMasks
-	xor a
-.loop
-	push af
-	push bc
-	push de
-	call GetObjectTimeMask
-	jr c, .next
-	call CheckObjectFlag
-.next
-	pop de
-	ld [de], a
-	inc de
-	pop bc
-	ld hl, OBJECT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	pop af
-	inc a
-	cp NUM_OBJECTS
-	jr nz, .loop
-	ret
-
-CheckObjectFlag: ; 2457d (9:457d)
-	ld hl, MAPOBJECT_SPRITE
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .masked
-	ld hl, MAPOBJECT_EVENT_FLAG
-	add hl, bc
-	ld a, [hli]
-	ld e, a
-	ld a, [hl]
-	ld d, a
-	cp -1
-	jr nz, .check
-	ld a, e
-	cp -1
-	jr z, .unmasked
-	jr .masked
-.check
-	ld b, CHECK_FLAG
-	call EventFlagAction
-	ld a, c
-	and a
-	jr nz, .masked
-.unmasked
-	xor a
-	ret
-
-.masked
-	ld a, -1
-	scf
-	ret
-
-GetObjectTimeMask: ; 245a7 (9:45a7)
-	call CheckObjectTime
-	ld a, -1
-	ret c
-	xor a
-	ret
-
+INCLUDE "engine/map_objects_2.asm"
 INCLUDE "engine/scrolling_menu.asm"
 INCLUDE "engine/switch_items.asm"
-
-PlaceMenuItemName: ; 0x24ab4
-	push de
-	ld a, [MenuSelection]
-	ld [wNamedObjectIndexBuffer], a
-	call GetItemName
-	pop hl
-	call PlaceString
-	ret
-
-PlaceMenuItemQuantity: ; 0x24ac3
-	push de
-	ld a, [MenuSelection]
-	ld [CurItem], a
-	callba _CheckTossableItem
-	ld a, [wItemAttributeParamBuffer]
-	pop hl
-	and a
-	jr nz, .done
-	ld de, $15
-	add hl, de
-	ld [hl], "×"
-	inc hl
-	ld de, MenuSelectionQuantity
-	lb bc, 1, 2
-	call PrintNum
-
-.done
-	ret
-
-PlaceMoneyTopRight: ; 24ae8
-	ld hl, MenuDataHeader_0x24b15
-	call CopyMenuDataHeader
-	jr PlaceMoneyDataHeader
-
-PlaceMoneyBottomLeft: ; 24af0
-	ld hl, MenuDataHeader_0x24b1d
-	call CopyMenuDataHeader
-	jr PlaceMoneyDataHeader
-
-PlaceMoneyAtTopLeftOfTextbox: ; 24af8
-	ld hl, MenuDataHeader_0x24b15
-	lb de, 0, 11
-	call OffsetMenuDataHeader
-
-PlaceMoneyDataHeader: ; 24b01
-	call MenuBox
-	call MenuBoxCoord2Tile
-	ld de, SCREEN_WIDTH + 1
-	add hl, de
-	ld de, Money
-	lb bc, PRINTNUM_MONEY | 3, 6
-	call PrintNum
-	ret
-
-MenuDataHeader_0x24b15: ; 0x24b15
-	db $40 ; flags
-	db 00, 11 ; start coords
-	db 02, 19 ; end coords
-	dw NULL
-	db 1 ; default option
-
-MenuDataHeader_0x24b1d: ; 0x24b1d
-	db $40 ; flags
-	db 11, 00 ; start coords
-	db 13, 08 ; end coords
-	dw NULL
-	db 1 ; default option
-
-Special_DisplayCoinCaseBalance: ; 24b25
-	; Place a text box of size 1x7 at 11, 0.
-	hlcoord 11, 0
-	ld b, 1
-	ld c, 7
-	call TextBox
-	hlcoord 12, 0
-	ld de, CoinString
-	call PlaceString
-	hlcoord 17, 1
-	ld de, ShowMoney_TerminatorString
-	call PlaceString
-	ld de, Coins
-	lb bc, 2, 4
-	hlcoord 13, 1
-	call PrintNum
-	ret
-
-Special_DisplayMoneyAndCoinBalance: ; 24b4e
-	hlcoord 5, 0
-	ld b, 3
-	ld c, 13
-	call TextBox
-	hlcoord 6, 1
-	ld de, MoneyString
-	call PlaceString
-	hlcoord 12, 1
-	ld de, Money
-	lb bc, PRINTNUM_MONEY | 3, 6
-	call PrintNum
-	hlcoord 6, 3
-	ld de, CoinString
-	call PlaceString
-	hlcoord 15, 3
-	ld de, Coins
-	lb bc, 2, 4
-	call PrintNum
-	ret
-
-MoneyString: ; 24b83
-	db "MONEY@"
-CoinString: ; 24b89
-	db "COIN@"
-ShowMoney_TerminatorString: ; 24b8e
-	db "@"
-
-Function24b8f: ; 24b8f
-; unreferenced, related to safari?
-	ld hl, Options
-	ld a, [hl]
-	push af
-	set NO_TEXT_SCROLL, [hl]
-	hlcoord 0, 0
-	ld b, 3
-	ld c, 7
-	call TextBox
-	hlcoord 1, 1
-	ld de, wSafariTimeRemaining
-	lb bc, 2, 3
-	call PrintNum
-	hlcoord 4, 1
-	ld de, .slash_500
-	call PlaceString
-	hlcoord 1, 3
-	ld de, .booru_ko
-	call PlaceString
-	hlcoord 5, 3
-	ld de, wSafariBallsRemaining
-	lb bc, 1, 2
-	call PrintNum
-	pop af
-	ld [Options], a
-	ret
-
-.slash_500 ; 24bcf
-	db "/500@"
-.booru_ko ; 24bd4
-	db "ボール   こ@"
-
-StartMenu_DrawBugContestStatusBox: ; 24bdc
-	hlcoord 0, 0
-	ld b, 5
-	ld c, 17
-	call TextBox
-	ret
-
-StartMenu_PrintBugContestStatus: ; 24be7
-	ld hl, Options
-	ld a, [hl]
-	push af
-	set NO_TEXT_SCROLL, [hl]
-	call StartMenu_DrawBugContestStatusBox
-	hlcoord 1, 5
-	ld de, .Balls_EN
-	call PlaceString
-	hlcoord 8, 5
-	ld de, wParkBallsRemaining
-	lb bc, PRINTNUM_RIGHTALIGN | 1, 2
-	call PrintNum
-	hlcoord 1, 1
-	ld de, .CAUGHT
-	call PlaceString
-	ld a, [wContestMon]
-	and a
-	ld de, .None
-	jr z, .no_contest_mon
-	ld [wd265], a
-	call GetPokemonName
-
-.no_contest_mon
-	hlcoord 8, 1
-	call PlaceString
-	ld a, [wContestMon]
-	and a
-	jr z, .skip_level
-	hlcoord 1, 3
-	ld de, .LEVEL
-	call PlaceString
-	ld a, [wContestMonLevel]
-	ld h, b
-	ld l, c
-	inc hl
-	ld c, 3
-	call Print8BitNumRightAlign
-
-.skip_level
-	pop af
-	ld [Options], a
-	ret
-
-.Balls_JP: ; 24c43
-	db "ボール   こ@"
-.CAUGHT: ; 24c4b
-	db "CAUGHT@"
-.Balls_EN: ; 24c52
-	db "BALLS:@"
-.None: ; 24c59
-	db "None@"
-.LEVEL: ; 24c5e
-	db "LEVEL@"
-
-FindApricornsInBag: ; 24c64
-; Checks the bag for Apricorns.
-	ld hl, Buffer1
-	xor a
-	ld [hli], a
-	dec a
-	ld bc, 10
-	call ByteFill
-
-	ld hl, .ApricornBalls
-.loop
-	ld a, [hl]
-	cp -1
-	jr z, .done
-	push hl
-	ld [CurItem], a
-	ld hl, NumItems
-	call CheckItem
-	pop hl
-	jr nc, .nope
-	ld a, [hl]
-	call .addtobuffer
-.nope
-	inc hl
-	inc hl
-	jr .loop
-
-.done
-	ld a, [Buffer1]
-	and a
-	ret nz
-	scf
-	ret
-
-.addtobuffer ; 24c94
-	push hl
-	ld hl, Buffer1
-	inc [hl]
-	ld e, [hl]
-	ld d, 0
-	add hl, de
-	ld [hl], a
-	pop hl
-	ret
-
-.ApricornBalls: ; 24ca0
-	db RED_APRICORN, LEVEL_BALL
-	db BLU_APRICORN, LURE_BALL
-	db YLW_APRICORN, MOON_BALL
-	db GRN_APRICORN, FRIEND_BALL
-	db WHT_APRICORN, FAST_BALL
-	db BLK_APRICORN, HEAVY_BALL
-	db PNK_APRICORN, LOVE_BALL
-	db -1
-
+INCLUDE "engine/menu_2.asm"
 INCLUDE "engine/mon_menu.asm"
 INCLUDE "battle/menu.asm"
 INCLUDE "engine/buy_sell_toss.asm"
@@ -1278,91 +328,8 @@
 	call WaitBGMap
 	jp SetPalettes
 
-ConsumeHeldItem: ; 27192
-	push hl
-	push de
-	push bc
-	ld a, [hBattleTurn]
-	and a
-	ld hl, OTPartyMon1Item
-	ld de, EnemyMonItem
-	ld a, [CurOTMon]
-	jr z, .theirturn
-	ld hl, PartyMon1Item
-	ld de, BattleMonItem
-	ld a, [CurBattleMon]
-
-.theirturn
-	push hl
-	push af
-	ld a, [de]
-	ld b, a
-	callba GetItemHeldEffect
-	ld hl, .ConsumableEffects
-.loop
-	ld a, [hli]
-	cp b
-	jr z, .ok
-	inc a
-	jr nz, .loop
-	pop af
-	pop hl
-	pop bc
-	pop de
-	pop hl
-	ret
-
-.ok
-	xor a
-	ld [de], a
-	pop af
-	pop hl
-	call GetPartyLocation
-	ld a, [hBattleTurn]
-	and a
-	jr nz, .ourturn
-	ld a, [wBattleMode]
-	dec a
-	jr z, .done
-
-.ourturn
-	ld [hl], $0
-
-.done
-	pop bc
-	pop de
-	pop hl
-	ret
-
-.ConsumableEffects: ; 271de
-; Consumable items?
-	db HELD_BERRY
-	db HELD_2
-	db HELD_5
-	db HELD_HEAL_POISON
-	db HELD_HEAL_FREEZE
-	db HELD_HEAL_BURN
-	db HELD_HEAL_SLEEP
-	db HELD_HEAL_PARALYZE
-	db HELD_HEAL_STATUS
-	db HELD_30
-	db HELD_ATTACK_UP
-	db HELD_DEFENSE_UP
-	db HELD_SPEED_UP
-	db HELD_SP_ATTACK_UP
-	db HELD_SP_DEFENSE_UP
-	db HELD_ACCURACY_UP
-	db HELD_EVASION_UP
-	db HELD_38
-	db HELD_71
-	db HELD_ESCAPE
-	db HELD_CRITICAL_UP
-	db -1
-
-MoveEffectsPointers: ; 271f4
+INCLUDE "engine/consume_held_item.asm"
 INCLUDE "battle/moves/move_effects_pointers.asm"
-
-MoveEffects: ; 2732e
 INCLUDE "battle/moves/move_effects.asm"
 
 Kurt_SelectQuantity_InterpretJoypad: ; 27a28
@@ -1399,380 +366,15 @@
 SECTION "bankB", ROMX
 
 INCLUDE "battle/trainer_huds.asm"
-
 INCLUDE "data/trainers/trainer_class_names.asm"
-
 INCLUDE "battle/ai/redundant.asm"
-
 INCLUDE "event/move_deleter.asm"
-
 INCLUDE "engine/mysterygift2.asm"
-
 INCLUDE "engine/tmhm2.asm"
-
-MoveDescriptions:: ; 2cb52
 INCLUDE "battle/moves/move_descriptions.asm"
+INCLUDE "engine/pokerus.asm"
+INCLUDE "engine/start_battle.asm"
 
-GivePokerusAndConvertBerries: ; 2ed44
-	call ConvertBerriesToBerryJuice
-	ld hl, PartyMon1PokerusStatus
-	ld a, [PartyCount]
-	ld b, a
-	ld de, PARTYMON_STRUCT_LENGTH
-; Check to see if any of your Pokemon already has Pokerus.
-; If so, sample its spread through your party.
-; This means that you cannot get Pokerus de novo while
-; a party member has an active infection.
-.loopMons
-	ld a, [hl]
-	and $f
-	jr nz, .TrySpreadPokerus
-	add hl, de
-	dec b
-	jr nz, .loopMons
-
-; If we haven't been to Goldenrod City at least once,
-; prevent the contraction of Pokerus.
-	ld hl, StatusFlags2
-	bit 6, [hl]
-	ret z
-	call Random
-	ld a, [hRandomAdd]
-	and a
-	ret nz
-	ld a, [hRandomSub]
-	cp $3
-	ret nc                 ; 3/65536 chance (00 00, 00 01 or 00 02)
-	ld a, [PartyCount]
-	ld b, a
-.randomMonSelectLoop
-	call Random
-	and $7
-	cp b
-	jr nc, .randomMonSelectLoop
-	ld hl, PartyMon1PokerusStatus
-	call GetPartyLocation  ; get pokerus byte of random mon
-	ld a, [hl]
-	and $f0
-	ret nz                 ; if it already has pokerus, do nothing
-.randomPokerusLoop         ; Simultaneously sample the strain and duration
-	call Random
-	and a
-	jr z, .randomPokerusLoop
-	ld b, a
-	and $f0
-	jr z, .load_pkrs
-	ld a, b
-	and $7
-	inc a
-.load_pkrs
-	ld b, a ; this should come before the label
-	swap b
-	and $3
-	inc a
-	add b
-	ld [hl], a
-	ret
-
-.TrySpreadPokerus:
-	call Random
-	cp 1 + 33 percent
-	ret nc              ; 1/3 chance
-
-	ld a, [PartyCount]
-	cp 1
-	ret z               ; only one mon, nothing to do
-
-	ld c, [hl]
-	ld a, b
-	cp 2
-	jr c, .checkPreviousMonsLoop    ; no more mons after this one, go backwards
-
-	call Random
-	cp 1 + 50 percent
-	jr c, .checkPreviousMonsLoop    ; 1/2 chance, go backwards
-.checkFollowingMonsLoop
-	add hl, de
-	ld a, [hl]
-	and a
-	jr z, .infectMon
-	ld c, a
-	and $3
-	ret z               ; if mon has cured pokerus, stop searching
-	dec b               ; go on to next mon
-	ld a, b
-	cp 1
-	jr nz, .checkFollowingMonsLoop ; no more mons left
-	ret
-
-.checkPreviousMonsLoop
-	ld a, [PartyCount]
-	cp b
-	ret z               ; no more mons
-	ld a, l
-	sub e
-	ld l, a
-	ld a, h
-	sbc d
-	ld h, a
-	ld a, [hl]
-	and a
-	jr z, .infectMon
-	ld c, a
-	and $3
-	ret z               ; if mon has cured pokerus, stop searching
-	inc b               ; go on to next mon
-	jr .checkPreviousMonsLoop
-
-.infectMon
-	ld a, c
-	and $f0
-	ld b, a
-	ld a, c
-	swap a
-	and $3
-	inc a
-	add b
-	ld [hl], a
-	ret
-
-; any berry held by a Shuckle may be converted to berry juice
-ConvertBerriesToBerryJuice: ; 2ede6
-	ld hl, StatusFlags2
-	bit 6, [hl]
-	ret z
-	call Random
-	cp $10
-	ret nc              ; 1/16 chance
-	ld hl, PartyMons
-	ld a, [PartyCount]
-.partyMonLoop
-	push af
-	push hl
-	ld a, [hl]
-	cp SHUCKLE
-	jr nz, .loopMon
-	ld bc, MON_ITEM
-	add hl, bc
-	ld a, [hl]
-	cp BERRY
-	jr z, .convertToJuice
-
-.loopMon
-	pop hl
-	ld bc, PARTYMON_STRUCT_LENGTH
-	add hl, bc
-	pop af
-	dec a
-	jr nz, .partyMonLoop
-	ret
-
-.convertToJuice
-	ld a, BERRY_JUICE
-	ld [hl], a
-	pop hl
-	pop af
-	ret
-
-ShowLinkBattleParticipants: ; 2ee18
-; If we're not in a communications room,
-; we don't need to be here.
-	ld a, [wLinkMode]
-	and a
-	ret z
-
-	callba _ShowLinkBattleParticipants
-	ld c, 150
-	call DelayFrames
-	call ClearTileMap
-	call ClearSprites
-	ret
-
-FindFirstAliveMonAndStartBattle: ; 2ee2f
-	xor a
-	ld [hMapAnims], a
-	call DelayFrame
-	ld b, 6
-	ld hl, PartyMon1HP
-	ld de, PARTYMON_STRUCT_LENGTH - 1
-
-.loop
-	ld a, [hli]
-	or [hl]
-	jr nz, .okay
-	add hl, de
-	dec b
-	jr nz, .loop
-
-.okay
-	ld de, MON_LEVEL - MON_HP
-	add hl, de
-	ld a, [hl]
-	ld [BattleMonLevel], a
-	predef Predef_StartBattle
-	callba _LoadBattleFontsHPBar
-	ld a, 1
-	ld [hBGMapMode], a
-	call ClearSprites
-	call ClearTileMap
-	xor a
-	ld [hBGMapMode], a
-	ld [hWY], a
-	ld [rWY], a
-	ld [hMapAnims], a
-	ret
-
-PlayBattleMusic: ; 2ee6c
-
-	push hl
-	push de
-	push bc
-
-	xor a
-	ld [MusicFade], a
-	ld de, MUSIC_NONE
-	call PlayMusic
-	call DelayFrame
-	call MaxVolume
-
-	ld a, [BattleType]
-	cp BATTLETYPE_SUICUNE
-	ld de, MUSIC_SUICUNE_BATTLE
-	jp z, .done
-	cp BATTLETYPE_ROAMING
-	jp z, .done
-
-	; Are we fighting a trainer?
-	ld a, [OtherTrainerClass]
-	and a
-	jr nz, .trainermusic
-
-	callba RegionCheck
-	ld a, e
-	and a
-	jr nz, .kantowild
-
-	ld de, MUSIC_JOHTO_WILD_BATTLE
-	ld a, [TimeOfDay]
-	cp NITE_F
-	jr nz, .done
-	ld de, MUSIC_JOHTO_WILD_BATTLE_NIGHT
-	jr .done
-
-.kantowild
-	ld de, MUSIC_KANTO_WILD_BATTLE
-	jr .done
-
-.trainermusic
-	ld de, MUSIC_CHAMPION_BATTLE
-	cp CHAMPION
-	jr z, .done
-	cp RED
-	jr z, .done
-
-	; really, they should have included admins and scientists here too...
-	ld de, MUSIC_ROCKET_BATTLE
-	cp GRUNTM
-	jr z, .done
-	cp GRUNTF
-	jr z, .done
-
-	ld de, MUSIC_KANTO_GYM_LEADER_BATTLE
-	callba IsKantoGymLeader
-	jr c, .done
-
-	ld de, MUSIC_JOHTO_GYM_LEADER_BATTLE
-	callba IsJohtoGymLeader
-	jr c, .done
-
-	ld de, MUSIC_RIVAL_BATTLE
-	ld a, [OtherTrainerClass]
-	cp RIVAL1
-	jr z, .done
-	cp RIVAL2
-	jr nz, .othertrainer
-
-	ld a, [OtherTrainerID]
-	cp RIVAL2_2_CHIKORITA ; Rival in Indigo Plateau
-	jr c, .done
-	ld de, MUSIC_CHAMPION_BATTLE
-	jr .done
-
-.othertrainer
-	ld a, [wLinkMode]
-	and a
-	jr nz, .johtotrainer
-
-	callba RegionCheck
-	ld a, e
-	and a
-	jr nz, .kantotrainer
-
-.johtotrainer
-	ld de, MUSIC_JOHTO_TRAINER_BATTLE
-	jr .done
-
-.kantotrainer
-	ld de, MUSIC_KANTO_TRAINER_BATTLE
-
-.done
-	call PlayMusic
-
-	pop bc
-	pop de
-	pop hl
-	ret
-
-ClearBattleRAM: ; 2ef18
-	xor a
-	ld [wPlayerAction], a
-	ld [wBattleResult], a
-
-	ld hl, wPartyMenuCursor
-	ld [hli], a
-	ld [hli], a
-	ld [hli], a
-	ld [hl], a
-
-	ld [wMenuScrollPosition], a
-	ld [CriticalHit], a
-	ld [BattleMonSpecies], a
-	ld [wBattleParticipantsNotFainted], a
-	ld [CurBattleMon], a
-	ld [wForcedSwitch], a
-	ld [TimeOfDayPal], a
-	ld [PlayerTurnsTaken], a
-	ld [EnemyTurnsTaken], a
-	ld [EvolvableFlags], a
-
-	ld hl, PlayerHPPal
-	ld [hli], a
-	ld [hl], a
-
-	ld hl, BattleMonDVs
-	ld [hli], a
-	ld [hl], a
-
-	ld hl, EnemyMonDVs
-	ld [hli], a
-	ld [hl], a
-
-; Clear the entire BattleMons area
-	ld hl, wBattle
-	ld bc, wBattleEnd - wBattle
-	xor a
-	call ByteFill
-
-	callab ResetEnemyStatLevels
-
-	call ClearWindowData
-
-	ld hl, hBGMapAddress
-	xor a
-	ld [hli], a
-	ld [hl], VBGMap0 / $100
-	ret
-
 PlaceGraphic: ; 2ef6e
 ; Fill wBoxAlignment-aligned box width b height c
 ; with iterating tile starting from hGraphicStartTile at hl.
@@ -1894,128 +496,14 @@
 PackFGFX: ; 48e9b
 INCBIN "gfx/pack/pack_f.2bpp"
 
-Special_MoveTutor: ; 4925b
-	call FadeToMenu
-	call ClearBGPalettes
-	call ClearScreen
-	call DelayFrame
-	ld b, SCGB_PACKPALS
-	call GetSGBLayout
-	xor a
-	ld [wItemAttributeParamBuffer], a
-	call .GetMoveTutorMove
-	ld [wd265], a
-	ld [wPutativeTMHMMove], a
-	call GetMoveName
-	call CopyName1
-	callba ChooseMonToLearnTMHM
-	jr c, .cancel
-	jr .enter_loop
-
-.loop
-	callba ChooseMonToLearnTMHM_NoRefresh
-	jr c, .cancel
-.enter_loop
-	call CheckCanLearnMoveTutorMove
-	jr nc, .loop
-	xor a
-	ld [ScriptVar], a
-	jr .quit
-
-.cancel
-	ld a, -1
-	ld [ScriptVar], a
-.quit
-	call CloseSubmenu
-	ret
-
-.GetMoveTutorMove: ; 492a5
-	ld a, [ScriptVar]
-	cp 1
-	jr z, .flamethrower
-	cp 2
-	jr z, .thunderbolt
-	ld a, ICE_BEAM
-	ret
-
-.flamethrower
-	ld a, FLAMETHROWER
-	ret
-
-.thunderbolt
-	ld a, THUNDERBOLT
-	ret
-
-CheckCanLearnMoveTutorMove: ; 492b9
-	ld hl, .MenuDataHeader
-	call LoadMenuDataHeader
-
-	predef CanLearnTMHMMove
-
-	push bc
-	ld a, [CurPartyMon]
-	ld hl, PartyMonNicknames
-	call GetNick
-	pop bc
-
-	ld a, c
-	and a
-	jr nz, .can_learn
-	push de
-	ld de, SFX_WRONG
-	call PlaySFX
-	pop de
-	ld a, BANK(Text_TMHMNotCompatible)
-	ld hl, Text_TMHMNotCompatible
-	call FarPrintText
-	jr .didnt_learn
-
-.can_learn
-	callab KnowsMove
-	jr c, .didnt_learn
-
-	predef LearnMove
-	ld a, b
-	and a
-	jr z, .didnt_learn
-
-	ld c, HAPPINESS_LEARNMOVE
-	callab ChangeHappiness
-	jr .learned
-
-.didnt_learn
-	call ExitMenu
-	and a
-	ret
-
-.learned
-	call ExitMenu
-	scf
-	ret
-
-.MenuDataHeader: ; 0x4930a
-	db $40 ; flags
-	db 12, 00 ; start coords
-	db 17, 19 ; end coords
-
+INCLUDE "event/move_tutor.asm"
 INCLUDE "engine/crystal_colors.asm"
-
-Unknown_4985a: ; unreferenced
-	db $ab, $03, $57, $24, $ac, $0e, $13, $32
-	db $be, $30, $5b, $4c, $47, $60, $ed, $f2
-	db $ab, $03, $55, $26, $aa, $0a, $13, $3a
-	db $be, $28, $33, $24, $6e, $71, $df, $b0
-	db $a8, $00, $e5, $e0, $9a, $fc, $f4, $2c
-	db $fe, $4c, $a3, $5e, $c6, $3a, $ab, $4d
-	db $a8, $00, $b5, $b0, $de, $e8, $fc, $1c
-	db $ba, $66, $f7, $0e, $ba, $5e, $43, $bd
-
 INCLUDE "event/celebi.asm"
 INCLUDE "engine/main_menu.asm"
 INCLUDE "mobile/mobile_menu.asm"
 INCLUDE "engine/search.asm"
+ ; mobile battle selection
 INCLUDE "mobile/mobile_12_2.asm"
-; mobile battle selection
 
 AskRememberPassword: ; 4ae12
 	call .DoMenu
@@ -2079,93 +567,7 @@
 
 SECTION "bank13", ROMX
 
-SwapTextboxPalettes:: ; 4c000
-	hlcoord 0, 0
-	decoord 0, 0, AttrMap
-	ld b, SCREEN_HEIGHT
-.loop
-	push bc
-	ld c, SCREEN_WIDTH
-.innerloop
-	ld a, [hl]
-	push hl
-	srl a
-	jr c, .UpperNybble
-	ld hl, TilesetPalettes
-	add [hl]
-	ld l, a
-	ld a, [TilesetPalettes + 1]
-	adc $0
-	ld h, a
-	ld a, [hl]
-	and $f
-	jr .next
-
-.UpperNybble:
-	ld hl, TilesetPalettes
-	add [hl]
-	ld l, a
-	ld a, [TilesetPalettes + 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, BGMapBuffer
-	ld de, BGMapPalBuffer
-.loop
-	ld a, [hl]
-	push hl
-	srl a
-	jr c, .UpperNybble
-
-; .LowerNybble
-	ld hl, TilesetPalettes
-	add [hl]
-	ld l, a
-	ld a, [TilesetPalettes + 1]
-	adc $0
-	ld h, a
-	ld a, [hl]
-	and $f
-	jr .next
-
-.UpperNybble:
-	ld hl, TilesetPalettes
-	add [hl]
-	ld l, a
-	ld a, [TilesetPalettes + 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
-
+INCLUDE "engine/map_palettes.asm"
 INCLUDE "tilesets/palette_maps.asm"
 
 Unknown_4ce05: ; unreferenced
@@ -2514,7 +916,6 @@
 	ret
 
 INCLUDE "engine/delete_save_change_clock.asm"
-
 INCLUDE "tilesets/tileset_headers.asm"
 
 FlagPredef: ; 4d7c1
@@ -2653,567 +1054,11 @@
 	scf
 	ret
 
-Special_CheckForLuckyNumberWinners: ; 4d87a
-	xor a
-	ld [ScriptVar], a
-	ld [wFoundMatchingIDInParty], a
-	ld a, [PartyCount]
-	and a
-	ret z
-	ld d, a
-	ld hl, PartyMon1ID
-	ld bc, PartySpecies
-.PartyLoop:
-	ld a, [bc]
-	inc bc
-	cp EGG
-	call nz, .CompareLuckyNumberToMonID
-	push bc
-	ld bc, PARTYMON_STRUCT_LENGTH
-	add hl, bc
-	pop bc
-	dec d
-	jr nz, .PartyLoop
-	ld a, BANK(sBox)
-	call GetSRAMBank
-	ld a, [sBoxCount]
-	and a
-	jr z, .SkipOpenBox
-	ld d, a
-	ld hl, sBoxMon1ID
-	ld bc, sBoxSpecies
-.OpenBoxLoop:
-	ld a, [bc]
-	inc bc
-	cp EGG
-	jr z, .SkipOpenBoxMon
-	call .CompareLuckyNumberToMonID
-	jr nc, .SkipOpenBoxMon
-	ld a, 1
-	ld [wFoundMatchingIDInParty], a
-
-.SkipOpenBoxMon:
-	push bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	add hl, bc
-	pop bc
-	dec d
-	jr nz, .OpenBoxLoop
-
-.SkipOpenBox:
-	call CloseSRAM
-	ld c, $0
-.BoxesLoop:
-	ld a, [wCurBox]
-	and $f
-	cp c
-	jr z, .SkipBox
-	ld hl, .BoxBankAddresses
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	call GetSRAMBank
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a ; hl now contains the address of the loaded box in SRAM
-	ld a, [hl]
-	and a
-	jr z, .SkipBox ; no mons in this box
-	push bc
-	ld b, h
-	ld c, l
-	inc bc
-	ld de, sBoxMon1ID - sBox
-	add hl, de
-	ld d, a
-.BoxNLoop:
-	ld a, [bc]
-	inc bc
-	cp EGG
-	jr z, .SkipBoxMon
-
-	call .CompareLuckyNumberToMonID ; sets ScriptVar and CurPartySpecies appropriately
-	jr nc, .SkipBoxMon
-	ld a, 1
-	ld [wFoundMatchingIDInParty], a
-
-.SkipBoxMon:
-	push bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	add hl, bc
-	pop bc
-	dec d
-	jr nz, .BoxNLoop
-	pop bc
-
-.SkipBox:
-	inc c
-	ld a, c
-	cp NUM_BOXES
-	jr c, .BoxesLoop
-
-	call CloseSRAM
-	ld a, [ScriptVar]
-	and a
-	ret z ; found nothing
-	callba TrainerRankings_LuckyNumberShow
-	ld a, [wFoundMatchingIDInParty]
-	and a
-	push af
-	ld a, [CurPartySpecies]
-	ld [wNamedObjectIndexBuffer], a
-	call GetPokemonName
-	ld hl, .FoundPartymonText
-	pop af
-	jr z, .print
-	ld hl, .FoundBoxmonText
-
-.print
-	jp PrintText
-
-.CompareLuckyNumberToMonID: ; 4d939
-	push bc
-	push de
-	push hl
-	ld d, h
-	ld e, l
-	ld hl, Buffer1
-	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
-	call PrintNum
-	ld hl, LuckyNumberDigit1Buffer
-	ld de, wLuckyIDNumber
-	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
-	call PrintNum
-	ld b, 5
-	ld c, 0
-	ld hl, LuckyNumberDigit5Buffer
-	ld de, Buffer5
-.loop
-	ld a, [de]
-	cp [hl]
-	jr nz, .done
-	dec de
-	dec hl
-	inc c
-	dec b
-	jr nz, .loop
-
-.done
-	pop hl
-	push hl
-	ld de, -6
-	add hl, de
-	ld a, [hl]
-	pop hl
-	pop de
-	push af
-	ld a, c
-	ld b, 1
-	cp 5
-	jr z, .okay
-	ld b, 2
-	cp 3
-	jr nc, .okay
-	ld b, 3
-	cp 2
-	jr nz, .nomatch
-
-.okay
-	inc b
-	ld a, [ScriptVar]
-	and a
-	jr z, .bettermatch
-	cp b
-	jr c, .nomatch
-
-.bettermatch
-	dec b
-	ld a, b
-	ld [ScriptVar], a
-	pop bc
-	ld a, b
-	ld [CurPartySpecies], a
-	pop bc
-	scf
-	ret
-
-.nomatch
-	pop bc
-	pop bc
-	and a
-	ret
-
-.BoxBankAddresses: ; 4d99f
-	dba sBox1
-	dba sBox2
-	dba sBox3
-	dba sBox4
-	dba sBox5
-	dba sBox6
-	dba sBox7
-	dba sBox8
-	dba sBox9
-	dba sBox10
-	dba sBox11
-	dba sBox12
-	dba sBox13
-	dba sBox14
-
-.FoundPartymonText: ; 0x4d9c9
-	; Congratulations! We have a match with the ID number of @  in your party.
-	text_jump UnknownText_0x1c1261
-	db "@"
-
-.FoundBoxmonText: ; 0x4d9ce
-	; Congratulations! We have a match with the ID number of @  in your PC BOX.
-	text_jump UnknownText_0x1c12ae
-	db "@"
-
-Special_PrintTodaysLuckyNumber: ; 4d9d3
-	ld hl, StringBuffer3
-	ld de, wLuckyIDNumber
-	lb bc, PRINTNUM_LEADINGZEROS | 2, 5
-	call PrintNum
-	ld a, "@"
-	ld [StringBuffer3 + 5], a
-	ret
-
-CheckPartyFullAfterContest: ; 4d9e5
-	ld a, [wContestMon]
-	and a
-	jp z, .DidntCatchAnything
-	ld [CurPartySpecies], a
-	ld [CurSpecies], a
-	call GetBaseData
-	ld hl, PartyCount
-	ld a, [hl]
-	cp 6
-	jp nc, .TryAddToBox
-	inc a
-	ld [hl], a
-	ld c, a
-	ld b, $0
-	add hl, bc
-	ld a, [wContestMon]
-	ld [hli], a
-	ld [CurSpecies], a
-	ld a, $ff
-	ld [hl], a
-	ld hl, PartyMon1Species
-	ld a, [PartyCount]
-	dec a
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld d, h
-	ld e, l
-	ld hl, wContestMon
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call CopyBytes
-	ld a, [PartyCount]
-	dec a
-	ld hl, PartyMonOT
-	call SkipNames
-	ld d, h
-	ld e, l
-	ld hl, PlayerName
-	call CopyBytes
-	ld a, [CurPartySpecies]
-	ld [wd265], a
-	call GetPokemonName
-	ld hl, StringBuffer1
-	ld de, wMonOrItemNameBuffer
-	ld bc, PKMN_NAME_LENGTH
-	call CopyBytes
-	call GiveANickname_YesNo
-	jr c, .Party_SkipNickname
-	ld a, [PartyCount]
-	dec a
-	ld [CurPartyMon], a
-	xor a
-	ld [MonType], a
-	ld de, wMonOrItemNameBuffer
-	callab InitNickname
-
-.Party_SkipNickname:
-	ld a, [PartyCount]
-	dec a
-	ld hl, PartyMonNicknames
-	call SkipNames
-	ld d, h
-	ld e, l
-	ld hl, wMonOrItemNameBuffer
-	call CopyBytes
-	ld a, [PartyCount]
-	dec a
-	ld hl, PartyMon1Level
-	call GetPartyLocation
-	ld a, [hl]
-	ld [CurPartyLevel], a
-	call SetCaughtData
-	ld a, [PartyCount]
-	dec a
-	ld hl, PartyMon1CaughtLocation
-	call GetPartyLocation
-	ld a, [hl]
-	and $80
-	ld b, $13
-	or b
-	ld [hl], a
-	xor a
-	ld [wContestMon], a
-	and a
-	ld [ScriptVar], a
-	ret
-
-.TryAddToBox: ; 4daa3
-	ld a, BANK(sBoxCount)
-	call GetSRAMBank
-	ld hl, sBoxCount
-	ld a, [hl]
-	cp MONS_PER_BOX
-	call CloseSRAM
-	jr nc, .BoxFull
-	xor a
-	ld [CurPartyMon], a
-	ld hl, wContestMon
-	ld de, wBufferMon
-	ld bc, BOXMON_STRUCT_LENGTH
-	call CopyBytes
-	ld hl, PlayerName
-	ld de, wBufferMonOT
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	callab InsertPokemonIntoBox
-	ld a, [CurPartySpecies]
-	ld [wd265], a
-	call GetPokemonName
-	call GiveANickname_YesNo
-	ld hl, StringBuffer1
-	jr c, .Box_SkipNickname
-	ld a, BOXMON
-	ld [MonType], a
-	ld de, wMonOrItemNameBuffer
-	callab InitNickname
-	ld hl, wMonOrItemNameBuffer
-
-.Box_SkipNickname:
-	ld a, BANK(sBoxMonNicknames)
-	call GetSRAMBank
-	ld de, sBoxMonNicknames
-	ld bc, PKMN_NAME_LENGTH
-	call CopyBytes
-	call CloseSRAM
-
-.BoxFull:
-	ld a, BANK(sBoxMon1Level)
-	call GetSRAMBank
-	ld a, [sBoxMon1Level]
-	ld [CurPartyLevel], a
-	call CloseSRAM
-	call SetBoxMonCaughtData
-	ld a, BANK(sBoxMon1CaughtLocation)
-	call GetSRAMBank
-	ld hl, sBoxMon1CaughtLocation
-	ld a, [hl]
-	and $80
-	ld b, $13
-	or b
-	ld [hl], a
-	call CloseSRAM
-	xor a
-	ld [wContestMon], a
-	ld a, $1
-	ld [ScriptVar], a
-	ret
-
-.DidntCatchAnything: ; 4db35
-	ld a, $2
-	ld [ScriptVar], a
-	ret
-
-GiveANickname_YesNo: ; 4db3b
-	ld hl, TextJump_GiveANickname
-	call PrintText
-	jp YesNoBox
-
-TextJump_GiveANickname: ; 0x4db44
-	; Give a nickname to the @  you received?
-	text_jump UnknownText_0x1c12fc
-	db "@"
-
-SetCaughtData: ; 4db49
-	ld a, [PartyCount]
-	dec a
-	ld hl, PartyMon1CaughtLevel
-	call GetPartyLocation
-SetBoxmonOrEggmonCaughtData: ; 4db53
-	ld a, [TimeOfDay]
-	inc a
-	rrca
-	rrca
-	ld b, a
-	ld a, [CurPartyLevel]
-	or b
-	ld [hli], a
-	ld a, [MapGroup]
-	ld b, a
-	ld a, [MapNumber]
-	ld c, a
-	cp MAP_POKECENTER_2F
-	jr nz, .NotPokecenter2F
-	ld a, b
-	cp GROUP_POKECENTER_2F
-	jr nz, .NotPokecenter2F
-
-	ld a, [BackupMapGroup]
-	ld b, a
-	ld a, [BackupMapNumber]
-	ld c, a
-
-.NotPokecenter2F:
-	call GetWorldMapLocation
-	ld b, a
-	ld a, [PlayerGender]
-	rrca
-	or b
-	ld [hl], a
-	ret
-
-SetBoxMonCaughtData: ; 4db83
-	ld a, BANK(sBoxMon1CaughtLevel)
-	call GetSRAMBank
-	ld hl, sBoxMon1CaughtLevel
-	call SetBoxmonOrEggmonCaughtData
-	call CloseSRAM
-	ret
-
-SetGiftBoxMonCaughtData: ; 4db92
-	push bc
-	ld a, BANK(sBoxMon1CaughtLevel)
-	call GetSRAMBank
-	ld hl, sBoxMon1CaughtLevel
-	pop bc
-	call SetGiftMonCaughtData
-	call CloseSRAM
-	ret
-
-SetGiftPartyMonCaughtData: ; 4dba3
-	ld a, [PartyCount]
-	dec a
-	ld hl, PartyMon1CaughtLevel
-	push bc
-	call GetPartyLocation
-	pop bc
-SetGiftMonCaughtData: ; 4dbaf
-	xor a
-	ld [hli], a
-	ld a, $7e
-	rrc b
-	or b
-	ld [hl], a
-	ret
-
-SetEggMonCaughtData: ; 4dbb8 (13:5bb8)
-	ld a, [CurPartyMon]
-	ld hl, PartyMon1CaughtLevel
-	call GetPartyLocation
-	ld a, [CurPartyLevel]
-	push af
-	ld a, $1
-	ld [CurPartyLevel], a
-	call SetBoxmonOrEggmonCaughtData
-	pop af
-	ld [CurPartyLevel], a
-	ret
-
+INCLUDE "event/lucky_number.asm"
+INCLUDE "engine/caught_data.asm"
 INCLUDE "engine/search2.asm"
-
 INCLUDE "engine/stats_screen.asm"
-
-CatchTutorial:: ; 4e554
-	ld a, [BattleType]
-	dec a
-	ld c, a
-	ld hl, .dw
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-.dw ; 4e564 (13:6564)
-	dw .DudeTutorial
-	dw .DudeTutorial
-	dw .DudeTutorial
-
-.DudeTutorial: ; 4e56a (13:656a)
-; Back up your name to your Mom's name.
-	ld hl, PlayerName
-	ld de, MomsName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-; Copy Dude's name to your name
-	ld hl, .Dude
-	ld de, PlayerName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-
-	call .LoadDudeData
-
-	xor a
-	ld [hJoyDown], a
-	ld [hJoyPressed], a
-	ld a, [Options]
-	push af
-	and $f8
-	add $3
-	ld [Options], a
-	ld hl, .AutoInput
-	ld a, BANK(.AutoInput)
-	call StartAutoInput
-	callab StartBattle
-	call StopAutoInput
-	pop af
-
-	ld [Options], a
-	ld hl, MomsName
-	ld de, PlayerName
-	ld bc, NAME_LENGTH
-	call CopyBytes
-	ret
-
-.LoadDudeData: ; 4e5b7 (13:65b7)
-	ld hl, wDudeNumItems
-	ld [hl], 1
-	inc hl
-	ld [hl], POTION
-	inc hl
-	ld [hl], 1
-	inc hl
-	ld [hl], -1
-	ld hl, wDudeNumKeyItems
-	ld [hl], 0
-	inc hl
-	ld [hl], -1
-	ld hl, wDudeNumBalls
-	ld a, 1
-	ld [hli], a
-	ld a, POKE_BALL ; 5
-	ld [hli], a
-	ld [hli], a
-	ld [hl], -1
-	ret
-
-.Dude: ; 4e5da
-	db "DUDE@"
-
-.AutoInput: ; 4e5df
-	db NO_INPUT, $ff ; end
-
+INCLUDE "event/catch_tutorial.asm"
 INCLUDE "engine/evolution_animation.asm"
 
 InitDisplayForHallOfFame: ; 4e881
@@ -3342,7 +1187,6 @@
 	ret
 
 INCLUDE "data/trainers/gendered_trainers.asm"
-
 INCLUDE "battle/sliding_intro.asm"
 
 Mobile_PrintOpponentBattleMessage: ; 4ea0a
@@ -3425,7 +1269,6 @@
 	ret
 
 INCLUDE "engine/gbc_only.asm"
-
 INCLUDE "event/poke_seer.asm"
 
 
@@ -3568,587 +1411,9 @@
 	ret
 
 INCLUDE "text/types.asm"
+INCLUDE "text/unused_gen_1_trainers.asm"
+INCLUDE "engine/mon_stats.asm"
 
-Function50a28: ; 50a28
-; XXX
-	ld hl, .Strings
-	ld a, [TrainerClass]
-	dec a
-	ld c, a
-	ld b, 0
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld de, StringBuffer1
-.copy
-	ld a, [hli]
-	ld [de], a
-	inc de
-	cp "@"
-	jr nz, .copy
-	ret
-
-.Strings: ; 50a42
-; Untranslated trainer class names from Red.
-	dw .Youngster
-	dw .BugCatcher
-	dw .Lass
-	dw OTClassName
-	dw .JrTrainerM
-	dw .JrTrainerF
-	dw .Pokemaniac
-	dw .SuperNerd
-	dw OTClassName
-	dw OTClassName
-	dw .Burglar
-	dw .Engineer
-	dw .Jack
-	dw OTClassName
-	dw .Swimmer
-	dw OTClassName
-	dw OTClassName
-	dw .Beauty
-	dw OTClassName
-	dw .Rocker
-	dw .Juggler
-	dw OTClassName
-	dw OTClassName
-	dw .Blackbelt
-	dw OTClassName
-	dw .ProfOak
-	dw .Chief
-	dw .Scientist
-	dw OTClassName
-	dw .Rocket
-	dw .CooltrainerM
-	dw .CooltrainerF
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-	dw OTClassName
-
-.Youngster:    db "たんパン@"
-.BugCatcher:   db "むしとり@"
-.Lass:         db "ミニスカ@"
-.JrTrainerM:   db "ボーイ@"
-.JrTrainerF:   db "ガール@"
-.Pokemaniac:   db "マニア@"
-.SuperNerd:    db "りかけい@"
-.Burglar:      db "どろぼう@"
-.Engineer:     db "ォヤジ@"
-.Jack:         db "ジャック@"
-.Swimmer:      db "かいパン@"
-.Beauty:       db "おねえさん@"
-.Rocker:       db "グループ@"
-.Juggler:      db "ジャグラー@"
-.Blackbelt:    db "からて@"
-.ProfOak:      db "ォーキド@"
-.Chief:        db "チーフ@"
-.Scientist:    db "けんきゅういん@"
-.Rocket:       db "だんいん@"
-.CooltrainerM: db "エりート♂@"
-.CooltrainerF: db "エりート♀@"
-
-DrawPlayerHP: ; 50b0a
-	ld a, $1
-	jr DrawHP
-
-DrawEnemyHP: ; 50b0e
-	ld a, $2
-
-DrawHP: ; 50b10
-	ld [wWhichHPBar], a
-	push hl
-	push bc
-	; box mons have full HP
-	ld a, [MonType]
-	cp BOXMON
-	jr z, .at_least_1_hp
-
-	ld a, [TempMonHP]
-	ld b, a
-	ld a, [TempMonHP + 1]
-	ld c, a
-
-; Any HP?
-	or b
-	jr nz, .at_least_1_hp
-
-	xor a
-	ld c, a
-	ld e, a
-	ld a, 6
-	ld d, a
-	jp .fainted
-
-.at_least_1_hp
-	ld a, [TempMonMaxHP]
-	ld d, a
-	ld a, [TempMonMaxHP + 1]
-	ld e, a
-	ld a, [MonType]
-	cp BOXMON
-	jr nz, .not_boxmon
-
-	ld b, d
-	ld c, e
-
-.not_boxmon
-	predef ComputeHPBarPixels
-	ld a, 6
-	ld d, a
-	ld c, a
-
-.fainted
-	ld a, c
-	pop bc
-	ld c, a
-	pop hl
-	push de
-	push hl
-	push hl
-	call DrawBattleHPBar
-	pop hl
-
-; Print HP
-	bccoord 1, 1, 0
-	add hl, bc
-	ld de, TempMonHP
-	ld a, [MonType]
-	cp BOXMON
-	jr nz, .not_boxmon_2
-	ld de, TempMonMaxHP
-.not_boxmon_2
-	lb bc, 2, 3
-	call PrintNum
-
-	ld a, "/"
-	ld [hli], a
-
-; Print max HP
-	ld de, TempMonMaxHP
-	lb bc, 2, 3
-	call PrintNum
-	pop hl
-	pop de
-	ret
-
-PrintTempMonStats: ; 50b7b
-; Print TempMon's stats at hl, with spacing bc.
-	push bc
-	push hl
-	ld de, .StatNames
-	call PlaceString
-	pop hl
-	pop bc
-	add hl, bc
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	ld de, TempMonAttack
-	lb bc, 2, 3
-	call .PrintStat
-	ld de, TempMonDefense
-	call .PrintStat
-	ld de, TempMonSpclAtk
-	call .PrintStat
-	ld de, TempMonSpclDef
-	call .PrintStat
-	ld de, TempMonSpeed
-	jp PrintNum
-
-.PrintStat: ; 50bab
-	push hl
-	call PrintNum
-	pop hl
-	ld de, SCREEN_WIDTH * 2
-	add hl, de
-	ret
-
-.StatNames: ; 50bb5
-	db   "ATTACK"
-	next "DEFENSE"
-	next "SPCL.ATK"
-	next "SPCL.DEF"
-	next "SPEED"
-	next "@"
-
-GetGender: ; 50bdd
-; Return the gender of a given monster (CurPartyMon/CurOTMon/CurWildMon).
-; When calling this function, a should be set to an appropriate MonType value.
-
-; return values:
-; a = 1: f = nc|nz; male
-; a = 0: f = nc|z;  female
-;        f = c:  genderless
-
-; This is determined by comparing the Attack and Speed DVs
-; with the species' gender ratio.
-
-; Figure out what type of monster struct we're looking at.
-
-; 0: PartyMon
-	ld hl, PartyMon1DVs
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, [MonType]
-	and a
-	jr z, .PartyMon
-
-; 1: OTPartyMon
-	ld hl, OTPartyMon1DVs
-	dec a
-	jr z, .PartyMon
-
-; 2: sBoxMon
-	ld hl, sBoxMon1DVs
-	ld bc, BOXMON_STRUCT_LENGTH
-	dec a
-	jr z, .sBoxMon
-
-; 3: Unknown
-	ld hl, TempMonDVs
-	dec a
-	jr z, .DVs
-
-; else: WildMon
-	ld hl, EnemyMonDVs
-	jr .DVs
-
-; Get our place in the party/box.
-
-.PartyMon:
-.sBoxMon
-	ld a, [CurPartyMon]
-	call AddNTimes
-
-.DVs:
-
-; sBoxMon data is read directly from SRAM.
-	ld a, [MonType]
-	cp BOXMON
-	ld a, 1
-	call z, GetSRAMBank
-
-; Attack DV
-	ld a, [hli]
-	and $f0
-	ld b, a
-; Speed DV
-	ld a, [hl]
-	and $f0
-	swap a
-
-; Put our DVs together.
-	or b
-	ld b, a
-
-; Close SRAM if we were dealing with a sBoxMon.
-	ld a, [MonType]
-	cp BOXMON
-	call z, CloseSRAM
-
-; We need the gender ratio to do anything with this.
-	push bc
-	ld a, [CurPartySpecies]
-	dec a
-	ld hl, BaseData + BASE_GENDER
-	ld bc, BASE_DATA_SIZE
-	call AddNTimes
-	pop bc
-
-	ld a, BANK(BaseData)
-	call GetFarByte
-
-; The higher the ratio, the more likely the monster is to be female.
-
-	cp GENDERLESS
-	jr z, .Genderless
-
-	and a ; GENDER_F0?
-	jr z, .Male
-
-	cp GENDER_F100
-	jr z, .Female
-
-; Values below the ratio are male, and vice versa.
-	cp b
-	jr c, .Male
-
-.Female:
-	xor a
-	ret
-
-.Male:
-	ld a, 1
-	and a
-	ret
-
-.Genderless:
-	scf
-	ret
-
-ListMovePP: ; 50c50
-	ld a, [wNumMoves]
-	inc a
-	ld c, a
-	ld a, NUM_MOVES
-	sub c
-	ld b, a
-	push hl
-	ld a, [Buffer1]
-	ld e, a
-	ld d, $0
-	ld a, $3e ; P
-	call .load_loop
-	ld a, b
-	and a
-	jr z, .skip
-	ld c, a
-	ld a, "-"
-	call .load_loop
-
-.skip
-	pop hl
-	inc hl
-	inc hl
-	inc hl
-	ld d, h
-	ld e, l
-	ld hl, TempMonMoves
-	ld b, 0
-.loop
-	ld a, [hli]
-	and a
-	jr z, .done
-	push bc
-	push hl
-	push de
-	ld hl, wMenuCursorY
-	ld a, [hl]
-	push af
-	ld [hl], b
-	push hl
-	callab GetMaxPPOfMove
-	pop hl
-	pop af
-	ld [hl], a
-	pop de
-	pop hl
-	push hl
-	ld bc, TempMonPP - (TempMonMoves + 1)
-	add hl, bc
-	ld a, [hl]
-	and $3f
-	ld [StringBuffer1 + 4], a
-	ld h, d
-	ld l, e
-	push hl
-	ld de, StringBuffer1 + 4
-	lb bc, 1, 2
-	call PrintNum
-	ld a, "/"
-	ld [hli], a
-	ld de, wd265
-	lb bc, 1, 2
-	call PrintNum
-	pop hl
-	ld a, [Buffer1]
-	ld e, a
-	ld d, 0
-	add hl, de
-	ld d, h
-	ld e, l
-	pop hl
-	pop bc
-	inc b
-	ld a, b
-	cp NUM_MOVES
-	jr nz, .loop
-
-.done
-	ret
-
-.load_loop ; 50cc9
-	ld [hli], a
-	ld [hld], a
-	add hl, de
-	dec c
-	jr nz, .load_loop
-	ret
-
-Function50cd0: ; 50cd0
-; XXX
-.loop
-	ld [hl], $32
-	inc hl
-	ld [hl], $3e
-	dec hl
-	add hl, de
-	dec c
-	jr nz, .loop
-	ret
-
-Predef22: ; unreferenced predef
-	push hl
-	push hl
-	ld hl, PartyMonNicknames
-	ld a, [CurPartyMon]
-	call GetNick
-	pop hl
-	call PlaceString
-	call CopyPkmnToTempMon
-	pop hl
-	ld a, [CurPartySpecies]
-	cp EGG
-	jr z, .egg
-	push hl
-	ld bc, -12
-	add hl, bc
-	ld b, $0
-	call DrawEnemyHP
-	pop hl
-	ld bc, 5
-	add hl, bc
-	push de
-	call PrintLevel
-	pop de
-
-.egg
-	ret
-
-PlaceStatusString: ; 50d0a
-	push de
-	inc de
-	inc de
-	ld a, [de]
-	ld b, a
-	inc de
-	ld a, [de]
-	or b
-	pop de
-	jr nz, PlaceNonFaintStatus
-	push de
-	ld de, FntString
-	call CopyStatusString
-	pop de
-	ld a, $1
-	and a
-	ret
-
-FntString: ; 50d22
-	db "FNT@"
-
-CopyStatusString: ; 50d25
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	ld [hl], a
-	ret
-
-PlaceNonFaintStatus: ; 50d2e
-	push de
-	ld a, [de]
-	ld de, PsnString
-	bit PSN, a
-	jr nz, .place
-	ld de, BrnString
-	bit BRN, a
-	jr nz, .place
-	ld de, FrzString
-	bit FRZ, a
-	jr nz, .place
-	ld de, ParString
-	bit PAR, a
-	jr nz, .place
-	ld de, SlpString
-	and SLP
-	jr z, .no_status
-
-.place
-	call CopyStatusString
-	ld a, $1
-	and a
-
-.no_status
-	pop de
-	ret
-
-SlpString: db "SLP@"
-PsnString: db "PSN@"
-BrnString: db "BRN@"
-FrzString: db "FRZ@"
-ParString: db "PAR@"
-
-ListMoves: ; 50d6f
-; List moves at hl, spaced every [Buffer1] tiles.
-	ld de, wListMoves_MoveIndicesBuffer
-	ld b, $0
-.moves_loop
-	ld a, [de]
-	inc de
-	and a
-	jr z, .no_more_moves
-	push de
-	push hl
-	push hl
-	ld [CurSpecies], a
-	ld a, MOVE_NAME
-	ld [wNamedObjectTypeBuffer], a
-	call GetName
-	ld de, StringBuffer1
-	pop hl
-	push bc
-	call PlaceString
-	pop bc
-	ld a, b
-	ld [wNumMoves], a
-	inc b
-	pop hl
-	push bc
-	ld a, [Buffer1]
-	ld c, a
-	ld b, 0
-	add hl, bc
-	pop bc
-	pop de
-	ld a, b
-	cp NUM_MOVES
-	jr z, .done
-	jr .moves_loop
-
-.no_more_moves
-	ld a, b
-.nonmove_loop
-	push af
-	ld [hl], "-"
-	ld a, [Buffer1]
-	ld c, a
-	ld b, 0
-	add hl, bc
-	pop af
-	inc a
-	cp NUM_MOVES
-	jr nz, .nonmove_loop
-
-.done
-	ret
-
 InitList: ; 50db9
 	ld a, [wInitListType]
 
@@ -4204,169 +1469,8 @@
 	ld [wItemAttributesPtr + 1], a
 	ret
 
-CalcLevel: ; 50e1b
-	ld a, [TempMonSpecies]
-	ld [CurSpecies], a
-	call GetBaseData
-	ld d, 1
-.next_level
-	inc d
-	ld a, d
-	cp (MAX_LEVEL + 1) % $100
-	jr z, .got_level
-	call CalcExpAtLevel
-	push hl
-	ld hl, TempMonExp + 2
-	ld a, [hProduct + 3]
-	ld c, a
-	ld a, [hld]
-	sub c
-	ld a, [hProduct + 2]
-	ld c, a
-	ld a, [hld]
-	sbc c
-	ld a, [hProduct + 1]
-	ld c, a
-	ld a, [hl]
-	sbc c
-	pop hl
-	jr nc, .next_level
+INCLUDE "engine/experience.asm"
 
-.got_level
-	dec d
-	ret
-
-CalcExpAtLevel: ; 50e47
-; (a/b)*n**3 + c*n**2 + d*n - e
-	ld a, [BaseGrowthRate]
-	add a
-	add a
-	ld c, a
-	ld b, 0
-	ld hl, GrowthRates
-	add hl, bc
-; Cube the level
-	call .LevelSquared
-	ld a, d
-	ld [hMultiplier], a
-	call Multiply
-
-; Multiply by a
-	ld a, [hl]
-	and $f0
-	swap a
-	ld [hMultiplier], a
-	call Multiply
-; Divide by b
-	ld a, [hli]
-	and $f
-	ld [hDivisor], a
-	ld b, 4
-	call Divide
-; Push the cubic term to the stack
-	ld a, [hQuotient + 0]
-	push af
-	ld a, [hQuotient + 1]
-	push af
-	ld a, [hQuotient + 2]
-	push af
-; Square the level and multiply by the lower 7 bits of c
-	call .LevelSquared
-	ld a, [hl]
-	and $7f
-	ld [hMultiplier], a
-	call Multiply
-; Push the absolute value of the quadratic term to the stack
-	ld a, [hProduct + 1]
-	push af
-	ld a, [hProduct + 2]
-	push af
-	ld a, [hProduct + 3]
-	push af
-	ld a, [hli]
-	push af
-; Multiply the level by d
-	xor a
-	ld [hMultiplicand + 0], a
-	ld [hMultiplicand + 1], a
-	ld a, d
-	ld [hMultiplicand + 2], a
-	ld a, [hli]
-	ld [hMultiplier], a
-	call Multiply
-; Subtract e
-	ld b, [hl]
-	ld a, [hProduct + 3]
-	sub b
-	ld [hMultiplicand + 2], a
-	ld b, $0
-	ld a, [hProduct + 2]
-	sbc b
-	ld [hMultiplicand + 1], a
-	ld a, [hProduct + 1]
-	sbc b
-	ld [hMultiplicand], a
-; If bit 7 of c is set, c is negative; otherwise, it's positive
-	pop af
-	and $80
-	jr nz, .subtract
-; Add c*n**2 to (d*n - e)
-	pop bc
-	ld a, [hProduct + 3]
-	add b
-	ld [hMultiplicand + 2], a
-	pop bc
-	ld a, [hProduct + 2]
-	adc b
-	ld [hMultiplicand + 1], a
-	pop bc
-	ld a, [hProduct + 1]
-	adc b
-	ld [hMultiplicand], a
-	jr .done_quadratic
-
-.subtract
-; Subtract c*n**2 from (d*n - e)
-	pop bc
-	ld a, [hProduct + 3]
-	sub b
-	ld [hMultiplicand + 2], a
-	pop bc
-	ld a, [hProduct + 2]
-	sbc b
-	ld [hMultiplicand + 1], a
-	pop bc
-	ld a, [hProduct + 1]
-	sbc b
-	ld [hMultiplicand], a
-
-.done_quadratic
-; Add (a/b)*n**3 to (d*n - e +/- c*n**2)
-	pop bc
-	ld a, [hProduct + 3]
-	add b
-	ld [hMultiplicand + 2], a
-	pop bc
-	ld a, [hProduct + 2]
-	adc b
-	ld [hMultiplicand + 1], a
-	pop bc
-	ld a, [hProduct + 1]
-	adc b
-	ld [hMultiplicand], a
-	ret
-
-.LevelSquared: ; 50eed
-	xor a
-	ld [hMultiplicand + 0], a
-	ld [hMultiplicand + 1], a
-	ld a, d
-	ld [hMultiplicand + 2], a
-	ld [hMultiplier], a
-	jp Multiply
-
-INCLUDE "data/growth_rates.asm"
-
 _SwitchPartyMons:
 	ld a, [wd0e3]
 	dec a
@@ -4514,11 +1618,8 @@
 	ret
 
 INCLUDE "gfx/load_pics.asm"
-
 INCLUDE "engine/move_mon_wo_mail.asm"
-
 INCLUDE "data/pokemon/base_stats.asm"
-
 INCLUDE "data/pokemon/pokemon_names.asm"
 
 Unknown_53d84: ; unreferenced
@@ -4564,274 +1665,7 @@
 SECTION "bank22", ROMX
 
 INCLUDE "event/kurt.asm"
-
-Function88248: ; 88248
-; XXX
-	ld c, CAL
-	ld a, [PlayerGender]
-	bit 0, a
-	jr z, .okay
-	ld c, KAREN
-
-.okay
-	ld a, c
-	ld [TrainerClass], a
-	ret
-
-MovePlayerPicRight: ; 88258
-	hlcoord 6, 4
-	ld de, 1
-	jr MovePlayerPic
-
-MovePlayerPicLeft: ; 88260
-	hlcoord 13, 4
-	ld de, -1
-	; fallthrough
-
-MovePlayerPic: ; 88266
-; Move player pic at hl by de * 7 tiles.
-	ld c, $8
-.loop
-	push bc
-	push hl
-	push de
-	xor a
-	ld [hBGMapMode], a
-	lb bc, 7, 7
-	predef PlaceGraphic
-	xor a
-	ld [hBGMapThird], a
-	call WaitBGMap
-	call DelayFrame
-	pop de
-	pop hl
-	add hl, de
-	pop bc
-	dec c
-	ret z
-	push hl
-	push bc
-	ld a, l
-	sub e
-	ld l, a
-	ld a, h
-	sbc d
-	ld h, a
-	lb bc, 7, 7
-	call ClearBox
-	pop bc
-	pop hl
-	jr .loop
-
-ShowPlayerNamingChoices: ; 88297
-	ld hl, ChrisNameMenuHeader
-	ld a, [PlayerGender]
-	bit 0, a
-	jr z, .GotGender
-	ld hl, KrisNameMenuHeader
-.GotGender:
-	call LoadMenuDataHeader
-	call VerticalMenu
-	ld a, [wMenuCursorY]
-	dec a
-	call CopyNameFromMenu
-	call CloseWindow
-	ret
-
-ChrisNameMenuHeader: ; 882b5
-	db $40 ; flags
-	db 00, 00 ; start coords
-	db 11, 10 ; end coords
-	dw .MaleNames
-	db 1 ; ????
-	db 0 ; default option
-
-.MaleNames: ; 882be
-	db $91 ; flags
-	db 5 ; items
-	db "NEW NAME@"
-MalePlayerNameArray: ; 882c9
-	db "CHRIS@"
-	db "MAT@"
-	db "ALLAN@"
-	db "JON@"
-	db 2 ; displacement
-	db " NAME @" ; title
-
-KrisNameMenuHeader: ; 882e5
-	db $40 ; flags
-	db 00, 00 ; start coords
-	db 11, 10 ; end coords
-	dw .FemaleNames
-	db 1 ; ????
-	db 0 ; default option
-
-.FemaleNames: ; 882ee
-	db $91 ; flags
-	db 5 ; items
-	db "NEW NAME@"
-FemalePlayerNameArray: ; 882f9
-	db "KRIS@"
-	db "AMANDA@"
-	db "JUANA@"
-	db "JODI@"
-	db 2 ; displacement
-	db " NAME @" ; title
-
-GetPlayerNameArray: ; 88318 This Function is never called
-	ld hl, PlayerName
-	ld de, MalePlayerNameArray
-	ld a, [PlayerGender]
-	bit 0, a
-	jr z, .done
-	ld de, FemalePlayerNameArray
-
-.done
-	call InitName
-	ret
-
-GetPlayerIcon: ; 8832c
-; Get the player icon corresponding to gender
-
-; Male
-	ld de, ChrisSpriteGFX
-	ld b, BANK(ChrisSpriteGFX)
-
-	ld a, [PlayerGender]
-	bit 0, a
-	jr z, .done
-
-; Female
-	ld de, KrisSpriteGFX
-	ld b, BANK(KrisSpriteGFX)
-
-.done
-	ret
-
-GetCardPic: ; 8833e
-	ld hl, ChrisCardPic
-	ld a, [PlayerGender]
-	bit 0, a
-	jr z, .GotClass
-	ld hl, KrisCardPic
-.GotClass:
-	ld de, VTiles2 tile $00
-	ld bc, $23 tiles
-	ld a, BANK(ChrisCardPic) ; BANK(KrisCardPic)
-	call FarCopyBytes
-	ld hl, CardGFX
-	ld de, VTiles2 tile $23
-	ld bc, 6 tiles
-	ld a, BANK(CardGFX)
-	call FarCopyBytes
-	ret
-
-ChrisCardPic: ; 88365
-INCBIN "gfx/trainer_card/chris_card.2bpp"
-
-KrisCardPic: ; 88595
-INCBIN "gfx/trainer_card/kris_card.2bpp"
-
-CardGFX: ; 887c5
-INCBIN "gfx/trainer_card/trainer_card.2bpp"
-
-GetPlayerBackpic: ; 88825
-	ld a, [PlayerGender]
-	bit 0, a
-	jr z, GetChrisBackpic
-	call GetKrisBackpic
-	ret
-
-GetChrisBackpic: ; 88830
-	ld hl, ChrisBackpic
-	ld b, BANK(ChrisBackpic)
-	ld de, VTiles2 tile $31
-	ld c, 7 * 7
-	predef DecompressPredef
-	ret
-
-HOF_LoadTrainerFrontpic: ; 88840
-	call WaitBGMap
-	xor a
-	ld [hBGMapMode], a
-	ld e, 0
-	ld a, [PlayerGender]
-	bit 0, a
-	jr z, .GotClass
-	ld e, 1
-
-.GotClass:
-	ld a, e
-	ld [TrainerClass], a
-	ld de, ChrisPic
-	ld a, [PlayerGender]
-	bit 0, a
-	jr z, .GotPic
-	ld de, KrisPic
-
-.GotPic:
-	ld hl, VTiles2
-	ld b, BANK(ChrisPic) ; BANK(KrisPic)
-	ld c, 7 * 7
-	call Get2bpp
-	call WaitBGMap
-	ld a, $1
-	ld [hBGMapMode], a
-	ret
-
-DrawIntroPlayerPic: ; 88874
-; Draw the player pic at (6,4).
-
-; Get class
-	ld e, CHRIS
-	ld a, [PlayerGender]
-	bit 0, a
-	jr z, .GotClass
-	ld e, KRIS
-.GotClass:
-	ld a, e
-	ld [TrainerClass], a
-
-; Load pic
-	ld de, ChrisPic
-	ld a, [PlayerGender]
-	bit 0, a
-	jr z, .GotPic
-	ld de, KrisPic
-.GotPic:
-	ld hl, VTiles2
-	ld b, BANK(ChrisPic) ; BANK(KrisPic)
-	ld c, 7 * 7 ; dimensions
-	call Get2bpp
-
-; Draw
-	xor a
-	ld [hGraphicStartTile], a
-	hlcoord 6, 4
-	lb bc, 7, 7
-	predef PlaceGraphic
-	ret
-
-ChrisPic: ; 888a9
-INCBIN "gfx/player/chris.2bpp"
-
-KrisPic: ; 88bb9
-INCBIN "gfx/player/kris.2bpp"
-
-GetKrisBackpic: ; 88ec9
-; Kris's backpic is uncompressed.
-	ld de, KrisBackpic
-	ld hl, VTiles2 tile $31
-	lb bc, BANK(KrisBackpic), 7 * 7 ; dimensions
-	call Get2bpp
-	ret
-
-KrisBackpic: ; 88ed6
-INCBIN "gfx/player/kris_back.2bpp"
-
-String_89116:
-	db "-----@"
-
+INCLUDE "engine/player_gfx.asm"
 INCLUDE "mobile/mobile_22.asm"
 INCLUDE "event/unown.asm"
 INCLUDE "event/buena.asm"
@@ -4842,22 +1676,8 @@
 
 SECTION "bank23", ROMX
 
-Predef35: ; 8c000
-Predef36:
-	ret
-
 INCLUDE "engine/timeofdaypals.asm"
-INCLUDE "engine/battle_start.asm"
-
-Function8c7c9:
-; XXX
-	ld a, $1
-	ld [hBGMapMode], a
-	call WaitBGMap
-	xor a
-	ld [hBGMapMode], a
-	ret
-
+INCLUDE "engine/battle_transition.asm"
 INCLUDE "event/field_moves.asm"
 INCLUDE "event/magnet_train.asm"
 
@@ -4916,39 +1736,7 @@
 
 INCLUDE "engine/std_scripts.asm"
 INCLUDE "engine/phone_scripts.asm"
-
-TalkToTrainerScript:: ; 0xbe66a
-	faceplayer
-	trainerflagaction CHECK_FLAG
-	iftrue AlreadyBeatenTrainerScript
-	loadmemtrainer
-	encountermusic
-	jump StartBattleWithMapTrainerScript
-
-SeenByTrainerScript:: ; 0xbe675
-	loadmemtrainer
-	encountermusic
-	showemote EMOTE_SHOCK, LAST_TALKED, 30
-	callasm TrainerWalkToPlayer
-	applymovement2 MovementBuffer
-	writepersonxy LAST_TALKED
-	faceperson PLAYER, LAST_TALKED
-	jump StartBattleWithMapTrainerScript
-
-StartBattleWithMapTrainerScript: ; 0xbe68a
-	opentext
-	trainertext $0
-	waitbutton
-	closetext
-	loadmemtrainer
-	startbattle
-	reloadmapafterbattle
-	trainerflagaction SET_FLAG
-	loadvar wRunningTrainerBattleScript, -1
-
-AlreadyBeatenTrainerScript:
-	scripttalkafter
-
+INCLUDE "engine/trainer_scripts.asm"
 INCLUDE "gfx/sprites.asm"
 
 
@@ -5012,114 +1800,7 @@
 
 SECTION "bank33", ROMX
 
-DisplayCaughtContestMonStats: ; cc000
-	call ClearBGPalettes
-	call ClearTileMap
-	call ClearSprites
-	call LoadFontsBattleExtra
-
-	ld hl, Options
-	ld a, [hl]
-	push af
-	set 4, [hl]
-
-	hlcoord 0, 0
-	ld b, 4
-	ld c, 13
-	call TextBox
-
-	hlcoord 0, 6
-	ld b, 4
-	ld c, 13
-	call TextBox
-
-	hlcoord 2, 0
-	ld de, .Stock
-	call PlaceString
-
-	hlcoord 2, 6
-	ld de, .This
-	call PlaceString
-
-	hlcoord 5, 4
-	ld de, .Health
-	call PlaceString
-
-	hlcoord 5, 10
-	ld de, .Health
-	call PlaceString
-
-	ld a, [wContestMon]
-	ld [wd265], a
-	call GetPokemonName
-	ld de, StringBuffer1
-	hlcoord 1, 2
-	call PlaceString
-
-	ld h, b
-	ld l, c
-	ld a, [wContestMonLevel]
-	ld [TempMonLevel], a
-	call PrintLevel
-
-	ld de, EnemyMonNick
-	hlcoord 1, 8
-	call PlaceString
-
-	ld h, b
-	ld l, c
-	ld a, [EnemyMonLevel]
-	ld [TempMonLevel], a
-	call PrintLevel
-
-	hlcoord 11, 4
-	ld de, wContestMonMaxHP
-	lb bc, 2, 3
-	call PrintNum
-
-	hlcoord 11, 10
-	ld de, EnemyMonMaxHP
-	call PrintNum
-
-	ld hl, SwitchMonText
-	call PrintText
-
-	pop af
-	ld [Options], a
-
-	call WaitBGMap
-	ld b, SCGB_DIPLOMA
-	call GetSGBLayout
-	call SetPalettes
-	ret
-
-.Health:
-	db "HEALTH@"
-.Stock:
-	db " STOCK ", $4a, " @"
-.This:
-	db " THIS ", $4a, "  @"
-
-SwitchMonText: ; cc0c2
-	; Switch #MON?
-	text_jump UnknownText_0x1c10cf
-	db "@"
-
-DisplayAlreadyCaughtText: ; cc0c7
-	call GetPokemonName
-	ld hl, .AlreadyCaughtText
-	jp PrintText
-
-.AlreadyCaughtText: ; 0xcc0d0
-	; You already caught a @ .
-	text_jump UnknownText_0x1c10dd
-	db "@"
-
-Predef2F:
-Predef38:
-Predef39: ; cc0d5
-	ret
-
+INCLUDE "event/bug_contest_mon_stats.asm"
 INCLUDE "battle/anim_commands.asm"
 INCLUDE "battle/anim_objects.asm"
 
@@ -5331,25 +2012,9 @@
 INCLUDE "engine/mysterygift.asm"
 INCLUDE "battle/used_move_text.asm"
 INCLUDE "mobile/mobile_41.asm"
+INCLUDE "gfx/overworld_font.asm"
 
-LoadOverworldFont:: ; 106594
-	ld de, .font
-	ld hl, VTiles1
-	lb bc, BANK(.font), $80
-	call Get2bpp
-	ld de, .space
-	ld hl, VTiles2 tile $7f
-	lb bc, BANK(.space), 1
-	call Get2bpp
-	ret
-; 1065ad
 
-.font
-INCBIN "gfx/font/overworld.2bpp"
-.space
-INCBIN "gfx/font/space.2bpp"
-
-
 SECTION "mobile_42", ROMX
 
 INCLUDE "mobile/mobile_42.asm"
@@ -5403,7 +2068,6 @@
 	ret
 
 INCLUDE "mobile/mobile_5e.asm"
-
 INCLUDE "mobile/mobile_5f.asm"
 
 
@@ -5515,214 +2179,9 @@
 String_PM: db "PM@" ; 1dd6ff
 
 INCLUDE "engine/diploma.asm"
+INCLUDE "engine/pokedex_3.asm"
+INCLUDE "event/catch_tutorial_input.asm"
 
-LoadSGBPokedexGFX: ; 1ddf1c
-	ld hl, SGBPokedexGFX_LZ
-	ld de, VTiles2 tile $31
-	call Decompress
-	ret
-
-LoadSGBPokedexGFX2: ; 1ddf26 (77:5f26)
-	ld hl, SGBPokedexGFX_LZ
-	ld de, VTiles2 tile $31
-	lb bc, BANK(SGBPokedexGFX_LZ), $3a
-	call DecompressRequest2bpp
-	ret
-
-SGBPokedexGFX_LZ: ; 1ddf33
-INCBIN "gfx/pokedex/sgb.2bpp.lz"
-
-LoadQuestionMarkPic: ; 1de0d7
-	ld hl, .QuestionMarkLZ
-	ld de, sScratch
-	call Decompress
-	ret
-
-.QuestionMarkLZ: ; 1de0e1
-INCBIN "gfx/pics/questionmark/front.2bpp.lz"
-
-DrawPokedexListWindow: ; 1de171 (77:6171)
-	ld a, $32
-	hlcoord 0, 17
-	ld bc, 12
-	call ByteFill
-	hlcoord 0, 1
-	lb bc, 15, 11
-	call ClearBox
-	ld a, $34
-	hlcoord 0, 0
-	ld bc, 11
-	call ByteFill
-	ld a, $39
-	hlcoord 0, 16
-	ld bc, 11
-	call ByteFill
-	hlcoord 5, 0
-	ld [hl], $3f
-	hlcoord 5, 16
-	ld [hl], $40
-	ld a, [wCurrentDexMode]
-	cp DEXMODE_OLD
-	jr z, .OldMode
-; scroll bar
-	hlcoord 11, 0
-	ld [hl], $50
-	ld a, $51
-	hlcoord 11, 1
-	ld b, SCREEN_HEIGHT - 3
-	call Bank77_FillColumn
-	ld [hl], $52
-	jr .Done
-
-.OldMode:
-; no scroll bar
-	hlcoord 11, 0
-	ld [hl], $66
-	ld a, $67
-	hlcoord 11, 1
-	ld b, SCREEN_HEIGHT - 3
-	call Bank77_FillColumn
-	ld [hl], $68
-.Done:
-	ret
-
-DrawPokedexSearchResultsWindow: ; 1de1d1 (77:61d1)
-	ld a, $34
-	hlcoord 0, 0
-	ld bc, 11
-	call ByteFill
-	ld a, $39
-	hlcoord 0, 10
-	ld bc, 11
-	call ByteFill
-	hlcoord 5, 0
-	ld [hl], $3f
-	hlcoord 5, 10
-	ld [hl], $40
-	hlcoord 11, 0
-	ld [hl], $66
-	ld a, $67
-	hlcoord 11, 1
-	ld b, SCREEN_HEIGHT / 2
-	call Bank77_FillColumn
-	ld [hl], $68
-	ld a, $34
-	hlcoord 0, 11
-	ld bc, 11
-	call ByteFill
-	ld a, $39
-	hlcoord 0, 17
-	ld bc, 11
-	call ByteFill
-	hlcoord 11, 11
-	ld [hl], $66
-	ld a, $67
-	hlcoord 11, 12
-	ld b, 5
-	call Bank77_FillColumn
-	ld [hl], $68
-	hlcoord 0, 12
-	lb bc, 5, 11
-	call ClearBox
-	ld de, .esults_D
-	hlcoord 0, 12
-	call PlaceString
-	ret
-
-.esults_D ; 1de23c
-; (SEARCH R)
-	db   "ESULTS"
-	next ""
-; (### FOUN)
-	next "D!@"
-
-DrawDexEntryScreenRightEdge: ; 1de247
-	ld a, [hBGMapAddress]
-	ld l, a
-	ld a, [hBGMapAddress + 1]
-	ld h, a
-	push hl
-	inc hl
-	ld a, l
-	ld [hBGMapAddress], a
-	ld a, h
-	ld [hBGMapAddress + 1], a
-	hlcoord 19, 0
-	ld [hl], $66
-	hlcoord 19, 1
-	ld a, $67
-	ld b, 15
-	call Bank77_FillColumn
-	ld [hl], $68
-	hlcoord 19, 17
-	ld [hl], $3c
-	xor a
-	ld b, SCREEN_HEIGHT
-	hlcoord 19, 0, AttrMap
-	call Bank77_FillColumn
-	call WaitBGMap2
-	pop hl
-	ld a, l
-	ld [hBGMapAddress], a
-	ld a, h
-	ld [hBGMapAddress + 1], a
-	ret
-
-Bank77_FillColumn: ; 1de27f
-	push de
-	ld de, SCREEN_WIDTH
-.loop
-	ld [hl], a
-	add hl, de
-	dec b
-	jr nz, .loop
-	pop de
-	ret
-
-_DudeAutoInput_A:: ; 1de28a
-	ld hl, DudeAutoInput_A
-	jr _DudeAutoInput
-
-_DudeAutoInput_RightA: ; 1de28f
-	ld hl, DudeAutoInput_RightA
-	jr _DudeAutoInput
-
-_DudeAutoInput_DownA: ; 1de294
-	ld hl, DudeAutoInput_DownA
-	jr _DudeAutoInput
-
-_DudeAutoInput: ; 1de299
-	ld a, BANK(DudeAutoInputs)
-	call StartAutoInput
-	ret
-
-DudeAutoInputs:
-
-DudeAutoInput_A: ; 1de29f
-	db NO_INPUT, $50
-	db A_BUTTON, $00
-	db NO_INPUT, $ff ; end
-
-DudeAutoInput_RightA: ; 1de2a5
-	db NO_INPUT, $08
-	db D_RIGHT,  $00
-	db NO_INPUT, $08
-	db A_BUTTON, $00
-	db NO_INPUT, $ff ; end
-
-DudeAutoInput_DownA: ; 1de2af
-	db NO_INPUT, $fe
-	db NO_INPUT, $fe
-	db NO_INPUT, $fe
-	db NO_INPUT, $fe
-	db D_DOWN,   $00
-	db NO_INPUT, $fe
-	db NO_INPUT, $fe
-	db NO_INPUT, $fe
-	db NO_INPUT, $fe
-	db A_BUTTON, $00
-	db NO_INPUT, $ff ; end
-
 TownMap_ConvertLineBreakCharacters: ; 1de2c5
 	ld hl, StringBuffer1
 .loop
@@ -5748,135 +2207,7 @@
 PokegearGFX: ; 1de2e4
 INCBIN "gfx/pokegear/pokegear.2bpp.lz"
 
-IsMailEuropean: ; 1de5c8
-; return 1 if French
-; return 2 if German
-; return 3 if Italian
-; return 4 if Spanish
-; return 0 if none of the above
-	ld c, $0
-	ld hl, sPartyMon1MailAuthorNationality - sPartyMon1Mail
-	add hl, de
-	ld a, [hli]
-	cp "E"
-	ret nz
-	ld a, [hli]
-	inc c
-	cp "F"
-	ret z
-	inc c
-	cp "G"
-	ret z
-	inc c
-	cp "I"
-	ret z
-	inc c
-	cp "S"
-	ret z
-	ld c, $0
-	ret
-
-; The regular font.
-StandardEnglishFont: ; 1de5e6
-INCBIN "gfx/font/english.1bpp"
-
-; An extended font.
-FrenchGermanFont: ; 1de9e6
-INCBIN "gfx/font/french_german.1bpp"
-
-; An even more extended font.
-SpanishItalianFont: ; 1dede6
-INCBIN "gfx/font/spanish_italian.1bpp"
-
-HandleFrenchGermanMail: ; 1df1e6
-; called if mail is french or german
-; fix 's 't 'v
-	ld b, sPartyMon1MailAuthor - sPartyMon1Mail
-	ld h, d
-	ld l, e
-.loop
-	ld a, [hl]
-	cp $dc ; 's in french/german font
-	jr nz, .check_intermediate_chars
-	ld a, "'s"
-	jr .replace
-
-.check_intermediate_chars
-	sub "'s"
-	jr c, .dont_replace
-	cp "'v" - "'s" + 1
-	jr nc, .dont_replace
-	add $cd
-
-.replace
-	ld [hl], a
-
-.dont_replace
-	inc hl
-	dec b
-	jr nz, .loop
-	ret
-
-LireLeCourrierAnglais:
-DeutenEnglischenPost: ; 1df203
-; Cette fonction convertit certains des caractères anglais pour
-; leur équivalent dans le jeu de caractères français.
-; Diese Funktion wandelt bestimmte englische Zeichen, um ihre
-; Entsprechung in der Deutschen-Zeichensatz.
-	ld b, sPartyMon1MailAuthor - sPartyMon1Mail
-	ld h, d
-	ld l, e
-.loop
-	ld a, [hl]
-	cp "'s"
-	jr nz, .check_intermediate_chars
-	ld a, $dc
-	jr .replace
-
-.check_intermediate_chars
-	sub $cd
-	jr c, .dont_replace
-	cp "'v" - "'s" + 1
-	jr nc, .dont_replace
-	add "'s"
-
-.replace
-	ld [hl], a
-
-.dont_replace
-	inc hl
-	dec b
-	jr nz, .loop
-	ret
-
-HandleSpanishItalianMail: ; 1df220
-LeerCorreosIngleses:
-LeggiPostaInglese:
-; This function converts certain characters between
-; the English and Spanish/Italian character sets.
-; Esta función convierte ciertos caracteres entre
-; el juego de caracteres Inglés y Español.
-; Questa funzione converte alcuni caratteri tra
-; l'inglese e il set di caratteri italiani.
-	ld b, sPartyMon1MailAuthor - sPartyMon1Mail
-	ld h, d
-	ld l, e
-.loop
-	ld a, [hl]
-	and $f0
-	cp $d0
-	jr nz, .dont_replace
-	ld a, [hl]
-	add $8
-	and $f
-	or $d0
-	ld [hl], a
-
-.dont_replace
-	inc hl
-	dec b
-	jr nz, .loop
-	ret
+INCLUDE "engine/european_mail.asm"
 
 
 SECTION "Battle Tower Text", ROMX
--- a/maps/GoldenrodNameRater.asm
+++ b/maps/GoldenrodNameRater.asm
@@ -22,7 +22,7 @@
 GoldenrodNameRaterRadio:
 	jumpstd radio2
 
-INCLUDE "text/sweethoney.asm"
+INCLUDE "text/unused_sweet_honey.asm"
 
 GoldenrodNameRater_MapEventHeader:
 	; filler
--- a/mobile/mobile_22.asm
+++ b/mobile/mobile_22.asm
@@ -1,3 +1,5 @@
+String_89116:
+	db "-----@"
 
 String_8911c: ; 8911c
 	db   "でんわばんごうが ただしく"   ; Phone number is not
--- a/text/sweethoney.asm
+++ /dev/null
@@ -1,68 +1,0 @@
-; Sweet Honey is a feature that was scrapped before development.
-; It was later implemented in Pokémon Diamond and Pearl.
-;
-; Sweet Honey was probably reworked into Sweet Scent.
-; A map in the final game has a Butterfree and a woman who gives
-; the Sweet Scent TM.
-
-; Most of these texts seem to be associated with a single NPC.
-; The last text is associated with a second NPC, probably a Butterfree.
-
-UnusedSweetHoneyText: ; 0x5578a
-	text "My #MON is an"
-	line "expert at collect-"
-	cont "ing SWEET HONEY."
-
-	para "I'll share some"
-	line "with you."
-	done
-
-UnusedSweetHoneyBagFullText: ; 0x557d6
-	text "I want to give you"
-	line "some SWEET HONEY,"
-
-	para "but you have no"
-	line "room for it."
-	done
-
-UnusedSweetHoneyGiveText: ; 0x55819
-	text "Here you go! Have"
-	line "some SWEET HONEY!"
-	done
-
-UnusedGotSweetHoneyText: ; 0x5583e
-	text "<PLAYER> received"
-	line "SWEET HONEY."
-	done
-
-UnusedSweetHoneyAfterText1: ; 0x55856
-	text "My little brother"
-	line "takes SWEET HONEY"
-
-	para "and goes somewhere"
-	line "with it."
-
-	para "I wonder what he's"
-	line "up to?"
-	done
-
-UnusedSweetHoneyAfterText2: ; 0x558b1
-	text "Did you put SWEET"
-	line "HONEY on a tree?"
-
-	para "What happened to"
-	line "it?"
-	done
-
-UnusedSweetHoneyAfterText3: ; 0x558ea
-	text "Did you put SWEET"
-	line "HONEY on a tree?"
-
-	para "It takes about a"
-	line "day for #MON to"
-	cont "be drawn to it."
-	done
-
-UnusedSweetHoneyButterfreeText: ; 0x5593f
-	text "BUTTERFREE: Freeh!"
-	done
--- /dev/null
+++ b/text/unused_gen_1_trainers.asm
@@ -1,0 +1,92 @@
+GetGen1TrainerClassName: ; 50a28
+; XXX
+	ld hl, .Strings
+	ld a, [TrainerClass]
+	dec a
+	ld c, a
+	ld b, 0
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld de, StringBuffer1
+.copy
+	ld a, [hli]
+	ld [de], a
+	inc de
+	cp "@"
+	jr nz, .copy
+	ret
+
+.Strings: ; 50a42
+; Untranslated trainer class names from Red.
+	dw .Youngster
+	dw .BugCatcher
+	dw .Lass
+	dw OTClassName
+	dw .JrTrainerM
+	dw .JrTrainerF
+	dw .Pokemaniac
+	dw .SuperNerd
+	dw OTClassName
+	dw OTClassName
+	dw .Burglar
+	dw .Engineer
+	dw .Jack
+	dw OTClassName
+	dw .Swimmer
+	dw OTClassName
+	dw OTClassName
+	dw .Beauty
+	dw OTClassName
+	dw .Rocker
+	dw .Juggler
+	dw OTClassName
+	dw OTClassName
+	dw .Blackbelt
+	dw OTClassName
+	dw .ProfOak
+	dw .Chief
+	dw .Scientist
+	dw OTClassName
+	dw .Rocket
+	dw .CooltrainerM
+	dw .CooltrainerF
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+	dw OTClassName
+
+.Youngster:    db "たんパン@"
+.BugCatcher:   db "むしとり@"
+.Lass:         db "ミニスカ@"
+.JrTrainerM:   db "ボーイ@"
+.JrTrainerF:   db "ガール@"
+.Pokemaniac:   db "マニア@"
+.SuperNerd:    db "りかけい@"
+.Burglar:      db "どろぼう@"
+.Engineer:     db "ォヤジ@"
+.Jack:         db "ジャック@"
+.Swimmer:      db "かいパン@"
+.Beauty:       db "おねえさん@"
+.Rocker:       db "グループ@"
+.Juggler:      db "ジャグラー@"
+.Blackbelt:    db "からて@"
+.ProfOak:      db "ォーキド@"
+.Chief:        db "チーフ@"
+.Scientist:    db "けんきゅういん@"
+.Rocket:       db "だんいん@"
+.CooltrainerM: db "エりート♂@"
+.CooltrainerF: db "エりート♀@"
--- /dev/null
+++ b/text/unused_sweet_honey.asm
@@ -1,0 +1,68 @@
+; Sweet Honey is a feature that was scrapped before development.
+; It was later implemented in Pokémon Diamond and Pearl.
+;
+; Sweet Honey was probably reworked into Sweet Scent.
+; A map in the final game has a Butterfree and a woman who gives
+; the Sweet Scent TM.
+
+; Most of these texts seem to be associated with a single NPC.
+; The last text is associated with a second NPC, probably a Butterfree.
+
+UnusedSweetHoneyText: ; 0x5578a
+	text "My #MON is an"
+	line "expert at collect-"
+	cont "ing SWEET HONEY."
+
+	para "I'll share some"
+	line "with you."
+	done
+
+UnusedSweetHoneyBagFullText: ; 0x557d6
+	text "I want to give you"
+	line "some SWEET HONEY,"
+
+	para "but you have no"
+	line "room for it."
+	done
+
+UnusedSweetHoneyGiveText: ; 0x55819
+	text "Here you go! Have"
+	line "some SWEET HONEY!"
+	done
+
+UnusedGotSweetHoneyText: ; 0x5583e
+	text "<PLAYER> received"
+	line "SWEET HONEY."
+	done
+
+UnusedSweetHoneyAfterText1: ; 0x55856
+	text "My little brother"
+	line "takes SWEET HONEY"
+
+	para "and goes somewhere"
+	line "with it."
+
+	para "I wonder what he's"
+	line "up to?"
+	done
+
+UnusedSweetHoneyAfterText2: ; 0x558b1
+	text "Did you put SWEET"
+	line "HONEY on a tree?"
+
+	para "What happened to"
+	line "it?"
+	done
+
+UnusedSweetHoneyAfterText3: ; 0x558ea
+	text "Did you put SWEET"
+	line "HONEY on a tree?"
+
+	para "It takes about a"
+	line "day for #MON to"
+	cont "be drawn to it."
+	done
+
+UnusedSweetHoneyButterfreeText: ; 0x5593f
+	text "BUTTERFREE: Freeh!"
+	done