summaryrefslogtreecommitdiff
path: root/home/overworld.asm
diff options
context:
space:
mode:
Diffstat (limited to 'home/overworld.asm')
-rw-r--r--home/overworld.asm1251
1 files changed, 563 insertions, 688 deletions
diff --git a/home/overworld.asm b/home/overworld.asm
index b96efcb4..8608cbfe 100644
--- a/home/overworld.asm
+++ b/home/overworld.asm
@@ -1,8 +1,3 @@
-HandleMidJump::
-; Handle the player jumping down
-; a ledge in the overworld.
- jpba _HandleMidJump
-
EnterMap::
; Load a new map.
ld a, $ff
@@ -24,11 +19,18 @@ EnterMap::
ld a, [hl]
and 1 << 4 | 1 << 3 ; fly warp or dungeon warp
jr z, .didNotEnterUsingFlyWarpOrDungeonWarp
- res 3, [hl]
callba EnterMapAnim
call UpdateSprites
+ ld hl, wd732
+ res 3, [hl]
+ ld hl, wd72e
+ res 4, [hl]
.didNotEnterUsingFlyWarpOrDungeonWarp
+ call IsSurfingPikachuInParty
callba CheckForceBikeOrSurf ; handle currents in SF islands and forced bike riding in cycling road
+ ld hl, wd732
+ bit 4, [hl]
+ res 4, [hl]
ld hl, wd72d
res 5, [hl]
call UpdateSprites
@@ -42,10 +44,9 @@ OverworldLoop::
call DelayFrame
OverworldLoopLessDelay::
call DelayFrame
+ call IsSurfingPikachuInParty
call LoadGBPal
- ld a, [wd736]
- bit 6, a ; jumping down a ledge?
- call nz, HandleMidJump
+ call HandleMidJump
ld a, [wWalkCounter]
and a
jp nz, .moveAhead ; if the player sprite has not yet completed the walking animation
@@ -91,7 +92,10 @@ OverworldLoopLessDelay::
ld a, [$ffeb]
and a
jp z, OverworldLoop ; jump if a hidden object or bookshelf was found, but not if a card key door was found
+ xor a
+ ld [wd436], a ; new yellow address
call IsSpriteOrSignInFrontOfPlayer
+ call Func_0ffe
ld a, [hSpriteIndexOrTextID]
and a
jp z, OverworldLoop
@@ -109,39 +113,31 @@ OverworldLoopLessDelay::
ld a, [wEnteringCableClub]
and a
jr z, .checkForOpponent
- dec a
- ld a, 0
- ld [wEnteringCableClub], a
- jr z, .changeMap
-; XXX can this code be reached?
- predef LoadSAV
- ld a, [wCurMap]
- ld [wDestinationMap], a
- call SpecialWarpIn
- ld a, [wCurMap]
- call SwitchToMapRomBank ; switch to the ROM bank of the current map
- ld hl, wCurMapTileset
- set 7, [hl]
-.changeMap
+ xor a
+ ld [wLinkTimeoutCounter], a
jp EnterMap
.checkForOpponent
ld a, [wCurOpponent]
and a
jp nz, .newBattle
jp OverworldLoop
+
.noDirectionButtonsPressed
+ call UpdateSprites
ld hl, wFlags_0xcd60
res 2, [hl]
- call UpdateSprites
+ xor a
+ ld [wd435], a
ld a, 1
ld [wCheckFor180DegreeTurn], a
ld a, [wPlayerMovingDirection] ; the direction that was pressed last time
and a
- jp z, OverworldLoop
+ jr z, .overworldloop
; if a direction was pressed last time
ld [wPlayerLastStopDirection], a ; save the last direction
xor a
ld [wPlayerMovingDirection], a ; zero the direction
+.overworldloop
jp OverworldLoop
.checkIfDownButtonIsPressed
@@ -174,7 +170,7 @@ OverworldLoopLessDelay::
jr z, .noDirectionButtonsPressed
ld a, 1
ld [wSpriteStateData1 + 5], a ; delta X
-
+ ld a, 1
.handleDirectionButtonPress
ld [wPlayerDirection], a ; new direction
@@ -189,44 +185,13 @@ OverworldLoopLessDelay::
ld a, [wPlayerLastStopDirection] ; old direction
cp b
jr z, .noDirectionChange
-; Check whether the player did a 180-degree turn.
-; It appears that this code was supposed to show the player rotate by having
-; the player's sprite face an intermediate direction before facing the opposite
-; direction (instead of doing an instantaneous about-face), but the intermediate
-; direction is only set for a short period of time. It is unlikely for it to
-; ever be visible because DelayFrame is called at the start of OverworldLoop and
-; normally not enough cycles would be executed between then and the time the
-; direction is set for V-blank to occur while the direction is still set.
- swap a ; put old direction in upper half
- or b ; put new direction in lower half
- cp (PLAYER_DIR_DOWN << 4) | PLAYER_DIR_UP ; change dir from down to up
- jr nz, .notDownToUp
- ld a, PLAYER_DIR_LEFT
- ld [wPlayerMovingDirection], a
- jr .holdIntermediateDirectionLoop
-.notDownToUp
- cp (PLAYER_DIR_UP << 4) | PLAYER_DIR_DOWN ; change dir from up to down
- jr nz, .notUpToDown
- ld a, PLAYER_DIR_RIGHT
- ld [wPlayerMovingDirection], a
- jr .holdIntermediateDirectionLoop
-.notUpToDown
- cp (PLAYER_DIR_RIGHT << 4) | PLAYER_DIR_LEFT ; change dir from right to left
- jr nz, .notRightToLeft
- ld a, PLAYER_DIR_DOWN
- ld [wPlayerMovingDirection], a
- jr .holdIntermediateDirectionLoop
-.notRightToLeft
- cp (PLAYER_DIR_LEFT << 4) | PLAYER_DIR_RIGHT ; change dir from left to right
- jr nz, .holdIntermediateDirectionLoop
- ld a, PLAYER_DIR_UP
- ld [wPlayerMovingDirection], a
-.holdIntermediateDirectionLoop
+ ld a, $8
+ ld [wd435], a
+; unlike in red/blue, yellow does not have the 180 degrees odd code
ld hl, wFlags_0xcd60
set 2, [hl]
- ld hl, wCheckFor180DegreeTurn
- dec [hl]
- jr nz, .holdIntermediateDirectionLoop
+ xor a
+ ld [wCheckFor180DegreeTurn], a
ld a, [wPlayerDirection]
ld [wPlayerMovingDirection], a
call NewBattle
@@ -263,48 +228,26 @@ OverworldLoopLessDelay::
.noCollision
ld a, $08
ld [wWalkCounter], a
+ callab Func_fcc08
jr .moveAhead2
.moveAhead
- ld a, [wd736]
- bit 7, a
- jr z, .noSpinning
- callba LoadSpinnerArrowTiles
-.noSpinning
+ call IsSpinning
call UpdateSprites
.moveAhead2
ld hl, wFlags_0xcd60
res 2, [hl]
- ld a, [wWalkBikeSurfState]
- dec a ; riding a bike?
- jr nz, .normalPlayerSpriteAdvancement
- ld a, [wd736]
- bit 6, a ; jumping a ledge?
- jr nz, .normalPlayerSpriteAdvancement
+ xor a
+ ld [wd435], a
call DoBikeSpeedup
-.normalPlayerSpriteAdvancement
call AdvancePlayerSprite
ld a, [wWalkCounter]
and a
jp nz, CheckMapConnections ; it seems like this check will never succeed (the other place where CheckMapConnections is run works)
; walking animation finished
- ld a, [wd730]
- bit 7, a
- jr nz, .doneStepCounting ; if button presses are being simulated, don't count steps
-; step counting
- ld hl, wStepCounter
- dec [hl]
- ld a, [wd72c]
- bit 0, a
- jr z, .doneStepCounting
- ld hl, wNumberOfNoRandomBattleStepsLeft
- dec [hl]
- jr nz, .doneStepCounting
- ld hl, wd72c
- res 0, [hl] ; indicate that the player has stepped thrice since the last battle
-.doneStepCounting
- CheckEvent EVENT_IN_SAFARI_ZONE
+ call StepCountCheck
+ CheckEvent EVENT_IN_SAFARI_ZONE ; in the safari zone?
jr z, .notSafariZone
callba SafariZoneCheckSteps
ld a, [wSafariZoneGameOver]
@@ -346,12 +289,31 @@ OverworldLoopLessDelay::
callab AnyPartyAlive
ld a, d
and a
- jr z, .allPokemonFainted
+ jr z, AllPokemonFainted
.noFaintCheck
ld c, 10
call DelayFrames
jp EnterMap
-.allPokemonFainted
+
+StepCountCheck::
+ ld a, [wd730]
+ bit 7, a
+ jr nz, .doneStepCounting ; if button presses are being simulated, don't count steps
+; step counting
+ ld hl, wStepCounter
+ dec [hl]
+ ld a, [wd72c]
+ bit 0, a
+ jr z, .doneStepCounting
+ ld hl, wNumberOfNoRandomBattleStepsLeft
+ dec [hl]
+ jr nz, .doneStepCounting
+ ld hl, wd72c
+ res 0, [hl] ; indicate that the player has stepped thrice since the last battle
+.doneStepCounting
+ ret
+
+AllPokemonFainted::
ld a, $ff
ld [wIsInBattle], a
call RunMapScript
@@ -375,6 +337,12 @@ NewBattle::
; function to make bikes twice as fast as walking
DoBikeSpeedup::
+ ld a, [wWalkBikeSurfState]
+ dec a ; riding a bike?
+ ret nz
+ ld a, [wd736]
+ bit 6, a
+ ret nz
ld a, [wNPCMovementScriptPointerTableNum]
and a
ret nz
@@ -385,15 +353,16 @@ DoBikeSpeedup::
and D_UP | D_LEFT | D_RIGHT
ret nz
.goFaster
- jp AdvancePlayerSprite
+ call AdvancePlayerSprite
+ ret
; check if the player has stepped onto a warp after having not collided
CheckWarpsNoCollision::
ld a, [wNumberOfWarps]
and a
jp z, CheckMapConnections
- ld a, [wNumberOfWarps]
ld b, 0
+ ld a, [wNumberOfWarps]
ld c, a
ld a, [wYCoord]
ld d, a
@@ -436,6 +405,17 @@ CheckWarpsNoCollisionLoop::
jr z, CheckWarpsNoCollisionRetry2 ; if directional buttons aren't being pressed, do not pass through the warp
jr WarpFound1
+CheckWarpsNoCollisionRetry1::
+ inc hl
+CheckWarpsNoCollisionRetry2::
+ inc hl
+ inc hl
+ContinueCheckWarpsNoCollisionLoop::
+ inc b ; increment warp number
+ dec c ; decrement number of warps
+ jp nz, CheckWarpsNoCollisionLoop
+ jp CheckMapConnections
+
; check if the player has stepped onto a warp after having collided
CheckWarpsCollision::
ld a, [wNumberOfWarps]
@@ -466,13 +446,6 @@ CheckWarpsCollision::
jr nz, .loop
jp OverworldLoop
-CheckWarpsNoCollisionRetry1::
- inc hl
-CheckWarpsNoCollisionRetry2::
- inc hl
- inc hl
- jp ContinueCheckWarpsNoCollisionLoop
-
WarpFound1::
ld a, [hli]
ld [wDestinationWarpID], a
@@ -500,6 +473,7 @@ WarpFound2::
ld [wMapPalOffset], a
call GBFadeOutToBlack
.notRockTunnel
+ callab SetPikachuSpawnOutside
call PlayMapChangeSound
jr .done
@@ -516,9 +490,9 @@ WarpFound2::
dec a ; is the player on a warp pad?
jr nz, .notWarpPad
; if the player is on a warp pad
+ call LeaveMapAnim
ld hl, wd732
set 3, [hl]
- call LeaveMapAnim
jr .skipMapChangeSound
.notWarpPad
call PlayMapChangeSound
@@ -526,8 +500,11 @@ WarpFound2::
ld hl, wd736
res 0, [hl]
res 1, [hl]
+ callab SetPikachuSpawnWarpPad
jr .done
+
.goBackOutside
+ callab SetPikachuSpawnBackOutside
ld a, [wLastMap]
ld [wCurMap], a
call PlayMapChangeSound
@@ -539,11 +516,6 @@ WarpFound2::
call IgnoreInputForHalfSecond
jp EnterMap
-ContinueCheckWarpsNoCollisionLoop::
- inc b ; increment warp number
- dec c ; decrement number of warps
- jp nz, CheckWarpsNoCollisionLoop
-
; if no matching warp was found
CheckMapConnections::
.checkWestMap
@@ -673,13 +645,17 @@ CheckMapConnections::
ld a, h
ld [wCurrentTileBlockMapViewPointer + 1], a
.loadNewMap ; load the connected map that was entered
+ ld hl, wPikachuOverworldStateFlags
+ set 4, [hl]
+ ld a, $2
+ ld [wPikachuSpawnState], a
call LoadMapHeader
call PlayDefaultMusicFadeOutCurrent
ld b, SET_PAL_OVERWORLD
call RunPaletteCommand
; Since the sprite set shouldn't change, this will just update VRAM slots at
; $C2XE without loading any tile patterns.
- callba InitMapSprites
+ call InitMapSprites
call LoadTileBlockMap
jp OverworldLoopLessDelay
@@ -688,6 +664,11 @@ CheckMapConnections::
; function to play a sound when changing maps
PlayMapChangeSound::
+ ld a, [wCurMapTileset]
+ cp FACILITY
+ jr z, .didNotGoThroughDoor
+ cp CEMETERY
+ jr z, .didNotGoThroughDoor
aCoord 8, 8 ; upper left tile of the 4x4 square the player's sprite is standing on
cp $0b ; door tile in tileset 0
jr nz, .didNotGoThroughDoor
@@ -762,19 +743,15 @@ HandleBlackOut::
call StopMusic
ld hl, wd72e
res 5, [hl]
- ld a, Bank(ResetStatusAndHalveMoneyOnBlackout) ; also Bank(SpecialWarpIn) and Bank(SpecialEnterMap)
- ld [H_LOADEDROMBANK], a
- ld [MBC1RomBank], a
- call ResetStatusAndHalveMoneyOnBlackout
+ switchbank SpecialWarpIn ; also Bank(SpecialEnterMap)
+ callab ResetStatusAndHalveMoneyOnBlackout
call SpecialWarpIn
call PlayDefaultMusicFadeOutCurrent
jp SpecialEnterMap
StopMusic::
ld [wAudioFadeOutControl], a
- ld a, $ff
- ld [wNewSoundID], a
- call PlaySound
+ call StopAllMusic
.wait
ld a, [wAudioFadeOutControl]
and a
@@ -786,22 +763,31 @@ HandleFlyWarpOrDungeonWarp::
call Delay3
xor a
ld [wBattleResult], a
- ld [wWalkBikeSurfState], a
ld [wIsInBattle], a
ld [wMapPalOffset], a
ld hl, wd732
set 2, [hl] ; fly warp or dungeon warp
res 5, [hl] ; forced to ride bike
call LeaveMapAnim
- ld a, Bank(SpecialWarpIn)
- ld [H_LOADEDROMBANK], a
- ld [MBC1RomBank], a
- call SpecialWarpIn
+ call Func_07c4
+ callbs SpecialWarpIn
jp SpecialEnterMap
LeaveMapAnim::
jpba _LeaveMapAnim
+Func_07c4::
+ ld a, [wWalkBikeSurfState]
+ and a
+ ret z
+ xor a
+ ld [wWalkBikeSurfState], a
+ ld hl, wd732
+ bit 4, [hl]
+ ret z
+ call PlayDefaultMusic
+ ret
+
LoadPlayerSpriteGraphics::
; Load sprite graphics based on whether the player is standing, biking, or surfing.
@@ -837,7 +823,7 @@ LoadPlayerSpriteGraphics::
dec a
jp z, LoadBikePlayerSpriteGraphics
dec a
- jp z, LoadSurfingPlayerSpriteGraphics
+ jp z, LoadSurfingPlayerSpriteGraphics2
jp LoadWalkingPlayerSpriteGraphics
IsBikeRidingAllowed::
@@ -878,23 +864,16 @@ LoadTilesetTilePatternData::
ld de, vTileset
ld bc, $600
ld a, [wTilesetBank]
- jp FarCopyData2
+ jp FarCopyData
; this loads the current maps complete tile map (which references blocks, not individual tiles) to C6E8
; it can also load partial tile maps of connected maps into a border of length 3 around the current map
LoadTileBlockMap::
; fill C6E8-CBFB with the background tile
ld hl, wOverworldMap
- ld a, [wMapBackgroundTile]
- ld d, a
ld bc, wOverworldMapEnd - wOverworldMap
-.backgroundTileLoop
- ld a, d
- ld [hli], a
- dec bc
- ld a, c
- or b
- jr nz, .backgroundTileLoop
+ ld a, [wMapBackgroundTile] ; background tile number
+ call FillMemory
; load tile map of current map (made of tile block IDs)
; a 3-byte border at the edges of the map is kept so that there is space for map connections
ld hl, wOverworldMap
@@ -1073,8 +1052,7 @@ LoadEastWestConnectionsTileMap::
ret
; function to check if there is a sign or sprite in front of the player
-; if so, it is stored in [hSpriteIndexOrTextID]
-; if not, [hSpriteIndexOrTextID] is set to 0
+; if so, carry is set. otherwise, carry is cleared
IsSpriteOrSignInFrontOfPlayer::
xor a
ld [hSpriteIndexOrTextID], a
@@ -1083,39 +1061,10 @@ IsSpriteOrSignInFrontOfPlayer::
jr z, .extendRangeOverCounter
; if there are signs
predef GetTileAndCoordsInFrontOfPlayer ; get the coordinates in front of the player in de
- ld hl, wSignCoords
- ld a, [wNumSigns]
- ld b, a
- ld c, 0
-.signLoop
- inc c
- ld a, [hli] ; sign Y
- cp d
- jr z, .yCoordMatched
- inc hl
- jr .retry
-.yCoordMatched
- ld a, [hli] ; sign X
- cp e
- jr nz, .retry
-.xCoordMatched
-; found sign
- push hl
- push bc
- ld hl, wSignTextIDs
- ld b, 0
- dec c
- add hl, bc
- ld a, [hl]
- ld [hSpriteIndexOrTextID], a ; store sign text ID
- pop bc
- pop hl
- ret
-.retry
- dec b
- jr nz, .signLoop
-; check if the player is front of a counter in a pokemon center, pokemart, etc. and if so, extend the range at which he can talk to the NPC
+ call SignLoop
+ ret c
.extendRangeOverCounter
+; check if the player is front of a counter in a pokemon center, pokemart, etc. and if so, extend the range at which he can talk to the NPC
predef GetTileAndCoordsInFrontOfPlayer ; get the tile in front of the player in c
ld hl, wTilesetTalkingOverTiles ; list of tiles that extend talking range (counter tiles)
ld b, 3
@@ -1127,13 +1076,12 @@ IsSpriteOrSignInFrontOfPlayer::
dec b
jr nz, .counterTilesLoop
-; part of the above function, but sometimes its called on its own, when signs are irrelevant
-; the caller must zero [hSpriteIndexOrTextID]
+; sets carry flag if a sprite is in front of the player, resets if not
IsSpriteInFrontOfPlayer::
ld d, $10 ; talking range in pixels (normal range)
IsSpriteInFrontOfPlayer2::
lb bc, $3c, $40 ; Y and X position of player sprite
- ld a, [wSpriteStateData1 + 9] ; direction the player is facing
+ ld a, [wSpritePlayerStateData1FacingDirection] ; direction the player is facing
.checkIfPlayerFacingUp
cp SPRITE_FACING_UP
jr nz, .checkIfPlayerFacingDown
@@ -1172,13 +1120,10 @@ IsSpriteInFrontOfPlayer2::
ld a, PLAYER_DIR_LEFT
.doneCheckingDirection
ld [wPlayerDirection], a
- ld a, [wNumSprites] ; number of sprites
- and a
- ret z
-; if there are sprites
ld hl, wSpriteStateData1 + $10
- ld d, a
+; yellow does not have the "if sprites are existant" check
ld e, $01
+ ld d, $f
.spriteLoop
push hl
ld a, [hli] ; image (0 if no sprite)
@@ -1204,7 +1149,9 @@ IsSpriteInFrontOfPlayer2::
inc e
dec d
jr nz, .spriteLoop
+ xor a
ret
+
.foundSpriteInFrontOfPlayer
pop hl
ld a, l
@@ -1214,6 +1161,52 @@ IsSpriteInFrontOfPlayer2::
set 7, [hl] ; set flag to make the sprite face the player
ld a, e
ld [hSpriteIndexOrTextID], a
+ ld a, [hSpriteIndexOrTextID] ; possible useless read because a already has the value of the read address
+ cp $f
+ jr nz, .dontwritetowd436
+ ld a, $FF
+ ld [wd436], a
+.dontwritetowd436
+ scf
+ ret
+
+SignLoop::
+; search if a player is facing a sign
+ ld hl, wSignCoords ; start of sign coordinates
+ ld a, [wNumSigns] ; number of signs in the map
+ ld b, a
+ ld c, $00
+.signLoop
+ inc c
+ ld a, [hli] ; sign Y
+ cp d
+ jr z, .yCoordMatched
+ inc hl
+ jr .retry
+
+.yCoordMatched
+ ld a, [hli] ; sign X
+ cp e
+ jr nz, .retry
+.xCoordMatched
+; found sign
+ push hl
+ push bc
+ ld hl, wSignTextIDs ; start of sign text ID's
+ ld b, $00
+ dec c
+ add hl, bc
+ ld a, [hl]
+ ld [hSpriteIndexOrTextID], a ; store sign text ID
+ pop bc
+ pop hl
+ scf
+ ret
+
+.retry
+ dec b
+ jr nz, .signLoop
+ xor a
ret
; function to check if the player will jump down a ledge and check if the tile ahead is passable (when not surfing)
@@ -1230,14 +1223,31 @@ CollisionCheckOnLand::
ld d, a
ld a, [wSpriteStateData1 + 12] ; the player sprite's collision data (bit field) (set in the sprite movement code)
and d ; check if a sprite is in the direction the player is trying to go
+ nop ; ??? why is this in the code
jr nz, .collision
xor a
ld [hSpriteIndexOrTextID], a
call IsSpriteInFrontOfPlayer ; check for sprite collisions again? when does the above check fail to detect a sprite collision?
+ jr nc, .asm_0a5c
+ res 7, [hl]
ld a, [hSpriteIndexOrTextID]
and a ; was there a sprite collision?
- jr nz, .collision
+ jr z, .asm_0a5c
; if no sprite collision
+ cp $f
+ jr nz, .collision
+ call CheckPikachuFollowingPlayer
+ jr nz, .collision
+ ld a, [hJoyHeld]
+ and $2
+ jr nz, .asm_0a5c
+ ld hl, wd435
+ ld a, [hl]
+ and a
+ jr z, .asm_0a5c
+ dec [hl]
+ jr nz, .collision
+.asm_0a5c
ld hl, TilePairCollisionsLand
call CheckForJumpingAndTilePairCollisions
jr c, .collision
@@ -1262,19 +1272,7 @@ CheckTilePassable::
predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player
ld a, [wTileInFrontOfPlayer] ; tile in front of player
ld c, a
- ld hl, wTilesetCollisionPtr ; pointer to list of passable tiles
- ld a, [hli]
- ld h, [hl]
- ld l, a ; hl now points to passable tiles
-.loop
- ld a, [hli]
- cp $ff
- jr z, .tileNotPassable
- cp c
- ret z
- jr .loop
-.tileNotPassable
- scf
+ call IsTilePassable
ret
; check if the player is going to jump down a small ledge
@@ -1286,7 +1284,7 @@ CheckForJumpingAndTilePairCollisions::
predef GetTileAndCoordsInFrontOfPlayer ; get the tile in front of the player
push de
push bc
- callba HandleLedges ; check if the player is trying to jump a ledge
+ callba HandleLedges ; check if the player is trying to jump a ledge
pop bc
pop de
pop hl
@@ -1375,8 +1373,7 @@ LoadCurrentMapView::
ld a, [H_LOADEDROMBANK]
push af
ld a, [wTilesetBank] ; tile data ROM bank
- ld [H_LOADEDROMBANK], a
- ld [MBC1RomBank], a ; switch to ROM bank that contains tile data
+ call BankswitchCommon ; switch to ROM bank that contains tile data
ld a, [wCurrentTileBlockMapViewPointer] ; address of upper left corner of current map view
ld e, a
ld a, [wCurrentTileBlockMapViewPointer + 1]
@@ -1457,254 +1454,19 @@ LoadCurrentMapView::
dec b
jr nz, .rowLoop2
pop af
- ld [H_LOADEDROMBANK], a
- ld [MBC1RomBank], a ; restore previous ROM bank
+ call BankswitchCommon ; restore previous ROM bank
ret
AdvancePlayerSprite::
- ld a, [wSpriteStateData1 + 3] ; delta Y
- ld b, a
- ld a, [wSpriteStateData1 + 5] ; delta X
- 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 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, [wSpriteStateData1 + 3] ; delta Y
- 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, [wSpriteStateData1 + 5] ; delta X
- 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, [wSpriteStateData1 + 3] ; delta Y
- ld b, a
- ld a, [wSpriteStateData1 + 5] ; delta X
- ld c, a
- sla b
- sla c
- ld a, [hSCY]
- add b
- ld [hSCY], a ; update background scroll Y
- ld a, [hSCX]
- add c
- ld [hSCX], a ; update background scroll X
-; 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, wSpriteStateData1 + $14
- ld a, [wNumSprites] ; number of sprites
- and a ; are there any sprites?
- jr z, .done
- ld e, a
-.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
- 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
+ ld a, [wUpdateSpritesEnabled]
+ push af
+ ld a, $FF
+ ld [wUpdateSpritesEnabled], a
+ ld hl, _AdvancePlayerSprite
+ ld b, BANK(_AdvancePlayerSprite)
+ call Bankswitch
+ pop af
+ ld [wUpdateSpritesEnabled], a
ret
; the following 6 functions are used to tell the V-blank handler to redraw
@@ -1849,18 +1611,25 @@ JoypadOverworld::
ld [wSpriteStateData1 + 5], a
call RunMapScript
call Joypad
+ call ForceBikeDown
+ call AreInputsSimulated
+ ret
+
+ForceBikeDown::
ld a, [wFlags_D733]
bit 3, a ; check if a trainer wants a challenge
- jr nz, .notForcedDownwards
+ ret nz
ld a, [wCurMap]
cp ROUTE_17 ; Cycling Road
- jr nz, .notForcedDownwards
+ ret nz
ld a, [hJoyHeld]
and D_DOWN | D_UP | D_LEFT | D_RIGHT | B_BUTTON | A_BUTTON
- jr nz, .notForcedDownwards
+ ret nz
ld a, D_DOWN
ld [hJoyHeld], a ; on the cycling road, if there isn't a trainer and the player isn't pressing buttons, simulate a down press
-.notForcedDownwards
+ ret
+
+AreInputsSimulated::
ld a, [wd730]
bit 7, a
ret z
@@ -1870,18 +1639,8 @@ JoypadOverworld::
ld a, [wOverrideSimulatedJoypadStatesMask] ; bit mask for button presses that override simulated ones
and b
ret nz ; return if the simulated button presses are overridden
- ld hl, wSimulatedJoypadStatesIndex
- dec [hl]
- ld a, [hl]
- cp $ff
- jr z, .doneSimulating ; if the end of the simulated button presses has been reached
- ld hl, wSimulatedJoypadStatesEnd
- add l
- ld l, a
- jr nc, .noCarry
- inc h
-.noCarry
- ld a, [hl]
+ call GetSimulatedInput
+ jr nc, .doneSimulating
ld [hJoyHeld], a ; store simulated button press in joypad state
and a
ret nz
@@ -1905,15 +1664,30 @@ JoypadOverworld::
res 7, [hl]
ret
+GetSimulatedInput::
+ ld hl, wSimulatedJoypadStatesIndex
+ dec [hl]
+ ld a, [hl]
+ cp $ff
+ jr z, .endofsimulatedinputs ; if the end of the simulated button presses has been reached
+ push de
+ ld e, a
+ ld d, $0
+ ld hl, wSimulatedJoypadStatesEnd
+ add hl, de
+ ld a, [hl]
+ pop de
+ scf
+ ret
+
+.endofsimulatedinputs
+ and a
+ ret
+
+
; function to check the tile ahead to determine if the character should get on land or keep surfing
; sets carry if there is a collision and clears carry otherwise
-; It seems that this function has a bug in it, but due to luck, it doesn't
-; show up. After detecting a sprite collision, it jumps to the code that
-; checks if the next tile is passable instead of just directly jumping to the
-; "collision detected" code. However, it doesn't store the next tile in c,
-; so the old value of c is used. 2429 is always called before this function,
-; and 2429 always sets c to 0xF0. There is no 0xF0 background tile, so it
-; is considered impassable and it is detected as a collision.
+; This function had a bug in Red/Blue, but it was fixed in Yellow.
CollisionCheckOnWater::
ld a, [wd730]
bit 7, a
@@ -1922,31 +1696,17 @@ CollisionCheckOnWater::
ld d, a
ld a, [wSpriteStateData1 + 12] ; the player sprite's collision data (bit field) (set in the sprite movement code)
and d ; check if a sprite is in the direction the player is trying to go
- jr nz, .checkIfNextTileIsPassable ; bug?
+ jr nz, .collision
ld hl, TilePairCollisionsWater
call CheckForJumpingAndTilePairCollisions
jr c, .collision
predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player (puts it in c and [wTileInFrontOfPlayer])
+ callab IsNextTileShoreOrWater
+ jr c, .noCollision
ld a, [wTileInFrontOfPlayer] ; tile in front of player
- cp $14 ; water tile
- jr z, .noCollision ; keep surfing if it's a water tile
- cp $32 ; either the left tile of the S.S. Anne boarding platform or the tile on eastern coastlines (depending on the current tileset)
- jr z, .checkIfVermilionDockTileset
- cp $48 ; tile on right on coast lines in Safari Zone
- jr z, .noCollision ; keep surfing
-; check if the [land] tile in front of the player is passable
-.checkIfNextTileIsPassable
- ld hl, wTilesetCollisionPtr ; pointer to list of passable tiles
- ld a, [hli]
- ld h, [hl]
- ld l, a
-.loop
- ld a, [hli]
- cp $ff
- jr z, .collision
- cp c
- jr z, .stopSurfing ; stop surfing if the tile is passable
- jr .loop
+ ld c, a
+ call IsTilePassable
+ jr nc, .stopSurfing
.collision
ld a, [wChannelSoundIDs + Ch5]
cp SFX_COLLISION ; check if collision sound is already playing
@@ -1956,21 +1716,26 @@ CollisionCheckOnWater::
.setCarry
scf
jr .done
-.noCollision
- and a
-.done
- ret
-.stopSurfing
- xor a
- ld [wWalkBikeSurfState], a
- call LoadPlayerSpriteGraphics
- call PlayDefaultMusic
- jr .noCollision
.checkIfVermilionDockTileset
ld a, [wCurMapTileset] ; tileset
cp SHIP_PORT ; Vermilion Dock tileset
jr nz, .noCollision ; keep surfing if it's not the boarding platform tile
jr .stopSurfing ; if it is the boarding platform tile, stop surfing
+.stopSurfing ; based game freak
+ ld a, $3
+ ld [wPikachuSpawnState], a
+ ld hl, wPikachuOverworldStateFlags
+ set 5, [hl]
+ xor a
+ ld [wWalkBikeSurfState], a
+ call LoadPlayerSpriteGraphics
+ call PlayDefaultMusic
+ jr .noCollision
+
+.noCollision ; ...and they do the same mistake twice
+ and a
+.done
+ ret
; function to run the current map's script
RunMapScript::
@@ -2000,24 +1765,46 @@ RunMapScript::
ret
LoadWalkingPlayerSpriteGraphics::
+; new sprite copy stuff
+ xor a
+ ld [wd473], a
+ ld b, BANK(RedSprite)
ld de, RedSprite
- ld hl, vNPCSprites
+ jr LoadPlayerSpriteGraphicsCommon
+
+LoadSurfingPlayerSpriteGraphics2::
+ ld a, [wd473]
+ and a
+ jr z, .asm_0d75
+ dec a
+ jr z, LoadSurfingPlayerSpriteGraphics
+ dec a
+ jr z, .asm_0d7c
+.asm_0d75
+ ld a, [wd472]
+ bit 6, a
+ jr z, LoadSurfingPlayerSpriteGraphics
+.asm_0d7c
+ ld b, BANK(SurfingPikachuSprite)
+ ld de, SurfingPikachuSprite
jr LoadPlayerSpriteGraphicsCommon
LoadSurfingPlayerSpriteGraphics::
+ ld b, BANK(SeelSprite)
ld de, SeelSprite
- ld hl, vNPCSprites
jr LoadPlayerSpriteGraphicsCommon
LoadBikePlayerSpriteGraphics::
+ ld b, BANK(RedCyclingSprite)
ld de, RedCyclingSprite
- ld hl, vNPCSprites
-
LoadPlayerSpriteGraphicsCommon::
+ ld hl, vNPCSprites
push de
push hl
- lb bc, BANK(RedSprite), $0c
+ push bc
+ ld c, $c
call CopyVideoData
+ pop bc
pop hl
pop de
ld a, $c0
@@ -2027,12 +1814,17 @@ LoadPlayerSpriteGraphicsCommon::
inc d
.noCarry
set 3, h
- lb bc, BANK(RedSprite), $0c
+ ld c, $c
jp CopyVideoData
; function to load data from the map header
LoadMapHeader::
callba MarkTownVisitedAndLoadMissableObjects
+ jr asm_0dbd
+
+Func_0db5:: ; XXX
+ callba LoadUnusedBluesHouseMissableObjectData
+asm_0dbd
ld a, [wCurMapTileset]
ld [wUnusedD119], a
ld a, [wCurMap]
@@ -2044,20 +1836,7 @@ LoadMapHeader::
ld [hPreviousTileset], a
bit 7, b
ret nz
- ld hl, MapHeaderPointers
- ld a, [wCurMap]
- sla a
- jr nc, .noCarry1
- inc h
-.noCarry1
- add l
- ld l, a
- jr nc, .noCarry2
- inc h
-.noCarry2
- ld a, [hli]
- ld h, [hl]
- ld l, a ; hl = base of map header
+ call GetMapHeaderPointer
; copy the first 10 bytes (the fixed area) of the map data to D367-D370
ld de, wCurMapTileset
ld c, $0a
@@ -2131,155 +1910,19 @@ LoadMapHeader::
ld [wNumSigns], a
and a ; are there any signs?
jr z, .loadSpriteData ; if not, skip this
- ld c, a
- ld de, wSignTextIDs
- ld a, d
- ld [hSignCoordPointer], a
- ld a, e
- ld [hSignCoordPointer + 1], a
- ld de, wSignCoords
-.signLoop
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hli]
- ld [de], a
- inc de
- push de
- ld a, [hSignCoordPointer]
- ld d, a
- ld a, [hSignCoordPointer + 1]
- ld e, a
- ld a, [hli]
- ld [de], a
- inc de
- ld a, d
- ld [hSignCoordPointer], a
- ld a, e
- ld [hSignCoordPointer + 1], a
- pop de
- dec c
- jr nz, .signLoop
+ call CopySignData
.loadSpriteData
ld a, [wd72e]
bit 5, a ; did a battle happen immediately before this?
- jp nz, .finishUp ; if so, skip this because battles don't destroy this data
- ld a, [hli]
- ld [wNumSprites], a ; save the number of sprites
- push hl
-; zero C110-C1FF and C210-C2FF
- ld hl, wSpriteStateData1 + $10
- ld de, wSpriteStateData2 + $10
- xor a
- ld b, $f0
-.zeroSpriteDataLoop
- ld [hli], a
- ld [de], a
- inc e
- dec b
- jr nz, .zeroSpriteDataLoop
-; initialize all C100-C1FF sprite entries to disabled (other than player's)
- ld hl, wSpriteStateData1 + $12
- ld de, $0010
- ld c, $0f
-.disableSpriteEntriesLoop
- ld [hl], $ff
- add hl, de
- dec c
- jr nz, .disableSpriteEntriesLoop
- pop hl
- ld de, wSpriteStateData1 + $10
- ld a, [wNumSprites] ; number of sprites
- and a ; are there any sprites?
- jp z, .finishUp ; if there are no sprites, skip the rest
- ld b, a
- ld c, $00
-.loadSpriteLoop
- ld a, [hli]
- ld [de], a ; store picture ID at C1X0
- inc d
- ld a, $04
- add e
- ld e, a
- ld a, [hli]
- ld [de], a ; store Y position at C2X4
- inc e
- ld a, [hli]
- ld [de], a ; store X position at C2X5
- inc e
- ld a, [hli]
- ld [de], a ; store movement byte 1 at C2X6
- ld a, [hli]
- ld [hLoadSpriteTemp1], a ; save movement byte 2
- ld a, [hli]
- ld [hLoadSpriteTemp2], a ; save text ID and flags byte
- push bc
- push hl
- ld b, $00
- ld hl, wMapSpriteData
- add hl, bc
- ld a, [hLoadSpriteTemp1]
- ld [hli], a ; store movement byte 2 in byte 0 of sprite entry
- ld a, [hLoadSpriteTemp2]
- ld [hl], a ; this appears pointless, since the value is overwritten immediately after
- ld a, [hLoadSpriteTemp2]
- ld [hLoadSpriteTemp1], a
- and $3f
- ld [hl], a ; store text ID in byte 1 of sprite entry
- pop hl
- ld a, [hLoadSpriteTemp1]
- bit 6, a
- jr nz, .trainerSprite
- bit 7, a
- jr nz, .itemBallSprite
- jr .regularSprite
-.trainerSprite
- ld a, [hli]
- ld [hLoadSpriteTemp1], a ; save trainer class
- ld a, [hli]
- ld [hLoadSpriteTemp2], a ; save trainer number (within class)
- push hl
- ld hl, wMapSpriteExtraData
- add hl, bc
- ld a, [hLoadSpriteTemp1]
- ld [hli], a ; store trainer class in byte 0 of the entry
- ld a, [hLoadSpriteTemp2]
- ld [hl], a ; store trainer number in byte 1 of the entry
- pop hl
- jr .nextSprite
-.itemBallSprite
- ld a, [hli]
- ld [hLoadSpriteTemp1], a ; save item number
- push hl
- ld hl, wMapSpriteExtraData
- add hl, bc
- ld a, [hLoadSpriteTemp1]
- ld [hli], a ; store item number in byte 0 of the entry
- xor a
- ld [hl], a ; zero byte 1, since it is not used
- pop hl
- jr .nextSprite
-.regularSprite
- push hl
- ld hl, wMapSpriteExtraData
- add hl, bc
-; zero both bytes, since regular sprites don't use this extra space
- xor a
- ld [hli], a
- ld [hl], a
- pop hl
-.nextSprite
- pop bc
- dec d
- ld a, $0a
- add e
- ld e, a
- inc c
- inc c
- dec b
- jp nz, .loadSpriteLoop
+ jr nz, .finishUp ; if so, skip this because battles don't destroy this data
+ call InitSprites
.finishUp
predef LoadTilesetHeader
+ ld a, [wd72e]
+ bit 5, a ; did a battle happen immediately before this?
+ jr nz, .skip_pika_spawn
+ callab SchedulePikachuSpawnForAfterText
+.skip_pika_spawn
callab LoadWildData
pop hl ; restore hl from before going to the warp/sign/sprite data (this value was saved for seemingly no purpose)
ld a, [wCurMapHeight] ; map height in 4x4 tile blocks
@@ -2293,9 +1936,7 @@ LoadMapHeader::
ld b, $00
ld a, [H_LOADEDROMBANK]
push af
- ld a, BANK(MapSongBanks)
- ld [H_LOADEDROMBANK], a
- ld [MBC1RomBank], a
+ switchbank MapSongBanks
ld hl, MapSongBanks
add hl, bc
add hl, bc
@@ -2304,8 +1945,7 @@ LoadMapHeader::
ld a, [hl]
ld [wMapMusicROMBank], a ; music 2
pop af
- ld [H_LOADEDROMBANK], a
- ld [MBC1RomBank], a
+ call BankswitchCommon
ret
; function to copy map connection data from ROM to WRAM
@@ -2320,11 +1960,92 @@ CopyMapConnectionHeader::
jr nz, .loop
ret
+CopySignData::
+ ld de, wSignCoords ; start of sign coords
+ ld bc, wSignTextIDs ; start of sign text ids
+ ld a, [wNumSigns] ; number of signs
+.signcopyloop
+ push af
+ ld a, [hli]
+ ld [de], a ; copy y coord
+ inc de
+ ld a, [hli]
+ ld [de], a ; copy x coord
+ inc de
+ ld a, [hli]
+ ld [bc], a ; copy sign text id
+ inc bc
+ pop af
+ dec a
+ jr nz, .signcopyloop
+ ret
+
; function to load map data
LoadMapData::
ld a, [H_LOADEDROMBANK]
push af
call DisableLCD
+ call ResetMapVariables
+ call LoadTextBoxTilePatterns
+ call LoadMapHeader
+ call InitMapSprites ; load tile pattern data for sprites
+ call LoadScreenRelatedData
+ call CopyMapViewToVRAM
+ ld a, $01
+ ld [wUpdateSpritesEnabled], a
+ call EnableLCD
+ ld b, $09
+ call RunPaletteCommand
+ call LoadPlayerSpriteGraphics
+ ld a, [wd732]
+ and 1 << 4 | 1 << 3 ; fly warp or dungeon warp
+ jr nz, .restoreRomBank
+ ld a, [wFlags_D733]
+ bit 1, a
+ jr nz, .restoreRomBank
+ call UpdateMusic6Times ; music related
+ call PlayDefaultMusicFadeOutCurrent ; music related
+.restoreRomBank
+ pop af
+ call BankswitchCommon
+ ret
+
+LoadScreenRelatedData::
+ call LoadTileBlockMap
+ call LoadTilesetTilePatternData
+ call LoadCurrentMapView
+ ret
+
+ReloadMapAfterSurfingMinigame::
+ ld a, [H_LOADEDROMBANK]
+ push af
+ call DisableLCD
+ call ResetMapVariables
+ ld a, [wCurMap]
+ call SwitchToMapRomBank
+ call LoadScreenRelatedData
+ call CopyMapViewToVRAM
+ ld de, vBGMap1
+ call CopyMapViewToVRAM2
+ call EnableLCD
+ call ReloadMapSpriteTilePatterns
+ pop af
+ call BankswitchCommon
+ jr asm_0f4d
+
+ReloadMapAfterPrinter::
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, [wCurMap]
+ call SwitchToMapRomBank
+ call LoadTileBlockMap
+ pop af
+ call BankswitchCommon
+asm_0f4d:
+ jpab SetMapSpecificScriptFlagsOnMapReload
+ ret ; useless?
+
+ResetMapVariables::
ld a, $98
ld [wMapViewVRAMPointer + 1], a
xor a
@@ -2333,17 +2054,15 @@ LoadMapData::
ld [hSCX], a
ld [wWalkCounter], a
ld [wUnusedD119], a
- ld [wWalkBikeSurfStateCopy], a
ld [wSpriteSetID], a
- call LoadTextBoxTilePatterns
- call LoadMapHeader
- callba InitMapSprites ; load tile pattern data for sprites
- call LoadTileBlockMap
- call LoadTilesetTilePatternData
- call LoadCurrentMapView
+ ld [wWalkBikeSurfStateCopy], a
+ ret
+
+CopyMapViewToVRAM::
; copy current map view to VRAM
- coord hl, 0, 0
ld de, vBGMap0
+CopyMapViewToVRAM2:
+ ld hl, wTileMap
ld b, 18
.vramCopyLoop
ld c, 20
@@ -2353,7 +2072,7 @@ LoadMapData::
inc e
dec c
jr nz, .vramCopyInnerLoop
- ld a, 32 - 20
+ ld a, 32 - 20 ; total vram map width in tiles - screen width in tiles
add e
ld e, a
jr nc, .noCarry
@@ -2361,24 +2080,6 @@ LoadMapData::
.noCarry
dec b
jr nz, .vramCopyLoop
- ld a, $01
- ld [wUpdateSpritesEnabled], a
- call EnableLCD
- ld b, SET_PAL_OVERWORLD
- call RunPaletteCommand
- call LoadPlayerSpriteGraphics
- ld a, [wd732]
- and 1 << 4 | 1 << 3 ; fly warp or dungeon warp
- jr nz, .restoreRomBank
- ld a, [wFlags_D733]
- bit 1, a
- jr nz, .restoreRomBank
- call UpdateMusic6Times
- call PlayDefaultMusicFadeOutCurrent
-.restoreRomBank
- pop af
- ld [H_LOADEDROMBANK], a
- ld [MBC1RomBank], a
ret
; function to switch to the ROM bank that a map is stored in
@@ -2388,20 +2089,37 @@ SwitchToMapRomBank::
push bc
ld c, a
ld b, $00
- ld a, Bank(MapHeaderBanks)
- call BankswitchHome ; switch to ROM bank 3
+ ld a, BANK(MapHeaderBanks)
+ call BankswitchHome ; switch to ROM bank 3F
ld hl, MapHeaderBanks
add hl, bc
ld a, [hl]
ld [$ffe8], a ; save map ROM bank
call BankswitchBack
ld a, [$ffe8]
- ld [H_LOADEDROMBANK], a
- ld [MBC1RomBank], a ; switch to map ROM bank
+ call BankswitchCommon
pop bc
pop hl
ret
+GetMapHeaderPointer::
+ ld a, [H_LOADEDROMBANK]
+ push af
+ switchbank MapHeaderPointers
+ push de
+ ld a, [wCurMap]
+ ld e, a
+ ld d, $0
+ ld hl, MapHeaderPointers
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ pop de
+ pop af
+ jp BankswitchCommon
+
IgnoreInputForHalfSecond:
ld a, 30
ld [wIgnoreInputCounter], a
@@ -2421,3 +2139,160 @@ ForceBikeOrSurf::
ld hl, LoadPlayerSpriteGraphics
call Bankswitch
jp PlayDefaultMusic ; update map/player state?
+
+; Handle the player jumping down
+; a ledge in the overworld.
+HandleMidJump::
+ ld a, [wd736]
+ bit 6, a ; jumping down a ledge?
+ ret z
+ callba _HandleMidJump
+ ret
+
+IsSpinning::
+ ld a, [wd736]
+ bit 7, a
+ ret z ; no spinning
+ jpba LoadSpinnerArrowTiles ; spin while moving
+
+Func_0ffe::
+ jpab IsPlayerTalkingToPikachu
+
+InitSprites::
+ ld a, [hli]
+ ld [wNumSprites], a ; save the number of sprites
+ push hl
+ push de
+ push bc
+ call ZeroSpriteStateData
+ call DisableRegularSprites
+ ld hl, wMapSpriteData
+ ld bc, $20
+ xor a
+ call FillMemory
+ pop bc
+ pop de
+ pop hl
+ ld a, [wNumSprites]
+ and a ; are sprites existant?
+ ret z ; don't copy sprite data if not
+ ld b, a
+ ld c, $0
+ ld de, wSpriteStateData1 + $10
+; copy sprite stuff?
+.loadSpriteLoop
+ ld a, [hli]
+ ld [de], a ; store picture ID at C1X0
+ inc d
+ ld a, e
+ add $4
+ ld e, a
+ ld a, [hli]
+ ld [de], a ; store Y position at C2X4
+ inc e
+ ld a, [hli]
+ ld [de], a ; store X position at C2X5
+ inc e
+ ld a, [hli]
+ ld [de], a ; store movement byte 1 at C2X6
+ ld a, [hli]
+ ld [$ff8d], a ; save movement byte 2
+ ld a, [hli]
+ ld [$ff8e], a ; save text ID and flags byte
+ push bc
+ call LoadSprite
+ pop bc
+ dec d
+ ld a, e
+ add $a
+ ld e, a
+ inc c
+ inc c
+ dec b
+ jr nz, .loadSpriteLoop
+ ret
+
+ZeroSpriteStateData::
+; zero C110-C1EF and C210-C2EF
+; C1F0-C1FF and C2F0-C2FF is used for Pikachu
+ ld hl, wSpriteStateData1 + $10
+ ld de, wSpriteStateData2 + $10
+ xor a
+ ld b, 14 * $10
+.loop
+ ld [hli], a
+ ld [de], a
+ inc e
+ dec b
+ jr nz, .loop
+ ret
+
+DisableRegularSprites::
+; initialize all C100-C1FF sprite entries to disabled (other than player's and pikachu)
+ ld hl, wSpriteStateData1 + 1 * $10 + 2
+ ld de, $10
+ ld c, $e
+.loop
+ ld [hl], $ff
+ add hl, de
+ dec c
+ jr nz, .loop
+ ret
+
+LoadSprite::
+ push hl
+ ld b, $0
+ ld hl, wMapSpriteData
+ add hl, bc
+ ld a, [$ff8d]
+ ld [hli], a ; store movement byte 2 in byte 0 of sprite entry
+ ld a, [$ff8e]
+ ld [hl], a ; this appears pointless, since the value is overwritten immediately after
+ ld a, [$ff8e]
+ ld [$ff8d], a
+ and $3f
+ ld [hl], a ; store text ID in byte 1 of sprite entry
+ pop hl
+ ld a, [$ff8d]
+ bit 6, a
+ jr nz, .trainerSprite
+ bit 7, a
+ jr nz, .itemBallSprite
+; for regular sprites
+ push hl
+ ld hl, wMapSpriteExtraData
+ add hl, bc
+; zero both bytes, since regular sprites don't use this extra space
+ xor a
+ ld [hli], a
+ ld [hl], a
+ pop hl
+ ret
+
+.trainerSprite
+ ld a, [hli]
+ ld [$ff8d], a ; save trainer class
+ ld a, [hli]
+ ld [$ff8e], a ; save trainer number (within class)
+ push hl
+ ld hl, wMapSpriteExtraData
+ add hl, bc
+ ld a, [$ff8d]
+ ld [hli], a ; store trainer class in byte 0 of the entry
+ ld a, [$ff8e]
+ ld [hl], a ; store trainer number in byte 1 of the entry
+ pop hl
+ ret
+
+.itemBallSprite
+ ld a, [hli]
+ ld [$ff8d], a ; save item number
+ push hl
+ ld hl, wMapSpriteExtraData
+ add hl, bc
+ ld a, [$ff8d]
+ ld [hli], a ; store item number in byte 0 of the entry
+ xor a
+ ld [hl], a ; zero byte 1, since it is not used
+ pop hl
+ ret