diff options
Diffstat (limited to 'home/overworld.asm')
-rw-r--r-- | home/overworld.asm | 1428 |
1 files changed, 657 insertions, 771 deletions
diff --git a/home/overworld.asm b/home/overworld.asm index 051d055e..7b9fadfa 100644 --- a/home/overworld.asm +++ b/home/overworld.asm @@ -1,14 +1,9 @@ -HandleMidJump:: -; Handle the player jumping down -; a ledge in the overworld. - jpba _HandleMidJump - -EnterMap:: +EnterMap:: ; 01d7 (0:01d7) ; Load a new map. ld a, $ff ld [wJoyIgnore], a call LoadMapData - callba ClearVariablesAfterLoadingMapData + callba ClearVariablesAfterLoadingMapData ; 3:407c ld hl, wd72c bit 0, [hl] ; has the player already made 3 steps since the last battle? jr z, .skipGivingThreeStepsOfNoRandomBattles @@ -24,11 +19,18 @@ EnterMap:: ld a, [hl] and 1 << 4 | 1 << 3 ; fly warp or dungeon warp jr z, .didNotEnterUsingFlyWarpOrDungeonWarp - res 3, [hl] callba EnterMapAnim call UpdateSprites + ld hl, wd732 + res 3, [hl] + ld hl, wd72e + res 4, [hl] .didNotEnterUsingFlyWarpOrDungeonWarp + call IsSurfingPikachuInParty callba CheckForceBikeOrSurf ; handle currents in SF islands and forced bike riding in cycling road + ld hl, wd732 + bit 4, [hl] + res 4, [hl] ld hl, wd72d res 5, [hl] call UpdateSprites @@ -38,19 +40,18 @@ EnterMap:: xor a ld [wJoyIgnore], a -OverworldLoop:: +OverworldLoop:: ; 0242 (0:0242) call DelayFrame -OverworldLoopLessDelay:: +OverworldLoopLessDelay:: ; 0245 (0:0245) call DelayFrame + call IsSurfingPikachuInParty call LoadGBPal - ld a,[wd736] - bit 6,a ; jumping down a ledge? - call nz, HandleMidJump + call HandleMidJump ld a,[wWalkCounter] and a jp nz,.moveAhead ; if the player sprite has not yet completed the walking animation call JoypadOverworld ; get joypad state (which is possibly simulated) - callba SafariZoneCheck + callba SafariZoneCheck ; 7:6321 ld a,[wSafariZoneGameOver] and a jp nz,WarpFound2 @@ -91,7 +92,10 @@ OverworldLoopLessDelay:: ld a,[$ffeb] and a jp z,OverworldLoop ; jump if a hidden object or bookshelf was found, but not if a card key door was found + xor a + ld [wd436],a ; new yellow address call IsSpriteOrSignInFrontOfPlayer + call Func_0ffe ld a,[hSpriteIndexOrTextID] and a jp z,OverworldLoop @@ -109,39 +113,38 @@ OverworldLoopLessDelay:: ld a,[wEnteringCableClub] and a jr z,.checkForOpponent - dec a - ld a,0 - ld [wEnteringCableClub],a - jr z,.changeMap -; XXX can this code be reached? - predef LoadSAV - ld a,[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] -.changeMap + 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] - call UpdateSprites - ld a,1 + xor a + ld [wd435], a + ld a, $1 ld [wCheckFor180DegreeTurn],a ld a,[wPlayerMovingDirection] ; the direction that was pressed last time and a - jp z,OverworldLoop + jr z, .overworldloop ; if a direction was pressed last time ld [wPlayerLastStopDirection],a ; save the last direction xor a ld [wPlayerMovingDirection],a ; zero the direction +.overworldloop jp OverworldLoop .checkIfDownButtonIsPressed ld a,[hJoyHeld] ; current joypad state @@ -168,8 +171,9 @@ OverworldLoopLessDelay:: .checkIfRightButtonIsPressed bit 4,a ; right button jr z,.noDirectionButtonsPressed - ld a,1 ; PLAYER_DIR_RIGHT - ld [wSpriteStateData1 + 5],a ; delta X + ld a,$1 + ld [wSpriteStateData1 + 5],a + ld a,$1 .handleDirectionButtonPress ld [wPlayerDirection],a ; new direction ld a,[wd730] @@ -183,46 +187,15 @@ OverworldLoopLessDelay:: ld a,[wPlayerLastStopDirection] ; old direction cp b jr z,.noDirectionChange -; Check whether the player did a 180-degree turn. -; It appears that this code was supposed to show the player rotate by having -; the player's sprite face an intermediate direction before facing the opposite -; direction (instead of doing an instantaneous about-face), but the intermediate -; direction is only set for a short period of time. It is unlikely for it to -; ever be visible because DelayFrame is called at the start of OverworldLoop and -; normally not enough cycles would be executed between then and the time the -; direction is set for V-blank to occur while the direction is still set. - swap a ; put old direction in upper half - or b ; put new direction in lower half - cp a,(PLAYER_DIR_DOWN << 4) | PLAYER_DIR_UP ; change dir from down to up - jr nz,.notDownToUp - ld a,PLAYER_DIR_LEFT - ld [wPlayerMovingDirection],a - jr .holdIntermediateDirectionLoop -.notDownToUp - cp a,(PLAYER_DIR_UP << 4) | PLAYER_DIR_DOWN ; change dir from up to down - jr nz,.notUpToDown - ld a,PLAYER_DIR_RIGHT - ld [wPlayerMovingDirection],a - jr .holdIntermediateDirectionLoop -.notUpToDown - cp a,(PLAYER_DIR_RIGHT << 4) | PLAYER_DIR_LEFT ; change dir from right to left - jr nz,.notRightToLeft - ld a,PLAYER_DIR_DOWN - ld [wPlayerMovingDirection],a - jr .holdIntermediateDirectionLoop -.notRightToLeft - cp a,(PLAYER_DIR_LEFT << 4) | PLAYER_DIR_RIGHT ; change dir from left to right - jr nz,.holdIntermediateDirectionLoop - ld a,PLAYER_DIR_UP - ld [wPlayerMovingDirection],a -.holdIntermediateDirectionLoop + ld a,$8 + ld [wd435],a +; unlike in red/blue, yellow does not have the 180 degrees odd code ld hl,wFlags_0xcd60 set 2,[hl] - ld hl,wCheckFor180DegreeTurn - dec [hl] - jr nz,.holdIntermediateDirectionLoop - ld a,[wPlayerDirection] - ld [wPlayerMovingDirection],a + xor a + ld [wCheckFor180DegreeTurn],a + ld a,[wd52a] + ld [wd528],a call NewBattle jp c,.battleOccurred jp OverworldLoop @@ -254,46 +227,25 @@ OverworldLoopLessDelay:: .noCollision ld a,$08 ld [wWalkCounter],a + callab Func_fcc08 jr .moveAhead2 .moveAhead - ld a,[wd736] - bit 7,a - jr z,.noSpinning - callba LoadSpinnerArrowTiles ; spin while moving -.noSpinning - call UpdateSprites + call IsSpinning + call UpdateSprites ; move sprites .moveAhead2 ld hl,wFlags_0xcd60 res 2,[hl] - ld a,[wWalkBikeSurfState] - dec a ; riding a bike? - jr nz,.normalPlayerSpriteAdvancement - ld a,[wd736] - bit 6,a ; jumping a ledge? - jr nz,.normalPlayerSpriteAdvancement - call BikeSpeedup ; if riding a bike and not jumping a ledge -.normalPlayerSpriteAdvancement + 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 - ld a,[wd730] - bit 7,a - jr nz,.doneStepCounting ; if button presses are being simulated, don't count steps -; step counting - ld hl,wStepCounter - dec [hl] - ld a,[wd72c] - bit 0,a - jr z,.doneStepCounting - ld hl,wNumberOfNoRandomBattleStepsLeft - dec [hl] - jr nz,.doneStepCounting - ld hl,wd72c - res 0,[hl] ; indicate that the player has stepped thrice since the last battle -.doneStepCounting - CheckEvent EVENT_IN_SAFARI_ZONE + call StepCountCheck + ld a,[wd790] + bit 7,a ; in the safari zone? jr z,.notSafariZone callba SafariZoneCheckSteps ld a,[wSafariZoneGameOver] @@ -325,7 +277,8 @@ OverworldLoopLessDelay:: ld a,[W_CURMAP] cp a,CINNABAR_GYM jr nz,.notCinnabarGym - SetEvent EVENT_2A7 + ld hl,wd79b + set 7,[hl] .notCinnabarGym ld hl,wd72e set 5,[hl] @@ -335,12 +288,31 @@ OverworldLoopLessDelay:: callab AnyPartyAlive ld a,d and a - jr z,.allPokemonFainted + jr z,AllPokemonFainted .noFaintCheck ld c,10 call DelayFrames jp EnterMap -.allPokemonFainted + +StepCountCheck:: ; 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 + +AllPokemonFainted:: ; 0475 (0:0475) ld a,$ff ld [W_ISINBATTLE],a call RunMapScript @@ -348,7 +320,7 @@ OverworldLoopLessDelay:: ; 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:: ; 0683 (0:0683) +NewBattle:: ; 0480 (0:0480) ld a,[wd72d] bit 4,a jr nz,.noBattle @@ -357,39 +329,45 @@ NewBattle:: ; 0683 (0:0683) ld a,[wd72e] bit 4,a jr nz,.noBattle - jpba InitBattle + jpba InitBattle ; 3d:5ff2 .noBattle and a ret -; function to make bikes twice as fast as walking -BikeSpeedup:: ; 06a0 (0:06a0) +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 a,ROUTE_17 ; Cycling Road + cp ROUTE_17 ; cycling road jr nz,.goFaster ld a,[hJoyHeld] and a,D_UP | D_LEFT | D_RIGHT ret nz .goFaster - jp AdvancePlayerSprite + call AdvancePlayerSprite + ret ; check if the player has stepped onto a warp after having not collided -CheckWarpsNoCollision:: ; 06b4 (0:06b4) +CheckWarpsNoCollision:: ; 04bd (0:04bd) ld a,[wNumberOfWarps] and a jp z,CheckMapConnections - ld a,[wNumberOfWarps] 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:: ; 06cc (0:06cc) +CheckWarpsNoCollisionLoop:: ; 04d5 (0:04d5) ld a,[hli] ; check if the warp's Y position matches cp d jr nz,CheckWarpsNoCollisionRetry1 @@ -424,9 +402,20 @@ CheckWarpsNoCollisionLoop:: ; 06cc (0:06cc) 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) +CheckWarpsCollision:: ; 051a (0:051a) ld a,[wNumberOfWarps] ld c,a ld hl,wWarpEntries @@ -455,20 +444,13 @@ CheckWarpsCollision:: ; 0706 (0:0706) jr nz,.loop jp OverworldLoop -CheckWarpsNoCollisionRetry1:: ; 072f (0:072f) - inc hl -CheckWarpsNoCollisionRetry2:: ; 0730 (0:0730) - inc hl - inc hl - jp ContinueCheckWarpsNoCollisionLoop - -WarpFound1:: ; 0735 (0:0735) +WarpFound1:: ; 0543 (0:0543) ld a,[hli] ld [wDestinationWarpID],a ld a,[hli] ld [hWarpDestinationMap],a -WarpFound2:: ; 073c (0:073c) +WarpFound2:: ; 054a (0:054a) ld a,[wNumberOfWarps] sub c ld [wWarpedFromWhichWarp],a ; save ID of used warp @@ -489,6 +471,7 @@ WarpFound2:: ; 073c (0:073c) 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 @@ -503,9 +486,9 @@ WarpFound2:: ; 073c (0:073c) dec a ; is the player on a warp pad? jr nz,.notWarpPad ; if the player is on a warp pad + call LeaveMapAnim ld hl,wd732 set 3,[hl] - call LeaveMapAnim jr .skipMapChangeSound .notWarpPad call PlayMapChangeSound @@ -513,8 +496,10 @@ WarpFound2:: ; 073c (0:073c) 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 @@ -526,13 +511,8 @@ WarpFound2:: ; 073c (0:073c) call IgnoreInputForHalfSecond jp EnterMap -ContinueCheckWarpsNoCollisionLoop:: ; 07b5 (0:07b5) - inc b ; increment warp number - dec c ; decrement number of warps - jp nz,CheckWarpsNoCollisionLoop - ; if no matching warp was found -CheckMapConnections:: ; 07ba (0:07ba) +CheckMapConnections:: ; 05db (0:05db) .checkWestMap ld a,[W_XCOORD] cp a,$ff @@ -656,28 +636,38 @@ CheckMapConnections:: ; 07ba (0:07ba) 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 PlayDefaultMusicFadeOutCurrent - ld b, SET_PAL_OVERWORLD +.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 PlayDefaultMusicFadeOutCurrent ; music + ld b,SET_PAL_OVERWORLD call RunPaletteCommand ; Since the sprite set shouldn't change, this will just update VRAM slots at ; $C2XE without loading any tile patterns. - callba InitMapSprites + call InitMapSprites call LoadTileBlockMap jp OverworldLoopLessDelay .didNotEnterConnectedMap jp OverworldLoop ; function to play a sound when changing maps -PlayMapChangeSound:: ; 08c9 (0:08c9) +PlayMapChangeSound:: ; 06ef (0:06ef) + ld a,[W_CURMAPTILESET] + cp FACILITY + jr z,.didNotGoThroughDoor + cp CEMETERY + jr z,.didNotGoThroughDoor aCoord 8, 8 ; upper left tile of the 4x4 square the player's sprite is standing on - cp a,$0b ; door tile in tileset 0 + cp UNDERGROUND ; door tile in tileset 0 jr nz,.didNotGoThroughDoor - ld a,SFX_GO_INSIDE + ld a, $ad ; SFX_GO_INSIDE jr .playSound .didNotGoThroughDoor - ld a,SFX_GO_OUTSIDE + ld a, $b5 ; SFX_GO_OUTSIDE .playSound call PlaySound ld a,[wMapPalOffset] @@ -685,7 +675,7 @@ PlayMapChangeSound:: ; 08c9 (0:08c9) ret nz jp GBFadeOutToBlack -CheckIfInOutsideMap:: ; 08e1 (0:08e1) +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) @@ -699,7 +689,7 @@ CheckIfInOutsideMap:: ; 08e1 (0:08e1) ; "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) +ExtraWarpCheck:: ; 071a (0:071a) ld a, [W_CURMAP] cp SS_ANNE_3 jr z, .useFunction1 @@ -729,14 +719,14 @@ ExtraWarpCheck:: ; 08e9 (0:08e9) ld b, BANK(IsWarpTileInFrontOfPlayer) jp Bankswitch -MapEntryAfterBattle:: ; 091f (0:091f) +MapEntryAfterBattle:: ; 0750 (0:0750) callba IsPlayerStandingOnWarp ; for enabling warp testing after collisions ld a,[wMapPalOffset] and a jp z,GBFadeInFromWhite jp LoadGBPal -HandleBlackOut:: +HandleBlackOut:: ; 0762 (0:0762) ; For when all the player's pokemon faint. ; Does not print the "blacked out" message. @@ -745,47 +735,49 @@ HandleBlackOut:: call StopMusic ld hl, wd72e res 5, [hl] - ld a, Bank(ResetStatusAndHalveMoneyOnBlackout) ; also Bank(SpecialWarpIn) and Bank(SpecialEnterMap) - ld [H_LOADEDROMBANK], a - ld [MBC1RomBank], a - call ResetStatusAndHalveMoneyOnBlackout + switchbank SpecialWarpIn ; also Bank(SpecialEnterMap) + callab ResetStatusAndHalveMoneyOnBlackout ; 3c:4274 call SpecialWarpIn call PlayDefaultMusicFadeOutCurrent jp SpecialEnterMap -StopMusic:: - ld [wAudioFadeOutControl], a - ld a, $ff - ld [wNewSoundID], a - call PlaySound +StopMusic:: ; 0788 (0:0788) + ld [wMusicHeaderPointer], a + call StopAllMusic .wait ld a, [wAudioFadeOutControl] and a jr nz, .wait jp StopAllSounds -HandleFlyWarpOrDungeonWarp:: +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 [MBC1RomBank], a - call SpecialWarpIn + call Func_07c4 + callbs SpecialWarpIn jp SpecialEnterMap -LeaveMapAnim:: - jpba _LeaveMapAnim - -LoadPlayerSpriteGraphics:: +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 @@ -820,10 +812,10 @@ LoadPlayerSpriteGraphics:: dec a jp z, LoadBikePlayerSpriteGraphics dec a - jp z, LoadSurfingPlayerSpriteGraphics + jp z, LoadSurfingPlayerSpriteGraphics2 jp LoadWalkingPlayerSpriteGraphics -IsBikeRidingAllowed:: +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. @@ -853,7 +845,7 @@ IsBikeRidingAllowed:: INCLUDE "data/bike_riding_tilesets.asm" ; load the tile pattern data of the current tileset into VRAM -LoadTilesetTilePatternData:: ; 09e8 (0:09e8) +LoadTilesetTilePatternData:: ; 0828 (0:0828) ld a,[W_TILESETGFXPTR] ld l,a ld a,[W_TILESETGFXPTR + 1] @@ -861,23 +853,16 @@ LoadTilesetTilePatternData:: ; 09e8 (0:09e8) ld de,vTileset ld bc,$600 ld a,[W_TILESETBANK] - jp FarCopyData2 + jp FarCopyData ; this loads the current maps complete tile map (which references blocks, not individual tiles) to C6E8 ; it can also load partial tile maps of connected maps into a border of length 3 around the current map -LoadTileBlockMap:: ; 09fc (0:09fc) +LoadTileBlockMap:: ; 083c (0:083c) ; fill C6E8-CBFB with the background tile ld hl,wOverworldMap - ld a,[wMapBackgroundTile] - ld d,a ld bc,$0514 -.backgroundTileLoop - ld a,d - ld [hli],a - dec bc - ld a,c - or b - jr nz,.backgroundTileLoop + 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 @@ -994,7 +979,7 @@ LoadTileBlockMap:: ; 09fc (0:09fc) .done ret -LoadNorthSouthConnectionsTileMap:: ; 0ade (0:0ade) +LoadNorthSouthConnectionsTileMap:: ; 0919 (0:0919) ld c,MAP_BORDER .loop push de @@ -1026,7 +1011,7 @@ LoadNorthSouthConnectionsTileMap:: ; 0ade (0:0ade) jr nz,.loop ret -LoadEastWestConnectionsTileMap:: ; 0b02 (0:0b02) +LoadEastWestConnectionsTileMap:: ; 093d (0:093d) push hl push de ld c,MAP_BORDER @@ -1056,9 +1041,8 @@ LoadEastWestConnectionsTileMap:: ; 0b02 (0:0b02) 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) +; if so, carry is set. otherwise, carry is cleared +IsSpriteOrSignInFrontOfPlayer:: ; 095e (0:095e) xor a ld [hSpriteIndexOrTextID],a ld a,[wNumSigns] @@ -1066,39 +1050,10 @@ IsSpriteOrSignInFrontOfPlayer:: ; 0b23 (0:0b23) jr z,.extendRangeOverCounter ; if there are signs predef GetTileAndCoordsInFrontOfPlayer ; get the coordinates in front of the player in de - ld hl,wSignCoords - ld a,[wNumSigns] - ld b,a - ld c,0 -.signLoop - inc c - ld a,[hli] ; sign Y - cp d - jr z,.yCoordMatched - inc hl - jr .retry -.yCoordMatched - ld a,[hli] ; sign X - cp e - jr nz,.retry -.xCoordMatched -; found sign - push hl - push bc - ld hl,wSignTextIDs - ld b,0 - dec c - add hl,bc - ld a,[hl] - ld [hSpriteIndexOrTextID],a ; store sign text ID - pop bc - pop hl - ret -.retry - dec b - jr nz,.signLoop -; check if the player is front of a counter in a pokemon center, pokemart, etc. and if so, extend the range at which he can talk to the NPC + call SignLoop + ret c .extendRangeOverCounter +; check if the player is front of a counter in a pokemon center, pokemart, etc. and if so, extend the range at which he can talk to the NPC predef GetTileAndCoordsInFrontOfPlayer ; get the tile in front of the player in c ld hl,W_TILESETTALKINGOVERTILES ; list of tiles that extend talking range (counter tiles) ld b,3 @@ -1110,12 +1065,11 @@ IsSpriteOrSignInFrontOfPlayer:: ; 0b23 (0:0b23) 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) +; 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:: ; 0b6d (0:0b6d) - lb bc, $3c, $40 ; Y and X position of player sprite +IsSpriteInFrontOfPlayer2:: ; 0985 (0:0985) + lb bc,$3c, $40 ; Y and X position of player sprite ld a,[wSpriteStateData1 + 9] ; direction the player is facing .checkIfPlayerFacingUp cp SPRITE_FACING_UP @@ -1152,13 +1106,10 @@ IsSpriteInFrontOfPlayer2:: ; 0b6d (0:0b6d) ld a,PLAYER_DIR_LEFT .doneCheckingDirection ld [wPlayerDirection],a - ld a,[W_NUMSPRITES] ; number of sprites - and a - ret z -; if there are sprites ld hl,wSpriteStateData1 + $10 - ld d,a +; yellow does not have the "if sprites are existant" check ld e,$01 + ld d,$f .spriteLoop push hl ld a,[hli] ; image (0 if no sprite) @@ -1184,6 +1135,7 @@ IsSpriteInFrontOfPlayer2:: ; 0b6d (0:0b6d) inc e dec d jr nz,.spriteLoop + xor a ret .foundSpriteInFrontOfPlayer pop hl @@ -1194,11 +1146,55 @@ IsSpriteInFrontOfPlayer2:: ; 0b6d (0:0b6d) 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:: ; 0bd1 (0:0bd1) +CollisionCheckOnLand:: ; 0a1c (0:0a1c) ld a,[wd736] bit 6,a ; is the player jumping? jr nz,.noCollision @@ -1210,14 +1206,31 @@ CollisionCheckOnLand:: ; 0bd1 (0:0bd1) ld d,a ld a,[wSpriteStateData1 + 12] ; the player sprite's collision data (bit field) (set in the sprite movement code) and d ; check if a sprite is in the direction the player is trying to go + nop ; ??? why is this in the code jr nz,.collision xor a ld [hSpriteIndexOrTextID],a call IsSpriteInFrontOfPlayer ; check for sprite collisions again? when does the above check fail to detect a sprite collision? + jr nc,.asm_0a5c + res 7,[hl] ld a,[hSpriteIndexOrTextID] and a ; was there a sprite collision? - jr nz,.collision + jr z,.asm_0a5c ; if no sprite collision + cp $f + jr nz,.collision + call Func_154a + 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 @@ -1225,9 +1238,9 @@ CollisionCheckOnLand:: ; 0bd1 (0:0bd1) jr nc,.noCollision .collision ld a,[wChannelSoundIDs + CH4] - cp a,SFX_COLLISION ; check if collision sound is already playing + cp $b4 ; SFX_COLLISION ; check if collision sound is already playing jr z,.setCarry - ld a,SFX_COLLISION + ld a, $b4 ; SFX_COLLISION call PlaySound ; play collision sound (if it's not already playing) .setCarry scf @@ -1238,35 +1251,24 @@ CollisionCheckOnLand:: ; 0bd1 (0:0bd1) ; 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) +CheckTilePassable:: ; 0a79 (0:0a79) 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 + 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:: ; 0c2a (0:0c2a) +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 + callba HandleLedges ; 6:67f4 + ; check if the player is trying to jump a ledge pop bc pop de pop hl @@ -1276,11 +1278,11 @@ CheckForJumpingAndTilePairCollisions:: ; 0c2a (0:0c2a) ret nz ; if not jumping -CheckForTilePairCollisions2:: ; 0c44 (0:0c44) +CheckForTilePairCollisions2:: ; 0aa0 (0:0aa0) aCoord 8, 9 ; tile the player is on ld [wTilePlayerStandingOn],a -CheckForTilePairCollisions:: ; 0c4a (0:0c4a) +CheckForTilePairCollisions:: ; 0aa6 (0:0aa6) ld a,[wTileInFrontOfPlayer] ld c,a .tilePairCollisionLoop @@ -1330,7 +1332,7 @@ CheckForTilePairCollisions:: ; 0c4a (0:0c4a) ; 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) +TilePairCollisionsLand:: ; 0ada (0:0ada) db CAVERN, $20, $05 db CAVERN, $41, $05 db FOREST, $30, $2E @@ -1344,19 +1346,18 @@ TilePairCollisionsLand:: ; 0c7e (0:0c7e) db FOREST, $5F, $2E db $FF -TilePairCollisionsWater:: ; 0ca0 (0:0ca0) +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:: ; 0caa (0:0caa) +LoadCurrentMapView:: ; 0b06 (0:0b06) ld a,[H_LOADEDROMBANK] push af ld a,[W_TILESETBANK] ; tile data ROM bank - ld [H_LOADEDROMBANK],a - ld [MBC1RomBank],a ; switch to ROM bank that contains tile data + call BankswitchCommon ; switch to ROM bank that contains tile data ld a,[wCurrentTileBlockMapViewPointer] ; address of upper left corner of current map view ld e,a ld a,[wCurrentTileBlockMapViewPointer + 1] @@ -1437,271 +1438,36 @@ LoadCurrentMapView:: ; 0caa (0:0caa) dec b jr nz,.rowLoop2 pop af - ld [H_LOADEDROMBANK],a - ld [MBC1RomBank],a ; restore previous ROM bank + call BankswitchCommon ; restore previous ROM bank ret -AdvancePlayerSprite:: ; 0d27 (0:0d27) - ld a,[wSpriteStateData1 + 3] ; delta Y - ld b,a - ld a,[wSpriteStateData1 + 5] ; delta X - ld c,a - ld hl,wWalkCounter ; walking animation counter - dec [hl] - jr nz,.afterUpdateMapCoords -; if it's the end of the animation, update the player's map coordinates - ld a,[W_YCOORD] - add b - ld [W_YCOORD],a - ld a,[W_XCOORD] - add c - ld [W_XCOORD],a -.afterUpdateMapCoords - ld a,[wWalkCounter] ; walking animation counter - cp a,$07 - jp nz,.scrollBackgroundAndSprites -; if this is the first iteration of the animation - ld a,c - cp a,$01 - jr nz,.checkIfMovingWest -; moving east - ld a,[wMapViewVRAMPointer] - ld e,a - and a,$e0 - ld d,a - ld a,e - add a,$02 - and a,$1f - or d - ld [wMapViewVRAMPointer],a - jr .adjustXCoordWithinBlock -.checkIfMovingWest - cp a,$ff - jr nz,.checkIfMovingSouth -; moving west - ld a,[wMapViewVRAMPointer] - ld e,a - and a,$e0 - ld d,a - ld a,e - sub a,$02 - and a,$1f - or d - ld [wMapViewVRAMPointer],a - jr .adjustXCoordWithinBlock -.checkIfMovingSouth - ld a,b - cp a,$01 - jr nz,.checkIfMovingNorth -; moving south - ld a,[wMapViewVRAMPointer] - add a,$40 - ld [wMapViewVRAMPointer],a - jr nc,.adjustXCoordWithinBlock - ld a,[wMapViewVRAMPointer + 1] - inc a - and a,$03 - or a,$98 - ld [wMapViewVRAMPointer + 1],a - jr .adjustXCoordWithinBlock -.checkIfMovingNorth - cp a,$ff - jr nz,.adjustXCoordWithinBlock -; moving north - ld a,[wMapViewVRAMPointer] - sub a,$40 - ld [wMapViewVRAMPointer],a - jr nc,.adjustXCoordWithinBlock - ld a,[wMapViewVRAMPointer + 1] - dec a - and a,$03 - or a,$98 - ld [wMapViewVRAMPointer + 1],a -.adjustXCoordWithinBlock - ld a,c - and a - jr z,.pointlessJump ; mistake? -.pointlessJump - ld hl,W_XBLOCKCOORD - ld a,[hl] - add c - ld [hl],a - cp a,$02 - jr nz,.checkForMoveToWestBlock -; moved into the tile block to the east - xor a - ld [hl],a - ld hl,wXOffsetSinceLastSpecialWarp - inc [hl] - ld de,wCurrentTileBlockMapViewPointer - call MoveTileBlockMapPointerEast - jr .updateMapView -.checkForMoveToWestBlock - cp a,$ff - jr nz,.adjustYCoordWithinBlock -; moved into the tile block to the west - ld a,$01 - ld [hl],a - ld hl,wXOffsetSinceLastSpecialWarp - dec [hl] - ld de,wCurrentTileBlockMapViewPointer - call MoveTileBlockMapPointerWest - jr .updateMapView -.adjustYCoordWithinBlock - ld hl,W_YBLOCKCOORD - ld a,[hl] - add b - ld [hl],a - cp a,$02 - jr nz,.checkForMoveToNorthBlock -; moved into the tile block to the south - xor a - ld [hl],a - ld hl,wYOffsetSinceLastSpecialWarp - inc [hl] - ld de,wCurrentTileBlockMapViewPointer - ld a,[W_CURMAPWIDTH] - call MoveTileBlockMapPointerSouth - jr .updateMapView -.checkForMoveToNorthBlock - cp a,$ff - jr nz,.updateMapView -; moved into the tile block to the north - ld a,$01 - ld [hl],a - ld hl,wYOffsetSinceLastSpecialWarp - dec [hl] - ld de,wCurrentTileBlockMapViewPointer - ld a,[W_CURMAPWIDTH] - call MoveTileBlockMapPointerNorth -.updateMapView - call LoadCurrentMapView - ld a,[wSpriteStateData1 + 3] ; delta Y - cp a,$01 - jr nz,.checkIfMovingNorth2 -; if moving south - call ScheduleSouthRowRedraw - jr .scrollBackgroundAndSprites -.checkIfMovingNorth2 - cp a,$ff - jr nz,.checkIfMovingEast2 -; if moving north - call ScheduleNorthRowRedraw - jr .scrollBackgroundAndSprites -.checkIfMovingEast2 - ld a,[wSpriteStateData1 + 5] ; delta X - cp a,$01 - jr nz,.checkIfMovingWest2 -; if moving east - call ScheduleEastColumnRedraw - jr .scrollBackgroundAndSprites -.checkIfMovingWest2 - cp a,$ff - jr nz,.scrollBackgroundAndSprites -; if moving west - call ScheduleWestColumnRedraw -.scrollBackgroundAndSprites - ld a,[wSpriteStateData1 + 3] ; delta Y - ld b,a - ld a,[wSpriteStateData1 + 5] ; delta X - ld c,a - sla b - sla c - ld a,[hSCY] - add b - ld [hSCY],a ; update background scroll Y - ld a,[hSCX] - add c - ld [hSCX],a ; update background scroll X -; shift all the sprites in the direction opposite of the player's motion -; so that the player appears to move relative to them - ld hl,wSpriteStateData1 + $14 - ld a,[W_NUMSPRITES] ; number of sprites - and a ; are there any sprites? - jr z,.done - ld e,a -.spriteShiftLoop - ld a,[hl] - sub b - ld [hli],a - inc l - ld a,[hl] - sub c - ld [hl],a - ld a,$0e - add l - ld l,a - dec e - jr nz,.spriteShiftLoop -.done - ret - -; the following four functions are used to move the pointer to the upper left -; corner of the tile block map in the direction of motion - -MoveTileBlockMapPointerEast:: ; 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,MAP_BORDER * 2 - ld b,a - ld a,[de] - add b - ld [de],a - ret nc - inc de - ld a,[de] - inc a - ld [de],a - ret - -MoveTileBlockMapPointerNorth:: ; 0e85 (0:0e85) - add a,MAP_BORDER * 2 - ld b,a - ld a,[de] - sub b - ld [de],a - ret nc - inc de - ld a,[de] - dec a - ld [de],a +AdvancePlayerSprite:: ; 0b7f (0:0b7f) + ld a,[wUpdateSpritesEnabled] + push af + ld a,$FF + ld [wUpdateSpritesEnabled],a + ld hl, _AdvancePlayerSprite ; 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:: ; 0e91 (0:0e91) - coord hl, 0, 0 +ScheduleNorthRowRedraw:: ; 0b95 (0:0b95) + hlCoord 0, 0 call CopyToRedrawRowOrColumnSrcTiles ld a,[wMapViewVRAMPointer] - ld [hRedrawRowOrColumnDest],a + ld [H_SCREENEDGEREDRAWADDR],a ld a,[wMapViewVRAMPointer + 1] ld [hRedrawRowOrColumnDest + 1],a ld a,REDRAW_ROW ld [hRedrawRowOrColumnMode],a ret -CopyToRedrawRowOrColumnSrcTiles:: ; 0ea6 (0:0ea6) +CopyToRedrawRowOrColumnSrcTiles:: ; 0baa (0:0baa) ld de,wRedrawRowOrColumnSrcTiles ld c,2 * SCREEN_WIDTH .loop @@ -1711,8 +1477,8 @@ CopyToRedrawRowOrColumnSrcTiles:: ; 0ea6 (0:0ea6) dec c jr nz,.loop ret - -ScheduleSouthRowRedraw:: ; 0eb2 (0:0eb2) + +ScheduleSouthRowRedraw:: ; 0bb6 (0:0bb6) coord hl, 0, 16 call CopyToRedrawRowOrColumnSrcTiles ld a,[wMapViewVRAMPointer] @@ -1731,7 +1497,7 @@ ScheduleSouthRowRedraw:: ; 0eb2 (0:0eb2) ld [hRedrawRowOrColumnMode],a ret -ScheduleEastColumnRedraw:: ; 0ed3 (0:0ed3) +ScheduleEastColumnRedraw:: ; 0bd6 (0:0bd7) coord hl, 18, 0 call ScheduleColumnRedrawHelper ld a,[wMapViewVRAMPointer] @@ -1749,7 +1515,7 @@ ScheduleEastColumnRedraw:: ; 0ed3 (0:0ed3) ld [hRedrawRowOrColumnMode],a ret -ScheduleColumnRedrawHelper:: ; 0ef2 (0:0ef2) +ScheduleColumnRedrawHelper:: ; 0bf6 (0:0bf6) ld de,wRedrawRowOrColumnSrcTiles ld c,SCREEN_HEIGHT .loop @@ -1769,7 +1535,7 @@ ScheduleColumnRedrawHelper:: ; 0ef2 (0:0ef2) jr nz,.loop ret -ScheduleWestColumnRedraw:: ; 0f08 (0:0f08) +ScheduleWestColumnRedraw:: ; 0c0c (0:0c0c) coord hl, 0, 0 call ScheduleColumnRedrawHelper ld a,[wMapViewVRAMPointer] @@ -1782,7 +1548,7 @@ ScheduleWestColumnRedraw:: ; 0f08 (0:0f08) ; 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) +DrawTileBlock:: ; 0c21 (0:0c21) push hl ld a,[W_TILESETBLOCKSPTR] ; pointer to tiles ld l,a @@ -1823,24 +1589,31 @@ DrawTileBlock:: ; 0f1d (0:0f1d) ret ; function to update joypad state and simulate button presses -JoypadOverworld:: ; 0f4d (0:0f4d) +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 - jr nz,.notForcedDownwards + ret nz ld a,[W_CURMAP] cp a,ROUTE_17 ; Cycling Road - jr nz,.notForcedDownwards + ret nz ld a,[hJoyHeld] and a,D_DOWN | D_UP | D_LEFT | D_RIGHT | B_BUTTON | A_BUTTON - jr nz,.notForcedDownwards + ret nz ld a,D_DOWN ld [hJoyHeld],a ; on the cycling road, if there isn't a trainer and the player isn't pressing buttons, simulate a down press -.notForcedDownwards + ret + +AreInputsSimulated:: ; 0c7b (0:0c7b) ld a,[wd730] bit 7,a ret z @@ -1850,24 +1623,15 @@ JoypadOverworld:: ; 0f4d (0:0f4d) 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] + 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 @@ -1883,6 +1647,26 @@ JoypadOverworld:: ; 0f4d (0:0f4d) 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 @@ -1893,7 +1677,7 @@ JoypadOverworld:: ; 0f4d (0:0f4d) ; 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) +CollisionCheckOnWater:: ; 0cca (0:0cca) ld a,[wd730] bit 7,a jp nz,.noCollision ; return and clear carry if button presses are being simulated @@ -1901,58 +1685,48 @@ CollisionCheckOnWater:: ; 0fb7 (0:0fb7) ld d,a ld a,[wSpriteStateData1 + 12] ; the player sprite's collision data (bit field) (set in the sprite movement code) and d ; check if a sprite is in the direction the player is trying to go - jr nz,.checkIfNextTileIsPassable ; bug? + jr nz,.collision ; 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,.noCollision 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 + ld c,a + call IsTilePassable + jr nc,.stopSurfing .collision ld a,[wChannelSoundIDs + CH4] - cp a,SFX_COLLISION ; check if collision sound is already playing + cp $b4 ; SFX_COLLISION jr z,.setCarry - ld a,SFX_COLLISION + ld a, $b4 ; SFX_COLLISION 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 +.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:: ; 101b (0:101b) +RunMapScript:: ; 0d2c (0:0d2c) push hl push de push bc @@ -1978,25 +1752,46 @@ RunMapScript:: ; 101b (0:101b) .return ret -LoadWalkingPlayerSpriteGraphics:: ; 104d (0:104d) - ld de,RedSprite - ld hl,vNPCSprites +LoadWalkingPlayerSpriteGraphics:: ; 0d5e (0:0d5e) +; new sprite copy stuff + xor a + ld [wd473],a + ld b,BANK(RedSprite) + ld de,RedSprite ; $4180 + +LoadSurfingPlayerSpriteGraphics2:: ; 0d69 (0:0d69) + ld a,[wd473] + and a + jr z,.asm_0d75 + dec a + jr z,LoadSurfingPlayerSpriteGraphics + dec a + jr z,.asm_0d7c +.asm_0d75 + ld a,[wd472] + bit 6,a + jr z,LoadSurfingPlayerSpriteGraphics +.asm_0d7c + ld b,BANK(SurfingPikachuSprite) + ld de,SurfingPikachuSprite ; 3f:6def jr LoadPlayerSpriteGraphicsCommon - -LoadSurfingPlayerSpriteGraphics:: ; 1055 (0:1055) + +LoadSurfingPlayerSpriteGraphics:: ; 0d83 (0:0d83) + ld b,BANK(RedSprite) ; not sure, but probably same bank (5) ld de,SeelSprite - ld hl,vNPCSprites jr LoadPlayerSpriteGraphicsCommon -LoadBikePlayerSpriteGraphics:: ; 105d (0:105d) +LoadBikePlayerSpriteGraphics:: ; 0d8a (0:0d8a) + ld b,BANK(RedCyclingSprite) ld de,RedCyclingSprite +LoadPlayerSpriteGraphicsCommon:: ; 0d8f (0:0d8f) ld hl,vNPCSprites - -LoadPlayerSpriteGraphicsCommon:: ; 1063 (0:1063) push de push hl - lb bc, BANK(RedSprite), $0c + push bc + ld c, $c call CopyVideoData + pop bc pop hl pop de ld a,$c0 @@ -2006,12 +1801,15 @@ LoadPlayerSpriteGraphicsCommon:: ; 1063 (0:1063) inc d .noCarry set 3,h - lb bc, BANK(RedSprite), $0c + ld c,$c jp CopyVideoData ; function to load data from the map header -LoadMapHeader:: ; 107c (0:107c) +LoadMapHeader:: ; 0dab (0:0dab) callba MarkTownVisitedAndLoadMissableObjects + jr .asm_0dbd + callba Func_f0a55 ; 3c:4a55 +.asm_0dbd ld a,[W_CURMAPTILESET] ld [wUnusedD119],a ld a,[W_CURMAP] @@ -2023,20 +1821,7 @@ LoadMapHeader:: ; 107c (0:107c) ld [hPreviousTileset],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 + call GetMapHeaderPointer ; copy the first 10 bytes (the fixed area) of the map data to D367-D370 ld de,W_CURMAPTILESET ld c,$0a @@ -2110,156 +1895,20 @@ LoadMapHeader:: ; 107c (0:107c) ld [wNumSigns],a and a ; are there any signs? jr z,.loadSpriteData ; if not, skip this - ld c,a - ld de,wSignTextIDs - ld a,d - ld [hSignCoordPointer],a - ld a,e - ld [hSignCoordPointer + 1],a - ld de,wSignCoords -.signLoop - ld a,[hli] - ld [de],a - inc de - ld a,[hli] - ld [de],a - inc de - push de - ld a,[hSignCoordPointer] - ld d,a - ld a,[hSignCoordPointer + 1] - ld e,a - ld a,[hli] - ld [de],a - inc de - ld a,d - ld [hSignCoordPointer],a - ld a,e - ld [hSignCoordPointer + 1],a - pop de - dec c - jr nz,.signLoop + call CopySignData ; 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 - 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 [hLoadSpriteTemp1],a ; save movement byte 2 - ld a,[hli] - ld [hLoadSpriteTemp2],a ; save text ID and flags byte - push bc - push hl - ld b,$00 - ld hl,W_MAPSPRITEDATA - add hl,bc - ld a,[hLoadSpriteTemp1] - ld [hli],a ; store movement byte 2 in byte 0 of sprite entry - ld a,[hLoadSpriteTemp2] - ld [hl],a ; this appears pointless, since the value is overwritten immediately after - ld a,[hLoadSpriteTemp2] - ld [hLoadSpriteTemp1],a - and a,$3f - ld [hl],a ; store text ID in byte 1 of sprite entry - pop hl - ld a,[hLoadSpriteTemp1] - bit 6,a - jr nz,.trainerSprite - bit 7,a - jr nz,.itemBallSprite - jr .regularSprite -.trainerSprite - ld a,[hli] - ld [hLoadSpriteTemp1],a ; save trainer class - ld a,[hli] - ld [hLoadSpriteTemp2],a ; save trainer number (within class) - push hl - ld hl,W_MAPSPRITEEXTRADATA - add hl,bc - ld a,[hLoadSpriteTemp1] - ld [hli],a ; store trainer class in byte 0 of the entry - ld a,[hLoadSpriteTemp2] - ld [hl],a ; store trainer number in byte 1 of the entry - pop hl - jr .nextSprite -.itemBallSprite - ld a,[hli] - ld [hLoadSpriteTemp1],a ; save item number - push hl - ld hl,W_MAPSPRITEEXTRADATA - add hl,bc - ld a,[hLoadSpriteTemp1] - ld [hli],a ; store item number in byte 0 of the entry - xor a - ld [hl],a ; zero byte 1, since it is not used - pop hl - jr .nextSprite -.regularSprite - push hl - ld hl,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 + jr nz,.finishUp ; if so, skip this because battles don't destroy this data + call InitSprites .finishUp predef LoadTilesetHeader - callab LoadWildData + ld a,[wd72e] + bit 5,a ; did a battle happen immediately before this? + jr nz,.asm_0e73 + callab Func_fc4fa ; 3f:44fa +.asm_0e73 + callab LoadWildData ; 3:4b62 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 @@ -2272,10 +1921,8 @@ LoadMapHeader:: ; 107c (0:107c) ld b,$00 ld a,[H_LOADEDROMBANK] push af - ld a, BANK(MapSongBanks) - ld [H_LOADEDROMBANK],a - ld [MBC1RomBank],a - ld hl, MapSongBanks + switchbank MapSongBanks + ld hl, MapSongBanks ; 3f:4000 add hl,bc add hl,bc ld a,[hli] @@ -2283,13 +1930,12 @@ LoadMapHeader:: ; 107c (0:107c) ld a,[hl] ld [wMapMusicROMBank],a ; music 2 pop af - ld [H_LOADEDROMBANK],a - ld [MBC1RomBank],a + call BankswitchCommon ret ; function to copy map connection data from ROM to WRAM ; Input: hl = source, de = destination -CopyMapConnectionHeader:: ; 1238 (0:1238) +CopyMapConnectionHeader:: ; 0eaa (0:0eaa) ld c,$0b .loop ld a,[hli] @@ -2299,11 +1945,93 @@ CopyMapConnectionHeader:: ; 1238 (0:1238) 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_21e3 ; music related + call Func_2176 ; music related +.restoreRomBank + pop af + call BankswitchCommon + 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: ; 0f4d (0: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 @@ -2312,17 +2040,15 @@ LoadMapData:: ; 1241 (0:1241) ld [hSCX],a ld [wWalkCounter],a ld [wUnusedD119],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 + ld [wWalkBikeSurfStateCopy],a + ret + +CopyMapViewToVRAM:: ; 0f70 (0:0f70) ; copy current map view to VRAM - coord hl, 0, 0 ld de,vBGMap0 +CopyMapViewToVRAM2: ; 0f73 (0:0f73) + ld hl,wTileMap ld b,18 .vramCopyLoop ld c,20 @@ -2332,7 +2058,7 @@ LoadMapData:: ; 1241 (0:1241) inc e dec c jr nz,.vramCopyInnerLoop - ld a,32 - 20 + ld a,32 - 20 ; total vram map width in tiles - screen width in tiles add e ld e,a jr nc,.noCarry @@ -2340,48 +2066,47 @@ LoadMapData:: ; 1241 (0:1241) .noCarry dec b jr nz,.vramCopyLoop - ld a,$01 - ld [wUpdateSpritesEnabled],a - call EnableLCD - ld b, SET_PAL_OVERWORLD - call RunPaletteCommand - call LoadPlayerSpriteGraphics - ld a,[wd732] - and 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 UpdateMusic6Times - call PlayDefaultMusicFadeOutCurrent -.restoreRomBank - pop af - ld [H_LOADEDROMBANK],a - ld [MBC1RomBank],a ret ; function to switch to the ROM bank that a map is stored in ; Input: a = map number -SwitchToMapRomBank:: ; 12bc (0:12bc) +SwitchToMapRomBank:: ; 0f8b (0:0f8b) push hl push bc ld c,a ld b,$00 - ld a,Bank(MapHeaderBanks) - call BankswitchHome ; switch to ROM bank 3 + ld a,BANK(MapHeaderBanks) + call BankswitchHome ; switch to ROM bank 3F ld hl,MapHeaderBanks add hl,bc ld a,[hl] ld [$ffe8],a ; save map ROM bank call BankswitchBack ld a,[$ffe8] - ld [H_LOADEDROMBANK],a - ld [MBC1RomBank],a ; switch to map ROM bank + call BankswitchCommon pop bc pop hl ret -IgnoreInputForHalfSecond: ; 12da (0:12da) +GetMapHeaderPointer:: ; 0fa7 (0:0fa7) + ld a,[H_LOADEDROMBANK] + push af + switchbank MapHeaderPointers ; 3f:41f2 + push de + ld a,[W_CURMAP] + ld e,a + ld d,$0 + ld hl,MapHeaderPointers + add hl,de + add hl,de + ld a,[hli] + ld h,[hl] + ld l,a + pop de + pop af + jp BankswitchCommon + +IgnoreInputForHalfSecond: ; 0fc3 (0:0fc3) ld a, 30 ld [wIgnoreInputCounter], a ld hl, wd730 @@ -2390,13 +2115,174 @@ IgnoreInputForHalfSecond: ; 12da (0:12da) ld [hl], a ; set ignore input bit ret -ResetUsingStrengthOutOfBattleBit: ; 12e7 (0:12e7) +ResetUsingStrengthOutOfBattleBit: ; 0fd0 (0:0fd0) ld hl, wd728 res 0, [hl] ret -ForceBikeOrSurf:: ; 12ed (0:12ed) +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 6,a ; jumping down a ledge? + ret z + callba _HandleMidJump + ret + +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 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,e + add $4 + ld e,a + ld a,[hli] + ld [de],a ; store Y position at C2X4 + inc e + ld a,[hli] + ld [de],a ; store X position at C2X5 + inc e + ld a,[hli] + ld [de],a ; store movement byte 1 at C2X6 + ld a,[hli] + ld [$ff8d],a ; save movement byte 2 + ld a,[hli] + ld [$ff8e],a ; save text ID and flags byte + push bc + call LoadSprite + pop bc + dec d + ld a,e + add a,$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) |