summaryrefslogtreecommitdiff
path: root/engine/overworld
diff options
context:
space:
mode:
Diffstat (limited to 'engine/overworld')
-rw-r--r--engine/overworld/advance_player_sprite.asm244
-rwxr-xr-xengine/overworld/auto_movement.asm52
-rwxr-xr-xengine/overworld/cut.asm5
-rwxr-xr-xengine/overworld/cut2.asm2
-rw-r--r--engine/overworld/dungeon_warps.asm15
-rwxr-xr-xengine/overworld/dust_smoke.asm2
-rwxr-xr-xengine/overworld/elevator.asm6
-rwxr-xr-xengine/overworld/emotion_bubbles.asm24
-rwxr-xr-xengine/overworld/healing_machine.asm27
-rwxr-xr-xengine/overworld/hidden_objects.asm34
-rwxr-xr-xengine/overworld/ledges.asm16
-rwxr-xr-xengine/overworld/map_sprites.asm604
-rw-r--r--engine/overworld/missable_objects.asm11
-rw-r--r--engine/overworld/movement.asm385
-rwxr-xr-xengine/overworld/npc_movement_2.asm24
-rw-r--r--engine/overworld/pathfinding.asm8
-rwxr-xr-xengine/overworld/player_animations.asm26
-rw-r--r--engine/overworld/player_state.asm29
-rw-r--r--engine/overworld/push_boulder.asm2
-rw-r--r--engine/overworld/sprite_collisions.asm46
-rw-r--r--engine/overworld/tilesets.asm21
-rwxr-xr-xengine/overworld/turn_sprite.asm25
22 files changed, 981 insertions, 627 deletions
diff --git a/engine/overworld/advance_player_sprite.asm b/engine/overworld/advance_player_sprite.asm
new file mode 100644
index 00000000..4ebdac84
--- /dev/null
+++ b/engine/overworld/advance_player_sprite.asm
@@ -0,0 +1,244 @@
+_AdvancePlayerSprite::
+ ld a, [wSpritePlayerStateData1YStepVector]
+ ld b, a
+ ld a, [wSpritePlayerStateData1XStepVector]
+ ld c, a
+ ld hl, wWalkCounter ; walking animation counter
+ dec [hl]
+ jr nz, .afterUpdateMapCoords
+; if it's the end of the animation, update the player's map coordinates
+ ld hl, wPikachuOverworldStateFlags
+ res 5, [hl]
+ ld a, [wYCoord]
+ add b
+ ld [wYCoord], a
+ ld a, [wXCoord]
+ add c
+ ld [wXCoord], a
+.afterUpdateMapCoords
+ ld a, [wWalkCounter] ; walking animation counter
+ cp $07
+ jp nz, .scrollBackgroundAndSprites
+; if this is the first iteration of the animation
+ ld a, c
+ cp $01
+ jr nz, .checkIfMovingWest
+; moving east
+ ld a, [wMapViewVRAMPointer]
+ ld e, a
+ and $e0
+ ld d, a
+ ld a, e
+ add $02
+ and $1f
+ or d
+ ld [wMapViewVRAMPointer], a
+ jr .adjustXCoordWithinBlock
+.checkIfMovingWest
+ cp $ff
+ jr nz, .checkIfMovingSouth
+; moving west
+ ld a, [wMapViewVRAMPointer]
+ ld e, a
+ and $e0
+ ld d, a
+ ld a, e
+ sub $02
+ and $1f
+ or d
+ ld [wMapViewVRAMPointer], a
+ jr .adjustXCoordWithinBlock
+.checkIfMovingSouth
+ ld a, b
+ cp $01
+ jr nz, .checkIfMovingNorth
+; moving south
+ ld a, [wMapViewVRAMPointer]
+ add $40
+ ld [wMapViewVRAMPointer], a
+ jr nc, .adjustXCoordWithinBlock
+ ld a, [wMapViewVRAMPointer + 1]
+ inc a
+ and $03
+ or $98
+ ld [wMapViewVRAMPointer + 1], a
+ jr .adjustXCoordWithinBlock
+.checkIfMovingNorth
+ cp $ff
+ jr nz, .adjustXCoordWithinBlock
+; moving north
+ ld a, [wMapViewVRAMPointer]
+ sub $40
+ ld [wMapViewVRAMPointer], a
+ jr nc, .adjustXCoordWithinBlock
+ ld a, [wMapViewVRAMPointer + 1]
+ dec a
+ and $03
+ or $98
+ ld [wMapViewVRAMPointer + 1], a
+.adjustXCoordWithinBlock
+ ld a, c
+ and a
+ jr z, .pointlessJump ; mistake?
+.pointlessJump
+ ld hl, wXBlockCoord
+ ld a, [hl]
+ add c
+ ld [hl], a
+ cp $02
+ jr nz, .checkForMoveToWestBlock
+; moved into the tile block to the east
+ xor a
+ ld [hl], a
+ ld hl, wXOffsetSinceLastSpecialWarp
+ inc [hl]
+ ld de, wCurrentTileBlockMapViewPointer
+ call MoveTileBlockMapPointerEast
+ jr .updateMapView
+.checkForMoveToWestBlock
+ cp $ff
+ jr nz, .adjustYCoordWithinBlock
+; moved into the tile block to the west
+ ld a, $01
+ ld [hl], a
+ ld hl, wXOffsetSinceLastSpecialWarp
+ dec [hl]
+ ld de, wCurrentTileBlockMapViewPointer
+ call MoveTileBlockMapPointerWest
+ jr .updateMapView
+.adjustYCoordWithinBlock
+ ld hl, wYBlockCoord
+ ld a, [hl]
+ add b
+ ld [hl], a
+ cp $02
+ jr nz, .checkForMoveToNorthBlock
+; moved into the tile block to the south
+ xor a
+ ld [hl], a
+ ld hl, wYOffsetSinceLastSpecialWarp
+ inc [hl]
+ ld de, wCurrentTileBlockMapViewPointer
+ ld a, [wCurMapWidth]
+ call MoveTileBlockMapPointerSouth
+ jr .updateMapView
+.checkForMoveToNorthBlock
+ cp $ff
+ jr nz, .updateMapView
+; moved into the tile block to the north
+ ld a, $01
+ ld [hl], a
+ ld hl, wYOffsetSinceLastSpecialWarp
+ dec [hl]
+ ld de, wCurrentTileBlockMapViewPointer
+ ld a, [wCurMapWidth]
+ call MoveTileBlockMapPointerNorth
+.updateMapView
+ call LoadCurrentMapView
+ ld a, [wSpritePlayerStateData1YStepVector]
+ cp $01
+ jr nz, .checkIfMovingNorth2
+; if moving south
+ call ScheduleSouthRowRedraw
+ jr .scrollBackgroundAndSprites
+.checkIfMovingNorth2
+ cp $ff
+ jr nz, .checkIfMovingEast2
+; if moving north
+ call ScheduleNorthRowRedraw
+ jr .scrollBackgroundAndSprites
+.checkIfMovingEast2
+ ld a, [wSpritePlayerStateData1XStepVector]
+ cp $01
+ jr nz, .checkIfMovingWest2
+; if moving east
+ call ScheduleEastColumnRedraw
+ jr .scrollBackgroundAndSprites
+.checkIfMovingWest2
+ cp $ff
+ jr nz, .scrollBackgroundAndSprites
+; if moving west
+ call ScheduleWestColumnRedraw
+.scrollBackgroundAndSprites
+ ld a, [wSpritePlayerStateData1YStepVector]
+ add a
+ ld b, a
+ ld a, [wSpritePlayerStateData1XStepVector]
+ add a
+ ld c, a
+; shift all the sprites in the direction opposite of the player's motion
+; so that the player appears to move relative to them
+ ld hl, wSprite01StateData1YPixels
+ ld e, 15
+.spriteShiftLoop
+ ld a, [hl]
+ sub b
+ ld [hli], a
+ inc l
+ ld a, [hl]
+ sub c
+ ld [hl], a
+ ld a, $0e
+ add l
+ ld l, a
+ dec e
+ jr nz, .spriteShiftLoop
+.done
+ ldh a, [hSCY]
+ add b
+ ldh [hSCY], a ; update background scroll Y
+ ldh a, [hSCX]
+ add c
+ ldh [hSCX], a ; update background scroll X
+ ret
+
+; the following four functions are used to move the pointer to the upper left
+; corner of the tile block map in the direction of motion
+
+MoveTileBlockMapPointerEast::
+ ld a, [de]
+ add $01
+ ld [de], a
+ ret nc
+ inc de
+ ld a, [de]
+ inc a
+ ld [de], a
+ ret
+
+MoveTileBlockMapPointerWest::
+ ld a, [de]
+ sub $01
+ ld [de], a
+ ret nc
+ inc de
+ ld a, [de]
+ dec a
+ ld [de], a
+ ret
+
+MoveTileBlockMapPointerSouth::
+ add MAP_BORDER * 2
+ ld b, a
+ ld a, [de]
+ add b
+ ld [de], a
+ ret nc
+ inc de
+ ld a, [de]
+ inc a
+ ld [de], a
+ ret
+
+MoveTileBlockMapPointerNorth::
+ add MAP_BORDER * 2
+ ld b, a
+ ld a, [de]
+ sub b
+ ld [de], a
+ ret nc
+ inc de
+ ld a, [de]
+ dec a
+ ld [de], a
+ ret
diff --git a/engine/overworld/auto_movement.asm b/engine/overworld/auto_movement.asm
index 9c078f08..a68da55f 100755
--- a/engine/overworld/auto_movement.asm
+++ b/engine/overworld/auto_movement.asm
@@ -37,8 +37,8 @@ _EndNPCMovementScript::
res 1, [hl]
xor a
ld [wNPCMovementScriptSpriteOffset], a
- ld [wNPCMovementScriptPointerTableNum], a
ld [wNPCMovementScriptFunctionNum], a
+ ld [wNPCMovementScriptPointerTableNum], a
ld [wWastedByteCD3A], a
ld [wSimulatedJoypadStatesIndex], a
ld [wSimulatedJoypadStatesEnd], a
@@ -79,6 +79,10 @@ PalletMovementScript_OakMoveLeft:
ld a, $3
ld [wNPCMovementScriptFunctionNum], a
.done
+ ld a, BANK(Music_MuseumGuy)
+ ld c, a
+ ld a, MUSIC_MUSEUM_GUY
+ call PlayMusic
ld hl, wFlags_D733
set 1, [hl]
ld a, $fc
@@ -127,8 +131,9 @@ PalletMovementScript_WalkToLab:
ld [wNPCMovementScriptFunctionNum], a
ret
+
RLEList_ProfOakWalkToLab:
- db NPC_MOVEMENT_DOWN, 5
+ db NPC_MOVEMENT_DOWN, 6 ; differs from red
db NPC_MOVEMENT_LEFT, 1
db NPC_MOVEMENT_DOWN, 5
db NPC_MOVEMENT_RIGHT, 3
@@ -141,7 +146,7 @@ RLEList_PlayerWalkToLab:
db D_RIGHT, 3
db D_DOWN, 5
db D_LEFT, 1
- db D_DOWN, 6
+ db D_DOWN, 7 ; differs from red
db -1 ; end
PalletMovementScript_Done:
@@ -163,11 +168,9 @@ PewterMuseumGuyMovementScriptPointerTable::
PewterMovementScript_WalkToMuseum:
ld a, BANK(Music_MuseumGuy)
- ld [wAudioROMBank], a
- ld [wAudioSavedROMBank], a
+ ld c, a
ld a, MUSIC_MUSEUM_GUY
- ld [wNewSoundID], a
- call PlaySound
+ call PlayMusic
ld a, [wSpriteIndex]
swap a
ld [wNPCMovementScriptSpriteOffset], a
@@ -179,7 +182,7 @@ PewterMovementScript_WalkToMuseum:
ld [wSimulatedJoypadStatesIndex], a
xor a
ld [wWhichPewterGuy], a
- predef PewterGuys
+ call PewterGuys
ld hl, wNPCMovementDirections2
ld de, RLEList_PewterMuseumGuy
call DecodeRLEList
@@ -219,11 +222,9 @@ PewterGymGuyMovementScriptPointerTable::
PewterMovementScript_WalkToGym:
ld a, BANK(Music_MuseumGuy)
- ld [wAudioROMBank], a
- ld [wAudioSavedROMBank], a
+ ld c, a
ld a, MUSIC_MUSEUM_GUY
- ld [wNewSoundID], a
- call PlaySound
+ call PlayMusic
ld a, [wSpriteIndex]
swap a
ld [wNPCMovementScriptSpriteOffset], a
@@ -236,7 +237,7 @@ PewterMovementScript_WalkToGym:
ld [wSimulatedJoypadStatesIndex], a
ld a, 1
ld [wWhichPewterGuy], a
- predef PewterGuys
+ call PewterGuys
ld hl, wNPCMovementDirections2
ld de, RLEList_PewterGymGuy
call DecodeRLEList
@@ -266,27 +267,4 @@ RLEList_PewterGymGuy:
db NPC_MOVEMENT_RIGHT, 3
db -1 ; end
-FreezeEnemyTrainerSprite::
- ld a, [wCurMap]
- cp POKEMON_TOWER_7F
- ret z ; the Rockets on Pokemon Tower 7F leave after battling, so don't freeze them
- ld hl, RivalIDs
- ld a, [wEngagedTrainerClass]
- ld b, a
-.loop
- ld a, [hli]
- cp -1
- jr z, .notRival
- cp b
- ret z ; the rival leaves after battling, so don't freeze him
- jr .loop
-.notRival
- ld a, [wSpriteIndex]
- ldh [hSpriteIndex], a
- jp SetSpriteMovementBytesToFF
-
-RivalIDs:
- db OPP_RIVAL1
- db OPP_RIVAL2
- db OPP_RIVAL3
- db -1 ; end
+INCLUDE "engine/events/pewter_guys.asm"
diff --git a/engine/overworld/cut.asm b/engine/overworld/cut.asm
index 6a92ccc0..e36b8d88 100755
--- a/engine/overworld/cut.asm
+++ b/engine/overworld/cut.asm
@@ -76,6 +76,7 @@ InitCutAnimOAM:
ld [wWhichAnimationOffsets], a
ld a, %11100100
ldh [rOBP1], a
+ call UpdateGBCPal_OBP1
ld a, [wCutTile]
cp $52
jr z, .grass
@@ -123,8 +124,8 @@ WriteCutOrBoulderDustAnimationOAMBlock:
jp WriteOAMBlock
CutOrBoulderDustAnimationTilesAndAttributes:
- dbsprite 2, -1, 0, 4, $fd, OAM_OBP1
- dbsprite 2, -1, 0, 6, $ff, OAM_OBP1
+ dbsprite 2, -1, 4, 4, $fd, OAM_OBP1 | %100
+ dbsprite 2, -1, 4, 6, $ff, OAM_OBP1 | %100
GetCutOrBoulderDustAnimationOffsets:
ld hl, wSpritePlayerStateData1YPixels
diff --git a/engine/overworld/cut2.asm b/engine/overworld/cut2.asm
index 3d4a5905..1f691eef 100755
--- a/engine/overworld/cut2.asm
+++ b/engine/overworld/cut2.asm
@@ -18,6 +18,7 @@ AnimCut:
ldh a, [rOBP1]
xor $64
ldh [rOBP1], a
+ call UpdateGBCPal_OBP1
call DelayFrame
pop bc
dec c
@@ -68,6 +69,7 @@ AnimCutGrass_UpdateOAMEntries:
ldh a, [rOBP1]
xor $64
ldh [rOBP1], a
+ call UpdateGBCPal_OBP1
call DelayFrame
pop bc
dec c
diff --git a/engine/overworld/dungeon_warps.asm b/engine/overworld/dungeon_warps.asm
new file mode 100644
index 00000000..7641c688
--- /dev/null
+++ b/engine/overworld/dungeon_warps.asm
@@ -0,0 +1,15 @@
+IsPlayerOnDungeonWarp::
+ xor a
+ ld [wWhichDungeonWarp], a
+ ld a, [wd72d]
+ bit 4, a
+ ret nz
+ call ArePlayerCoordsInArray
+ ret nc
+ ld a, [wCoordIndex]
+ ld [wWhichDungeonWarp], a
+ ld hl, wd72d
+ set 4, [hl]
+ ld hl, wd732
+ set 4, [hl]
+ ret
diff --git a/engine/overworld/dust_smoke.asm b/engine/overworld/dust_smoke.asm
index a20a0591..773def96 100755
--- a/engine/overworld/dust_smoke.asm
+++ b/engine/overworld/dust_smoke.asm
@@ -7,6 +7,7 @@ AnimateBoulderDust:
ld [wUpdateSpritesEnabled], a
ld a, %11100100
ldh [rOBP1], a
+ call UpdateGBCPal_OBP1
call LoadSmokeTileFourTimes
farcall WriteCutOrBoulderDustAnimationOAMBlock
ld c, 8 ; number of steps in animation
@@ -21,6 +22,7 @@ AnimateBoulderDust:
ldh a, [rOBP1]
xor %01100100
ldh [rOBP1], a
+ call UpdateGBCPal_OBP1
call Delay3
pop bc
dec c
diff --git a/engine/overworld/elevator.asm b/engine/overworld/elevator.asm
index fa404602..b873ffad 100755
--- a/engine/overworld/elevator.asm
+++ b/engine/overworld/elevator.asm
@@ -4,8 +4,7 @@ ShakeElevator::
ld de, SCREEN_HEIGHT * $20
call ShakeElevatorRedrawRow
call Delay3
- ld a, SFX_STOP_ALL_MUSIC
- call PlaySound
+ call StopAllMusic
ldh a, [hSCY]
ld d, a
ld e, $1
@@ -27,8 +26,7 @@ ShakeElevator::
jr nz, .shakeLoop
ld a, d
ldh [hSCY], a
- ld a, SFX_STOP_ALL_MUSIC
- call PlaySound
+ call StopAllMusic
ld c, BANK(SFX_Safari_Zone_PA)
ld a, SFX_SAFARI_ZONE_PA
call PlayMusic
diff --git a/engine/overworld/emotion_bubbles.asm b/engine/overworld/emotion_bubbles.asm
index 5a41c226..3ad714e9 100755
--- a/engine/overworld/emotion_bubbles.asm
+++ b/engine/overworld/emotion_bubbles.asm
@@ -1,13 +1,16 @@
EmotionBubble:
ld a, [wWhichEmotionBubble]
+ and $f
+ swap a
ld c, a
ld b, 0
- ld hl, EmotionBubblesPointerTable
+ ld hl, EmotionBubbles
+ add hl, bc ; each emotion bubble is 16 bytes, so calculate the offset directly instead of with a pointer table
add hl, bc
add hl, bc
- ld e, [hl]
- inc hl
- ld d, [hl]
+ add hl, bc
+ ld e, l
+ ld d, h
ld hl, vChars1 tile $78
lb bc, BANK(EmotionBubbles), 4
call CopyVideoData
@@ -59,13 +62,9 @@ EmotionBubble:
pop af
ld [wUpdateSpritesEnabled], a
call DelayFrame
- jp UpdateSprites
+ call UpdateSprites
+ ret
-EmotionBubblesPointerTable:
-; entries correspond to *_BUBBLE constants
- dw ShockEmote
- dw QuestionEmote
- dw HappyEmote
EmotionBubblesOAM:
dbsprite 0, -1, 0, 0, $f9, 0
@@ -75,3 +74,8 @@ EmotionBubbles:
ShockEmote: INCBIN "gfx/emotes/shock.2bpp"
QuestionEmote: INCBIN "gfx/emotes/question.2bpp"
HappyEmote: INCBIN "gfx/emotes/happy.2bpp"
+SkullEmote: INCBIN "gfx/emotes/skull.2bpp"
+HeartEmote: INCBIN "gfx/emotes/heart.2bpp"
+BoltEmote: INCBIN "gfx/emotes/bolt.2bpp"
+ZzzEmote: INCBIN "gfx/emotes/zzz.2bpp"
+FishEmote: INCBIN "gfx/emotes/fish.2bpp"
diff --git a/engine/overworld/healing_machine.asm b/engine/overworld/healing_machine.asm
index 40ca6f65..e5fba7e1 100755
--- a/engine/overworld/healing_machine.asm
+++ b/engine/overworld/healing_machine.asm
@@ -12,14 +12,13 @@ AnimateHealingMachine:
push af
ld a, $e0
ldh [rOBP1], a
+ call UpdateGBCPal_OBP1
ld hl, wOAMBuffer + $84
ld de, PokeCenterOAMData
call CopyHealingMachineOAM
ld a, 4
ld [wAudioFadeOutControl], a
- ld a, SFX_STOP_ALL_MUSIC
- ld [wNewSoundID], a
- call PlaySound
+ call StopAllMusic
.waitLoop
ld a, [wAudioFadeOutControl]
and a ; is fade-out finished?
@@ -35,12 +34,10 @@ AnimateHealingMachine:
dec b
jr nz, .partyLoop
ld a, [wAudioROMBank]
- cp BANK(Audio3_UpdateMusic)
+ cp BANK(AudioEngine3)
ld [wAudioSavedROMBank], a
jr nz, .next
- ld a, SFX_STOP_ALL_MUSIC
- ld [wNewSoundID], a
- call PlaySound
+ call StopAllMusic
ld a, BANK(Music_PkmnHealed)
ld [wAudioROMBank], a
.next
@@ -57,6 +54,7 @@ AnimateHealingMachine:
call DelayFrames
pop af
ldh [rOBP1], a
+ call UpdateGBCPal_OBP1
pop hl
pop af
ld [hl], a
@@ -67,14 +65,14 @@ PokeCenterFlashingMonitorAndHealBall:
PokeCenterOAMData:
; heal machine monitor
- dbsprite 6, 4, 4, 4, $7c, OAM_OBP1
+ dbsprite 6, 4, 4, 4, $7c, OAM_OBP1 | %100
; poke balls 1-6
- dbsprite 6, 5, 0, 3, $7d, OAM_OBP1
- dbsprite 7, 5, 0, 3, $7d, OAM_OBP1 | OAM_HFLIP
- dbsprite 6, 6, 0, 0, $7d, OAM_OBP1
- dbsprite 7, 6, 0, 0, $7d, OAM_OBP1 | OAM_HFLIP
- dbsprite 6, 6, 0, 5, $7d, OAM_OBP1
- dbsprite 7, 6, 0, 5, $7d, OAM_OBP1 | OAM_HFLIP
+ dbsprite 6, 5, 0, 3, $7d, OAM_OBP1 | %100
+ dbsprite 7, 5, 0, 3, $7d, OAM_OBP1 | OAM_HFLIP | %100
+ dbsprite 6, 6, 0, 0, $7d, OAM_OBP1 | %100
+ dbsprite 7, 6, 0, 0, $7d, OAM_OBP1 | OAM_HFLIP | %100
+ dbsprite 6, 6, 0, 5, $7d, OAM_OBP1 | %100
+ dbsprite 7, 6, 0, 5, $7d, OAM_OBP1 | OAM_HFLIP | %100
; d = value to xor with palette
FlashSprite8Times:
@@ -83,6 +81,7 @@ FlashSprite8Times:
ldh a, [rOBP1]
xor d
ldh [rOBP1], a
+ call UpdateGBCPal_OBP1
ld c, 10
call DelayFrames
dec b
diff --git a/engine/overworld/hidden_objects.asm b/engine/overworld/hidden_objects.asm
index 855328e7..84108986 100755
--- a/engine/overworld/hidden_objects.asm
+++ b/engine/overworld/hidden_objects.asm
@@ -1,19 +1,3 @@
-IsPlayerOnDungeonWarp::
- xor a
- ld [wWhichDungeonWarp], a
- ld a, [wd72d]
- bit 4, a
- ret nz
- call ArePlayerCoordsInArray
- ret nc
- ld a, [wCoordIndex]
- ld [wWhichDungeonWarp], a
- ld hl, wd72d
- set 4, [hl]
- ld hl, wd732
- set 4, [hl]
- ret
-
; if a hidden object was found, stores $00 in [hDidntFindAnyHiddenObject], else stores $ff
CheckForHiddenObject::
ld hl, hItemAlreadyFound
@@ -22,22 +6,12 @@ CheckForHiddenObject::
ld [hli], a ; [hSavedMapTextPtr]
ld [hli], a ; [hSavedMapTextPtr + 1]
ld [hl], a ; [hDidntFindAnyHiddenObject]
- ld de, $0
ld hl, HiddenObjectMaps
-.hiddenMapLoop
- ld a, [hli]
- ld b, a
- cp $ff
- jr z, .noMatch
+ ld de, 3
ld a, [wCurMap]
- cp b
- jr z, .foundMatchingMap
- inc de
- inc de
- jr .hiddenMapLoop
-.foundMatchingMap
- ld hl, HiddenObjectPointers
- add hl, de
+ call IsInArray
+ jr nc, .noMatch
+ inc hl
ld a, [hli]
ld h, [hl]
ld l, a
diff --git a/engine/overworld/ledges.asm b/engine/overworld/ledges.asm
index f01ae5ef..9925c528 100755
--- a/engine/overworld/ledges.asm
+++ b/engine/overworld/ledges.asm
@@ -61,10 +61,13 @@ LoadHoppingShadowOAM:
ld de, LedgeHoppingShadow
lb bc, BANK(LedgeHoppingShadow), (LedgeHoppingShadowEnd - LedgeHoppingShadow) / $8
call CopyVideoDataDouble
- ld a, $9
- lb bc, $54, $48 ; b, c = y, x coordinates of shadow
- ld de, LedgeHoppingShadowOAM
- call WriteOAMBlock
+ ld hl, LedgeHoppingShadowOAM
+ ld de, wOAMBuffer + 36 * 4
+ ld bc, LedgeHoppingShadowOAMEnd - LedgeHoppingShadowOAM
+ call CopyData
+ ld a, $a0
+ ld [wOAMBuffer + 38 * 4], a
+ ld [wOAMBuffer + 39 * 4], a
ret
LedgeHoppingShadow:
@@ -72,5 +75,6 @@ LedgeHoppingShadow:
LedgeHoppingShadowEnd:
LedgeHoppingShadowOAM:
- dbsprite 2, -1, 0, 7, $ff, OAM_HFLIP
- dbsprite 8, -1, 0, 7, $ff, OAM_HFLIP | OAM_VFLIP
+ dbsprite 9, 11, 0, 0, $ff, 0
+ dbsprite 10, 11, 0, 0, $ff, OAM_HFLIP
+LedgeHoppingShadowOAMEnd:
diff --git a/engine/overworld/map_sprites.asm b/engine/overworld/map_sprites.asm
index fa3a37dc..e31c0bd2 100755
--- a/engine/overworld/map_sprites.asm
+++ b/engine/overworld/map_sprites.asm
@@ -4,251 +4,17 @@
; This is also called after displaying text because loading
; text tile patterns overwrites half of the sprite tile pattern data.
; Note on notation:
-; x#SPRITESTATEDATA1_* and x#SPRITESTATEDATA2_* are used to denote wSpriteStateData1 and
-; wSpriteStateData2 sprite slot, respectively, within loops. The X is the loop index.
-; If there is an inner loop, Y is the inner loop index, i.e. y#SPRITESTATEDATA1_* and
-; y#SPRITESTATEDATA2_* denote fields of the sprite slots iterated over in the inner loop.
-InitMapSprites::
+; $C1X* and $C2X* are used to denote wSpriteStateData1-wSpriteStateData1 + $ff and wSpriteStateData2 + $00-wSpriteStateData2 + $ff sprite slot
+; fields, respectively, within loops. The X is the loop index.
+; If there is an inner loop, Y is the inner loop index, i.e. $C1Y* and $C2Y*
+; denote fields of the sprite slots iterated over in the inner loop.
+_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)
- ld hl, wSpritePlayerStateData1PictureID
- ld de, wSpritePlayerStateData2PictureID
-; Loop to copy picture IDs from [x#SPRITESTATEDATA1_PICTUREID]
-; to [x#SPRITESTATEDATA2_PICTUREID] for LoadMapSpriteTilePatterns.
-.copyPictureIDLoop
- ld a, [hl] ; a = [x#SPRITESTATEDATA1_PICTUREID]
- ld [de], a ; [x#SPRITESTATEDATA2_PICTUREID] = a
- ld a, $10
- add e
- ld e, a
- ld a, $10
- add l
- ld l, a
- jr nz, .copyPictureIDLoop
-
-; This is used for both inside and outside maps, since it is called by
-; InitOutsideMapSprites.
-; Loads tile pattern data for sprites into VRAM.
-LoadMapSpriteTilePatterns:
- ld a, [wNumSprites]
- and a ; are there any sprites?
- jr nz, .spritesExist
- ret
-.spritesExist
- ld c, a ; c = [wNumSprites]
- ld b, $10 ; number of sprite slots
- ld hl, wSpritePlayerStateData2PictureID
- xor a
- ldh [hFourTileSpriteCount], a
-; Loop to copy picture IDs from [x#SPRITESTATEDATA2_PICTUREID]
-; to [x#SPRITESTATEDATA2_IMAGEBASEOFFSET].
-.copyPictureIDLoop
- ld a, [hli] ; a = [x#SPRITESTATEDATA2_PICTUREID]
- ld [hld], a ; [x#SPRITESTATEDATA2_IMAGEBASEOFFSET] = a
- ld a, l
- add $10
- ld l, a
- dec b
- jr nz, .copyPictureIDLoop
- ld hl, wSprite01StateData2ImageBaseOffset
-.loadTilePatternLoop
- ld de, wSprite01StateData2PictureID
-; Check if the current picture ID has already had its tile patterns loaded.
-; This done by looping through the previous sprite slots and seeing if any of
-; their picture ID's match that of the current sprite slot.
-.checkIfAlreadyLoadedLoop
- ld a, e
- and $f0
- ld b, a ; b = offset of the wSpriteStateData2 sprite slot being checked against
- ld a, l
- and $f0 ; a = offset of current wSpriteStateData2 sprite slot
- cp b ; done checking all previous sprite slots?
- jr z, .notAlreadyLoaded
- ld a, [de] ; picture ID of the wSpriteStateData2 sprite slot being checked against
- cp [hl] ; do the picture ID's match?
- jp z, .alreadyLoaded
- ld a, e
- add $10
- ld e, a
- jr .checkIfAlreadyLoadedLoop
-.notAlreadyLoaded
- ld de, wSpritePlayerStateData2ImageBaseOffset
- ld b, $01
-; loop to find the highest tile pattern VRAM slot (among the first 10 slots) used by a previous sprite slot
-; this is done in order to find the first free VRAM slot available
-.findNextVRAMSlotLoop
- ld a, e
- add $10
- ld e, a
- ld a, l
- cp e ; reached current slot?
- jr z, .foundNextVRAMSlot
- ld a, [de] ; y#SPRITESTATEDATA2_IMAGEBASEOFFSET
- cp 11 ; is it one of the first 10 slots?
- jr nc, .findNextVRAMSlotLoop
- cp b ; compare the slot being checked to the current max
- jr c, .findNextVRAMSlotLoop ; if the slot being checked is less than the current max
-; if the slot being checked is greater than or equal to the current max
- ld b, a ; store new max VRAM slot
- jr .findNextVRAMSlotLoop
-.foundNextVRAMSlot
- inc b ; increment previous max value to get next VRAM tile pattern slot
- ld a, b ; a = next VRAM tile pattern slot
- push af
- ld a, [hl] ; [x#SPRITESTATEDATA2_IMAGEBASEOFFSET]
- ld b, a ; b = current sprite picture ID
- cp FIRST_STILL_SPRITE ; is it a 4-tile sprite?
- jr c, .notFourTileSprite
- pop af
- ldh a, [hFourTileSpriteCount]
- add 11
- jr .storeVRAMSlot
-.notFourTileSprite
- pop af
-.storeVRAMSlot
- ld [hl], a ; store VRAM slot at [x#SPRITESTATEDATA2_IMAGEBASEOFFSET]
- ldh [hVRAMSlot], a ; used to determine if it's 4-tile sprite later
- ld a, b ; a = current sprite picture ID
- dec a
- add a
- add a
- push bc
- push hl
- ld hl, SpriteSheetPointerTable
- jr nc, .noCarry
- inc h
-.noCarry
- add l
- ld l, a
- jr nc, .noCarry2
- inc h
-.noCarry2
- push hl
- call ReadSpriteSheetData
- push af
- push de
- push bc
- ld hl, vNPCSprites ; VRAM base address
- ld bc, 12 tiles ; number of bytes per VRAM slot
- ldh a, [hVRAMSlot]
- cp 11 ; is it a 4-tile sprite?
- jr nc, .fourTileSpriteVRAMAddr
- ld d, a
- dec d
-; hl = vSprites + [hVRAMSlot] * 12 tiles
-.calculateVRAMAddrLoop
- add hl, bc
- dec d
- jr nz, .calculateVRAMAddrLoop
- jr .loadStillTilePattern
-.fourTileSpriteVRAMAddr
- ld hl, vSprites tile $7c ; address for second 4-tile sprite
- ldh a, [hFourTileSpriteCount]
- and a
- jr nz, .loadStillTilePattern
-; if it's the first 4-tile sprite
- ld hl, vSprites tile $78 ; address for first 4-tile sprite
- inc a
- ldh [hFourTileSpriteCount], a
-.loadStillTilePattern
- pop bc
- pop de
- pop af
- push hl
- push hl
- ld h, d
- ld l, e
- pop de
- ld b, a
- ld a, [wFontLoaded]
- bit 0, a ; reloading upper half of tile patterns after displaying text?
- jr nz, .skipFirstLoad ; if so, skip loading data into the lower half
- ld a, b
- ld b, 0
- call FarCopyData2 ; load tile pattern data for sprite when standing still
-.skipFirstLoad
- pop de
- pop hl
- ldh a, [hVRAMSlot]
- cp 11 ; is it a 4-tile sprite?
- jr nc, .skipSecondLoad ; if so, there is no second block
- push de
- call ReadSpriteSheetData
- push af
- ld a, $c0
- add e
- ld e, a
- jr nc, .noCarry3
- inc d
-.noCarry3
- ld a, [wFontLoaded]
- bit 0, a ; reloading upper half of tile patterns after displaying text?
- jr nz, .loadWhileLCDOn
- pop af
- pop hl
- set 3, h ; add $800 to hl
- push hl
- ld h, d
- ld l, e
- pop de
- call FarCopyData2 ; load tile pattern data for sprite when walking
- jr .skipSecondLoad
-; When reloading the upper half of tile patterns after displaying text, the LCD
-; will be on, so CopyVideoData (which writes to VRAM only during V-blank) must
-; be used instead of FarCopyData2.
-.loadWhileLCDOn
- pop af
- pop hl
- set 3, h ; add $800 to hl
- ld b, a
- swap c
- call CopyVideoData ; load tile pattern data for sprite when walking
-.skipSecondLoad
- pop hl
- pop bc
- jr .nextSpriteSlot
-.alreadyLoaded ; if the current picture ID has already had its tile patterns loaded
- inc de
- ld a, [de] ; a = [y#SPRITESTATEDATA2_IMAGEBASEOFFSET]
- ld [hl], a ; [x#SPRITESTATEDATA2_IMAGEBASEOFFSET] = a
-.nextSpriteSlot
- ld a, l
- add $10
- ld l, a
- dec c
- jp nz, .loadTilePatternLoop
- ld hl, wSpritePlayerStateData2PictureID
- ld b, $10
-; the pictures IDs stored at [x#SPRITESTATEDATA2_PICTUREID] are no longer needed,
-; so zero them
-.zeroStoredPictureIDLoop
- xor a
- ld [hl], a ; [x#SPRITESTATEDATA2_PICTUREID]
- ld a, $10
- add l
- ld l, a
- dec b
- jr nz, .zeroStoredPictureIDLoop
- ret
-
-; reads data from SpriteSheetPointerTable
-; INPUT:
-; hl = address of sprite sheet entry
-; OUTPUT:
-; de = pointer to sprite sheet
-; bc = length in bytes
-; a = ROM bank
-ReadSpriteSheetData:
- ld a, [hli]
- ld e, a
- ld a, [hli]
- ld d, a
- ld a, [hli]
- ld c, a
- xor a
- ld b, a
- ld a, [hli]
+ call LoadSpriteSetFromMapHeader
+ call LoadMapSpriteTilePatterns
+ call Func_14150
ret
; Loads sprite set for outside maps (cities and routes) and sets VRAM slots.
@@ -257,15 +23,8 @@ InitOutsideMapSprites:
ld a, [wCurMap]
cp FIRST_INDOOR_MAP ; is the map a city or a route?
ret nc ; if not, return
- ld hl, MapSpriteSets
- add l
- ld l, a
- jr nc, .noCarry
- inc h
-.noCarry
- ld a, [hl] ; a = spriteSetID
- cp $f0 ; does the map have 2 sprite sets?
- call nc, GetSplitMapSpriteSetID ; if so, choose the appropriate one
+ call GetSplitMapSpriteSetID
+; if so, choose the appropriate one
ld b, a ; b = spriteSetID
ld a, [wFontLoaded]
bit 0, a ; reloading upper half of tile patterns after displaying text?
@@ -277,120 +36,285 @@ InitOutsideMapSprites:
ld a, b
ld [wSpriteSetID], a
dec a
- ld b, a
- sla a
ld c, a
- sla a
- sla a
- add c
- add b ; a = (spriteSetID - 1) * 11
- ld de, SpriteSets
-; add a to de to get offset of sprite set
- add e
- ld e, a
- jr nc, .noCarry2
- inc d
-.noCarry2
- ld hl, wSpritePlayerStateData2PictureID
- ld a, SPRITE_RED
- ld [hl], a
- ld bc, wSpriteSet
-; Load the sprite set into RAM.
-; This loop also fills [x#SPRITESTATEDATA2_PICTUREID] where X is from $0 to $A
-; with picture IDs. This is done so that LoadMapSpriteTilePatterns will
-; load tile patterns for all sprite pictures in the sprite set.
-.loadSpriteSetLoop
- ld a, $10
- add l
- ld l, a
- ld a, [de] ; sprite picture ID from sprite set
- ld [hl], a ; [x#SPRITESTATEDATA2_PICTUREID]
- ld [bc], a
- inc de
- inc bc
- ld a, l
- cp $bd ; reached 11th sprite slot?
- jr nz, .loadSpriteSetLoop
- ld b, 4 ; 4 remaining sprite slots
-.zeroRemainingSlotsLoop ; loop to zero the picture ID's of the remaining sprite slots
- ld a, $10
- add l
- ld l, a
- xor a
- ld [hl], a ; [x#SPRITESTATEDATA2_PICTUREID]
- dec b
- jr nz, .zeroRemainingSlotsLoop
- ld a, [wNumSprites]
- push af ; save number of sprites
- ld a, 11 ; 11 sprites in sprite set
- ld [wNumSprites], a
+ ld b, 0
+ ld a, (wSpriteSetID - wSpriteSet)
+ ld hl, SpriteSets
+ call AddNTimes ; get sprite set offset
+ ld de, wSpriteSet
+ ld bc, (wSpriteSetID - wSpriteSet)
+ call CopyData ; copy it to wSpriteSet
call LoadMapSpriteTilePatterns
- pop af
- ld [wNumSprites], a ; restore number of sprites
- ld hl, wSprite01StateData2ImageBaseOffset
- ld b, $0f
-; The VRAM tile pattern slots that LoadMapSpriteTilePatterns set are in the
-; order of the map's sprite set, not the order of the actual sprites loaded
-; for the current map. So, they are not needed and are zeroed by this loop.
-.zeroVRAMSlotsLoop
- xor a
- ld [hl], a ; [x#SPRITESTATEDATA2_IMAGEBASEOFFSET]
- ld a, $10
- add l
- ld l, a
- dec b
- jr nz, .zeroVRAMSlotsLoop
.skipLoadingSpriteSet
- ld hl, wSprite01StateData1
+ call Func_14150
+ scf
+ ret
+
+LoadSpriteSetFromMapHeader:
; This loop stores the correct VRAM tile pattern slots according the sprite
; data from the map's header. Since the VRAM tile pattern slots are filled in
; the order of the sprite set, in order to find the VRAM tile pattern slot
; for a sprite slot, the picture ID for the sprite is looked up within the
-; sprite set. The index of the picture ID within the sprite set plus one
-; (since the Red sprite always has the first VRAM tile pattern slot) is the
-; VRAM tile pattern slot.
+; sprite set. The index of the picture ID within the sprite set plus two
+; (since the Red sprite always has the first VRAM tile pattern slot and the
+; Pikachu sprite reserves the second slot) is the VRAM tile pattern slot.
+ ld hl, wSpriteSet
+ ld bc, (wSpriteSetID - wSpriteSet)
+ xor a
+ call FillMemory
+ ld a, SPRITE_PIKACHU ; load Pikachu separately
+ ld [wSpriteSet], a
+ ld hl, wSprite01StateData1
+ ld a, 14
.storeVRAMSlotsLoop
- ld c, 0
+ push af
ld a, [hl] ; [x#SPRITESTATEDATA1_PICTUREID] (zero if sprite slot is not used)
and a ; is the sprite slot used?
- jr z, .skipGettingPictureIndex ; if the sprite slot is not used
- ld b, a ; b = picture ID
+ jr z, .continue ; if the sprite slot is not used
+ ld c, a
+ call CheckForFourTileSprite ; is this a four tile sprite?
+ jr nc, .isFourTileSprite
+; loop through the space reserved for four tile picture IDs
+ ld de, wSpriteSet + 9
+ ld b, 2
+ call CheckIfPictureIDAlreadyLoaded
+ jr .continue
+
+.isFourTileSprite
+; loop through the space reserved for regular picture IDs
ld de, wSpriteSet
-; Loop to find the index of the sprite's picture ID within the sprite set.
-.getPictureIndexLoop
- inc c
+ ld b, 9
+ call CheckIfPictureIDAlreadyLoaded
+.continue
+ ld de, wSprite02StateData1 - wSprite01StateData1
+ add hl, de
+ pop af
+ dec a
+ jr nz, .storeVRAMSlotsLoop
+ ret
+
+CheckIfPictureIDAlreadyLoaded:
+; Check if the current picture ID has already had its tile patterns loaded.
+; This done by looping through the previous sprite slots and seeing if any of
+; their picture ID's match that of the current sprite slot.
+.loop
ld a, [de]
+ and a ; is sprite set slot not taken up yet?
+ jr z, .spriteSlotNotTaken ; if so, load it as it signifies we've reached
+ ; the end of data for the last sprite set
+
+ cp c ; is the tile pattern already loaded?
+ ret z ; don't redundantly load
+ dec b ; have we reached the end of the sprite set?
+ jr z, .spriteNotAlreadyLoaded ; if so, we're done here
inc de
- cp b ; does the picture ID match?
- jr nz, .getPictureIndexLoop
- inc c
-.skipGettingPictureIndex
- push hl
- inc h
- ld a, $0e
- add l
- ld l, a
- ld a, c ; a = VRAM slot (zero if sprite slot is not used)
- ld [hl], a ; [x#SPRITESTATEDATA2_IMAGEBASEOFFSET]
- pop hl
- ld a, $10
- add l
+ jr .loop
+
+.spriteSlotNotTaken
+ ld a, c
+ ld [de], a
+ ret
+.spriteNotAlreadyLoaded
+ scf
+ ret
+
+CheckForFourTileSprite:
+; Checks for a sprite added in yellow
+; Returns no carry if the sprite is Pikachu, as its sprite is handled separately
+; Else, returns carry if the sprite uses 4 tiles
+ cp SPRITE_PIKACHU ; is this the Pikachu Sprite?
+ ret z ; return if yes
+
+ cp FIRST_STILL_SPRITE ; is this a four tile sprite?
+ jr nc, .notYellowSprite ; set carry if yes
+; regular sprite
+ and a
+ ret
+
+.notYellowSprite
+ scf
+ ret
+
+LoadMapSpriteTilePatterns:
+ ld a, 0
+.loop
+ ldh [hVRAMSlot], a
+ cp 9
+ jr nc, .fourTileSprite
+ call LoadStillTilePattern
+ call LoadWalkingTilePattern
+ jr .continue
+
+.fourTileSprite
+ call LoadStillTilePattern
+.continue
+ ldh a, [hVRAMSlot]
+ inc a
+ cp 11
+ jr nz, .loop
+ ret
+
+ReloadWalkingTilePatterns:
+ xor a
+.loop
+ ldh [hVRAMSlot], a
+ cp 9
+ jr nc, .fourTileSprite
+ call LoadWalkingTilePattern
+.fourTileSprite
+ ldh a, [hVRAMSlot]
+ inc a
+ cp 11
+ jr nz, .loop
+ ret
+
+LoadStillTilePattern:
+ ld a, [wFontLoaded]
+ bit 0, a ; reloading upper half of tile patterns after displaying text?
+ ret nz ; if so, skip loading data into the lower half
+ call ReadSpriteSheetData
+ ret nc
+ call GetSpriteVRAMAddress
+ call CopyVideoDataAlternate ; new yellow function
+ ret
+
+LoadWalkingTilePattern:
+ call ReadSpriteSheetData
+ ret nc
+ ld hl, $c0
+ add hl, de
+ ld d, h
+ ld e, l
+ call GetSpriteVRAMAddress
+ set 3, h ; add $800 to hl
+ call CopyVideoDataAlternate
+ ret
+
+GetSpriteVRAMAddress:
+ push bc
+ ldh a, [hVRAMSlot]
+ ld c, a
+ ld b, 0
+ ld hl, SpriteVRAMAddresses
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
ld l, a
+ pop bc
+ ret
+
+SpriteVRAMAddresses:
+; Equivalent to multiplying $C0 (number of bytes in 12 tiles) times the VRAM
+; slot and adding the result to $8000 (the VRAM base address).
+ dw vChars0 + $0c0
+ dw vChars0 + $180
+ dw vChars0 + $240
+ dw vChars0 + $300
+ dw vChars0 + $3c0
+ dw vChars0 + $480
+ dw vChars0 + $540
+ dw vChars0 + $600
+ dw vChars0 + $6c0
+ dw vChars0 + $780 ; 4-tile sprites
+ dw vChars0 + $7c0 ; 4-tile sprites
+
+ReadSpriteSheetData:
+ ldh a, [hVRAMSlot]
+ ld e, a
+ ld d, 0
+ ld hl, wSpriteSet
+ add hl, de
+ ld a, [hl]
and a
- jr nz, .storeVRAMSlotsLoop
+ ret z
+
+ dec a
+ ld l, a
+ ld h, 0
+ add hl, hl
+ add hl, hl
+ ld de, SpriteSheetPointerTable
+ add hl, de
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ inc hl
+ ld c, [hl]
+ swap c ; get the number of tiles, not the raw byte length
+ ; this is because of the use of CopyVideoDataAlternate
+ inc hl
+ ld b, [hl]
+ inc hl
scf
ret
+Func_14150:
+ ld a, $1
+ ld [wSpritePlayerStateData2ImageBaseOffset], a ; vram slot for player
+ ld a, $2
+ ld [wSpritePikachuStateData2ImageBaseOffset], a ; vram slot for Pikachu
+ ld a, $e
+ ld hl, wSprite01StateData1
+.loop
+ ldh [hVRAMSlot], a ; store current sprite set slot as a counter
+ ld a, [hl] ; [x#SPRITESTATEDATA1_PICTUREID]
+ and a ; is the sprite unused?
+ jr z, .spriteUnused
+ call Func_14179
+ push hl
+ ld de, (wSpritePlayerStateData2ImageBaseOffset) - (wSpriteStateData1) ; $10e
+ add hl, de ; [x#SPRITESTATEDATA2_IMAGEBASEOFFSET]
+ ld [hl], a ; write offset
+ pop hl
+.spriteUnused
+ ld de, wSprite02StateData1 - wSprite01StateData1
+ add hl, de
+ ldh a, [hVRAMSlot]
+ dec a
+ jr nz, .loop
+ ret
+
+Func_14179:
+ push de
+ push bc
+ ld c, a ; c = picture ID
+ ld b, 11
+ ld de, wSpriteSet
+.findSpriteImageBaseOffsetLoop
+ ld a, [de] ; a = sprite set picture ID
+ cp c ; have we found a match?
+ jr z, .foundSpritePictureID ; if so, get the sprite image base offset and return
+ inc de
+ dec b ; have we looped through all entries in wSpriteSet?
+ jr nz, .findSpriteImageBaseOffsetLoop ; continue looping if not
+ ld a, $1 ; assume slot one if this ever happens
+ jr .done
+.foundSpritePictureID
+ ld a, 13
+ sub b ; get sprite image base offset
+.done
+ pop bc
+ pop de
+ ret
+
+GetSplitMapSpriteSetID:
+ ld e, a
+ ld d, 0
+ ld hl, MapSpriteSets
+ add hl, de
+ ld a, [hl] ; a = spriteSetID
+ cp a, $f0 ; does the map have 2 sprite sets?
+ ret c
; Chooses the correct sprite set ID depending on the player's position within
; the map for maps with two sprite sets.
-GetSplitMapSpriteSetID:
cp $f8
jr z, .route20
ld hl, SplitMapSpriteSets
and $0f
dec a
- sla a
- sla a
+ add a
+ add a
add l
ld l, a
jr nc, .noCarry
diff --git a/engine/overworld/missable_objects.asm b/engine/overworld/missable_objects.asm
index 31fdc257..358a9b9f 100644
--- a/engine/overworld/missable_objects.asm
+++ b/engine/overworld/missable_objects.asm
@@ -17,18 +17,15 @@ MarkTownVisitedAndLoadMissableObjects::
ld h, [hl]
; fall through
-LoadMissableObjects:
+; LoadMissableObjects:
+; seems to not exist in yellow (predef replaced with something near TryPushingBoulder)
ld l, a
push hl
- ld de, MissableObjects ; calculate difference between out pointer and the base pointer
ld a, l
- sub e
- jr nc, .asm_f13c
- dec h
-.asm_f13c
+ sub MissableObjects & $ff ; calculate difference between out pointer and the base pointer
ld l, a
ld a, h
- sub d
+ sbc MissableObjects / $100
ld h, a
ld a, h
ldh [hDividend], a
diff --git a/engine/overworld/movement.asm b/engine/overworld/movement.asm
index 2fb8c384..dadf2194 100644
--- a/engine/overworld/movement.asm
+++ b/engine/overworld/movement.asm
@@ -22,7 +22,13 @@ UpdatePlayerSprite:
ld [wSpritePlayerStateData1ImageIndex], a
ret
.lowerLeftTileIsMapTile
+ ld a, [wUpdateSpritesEnabled]
+ push af
+ ld a, $ff
+ ld [wUpdateSpritesEnabled], a
call DetectCollisionBetweenSprites
+ pop af
+ ld [wUpdateSpritesEnabled], a
ld h, HIGH(wSpriteStateData1)
ld a, [wWalkCounter]
and a
@@ -48,42 +54,24 @@ UpdatePlayerSprite:
jr z, .notMoving
ld a, SPRITE_FACING_RIGHT
jr .next
+.next
+ ld [wSpritePlayerStateData1FacingDirection], a ; facing direction
+ ld a, [wFontLoaded]
+ bit 0, a
+ jr z, .moving
.notMoving
; zero the animation counters
xor a
ld [wSpritePlayerStateData1IntraAnimFrameCounter], a
ld [wSpritePlayerStateData1AnimFrameCounter], a
- jr .calcImageIndex
-.next
- ld [wSpritePlayerStateData1FacingDirection], a
- ld a, [wFontLoaded]
- bit 0, a
- jr nz, .notMoving
+ call Func_4e32
+ jr .skipSpriteAnim
.moving
ld a, [wd736]
bit 7, a ; is the player sprite spinning due to a spin tile?
jr nz, .skipSpriteAnim
- ldh a, [hCurrentSpriteOffset]
- add $7
- ld l, a
- ld a, [hl]
- inc a
- ld [hl], a
- cp 4
- jr nz, .calcImageIndex
- xor a
- ld [hl], a
- inc hl
- ld a, [hl]
- inc a
- and $3
- ld [hl], a
-.calcImageIndex
- ld a, [wSpritePlayerStateData1AnimFrameCounter]
- ld b, a
- ld a, [wSpritePlayerStateData1FacingDirection]
- add b
- ld [wSpritePlayerStateData1ImageIndex], a
+ call Func_5274
+ call Func_4e32
.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
@@ -100,15 +88,12 @@ UpdatePlayerSprite:
ld [wSpritePlayerStateData2GrassPriority], a
ret
-UnusedReadSpriteDataFunction:
- push bc
- push af
- ldh a, [hCurrentSpriteOffset]
- ld c, a
- pop af
- add c
- ld l, a
- pop bc
+Func_4e32:
+ ld a, [wSpritePlayerStateData1AnimFrameCounter]
+ ld b, a
+ ld a, [wSpritePlayerStateData1FacingDirection]
+ add b
+ ld [wSpritePlayerStateData1ImageIndex], a
ret
UpdateNPCSprite:
@@ -146,6 +131,8 @@ UpdateNPCSprite:
jp z, UpdateSpriteMovementDelay ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] == 2
cp $3
jp z, UpdateSpriteInWalkingAnimation ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] == 3
+ cp $4
+ jp z, Func_5357
ld a, [wWalkCounter]
and a
ret nz ; don't do anything yet if player is currently moving (redundant, already tested in CheckSpriteAvailability)
@@ -156,9 +143,9 @@ UpdateNPCSprite:
ld l, a
ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1
inc a
- jr z, .randomMovement ; value STAY
+ jp z, .randomMovement ; value STAY
inc a
- jr z, .randomMovement ; value WALK
+ jp z, .randomMovement ; value WALK
; scripted movement
dec a
ld [hl], a ; increment movement byte 1 (movement data index)
@@ -183,12 +170,18 @@ UpdateNPCSprite:
ret
.next
cp WALK
- jr nz, .determineDirection
+ jr nz, .asm_4ecb
; current NPC movement data is WALK ($fe). this seems buggy
ld [hl], $1 ; set movement byte 1 to $1
ld de, wNPCMovementDirections
call LoadDEPlusA ; a = [wNPCMovementDirections + $fe] (?)
- jr .determineDirection
+.asm_4ecb
+ push af
+ call Func_5288
+ pop bc
+ ld a, b
+ jr nc, .determineDirection
+ ret
.randomMovement
call GetTileSpriteStandsOn
call Random
@@ -263,34 +256,14 @@ ChangeFacingDirection:
; set carry on failure, clears carry on success
TryWalking:
push hl
- ld h, HIGH(wSpriteStateData1)
- ldh a, [hCurrentSpriteOffset]
- add $9
- ld l, a
- ld [hl], c ; x#SPRITESTATEDATA1_FACINGDIRECTION
- ldh a, [hCurrentSpriteOffset]
- add $3
- ld l, a
- ld [hl], d ; x#SPRITESTATEDATA1_YSTEPVECTOR
- inc l
- inc l
- ld [hl], e ; x#SPRITESTATEDATA1_XSTEPVECTOR
+ call Func_5337
pop hl
push de
- ld c, [hl] ; read tile to walk onto
+ ld c, [hl]
call CanWalkOntoTile
pop de
ret c ; cannot walk there (reinitialization of delay values already done)
- ld h, HIGH(wSpriteStateData2)
- ldh a, [hCurrentSpriteOffset]
- add $4
- ld l, a
- ld a, [hl] ; x#SPRITESTATEDATA2_MAPY
- add d
- ld [hli], a ; update Y position
- ld a, [hl] ; x#SPRITESTATEDATA2_MAPX
- add e
- ld [hl], a ; update X position
+ call Func_5349
ldh a, [hCurrentSpriteOffset]
ld l, a
ld [hl], $10 ; [x#SPRITESTATEDATA2_WALKANIMATIONCOUNTER] = 16
@@ -301,22 +274,7 @@ TryWalking:
; update the walking animation parameters for a sprite that is currently walking
UpdateSpriteInWalkingAnimation:
- ldh a, [hCurrentSpriteOffset]
- add $7
- ld l, a
- ld a, [hl] ; x#SPRITESTATEDATA1_INTRAANIMFRAMECOUNTER
- inc a
- ld [hl], a ; [x#SPRITESTATEDATA1_INTRAANIMFRAMECOUNTER]++
- cp $4
- jr nz, .noNextAnimationFrame
- xor a
- ld [hl], a ; [x#SPRITESTATEDATA1_INTRAANIMFRAMECOUNTER] = 0
- inc l
- ld a, [hl] ; x#SPRITESTATEDATA1_ANIMFRAMECOUNTER
- inc a
- and $3
- ld [hl], a ; advance to next animation frame every 4 ticks (16 ticks total for one step)
-.noNextAnimationFrame
+ call Func_5274
ldh a, [hCurrentSpriteOffset]
add $3
ld l, a
@@ -448,6 +406,7 @@ InitializeSpriteStatus:
ld a, $8
ld [hli], a ; [x#SPRITESTATEDATA2_YDISPLACEMENT] = 8
ld [hl], a ; [x#SPRITESTATEDATA2_XDISPLACEMENT] = 8
+ call InitializeSpriteScreenPosition ; could have done fallthrough here
ret
; calculates the sprite's screen position from its map position and the player position
@@ -460,7 +419,7 @@ InitializeSpriteScreenPosition:
ld b, a
ld a, [hl] ; x#SPRITESTATEDATA2_MAPY
sub b ; relative to player position
- swap a ; * 16
+ call Func_5033
sub $4 ; - 4
dec h
ld [hli], a ; [x#SPRITESTATEDATA1_YPIXELS]
@@ -469,11 +428,23 @@ InitializeSpriteScreenPosition:
ld b, a
ld a, [hli] ; x#SPRITESTATEDATA2_MAPX
sub b ; relative to player position
- swap a ; * 16
+ call Func_5033
dec h
ld [hl], a ; [x#SPRITESTATEDATA1_XPIXELS]
ret
+Func_5033:
+ jr nc, .asm_503c
+ cpl
+ inc a
+ swap a
+ cpl
+ inc a
+ ret
+.asm_503c
+ swap a
+ ret
+
; tests if sprite is off screen or otherwise unable to do anything
CheckSpriteAvailability:
predef IsObjectHidden
@@ -593,16 +564,8 @@ CanWalkOntoTile:
and a
ret
.notScripted
- ld a, [wTilesetCollisionPtr]
- ld l, a
- ld a, [wTilesetCollisionPtr+1]
- ld h, a
-.tilePassableLoop
- ld a, [hli]
- cp $ff
- jr z, .impassable
- cp c
- jr nz, .tilePassableLoop
+ call _IsTilePassable
+ jr c, .impassable
ld h, HIGH(wSpriteStateData2)
ldh a, [hCurrentSpriteOffset]
add $6
@@ -626,7 +589,13 @@ CanWalkOntoTile:
jr nc, .impassable ; don't walk off screen
push de
push bc
+ ld a, [wUpdateSpritesEnabled]
+ push af
+ ld a, $ff
+ ld [wUpdateSpritesEnabled], a
call DetectCollisionBetweenSprites
+ pop af
+ ld [wUpdateSpritesEnabled], a
pop bc
pop de
ld h, HIGH(wSpriteStateData1)
@@ -649,8 +618,9 @@ CanWalkOntoTile:
; stuck whenever they walked upwards 5 steps
; on the other hand, the amount a sprite can walk out to the
; right of bottom is not limited (until the counter overflows)
+ ; this was fixed in Yellow
cp $5
- jr c, .impassable ; if [x#SPRITESTATEDATA2_YDISPLACEMENT]+d < 5, don't go
+ ;jr c, .impassable ; if [x#SPRITESTATEDATA2_YDISPLACEMENT]+d < 5, don't go
jr .checkHorizontal
.upwards
sub $1
@@ -704,7 +674,7 @@ GetTileSpriteStandsOn:
ld l, a
ld a, [hli] ; x#SPRITESTATEDATA1_YPIXELS
add $4 ; align to 2*2 tile blocks (Y position is always off 4 pixels to the top)
- and $f0 ; in case object is currently moving
+ and $f8 ; in case object is currently moving (XXX why changed to $f8?)
srl a ; screen Y tile * 4
ld c, a
ld b, $0
@@ -870,20 +840,235 @@ AnimScriptedNPCMovement:
ret
AdvanceScriptedNPCAnimFrameCounter:
+ call Func_5274
+ ld h, HIGH(wSpriteStateData1)
ldh a, [hCurrentSpriteOffset]
- add $7
+ add $8
ld l, a
ld a, [hl] ; intra-animation frame counter
+ and $3
+ ldh [hSpriteAnimFrameCounter], a
+ ret
+
+Func_5274:
+ ldh a, [hCurrentSpriteOffset]
+ add $7
+ ld l, a
+ ld h, HIGH(wSpriteStateData1)
+ ld a, [hl] ; x#SPRITESTATEDATA1_INTRAANIMFRAMECOUNTER
inc a
- ld [hl], a
- cp 4
+ and $3
+ ld [hl], a ; [x#SPRITESTATEDATA1_INTRAANIMFRAMECOUNTER]++
ret nz
- xor a
- ld [hl], a ; reset intra-animation frame counter
inc l
- ld a, [hl] ; animation frame counter
+ ld a, [hl] ; x#SPRITESTATEDATA1_ANIMFRAMECOUNTER
inc a
and $3
+ ld [hl], a ; advance to next animation frame every 4 ticks (16 ticks total for one step)
+ ret
+
+Func_5288:
+; nice lookup table
+; a is supposedly [wNPCMovementDirections + $fe]
+ cp $5
+ jr z, .asm_52af
+ cp $4
+ jr z, .asm_52aa
+ cp $6
+ jr z, .asm_52b4
+ cp $7
+ jr z, .asm_52b9
+ cp $11
+ jr z, .asm_52c3
+ cp $12
+ jr z, .asm_52be
+ cp $13
+ jr z, .asm_52c8
+ cp $14
+ jr z, .asm_52cd
+ xor a
+ ret
+; set 1?
+.asm_52aa
+ call Func_531f
+ jr .asm_52e6
+.asm_52af
+ call Func_5325
+ jr .asm_52e6
+.asm_52b4
+ call Func_5331
+ jr .asm_52e6
+.asm_52b9
+ call Func_532b
+ jr .asm_52e6
+; set 2?
+.asm_52be
+ call Func_531f
+ jr .asm_52fa
+.asm_52c3
+ call Func_5325
+ jr .asm_52fa
+.asm_52c8
+ call Func_5331
+ jr .asm_52fa
+.asm_52cd
+ call Func_532b
+ jr .asm_52fa
+; set 3? (unused)
+.asm_52d2
+ call Func_531f
+ jr .asm_530b
+.asm_52d7
+ call Func_5325
+ jr .asm_530b
+.asm_52dc
+ call Func_5331
+ jr .asm_530b
+.asm_52e1
+ call Func_532b
+ jr .asm_530b
+
+.asm_52e6
+ call Func_5337
+ call Func_5349
+ ldh a, [hCurrentSpriteOffset]
+ ld l, a
+ ld [hl], $8
+ dec h
+ inc l
+ ld [hl], $4
+ call UpdateSpriteImage
+ scf
+ ret
+
+.asm_52fa
+ call Func_5337
+ ldh a, [hCurrentSpriteOffset]
+ ld l, a
+ ld [hl], $8
+ dec h
+ inc l
+ ld [hl], $3
+ call UpdateSpriteImage
+ scf
+ ret
+
+.asm_530b
+ call Func_5337
+ call Func_5349
+ ldh a, [hCurrentSpriteOffset]
+ ld l, a
+ ld [hl], $8
+ dec h
+ inc l
+ ld [hl], $3
+ call UpdateSpriteImage
+ scf
+ ret
+
+Func_531f:
+ lb de, 1, 0
+ ld c, SPRITE_FACING_DOWN
+ ret
+
+Func_5325:
+ lb de, -1, 0
+ ld c, SPRITE_FACING_UP
+ ret
+
+Func_532b:
+ lb de, 0, 1
+ ld c, SPRITE_FACING_RIGHT
+ ret
+
+Func_5331:
+ lb de, 0, -1
+ ld c, SPRITE_FACING_LEFT
+ ret
+
+Func_5337:
+ ldh a, [hCurrentSpriteOffset]
+ add $9
+ ld l, a
+ ld h, HIGH(wSpriteStateData1)
+ ld [hl], c ; x#SPRITESTATEDATA1_FACINGDIRECTION
+ ldh a, [hCurrentSpriteOffset]
+ add $3
+ ld l, a
+ ld [hl], d ; x#SPRITESTATEDATA1_YSTEPVECTOR
+ inc l
+ inc l
+ ld [hl], e ; x#SPRITESTATEDATA1_XSTEPVECTOR
+ ret
+
+Func_5349:
+ ld h, HIGH(wSpriteStateData2)
+ ldh a, [hCurrentSpriteOffset]
+ add $4
+ ld l, a
+ ld a, [hl] ; x#SPRITESTATEDATA2_MAPY
+ add d
+ ld [hli], a ; update Y position
+ ld a, [hl] ; x#SPRITESTATEDATA2_MAPX
+ add e
+ ld [hl], a ; update X position
+ ret
+
+Func_5357:
+ call Func_5274
+ ldh a, [hCurrentSpriteOffset]
+ add $3
+ ld l, a
+ ld h, HIGH(wSpriteStateData1)
+ ld a, [hli]
+ add a
+ ld b, a
+ ld a, [hl]
+ add b
+ ld [hli], a
+ ld a, [hli]
+ add a
+ ld b, a
+ ld a, [hl]
+ add b
+ ld [hl], a
+ ldh a, [hCurrentSpriteOffset]
+ ld l, a
+ ld h, HIGH(wSpriteStateData2)
+ dec [hl]
+ ret nz
+ ld a, $6
+ add l
+ ld l, a
+ ld a, [hl]
+ cp $fe
+ jr nc, .asm_5386
+ ldh a, [hCurrentSpriteOffset]
+ inc a
+ ld l, a
+ ld h, HIGH(wSpriteStateData1)
+ ld [hl], $1
+ ret
+.asm_5386
+ call Random
+ ldh a, [hCurrentSpriteOffset]
+ add $8
+ ld l, a
+ ld h, HIGH(wSpriteStateData2)
+ ldh a, [hRandomAdd]
+ and $7f
+ ld [hl], a
+ dec h
+ ldh a, [hCurrentSpriteOffset]
+ inc a
+ ld l, a
+ ld [hl], $2
+ inc l
+ inc l
+ xor a
+ ld b, [hl]
+ ld [hli], a
+ inc l
+ ld c, [hl]
ld [hl], a
- ldh [hSpriteAnimFrameCounter], a
ret
diff --git a/engine/overworld/npc_movement_2.asm b/engine/overworld/npc_movement_2.asm
new file mode 100755
index 00000000..2ced9da6
--- /dev/null
+++ b/engine/overworld/npc_movement_2.asm
@@ -0,0 +1,24 @@
+FreezeEnemyTrainerSprite::
+ ld a, [wCurMap]
+ cp POKEMON_TOWER_7F
+ ret z ; the Rockets on Pokemon Tower 7F leave after battling, so don't freeze them
+ ld hl, RivalIDs
+ ld a, [wEngagedTrainerClass]
+ ld b, a
+.loop
+ ld a, [hli]
+ cp -1
+ jr z, .notRival
+ cp b
+ ret z ; the rival leaves after battling, so don't freeze him
+ jr .loop
+.notRival
+ ld a, [wSpriteIndex]
+ ldh [hSpriteIndex], a
+ jp SetSpriteMovementBytesToFF
+
+RivalIDs:
+ db OPP_RIVAL1
+ db OPP_RIVAL2
+ db OPP_RIVAL3
+ db -1 ; end
diff --git a/engine/overworld/pathfinding.asm b/engine/overworld/pathfinding.asm
index 1925dbbc..a824d337 100644
--- a/engine/overworld/pathfinding.asm
+++ b/engine/overworld/pathfinding.asm
@@ -14,22 +14,22 @@ FindPathToPlayer:
call CalcDifference
ld d, a
and a
- jr nz, .asm_f8da
+ jr nz, .asm_f76a
ldh a, [hFindPathFlags]
set 0, a ; current end of path matches the player's Y coordinate
ldh [hFindPathFlags], a
-.asm_f8da
+.asm_f76a
ldh a, [hFindPathXProgress]
ld b, a
ldh a, [hNPCPlayerXDistance] ; X distance in steps
call CalcDifference
ld e, a
and a
- jr nz, .asm_f8ec
+ jr nz, .asm_f77c
ldh a, [hFindPathFlags]
set 1, a ; current end of path matches the player's X coordinate
ldh [hFindPathFlags], a
-.asm_f8ec
+.asm_f77c
ldh a, [hFindPathFlags]
cp $3 ; has the end of the path reached the player's position?
jr z, .done
diff --git a/engine/overworld/player_animations.asm b/engine/overworld/player_animations.asm
index c458a013..5056c0b2 100755
--- a/engine/overworld/player_animations.asm
+++ b/engine/overworld/player_animations.asm
@@ -13,8 +13,8 @@ EnterMapAnim::
call PlaySound
ld hl, wd732
bit 4, [hl] ; used dungeon warp?
- res 4, [hl]
pop hl
+ ;res 4, [hl]
jr nz, .dungeonWarpAnimation
call PlayerSpinWhileMovingDown
ld a, SFX_TELEPORT_ENTER_2
@@ -34,21 +34,22 @@ EnterMapAnim::
ld [hl], $ff ; wPlayerSpinInPlaceAnimSoundID
ld hl, wFacingDirectionList
call PlayerSpinInPlace
+ ld a, $1
+ ld [wPikachuSpawnState], a
.restoreDefaultMusic
call PlayDefaultMusic
.done
+ call Func_151d
jp RestoreFacingDirectionAndYScreenPos
.dungeonWarpAnimation
ld c, 50
call DelayFrames
call PlayerSpinWhileMovingDown
+ ld a, $0
+ ld [wPikachuSpawnState], a
jr .done
.flyAnimation
pop hl
- ld de, BirdSprite
- ld hl, vNPCSprites
- lb bc, BANK(BirdSprite), $0c
- call CopyVideoData
call LoadBirdSpriteGraphics
ld a, SFX_FLY
call PlaySound
@@ -61,6 +62,8 @@ EnterMapAnim::
ld de, FlyAnimationEnterScreenCoords
call DoFlyAnimation
call LoadPlayerSpriteGraphics
+ ld a, $1
+ ld [wPikachuSpawnState], a
jr .restoreDefaultMusic
FlyAnimationEnterScreenCoords:
@@ -90,7 +93,9 @@ PlayerSpinWhileMovingDown:
ld [hl], a ; wPlayerSpinWhileMovingUpOrDownAnimFrameDelay
jp PlayerSpinWhileMovingUpOrDown
+
_LeaveMapAnim::
+ call Func_1510
call InitFacingDirectionList
call IsPlayerStandingOnWarpPadOrHole
ld a, b
@@ -249,12 +254,14 @@ DoFlyAnimation:
LoadBirdSpriteGraphics:
ld de, BirdSprite
+ ld b, BANK(BirdSprite)
+ ld c, $c
ld hl, vNPCSprites
- lb bc, BANK(BirdSprite), 12
call CopyVideoData
ld de, BirdSprite tile 12 ; moving animation sprite
+ ld b, BANK(BirdSprite)
+ ld c, 12
ld hl, vNPCSprites2
- lb bc, BANK(BirdSprite), 12
jp CopyVideoData
InitFacingDirectionList:
@@ -380,9 +387,10 @@ FishingAnim:
call DelayFrames
ld hl, wd736
set 6, [hl] ; reserve the last 4 OAM entries
+ ld hl, vNPCSprites
ld de, RedSprite
- ld hl, vNPCSprites tile $00
- lb bc, BANK(RedSprite), 12
+ ld b, BANK(RedSprite)
+ ld c, 12
call CopyVideoData
ld a, $4
ld hl, RedFishingTiles
diff --git a/engine/overworld/player_state.asm b/engine/overworld/player_state.asm
index 70326754..c966c128 100644
--- a/engine/overworld/player_state.asm
+++ b/engine/overworld/player_state.asm
@@ -70,7 +70,8 @@ CheckForceBikeOrSurf::
ld a, $1
ld [wWalkBikeSurfState], a
ld [wWalkBikeSurfStateCopy], a
- jp ForceBikeOrSurf
+ call ForceBikeOrSurf
+ ret
.incorrectMap
inc hl
.incorrectY
@@ -80,7 +81,8 @@ CheckForceBikeOrSurf::
ld a, $2
ld [wWalkBikeSurfState], a
ld [wWalkBikeSurfStateCopy], a
- jp ForceBikeOrSurf
+ call ForceBikeOrSurf
+ ret
INCLUDE "data/maps/force_bike_surf.asm"
@@ -101,10 +103,10 @@ IsPlayerFacingEdgeOfMap::
ld b, a
ld a, [wXCoord]
ld c, a
- ld de, .asm_c41e
+ ld de, .returnaddress
push de
jp hl
-.asm_c41e
+.returnaddress
pop bc
pop de
pop hl
@@ -224,8 +226,7 @@ PrintSafariZoneSteps::
cp CERULEAN_CAVE_2F
ret nc
hlcoord 0, 0
- ld b, 3
- ld c, 7
+ lb bc, 3, 7
call TextBoxBorder
hlcoord 1, 1
ld de, wSafariSteps
@@ -239,11 +240,11 @@ PrintSafariZoneSteps::
call PlaceString
ld a, [wNumSafariBalls]
cp 10
- jr nc, .asm_c56d
+ jr nc, .numSafariBallsTwoDigits
hlcoord 5, 3
ld a, " "
ld [hl], a
-.asm_c56d
+.numSafariBallsTwoDigits
hlcoord 6, 3
ld de, wNumSafariBalls
lb bc, 1, 2
@@ -345,16 +346,8 @@ GetTileTwoStepsInFrontOfPlayer:
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
+ call IsTilePassable
+ jr c, .done
ld hl, TilePairCollisionsLand
call CheckForTilePairCollisions2
ld a, $ff
diff --git a/engine/overworld/push_boulder.asm b/engine/overworld/push_boulder.asm
index a8e532d3..09911ca3 100644
--- a/engine/overworld/push_boulder.asm
+++ b/engine/overworld/push_boulder.asm
@@ -2,6 +2,8 @@ TryPushingBoulder::
ld a, [wd728]
bit 0, a ; using Strength?
ret z
+Func_f0a7:
+; where LoadMissableObjects predef points to now
ld a, [wFlags_0xcd60]
bit 1, a ; has boulder dust animation from previous push played yet?
ret nz
diff --git a/engine/overworld/sprite_collisions.asm b/engine/overworld/sprite_collisions.asm
index dc57d5b9..db81977b 100644
--- a/engine/overworld/sprite_collisions.asm
+++ b/engine/overworld/sprite_collisions.asm
@@ -1,5 +1,5 @@
_UpdateSprites::
- ld h, $c1
+ ld h, wSpriteStateData1 / $100
inc h
ld a, SPRITESTATEDATA2_IMAGEBASEOFFSET
.spriteLoop
@@ -24,9 +24,12 @@ _UpdateSprites::
jr nz, .spriteLoop
ret
.updateCurrentSprite
- cp $1
- jp nz, UpdateNonPlayerSprite
- jp UpdatePlayerSprite
+ ldh a, [hCurrentSpriteOffset]
+ and a
+ jp z, UpdatePlayerSprite
+ cp $f0 ; pikachu
+ jp z, SpawnPikachu
+ ld a, [hl]
UpdateNonPlayerSprite:
dec a
@@ -52,11 +55,10 @@ UpdateNonPlayerSprite:
; 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
+ ; nop
ld h, HIGH(wSpriteStateData1)
ldh a, [hCurrentSpriteOffset]
- add LOW(wSpriteStateData1)
ld l, a
ld a, [hl] ; a = [i#SPRITESTATEDATA1_PICTUREID] (0 if slot is unused)
@@ -271,6 +273,17 @@ DetectCollisionBetweenSprites:
jr nc, .next ; go to next sprite if distance is still positive after both adjustments
.collision
+ ld a, l
+ and $f0 ; collision with pikachu?
+ jr nz, .asm_4cd9
+ xor a
+ ld [wd434], a
+ ldh a, [hFF8F]
+ cp $f
+ jr nz, .asm_4cd9
+ call Func_4d0a
+ jr .asm_4cef
+.asm_4cd9
ldh a, [hFF91] ; a = 7 or 9 depending on sprite i's delta X
ld b, a
ldh a, [hFF90] ; a = 7 or 9 depending on sprite i's delta Y
@@ -296,6 +309,7 @@ DetectCollisionBetweenSprites:
; to indicate which sprite the collision occurred with
inc l
inc l
+.asm_4cef
ldh a, [hFF8F] ; a = loop counter
ld de, SpriteCollisionBitTable
add a
@@ -324,6 +338,26 @@ DetectCollisionBetweenSprites:
; c = 0 if delta X/Y is 0
; c = 7 if delta X/Y is 1
; c = 9 if delta X/Y is -1
+Func_4d0a:
+ ldh a, [hFF91]
+ ld b, a
+ ldh a, [hFF90]
+ inc l
+ cp b
+ jr c, .asm_4d17
+ ld b, %1100
+ jr .asm_4d19
+.asm_4d17
+ ld b, %11
+.asm_4d19
+ ld a, c
+ and b
+ ld [wd434], a
+ ld a, c
+ inc l
+ inc l
+ ret
+
SetSpriteCollisionValues:
and a
ld b, 0
diff --git a/engine/overworld/tilesets.asm b/engine/overworld/tilesets.asm
index f40cbbc2..686fa50c 100644
--- a/engine/overworld/tilesets.asm
+++ b/engine/overworld/tilesets.asm
@@ -5,23 +5,14 @@ LoadTilesetHeader:
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
+ add hl, de
+ add hl, de
ld de, wTilesetBank
- ld c, $b
-.copyTilesetHeaderLoop
- ld a, [hli]
- ld [de], a
- inc de
- dec c
- jr nz, .copyTilesetHeaderLoop
+ ld bc, $b
+ call CopyData
ld a, [hl]
ldh [hTilesetType], a
xor a
@@ -35,13 +26,13 @@ LoadTilesetHeader:
call IsInArray
pop de
pop hl
- jr c, .asm_c797
+ jr c, .notDungeonTileset
ld a, [wCurMapTileset]
ld b, a
ldh a, [hPreviousTileset]
cp b
jr z, .done
-.asm_c797
+.notDungeonTileset
ld a, [wDestinationWarpID]
cp $ff
jr z, .done
diff --git a/engine/overworld/turn_sprite.asm b/engine/overworld/turn_sprite.asm
deleted file mode 100755
index 7b34a03a..00000000
--- a/engine/overworld/turn_sprite.asm
+++ /dev/null
@@ -1,25 +0,0 @@
-UpdateSpriteFacingOffsetAndDelayMovement::
- ld h, HIGH(wSpriteStateData2)
- ldh a, [hCurrentSpriteOffset]
- add $8
- ld l, a
- ld a, $7f ; maximum movement delay
- ld [hl], a ; x#SPRITESTATEDATA2_MOVEMENTDELAY
- dec h ; HIGH(wSpriteStateData1)
- ldh a, [hCurrentSpriteOffset]
- add $9
- ld l, a
- ld a, [hld] ; x#SPRITESTATEDATA1_FACINGDIRECTION
- ld b, a
- xor a
- ld [hld], a
- ld [hl], a ; x#SPRITESTATEDATA1_ANIMFRAMECOUNTER
- ldh a, [hCurrentSpriteOffset]
- add SPRITESTATEDATA1_IMAGEINDEX
- ld l, a
- ld a, [hl] ; x#SPRITESTATEDATA1_IMAGEINDEX
- or b ; or in the facing direction
- ld [hld], a
- ld a, $2 ; delayed movement status
- ld [hl], a ; x#SPRITESTATEDATA1_MOVEMENTSTATUS
- ret