summaryrefslogtreecommitdiff
path: root/engine/overworld
diff options
context:
space:
mode:
authormid-kid <esteve.varela@gmail.com>2018-03-13 13:07:16 +0100
committermid-kid <esteve.varela@gmail.com>2018-03-13 13:21:40 +0100
commitbaa0dc5a963a79843b37888bcfe1d2dfe833ade9 (patch)
tree968c86105bd67a3121d8f3f20018bfc59191f4c9 /engine/overworld
parent12070ca50067d3abe36a730190f88ee43f2cace9 (diff)
Organize the engine/ directory
This is an informed attempt at reorganizing the engine/ directory by creating categorized subdirectories, in order to make it easier to navigate and find things. The directories created are as follows: * engine/game: Contains all "minigames", things like the unown puzzle and slot machine. * engine/gfx: Contains all handling of graphics. From loading palettes to playing animations. * engine/link: Contains all multiplayer functionality. * engine/menu: Contains all generic/misc. menus and menu code. Other, more specialized menus are in their own subdirectories (pokedex, pokegear, party menu, etc). * engine/overworld: Contains all handling of the overworld. From loading and connecting maps to wild encounters and the scripting engine. * engine/pokegear: In the same vein as engine/pokedex, except it could use some more splitting up. * engine/pokemon: Contains everything related to manipulating pokemon data. From the pokemon storage system to evolution and mail. * engine/printer: Contains everything related to printing things as well as the printer communication. * engine/title: Contains intro sequences, title screens and credits.
Diffstat (limited to 'engine/overworld')
-rwxr-xr-xengine/overworld/decorations.asm1303
-rw-r--r--engine/overworld/events.asm1111
-rw-r--r--engine/overworld/events_2.asm650
-rw-r--r--engine/overworld/init_map.asm103
-rw-r--r--engine/overworld/landmarks.asm87
-rwxr-xr-xengine/overworld/map_object_action.asm313
-rw-r--r--engine/overworld/map_objects.asm3123
-rw-r--r--engine/overworld/map_objects_2.asm70
-rw-r--r--engine/overworld/map_setup.asm260
-rw-r--r--engine/overworld/movement.asm864
-rwxr-xr-xengine/overworld/npc_movement.asm573
-rwxr-xr-xengine/overworld/overworld.asm715
-rwxr-xr-xengine/overworld/player_movement.asm851
-rwxr-xr-xengine/overworld/player_object.asm856
-rwxr-xr-xengine/overworld/player_step.asm270
-rw-r--r--engine/overworld/scripting.asm2857
-rwxr-xr-xengine/overworld/select_menu.asm191
-rw-r--r--engine/overworld/spawn_points.asm62
-rwxr-xr-xengine/overworld/tile_events.asm110
-rwxr-xr-xengine/overworld/time.asm465
-rwxr-xr-xengine/overworld/variables.asm151
-rwxr-xr-xengine/overworld/warp_connection.asm439
-rwxr-xr-xengine/overworld/wildmons.asm1000
23 files changed, 16424 insertions, 0 deletions
diff --git a/engine/overworld/decorations.asm b/engine/overworld/decorations.asm
new file mode 100755
index 000000000..33d0ca0cd
--- /dev/null
+++ b/engine/overworld/decorations.asm
@@ -0,0 +1,1303 @@
+InitDecorations: ; 26751 (9:6751)
+ ld a, DECO_FEATHERY_BED
+ ld [wDecoBed], a
+ ld a, DECO_TOWN_MAP
+ ld [wDecoPoster], a
+ ret
+
+_PlayerDecorationMenu: ; 0x2675c
+ ld a, [wWhichIndexSet]
+ push af
+ ld hl, .MenuHeader
+ call LoadMenuHeader
+ xor a
+ ld [wBuffer5], a
+ ld a, $1
+ ld [wBuffer6], a
+.top_loop
+ ld a, [wBuffer6]
+ ld [wMenuCursorBuffer], a
+ call .FindCategoriesWithOwnedDecos
+ call DoNthMenu
+ ld a, [wMenuCursorY]
+ ld [wBuffer6], a
+ jr c, .exit_menu
+ ld a, [wMenuSelection]
+ ld hl, .pointers
+ call MenuJumptable
+ jr nc, .top_loop
+
+.exit_menu
+ call ExitMenu
+ pop af
+ ld [wWhichIndexSet], a
+ ld a, [wBuffer5]
+ ld c, a
+ ret
+; 0x2679a
+
+.MenuHeader: ; 0x2679a
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 5, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+ dw .MenuData
+ db 1 ; default option
+; 0x267a2
+
+.MenuData: ; 0x267a2
+ db STATICMENU_CURSOR | STATICMENU_WRAP ; flags
+ db 0 ; items
+ dw wd002
+ dw PlaceNthMenuStrings
+ dw .pointers
+; 0x267aa
+
+.pointers ; 267aa
+ dw DecoBedMenu, .bed
+ dw DecoCarpetMenu, .carpet
+ dw DecoPlantMenu, .plant
+ dw DecoPosterMenu, .poster
+ dw DecoConsoleMenu, .game
+ dw DecoOrnamentMenu, .ornament
+ dw DecoBigDollMenu, .big_doll
+ dw DecoExitMenu, .exit
+
+.bed db "BED@"
+.carpet db "CARPET@"
+.plant db "PLANT@"
+.poster db "POSTER@"
+.game db "GAME CONSOLE@"
+.ornament db "ORNAMENT@"
+.big_doll db "BIG DOLL@"
+.exit db "EXIT@"
+; 26806
+
+.FindCategoriesWithOwnedDecos: ; 26806
+ xor a
+ ld [wWhichIndexSet], a
+ call .ClearStringBuffer2
+ call .FindOwndDecos
+ ld a, 7
+ call .AppendToStringBuffer2
+ ld hl, wStringBuffer2
+ ld de, wd002
+ ld bc, ITEM_NAME_LENGTH
+ call CopyBytes
+ ret
+
+.ClearStringBuffer2: ; 26822 (9:6822)
+ ld hl, wStringBuffer2
+ xor a
+ ld [hli], a
+ ld bc, ITEM_NAME_LENGTH - 1
+ ld a, -1
+ call ByteFill
+ ret
+
+.AppendToStringBuffer2: ; 26830 (9:6830)
+ ld hl, wStringBuffer2
+ inc [hl]
+ ld e, [hl]
+ ld d, 0
+ add hl, de
+ ld [hl], a
+ ret
+
+.FindOwndDecos: ; 2683a (9:683a)
+ ld hl, .dw
+.loop
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+ ld d, a
+ or e
+ jr z, .done
+ push hl
+ call _de_
+ pop hl
+ jr nc, .next
+ ld a, [hl]
+ push hl
+ call .AppendToStringBuffer2
+ pop hl
+.next
+ inc hl
+ jr .loop
+.done
+ ret
+; 26855 (9:6855)
+
+.dw ; 26855
+ dwb FindOwnedBeds, 0 ; bed
+ dwb FindOwnedCarpets, 1 ; carpet
+ dwb FindOwnedPlants, 2 ; plant
+ dwb FindOwnedPosters, 3 ; poster
+ dwb FindOwnedConsoles, 4 ; game console
+ dwb FindOwnedOrnaments, 5 ; ornament
+ dwb FindOwnedBigDolls, 6 ; big doll
+ dw 0 ; end
+; 2686c
+
+Deco_FillTempWithMinusOne: ; 2686c
+ xor a
+ ld hl, wd002
+ ld [hli], a
+ ld a, -1
+ ld bc, $10
+ call ByteFill
+ ret
+; 2687a
+
+CheckAllDecorationFlags: ; 2687a
+.loop
+ ld a, [hli]
+ cp -1
+ jr z, .done
+ push hl
+ push af
+ ld b, CHECK_FLAG
+ call DecorationFlagAction
+ ld a, c
+ and a
+ pop bc
+ ld a, b
+ call nz, AppendDecoIndex
+ pop hl
+ jr .loop
+
+.done
+ ret
+; 26891
+
+AppendDecoIndex: ; 26891
+ ld hl, wd002
+ inc [hl]
+ ld e, [hl]
+ ld d, $0
+ add hl, de
+ ld [hl], a
+ ret
+; 2689b
+
+FindOwnedDecosInCategory: ; 2689b
+ push bc
+ push hl
+ call Deco_FillTempWithMinusOne
+ pop hl
+ call CheckAllDecorationFlags
+ pop bc
+ ld a, [wd002]
+ and a
+ ret z
+
+ ld a, c
+ call AppendDecoIndex
+ ld a, 0
+ call AppendDecoIndex
+ scf
+ ret
+; 268b5
+
+DecoBedMenu: ; 268b5
+ call FindOwnedBeds
+ call PopulateDecoCategoryMenu
+ xor a
+ ret
+; 268bd
+
+FindOwnedBeds: ; 268bd
+ ld hl, .beds
+ ld c, BEDS
+ jp FindOwnedDecosInCategory
+; 268c5
+
+.beds ; 268c5
+ db DECO_FEATHERY_BED ; 2
+ db DECO_PINK_BED ; 3
+ db DECO_POLKADOT_BED ; 4
+ db DECO_PIKACHU_BED ; 5
+ db -1
+; 268ca
+
+DecoCarpetMenu: ; 268ca
+ call FindOwnedCarpets
+ call PopulateDecoCategoryMenu
+ xor a
+ ret
+; 268d2
+
+FindOwnedCarpets: ; 268d2
+ ld hl, .carpets
+ ld c, CARPETS
+ jp FindOwnedDecosInCategory
+; 268da
+
+.carpets ; 268da
+ db DECO_RED_CARPET ; 7
+ db DECO_BLUE_CARPET ; 8
+ db DECO_YELLOW_CARPET ; 9
+ db DECO_GREEN_CARPET ; a
+ db -1
+; 268df
+
+DecoPlantMenu: ; 268df
+ call FindOwnedPlants
+ call PopulateDecoCategoryMenu
+ xor a
+ ret
+; 268e7
+
+FindOwnedPlants: ; 268e7
+ ld hl, .plants
+ ld c, PLANTS
+ jp FindOwnedDecosInCategory
+; 268ef
+
+.plants ; 268ef
+ db DECO_MAGNAPLANT ; c
+ db DECO_TROPICPLANT ; d
+ db DECO_JUMBOPLANT ; e
+ db -1
+; 268f3
+
+DecoPosterMenu: ; 268f3
+ call FindOwnedPosters
+ call PopulateDecoCategoryMenu
+ xor a
+ ret
+; 268fb
+
+FindOwnedPosters: ; 268fb
+ ld hl, .posters
+ ld c, POSTERS
+ jp FindOwnedDecosInCategory
+; 26903
+
+.posters ; 26903
+ db DECO_TOWN_MAP ; 10
+ db DECO_PIKACHU_POSTER ; 11
+ db DECO_CLEFAIRY_POSTER ; 12
+ db DECO_JIGGLYPUFF_POSTER ; 13
+ db -1
+; 26908
+
+DecoConsoleMenu: ; 26908
+ call FindOwnedConsoles
+ call PopulateDecoCategoryMenu
+ xor a
+ ret
+; 26910
+
+FindOwnedConsoles: ; 26910
+ ld hl, .consoles
+ ld c, CONSOLES
+ jp FindOwnedDecosInCategory
+; 26918
+
+.consoles ; 26918
+ db DECO_FAMICOM ; 15
+ db DECO_SNES ; 16
+ db DECO_N64 ; 17
+ db DECO_VIRTUAL_BOY ; 18
+ db -1
+; 2691d
+
+DecoOrnamentMenu: ; 2691d
+ call FindOwnedOrnaments
+ call PopulateDecoCategoryMenu
+ xor a
+ ret
+; 26925
+
+FindOwnedOrnaments: ; 26925
+ ld hl, .ornaments
+ ld c, DOLLS
+ jp FindOwnedDecosInCategory
+; 2692d
+
+.ornaments ; 2692d
+ db DECO_PIKACHU_DOLL ; 1e
+ db DECO_SURF_PIKACHU_DOLL ; 1f
+ db DECO_CLEFAIRY_DOLL ; 20
+ db DECO_JIGGLYPUFF_DOLL ; 21
+ db DECO_BULBASAUR_DOLL ; 22
+ db DECO_CHARMANDER_DOLL ; 23
+ db DECO_SQUIRTLE_DOLL ; 24
+ db DECO_POLIWAG_DOLL ; 25
+ db DECO_DIGLETT_DOLL ; 26
+ db DECO_STARMIE_DOLL ; 27
+ db DECO_MAGIKARP_DOLL ; 28
+ db DECO_ODDISH_DOLL ; 29
+ db DECO_GENGAR_DOLL ; 2a
+ db DECO_SHELLDER_DOLL ; 2b
+ db DECO_GRIMER_DOLL ; 2c
+ db DECO_VOLTORB_DOLL ; 2d
+ db DECO_WEEDLE_DOLL ; 2e
+ db DECO_UNOWN_DOLL ; 2f
+ db DECO_GEODUDE_DOLL ; 30
+ db DECO_MACHOP_DOLL ; 31
+ db DECO_TENTACOOL_DOLL ; 32
+ db DECO_GOLD_TROPHY_DOLL ; 33
+ db DECO_SILVER_TROPHY_DOLL ; 34
+ db -1
+; 26945
+
+DecoBigDollMenu: ; 26945
+ call FindOwnedBigDolls
+ call PopulateDecoCategoryMenu
+ xor a
+ ret
+; 2694d
+
+FindOwnedBigDolls: ; 2694d
+ ld hl, .big_dolls
+ ld c, BIG_DOLLS
+ jp FindOwnedDecosInCategory
+; 26955
+
+.big_dolls ; 26955
+ db DECO_BIG_SNORLAX_DOLL ; 1a
+ db DECO_BIG_ONIX_DOLL ; 1b
+ db DECO_BIG_LAPRAS_DOLL ; 1c
+ db -1
+; 26959
+
+DecoExitMenu: ; 26959
+ scf
+ ret
+; 2695b
+
+PopulateDecoCategoryMenu: ; 2695b
+ ld a, [wd002]
+ and a
+ jr z, .empty
+ cp 8
+ jr nc, .beyond_eight
+ xor a
+ ld [wWhichIndexSet], a
+ ld hl, .NonscrollingMenuHeader
+ call LoadMenuHeader
+ call DoNthMenu
+ jr c, .no_action_1
+ call DoDecorationAction2
+
+.no_action_1
+ call ExitMenu
+ ret
+
+.beyond_eight
+ ld hl, wd002
+ ld e, [hl]
+ dec [hl]
+ ld d, 0
+ add hl, de
+ ld [hl], -1
+ call LoadStandardMenuHeader
+ ld hl, .ScrollingMenuHeader
+ call CopyMenuHeader
+ xor a
+ ld [hBGMapMode], a
+ call InitScrollingMenu
+ xor a
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuJoypad]
+ cp 2
+ jr z, .no_action_2
+ call DoDecorationAction2
+
+.no_action_2
+ call ExitMenu
+ ret
+
+.empty
+ ld hl, .Text_nothing_to_choose
+ call MenuTextBoxBackup
+ ret
+; 269b0
+
+.Text_nothing_to_choose: ; 0x269b0
+ ; There's nothing to choose.
+ text_jump UnknownText_0x1bc471
+ db "@"
+; 0x269b5
+
+.NonscrollingMenuHeader: ; 0x269b5
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1
+ dw .NonscrollingMenuData
+ db 1 ; default option
+; 0x269bd
+
+.NonscrollingMenuData: ; 0x269bd
+ db STATICMENU_CURSOR | STATICMENU_WRAP ; flags
+ db 0 ; items
+ dw wd002
+ dw DecorationMenuFunction
+ dw DecorationAttributes
+; 0x269c5
+
+.ScrollingMenuHeader: ; 0x269c5
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 1, 1, SCREEN_WIDTH - 2, SCREEN_HEIGHT - 2
+ dw .ScrollingMenuData
+ db 1 ; default option
+; 0x269cd
+
+.ScrollingMenuData: ; 0x269cd
+ db SCROLLINGMENU_DISPLAY_ARROWS ; flags
+ db 8, 0 ; rows, columns
+ db 1 ; horizontal spacing
+ dbw 0, wd002 ; text pointer
+ dba DecorationMenuFunction
+ dbw 0, 0
+ dbw 0, 0
+; 269dd
+
+
+GetDecorationData: ; 269dd
+ ld hl, DecorationAttributes
+ ld bc, 6
+ call AddNTimes
+ ret
+; 269e7
+
+GetDecorationName: ; 269e7
+ push hl
+ call GetDecorationData
+ call GetDecoName
+ pop hl
+ call CopyName2
+ ret
+; 269f3
+
+DecorationMenuFunction: ; 269f3
+ ld a, [wMenuSelection]
+ push de
+ call GetDecorationData
+ call GetDecoName
+ pop hl
+ call PlaceString
+ ret
+; 26a02
+
+DoDecorationAction2: ; 26a02
+ ld a, [wMenuSelection]
+ call GetDecorationData
+ ld de, 2 ; function 2
+ add hl, de
+ ld a, [hl]
+ ld hl, .DecoActions
+ rst JumpTable
+ ret
+; 26a12
+
+.DecoActions: ; 26a12
+ dw DecoAction_nothing
+ dw DecoAction_setupbed
+ dw DecoAction_putawaybed
+ dw DecoAction_setupcarpet
+ dw DecoAction_putawaycarpet
+ dw DecoAction_setupplant
+ dw DecoAction_putawayplant
+ dw DecoAction_setupposter
+ dw DecoAction_putawayposter
+ dw DecoAction_setupconsole
+ dw DecoAction_putawayconsole
+ dw DecoAction_setupbigdoll
+ dw DecoAction_putawaybigdoll
+ dw DecoAction_setupornament
+ dw DecoAction_putawayornament
+; 26a30
+
+
+GetDecorationFlag: ; 26a30
+ call GetDecorationData
+ ld de, 3 ; event flag
+ add hl, de
+ ld a, [hli]
+ ld d, [hl]
+ ld e, a
+ ret
+; 26a3b
+
+DecorationFlagAction: ; 26a3b
+ push bc
+ call GetDecorationFlag
+ pop bc
+ call EventFlagAction
+ ret
+; 26a44
+
+GetDecorationSprite: ; 26a44
+ ld a, c
+ call GetDecorationData
+ ld de, 5 ; sprite
+ add hl, de
+ ld a, [hl]
+ ld c, a
+ ret
+; 26a4f
+
+INCLUDE "data/decorations/attributes.asm"
+
+INCLUDE "data/decorations/names.asm"
+
+GetDecoName: ; 26c72
+ ld a, [hli]
+ ld e, [hl]
+ ld bc, wStringBuffer2
+ push bc
+ ld hl, .NameFunctions
+ rst JumpTable
+ pop de
+ ret
+; 26c7e
+
+.NameFunctions: ; 26c7e
+ dw .invalid
+ dw .plant
+ dw .bed
+ dw .carpet
+ dw .poster
+ dw .doll
+ dw .bigdoll
+; 26c8c
+
+
+.invalid ; 26c8c
+ ret
+; 26c8d
+
+.plant ; 26c8d
+ ld a, e
+ jr .getdeconame
+
+.bed ; 26c90
+ call .plant
+ ld a, _BED
+ jr .getdeconame
+
+.carpet ; 26c97
+ call .plant
+ ld a, _CARPET
+ jr .getdeconame
+
+.poster ; 26c9e
+ ld a, e
+ call .getpokename
+ ld a, _POSTER
+ jr .getdeconame
+
+.doll ; 26ca6
+ ld a, e
+ call .getpokename
+ ld a, _DOLL
+ jr .getdeconame
+
+.bigdoll ; 26cae
+ push de
+ ld a, BIG_
+ call .getdeconame
+ pop de
+ ld a, e
+ jr .getpokename
+
+.unused ; 26cb8
+ push de
+ call .getdeconame
+ pop de
+ ld a, e
+ jr .getdeconame
+
+.getpokename ; 26cc0
+ push bc
+ ld [wd265], a
+ call GetPokemonName
+ pop bc
+ jr .copy
+
+.getdeconame ; 26cca
+ call ._getdeconame
+ jr .copy
+
+._getdeconame ; 26ccf
+ push bc
+ ld hl, DecorationNames
+ call GetNthString
+ ld d, h
+ ld e, l
+ pop bc
+ ret
+
+.copy ; 26cda
+ ld h, b
+ ld l, c
+ call CopyName2
+ dec hl
+ ld b, h
+ ld c, l
+ ret
+; 26ce3
+
+DecoAction_nothing: ; 26ce3
+ scf
+ ret
+; 26ce5
+
+DecoAction_setupbed: ; 26ce5
+ ld hl, wDecoBed
+ jp DecoAction_TrySetItUp
+; 26ceb
+
+DecoAction_putawaybed: ; 26ceb
+ ld hl, wDecoBed
+ jp DecoAction_TryPutItAway
+; 26cf1
+
+DecoAction_setupcarpet: ; 26cf1
+ ld hl, wDecoCarpet
+ jp DecoAction_TrySetItUp
+; 26cf7
+
+DecoAction_putawaycarpet: ; 26cf7
+ ld hl, wDecoCarpet
+ jp DecoAction_TryPutItAway
+; 26cfd
+
+DecoAction_setupplant: ; 26cfd
+ ld hl, wDecoPlant
+ jp DecoAction_TrySetItUp
+; 26d03
+
+DecoAction_putawayplant: ; 26d03
+ ld hl, wDecoPlant
+ jp DecoAction_TryPutItAway
+; 26d09
+
+DecoAction_setupposter: ; 26d09
+ ld hl, wDecoPoster
+ jp DecoAction_TrySetItUp
+; 26d0f
+
+DecoAction_putawayposter: ; 26d0f
+ ld hl, wDecoPoster
+ jp DecoAction_TryPutItAway
+; 26d15
+
+DecoAction_setupconsole: ; 26d15
+ ld hl, wDecoConsole
+ jp DecoAction_TrySetItUp
+; 26d1b
+
+DecoAction_putawayconsole: ; 26d1b
+ ld hl, wDecoConsole
+ jp DecoAction_TryPutItAway
+; 26d21
+
+DecoAction_setupbigdoll: ; 26d21
+ ld hl, wDecoBigDoll
+ jp DecoAction_TrySetItUp
+; 26d27
+
+DecoAction_putawaybigdoll: ; 26d27
+ ld hl, wDecoBigDoll
+ jp DecoAction_TryPutItAway
+; 26d2d
+
+DecoAction_TrySetItUp: ; 26d2d
+ ld a, [hl]
+ ld [wBuffer1], a
+ push hl
+ call DecoAction_SetItUp
+ jr c, .failed
+ ld a, 1
+ ld [wBuffer5], a
+ pop hl
+ ld a, [wMenuSelection]
+ ld [hl], a
+ xor a
+ ret
+
+.failed
+ pop hl
+ xor a
+ ret
+; 26d46
+
+DecoAction_SetItUp: ; 26d46
+; See if there's anything of the same type already out
+ ld a, [wBuffer1]
+ and a
+ jr z, .nothingthere
+; See if that item is already out
+ ld b, a
+ ld a, [wMenuSelection]
+ cp b
+ jr z, .alreadythere
+; Put away the item that's already out, and set up the new one
+ ld a, [wMenuSelection]
+ ld hl, wStringBuffer4
+ call GetDecorationName
+ ld a, [wBuffer1]
+ ld hl, wStringBuffer3
+ call GetDecorationName
+ ld hl, DecoText_PutAwayAndSetUp
+ call MenuTextBoxBackup
+ xor a
+ ret
+
+.nothingthere
+ ld a, [wMenuSelection]
+ ld hl, wStringBuffer3
+ call GetDecorationName
+ ld hl, DecoText_SetUpTheDeco
+ call MenuTextBoxBackup
+ xor a
+ ret
+
+.alreadythere
+ ld hl, DecoText_AlreadySetUp
+ call MenuTextBoxBackup
+ scf
+ ret
+; 26d86
+
+DecoAction_TryPutItAway: ; 26d86
+; If there is no item of that type already set, there is nothing to put away.
+ ld a, [hl]
+ ld [wBuffer1], a
+ xor a
+ ld [hl], a
+ ld a, [wBuffer1]
+ and a
+ jr z, .nothingthere
+; Put it away.
+ ld a, $1
+ ld [wBuffer5], a
+ ld a, [wBuffer1]
+ ld [wMenuSelection], a
+ ld hl, wStringBuffer3
+ call GetDecorationName
+ ld hl, DecoText_PutAwayTheDeco
+ call MenuTextBoxBackup
+ xor a
+ ret
+
+.nothingthere
+ ld hl, DecoText_NothingToPutAway
+ call MenuTextBoxBackup
+ xor a
+ ret
+; 26db3
+
+DecoAction_setupornament: ; 26db3
+ ld hl, UnknownText_0x26e41
+ call DecoAction_AskWhichSide
+ jr c, .cancel
+ call DecoAction_SetItUp_Ornament
+ jr c, .cancel
+ ld a, $1
+ ld [wBuffer5], a
+ jr DecoAction_FinishUp_Ornament
+
+.cancel
+ xor a
+ ret
+
+DecoAction_putawayornament: ; 26dc9
+ ld hl, DecoText_WhichSide
+ call DecoAction_AskWhichSide
+ jr nc, .incave
+ xor a
+ ret
+
+.incave
+ call DecoAction_PutItAway_Ornament
+
+DecoAction_FinishUp_Ornament: ; 26dd6
+ call QueryWhichSide
+ ld a, [wSelectedDecoration]
+ ld [hl], a
+ ld a, [wOtherDecoration]
+ ld [de], a
+ xor a
+ ret
+; 26de3
+
+DecoAction_SetItUp_Ornament: ; 26de3
+ ld a, [wSelectedDecoration]
+ and a
+ jr z, .nothingthere
+ ld b, a
+ ld a, [wMenuSelection]
+ cp b
+ jr z, .failed
+ ld a, b
+ ld hl, wStringBuffer3
+ call GetDecorationName
+ ld a, [wMenuSelection]
+ ld hl, wStringBuffer4
+ call GetDecorationName
+ ld a, [wMenuSelection]
+ ld [wSelectedDecoration], a
+ call .getwhichside
+ ld hl, DecoText_PutAwayAndSetUp
+ call MenuTextBoxBackup
+ xor a
+ ret
+
+.nothingthere
+ ld a, [wMenuSelection]
+ ld [wSelectedDecoration], a
+ call .getwhichside
+ ld a, [wMenuSelection]
+ ld hl, wStringBuffer3
+ call GetDecorationName
+ ld hl, DecoText_SetUpTheDeco
+ call MenuTextBoxBackup
+ xor a
+ ret
+
+.failed
+ ld hl, DecoText_AlreadySetUp
+ call MenuTextBoxBackup
+ scf
+ ret
+; 26e33
+
+.getwhichside ; 26e33
+ ld a, [wMenuSelection]
+ ld b, a
+ ld a, [wOtherDecoration]
+ cp b
+ ret nz
+ xor a
+ ld [wOtherDecoration], a
+ ret
+; 26e41
+
+UnknownText_0x26e41: ; 0x26e41
+ ; Which side do you want to put it on?
+ text_jump UnknownText_0x1bc48c
+ db "@"
+; 0x26e46
+
+DecoAction_PutItAway_Ornament: ; 26e46
+ ld a, [wSelectedDecoration]
+ and a
+ jr z, .nothingthere
+ ld hl, wStringBuffer3
+ call GetDecorationName
+ ld a, $1
+ ld [wBuffer5], a
+ xor a
+ ld [wSelectedDecoration], a
+ ld hl, DecoText_PutAwayTheDeco
+ call MenuTextBoxBackup
+ xor a
+ ret
+
+.nothingthere
+ ld hl, DecoText_NothingToPutAway
+ call MenuTextBoxBackup
+ xor a
+ ret
+; 26e6b
+
+DecoText_WhichSide: ; 0x26e6b
+ ; Which side do you want to put away?
+ text_jump UnknownText_0x1bc4b2
+ db "@"
+; 0x26e70
+
+DecoAction_AskWhichSide: ; 26e70
+ call MenuTextBox
+ ld hl, MenuHeader_0x26eab
+ call GetMenu2
+ call ExitMenu
+ call CopyMenuData
+ jr c, .nope
+ ld a, [wMenuCursorY]
+ cp 3
+ jr z, .nope
+ ld [wBuffer2], a
+ call QueryWhichSide
+ ld a, [hl]
+ ld [wSelectedDecoration], a
+ ld a, [de]
+ ld [wOtherDecoration], a
+ xor a
+ ret
+
+.nope
+ scf
+ ret
+; 26e9a
+
+QueryWhichSide: ; 26e9a
+ ld hl, wDecoRightOrnament
+ ld de, wDecoLeftOrnament
+ ld a, [wBuffer2]
+ cp 1
+ ret z
+ push hl
+ ld h, d
+ ld l, e
+ pop de
+ ret
+; 26eab
+
+MenuHeader_0x26eab: ; 0x26eab
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 0, 0, 13, 7
+ dw MenuData_0x26eb3
+ db 1 ; default option
+; 0x26eb3
+
+MenuData_0x26eb3: ; 0x26eb3
+ db STATICMENU_CURSOR ; flags
+ db 3 ; items
+ db "RIGHT SIDE@"
+ db "LEFT SIDE@"
+ db "CANCEL@"
+; 0x26ed1
+
+DecoText_PutAwayTheDeco: ; 0x26ed1
+ ; Put away the @ .
+ text_jump UnknownText_0x1bc4d7
+ db "@"
+; 0x26ed6
+
+DecoText_NothingToPutAway: ; 0x26ed6
+ ; There's nothing to put away.
+ text_jump UnknownText_0x1bc4ec
+ db "@"
+; 0x26edb
+
+DecoText_SetUpTheDeco: ; 0x26edb
+ ; Set up the @ .
+ text_jump UnknownText_0x1bc509
+ db "@"
+; 0x26ee0
+
+DecoText_PutAwayAndSetUp: ; 0x26ee0
+ ; Put away the @ and set up the @ .
+ text_jump UnknownText_0x1bc51c
+ db "@"
+; 0x26ee5
+
+DecoText_AlreadySetUp: ; 0x26ee5
+ ; That's already set up.
+ text_jump UnknownText_0x1bc546
+ db "@"
+; 0x26eea
+
+GetDecorationName_c_de: ; 26eea
+ ld a, c
+ ld h, d
+ ld l, e
+ call GetDecorationName
+ ret
+; 26ef1
+
+DecorationFlagAction_c: ; 26ef1
+ ld a, c
+ jp DecorationFlagAction
+; 26ef5
+
+
+GetDecorationName_c: ; 26ef5 (9:6ef5)
+ ld a, c
+ call GetDecorationID
+ ld hl, wStringBuffer1
+ push hl
+ call GetDecorationName
+ pop de
+ ret
+
+
+SetSpecificDecorationFlag: ; 26f02
+ ld a, c
+ call GetDecorationID
+ ld b, SET_FLAG
+ call DecorationFlagAction
+ ret
+; 26f0c
+
+GetDecorationID: ; 26f0c
+ push hl
+ push de
+ ld e, a
+ ld d, 0
+ ld hl, DecorationIDs
+ add hl, de
+ ld a, [hl]
+ pop de
+ pop hl
+ ret
+; 26f19
+
+SetAllDecorationFlags: ; 26f19
+ ld hl, DecorationIDs
+.loop
+ ld a, [hli]
+ cp -1
+ jr z, .done
+ push hl
+ ld b, SET_FLAG
+ call DecorationFlagAction
+ pop hl
+ jr .loop
+
+.done
+ ret
+; 26f2b
+
+INCLUDE "data/decorations/decorations.asm"
+
+DescribeDecoration:: ; 26f59
+ ld a, b
+ ld hl, .JumpTable
+ rst JumpTable
+ ret
+; 26f5f
+
+.JumpTable: ; 26f5f
+; entries correspond to DECODESC_* constants
+ dw DecorationDesc_Poster
+ dw DecorationDesc_LeftOrnament
+ dw DecorationDesc_RightOrnament
+ dw DecorationDesc_GiantOrnament
+ dw DecorationDesc_Console
+; 26f69
+
+DecorationDesc_Poster: ; 26f69
+ ld a, [wDecoPoster]
+ ld hl, DecorationDesc_PosterPointers
+ ld de, 3
+ call IsInArray
+ jr c, .nope
+ ld de, DecorationDesc_NullPoster
+ ld b, BANK(DecorationDesc_NullPoster)
+ ret
+
+.nope
+ ld b, BANK(DecorationDesc_TownMapPoster)
+ inc hl
+ ld a, [hli]
+ ld d, [hl]
+ ld e, a
+ ret
+; 26f84
+
+DecorationDesc_PosterPointers: ; 26f84
+ dbw DECO_TOWN_MAP, DecorationDesc_TownMapPoster
+ dbw DECO_PIKACHU_POSTER, DecorationDesc_PikachuPoster
+ dbw DECO_CLEFAIRY_POSTER, DecorationDesc_ClefairyPoster
+ dbw DECO_JIGGLYPUFF_POSTER, DecorationDesc_JigglypuffPoster
+ db -1
+; 26f91
+
+DecorationDesc_TownMapPoster: ; 0x26f91
+ opentext
+ writetext .TownMapText
+ waitbutton
+ special OverworldTownMap
+ closetext
+ end
+; 0x26f9b
+
+.TownMapText: ; 0x26f9b
+ ; It's the TOWN MAP.
+ text_jump UnknownText_0x1bc55d
+ db "@"
+; 0x26fa0
+
+DecorationDesc_PikachuPoster: ; 0x26fa0
+ jumptext .PikaPosterText
+; 0x26fa3
+
+.PikaPosterText: ; 0x26fa3
+ ; It's a poster of a cute PIKACHU.
+ text_jump UnknownText_0x1bc570
+ db "@"
+; 0x26fa8
+
+DecorationDesc_ClefairyPoster: ; 0x26fa8
+ jumptext .ClefairyPosterText
+; 0x26fab
+
+.ClefairyPosterText: ; 0x26fab
+ ; It's a poster of a cute CLEFAIRY.
+ text_jump UnknownText_0x1bc591
+ db "@"
+; 0x26fb0
+
+DecorationDesc_JigglypuffPoster: ; 0x26fb0
+ jumptext .JigglypuffPosterText
+; 0x26fb3
+
+.JigglypuffPosterText: ; 0x26fb3
+ ; It's a poster of a cute JIGGLYPUFF.
+ text_jump UnknownText_0x1bc5b3
+ db "@"
+; 0x26fb8
+
+DecorationDesc_NullPoster: ; 26fb8
+ end
+; 26fb9
+
+DecorationDesc_LeftOrnament: ; 26fb9
+ ld a, [wDecoLeftOrnament]
+ jr DecorationDesc_OrnamentOrConsole
+
+DecorationDesc_RightOrnament: ; 26fbe
+ ld a, [wDecoRightOrnament]
+ jr DecorationDesc_OrnamentOrConsole
+
+DecorationDesc_Console: ; 26fc3
+ ld a, [wDecoConsole]
+ jr DecorationDesc_OrnamentOrConsole
+
+DecorationDesc_OrnamentOrConsole: ; 26fc8
+ ld c, a
+ ld de, wStringBuffer3
+ call GetDecorationName_c_de
+ ld b, BANK(.OrnamentConsoleScript)
+ ld de, .OrnamentConsoleScript
+ ret
+; 26fd5
+
+.OrnamentConsoleScript: ; 26fd5
+ jumptext .OrnamentConsoleText
+; 26fd8
+
+.OrnamentConsoleText: ; 0x26fd8
+ ; It's an adorable @ .
+ text_jump UnknownText_0x1bc5d7
+ db "@"
+; 0x26fdd
+
+DecorationDesc_GiantOrnament: ; 26fdd
+ ld b, BANK(.BigDollScript)
+ ld de, .BigDollScript
+ ret
+; 26fe3
+
+.BigDollScript: ; 26fe3
+ jumptext .BigDollText
+; 26fe6
+
+.BigDollText: ; 0x26fe6
+ ; A giant doll! It's fluffy and cuddly.
+ text_jump UnknownText_0x1bc5ef
+ db "@"
+; 0x26feb
+
+ToggleMaptileDecorations: ; 26feb
+ lb de, 0, 4
+ ld a, [wDecoBed]
+ call SetDecorationTile
+ lb de, 7, 4
+ ld a, [wDecoPlant]
+ call SetDecorationTile
+ lb de, 6, 0
+ ld a, [wDecoPoster]
+ call SetDecorationTile
+ call SetPosterVisibility
+ lb de, 0, 0
+ call PadCoords_de
+ ld a, [wDecoCarpet]
+ and a
+ ret z
+ call _GetDecorationSprite
+ ld [hl], a
+ push af
+ lb de, 0, 2
+ call PadCoords_de
+ pop af
+ inc a
+ ld [hli], a
+ inc a
+ ld [hli], a
+ dec a
+ ld [hl], a
+ ret
+; 27027
+
+SetPosterVisibility: ; 27027
+ ld b, SET_FLAG
+ ld a, [wDecoPoster]
+ and a
+ jr nz, .ok
+ ld b, RESET_FLAG
+
+.ok
+ ld de, EVENT_PLAYERS_ROOM_POSTER
+ jp EventFlagAction
+; 27037
+
+SetDecorationTile: ; 27037
+ push af
+ call PadCoords_de
+ pop af
+ and a
+ ret z
+ call _GetDecorationSprite
+ ld [hl], a
+ ret
+; 27043
+
+ToggleDecorationsVisibility: ; 27043
+ ld de, EVENT_PLAYERS_HOUSE_2F_CONSOLE
+ ld hl, wVariableSprites + SPRITE_CONSOLE - SPRITE_VARS
+ ld a, [wDecoConsole]
+ call ToggleDecorationVisibility
+ ld de, EVENT_PLAYERS_HOUSE_2F_DOLL_1
+ ld hl, wVariableSprites + SPRITE_DOLL_1 - SPRITE_VARS
+ ld a, [wDecoLeftOrnament]
+ call ToggleDecorationVisibility
+ ld de, EVENT_PLAYERS_HOUSE_2F_DOLL_2
+ ld hl, wVariableSprites + SPRITE_DOLL_2 - SPRITE_VARS
+ ld a, [wDecoRightOrnament]
+ call ToggleDecorationVisibility
+ ld de, EVENT_PLAYERS_HOUSE_2F_BIG_DOLL
+ ld hl, wVariableSprites + SPRITE_BIG_DOLL - SPRITE_VARS
+ ld a, [wDecoBigDoll]
+ call ToggleDecorationVisibility
+ ret
+; 27074
+
+ToggleDecorationVisibility: ; 27074
+ and a
+ jr z, .hide
+ call _GetDecorationSprite
+ ld [hl], a
+ ld b, RESET_FLAG
+ jp EventFlagAction
+
+.hide
+ ld b, SET_FLAG
+ jp EventFlagAction
+; 27085
+
+_GetDecorationSprite: ; 27085
+ ld c, a
+ push de
+ push hl
+ farcall GetDecorationSprite
+ pop hl
+ pop de
+ ld a, c
+ ret
+; 27092
+
+PadCoords_de: ; 27092
+ ld a, d
+ add 4
+ ld d, a
+ ld a, e
+ add 4
+ ld e, a
+ call GetBlockLocation
+ ret
diff --git a/engine/overworld/events.asm b/engine/overworld/events.asm
new file mode 100644
index 000000000..cc2c8c574
--- /dev/null
+++ b/engine/overworld/events.asm
@@ -0,0 +1,1111 @@
+INCLUDE "constants.asm"
+
+
+SECTION "Events", ROMX
+
+OverworldLoop:: ; 966b0
+ xor a
+ ld [wMapStatus], a
+.loop
+ ld a, [wMapStatus]
+ ld hl, .jumps
+ rst JumpTable
+ ld a, [wMapStatus]
+ cp 3 ; done
+ jr nz, .loop
+.done
+ ret
+
+.jumps
+ dw StartMap
+ dw EnterMap
+ dw HandleMap
+ dw .done
+; 966cb
+
+DisableEvents: ; 966cb
+ xor a
+ ld [wScriptFlags3], a
+ ret
+; 966d0
+
+EnableEvents:: ; 966d0
+ ld a, $ff
+ ld [wScriptFlags3], a
+ ret
+; 966d6
+
+CheckBit5_ScriptFlags3: ; 966d6
+ ld hl, wScriptFlags3
+ bit 5, [hl]
+ ret
+; 966dc
+
+DisableWarpsConnxns: ; 966dc
+ ld hl, wScriptFlags3
+ res 2, [hl]
+ ret
+; 966e2
+
+DisableCoordEvents: ; 966e2
+ ld hl, wScriptFlags3
+ res 1, [hl]
+ ret
+; 966e8
+
+DisableStepCount: ; 966e8
+ ld hl, wScriptFlags3
+ res 0, [hl]
+ ret
+; 966ee
+
+DisableWildEncounters: ; 966ee
+ ld hl, wScriptFlags3
+ res 4, [hl]
+ ret
+; 966f4
+
+EnableWarpsConnxns: ; 966f4
+ ld hl, wScriptFlags3
+ set 2, [hl]
+ ret
+; 966fa
+
+EnableCoordEvents: ; 966fa
+ ld hl, wScriptFlags3
+ set 1, [hl]
+ ret
+; 96700
+
+EnableStepCount: ; 96700
+ ld hl, wScriptFlags3
+ set 0, [hl]
+ ret
+; 96706
+
+EnableWildEncounters: ; 96706
+ ld hl, wScriptFlags3
+ set 4, [hl]
+ ret
+; 9670c
+
+CheckWarpConnxnScriptFlag: ; 9670c
+ ld hl, wScriptFlags3
+ bit 2, [hl]
+ ret
+; 96712
+
+CheckCoordEventScriptFlag: ; 96712
+ ld hl, wScriptFlags3
+ bit 1, [hl]
+ ret
+; 96718
+
+CheckStepCountScriptFlag: ; 96718
+ ld hl, wScriptFlags3
+ bit 0, [hl]
+ ret
+; 9671e
+
+CheckWildEncountersScriptFlag: ; 9671e
+ ld hl, wScriptFlags3
+ bit 4, [hl]
+ ret
+; 96724
+
+StartMap: ; 96724
+ xor a
+ ld [wScriptVar], a
+ xor a
+ ld [wScriptRunning], a
+ ld hl, wMapStatus
+ ld bc, wMapStatusEnd - wMapStatus
+ call ByteFill
+ farcall InitCallReceiveDelay
+ call ClearJoypad
+EnterMap: ; 9673e
+ xor a
+ ld [wXYComparePointer], a
+ ld [wXYComparePointer + 1], a
+ call SetUpFiveStepWildEncounterCooldown
+ farcall RunMapSetupScript
+ call DisableEvents
+
+ ld a, [hMapEntryMethod]
+ cp MAPSETUP_CONNECTION
+ jr nz, .dont_enable
+ call EnableEvents
+.dont_enable
+
+ ld a, [hMapEntryMethod]
+ cp MAPSETUP_RELOADMAP
+ jr nz, .dontresetpoison
+ xor a
+ ld [wPoisonStepCount], a
+.dontresetpoison
+
+ xor a ; end map entry
+ ld [hMapEntryMethod], a
+ ld a, 2 ; HandleMap
+ ld [wMapStatus], a
+ ret
+; 9676d
+
+UnusedWait30Frames: ; 9676d
+ ld c, 30
+ call DelayFrames
+ ret
+; 96773
+
+HandleMap: ; 96773
+ call ResetOverworldDelay
+ call HandleMapTimeAndJoypad
+ farcall HandleCmdQueue ; no need to farcall
+ call MapEvents
+
+; Not immediately entering a connected map will cause problems.
+ ld a, [wMapStatus]
+ cp 2 ; HandleMap
+ ret nz
+
+ call HandleMapObjects
+ call NextOverworldFrame
+ call HandleMapBackground
+ call CheckPlayerState
+ ret
+; 96795
+
+MapEvents: ; 96795
+ ld a, [wMapEventStatus]
+ ld hl, .jumps
+ rst JumpTable
+ ret
+
+.jumps
+ dw .events
+ dw .no_events
+; 967a1
+
+.events ; 967a1
+ call PlayerEvents
+ call DisableEvents
+ farcall ScriptEvents
+ ret
+; 967ae
+
+.no_events ; 967ae
+ ret
+; 967af
+
+MaxOverworldDelay: ; 967af
+ db 2
+; 967b0
+
+ResetOverworldDelay: ; 967b0
+ ld a, [MaxOverworldDelay]
+ ld [wOverworldDelay], a
+ ret
+; 967b7
+
+NextOverworldFrame: ; 967b7
+ ld a, [wOverworldDelay]
+ and a
+ ret z
+ ld c, a
+ call DelayFrames
+ ret
+; 967c1
+
+HandleMapTimeAndJoypad: ; 967c1
+ ld a, [wMapEventStatus]
+ cp 1 ; no events
+ ret z
+
+ call UpdateTime
+ call GetJoypad
+ call TimeOfDayPals
+ ret
+; 967d1
+
+HandleMapObjects: ; 967d1
+ farcall HandleNPCStep ; engine/map_objects.asm
+ farcall _HandlePlayerStep
+ call _CheckObjectEnteringVisibleRange
+ ret
+; 967e1
+
+HandleMapBackground: ; 967e1
+ farcall _UpdateSprites
+ farcall ScrollScreen
+ farcall PlaceMapNameSign
+ ret
+; 967f4
+
+CheckPlayerState: ; 967f4
+ ld a, [wPlayerStepFlags]
+ bit 5, a ; in the middle of step
+ jr z, .events
+ bit 6, a ; stopping step
+ jr z, .noevents
+ bit 4, a ; in midair
+ jr nz, .noevents
+ call EnableEvents
+.events
+ ld a, 0 ; events
+ ld [wMapEventStatus], a
+ ret
+
+.noevents
+ ld a, 1 ; no events
+ ld [wMapEventStatus], a
+ ret
+; 96812
+
+_CheckObjectEnteringVisibleRange: ; 96812
+ ld hl, wPlayerStepFlags
+ bit 6, [hl]
+ ret z
+ farcall CheckObjectEnteringVisibleRange
+ ret
+; 9681f
+
+PlayerEvents: ; 9681f
+ xor a
+; If there's already a player event, don't interrupt it.
+ ld a, [wScriptRunning]
+ and a
+ ret nz
+
+ call Dummy_CheckScriptFlags3Bit5 ; This is a waste of time
+
+ call CheckTrainerBattle3
+ jr c, .ok
+
+ call CheckTileEvent
+ jr c, .ok
+
+ call RunMemScript
+ jr c, .ok
+
+ call RunSceneScript
+ jr c, .ok
+
+ call CheckTimeEvents
+ jr c, .ok
+
+ call OWPlayerInput
+ jr c, .ok
+
+ xor a
+ ret
+
+.ok
+ push af
+ farcall EnableScriptMode
+ pop af
+
+ ld [wScriptRunning], a
+ call DoPlayerEvent
+ ld a, [wScriptRunning]
+ cp PLAYEREVENT_CONNECTION
+ jr z, .ok2
+ cp PLAYEREVENT_JOYCHANGEFACING
+ jr z, .ok2
+
+ xor a
+ ld [wLandmarkSignTimer], a
+
+.ok2
+ scf
+ ret
+; 96867
+
+CheckTrainerBattle3: ; 96867
+ nop
+ nop
+ call CheckTrainerBattle2
+ jr nc, .nope
+
+ ld a, PLAYEREVENT_SEENBYTRAINER
+ scf
+ ret
+
+.nope
+ xor a
+ ret
+; 96874
+
+CheckTileEvent: ; 96874
+; Check for warps, coord events, or wild battles.
+
+ call CheckWarpConnxnScriptFlag
+ jr z, .connections_disabled
+
+ farcall CheckMovingOffEdgeOfMap
+ jr c, .map_connection
+
+ call CheckWarpTile
+ jr c, .warp_tile
+
+.connections_disabled
+ call CheckCoordEventScriptFlag
+ jr z, .coord_events_disabled
+
+ call CheckCurrentMapCoordEvents
+ jr c, .coord_event
+
+.coord_events_disabled
+ call CheckStepCountScriptFlag
+ jr z, .step_count_disabled
+
+ call CountStep
+ ret c
+
+.step_count_disabled
+ call CheckWildEncountersScriptFlag
+ jr z, .ok
+
+ call RandomEncounter
+ ret c
+ jr .ok ; pointless
+
+.ok
+ xor a
+ ret
+
+.map_connection
+ ld a, PLAYEREVENT_CONNECTION
+ scf
+ ret
+
+.warp_tile
+ ld a, [wPlayerStandingTile]
+ call CheckPitTile
+ jr nz, .not_pit
+ ld a, PLAYEREVENT_FALL
+ scf
+ ret
+
+.not_pit
+ ld a, PLAYEREVENT_WARP
+ scf
+ ret
+
+.coord_event
+ ld hl, wCurCoordEventScriptAddr
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call GetMapScriptsBank
+ call CallScript
+ ret
+; 968c7
+
+CheckWildEncounterCooldown:: ; 968c7
+ ld hl, wWildEncounterCooldown
+ ld a, [hl]
+ and a
+ ret z
+ dec [hl]
+ ret z
+ scf
+ ret
+; 968d1
+
+SetUpFiveStepWildEncounterCooldown: ; 968d1
+ ld a, 5
+ ld [wWildEncounterCooldown], a
+ ret
+; 968d7
+
+ret_968d7: ; 968d7
+ ret
+;968d8
+
+SetMinTwoStepWildEncounterCooldown: ; 968d8
+ ld a, [wWildEncounterCooldown]
+ cp 2
+ ret nc
+ ld a, 2
+ ld [wWildEncounterCooldown], a
+ ret
+; 968e4
+
+Dummy_CheckScriptFlags3Bit5: ; 968e4
+ call CheckBit5_ScriptFlags3
+ ret z
+ call ret_2f3e
+ ret
+; 968ec
+
+RunSceneScript: ; 968ec
+ ld a, [wCurrMapSceneScriptCount]
+ and a
+ jr z, .nope
+
+ ld c, a
+ call CheckScenes
+ cp c
+ jr nc, .nope
+
+ ld e, a
+ ld d, 0
+ ld hl, wCurrMapSceneScriptsPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+rept 4
+ add hl, de
+endr
+
+ call GetMapScriptsBank
+ call GetFarHalfword
+ call GetMapScriptsBank
+ call CallScript
+
+ ld hl, wScriptFlags
+ res 3, [hl]
+
+ farcall EnableScriptMode
+ farcall ScriptEvents
+
+ ld hl, wScriptFlags
+ bit 3, [hl]
+ jr z, .nope
+
+ ld hl, wPriorityScriptAddr
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wPriorityScriptBank]
+ call CallScript
+ scf
+ ret
+
+.nope
+ xor a
+ ret
+; 9693a
+
+CheckTimeEvents: ; 9693a
+ ld a, [wLinkMode]
+ and a
+ jr nz, .nothing
+
+ ld hl, wStatusFlags2
+ bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
+ jr z, .do_daily
+
+ farcall CheckBugContestTimer
+ jr c, .end_bug_contest
+ xor a
+ ret
+
+.do_daily
+ farcall CheckDailyResetTimer
+ farcall CheckPokerusTick
+ farcall CheckPhoneCall
+ ret c
+
+.nothing
+ xor a
+ ret
+
+.end_bug_contest
+ ld a, BANK(BugCatchingContestOverScript)
+ ld hl, BugCatchingContestOverScript
+ call CallScript
+ scf
+ ret
+; 96970
+
+.unused ; 96970
+ ld a, 8
+ scf
+ ret
+; 96974
+
+OWPlayerInput: ; 96974
+
+ call PlayerMovement
+ ret c
+ and a
+ jr nz, .NoAction
+
+; Can't perform button actions while sliding on ice.
+ farcall CheckStandingOnIce
+ jr c, .NoAction
+
+ call CheckAPressOW
+ jr c, .Action
+
+ call CheckMenuOW
+ jr c, .Action
+
+.NoAction:
+ xor a
+ ret
+
+.Action:
+ push af
+ farcall StopPlayerForEvent
+ pop af
+ scf
+ ret
+; 96999
+
+CheckAPressOW: ; 96999
+ ld a, [hJoyPressed]
+ and A_BUTTON
+ ret z
+ call TryObjectEvent
+ ret c
+ call TryBGEvent
+ ret c
+ call TryTileCollisionEvent
+ ret c
+ xor a
+ ret
+; 969ac
+
+PlayTalkObject: ; 969ac
+ push de
+ ld de, SFX_READ_TEXT_2
+ call PlaySFX
+ pop de
+ ret
+; 969b5
+
+TryObjectEvent: ; 969b5
+ farcall CheckFacingObject
+ jr c, .IsObject
+ xor a
+ ret
+
+.IsObject:
+ call PlayTalkObject
+ ld a, [hObjectStructIndexBuffer]
+ call GetObjectStruct
+ ld hl, OBJECT_MAP_OBJECT_INDEX
+ add hl, bc
+ ld a, [hl]
+ ld [hLastTalked], a
+
+ ld a, [hLastTalked]
+ call GetMapObject
+ ld hl, MAPOBJECT_COLOR
+ add hl, bc
+ ld a, [hl]
+ and %00001111
+
+; Bug: If IsInArray returns nc, data at bc will be executed as code.
+ push bc
+ ld de, 3
+ ld hl, .pointers
+ call IsInArray
+ jr nc, .nope_bugged
+ pop bc
+
+ inc hl
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.nope_bugged
+ ; pop bc
+ xor a
+ ret
+
+.pointers
+ dbw OBJECTTYPE_SCRIPT, .script
+ dbw OBJECTTYPE_ITEMBALL, .itemball
+ dbw OBJECTTYPE_TRAINER, .trainer
+ ; the remaining four are dummy events
+ dbw OBJECTTYPE_3, .three
+ dbw OBJECTTYPE_4, .four
+ dbw OBJECTTYPE_5, .five
+ dbw OBJECTTYPE_6, .six
+ db -1
+; 96a04
+
+.script ; 96a04
+ ld hl, MAPOBJECT_SCRIPT_POINTER
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call GetMapScriptsBank
+ call CallScript
+ ret
+; 96a12
+
+.itemball ; 96a12
+ ld hl, MAPOBJECT_SCRIPT_POINTER
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call GetMapScriptsBank
+ ld de, wEngineBuffer1
+ ld bc, 2
+ call FarCopyBytes
+ ld a, PLAYEREVENT_ITEMBALL
+ scf
+ ret
+; 96a29
+
+.trainer ; 96a29
+ call TalkToTrainer
+ ld a, PLAYEREVENT_TALKTOTRAINER
+ scf
+ ret
+; 96a30
+
+.three ; 96a30
+ xor a
+ ret
+; 96a32
+
+.four ; 96a32
+ xor a
+ ret
+; 96a34
+
+.five ; 96a34
+ xor a
+ ret
+; 96a36
+
+.six ; 96a36
+ xor a
+ ret
+; 96a38
+
+TryBGEvent: ; 96a38
+ call CheckFacingBGEvent
+ jr c, .is_bg_event
+ xor a
+ ret
+
+.is_bg_event:
+ ld a, [wEngineBuffer3]
+ ld hl, .bg_events
+ rst JumpTable
+ ret
+
+.bg_events
+ dw .read
+ dw .up
+ dw .down
+ dw .right
+ dw .left
+ dw .ifset
+ dw .ifnotset
+ dw .itemifset
+ dw .copy
+; 96a59
+
+.up
+ ld b, OW_UP
+ jr .checkdir
+.down
+ ld b, OW_DOWN
+ jr .checkdir
+.right
+ ld b, OW_RIGHT
+ jr .checkdir
+.left
+ ld b, OW_LEFT
+ jr .checkdir
+
+.checkdir
+ ld a, [wPlayerDirection]
+ and %1100
+ cp b
+ jp nz, .dontread
+
+.read
+ call PlayTalkObject
+ ld hl, wEngineBuffer4
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call GetMapScriptsBank
+ call CallScript
+ scf
+ ret
+
+.itemifset
+ call CheckBGEventFlag
+ jp nz, .dontread
+ call PlayTalkObject
+ call GetMapScriptsBank
+ ld de, wEngineBuffer1
+ ld bc, 3
+ call FarCopyBytes
+ ld a, BANK(HiddenItemScript)
+ ld hl, HiddenItemScript
+ call CallScript
+ scf
+ ret
+
+.copy
+ call CheckBGEventFlag
+ jr nz, .dontread
+ call GetMapScriptsBank
+ ld de, wEngineBuffer1
+ ld bc, 3
+ call FarCopyBytes
+ jr .dontread
+
+.ifset
+ call CheckBGEventFlag
+ jr z, .dontread
+ jr .thenread
+
+.ifnotset
+ call CheckBGEventFlag
+ jr nz, .dontread
+
+.thenread
+ push hl
+ call PlayTalkObject
+ pop hl
+ inc hl
+ inc hl
+ call GetMapScriptsBank
+ call GetFarHalfword
+ call GetMapScriptsBank
+ call CallScript
+ scf
+ ret
+
+.dontread
+ xor a
+ ret
+; 96ad8
+
+CheckBGEventFlag: ; 96ad8
+ ld hl, wEngineBuffer4
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ push hl
+ call GetMapScriptsBank
+ call GetFarHalfword
+ ld e, l
+ ld d, h
+ ld b, CHECK_FLAG
+ call EventFlagAction
+ ld a, c
+ and a
+ pop hl
+ ret
+; 96af0
+
+PlayerMovement: ; 96af0
+ farcall DoPlayerMovement
+ ld a, c
+ ld hl, .pointers
+ rst JumpTable
+ ld a, c
+ ret
+; 96afd
+
+.pointers
+ dw .zero
+ dw .one
+ dw .two
+ dw .three
+ dw .four
+ dw .five
+ dw .six
+ dw .seven
+
+.zero
+.four ; 96b0d
+ xor a
+ ld c, a
+ ret
+; 96b10
+
+.seven ; 96b10
+ call ret_968d7 ; mobile
+ xor a
+ ld c, a
+ ret
+; 96b16
+
+.one ; 96b16
+ ld a, 5
+ ld c, a
+ scf
+ ret
+; 96b1b
+
+.two ; 96b1b
+ ld a, 9
+ ld c, a
+ scf
+ ret
+; 96b20
+
+.three ; 96b20
+; force the player to move in some direction
+ ld a, BANK(Script_ForcedMovement)
+ ld hl, Script_ForcedMovement
+ call CallScript
+; ld a, -1
+ ld c, a
+ scf
+ ret
+; 96b2b
+
+.five
+.six ; 96b2b
+ ld a, -1
+ ld c, a
+ and a
+ ret
+; 96b30
+
+CheckMenuOW: ; 96b30
+ xor a
+ ld [hMenuReturn], a
+ ld [hMenuReturn + 1], a
+ ld a, [hJoyPressed]
+
+ bit SELECT_F, a
+ jr nz, .Select
+
+ bit START_F, a
+ jr z, .NoMenu
+
+ ld a, BANK(StartMenuScript)
+ ld hl, StartMenuScript
+ call CallScript
+ scf
+ ret
+
+.NoMenu:
+ xor a
+ ret
+
+.Select:
+ call PlayTalkObject
+ ld a, BANK(SelectMenuScript)
+ ld hl, SelectMenuScript
+ call CallScript
+ scf
+ ret
+; 96b58
+
+StartMenuScript: ; 96b58
+ callasm StartMenu
+ jump StartMenuCallback
+; 96b5f
+
+SelectMenuScript: ; 96b5f
+ callasm SelectMenu
+ jump SelectMenuCallback
+; 96b66
+
+StartMenuCallback:
+SelectMenuCallback: ; 96b66
+ copybytetovar hMenuReturn
+ ifequal HMENURETURN_SCRIPT, .Script
+ ifequal HMENURETURN_ASM, .Asm
+ end
+; 96b72
+
+.Script: ; 96b72
+ ptjump wQueuedScriptBank
+; 96b75
+
+.Asm: ; 96b75
+ ptcallasm wQueuedScriptBank
+ end
+; 96b79
+
+CountStep: ; 96b79
+ ; Don't count steps in link communication rooms.
+ ld a, [wLinkMode]
+ and a
+ jr nz, .done
+
+ ; If there is a special phone call, don't count the step.
+ farcall CheckSpecialPhoneCall
+ jr c, .doscript
+
+ ; If Repel wore off, don't count the step.
+ call DoRepelStep
+ jr c, .doscript
+
+ ; Count the step for poison and total steps
+ ld hl, wPoisonStepCount
+ inc [hl]
+ ld hl, wStepCount
+ inc [hl]
+ ; Every 256 steps, increase the happiness of all your Pokemon.
+ jr nz, .skip_happiness
+
+ farcall StepHappiness
+
+.skip_happiness
+ ; Every 256 steps, offset from the happiness incrementor by 128 steps,
+ ; decrease the hatch counter of all your eggs until you reach the first
+ ; one that is ready to hatch.
+ ld a, [wStepCount]
+ cp $80
+ jr nz, .skip_egg
+
+ farcall DoEggStep
+ jr nz, .hatch
+
+.skip_egg
+ ; Increase the EXP of (both) DayCare Pokemon by 1.
+ farcall DayCareStep
+
+ ; Every four steps, deal damage to all Poisoned Pokemon
+ ld hl, wPoisonStepCount
+ ld a, [hl]
+ cp 4
+ jr c, .skip_poison
+ ld [hl], 0
+
+ farcall DoPoisonStep
+ jr c, .doscript
+
+.skip_poison
+ farcall DoBikeStep
+
+.done
+ xor a
+ ret
+
+.doscript
+ ld a, -1
+ scf
+ ret
+
+.hatch
+ ld a, 8
+ scf
+ ret
+; 96bd3
+
+; unused
+.unreferenced ; 96bd3
+ ld a, 7
+ scf
+ ret
+; 96bd7
+
+DoRepelStep: ; 96bd7
+ ld a, [wRepelEffect]
+ and a
+ ret z
+
+ dec a
+ ld [wRepelEffect], a
+ ret nz
+
+ ld a, BANK(RepelWoreOffScript)
+ ld hl, RepelWoreOffScript
+ call CallScript
+ scf
+ ret
+; 96beb
+
+DoPlayerEvent: ; 96beb
+ ld a, [wScriptRunning]
+ and a
+ ret z
+
+ cp PLAYEREVENT_MAPSCRIPT ; run script
+ ret z
+
+ cp NUM_PLAYER_EVENTS
+ ret nc
+
+ ld c, a
+ ld b, 0
+ ld hl, PlayerEventScriptPointers
+ add hl, bc
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld [wScriptBank], a
+ ld a, [hli]
+ ld [wScriptPos], a
+ ld a, [hl]
+ ld [wScriptPos + 1], a
+ ret
+; 96c0c
+
+PlayerEventScriptPointers: ; 96c0c
+ dba Invalid_0x96c2d ; 0
+ dba SeenByTrainerScript ; 1
+ dba TalkToTrainerScript ; 2
+ dba FindItemInBallScript ; 3
+ dba EdgeWarpScript ; 4
+ dba WarpToNewMapScript ; 5
+ dba FallIntoMapScript ; 6
+ dba Script_OverworldWhiteout ; 7
+ dba HatchEggScript ; 8
+ dba ChangeDirectionScript ; 9
+ dba Invalid_0x96c2d ; 10
+; 96c2d
+
+Invalid_0x96c2d: ; 96c2d
+ end
+; 96c2e
+
+; unused
+ end
+; 96c2f
+
+HatchEggScript: ; 96c2f
+ callasm OverworldHatchEgg
+ end
+; 96c34
+
+WarpToNewMapScript: ; 96c34
+ warpsound
+ newloadmap MAPSETUP_DOOR
+ end
+; 96c38
+
+FallIntoMapScript: ; 96c38
+ newloadmap MAPSETUP_FALL
+ playsound SFX_KINESIS
+ applymovement PLAYER, MovementData_0x96c48
+ playsound SFX_STRENGTH
+ scall LandAfterPitfallScript
+ end
+; 96c48
+
+MovementData_0x96c48: ; 96c48
+ skyfall
+ step_end
+; 96c4a
+
+LandAfterPitfallScript: ; 96c4a
+ earthquake 16
+ end
+; 96c4d
+
+EdgeWarpScript: ; 4
+ reloadandreturn MAPSETUP_CONNECTION
+; 96c4f
+
+ChangeDirectionScript: ; 9
+ deactivatefacing 3
+ callasm EnableWildEncounters
+ end
+; 96c56
+
+INCLUDE "engine/overworld/scripting.asm"
+
+INCLUDE "engine/overworld/events_2.asm"
diff --git a/engine/overworld/events_2.asm b/engine/overworld/events_2.asm
new file mode 100644
index 000000000..6e106541a
--- /dev/null
+++ b/engine/overworld/events_2.asm
@@ -0,0 +1,650 @@
+; More overworld event handling.
+
+
+WarpToSpawnPoint:: ; 97c28
+ ld hl, wStatusFlags2
+ res STATUSFLAGS2_SAFARI_GAME_F, [hl]
+ res STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
+ ret
+; 97c30
+
+RunMemScript:: ; 97c30
+; If there is no script here, we don't need to be here.
+ ld a, [wMapReentryScriptQueueFlag]
+ and a
+ ret z
+; Execute the script at (wMapReentryScriptBank):(wMapReentryScriptAddress).
+ ld hl, wMapReentryScriptAddress
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wMapReentryScriptBank]
+ call CallScript
+ scf
+; Clear the buffer for the next script.
+ push af
+ xor a
+ ld hl, wMapReentryScriptQueueFlag
+ ld bc, 8
+ call ByteFill
+ pop af
+ ret
+; 97c4f
+
+LoadScriptBDE:: ; 97c4f
+; If there's already a script here, don't overwrite.
+ ld hl, wMapReentryScriptQueueFlag
+ ld a, [hl]
+ and a
+ ret nz
+; Set the flag
+ ld [hl], 1
+ inc hl
+; Load the script pointer b:de into (wMapReentryScriptBank):(wMapReentryScriptAddress)
+ ld [hl], b
+ inc hl
+ ld [hl], e
+ inc hl
+ ld [hl], d
+ scf
+ ret
+; 97c5f
+
+TryTileCollisionEvent:: ; 97c5f
+ call GetFacingTileCoord
+ ld [wEngineBuffer1], a
+ ld c, a
+ farcall CheckFacingTileForStdScript
+ jr c, .done
+
+ call CheckCutTreeTile
+ jr nz, .whirlpool
+ farcall TryCutOW
+ jr .done
+
+.whirlpool
+ ld a, [wEngineBuffer1]
+ call CheckWhirlpoolTile
+ jr nz, .waterfall
+ farcall TryWhirlpoolOW
+ jr .done
+
+.waterfall
+ ld a, [wEngineBuffer1]
+ call CheckWaterfallTile
+ jr nz, .headbutt
+ farcall TryWaterfallOW
+ jr .done
+
+.headbutt
+ ld a, [wEngineBuffer1]
+ call CheckHeadbuttTreeTile
+ jr nz, .surf
+ farcall TryHeadbuttOW
+ jr c, .done
+ jr .noevent
+
+.surf
+ farcall TrySurfOW
+ jr nc, .noevent
+ jr .done
+
+.noevent
+ xor a
+ ret
+
+.done
+ call PlayClickSFX
+ ld a, $ff
+ scf
+ ret
+; 97cc0
+
+
+RandomEncounter:: ; 97cc0
+; Random encounter
+
+ call CheckWildEncounterCooldown
+ jr c, .nope
+ call CanUseSweetScent
+ jr nc, .nope
+ ld hl, wStatusFlags2
+ bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl]
+ jr nz, .bug_contest
+ farcall TryWildEncounter
+ jr nz, .nope
+ jr .ok
+
+.bug_contest
+ call _TryWildEncounter_BugContest
+ jr nc, .nope
+ jr .ok_bug_contest
+
+.nope
+ ld a, 1
+ and a
+ ret
+
+.ok
+ ld a, BANK(WildBattleScript)
+ ld hl, WildBattleScript
+ jr .done
+
+.ok_bug_contest
+ ld a, BANK(BugCatchingContestBattleScript)
+ ld hl, BugCatchingContestBattleScript
+ jr .done
+
+.done
+ call CallScript
+ scf
+ ret
+; 97cf9
+
+WildBattleScript: ; 97cf9
+ randomwildmon
+ startbattle
+ reloadmapafterbattle
+ end
+; 97cfd
+
+CanUseSweetScent:: ; 97cfd
+ ld hl, wStatusFlags
+ bit STATUSFLAGS_NO_WILD_ENCOUNTERS_F, [hl]
+ jr nz, .no
+ ld a, [wEnvironment]
+ cp CAVE
+ jr z, .ice_check
+ cp DUNGEON
+ jr z, .ice_check
+ farcall CheckGrassCollision
+ jr nc, .no
+
+.ice_check
+ ld a, [wPlayerStandingTile]
+ call CheckIceTile
+ jr z, .no
+ scf
+ ret
+
+.no
+ and a
+ ret
+; 97d23
+
+_TryWildEncounter_BugContest: ; 97d23
+ call TryWildEncounter_BugContest
+ ret nc
+ call ChooseWildEncounter_BugContest
+ farcall CheckRepelEffect
+ ret
+; 97d31
+
+ChooseWildEncounter_BugContest:: ; 97d31
+; Pick a random mon out of ContestMons.
+
+.loop
+ call Random
+ cp 100 << 1
+ jr nc, .loop
+ srl a
+
+ ld hl, ContestMons
+ ld de, 4
+.CheckMon:
+ sub [hl]
+ jr c, .GotMon
+ add hl, de
+ jr .CheckMon
+
+.GotMon:
+ inc hl
+
+; Species
+ ld a, [hli]
+ ld [wTempWildMonSpecies], a
+
+; Min level
+ ld a, [hli]
+ ld d, a
+
+; Max level
+ ld a, [hl]
+
+ sub d
+ jr nz, .RandomLevel
+
+; If min and max are the same.
+ ld a, d
+ jr .GotLevel
+
+.RandomLevel:
+; Get a random level between the min and max.
+ ld c, a
+ inc c
+ call Random
+ ld a, [hRandomAdd]
+ call SimpleDivide
+ add d
+
+.GotLevel:
+ ld [wCurPartyLevel], a
+
+ xor a
+ ret
+; 97d64
+
+TryWildEncounter_BugContest: ; 97d64
+ ld a, [wPlayerStandingTile]
+ call CheckSuperTallGrassTile
+ ld b, 40 percent
+ jr z, .ok
+ ld b, 20 percent
+
+.ok
+ farcall ApplyMusicEffectOnEncounterRate
+ farcall ApplyCleanseTagEffectOnEncounterRate
+ call Random
+ ld a, [hRandomAdd]
+ cp b
+ ret c
+ ld a, 1
+ and a
+ ret
+; 97d87
+
+
+INCLUDE "data/wild/bug_contest_mons.asm"
+
+
+DoBikeStep:: ; 97db3
+ nop
+ nop
+ ; If the bike shop owner doesn't have our number, or
+ ; if we've already gotten the call, we don't have to
+ ; be here.
+ ld hl, wStatusFlags2
+ bit STATUSFLAGS2_BIKE_SHOP_CALL_F, [hl]
+ jr z, .NoCall
+
+ ; If we're not on the bike, we don't have to be here.
+ ld a, [wPlayerState]
+ cp PLAYER_BIKE
+ jr nz, .NoCall
+
+ ; If we're not in an area of phone service, we don't
+ ; have to be here.
+ call GetMapPhoneService
+ and a
+ jr nz, .NoCall
+
+ ; Check the bike step count and check whether we've
+ ; taken 65536 of them yet.
+ ld hl, wBikeStep
+ ld a, [hli]
+ ld d, a
+ ld e, [hl]
+ cp 255
+ jr nz, .increment
+ ld a, e
+ cp 255
+ jr z, .dont_increment
+
+.increment
+ inc de
+ ld [hl], e
+ dec hl
+ ld [hl], d
+
+.dont_increment
+ ; If we've taken at least 1024 steps, have the bike
+ ; shop owner try to call us.
+ ld a, d
+ cp HIGH(1024)
+ jr c, .NoCall
+
+ ; If a call has already been queued, don't overwrite
+ ; that call.
+ ld a, [wSpecialPhoneCallID]
+ and a
+ jr nz, .NoCall
+
+ ; Queue the call.
+ ld a, SPECIALCALL_BIKESHOP
+ ld [wSpecialPhoneCallID], a
+ xor a
+ ld [wSpecialPhoneCallID + 1], a
+ ld hl, wStatusFlags2
+ res STATUSFLAGS2_BIKE_SHOP_CALL_F, [hl]
+ scf
+ ret
+
+.NoCall:
+ xor a
+ ret
+; 97df9
+
+ClearCmdQueue:: ; 97df9
+ ld hl, wCmdQueue
+ ld de, 6
+ ld c, 4
+ xor a
+.loop
+ ld [hl], a
+ add hl, de
+ dec c
+ jr nz, .loop
+ ret
+; 97e08
+
+HandleCmdQueue:: ; 97e08
+ ld hl, wCmdQueue
+ xor a
+.loop
+ ld [hMapObjectIndexBuffer], a
+ ld a, [hl]
+ and a
+ jr z, .skip
+ push hl
+ ld b, h
+ ld c, l
+ call HandleQueuedCommand
+ pop hl
+
+.skip
+ ld de, CMDQUEUE_ENTRY_SIZE
+ add hl, de
+ ld a, [hMapObjectIndexBuffer]
+ inc a
+ cp CMDQUEUE_CAPACITY
+ jr nz, .loop
+ ret
+; 97e25
+
+Unreferenced_GetNthCmdQueueEntry: ; 97e25
+ ld hl, wCmdQueue
+ ld bc, CMDQUEUE_ENTRY_SIZE
+ call AddNTimes
+ ld b, h
+ ld c, l
+ ret
+; 97e31
+
+WriteCmdQueue:: ; 97e31
+ push bc
+ push de
+ call .GetNextEmptyEntry
+ ld d, h
+ ld e, l
+ pop hl
+ pop bc
+ ret c
+ ld a, b
+ ld bc, CMDQUEUE_ENTRY_SIZE - 1
+ call FarCopyBytes
+ xor a
+ ld [hl], a
+ ret
+; 97e45
+
+.GetNextEmptyEntry: ; 97e45
+ ld hl, wCmdQueue
+ ld de, CMDQUEUE_ENTRY_SIZE
+ ld c, CMDQUEUE_CAPACITY
+.loop
+ ld a, [hl]
+ and a
+ jr z, .done
+ add hl, de
+ dec c
+ jr nz, .loop
+ scf
+ ret
+
+.done
+ ld a, CMDQUEUE_CAPACITY
+ sub c
+ and a
+ ret
+; 97e5c
+
+DelCmdQueue:: ; 97e5c
+ ld hl, wCmdQueue
+ ld de, CMDQUEUE_ENTRY_SIZE
+ ld c, CMDQUEUE_CAPACITY
+.loop
+ ld a, [hl]
+ cp b
+ jr z, .done
+ add hl, de
+ dec c
+ jr nz, .loop
+ and a
+ ret
+
+.done
+ xor a
+ ld [hl], a
+ scf
+ ret
+; 97e72
+
+_DelCmdQueue: ; 97e72
+ ld hl, CMDQUEUE_TYPE
+ add hl, bc
+ ld [hl], 0
+ ret
+; 97e79
+
+HandleQueuedCommand: ; 97e79
+ ld hl, CMDQUEUE_TYPE
+ add hl, bc
+ ld a, [hl]
+ cp 5
+ jr c, .okay
+ xor a
+
+.okay
+ ld e, a
+ ld d, 0
+ ld hl, .Jumptable
+ add hl, de
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ push af
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ pop af
+ rst FarCall
+ ret
+; 97e94
+
+.Jumptable: ; 97e94
+ dba CmdQueue_Null
+ dba CmdQueue_Null2
+ dba CmdQueue_StoneTable
+ dba CmdQueue_Type3
+ dba CmdQueue_Type4
+; 97ea3
+
+CmdQueueAnonymousJumptable: ; 97ea3
+ ld hl, CMDQUEUE_05
+ add hl, bc
+ ld a, [hl]
+ pop hl
+ rst JumpTable
+ ret
+; 97eab
+
+CmdQueueAnonJT_Increment: ; 97eab
+ ld hl, CMDQUEUE_05
+ add hl, bc
+ inc [hl]
+ ret
+; 97eb1
+
+CmdQueueAnonJT_Decrement: ; 97eb1
+ ld hl, CMDQUEUE_05
+ add hl, bc
+ dec [hl]
+ ret
+; 97eb7
+
+CmdQueue_Null: ; 97eb7
+ ret
+; 97eb8
+
+CmdQueue_Null2: ; 97eb8
+ call ret_2f3e
+ ret
+; 97ebc
+
+CmdQueue_Type4: ; 97ebc
+ call CmdQueueAnonymousJumptable
+ ; anonymous dw
+ dw .zero
+ dw .one
+; 97ec3
+
+.zero ; 97ec3
+ ld a, [hSCY]
+ ld hl, 4
+ add hl, bc
+ ld [hl], a
+ call CmdQueueAnonJT_Increment
+.one ; 97ecd
+ ld hl, 1
+ add hl, bc
+ ld a, [hl]
+ dec a
+ ld [hl], a
+ jr z, .finish
+ and $1
+ jr z, .add
+ ld hl, 2
+ add hl, bc
+ ld a, [hSCY]
+ sub [hl]
+ ld [hSCY], a
+ ret
+
+.add
+ ld hl, 2
+ add hl, bc
+ ld a, [hSCY]
+ add [hl]
+ ld [hSCY], a
+ ret
+
+.finish
+ ld hl, 4
+ add hl, bc
+ ld a, [hl]
+ ld [hSCY], a
+ call _DelCmdQueue
+ ret
+; 97ef9
+
+CmdQueue_Type3: ; 97ef9
+ call CmdQueueAnonymousJumptable
+ ; anonymous dw
+ dw .zero
+ dw .one
+ dw .two
+; 97f02
+
+.zero ; 97f02
+ call .IsPlayerFacingDown
+ jr z, .PlayerNotFacingDown
+ call CmdQueueAnonJT_Increment
+.one ; 97f0a
+ call .IsPlayerFacingDown
+ jr z, .PlayerNotFacingDown
+ call CmdQueueAnonJT_Increment
+
+ ld hl, 2
+ add hl, bc
+ ld a, [hl]
+ ld [wd173], a
+ ret
+; 97f1b
+
+.two ; 97f1b
+ call .IsPlayerFacingDown
+ jr z, .PlayerNotFacingDown
+ call CmdQueueAnonJT_Decrement
+
+ ld hl, 3
+ add hl, bc
+ ld a, [hl]
+ ld [wd173], a
+ ret
+; 97f2c
+
+.PlayerNotFacingDown: ; 97f2c
+ ld a, $7f
+ ld [wd173], a
+ ld hl, 5
+ add hl, bc
+ ld [hl], 0
+ ret
+; 97f38
+
+.IsPlayerFacingDown: ; 97f38
+ push bc
+ ld bc, wPlayerStruct
+ call GetSpriteDirection
+ and a
+ pop bc
+ ret
+; 97f42
+
+CmdQueue_StoneTable: ; 97f42
+ ld de, wPlayerStruct
+ ld a, NUM_OBJECT_STRUCTS
+.loop
+ push af
+
+ ld hl, OBJECT_SPRITE
+ add hl, de
+ ld a, [hl]
+ and a
+ jr z, .next
+
+ ld hl, OBJECT_MOVEMENTTYPE
+ add hl, de
+ ld a, [hl]
+ cp SPRITEMOVEDATA_STRENGTH_BOULDER
+ jr nz, .next
+
+ ld hl, OBJECT_NEXT_TILE
+ add hl, de
+ ld a, [hl]
+ call CheckPitTile
+ jr nz, .next
+
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, de
+ ld a, [hl]
+ cp STANDING
+ jr nz, .next
+ call HandleStoneQueue
+ jr c, .fall_down_hole
+
+.next
+ ld hl, OBJECT_STRUCT_LENGTH
+ add hl, de
+ ld d, h
+ ld e, l
+
+ pop af
+ dec a
+ jr nz, .loop
+ ret
+
+.fall_down_hole
+ pop af
+ ret
+; 97f7e
diff --git a/engine/overworld/init_map.asm b/engine/overworld/init_map.asm
new file mode 100644
index 000000000..2eb4998a6
--- /dev/null
+++ b/engine/overworld/init_map.asm
@@ -0,0 +1,103 @@
+ReanchorBGMap_NoOAMUpdate:: ; 6454
+ call DelayFrame
+ ld a, [hOAMUpdate]
+ push af
+
+ ld a, $1
+ ld [hOAMUpdate], a
+ ld a, [hBGMapMode]
+ push af
+ xor a
+ ld [hBGMapMode], a
+
+ call .ReanchorBGMap
+
+ pop af
+ ld [hBGMapMode], a
+ pop af
+ ld [hOAMUpdate], a
+ ld hl, wVramState
+ set 6, [hl]
+ ret
+
+.ReanchorBGMap:
+ xor a
+ ld [hLCDCPointer], a
+ ld [hBGMapMode], a
+ ld a, $90
+ ld [hWY], a
+ call OverworldTextModeSwitch
+ ld a, HIGH(vBGMap1)
+ call .LoadBGMapAddrIntoHRAM
+ call _OpenAndCloseMenu_HDMATransferTileMapAndAttrMap
+ farcall LoadOW_BGPal7
+ farcall ApplyPals
+ ld a, $1
+ ld [hCGBPalUpdate], a
+ xor a
+ ld [hBGMapMode], a
+ ld [hWY], a
+ farcall HDMATransfer_FillBGMap0WithBlack ; no need to farcall
+ ld a, HIGH(vBGMap0)
+ call .LoadBGMapAddrIntoHRAM
+ xor a ; LOW(vBGMap0)
+ ld [wBGMapAnchor], a
+ ld a, HIGH(vBGMap0)
+ ld [wBGMapAnchor + 1], a
+ xor a
+ ld [hSCX], a
+ ld [hSCY], a
+ call ApplyBGMapAnchorToObjects
+ ret
+
+.LoadBGMapAddrIntoHRAM: ; 64b9
+ ld [hBGMapAddress + 1], a
+ xor a
+ ld [hBGMapAddress], a
+ ret
+
+LoadFonts_NoOAMUpdate:: ; 64bf
+ ld a, [hOAMUpdate]
+ push af
+ ld a, $1
+ ld [hOAMUpdate], a
+
+ call .LoadGFX
+
+ pop af
+ ld [hOAMUpdate], a
+ ret
+
+.LoadGFX:
+ call LoadFontsExtra
+ ld a, $90
+ ld [hWY], a
+ call SafeUpdateSprites
+ call LoadStandardFont
+ ret
+
+HDMATransfer_FillBGMap0WithBlack: ; 64db
+ ld a, [rSVBK]
+ push af
+ ld a, BANK(wDecompressScratch)
+ ld [rSVBK], a
+
+ ld a, "■"
+ ld hl, wDecompressScratch
+ ld bc, wScratchAttrMap - wDecompressScratch
+ call ByteFill
+ ld a, HIGH(wDecompressScratch)
+ ld [rHDMA1], a
+ ld a, LOW(wDecompressScratch)
+ ld [rHDMA2], a
+ ld a, HIGH(vBGMap0 % $8000)
+ ld [rHDMA3], a
+ ld a, LOW(vBGMap0 % $8000)
+ ld [rHDMA4], a
+ ld a, $3f
+ ld [hDMATransfer], a
+ call DelayFrame
+
+ pop af
+ ld [rSVBK], a
+ ret
diff --git a/engine/overworld/landmarks.asm b/engine/overworld/landmarks.asm
new file mode 100644
index 000000000..f16f48e67
--- /dev/null
+++ b/engine/overworld/landmarks.asm
@@ -0,0 +1,87 @@
+GetLandmarkCoords: ; 0x1ca896
+; Return coordinates (d, e) of landmark e.
+ push hl
+ ld l, e
+ ld h, 0
+ add hl, hl
+ add hl, hl
+ ld de, Landmarks
+ add hl, de
+ ld a, [hli]
+ ld e, a
+ ld d, [hl]
+ pop hl
+ ret
+; 0x1ca8a5
+
+
+GetLandmarkName:: ; 0x1ca8a5
+; Copy the name of landmark e to wStringBuffer1.
+ push hl
+ push de
+ push bc
+
+ ld l, e
+ ld h, 0
+ add hl, hl
+ add hl, hl
+ ld de, Landmarks + 2
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+
+ ld de, wStringBuffer1
+ ld c, 18
+.copy
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .copy
+
+ pop bc
+ pop de
+ pop hl
+ ret
+; 0x1ca8c3
+
+
+INCLUDE "data/maps/landmarks.asm"
+
+
+RegionCheck: ; 0x1caea1
+; Checks if the player is in Kanto or Johto.
+; If in Johto, returns 0 in e.
+; If in Kanto, returns 1 in e.
+ ld a, [wMapGroup]
+ ld b, a
+ ld a, [wMapNumber]
+ ld c, a
+ call GetWorldMapLocation
+ cp FAST_SHIP ; S.S. Aqua
+ jr z, .johto
+ cp SPECIAL_MAP
+ jr nz, .checkagain
+
+; In a special map, get the backup map group / map id
+ ld a, [wBackupMapGroup]
+ ld b, a
+ ld a, [wBackupMapNumber]
+ ld c, a
+ call GetWorldMapLocation
+
+.checkagain
+ cp KANTO_LANDMARK
+ jr c, .johto
+
+; Victory Road area is considered to be Johto.
+ cp VICTORY_ROAD
+ jr c, .kanto
+
+.johto
+ ld e, JOHTO_REGION
+ ret
+.kanto
+ ld e, KANTO_REGION
+ ret
diff --git a/engine/overworld/map_object_action.asm b/engine/overworld/map_object_action.asm
new file mode 100755
index 000000000..c82cd80a2
--- /dev/null
+++ b/engine/overworld/map_object_action.asm
@@ -0,0 +1,313 @@
+ObjectActionPairPointers: ; 445f
+; entries correspond to OBJECT_ACTION_* constants
+ dw SetFacingStanding, SetFacingStanding
+ dw SetFacingStandAction, SetFacingCurrent
+ dw SetFacingStepAction, SetFacingCurrent
+ dw SetFacingBumpAction, SetFacingCurrent
+ dw SetFacingCounterclockwiseSpin, SetFacingCurrent
+ dw SetFacingCounterclockwiseSpin2, SetFacingStanding
+ dw SetFacingFish, SetFacingFish
+ dw SetFacingShadow, SetFacingStanding
+ dw SetFacingEmote, SetFacingEmote
+ dw SetFacingBigDollSym, SetFacingBigDollSym
+ dw SetFacingBounce, SetFacingFreezeBounce
+ dw SetFacingWeirdTree, SetFacingCurrent
+ dw SetFacingBigDollAsym, SetFacingBigDollAsym
+ dw SetFacingBigDoll, SetFacingBigDoll
+ dw SetFacingBoulderDust, SetFacingStanding
+ dw SetFacingGrassShake, SetFacingStanding
+ dw SetFacingSkyfall, SetFacingCurrent
+; 44a3
+
+SetFacingStanding: ; 44a3
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], STANDING
+ ret
+; 44aa
+
+SetFacingCurrent: ; 44aa
+ call GetSpriteDirection
+ or FACING_STEP_DOWN_0 ; useless
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], a
+ ret
+; 44b5
+
+SetFacingStandAction: ; 44b5
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld a, [hl]
+ and 1
+ jr nz, SetFacingStepAction
+ jp SetFacingCurrent
+; 44c1
+
+SetFacingStepAction: ; 44c1
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ bit SLIDING, [hl]
+ jp nz, SetFacingCurrent
+
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld a, [hl]
+ inc a
+ and %00001111
+ ld [hl], a
+
+ rrca
+ rrca
+ and %00000011
+ ld d, a
+
+ call GetSpriteDirection
+ or FACING_STEP_DOWN_0 ; useless
+ or d
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], a
+ ret
+; 44e4
+
+SetFacingSkyfall: ; 44e4
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ bit SLIDING, [hl]
+ jp nz, SetFacingCurrent
+
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld a, [hl]
+ add 2
+ and %00001111
+ ld [hl], a
+
+ rrca
+ rrca
+ and %00000011
+ ld d, a
+
+ call GetSpriteDirection
+ or FACING_STEP_DOWN_0 ; useless
+ or d
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], a
+ ret
+; 4508
+
+SetFacingBumpAction: ; 4508
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ bit SLIDING, [hl]
+ jp nz, SetFacingCurrent
+
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ inc [hl]
+
+ ld a, [hl]
+ rrca
+ rrca
+ rrca
+ and %00000011
+ ld d, a
+
+ call GetSpriteDirection
+ or FACING_STEP_DOWN_0 ; useless
+ or d
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], a
+ ret
+; 4529
+
+SetFacingCounterclockwiseSpin: ; 4529
+ call CounterclockwiseSpinAction
+ ld hl, OBJECT_FACING
+ add hl, bc
+ ld a, [hl]
+ or FACING_STEP_DOWN_0 ; useless
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], a
+ ret
+; 4539
+
+SetFacingCounterclockwiseSpin2: ; 4539
+ call CounterclockwiseSpinAction
+ jp SetFacingStanding
+; 453f
+
+CounterclockwiseSpinAction: ; 453f
+; Here, OBJECT_STEP_FRAME consists of two 2-bit components,
+; using only bits 0,1 and 4,5.
+; bits 0,1 is a timer (4 overworld frames)
+; bits 4,5 determines the facing - the direction is counterclockwise.
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld a, [hl]
+ and %11110000
+ ld e, a
+
+ ld a, [hl]
+ inc a
+ and %00001111
+ ld d, a
+ cp 4
+ jr c, .ok
+
+ ld d, 0
+ ld a, e
+ add $10
+ and %00110000
+ ld e, a
+
+.ok
+ ld a, d
+ or e
+ ld [hl], a
+
+ swap e
+ ld d, 0
+ ld hl, .Directions
+ add hl, de
+ ld a, [hl]
+ ld hl, OBJECT_FACING
+ add hl, bc
+ ld [hl], a
+ ret
+; 456a
+
+.Directions: ; 456a
+ db OW_DOWN, OW_RIGHT, OW_UP, OW_LEFT
+; 456e
+
+SetFacingFish: ; 456e
+ call GetSpriteDirection
+ rrca
+ rrca
+ add FACING_FISH_DOWN
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], a
+ ret
+; 457b
+
+SetFacingShadow: ; 457b
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], FACING_SHADOW
+ ret
+; 4582
+
+SetFacingEmote: ; 4582 emote
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], FACING_EMOTE
+ ret
+; 4589
+
+SetFacingBigDollSym: ; 4589
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], FACING_BIG_DOLL_SYM
+ ret
+; 4590
+
+SetFacingBounce: ; 4590
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld a, [hl]
+ inc a
+ and %00001111
+ ld [hl], a
+ and %00001000
+ jr z, SetFacingFreezeBounce
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], FACING_STEP_UP_0
+ ret
+; 45a4
+
+SetFacingFreezeBounce: ; 45a4
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], FACING_STEP_DOWN_0
+ ret
+; 45ab
+
+SetFacingWeirdTree: ; 45ab
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld a, [hl]
+ inc a
+ ld [hl], a
+ and %00001100
+ rrca
+ rrca
+ add FACING_WEIRD_TREE_0
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], a
+ ret
+; 45be
+
+SetFacingBigDollAsym: ; 45be
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], FACING_BIG_DOLL_ASYM
+ ret
+; 45c5
+
+SetFacingBigDoll: ; 45c5
+ ld a, [wVariableSprites + SPRITE_BIG_DOLL - SPRITE_VARS]
+ ld d, FACING_BIG_DOLL_SYM ; symmetric
+ cp SPRITE_BIG_SNORLAX
+ jr z, .ok
+ cp SPRITE_BIG_LAPRAS
+ jr z, .ok
+ ld d, FACING_BIG_DOLL_ASYM ; asymmetric
+
+.ok
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], d
+ ret
+; 45da
+
+SetFacingBoulderDust: ; 45da
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ inc [hl]
+ ld a, [hl]
+
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ and 2
+ ld a, FACING_BOULDER_DUST_1
+ jr z, .ok
+ inc a ; FACING_BOULDER_DUST_2
+.ok
+ ld [hl], a
+ ret
+; 45ed
+
+SetFacingGrassShake: ; 45ed
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ inc [hl]
+ ld a, [hl]
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ and 4
+ ld a, FACING_GRASS_1
+ jr z, .ok
+ inc a ; FACING_GRASS_2
+
+.ok
+ ld [hl], a
+ ret
+; 4600
diff --git a/engine/overworld/map_objects.asm b/engine/overworld/map_objects.asm
new file mode 100644
index 000000000..8d6f4082f
--- /dev/null
+++ b/engine/overworld/map_objects.asm
@@ -0,0 +1,3123 @@
+INCLUDE "data/sprites/facings.asm"
+
+INCLUDE "data/sprites/map_objects.asm"
+
+
+; 4357
+DeleteMapObject:: ; 4357
+ push bc
+ ld hl, OBJECT_MAP_OBJECT_INDEX
+ add hl, bc
+ ld a, [hl]
+ push af
+ ld h, b
+ ld l, c
+ ld bc, OBJECT_STRUCT_LENGTH
+ xor a
+ call ByteFill
+ pop af
+ cp -1
+ jr z, .ok
+ bit 7, a
+ jr nz, .ok
+ call GetMapObject
+ ld hl, OBJECT_SPRITE
+ add hl, bc
+ ld [hl], -1
+.ok
+ pop bc
+ ret
+; 437b
+
+Function437b: ; 437b
+ call .CheckObjectStillVisible
+ ret c
+ call .HandleStepType
+ call .HandleObjectAction
+ ret
+
+.CheckObjectStillVisible:
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ res 6, [hl]
+ ld a, [wXCoord]
+ ld e, a
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ add 1
+ sub e
+ jr c, .ok
+ cp MAPOBJECT_SCREEN_WIDTH
+ jr nc, .ok
+ ld a, [wYCoord]
+ ld e, a
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ add 1
+ sub e
+ jr c, .ok
+ cp MAPOBJECT_SCREEN_HEIGHT
+ jr nc, .ok
+ jr .yes
+
+.ok
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ set 6, [hl]
+ ld a, [wXCoord]
+ ld e, a
+ ld hl, OBJECT_INIT_X
+ add hl, bc
+ ld a, [hl]
+ add 1
+ sub e
+ jr c, .ok2
+ cp MAPOBJECT_SCREEN_WIDTH
+ jr nc, .ok2
+ ld a, [wYCoord]
+ ld e, a
+ ld hl, OBJECT_INIT_Y
+ add hl, bc
+ ld a, [hl]
+ add 1
+ sub e
+ jr c, .ok2
+ cp MAPOBJECT_SCREEN_HEIGHT
+ jr nc, .ok2
+.yes
+ and a
+ ret
+
+.ok2
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ bit 1, [hl]
+ jr nz, .yes2
+ call DeleteMapObject
+ scf
+ ret
+
+.yes2
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ set 6, [hl]
+ and a
+ ret
+
+.HandleStepType:
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .zero
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ bit 5, [hl]
+ jr nz, .bit5
+ cp STEP_TYPE_SLEEP
+ jr z, .one
+ jr .ok3
+
+.zero
+ call ObjectMovementReset
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ bit 5, [hl]
+ jr nz, .bit5
+.one
+ call MapObjectMovementPattern
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld a, [hl]
+ and a
+ ret z
+ cp STEP_TYPE_SLEEP
+ ret z
+.ok3
+ ld hl, StepTypesJumptable
+ rst JumpTable
+ ret
+
+.bit5
+ ret
+
+.HandleObjectAction:
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ bit INVISIBLE, [hl]
+ jr nz, SetFacingStanding
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ bit 6, [hl]
+ jr nz, SetFacingStanding
+ bit 5, [hl]
+ jr nz, asm_4448
+ ld de, ObjectActionPairPointers ; use first column
+ jr _HandleObjectAction
+; 4440
+
+Function4440: ; 4440
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ bit INVISIBLE, [hl]
+ jr nz, SetFacingStanding
+asm_4448
+ ld de, ObjectActionPairPointers + 2 ; use second column
+ jr _HandleObjectAction
+; 444d
+
+_HandleObjectAction
+; call [4 * wObjectStructs[ObjInd, OBJECT_ACTION] + de]
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld a, [hl]
+ ld l, a
+ ld h, 0
+ add hl, hl
+ add hl, hl
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call _hl_
+ ret
+; 445f
+
+INCLUDE "engine/overworld/map_object_action.asm"
+
+CopyNextCoordsTileToStandingCoordsTile: ; 4600
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_MAP_X
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_MAP_Y
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_NEXT_TILE
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_STANDING_TILE
+ add hl, bc
+ ld [hl], a
+ call SetTallGrassFlags
+ ld hl, OBJECT_NEXT_TILE
+ add hl, bc
+ ld a, [hl]
+ call UselessAndA
+ ret
+; 462a
+
+Function462a: ; 462a
+ ld hl, OBJECT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld [hl], a
+ ret
+; 463f
+
+UpdateTallGrassFlags: ; 463f
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ bit OVERHEAD, [hl]
+ jr z, .ok
+ ld hl, OBJECT_NEXT_TILE
+ add hl, bc
+ ld a, [hl]
+ call SetTallGrassFlags
+.ok
+ ld hl, OBJECT_NEXT_TILE
+ add hl, bc
+ ld a, [hl]
+ call UselessAndA
+ ret c ; never happens
+ ld hl, OBJECT_STANDING_TILE
+ add hl, bc
+ ld a, [hl]
+ call UselessAndA
+ ret
+; 4661
+
+SetTallGrassFlags: ; 4661
+ call CheckSuperTallGrassTile
+ jr z, .set
+ call CheckGrassTile
+ jr c, .reset
+.set
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ set OVERHEAD, [hl]
+ ret
+
+.reset
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ res OVERHEAD, [hl]
+ ret
+; 4679
+
+UselessAndA: ; 4679
+ and a
+ ret
+; 467b
+
+EndSpriteMovement: ; 467b
+ xor a
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+ add hl, bc
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld [hl], a ; OBJECT_1E
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ret
+; 4690
+
+InitStep: ; 4690
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ bit FIXED_FACING, [hl]
+ jr nz, GetNextTile
+ add a
+ add a
+ and %00001100
+ ld hl, OBJECT_FACING
+ add hl, bc
+ ld [hl], a
+GetNextTile: ; 46a6
+ call GetStepVector
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+ ld a, d
+ call GetStepVectorSign
+ ld hl, OBJECT_MAP_X
+ add hl, bc
+ add [hl]
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld [hl], a
+ ld d, a
+ ld a, e
+ call GetStepVectorSign
+ ld hl, OBJECT_MAP_Y
+ add hl, bc
+ add [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld [hl], a
+ ld e, a
+ push bc
+ call GetCoordTile
+ pop bc
+ ld hl, OBJECT_NEXT_TILE
+ add hl, bc
+ ld [hl], a
+ ret
+; 46d7
+
+AddStepVector: ; 46d7
+ call GetStepVector
+ ld hl, OBJECT_SPRITE_X
+ add hl, bc
+ ld a, [hl]
+ add d
+ ld [hl], a
+ ld hl, OBJECT_SPRITE_Y
+ add hl, bc
+ ld a, [hl]
+ add e
+ ld [hl], a
+ ret
+; 46e9
+
+GetStepVector: ; 46e9
+; Return (x, y, duration, speed) in (d, e, a, h).
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld a, [hl]
+ and %00001111
+ add a
+ add a
+ ld l, a
+ ld h, 0
+ ld de, StepVectors
+ add hl, de
+ ld d, [hl]
+ inc hl
+ ld e, [hl]
+ inc hl
+ ld a, [hli]
+ ld h, [hl]
+ ret
+; 4700
+
+StepVectors: ; 4700
+; x, y, duration, speed
+ ; slow
+ db 0, 1, 16, 1
+ db 0, -1, 16, 1
+ db -1, 0, 16, 1
+ db 1, 0, 16, 1
+ ; normal
+ db 0, 2, 8, 2
+ db 0, -2, 8, 2
+ db -2, 0, 8, 2
+ db 2, 0, 8, 2
+ ; fast
+ db 0, 4, 4, 4
+ db 0, -4, 4, 4
+ db -4, 0, 4, 4
+ db 4, 0, 4, 4
+; 4730
+
+GetStepVectorSign: ; 4730
+ add a
+ ret z ; 0 or 128
+ ld a, 1
+ ret nc ; 1 - 127
+ ld a, -1
+ ret ; 129 - 255
+; 4738
+
+UpdatePlayerStep: ; 4738
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld a, [hl]
+ and %00000011
+ ld [wPlayerStepDirection], a
+ call AddStepVector
+ ld a, [wPlayerStepVectorX]
+ add d
+ ld [wPlayerStepVectorX], a
+ ld a, [wPlayerStepVectorY]
+ add e
+ ld [wPlayerStepVectorY], a
+ ld hl, wPlayerStepFlags
+ set 5, [hl]
+ ret
+; 4759
+
+Unreferenced_Function4759: ; 4759
+ push bc
+ ld e, a
+ ld d, 0
+ ld hl, OBJECT_MAP_OBJECT_INDEX
+ add hl, bc
+ ld a, [hl]
+ call GetMapObject
+ add hl, de
+ ld a, [hl]
+ pop bc
+ ret
+; 4769
+
+RestoreDefaultMovement: ; 4769
+ ld hl, OBJECT_MAP_OBJECT_INDEX
+ add hl, bc
+ ld a, [hl]
+ cp -1
+ jr z, .ok
+ push bc
+ call GetMapObject
+ ld hl, MAPOBJECT_MOVEMENT
+ add hl, bc
+ ld a, [hl]
+ pop bc
+ ret
+
+.ok
+ ld a, SPRITEMOVEFN_STANDING
+ ret
+; 4780
+
+ClearObjectMovementByteIndex: ; 4780
+ ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+ add hl, bc
+ ld [hl], 0
+ ret
+; 4787
+
+IncrementObjectMovementByteIndex: ; 4787
+ ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+ add hl, bc
+ inc [hl]
+ ret
+; 478d
+
+DecrementObjectMovementByteIndex: ; 478d
+ ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+ add hl, bc
+ dec [hl]
+ ret
+; 4793
+
+MovementAnonymousJumptable: ; 4793
+ ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+ add hl, bc
+ ld a, [hl]
+ pop hl
+ rst JumpTable
+ ret
+; 479b
+
+ClearObjectStructField1c: ; 479b
+ ld hl, OBJECT_1C
+ add hl, bc
+ ld [hl], 0
+ ret
+; 47a2
+
+IncrementObjectStructField1c: ; 47a2
+ ld hl, OBJECT_1C
+ add hl, bc
+ inc [hl]
+ ret
+; 47a8
+
+Field1cAnonymousJumptable: ; 47a8
+ ld hl, OBJECT_1C
+ add hl, bc
+ ld a, [hl]
+ pop hl
+ rst JumpTable
+ ret
+; 47b0
+
+GetValueObjectStructField1c: ; 47b0
+ ld hl, OBJECT_1C
+ add hl, bc
+ ld a, [hl]
+ ret
+; 47b6
+
+SetValueObjectStructField1c: ; 47b6
+ ld hl, OBJECT_1C
+ add hl, bc
+ ld [hl], a
+ ret
+; 47bc
+
+ObjectMovementReset: ; 47bc
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ push bc
+ call GetCoordTile
+ pop bc
+ ld hl, OBJECT_NEXT_TILE
+ add hl, bc
+ ld [hl], a
+ call CopyNextCoordsTileToStandingCoordsTile
+ call EndSpriteMovement
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 47dd
+
+MapObjectMovementPattern: ; 47dd
+ call ClearObjectStructField1c
+ call GetSpriteMovementFunction
+ ld a, [hl]
+ ld hl, .Pointers
+ rst JumpTable
+ ret
+
+.Pointers: ; 47e9
+; entries correspond to SPRITEMOVEFN_* constants
+ dw .Null_00 ; 00
+ dw .RandomWalkY ; 01
+ dw .RandomWalkX ; 02
+ dw .RandomWalkXY ; 03
+ dw .RandomSpin1 ; 04
+ dw .RandomSpin2 ; 05
+ dw .Standing ; 06
+ dw .ObeyDPad ; 07
+ dw .Movement08 ; 08
+ dw .Movement09 ; 09
+ dw .Movement0a ; 0a
+ dw .Movement0b ; 0b
+ dw .Movement0c ; 0c
+ dw .Movement0d ; 0d
+ dw .Movement0e ; 0e
+ dw .Follow ; 0f
+ dw .Script ; 10
+ dw .Strength ; 11
+ dw .FollowNotExact ; 12
+ dw .MovementShadow ; 13
+ dw .MovementEmote ; 14
+ dw .MovementBigStanding ; 15
+ dw .MovementBouncing ; 16
+ dw .MovementScreenShake ; 17
+ dw .MovementSpinClockwise ; 18
+ dw .MovementSpinCounterclockwise ; 19
+ dw .MovementBoulderDust ; 1a
+ dw .MovementShakingGrass ; 1b
+
+.Null_00:
+ ret
+
+.RandomWalkY:
+ call Random
+ ld a, [hRandomAdd]
+ and %00000001
+ jp .RandomWalkContinue
+
+.RandomWalkX:
+ call Random
+ ld a, [hRandomAdd]
+ and %00000001
+ or %00000010
+ jp .RandomWalkContinue
+
+.RandomWalkXY:
+ call Random
+ ld a, [hRandomAdd]
+ and %00000011
+ jp .RandomWalkContinue
+
+.RandomSpin1:
+ call Random
+ ld a, [hRandomAdd]
+ and %00001100
+ ld hl, OBJECT_FACING
+ add hl, bc
+ ld [hl], a
+ jp RandomStepDuration_Slow
+
+.RandomSpin2:
+ ld hl, OBJECT_FACING
+ add hl, bc
+ ld a, [hl]
+ and %00001100
+ ld d, a
+ call Random
+ ld a, [hRandomAdd]
+ and %00001100
+ cp d
+ jr nz, .keep
+ xor %00001100
+.keep
+ ld [hl], a
+ jp RandomStepDuration_Fast
+
+.Standing:
+ call Function462a
+ call EndSpriteMovement
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STAND
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_05
+ ret
+
+.ObeyDPad:
+ ld hl, Function5000
+ jp HandleMovementData
+
+.Movement08:
+ ld hl, Function5015
+ jp HandleMovementData
+
+.Movement09:
+ ld hl, Function5026
+ jp HandleMovementData
+
+.Movement0a:
+ jp _GetMovementObject
+
+.Movement0b:
+ jp _GetMovementObject
+
+.Movement0c:
+ jp _GetMovementObject
+
+.Movement0d:
+ ld hl, Function5000
+ jp HandleMovementData
+
+.Movement0e:
+ jp _GetMovementObject
+
+.Follow:
+ ld hl, GetFollowerNextMovementByte
+ jp HandleMovementData
+
+.Script:
+ ld hl, GetMovementByte
+ jp HandleMovementData
+
+.Strength:
+ call MovementAnonymousJumptable
+ dw .Strength_Start
+ dw .Strength_Stop
+
+.Strength_Start:
+ ld hl, OBJECT_NEXT_TILE
+ add hl, bc
+ ld a, [hl]
+ call CheckPitTile
+ jr z, .on_pit
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ bit 2, [hl]
+ res 2, [hl]
+ jr z, .ok
+ ld hl, OBJECT_RANGE
+ add hl, bc
+ ld a, [hl]
+ and %00000011
+ or 0
+ call InitStep
+ call Function6ec1
+ jr c, .ok2
+ ld de, SFX_STRENGTH
+ call PlaySFX
+ call SpawnStrengthBoulderDust
+ call UpdateTallGrassFlags
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_0F
+ ret
+
+.ok2
+ call Function462a
+.ok
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ret
+
+.on_pit
+ call IncrementObjectMovementByteIndex
+.Strength_Stop:
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ret
+
+.FollowNotExact:
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ ld hl, OBJECT_RANGE
+ add hl, bc
+ ld a, [hl]
+ push bc
+ call GetObjectStruct
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld a, [hl]
+ cp STANDING
+ jr z, .standing
+ ld hl, OBJECT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ cp d
+ jr z, .equal
+ jr c, .less
+ ld a, 3
+ jr .done
+
+.less
+ ld a, 2
+ jr .done
+
+.equal
+ ld hl, OBJECT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ cp e
+ jr z, .standing
+ jr c, .less2
+ ld a, 0
+ jr .done
+
+.less2
+ ld a, 1
+.done
+ ld d, a
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld a, [hl]
+ and %00001100
+ or d
+ pop bc
+ jp NormalStep
+
+.standing
+ pop bc
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STAND
+ ret
+
+.MovementBigStanding:
+ call EndSpriteMovement
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_BIG_DOLL_SYM
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_04
+ ret
+
+.MovementBouncing:
+ call EndSpriteMovement
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_BOUNCE
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_04
+ ret
+
+.MovementSpinCounterclockwise:
+ call MovementAnonymousJumptable
+ dw .MovementSpinInit
+ dw .MovementSpinRepeat
+ dw .MovementSpinTurnLeft
+
+.MovementSpinClockwise:
+ call MovementAnonymousJumptable
+ dw .MovementSpinInit
+ dw .MovementSpinRepeat
+ dw .MovementSpinTurnRight
+
+.MovementSpinInit:
+ call EndSpriteMovement
+ call IncrementObjectMovementByteIndex
+.MovementSpinRepeat:
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STAND
+ ld hl, OBJECT_RANGE
+ add hl, bc
+ ld a, [hl]
+ ld a, $10
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_03
+ call IncrementObjectMovementByteIndex
+ ret
+
+.MovementSpinTurnLeft:
+ ld de, .DirectionData_Counterclockwise
+ call .MovementSpinNextFacing
+ jr .MovementSpinCounterclockwise
+
+.DirectionData_Counterclockwise: ; 49c0
+ db OW_RIGHT, OW_LEFT, OW_DOWN, OW_UP
+
+.MovementSpinTurnRight:
+ ld de, .DirectionData_Clockwise
+ call .MovementSpinNextFacing
+ jr .MovementSpinClockwise
+
+.DirectionData_Clockwise: ; 49cc
+ db OW_LEFT, OW_RIGHT, OW_UP, OW_DOWN
+
+.MovementSpinNextFacing:
+ ld hl, OBJECT_FACING
+ add hl, bc
+ ld a, [hl]
+ and %00001100
+ rrca
+ rrca
+ push hl
+ ld l, a
+ ld h, 0
+ add hl, de
+ ld a, [hl]
+ pop hl
+ ld [hl], a
+ call DecrementObjectMovementByteIndex
+ ret
+
+.MovementShadow:
+ call ._MovementShadow_Grass_Emote_BoulderDust
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_SHADOW
+ ld hl, OBJECT_STEP_DURATION
+ add hl, de
+ ld a, [hl]
+ inc a
+ add a
+ add 0
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, de
+ ld a, [hl]
+ maskbits NUM_DIRECTIONS
+ ld d, 1 * 8 + 6
+ cp DOWN
+ jr z, .ok_13
+ cp UP
+ jr z, .ok_13
+ ld d, 1 * 8 + 4
+.ok_13
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], d
+ ld hl, OBJECT_SPRITE_X_OFFSET
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_TRACKING_OBJECT
+ ret
+
+.MovementEmote:
+ call EndSpriteMovement
+ call ._MovementShadow_Grass_Emote_BoulderDust
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_EMOTE
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], -2 * 8
+ ld hl, OBJECT_SPRITE_X_OFFSET
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_TRACKING_OBJECT
+ ret
+
+.MovementBoulderDust:
+ call EndSpriteMovement
+ call ._MovementShadow_Grass_Emote_BoulderDust
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_BOULDER_DUST
+ ld hl, OBJECT_STEP_DURATION
+ add hl, de
+ ld a, [hl]
+ inc a
+ add a
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, de
+ ld a, [hl]
+ and %00000011
+ ld e, a
+ ld d, 0
+ ld hl, .data_4a81
+ add hl, de
+ add hl, de
+ ld d, [hl]
+ inc hl
+ ld e, [hl]
+ ld hl, OBJECT_SPRITE_X_OFFSET
+ add hl, bc
+ ld [hl], d
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], e
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_TRACKING_OBJECT
+ ret
+
+.data_4a81 ; 4a81
+ ; x, y
+ db 0, -4
+ db 0, 8
+ db 6, 2
+ db -6, 2
+
+.MovementShakingGrass:
+ call EndSpriteMovement
+ call ._MovementShadow_Grass_Emote_BoulderDust
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_GRASS_SHAKE
+ ld hl, OBJECT_STEP_DURATION
+ add hl, de
+ ld a, [hl]
+ add -1
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_TRACKING_OBJECT
+ ret
+
+._MovementShadow_Grass_Emote_BoulderDust:
+ ld hl, OBJECT_RANGE
+ add hl, bc
+ ld a, [hl]
+ push bc
+ call GetObjectStruct
+ ld d, b
+ ld e, c
+ pop bc
+ ld hl, OBJECT_1D
+ add hl, bc
+ ld [hl], e
+ inc hl
+ ld [hl], d
+ ret
+
+.MovementScreenShake:
+ call EndSpriteMovement
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_00
+ ld hl, OBJECT_RANGE
+ add hl, bc
+ ld a, [hl]
+ call ._MovementScreenShake
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], e
+ ld hl, OBJECT_1E
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_15
+ ret
+
+._MovementScreenShake:
+ ld d, a
+ and %00111111
+ ld e, a
+ ld a, d
+ rlca
+ rlca
+ and %00000011
+ ld d, a
+ inc d
+ ld a, 1
+.loop
+ dec d
+ ret z
+ add a
+ jr .loop
+
+.RandomWalkContinue:
+ call InitStep
+ call Function6ec1 ; check whether the object can move in that direction
+ jr c, .NewDuration
+ call UpdateTallGrassFlags
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STEP
+ ld hl, wCenteredObject
+ ld a, [hMapObjectIndexBuffer]
+ cp [hl]
+ jr z, .load_6
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_07
+ ret
+
+.load_6
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_PLAYER_WALK
+ ret
+
+.NewDuration:
+ call EndSpriteMovement
+ call Function462a
+RandomStepDuration_Slow: ; 4b1d
+ call Random
+ ld a, [hRandomAdd]
+ and %01111111
+ jr SetRandomStepDuration
+; 4b26
+
+RandomStepDuration_Fast: ; 4b26
+ call Random
+ ld a, [hRandomAdd]
+ and %00011111
+SetRandomStepDuration: ; 4b2d
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STAND
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_03
+ ret
+; 4b45
+
+StepTypesJumptable: ; 4b45
+; entries correspond to STEP_TYPE_* constants
+ dw ObjectMovementReset ; 00
+ dw MapObjectMovementPattern ; 01
+ dw NPCStep ; 02
+ dw StepType03 ; 03
+ dw StepType04 ; 04
+ dw StepType05 ; 05
+ dw PlayerStep ; 06
+ dw StepType07 ; 07
+ dw NPCJump ; 08
+ dw PlayerJump ; 09
+ dw PlayerOrNPCTurnStep ; 0a
+ dw StepTypeBump ; 0b
+ dw TeleportFrom ; 0c
+ dw TeleportTo ; 0d
+ dw Skyfall ; 0e
+ dw StepType0f ; 0f
+ dw GotBiteStep ; 10
+ dw RockSmashStep ; 11
+ dw ReturnDigStep ; 12
+ dw StepTypeTrackingObject ; 13
+ dw StepType14 ; 14
+ dw StepType15 ; 15
+ dw StepType16 ; 16
+ dw StepType17 ; 17
+ dw StepType18 ; 18
+ dw SkyfallTop ; 19
+; 4b79
+
+WaitStep_InPlace: ; 4b79
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4b86
+
+NPCJump: ; 4b86
+ call Field1cAnonymousJumptable
+; anonymous dw
+ dw .Jump
+ dw .Land
+
+.Jump:
+ call AddStepVector
+ call UpdateJumpPosition
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ call CopyNextCoordsTileToStandingCoordsTile
+ call GetNextTile
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ res 3, [hl]
+ call IncrementObjectStructField1c
+ ret
+
+.Land:
+ call AddStepVector
+ call UpdateJumpPosition
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ call CopyNextCoordsTileToStandingCoordsTile
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4bbf
+
+PlayerJump: ; 4bbf
+ call Field1cAnonymousJumptable
+; anonymous dw
+ dw .initjump
+ dw .stepjump
+ dw .initland
+ dw .stepland
+
+.initjump
+ ld hl, wPlayerStepFlags
+ set 7, [hl]
+ call IncrementObjectStructField1c
+.stepjump
+ call UpdateJumpPosition
+ call UpdatePlayerStep
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ call CopyNextCoordsTileToStandingCoordsTile
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ res 3, [hl]
+ ld hl, wPlayerStepFlags
+ set 6, [hl]
+ set 4, [hl]
+ call IncrementObjectStructField1c
+ ret
+
+.initland
+ call GetNextTile
+ ld hl, wPlayerStepFlags
+ set 7, [hl]
+ call IncrementObjectStructField1c
+.stepland
+ call UpdateJumpPosition
+ call UpdatePlayerStep
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ ld hl, wPlayerStepFlags
+ set 6, [hl]
+ call CopyNextCoordsTileToStandingCoordsTile
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4c18
+
+TeleportFrom: ; 4c18
+ call Field1cAnonymousJumptable
+; anonymous dw
+ dw .InitSpin
+ dw .DoSpin
+ dw .InitSpinRise
+ dw .DoSpinRise
+; 4c23
+
+.InitSpin:
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], 16
+ call IncrementObjectStructField1c
+.DoSpin:
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_SPIN
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ call IncrementObjectStructField1c
+ ret
+
+.InitSpinRise:
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_1F
+ add hl, bc
+ ld [hl], $10
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], 16
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ res 3, [hl]
+ call IncrementObjectStructField1c
+.DoSpinRise:
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_SPIN
+ ld hl, OBJECT_1F
+ add hl, bc
+ inc [hl]
+ ld a, [hl]
+ ld d, $60
+ call Sine
+ ld a, h
+ sub $60
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4c89
+
+TeleportTo: ; 4c89
+ call Field1cAnonymousJumptable
+; anonymous dw
+ dw .InitWait
+ dw .DoWait
+ dw .InitDescent
+ dw .DoDescent
+ dw .InitFinalSpin
+ dw .DoFinalSpin
+ dw .FinishStep
+; 4c9a
+
+.InitWait:
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_00
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], 16
+ call IncrementObjectStructField1c
+ ret
+; 4caa
+
+.DoWait:
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ call IncrementObjectStructField1c
+.InitDescent:
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_1F
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], 16
+ call IncrementObjectStructField1c
+ ret
+; 4cc9
+
+.DoDescent:
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_SPIN
+ ld hl, OBJECT_1F
+ add hl, bc
+ inc [hl]
+ ld a, [hl]
+ ld d, $60
+ call Sine
+ ld a, h
+ sub $60
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ call IncrementObjectStructField1c
+.InitFinalSpin:
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], 16
+ call IncrementObjectStructField1c
+ ret
+; 4cf5
+
+.DoFinalSpin:
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_SPIN
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+.FinishStep:
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4d14
+
+Skyfall: ; 4d14
+ call Field1cAnonymousJumptable
+; anonymous dw
+ dw .Init
+ dw .Step
+ dw .Fall
+ dw .Finish
+; 4d1f
+
+.Init:
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_00
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], 16
+ call IncrementObjectStructField1c
+.Step:
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STEP
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_1F
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], 16
+ call IncrementObjectStructField1c
+.Fall:
+ ld hl, OBJECT_1F
+ add hl, bc
+ inc [hl]
+ ld a, [hl]
+ ld d, $60
+ call Sine
+ ld a, h
+ sub $60
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ call IncrementObjectStructField1c
+.Finish:
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4d7e
+
+GotBiteStep: ; 4d7e
+ call Field1cAnonymousJumptable
+; anonymous dw
+ dw .Init
+ dw .Run
+; 4d85
+
+.Init:
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], 8
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], 0
+ call IncrementObjectStructField1c
+.Run:
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld a, [hl]
+ xor 1
+ ld [hl], a
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4daf
+
+RockSmashStep: ; 4daf
+ call .Step
+ jp WaitStep_InPlace
+; 4db5
+
+.Step:
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld a, [hl]
+ and %00000001
+ ld a, OBJECT_ACTION_STAND
+ jr z, .yes
+ ld a, OBJECT_ACTION_00
+.yes
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], a
+ ret
+; 4dc8
+
+ReturnDigStep: ; 4dc8
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld a, [hl]
+ and %00000001
+ ld a, OBJECT_ACTION_SPIN
+ jr z, .yes
+ ld a, OBJECT_ACTION_SPIN_FLICKER
+.yes
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], a
+ jp WaitStep_InPlace
+; 4ddd
+
+StepType03: ; 4ddd
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4df0
+
+StepType18: ; 4df0
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ jp DeleteMapObject
+; 4dff
+
+StepTypeBump: ; 4dff
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4e0c
+
+StepType05: ; 4e0c
+ call Field1cAnonymousJumptable
+; anonymous dw
+ dw .Reset
+ dw StepType04
+
+.Reset:
+ call RestoreDefaultMovement
+ call GetInitialFacing
+ ld hl, OBJECT_FACING
+ add hl, bc
+ ld [hl], a
+ call IncrementObjectStructField1c
+StepType04: ; 4e21
+ call Stubbed_Function4fb2
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ret
+; 4e2b
+
+NPCStep: ; 4e2b
+ call Stubbed_Function4fb2
+ call AddStepVector
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ call CopyNextCoordsTileToStandingCoordsTile
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4e47
+
+StepType07: ; 4e47
+ call AddStepVector
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ call CopyNextCoordsTileToStandingCoordsTile
+ jp RandomStepDuration_Slow
+; 4e56
+
+PlayerStep: ; 4e56
+; AnimateStep?
+ call Field1cAnonymousJumptable
+; anonymous dw
+ dw .init
+ dw .step
+
+.init
+ ld hl, wPlayerStepFlags
+ set 7, [hl]
+ call IncrementObjectStructField1c
+.step
+ call UpdatePlayerStep
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ ld hl, wPlayerStepFlags
+ set 6, [hl]
+ call CopyNextCoordsTileToStandingCoordsTile
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4e83
+
+PlayerOrNPCTurnStep: ; 4e83
+ call Field1cAnonymousJumptable
+; anonymous dw
+ dw .init1
+ dw .step1
+ dw .init2
+ dw .step2
+
+.init1
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld a, [hl]
+ ld [hl], 2
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], 2
+ call IncrementObjectStructField1c
+.step1
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ call IncrementObjectStructField1c
+.init2
+ ld hl, OBJECT_1D ; new facing
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_FACING
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], 2
+ call IncrementObjectStructField1c
+.step2
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4ecd
+
+StepType0f: ; 4ecd
+ call AddStepVector
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ push bc
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ ld hl, OBJECT_MAP_OBJECT_INDEX
+ add hl, bc
+ ld a, [hl]
+ ld b, a
+ farcall CopyDECoordsToMapObject
+ pop bc
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ res 2, [hl]
+ call CopyNextCoordsTileToStandingCoordsTile
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4f04
+
+StepTypeTrackingObject: ; 4f04
+ ld hl, OBJECT_1D
+ add hl, bc
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ld hl, OBJECT_SPRITE
+ add hl, de
+ ld a, [hl]
+ and a
+ jr z, .nope
+ ld hl, OBJECT_SPRITE_X
+ add hl, de
+ ld a, [hl]
+ ld hl, OBJECT_SPRITE_X
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_SPRITE_Y
+ add hl, de
+ ld a, [hl]
+ ld hl, OBJECT_SPRITE_Y
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld a, [hl]
+ and a
+ ret z
+ dec [hl]
+ ret nz
+.nope
+ jp DeleteMapObject
+; 4f33
+
+StepType14: ; 4f33
+StepType15: ; 4f33
+ call Field1cAnonymousJumptable
+; anonymous dw
+ dw .Init
+ dw .Run
+
+.Init:
+ xor a
+ ld hl, OBJECT_1D
+ add hl, bc
+ ld [hl], a
+ call IncrementObjectStructField1c
+.Run:
+ ld hl, OBJECT_1D
+ add hl, bc
+ ld d, [hl]
+ ld a, [wPlayerStepVectorY]
+ sub d
+ ld [wPlayerStepVectorY], a
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ jr z, .ok
+ ld a, [hl]
+ call .GetSign
+ ld hl, OBJECT_1D
+ add hl, bc
+ ld [hl], a
+ ld d, a
+ ld a, [wPlayerStepVectorY]
+ add d
+ ld [wPlayerStepVectorY], a
+ ret
+
+.ok
+ call DeleteMapObject
+ ret
+
+.GetSign:
+ ld hl, OBJECT_1E
+ add hl, bc
+ and 1
+ ld a, [hl]
+ ret z
+ cpl
+ inc a
+ ret
+; 4f77
+
+StepType16: ; 4f77
+ call Field1cAnonymousJumptable ; ????
+; 4f7a
+StepType17: ; 4f7a
+ call Field1cAnonymousJumptable
+; anonymous dw
+ dw .null
+ dw .null
+ dw .null
+.null
+; 4f83
+
+SkyfallTop: ; 4f83
+ call Field1cAnonymousJumptable
+; anonymous dw
+ dw .Init
+ dw .Run
+
+.Init:
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_SKYFALL
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], 16
+ call IncrementObjectStructField1c
+
+.Run:
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ dec [hl]
+ ret nz
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], $60
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld [hl], 0
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 4fb2
+
+Stubbed_Function4fb2:
+ ret
+ ld hl, OBJECT_1D
+ add hl, bc
+ inc [hl]
+ ld a, [hl]
+ srl a
+ srl a
+ and %00000111
+ ld l, a
+ ld h, 0
+ ld de, .y
+ add hl, de
+ ld a, [hl]
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], a
+ ret
+
+.y ; 4fcd
+ db 0, -1, -2, -3, -4, -3, -2, -1
+; 4fd5
+UpdateJumpPosition: ; 4fd5
+ call GetStepVector
+ ld a, h
+ ld hl, OBJECT_1F
+ add hl, bc
+ ld e, [hl]
+ add e
+ ld [hl], a
+ nop
+ srl e
+ ld d, 0
+ ld hl, .y
+ add hl, de
+ ld a, [hl]
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld [hl], a
+ ret
+
+.y ; 4ff0
+ db -4, -6, -8, -10, -11, -12, -12, -12
+ db -11, -10, -9, -8, -6, -4, 0, 0
+; 5000
+Function5000: ; unscripted?
+; copy [wPlayerNextMovement] to [wPlayerMovement]
+ ld a, [wPlayerNextMovement]
+ ld hl, wPlayerMovement
+ ld [hl], a
+; load [wPlayerNextMovement] with movement_step_sleep
+ ld a, movement_step_sleep
+ ld [wPlayerNextMovement], a
+; recover the previous value of [wPlayerNextMovement]
+ ld a, [hl]
+ ret
+; 500e
+
+GetMovementByte:
+ ld hl, wMovementDataPointer
+ call _GetMovementByte
+ ret
+; 5015
+
+Function5015: ; 5015
+ ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+ add hl, bc
+ ld e, [hl]
+ inc [hl]
+ ld d, 0
+ ld hl, wc2e2
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ add hl, de
+ ld a, [hl]
+ ret
+; 5026
+
+Function5026: ; 5026
+ ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+ add hl, bc
+ ld e, [hl]
+ inc [hl]
+ ld d, 0
+ ld hl, wc2e6
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ add hl, de
+ ld a, [hl]
+ ret
+; 5037
+
+_GetMovementObject: ; 5037
+ ld hl, GetMovementObject
+ jp HandleMovementData
+; 503d
+
+GetMovementObject: ; 503d
+ ld a, [wMovementObject]
+ ret
+; 5041
+
+HandleMovementData: ; 5041
+ call .StorePointer
+.loop
+ xor a
+ ld [wMovementByteWasControlSwitch], a
+ call JumpMovementPointer
+ call DoMovementFunction
+ ld a, [wMovementByteWasControlSwitch]
+ and a
+ jr nz, .loop
+ ret
+
+.StorePointer:
+ ld a, l
+ ld [wMovementPointer], a
+ ld a, h
+ ld [wMovementPointer + 1], a
+ ret
+; 505e
+
+JumpMovementPointer: ; 505e
+ ld hl, wMovementPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+; 5065
+
+ContinueReadingMovement: ; 5065
+ ld a, 1
+ ld [wMovementByteWasControlSwitch], a
+ ret
+; 506b
+
+DoMovementFunction: ; 506b
+ push af
+ call ApplyMovementToFollower
+ pop af
+ ld hl, MovementPointers
+ rst JumpTable
+ ret
+; 5075
+
+INCLUDE "engine/overworld/movement.asm"
+; 54b8
+
+ApplyMovementToFollower: ; 54b8
+ ld e, a
+ ld a, [wObjectFollow_Follower]
+ cp -1
+ ret z
+ ld a, [wObjectFollow_Leader]
+ ld d, a
+ ld a, [hMapObjectIndexBuffer]
+ cp d
+ ret nz
+ ld a, e
+ cp movement_step_sleep
+ ret z
+ cp movement_step_end
+ ret z
+ cp movement_step_4b
+ ret z
+ cp movement_step_bump
+ ret z
+ cp movement_slow_step
+ ret c
+ push af
+ ld hl, wFollowerMovementQueueLength
+ inc [hl]
+ ld e, [hl]
+ ld d, 0
+ ld hl, wFollowMovementQueue
+ add hl, de
+ pop af
+ ld [hl], a
+ ret
+; 54e6
+
+GetFollowerNextMovementByte: ; 54e6
+ ld hl, wFollowerMovementQueueLength
+ ld a, [hl]
+ and a
+ jr z, .done
+ cp -1
+ jr z, .done
+ dec [hl]
+ ld e, a
+ ld d, 0
+ ld hl, wFollowMovementQueue
+ add hl, de
+ inc e
+ ld a, -1
+.loop
+ ld d, [hl]
+ ld [hld], a
+ ld a, d
+ dec e
+ jr nz, .loop
+ ret
+
+.done
+ call .CancelFollowIfLeaderMissing
+ ret c
+ ld a, movement_step_sleep
+ ret
+
+.CancelFollowIfLeaderMissing:
+ ld a, [wObjectFollow_Leader]
+ cp -1
+ jr z, .nope
+ push bc
+ call GetObjectStruct
+ ld hl, OBJECT_SPRITE
+ add hl, bc
+ ld a, [hl]
+ pop bc
+ and a
+ jr z, .nope
+ and a
+ ret
+
+.nope
+ ld a, -1
+ ld [wObjectFollow_Follower], a
+ ld a, movement_step_end
+ scf
+ ret
+; 5529
+
+SpawnShadow: ; 5529
+ push bc
+ ld de, .ShadowObject
+ call CopyTempObjectData
+ call InitTempObject
+ pop bc
+ ret
+
+.ShadowObject:
+ ; vtile, palette, movement
+ db $00, PAL_OW_SILVER, SPRITEMOVEDATA_SHADOW
+; 5538
+
+SpawnStrengthBoulderDust: ; 5538
+ push bc
+ ld de, .BoulderDustObject
+ call CopyTempObjectData
+ call InitTempObject
+ pop bc
+ ret
+
+.BoulderDustObject:
+ db $00, PAL_OW_SILVER, SPRITEMOVEDATA_BOULDERDUST
+; 5547
+
+SpawnEmote: ; 5547
+ push bc
+ ld de, .EmoteObject
+ call CopyTempObjectData
+ call InitTempObject
+ pop bc
+ ret
+
+.EmoteObject:
+ db $00, PAL_OW_SILVER, SPRITEMOVEDATA_EMOTE
+; 5556
+
+ShakeGrass: ; 5556
+ push bc
+ ld de, .data_5562
+ call CopyTempObjectData
+ call InitTempObject
+ pop bc
+ ret
+
+.data_5562
+ db $00, PAL_OW_TREE, SPRITEMOVEDATA_GRASS
+; 5565
+
+ShakeScreen: ; 5565
+ push bc
+ push af
+ ld de, .ScreenShakeObject
+ call CopyTempObjectData
+ pop af
+ ld [wTempObjectCopyRange], a
+ call InitTempObject
+ pop bc
+ ret
+
+.ScreenShakeObject:
+ db $00, PAL_OW_SILVER, SPRITEMOVEDATA_SCREENSHAKE
+; 5579
+DespawnEmote: ; 5579
+ push bc
+ ld a, [hMapObjectIndexBuffer]
+ ld c, a
+ call .DeleteEmote
+ pop bc
+ ret
+
+.DeleteEmote:
+ ld de, wObjectStructs
+ ld a, NUM_OBJECT_STRUCTS
+.loop
+ push af
+ ld hl, OBJECT_FLAGS1
+ add hl, de
+ bit EMOTE_OBJECT, [hl]
+ jr z, .next
+ ld hl, OBJECT_SPRITE
+ add hl, de
+ ld a, [hl]
+ and a
+ jr z, .next
+ push bc
+ xor a
+ ld bc, OBJECT_STRUCT_LENGTH
+ call ByteFill
+ pop bc
+.next
+ ld hl, OBJECT_STRUCT_LENGTH
+ add hl, de
+ ld d, h
+ ld e, l
+ pop af
+ dec a
+ jr nz, .loop
+ ret
+; 55ac
+
+InitTempObject: ; 55ac
+ call FindFirstEmptyObjectStruct
+ ret nc
+ ld d, h
+ ld e, l
+ farcall CopyTempObjectToObjectStruct
+ ret
+; 55b9
+
+CopyTempObjectData: ; 55b9
+; load into wTempObjectCopy:
+; -1, -1, [de], [de + 1], [de + 2], [hMapObjectIndexBuffer], [NextMapX], [NextMapY], -1
+; This spawns the object at the same place as whichever object is loaded into bc.
+ ld hl, wTempObjectCopyMapObjectIndex
+ ld [hl], -1
+ inc hl
+ ld [hl], -1
+ inc hl
+ ld a, [de]
+ inc de
+ ld [hli], a
+ ld a, [de]
+ inc de
+ ld [hli], a
+ ld a, [de]
+ ld [hli], a
+ ld a, [hMapObjectIndexBuffer]
+ ld [hli], a
+ push hl
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ pop hl
+ ld [hl], d
+ inc hl
+ ld [hl], e
+ inc hl
+ ld [hl], -1
+ ret
+; 55e0
+
+Function55e0:: ; 55e0
+ ld a, [wVramState]
+ bit 0, a
+ ret z
+ ld bc, wObjectStructs
+ xor a
+.loop
+ ld [hMapObjectIndexBuffer], a
+ call DoesObjectHaveASprite
+ jr z, .ok
+ call Function565c
+.ok
+ ld hl, OBJECT_STRUCT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ ld a, [hMapObjectIndexBuffer]
+ inc a
+ cp NUM_OBJECT_STRUCTS
+ jr nz, .loop
+ ret
+; 5602
+
+Function5602: ; 5602, called at battle start
+ call Function5645 ; clear sprites
+ ld a, PLAYER
+ call Function5629 ; respawn player
+ ld a, [wBattleScriptFlags]
+ bit 7, a
+ jr z, .ok
+ ld a, [hLastTalked]
+ and a
+ jr z, .ok
+ call Function5629 ; respawn opponent
+.ok
+ call _UpdateSprites
+ ret
+; 561d
+
+Function561d: ; 561d
+ call Function5645 ; clear sprites
+ ld a, PLAYER
+ call Function5629 ; respawn player
+ call _UpdateSprites
+ ret
+; 5629
+
+Function5629: ; 5629
+ cp NUM_OBJECTS
+ ret nc
+ call GetMapObject
+ ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+ add hl, bc
+ ld a, [hl]
+ cp -1
+ ret z
+ cp NUM_OBJECT_STRUCTS
+ ret nc
+ call GetObjectStruct
+ call DoesObjectHaveASprite
+ ret z
+ call Function5673
+ ret
+; 5645
+
+Function5645: ; 5645
+ xor a
+ ld bc, wObjectStructs
+.loop
+ ld [hMapObjectIndexBuffer], a
+ call SetFacing_Standing
+ ld hl, OBJECT_STRUCT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ ld a, [hMapObjectIndexBuffer]
+ inc a
+ cp NUM_OBJECT_STRUCTS
+ jr nz, .loop
+ ret
+; 565c
+
+Function565c: ; 565c
+ push bc
+ call Function56cd
+ pop bc
+ jr c, SetFacing_Standing
+ call Function56a3
+ jr c, SetFacing_Standing
+ call Function5688
+ farcall Function4440
+ xor a
+ ret
+; 5673
+
+Function5673: ; 5673
+ call Function56a3
+ jr c, SetFacing_Standing
+ farcall Function4440 ; no need to farcall
+ xor a
+ ret
+; 5680
+
+SetFacing_Standing: ; 5680
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld [hl], STANDING
+ scf
+ ret
+; 5688
+
+Function5688: ; 5688
+ push bc
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ call GetCoordTile
+ pop bc
+ ld hl, OBJECT_NEXT_TILE
+ add hl, bc
+ ld [hl], a
+ farcall UpdateTallGrassFlags ; no need to farcall
+ ret
+; 56a3
+
+Function56a3: ; 56a3
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ inc d
+ inc e
+ ld a, [wXCoord]
+ cp d
+ jr z, .equal_x
+ jr nc, .nope
+ add MAPOBJECT_SCREEN_WIDTH - 1
+ cp d
+ jr c, .nope
+.equal_x
+ ld a, [wYCoord]
+ cp e
+ jr z, .equal_y
+ jr nc, .nope
+ add MAPOBJECT_SCREEN_HEIGHT - 1
+ cp e
+ jr c, .nope
+.equal_y
+ xor a
+ ret
+
+.nope
+ scf
+ ret
+; 56cd
+
+Function56cd: ; 56cd
+ ld a, [wPlayerBGMapOffsetX]
+ ld d, a
+ ld hl, OBJECT_SPRITE_X_OFFSET
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_SPRITE_X
+ add hl, bc
+ add [hl]
+ add d
+ cp $f0
+ jr nc, .ok1
+ cp $a0
+ jp nc, .nope
+.ok1
+ and %00000111
+ ld d, 2
+ cp 4
+ jr c, .ok2
+ ld d, 3
+.ok2
+ ld a, [hl]
+ srl a
+ srl a
+ srl a
+ cp SCREEN_WIDTH
+ jr c, .ok3
+ sub BG_MAP_WIDTH
+.ok3
+ ld [hUsedSpriteIndex], a
+ ld a, [wPlayerBGMapOffsetY]
+ ld e, a
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_SPRITE_Y
+ add hl, bc
+ add [hl]
+ add e
+ cp $f0
+ jr nc, .ok4
+ cp $90
+ jr nc, .nope
+.ok4
+ and %00000111
+ ld e, 2
+ cp 4
+ jr c, .ok5
+ ld e, 3
+.ok5
+ ld a, [hl]
+ srl a
+ srl a
+ srl a
+ cp SCREEN_HEIGHT
+ jr c, .ok6
+ sub BG_MAP_HEIGHT
+.ok6
+ ld [hUsedSpriteTile], a
+ ld hl, OBJECT_PALETTE
+ add hl, bc
+ bit 7, [hl]
+ jr z, .ok7
+ ld a, d
+ add 2
+ ld d, a
+ ld a, e
+ add 2
+ ld e, a
+.ok7
+ ld a, d
+ ld [hFFBF], a
+.loop
+ ld a, [hFFBF]
+ ld d, a
+ ld a, [hUsedSpriteTile]
+ add e
+ dec a
+ cp SCREEN_HEIGHT
+ jr nc, .ok9
+ ld b, a
+.next
+ ld a, [hUsedSpriteIndex]
+ add d
+ dec a
+ cp SCREEN_WIDTH
+ jr nc, .ok8
+ ld c, a
+ push bc
+ call Coord2Tile
+ pop bc
+; NPCs disappear if standing on tile $60-$7f (or $e0-$ff),
+; since those IDs are for text characters and textbox frames.
+ ld a, [hl]
+ cp FIRST_REGULAR_TEXT_CHAR
+ jr nc, .nope
+.ok8
+ dec d
+ jr nz, .next
+.ok9
+ dec e
+ jr nz, .loop
+ and a
+ ret
+
+.nope
+ scf
+ ret
+; 576a
+
+HandleNPCStep:: ; 576a
+ call .ResetStepVector
+ call .DoStepsForAllObjects
+ ret
+
+.ResetStepVector:
+ xor a
+ ld [wPlayerStepVectorX], a
+ ld [wPlayerStepVectorY], a
+ ld [wPlayerStepFlags], a
+ ld a, -1
+ ld [wPlayerStepDirection], a
+ ret
+
+.DoStepsForAllObjects:
+ ld bc, wObjectStructs
+ xor a
+.loop
+ ld [hMapObjectIndexBuffer], a
+ call DoesObjectHaveASprite
+ jr z, .next
+ call Function437b
+.next
+ ld hl, OBJECT_STRUCT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ ld a, [hMapObjectIndexBuffer]
+ inc a
+ cp NUM_OBJECT_STRUCTS
+ jr nz, .loop
+ ret
+; 579d
+
+RefreshPlayerSprite: ; 579d
+ ld a, movement_step_sleep
+ ld [wPlayerNextMovement], a
+ ld [wPlayerMovement], a
+ xor a
+ ld [wPlayerTurningDirection], a
+ ld [wPlayerObjectStepFrame], a
+ call .TryResetPlayerAction
+ farcall CheckWarpFacingDown
+ call c, SpawnInFacingDown
+ call .SpawnInCustomFacing
+ ret
+; 57bc
+
+.TryResetPlayerAction: ; 57bc
+ ld hl, wPlayerSpriteSetupFlags
+ bit PLAYERSPRITESETUP_RESET_ACTION_F, [hl]
+ jr nz, .ok
+ ret
+
+.ok
+ ld a, OBJECT_ACTION_00
+ ld [wPlayerAction], a
+ ret
+; 57ca
+
+.SpawnInCustomFacing: ; 57ca
+ ld hl, wPlayerSpriteSetupFlags
+ bit PLAYERSPRITESETUP_CUSTOM_FACING_F, [hl]
+ ret z
+ ld a, [wPlayerSpriteSetupFlags]
+ and PLAYERSPRITESETUP_FACING_MASK
+ add a
+ add a
+ jr ContinueSpawnFacing
+; 57d9
+
+SpawnInFacingDown: ; 57d9
+ ld a, 0
+ContinueSpawnFacing: ; 57db
+ ld bc, wPlayerStruct
+ call SetSpriteDirection
+ ret
+; 57e2
+
+_SetPlayerPalette: ; 57e2
+ ld a, d
+ and %10000000
+ ret z
+ ld bc, 0 ; debug?
+ ld hl, OBJECT_FACING
+ add hl, bc
+ ld a, [hl]
+ or d
+ ld [hl], a
+ ld a, d
+ swap a
+ and %00000111
+ ld d, a
+ ld bc, wPlayerStruct
+ ld hl, OBJECT_PALETTE
+ add hl, bc
+ ld a, [hl]
+ and %11111000
+ or d
+ ld [hl], a
+ ret
+; 5803
+
+StartFollow:: ; 5803
+ push bc
+ ld a, b
+ call SetLeaderIfVisible
+ pop bc
+ ret c
+ ld a, c
+ call SetFollowerIfVisible
+ farcall QueueFollowerFirstStep
+ ret
+; 5815
+
+SetLeaderIfVisible: ; 5815
+ call CheckObjectVisibility
+ ret c
+ ld a, [hObjectStructIndexBuffer]
+ ld [wObjectFollow_Leader], a
+ ret
+; 581f
+
+StopFollow:: ; 581f
+ call ResetLeader
+ call ResetFollower
+ ret
+; 5826
+
+ResetLeader: ; 5826
+ ld a, -1
+ ld [wObjectFollow_Leader], a
+ ret
+; 582c
+
+SetFollowerIfVisible: ; 582c
+ push af
+ call ResetFollower
+ pop af
+ call CheckObjectVisibility
+ ret c
+ ld hl, OBJECT_MOVEMENTTYPE
+ add hl, bc
+ ld [hl], SPRITEMOVEDATA_FOLLOWING
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_00
+ ld a, [hObjectStructIndexBuffer]
+ ld [wObjectFollow_Follower], a
+ ret
+; 5847
+
+ResetFollower: ; 5847
+ ld a, [wObjectFollow_Follower]
+ cp -1
+ ret z
+ call GetObjectStruct
+ farcall Function58e3 ; no need to bankswitch
+ ld a, -1
+ ld [wObjectFollow_Follower], a
+ ret
+; 585c
+
+SetFlagsForMovement_1:: ; 585c
+ ld a, c
+ call CheckObjectVisibility
+ ret c
+ push bc
+ call Function587a
+ pop bc
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ res 5, [hl]
+ xor a
+ ret
+; 586e
+
+Function586e: ; 586e
+ call CheckObjectVisibility
+ ret c
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ set 5, [hl]
+ xor a
+ ret
+; 587a
+
+Function587a: ; 587a
+ ld bc, wObjectStructs
+ xor a
+.loop
+ push af
+ call DoesObjectHaveASprite
+ jr z, .next
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ set 5, [hl]
+.next
+ ld hl, OBJECT_STRUCT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ pop af
+ inc a
+ cp NUM_OBJECT_STRUCTS
+ jr nz, .loop
+ ret
+; 5897
+
+_SetFlagsForMovement_2:: ; 5897
+ ld a, [wObjectFollow_Leader]
+ cp -1
+ ret z
+ push bc
+ call GetObjectStruct
+ ld hl, OBJECT_MAP_OBJECT_INDEX
+ add hl, bc
+ ld a, [hl]
+ pop bc
+ cp c
+ ret nz
+ ld a, [wObjectFollow_Follower]
+ cp -1
+ ret z
+ call GetObjectStruct
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ res 5, [hl]
+ ret
+; 58b9
+
+Function58b9:: ; 58b9
+ push bc
+ ld bc, wObjectStructs
+ xor a
+.loop
+ push af
+ call DoesObjectHaveASprite
+ jr z, .next
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ res 5, [hl]
+.next
+ ld hl, OBJECT_STRUCT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ pop af
+ inc a
+ cp NUM_OBJECT_STRUCTS
+ jr nz, .loop
+ pop bc
+ ret
+; 58d8
+
+Function58d8: ; 58d8
+ call CheckObjectVisibility
+ ret c
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ res 5, [hl]
+ ret
+; 58e3
+
+Function58e3: ; 58e3
+ ld hl, OBJECT_MAP_OBJECT_INDEX
+ add hl, bc
+ ld a, [hl]
+ cp -1
+ jp z, Function5903 ; a jr would have been appropriate here
+ push bc
+ call GetMapObject
+ ld hl, MAPOBJECT_MOVEMENT
+ add hl, bc
+ ld a, [hl]
+ pop bc
+ ld hl, OBJECT_MOVEMENTTYPE
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_00
+ ret
+; 5903
+
+Function5903: ; 5903
+ call GetSpriteDirection
+ rrca
+ rrca
+ ld e, a
+ ld d, 0
+ ld hl, .standing_movefns
+ add hl, de
+ ld a, [hl]
+ ld hl, OBJECT_MOVEMENTTYPE
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_00
+ ret
+
+.standing_movefns
+ db SPRITEMOVEDATA_STANDING_DOWN
+ db SPRITEMOVEDATA_STANDING_UP
+ db SPRITEMOVEDATA_STANDING_LEFT
+ db SPRITEMOVEDATA_STANDING_RIGHT
+; 5920
+
+_UpdateSprites:: ; 5920
+ ld a, [wVramState]
+ bit 0, a
+ ret z
+ xor a
+ ld [hUsedSpriteIndex], a
+ ld a, [hOAMUpdate]
+ push af
+ ld a, 1
+ ld [hOAMUpdate], a
+ call InitSprites
+ call .fill
+ pop af
+ ld [hOAMUpdate], a
+ ret
+
+.fill
+ ld a, [wVramState]
+ bit 1, a
+ ld b, LOW(wVirtualOAMEnd)
+ jr z, .ok
+ ld b, 28 * SPRITEOAMSTRUCT_LENGTH
+.ok
+ ld a, [hUsedSpriteIndex]
+ cp b
+ ret nc
+ ld l, a
+ ld h, HIGH(wVirtualOAM)
+ ld de, SPRITEOAMSTRUCT_LENGTH
+ ld a, b
+ ld c, SCREEN_HEIGHT_PX + 2 * TILE_WIDTH
+.loop
+ ld [hl], c ; y
+ add hl, de
+ cp l
+ jr nz, .loop
+ ret
+; 5958
+
+ApplyBGMapAnchorToObjects: ; 5958
+ push hl
+ push de
+ push bc
+ ld a, [wPlayerBGMapOffsetX]
+ ld d, a
+ ld a, [wPlayerBGMapOffsetY]
+ ld e, a
+ ld bc, wObjectStructs
+ ld a, NUM_OBJECT_STRUCTS
+.loop
+ push af
+ call DoesObjectHaveASprite
+ jr z, .skip
+ ld hl, OBJECT_SPRITE_X
+ add hl, bc
+ ld a, [hl]
+ add d
+ ld [hl], a
+ ld hl, OBJECT_SPRITE_Y
+ add hl, bc
+ ld a, [hl]
+ add e
+ ld [hl], a
+.skip
+ ld hl, OBJECT_STRUCT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ pop af
+ dec a
+ jr nz, .loop
+ xor a
+ ld [wPlayerBGMapOffsetX], a
+ ld [wPlayerBGMapOffsetY], a
+ pop bc
+ pop de
+ pop hl
+ ret
+; 5991
+
+
+PRIORITY_LOW EQU $10
+PRIORITY_NORM EQU $20
+PRIORITY_HIGH EQU $30
+
+InitSprites: ; 5991
+ call .DeterminePriorities
+ ld c, PRIORITY_HIGH
+ call .InitSpritesByPriority
+ ld c, PRIORITY_NORM
+ call .InitSpritesByPriority
+ ld c, PRIORITY_LOW
+ call .InitSpritesByPriority
+ ret
+
+.DeterminePriorities:
+ xor a
+ ld hl, wMovementPointer
+ ld bc, NUM_OBJECT_STRUCTS
+ call ByteFill
+ ld d, 0
+ ld bc, wObjectStructs
+ ld hl, wMovementPointer
+.loop
+ push hl
+ call DoesObjectHaveASprite
+ jr z, .skip
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld a, [hl]
+ cp STANDING
+ jr z, .skip
+; Define the sprite priority.
+ ld e, PRIORITY_LOW
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ bit LOW_PRIORITY, [hl]
+ jr nz, .add
+ ld e, PRIORITY_NORM
+ bit HIGH_PRIORITY, [hl]
+ jr z, .add
+ ld e, PRIORITY_HIGH
+ jr .add
+
+.skip
+ ld hl, OBJECT_STRUCT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ pop hl
+ jr .next
+
+.add
+ ld hl, OBJECT_STRUCT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ pop hl
+ ld a, d
+ or e
+ ld [hli], a
+.next
+ inc d
+ ld a, d
+ cp NUM_OBJECT_STRUCTS
+ jr nz, .loop
+ ret
+
+.InitSpritesByPriority:
+ ld hl, wMovementPointer
+.next_sprite
+ ld a, [hli]
+ ld d, a
+ and $f0
+ ret z
+ cp c
+ jr nz, .next_sprite
+ push bc
+ push hl
+ ld a, d
+ and $f
+ call .GetObjectStructPointer
+ call .InitSprite
+ pop hl
+ pop bc
+ jr .next_sprite
+
+.InitSprite:
+ ld hl, OBJECT_SPRITE_TILE
+ add hl, bc
+ ld a, [hl]
+ and %01111111
+ ld [hFFC1], a
+ xor a
+ bit 7, [hl]
+ jr nz, .skip1
+ or %00001000
+.skip1
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ ld e, [hl]
+ bit 7, e
+ jr z, .skip2
+ or %10000000
+.skip2
+ bit 4, e
+ jr z, .skip3
+ or %00010000
+.skip3
+ ld hl, OBJECT_PALETTE
+ add hl, bc
+ ld d, a
+ ld a, [hl]
+ and %00000111
+ or d
+ ld d, a
+ xor a
+ bit 3, e
+ jr z, .skip4
+ or %10000000
+.skip4
+ ld [hFFC2], a
+ ld hl, OBJECT_SPRITE_X
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_SPRITE_X_OFFSET
+ add hl, bc
+ add [hl]
+ add 8
+ ld e, a
+ ld a, [wPlayerBGMapOffsetX]
+ add e
+ ld [hFFBF], a
+ ld hl, OBJECT_SPRITE_Y
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_SPRITE_Y_OFFSET
+ add hl, bc
+ add [hl]
+ add 12
+ ld e, a
+ ld a, [wPlayerBGMapOffsetY]
+ add e
+ ld [hFFC0], a
+ ld hl, OBJECT_FACING_STEP
+ add hl, bc
+ ld a, [hl]
+ cp STANDING
+ jp z, .done
+ cp NUM_FACINGS
+ jp nc, .done
+ ld l, a
+ ld h, 0
+ add hl, hl
+ ld bc, Facings
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [hUsedSpriteIndex]
+ ld c, a
+ ld b, HIGH(wVirtualOAM)
+ ld a, [hli]
+ ld [hUsedSpriteTile], a
+ add c
+ cp LOW(wVirtualOAMEnd)
+ jr nc, .full
+.addsprite
+ ld a, [hFFC0]
+ add [hl]
+ inc hl
+ ld [bc], a ; y
+ inc c
+ ld a, [hFFBF]
+ add [hl]
+ inc hl
+ ld [bc], a ; x
+ inc c
+ ld e, [hl]
+ inc hl
+ ld a, [hFFC1]
+ bit 2, e
+ jr z, .nope1
+ xor a
+.nope1
+ add [hl]
+ inc hl
+ ld [bc], a ; tile id
+ inc c
+ ld a, e
+ bit 1, a
+ jr z, .nope2
+ ld a, [hFFC2]
+ or e
+.nope2
+ and OBP_NUM | X_FLIP | Y_FLIP | PRIORITY
+ or d
+ ld [bc], a ; attributes
+ inc c
+ ld a, [hUsedSpriteTile]
+ dec a
+ ld [hUsedSpriteTile], a
+ jr nz, .addsprite
+ ld a, c
+ ld [hUsedSpriteIndex], a
+.done
+ xor a
+ ret
+
+.full
+ scf
+ ret
+
+.GetObjectStructPointer:
+ ld c, a
+ ld b, 0
+ ld hl, .Addresses
+ add hl, bc
+ add hl, bc
+ ld c, [hl]
+ inc hl
+ ld b, [hl]
+ ret
+
+.Addresses: ; 5ace
+ dw wPlayerStruct
+ dw wObject1Struct
+ dw wObject2Struct
+ dw wObject3Struct
+ dw wObject4Struct
+ dw wObject5Struct
+ dw wObject6Struct
+ dw wObject7Struct
+ dw wObject8Struct
+ dw wObject9Struct
+ dw wObject10Struct
+ dw wObject11Struct
+ dw wObject12Struct
+; 5ae8
diff --git a/engine/overworld/map_objects_2.asm b/engine/overworld/map_objects_2.asm
new file mode 100644
index 000000000..038e2b49b
--- /dev/null
+++ b/engine/overworld/map_objects_2.asm
@@ -0,0 +1,70 @@
+LoadObjectMasks: ; 2454f
+ ld hl, wObjectMasks
+ xor a
+ ld bc, NUM_OBJECTS
+ call ByteFill
+ nop
+ ld bc, wMapObjects
+ ld de, wObjectMasks
+ xor a
+.loop
+ push af
+ push bc
+ push de
+ call GetObjectTimeMask
+ jr c, .next
+ call CheckObjectFlag
+.next
+ pop de
+ ld [de], a
+ inc de
+ pop bc
+ ld hl, OBJECT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ pop af
+ inc a
+ cp NUM_OBJECTS
+ jr nz, .loop
+ ret
+
+CheckObjectFlag: ; 2457d (9:457d)
+ ld hl, MAPOBJECT_SPRITE
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .masked
+ ld hl, MAPOBJECT_EVENT_FLAG
+ add hl, bc
+ ld a, [hli]
+ ld e, a
+ ld a, [hl]
+ ld d, a
+ cp -1
+ jr nz, .check
+ ld a, e
+ cp -1
+ jr z, .unmasked
+ jr .masked
+.check
+ ld b, CHECK_FLAG
+ call EventFlagAction
+ ld a, c
+ and a
+ jr nz, .masked
+.unmasked
+ xor a
+ ret
+
+.masked
+ ld a, -1
+ scf
+ ret
+
+GetObjectTimeMask: ; 245a7 (9:45a7)
+ call CheckObjectTime
+ ld a, -1
+ ret c
+ xor a
+ ret
diff --git a/engine/overworld/map_setup.asm b/engine/overworld/map_setup.asm
new file mode 100644
index 000000000..268574de0
--- /dev/null
+++ b/engine/overworld/map_setup.asm
@@ -0,0 +1,260 @@
+RunMapSetupScript:: ; 15363
+ ld a, [hMapEntryMethod]
+ and $f
+ dec a
+ ld c, a
+ ld b, 0
+ ld hl, MapSetupScripts
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call ReadMapSetupScript
+ ret
+; 15377
+
+INCLUDE "data/maps/setup_scripts.asm"
+
+ReadMapSetupScript: ; 1541d
+.loop
+ ld a, [hli]
+ cp -1
+ ret z
+
+ push hl
+
+ ld c, a
+ ld b, 0
+ ld hl, MapSetupCommands
+ add hl, bc
+ add hl, bc
+ add hl, bc
+
+ ; bank
+ ld b, [hl]
+ inc hl
+
+ ; address
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+
+ ; Bit 7 of the bank indicates a parameter.
+ ; This is left unused.
+ bit 7, b
+ jr z, .go
+
+ pop de
+ ld a, [de]
+ ld c, a
+ inc de
+ push de
+
+.go
+ ld a, b
+ and $7f
+ rst FarCall
+
+ pop hl
+ jr .loop
+; 15440
+
+MapSetupCommands: ; 15440
+; entries correspond to command indexes in constants/map_setup_constants.asm
+ dba EnableLCD ; 00
+ dba DisableLCD ; 01
+ dba MapSetup_Sound_Off ; 02
+ dba PlayMapMusic ; 03
+ dba RestartMapMusic ; 04
+ dba FadeToMapMusic ; 05
+ dba RotatePalettesRightMapAndMusic ; 06
+ dba EnterMapMusic ; 07
+ dba ForceMapMusic ; 08
+ dba FadeInMusic ; 09
+ dba LoadBlockData ; 0a (callback 1)
+ dba LoadNeighboringBlockData ; 0b
+ dba SaveScreen ; 0c
+ dba BufferScreen ; 0d
+ dba LoadGraphics ; 0e
+ dba LoadTileset ; 0f
+ dba LoadMapTimeOfDay ; 10
+ dba LoadMapPalettes ; 11
+ dba LoadWildMonData ; 12
+ dba RefreshMapSprites ; 13
+ dba HandleNewMap ; 14
+ dba InitCommandQueue ; 15
+ dba LoadObjectsRunCallback_02 ; 16
+ dba LoadSpawnPoint ; 17
+ dba EnterMapConnection ; 18
+ dba LoadWarpData ; 19
+ dba LoadMapAttributes ; 1a
+ dba LoadMapAttributes_SkipPeople ; 1b
+ dba ClearBGPalettes ; 1c
+ dba FadeOutPalettes ; 1d
+ dba FadeInPalettes ; 1e
+ dba GetCoordOfUpperLeftCorner ; 1f
+ dba RestoreFacingAfterWarp ; 20
+ dba SpawnInFacingDown ; 21
+ dba SpawnPlayer ; 22
+ dba RefreshPlayerCoords ; 23
+ dba DelayClearingOldSprites ; 24
+ dba DelayLoadingNewSprites ; 25
+ dba UpdateRoamMons ; 26
+ dba JumpRoamMons ; 27
+ dba FadeOldMapMusic ; 28
+ dba ActivateMapAnims ; 29
+ dba SuspendMapAnims ; 2a
+ dba RetainOldPalettes ; 2b
+ dba DontScrollText ; 2c
+ dba ReturnFromMapSetupScript ; 2d
+; 154ca
+
+
+DontScrollText: ; 154ca
+ xor a
+ ld [wDisableTextAcceleration], a
+ ret
+; 154cf
+
+ActivateMapAnims: ; 154cf
+ ld a, $1
+ ld [hMapAnims], a
+ ret
+; 154d3
+
+SuspendMapAnims: ; 154d3
+ xor a
+ ld [hMapAnims], a
+ ret
+; 154d7
+
+LoadObjectsRunCallback_02: ; 154d7
+ ld a, MAPCALLBACK_OBJECTS
+ call RunMapCallback
+ farcall LoadObjectMasks
+ farcall InitializeVisibleSprites
+ ret
+; 154ea (5:54ea)
+
+; unused
+ ret
+; 154eb
+
+DelayClearingOldSprites: ; 154eb
+ ld hl, wPlayerSpriteSetupFlags
+ set PLAYERSPRITESETUP_RESET_ACTION_F, [hl]
+ ret
+; 154f1
+
+DelayLoadingNewSprites: ; 154f1
+ ld hl, wPlayerSpriteSetupFlags
+ set PLAYERSPRITESETUP_SKIP_RELOAD_GFX_F, [hl]
+ ret
+
+CheckReplaceKrisSprite: ; 154f7
+ nop
+ call .CheckBiking
+ jr c, .ok
+ call .CheckSurfing
+ jr c, .ok
+ call .CheckSurfing2
+ jr c, .ok
+ ret
+
+.ok
+ call ReplaceKrisSprite
+ ret
+
+.CheckBiking: ; 1550c (5:550c)
+ and a
+ ld hl, wBikeFlags
+ bit BIKEFLAGS_ALWAYS_ON_BIKE_F, [hl]
+ ret z
+ ld a, PLAYER_BIKE
+ ld [wPlayerState], a
+ scf
+ ret
+
+.CheckSurfing2: ; 1551a (5:551a)
+ ld a, [wPlayerState]
+ cp PLAYER_NORMAL
+ jr z, .nope
+ cp PLAYER_SKATE
+ jr z, .nope
+ cp PLAYER_SURF
+ jr z, .surfing
+ cp PLAYER_SURF_PIKA
+ jr z, .surfing
+ call GetMapEnvironment
+ cp INDOOR
+ jr z, .checkbiking
+ cp ENVIRONMENT_5
+ jr z, .checkbiking
+ cp DUNGEON
+ jr z, .checkbiking
+ jr .nope
+.checkbiking
+ ld a, [wPlayerState]
+ cp PLAYER_BIKE
+ jr nz, .nope
+.surfing
+ ld a, PLAYER_NORMAL
+ ld [wPlayerState], a
+ scf
+ ret
+
+.nope
+ and a
+ ret
+
+.CheckSurfing: ; 1554e (5:554e)
+ call CheckOnWater
+ jr nz, .ret_nc
+ ld a, [wPlayerState]
+ cp PLAYER_SURF
+ jr z, ._surfing
+ cp PLAYER_SURF_PIKA
+ jr z, ._surfing
+ ld a, PLAYER_SURF
+ ld [wPlayerState], a
+._surfing
+ scf
+ ret
+.ret_nc
+ and a
+ ret
+; 15567
+
+FadeOldMapMusic: ; 15567
+ ld a, 6
+ call SkipMusic
+ ret
+; 1556d
+
+RetainOldPalettes: ; 1556d
+ farcall _UpdateTimePals
+ ret
+
+RotatePalettesRightMapAndMusic: ; 15574
+ ld e, 0
+ ld a, [wMusicFadeID]
+ ld d, 0
+ ld a, [wMusicFadeID + 1]
+ ld a, $4
+ ld [wMusicFade], a
+ call RotateThreePalettesRight
+ ret
+; 15587
+
+ForceMapMusic: ; 15587
+ ld a, [wPlayerState]
+ cp PLAYER_BIKE
+ jr nz, .notbiking
+ call VolumeOff
+ ld a, $88
+ ld [wMusicFade], a
+.notbiking
+ call TryRestartMapMusic
+ ret
+; 1559a
diff --git a/engine/overworld/movement.asm b/engine/overworld/movement.asm
new file mode 100644
index 000000000..3dbb0b83a
--- /dev/null
+++ b/engine/overworld/movement.asm
@@ -0,0 +1,864 @@
+MovementPointers: ; 5075
+; entries correspond to macros/scripts/movement.asm enumeration
+ dw Movement_turn_head_down ; 00
+ dw Movement_turn_head_up ; 01
+ dw Movement_turn_head_left ; 02
+ dw Movement_turn_head_right ; 03
+ dw Movement_turn_step_down ; 04
+ dw Movement_turn_step_up ; 05
+ dw Movement_turn_step_left ; 06
+ dw Movement_turn_step_right ; 07
+ dw Movement_slow_step_down ; 08
+ dw Movement_slow_step_up ; 09
+ dw Movement_slow_step_left ; 0a
+ dw Movement_slow_step_right ; 0b
+ dw Movement_step_down ; 0c
+ dw Movement_step_up ; 0d
+ dw Movement_step_left ; 0e
+ dw Movement_step_right ; 0f
+ dw Movement_big_step_down ; 10
+ dw Movement_big_step_up ; 11
+ dw Movement_big_step_left ; 12
+ dw Movement_big_step_right ; 13
+ dw Movement_slow_slide_step_down ; 14
+ dw Movement_slow_slide_step_up ; 15
+ dw Movement_slow_slide_step_left ; 16
+ dw Movement_slow_slide_step_right ; 17
+ dw Movement_slide_step_down ; 18
+ dw Movement_slide_step_up ; 19
+ dw Movement_slide_step_left ; 1a
+ dw Movement_slide_step_right ; 1b
+ dw Movement_fast_slide_step_down ; 1c
+ dw Movement_fast_slide_step_up ; 1d
+ dw Movement_fast_slide_step_left ; 1e
+ dw Movement_fast_slide_step_right ; 1f
+ dw Movement_turn_away_down ; 20
+ dw Movement_turn_away_up ; 21
+ dw Movement_turn_away_left ; 22
+ dw Movement_turn_away_right ; 23
+ dw Movement_turn_in_down ; 24
+ dw Movement_turn_in_up ; 25
+ dw Movement_turn_in_left ; 26
+ dw Movement_turn_in_right ; 27
+ dw Movement_turn_waterfall_down ; 28
+ dw Movement_turn_waterfall_up ; 29
+ dw Movement_turn_waterfall_left ; 2a
+ dw Movement_turn_waterfall_right ; 2b
+ dw Movement_slow_jump_step_down ; 2c
+ dw Movement_slow_jump_step_up ; 2d
+ dw Movement_slow_jump_step_left ; 2e
+ dw Movement_slow_jump_step_right ; 2f
+ dw Movement_jump_step_down ; 30
+ dw Movement_jump_step_up ; 31
+ dw Movement_jump_step_left ; 32
+ dw Movement_jump_step_right ; 33
+ dw Movement_fast_jump_step_down ; 34
+ dw Movement_fast_jump_step_up ; 35
+ dw Movement_fast_jump_step_left ; 36
+ dw Movement_fast_jump_step_right ; 37
+ dw Movement_remove_sliding ; 38
+ dw Movement_set_sliding ; 39
+ dw Movement_remove_fixed_facing ; 3a
+ dw Movement_fix_facing ; 3b
+ dw Movement_show_object ; 3c
+ dw Movement_hide_object ; 3d
+ dw Movement_step_sleep_1 ; 3e
+ dw Movement_step_sleep_2 ; 3f
+ dw Movement_step_sleep_3 ; 40
+ dw Movement_step_sleep_4 ; 41
+ dw Movement_step_sleep_5 ; 42
+ dw Movement_step_sleep_6 ; 43
+ dw Movement_step_sleep_7 ; 44
+ dw Movement_step_sleep_8 ; 45
+ dw Movement_step_sleep ; 46
+ dw Movement_step_end ; 47
+ dw Movement_48 ; 48
+ dw Movement_remove_object ; 49
+ dw Movement_step_loop ; 4a
+ dw Movement_4b ; 4b
+ dw Movement_teleport_from ; 4c
+ dw Movement_teleport_to ; 4d
+ dw Movement_skyfall ; 4e
+ dw Movement_step_dig ; 4f
+ dw Movement_step_bump ; 50
+ dw Movement_fish_got_bite ; 51
+ dw Movement_fish_cast_rod ; 52
+ dw Movement_hide_emote ; 53
+ dw Movement_show_emote ; 54
+ dw Movement_step_shake ; 55
+ dw Movement_tree_shake ; 56
+ dw Movement_rock_smash ; 57
+ dw Movement_return_dig ; 58
+ dw Movement_skyfall_top ; 59
+; 5129
+
+
+Movement_teleport_from: ; 5129
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_TELEPORT_FROM
+ ret
+; 5130
+
+Movement_teleport_to: ; 5130
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_TELEPORT_TO
+ ret
+; 5137
+
+Movement_skyfall: ; 5137
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SKYFALL
+ ret
+; 513e
+
+Movement_skyfall_top: ; 513e
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SKYFALL_TOP
+ ret
+; 5145
+
+Movement_step_dig: ; 5145
+ call GetSpriteDirection
+ rlca
+ rlca
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_SPIN
+ call JumpMovementPointer
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_03
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ret
+; 516a
+
+Movement_return_dig: ; 516a
+ call GetSpriteDirection
+ rlca
+ rlca
+ ld hl, OBJECT_STEP_FRAME
+ add hl, bc
+ ld [hl], a
+ call JumpMovementPointer
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_RETURN_DIG
+ ret
+; 5189
+
+Movement_fish_got_bite: ; 5189
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_FISHING
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_GOT_BITE
+ ret
+; 5196
+
+Movement_rock_smash: ; 5196
+ call JumpMovementPointer
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STAND
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_ROCK_SMASH
+ ret
+; 51ab
+
+Movement_fish_cast_rod: ; 51ab
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_FISHING
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 51b8
+
+Movement_step_loop: ; 51b8
+ ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+ add hl, bc
+ ld [hl], $0
+ jp ContinueReadingMovement
+; 51c1
+
+Movement_step_end: ; 51c1
+ call RestoreDefaultMovement
+ ld hl, OBJECT_MOVEMENTTYPE
+ add hl, bc
+ ld [hl], a
+
+ ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+ add hl, bc
+ ld [hl], $0
+
+ ld hl, wVramState
+ res 7, [hl]
+
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_SLEEP
+ ret
+; 51db
+
+Movement_48: ; 51db
+ call RestoreDefaultMovement
+ ld hl, OBJECT_MOVEMENTTYPE
+ add hl, bc
+ ld [hl], a
+
+ ld hl, OBJECT_MOVEMENT_BYTE_INDEX
+ add hl, bc
+ ld [hl], $0
+
+ call JumpMovementPointer
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_03
+
+ ld hl, wVramState
+ res 7, [hl]
+ ret
+; 51fd
+
+Movement_remove_object: ; 51fd
+ call DeleteMapObject
+ ld hl, wObjectFollow_Leader
+ ld a, [hMapObjectIndexBuffer]
+ cp [hl]
+ jr nz, .not_leading
+ ld [hl], -1
+
+.not_leading
+ ld hl, wVramState
+ res 7, [hl]
+ ret
+; 5210
+
+Movement_4b: ; 5210
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STAND
+
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_04
+
+ ld hl, wVramState
+ res 7, [hl]
+ ret
+; 5222
+
+Movement_step_sleep_1: ; 5222
+ ld a, 1
+ jr Movement_step_sleep_common
+
+Movement_step_sleep_2: ; 5226
+ ld a, 2
+ jr Movement_step_sleep_common
+
+Movement_step_sleep_3: ; 522a
+ ld a, 3
+ jr Movement_step_sleep_common
+
+Movement_step_sleep_4: ; 522e
+ ld a, 4
+ jr Movement_step_sleep_common
+
+Movement_step_sleep_5: ; 5232
+ ld a, 5
+ jr Movement_step_sleep_common
+
+Movement_step_sleep_6: ; 5236
+ ld a, 6
+ jr Movement_step_sleep_common
+
+Movement_step_sleep_7: ; 523a
+ ld a, 7
+ jr Movement_step_sleep_common
+
+Movement_step_sleep_8: ; 523e
+ ld a, 8
+ jr Movement_step_sleep_common
+
+Movement_step_sleep: ; 5242
+; parameters:
+; duration (DecimalParam)
+
+ call JumpMovementPointer
+ jr Movement_step_sleep_common
+
+Movement_step_sleep_common: ; 5247
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_03
+
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STAND
+
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ret
+; 525f
+
+Movement_step_bump: ; 525f
+ ld a, 1
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_BUMP
+
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_BUMP
+
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ret
+; 5279
+
+Movement_tree_shake: ; 5279
+ ld a, 24
+ ld hl, OBJECT_STEP_DURATION
+ add hl, bc
+ ld [hl], a
+
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_03
+
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_WEIRD_TREE
+
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ret
+; 5293
+
+Movement_remove_sliding: ; 5293
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ res SLIDING, [hl]
+ jp ContinueReadingMovement
+; 529c
+
+Movement_set_sliding: ; 529c
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ set SLIDING, [hl]
+ jp ContinueReadingMovement
+; 52a5
+
+Movement_remove_fixed_facing: ; 52a5
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ res FIXED_FACING, [hl]
+ jp ContinueReadingMovement
+; 52ae
+
+Movement_fix_facing: ; 52ae
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ set FIXED_FACING, [hl]
+ jp ContinueReadingMovement
+; 52b7
+
+Movement_show_object: ; 52b7
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ res INVISIBLE, [hl]
+ jp ContinueReadingMovement
+; 52c0
+
+Movement_hide_object: ; 52c0
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ set INVISIBLE, [hl]
+ jp ContinueReadingMovement
+; 52c9
+
+Movement_hide_emote: ; 52c9
+ call DespawnEmote
+ jp ContinueReadingMovement
+; 52cf
+
+Movement_show_emote: ; 52cf
+ call SpawnEmote
+ jp ContinueReadingMovement
+; 52d5
+
+Movement_step_shake: ; 52d5
+; parameters:
+; displacement (DecimalParam)
+
+ call JumpMovementPointer
+ call ShakeScreen
+ jp ContinueReadingMovement
+; 52de
+
+Movement_turn_head_down: ; 52de
+ ld a, OW_DOWN
+ jr TurnHead
+
+Movement_turn_head_up: ; 52e2
+ ld a, OW_UP
+ jr TurnHead
+
+Movement_turn_head_left: ; 52e6
+ ld a, OW_LEFT
+ jr TurnHead
+
+Movement_turn_head_right: ; 52ea
+ ld a, OW_RIGHT
+ jr TurnHead
+
+TurnHead: ; 52ee
+ ld hl, OBJECT_FACING
+ add hl, bc
+ ld [hl], a
+
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STAND
+
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld [hl], STANDING
+ ret
+; 5300
+
+Movement_slow_step_down: ; 5300
+ ld a, STEP_SLOW << 2 | DOWN
+ jp NormalStep
+; 5305
+
+Movement_slow_step_up: ; 5305
+ ld a, STEP_SLOW << 2 | UP
+ jp NormalStep
+; 530a
+
+Movement_slow_step_left: ; 530a
+ ld a, STEP_SLOW << 2 | LEFT
+ jp NormalStep
+; 530f
+
+Movement_slow_step_right: ; 530f
+ ld a, STEP_SLOW << 2 | RIGHT
+ jp NormalStep
+; 5314
+
+Movement_step_down: ; 5314
+ ld a, STEP_WALK << 2 | DOWN
+ jp NormalStep
+; 5319
+
+Movement_step_up: ; 5319
+ ld a, STEP_WALK << 2 | UP
+ jp NormalStep
+; 531e
+
+Movement_step_left: ; 531e
+ ld a, STEP_WALK << 2 | LEFT
+ jp NormalStep
+; 5323
+
+Movement_step_right: ; 5323
+ ld a, STEP_WALK << 2 | RIGHT
+ jp NormalStep
+; 5328
+
+Movement_big_step_down: ; 5328
+ ld a, STEP_BIKE << 2 | DOWN
+ jp NormalStep
+; 532d
+
+Movement_big_step_up: ; 532d
+ ld a, STEP_BIKE << 2 | UP
+ jp NormalStep
+; 5332
+
+Movement_big_step_left: ; 5332
+ ld a, STEP_BIKE << 2 | LEFT
+ jp NormalStep
+; 5337
+
+Movement_big_step_right: ; 5337
+ ld a, STEP_BIKE << 2 | RIGHT
+ jp NormalStep
+; 533c
+
+
+Movement_turn_away_down: ; 533c
+ ld a, STEP_SLOW << 2 | DOWN
+ jp TurningStep
+; 5341
+
+Movement_turn_away_up: ; 5341
+ ld a, STEP_SLOW << 2 | UP
+ jp TurningStep
+; 5346
+
+Movement_turn_away_left: ; 5346
+ ld a, STEP_SLOW << 2 | LEFT
+ jp TurningStep
+; 534b
+
+Movement_turn_away_right: ; 534b
+ ld a, STEP_SLOW << 2 | RIGHT
+ jp TurningStep
+; 5350
+
+Movement_turn_in_down: ; 5350
+ ld a, STEP_WALK << 2 | DOWN
+ jp TurningStep
+; 5355
+
+Movement_turn_in_up: ; 5355
+ ld a, STEP_WALK << 2 | UP
+ jp TurningStep
+; 535a
+
+Movement_turn_in_left: ; 535a
+ ld a, STEP_WALK << 2 | LEFT
+ jp TurningStep
+; 535f
+
+Movement_turn_in_right: ; 535f
+ ld a, STEP_WALK << 2 | RIGHT
+ jp TurningStep
+; 5364
+
+Movement_turn_waterfall_down: ; 5364
+ ld a, STEP_BIKE << 2 | DOWN
+ jp TurningStep
+; 5369
+
+Movement_turn_waterfall_up: ; 5369
+ ld a, STEP_BIKE << 2 | UP
+ jp TurningStep
+; 536e
+
+Movement_turn_waterfall_left: ; 536e
+ ld a, STEP_BIKE << 2 | LEFT
+ jp TurningStep
+; 5373
+
+Movement_turn_waterfall_right: ; 5373
+ ld a, STEP_BIKE << 2 | RIGHT
+ jp TurningStep
+; 5378
+
+
+Movement_slow_slide_step_down: ; 5378
+ ld a, STEP_SLOW << 2 | DOWN
+ jp SlideStep
+; 537d
+
+Movement_slow_slide_step_up: ; 537d
+ ld a, STEP_SLOW << 2 | UP
+ jp SlideStep
+; 5382
+
+Movement_slow_slide_step_left: ; 5382
+ ld a, STEP_SLOW << 2 | LEFT
+ jp SlideStep
+; 5387
+
+Movement_slow_slide_step_right: ; 5387
+ ld a, STEP_SLOW << 2 | RIGHT
+ jp SlideStep
+; 538c
+
+Movement_slide_step_down: ; 538c
+ ld a, STEP_WALK << 2 | DOWN
+ jp SlideStep
+; 5391
+
+Movement_slide_step_up: ; 5391
+ ld a, STEP_WALK << 2 | UP
+ jp SlideStep
+; 5396
+
+Movement_slide_step_left: ; 5396
+ ld a, STEP_WALK << 2 | LEFT
+ jp SlideStep
+; 539b
+
+Movement_slide_step_right: ; 539b
+ ld a, STEP_WALK << 2 | RIGHT
+ jp SlideStep
+; 53a0
+
+Movement_fast_slide_step_down: ; 53a0
+ ld a, STEP_BIKE << 2 | DOWN
+ jp SlideStep
+; 53a5
+
+Movement_fast_slide_step_up: ; 53a5
+ ld a, STEP_BIKE << 2 | UP
+ jp SlideStep
+; 53aa
+
+Movement_fast_slide_step_left: ; 53aa
+ ld a, STEP_BIKE << 2 | LEFT
+ jp SlideStep
+; 53af
+
+Movement_fast_slide_step_right: ; 53af
+ ld a, STEP_BIKE << 2 | RIGHT
+ jp SlideStep
+; 53b4
+
+
+Movement_slow_jump_step_down: ; 53b4
+ ld a, STEP_SLOW << 2 | DOWN
+ jp JumpStep
+; 53b9
+
+Movement_slow_jump_step_up: ; 53b9
+ ld a, STEP_SLOW << 2 | UP
+ jp JumpStep
+; 53be
+
+Movement_slow_jump_step_left: ; 53be
+ ld a, STEP_SLOW << 2 | LEFT
+ jp JumpStep
+; 53c3
+
+Movement_slow_jump_step_right: ; 53c3
+ ld a, STEP_SLOW << 2 | RIGHT
+ jp JumpStep
+; 53c8
+
+Movement_jump_step_down: ; 53c8
+ ld a, STEP_WALK << 2 | DOWN
+ jp JumpStep
+; 53cd
+
+Movement_jump_step_up: ; 53cd
+ ld a, STEP_WALK << 2 | UP
+ jp JumpStep
+; 53d2
+
+Movement_jump_step_left: ; 53d2
+ ld a, STEP_WALK << 2 | LEFT
+ jp JumpStep
+; 53d7
+
+Movement_jump_step_right: ; 53d7
+ ld a, STEP_WALK << 2 | RIGHT
+ jp JumpStep
+; 53dc
+
+Movement_fast_jump_step_down: ; 53dc
+ ld a, STEP_BIKE << 2 | DOWN
+ jp JumpStep
+; 53e1
+
+Movement_fast_jump_step_up: ; 53e1
+ ld a, STEP_BIKE << 2 | UP
+ jp JumpStep
+; 53e6
+
+Movement_fast_jump_step_left: ; 53e6
+ ld a, STEP_BIKE << 2 | LEFT
+ jp JumpStep
+; 53eb
+
+Movement_fast_jump_step_right: ; 53eb
+ ld a, STEP_BIKE << 2 | RIGHT
+ jp JumpStep
+; 53f0
+
+
+Movement_turn_step_down: ; 53f0
+ ld a, OW_DOWN
+ jr TurnStep
+
+Movement_turn_step_up: ; 53f4
+ ld a, OW_UP
+ jr TurnStep
+
+Movement_turn_step_left: ; 53f8
+ ld a, OW_LEFT
+ jr TurnStep
+
+Movement_turn_step_right: ; 53fc
+ ld a, OW_RIGHT
+ jr TurnStep
+
+TurnStep: ; 5400
+ ld hl, OBJECT_1D ; new facing
+ add hl, bc
+ ld [hl], a
+
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STEP
+
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_HALF_STEP
+ ret
+; 5412
+
+NormalStep: ; 5412
+ call InitStep
+ call UpdateTallGrassFlags
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STEP
+
+ ld hl, OBJECT_NEXT_TILE
+ add hl, bc
+ ld a, [hl]
+ call CheckSuperTallGrassTile
+ jr z, .shake_grass
+
+ call CheckGrassTile
+ jr c, .skip_grass
+
+.shake_grass
+ call ShakeGrass
+
+.skip_grass
+ ld hl, wCenteredObject
+ ld a, [hMapObjectIndexBuffer]
+ cp [hl]
+ jr z, .player
+
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_NPC_WALK
+ ret
+
+.player
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_PLAYER_WALK
+ ret
+; 5446
+
+TurningStep: ; 5446
+ call InitStep
+ call UpdateTallGrassFlags
+
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_SPIN
+
+ ld hl, wCenteredObject
+ ld a, [hMapObjectIndexBuffer]
+ cp [hl]
+ jr z, .player
+
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_NPC_WALK
+ ret
+
+.player
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_PLAYER_WALK
+ ret
+; 5468
+
+
+SlideStep: ; 5468
+ call InitStep
+ call UpdateTallGrassFlags
+
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STAND
+
+ ld hl, wCenteredObject
+ ld a, [hMapObjectIndexBuffer]
+ cp [hl]
+ jr z, .player
+
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_NPC_WALK
+ ret
+
+.player
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_PLAYER_WALK
+ ret
+; 548a
+
+
+JumpStep: ; 548a
+ call InitStep
+ ld hl, OBJECT_1F
+ add hl, bc
+ ld [hl], $0
+
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ res OVERHEAD, [hl]
+
+ ld hl, OBJECT_ACTION
+ add hl, bc
+ ld [hl], OBJECT_ACTION_STEP
+
+ call SpawnShadow
+
+ ld hl, wCenteredObject
+ ld a, [hMapObjectIndexBuffer]
+ cp [hl]
+ jr z, .player
+
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_NPC_JUMP
+ ret
+
+.player
+ ld hl, OBJECT_STEP_TYPE
+ add hl, bc
+ ld [hl], STEP_TYPE_PLAYER_JUMP
+ ret
+; 54b8
diff --git a/engine/overworld/npc_movement.asm b/engine/overworld/npc_movement.asm
new file mode 100755
index 000000000..5670935e8
--- /dev/null
+++ b/engine/overworld/npc_movement.asm
@@ -0,0 +1,573 @@
+Function6ec1: ; 6ec1
+
+ ld hl, OBJECT_PALETTE
+ add hl, bc
+ bit 5, [hl]
+ jr z, .not_bit_5
+
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ bit 4, [hl] ; lost, uncomment next line to fix
+; jr nz, .resume
+ push hl
+ push bc
+ call Function6f2c
+ pop bc
+ pop hl
+ ret c
+ jr .resume
+
+.not_bit_5
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ bit 4, [hl]
+ jr nz, .resume
+ push hl
+ push bc
+ call Function6f07
+ pop bc
+ pop hl
+ ret c
+
+.resume
+ bit 6, [hl]
+ jr nz, .bit_6
+
+ push hl
+ push bc
+ call WillObjectBumpIntoSomeoneElse
+ pop bc
+ pop hl
+ ret c
+
+.bit_6
+ bit 5, [hl]
+ jr nz, .bit_5
+ push hl
+ call HasObjectReachedMovementLimit
+ pop hl
+ ret c
+
+ push hl
+ call IsObjectMovingOffEdgeOfScreen
+ pop hl
+ ret c
+
+.bit_5
+ and a
+ ret
+; 6f07
+
+
+Function6f07: ; 6f07
+ call Function6f5f
+ ret c
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ ld hl, OBJECT_PALETTE
+ add hl, bc
+ bit OAM_PRIORITY, [hl]
+ jp nz, Function6fa1
+ ld hl, OBJECT_NEXT_TILE
+ add hl, bc
+ ld a, [hl]
+ ld d, a
+ call GetTileCollision
+ and a ; LANDTILE
+ jr z, Function6f3e
+ scf
+ ret
+; 6f2c
+
+Function6f2c: ; 6f2c
+ call Function6f5f
+ ret c
+ ld hl, OBJECT_NEXT_TILE
+ add hl, bc
+ ld a, [hl]
+ call GetTileCollision
+ cp WATERTILE
+ jr z, Function6f3e
+ scf
+ ret
+; 6f3e
+
+Function6f3e: ; 6f3e
+ ld hl, OBJECT_NEXT_TILE
+ add hl, bc
+ ld a, [hl]
+ call Function6f7f
+ ret nc
+ push af
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld a, [hl]
+ maskbits NUM_DIRECTIONS
+ ld e, a
+ ld d, 0
+ ld hl, .data_6f5b
+ add hl, de
+ pop af
+ and [hl]
+ ret z
+ scf
+ ret
+; 6f5b
+
+.data_6f5b
+ db DOWN_MASK, UP_MASK, RIGHT_MASK, LEFT_MASK
+; 6f5f
+
+Function6f5f: ; 6f5f
+ ld hl, OBJECT_STANDING_TILE
+ add hl, bc
+ ld a, [hl]
+ call Function6f7f
+ ret nc
+ push af
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ maskbits NUM_DIRECTIONS
+ ld e, a
+ ld d, 0
+ ld hl, .data_6f7b
+ add hl, de
+ pop af
+ and [hl]
+ ret z
+ scf
+ ret
+; 6f7b
+
+.data_6f7b
+ db UP_MASK, DOWN_MASK, LEFT_MASK, RIGHT_MASK
+; 6f7f
+
+Function6f7f: ; 6f7f
+ ld d, a
+ and $f0
+ cp $b0
+ jr z, .done
+ cp $c0
+ jr z, .done
+ xor a
+ ret
+
+.done
+ ld a, d
+ and 7
+ ld e, a
+ ld d, 0
+ ld hl, .data_6f99
+ add hl, de
+ ld a, [hl]
+ scf
+ ret
+; 6f99
+
+.data_6f99
+ db 8, 4, 1, 2
+ db 10, 6, 9, 5
+; 6fa1
+
+Function6fa1: ; 6fa1
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld a, [hl]
+ maskbits NUM_DIRECTIONS
+ jr z, .down
+ dec a
+ jr z, .up
+ dec a
+ jr z, .left
+ jr .right
+
+.down
+ inc e
+ push de
+ inc d
+ jr .continue
+
+.up
+ push de
+ inc d
+ jr .continue
+
+.left
+ push de
+ inc e
+ jr .continue
+
+.right
+ inc d
+ push de
+ inc e
+
+.continue
+ call GetCoordTile
+ call GetTileCollision
+ pop de
+ and a ; LANDTILE
+ jr nz, .not_land
+ call GetCoordTile
+ call GetTileCollision
+ and a ; LANDTILE
+ jr nz, .not_land
+ xor a
+ ret
+
+.not_land
+ scf
+ ret
+; 6fd9
+
+
+
+CheckFacingObject:: ; 6fd9
+
+ call GetFacingTileCoord
+
+; Double the distance for counter tiles.
+ call CheckCounterTile
+ jr nz, .asm_6ff1
+
+ ld a, [wPlayerStandingMapX]
+ sub d
+ cpl
+ inc a
+ add d
+ ld d, a
+
+ ld a, [wPlayerStandingMapY]
+ sub e
+ cpl
+ inc a
+ add e
+ ld e, a
+
+.asm_6ff1
+ ld bc, wObjectStructs ; redundant
+ ld a, 0
+ ld [hMapObjectIndexBuffer], a
+ call IsNPCAtCoord
+ ret nc
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld a, [hl]
+ cp STANDING
+ jr z, .standing
+ xor a
+ ret
+
+.standing
+ scf
+ ret
+; 7009
+
+
+WillObjectBumpIntoSomeoneElse: ; 7009
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ jr IsNPCAtCoord
+; 7015
+
+Unreferenced_Function7015:
+ ld a, [hMapObjectIndexBuffer]
+ call GetObjectStruct
+ call .CheckWillBeFacingNPC
+ call IsNPCAtCoord
+ ret
+
+.CheckWillBeFacingNPC: ; 7021
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ call GetSpriteDirection
+ and a
+ jr z, .down
+ cp OW_UP
+ jr z, .up
+ cp OW_LEFT
+ jr z, .left
+ inc d
+ ret
+
+.down
+ inc e
+ ret
+
+.up
+ dec e
+ ret
+
+.left
+ dec d
+ ret
+; 7041
+
+IsNPCAtCoord: ; 7041
+ ld bc, wObjectStructs
+ xor a
+.loop
+ ld [hObjectStructIndexBuffer], a
+ call DoesObjectHaveASprite
+ jr z, .next
+
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ bit 7, [hl]
+ jr nz, .next
+
+ ld hl, OBJECT_PALETTE
+ add hl, bc
+ bit 7, [hl]
+ jr z, .got
+
+ call Function7171
+ jr nc, .ok
+ jr .ok2
+
+.got
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ cp d
+ jr nz, .ok
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ cp e
+ jr nz, .ok
+
+.ok2
+ ld a, [hMapObjectIndexBuffer]
+ ld l, a
+ ld a, [hObjectStructIndexBuffer]
+ cp l
+ jr nz, .setcarry
+
+.ok
+ ld hl, OBJECT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ cp d
+ jr nz, .next
+ ld hl, OBJECT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ cp e
+ jr nz, .next
+ ld a, [hMapObjectIndexBuffer]
+ ld l, a
+ ld a, [hObjectStructIndexBuffer]
+ cp l
+ jr nz, .setcarry
+
+.next
+ ld hl, OBJECT_STRUCT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ ld a, [hObjectStructIndexBuffer]
+ inc a
+ cp NUM_OBJECT_STRUCTS
+ jr nz, .loop
+ and a
+ ret
+
+.setcarry
+ scf
+ ret
+; 70a4
+
+HasObjectReachedMovementLimit: ; 70a4
+ ld hl, OBJECT_RADIUS
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .nope
+ and $f
+ jr z, .check_y
+ ld e, a
+ ld d, a
+ ld hl, OBJECT_INIT_X
+ add hl, bc
+ ld a, [hl]
+ sub d
+ ld d, a
+ ld a, [hl]
+ add e
+ ld e, a
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ cp d
+ jr z, .yes
+ cp e
+ jr z, .yes
+
+.check_y
+ ld hl, OBJECT_RADIUS
+ add hl, bc
+ ld a, [hl]
+ swap a
+ and $f
+ jr z, .nope
+ ld e, a
+ ld d, a
+ ld hl, OBJECT_INIT_Y
+ add hl, bc
+ ld a, [hl]
+ sub d
+ ld d, a
+ ld a, [hl]
+ add e
+ ld e, a
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ cp d
+ jr z, .yes
+ cp e
+ jr z, .yes
+
+.nope
+ xor a
+ ret
+
+.yes
+ scf
+ ret
+; 70ed
+
+IsObjectMovingOffEdgeOfScreen: ; 70ed
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, [wXCoord]
+ cp [hl]
+ jr z, .check_y
+ jr nc, .yes
+ add $9
+ cp [hl]
+ jr c, .yes
+
+.check_y
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld a, [wYCoord]
+ cp [hl]
+ jr z, .nope
+ jr nc, .yes
+ add $8
+ cp [hl]
+ jr c, .yes
+
+.nope
+ and a
+ ret
+
+.yes
+ scf
+ ret
+; 7113
+
+Unreferenced_Function7113:
+ ld a, [wPlayerStandingMapX]
+ ld d, a
+ ld a, [wPlayerStandingMapY]
+ ld e, a
+ ld bc, wObjectStructs
+ xor a
+.loop
+ ld [hObjectStructIndexBuffer], a
+ call DoesObjectHaveASprite
+ jr z, .next
+ ld hl, OBJECT_MOVEMENTTYPE
+ add hl, bc
+ ld a, [hl]
+ cp SPRITEMOVEDATA_BIGDOLLSYM
+ jr nz, .not_snorlax
+ call Function7171
+ jr c, .yes
+ jr .next
+
+.not_snorlax
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ cp e
+ jr nz, .check_current_coords
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ cp d
+ jr nz, .check_current_coords
+ ld a, [hObjectStructIndexBuffer]
+ cp $0
+ jr z, .next
+ jr .yes
+
+.check_current_coords
+ ld hl, OBJECT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ cp e
+ jr nz, .next
+ ld hl, OBJECT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ cp d
+ jr nz, .next
+ jr .yes
+
+.next
+ ld hl, OBJECT_STRUCT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ ld a, [hObjectStructIndexBuffer]
+ inc a
+ cp NUM_OBJECT_STRUCTS
+ jr nz, .loop
+ xor a
+ ret
+
+.yes
+ scf
+ ret
+; 7171
+
+
+Function7171: ; 7171
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, d
+ sub [hl]
+ jr c, .nope
+ cp $2
+ jr nc, .nope
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld a, e
+ sub [hl]
+ jr c, .nope
+ cp $2
+ jr nc, .nope
+ scf
+ ret
+
+.nope
+ and a
+ ret
+; 718d
diff --git a/engine/overworld/overworld.asm b/engine/overworld/overworld.asm
new file mode 100755
index 000000000..381c2d89f
--- /dev/null
+++ b/engine/overworld/overworld.asm
@@ -0,0 +1,715 @@
+GetEmote2bpp: ; 1412a
+ ld a, $1
+ ld [rVBK], a
+ call Get2bpp
+ xor a
+ ld [rVBK], a
+ ret
+; 14135
+
+_ReplaceKrisSprite:: ; 14135
+ call GetPlayerSprite
+ ld a, [wUsedSprites]
+ ld [hUsedSpriteIndex], a
+ ld a, [wUsedSprites + 1]
+ ld [hUsedSpriteTile], a
+ call GetUsedSprite
+ ret
+; 14146
+
+Function14146: ; mobile
+ ld hl, wSpriteFlags
+ ld a, [hl]
+ push af
+ res 7, [hl]
+ set 6, [hl]
+ call LoadUsedSpritesGFX
+ pop af
+ ld [wSpriteFlags], a
+ ret
+; 14157
+
+Function14157: ; mobile
+ ld hl, wSpriteFlags
+ ld a, [hl]
+ push af
+ set 7, [hl]
+ res 6, [hl]
+ call LoadUsedSpritesGFX
+ pop af
+ ld [wSpriteFlags], a
+ ret
+; 14168
+
+RefreshSprites:: ; 14168
+ call .Refresh
+ call LoadUsedSpritesGFX
+ ret
+; 1416f
+
+.Refresh: ; 1416f
+ xor a
+ ld bc, wUsedSpritesEnd - wUsedSprites
+ ld hl, wUsedSprites
+ call ByteFill
+ call GetPlayerSprite
+ call AddMapSprites
+ call LoadAndSortSprites
+ ret
+; 14183
+
+GetPlayerSprite: ; 14183
+; Get Chris or Kris's sprite.
+ ld hl, ChrisStateSprites
+ ld a, [wPlayerSpriteSetupFlags]
+ bit PLAYERSPRITESETUP_FEMALE_TO_MALE_F, a
+ jr nz, .go
+ ld a, [wPlayerGender]
+ bit PLAYERGENDER_FEMALE_F, a
+ jr z, .go
+ ld hl, KrisStateSprites
+
+.go
+ ld a, [wPlayerState]
+ ld c, a
+.loop
+ ld a, [hli]
+ cp c
+ jr z, .good
+ inc hl
+ cp -1
+ jr nz, .loop
+
+; Any player state not in the array defaults to Chris's sprite.
+ xor a ; ld a, PLAYER_NORMAL
+ ld [wPlayerState], a
+ ld a, SPRITE_CHRIS
+ jr .finish
+
+.good
+ ld a, [hl]
+
+.finish
+ ld [wUsedSprites + 0], a
+ ld [wPlayerSprite], a
+ ld [wPlayerObjectSprite], a
+ ret
+
+INCLUDE "data/sprites/player_sprites.asm"
+
+
+AddMapSprites: ; 141c9
+ call GetMapEnvironment
+ call CheckOutdoorMap
+ jr z, .outdoor
+ call AddIndoorSprites
+ ret
+
+.outdoor
+ call AddOutdoorSprites
+ ret
+; 141d9
+
+
+AddIndoorSprites: ; 141d9
+ ld hl, wMap1ObjectSprite
+ ld a, 1
+.loop
+ push af
+ ld a, [hl]
+ call AddSpriteGFX
+ ld de, OBJECT_LENGTH
+ add hl, de
+ pop af
+ inc a
+ cp NUM_OBJECTS
+ jr nz, .loop
+ ret
+; 141ee
+
+
+AddOutdoorSprites: ; 141ee
+ ld a, [wMapGroup]
+ dec a
+ ld c, a
+ ld b, 0
+ ld hl, OutdoorSprites
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld c, MAX_OUTDOOR_SPRITES
+.loop
+ push bc
+ ld a, [hli]
+ call AddSpriteGFX
+ pop bc
+ dec c
+ jr nz, .loop
+ ret
+; 14209
+
+
+LoadUsedSpritesGFX: ; 14209
+ ld a, MAPCALLBACK_SPRITES
+ call RunMapCallback
+ call GetUsedSprites
+ call .LoadMiscTiles
+ ret
+; 14215
+
+.LoadMiscTiles: ; 14215
+ ld a, [wSpriteFlags]
+ bit 6, a
+ ret nz
+
+ ld c, EMOTE_SHADOW
+ farcall LoadEmote
+ call GetMapEnvironment
+ call CheckOutdoorMap
+ ld c, EMOTE_GRASS_RUSTLE
+ jr z, .outdoor
+ ld c, EMOTE_BOULDER_DUST
+.outdoor
+ farcall LoadEmote
+ ret
+; 14236
+
+
+
+SafeGetSprite: ; 14236
+ push hl
+ call GetSprite
+ pop hl
+ ret
+; 1423c
+
+GetSprite: ; 1423c
+ call GetMonSprite
+ ret c
+
+ ld hl, OverworldSprites + SPRITEDATA_ADDR
+ dec a
+ ld c, a
+ ld b, 0
+ ld a, NUM_SPRITEDATA_FIELDS
+ call AddNTimes
+ ; load the address into de
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+ ld d, a
+ ; load the length into c
+ ld a, [hli]
+ swap a
+ ld c, a
+ ; load the sprite bank into both b and h
+ ld b, [hl]
+ ld a, [hli]
+ ; load the sprite type into l
+ ld l, [hl]
+ ld h, a
+ ret
+; 14259
+
+
+GetMonSprite: ; 14259
+; Return carry if a monster sprite was loaded.
+
+ cp SPRITE_POKEMON
+ jr c, .Normal
+ cp SPRITE_DAY_CARE_MON_1
+ jr z, .BreedMon1
+ cp SPRITE_DAY_CARE_MON_2
+ jr z, .BreedMon2
+ cp SPRITE_VARS
+ jr nc, .Variable
+ jr .Icon
+
+.Normal:
+ and a
+ ret
+
+.Icon:
+ sub SPRITE_POKEMON
+ ld e, a
+ ld d, 0
+ ld hl, SpriteMons
+ add hl, de
+ ld a, [hl]
+ jr .Mon
+
+.BreedMon1
+ ld a, [wBreedMon1Species]
+ jr .Mon
+
+.BreedMon2
+ ld a, [wBreedMon2Species]
+
+.Mon:
+ ld e, a
+ and a
+ jr z, .NoBreedmon
+
+ farcall LoadOverworldMonIcon
+
+ ld l, 1
+ ld h, 0
+ scf
+ ret
+
+.Variable:
+ sub SPRITE_VARS
+ ld e, a
+ ld d, 0
+ ld hl, wVariableSprites
+ add hl, de
+ ld a, [hl]
+ and a
+ jp nz, GetMonSprite
+
+.NoBreedmon:
+ ld a, 1
+ ld l, 1
+ ld h, 0
+ and a
+ ret
+; 142a7
+
+
+_DoesSpriteHaveFacings:: ; 142a7
+; Checks to see whether we can apply a facing to a sprite.
+; Returns carry unless the sprite is a Pokemon or a Still Sprite.
+ cp SPRITE_POKEMON
+ jr nc, .only_down
+
+ push hl
+ push bc
+ ld hl, OverworldSprites + SPRITEDATA_TYPE
+ dec a
+ ld c, a
+ ld b, 0
+ ld a, NUM_SPRITEDATA_FIELDS
+ call AddNTimes
+ ld a, [hl]
+ pop bc
+ pop hl
+ cp STILL_SPRITE
+ jr nz, .only_down
+ scf
+ ret
+
+.only_down
+ and a
+ ret
+; 142c4
+
+
+_GetSpritePalette:: ; 142c4
+ ld a, c
+ call GetMonSprite
+ jr c, .is_pokemon
+
+ ld hl, OverworldSprites + SPRITEDATA_PALETTE
+ dec a
+ ld c, a
+ ld b, 0
+ ld a, NUM_SPRITEDATA_FIELDS
+ call AddNTimes
+ ld c, [hl]
+ ret
+
+.is_pokemon
+ xor a
+ ld c, a
+ ret
+; 142db
+
+
+LoadAndSortSprites: ; 142db
+ call LoadSpriteGFX
+ call SortUsedSprites
+ call ArrangeUsedSprites
+ ret
+; 142e5
+
+
+AddSpriteGFX: ; 142e5
+; Add any new sprite ids to a list of graphics to be loaded.
+; Return carry if the list is full.
+
+ push hl
+ push bc
+ ld b, a
+ ld hl, wUsedSprites + 2
+ ld c, SPRITE_GFX_LIST_CAPACITY - 1
+.loop
+ ld a, [hl]
+ cp b
+ jr z, .exists
+ and a
+ jr z, .new
+ inc hl
+ inc hl
+ dec c
+ jr nz, .loop
+
+ pop bc
+ pop hl
+ scf
+ ret
+
+.exists
+ pop bc
+ pop hl
+ and a
+ ret
+
+.new
+ ld [hl], b
+ pop bc
+ pop hl
+ and a
+ ret
+; 14306
+
+
+LoadSpriteGFX: ; 14306
+; Bug: b is not preserved, so it's useless as a next count.
+; Uncomment the lines below to fix.
+
+ ld hl, wUsedSprites
+ ld b, SPRITE_GFX_LIST_CAPACITY
+.loop
+ ld a, [hli]
+ and a
+ jr z, .done
+ push hl
+ call .LoadSprite
+ pop hl
+ ld [hli], a
+ dec b
+ jr nz, .loop
+
+.done
+ ret
+
+.LoadSprite:
+ ; push bc
+ call GetSprite
+ ; pop bc
+ ld a, l
+ ret
+; 1431e
+
+
+SortUsedSprites: ; 1431e
+; Bubble-sort sprites by type.
+
+; Run backwards through wUsedSprites to find the last one.
+
+ ld c, SPRITE_GFX_LIST_CAPACITY
+ ld de, wUsedSprites + (SPRITE_GFX_LIST_CAPACITY - 1) * 2
+.FindLastSprite:
+ ld a, [de]
+ and a
+ jr nz, .FoundLastSprite
+ dec de
+ dec de
+ dec c
+ jr nz, .FindLastSprite
+.FoundLastSprite:
+ dec c
+ jr z, .quit
+
+; If the length of the current sprite is
+; higher than a later one, swap them.
+
+ inc de
+ ld hl, wUsedSprites + 1
+
+.CheckSprite:
+ push bc
+ push de
+ push hl
+
+.CheckFollowing:
+ ld a, [de]
+ cp [hl]
+ jr nc, .loop
+
+; Swap the two sprites.
+
+ ld b, a
+ ld a, [hl]
+ ld [hl], b
+ ld [de], a
+ dec de
+ dec hl
+ ld a, [de]
+ ld b, a
+ ld a, [hl]
+ ld [hl], b
+ ld [de], a
+ inc de
+ inc hl
+
+; Keep doing this until everything's in order.
+
+.loop
+ dec de
+ dec de
+ dec c
+ jr nz, .CheckFollowing
+
+ pop hl
+ inc hl
+ inc hl
+ pop de
+ pop bc
+ dec c
+ jr nz, .CheckSprite
+
+.quit
+ ret
+; 14355
+
+
+ArrangeUsedSprites: ; 14355
+; Get the length of each sprite and space them out in VRAM.
+; Crystal introduces a second table in VRAM bank 0.
+
+ ld hl, wUsedSprites
+ ld c, SPRITE_GFX_LIST_CAPACITY
+ ld b, 0
+.FirstTableLength:
+; Keep going until the end of the list.
+ ld a, [hli]
+ and a
+ jr z, .quit
+
+ ld a, [hl]
+ call GetSpriteLength
+
+; Spill over into the second table after $80 tiles.
+ add b
+ cp $80
+ jr z, .loop
+ jr nc, .SecondTable
+
+.loop
+ ld [hl], b
+ inc hl
+ ld b, a
+
+; Assumes the next table will be reached before c hits 0.
+ dec c
+ jr nz, .FirstTableLength
+
+.SecondTable:
+; The second tile table starts at tile $80.
+ ld b, $80
+ dec hl
+.SecondTableLength:
+; Keep going until the end of the list.
+ ld a, [hli]
+ and a
+ jr z, .quit
+
+ ld a, [hl]
+ call GetSpriteLength
+
+; There are only two tables, so don't go any further than that.
+ add b
+ jr c, .quit
+
+ ld [hl], b
+ ld b, a
+ inc hl
+
+ dec c
+ jr nz, .SecondTableLength
+
+.quit
+ ret
+; 14386
+
+
+GetSpriteLength: ; 14386
+; Return the length of sprite type a in tiles.
+
+ cp WALKING_SPRITE
+ jr z, .AnyDirection
+ cp STANDING_SPRITE
+ jr z, .AnyDirection
+ cp STILL_SPRITE
+ jr z, .OneDirection
+
+ ld a, 12
+ ret
+
+.AnyDirection:
+ ld a, 12
+ ret
+
+.OneDirection:
+ ld a, 4
+ ret
+; 1439b
+
+
+GetUsedSprites: ; 1439b
+ ld hl, wUsedSprites
+ ld c, SPRITE_GFX_LIST_CAPACITY
+
+.loop
+ ld a, [wSpriteFlags]
+ res 5, a
+ ld [wSpriteFlags], a
+
+ ld a, [hli]
+ and a
+ jr z, .done
+ ld [hUsedSpriteIndex], a
+
+ ld a, [hli]
+ ld [hUsedSpriteTile], a
+
+ bit 7, a
+ jr z, .dont_set
+
+ ld a, [wSpriteFlags]
+ set 5, a ; load VBank0
+ ld [wSpriteFlags], a
+
+.dont_set
+ push bc
+ push hl
+ call GetUsedSprite
+ pop hl
+ pop bc
+ dec c
+ jr nz, .loop
+
+.done
+ ret
+; 143c8
+
+GetUsedSprite: ; 143c8
+ ld a, [hUsedSpriteIndex]
+ call SafeGetSprite
+ ld a, [hUsedSpriteTile]
+ call .GetTileAddr
+ push hl
+ push de
+ push bc
+ ld a, [wSpriteFlags]
+ bit 7, a
+ jr nz, .skip
+ call .CopyToVram
+
+.skip
+ pop bc
+ ld l, c
+ ld h, $0
+rept 4
+ add hl, hl
+endr
+ pop de
+ add hl, de
+ ld d, h
+ ld e, l
+ pop hl
+
+ ld a, [wSpriteFlags]
+ bit 5, a
+ jr nz, .done
+ bit 6, a
+ jr nz, .done
+
+ ld a, [hUsedSpriteIndex]
+ call _DoesSpriteHaveFacings
+ jr c, .done
+
+ ld a, h
+ add $8
+ ld h, a
+ call .CopyToVram
+
+.done
+ ret
+; 14406
+
+.GetTileAddr: ; 14406
+; Return the address of tile (a) in (hl).
+ and $7f
+ ld l, a
+ ld h, 0
+rept 4
+ add hl, hl
+endr
+ ld a, l
+ add LOW(vTiles0)
+ ld l, a
+ ld a, h
+ adc HIGH(vTiles0)
+ ld h, a
+ ret
+; 14418
+
+.CopyToVram: ; 14418
+ ld a, [rVBK]
+ push af
+ ld a, [wSpriteFlags]
+ bit 5, a
+ ld a, $1
+ jr z, .bankswitch
+ ld a, $0
+
+.bankswitch
+ ld [rVBK], a
+ call Get2bpp
+ pop af
+ ld [rVBK], a
+ ret
+; 1442f
+
+LoadEmote:: ; 1442f
+; Get the address of the pointer to emote c.
+ ld a, c
+ ld bc, 6 ; sizeof(emote)
+ ld hl, Emotes
+ call AddNTimes
+; Load the emote address into de
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+; load the length of the emote (in tiles) into c
+ inc hl
+ ld c, [hl]
+ swap c
+; load the emote pointer bank into b
+ inc hl
+ ld b, [hl]
+; load the VRAM destination into hl
+ inc hl
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+; if the emote has a length of 0, do not proceed (error handling)
+ ld a, c
+ and a
+ ret z
+ call GetEmote2bpp
+ ret
+; 1444d
+
+
+INCLUDE "data/sprites/emotes.asm"
+
+INCLUDE "data/sprites/sprite_mons.asm"
+
+INCLUDE "data/maps/outdoor_sprites.asm"
+
+INCLUDE "data/sprites/sprites.asm"
diff --git a/engine/overworld/player_movement.asm b/engine/overworld/player_movement.asm
new file mode 100755
index 000000000..ef9afc7ad
--- /dev/null
+++ b/engine/overworld/player_movement.asm
@@ -0,0 +1,851 @@
+DoPlayerMovement:: ; 80000
+
+ call .GetDPad
+ ld a, movement_step_sleep
+ ld [wMovementAnimation], a
+ xor a
+ ld [wd041], a
+ call .TranslateIntoMovement
+ ld c, a
+ ld a, [wMovementAnimation]
+ ld [wPlayerNextMovement], a
+ ret
+
+.GetDPad:
+
+ ld a, [hJoyDown]
+ ld [wCurInput], a
+
+; Standing downhill instead moves down.
+
+ ld hl, wBikeFlags
+ bit BIKEFLAGS_DOWNHILL_F, [hl]
+ ret z
+
+ ld c, a
+ and D_PAD
+ ret nz
+
+ ld a, c
+ or D_DOWN
+ ld [wCurInput], a
+ ret
+; 8002d
+
+.TranslateIntoMovement:
+ ld a, [wPlayerState]
+ cp PLAYER_NORMAL
+ jr z, .Normal
+ cp PLAYER_SURF
+ jr z, .Surf
+ cp PLAYER_SURF_PIKA
+ jr z, .Surf
+ cp PLAYER_BIKE
+ jr z, .Normal
+ cp PLAYER_SKATE
+ jr z, .Ice
+
+.Normal:
+ call .CheckForced
+ call .GetAction
+ call .CheckTile
+ ret c
+ call .CheckTurning
+ ret c
+ call .TryStep
+ ret c
+ call .TryJump
+ ret c
+ call .CheckWarp
+ ret c
+ jr .NotMoving
+
+.Surf:
+ call .CheckForced
+ call .GetAction
+ call .CheckTile
+ ret c
+ call .CheckTurning
+ ret c
+ call .TrySurf
+ ret c
+ jr .NotMoving
+
+.Ice:
+ call .CheckForced
+ call .GetAction
+ call .CheckTile
+ ret c
+ call .CheckTurning
+ ret c
+ call .TryStep
+ ret c
+ call .TryJump
+ ret c
+ call .CheckWarp
+ ret c
+ ld a, [wWalkingDirection]
+ cp STANDING
+ jr z, .HitWall
+ call .BumpSound
+.HitWall:
+ call .StandInPlace
+ xor a
+ ret
+
+.NotMoving:
+ ld a, [wWalkingDirection]
+ cp STANDING
+ jr z, .Standing
+
+; Walking into an edge warp won't bump.
+ ld a, [wEngineBuffer4]
+ and a
+ jr nz, .CantMove
+ call .BumpSound
+.CantMove:
+ call ._WalkInPlace
+ xor a
+ ret
+
+.Standing:
+ call .StandInPlace
+ xor a
+ ret
+; 800b7
+
+.CheckTile: ; 800b7
+; Tiles such as waterfalls and warps move the player
+; in a given direction, overriding input.
+
+ ld a, [wPlayerStandingTile]
+ ld c, a
+ call CheckWhirlpoolTile
+ jr c, .not_whirlpool
+ ld a, 3
+ scf
+ ret
+
+.not_whirlpool
+ and $f0
+ cp HI_NYBBLE_CURRENT
+ jr z, .water
+ cp HI_NYBBLE_WALK
+ jr z, .land1
+ cp HI_NYBBLE_WALK_ALT
+ jr z, .land2
+ cp HI_NYBBLE_WARPS
+ jr z, .warps
+ jr .no_walk
+
+.water
+ ld a, c
+ maskbits NUM_DIRECTIONS
+ ld c, a
+ ld b, 0
+ ld hl, .water_table
+ add hl, bc
+ ld a, [hl]
+ ld [wWalkingDirection], a
+ jr .continue_walk
+
+.water_table
+ db RIGHT ; COLL_WATERFALL_RIGHT
+ db LEFT ; COLL_WATERFALL_LEFT
+ db UP ; COLL_WATERFALL_UP
+ db DOWN ; COLL_WATERFALL
+
+.land1
+ ld a, c
+ and 7
+ ld c, a
+ ld b, 0
+ ld hl, .land1_table
+ add hl, bc
+ ld a, [hl]
+ cp STANDING
+ jr z, .no_walk
+ ld [wWalkingDirection], a
+ jr .continue_walk
+
+.land1_table
+ db STANDING ; COLL_BRAKE
+ db RIGHT ; COLL_WALK_RIGHT
+ db LEFT ; COLL_WALK_LEFT
+ db UP ; COLL_WALK_UP
+ db DOWN ; COLL_WALK_DOWN
+ db STANDING ; COLL_BRAKE_45
+ db STANDING ; COLL_BRAKE_46
+ db STANDING ; COLL_BRAKE_47
+
+.land2
+ ld a, c
+ and 7
+ ld c, a
+ ld b, 0
+ ld hl, .land2_table
+ add hl, bc
+ ld a, [hl]
+ cp STANDING
+ jr z, .no_walk
+ ld [wWalkingDirection], a
+ jr .continue_walk
+
+.land2_table
+ db RIGHT ; COLL_WALK_RIGHT_ALT
+ db LEFT ; COLL_WALK_LEFT_ALT
+ db UP ; COLL_WALK_UP_ALT
+ db DOWN ; COLL_WALK_DOWN_ALT
+ db STANDING ; COLL_BRAKE_ALT
+ db STANDING ; COLL_BRAKE_55
+ db STANDING ; COLL_BRAKE_56
+ db STANDING ; COLL_BRAKE_57
+
+.warps
+ ld a, c
+ cp COLL_DOOR
+ jr z, .down
+ cp COLL_DOOR_79
+ jr z, .down
+ cp COLL_STAIRCASE
+ jr z, .down
+ cp COLL_CAVE
+ jr nz, .no_walk
+
+.down
+ ld a, DOWN
+ ld [wWalkingDirection], a
+ jr .continue_walk
+
+.no_walk
+ xor a
+ ret
+
+.continue_walk
+ ld a, STEP_WALK
+ call .DoStep
+ ld a, 5
+ scf
+ ret
+; 80147
+
+.CheckTurning: ; 80147
+; If the player is turning, change direction first. This also lets
+; the player change facing without moving by tapping a direction.
+
+ ld a, [wPlayerTurningDirection]
+ cp 0
+ jr nz, .not_turning
+ ld a, [wWalkingDirection]
+ cp STANDING
+ jr z, .not_turning
+
+ ld e, a
+ ld a, [wPlayerDirection]
+ rrca
+ rrca
+ maskbits NUM_DIRECTIONS
+ cp e
+ jr z, .not_turning
+
+ ld a, STEP_TURN
+ call .DoStep
+ ld a, 2
+ scf
+ ret
+
+.not_turning
+ xor a
+ ret
+; 8016b
+
+.TryStep: ; 8016b
+
+; Surfing actually calls .TrySurf directly instead of passing through here.
+ ld a, [wPlayerState]
+ cp PLAYER_SURF
+ jr z, .TrySurf
+ cp PLAYER_SURF_PIKA
+ jr z, .TrySurf
+
+ call .CheckLandPerms
+ jr c, .bump
+
+ call .CheckNPC
+ and a
+ jr z, .bump
+ cp 2
+ jr z, .bump
+
+ ld a, [wPlayerStandingTile]
+ call CheckIceTile
+ jr nc, .ice
+
+; Downhill riding is slower when not moving down.
+ call .BikeCheck
+ jr nz, .walk
+
+ ld hl, wBikeFlags
+ bit BIKEFLAGS_DOWNHILL_F, [hl]
+ jr z, .fast
+
+ ld a, [wWalkingDirection]
+ cp DOWN
+ jr z, .fast
+
+ ld a, STEP_WALK
+ call .DoStep
+ scf
+ ret
+
+.fast
+ ld a, STEP_BIKE
+ call .DoStep
+ scf
+ ret
+
+.walk
+ ld a, STEP_WALK
+ call .DoStep
+ scf
+ ret
+
+.ice
+ ld a, STEP_ICE
+ call .DoStep
+ scf
+ ret
+
+; unused
+ xor a
+ ret
+
+.bump
+ xor a
+ ret
+; 801c0
+
+.TrySurf: ; 801c0
+
+ call .CheckSurfPerms
+ ld [wd040], a
+ jr c, .surf_bump
+
+ call .CheckNPC
+ ld [wd03f], a
+ and a
+ jr z, .surf_bump
+ cp 2
+ jr z, .surf_bump
+
+ ld a, [wd040]
+ and a
+ jr nz, .ExitWater
+
+ ld a, STEP_WALK
+ call .DoStep
+ scf
+ ret
+
+.ExitWater:
+ call .GetOutOfWater
+ call PlayMapMusic
+ ld a, STEP_WALK
+ call .DoStep
+ ld a, 6
+ scf
+ ret
+
+.surf_bump
+ xor a
+ ret
+; 801f3
+
+.TryJump: ; 801f3
+ ld a, [wPlayerStandingTile]
+ ld e, a
+ and $f0
+ cp HI_NYBBLE_LEDGES
+ jr nz, .DontJump
+
+ ld a, e
+ and 7
+ ld e, a
+ ld d, 0
+ ld hl, .data_8021e
+ add hl, de
+ ld a, [wFacingDirection]
+ and [hl]
+ jr z, .DontJump
+
+ ld de, SFX_JUMP_OVER_LEDGE
+ call PlaySFX
+ ld a, STEP_LEDGE
+ call .DoStep
+ ld a, 7
+ scf
+ ret
+
+.DontJump:
+ xor a
+ ret
+
+.data_8021e
+ db FACE_RIGHT ; COLL_HOP_RIGHT
+ db FACE_LEFT ; COLL_HOP_LEFT
+ db FACE_UP ; COLL_HOP_UP
+ db FACE_DOWN ; COLL_HOP_DOWN
+ db FACE_RIGHT | FACE_DOWN ; COLL_HOP_DOWN_RIGHT
+ db FACE_DOWN | FACE_LEFT ; COLL_HOP_DOWN_LEFT
+ db FACE_UP | FACE_RIGHT ; COLL_HOP_UP_RIGHT
+ db FACE_UP | FACE_LEFT ; COLL_HOP_UP_LEFT
+; 80226
+
+.CheckWarp: ; 80226
+
+; Bug: Since no case is made for STANDING here, it will check
+; [.edgewarps + $ff]. This resolves to $3e at $8035a.
+; This causes wd041 to be nonzero when standing on tile $3e,
+; making bumps silent.
+
+ ld a, [wWalkingDirection]
+ ; cp STANDING
+ ; jr z, .not_warp
+ ld e, a
+ ld d, 0
+ ld hl, .EdgeWarps
+ add hl, de
+ ld a, [wPlayerStandingTile]
+ cp [hl]
+ jr nz, .not_warp
+
+ ld a, 1
+ ld [wd041], a
+ ld a, [wWalkingDirection]
+ ; This is in the wrong place.
+ cp STANDING
+ jr z, .not_warp
+
+ ld e, a
+ ld a, [wPlayerDirection]
+ rrca
+ rrca
+ maskbits NUM_DIRECTIONS
+ cp e
+ jr nz, .not_warp
+ call WarpCheck
+ jr nc, .not_warp
+
+ call .StandInPlace
+ scf
+ ld a, 1
+ ret
+
+.not_warp
+ xor a
+ ret
+
+.EdgeWarps:
+ db COLL_WARP_CARPET_DOWN
+ db COLL_WARP_CARPET_UP
+ db COLL_WARP_CARPET_LEFT
+ db COLL_WARP_CARPET_RIGHT
+; 8025f
+
+.DoStep:
+ ld e, a
+ ld d, 0
+ ld hl, .Steps
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+
+ ld a, [wWalkingDirection]
+ ld e, a
+ cp STANDING
+ jp z, .StandInPlace
+
+ add hl, de
+ ld a, [hl]
+ ld [wMovementAnimation], a
+
+ ld hl, .FinishFacing
+ add hl, de
+ ld a, [hl]
+ ld [wPlayerTurningDirection], a
+
+ ld a, 4
+ ret
+
+.Steps:
+ dw .SlowStep
+ dw .NormalStep
+ dw .FastStep
+ dw .JumpStep
+ dw .SlideStep
+ dw .TurningStep
+ dw .BackJumpStep
+ dw .FinishFacing
+
+.SlowStep:
+ slow_step DOWN
+ slow_step UP
+ slow_step LEFT
+ slow_step RIGHT
+.NormalStep:
+ step DOWN
+ step UP
+ step LEFT
+ step RIGHT
+.FastStep:
+ big_step DOWN
+ big_step UP
+ big_step LEFT
+ big_step RIGHT
+.JumpStep:
+ jump_step DOWN
+ jump_step UP
+ jump_step LEFT
+ jump_step RIGHT
+.SlideStep:
+ fast_slide_step DOWN
+ fast_slide_step UP
+ fast_slide_step LEFT
+ fast_slide_step RIGHT
+.BackJumpStep:
+ jump_step UP
+ jump_step DOWN
+ jump_step RIGHT
+ jump_step LEFT
+.TurningStep:
+ turn_step DOWN
+ turn_step UP
+ turn_step LEFT
+ turn_step RIGHT
+.FinishFacing:
+ db $80 + DOWN
+ db $80 + UP
+ db $80 + LEFT
+ db $80 + RIGHT
+; 802b3
+
+.StandInPlace: ; 802b3
+ ld a, 0
+ ld [wPlayerTurningDirection], a
+ ld a, movement_step_sleep
+ ld [wMovementAnimation], a
+ xor a
+ ret
+; 802bf
+
+._WalkInPlace: ; 802bf
+ ld a, 0
+ ld [wPlayerTurningDirection], a
+ ld a, movement_step_bump
+ ld [wMovementAnimation], a
+ xor a
+ ret
+; 802cb
+
+.CheckForced: ; 802cb
+; When sliding on ice, input is forced to remain in the same direction.
+
+ call CheckStandingOnIce
+ ret nc
+
+ ld a, [wPlayerTurningDirection]
+ cp 0
+ ret z
+
+ maskbits NUM_DIRECTIONS
+ ld e, a
+ ld d, 0
+ ld hl, .forced_dpad
+ add hl, de
+ ld a, [wCurInput]
+ and BUTTONS
+ or [hl]
+ ld [wCurInput], a
+ ret
+
+.forced_dpad
+ db D_DOWN, D_UP, D_LEFT, D_RIGHT
+; 802ec
+
+.GetAction: ; 802ec
+; Poll player input and update movement info.
+
+ ld hl, .table
+ ld de, .table2 - .table1
+ ld a, [wCurInput]
+ bit D_DOWN_F, a
+ jr nz, .d_down
+ bit D_UP_F, a
+ jr nz, .d_up
+ bit D_LEFT_F, a
+ jr nz, .d_left
+ bit D_RIGHT_F, a
+ jr nz, .d_right
+; Standing
+ jr .update
+
+.d_down add hl, de
+.d_up add hl, de
+.d_left add hl, de
+.d_right add hl, de
+
+.update
+ ld a, [hli]
+ ld [wWalkingDirection], a
+ ld a, [hli]
+ ld [wFacingDirection], a
+ ld a, [hli]
+ ld [wWalkingX], a
+ ld a, [hli]
+ ld [wWalkingY], a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [hl]
+ ld [wWalkingTile], a
+ ret
+
+.table
+; struct:
+; walk direction
+; facing
+; x movement
+; y movement
+; tile collision pointer
+.table1
+ db STANDING, FACE_CURRENT, 0, 0
+ dw wPlayerStandingTile
+.table2
+ db RIGHT, FACE_RIGHT, 1, 0
+ dw wTileRight
+ db LEFT, FACE_LEFT, -1, 0
+ dw wTileLeft
+ db UP, FACE_UP, 0, -1
+ dw wTileUp
+ db DOWN, FACE_DOWN, 0, 1
+ dw wTileDown
+; 80341
+
+.CheckNPC: ; 80341
+; Returns 0 if there is an NPC in front that you can't move
+; Returns 1 if there is no NPC in front
+; Returns 2 if there is a movable NPC in front
+ ld a, 0
+ ld [hMapObjectIndexBuffer], a
+; Load the next X coordinate into d
+ ld a, [wPlayerStandingMapX]
+ ld d, a
+ ld a, [wWalkingX]
+ add d
+ ld d, a
+; Load the next Y coordinate into e
+ ld a, [wPlayerStandingMapY]
+ ld e, a
+ ld a, [wWalkingY]
+ add e
+ ld e, a
+; Find an object struct with coordinates equal to d,e
+ ld bc, wObjectStructs ; redundant
+ farcall IsNPCAtCoord
+ jr nc, .is_npc
+ call .CheckStrengthBoulder
+ jr c, .no_bump
+
+ xor a
+ ret
+
+.is_npc
+ ld a, 1
+ ret
+
+.no_bump
+ ld a, 2
+ ret
+; 8036f
+
+.CheckStrengthBoulder: ; 8036f
+
+ ld hl, wBikeFlags
+ bit BIKEFLAGS_STRENGTH_ACTIVE_F, [hl]
+ jr z, .not_boulder
+
+ ld hl, OBJECT_DIRECTION_WALKING
+ add hl, bc
+ ld a, [hl]
+ cp STANDING
+ jr nz, .not_boulder
+
+ ld hl, OBJECT_PALETTE
+ add hl, bc
+ bit 6, [hl]
+ jr z, .not_boulder
+
+ ld hl, OBJECT_FLAGS2
+ add hl, bc
+ set 2, [hl]
+
+ ld a, [wWalkingDirection]
+ ld d, a
+ ld hl, OBJECT_RANGE
+ add hl, bc
+ ld a, [hl]
+ and $fc
+ or d
+ ld [hl], a
+
+ scf
+ ret
+
+.not_boulder
+ xor a
+ ret
+; 8039e
+
+.CheckLandPerms: ; 8039e
+; Return 0 if walking onto land and tile permissions allow it.
+; Otherwise, return carry.
+
+ ld a, [wTilePermissions]
+ ld d, a
+ ld a, [wFacingDirection]
+ and d
+ jr nz, .NotWalkable
+
+ ld a, [wWalkingTile]
+ call .CheckWalkable
+ jr c, .NotWalkable
+
+ xor a
+ ret
+
+.NotWalkable:
+ scf
+ ret
+; 803b4
+
+.CheckSurfPerms: ; 803b4
+; Return 0 if moving in water, or 1 if moving onto land.
+; Otherwise, return carry.
+
+ ld a, [wTilePermissions]
+ ld d, a
+ ld a, [wFacingDirection]
+ and d
+ jr nz, .NotSurfable
+
+ ld a, [wWalkingTile]
+ call .CheckSurfable
+ jr c, .NotSurfable
+
+ and a
+ ret
+
+.NotSurfable:
+ scf
+ ret
+; 803ca
+
+.BikeCheck: ; 803ca
+ ld a, [wPlayerState]
+ cp PLAYER_BIKE
+ ret z
+ cp PLAYER_SKATE
+ ret
+; 803d3
+
+.CheckWalkable: ; 803d3
+; Return 0 if tile a is land. Otherwise, return carry.
+
+ call GetTileCollision
+ and a ; LANDTILE?
+ ret z
+ scf
+ ret
+; 803da
+
+.CheckSurfable: ; 803da
+; Return 0 if tile a is water, or 1 if land.
+; Otherwise, return carry.
+
+ call GetTileCollision
+ cp WATERTILE
+ jr z, .Water
+
+; Can walk back onto land from water.
+ and a ; LANDTILE?
+ jr z, .Land
+
+ jr .Neither
+
+.Water:
+ xor a
+ ret
+
+.Land:
+ ld a, 1
+ and a
+ ret
+
+.Neither:
+ scf
+ ret
+; 803ee
+
+.BumpSound: ; 803ee
+
+ call CheckSFX
+ ret c
+ ld de, SFX_BUMP
+ call PlaySFX
+ ret
+; 803f9
+
+.GetOutOfWater: ; 803f9
+ push bc
+ ld a, PLAYER_NORMAL
+ ld [wPlayerState], a
+ call ReplaceKrisSprite ; UpdateSprites
+ pop bc
+ ret
+; 80404
+
+CheckStandingOnIce:: ; 80404
+ ld a, [wPlayerTurningDirection]
+ cp 0
+ jr z, .not_ice
+ cp $f0
+ jr z, .not_ice
+ ld a, [wPlayerStandingTile]
+ call CheckIceTile
+ jr nc, .yep
+ ld a, [wPlayerState]
+ cp PLAYER_SKATE
+ jr nz, .not_ice
+
+.yep
+ scf
+ ret
+
+.not_ice
+ and a
+ ret
+; 80422
+
+StopPlayerForEvent:: ; 80422
+ ld hl, wPlayerNextMovement
+ ld a, movement_step_sleep
+ cp [hl]
+ ret z
+
+ ld [hl], a
+ ld a, 0
+ ld [wPlayerTurningDirection], a
+ ret
+; 80430
diff --git a/engine/overworld/player_object.asm b/engine/overworld/player_object.asm
new file mode 100755
index 000000000..7d287dedb
--- /dev/null
+++ b/engine/overworld/player_object.asm
@@ -0,0 +1,856 @@
+BlankScreen: ; 8000
+ call DisableSpriteUpdates
+ xor a
+ ld [hBGMapMode], a
+ call ClearBGPalettes
+ call ClearSprites
+ hlcoord 0, 0
+ ld bc, wTileMapEnd - wTileMap
+ ld a, " "
+ call ByteFill
+ hlcoord 0, 0, wAttrMap
+ ld bc, wAttrMapEnd - wAttrMap
+ ld a, $7
+ call ByteFill
+ call WaitBGMap2
+ call SetPalettes
+ ret
+
+SpawnPlayer: ; 8029
+ ld a, -1
+ ld [wObjectFollow_Leader], a
+ ld [wObjectFollow_Follower], a
+ ld a, $0
+ ld hl, PlayerObjectTemplate
+ call CopyPlayerObjectTemplate
+ ld b, $0
+ call PlayerSpawn_ConvertCoords
+ ld a, PLAYER_OBJECT
+ call GetMapObject
+ ld hl, MAPOBJECT_COLOR
+ add hl, bc
+ ln e, PAL_NPC_RED, OBJECTTYPE_SCRIPT
+ ld a, [wPlayerSpriteSetupFlags]
+ bit PLAYERSPRITESETUP_FEMALE_TO_MALE_F, a
+ jr nz, .ok
+ ld a, [wPlayerGender]
+ bit PLAYERGENDER_FEMALE_F, a
+ jr z, .ok
+ ln e, PAL_NPC_BLUE, OBJECTTYPE_SCRIPT
+
+.ok
+ ld [hl], e
+ ld a, PLAYER_OBJECT
+ ld [hMapObjectIndexBuffer], a
+ ld bc, wMapObjects
+ ld a, PLAYER_OBJECT
+ ld [hObjectStructIndexBuffer], a
+ ld de, wObjectStructs
+ call CopyMapObjectToObjectStruct
+ ld a, PLAYER
+ ld [wCenteredObject], a
+ ret
+
+PlayerObjectTemplate: ; 8071
+; A dummy map object used to initialize the player object.
+; Shorter than the actual amount copied by two bytes.
+; Said bytes seem to be unused.
+ object_event -4, -4, SPRITE_CHRIS, SPRITEMOVEDATA_PLAYER, 15, 15, -1, -1, 0, OBJECTTYPE_SCRIPT, 0, 0, -1
+
+CopyDECoordsToMapObject:: ; 807e
+ push de
+ ld a, b
+ call GetMapObject
+ pop de
+ ld hl, MAPOBJECT_X_COORD
+ add hl, bc
+ ld [hl], d
+ ld hl, MAPOBJECT_Y_COORD
+ add hl, bc
+ ld [hl], e
+ ret
+
+PlayerSpawn_ConvertCoords: ; 808f
+ push bc
+ ld a, [wXCoord]
+ add 4
+ ld d, a
+ ld a, [wYCoord]
+ add 4
+ ld e, a
+ pop bc
+ call CopyDECoordsToMapObject
+ ret
+
+WriteObjectXY:: ; 80a1
+ ld a, b
+ call CheckObjectVisibility
+ ret c
+
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ ld a, [hMapObjectIndexBuffer]
+ ld b, a
+ call CopyDECoordsToMapObject
+ and a
+ ret
+
+RefreshPlayerCoords: ; 80b8
+ ld a, [wXCoord]
+ add 4
+ ld d, a
+ ld hl, wPlayerStandingMapX
+ sub [hl]
+ ld [hl], d
+ ld hl, wMapObjects + MAPOBJECT_X_COORD
+ ld [hl], d
+ ld hl, wPlayerLastMapX
+ ld [hl], d
+ ld d, a
+ ld a, [wYCoord]
+ add 4
+ ld e, a
+ ld hl, wPlayerStandingMapY
+ sub [hl]
+ ld [hl], e
+ ld hl, wMapObjects + MAPOBJECT_Y_COORD
+ ld [hl], e
+ ld hl, wPlayerLastMapY
+ ld [hl], e
+ ld e, a
+ ld a, [wObjectFollow_Leader]
+ cp $0
+ ret nz ; wtf
+ ret
+
+CopyObjectStruct:: ; 80e7
+ call CheckObjectMask
+ and a
+ ret nz ; masked
+
+ ld hl, wObjectStructs + OBJECT_STRUCT_LENGTH * 1
+ ld a, 1
+ ld de, OBJECT_STRUCT_LENGTH
+.loop
+ ld [hObjectStructIndexBuffer], a
+ ld a, [hl]
+ and a
+ jr z, .done
+ add hl, de
+ ld a, [hObjectStructIndexBuffer]
+ inc a
+ cp NUM_OBJECT_STRUCTS
+ jr nz, .loop
+ scf
+ ret ; overflow
+
+.done
+ ld d, h
+ ld e, l
+ call CopyMapObjectToObjectStruct
+ ld hl, wVramState
+ bit 7, [hl]
+ ret z
+
+ ld hl, OBJECT_FLAGS2
+ add hl, de
+ set 5, [hl]
+ ret
+
+CopyMapObjectToObjectStruct: ; 8116
+ call .CopyMapObjectToTempObject
+ call CopyTempObjectToObjectStruct
+ ret
+
+.CopyMapObjectToTempObject: ; 811d
+ ld a, [hObjectStructIndexBuffer]
+ ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+ add hl, bc
+ ld [hl], a
+
+ ld a, [hMapObjectIndexBuffer]
+ ld [wTempObjectCopyMapObjectIndex], a
+
+ ld hl, MAPOBJECT_SPRITE
+ add hl, bc
+ ld a, [hl]
+ ld [wTempObjectCopySprite], a
+
+ call GetSpriteVTile
+ ld [wTempObjectCopySpriteVTile], a
+
+ ld a, [hl]
+ call GetSpritePalette
+ ld [wTempObjectCopyPalette], a
+
+ ld hl, MAPOBJECT_COLOR
+ add hl, bc
+ ld a, [hl]
+ and $f0
+ jr z, .skip_color_override
+ swap a
+ and PALETTE_MASK
+ ld [wTempObjectCopyPalette], a
+
+.skip_color_override
+ ld hl, MAPOBJECT_MOVEMENT
+ add hl, bc
+ ld a, [hl]
+ ld [wTempObjectCopyMovement], a
+
+ ld hl, MAPOBJECT_RANGE
+ add hl, bc
+ ld a, [hl]
+ ld [wTempObjectCopyRange], a
+
+ ld hl, MAPOBJECT_X_COORD
+ add hl, bc
+ ld a, [hl]
+ ld [wTempObjectCopyX], a
+
+ ld hl, MAPOBJECT_Y_COORD
+ add hl, bc
+ ld a, [hl]
+ ld [wTempObjectCopyY], a
+
+ ld hl, MAPOBJECT_RADIUS
+ add hl, bc
+ ld a, [hl]
+ ld [wTempObjectCopyRadius], a
+ ret
+
+InitializeVisibleSprites: ; 8177
+ ld bc, wMapObjects + OBJECT_LENGTH
+ ld a, 1
+.loop
+ ld [hMapObjectIndexBuffer], a
+ ld hl, MAPOBJECT_SPRITE
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .next
+
+ ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+ add hl, bc
+ ld a, [hl]
+ cp -1
+ jr nz, .next
+
+ ld a, [wXCoord]
+ ld d, a
+ ld a, [wYCoord]
+ ld e, a
+
+ ld hl, MAPOBJECT_X_COORD
+ add hl, bc
+ ld a, [hl]
+ add 1
+ sub d
+ jr c, .next
+
+ cp MAPOBJECT_SCREEN_WIDTH
+ jr nc, .next
+
+ ld hl, MAPOBJECT_Y_COORD
+ add hl, bc
+ ld a, [hl]
+ add 1
+ sub e
+ jr c, .next
+
+ cp MAPOBJECT_SCREEN_HEIGHT
+ jr nc, .next
+
+ push bc
+ call CopyObjectStruct
+ pop bc
+ jp c, .ret
+
+.next
+ ld hl, OBJECT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ ld a, [hMapObjectIndexBuffer]
+ inc a
+ cp NUM_OBJECTS
+ jr nz, .loop
+ ret
+
+.ret ; 81c9
+ ret
+
+CheckObjectEnteringVisibleRange:: ; 81ca
+ nop
+ ld a, [wPlayerStepDirection]
+ cp STANDING
+ ret z
+ ld hl, .dw
+ rst JumpTable
+ ret
+
+.dw ; 81d6
+ dw .Down
+ dw .Up
+ dw .Left
+ dw .Right
+
+.Up: ; 81de
+ ld a, [wYCoord]
+ sub 1
+ jr .Vertical
+
+.Down: ; 81e5
+ ld a, [wYCoord]
+ add 9
+.Vertical: ; 81ea
+ ld d, a
+ ld a, [wXCoord]
+ ld e, a
+ ld bc, wMapObjects + OBJECT_LENGTH
+ ld a, 1
+.loop_v
+ ld [hMapObjectIndexBuffer], a
+ ld hl, MAPOBJECT_SPRITE
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .next_v
+ ld hl, MAPOBJECT_Y_COORD
+ add hl, bc
+ ld a, d
+ cp [hl]
+ jr nz, .next_v
+ ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+ add hl, bc
+ ld a, [hl]
+ cp -1
+ jr nz, .next_v
+ ld hl, MAPOBJECT_X_COORD
+ add hl, bc
+ ld a, [hl]
+ add 1
+ sub e
+ jr c, .next_v
+ cp MAPOBJECT_SCREEN_WIDTH
+ jr nc, .next_v
+ push de
+ push bc
+ call CopyObjectStruct
+ pop bc
+ pop de
+
+.next_v
+ ld hl, OBJECT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ ld a, [hMapObjectIndexBuffer]
+ inc a
+ cp NUM_OBJECTS
+ jr nz, .loop_v
+ ret
+
+.Left: ; 8232
+ ld a, [wXCoord]
+ sub 1
+ jr .Horizontal
+
+.Right: ; 8239
+ ld a, [wXCoord]
+ add 10
+.Horizontal: ; 823e
+ ld e, a
+ ld a, [wYCoord]
+ ld d, a
+ ld bc, wMapObjects + OBJECT_LENGTH
+ ld a, 1
+.loop_h
+ ld [hMapObjectIndexBuffer], a
+ ld hl, MAPOBJECT_SPRITE
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .next_h
+ ld hl, MAPOBJECT_X_COORD
+ add hl, bc
+ ld a, e
+ cp [hl]
+ jr nz, .next_h
+ ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+ add hl, bc
+ ld a, [hl]
+ cp -1
+ jr nz, .next_h
+ ld hl, MAPOBJECT_Y_COORD
+ add hl, bc
+ ld a, [hl]
+ add 1
+ sub d
+ jr c, .next_h
+ cp MAPOBJECT_SCREEN_HEIGHT
+ jr nc, .next_h
+ push de
+ push bc
+ call CopyObjectStruct
+ pop bc
+ pop de
+
+.next_h
+ ld hl, OBJECT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ ld a, [hMapObjectIndexBuffer]
+ inc a
+ cp NUM_OBJECTS
+ jr nz, .loop_h
+ ret
+
+CopyTempObjectToObjectStruct: ; 8286
+ ld a, [wTempObjectCopyMapObjectIndex]
+ ld hl, OBJECT_MAP_OBJECT_INDEX
+ add hl, de
+ ld [hl], a
+
+ ld a, [wTempObjectCopyMovement]
+ call CopySpriteMovementData
+
+ ld a, [wTempObjectCopyPalette]
+ ld hl, OBJECT_PALETTE
+ add hl, de
+ or [hl]
+ ld [hl], a
+
+ ld a, [wTempObjectCopyY]
+ call .InitYCoord
+
+ ld a, [wTempObjectCopyX]
+ call .InitXCoord
+
+ ld a, [wTempObjectCopySprite]
+ ld hl, OBJECT_SPRITE
+ add hl, de
+ ld [hl], a
+
+ ld a, [wTempObjectCopySpriteVTile]
+ ld hl, OBJECT_SPRITE_TILE
+ add hl, de
+ ld [hl], a
+
+ ld hl, OBJECT_STEP_TYPE
+ add hl, de
+ ld [hl], STEP_TYPE_00
+
+ ld hl, OBJECT_FACING_STEP
+ add hl, de
+ ld [hl], STANDING
+
+ ld a, [wTempObjectCopyRadius]
+ call .InitRadius
+
+ ld a, [wTempObjectCopyRange]
+ ld hl, OBJECT_RANGE
+ add hl, de
+ ld [hl], a
+
+ and a
+ ret
+
+.InitYCoord: ; 82d5
+ ld hl, OBJECT_INIT_Y
+ add hl, de
+ ld [hl], a
+
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, de
+ ld [hl], a
+
+ ld hl, wYCoord
+ sub [hl]
+ and $f
+ swap a
+ ld hl, wPlayerBGMapOffsetY
+ sub [hl]
+ ld hl, OBJECT_SPRITE_Y
+ add hl, de
+ ld [hl], a
+ ret
+
+.InitXCoord: ; 82f1
+ ld hl, OBJECT_INIT_X
+ add hl, de
+ ld [hl], a
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, de
+ ld [hl], a
+ ld hl, wXCoord
+ sub [hl]
+ and $f
+ swap a
+ ld hl, wPlayerBGMapOffsetX
+ sub [hl]
+ ld hl, OBJECT_SPRITE_X
+ add hl, de
+ ld [hl], a
+ ret
+
+.InitRadius: ; 830d
+ ld h, a
+ inc a
+ and $f
+ ld l, a
+ ld a, h
+ add $10
+ and $f0
+ or l
+ ld hl, OBJECT_RADIUS
+ add hl, de
+ ld [hl], a
+ ret
+
+TrainerWalkToPlayer: ; 831e
+ ld a, [hLastTalked]
+ call InitMovementBuffer
+ ld a, movement_step_sleep
+ call AppendToMovementBuffer
+ ld a, [wd03f]
+ dec a
+ jr z, .TerminateStep
+ ld a, [hLastTalked]
+ ld b, a
+ ld c, PLAYER
+ ld d, 1
+ call .GetPathToPlayer
+ call DecrementMovementBufferCount
+
+.TerminateStep:
+ ld a, movement_step_end
+ call AppendToMovementBuffer
+ ret
+
+.GetPathToPlayer: ; 8341
+ push de
+ push bc
+; get player object struct, load to de
+ ld a, c
+ call GetMapObject
+ ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+ add hl, bc
+ ld a, [hl]
+ call GetObjectStruct
+ ld d, b
+ ld e, c
+
+; get last talked object struct, load to bc
+ pop bc
+ ld a, b
+ call GetMapObject
+ ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+ add hl, bc
+ ld a, [hl]
+ call GetObjectStruct
+
+; get last talked coords, load to bc
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld c, [hl]
+ ld b, a
+
+; get player coords, load to de
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, de
+ ld a, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, de
+ ld e, [hl]
+ ld d, a
+
+ pop af
+ call ComputePathToWalkToPlayer
+ ret
+
+SurfStartStep: ; 8379
+ call InitMovementBuffer
+ call .GetMovementData
+ call AppendToMovementBuffer
+ ld a, movement_step_end
+ call AppendToMovementBuffer
+ ret
+
+.GetMovementData: ; 8388
+ ld a, [wPlayerDirection]
+ srl a
+ srl a
+ maskbits NUM_DIRECTIONS
+ ld e, a
+ ld d, 0
+ ld hl, .movement_data
+ add hl, de
+ ld a, [hl]
+ ret
+
+.movement_data
+ slow_step DOWN
+ slow_step UP
+ slow_step LEFT
+ slow_step RIGHT
+
+FollowNotExact:: ; 839e
+ push bc
+ ld a, c
+ call CheckObjectVisibility
+ ld d, b
+ ld e, c
+ pop bc
+ ret c
+
+ ld a, b
+ call CheckObjectVisibility
+ ret c
+
+; object 2 is now in bc, object 1 is now in de
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld c, [hl]
+ ld b, a
+
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, de
+ ld a, [hl]
+ cp b
+ jr z, .same_x
+ jr c, .to_the_left
+ inc b
+ jr .continue
+
+.to_the_left
+ dec b
+ jr .continue
+
+.same_x
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, de
+ ld a, [hl]
+ cp c
+ jr z, .continue
+ jr c, .below
+ inc c
+ jr .continue
+
+.below
+ dec c
+
+.continue
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, de
+ ld [hl], b
+ ld a, b
+ ld hl, wXCoord
+ sub [hl]
+ and $f
+ swap a
+ ld hl, wPlayerBGMapOffsetX
+ sub [hl]
+ ld hl, OBJECT_SPRITE_X
+ add hl, de
+ ld [hl], a
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, de
+ ld [hl], c
+ ld a, c
+ ld hl, wYCoord
+ sub [hl]
+ and $f
+ swap a
+ ld hl, wPlayerBGMapOffsetY
+ sub [hl]
+ ld hl, OBJECT_SPRITE_Y
+ add hl, de
+ ld [hl], a
+ ld a, [hObjectStructIndexBuffer]
+ ld hl, OBJECT_RANGE
+ add hl, de
+ ld [hl], a
+ ld hl, OBJECT_MOVEMENTTYPE
+ add hl, de
+ ld [hl], SPRITEMOVEDATA_FOLLOWNOTEXACT
+ ld hl, OBJECT_STEP_TYPE
+ add hl, de
+ ld [hl], STEP_TYPE_00
+ ret
+
+GetRelativeFacing:: ; 8417
+; Determines which way map object e would have to turn to face map object d. Returns carry if it's impossible for whatever reason.
+ ld a, d
+ call GetMapObject
+ ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+ add hl, bc
+ ld a, [hl]
+ cp NUM_OBJECT_STRUCTS
+ jr nc, .carry
+ ld d, a
+ ld a, e
+ call GetMapObject
+ ld hl, MAPOBJECT_OBJECT_STRUCT_ID
+ add hl, bc
+ ld a, [hl]
+ cp NUM_OBJECT_STRUCTS
+ jr nc, .carry
+ ld e, a
+ call .GetFacing_e_relativeto_d
+ ret
+
+.carry
+ scf
+ ret
+
+.GetFacing_e_relativeto_d: ; 8439
+; Determines which way object e would have to turn to face object d. Returns carry if it's impossible.
+; load the coordinates of object d into bc
+ ld a, d
+ call GetObjectStruct
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld c, [hl]
+ ld b, a
+ push bc
+; load the coordinates of object e into de
+ ld a, e
+ call GetObjectStruct
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ pop bc
+; |x1 - x2|
+ ld a, b
+ sub d
+ jr z, .same_x_1
+ jr nc, .b_right_of_d_1
+ cpl
+ inc a
+
+.b_right_of_d_1
+; |y1 - y2|
+ ld h, a
+ ld a, c
+ sub e
+ jr z, .same_y_1
+ jr nc, .c_below_e_1
+ cpl
+ inc a
+
+.c_below_e_1
+; |y1 - y2| - |x1 - x2|
+ sub h
+ jr c, .same_y_1
+
+.same_x_1
+; compare the y coordinates
+ ld a, c
+ cp e
+ jr z, .same_x_and_y
+ jr c, .c_directly_below_e
+; c directly above e
+ ld d, DOWN
+ and a
+ ret
+
+.c_directly_below_e
+ ld d, UP
+ and a
+ ret
+
+.same_y_1
+ ld a, b
+ cp d
+ jr z, .same_x_and_y
+ jr c, .b_directly_right_of_d
+; b directly left of d
+ ld d, RIGHT
+ and a
+ ret
+
+.b_directly_right_of_d
+ ld d, LEFT
+ and a
+ ret
+
+.same_x_and_y
+ scf
+ ret
+
+QueueFollowerFirstStep: ; 848a
+ call .QueueFirstStep
+ jr c, .same
+ ld [wFollowMovementQueue], a
+ xor a
+ ld [wFollowerMovementQueueLength], a
+ ret
+
+.same
+ ld a, -1
+ ld [wFollowerMovementQueueLength], a
+ ret
+
+.QueueFirstStep:
+ ld a, [wObjectFollow_Leader]
+ call GetObjectStruct
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ ld a, [wObjectFollow_Follower]
+ call GetObjectStruct
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, d
+ cp [hl]
+ jr z, .check_y
+ jr c, .left
+ and a
+ ld a, movement_step + RIGHT
+ ret
+
+.left
+ and a
+ ld a, movement_step + LEFT
+ ret
+
+.check_y
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld a, e
+ cp [hl]
+ jr z, .same_xy
+ jr c, .up
+ and a
+ ld a, movement_step + DOWN
+ ret
+
+.up
+ and a
+ ld a, movement_step + UP
+ ret
+
+.same_xy
+ scf
+ ret
diff --git a/engine/overworld/player_step.asm b/engine/overworld/player_step.asm
new file mode 100755
index 000000000..675c6553b
--- /dev/null
+++ b/engine/overworld/player_step.asm
@@ -0,0 +1,270 @@
+_HandlePlayerStep:: ; d497 (3:5497)
+ ld a, [wPlayerStepFlags]
+ and a
+ ret z
+ bit 7, a ; starting step
+ jr nz, .update_overworld_map
+ bit 6, a ; finishing step
+ jr nz, .update_player_coords
+ bit 5, a ; ongoing step
+ jr nz, .finish
+ ret
+
+.update_overworld_map
+ ld a, 4
+ ld [wHandlePlayerStep], a
+ call UpdateOverworldMap
+ jr .finish
+
+.update_player_coords
+ call UpdatePlayerCoords
+ jr .finish
+
+.finish
+ call HandlePlayerStep
+ ld a, [wPlayerStepVectorX]
+ ld d, a
+ ld a, [wPlayerStepVectorY]
+ ld e, a
+ ld a, [wPlayerBGMapOffsetX]
+ sub d
+ ld [wPlayerBGMapOffsetX], a
+ ld a, [wPlayerBGMapOffsetY]
+ sub e
+ ld [wPlayerBGMapOffsetY], a
+ ret
+
+ScrollScreen:: ; d4d2 (3:54d2)
+ ld a, [wPlayerStepVectorX]
+ ld d, a
+ ld a, [wPlayerStepVectorY]
+ ld e, a
+ ld a, [hSCX]
+ add d
+ ld [hSCX], a
+ ld a, [hSCY]
+ add e
+ ld [hSCY], a
+ ret
+
+HandlePlayerStep: ; d4e5 (3:54e5)
+ ld hl, wHandlePlayerStep
+ ld a, [hl]
+ and a
+ ret z
+ dec [hl]
+ ld a, [hl]
+ ld hl, .Jumptable
+ rst JumpTable
+ ret
+
+.Jumptable: ; d4f2 (3:54f2)
+ dw GetMovementPermissions
+ dw BufferScreen
+ dw .mobile
+ dw .fail2
+; The rest are never used. Ever.
+ dw .fail1
+ dw .fail1
+ dw .fail1
+ dw .fail1
+ dw .fail1
+ dw .fail1
+ dw .fail1
+
+.fail1 ; d508 (3:5508)
+ ret
+
+.mobile ; d509 (3:5509)
+ farcall StubbedTrainerRankings_StepCount
+ ret
+
+.fail2 ; d510 (3:5510)
+ ret
+
+UpdatePlayerCoords: ; d511 (3:5511)
+ ld a, [wPlayerStepDirection]
+ and a
+ jr nz, .check_step_down
+ ld hl, wYCoord
+ inc [hl]
+ ret
+
+.check_step_down
+ cp UP
+ jr nz, .check_step_left
+ ld hl, wYCoord
+ dec [hl]
+ ret
+
+.check_step_left
+ cp LEFT
+ jr nz, .check_step_right
+ ld hl, wXCoord
+ dec [hl]
+ ret
+
+.check_step_right
+ cp RIGHT
+ ret nz
+ ld hl, wXCoord
+ inc [hl]
+ ret
+
+UpdateOverworldMap: ; d536 (3:5536)
+ ld a, [wPlayerStepDirection]
+ and a
+ jr z, .step_down
+ cp UP
+ jr z, .step_up
+ cp LEFT
+ jr z, .step_left
+ cp RIGHT
+ jr z, .step_right
+ ret
+
+.step_down
+ call .ScrollOverworldMapDown
+ call LoadMapPart
+ call ScrollMapUp
+ ret
+
+.step_up
+ call .ScrollOverworldMapUp
+ call LoadMapPart
+ call ScrollMapDown
+ ret
+
+.step_left
+ call .ScrollOverworldMapLeft
+ call LoadMapPart
+ call ScrollMapRight
+ ret
+
+.step_right
+ call .ScrollOverworldMapRight
+ call LoadMapPart
+ call ScrollMapLeft
+ ret
+
+.ScrollOverworldMapDown: ; d571 (3:5571)
+ ld a, [wBGMapAnchor]
+ add 2 * BG_MAP_WIDTH
+ ld [wBGMapAnchor], a
+ jr nc, .not_overflowed
+ ld a, [wBGMapAnchor + 1]
+ inc a
+ and %11
+ or HIGH(vBGMap0)
+ ld [wBGMapAnchor + 1], a
+.not_overflowed
+ ld hl, wMetatileStandingY
+ inc [hl]
+ ld a, [hl]
+ cp 2 ; was 1
+ jr nz, .done_down
+ ld [hl], 0
+ call .Add6ToOverworldMapAnchor
+.done_down
+ ret
+
+.Add6ToOverworldMapAnchor: ; d595 (3:5595)
+ ld hl, wOverworldMapAnchor
+ ld a, [wMapWidth]
+ add 6
+ add [hl]
+ ld [hli], a
+ ret nc
+ inc [hl]
+ ret
+
+.ScrollOverworldMapUp: ; d5a2 (3:55a2)
+ ld a, [wBGMapAnchor]
+ sub 2 * BG_MAP_WIDTH
+ ld [wBGMapAnchor], a
+ jr nc, .not_underflowed
+ ld a, [wBGMapAnchor + 1]
+ dec a
+ and %11
+ or HIGH(vBGMap0)
+ ld [wBGMapAnchor + 1], a
+.not_underflowed
+ ld hl, wMetatileStandingY
+ dec [hl]
+ ld a, [hl]
+ cp -1 ; was 0
+ jr nz, .done_up
+ ld [hl], $1
+ call .Sub6FromOverworldMapAnchor
+.done_up
+ ret
+
+.Sub6FromOverworldMapAnchor: ; d5c6 (3:55c6)
+ ld hl, wOverworldMapAnchor
+ ld a, [wMapWidth]
+ add 6
+ ld b, a
+ ld a, [hl]
+ sub b
+ ld [hli], a
+ ret nc
+ dec [hl]
+ ret
+
+.ScrollOverworldMapLeft: ; d5d5 (3:55d5)
+ ld a, [wBGMapAnchor]
+ ld e, a
+ and $e0
+ ld d, a
+ ld a, e
+ sub $2
+ and $1f
+ or d
+ ld [wBGMapAnchor], a
+ ld hl, wMetatileStandingX
+ dec [hl]
+ ld a, [hl]
+ cp -1
+ jr nz, .done_left
+ ld [hl], 1
+ call .DecrementwOverworldMapAnchor
+.done_left
+ ret
+
+.DecrementwOverworldMapAnchor: ; d5f4 (3:55f4)
+ ld hl, wOverworldMapAnchor
+ ld a, [hl]
+ sub 1
+ ld [hli], a
+ ret nc
+ dec [hl]
+ ret
+
+.ScrollOverworldMapRight: ; d5fe (3:55fe)
+ ld a, [wBGMapAnchor]
+ ld e, a
+ and $e0
+ ld d, a
+ ld a, e
+ add $2
+ and $1f
+ or d
+ ld [wBGMapAnchor], a
+ ld hl, wMetatileStandingX
+ inc [hl]
+ ld a, [hl]
+ cp 2
+ jr nz, .done_right
+ ld [hl], 0
+ call .IncrementwOverworldMapAnchor
+.done_right
+ ret
+
+.IncrementwOverworldMapAnchor: ; d61d (3:561d)
+ ld hl, wOverworldMapAnchor
+ ld a, [hl]
+ add 1
+ ld [hli], a
+ ret nc
+ inc [hl]
+ ret
diff --git a/engine/overworld/scripting.asm b/engine/overworld/scripting.asm
new file mode 100644
index 000000000..f65f2f9c0
--- /dev/null
+++ b/engine/overworld/scripting.asm
@@ -0,0 +1,2857 @@
+; Event scripting commands.
+
+
+EnableScriptMode::
+ push af
+ ld a, SCRIPT_READ
+ ld [wScriptMode], a
+ pop af
+ ret
+
+ScriptEvents::
+ call StartScript
+.loop
+ ld a, [wScriptMode]
+ ld hl, .modes
+ rst JumpTable
+ call CheckScript
+ jr nz, .loop
+ ret
+
+.modes
+ dw EndScript
+ dw RunScriptCommand
+ dw WaitScriptMovement
+ dw WaitScript
+
+EndScript:
+ call StopScript
+ ret
+
+WaitScript:
+ call StopScript
+
+ ld hl, wScriptDelay
+ dec [hl]
+ ret nz
+
+ farcall Function58b9
+
+ ld a, SCRIPT_READ
+ ld [wScriptMode], a
+ call StartScript
+ ret
+
+WaitScriptMovement:
+ call StopScript
+
+ ld hl, wVramState
+ bit 7, [hl]
+ ret nz
+
+ farcall Function58b9
+
+ ld a, SCRIPT_READ
+ ld [wScriptMode], a
+ call StartScript
+ ret
+
+RunScriptCommand:
+ call GetScriptByte
+ ld hl, ScriptCommandTable
+ rst JumpTable
+ ret
+
+
+ScriptCommandTable:
+; entries correspond to macros/scripts/events.asm enumeration
+ dw Script_scall ; 00
+ dw Script_farscall ; 01
+ dw Script_ptcall ; 02
+ dw Script_jump ; 03
+ dw Script_farjump ; 04
+ dw Script_ptjump ; 05
+ dw Script_ifequal ; 06
+ dw Script_ifnotequal ; 07
+ dw Script_iffalse ; 08
+ dw Script_iftrue ; 09
+ dw Script_ifgreater ; 0a
+ dw Script_ifless ; 0b
+ dw Script_jumpstd ; 0c
+ dw Script_callstd ; 0d
+ dw Script_callasm ; 0e
+ dw Script_special ; 0f
+ dw Script_ptcallasm ; 10
+ dw Script_checkmapscene ; 11
+ dw Script_setmapscene ; 12
+ dw Script_checkscene ; 13
+ dw Script_setscene ; 14
+ dw Script_writebyte ; 15
+ dw Script_addvar ; 16
+ dw Script_random ; 17
+ dw Script_checkver ; 18
+ dw Script_copybytetovar ; 19
+ dw Script_copyvartobyte ; 1a
+ dw Script_loadvar ; 1b
+ dw Script_checkcode ; 1c
+ dw Script_writevarcode ; 1d
+ dw Script_writecode ; 1e
+ dw Script_giveitem ; 1f
+ dw Script_takeitem ; 20
+ dw Script_checkitem ; 21
+ dw Script_givemoney ; 22
+ dw Script_takemoney ; 23
+ dw Script_checkmoney ; 24
+ dw Script_givecoins ; 25
+ dw Script_takecoins ; 26
+ dw Script_checkcoins ; 27
+ dw Script_addcellnum ; 28
+ dw Script_delcellnum ; 29
+ dw Script_checkcellnum ; 2a
+ dw Script_checktime ; 2b
+ dw Script_checkpoke ; 2c
+ dw Script_givepoke ; 2d
+ dw Script_giveegg ; 2e
+ dw Script_givepokeitem ; 2f
+ dw Script_checkpokeitem ; 30
+ dw Script_checkevent ; 31
+ dw Script_clearevent ; 32
+ dw Script_setevent ; 33
+ dw Script_checkflag ; 34
+ dw Script_clearflag ; 35
+ dw Script_setflag ; 36
+ dw Script_wildon ; 37
+ dw Script_wildoff ; 38
+ dw Script_xycompare ; 39
+ dw Script_warpmod ; 3a
+ dw Script_blackoutmod ; 3b
+ dw Script_warp ; 3c
+ dw Script_readmoney ; 3d
+ dw Script_readcoins ; 3e
+ dw Script_vartomem ; 3f
+ dw Script_pokenamemem ; 40
+ dw Script_itemtotext ; 41
+ dw Script_mapnametotext ; 42
+ dw Script_trainertotext ; 43
+ dw Script_stringtotext ; 44
+ dw Script_itemnotify ; 45
+ dw Script_pocketisfull ; 46
+ dw Script_opentext ; 47
+ dw Script_refreshscreen ; 48
+ dw Script_closetext ; 49
+ dw Script_loadbytec2cf ; 4a
+ dw Script_farwritetext ; 4b
+ dw Script_writetext ; 4c
+ dw Script_repeattext ; 4d
+ dw Script_yesorno ; 4e
+ dw Script_loadmenu ; 4f
+ dw Script_closewindow ; 50
+ dw Script_jumptextfaceplayer ; 51
+if _CRYSTAL
+ dw Script_farjumptext ; 52
+endc
+ dw Script_jumptext ; 53
+ dw Script_waitbutton ; 54
+ dw Script_buttonsound ; 55
+ dw Script_pokepic ; 56
+ dw Script_closepokepic ; 57
+ dw Script__2dmenu ; 58
+ dw Script_verticalmenu ; 59
+ dw Script_loadpikachudata ; 5a
+ dw Script_randomwildmon ; 5b
+ dw Script_loadmemtrainer ; 5c
+ dw Script_loadwildmon ; 5d
+ dw Script_loadtrainer ; 5e
+ dw Script_startbattle ; 5f
+ dw Script_reloadmapafterbattle ; 60
+ dw Script_catchtutorial ; 61
+ dw Script_trainertext ; 62
+ dw Script_trainerflagaction ; 63
+ dw Script_winlosstext ; 64
+ dw Script_scripttalkafter ; 65
+ dw Script_endifjustbattled ; 66
+ dw Script_checkjustbattled ; 67
+ dw Script_setlasttalked ; 68
+ dw Script_applymovement ; 69
+ dw Script_applymovement2 ; 6a
+ dw Script_faceplayer ; 6b
+ dw Script_faceobject ; 6c
+ dw Script_variablesprite ; 6d
+ dw Script_disappear ; 6e
+ dw Script_appear ; 6f
+ dw Script_follow ; 70
+ dw Script_stopfollow ; 71
+ dw Script_moveobject ; 72
+ dw Script_writeobjectxy ; 73
+ dw Script_loademote ; 74
+ dw Script_showemote ; 75
+ dw Script_turnobject ; 76
+ dw Script_follownotexact ; 77
+ dw Script_earthquake ; 78
+ dw Script_changemap ; 79
+ dw Script_changeblock ; 7a
+ dw Script_reloadmap ; 7b
+ dw Script_reloadmappart ; 7c
+ dw Script_writecmdqueue ; 7d
+ dw Script_delcmdqueue ; 7e
+ dw Script_playmusic ; 7f
+ dw Script_encountermusic ; 80
+ dw Script_musicfadeout ; 81
+ dw Script_playmapmusic ; 82
+ dw Script_dontrestartmapmusic ; 83
+ dw Script_cry ; 84
+ dw Script_playsound ; 85
+ dw Script_waitsfx ; 86
+ dw Script_warpsound ; 87
+ dw Script_specialsound ; 88
+ dw Script_passtoengine ; 89
+ dw Script_newloadmap ; 8a
+ dw Script_pause ; 8b
+ dw Script_deactivatefacing ; 8c
+ dw Script_priorityjump ; 8d
+ dw Script_warpcheck ; 8e
+ dw Script_ptpriorityjump ; 8f
+ dw Script_return ; 90
+ dw Script_end ; 91
+ dw Script_reloadandreturn ; 92
+ dw Script_endall ; 93
+ dw Script_pokemart ; 94
+ dw Script_elevator ; 95
+ dw Script_trade ; 96
+ dw Script_askforphonenumber ; 97
+ dw Script_phonecall ; 98
+ dw Script_hangup ; 99
+ dw Script_describedecoration ; 9a
+ dw Script_fruittree ; 9b
+ dw Script_specialphonecall ; 9c
+ dw Script_checkphonecall ; 9d
+ dw Script_verbosegiveitem ; 9e
+ dw Script_verbosegiveitem2 ; 9f
+ dw Script_swarm ; a0
+ dw Script_halloffame ; a1
+ dw Script_credits ; a2
+ dw Script_warpfacing ; a3
+ dw Script_battletowertext ; a4
+ dw Script_landmarktotext ; a5
+ dw Script_trainerclassname ; a6
+ dw Script_name ; a7
+ dw Script_wait ; a8
+ dw Script_checksave ; a9
+
+StartScript:
+ ld hl, wScriptFlags
+ set SCRIPT_RUNNING, [hl]
+ ret
+
+CheckScript:
+ ld hl, wScriptFlags
+ bit SCRIPT_RUNNING, [hl]
+ ret
+
+StopScript:
+ ld hl, wScriptFlags
+ res SCRIPT_RUNNING, [hl]
+ ret
+
+Script_callasm:
+; script command 0xe
+; parameters: asm
+
+ call GetScriptByte
+ ld b, a
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ ld a, b
+ rst FarCall
+ ret
+
+Script_special:
+; script command 0xf
+; parameters: predefined_script
+
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ farcall Special
+ ret
+
+Script_ptcallasm:
+; script command 0x10
+; parameters: asm
+
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ ld b, [hl]
+ inc hl
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, b
+ rst FarCall
+ ret
+
+Script_jumptextfaceplayer:
+; script command 0x51
+; parameters: text_pointer
+
+ ld a, [wScriptBank]
+ ld [wScriptTextBank], a
+ call GetScriptByte
+ ld [wScriptTextAddr], a
+ call GetScriptByte
+ ld [wScriptTextAddr + 1], a
+ ld b, BANK(JumpTextFacePlayerScript)
+ ld hl, JumpTextFacePlayerScript
+ jp ScriptJump
+
+Script_jumptext:
+; script command 0x53
+; parameters: text_pointer
+
+ ld a, [wScriptBank]
+ ld [wScriptTextBank], a
+ call GetScriptByte
+ ld [wScriptTextAddr], a
+ call GetScriptByte
+ ld [wScriptTextAddr + 1], a
+ ld b, BANK(JumpTextScript)
+ ld hl, JumpTextScript
+ jp ScriptJump
+
+JumpTextFacePlayerScript:
+ faceplayer
+JumpTextScript:
+ opentext
+ repeattext -1, -1
+ waitbutton
+ closetext
+ end
+
+
+if _CRYSTAL
+
+Script_farjumptext:
+; script command 0x52
+; parameters: text_pointer
+
+ call GetScriptByte
+ ld [wScriptTextBank], a
+ call GetScriptByte
+ ld [wScriptTextAddr], a
+ call GetScriptByte
+ ld [wScriptTextAddr + 1], a
+ ld b, BANK(JumpTextScript)
+ ld hl, JumpTextScript
+ jp ScriptJump
+
+endc
+
+
+Script_writetext:
+; script command 0x4c
+; parameters: text_pointer
+
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ ld a, [wScriptBank]
+ ld b, a
+ call MapTextbox
+ ret
+
+Script_farwritetext:
+; script command 0x4b
+; parameters: text_pointer
+
+ call GetScriptByte
+ ld b, a
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ call MapTextbox
+ ret
+
+Script_repeattext:
+; script command 0x4d
+; parameters: byte, byte
+
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ cp -1
+ jr nz, .done
+ ld a, l
+ cp -1
+ jr nz, .done
+ ld hl, wScriptTextBank
+ ld a, [hli]
+ ld b, a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ call MapTextbox
+ ret
+
+.done
+ ret
+
+Script_waitbutton:
+; script command 0x54
+
+ jp WaitButton
+
+Script_buttonsound:
+; script command 0x55
+
+ ld a, [hOAMUpdate]
+ push af
+ ld a, $1
+ ld [hOAMUpdate], a
+ call WaitBGMap
+ call ButtonSound
+ pop af
+ ld [hOAMUpdate], a
+ ret
+
+Script_yesorno:
+; script command 0x4e
+
+ call YesNoBox
+ ld a, FALSE
+ jr c, .no
+ ld a, TRUE
+.no
+ ld [wScriptVar], a
+ ret
+
+Script_loadmenu:
+; script command 0x4f
+; parameters: menu_header
+
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ ld de, LoadMenuHeader
+ ld a, [wScriptBank]
+ call Call_a_de
+ call UpdateSprites
+ ret
+
+Script_closewindow:
+; script command 0x50
+
+ call CloseWindow
+ call UpdateSprites
+ ret
+
+Script_pokepic:
+; script command 0x56
+; parameters: pokemon
+
+ call GetScriptByte
+ and a
+ jr nz, .ok
+ ld a, [wScriptVar]
+.ok
+ ld [wCurPartySpecies], a
+ farcall Pokepic
+ ret
+
+Script_closepokepic:
+; script command 0x57
+
+ farcall ClosePokepic
+ ret
+
+Script_verticalmenu:
+; script command 0x59
+
+ ld a, [wScriptBank]
+ ld hl, VerticalMenu
+ rst FarCall
+ ld a, [wMenuCursorY]
+ jr nc, .ok
+ xor a
+.ok
+ ld [wScriptVar], a
+ ret
+
+Script__2dmenu:
+; script command 0x58
+
+ ld a, [wScriptBank]
+ ld hl, _2DMenu
+ rst FarCall
+ ld a, [wMenuCursorBuffer]
+ jr nc, .ok
+ xor a
+.ok
+ ld [wScriptVar], a
+ ret
+
+Script_battletowertext:
+; script command 0xa4
+; parameters: pointer, memory
+
+ call SetUpTextBox
+ call GetScriptByte
+ ld c, a
+ farcall BattleTowerText
+ ret
+
+Script_verbosegiveitem:
+; script command 0x9e
+; parameters: item, quantity
+
+ call Script_giveitem
+ call CurItemName
+ ld de, wStringBuffer1
+ ld a, 1
+ call CopyConvertedText
+ ld b, BANK(GiveItemScript)
+ ld de, GiveItemScript
+ jp ScriptCall
+
+
+ret_96f76:
+ ret
+
+GiveItemScript:
+ callasm ret_96f76
+ writetext ReceivedItemText
+ iffalse .Full
+ waitsfx
+ specialsound
+ waitbutton
+ itemnotify
+ end
+
+.Full:
+ buttonsound
+ pocketisfull
+ end
+
+ReceivedItemText:
+ text_jump UnknownText_0x1c4719
+ db "@"
+
+
+Script_verbosegiveitem2:
+; script command 0x9f
+; parameters: item, var
+
+ call GetScriptByte
+ cp -1
+ jr nz, .ok
+ ld a, [wScriptVar]
+.ok
+ ld [wCurItem], a
+ call GetScriptByte
+ call GetVarAction
+ ld a, [de]
+ ld [wItemQuantityChangeBuffer], a
+ ld hl, wNumItems
+ call ReceiveItem
+ ld a, TRUE
+ jr c, .ok2
+ xor a
+.ok2
+ ld [wScriptVar], a
+ call CurItemName
+ ld de, wStringBuffer1
+ ld a, 1
+ call CopyConvertedText
+ ld b, BANK(GiveItemScript)
+ ld de, GiveItemScript
+ jp ScriptCall
+
+Script_itemnotify:
+; script command 0x45
+
+ call GetPocketName
+ call CurItemName
+ ld b, BANK(PutItemInPocketText)
+ ld hl, PutItemInPocketText
+ call MapTextbox
+ ret
+
+Script_pocketisfull:
+; script command 0x46
+
+ call GetPocketName
+ call CurItemName
+ ld b, BANK(PocketIsFullText)
+ ld hl, PocketIsFullText
+ call MapTextbox
+ ret
+
+Script_specialsound:
+; script command 0x88
+
+ farcall CheckItemPocket
+ ld a, [wItemAttributeParamBuffer]
+ cp TM_HM
+ ld de, SFX_GET_TM
+ jr z, .play
+ ld de, SFX_ITEM
+.play
+ call PlaySFX
+ call WaitSFX
+ ret
+
+
+GetPocketName:
+ farcall CheckItemPocket
+ ld a, [wItemAttributeParamBuffer]
+ dec a
+ ld hl, .Pockets
+ maskbits NUM_POCKETS
+ add a
+ ld e, a
+ ld d, 0
+ add hl, de
+ ld a, [hli]
+ ld d, [hl]
+ ld e, a
+ ld hl, wStringBuffer3
+ call CopyName2
+ ret
+
+.Pockets:
+ dw .Item
+ dw .Key
+ dw .Ball
+ dw .TM
+
+.Item:
+ db "ITEM POCKET@"
+.Key:
+ db "KEY POCKET@"
+.Ball:
+ db "BALL POCKET@"
+.TM:
+ db "TM POCKET@"
+
+CurItemName:
+ ld a, [wCurItem]
+ ld [wd265], a
+ call GetItemName
+ ret
+
+
+PutItemInPocketText:
+ text_jump UnknownText_0x1c472c
+ db "@"
+
+PocketIsFullText:
+ text_jump UnknownText_0x1c474b
+ db "@"
+
+
+Script_pokemart:
+; script command 0x94
+; parameters: dialog_id, mart_id
+
+ call GetScriptByte
+ ld c, a
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld a, [wScriptBank]
+ ld b, a
+ farcall OpenMartDialog
+ ret
+
+Script_elevator:
+; script command 0x95
+; parameters: floor_list_pointer
+
+ xor a
+ ld [wScriptVar], a
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld a, [wScriptBank]
+ ld b, a
+ farcall Elevator
+ ret c
+ ld a, TRUE
+ ld [wScriptVar], a
+ ret
+
+Script_trade:
+; script command 0x96
+; parameters: trade_id
+
+ call GetScriptByte
+ ld e, a
+ farcall NPCTrade
+ ret
+
+Script_phonecall:
+; script command 0x98
+; parameters: caller_name
+
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld a, [wScriptBank]
+ ld b, a
+ farcall PhoneCall
+ ret
+
+Script_hangup:
+; script command 0x99
+
+ farcall HangUp
+ ret
+
+Script_askforphonenumber:
+; script command 0x97
+; parameters: number
+
+ call YesNoBox
+ jr c, .refused
+ call GetScriptByte
+ ld c, a
+ farcall AddPhoneNumber
+ jr c, .phonefull
+ xor a ; PHONE_CONTACT_GOT
+ jr .done
+.phonefull
+ ld a, PHONE_CONTACTS_FULL
+ jr .done
+.refused
+ call GetScriptByte
+ ld a, PHONE_CONTACT_REFUSED
+.done
+ ld [wScriptVar], a
+ ret
+
+Script_describedecoration:
+; script command 0x9a
+; parameters: byte
+
+ call GetScriptByte
+ ld b, a
+ farcall DescribeDecoration
+ ld h, d
+ ld l, e
+ jp ScriptJump
+
+Script_fruittree:
+; script command 0x9b
+; parameters: tree_id
+
+ call GetScriptByte
+ ld [wCurFruitTree], a
+ ld b, BANK(FruitTreeScript)
+ ld hl, FruitTreeScript
+ jp ScriptJump
+
+Script_swarm:
+; script command 0xa0
+; parameters: flag, map_group, map_id
+
+ call GetScriptByte
+ ld c, a
+ call GetScriptByte
+ ld d, a
+ call GetScriptByte
+ ld e, a
+ farcall StoreSwarmMapIndices
+ ret
+
+Script_trainertext:
+; script command 0x62
+; parameters: which_text
+
+ call GetScriptByte
+ ld c, a
+ ld b, 0
+ ld hl, wWalkingX
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wEngineBuffer1]
+ ld b, a
+ call MapTextbox
+ ret
+
+Script_scripttalkafter:
+; script command 0x65
+
+ ld hl, wScriptAfterPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wEngineBuffer1]
+ ld b, a
+ jp ScriptJump
+
+Script_trainerflagaction:
+; script command 0x63
+; parameters: action
+
+ xor a
+ ld [wScriptVar], a
+ ld hl, wd041
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ call GetScriptByte
+ ld b, a
+ call EventFlagAction
+ ld a, c
+ and a
+ ret z
+ ld a, TRUE
+ ld [wScriptVar], a
+ ret
+
+Script_winlosstext:
+; script command 0x64
+; parameters: win_text_pointer, loss_text_pointer
+
+ ld hl, wWinTextPointer
+ call GetScriptByte
+ ld [hli], a
+ call GetScriptByte
+ ld [hli], a
+ ld hl, wLossTextPointer
+ call GetScriptByte
+ ld [hli], a
+ call GetScriptByte
+ ld [hli], a
+ ret
+
+Script_endifjustbattled:
+; script command 0x66
+
+ ld a, [wRunningTrainerBattleScript]
+ and a
+ ret z
+ jp Script_end
+
+Script_checkjustbattled:
+; script command 0x67
+
+ ld a, TRUE
+ ld [wScriptVar], a
+ ld a, [wRunningTrainerBattleScript]
+ and a
+ ret nz
+ xor a
+ ld [wScriptVar], a
+ ret
+
+Script_encountermusic:
+; script command 0x80
+
+ ld a, [wOtherTrainerClass]
+ ld e, a
+ farcall PlayTrainerEncounterMusic
+ ret
+
+Script_playmapmusic:
+; script command 0x82
+
+ call PlayMapMusic
+ ret
+
+Script_playmusic:
+; script command 0x7f
+; parameters: music_pointer
+
+ ld de, MUSIC_NONE
+ call PlayMusic
+ xor a
+ ld [wMusicFade], a
+ call MaxVolume
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ call PlayMusic
+ ret
+
+Script_musicfadeout:
+; script command 0x81
+; parameters: music, fadetime
+
+ call GetScriptByte
+ ld [wMusicFadeID], a
+ call GetScriptByte
+ ld [wMusicFadeID + 1], a
+ call GetScriptByte
+ and $ff ^ (1 << MUSIC_FADE_IN_F)
+ ld [wMusicFade], a
+ ret
+
+Script_playsound:
+; script command 0x85
+; parameters: sound_pointer
+
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ call PlaySFX
+ ret
+
+Script_waitsfx:
+; script command 0x86
+
+ call WaitSFX
+ ret
+
+Script_warpsound:
+; script command 0x87
+
+ farcall GetWarpSFX
+ call PlaySFX
+ ret
+
+Script_cry:
+; script command 0x84
+; parameters: cry_id
+
+ call GetScriptByte
+ push af
+ call GetScriptByte
+ pop af
+ and a
+ jr nz, .ok
+ ld a, [wScriptVar]
+.ok
+ call PlayMonCry
+ ret
+
+GetScriptObject:
+ and a ; PLAYER?
+ ret z
+ cp LAST_TALKED
+ ret z
+ dec a
+ ret
+
+Script_setlasttalked:
+; script command 0x68
+; parameters: object_id
+
+ call GetScriptByte
+ call GetScriptObject
+ ld [hLastTalked], a
+ ret
+
+Script_applymovement:
+; script command 0x69
+; parameters: object_id, data
+
+ call GetScriptByte
+ call GetScriptObject
+ ld c, a
+
+ApplyMovement:
+ push bc
+ ld a, c
+ farcall SetFlagsForMovement_1
+ pop bc
+
+ push bc
+ call SetFlagsForMovement_2
+ pop bc
+
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ ld a, [wScriptBank]
+ ld b, a
+ call GetMovementData
+ ret c
+
+ ld a, SCRIPT_WAIT_MOVEMENT
+ ld [wScriptMode], a
+ call StopScript
+ ret
+
+SetFlagsForMovement_2:
+ farcall _SetFlagsForMovement_2
+ ret
+
+Script_applymovement2:
+; script command 0x6a
+; parameters: data
+; apply movement to last talked
+
+ ld a, [hLastTalked]
+ ld c, a
+ jp ApplyMovement
+
+Script_faceplayer:
+; script command 0x6b
+
+ ld a, [hLastTalked]
+ and a
+ ret z
+ ld d, $0
+ ld a, [hLastTalked]
+ ld e, a
+ farcall GetRelativeFacing
+ ld a, d
+ add a
+ add a
+ ld e, a
+ ld a, [hLastTalked]
+ ld d, a
+ call ApplyObjectFacing
+ ret
+
+Script_faceobject:
+; script command 0x6c
+; parameters: object1, object2
+
+ call GetScriptByte
+ call GetScriptObject
+ cp LAST_TALKED
+ jr c, .ok
+ ld a, [hLastTalked]
+.ok
+ ld e, a
+ call GetScriptByte
+ call GetScriptObject
+ cp LAST_TALKED
+ jr nz, .ok2
+ ld a, [hLastTalked]
+.ok2
+ ld d, a
+ push de
+ farcall GetRelativeFacing
+ pop bc
+ ret c
+ ld a, d
+ add a
+ add a
+ ld e, a
+ ld d, c
+ call ApplyObjectFacing
+ ret
+
+Script_turnobject:
+; script command 0x76
+; parameters: object_id, facing
+
+ call GetScriptByte
+ call GetScriptObject
+ cp LAST_TALKED
+ jr nz, .ok
+ ld a, [hLastTalked]
+.ok
+ ld d, a
+ call GetScriptByte
+ add a
+ add a
+ ld e, a
+ call ApplyObjectFacing
+ ret
+
+ApplyObjectFacing:
+ ld a, d
+ push de
+ call CheckObjectVisibility
+ jr c, .not_visible
+ ld hl, OBJECT_SPRITE
+ add hl, bc
+ ld a, [hl]
+ push bc
+ call DoesSpriteHaveFacings
+ pop bc
+ jr c, .not_visible ; STILL_SPRITE
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ bit FIXED_FACING, [hl]
+ jr nz, .not_visible
+ pop de
+ ld a, e
+ call SetSpriteDirection
+ ld hl, wVramState
+ bit 6, [hl]
+ jr nz, .text_state
+ call .DisableTextTiles
+.text_state
+ call UpdateSprites
+ ret
+
+.not_visible
+ pop de
+ scf
+ ret
+
+.DisableTextTiles:
+ call LoadMapPart
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+.loop
+ res 7, [hl]
+ inc hl
+ dec bc
+ ld a, b
+ or c
+ jr nz, .loop
+ ret
+
+Script_variablesprite:
+; script command 0x6d
+; parameters: byte, sprite
+
+ call GetScriptByte
+ ld e, a
+ ld d, $0
+ ld hl, wVariableSprites
+ add hl, de
+ call GetScriptByte
+ ld [hl], a
+ ret
+
+Script_appear:
+; script command 0x6f
+; parameters: object_id
+
+ call GetScriptByte
+ call GetScriptObject
+ call _CopyObjectStruct
+ ld a, [hMapObjectIndexBuffer]
+ ld b, 0 ; clear
+ call ApplyEventActionAppearDisappear
+ ret
+
+Script_disappear:
+; script command 0x6e
+; parameters: object_id
+
+ call GetScriptByte
+ call GetScriptObject
+ cp LAST_TALKED
+ jr nz, .ok
+ ld a, [hLastTalked]
+.ok
+ call DeleteObjectStruct
+ ld a, [hMapObjectIndexBuffer]
+ ld b, 1 ; set
+ call ApplyEventActionAppearDisappear
+ farcall _UpdateSprites
+ ret
+
+ApplyEventActionAppearDisappear:
+ push bc
+ call GetMapObject
+ ld hl, MAPOBJECT_EVENT_FLAG
+ add hl, bc
+ pop bc
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ld a, -1
+ cp e
+ jr nz, .okay
+ cp d
+ jr nz, .okay
+ xor a
+ ret
+.okay
+ call EventFlagAction
+ ret
+
+Script_follow:
+; script command 0x70
+; parameters: object2, object1
+
+ call GetScriptByte
+ call GetScriptObject
+ ld b, a
+ call GetScriptByte
+ call GetScriptObject
+ ld c, a
+ farcall StartFollow
+ ret
+
+Script_stopfollow:
+; script command 0x71
+
+ farcall StopFollow
+ ret
+
+Script_moveobject:
+; script command 0x72
+; parameters: object id, x, y
+
+ call GetScriptByte
+ call GetScriptObject
+ ld b, a
+ call GetScriptByte
+ add 4
+ ld d, a
+ call GetScriptByte
+ add 4
+ ld e, a
+ farcall CopyDECoordsToMapObject
+ ret
+
+Script_writeobjectxy:
+; script command 0x73
+; parameters: object_id
+
+ call GetScriptByte
+ call GetScriptObject
+ cp LAST_TALKED
+ jr nz, .ok
+ ld a, [hLastTalked]
+.ok
+ ld b, a
+ farcall WriteObjectXY
+ ret
+
+Script_follownotexact:
+; script command 0x77
+; parameters: object2, object1
+
+ call GetScriptByte
+ call GetScriptObject
+ ld b, a
+ call GetScriptByte
+ call GetScriptObject
+ ld c, a
+ farcall FollowNotExact
+ ret
+
+Script_loademote:
+; script command 0x74
+; parameters: bubble
+
+ call GetScriptByte
+ cp -1
+ jr nz, .not_var_emote
+ ld a, [wScriptVar]
+.not_var_emote
+ ld c, a
+ farcall LoadEmote
+ ret
+
+Script_showemote:
+; script command 0x75
+; parameters: bubble, object_id, time
+
+ call GetScriptByte
+ ld [wScriptVar], a
+ call GetScriptByte
+ call GetScriptObject
+ cp LAST_TALKED
+ jr z, .ok
+ ld [hLastTalked], a
+.ok
+ call GetScriptByte
+ ld [wScriptDelay], a
+ ld b, BANK(ShowEmoteScript)
+ ld de, ShowEmoteScript
+ jp ScriptCall
+
+ShowEmoteScript:
+ loademote EMOTE_MEM
+ applymovement2 .Show
+ pause 0
+ applymovement2 .Hide
+ end
+
+.Show:
+ show_emote
+ step_sleep 1
+ step_end
+
+.Hide:
+ hide_emote
+ step_sleep 1
+ step_end
+
+
+Script_earthquake:
+; script command 0x78
+; parameters: param
+
+ ld hl, EarthquakeMovement
+ ld de, wEarthquakeMovementDataBuffer
+ ld bc, EarthquakeMovement.End - EarthquakeMovement
+ call CopyBytes
+ call GetScriptByte
+ ld [wEarthquakeMovementDataBuffer + 1], a
+ and %00111111
+ ld [wEarthquakeMovementDataBuffer + 3], a
+ ld b, BANK(.script)
+ ld de, .script
+ jp ScriptCall
+
+.script
+ applymovement PLAYER, wEarthquakeMovementDataBuffer
+ end
+
+EarthquakeMovement:
+ step_shake 16 ; the 16 gets overwritten with the script byte
+ step_sleep 16 ; the 16 gets overwritten with the lower 6 bits of the script byte
+ step_end
+.End
+
+
+Script_loadpikachudata:
+; script command 0x5a
+
+ ld a, PIKACHU
+ ld [wTempWildMonSpecies], a
+ ld a, 5
+ ld [wCurPartyLevel], a
+ ret
+
+Script_randomwildmon:
+; script command 0x5b
+
+ xor a
+ ld [wBattleScriptFlags], a
+ ret
+
+Script_loadmemtrainer:
+; script command 0x5c
+
+ ld a, (1 << 7) | 1
+ ld [wBattleScriptFlags], a
+ ld a, [wTempTrainerClass]
+ ld [wOtherTrainerClass], a
+ ld a, [wTempTrainerID]
+ ld [wOtherTrainerID], a
+ ret
+
+Script_loadwildmon:
+; script command 0x5d
+; parameters: pokemon, level
+
+ ld a, (1 << 7)
+ ld [wBattleScriptFlags], a
+ call GetScriptByte
+ ld [wTempWildMonSpecies], a
+ call GetScriptByte
+ ld [wCurPartyLevel], a
+ ret
+
+Script_loadtrainer:
+; script command 0x5e
+; parameters: trainer_group, trainer_id
+
+ ld a, (1 << 7) | 1
+ ld [wBattleScriptFlags], a
+ call GetScriptByte
+ ld [wOtherTrainerClass], a
+ call GetScriptByte
+ ld [wOtherTrainerID], a
+ ret
+
+Script_startbattle:
+; script command 0x5f
+
+ call BufferScreen
+ predef StartBattle
+ ld a, [wBattleResult]
+ and $3f
+ ld [wScriptVar], a
+ ret
+
+Script_catchtutorial:
+; script command 0x61
+; parameters: byte
+
+ call GetScriptByte
+ ld [wBattleType], a
+ call BufferScreen
+ farcall CatchTutorial
+ jp Script_reloadmap
+
+Script_reloadmapafterbattle:
+; script command 0x60
+
+ ld hl, wBattleScriptFlags
+ ld d, [hl]
+ ld [hl], $0
+ ld a, [wBattleResult]
+ and $3f
+ cp $1
+ jr nz, .notblackedout
+ ld b, BANK(Script_BattleWhiteout)
+ ld hl, Script_BattleWhiteout
+ jp ScriptJump
+
+.notblackedout
+ bit 0, d
+ jr z, .was_wild
+ farcall MomTriesToBuySomething
+ jr .done
+
+.was_wild
+ ld a, [wBattleResult]
+ bit 7, a
+ jr z, .done
+ ld b, BANK(Script_SpecialBillCall)
+ ld de, Script_SpecialBillCall
+ farcall LoadScriptBDE
+.done
+ jp Script_reloadmap
+
+Script_reloadmap:
+; script command 0x7b
+
+ xor a
+ ld [wBattleScriptFlags], a
+ ld a, MAPSETUP_RELOADMAP
+ ld [hMapEntryMethod], a
+ ld a, $1
+ call LoadMapStatus
+ call StopScript
+ ret
+
+Script_scall:
+; script command 0x0
+; parameters: pointer
+
+ ld a, [wScriptBank]
+ ld b, a
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ jr ScriptCall
+
+Script_farscall:
+; script command 0x1
+; parameters: pointer
+
+ call GetScriptByte
+ ld b, a
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ jr ScriptCall
+
+Script_ptcall:
+; script command 0x2
+; parameters: pointer
+
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ ld b, [hl]
+ inc hl
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ; fallthrough
+
+ScriptCall:
+; Bug: The script stack has a capacity of 5 scripts, yet there is
+; nothing to stop you from pushing a sixth script. The high part
+; of the script address can then be overwritten by modifications
+; to wScriptDelay, causing the script to return to the rst/interrupt
+; space.
+
+ push de
+ ld hl, wScriptStackSize
+ ld e, [hl]
+ inc [hl]
+ ld d, $0
+ ld hl, wScriptStack
+ add hl, de
+ add hl, de
+ add hl, de
+ pop de
+ ld a, [wScriptBank]
+ ld [hli], a
+ ld a, [wScriptPos]
+ ld [hli], a
+ ld a, [wScriptPos + 1]
+ ld [hl], a
+ ld a, b
+ ld [wScriptBank], a
+ ld a, e
+ ld [wScriptPos], a
+ ld a, d
+ ld [wScriptPos + 1], a
+ ret
+
+CallCallback::
+ ld a, [wScriptBank]
+ or $80
+ ld [wScriptBank], a
+ jp ScriptCall
+
+Script_jump:
+; script command 0x3
+; parameters: pointer
+
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ ld a, [wScriptBank]
+ ld b, a
+ jp ScriptJump
+
+Script_farjump:
+; script command 0x4
+; parameters: pointer
+
+ call GetScriptByte
+ ld b, a
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ jp ScriptJump
+
+Script_ptjump:
+; script command 0x5
+; parameters: pointer
+
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ ld b, [hl]
+ inc hl
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp ScriptJump
+
+Script_iffalse:
+; script command 0x8
+; parameters: pointer
+
+ ld a, [wScriptVar]
+ and a
+ jp nz, SkipTwoScriptBytes
+ jp Script_jump
+
+Script_iftrue:
+; script command 0x9
+; parameters: pointer
+
+ ld a, [wScriptVar]
+ and a
+ jp nz, Script_jump
+ jp SkipTwoScriptBytes
+
+Script_ifequal:
+; script command 0x6
+; parameters: byte, pointer
+
+ call GetScriptByte
+ ld hl, wScriptVar
+ cp [hl]
+ jr z, Script_jump
+ jr SkipTwoScriptBytes
+
+Script_ifnotequal:
+; script command 0x7
+; parameters: byte, pointer
+
+ call GetScriptByte
+ ld hl, wScriptVar
+ cp [hl]
+ jr nz, Script_jump
+ jr SkipTwoScriptBytes
+
+Script_ifgreater:
+; script command 0xa
+; parameters: byte, pointer
+
+ ld a, [wScriptVar]
+ ld b, a
+ call GetScriptByte
+ cp b
+ jr c, Script_jump
+ jr SkipTwoScriptBytes
+
+Script_ifless:
+; script command 0xb
+; parameters: byte, pointer
+
+ call GetScriptByte
+ ld b, a
+ ld a, [wScriptVar]
+ cp b
+ jr c, Script_jump
+ jr SkipTwoScriptBytes
+
+Script_jumpstd:
+; script command 0xc
+; parameters: predefined_script
+
+ call StdScript
+ jr ScriptJump
+
+Script_callstd:
+; script command 0xd
+; parameters: predefined_script
+
+ call StdScript
+ ld d, h
+ ld e, l
+ jp ScriptCall
+
+StdScript:
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld hl, StdScripts
+ add hl, de
+ add hl, de
+ add hl, de
+ ld a, BANK(StdScripts)
+ call GetFarByte
+ ld b, a
+ inc hl
+ ld a, BANK(StdScripts)
+ call GetFarHalfword
+ ret
+
+SkipTwoScriptBytes:
+ call GetScriptByte
+ call GetScriptByte
+ ret
+
+ScriptJump:
+ ld a, b
+ ld [wScriptBank], a
+ ld a, l
+ ld [wScriptPos], a
+ ld a, h
+ ld [wScriptPos + 1], a
+ ret
+
+Script_priorityjump:
+; script command 0x8d
+; parameters: pointer
+
+ ld a, [wScriptBank]
+ ld [wPriorityScriptBank], a
+ call GetScriptByte
+ ld [wPriorityScriptAddr], a
+ call GetScriptByte
+ ld [wPriorityScriptAddr + 1], a
+ ld hl, wScriptFlags
+ set 3, [hl]
+ ret
+
+Script_checkscene:
+; script command 0x13
+
+ call CheckScenes
+ jr z, .no_scene
+ ld [wScriptVar], a
+ ret
+
+.no_scene
+ ld a, $ff
+ ld [wScriptVar], a
+ ret
+
+Script_checkmapscene:
+; script command 0x11
+; parameters: map_group, map_id
+
+ call GetScriptByte
+ ld b, a
+ call GetScriptByte
+ ld c, a
+ call GetMapSceneID
+ ld a, d
+ or e
+ jr z, .no_scene
+ ld a, [de]
+ ld [wScriptVar], a
+ ret
+
+.no_scene
+ ld a, $ff
+ ld [wScriptVar], a
+ ret
+
+Script_setscene:
+; script command 0x14
+; parameters: scene_id
+
+ ld a, [wMapGroup]
+ ld b, a
+ ld a, [wMapNumber]
+ ld c, a
+ jr DoScene
+
+Script_setmapscene:
+; script command 0x12
+; parameters: map_group, map_id, scene_id
+
+ call GetScriptByte
+ ld b, a
+ call GetScriptByte
+ ld c, a
+DoScene:
+ call GetMapSceneID
+ ld a, d
+ or e
+ jr z, .no_scene
+ call GetScriptByte
+ ld [de], a
+.no_scene
+ ret
+
+Script_copybytetovar:
+; script command 0x19
+; parameters: address
+
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ ld a, [hl]
+ ld [wScriptVar], a
+ ret
+
+Script_copyvartobyte:
+; script command 0x1a
+; parameters: address
+
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ ld a, [wScriptVar]
+ ld [hl], a
+ ret
+
+Script_loadvar:
+; script command 0x1b
+; parameters: address, value
+
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ call GetScriptByte
+ ld [hl], a
+ ret
+
+Script_writebyte:
+; script command 0x15
+; parameters: value
+
+ call GetScriptByte
+ ld [wScriptVar], a
+ ret
+
+Script_addvar:
+; script command 0x16
+; parameters: value
+
+ call GetScriptByte
+ ld hl, wScriptVar
+ add [hl]
+ ld [hl], a
+ ret
+
+Script_random:
+; script command 0x17
+; parameters: input
+
+ call GetScriptByte
+ ld [wScriptVar], a
+ and a
+ ret z
+
+ ld c, a
+ call .Divide256byC
+ and a
+ jr z, .no_restriction ; 256 % b == 0
+ ld b, a
+ xor a
+ sub b
+ ld b, a
+.loop
+ push bc
+ call Random
+ pop bc
+ ld a, [hRandomAdd]
+ cp b
+ jr nc, .loop
+ jr .finish
+
+.no_restriction
+ push bc
+ call Random
+ pop bc
+ ld a, [hRandomAdd]
+
+.finish
+ push af
+ ld a, [wScriptVar]
+ ld c, a
+ pop af
+ call SimpleDivide
+ ld [wScriptVar], a
+ ret
+
+.Divide256byC:
+ xor a
+ ld b, a
+ sub c
+.mod_loop
+ inc b
+ sub c
+ jr nc, .mod_loop
+ dec b
+ add c
+ ret
+
+Script_checkcode:
+; script command 0x1c
+; parameters: variable_id
+
+ call GetScriptByte
+ call GetVarAction
+ ld a, [de]
+ ld [wScriptVar], a
+ ret
+
+Script_writevarcode:
+; script command 0x1d
+; parameters: variable_id
+
+ call GetScriptByte
+ call GetVarAction
+ ld a, [wScriptVar]
+ ld [de], a
+ ret
+
+Script_writecode:
+; script command 0x1e
+; parameters: variable_id, value
+
+ call GetScriptByte
+ call GetVarAction
+ call GetScriptByte
+ ld [de], a
+ ret
+
+GetVarAction:
+ ld c, a
+ farcall _GetVarAction
+ ret
+
+Script_checkver:
+; script command 0x18
+
+ ld a, [.gs_version]
+ ld [wScriptVar], a
+ ret
+
+.gs_version:
+ db GS_VERSION
+
+Script_pokenamemem:
+; script command 0x40
+; parameters: pokemon (0 aka USE_SCRIPT_VAR to use wScriptVar), memory
+
+ call GetScriptByte
+ and a
+ jr nz, .gotit
+ ld a, [wScriptVar]
+.gotit
+ ld [wd265], a
+ call GetPokemonName
+ ld de, wStringBuffer1
+
+ConvertMemToText:
+ call GetScriptByte
+ cp NUM_MEM_BUFFERS
+ jr c, .ok
+ xor a
+.ok
+
+CopyConvertedText:
+ ld hl, wStringBuffer3
+ ld bc, wStringBuffer4 - wStringBuffer3
+ call AddNTimes
+ call CopyName2
+ ret
+
+Script_itemtotext:
+; script command 0x41
+; parameters: item (0 aka USE_SCRIPT_VAR to use wScriptVar), memory
+
+ call GetScriptByte
+ and a ; USE_SCRIPT_VAR
+ jr nz, .ok
+ ld a, [wScriptVar]
+.ok
+ ld [wd265], a
+ call GetItemName
+ ld de, wStringBuffer1
+ jr ConvertMemToText
+
+Script_mapnametotext:
+; script command 0x42
+; parameters: memory
+
+ ld a, [wMapGroup]
+ ld b, a
+ ld a, [wMapNumber]
+ ld c, a
+ call GetWorldMapLocation
+
+ConvertLandmarkToText:
+ ld e, a
+ farcall GetLandmarkName
+ ld de, wStringBuffer1
+ jp ConvertMemToText
+
+Script_landmarktotext:
+; script command 0xa5
+; parameters: id, memory
+
+ call GetScriptByte
+ jr ConvertLandmarkToText
+
+Script_trainertotext:
+; script command 0x43
+; parameters: trainer_id, trainer_group, memory
+
+ call GetScriptByte
+ ld c, a
+ call GetScriptByte
+ ld b, a
+ farcall GetTrainerName
+ jr ConvertMemToText
+
+Script_name:
+; script command 0xa7
+; parameters: type, id, memory
+
+ call GetScriptByte
+ ld [wNamedObjectTypeBuffer], a
+
+ContinueToGetName:
+ call GetScriptByte
+ ld [wCurSpecies], a
+ call GetName
+ ld de, wStringBuffer1
+ jp ConvertMemToText
+
+Script_trainerclassname:
+; script command 0xa6
+; parameters: id, memory
+
+ ld a, TRAINER_NAME
+ ld [wNamedObjectTypeBuffer], a
+ jr ContinueToGetName
+
+Script_readmoney:
+; script command 0x3d
+; parameters: account, memory
+
+ call ResetStringBuffer1
+ call GetMoneyAccount
+ ld hl, wStringBuffer1
+ lb bc, PRINTNUM_RIGHTALIGN | 3, 6
+ call PrintNum
+ ld de, wStringBuffer1
+ jp ConvertMemToText
+
+Script_readcoins:
+; script command 0x3e
+; parameters: memory
+
+ call ResetStringBuffer1
+ ld hl, wStringBuffer1
+ ld de, wCoins
+ lb bc, PRINTNUM_RIGHTALIGN | 2, 6
+ call PrintNum
+ ld de, wStringBuffer1
+ jp ConvertMemToText
+
+Script_vartomem:
+; script command 0x3f
+; parameters: memory
+
+ call ResetStringBuffer1
+ ld de, wScriptVar
+ ld hl, wStringBuffer1
+ lb bc, PRINTNUM_RIGHTALIGN | 1, 3
+ call PrintNum
+ ld de, wStringBuffer1
+ jp ConvertMemToText
+
+ResetStringBuffer1:
+ ld hl, wStringBuffer1
+ ld bc, NAME_LENGTH
+ ld a, "@"
+ call ByteFill
+ ret
+
+Script_stringtotext:
+; script command 0x44
+; parameters: text_pointer, memory
+
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld a, [wScriptBank]
+ ld hl, CopyName1
+ rst FarCall
+ ld de, wStringBuffer2
+ jp ConvertMemToText
+
+Script_givepokeitem:
+; script command 0x2f
+; parameters: pointer
+
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ ld a, [wScriptBank]
+ call GetFarByte
+ ld b, a
+ push bc
+ inc hl
+ ld bc, MAIL_MSG_LENGTH
+ ld de, wd002
+ ld a, [wScriptBank]
+ call FarCopyBytes
+ pop bc
+ farcall GivePokeItem
+ ret
+
+Script_checkpokeitem:
+; script command 0x30
+; parameters: pointer
+
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld a, [wScriptBank]
+ ld b, a
+ farcall CheckPokeItem
+ ret
+
+Script_giveitem:
+; script command 0x1f
+; parameters: item, quantity
+
+ call GetScriptByte
+ cp ITEM_FROM_MEM
+ jr nz, .ok
+ ld a, [wScriptVar]
+.ok
+ ld [wCurItem], a
+ call GetScriptByte
+ ld [wItemQuantityChangeBuffer], a
+ ld hl, wNumItems
+ call ReceiveItem
+ jr nc, .full
+ ld a, TRUE
+ ld [wScriptVar], a
+ ret
+.full
+ xor a
+ ld [wScriptVar], a
+ ret
+
+Script_takeitem:
+; script command 0x20
+; parameters: item, quantity
+
+ xor a
+ ld [wScriptVar], a
+ call GetScriptByte
+ ld [wCurItem], a
+ call GetScriptByte
+ ld [wItemQuantityChangeBuffer], a
+ ld a, -1
+ ld [wCurItemQuantity], a
+ ld hl, wNumItems
+ call TossItem
+ ret nc
+ ld a, TRUE
+ ld [wScriptVar], a
+ ret
+
+Script_checkitem:
+; script command 0x21
+; parameters: item
+
+ xor a
+ ld [wScriptVar], a
+ call GetScriptByte
+ ld [wCurItem], a
+ ld hl, wNumItems
+ call CheckItem
+ ret nc
+ ld a, TRUE
+ ld [wScriptVar], a
+ ret
+
+Script_givemoney:
+; script command 0x22
+; parameters: account, money
+
+ call GetMoneyAccount
+ call LoadMoneyAmountToMem
+ farcall GiveMoney
+ ret
+
+Script_takemoney:
+; script command 0x23
+; parameters: account, money
+
+ call GetMoneyAccount
+ call LoadMoneyAmountToMem
+ farcall TakeMoney
+ ret
+
+Script_checkmoney:
+; script command 0x24
+; parameters: account, money
+
+ call GetMoneyAccount
+ call LoadMoneyAmountToMem
+ farcall CompareMoney
+
+CompareMoneyAction:
+ jr c, .less
+ jr z, .exact
+ ld a, HAVE_MORE
+ jr .done
+.exact
+ ld a, HAVE_AMOUNT
+ jr .done
+.less
+ ld a, HAVE_LESS
+.done
+ ld [wScriptVar], a
+ ret
+
+GetMoneyAccount:
+ call GetScriptByte
+ and a
+ ld de, wMoney ; YOUR_MONEY
+ ret z
+ ld de, wMomsMoney ; MOMS_MONEY
+ ret
+
+LoadMoneyAmountToMem:
+ ld bc, hMoneyTemp
+ push bc
+ call GetScriptByte
+ ld [bc], a
+ inc bc
+ call GetScriptByte
+ ld [bc], a
+ inc bc
+ call GetScriptByte
+ ld [bc], a
+ pop bc
+ ret
+
+Script_givecoins:
+; script command 0x25
+; parameters: coins
+
+ call LoadCoinAmountToMem
+ farcall GiveCoins
+ ret
+
+Script_takecoins:
+; script command 0x26
+; parameters: coins
+
+ call LoadCoinAmountToMem
+ farcall TakeCoins
+ ret
+
+Script_checkcoins:
+; script command 0x27
+; parameters: coins
+
+ call LoadCoinAmountToMem
+ farcall CheckCoins
+ jr CompareMoneyAction
+
+LoadCoinAmountToMem:
+ call GetScriptByte
+ ld [hMoneyTemp + 1], a
+ call GetScriptByte
+ ld [hMoneyTemp], a
+ ld bc, hMoneyTemp
+ ret
+
+Script_checktime:
+; script command 0x2b
+; parameters: time
+
+ xor a
+ ld [wScriptVar], a
+ farcall CheckTime
+ call GetScriptByte
+ and c
+ ret z
+ ld a, TRUE
+ ld [wScriptVar], a
+ ret
+
+Script_checkpoke:
+; script command 0x2c
+; parameters: pokemon
+
+ xor a
+ ld [wScriptVar], a
+ call GetScriptByte
+ ld hl, wPartySpecies
+ ld de, 1
+ call IsInArray
+ ret nc
+ ld a, TRUE
+ ld [wScriptVar], a
+ ret
+
+Script_addcellnum:
+; script command 0x28
+; parameters: person
+
+ xor a
+ ld [wScriptVar], a
+ call GetScriptByte
+ ld c, a
+ farcall AddPhoneNumber
+ ret nc
+ ld a, TRUE
+ ld [wScriptVar], a
+ ret
+
+Script_delcellnum:
+; script command 0x29
+; parameters: person
+
+ xor a
+ ld [wScriptVar], a
+ call GetScriptByte
+ ld c, a
+ farcall DelCellNum
+ ret nc
+ ld a, TRUE
+ ld [wScriptVar], a
+ ret
+
+Script_checkcellnum:
+; script command 0x2a
+; parameters: person
+; returns false if the cell number is not in your phone
+
+ xor a
+ ld [wScriptVar], a
+ call GetScriptByte
+ ld c, a
+ farcall CheckCellNum
+ ret nc
+ ld a, TRUE
+ ld [wScriptVar], a
+ ret
+
+Script_specialphonecall:
+; script command 0x9c
+; parameters: call_id
+
+ call GetScriptByte
+ ld [wSpecialPhoneCallID], a
+ call GetScriptByte
+ ld [wSpecialPhoneCallID + 1], a
+ ret
+
+Script_checkphonecall:
+; script command 0x9d
+; returns false if no special phone call is stored
+
+ ld a, [wSpecialPhoneCallID]
+ and a
+ jr z, .ok
+ ld a, TRUE
+.ok
+ ld [wScriptVar], a
+ ret
+
+Script_givepoke:
+; script command 0x2d
+; parameters: pokemon, level, item, trainer, trainer_name_pointer, pkmn_nickname
+
+ call GetScriptByte
+ ld [wCurPartySpecies], a
+ call GetScriptByte
+ ld [wCurPartyLevel], a
+ call GetScriptByte
+ ld [wCurItem], a
+ call GetScriptByte
+ and a
+ ld b, a
+ jr z, .ok
+ ld hl, wScriptPos
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ call GetScriptByte
+ call GetScriptByte
+ call GetScriptByte
+ call GetScriptByte
+.ok
+ farcall GivePoke
+ ld a, b
+ ld [wScriptVar], a
+ ret
+
+Script_giveegg:
+; script command 0x2e
+; parameters: pokemon, level
+; if no room in the party, return 0 in wScriptVar; else, return 2
+
+ xor a ; PARTYMON
+ ld [wScriptVar], a
+ ld [wMonType], a
+ call GetScriptByte
+ ld [wCurPartySpecies], a
+ call GetScriptByte
+ ld [wCurPartyLevel], a
+ farcall GiveEgg
+ ret nc
+ ld a, 2
+ ld [wScriptVar], a
+ ret
+
+Script_setevent:
+; script command 0x33
+; parameters: bit_number
+
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld b, SET_FLAG
+ call EventFlagAction
+ ret
+
+Script_clearevent:
+; script command 0x32
+; parameters: bit_number
+
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld b, RESET_FLAG
+ call EventFlagAction
+ ret
+
+Script_checkevent:
+; script command 0x31
+; parameters: bit_number
+
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld b, CHECK_FLAG
+ call EventFlagAction
+ ld a, c
+ and a
+ jr z, .false
+ ld a, TRUE
+.false
+ ld [wScriptVar], a
+ ret
+
+Script_setflag:
+; script command 0x36
+; parameters: bit_number
+
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld b, SET_FLAG
+ call _EngineFlagAction
+ ret
+
+Script_clearflag:
+; script command 0x35
+; parameters: bit_number
+
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld b, RESET_FLAG
+ call _EngineFlagAction
+ ret
+
+Script_checkflag:
+; script command 0x34
+; parameters: bit_number
+
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld b, CHECK_FLAG
+ call _EngineFlagAction
+ ld a, c
+ and a
+ jr z, .false
+ ld a, TRUE
+.false
+ ld [wScriptVar], a
+ ret
+
+_EngineFlagAction:
+ farcall EngineFlagAction
+ ret
+
+Script_wildoff:
+; script command 0x38
+
+ ld hl, wStatusFlags
+ set STATUSFLAGS_NO_WILD_ENCOUNTERS_F, [hl]
+ ret
+
+Script_wildon:
+; script command 0x37
+
+ ld hl, wStatusFlags
+ res STATUSFLAGS_NO_WILD_ENCOUNTERS_F, [hl]
+ ret
+
+Script_xycompare:
+; script command 0x39
+; parameters: pointer
+
+ call GetScriptByte
+ ld [wXYComparePointer], a
+ call GetScriptByte
+ ld [wXYComparePointer + 1], a
+ ret
+
+Script_warpfacing:
+; script command 0xa3
+; parameters: facing, map_group, map_id, x, y
+
+ call GetScriptByte
+ maskbits NUM_DIRECTIONS
+ ld c, a
+ ld a, [wPlayerSpriteSetupFlags]
+ set PLAYERSPRITESETUP_CUSTOM_FACING_F, a
+ or c
+ ld [wPlayerSpriteSetupFlags], a
+; fall through
+
+Script_warp:
+; script command 0x3c
+; parameters: map_group, map_id, x, y
+
+; This seems to be some sort of error handling case.
+ call GetScriptByte
+ and a
+ jr z, .not_ok
+ ld [wMapGroup], a
+ call GetScriptByte
+ ld [wMapNumber], a
+ call GetScriptByte
+ ld [wXCoord], a
+ call GetScriptByte
+ ld [wYCoord], a
+ ld a, -1
+ ld [wDefaultSpawnpoint], a
+ ld a, MAPSETUP_WARP
+ ld [hMapEntryMethod], a
+ ld a, 1
+ call LoadMapStatus
+ call StopScript
+ ret
+
+.not_ok
+ call GetScriptByte
+ call GetScriptByte
+ call GetScriptByte
+ ld a, -1
+ ld [wDefaultSpawnpoint], a
+ ld a, MAPSETUP_BADWARP
+ ld [hMapEntryMethod], a
+ ld a, 1
+ call LoadMapStatus
+ call StopScript
+ ret
+
+Script_warpmod:
+; script command 0x3a
+; parameters: warp_id, map_group, map_id
+
+ call GetScriptByte
+ ld [wBackupWarpNumber], a
+ call GetScriptByte
+ ld [wBackupMapGroup], a
+ call GetScriptByte
+ ld [wBackupMapNumber], a
+ ret
+
+Script_blackoutmod:
+; script command 0x3b
+; parameters: map_group, map_id
+
+ call GetScriptByte
+ ld [wLastSpawnMapGroup], a
+ call GetScriptByte
+ ld [wLastSpawnMapNumber], a
+ ret
+
+Script_dontrestartmapmusic:
+; script command 0x83
+
+ ld a, 1
+ ld [wDontPlayMapMusicOnReload], a
+ ret
+
+Script_writecmdqueue:
+; script command 0x7d
+; parameters: queue_pointer
+
+ call GetScriptByte
+ ld e, a
+ call GetScriptByte
+ ld d, a
+ ld a, [wScriptBank]
+ ld b, a
+ farcall WriteCmdQueue ; no need to farcall
+ ret
+
+Script_delcmdqueue:
+; script command 0x7e
+; parameters: byte
+
+ xor a
+ ld [wScriptVar], a
+ call GetScriptByte
+ ld b, a
+ farcall DelCmdQueue ; no need to farcall
+ ret c
+ ld a, 1
+ ld [wScriptVar], a
+ ret
+
+Script_changemap:
+; script command 0x79
+; parameters: map_data_pointer
+
+ call GetScriptByte
+ ld [wMapBlocksBank], a
+ call GetScriptByte
+ ld [wMapBlocksPointer], a
+ call GetScriptByte
+ ld [wMapBlocksPointer + 1], a
+ call ChangeMap
+ call BufferScreen
+ ret
+
+Script_changeblock:
+; script command 0x7a
+; parameters: x, y, block
+
+ call GetScriptByte
+ add 4
+ ld d, a
+ call GetScriptByte
+ add 4
+ ld e, a
+ call GetBlockLocation
+ call GetScriptByte
+ ld [hl], a
+ call BufferScreen
+ ret
+
+Script_reloadmappart::
+; script command 0x7c
+
+ xor a
+ ld [hBGMapMode], a
+ call OverworldTextModeSwitch
+ call GetMovementPermissions
+ farcall ReloadMapPart
+ call UpdateSprites
+ ret
+
+Script_warpcheck:
+; script command 0x8e
+
+ call WarpCheck
+ ret nc
+ farcall EnableEvents
+ ret
+
+Script_enableevents:
+; unused
+ farcall EnableEvents
+ ret
+
+Script_newloadmap:
+; script command 0x8a
+; parameters: which_method
+
+ call GetScriptByte
+ ld [hMapEntryMethod], a
+ ld a, 1
+ call LoadMapStatus
+ call StopScript
+ ret
+
+Script_reloadandreturn:
+; script command 0x92
+
+ call Script_newloadmap
+ jp Script_end
+
+Script_opentext:
+; script command 0x47
+
+ call OpenText
+ ret
+
+Script_refreshscreen:
+; script command 0x48
+; parameters: dummy
+
+ call RefreshScreen
+ call GetScriptByte
+ ret
+
+Script_loadbytec2cf:
+; script command 0x4a
+; parameters: byte
+
+ call GetScriptByte
+ ld [wc2cf], a
+ ret
+
+ db closetext_command ; unused
+
+Script_closetext:
+; script command 0x49
+
+ call _OpenAndCloseMenu_HDMATransferTileMapAndAttrMap
+ call CloseText
+ ret
+
+
+Script_passtoengine:
+; script command 0x89
+; parameters: data_pointer
+
+ call GetScriptByte
+ push af
+ call GetScriptByte
+ ld l, a
+ call GetScriptByte
+ ld h, a
+ pop af
+ call StartAutoInput
+ ret
+
+Script_pause:
+; script command 0x8b
+; parameters: length
+
+ call GetScriptByte
+ and a
+ jr z, .loop
+ ld [wScriptDelay], a
+.loop
+ ld c, 2
+ call DelayFrames
+ ld hl, wScriptDelay
+ dec [hl]
+ jr nz, .loop
+ ret
+
+Script_deactivatefacing:
+; script command 0x8c
+; parameters: time
+
+ call GetScriptByte
+ and a
+ jr z, .no_time
+ ld [wScriptDelay], a
+.no_time
+ ld a, SCRIPT_WAIT
+ ld [wScriptMode], a
+ call StopScript
+ ret
+
+Script_ptpriorityjump:
+; script command 0x8f
+; parameters: pointer
+
+ call StopScript
+ jp Script_jump
+
+Script_end:
+; script command 0x91
+
+ call ExitScriptSubroutine
+ jr c, .resume
+ ret
+
+.resume
+ xor a
+ ld [wScriptRunning], a
+ ld a, SCRIPT_OFF
+ ld [wScriptMode], a
+ ld hl, wScriptFlags
+ res 0, [hl]
+ call StopScript
+ ret
+
+Script_return:
+; script command 0x90
+
+ call ExitScriptSubroutine
+ jr c, .dummy
+.dummy
+ ld hl, wScriptFlags
+ res 0, [hl]
+ call StopScript
+ ret
+
+ExitScriptSubroutine:
+; Return carry if there's no parent to return to.
+
+ ld hl, wScriptStackSize
+ ld a, [hl]
+ and a
+ jr z, .done
+ dec [hl]
+ ld e, [hl]
+ ld d, $0
+ ld hl, wScriptStack
+ add hl, de
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld b, a
+ and " "
+ ld [wScriptBank], a
+ ld a, [hli]
+ ld e, a
+ ld [wScriptPos], a
+ ld a, [hl]
+ ld d, a
+ ld [wScriptPos + 1], a
+ and a
+ ret
+.done
+ scf
+ ret
+
+Script_endall:
+; script command 0x93
+
+ xor a
+ ld [wScriptStackSize], a
+ ld [wScriptRunning], a
+ ld a, SCRIPT_OFF
+ ld [wScriptMode], a
+ ld hl, wScriptFlags
+ res 0, [hl]
+ call StopScript
+ ret
+
+Script_halloffame:
+; script command 0xa1
+
+ ld hl, wGameTimerPause
+ res GAMETIMERPAUSE_TIMER_PAUSED_F, [hl]
+ farcall StubbedTrainerRankings_HallOfFame
+ farcall StubbedTrainerRankings_HallOfFame2
+ farcall HallOfFame
+ ld hl, wGameTimerPause
+ set GAMETIMERPAUSE_TIMER_PAUSED_F, [hl]
+ jr ReturnFromCredits
+
+Script_credits:
+; script command 0xa2
+
+ farcall RedCredits
+ReturnFromCredits:
+ call Script_endall
+ ld a, $3
+ call LoadMapStatus
+ call StopScript
+ ret
+
+Script_wait:
+; script command 0xa8
+; parameters: unknown
+
+ push bc
+ call GetScriptByte
+.loop
+ push af
+ ld c, 6
+ call DelayFrames
+ pop af
+ dec a
+ jr nz, .loop
+ pop bc
+ ret
+
+Script_checksave:
+; script command 0xa9
+
+ farcall CheckSave
+ ld a, c
+ ld [wScriptVar], a
+ ret
+
+
+; unused
+ ld a, [.byte]
+ ld [wScriptVar], a
+ ret
+
+.byte
+ db 0
diff --git a/engine/overworld/select_menu.asm b/engine/overworld/select_menu.asm
new file mode 100755
index 000000000..9898afda2
--- /dev/null
+++ b/engine/overworld/select_menu.asm
@@ -0,0 +1,191 @@
+SelectMenu:: ; 13327
+
+ call CheckRegisteredItem
+ jr c, .NotRegistered
+ jp UseRegisteredItem
+
+.NotRegistered:
+ call OpenText
+ ld b, BANK(ItemMayBeRegisteredText)
+ ld hl, ItemMayBeRegisteredText
+ call MapTextbox
+ call WaitButton
+ jp CloseText
+; 13340
+
+
+ItemMayBeRegisteredText: ; 13340
+ text_jump UnknownText_0x1c1cf3
+ db "@"
+; 13345
+
+
+CheckRegisteredItem: ; 13345
+
+ ld a, [wWhichRegisteredItem]
+ and a
+ jr z, .NoRegisteredItem
+ and REGISTERED_POCKET
+ rlca
+ rlca
+ ld hl, .Pockets
+ rst JumpTable
+ ret
+
+.Pockets:
+; entries correspond to *_POCKET constants
+ dw .CheckItem
+ dw .CheckBall
+ dw .CheckKeyItem
+ dw .CheckTMHM
+
+.CheckItem:
+ ld hl, wNumItems
+ call .CheckRegisteredNo
+ jr c, .NoRegisteredItem
+ inc hl
+ ld e, a
+ ld d, 0
+ add hl, de
+ add hl, de
+ call .IsSameItem
+ jr c, .NoRegisteredItem
+ and a
+ ret
+
+.CheckKeyItem:
+ ld a, [wRegisteredItem]
+ ld hl, wKeyItems
+ ld de, 1
+ call IsInArray
+ jr nc, .NoRegisteredItem
+ ld a, [wRegisteredItem]
+ ld [wCurItem], a
+ and a
+ ret
+
+.CheckBall:
+ ld hl, wNumBalls
+ call .CheckRegisteredNo
+ jr nc, .NoRegisteredItem
+ inc hl
+ ld e, a
+ ld d, 0
+ add hl, de
+ add hl, de
+ call .IsSameItem
+ jr c, .NoRegisteredItem
+ ret
+
+.CheckTMHM:
+ jr .NoRegisteredItem
+
+.NoRegisteredItem:
+ xor a
+ ld [wWhichRegisteredItem], a
+ ld [wRegisteredItem], a
+ scf
+ ret
+; 133a6
+
+
+.CheckRegisteredNo: ; 133a6
+ ld a, [wWhichRegisteredItem]
+ and REGISTERED_NUMBER
+ dec a
+ cp [hl]
+ jr nc, .NotEnoughItems
+ ld [wCurItemQuantity], a
+ and a
+ ret
+
+.NotEnoughItems:
+ scf
+ ret
+; 133b6
+
+
+.IsSameItem: ; 133b6
+ ld a, [wRegisteredItem]
+ cp [hl]
+ jr nz, .NotSameItem
+ ld [wCurItem], a
+ and a
+ ret
+
+.NotSameItem:
+ scf
+ ret
+; 133c3
+
+
+UseRegisteredItem: ; 133c3
+
+ farcall CheckItemMenu
+ ld a, [wItemAttributeParamBuffer]
+ ld hl, .SwitchTo
+ rst JumpTable
+ ret
+
+.SwitchTo:
+; entries correspond to ITEMMENU_* constants
+ dw .CantUse
+ dw .NoFunction
+ dw .NoFunction
+ dw .NoFunction
+ dw .Current
+ dw .Party
+ dw .Overworld
+; 133df
+
+.NoFunction: ; 133df
+ call OpenText
+ call CantUseItem
+ call CloseText
+ and a
+ ret
+; 133ea
+
+.Current: ; 133ea
+ call OpenText
+ call DoItemEffect
+ call CloseText
+ and a
+ ret
+; 133f5
+
+.Party: ; 133f5
+ call RefreshScreen
+ call FadeToMenu
+ call DoItemEffect
+ call CloseSubmenu
+ call CloseText
+ and a
+ ret
+; 13406
+
+.Overworld: ; 13406
+ call RefreshScreen
+ ld a, 1
+ ld [wUsingItemWithSelect], a
+ call DoItemEffect
+ xor a
+ ld [wUsingItemWithSelect], a
+ ld a, [wItemEffectSucceeded]
+ cp 1
+ jr nz, ._cantuse
+ scf
+ ld a, HMENURETURN_SCRIPT
+ ld [hMenuReturn], a
+ ret
+; 13422
+
+.CantUse: ; 13422
+ call RefreshScreen
+
+._cantuse
+ call CantUseItem
+ call CloseText
+ and a
+ ret
+; 1342d
diff --git a/engine/overworld/spawn_points.asm b/engine/overworld/spawn_points.asm
new file mode 100644
index 000000000..1a3d12441
--- /dev/null
+++ b/engine/overworld/spawn_points.asm
@@ -0,0 +1,62 @@
+INCLUDE "data/maps/spawn_points.asm"
+
+
+LoadSpawnPoint: ; 1531f
+ ; loads the spawn point in wDefaultSpawnpoint
+ push hl
+ push de
+ ld a, [wDefaultSpawnpoint]
+ cp SPAWN_N_A
+ jr z, .spawn_n_a
+ ld l, a
+ ld h, 0
+ add hl, hl
+ add hl, hl
+ ld de, SpawnPoints
+ add hl, de
+ ld a, [hli]
+ ld [wMapGroup], a
+ ld a, [hli]
+ ld [wMapNumber], a
+ ld a, [hli]
+ ld [wXCoord], a
+ ld a, [hli]
+ ld [wYCoord], a
+.spawn_n_a
+ pop de
+ pop hl
+ ret
+; 15344
+
+
+IsSpawnPoint: ; 15344
+; Checks if the map loaded in de is a spawn point. Returns carry if it's a spawn point.
+ ld hl, SpawnPoints
+ ld c, 0
+.loop
+ ld a, [hl]
+ cp SPAWN_N_A
+ jr z, .nope
+ cp d
+ jr nz, .next
+ inc hl
+ ld a, [hld]
+ cp e
+ jr z, .yes
+
+.next
+ push bc
+ ld bc, 4 ; length of a spawn table entry
+ add hl, bc
+ pop bc
+ inc c
+ jr .loop
+
+.nope
+ and a
+ ret
+
+.yes
+ scf
+ ret
+; 15363
diff --git a/engine/overworld/tile_events.asm b/engine/overworld/tile_events.asm
new file mode 100755
index 000000000..705c0e427
--- /dev/null
+++ b/engine/overworld/tile_events.asm
@@ -0,0 +1,110 @@
+CheckWarpCollision:: ; 1499a
+; Is this tile a warp?
+ ld a, [wPlayerStandingTile]
+ cp COLL_PIT
+ jr z, .warp
+ cp COLL_PIT_68
+ jr z, .warp
+ and $f0
+ cp HI_NYBBLE_WARPS
+ jr z, .warp
+ and a
+ ret
+
+.warp
+ scf
+ ret
+; 149af
+
+CheckDirectionalWarp:: ; 149af
+; If this is a directional warp, clear carry (press the designated button to warp).
+; Else, set carry (immediate warp).
+ ld a, [wPlayerStandingTile]
+ cp COLL_WARP_CARPET_DOWN
+ jr z, .directional
+ cp COLL_WARP_CARPET_LEFT
+ jr z, .directional
+ cp COLL_WARP_CARPET_UP
+ jr z, .directional
+ cp COLL_WARP_CARPET_RIGHT
+ jr z, .directional
+ scf
+ ret
+
+.directional
+ xor a
+ ret
+; 149c6
+
+CheckWarpFacingDown: ; 149c6
+ ld de, 1
+ ld hl, .blocks
+ ld a, [wPlayerStandingTile]
+ call IsInArray
+ ret
+; 149d3
+
+.blocks ; 149d3
+ db COLL_DOOR
+ db COLL_DOOR_79
+ db COLL_STAIRCASE
+ db COLL_STAIRCASE_73
+ db COLL_CAVE
+ db COLL_CAVE_74
+ db COLL_WARP_PANEL
+ db COLL_DOOR_75
+ db COLL_DOOR_7D
+ db -1
+; 149dd
+
+CheckGrassCollision:: ; 149dd
+ ld a, [wPlayerStandingTile]
+ ld hl, .blocks
+ ld de, 1
+ call IsInArray
+ ret
+; 149ea
+
+.blocks ; 149ea
+ db COLL_CUT_08
+ db COLL_TALL_GRASS
+ db COLL_LONG_GRASS
+ db COLL_CUT_28
+ db COLL_WATER
+ db COLL_GRASS_48
+ db COLL_GRASS_49
+ db COLL_GRASS_4A
+ db COLL_GRASS_4B
+ db COLL_GRASS_4C
+ db -1
+; 149f5
+
+CheckCutCollision: ; 149f5
+ ld a, c
+ ld hl, .blocks
+ ld de, 1
+ call IsInArray
+ ret
+; 14a00
+
+.blocks ; 14a00
+ db COLL_CUT_TREE
+ db COLL_CUT_TREE_1A
+ db COLL_TALL_GRASS_10
+ db COLL_TALL_GRASS
+ db COLL_LONG_GRASS
+ db COLL_LONG_GRASS_1C
+ db -1
+; 14a07
+
+GetWarpSFX:: ; 14a07
+ ld a, [wPlayerStandingTile]
+ ld de, SFX_ENTER_DOOR
+ cp COLL_DOOR
+ ret z
+ ld de, SFX_WARP_TO
+ cp COLL_WARP_PANEL
+ ret z
+ ld de, SFX_EXIT_BUILDING
+ ret
+; 14a1a
diff --git a/engine/overworld/time.asm b/engine/overworld/time.asm
new file mode 100755
index 000000000..0f83447cc
--- /dev/null
+++ b/engine/overworld/time.asm
@@ -0,0 +1,465 @@
+_InitializeStartDay: ; 113d6
+ call InitializeStartDay
+ ret
+; 113da
+
+ClearDailyTimers: ; 113da
+ xor a
+ ld [wLuckyNumberDayBuffer], a
+ ld [wUnusedTwoDayTimer], a
+ ld [wDailyResetTimer], a
+ ret
+; 113e5
+
+InitCallReceiveDelay:: ; 113e5
+ xor a
+ ld [wTimeCyclesSinceLastCall], a
+
+NextCallReceiveDelay: ; 113e9
+ ld a, [wTimeCyclesSinceLastCall]
+ cp 3
+ jr c, .okay
+ ld a, 3
+
+.okay
+ ld e, a
+ ld d, 0
+ ld hl, .ReceiveCallDelays
+ add hl, de
+ ld a, [hl]
+ jp RestartReceiveCallDelay
+; 113fd
+
+.ReceiveCallDelays:
+ db 20, 10, 5, 3
+; 11401
+
+CheckReceiveCallTimer: ; 11401
+ call CheckReceiveCallDelay ; check timer
+ ret nc
+ ld hl, wTimeCyclesSinceLastCall
+ ld a, [hl]
+ cp 3
+ jr nc, .ok
+ inc [hl]
+
+.ok
+ call NextCallReceiveDelay ; restart timer
+ scf
+ ret
+; 11413
+
+InitOneDayCountdown: ; 11413
+ ld a, 1
+
+InitNDaysCountdown: ; 11415
+ ld [hl], a
+ push hl
+ call UpdateTime
+ pop hl
+ inc hl
+ call CopyDayToHL
+ ret
+; 11420
+
+CheckDayDependentEventHL: ; 11420
+ inc hl
+ push hl
+ call CalcDaysSince
+ call GetDaysSince
+ pop hl
+ dec hl
+ call UpdateTimeRemaining
+ ret
+; 1142e
+
+RestartReceiveCallDelay: ; 1142e
+ ld hl, wReceiveCallDelay_MinsRemaining
+ ld [hl], a
+ call UpdateTime
+ ld hl, wReceiveCallDelay_StartTime
+ call CopyDayHourMinToHL
+ ret
+; 1143c
+
+CheckReceiveCallDelay: ; 1143c
+ ld hl, wReceiveCallDelay_StartTime
+ call CalcMinsHoursDaysSince
+ call GetMinutesSinceIfLessThan60
+ ld hl, wReceiveCallDelay_MinsRemaining
+ call UpdateTimeRemaining
+ ret
+; 1144c
+
+RestartDailyResetTimer: ; 1144c
+ ld hl, wDailyResetTimer
+ jp InitOneDayCountdown
+; 11452
+
+CheckDailyResetTimer:: ; 11452
+ ld hl, wDailyResetTimer
+ call CheckDayDependentEventHL
+ ret nc
+ xor a
+ ld hl, wDailyFlags
+ ld [hli], a ; wDailyFlags
+ ld [hli], a ; wWeeklyFlags
+ ld [hli], a ; wSwarmFlags
+ ld [hl], a ; wSwarmFlags + 1
+ ld hl, wDailyRematchFlags
+rept 4
+ ld [hli], a
+endr
+ ld hl, wDailyPhoneItemFlags
+rept 4
+ ld [hli], a
+endr
+ ld hl, wDailyPhoneTimeOfDayFlags
+rept 4
+ ld [hli], a
+endr
+ ld hl, wKenjiBreakTimer
+ ld a, [hl]
+ and a
+ jr z, .RestartKenjiBreakCountdown
+ dec [hl]
+ jr nz, .DontRestartKenjiBreakCountdown
+.RestartKenjiBreakCountdown:
+ call SampleKenjiBreakCountdown
+.DontRestartKenjiBreakCountdown:
+ jr RestartDailyResetTimer
+; 11485
+
+SampleKenjiBreakCountdown: ; 11485
+; Generate a random number between 3 and 6
+ call Random
+ and %11
+ add 3
+ ld [wKenjiBreakTimer], a
+ ret
+; 11490
+
+StartBugContestTimer: ; 11490
+ ld a, BUG_CONTEST_MINUTES
+ ld [wBugContestMinsRemaining], a
+ ld a, BUG_CONTEST_SECONDS
+ ld [wBugContestSecsRemaining], a
+ call UpdateTime
+ ld hl, wBugContestStartTime
+ call CopyDayHourMinSecToHL
+ ret
+; 114a4
+
+
+CheckBugContestTimer:: ; 114a4 (4:54a4)
+ ld hl, wBugContestStartTime
+ call CalcSecsMinsHoursDaysSince
+ ld a, [wDaysSince]
+ and a
+ jr nz, .timed_out
+ ld a, [wHoursSince]
+ and a
+ jr nz, .timed_out
+ ld a, [wSecondsSince]
+ ld b, a
+ ld a, [wBugContestSecsRemaining]
+ sub b
+ jr nc, .okay
+ add 60
+
+.okay
+ ld [wBugContestSecsRemaining], a
+ ld a, [wMinutesSince]
+ ld b, a
+ ld a, [wBugContestMinsRemaining]
+ sbc b
+ ld [wBugContestMinsRemaining], a
+ jr c, .timed_out
+ and a
+ ret
+
+.timed_out
+ xor a
+ ld [wBugContestMinsRemaining], a
+ ld [wBugContestSecsRemaining], a
+ scf
+ ret
+
+
+InitializeStartDay: ; 114dd
+ call UpdateTime
+ ld hl, wTimerEventStartDay
+ call CopyDayToHL
+ ret
+; 114e7
+
+CheckPokerusTick:: ; 114e7
+ ld hl, wTimerEventStartDay
+ call CalcDaysSince
+ call GetDaysSince
+ and a
+ jr z, .done ; not even a day has passed since game start
+ ld b, a
+ farcall ApplyPokerusTick
+.done
+ xor a
+ ret
+; 114fc
+
+SetUnusedTwoDayTimer: ; 114fc
+ ld a, 2
+ ld hl, wUnusedTwoDayTimer
+ ld [hl], a
+ call UpdateTime
+ ld hl, wUnusedTwoDayTimerStartDate
+ call CopyDayToHL
+ ret
+; 1150c
+
+CheckUnusedTwoDayTimer: ; 1150c
+ ld hl, wUnusedTwoDayTimerStartDate
+ call CalcDaysSince
+ call GetDaysSince
+ ld hl, wUnusedTwoDayTimer
+ call UpdateTimeRemaining
+ ret
+; 1151c
+
+; unused
+ ld hl, wDailyFlags
+ set DAILYFLAGS_FISH_SWARM_F, [hl]
+ ret
+; 11522
+
+; unused
+ and a
+ ld hl, wDailyFlags
+ bit DAILYFLAGS_FISH_SWARM_F, [hl]
+ ret nz
+ scf
+ ret
+; 1152b
+
+RestartLuckyNumberCountdown: ; 1152b
+ call .GetDaysUntilNextFriday
+ ld hl, wLuckyNumberDayBuffer
+ jp InitNDaysCountdown
+; 11534
+
+.GetDaysUntilNextFriday: ; 11534
+ call GetWeekday
+ ld c, a
+ ld a, FRIDAY
+ sub c
+ jr z, .friday_saturday
+ jr nc, .earlier ; could have done "ret nc"
+
+.friday_saturday
+ add 7
+
+.earlier
+ ret
+; 11542
+
+_CheckLuckyNumberShowFlag: ; 11542
+ ld hl, wLuckyNumberDayBuffer
+ jp CheckDayDependentEventHL
+; 11548
+
+DoMysteryGiftIfDayHasPassed: ; 11548
+ ld a, BANK(sMysteryGiftTimer)
+ call GetSRAMBank
+ ld hl, sMysteryGiftTimer
+ ld a, [hli]
+ ld [wBuffer1], a
+ ld a, [hl]
+ ld [wBuffer2], a
+ call CloseSRAM
+
+ ld hl, wBuffer1
+ call CheckDayDependentEventHL
+ jr nc, .not_timed_out
+ ld hl, wBuffer1
+ call InitOneDayCountdown
+ call CloseSRAM
+ farcall Function1050c8
+
+.not_timed_out
+ ld a, BANK(sMysteryGiftTimer)
+ call GetSRAMBank
+ ld hl, wBuffer1
+ ld a, [hli]
+ ld [sMysteryGiftTimer], a
+ ld a, [hl]
+ ld [sMysteryGiftTimer + 1], a
+ call CloseSRAM
+ ret
+; 11586
+
+UpdateTimeRemaining: ; 11586
+; If the amount of time elapsed exceeds the capacity of its
+; unit, skip this part.
+ cp -1
+ jr z, .set_carry
+ ld c, a
+ ld a, [hl] ; time remaining
+ sub c
+ jr nc, .ok
+ xor a
+
+.ok
+ ld [hl], a
+ jr z, .set_carry
+ xor a
+ ret
+
+.set_carry
+ xor a
+ ld [hl], a
+ scf
+ ret
+; 11599
+
+GetSecondsSinceIfLessThan60: ; 11599
+ ld a, [wDaysSince]
+ and a
+ jr nz, GetTimeElapsed_ExceedsUnitLimit
+ ld a, [wHoursSince]
+ and a
+ jr nz, GetTimeElapsed_ExceedsUnitLimit
+ ld a, [wMinutesSince]
+ jr nz, GetTimeElapsed_ExceedsUnitLimit
+ ld a, [wSecondsSince]
+ ret
+; 115ae
+
+GetMinutesSinceIfLessThan60: ; 115ae
+ ld a, [wDaysSince]
+ and a
+ jr nz, GetTimeElapsed_ExceedsUnitLimit
+ ld a, [wHoursSince]
+ and a
+ jr nz, GetTimeElapsed_ExceedsUnitLimit
+ ld a, [wMinutesSince]
+ ret
+; 115be
+
+GetHoursSinceIfLessThan24: ; 115be
+ ld a, [wDaysSince]
+ and a
+ jr nz, GetTimeElapsed_ExceedsUnitLimit
+ ld a, [wHoursSince]
+ ret
+; 115c8
+
+GetDaysSince: ; 115c8
+ ld a, [wDaysSince]
+ ret
+; 115cc
+
+GetTimeElapsed_ExceedsUnitLimit: ; 115cc
+ ld a, -1
+ ret
+; 115cf
+
+CalcDaysSince: ; 115cf
+ xor a
+ jr _CalcDaysSince
+; 115d2
+
+CalcHoursDaysSince: ; 115d2
+ inc hl
+ xor a
+ jr _CalcHoursDaysSince
+; 115d6
+
+CalcMinsHoursDaysSince: ; 115d6
+ inc hl
+ inc hl
+ xor a
+ jr _CalcMinsHoursDaysSince
+; 115db
+
+CalcSecsMinsHoursDaysSince: ; 115db
+ inc hl
+ inc hl
+ inc hl
+ ld a, [hSeconds]
+ ld c, a
+ sub [hl]
+ jr nc, .skip
+ add 60
+.skip
+ ld [hl], c ; current seconds
+ dec hl
+ ld [wSecondsSince], a ; seconds since
+
+_CalcMinsHoursDaysSince: ; 115eb
+ ld a, [hMinutes]
+ ld c, a
+ sbc [hl]
+ jr nc, .skip
+ add 60
+.skip
+ ld [hl], c ; current minutes
+ dec hl
+ ld [wMinutesSince], a ; minutes since
+
+_CalcHoursDaysSince: ; 115f8
+ ld a, [hHours]
+ ld c, a
+ sbc [hl]
+ jr nc, .skip
+ add 24
+.skip
+ ld [hl], c ; current hours
+ dec hl
+ ld [wHoursSince], a ; hours since
+
+_CalcDaysSince:
+ ld a, [wCurDay]
+ ld c, a
+ sbc [hl]
+ jr nc, .skip
+ add 20 * 7
+.skip
+ ld [hl], c ; current days
+ ld [wDaysSince], a ; days since
+ ret
+; 11613
+
+CopyDayHourMinSecToHL: ; 11613
+ ld a, [wCurDay]
+ ld [hli], a
+ ld a, [hHours]
+ ld [hli], a
+ ld a, [hMinutes]
+ ld [hli], a
+ ld a, [hSeconds]
+ ld [hli], a
+ ret
+; 11621
+
+CopyDayToHL: ; 11621
+ ld a, [wCurDay]
+ ld [hl], a
+ ret
+; 11626
+
+CopyDayHourToHL: ; 11626
+ ld a, [wCurDay]
+ ld [hli], a
+ ld a, [hHours]
+ ld [hli], a
+ ret
+; 1162e
+
+CopyDayHourMinToHL: ; 1162e
+ ld a, [wCurDay]
+ ld [hli], a
+ ld a, [hHours]
+ ld [hli], a
+ ld a, [hMinutes]
+ ld [hli], a
+ ret
+; 11639
diff --git a/engine/overworld/variables.asm b/engine/overworld/variables.asm
new file mode 100755
index 000000000..89026fdba
--- /dev/null
+++ b/engine/overworld/variables.asm
@@ -0,0 +1,151 @@
+_GetVarAction:: ; 80648 (20:4648)
+ ld a, c
+ cp NUM_VARS
+ jr c, .valid
+ xor a
+.valid
+ ld c, a
+ ld b, 0
+ ld hl, .VarActionTable
+ add hl, bc
+ add hl, bc
+ add hl, bc
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ inc hl
+ ld b, [hl]
+ ld a, b
+ and RETVAR_EXECUTE
+ jr nz, .call
+ ld a, b
+ and RETVAR_ADDR_DE
+ ret nz
+ ld a, [de]
+ jr .loadstringbuffer2
+
+.call
+ call _de_
+ ret
+
+.loadstringbuffer2 ; 8066c (20:466c)
+ ld de, wStringBuffer2
+ ld [de], a
+ ret
+; 80671 (20:4671)
+
+.VarActionTable: ; 80671
+; entries correspond to VAR_* constants
+ ; RETVAR_STRBUF2: copy [de] to wStringBuffer2
+ ; RETVAR_ADDR_DE: return address in de
+ ; RETVAR_EXECUTE: call function
+ dwb wStringBuffer2, RETVAR_STRBUF2
+ dwb wPartyCount, RETVAR_STRBUF2
+ dwb .BattleResult, RETVAR_EXECUTE
+ dwb wBattleType, RETVAR_ADDR_DE
+ dwb wTimeOfDay, RETVAR_STRBUF2
+ dwb .CountCaughtMons, RETVAR_EXECUTE
+ dwb .CountSeenMons, RETVAR_EXECUTE
+ dwb .CountBadges, RETVAR_EXECUTE
+ dwb wPlayerState, RETVAR_ADDR_DE
+ dwb .PlayerFacing, RETVAR_EXECUTE
+ dwb hHours, RETVAR_STRBUF2
+ dwb .DayOfWeek, RETVAR_EXECUTE
+ dwb wMapGroup, RETVAR_STRBUF2
+ dwb wMapNumber, RETVAR_STRBUF2
+ dwb .UnownCaught, RETVAR_EXECUTE
+ dwb wEnvironment, RETVAR_STRBUF2
+ dwb .BoxFreeSpace, RETVAR_EXECUTE
+ dwb wBugContestMinsRemaining, RETVAR_STRBUF2
+ dwb wXCoord, RETVAR_STRBUF2
+ dwb wYCoord, RETVAR_STRBUF2
+ dwb wSpecialPhoneCallID, RETVAR_STRBUF2
+ dwb wNrOfBeatenBattleTowerTrainers, RETVAR_STRBUF2
+ dwb wKurtApricornQuantity, RETVAR_STRBUF2
+ dwb wCurrentCaller, RETVAR_ADDR_DE
+ dwb wBlueCardBalance, RETVAR_ADDR_DE
+ dwb wBuenasPassword, RETVAR_ADDR_DE
+ dwb wKenjiBreakTimer, RETVAR_STRBUF2
+ dwb NULL, RETVAR_STRBUF2
+; 806c5
+
+.CountCaughtMons: ; 806c5
+; Caught mons.
+ ld hl, wPokedexCaught
+ ld b, wEndPokedexCaught - wPokedexCaught
+ call CountSetBits
+ ld a, [wd265]
+ jp .loadstringbuffer2
+; 806d3
+
+.CountSeenMons: ; 806d3
+; Seen mons.
+ ld hl, wPokedexSeen
+ ld b, wEndPokedexSeen - wPokedexSeen
+ call CountSetBits
+ ld a, [wd265]
+ jp .loadstringbuffer2
+; 806e1
+
+.CountBadges: ; 806e1
+; Number of owned badges.
+ ld hl, wBadges
+ ld b, 2
+ call CountSetBits
+ ld a, [wd265]
+ jp .loadstringbuffer2
+; 806ef
+
+.PlayerFacing: ; 806ef
+; The direction the player is facing.
+ ld a, [wPlayerDirection]
+ and $c
+ rrca
+ rrca
+ jp .loadstringbuffer2
+; 806f9
+
+.DayOfWeek: ; 806f9
+; The day of the week.
+ call GetWeekday
+ jp .loadstringbuffer2
+; 806ff
+
+.UnownCaught: ; 806ff
+; Number of unique Unown caught.
+ call .count
+ ld a, b
+ jp .loadstringbuffer2
+
+.count
+ ld hl, wUnownDex
+ ld b, 0
+.loop
+ ld a, [hli]
+ and a
+ ret z
+ inc b
+ ld a, b
+ cp NUM_UNOWN
+ jr c, .loop
+ ret
+; 80715
+
+.BoxFreeSpace: ; 80715
+; Remaining slots in the current box.
+ ld a, BANK(sBoxCount)
+ call GetSRAMBank
+ ld hl, sBoxCount
+ ld a, MONS_PER_BOX
+ sub [hl]
+ ld b, a
+ call CloseSRAM
+ ld a, b
+ jp .loadstringbuffer2
+; 80728
+
+.BattleResult: ; 80728
+ ld a, [wBattleResult]
+ and $3f
+ jp .loadstringbuffer2
+; 80730
diff --git a/engine/overworld/warp_connection.asm b/engine/overworld/warp_connection.asm
new file mode 100755
index 000000000..069b72234
--- /dev/null
+++ b/engine/overworld/warp_connection.asm
@@ -0,0 +1,439 @@
+
+HandleNewMap: ; 1045b0
+ call Clearwc7e8
+ call ResetMapBufferEventFlags
+ call ResetFlashIfOutOfCave
+ call GetCurrentMapSceneID
+ call ResetBikeFlags
+ ld a, MAPCALLBACK_NEWMAP
+ call RunMapCallback
+InitCommandQueue: ; 1045c4
+ farcall ClearCmdQueue
+ ld a, MAPCALLBACK_CMDQUEUE
+ call RunMapCallback
+ call GetMapTimeOfDay
+ ld [wMapTimeOfDay], a
+ ret
+
+
+EnterMapConnection: ; 1045d6
+; Return carry if a connection has been entered.
+ ld a, [wPlayerStepDirection]
+ and a
+ jp z, .south
+ cp UP
+ jp z, .north
+ cp LEFT
+ jp z, .west
+ cp RIGHT
+ jp z, .east
+ ret
+
+.west
+ ld a, [wWestConnectedMapGroup]
+ ld [wMapGroup], a
+ ld a, [wWestConnectedMapNumber]
+ ld [wMapNumber], a
+ ld a, [wWestConnectionStripXOffset]
+ ld [wXCoord], a
+ ld a, [wWestConnectionStripYOffset]
+ ld hl, wYCoord
+ add [hl]
+ ld [hl], a
+ ld c, a
+ ld hl, wWestConnectionWindow
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ srl c
+ jr z, .skip_to_load
+ ld a, [wWestConnectedMapWidth]
+ add 6
+ ld e, a
+ ld d, 0
+
+.loop
+ add hl, de
+ dec c
+ jr nz, .loop
+
+.skip_to_load
+ ld a, l
+ ld [wOverworldMapAnchor], a
+ ld a, h
+ ld [wOverworldMapAnchor + 1], a
+ jp .done
+
+.east
+ ld a, [wEastConnectedMapGroup]
+ ld [wMapGroup], a
+ ld a, [wEastConnectedMapNumber]
+ ld [wMapNumber], a
+ ld a, [wEastConnectionStripXOffset]
+ ld [wXCoord], a
+ ld a, [wEastConnectionStripYOffset]
+ ld hl, wYCoord
+ add [hl]
+ ld [hl], a
+ ld c, a
+ ld hl, wEastConnectionWindow
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ srl c
+ jr z, .skip_to_load2
+ ld a, [wEastConnectedMapWidth]
+ add 6
+ ld e, a
+ ld d, 0
+
+.loop2
+ add hl, de
+ dec c
+ jr nz, .loop2
+
+.skip_to_load2
+ ld a, l
+ ld [wOverworldMapAnchor], a
+ ld a, h
+ ld [wOverworldMapAnchor + 1], a
+ jp .done
+
+.north
+ ld a, [wNorthConnectedMapGroup]
+ ld [wMapGroup], a
+ ld a, [wNorthConnectedMapNumber]
+ ld [wMapNumber], a
+ ld a, [wNorthConnectionStripYOffset]
+ ld [wYCoord], a
+ ld a, [wNorthConnectionStripXOffset]
+ ld hl, wXCoord
+ add [hl]
+ ld [hl], a
+ ld c, a
+ ld hl, wNorthConnectionWindow
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld b, 0
+ srl c
+ add hl, bc
+ ld a, l
+ ld [wOverworldMapAnchor], a
+ ld a, h
+ ld [wOverworldMapAnchor + 1], a
+ jp .done
+
+.south
+ ld a, [wSouthConnectedMapGroup]
+ ld [wMapGroup], a
+ ld a, [wSouthConnectedMapNumber]
+ ld [wMapNumber], a
+ ld a, [wSouthConnectionStripYOffset]
+ ld [wYCoord], a
+ ld a, [wSouthConnectionStripXOffset]
+ ld hl, wXCoord
+ add [hl]
+ ld [hl], a
+ ld c, a
+ ld hl, wSouthConnectionWindow
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld b, 0
+ srl c
+ add hl, bc
+ ld a, l
+ ld [wOverworldMapAnchor], a
+ ld a, h
+ ld [wOverworldMapAnchor + 1], a
+.done
+ scf
+ ret
+; 1046c6
+
+LoadWarpData: ; 1046c6
+ call .SaveDigWarp
+ call .SetSpawn
+ ld a, [wNextWarp]
+ ld [wWarpNumber], a
+ ld a, [wNextMapGroup]
+ ld [wMapGroup], a
+ ld a, [wNextMapNumber]
+ ld [wMapNumber], a
+ ret
+
+.SaveDigWarp: ; 1046df (41:46df)
+ call GetMapEnvironment
+ call CheckOutdoorMap
+ ret nz
+ ld a, [wNextMapGroup]
+ ld b, a
+ ld a, [wNextMapNumber]
+ ld c, a
+ call GetAnyMapEnvironment
+ call CheckIndoorMap
+ ret nz
+
+; MOUNT_MOON_SQUARE and TIN_TOWER_ROOF are outdoor maps within indoor maps.
+; Dig and Escape Rope should not take you to them.
+ ld a, [wPrevMapGroup]
+ cp GROUP_MOUNT_MOON_SQUARE ; GROUP_TIN_TOWER_ROOF
+ jr nz, .not_mt_moon_or_tin_tower
+ ld a, [wPrevMapNumber]
+ cp MAP_MOUNT_MOON_SQUARE
+ ret z
+ cp MAP_TIN_TOWER_ROOF
+ ret z
+.not_mt_moon_or_tin_tower
+
+ ld a, [wPrevWarp]
+ ld [wDigWarpNumber], a
+ ld a, [wPrevMapGroup]
+ ld [wDigMapGroup], a
+ ld a, [wPrevMapNumber]
+ ld [wDigMapNumber], a
+ ret
+
+.SetSpawn: ; 104718 (41:4718)
+ call GetMapEnvironment
+ call CheckOutdoorMap
+ ret nz
+ ld a, [wNextMapGroup]
+ ld b, a
+ ld a, [wNextMapNumber]
+ ld c, a
+ call GetAnyMapEnvironment
+ call CheckIndoorMap
+ ret nz
+ ld a, [wNextMapGroup]
+ ld b, a
+ ld a, [wNextMapNumber]
+ ld c, a
+
+; Respawn in Pokémon Centers.
+ call GetAnyMapTileset
+ ld a, c
+ cp TILESET_POKECENTER
+ jr z, .pokecenter_pokecom
+ cp TILESET_POKECOM_CENTER
+ jr z, .pokecenter_pokecom
+ ret
+.pokecenter_pokecom
+
+ ld a, [wPrevMapGroup]
+ ld [wLastSpawnMapGroup], a
+ ld a, [wPrevMapNumber]
+ ld [wLastSpawnMapNumber], a
+ ret
+
+LoadMapTimeOfDay: ; 104750
+ ld hl, wVramState
+ res 6, [hl]
+ ld a, $1
+ ld [wSpriteUpdatesEnabled], a
+ farcall ReplaceTimeOfDayPals
+ farcall UpdateTimeOfDayPal
+ call OverworldTextModeSwitch
+ call .ClearBGMap
+ call .PushAttrMap
+ ret
+
+.ClearBGMap: ; 104770 (41:4770)
+ ld a, HIGH(vBGMap0)
+ ld [wBGMapAnchor + 1], a
+ xor a ; LOW(vBGMap0)
+ ld [wBGMapAnchor], a
+ ld [hSCY], a
+ ld [hSCX], a
+ farcall ApplyBGMapAnchorToObjects
+
+ ld a, [rVBK]
+ push af
+ ld a, $1
+ ld [rVBK], a
+
+ xor a
+ ld bc, vBGMap1 - vBGMap0
+ hlbgcoord 0, 0
+ call ByteFill
+
+ pop af
+ ld [rVBK], a
+
+ ld a, "■"
+ ld bc, vBGMap1 - vBGMap0
+ hlbgcoord 0, 0
+ call ByteFill
+ ret
+
+.PushAttrMap: ; 1047a3 (41:47a3)
+ decoord 0, 0
+ call .copy
+ ld a, [hCGB]
+ and a
+ ret z
+
+ decoord 0, 0, wAttrMap
+ ld a, $1
+ ld [rVBK], a
+.copy
+ hlbgcoord 0, 0
+ ld c, SCREEN_WIDTH
+ ld b, SCREEN_HEIGHT
+.row
+ push bc
+.column
+ ld a, [de]
+ inc de
+ ld [hli], a
+ dec c
+ jr nz, .column
+ ld bc, BG_MAP_WIDTH - SCREEN_WIDTH
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .row
+ ld a, $0
+ ld [rVBK], a
+ ret
+
+LoadGraphics: ; 1047cf
+ call LoadTileset
+ call LoadTilesetGFX
+ xor a
+ ld [hMapAnims], a
+ xor a
+ ld [hTileAnimFrame], a
+ farcall RefreshSprites
+ call LoadFontsExtra
+ farcall LoadOverworldFont
+ ret
+
+LoadMapPalettes: ; 1047eb
+ ld b, SCGB_MAPPALS
+ jp GetSGBLayout
+; 1047f0
+
+RefreshMapSprites: ; 1047f0
+ call ClearSprites
+ farcall ReturnFromMapSetupScript
+ call GetMovementPermissions
+ farcall RefreshPlayerSprite
+ farcall CheckReplaceKrisSprite
+ ld hl, wPlayerSpriteSetupFlags
+ bit PLAYERSPRITESETUP_SKIP_RELOAD_GFX_F, [hl]
+ jr nz, .skip
+ ld hl, wVramState
+ set 0, [hl]
+ call SafeUpdateSprites
+.skip
+ ld a, [wPlayerSpriteSetupFlags]
+ and %00011100
+ ld [wPlayerSpriteSetupFlags], a
+ ret
+
+CheckMovingOffEdgeOfMap:: ; 104820 (41:4820)
+ ld a, [wPlayerStepDirection]
+ cp STANDING
+ ret z
+ and a ; DOWN
+ jr z, .down
+ cp UP
+ jr z, .up
+ cp LEFT
+ jr z, .left
+ cp RIGHT
+ jr z, .right
+ and a
+ ret
+
+.down
+ ld a, [wPlayerStandingMapY]
+ sub 4
+ ld b, a
+ ld a, [wMapHeight]
+ add a
+ cp b
+ jr z, .ok
+ and a
+ ret
+
+.up
+ ld a, [wPlayerStandingMapY]
+ sub 4
+ cp -1
+ jr z, .ok
+ and a
+ ret
+
+.left
+ ld a, [wPlayerStandingMapX]
+ sub 4
+ cp -1
+ jr z, .ok
+ and a
+ ret
+
+.right
+ ld a, [wPlayerStandingMapX]
+ sub 4
+ ld b, a
+ ld a, [wMapWidth]
+ add a
+ cp b
+ jr z, .ok
+ and a
+ ret
+
+.ok
+ scf
+ ret
+
+
+GetCoordOfUpperLeftCorner:: ; 10486d
+ ld hl, wOverworldMap
+ ld a, [wXCoord]
+ bit 0, a
+ jr nz, .increment_then_halve1
+ srl a
+ add $1
+ jr .resume
+
+.increment_then_halve1
+ add $1
+ srl a
+
+.resume
+ ld c, a
+ ld b, $0
+ add hl, bc
+ ld a, [wMapWidth]
+ add $6
+ ld c, a
+ ld b, $0
+ ld a, [wYCoord]
+ bit 0, a
+ jr nz, .increment_then_halve2
+ srl a
+ add $1
+ jr .resume2
+
+.increment_then_halve2
+ add $1
+ srl a
+
+.resume2
+ call AddNTimes
+ ld a, l
+ ld [wOverworldMapAnchor], a
+ ld a, h
+ ld [wOverworldMapAnchor + 1], a
+ ld a, [wYCoord]
+ and $1
+ ld [wMetatileStandingY], a
+ ld a, [wXCoord]
+ and $1
+ ld [wMetatileStandingX], a
+ ret
+; 1048ba
diff --git a/engine/overworld/wildmons.asm b/engine/overworld/wildmons.asm
new file mode 100755
index 000000000..494e8d2a4
--- /dev/null
+++ b/engine/overworld/wildmons.asm
@@ -0,0 +1,1000 @@
+LoadWildMonData: ; 29ff8
+ call _GrassWildmonLookup
+ jr c, .copy
+ ld hl, wMornEncounterRate
+ xor a
+ ld [hli], a
+ ld [hli], a
+ ld [hl], a
+ jr .done_copy
+
+.copy
+ inc hl
+ inc hl
+ ld de, wMornEncounterRate
+ ld bc, 3
+ call CopyBytes
+.done_copy
+ call _WaterWildmonLookup
+ ld a, 0
+ jr nc, .no_copy
+ inc hl
+ inc hl
+ ld a, [hl]
+.no_copy
+ ld [wWaterEncounterRate], a
+ ret
+
+FindNest: ; 2a01f
+; Parameters:
+; e: 0 = Johto, 1 = Kanto
+; wNamedObjectIndexBuffer: species
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ xor a
+ call ByteFill
+ ld a, e
+ and a
+ jr nz, .kanto
+ decoord 0, 0
+ ld hl, JohtoGrassWildMons
+ call .FindGrass
+ ld hl, JohtoWaterWildMons
+ call .FindWater
+ call .RoamMon1
+ call .RoamMon2
+ ret
+
+.kanto
+ decoord 0, 0
+ ld hl, KantoGrassWildMons
+ call .FindGrass
+ ld hl, KantoWaterWildMons
+ jp .FindWater
+; 2a052
+
+.FindGrass: ; 2a052
+ ld a, [hl]
+ cp -1
+ ret z
+ push hl
+ ld a, [hli]
+ ld b, a
+ ld a, [hli]
+ ld c, a
+ inc hl
+ inc hl
+ inc hl
+ ld a, NUM_GRASSMON * 3
+ call .SearchMapForMon
+ jr nc, .next_grass
+ ld [de], a
+ inc de
+
+.next_grass
+ pop hl
+ ld bc, GRASS_WILDDATA_LENGTH
+ add hl, bc
+ jr .FindGrass
+; 2a06e
+
+.FindWater: ; 2a06e
+ ld a, [hl]
+ cp -1
+ ret z
+ push hl
+ ld a, [hli]
+ ld b, a
+ ld a, [hli]
+ ld c, a
+ inc hl
+ ld a, 3
+ call .SearchMapForMon
+ jr nc, .next_water
+ ld [de], a
+ inc de
+
+.next_water
+ pop hl
+ ld bc, 3 * 3
+ add hl, bc
+ jr .FindWater
+; 2a088
+
+.SearchMapForMon: ; 2a088
+ inc hl
+.ScanMapLoop:
+ push af
+ ld a, [wNamedObjectIndexBuffer]
+ cp [hl]
+ jr z, .found
+ inc hl
+ inc hl
+ pop af
+ dec a
+ jr nz, .ScanMapLoop
+ and a
+ ret
+
+.found
+ pop af
+ jp .AppendNest
+; 2a09c
+
+.AppendNest: ; 2a09c
+ push de
+ call GetWorldMapLocation
+ ld c, a
+ hlcoord 0, 0
+ ld de, SCREEN_WIDTH * SCREEN_HEIGHT
+.AppendNestLoop:
+ ld a, [hli]
+ cp c
+ jr z, .found_nest
+ dec de
+ ld a, e
+ or d
+ jr nz, .AppendNestLoop
+ ld a, c
+ pop de
+ scf
+ ret
+
+.found_nest
+ pop de
+ and a
+ ret
+; 2a0b7
+
+.RoamMon1: ; 2a0b7
+ ld a, [wRoamMon1Species]
+ ld b, a
+ ld a, [wNamedObjectIndexBuffer]
+ cp b
+ ret nz
+ ld a, [wRoamMon1MapGroup]
+ ld b, a
+ ld a, [wRoamMon1MapNumber]
+ ld c, a
+ call .AppendNest
+ ret nc
+ ld [de], a
+ inc de
+ ret
+; 2a0cf
+
+.RoamMon2: ; 2a0cf
+ ld a, [wRoamMon2Species]
+ ld b, a
+ ld a, [wNamedObjectIndexBuffer]
+ cp b
+ ret nz
+ ld a, [wRoamMon2MapGroup]
+ ld b, a
+ ld a, [wRoamMon2MapNumber]
+ ld c, a
+ call .AppendNest
+ ret nc
+ ld [de], a
+ inc de
+ ret
+; 2a0e7
+
+TryWildEncounter:: ; 2a0e7
+; Try to trigger a wild encounter.
+ call .EncounterRate
+ jr nc, .no_battle
+ call ChooseWildEncounter
+ jr nz, .no_battle
+ call CheckRepelEffect
+ jr nc, .no_battle
+ xor a
+ ret
+
+.no_battle
+ xor a ; BATTLETYPE_NORMAL
+ ld [wTempWildMonSpecies], a
+ ld [wBattleType], a
+ ld a, 1
+ and a
+ ret
+; 2a103
+
+.EncounterRate: ; 2a103
+ call GetMapEncounterRate
+ call ApplyMusicEffectOnEncounterRate
+ call ApplyCleanseTagEffectOnEncounterRate
+ call Random
+ cp b
+ ret
+; 2a111
+
+GetMapEncounterRate: ; 2a111
+ ld hl, wMornEncounterRate
+ call CheckOnWater
+ ld a, wWaterEncounterRate - wMornEncounterRate
+ jr z, .ok
+ ld a, [wTimeOfDay]
+.ok
+ ld c, a
+ ld b, 0
+ add hl, bc
+ ld b, [hl]
+ ret
+; 2a124
+
+ApplyMusicEffectOnEncounterRate:: ; 2a124
+; Pokemon March and Ruins of Alph signal double encounter rate.
+; Pokemon Lullaby halves encounter rate.
+ ld a, [wMapMusic]
+ cp MUSIC_POKEMON_MARCH
+ jr z, .double
+ cp MUSIC_RUINS_OF_ALPH_RADIO
+ jr z, .double
+ cp MUSIC_POKEMON_LULLABY
+ ret nz
+ srl b
+ ret
+
+.double
+ sla b
+ ret
+; 2a138
+
+ApplyCleanseTagEffectOnEncounterRate:: ; 2a138
+; Cleanse Tag halves encounter rate.
+ ld hl, wPartyMon1Item
+ ld de, PARTYMON_STRUCT_LENGTH
+ ld a, [wPartyCount]
+ ld c, a
+.loop
+ ld a, [hl]
+ cp CLEANSE_TAG
+ jr z, .cleansetag
+ add hl, de
+ dec c
+ jr nz, .loop
+ ret
+
+.cleansetag
+ srl b
+ ret
+; 2a14f
+
+ChooseWildEncounter: ; 2a14f
+ call LoadWildMonDataPointer
+ jp nc, .nowildbattle
+ call CheckEncounterRoamMon
+ jp c, .startwildbattle
+
+ inc hl
+ inc hl
+ inc hl
+ call CheckOnWater
+ ld de, WaterMonProbTable
+ jr z, .watermon
+ inc hl
+ inc hl
+ ld a, [wTimeOfDay]
+ ld bc, $e
+ call AddNTimes
+ ld de, GrassMonProbTable
+
+.watermon
+; hl contains the pointer to the wild mon data, let's save that to the stack
+ push hl
+.randomloop
+ call Random
+ cp 100
+ jr nc, .randomloop
+ inc a ; 1 <= a <= 100
+ ld b, a
+ ld h, d
+ ld l, e
+; This next loop chooses which mon to load up.
+.prob_bracket_loop
+ ld a, [hli]
+ cp b
+ jr nc, .got_it
+ inc hl
+ jr .prob_bracket_loop
+
+.got_it
+ ld c, [hl]
+ ld b, 0
+ pop hl
+ add hl, bc ; this selects our mon
+ ld a, [hli]
+ ld b, a
+; If the Pokemon is encountered by surfing, we need to give the levels some variety.
+ call CheckOnWater
+ jr nz, .ok
+; Check if we buff the wild mon, and by how much.
+ call Random
+ cp 35 percent
+ jr c, .ok
+ inc b
+ cp 65 percent
+ jr c, .ok
+ inc b
+ cp 85 percent
+ jr c, .ok
+ inc b
+ cp 95 percent
+ jr c, .ok
+ inc b
+; Store the level
+.ok
+ ld a, b
+ ld [wCurPartyLevel], a
+ ld b, [hl]
+ ; ld a, b
+ call ValidateTempWildMonSpecies
+ jr c, .nowildbattle
+
+ ld a, b ; This is in the wrong place.
+ cp UNOWN
+ jr nz, .done
+
+ ld a, [wUnlockedUnowns]
+ and a
+ jr z, .nowildbattle
+
+.done
+ jr .loadwildmon
+
+.nowildbattle
+ ld a, 1
+ and a
+ ret
+
+.loadwildmon
+ ld a, b
+ ld [wTempWildMonSpecies], a
+
+.startwildbattle
+ xor a
+ ret
+; 2a1cb
+
+INCLUDE "data/wild/probabilities.asm"
+
+CheckRepelEffect:: ; 2a1df
+; If there is no active Repel, there's no need to be here.
+ ld a, [wRepelEffect]
+ and a
+ jr z, .encounter
+; Get the first Pokemon in your party that isn't fainted.
+ ld hl, wPartyMon1HP
+ ld bc, PARTYMON_STRUCT_LENGTH - 1
+.loop
+ ld a, [hli]
+ or [hl]
+ jr nz, .ok
+ add hl, bc
+ jr .loop
+
+.ok
+; to PartyMonLevel
+rept 4
+ dec hl
+endr
+
+ ld a, [wCurPartyLevel]
+ cp [hl]
+ jr nc, .encounter
+ and a
+ ret
+
+.encounter
+ scf
+ ret
+; 2a200
+
+LoadWildMonDataPointer: ; 2a200
+ call CheckOnWater
+ jr z, _WaterWildmonLookup
+
+_GrassWildmonLookup: ; 2a205
+ ld hl, SwarmGrassWildMons
+ ld bc, GRASS_WILDDATA_LENGTH
+ call _SwarmWildmonCheck
+ ret c
+ ld hl, JohtoGrassWildMons
+ ld de, KantoGrassWildMons
+ call _JohtoWildmonCheck
+ ld bc, GRASS_WILDDATA_LENGTH
+ jr _NormalWildmonOK
+
+_WaterWildmonLookup: ; 2a21d
+ ld hl, SwarmWaterWildMons
+ ld bc, WATER_WILDDATA_LENGTH
+ call _SwarmWildmonCheck
+ ret c
+ ld hl, JohtoWaterWildMons
+ ld de, KantoWaterWildMons
+ call _JohtoWildmonCheck
+ ld bc, WATER_WILDDATA_LENGTH
+ jr _NormalWildmonOK
+
+_JohtoWildmonCheck
+ call IsInJohto
+ and a
+ ret z
+ ld h, d
+ ld l, e
+ ret
+
+_SwarmWildmonCheck
+ call CopyCurrMapDE
+ push hl
+ ld hl, wSwarmFlags
+ bit SWARMFLAGS_DUNSPARCE_SWARM_F, [hl]
+ pop hl
+ jr z, .CheckYanma
+ ld a, [wDunsparceMapGroup]
+ cp d
+ jr nz, .CheckYanma
+ ld a, [wDunsparceMapNumber]
+ cp e
+ jr nz, .CheckYanma
+ call LookUpWildmonsForMapDE
+ jr nc, _NoSwarmWildmon
+ scf
+ ret
+
+.CheckYanma:
+ push hl
+ ld hl, wSwarmFlags
+ bit SWARMFLAGS_YANMA_SWARM_F, [hl]
+ pop hl
+ jr z, _NoSwarmWildmon
+ ld a, [wYanmaMapGroup]
+ cp d
+ jr nz, _NoSwarmWildmon
+ ld a, [wYanmaMapNumber]
+ cp e
+ jr nz, _NoSwarmWildmon
+ call LookUpWildmonsForMapDE
+ jr nc, _NoSwarmWildmon
+ scf
+ ret
+
+_NoSwarmWildmon
+ and a
+ ret
+
+_NormalWildmonOK
+ call CopyCurrMapDE
+ jr LookUpWildmonsForMapDE
+; 2a27f
+
+CopyCurrMapDE: ; 2a27f
+ ld a, [wMapGroup]
+ ld d, a
+ ld a, [wMapNumber]
+ ld e, a
+ ret
+; 2a288
+
+LookUpWildmonsForMapDE: ; 2a288
+.loop
+ push hl
+ ld a, [hl]
+ inc a
+ jr z, .nope
+ ld a, d
+ cp [hl]
+ jr nz, .next
+ inc hl
+ ld a, e
+ cp [hl]
+ jr z, .yup
+
+.next
+ pop hl
+ add hl, bc
+ jr .loop
+
+.nope
+ pop hl
+ and a
+ ret
+
+.yup
+ pop hl
+ scf
+ ret
+; 2a2a0
+
+
+InitRoamMons: ; 2a2a0
+; initialize wRoamMon structs
+
+; species
+ ld a, RAIKOU
+ ld [wRoamMon1Species], a
+ ld a, ENTEI
+ ld [wRoamMon2Species], a
+
+; level
+ ld a, 40
+ ld [wRoamMon1Level], a
+ ld [wRoamMon2Level], a
+
+; raikou starting map
+ ld a, GROUP_ROUTE_42
+ ld [wRoamMon1MapGroup], a
+ ld a, MAP_ROUTE_42
+ ld [wRoamMon1MapNumber], a
+
+; entei starting map
+ ld a, GROUP_ROUTE_37
+ ld [wRoamMon2MapGroup], a
+ ld a, MAP_ROUTE_37
+ ld [wRoamMon2MapNumber], a
+
+; hp
+ xor a ; generate new stats
+ ld [wRoamMon1HP], a
+ ld [wRoamMon2HP], a
+
+ ret
+; 2a2ce
+
+
+CheckEncounterRoamMon: ; 2a2ce
+ push hl
+; Don't trigger an encounter if we're on water.
+ call CheckOnWater
+ jr z, .DontEncounterRoamMon
+; Load the current map group and number to de
+ call CopyCurrMapDE
+; Randomly select a beast.
+ call Random
+ cp 100 ; 25/64 chance
+ jr nc, .DontEncounterRoamMon
+ and %00000011 ; Of that, a 3/4 chance. Running total: 75/256, or around 29.3%.
+ jr z, .DontEncounterRoamMon
+ dec a ; 1/3 chance that it's Entei, 1/3 chance that it's Raikou
+; Compare its current location with yours
+ ld hl, wRoamMon1MapGroup
+ ld c, a
+ ld b, 0
+ ld a, 7 ; length of the roam_struct
+ call AddNTimes
+ ld a, d
+ cp [hl]
+ jr nz, .DontEncounterRoamMon
+ inc hl
+ ld a, e
+ cp [hl]
+ jr nz, .DontEncounterRoamMon
+; We've decided to take on a beast, so stage its information for battle.
+ dec hl
+ dec hl
+ dec hl
+ ld a, [hli]
+ ld [wTempWildMonSpecies], a
+ ld a, [hl]
+ ld [wCurPartyLevel], a
+ ld a, BATTLETYPE_ROAMING
+ ld [wBattleType], a
+
+ pop hl
+ scf
+ ret
+
+.DontEncounterRoamMon:
+ pop hl
+ and a
+ ret
+; 2a30d
+
+
+UpdateRoamMons: ; 2a30d
+ ld a, [wRoamMon1MapGroup]
+ cp GROUP_N_A
+ jr z, .SkipRaikou
+ ld b, a
+ ld a, [wRoamMon1MapNumber]
+ ld c, a
+ call .Update
+ ld a, b
+ ld [wRoamMon1MapGroup], a
+ ld a, c
+ ld [wRoamMon1MapNumber], a
+
+.SkipRaikou:
+ ld a, [wRoamMon2MapGroup]
+ cp GROUP_N_A
+ jr z, .SkipEntei
+ ld b, a
+ ld a, [wRoamMon2MapNumber]
+ ld c, a
+ call .Update
+ ld a, b
+ ld [wRoamMon2MapGroup], a
+ ld a, c
+ ld [wRoamMon2MapNumber], a
+
+.SkipEntei:
+ ld a, [wRoamMon3MapGroup]
+ cp GROUP_N_A
+ jr z, .Finished
+ ld b, a
+ ld a, [wRoamMon3MapNumber]
+ ld c, a
+ call .Update
+ ld a, b
+ ld [wRoamMon3MapGroup], a
+ ld a, c
+ ld [wRoamMon3MapNumber], a
+
+.Finished:
+ jp _BackUpMapIndices
+; 2a355
+
+
+.Update: ; 2a355
+ ld hl, RoamMaps
+.loop
+; Are we at the end of the table?
+ ld a, [hl]
+ cp -1
+ ret z
+; Is this the correct entry?
+ ld a, b
+ cp [hl]
+ jr nz, .next
+ inc hl
+ ld a, c
+ cp [hl]
+ jr z, .yes
+; We don't have the correct entry yet, so let's continue. A 0 terminates each entry.
+.next
+ ld a, [hli]
+ and a
+ jr nz, .next
+ jr .loop
+
+; We have the correct entry now, so let's choose a random map from it.
+.yes
+ inc hl
+ ld d, h
+ ld e, l
+.update_loop
+ ld h, d
+ ld l, e
+; Choose which map to warp to.
+ call Random
+ and %00011111 ; 1/8n chance it moves to a completely random map, where n is the number of roaming connections from the current map.
+ jr z, JumpRoamMon
+ and %11
+ cp [hl]
+ jr nc, .update_loop ; invalid index, try again
+ inc hl
+ ld c, a
+ ld b, $0
+ add hl, bc
+ add hl, bc
+ ld a, [wRoamMons_LastMapGroup]
+ cp [hl]
+ jr nz, .done
+ inc hl
+ ld a, [wRoamMons_LastMapNumber]
+ cp [hl]
+ jr z, .update_loop
+ dec hl
+
+.done
+ ld a, [hli]
+ ld b, a
+ ld c, [hl]
+ ret
+
+JumpRoamMons: ; 2a394
+ ld a, [wRoamMon1MapGroup]
+ cp GROUP_N_A
+ jr z, .SkipRaikou
+ call JumpRoamMon
+ ld a, b
+ ld [wRoamMon1MapGroup], a
+ ld a, c
+ ld [wRoamMon1MapNumber], a
+
+.SkipRaikou:
+ ld a, [wRoamMon2MapGroup]
+ cp GROUP_N_A
+ jr z, .SkipEntei
+ call JumpRoamMon
+ ld a, b
+ ld [wRoamMon2MapGroup], a
+ ld a, c
+ ld [wRoamMon2MapNumber], a
+
+.SkipEntei:
+ ld a, [wRoamMon3MapGroup]
+ cp GROUP_N_A
+ jr z, .Finished
+ call JumpRoamMon
+ ld a, b
+ ld [wRoamMon3MapGroup], a
+ ld a, c
+ ld [wRoamMon3MapNumber], a
+
+.Finished:
+ jp _BackUpMapIndices
+
+JumpRoamMon: ; 2a3cd
+.loop
+ ld hl, RoamMaps
+.innerloop1 ; This loop happens to be unnecessary.
+ call Random ; Choose a random number.
+ maskbits NUM_ROAMMON_MAPS ; Mask the number to limit it between 0 and 15.
+ cp NUM_ROAMMON_MAPS ; If the number is not less than 16, try again.
+ jr nc, .innerloop1 ; I'm sure you can guess why this check is bogus.
+ inc a
+ ld b, a
+.innerloop2 ; Loop to get hl to the address of the chosen roam map.
+ dec b
+ jr z, .ok
+.innerloop3 ; Loop to skip the current roam map, which is terminated by a 0.
+ ld a, [hli]
+ and a
+ jr nz, .innerloop3
+ jr .innerloop2
+; Check to see if the selected map is the one the player is currently in. If so, try again.
+.ok
+ ld a, [wMapGroup]
+ cp [hl]
+ jr nz, .done
+ inc hl
+ ld a, [wMapNumber]
+ cp [hl]
+ jr z, .loop
+ dec hl
+; Return the map group and number in bc.
+.done
+ ld a, [hli]
+ ld b, a
+ ld c, [hl]
+ ret
+; 2a3f6
+
+_BackUpMapIndices: ; 2a3f6
+ ld a, [wRoamMons_CurrentMapNumber]
+ ld [wRoamMons_LastMapNumber], a
+ ld a, [wRoamMons_CurrentMapGroup]
+ ld [wRoamMons_LastMapGroup], a
+ ld a, [wMapNumber]
+ ld [wRoamMons_CurrentMapNumber], a
+ ld a, [wMapGroup]
+ ld [wRoamMons_CurrentMapGroup], a
+ ret
+; 2a40f
+
+
+INCLUDE "data/wild/roammon_maps.asm"
+
+
+ValidateTempWildMonSpecies: ; 2a4a0
+; Due to a development oversight, this function is called with the wild Pokemon's level, not its species, in a.
+ and a
+ jr z, .nowildmon ; = 0
+ cp NUM_POKEMON + 1 ; 252
+ jr nc, .nowildmon ; >= 252
+ and a ; 1 <= Species <= 251
+ ret
+
+.nowildmon
+ scf
+ ret
+; 2a4ab
+
+; Finds a rare wild Pokemon in the route of the trainer calling, then checks if it's been Seen already.
+; The trainer will then tell you about the Pokemon if you haven't seen it.
+RandomUnseenWildMon: ; 2a4ab
+ farcall GetCallerLocation
+ ld d, b
+ ld e, c
+ ld hl, JohtoGrassWildMons
+ ld bc, GRASS_WILDDATA_LENGTH
+ call LookUpWildmonsForMapDE
+ jr c, .GetGrassmon
+ ld hl, KantoGrassWildMons
+ call LookUpWildmonsForMapDE
+ jr nc, .done
+
+.GetGrassmon:
+ push hl
+ ld bc, 5 + 4 * 2 ; Location of the level of the 5th wild Pokemon in that map
+ add hl, bc
+ ld a, [wTimeOfDay]
+ ld bc, NUM_GRASSMON * 2
+ call AddNTimes
+.randloop1
+ call Random
+ and %11
+ jr z, .randloop1
+ dec a
+ ld c, a
+ ld b, $0
+ add hl, bc
+ add hl, bc
+; We now have the pointer to one of the last (rarest) three wild Pokemon found in that area.
+ inc hl
+ ld c, [hl] ; Contains the species index of this rare Pokemon
+ pop hl
+ ld de, 5 + 0 * 2
+ add hl, de
+ inc hl ; Species index of the most common Pokemon on that route
+ ld b, 4
+.loop2
+ ld a, [hli]
+ cp c ; Compare this most common Pokemon with the rare one stored in c.
+ jr z, .done
+ inc hl
+ dec b
+ jr nz, .loop2
+; This Pokemon truly is rare.
+ push bc
+ dec c
+ ld a, c
+ call CheckSeenMon
+ pop bc
+ jr nz, .done
+; Since we haven't seen it, have the caller tell us about it.
+ ld de, wStringBuffer1
+ call CopyName1
+ ld a, c
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ ld hl, .SawRareMonText
+ call PrintText
+ xor a
+ ld [wScriptVar], a
+ ret
+
+.done
+ ld a, $1
+ ld [wScriptVar], a
+ ret
+
+.SawRareMonText:
+ ; I just saw some rare @ in @ . I'll call you if I see another rare #MON, OK?
+ text_jump UnknownText_0x1bd34b
+ db "@"
+; 0x2a51f
+
+RandomPhoneWildMon: ; 2a51f
+ farcall GetCallerLocation
+ ld d, b
+ ld e, c
+ ld hl, JohtoGrassWildMons
+ ld bc, GRASS_WILDDATA_LENGTH
+ call LookUpWildmonsForMapDE
+ jr c, .ok
+ ld hl, KantoGrassWildMons
+ call LookUpWildmonsForMapDE
+
+.ok
+ ld bc, 5 + 0 * 2
+ add hl, bc
+ ld a, [wTimeOfDay]
+ inc a
+ ld bc, NUM_GRASSMON * 2
+.loop
+ dec a
+ jr z, .done
+ add hl, bc
+ jr .loop
+
+.done
+ call Random
+ and %11
+ ld c, a
+ ld b, $0
+ add hl, bc
+ add hl, bc
+ inc hl
+ ld a, [hl]
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ ld hl, wStringBuffer1
+ ld de, wStringBuffer4
+ ld bc, MON_NAME_LENGTH
+ jp CopyBytes
+; 2a567
+
+RandomPhoneMon: ; 2a567
+; Get a random monster owned by the trainer who's calling.
+ farcall GetCallerLocation
+ ld hl, TrainerGroups
+ ld a, d
+ dec a
+ ld c, a
+ ld b, 0
+ add hl, bc
+ add hl, bc
+ ld a, BANK(TrainerGroups)
+ call GetFarHalfword
+
+.skip_trainer
+ dec e
+ jr z, .skipped
+.skip
+ ld a, BANK(Trainers)
+ call GetFarByte
+ inc hl
+ cp -1
+ jr nz, .skip
+ jr .skip_trainer
+.skipped
+
+.skip_name
+ ld a, BANK(Trainers)
+ call GetFarByte
+ inc hl
+ cp "@"
+ jr nz, .skip_name
+
+ ld a, BANK(Trainers)
+ call GetFarByte
+ inc hl
+ ld bc, 2 ; level, species
+ cp TRAINERTYPE_NORMAL
+ jr z, .got_mon_length
+ ld bc, 2 + NUM_MOVES ; level, species, moves
+ cp TRAINERTYPE_MOVES
+ jr z, .got_mon_length
+ ld bc, 2 + 1 ; level, species, item
+ cp TRAINERTYPE_ITEM
+ jr z, .got_mon_length
+ ; TRAINERTYPE_ITEM_MOVES
+ ld bc, 2 + 1 + NUM_MOVES ; level, species, item, moves
+.got_mon_length
+
+ ld e, 0
+ push hl
+.count_mon
+ inc e
+ add hl, bc
+ ld a, BANK(Trainers)
+ call GetFarByte
+ cp -1
+ jr nz, .count_mon
+ pop hl
+
+.rand
+ call Random
+ maskbits PARTY_LENGTH
+ cp e
+ jr nc, .rand
+
+ inc a
+.get_mon
+ dec a
+ jr z, .got_mon
+ add hl, bc
+ jr .get_mon
+.got_mon
+
+ inc hl ; species
+ ld a, BANK(Trainers)
+ call GetFarByte
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ ld hl, wStringBuffer1
+ ld de, wStringBuffer4
+ ld bc, MON_NAME_LENGTH
+ jp CopyBytes
+; 2a5e9
+
+
+INCLUDE "data/wild/johto_grass.asm"
+INCLUDE "data/wild/johto_water.asm"
+INCLUDE "data/wild/kanto_grass.asm"
+INCLUDE "data/wild/kanto_water.asm"
+INCLUDE "data/wild/swarm_grass.asm"
+INCLUDE "data/wild/swarm_water.asm"