summaryrefslogtreecommitdiff
path: root/engine/overworld
diff options
context:
space:
mode:
authorU-Fish-PC\Daniel <corrnondacqb@yahoo.com>2014-05-22 18:13:20 -0400
committerU-Fish-PC\Daniel <corrnondacqb@yahoo.com>2014-05-22 18:13:20 -0400
commit15427f532085846ab6b51719be687951a094cb6c (patch)
treeedea9b189e91641a12dd521756894df84aeeace7 /engine/overworld
parentea3ba4cde3706b7c77efb705555ec0c86321cbe2 (diff)
Pull a lot of engine out of main.asm
Diffstat (limited to 'engine/overworld')
-rwxr-xr-xengine/overworld/cable_club_npc.asm156
-rwxr-xr-xengine/overworld/card_key.asm108
-rwxr-xr-xengine/overworld/cinnabar_lab.asm125
-rwxr-xr-xengine/overworld/cut.asm258
-rwxr-xr-xengine/overworld/cut2.asm89
-rwxr-xr-xengine/overworld/doors.asm88
-rwxr-xr-xengine/overworld/elevator.asm69
-rwxr-xr-xengine/overworld/emotion_bubbles.asm68
-rwxr-xr-xengine/overworld/healing_machine.asm102
-rwxr-xr-xengine/overworld/hidden_items.asm168
-rwxr-xr-xengine/overworld/hidden_objects.asm129
-rwxr-xr-xengine/overworld/ledges.asm87
-rwxr-xr-xengine/overworld/map_sprites.asm440
-rwxr-xr-xengine/overworld/npc_movement.asm291
-rwxr-xr-xengine/overworld/oaks_aide.asm71
-rwxr-xr-xengine/overworld/pewter_guys.asm101
-rwxr-xr-xengine/overworld/player_animations.asm520
-rwxr-xr-xengine/overworld/pokecenter.asm68
-rwxr-xr-xengine/overworld/pokemart.asm256
-rwxr-xr-xengine/overworld/saffron_guards.asm18
-rwxr-xr-xengine/overworld/ssanne.asm88
-rwxr-xr-xengine/overworld/trainers.asm347
22 files changed, 3647 insertions, 0 deletions
diff --git a/engine/overworld/cable_club_npc.asm b/engine/overworld/cable_club_npc.asm
new file mode 100755
index 00000000..88bf177f
--- /dev/null
+++ b/engine/overworld/cable_club_npc.asm
@@ -0,0 +1,156 @@
+CableClubNPC: ; 71c5 (1:71c5)
+ ld hl, CableClubNPCText1
+ call PrintText
+ ld a, [$d74b]
+ bit 5, a
+ jp nz, Func_71e1
+ ld c, $3c
+ call DelayFrames
+ ld hl, CableClubNPCText6
+ call PrintText
+ jp Func_7298
+
+Func_71e1: ; 71e1 (1:71e1)
+ ld a, $1
+ ld [$cc34], a
+ ld a, $5a
+ ld [$cc47], a
+.asm_71eb
+ ld a, [$ffaa]
+ cp $2
+ jr z, .asm_721a ; 0x71ef $29
+ cp $1
+ jr z, .asm_721a ; 0x71f3 $25
+ ld a, $ff
+ ld [$ffaa], a
+ ld a, $2
+ ld [$ff01], a
+ xor a
+ ld [$ffad], a
+ ld a, $80
+ ld [$ff02], a
+ ld a, [$cc47]
+ dec a
+ ld [$cc47], a
+ jr z, .asm_7287 ; 0x720b $7a
+ ld a, $1
+ ld [$ff01], a
+ ld a, $81
+ ld [$ff02], a
+ call DelayFrame
+ jr .asm_71eb ; 0x7218 $d1
+.asm_721a
+ call Func_22ed
+ call DelayFrame
+ call Func_22ed
+ ld c, $32
+ call DelayFrames
+ ld hl, CableClubNPCText2
+ call PrintText
+ xor a
+ ld [$cc34], a
+ call YesNoChoice
+ ld a, $1
+ ld [$cc34], a
+ ld a, [$cc26]
+ and a
+ jr nz, .asm_728f ; 0x723e $4f
+ callab SaveSAVtoSRAM
+ call WaitForSoundToFinish
+ ld a, (SFX_02_5d - SFX_Headers_02) / 3
+ call PlaySoundWaitForCurrent
+ ld hl, CableClubNPCText3
+ call PrintText
+ ld hl, $cc47
+ ld a, $3
+ ld [hli], a
+ xor a
+ ld [hl], a
+ ld [$ffa9], a
+ ld [$cc42], a
+ call Func_227f
+ ld hl, $cc47
+ ld a, [hli]
+ inc a
+ jr nz, Func_72a8 ; 0x726b $3b
+ ld a, [hl]
+ inc a
+ jr nz, Func_72a8 ; 0x726f $37
+ ld b, $a
+.asm_7273
+ call DelayFrame
+ call Func_22ed
+ dec b
+ jr nz, .asm_7273 ; 0x727a $f7
+ call Func_72d7
+ ld hl, CableClubNPCText4
+ call PrintText
+ jr Func_7298 ; 0x7285 $11
+.asm_7287
+ ld hl, CableClubNPCText7
+ call PrintText
+ jr Func_7298 ; 0x728d $9
+.asm_728f
+ call Func_72d7
+ ld hl, CableClubNPCText5
+ call PrintText
+ ; fall through
+
+Func_7298: ; 7298 (1:7298)
+ xor a
+ ld hl, $cc47
+ ld [hli], a
+ ld [hl], a
+ ld hl, $d72e
+ res 6, [hl]
+ xor a
+ ld [$cc34], a
+ ret
+
+Func_72a8: ; 72a8 (1:72a8)
+ xor a
+ ld [hld], a
+ ld [hl], a
+ ld hl, LinkMenu
+ ld b, BANK(LinkMenu)
+ jp Bankswitch
+
+CableClubNPCText7: ; 72b3 (1:72b3)
+ TX_FAR _CableClubNPCText7
+ db "@"
+
+CableClubNPCText1: ; 72b8 (1:72b8)
+ TX_FAR _CableClubNPCText1
+ db "@"
+
+CableClubNPCText2: ; 72bd (1:72bd)
+ TX_FAR _CableClubNPCText2
+ db "@"
+
+CableClubNPCText3: ; 72c2 (1:72c2)
+ TX_FAR _CableClubNPCText3
+ db $a, "@"
+
+CableClubNPCText4: ; 72c8 (1:72c8)
+ TX_FAR _CableClubNPCText4
+ db "@"
+
+CableClubNPCText5: ; 72cd (1:72cd)
+ TX_FAR _CableClubNPCText5
+ db "@"
+
+CableClubNPCText6: ; 72d2 (1:72d2)
+ TX_FAR _CableClubNPCText6
+ db "@"
+
+Func_72d7: ; 72d7 (1:72d7)
+ call Delay3
+ ld a, $ff
+ ld [$ffaa], a
+ ld a, $2
+ ld [$ff01], a
+ xor a
+ ld [$ffad], a
+ ld a, $80
+ ld [$ff02], a
+ ret
diff --git a/engine/overworld/card_key.asm b/engine/overworld/card_key.asm
new file mode 100755
index 00000000..658f4712
--- /dev/null
+++ b/engine/overworld/card_key.asm
@@ -0,0 +1,108 @@
+PrintCardKeyText: ; 52673 (14:6673)
+ ld hl, SilphCoMapList
+ ld a, [W_CURMAP]
+ ld b, a
+.asm_5267a
+ ld a, [hli]
+ cp $ff
+ ret z
+ cp b
+ jr nz, .asm_5267a
+ ld a, $35
+ call Predef ; indirect jump to Func_c586 (c586 (3:4586))
+ ld a, [$cfc6]
+ cp $18
+ jr z, .asm_5269c
+ cp $24
+ jr z, .asm_5269c
+ ld b, a
+ ld a, [W_CURMAP]
+ cp SILPH_CO_11F
+ ret nz
+ ld a, b
+ cp $5e
+ ret nz
+.asm_5269c
+ ld b, CARD_KEY
+ call IsItemInBag
+ jr z, .asm_526dc
+ call Func_526fd
+ push de
+ ld a, $1
+ ld [H_DOWNARROWBLINKCNT2], a ; $ff8c
+ call PrintPredefTextID
+ pop de
+ srl d
+ ld a, d
+ ld b, a
+ ld [$d73f], a
+ srl e
+ ld a, e
+ ld c, a
+ ld [$d740], a
+ ld a, [W_CURMAP] ; $d35e
+ cp SILPH_CO_11F
+ jr nz, .asm_526c8
+ ld a, $3
+ jr .asm_526ca
+.asm_526c8
+ ld a, $e
+.asm_526ca
+ ld [$d09f], a
+ ld a, $17
+ call Predef ; indirect jump to Func_ee9e
+ ld hl, $d126
+ set 5, [hl]
+ ld a, (SFX_1f_57 - SFX_Headers_1f) / 3
+ jp PlaySound
+.asm_526dc
+ ld a, $2
+ ld [H_DOWNARROWBLINKCNT2], a ; $ff8c
+ jp PrintPredefTextID
+
+SilphCoMapList: ; 526e3 (14:66e3)
+ db SILPH_CO_2F
+ db SILPH_CO_3F
+ db SILPH_CO_4F
+ db SILPH_CO_5F
+ db SILPH_CO_6F
+ db SILPH_CO_7F
+ db SILPH_CO_8F
+ db SILPH_CO_9F
+ db SILPH_CO_10F
+ db SILPH_CO_11F
+ db $FF
+
+CardKeySuccessText: ; 526ee (14:66ee)
+ TX_FAR _CardKeySuccessText1
+ db $0b
+ TX_FAR _CardKeySuccessText2
+ db "@"
+
+CardKeyFailText: ; 526f8 (14:66f8)
+ TX_FAR _CardKeyFailText
+ db "@"
+
+Func_526fd: ; 526fd (14:66fd)
+ ld a, [W_YCOORD] ; $d361
+ ld d, a
+ ld a, [W_XCOORD] ; $d362
+ ld e, a
+ ld a, [$c109]
+ and a
+ jr nz, .asm_5270d
+ inc d
+ ret
+.asm_5270d
+ cp $4
+ jr nz, .asm_52713
+ dec d
+ ret
+.asm_52713
+ cp $8
+ jr nz, .asm_52719
+ dec e
+ ret
+.asm_52719
+ inc e
+ ret
diff --git a/engine/overworld/cinnabar_lab.asm b/engine/overworld/cinnabar_lab.asm
new file mode 100755
index 00000000..4087b334
--- /dev/null
+++ b/engine/overworld/cinnabar_lab.asm
@@ -0,0 +1,125 @@
+GiveFossilToCinnabarLab: ; 61006 (18:5006)
+ ld hl, $d730
+ set 6, [hl]
+ xor a
+ ld [wCurrentMenuItem], a ; $cc26
+ ld a, $3
+ ld [wMenuWatchedKeys], a ; $cc29
+ ld a, [$cd37]
+ dec a
+ ld [wMaxMenuItem], a ; $cc28
+ ld a, $2
+ ld [wTopMenuItemY], a ; $cc24
+ ld a, $1
+ ld [wTopMenuItemX], a ; $cc25
+ ld a, [$cd37]
+ dec a
+ ld bc, $2
+ ld hl, $3
+ call AddNTimes
+ dec l
+ ld b, l
+ ld c, $d
+ ld hl, wTileMap
+ call TextBoxBorder
+ call UpdateSprites
+ call Func_610c2
+ ld hl, $d730
+ res 6, [hl]
+ call HandleMenuInput
+ bit 1, a
+ jr nz, .asm_610a7
+ ld hl, $cc5b
+ ld a, [wCurrentMenuItem] ; $cc26
+ ld d, $0
+ ld e, a
+ add hl, de
+ ld a, [hl]
+ ld [$ffdb], a
+ cp DOME_FOSSIL
+ jr z, .choseDomeFossil
+ cp HELIX_FOSSIL
+ jr z, .choseHelixFossil
+ ld b, AERODACTYL
+ jr .fossilSelected
+.choseHelixFossil
+ ld b, OMANYTE
+ jr .fossilSelected
+.choseDomeFossil
+ ld b, KABUTO
+.fossilSelected
+ ld [W_FOSSILITEM], a
+ ld a, b
+ ld [W_FOSSILMON], a
+ call LoadFossilItemAndMonName
+ ld hl, LabFossil_610ae
+ call PrintText
+ call YesNoChoice
+ ld a, [wCurrentMenuItem] ; $cc26
+ and a
+ jr nz, .asm_610a7
+ ld hl, LabFossil_610b3
+ call PrintText
+ ld a, [W_FOSSILITEM]
+ ld [$ffdb], a
+ callba RemoveItemByID
+ ld hl, LabFossil_610b8
+ call PrintText
+ ld hl, $d7a3
+ set 0, [hl]
+ set 1, [hl]
+ ret
+.asm_610a7
+ ld hl, LabFossil_610bd
+ call PrintText
+ ret
+
+LabFossil_610ae: ; 610ae (18:50ae)
+ TX_FAR _Lab4Text_610ae
+ db "@"
+
+LabFossil_610b3: ; 610b3 (18:50b3)
+ TX_FAR _Lab4Text_610b3
+ db "@"
+
+LabFossil_610b8: ; 610b8 (18:50b8)
+ TX_FAR _Lab4Text_610b8
+ db "@"
+
+LabFossil_610bd: ; 610bd (18:50bd)
+ TX_FAR _Lab4Text_610bd
+ db "@"
+
+Func_610c2: ; 610c2 (18:50c2)
+ ld hl, $cc5b
+ xor a
+ ld [$ffdb], a
+.asm_610c8
+ ld a, [hli]
+ cp $ff
+ ret z
+ push hl
+ ld [$d11e], a
+ call GetItemName
+ FuncCoord 2, 2 ; $c3ca
+ ld hl, Coord
+ ld a, [$ffdb]
+ ld bc, $28
+ call AddNTimes
+ ld de, $cd6d
+ call PlaceString
+ ld hl, $ffdb
+ inc [hl]
+ pop hl
+ jr .asm_610c8
+
+; loads the names of the fossil item and the resulting mon
+LoadFossilItemAndMonName: ; 610eb (18:50eb)
+ ld a, [W_FOSSILMON]
+ ld [$d11e], a
+ call GetMonName
+ call CopyStringToCF4B
+ ld a, [W_FOSSILITEM]
+ ld [$d11e], a
+ call GetItemName
+ ret
diff --git a/engine/overworld/cut.asm b/engine/overworld/cut.asm
new file mode 100755
index 00000000..6c888e7f
--- /dev/null
+++ b/engine/overworld/cut.asm
@@ -0,0 +1,258 @@
+UsedCut: ; ef54 (3:6f54)
+ xor a
+ ld [$cd6a], a
+ ld a, [W_CURMAPTILESET] ; $d367
+ and a ; OVERWORLD
+ jr z, .asm_ef6b
+ cp GYM
+ jr nz, .asm_ef77
+ ld a, [$cfc6]
+ cp $50 ; gym cut tree
+ jr nz, .asm_ef77
+ jr asm_ef82
+.asm_ef6b
+ dec a
+ ld a, [$cfc6]
+ cp $3d ; cut tree
+ jr z, asm_ef82
+ cp $52 ; grass
+ jr z, asm_ef82
+.asm_ef77
+ ld hl, NothingToCutText
+ jp PrintText
+
+NothingToCutText: ; ef7d (3:6f7d)
+ TX_FAR _NothingToCutText
+ db "@"
+
+asm_ef82: ; ef82 (3:6f82)
+ ld [$cd4d], a
+ ld a, $1
+ ld [$cd6a], a
+ ld a, [wWhichPokemon] ; $cf92
+ ld hl, W_PARTYMON1NAME ; $d2b5
+ call GetPartyMonName
+ ld hl, $d730
+ set 6, [hl]
+ call GBPalWhiteOutWithDelay3
+ call CleanLCD_OAM
+ call Func_3dbe
+ ld a, $90
+ ld [$ffb0], a
+ call Delay3
+ call LoadGBPal
+ call LoadCurrentMapView
+ call SaveScreenTilesToBuffer2
+ call Delay3
+ xor a
+ ld [$ffb0], a
+ ld hl, UsedCutText
+ call PrintText
+ call LoadScreenTilesFromBuffer2
+ ld hl, $d730
+ res 6, [hl]
+ ld a, $ff
+ ld [$cfcb], a
+ call AnimateCutTree
+ ld de, CutTreeBlockSwaps ; $7100
+ call Func_f09f
+ call Func_eedc
+ callba Func_79e96
+ ld a, $1
+ ld [$cfcb], a
+ ld a, (SFX_02_56 - SFX_Headers_02) / 3
+ call PlaySound
+ ld a, $90
+ ld [$ffb0], a
+ call UpdateSprites
+ jp Func_eedc
+
+UsedCutText: ; eff2 (3:6ff2)
+ TX_FAR _UsedCutText
+ db "@"
+
+AnimateCutTree: ; eff7 (3:6ff7)
+ xor a
+ ld [$cd50], a
+ ld a, $e4
+ ld [rOBP1], a ; $ff49
+ ld a, [$cd4d]
+ cp $52
+ jr z, .asm_f020
+ ld de, Overworld_GFX + $2d0 ; $42d0 ; cuttable tree sprite top row
+ ld hl, $8fc0
+ ld bc, (BANK(Overworld_GFX) << 8) + $02
+ call CopyVideoData
+ ld de, Overworld_GFX + $3d0 ; $43d0 ; cuttable tree sprite bottom row
+ ld hl, $8fe0
+ ld bc, (BANK(Overworld_GFX) << 8) + $02
+ call CopyVideoData
+ jr asm_f055
+.asm_f020
+ ld hl, $8fc0
+ call LoadCutTreeOAM
+ ld hl, $8fd0
+ call LoadCutTreeOAM
+ ld hl, $8fe0
+ call LoadCutTreeOAM
+ ld hl, $8ff0
+ call LoadCutTreeOAM
+ call asm_f055
+ ld hl, $c393
+ ld de, $4
+ ld a, $30
+ ld c, e
+.asm_f044
+ ld [hl], a
+ add hl, de
+ xor $60
+ dec c
+ jr nz, .asm_f044
+ ret
+
+LoadCutTreeOAM: ; f04c (3:704c)
+ ld de, AnimationTileset2 + $60 ; $474e ; tile depicting a leaf
+ ld bc, (BANK(AnimationTileset2) << 8) + $01
+ jp CopyVideoData
+asm_f055: ; f055 (3:7055)
+ call Func_f068
+ ld a, $9
+ ld de, CutTreeOAM ; $7060
+ jp WriteOAMBlock
+
+CutTreeOAM: ; f060 (3:7060)
+ db $FC,$10,$FD,$10
+ db $FE,$10,$FF,$10
+
+Func_f068: ; f068 (3:7068)
+ ld hl, $c104
+ ld a, [hli]
+ ld b, a
+ inc hl
+ ld a, [hli]
+ ld c, a ; bc holds ypos/xpos of player's sprite
+ inc hl
+ inc hl
+ ld a, [hl] ; a holds direction of player (00: down, 04: up, 08: left, 0C: right)
+ srl a
+ ld e, a
+ ld d, $0 ; de holds direction (00: down, 02: up, 04: left, 06: right)
+ ld a, [$cd50]
+ and a
+ ld hl, CutTreeAnimationOffsets ; $708f
+ jr z, .asm_f084
+ ld hl, CutTreeAnimationOffsets2 ; $7097
+.asm_f084
+ add hl, de
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ld a, b
+ add d
+ ld b, a
+ ld a, c
+ add e
+ ld c, a
+ ret
+
+CutTreeAnimationOffsets: ; f08f (3:708f)
+; Each pair represents the x and y pixels offsets from the player of where the cut tree animation should be drawn
+ db 8, 36 ; player is facing down
+ db 8, 4 ; player is facing up
+ db -8, 20 ; player is facing left
+ db 24, 20 ; player is facing right
+
+CutTreeAnimationOffsets2: ; f097 (3:7097)
+; Not sure if these ever get used. CutTreeAnimationOffsets only seems to be used.
+; Each pair represents the x and y pixels offsets from the player of where the cut tree animation should be drawn
+; These offsets represent 2 blocks away from the player
+ db 8, 52 ; player is facing down
+ db 8, -12 ; player is facing up
+ db -24, 20 ; player is facing left
+ db 40, 20 ; player is facing right
+
+Func_f09f: ; f09f (3:709f)
+ push de
+ ld a, [W_CURMAPWIDTH] ; $d369
+ add $6
+ ld c, a
+ ld b, $0
+ ld d, $0
+ ld hl, $d35f
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ add hl, bc
+ ld a, [$c109]
+ and a
+ jr z, .asm_f0c7
+ cp $4
+ jr z, .asm_f0cf
+ cp $8
+ jr z, .asm_f0d7
+ ld a, [W_XBLOCKCOORD] ; $d364
+ and a
+ jr z, .asm_f0e0
+ jr .asm_f0ec
+.asm_f0c7
+ ld a, [W_YBLOCKCOORD] ; $d363
+ and a
+ jr z, .asm_f0e0
+ jr .asm_f0df
+.asm_f0cf
+ ld a, [W_YBLOCKCOORD] ; $d363
+ and a
+ jr z, .asm_f0e1
+ jr .asm_f0e0
+.asm_f0d7
+ ld a, [W_XBLOCKCOORD] ; $d364
+ and a
+ jr z, .asm_f0e6
+ jr .asm_f0e0
+.asm_f0df
+ add hl, bc
+.asm_f0e0
+ add hl, bc
+.asm_f0e1
+ ld e, $2
+ add hl, de
+ jr .asm_f0f0
+.asm_f0e6
+ ld e, $1
+ add hl, bc
+ add hl, de
+ jr .asm_f0f0
+.asm_f0ec
+ ld e, $3
+ add hl, bc
+ add hl, de
+.asm_f0f0
+ pop de
+ ld a, [hl]
+ ld c, a
+.asm_f0f3
+ ld a, [de]
+ inc de
+ inc de
+ cp $ff
+ ret z
+ cp c
+ jr nz, .asm_f0f3
+ dec de
+ ld a, [de]
+ ld [hl], a
+ ret
+
+CutTreeBlockSwaps: ; f100 (3:7100)
+; first byte = tileset block containing the cut tree
+; second byte = corresponding tileset block after the cut animation happens
+ db $32, $6D
+ db $33, $6C
+ db $34, $6F
+ db $35, $4C
+ db $60, $6E
+ db $0B, $0A
+ db $3C, $35
+ db $3F, $35
+ db $3D, $36
+ db $FF ; list terminator
diff --git a/engine/overworld/cut2.asm b/engine/overworld/cut2.asm
new file mode 100755
index 00000000..c83e571b
--- /dev/null
+++ b/engine/overworld/cut2.asm
@@ -0,0 +1,89 @@
+Func_79e96: ; 79e96 (1e:5e96)
+ ld a, [$cd4d]
+ cp $52
+ jr z, .asm_79ec8
+ ld c, $8
+.asm_79e9f
+ push bc
+ ld hl, $c391
+ ld a, $1
+ ld [$d08a], a
+ ld c, $2
+ call Func_79339
+ ld hl, $c399
+ ld a, $ff
+ ld [$d08a], a
+ ld c, $2
+ call Func_79339
+ ld a, [rOBP1] ; $ff49
+ xor $64
+ ld [rOBP1], a ; $ff49
+ call DelayFrame
+ pop bc
+ dec c
+ jr nz, .asm_79e9f
+ ret
+.asm_79ec8
+ ld c, $2
+.asm_79eca
+ push bc
+ ld c, $8
+ call Func_79eed
+ call Func_79f30
+ ld c, $8
+ call Func_79eed
+ call Func_79f30
+ ld hl, $c390
+ ld a, $2
+ ld [$d08a], a
+ ld c, $4
+ call Func_79352
+ pop bc
+ dec c
+ jr nz, .asm_79eca
+ ret
+
+Func_79eed: ; 79eed (1e:5eed)
+ push bc
+ ld hl, $c391
+ ld a, $1
+ ld [$d08a], a
+ ld c, $1
+ call Func_79339
+ ld hl, $c395
+ ld a, $2
+ ld [$d08a], a
+ ld c, $1
+ call Func_79339
+ ld hl, $c399
+ ld a, $fe
+ ld [$d08a], a
+ ld c, $1
+ call Func_79339
+ ld hl, $c39d
+ ld a, $ff
+ ld [$d08a], a
+ ld c, $1
+ call Func_79339
+ ld a, [rOBP1] ; $ff49
+ xor $64
+ ld [rOBP1], a ; $ff49
+ call DelayFrame
+ pop bc
+ dec c
+ jr nz, Func_79eed
+ ret
+
+Func_79f30: ; 79f30 (1e:5f30)
+ ld hl, $c390
+ ld de, $cee9
+ ld bc, $8
+ call CopyData
+ ld hl, $c398
+ ld de, $c390
+ ld bc, $8
+ call CopyData
+ ld hl, $cee9
+ ld de, $c398
+ ld bc, $8
+ jp CopyData
diff --git a/engine/overworld/doors.asm b/engine/overworld/doors.asm
new file mode 100755
index 00000000..ff58b752
--- /dev/null
+++ b/engine/overworld/doors.asm
@@ -0,0 +1,88 @@
+HandleDoors: ; 1a609 (6:6609)
+ push de
+ ld hl, DoorTileIDPointers ; $662c
+ ld a, [W_CURMAPTILESET] ; $d367
+ ld de, $3
+ call IsInArray
+ pop de
+ jr nc, .asm_1a62a
+ inc hl
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ FuncCoord 8, 9 ; $c45c
+ ld a, [Coord]
+ ld b, a
+.asm_1a621
+ ld a, [hli]
+ and a
+ jr z, .asm_1a62a
+ cp b
+ jr nz, .asm_1a621
+ scf
+ ret
+.asm_1a62a
+ and a
+ ret
+
+DoorTileIDPointers: ; 1a62c (6:662c)
+ db OVERWORLD
+ dw OverworldDoorTileIDs
+ db FOREST
+ dw ForestDoorTileIDs
+ db MART
+ dw MartDoorTileIDs
+ db HOUSE
+ dw HouseDoorTileIDs
+ db FOREST_GATE
+ dw TilesetMuseumDoorTileIDs
+ db MUSEUM
+ dw TilesetMuseumDoorTileIDs
+ db GATE
+ dw TilesetMuseumDoorTileIDs
+ db SHIP
+ dw ShipDoorTileIDs
+ db LOBBY
+ dw LobbyDoorTileIDs
+ db MANSION
+ dw MansionDoorTileIDs
+ db LAB
+ dw LabDoorTileIDs
+ db FACILITY
+ dw FacilityDoorTileIDs
+ db PLATEAU
+ dw PlateauDoorTileIDs
+ db $ff
+
+OverworldDoorTileIDs: ; 1a654 (6:6654)
+ db $1B,$58,$00
+
+ForestDoorTileIDs: ; 1a657 (6:6657)
+ db $3a,$00
+
+MartDoorTileIDs: ; 1a659 (6:6659)
+ db $5e,$00
+
+HouseDoorTileIDs: ; 1a65b (6:665b)
+ db $54,$00
+
+TilesetMuseumDoorTileIDs: ; 1a65d (6:665d)
+ db $3b,$00
+
+ShipDoorTileIDs: ; 1a65f (6:665f)
+ db $1e,$00
+
+LobbyDoorTileIDs: ; 1a661 (6:6661)
+ db $1c,$38,$1a,$00
+
+MansionDoorTileIDs: ; 1a665 (6:6665)
+ db $1a,$1c,$53,$00
+
+LabDoorTileIDs: ; 1a669 (6:6669)
+ db $34,$00
+
+FacilityDoorTileIDs: ; 1a66b (6:666b)
+ db $43,$58,$1b,$00
+
+PlateauDoorTileIDs: ; 1a66f (6:666f)
+ db $3b,$1b,$00
diff --git a/engine/overworld/elevator.asm b/engine/overworld/elevator.asm
new file mode 100755
index 00000000..e483e0c3
--- /dev/null
+++ b/engine/overworld/elevator.asm
@@ -0,0 +1,69 @@
+ShakeElevator: ; 7bf15 (1e:7f15)
+ ld de, $ffe0
+ call Func_7bf64
+ ld de, $240
+ call Func_7bf64
+ call Delay3
+ ld a, $ff
+ call PlaySound
+ ld a, [$ffaf]
+ ld d, a
+ ld e, $1
+ ; number of times to play collision sfx
+ ld b, $64
+.asm_7bf30
+ ld a, e
+ xor $fe
+ ld e, a
+ add d
+ ld [$ffaf], a
+ push bc
+ ld c, BANK(SFX_02_5b)
+ ld a, (SFX_02_5b - SFX_Headers_02) / 3
+ call PlayMusic
+ pop bc
+ ld c, $2
+ call DelayFrames
+ dec b
+ jr nz, .asm_7bf30
+ ld a, d
+ ld [$ffaf], a
+ ld a, $ff
+ call PlaySound
+ ld c, BANK(SFX_02_5f)
+ ld a, (SFX_02_5f - SFX_Headers_02) / 3
+ call PlayMusic
+.asm_7bf57
+ ld a, [$c02a]
+ cp $b9
+ jr z, .asm_7bf57
+ call UpdateSprites
+ jp Func_2307
+
+Func_7bf64: ; 7bf64 (1e:7f64)
+ ld hl, $d527
+ ld a, [hld]
+ push af
+ ld a, [hl]
+ push af
+ push hl
+ push hl
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ add hl, de
+ ld a, h
+ and $3
+ or $98
+ ld d, a
+ ld a, l
+ pop hl
+ ld [hli], a
+ ld [hl], d
+ call ScheduleNorthRowRedraw
+ pop hl
+ pop af
+ ld [hli], a
+ pop af
+ ld [hl], a
+ jp Delay3
diff --git a/engine/overworld/emotion_bubbles.asm b/engine/overworld/emotion_bubbles.asm
new file mode 100755
index 00000000..b480c06d
--- /dev/null
+++ b/engine/overworld/emotion_bubbles.asm
@@ -0,0 +1,68 @@
+PrintEmotionBubble: ; 17c47 (5:7c47)
+ ld a, [$cd50]
+ ld c, a
+ ld b, $0
+ ld hl, EmotionBubblesPointerTable ; $7caf
+ add hl, bc
+ add hl, bc
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ld hl, $8f80
+ ld bc, (BANK(EmotionBubblesPointerTable) << 8) + $04
+ call CopyVideoData
+ ld a, [$cfcb]
+ push af
+ ld a, $ff
+ ld [$cfcb], a
+ ld a, [$d736]
+ bit 6, a
+ ld hl, $c38f
+ ld de, $c39f
+ jr z, .asm_17c7a
+ ld hl, $c37f
+ ld de, $c38f
+.asm_17c7a
+ ld bc, $90
+.asm_17c7d
+ ld a, [hl]
+ ld [de], a
+ dec hl
+ dec de
+ dec bc
+ ld a, c
+ or b
+ jr nz, .asm_17c7d
+ ld hl, $c104
+ ld a, [$cd4f]
+ swap a
+ ld c, a
+ ld b, $0
+ add hl, bc
+ ld a, [hli]
+ ld b, a
+ inc hl
+ ld a, [hl]
+ add $8
+ ld c, a
+ ld de, EmotionBubblesOAM ; $7cb5
+ xor a
+ call WriteOAMBlock
+ ld c, $3c
+ call DelayFrames
+ pop af
+ ld [$cfcb], a
+ call DelayFrame
+ jp UpdateSprites
+
+EmotionBubblesPointerTable: ; 17caf (5:7caf)
+ dw EmotionBubbles
+ dw EmotionBubbles + $40
+ dw EmotionBubbles + $80
+
+EmotionBubblesOAM: ; 17cb5 (5:7cb5)
+ db $F8,$00,$F9,$00
+ db $FA,$00,$FB,$00
+
+EmotionBubbles: ; 17cbd (5:7cbd)
+ INCBIN "gfx/emotion_bubbles.w16.2bpp"
diff --git a/engine/overworld/healing_machine.asm b/engine/overworld/healing_machine.asm
new file mode 100755
index 00000000..77ff4ccc
--- /dev/null
+++ b/engine/overworld/healing_machine.asm
@@ -0,0 +1,102 @@
+AnimateHealingMachine: ; 70433 (1c:4433)
+ ld de, PokeCenterFlashingMonitorAndHealBall ; $44b7
+ ld hl, $87c0
+ ld bc, (BANK(PokeCenterFlashingMonitorAndHealBall) << 8) + $03
+ call CopyVideoData
+ ld hl, $cfcb
+ ld a, [hl]
+ push af
+ ld [hl], $ff
+ push hl
+ ld a, [rOBP1] ; $ff49
+ push af
+ ld a, $e0
+ ld [rOBP1], a ; $ff49
+ ld hl, $c384
+ ld de, PokeCenterOAMData ; $44d7
+ call Func_70503
+ ld a, $4
+ ld [wMusicHeaderPointer], a
+ ld a, $ff
+ ld [$c0ee], a
+ call PlaySound
+.asm_70464
+ ld a, [wMusicHeaderPointer]
+ and a
+ jr nz, .asm_70464
+ ld a, [W_NUMINPARTY] ; $d163
+ ld b, a
+.asm_7046e
+ call Func_70503
+ ld a, (SFX_02_4a - SFX_Headers_02) / 3
+ call PlaySound
+ ld c, $1e
+ call DelayFrames
+ dec b
+ jr nz, .asm_7046e
+ ld a, [$c0ef]
+ cp $1f
+ ld [$c0f0], a
+ jr nz, .asm_70495
+ ld a, $ff
+ ld [$c0ee], a
+ call PlaySound
+ ld a, Bank(Func_9876)
+ ld [$c0ef], a
+.asm_70495
+ ld a, MUSIC_PKMN_HEALED
+ ld [$c0ee], a
+ call PlaySound
+ ld d, $28
+ call Func_704f3
+.asm_704a2
+ ld a, [$c026]
+ cp MUSIC_PKMN_HEALED
+ jr z, .asm_704a2
+ ld c, $20
+ call DelayFrames
+ pop af
+ ld [rOBP1], a ; $ff49
+ pop hl
+ pop af
+ ld [hl], a
+ jp UpdateSprites
+
+PokeCenterFlashingMonitorAndHealBall: ; 704b7 (1c:44b7)
+ INCBIN "gfx/pokecenter_ball.2bpp"
+
+PokeCenterOAMData: ; 704d7 (1c:44d7)
+ db $24,$34,$7C,$10 ; heal machine monitor
+ db $2B,$30,$7D,$10 ; pokeballs 1-6
+ db $2B,$38,$7D,$30
+ db $30,$30,$7D,$10
+ db $30,$38,$7D,$30
+ db $35,$30,$7D,$10
+ db $35,$38,$7D,$30
+
+Func_704f3: ; 704f3 (1c:44f3)
+ ld b, $8
+.asm_704f5
+ ld a, [rOBP1] ; $ff49
+ xor d
+ ld [rOBP1], a ; $ff49
+ ld c, $a
+ call DelayFrames
+ dec b
+ jr nz, .asm_704f5
+ ret
+
+Func_70503: ; 70503 (1c:4503)
+ ld a, [de]
+ inc de
+ ld [hli], a
+ ld a, [de]
+ inc de
+ ld [hli], a
+ ld a, [de]
+ inc de
+ ld [hli], a
+ ld a, [de]
+ inc de
+ ld [hli], a
+ ret
diff --git a/engine/overworld/hidden_items.asm b/engine/overworld/hidden_items.asm
new file mode 100755
index 00000000..db6bf1cd
--- /dev/null
+++ b/engine/overworld/hidden_items.asm
@@ -0,0 +1,168 @@
+HiddenItems: ; 76688 (1d:6688)
+ ld hl, HiddenItemCoords
+ call Func_76857
+ ld [$cd41], a
+ ld hl, $d6f0
+ ld a, [$cd41]
+ ld c, a
+ ld b, $2
+ ld a, $10
+ call Predef
+ ld a, c
+ and a
+ ret nz
+ call EnableAutoTextBoxDrawing
+ ld a, $1
+ ld [$cc3c], a
+ ld a, [$cd3d] ; item ID
+ ld [$d11e], a
+ call GetItemName
+ ld a, $24
+ jp PrintPredefTextID
+
+INCLUDE "data/hidden_item_coords.asm"
+
+FoundHiddenItemText: ; 7675b (1d:675b)
+; XXX where is the pointer to this?
+ TX_FAR _FoundHiddenItemText
+ db $8
+ ld a, [$cd3d] ; item ID
+ ld b, a
+ ld c, 1
+ call GiveItem
+ jr nc, .BagFull
+ ld hl, $d6f0
+ ld a, [$cd41]
+ ld c, a
+ ld b, $1
+ ld a, $10
+ call Predef
+ ld a, (SFX_02_3b - SFX_Headers_02) / 3
+ call PlaySoundWaitForCurrent ; play sound
+ call WaitForSoundToFinish ; wait for sound to finish playing
+ jp TextScriptEnd
+.BagFull
+ call WaitForTextScrollButtonPress ; wait for button press
+ xor a
+ ld [$cc3c], a
+ ld hl, HiddenItemBagFullText
+ call PrintText
+ jp TextScriptEnd
+
+HiddenItemBagFullText: ; 76794 (1d:6794)
+ TX_FAR _HiddenItemBagFullText
+ db "@"
+
+HiddenCoins: ; 76799 (1d:6799)
+ ld b, COIN_CASE
+ ld a, $1c
+ call Predef
+ ld a, b
+ and a
+ ret z
+ ld hl, HiddenCoinCoords
+ call Func_76857
+ ld [$cd41], a
+ ld hl, $d6fe
+ ld a, [$cd41]
+ ld c, a
+ ld b, $2
+ ld a, $10
+ call Predef
+ ld a, c
+ and a
+ ret nz
+ xor a
+ ld [$ff9f], a
+ ld [$ffa0], a
+ ld [$ffa1], a
+ ld a, [$cd3d]
+ sub COIN
+ cp 10
+ jr z, .bcd10
+ cp 20
+ jr z, .bcd20
+ cp 40
+ jr z, .bcd20
+ jr .bcd100
+.bcd10
+ ld a, $10
+ ld [$ffa1], a
+ jr .bcddone
+.bcd20
+ ld a, $20
+ ld [$ffa1], a
+ jr .bcddone
+.bcd40 ; due to a typo, this is never used
+ ld a, $40
+ ld [$ffa1], a
+ jr .bcddone
+.bcd100
+ ld a, $1
+ ld [$ffa0], a
+.bcddone
+ ld de, $d5a5
+ ld hl, $ffa1
+ ld c, $2
+ ld a, $b
+ call Predef
+ ld hl, $d6fe
+ ld a, [$cd41]
+ ld c, a
+ ld b, $1
+ ld a, $10
+ call Predef
+ call EnableAutoTextBoxDrawing
+ ld a, [wPlayerCoins]
+ cp $99
+ jr nz, .RoomInCoinCase
+ ld a, [wPlayerCoins + 1]
+ cp $99
+ jr nz, .RoomInCoinCase
+ ld a, $2c
+ jr .done
+.RoomInCoinCase
+ ld a, $2b
+.done
+ jp PrintPredefTextID
+
+INCLUDE "data/hidden_coins.asm"
+
+FoundHiddenCoinsText: ; 76847 (1d:6847)
+ TX_FAR _FoundHiddenCoinsText
+ db $10,"@"
+
+DroppedHiddenCoinsText: ; 7684d (1d:684d)
+ TX_FAR _FoundHiddenCoins2Text
+ db $10
+ TX_FAR _DroppedHiddenCoinsText
+ db "@"
+
+Func_76857: ; 76857 (1d:6857)
+ ld a, [$cd40]
+ ld d, a
+ ld a, [$cd41]
+ ld e, a
+ ld a, [W_CURMAP]
+ ld b, a
+ ld c, $ff
+.loop
+ inc c
+ ld a, [hli]
+ cp $ff ; end of the list?
+ ret z ; if so, we're done here
+ cp b
+ jr nz, .asm_76877 ; 0x7686b $a
+ ld a, [hli]
+ cp d
+ jr nz, .asm_76878 ; 0x7686f $7
+ ld a, [hli]
+ cp e
+ jr nz, .loop
+ ld a, c
+ ret
+.asm_76877
+ inc hl
+.asm_76878
+ inc hl
+ jr .loop
diff --git a/engine/overworld/hidden_objects.asm b/engine/overworld/hidden_objects.asm
new file mode 100755
index 00000000..e4777a84
--- /dev/null
+++ b/engine/overworld/hidden_objects.asm
@@ -0,0 +1,129 @@
+Func_46981: ; 46981 (11:6981)
+ xor a
+ ld [$d71e], a
+ ld a, [$d72d]
+ bit 4, a
+ ret nz
+ call ArePlayerCoordsInArray
+ ret nc
+ ld a, [wWhichTrade] ; $cd3d
+ ld [$d71e], a
+ ld hl, $d72d
+ set 4, [hl]
+ ld hl, $d732
+ set 4, [hl]
+ ret
+
+Func_469a0: ; 469a0 (11:69a0)
+ ld hl, $ffeb
+ xor a
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld [hl], a
+ ld de, $0
+ ld hl, HiddenObjectMaps ; $6a40
+.asm_469ae
+ ld a, [hli]
+ ld b, a
+ cp $ff
+ jr z, .asm_469fc
+ ld a, [W_CURMAP] ; $d35e
+ cp b
+ jr z, .asm_469be
+ inc de
+ inc de
+ jr .asm_469ae
+.asm_469be
+ ld hl, HiddenObjectPointers ; $6a96
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ push hl
+ ld hl, wWhichTrade ; $cd3d
+ xor a
+ ld [hli], a
+ ld [hli], a
+ ld [hl], a
+ pop hl
+.asm_469ce
+ ld a, [hli]
+ cp $ff
+ jr z, .asm_469fc
+ ld [$cd40], a
+ ld b, a
+ ld a, [hli]
+ ld [$cd41], a
+ ld c, a
+ call Func_46a01
+ ld a, [$ffea]
+ and a
+ jr z, .asm_469f0
+ inc hl
+ inc hl
+ inc hl
+ inc hl
+ push hl
+ ld hl, $cd3f
+ inc [hl]
+ pop hl
+ jr .asm_469ce
+.asm_469f0
+ ld a, [hli]
+ ld [wWhichTrade], a ; $cd3d
+ ld a, [hli]
+ ld [$cd3e], a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ret
+.asm_469fc
+ ld a, $ff
+ ld [$ffee], a
+ ret
+
+Func_46a01: ; 46a01 (11:6a01)
+ ld a, [$c109]
+ cp $4
+ jr z, .asm_46a16
+ cp $8
+ jr z, .asm_46a25
+ cp $c
+ jr z, .asm_46a2b
+ ld a, [W_YCOORD] ; $d361
+ inc a
+ jr .asm_46a1a
+.asm_46a16
+ ld a, [W_YCOORD] ; $d361
+ dec a
+.asm_46a1a
+ cp b
+ jr nz, .asm_46a3b
+ ld a, [W_XCOORD] ; $d362
+ cp c
+ jr nz, .asm_46a3b
+ jr .asm_46a38
+.asm_46a25
+ ld a, [W_XCOORD] ; $d362
+ dec a
+ jr .asm_46a2f
+.asm_46a2b
+ ld a, [W_XCOORD] ; $d362
+ inc a
+.asm_46a2f
+ cp c
+ jr nz, .asm_46a3b
+ ld a, [W_YCOORD] ; $d361
+ cp b
+ jr nz, .asm_46a3b
+.asm_46a38
+ xor a
+ jr .asm_46a3d
+.asm_46a3b
+ ld a, $ff
+.asm_46a3d
+ ld [$ffea], a
+ ret
+
+INCLUDE "data/hidden_objects.asm"
diff --git a/engine/overworld/ledges.asm b/engine/overworld/ledges.asm
new file mode 100755
index 00000000..d2f248cd
--- /dev/null
+++ b/engine/overworld/ledges.asm
@@ -0,0 +1,87 @@
+HandleLedges: ; 1a672 (6:6672)
+ ld a, [$d736]
+ bit 6, a
+ ret nz
+ ld a, [W_CURMAPTILESET] ; $d367
+ and a ; OVERWORLD
+ ret nz
+ ld a, $35
+ call Predef ; indirect jump to Func_c586 (c586 (3:4586))
+ ld a, [$c109]
+ ld b, a
+ FuncCoord 8, 9 ; $c45c
+ ld a, [Coord]
+ ld c, a
+ ld a, [$cfc6]
+ ld d, a
+ ld hl, LedgeTiles ; $66cf
+.asm_1a691
+ ld a, [hli]
+ cp $ff
+ ret z
+ cp b
+ jr nz, .asm_1a6a4
+ ld a, [hli]
+ cp c
+ jr nz, .asm_1a6a5
+ ld a, [hli]
+ cp d
+ jr nz, .asm_1a6a6
+ ld a, [hl]
+ ld e, a
+ jr .asm_1a6a9
+.asm_1a6a4
+ inc hl
+.asm_1a6a5
+ inc hl
+.asm_1a6a6
+ inc hl
+ jr .asm_1a691
+.asm_1a6a9
+ ld a, [H_CURRENTPRESSEDBUTTONS]
+ and e
+ ret z
+ ld a, $ff
+ ld [wJoypadForbiddenButtonsMask], a
+ ld hl, $d736
+ set 6, [hl]
+ call Func_3486
+ ld a, e
+ ld [$ccd3], a
+ ld [$ccd4], a
+ ld a, $2
+ ld [$cd38], a
+ call LoadHoppingShadowOAM
+ ld a, (SFX_02_4e - SFX_Headers_02) / 3
+ call PlaySound
+ ret
+
+ ; (player direction) (tile player standing on) (ledge tile) (input required)
+LedgeTiles: ; 1a6cf (6:66cf)
+ db $00,$2C,$37,$80
+ db $00,$39,$36,$80
+ db $00,$39,$37,$80
+ db $08,$2C,$27,$20
+ db $08,$39,$27,$20
+ db $0C,$2C,$0D,$10
+ db $0C,$2C,$1D,$10
+ db $0C,$39,$0D,$10
+ db $FF
+
+LoadHoppingShadowOAM: ; 1a6f0 (6:66f0)
+ ld hl, $8ff0
+ ld de, LedgeHoppingShadow ; $6708
+ ld bc, (BANK(LedgeHoppingShadow) << 8) + $01
+ call CopyVideoDataDouble
+ ld a, $9
+ ld bc, $5448 ; b, c = y, x coordinates of shadow
+ ld de, LedgeHoppingShadowOAM ; $6710
+ call WriteOAMBlock
+ ret
+
+LedgeHoppingShadow: ; 1a708 (6:6708)
+ INCBIN "gfx/ledge_hopping_shadow.1bpp"
+
+LedgeHoppingShadowOAM: ; 1a710 (6:6710)
+ db $FF,$10,$FF,$20
+ db $FF,$40,$FF,$60
diff --git a/engine/overworld/map_sprites.asm b/engine/overworld/map_sprites.asm
new file mode 100755
index 00000000..a734319d
--- /dev/null
+++ b/engine/overworld/map_sprites.asm
@@ -0,0 +1,440 @@
+; Loads tile patterns for map's sprites.
+; For outside maps, it loads one of several fixed sets of sprites.
+; For inside maps, it loads each sprite picture ID used in the map header.
+; This is also called after displaying text because loading
+; text tile patterns overwrites half of the sprite tile pattern data.
+; Note on notation:
+; $C1X* and $C2X* are used to denote $C100-$C1FF and $C200-$C2FF sprite slot
+; fields, respectively, within loops. The X is the loop index.
+; If there is an inner loop, Y is the inner loop index, i.e. $C1Y* and $C2Y*
+; denote fields of the sprite slots interated over in the inner loop.
+InitMapSprites: ; 1785b (5:785b)
+ call InitOutsideMapSprites
+ ret c ; return if the map is an outside map (already handled by above call)
+; if the map is an inside map (i.e. mapID >= $25)
+ ld hl,wSpriteStateData1
+ ld de,$c20d
+; Loop to copy picture ID's from $C1X0 to $C2XD for LoadMapSpriteTilePatterns.
+.copyPictureIDLoop
+ ld a,[hl] ; $C1X0 (picture ID)
+ ld [de],a ; $C2XD
+ ld a,$10
+ add e
+ ld e,a
+ ld a,$10
+ add l
+ ld l,a
+ jr nz,.copyPictureIDLoop
+
+; This is used for both inside and outside maps, since it is called by
+; InitOutsideMapSprites.
+; Loads tile pattern data for sprites into VRAM.
+LoadMapSpriteTilePatterns: ; 17871 (5:7871)
+ ld a,[W_NUMSPRITES]
+ and a ; are there any sprites?
+ jr nz,.spritesExist
+ ret
+.spritesExist
+ ld c,a ; c = [W_NUMSPRITES]
+ ld b,$10 ; number of sprite slots
+ ld hl,$c20d
+ xor a
+ ld [$ff8e],a ; 4-tile sprite counter
+.copyPictureIDLoop ; loop to copy picture ID from $C2XD to $C2XE
+ ld a,[hli] ; $C2XD (sprite picture ID)
+ ld [hld],a ; $C2XE
+ ld a,l
+ add a,$10
+ ld l,a
+ dec b
+ jr nz,.copyPictureIDLoop
+ ld hl,$c21e
+.loadTilePatternLoop
+ ld de,$c21d
+; Check if the current picture ID has already had its tile patterns loaded.
+; This done by looping through the previous sprite slots and seeing if any of
+; their picture ID's match that of the current sprite slot.
+.checkIfAlreadyLoadedLoop
+ ld a,e
+ and a,$f0
+ ld b,a ; b = offset of the wSpriteStateData2 sprite slot being checked against
+ ld a,l
+ and a,$f0 ; a = offset of current wSpriteStateData2 sprite slot
+ cp b ; done checking all previous sprite slots?
+ jr z,.notAlreadyLoaded
+ ld a,[de] ; picture ID of the wSpriteStateData2 sprite slot being checked against
+ cp [hl] ; do the picture ID's match?
+ jp z,.alreadyLoaded
+ ld a,e
+ add a,$10
+ ld e,a
+ jr .checkIfAlreadyLoadedLoop
+.notAlreadyLoaded
+ ld de,$c20e
+ ld b,$01
+; loop to find the highest tile pattern VRAM slot (among the first 10 slots) used by a previous sprite slot
+; this is done in order to find the first free VRAM slot available
+.findNextVRAMSlotLoop
+ ld a,e
+ add a,$10
+ ld e,a
+ ld a,l
+ cp e ; reached current slot?
+ jr z,.foundNextVRAMSlot
+ ld a,[de] ; $C2YE (VRAM slot)
+ cp a,11 ; is it one of the first 10 slots?
+ jr nc,.findNextVRAMSlotLoop
+ cp b ; compare the slot being checked to the current max
+ jr c,.findNextVRAMSlotLoop ; if the slot being checked is less than the current max
+; if the slot being checked is greater than or equal to the current max
+ ld b,a ; store new max VRAM slot
+ jr .findNextVRAMSlotLoop
+.foundNextVRAMSlot
+ inc b ; increment previous max value to get next VRAM tile pattern slot
+ ld a,b ; a = next VRAM tile pattern slot
+ push af
+ ld a,[hl] ; $C2XE (sprite picture ID)
+ ld b,a ; b = current sprite picture ID
+ cp a,SPRITE_BALL ; is it a 4-tile sprite?
+ jr c,.notFourTileSprite
+ pop af
+ ld a,[$ff8e] ; 4-tile sprite counter
+ add a,11
+ jr .storeVRAMSlot
+.notFourTileSprite
+ pop af
+.storeVRAMSlot
+ ld [hl],a ; store VRAM slot at $C2XE
+ ld [$ff8d],a ; used to determine if it's 4-tile sprite later
+ ld a,b ; a = current sprite picture ID
+ dec a
+ add a
+ add a
+ push bc
+ push hl
+ ld hl,SpriteSheetPointerTable
+ jr nc,.noCarry
+ inc h
+.noCarry
+ add l
+ ld l,a
+ jr nc,.noCarry2
+ inc h
+.noCarry2
+ push hl
+ call ReadSpriteSheetData
+ push af
+ push de
+ push bc
+ ld hl,$8000 ; VRAM base address
+ ld bc,$c0 ; number of bytes per VRAM slot
+ ld a,[$ff8d]
+ cp a,11 ; is it a 4-tile sprite?
+ jr nc,.fourTileSpriteVRAMAddr
+ ld d,a
+ dec d
+; Equivalent to multiplying $C0 (number of bytes in 12 tiles) times the VRAM
+; slot and adding the result to $8000 (the VRAM base address).
+.calculateVRAMAddrLoop
+ add hl,bc
+ dec d
+ jr nz,.calculateVRAMAddrLoop
+ jr .loadStillTilePattern
+.fourTileSpriteVRAMAddr
+ ld hl,$87c0 ; address for second 4-tile sprite
+ ld a,[$ff8e] ; 4-tile sprite counter
+ and a ; is it the first 4-tile sprite?
+ jr nz,.loadStillTilePattern
+; if it's the first 4-tile sprite
+ ld hl,$8780 ; address for first 4-tile sprite
+ inc a
+ ld [$ff8e],a ; 4-tile sprite counter
+.loadStillTilePattern
+ pop bc
+ pop de
+ pop af
+ push hl
+ push hl
+ ld h,d
+ ld l,e
+ pop de
+ ld b,a
+ ld a,[$cfc4]
+ bit 0,a ; reloading upper half of tile patterns after displaying text?
+ jr nz,.skipFirstLoad ; if so, skip loading data into the lower half
+ ld a,b
+ ld b,0
+ call FarCopyData2 ; load tile pattern data for sprite when standing still
+.skipFirstLoad
+ pop de
+ pop hl
+ ld a,[$ff8d]
+ cp a,11 ; is it a 4-tile sprite?
+ jr nc,.skipSecondLoad ; if so, there is no second block
+ push de
+ call ReadSpriteSheetData
+ push af
+ ld a,$c0
+ add e
+ ld e,a
+ jr nc,.noCarry3
+ inc d
+.noCarry3
+ ld a,[$cfc4]
+ bit 0,a ; reloading upper half of tile patterns after displaying text?
+ jr nz,.loadWhileLCDOn
+ pop af
+ pop hl
+ set 3,h ; add $800 to hl
+ push hl
+ ld h,d
+ ld l,e
+ pop de
+ call FarCopyData2 ; load tile pattern data for sprite when walking
+ jr .skipSecondLoad
+; When reloading the upper half of tile patterns after diplaying text, the LCD
+; will be on, so CopyVideoData (which writes to VRAM only during V-blank) must
+; be used instead of FarCopyData2.
+.loadWhileLCDOn
+ pop af
+ pop hl
+ set 3,h ; add $800 to hl
+ ld b,a
+ swap c
+ call CopyVideoData ; load tile pattern data for sprite when walking
+.skipSecondLoad
+ pop hl
+ pop bc
+ jr .nextSpriteSlot
+.alreadyLoaded ; if the current picture ID has already had its tile patterns loaded
+ inc de
+ ld a,[de] ; a = VRAM slot for the current picture ID (from $C2YE)
+ ld [hl],a ; store VRAM slot in current wSpriteStateData2 sprite slot (at $C2XE)
+.nextSpriteSlot
+ ld a,l
+ add a,$10
+ ld l,a
+ dec c
+ jp nz,.loadTilePatternLoop
+ ld hl,$c20d
+ ld b,$10
+; the pictures ID's stored at $C2XD are no longer needed, so zero them
+.zeroStoredPictureIDLoop
+ xor a
+ ld [hl],a ; $C2XD
+ ld a,$10
+ add l
+ ld l,a
+ dec b
+ jr nz,.zeroStoredPictureIDLoop
+ ret
+
+; reads data from SpriteSheetPointerTable
+; INPUT:
+; hl = address of sprite sheet entry
+; OUTPUT:
+; de = pointer to sprite sheet
+; bc = length in bytes
+; a = ROM bank
+ReadSpriteSheetData: ; 17971 (5:7971)
+ ld a,[hli]
+ ld e,a
+ ld a,[hli]
+ ld d,a
+ ld a,[hli]
+ ld c,a
+ xor a
+ ld b,a
+ ld a,[hli]
+ ret
+
+; Loads sprite set for outside maps (cities and routes) and sets VRAM slots.
+; sets carry if the map is a city or route, unsets carry if not
+InitOutsideMapSprites: ; 1797b (5:797b)
+ ld a,[W_CURMAP]
+ cp a,REDS_HOUSE_1F ; is the map a city or a route (map ID less than $25)?
+ ret nc ; if not, return
+ ld hl,MapSpriteSets
+ add l
+ ld l,a
+ jr nc,.noCarry
+ inc h
+.noCarry
+ ld a,[hl] ; a = spriteSetID
+ cp a,$f0 ; does the map have 2 sprite sets?
+ call nc,GetSplitMapSpriteSetID ; if so, choose the appropriate one
+ ld b,a ; b = spriteSetID
+ ld a,[$cfc4]
+ bit 0,a ; reloading upper half of tile patterns after displaying text?
+ jr nz,.loadSpriteSet ; if so, forcibly reload the sprite set
+ ld a,[W_SPRITESETID]
+ cp b ; has the sprite set ID changed?
+ jr z,.skipLoadingSpriteSet ; if not, don't load it again
+.loadSpriteSet
+ ld a,b
+ ld [W_SPRITESETID],a
+ dec a
+ ld b,a
+ sla a
+ ld c,a
+ sla a
+ sla a
+ add c
+ add b ; a = (spriteSetID - 1) * 11
+ ld de,SpriteSets
+; add a to de to get offset of sprite set
+ add e
+ ld e,a
+ jr nc,.noCarry2
+ inc d
+.noCarry2
+ ld hl,$c20d
+ ld a,SPRITE_RED
+ ld [hl],a
+ ld bc,W_SPRITESET
+; Load the sprite set into RAM.
+; This loop also fills $C2XD (sprite picture ID) where X is from $0 to $A
+; with picture ID's. This is done so that LoadMapSpriteTilePatterns will
+; load tile patterns for all sprite pictures in the sprite set.
+.loadSpriteSetLoop
+ ld a,$10
+ add l
+ ld l,a
+ ld a,[de] ; sprite picture ID from sprite set
+ ld [hl],a ; $C2XD (sprite picture ID)
+ ld [bc],a
+ inc de
+ inc bc
+ ld a,l
+ cp a,$bd ; reached 11th sprite slot?
+ jr nz,.loadSpriteSetLoop
+ ld b,4 ; 4 remaining sprite slots
+.zeroRemainingSlotsLoop ; loop to zero the picture ID's of the remaining sprite slots
+ ld a,$10
+ add l
+ ld l,a
+ xor a
+ ld [hl],a ; $C2XD (sprite picture ID)
+ dec b
+ jr nz,.zeroRemainingSlotsLoop
+ ld a,[W_NUMSPRITES]
+ push af ; save number of sprites
+ ld a,11 ; 11 sprites in sprite set
+ ld [W_NUMSPRITES],a
+ call LoadMapSpriteTilePatterns
+ pop af
+ ld [W_NUMSPRITES],a ; restore number of sprites
+ ld hl,$c21e
+ ld b,$0f
+; The VRAM tile pattern slots that LoadMapSpriteTilePatterns set are in the
+; order of the map's sprite set, not the order of the actual sprites loaded
+; for the current map. So, they are not needed and are zeroed by this loop.
+.zeroVRAMSlotsLoop
+ xor a
+ ld [hl],a ; $C2XE (VRAM slot)
+ ld a,$10
+ add l
+ ld l,a
+ dec b
+ jr nz,.zeroVRAMSlotsLoop
+.skipLoadingSpriteSet
+ ld hl,$c110
+; This loop stores the correct VRAM tile pattern slots according the sprite
+; data from the map's header. Since the VRAM tile pattern slots are filled in
+; the order of the sprite set, in order to find the VRAM tile pattern slot
+; for a sprite slot, the picture ID for the sprite is looked up within the
+; sprite set. The index of the picture ID within the sprite set plus one
+; (since the Red sprite always has the first VRAM tile pattern slot) is the
+; VRAM tile pattern slot.
+.storeVRAMSlotsLoop
+ ld c,0
+ ld a,[hl] ; $C1X0 (picture ID) (zero if sprite slot is not used)
+ and a ; is the sprite slot used?
+ jr z,.skipGettingPictureIndex ; if the sprite slot is not used
+ ld b,a ; b = picture ID
+ ld de,W_SPRITESET
+; Loop to find the index of the sprite's picture ID within the sprite set.
+.getPictureIndexLoop
+ inc c
+ ld a,[de]
+ inc de
+ cp b ; does the picture ID match?
+ jr nz,.getPictureIndexLoop
+ inc c
+.skipGettingPictureIndex
+ push hl
+ inc h
+ ld a,$0e
+ add l
+ ld l,a
+ ld a,c ; a = VRAM slot (zero if sprite slot is not used)
+ ld [hl],a ; $C2XE (VRAM slot)
+ pop hl
+ ld a,$10
+ add l
+ ld l,a
+ and a
+ jr nz,.storeVRAMSlotsLoop
+ scf
+ ret
+
+; Chooses the correct sprite set ID depending on the player's position within
+; the map for maps with two sprite sets.
+GetSplitMapSpriteSetID: ; 17a1a (5:7a1a)
+ cp a,$f8
+ jr z,.route20
+ ld hl,SplitMapSpriteSets
+ and a,$0f
+ dec a
+ sla a
+ sla a
+ add l
+ ld l,a
+ jr nc,.noCarry
+ inc h
+.noCarry
+ ld a,[hli] ; determines whether the map is split East/West or North/South
+ cp a,$01
+ ld a,[hli] ; position of dividing line
+ ld b,a
+ jr z,.eastWestDivide
+.northSouthDivide
+ ld a,[W_YCOORD]
+ jr .compareCoord
+.eastWestDivide
+ ld a,[W_XCOORD]
+.compareCoord
+ cp b
+ jr c,.loadSpriteSetID
+; if in the East side or South side
+ inc hl
+.loadSpriteSetID
+ ld a,[hl]
+ ret
+; Uses sprite set $01 for West side and $0A for East side.
+; Route 20 is a special case because the two map sections have a more complex
+; shape instead of the map simply being split horizontally or vertically.
+.route20
+ ld hl,W_XCOORD
+ ld a,[hl]
+ cp a,$2b
+ ld a,$01
+ ret c
+ ld a,[hl]
+ cp a,$3e
+ ld a,$0a
+ ret nc
+ ld a,[hl]
+ cp a,$37
+ ld b,$08
+ jr nc,.next
+ ld b,$0d
+.next
+ ld a,[W_YCOORD]
+ cp b
+ ld a,$0a
+ ret c
+ ld a,$01
+ ret
+
+INCLUDE "data/sprite_sets.asm"
diff --git a/engine/overworld/npc_movement.asm b/engine/overworld/npc_movement.asm
new file mode 100755
index 00000000..54d7321b
--- /dev/null
+++ b/engine/overworld/npc_movement.asm
@@ -0,0 +1,291 @@
+Func_1a3e0: ; 1a3e0 (6:63e0)
+ ld hl, $d730
+ res 1, [hl]
+ call HandleDoors
+ jr nc, .asm_1a406
+ ld a, $fc
+ ld [wJoypadForbiddenButtonsMask], a
+ ld hl, $d736
+ set 1, [hl]
+ ld a, $1
+ ld [$cd38], a
+ ld a, $80
+ ld [$ccd3], a
+ xor a
+ ld [$c102], a
+ call Func_3486
+ ret
+.asm_1a406
+ xor a
+ ld [$cd3a], a
+ ld [$cd38], a
+ ld [$ccd3], a
+ ld hl, $d736
+ res 0, [hl]
+ res 1, [hl]
+ ld hl, $d730
+ res 7, [hl]
+ ret
+
+Func_1a41d: ; 1a41d (6:641d)
+ ld hl, $d730
+ res 7, [hl]
+ ld hl, $d72e
+ res 7, [hl]
+ ld hl, $d736
+ res 0, [hl]
+ res 1, [hl]
+ xor a
+ ld [$cf17], a
+ ld [$cc57], a
+ ld [$cf10], a
+ ld [$cd3a], a
+ ld [$cd38], a
+ ld [$ccd3], a
+ ret
+
+PointerTable_1a442: ; 1a442 (6:6442)
+ dw Func_1a44c
+ dw Func_1a485
+ dw Func_1a4a1
+ dw Func_1a4a6
+ dw Func_1a4f4
+
+Func_1a44c: ; 1a44c (6:644c)
+ ld a, [W_XCOORD] ; $d362
+ sub $a
+ ld [$cca1], a
+ jr z, .asm_1a475
+ ld b, $0
+ ld c, a
+ ld hl, $cc97
+ ld a, $80
+ call FillMemory
+ ld [hl], $ff
+ ld a, [$cf13]
+ ld [H_DOWNARROWBLINKCNT2], a ; $ff8c
+ ld de, $cc97
+ call MoveSprite
+ ld a, $1
+ ld [$cf10], a
+ jr .asm_1a47a
+.asm_1a475
+ ld a, $3
+ ld [$cf10], a
+.asm_1a47a
+ ld hl, W_FLAGS_D733
+ set 1, [hl]
+ ld a, $fc
+ ld [wJoypadForbiddenButtonsMask], a
+ ret
+
+Func_1a485: ; 1a485 (6:6485)
+ ld a, [$d730]
+ bit 0, a
+ ret nz
+ ld a, [$cca1]
+ ld [$cd38], a
+ ld [$ff95], a
+ ld a, $23
+ call Predef
+ call Func_3486
+ ld a, $2
+ ld [$cf10], a
+ ret
+
+Func_1a4a1: ; 1a4a1 (6:64a1)
+ ld a, [$cd38]
+ and a
+ ret nz
+
+Func_1a4a6: ; 1a4a6 (6:64a6)
+ xor a
+ ld [$cd3b], a
+ ld a, [$cf13]
+ swap a
+ ld [$cf17], a
+ xor a
+ ld [$c206], a
+ ld hl, $ccd3
+ ld de, RLEList_1a4e9
+ call DecodeRLEList
+ dec a
+ ld [$cd38], a
+ ld hl, $cc97
+ ld de, RLEList_1a4dc
+ call DecodeRLEList
+ ld hl, $d72e
+ res 7, [hl]
+ ld hl, $d730
+ set 7, [hl]
+ ld a, $4
+ ld [$cf10], a
+ ret
+
+RLEList_1a4dc: ; 1a4dc (6:64dc)
+ db $00, $05
+ db $80, $01
+ db $00, $05
+ db $C0, $03
+ db $40, $01
+ db $E0, $01
+ db $FF
+
+RLEList_1a4e9: ; 1a4e9 (6:64e9)
+ db $40, $02
+ db $10, $03
+ db $80, $05
+ db $20, $01
+ db $80, $06
+ db $FF
+
+Func_1a4f4: ; 1a4f4 (6:64f4)
+ ld a, [$cd38]
+ and a
+ ret nz
+ ld a, $0
+ ld [$cc4d], a
+ ld a, $11
+ call Predef ; indirect jump to RemoveMissableObject (f1d7 (3:71d7))
+ ld hl, $d730
+ res 7, [hl]
+ ld hl, $d72e
+ res 7, [hl]
+ jp Func_314e
+
+PointerTable_1a510: ; 1a510 (6:6510)
+ dw Func_1a514
+ dw Func_1a56b
+
+Func_1a514: ; 1a514 (6:6514)
+ ld a, Bank(Func_9876)
+ ld [$c0ef], a
+ ld [$c0f0], a
+ ld a, MUSIC_MUSEUM_GUY
+ ld [$c0ee], a
+ call PlaySound
+ ld a, [$cf13]
+ swap a
+ ld [$cf17], a
+ call Func_3486
+ ld hl, $ccd3
+ ld de, RLEList_PewterMuseumPlayer
+ call DecodeRLEList
+ dec a
+ ld [$cd38], a
+ xor a
+ ld [$d12f], a
+ ld a, $4f
+ call Predef
+ ld hl, $cc97
+ ld de, RLEList_PewterMuseumGuy
+ call DecodeRLEList
+ ld hl, $d72e
+ res 7, [hl]
+ ld a, $1
+ ld [$cf10], a
+ ret
+
+RLEList_PewterMuseumPlayer: ; 1a559 (6:6559)
+ db $00, $01
+ db $40, $03
+ db $20, $0D
+ db $40, $06
+ db $FF
+
+RLEList_PewterMuseumGuy: ; 1a562 (6:6562)
+ db $40, $06
+ db $80, $0D
+ db $40, $03
+ db $80, $01
+ db $FF
+
+Func_1a56b: ; 1a56b (6:656b)
+ ld a, [$cd38]
+ and a
+ ret nz
+ ld hl, $d730
+ res 7, [hl]
+ ld hl, $d72e
+ res 7, [hl]
+ jp Func_314e
+
+PointerTable_1a57d: ; 1a57d (6:657d)
+ dw Func_1a581
+ dw Func_1a56b
+
+Func_1a581: ; 1a581 (6:6581)
+ ld a, Bank(Func_9876)
+ ld [$c0ef], a
+ ld [$c0f0], a
+ ld a, MUSIC_MUSEUM_GUY
+ ld [$c0ee], a
+ call PlaySound
+ ld a, [$cf13]
+ swap a
+ ld [$cf17], a
+ xor a
+ ld [$c206], a
+ ld hl, $ccd3
+ ld de, RLEList_PewterGymPlayer
+ call DecodeRLEList
+ dec a
+ ld [$cd38], a
+ ld a, $1
+ ld [$d12f], a
+ ld a, $4f
+ call Predef
+ ld hl, $cc97
+ ld de, RLEList_PewterGymGuy
+ call DecodeRLEList
+ ld hl, $d72e
+ res 7, [hl]
+ ld hl, $d730
+ set 7, [hl]
+ ld a, $1
+ ld [$cf10], a
+ ret
+
+RLEList_PewterGymPlayer: ; 1a5cd (6:65cd)
+ db $00, $01
+ db $10, $02
+ db $80, $05
+ db $20, $0B
+ db $40, $05
+ db $20, $0F
+ db $FF
+
+RLEList_PewterGymGuy: ; 1a5da (6:65da)
+ db $00, $02
+ db $80, $0F
+ db $40, $05
+ db $80, $0B
+ db $00, $05
+ db $C0, $03
+ db $FF
+
+; XXX why would this function want to return on POKEMONTOWER_7?
+Func_1a5e7: ; 1a5e7 (6:65e7)
+ ld a, [W_CURMAP] ; $d35e
+ cp POKEMONTOWER_7
+ ret z
+ ld hl, RivalIDs ; $6605
+ ld a, [wEngagedTrainerClass]
+ ld b, a
+.loop
+ ld a, [hli]
+ cp $ff
+ jr z, .notRival
+ cp b
+ ret z
+ jr .loop
+.notRival
+ ld a, [$cf13]
+ ld [H_DOWNARROWBLINKCNT2], a ; $ff8c
+ jp SetSpriteMovementBytesToFF
+
+RivalIDs: ; 1a605 (6:6605)
+ db SONY1 + $c8
+ db SONY2 + $c8
+ db SONY3 + $c8
+ db $ff
diff --git a/engine/overworld/oaks_aide.asm b/engine/overworld/oaks_aide.asm
new file mode 100755
index 00000000..ca2c6726
--- /dev/null
+++ b/engine/overworld/oaks_aide.asm
@@ -0,0 +1,71 @@
+OaksAideScript ; 0x59035
+ ld hl, OaksAideHiText
+ call PrintText
+ call YesNoChoice
+ ld a, [$cc26]
+ and a
+ jr nz, .asm_59086 ; 0x59042 $42
+ ld hl, wPokedexOwned
+ ld b, wPokedexOwnedEnd - wPokedexOwned
+ call CountSetBits
+ ld a, [$d11e]
+ ld [$ffdd], a
+ ld b, a
+ ld a, [$ffdb]
+ cp b
+ jr z, .asm_59059 ; 0x59055 $2
+ jr nc, .asm_5907c ; 0x59057 $23
+.asm_59059
+ ld hl, OaksAideHereYouGoText
+ call PrintText
+ ld a, [$ffdc]
+ ld b, a
+ ld c, 1
+ call GiveItem
+ jr nc, .BagFull
+ ld hl, OaksAideGotItemText
+ call PrintText
+ ld a, $1
+ jr .asm_5908e ; 0x59071 $1b
+.BagFull
+ ld hl, OaksAideNoRoomText
+ call PrintText
+ xor a
+ jr .asm_5908e ; 0x5907a $12
+.asm_5907c
+ ld hl, OaksAideUhOhText
+ call PrintText
+ ld a, $80
+ jr .asm_5908e ; 0x59084 $8
+.asm_59086
+ ld hl, OaksAideComeBackText
+ call PrintText
+ ld a, $ff
+.asm_5908e
+ ld [$ffdb], a
+ ret
+
+OaksAideHiText: ; 59091 (16:5091)
+ TX_FAR _OaksAideHiText
+ db "@"
+
+OaksAideUhOhText: ; 59096 (16:5096)
+ TX_FAR _OaksAideUhOhText
+ db "@"
+
+OaksAideComeBackText: ; 5909b (16:509b)
+ TX_FAR _OaksAideComeBackText
+ db "@"
+
+OaksAideHereYouGoText: ; 590a0 (16:50a0)
+ TX_FAR _OaksAideHereYouGoText
+ db "@"
+
+OaksAideGotItemText: ; 590a5 (16:50a5)
+ TX_FAR _OaksAideGotItemText
+ db $0b
+ db "@"
+
+OaksAideNoRoomText: ; 590ab (16:50ab)
+ TX_FAR _OaksAideNoRoomText
+ db "@"
diff --git a/engine/overworld/pewter_guys.asm b/engine/overworld/pewter_guys.asm
new file mode 100755
index 00000000..7c5779a2
--- /dev/null
+++ b/engine/overworld/pewter_guys.asm
@@ -0,0 +1,101 @@
+PewterGuys: ; 37ca1 (d:7ca1)
+ ld hl, $ccd3
+ ld a, [$cd38]
+ dec a
+ ld [$cd38], a
+ ld d, 0
+ ld e, a
+ add hl, de
+ ld d, h
+ ld e, l
+ ld hl, PointerTable_37ce6
+ ld a, [$d12f]
+ add a
+ ld b, 0
+ ld c, a
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [W_YCOORD]
+ ld b, a
+ ld a, [W_XCOORD]
+ ld c, a
+.asm_37cc7
+ ld a, [hli]
+ cp b
+ jr nz, .asm_37ce1
+ ld a, [hli]
+ cp c
+ jr nz, .asm_37ce2
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+.asm_37cd2
+ ld a, [hli]
+ cp $ff
+ ret z
+ ld [de], a
+ inc de
+ ld a, [$cd38]
+ inc a
+ ld [$cd38], a
+ jr .asm_37cd2
+.asm_37ce1
+ inc hl
+.asm_37ce2
+ inc hl
+ inc hl
+ jr .asm_37cc7
+
+PointerTable_37ce6: ; 37ce6 (d:7ce6)
+ dw PewterMuseumGuyCoords
+ dw PewterGymGuyCoords
+
+; these are the four coordinates of the spaces below, above, to the left and
+; to the right of the museum guy, and pointers to different movements for
+; the player to make to get positioned before the main movement.
+PewterMuseumGuyCoords: ; 37cea (d:7cea)
+ db 18, 27
+ dw .down
+ db 16, 27
+ dw .up
+ db 17, 26
+ dw .left
+ db 17, 28
+ dw .right
+
+.down
+ db $40, $40, $ff
+.up
+ db $10, $20, $ff
+.left
+ db $40, $10, $ff
+.right
+ db $40, $20, $ff
+
+; these are the five coordinates which trigger the gym guy and pointers to
+; different movements for the player to make to get positioned before the
+; main movement
+PewterGymGuyCoords: ; 37d06 (d:7d06)
+ db 16, 34
+ dw .one
+ db 17, 35
+ dw .two
+ db 18, 37
+ dw .three
+ db 19, 37
+ dw .four
+ db 17, 36
+ dw .five
+
+.one
+ db $20, $80, $80, $10, $ff
+.two
+ db $20, $80, $10, $20, $ff
+.three
+ db $20, $20, $20, $00, $00, $00, $00, $00, $00, $00, $00, $ff
+.four
+ db $20, $20, $40, $20, $ff
+.five
+ db $20, $80, $20, $00, $00, $00, $00, $00, $00, $00, $00, $ff
diff --git a/engine/overworld/player_animations.asm b/engine/overworld/player_animations.asm
new file mode 100755
index 00000000..1af178c7
--- /dev/null
+++ b/engine/overworld/player_animations.asm
@@ -0,0 +1,520 @@
+Func_70510: ; 70510 (1c:4510)
+ call Func_706ef
+ ld a, $ec
+ ld [$c104], a
+ call Delay3
+ push hl
+ call GBFadeIn2
+ ld hl, W_FLAGS_D733
+ bit 7, [hl]
+ res 7, [hl]
+ jr nz, .asm_70568
+ ld a, (SFX_02_4c - SFX_Headers_02) / 3
+ call PlaySound
+ ld hl, $d732
+ bit 4, [hl]
+ res 4, [hl]
+ pop hl
+ jr nz, .asm_7055e
+ call Func_705aa
+ ld a, (SFX_02_4f - SFX_Headers_02) / 3
+ call PlaySound
+ call Func_70787
+ ld a, b
+ and a
+ jr nz, .asm_7055b
+ ld hl, wWhichTrade ; $cd3d
+ xor a
+ ld [hli], a
+ inc a
+ ld [hli], a
+ ld a, $8
+ ld [hli], a
+ ld [hl], $ff
+ ld hl, $cd48
+ call Func_70730
+.asm_70558
+ call Func_2307
+.asm_7055b
+ jp Func_70772
+.asm_7055e
+ ld c, $32
+ call DelayFrames
+ call Func_705aa
+ jr .asm_7055b
+.asm_70568
+ pop hl
+ ld de, BirdSprite ; $4d80
+ ld hl, $8000
+ ld bc, (BANK(BirdSprite) << 8) + $0c
+ call CopyVideoData
+ call Func_706d7
+ ld a, (SFX_02_50 - SFX_Headers_02) / 3
+ call PlaySound
+ ld hl, wWhichTrade ; $cd3d
+ xor a
+ ld [hli], a
+ ld a, $c
+ ld [hli], a
+ ld [hl], $8
+ ld de, FlyAnimationEnterScreenCoords ; $4592
+ call Func_706ae
+ call LoadPlayerSpriteGraphics
+ jr .asm_70558
+
+FlyAnimationEnterScreenCoords: ; 70592 (1c:4592)
+; y, x pairs
+; This is the sequence of screen coordinates used by the overworld
+; Fly animation when the player is entering a map.
+ db $05, $98
+ db $0F, $90
+ db $18, $88
+ db $20, $80
+ db $27, $78
+ db $2D, $70
+ db $32, $68
+ db $36, $60
+ db $39, $58
+ db $3B, $50
+ db $3C, $48
+ db $3C, $40
+
+Func_705aa: ; 705aa (1c:45aa)
+ ld hl, wWhichTrade ; $cd3d
+ ld a, $10
+ ld [hli], a
+ ld a, $3c
+ ld [hli], a
+ call Func_7077f
+ ld [hl], a
+ jp Func_70755
+
+_DoFlyOrTeleportAwayGraphics: ; 705ba (1c:45ba)
+ call Func_706ef
+ call Func_70787
+ ld a, b
+ and a
+ jr z, .asm_705ef
+ dec a
+ jp nz, Func_7067d
+.asm_705c8
+ ld a, (SFX_02_4b - SFX_Headers_02) / 3
+ call PlaySound
+ ld hl, wWhichTrade ; $cd3d
+ ld a, $f0
+ ld [hli], a
+ ld a, $ec
+ ld [hli], a
+ call Func_7077f
+ ld [hl], a
+ call Func_70755
+ call Func_70787
+ ld a, b
+ dec a
+ jr z, .asm_705e9
+ ld c, $a
+ call DelayFrames
+.asm_705e9
+ call GBFadeOut2
+ jp Func_70772
+.asm_705ef
+ ld a, $4
+ call StopMusic
+ ld a, [$d732]
+ bit 6, a
+ jr z, .asm_70610
+ ld hl, wWhichTrade ; $cd3d
+ ld a, $10
+ ld [hli], a
+ ld a, $ff
+ ld [hli], a
+ xor a
+ ld [hli], a
+ ld [hl], $a1
+ ld hl, $cd48
+ call Func_70730
+ jr .asm_705c8
+.asm_70610
+ call Func_706d7
+ ld hl, wWhichTrade ; $cd3d
+ ld a, $ff
+ ld [hli], a
+ ld a, $8
+ ld [hli], a
+ ld [hl], $c
+ call Func_706ae
+ ld a, (SFX_02_50 - SFX_Headers_02) / 3
+ call PlaySound
+ ld hl, wWhichTrade ; $cd3d
+ xor a
+ ld [hli], a
+ ld a, $c
+ ld [hli], a
+ ld [hl], $c
+ ld de, FlyAnimationScreenCoords1 ; $464f
+ call Func_706ae
+ ld c, $28
+ call DelayFrames
+ ld hl, $cd3e
+ ld a, $b
+ ld [hli], a
+ ld [hl], $8
+ ld de, FlyAnimationScreenCoords2 ; $4667
+ call Func_706ae
+ call GBFadeOut2
+ jp Func_70772
+
+FlyAnimationScreenCoords1: ; 7064f (1c:464f)
+; y, x pairs
+; This is the sequence of screen coordinates used by the first part
+; of the Fly overworld animation.
+ db $3C, $48
+ db $3C, $50
+ db $3B, $58
+ db $3A, $60
+ db $39, $68
+ db $37, $70
+ db $37, $78
+ db $33, $80
+ db $30, $88
+ db $2D, $90
+ db $2A, $98
+ db $27, $A0
+
+FlyAnimationScreenCoords2: ; 70667 (1c:4667)
+; y, x pairs
+; This is the sequence of screen coordinates used by the second part
+; of the Fly overworld animation.
+ db $1A, $90
+ db $19, $80
+ db $17, $70
+ db $15, $60
+ db $12, $50
+ db $0F, $40
+ db $0C, $30
+ db $09, $20
+ db $05, $10
+ db $00, $00
+
+ db $F0, $00
+
+Func_7067d: ; 7067d (1c:467d)
+ ld a, $ff
+ ld [$cfcb], a
+ ld a, [$c302]
+ ld [$c30a], a
+ ld a, [$c306]
+ ld [$c30e], a
+ ld a, $a0
+ ld [wOAMBuffer], a
+ ld [$c304], a
+ ld c, $2
+ call DelayFrames
+ ld a, $a0
+ ld [$c308], a
+ ld [$c30c], a
+ call GBFadeOut2
+ ld a, $1
+ ld [$cfcb], a
+ jp Func_70772
+
+Func_706ae: ; 706ae (1c:46ae)
+ ld a, [$cd3f]
+ xor $1
+ ld [$cd3f], a
+ ld [$c102], a
+ call Delay3
+ ld a, [wWhichTrade] ; $cd3d
+ cp $ff
+ jr z, .asm_706cd
+ ld hl, $c104
+ ld a, [de]
+ inc de
+ ld [hli], a
+ inc hl
+ ld a, [de]
+ inc de
+ ld [hl], a
+.asm_706cd
+ ld a, [$cd3e]
+ dec a
+ ld [$cd3e], a
+ jr nz, Func_706ae
+ ret
+
+Func_706d7: ; 706d7 (1c:46d7)
+ ld de, BirdSprite ; $4d80
+ ld hl, $8000
+ ld bc, (BANK(BirdSprite) << 8) + $0c
+ call CopyVideoData
+ ld de, BirdSprite + $c0 ; $4e40 ; moving amination sprite
+ ld hl, $8800
+ ld bc, (BANK(BirdSprite) << 8) + $0c
+ jp CopyVideoData
+
+Func_706ef: ; 706ef (1c:46ef)
+ ld a, [$c102]
+ ld [$cd50], a
+ ld a, [$c104]
+ ld [$cd4f], a
+ ld hl, PlayerSpinningFacingOrder ; $4713
+ ld de, $cd48
+ ld bc, $4
+ call CopyData
+ ld a, [$c102]
+ ld hl, $cd48
+.asm_7070d
+ cp [hl]
+ inc hl
+ jr nz, .asm_7070d
+ dec hl
+ ret
+
+PlayerSpinningFacingOrder: ; 70713 (1c:4713)
+; The order of the direction the player's sprite is facing when teleporting
+; away. Creates a spinning effect.
+ db $00, $08, $04, $0C ; down, left, up, right
+
+Func_70717: ; 70717 (1c:4717)
+ ld a, [hl]
+ ld [$c102], a
+ push hl
+ ld hl, $cd48
+ ld de, $cd47
+ ld bc, $4
+ call CopyData
+ ld a, [$cd47]
+ ld [$cd4b], a
+ pop hl
+ ret
+
+Func_70730: ; 70730 (1c:4730)
+ call Func_70717
+ ld a, [wWhichTrade] ; $cd3d
+ ld c, a
+ and $3
+ jr nz, .asm_70743
+ ld a, [$cd40]
+ cp $ff
+ call nz, PlaySound
+.asm_70743
+ ld a, [$cd3e]
+ add c
+ ld [wWhichTrade], a ; $cd3d
+ ld c, a
+ ld a, [$cd3f]
+ cp c
+ ret z
+ call DelayFrames
+ jr Func_70730
+
+Func_70755: ; 70755 (1c:4755)
+ call Func_70717
+ ld a, [wWhichTrade] ; $cd3d
+ ld c, a
+ ld a, [$c104]
+ add c
+ ld [$c104], a
+ ld c, a
+ ld a, [$cd3e]
+ cp c
+ ret z
+ ld a, [$cd3f]
+ ld c, a
+ call DelayFrames
+ jr Func_70755
+
+Func_70772: ; 70772 (1c:4772)
+ ld a, [$cd4f]
+ ld [$c104], a
+ ld a, [$cd50]
+ ld [$c102], a
+ ret
+
+Func_7077f: ; 7077f (1c:477f)
+ ld a, [$cf1b]
+ xor $1
+ inc a
+ inc a
+ ret
+
+Func_70787: ; 70787 (1c:4787)
+ ld b, 0
+ ld hl, DataTable_707a9 ; $47a9
+ ld a, [W_CURMAPTILESET] ; $d367
+ ld c, a
+.asm_70790
+ ld a, [hli]
+ cp $ff
+ jr z, .asm_707a4
+ cp c
+ jr nz, .asm_7079e
+ FuncCoord 8, 9 ; $c45c
+ ld a, [Coord]
+ cp [hl]
+ jr z, .asm_707a2
+.asm_7079e
+ inc hl
+ inc hl
+ jr .asm_70790
+.asm_707a2
+ inc hl
+ ld b, [hl]
+.asm_707a4
+ ld a, b
+ ld [$cd5b], a
+ ret
+
+; format: db tileset id, tile id, value to be put in $cd5b
+DataTable_707a9: ; 707a9 (1c:47a9)
+ db FACILITY, $20, 1 ; warp pad
+ db FACILITY, $11, 2 ; hole
+ db CAVERN, $22, 2 ; hole
+ db INTERIOR, $55, 1 ; warp pad
+ db $FF
+
+Func_707b6: ; 707b6 (1c:47b6)
+ ld c, $a
+ call DelayFrames
+ ld hl, $d736
+ set 6, [hl]
+ ld de, RedSprite ; $4180
+ ld hl, $8000
+ ld bc, (BANK(RedSprite) << 8) + $0c
+ call CopyVideoData
+ ld a, $4
+ ld hl, RedFishingTiles ; $4866
+ call Func_71771
+ ld a, [$c102]
+ ld c, a
+ ld b, $0
+ ld hl, FishingRodGfxProperties ; $4856
+ add hl, bc
+ ld de, $c39c
+ ld bc, $4
+ call CopyData
+ ld c, $64
+ call DelayFrames
+ ld a, [wWhichTrade] ; $cd3d
+ and a
+ ld hl, NoNibbleText
+ jr z, .asm_70836
+ cp $2
+ ld hl, NothingHereText
+ jr z, .asm_70836
+ ld b, $a
+.asm_707fe
+ ld hl, $c104
+ call Func_70842
+ ld hl, $c39c
+ call Func_70842
+ call Delay3
+ dec b
+ jr nz, .asm_707fe
+ ld a, [$c102]
+ cp $4
+ jr nz, .asm_7081c
+ ld a, $a0
+ ld [$c39c], a
+.asm_7081c
+ ld hl, $cd4f
+ xor a
+ ld [hli], a
+ ld [hl], a
+ ld a, $4c
+ call Predef ; indirect jump to PrintEmotionBubble (17c47 (5:7c47))
+ ld a, [$c102]
+ cp $4
+ jr nz, .asm_70833
+ ld a, $44
+ ld [$c39c], a
+.asm_70833
+ ld hl, ItsABiteText
+.asm_70836
+ call PrintText
+ ld hl, $d736
+ res 6, [hl]
+ call LoadFontTilePatterns
+ ret
+
+Func_70842: ; 70842 (1c:4842)
+ ld a, [hl]
+ xor $1
+ ld [hl], a
+ ret
+
+NoNibbleText: ; 70847 (1c:4847)
+ TX_FAR _NoNibbleText
+ db "@"
+
+NothingHereText: ; 7084c (1c:484c)
+ TX_FAR _NothingHereText
+ db "@"
+
+ItsABiteText: ; 70851 (1c:4851)
+ TX_FAR _ItsABiteText
+ db "@"
+
+FishingRodGfxProperties: ; 70856 (1c:4856)
+; specicies how the fishing rod should be drawn on the screen
+; first byte = screen y coordinate
+; second byte = screen x coordinate
+; third byte = tile number
+; fourth byte = sprite properties
+ db $5B, $4C, $FD, $00 ; player facing down
+ db $44, $4C, $FD, $00 ; player facing up
+ db $50, $40, $FE, $00 ; player facing left
+ db $50, $58, $FE, $20 ; player facing right ($20 means "horizontally flip the tile")
+
+RedFishingTiles: ; 70866 (1c:4866)
+ dw RedFishingTilesFront
+ db $02, $1E
+ dw $8020
+
+ dw RedFishingTilesBack
+ db $02, $1E
+ dw $8060
+
+ dw RedFishingTilesSide
+ db $02, $1E
+ dw $80A0
+
+ dw RedFishingRodTiles
+ db $03, $1E
+ dw $8FD0
+
+_HandleMidJump: ; 7087e (1c:487e)
+ ld a, [$d714]
+ ld c, a
+ inc a
+ cp $10
+ jr nc, .asm_70895
+ ld [$d714], a
+ ld b, $0
+ ld hl, PlayerJumpingYScreenCoords ; $48ba
+ add hl, bc
+ ld a, [hl]
+ ld [$c104], a ; player's sprite y coordinate
+ ret
+.asm_70895
+ ld a, [wWalkCounter] ; $cfc5
+ cp $0
+ ret nz
+ call UpdateSprites
+ call Delay3
+ xor a
+ ld [H_CURRENTPRESSEDBUTTONS], a
+ ld [H_NEWLYPRESSEDBUTTONS], a
+ ld [H_NEWLYRELEASEDBUTTONS], a
+ ld [$d714], a
+ ld hl, $d736
+ res 6, [hl]
+ ld hl, $d730
+ res 7, [hl]
+ xor a
+ ld [wJoypadForbiddenButtonsMask], a
+ ret
+
+PlayerJumpingYScreenCoords: ; 708ba (1c:48ba)
+; Sequence of y screen coordinates for player's sprite when jumping over a ledge.
+ db $38, $36, $34, $32, $31, $30, $30, $30, $31, $32, $33, $34, $36, $38, $3C, $3C
diff --git a/engine/overworld/pokecenter.asm b/engine/overworld/pokecenter.asm
new file mode 100755
index 00000000..45599498
--- /dev/null
+++ b/engine/overworld/pokecenter.asm
@@ -0,0 +1,68 @@
+DisplayPokemonCenterDialogue_: ; 6fe6 (1:6fe6)
+ call SaveScreenTilesToBuffer1 ; save screen
+ ld hl, PokemonCenterWelcomeText
+ call PrintText
+ ld hl, $d72e
+ bit 2, [hl]
+ set 1, [hl]
+ set 2, [hl]
+ jr nz, .skipShallWeHealYourPokemon
+ ld hl, ShallWeHealYourPokemonText
+ call PrintText
+.skipShallWeHealYourPokemon
+ call YesNoChoicePokeCenter ; yes/no menu
+ ld a, [wCurrentMenuItem]
+ and a
+ jr nz, .declinedHealing ; if the player chose No
+ call SetLastBlackoutMap
+ call LoadScreenTilesFromBuffer1 ; restore screen
+ ld hl, NeedYourPokemonText
+ call PrintText
+ ld a, $18
+ ld [$c112], a ; make the nurse turn to face the machine
+ call Delay3
+ PREDEF HealPartyPredef
+ callba AnimateHealingMachine ; do the healing machine animation
+ xor a
+ ld [wMusicHeaderPointer], a
+ ld a, [$c0f0]
+ ld [$c0ef], a
+ ld a, [$d35b]
+ ld [$cfca], a
+ ld [$c0ee], a
+ call PlaySound
+ ld hl, PokemonFightingFitText
+ call PrintText
+ ld a, $14
+ ld [$c112], a ; make the nurse bow
+ ld c, a
+ call DelayFrames
+ jr .done
+.declinedHealing
+ call LoadScreenTilesFromBuffer1 ; restore screen
+.done
+ ld hl, PokemonCenterFarewellText
+ call PrintText
+ jp UpdateSprites ; move sprites
+
+PokemonCenterWelcomeText: ; 705d (1:705d)
+ TX_FAR _PokemonCenterWelcomeText
+ db "@"
+
+ShallWeHealYourPokemonText: ; 7062 (1:7062)
+ db $a
+ TX_FAR _ShallWeHealYourPokemonText
+ db "@"
+
+NeedYourPokemonText: ; 7068 (1:7068)
+ TX_FAR _NeedYourPokemonText
+ db "@"
+
+PokemonFightingFitText: ; 706d (1:706d)
+ TX_FAR _PokemonFightingFitText
+ db "@"
+
+PokemonCenterFarewellText: ; 7072 (1:7072)
+ db $a
+ TX_FAR _PokemonCenterFarewellText
+ db "@"
diff --git a/engine/overworld/pokemart.asm b/engine/overworld/pokemart.asm
new file mode 100755
index 00000000..6e6f5ee2
--- /dev/null
+++ b/engine/overworld/pokemart.asm
@@ -0,0 +1,256 @@
+DisplayPokemartDialogue_: ; 6c20 (1:6c20)
+ ld a,[wListScrollOffset]
+ ld [$d07e],a
+ call UpdateSprites ; move sprites
+ xor a
+ ld [$cf0a],a ; flag that is set if something is sold or bought
+.loop
+ xor a
+ ld [wListScrollOffset],a
+ ld [wCurrentMenuItem],a
+ ld [$cc2f],a
+ inc a
+ ld [$cf93],a
+ ld a,$13
+ ld [$d125],a
+ call DisplayTextBoxID ; draw money text box
+ ld a,$15
+ ld [$d125],a
+ call DisplayTextBoxID ; do buy/sell/quit menu
+ ld hl,$d128 ; pointer to this pokemart's inventory
+ ld a,[hli]
+ ld l,[hl]
+ ld h,a ; hl = address of inventory
+ ld a,[$d12e]
+ cp a,$02
+ jp z,.done
+ ld a,[$d12d] ; ID of the chosen menu item
+ and a ; buying?
+ jp z,.buyMenu
+ dec a ; selling?
+ jp z,.sellMenu
+ dec a ; quitting?
+ jp z,.done
+.sellMenu
+ xor a
+ ld [$cf93],a
+ ld a,$02
+ ld [$d11b],a
+ callab Func_39bd5
+ ld a,[wNumBagItems]
+ and a
+ jp z,.bagEmpty
+ ld hl,PokemonSellingGreetingText
+ call PrintText
+ call SaveScreenTilesToBuffer1 ; save screen
+.sellMenuLoop
+ call LoadScreenTilesFromBuffer1 ; restore saved screen
+ ld a,$13
+ ld [$d125],a
+ call DisplayTextBoxID ; draw money text box
+ ld hl,wNumBagItems
+ ld a,l
+ ld [$cf8b],a
+ ld a,h
+ ld [$cf8c],a
+ xor a
+ ld [$cf93],a
+ ld [wCurrentMenuItem],a
+ ld a,ITEMLISTMENU
+ ld [wListMenuID],a
+ call DisplayListMenuID
+ jp c,.returnToMainPokemartMenu ; if the player closed the menu
+.confirmItemSale ; if the player is trying to sell a specific item
+ call IsKeyItem ; check if item is unsellable
+ ld a,[$d124]
+ and a
+ jr nz,.unsellableItem
+ ld a,[$cf91]
+ call IsItemHM
+ jr c,.unsellableItem
+ ld a,PRICEDITEMLISTMENU
+ ld [wListMenuID],a
+ ld [$ff8e],a ; halve prices when selling
+ call DisplayChooseQuantityMenu
+ inc a
+ jr z,.sellMenuLoop ; if the player closed the choose quantity menu with the B button
+ ld hl,PokemartTellSellPriceText
+ ld bc,$0e01
+ call PrintText
+ FuncCoord 14,7
+ ld hl,Coord
+ ld bc,$080f
+ ld a,$14
+ ld [$d125],a
+ call DisplayTextBoxID ; yes/no menu
+ ld a,[$d12e]
+ cp a,$02
+ jr z,.sellMenuLoop ; if the player pressed the B button
+ ld a,[$d12d] ; ID of the chosen menu item
+ dec a
+ jr z,.sellMenuLoop ; if the player chose No
+.sellItem
+ ld a,[$cf0a] ; flag that is set if something is sold or bought
+ and a
+ jr nz,.skipSettingFlag1
+ inc a
+ ld [$cf0a],a
+.skipSettingFlag1
+ call AddAmountSoldToMoney
+ ld hl,wNumBagItems
+ call RemoveItemFromInventory
+ jp .sellMenuLoop
+.unsellableItem
+ ld hl,PokemartUnsellableItemText
+ call PrintText
+ jp .returnToMainPokemartMenu
+.bagEmpty
+ ld hl,PokemartItemBagEmptyText
+ call PrintText
+ call SaveScreenTilesToBuffer1 ; save screen
+ jp .returnToMainPokemartMenu
+.buyMenu
+ ld a,$01
+ ld [$cf93],a
+ ld a,$03
+ ld [$d11b],a
+ callab Func_39bd5
+ ld hl,PokemartBuyingGreetingText
+ call PrintText
+ call SaveScreenTilesToBuffer1 ; save screen
+.buyMenuLoop
+ call LoadScreenTilesFromBuffer1 ; restore saved screen
+ ld a,$13
+ ld [$d125],a
+ call DisplayTextBoxID ; draw money text box
+ ld hl,$cf7b
+ ld a,l
+ ld [$cf8b],a
+ ld a,h
+ ld [$cf8c],a
+ xor a
+ ld [wCurrentMenuItem],a
+ inc a
+ ld [$cf93],a
+ inc a ; a = 2 (PRICEDITEMLISTMENU)
+ ld [wListMenuID],a
+ call DisplayListMenuID
+ jr c,.returnToMainPokemartMenu ; if the player closed the menu
+ ld a,$63
+ ld [$cf97],a
+ xor a
+ ld [$ff8e],a
+ call DisplayChooseQuantityMenu
+ inc a
+ jr z,.buyMenuLoop ; if the player closed the choose quantity menu with the B button
+ ld a,[$cf91] ; item ID
+ ld [$d11e],a ; store item ID for GetItemName
+ call GetItemName
+ call CopyStringToCF4B ; copy name to $cf4b
+ ld hl,PokemartTellBuyPriceText
+ call PrintText
+ FuncCoord 14,7
+ ld hl,Coord
+ ld bc,$080f
+ ld a,$14
+ ld [$d125],a
+ call DisplayTextBoxID ; yes/no menu
+ ld a,[$d12e]
+ cp a,$02
+ jp z,.buyMenuLoop ; if the player pressed the B button
+ ld a,[$d12d] ; ID of the chosen menu item
+ dec a
+ jr z,.buyMenuLoop ; if the player chose No
+.buyItem
+ call .isThereEnoughMoney
+ jr c,.notEnoughMoney
+ ld hl,wNumBagItems
+ call AddItemToInventory
+ jr nc,.bagFull
+ call SubtractAmountPaidFromMoney
+ ld a,[$cf0a] ; flag that is set if something is sold or bought
+ and a
+ jr nz,.skipSettingFlag2
+ ld a,$01
+ ld [$cf0a],a
+.skipSettingFlag2
+ ld a,(SFX_02_5a - SFX_Headers_02) / 3
+ call PlaySoundWaitForCurrent ; play sound
+ call WaitForSoundToFinish ; wait until sound is done playing
+ ld hl,PokemartBoughtItemText
+ call PrintText
+ jp .buyMenuLoop
+.returnToMainPokemartMenu
+ call LoadScreenTilesFromBuffer1 ; restore save screen
+ ld a,$13
+ ld [$d125],a
+ call DisplayTextBoxID ; draw money text box
+ ld hl,PokemartAnythingElseText
+ call PrintText
+ jp .loop
+.isThereEnoughMoney
+ ld de,wPlayerMoney
+ ld hl,$ff9f ; item price
+ ld c,3 ; length of money in bytes
+ jp StringCmp
+.notEnoughMoney
+ ld hl,PokemartNotEnoughMoneyText
+ call PrintText
+ jr .returnToMainPokemartMenu
+.bagFull
+ ld hl,PokemartItemBagFullText
+ call PrintText
+ jr .returnToMainPokemartMenu
+.done
+ ld hl,PokemartThankYouText
+ call PrintText
+ ld a,$01
+ ld [$cfcb],a
+ call UpdateSprites ; move sprites
+ ld a,[$d07e]
+ ld [wListScrollOffset],a
+ ret
+
+PokemartBuyingGreetingText: ; 6e0c (1:6e0c)
+ TX_FAR _PokemartBuyingGreetingText
+ db "@"
+
+PokemartTellBuyPriceText: ; 6e11 (1:6e11)
+ TX_FAR _PokemartTellBuyPriceText
+ db "@"
+
+PokemartBoughtItemText: ; 6e16 (1:6e16)
+ TX_FAR _PokemartBoughtItemText
+ db "@"
+
+PokemartNotEnoughMoneyText: ; 6e1b (1:6e1b)
+ TX_FAR _PokemartNotEnoughMoneyText
+ db "@"
+
+PokemartItemBagFullText: ; 6e20 (1:6e20)
+ TX_FAR _PokemartItemBagFullText
+ db "@"
+
+PokemonSellingGreetingText: ; 6e25 (1:6e25)
+ TX_FAR _PokemonSellingGreetingText
+ db "@"
+
+PokemartTellSellPriceText: ; 6e2a (1:6e2a)
+ TX_FAR _PokemartTellSellPriceText
+ db "@"
+
+PokemartItemBagEmptyText: ; 6e2f (1:6e2f)
+ TX_FAR _PokemartItemBagEmptyText
+ db "@"
+
+PokemartUnsellableItemText: ; 6e34 (1:6e34)
+ TX_FAR _PokemartUnsellableItemText
+ db "@"
+
+PokemartThankYouText: ; 6e39 (1:6e39)
+ TX_FAR _PokemartThankYouText
+ db "@"
+
+PokemartAnythingElseText: ; 6e3e (1:6e3e)
+ TX_FAR _PokemartAnythingElseText
+ db "@"
diff --git a/engine/overworld/saffron_guards.asm b/engine/overworld/saffron_guards.asm
new file mode 100755
index 00000000..8e584a2d
--- /dev/null
+++ b/engine/overworld/saffron_guards.asm
@@ -0,0 +1,18 @@
+RemoveGuardDrink: ; 5a59f (16:659f)
+ ld hl, GuardDrinksList
+.drinkLoop
+ ld a, [hli]
+ ld [$ffdb], a
+ and a
+ ret z
+ push hl
+ ld b, a
+ call IsItemInBag
+ pop hl
+ jr z, .drinkLoop
+ ld b, BANK(RemoveItemByID)
+ ld hl, RemoveItemByID
+ jp Bankswitch
+
+GuardDrinksList: ; 5a5b7 (16:65b7)
+ db FRESH_WATER, SODA_POP, LEMONADE, $00
diff --git a/engine/overworld/ssanne.asm b/engine/overworld/ssanne.asm
new file mode 100755
index 00000000..e8060810
--- /dev/null
+++ b/engine/overworld/ssanne.asm
@@ -0,0 +1,88 @@
+Func_79f54: ; 79f54 (1e:5f54)
+ ld a, $1
+ ld [$cd50], a
+ ld a, [$cfcb]
+ push af
+ ld a, $ff
+ ld [$cfcb], a
+ ld a, $e4
+ ld [rOBP1], a ; $ff49
+ call LoadSmokeTileFourTimes
+ callba asm_f055
+ ld c, $8
+.asm_79f73
+ push bc
+ call Func_79f92
+ ld bc, .asm_79f7e
+ push bc
+ ld c, $4
+ jp [hl]
+.asm_79f7e
+ ld a, [rOBP1] ; $ff49
+ xor $64
+ ld [rOBP1], a ; $ff49
+ call Delay3
+ pop bc
+ dec c
+ jr nz, .asm_79f73
+ pop af
+ ld [$cfcb], a
+ jp LoadPlayerSpriteGraphics
+
+Func_79f92: ; 79f92 (1e:5f92)
+ ld a, [$c109]
+ ld hl, PointerTable_79fb0 ; $5fb0
+ ld c, a
+ ld b, $0
+ add hl, bc
+ ld a, [hli]
+ ld [$d08a], a
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ push hl
+ ld hl, $c390
+ ld d, $0
+ add hl, de
+ ld e, l
+ ld d, h
+ pop hl
+ ret
+
+PointerTable_79fb0: ; 79fb0 (1e:5fb0)
+ db $FF,$00
+ dw Func_79350
+
+ db $01,$00
+ dw Func_79350
+
+ db $01,$01
+ dw Func_79337
+
+ db $FF,$01
+ dw Func_79337
+
+LoadSmokeTileFourTimes: ; 79fc0 (1e:5fc0)
+ ld hl, $8fc0
+ ld c, $4
+.loop
+ push bc
+ push hl
+ call LoadSmokeTile
+ pop hl
+ ld bc, $10
+ add hl, bc
+ pop bc
+ dec c
+ jr nz, .loop
+ ret
+
+LoadSmokeTile: ; 79fd4 (1e:5fd4)
+ ld de, SSAnneSmokePuffTile ; $5fdd
+ ld bc, (BANK(SSAnneSmokePuffTile) << 8) + $01
+ jp CopyVideoData
+
+SSAnneSmokePuffTile: ; 79fdd (1e:5fdd)
+ INCBIN "gfx/ss_anne_smoke_puff.2bpp"
diff --git a/engine/overworld/trainers.asm b/engine/overworld/trainers.asm
new file mode 100755
index 00000000..8968332a
--- /dev/null
+++ b/engine/overworld/trainers.asm
@@ -0,0 +1,347 @@
+Func_567f9: ; 567f9 (15:67f9)
+ ld hl, wSpriteStateData1
+ ld de, $4
+ ld a, [$cf13]
+ ld [H_DOWNARROWBLINKCNT2], a ; $ff8c
+ call Func_56903
+ ld a, [hli]
+ ld [$ffeb], a
+ inc hl
+ ld a, [hl]
+ ld [$ffec], a
+ ld de, $fe
+ add hl, de
+ ld a, [hli]
+ ld [$ffed], a
+ ld a, [hl]
+ ld [$ffee], a
+ ret
+
+Func_56819: ; 56819 (15:6819)
+ ld hl, wSpriteStateData1
+ ld de, $0004
+ ld a, [$cf13]
+ ld [H_DOWNARROWBLINKCNT2], a ; $ff8c
+ call Func_56903
+ ld a, [hli]
+ ld [$d130], a
+ inc hl
+ ld a, [hl]
+ ld [$d131], a
+ ld de, $00fe
+ add hl, de
+ ld a, [hli]
+ ld [$d132], a
+ ld a, [hl]
+ ld [$d133], a
+ ret
+
+Func_5683d: ; 5683d (15:683d)
+ ld hl, wSpriteStateData1
+ ld de, $4
+ ld a, [$cf13]
+ ld [H_DOWNARROWBLINKCNT2], a ; $ff8c
+ call Func_56903
+ ld a, [$ffeb]
+ ld [hli], a
+ inc hl
+ ld a, [$ffec]
+ ld [hl], a
+ ld de, $fe
+ add hl, de
+ ld a, [$ffed]
+ ld [hli], a
+ ld a, [$ffee]
+ ld [hl], a
+ ret
+
+Func_5685d: ; 5685d (15:685d)
+ ld hl, wSpriteStateData1
+ ld de, $0004
+ ld a, [$cf13]
+ ld [H_DOWNARROWBLINKCNT2], a ; $ff8c
+ call Func_56903
+ ld a, [$d130]
+ ld [hli], a
+ inc hl
+ ld a, [$d131]
+ ld [hl], a
+ ld de, $00fe
+ add hl, de
+ ld a, [$d132]
+ ld [hli], a
+ ld a, [$d133]
+ ld [hl], a
+ ret
+
+TrainerWalkUpToPlayer: ; 56881 (15:6881)
+ ld a, [$cf13]
+ swap a
+ ld [wTrainerSpriteOffset], a ; $cd3d
+ call ReadTrainerScreenPosition
+ ld a, [wTrainerFacingDirection]
+ and a
+ jr z, .facingDown
+ cp $4
+ jr z, .facingUp
+ cp $8
+ jr z, .facingLeft
+ jr .facingRight
+.facingDown
+ ld a, [wTrainerScreenY]
+ ld b, a
+ ld a, $3c ; (fixed) player screen Y pos
+ call CalcDifference
+ cp $10 ; trainer is right above player
+ ret z
+ swap a
+ dec a
+ ld c, a ; bc = steps yet to go to reach player
+ xor a
+ ld b, a ; a = direction to go to
+ jr .writeWalkScript
+.facingUp
+ ld a, [wTrainerScreenY]
+ ld b, a
+ ld a, $3c ; (fixed) player screen Y pos
+ call CalcDifference
+ cp $10 ; trainer is right below player
+ ret z
+ swap a
+ dec a
+ ld c, a ; bc = steps yet to go to reach player
+ ld b, $0
+ ld a, $40 ; a = direction to go to
+ jr .writeWalkScript
+.facingRight
+ ld a, [wTrainerScreenX]
+ ld b, a
+ ld a, $40 ; (fixed) player screen X pos
+ call CalcDifference
+ cp $10 ; trainer is directly left of player
+ ret z
+ swap a
+ dec a
+ ld c, a ; bc = steps yet to go to reach player
+ ld b, $0
+ ld a, $c0 ; a = direction to go to
+ jr .writeWalkScript
+.facingLeft
+ ld a, [$cd41]
+ ld b, a
+ ld a, $40 ; (fixed) player screen X pos
+ call CalcDifference
+ cp $10 ; trainer is directly right of player
+ ret z
+ swap a
+ dec a
+ ld c, a ; bc = steps yet to go to reach player
+ ld b, $0
+ ld a, $80 ; a = direction to go to
+.writeWalkScript
+ ld hl, $cc97
+ ld de, $cc97
+ call FillMemory ; write the necessary steps to reach player
+ ld [hl], $ff ; write end of list sentinel
+ ld a, [$cf13]
+ ld [H_DOWNARROWBLINKCNT2], a ; $ff8c
+ jp MoveSprite_
+
+Func_56903: ; 56903 (15:6903)
+ push de
+ add hl, de
+ ld a, [H_DOWNARROWBLINKCNT2] ; $ff8c
+ swap a
+ ld d, $0
+ ld e, a
+ add hl, de
+ pop de
+ ret
+
+; tests if this trainer is in the right position to engage the player and do so if she is.
+CheckEngagePlayer: ; 5690f (15:690f)
+ push hl
+ push de
+ ld a, [wTrainerSpriteOffset] ; $cd3d
+ add $2
+ ld d, $0
+ ld e, a
+ ld hl, wSpriteStateData1
+ add hl, de
+ ld a, [hl] ; c1x2: sprite image index
+ sub $ff
+ jr nz, .spriteOnScreen ; test if sprite is on screen
+ jp .noEngage
+.spriteOnScreen
+ ld a, [wTrainerSpriteOffset] ; $cd3d
+ add $9
+ ld d, $0
+ ld e, a
+ ld hl, wSpriteStateData1
+ add hl, de
+ ld a, [hl] ; c1x9: facing direction
+ ld [$cd3f], a
+ call ReadTrainerScreenPosition
+ ld a, [$cd40] ; sprite screen Y pos
+ ld b, a
+ ld a, $3c
+ cp b
+ jr z, .linedUpY
+ ld a, [$cd41] ; sprite screen X pos
+ ld b, a
+ ld a, $40
+ cp b
+ jr z, .linedUpX
+ xor a
+ jp .noEngage
+.linedUpY
+ ld a, [$cd41] ; sprite screen X pos
+ ld b, a
+ ld a, $40 ; (fixed) player X position
+ call CalcDifference ; calc distance
+ jr z, .noEngage ; exact same position as player
+ call CheckSpriteCanSeePlayer
+ jr c, .engage
+ xor a
+ jr .noEngage
+.linedUpX
+ ld a, [$cd40] ; sprite screen Y pos
+ ld b, a
+ ld a, $3c ; (fixed) player Y position
+ call CalcDifference ; calc distance
+ jr z, .noEngage ; exact same position as player
+ call CheckSpriteCanSeePlayer
+ jr c, .engage
+ xor a
+ jp .noEngage
+.engage
+ call CheckPlayerIsInFrontOfSprite
+ ld a, [wTrainerSpriteOffset] ; $cd3d
+ and a
+ jr z, .noEngage
+ ld hl, wFlags_0xcd60
+ set 0, [hl]
+ call EngageMapTrainer
+ ld a, $ff
+.noEngage: ; 56988 (15:6988)
+ ld [wTrainerSpriteOffset], a ; $cd3d
+ pop de
+ pop hl
+ ret
+
+; reads trainer's Y position to $cd40 and X position to $cd41
+ReadTrainerScreenPosition: ; 5698e (15:698e)
+ ld a, [wTrainerSpriteOffset] ; $cd3d
+ add $4
+ ld d, $0
+ ld e, a
+ ld hl, wSpriteStateData1
+ add hl, de
+ ld a, [hl]
+ ld [$cd40], a
+ ld a, [wTrainerSpriteOffset] ; $cd3d
+ add $6
+ ld d, $0
+ ld e, a
+ ld hl, wSpriteStateData1
+ add hl, de
+ ld a, [hl]
+ ld [$cd41], a
+ ret
+
+; checks if the sprite is properly lined up with the player with respect to the direction it's looking. Also checks the distance between player and sprite
+; note that this does not necessarily mean the sprite is seeing the player, he could be behind it's back
+; a: distance player to sprite
+CheckSpriteCanSeePlayer: ; 569af (15:69af)
+ ld b, a
+ ld a, [wTrainerEngageDistance] ; sprite line of sight (engage distance)
+ cp b
+ jr nc, .checkIfLinedUp
+ jr .notInLine ; player too far away
+.checkIfLinedUp
+ ld a, [$cd3f] ; sprite facing direction
+ cp $0 ; down
+ jr z, .checkXCoord
+ cp $4 ; up
+ jr z, .checkXCoord
+ cp $8 ; left
+ jr z, .checkYCoord
+ cp $c ; right
+ jr z, .checkYCoord
+ jr .notInLine
+.checkXCoord
+ ld a, [$cd41] ; sprite screen X position
+ ld b, a
+ cp $40
+ jr z, .inLine
+ jr .notInLine
+.checkYCoord
+ ld a, [$cd40] ; sprite screen Y position
+ ld b, a
+ cp $3c
+ jr nz, .notInLine
+.inLine
+ scf
+ ret
+.notInLine
+ and a
+ ret
+
+; tests if the player is in front of the sprite (rather than behind it)
+CheckPlayerIsInFrontOfSprite: ; 569e3 (15:69e3)
+ ld a, [W_CURMAP] ; $d35e
+ cp POWER_PLANT
+ jp z, .engage ; XXX not sure why bypass this for power plant (maybe to get voltorb fake items to work?)
+ ld a, [wTrainerSpriteOffset] ; $cd3d
+ add $4
+ ld d, $0
+ ld e, a
+ ld hl, wSpriteStateData1
+ add hl, de
+ ld a, [hl] ; c1x4 (sprite screen Y pos)
+ cp $fc
+ jr nz, .notOnTopmostTile ; special case if sprite is on topmost tile (Y = $fc (-4)), make it come down a block
+ ld a, $c
+.notOnTopmostTile
+ ld [$cd40], a
+ ld a, [wTrainerSpriteOffset] ; $cd3d
+ add $6
+ ld d, $0
+ ld e, a
+ ld hl, wSpriteStateData1
+ add hl, de
+ ld a, [hl] ; c1x6 (sprite screen X pos)
+ ld [$cd41], a
+ ld a, [$cd3f] ; facing direction
+ cp $0
+ jr nz, .notFacingDown
+ ld a, [$cd40] ; sprite screen Y pos
+ cp $3c
+ jr c, .engage ; sprite above player
+ jr .noEngage ; sprite below player
+.notFacingDown
+ cp $4
+ jr nz, .notFacingUp
+ ld a, [$cd40] ; sprite screen Y pos
+ cp $3c
+ jr nc, .engage ; sprite below player
+ jr .noEngage ; sprite above player
+.notFacingUp
+ cp $8
+ jr nz, .notFacingLeft
+ ld a, [$cd41] ; sprite screen X pos
+ cp $40
+ jr nc, .engage ; sprite right of player
+ jr .noEngage ; sprite left of player
+.notFacingLeft
+ ld a, [$cd41] ; sprite screen X pos
+ cp $40
+ jr nc, .noEngage ; sprite right of player
+.engage
+ ld a, $ff
+ jr .done
+.noEngage
+ xor a
+.done
+ ld [wTrainerSpriteOffset], a ; $cd3d
+ ret