shithub: pokecrystal

Download patch

ref: 93e12d200300c7320640922fe6bcebe64f942eda
parent: 2650bcffad179be1a874bfaadccb0bb554d28096
author: pikalaxalt <[email protected]>
date: Sun Mar 27 08:47:28 EDT 2016

Split up banks 1-3 of main.asm

--- a/battle/anim_commands.asm
+++ b/battle/anim_commands.asm
@@ -980,7 +980,7 @@
 GetSubstitutePic: ; cc64c
 
 	ld hl, sScratch
-	ld bc, $310
+	ld bc, (7 * 7) tiles
 .loop
 	xor a
 	ld [hli], a
@@ -994,16 +994,16 @@
 	jr z, .player
 
 	ld hl, MonsterSpriteGFX + 0 tiles
-	ld de, sScratch + $13 tiles
+	ld de, sScratch + (2 * 7 + 5) tiles
 	call .CopyTile
 	ld hl, MonsterSpriteGFX + 1 tiles
-	ld de, sScratch + $1a tiles
+	ld de, sScratch + (3 * 7 + 5) tiles
 	call .CopyTile
 	ld hl, MonsterSpriteGFX + 2 tiles
-	ld de, sScratch + $14 tiles
+	ld de, sScratch + (2 * 7 + 6) tiles
 	call .CopyTile
 	ld hl, MonsterSpriteGFX + 3 tiles
-	ld de, sScratch + $1b tiles
+	ld de, sScratch + (3 * 7 + 6) tiles
 	call .CopyTile
 
 	ld hl, VTiles2 tile $00
@@ -1014,16 +1014,16 @@
 
 .player
 	ld hl, MonsterSpriteGFX + 4 tiles
-	ld de, sScratch + $10 tiles
+	ld de, sScratch + (2 * 6 + 4) tiles
 	call .CopyTile
 	ld hl, MonsterSpriteGFX + 5 tiles
-	ld de, sScratch + $16 tiles
+	ld de, sScratch + (3 * 6 + 4) tiles
 	call .CopyTile
 	ld hl, MonsterSpriteGFX + 6 tiles
-	ld de, sScratch + $11 tiles
+	ld de, sScratch + (2 * 6 + 5) tiles
 	call .CopyTile
 	ld hl, MonsterSpriteGFX + 7 tiles
-	ld de, sScratch + $17 tiles
+	ld de, sScratch + (3 * 6 + 5) tiles
 	call .CopyTile
 
 	ld hl, VTiles2 tile $31
--- a/battle/effect_commands.asm
+++ b/battle/effect_commands.asm
@@ -7873,7 +7873,7 @@
 	ld [hl], a
 	ld [de], a
 	call _CheckBattleScene
-	jr c, .mobile
+	jr c, .no_anim
 
 	xor a
 	ld [wNumHits], a
@@ -7883,7 +7883,7 @@
 	call LoadAnim
 	jr .finish
 
-.mobile
+.no_anim
 	call BattleCommand_RaiseSubNoAnim
 .finish
 	ld hl, MadeSubstituteText
--- a/constants/battle_tower_constants.asm
+++ b/constants/battle_tower_constants.asm
@@ -19,8 +19,8 @@
 	const BATTLETOWERACTION_11 ; store 0 in 5:aa8d
 	const BATTLETOWERACTION_12 ; store 1 in 5:aa8d
 	const BATTLETOWERACTION_13 ; check 5:aa8d
-	const BATTLETOWERACTION_14 ; if save file is yours: bit 0, [sbe4f]
-	const BATTLETOWERACTION_15 ; set 0, [sbe4f]
+	const BATTLETOWERACTION_14 ; if save file is yours: bit 0, [s1_be4f]
+	const BATTLETOWERACTION_15 ; set 0, [s1_be4f]
 	const BATTLETOWERACTION_16 ; update time in SRAM bank 5
 	const BATTLETOWERACTION_17 ; check time in SRAM bank 5
 	const BATTLETOWERACTION_18 ; level check
--- /dev/null
+++ b/engine/billspctop.asm
@@ -1,0 +1,388 @@
+_BillsPC: ; e3fd
+	call .CheckCanUsePC
+	ret c
+	call .LogIn
+	call .UseBillsPC
+	jp .LogOut
+
+.CheckCanUsePC: ; e40a (3:640a)
+	ld a, [PartyCount]
+	and a
+	ret nz
+	ld hl, .Text_GottaHavePokemon
+	call MenuTextBoxBackup
+	scf
+	ret
+
+.Text_GottaHavePokemon: ; 0xe417
+	; You gotta have #MON to call!
+	text_jump UnknownText_0x1c1006
+	db "@"
+
+.LogIn: ; e41c (3:641c)
+	xor a
+	ld [hBGMapMode], a
+	call LoadStandardMenuDataHeader
+	call ClearPCItemScreen
+	ld hl, Options
+	ld a, [hl]
+	push af
+	set NO_TEXT_SCROLL, [hl]
+	ld hl, .Text_What
+	call PrintText
+	pop af
+	ld [Options], a
+	call LoadFontsBattleExtra
+	ret
+
+.Text_What: ; 0xe43a
+	; What?
+	text_jump UnknownText_0x1c1024
+	db "@"
+
+.LogOut: ; e43f (3:643f)
+	call CloseSubmenu
+	ret
+
+.UseBillsPC: ; e443 (3:6443)
+	ld hl, .MenuDataHeader
+	call LoadMenuDataHeader
+	ld a, $1
+.loop
+	ld [wMenuCursorBuffer], a
+	call SetPalettes
+	xor a
+	ld [wWhichIndexSet], a
+	ld [hBGMapMode], a
+	call DoNthMenu
+	jr c, .cancel
+	ld a, [wMenuCursorBuffer]
+	push af
+	ld a, [MenuSelection]
+	ld hl, .Jumptable
+	rst JumpTable
+	pop bc
+	ld a, b
+	jr nc, .loop
+.cancel
+	call CloseWindow
+	ret
+
+.MenuDataHeader: ; 0xe46f
+	db $40 ; flags
+	db 00, 00 ; start coords
+	db 17, 19 ; end coords
+	dw .MenuData2
+	db 1 ; default option
+
+.MenuData2: ; 0xe477
+	db $80 ; flags
+	db 0 ; items
+	dw .items
+	dw PlaceMenuStrings
+	dw .strings
+
+.strings: ; e47f
+	db "WITHDRAW <PK><MN>@"
+	db "DEPOSIT <PK><MN>@"
+	db "CHANGE BOX@"
+	db "MOVE <PK><MN> W/O MAIL@"
+	db "SEE YA!@"
+
+.Jumptable: ; e4ba (3:64ba)
+	dw BillsPC_WithdrawMenu
+	dw BillsPC_DepositMenu
+	dw BillsPC_ChangeBoxMenu
+	dw BillsPC_MovePKMNMenu
+	dw BillsPC_SeeYa
+
+.items: ; e4c4
+	db 5
+	db 0 ; WITHDRAW
+	db 1;  DEPOSIT
+	db 2 ; CHANGE BOX
+	db 3 ; MOVE PKMN
+	db 4 ; SEE YA!
+	db -1
+
+BillsPC_SeeYa: ; e4cb
+	scf
+	ret
+
+BillsPC_MovePKMNMenu: ; e4cd
+	call LoadStandardMenuDataHeader
+	callba IsAnyMonHoldingMail
+	jr nc, .no_mail
+	ld hl, .Text_MonHoldingMail
+	call PrintText
+	jr .quit
+
+.no_mail
+	callba StartMovePkmnWOMail_SaveGame
+	jr c, .quit
+	callba _MovePKMNWithoutMail
+	call ReturnToMapFromSubmenu
+	call ClearPCItemScreen
+
+.quit
+	call CloseWindow
+	and a
+	ret
+
+.Text_MonHoldingMail: ; 0xe4f9
+	; There is a #MON holding MAIL. Please remove the MAIL.
+	text_jump UnknownText_0x1c102b
+	db "@"
+
+BillsPC_DepositMenu: ; e4fe (3:64fe)
+	call LoadStandardMenuDataHeader
+	callba _DepositPKMN
+	call ReturnToMapFromSubmenu
+	call ClearPCItemScreen
+	call CloseWindow
+	and a
+	ret
+
+Functione512: ; unused
+	ld a, [PartyCount]
+	and a
+	jr z, .no_pkmn
+	cp 2
+	jr c, .only_one_pkmn
+	and a
+	ret
+
+.no_pkmn
+	ld hl, .Text_NoPKMN
+	call MenuTextBoxBackup
+	scf
+	ret
+
+.only_one_pkmn
+	ld hl, .Text_ItsYourLastPKMN
+	call MenuTextBoxBackup
+	scf
+	ret
+
+.Text_NoPKMN: ; 0xe52e
+	; You don't have a single #MON!
+	text_jump UnknownText_0x1c1062
+	db "@"
+
+.Text_ItsYourLastPKMN: ; 0xe533
+	; You can't deposit your last #MON!
+	text_jump UnknownText_0x1c1080
+	db "@"
+
+CheckCurPartyMonFainted: ; e538
+	ld hl, PartyMon1HP
+	ld de, PARTYMON_STRUCT_LENGTH
+	ld b, $0
+.loop
+	ld a, [CurPartyMon]
+	cp b
+	jr z, .skip
+	ld a, [hli]
+	or [hl]
+	jr nz, .notfainted
+	dec hl
+
+.skip
+	inc b
+	ld a, [PartyCount]
+	cp b
+	jr z, .done
+	add hl, de
+	jr .loop
+
+.done
+	scf
+	ret
+
+.notfainted
+	and a
+	ret
+
+BillsPC_WithdrawMenu: ; e559 (3:6559)
+	call LoadStandardMenuDataHeader
+	callba _WithdrawPKMN
+	call ReturnToMapFromSubmenu
+	call ClearPCItemScreen
+	call CloseWindow
+	and a
+	ret
+
+Functione56d: ; unused
+	ld a, [PartyCount]
+	cp PARTY_LENGTH
+	jr nc, .asm_e576
+	and a
+	ret
+
+.asm_e576
+	ld hl, UnknownText_0xe57e
+	call MenuTextBoxBackup
+	scf
+	ret
+
+UnknownText_0xe57e: ; 0xe57e
+	; You can't take any more #MON.
+	text_jump UnknownText_0x1c10a2
+	db "@"
+
+BillsPC_ChangeBoxMenu: ; e583 (3:6583)
+	callba _ChangeBox
+	and a
+	ret
+
+ClearPCItemScreen: ; e58b
+	call DisableSpriteUpdates
+	xor a
+	ld [hBGMapMode], a
+	call ClearBGPalettes
+	call ClearSprites
+	hlcoord 0, 0
+	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+	ld a, " "
+	call ByteFill
+	hlcoord 0,0
+	lb bc, 10, 18
+	call TextBox
+	hlcoord 0,12
+	lb bc, 4, 18
+	call TextBox
+	call WaitBGMap2
+	call SetPalettes ; load regular palettes?
+	ret
+
+CopyBoxmonToTempMon: ; e5bb
+	ld a, [CurPartyMon]
+	ld hl, sBoxMon1Species
+	ld bc, BOXMON_STRUCT_LENGTH
+	call AddNTimes
+	ld de, TempMonSpecies
+	ld bc, BOXMON_STRUCT_LENGTH
+	ld a, BANK(sBoxMon1Species)
+	call GetSRAMBank
+	call CopyBytes
+	call CloseSRAM
+	ret
+
+Functione5d9: ; unreferenced
+	ld a, [wCurBox]
+	cp b
+	jr z, .same_box
+	ld a, b
+	ld hl, .BoxAddrs
+	ld bc, 3
+	call AddNTimes
+	ld a, [hli]
+	push af
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	pop af
+	jr .okay
+
+.same_box
+	ld a, BANK(sBoxCount)
+	ld hl, sBoxCount
+
+.okay
+	call GetSRAMBank
+	ld a, [hl]
+	ld bc, 1 + MONS_PER_BOX + 1
+	add hl, bc
+	ld b, a
+	ld c, $0
+	ld de, wc608
+	ld a, b
+	and a
+	jr z, .empty_box
+.loop
+	push hl
+	push bc
+	ld a, c
+	ld bc, 0
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [hl]
+	ld [de], a
+	inc de
+	ld [CurSpecies], a
+	call GetBaseData
+	pop bc
+	pop hl
+
+	push hl
+	push bc
+	ld a, c
+	ld bc, MONS_PER_BOX * (BOXMON_STRUCT_LENGTH + NAME_LENGTH)
+	add hl, bc
+	call SkipNames
+	call CopyBytes
+	pop bc
+	pop hl
+
+	push hl
+	push bc
+	ld a, c
+	ld bc, MON_LEVEL
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [hl]
+	ld [de], a
+	inc de
+	pop bc
+	pop hl
+
+	push hl
+	push bc
+	ld a, c
+	ld bc, MON_DVS
+	add hl, bc
+	ld bc, BOXMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [hli]
+	and $f0
+	ld b, a
+	ld a, [hl]
+	and $f0
+	swap a
+	or b
+	ld b, a
+	ld a, [BaseGender]
+	cp b
+	ld a, $1
+	jr c, .okay2
+	xor a
+.okay2
+	ld [de], a
+	inc de
+	pop bc
+	pop hl
+
+	inc c
+	dec b
+	jr nz, .loop
+.empty_box
+	call CloseSRAM
+	ret
+
+.BoxAddrs: ; e66e
+	dba sBox1
+	dba sBox2
+	dba sBox3
+	dba sBox4
+	dba sBox5
+	dba sBox6
+	dba sBox7
+	dba sBox8
+	dba sBox9
+	dba sBox10
+	dba sBox11
+	dba sBox12
+	dba sBox13
+	dba sBox14
--- /dev/null
+++ b/engine/health.asm
@@ -1,0 +1,110 @@
+HealParty: ; c658
+	xor a
+	ld [CurPartyMon], a
+	ld hl, PartySpecies
+.loop
+	ld a, [hli]
+	cp -1
+	jr z, .done
+	cp EGG
+	jr z, .next
+
+	push hl
+	call HealPartyMon
+	pop hl
+
+.next
+	ld a, [CurPartyMon]
+	inc a
+	ld [CurPartyMon], a
+	jr .loop
+
+.done
+	ret
+
+HealPartyMon: ; c677
+	ld a, MON_SPECIES
+	call GetPartyParamLocation
+	ld d, h
+	ld e, l
+
+	ld hl, MON_STATUS
+	add hl, de
+	xor a
+	ld [hli], a
+	ld [hl], a
+
+	ld hl, MON_MAXHP
+	add hl, de
+
+	; bc = MON_HP
+	ld b, h
+	ld c, l
+	dec bc
+	dec bc
+
+	ld a, [hli]
+	ld [bc], a
+	inc bc
+	ld a, [hl]
+	ld [bc], a
+
+	callba RestoreAllPP
+	ret
+
+ComputeHPBarPixels: ; c699
+; e = bc * (6 * 8) / de
+	ld a, b
+	or c
+	jr z, .zero
+	push hl
+	xor a
+	ld [hMultiplicand + 0], a
+	ld a, b
+	ld [hMultiplicand + 1], a
+	ld a, c
+	ld [hMultiplicand + 2], a
+	ld a, 6 * 8
+	ld [hMultiplier], a
+	call Multiply
+	; We need de to be under 256 because hDivisor is only 1 byte.
+	ld a, d
+	and a
+	jr z, .divide
+	; divide de and hProduct by 4
+	srl d
+	rr e
+	srl d
+	rr e
+	ld a, [hProduct + 2]
+	ld b, a
+	ld a, [hProduct + 3]
+	srl b
+	rr a
+	srl b
+	rr a
+	ld [hDividend + 3], a
+	ld a, b
+	ld [hDividend + 2], a
+.divide
+	ld a, e
+	ld [hDivisor], a
+	ld b, 4
+	call Divide
+	ld a, [hQuotient + 2]
+	ld e, a
+	pop hl
+	and a
+	ret nz
+	ld e, 1
+	ret
+
+.zero
+	ld e, 0
+	ret
+
+AnimateHPBar: ; c6e0
+	call WaitBGMap
+	call _AnimateHPBar
+	call WaitBGMap
+	ret
--- /dev/null
+++ b/engine/items.asm
@@ -1,0 +1,584 @@
+_ReceiveItem:: ; d1d5
+	call DoesHLEqualNumItems
+	jp nz, PutItemInPocket
+	push hl
+	call CheckItemPocket
+	pop de
+	ld a, [wItemAttributeParamBuffer]
+	dec a
+	ld hl, .Pockets
+	rst JumpTable
+	ret
+
+.Pockets: ; d1e9
+	dw .Item
+	dw .KeyItem
+	dw .Ball
+	dw .TMHM
+
+.Item: ; d1f1
+	ld h, d
+	ld l, e
+	jp PutItemInPocket
+
+.KeyItem: ; d1f6
+	ld h, d
+	ld l, e
+	jp ReceiveKeyItem
+
+.Ball: ; d1fb
+	ld hl, NumBalls
+	jp PutItemInPocket
+
+.TMHM: ; d201
+	ld h, d
+	ld l, e
+	ld a, [CurItem]
+	ld c, a
+	call GetTMHMNumber
+	jp ReceiveTMHM
+
+_TossItem:: ; d20d
+	call DoesHLEqualNumItems
+	jr nz, .remove
+	push hl
+	call CheckItemPocket
+	pop de
+	ld a, [wItemAttributeParamBuffer]
+	dec a
+	ld hl, .Pockets
+	rst JumpTable
+	ret
+
+.Pockets
+	dw .Item
+	dw .KeyItem
+	dw .Ball
+	dw .TMHM
+
+.Ball ; d228
+	ld hl, NumBalls
+	jp RemoveItemFromPocket
+
+.TMHM ; d22e
+	ld h, d
+	ld l, e
+	ld a, [CurItem]
+	ld c, a
+	call GetTMHMNumber
+	jp TossTMHM
+
+.KeyItem ; d23a
+	ld h, d
+	ld l, e
+	jp TossKeyItem
+
+.Item ; d23f
+	ld h, d
+	ld l, e
+
+.remove
+	jp RemoveItemFromPocket
+
+_CheckItem:: ; d244
+	call DoesHLEqualNumItems
+	jr nz, .nope
+	push hl
+	call CheckItemPocket
+	pop de
+	ld a, [wItemAttributeParamBuffer]
+	dec a
+	ld hl, .Pockets
+	rst JumpTable
+	ret
+
+.Pockets
+	dw .Item
+	dw .KeyItem
+	dw .Ball
+	dw .TMHM
+
+.Ball ; d25f
+	ld hl, NumBalls
+	jp CheckTheItem
+
+.TMHM ; d265
+	ld h, d
+	ld l, e
+	ld a, [CurItem]
+	ld c, a
+	call GetTMHMNumber
+	jp CheckTMHM
+
+.KeyItem ; d271
+	ld h, d
+	ld l, e
+	jp CheckKeyItems
+
+.Item ; d276
+	ld h, d
+	ld l, e
+
+.nope
+	jp CheckTheItem
+
+DoesHLEqualNumItems: ; d27b
+	ld a, l
+	cp NumItems % $100
+	ret nz
+	ld a, h
+	cp NumItems / $100
+	ret
+
+GetPocketCapacity: ; d283
+	ld c, MAX_ITEMS
+	ld a, e
+	cp NumItems % $100
+	jr nz, .not_bag
+	ld a, d
+	cp NumItems / $100
+	ret z
+
+.not_bag
+	ld c, MAX_PC_ITEMS
+	ld a, e
+	cp PCItems % $100
+	jr nz, .not_pc
+	ld a, d
+	cp PCItems / $100
+	ret z
+
+.not_pc
+	ld c, MAX_BALLS
+	ret
+
+PutItemInPocket: ; d29c
+	ld d, h
+	ld e, l
+	inc hl
+	ld a, [CurItem]
+	ld c, a
+	ld b, 0
+.loop
+	ld a, [hli]
+	cp -1
+	jr z, .terminator
+	cp c
+	jr nz, .next
+	ld a, 99
+	sub [hl]
+	add b
+	ld b, a
+	ld a, [wItemQuantityChangeBuffer]
+	cp b
+	jr z, .ok
+	jr c, .ok
+
+.next
+	inc hl
+	jr .loop
+
+.terminator
+	call GetPocketCapacity
+	ld a, [de]
+	cp c
+	jr c, .ok
+	and a
+	ret
+
+.ok
+	ld h, d
+	ld l, e
+	ld a, [CurItem]
+	ld c, a
+	ld a, [wItemQuantityChangeBuffer]
+	ld [wItemQuantityBuffer], a
+.loop2
+	inc hl
+	ld a, [hli]
+	cp -1
+	jr z, .terminator2
+	cp c
+	jr nz, .loop2
+	ld a, [wItemQuantityBuffer]
+	add [hl]
+	cp 100
+	jr nc, .newstack
+	ld [hl], a
+	jr .done
+
+.newstack
+	ld [hl], 99
+	sub 99
+	ld [wItemQuantityBuffer], a
+	jr .loop2
+
+.terminator2
+	dec hl
+	ld a, [CurItem]
+	ld [hli], a
+	ld a, [wItemQuantityBuffer]
+	ld [hli], a
+	ld [hl], -1
+	ld h, d
+	ld l, e
+	inc [hl]
+
+.done
+	scf
+	ret
+
+RemoveItemFromPocket: ; d2ff
+	ld d, h
+	ld e, l
+	ld a, [hli]
+	ld c, a
+	ld a, [CurItemQuantity]
+	cp c
+	jr nc, .ok ; memory
+	ld c, a
+	ld b, $0
+	add hl, bc
+	add hl, bc
+	ld a, [CurItem]
+	cp [hl]
+	inc hl
+	jr z, .skip
+	ld h, d
+	ld l, e
+	inc hl
+
+.ok
+	ld a, [CurItem]
+	ld b, a
+.loop
+	ld a, [hli]
+	cp b
+	jr z, .skip
+	cp -1
+	jr z, .nope
+	inc hl
+	jr .loop
+
+.skip
+	ld a, [wItemQuantityChangeBuffer]
+	ld b, a
+	ld a, [hl]
+	sub b
+	jr c, .nope
+	ld [hl], a
+	ld [wItemQuantityBuffer], a
+	and a
+	jr nz, .yup
+	dec hl
+	ld b, h
+	ld c, l
+	inc hl
+	inc hl
+.loop2
+	ld a, [hli]
+	ld [bc], a
+	inc bc
+	cp -1
+	jr nz, .loop2
+	ld h, d
+	ld l, e
+	dec [hl]
+
+.yup
+	scf
+	ret
+
+.nope
+	and a
+	ret
+
+CheckTheItem: ; d349
+	ld a, [CurItem]
+	ld c, a
+.loop
+	inc hl
+	ld a, [hli]
+	cp -1
+	jr z, .done
+	cp c
+	jr nz, .loop
+	scf
+	ret
+
+.done
+	and a
+	ret
+
+ReceiveKeyItem: ; d35a
+	ld hl, NumKeyItems
+	ld a, [hli]
+	cp MAX_KEY_ITEMS
+	jr nc, .nope
+	ld c, a
+	ld b, 0
+	add hl, bc
+	ld a, [CurItem]
+	ld [hli], a
+	ld [hl], -1
+	ld hl, NumKeyItems
+	inc [hl]
+	scf
+	ret
+
+.nope
+	and a
+	ret
+
+TossKeyItem: ; d374
+	ld a, [wd107]
+	ld e, a
+	ld d, 0
+	ld hl, NumKeyItems
+	ld a, [hl]
+	cp e
+	jr nc, .ok
+	call .Toss
+	ret nc
+	jr .ok2
+
+.ok
+	dec [hl]
+	inc hl
+	add hl, de
+
+.ok2
+	ld d, h
+	ld e, l
+	inc hl
+.loop
+	ld a, [hli]
+	ld [de], a
+	inc de
+	cp -1
+	jr nz, .loop
+	scf
+	ret
+
+.Toss: ; d396
+	ld hl, NumKeyItems
+	ld a, [CurItem]
+	ld c, a
+.loop3
+	inc hl
+	ld a, [hl]
+	cp c
+	jr z, .ok3
+	cp -1
+	jr nz, .loop3
+	xor a
+	ret
+
+.ok3
+	ld a, [NumKeyItems]
+	dec a
+	ld [NumKeyItems], a
+	scf
+	ret
+
+CheckKeyItems: ; d3b1
+	ld a, [CurItem]
+	ld c, a
+	ld hl, KeyItems
+.loop
+	ld a, [hli]
+	cp c
+	jr z, .done
+	cp -1
+	jr nz, .loop
+	and a
+	ret
+
+.done
+	scf
+	ret
+
+ReceiveTMHM: ; d3c4
+	dec c
+	ld b, 0
+	ld hl, TMsHMs
+	add hl, bc
+	ld a, [wItemQuantityChangeBuffer]
+	add [hl]
+	cp 100
+	jr nc, .toomany
+	ld [hl], a
+	scf
+	ret
+
+.toomany
+	and a
+	ret
+
+TossTMHM: ; d3d8
+	dec c
+	ld b, 0
+	ld hl, TMsHMs
+	add hl, bc
+	ld a, [wItemQuantityChangeBuffer]
+	ld b, a
+	ld a, [hl]
+	sub b
+	jr c, .nope
+	ld [hl], a
+	ld [wItemQuantityBuffer], a
+	jr nz, .yup
+	ld a, [wTMHMPocketScrollPosition]
+	and a
+	jr z, .yup
+	dec a
+	ld [wTMHMPocketScrollPosition], a
+
+.yup
+	scf
+	ret
+
+.nope
+	and a
+	ret
+
+CheckTMHM: ; d3fb
+	dec c
+	ld b, $0
+	ld hl, TMsHMs
+	add hl, bc
+	ld a, [hl]
+	and a
+	ret z
+	scf
+	ret
+
+GetTMHMNumber:: ; d407
+; Return the number of a TM/HM by item id c.
+
+	ld a, c
+
+; Skip any dummy items.
+	cp ITEM_C3 ; TM04-05
+	jr c, .done
+	cp ITEM_DC ; TM28-29
+	jr c, .skip
+
+	dec a
+.skip
+	dec a
+.done
+	sub TM01
+	inc a
+	ld c, a
+	ret
+
+GetNumberedTMHM: ; d417
+; Return the item id of a TM/HM by number c.
+
+	ld a, c
+
+; Skip any gaps.
+	cp ITEM_C3 - (TM01 - 1)
+	jr c, .done
+	cp ITEM_DC - (TM01 - 1) - 1
+	jr c, .skip_one
+
+.skip_two
+	inc a
+.skip_one
+	inc a
+.done
+	add TM01
+	dec a
+	ld c, a
+	ret
+
+_CheckTossableItem:: ; d427
+; Return 1 in wItemAttributeParamBuffer and carry if CurItem can't be removed from the bag.
+	ld a, ITEMATTR_PERMISSIONS
+	call GetItemAttr
+	bit 7, a
+	jr nz, ItemAttr_ReturnCarry
+	and a
+	ret
+
+CheckSelectableItem: ; d432
+; Return 1 in wItemAttributeParamBuffer and carry if CurItem can't be selected.
+	ld a, ITEMATTR_PERMISSIONS
+	call GetItemAttr
+	bit 6, a
+	jr nz, ItemAttr_ReturnCarry
+	and a
+	ret
+
+CheckItemPocket:: ; d43d
+; Return the pocket for CurItem in wItemAttributeParamBuffer.
+	ld a, ITEMATTR_POCKET
+	call GetItemAttr
+	and $f
+	ld [wItemAttributeParamBuffer], a
+	ret
+
+CheckItemContext: ; d448
+; Return the context for CurItem in wItemAttributeParamBuffer.
+	ld a, ITEMATTR_HELP
+	call GetItemAttr
+	and $f
+	ld [wItemAttributeParamBuffer], a
+	ret
+
+CheckItemMenu: ; d453
+; Return the menu for CurItem in wItemAttributeParamBuffer.
+	ld a, ITEMATTR_HELP
+	call GetItemAttr
+	swap a
+	and $f
+	ld [wItemAttributeParamBuffer], a
+	ret
+
+GetItemAttr: ; d460
+; Get attribute a of CurItem.
+
+	push hl
+	push bc
+
+	ld hl, ItemAttributes
+	ld c, a
+	ld b, 0
+	add hl, bc
+
+	xor a
+	ld [wItemAttributeParamBuffer], a
+
+	ld a, [CurItem]
+	dec a
+	ld c, a
+	ld a, NUM_ITEMATTRS
+	call AddNTimes
+	ld a, BANK(ItemAttributes)
+	call GetFarByte
+
+	pop bc
+	pop hl
+	ret
+
+ItemAttr_ReturnCarry: ; d47f
+	ld a, 1
+	ld [wItemAttributeParamBuffer], a
+	scf
+	ret
+
+GetItemPrice: ; d486
+; Return the price of CurItem in de.
+	push hl
+	push bc
+	ld a, ITEMATTR_PRICE
+	call GetItemAttr
+	ld e, a
+	ld a, ITEMATTR_PRICE_HI
+	call GetItemAttr
+	ld d, a
+	pop bc
+	pop hl
+	ret
--- a/engine/phone.asm
+++ b/engine/phone.asm
@@ -451,22 +451,20 @@
 ; 0x90255
 
 Script_SpecialBillCall:: ; 0x90255
-	callasm Function9025c
+	callasm .LoadBillScript
 	jump Script_ReceivePhoneCall
-; 0x9025c
 
-Function9025c: ; 9025c
+.LoadBillScript
 	ld e, PHONE_BILL
 	jp LoadCallerScript
 ; 90261
 
 UnknownScript_0x90261: ; 0x90261
-	callasm Function9026a
+	callasm .LoadElmScript
 	pause 30
 	jump Script_ReceivePhoneCall
-; 0x9026a
 
-Function9026a: ; 9026a
+.LoadElmScript
 	ld e, PHONE_ELM
 	jp LoadCallerScript
 ; 9026f
@@ -493,7 +491,6 @@
 	ld b, a
 	call Function90363
 	ret
-
 
 PhoneCall:: ; 9029a
 	ld a, b
