summaryrefslogtreecommitdiff
path: root/engine/overworld
diff options
context:
space:
mode:
Diffstat (limited to 'engine/overworld')
-rwxr-xr-xengine/overworld/cable_club_npc.asm55
-rwxr-xr-xengine/overworld/card_key.asm36
-rwxr-xr-xengine/overworld/cinnabar_lab.asm91
-rw-r--r--engine/overworld/clear_variables.asm20
-rwxr-xr-xengine/overworld/cut.asm201
-rwxr-xr-xengine/overworld/cut2.asm86
-rw-r--r--engine/overworld/daycare_exp.asm18
-rwxr-xr-xengine/overworld/doors.asm69
-rwxr-xr-xengine/overworld/elevator.asm42
-rwxr-xr-xengine/overworld/emotion_bubbles.asm48
-rw-r--r--engine/overworld/field_move_messages.asm57
-rwxr-xr-xengine/overworld/healing_machine.asm77
-rwxr-xr-xengine/overworld/hidden_items.asm129
-rwxr-xr-xengine/overworld/hidden_objects.asm28
-rw-r--r--engine/overworld/is_player_just_outside_map.asm10
-rw-r--r--engine/overworld/item.asm14
-rwxr-xr-xengine/overworld/ledges.asm19
-rw-r--r--engine/overworld/map_sprite_functions1.asm356
-rwxr-xr-xengine/overworld/map_sprites.asm54
-rw-r--r--engine/overworld/missable_objects.asm215
-rw-r--r--engine/overworld/movement.asm407
-rwxr-xr-xengine/overworld/npc_movement.asm156
-rwxr-xr-xengine/overworld/oaks_aide.asm50
-rw-r--r--engine/overworld/oam.asm101
-rwxr-xr-xengine/overworld/pewter_guys.asm49
-rwxr-xr-xengine/overworld/player_animations.asm205
-rw-r--r--engine/overworld/player_state.asm463
-rw-r--r--engine/overworld/poison.asm112
-rwxr-xr-xengine/overworld/pokecenter.asm30
-rwxr-xr-xengine/overworld/pokemart.asm168
-rw-r--r--engine/overworld/push_boulder.asm105
-rwxr-xr-xengine/overworld/saffron_guards.asm8
-rw-r--r--engine/overworld/set_blackout_map.asm29
-rwxr-xr-xengine/overworld/ssanne.asm25
-rw-r--r--engine/overworld/tileset_header.asm60
-rwxr-xr-xengine/overworld/trainers.asm116
-rw-r--r--engine/overworld/update_map.asm126
-rw-r--r--engine/overworld/wild_mons.asm33
38 files changed, 2763 insertions, 1105 deletions
diff --git a/engine/overworld/cable_club_npc.asm b/engine/overworld/cable_club_npc.asm
index bdab41a6..08067412 100755
--- a/engine/overworld/cable_club_npc.asm
+++ b/engine/overworld/cable_club_npc.asm
@@ -1,15 +1,14 @@
-CableClubNPC: ; 71c5 (1:71c5)
+CableClubNPC:
ld hl, CableClubNPCWelcomeText
call PrintText
- ld a, [wd74b]
- bit 5, a ; received pokedex?
+ CheckEvent EVENT_GOT_POKEDEX
jp nz, .receivedPokedex
; if the player hasn't received the pokedex
- ld c, $3c
+ ld c, 60
call DelayFrames
ld hl, CableClubNPCMakingPreparationsText
call PrintText
- jp Func_7298
+ jp .didNotConnect
.receivedPokedex
ld a, $1
ld [wMenuJoypadPollCount], a
@@ -57,7 +56,7 @@ CableClubNPC: ; 71c5 (1:71c5)
jr nz, .choseNo
callab SaveSAVtoSRAM
call WaitForSoundToFinish
- ld a, (SFX_02_5d - SFX_Headers_02) / 3
+ ld a, SFX_SAVE
call PlaySoundWaitForCurrent
ld hl, CableClubNPCPleaseWaitText
call PrintText
@@ -72,31 +71,29 @@ CableClubNPC: ; 71c5 (1:71c5)
ld hl, wUnknownSerialCounter
ld a, [hli]
inc a
- jr nz, Func_72a8 ; 0x726b $3b
+ jr nz, .connected
ld a, [hl]
inc a
- jr nz, Func_72a8 ; 0x726f $37
- ld b, $a
-.asm_7273
+ jr nz, .connected
+ ld b, 10
+.syncLoop
call DelayFrame
call Serial_SendZeroByte
dec b
- jr nz, .asm_7273 ; 0x727a $f7
+ jr nz, .syncLoop
call CloseLinkConnection
ld hl, CableClubNPCLinkClosedBecauseOfInactivityText
call PrintText
- jr Func_7298 ; 0x7285 $11
+ jr .didNotConnect
.failedToEstablishConnection
ld hl, CableClubNPCAreaReservedFor2FriendsLinkedByCableText
call PrintText
- jr Func_7298 ; 0x728d $9
+ jr .didNotConnect
.choseNo
call CloseLinkConnection
ld hl, CableClubNPCPleaseComeAgainText
call PrintText
- ; fall through
-
-Func_7298: ; 7298 (1:7298)
+.didNotConnect
xor a
ld hl, wUnknownSerialCounter
ld [hli], a
@@ -106,44 +103,42 @@ Func_7298: ; 7298 (1:7298)
xor a
ld [wMenuJoypadPollCount], a
ret
-
-Func_72a8: ; 72a8 (1:72a8)
+.connected
xor a
ld [hld], a
ld [hl], a
- ld hl, LinkMenu
- ld b, BANK(LinkMenu)
- jp Bankswitch
+ jpab LinkMenu
-CableClubNPCAreaReservedFor2FriendsLinkedByCableText: ; 72b3 (1:72b3)
+CableClubNPCAreaReservedFor2FriendsLinkedByCableText:
TX_FAR _CableClubNPCAreaReservedFor2FriendsLinkedByCableText
db "@"
-CableClubNPCWelcomeText: ; 72b8 (1:72b8)
+CableClubNPCWelcomeText:
TX_FAR _CableClubNPCWelcomeText
db "@"
-CableClubNPCPleaseApplyHereHaveToSaveText: ; 72bd (1:72bd)
+CableClubNPCPleaseApplyHereHaveToSaveText:
TX_FAR _CableClubNPCPleaseApplyHereHaveToSaveText
db "@"
-CableClubNPCPleaseWaitText: ; 72c2 (1:72c2)
+CableClubNPCPleaseWaitText:
TX_FAR _CableClubNPCPleaseWaitText
- db $a, "@"
+ TX_DELAY
+ db "@"
-CableClubNPCLinkClosedBecauseOfInactivityText: ; 72c8 (1:72c8)
+CableClubNPCLinkClosedBecauseOfInactivityText:
TX_FAR _CableClubNPCLinkClosedBecauseOfInactivityText
db "@"
-CableClubNPCPleaseComeAgainText: ; 72cd (1:72cd)
+CableClubNPCPleaseComeAgainText:
TX_FAR _CableClubNPCPleaseComeAgainText
db "@"
-CableClubNPCMakingPreparationsText: ; 72d2 (1:72d2)
+CableClubNPCMakingPreparationsText:
TX_FAR _CableClubNPCMakingPreparationsText
db "@"
-CloseLinkConnection: ; 72d7 (1:72d7)
+CloseLinkConnection:
call Delay3
ld a, CONNECTION_NOT_ESTABLISHED
ld [hSerialConnectionStatus], a
diff --git a/engine/overworld/card_key.asm b/engine/overworld/card_key.asm
index c4df0d51..35495c82 100755
--- a/engine/overworld/card_key.asm
+++ b/engine/overworld/card_key.asm
@@ -1,6 +1,6 @@
-PrintCardKeyText: ; 52673 (14:6673)
+PrintCardKeyText:
ld hl, SilphCoMapList
- ld a, [W_CURMAP]
+ ld a, [wCurMap]
ld b, a
.silphCoMapListLoop
ld a, [hli]
@@ -15,7 +15,7 @@ PrintCardKeyText: ; 52673 (14:6673)
cp $24
jr z, .cardKeyDoorInFrontOfPlayer
ld b, a
- ld a, [W_CURMAP]
+ ld a, [wCurMap]
cp SILPH_CO_11F
ret nz
ld a, b
@@ -27,8 +27,8 @@ PrintCardKeyText: ; 52673 (14:6673)
jr z, .noCardKey
call GetCoordsInFrontOfPlayer
push de
- ld a, $1
- ld [H_DOWNARROWBLINKCNT2], a
+ tx_pre_id CardKeySuccessText
+ ld [hSpriteIndexOrTextID], a
call PrintPredefTextID
pop de
srl d
@@ -39,7 +39,7 @@ PrintCardKeyText: ; 52673 (14:6673)
ld a, e
ld c, a
ld [wCardKeyDoorX], a
- ld a, [W_CURMAP]
+ ld a, [wCurMap]
cp SILPH_CO_11F
jr nz, .notSilphCo11F
ld a, $3
@@ -47,18 +47,18 @@ PrintCardKeyText: ; 52673 (14:6673)
.notSilphCo11F
ld a, $e
.replaceCardKeyDoorTileBlock
- ld [wd09f], a
+ ld [wNewTileBlockID], a
predef ReplaceTileBlock
- ld hl, wd126
+ ld hl, wCurrentMapScriptFlags
set 5, [hl]
- ld a, (SFX_1f_57 - SFX_Headers_1f) / 3
+ ld a, SFX_GO_INSIDE
jp PlaySound
.noCardKey
- ld a, $2
- ld [H_DOWNARROWBLINKCNT2], a
+ tx_pre_id CardKeyFailText
+ ld [hSpriteIndexOrTextID], a
jp PrintPredefTextID
-SilphCoMapList: ; 526e3 (14:66e3)
+SilphCoMapList:
db SILPH_CO_2F
db SILPH_CO_3F
db SILPH_CO_4F
@@ -71,22 +71,22 @@ SilphCoMapList: ; 526e3 (14:66e3)
db SILPH_CO_11F
db $FF
-CardKeySuccessText: ; 526ee (14:66ee)
+CardKeySuccessText:
TX_FAR _CardKeySuccessText1
- db $0b
+ TX_SFX_ITEM_1
TX_FAR _CardKeySuccessText2
db "@"
-CardKeyFailText: ; 526f8 (14:66f8)
+CardKeyFailText:
TX_FAR _CardKeyFailText
db "@"
; d = Y
; e = X
-GetCoordsInFrontOfPlayer: ; 526fd (14:66fd)
- ld a, [W_YCOORD]
+GetCoordsInFrontOfPlayer:
+ ld a, [wYCoord]
ld d, a
- ld a, [W_XCOORD]
+ ld a, [wXCoord]
ld e, a
ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
and a
diff --git a/engine/overworld/cinnabar_lab.asm b/engine/overworld/cinnabar_lab.asm
index eefa2176..13313746 100755
--- a/engine/overworld/cinnabar_lab.asm
+++ b/engine/overworld/cinnabar_lab.asm
@@ -1,37 +1,37 @@
-GiveFossilToCinnabarLab: ; 61006 (18:5006)
+GiveFossilToCinnabarLab:
ld hl, wd730
set 6, [hl]
xor a
- ld [wCurrentMenuItem], a ; wCurrentMenuItem
- ld a, $3
- ld [wMenuWatchedKeys], a ; wMenuWatchedKeys
- ld a, [wcd37]
+ ld [wCurrentMenuItem], a
+ ld a, A_BUTTON | B_BUTTON
+ ld [wMenuWatchedKeys], a
+ ld a, [wFilteredBagItemsCount]
dec a
- ld [wMaxMenuItem], a ; wMaxMenuItem
- ld a, $2
- ld [wTopMenuItemY], a ; wTopMenuItemY
- ld a, $1
- ld [wTopMenuItemX], a ; wTopMenuItemX
- ld a, [wcd37]
+ ld [wMaxMenuItem], a
+ ld a, 2
+ ld [wTopMenuItemY], a
+ ld a, 1
+ ld [wTopMenuItemX], a
+ ld a, [wFilteredBagItemsCount]
dec a
- ld bc, $2
- ld hl, $3
+ ld bc, 2
+ ld hl, 3
call AddNTimes
dec l
ld b, l
ld c, $d
- ld hl, wTileMap
+ coord hl, 0, 0
call TextBoxBorder
call UpdateSprites
- call Func_610c2
+ call PrintFossilsInBag
ld hl, wd730
res 6, [hl]
call HandleMenuInput
- bit 1, a
- jr nz, .asm_610a7
- ld hl, wcc5b
- ld a, [wCurrentMenuItem] ; wCurrentMenuItem
- ld d, $0
+ bit 1, a ; pressed B?
+ jr nz, .cancelledGivingFossil
+ ld hl, wFilteredBagItems
+ ld a, [wCurrentMenuItem]
+ ld d, 0
ld e, a
add hl, de
ld a, [hl]
@@ -48,77 +48,76 @@ GiveFossilToCinnabarLab: ; 61006 (18:5006)
.choseDomeFossil
ld b, KABUTO
.fossilSelected
- ld [W_FOSSILITEM], a
+ ld [wFossilItem], a
ld a, b
- ld [W_FOSSILMON], a
+ ld [wFossilMon], a
call LoadFossilItemAndMonName
ld hl, LabFossil_610ae
call PrintText
call YesNoChoice
- ld a, [wCurrentMenuItem] ; wCurrentMenuItem
+ ld a, [wCurrentMenuItem]
and a
- jr nz, .asm_610a7
+ jr nz, .cancelledGivingFossil
ld hl, LabFossil_610b3
call PrintText
- ld a, [W_FOSSILITEM]
- ld [$ffdb], a
+ ld a, [wFossilItem]
+ ld [hItemToRemoveID], a
callba RemoveItemByID
ld hl, LabFossil_610b8
call PrintText
- ld hl, wd7a3
- set 0, [hl]
- set 1, [hl]
+ SetEvents EVENT_GAVE_FOSSIL_TO_LAB, EVENT_LAB_STILL_REVIVING_FOSSIL
ret
-.asm_610a7
+.cancelledGivingFossil
ld hl, LabFossil_610bd
call PrintText
ret
-LabFossil_610ae: ; 610ae (18:50ae)
+LabFossil_610ae:
TX_FAR _Lab4Text_610ae
db "@"
-LabFossil_610b3: ; 610b3 (18:50b3)
+LabFossil_610b3:
TX_FAR _Lab4Text_610b3
db "@"
-LabFossil_610b8: ; 610b8 (18:50b8)
+LabFossil_610b8:
TX_FAR _Lab4Text_610b8
db "@"
-LabFossil_610bd: ; 610bd (18:50bd)
+LabFossil_610bd:
TX_FAR _Lab4Text_610bd
db "@"
-Func_610c2: ; 610c2 (18:50c2)
- ld hl, wcc5b
+PrintFossilsInBag:
+; Prints each fossil in the player's bag on a separate line in the menu.
+ ld hl, wFilteredBagItems
xor a
- ld [$ffdb], a
-.asm_610c8
+ ld [hItemCounter], a
+.loop
ld a, [hli]
cp $ff
ret z
push hl
ld [wd11e], a
call GetItemName
- hlCoord 2, 2
- ld a, [$ffdb]
- ld bc, $28
+ coord hl, 2, 2
+ ld a, [hItemCounter]
+ ld bc, SCREEN_WIDTH * 2
call AddNTimes
ld de, wcd6d
call PlaceString
- ld hl, $ffdb
+ ld hl, hItemCounter
inc [hl]
pop hl
- jr .asm_610c8
+ jr .loop
; loads the names of the fossil item and the resulting mon
-LoadFossilItemAndMonName: ; 610eb (18:50eb)
- ld a, [W_FOSSILMON]
+LoadFossilItemAndMonName:
+ ld a, [wFossilMon]
ld [wd11e], a
call GetMonName
call CopyStringToCF4B
- ld a, [W_FOSSILITEM]
+ ld a, [wFossilItem]
ld [wd11e], a
call GetItemName
ret
diff --git a/engine/overworld/clear_variables.asm b/engine/overworld/clear_variables.asm
new file mode 100644
index 00000000..9a59cc7c
--- /dev/null
+++ b/engine/overworld/clear_variables.asm
@@ -0,0 +1,20 @@
+ClearVariablesOnEnterMap:
+ ld a, SCREEN_HEIGHT_PIXELS
+ ld [hWY], a
+ ld [rWY], a
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a
+ ld [wStepCounter], a
+ ld [wLoneAttackNo], a
+ ld [hJoyPressed], a
+ ld [hJoyReleased], a
+ ld [hJoyHeld], a
+ ld [wActionResultOrTookBattleTurn], a
+ ld [wUnusedD5A3], a
+ ld hl, wCardKeyDoorY
+ ld [hli], a
+ ld [hl], a
+ ld hl, wWhichTrade
+ ld bc, wStandingOnWarpPadOrHole - wWhichTrade
+ call FillMemory
+ ret
diff --git a/engine/overworld/cut.asm b/engine/overworld/cut.asm
index 7b92bca3..f6ae6468 100755
--- a/engine/overworld/cut.asm
+++ b/engine/overworld/cut.asm
@@ -1,43 +1,43 @@
-UsedCut: ; ef54 (3:6f54)
+UsedCut:
xor a
- ld [wcd6a], a
- ld a, [W_CURMAPTILESET] ; W_CURMAPTILESET
+ ld [wActionResultOrTookBattleTurn], a ; initialise to failure value
+ ld a, [wCurMapTileset]
and a ; OVERWORLD
- jr z, .asm_ef6b
+ jr z, .overworld
cp GYM
- jr nz, .asm_ef77
+ jr nz, .nothingToCut
ld a, [wTileInFrontOfPlayer]
cp $50 ; gym cut tree
- jr nz, .asm_ef77
- jr asm_ef82
-.asm_ef6b
+ jr nz, .nothingToCut
+ jr .canCut
+.overworld
dec a
ld a, [wTileInFrontOfPlayer]
cp $3d ; cut tree
- jr z, asm_ef82
+ jr z, .canCut
cp $52 ; grass
- jr z, asm_ef82
-.asm_ef77
- ld hl, NothingToCutText
+ jr z, .canCut
+.nothingToCut
+ ld hl, .NothingToCutText
jp PrintText
-NothingToCutText: ; ef7d (3:6f7d)
+.NothingToCutText
TX_FAR _NothingToCutText
db "@"
-asm_ef82: ; ef82 (3:6f82)
- ld [wcd4d], a
- ld a, $1
- ld [wcd6a], a
- ld a, [wWhichPokemon] ; wWhichPokemon
- ld hl, wPartyMonNicks ; wPartyMonNicks
+.canCut
+ ld [wCutTile], a
+ ld a, 1
+ ld [wActionResultOrTookBattleTurn], a ; used cut
+ ld a, [wWhichPokemon]
+ ld hl, wPartyMonNicks
call GetPartyMonName
ld hl, wd730
set 6, [hl]
call GBPalWhiteOutWithDelay3
call ClearSprites
call RestoreScreenTilesAndReloadTilePatterns
- ld a, $90
+ ld a, SCREEN_HEIGHT_PIXELS
ld [hWY], a
call Delay3
call LoadGBPal
@@ -53,79 +53,80 @@ asm_ef82: ; ef82 (3:6f82)
res 6, [hl]
ld a, $ff
ld [wUpdateSpritesEnabled], a
- call AnimateCutTree
- ld de, CutTreeBlockSwaps ; $7100
- call Func_f09f
+ call InitCutAnimOAM
+ ld de, CutTreeBlockSwaps
+ call ReplaceTreeTileBlock
call RedrawMapView
- callba Func_79e96
+ callba AnimCut
ld a, $1
ld [wUpdateSpritesEnabled], a
- ld a, (SFX_02_56 - SFX_Headers_02) / 3
+ ld a, SFX_CUT
call PlaySound
ld a, $90
ld [hWY], a
call UpdateSprites
jp RedrawMapView
-UsedCutText: ; eff2 (3:6ff2)
+UsedCutText:
TX_FAR _UsedCutText
db "@"
-AnimateCutTree: ; eff7 (3:6ff7)
+InitCutAnimOAM:
xor a
- ld [wcd50], a
- ld a, $e4
- ld [rOBP1], a ; $ff49
- ld a, [wcd4d]
+ ld [wWhichAnimationOffsets], a
+ ld a, %11100100
+ ld [rOBP1], a
+ ld a, [wCutTile]
cp $52
- jr z, .asm_f020
- ld de, Overworld_GFX + $2d0 ; $42d0 ; cuttable tree sprite top row
+ jr z, .grass
+; tree
+ ld de, Overworld_GFX + $2d0 ; cuttable tree sprite top row
ld hl, vChars1 + $7c0
- ld bc, (BANK(Overworld_GFX) << 8) + $02
+ lb bc, BANK(Overworld_GFX), $02
call CopyVideoData
- ld de, Overworld_GFX + $3d0 ; $43d0 ; cuttable tree sprite bottom row
+ ld de, Overworld_GFX + $3d0 ; cuttable tree sprite bottom row
ld hl, vChars1 + $7e0
- ld bc, (BANK(Overworld_GFX) << 8) + $02
+ lb bc, BANK(Overworld_GFX), $02
call CopyVideoData
- jr WriteCutTreeBoulderDustAnimationOAMBlock
-.asm_f020
+ jr WriteCutOrBoulderDustAnimationOAMBlock
+.grass
ld hl, vChars1 + $7c0
- call LoadCutTreeAnimationTilePattern
+ call LoadCutGrassAnimationTilePattern
ld hl, vChars1 + $7d0
- call LoadCutTreeAnimationTilePattern
+ call LoadCutGrassAnimationTilePattern
ld hl, vChars1 + $7e0
- call LoadCutTreeAnimationTilePattern
+ call LoadCutGrassAnimationTilePattern
ld hl, vChars1 + $7f0
- call LoadCutTreeAnimationTilePattern
- call WriteCutTreeBoulderDustAnimationOAMBlock
+ call LoadCutGrassAnimationTilePattern
+ call WriteCutOrBoulderDustAnimationOAMBlock
ld hl, wOAMBuffer + $93
- ld de, $4
+ ld de, 4
ld a, $30
ld c, e
-.asm_f044
+.loop
ld [hl], a
add hl, de
xor $60
dec c
- jr nz, .asm_f044
+ jr nz, .loop
ret
-LoadCutTreeAnimationTilePattern: ; f04c (3:704c)
- ld de, AnimationTileset2 + $60 ; $474e ; tile depicting a leaf
- ld bc, (BANK(AnimationTileset2) << 8) + $01
+LoadCutGrassAnimationTilePattern:
+ ld de, AnimationTileset2 + $60 ; tile depicting a leaf
+ lb bc, BANK(AnimationTileset2), $01
jp CopyVideoData
-WriteCutTreeBoulderDustAnimationOAMBlock: ; f055 (3:7055)
- call GetCutTreeBoulderDustAnimationOffsets
+WriteCutOrBoulderDustAnimationOAMBlock:
+ call GetCutOrBoulderDustAnimationOffsets
ld a, $9
- ld de, CutTreeBoulderDustAnimationTilesAndAttributes
+ ld de, CutOrBoulderDustAnimationTilesAndAttributes
jp WriteOAMBlock
-CutTreeBoulderDustAnimationTilesAndAttributes: ; f060 (3:7060)
+CutOrBoulderDustAnimationTilesAndAttributes:
db $FC,$10,$FD,$10
db $FE,$10,$FF,$10
-GetCutTreeBoulderDustAnimationOffsets: ; f068 (3:7068)
+GetCutOrBoulderDustAnimationOffsets:
ld hl, wSpriteStateData1 + 4
ld a, [hli] ; player's sprite screen Y position
ld b, a
@@ -138,12 +139,12 @@ GetCutTreeBoulderDustAnimationOffsets: ; f068 (3:7068)
srl a
ld e, a
ld d, $0 ; de holds direction (00: down, 02: up, 04: left, 06: right)
- ld a, [wcd50]
+ ld a, [wWhichAnimationOffsets]
and a
- ld hl, CutTreeAnimationOffsets
- jr z, .asm_f084
+ ld hl, CutAnimationOffsets
+ jr z, .next
ld hl, BoulderDustAnimationOffsets
-.asm_f084
+.next
add hl, de
ld e, [hl]
inc hl
@@ -156,14 +157,14 @@ GetCutTreeBoulderDustAnimationOffsets: ; f068 (3:7068)
ld c, a
ret
-CutTreeAnimationOffsets: ; f08f (3:708f)
+CutAnimationOffsets:
; 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
-BoulderDustAnimationOffsets: ; f097 (3:7097)
+BoulderDustAnimationOffsets:
; 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
@@ -171,79 +172,83 @@ BoulderDustAnimationOffsets: ; f097 (3:7097)
db -24, 20 ; player is facing left
db 40, 20 ; player is facing right
-Func_f09f: ; f09f (3:709f)
+ReplaceTreeTileBlock:
+; Determine the address of the tile block that contains the tile in front of the
+; player (i.e. where the tree is) and replace it with the corresponding tile
+; block that doesn't have the tree.
push de
- ld a, [W_CURMAPWIDTH] ; wd369
- add $6
+ ld a, [wCurMapWidth]
+ add 6
ld c, a
- ld b, $0
- ld d, $0
+ ld b, 0
+ ld d, 0
ld hl, wCurrentTileBlockMapViewPointer
ld a, [hli]
ld h, [hl]
ld l, a
add hl, bc
- ld a, [wSpriteStateData1 + 9]
+ ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction
and a
- jr z, .asm_f0c7
- cp $4
- jr z, .asm_f0cf
- cp $8
- jr z, .asm_f0d7
- ld a, [W_XBLOCKCOORD] ; wd364
+ jr z, .down
+ cp SPRITE_FACING_UP
+ jr z, .up
+ cp SPRITE_FACING_LEFT
+ jr z, .left
+; right
+ ld a, [wXBlockCoord]
and a
- jr z, .asm_f0e0
- jr .asm_f0ec
-.asm_f0c7
- ld a, [W_YBLOCKCOORD] ; wd363
+ jr z, .centerTileBlock
+ jr .rightOfCenter
+.down
+ ld a, [wYBlockCoord]
and a
- jr z, .asm_f0e0
- jr .asm_f0df
-.asm_f0cf
- ld a, [W_YBLOCKCOORD] ; wd363
+ jr z, .centerTileBlock
+ jr .belowCenter
+.up
+ ld a, [wYBlockCoord]
and a
- jr z, .asm_f0e1
- jr .asm_f0e0
-.asm_f0d7
- ld a, [W_XBLOCKCOORD] ; wd364
+ jr z, .aboveCenter
+ jr .centerTileBlock
+.left
+ ld a, [wXBlockCoord]
and a
- jr z, .asm_f0e6
- jr .asm_f0e0
-.asm_f0df
+ jr z, .leftOfCenter
+ jr .centerTileBlock
+.belowCenter
add hl, bc
-.asm_f0e0
+.centerTileBlock
add hl, bc
-.asm_f0e1
+.aboveCenter
ld e, $2
add hl, de
- jr .asm_f0f0
-.asm_f0e6
+ jr .next
+.leftOfCenter
ld e, $1
add hl, bc
add hl, de
- jr .asm_f0f0
-.asm_f0ec
+ jr .next
+.rightOfCenter
ld e, $3
add hl, bc
add hl, de
-.asm_f0f0
+.next
pop de
ld a, [hl]
ld c, a
-.asm_f0f3
+.loop ; find the matching tile block in the array
ld a, [de]
inc de
inc de
cp $ff
ret z
cp c
- jr nz, .asm_f0f3
+ jr nz, .loop
dec de
- ld a, [de]
+ ld a, [de] ; replacement tile block from matching array entry
ld [hl], a
ret
-CutTreeBlockSwaps: ; f100 (3:7100)
+CutTreeBlockSwaps:
; first byte = tileset block containing the cut tree
; second byte = corresponding tileset block after the cut animation happens
db $32, $6D
diff --git a/engine/overworld/cut2.asm b/engine/overworld/cut2.asm
index de2b9d55..f16fed66 100755
--- a/engine/overworld/cut2.asm
+++ b/engine/overworld/cut2.asm
@@ -1,89 +1,89 @@
-Func_79e96: ; 79e96 (1e:5e96)
- ld a, [wcd4d]
+AnimCut:
+ ld a, [wCutTile]
cp $52
- jr z, .asm_79ec8
+ jr z, .grass
ld c, $8
-.asm_79e9f
+.cutTreeLoop
push bc
ld hl, wOAMBuffer + $91
- ld a, $1
- ld [wd08a], a
- ld c, $2
+ ld a, 1
+ ld [wCoordAdjustmentAmount], a
+ ld c, 2
call AdjustOAMBlockXPos2
ld hl, wOAMBuffer + $99
- ld a, $ff
- ld [wd08a], a
- ld c, $2
+ ld a, -1
+ ld [wCoordAdjustmentAmount], a
+ ld c, 2
call AdjustOAMBlockXPos2
- ld a, [rOBP1] ; $ff49
+ ld a, [rOBP1]
xor $64
- ld [rOBP1], a ; $ff49
+ ld [rOBP1], a
call DelayFrame
pop bc
dec c
- jr nz, .asm_79e9f
+ jr nz, .cutTreeLoop
ret
-.asm_79ec8
- ld c, $2
-.asm_79eca
+.grass
+ ld c, 2
+.cutGrassLoop
push bc
ld c, $8
- call Func_79eed
- call Func_79f30
+ call AnimCutGrass_UpdateOAMEntries
+ call AnimCutGrass_SwapOAMEntries
ld c, $8
- call Func_79eed
- call Func_79f30
+ call AnimCutGrass_UpdateOAMEntries
+ call AnimCutGrass_SwapOAMEntries
ld hl, wOAMBuffer + $90
- ld a, $2
- ld [wd08a], a
- ld c, $4
+ ld a, 2
+ ld [wCoordAdjustmentAmount], a
+ ld c, 4
call AdjustOAMBlockYPos2
pop bc
dec c
- jr nz, .asm_79eca
+ jr nz, .cutGrassLoop
ret
-Func_79eed: ; 79eed (1e:5eed)
+AnimCutGrass_UpdateOAMEntries:
push bc
ld hl, wOAMBuffer + $91
- ld a, $1
- ld [wd08a], a
- ld c, $1
+ ld a, 1
+ ld [wCoordAdjustmentAmount], a
+ ld c, 1
call AdjustOAMBlockXPos2
ld hl, wOAMBuffer + $95
- ld a, $2
- ld [wd08a], a
- ld c, $1
+ ld a, 2
+ ld [wCoordAdjustmentAmount], a
+ ld c, 1
call AdjustOAMBlockXPos2
ld hl, wOAMBuffer + $99
- ld a, $fe
- ld [wd08a], a
- ld c, $1
+ ld a, -2
+ ld [wCoordAdjustmentAmount], a
+ ld c, 1
call AdjustOAMBlockXPos2
ld hl, wOAMBuffer + $9d
- ld a, $ff
- ld [wd08a], a
- ld c, $1
+ ld a, -1
+ ld [wCoordAdjustmentAmount], a
+ ld c, 1
call AdjustOAMBlockXPos2
- ld a, [rOBP1] ; $ff49
+ ld a, [rOBP1]
xor $64
- ld [rOBP1], a ; $ff49
+ ld [rOBP1], a
call DelayFrame
pop bc
dec c
- jr nz, Func_79eed
+ jr nz, AnimCutGrass_UpdateOAMEntries
ret
-Func_79f30: ; 79f30 (1e:5f30)
+AnimCutGrass_SwapOAMEntries:
ld hl, wOAMBuffer + $90
- ld de, wHPBarMaxHP
+ ld de, wBuffer
ld bc, $8
call CopyData
ld hl, wOAMBuffer + $98
ld de, wOAMBuffer + $90
ld bc, $8
call CopyData
- ld hl, wHPBarMaxHP
+ ld hl, wBuffer
ld de, wOAMBuffer + $98
ld bc, $8
jp CopyData
diff --git a/engine/overworld/daycare_exp.asm b/engine/overworld/daycare_exp.asm
new file mode 100644
index 00000000..dbe4023a
--- /dev/null
+++ b/engine/overworld/daycare_exp.asm
@@ -0,0 +1,18 @@
+IncrementDayCareMonExp:
+ ld a, [wDayCareInUse]
+ and a
+ ret z
+ ld hl, wDayCareMonExp + 2
+ inc [hl]
+ ret nz
+ dec hl
+ inc [hl]
+ ret nz
+ dec hl
+ inc [hl]
+ ld a, [hl]
+ cp $50
+ ret c
+ ld a, $50
+ ld [hl], a
+ ret
diff --git a/engine/overworld/doors.asm b/engine/overworld/doors.asm
index ac345af9..c39e096d 100755
--- a/engine/overworld/doors.asm
+++ b/engine/overworld/doors.asm
@@ -1,8 +1,8 @@
; returns whether the player is standing on a door tile in carry
-IsPlayerStandingOnDoorTile: ; 1a609 (6:6609)
+IsPlayerStandingOnDoorTile:
push de
- ld hl, DoorTileIDPointers ; $662c
- ld a, [W_CURMAPTILESET] ; W_CURMAPTILESET
+ ld hl, DoorTileIDPointers
+ ld a, [wCurMapTileset]
ld de, $3
call IsInArray
pop de
@@ -25,64 +25,51 @@ IsPlayerStandingOnDoorTile: ; 1a609 (6:6609)
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
+DoorTileIDPointers:
+ dbw OVERWORLD, OverworldDoorTileIDs
+ dbw FOREST, ForestDoorTileIDs
+ dbw MART, MartDoorTileIDs
+ dbw HOUSE, HouseDoorTileIDs
+ dbw FOREST_GATE, TilesetMuseumDoorTileIDs
+ dbw MUSEUM, TilesetMuseumDoorTileIDs
+ dbw GATE, TilesetMuseumDoorTileIDs
+ dbw SHIP, ShipDoorTileIDs
+ dbw LOBBY, LobbyDoorTileIDs
+ dbw MANSION, MansionDoorTileIDs
+ dbw LAB, LabDoorTileIDs
+ dbw FACILITY, FacilityDoorTileIDs
+ dbw PLATEAU, PlateauDoorTileIDs
db $ff
-OverworldDoorTileIDs: ; 1a654 (6:6654)
+OverworldDoorTileIDs:
db $1B,$58,$00
-ForestDoorTileIDs: ; 1a657 (6:6657)
+ForestDoorTileIDs:
db $3a,$00
-MartDoorTileIDs: ; 1a659 (6:6659)
+MartDoorTileIDs:
db $5e,$00
-HouseDoorTileIDs: ; 1a65b (6:665b)
+HouseDoorTileIDs:
db $54,$00
-TilesetMuseumDoorTileIDs: ; 1a65d (6:665d)
+TilesetMuseumDoorTileIDs:
db $3b,$00
-ShipDoorTileIDs: ; 1a65f (6:665f)
+ShipDoorTileIDs:
db $1e,$00
-LobbyDoorTileIDs: ; 1a661 (6:6661)
+LobbyDoorTileIDs:
db $1c,$38,$1a,$00
-MansionDoorTileIDs: ; 1a665 (6:6665)
+MansionDoorTileIDs:
db $1a,$1c,$53,$00
-LabDoorTileIDs: ; 1a669 (6:6669)
+LabDoorTileIDs:
db $34,$00
-FacilityDoorTileIDs: ; 1a66b (6:666b)
+FacilityDoorTileIDs:
db $43,$58,$1b,$00
-PlateauDoorTileIDs: ; 1a66f (6:666f)
+PlateauDoorTileIDs:
db $3b,$1b,$00
diff --git a/engine/overworld/elevator.asm b/engine/overworld/elevator.asm
index 3a23d410..7ff4ff71 100755
--- a/engine/overworld/elevator.asm
+++ b/engine/overworld/elevator.asm
@@ -1,46 +1,48 @@
-ShakeElevator: ; 7bf15 (1e:7f15)
- ld de, $ffe0
- call Func_7bf64
- ld de, $240
- call Func_7bf64
+ShakeElevator:
+ ld de, -$20
+ call ShakeElevatorRedrawRow
+ ld de, SCREEN_HEIGHT * $20
+ call ShakeElevatorRedrawRow
call Delay3
ld a, $ff
call PlaySound
ld a, [hSCY]
ld d, a
ld e, $1
- ; number of times to play collision sfx
- ld b, $64
-.asm_7bf30
+ ld b, 100
+.shakeLoop ; scroll the BG up and down and play a sound effect
ld a, e
xor $fe
ld e, a
add d
ld [hSCY], a
push bc
- ld c, BANK(SFX_02_5b)
- ld a, (SFX_02_5b - SFX_Headers_02) / 3
+ ld c, BANK(SFX_Collision_1)
+ ld a, SFX_COLLISION
call PlayMusic
pop bc
- ld c, $2
+ ld c, 2
call DelayFrames
dec b
- jr nz, .asm_7bf30
+ jr nz, .shakeLoop
ld a, d
ld [hSCY], a
ld a, $ff
call PlaySound
- ld c, BANK(SFX_02_5f)
- ld a, (SFX_02_5f - SFX_Headers_02) / 3
+ ld c, BANK(SFX_Safari_Zone_PA)
+ ld a, SFX_SAFARI_ZONE_PA
call PlayMusic
-.asm_7bf57
- ld a, [wc02a]
- cp $b9
- jr z, .asm_7bf57
+.musicLoop
+ ld a, [wChannelSoundIDs + Ch4]
+ cp SFX_SAFARI_ZONE_PA
+ jr z, .musicLoop
call UpdateSprites
jp PlayDefaultMusic
-Func_7bf64: ; 7bf64 (1e:7f64)
+ShakeElevatorRedrawRow:
+; This function is used to redraw certain portions of the screen, but it does
+; not appear to ever result in any visible effect, so this function seems to
+; be pointless.
ld hl, wMapViewVRAMPointer + 1
ld a, [hld]
push af
@@ -54,7 +56,7 @@ Func_7bf64: ; 7bf64 (1e:7f64)
add hl, de
ld a, h
and $3
- or $98
+ or vBGMap0 / $100
ld d, a
ld a, l
pop hl
diff --git a/engine/overworld/emotion_bubbles.asm b/engine/overworld/emotion_bubbles.asm
index 7106063b..ac4276bd 100755
--- a/engine/overworld/emotion_bubbles.asm
+++ b/engine/overworld/emotion_bubbles.asm
@@ -1,30 +1,33 @@
-EmotionBubble: ; 17c47 (5:7c47)
- ld a, [wcd50]
+EmotionBubble:
+ ld a, [wWhichEmotionBubble]
ld c, a
- ld b, $0
- ld hl, EmotionBubblesPointerTable ; $7caf
+ ld b, 0
+ ld hl, EmotionBubblesPointerTable
add hl, bc
add hl, bc
ld e, [hl]
inc hl
ld d, [hl]
ld hl, vChars1 + $780
- ld bc, (BANK(EmotionBubblesPointerTable) << 8) + $04
+ lb bc, BANK(EmotionBubbles), $04
call CopyVideoData
ld a, [wUpdateSpritesEnabled]
push af
ld a, $ff
ld [wUpdateSpritesEnabled], a
ld a, [wd736]
- bit 6, a
- ld hl, wOAMBuffer + $8f
- ld de, wOAMBuffer + $9f
- jr z, .asm_17c7a
- ld hl, wOAMBuffer + $7f
- ld de, wOAMBuffer + $8f
-.asm_17c7a
+ bit 6, a ; are the last 4 OAM entries reserved for a shadow or fishing rod?
+ ld hl, wOAMBuffer + 4 * 35 + $3 ; $8f
+ ld de, wOAMBuffer + 4 * 39 + $3 ; $9f
+ jr z, .next
+ ld hl, wOAMBuffer + 4 * 31 + $3 ; $7f
+ ld de, wOAMBuffer + 4 * 35 + $3 ; $8f
+
+; Copy OAM data 16 bytes forward to make room for emotion bubble OAM data at the
+; start of the OAM buffer.
+.next
ld bc, $90
-.asm_17c7d
+.loop
ld a, [hl]
ld [de], a
dec hl
@@ -32,12 +35,14 @@ EmotionBubble: ; 17c47 (5:7c47)
dec bc
ld a, c
or b
- jr nz, .asm_17c7d
+ jr nz, .loop
+
+; get the screen coordinates of the sprite the bubble is to be displayed above
ld hl, wSpriteStateData1 + 4
- ld a, [wcd4f]
+ ld a, [wEmotionBubbleSpriteIndex]
swap a
ld c, a
- ld b, $0
+ ld b, 0
add hl, bc
ld a, [hli]
ld b, a
@@ -45,24 +50,25 @@ EmotionBubble: ; 17c47 (5:7c47)
ld a, [hl]
add $8
ld c, a
- ld de, EmotionBubblesOAM ; $7cb5
+
+ ld de, EmotionBubblesOAM
xor a
call WriteOAMBlock
- ld c, $3c
+ ld c, 60
call DelayFrames
pop af
ld [wUpdateSpritesEnabled], a
call DelayFrame
jp UpdateSprites
-EmotionBubblesPointerTable: ; 17caf (5:7caf)
+EmotionBubblesPointerTable:
dw EmotionBubbles
dw EmotionBubbles + $40
dw EmotionBubbles + $80
-EmotionBubblesOAM: ; 17cb5 (5:7cb5)
+EmotionBubblesOAM:
db $F8,$00,$F9,$00
db $FA,$00,$FB,$00
-EmotionBubbles: ; 17cbd (5:7cbd)
+EmotionBubbles:
INCBIN "gfx/emotion_bubbles.2bpp"
diff --git a/engine/overworld/field_move_messages.asm b/engine/overworld/field_move_messages.asm
new file mode 100644
index 00000000..69914bfc
--- /dev/null
+++ b/engine/overworld/field_move_messages.asm
@@ -0,0 +1,57 @@
+PrintStrengthTxt:
+ ld hl, wd728
+ set 0, [hl]
+ ld hl, UsedStrengthText
+ call PrintText
+ ld hl, CanMoveBouldersText
+ jp PrintText
+
+UsedStrengthText:
+ TX_FAR _UsedStrengthText
+ TX_ASM
+ ld a, [wcf91]
+ call PlayCry
+ call Delay3
+ jp TextScriptEnd
+
+CanMoveBouldersText:
+ TX_FAR _CanMoveBouldersText
+ db "@"
+
+IsSurfingAllowed:
+; Returns whether surfing is allowed in bit 1 of wd728.
+; Surfing isn't allowed on the Cycling Road or in the lowest level of the
+; Seafoam Islands before the current has been slowed with boulders.
+ ld hl, wd728
+ set 1, [hl]
+ ld a, [wd732]
+ bit 5, a
+ jr nz, .forcedToRideBike
+ ld a, [wCurMap]
+ cp SEAFOAM_ISLANDS_5
+ ret nz
+ CheckBothEventsSet EVENT_SEAFOAM4_BOULDER1_DOWN_HOLE, EVENT_SEAFOAM4_BOULDER2_DOWN_HOLE
+ ret z
+ ld hl, CoordsData_cdf7
+ call ArePlayerCoordsInArray
+ ret nc
+ ld hl, wd728
+ res 1, [hl]
+ ld hl, CurrentTooFastText
+ jp PrintText
+.forcedToRideBike
+ ld hl, wd728
+ res 1, [hl]
+ ld hl, CyclingIsFunText
+ jp PrintText
+
+CoordsData_cdf7:
+ db $0B,$07,$FF
+
+CurrentTooFastText:
+ TX_FAR _CurrentTooFastText
+ db "@"
+
+CyclingIsFunText:
+ TX_FAR _CyclingIsFunText
+ db "@"
diff --git a/engine/overworld/healing_machine.asm b/engine/overworld/healing_machine.asm
index 90d306c3..38a44cfb 100755
--- a/engine/overworld/healing_machine.asm
+++ b/engine/overworld/healing_machine.asm
@@ -1,71 +1,71 @@
-AnimateHealingMachine: ; 70433 (1c:4433)
- ld de, PokeCenterFlashingMonitorAndHealBall ; $44b7
+AnimateHealingMachine:
+ ld de, PokeCenterFlashingMonitorAndHealBall
ld hl, vChars0 + $7c0
- ld bc, (BANK(PokeCenterFlashingMonitorAndHealBall) << 8) + $03
+ lb bc, BANK(PokeCenterFlashingMonitorAndHealBall), $03 ; loads one too many tiles
call CopyVideoData
ld hl, wUpdateSpritesEnabled
ld a, [hl]
push af
ld [hl], $ff
push hl
- ld a, [rOBP1] ; $ff49
+ ld a, [rOBP1]
push af
ld a, $e0
- ld [rOBP1], a ; $ff49
+ ld [rOBP1], a
ld hl, wOAMBuffer + $84
- ld de, PokeCenterOAMData ; $44d7
- call Func_70503
- ld a, $4
- ld [wMusicHeaderPointer], a
+ ld de, PokeCenterOAMData
+ call CopyHealingMachineOAM
+ ld a, 4
+ ld [wAudioFadeOutControl], a
ld a, $ff
- ld [wc0ee], a
+ ld [wNewSoundID], a
call PlaySound
-.asm_70464
- ld a, [wMusicHeaderPointer]
- and a
- jr nz, .asm_70464
- ld a, [wPartyCount] ; wPartyCount
+.waitLoop
+ ld a, [wAudioFadeOutControl]
+ and a ; is fade-out finished?
+ jr nz, .waitLoop ; if not, check again
+ ld a, [wPartyCount]
ld b, a
-.asm_7046e
- call Func_70503
- ld a, (SFX_02_4a - SFX_Headers_02) / 3
+.partyLoop
+ call CopyHealingMachineOAM
+ ld a, SFX_HEALING_MACHINE
call PlaySound
- ld c, $1e
+ ld c, 30
call DelayFrames
dec b
- jr nz, .asm_7046e
- ld a, [wc0ef]
- cp $1f
- ld [wc0f0], a
- jr nz, .asm_70495
+ jr nz, .partyLoop
+ ld a, [wAudioROMBank]
+ cp BANK(Audio3_UpdateMusic)
+ ld [wAudioSavedROMBank], a
+ jr nz, .next
ld a, $ff
- ld [wc0ee], a
+ ld [wNewSoundID], a
call PlaySound
ld a, BANK(Music_PkmnHealed)
- ld [wc0ef], a
-.asm_70495
+ ld [wAudioROMBank], a
+.next
ld a, MUSIC_PKMN_HEALED
- ld [wc0ee], a
+ ld [wNewSoundID], a
call PlaySound
ld d, $28
call FlashSprite8Times
-.asm_704a2
- ld a, [wc026]
- cp MUSIC_PKMN_HEALED
- jr z, .asm_704a2
- ld c, $20
+.waitLoop2
+ ld a, [wChannelSoundIDs]
+ cp MUSIC_PKMN_HEALED ; is the healed music still playing?
+ jr z, .waitLoop2 ; if so, check gain
+ ld c, 32
call DelayFrames
pop af
- ld [rOBP1], a ; $ff49
+ ld [rOBP1], a
pop hl
pop af
ld [hl], a
jp UpdateSprites
-PokeCenterFlashingMonitorAndHealBall: ; 704b7 (1c:44b7)
+PokeCenterFlashingMonitorAndHealBall:
INCBIN "gfx/pokecenter_ball.2bpp"
-PokeCenterOAMData: ; 704d7 (1c:44d7)
+PokeCenterOAMData:
db $24,$34,$7C,$10 ; heal machine monitor
db $2B,$30,$7D,$10 ; pokeballs 1-6
db $2B,$38,$7D,$30
@@ -75,7 +75,7 @@ PokeCenterOAMData: ; 704d7 (1c:44d7)
db $35,$38,$7D,$30
; d = value to xor with palette
-FlashSprite8Times: ; 704f3 (1c:44f3)
+FlashSprite8Times:
ld b, 8
.loop
ld a, [rOBP1]
@@ -87,7 +87,8 @@ FlashSprite8Times: ; 704f3 (1c:44f3)
jr nz, .loop
ret
-Func_70503: ; 70503 (1c:4503)
+CopyHealingMachineOAM:
+; copy one OAM entry and advance the pointers
ld a, [de]
inc de
ld [hli], a
diff --git a/engine/overworld/hidden_items.asm b/engine/overworld/hidden_items.asm
index 17288a17..32783f83 100755
--- a/engine/overworld/hidden_items.asm
+++ b/engine/overworld/hidden_items.asm
@@ -1,45 +1,43 @@
-HiddenItems: ; 76688 (1d:6688)
+HiddenItems:
ld hl, HiddenItemCoords
- call Func_76857
- ld [wTrainerScreenX], a
- ld hl, wd6f0
- ld a, [wTrainerScreenX]
+ call FindHiddenItemOrCoinsIndex
+ ld [wHiddenItemOrCoinsIndex], a
+ ld hl, wObtainedHiddenItemsFlags
+ ld a, [wHiddenItemOrCoinsIndex]
ld c, a
- ld b, $2
+ ld b, FLAG_TEST
predef FlagActionPredef
ld a, c
and a
ret nz
call EnableAutoTextBoxDrawing
- ld a, $1
+ ld a, 1
ld [wDoNotWaitForButtonPressAfterDisplayingText], a
- ld a, [wWhichTrade] ; item ID
+ ld a, [wHiddenObjectFunctionArgument] ; item ID
ld [wd11e], a
call GetItemName
- ld a, $24
- jp PrintPredefTextID
+ tx_pre_jump FoundHiddenItemText
INCLUDE "data/hidden_item_coords.asm"
-FoundHiddenItemText: ; 7675b (1d:675b)
-; XXX where is the pointer to this?
+FoundHiddenItemText:
TX_FAR _FoundHiddenItemText
- db $8
- ld a, [wWhichTrade] ; item ID
+ TX_ASM
+ ld a, [wHiddenObjectFunctionArgument] ; item ID
ld b, a
ld c, 1
call GiveItem
- jr nc, .BagFull
- ld hl, wd6f0
- ld a, [wTrainerScreenX]
+ jr nc, .bagFull
+ ld hl, wObtainedHiddenItemsFlags
+ ld a, [wHiddenItemOrCoinsIndex]
ld c, a
- ld b, $1
+ ld b, FLAG_SET
predef FlagActionPredef
- ld a, (SFX_02_3b - SFX_Headers_02) / 3
- call PlaySoundWaitForCurrent ; play sound
- call WaitForSoundToFinish ; wait for sound to finish playing
+ ld a, SFX_GET_ITEM_2
+ call PlaySoundWaitForCurrent
+ call WaitForSoundToFinish
jp TextScriptEnd
-.BagFull
+.bagFull
call WaitForTextScrollButtonPress ; wait for button press
xor a
ld [wDoNotWaitForButtonPressAfterDisplayingText], a
@@ -47,116 +45,117 @@ FoundHiddenItemText: ; 7675b (1d:675b)
call PrintText
jp TextScriptEnd
-HiddenItemBagFullText: ; 76794 (1d:6794)
+HiddenItemBagFullText:
TX_FAR _HiddenItemBagFullText
db "@"
-HiddenCoins: ; 76799 (1d:6799)
+HiddenCoins:
ld b, COIN_CASE
- predef IsItemInBag_
+ predef GetQuantityOfItemInBag
ld a, b
and a
ret z
ld hl, HiddenCoinCoords
- call Func_76857
- ld [wTrainerScreenX], a
- ld hl, wd6fe
- ld a, [wTrainerScreenX]
+ call FindHiddenItemOrCoinsIndex
+ ld [wHiddenItemOrCoinsIndex], a
+ ld hl, wObtainedHiddenCoinsFlags
+ ld a, [wHiddenItemOrCoinsIndex]
ld c, a
- ld b, $2
+ ld b, FLAG_TEST
predef FlagActionPredef
ld a, c
and a
ret nz
xor a
- ld [$ff9f], a
- ld [$ffa0], a
- ld [$ffa1], a
- ld a, [wWhichTrade]
+ ld [hUnusedCoinsByte], a
+ ld [hCoins], a
+ ld [hCoins + 1], a
+ ld a, [wHiddenObjectFunctionArgument]
sub COIN
cp 10
jr z, .bcd10
cp 20
jr z, .bcd20
cp 40
- jr z, .bcd20
+ jr z, .bcd20 ; should be bcd40
jr .bcd100
.bcd10
ld a, $10
- ld [$ffa1], a
- jr .bcddone
+ ld [hCoins + 1], a
+ jr .bcdDone
.bcd20
ld a, $20
- ld [$ffa1], a
- jr .bcddone
+ ld [hCoins + 1], a
+ jr .bcdDone
.bcd40 ; due to a typo, this is never used
ld a, $40
- ld [$ffa1], a
- jr .bcddone
+ ld [hCoins + 1], a
+ jr .bcdDone
.bcd100
ld a, $1
- ld [$ffa0], a
-.bcddone
+ ld [hCoins], a
+.bcdDone
ld de, wPlayerCoins + 1
- ld hl, $ffa1
+ ld hl, hCoins + 1
ld c, $2
predef AddBCDPredef
- ld hl, wd6fe
- ld a, [wTrainerScreenX]
+ ld hl, wObtainedHiddenCoinsFlags
+ ld a, [wHiddenItemOrCoinsIndex]
ld c, a
- ld b, $1
+ ld b, FLAG_SET
predef FlagActionPredef
call EnableAutoTextBoxDrawing
ld a, [wPlayerCoins]
cp $99
- jr nz, .RoomInCoinCase
+ jr nz, .roomInCoinCase
ld a, [wPlayerCoins + 1]
cp $99
- jr nz, .RoomInCoinCase
- ld a, $2c
+ jr nz, .roomInCoinCase
+ tx_pre_id DroppedHiddenCoinsText
jr .done
-.RoomInCoinCase
- ld a, $2b
+.roomInCoinCase
+ tx_pre_id FoundHiddenCoinsText
.done
jp PrintPredefTextID
INCLUDE "data/hidden_coins.asm"
-FoundHiddenCoinsText: ; 76847 (1d:6847)
+FoundHiddenCoinsText:
TX_FAR _FoundHiddenCoinsText
- db $10,"@"
+ TX_SFX_ITEM_2
+ db "@"
-DroppedHiddenCoinsText: ; 7684d (1d:684d)
+DroppedHiddenCoinsText:
TX_FAR _FoundHiddenCoins2Text
- db $10
+ TX_SFX_ITEM_2
TX_FAR _DroppedHiddenCoinsText
db "@"
-Func_76857: ; 76857 (1d:6857)
- ld a, [wTrainerScreenY]
+FindHiddenItemOrCoinsIndex:
+ ld a, [wHiddenObjectY]
ld d, a
- ld a, [wTrainerScreenX]
+ ld a, [wHiddenObjectX]
ld e, a
- ld a, [W_CURMAP]
+ ld a, [wCurMap]
ld b, a
- ld c, $ff
+ ld c, -1
.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
+ jr nz, .next1
ld a, [hli]
cp d
- jr nz, .asm_76878 ; 0x7686f $7
+ jr nz, .next2
ld a, [hli]
cp e
jr nz, .loop
ld a, c
ret
-.asm_76877
+.next1
inc hl
-.asm_76878
+.next2
inc hl
jr .loop
diff --git a/engine/overworld/hidden_objects.asm b/engine/overworld/hidden_objects.asm
index ae67aeed..dcdf8537 100755
--- a/engine/overworld/hidden_objects.asm
+++ b/engine/overworld/hidden_objects.asm
@@ -1,4 +1,4 @@
-Func_46981: ; 46981 (11:6981)
+IsPlayerOnDungeonWarp:
xor a
ld [wWhichDungeonWarp], a
ld a, [wd72d]
@@ -6,7 +6,7 @@ Func_46981: ; 46981 (11:6981)
ret nz
call ArePlayerCoordsInArray
ret nc
- ld a, [wWhichTrade]
+ ld a, [wCoordIndex]
ld [wWhichDungeonWarp], a
ld hl, wd72d
set 4, [hl]
@@ -15,7 +15,7 @@ Func_46981: ; 46981 (11:6981)
ret
; if a hidden object was found, stores $00 in [$ffee], else stores $ff
-CheckForHiddenObject: ; 469a0 (11:69a0)
+CheckForHiddenObject:
ld hl, $ffeb
xor a
ld [hli], a
@@ -29,7 +29,7 @@ CheckForHiddenObject: ; 469a0 (11:69a0)
ld b, a
cp $ff
jr z, .noMatch
- ld a, [W_CURMAP]
+ ld a, [wCurMap]
cp b
jr z, .foundMatchingMap
inc de
@@ -58,7 +58,7 @@ CheckForHiddenObject: ; 469a0 (11:69a0)
ld [wHiddenObjectX], a
ld c, a
call CheckIfCoordsInFrontOfPlayerMatch
- ld a, [$ffea]
+ ld a, [hCoordsInFrontOfPlayerMatch]
and a
jr z, .foundMatchingObject
inc hl
@@ -85,8 +85,8 @@ CheckForHiddenObject: ; 469a0 (11:69a0)
ret
; checks if the coordinates in front of the player's sprite match Y in b and X in c
-; [$ffea] = $00 if they match, $ff if they don't match
-CheckIfCoordsInFrontOfPlayerMatch: ; 46a01 (11:6a01)
+; [hCoordsInFrontOfPlayerMatch] = $00 if they match, $ff if they don't match
+CheckIfCoordsInFrontOfPlayerMatch:
ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
cp SPRITE_FACING_UP
jr z, .facingUp
@@ -95,30 +95,30 @@ CheckIfCoordsInFrontOfPlayerMatch: ; 46a01 (11:6a01)
cp SPRITE_FACING_RIGHT
jr z, .facingRight
; facing down
- ld a, [W_YCOORD]
+ ld a, [wYCoord]
inc a
jr .upDownCommon
.facingUp
- ld a, [W_YCOORD]
+ ld a, [wYCoord]
dec a
.upDownCommon
cp b
jr nz, .didNotMatch
- ld a, [W_XCOORD]
+ ld a, [wXCoord]
cp c
jr nz, .didNotMatch
jr .matched
.facingLeft
- ld a, [W_XCOORD]
+ ld a, [wXCoord]
dec a
jr .leftRightCommon
.facingRight
- ld a, [W_XCOORD]
+ ld a, [wXCoord]
inc a
.leftRightCommon
cp c
jr nz, .didNotMatch
- ld a, [W_YCOORD]
+ ld a, [wYCoord]
cp b
jr nz, .didNotMatch
.matched
@@ -127,7 +127,7 @@ CheckIfCoordsInFrontOfPlayerMatch: ; 46a01 (11:6a01)
.didNotMatch
ld a, $ff
.done
- ld [$ffea], a
+ ld [hCoordsInFrontOfPlayerMatch], a
ret
INCLUDE "data/hidden_objects.asm"
diff --git a/engine/overworld/is_player_just_outside_map.asm b/engine/overworld/is_player_just_outside_map.asm
index 24e434b3..44690db0 100644
--- a/engine/overworld/is_player_just_outside_map.asm
+++ b/engine/overworld/is_player_just_outside_map.asm
@@ -1,13 +1,13 @@
; returns whether the player is one tile outside the map in Z
-IsPlayerJustOutsideMap: ; 128d8 (4:68d8)
- ld a, [W_YCOORD]
+IsPlayerJustOutsideMap:
+ ld a, [wYCoord]
ld b, a
- ld a, [W_CURMAPHEIGHT]
+ ld a, [wCurMapHeight]
call .compareCoordWithMapDimension
ret z
- ld a, [W_XCOORD]
+ ld a, [wXCoord]
ld b, a
- ld a, [W_CURMAPWIDTH]
+ ld a, [wCurMapWidth]
.compareCoordWithMapDimension
add a
cp b
diff --git a/engine/overworld/item.asm b/engine/overworld/item.asm
index a49fc268..9f19100a 100644
--- a/engine/overworld/item.asm
+++ b/engine/overworld/item.asm
@@ -1,9 +1,9 @@
-PickupItem:
+PickUpItem:
call EnableAutoTextBoxDrawing
- ld a, [H_DOWNARROWBLINKCNT2] ; $ff8c
+ ld a, [hSpriteIndexOrTextID]
ld b, a
- ld hl, W_MISSABLEOBJECTLIST
+ ld hl, wMissableObjectList
.missableObjectsListLoop
ld a, [hli]
cp $ff
@@ -17,8 +17,8 @@ PickupItem:
ld a, [hl]
ld [$ffdb], a
- ld hl, W_MAPSPRITEEXTRADATA
- ld a, [H_DOWNARROWBLINKCNT2] ; $ff8c
+ ld hl, wMapSpriteExtraData
+ ld a, [hSpriteIndexOrTextID]
dec a
add a
ld d, 0
@@ -31,7 +31,7 @@ PickupItem:
jr nc, .BagFull
ld a, [$ffdb]
- ld [wcc4d], a
+ ld [wMissableObjectIndex], a
predef HideObject
ld a, 1
ld [wDoNotWaitForButtonPressAfterDisplayingText], a
@@ -46,7 +46,7 @@ PickupItem:
FoundItemText:
TX_FAR _FoundItemText
- db $0B
+ TX_SFX_ITEM_1
db "@"
NoMoreRoomForItemText:
diff --git a/engine/overworld/ledges.asm b/engine/overworld/ledges.asm
index b8c19181..342540b2 100755
--- a/engine/overworld/ledges.asm
+++ b/engine/overworld/ledges.asm
@@ -1,8 +1,8 @@
-HandleLedges: ; 1a672 (6:6672)
+HandleLedges:
ld a, [wd736]
bit 6, a ; already jumping down ledge
ret nz
- ld a, [W_CURMAPTILESET] ; W_CURMAPTILESET
+ ld a, [wCurMapTileset]
and a ; OVERWORLD
ret nz
predef GetTileAndCoordsInFrontOfPlayer
@@ -50,12 +50,12 @@ HandleLedges: ; 1a672 (6:6672)
ld a, $2
ld [wSimulatedJoypadStatesIndex], a
call LoadHoppingShadowOAM
- ld a, (SFX_02_4e - SFX_Headers_02) / 3
+ ld a, SFX_LEDGE
call PlaySound
ret
; (player direction) (tile player standing on) (ledge tile) (input required)
-LedgeTiles: ; 1a6cf (6:66cf)
+LedgeTiles:
db SPRITE_FACING_DOWN, $2C,$37,D_DOWN
db SPRITE_FACING_DOWN, $39,$36,D_DOWN
db SPRITE_FACING_DOWN, $39,$37,D_DOWN
@@ -66,20 +66,21 @@ LedgeTiles: ; 1a6cf (6:66cf)
db SPRITE_FACING_RIGHT,$39,$0D,D_RIGHT
db $FF
-LoadHoppingShadowOAM: ; 1a6f0 (6:66f0)
+LoadHoppingShadowOAM:
ld hl, vChars1 + $7f0
ld de, LedgeHoppingShadow
- ld bc, (BANK(LedgeHoppingShadow) << 8) + $01
+ lb bc, BANK(LedgeHoppingShadow), (LedgeHoppingShadowEnd - LedgeHoppingShadow) / $8
call CopyVideoDataDouble
ld a, $9
- ld bc, $5448 ; b, c = y, x coordinates of shadow
+ lb bc, $54, $48 ; b, c = y, x coordinates of shadow
ld de, LedgeHoppingShadowOAM
call WriteOAMBlock
ret
-LedgeHoppingShadow: ; 1a708 (6:6708)
+LedgeHoppingShadow:
INCBIN "gfx/ledge_hopping_shadow.1bpp"
+LedgeHoppingShadowEnd:
-LedgeHoppingShadowOAM: ; 1a710 (6:6710)
+LedgeHoppingShadowOAM:
db $FF,$10,$FF,$20
db $FF,$40,$FF,$60
diff --git a/engine/overworld/map_sprite_functions1.asm b/engine/overworld/map_sprite_functions1.asm
new file mode 100644
index 00000000..d1a411fa
--- /dev/null
+++ b/engine/overworld/map_sprite_functions1.asm
@@ -0,0 +1,356 @@
+_UpdateSprites:
+ ld h, $c1
+ inc h
+ ld a, $e ; wSpriteStateData2 + $0e
+.spriteLoop
+ ld l, a
+ sub $e
+ ld c, a
+ ld [H_CURRENTSPRITEOFFSET], a
+ ld a, [hl]
+ and a
+ jr z, .skipSprite ; tests $c2Xe
+ push hl
+ push de
+ push bc
+ call .updateCurrentSprite
+ pop bc
+ pop de
+ pop hl
+.skipSprite
+ ld a, l
+ add $10 ; move to next sprite
+ cp $e ; test for overflow (back at $0e)
+ jr nz, .spriteLoop
+ ret
+.updateCurrentSprite
+ cp $1
+ jp nz, UpdateNonPlayerSprite
+ jp UpdatePlayerSprite
+
+UpdateNonPlayerSprite:
+ dec a
+ swap a
+ ld [$ff93], a ; $10 * sprite#
+ ld a, [wNPCMovementScriptSpriteOffset] ; some sprite offset?
+ ld b, a
+ ld a, [H_CURRENTSPRITEOFFSET]
+ cp b
+ jr nz, .unequal
+ jp DoScriptedNPCMovement
+.unequal
+ jp UpdateNPCSprite
+
+; This detects if the current sprite (whose offset is at H_CURRENTSPRITEOFFSET)
+; is going to collide with another sprite by looping over the other sprites.
+; The current sprite's offset will be labelled with i (e.g. $c1i0).
+; The loop sprite's offset will labelled with j (e.g. $c1j0).
+;
+; Note that the Y coordinate of the sprite (in [$c1k4]) is one of the following
+; 9 values when the sprite is aligned with the grid: $fc, $0c, $1c, $2c, ..., $7c.
+; The reason that 4 is added below to the coordinate is to make it align with a
+; multiple of $10 to make comparisons easier.
+DetectCollisionBetweenSprites:
+ nop
+
+ ld h, wSpriteStateData1 / $100
+ ld a, [H_CURRENTSPRITEOFFSET]
+ add wSpriteStateData1 % $100
+ ld l, a
+
+ ld a, [hl] ; a = [$c1i0] (picture) (0 if slot is unused)
+ and a ; is this sprite slot slot used?
+ ret z ; return if not used
+
+ ld a, l
+ add 3
+ ld l, a
+
+ ld a, [hli] ; a = [$c1i3] (delta Y) (-1, 0, or 1)
+ call SetSpriteCollisionValues
+
+ ld a, [hli] ; a = [$C1i4] (Y screen coordinate)
+ add 4 ; align with multiple of $10
+
+; The effect of the following 3 lines is to
+; add 7 to a if moving south or
+; subtract 7 from a if moving north.
+ add b
+ and $f0
+ or c
+
+ ld [$ff90], a ; store Y coordinate adjusted for direction of movement
+
+ ld a, [hli] ; a = [$c1i5] (delta X) (-1, 0, or 1)
+ call SetSpriteCollisionValues
+ ld a, [hl] ; a = [$C1i6] (X screen coordinate)
+
+; The effect of the following 3 lines is to
+; add 7 to a if moving east or
+; subtract 7 from a if moving west.
+ add b
+ and $f0
+ or c
+
+ ld [$ff91], a ; store X coordinate adjusted for direction of movement
+
+ ld a, l
+ add 7
+ ld l, a
+
+ xor a
+ ld [hld], a ; zero [$c1id] XXX what's [$c1id] for?
+ ld [hld], a ; zero [$c1ic] (directions in which collisions occurred)
+
+ ld a, [$ff91]
+ ld [hld], a ; [$c1ib] = adjusted X coordinate
+ ld a, [$ff90]
+ ld [hl], a ; [$c1ia] = adjusted Y coordinate
+
+ xor a ; zero the loop counter
+
+.loop
+ ld [$ff8f], a ; store loop counter
+ swap a
+ ld e, a
+ ld a, [H_CURRENTSPRITEOFFSET]
+ cp e ; does the loop sprite match the current sprite?
+ jp z, .next ; go to the next sprite if they match
+
+ ld d, h
+ ld a, [de] ; a = [$c1j0] (picture) (0 if slot is unused)
+ and a ; is this sprite slot slot used?
+ jp z, .next ; go the next sprite if not used
+
+ inc e
+ inc e
+ ld a, [de] ; a = [$c1j2] ($ff means the sprite is offscreen)
+ inc a
+ jp z, .next ; go the next sprite if offscreen
+
+ ld a, [H_CURRENTSPRITEOFFSET]
+ add 10
+ ld l, a
+
+ inc e
+ ld a, [de] ; a = [$c1j3] (delta Y)
+ call SetSpriteCollisionValues
+
+ inc e
+ ld a, [de] ; a = [$C1j4] (Y screen coordinate)
+ add 4 ; align with multiple of $10
+
+; The effect of the following 3 lines is to
+; add 7 to a if moving south or
+; subtract 7 from a if moving north.
+ add b
+ and $f0
+ or c
+
+ sub [hl] ; subtract the adjusted Y coordinate of sprite i ([$c1ia]) from that of sprite j
+
+; calculate the absolute value of the difference to get the distance
+ jr nc, .noCarry1
+ cpl
+ inc a
+.noCarry1
+ ld [$ff90], a ; store the distance between the two sprites' adjusted Y values
+
+; Use the carry flag set by the above subtraction to determine which sprite's
+; Y coordinate is larger. This information is used later to set [$c1ic],
+; which stores which direction the collision occurred in.
+; The following 5 lines set the lowest 2 bits of c, which are later shifted left by 2.
+; If sprite i's Y is larger, set lowest 2 bits of c to 10.
+; If sprite j's Y is larger or both are equal, set lowest 2 bits of c to 01.
+ push af
+ rl c
+ pop af
+ ccf
+ rl c
+
+; If sprite i's delta Y is 0, then b = 7, else b = 9.
+ ld b, 7
+ ld a, [hl] ; a = [$c1ia] (adjusted Y coordinate)
+ and $f
+ jr z, .next1
+ ld b, 9
+
+.next1
+ ld a, [$ff90] ; a = distance between adjusted Y coordinates
+ sub b
+ ld [$ff92], a ; store distance adjusted using sprite i's direction
+ ld a, b
+ ld [$ff90], a ; store 7 or 9 depending on sprite i's delta Y
+ jr c, .checkXDistance
+
+; If sprite j's delta Y is 0, then b = 7, else b = 9.
+ ld b, 7
+ dec e
+ ld a, [de] ; a = [$c1j3] (delta Y)
+ inc e
+ and a
+ jr z, .next2
+ ld b, 9
+
+.next2
+ ld a, [$ff92] ; a = distance adjusted using sprite i's direction
+ sub b ; adjust distance using sprite j's direction
+ jr z, .checkXDistance
+ jr nc, .next ; go to next sprite if distance is still positive after both adjustments
+
+.checkXDistance
+ inc e
+ inc l
+ ld a, [de] ; a = [$c1j5] (delta X)
+
+ push bc
+
+ call SetSpriteCollisionValues
+ inc e
+ ld a, [de] ; a = [$c1j6] (X screen coordinate)
+
+; The effect of the following 3 lines is to
+; add 7 to a if moving east or
+; subtract 7 from a if moving west.
+ add b
+ and $f0
+ or c
+
+ pop bc
+
+ sub [hl] ; subtract the adjusted X coordinate of sprite i ([$c1ib]) from that of sprite j
+
+; calculate the absolute value of the difference to get the distance
+ jr nc, .noCarry2
+ cpl
+ inc a
+.noCarry2
+ ld [$ff91], a ; store the distance between the two sprites' adjusted X values
+
+; Use the carry flag set by the above subtraction to determine which sprite's
+; X coordinate is larger. This information is used later to set [$c1ic],
+; which stores which direction the collision occurred in.
+; The following 5 lines set the lowest 2 bits of c.
+; If sprite i's X is larger, set lowest 2 bits of c to 10.
+; If sprite j's X is larger or both are equal, set lowest 2 bits of c to 01.
+ push af
+ rl c
+ pop af
+ ccf
+ rl c
+
+; If sprite i's delta X is 0, then b = 7, else b = 9.
+ ld b, 7
+ ld a, [hl] ; a = [$c1ib] (adjusted X coordinate)
+ and $f
+ jr z, .next3
+ ld b, 9
+
+.next3
+ ld a, [$ff91] ; a = distance between adjusted X coordinates
+ sub b
+ ld [$ff92], a ; store distance adjusted using sprite i's direction
+ ld a, b
+ ld [$ff91], a ; store 7 or 9 depending on sprite i's delta X
+ jr c, .collision
+
+; If sprite j's delta X is 0, then b = 7, else b = 9.
+ ld b, 7
+ dec e
+ ld a, [de] ; a = [$c1j5] (delta X)
+ inc e
+ and a
+ jr z, .next4
+ ld b, 9
+
+.next4
+ ld a, [$ff92] ; a = distance adjusted using sprite i's direction
+ sub b ; adjust distance using sprite j's direction
+ jr z, .collision
+ jr nc, .next ; go to next sprite if distance is still positive after both adjustments
+
+.collision
+ ld a, [$ff91] ; a = 7 or 9 depending on sprite i's delta X
+ ld b, a
+ ld a, [$ff90] ; a = 7 or 9 depending on sprite i's delta Y
+ inc l
+
+; If delta X isn't 0 and delta Y is 0, then b = %0011, else b = %1100.
+; (note that normally if delta X isn't 0, then delta Y must be 0 and vice versa)
+ cp b
+ jr c, .next5
+ ld b, %1100
+ jr .next6
+.next5
+ ld b, %0011
+
+.next6
+ ld a, c ; c has 2 bits set (one of bits 0-1 is set for the X axis and one of bits 2-3 for the Y axis)
+ and b ; we select either the bit in bits 0-1 or bits 2-3 based on the calculation immediately above
+ or [hl] ; or with existing collision direction bits in [$c1ic]
+ ld [hl], a ; store new value
+ ld a, c ; useless code because a is overwritten before being used again
+
+; set bit in [$c1ie] or [$c1if] to indicate which sprite the collision occurred with
+ inc l
+ inc l
+ ld a, [$ff8f] ; a = loop counter
+ ld de, SpriteCollisionBitTable
+ add a
+ add e
+ ld e, a
+ jr nc, .noCarry3
+ inc d
+.noCarry3
+ ld a, [de]
+ or [hl]
+ ld [hli], a
+ inc de
+ ld a, [de]
+ or [hl]
+ ld [hl], a
+
+.next
+ ld a, [$ff8f] ; a = loop counter
+ inc a
+ cp $10
+ jp nz, .loop
+ ret
+
+; takes delta X or delta Y in a
+; b = delta X/Y
+; c = 0 if delta X/Y is 0
+; c = 7 if delta X/Y is 1
+; c = 9 if delta X/Y is -1
+SetSpriteCollisionValues:
+ and a
+ ld b, 0
+ ld c, 0
+ jr z, .done
+ ld c, 9
+ cp -1
+ jr z, .ok
+ ld c, 7
+ ld a, 0
+.ok
+ ld b, a
+.done
+ ret
+
+SpriteCollisionBitTable:
+ db %00000000,%00000001
+ db %00000000,%00000010
+ db %00000000,%00000100
+ db %00000000,%00001000
+ db %00000000,%00010000
+ db %00000000,%00100000
+ db %00000000,%01000000
+ db %00000000,%10000000
+ db %00000001,%00000000
+ db %00000010,%00000000
+ db %00000100,%00000000
+ db %00001000,%00000000
+ db %00010000,%00000000
+ db %00100000,%00000000
+ db %01000000,%00000000
+ db %10000000,%00000000
diff --git a/engine/overworld/map_sprites.asm b/engine/overworld/map_sprites.asm
index df39d112..05588321 100755
--- a/engine/overworld/map_sprites.asm
+++ b/engine/overworld/map_sprites.asm
@@ -8,7 +8,7 @@
; 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)
+InitMapSprites:
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)
@@ -29,17 +29,17 @@ InitMapSprites: ; 1785b (5:785b)
; 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]
+LoadMapSpriteTilePatterns:
+ ld a,[wNumSprites]
and a ; are there any sprites?
jr nz,.spritesExist
ret
.spritesExist
- ld c,a ; c = [W_NUMSPRITES]
+ ld c,a ; c = [wNumSprites]
ld b,$10 ; number of sprite slots
ld hl,wSpriteStateData2 + $0d
xor a
- ld [$ff8e],a ; 4-tile sprite counter
+ ld [hFourTileSpriteCount],a
.copyPictureIDLoop ; loop to copy picture ID from $C2XD to $C2XE
ld a,[hli] ; $C2XD (sprite picture ID)
ld [hld],a ; $C2XE
@@ -98,14 +98,14 @@ LoadMapSpriteTilePatterns: ; 17871 (5:7871)
cp a,SPRITE_BALL ; is it a 4-tile sprite?
jr c,.notFourTileSprite
pop af
- ld a,[$ff8e] ; 4-tile sprite counter
+ ld a,[hFourTileSpriteCount]
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 [hVRAMSlot],a ; used to determine if it's 4-tile sprite later
ld a,b ; a = current sprite picture ID
dec a
add a
@@ -128,7 +128,7 @@ LoadMapSpriteTilePatterns: ; 17871 (5:7871)
push bc
ld hl,vNPCSprites ; VRAM base address
ld bc,$c0 ; number of bytes per VRAM slot
- ld a,[$ff8d]
+ ld a,[hVRAMSlot]
cp a,11 ; is it a 4-tile sprite?
jr nc,.fourTileSpriteVRAMAddr
ld d,a
@@ -142,13 +142,13 @@ LoadMapSpriteTilePatterns: ; 17871 (5:7871)
jr .loadStillTilePattern
.fourTileSpriteVRAMAddr
ld hl,vSprites + $7c0 ; address for second 4-tile sprite
- ld a,[$ff8e] ; 4-tile sprite counter
- and a ; is it the first 4-tile sprite?
+ ld a,[hFourTileSpriteCount]
+ and a
jr nz,.loadStillTilePattern
; if it's the first 4-tile sprite
ld hl,vSprites + $780 ; address for first 4-tile sprite
inc a
- ld [$ff8e],a ; 4-tile sprite counter
+ ld [hFourTileSpriteCount],a
.loadStillTilePattern
pop bc
pop de
@@ -168,7 +168,7 @@ LoadMapSpriteTilePatterns: ; 17871 (5:7871)
.skipFirstLoad
pop de
pop hl
- ld a,[$ff8d]
+ ld a,[hVRAMSlot]
cp a,11 ; is it a 4-tile sprite?
jr nc,.skipSecondLoad ; if so, there is no second block
push de
@@ -236,7 +236,7 @@ LoadMapSpriteTilePatterns: ; 17871 (5:7871)
; de = pointer to sprite sheet
; bc = length in bytes
; a = ROM bank
-ReadSpriteSheetData: ; 17971 (5:7971)
+ReadSpriteSheetData:
ld a,[hli]
ld e,a
ld a,[hli]
@@ -250,8 +250,8 @@ ReadSpriteSheetData: ; 17971 (5:7971)
; 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]
+InitOutsideMapSprites:
+ ld a,[wCurMap]
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
@@ -267,12 +267,12 @@ InitOutsideMapSprites: ; 1797b (5:797b)
ld a,[wFontLoaded]
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]
+ ld a,[wSpriteSetID]
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
+ ld [wSpriteSetID],a
dec a
ld b,a
sla a
@@ -291,7 +291,7 @@ InitOutsideMapSprites: ; 1797b (5:797b)
ld hl,wSpriteStateData2 + $0d
ld a,SPRITE_RED
ld [hl],a
- ld bc,W_SPRITESET
+ ld bc,wSpriteSet
; 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
@@ -317,13 +317,13 @@ InitOutsideMapSprites: ; 1797b (5:797b)
ld [hl],a ; $C2XD (sprite picture ID)
dec b
jr nz,.zeroRemainingSlotsLoop
- ld a,[W_NUMSPRITES]
+ ld a,[wNumSprites]
push af ; save number of sprites
ld a,11 ; 11 sprites in sprite set
- ld [W_NUMSPRITES],a
+ ld [wNumSprites],a
call LoadMapSpriteTilePatterns
pop af
- ld [W_NUMSPRITES],a ; restore number of sprites
+ ld [wNumSprites],a ; restore number of sprites
ld hl,wSpriteStateData2 + $1e
ld b,$0f
; The VRAM tile pattern slots that LoadMapSpriteTilePatterns set are in the
@@ -352,7 +352,7 @@ InitOutsideMapSprites: ; 1797b (5:797b)
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
+ ld de,wSpriteSet
; Loop to find the index of the sprite's picture ID within the sprite set.
.getPictureIndexLoop
inc c
@@ -380,7 +380,7 @@ InitOutsideMapSprites: ; 1797b (5:797b)
; 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)
+GetSplitMapSpriteSetID:
cp a,$f8
jr z,.route20
ld hl,SplitMapSpriteSets
@@ -399,10 +399,10 @@ GetSplitMapSpriteSetID: ; 17a1a (5:7a1a)
ld b,a
jr z,.eastWestDivide
.northSouthDivide
- ld a,[W_YCOORD]
+ ld a,[wYCoord]
jr .compareCoord
.eastWestDivide
- ld a,[W_XCOORD]
+ ld a,[wXCoord]
.compareCoord
cp b
jr c,.loadSpriteSetID
@@ -415,7 +415,7 @@ GetSplitMapSpriteSetID: ; 17a1a (5:7a1a)
; 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 hl,wXCoord
ld a,[hl]
cp a,$2b
ld a,$01
@@ -430,7 +430,7 @@ GetSplitMapSpriteSetID: ; 17a1a (5:7a1a)
jr nc,.next
ld b,$0d
.next
- ld a,[W_YCOORD]
+ ld a,[wYCoord]
cp b
ld a,$0a
ret c
diff --git a/engine/overworld/missable_objects.asm b/engine/overworld/missable_objects.asm
new file mode 100644
index 00000000..8587c0f7
--- /dev/null
+++ b/engine/overworld/missable_objects.asm
@@ -0,0 +1,215 @@
+MarkTownVisitedAndLoadMissableObjects:
+ ld a, [wCurMap]
+ cp ROUTE_1
+ jr nc, .notInTown
+ ld c, a
+ ld b, FLAG_SET
+ ld hl, wTownVisitedFlag ; mark town as visited (for flying)
+ predef FlagActionPredef
+.notInTown
+ ld hl, MapHSPointers
+ ld a, [wCurMap]
+ ld b, $0
+ ld c, a
+ add hl, bc
+ add hl, bc
+ ld a, [hli] ; load missable objects pointer in hl
+ ld h, [hl]
+ ; fall through
+
+LoadMissableObjects:
+ ld l, a
+ push hl
+ ld de, MapHS00 ; calculate difference between out pointer and the base pointer
+ ld a, l
+ sub e
+ jr nc, .asm_f13c
+ dec h
+.asm_f13c
+ ld l, a
+ ld a, h
+ sub d
+ ld h, a
+ ld a, h
+ ld [H_DIVIDEND], a
+ ld a, l
+ ld [H_DIVIDEND+1], a
+ xor a
+ ld [H_DIVIDEND+2], a
+ ld [H_DIVIDEND+3], a
+ ld a, $3
+ ld [H_DIVISOR], a
+ ld b, $2
+ call Divide ; divide difference by 3, resulting in the global offset (number of missable items before ours)
+ ld a, [wCurMap]
+ ld b, a
+ ld a, [H_DIVIDEND+3]
+ ld c, a ; store global offset in c
+ ld de, wMissableObjectList
+ pop hl
+.writeMissableObjectsListLoop
+ ld a, [hli]
+ cp $ff
+ jr z, .done ; end of list
+ cp b
+ jr nz, .done ; not for current map anymore
+ ld a, [hli]
+ inc hl
+ ld [de], a ; write (map-local) sprite ID
+ inc de
+ ld a, c
+ inc c
+ ld [de], a ; write (global) missable object index
+ inc de
+ jr .writeMissableObjectsListLoop
+.done
+ ld a, $ff
+ ld [de], a ; write sentinel
+ ret
+
+InitializeMissableObjectsFlags:
+ ld hl, wMissableObjectFlags
+ ld bc, wMissableObjectFlagsEnd - wMissableObjectFlags
+ xor a
+ call FillMemory ; clear missable objects flags
+ ld hl, MapHS00
+ xor a
+ ld [wMissableObjectCounter], a
+.missableObjectsLoop
+ ld a, [hli]
+ cp $ff ; end of list
+ ret z
+ push hl
+ inc hl
+ ld a, [hl]
+ cp Hide
+ jr nz, .skip
+ ld hl, wMissableObjectFlags
+ ld a, [wMissableObjectCounter]
+ ld c, a
+ ld b, FLAG_SET
+ call MissableObjectFlagAction ; set flag if Item is hidden
+.skip
+ ld hl, wMissableObjectCounter
+ inc [hl]
+ pop hl
+ inc hl
+ inc hl
+ jr .missableObjectsLoop
+
+; tests if current sprite is a missable object that is hidden/has been removed
+IsObjectHidden:
+ ld a, [H_CURRENTSPRITEOFFSET]
+ swap a
+ ld b, a
+ ld hl, wMissableObjectList
+.loop
+ ld a, [hli]
+ cp $ff
+ jr z, .notHidden ; not missable -> not hidden
+ cp b
+ ld a, [hli]
+ jr nz, .loop
+ ld c, a
+ ld b, FLAG_TEST
+ ld hl, wMissableObjectFlags
+ call MissableObjectFlagAction
+ ld a, c
+ and a
+ jr nz, .hidden
+.notHidden
+ xor a
+.hidden
+ ld [$ffe5], a
+ ret
+
+; adds missable object (items, leg. pokemon, etc.) to the map
+; [wMissableObjectIndex]: index of the missable object to be added (global index)
+ShowObject:
+ShowObject2:
+ ld hl, wMissableObjectFlags
+ ld a, [wMissableObjectIndex]
+ ld c, a
+ ld b, FLAG_RESET
+ call MissableObjectFlagAction ; reset "removed" flag
+ jp UpdateSprites
+
+; removes missable object (items, leg. pokemon, etc.) from the map
+; [wMissableObjectIndex]: index of the missable object to be removed (global index)
+HideObject:
+ ld hl, wMissableObjectFlags
+ ld a, [wMissableObjectIndex]
+ ld c, a
+ ld b, FLAG_SET
+ call MissableObjectFlagAction ; set "removed" flag
+ jp UpdateSprites
+
+MissableObjectFlagAction:
+; identical to FlagAction
+
+ push hl
+ push de
+ push bc
+
+ ; bit
+ ld a, c
+ ld d, a
+ and 7
+ ld e, a
+
+ ; byte
+ ld a, d
+ srl a
+ srl a
+ srl a
+ add l
+ ld l, a
+ jr nc, .ok
+ inc h
+.ok
+
+ ; d = 1 << e (bitmask)
+ inc e
+ ld d, 1
+.shift
+ dec e
+ jr z, .shifted
+ sla d
+ jr .shift
+.shifted
+
+ ld a, b
+ and a
+ jr z, .reset
+ cp 2
+ jr z, .read
+
+.set
+ ld a, [hl]
+ ld b, a
+ ld a, d
+ or b
+ ld [hl], a
+ jr .done
+
+.reset
+ ld a, [hl]
+ ld b, a
+ ld a, d
+ xor $ff
+ and b
+ ld [hl], a
+ jr .done
+
+.read
+ ld a, [hl]
+ ld b, a
+ ld a, d
+ and b
+
+.done
+ pop bc
+ pop de
+ pop hl
+ ld c, a
+ ret
diff --git a/engine/overworld/movement.asm b/engine/overworld/movement.asm
index c4482700..6d05859e 100644
--- a/engine/overworld/movement.asm
+++ b/engine/overworld/movement.asm
@@ -1,4 +1,4 @@
-UpdatePlayerSprite: ; 4e31 (1:4e31)
+UpdatePlayerSprite:
ld a, [wSpriteStateData2]
and a
jr z, .checkIfTextBoxInFrontOfSprite
@@ -12,7 +12,7 @@ UpdatePlayerSprite: ; 4e31 (1:4e31)
; the maximum number for map tiles
.checkIfTextBoxInFrontOfSprite
aCoord 8, 9
- ld [$ff93], a
+ ld [hTilePlayerStandingOn], a
cp $60
jr c, .lowerLeftTileIsMapTile
.disableSprite
@@ -21,52 +21,54 @@ UpdatePlayerSprite: ; 4e31 (1:4e31)
ret
.lowerLeftTileIsMapTile
call DetectCollisionBetweenSprites
- ld h, $c1
- ld a, [wWalkCounter] ; wcfc5
+ ld h, wSpriteStateData1 / $100
+ ld a, [wWalkCounter]
and a
- jr nz, .asm_4e90
- ld a, [wd528]
- bit 2, a
- jr z, .asm_4e65
- xor a
- jr .asm_4e86
-.asm_4e65
- bit 3, a
- jr z, .asm_4e6d
- ld a, $4
- jr .asm_4e86
-.asm_4e6d
- bit 1, a
- jr z, .asm_4e75
- ld a, $8
- jr .asm_4e86
-.asm_4e75
- bit 0, a
- jr z, .asm_4e7d
- ld a, $c
- jr .asm_4e86
-.asm_4e7d
+ jr nz, .moving
+ ld a, [wPlayerMovingDirection]
+; check if down
+ bit PLAYER_DIR_BIT_DOWN, a
+ jr z, .checkIfUp
+ xor a ; ld a, SPRITE_FACING_DOWN
+ jr .next
+.checkIfUp
+ bit PLAYER_DIR_BIT_UP, a
+ jr z, .checkIfLeft
+ ld a, SPRITE_FACING_UP
+ jr .next
+.checkIfLeft
+ bit PLAYER_DIR_BIT_LEFT, a
+ jr z, .checkIfRight
+ ld a, SPRITE_FACING_LEFT
+ jr .next
+.checkIfRight
+ bit PLAYER_DIR_BIT_RIGHT, a
+ jr z, .notMoving
+ ld a, SPRITE_FACING_RIGHT
+ jr .next
+.notMoving
+; zero the animation counters
xor a
ld [wSpriteStateData1 + 7], a
ld [wSpriteStateData1 + 8], a
- jr .asm_4eab
-.asm_4e86
- ld [wSpriteStateData1 + 9], a
+ jr .calcImageIndex
+.next
+ ld [wSpriteStateData1 + 9], a ; facing direction
ld a, [wFontLoaded]
bit 0, a
- jr nz, .asm_4e7d
-.asm_4e90
+ jr nz, .notMoving
+.moving
ld a, [wd736]
- bit 7, a
- jr nz, .asm_4eb6
+ bit 7, a ; is the player sprite spinning due to a spin tile?
+ jr nz, .skipSpriteAnim
ld a, [H_CURRENTSPRITEOFFSET]
add $7
ld l, a
ld a, [hl]
inc a
ld [hl], a
- cp $4
- jr nz, .asm_4eab
+ cp 4
+ jr nz, .calcImageIndex
xor a
ld [hl], a
inc hl
@@ -74,28 +76,32 @@ UpdatePlayerSprite: ; 4e31 (1:4e31)
inc a
and $3
ld [hl], a
-.asm_4eab
+.calcImageIndex
ld a, [wSpriteStateData1 + 8]
ld b, a
ld a, [wSpriteStateData1 + 9]
add b
ld [wSpriteStateData1 + 2], a
-.asm_4eb6
- ld a, [$ff93]
+.skipSpriteAnim
+; If the player is standing on a grass tile, make the player's sprite have
+; lower priority than the background so that it's partially obscured by the
+; grass. Only the lower half of the sprite is permitted to have the priority
+; bit set by later logic.
+ ld a, [hTilePlayerStandingOn]
ld c, a
- ld a, [W_GRASSTILE]
+ ld a, [wGrassTile]
cp c
ld a, $0
- jr nz, .asm_4ec3
+ jr nz, .next2
ld a, $80
-.asm_4ec3
- ld [wSpriteStateData2 + $07], a
+.next2
+ ld [wSpriteStateData2 + 7], a
ret
-Func_4ec7: ; 4ec7 (1:4ec7)
+UnusedReadSpriteDataFunction:
push bc
push af
- ld a, [$ffda]
+ ld a, [H_CURRENTSPRITEOFFSET]
ld c, a
pop af
add c
@@ -103,12 +109,12 @@ Func_4ec7: ; 4ec7 (1:4ec7)
pop bc
ret
-Func_4ed1: ; 4ed1 (1:4ed1)
+UpdateNPCSprite:
ld a, [H_CURRENTSPRITEOFFSET]
swap a
dec a
add a
- ld hl, W_MAPSPRITEDATA ; wd4e4
+ ld hl, wMapSpriteData
add l
ld l, a
ld a, [hl] ; read movement byte 2
@@ -127,8 +133,8 @@ Func_4ed1: ; 4ed1 (1:4ed1)
ld l, a
inc l
ld a, [hl] ; c1x1
- bit 7, a
- jp nz, InitializeSpriteFacingDirection ; c1x1 >= $80
+ bit 7, a ; is the face player flag set?
+ jp nz, MakeNPCFacePlayer
ld b, a
ld a, [wFontLoaded]
bit 0, a
@@ -138,7 +144,7 @@ Func_4ed1: ; 4ed1 (1:4ed1)
jp z, UpdateSpriteMovementDelay ; c1x1 == 2
cp $3
jp z, UpdateSpriteInWalkingAnimation ; c1x1 == 3
- ld a, [wWalkCounter] ; wcfc5
+ ld a, [wWalkCounter]
and a
ret nz ; don't do anything yet if player is currently moving (redundant, already tested in CheckSpriteAvailability)
call InitializeSpriteScreenPosition
@@ -148,40 +154,43 @@ Func_4ed1: ; 4ed1 (1:4ed1)
ld l, a
ld a, [hl] ; c2x6: movement byte 1
inc a
- jr z, .asm_4f59 ; value $FF
+ jr z, .randomMovement ; value $FF
inc a
- jr z, .asm_4f59 ; value $FE
+ jr z, .randomMovement ; value $FE
+; scripted movement
dec a
- ld [hl], a ; (temporarily) increment movement byte 1
+ ld [hl], a ; increment movement byte 1 (movement data index)
dec a
push hl
- ld hl, wcf0f
- dec [hl] ; decrement wcf0f
+ ld hl, wNPCNumScriptedSteps
+ dec [hl] ; decrement wNPCNumScriptedSteps
pop hl
- ld de, wcc5b
- call LoadDEPlusA ; a = [wcc5b + movement byte 1]
+ ld de, wNPCMovementDirections
+ call LoadDEPlusA ; a = [wNPCMovementDirections + movement byte 1]
cp $e0
jp z, ChangeFacingDirection
- cp $ff
- jr nz, .asm_4f4b
- ld [hl], a ; reset movement byte 1 to initial value
+ cp STAY
+ jr nz, .next
+; reached end of wNPCMovementDirections list
+ ld [hl], a ; store $ff in movement byte 1, disabling scripted movement
ld hl, wd730
res 0, [hl]
xor a
ld [wSimulatedJoypadStatesIndex], a
ld [wWastedByteCD3A], a
ret
-.asm_4f4b
- cp $fe
- jr nz, .asm_4f5f
+.next
+ cp WALK
+ jr nz, .determineDirection
+; current NPC movement data is $fe. this seems buggy
ld [hl], $1 ; set movement byte 1 to $1
- ld de, wcc5b
- call LoadDEPlusA ; a = [wcc5b + $fe] (?)
- jr .asm_4f5f
-.asm_4f59
- call getTileSpriteStandsOn
+ ld de, wNPCMovementDirections
+ call LoadDEPlusA ; a = [wNPCMovementDirections + $fe] (?)
+ jr .determineDirection
+.randomMovement
+ call GetTileSpriteStandsOn
call Random
-.asm_4f5f
+.determineDirection
ld b, a
ld a, [wCurSpriteMovement2]
cp $d0
@@ -199,11 +208,10 @@ Func_4ed1: ; 4ed1 (1:4ed1)
cp $2
jr z, .moveLeft ; movement byte 2 = $2 only allows left or right
.moveDown
- ld de, 2*20
+ ld de, 2*SCREEN_WIDTH
add hl, de ; move tile pointer two rows down
- ld de, $100
-
- ld bc, $400
+ lb de, 1, 0
+ lb bc, 4, SPRITE_FACING_DOWN
jr TryWalking
.notDown
cp $80 ; $40 <= a < $80: up (or right)
@@ -212,10 +220,10 @@ Func_4ed1: ; 4ed1 (1:4ed1)
cp $2
jr z, .moveRight ; movement byte 2 = $2 only allows left or right
.moveUp
- ld de, -2*20 ; $ffd8
+ ld de, -2*SCREEN_WIDTH
add hl, de ; move tile pointer two rows up
- ld de, $ff00
- ld bc, $804
+ lb de, -1, 0
+ lb bc, 8, SPRITE_FACING_UP
jr TryWalking
.notUp
cp $c0 ; $80 <= a < $c0: left (or up)
@@ -226,8 +234,8 @@ Func_4ed1: ; 4ed1 (1:4ed1)
.moveLeft
dec hl
dec hl ; move tile pointer two columns left
- ld de, $ff
- ld bc, $208
+ lb de, 0, -1
+ lb bc, 2, SPRITE_FACING_LEFT
jr TryWalking
.notLeft ; $c0 <= a: right (or down)
ld a, [wCurSpriteMovement2]
@@ -236,12 +244,12 @@ Func_4ed1: ; 4ed1 (1:4ed1)
.moveRight
inc hl
inc hl ; move tile pointer two columns right
- ld de, $1
- ld bc, $10c
+ lb de, 0, 1
+ lb bc, 1, SPRITE_FACING_RIGHT
jr TryWalking
; changes facing direction by zeroing the movement delta and calling TryWalking
-ChangeFacingDirection: ; 4fc8 (1:4fc8)
+ChangeFacingDirection:
ld de, $0
; fall through
@@ -249,9 +257,9 @@ ChangeFacingDirection: ; 4fc8 (1:4fc8)
; c: new facing direction (0,4,8 or $c)
; d: Y movement delta (-1, 0 or 1)
; e: X movement delta (-1, 0 or 1)
-; hl: pointer to tile the sprite would wlak onto
+; hl: pointer to tile the sprite would walk onto
; set carry on failure, clears carry on success
-TryWalking: ; 4fcb (1:4fcb)
+TryWalking:
push hl
ld h, $c1
ld a, [H_CURRENTSPRITEOFFSET]
@@ -290,7 +298,7 @@ TryWalking: ; 4fcb (1:4fcb)
jp UpdateSpriteImage
; update the walking animation parameters for a sprite that is currently walking
-UpdateSpriteInWalkingAnimation: ; 4ffe (1:4ffe)
+UpdateSpriteInWalkingAnimation:
ld a, [H_CURRENTSPRITEOFFSET]
add $7
ld l, a
@@ -363,7 +371,7 @@ UpdateSpriteInWalkingAnimation: ; 4ffe (1:4ffe)
ret
; update delay value (c2x8) for sprites in the delayed state (c1x1)
-UpdateSpriteMovementDelay: ; 5057 (1:5057)
+UpdateSpriteMovementDelay:
ld h, $c2
ld a, [H_CURRENTSPRITEOFFSET]
add $6
@@ -384,36 +392,40 @@ UpdateSpriteMovementDelay: ; 5057 (1:5057)
inc a
ld l, a
ld [hl], $1 ; c1x1 = 1 (mark as ready to move)
-notYetMoving: ; 5073 (1:5073)
- ld h, $c1
+notYetMoving:
+ ld h, wSpriteStateData1 / $100
ld a, [H_CURRENTSPRITEOFFSET]
add $8
ld l, a
ld [hl], $0 ; c1x8 = 0 (walk animation frame)
jp UpdateSpriteImage
-InitializeSpriteFacingDirection: ; 507f (1:507f)
+MakeNPCFacePlayer:
+; Make an NPC face the player if the player has spoken to him or her.
+
+; Check if the behaviour of the NPC facing the player when spoken to is
+; disabled. This is only done when rubbing the S.S. Anne captain's back.
ld a, [wd72d]
bit 5, a
jr nz, notYetMoving
res 7, [hl]
- ld a, [wd52a]
- bit 3, a
+ ld a, [wPlayerDirection]
+ bit PLAYER_DIR_BIT_UP, a
jr z, .notFacingDown
- ld c, $0 ; make sprite face down
+ ld c, SPRITE_FACING_DOWN
jr .facingDirectionDetermined
.notFacingDown
- bit 2, a
+ bit PLAYER_DIR_BIT_DOWN, a
jr z, .notFacingUp
- ld c, $4 ; make sprite face up
+ ld c, SPRITE_FACING_UP
jr .facingDirectionDetermined
.notFacingUp
- bit 1, a
+ bit PLAYER_DIR_BIT_LEFT, a
jr z, .notFacingRight
- ld c, $c ; make sprite face right
+ ld c, SPRITE_FACING_RIGHT
jr .facingDirectionDetermined
.notFacingRight
- ld c, $8 ; make sprite face left
+ ld c, SPRITE_FACING_LEFT
.facingDirectionDetermined
ld a, [H_CURRENTSPRITEOFFSET]
add $9
@@ -421,7 +433,7 @@ InitializeSpriteFacingDirection: ; 507f (1:507f)
ld [hl], c ; c1x9: set facing direction
jr notYetMoving
-InitializeSpriteStatus: ; 50ad (1:50ad)
+InitializeSpriteStatus:
ld [hl], $1 ; $c1x1: set movement status to ready
inc l
ld [hl], $ff ; $c1x2: set sprite image to $ff (invisible/off screen)
@@ -435,12 +447,12 @@ InitializeSpriteStatus: ; 50ad (1:50ad)
ret
; calculates the spprite's scrren position form its map position and the player position
-InitializeSpriteScreenPosition: ; 50bd (1:50bd)
- ld h, $c2
+InitializeSpriteScreenPosition:
+ ld h, wSpriteStateData2 / $100
ld a, [H_CURRENTSPRITEOFFSET]
add $4
ld l, a
- ld a, [W_YCOORD] ; wd361
+ ld a, [wYCoord]
ld b, a
ld a, [hl] ; c2x4 (Y position + 4)
sub b ; relative to player position
@@ -449,7 +461,7 @@ InitializeSpriteScreenPosition: ; 50bd (1:50bd)
dec h
ld [hli], a ; c1x4 (screen Y position)
inc h
- ld a, [W_XCOORD] ; wd362
+ ld a, [wXCoord]
ld b, a
ld a, [hli] ; c2x6 (X position + 4)
sub b ; relative to player position
@@ -459,23 +471,23 @@ InitializeSpriteScreenPosition: ; 50bd (1:50bd)
ret
; tests if sprite is off screen or otherwise unable to do anything
-CheckSpriteAvailability: ; 50dc (1:50dc)
+CheckSpriteAvailability:
predef IsObjectHidden
ld a, [$ffe5]
and a
jp nz, .spriteInvisible
- ld h, $c2
+ ld h, wSpriteStateData2 / $100
ld a, [H_CURRENTSPRITEOFFSET]
add $6
ld l, a
ld a, [hl] ; c2x6: movement byte 1
cp $fe
- jr c, .skipXVisibilityTest ; movement byte 1 < $fe
+ jr c, .skipXVisibilityTest ; movement byte 1 < $fe (i.e. the sprite's movement is scripted)
ld a, [H_CURRENTSPRITEOFFSET]
add $4
ld l, a
ld b, [hl] ; c2x4: Y pos (+4)
- ld a, [W_YCOORD] ; wd361
+ ld a, [wYCoord]
cp b
jr z, .skipYVisibilityTest
jr nc, .spriteInvisible ; above screen region
@@ -485,7 +497,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc)
.skipYVisibilityTest
inc l
ld b, [hl] ; c2x5: X pos (+4)
- ld a, [W_XCOORD] ; wd362
+ ld a, [wXCoord]
cp b
jr z, .skipXVisibilityTest
jr nc, .spriteInvisible ; left of screen region
@@ -495,7 +507,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc)
.skipXVisibilityTest
; make the sprite invisible if a text box is in front of it
; $5F is the maximum number for map tiles
- call getTileSpriteStandsOn
+ call GetTileSpriteStandsOn
ld d, $60
ld a, [hli]
cp d
@@ -503,7 +515,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc)
ld a, [hld]
cp d
jr nc, .spriteInvisible ; standing on tile with ID >=$60 (bottom right tile)
- ld bc, -20 ; $ffec
+ ld bc, -20
add hl, bc ; go back one row of tiles
ld a, [hli]
cp d
@@ -512,7 +524,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc)
cp d
jr c, .spriteVisible ; standing on tile with ID >=$60 (top right tile)
.spriteInvisible
- ld h, $c1
+ ld h, wSpriteStateData1 / $100
ld a, [H_CURRENTSPRITEOFFSET]
add $2
ld l, a
@@ -521,7 +533,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc)
jr .done
.spriteVisible
ld c, a
- ld a, [wWalkCounter] ; wcfc5
+ ld a, [wWalkCounter]
and a
jr nz, .done ; if player is currently walking, we're done
call UpdateSpriteImage
@@ -529,7 +541,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc)
ld a, [H_CURRENTSPRITEOFFSET]
add $7
ld l, a
- ld a, [W_GRASSTILE]
+ ld a, [wGrassTile]
cp c
ld a, $0
jr nz, .notInGrass
@@ -540,7 +552,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc)
.done
ret
-UpdateSpriteImage: ; 5157 (1:5157)
+UpdateSpriteImage:
ld h, $c1
ld a, [H_CURRENTSPRITEOFFSET]
add $8
@@ -565,20 +577,21 @@ UpdateSpriteImage: ; 5157 (1:5157)
; d: Y movement delta (-1, 0 or 1)
; e: X movement delta (-1, 0 or 1)
; set carry on failure, clears carry on success
-CanWalkOntoTile: ; 516e (1:516e)
- ld h, $c2
+CanWalkOntoTile:
+ ld h, wSpriteStateData2 / $100
ld a, [H_CURRENTSPRITEOFFSET]
add $6
ld l, a
ld a, [hl] ; c2x6 (movement byte 1)
cp $fe
- jr nc, .canMove ; values $fe and $ff
+ jr nc, .notScripted ; values $fe and $ff
+; always allow walking if the movement is scripted
and a
ret
-.canMove
- ld a, [W_TILESETCOLLISIONPTR]
+.notScripted
+ ld a, [wTilesetCollisionPtr]
ld l, a
- ld a, [W_TILESETCOLLISIONPTR+1]
+ ld a, [wTilesetCollisionPtr+1]
ld h, a
.tilePassableLoop
ld a, [hli]
@@ -593,7 +606,7 @@ CanWalkOntoTile: ; 516e (1:516e)
ld a, [hl] ; $c2x6 (movement byte 1)
inc a
jr z, .impassable ; if $ff, no movement allowed (however, changing direction is)
- ld h, $c1
+ ld h, wSpriteStateData1 / $100
ld a, [H_CURRENTSPRITEOFFSET]
add $4
ld l, a
@@ -612,14 +625,14 @@ CanWalkOntoTile: ; 516e (1:516e)
call DetectCollisionBetweenSprites
pop bc
pop de
- ld h, $c1
+ ld h, wSpriteStateData1 / $100
ld a, [H_CURRENTSPRITEOFFSET]
add $c
ld l, a
ld a, [hl] ; c1xc (directions in which sprite collision would occur)
and b ; check against chosen direction (1,2,4 or 8)
jr nz, .impassable ; collision between sprites, don't go there
- ld h, $c2
+ ld h, wSpriteStateData2 / $100
ld a, [H_CURRENTSPRITEOFFSET]
add $2
ld l, a
@@ -675,8 +688,8 @@ CanWalkOntoTile: ; 516e (1:516e)
; calculates the tile pointer pointing to the tile the current sprite stancs on
; this is always the lower left tile of the 2x2 tile blocks all sprites are snapped to
; hl: output pointer
-getTileSpriteStandsOn: ; 5207 (1:5207)
- ld h, $c1
+GetTileSpriteStandsOn:
+ ld h, wSpriteStateData1 / $100
ld a, [H_CURRENTSPRITEOFFSET]
add $4
ld l, a
@@ -690,11 +703,11 @@ getTileSpriteStandsOn: ; 5207 (1:5207)
ld a, [hl] ; c1x6: screen Y position
srl a
srl a
- srl a ; screen X tile
- add $14 ; screen X tile + 20
+ srl a ; screen X tile
+ add SCREEN_WIDTH ; screen X tile + 20
ld d, $0
ld e, a
- ld hl, wTileMap
+ coord hl, 0, 0
add hl, bc
add hl, bc
add hl, bc
@@ -704,7 +717,7 @@ getTileSpriteStandsOn: ; 5207 (1:5207)
ret
; loads [de+a] into a
-LoadDEPlusA: ; 522f (1:522f)
+LoadDEPlusA:
add e
ld e, a
jr nc, .noCarry
@@ -713,53 +726,58 @@ LoadDEPlusA: ; 522f (1:522f)
ld a, [de]
ret
-Func_5236: ; 5236 (1:5236)
+DoScriptedNPCMovement:
+; This is an alternative method of scripting an NPC's movement and is only used
+; a few times in the game. It is used when the NPC and player must walk together
+; in sync, such as when the player is following the NPC somewhere. An NPC can't
+; be moved in sync with the player using the other method.
ld a, [wd730]
bit 7, a
ret z
ld hl, wd72e
bit 7, [hl]
set 7, [hl]
- jp z, Func_52a6
+ jp z, InitScriptedNPCMovement
ld hl, wNPCMovementDirections2
ld a, [wNPCMovementDirections2Index]
add l
ld l, a
- jr nc, .asm_5251
+ jr nc, .noCarry
inc h
-.asm_5251
+.noCarry
ld a, [hl]
- cp $40
- jr nz, .asm_525f
- call Func_52b2
- ld c, $4
- ld a, $fe
- jr .asm_5289
-.asm_525f
- cp $0
- jr nz, .asm_526c
- call Func_52b2
- ld c, $0
- ld a, $2
- jr .asm_5289
-.asm_526c
- cp $80
- jr nz, .asm_5279
- call Func_52b7
- ld c, $8
- ld a, $fe
- jr .asm_5289
-.asm_5279
- cp $c0
- jr nz, .asm_5286
- call Func_52b7
- ld c, $c
- ld a, $2
- jr .asm_5289
-.asm_5286
+; check if moving up
+ cp NPC_MOVEMENT_UP
+ jr nz, .checkIfMovingDown
+ call GetSpriteScreenYPointer
+ ld c, SPRITE_FACING_UP
+ ld a, -2
+ jr .move
+.checkIfMovingDown
+ cp NPC_MOVEMENT_DOWN
+ jr nz, .checkIfMovingLeft
+ call GetSpriteScreenYPointer
+ ld c, SPRITE_FACING_DOWN
+ ld a, 2
+ jr .move
+.checkIfMovingLeft
+ cp NPC_MOVEMENT_LEFT
+ jr nz, .checkIfMovingRight
+ call GetSpriteScreenXPointer
+ ld c, SPRITE_FACING_LEFT
+ ld a, -2
+ jr .move
+.checkIfMovingRight
+ cp NPC_MOVEMENT_RIGHT
+ jr nz, .noMatch
+ call GetSpriteScreenXPointer
+ ld c, SPRITE_FACING_RIGHT
+ ld a, 2
+ jr .move
+.noMatch
cp $ff
ret
-.asm_5289
+.move
ld b, a
ld a, [hl]
add b
@@ -768,33 +786,34 @@ Func_5236: ; 5236 (1:5236)
add $9
ld l, a
ld a, c
- ld [hl], a
- call Func_52c3
- ld hl, wcf18
+ ld [hl], a ; facing direction
+ call AnimScriptedNPCMovement
+ ld hl, wScriptedNPCWalkCounter
dec [hl]
ret nz
- ld a, $8
- ld [wcf18], a
+ ld a, 8
+ ld [wScriptedNPCWalkCounter], a
ld hl, wNPCMovementDirections2Index
inc [hl]
ret
-Func_52a6: ; 52a6 (1:52a6)
+InitScriptedNPCMovement:
xor a
ld [wNPCMovementDirections2Index], a
- ld a, $8
- ld [wcf18], a
- jp Func_52c3
+ ld a, 8
+ ld [wScriptedNPCWalkCounter], a
+ jp AnimScriptedNPCMovement
-Func_52b2: ; 52b2 (1:52b2)
+GetSpriteScreenYPointer:
ld a, $4
ld b, a
- jr asm_52ba
+ jr GetSpriteScreenXYPointerCommon
-Func_52b7: ; 52b7 (1:52b7)
+GetSpriteScreenXPointer:
ld a, $6
ld b, a
-asm_52ba: ; 52ba (1:52ba)
+
+GetSpriteScreenXYPointerCommon:
ld hl, wSpriteStateData1
ld a, [H_CURRENTSPRITEOFFSET]
add l
@@ -802,12 +821,12 @@ asm_52ba: ; 52ba (1:52ba)
ld l, a
ret
-Func_52c3: ; 52c3 (1:52c3)
+AnimScriptedNPCMovement:
ld hl, wSpriteStateData2
ld a, [H_CURRENTSPRITEOFFSET]
add $e
ld l, a
- ld a, [hl]
+ ld a, [hl] ; VRAM slot
dec a
swap a
ld b, a
@@ -815,47 +834,47 @@ Func_52c3: ; 52c3 (1:52c3)
ld a, [H_CURRENTSPRITEOFFSET]
add $9
ld l, a
- ld a, [hl]
- cp $0
- jr z, .asm_52ea
- cp $4
- jr z, .asm_52ea
- cp $8
- jr z, .asm_52ea
- cp $c
- jr z, .asm_52ea
+ ld a, [hl] ; facing direction
+ cp SPRITE_FACING_DOWN
+ jr z, .anim
+ cp SPRITE_FACING_UP
+ jr z, .anim
+ cp SPRITE_FACING_LEFT
+ jr z, .anim
+ cp SPRITE_FACING_RIGHT
+ jr z, .anim
ret
-.asm_52ea
+.anim
add b
ld b, a
- ld [$ffe9], a
- call Func_5301
+ ld [hSpriteVRAMSlotAndFacing], a
+ call AdvanceScriptedNPCAnimFrameCounter
ld hl, wSpriteStateData1
ld a, [H_CURRENTSPRITEOFFSET]
add $2
ld l, a
- ld a, [$ffe9]
+ ld a, [hSpriteVRAMSlotAndFacing]
ld b, a
- ld a, [$ffea]
+ ld a, [hSpriteAnimFrameCounter]
add b
ld [hl], a
ret
-Func_5301: ; 5301 (1:5301)
+AdvanceScriptedNPCAnimFrameCounter:
ld a, [H_CURRENTSPRITEOFFSET]
add $7
ld l, a
- ld a, [hl]
+ ld a, [hl] ; intra-animation frame counter
inc a
ld [hl], a
- cp $4
+ cp 4
ret nz
xor a
- ld [hl], a
+ ld [hl], a ; reset intra-animation frame counter
inc l
- ld a, [hl]
+ ld a, [hl] ; animation frame counter
inc a
and $3
ld [hl], a
- ld [$ffea], a
+ ld [hSpriteAnimFrameCounter], a
ret
diff --git a/engine/overworld/npc_movement.asm b/engine/overworld/npc_movement.asm
index 84e39853..98d1b7a7 100755
--- a/engine/overworld/npc_movement.asm
+++ b/engine/overworld/npc_movement.asm
@@ -1,4 +1,4 @@
-PlayerStepOutFromDoor: ; 1a3e0 (6:63e0)
+PlayerStepOutFromDoor:
ld hl, wd730
res 1, [hl]
call IsPlayerStandingOnDoorTile
@@ -27,7 +27,7 @@ PlayerStepOutFromDoor: ; 1a3e0 (6:63e0)
res 7, [hl]
ret
-_EndNPCMovementScript: ; 1a41d (6:641d)
+_EndNPCMovementScript:
ld hl, wd730
res 7, [hl]
ld hl, wd72e
@@ -44,60 +44,66 @@ _EndNPCMovementScript: ; 1a41d (6:641d)
ld [wSimulatedJoypadStatesEnd], a
ret
-ProfOakMovementScriptPointerTable: ; 1a442 (6:6442)
- dw Func_1a44c
- dw Func_1a485
- dw Func_1a4a1
- dw Func_1a4a6
- dw Func_1a4f4
+PalletMovementScriptPointerTable:
+ dw PalletMovementScript_OakMoveLeft
+ dw PalletMovementScript_PlayerMoveLeft
+ dw PalletMovementScript_WaitAndWalkToLab
+ dw PalletMovementScript_WalkToLab
+ dw PalletMovementScript_Done
-Func_1a44c: ; 1a44c (6:644c)
- ld a, [W_XCOORD] ; wd362
+PalletMovementScript_OakMoveLeft:
+ ld a, [wXCoord]
sub $a
- ld [wcca1], a
- jr z, .asm_1a475
- ld b, $0
+ ld [wNumStepsToTake], a
+ jr z, .playerOnLeftTile
+; The player is on the right tile of the northern path out of Pallet Town and
+; Prof. Oak is below.
+; Make Prof. Oak step to the left.
+ ld b, 0
ld c, a
ld hl, wNPCMovementDirections2
- ld a, $80
+ ld a, NPC_MOVEMENT_LEFT
call FillMemory
ld [hl], $ff
ld a, [wSpriteIndex]
- ld [H_DOWNARROWBLINKCNT2], a ; $ff8c
+ ld [H_SPRITEINDEX], a
ld de, wNPCMovementDirections2
call MoveSprite
ld a, $1
ld [wNPCMovementScriptFunctionNum], a
- jr .asm_1a47a
-.asm_1a475
+ jr .done
+; The player is on the left tile of the northern path out of Pallet Town and
+; Prof. Oak is below.
+; Prof. Oak is already where he needs to be.
+.playerOnLeftTile
ld a, $3
ld [wNPCMovementScriptFunctionNum], a
-.asm_1a47a
- ld hl, W_FLAGS_D733
+.done
+ ld hl, wFlags_D733
set 1, [hl]
ld a, $fc
ld [wJoyIgnore], a
ret
-Func_1a485: ; 1a485 (6:6485)
+PalletMovementScript_PlayerMoveLeft:
ld a, [wd730]
- bit 0, a
- ret nz
- ld a, [wcca1]
+ bit 0, a ; is an NPC being moved by a script?
+ ret nz ; return if Oak is still moving
+ ld a, [wNumStepsToTake]
ld [wSimulatedJoypadStatesIndex], a
- ld [$ff95], a
+ ld [hNPCMovementDirections2Index], a
predef ConvertNPCMovementDirectionsToJoypadMasks
call StartSimulatingJoypadStates
ld a, $2
ld [wNPCMovementScriptFunctionNum], a
ret
-Func_1a4a1: ; 1a4a1 (6:64a1)
+PalletMovementScript_WaitAndWalkToLab:
ld a, [wSimulatedJoypadStatesIndex]
- and a
+ and a ; is the player done moving left yet?
ret nz
-Func_1a4a6: ; 1a4a6 (6:64a6)
+PalletMovementScript_WalkToLab:
xor a
ld [wOverrideSimulatedJoypadStatesMask], a
ld a, [wSpriteIndex]
@@ -121,16 +127,16 @@ Func_1a4a6: ; 1a4a6 (6:64a6)
ld [wNPCMovementScriptFunctionNum], a
ret
-RLEList_ProfOakWalkToLab: ; 1a4dc (6:64dc)
- db $00, $05
- db $80, $01
- db $00, $05
- db $C0, $03
- db $40, $01
- db $E0, $01
+RLEList_ProfOakWalkToLab:
+ db NPC_MOVEMENT_DOWN, $05
+ db NPC_MOVEMENT_LEFT, $01
+ db NPC_MOVEMENT_DOWN, $05
+ db NPC_MOVEMENT_RIGHT, $03
+ db NPC_MOVEMENT_UP, $01
+ db $E0, $01 ; stand still
db $FF
-RLEList_PlayerWalkToLab: ; 1a4e9 (6:64e9)
+RLEList_PlayerWalkToLab:
db D_UP, $02
db D_RIGHT, $03
db D_DOWN, $05
@@ -138,12 +144,12 @@ RLEList_PlayerWalkToLab: ; 1a4e9 (6:64e9)
db D_DOWN, $06
db $FF
-Func_1a4f4: ; 1a4f4 (6:64f4)
+PalletMovementScript_Done:
ld a, [wSimulatedJoypadStatesIndex]
and a
ret nz
ld a, $0
- ld [wcc4d], a
+ ld [wMissableObjectIndex], a
predef HideObject
ld hl, wd730
res 7, [hl]
@@ -151,16 +157,16 @@ Func_1a4f4: ; 1a4f4 (6:64f4)
res 7, [hl]
jp EndNPCMovementScript
-PewterMuseumGuyMovementScriptPointerTable: ; 1a510 (6:6510)
- dw Func_1a514
- dw PewterMovementScriptDone
+PewterMuseumGuyMovementScriptPointerTable:
+ dw PewterMovementScript_WalkToMuseum
+ dw PewterMovementScript_Done
-Func_1a514: ; 1a514 (6:6514)
+PewterMovementScript_WalkToMuseum:
ld a, BANK(Music_MuseumGuy)
- ld [wc0ef], a
- ld [wc0f0], a
+ ld [wAudioROMBank], a
+ ld [wAudioSavedROMBank], a
ld a, MUSIC_MUSEUM_GUY
- ld [wc0ee], a
+ ld [wNewSoundID], a
call PlaySound
ld a, [wSpriteIndex]
swap a
@@ -172,7 +178,7 @@ Func_1a514: ; 1a514 (6:6514)
dec a
ld [wSimulatedJoypadStatesIndex], a
xor a
- ld [wd12f], a
+ ld [wWhichPewterGuy], a
predef PewterGuys
ld hl, wNPCMovementDirections2
ld de, RLEList_PewterMuseumGuy
@@ -183,21 +189,21 @@ Func_1a514: ; 1a514 (6:6514)
ld [wNPCMovementScriptFunctionNum], a
ret
-RLEList_PewterMuseumPlayer: ; 1a559 (6:6559)
+RLEList_PewterMuseumPlayer:
db 0, $01
db D_UP, $03
db D_LEFT, $0D
db D_UP, $06
db $FF
-RLEList_PewterMuseumGuy: ; 1a562 (6:6562)
- db $40, $06
- db $80, $0D
- db $40, $03
- db $80, $01
+RLEList_PewterMuseumGuy:
+ db NPC_MOVEMENT_UP, $06
+ db NPC_MOVEMENT_LEFT, $0D
+ db NPC_MOVEMENT_UP, $03
+ db NPC_MOVEMENT_LEFT, $01
db $FF
-PewterMovementScriptDone: ; 1a56b (6:656b)
+PewterMovementScript_Done:
ld a, [wSimulatedJoypadStatesIndex]
and a
ret nz
@@ -207,16 +213,16 @@ PewterMovementScriptDone: ; 1a56b (6:656b)
res 7, [hl]
jp EndNPCMovementScript
-PewterGymGuyMovementScriptPointerTable: ; 1a57d (6:657d)
- dw Func_1a581
- dw PewterMovementScriptDone
+PewterGymGuyMovementScriptPointerTable:
+ dw PewterMovementScript_WalkToGym
+ dw PewterMovementScript_Done
-Func_1a581: ; 1a581 (6:6581)
+PewterMovementScript_WalkToGym:
ld a, BANK(Music_MuseumGuy)
- ld [wc0ef], a
- ld [wc0f0], a
+ ld [wAudioROMBank], a
+ ld [wAudioSavedROMBank], a
ld a, MUSIC_MUSEUM_GUY
- ld [wc0ee], a
+ ld [wNewSoundID], a
call PlaySound
ld a, [wSpriteIndex]
swap a
@@ -228,8 +234,8 @@ Func_1a581: ; 1a581 (6:6581)
call DecodeRLEList
dec a
ld [wSimulatedJoypadStatesIndex], a
- ld a, $1
- ld [wd12f], a
+ ld a, 1
+ ld [wWhichPewterGuy], a
predef PewterGuys
ld hl, wNPCMovementDirections2
ld de, RLEList_PewterGymGuy
@@ -242,7 +248,7 @@ Func_1a581: ; 1a581 (6:6581)
ld [wNPCMovementScriptFunctionNum], a
ret
-RLEList_PewterGymPlayer: ; 1a5cd (6:65cd)
+RLEList_PewterGymPlayer:
db 0, $01
db D_RIGHT, $02
db D_DOWN, $05
@@ -251,17 +257,17 @@ RLEList_PewterGymPlayer: ; 1a5cd (6:65cd)
db D_LEFT, $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
+RLEList_PewterGymGuy:
+ db NPC_MOVEMENT_DOWN, $02
+ db NPC_MOVEMENT_LEFT, $0F
+ db NPC_MOVEMENT_UP, $05
+ db NPC_MOVEMENT_LEFT, $0B
+ db NPC_MOVEMENT_DOWN, $05
+ db NPC_MOVEMENT_RIGHT, $03
db $FF
-FreezeEnemyTrainerSprite: ; 1a5e7 (6:65e7)
- ld a, [W_CURMAP]
+FreezeEnemyTrainerSprite:
+ ld a, [wCurMap]
cp POKEMONTOWER_7
ret z ; the Rockets on Pokemon Tower 7F leave after battling, so don't freeze them
ld hl, RivalIDs
@@ -279,8 +285,8 @@ FreezeEnemyTrainerSprite: ; 1a5e7 (6:65e7)
ld [H_SPRITEINDEX], a
jp SetSpriteMovementBytesToFF
-RivalIDs: ; 1a605 (6:6605)
- db SONY1 + $c8
- db SONY2 + $c8
- db SONY3 + $c8
+RivalIDs:
+ db OPP_SONY1
+ db OPP_SONY2
+ db OPP_SONY3
db $ff
diff --git a/engine/overworld/oaks_aide.asm b/engine/overworld/oaks_aide.asm
index 68135287..f5068fda 100755
--- a/engine/overworld/oaks_aide.asm
+++ b/engine/overworld/oaks_aide.asm
@@ -1,71 +1,71 @@
-OaksAideScript ; 0x59035
+OaksAideScript:
ld hl, OaksAideHiText
call PrintText
call YesNoChoice
ld a, [wCurrentMenuItem]
and a
- jr nz, .asm_59086 ; 0x59042 $42
+ jr nz, .choseNo
ld hl, wPokedexOwned
ld b, wPokedexOwnedEnd - wPokedexOwned
call CountSetBits
- ld a, [wd11e]
- ld [$ffdd], a
+ ld a, [wNumSetBits]
+ ld [hOaksAideNumMonsOwned], a
ld b, a
- ld a, [$ffdb]
+ ld a, [hOaksAideRequirement]
cp b
- jr z, .asm_59059 ; 0x59055 $2
- jr nc, .asm_5907c ; 0x59057 $23
-.asm_59059
+ jr z, .giveItem
+ jr nc, .notEnoughOwnedMons
+.giveItem
ld hl, OaksAideHereYouGoText
call PrintText
- ld a, [$ffdc]
+ ld a, [hOaksAideRewardItem]
ld b, a
ld c, 1
call GiveItem
- jr nc, .BagFull
+ jr nc, .bagFull
ld hl, OaksAideGotItemText
call PrintText
ld a, $1
- jr .asm_5908e ; 0x59071 $1b
-.BagFull
+ jr .done
+.bagFull
ld hl, OaksAideNoRoomText
call PrintText
xor a
- jr .asm_5908e ; 0x5907a $12
-.asm_5907c
+ jr .done
+.notEnoughOwnedMons
ld hl, OaksAideUhOhText
call PrintText
ld a, $80
- jr .asm_5908e ; 0x59084 $8
-.asm_59086
+ jr .done
+.choseNo
ld hl, OaksAideComeBackText
call PrintText
ld a, $ff
-.asm_5908e
- ld [$ffdb], a
+.done
+ ld [hOaksAideResult], a
ret
-OaksAideHiText: ; 59091 (16:5091)
+OaksAideHiText:
TX_FAR _OaksAideHiText
db "@"
-OaksAideUhOhText: ; 59096 (16:5096)
+OaksAideUhOhText:
TX_FAR _OaksAideUhOhText
db "@"
-OaksAideComeBackText: ; 5909b (16:509b)
+OaksAideComeBackText:
TX_FAR _OaksAideComeBackText
db "@"
-OaksAideHereYouGoText: ; 590a0 (16:50a0)
+OaksAideHereYouGoText:
TX_FAR _OaksAideHereYouGoText
db "@"
-OaksAideGotItemText: ; 590a5 (16:50a5)
+OaksAideGotItemText:
TX_FAR _OaksAideGotItemText
- db $0b
+ TX_SFX_ITEM_1
db "@"
-OaksAideNoRoomText: ; 590ab (16:50ab)
+OaksAideNoRoomText:
TX_FAR _OaksAideNoRoomText
db "@"
diff --git a/engine/overworld/oam.asm b/engine/overworld/oam.asm
index b4247257..2c2a3dff 100644
--- a/engine/overworld/oam.asm
+++ b/engine/overworld/oam.asm
@@ -4,25 +4,26 @@ PrepareOAMData:
ld a, [wUpdateSpritesEnabled]
dec a
- jr z, .asm_4b1e
+ jr z, .updateEnabled
- cp 0 - 1
+ cp -1
ret nz
ld [wUpdateSpritesEnabled], a
jp HideSprites
-.asm_4b1e
+.updateEnabled
xor a
- ld [$ff90], a
-.asm_4b21
- ld [$ff8f], a
+ ld [hOAMBufferOffset], a
+
+.spriteLoop
+ ld [hSpriteOffset2], a
ld d, wSpriteStateData1 / $100
- ld a, [$ff8f]
+ ld a, [hSpriteOffset2]
ld e, a
ld a, [de] ; c1x0
and a
- jp z, .asm_4bad
+ jp z, .nextSprite
inc e
inc e
@@ -31,21 +32,25 @@ PrepareOAMData:
cp $ff ; off-screen (don't draw)
jr nz, .visible
- call Func_4bd1
- jr .asm_4bad
+ call GetSpriteScreenXY
+ jr .nextSprite
.visible
- cp $a0
+ cp $a0 ; is the sprite unchanging like an item ball or boulder?
jr c, .usefacing
+
+; unchanging
and $f
- add $10
- jr .asm_4b48
+ add $10 ; skip to the second half of the table which doesn't account for facing direction
+ jr .next
.usefacing
and $f
-.asm_4b48
+
+.next
ld l, a
+; get sprite priority
push de
inc d
ld a, e
@@ -53,15 +58,15 @@ PrepareOAMData:
ld e, a
ld a, [de] ; c2x7
and $80
- ld [$ff94], a ; temp store sprite priority
+ ld [hSpritePriority], a ; temp store sprite priority
pop de
+; read the entry from the table
ld h, 0
ld bc, SpriteFacingAndAnimationTable
add hl, hl
add hl, hl
add hl, bc
-
ld a, [hli]
ld c, a
ld a, [hli]
@@ -70,24 +75,25 @@ PrepareOAMData:
ld h, [hl]
ld l, a
- call Func_4bd1
+ call GetSpriteScreenXY
- ld a, [$ff90]
+ ld a, [hOAMBufferOffset]
ld e, a
ld d, wOAMBuffer / $100
-.tile
- ld a, [$ff92] ; temp for sprite Y position
+
+.tileLoop
+ ld a, [hSpriteScreenY] ; temp for sprite Y position
add $10 ; Y=16 is top of screen (Y=0 is invisible)
add [hl] ; add Y offset from table
ld [de], a ; write new sprite OAM Y position
inc hl
- ld a, [$ff91] ; temp for sprite X position
+ ld a, [hSpriteScreenX] ; temp for sprite X position
add $8 ; X=8 is left of screen (X=0 is invisible)
add [hl] ; add X offset from table
inc e
ld [de], a ; write new sprite OAM X position
inc e
- ld a, [bc] ; read pattern number offset (accomodates orientation (offset 0,4 or 8) and animation (offset 0 or $80))
+ ld a, [bc] ; read pattern number offset (accommodates orientation (offset 0,4 or 8) and animation (offset 0 or $80))
inc bc
push bc
ld b, a
@@ -99,55 +105,60 @@ PrepareOAMData:
; Sprites $a and $b have one face (and therefore 4 tiles instead of 12).
; As a result, sprite $b's tile offset is less than normal.
cp $b
- jr nz, .offset
+ jr nz, .notFourTileSprite
ld a, $a * 12 + 4
- jr .gotoffset
+ jr .next2
-.offset
+.notFourTileSprite
; a *= 12
sla a
sla a
ld c, a
sla a
add c
-.gotoffset
- add b ; which frame
+
+.next2
+ add b ; add the tile offset from the table (based on frame and facing direction)
pop bc
ld [de], a ; tile id
inc hl
inc e
ld a, [hl]
- bit 1, a ; sprite priority
- jr z, .fg
- ld a, [$ff94] ; facing priority
+ bit 1, a ; is the tile allowed to set the sprite priority bit?
+ jr z, .skipPriority
+ ld a, [hSpritePriority]
or [hl]
-.fg
+.skipPriority
inc hl
ld [de], a
inc e
bit 0, a ; OAMFLAG_ENDOFDATA
- jr z, .tile
+ jr z, .tileLoop
ld a, e
- ld [$ff90], a
+ ld [hOAMBufferOffset], a
-.asm_4bad
- ld a, [$ff8f]
+.nextSprite
+ ld a, [hSpriteOffset2]
add $10
cp $100 % $100
- jp nz, .asm_4b21
+ jp nz, .spriteLoop
; Clear unused OAM.
- ld a, [$ff90]
+ ld a, [hOAMBufferOffset]
ld l, a
ld h, wOAMBuffer / $100
ld de, $4
ld b, $a0
ld a, [wd736]
- bit 6, a
+ bit 6, a ; jumping down ledge or fishing animation?
ld a, $a0
jr z, .clear
+
+; Don't clear the last 4 entries because they are used for the shadow in the
+; jumping down ledge animation and the rod in the fishing animation.
ld a, $90
+
.clear
cp l
ret z
@@ -155,24 +166,24 @@ PrepareOAMData:
add hl, de
jr .clear
-Func_4bd1: ; 4bd1 (1:4bd1)
+GetSpriteScreenXY:
inc e
inc e
ld a, [de] ; c1x4
- ld [$ff92], a
+ ld [hSpriteScreenY], a
inc e
inc e
ld a, [de] ; c1x6
- ld [$ff91], a
- ld a, $4
+ ld [hSpriteScreenX], a
+ ld a, 4
add e
ld e, a
- ld a, [$ff92]
- add $4
+ ld a, [hSpriteScreenY]
+ add 4
and $f0
ld [de], a ; c1xa (y)
inc e
- ld a, [$ff91]
+ ld a, [hSpriteScreenX]
and $f0
ld [de], a ; c1xb (x)
ret
diff --git a/engine/overworld/pewter_guys.asm b/engine/overworld/pewter_guys.asm
index eb6dd5ac..532fa4bf 100755
--- a/engine/overworld/pewter_guys.asm
+++ b/engine/overworld/pewter_guys.asm
@@ -1,4 +1,4 @@
-PewterGuys: ; 37ca1 (d:7ca1)
+PewterGuys:
ld hl, wSimulatedJoypadStatesEnd
ld a, [wSimulatedJoypadStatesIndex]
dec a ; this decrement causes it to overwrite the last byte before $FF in the list
@@ -9,7 +9,7 @@ PewterGuys: ; 37ca1 (d:7ca1)
ld d, h
ld e, l
ld hl, PointerTable_37ce6
- ld a, [wd12f]
+ ld a, [wWhichPewterGuy]
add a
ld b, 0
ld c, a
@@ -17,21 +17,21 @@ PewterGuys: ; 37ca1 (d:7ca1)
ld a, [hli]
ld h, [hl]
ld l, a
- ld a, [W_YCOORD]
+ ld a, [wYCoord]
ld b, a
- ld a, [W_XCOORD]
+ ld a, [wXCoord]
ld c, a
-.asm_37cc7
+.findMatchingCoordsLoop
ld a, [hli]
cp b
- jr nz, .asm_37ce1
+ jr nz, .nextEntry1
ld a, [hli]
cp c
- jr nz, .asm_37ce2
+ jr nz, .nextEntry2
ld a, [hli]
ld h, [hl]
ld l, a
-.asm_37cd2
+.copyMovementDataLoop
ld a, [hli]
cp $ff
ret z
@@ -40,22 +40,22 @@ PewterGuys: ; 37ca1 (d:7ca1)
ld a, [wSimulatedJoypadStatesIndex]
inc a
ld [wSimulatedJoypadStatesIndex], a
- jr .asm_37cd2
-.asm_37ce1
+ jr .copyMovementDataLoop
+.nextEntry1
inc hl
-.asm_37ce2
+.nextEntry2
inc hl
inc hl
- jr .asm_37cc7
+ jr .findMatchingCoordsLoop
-PointerTable_37ce6: ; 37ce6 (d:7ce6)
+PointerTable_37ce6:
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)
+PewterMuseumGuyCoords:
db 18, 27
dw .down
db 16, 27
@@ -66,18 +66,19 @@ PewterMuseumGuyCoords: ; 37cea (d:7cea)
dw .right
.down
- db $40, $40, $ff
+ db D_UP, D_UP, $ff
.up
- db $10, $20, $ff
+ db D_RIGHT, D_LEFT, $ff
.left
- db $40, $10, $ff
+ db D_UP, D_RIGHT, $ff
.right
- db $40, $20, $ff
+ db D_UP, D_LEFT, $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)
+; $00 is a pause
+PewterGymGuyCoords:
db 16, 34
dw .one
db 17, 35
@@ -90,12 +91,12 @@ PewterGymGuyCoords: ; 37d06 (d:7d06)
dw .five
.one
- db $20, $80, $80, $10, $ff
+ db D_LEFT, D_DOWN, D_DOWN, D_RIGHT, $ff
.two
- db $20, $80, $10, $20, $ff
+ db D_LEFT, D_DOWN, D_RIGHT, D_LEFT, $ff
.three
- db $20, $20, $20, $00, $00, $00, $00, $00, $00, $00, $00, $ff
+ db D_LEFT, D_LEFT, D_LEFT, $00, $00, $00, $00, $00, $00, $00, $00, $ff
.four
- db $20, $20, $40, $20, $ff
+ db D_LEFT, D_LEFT, D_UP, D_LEFT, $ff
.five
- db $20, $80, $20, $00, $00, $00, $00, $00, $00, $00, $00, $ff
+ db D_LEFT, D_DOWN, D_LEFT, $00, $00, $00, $00, $00, $00, $00, $00, $ff
diff --git a/engine/overworld/player_animations.asm b/engine/overworld/player_animations.asm
index 6602cedd..a17e67bd 100755
--- a/engine/overworld/player_animations.asm
+++ b/engine/overworld/player_animations.asm
@@ -1,15 +1,15 @@
-EnterMapAnim: ; 70510 (1c:4510)
- call InitFacingDirectionBuffer
+EnterMapAnim:
+ call InitFacingDirectionList
ld a, $ec
ld [wSpriteStateData1 + 4], a ; player's sprite Y screen position
call Delay3
push hl
call GBFadeInFromWhite
- ld hl, W_FLAGS_D733
+ ld hl, wFlags_D733
bit 7, [hl] ; used fly out of battle?
res 7, [hl]
jr nz, .flyAnimation
- ld a, (SFX_02_4c - SFX_Headers_02) / 3
+ ld a, SFX_TELEPORT_ENTER_1
call PlaySound
ld hl, wd732
bit 4, [hl] ; used dungeon warp?
@@ -17,7 +17,7 @@ EnterMapAnim: ; 70510 (1c:4510)
pop hl
jr nz, .dungeonWarpAnimation
call PlayerSpinWhileMovingDown
- ld a, (SFX_02_4f - SFX_Headers_02) / 3
+ ld a, SFX_TELEPORT_ENTER_2
call PlaySound
call IsPlayerStandingOnWarpPadOrHole
ld a, b
@@ -32,7 +32,7 @@ EnterMapAnim: ; 70510 (1c:4510)
ld a, $8
ld [hli], a ; wPlayerSpinInPlaceAnimFrameDelayEndValue
ld [hl], $ff ; wPlayerSpinInPlaceAnimSoundID
- ld hl, wcd48
+ ld hl, wFacingDirectionList
call PlayerSpinInPlace
.restoreDefaultMusic
call PlayDefaultMusic
@@ -47,10 +47,10 @@ EnterMapAnim: ; 70510 (1c:4510)
pop hl
ld de, BirdSprite
ld hl, vNPCSprites
- ld bc, (BANK(BirdSprite) << 8) + $0c
+ lb bc, BANK(BirdSprite), $0c
call CopyVideoData
call LoadBirdSpriteGraphics
- ld a, (SFX_02_50 - SFX_Headers_02) / 3
+ ld a, SFX_FLY
call PlaySound
ld hl, wFlyAnimUsingCoordList
xor a ; is using coord list
@@ -58,12 +58,12 @@ EnterMapAnim: ; 70510 (1c:4510)
ld a, 12
ld [hli], a ; wFlyAnimCounter
ld [hl], $8 ; wFlyAnimBirdSpriteImageIndex (facing right)
- ld de, FlyAnimationEnterScreenCoords ; $4592
+ ld de, FlyAnimationEnterScreenCoords
call DoFlyAnimation
call LoadPlayerSpriteGraphics
jr .restoreDefaultMusic
-FlyAnimationEnterScreenCoords: ; 70592 (1c:4592)
+FlyAnimationEnterScreenCoords:
; y, x pairs
; This is the sequence of screen coordinates used by the overworld
; Fly animation when the player is entering a map.
@@ -80,7 +80,7 @@ FlyAnimationEnterScreenCoords: ; 70592 (1c:4592)
db $3C, $48
db $3C, $40
-PlayerSpinWhileMovingDown: ; 705aa (1c:45aa)
+PlayerSpinWhileMovingDown:
ld hl, wPlayerSpinWhileMovingUpOrDownAnimDeltaY
ld a, $10
ld [hli], a ; wPlayerSpinWhileMovingUpOrDownAnimDeltaY
@@ -90,8 +90,8 @@ PlayerSpinWhileMovingDown: ; 705aa (1c:45aa)
ld [hl], a ; wPlayerSpinWhileMovingUpOrDownAnimFrameDelay
jp PlayerSpinWhileMovingUpOrDown
-_LeaveMapAnim: ; 705ba (1c:45ba)
- call InitFacingDirectionBuffer
+_LeaveMapAnim:
+ call InitFacingDirectionList
call IsPlayerStandingOnWarpPadOrHole
ld a, b
and a
@@ -99,7 +99,7 @@ _LeaveMapAnim: ; 705ba (1c:45ba)
dec a
jp nz, LeaveMapThroughHoleAnim
.spinWhileMovingUp
- ld a, (SFX_02_4b - SFX_Headers_02) / 3
+ ld a, SFX_TELEPORT_EXIT_1
call PlaySound
ld hl, wPlayerSpinWhileMovingUpOrDownAnimDeltaY
ld a, -$10
@@ -133,8 +133,8 @@ _LeaveMapAnim: ; 705ba (1c:45ba)
ld [hli], a ; wPlayerSpinInPlaceAnimFrameDelayDelta
xor a
ld [hli], a ; wPlayerSpinInPlaceAnimFrameDelayEndValue
- ld [hl], (SFX_02_4d - SFX_Headers_02) / 3 ; wPlayerSpinInPlaceAnimSoundID
- ld hl, wcd48
+ ld [hl], SFX_TELEPORT_EXIT_2 ; wPlayerSpinInPlaceAnimSoundID
+ ld hl, wFacingDirectionList
call PlayerSpinInPlace
jr .spinWhileMovingUp
.flyAnimation
@@ -146,7 +146,7 @@ _LeaveMapAnim: ; 705ba (1c:45ba)
ld [hli], a ; wFlyAnimCounter
ld [hl], $c ; wFlyAnimBirdSpriteImageIndex
call DoFlyAnimation
- ld a, (SFX_02_50 - SFX_Headers_02) / 3
+ ld a, SFX_FLY
call PlaySound
ld hl, wFlyAnimUsingCoordList
xor a ; is using coord list
@@ -154,7 +154,7 @@ _LeaveMapAnim: ; 705ba (1c:45ba)
ld a, $c
ld [hli], a ; wFlyAnimCounter
ld [hl], $c ; wFlyAnimBirdSpriteImageIndex (facing right)
- ld de, FlyAnimationScreenCoords1 ; $464f
+ ld de, FlyAnimationScreenCoords1
call DoFlyAnimation
ld c, 40
call DelayFrames
@@ -162,12 +162,12 @@ _LeaveMapAnim: ; 705ba (1c:45ba)
ld a, 11
ld [hli], a ; wFlyAnimCounter
ld [hl], $8 ; wFlyAnimBirdSpriteImageIndex (facing left)
- ld de, FlyAnimationScreenCoords2 ; $4667
+ ld de, FlyAnimationScreenCoords2
call DoFlyAnimation
call GBFadeOutToWhite
jp RestoreFacingDirectionAndYScreenPos
-FlyAnimationScreenCoords1: ; 7064f (1c:464f)
+FlyAnimationScreenCoords1:
; y, x pairs
; This is the sequence of screen coordinates used by the first part
; of the Fly overworld animation.
@@ -184,7 +184,7 @@ FlyAnimationScreenCoords1: ; 7064f (1c:464f)
db $2A, $98
db $27, $A0
-FlyAnimationScreenCoords2: ; 70667 (1c:4667)
+FlyAnimationScreenCoords2:
; y, x pairs
; This is the sequence of screen coordinates used by the second part
; of the Fly overworld animation.
@@ -201,7 +201,7 @@ FlyAnimationScreenCoords2: ; 70667 (1c:4667)
db $F0, $00
-LeaveMapThroughHoleAnim: ; 7067d (1c:467d)
+LeaveMapThroughHoleAnim:
ld a, $ff
ld [wUpdateSpritesEnabled], a ; disable UpdateSprites
; shift upper half of player's sprite down 8 pixels and hide lower half
@@ -214,7 +214,7 @@ LeaveMapThroughHoleAnim: ; 7067d (1c:467d)
ld [wOAMBuffer + 1 * 4], a
ld c, 2
call DelayFrames
- ; hide lower half of player's sprite
+ ; hide upper half of player's sprite
ld a, $a0
ld [wOAMBuffer + 2 * 4], a
ld [wOAMBuffer + 3 * 4], a
@@ -223,7 +223,7 @@ LeaveMapThroughHoleAnim: ; 7067d (1c:467d)
ld [wUpdateSpritesEnabled], a ; enable UpdateSprites
jp RestoreFacingDirectionAndYScreenPos
-DoFlyAnimation: ; 706ae (1c:46ae)
+DoFlyAnimation:
ld a, [wFlyAnimBirdSpriteImageIndex]
xor $1 ; make the bird flap its wings
ld [wFlyAnimBirdSpriteImageIndex], a
@@ -231,7 +231,7 @@ DoFlyAnimation: ; 706ae (1c:46ae)
call Delay3
ld a, [wFlyAnimUsingCoordList]
cp $ff
- jr z, .asm_706cd
+ jr z, .skipCopyingCoords ; if the bird is flapping its wings in place
ld hl, wSpriteStateData1 + 4
ld a, [de]
inc de
@@ -240,34 +240,35 @@ DoFlyAnimation: ; 706ae (1c:46ae)
ld a, [de]
inc de
ld [hl], a
-.asm_706cd
+.skipCopyingCoords
ld a, [wFlyAnimCounter]
dec a
ld [wFlyAnimCounter], a
jr nz, DoFlyAnimation
ret
-LoadBirdSpriteGraphics: ; 706d7 (1c:46d7)
- ld de, BirdSprite ; $4d80
+LoadBirdSpriteGraphics:
+ ld de, BirdSprite
ld hl, vNPCSprites
- ld bc, (BANK(BirdSprite) << 8) + $0c
+ lb bc, BANK(BirdSprite), $0c
call CopyVideoData
- ld de, BirdSprite + $c0 ; $4e40 ; moving amination sprite
+ ld de, BirdSprite + $c0 ; moving animation sprite
ld hl, vNPCSprites2
- ld bc, (BANK(BirdSprite) << 8) + $0c
+ lb bc, BANK(BirdSprite), $0c
jp CopyVideoData
-InitFacingDirectionBuffer: ; 706ef (1c:46ef)
+InitFacingDirectionList:
ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction (image index is locked to standing images)
- ld [wcd50], a
+ ld [wSavedPlayerFacingDirection], a
ld a, [wSpriteStateData1 + 4] ; player's sprite Y screen position
- ld [wcd4f], a
+ ld [wSavedPlayerScreenY], a
ld hl, PlayerSpinningFacingOrder
- ld de, wcd48
- ld bc, $4
+ ld de, wFacingDirectionList
+ ld bc, 4
call CopyData
ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction (image index is locked to standing images)
- ld hl, wcd48
+ ld hl, wFacingDirectionList
+; find the place in the list that matches the current facing direction
.loop
cp [hl]
inc hl
@@ -275,34 +276,36 @@ InitFacingDirectionBuffer: ; 706ef (1c:46ef)
dec hl
ret
-PlayerSpinningFacingOrder: ; 70713 (1c:4713)
+PlayerSpinningFacingOrder:
; The order of the direction the player's sprite is facing when teleporting
; away. Creates a spinning effect.
db SPRITE_FACING_DOWN, SPRITE_FACING_LEFT, SPRITE_FACING_UP, SPRITE_FACING_RIGHT
-SpinPlayerSprite: ; 70717 (1c:4717)
+SpinPlayerSprite:
+; copy the current value from the list into the sprite data and rotate the list
ld a, [hl]
ld [wSpriteStateData1 + 2], a ; player's sprite facing direction (image index is locked to standing images)
push hl
- ld hl, wcd48
- ld de, wcd47
- ld bc, $4
+ ld hl, wFacingDirectionList
+ ld de, wFacingDirectionList - 1
+ ld bc, 4
call CopyData
- ld a, [wcd47]
- ld [wcd4b], a
+ ld a, [wFacingDirectionList - 1]
+ ld [wFacingDirectionList + 3], a
pop hl
ret
-PlayerSpinInPlace: ; 70730 (1c:4730)
+PlayerSpinInPlace:
call SpinPlayerSprite
ld a, [wPlayerSpinInPlaceAnimFrameDelay]
ld c, a
and $3
- jr nz, .asm_70743
+ jr nz, .skipPlayingSound
+; when the last delay was a multiple of 4, play a sound if there is one
ld a, [wPlayerSpinInPlaceAnimSoundID]
cp $ff
call nz, PlaySound
-.asm_70743
+.skipPlayingSound
ld a, [wPlayerSpinInPlaceAnimFrameDelayDelta]
add c
ld [wPlayerSpinInPlaceAnimFrameDelay], a
@@ -313,7 +316,7 @@ PlayerSpinInPlace: ; 70730 (1c:4730)
call DelayFrames
jr PlayerSpinInPlace
-PlayerSpinWhileMovingUpOrDown: ; 70755 (1c:4755)
+PlayerSpinWhileMovingUpOrDown:
call SpinPlayerSprite
ld a, [wPlayerSpinWhileMovingUpOrDownAnimDeltaY]
ld c, a
@@ -329,25 +332,25 @@ PlayerSpinWhileMovingUpOrDown: ; 70755 (1c:4755)
call DelayFrames
jr PlayerSpinWhileMovingUpOrDown
-RestoreFacingDirectionAndYScreenPos: ; 70772 (1c:4772)
- ld a, [wcd4f]
+RestoreFacingDirectionAndYScreenPos:
+ ld a, [wSavedPlayerScreenY]
ld [wSpriteStateData1 + 4], a
- ld a, [wcd50]
+ ld a, [wSavedPlayerFacingDirection]
ld [wSpriteStateData1 + 2], a
ret
; if SGB, 2 frames, else 3 frames
-GetPlayerTeleportAnimFrameDelay: ; 7077f (1c:477f)
+GetPlayerTeleportAnimFrameDelay:
ld a, [wOnSGB]
xor $1
inc a
inc a
ret
-IsPlayerStandingOnWarpPadOrHole: ; 70787 (1c:4787)
+IsPlayerStandingOnWarpPadOrHole:
ld b, 0
ld hl, .warpPadAndHoleData
- ld a, [W_CURMAPTILESET]
+ ld a, [wCurMapTileset]
ld c, a
.loop
ld a, [hli]
@@ -367,99 +370,111 @@ IsPlayerStandingOnWarpPadOrHole: ; 70787 (1c:4787)
ld b, [hl]
.done
ld a, b
- ld [wcd5b], a
+ ld [wStandingOnWarpPadOrHole], a
ret
-; format: db tileset id, tile id, value to be put in wcd5b
-.warpPadAndHoleData: ; 707a9 (1c:47a9)
+; format: db tileset id, tile id, value to be put in [wStandingOnWarpPadOrHole]
+.warpPadAndHoleData:
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
+FishingAnim:
+ ld c, 10
call DelayFrames
ld hl, wd736
- set 6, [hl]
- ld de, RedSprite ; $4180
+ set 6, [hl] ; reserve the last 4 OAM entries
+ ld de, RedSprite
ld hl, vNPCSprites
- ld bc, (BANK(RedSprite) << 8) + $0c
+ lb bc, BANK(RedSprite), $c
call CopyVideoData
ld a, $4
- ld hl, RedFishingTiles ; $4866
+ ld hl, RedFishingTiles
call LoadAnimSpriteGfx
ld a, [wSpriteStateData1 + 2]
ld c, a
ld b, $0
- ld hl, FishingRodGfxProperties ; $4856
+ ld hl, FishingRodOAM
add hl, bc
ld de, wOAMBuffer + $9c
ld bc, $4
call CopyData
- ld c, $64
+ ld c, 100
call DelayFrames
- ld a, [wWhichTrade] ; wWhichTrade
+ ld a, [wRodResponse]
and a
ld hl, NoNibbleText
- jr z, .asm_70836
+ jr z, .done
cp $2
ld hl, NothingHereText
- jr z, .asm_70836
- ld b, $a
-.asm_707fe
- ld hl, wSpriteStateData1 + 4
- call Func_70842
+ jr z, .done
+
+; there was a bite
+
+; shake the player's sprite vertically
+ ld b, 10
+.loop
+ ld hl, wSpriteStateData1 + 4 ; player's sprite Y screen position
+ call .ShakePlayerSprite
ld hl, wOAMBuffer + $9c
- call Func_70842
+ call .ShakePlayerSprite
call Delay3
dec b
- jr nz, .asm_707fe
- ld a, [wSpriteStateData1 + 2]
- cp $4
- jr nz, .asm_7081c
+ jr nz, .loop
+
+; If the player is facing up, hide the fishing rod so it doesn't overlap with
+; the exclamation bubble that will be shown next.
+ ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction
+ cp SPRITE_FACING_UP
+ jr nz, .skipHidingFishingRod
ld a, $a0
ld [wOAMBuffer + $9c], a
-.asm_7081c
- ld hl, wcd4f
+
+.skipHidingFishingRod
+ ld hl, wEmotionBubbleSpriteIndex
xor a
- ld [hli], a
- ld [hl], a
+ ld [hli], a ; player's sprite
+ ld [hl], a ; EXCLAMATION_BUBBLE
predef EmotionBubble
- ld a, [wSpriteStateData1 + 2]
- cp $4
- jr nz, .asm_70833
+
+; If the player is facing up, unhide the fishing rod.
+ ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction
+ cp SPRITE_FACING_UP
+ jr nz, .skipUnhidingFishingRod
ld a, $44
ld [wOAMBuffer + $9c], a
-.asm_70833
+
+.skipUnhidingFishingRod
ld hl, ItsABiteText
-.asm_70836
+
+.done
call PrintText
ld hl, wd736
- res 6, [hl]
+ res 6, [hl] ; unreserve the last 4 OAM entries
call LoadFontTilePatterns
ret
-Func_70842: ; 70842 (1c:4842)
+.ShakePlayerSprite
ld a, [hl]
xor $1
ld [hl], a
ret
-NoNibbleText: ; 70847 (1c:4847)
+NoNibbleText:
TX_FAR _NoNibbleText
db "@"
-NothingHereText: ; 7084c (1c:484c)
+NothingHereText:
TX_FAR _NothingHereText
db "@"
-ItsABiteText: ; 70851 (1c:4851)
+ItsABiteText:
TX_FAR _ItsABiteText
db "@"
-FishingRodGfxProperties: ; 70856 (1c:4856)
+FishingRodOAM:
; specifies how the fishing rod should be drawn on the screen
; first byte = screen y coordinate
; second byte = screen x coordinate
@@ -470,7 +485,7 @@ FishingRodGfxProperties: ; 70856 (1c:4856)
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)
+RedFishingTiles:
dw RedFishingTilesFront
db 2, BANK(RedFishingTilesFront)
dw vNPCSprites + $20
@@ -487,7 +502,7 @@ RedFishingTiles: ; 70866 (1c:4866)
db 3, BANK(RedFishingRodTiles)
dw vNPCSprites2 + $7d0
-_HandleMidJump: ; 7087e (1c:487e)
+_HandleMidJump:
ld a, [wPlayerJumpingYScreenCoordsIndex]
ld c, a
inc a
@@ -519,6 +534,6 @@ _HandleMidJump: ; 7087e (1c:487e)
ld [wJoyIgnore], a
ret
-PlayerJumpingYScreenCoords: ; 708ba (1c:48ba)
+PlayerJumpingYScreenCoords:
; 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/player_state.asm b/engine/overworld/player_state.asm
new file mode 100644
index 00000000..79f755b9
--- /dev/null
+++ b/engine/overworld/player_state.asm
@@ -0,0 +1,463 @@
+; only used for setting bit 2 of wd736 upon entering a new map
+IsPlayerStandingOnWarp:
+ ld a, [wNumberOfWarps]
+ and a
+ ret z
+ ld c, a
+ ld hl, wWarpEntries
+.loop
+ ld a, [wYCoord]
+ cp [hl]
+ jr nz, .nextWarp1
+ inc hl
+ ld a, [wXCoord]
+ cp [hl]
+ jr nz, .nextWarp2
+ inc hl
+ ld a, [hli] ; target warp
+ ld [wDestinationWarpID], a
+ ld a, [hl] ; target map
+ ld [hWarpDestinationMap], a
+ ld hl, wd736
+ set 2, [hl] ; standing on warp flag
+ ret
+.nextWarp1
+ inc hl
+.nextWarp2
+ inc hl
+ inc hl
+ inc hl
+ dec c
+ jr nz, .loop
+ ret
+
+CheckForceBikeOrSurf:
+ ld hl, wd732
+ bit 5, [hl]
+ ret nz
+ ld hl, ForcedBikeOrSurfMaps
+ ld a, [wYCoord]
+ ld b, a
+ ld a, [wXCoord]
+ ld c, a
+ ld a, [wCurMap]
+ ld d, a
+.loop
+ ld a, [hli]
+ cp $ff
+ ret z ;if we reach FF then it's not part of the list
+ cp d ;compare to current map
+ jr nz, .incorrectMap
+ ld a, [hli]
+ cp b ;compare y-coord
+ jr nz, .incorrectY
+ ld a, [hli]
+ cp c ;compare x-coord
+ jr nz, .loop ; incorrect x-coord, check next item
+ ld a, [wCurMap]
+ cp SEAFOAM_ISLANDS_4
+ ld a, $2
+ ld [wSeafoamIslands4CurScript], a
+ jr z, .forceSurfing
+ ld a, [wCurMap]
+ cp SEAFOAM_ISLANDS_5
+ ld a, $2
+ ld [wSeafoamIslands5CurScript], a
+ jr z, .forceSurfing
+ ;force bike riding
+ ld hl, wd732
+ set 5, [hl]
+ ld a, $1
+ ld [wWalkBikeSurfState], a
+ ld [wWalkBikeSurfStateCopy], a
+ jp ForceBikeOrSurf
+.incorrectMap
+ inc hl
+.incorrectY
+ inc hl
+ jr .loop
+.forceSurfing
+ ld a, $2
+ ld [wWalkBikeSurfState], a
+ ld [wWalkBikeSurfStateCopy], a
+ jp ForceBikeOrSurf
+
+INCLUDE "data/force_bike_surf.asm"
+
+IsPlayerFacingEdgeOfMap:
+ push hl
+ push de
+ push bc
+ ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction
+ srl a
+ ld c, a
+ ld b, $0
+ ld hl, .functionPointerTable
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wYCoord]
+ ld b, a
+ ld a, [wXCoord]
+ ld c, a
+ ld de, .asm_c41e
+ push de
+ jp [hl]
+.asm_c41e
+ pop bc
+ pop de
+ pop hl
+ ret
+
+.functionPointerTable
+ dw .facingDown
+ dw .facingUp
+ dw .facingLeft
+ dw .facingRight
+
+.facingDown
+ ld a, [wCurMapHeight]
+ add a
+ dec a
+ cp b
+ jr z, .setCarry
+ jr .resetCarry
+
+.facingUp
+ ld a, b
+ and a
+ jr z, .setCarry
+ jr .resetCarry
+
+.facingLeft
+ ld a, c
+ and a
+ jr z, .setCarry
+ jr .resetCarry
+
+.facingRight
+ ld a, [wCurMapWidth]
+ add a
+ dec a
+ cp c
+ jr z, .setCarry
+ jr .resetCarry
+.resetCarry
+ and a
+ ret
+.setCarry
+ scf
+ ret
+
+IsWarpTileInFrontOfPlayer:
+ push hl
+ push de
+ push bc
+ call _GetTileAndCoordsInFrontOfPlayer
+ ld a, [wCurMap]
+ cp SS_ANNE_5
+ jr z, .ssAnne5
+ ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction
+ srl a
+ ld c, a
+ ld b, 0
+ ld hl, .warpTileListPointers
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wTileInFrontOfPlayer]
+ ld de, $1
+ call IsInArray
+.done
+ pop bc
+ pop de
+ pop hl
+ ret
+
+.warpTileListPointers:
+ dw .facingDownWarpTiles
+ dw .facingUpWarpTiles
+ dw .facingLeftWarpTiles
+ dw .facingRightWarpTiles
+
+.facingDownWarpTiles
+ db $01,$12,$17,$3D,$04,$18,$33,$FF
+
+.facingUpWarpTiles
+ db $01,$5C,$FF
+
+.facingLeftWarpTiles
+ db $1A,$4B,$FF
+
+.facingRightWarpTiles
+ db $0F,$4E,$FF
+
+.ssAnne5
+ ld a, [wTileInFrontOfPlayer]
+ cp $15
+ jr nz, .notSSAnne5Warp
+ scf
+ jr .done
+.notSSAnne5Warp
+ and a
+ jr .done
+
+IsPlayerStandingOnDoorTileOrWarpTile:
+ push hl
+ push de
+ push bc
+ callba IsPlayerStandingOnDoorTile
+ jr c, .done
+ ld a, [wCurMapTileset]
+ add a
+ ld c, a
+ ld b, $0
+ ld hl, WarpTileIDPointers
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, $1
+ aCoord 8, 9
+ call IsInArray
+ jr nc, .done
+ ld hl, wd736
+ res 2, [hl]
+.done
+ pop bc
+ pop de
+ pop hl
+ ret
+
+INCLUDE "data/warp_tile_ids.asm"
+
+PrintSafariZoneSteps:
+ ld a, [wCurMap]
+ cp SAFARI_ZONE_EAST
+ ret c
+ cp UNKNOWN_DUNGEON_2
+ ret nc
+ coord hl, 0, 0
+ ld b, 3
+ ld c, 7
+ call TextBoxBorder
+ coord hl, 1, 1
+ ld de, wSafariSteps
+ lb bc, 2, 3
+ call PrintNumber
+ coord hl, 4, 1
+ ld de, SafariSteps
+ call PlaceString
+ coord hl, 1, 3
+ ld de, SafariBallText
+ call PlaceString
+ ld a, [wNumSafariBalls]
+ cp 10
+ jr nc, .asm_c56d
+ coord hl, 5, 3
+ ld a, " "
+ ld [hl], a
+.asm_c56d
+ coord hl, 6, 3
+ ld de, wNumSafariBalls
+ lb bc, 1, 2
+ jp PrintNumber
+
+SafariSteps:
+ db "/500@"
+
+SafariBallText:
+ db "BALL×× @"
+
+GetTileAndCoordsInFrontOfPlayer:
+ call GetPredefRegisters
+
+_GetTileAndCoordsInFrontOfPlayer:
+ ld a, [wYCoord]
+ ld d, a
+ ld a, [wXCoord]
+ ld e, a
+ ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
+ and a ; cp SPRITE_FACING_DOWN
+ jr nz, .notFacingDown
+; facing down
+ aCoord 8, 11
+ inc d
+ jr .storeTile
+.notFacingDown
+ cp SPRITE_FACING_UP
+ jr nz, .notFacingUp
+; facing up
+ aCoord 8, 7
+ dec d
+ jr .storeTile
+.notFacingUp
+ cp SPRITE_FACING_LEFT
+ jr nz, .notFacingLeft
+; facing left
+ aCoord 6, 9
+ dec e
+ jr .storeTile
+.notFacingLeft
+ cp SPRITE_FACING_RIGHT
+ jr nz, .storeTile
+; facing right
+ aCoord 10, 9
+ inc e
+.storeTile
+ ld c, a
+ ld [wTileInFrontOfPlayer], a
+ ret
+
+GetTileTwoStepsInFrontOfPlayer:
+ xor a
+ ld [$ffdb], a
+ ld hl, wYCoord
+ ld a, [hli]
+ ld d, a
+ ld e, [hl]
+ ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
+ and a ; cp SPRITE_FACING_DOWN
+ jr nz, .notFacingDown
+; facing down
+ ld hl, $ffdb
+ set 0, [hl]
+ aCoord 8, 13
+ inc d
+ jr .storeTile
+.notFacingDown
+ cp SPRITE_FACING_UP
+ jr nz, .notFacingUp
+; facing up
+ ld hl, $ffdb
+ set 1, [hl]
+ aCoord 8, 5
+ dec d
+ jr .storeTile
+.notFacingUp
+ cp SPRITE_FACING_LEFT
+ jr nz, .notFacingLeft
+; facing left
+ ld hl, $ffdb
+ set 2, [hl]
+ aCoord 4, 9
+ dec e
+ jr .storeTile
+.notFacingLeft
+ cp SPRITE_FACING_RIGHT
+ jr nz, .storeTile
+; facing right
+ ld hl, $ffdb
+ set 3, [hl]
+ aCoord 12, 9
+ inc e
+.storeTile
+ ld c, a
+ ld [wTileInFrontOfBoulderAndBoulderCollisionResult], a
+ ld [wTileInFrontOfPlayer], a
+ ret
+
+CheckForCollisionWhenPushingBoulder:
+ call GetTileTwoStepsInFrontOfPlayer
+ ld hl, wTilesetCollisionPtr
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+.loop
+ ld a, [hli]
+ cp $ff
+ jr z, .done ; if the tile two steps ahead is not passable
+ cp c
+ jr nz, .loop
+ ld hl, TilePairCollisionsLand
+ call CheckForTilePairCollisions2
+ ld a, $ff
+ jr c, .done ; if there is an elevation difference between the current tile and the one two steps ahead
+ ld a, [wTileInFrontOfBoulderAndBoulderCollisionResult]
+ cp $15 ; stairs tile
+ ld a, $ff
+ jr z, .done ; if the tile two steps ahead is stairs
+ call CheckForBoulderCollisionWithSprites
+.done
+ ld [wTileInFrontOfBoulderAndBoulderCollisionResult], a
+ ret
+
+; sets a to $ff if there is a collision and $00 if there is no collision
+CheckForBoulderCollisionWithSprites:
+ ld a, [wBoulderSpriteIndex]
+ dec a
+ swap a
+ ld d, 0
+ ld e, a
+ ld hl, wSpriteStateData2 + $14
+ add hl, de
+ ld a, [hli] ; map Y position
+ ld [$ffdc], a
+ ld a, [hl] ; map X position
+ ld [$ffdd], a
+ ld a, [wNumSprites]
+ ld c, a
+ ld de, $f
+ ld hl, wSpriteStateData2 + $14
+ ld a, [$ffdb]
+ and $3 ; facing up or down?
+ jr z, .pushingHorizontallyLoop
+.pushingVerticallyLoop
+ inc hl
+ ld a, [$ffdd]
+ cp [hl]
+ jr nz, .nextSprite1 ; if X coordinates don't match
+ dec hl
+ ld a, [hli]
+ ld b, a
+ ld a, [$ffdb]
+ rrca
+ jr c, .pushingDown
+; pushing up
+ ld a, [$ffdc]
+ dec a
+ jr .compareYCoords
+.pushingDown
+ ld a, [$ffdc]
+ inc a
+.compareYCoords
+ cp b
+ jr z, .failure
+.nextSprite1
+ dec c
+ jr z, .success
+ add hl, de
+ jr .pushingVerticallyLoop
+.pushingHorizontallyLoop
+ ld a, [hli]
+ ld b, a
+ ld a, [$ffdc]
+ cp b
+ jr nz, .nextSprite2
+ ld b, [hl]
+ ld a, [$ffdb]
+ bit 2, a
+ jr nz, .pushingLeft
+; pushing right
+ ld a, [$ffdd]
+ inc a
+ jr .compareXCoords
+.pushingLeft
+ ld a, [$ffdd]
+ dec a
+.compareXCoords
+ cp b
+ jr z, .failure
+.nextSprite2
+ dec c
+ jr z, .success
+ add hl, de
+ jr .pushingHorizontallyLoop
+.failure
+ ld a, $ff
+ ret
+.success
+ xor a
+ ret
diff --git a/engine/overworld/poison.asm b/engine/overworld/poison.asm
new file mode 100644
index 00000000..5d8eb9fd
--- /dev/null
+++ b/engine/overworld/poison.asm
@@ -0,0 +1,112 @@
+ApplyOutOfBattlePoisonDamage:
+ ld a, [wd730]
+ add a
+ jp c, .noBlackOut ; no black out if joypad states are being simulated
+ ld a, [wPartyCount]
+ and a
+ jp z, .noBlackOut
+ call IncrementDayCareMonExp
+ ld a, [wStepCounter]
+ and $3 ; is the counter a multiple of 4?
+ jp nz, .noBlackOut ; only apply poison damage every fourth step
+ ld [wWhichPokemon], a
+ ld hl, wPartyMon1Status
+ ld de, wPartySpecies
+.applyDamageLoop
+ ld a, [hl]
+ and (1 << PSN)
+ jr z, .nextMon2 ; not poisoned
+ dec hl
+ dec hl
+ ld a, [hld]
+ ld b, a
+ ld a, [hli]
+ or b
+ jr z, .nextMon ; already fainted
+; subtract 1 from HP
+ ld a, [hl]
+ dec a
+ ld [hld], a
+ inc a
+ jr nz, .noBorrow
+; borrow 1 from upper byte of HP
+ dec [hl]
+ inc hl
+ jr .nextMon
+.noBorrow
+ ld a, [hli]
+ or [hl]
+ jr nz, .nextMon ; didn't faint from damage
+; the mon fainted from the damage
+ push hl
+ inc hl
+ inc hl
+ ld [hl], a
+ ld a, [de]
+ ld [wd11e], a
+ push de
+ ld a, [wWhichPokemon]
+ ld hl, wPartyMonNicks
+ call GetPartyMonName
+ xor a
+ ld [wJoyIgnore], a
+ call EnableAutoTextBoxDrawing
+ ld a, TEXT_MON_FAINTED
+ ld [hSpriteIndexOrTextID], a
+ call DisplayTextID
+ pop de
+ pop hl
+.nextMon
+ inc hl
+ inc hl
+.nextMon2
+ inc de
+ ld a, [de]
+ inc a
+ jr z, .applyDamageLoopDone
+ ld bc, wPartyMon2 - wPartyMon1
+ add hl, bc
+ push hl
+ ld hl, wWhichPokemon
+ inc [hl]
+ pop hl
+ jr .applyDamageLoop
+.applyDamageLoopDone
+ ld hl, wPartyMon1Status
+ ld a, [wPartyCount]
+ ld d, a
+ ld e, 0
+.countPoisonedLoop
+ ld a, [hl]
+ and (1 << PSN)
+ or e
+ ld e, a
+ ld bc, wPartyMon2 - wPartyMon1
+ add hl, bc
+ dec d
+ jr nz, .countPoisonedLoop
+ ld a, e
+ and a ; are any party members poisoned?
+ jr z, .skipPoisonEffectAndSound
+ ld b, $2
+ predef ChangeBGPalColor0_4Frames ; change BG white to dark grey for 4 frames
+ ld a, SFX_POISONED
+ call PlaySound
+.skipPoisonEffectAndSound
+ predef AnyPartyAlive
+ ld a, d
+ and a
+ jr nz, .noBlackOut
+ call EnableAutoTextBoxDrawing
+ ld a, TEXT_BLACKED_OUT
+ ld [hSpriteIndexOrTextID], a
+ call DisplayTextID
+ ld hl, wd72e
+ set 5, [hl]
+ ld a, $ff
+ jr .done
+.noBlackOut
+ xor a
+.done
+ ld [wOutOfBattleBlackout], a
+ ret
diff --git a/engine/overworld/pokecenter.asm b/engine/overworld/pokecenter.asm
index 3c640d8e..f26bedf8 100755
--- a/engine/overworld/pokecenter.asm
+++ b/engine/overworld/pokecenter.asm
@@ -1,4 +1,4 @@
-DisplayPokemonCenterDialogue_: ; 6fe6 (1:6fe6)
+DisplayPokemonCenterDialogue_:
call SaveScreenTilesToBuffer1 ; save screen
ld hl, PokemonCenterWelcomeText
call PrintText
@@ -24,12 +24,12 @@ DisplayPokemonCenterDialogue_: ; 6fe6 (1:6fe6)
predef HealParty
callba AnimateHealingMachine ; do the healing machine animation
xor a
- ld [wMusicHeaderPointer], a
- ld a, [wc0f0]
- ld [wc0ef], a
- ld a, [wd35b]
- ld [wcfca], a
- ld [wc0ee], a
+ ld [wAudioFadeOutControl], a
+ ld a, [wAudioSavedROMBank]
+ ld [wAudioROMBank], a
+ ld a, [wMapMusicSoundID]
+ ld [wLastMusicSoundID], a
+ ld [wNewSoundID], a
call PlaySound
ld hl, PokemonFightingFitText
call PrintText
@@ -43,26 +43,26 @@ DisplayPokemonCenterDialogue_: ; 6fe6 (1:6fe6)
.done
ld hl, PokemonCenterFarewellText
call PrintText
- jp UpdateSprites ; move sprites
+ jp UpdateSprites
-PokemonCenterWelcomeText: ; 705d (1:705d)
+PokemonCenterWelcomeText:
TX_FAR _PokemonCenterWelcomeText
db "@"
-ShallWeHealYourPokemonText: ; 7062 (1:7062)
- db $a
+ShallWeHealYourPokemonText:
+ TX_DELAY
TX_FAR _ShallWeHealYourPokemonText
db "@"
-NeedYourPokemonText: ; 7068 (1:7068)
+NeedYourPokemonText:
TX_FAR _NeedYourPokemonText
db "@"
-PokemonFightingFitText: ; 706d (1:706d)
+PokemonFightingFitText:
TX_FAR _PokemonFightingFitText
db "@"
-PokemonCenterFarewellText: ; 7072 (1:7072)
- db $a
+PokemonCenterFarewellText:
+ TX_DELAY
TX_FAR _PokemonCenterFarewellText
db "@"
diff --git a/engine/overworld/pokemart.asm b/engine/overworld/pokemart.asm
index 8325b93f..823939b1 100755
--- a/engine/overworld/pokemart.asm
+++ b/engine/overworld/pokemart.asm
@@ -1,30 +1,34 @@
-DisplayPokemartDialogue_: ; 6c20 (1:6c20)
+DisplayPokemartDialogue_:
ld a,[wListScrollOffset]
- ld [wd07e],a
- call UpdateSprites ; move sprites
+ ld [wSavedListScrollOffset],a
+ call UpdateSprites
xor a
- ld [wcf0a],a ; flag that is set if something is sold or bought
+ ld [wBoughtOrSoldItemInMart],a
.loop
xor a
ld [wListScrollOffset],a
ld [wCurrentMenuItem],a
ld [wPlayerMonNumber],a
inc a
- ld [wcf93],a
+ ld [wPrintItemPrices],a
ld a,MONEY_BOX
ld [wTextBoxID],a
- call DisplayTextBoxID ; draw money text box
+ call DisplayTextBoxID
ld a,BUY_SELL_QUIT_MENU
ld [wTextBoxID],a
- call DisplayTextBoxID ; do buy/sell/quit menu
- ld hl,wd128 ; pointer to this pokemart's inventory
+ call DisplayTextBoxID
+
+; This code is useless. It copies the address of the pokemart's inventory to hl,
+; but the address is never used.
+ ld hl,wItemListPointer
ld a,[hli]
ld l,[hl]
- ld h,a ; hl = address of inventory
- ld a,[wd12e]
- cp a,$02
+ ld h,a
+
+ ld a,[wMenuExitMethod]
+ cp a,CANCELLED_MENU
jp z,.done
- ld a,[wd12d] ; ID of the chosen menu item
+ ld a,[wChosenMenuItem]
and a ; buying?
jp z,.buyMenu
dec a ; selling?
@@ -32,11 +36,14 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20)
dec a ; quitting?
jp z,.done
.sellMenu
+
+; the same variables are set again below, so this code has no effect
xor a
- ld [wcf93],a
- ld a,$02
- ld [wd11b],a
- callab Func_39bd5
+ ld [wPrintItemPrices],a
+ ld a,INIT_BAG_ITEM_LIST
+ ld [wInitListType],a
+ callab InitList
+
ld a,[wNumBagItems]
and a
jp z,.bagEmpty
@@ -50,19 +57,19 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20)
call DisplayTextBoxID ; draw money text box
ld hl,wNumBagItems
ld a,l
- ld [wList],a
+ ld [wListPointer],a
ld a,h
- ld [wList + 1],a
+ ld [wListPointer + 1],a
xor a
- ld [wcf93],a
+ ld [wPrintItemPrices],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,[wd124]
+ call IsKeyItem
+ ld a,[wIsKeyItem]
and a
jr nz,.unsellableItem
ld a,[wcf91]
@@ -70,30 +77,34 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20)
jr c,.unsellableItem
ld a,PRICEDITEMLISTMENU
ld [wListMenuID],a
- ld [$ff8e],a ; halve prices when selling
+ ld [hHalveItemPrices],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
+ lb bc, 14, 1 ; location that PrintText always prints to, this is useless
call PrintText
- hlCoord 14, 7
- ld bc,$080f
+ coord hl, 14, 7
+ lb bc, 8, 15
ld a,TWO_OPTION_MENU
ld [wTextBoxID],a
call DisplayTextBoxID ; yes/no menu
- ld a,[wd12e]
- cp a,$02
- jr z,.sellMenuLoop ; if the player pressed the B button
- ld a,[wd12d] ; ID of the chosen menu item
+ ld a,[wMenuExitMethod]
+ cp a,CHOSE_SECOND_ITEM
+ jr z,.sellMenuLoop ; if the player chose No or pressed the B button
+
+; The following code is supposed to check if the player chose No, but the above
+; check already catches it.
+ ld a,[wChosenMenuItem]
dec a
- jr z,.sellMenuLoop ; if the player chose No
+ jr z,.sellMenuLoop
+
.sellItem
- ld a,[wcf0a] ; flag that is set if something is sold or bought
+ ld a,[wBoughtOrSoldItemInMart]
and a
jr nz,.skipSettingFlag1
inc a
- ld [wcf0a],a
+ ld [wBoughtOrSoldItemInMart],a
.skipSettingFlag1
call AddAmountSoldToMoney
ld hl,wNumBagItems
@@ -106,39 +117,42 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20)
.bagEmpty
ld hl,PokemartItemBagEmptyText
call PrintText
- call SaveScreenTilesToBuffer1 ; save screen
+ call SaveScreenTilesToBuffer1
jp .returnToMainPokemartMenu
.buyMenu
- ld a,$01
- ld [wcf93],a
- ld a,$03
- ld [wd11b],a
- callab Func_39bd5
+
+; the same variables are set again below, so this code has no effect
+ ld a,1
+ ld [wPrintItemPrices],a
+ ld a,INIT_OTHER_ITEM_LIST
+ ld [wInitListType],a
+ callab InitList
+
ld hl,PokemartBuyingGreetingText
call PrintText
- call SaveScreenTilesToBuffer1 ; save screen
+ call SaveScreenTilesToBuffer1
.buyMenuLoop
- call LoadScreenTilesFromBuffer1 ; restore saved screen
+ call LoadScreenTilesFromBuffer1
ld a,MONEY_BOX
ld [wTextBoxID],a
- call DisplayTextBoxID ; draw money text box
- ld hl,wStringBuffer2 + 11
+ call DisplayTextBoxID
+ ld hl,wItemList
ld a,l
- ld [wList],a
+ ld [wListPointer],a
ld a,h
- ld [wList + 1],a
+ ld [wListPointer + 1],a
xor a
ld [wCurrentMenuItem],a
inc a
- ld [wcf93],a
+ ld [wPrintItemPrices],a
inc a ; a = 2 (PRICEDITEMLISTMENU)
ld [wListMenuID],a
call DisplayListMenuID
jr c,.returnToMainPokemartMenu ; if the player closed the menu
- ld a,$63
- ld [wcf97],a
+ ld a,99
+ ld [wMaxItemQuantity],a
xor a
- ld [$ff8e],a
+ ld [hHalveItemPrices],a ; don't halve item prices when buying
call DisplayChooseQuantityMenu
inc a
jr z,.buyMenuLoop ; if the player closed the choose quantity menu with the B button
@@ -148,17 +162,21 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20)
call CopyStringToCF4B ; copy name to wcf4b
ld hl,PokemartTellBuyPriceText
call PrintText
- hlCoord 14, 7
- ld bc,$080f
+ coord hl, 14, 7
+ lb bc, 8, 15
ld a,TWO_OPTION_MENU
ld [wTextBoxID],a
call DisplayTextBoxID ; yes/no menu
- ld a,[wd12e]
- cp a,$02
- jp z,.buyMenuLoop ; if the player pressed the B button
- ld a,[wd12d] ; ID of the chosen menu item
+ ld a,[wMenuExitMethod]
+ cp a,CHOSE_SECOND_ITEM
+ jp z,.buyMenuLoop ; if the player chose No or pressed the B button
+
+; The following code is supposed to check if the player chose No, but the above
+; check already catches it.
+ ld a,[wChosenMenuItem]
dec a
- jr z,.buyMenuLoop ; if the player chose No
+ jr z,.buyMenuLoop
+
.buyItem
call .isThereEnoughMoney
jr c,.notEnoughMoney
@@ -166,13 +184,13 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20)
call AddItemToInventory
jr nc,.bagFull
call SubtractAmountPaidFromMoney
- ld a,[wcf0a] ; flag that is set if something is sold or bought
+ ld a,[wBoughtOrSoldItemInMart]
and a
jr nz,.skipSettingFlag2
- ld a,$01
- ld [wcf0a],a
+ ld a,1
+ ld [wBoughtOrSoldItemInMart],a
.skipSettingFlag2
- ld a,(SFX_02_5a - SFX_Headers_02) / 3
+ ld a,SFX_PURCHASE
call PlaySoundWaitForCurrent
call WaitForSoundToFinish
ld hl,PokemartBoughtItemText
@@ -182,13 +200,13 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20)
call LoadScreenTilesFromBuffer1
ld a,MONEY_BOX
ld [wTextBoxID],a
- call DisplayTextBoxID ; draw money text box
+ call DisplayTextBoxID
ld hl,PokemartAnythingElseText
call PrintText
jp .loop
.isThereEnoughMoney
ld de,wPlayerMoney
- ld hl,$ff9f ; item price
+ ld hl,hMoney
ld c,3 ; length of money in bytes
jp StringCmp
.notEnoughMoney
@@ -202,53 +220,53 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20)
.done
ld hl,PokemartThankYouText
call PrintText
- ld a,$01
+ ld a,1
ld [wUpdateSpritesEnabled],a
- call UpdateSprites ; move sprites
- ld a,[wd07e]
+ call UpdateSprites
+ ld a,[wSavedListScrollOffset]
ld [wListScrollOffset],a
ret
-PokemartBuyingGreetingText: ; 6e0c (1:6e0c)
+PokemartBuyingGreetingText:
TX_FAR _PokemartBuyingGreetingText
db "@"
-PokemartTellBuyPriceText: ; 6e11 (1:6e11)
+PokemartTellBuyPriceText:
TX_FAR _PokemartTellBuyPriceText
db "@"
-PokemartBoughtItemText: ; 6e16 (1:6e16)
+PokemartBoughtItemText:
TX_FAR _PokemartBoughtItemText
db "@"
-PokemartNotEnoughMoneyText: ; 6e1b (1:6e1b)
+PokemartNotEnoughMoneyText:
TX_FAR _PokemartNotEnoughMoneyText
db "@"
-PokemartItemBagFullText: ; 6e20 (1:6e20)
+PokemartItemBagFullText:
TX_FAR _PokemartItemBagFullText
db "@"
-PokemonSellingGreetingText: ; 6e25 (1:6e25)
+PokemonSellingGreetingText:
TX_FAR _PokemonSellingGreetingText
db "@"
-PokemartTellSellPriceText: ; 6e2a (1:6e2a)
+PokemartTellSellPriceText:
TX_FAR _PokemartTellSellPriceText
db "@"
-PokemartItemBagEmptyText: ; 6e2f (1:6e2f)
+PokemartItemBagEmptyText:
TX_FAR _PokemartItemBagEmptyText
db "@"
-PokemartUnsellableItemText: ; 6e34 (1:6e34)
+PokemartUnsellableItemText:
TX_FAR _PokemartUnsellableItemText
db "@"
-PokemartThankYouText: ; 6e39 (1:6e39)
+PokemartThankYouText:
TX_FAR _PokemartThankYouText
db "@"
-PokemartAnythingElseText: ; 6e3e (1:6e3e)
+PokemartAnythingElseText:
TX_FAR _PokemartAnythingElseText
db "@"
diff --git a/engine/overworld/push_boulder.asm b/engine/overworld/push_boulder.asm
new file mode 100644
index 00000000..c91605a8
--- /dev/null
+++ b/engine/overworld/push_boulder.asm
@@ -0,0 +1,105 @@
+TryPushingBoulder:
+ ld a, [wd728]
+ bit 0, a ; using Strength?
+ ret z
+ ld a, [wFlags_0xcd60]
+ bit 1, a ; has boulder dust animation from previous push played yet?
+ ret nz
+ xor a
+ ld [hSpriteIndexOrTextID], a
+ call IsSpriteInFrontOfPlayer
+ ld a, [hSpriteIndexOrTextID]
+ ld [wBoulderSpriteIndex], a
+ and a
+ jp z, ResetBoulderPushFlags
+ ld hl, wSpriteStateData1 + 1
+ ld d, $0
+ ld a, [hSpriteIndexOrTextID]
+ swap a
+ ld e, a
+ add hl, de
+ res 7, [hl]
+ call GetSpriteMovementByte2Pointer
+ ld a, [hl]
+ cp BOULDER_MOVEMENT_BYTE_2
+ jp nz, ResetBoulderPushFlags
+ ld hl, wFlags_0xcd60
+ bit 6, [hl]
+ set 6, [hl] ; indicate that the player has tried pushing
+ ret z ; the player must try pushing twice before the boulder will move
+ ld a, [hJoyHeld]
+ and D_RIGHT | D_LEFT | D_UP | D_DOWN
+ ret z
+ predef CheckForCollisionWhenPushingBoulder
+ ld a, [wTileInFrontOfBoulderAndBoulderCollisionResult]
+ and a ; was there a collision?
+ jp nz, ResetBoulderPushFlags
+ ld a, [hJoyHeld]
+ ld b, a
+ ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
+ cp SPRITE_FACING_UP
+ jr z, .pushBoulderUp
+ cp SPRITE_FACING_LEFT
+ jr z, .pushBoulderLeft
+ cp SPRITE_FACING_RIGHT
+ jr z, .pushBoulderRight
+.pushBoulderDown
+ bit 7, b
+ ret z
+ ld de, PushBoulderDownMovementData
+ jr .done
+.pushBoulderUp
+ bit 6, b
+ ret z
+ ld de, PushBoulderUpMovementData
+ jr .done
+.pushBoulderLeft
+ bit 5, b
+ ret z
+ ld de, PushBoulderLeftMovementData
+ jr .done
+.pushBoulderRight
+ bit 4, b
+ ret z
+ ld de, PushBoulderRightMovementData
+.done
+ call MoveSprite
+ ld a, SFX_PUSH_BOULDER
+ call PlaySound
+ ld hl, wFlags_0xcd60
+ set 1, [hl]
+ ret
+
+PushBoulderUpMovementData:
+ db NPC_MOVEMENT_UP,$FF
+
+PushBoulderDownMovementData:
+ db NPC_MOVEMENT_DOWN,$FF
+
+PushBoulderLeftMovementData:
+ db NPC_MOVEMENT_LEFT,$FF
+
+PushBoulderRightMovementData:
+ db NPC_MOVEMENT_RIGHT,$FF
+
+DoBoulderDustAnimation:
+ ld a, [wd730]
+ bit 0, a
+ ret nz
+ callab AnimateBoulderDust
+ call DiscardButtonPresses
+ ld [wJoyIgnore], a
+ call ResetBoulderPushFlags
+ set 7, [hl]
+ ld a, [wBoulderSpriteIndex]
+ ld [H_SPRITEINDEX], a
+ call GetSpriteMovementByte2Pointer
+ ld [hl], $10
+ ld a, SFX_CUT
+ jp PlaySound
+
+ResetBoulderPushFlags:
+ ld hl, wFlags_0xcd60
+ res 1, [hl]
+ res 6, [hl]
+ ret
diff --git a/engine/overworld/saffron_guards.asm b/engine/overworld/saffron_guards.asm
index 8e584a2d..3b26b6f8 100755
--- a/engine/overworld/saffron_guards.asm
+++ b/engine/overworld/saffron_guards.asm
@@ -1,4 +1,4 @@
-RemoveGuardDrink: ; 5a59f (16:659f)
+RemoveGuardDrink:
ld hl, GuardDrinksList
.drinkLoop
ld a, [hli]
@@ -10,9 +10,7 @@ RemoveGuardDrink: ; 5a59f (16:659f)
call IsItemInBag
pop hl
jr z, .drinkLoop
- ld b, BANK(RemoveItemByID)
- ld hl, RemoveItemByID
- jp Bankswitch
+ jpba RemoveItemByID
-GuardDrinksList: ; 5a5b7 (16:65b7)
+GuardDrinksList:
db FRESH_WATER, SODA_POP, LEMONADE, $00
diff --git a/engine/overworld/set_blackout_map.asm b/engine/overworld/set_blackout_map.asm
new file mode 100644
index 00000000..9bfe82bd
--- /dev/null
+++ b/engine/overworld/set_blackout_map.asm
@@ -0,0 +1,29 @@
+SetLastBlackoutMap:
+; Set the map to return to when
+; blacking out or using Teleport or Dig.
+; Safari rest houses don't count.
+
+ push hl
+ ld hl, SafariZoneRestHouses
+ ld a, [wCurMap]
+ ld b, a
+.loop
+ ld a, [hli]
+ cp -1
+ jr z, .notresthouse
+ cp b
+ jr nz, .loop
+ jr .done
+
+.notresthouse
+ ld a, [wLastMap]
+ ld [wLastBlackoutMap], a
+.done
+ pop hl
+ ret
+
+SafariZoneRestHouses:
+ db SAFARI_ZONE_REST_HOUSE_2
+ db SAFARI_ZONE_REST_HOUSE_3
+ db SAFARI_ZONE_REST_HOUSE_4
+ db -1
diff --git a/engine/overworld/ssanne.asm b/engine/overworld/ssanne.asm
index f1a8ecf9..712c53ed 100755
--- a/engine/overworld/ssanne.asm
+++ b/engine/overworld/ssanne.asm
@@ -1,6 +1,6 @@
-AnimateBoulderDust: ; 79f54 (1e:5f54)
+AnimateBoulderDust:
ld a, $1
- ld [wcd50], a ; select the boulder dust offsets
+ ld [wWhichAnimationOffsets], a ; select the boulder dust offsets
ld a, [wUpdateSpritesEnabled]
push af
ld a, $ff
@@ -8,14 +8,14 @@ AnimateBoulderDust: ; 79f54 (1e:5f54)
ld a, %11100100
ld [rOBP1], a
call LoadSmokeTileFourTimes
- callba WriteCutTreeBoulderDustAnimationOAMBlock
+ callba WriteCutOrBoulderDustAnimationOAMBlock
ld c, 8 ; number of steps in animation
.loop
push bc
call GetMoveBoulderDustFunctionPointer
ld bc, .returnAddress
push bc
- ld c, $4
+ ld c, 4
jp [hl]
.returnAddress
ld a, [rOBP1]
@@ -29,14 +29,14 @@ AnimateBoulderDust: ; 79f54 (1e:5f54)
ld [wUpdateSpritesEnabled], a
jp LoadPlayerSpriteGraphics
-GetMoveBoulderDustFunctionPointer: ; 79f92 (1e:5f92)
+GetMoveBoulderDustFunctionPointer:
ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
ld hl, MoveBoulderDustFunctionPointerTable
ld c, a
ld b, $0
add hl, bc
ld a, [hli]
- ld [wd08a], a
+ ld [wCoordAdjustmentAmount], a
ld a, [hli]
ld e, a
ld a, [hli]
@@ -51,7 +51,7 @@ GetMoveBoulderDustFunctionPointer: ; 79f92 (1e:5f92)
pop hl
ret
-MoveBoulderDustFunctionPointerTable: ; 79fb0 (1e:5fb0)
+MoveBoulderDustFunctionPointerTable:
; facing down
db $FF,$00
dw AdjustOAMBlockYPos
@@ -68,7 +68,7 @@ MoveBoulderDustFunctionPointerTable: ; 79fb0 (1e:5fb0)
db $FF,$01
dw AdjustOAMBlockXPos
-LoadSmokeTileFourTimes: ; 79fc0 (1e:5fc0)
+LoadSmokeTileFourTimes:
ld hl, vChars1 + $7c0
ld c, $4
.loop
@@ -83,10 +83,11 @@ LoadSmokeTileFourTimes: ; 79fc0 (1e:5fc0)
jr nz, .loop
ret
-LoadSmokeTile: ; 79fd4 (1e:5fd4)
- ld de, SSAnneSmokePuffTile ; $5fdd
- ld bc, (BANK(SSAnneSmokePuffTile) << 8) + $01
+LoadSmokeTile:
+ ld de, SSAnneSmokePuffTile
+ lb bc, BANK(SSAnneSmokePuffTile), (SSAnneSmokePuffTileEnd - SSAnneSmokePuffTile) / $10
jp CopyVideoData
-SSAnneSmokePuffTile: ; 79fdd (1e:5fdd)
+SSAnneSmokePuffTile:
INCBIN "gfx/ss_anne_smoke_puff.2bpp"
+SSAnneSmokePuffTileEnd:
diff --git a/engine/overworld/tileset_header.asm b/engine/overworld/tileset_header.asm
new file mode 100644
index 00000000..6e33974f
--- /dev/null
+++ b/engine/overworld/tileset_header.asm
@@ -0,0 +1,60 @@
+LoadTilesetHeader:
+ call GetPredefRegisters
+ push hl
+ ld d, 0
+ ld a, [wCurMapTileset]
+ add a
+ add a
+ ld b, a
+ add a
+ add b ; a = tileset * 12
+ jr nc, .noCarry
+ inc d
+.noCarry
+ ld e, a
+ ld hl, Tilesets
+ add hl, de
+ ld de, wTilesetBank
+ ld c, $b
+.copyTilesetHeaderLoop
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .copyTilesetHeaderLoop
+ ld a, [hl]
+ ld [hTilesetType], a
+ xor a
+ ld [$ffd8], a
+ pop hl
+ ld a, [wCurMapTileset]
+ push hl
+ push de
+ ld hl, DungeonTilesets
+ ld de, $1
+ call IsInArray
+ pop de
+ pop hl
+ jr c, .asm_c797
+ ld a, [wCurMapTileset]
+ ld b, a
+ ld a, [hPreviousTileset]
+ cp b
+ jr z, .done
+.asm_c797
+ ld a, [wDestinationWarpID]
+ cp $ff
+ jr z, .done
+ call LoadDestinationWarpPosition
+ ld a, [wYCoord]
+ and $1
+ ld [wYBlockCoord], a
+ ld a, [wXCoord]
+ and $1
+ ld [wXBlockCoord], a
+.done
+ ret
+
+INCLUDE "data/dungeon_tilesets.asm"
+
+INCLUDE "data/tileset_headers.asm"
diff --git a/engine/overworld/trainers.asm b/engine/overworld/trainers.asm
index 4aaab3ed..655c6b2a 100755
--- a/engine/overworld/trainers.asm
+++ b/engine/overworld/trainers.asm
@@ -1,42 +1,42 @@
-_GetSpritePosition1: ; 567f9 (15:67f9)
+_GetSpritePosition1:
ld hl, wSpriteStateData1
ld de, $4
ld a, [wSpriteIndex]
ld [H_SPRITEINDEX], a
call GetSpriteDataPointer
- ld a, [hli]
+ ld a, [hli] ; c1x4 (screen Y pos)
ld [$ffeb], a
inc hl
- ld a, [hl]
+ ld a, [hl] ; c1x6 (screen X pos)
ld [$ffec], a
- ld de, $fe
+ ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6)
add hl, de
- ld a, [hli]
+ ld a, [hli] ; c2x4 (map Y pos)
ld [$ffed], a
- ld a, [hl]
+ ld a, [hl] ; c2x5 (map X pos)
ld [$ffee], a
ret
-_GetSpritePosition2: ; 56819 (15:6819)
+_GetSpritePosition2:
ld hl, wSpriteStateData1
ld de, $4
ld a, [wSpriteIndex]
ld [H_SPRITEINDEX], a
call GetSpriteDataPointer
ld a, [hli] ; c1x4 (screen Y pos)
- ld [wd130], a
+ ld [wSavedSpriteScreenY], a
inc hl
ld a, [hl] ; c1x6 (screen X pos)
- ld [wd131], a
- ld de, $104 - $6
+ ld [wSavedSpriteScreenX], a
+ ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6)
add hl, de
ld a, [hli] ; c2x4 (map Y pos)
- ld [wd132], a
+ ld [wSavedSpriteMapY], a
ld a, [hl] ; c2x5 (map X pos)
- ld [wd133], a
+ ld [wSavedSpriteMapX], a
ret
-_SetSpritePosition1: ; 5683d (15:683d)
+_SetSpritePosition1:
ld hl, wSpriteStateData1
ld de, $4
ld a, [wSpriteIndex]
@@ -47,7 +47,7 @@ _SetSpritePosition1: ; 5683d (15:683d)
inc hl
ld a, [$ffec] ; c1x6 (screen X pos)
ld [hl], a
- ld de, $104 - $6
+ ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6)
add hl, de
ld a, [$ffed] ; c2x4 (map Y pos)
ld [hli], a
@@ -55,36 +55,36 @@ _SetSpritePosition1: ; 5683d (15:683d)
ld [hl], a
ret
-_SetSpritePosition2: ; 5685d (15:685d)
+_SetSpritePosition2:
ld hl, wSpriteStateData1
- ld de, $0004
+ ld de, 4
ld a, [wSpriteIndex]
ld [H_SPRITEINDEX], a
call GetSpriteDataPointer
- ld a, [wd130]
- ld [hli], a
+ ld a, [wSavedSpriteScreenY]
+ ld [hli], a ; c1x4 (screen Y pos)
inc hl
- ld a, [wd131]
- ld [hl], a
- ld de, $00fe
+ ld a, [wSavedSpriteScreenX]
+ ld [hl], a ; c1x6 (screen X pos)
+ ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6)
add hl, de
- ld a, [wd132]
- ld [hli], a
- ld a, [wd133]
- ld [hl], a
+ ld a, [wSavedSpriteMapY]
+ ld [hli], a ; c2x4 (map Y pos)
+ ld a, [wSavedSpriteMapX]
+ ld [hl], a ; c2x5 (map X pos)
ret
-TrainerWalkUpToPlayer: ; 56881 (15:6881)
+TrainerWalkUpToPlayer:
ld a, [wSpriteIndex]
swap a
- ld [wTrainerSpriteOffset], a ; wWhichTrade
+ ld [wTrainerSpriteOffset], a
call ReadTrainerScreenPosition
ld a, [wTrainerFacingDirection]
- and a
+ and a ; SPRITE_FACING_DOWN
jr z, .facingDown
- cp $4
+ cp SPRITE_FACING_UP
jr z, .facingUp
- cp $8
+ cp SPRITE_FACING_LEFT
jr z, .facingLeft
jr .facingRight
.facingDown
@@ -148,8 +148,8 @@ TrainerWalkUpToPlayer: ; 56881 (15:6881)
jp MoveSprite_
; input: de = offset within sprite entry
-; output: de = pointer to sprite data
-GetSpriteDataPointer: ; 56903 (15:6903)
+; output: hl = pointer to sprite data
+GetSpriteDataPointer:
push de
add hl, de
ld a, [H_SPRITEINDEX]
@@ -161,10 +161,10 @@ GetSpriteDataPointer: ; 56903 (15:6903)
ret
; tests if this trainer is in the right position to engage the player and do so if she is.
-TrainerEngage: ; 5690f (15:690f)
+TrainerEngage:
push hl
push de
- ld a, [wTrainerSpriteOffset] ; wWhichTrade
+ ld a, [wTrainerSpriteOffset]
add $2
ld d, $0
ld e, a
@@ -175,7 +175,7 @@ TrainerEngage: ; 5690f (15:690f)
jr nz, .spriteOnScreen ; test if sprite is on screen
jp .noEngage
.spriteOnScreen
- ld a, [wTrainerSpriteOffset] ; wWhichTrade
+ ld a, [wTrainerSpriteOffset]
add $9
ld d, $0
ld e, a
@@ -218,57 +218,57 @@ TrainerEngage: ; 5690f (15:690f)
jp .noEngage
.engage
call CheckPlayerIsInFrontOfSprite
- ld a, [wTrainerSpriteOffset] ; wWhichTrade
+ ld a, [wTrainerSpriteOffset]
and a
jr z, .noEngage
ld hl, wFlags_0xcd60
set 0, [hl]
call EngageMapTrainer
ld a, $ff
-.noEngage: ; 56988 (15:6988)
- ld [wTrainerSpriteOffset], a ; wWhichTrade
+.noEngage
+ ld [wTrainerSpriteOffset], a
pop de
pop hl
ret
; reads trainer's Y position to wTrainerScreenY and X position to wTrainerScreenX
-ReadTrainerScreenPosition: ; 5698e (15:698e)
- ld a, [wTrainerSpriteOffset] ; wWhichTrade
+ReadTrainerScreenPosition:
+ ld a, [wTrainerSpriteOffset]
add $4
ld d, $0
ld e, a
ld hl, wSpriteStateData1
add hl, de
- ld a, [hl]
+ ld a, [hl] ; c1x4 (sprite Y pos)
ld [wTrainerScreenY], a
- ld a, [wTrainerSpriteOffset] ; wWhichTrade
+ ld a, [wTrainerSpriteOffset]
add $6
ld d, $0
ld e, a
ld hl, wSpriteStateData1
add hl, de
- ld a, [hl]
+ ld a, [hl] ; c1x6 (sprite X pos)
ld [wTrainerScreenX], 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)
+CheckSpriteCanSeePlayer:
ld b, a
- ld a, [wTrainerEngageDistance] ; sprite line of sight (engage distance)
+ ld a, [wTrainerEngageDistance] ; how far the trainer can see
cp b
jr nc, .checkIfLinedUp
jr .notInLine ; player too far away
.checkIfLinedUp
ld a, [wTrainerFacingDirection] ; sprite facing direction
- cp $0 ; down
+ cp SPRITE_FACING_DOWN
jr z, .checkXCoord
- cp $4 ; up
+ cp SPRITE_FACING_UP
jr z, .checkXCoord
- cp $8 ; left
+ cp SPRITE_FACING_LEFT
jr z, .checkYCoord
- cp $c ; right
+ cp SPRITE_FACING_RIGHT
jr z, .checkYCoord
jr .notInLine
.checkXCoord
@@ -290,11 +290,11 @@ CheckSpriteCanSeePlayer: ; 569af (15:69af)
ret
; tests if the player is in front of the sprite (rather than behind it)
-CheckPlayerIsInFrontOfSprite: ; 569e3 (15:69e3)
- ld a, [W_CURMAP] ; W_CURMAP
+CheckPlayerIsInFrontOfSprite:
+ ld a, [wCurMap]
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] ; wWhichTrade
+ jp z, .engage ; bypass this for power plant to get voltorb fake items to work
+ ld a, [wTrainerSpriteOffset]
add $4
ld d, $0
ld e, a
@@ -306,7 +306,7 @@ CheckPlayerIsInFrontOfSprite: ; 569e3 (15:69e3)
ld a, $c
.notOnTopmostTile
ld [wTrainerScreenY], a
- ld a, [wTrainerSpriteOffset] ; wWhichTrade
+ ld a, [wTrainerSpriteOffset]
add $6
ld d, $0
ld e, a
@@ -315,21 +315,21 @@ CheckPlayerIsInFrontOfSprite: ; 569e3 (15:69e3)
ld a, [hl] ; c1x6 (sprite screen X pos)
ld [wTrainerScreenX], a
ld a, [wTrainerFacingDirection] ; facing direction
- cp $0
+ cp SPRITE_FACING_DOWN
jr nz, .notFacingDown
ld a, [wTrainerScreenY] ; sprite screen Y pos
cp $3c
jr c, .engage ; sprite above player
jr .noEngage ; sprite below player
.notFacingDown
- cp $4
+ cp SPRITE_FACING_UP
jr nz, .notFacingUp
ld a, [wTrainerScreenY] ; sprite screen Y pos
cp $3c
jr nc, .engage ; sprite below player
jr .noEngage ; sprite above player
.notFacingUp
- cp $8
+ cp SPRITE_FACING_LEFT
jr nz, .notFacingLeft
ld a, [wTrainerScreenX] ; sprite screen X pos
cp $40
@@ -345,5 +345,5 @@ CheckPlayerIsInFrontOfSprite: ; 569e3 (15:69e3)
.noEngage
xor a
.done
- ld [wTrainerSpriteOffset], a ; wWhichTrade
+ ld [wTrainerSpriteOffset], a
ret
diff --git a/engine/overworld/update_map.asm b/engine/overworld/update_map.asm
new file mode 100644
index 00000000..8577b9e7
--- /dev/null
+++ b/engine/overworld/update_map.asm
@@ -0,0 +1,126 @@
+; replaces a tile block with the one specified in [wNewTileBlockID]
+; and redraws the map view if necessary
+; b = Y
+; c = X
+ReplaceTileBlock:
+ call GetPredefRegisters
+ ld hl, wOverworldMap
+ ld a, [wCurMapWidth]
+ add $6
+ ld e, a
+ ld d, $0
+ add hl, de
+ add hl, de
+ add hl, de
+ ld e, $3
+ add hl, de
+ ld e, a
+ ld a, b
+ and a
+ jr z, .addX
+; add width * Y
+.addWidthYTimesLoop
+ add hl, de
+ dec b
+ jr nz, .addWidthYTimesLoop
+.addX
+ add hl, bc ; add X
+ ld a, [wNewTileBlockID]
+ ld [hl], a
+ ld a, [wCurrentTileBlockMapViewPointer]
+ ld c, a
+ ld a, [wCurrentTileBlockMapViewPointer + 1]
+ ld b, a
+ call CompareHLWithBC
+ ret c ; return if the replaced tile block is below the map view in memory
+ push hl
+ ld l, e
+ ld h, $0
+ ld e, $6
+ ld d, h
+ add hl, hl
+ add hl, hl
+ add hl, de
+ add hl, bc
+ pop bc
+ call CompareHLWithBC
+ ret c ; return if the replaced tile block is above the map view in memory
+
+RedrawMapView:
+ ld a, [wIsInBattle]
+ inc a
+ ret z
+ ld a, [H_AUTOBGTRANSFERENABLED]
+ push af
+ ld a, [hTilesetType]
+ push af
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a
+ ld [hTilesetType], a ; no flower/water BG tile animations
+ call LoadCurrentMapView
+ call RunDefaultPaletteCommand
+ ld hl, wMapViewVRAMPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, -2 * 32
+ add hl, de
+ ld a, h
+ and $3
+ or $98
+ ld a, l
+ ld [wBuffer], a
+ ld a, h
+ ld [wBuffer + 1], a ; this copy of the address is not used
+ ld a, 2
+ ld [$ffbe], a
+ ld c, 9 ; number of rows of 2x2 tiles (this covers the whole screen)
+.redrawRowLoop
+ push bc
+ push hl
+ push hl
+ ld hl, wTileMap - 2 * SCREEN_WIDTH
+ ld de, SCREEN_WIDTH
+ ld a, [$ffbe]
+.calcWRAMAddrLoop
+ add hl, de
+ dec a
+ jr nz, .calcWRAMAddrLoop
+ call CopyToRedrawRowOrColumnSrcTiles
+ pop hl
+ ld de, $20
+ ld a, [$ffbe]
+ ld c, a
+.calcVRAMAddrLoop
+ add hl, de
+ ld a, h
+ and $3
+ or $98
+ dec c
+ jr nz, .calcVRAMAddrLoop
+ ld [hRedrawRowOrColumnDest + 1], a
+ ld a, l
+ ld [hRedrawRowOrColumnDest], a
+ ld a, REDRAW_ROW
+ ld [hRedrawRowOrColumnMode], a
+ call DelayFrame
+ ld hl, $ffbe
+ inc [hl]
+ inc [hl]
+ pop hl
+ pop bc
+ dec c
+ jr nz, .redrawRowLoop
+ pop af
+ ld [hTilesetType], a
+ pop af
+ ld [H_AUTOBGTRANSFERENABLED], a
+ ret
+
+CompareHLWithBC:
+ ld a, h
+ sub b
+ ret nz
+ ld a, l
+ sub c
+ ret
diff --git a/engine/overworld/wild_mons.asm b/engine/overworld/wild_mons.asm
new file mode 100644
index 00000000..6444ab7e
--- /dev/null
+++ b/engine/overworld/wild_mons.asm
@@ -0,0 +1,33 @@
+LoadWildData:
+ ld hl,WildDataPointers
+ ld a,[wCurMap]
+
+ ; get wild data for current map
+ ld c,a
+ ld b,0
+ add hl,bc
+ add hl,bc
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a ; hl now points to wild data for current map
+ ld a,[hli]
+ ld [wGrassRate],a
+ and a
+ jr z,.NoGrassData ; if no grass data, skip to surfing data
+ push hl
+ ld de,wGrassMons ; otherwise, load grass data
+ ld bc,$0014
+ call CopyData
+ pop hl
+ ld bc,$0014
+ add hl,bc
+.NoGrassData
+ ld a,[hli]
+ ld [wWaterRate],a
+ and a
+ ret z ; if no water data, we're done
+ ld de,wWaterMons ; otherwise, load surfing data
+ ld bc,$0014
+ jp CopyData
+
+INCLUDE "data/wild_mons.asm"