diff options
Diffstat (limited to 'home/overworld.asm')
-rw-r--r-- | home/overworld.asm | 4518 |
1 files changed, 2293 insertions, 2225 deletions
diff --git a/home/overworld.asm b/home/overworld.asm index 0a92355c..3309f1cc 100644 --- a/home/overworld.asm +++ b/home/overworld.asm @@ -1,2225 +1,2293 @@ -EnterMap:: ; 01d7 (0:01d7) -; Load a new map. - ld a, $ff - ld [wJoyIgnore], a - call LoadMapData - callba ClearVariablesAfterLoadingMapData - ld hl, wd72c - bit 0, [hl] ; has the player already made 3 steps since the last battle? - jr z, .skipGivingThreeStepsOfNoRandomBattles - ld a, 3 ; minimum number of steps between battles - ld [wNumberOfNoRandomBattleStepsLeft], a -.skipGivingThreeStepsOfNoRandomBattles - ld hl, wd72e - bit 5, [hl] ; did a battle happen immediately before this? - res 5, [hl] ; unset the "battle just happened" flag - call z, ResetUsingStrengthOutOfBattleBit - call nz, MapEntryAfterBattle - ld hl, wd732 - ld a, [hl] - and 1 << 4 | 1 << 3 ; fly warp or dungeon warp - jr z, .didNotEnterUsingFlyWarpOrDungeonWarp - callba EnterMapAnim - call UpdateSprites - ld hl, wd732 - res 3, [hl] - ld hl, wd72e - res 4, [hl] - call Func_342a -.didNotEnterUsingFlyWarpOrDungeonWarp - 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 - ld hl, wd126 - set 5, [hl] - set 6, [hl] - xor a - ld [wJoyIgnore], a - -OverworldLoop:: ; 0242 (0:0242) - call DelayFrame -OverworldLoopLessDelay:: ; 0245 (0:0245) - call DelayFrame - call Func_342a - call LoadGBPal - ld a,[wWalkCounter] - and a - jp nz,.moveAhead ; if the player sprite has not yet completed the walking animation - call JoypadOverworld ; get joypad state (which is possibly simulated) - callba SafariZoneCheck - ld a,[wSafariZoneGameOver] - and a - jp nz,WarpFound2 - ld hl,wd72d - bit 3,[hl] - res 3,[hl] - jp nz,WarpFound2 - ld a,[wd732] - and a,1 << 4 | 1 << 3 ; fly warp or dungeon warp - jp nz,HandleFlyWarpOrDungeonWarp - ld a,[W_CUROPPONENT] - and a - jp nz,.newBattle - ld a,[wd730] - bit 7,a ; are we simulating button presses? - jr z,.notSimulating - ld a,[hJoyHeld] - jr .checkIfStartIsPressed -.notSimulating - ld a,[hJoyPressed] -.checkIfStartIsPressed - bit 3,a ; start button - jr z,.startButtonNotPressed -; if START is pressed - xor a - ld [hSpriteIndexOrTextID],a ; start menu text ID - jp .displayDialogue -.startButtonNotPressed - bit 0,a ; A button - jp z,.checkIfDownButtonIsPressed -; if A is pressed - ld a,[wd730] - bit 2,a - jp nz,.noDirectionButtonsPressed - call IsPlayerCharacterBeingControlledByGame - jr nz,.checkForOpponent - call CheckForHiddenObjectOrBookshelfOrCardKeyDoor - 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 -.displayDialogue - predef GetTileAndCoordsInFrontOfPlayer - call UpdateSprites - ld a,[wFlags_0xcd60] - bit 2,a - jr nz,.checkForOpponent - bit 0,a - jr nz,.checkForOpponent - aCoord 8, 9 - ld [wcf0e],a - call DisplayTextID ; display either the start menu or the NPC/sign text - ld a,[wcc47] - and a - jr z,.checkForOpponent - xor a - ld [wcc47],a - jp EnterMap -; predef LoadSAV -; ld a,[W_CURMAP] -; ld [wDestinationMap],a -; call SpecialWarpIn -; ld a,[W_CURMAP] -; call SwitchToMapRomBank ; switch to the ROM bank of the current map -; ld hl,W_CURMAPTILESET -; set 7,[hl] -.checkForOpponent - ld a,[W_CUROPPONENT] - and a - jp nz,.newBattle - jp OverworldLoop -.noDirectionButtonsPressed - call UpdateSprites ; 231c - ld hl,wFlags_0xcd60 - res 2,[hl] - xor a - ld [wd435], a - ld a, $1 - ld a,$01 - ld [wcc4b],a - ld a,[wd528] ; the direction that was pressed last time - and a - jr z, .overworldloop -; if a direction was pressed last time - ld [wd529],a ; save the last direction - xor a - ld [wd528],a ; zero the direction -.overworldloop - jp OverworldLoop -.checkIfDownButtonIsPressed - ld a,[hJoyHeld] ; current joypad state - bit 7,a ; down button - jr z,.checkIfUpButtonIsPressed - ld a,$01 - ld [wSpriteStateData1 + 3],a - ld a,$04 - jr .handleDirectionButtonPress -.checkIfUpButtonIsPressed - bit 6,a ; up button - jr z,.checkIfLeftButtonIsPressed - ld a,$ff - ld [wSpriteStateData1 + 3],a - ld a,$08 - jr .handleDirectionButtonPress -.checkIfLeftButtonIsPressed - bit 5,a ; left button - jr z,.checkIfRightButtonIsPressed - ld a,$ff - ld [wSpriteStateData1 + 5],a - ld a,$02 - jr .handleDirectionButtonPress -.checkIfRightButtonIsPressed - bit 4,a ; right button - jr z,.noDirectionButtonsPressed - ld a,$01 - ld [wSpriteStateData1 + 5],a -.handleDirectionButtonPress - ld [wd52a],a ; new direction - ld a,[wd730] - bit 7,a ; are we simulating button presses? - jr nz,.noDirectionChange ; ignore direction changes if we are - ld a,[wcc4b] - and a - jr z,.noDirectionChange - ld a,[wd52a] ; new direction - ld b,a - ld a,[wd529] ; old direction - cp b - jr z,.noDirectionChange - ld a,$8 - ld [wd434],a -; unlike in red/blue, yellow does not have the 180 degrees odd code - ld hl,wFlags_0xcd60 - set 2,[hl] - xor a - ld [wcc4b],a - ld a,[wd52a] - ld [wd528],a - call NewBattle - jp c,.battleOccurred - jp OverworldLoop -.noDirectionChange - ld a,[wd52a] ; current direction - ld [wd528],a ; save direction - call UpdateSprites - ld a,[wWalkBikeSurfState] - cp a,$02 ; surfing - jr z,.surfing -; not surfing - call CollisionCheckOnLand - jr nc,.noCollision -; collision occurred - push hl - ld hl,wd736 - bit 2,[hl] ; standing on warp flag - pop hl - jp z,OverworldLoop -; collision occurred while standing on a warp - push hl - call ExtraWarpCheck ; sets carry if there is a potential to warp - pop hl - jp c,CheckWarpsCollision - jp OverworldLoop -.surfing - call CollisionCheckOnWater - jp c,OverworldLoop -.noCollision - ld a,$08 - ld [wWalkCounter],a - callab Func_fcc08 - jr .moveAhead2 -.moveAhead - call IsSpinning - call UpdateSprites ; move sprites -.moveAhead2 - ld hl,wFlags_0xcd60 - res 2,[hl] - xor a - ld [wd435],a - call DoBikeSpeedup - 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 - call StepCountCheck - ld a,[wd790] - bit 7,a ; in the safari zone? - jr z,.notSafariZone - callba SafariZoneCheckSteps - ld a,[wSafariZoneGameOver] - and a - jp nz,WarpFound2 -.notSafariZone - ld a,[W_ISINBATTLE] - and a - jp nz,CheckWarpsNoCollision - predef ApplyOutOfBattlePoisonDamage ; also increment daycare mon exp - ld a,[wd12d] - and a - jp nz,HandleBlackOut ; if all pokemon fainted -.newBattle - call NewBattle - ld hl,wd736 - res 2,[hl] ; standing on warp flag - jp nc,CheckWarpsNoCollision ; check for warps if there was no battle -.battleOccurred - ld hl,wd72d - res 6,[hl] - ld hl,W_FLAGS_D733 - res 3,[hl] - ld hl,wd126 - set 5,[hl] - set 6,[hl] - xor a - ld [hJoyHeld],a - ld a,[W_CURMAP] - cp a,CINNABAR_GYM - jr nz,.notCinnabarGym - ld hl,wd79b - set 7,[hl] -.notCinnabarGym - ld hl,wd72e - set 5,[hl] - ld a,[W_CURMAP] - cp a,OAKS_LAB - jp z,.noFaintCheck ; no blacking out if the player lost to the rival in Oak's lab - callab AnyPartyAlive - ld a,d - and a - jr z,.allPokemonFainted -.noFaintCheck - ld c,$0a - call DelayFrames - jp EnterMap -;.allPokemonFainted -; ld a,$ff -; ld [W_ISINBATTLE],a -; call RunMapScript -; jp HandleBlackOut - -StepCountCheck:: ; 0457 (0:0457) - 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 - -; function to determine if there will be a battle and execute it (either a trainer battle or wild battle) -; sets carry if a battle occurred and unsets carry if not -NewBattle:: ; 0480 (0:0480) - ld a,[wd72d] - bit 4,a - jr nz,.noBattle - call IsPlayerCharacterBeingControlledByGame - jr nz,.noBattle ; no battle if the player character is under the game's control - ld a,[wd72e] - bit 4,a - jr nz,.noBattle - ld b, BANK(InitBattle) - ld hl, InitBattle ; 3d:5ff2 - jp Bankswitch -.noBattle - and a - ret - -DoBikeSpeedup:: ; 049d (0:049d) - 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 - ld a,[W_CURMAP] - cp ROUTE_17 ; cycling road - jr nz,.goFaster - ld a,[hJoyHeld] - and a,D_UP | D_LEFT | D_RIGHT - ret nz -.goFaster - call AdvancePlayerSprite - ret - -; check if the player has stepped onto a warp after having not collided -CheckWarpsNoCollision:: ; 04bd (0:04bd) - ld a,[wNumberOfWarps] - and a - jp z,CheckMapConnections - ld b,0 - ld a,[wNumberOfWarps] - ld c,a - ld a,[W_YCOORD] - ld d,a - ld a,[W_XCOORD] - ld e,a - ld hl,wWarpEntries -CheckWarpsNoCollisionLoop:: ; 04d5 (0:04d5) - ld a,[hli] ; check if the warp's Y position matches - cp d - jr nz,CheckWarpsNoCollisionRetry1 - ld a,[hli] ; check if the warp's X position matches - cp e - jr nz,CheckWarpsNoCollisionRetry2 -; if a match was found - push hl - push bc - ld hl,wd736 - set 2,[hl] ; standing on warp flag - callba IsPlayerStandingOnDoorTileOrWarpTile - pop bc - pop hl - jr c,WarpFound1 ; jump if standing on door or warp - push hl - push bc - call ExtraWarpCheck - pop bc - pop hl - jr nc,CheckWarpsNoCollisionRetry2 -; if the extra check passed - ld a,[W_FLAGS_D733] - bit 2,a - jr nz,WarpFound1 - push de - push bc - call Joypad - pop bc - pop de - ld a,[hJoyHeld] - and a,D_DOWN | D_UP | D_LEFT | D_RIGHT - jr z,CheckWarpsNoCollisionRetry2 ; if directional buttons aren't being pressed, do not pass through the warp - jr WarpFound1 - -CheckWarpsNoCollisionRetry1:: ; 050f (0:050f) - inc hl -CheckWarpsNoCollisionRetry2:: ; 0510 (0:0510) - inc hl - inc hl -ContinueCheckWarpsNoCollisionLoop:: ; 0512 (0:0512) - 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:: ; 0706 (0:0706) - ld a,[wNumberOfWarps] - ld c,a - ld hl,wWarpEntries -.loop - ld a,[hli] ; Y coordinate of warp - ld b,a - ld a,[W_YCOORD] - cp b - jr nz,.retry1 - ld a,[hli] ; X coordinate of warp - ld b,a - ld a,[W_XCOORD] - cp b - jr nz,.retry2 - ld a,[hli] - ld [wDestinationWarpID],a - ld a,[hl] - ld [$ff8b],a ; save target map - jr WarpFound2 -.retry1 - inc hl -.retry2 - inc hl - inc hl - dec c - jr nz,.loop - jp OverworldLoop - -WarpFound1:: ; 0735 (0:0735) - ld a,[hli] - ld [wDestinationWarpID],a - ld a,[hli] - ld [$ff8b],a ; save target map - -WarpFound2:: ; 073c (0:073c) - ld a,[wNumberOfWarps] - sub c - ld [wd73b],a ; save ID of used warp - ld a,[W_CURMAP] - ld [wd73c],a - call CheckIfInOutsideMap - jr nz,.indoorMaps -; this is for handling "outside" maps that can't have the 0xFF destination map - ld a,[W_CURMAP] - ld [wLastMap],a - ld a,[W_CURMAPWIDTH] - ld [wd366],a - ld a,[$ff8b] ; destination map number - ld [W_CURMAP],a ; change current map to destination map - cp a,ROCK_TUNNEL_1 - jr nz,.notRockTunnel - ld a,$06 - ld [wMapPalOffset],a - call GBFadeOutToBlack -.notRockTunnel - callab Func_fc5fa ; 3f:45fa - call PlayMapChangeSound - jr .done -; for maps that can have the 0xFF destination map, which means to return to the outside map; not all these maps are necessarily indoors, though -.indoorMaps - ld a,[$ff8b] ; destination map - cp a,$ff - jr z,.goBackOutside -; if not going back to the previous map - ld [W_CURMAP],a ; current map number - callba IsPlayerStandingOnWarpPadOrHole - ld a,[wcd5b] - 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] - jr .skipMapChangeSound -.notWarpPad - call PlayMapChangeSound -.skipMapChangeSound - ld hl,wd736 - res 0,[hl] - res 1,[hl] - callab Func_fc65b ; 3f:465b - jr .done -.goBackOutside - callab Func_fc69a ; 3f:469a - ; continue from here - ld a,[wLastMap] - ld [W_CURMAP],a - call PlayMapChangeSound - xor a - ld [wMapPalOffset],a -.done - ld hl,wd736 - set 0,[hl] ; have the player's sprite step out from the door (if there is one) - call IgnoreInputForHalfSecond - jp EnterMap - -; if no matching warp was found -CheckMapConnections:: ; 05db (0:05db) -.checkWestMap - ld a,[W_XCOORD] - cp a,$ff - jr nz,.checkEastMap - ld a,[W_MAPCONN3PTR] - ld [W_CURMAP],a - ld a,[wd38f] ; new X coordinate upon entering west map - ld [W_XCOORD],a - ld a,[W_YCOORD] - ld c,a - ld a,[wd38e] ; Y adjustment upon entering west map - add c - ld c,a - ld [W_YCOORD],a - ld a,[wd390] ; pointer to upper left corner of map without adjustment for Y position - ld l,a - ld a,[wd391] - ld h,a - srl c - jr z,.savePointer1 -.pointerAdjustmentLoop1 - ld a,[wd38d] ; width of connected map - add a,$06 - ld e,a - ld d,$00 - ld b,$00 - add hl,de - dec c - jr nz,.pointerAdjustmentLoop1 -.savePointer1 - ld a,l - ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section - ld a,h - ld [wCurrentTileBlockMapViewPointer + 1],a - jp .loadNewMap -.checkEastMap - ld b,a - ld a,[wd525] ; map width - cp b - jr nz,.checkNorthMap - ld a,[W_MAPCONN4PTR] - ld [W_CURMAP],a - ld a,[wd39a] ; new X coordinate upon entering east map - ld [W_XCOORD],a - ld a,[W_YCOORD] - ld c,a - ld a,[wd399] ; Y adjustment upon entering east map - add c - ld c,a - ld [W_YCOORD],a - ld a,[wd39b] ; pointer to upper left corner of map without adjustment for Y position - ld l,a - ld a,[wd39c] - ld h,a - srl c - jr z,.savePointer2 -.pointerAdjustmentLoop2 - ld a,[wd398] - add a,$06 - ld e,a - ld d,$00 - ld b,$00 - add hl,de - dec c - jr nz,.pointerAdjustmentLoop2 -.savePointer2 - ld a,l - ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section - ld a,h - ld [wCurrentTileBlockMapViewPointer + 1],a - jp .loadNewMap -.checkNorthMap - ld a,[W_YCOORD] - cp a,$ff - jr nz,.checkSouthMap - ld a,[W_MAPCONN1PTR] - ld [W_CURMAP],a - ld a,[wd378] ; new Y coordinate upon entering north map - ld [W_YCOORD],a - ld a,[W_XCOORD] - ld c,a - ld a,[wd379] ; X adjustment upon entering north map - add c - ld c,a - ld [W_XCOORD],a - ld a,[wd37a] ; pointer to upper left corner of map without adjustment for X position - ld l,a - ld a,[wd37b] - ld h,a - ld b,$00 - srl c - add hl,bc - ld a,l - ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section - ld a,h - ld [wCurrentTileBlockMapViewPointer + 1],a - jp .loadNewMap -.checkSouthMap - ld b,a - ld a,[wd524] - cp b - jr nz,.didNotEnterConnectedMap - ld a,[W_MAPCONN2PTR] - ld [W_CURMAP],a - ld a,[wd383] ; new Y coordinate upon entering south map - ld [W_YCOORD],a - ld a,[W_XCOORD] - ld c,a - ld a,[wd384] ; X adjustment upon entering south map - add c - ld c,a - ld [W_XCOORD],a - ld a,[wd385] ; pointer to upper left corner of map without adjustment for X position - ld l,a - ld a,[wd386] - ld h,a - ld b,$00 - srl c - add hl,bc - ld a,l - ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section - ld a,h - ld [wCurrentTileBlockMapViewPointer + 1],a -.loadNewMap ; load the connected map that was entered - call LoadMapHeader - call Func_2312 ; music - ld b,$09 - call GoPAL_SET -; Since the sprite set shouldn't change, this will just update VRAM slots at -; $C2XE without loading any tile patterns. - callba InitMapSprites - call LoadTileBlockMap - jp OverworldLoopLessDelay -.didNotEnterConnectedMap - jp OverworldLoop - -; function to play a sound when changing maps -PlayMapChangeSound:: ; 08c9 (0:08c9) - aCoord 8, 8 ; upper left tile of the 4x4 square the player's sprite is standing on - cp a,$0b ; door tile in tileset 0 - jr nz,.didNotGoThroughDoor - ld a,(SFX_02_57 - SFX_Headers_02) / 3 - jr .playSound -.didNotGoThroughDoor - ld a,(SFX_02_5c - SFX_Headers_02) / 3 -.playSound - call PlaySound - ld a,[wMapPalOffset] - and a - ret nz - jp GBFadeOutToBlack - -CheckIfInOutsideMap:: ; 08e1 (0:08e1) -; If the player is in an outside map (a town or route), set the z flag - ld a, [W_CURMAPTILESET] - and a ; most towns/routes have tileset 0 (OVERWORLD) - ret z - cp PLATEAU ; Route 23 / Indigo Plateau - ret - -; this function is an extra check that sometimes has to pass in order to warp, beyond just standing on a warp -; the "sometimes" qualification is necessary because of CheckWarpsNoCollision's behavior -; depending on the map, either "function 1" or "function 2" is used for the check -; "function 1" passes when the player is at the edge of the map and is facing towards the outside of the map -; "function 2" passes when the the tile in front of the player is among a certain set -; sets carry if the check passes, otherwise clears carry -ExtraWarpCheck:: ; 08e9 (0:08e9) - ld a, [W_CURMAP] - cp SS_ANNE_3 - jr z, .useFunction1 - cp ROCKET_HIDEOUT_1 - jr z, .useFunction2 - cp ROCKET_HIDEOUT_2 - jr z, .useFunction2 - cp ROCKET_HIDEOUT_4 - jr z, .useFunction2 - cp ROCK_TUNNEL_1 - jr z, .useFunction2 - ld a, [W_CURMAPTILESET] - and a ; outside tileset (OVERWORLD) - jr z, .useFunction2 - cp SHIP ; S.S. Anne tileset - jr z, .useFunction2 - cp SHIP_PORT ; Vermilion Port tileset - jr z, .useFunction2 - cp PLATEAU ; Indigo Plateau tileset - jr z, .useFunction2 -.useFunction1 - ld hl, IsPlayerFacingEdgeOfMap - jr .doBankswitch -.useFunction2 - ld hl, IsWarpTileInFrontOfPlayer -.doBankswitch - ld b, BANK(IsWarpTileInFrontOfPlayer) - jp Bankswitch - -MapEntryAfterBattle:: ; 091f (0:091f) - callba IsPlayerStandingOnWarp ; for enabling warp testing after collisions - ld a,[wMapPalOffset] - and a - jp z,GBFadeInFromWhite - jp LoadGBPal - -HandleBlackOut:: -; For when all the player's pokemon faint. -; Does not print the "blacked out" message. - - call GBFadeOutToBlack - ld a, $08 - 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 - call SpecialWarpIn - call Func_2312 - jp SpecialEnterMap - -StopMusic:: - ld [wMusicHeaderPointer], a - ld a, $ff - ld [wc0ee], a - call PlaySound -.wait - ld a, [wMusicHeaderPointer] - and a - jr nz, .wait - jp StopAllSounds - -HandleFlyWarpOrDungeonWarp:: ; 0794 (0:0794) - call UpdateSprites - call Delay3 - xor a - ld [wBattleResult], a - ld [wWalkBikeSurfState], a - ld [W_ISINBATTLE], 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 [$2000], a - call SpecialWarpIn - jp SpecialEnterMap - -LeaveMapAnim:: ; 07bc (0:07bc) - ld b, BANK(_LeaveMapAnim) - ld hl, _LeaveMapAnim - jp Bankswitch - -LoadPlayerSpriteGraphics:: -; Load sprite graphics based on whether the player is standing, biking, or surfing. - - ; 0: standing - ; 1: biking - ; 2: surfing - - ld a, [wWalkBikeSurfState] - dec a - jr z, .ridingBike - - ld a, [hTilesetType] - and a - jr nz, .determineGraphics - jr .startWalking - -.ridingBike - ; If the bike can't be used, - ; start walking instead. - call IsBikeRidingAllowed - jr c, .determineGraphics - -.startWalking - xor a - ld [wWalkBikeSurfState], a - ld [wWalkBikeSurfStateCopy], a - jp LoadWalkingPlayerSpriteGraphics - -.determineGraphics - ld a, [wWalkBikeSurfState] - and a - jp z, LoadWalkingPlayerSpriteGraphics - dec a - jp z, LoadBikePlayerSpriteGraphics - dec a - jp z, LoadSurfingPlayerSpriteGraphics - jp LoadWalkingPlayerSpriteGraphics - -IsBikeRidingAllowed:: -; The bike can be used on Route 23 and Indigo Plateau, -; or maps with tilesets in BikeRidingTilesets. -; Return carry if biking is allowed. - - ld a, [W_CURMAP] - cp ROUTE_23 - jr z, .allowed - cp INDIGO_PLATEAU - jr z, .allowed - - ld a, [W_CURMAPTILESET] - ld b, a - ld hl, BikeRidingTilesets -.loop - ld a, [hli] - cp b - jr z, .allowed - inc a - jr nz, .loop - and a - ret - -.allowed - scf - ret - -INCLUDE "data/bike_riding_tilesets.asm" - -; load the tile pattern data of the current tileset into VRAM -LoadTilesetTilePatternData:: ; 09e8 (0:09e8) - ld a,[W_TILESETGFXPTR] - ld l,a - ld a,[W_TILESETGFXPTR + 1] - ld h,a - ld de,vTileset - ld bc,$600 - ld a,[W_TILESETBANK] - jp FarCopyData2 - -; 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:: ; 09fc (0:09fc) -; fill C6E8-CBFB with the background tile - ld hl,wOverworldMap - ld a,[wd3ad] ; background tile number - ld d,a - ld bc,$0514 -.backgroundTileLoop - ld a,d - ld [hli],a - dec bc - ld a,c - or b - jr nz,.backgroundTileLoop -; 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 - ld a,[W_CURMAPWIDTH] - ld [$ff8c],a - add a,$06 ; border (east and west) - ld [$ff8b],a ; map width + border - ld b,$00 - ld c,a -; make space for north border (next 3 lines) - add hl,bc - add hl,bc - add hl,bc - ld c,$03 - add hl,bc ; this puts us past the (west) border - ld a,[W_MAPDATAPTR] ; tile map pointer - ld e,a - ld a,[W_MAPDATAPTR + 1] - ld d,a ; de = tile map pointer - ld a,[W_CURMAPHEIGHT] - ld b,a -.rowLoop ; copy one row each iteration - push hl - ld a,[$ff8c] ; map width (without border) - ld c,a -.rowInnerLoop - ld a,[de] - inc de - ld [hli],a - dec c - jr nz,.rowInnerLoop -; add the map width plus the border to the base address of the current row to get the next row's address - pop hl - ld a,[$ff8b] ; map width + border - add l - ld l,a - jr nc,.noCarry - inc h -.noCarry - dec b - jr nz,.rowLoop -.northConnection - ld a,[W_MAPCONN1PTR] - cp a,$ff - jr z,.southConnection - call SwitchToMapRomBank - ld a,[wd372] - ld l,a - ld a,[wd373] - ld h,a - ld a,[wd374] - ld e,a - ld a,[wd375] - ld d,a - ld a,[wd376] - ld [$ff8b],a - ld a,[wd377] - ld [$ff8c],a - call LoadNorthSouthConnectionsTileMap -.southConnection - ld a,[W_MAPCONN2PTR] - cp a,$ff - jr z,.westConnection - call SwitchToMapRomBank - ld a,[wd37d] - ld l,a - ld a,[wd37e] - ld h,a - ld a,[wd37f] - ld e,a - ld a,[wd380] - ld d,a - ld a,[wd381] - ld [$ff8b],a - ld a,[wd382] - ld [$ff8c],a - call LoadNorthSouthConnectionsTileMap -.westConnection - ld a,[W_MAPCONN3PTR] - cp a,$ff - jr z,.eastConnection - call SwitchToMapRomBank - ld a,[wd388] - ld l,a - ld a,[wd389] - ld h,a - ld a,[wd38a] - ld e,a - ld a,[wd38b] - ld d,a - ld a,[wd38c] - ld b,a - ld a,[wd38d] - ld [$ff8b],a - call LoadEastWestConnectionsTileMap -.eastConnection - ld a,[W_MAPCONN4PTR] - cp a,$ff - jr z,.done - call SwitchToMapRomBank - ld a,[wd393] - ld l,a - ld a,[wd394] - ld h,a - ld a,[wd395] - ld e,a - ld a,[wd396] - ld d,a - ld a,[wd397] - ld b,a - ld a,[wd398] - ld [$ff8b],a - call LoadEastWestConnectionsTileMap -.done - ret - -LoadNorthSouthConnectionsTileMap:: ; 0ade (0:0ade) - ld c,$03 -.loop - push de - push hl - ld a,[$ff8b] ; width of connection - ld b,a -.innerLoop - ld a,[hli] - ld [de],a - inc de - dec b - jr nz,.innerLoop - pop hl - pop de - ld a,[$ff8c] ; width of connected map - add l - ld l,a - jr nc,.noCarry1 - inc h -.noCarry1 - ld a,[W_CURMAPWIDTH] - add a,$06 - add e - ld e,a - jr nc,.noCarry2 - inc d -.noCarry2 - dec c - jr nz,.loop - ret - -LoadEastWestConnectionsTileMap:: ; 0b02 (0:0b02) - push hl - push de - ld c,$03 -.innerLoop - ld a,[hli] - ld [de],a - inc de - dec c - jr nz,.innerLoop - pop de - pop hl - ld a,[$ff8b] ; width of connected map - add l - ld l,a - jr nc,.noCarry1 - inc h -.noCarry1 - ld a,[W_CURMAPWIDTH] - add a,$06 - add e - ld e,a - jr nc,.noCarry2 - inc d -.noCarry2 - dec b - jr nz,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 -IsSpriteOrSignInFrontOfPlayer:: ; 0b23 (0:0b23) - xor a - ld [hSpriteIndexOrTextID],a - ld a,[wd4b0] ; number of signs in the map - and a - jr z,.extendRangeOverCounter -; if there are signs - predef GetTileAndCoordsInFrontOfPlayer ; get the coordinates in front of the player in de - ld hl,wd4b1 ; start of sign coordinates - ld a,[wd4b0] ; 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,wd4d1 ; 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 - 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 -.extendRangeOverCounter - predef GetTileAndCoordsInFrontOfPlayer ; get the tile in front of the player in c - ld hl,W_TILESETTALKINGOVERTILES ; list of tiles that extend talking range (counter tiles) - ld b,$03 - ld d,$20 ; talking range in pixels (long range) -.counterTilesLoop - ld a,[hli] - cp c - jr z,IsSpriteInFrontOfPlayer2 ; jumps if the tile in front of the player is a counter tile - 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] -IsSpriteInFrontOfPlayer:: ; 0b6b (0:0b6b) - ld d,$10 ; talking range in pixels (normal range) -IsSpriteInFrontOfPlayer2:: ; 0b6d (0:0b6d) - ld bc,$3c40 ; Y and X position of player sprite - ld a,[wSpriteStateData1 + 9] ; direction the player is facing -.checkIfPlayerFacingUp - cp a,$04 - jr nz,.checkIfPlayerFacingDown -; facing up - ld a,b - sub d - ld b,a - ld a,$08 - jr .doneCheckingDirection -.checkIfPlayerFacingDown - cp a,$00 - jr nz,.checkIfPlayerFacingRight -; facing down - ld a,b - add d - ld b,a - ld a,$04 - jr .doneCheckingDirection -.checkIfPlayerFacingRight - cp a,$0c - jr nz,.playerFacingLeft -; facing right - ld a,c - add d - ld c,a - ld a,$01 - jr .doneCheckingDirection -.playerFacingLeft -; facing left - ld a,c - sub d - ld c,a - ld a,$02 -.doneCheckingDirection - ld [wd52a],a - ld a,[W_NUMSPRITES] ; number of sprites - and a - ret z -; if there are sprites - ld hl,wSpriteStateData1 + $10 - ld d,a - ld e,$01 -.spriteLoop - push hl - ld a,[hli] ; image (0 if no sprite) - and a - jr z,.nextSprite - inc l - ld a,[hli] ; sprite visibility - inc a - jr z,.nextSprite - inc l - ld a,[hli] ; Y location - cp b - jr nz,.nextSprite - inc l - ld a,[hl] ; X location - cp c - jr z,.foundSpriteInFrontOfPlayer -.nextSprite - pop hl - ld a,l - add a,$10 - ld l,a - inc e - dec d - jr nz,.spriteLoop - ret -.foundSpriteInFrontOfPlayer - pop hl - ld a,l - and a,$f0 - inc a - ld l,a - set 7,[hl] - ld a,e - ld [hSpriteIndexOrTextID],a - ret - -; function to check if the player will jump down a ledge and check if the tile ahead is passable (when not surfing) -; sets the carry flag if there is a collision, and unsets it if there isn't a collision -CollisionCheckOnLand:: ; 0bd1 (0:0bd1) - ld a,[wd736] - bit 6,a ; is the player jumping? - jr nz,.noCollision -; if not jumping a ledge - ld a,[wSimulatedJoypadStatesIndex] - and a - jr nz,.noCollision ; no collisions when the player's movements are being controlled by the game - ld a,[wd52a] ; the direction that the player is trying to go in - 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,.collision - xor a - ld [hSpriteIndexOrTextID],a - call IsSpriteInFrontOfPlayer ; check for sprite collisions again? when does the above check fail to detect a sprite collision? - ld a,[hSpriteIndexOrTextID] - and a ; was there a sprite collision? - jr nz,.collision -; if no sprite collision - ld hl,TilePairCollisionsLand - call CheckForJumpingAndTilePairCollisions - jr c,.collision - call CheckTilePassable - jr nc,.noCollision -.collision - ld a,[wc02a] - cp a,(SFX_02_5b - SFX_Headers_02) / 3 ; check if collision sound is already playing - jr z,.setCarry - ld a,(SFX_02_5b - SFX_Headers_02) / 3 - call PlaySound ; play collision sound (if it's not already playing) -.setCarry - scf - ret -.noCollision - and a - ret - -; function that checks if the tile in front of the player is passable -; clears carry if it is, sets carry if not -CheckTilePassable:: ; 0c10 (0:0c10) - predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player - ld a,[wTileInFrontOfPlayer] ; tile in front of player - ld c,a - ld hl,W_TILESETCOLLISIONPTR ; 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 a,$ff - jr z,.tileNotPassable - cp c - ret z - jr .loop -.tileNotPassable - scf - ret - -; check if the player is going to jump down a small ledge -; and check for collisions that only occur between certain pairs of tiles -; Input: hl - address of directional collision data -; sets carry if there is a collision and unsets carry if not -CheckForJumpingAndTilePairCollisions:: ; 0c2a (0:0c2a) - push hl - 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 - pop bc - pop de - pop hl - and a - ld a,[wd736] - bit 6,a ; is the player jumping? - ret nz -; if not jumping - -CheckForTilePairCollisions2:: ; 0c44 (0:0c44) - aCoord 8, 9 ; tile the player is on - ld [wcf0e],a - -CheckForTilePairCollisions:: ; 0c4a (0:0c4a) - ld a,[wTileInFrontOfPlayer] - ld c,a -.tilePairCollisionLoop - ld a,[W_CURMAPTILESET] ; tileset number - ld b,a - ld a,[hli] - cp a,$ff - jr z,.noMatch - cp b - jr z,.tilesetMatches - inc hl -.retry - inc hl - jr .tilePairCollisionLoop -.tilesetMatches - ld a,[wcf0e] ; tile the player is on - ld b,a - ld a,[hl] - cp b - jr z,.currentTileMatchesFirstInPair - inc hl - ld a,[hl] - cp b - jr z,.currentTileMatchesSecondInPair - jr .retry -.currentTileMatchesFirstInPair - inc hl - ld a,[hl] - cp c - jr z,.foundMatch - jr .tilePairCollisionLoop -.currentTileMatchesSecondInPair - dec hl - ld a,[hli] - cp c - inc hl - jr nz,.tilePairCollisionLoop -.foundMatch - scf - ret -.noMatch - and a - ret - -; FORMAT: tileset number, tile 1, tile 2 -; terminated by 0xFF -; these entries indicate that the player may not cross between tile 1 and tile 2 -; it's mainly used to simulate differences in elevation - -TilePairCollisionsLand:: ; 0c7e (0:0c7e) - db CAVERN, $20, $05 - db CAVERN, $41, $05 - db FOREST, $30, $2E - db CAVERN, $2A, $05 - db CAVERN, $05, $21 - db FOREST, $52, $2E - db FOREST, $55, $2E - db FOREST, $56, $2E - db FOREST, $20, $2E - db FOREST, $5E, $2E - db FOREST, $5F, $2E - db $FF - -TilePairCollisionsWater:: ; 0ca0 (0:0ca0) - db FOREST, $14, $2E - db FOREST, $48, $2E - db CAVERN, $14, $05 - db $FF - -; this builds a tile map from the tile block map based on the current X/Y coordinates of the player's character -LoadCurrentMapView:: ; 0caa (0:0caa) - ld a,[H_LOADEDROMBANK] - push af - ld a,[W_TILESETBANK] ; tile data ROM bank - ld [H_LOADEDROMBANK],a - ld [$2000],a ; 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] - ld d,a - ld hl,wTileMapBackup - ld b,$05 -.rowLoop ; each loop iteration fills in one row of tile blocks - push hl - push de - ld c,$06 -.rowInnerLoop ; loop to draw each tile block of the current row - push bc - push de - push hl - ld a,[de] - ld c,a ; tile block number - call DrawTileBlock - pop hl - pop de - pop bc - inc hl - inc hl - inc hl - inc hl - inc de - dec c - jr nz,.rowInnerLoop -; update tile block map pointer to next row's address - pop de - ld a,[W_CURMAPWIDTH] - add a,$06 - add e - ld e,a - jr nc,.noCarry - inc d -.noCarry -; update tile map pointer to next row's address - pop hl - ld a,$60 - add l - ld l,a - jr nc,.noCarry2 - inc h -.noCarry2 - dec b - jr nz,.rowLoop - ld hl,wTileMapBackup - ld bc,$0000 -.adjustForYCoordWithinTileBlock - ld a,[W_YBLOCKCOORD] - and a - jr z,.adjustForXCoordWithinTileBlock - ld bc,$0030 - add hl,bc -.adjustForXCoordWithinTileBlock - ld a,[W_XBLOCKCOORD] - and a - jr z,.copyToVisibleAreaBuffer - ld bc,$0002 - add hl,bc -.copyToVisibleAreaBuffer - ld de,wTileMap ; base address for the tiles that are directly transfered to VRAM during V-blank - ld b,$12 -.rowLoop2 - ld c,$14 -.rowInnerLoop2 - ld a,[hli] - ld [de],a - inc de - dec c - jr nz,.rowInnerLoop2 - ld a,$04 - add l - ld l,a - jr nc,.noCarry3 - inc h -.noCarry3 - dec b - jr nz,.rowLoop2 - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a ; restore previous ROM bank - ret - -AdvancePlayerSprite:: ; 0b7f (0:0b7f) - ld a,[wUpdateSpritesEnabled] - push af - ld a,$FF - ld [wUpdateSpritesEnabled],a - ld hl, _AdvancePlayerSorite ; 3c:410c - ld b, BANK(_AdvancePlayerSprite) - call Bankswitch - pop af - ld [wUpdateSpritesEnabled],a - 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:: ; 0e65 (0:0e65) - ld a,[de] - add a,$01 - ld [de],a - ret nc - inc de - ld a,[de] - inc a - ld [de],a - ret - -MoveTileBlockMapPointerWest:: ; 0e6f (0:0e6f) - ld a,[de] - sub a,$01 - ld [de],a - ret nc - inc de - ld a,[de] - dec a - ld [de],a - ret - -MoveTileBlockMapPointerSouth:: ; 0e79 (0:0e79) - add a,$06 - 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:: ; 0e85 (0:0e85) - add a,$06 - ld b,a - ld a,[de] - sub b - ld [de],a - ret nc - inc de - ld a,[de] - dec a - ld [de],a - ret - -; the following 6 functions are used to tell the V-blank handler to redraw -; the portion of the map that was newly exposed due to the player's movement - -ScheduleNorthRowRedraw:: ; 0e91 (0:0e91) - hlCoord 0, 0 - call CopyToScreenEdgeTiles - ld a,[wMapViewVRAMPointer] - ld [H_SCREENEDGEREDRAWADDR],a - ld a,[wMapViewVRAMPointer + 1] - ld [H_SCREENEDGEREDRAWADDR + 1],a - ld a,REDRAWROW - ld [H_SCREENEDGEREDRAW],a - ret - -CopyToScreenEdgeTiles:: ; 0ea6 (0:0ea6) - ld de,wScreenEdgeTiles - ld c,2 * 20 -.loop - ld a,[hli] - ld [de],a - inc de - dec c - jr nz,.loop - ret - -ScheduleSouthRowRedraw:: ; 0eb2 (0:0eb2) - hlCoord 0, 16 - call CopyToScreenEdgeTiles - ld a,[wMapViewVRAMPointer] - ld l,a - ld a,[wMapViewVRAMPointer + 1] - ld h,a - ld bc,$0200 - add hl,bc - ld a,h - and a,$03 - or a,$98 - ld [H_SCREENEDGEREDRAWADDR + 1],a - ld a,l - ld [H_SCREENEDGEREDRAWADDR],a - ld a,REDRAWROW - ld [H_SCREENEDGEREDRAW],a - ret - -ScheduleEastColumnRedraw:: ; 0ed3 (0:0ed3) - hlCoord 18, 0 - call ScheduleColumnRedrawHelper - ld a,[wMapViewVRAMPointer] - ld c,a - and a,$e0 - ld b,a - ld a,c - add a,18 - and a,$1f - or b - ld [H_SCREENEDGEREDRAWADDR],a - ld a,[wMapViewVRAMPointer + 1] - ld [H_SCREENEDGEREDRAWADDR + 1],a - ld a,REDRAWCOL - ld [H_SCREENEDGEREDRAW],a - ret - -ScheduleColumnRedrawHelper:: ; 0ef2 (0:0ef2) - ld de,wScreenEdgeTiles - ld c,$12 -.loop - ld a,[hli] - ld [de],a - inc de - ld a,[hl] - ld [de],a - inc de - ld a,19 - add l - ld l,a - jr nc,.noCarry - inc h -.noCarry - dec c - jr nz,.loop - ret - -ScheduleWestColumnRedraw:: ; 0f08 (0:0f08) - hlCoord 0, 0 - call ScheduleColumnRedrawHelper - ld a,[wMapViewVRAMPointer] - ld [H_SCREENEDGEREDRAWADDR],a - ld a,[wMapViewVRAMPointer + 1] - ld [H_SCREENEDGEREDRAWADDR + 1],a - ld a,REDRAWCOL - ld [H_SCREENEDGEREDRAW],a - ret - -; function to write the tiles that make up a tile block to memory -; Input: c = tile block ID, hl = destination address -DrawTileBlock:: ; 0f1d (0:0f1d) - push hl - ld a,[W_TILESETBLOCKSPTR] ; pointer to tiles - ld l,a - ld a,[W_TILESETBLOCKSPTR + 1] - ld h,a - ld a,c - swap a - ld b,a - and a,$f0 - ld c,a - ld a,b - and a,$0f - ld b,a ; bc = tile block ID * 0x10 - add hl,bc - ld d,h - ld e,l ; de = address of the tile block's tiles - pop hl - ld c,$04 ; 4 loop iterations -.loop ; each loop iteration, write 4 tile numbers - push bc - ld a,[de] - ld [hli],a - inc de - ld a,[de] - ld [hli],a - inc de - ld a,[de] - ld [hli],a - inc de - ld a,[de] - ld [hl],a - inc de - ld bc,$0015 - add hl,bc - pop bc - dec c - jr nz,.loop - ret - -; function to update joypad state and simulate button presses -JoypadOverworld:: ; 0f4d (0:0f4d) - xor a - ld [wSpriteStateData1 + 3],a - ld [wSpriteStateData1 + 5],a - call RunMapScript - call Joypad - ld a,[W_FLAGS_D733] - bit 3,a ; check if a trainer wants a challenge - jr nz,.notForcedDownwards - ld a,[W_CURMAP] - cp a,ROUTE_17 ; Cycling Road - jr nz,.notForcedDownwards - ld a,[hJoyHeld] - and a,D_DOWN | D_UP | D_LEFT | D_RIGHT | B_BUTTON | A_BUTTON - jr nz,.notForcedDownwards - 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 - ld a,[wd730] - bit 7,a - ret z -; if simulating button presses - ld a,[hJoyHeld] - ld b,a - 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 a,$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] - ld [hJoyHeld],a ; store simulated button press in joypad state - and a - ret nz - ld [hJoyPressed],a - ld [hJoyReleased],a - ret -; if done simulating button presses -.doneSimulating - xor a - ld [wWastedByteCD3A],a - ld [wSimulatedJoypadStatesIndex],a - ld [wSimulatedJoypadStatesEnd],a - ld [wJoyIgnore],a - ld [hJoyHeld],a - ld hl,wd736 - ld a,[hl] - and a,$f8 - ld [hl],a - ld hl,wd730 - res 7,[hl] - 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. -CollisionCheckOnWater:: ; 0fb7 (0:0fb7) - ld a,[wd730] - bit 7,a - jp nz,.noCollision ; return and clear carry if button presses are being simulated - ld a,[wd52a] ; the direction that the player is trying to go in - 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? - ld hl,TilePairCollisionsWater - call CheckForJumpingAndTilePairCollisions - jr c,.collision - predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player (puts it in c and [wTileInFrontOfPlayer]) - ld a,[wTileInFrontOfPlayer] ; tile in front of player - cp a,$14 ; water tile - jr z,.noCollision ; keep surfing if it's a water tile - cp a,$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 a,$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,W_TILESETCOLLISIONPTR ; pointer to list of passable tiles - ld a,[hli] - ld h,[hl] - ld l,a -.loop - ld a,[hli] - cp a,$ff - jr z,.collision - cp c - jr z,.stopSurfing ; stop surfing if the tile is passable - jr .loop -.collision - ld a,[wc02a] - cp a,(SFX_02_5b - SFX_Headers_02) / 3 ; check if collision sound is already playing - jr z,.setCarry - ld a,(SFX_02_5b - SFX_Headers_02) / 3 - call PlaySound ; play collision sound (if it's not already playing) -.setCarry - scf - jr .done -.noCollision - and a -.done - ret -.stopSurfing - xor a - ld [wWalkBikeSurfState],a - call LoadPlayerSpriteGraphics - call PlayDefaultMusic - jr .noCollision -.checkIfVermilionDockTileset - ld a, [W_CURMAPTILESET] ; 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 - -; function to run the current map's script -RunMapScript:: ; 101b (0:101b) - push hl - push de - push bc - callba TryPushingBoulder - ld a,[wFlags_0xcd60] - bit 1,a ; play boulder dust animation - jr z,.afterBoulderEffect - callba DoBoulderDustAnimation -.afterBoulderEffect - pop bc - pop de - pop hl - call RunNPCMovementScript - ld a,[W_CURMAP] ; current map number - call SwitchToMapRomBank ; change to the ROM bank the map's data is in - ld hl,W_MAPSCRIPTPTR - ld a,[hli] - ld h,[hl] - ld l,a - ld de,.return - push de - jp [hl] ; jump to script -.return - ret - -LoadWalkingPlayerSpriteGraphics:: ; 104d (0:104d) - ld de,RedSprite ; $4180 - ld hl,vNPCSprites - jr LoadPlayerSpriteGraphicsCommon - -LoadSurfingPlayerSpriteGraphics:: ; 1055 (0:1055) - ld de,SeelSprite - ld hl,vNPCSprites - jr LoadPlayerSpriteGraphicsCommon - -LoadBikePlayerSpriteGraphics:: ; 105d (0:105d) - ld de,RedCyclingSprite - ld hl,vNPCSprites - -LoadPlayerSpriteGraphicsCommon:: ; 1063 (0:1063) - push de - push hl - ld bc,(BANK(RedSprite) << 8) + $0c - call CopyVideoData - pop hl - pop de - ld a,$c0 - add e - ld e,a - jr nc,.noCarry - inc d -.noCarry - set 3,h - ld bc,$050c - jp CopyVideoData - -; function to load data from the map header -LoadMapHeader:: ; 107c (0:107c) - callba MarkTownVisitedAndLoadMissableObjects - ld a,[W_CURMAPTILESET] - ld [wd119],a - ld a,[W_CURMAP] - call SwitchToMapRomBank - ld a,[W_CURMAPTILESET] - ld b,a - res 7,a - ld [W_CURMAPTILESET],a - ld [$ff8b],a - bit 7,b - ret nz - ld hl,MapHeaderPointers - ld a,[W_CURMAP] - 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 -; copy the first 10 bytes (the fixed area) of the map data to D367-D370 - ld de,W_CURMAPTILESET - ld c,$0a -.copyFixedHeaderLoop - ld a,[hli] - ld [de],a - inc de - dec c - jr nz,.copyFixedHeaderLoop -; initialize all the connected maps to disabled at first, before loading the actual values - ld a,$ff - ld [W_MAPCONN1PTR],a - ld [W_MAPCONN2PTR],a - ld [W_MAPCONN3PTR],a - ld [W_MAPCONN4PTR],a -; copy connection data (if any) to WRAM - ld a,[W_MAPCONNECTIONS] - ld b,a -.checkNorth - bit 3,b - jr z,.checkSouth - ld de,W_MAPCONN1PTR - call CopyMapConnectionHeader -.checkSouth - bit 2,b - jr z,.checkWest - ld de,W_MAPCONN2PTR - call CopyMapConnectionHeader -.checkWest - bit 1,b - jr z,.checkEast - ld de,W_MAPCONN3PTR - call CopyMapConnectionHeader -.checkEast - bit 0,b - jr z,.getObjectDataPointer - ld de,W_MAPCONN4PTR - call CopyMapConnectionHeader -.getObjectDataPointer - ld a,[hli] - ld [wd3a9],a - ld a,[hli] - ld [wd3aa],a - push hl - ld a,[wd3a9] - ld l,a - ld a,[wd3aa] - ld h,a ; hl = base of object data - ld de,wd3ad ; background tile ID - ld a,[hli] - ld [de],a ; save background tile ID -.loadWarpData - ld a,[hli] - ld [wNumberOfWarps],a - and a - jr z,.loadSignData - ld c,a - ld de,wWarpEntries -.warpLoop ; one warp per loop iteration - ld b,$04 -.warpInnerLoop - ld a,[hli] - ld [de],a - inc de - dec b - jr nz,.warpInnerLoop - dec c - jr nz,.warpLoop -.loadSignData - ld a,[hli] ; number of signs - ld [wd4b0],a ; save the number of signs - and a ; are there any signs? - jr z,.loadSpriteData ; if not, skip this - ld c,a - ld de,wd4d1 ; base address of sign text IDs - ld a,d - ld [$ff95],a - ld a,e - ld [$ff96],a - ld de,wd4b1 ; base address of sign coordinates -.signLoop - ld a,[hli] - ld [de],a - inc de - ld a,[hli] - ld [de],a - inc de - push de - ld a,[$ff95] - ld d,a - ld a,[$ff96] - ld e,a - ld a,[hli] - ld [de],a - inc de - ld a,d - ld [$ff95],a - ld a,e - ld [$ff96],a - pop de - dec c - jr nz,.signLoop -.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 [W_NUMSPRITES],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,[W_NUMSPRITES] ; 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 [$ff8d],a ; save movement byte 2 - ld a,[hli] - ld [$ff8e],a ; save text ID and flags byte - push bc - push hl - ld b,$00 - ld hl,W_MAPSPRITEDATA - 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 a,$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 - jr .regularSprite -.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,W_MAPSPRITEEXTRADATA - 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 - jr .nextSprite -.itemBallSprite - ld a,[hli] - ld [$ff8d],a ; save item number - push hl - ld hl,W_MAPSPRITEEXTRADATA - 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 - jr .nextSprite -.regularSprite - push hl - ld hl,W_MAPSPRITEEXTRADATA - 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 -.finishUp - predef LoadTilesetHeader - 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,[W_CURMAPHEIGHT] ; map height in 4x4 tile blocks - add a ; double it - ld [wd524],a ; store map height in 2x2 tile blocks - ld a,[W_CURMAPWIDTH] ; map width in 4x4 tile blocks - add a ; double it - ld [wd525],a ; map width in 2x2 tile blocks - ld a,[W_CURMAP] - ld c,a - ld b,$00 - ld a,[H_LOADEDROMBANK] - push af - ld a, BANK(MapSongBanks) - ld [H_LOADEDROMBANK],a - ld [$2000],a - ld hl, MapSongBanks - add hl,bc - add hl,bc - ld a,[hli] - ld [wd35b],a ; music 1 - ld a,[hl] - ld [wd35c],a ; music 2 - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -; function to copy map connection data from ROM to WRAM -; Input: hl = source, de = destination -CopyMapConnectionHeader:: ; 1238 (0:1238) - ld c,$0b -.loop - ld a,[hli] - ld [de],a - inc de - dec c - jr nz,.loop - ret - -; function to load map data -LoadMapData:: ; 1241 (0:1241) - ld a,[H_LOADEDROMBANK] - push af - call DisableLCD - ld a,$98 - ld [wMapViewVRAMPointer + 1],a - xor a - ld [wMapViewVRAMPointer],a - ld [hSCY],a - ld [hSCX],a - ld [wWalkCounter],a - ld [wd119],a - ld [wWalkBikeSurfStateCopy],a - ld [W_SPRITESETID],a - call LoadTextBoxTilePatterns - call LoadMapHeader - callba InitMapSprites ; load tile pattern data for sprites - call LoadTileBlockMap - call LoadTilesetTilePatternData - call LoadCurrentMapView -; copy current map view to VRAM - ld hl,wTileMap - ld de,vBGMap0 - ld b,18 -.vramCopyLoop - ld c,20 -.vramCopyInnerLoop - ld a,[hli] - ld [de],a - inc e - dec c - jr nz,.vramCopyInnerLoop - ld a,32 - 20 - add e - ld e,a - jr nc,.noCarry - inc d -.noCarry - dec b - jr nz,.vramCopyLoop - ld a,$01 - ld [wUpdateSpritesEnabled],a - call EnableLCD - ld b,$09 - call GoPAL_SET - call LoadPlayerSpriteGraphics - ld a,[wd732] - and a,1 << 4 | 1 << 3 ; fly warp or dungeon warp - jr nz,.restoreRomBank - ld a,[W_FLAGS_D733] - bit 1,a - jr nz,.restoreRomBank - call Func_235f ; music related - call Func_2312 ; music related -.restoreRomBank - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -; function to switch to the ROM bank that a map is stored in -; Input: a = map number -SwitchToMapRomBank:: ; 12bc (0:12bc) - push hl - push bc - ld c,a - ld b,$00 - ld a,Bank(MapHeaderBanks) - call BankswitchHome ; switch to ROM bank 3 - 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 [$2000],a ; switch to map ROM bank - pop bc - pop hl - ret - -IgnoreInputForHalfSecond: ; 12da (0:12da) - ld a, 30 - ld [wIgnoreInputCounter], a - ld hl, wd730 - ld a, [hl] - or $26 - ld [hl], a ; set ignore input bit - ret - -ResetUsingStrengthOutOfBattleBit: ; 12e7 (0:12e7) - ld hl, wd728 - res 0, [hl] - ret - -ForceBikeOrSurf:: ; 12ed (0:12ed) - ld b, BANK(RedSprite) - ld hl, LoadPlayerSpriteGraphics - call Bankswitch - jp PlayDefaultMusic ; update map/player state? - -; Handle the player jumping down -; a ledge in the overworld. -HandleMidJump:: ; 0fe1 (0:0fe1) - ld a,[wd736] - bit 7,a ; jumping down a ledge? - ret z - ld b, BANK(_HandleMidJump) - ld hl, _HandleMidJump - jp Bankswitch - -IsSpinning:: ; 0ff0 (0:0ff0) - ld a,[wd736] - bit 7,a - ret z ; no spinning - ld b, BANK(LoadSpinnerArrowTiles); spin while moving - ld hl,LoadSpinnerArrowTiles ; 11:5077 - jp Bankswitch - -Func_0ffe:: ; 0ffe (0:0ffe) - ld hl, Func_fcf0c ; 3f:4f0c - ld b, BANK(Func_fcf0c) - jp Bankswitch +EnterMap:: ; 01d7 (0:01d7)
+; Load a new map.
+ ld a, $ff
+ ld [wJoyIgnore], a
+ call LoadMapData
+ callba ClearVariablesAfterLoadingMapData
+ ld hl, wd72c
+ bit 0, [hl] ; has the player already made 3 steps since the last battle?
+ jr z, .skipGivingThreeStepsOfNoRandomBattles
+ ld a, 3 ; minimum number of steps between battles
+ ld [wNumberOfNoRandomBattleStepsLeft], a
+.skipGivingThreeStepsOfNoRandomBattles
+ ld hl, wd72e
+ bit 5, [hl] ; did a battle happen immediately before this?
+ res 5, [hl] ; unset the "battle just happened" flag
+ call z, ResetUsingStrengthOutOfBattleBit
+ call nz, MapEntryAfterBattle
+ ld hl, wd732
+ ld a, [hl]
+ and 1 << 4 | 1 << 3 ; fly warp or dungeon warp
+ jr z, .didNotEnterUsingFlyWarpOrDungeonWarp
+ callba EnterMapAnim
+ call UpdateSprites
+ ld hl, wd732
+ res 3, [hl]
+ ld hl, wd72e
+ res 4, [hl]
+ call Func_342a
+.didNotEnterUsingFlyWarpOrDungeonWarp
+ 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
+ ld hl, wd126
+ set 5, [hl]
+ set 6, [hl]
+ xor a
+ ld [wJoyIgnore], a
+
+OverworldLoop:: ; 0242 (0:0242)
+ call DelayFrame
+OverworldLoopLessDelay:: ; 0245 (0:0245)
+ call DelayFrame
+ call Func_342a
+ call LoadGBPal
+ ld a,[wWalkCounter]
+ and a
+ jp nz,.moveAhead ; if the player sprite has not yet completed the walking animation
+ call JoypadOverworld ; get joypad state (which is possibly simulated)
+ callba SafariZoneCheck
+ ld a,[wSafariZoneGameOver]
+ and a
+ jp nz,WarpFound2
+ ld hl,wd72d
+ bit 3,[hl]
+ res 3,[hl]
+ jp nz,WarpFound2
+ ld a,[wd732]
+ and a,1 << 4 | 1 << 3 ; fly warp or dungeon warp
+ jp nz,HandleFlyWarpOrDungeonWarp
+ ld a,[W_CUROPPONENT]
+ and a
+ jp nz,.newBattle
+ ld a,[wd730]
+ bit 7,a ; are we simulating button presses?
+ jr z,.notSimulating
+ ld a,[hJoyHeld]
+ jr .checkIfStartIsPressed
+.notSimulating
+ ld a,[hJoyPressed]
+.checkIfStartIsPressed
+ bit 3,a ; start button
+ jr z,.startButtonNotPressed
+; if START is pressed
+ xor a
+ ld [hSpriteIndexOrTextID],a ; start menu text ID
+ jp .displayDialogue
+.startButtonNotPressed
+ bit 0,a ; A button
+ jp z,.checkIfDownButtonIsPressed
+; if A is pressed
+ ld a,[wd730]
+ bit 2,a
+ jp nz,.noDirectionButtonsPressed
+ call IsPlayerCharacterBeingControlledByGame
+ jr nz,.checkForOpponent
+ call CheckForHiddenObjectOrBookshelfOrCardKeyDoor
+ 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
+.displayDialogue
+ predef GetTileAndCoordsInFrontOfPlayer
+ call UpdateSprites
+ ld a,[wFlags_0xcd60]
+ bit 2,a
+ jr nz,.checkForOpponent
+ bit 0,a
+ jr nz,.checkForOpponent
+ aCoord 8, 9
+ ld [wcf0e],a
+ call DisplayTextID ; display either the start menu or the NPC/sign text
+ ld a,[wcc47]
+ and a
+ jr z,.checkForOpponent
+ xor a
+ ld [wcc47],a
+ jp EnterMap
+; predef LoadSAV
+; ld a,[W_CURMAP]
+; ld [wDestinationMap],a
+; call SpecialWarpIn
+; ld a,[W_CURMAP]
+; call SwitchToMapRomBank ; switch to the ROM bank of the current map
+; ld hl,W_CURMAPTILESET
+; set 7,[hl]
+.checkForOpponent
+ ld a,[W_CUROPPONENT]
+ and a
+ jp nz,.newBattle
+ jp OverworldLoop
+.noDirectionButtonsPressed
+ call UpdateSprites ; 231c
+ ld hl,wFlags_0xcd60
+ res 2,[hl]
+ xor a
+ ld [wd435], a
+ ld a, $1
+ ld a,$01
+ ld [wcc4b],a
+ ld a,[wd528] ; the direction that was pressed last time
+ and a
+ jr z, .overworldloop
+; if a direction was pressed last time
+ ld [wd529],a ; save the last direction
+ xor a
+ ld [wd528],a ; zero the direction
+.overworldloop
+ jp OverworldLoop
+.checkIfDownButtonIsPressed
+ ld a,[hJoyHeld] ; current joypad state
+ bit 7,a ; down button
+ jr z,.checkIfUpButtonIsPressed
+ ld a,$01
+ ld [wSpriteStateData1 + 3],a
+ ld a,$04
+ jr .handleDirectionButtonPress
+.checkIfUpButtonIsPressed
+ bit 6,a ; up button
+ jr z,.checkIfLeftButtonIsPressed
+ ld a,$ff
+ ld [wSpriteStateData1 + 3],a
+ ld a,$08
+ jr .handleDirectionButtonPress
+.checkIfLeftButtonIsPressed
+ bit 5,a ; left button
+ jr z,.checkIfRightButtonIsPressed
+ ld a,$ff
+ ld [wSpriteStateData1 + 5],a
+ ld a,$02
+ jr .handleDirectionButtonPress
+.checkIfRightButtonIsPressed
+ bit 4,a ; right button
+ jr z,.noDirectionButtonsPressed
+ ld a,$01
+ ld [wSpriteStateData1 + 5],a
+.handleDirectionButtonPress
+ ld [wd52a],a ; new direction
+ ld a,[wd730]
+ bit 7,a ; are we simulating button presses?
+ jr nz,.noDirectionChange ; ignore direction changes if we are
+ ld a,[wcc4b]
+ and a
+ jr z,.noDirectionChange
+ ld a,[wd52a] ; new direction
+ ld b,a
+ ld a,[wd529] ; old direction
+ cp b
+ jr z,.noDirectionChange
+ ld a,$8
+ ld [wd434],a
+; unlike in red/blue, yellow does not have the 180 degrees odd code
+ ld hl,wFlags_0xcd60
+ set 2,[hl]
+ xor a
+ ld [wcc4b],a
+ ld a,[wd52a]
+ ld [wd528],a
+ call NewBattle
+ jp c,.battleOccurred
+ jp OverworldLoop
+.noDirectionChange
+ ld a,[wd52a] ; current direction
+ ld [wd528],a ; save direction
+ call UpdateSprites
+ ld a,[wWalkBikeSurfState]
+ cp a,$02 ; surfing
+ jr z,.surfing
+; not surfing
+ call CollisionCheckOnLand
+ jr nc,.noCollision
+; collision occurred
+ push hl
+ ld hl,wd736
+ bit 2,[hl] ; standing on warp flag
+ pop hl
+ jp z,OverworldLoop
+; collision occurred while standing on a warp
+ push hl
+ call ExtraWarpCheck ; sets carry if there is a potential to warp
+ pop hl
+ jp c,CheckWarpsCollision
+ jp OverworldLoop
+.surfing
+ call CollisionCheckOnWater
+ jp c,OverworldLoop
+.noCollision
+ ld a,$08
+ ld [wWalkCounter],a
+ callab Func_fcc08
+ jr .moveAhead2
+.moveAhead
+ call IsSpinning
+ call UpdateSprites ; move sprites
+.moveAhead2
+ ld hl,wFlags_0xcd60
+ res 2,[hl]
+ xor a
+ ld [wd435],a
+ call DoBikeSpeedup
+ 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
+ call StepCountCheck
+ ld a,[wd790]
+ bit 7,a ; in the safari zone?
+ jr z,.notSafariZone
+ callba SafariZoneCheckSteps
+ ld a,[wSafariZoneGameOver]
+ and a
+ jp nz,WarpFound2
+.notSafariZone
+ ld a,[W_ISINBATTLE]
+ and a
+ jp nz,CheckWarpsNoCollision
+ predef ApplyOutOfBattlePoisonDamage ; also increment daycare mon exp
+ ld a,[wd12d]
+ and a
+ jp nz,HandleBlackOut ; if all pokemon fainted
+.newBattle
+ call NewBattle
+ ld hl,wd736
+ res 2,[hl] ; standing on warp flag
+ jp nc,CheckWarpsNoCollision ; check for warps if there was no battle
+.battleOccurred
+ ld hl,wd72d
+ res 6,[hl]
+ ld hl,W_FLAGS_D733
+ res 3,[hl]
+ ld hl,wd126
+ set 5,[hl]
+ set 6,[hl]
+ xor a
+ ld [hJoyHeld],a
+ ld a,[W_CURMAP]
+ cp a,CINNABAR_GYM
+ jr nz,.notCinnabarGym
+ ld hl,wd79b
+ set 7,[hl]
+.notCinnabarGym
+ ld hl,wd72e
+ set 5,[hl]
+ ld a,[W_CURMAP]
+ cp a,OAKS_LAB
+ jp z,.noFaintCheck ; no blacking out if the player lost to the rival in Oak's lab
+ callab AnyPartyAlive
+ ld a,d
+ and a
+ jr z,.allPokemonFainted
+.noFaintCheck
+ ld c,$0a
+ call DelayFrames
+ jp EnterMap
+;.allPokemonFainted
+; ld a,$ff
+; ld [W_ISINBATTLE],a
+; call RunMapScript
+; jp HandleBlackOut
+
+StepCountCheck:: ; 0457 (0:0457)
+ 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
+
+; function to determine if there will be a battle and execute it (either a trainer battle or wild battle)
+; sets carry if a battle occurred and unsets carry if not
+NewBattle:: ; 0480 (0:0480)
+ ld a,[wd72d]
+ bit 4,a
+ jr nz,.noBattle
+ call IsPlayerCharacterBeingControlledByGame
+ jr nz,.noBattle ; no battle if the player character is under the game's control
+ ld a,[wd72e]
+ bit 4,a
+ jr nz,.noBattle
+ ld b, BANK(InitBattle)
+ ld hl, InitBattle ; 3d:5ff2
+ jp Bankswitch
+.noBattle
+ and a
+ ret
+
+DoBikeSpeedup:: ; 049d (0:049d)
+ 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
+ ld a,[W_CURMAP]
+ cp ROUTE_17 ; cycling road
+ jr nz,.goFaster
+ ld a,[hJoyHeld]
+ and a,D_UP | D_LEFT | D_RIGHT
+ ret nz
+.goFaster
+ call AdvancePlayerSprite
+ ret
+
+; check if the player has stepped onto a warp after having not collided
+CheckWarpsNoCollision:: ; 04bd (0:04bd)
+ ld a,[wNumberOfWarps]
+ and a
+ jp z,CheckMapConnections
+ ld b,0
+ ld a,[wNumberOfWarps]
+ ld c,a
+ ld a,[W_YCOORD]
+ ld d,a
+ ld a,[W_XCOORD]
+ ld e,a
+ ld hl,wWarpEntries
+CheckWarpsNoCollisionLoop:: ; 04d5 (0:04d5)
+ ld a,[hli] ; check if the warp's Y position matches
+ cp d
+ jr nz,CheckWarpsNoCollisionRetry1
+ ld a,[hli] ; check if the warp's X position matches
+ cp e
+ jr nz,CheckWarpsNoCollisionRetry2
+; if a match was found
+ push hl
+ push bc
+ ld hl,wd736
+ set 2,[hl] ; standing on warp flag
+ callba IsPlayerStandingOnDoorTileOrWarpTile
+ pop bc
+ pop hl
+ jr c,WarpFound1 ; jump if standing on door or warp
+ push hl
+ push bc
+ call ExtraWarpCheck
+ pop bc
+ pop hl
+ jr nc,CheckWarpsNoCollisionRetry2
+; if the extra check passed
+ ld a,[W_FLAGS_D733]
+ bit 2,a
+ jr nz,WarpFound1
+ push de
+ push bc
+ call Joypad
+ pop bc
+ pop de
+ ld a,[hJoyHeld]
+ and a,D_DOWN | D_UP | D_LEFT | D_RIGHT
+ jr z,CheckWarpsNoCollisionRetry2 ; if directional buttons aren't being pressed, do not pass through the warp
+ jr WarpFound1
+
+CheckWarpsNoCollisionRetry1:: ; 050f (0:050f)
+ inc hl
+CheckWarpsNoCollisionRetry2:: ; 0510 (0:0510)
+ inc hl
+ inc hl
+ContinueCheckWarpsNoCollisionLoop:: ; 0512 (0:0512)
+ 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:: ; 051a (0:051a)
+ ld a,[wNumberOfWarps]
+ ld c,a
+ ld hl,wWarpEntries
+.loop
+ ld a,[hli] ; Y coordinate of warp
+ ld b,a
+ ld a,[W_YCOORD]
+ cp b
+ jr nz,.retry1
+ ld a,[hli] ; X coordinate of warp
+ ld b,a
+ ld a,[W_XCOORD]
+ cp b
+ jr nz,.retry2
+ ld a,[hli]
+ ld [wDestinationWarpID],a
+ ld a,[hl]
+ ld [$ff8b],a ; save target map
+ jr WarpFound2
+.retry1
+ inc hl
+.retry2
+ inc hl
+ inc hl
+ dec c
+ jr nz,.loop
+ jp OverworldLoop
+
+WarpFound1:: ; 0543 (0:0543)
+ ld a,[hli]
+ ld [wDestinationWarpID],a
+ ld a,[hli]
+ ld [$ff8b],a ; save target map
+
+WarpFound2:: ; 054a (0:054a)
+ ld a,[wNumberOfWarps]
+ sub c
+ ld [wd73b],a ; save ID of used warp
+ ld a,[W_CURMAP]
+ ld [wd73c],a
+ call CheckIfInOutsideMap
+ jr nz,.indoorMaps
+; this is for handling "outside" maps that can't have the 0xFF destination map
+ ld a,[W_CURMAP]
+ ld [wLastMap],a
+ ld a,[W_CURMAPWIDTH]
+ ld [wd366],a
+ ld a,[$ff8b] ; destination map number
+ ld [W_CURMAP],a ; change current map to destination map
+ cp a,ROCK_TUNNEL_1
+ jr nz,.notRockTunnel
+ ld a,$06
+ ld [wMapPalOffset],a
+ call GBFadeOutToBlack
+.notRockTunnel
+ callab Func_fc5fa ; 3f:45fa
+ call PlayMapChangeSound
+ jr .done
+; for maps that can have the 0xFF destination map, which means to return to the outside map; not all these maps are necessarily indoors, though
+.indoorMaps
+ ld a,[$ff8b] ; destination map
+ cp a,$ff
+ jr z,.goBackOutside
+; if not going back to the previous map
+ ld [W_CURMAP],a ; current map number
+ callba IsPlayerStandingOnWarpPadOrHole
+ ld a,[wcd5b]
+ 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]
+ jr .skipMapChangeSound
+.notWarpPad
+ call PlayMapChangeSound
+.skipMapChangeSound
+ ld hl,wd736
+ res 0,[hl]
+ res 1,[hl]
+ callab Func_fc65b ; 3f:465b
+ jr .done
+.goBackOutside
+ callab Func_fc69a ; 3f:469a
+ ld a,[wLastMap]
+ ld [W_CURMAP],a
+ call PlayMapChangeSound
+ xor a
+ ld [wMapPalOffset],a
+.done
+ ld hl,wd736
+ set 0,[hl] ; have the player's sprite step out from the door (if there is one)
+ call IgnoreInputForHalfSecond
+ jp EnterMap
+
+; if no matching warp was found
+CheckMapConnections:: ; 05db (0:05db)
+.checkWestMap
+ ld a,[W_XCOORD]
+ cp a,$ff
+ jr nz,.checkEastMap
+ ld a,[W_MAPCONN3PTR]
+ ld [W_CURMAP],a
+ ld a,[wd38f] ; new X coordinate upon entering west map
+ ld [W_XCOORD],a
+ ld a,[W_YCOORD]
+ ld c,a
+ ld a,[wd38e] ; Y adjustment upon entering west map
+ add c
+ ld c,a
+ ld [W_YCOORD],a
+ ld a,[wd390] ; pointer to upper left corner of map without adjustment for Y position
+ ld l,a
+ ld a,[wd391]
+ ld h,a
+ srl c
+ jr z,.savePointer1
+.pointerAdjustmentLoop1
+ ld a,[wd38d] ; width of connected map
+ add a,$06
+ ld e,a
+ ld d,$00
+ ld b,$00
+ add hl,de
+ dec c
+ jr nz,.pointerAdjustmentLoop1
+.savePointer1
+ ld a,l
+ ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section
+ ld a,h
+ ld [wCurrentTileBlockMapViewPointer + 1],a
+ jp .loadNewMap
+.checkEastMap
+ ld b,a
+ ld a,[wd525] ; map width
+ cp b
+ jr nz,.checkNorthMap
+ ld a,[W_MAPCONN4PTR]
+ ld [W_CURMAP],a
+ ld a,[wd39a] ; new X coordinate upon entering east map
+ ld [W_XCOORD],a
+ ld a,[W_YCOORD]
+ ld c,a
+ ld a,[wd399] ; Y adjustment upon entering east map
+ add c
+ ld c,a
+ ld [W_YCOORD],a
+ ld a,[wd39b] ; pointer to upper left corner of map without adjustment for Y position
+ ld l,a
+ ld a,[wd39c]
+ ld h,a
+ srl c
+ jr z,.savePointer2
+.pointerAdjustmentLoop2
+ ld a,[wd398]
+ add a,$06
+ ld e,a
+ ld d,$00
+ ld b,$00
+ add hl,de
+ dec c
+ jr nz,.pointerAdjustmentLoop2
+.savePointer2
+ ld a,l
+ ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section
+ ld a,h
+ ld [wCurrentTileBlockMapViewPointer + 1],a
+ jp .loadNewMap
+.checkNorthMap
+ ld a,[W_YCOORD]
+ cp a,$ff
+ jr nz,.checkSouthMap
+ ld a,[W_MAPCONN1PTR]
+ ld [W_CURMAP],a
+ ld a,[wd378] ; new Y coordinate upon entering north map
+ ld [W_YCOORD],a
+ ld a,[W_XCOORD]
+ ld c,a
+ ld a,[wd379] ; X adjustment upon entering north map
+ add c
+ ld c,a
+ ld [W_XCOORD],a
+ ld a,[wd37a] ; pointer to upper left corner of map without adjustment for X position
+ ld l,a
+ ld a,[wd37b]
+ ld h,a
+ ld b,$00
+ srl c
+ add hl,bc
+ ld a,l
+ ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section
+ ld a,h
+ ld [wCurrentTileBlockMapViewPointer + 1],a
+ jp .loadNewMap
+.checkSouthMap
+ ld b,a
+ ld a,[wd524]
+ cp b
+ jr nz,.didNotEnterConnectedMap
+ ld a,[W_MAPCONN2PTR]
+ ld [W_CURMAP],a
+ ld a,[wd383] ; new Y coordinate upon entering south map
+ ld [W_YCOORD],a
+ ld a,[W_XCOORD]
+ ld c,a
+ ld a,[wd384] ; X adjustment upon entering south map
+ add c
+ ld c,a
+ ld [W_XCOORD],a
+ ld a,[wd385] ; pointer to upper left corner of map without adjustment for X position
+ ld l,a
+ ld a,[wd386]
+ ld h,a
+ ld b,$00
+ srl c
+ add hl,bc
+ ld a,l
+ ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section
+ ld a,h
+ ld [wCurrentTileBlockMapViewPointer + 1],a
+.loadNewMap ; 06ce (0:06ce)
+; load the connected map that was entered
+ ld hl,[wd430]
+ set 4,[hl]
+ ld a,$2
+ ld [wd431],a
+ call LoadMapHeader ; 0dab (0:0dab)
+ call Func_2312 ; music
+ ld b,$09
+ call GoPAL_SET
+; Since the sprite set shouldn't change, this will just update VRAM slots at
+; $C2XE without loading any tile patterns.
+ call InitMapSprites
+ call LoadTileBlockMap
+ jp OverworldLoopLessDelay
+.didNotEnterConnectedMap
+ jp OverworldLoop
+
+; function to play a sound when changing maps
+PlayMapChangeSound:: ; 06ef (0:06ef)
+ ld a,[W_CURMAPTILESET]
+ cp FACILITY
+ jr z,.didNotGoThroughDoor
+ cp CEMETERY
+ jr z,.didNotGoThroughDoor
+ cp UNDERGROUND
+ jr nz,.didNotGoThroughDoor
+ aCoord 8, 8 ; upper left tile of the 4x4 square the player's sprite is standing on
+ cp a,$0b ; door tile in tileset 0
+ jr nz,.didNotGoThroughDoor
+ ld a,(SFX_02_57 - SFX_Headers_02) / 3
+ jr .playSound
+.didNotGoThroughDoor
+ ld a,(SFX_02_5c - SFX_Headers_02) / 3
+.playSound
+ call PlaySound
+ ld a,[wMapPalOffset]
+ and a
+ ret nz
+ jp GBFadeOutToBlack
+
+CheckIfInOutsideMap:: ; 0712 (0:0712)
+; If the player is in an outside map (a town or route), set the z flag
+ ld a, [W_CURMAPTILESET]
+ and a ; most towns/routes have tileset 0 (OVERWORLD)
+ ret z
+ cp PLATEAU ; Route 23 / Indigo Plateau
+ ret
+
+; this function is an extra check that sometimes has to pass in order to warp, beyond just standing on a warp
+; the "sometimes" qualification is necessary because of CheckWarpsNoCollision's behavior
+; depending on the map, either "function 1" or "function 2" is used for the check
+; "function 1" passes when the player is at the edge of the map and is facing towards the outside of the map
+; "function 2" passes when the the tile in front of the player is among a certain set
+; sets carry if the check passes, otherwise clears carry
+ExtraWarpCheck:: ; 071a (0:071a)
+ ld a, [W_CURMAP]
+ cp SS_ANNE_3
+ jr z, .useFunction1
+ cp ROCKET_HIDEOUT_1
+ jr z, .useFunction2
+ cp ROCKET_HIDEOUT_2
+ jr z, .useFunction2
+ cp ROCKET_HIDEOUT_4
+ jr z, .useFunction2
+ cp ROCK_TUNNEL_1
+ jr z, .useFunction2
+ ld a, [W_CURMAPTILESET]
+ and a ; outside tileset (OVERWORLD)
+ jr z, .useFunction2
+ cp SHIP ; S.S. Anne tileset
+ jr z, .useFunction2
+ cp SHIP_PORT ; Vermilion Port tileset
+ jr z, .useFunction2
+ cp PLATEAU ; Indigo Plateau tileset
+ jr z, .useFunction2
+.useFunction1
+ ld hl, IsPlayerFacingEdgeOfMap
+ jr .doBankswitch
+.useFunction2
+ ld hl, IsWarpTileInFrontOfPlayer
+.doBankswitch
+ ld b, BANK(IsWarpTileInFrontOfPlayer)
+ jp Bankswitch
+
+MapEntryAfterBattle:: ; 0750 (0:0750)
+ callba IsPlayerStandingOnWarp ; for enabling warp testing after collisions
+ ld a,[wMapPalOffset]
+ and a
+ jp z,GBFadeInFromWhite
+ jp LoadGBPal
+
+HandleBlackOut:: ; 0762 (0:0762)
+; For when all the player's pokemon faint.
+; Does not print the "blacked out" message.
+
+ call GBFadeOutToBlack
+ ld a, $08
+ call StopMusic
+ ld hl, wd72e
+ res 5, [hl]
+ callsb ResetStatusAndHalveMoneyOnBlackout ; also Bank(SpecialWarpIn) and Bank(SpecialEnterMap)
+ callab Func_f0274 ; 3c:4274
+ call SpecialWarpIn
+ call Func_2312
+ jp SpecialEnterMap
+
+StopMusic:: ; 0788 (0:0788)
+ ld [wMusicHeaderPointer], a
+ call StopAllMusic
+.wait
+ ld a, [wMusicHeaderPointer]
+ and a
+ jr nz, .wait
+ jp StopAllSounds
+
+HandleFlyWarpOrDungeonWarp:: ; 0794 (0:0794)
+ call UpdateSprites
+ call Delay3
+ xor a
+ ld [wBattleResult], a
+ ld [wWalkBikeSurfState], a
+ ld [W_ISINBATTLE], a
+ ld [wMapPalOffset], a
+ ld hl, wd732
+ set 2, [hl] ; fly warp or dungeon warp
+ res 5, [hl] ; forced to ride bike
+ call LeaveMapAnim
+ call LoadPlayerSpriteGraphics
+ callsb SpecialWarpIn
+ jp SpecialEnterMap
+
+LeaveMapAnim:: ; 07bc (0:07bc)
+ ld b, BANK(_LeaveMapAnim)
+ ld hl, _LeaveMapAnim
+ jp Bankswitch
+
+Func_07c4:: ; 07c4 (0: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:: ; 07d7 (0:07d7)
+; Load sprite graphics based on whether the player is standing, biking, or surfing.
+
+ ; 0: standing
+ ; 1: biking
+ ; 2: surfing
+
+ ld a, [wWalkBikeSurfState]
+ dec a
+ jr z, .ridingBike
+
+ ld a, [hTilesetType]
+ and a
+ jr nz, .determineGraphics
+ jr .startWalking
+
+.ridingBike
+ ; If the bike can't be used,
+ ; start walking instead.
+ call IsBikeRidingAllowed
+ jr c, .determineGraphics
+
+.startWalking
+ xor a
+ ld [wWalkBikeSurfState], a
+ ld [wWalkBikeSurfStateCopy], a
+ jp LoadWalkingPlayerSpriteGraphics
+
+.determineGraphics
+ ld a, [wWalkBikeSurfState]
+ and a
+ jp z, LoadWalkingPlayerSpriteGraphics
+ dec a
+ jp z, LoadBikePlayerSpriteGraphics
+ dec a
+ jp z, LoadSurfingPlayerSpriteGraphics
+ jp LoadWalkingPlayerSpriteGraphics
+
+IsBikeRidingAllowed:: ; 0805 (0:0805)
+; The bike can be used on Route 23 and Indigo Plateau,
+; or maps with tilesets in BikeRidingTilesets.
+; Return carry if biking is allowed.
+
+ ld a, [W_CURMAP]
+ cp ROUTE_23
+ jr z, .allowed
+ cp INDIGO_PLATEAU
+ jr z, .allowed
+
+ ld a, [W_CURMAPTILESET]
+ ld b, a
+ ld hl, BikeRidingTilesets
+.loop
+ ld a, [hli]
+ cp b
+ jr z, .allowed
+ inc a
+ jr nz, .loop
+ and a
+ ret
+
+.allowed
+ scf
+ ret
+
+INCLUDE "data/bike_riding_tilesets.asm"
+
+; load the tile pattern data of the current tileset into VRAM
+LoadTilesetTilePatternData:: ; 0828 (0:0828)
+ ld a,[W_TILESETGFXPTR]
+ ld l,a
+ ld a,[W_TILESETGFXPTR + 1]
+ ld h,a
+ ld de,vTileset
+ ld bc,$600
+ ld a,[W_TILESETBANK]
+ jp FarCopyData2
+
+; 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:: ; 083c (0:083c)
+; fill C6E8-CBFB with the background tile
+ ld hl,wOverworldMap
+ ld bc,$0514
+ ld a,[wd3ad] ; 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
+ ld a,[W_CURMAPWIDTH]
+ ld [$ff8c],a
+ add a,$06 ; border (east and west)
+ ld [$ff8b],a ; map width + border
+ ld b,$00
+ ld c,a
+; make space for north border (next 3 lines)
+ add hl,bc
+ add hl,bc
+ add hl,bc
+ ld c,$03
+ add hl,bc ; this puts us past the (west) border
+ ld a,[W_MAPDATAPTR] ; tile map pointer
+ ld e,a
+ ld a,[W_MAPDATAPTR + 1]
+ ld d,a ; de = tile map pointer
+ ld a,[W_CURMAPHEIGHT]
+ ld b,a
+.rowLoop ; copy one row each iteration
+ push hl
+ ld a,[$ff8c] ; map width (without border)
+ ld c,a
+.rowInnerLoop
+ ld a,[de]
+ inc de
+ ld [hli],a
+ dec c
+ jr nz,.rowInnerLoop
+; add the map width plus the border to the base address of the current row to get the next row's address
+ pop hl
+ ld a,[$ff8b] ; map width + border
+ add l
+ ld l,a
+ jr nc,.noCarry
+ inc h
+.noCarry
+ dec b
+ jr nz,.rowLoop
+.northConnection
+ ld a,[W_MAPCONN1PTR]
+ cp a,$ff
+ jr z,.southConnection
+ call SwitchToMapRomBank
+ ld a,[wd372]
+ ld l,a
+ ld a,[wd373]
+ ld h,a
+ ld a,[wd374]
+ ld e,a
+ ld a,[wd375]
+ ld d,a
+ ld a,[wd376]
+ ld [$ff8b],a
+ ld a,[wd377]
+ ld [$ff8c],a
+ call LoadNorthSouthConnectionsTileMap
+.southConnection
+ ld a,[W_MAPCONN2PTR]
+ cp a,$ff
+ jr z,.westConnection
+ call SwitchToMapRomBank
+ ld a,[wd37d]
+ ld l,a
+ ld a,[wd37e]
+ ld h,a
+ ld a,[wd37f]
+ ld e,a
+ ld a,[wd380]
+ ld d,a
+ ld a,[wd381]
+ ld [$ff8b],a
+ ld a,[wd382]
+ ld [$ff8c],a
+ call LoadNorthSouthConnectionsTileMap
+.westConnection
+ ld a,[W_MAPCONN3PTR]
+ cp a,$ff
+ jr z,.eastConnection
+ call SwitchToMapRomBank
+ ld a,[wd388]
+ ld l,a
+ ld a,[wd389]
+ ld h,a
+ ld a,[wd38a]
+ ld e,a
+ ld a,[wd38b]
+ ld d,a
+ ld a,[wd38c]
+ ld b,a
+ ld a,[wd38d]
+ ld [$ff8b],a
+ call LoadEastWestConnectionsTileMap
+.eastConnection
+ ld a,[W_MAPCONN4PTR]
+ cp a,$ff
+ jr z,.done
+ call SwitchToMapRomBank
+ ld a,[wd393]
+ ld l,a
+ ld a,[wd394]
+ ld h,a
+ ld a,[wd395]
+ ld e,a
+ ld a,[wd396]
+ ld d,a
+ ld a,[wd397]
+ ld b,a
+ ld a,[wd398]
+ ld [$ff8b],a
+ call LoadEastWestConnectionsTileMap
+.done
+ ret
+
+LoadNorthSouthConnectionsTileMap:: ; 0919 (0:0919)
+ ld c,$03
+.loop
+ push de
+ push hl
+ ld a,[$ff8b] ; width of connection
+ ld b,a
+.innerLoop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec b
+ jr nz,.innerLoop
+ pop hl
+ pop de
+ ld a,[$ff8c] ; width of connected map
+ add l
+ ld l,a
+ jr nc,.noCarry1
+ inc h
+.noCarry1
+ ld a,[W_CURMAPWIDTH]
+ add a,$06
+ add e
+ ld e,a
+ jr nc,.noCarry2
+ inc d
+.noCarry2
+ dec c
+ jr nz,.loop
+ ret
+
+LoadEastWestConnectionsTileMap:: ; 093d (0:093d)
+ push hl
+ push de
+ ld c,$03
+.innerLoop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec c
+ jr nz,.innerLoop
+ pop de
+ pop hl
+ ld a,[$ff8b] ; width of connected map
+ add l
+ ld l,a
+ jr nc,.noCarry1
+ inc h
+.noCarry1
+ ld a,[W_CURMAPWIDTH]
+ add a,$06
+ add e
+ ld e,a
+ jr nc,.noCarry2
+ inc d
+.noCarry2
+ dec b
+ jr nz,LoadEastWestConnectionsTileMap
+ ret
+
+; function to check if there is a sign or sprite in front of the player
+; if so, carry is set. otherwise, carry is cleared
+IsSpriteOrSignInFrontOfPlayer:: ; 095e (0:095e)
+ xor a
+ ld [hSpriteIndexOrTextID],a
+ ld a,[wd4b0] ; number of signs in the map
+ and a
+ jr z,.extendRangeOverCounter
+; if there are signs
+ predef GetTileAndCoordsInFrontOfPlayer ; get the coordinates in front of the player in de
+ 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,W_TILESETTALKINGOVERTILES ; list of tiles that extend talking range (counter tiles)
+ ld b,$03
+ ld d,$20 ; talking range in pixels (long range)
+.counterTilesLoop
+ ld a,[hli]
+ cp c
+ jr z,IsSpriteInFrontOfPlayer2 ; jumps if the tile in front of the player is a counter tile
+ dec b
+ jr nz,.counterTilesLoop
+
+; sets carry flag if a sprite is in front of the player, resets if not
+IsSpriteInFrontOfPlayer:: ; 0983 (0:0983)
+ ld d,$10 ; talking range in pixels (normal range)
+IsSpriteInFrontOfPlayer2:: ; 0985 (0:0985)
+ ld bc,$3c40 ; Y and X position of player sprite
+ ld a,[wSpriteStateData1 + 9] ; direction the player is facing
+.checkIfPlayerFacingUp
+ cp a,$04
+ jr nz,.checkIfPlayerFacingDown
+; facing up
+ ld a,b
+ sub d
+ ld b,a
+ ld a,$08
+ jr .doneCheckingDirection
+.checkIfPlayerFacingDown
+ cp a,$00
+ jr nz,.checkIfPlayerFacingRight
+; facing down
+ ld a,b
+ add d
+ ld b,a
+ ld a,$04
+ jr .doneCheckingDirection
+.checkIfPlayerFacingRight
+ cp a,$0c
+ jr nz,.playerFacingLeft
+; facing right
+ ld a,c
+ add d
+ ld c,a
+ ld a,$01
+ jr .doneCheckingDirection
+.playerFacingLeft
+; facing left
+ ld a,c
+ sub d
+ ld c,a
+ ld a,$02
+.doneCheckingDirection
+ ld [wd52a],a
+ ld hl,wSpriteStateData1 + $10
+; 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)
+ and a
+ jr z,.nextSprite
+ inc l
+ ld a,[hli] ; sprite visibility
+ inc a
+ jr z,.nextSprite
+ inc l
+ ld a,[hli] ; Y location
+ cp b
+ jr nz,.nextSprite
+ inc l
+ ld a,[hl] ; X location
+ cp c
+ jr z,.foundSpriteInFrontOfPlayer
+.nextSprite
+ pop hl
+ ld a,l
+ add a,$10
+ ld l,a
+ inc e
+ dec d
+ jr nz,.spriteLoop
+ xor a
+ ret
+.foundSpriteInFrontOfPlayer
+ pop hl
+ ld a,l
+ and a,$f0
+ inc a
+ ld l,a
+ set 7,[hl]
+ ld a,e
+ ld [hSpriteIndexOrTextID],a
+ ld a,[hSpriteIndexOrTextID] ; possible useless read because a already has the value of the read address
+ cp a,$f
+ jr nz,.dontwritetowd436
+ ld a,$FF
+ ld [wd436],a
+.dontwritetowd436
+ scf
+ ret
+
+SignLoop:: ; 09f2 (0:09f2)
+; search if a player is facing a sign
+ ld hl,wd4b1 ; start of sign coordinates
+ ld a,[wd4b0] ; 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,wd4d1 ; 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)
+; sets the carry flag if there is a collision, and unsets it if there isn't a collision
+CollisionCheckOnLand:: ; 0a1c (0:0a1c)
+ ld a,[wd736]
+ bit 6,a ; is the player jumping?
+ jr nz,.noCollision
+; if not jumping a ledge
+ ld a,[wSimulatedJoypadStatesIndex]
+ and a
+ jr nz,.noCollision ; no collisions when the player's movements are being controlled by the game
+ ld a,[wd52a] ; the direction that the player is trying to go in
+ 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 z,.asm_0a5c
+; if no sprite collision
+ cp $f
+ jr nz,.collision
+ call CheckForJumpingAndTilePairCollisions
+ 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
+ call CheckTilePassable
+ jr nc,.noCollision
+.collision
+ ld a,[wc02a]
+ cp a,(SFX_02_5b - SFX_Headers_02) / 3 ; check if collision sound is already playing
+ jr z,.setCarry
+ ld a,(SFX_02_5b - SFX_Headers_02) / 3
+ call PlaySound ; play collision sound (if it's not already playing)
+.setCarry
+ scf
+ ret
+.noCollision
+ and a
+ ret
+
+; function that checks if the tile in front of the player is passable
+; clears carry if it is, sets carry if not
+CheckTilePassable:: ; 0a79 (0:0a79)
+ predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player
+ ld a,[wTileInFrontOfPlayer] ; tile in front of player
+ ld c,a
+ call IsTilePassable
+ ret
+
+; check if the player is going to jump down a small ledge
+; and check for collisions that only occur between certain pairs of tiles
+; Input: hl - address of directional collision data
+; sets carry if there is a collision and unsets carry if not
+CheckForJumpingAndTilePairCollisions:: ; 0a86 (0:0a86)
+ push hl
+ 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
+ pop bc
+ pop de
+ pop hl
+ and a
+ ld a,[wd736]
+ bit 6,a ; is the player jumping?
+ ret nz
+; if not jumping
+
+CheckForTilePairCollisions2:: ; 0aa0 (0:0aa0)
+ aCoord 8, 9 ; tile the player is on
+ ld [wcf0e],a
+
+CheckForTilePairCollisions:: ; 0aa6 (0:0aa6)
+ ld a,[wTileInFrontOfPlayer]
+ ld c,a
+.tilePairCollisionLoop
+ ld a,[W_CURMAPTILESET] ; tileset number
+ ld b,a
+ ld a,[hli]
+ cp a,$ff
+ jr z,.noMatch
+ cp b
+ jr z,.tilesetMatches
+ inc hl
+.retry
+ inc hl
+ jr .tilePairCollisionLoop
+.tilesetMatches
+ ld a,[wcf0e] ; tile the player is on
+ ld b,a
+ ld a,[hl]
+ cp b
+ jr z,.currentTileMatchesFirstInPair
+ inc hl
+ ld a,[hl]
+ cp b
+ jr z,.currentTileMatchesSecondInPair
+ jr .retry
+.currentTileMatchesFirstInPair
+ inc hl
+ ld a,[hl]
+ cp c
+ jr z,.foundMatch
+ jr .tilePairCollisionLoop
+.currentTileMatchesSecondInPair
+ dec hl
+ ld a,[hli]
+ cp c
+ inc hl
+ jr nz,.tilePairCollisionLoop
+.foundMatch
+ scf
+ ret
+.noMatch
+ and a
+ ret
+
+; FORMAT: tileset number, tile 1, tile 2
+; terminated by 0xFF
+; these entries indicate that the player may not cross between tile 1 and tile 2
+; it's mainly used to simulate differences in elevation
+
+TilePairCollisionsLand:: ; 0ada (0:0ada)
+ db CAVERN, $20, $05
+ db CAVERN, $41, $05
+ db FOREST, $30, $2E
+ db CAVERN, $2A, $05
+ db CAVERN, $05, $21
+ db FOREST, $52, $2E
+ db FOREST, $55, $2E
+ db FOREST, $56, $2E
+ db FOREST, $20, $2E
+ db FOREST, $5E, $2E
+ db FOREST, $5F, $2E
+ db $FF
+
+TilePairCollisionsWater:: ; 0afc (0:0afc)
+ db FOREST, $14, $2E
+ db FOREST, $48, $2E
+ db CAVERN, $14, $05
+ db $FF
+
+; this builds a tile map from the tile block map based on the current X/Y coordinates of the player's character
+LoadCurrentMapView:: ; 0b06 (0:0b06)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,[W_TILESETBANK] ; tile data ROM bank
+ 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]
+ ld d,a
+ ld hl,wTileMapBackup
+ ld b,$05
+.rowLoop ; each loop iteration fills in one row of tile blocks
+ push hl
+ push de
+ ld c,$06
+.rowInnerLoop ; loop to draw each tile block of the current row
+ push bc
+ push de
+ push hl
+ ld a,[de]
+ ld c,a ; tile block number
+ call DrawTileBlock
+ pop hl
+ pop de
+ pop bc
+ inc hl
+ inc hl
+ inc hl
+ inc hl
+ inc de
+ dec c
+ jr nz,.rowInnerLoop
+; update tile block map pointer to next row's address
+ pop de
+ ld a,[W_CURMAPWIDTH]
+ add a,$06
+ add e
+ ld e,a
+ jr nc,.noCarry
+ inc d
+.noCarry
+; update tile map pointer to next row's address
+ pop hl
+ ld a,$60
+ add l
+ ld l,a
+ jr nc,.noCarry2
+ inc h
+.noCarry2
+ dec b
+ jr nz,.rowLoop
+ ld hl,wTileMapBackup
+ ld bc,$0000
+.adjustForYCoordWithinTileBlock
+ ld a,[W_YBLOCKCOORD]
+ and a
+ jr z,.adjustForXCoordWithinTileBlock
+ ld bc,$0030
+ add hl,bc
+.adjustForXCoordWithinTileBlock
+ ld a,[W_XBLOCKCOORD]
+ and a
+ jr z,.copyToVisibleAreaBuffer
+ ld bc,$0002
+ add hl,bc
+.copyToVisibleAreaBuffer
+ ld de,wTileMap ; base address for the tiles that are directly transfered to VRAM during V-blank
+ ld b,$12
+.rowLoop2
+ ld c,$14
+.rowInnerLoop2
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec c
+ jr nz,.rowInnerLoop2
+ ld a,$04
+ add l
+ ld l,a
+ jr nc,.noCarry3
+ inc h
+.noCarry3
+ dec b
+ jr nz,.rowLoop2
+ pop af
+ call BankswitchCommon ; restore previous ROM bank
+ ret
+
+AdvancePlayerSprite:: ; 0b7f (0:0b7f)
+ ld a,[wUpdateSpritesEnabled]
+ push af
+ ld a,$FF
+ ld [wUpdateSpritesEnabled],a
+ ld hl, _AdvancePlayerSorite ; 3c:410c
+ 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
+; the portion of the map that was newly exposed due to the player's movement
+
+ScheduleNorthRowRedraw:: ; 0b95 (0:0b95)
+ hlCoord 0, 0
+ call CopyToScreenEdgeTiles
+ ld a,[wMapViewVRAMPointer]
+ ld [H_SCREENEDGEREDRAWADDR],a
+ ld a,[wMapViewVRAMPointer + 1]
+ ld [H_SCREENEDGEREDRAWADDR + 1],a
+ ld a,REDRAWROW
+ ld [H_SCREENEDGEREDRAW],a
+ ret
+
+CopyToScreenEdgeTiles:: ; 0baa (0:0baa)
+ ld de,wScreenEdgeTiles
+ ld c,2 * 20
+.loop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec c
+ jr nz,.loop
+ ret
+
+ScheduleSouthRowRedraw:: ; 0bb6 (0:0bb6)
+ hlCoord 0, 16
+ call CopyToScreenEdgeTiles
+ ld a,[wMapViewVRAMPointer]
+ ld l,a
+ ld a,[wMapViewVRAMPointer + 1]
+ ld h,a
+ ld bc,$0200
+ add hl,bc
+ ld a,h
+ and a,$03
+ or a,$98
+ ld [H_SCREENEDGEREDRAWADDR + 1],a
+ ld a,l
+ ld [H_SCREENEDGEREDRAWADDR],a
+ ld a,REDRAWROW
+ ld [H_SCREENEDGEREDRAW],a
+ ret
+
+ScheduleEastColumnRedraw:: ; 0bd6 (0:0bd7)
+ hlCoord 18, 0
+ call ScheduleColumnRedrawHelper
+ ld a,[wMapViewVRAMPointer]
+ ld c,a
+ and a,$e0
+ ld b,a
+ ld a,c
+ add a,18
+ and a,$1f
+ or b
+ ld [H_SCREENEDGEREDRAWADDR],a
+ ld a,[wMapViewVRAMPointer + 1]
+ ld [H_SCREENEDGEREDRAWADDR + 1],a
+ ld a,REDRAWCOL
+ ld [H_SCREENEDGEREDRAW],a
+ ret
+
+ScheduleColumnRedrawHelper:: ; 0bf6 (0:0bf6)
+ ld de,wScreenEdgeTiles
+ ld c,$12
+.loop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ ld a,[hl]
+ ld [de],a
+ inc de
+ ld a,19
+ add l
+ ld l,a
+ jr nc,.noCarry
+ inc h
+.noCarry
+ dec c
+ jr nz,.loop
+ ret
+
+ScheduleWestColumnRedraw:: ; 0c0c (0:0c0c)
+ hlCoord 0, 0
+ call ScheduleColumnRedrawHelper
+ ld a,[wMapViewVRAMPointer]
+ ld [H_SCREENEDGEREDRAWADDR],a
+ ld a,[wMapViewVRAMPointer + 1]
+ ld [H_SCREENEDGEREDRAWADDR + 1],a
+ ld a,REDRAWCOL
+ ld [H_SCREENEDGEREDRAW],a
+ ret
+
+; function to write the tiles that make up a tile block to memory
+; Input: c = tile block ID, hl = destination address
+DrawTileBlock:: ; 0c21 (0:0c21)
+ push hl
+ ld a,[W_TILESETBLOCKSPTR] ; pointer to tiles
+ ld l,a
+ ld a,[W_TILESETBLOCKSPTR + 1]
+ ld h,a
+ ld a,c
+ swap a
+ ld b,a
+ and a,$f0
+ ld c,a
+ ld a,b
+ and a,$0f
+ ld b,a ; bc = tile block ID * 0x10
+ add hl,bc
+ ld d,h
+ ld e,l ; de = address of the tile block's tiles
+ pop hl
+ ld c,$04 ; 4 loop iterations
+.loop ; each loop iteration, write 4 tile numbers
+ push bc
+ ld a,[de]
+ ld [hli],a
+ inc de
+ ld a,[de]
+ ld [hli],a
+ inc de
+ ld a,[de]
+ ld [hli],a
+ inc de
+ ld a,[de]
+ ld [hl],a
+ inc de
+ ld bc,$0015
+ add hl,bc
+ pop bc
+ dec c
+ jr nz,.loop
+ ret
+
+; function to update joypad state and simulate button presses
+JoypadOverworld:: ; 0c51 (0:0c51)
+ xor a
+ ld [wSpriteStateData1 + 3],a
+ ld [wSpriteStateData1 + 5],a
+ call RunMapScript
+ call Joypad
+ call ForceBikeDown
+ call AreInputsSimulated
+ ret
+
+ForceBikeDown:: ; 0c65 (0:0c65)
+ ld a,[W_FLAGS_D733]
+ bit 3,a ; check if a trainer wants a challenge
+ ret nz
+ ld a,[W_CURMAP]
+ cp a,ROUTE_17 ; Cycling Road
+ ret nz
+ ld a,[hJoyHeld]
+ and a,D_DOWN | D_UP | D_LEFT | D_RIGHT | B_BUTTON | A_BUTTON
+ jr nz,.notForcedDownwards
+ 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
+ ret
+
+AreInputsSimulated:: ; 0c7b (0:0c7b)
+ ld a,[wd730]
+ bit 7,a
+ ret z
+; if simulating button presses
+ ld a,[hJoyHeld]
+ ld b,a
+ ld a,[wOverrideSimulatedJoypadStatesMask] ; bit mask for button presses that override simulated ones
+ and b
+ ret nz ; return if the simulated button presses are overridden
+ call GetSimulatedInput
+ jr nc,.doneSimulating
+ ld [hJoyHeld],a ; store simulated button press in joypad state
+ and a
+ ret nz
+ ld [hJoyPressed],a
+ ld [hJoyReleased],a
+ ret
+
+; if done simulating button presses
+.doneSimulating
+ xor a
+ ld [wWastedByteCD3A],a
+ ld [wSimulatedJoypadStatesIndex],a
+ ld [wSimulatedJoypadStatesEnd],a
+ ld [wJoyIgnore],a
+ ld [hJoyHeld],a
+ ld hl,wd736
+ ld a,[hl]
+ and a,$f8
+ ld [hl],a
+ ld hl,wd730
+ res 7,[hl]
+ ret
+
+GetSimulatedInput:: ; 0cb3 (0:0cb3)
+ ld hl,wSimulatedJoypadStatesIndex
+ dec [hl]
+ ld a,[hl]
+ cp a,$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.
+CollisionCheckOnWater:: ; 0cca (0:0cca)
+ ld a,[wd730]
+ bit 7,a
+ jp nz,.noCollision ; return and clear carry if button presses are being simulated
+ ld a,[wd52a] ; the direction that the player is trying to go in
+ 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?
+ ld hl,TilePairCollisionsWater
+ call CheckForJumpingAndTilePairCollisions
+ jr c,.collision
+ predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player (puts it in c and [wTileInFrontOfPlayer])
+ callab IsNextTileShoreOrWater ; 3:6808
+ jr c,.noCollsion
+ ld a,[wTileInFrontOfPlayer] ; tile in front of player
+ ld c,a
+ call IsTilePassable
+ jr nc,.stopSurfing
+.collision
+ ld a,[wc02a]
+ cp a,(SFX_02_5b - SFX_Headers_02) / 3 ; check if collision sound is already playing
+ jr z,.setCarry
+ ld a,(SFX_02_5b - SFX_Headers_02) / 3
+ call PlaySound ; play collision sound (if it's not already playing)
+.setCarry
+ scf
+ jr .done
+.checkIfVermilionDockTileset
+ ld a, [W_CURMAPTILESET] ; 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 [wd431],a
+ ld hl,wd430
+ 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:: ; 0d2c (0:0d2c)
+ push hl
+ push de
+ push bc
+ callba TryPushingBoulder
+ ld a,[wFlags_0xcd60]
+ bit 1,a ; play boulder dust animation
+ jr z,.afterBoulderEffect
+ callba DoBoulderDustAnimation
+.afterBoulderEffect
+ pop bc
+ pop de
+ pop hl
+ call RunNPCMovementScript
+ ld a,[W_CURMAP] ; current map number
+ call SwitchToMapRomBank ; change to the ROM bank the map's data is in
+ ld hl,W_MAPSCRIPTPTR
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a
+ ld de,.return
+ push de
+ jp [hl] ; jump to script
+.return
+ ret
+
+Func_0d5e:: ; 0d5e (0:0d5e)
+; new sprite copy stuff
+ xor a
+ ld [wd473],a
+ ld b,BANK(RedSprite)
+ ld de,RedSprite ; $4180
+ jr LoadPlayerSpriteGraphicsCommon
+
+Func_0d69:: ; 0d69 (0:0d69)
+ ld a,[wd473]
+ and a
+ jr z,.asm_0d75
+ dec a
+ jr z,.asm_0d83
+ dec a
+ jr z,.asm_0d7c
+.asm_0d75
+ ld a,[wd472]
+ bit 6,a
+ jr z,LoadSurfingPlayerSpriteGraphics
+.asm_0d7c
+ ld b,BANK(Pointer_fedef)
+ ld de,Pointer_fedef ; 3f:6def
+ jr LoadPlayerSpriteGraphicsCommon
+
+LoadSurfingPlayerSpriteGraphics:: ; 0d83 (0:0d83)
+ ld b,BANK(RedSprite) ; not sure, but probably same bank (5)
+ ld de,SeelSprite
+ jr LoadPlayerSpriteGraphicsCommon
+
+LoadBikePlayerSpriteGraphics:: ; 0d8a (0:0d8a)
+ ld de,RedCyclingSprite
+LoadPlayerSpriteGraphicsCommon:: ; 0d8f (0:0d8f)
+ ld hl,vNPCSprites
+ push de
+ push hl
+ ld c, $c
+ call CopyVideoData
+ pop hl
+ pop de
+ ld a,$c0
+ add e
+ ld e,a
+ jr nc,.noCarry
+ inc d
+.noCarry
+ set 3,h
+ ld c,$c
+ jp CopyVideoData
+
+; function to load data from the map header
+LoadMapHeader:: ; 0dab (0:0dab)
+ callba MarkTownVisitedAndLoadMissableObjects
+ jr .asm_0dbd
+ callba Func_f0a55 ; 3c:4a55
+.asm_0dbd
+ ld a,[W_CURMAPTILESET]
+ ld [wd119],a
+ ld a,[W_CURMAP]
+ call SwitchToMapRomBank
+ ld a,[W_CURMAPTILESET]
+ ld b,a
+ res 7,a
+ ld [W_CURMAPTILESET],a
+ ld [$ff8b],a
+ bit 7,b
+ ret nz
+ call GetMapHeaderPointer
+; copy the first 10 bytes (the fixed area) of the map data to D367-D370
+ ld de,W_CURMAPTILESET
+ ld c,$0a
+.copyFixedHeaderLoop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec c
+ jr nz,.copyFixedHeaderLoop
+; initialize all the connected maps to disabled at first, before loading the actual values
+ ld a,$ff
+ ld [W_MAPCONN1PTR],a
+ ld [W_MAPCONN2PTR],a
+ ld [W_MAPCONN3PTR],a
+ ld [W_MAPCONN4PTR],a
+; copy connection data (if any) to WRAM
+ ld a,[W_MAPCONNECTIONS]
+ ld b,a
+.checkNorth
+ bit 3,b
+ jr z,.checkSouth
+ ld de,W_MAPCONN1PTR
+ call CopyMapConnectionHeader
+.checkSouth
+ bit 2,b
+ jr z,.checkWest
+ ld de,W_MAPCONN2PTR
+ call CopyMapConnectionHeader
+.checkWest
+ bit 1,b
+ jr z,.checkEast
+ ld de,W_MAPCONN3PTR
+ call CopyMapConnectionHeader
+.checkEast
+ bit 0,b
+ jr z,.getObjectDataPointer
+ ld de,W_MAPCONN4PTR
+ call CopyMapConnectionHeader
+.getObjectDataPointer
+ ld a,[hli]
+ ld [wd3a9],a
+ ld a,[hli]
+ ld [wd3aa],a
+ push hl
+ ld a,[wd3a9]
+ ld l,a
+ ld a,[wd3aa]
+ ld h,a ; hl = base of object data
+ ld de,wd3ad ; background tile ID
+ ld a,[hli]
+ ld [de],a ; save background tile ID
+.loadWarpData
+ ld a,[hli]
+ ld [wNumberOfWarps],a
+ and a
+ jr z,.loadSignData
+ ld c,a
+ ld de,wWarpEntries
+.warpLoop ; one warp per loop iteration
+ ld b,$04
+.warpInnerLoop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec b
+ jr nz,.warpInnerLoop
+ dec c
+ jr nz,.warpLoop
+.loadSignData
+ ld a,[hli] ; number of signs
+ ld [wd4b0],a ; save the number of signs
+ and a ; are there any signs?
+ jr z,.loadSpriteData ; if not, skip this
+ call CopySignData ; 0eb3 (0:0eb3)
+.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
+ call InitSprites
+.finishUp
+ predef LoadTilesetHeader
+ ld a,[wd72e]
+ bit 5,a ; did a battle happen immediately before this?
+ jr nz,.asm_0e73
+ callab Func_fc4fa ; 3f:44fa
+ 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,[W_CURMAPHEIGHT] ; map height in 4x4 tile blocks
+ add a ; double it
+ ld [wd524],a ; store map height in 2x2 tile blocks
+ ld a,[W_CURMAPWIDTH] ; map width in 4x4 tile blocks
+ add a ; double it
+ ld [wd525],a ; map width in 2x2 tile blocks
+ ld a,[W_CURMAP]
+ ld c,a
+ ld b,$00
+ ld a,[H_LOADEDROMBANK]
+ push af
+ switchbank MapSongBanks
+ ld hl, MapSongBanks ; 3f:4000
+ add hl,bc
+ add hl,bc
+ ld a,[hli]
+ ld [wd35b],a ; music 1
+ ld a,[hl]
+ ld [wd35c],a ; music 2
+ pop af
+ call BankswitchCommon
+ ret
+
+; function to copy map connection data from ROM to WRAM
+; Input: hl = source, de = destination
+CopyMapConnectionHeader:: ; 1238 (0:1238)
+ ld c,$0b
+.loop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec c
+ jr nz,.loop
+ ret
+
+CopySignData:: ; 0eb3 (0:0eb3)
+ ld de,wd4b1 ; start of sign coords
+ ld bc,wd4d1 ; start of sign text ids
+ ld a,[wd4b0] ; 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:: ; 1241 (0:1241)
+ 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 GoPAL_SET
+ call LoadPlayerSpriteGraphics
+ ld a,[wd732]
+ and a,1 << 4 | 1 << 3 ; fly warp or dungeon warp
+ jr nz,.restoreRomBank
+ ld a,[W_FLAGS_D733]
+ bit 1,a
+ jr nz,.restoreRomBank
+ call Func_235f ; music related
+ call Func_2312 ; music related
+.restoreRomBank
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+
+LoadScreenRelatedData:: ; 0f0c (0:0f0c)
+ call LoadTileBlockMap
+ call LoadTilesetTilePatternData
+ call LoadCurrentMapView
+ ret
+
+Func_0f16:: ; 0f16 (0:0f16)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ call DisableLCD
+ call ResetMapVariables
+ ld a,[W_CURMAP]
+ call SwitchToMapRomBank
+ call LoadScreenRelatedData
+ call CopyMapViewToVRAM
+ ld de,vBGMap1
+ call CopyMapViewToVRAM2
+ call EnableLCD
+ call ReloadMapSpriteTilePatterns
+ pop af
+ call BankswitchCommon
+ jr .asm_0f4d
+Func_0f3d:: ; 0f3d (0:0f3d)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,[W_CURMAP]
+ call SwitchToMapRomBank
+ call LoadTileBlockMap
+ pop af
+ call BankswitchCommon
+.asm_0f4d
+ ld hl, Func_f02da
+ ld b,BANK(Func_f02da) ; 3c:42da
+ jp Bankswitch
+ ret ; useless?
+
+ResetMapVariables:: ; 0f56 (0:0f56)
+ ld a,$98
+ ld [wMapViewVRAMPointer + 1],a
+ xor a
+ ld [wMapViewVRAMPointer],a
+ ld [hSCY],a
+ ld [hSCX],a
+ ld [wWalkCounter],a
+ ld [wd119],a
+ ld [W_SPRITESETID],a
+ ld [wWalkBikeSurfStateCopy],a
+ ret
+
+CopyMapViewToVRAM:: ; 0f70 (0:0f70)
+; copy current map view to VRAM
+ ld de,vBGMap0
+CopyMapViewToVRAM2: ; 0f73 (0:0f73)
+ ld hl,wTileMap
+ ld b,18
+.vramCopyLoop
+ ld c,20
+.vramCopyInnerLoop
+ ld a,[hli]
+ ld [de],a
+ inc e
+ dec c
+ jr nz,.vramCopyInnerLoop
+ ld a,32 - 20 ; total vram map width in tiles - screen width in tiles
+ add e
+ ld e,a
+ jr nc,.noCarry
+ inc d
+.noCarry
+ dec b
+ jr nz,.vramCopyLoop
+ ret
+
+; function to switch to the ROM bank that a map is stored in
+; Input: a = map number
+SwitchToMapRomBank:: ; 0f8b (0:0f8b)
+ push hl
+ push bc
+ ld c,a
+ ld b,$00
+ 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 BankswitchCommon
+ pop bc
+ pop hl
+ ret
+
+GetMapHeaderPointer:: ; 0fa7 (0:0fa7)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ switchbank Pointer_fc1f2 ; 3f:41f2
+ push de
+ ld a,[W_CURMAP]
+ ld e,a
+ ld d,$0
+ ld hl,Pointer_fc1f2
+ add hl,de
+ add hl,de
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a
+ pop de
+ pop af
+ jp BankswitchCommon
+
+IgnoreInputForHalfSecond: ; 0fc3 (0:0fc3)
+ ld a, 30
+ ld [wIgnoreInputCounter], a
+ ld hl, wd730
+ ld a, [hl]
+ or $26
+ ld [hl], a ; set ignore input bit
+ ret
+
+ResetUsingStrengthOutOfBattleBit: ; 0fd0 (0:0fd0)
+ ld hl, wd728
+ res 0, [hl]
+ ret
+
+ForceBikeOrSurf:: ; 0fd6 (0:0fd6)
+ ld b, BANK(RedSprite)
+ ld hl, LoadPlayerSpriteGraphics
+ call Bankswitch
+ jp PlayDefaultMusic ; update map/player state?
+
+; Handle the player jumping down
+; a ledge in the overworld.
+HandleMidJump:: ; 0fe1 (0:0fe1)
+ ld a,[wd736]
+ bit 7,a ; jumping down a ledge?
+ ret z
+ ld b, BANK(_HandleMidJump)
+ ld hl, _HandleMidJump
+ jp Bankswitch
+
+IsSpinning:: ; 0ff0 (0:0ff0)
+ ld a,[wd736]
+ bit 7,a
+ ret z ; no spinning
+ ld b, BANK(LoadSpinnerArrowTiles); spin while moving
+ ld hl,LoadSpinnerArrowTiles ; 11:5077
+ jp Bankswitch
+
+Func_0ffe:: ; 0ffe (0:0ffe)
+ ld hl, Func_fcf0c ; 3f:4f0c
+ ld b, BANK(Func_fcf0c)
+ jp Bankswitch
+
+InitSprites:: ; 1006 (0:1006)
+ ld a,[hli]
+ ld [W_NUMSPRITES],a ; save the number of sprites
+ push hl
+ push hl
+ push de
+ push bc
+ call ZeroSpriteStateData
+ call DisableRegularSprites
+ ld hl,W_MAPSPRITEDATA
+ ld bc,$20
+ xor a
+ call FillMemory
+ pop bc
+ pop de
+ pop hl
+ ld a,[W_NUMSPRITES]
+ 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,$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 [$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,$a
+ ld e,a
+ inc c
+ inc c
+ dec b
+ jr nz,.loadSpriteLoop
+ ret
+
+ZeroSpriteStateData:: ; 1050 (0:1050)
+; zero C110-C1EF and C210-C2EF
+; C1F0-C1FF and C2F0-C2FF is probably used for Pikachu
+ ld hl,wSpriteStateData1 + $10
+ ld de,wSpriteStateData2 + $10
+ xor a
+ ld b,$e0
+.loop
+ ld [hli],a
+ ld [de],a
+ inc e
+ dec b
+ jr nz,.loop
+ ret
+
+DisableRegularSprites:: ; 1060 (0:1060)
+; initialize all C100-C1FF sprite entries to disabled (other than player's and pikachu)
+ ld hl,wSpriteStateData1 + $12
+ ld de,$10
+ ld c,$e
+.loop
+ ld [hl],$ff
+ add hl,de
+ dec c
+ jr nz,.loop
+ ret
+
+LoadSprite:: ; 106f (0:106f)
+ push hl
+ ld b,$0
+ ld hl,W_MAPSPRITEDATA
+ 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 a,$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,W_MAPSPRITEEXTRADATA
+ 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,W_MAPSPRITEEXTRADATA
+ 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,W_MAPSPRITEEXTRADATA
+ 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 ; end of home/overworld.asm = 10b9 (0:10b9)
\ No newline at end of file |