--- /dev/null
+++ b/engine/player_object.asm
@@ -1,0 +1,856 @@
+BlankScreen: ; 8000
+	call DisableSpriteUpdates
+	xor a
+	ld [hBGMapMode], a
+	call ClearBGPalettes
+	call ClearSprites
+	hlcoord 0, 0
+	ld bc, TileMapEnd - TileMap
+	ld a, " "
+	call ByteFill
+	hlcoord 0, 0, AttrMap
+	ld bc, AttrMapEnd - AttrMap
+	ld a, $7
+	call ByteFill
+	call WaitBGMap2
+	call SetPalettes
+	ret
+
+SpawnPlayer: ; 8029
+	ld a, -1
+	ld [wObjectFollow_Leader], a
+	ld [wObjectFollow_Follower], a
+	ld a, $0
+	ld hl, PlayerObjectTemplate
+	call CopyPlayerObjectTemplate
+	ld b, $0
+	call PlayerSpawn_ConvertCoords
+	ld a, $0
+	call GetMapObject
+	ld hl, MAPOBJECT_COLOR
+	add hl, bc
+	ln e, (1 << 3) | PAL_OW_RED, PERSONTYPE_SCRIPT
+	ld a, [wPlayerSpriteSetupFlags]
+	bit 2, a
+	jr nz, .ok
+	ld a, [PlayerGender]
+	bit 0, a
+	jr z, .ok
+	ln e, (1 << 3) | PAL_OW_BLUE, PERSONTYPE_SCRIPT
+
+.ok
+	ld [hl], e
+	ld a, $0
+	ld [hMapObjectIndexBuffer], a
+	ld bc, MapObjects
+	ld a, $0
+	ld [hObjectStructIndexBuffer], a
+	ld de, ObjectStructs
+	call CopyMapObjectToObjectStruct
+	ld a, PLAYER
+	ld [wCenteredObject], a
+	ret
+
+PlayerObjectTemplate: ; 8071
+; A dummy map object used to initialize the player object.
+; Shorter than the actual amount copied by two bytes.
+; Said bytes seem to be unused.
+	person_event SPRITE_CHRIS, -4, -4, SPRITEMOVEDATA_PLAYER, 15, 15, -1, -1, 0, PERSONTYPE_SCRIPT, 0, 0, -1
+
+CopyDECoordsToMapObject:: ; 807e
+	push de
+	ld a, b
+	call GetMapObject
+	pop de
+	ld hl, MAPOBJECT_X_COORD
+	add hl, bc
+	ld [hl], d
+	ld hl, MAPOBJECT_Y_COORD
+	add hl, bc
+	ld [hl], e
+	ret
+
+PlayerSpawn_ConvertCoords: ; 808f
+	push bc
+	ld a, [XCoord]
+	add 4
+	ld d, a
+	ld a, [YCoord]
+	add 4
+	ld e, a
+	pop bc
+	call CopyDECoordsToMapObject
+	ret
+
+WritePersonXY:: ; 80a1
+	ld a, b
+	call CheckObjectVisibility
+	ret c
+
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	ld a, [hMapObjectIndexBuffer]
+	ld b, a
+	call CopyDECoordsToMapObject
+	and a
+	ret
+
+RefreshPlayerCoords: ; 80b8
+	ld a, [XCoord]
+	add 4
+	ld d, a
+	ld hl, PlayerStandingMapX
+	sub [hl]
+	ld [hl], d
+	ld hl, MapObjects + MAPOBJECT_X_COORD
+	ld [hl], d
+	ld hl, PlayerLastMapX
+	ld [hl], d
+	ld d, a
+	ld a, [YCoord]
+	add 4
+	ld e, a
+	ld hl, PlayerStandingMapY
+	sub [hl]
+	ld [hl], e
+	ld hl, MapObjects + MAPOBJECT_Y_COORD
+	ld [hl], e
+	ld hl, PlayerLastMapY
+	ld [hl], e
+	ld e, a
+	ld a, [wObjectFollow_Leader]
+	cp $0
+	ret nz ; wtf
+	ret
+
+CopyObjectStruct:: ; 80e7
+	call CheckObjectMask
+	and a
+	ret nz ; masked
+
+	ld hl, ObjectStructs + OBJECT_STRUCT_LENGTH * 1
+	ld a, 1
+	ld de, OBJECT_STRUCT_LENGTH
+.loop
+	ld [hObjectStructIndexBuffer], a
+	ld a, [hl]
+	and a
+	jr z, .done
+	add hl, de
+	ld a, [hObjectStructIndexBuffer]
+	inc a
+	cp NUM_OBJECT_STRUCTS
+	jr nz, .loop
+	scf
+	ret ; overflow
+
+.done
+	ld d, h
+	ld e, l
+	call CopyMapObjectToObjectStruct
+	ld hl, VramState
+	bit 7, [hl]
+	ret z
+
+	ld hl, OBJECT_FLAGS2
+	add hl, de
+	set 5, [hl]
+	ret
+
+CopyMapObjectToObjectStruct: ; 8116
+	call .CopyMapObjectToTempObject
+	call CopyTempObjectToObjectStruct
+	ret
+
+.CopyMapObjectToTempObject: ; 811d
+	ld a, [hObjectStructIndexBuffer]
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld [hl], a
+
+	ld a, [hMapObjectIndexBuffer]
+	ld [wTempObjectCopyMapObjectIndex], a
+
+	ld hl, MAPOBJECT_SPRITE
+	add hl, bc
+	ld a, [hl]
+	ld [wTempObjectCopySprite], a
+
+	call GetSpriteVTile
+	ld [wTempObjectCopySpriteVTile], a
+
+	ld a, [hl]
+	call GetSpritePalette
+	ld [wTempObjectCopyPalette], a
+
+	ld hl, MAPOBJECT_COLOR
+	add hl, bc
+	ld a, [hl]
+	and $f0
+	jr z, .skip_color_override
+	swap a
+	and $7 ; OAM_PALETTE
+	ld [wTempObjectCopyPalette], a
+
+.skip_color_override
+	ld hl, MAPOBJECT_MOVEMENT
+	add hl, bc
+	ld a, [hl]
+	ld [wTempObjectCopyMovement], a
+
+	ld hl, MAPOBJECT_RANGE
+	add hl, bc
+	ld a, [hl]
+	ld [wTempObjectCopyRange], a
+
+	ld hl, MAPOBJECT_X_COORD
+	add hl, bc
+	ld a, [hl]
+	ld [wTempObjectCopyX], a
+
+	ld hl, MAPOBJECT_Y_COORD
+	add hl, bc
+	ld a, [hl]
+	ld [wTempObjectCopyY], a
+
+	ld hl, MAPOBJECT_RADIUS
+	add hl, bc
+	ld a, [hl]
+	ld [wTempObjectCopyRadius], a
+	ret
+
+InitializeVisibleSprites: ; 8177
+	ld bc, MapObjects + OBJECT_LENGTH
+	ld a, 1
+.loop
+	ld [hMapObjectIndexBuffer], a
+	ld hl, MAPOBJECT_SPRITE
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .next
+
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	cp -1
+	jr nz, .next
+
+	ld a, [XCoord]
+	ld d, a
+	ld a, [YCoord]
+	ld e, a
+
+	ld hl, MAPOBJECT_X_COORD
+	add hl, bc
+	ld a, [hl]
+	add 1
+	sub d
+	jr c, .next
+
+	cp MAPOBJECT_SCREEN_WIDTH
+	jr nc, .next
+
+	ld hl, MAPOBJECT_Y_COORD
+	add hl, bc
+	ld a, [hl]
+	add 1
+	sub e
+	jr c, .next
+
+	cp MAPOBJECT_SCREEN_HEIGHT
+	jr nc, .next
+
+	push bc
+	call CopyObjectStruct
+	pop bc
+	jp c, .ret
+
+.next
+	ld hl, OBJECT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	ld a, [hMapObjectIndexBuffer]
+	inc a
+	cp NUM_OBJECTS
+	jr nz, .loop
+	ret
+
+.ret: ; 81c9
+	ret
+
+CheckObjectEnteringVisibleRange:: ; 81ca
+	nop
+	ld a, [wPlayerStepDirection]
+	cp STANDING
+	ret z
+	ld hl, .dw
+	rst JumpTable
+	ret
+
+.dw: ; 81d6
+	dw .Down
+	dw .Up
+	dw .Left
+	dw .Right
+
+.Up: ; 81de
+	ld a, [YCoord]
+	sub 1
+	jr .Vertical
+
+.Down: ; 81e5
+	ld a, [YCoord]
+	add 9
+.Vertical: ; 81ea
+	ld d, a
+	ld a, [XCoord]
+	ld e, a
+	ld bc, MapObjects + OBJECT_LENGTH
+	ld a, 1
+.loop_v
+	ld [hMapObjectIndexBuffer], a
+	ld hl, MAPOBJECT_SPRITE
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .next_v
+	ld hl, MAPOBJECT_Y_COORD
+	add hl, bc
+	ld a, d
+	cp [hl]
+	jr nz, .next_v
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	cp -1
+	jr nz, .next_v
+	ld hl, MAPOBJECT_X_COORD
+	add hl, bc
+	ld a, [hl]
+	add 1
+	sub e
+	jr c, .next_v
+	cp MAPOBJECT_SCREEN_WIDTH
+	jr nc, .next_v
+	push de
+	push bc
+	call CopyObjectStruct
+	pop bc
+	pop de
+
+.next_v
+	ld hl, OBJECT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	ld a, [hMapObjectIndexBuffer]
+	inc a
+	cp NUM_OBJECTS
+	jr nz, .loop_v
+	ret
+
+.Left: ; 8232
+	ld a, [XCoord]
+	sub 1
+	jr .Horizontal
+
+.Right: ; 8239
+	ld a, [XCoord]
+	add 10
+.Horizontal: ; 823e
+	ld e, a
+	ld a, [YCoord]
+	ld d, a
+	ld bc, MapObjects + OBJECT_LENGTH
+	ld a, 1
+.loop_h
+	ld [hMapObjectIndexBuffer], a
+	ld hl, MAPOBJECT_SPRITE
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .next_h
+	ld hl, MAPOBJECT_X_COORD
+	add hl, bc
+	ld a, e
+	cp [hl]
+	jr nz, .next_h
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	cp -1
+	jr nz, .next_h
+	ld hl, MAPOBJECT_Y_COORD
+	add hl, bc
+	ld a, [hl]
+	add 1
+	sub d
+	jr c, .next_h
+	cp MAPOBJECT_SCREEN_HEIGHT
+	jr nc, .next_h
+	push de
+	push bc
+	call CopyObjectStruct
+	pop bc
+	pop de
+
+.next_h
+	ld hl, OBJECT_LENGTH
+	add hl, bc
+	ld b, h
+	ld c, l
+	ld a, [hMapObjectIndexBuffer]
+	inc a
+	cp NUM_OBJECTS
+	jr nz, .loop_h
+	ret
+
+CopyTempObjectToObjectStruct: ; 8286
+	ld a, [wTempObjectCopyMapObjectIndex]
+	ld hl, OBJECT_MAP_OBJECT_INDEX
+	add hl, de
+	ld [hl], a
+
+	ld a, [wTempObjectCopyMovement]
+	call CopySpriteMovementData
+
+	ld a, [wTempObjectCopyPalette]
+	ld hl, OBJECT_PALETTE
+	add hl, de
+	or [hl]
+	ld [hl], a
+
+	ld a, [wTempObjectCopyY]
+	call .InitYCoord
+
+	ld a, [wTempObjectCopyX]
+	call .InitXCoord
+
+	ld a, [wTempObjectCopySprite]
+	ld hl, OBJECT_SPRITE
+	add hl, de
+	ld [hl], a
+
+	ld a, [wTempObjectCopySpriteVTile]
+	ld hl, OBJECT_SPRITE_TILE
+	add hl, de
+	ld [hl], a
+
+	ld hl, OBJECT_STEP_TYPE
+	add hl, de
+	ld [hl], STEP_TYPE_00
+
+	ld hl, OBJECT_FACING_STEP
+	add hl, de
+	ld [hl], STANDING
+
+	ld a, [wTempObjectCopyRadius]
+	call .InitRadius
+
+	ld a, [wTempObjectCopyRange]
+	ld hl, OBJECT_RANGE
+	add hl, de
+	ld [hl], a
+
+	and a
+	ret
+
+.InitYCoord: ; 82d5
+	ld hl, OBJECT_INIT_Y
+	add hl, de
+	ld [hl], a
+
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, de
+	ld [hl], a
+
+	ld hl, YCoord
+	sub [hl]
+	and $f
+	swap a
+	ld hl, wFollowNotExactPersonY
+	sub [hl]
+	ld hl, OBJECT_SPRITE_Y
+	add hl, de
+	ld [hl], a
+	ret
+
+.InitXCoord: ; 82f1
+	ld hl, OBJECT_INIT_X
+	add hl, de
+	ld [hl], a
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, de
+	ld [hl], a
+	ld hl, XCoord
+	sub [hl]
+	and $f
+	swap a
+	ld hl, wFollowNotExactPersonX
+	sub [hl]
+	ld hl, OBJECT_SPRITE_X
+	add hl, de
+	ld [hl], a
+	ret
+
+.InitRadius: ; 830d
+	ld h, a
+	inc a
+	and $f
+	ld l, a
+	ld a, h
+	add $10
+	and $f0
+	or l
+	ld hl, OBJECT_RADIUS
+	add hl, de
+	ld [hl], a
+	ret
+
+TrainerWalkToPlayer: ; 831e
+	ld a, [hLastTalked]
+	call InitMovementBuffer
+	ld a, movement_step_sleep_1
+	call AppendToMovementBuffer
+	ld a, [wd03f]
+	dec a
+	jr z, .TerminateStep
+	ld a, [hLastTalked]
+	ld b, a
+	ld c, PLAYER
+	ld d, 1
+	call .GetPathToPlayer
+	call DecrementMovementBufferCount
+
+.TerminateStep
+	ld a, movement_step_end
+	call AppendToMovementBuffer
+	ret
+
+.GetPathToPlayer: ; 8341
+	push de
+	push bc
+; get player object struct, load to de
+	ld a, c
+	call GetMapObject
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	call GetObjectStruct
+	ld d, b
+	ld e, c
+
+; get last talked object struct, load to bc
+	pop bc
+	ld a, b
+	call GetMapObject
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	call GetObjectStruct
+
+; get last talked coords, load to bc
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld c, [hl]
+	ld b, a
+
+; get player coords, load to de
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, de
+	ld a, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, de
+	ld e, [hl]
+	ld d, a
+
+	pop af
+	call ComputePathToWalkToPlayer
+	ret
+
+Special_SurfStartStep: ; 8379
+	call InitMovementBuffer
+	call .GetMovementData
+	call AppendToMovementBuffer
+	ld a, movement_step_end
+	call AppendToMovementBuffer
+	ret
+
+.GetMovementData: ; 8388
+	ld a, [PlayerDirection]
+	srl a
+	srl a
+	and 3
+	ld e, a
+	ld d, 0
+	ld hl, .movement_data
+	add hl, de
+	ld a, [hl]
+	ret
+
+.movement_data
+	slow_step_down
+	slow_step_up
+	slow_step_left
+	slow_step_right
+
+FollowNotExact:: ; 839e
+	push bc
+	ld a, c
+	call CheckObjectVisibility
+	ld d, b
+	ld e, c
+	pop bc
+	ret c
+
+	ld a, b
+	call CheckObjectVisibility
+	ret c
+
+; Person 2 is now in bc, person 1 is now in de
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld c, [hl]
+	ld b, a
+
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, de
+	ld a, [hl]
+	cp b
+	jr z, .same_x
+	jr c, .to_the_left
+	inc b
+	jr .continue
+
+.to_the_left
+	dec b
+	jr .continue
+
+.same_x
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, de
+	ld a, [hl]
+	cp c
+	jr z, .continue
+	jr c, .below
+	inc c
+	jr .continue
+
+.below
+	dec c
+
+.continue
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, de
+	ld [hl], b
+	ld a, b
+	ld hl, XCoord
+	sub [hl]
+	and $f
+	swap a
+	ld hl, wFollowNotExactPersonX
+	sub [hl]
+	ld hl, OBJECT_SPRITE_X
+	add hl, de
+	ld [hl], a
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, de
+	ld [hl], c
+	ld a, c
+	ld hl, YCoord
+	sub [hl]
+	and $f
+	swap a
+	ld hl, wFollowNotExactPersonY
+	sub [hl]
+	ld hl, OBJECT_SPRITE_Y
+	add hl, de
+	ld [hl], a
+	ld a, [hObjectStructIndexBuffer]
+	ld hl, OBJECT_RANGE
+	add hl, de
+	ld [hl], a
+	ld hl, OBJECT_MOVEMENTTYPE
+	add hl, de
+	ld [hl], SPRITEMOVEDATA_FOLLOWNOTEXACT
+	ld hl, OBJECT_STEP_TYPE
+	add hl, de
+	ld [hl], STEP_TYPE_00
+	ret
+
+GetRelativeFacing:: ; 8417
+; Determines which way map object e would have to turn to face map object d.  Returns carry if it's impossible for whatever reason.
+	ld a, d
+	call GetMapObject
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	cp NUM_OBJECT_STRUCTS
+	jr nc, .carry
+	ld d, a
+	ld a, e
+	call GetMapObject
+	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+	add hl, bc
+	ld a, [hl]
+	cp NUM_OBJECT_STRUCTS
+	jr nc, .carry
+	ld e, a
+	call .GetFacing_e_relativeto_d
+	ret
+
+.carry
+	scf
+	ret
+
+.GetFacing_e_relativeto_d: ; 8439
+; Determines which way object e would have to turn to face object d.  Returns carry if it's impossible.
+; load the coordinates of object d into bc
+	ld a, d
+	call GetObjectStruct
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld c, [hl]
+	ld b, a
+	push bc
+; load the coordinates of object e into de
+	ld a, e
+	call GetObjectStruct
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	pop bc
+; |x1 - x2|
+	ld a, b
+	sub d
+	jr z, .same_x_1
+	jr nc, .b_right_of_d_1
+	cpl
+	inc a
+
+.b_right_of_d_1
+; |y1 - y2|
+	ld h, a
+	ld a, c
+	sub e
+	jr z, .same_y_1
+	jr nc, .c_below_e_1
+	cpl
+	inc a
+
+.c_below_e_1
+; |y1 - y2| - |x1 - x2|
+	sub h
+	jr c, .same_y_1
+
+.same_x_1
+; compare the y coordinates
+	ld a, c
+	cp e
+	jr z, .same_x_and_y
+	jr c, .c_directly_below_e
+; c directly above e
+	ld d, DOWN
+	and a
+	ret
+
+.c_directly_below_e
+	ld d, UP
+	and a
+	ret
+
+.same_y_1
+	ld a, b
+	cp d
+	jr z, .same_x_and_y
+	jr c, .b_directly_right_of_d
+; b directly left of d
+	ld d, RIGHT
+	and a
+	ret
+
+.b_directly_right_of_d
+	ld d, LEFT
+	and a
+	ret
+
+.same_x_and_y
+	scf
+	ret
+
+QueueFollowerFirstStep: ; 848a
+	call .QueueFirstStep
+	jr c, .same
+	ld [wFollowMovementQueue], a
+	xor a
+	ld [wFollowerMovementQueueLength], a
+	ret
+
+.same
+	ld a, -1
+	ld [wFollowerMovementQueueLength], a
+	ret
+
+.QueueFirstStep
+	ld a, [wObjectFollow_Leader]
+	call GetObjectStruct
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld d, [hl]
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld e, [hl]
+	ld a, [wObjectFollow_Follower]
+	call GetObjectStruct
+	ld hl, OBJECT_NEXT_MAP_X
+	add hl, bc
+	ld a, d
+	cp [hl]
+	jr z, .check_y
+	jr c, .left
+	and a
+	ld a, movement_step_right
+	ret
+
+.left
+	and a
+	ld a, movement_step_left
+	ret
+
+.check_y
+	ld hl, OBJECT_NEXT_MAP_Y
+	add hl, bc
+	ld a, e
+	cp [hl]
+	jr z, .same_xy
+	jr c, .up
+	and a
+	ld a, movement_step_down
+	ret
+
+.up
+	and a
+	ld a, movement_step_up
+	ret
+
+.same_xy
+	scf
+	ret
--- /dev/null
+++ b/engine/printnum.asm
@@ -1,0 +1,300 @@
+_PrintNum:: ; c4c7
+; Print c digits of the b-byte value from de to hl.
+; Allows 2 to 7 digits. For 1-digit numbers, add
+; the value to char "0" instead of calling PrintNum.
+; Some extra flags can be given in bits 5-7 of b.
+; Bit 5: money if set (unless left-aligned without leading zeros)
+; Bit 6: right-aligned if set
+; Bit 7: print leading zeros if set
+
+	push bc
+
+	bit 5, b
+	jr z, .main
+	bit 7, b
+	jr nz, .moneyflag
+	bit 6, b
+	jr z, .main
+
+.moneyflag ; 101xxxxx or 011xxxxx
+	ld a, "¥"
+	ld [hli], a
+	res 5, b ; 100xxxxx or 010xxxxx
+
+.main
+	xor a
+	ld [hPrintNum1], a
+	ld [hPrintNum2], a
+	ld [hPrintNum3], a
+	ld a, b
+	and $f
+	cp 1
+	jr z, .byte
+	cp 2
+	jr z, .word
+; maximum 3 bytes
+.long
+	ld a, [de]
+	ld [hPrintNum2], a
+	inc de
+	ld a, [de]
+	ld [hPrintNum3], a
+	inc de
+	ld a, [de]
+	ld [hPrintNum4], a
+	jr .start
+
+.word
+	ld a, [de]
+	ld [hPrintNum3], a
+	inc de
+	ld a, [de]
+	ld [hPrintNum4], a
+	jr .start
+
+.byte
+	ld a, [de]
+	ld [hPrintNum4], a
+
+.start
+	push de
+
+	ld d, b
+	ld a, c
+	swap a
+	and $f
+	ld e, a
+	ld a, c
+	and $f
+	ld b, a
+	ld c, 0
+	cp 2
+	jr z, .two
+	cp 3
+	jr z, .three
+	cp 4
+	jr z, .four
+	cp 5
+	jr z, .five
+	cp 6
+	jr z, .six
+
+.seven
+	ld a, 1000000 / $10000 % $100
+	ld [hPrintNum5], a
+	ld a, 1000000 / $100 % $100
+	ld [hPrintNum6], a
+	ld a, 1000000 % $100
+	ld [hPrintNum7], a
+	call .PrintDigit
+	call .AdvancePointer
+
+.six
+	ld a, 100000 / $10000 % $100
+	ld [hPrintNum5], a
+	ld a, 100000 / $100 % $100
+	ld [hPrintNum6], a
+	ld a, 100000 % $100
+	ld [hPrintNum7], a
+	call .PrintDigit
+	call .AdvancePointer
+
+.five
+	xor a
+	ld [hPrintNum5], a
+	ld a, 10000 / $100
+	ld [hPrintNum6], a
+	ld a, 10000 % $100
+	ld [hPrintNum7], a
+	call .PrintDigit
+	call .AdvancePointer
+
+.four
+	xor a
+	ld [hPrintNum5], a
+	ld a, 1000 / $100
+	ld [hPrintNum6], a
+	ld a, 1000 % $100
+	ld [hPrintNum7], a
+	call .PrintDigit
+	call .AdvancePointer
+
+.three
+	xor a
+	ld [hPrintNum5], a
+	xor a
+	ld [hPrintNum6], a
+	ld a, 100
+	ld [hPrintNum7], a
+	call .PrintDigit
+	call .AdvancePointer
+
+.two
+	dec e
+	jr nz, .two_skip
+	ld a, "0"
+	ld [hPrintNum1], a
+.two_skip
+
+	ld c, 0
+	ld a, [hPrintNum4]
+.mod_10
+	cp 10
+	jr c, .modded_10
+	sub 10
+	inc c
+	jr .mod_10
+.modded_10
+
+	ld b, a
+	ld a, [hPrintNum1]
+	or c
+	jr nz, .money
+	call .PrintLeadingZero
+	jr .money_leading_zero
+
+.money
+	call .PrintYen
+	push af
+	ld a, "0"
+	add c
+	ld [hl], a
+	pop af
+	ld [hPrintNum1], a
+	inc e
+	dec e
+	jr nz, .money_leading_zero
+	inc hl
+	ld [hl], $f2 ; XXX
+
+.money_leading_zero
+	call .AdvancePointer
+	call .PrintYen
+	ld a, "0"
+	add b
+	ld [hli], a
+
+	pop de
+	pop bc
+	ret
+
+.PrintYen: ; c5ba
+	push af
+	ld a, [hPrintNum1]
+	and a
+	jr nz, .stop
+	bit 5, d
+	jr z, .stop
+	ld a, "¥"
+	ld [hli], a
+	res 5, d
+
+.stop
+	pop af
+	ret
+
+.PrintDigit: ; c5cb (3:45cb)
+	dec e
+	jr nz, .ok
+	ld a, "0"
+	ld [hPrintNum1], a
+.ok
+	ld c, 0
+.loop
+	ld a, [hPrintNum5]
+	ld b, a
+	ld a, [hPrintNum2]
+	ld [hPrintNum8], a
+	cp b
+	jr c, .skip1
+	sub b
+	ld [hPrintNum2], a
+	ld a, [hPrintNum6]
+	ld b, a
+	ld a, [hPrintNum3]
+	ld [hPrintNum9], a
+	cp b
+	jr nc, .skip2
+	ld a, [hPrintNum2]
+	or 0
+	jr z, .skip3
+	dec a
+	ld [hPrintNum2], a
+	ld a, [hPrintNum3]
+.skip2
+	sub b
+	ld [hPrintNum3], a
+	ld a, [hPrintNum7]
+	ld b, a
+	ld a, [hPrintNum4]
+	ld [hPrintNum10], a
+	cp b
+	jr nc, .skip4
+	ld a, [hPrintNum3]
+	and a
+	jr nz, .skip5
+	ld a, [hPrintNum2]
+	and a
+	jr z, .skip6
+	dec a
+	ld [hPrintNum2], a
+	xor a
+.skip5
+	dec a
+	ld [hPrintNum3], a
+	ld a, [hPrintNum4]
+.skip4
+	sub b
+	ld [hPrintNum4], a
+	inc c
+	jr .loop
+.skip6
+	ld a, [hPrintNum9]
+	ld [hPrintNum3], a
+.skip3
+	ld a, [hPrintNum8]
+	ld [hPrintNum2], a
+.skip1
+	ld a, [hPrintNum1]
+	or c
+	jr z, .PrintLeadingZero
+	ld a, [hPrintNum1]
+	and a
+	jr nz, .done
+	bit 5, d
+	jr z, .done
+	ld a, "¥"
+	ld [hli], a
+	res 5, d
+.done
+	ld a, "0"
+	add c
+	ld [hl], a
+	ld [hPrintNum1], a
+	inc e
+	dec e
+	ret nz
+	inc hl
+	ld [hl], "·"
+	ret
+
+.PrintLeadingZero: ; c644
+; prints a leading zero unless they are turned off in the flags
+	bit 7, d ; print leading zeroes?
+	ret z
+	ld [hl], "0"
+	ret
+
+.AdvancePointer: ; c64a
+; increments the pointer unless leading zeroes are not being printed,
+; the number is left-aligned, and no nonzero digits have been printed yet
+	bit 7, d ; print leading zeroes?
+	jr nz, .inc
+	bit 6, d ; left alignment or right alignment?
+	jr z, .inc
+	ld a, [hPrintNum1]
+	and a
+	ret z
+.inc
+	inc hl
+	ret
--- /dev/null
+++ b/engine/sine.asm
@@ -1,0 +1,50 @@
+_Sine:: ; 84d9
+; A simple sine function.
+; Return d * sin(e) in hl.
+
+; e is a signed 6-bit value.
+	ld a, e
+	and %111111
+	cp  %100000
+	jr nc, .negative
+
+	call .ApplySineWave
+	ld a, h
+	ret
+
+.negative
+	and %011111
+	call .ApplySineWave
+	ld a, h
+	xor -1
+	inc a
+	ret
+
+.ApplySineWave: ; 84ef
+	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
+
+; Factor amplitude
+.multiply
+	srl a
+	jr nc, .even
+	add hl, de
+.even
+	sla e
+	rl d
+	and a
+	jr nz, .multiply
+	ret
+
+.sinewave: ; 850b
+; A $20-word table representing a sine wave.
+; 90 degrees is index $10 at a base amplitude of $100.
+	sine_wave $100
--- /dev/null
+++ b/event/happiness_egg.asm
@@ -1,0 +1,238 @@
+GetFirstPokemonHappiness: ; 718d
+	ld hl, PartyMon1Happiness
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld de, PartySpecies
+.loop
+	ld a, [de]
+	cp EGG
+	jr nz, .done
+	inc de
+	add hl, bc
+	jr .loop
+
+.done
+	ld [wd265], a
+	ld a, [hl]
+	ld [ScriptVar], a
+	call GetPokemonName
+	jp CopyPokemonName_Buffer1_Buffer3
+
+CheckFirstMonIsEgg: ; 71ac
+	ld a, [PartySpecies]
+	ld [wd265], a
+	cp EGG
+	ld a, $1
+	jr z, .egg
+	xor a
+
+.egg
+	ld [ScriptVar], a
+	call GetPokemonName
+	jp CopyPokemonName_Buffer1_Buffer3
+
+ChangeHappiness: ; 71c2
+; Perform happiness action c on CurPartyMon
+
+	ld a, [CurPartyMon]
+	inc a
+	ld e, a
+	ld d, 0
+	ld hl, PartySpecies - 1
+	add hl, de
+	ld a, [hl]
+	cp EGG
+	ret z
+
+	push bc
+	ld hl, PartyMon1Happiness
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, [CurPartyMon]
+	call AddNTimes
+	pop bc
+
+	ld d, h
+	ld e, l
+
+	push de
+	ld a, [de]
+	cp 100
+	ld e, 0
+	jr c, .ok
+	inc e
+	cp 200
+	jr c, .ok
+	inc e
+
+.ok
+	dec c
+	ld b, 0
+	ld hl, .Actions
+rept 3
+	add hl, bc
+endr
+	ld d, 0
+	add hl, de
+	ld a, [hl]
+	cp 100
+	pop de
+
+	ld a, [de]
+	jr nc, .negative
+	add [hl]
+	jr nc, .done
+	ld a, -1
+	jr .done
+
+.negative
+	add [hl]
+	jr c, .done
+	xor a
+
+.done
+	ld [de], a
+	ld a, [wBattleMode]
+	and a
+	ret z
+	ld a, [CurPartyMon]
+	ld b, a
+	ld a, [wPartyMenuCursor]
+	cp b
+	ret nz
+	ld a, [de]
+	ld [BattleMonHappiness], a
+	ret
+
+.Actions
+	db  +5,  +3,  +2 ; Gained a level
+	db  +5,  +3,  +2 ; Vitamin
+	db  +1,  +1,  +0 ; X Item
+	db  +3,  +2,  +1 ; Battled a Gym Leader
+	db  +1,  +1,  +0 ; Learned a move
+	db  -1,  -1,  -1 ; Lost to an enemy
+	db  -5,  -5, -10 ; Fainted due to poison
+	db  -5,  -5, -10 ; Lost to a much stronger enemy
+	db  +1,  +1,  +1 ; Haircut (Y1)
+	db  +3,  +3,  +1 ; Haircut (Y2)
+	db  +5,  +5,  +2 ; Haircut (Y3)
+	db  +1,  +1,  +1 ; Haircut (O1)
+	db  +3,  +3,  +1 ; Haircut (O2)
+	db +10, +10,  +4 ; Haircut (O3)
+	db  -5,  -5, -10 ; Used Heal Powder or Energypowder (bitter)
+	db -10, -10, -15 ; Used Energy Root (bitter)
+	db -15, -15, -20 ; Used Revival Herb (bitter)
+	db  +3,  +3,  +1 ; Grooming
+	db +10,  +6,  +4 ; Gained a level in the place where it was caught
+
+StepHappiness:: ; 725a
+; Raise the party's happiness by 1 point every other step cycle.
+
+	ld hl, wHappinessStepCount
+	ld a, [hl]
+	inc a
+	and 1
+	ld [hl], a
+	ret nz
+
+	ld de, PartyCount
+	ld a, [de]
+	and a
+	ret z
+
+	ld c, a
+	ld hl, PartyMon1Happiness
+.loop
+	inc de
+	ld a, [de]
+	cp EGG
+	jr z, .next
+	inc [hl]
+	jr nz, .next
+	ld [hl], $ff
+
+.next
+	push de
+	ld de, PARTYMON_STRUCT_LENGTH
+	add hl, de
+	pop de
+	dec c
+	jr nz, .loop
+	ret
+
+DaycareStep:: ; 7282
+
+	ld a, [wDaycareMan]
+	bit 0, a
+	jr z, .daycare_lady
+
+	ld a, [wBreedMon1Level] ; level
+	cp 100
+	jr nc, .daycare_lady
+	ld hl, wBreedMon1Exp + 2 ; exp
+	inc [hl]
+	jr nz, .daycare_lady
+	dec hl
+	inc [hl]
+	jr nz, .daycare_lady
+	dec hl
+	inc [hl]
+	ld a, [hl]
+	cp 5242880 / $10000
+	jr c, .daycare_lady
+	ld a, 5242880 / $10000
+	ld [hl], a
+
+.daycare_lady
+	ld a, [wDaycareLady]
+	bit 0, a
+	jr z, .check_egg
+
+	ld a, [wBreedMon2Level] ; level
+	cp 100
+	jr nc, .check_egg
+	ld hl, wBreedMon2Exp + 2 ; exp
+	inc [hl]
+	jr nz, .check_egg
+	dec hl
+	inc [hl]
+	jr nz, .check_egg
+	dec hl
+	inc [hl]
+	ld a, [hl]
+	cp 5242880 / $10000
+	jr c, .check_egg
+	ld a, 5242880 / $10000
+	ld [hl], a
+
+.check_egg
+	ld hl, wDaycareMan
+	bit 5, [hl] ; egg
+	ret z
+	ld hl, wStepsToEgg
+	dec [hl]
+	ret nz
+
+	call Random
+	ld [hl], a
+	callab CheckBreedmonCompatibility
+	ld a, [wd265]
+	cp 230
+	ld b, -1 + 32 percent
+	jr nc, .okay
+	ld a, [wd265]
+	cp 170
+	ld b, 16 percent
+	jr nc, .okay
+	ld a, [wd265]
+	cp 110
+	ld b, 12 percent
+	jr nc, .okay
+	ld b, 4 percent
+
+.okay
+	call Random
+	cp b
+	ret nc
+	ld hl, wDaycareMan
+	res 5, [hl]
+	set 6, [hl]
+	ret
--- /dev/null
+++ b/event/overworld.asm
@@ -1,0 +1,1890 @@
+FieldMoveJumptableReset: ; c6ea
+	xor a
+	ld hl, Buffer1
+	ld bc, 7
+	call ByteFill
+	ret
+
+FieldMoveJumptable: ; c6f5
+	ld a, [Buffer1]
+	rst JumpTable
+	ld [Buffer1], a
+	bit 7, a
+	jr nz, .okay
+	and a
+	ret
+
+.okay
+	and $7f
+	scf
+	ret
+
+GetPartyNick: ; c706
+; write CurPartyMon nickname to StringBuffer1-3
+	ld hl, PartyMonNicknames
+	ld a, BOXMON
+	ld [MonType], a
+	ld a, [CurPartyMon]
+	call GetNick
+	call CopyName1
+; copy text from StringBuffer2 to StringBuffer3
+	ld de, StringBuffer2
+	ld hl, StringBuffer3
+	call CopyName2
+	ret
+
+CheckEngineFlag: ; c721
+; Check engine flag de
+; Return carry if flag is not set
+	ld b, CHECK_FLAG
+	callba EngineFlagAction
+	ld a, c
+	and a
+	jr nz, .isset
+	scf
+	ret
+.isset
+	xor a
+	ret
+
+CheckBadge: ; c731
+; Check engine flag a (ENGINE_ZEPHYRBADGE thru ENGINE_EARTHBADGE)
+; Display "Badge required" text and return carry if the badge is not owned
+	call CheckEngineFlag
+	ret nc
+	ld hl, .BadgeRequiredText
+	call MenuTextBoxBackup ; push text to queue
+	scf
+	ret
+
+.BadgeRequiredText: ; c73d
+	; Sorry! A new BADGE
+	; is required.
+	text_jump _BadgeRequiredText
+	db "@"
+
+CheckPartyMove: ; c742
+; Check if a monster in your party has move d.
+
+	ld e, 0
+	xor a
+	ld [CurPartyMon], a
+.loop
+	ld c, e
+	ld b, 0
+	ld hl, PartySpecies
+	add hl, bc
+	ld a, [hl]
+	and a
+	jr z, .no
+	cp a, -1
+	jr z, .no
+	cp a, EGG
+	jr z, .next
+
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld hl, PartyMon1Moves
+	ld a, e
+	call AddNTimes
+	ld b, NUM_MOVES
+.check
+	ld a, [hli]
+	cp d
+	jr z, .yes
+	dec b
+	jr nz, .check
+
+.next
+	inc e
+	jr .loop
+
+.yes
+	ld a, e
+	ld [CurPartyMon], a ; which mon has the move
+	xor a
+	ret
+.no
+	scf
+	ret
+
+FieldMoveFailed: ; c779
+	ld hl, .CantUseHere
+	call MenuTextBoxBackup
+	ret
+
+.CantUseHere: ; 0xc780
+	; Can't use that here.
+	text_jump UnknownText_0x1c05c8
+	db "@"
+
+CutFunction: ; c785
+	call FieldMoveJumptableReset
+.loop
+	ld hl, .Jumptable
+	call FieldMoveJumptable
+	jr nc, .loop
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+.Jumptable: ; c796 (3:4796)
+	
+	dw .CheckAble
+	dw .DoCut
+	dw .FailCut
+
+.CheckAble: ; c79c (3:479c)
+	ld de, ENGINE_HIVEBADGE
+	call CheckBadge
+	jr c, .nohivebadge
+	call CheckMapForSomethingToCut
+	jr c, .nothingtocut
+	ld a, $1
+	ret
+
+.nohivebadge
+	ld a, $80
+	ret
+
+.nothingtocut
+	ld a, $2
+	ret
+
+.DoCut: ; c7b2 (3:47b2)
+	ld hl, Script_CutFromMenu
+	call QueueScript
+	ld a, $81
+	ret
+
+.FailCut: ; c7bb (3:47bb)
+	ld hl, Text_NothingToCut
+	call MenuTextBoxBackup
+	ld a, $80
+	ret
+
+Text_UsedCut: ; 0xc7c4
+	; used CUT!
+	text_jump UnknownText_0x1c05dd
+	db "@"
+
+Text_NothingToCut: ; 0xc7c9
+	; There's nothing to CUT here.
+	text_jump UnknownText_0x1c05ec
+	db "@"
+
+CheckMapForSomethingToCut: ; c7ce
+	; Does the collision data of the facing tile permit cutting?
+	call GetFacingTileCoord
+	ld c, a
+	push de
+	callba CheckCutCollision
+	pop de
+	jr nc, .fail
+	; Get the location of the current block in OverworldMap.
+	call GetBlockLocation
+	ld c, [hl]
+	; See if that block contains something that can be cut.
+	push hl
+	ld hl, CutTreeBlockPointers
+	call CheckOverworldTileArrays
+	pop hl
+	jr nc, .fail
+	; Back up the OverworldMap address to Buffer3
+	ld a, l
+	ld [Buffer3], a
+	ld a, h
+	ld [Buffer4], a
+	; Back up the replacement tile to Buffer5
+	ld a, b
+	ld [Buffer5], a
+	; Back up the animation index to Buffer6
+	ld a, c
+	ld [Buffer6], a
+	xor a
+	ret
+
+.fail
+	scf
+	ret
+
+Script_CutFromMenu: ; c7fe
+	reloadmappart
+	special UpdateTimePals
+
+Script_Cut: ; 0xc802
+	callasm GetPartyNick
+	writetext Text_UsedCut
+	reloadmappart
+	callasm CutDownTreeOrGrass
+	closetext
+	end
+
+CutDownTreeOrGrass: ; c810
+	ld hl, Buffer3 ; OverworldMapTile
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [Buffer5] ; ReplacementTile
+	ld [hl], a
+	xor a
+	ld [hBGMapMode], a
+	call OverworldTextModeSwitch
+	call UpdateSprites
+	call DelayFrame
+	ld a, [Buffer6] ; Animation type
+	ld e, a
+	callba OWCutAnimation
+	call BufferScreen
+	call GetMovementPermissions
+	call UpdateSprites
+	call DelayFrame
+	call LoadStandardFont
+	ret
+
+CheckOverworldTileArrays: ; c840
+	; Input: c contains the tile you're facing
+	; Output: Replacement tile in b and effect on wild encounters in c, plus carry set.
+	;         Carry is not set if the facing tile cannot be replaced, or if the tileset
+	;         does not contain a tile you can replace.
+
+	; Dictionary lookup for pointer to tile replacement table
+	push bc
+	ld a, [wTileset]
+	ld de, 3
+	call IsInArray
+	pop bc
+	jr nc, .nope
+	; Load the pointer
+	inc hl
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	; Look up the tile you're facing
+	ld de, 3
+	ld a, c
+	call IsInArray
+	jr nc, .nope
+	; Load the replacement to b
+	inc hl
+	ld b, [hl]
+	; Load the animation type parameter to c
+	inc hl
+	ld c, [hl]
+	scf
+	ret
+
+.nope
+	xor a
+	ret
+
+CutTreeBlockPointers: ; c862
+; Which tileset are we in?
+	dbw TILESET_JOHTO_1, .johto1
+	dbw TILESET_JOHTO_2, .johto2
+	dbw TILESET_KANTO, .kanto
+	dbw TILESET_PARK, .park
+	dbw TILESET_ILEX_FOREST, .ilex
+	db -1
+
+.johto1: ; Johto OW
+; Which meta tile are we facing, which should we replace it with, and which animation?
+	db $03, $02, $01 ; grass
+	db $5b, $3c, $00 ; tree
+	db $5f, $3d, $00 ; tree
+	db $63, $3f, $00 ; tree
+	db $67, $3e, $00 ; tree
+	db -1
+
+.johto2: ; Goldenrod area
+	db $03, $02, $01 ; grass
+	db -1
+
+.kanto: ; Kanto OW
+	db $0b, $0a, $01 ; grass
+	db $32, $6d, $00 ; tree
+	db $33, $6c, $00 ; tree
+	db $34, $6f, $00 ; tree
+	db $35, $4c, $00 ; tree
+	db $60, $6e, $00 ; tree
+	db -1
+
+.park: ; National Park
+	db $13, $03, $01 ; grass
+	db $03, $04, $01 ; grass
+	db -1
+
+.ilex: ; Ilex Forest
+	db $0f, $17, $00
+	db -1
+
+WhirlpoolBlockPointers: ; c8a4
+	dbw TILESET_JOHTO_1, .johto
+	db -1
+
+.johto: ; c8a8
+	db $07, $36, $00
+	db -1
+
+OWFlash: ; c8ac
+	call .CheckUseFlash
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+.CheckUseFlash: ; c8b5
+; Flash
+	ld de, ENGINE_ZEPHYRBADGE
+	callba CheckBadge
+	jr c, .nozephyrbadge
+	push hl
+	callba SpecialAerodactylChamber
+	pop hl
+	jr c, .useflash
+	ld a, [wTimeOfDayPalset]
+	cp %11111111 ; 3, 3, 3, 3
+	jr nz, .notadarkcave
+.useflash
+	call UseFlash
+	ld a, $81
+	ret
+
+.notadarkcave
+	call FieldMoveFailed
+	ld a, $80
+	ret
+
+.nozephyrbadge
+	ld a, $80
+	ret
+
+UseFlash: ; c8e0
+	ld hl, Script_UseFlash
+	jp QueueScript
+
+Script_UseFlash: ; 0xc8e6
+	reloadmappart
+	special UpdateTimePals
+	writetext UnknownText_0xc8f3
+	callasm BlindingFlash
+	closetext
+	end
+
+UnknownText_0xc8f3: ; 0xc8f3
+	text_jump UnknownText_0x1c0609
+	start_asm
+	call WaitSFX
+	ld de, SFX_FLASH
+	call PlaySFX
+	call WaitSFX
+	ld hl, .BlankText
+	ret
+
+.BlankText: ; 0xc908
+	db "@"
+
+SurfFunction: ; c909
+	call FieldMoveJumptableReset
+.loop
+	ld hl, .Jumptable
+	call FieldMoveJumptable
+	jr nc, .loop
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+.Jumptable: ; c91a (3:491a)
+	dw .TrySurf
+	dw .DoSurf
+	dw .FailSurf
+	dw .AlreadySurfing
+
+.TrySurf: ; c922 (3:4922)
+	ld de, ENGINE_FOGBADGE
+	call CheckBadge
+	jr c, .asm_c956
+	ld hl, BikeFlags
+	bit 1, [hl] ; always on bike
+	jr nz, .cannotsurf
+	ld a, [PlayerState]
+	cp PLAYER_SURF
+	jr z, .alreadyfail
+	cp PLAYER_SURF_PIKA
+	jr z, .alreadyfail
+	call GetFacingTileCoord
+	call GetTileCollision
+	cp $1
+	jr nz, .cannotsurf
+	call CheckDirection
+	jr c, .cannotsurf
+	callba CheckFacingObject
+	jr c, .cannotsurf
+	ld a, $1
+	ret
+.asm_c956
+	ld a, $80
+	ret
+.alreadyfail
+	ld a, $3
+	ret
+.cannotsurf
+	ld a, $2
+	ret
+
+.DoSurf: ; c95f (3:495f)
+	call GetSurfType
+	ld [Buffer2], a ; wd1eb (aliases: MovementType)
+	call GetPartyNick
+	ld hl, SurfFromMenuScript
+	call QueueScript
+	ld a, $81
+	ret
+
+.FailSurf: ; c971 (3:4971)
+	ld hl, CantSurfText
+	call MenuTextBoxBackup
+	ld a, $80
+	ret
+
+.AlreadySurfing: ; c97a (3:497a)
+	ld hl, AlreadySurfingText
+	call MenuTextBoxBackup
+	ld a, $80
+	ret
+
+SurfFromMenuScript: ; c983
+	special UpdateTimePals
+
+UsedSurfScript: ; c986
+	writetext UsedSurfText ; "used SURF!"
+	waitbutton
+	closetext
+
+	callasm .empty_fn ; empty function
+
+	copybytetovar Buffer2
+	writevarcode VAR_MOVEMENT
+
+	special ReplaceKrisSprite
+	special PlayMapMusic
+; step into the water
+	special Special_SurfStartStep ; (slow_step_x, step_end)
+	applymovement PLAYER, MovementBuffer ; PLAYER, MovementBuffer
+	end
+
+.empty_fn: ; c9a2
+	callba MobileFn_1060bb ; empty
+	ret
+
+UsedSurfText: ; c9a9
+	text_jump _UsedSurfText
+	db "@"
+
+CantSurfText: ; c9ae
+	text_jump _CantSurfText
+	db "@"
+
+AlreadySurfingText: ; c9b3
+	text_jump _AlreadySurfingText
+	db "@"
+
+GetSurfType: ; c9b8
+; Surfing on Pikachu uses an alternate sprite.
+; This is done by using a separate movement type.
+
+	ld a, [CurPartyMon]
+	ld e, a
+	ld d, 0
+	ld hl, PartySpecies
+	add hl, de
+
+	ld a, [hl]
+	cp PIKACHU
+	ld a, PLAYER_SURF_PIKA
+	ret z
+	ld a, PLAYER_SURF
+	ret
+
+CheckDirection: ; c9cb
+; Return carry if a tile permission prevents you
+; from moving in the direction you're facing.
+
+; Get player direction
+	ld a, [PlayerDirection]
+	and a, %00001100 ; bits 2 and 3 contain direction
+	rrca
+	rrca
+	ld e, a
+	ld d, 0
+	ld hl, .Directions
+	add hl, de
+
+; Can you walk in this direction?
+	ld a, [TilePermissions]
+	and [hl]
+	jr nz, .quit
+	xor a
+	ret
+
+.quit
+	scf
+	ret
+
+.Directions
+	db FACE_DOWN
+	db FACE_UP
+	db FACE_LEFT
+	db FACE_RIGHT
+
+TrySurfOW:: ; c9e7
+; Checking a tile in the overworld.
+; Return carry if fail is allowed.
+
+; Don't ask to surf if already fail.
+	ld a, [PlayerState]
+	cp PLAYER_SURF_PIKA
+	jr z, .quit
+	cp PLAYER_SURF
+	jr z, .quit
+
+; Must be facing water.
+	ld a, [EngineBuffer1]
+	call GetTileCollision
+	cp 1 ; surfable
+	jr nz, .quit
+
+; Check tile permissions.
+	call CheckDirection
+	jr c, .quit
+
+	ld de, ENGINE_FOGBADGE
+	call CheckEngineFlag
+	jr c, .quit
+
+	ld d, SURF
+	call CheckPartyMove
+	jr c, .quit
+
+	ld hl, BikeFlags
+	bit 1, [hl] ; always on bike (can't surf)
+	jr nz, .quit
+
+	call GetSurfType
+	ld [MovementType], a
+	call GetPartyNick
+
+	ld a, BANK(AskSurfScript)
+	ld hl, AskSurfScript
+	call CallScript
+
+	scf
+	ret
+
+.quit
+	xor a
+	ret
+
+AskSurfScript: ; ca2c
+	opentext
+	writetext AskSurfText
+	yesorno
+	iftrue UsedSurfScript
+	closetext
+	end
+
+AskSurfText: ; ca36
+	text_jump _AskSurfText ; The water is calm.
+	db "@"              ; Want to SURF?
+
+FlyFunction: ; ca3b
+	call FieldMoveJumptableReset
+.loop
+	ld hl, .Jumptable
+	call FieldMoveJumptable
+	jr nc, .loop
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+.Jumptable
+ 	dw .TryFly
+ 	dw .DoFly
+ 	dw .FailFly
+
+.TryFly: ; ca52
+; Fly
+	ld de, ENGINE_STORMBADGE
+	call CheckBadge
+	jr c, .nostormbadge
+	call GetMapPermission
+	call CheckOutdoorMap
+	jr z, .outdoors
+	jr .indoors
+
+.outdoors
+	xor a
+	ld [hMapAnims], a
+	call LoadStandardMenuDataHeader
+	call ClearSprites
+	callba _FlyMap
+	ld a, e
+	cp -1
+	jr z, .illegal
+	cp NUM_SPAWNS
+	jr nc, .illegal
+
+	ld [wd001], a
+	call CloseWindow
+	ld a, $1
+	ret
+
+.nostormbadge
+	ld a, $82
+	ret
+
+.indoors
+	ld a, $2
+	ret
+
+.illegal
+	call CloseWindow
+	call WaitBGMap
+	ld a, $80
+	ret
+
+.DoFly: ; ca94
+	ld hl, .FlyScript
+	call QueueScript
+	ld a, $81
+	ret
+
+.FailFly: ; ca9d
+	call FieldMoveFailed
+	ld a, $82
+	ret
+
+.FlyScript: ; 0xcaa3
+	reloadmappart
+	callasm HideSprites
+	special UpdateTimePals
+	callasm FlyFromAnim
+	farscall Script_AbortBugContest
+	special WarpToSpawnPoint
+	callasm DelayLoadingNewSprites
+	writecode VAR_MOVEMENT, PLAYER_NORMAL
+	newloadmap MAPSETUP_FLY
+	callasm FlyToAnim
+	special WaitSFX
+	callasm .ReturnFromFly
+	end
+
+.ReturnFromFly: ; cacb
+	callba Function561d
+	call DelayFrame
+	call ReplaceKrisSprite
+	callba LoadOverworldFont
+	ret
+
+WaterfallFunction: ; cade
+	call .TryWaterfall
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+.TryWaterfall: ; cae7
+; Waterfall
+	ld de, ENGINE_RISINGBADGE
+	callba CheckBadge
+	ld a, $80
+	ret c
+	call CheckMapCanWaterfall
+	jr c, .failed
+	ld hl, Script_WaterfallFromMenu
+	call QueueScript
+	ld a, $81
+	ret
+
+.failed
+	call FieldMoveFailed
+	ld a, $80
+	ret
+
+CheckMapCanWaterfall: ; cb07
+	ld a, [PlayerDirection]
+	and $c
+	cp FACE_UP
+	jr nz, .failed
+	ld a, [TileUp]
+	call CheckWaterfallTile
+	jr nz, .failed
+	xor a
+	ret
+
+.failed
+	scf
+	ret
+
+Script_WaterfallFromMenu: ; 0xcb1c
+	reloadmappart
+	special UpdateTimePals
+
+Script_UsedWaterfall: ; 0xcb20
+	callasm GetPartyNick
+	writetext .Text_UsedWaterfall
+	waitbutton
+	closetext
+	playsound SFX_BUBBLEBEAM
+.loop
+	applymovement PLAYER, .WaterfallStep
+	callasm .CheckContinueWaterfall
+	iffalse .loop
+	end
+
+.CheckContinueWaterfall: ; cb38
+	xor a
+	ld [ScriptVar], a
+	ld a, [PlayerStandingTile]
+	call CheckWaterfallTile
+	ret z
+	callba MobileFn_1060c1
+	ld a, $1
+	ld [ScriptVar], a
+	ret
+
+.WaterfallStep: ; cb4f
+	turn_waterfall_up
+	step_end
+
+.Text_UsedWaterfall: ; 0xcb51
+	; used WATERFALL!
+	text_jump UnknownText_0x1c068e
+	db "@"
+
+TryWaterfallOW:: ; cb56
+	ld d, WATERFALL
+	call CheckPartyMove
+	jr c, .failed
+	ld de, ENGINE_RISINGBADGE
+	call CheckEngineFlag
+	jr c, .failed
+	call CheckMapCanWaterfall
+	jr c, .failed
+	ld a, BANK(Script_AskWaterfall)
+	ld hl, Script_AskWaterfall
+	call CallScript
+	scf
+	ret
+
+.failed
+	ld a, BANK(Script_CantDoWaterfall)
+	ld hl, Script_CantDoWaterfall
+	call CallScript
+	scf
+	ret
+
+Script_CantDoWaterfall: ; 0xcb7e
+	jumptext .Text_CantDoWaterfall
+
+.Text_CantDoWaterfall: ; 0xcb81
+	; Wow, it's a huge waterfall.
+	text_jump UnknownText_0x1c06a3
+	db "@"
+
+Script_AskWaterfall: ; 0xcb86
+	opentext
+	writetext .AskUseWaterfall
+	yesorno
+	iftrue Script_UsedWaterfall
+	closetext
+	end
+
+.AskUseWaterfall: ; 0xcb90
+	; Do you want to use WATERFALL?
+	text_jump UnknownText_0x1c06bf
+	db "@"
+
+EscapeRopeFunction: ; cb95
+	call FieldMoveJumptableReset
+	ld a, $1
+	jr dig_incave
+
+DigFunction: ; cb9c
+	call FieldMoveJumptableReset
+	ld a, $2
+
+dig_incave
+	ld [Buffer2], a
+.loop
+	ld hl, .DigTable
+	call FieldMoveJumptable
+	jr nc, .loop
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+.DigTable: ; cbb2
+	dw .CheckCanDig
+	dw .DoDig
+	dw .FailDig
+
+.CheckCanDig: ; cbb8
+	call GetMapPermission
+	cp CAVE
+	jr z, .incave
+	cp DUNGEON
+	jr z, .incave
+.fail
+	ld a, $2
+	ret
+
+.incave
+	ld hl, wDigWarp
+	ld a, [hli]
+	and a
+	jr z, .fail
+	ld a, [hli]
+	and a
+	jr z, .fail
+	ld a, [hl]
+	and a
+	jr z, .fail
+	ld a, $1
+	ret
+
+.DoDig: ; cbd8
+	ld hl, wDigWarp
+	ld de, wNextWarp
+	ld bc, 3
+	call CopyBytes
+	call GetPartyNick
+	ld a, [Buffer2]
+	cp $2
+	jr nz, .escaperope
+	ld hl, .UsedDigScript
+	call QueueScript
+	ld a, $81
+	ret
+
+.escaperope
+	callba SpecialKabutoChamber
+	ld hl, .UsedEscapeRopeScript
+	call QueueScript
+	ld a, $81
+	ret
+
+.FailDig: ; cc06
+	ld a, [Buffer2]
+	cp $2
+	jr nz, .failescaperope
+	ld hl, .Text_CantUseHere
+	call MenuTextBox
+	call WaitPressAorB_BlinkCursor
+	call CloseWindow
+
+.failescaperope
+	ld a, $80
+	ret
+
+.Text_UsedDig: ; 0xcc1c
+	; used DIG!
+	text_jump UnknownText_0x1c06de
+	db "@"
+
+.Text_UsedEscapeRope: ; 0xcc21
+	; used an ESCAPE ROPE.
+	text_jump UnknownText_0x1c06ed
+	db "@"
+
+.Text_CantUseHere: ; 0xcc26
+	; Can't use that here.
+	text_jump UnknownText_0x1c0705
+	db "@"
+
+.UsedEscapeRopeScript: ; 0xcc2b
+	reloadmappart
+	special UpdateTimePals
+	writetext .Text_UsedEscapeRope
+	jump .UsedDigOrEscapeRopeScript
+
+.UsedDigScript: ; 0xcc35
+	reloadmappart
+	special UpdateTimePals
+	writetext .Text_UsedDig
+
+.UsedDigOrEscapeRopeScript: ; 0xcc3c
+	waitbutton
+	closetext
+	playsound SFX_WARP_TO
+	applymovement PLAYER, .DigOut
+	farscall Script_AbortBugContest
+	special WarpToSpawnPoint
+	writecode VAR_MOVEMENT, PLAYER_NORMAL
+	newloadmap MAPSETUP_DOOR
+	playsound SFX_WARP_FROM
+	applymovement PLAYER, .DigReturn
+	end
+
+.DigOut: ; 0xcc59
+	step_dig 32
+	hide_person
+	step_end
+
+.DigReturn: ; 0xcc5d
+	show_person
+	return_dig 32
+	step_end
+
+TeleportFunction: ; cc61
+	call FieldMoveJumptableReset
+.loop
+	ld hl, .Jumptable
+	call FieldMoveJumptable
+	jr nc, .loop
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+.Jumptable: ; cc72
+	dw .TryTeleport
+	dw .DoTeleport
+	dw .FailTeleport
+
+.TryTeleport: ; cc78
+	call GetMapPermission
+	call CheckOutdoorMap
+	jr z, .CheckIfSpawnPoint
+	jr .nope
+
+.CheckIfSpawnPoint
+	ld a, [wLastSpawnMapGroup]
+	ld d, a
+	ld a, [wLastSpawnMapNumber]
+	ld e, a
+	callba IsSpawnPoint
+	jr nc, .nope
+	ld a, c
+	ld [wd001], a
+	ld a, $1
+	ret
+
+.nope
+	ld a, $2
+	ret
+
+.DoTeleport: ; cc9c
+	call GetPartyNick
+	ld hl, .TeleportScript
+	call QueueScript
+	ld a, $81
+	ret
+
+.FailTeleport: ; cca8
+	ld hl, .Text_CantUseHere
+	call MenuTextBoxBackup
+	ld a, $80
+	ret
+
+.Text_ReturnToLastMonCenter: ; 0xccb1
+	; Return to the last #MON CENTER.
+	text_jump UnknownText_0x1c071a
+	db "@"
+
+.Text_CantUseHere: ; 0xccb6
+	; Can't use that here.
+	text_jump UnknownText_0x1c073b
+	db "@"
+
+.TeleportScript: ; 0xccbb
+	reloadmappart
+	special UpdateTimePals
+	writetext .Text_ReturnToLastMonCenter
+	pause 60
+	reloadmappart
+	closetext
+	playsound SFX_WARP_TO
+	applymovement PLAYER, .TeleportFrom
+	farscall Script_AbortBugContest
+	special WarpToSpawnPoint
+	writecode VAR_MOVEMENT, PLAYER_NORMAL
+	newloadmap MAPSETUP_TELEPORT
+	playsound SFX_WARP_FROM
+	applymovement PLAYER, .TeleportTo
+	end
+
+.TeleportFrom: ; cce1
+	teleport_from
+	step_end
+
+.TeleportTo: ; cce3
+	teleport_to
+	step_end
+
+StrengthFunction: ; cce5
+	call .TryStrength
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+.TryStrength: ; ccee
+; Strength
+	ld de, ENGINE_PLAINBADGE
+	call CheckBadge
+	jr c, .Failed
+	jr .UseStrength
+
+.AlreadyUsing: ; unreferenced
+	ld hl, .JumpText
+	call MenuTextBoxBackup
+	ld a, $80
+	ret
+
+.JumpText: ; 0xcd01
+	text_jump UnknownText_0x1c0751
+	db "@"
+
+.Failed: ; cd06
+	ld a, $80
+	ret
+
+.UseStrength: ; cd09
+	ld hl, Script_StrengthFromMenu
+	call QueueScript
+	ld a, $81
+	ret
+
+SetStrengthFlag: ; cd12
+	ld hl, BikeFlags
+	set 0, [hl]
+	ld a, [CurPartyMon]
+	ld e, a
+	ld d, 0
+	ld hl, PartySpecies
+	add hl, de
+	ld a, [hl]
+	ld [Buffer6], a
+	call GetPartyNick
+	ret
+
+Script_StrengthFromMenu: ; 0xcd29
+	reloadmappart
+	special UpdateTimePals
+
+Script_UsedStrength: ; 0xcd2d
+	callasm SetStrengthFlag
+	writetext .UsedStrength
+	copybytetovar Buffer6
+	cry 0
+	pause 3
+	writetext .StrengthAllowedItToMoveBoulders
+	closetext
+	end
+
+.UsedStrength: ; 0xcd41
+	text_jump UnknownText_0x1c0774
+	db "@"
+
+.StrengthAllowedItToMoveBoulders: ; 0xcd46
+	text_jump UnknownText_0x1c0788
+	db "@"
+
+AskStrengthScript:
+	callasm TryStrengthOW
+	iffalse .AskStrength
+	if_equal $1, .DontMeetRequirements
+	jump .AlreadyUsedStrength
+
+.DontMeetRequirements: ; 0xcd59
+	jumptext UnknownText_0xcd73
+
+.AlreadyUsedStrength: ; 0xcd5c
+	jumptext UnknownText_0xcd6e
+
+.AskStrength: ; 0xcd5f
+	opentext
+	writetext UnknownText_0xcd69
+	yesorno
+	iftrue Script_UsedStrength
+	closetext
+	end
+
+UnknownText_0xcd69: ; 0xcd69
+	; A #MON may be able to move this. Want to use STRENGTH?
+	text_jump UnknownText_0x1c07a0
+	db "@"
+
+UnknownText_0xcd6e: ; 0xcd6e
+	; Boulders may now be moved!
+	text_jump UnknownText_0x1c07d8
+	db "@"
+
+UnknownText_0xcd73: ; 0xcd73
+	; A #MON may be able to move this.
+	text_jump UnknownText_0x1c07f4
+	db "@"
+
+TryStrengthOW: ; cd78
+	ld d, STRENGTH
+	call CheckPartyMove
+	jr c, .nope
+
+	ld de, ENGINE_PLAINBADGE
+	call CheckEngineFlag
+	jr c, .nope
+
+	ld hl, BikeFlags
+	bit 0, [hl]
+	jr z, .already_using
+
+	ld a, 2
+	jr .done
+
+.nope
+	ld a, 1
+	jr .done
+
+.already_using
+	xor a
+	jr .done
+
+.done
+	ld [ScriptVar], a
+	ret
+
+WhirlpoolFunction: ; cd9d
+	call FieldMoveJumptableReset
+.loop
+	ld hl, Jumptable_cdae
+	call FieldMoveJumptable
+	jr nc, .loop
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+Jumptable_cdae: ; cdae
+	dw .TryWhirlpool
+	dw .DoWhirlpool
+	dw .FailWhirlpool
+
+.TryWhirlpool: ; cdb4
+	ld de, ENGINE_GLACIERBADGE
+	call CheckBadge
+	jr c, .noglacierbadge
+	call TryWhirlpoolMenu
+	jr c, .failed
+	ld a, $1
+	ret
+
+.failed
+	ld a, $2
+	ret
+
+.noglacierbadge
+	ld a, $80
+	ret
+
+.DoWhirlpool: ; cdca
+	ld hl, Script_WhirlpoolFromMenu
+	call QueueScript
+	ld a, $81
+	ret
+
+.FailWhirlpool: ; cdd3
+	call FieldMoveFailed
+	ld a, $80
+	ret
+
+Text_UsedWhirlpool: ; 0xcdd9
+	; used WHIRLPOOL!
+	text_jump UnknownText_0x1c0816
+	db "@"
+
+TryWhirlpoolMenu: ; cdde
+	call GetFacingTileCoord
+	ld c, a
+	push de
+	call CheckWhirlpoolTile
+	pop de
+	jr c, .failed
+	call GetBlockLocation
+	ld c, [hl]
+	push hl
+	ld hl, WhirlpoolBlockPointers
+	call CheckOverworldTileArrays
+	pop hl
+	jr nc, .failed
+	ld a, l
+	ld [Buffer3], a
+	ld a, h
+	ld [Buffer4], a
+	ld a, b
+	ld [Buffer5], a
+	ld a, c
+	ld [Buffer6], a
+	xor a
+	ret
+
+.failed
+	scf
+	ret
+
+Script_WhirlpoolFromMenu: ; 0xce0b
+	reloadmappart
+	special UpdateTimePals
+
+Script_UsedWhirlpool: ; 0xce0f
+	callasm GetPartyNick
+	writetext Text_UsedWhirlpool
+	reloadmappart
+	callasm DisappearWhirlpool
+	closetext
+	end
+
+DisappearWhirlpool: ; ce1d
+	ld hl, Buffer3
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [Buffer5]
+	ld [hl], a
+	xor a
+	ld [hBGMapMode], a
+	call OverworldTextModeSwitch
+	ld a, [Buffer6]
+	ld e, a
+	callba PlayWhirlpoolSound
+	call BufferScreen
+	call GetMovementPermissions
+	ret
+
+TryWhirlpoolOW:: ; ce3e
+	ld d, WHIRLPOOL
+	call CheckPartyMove
+	jr c, .failed
+	ld de, ENGINE_GLACIERBADGE
+	call CheckEngineFlag
+	jr c, .failed
+	call TryWhirlpoolMenu
+	jr c, .failed
+	ld a, BANK(Script_AskWhirlpoolOW)
+	ld hl, Script_AskWhirlpoolOW
+	call CallScript
+	scf
+	ret
+
+.failed
+	ld a, BANK(Script_MightyWhirlpool)
+	ld hl, Script_MightyWhirlpool
+	call CallScript
+	scf
+	ret
+
+Script_MightyWhirlpool: ; 0xce66
+	jumptext .MightyWhirlpoolText
+
+.MightyWhirlpoolText: ; 0xce69
+	text_jump UnknownText_0x1c082b
+	db "@"
+
+Script_AskWhirlpoolOW: ; 0xce6e
+	opentext
+	writetext UnknownText_0xce78
+	yesorno
+	iftrue Script_UsedWhirlpool
+	closetext
+	end
+
+UnknownText_0xce78: ; 0xce78
+	text_jump UnknownText_0x1c0864
+	db "@"
+
+HeadbuttFunction: ; ce7d
+	call TryHeadbuttFromMenu
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+TryHeadbuttFromMenu: ; ce86
+	call GetFacingTileCoord
+	call CheckHeadbuttTreeTile
+	jr nz, .no_tree
+
+	ld hl, HeadbuttFromMenuScript
+	call QueueScript
+	ld a, $81
+	ret
+
+.no_tree
+	call FieldMoveFailed
+	ld a, $80
+	ret
+
+UnknownText_0xce9d: ; 0xce9d
+	; did a HEADBUTT!
+	text_jump UnknownText_0x1c0897
+	db "@"
+
+UnknownText_0xcea2: ; 0xcea2
+	; Nope. Nothing…
+	text_jump UnknownText_0x1c08ac
+	db "@"
+
+HeadbuttFromMenuScript: ; 0xcea7
+	reloadmappart
+	special UpdateTimePals
+
+HeadbuttScript: ; 0xceab
+	callasm GetPartyNick
+	writetext UnknownText_0xce9d
+
+	reloadmappart
+	callasm ShakeHeadbuttTree
+
+	callasm TreeMonEncounter
+	iffalse .no_battle
+	closetext
+	randomwildmon
+	startbattle
+	reloadmapafterbattle
+	end
+
+.no_battle
+	writetext UnknownText_0xcea2
+	waitbutton
+	closetext
+	end
+
+TryHeadbuttOW:: ; cec9
+	ld d, HEADBUTT
+	call CheckPartyMove
+	jr c, .no
+
+	ld a, BANK(AskHeadbuttScript)
+	ld hl, AskHeadbuttScript
+	call CallScript
+	scf
+	ret
+
+.no
+	xor a
+	ret
+
+AskHeadbuttScript: ; 0xcedc
+	opentext
+	writetext UnknownText_0xcee6
+	yesorno
+	iftrue HeadbuttScript
+	closetext
+	end
+
+UnknownText_0xcee6: ; 0xcee6
+	; A #MON could be in this tree. Want to HEADBUTT it?
+	text_jump UnknownText_0x1c08bc
+	db "@"
+
+RockSmashFunction: ; ceeb
+	call TryRockSmashFromMenu
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+TryRockSmashFromMenu: ; cef4
+	call GetFacingObject
+	jr c, .no_rock
+	ld a, d
+	cp $18
+	jr nz, .no_rock
+
+	ld hl, RockSmashFromMenuScript
+	call QueueScript
+	ld a, $81
+	ret
+
+.no_rock
+	call FieldMoveFailed
+	ld a, $80
+	ret
+
+GetFacingObject: ; cf0d
+	callba CheckFacingObject
+	jr nc, .fail
+
+	ld a, [hObjectStructIndexBuffer]
+	call GetObjectStruct
+	ld hl, OBJECT_MAP_OBJECT_INDEX
+	add hl, bc
+	ld a, [hl]
+	ld [hLastTalked], a
+	call GetMapObject
+	ld hl, MAPOBJECT_MOVEMENT
+	add hl, bc
+	ld a, [hl]
+	ld d, a
+	and a
+	ret
+
+.fail
+	scf
+	ret
+
+RockSmashFromMenuScript: ; 0xcf2e
+	reloadmappart
+	special UpdateTimePals
+
+RockSmashScript: ; cf32
+	callasm GetPartyNick
+	writetext UnknownText_0xcf58
+	closetext
+	special WaitSFX
+	playsound SFX_STRENGTH
+	earthquake 84
+	applymovement2 MovementData_0xcf55
+	disappear -2
+
+	callasm RockMonEncounter
+	copybytetovar TempWildMonSpecies
+	iffalse .done
+	randomwildmon
+	startbattle
+	reloadmapafterbattle
+.done
+	end
+
+MovementData_0xcf55: ; 0xcf55
+	rock_smash 10
+	step_end
+
+UnknownText_0xcf58: ; 0xcf58
+	text_jump UnknownText_0x1c08f0
+	db "@"
+
+AskRockSmashScript: ; 0xcf5d
+	callasm HasRockSmash
+	if_equal 1, .no
+
+	opentext
+	writetext UnknownText_0xcf77
+	yesorno
+	iftrue RockSmashScript
+	closetext
+	end
+.no
+	jumptext UnknownText_0xcf72
+
+UnknownText_0xcf72: ; 0xcf72
+	; Maybe a #MON can break this.
+	text_jump UnknownText_0x1c0906
+	db "@"
+
+UnknownText_0xcf77: ; 0xcf77
+	; This rock looks breakable. Want to use ROCK SMASH?
+	text_jump UnknownText_0x1c0924
+	db "@"
+
+HasRockSmash: ; cf7c
+	ld d, ROCK_SMASH
+	call CheckPartyMove
+	jr nc, .yes
+.no
+	ld a, 1
+	jr .done
+.yes
+	xor a
+	jr .done
+.done
+	ld [ScriptVar], a
+	ret
+
+FishFunction: ; cf8e
+	ld a, e
+	push af
+	call FieldMoveJumptableReset
+	pop af
+	ld [Buffer2], a
+.loop
+	ld hl, .FishTable
+	call FieldMoveJumptable
+	jr nc, .loop
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+.FishTable: ; cfa5
+	dw .TryFish
+	dw .FishNoBite
+	dw .FishGotSomething
+	dw .FailFish
+	dw .FishNoFish
+
+.TryFish: ; cfaf
+	ld a, [PlayerState]
+	cp PLAYER_SURF
+	jr z, .fail
+	cp PLAYER_SURF_PIKA
+	jr z, .fail
+	call GetFacingTileCoord
+	call GetTileCollision
+	cp $1
+	jr z, .facingwater
+.fail
+	ld a, $3
+	ret
+
+.facingwater
+	call GetFishingGroup
+	and a
+	jr nz, .goodtofish
+	ld a, $4
+	ret
+
+.goodtofish
+	ld d, a
+	ld a, [Buffer2]
+	ld e, a
+	callba Fish
+	ld a, d
+	and a
+	jr z, .nonibble
+	ld [TempWildMonSpecies], a
+	ld a, e
+	ld [CurPartyLevel], a
+	ld a, BATTLETYPE_FISH
+	ld [BattleType], a
+	ld a, $2
+	ret
+
+.nonibble
+	ld a, $1
+	ret
+
+.FailFish: ; cff1
+	ld a, $80
+	ret
+
+.FishGotSomething: ; cff4
+	ld a, $1
+	ld [Buffer6], a
+	ld hl, Script_GotABite
+	call QueueScript
+	ld a, $81
+	ret
+
+.FishNoBite: ; d002
+	ld a, $2
+	ld [Buffer6], a
+	ld hl, Script_NotEvenANibble
+	call QueueScript
+	ld a, $81
+	ret
+
+.FishNoFish: ; d010
+	ld a, $0
+	ld [Buffer6], a
+	ld hl, Script_NotEvenANibble2
+	call QueueScript
+	ld a, $81
+	ret
+
+Script_NotEvenANibble: ; 0xd01e
+	scall Script_FishCastRod
+	writetext UnknownText_0xd0a9
+	jump Script_NotEvenANibble_FallThrough
+
+Script_NotEvenANibble2: ; 0xd027
+	scall Script_FishCastRod
+	writetext UnknownText_0xd0a9
+
+Script_NotEvenANibble_FallThrough: ; 0xd02d
+	loademote EMOTE_SHADOW
+	callasm PutTheRodAway
+	closetext
+	end
+
+Script_GotABite: ; 0xd035
+	scall Script_FishCastRod
+	callasm Fishing_CheckFacingUp
+	iffalse .NotFacingUp
+	applymovement PLAYER, .Movement_FacingUp
+	jump .FightTheHookedPokemon
+
+.NotFacingUp: ; 0xd046
+	applymovement PLAYER, .Movement_NotFacingUp
+
+.FightTheHookedPokemon: ; 0xd04a
+	pause 40
+	applymovement PLAYER, .Movement_RestoreRod
+	writetext UnknownText_0xd0a4
+	callasm PutTheRodAway
+	closetext
+	randomwildmon
+	startbattle
+	reloadmapafterbattle
+	end
+
+.Movement_NotFacingUp: ; d05c
+	fish_got_bite
+	fish_got_bite
+	fish_got_bite
+	fish_got_bite
+	show_emote
+	step_end
+
+.Movement_FacingUp: ; d062
+	fish_got_bite
+	fish_got_bite
+	fish_got_bite
+	fish_got_bite
+	step_sleep_1
+	show_emote
+	step_end
+
+.Movement_RestoreRod: ; d069
+	hide_emote
+	fish_cast_rod
+	step_end
+
+Fishing_CheckFacingUp: ; d06c
+	ld a, [PlayerDirection]
+	and $c
+	cp OW_UP
+	ld a, $1
+	jr z, .up
+	xor a
+
+.up
+	ld [ScriptVar], a
+	ret
+
+Script_FishCastRod: ; 0xd07c
+	reloadmappart
+	loadvar hBGMapMode, $0
+	special UpdateTimePals
+	loademote EMOTE_ROD
+	callasm LoadFishingGFX
+	loademote EMOTE_SHOCK
+	applymovement PLAYER, MovementData_0xd093
+	pause 40
+	end
+
+MovementData_0xd093: ; d093
+	fish_cast_rod
+	step_end
+
+PutTheRodAway: ; d095
+	xor a
+	ld [hBGMapMode], a
+	ld a, $1
+	ld [PlayerAction], a
+	call UpdateSprites
+	call ReplaceKrisSprite
+	ret
+
+UnknownText_0xd0a4: ; 0xd0a4
+	; Oh! A bite!
+	text_jump UnknownText_0x1c0958
+	db "@"
+
+UnknownText_0xd0a9: ; 0xd0a9
+	; Not even a nibble!
+	text_jump UnknownText_0x1c0965
+	db "@"
+
+UnknownText_0xd0ae: ; unused
+	; Looks like there's nothing here.
+	text_jump UnknownText_0x1c0979
+	db "@"
+
+BikeFunction: ; d0b3
+	call .TryBike
+	and $7f
+	ld [wFieldMoveSucceeded], a
+	ret
+
+.TryBike: ; d0bc
+	call .CheckEnvironment
+	jr c, .CannotUseBike
+	ld a, [PlayerState]
+	cp PLAYER_NORMAL
+	jr z, .GetOnBike
+	cp PLAYER_BIKE
+	jr z, .GetOffBike
+	jr .CannotUseBike
+
+.GetOnBike
+	ld hl, Script_GetOnBike
+	ld de, Script_GetOnBike_Register
+	call .CheckIfRegistered
+	call QueueScript
+	xor a
+	ld [MusicFade], a
+	ld de, MUSIC_NONE
+	call PlayMusic
+	call DelayFrame
+	call MaxVolume
+	ld de, MUSIC_BICYCLE
+	ld a, e
+	ld [wMapMusic], a
+	call PlayMusic
+	ld a, $1
+	ret
+
+.GetOffBike
+	ld hl, BikeFlags
+	bit 1, [hl]
+	jr nz, .CantGetOffBike
+	ld hl, Script_GetOffBike
+	ld de, Script_GetOffBike_Register
+	call .CheckIfRegistered
+	ld a, BANK(Script_GetOffBike)
+	jr .done
+
+.CantGetOffBike
+	ld hl, Script_CantGetOffBike
+	jr .done
+
+.CannotUseBike
+	ld a, $0
+	ret
+
+.done
+	call QueueScript
+	ld a, $1
+	ret
+
+.CheckIfRegistered: ; d119
+	ld a, [wUsingItemWithSelect]
+	and a
+	ret z
+	ld h, d
+	ld l, e
+	ret
+
+.CheckEnvironment: ; d121
+	call GetMapPermission
+	call CheckOutdoorMap
+	jr z, .ok
+	cp CAVE
+	jr z, .ok
+	cp GATE
+	jr z, .ok
+	jr .nope
+
+.ok
+	call GetPlayerStandingTile
+	and $f ; can't use our bike in a wall or on water
+	jr nz, .nope
+	xor a
+	ret
+
+.nope
+	scf
+	ret
+
+Script_GetOnBike: ; 0xd13e
+	reloadmappart
+	special UpdateTimePals
+	writecode VAR_MOVEMENT, PLAYER_BIKE
+	writetext GotOnTheBikeText
+	waitbutton
+	closetext
+	special ReplaceKrisSprite
+	end
+
+Script_GetOnBike_Register: ; 0xd14e
+	writecode VAR_MOVEMENT, PLAYER_BIKE
+	closetext
+	special ReplaceKrisSprite
+	end
+
+; XXX
+	nop
+	ret
+
+Script_GetOffBike: ; 0xd158
+	reloadmappart
+	special UpdateTimePals
+	writecode VAR_MOVEMENT, PLAYER_NORMAL
+	writetext GotOffTheBikeText
+	waitbutton
+
+FinishGettingOffBike:
+	closetext
+	special ReplaceKrisSprite
+	special PlayMapMusic
+	end
+
+Script_GetOffBike_Register: ; 0xd16b
+	writecode VAR_MOVEMENT, PLAYER_NORMAL
+	jump FinishGettingOffBike
+
+Script_CantGetOffBike: ; 0xd171
+	writetext .CantGetOffBikeText
+	waitbutton
+	closetext
+	end
+
+.CantGetOffBikeText: ; 0xd177
+	; You can't get off here!
+	text_jump UnknownText_0x1c099a
+	db "@"
+
+GotOnTheBikeText: ; 0xd17c
+	; got on the @ .
+	text_jump UnknownText_0x1c09b2
+	db "@"
+
+GotOffTheBikeText: ; 0xd181
+	; got off the @ .
+	text_jump UnknownText_0x1c09c7
+	db "@"
+
+TryCutOW:: ; d186
+	ld d, CUT
+	call CheckPartyMove
+	jr c, .cant_cut
+
+	ld de, ENGINE_HIVEBADGE
+	call CheckEngineFlag
+	jr c, .cant_cut
+
+	ld a, BANK(AskCutScript)
+	ld hl, AskCutScript
+	call CallScript
+	scf
+	ret
+
+.cant_cut
+	ld a, BANK(CantCutScript)
+	ld hl, CantCutScript
+	call CallScript
+	scf
+	ret
+
+AskCutScript: ; 0xd1a9
+	opentext
+	writetext UnknownText_0xd1c8
+	yesorno
+	iffalse .script_d1b8
+	callasm .CheckMap
+	iftrue Script_Cut
+.script_d1b8
+	closetext
+	end
+
+.CheckMap: ; d1ba
+	xor a
+	ld [ScriptVar], a
+	call CheckMapForSomethingToCut
+	ret c
+	ld a, TRUE
+	ld [ScriptVar], a
+	ret
+
+UnknownText_0xd1c8: ; 0xd1c8
+	text_jump UnknownText_0x1c09dd
+	db "@"
+
+CantCutScript: ; 0xd1cd
+	jumptext UnknownText_0xd1d0
+
+UnknownText_0xd1d0: ; 0xd1d0
+	text_jump UnknownText_0x1c0a05
+	db "@"
--- /dev/null
+++ b/event/special.asm
@@ -1,0 +1,231 @@
+SpecialGiveShuckle: ; 7305
+
+; Adding to the party.
+	xor a
+	ld [MonType], a
+
+; Level 15 Shuckle.
+	ld a, SHUCKLE
+	ld [CurPartySpecies], a
+	ld a, 15
+	ld [CurPartyLevel], a
+
+	predef TryAddMonToParty
+	jr nc, .NotGiven
+
+; Caught data.
+	ld b, 0
+	callba SetGiftPartyMonCaughtData
+
+; Holding a Berry.
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld a, [PartyCount]
+	dec a
+	push af
+	push bc
+	ld hl, PartyMon1Item
+	call AddNTimes
+	ld [hl], BERRY
+	pop bc
+	pop af
+
+; OT ID.
+	ld hl, PartyMon1ID
+	call AddNTimes
+	ld a, $2
+	ld [hli], a
+	ld [hl], $6
+
+; Nickname.
+	ld a, [PartyCount]
+	dec a
+	ld hl, PartyMonNicknames
+	call SkipNames
+	ld de, SpecialShuckleNick
+	call CopyName2
+
+; OT.
+	ld a, [PartyCount]
+	dec a
+	ld hl, PartyMonOT
+	call SkipNames
+	ld de, SpecialShuckleOT
+	call CopyName2
+
+; Engine flag for this event.
+	ld hl, DailyFlags
+	set 5, [hl]
+; setflag ENGINE_SHUCKLE_GIVEN
+	ld a, 1
+	ld [ScriptVar], a
+	ret
+
+.NotGiven
+	xor a
+	ld [ScriptVar], a
+	ret
+
+SpecialShuckleOT:
+	db "MANIA@"
+SpecialShuckleNick:
+	db "SHUCKIE@"
+
+SpecialReturnShuckle: ; 737e
+	callba SelectMonFromParty
+	jr c, .refused
+
+	ld a, [CurPartySpecies]
+	cp SHUCKLE
+	jr nz, .DontReturn
+
+	ld a, [CurPartyMon]
+	ld hl, PartyMon1ID
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+
+; OT ID
+	ld a, [hli]
+	cp 00518 / $100
+	jr nz, .DontReturn
+	ld a, [hl]
+	cp 00518 % $100
+	jr nz, .DontReturn
+
+; OT
+	ld a, [CurPartyMon]
+	ld hl, PartyMonOT
+	call SkipNames
+	ld de, SpecialShuckleOT
+.CheckOT
+	ld a, [de]
+	cp [hl]
+	jr nz, .DontReturn
+	cp "@"
+	jr z, .done
+	inc de
+	inc hl
+	jr .CheckOT
+
+.done
+	callba CheckCurPartyMonFainted
+	jr c, .fainted
+	ld a, [CurPartyMon]
+	ld hl, PartyMon1Happiness
+	ld bc, PARTYMON_STRUCT_LENGTH
+	call AddNTimes
+	ld a, [hl]
+	cp 150
+	ld a, $3
+	jr nc, .HappyToStayWithYou
+	xor a ; take from pc
+	ld [wPokemonWithdrawDepositParameter], a
+	callab RemoveMonFromPartyOrBox
+	ld a, $2
+.HappyToStayWithYou
+	ld [ScriptVar], a
+	ret
+
+.refused
+	ld a, $1
+	ld [ScriptVar], a
+	ret
+
+.DontReturn
+	xor a
+	ld [ScriptVar], a
+	ret
+
+.fainted
+	ld a, $4
+	ld [ScriptVar], a
+	ret
+
+Special_BillsGrandfather: ; 73f7
+	callba SelectMonFromParty
+	jr c, .cancel
+	ld a, [CurPartySpecies]
+	ld [ScriptVar], a
+	ld [wNamedObjectIndexBuffer], a
+	call GetPokemonName
+	jp CopyPokemonName_Buffer1_Buffer3
+
+.cancel
+	xor a
+	ld [ScriptVar], a
+	ret
+
+Special_YoungerHaircutBrother: ; 7413
+	ld hl, Data_YoungerHaircutBrother
+	jr MassageOrHaircut
+
+Special_OlderHaircutBrother: ; 7418
+	ld hl, Data_OlderHaircutBrother
+	jr MassageOrHaircut
+
+Special_DaisyMassage: ; 741d
+	ld hl, Data_DaisyMassage
+
+MassageOrHaircut: ; 7420
+	push hl
+	callba SelectMonFromParty
+	pop hl
+	jr c, .nope
+	ld a, [CurPartySpecies]
+	cp EGG
+	jr z, .egg
+	push hl
+	call GetCurNick
+	call CopyPokemonName_Buffer1_Buffer3
+	pop hl
+	call Random
+; Bug: Subtracting $ff from $ff fails to set c.
+; This can result in overflow into the next data array.
+; In the case of getting a massage from Daisy, we bleed
+; into CopyPokemonName_Buffer1_Buffer3, which passes
+; $d0 to ChangeHappiness and returns $73 to the script.
+; The end result is that there is a 0.4% chance your
+; Pokemon's happiness will not change at all.
+.loop
+	sub [hl]
+	jr c, .ok
+rept 3
+	inc hl
+endr
+	jr .loop
+
+.ok
+	inc hl
+	ld a, [hli]
+	ld [ScriptVar], a
+	ld c, [hl]
+	call ChangeHappiness
+	ret
+
+.nope
+	xor a
+	ld [ScriptVar], a
+	ret
+
+.egg
+	ld a, 1
+	ld [ScriptVar], a
+	ret
+
+Data_YoungerHaircutBrother: ; 7459
+	db $4c, 2, HAPPINESS_YOUNGCUT1 ; 30% chance
+	db $80, 3, HAPPINESS_YOUNGCUT2 ; 20% chance
+	db $ff, 4, HAPPINESS_YOUNGCUT3 ; 50% chance
+
+Data_OlderHaircutBrother: ; 7462
+	db $9a, 2, HAPPINESS_OLDERCUT1 ; 60% chance
+	db $4c, 3, HAPPINESS_OLDERCUT2 ; 10% chance
+	db $ff, 4, HAPPINESS_OLDERCUT3 ; 30% chance
+
+Data_DaisyMassage: ; 746b
+	db $ff, 2, HAPPINESS_MASSAGE ; 99.6% chance
+
+CopyPokemonName_Buffer1_Buffer3: ; 746e
+	ld hl, StringBuffer1
+	ld de, StringBuffer3
+	ld bc, PKMN_NAME_LENGTH
+	jp CopyBytes
--- a/home/map.asm
+++ b/home/map.asm
@@ -1812,7 +1812,7 @@
 	add 6
 	ld c, a
 	ld b, 0
-	ld hl, wc801
+	ld hl, OverworldMap + 1
 	add hl, bc
 	ld a, e
 	srl a
--- a/items/item_effects.asm
+++ b/items/item_effects.asm
@@ -338,11 +338,13 @@
 ; catch rate than BRN/PSN/PAR, which in turn provide a higher catch rate than
 ; no status effect at all. But instead, it makes BRN/PSN/PAR provide no
 ; benefit.
+; Uncomment the line below to fix this.
 	ld b, a
 	ld a, [EnemyMonStatus]
 	and 1 << FRZ | SLP
 	ld c, 10
 	jr nz, .addstatus
+	; ld a, [EnemyMonStatus]
 	and a
 	ld c, 5
 	jr nz, .addstatus
@@ -3315,3 +3317,5 @@
 	add hl, bc
 	ret
 ; f971
+
+INCLUDE "items/pokeball_wobble.asm"
--- /dev/null
+++ b/items/pokeball_wobble.asm
@@ -1,0 +1,88 @@
+GetPokeBallWobble: ; f971 (3:7971)
+; Returns whether a Poke Ball will wobble in the catch animation.
+; Whether a Pokemon is caught is determined beforehand.
+
+	push de
+
+	ld a, [rSVBK]
+	ld d, a
+	push de
+
+	ld a, 1 ; BANK(Buffer2)
+	ld [rSVBK], a
+
+	ld a, [Buffer2]
+	inc a
+	ld [Buffer2], a
+
+; Wobble up to 3 times.
+	cp 3 + 1
+	jr z, .finished
+
+	ld a, [wWildMon]
+	and a
+	ld c, 0 ; next
+	jr nz, .done
+
+	ld hl, .WobbleProbabilities
+	ld a, [Buffer1]
+	ld b, a
+.loop
+	ld a, [hli]
+	cp b
+	jr nc, .checkwobble
+	inc hl
+	jr .loop
+
+.checkwobble
+	ld b, [hl]
+	call Random
+	cp b
+	ld c, 0 ; next
+	jr c, .done
+	ld c, 2 ; escaped
+	jr .done
+
+.finished
+	ld a, [wWildMon]
+	and a
+	ld c, 1 ; caught
+	jr nz, .done
+	ld c, 2 ; escaped
+
+.done
+	pop de
+	ld e, a
+	ld a, d
+	ld [rSVBK], a
+	ld a, e
+	pop de
+	ret
+
+.WobbleProbabilities: ; f9ba
+; catch rate, chance of wobbling / 255
+; nLeft/255 = (nRight/255) ** 4
+	db   1,  63
+	db   2,  75
+	db   3,  84
+	db   4,  90
+	db   5,  95
+	db   7, 103
+	db  10, 113
+	db  15, 126
+	db  20, 134
+	db  30, 149
+	db  40, 160
+	db  50, 169
+	db  60, 177
+	db  80, 191
+	db 100, 201
+	db 120, 211
+	db 140, 220
+	db 160, 227
+	db 180, 234
+	db 200, 240
+	db 220, 246
+	db 240, 251
+	db 254, 253
+	db 255, 255
--- a/main.asm
+++ b/main.asm
@@ -238,478 +238,9 @@
 ItemAttributes: ; 67c1
 INCLUDE "items/item_attributes.asm"
 INCLUDE "engine/npc_movement.asm"
+INCLUDE "event/happiness_egg.asm"
+INCLUDE "event/special.asm"
 
-GetFirstPokemonHappiness: ; 718d
-	ld hl, PartyMon1Happiness
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld de, PartySpecies
-.loop
-	ld a, [de]
-	cp EGG
-	jr nz, .done
-	inc de
-	add hl, bc
-	jr .loop
-
-.done
-	ld [wd265], a
-	ld a, [hl]
-	ld [ScriptVar], a
-	call GetPokemonName
-	jp CopyPokemonName_Buffer1_Buffer3
-
-CheckFirstMonIsEgg: ; 71ac
-	ld a, [PartySpecies]
-	ld [wd265], a
-	cp EGG
-	ld a, $1
-	jr z, .egg
-	xor a
-
-.egg
-	ld [ScriptVar], a
-	call GetPokemonName
-	jp CopyPokemonName_Buffer1_Buffer3
-
-ChangeHappiness: ; 71c2
-; Perform happiness action c on CurPartyMon
-
-	ld a, [CurPartyMon]
-	inc a
-	ld e, a
-	ld d, 0
-	ld hl, PartySpecies - 1
-	add hl, de
-	ld a, [hl]
-	cp EGG
-	ret z
-
-	push bc
-	ld hl, PartyMon1Happiness
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, [CurPartyMon]
-	call AddNTimes
-	pop bc
-
-	ld d, h
-	ld e, l
-
-	push de
-	ld a, [de]
-	cp 100
-	ld e, 0
-	jr c, .ok
-	inc e
-	cp 200
-	jr c, .ok
-	inc e
-
-.ok
-	dec c
-	ld b, 0
-	ld hl, .Actions
-rept 3
-	add hl, bc
-endr
-	ld d, 0
-	add hl, de
-	ld a, [hl]
-	cp 100
-	pop de
-
-	ld a, [de]
-	jr nc, .negative
-	add [hl]
-	jr nc, .done
-	ld a, -1
-	jr .done
-
-.negative
-	add [hl]
-	jr c, .done
-	xor a
-
-.done
-	ld [de], a
-	ld a, [wBattleMode]
-	and a
-	ret z
-	ld a, [CurPartyMon]
-	ld b, a
-	ld a, [wPartyMenuCursor]
-	cp b
-	ret nz
-	ld a, [de]
-	ld [BattleMonHappiness], a
-	ret
-
-.Actions
-	db  +5,  +3,  +2 ; Gained a level
-	db  +5,  +3,  +2 ; Vitamin
-	db  +1,  +1,  +0 ; X Item
-	db  +3,  +2,  +1 ; Battled a Gym Leader
-	db  +1,  +1,  +0 ; Learned a move
-	db  -1,  -1,  -1 ; Lost to an enemy
-	db  -5,  -5, -10 ; Fainted due to poison
-	db  -5,  -5, -10 ; Lost to a much stronger enemy
-	db  +1,  +1,  +1 ; Haircut (Y1)
-	db  +3,  +3,  +1 ; Haircut (Y2)
-	db  +5,  +5,  +2 ; Haircut (Y3)
-	db  +1,  +1,  +1 ; Haircut (O1)
-	db  +3,  +3,  +1 ; Haircut (O2)
-	db +10, +10,  +4 ; Haircut (O3)
-	db  -5,  -5, -10 ; Used Heal Powder or Energypowder (bitter)
-	db -10, -10, -15 ; Used Energy Root (bitter)
-	db -15, -15, -20 ; Used Revival Herb (bitter)
-	db  +3,  +3,  +1 ; Grooming
-	db +10,  +6,  +4 ; Gained a level in the place where it was caught
-
-StepHappiness:: ; 725a
-; Raise the party's happiness by 1 point every other step cycle.
-
-	ld hl, wHappinessStepCount
-	ld a, [hl]
-	inc a
-	and 1
-	ld [hl], a
-	ret nz
-
-	ld de, PartyCount
-	ld a, [de]
-	and a
-	ret z
-
-	ld c, a
-	ld hl, PartyMon1Happiness
-.loop
-	inc de
-	ld a, [de]
-	cp EGG
-	jr z, .next
-	inc [hl]
-	jr nz, .next
-	ld [hl], $ff
-
-.next
-	push de
-	ld de, PARTYMON_STRUCT_LENGTH
-	add hl, de
-	pop de
-	dec c
-	jr nz, .loop
-	ret
-
-DaycareStep:: ; 7282
-
-	ld a, [wDaycareMan]
-	bit 0, a
-	jr z, .daycare_lady
-
-	ld a, [wBreedMon1Level] ; level
-	cp 100
-	jr nc, .daycare_lady
-	ld hl, wBreedMon1Exp + 2 ; exp
-	inc [hl]
-	jr nz, .daycare_lady
-	dec hl
-	inc [hl]
-	jr nz, .daycare_lady
-	dec hl
-	inc [hl]
-	ld a, [hl]
-	cp 5242880 / $10000
-	jr c, .daycare_lady
-	ld a, 5242880 / $10000
-	ld [hl], a
-
-.daycare_lady
-	ld a, [wDaycareLady]
-	bit 0, a
-	jr z, .check_egg
-
-	ld a, [wBreedMon2Level] ; level
-	cp 100
-	jr nc, .check_egg
-	ld hl, wBreedMon2Exp + 2 ; exp
-	inc [hl]
-	jr nz, .check_egg
-	dec hl
-	inc [hl]
-	jr nz, .check_egg
-	dec hl
-	inc [hl]
-	ld a, [hl]
-	cp 5242880 / $10000
-	jr c, .check_egg
-	ld a, 5242880 / $10000
-	ld [hl], a
-
-.check_egg
-	ld hl, wDaycareMan
-	bit 5, [hl] ; egg
-	ret z
-	ld hl, wStepsToEgg
-	dec [hl]
-	ret nz
-
-	call Random
-	ld [hl], a
-	callab CheckBreedmonCompatibility
-	ld a, [wd265]
-	cp 230
-	ld b, -1 + 32 percent
-	jr nc, .okay
-	ld a, [wd265]
-	cp 170
-	ld b, 16 percent
-	jr nc, .okay
-	ld a, [wd265]
-	cp 110
-	ld b, 12 percent
-	jr nc, .okay
-	ld b, 4 percent
-
-.okay
-	call Random
-	cp b
-	ret nc
-	ld hl, wDaycareMan
-	res 5, [hl]
-	set 6, [hl]
-	ret
-
-SpecialGiveShuckle: ; 7305
-
-; Adding to the party.
-	xor a
-	ld [MonType], a
-
-; Level 15 Shuckle.
-	ld a, SHUCKLE
-	ld [CurPartySpecies], a
-	ld a, 15
-	ld [CurPartyLevel], a
-
-	predef TryAddMonToParty
-	jr nc, .NotGiven
-
-; Caught data.
-	ld b, 0
-	callba SetGiftPartyMonCaughtData
-
-; Holding a Berry.
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld a, [PartyCount]
-	dec a
-	push af
-	push bc
-	ld hl, PartyMon1Item
-	call AddNTimes
-	ld [hl], BERRY
-	pop bc
-	pop af
-
-; OT ID.
-	ld hl, PartyMon1ID
-	call AddNTimes
-	ld a, $2
-	ld [hli], a
-	ld [hl], $6
-
-; Nickname.
-	ld a, [PartyCount]
-	dec a
-	ld hl, PartyMonNicknames
-	call SkipNames
-	ld de, SpecialShuckleNick
-	call CopyName2
-
-; OT.
-	ld a, [PartyCount]
-	dec a
-	ld hl, PartyMonOT
-	call SkipNames
-	ld de, SpecialShuckleOT
-	call CopyName2
-
-; Engine flag for this event.
-	ld hl, DailyFlags
-	set 5, [hl]
-; setflag ENGINE_SHUCKLE_GIVEN
-	ld a, 1
-	ld [ScriptVar], a
-	ret
-
-.NotGiven
-	xor a
-	ld [ScriptVar], a
-	ret
-
-SpecialShuckleOT:
-	db "MANIA@"
-SpecialShuckleNick:
-	db "SHUCKIE@"
-
-SpecialReturnShuckle: ; 737e
-	callba SelectMonFromParty
-	jr c, .refused
-
-	ld a, [CurPartySpecies]
-	cp SHUCKLE
-	jr nz, .DontReturn
-
-	ld a, [CurPartyMon]
-	ld hl, PartyMon1ID
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-
-; OT ID
-	ld a, [hli]
-	cp 00518 / $100
-	jr nz, .DontReturn
-	ld a, [hl]
-	cp 00518 % $100
-	jr nz, .DontReturn
-
-; OT
-	ld a, [CurPartyMon]
-	ld hl, PartyMonOT
-	call SkipNames
-	ld de, SpecialShuckleOT
-.CheckOT
-	ld a, [de]
-	cp [hl]
-	jr nz, .DontReturn
-	cp "@"
-	jr z, .done
-	inc de
-	inc hl
-	jr .CheckOT
-
-.done
-	callba CheckCurPartyMonFainted
-	jr c, .fainted
-	ld a, [CurPartyMon]
-	ld hl, PartyMon1Happiness
-	ld bc, PARTYMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [hl]
-	cp 150
-	ld a, $3
-	jr nc, .HappyToStayWithYou
-	xor a ; take from pc
-	ld [wPokemonWithdrawDepositParameter], a
-	callab RemoveMonFromPartyOrBox
-	ld a, $2
-.HappyToStayWithYou
-	ld [ScriptVar], a
-	ret
-
-.refused
-	ld a, $1
-	ld [ScriptVar], a
-	ret
-
-.DontReturn
-	xor a
-	ld [ScriptVar], a
-	ret
-
-.fainted
-	ld a, $4
-	ld [ScriptVar], a
-	ret
-
-Special_BillsGrandfather: ; 73f7
-	callba SelectMonFromParty
-	jr c, .cancel
-	ld a, [CurPartySpecies]
-	ld [ScriptVar], a
-	ld [wNamedObjectIndexBuffer], a
-	call GetPokemonName
-	jp CopyPokemonName_Buffer1_Buffer3
-
-.cancel
-	xor a
-	ld [ScriptVar], a
-	ret
-
-Special_YoungerHaircutBrother: ; 7413
-	ld hl, Data_YoungerHaircutBrother
-	jr MassageOrHaircut
-
-Special_OlderHaircutBrother: ; 7418
-	ld hl, Data_OlderHaircutBrother
-	jr MassageOrHaircut
-
-Special_DaisyMassage: ; 741d
-	ld hl, Data_DaisyMassage
-
-MassageOrHaircut: ; 7420
-	push hl
-	callba SelectMonFromParty
-	pop hl
-	jr c, .nope
-	ld a, [CurPartySpecies]
-	cp EGG
-	jr z, .egg
-	push hl
-	call GetCurNick
-	call CopyPokemonName_Buffer1_Buffer3
-	pop hl
-	call Random
-; Bug: Subtracting $ff from $ff fails to set c.
-; This can result in overflow into the next data array.
-; In the case of getting a massage from Daisy, we bleed
-; into CopyPokemonName_Buffer1_Buffer3, which passes
-; $d0 to ChangeHappiness and returns $73 to the script.
-; The end result is that there is a 0.4% chance your
-; Pokemon's happiness will not change at all.
-.loop
-	sub [hl]
-	jr c, .ok
-rept 3
-	inc hl
-endr
-	jr .loop
-
-.ok
-	inc hl
-	ld a, [hli]
-	ld [ScriptVar], a
-	ld c, [hl]
-	call ChangeHappiness
-	ret
-
-.nope
-	xor a
-	ld [ScriptVar], a
-	ret
-
-.egg
-	ld a, 1
-	ld [ScriptVar], a
-	ret
-
-Data_YoungerHaircutBrother: ; 7459
-	db $4c, 2, HAPPINESS_YOUNGCUT1 ; 30% chance
-	db $80, 3, HAPPINESS_YOUNGCUT2 ; 20% chance
-	db $ff, 4, HAPPINESS_YOUNGCUT3 ; 50% chance
-
-Data_OlderHaircutBrother: ; 7462
-	db $9a, 2, HAPPINESS_OLDERCUT1 ; 60% chance
-	db $4c, 3, HAPPINESS_OLDERCUT2 ; 10% chance
-	db $ff, 4, HAPPINESS_OLDERCUT3 ; 30% chance
-
-Data_DaisyMassage: ; 746b
-	db $ff, 2, HAPPINESS_MASSAGE ; 99.6% chance
-
-CopyPokemonName_Buffer1_Buffer3: ; 746e
-	ld hl, StringBuffer1
-	ld de, StringBuffer3
-	ld bc, PKMN_NAME_LENGTH
-	jp CopyBytes
-
 Predef1: ; 747a
 ; not used
 	ret
@@ -716,916 +247,9 @@
 
 SECTION "bank2", ROMX, BANK[$2]
 
-BlankScreen: ; 8000
-	call DisableSpriteUpdates
-	xor a
-	ld [hBGMapMode], a
-	call ClearBGPalettes
-	call ClearSprites
-	hlcoord 0, 0
-	ld bc, TileMapEnd - TileMap
-	ld a, " "
-	call ByteFill
-	hlcoord 0, 0, AttrMap
-	ld bc, AttrMapEnd - AttrMap
-	ld a, $7
-	call ByteFill
-	call WaitBGMap2
-	call SetPalettes
-	ret
-
-SpawnPlayer: ; 8029
-	ld a, -1
-	ld [wObjectFollow_Leader], a
-	ld [wObjectFollow_Follower], a
-	ld a, $0
-	ld hl, PlayerObjectTemplate
-	call CopyPlayerObjectTemplate
-	ld b, $0
-	call PlayerSpawn_ConvertCoords
-	ld a, $0
-	call GetMapObject
-	ld hl, MAPOBJECT_COLOR
-	add hl, bc
-	ln e, (1 << 3) | PAL_OW_RED, PERSONTYPE_SCRIPT
-	ld a, [wPlayerSpriteSetupFlags]
-	bit 2, a
-	jr nz, .ok
-	ld a, [PlayerGender]
-	bit 0, a
-	jr z, .ok
-	ln e, (1 << 3) | PAL_OW_BLUE, PERSONTYPE_SCRIPT
-
-.ok
-	ld [hl], e
-	ld a, $0
-	ld [hMapObjectIndexBuffer], a
-	ld bc, MapObjects
-	ld a, $0
-	ld [hObjectStructIndexBuffer], a
-	ld de, ObjectStructs
-	call CopyMapObjectToObjectStruct
-	ld a, PLAYER
-	ld [wCenteredObject], a
-	ret
-
-PlayerObjectTemplate: ; 8071
-; A dummy map object used to initialize the player object.
-; Shorter than the actual amount copied by two bytes.
-; Said bytes seem to be unused.
-	person_event SPRITE_CHRIS, -4, -4, SPRITEMOVEDATA_PLAYER, 15, 15, -1, -1, 0, PERSONTYPE_SCRIPT, 0, 0, -1
-
-CopyDECoordsToMapObject:: ; 807e
-	push de
-	ld a, b
-	call GetMapObject
-	pop de
-	ld hl, MAPOBJECT_X_COORD
-	add hl, bc
-	ld [hl], d
-	ld hl, MAPOBJECT_Y_COORD
-	add hl, bc
-	ld [hl], e
-	ret
-
-PlayerSpawn_ConvertCoords: ; 808f
-	push bc
-	ld a, [XCoord]
-	add 4
-	ld d, a
-	ld a, [YCoord]
-	add 4
-	ld e, a
-	pop bc
-	call CopyDECoordsToMapObject
-	ret
-
-WritePersonXY:: ; 80a1
-	ld a, b
-	call CheckObjectVisibility
-	ret c
-
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	ld a, [hMapObjectIndexBuffer]
-	ld b, a
-	call CopyDECoordsToMapObject
-	and a
-	ret
-
-RefreshPlayerCoords: ; 80b8
-	ld a, [XCoord]
-	add 4
-	ld d, a
-	ld hl, PlayerStandingMapX
-	sub [hl]
-	ld [hl], d
-	ld hl, MapObjects + MAPOBJECT_X_COORD
-	ld [hl], d
-	ld hl, PlayerLastMapX
-	ld [hl], d
-	ld d, a
-	ld a, [YCoord]
-	add 4
-	ld e, a
-	ld hl, PlayerStandingMapY
-	sub [hl]
-	ld [hl], e
-	ld hl, MapObjects + MAPOBJECT_Y_COORD
-	ld [hl], e
-	ld hl, PlayerLastMapY
-	ld [hl], e
-	ld e, a
-	ld a, [wObjectFollow_Leader]
-	cp $0
-	ret nz ; wtf
-	ret
-
-CopyObjectStruct:: ; 80e7
-	call CheckObjectMask
-	and a
-	ret nz ; masked
-
-	ld hl, ObjectStructs + OBJECT_STRUCT_LENGTH * 1
-	ld a, 1
-	ld de, OBJECT_STRUCT_LENGTH
-.loop
-	ld [hObjectStructIndexBuffer], a
-	ld a, [hl]
-	and a
-	jr z, .done
-	add hl, de
-	ld a, [hObjectStructIndexBuffer]
-	inc a
-	cp NUM_OBJECT_STRUCTS
-	jr nz, .loop
-	scf
-	ret ; overflow
-
-.done
-	ld d, h
-	ld e, l
-	call CopyMapObjectToObjectStruct
-	ld hl, VramState
-	bit 7, [hl]
-	ret z
-
-	ld hl, OBJECT_FLAGS2
-	add hl, de
-	set 5, [hl]
-	ret
-
-CopyMapObjectToObjectStruct: ; 8116
-	call .CopyMapObjectToTempObject
-	call CopyTempObjectToObjectStruct
-	ret
-
-.CopyMapObjectToTempObject: ; 811d
-	ld a, [hObjectStructIndexBuffer]
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld [hl], a
-
-	ld a, [hMapObjectIndexBuffer]
-	ld [wTempObjectCopyMapObjectIndex], a
-
-	ld hl, MAPOBJECT_SPRITE
-	add hl, bc
-	ld a, [hl]
-	ld [wTempObjectCopySprite], a
-
-	call GetSpriteVTile
-	ld [wTempObjectCopySpriteVTile], a
-
-	ld a, [hl]
-	call GetSpritePalette
-	ld [wTempObjectCopyPalette], a
-
-	ld hl, MAPOBJECT_COLOR
-	add hl, bc
-	ld a, [hl]
-	and $f0
-	jr z, .skip_color_override
-	swap a
-	and $7 ; OAM_PALETTE
-	ld [wTempObjectCopyPalette], a
-
-.skip_color_override
-	ld hl, MAPOBJECT_MOVEMENT
-	add hl, bc
-	ld a, [hl]
-	ld [wTempObjectCopyMovement], a
-
-	ld hl, MAPOBJECT_RANGE
-	add hl, bc
-	ld a, [hl]
-	ld [wTempObjectCopyRange], a
-
-	ld hl, MAPOBJECT_X_COORD
-	add hl, bc
-	ld a, [hl]
-	ld [wTempObjectCopyX], a
-
-	ld hl, MAPOBJECT_Y_COORD
-	add hl, bc
-	ld a, [hl]
-	ld [wTempObjectCopyY], a
-
-	ld hl, MAPOBJECT_RADIUS
-	add hl, bc
-	ld a, [hl]
-	ld [wTempObjectCopyRadius], a
-	ret
-
-InitializeVisibleSprites: ; 8177
-	ld bc, MapObjects + OBJECT_LENGTH
-	ld a, 1
-.loop
-	ld [hMapObjectIndexBuffer], a
-	ld hl, MAPOBJECT_SPRITE
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .next
-
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	cp -1
-	jr nz, .next
-
-	ld a, [XCoord]
-	ld d, a
-	ld a, [YCoord]
-	ld e, a
-
-	ld hl, MAPOBJECT_X_COORD
-	add hl, bc
-	ld a, [hl]
-	add 1
-	sub d
-	jr c, .next
-
-	cp MAPOBJECT_SCREEN_WIDTH
-	jr nc, .next
-
-	ld hl, MAPOBJECT_Y_COORD
-	add hl, bc
-	ld a, [hl]
-	add 1
-	sub e
-	jr c, .next
-
-	cp MAPOBJECT_SCREEN_HEIGHT
-	jr nc, .next
-
-	push bc
-	call CopyObjectStruct
-	pop bc
-	jp c, .ret
-
-.next
-	ld hl, OBJECT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	ld a, [hMapObjectIndexBuffer]
-	inc a
-	cp NUM_OBJECTS
-	jr nz, .loop
-	ret
-
-.ret: ; 81c9
-	ret
-
-CheckObjectEnteringVisibleRange:: ; 81ca
-	nop
-	ld a, [wPlayerStepDirection]
-	cp STANDING
-	ret z
-	ld hl, .dw
-	rst JumpTable
-	ret
-
-.dw: ; 81d6
-	dw .Down
-	dw .Up
-	dw .Left
-	dw .Right
-
-.Up: ; 81de
-	ld a, [YCoord]
-	sub 1
-	jr .Vertical
-
-.Down: ; 81e5
-	ld a, [YCoord]
-	add 9
-.Vertical: ; 81ea
-	ld d, a
-	ld a, [XCoord]
-	ld e, a
-	ld bc, MapObjects + OBJECT_LENGTH
-	ld a, 1
-.loop_v
-	ld [hMapObjectIndexBuffer], a
-	ld hl, MAPOBJECT_SPRITE
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .next_v
-	ld hl, MAPOBJECT_Y_COORD
-	add hl, bc
-	ld a, d
-	cp [hl]
-	jr nz, .next_v
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	cp -1
-	jr nz, .next_v
-	ld hl, MAPOBJECT_X_COORD
-	add hl, bc
-	ld a, [hl]
-	add 1
-	sub e
-	jr c, .next_v
-	cp MAPOBJECT_SCREEN_WIDTH
-	jr nc, .next_v
-	push de
-	push bc
-	call CopyObjectStruct
-	pop bc
-	pop de
-
-.next_v
-	ld hl, OBJECT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	ld a, [hMapObjectIndexBuffer]
-	inc a
-	cp NUM_OBJECTS
-	jr nz, .loop_v
-	ret
-
-.Left: ; 8232
-	ld a, [XCoord]
-	sub 1
-	jr .Horizontal
-
-.Right: ; 8239
-	ld a, [XCoord]
-	add 10
-.Horizontal: ; 823e
-	ld e, a
-	ld a, [YCoord]
-	ld d, a
-	ld bc, MapObjects + OBJECT_LENGTH
-	ld a, 1
-.loop_h
-	ld [hMapObjectIndexBuffer], a
-	ld hl, MAPOBJECT_SPRITE
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .next_h
-	ld hl, MAPOBJECT_X_COORD
-	add hl, bc
-	ld a, e
-	cp [hl]
-	jr nz, .next_h
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	cp -1
-	jr nz, .next_h
-	ld hl, MAPOBJECT_Y_COORD
-	add hl, bc
-	ld a, [hl]
-	add 1
-	sub d
-	jr c, .next_h
-	cp MAPOBJECT_SCREEN_HEIGHT
-	jr nc, .next_h
-	push de
-	push bc
-	call CopyObjectStruct
-	pop bc
-	pop de
-
-.next_h
-	ld hl, OBJECT_LENGTH
-	add hl, bc
-	ld b, h
-	ld c, l
-	ld a, [hMapObjectIndexBuffer]
-	inc a
-	cp NUM_OBJECTS
-	jr nz, .loop_h
-	ret
-
-CopyTempObjectToObjectStruct: ; 8286
-	ld a, [wTempObjectCopyMapObjectIndex]
-	ld hl, OBJECT_MAP_OBJECT_INDEX
-	add hl, de
-	ld [hl], a
-
-	ld a, [wTempObjectCopyMovement]
-	call CopySpriteMovementData
-
-	ld a, [wTempObjectCopyPalette]
-	ld hl, OBJECT_PALETTE
-	add hl, de
-	or [hl]
-	ld [hl], a
-
-	ld a, [wTempObjectCopyY]
-	call .InitYCoord
-
-	ld a, [wTempObjectCopyX]
-	call .InitXCoord
-
-	ld a, [wTempObjectCopySprite]
-	ld hl, OBJECT_SPRITE
-	add hl, de
-	ld [hl], a
-
-	ld a, [wTempObjectCopySpriteVTile]
-	ld hl, OBJECT_SPRITE_TILE
-	add hl, de
-	ld [hl], a
-
-	ld hl, OBJECT_STEP_TYPE
-	add hl, de
-	ld [hl], STEP_TYPE_00
-
-	ld hl, OBJECT_FACING_STEP
-	add hl, de
-	ld [hl], STANDING
-
-	ld a, [wTempObjectCopyRadius]
-	call .InitRadius
-
-	ld a, [wTempObjectCopyRange]
-	ld hl, OBJECT_RANGE
-	add hl, de
-	ld [hl], a
-
-	and a
-	ret
-
-.InitYCoord: ; 82d5
-	ld hl, OBJECT_INIT_Y
-	add hl, de
-	ld [hl], a
-
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, de
-	ld [hl], a
-
-	ld hl, YCoord
-	sub [hl]
-	and $f
-	swap a
-	ld hl, wFollowNotExactPersonY
-	sub [hl]
-	ld hl, OBJECT_SPRITE_Y
-	add hl, de
-	ld [hl], a
-	ret
-
-.InitXCoord: ; 82f1
-	ld hl, OBJECT_INIT_X
-	add hl, de
-	ld [hl], a
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, de
-	ld [hl], a
-	ld hl, XCoord
-	sub [hl]
-	and $f
-	swap a
-	ld hl, wFollowNotExactPersonX
-	sub [hl]
-	ld hl, OBJECT_SPRITE_X
-	add hl, de
-	ld [hl], a
-	ret
-
-.InitRadius: ; 830d
-	ld h, a
-	inc a
-	and $f
-	ld l, a
-	ld a, h
-	add $10
-	and $f0
-	or l
-	ld hl, OBJECT_RADIUS
-	add hl, de
-	ld [hl], a
-	ret
-
-TrainerWalkToPlayer: ; 831e
-	ld a, [hLastTalked]
-	call InitMovementBuffer
-	ld a, movement_step_sleep_1
-	call AppendToMovementBuffer
-	ld a, [wd03f]
-	dec a
-	jr z, .TerminateStep
-	ld a, [hLastTalked]
-	ld b, a
-	ld c, PLAYER
-	ld d, 1
-	call .GetPathToPlayer
-	call DecrementMovementBufferCount
-
-.TerminateStep
-	ld a, movement_step_end
-	call AppendToMovementBuffer
-	ret
-
-.GetPathToPlayer: ; 8341
-	push de
-	push bc
-; get player object struct, load to de
-	ld a, c
-	call GetMapObject
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	call GetObjectStruct
-	ld d, b
-	ld e, c
-
-; get last talked object struct, load to bc
-	pop bc
-	ld a, b
-	call GetMapObject
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	call GetObjectStruct
-
-; get last talked coords, load to bc
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld c, [hl]
-	ld b, a
-
-; get player coords, load to de
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, de
-	ld a, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, de
-	ld e, [hl]
-	ld d, a
-
-	pop af
-	call ComputePathToWalkToPlayer
-	ret
-
-Special_SurfStartStep: ; 8379
-	call InitMovementBuffer
-	call .GetMovementData
-	call AppendToMovementBuffer
-	ld a, movement_step_end
-	call AppendToMovementBuffer
-	ret
-
-.GetMovementData: ; 8388
-	ld a, [PlayerDirection]
-	srl a
-	srl a
-	and 3
-	ld e, a
-	ld d, 0
-	ld hl, .movement_data
-	add hl, de
-	ld a, [hl]
-	ret
-
-.movement_data
-	slow_step_down
-	slow_step_up
-	slow_step_left
-	slow_step_right
-
-FollowNotExact:: ; 839e
-	push bc
-	ld a, c
-	call CheckObjectVisibility
-	ld d, b
-	ld e, c
-	pop bc
-	ret c
-
-	ld a, b
-	call CheckObjectVisibility
-	ret c
-
-; Person 2 is now in bc, person 1 is now in de
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld c, [hl]
-	ld b, a
-
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, de
-	ld a, [hl]
-	cp b
-	jr z, .same_x
-	jr c, .to_the_left
-	inc b
-	jr .continue
-
-.to_the_left
-	dec b
-	jr .continue
-
-.same_x
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, de
-	ld a, [hl]
-	cp c
-	jr z, .continue
-	jr c, .below
-	inc c
-	jr .continue
-
-.below
-	dec c
-
-.continue
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, de
-	ld [hl], b
-	ld a, b
-	ld hl, XCoord
-	sub [hl]
-	and $f
-	swap a
-	ld hl, wFollowNotExactPersonX
-	sub [hl]
-	ld hl, OBJECT_SPRITE_X
-	add hl, de
-	ld [hl], a
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, de
-	ld [hl], c
-	ld a, c
-	ld hl, YCoord
-	sub [hl]
-	and $f
-	swap a
-	ld hl, wFollowNotExactPersonY
-	sub [hl]
-	ld hl, OBJECT_SPRITE_Y
-	add hl, de
-	ld [hl], a
-	ld a, [hObjectStructIndexBuffer]
-	ld hl, OBJECT_RANGE
-	add hl, de
-	ld [hl], a
-	ld hl, OBJECT_MOVEMENTTYPE
-	add hl, de
-	ld [hl], SPRITEMOVEDATA_FOLLOWNOTEXACT
-	ld hl, OBJECT_STEP_TYPE
-	add hl, de
-	ld [hl], STEP_TYPE_00
-	ret
-
-GetRelativeFacing:: ; 8417
-; Determines which way map object e would have to turn to face map object d.  Returns carry if it's impossible for whatever reason.
-	ld a, d
-	call GetMapObject
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	cp NUM_OBJECT_STRUCTS
-	jr nc, .carry
-	ld d, a
-	ld a, e
-	call GetMapObject
-	ld hl, MAPOBJECT_OBJECT_STRUCT_ID
-	add hl, bc
-	ld a, [hl]
-	cp NUM_OBJECT_STRUCTS
-	jr nc, .carry
-	ld e, a
-	call .GetFacing_e_relativeto_d
-	ret
-
-.carry
-	scf
-	ret
-
-.GetFacing_e_relativeto_d: ; 8439
-; Determines which way object e would have to turn to face object d.  Returns carry if it's impossible.
-; load the coordinates of object d into bc
-	ld a, d
-	call GetObjectStruct
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld c, [hl]
-	ld b, a
-	push bc
-; load the coordinates of object e into de
-	ld a, e
-	call GetObjectStruct
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	pop bc
-; |x1 - x2|
-	ld a, b
-	sub d
-	jr z, .same_x_1
-	jr nc, .b_right_of_d_1
-	cpl
-	inc a
-
-.b_right_of_d_1
-; |y1 - y2|
-	ld h, a
-	ld a, c
-	sub e
-	jr z, .same_y_1
-	jr nc, .c_below_e_1
-	cpl
-	inc a
-
-.c_below_e_1
-; |y1 - y2| - |x1 - x2|
-	sub h
-	jr c, .same_y_1
-
-.same_x_1
-; compare the y coordinates
-	ld a, c
-	cp e
-	jr z, .same_x_and_y
-	jr c, .c_directly_below_e
-; c directly above e
-	ld d, DOWN
-	and a
-	ret
-
-.c_directly_below_e
-	ld d, UP
-	and a
-	ret
-
-.same_y_1
-	ld a, b
-	cp d
-	jr z, .same_x_and_y
-	jr c, .b_directly_right_of_d
-; b directly left of d
-	ld d, RIGHT
-	and a
-	ret
-
-.b_directly_right_of_d
-	ld d, LEFT
-	and a
-	ret
-
-.same_x_and_y
-	scf
-	ret
-
-QueueFollowerFirstStep: ; 848a
-	call .QueueFirstStep
-	jr c, .same
-	ld [wFollowMovementQueue], a
-	xor a
-	ld [wFollowerMovementQueueLength], a
-	ret
-
-.same
-	ld a, -1
-	ld [wFollowerMovementQueueLength], a
-	ret
-
-.QueueFirstStep
-	ld a, [wObjectFollow_Leader]
-	call GetObjectStruct
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld d, [hl]
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld e, [hl]
-	ld a, [wObjectFollow_Follower]
-	call GetObjectStruct
-	ld hl, OBJECT_NEXT_MAP_X
-	add hl, bc
-	ld a, d
-	cp [hl]
-	jr z, .check_y
-	jr c, .left
-	and a
-	ld a, movement_step_right
-	ret
-
-.left
-	and a
-	ld a, movement_step_left
-	ret
-
-.check_y
-	ld hl, OBJECT_NEXT_MAP_Y
-	add hl, bc
-	ld a, e
-	cp [hl]
-	jr z, .same_xy
-	jr c, .up
-	and a
-	ld a, movement_step_down
-	ret
-
-.up
-	and a
-	ld a, movement_step_up
-	ret
-
-.same_xy
-	scf
-	ret
-
-_Sine:: ; 84d9
-; A simple sine function.
-; Return d * sin(e) in hl.
-
-; e is a signed 6-bit value.
-	ld a, e
-	and %111111
-	cp  %100000
-	jr nc, .negative
-
-	call .ApplySineWave
-	ld a, h
-	ret
-
-.negative
-	and %011111
-	call .ApplySineWave
-	ld a, h
-	xor -1
-	inc a
-	ret
-
-.ApplySineWave: ; 84ef
-	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
-
-; Factor amplitude
-.multiply
-	srl a
-	jr nc, .even
-	add hl, de
-.even
-	sla e
-	rl d
-	and a
-	jr nz, .multiply
-	ret
-
-.sinewave: ; 850b
-; A $20-word table representing a sine wave.
-; 90 degrees is index $10 at a base amplitude of $100.
-	sine_wave $100
-
+INCLUDE "engine/player_object.asm"
+INCLUDE "engine/sine.asm"
 INCLUDE "engine/predef.asm"
-
 INCLUDE "engine/color.asm"
 
 SECTION "bank3", ROMX, BANK[$3]
@@ -1651,3288 +275,15 @@
 	db -1
 
 INCLUDE "engine/specials.asm"
-
-_PrintNum:: ; c4c7
-; Print c digits of the b-byte value from de to hl.
-; Allows 2 to 7 digits. For 1-digit numbers, add
-; the value to char "0" instead of calling PrintNum.
-; Some extra flags can be given in bits 5-7 of b.
-; Bit 5: money if set (unless left-aligned without leading zeros)
-; Bit 6: right-aligned if set
-; Bit 7: print leading zeros if set
-
-	push bc
-
-	bit 5, b
-	jr z, .main
-	bit 7, b
-	jr nz, .moneyflag
-	bit 6, b
-	jr z, .main
-
-.moneyflag ; 101xxxxx or 011xxxxx
-	ld a, "¥"
-	ld [hli], a
-	res 5, b ; 100xxxxx or 010xxxxx
-
-.main
-	xor a
-	ld [hPrintNum1], a
-	ld [hPrintNum2], a
-	ld [hPrintNum3], a
-	ld a, b
-	and $f
-	cp 1
-	jr z, .byte
-	cp 2
-	jr z, .word
-; maximum 3 bytes
-.long
-	ld a, [de]
-	ld [hPrintNum2], a
-	inc de
-	ld a, [de]
-	ld [hPrintNum3], a
-	inc de
-	ld a, [de]
-	ld [hPrintNum4], a
-	jr .start
-
-.word
-	ld a, [de]
-	ld [hPrintNum3], a
-	inc de
-	ld a, [de]
-	ld [hPrintNum4], a
-	jr .start
-
-.byte
-	ld a, [de]
-	ld [hPrintNum4], a
-
-.start
-	push de
-
-	ld d, b
-	ld a, c
-	swap a
-	and $f
-	ld e, a
-	ld a, c
-	and $f
-	ld b, a
-	ld c, 0
-	cp 2
-	jr z, .two
-	cp 3
-	jr z, .three
-	cp 4
-	jr z, .four
-	cp 5
-	jr z, .five
-	cp 6
-	jr z, .six
-
-.seven
-	ld a, 1000000 / $10000 % $100
-	ld [hPrintNum5], a
-	ld a, 1000000 / $100 % $100
-	ld [hPrintNum6], a
-	ld a, 1000000 % $100
-	ld [hPrintNum7], a
-	call .PrintDigit
-	call .AdvancePointer
-
-.six
-	ld a, 100000 / $10000 % $100
-	ld [hPrintNum5], a
-	ld a, 100000 / $100 % $100
-	ld [hPrintNum6], a
-	ld a, 100000 % $100
-	ld [hPrintNum7], a
-	call .PrintDigit
-	call .AdvancePointer
-
-.five
-	xor a
-	ld [hPrintNum5], a
-	ld a, 10000 / $100
-	ld [hPrintNum6], a
-	ld a, 10000 % $100
-	ld [hPrintNum7], a
-	call .PrintDigit
-	call .AdvancePointer
-
-.four
-	xor a
-	ld [hPrintNum5], a
-	ld a, 1000 / $100
-	ld [hPrintNum6], a
-	ld a, 1000 % $100
-	ld [hPrintNum7], a
-	call .PrintDigit
-	call .AdvancePointer
-
-.three
-	xor a
-	ld [hPrintNum5], a
-	xor a
-	ld [hPrintNum6], a
-	ld a, 100
-	ld [hPrintNum7], a
-	call .PrintDigit
-	call .AdvancePointer
-
-.two
-	dec e
-	jr nz, .two_skip
-	ld a, "0"
-	ld [hPrintNum1], a
-.two_skip
-
-	ld c, 0
-	ld a, [hPrintNum4]
-.mod_10
-	cp 10
-	jr c, .modded_10
-	sub 10
-	inc c
-	jr .mod_10
-.modded_10
-
-	ld b, a
-	ld a, [hPrintNum1]
-	or c
-	jr nz, .money
-	call .PrintLeadingZero
-	jr .money_leading_zero
-
-.money
-	call .PrintYen
-	push af
-	ld a, "0"
-	add c
-	ld [hl], a
-	pop af
-	ld [hPrintNum1], a
-	inc e
-	dec e
-	jr nz, .money_leading_zero
-	inc hl
-	ld [hl], $f2 ; XXX
-
-.money_leading_zero
-	call .AdvancePointer
-	call .PrintYen
-	ld a, "0"
-	add b
-	ld [hli], a
-
-	pop de
-	pop bc
-	ret
-
-.PrintYen: ; c5ba
-	push af
-	ld a, [hPrintNum1]
-	and a
-	jr nz, .stop
-	bit 5, d
-	jr z, .stop
-	ld a, "¥"
-	ld [hli], a
-	res 5, d
-
-.stop
-	pop af
-	ret
-
-.PrintDigit: ; c5cb (3:45cb)
-	dec e
-	jr nz, .ok
-	ld a, "0"
-	ld [hPrintNum1], a
-.ok
-	ld c, 0
-.loop
-	ld a, [hPrintNum5]
-	ld b, a
-	ld a, [hPrintNum2]
-	ld [hPrintNum8], a
-	cp b
-	jr c, .skip1
-	sub b
-	ld [hPrintNum2], a
-	ld a, [hPrintNum6]
-	ld b, a
-	ld a, [hPrintNum3]
-	ld [hPrintNum9], a
-	cp b
-	jr nc, .skip2
-	ld a, [hPrintNum2]
-	or 0
-	jr z, .skip3
-	dec a
-	ld [hPrintNum2], a
-	ld a, [hPrintNum3]
-.skip2
-	sub b
-	ld [hPrintNum3], a
-	ld a, [hPrintNum7]
-	ld b, a
-	ld a, [hPrintNum4]
-	ld [hPrintNum10], a
-	cp b
-	jr nc, .skip4
-	ld a, [hPrintNum3]
-	and a
-	jr nz, .skip5
-	ld a, [hPrintNum2]
-	and a
-	jr z, .skip6
-	dec a
-	ld [hPrintNum2], a
-	xor a
-.skip5
-	dec a
-	ld [hPrintNum3], a
-	ld a, [hPrintNum4]
-.skip4
-	sub b
-	ld [hPrintNum4], a
-	inc c
-	jr .loop
-.skip6
-	ld a, [hPrintNum9]
-	ld [hPrintNum3], a
-.skip3
-	ld a, [hPrintNum8]
-	ld [hPrintNum2], a
-.skip1
-	ld a, [hPrintNum1]
-	or c
-	jr z, .PrintLeadingZero
-	ld a, [hPrintNum1]
-	and a
-	jr nz, .done
-	bit 5, d
-	jr z, .done
-	ld a, "¥"
-	ld [hli], a
-	res 5, d
-.done
-	ld a, "0"
-	add c
-	ld [hl], a
-	ld [hPrintNum1], a
-	inc e
-	dec e
-	ret nz
-	inc hl
-	ld [hl], "·"
-	ret
-
-.PrintLeadingZero: ; c644
-; prints a leading zero unless they are turned off in the flags
-	bit 7, d ; print leading zeroes?
-	ret z
-	ld [hl], "0"
-	ret
-
-.AdvancePointer: ; c64a
-; increments the pointer unless leading zeroes are not being printed,
-; the number is left-aligned, and no nonzero digits have been printed yet
-	bit 7, d ; print leading zeroes?
-	jr nz, .inc
-	bit 6, d ; left alignment or right alignment?
-	jr z, .inc
-	ld a, [hPrintNum1]
-	and a
-	ret z
-.inc
-	inc hl
-	ret
-
-HealParty: ; c658
-	xor a
-	ld [CurPartyMon], a
-	ld hl, PartySpecies
-.loop
-	ld a, [hli]
-	cp -1
-	jr z, .done
-	cp EGG
-	jr z, .next
-
-	push hl
-	call HealPartyMon
-	pop hl
-
-.next
-	ld a, [CurPartyMon]
-	inc a
-	ld [CurPartyMon], a
-	jr .loop
-
-.done
-	ret
-
-HealPartyMon: ; c677
-	ld a, MON_SPECIES
-	call GetPartyParamLocation
-	ld d, h
-	ld e, l
-
-	ld hl, MON_STATUS
-	add hl, de
-	xor a
-	ld [hli], a
-	ld [hl], a
-
-	ld hl, MON_MAXHP
-	add hl, de
-
-	; bc = MON_HP
-	ld b, h
-	ld c, l
-	dec bc
-	dec bc
-
-	ld a, [hli]
-	ld [bc], a
-	inc bc
-	ld a, [hl]
-	ld [bc], a
-
-	callba RestoreAllPP
-	ret
-
-ComputeHPBarPixels: ; c699
-; e = bc * (6 * 8) / de
-	ld a, b
-	or c
-	jr z, .zero
-	push hl
-	xor a
-	ld [hMultiplicand + 0], a
-	ld a, b
-	ld [hMultiplicand + 1], a
-	ld a, c
-	ld [hMultiplicand + 2], a
-	ld a, 6 * 8
-	ld [hMultiplier], a
-	call Multiply
-	; We need de to be under 256 because hDivisor is only 1 byte.
-	ld a, d
-	and a
-	jr z, .divide
-	; divide de and hProduct by 4
-	srl d
-	rr e
-	srl d
-	rr e
-	ld a, [hProduct + 2]
-	ld b, a
-	ld a, [hProduct + 3]
-	srl b
-	rr a
-	srl b
-	rr a
-	ld [hDividend + 3], a
-	ld a, b
-	ld [hDividend + 2], a
-.divide
-	ld a, e
-	ld [hDivisor], a
-	ld b, 4
-	call Divide
-	ld a, [hQuotient + 2]
-	ld e, a
-	pop hl
-	and a
-	ret nz
-	ld e, 1
-	ret
-
-.zero
-	ld e, 0
-	ret
-
-AnimateHPBar: ; c6e0
-	call WaitBGMap
-	call _AnimateHPBar
-	call WaitBGMap
-	ret
-
-ClearBuffer1: ; c6ea
-	xor a
-	ld hl, Buffer1
-	ld bc, 7
-	call ByteFill
-	ret
-
-FieldMoveJumptable: ; c6f5
-	ld a, [Buffer1]
-	rst JumpTable
-	ld [Buffer1], a
-	bit 7, a
-	jr nz, .okay
-	and a
-	ret
-
-.okay
-	and $7f
-	scf
-	ret
-
-GetPartyNick: ; c706
-; write CurPartyMon nickname to StringBuffer1-3
-	ld hl, PartyMonNicknames
-	ld a, BOXMON
-	ld [MonType], a
-	ld a, [CurPartyMon]
-	call GetNick
-	call CopyName1
-; copy text from StringBuffer2 to StringBuffer3
-	ld de, StringBuffer2
-	ld hl, StringBuffer3
-	call CopyName2
-	ret
-
-CheckEngineFlag: ; c721
-; Check engine flag de
-; Return carry if flag is not set
-	ld b, CHECK_FLAG
-	callba EngineFlagAction
-	ld a, c
-	and a
-	jr nz, .isset
-	scf
-	ret
-.isset
-	xor a
-	ret
-
-CheckBadge: ; c731
-; Check engine flag a (ENGINE_ZEPHYRBADGE thru ENGINE_EARTHBADGE)
-; Display "Badge required" text and return carry if the badge is not owned
-	call CheckEngineFlag
-	ret nc
-	ld hl, .BadgeRequiredText
-	call MenuTextBoxBackup ; push text to queue
-	scf
-	ret
-
-.BadgeRequiredText: ; c73d
-	; Sorry! A new BADGE
-	; is required.
-	text_jump _BadgeRequiredText
-	db "@"
-
-CheckPartyMove: ; c742
-; Check if a monster in your party has move d.
-
-	ld e, 0
-	xor a
-	ld [CurPartyMon], a
-.loop
-	ld c, e
-	ld b, 0
-	ld hl, PartySpecies
-	add hl, bc
-	ld a, [hl]
-	and a
-	jr z, .no
-	cp a, -1
-	jr z, .no
-	cp a, EGG
-	jr z, .next
-
-	ld bc, PARTYMON_STRUCT_LENGTH
-	ld hl, PartyMon1Moves
-	ld a, e
-	call AddNTimes
-	ld b, NUM_MOVES
-.check
-	ld a, [hli]
-	cp d
-	jr z, .yes
-	dec b
-	jr nz, .check
-
-.next
-	inc e
-	jr .loop
-
-.yes
-	ld a, e
-	ld [CurPartyMon], a ; which mon has the move
-	xor a
-	ret
-.no
-	scf
-	ret
-
-FieldMoveFailed: ; c779
-	ld hl, .CantUseHere
-	call MenuTextBoxBackup
-	ret
-
-.CantUseHere: ; 0xc780
-	; Can't use that here.
-	text_jump UnknownText_0x1c05c8
-	db "@"
-
-CutFunction: ; c785
-	call ClearBuffer1
-.loop
-	ld hl, .Jumptable
-	call FieldMoveJumptable
-	jr nc, .loop
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-.Jumptable: ; c796 (3:4796)
-	
-	dw .CheckAble
-	dw .DoCut
-	dw .FailCut
-
-.CheckAble: ; c79c (3:479c)
-	ld de, ENGINE_HIVEBADGE
-	call CheckBadge
-	jr c, .nohivebadge
-	call CheckMapForSomethingToCut
-	jr c, .nothingtocut
-	ld a, $1
-	ret
-
-.nohivebadge
-	ld a, $80
-	ret
-
-.nothingtocut
-	ld a, $2
-	ret
-
-.DoCut: ; c7b2 (3:47b2)
-	ld hl, Script_CutFromMenu
-	call QueueScript
-	ld a, $81
-	ret
-
-.FailCut: ; c7bb (3:47bb)
-	ld hl, Text_NothingToCut
-	call MenuTextBoxBackup
-	ld a, $80
-	ret
-
-Text_UsedCut: ; 0xc7c4
-	; used CUT!
-	text_jump UnknownText_0x1c05dd
-	db "@"
-
-Text_NothingToCut: ; 0xc7c9
-	; There's nothing to CUT here.
-	text_jump UnknownText_0x1c05ec
-	db "@"
-
-CheckMapForSomethingToCut: ; c7ce
-	; Does the collision data of the facing tile permit cutting?
-	call GetFacingTileCoord
-	ld c, a
-	push de
-	callba CheckCutCollision
-	pop de
-	jr nc, .fail
-	; Get the location of the current block in OverworldMap.
-	call GetBlockLocation
-	ld c, [hl]
-	; See if that block contains something that can be cut.
-	push hl
-	ld hl, CutTreeBlockPointers
-	call CheckOverworldTileArrays
-	pop hl
-	jr nc, .fail
-	; Back up the OverworldMap address to Buffer3
-	ld a, l
-	ld [Buffer3], a
-	ld a, h
-	ld [Buffer4], a
-	; Back up the replacement tile to Buffer5
-	ld a, b
-	ld [Buffer5], a
-	; Back up the animation index to Buffer6
-	ld a, c
-	ld [Buffer6], a
-	xor a
-	ret
-
-.fail
-	scf
-	ret
-
-Script_CutFromMenu: ; c7fe
-	reloadmappart
-	special UpdateTimePals
-
-Script_Cut: ; 0xc802
-	callasm GetPartyNick
-	writetext Text_UsedCut
-	reloadmappart
-	callasm CutDownTreeOrGrass
-	closetext
-	end
-
-CutDownTreeOrGrass: ; c810
-	ld hl, Buffer3 ; OverworldMapTile
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [Buffer5] ; ReplacementTile
-	ld [hl], a
-	xor a
-	ld [hBGMapMode], a
-	call OverworldTextModeSwitch
-	call UpdateSprites
-	call DelayFrame
-	ld a, [Buffer6] ; Animation type
-	ld e, a
-	callba OWCutAnimation
-	call BufferScreen
-	call GetMovementPermissions
-	call UpdateSprites
-	call DelayFrame
-	call LoadStandardFont
-	ret
-
-CheckOverworldTileArrays: ; c840
-	; Input: c contains the tile you're facing
-	; Output: Replacement tile in b and effect on wild encounters in c, plus carry set.
-	;         Carry is not set if the facing tile cannot be replaced, or if the tileset
-	;         does not contain a tile you can replace.
-
-	; Dictionary lookup for pointer to tile replacement table
-	push bc
-	ld a, [wTileset]
-	ld de, 3
-	call IsInArray
-	pop bc
-	jr nc, .nope
-	; Load the pointer
-	inc hl
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	; Look up the tile you're facing
-	ld de, 3
-	ld a, c
-	call IsInArray
-	jr nc, .nope
-	; Load the replacement to b
-	inc hl
-	ld b, [hl]
-	; Load the animation type parameter to c
-	inc hl
-	ld c, [hl]
-	scf
-	ret
-
-.nope
-	xor a
-	ret
-
-CutTreeBlockPointers: ; c862
-; Which tileset are we in?
-	dbw TILESET_JOHTO_1, .johto1
-	dbw TILESET_JOHTO_2, .johto2
-	dbw TILESET_KANTO, .kanto
-	dbw TILESET_PARK, .park
-	dbw TILESET_ILEX_FOREST, .ilex
-	db -1
-
-.johto1: ; Johto OW
-; Which meta tile are we facing, which should we replace it with, and which animation?
-	db $03, $02, $01 ; grass
-	db $5b, $3c, $00 ; tree
-	db $5f, $3d, $00 ; tree
-	db $63, $3f, $00 ; tree
-	db $67, $3e, $00 ; tree
-	db -1
-
-.johto2: ; Goldenrod area
-	db $03, $02, $01 ; grass
-	db -1
-
-.kanto: ; Kanto OW
-	db $0b, $0a, $01 ; grass
-	db $32, $6d, $00 ; tree
-	db $33, $6c, $00 ; tree
-	db $34, $6f, $00 ; tree
-	db $35, $4c, $00 ; tree
-	db $60, $6e, $00 ; tree
-	db -1
-
-.park: ; National Park
-	db $13, $03, $01 ; grass
-	db $03, $04, $01 ; grass
-	db -1
-
-.ilex: ; Ilex Forest
-	db $0f, $17, $00
-	db -1
-
-WhirlpoolBlockPointers: ; c8a4
-	dbw TILESET_JOHTO_1, .johto
-	db -1
-
-.johto: ; c8a8
-	db $07, $36, $00
-	db -1
-
-OWFlash: ; c8ac
-	call .CheckUseFlash
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-.CheckUseFlash: ; c8b5
-; Flash
-	ld de, ENGINE_ZEPHYRBADGE
-	callba CheckBadge
-	jr c, .nozephyrbadge
-	push hl
-	callba SpecialAerodactylChamber
-	pop hl
-	jr c, .useflash
-	ld a, [wTimeOfDayPalset]
-	cp %11111111 ; 3, 3, 3, 3
-	jr nz, .notadarkcave
-.useflash
-	call UseFlash
-	ld a, $81
-	ret
-
-.notadarkcave
-	call FieldMoveFailed
-	ld a, $80
-	ret
-
-.nozephyrbadge
-	ld a, $80
-	ret
-
-UseFlash: ; c8e0
-	ld hl, Script_UseFlash
-	jp QueueScript
-
-Script_UseFlash: ; 0xc8e6
-	reloadmappart
-	special UpdateTimePals
-	writetext UnknownText_0xc8f3
-	callasm BlindingFlash
-	closetext
-	end
-
-UnknownText_0xc8f3: ; 0xc8f3
-	text_jump UnknownText_0x1c0609
-	start_asm
-	call WaitSFX
-	ld de, SFX_FLASH
-	call PlaySFX
-	call WaitSFX
-	ld hl, .BlankText
-	ret
-
-.BlankText: ; 0xc908
-	db "@"
-
-SurfFunction: ; c909
-	call ClearBuffer1
-.loop
-	ld hl, .Jumptable
-	call FieldMoveJumptable
-	jr nc, .loop
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-.Jumptable: ; c91a (3:491a)
-	dw .TrySurf
-	dw .DoSurf
-	dw .FailSurf
-	dw .AlreadySurfing
-
-.TrySurf: ; c922 (3:4922)
-	ld de, ENGINE_FOGBADGE
-	call CheckBadge
-	jr c, .asm_c956
-	ld hl, BikeFlags
-	bit 1, [hl] ; always on bike
-	jr nz, .cannotsurf
-	ld a, [PlayerState]
-	cp PLAYER_SURF
-	jr z, .alreadyfail
-	cp PLAYER_SURF_PIKA
-	jr z, .alreadyfail
-	call GetFacingTileCoord
-	call GetTileCollision
-	cp $1
-	jr nz, .cannotsurf
-	call CheckDirection
-	jr c, .cannotsurf
-	callba CheckFacingObject
-	jr c, .cannotsurf
-	ld a, $1
-	ret
-.asm_c956
-	ld a, $80
-	ret
-.alreadyfail
-	ld a, $3
-	ret
-.cannotsurf
-	ld a, $2
-	ret
-
-.DoSurf: ; c95f (3:495f)
-	call GetSurfType
-	ld [Buffer2], a ; wd1eb (aliases: MovementType)
-	call GetPartyNick
-	ld hl, SurfFromMenuScript
-	call QueueScript
-	ld a, $81
-	ret
-
-.FailSurf: ; c971 (3:4971)
-	ld hl, CantSurfText
-	call MenuTextBoxBackup
-	ld a, $80
-	ret
-
-.AlreadySurfing: ; c97a (3:497a)
-	ld hl, AlreadySurfingText
-	call MenuTextBoxBackup
-	ld a, $80
-	ret
-
-SurfFromMenuScript: ; c983
-	special UpdateTimePals
-
-UsedSurfScript: ; c986
-	writetext UsedSurfText ; "used SURF!"
-	waitbutton
-	closetext
-
-	callasm .empty_fn ; empty function
-
-	copybytetovar Buffer2
-	writevarcode VAR_MOVEMENT
-
-	special ReplaceKrisSprite
-	special PlayMapMusic
-; step into the water
-	special Special_SurfStartStep ; (slow_step_x, step_end)
-	applymovement PLAYER, MovementBuffer ; PLAYER, MovementBuffer
-	end
-
-.empty_fn: ; c9a2
-	callba MobileFn_1060bb ; empty
-	ret
-
-UsedSurfText: ; c9a9
-	text_jump _UsedSurfText
-	db "@"
-
-CantSurfText: ; c9ae
-	text_jump _CantSurfText
-	db "@"
-
-AlreadySurfingText: ; c9b3
-	text_jump _AlreadySurfingText
-	db "@"
-
-GetSurfType: ; c9b8
-; Surfing on Pikachu uses an alternate sprite.
-; This is done by using a separate movement type.
-
-	ld a, [CurPartyMon]
-	ld e, a
-	ld d, 0
-	ld hl, PartySpecies
-	add hl, de
-
-	ld a, [hl]
-	cp PIKACHU
-	ld a, PLAYER_SURF_PIKA
-	ret z
-	ld a, PLAYER_SURF
-	ret
-
-CheckDirection: ; c9cb
-; Return carry if a tile permission prevents you
-; from moving in the direction you're facing.
-
-; Get player direction
-	ld a, [PlayerDirection]
-	and a, %00001100 ; bits 2 and 3 contain direction
-	rrca
-	rrca
-	ld e, a
-	ld d, 0
-	ld hl, .Directions
-	add hl, de
-
-; Can you walk in this direction?
-	ld a, [TilePermissions]
-	and [hl]
-	jr nz, .quit
-	xor a
-	ret
-
-.quit
-	scf
-	ret
-
-.Directions
-	db FACE_DOWN
-	db FACE_UP
-	db FACE_LEFT
-	db FACE_RIGHT
-
-TrySurfOW:: ; c9e7
-; Checking a tile in the overworld.
-; Return carry if fail is allowed.
-
-; Don't ask to surf if already fail.
-	ld a, [PlayerState]
-	cp PLAYER_SURF_PIKA
-	jr z, .quit
-	cp PLAYER_SURF
-	jr z, .quit
-
-; Must be facing water.
-	ld a, [EngineBuffer1]
-	call GetTileCollision
-	cp 1 ; surfable
-	jr nz, .quit
-
-; Check tile permissions.
-	call CheckDirection
-	jr c, .quit
-
-	ld de, ENGINE_FOGBADGE
-	call CheckEngineFlag
-	jr c, .quit
-
-	ld d, SURF
-	call CheckPartyMove
-	jr c, .quit
-
-	ld hl, BikeFlags
-	bit 1, [hl] ; always on bike (can't surf)
-	jr nz, .quit
-
-	call GetSurfType
-	ld [MovementType], a
-	call GetPartyNick
-
-	ld a, BANK(AskSurfScript)
-	ld hl, AskSurfScript
-	call CallScript
-
-	scf
-	ret
-
-.quit
-	xor a
-	ret
-
-AskSurfScript: ; ca2c
-	opentext
-	writetext AskSurfText
-	yesorno
-	iftrue UsedSurfScript
-	closetext
-	end
-
-AskSurfText: ; ca36
-	text_jump _AskSurfText ; The water is calm.
-	db "@"              ; Want to SURF?
-
-FlyFunction: ; ca3b
-	call ClearBuffer1
-.loop
-	ld hl, .Jumptable
-	call FieldMoveJumptable
-	jr nc, .loop
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-.Jumptable
- 	dw .TryFly
- 	dw .DoFly
- 	dw .FailFly
-
-.TryFly: ; ca52
-; Fly
-	ld de, ENGINE_STORMBADGE
-	call CheckBadge
-	jr c, .nostormbadge
-	call GetMapPermission
-	call CheckOutdoorMap
-	jr z, .outdoors
-	jr .indoors
-
-.outdoors
-	xor a
-	ld [hMapAnims], a
-	call LoadStandardMenuDataHeader
-	call ClearSprites
-	callba _FlyMap
-	ld a, e
-	cp -1
-	jr z, .illegal
-	cp NUM_SPAWNS
-	jr nc, .illegal
-
-	ld [wd001], a
-	call CloseWindow
-	ld a, $1
-	ret
-
-.nostormbadge
-	ld a, $82
-	ret
-
-.indoors
-	ld a, $2
-	ret
-
-.illegal
-	call CloseWindow
-	call WaitBGMap
-	ld a, $80
-	ret
-
-.DoFly: ; ca94
-	ld hl, .FlyScript
-	call QueueScript
-	ld a, $81
-	ret
-
-.FailFly: ; ca9d
-	call FieldMoveFailed
-	ld a, $82
-	ret
-
-.FlyScript: ; 0xcaa3
-	reloadmappart
-	callasm HideSprites
-	special UpdateTimePals
-	callasm FlyFromAnim
-	farscall Script_AbortBugContest
-	special WarpToSpawnPoint
-	callasm DelayLoadingNewSprites
-	writecode VAR_MOVEMENT, PLAYER_NORMAL
-	newloadmap MAPSETUP_FLY
-	callasm FlyToAnim
-	special WaitSFX
-	callasm .ReturnFromFly
-	end
-
-.ReturnFromFly: ; cacb
-	callba Function561d
-	call DelayFrame
-	call ReplaceKrisSprite
-	callba LoadOverworldFont
-	ret
-
-WaterfallFunction: ; cade
-	call .TryWaterfall
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-.TryWaterfall: ; cae7
-; Waterfall
-	ld de, ENGINE_RISINGBADGE
-	callba CheckBadge
-	ld a, $80
-	ret c
-	call CheckMapCanWaterfall
-	jr c, .failed
-	ld hl, Script_WaterfallFromMenu
-	call QueueScript
-	ld a, $81
-	ret
-
-.failed
-	call FieldMoveFailed
-	ld a, $80
-	ret
-
-CheckMapCanWaterfall: ; cb07
-	ld a, [PlayerDirection]
-	and $c
-	cp FACE_UP
-	jr nz, .failed
-	ld a, [TileUp]
-	call CheckWaterfallTile
-	jr nz, .failed
-	xor a
-	ret
-
-.failed
-	scf
-	ret
-
-Script_WaterfallFromMenu: ; 0xcb1c
-	reloadmappart
-	special UpdateTimePals
-
-Script_UsedWaterfall: ; 0xcb20
-	callasm GetPartyNick
-	writetext .Text_UsedWaterfall
-	waitbutton
-	closetext
-	playsound SFX_BUBBLEBEAM
-.loop
-	applymovement PLAYER, .WaterfallStep
-	callasm .CheckContinueWaterfall
-	iffalse .loop
-	end
-
-.CheckContinueWaterfall: ; cb38
-	xor a
-	ld [ScriptVar], a
-	ld a, [PlayerStandingTile]
-	call CheckWaterfallTile
-	ret z
-	callba MobileFn_1060c1
-	ld a, $1
-	ld [ScriptVar], a
-	ret
-
-.WaterfallStep: ; cb4f
-	turn_waterfall_up
-	step_end
-
-.Text_UsedWaterfall: ; 0xcb51
-	; used WATERFALL!
-	text_jump UnknownText_0x1c068e
-	db "@"
-
-TryWaterfallOW:: ; cb56
-	ld d, WATERFALL
-	call CheckPartyMove
-	jr c, .failed
-	ld de, ENGINE_RISINGBADGE
-	call CheckEngineFlag
-	jr c, .failed
-	call CheckMapCanWaterfall
-	jr c, .failed
-	ld a, BANK(Script_AskWaterfall)
-	ld hl, Script_AskWaterfall
-	call CallScript
-	scf
-	ret
-
-.failed
-	ld a, BANK(Script_CantDoWaterfall)
-	ld hl, Script_CantDoWaterfall
-	call CallScript
-	scf
-	ret
-
-Script_CantDoWaterfall: ; 0xcb7e
-	jumptext .Text_CantDoWaterfall
-
-.Text_CantDoWaterfall: ; 0xcb81
-	; Wow, it's a huge waterfall.
-	text_jump UnknownText_0x1c06a3
-	db "@"
-
-Script_AskWaterfall: ; 0xcb86
-	opentext
-	writetext .AskUseWaterfall
-	yesorno
-	iftrue Script_UsedWaterfall
-	closetext
-	end
-
-.AskUseWaterfall: ; 0xcb90
-	; Do you want to use WATERFALL?
-	text_jump UnknownText_0x1c06bf
-	db "@"
-
-EscapeRopeFunction: ; cb95
-	call ClearBuffer1
-	ld a, $1
-	jr dig_incave
-
-DigFunction: ; cb9c
-	call ClearBuffer1
-	ld a, $2
-
-dig_incave
-	ld [Buffer2], a
-.loop
-	ld hl, .DigTable
-	call FieldMoveJumptable
-	jr nc, .loop
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-.DigTable: ; cbb2
-	dw .CheckCanDig
-	dw .DoDig
-	dw .FailDig
-
-.CheckCanDig: ; cbb8
-	call GetMapPermission
-	cp CAVE
-	jr z, .incave
-	cp DUNGEON
-	jr z, .incave
-.fail
-	ld a, $2
-	ret
-
-.incave
-	ld hl, wDigWarp
-	ld a, [hli]
-	and a
-	jr z, .fail
-	ld a, [hli]
-	and a
-	jr z, .fail
-	ld a, [hl]
-	and a
-	jr z, .fail
-	ld a, $1
-	ret
-
-.DoDig: ; cbd8
-	ld hl, wDigWarp
-	ld de, wNextWarp
-	ld bc, 3
-	call CopyBytes
-	call GetPartyNick
-	ld a, [Buffer2]
-	cp $2
-	jr nz, .escaperope
-	ld hl, .UsedDigScript
-	call QueueScript
-	ld a, $81
-	ret
-
-.escaperope
-	callba SpecialKabutoChamber
-	ld hl, .UsedEscapeRopeScript
-	call QueueScript
-	ld a, $81
-	ret
-
-.FailDig: ; cc06
-	ld a, [Buffer2]
-	cp $2
-	jr nz, .failescaperope
-	ld hl, .Text_CantUseHere
-	call MenuTextBox
-	call WaitPressAorB_BlinkCursor
-	call CloseWindow
-
-.failescaperope
-	ld a, $80
-	ret
-
-.Text_UsedDig: ; 0xcc1c
-	; used DIG!
-	text_jump UnknownText_0x1c06de
-	db "@"
-
-.Text_UsedEscapeRope: ; 0xcc21
-	; used an ESCAPE ROPE.
-	text_jump UnknownText_0x1c06ed
-	db "@"
-
-.Text_CantUseHere: ; 0xcc26
-	; Can't use that here.
-	text_jump UnknownText_0x1c0705
-	db "@"
-
-.UsedEscapeRopeScript: ; 0xcc2b
-	reloadmappart
-	special UpdateTimePals
-	writetext .Text_UsedEscapeRope
-	jump .UsedDigOrEscapeRopeScript
-
-.UsedDigScript: ; 0xcc35
-	reloadmappart
-	special UpdateTimePals
-	writetext .Text_UsedDig
-
-.UsedDigOrEscapeRopeScript: ; 0xcc3c
-	waitbutton
-	closetext
-	playsound SFX_WARP_TO
-	applymovement PLAYER, .DigOut
-	farscall Script_AbortBugContest
-	special WarpToSpawnPoint
-	writecode VAR_MOVEMENT, PLAYER_NORMAL
-	newloadmap MAPSETUP_DOOR
-	playsound SFX_WARP_FROM
-	applymovement PLAYER, .DigReturn
-	end
-
-.DigOut: ; 0xcc59
-	step_dig 32
-	hide_person
-	step_end
-
-.DigReturn: ; 0xcc5d
-	show_person
-	return_dig 32
-	step_end
-
-TeleportFunction: ; cc61
-	call ClearBuffer1
-.loop
-	ld hl, .Jumptable
-	call FieldMoveJumptable
-	jr nc, .loop
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-.Jumptable: ; cc72
-	dw .TryTeleport
-	dw .DoTeleport
-	dw .FailTeleport
-
-.TryTeleport: ; cc78
-	call GetMapPermission
-	call CheckOutdoorMap
-	jr z, .CheckIfSpawnPoint
-	jr .nope
-
-.CheckIfSpawnPoint
-	ld a, [wLastSpawnMapGroup]
-	ld d, a
-	ld a, [wLastSpawnMapNumber]
-	ld e, a
-	callba IsSpawnPoint
-	jr nc, .nope
-	ld a, c
-	ld [wd001], a
-	ld a, $1
-	ret
-
-.nope
-	ld a, $2
-	ret
-
-.DoTeleport: ; cc9c
-	call GetPartyNick
-	ld hl, .TeleportScript
-	call QueueScript
-	ld a, $81
-	ret
-
-.FailTeleport: ; cca8
-	ld hl, .Text_CantUseHere
-	call MenuTextBoxBackup
-	ld a, $80
-	ret
-
-.Text_ReturnToLastMonCenter: ; 0xccb1
-	; Return to the last #MON CENTER.
-	text_jump UnknownText_0x1c071a
-	db "@"
-
-.Text_CantUseHere: ; 0xccb6
-	; Can't use that here.
-	text_jump UnknownText_0x1c073b
-	db "@"
-
-.TeleportScript: ; 0xccbb
-	reloadmappart
-	special UpdateTimePals
-	writetext .Text_ReturnToLastMonCenter
-	pause 60
-	reloadmappart
-	closetext
-	playsound SFX_WARP_TO
-	applymovement PLAYER, .TeleportFrom
-	farscall Script_AbortBugContest
-	special WarpToSpawnPoint
-	writecode VAR_MOVEMENT, PLAYER_NORMAL
-	newloadmap MAPSETUP_TELEPORT
-	playsound SFX_WARP_FROM
-	applymovement PLAYER, .TeleportTo
-	end
-
-.TeleportFrom: ; cce1
-	teleport_from
-	step_end
-
-.TeleportTo: ; cce3
-	teleport_to
-	step_end
-
-StrengthFunction: ; cce5
-	call .TryStrength
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-.TryStrength: ; ccee
-; Strength
-	ld de, ENGINE_PLAINBADGE
-	call CheckBadge
-	jr c, .Failed
-	jr .UseStrength
-
-.AlreadyUsing: ; unreferenced
-	ld hl, .JumpText
-	call MenuTextBoxBackup
-	ld a, $80
-	ret
-
-.JumpText: ; 0xcd01
-	text_jump UnknownText_0x1c0751
-	db "@"
-
-.Failed: ; cd06
-	ld a, $80
-	ret
-
-.UseStrength: ; cd09
-	ld hl, Script_StrengthFromMenu
-	call QueueScript
-	ld a, $81
-	ret
-
-SetStrengthFlag: ; cd12
-	ld hl, BikeFlags
-	set 0, [hl]
-	ld a, [CurPartyMon]
-	ld e, a
-	ld d, 0
-	ld hl, PartySpecies
-	add hl, de
-	ld a, [hl]
-	ld [Buffer6], a
-	call GetPartyNick
-	ret
-
-Script_StrengthFromMenu: ; 0xcd29
-	reloadmappart
-	special UpdateTimePals
-
-Script_UsedStrength: ; 0xcd2d
-	callasm SetStrengthFlag
-	writetext .UsedStrength
-	copybytetovar Buffer6
-	cry 0
-	pause 3
-	writetext .StrengthAllowedItToMoveBoulders
-	closetext
-	end
-
-.UsedStrength: ; 0xcd41
-	text_jump UnknownText_0x1c0774
-	db "@"
-
-.StrengthAllowedItToMoveBoulders: ; 0xcd46
-	text_jump UnknownText_0x1c0788
-	db "@"
-
-AskStrengthScript:
-	callasm TryStrengthOW
-	iffalse .AskStrength
-	if_equal $1, .DontMeetRequirements
-	jump .AlreadyUsedStrength
-
-.DontMeetRequirements: ; 0xcd59
-	jumptext UnknownText_0xcd73
-
-.AlreadyUsedStrength: ; 0xcd5c
-	jumptext UnknownText_0xcd6e
-
-.AskStrength: ; 0xcd5f
-	opentext
-	writetext UnknownText_0xcd69
-	yesorno
-	iftrue Script_UsedStrength
-	closetext
-	end
-
-UnknownText_0xcd69: ; 0xcd69
-	; A #MON may be able to move this. Want to use STRENGTH?
-	text_jump UnknownText_0x1c07a0
-	db "@"
-
-UnknownText_0xcd6e: ; 0xcd6e
-	; Boulders may now be moved!
-	text_jump UnknownText_0x1c07d8
-	db "@"
-
-UnknownText_0xcd73: ; 0xcd73
-	; A #MON may be able to move this.
-	text_jump UnknownText_0x1c07f4
-	db "@"
-
-TryStrengthOW: ; cd78
-	ld d, STRENGTH
-	call CheckPartyMove
-	jr c, .nope
-
-	ld de, ENGINE_PLAINBADGE
-	call CheckEngineFlag
-	jr c, .nope
-
-	ld hl, BikeFlags
-	bit 0, [hl]
-	jr z, .already_using
-
-	ld a, 2
-	jr .done
-
-.nope
-	ld a, 1
-	jr .done
-
-.already_using
-	xor a
-	jr .done
-
-.done
-	ld [ScriptVar], a
-	ret
-
-WhirlpoolFunction: ; cd9d
-	call ClearBuffer1
-.loop
-	ld hl, Jumptable_cdae
-	call FieldMoveJumptable
-	jr nc, .loop
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-Jumptable_cdae: ; cdae
-	dw .TryWhirlpool
-	dw .DoWhirlpool
-	dw .FailWhirlpool
-
-.TryWhirlpool: ; cdb4
-	ld de, ENGINE_GLACIERBADGE
-	call CheckBadge
-	jr c, .noglacierbadge
-	call TryWhirlpoolMenu
-	jr c, .failed
-	ld a, $1
-	ret
-
-.failed
-	ld a, $2
-	ret
-
-.noglacierbadge
-	ld a, $80
-	ret
-
-.DoWhirlpool: ; cdca
-	ld hl, Script_WhirlpoolFromMenu
-	call QueueScript
-	ld a, $81
-	ret
-
-.FailWhirlpool: ; cdd3
-	call FieldMoveFailed
-	ld a, $80
-	ret
-
-Text_UsedWhirlpool: ; 0xcdd9
-	; used WHIRLPOOL!
-	text_jump UnknownText_0x1c0816
-	db "@"
-
-TryWhirlpoolMenu: ; cdde
-	call GetFacingTileCoord
-	ld c, a
-	push de
-	call CheckWhirlpoolTile
-	pop de
-	jr c, .failed
-	call GetBlockLocation
-	ld c, [hl]
-	push hl
-	ld hl, WhirlpoolBlockPointers
-	call CheckOverworldTileArrays
-	pop hl
-	jr nc, .failed
-	ld a, l
-	ld [Buffer3], a
-	ld a, h
-	ld [Buffer4], a
-	ld a, b
-	ld [Buffer5], a
-	ld a, c
-	ld [Buffer6], a
-	xor a
-	ret
-
-.failed
-	scf
-	ret
-
-Script_WhirlpoolFromMenu: ; 0xce0b
-	reloadmappart
-	special UpdateTimePals
-
-Script_UsedWhirlpool: ; 0xce0f
-	callasm GetPartyNick
-	writetext Text_UsedWhirlpool
-	reloadmappart
-	callasm DisappearWhirlpool
-	closetext
-	end
-
-DisappearWhirlpool: ; ce1d
-	ld hl, Buffer3
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	ld a, [Buffer5]
-	ld [hl], a
-	xor a
-	ld [hBGMapMode], a
-	call OverworldTextModeSwitch
-	ld a, [Buffer6]
-	ld e, a
-	callba PlayWhirlpoolSound
-	call BufferScreen
-	call GetMovementPermissions
-	ret
-
-TryWhirlpoolOW:: ; ce3e
-	ld d, WHIRLPOOL
-	call CheckPartyMove
-	jr c, .failed
-	ld de, ENGINE_GLACIERBADGE
-	call CheckEngineFlag
-	jr c, .failed
-	call TryWhirlpoolMenu
-	jr c, .failed
-	ld a, BANK(Script_AskWhirlpoolOW)
-	ld hl, Script_AskWhirlpoolOW
-	call CallScript
-	scf
-	ret
-
-.failed
-	ld a, BANK(Script_MightyWhirlpool)
-	ld hl, Script_MightyWhirlpool
-	call CallScript
-	scf
-	ret
-
-Script_MightyWhirlpool: ; 0xce66
-	jumptext .MightyWhirlpoolText
-
-.MightyWhirlpoolText: ; 0xce69
-	text_jump UnknownText_0x1c082b
-	db "@"
-
-Script_AskWhirlpoolOW: ; 0xce6e
-	opentext
-	writetext UnknownText_0xce78
-	yesorno
-	iftrue Script_UsedWhirlpool
-	closetext
-	end
-
-UnknownText_0xce78: ; 0xce78
-	text_jump UnknownText_0x1c0864
-	db "@"
-
-HeadbuttFunction: ; ce7d
-	call TryHeadbuttFromMenu
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-TryHeadbuttFromMenu: ; ce86
-	call GetFacingTileCoord
-	call CheckHeadbuttTreeTile
-	jr nz, .no_tree
-
-	ld hl, HeadbuttFromMenuScript
-	call QueueScript
-	ld a, $81
-	ret
-
-.no_tree
-	call FieldMoveFailed
-	ld a, $80
-	ret
-
-UnknownText_0xce9d: ; 0xce9d
-	; did a HEADBUTT!
-	text_jump UnknownText_0x1c0897
-	db "@"
-
-UnknownText_0xcea2: ; 0xcea2
-	; Nope. Nothing…
-	text_jump UnknownText_0x1c08ac
-	db "@"
-
-HeadbuttFromMenuScript: ; 0xcea7
-	reloadmappart
-	special UpdateTimePals
-
-HeadbuttScript: ; 0xceab
-	callasm GetPartyNick
-	writetext UnknownText_0xce9d
-
-	reloadmappart
-	callasm ShakeHeadbuttTree
-
-	callasm TreeMonEncounter
-	iffalse .no_battle
-	closetext
-	randomwildmon
-	startbattle
-	reloadmapafterbattle
-	end
-
-.no_battle
-	writetext UnknownText_0xcea2
-	waitbutton
-	closetext
-	end
-
-TryHeadbuttOW:: ; cec9
-	ld d, HEADBUTT
-	call CheckPartyMove
-	jr c, .no
-
-	ld a, BANK(AskHeadbuttScript)
-	ld hl, AskHeadbuttScript
-	call CallScript
-	scf
-	ret
-
-.no
-	xor a
-	ret
-
-AskHeadbuttScript: ; 0xcedc
-	opentext
-	writetext UnknownText_0xcee6
-	yesorno
-	iftrue HeadbuttScript
-	closetext
-	end
-
-UnknownText_0xcee6: ; 0xcee6
-	; A #MON could be in this tree. Want to HEADBUTT it?
-	text_jump UnknownText_0x1c08bc
-	db "@"
-
-RockSmashFunction: ; ceeb
-	call TryRockSmashFromMenu
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-TryRockSmashFromMenu: ; cef4
-	call GetFacingObject
-	jr c, .no_rock
-	ld a, d
-	cp $18
-	jr nz, .no_rock
-
-	ld hl, RockSmashFromMenuScript
-	call QueueScript
-	ld a, $81
-	ret
-
-.no_rock
-	call FieldMoveFailed
-	ld a, $80
-	ret
-
-GetFacingObject: ; cf0d
-	callba CheckFacingObject
-	jr nc, .fail
-
-	ld a, [hObjectStructIndexBuffer]
-	call GetObjectStruct
-	ld hl, OBJECT_MAP_OBJECT_INDEX
-	add hl, bc
-	ld a, [hl]
-	ld [hLastTalked], a
-	call GetMapObject
-	ld hl, MAPOBJECT_MOVEMENT
-	add hl, bc
-	ld a, [hl]
-	ld d, a
-	and a
-	ret
-
-.fail
-	scf
-	ret
-
-RockSmashFromMenuScript: ; 0xcf2e
-	reloadmappart
-	special UpdateTimePals
-
-RockSmashScript: ; cf32
-	callasm GetPartyNick
-	writetext UnknownText_0xcf58
-	closetext
-	special WaitSFX
-	playsound SFX_STRENGTH
-	earthquake 84
-	applymovement2 MovementData_0xcf55
-	disappear -2
-
-	callasm RockMonEncounter
-	copybytetovar TempWildMonSpecies
-	iffalse .done
-	randomwildmon
-	startbattle
-	reloadmapafterbattle
-.done
-	end
-
-MovementData_0xcf55: ; 0xcf55
-	rock_smash 10
-	step_end
-
-UnknownText_0xcf58: ; 0xcf58
-	text_jump UnknownText_0x1c08f0
-	db "@"
-
-AskRockSmashScript: ; 0xcf5d
-	callasm HasRockSmash
-	if_equal 1, .no
-
-	opentext
-	writetext UnknownText_0xcf77
-	yesorno
-	iftrue RockSmashScript
-	closetext
-	end
-.no
-	jumptext UnknownText_0xcf72
-
-UnknownText_0xcf72: ; 0xcf72
-	; Maybe a #MON can break this.
-	text_jump UnknownText_0x1c0906
-	db "@"
-
-UnknownText_0xcf77: ; 0xcf77
-	; This rock looks breakable. Want to use ROCK SMASH?
-	text_jump UnknownText_0x1c0924
-	db "@"
-
-HasRockSmash: ; cf7c
-	ld d, ROCK_SMASH
-	call CheckPartyMove
-	jr nc, .yes
-.no
-	ld a, 1
-	jr .done
-.yes
-	xor a
-	jr .done
-.done
-	ld [ScriptVar], a
-	ret
-
-FishFunction: ; cf8e
-	ld a, e
-	push af
-	call ClearBuffer1
-	pop af
-	ld [Buffer2], a
-.loop
-	ld hl, .FishTable
-	call FieldMoveJumptable
-	jr nc, .loop
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-.FishTable: ; cfa5
-	dw .TryFish
-	dw .FishNoBite
-	dw .FishGotSomething
-	dw .FailFish
-	dw .FishNoFish
-
-.TryFish: ; cfaf
-	ld a, [PlayerState]
-	cp PLAYER_SURF
-	jr z, .fail
-	cp PLAYER_SURF_PIKA
-	jr z, .fail
-	call GetFacingTileCoord
-	call GetTileCollision
-	cp $1
-	jr z, .facingwater
-.fail
-	ld a, $3
-	ret
-
-.facingwater
-	call GetFishingGroup
-	and a
-	jr nz, .goodtofish
-	ld a, $4
-	ret
-
-.goodtofish
-	ld d, a
-	ld a, [Buffer2]
-	ld e, a
-	callba Fish
-	ld a, d
-	and a
-	jr z, .nonibble
-	ld [TempWildMonSpecies], a
-	ld a, e
-	ld [CurPartyLevel], a
-	ld a, BATTLETYPE_FISH
-	ld [BattleType], a
-	ld a, $2
-	ret
-
-.nonibble
-	ld a, $1
-	ret
-
-.FailFish: ; cff1
-	ld a, $80
-	ret
-
-.FishGotSomething: ; cff4
-	ld a, $1
-	ld [Buffer6], a
-	ld hl, Script_GotABite
-	call QueueScript
-	ld a, $81
-	ret
-
-.FishNoBite: ; d002
-	ld a, $2
-	ld [Buffer6], a
-	ld hl, Script_NotEvenANibble
-	call QueueScript
-	ld a, $81
-	ret
-
-.FishNoFish: ; d010
-	ld a, $0
-	ld [Buffer6], a
-	ld hl, Script_NotEvenANibble2
-	call QueueScript
-	ld a, $81
-	ret
-
-Script_NotEvenANibble: ; 0xd01e
-	scall Script_FishCastRod
-	writetext UnknownText_0xd0a9
-	jump Script_NotEvenANibble_FallThrough
-
-Script_NotEvenANibble2: ; 0xd027
-	scall Script_FishCastRod
-	writetext UnknownText_0xd0a9
-
-Script_NotEvenANibble_FallThrough: ; 0xd02d
-	loademote EMOTE_SHADOW
-	callasm PutTheRodAway
-	closetext
-	end
-
-Script_GotABite: ; 0xd035
-	scall Script_FishCastRod
-	callasm Fishing_CheckFacingUp
-	iffalse .NotFacingUp
-	applymovement PLAYER, .Movement_FacingUp
-	jump .FightTheHookedPokemon
-
-.NotFacingUp: ; 0xd046
-	applymovement PLAYER, .Movement_NotFacingUp
-
-.FightTheHookedPokemon: ; 0xd04a
-	pause 40
-	applymovement PLAYER, .Movement_RestoreRod
-	writetext UnknownText_0xd0a4
-	callasm PutTheRodAway
-	closetext
-	randomwildmon
-	startbattle
-	reloadmapafterbattle
-	end
-
-.Movement_NotFacingUp: ; d05c
-	fish_got_bite
-	fish_got_bite
-	fish_got_bite
-	fish_got_bite
-	show_emote
-	step_end
-
-.Movement_FacingUp: ; d062
-	fish_got_bite
-	fish_got_bite
-	fish_got_bite
-	fish_got_bite
-	step_sleep_1
-	show_emote
-	step_end
-
-.Movement_RestoreRod: ; d069
-	hide_emote
-	fish_cast_rod
-	step_end
-
-Fishing_CheckFacingUp: ; d06c
-	ld a, [PlayerDirection]
-	and $c
-	cp OW_UP
-	ld a, $1
-	jr z, .up
-	xor a
-
-.up
-	ld [ScriptVar], a
-	ret
-
-Script_FishCastRod: ; 0xd07c
-	reloadmappart
-	loadvar hBGMapMode, $0
-	special UpdateTimePals
-	loademote EMOTE_ROD
-	callasm LoadFishingGFX
-	loademote EMOTE_SHOCK
-	applymovement PLAYER, MovementData_0xd093
-	pause 40
-	end
-
-MovementData_0xd093: ; d093
-	fish_cast_rod
-	step_end
-
-PutTheRodAway: ; d095
-	xor a
-	ld [hBGMapMode], a
-	ld a, $1
-	ld [PlayerAction], a
-	call UpdateSprites
-	call ReplaceKrisSprite
-	ret
-
-UnknownText_0xd0a4: ; 0xd0a4
-	; Oh! A bite!
-	text_jump UnknownText_0x1c0958
-	db "@"
-
-UnknownText_0xd0a9: ; 0xd0a9
-	; Not even a nibble!
-	text_jump UnknownText_0x1c0965
-	db "@"
-
-UnknownText_0xd0ae: ; unused
-	; Looks like there's nothing here.
-	text_jump UnknownText_0x1c0979
-	db "@"
-
-BikeFunction: ; d0b3
-	call .TryBike
-	and $7f
-	ld [wFieldMoveSucceeded], a
-	ret
-
-.TryBike: ; d0bc
-	call .CheckEnvironment
-	jr c, .CannotUseBike
-	ld a, [PlayerState]
-	cp PLAYER_NORMAL
-	jr z, .GetOnBike
-	cp PLAYER_BIKE
-	jr z, .GetOffBike
-	jr .CannotUseBike
-
-.GetOnBike
-	ld hl, Script_GetOnBike
-	ld de, Script_GetOnBike_Register
-	call .CheckIfRegistered
-	call QueueScript
-	xor a
-	ld [MusicFade], a
-	ld de, MUSIC_NONE
-	call PlayMusic
-	call DelayFrame
-	call MaxVolume
-	ld de, MUSIC_BICYCLE
-	ld a, e
-	ld [wMapMusic], a
-	call PlayMusic
-	ld a, $1
-	ret
-
-.GetOffBike
-	ld hl, BikeFlags
-	bit 1, [hl]
-	jr nz, .CantGetOffBike
-	ld hl, Script_GetOffBike
-	ld de, Script_GetOffBike_Register
-	call .CheckIfRegistered
-	ld a, BANK(Script_GetOffBike)
-	jr .done
-
-.CantGetOffBike
-	ld hl, Script_CantGetOffBike
-	jr .done
-
-.CannotUseBike
-	ld a, $0
-	ret
-
-.done
-	call QueueScript
-	ld a, $1
-	ret
-
-.CheckIfRegistered: ; d119
-	ld a, [wUsingItemWithSelect]
-	and a
-	ret z
-	ld h, d
-	ld l, e
-	ret
-
-.CheckEnvironment: ; d121
-	call GetMapPermission
-	call CheckOutdoorMap
-	jr z, .ok
-	cp CAVE
-	jr z, .ok
-	cp GATE
-	jr z, .ok
-	jr .nope
-
-.ok
-	call GetPlayerStandingTile
-	and $f ; can't use our bike in a wall or on water
-	jr nz, .nope
-	xor a
-	ret
-
-.nope
-	scf
-	ret
-
-Script_GetOnBike: ; 0xd13e
-	reloadmappart
-	special UpdateTimePals
-	writecode VAR_MOVEMENT, PLAYER_BIKE
-	writetext GotOnTheBikeText
-	waitbutton
-	closetext
-	special ReplaceKrisSprite
-	end
-
-Script_GetOnBike_Register: ; 0xd14e
-	writecode VAR_MOVEMENT, PLAYER_BIKE
-	closetext
-	special ReplaceKrisSprite
-	end
-
-; XXX
-	nop
-	ret
-
-Script_GetOffBike: ; 0xd158
-	reloadmappart
-	special UpdateTimePals
-	writecode VAR_MOVEMENT, PLAYER_NORMAL
-	writetext GotOffTheBikeText
-	waitbutton
-
-FinishGettingOffBike:
-	closetext
-	special ReplaceKrisSprite
-	special PlayMapMusic
-	end
-
-Script_GetOffBike_Register: ; 0xd16b
-	writecode VAR_MOVEMENT, PLAYER_NORMAL
-	jump FinishGettingOffBike
-
-Script_CantGetOffBike: ; 0xd171
-	writetext .CantGetOffBikeText
-	waitbutton
-	closetext
-	end
-
-.CantGetOffBikeText: ; 0xd177
-	; You can't get off here!
-	text_jump UnknownText_0x1c099a
-	db "@"
-
-GotOnTheBikeText: ; 0xd17c
-	; got on the @ .
-	text_jump UnknownText_0x1c09b2
-	db "@"
-
-GotOffTheBikeText: ; 0xd181
-	; got off the @ .
-	text_jump UnknownText_0x1c09c7
-	db "@"
-
-TryCutOW:: ; d186
-	ld d, CUT
-	call CheckPartyMove
-	jr c, .cant_cut
-
-	ld de, ENGINE_HIVEBADGE
-	call CheckEngineFlag
-	jr c, .cant_cut
-
-	ld a, BANK(AskCutScript)
-	ld hl, AskCutScript
-	call CallScript
-	scf
-	ret
-
-.cant_cut
-	ld a, BANK(CantCutScript)
-	ld hl, CantCutScript
-	call CallScript
-	scf
-	ret
-
-AskCutScript: ; 0xd1a9
-	opentext
-	writetext UnknownText_0xd1c8
-	yesorno
-	iffalse .script_d1b8
-	callasm .CheckMap
-	iftrue Script_Cut
-.script_d1b8
-	closetext
-	end
-
-.CheckMap: ; d1ba
-	xor a
-	ld [ScriptVar], a
-	call CheckMapForSomethingToCut
-	ret c
-	ld a, TRUE
-	ld [ScriptVar], a
-	ret
-
-UnknownText_0xd1c8: ; 0xd1c8
-	text_jump UnknownText_0x1c09dd
-	db "@"
-
-CantCutScript: ; 0xd1cd
-	jumptext UnknownText_0xd1d0
-
-UnknownText_0xd1d0: ; 0xd1d0
-	text_jump UnknownText_0x1c0a05
-	db "@"
-
-_ReceiveItem:: ; d1d5
-	call DoesHLEqualNumItems
-	jp nz, PutItemInPocket
-	push hl
-	call CheckItemPocket
-	pop de
-	ld a, [wItemAttributeParamBuffer]
-	dec a
-	ld hl, .Pockets
-	rst JumpTable
-	ret
-
-.Pockets: ; d1e9
-	dw .Item
-	dw .KeyItem
-	dw .Ball
-	dw .TMHM
-
-.Item: ; d1f1
-	ld h, d
-	ld l, e
-	jp PutItemInPocket
-
-.KeyItem: ; d1f6
-	ld h, d
-	ld l, e
-	jp ReceiveKeyItem
-
-.Ball: ; d1fb
-	ld hl, NumBalls
-	jp PutItemInPocket
-
-.TMHM: ; d201
-	ld h, d
-	ld l, e
-	ld a, [CurItem]
-	ld c, a
-	call GetTMHMNumber
-	jp ReceiveTMHM
-
-_TossItem:: ; d20d
-	call DoesHLEqualNumItems
-	jr nz, .remove
-	push hl
-	call CheckItemPocket
-	pop de
-	ld a, [wItemAttributeParamBuffer]
-	dec a
-	ld hl, .Pockets
-	rst JumpTable
-	ret
-
-.Pockets
-	dw .Item
-	dw .KeyItem
-	dw .Ball
-	dw .TMHM
-
-.Ball ; d228
-	ld hl, NumBalls
-	jp RemoveItemFromPocket
-
-.TMHM ; d22e
-	ld h, d
-	ld l, e
-	ld a, [CurItem]
-	ld c, a
-	call GetTMHMNumber
-	jp TossTMHM
-
-.KeyItem ; d23a
-	ld h, d
-	ld l, e
-	jp TossKeyItem
-
-.Item ; d23f
-	ld h, d
-	ld l, e
-
-.remove
-	jp RemoveItemFromPocket
-
-_CheckItem:: ; d244
-	call DoesHLEqualNumItems
-	jr nz, .nope
-	push hl
-	call CheckItemPocket
-	pop de
-	ld a, [wItemAttributeParamBuffer]
-	dec a
-	ld hl, .Pockets
-	rst JumpTable
-	ret
-
-.Pockets
-	dw .Item
-	dw .KeyItem
-	dw .Ball
-	dw .TMHM
-
-.Ball ; d25f
-	ld hl, NumBalls
-	jp CheckTheItem
-
-.TMHM ; d265
-	ld h, d
-	ld l, e
-	ld a, [CurItem]
-	ld c, a
-	call GetTMHMNumber
-	jp CheckTMHM
-
-.KeyItem ; d271
-	ld h, d
-	ld l, e
-	jp CheckKeyItems
-
-.Item ; d276
-	ld h, d
-	ld l, e
-
-.nope
-	jp CheckTheItem
-
-DoesHLEqualNumItems: ; d27b
-	ld a, l
-	cp NumItems % $100
-	ret nz
-	ld a, h
-	cp NumItems / $100
-	ret
-
-GetPocketCapacity: ; d283
-	ld c, MAX_ITEMS
-	ld a, e
-	cp NumItems % $100
-	jr nz, .not_bag
-	ld a, d
-	cp NumItems / $100
-	ret z
-
-.not_bag
-	ld c, MAX_PC_ITEMS
-	ld a, e
-	cp PCItems % $100
-	jr nz, .not_pc
-	ld a, d
-	cp PCItems / $100
-	ret z
-
-.not_pc
-	ld c, MAX_BALLS
-	ret
-
-PutItemInPocket: ; d29c
-	ld d, h
-	ld e, l
-	inc hl
-	ld a, [CurItem]
-	ld c, a
-	ld b, 0
-.loop
-	ld a, [hli]
-	cp -1
-	jr z, .terminator
-	cp c
-	jr nz, .next
-	ld a, 99
-	sub [hl]
-	add b
-	ld b, a
-	ld a, [wItemQuantityChangeBuffer]
-	cp b
-	jr z, .ok
-	jr c, .ok
-
-.next
-	inc hl
-	jr .loop
-
-.terminator
-	call GetPocketCapacity
-	ld a, [de]
-	cp c
-	jr c, .ok
-	and a
-	ret
-
-.ok
-	ld h, d
-	ld l, e
-	ld a, [CurItem]
-	ld c, a
-	ld a, [wItemQuantityChangeBuffer]
-	ld [wItemQuantityBuffer], a
-.loop2
-	inc hl
-	ld a, [hli]
-	cp -1
-	jr z, .terminator2
-	cp c
-	jr nz, .loop2
-	ld a, [wItemQuantityBuffer]
-	add [hl]
-	cp 100
-	jr nc, .newstack
-	ld [hl], a
-	jr .done
-
-.newstack
-	ld [hl], 99
-	sub 99
-	ld [wItemQuantityBuffer], a
-	jr .loop2
-
-.terminator2
-	dec hl
-	ld a, [CurItem]
-	ld [hli], a
-	ld a, [wItemQuantityBuffer]
-	ld [hli], a
-	ld [hl], -1
-	ld h, d
-	ld l, e
-	inc [hl]
-
-.done
-	scf
-	ret
-
-RemoveItemFromPocket: ; d2ff
-	ld d, h
-	ld e, l
-	ld a, [hli]
-	ld c, a
-	ld a, [CurItemQuantity]
-	cp c
-	jr nc, .ok ; memory
-	ld c, a
-	ld b, $0
-	add hl, bc
-	add hl, bc
-	ld a, [CurItem]
-	cp [hl]
-	inc hl
-	jr z, .skip
-	ld h, d
-	ld l, e
-	inc hl
-
-.ok
-	ld a, [CurItem]
-	ld b, a
-.loop
-	ld a, [hli]
-	cp b
-	jr z, .skip
-	cp -1
-	jr z, .nope
-	inc hl
-	jr .loop
-
-.skip
-	ld a, [wItemQuantityChangeBuffer]
-	ld b, a
-	ld a, [hl]
-	sub b
-	jr c, .nope
-	ld [hl], a
-	ld [wItemQuantityBuffer], a
-	and a
-	jr nz, .yup
-	dec hl
-	ld b, h
-	ld c, l
-	inc hl
-	inc hl
-.loop2
-	ld a, [hli]
-	ld [bc], a
-	inc bc
-	cp -1
-	jr nz, .loop2
-	ld h, d
-	ld l, e
-	dec [hl]
-
-.yup
-	scf
-	ret
-
-.nope
-	and a
-	ret
-
-CheckTheItem: ; d349
-	ld a, [CurItem]
-	ld c, a
-.loop
-	inc hl
-	ld a, [hli]
-	cp -1
-	jr z, .done
-	cp c
-	jr nz, .loop
-	scf
-	ret
-
-.done
-	and a
-	ret
-
-ReceiveKeyItem: ; d35a
-	ld hl, NumKeyItems
-	ld a, [hli]
-	cp MAX_KEY_ITEMS
-	jr nc, .nope
-	ld c, a
-	ld b, 0
-	add hl, bc
-	ld a, [CurItem]
-	ld [hli], a
-	ld [hl], -1
-	ld hl, NumKeyItems
-	inc [hl]
-	scf
-	ret
-
-.nope
-	and a
-	ret
-
-TossKeyItem: ; d374
-	ld a, [wd107]
-	ld e, a
-	ld d, 0
-	ld hl, NumKeyItems
-	ld a, [hl]
-	cp e
-	jr nc, .ok
-	call .Toss
-	ret nc
-	jr .ok2
-
-.ok
-	dec [hl]
-	inc hl
-	add hl, de
-
-.ok2
-	ld d, h
-	ld e, l
-	inc hl
-.loop
-	ld a, [hli]
-	ld [de], a
-	inc de
-	cp -1
-	jr nz, .loop
-	scf
-	ret
-
-.Toss: ; d396
-	ld hl, NumKeyItems
-	ld a, [CurItem]
-	ld c, a
-.loop3
-	inc hl
-	ld a, [hl]
-	cp c
-	jr z, .ok3
-	cp -1
-	jr nz, .loop3
-	xor a
-	ret
-
-.ok3
-	ld a, [NumKeyItems]
-	dec a
-	ld [NumKeyItems], a
-	scf
-	ret
-
-CheckKeyItems: ; d3b1
-	ld a, [CurItem]
-	ld c, a
-	ld hl, KeyItems
-.loop
-	ld a, [hli]
-	cp c
-	jr z, .done
-	cp -1
-	jr nz, .loop
-	and a
-	ret
-
-.done
-	scf
-	ret
-
-ReceiveTMHM: ; d3c4
-	dec c
-	ld b, 0
-	ld hl, TMsHMs
-	add hl, bc
-	ld a, [wItemQuantityChangeBuffer]
-	add [hl]
-	cp 100
-	jr nc, .toomany
-	ld [hl], a
-	scf
-	ret
-
-.toomany
-	and a
-	ret
-
-TossTMHM: ; d3d8
-	dec c
-	ld b, 0
-	ld hl, TMsHMs
-	add hl, bc
-	ld a, [wItemQuantityChangeBuffer]
-	ld b, a
-	ld a, [hl]
-	sub b
-	jr c, .nope
-	ld [hl], a
-	ld [wItemQuantityBuffer], a
-	jr nz, .yup
-	ld a, [wTMHMPocketScrollPosition]
-	and a
-	jr z, .yup
-	dec a
-	ld [wTMHMPocketScrollPosition], a
-
-.yup
-	scf
-	ret
-
-.nope
-	and a
-	ret
-
-CheckTMHM: ; d3fb
-	dec c
-	ld b, $0
-	ld hl, TMsHMs
-	add hl, bc
-	ld a, [hl]
-	and a
-	ret z
-	scf
-	ret
-
-GetTMHMNumber:: ; d407
-; Return the number of a TM/HM by item id c.
-
-	ld a, c
-
-; Skip any dummy items.
-	cp ITEM_C3 ; TM04-05
-	jr c, .done
-	cp ITEM_DC ; TM28-29
-	jr c, .skip
-
-	dec a
-.skip
-	dec a
-.done
-	sub TM01
-	inc a
-	ld c, a
-	ret
-
-GetNumberedTMHM: ; d417
-; Return the item id of a TM/HM by number c.
-
-	ld a, c
-
-; Skip any gaps.
-	cp ITEM_C3 - (TM01 - 1)
-	jr c, .done
-	cp ITEM_DC - (TM01 - 1) - 1
-	jr c, .skip_one
-
-.skip_two
-	inc a
-.skip_one
-	inc a
-.done
-	add TM01
-	dec a
-	ld c, a
-	ret
-
-_CheckTossableItem:: ; d427
-; Return 1 in wItemAttributeParamBuffer and carry if CurItem can't be removed from the bag.
-	ld a, ITEMATTR_PERMISSIONS
-	call GetItemAttr
-	bit 7, a
-	jr nz, ItemAttr_ReturnCarry
-	and a
-	ret
-
-CheckSelectableItem: ; d432
-; Return 1 in wItemAttributeParamBuffer and carry if CurItem can't be selected.
-	ld a, ITEMATTR_PERMISSIONS
-	call GetItemAttr
-	bit 6, a
-	jr nz, ItemAttr_ReturnCarry
-	and a
-	ret
-
-CheckItemPocket:: ; d43d
-; Return the pocket for CurItem in wItemAttributeParamBuffer.
-	ld a, ITEMATTR_POCKET
-	call GetItemAttr
-	and $f
-	ld [wItemAttributeParamBuffer], a
-	ret
-
-CheckItemContext: ; d448
-; Return the context for CurItem in wItemAttributeParamBuffer.
-	ld a, ITEMATTR_HELP
-	call GetItemAttr
-	and $f
-	ld [wItemAttributeParamBuffer], a
-	ret
-
-CheckItemMenu: ; d453
-; Return the menu for CurItem in wItemAttributeParamBuffer.
-	ld a, ITEMATTR_HELP
-	call GetItemAttr
-	swap a
-	and $f
-	ld [wItemAttributeParamBuffer], a
-	ret
-
-GetItemAttr: ; d460
-; Get attribute a of CurItem.
-
-	push hl
-	push bc
-
-	ld hl, ItemAttributes
-	ld c, a
-	ld b, 0
-	add hl, bc
-
-	xor a
-	ld [wItemAttributeParamBuffer], a
-
-	ld a, [CurItem]
-	dec a
-	ld c, a
-	ld a, NUM_ITEMATTRS
-	call AddNTimes
-	ld a, BANK(ItemAttributes)
-	call GetFarByte
-
-	pop bc
-	pop hl
-	ret
-
-ItemAttr_ReturnCarry: ; d47f
-	ld a, 1
-	ld [wItemAttributeParamBuffer], a
-	scf
-	ret
-
-GetItemPrice: ; d486
-; Return the price of CurItem in de.
-	push hl
-	push bc
-	ld a, ITEMATTR_PRICE
-	call GetItemAttr
-	ld e, a
-	ld a, ITEMATTR_PRICE_HI
-	call GetItemAttr
-	ld d, a
-	pop bc
-	pop hl
-	ret
-
+INCLUDE "engine/printnum.asm"
+INCLUDE "engine/health.asm"
+INCLUDE "event/overworld.asm"
+INCLUDE "engine/items.asm"
 INCLUDE "engine/player_step.asm"
 INCLUDE "engine/anim_hp_bar.asm"
 INCLUDE "engine/move_mon.asm"
+INCLUDE "engine/billspctop.asm"
 
-_BillsPC: ; e3fd
-	call .CheckCanUsePC
-	ret c
-	call .LogIn
-	call .UseBillsPC
-	jp .LogOut
-
-.CheckCanUsePC: ; e40a (3:640a)
-	ld a, [PartyCount]
-	and a
-	ret nz
-	ld hl, .Text_GottaHavePokemon
-	call MenuTextBoxBackup
-	scf
-	ret
-
-.Text_GottaHavePokemon: ; 0xe417
-	; You gotta have #MON to call!
-	text_jump UnknownText_0x1c1006
-	db "@"
-
-.LogIn: ; e41c (3:641c)
-	xor a
-	ld [hBGMapMode], a
-	call LoadStandardMenuDataHeader
-	call ClearPCItemScreen
-	ld hl, Options
-	ld a, [hl]
-	push af
-	set NO_TEXT_SCROLL, [hl]
-	ld hl, .Text_What
-	call PrintText
-	pop af
-	ld [Options], a
-	call LoadFontsBattleExtra
-	ret
-
-.Text_What: ; 0xe43a
-	; What?
-	text_jump UnknownText_0x1c1024
-	db "@"
-
-.LogOut: ; e43f (3:643f)
-	call CloseSubmenu
-	ret
-
-.UseBillsPC: ; e443 (3:6443)
-	ld hl, .MenuDataHeader
-	call LoadMenuDataHeader
-	ld a, $1
-.loop
-	ld [wMenuCursorBuffer], a
-	call SetPalettes
-	xor a
-	ld [wWhichIndexSet], a
-	ld [hBGMapMode], a
-	call DoNthMenu
-	jr c, .cancel
-	ld a, [wMenuCursorBuffer]
-	push af
-	ld a, [MenuSelection]
-	ld hl, .Jumptable
-	rst JumpTable
-	pop bc
-	ld a, b
-	jr nc, .loop
-.cancel
-	call CloseWindow
-	ret
-
-.MenuDataHeader: ; 0xe46f
-	db $40 ; flags
-	db 00, 00 ; start coords
-	db 17, 19 ; end coords
-	dw .MenuData2
-	db 1 ; default option
-
-.MenuData2: ; 0xe477
-	db $80 ; flags
-	db 0 ; items
-	dw .items
-	dw PlaceMenuStrings
-	dw .strings
-
-.strings: ; e47f
-	db "WITHDRAW <PK><MN>@"
-	db "DEPOSIT <PK><MN>@"
-	db "CHANGE BOX@"
-	db "MOVE <PK><MN> W/O MAIL@"
-	db "SEE YA!@"
-
-.Jumptable: ; e4ba (3:64ba)
-	dw BillsPC_WithdrawMenu
-	dw BillsPC_DepositMenu
-	dw BillsPC_ChangeBoxMenu
-	dw BillsPC_MovePKMNMenu
-	dw BillsPC_SeeYa
-
-.items: ; e4c4
-	db 5
-	db 0 ; WITHDRAW
-	db 1;  DEPOSIT
-	db 2 ; CHANGE BOX
-	db 3 ; MOVE PKMN
-	db 4 ; SEE YA!
-	db -1
-
-BillsPC_SeeYa: ; e4cb
-	scf
-	ret
-
-BillsPC_MovePKMNMenu: ; e4cd
-	call LoadStandardMenuDataHeader
-	callba IsAnyMonHoldingMail
-	jr nc, .no_mail
-	ld hl, .Text_MonHoldingMail
-	call PrintText
-	jr .quit
-
-.no_mail
-	callba StartMovePkmnWOMail_SaveGame
-	jr c, .quit
-	callba _MovePKMNWithoutMail
-	call ReturnToMapFromSubmenu
-	call ClearPCItemScreen
-
-.quit
-	call CloseWindow
-	and a
-	ret
-
-.Text_MonHoldingMail: ; 0xe4f9
-	; There is a #MON holding MAIL. Please remove the MAIL.
-	text_jump UnknownText_0x1c102b
-	db "@"
-
-BillsPC_DepositMenu: ; e4fe (3:64fe)
-	call LoadStandardMenuDataHeader
-	callba _DepositPKMN
-	call ReturnToMapFromSubmenu
-	call ClearPCItemScreen
-	call CloseWindow
-	and a
-	ret
-
-Functione512: ; unused
-	ld a, [PartyCount]
-	and a
-	jr z, .no_pkmn
-	cp 2
-	jr c, .only_one_pkmn
-	and a
-	ret
-
-.no_pkmn
-	ld hl, .Text_NoPKMN
-	call MenuTextBoxBackup
-	scf
-	ret
-
-.only_one_pkmn
-	ld hl, .Text_ItsYourLastPKMN
-	call MenuTextBoxBackup
-	scf
-	ret
-
-.Text_NoPKMN: ; 0xe52e
-	; You don't have a single #MON!
-	text_jump UnknownText_0x1c1062
-	db "@"
-
-.Text_ItsYourLastPKMN: ; 0xe533
-	; You can't deposit your last #MON!
-	text_jump UnknownText_0x1c1080
-	db "@"
-
-CheckCurPartyMonFainted: ; e538
-	ld hl, PartyMon1HP
-	ld de, PARTYMON_STRUCT_LENGTH
-	ld b, $0
-.loop
-	ld a, [CurPartyMon]
-	cp b
-	jr z, .skip
-	ld a, [hli]
-	or [hl]
-	jr nz, .notfainted
-	dec hl
-
-.skip
-	inc b
-	ld a, [PartyCount]
-	cp b
-	jr z, .done
-	add hl, de
-	jr .loop
-
-.done
-	scf
-	ret
-
-.notfainted
-	and a
-	ret
-
-BillsPC_WithdrawMenu: ; e559 (3:6559)
-	call LoadStandardMenuDataHeader
-	callba _WithdrawPKMN
-	call ReturnToMapFromSubmenu
-	call ClearPCItemScreen
-	call CloseWindow
-	and a
-	ret
-
-Functione56d: ; unused
-	ld a, [PartyCount]
-	cp PARTY_LENGTH
-	jr nc, .asm_e576
-	and a
-	ret
-
-.asm_e576
-	ld hl, UnknownText_0xe57e
-	call MenuTextBoxBackup
-	scf
-	ret
-
-UnknownText_0xe57e: ; 0xe57e
-	; You can't take any more #MON.
-	text_jump UnknownText_0x1c10a2
-	db "@"
-
-BillsPC_ChangeBoxMenu: ; e583 (3:6583)
-	callba _ChangeBox
-	and a
-	ret
-
-ClearPCItemScreen: ; e58b
-	call DisableSpriteUpdates
-	xor a
-	ld [hBGMapMode], a
-	call ClearBGPalettes
-	call ClearSprites
-	hlcoord 0, 0
-	ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
-	ld a, " "
-	call ByteFill
-	hlcoord 0,0
-	lb bc, 10, 18
-	call TextBox
-	hlcoord 0,12
-	lb bc, 4, 18
-	call TextBox
-	call WaitBGMap2
-	call SetPalettes ; load regular palettes?
-	ret
-
-CopyBoxmonToTempMon: ; e5bb
-	ld a, [CurPartyMon]
-	ld hl, sBoxMon1Species
-	ld bc, BOXMON_STRUCT_LENGTH
-	call AddNTimes
-	ld de, TempMonSpecies
-	ld bc, BOXMON_STRUCT_LENGTH
-	ld a, BANK(sBoxMon1Species)
-	call GetSRAMBank
-	call CopyBytes
-	call CloseSRAM
-	ret
-
-Functione5d9: ; unreferenced
-	ld a, [wCurBox]
-	cp b
-	jr z, .same_box
-	ld a, b
-	ld hl, .BoxAddrs
-	ld bc, 3
-	call AddNTimes
-	ld a, [hli]
-	push af
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	pop af
-	jr .okay
-
-.same_box
-	ld a, BANK(sBoxCount)
-	ld hl, sBoxCount
-
-.okay
-	call GetSRAMBank
-	ld a, [hl]
-	ld bc, 1 + MONS_PER_BOX + 1
-	add hl, bc
-	ld b, a
-	ld c, $0
-	ld de, wc608
-	ld a, b
-	and a
-	jr z, .empty_box
-.loop
-	push hl
-	push bc
-	ld a, c
-	ld bc, 0
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [hl]
-	ld [de], a
-	inc de
-	ld [CurSpecies], a
-	call GetBaseData
-	pop bc
-	pop hl
-
-	push hl
-	push bc
-	ld a, c
-	ld bc, MONS_PER_BOX * (BOXMON_STRUCT_LENGTH + NAME_LENGTH)
-	add hl, bc
-	call SkipNames
-	call CopyBytes
-	pop bc
-	pop hl
-
-	push hl
-	push bc
-	ld a, c
-	ld bc, MON_LEVEL
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [hl]
-	ld [de], a
-	inc de
-	pop bc
-	pop hl
-
-	push hl
-	push bc
-	ld a, c
-	ld bc, MON_DVS
-	add hl, bc
-	ld bc, BOXMON_STRUCT_LENGTH
-	call AddNTimes
-	ld a, [hli]
-	and $f0
-	ld b, a
-	ld a, [hl]
-	and $f0
-	swap a
-	or b
-	ld b, a
-	ld a, [BaseGender]
-	cp b
-	ld a, $1
-	jr c, .okay2
-	xor a
-.okay2
-	ld [de], a
-	inc de
-	pop bc
-	pop hl
-
-	inc c
-	dec b
-	jr nz, .loop
-.empty_box
-	call CloseSRAM
-	ret
-
-.BoxAddrs: ; e66e
-	dba sBox1
-	dba sBox2
-	dba sBox3
-	dba sBox4
-	dba sBox5
-	dba sBox6
-	dba sBox7
-	dba sBox8
-	dba sBox9
-	dba sBox10
-	dba sBox11
-	dba sBox12
-	dba sBox13
-	dba sBox14
-
 GetBreedMon1LevelGrowth: ; e698
 	ld hl, wBreedMon1Stats
 	ld de, TempMon
@@ -5001,95 +352,6 @@
 	db "@"
 
 INCLUDE "items/item_effects.asm"
-
-GetPokeBallWobble: ; f971 (3:7971)
-; Returns whether a Poke Ball will wobble in the catch animation.
-; Whether a Pokemon is caught is determined beforehand.
-
-	push de
-
-	ld a, [rSVBK]
-	ld d, a
-	push de
-
-	ld a, 1 ; BANK(Buffer2)
-	ld [rSVBK], a
-
-	ld a, [Buffer2]
-	inc a
-	ld [Buffer2], a
-
-; Wobble up to 3 times.
-	cp 3 + 1
-	jr z, .finished
-
-	ld a, [wWildMon]
-	and a
-	ld c, 0 ; next
-	jr nz, .done
-
-	ld hl, .WobbleProbabilities
-	ld a, [Buffer1]
-	ld b, a
-.loop
-	ld a, [hli]
-	cp b
-	jr nc, .checkwobble
-	inc hl
-	jr .loop
-
-.checkwobble
-	ld b, [hl]
-	call Random
-	cp b
-	ld c, 0 ; next
-	jr c, .done
-	ld c, 2 ; escaped
-	jr .done
-
-.finished
-	ld a, [wWildMon]
-	and a
-	ld c, 1 ; caught
-	jr nz, .done
-	ld c, 2 ; escaped
-
-.done
-	pop de
-	ld e, a
-	ld a, d
-	ld [rSVBK], a
-	ld a, e
-	pop de
-	ret
-
-.WobbleProbabilities: ; f9ba
-; catch rate, chance of wobbling / 255
-; nLeft/255 = (nRight/255) ** 4
-	db   1,  63
-	db   2,  75
-	db   3,  84
-	db   4,  90
-	db   5,  95
-	db   7, 103
-	db  10, 113
-	db  15, 126
-	db  20, 134
-	db  30, 149
-	db  40, 160
-	db  50, 169
-	db  60, 177
-	db  80, 191
-	db 100, 201
-	db 120, 211
-	db 140, 220
-	db 160, 227
-	db 180, 234
-	db 200, 240
-	db 220, 246
-	db 240, 251
-	db 254, 253
-	db 255, 255
 
 KnowsMove: ; f9ea
 	ld a, MON_MOVES
--- a/maps/BattleTower1F.asm
+++ b/maps/BattleTower1F.asm
@@ -62,7 +62,7 @@
 	opentext
 	writetext Text_BattleTowerWelcomesYou
 	buttonsound
-	writebyte BATTLETOWERACTION_00 ; if new save file: bit 1, [sbe4f]
+	writebyte BATTLETOWERACTION_00 ; if new save file: bit 1, [s1_be4f]
 	special BattleTowerAction
 	if_not_equal $0, Script_Menu_ChallengeExplanationCancel
 	jump Script_BattleTowerIntroductionYesNo
@@ -87,7 +87,7 @@
 	special Special_TryQuickSave
 	iffalse Script_Menu_ChallengeExplanationCancel
 	dotrigger $1
-	writebyte BATTLETOWERACTION_01 ; set 1, [sbe4f]
+	writebyte BATTLETOWERACTION_01 ; set 1, [s1_be4f]
 	special BattleTowerAction
 	special Function1700b0
 	if_equal $a, Script_Menu_ChallengeExplanationCancel
--- a/misc/battle_tower_5c.asm
+++ b/misc/battle_tower_5c.asm
@@ -1085,9 +1085,9 @@
 	and a
 	ret z
 
-	ld a, BANK(sbe4f)
+	ld a, BANK(s1_be4f)
 	call GetSRAMBank
-	ld a, [sbe4f]
+	ld a, [s1_be4f]
 	and $2
 	ld [ScriptVar], a
 	call CloseSRAM
@@ -1103,11 +1103,11 @@
 	ret
 
 Function170788: ; 170788 (5c:4788) BattleTowerAction $01
-	ld a, BANK(sbe4f)
+	ld a, BANK(s1_be4f)
 	call GetSRAMBank
-	ld a, [sbe4f]
+	ld a, [s1_be4f]
 	or $2
-	ld [sbe4f], a
+	ld [s1_be4f], a
 	call CloseSRAM
 	ret
 
@@ -1591,9 +1591,9 @@
 	and a
 	ret z
 
-	ld a, BANK(sbe4f)
+	ld a, BANK(s1_be4f)
 	call GetSRAMBank
-	ld a, [sbe4f]
+	ld a, [s1_be4f]
 	and $1
 	ld [ScriptVar], a
 	call CloseSRAM
@@ -1600,11 +1600,11 @@
 	ret
 
 Function170ad7: ; 170ad7 (5c:4ad7) BattleTowerAction $15
-	ld a, BANK(sbe4f)
+	ld a, BANK(s1_be4f)
 	call GetSRAMBank
-	ld a, [sbe4f]
+	ld a, [s1_be4f]
 	or $1
-	ld [sbe4f], a
+	ld [s1_be4f], a
 	call CloseSRAM
 	ret
 
--- a/sram.asm
+++ b/sram.asm
@@ -81,7 +81,7 @@
 SECTION "Backup Save", SRAM [$b200], BANK [0]
 sBackupOptions:: ds OptionsEnd - Options
 
-s0_b208:: ds 1
+s0_b208:: ds 1 ; loaded with 99, used to check save corruption
 
 sBackupGameData::
 sBackupPlayerData::  ds wPlayerDataEnd - wPlayerData
@@ -94,11 +94,11 @@
 ; bf0d
 
 sBackupChecksum:: ds 2
-s0_bf0f:: ds 1
+s0_bf0f:: ds 1 ; loaded with 0x7f, used to check save corruption
 sStackTop:: ds 2
 
 
-SECTION "SRAM Bank 1", SRAM, BANK [1]
+SECTION "Save", SRAM, BANK [1]
 
 sOptions:: ds OptionsEnd - Options
 
@@ -117,11 +117,13 @@
 sChecksum::   ds 2
 s1_ad0f::     ds 1 ; loaded with 0x7f, used to check save corruption
 
+SECTION "Active Box", SRAM, BANK [1]
 ; ad10
 	box sBox
 ; b160
 
 	ds $f4
+SECTION "Link Battle Data", SRAM, BANK [1]
 sLinkBattleResults:: ds $c
 
 sLinkBattleStats:: ; b260
@@ -143,6 +145,7 @@
 sLinkBattleRecord5:: link_battle_record sLinkBattleRecord5
 sLinkBattleStatsEnd::
 
+SECTION "SRAM Hall of Fame", SRAM, BANK [1]
 sHallOfFame:: ; b2c0
 ; temporary until I can find a way to macrofy it
 	hall_of_fame sHallOfFame01
@@ -190,6 +193,7 @@
 ; endr
 sHallOfFameEnd::
 
+SECTION "SRAM Crystal Data", SRAM, BANK [1]
 sMobileEventIndex:: ds 1 ; be3c
 
 sCrystalData::
@@ -208,7 +212,7 @@
 ; The 7 trainers of the BattleTower are saved here, so nobody appears more than once
 sBTTrainers:: ; sbe48
 	ds 7
-sbe4f:: ds 1
+s1_be4f:: ds 1
 sBattleTowerReward:: ds 1
 ; Pkmn of previous trainer
 sBTPkmnOfTrainers:: ; 0xbe51