From 5647ca687b92954dcf37a6ea6bfbc9a341c32de4 Mon Sep 17 00:00:00 2001 From: dannye <33dannye@gmail.com> Date: Wed, 4 Nov 2020 00:06:44 -0600 Subject: Sync with pokered --- engine/overworld/advance_player_sprite.asm | 247 ++++++++-------- engine/overworld/auto_movement.asm | 270 +++++++++++++++++ engine/overworld/cable_club_npc.asm | 208 ------------- engine/overworld/card_key.asm | 113 ------- engine/overworld/cinnabar_lab.asm | 123 -------- engine/overworld/clear_variables.asm | 16 +- engine/overworld/cut.asm | 66 ++--- engine/overworld/cut2.asm | 8 +- engine/overworld/doors.asm | 55 +--- engine/overworld/dungeon_warps.asm | 2 +- engine/overworld/dust_smoke.asm | 95 ++++++ engine/overworld/elevator.asm | 10 +- engine/overworld/emotion_bubbles.asm | 19 +- engine/overworld/field_move_messages.asm | 23 +- engine/overworld/healing_machine.asm | 43 ++- engine/overworld/hidden_items.asm | 172 ----------- engine/overworld/hidden_objects.asm | 20 +- engine/overworld/item.asm | 54 ---- engine/overworld/ledges.asm | 26 +- engine/overworld/map_sprite_functions1.asm | 390 ------------------------ engine/overworld/map_sprites.asm | 32 +- engine/overworld/missable_objects.asm | 36 +-- engine/overworld/movement.asm | 459 +++++++++++++++-------------- engine/overworld/npc_movement.asm | 270 ----------------- engine/overworld/npc_movement_2.asm | 14 +- engine/overworld/oaks_aide.asm | 71 ----- engine/overworld/oam.asm | 232 --------------- engine/overworld/pathfinding.asm | 201 +++++++++++++ engine/overworld/pewter_guys.asm | 102 ------- engine/overworld/player_animations.asm | 118 ++++---- engine/overworld/player_state.asm | 122 ++++---- engine/overworld/poison.asm | 151 ---------- engine/overworld/pokecenter.asm | 149 ---------- engine/overworld/pokemart.asm | 272 ----------------- engine/overworld/push_boulder.asm | 34 ++- engine/overworld/saffron_guards.asm | 16 - engine/overworld/set_blackout_map.asm | 29 -- engine/overworld/special_warps.asm | 149 ++++++++++ engine/overworld/spinners.asm | 65 ++++ engine/overworld/sprite_collisions.asm | 392 ++++++++++++++++++++++++ engine/overworld/ssanne.asm | 95 ------ engine/overworld/tileset_header.asm | 51 ---- engine/overworld/tilesets.asm | 51 ++++ engine/overworld/trainer_sight.asm | 349 ++++++++++++++++++++++ engine/overworld/trainers.asm | 349 ---------------------- engine/overworld/update_map.asm | 32 +- engine/overworld/wild_mons.asm | 10 +- 47 files changed, 2226 insertions(+), 3585 deletions(-) create mode 100755 engine/overworld/auto_movement.asm delete mode 100755 engine/overworld/cable_club_npc.asm delete mode 100755 engine/overworld/card_key.asm delete mode 100755 engine/overworld/cinnabar_lab.asm create mode 100755 engine/overworld/dust_smoke.asm delete mode 100755 engine/overworld/hidden_items.asm delete mode 100644 engine/overworld/item.asm delete mode 100644 engine/overworld/map_sprite_functions1.asm delete mode 100755 engine/overworld/npc_movement.asm delete mode 100755 engine/overworld/oaks_aide.asm delete mode 100644 engine/overworld/oam.asm create mode 100644 engine/overworld/pathfinding.asm delete mode 100755 engine/overworld/pewter_guys.asm delete mode 100644 engine/overworld/poison.asm delete mode 100755 engine/overworld/pokecenter.asm delete mode 100755 engine/overworld/pokemart.asm delete mode 100755 engine/overworld/saffron_guards.asm delete mode 100644 engine/overworld/set_blackout_map.asm create mode 100644 engine/overworld/special_warps.asm create mode 100644 engine/overworld/spinners.asm create mode 100644 engine/overworld/sprite_collisions.asm delete mode 100755 engine/overworld/ssanne.asm delete mode 100644 engine/overworld/tileset_header.asm create mode 100644 engine/overworld/tilesets.asm create mode 100755 engine/overworld/trainer_sight.asm delete mode 100755 engine/overworld/trainers.asm (limited to 'engine/overworld') diff --git a/engine/overworld/advance_player_sprite.asm b/engine/overworld/advance_player_sprite.asm index 6b4a0cbb..4ebdac84 100644 --- a/engine/overworld/advance_player_sprite.asm +++ b/engine/overworld/advance_player_sprite.asm @@ -1,241 +1,244 @@ _AdvancePlayerSprite:: - ld a,[wSpriteStateData1 + 3] ; delta Y - ld b,a - ld a,[wSpriteStateData1 + 5] ; delta X - ld c,a - ld hl,wWalkCounter ; walking animation counter + ld a, [wSpritePlayerStateData1YStepVector] + ld b, a + ld a, [wSpritePlayerStateData1XStepVector] + ld c, a + ld hl, wWalkCounter ; walking animation counter dec [hl] - jr nz,.afterUpdateMapCoords + jr nz, .afterUpdateMapCoords ; if it's the end of the animation, update the player's map coordinates ld hl, wPikachuOverworldStateFlags res 5, [hl] - ld a,[wYCoord] + ld a, [wYCoord] add b - ld [wYCoord],a - ld a,[wXCoord] + ld [wYCoord], a + ld a, [wXCoord] add c - ld [wXCoord],a + ld [wXCoord], a .afterUpdateMapCoords - ld a,[wWalkCounter] ; walking animation counter - cp a,$07 - jp nz,.scrollBackgroundAndSprites + ld a, [wWalkCounter] ; walking animation counter + cp $07 + jp nz, .scrollBackgroundAndSprites ; if this is the first iteration of the animation - ld a,c - cp a,$01 - jr nz,.checkIfMovingWest + ld a, c + cp $01 + jr nz, .checkIfMovingWest ; moving east - ld a,[wMapViewVRAMPointer] - ld e,a + ld a, [wMapViewVRAMPointer] + ld e, a and $e0 - ld d,a - ld a,e + ld d, a + ld a, e add $02 and $1f or d - ld [wMapViewVRAMPointer],a + ld [wMapViewVRAMPointer], a jr .adjustXCoordWithinBlock .checkIfMovingWest - cp a,$ff - jr nz,.checkIfMovingSouth + cp $ff + jr nz, .checkIfMovingSouth ; moving west - ld a,[wMapViewVRAMPointer] - ld e,a - and a,$e0 - ld d,a - ld a,e + ld a, [wMapViewVRAMPointer] + ld e, a + and $e0 + ld d, a + ld a, e sub $02 and $1f or d - ld [wMapViewVRAMPointer],a + ld [wMapViewVRAMPointer], a jr .adjustXCoordWithinBlock .checkIfMovingSouth - ld a,b - cp a,$01 - jr nz,.checkIfMovingNorth + ld a, b + cp $01 + jr nz, .checkIfMovingNorth ; moving south - ld a,[wMapViewVRAMPointer] + ld a, [wMapViewVRAMPointer] add $40 - ld [wMapViewVRAMPointer],a - jr nc,.adjustXCoordWithinBlock - ld a,[wMapViewVRAMPointer + 1] + ld [wMapViewVRAMPointer], a + jr nc, .adjustXCoordWithinBlock + ld a, [wMapViewVRAMPointer + 1] inc a and $03 or $98 - ld [wMapViewVRAMPointer + 1],a + ld [wMapViewVRAMPointer + 1], a jr .adjustXCoordWithinBlock .checkIfMovingNorth - cp a,$ff - jr nz,.adjustXCoordWithinBlock + cp $ff + jr nz, .adjustXCoordWithinBlock ; moving north - ld a,[wMapViewVRAMPointer] + ld a, [wMapViewVRAMPointer] sub $40 - ld [wMapViewVRAMPointer],a - jr nc,.adjustXCoordWithinBlock - ld a,[wMapViewVRAMPointer + 1] + ld [wMapViewVRAMPointer], a + jr nc, .adjustXCoordWithinBlock + ld a, [wMapViewVRAMPointer + 1] dec a and $03 or $98 - ld [wMapViewVRAMPointer + 1],a + ld [wMapViewVRAMPointer + 1], a .adjustXCoordWithinBlock - ld a,c + ld a, c and a - jr z,.pointlessJump ; mistake? + jr z, .pointlessJump ; mistake? .pointlessJump - ld hl,wXBlockCoord - ld a,[hl] + ld hl, wXBlockCoord + ld a, [hl] add c - ld [hl],a + ld [hl], a cp $02 - jr nz,.checkForMoveToWestBlock + jr nz, .checkForMoveToWestBlock ; moved into the tile block to the east xor a - ld [hl],a - ld hl,wXOffsetSinceLastSpecialWarp + ld [hl], a + ld hl, wXOffsetSinceLastSpecialWarp inc [hl] - ld de,wCurrentTileBlockMapViewPointer + ld de, wCurrentTileBlockMapViewPointer call MoveTileBlockMapPointerEast jr .updateMapView .checkForMoveToWestBlock - cp a,$ff - jr nz,.adjustYCoordWithinBlock + cp $ff + jr nz, .adjustYCoordWithinBlock ; moved into the tile block to the west - ld a,$1 - ld [hl],a - ld hl,wXOffsetSinceLastSpecialWarp + ld a, $01 + ld [hl], a + ld hl, wXOffsetSinceLastSpecialWarp dec [hl] - ld de,wCurrentTileBlockMapViewPointer + ld de, wCurrentTileBlockMapViewPointer call MoveTileBlockMapPointerWest jr .updateMapView .adjustYCoordWithinBlock - ld hl,wYBlockCoord - ld a,[hl] + ld hl, wYBlockCoord + ld a, [hl] add b - ld [hl],a - cp $2 - jr nz,.checkForMoveToNorthBlock + ld [hl], a + cp $02 + jr nz, .checkForMoveToNorthBlock ; moved into the tile block to the south xor a - ld [hl],a - ld hl,wYOffsetSinceLastSpecialWarp + ld [hl], a + ld hl, wYOffsetSinceLastSpecialWarp inc [hl] - ld de,wCurrentTileBlockMapViewPointer - ld a,[wCurMapWidth] + ld de, wCurrentTileBlockMapViewPointer + ld a, [wCurMapWidth] call MoveTileBlockMapPointerSouth jr .updateMapView .checkForMoveToNorthBlock - cp a,$ff - jr nz,.updateMapView + cp $ff + jr nz, .updateMapView ; moved into the tile block to the north - ld a,$1 - ld [hl],a - ld hl,wYOffsetSinceLastSpecialWarp + ld a, $01 + ld [hl], a + ld hl, wYOffsetSinceLastSpecialWarp dec [hl] - ld de,wCurrentTileBlockMapViewPointer - ld a,[wCurMapWidth] + ld de, wCurrentTileBlockMapViewPointer + ld a, [wCurMapWidth] call MoveTileBlockMapPointerNorth .updateMapView call LoadCurrentMapView - ld a,[wSpriteStateData1 + 3] ; delta Y - cp $1 - jr nz,.checkIfMovingNorth2 + ld a, [wSpritePlayerStateData1YStepVector] + cp $01 + jr nz, .checkIfMovingNorth2 ; if moving south call ScheduleSouthRowRedraw jr .scrollBackgroundAndSprites .checkIfMovingNorth2 cp $ff - jr nz,.checkIfMovingEast2 + jr nz, .checkIfMovingEast2 ; if moving north call ScheduleNorthRowRedraw jr .scrollBackgroundAndSprites .checkIfMovingEast2 - ld a,[wSpriteStateData1 + 5] ; delta X - cp $1 - jr nz,.checkIfMovingWest2 + ld a, [wSpritePlayerStateData1XStepVector] + cp $01 + jr nz, .checkIfMovingWest2 ; if moving east call ScheduleEastColumnRedraw jr .scrollBackgroundAndSprites .checkIfMovingWest2 cp $ff - jr nz,.scrollBackgroundAndSprites + jr nz, .scrollBackgroundAndSprites ; if moving west call ScheduleWestColumnRedraw .scrollBackgroundAndSprites - ld a,[wSpriteStateData1 + 3] ; delta Y + ld a, [wSpritePlayerStateData1YStepVector] add a - ld b,a - ld a,[wSpriteStateData1 + 5] ; delta X + ld b, a + ld a, [wSpritePlayerStateData1XStepVector] add a - ld c,a + ld c, a ; shift all the sprites in the direction opposite of the player's motion ; so that the player appears to move relative to them - ld hl,wSpriteStateData1 + $14 - ld e,15 + ld hl, wSprite01StateData1YPixels + ld e, 15 .spriteShiftLoop - ld a,[hl] + ld a, [hl] sub b - ld [hli],a + ld [hli], a inc l - ld a,[hl] + ld a, [hl] sub c - ld [hl],a - ld a,$0e + ld [hl], a + ld a, $0e add l - ld l,a + ld l, a dec e - jr nz,.spriteShiftLoop + jr nz, .spriteShiftLoop .done - ld a,[hSCY] + ldh a, [hSCY] add b - ld [hSCY],a ; update background scroll Y - ld a,[hSCX] + ldh [hSCY], a ; update background scroll Y + ldh a, [hSCX] add c - ld [hSCX],a ; update background scroll X + ldh [hSCX], a ; update background scroll X ret +; the following four functions are used to move the pointer to the upper left +; corner of the tile block map in the direction of motion + MoveTileBlockMapPointerEast:: - ld a,[de] - add $1 - ld [de],a + ld a, [de] + add $01 + ld [de], a ret nc inc de - ld a,[de] + ld a, [de] inc a - ld [de],a + ld [de], a ret MoveTileBlockMapPointerWest:: - ld a,[de] - sub $1 - ld [de],a + ld a, [de] + sub $01 + ld [de], a ret nc inc de - ld a,[de] + ld a, [de] dec a - ld [de],a + ld [de], a ret MoveTileBlockMapPointerSouth:: - add $6 - ld b,a - ld a,[de] + add MAP_BORDER * 2 + ld b, a + ld a, [de] add b - ld [de],a + ld [de], a ret nc inc de - ld a,[de] + ld a, [de] inc a - ld [de],a + ld [de], a ret MoveTileBlockMapPointerNorth:: - add $6 - ld b,a - ld a,[de] + add MAP_BORDER * 2 + ld b, a + ld a, [de] sub b - ld [de],a + ld [de], a ret nc inc de - ld a,[de] + ld a, [de] dec a - ld [de],a + ld [de], a ret diff --git a/engine/overworld/auto_movement.asm b/engine/overworld/auto_movement.asm new file mode 100755 index 00000000..a68da55f --- /dev/null +++ b/engine/overworld/auto_movement.asm @@ -0,0 +1,270 @@ +PlayerStepOutFromDoor:: + ld hl, wd730 + res 1, [hl] + call IsPlayerStandingOnDoorTile + jr nc, .notStandingOnDoor + ld a, $fc + ld [wJoyIgnore], a + ld hl, wd736 + set 1, [hl] + ld a, $1 + ld [wSimulatedJoypadStatesIndex], a + ld a, D_DOWN + ld [wSimulatedJoypadStatesEnd], a + xor a + ld [wSpritePlayerStateData1ImageIndex], a + call StartSimulatingJoypadStates + ret +.notStandingOnDoor + xor a + ld [wWastedByteCD3A], a + ld [wSimulatedJoypadStatesIndex], a + ld [wSimulatedJoypadStatesEnd], a + ld hl, wd736 + res 0, [hl] + res 1, [hl] + ld hl, wd730 + res 7, [hl] + ret + +_EndNPCMovementScript:: + ld hl, wd730 + res 7, [hl] + ld hl, wd72e + res 7, [hl] + ld hl, wd736 + res 0, [hl] + res 1, [hl] + xor a + ld [wNPCMovementScriptSpriteOffset], a + ld [wNPCMovementScriptFunctionNum], a + ld [wNPCMovementScriptPointerTableNum], a + ld [wWastedByteCD3A], a + ld [wSimulatedJoypadStatesIndex], a + ld [wSimulatedJoypadStatesEnd], a + ret + +PalletMovementScriptPointerTable:: + dw PalletMovementScript_OakMoveLeft + dw PalletMovementScript_PlayerMoveLeft + dw PalletMovementScript_WaitAndWalkToLab + dw PalletMovementScript_WalkToLab + dw PalletMovementScript_Done + +PalletMovementScript_OakMoveLeft: + ld a, [wXCoord] + sub $a + ld [wNumStepsToTake], a + jr z, .playerOnLeftTile +; The player is on the right tile of the northern path out of Pallet Town and +; Prof. Oak is below. +; Make Prof. Oak step to the left. + ld b, 0 + ld c, a + ld hl, wNPCMovementDirections2 + ld a, NPC_MOVEMENT_LEFT + call FillMemory + ld [hl], $ff + ld a, [wSpriteIndex] + ldh [hSpriteIndex], a + ld de, wNPCMovementDirections2 + call MoveSprite + ld a, $1 + ld [wNPCMovementScriptFunctionNum], a + jr .done +; The player is on the left tile of the northern path out of Pallet Town and +; Prof. Oak is below. +; Prof. Oak is already where he needs to be. +.playerOnLeftTile + ld a, $3 + ld [wNPCMovementScriptFunctionNum], a +.done + ld a, BANK(Music_MuseumGuy) + ld c, a + ld a, MUSIC_MUSEUM_GUY + call PlayMusic + ld hl, wFlags_D733 + set 1, [hl] + ld a, $fc + ld [wJoyIgnore], a + ret + +PalletMovementScript_PlayerMoveLeft: + ld a, [wd730] + bit 0, a ; is an NPC being moved by a script? + ret nz ; return if Oak is still moving + ld a, [wNumStepsToTake] + ld [wSimulatedJoypadStatesIndex], a + ldh [hNPCMovementDirections2Index], a + predef ConvertNPCMovementDirectionsToJoypadMasks + call StartSimulatingJoypadStates + ld a, $2 + ld [wNPCMovementScriptFunctionNum], a + ret + +PalletMovementScript_WaitAndWalkToLab: + ld a, [wSimulatedJoypadStatesIndex] + and a ; is the player done moving left yet? + ret nz + +PalletMovementScript_WalkToLab: + xor a + ld [wOverrideSimulatedJoypadStatesMask], a + ld a, [wSpriteIndex] + swap a + ld [wNPCMovementScriptSpriteOffset], a + xor a + ld [wSpritePlayerStateData2MovementByte1], a + ld hl, wSimulatedJoypadStatesEnd + ld de, RLEList_PlayerWalkToLab + call DecodeRLEList + dec a + ld [wSimulatedJoypadStatesIndex], a + ld hl, wNPCMovementDirections2 + ld de, RLEList_ProfOakWalkToLab + call DecodeRLEList + ld hl, wd72e + res 7, [hl] + ld hl, wd730 + set 7, [hl] + ld a, $4 + ld [wNPCMovementScriptFunctionNum], a + ret + + +RLEList_ProfOakWalkToLab: + db NPC_MOVEMENT_DOWN, 6 ; differs from red + db NPC_MOVEMENT_LEFT, 1 + db NPC_MOVEMENT_DOWN, 5 + db NPC_MOVEMENT_RIGHT, 3 + db NPC_MOVEMENT_UP, 1 + db NPC_CHANGE_FACING, 1 + db -1 ; end + +RLEList_PlayerWalkToLab: + db D_UP, 2 + db D_RIGHT, 3 + db D_DOWN, 5 + db D_LEFT, 1 + db D_DOWN, 7 ; differs from red + db -1 ; end + +PalletMovementScript_Done: + ld a, [wSimulatedJoypadStatesIndex] + and a + ret nz + ld a, HS_PALLET_TOWN_OAK + ld [wMissableObjectIndex], a + predef HideObject + ld hl, wd730 + res 7, [hl] + ld hl, wd72e + res 7, [hl] + jp EndNPCMovementScript + +PewterMuseumGuyMovementScriptPointerTable:: + dw PewterMovementScript_WalkToMuseum + dw PewterMovementScript_Done + +PewterMovementScript_WalkToMuseum: + ld a, BANK(Music_MuseumGuy) + ld c, a + ld a, MUSIC_MUSEUM_GUY + call PlayMusic + ld a, [wSpriteIndex] + swap a + ld [wNPCMovementScriptSpriteOffset], a + call StartSimulatingJoypadStates + ld hl, wSimulatedJoypadStatesEnd + ld de, RLEList_PewterMuseumPlayer + call DecodeRLEList + dec a + ld [wSimulatedJoypadStatesIndex], a + xor a + ld [wWhichPewterGuy], a + call PewterGuys + ld hl, wNPCMovementDirections2 + ld de, RLEList_PewterMuseumGuy + call DecodeRLEList + ld hl, wd72e + res 7, [hl] + ld a, $1 + ld [wNPCMovementScriptFunctionNum], a + ret + +RLEList_PewterMuseumPlayer: + db NO_INPUT, 1 + db D_UP, 3 + db D_LEFT, 13 + db D_UP, 6 + db -1 ; end + +RLEList_PewterMuseumGuy: + db NPC_MOVEMENT_UP, 6 + db NPC_MOVEMENT_LEFT, 13 + db NPC_MOVEMENT_UP, 3 + db NPC_MOVEMENT_LEFT, 1 + db -1 ; end + +PewterMovementScript_Done: + ld a, [wSimulatedJoypadStatesIndex] + and a + ret nz + ld hl, wd730 + res 7, [hl] + ld hl, wd72e + res 7, [hl] + jp EndNPCMovementScript + +PewterGymGuyMovementScriptPointerTable:: + dw PewterMovementScript_WalkToGym + dw PewterMovementScript_Done + +PewterMovementScript_WalkToGym: + ld a, BANK(Music_MuseumGuy) + ld c, a + ld a, MUSIC_MUSEUM_GUY + call PlayMusic + ld a, [wSpriteIndex] + swap a + ld [wNPCMovementScriptSpriteOffset], a + xor a + ld [wSpritePlayerStateData2MovementByte1], a + ld hl, wSimulatedJoypadStatesEnd + ld de, RLEList_PewterGymPlayer + call DecodeRLEList + dec a + ld [wSimulatedJoypadStatesIndex], a + ld a, 1 + ld [wWhichPewterGuy], a + call PewterGuys + ld hl, wNPCMovementDirections2 + ld de, RLEList_PewterGymGuy + call DecodeRLEList + ld hl, wd72e + res 7, [hl] + ld hl, wd730 + set 7, [hl] + ld a, $1 + ld [wNPCMovementScriptFunctionNum], a + ret + +RLEList_PewterGymPlayer: + db NO_INPUT, 1 + db D_RIGHT, 2 + db D_DOWN, 5 + db D_LEFT, 11 + db D_UP, 5 + db D_LEFT, 15 + db -1 ; end + +RLEList_PewterGymGuy: + db NPC_MOVEMENT_DOWN, 2 + db NPC_MOVEMENT_LEFT, 15 + db NPC_MOVEMENT_UP, 5 + db NPC_MOVEMENT_LEFT, 11 + db NPC_MOVEMENT_DOWN, 5 + db NPC_MOVEMENT_RIGHT, 3 + db -1 ; end + +INCLUDE "engine/events/pewter_guys.asm" diff --git a/engine/overworld/cable_club_npc.asm b/engine/overworld/cable_club_npc.asm deleted file mode 100755 index 12ce64a4..00000000 --- a/engine/overworld/cable_club_npc.asm +++ /dev/null @@ -1,208 +0,0 @@ -CableClubNPC: - ld hl, CableClubNPCWelcomeText - call PrintText - call CheckPikachuFollowingPlayer - jr nz, .asm_7048 - CheckEvent EVENT_GOT_POKEDEX - jp nz, .receivedPokedex -; if the player hasn't received the pokedex -.asm_7048 - ld c, 60 - call DelayFrames - ld hl, CableClubNPCMakingPreparationsText - call PrintText - jp .didNotConnect -.receivedPokedex - ld a, $1 - ld [wMenuJoypadPollCount], a - ld a, 90 - ld [wLinkTimeoutCounter], a -.establishConnectionLoop - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - jr z, .establishedConnection - cp USING_EXTERNAL_CLOCK - jr z, .establishedConnection - ld a, CONNECTION_NOT_ESTABLISHED - ld [hSerialConnectionStatus], a - ld a, ESTABLISH_CONNECTION_WITH_EXTERNAL_CLOCK - ld [rSB], a - xor a - ld [hSerialReceiveData], a - ld a, START_TRANSFER_EXTERNAL_CLOCK - ld [rSC], a - ld a, [wLinkTimeoutCounter] - dec a - ld [wLinkTimeoutCounter], a - jr z, .failedToEstablishConnection - ld a, ESTABLISH_CONNECTION_WITH_INTERNAL_CLOCK - ld [rSB], a - ld a, START_TRANSFER_INTERNAL_CLOCK - ld [rSC], a - call DelayFrame - jr .establishConnectionLoop -.establishedConnection - call Serial_SendZeroByte - call DelayFrame - call Serial_SendZeroByte - ld c, 50 - call DelayFrames - ld hl, CableClubNPCPleaseApplyHereHaveToSaveText - call PrintText - xor a - ld [wMenuJoypadPollCount], a - call YesNoChoice - ld a, $1 - ld [wMenuJoypadPollCount], a - ld a, [wCurrentMenuItem] - and a - jr nz, .choseNo - callab SaveSAVtoSRAM - call WaitForSoundToFinish - ld a, SFX_SAVE - call PlaySoundWaitForCurrent - ld hl, CableClubNPCPleaseWaitText - call PrintText - ld hl, wUnknownSerialCounter - ld a, $3 - ld [hli], a - xor a - ld [hl], a - ld [hSerialReceivedNewData], a - ld [wSerialExchangeNybbleSendData], a - call Serial_SyncAndExchangeNybble - ld hl, wUnknownSerialCounter - ld a, [hli] - inc a - jr nz, .connected - ld a, [hl] - inc a - jr nz, .connected - ld b, 10 -.syncLoop - call DelayFrame - call Serial_SendZeroByte - dec b - jr nz, .syncLoop - call CloseLinkConnection - ld hl, CableClubNPCLinkClosedBecauseOfInactivityText - call PrintText - jr .didNotConnect -.failedToEstablishConnection - ld hl, CableClubNPCAreaReservedFor2FriendsLinkedByCableText - call PrintText - jr .didNotConnect -.choseNo - call CloseLinkConnection - ld hl, CableClubNPCPleaseComeAgainText - call PrintText -.didNotConnect - xor a - ld hl, wUnknownSerialCounter - ld [hli], a - ld [hl], a - ld hl, wd72e - res 6, [hl] - xor a - ld [wMenuJoypadPollCount], a - ret -.connected - xor a - ld [hld], a - ld [hl], a - ld a, [wLetterPrintingDelayFlags] - push af - callab LinkMenu - pop af - ld [wLetterPrintingDelayFlags], a - ret - -; seems to be similar of Serial_SyncAndExchangeNybble -Serial_SyncAndExchangeNybbleDouble: - ld a, $ff - ld [wSerialExchangeNybbleReceiveData], a -.loop - call Serial_ExchangeNybble - call DelayFrame - push hl - ld hl, wUnknownSerialCounter + 1 - dec [hl] - jr nz, .next - dec hl - dec [hl] - jr nz, .next - pop hl - jr .setUnknownSerialCounterToFFFF -.next - pop hl - ld a, [wSerialExchangeNybbleReceiveData] - inc a - jr z, .loop - call DelayFrame - ld a, $ff - ld [wSerialExchangeNybbleReceiveData], a - call Serial_ExchangeNybble - ld a, [wSerialExchangeNybbleReceiveData] - inc a - jr z, .loop - ld b, 10 -.syncLoop1 - call DelayFrame - call Serial_ExchangeNybble - dec b - jr nz, .syncLoop1 - ld b, 10 -.syncLoop2 - call DelayFrame - call Serial_SendZeroByte - dec b - jr nz, .syncLoop2 - ld a, [wSerialExchangeNybbleReceiveData] - ld [wSerialSyncAndExchangeNybbleReceiveData], a - ret -.setUnknownSerialCounterToFFFF - ld a, $ff - ld [wUnknownSerialCounter], a - ld [wUnknownSerialCounter + 1], a - ret - -CableClubNPCAreaReservedFor2FriendsLinkedByCableText: - TX_FAR _CableClubNPCAreaReservedFor2FriendsLinkedByCableText - db "@" - -CableClubNPCWelcomeText: - TX_FAR _CableClubNPCWelcomeText - db "@" - -CableClubNPCPleaseApplyHereHaveToSaveText: - TX_FAR _CableClubNPCPleaseApplyHereHaveToSaveText - db "@" - -CableClubNPCPleaseWaitText: - TX_FAR _CableClubNPCPleaseWaitText - TX_DELAY - db "@" - -CableClubNPCLinkClosedBecauseOfInactivityText: - TX_FAR _CableClubNPCLinkClosedBecauseOfInactivityText - db "@" - -CableClubNPCPleaseComeAgainText: - TX_FAR _CableClubNPCPleaseComeAgainText - db "@" - -CableClubNPCMakingPreparationsText: - TX_FAR _CableClubNPCMakingPreparationsText - db "@" - -CloseLinkConnection: - call Delay3 - ld a, CONNECTION_NOT_ESTABLISHED - ld [hSerialConnectionStatus], a - ld a, ESTABLISH_CONNECTION_WITH_EXTERNAL_CLOCK - ld [rSB], a - xor a - ld [hSerialReceiveData], a - ld a, START_TRANSFER_EXTERNAL_CLOCK - ld [rSC], a - ret diff --git a/engine/overworld/card_key.asm b/engine/overworld/card_key.asm deleted file mode 100755 index a4452b4a..00000000 --- a/engine/overworld/card_key.asm +++ /dev/null @@ -1,113 +0,0 @@ -PrintCardKeyText: - ld hl, SilphCoMapList - ld a, [wCurMap] - ld b, a -.silphCoMapListLoop - ld a, [hli] - cp $ff - ret z - cp b - jr nz, .silphCoMapListLoop -; does not check for tile in front of player. This might be buggy - ;predef GetTileAndCoordsInFrontOfPlayer - ld a, [wTileInFrontOfPlayer] - cp $18 - jr z, .cardKeyDoorInFrontOfPlayer - cp $24 - jr z, .cardKeyDoorInFrontOfPlayer - ld b, a - ld a, [wCurMap] - cp SILPH_CO_11F - ret nz - ld a, b - cp $5e - ret nz -.cardKeyDoorInFrontOfPlayer - ld b, CARD_KEY - call IsItemInBag - jr z, .noCardKey - xor a - ld [wPlayerMovingDirection], a - tx_pre_id CardKeySuccessText - ld [hSpriteIndexOrTextID], a - call PrintPredefTextID - call GetCoordsInFrontOfPlayer - srl d - ld a, d - ld b, a - ld [wCardKeyDoorY], a - srl e - ld a, e - ld c, a - ld [wCardKeyDoorX], a - ld a, [wCurMap] - cp SILPH_CO_11F - jr nz, .notSilphCo11F - ld a, $3 - jr .replaceCardKeyDoorTileBlock -.notSilphCo11F - ld a, $e -.replaceCardKeyDoorTileBlock - ld [wNewTileBlockID], a - predef ReplaceTileBlock - ld hl, wCurrentMapScriptFlags - set 5, [hl] - ld a, SFX_GO_INSIDE - jp PlaySound -.noCardKey - tx_pre_id CardKeyFailText - ld [hSpriteIndexOrTextID], a - jp PrintPredefTextID - -SilphCoMapList: - db SILPH_CO_2F - db SILPH_CO_3F - db SILPH_CO_4F - db SILPH_CO_5F - db SILPH_CO_6F - db SILPH_CO_7F - db SILPH_CO_8F - db SILPH_CO_9F - db SILPH_CO_10F - db SILPH_CO_11F - db $FF - -CardKeySuccessText: - TX_FAR _CardKeySuccessText1 - TX_SFX_ITEM_1 - TX_FAR _CardKeySuccessText2 - db "@" - -CardKeyFailText: - TX_FAR _CardKeyFailText - db "@" - -; d = Y -; e = X -GetCoordsInFrontOfPlayer: - ld a, [wYCoord] - ld d, a - ld a, [wXCoord] - ld e, a - ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction - and a - jr nz, .notFacingDown -; facing down - inc d - ret -.notFacingDown - cp SPRITE_FACING_UP - jr nz, .notFacingUp -; facing up - dec d - ret -.notFacingUp - cp SPRITE_FACING_LEFT - jr nz, .notFacingLeft -; facing left - dec e - ret -.notFacingLeft -; facing right - inc e - ret diff --git a/engine/overworld/cinnabar_lab.asm b/engine/overworld/cinnabar_lab.asm deleted file mode 100755 index 13313746..00000000 --- a/engine/overworld/cinnabar_lab.asm +++ /dev/null @@ -1,123 +0,0 @@ -GiveFossilToCinnabarLab: - ld hl, wd730 - set 6, [hl] - xor a - ld [wCurrentMenuItem], a - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, [wFilteredBagItemsCount] - dec a - ld [wMaxMenuItem], a - ld a, 2 - ld [wTopMenuItemY], a - ld a, 1 - ld [wTopMenuItemX], a - ld a, [wFilteredBagItemsCount] - dec a - ld bc, 2 - ld hl, 3 - call AddNTimes - dec l - ld b, l - ld c, $d - coord hl, 0, 0 - call TextBoxBorder - call UpdateSprites - call PrintFossilsInBag - ld hl, wd730 - res 6, [hl] - call HandleMenuInput - bit 1, a ; pressed B? - jr nz, .cancelledGivingFossil - ld hl, wFilteredBagItems - ld a, [wCurrentMenuItem] - ld d, 0 - ld e, a - add hl, de - ld a, [hl] - ld [$ffdb], a - cp DOME_FOSSIL - jr z, .choseDomeFossil - cp HELIX_FOSSIL - jr z, .choseHelixFossil - ld b, AERODACTYL - jr .fossilSelected -.choseHelixFossil - ld b, OMANYTE - jr .fossilSelected -.choseDomeFossil - ld b, KABUTO -.fossilSelected - ld [wFossilItem], a - ld a, b - ld [wFossilMon], a - call LoadFossilItemAndMonName - ld hl, LabFossil_610ae - call PrintText - call YesNoChoice - ld a, [wCurrentMenuItem] - and a - jr nz, .cancelledGivingFossil - ld hl, LabFossil_610b3 - call PrintText - ld a, [wFossilItem] - ld [hItemToRemoveID], a - callba RemoveItemByID - ld hl, LabFossil_610b8 - call PrintText - SetEvents EVENT_GAVE_FOSSIL_TO_LAB, EVENT_LAB_STILL_REVIVING_FOSSIL - ret -.cancelledGivingFossil - ld hl, LabFossil_610bd - call PrintText - ret - -LabFossil_610ae: - TX_FAR _Lab4Text_610ae - db "@" - -LabFossil_610b3: - TX_FAR _Lab4Text_610b3 - db "@" - -LabFossil_610b8: - TX_FAR _Lab4Text_610b8 - db "@" - -LabFossil_610bd: - TX_FAR _Lab4Text_610bd - db "@" - -PrintFossilsInBag: -; Prints each fossil in the player's bag on a separate line in the menu. - ld hl, wFilteredBagItems - xor a - ld [hItemCounter], a -.loop - ld a, [hli] - cp $ff - ret z - push hl - ld [wd11e], a - call GetItemName - coord hl, 2, 2 - ld a, [hItemCounter] - ld bc, SCREEN_WIDTH * 2 - call AddNTimes - ld de, wcd6d - call PlaceString - ld hl, hItemCounter - inc [hl] - pop hl - jr .loop - -; loads the names of the fossil item and the resulting mon -LoadFossilItemAndMonName: - ld a, [wFossilMon] - ld [wd11e], a - call GetMonName - call CopyStringToCF4B - ld a, [wFossilItem] - ld [wd11e], a - call GetItemName - ret diff --git a/engine/overworld/clear_variables.asm b/engine/overworld/clear_variables.asm index 9a59cc7c..bbb7c986 100644 --- a/engine/overworld/clear_variables.asm +++ b/engine/overworld/clear_variables.asm @@ -1,14 +1,14 @@ -ClearVariablesOnEnterMap: - ld a, SCREEN_HEIGHT_PIXELS - ld [hWY], a - ld [rWY], a +ClearVariablesOnEnterMap:: + ld a, SCREEN_HEIGHT_PX + ldh [hWY], a + ldh [rWY], a xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld [wStepCounter], a ld [wLoneAttackNo], a - ld [hJoyPressed], a - ld [hJoyReleased], a - ld [hJoyHeld], a + ldh [hJoyPressed], a + ldh [hJoyReleased], a + ldh [hJoyHeld], a ld [wActionResultOrTookBattleTurn], a ld [wUnusedD5A3], a ld hl, wCardKeyDoorY diff --git a/engine/overworld/cut.asm b/engine/overworld/cut.asm index bc7d092d..e36b8d88 100755 --- a/engine/overworld/cut.asm +++ b/engine/overworld/cut.asm @@ -22,8 +22,8 @@ UsedCut: jp PrintText .NothingToCutText - TX_FAR _NothingToCutText - db "@" + text_far _NothingToCutText + text_end .canCut ld [wCutTile], a @@ -37,15 +37,15 @@ UsedCut: call GBPalWhiteOutWithDelay3 call ClearSprites call RestoreScreenTilesAndReloadTilePatterns - ld a, SCREEN_HEIGHT_PIXELS - ld [hWY], a + ld a, SCREEN_HEIGHT_PX + ldh [hWY], a call Delay3 call LoadGBPal call LoadCurrentMapView call SaveScreenTilesToBuffer2 call Delay3 xor a - ld [hWY], a + ldh [hWY], a ld hl, UsedCutText call PrintText call LoadScreenTilesFromBuffer2 @@ -57,47 +57,47 @@ UsedCut: ld de, CutTreeBlockSwaps call ReplaceTreeTileBlock call RedrawMapView - callba AnimCut + farcall AnimCut ld a, $1 ld [wUpdateSpritesEnabled], a ld a, SFX_CUT call PlaySound ld a, $90 - ld [hWY], a + ldh [hWY], a call UpdateSprites jp RedrawMapView UsedCutText: - TX_FAR _UsedCutText - db "@" + text_far _UsedCutText + text_end InitCutAnimOAM: xor a ld [wWhichAnimationOffsets], a ld a, %11100100 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 ld a, [wCutTile] cp $52 jr z, .grass ; tree - ld de, Overworld_GFX + $2d0 ; cuttable tree sprite top row - ld hl, vChars1 + $7c0 - lb bc, BANK(Overworld_GFX), $02 + ld de, Overworld_GFX tile $2d ; cuttable tree sprite top row + ld hl, vChars1 tile $7c + lb bc, BANK(Overworld_GFX), 2 call CopyVideoData - ld de, Overworld_GFX + $3d0 ; cuttable tree sprite bottom row - ld hl, vChars1 + $7e0 - lb bc, BANK(Overworld_GFX), $02 + ld de, Overworld_GFX tile $3d ; cuttable tree sprite bottom row + ld hl, vChars1 tile $7e + lb bc, BANK(Overworld_GFX), 2 call CopyVideoData jr WriteCutOrBoulderDustAnimationOAMBlock .grass - ld hl, vChars1 + $7c0 + ld hl, vChars1 tile $7c call LoadCutGrassAnimationTilePattern - ld hl, vChars1 + $7d0 + ld hl, vChars1 tile $7d call LoadCutGrassAnimationTilePattern - ld hl, vChars1 + $7e0 + ld hl, vChars1 tile $7e call LoadCutGrassAnimationTilePattern - ld hl, vChars1 + $7f0 + ld hl, vChars1 tile $7f call LoadCutGrassAnimationTilePattern call WriteCutOrBoulderDustAnimationOAMBlock ld hl, wOAMBuffer + $93 @@ -113,8 +113,8 @@ InitCutAnimOAM: ret LoadCutGrassAnimationTilePattern: - ld de, AnimationTileset2 + $60 ; tile depicting a leaf - lb bc, BANK(AnimationTileset2), $01 + ld de, AnimationTileset2 tile 6 ; tile depicting a leaf + lb bc, BANK(AnimationTileset2), 1 jp CopyVideoData WriteCutOrBoulderDustAnimationOAMBlock: @@ -124,11 +124,11 @@ WriteCutOrBoulderDustAnimationOAMBlock: jp WriteOAMBlock CutOrBoulderDustAnimationTilesAndAttributes: - db $FC,$14,$FD,$14 - db $FE,$14,$FF,$14 + dbsprite 2, -1, 4, 4, $fd, OAM_OBP1 | %100 + dbsprite 2, -1, 4, 6, $ff, OAM_OBP1 | %100 GetCutOrBoulderDustAnimationOffsets: - ld hl, wSpriteStateData1 + 4 + ld hl, wSpritePlayerStateData1YPixels ld a, [hli] ; player's sprite screen Y position ld b, a inc hl @@ -188,7 +188,7 @@ ReplaceTreeTileBlock: ld h, [hl] ld l, a add hl, bc - ld a, [wSpritePlayerStateData1FacingDirection] ; player sprite's facing direction + ld a, [wSpritePlayerStateData1FacingDirection] and a jr z, .down cp SPRITE_FACING_UP @@ -249,16 +249,4 @@ ReplaceTreeTileBlock: ld [hl], a ret -CutTreeBlockSwaps: -; first byte = tileset block containing the cut tree -; second byte = corresponding tileset block after the cut animation happens - db $32, $6D - db $33, $6C - db $34, $6F - db $35, $4C - db $60, $6E - db $0B, $0A - db $3C, $35 - db $3F, $35 - db $3D, $36 - db $FF ; list terminator +INCLUDE "data/tilesets/cut_tree_blocks.asm" diff --git a/engine/overworld/cut2.asm b/engine/overworld/cut2.asm index 37490f95..1f691eef 100755 --- a/engine/overworld/cut2.asm +++ b/engine/overworld/cut2.asm @@ -15,9 +15,9 @@ AnimCut: ld [wCoordAdjustmentAmount], a ld c, 2 call AdjustOAMBlockXPos2 - ld a, [rOBP1] + ldh a, [rOBP1] xor $64 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 call DelayFrame pop bc @@ -66,9 +66,9 @@ AnimCutGrass_UpdateOAMEntries: ld [wCoordAdjustmentAmount], a ld c, 1 call AdjustOAMBlockXPos2 - ld a, [rOBP1] + ldh a, [rOBP1] xor $64 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 call DelayFrame pop bc diff --git a/engine/overworld/doors.asm b/engine/overworld/doors.asm index 8bde8600..d38818fa 100755 --- a/engine/overworld/doors.asm +++ b/engine/overworld/doors.asm @@ -11,7 +11,7 @@ IsPlayerStandingOnDoorTile: ld a, [hli] ld h, [hl] ld l, a - aCoord 8, 9 ; a = lower left background tile under player's sprite + lda_coord 8, 9 ; a = lower left background tile under player's sprite ld b, a .loop ld a, [hli] @@ -25,55 +25,4 @@ IsPlayerStandingOnDoorTile: and a ret -DoorTileIDPointers: - dbw OVERWORLD, OverworldDoorTileIDs - dbw FOREST, ForestDoorTileIDs - dbw MART, MartDoorTileIDs - dbw HOUSE, HouseDoorTileIDs - dbw FOREST_GATE, TilesetMuseumDoorTileIDs - dbw MUSEUM, TilesetMuseumDoorTileIDs - dbw GATE, TilesetMuseumDoorTileIDs - dbw SHIP, ShipDoorTileIDs - dbw LOBBY, LobbyDoorTileIDs - dbw MANSION, MansionDoorTileIDs - dbw LAB, LabDoorTileIDs - dbw FACILITY, FacilityDoorTileIDs - dbw PLATEAU, PlateauDoorTileIDs - dbw INTERIOR, InteriorDoorTileIDs - db $ff - -OverworldDoorTileIDs: - db $1B,$58,$00 - -ForestDoorTileIDs: - db $3a,$00 - -MartDoorTileIDs: - db $5e,$00 - -HouseDoorTileIDs: - db $54,$00 - -TilesetMuseumDoorTileIDs: - db $3b,$00 - -ShipDoorTileIDs: - db $1e,$00 - -LobbyDoorTileIDs: - db $1c,$38,$1a,$00 - -MansionDoorTileIDs: - db $1a,$1c,$53,$00 - -LabDoorTileIDs: - db $34,$00 - -FacilityDoorTileIDs: - db $43,$58,$1b,$00 - -PlateauDoorTileIDs: - db $3b,$1b,$00 - -InteriorDoorTileIDs: - db $04,$15,$00 +INCLUDE "data/tilesets/door_tile_ids.asm" diff --git a/engine/overworld/dungeon_warps.asm b/engine/overworld/dungeon_warps.asm index f47dfb01..7641c688 100644 --- a/engine/overworld/dungeon_warps.asm +++ b/engine/overworld/dungeon_warps.asm @@ -1,4 +1,4 @@ -IsPlayerOnDungeonWarp: +IsPlayerOnDungeonWarp:: xor a ld [wWhichDungeonWarp], a ld a, [wd72d] diff --git a/engine/overworld/dust_smoke.asm b/engine/overworld/dust_smoke.asm new file mode 100755 index 00000000..773def96 --- /dev/null +++ b/engine/overworld/dust_smoke.asm @@ -0,0 +1,95 @@ +AnimateBoulderDust: + ld a, $1 + ld [wWhichAnimationOffsets], a ; select the boulder dust offsets + ld a, [wUpdateSpritesEnabled] + push af + ld a, $ff + ld [wUpdateSpritesEnabled], a + ld a, %11100100 + ldh [rOBP1], a + call UpdateGBCPal_OBP1 + call LoadSmokeTileFourTimes + farcall WriteCutOrBoulderDustAnimationOAMBlock + ld c, 8 ; number of steps in animation +.loop + push bc + call GetMoveBoulderDustFunctionPointer + ld bc, .returnAddress + push bc + ld c, 4 + jp hl +.returnAddress + ldh a, [rOBP1] + xor %01100100 + ldh [rOBP1], a + call UpdateGBCPal_OBP1 + call Delay3 + pop bc + dec c + jr nz, .loop + pop af + ld [wUpdateSpritesEnabled], a + jp LoadPlayerSpriteGraphics + +GetMoveBoulderDustFunctionPointer: + ld a, [wSpritePlayerStateData1FacingDirection] + ld hl, MoveBoulderDustFunctionPointerTable + ld c, a + ld b, $0 + add hl, bc + ld a, [hli] + ld [wCoordAdjustmentAmount], a + ld a, [hli] + ld e, a + ld a, [hli] + ld h, [hl] + ld l, a + push hl + ld hl, wOAMBuffer + $90 + ld d, $0 + add hl, de + ld e, l + ld d, h + pop hl + ret + +MoveBoulderDustFunctionPointerTable: +; facing down + db $FF,$00 + dw AdjustOAMBlockYPos + +; facing up + db $01,$00 + dw AdjustOAMBlockYPos + +; facing left + db $01,$01 + dw AdjustOAMBlockXPos + +; facing right + db $FF,$01 + dw AdjustOAMBlockXPos + +LoadSmokeTileFourTimes:: + ld hl, vChars1 tile $7c + ld c, 4 +.loop + push bc + push hl + call LoadSmokeTile + pop hl + ld bc, 1 tiles + add hl, bc + pop bc + dec c + jr nz, .loop + ret + +LoadSmokeTile: + ld de, SSAnneSmokePuffTile + lb bc, BANK(SSAnneSmokePuffTile), (SSAnneSmokePuffTileEnd - SSAnneSmokePuffTile) / $10 + jp CopyVideoData + +SSAnneSmokePuffTile: + INCBIN "gfx/overworld/smoke.2bpp" +SSAnneSmokePuffTileEnd: diff --git a/engine/overworld/elevator.asm b/engine/overworld/elevator.asm index 47ec78f9..b873ffad 100755 --- a/engine/overworld/elevator.asm +++ b/engine/overworld/elevator.asm @@ -1,11 +1,11 @@ -ShakeElevator: +ShakeElevator:: ld de, -$20 call ShakeElevatorRedrawRow ld de, SCREEN_HEIGHT * $20 call ShakeElevatorRedrawRow call Delay3 call StopAllMusic - ld a, [hSCY] + ldh a, [hSCY] ld d, a ld e, $1 ld b, 100 @@ -14,7 +14,7 @@ ShakeElevator: xor $fe ld e, a add d - ld [hSCY], a + ldh [hSCY], a push bc ld c, BANK(SFX_Collision_1) ld a, SFX_COLLISION @@ -25,7 +25,7 @@ ShakeElevator: dec b jr nz, .shakeLoop ld a, d - ld [hSCY], a + ldh [hSCY], a call StopAllMusic ld c, BANK(SFX_Safari_Zone_PA) ld a, SFX_SAFARI_ZONE_PA @@ -54,7 +54,7 @@ ShakeElevatorRedrawRow: add hl, de ld a, h and $3 - or vBGMap0 / $100 + or HIGH(vBGMap0) ld d, a ld a, l pop hl diff --git a/engine/overworld/emotion_bubbles.asm b/engine/overworld/emotion_bubbles.asm index 3b02fd55..3ad714e9 100755 --- a/engine/overworld/emotion_bubbles.asm +++ b/engine/overworld/emotion_bubbles.asm @@ -11,8 +11,8 @@ EmotionBubble: add hl, bc ld e, l ld d, h - ld hl, vChars1 + $780 - lb bc, BANK(EmotionBubbles), $04 + ld hl, vChars1 tile $78 + lb bc, BANK(EmotionBubbles), 4 call CopyVideoData ld a, [wUpdateSpritesEnabled] push af @@ -41,7 +41,7 @@ EmotionBubble: jr nz, .loop ; get the screen coordinates of the sprite the bubble is to be displayed above - ld hl, wSpriteStateData1 + 4 + ld hl, wSpritePlayerStateData1YPixels ld a, [wEmotionBubbleSpriteIndex] swap a ld c, a @@ -67,8 +67,15 @@ EmotionBubble: EmotionBubblesOAM: - db $F8,$00,$F9,$00 - db $FA,$00,$FB,$00 + dbsprite 0, -1, 0, 0, $f9, 0 + dbsprite 0, -1, 0, 2, $fb, 0 EmotionBubbles: - INCBIN "gfx/emotion_bubbles.2bpp" +ShockEmote: INCBIN "gfx/emotes/shock.2bpp" +QuestionEmote: INCBIN "gfx/emotes/question.2bpp" +HappyEmote: INCBIN "gfx/emotes/happy.2bpp" +SkullEmote: INCBIN "gfx/emotes/skull.2bpp" +HeartEmote: INCBIN "gfx/emotes/heart.2bpp" +BoltEmote: INCBIN "gfx/emotes/bolt.2bpp" +ZzzEmote: INCBIN "gfx/emotes/zzz.2bpp" +FishEmote: INCBIN "gfx/emotes/fish.2bpp" diff --git a/engine/overworld/field_move_messages.asm b/engine/overworld/field_move_messages.asm index 1d111917..520ef8ad 100644 --- a/engine/overworld/field_move_messages.asm +++ b/engine/overworld/field_move_messages.asm @@ -7,16 +7,16 @@ PrintStrengthTxt: jp PrintText UsedStrengthText: - TX_FAR _UsedStrengthText - TX_ASM + text_far _UsedStrengthText + text_asm ld a, [wcf91] call PlayCry call Delay3 jp TextScriptEnd CanMoveBouldersText: - TX_FAR _CanMoveBouldersText - db "@" + text_far _CanMoveBouldersText + text_end IsSurfingAllowed: ; Returns whether surfing is allowed in bit 1 of wd728. @@ -32,7 +32,7 @@ IsSurfingAllowed: ret nz CheckBothEventsSet EVENT_SEAFOAM4_BOULDER1_DOWN_HOLE, EVENT_SEAFOAM4_BOULDER2_DOWN_HOLE ret z - ld hl, CoordsData_f5b64 + ld hl, CoordsData_cdf7 call ArePlayerCoordsInArray ret nc ld hl, wd728 @@ -45,13 +45,14 @@ IsSurfingAllowed: ld hl, CyclingIsFunText jp PrintText -CoordsData_f5b64: - db $0B,$07,$FF +CoordsData_cdf7: + dbmapcoord 7, 11 + db -1 ; end CurrentTooFastText: - TX_FAR _CurrentTooFastText - db "@" + text_far _CurrentTooFastText + text_end CyclingIsFunText: - TX_FAR _CyclingIsFunText - db "@" + text_far _CyclingIsFunText + text_end diff --git a/engine/overworld/healing_machine.asm b/engine/overworld/healing_machine.asm index e5ba004e..e5fba7e1 100755 --- a/engine/overworld/healing_machine.asm +++ b/engine/overworld/healing_machine.asm @@ -1,17 +1,17 @@ AnimateHealingMachine: ld de, PokeCenterFlashingMonitorAndHealBall - ld hl, vChars0 + $7c0 - lb bc, BANK(PokeCenterFlashingMonitorAndHealBall), $03 ; loads one too many tiles + ld hl, vChars0 tile $7c + lb bc, BANK(PokeCenterFlashingMonitorAndHealBall), 3 ; should be 2 call CopyVideoData ld hl, wUpdateSpritesEnabled ld a, [hl] push af ld [hl], $ff push hl - ld a, [rOBP1] + ldh a, [rOBP1] push af ld a, $e0 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 ld hl, wOAMBuffer + $84 ld de, PokeCenterOAMData @@ -53,7 +53,7 @@ AnimateHealingMachine: ld c, 32 call DelayFrames pop af - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 pop hl pop af @@ -61,24 +61,26 @@ AnimateHealingMachine: jp UpdateSprites PokeCenterFlashingMonitorAndHealBall: - INCBIN "gfx/pokecenter_ball.2bpp" + INCBIN "gfx/overworld/heal_machine.2bpp" PokeCenterOAMData: - db $24,$34,$7C,$14 ; heal machine monitor - db $2B,$30,$7D,$14 ; pokeballs 1-6 - db $2B,$38,$7D,$34 - db $30,$30,$7D,$14 - db $30,$38,$7D,$34 - db $35,$30,$7D,$14 - db $35,$38,$7D,$34 + ; heal machine monitor + dbsprite 6, 4, 4, 4, $7c, OAM_OBP1 | %100 + ; poke balls 1-6 + dbsprite 6, 5, 0, 3, $7d, OAM_OBP1 | %100 + dbsprite 7, 5, 0, 3, $7d, OAM_OBP1 | OAM_HFLIP | %100 + dbsprite 6, 6, 0, 0, $7d, OAM_OBP1 | %100 + dbsprite 7, 6, 0, 0, $7d, OAM_OBP1 | OAM_HFLIP | %100 + dbsprite 6, 6, 0, 5, $7d, OAM_OBP1 | %100 + dbsprite 7, 6, 0, 5, $7d, OAM_OBP1 | OAM_HFLIP | %100 ; d = value to xor with palette FlashSprite8Times: ld b, 8 .loop - ld a, [rOBP1] + ldh a, [rOBP1] xor d - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 ld c, 10 call DelayFrames @@ -88,16 +90,9 @@ FlashSprite8Times: CopyHealingMachineOAM: ; copy one OAM entry and advance the pointers + REPT 4 ld a, [de] inc de ld [hli], a - ld a, [de] - inc de - ld [hli], a - ld a, [de] - inc de - ld [hli], a - ld a, [de] - inc de - ld [hli], a + ENDR ret diff --git a/engine/overworld/hidden_items.asm b/engine/overworld/hidden_items.asm deleted file mode 100755 index b64411c7..00000000 --- a/engine/overworld/hidden_items.asm +++ /dev/null @@ -1,172 +0,0 @@ -HiddenItems: - ld hl, HiddenItemCoords - call FindHiddenItemOrCoinsIndex - ld [wHiddenItemOrCoinsIndex], a - ld hl, wObtainedHiddenItemsFlags - ld a, [wHiddenItemOrCoinsIndex] - ld c, a - ld b, FLAG_TEST - predef FlagActionPredef - ld a, c - and a - jr nz, .itemAlreadyFound - call EnableAutoTextBoxDrawing - ld a, 1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ld a, [wHiddenObjectFunctionArgument] ; item ID - ld [wd11e], a - call GetItemName - tx_pre_jump FoundHiddenItemText - -.itemAlreadyFound - ld a, $ff - ld [hItemAlreadyFound], a - ret - -INCLUDE "data/hidden_item_coords.asm" - -FoundHiddenItemText: - TX_FAR _FoundHiddenItemText - TX_ASM - ld a, [wHiddenObjectFunctionArgument] ; item ID - ld b, a - ld c, 1 - call GiveItem - jr nc, .bagFull - ld hl, wObtainedHiddenItemsFlags - ld a, [wHiddenItemOrCoinsIndex] - ld c, a - ld b, FLAG_SET - predef FlagActionPredef - ld a, SFX_GET_ITEM_2 - call PlaySoundWaitForCurrent - call WaitForSoundToFinish - jp TextScriptEnd -.bagFull - call WaitForTextScrollButtonPress ; wait for button press - xor a - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ld hl, HiddenItemBagFullText - call PrintText - jp TextScriptEnd - -HiddenItemBagFullText: - TX_FAR _HiddenItemBagFullText - db "@" - -HiddenCoins: - ld b, COIN_CASE - predef GetQuantityOfItemInBag - ld a, b - and a - jr z, .doNotPickUpCoins - ld hl, HiddenCoinCoords - call FindHiddenItemOrCoinsIndex - ld [wHiddenItemOrCoinsIndex], a - ld hl, wObtainedHiddenCoinsFlags - ld a, [wHiddenItemOrCoinsIndex] - ld c, a - ld b, FLAG_TEST - predef FlagActionPredef - ld a, c - and a - jr nz, .doNotPickUpCoins - xor a - ld [hUnusedCoinsByte], a - ld [hCoins], a - ld [hCoins + 1], a - ld a, [wHiddenObjectFunctionArgument] - sub COIN - cp 10 - jr z, .bcd10 - cp 20 - jr z, .bcd20 - cp 40 - jr z, .bcd20 ; should be bcd40 - jr .bcd100 - -.doNotPickUpCoins - ld a, $ff - ld [hItemAlreadyFound], a - ret - -.bcd10 - ld a, $10 - ld [hCoins + 1], a - jr .bcdDone -.bcd20 - ld a, $20 - ld [hCoins + 1], a - jr .bcdDone -.bcd40 ; due to a typo, this is never used - ld a, $40 - ld [hCoins + 1], a - jr .bcdDone -.bcd100 - ld a, $1 - ld [hCoins], a -.bcdDone - ld de, wPlayerCoins + 1 - ld hl, hCoins + 1 - ld c, $2 - predef AddBCDPredef - ld hl, wObtainedHiddenCoinsFlags - ld a, [wHiddenItemOrCoinsIndex] - ld c, a - ld b, FLAG_SET - predef FlagActionPredef - call EnableAutoTextBoxDrawing - ld a, [wPlayerCoins] - cp $99 - jr nz, .roomInCoinCase - ld a, [wPlayerCoins + 1] - cp $99 - jr nz, .roomInCoinCase - tx_pre_id DroppedHiddenCoinsText - jr .done -.roomInCoinCase - tx_pre_id FoundHiddenCoinsText -.done - jp PrintPredefTextID - -INCLUDE "data/hidden_coins.asm" - -FoundHiddenCoinsText: - TX_FAR _FoundHiddenCoinsText - TX_SFX_ITEM_2 - db "@" - -DroppedHiddenCoinsText: - TX_FAR _FoundHiddenCoins2Text - TX_SFX_ITEM_2 - TX_FAR _DroppedHiddenCoinsText - db "@" - -FindHiddenItemOrCoinsIndex: - ld a, [wHiddenObjectY] - ld d, a - ld a, [wHiddenObjectX] - ld e, a - ld a, [wCurMap] - ld b, a - ld c, -1 -.loop - inc c - ld a, [hli] - cp $ff ; end of the list? - ret z ; if so, we're done here - cp b - jr nz, .next1 - ld a, [hli] - cp d - jr nz, .next2 - ld a, [hli] - cp e - jr nz, .loop - ld a, c - ret -.next1 - inc hl -.next2 - inc hl - jr .loop diff --git a/engine/overworld/hidden_objects.asm b/engine/overworld/hidden_objects.asm index 66815b60..84108986 100755 --- a/engine/overworld/hidden_objects.asm +++ b/engine/overworld/hidden_objects.asm @@ -1,11 +1,11 @@ ; if a hidden object was found, stores $00 in [hDidntFindAnyHiddenObject], else stores $ff -CheckForHiddenObject: +CheckForHiddenObject:: ld hl, hItemAlreadyFound xor a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hl], a + ld [hli], a ; [hItemAlreadyFound] + ld [hli], a ; [hSavedMapTextPtr] + ld [hli], a ; [hSavedMapTextPtr + 1] + ld [hl], a ; [hDidntFindAnyHiddenObject] ld hl, HiddenObjectMaps ld de, 3 ld a, [wCurMap] @@ -32,7 +32,7 @@ CheckForHiddenObject: ld [wHiddenObjectX], a ld c, a call CheckIfCoordsInFrontOfPlayerMatch - ld a, [hCoordsInFrontOfPlayerMatch] + ldh a, [hCoordsInFrontOfPlayerMatch] and a jr z, .foundMatchingObject inc hl @@ -55,13 +55,13 @@ CheckForHiddenObject: ret .noMatch ld a, $ff - ld [hDidntFindAnyHiddenObject], a + ldh [hDidntFindAnyHiddenObject], a ret ; checks if the coordinates in front of the player's sprite match Y in b and X in c ; [hCoordsInFrontOfPlayerMatch] = $00 if they match, $ff if they don't match CheckIfCoordsInFrontOfPlayerMatch: - ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] cp SPRITE_FACING_UP jr z, .facingUp cp SPRITE_FACING_LEFT @@ -101,7 +101,7 @@ CheckIfCoordsInFrontOfPlayerMatch: .didNotMatch ld a, $ff .done - ld [hCoordsInFrontOfPlayerMatch], a + ldh [hCoordsInFrontOfPlayerMatch], a ret -INCLUDE "data/hidden_objects.asm" +INCLUDE "data/events/hidden_objects.asm" diff --git a/engine/overworld/item.asm b/engine/overworld/item.asm deleted file mode 100644 index 9f19100a..00000000 --- a/engine/overworld/item.asm +++ /dev/null @@ -1,54 +0,0 @@ -PickUpItem: - call EnableAutoTextBoxDrawing - - ld a, [hSpriteIndexOrTextID] - ld b, a - ld hl, wMissableObjectList -.missableObjectsListLoop - ld a, [hli] - cp $ff - ret z - cp b - jr z, .isMissable - inc hl - jr .missableObjectsListLoop - -.isMissable - ld a, [hl] - ld [$ffdb], a - - ld hl, wMapSpriteExtraData - ld a, [hSpriteIndexOrTextID] - dec a - add a - ld d, 0 - ld e, a - add hl, de - ld a, [hl] - ld b, a ; item - ld c, 1 ; quantity - call GiveItem - jr nc, .BagFull - - ld a, [$ffdb] - ld [wMissableObjectIndex], a - predef HideObject - ld a, 1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ld hl, FoundItemText - jr .print - -.BagFull - ld hl, NoMoreRoomForItemText -.print - call PrintText - ret - -FoundItemText: - TX_FAR _FoundItemText - TX_SFX_ITEM_1 - db "@" - -NoMoreRoomForItemText: - TX_FAR _NoMoreRoomForItemText - db "@" diff --git a/engine/overworld/ledges.asm b/engine/overworld/ledges.asm index a44ddf8b..9925c528 100755 --- a/engine/overworld/ledges.asm +++ b/engine/overworld/ledges.asm @@ -1,4 +1,4 @@ -HandleLedges: +HandleLedges:: ld a, [wd736] bit 6, a ; already jumping down ledge ret nz @@ -8,7 +8,7 @@ HandleLedges: predef GetTileAndCoordsInFrontOfPlayer ld a, [wSpritePlayerStateData1FacingDirection] ld b, a - aCoord 8, 9 + lda_coord 8, 9 ld c, a ld a, [wTileInFrontOfPlayer] ld d, a @@ -36,7 +36,7 @@ HandleLedges: inc hl jr .loop .foundMatch - ld a, [hJoyHeld] + ldh a, [hJoyHeld] and e ret z ld a, $ff @@ -54,20 +54,10 @@ HandleLedges: call PlaySound ret - ; (player direction) (tile player standing on) (ledge tile) (input required) -LedgeTiles: - db SPRITE_FACING_DOWN, $2C,$37,D_DOWN - db SPRITE_FACING_DOWN, $39,$36,D_DOWN - db SPRITE_FACING_DOWN, $39,$37,D_DOWN - db SPRITE_FACING_LEFT, $2C,$27,D_LEFT - db SPRITE_FACING_LEFT, $39,$27,D_LEFT - db SPRITE_FACING_RIGHT,$2C,$0D,D_RIGHT - db SPRITE_FACING_RIGHT,$2C,$1D,D_RIGHT - db SPRITE_FACING_RIGHT,$39,$0D,D_RIGHT - db $FF +INCLUDE "data/tilesets/ledge_tiles.asm" LoadHoppingShadowOAM: - ld hl, vChars1 + $7f0 + ld hl, vChars1 tile $7f ld de, LedgeHoppingShadow lb bc, BANK(LedgeHoppingShadow), (LedgeHoppingShadowEnd - LedgeHoppingShadow) / $8 call CopyVideoDataDouble @@ -81,10 +71,10 @@ LoadHoppingShadowOAM: ret LedgeHoppingShadow: - INCBIN "gfx/ledge_hopping_shadow.1bpp" + INCBIN "gfx/overworld/shadow.1bpp" LedgeHoppingShadowEnd: LedgeHoppingShadowOAM: - db $58,$48,$FF,$00 - db $58,$50,$FF,$20 + dbsprite 9, 11, 0, 0, $ff, 0 + dbsprite 10, 11, 0, 0, $ff, OAM_HFLIP LedgeHoppingShadowOAMEnd: diff --git a/engine/overworld/map_sprite_functions1.asm b/engine/overworld/map_sprite_functions1.asm deleted file mode 100644 index 2ad923fb..00000000 --- a/engine/overworld/map_sprite_functions1.asm +++ /dev/null @@ -1,390 +0,0 @@ -_UpdateSprites: - ld h, wSpriteStateData1 / $100 - inc h - ld a, $e ; (wSpriteStateData2 + $0e) & $ff -.spriteLoop - ld l, a - sub $e - ld c, a - ld [H_CURRENTSPRITEOFFSET], a - ld a, [hl] - and a - jr z, .skipSprite ; tests $c2Xe - push hl - push de - push bc - call .updateCurrentSprite - pop bc - pop de - pop hl -.skipSprite - ld a, l - add $10 ; move to next sprite - cp $e ; test for overflow (back at $0e) - jr nz, .spriteLoop - ret -.updateCurrentSprite - ld a, [H_CURRENTSPRITEOFFSET] - and a - jp z, UpdatePlayerSprite - cp $f0 ; pikachu - jp z, SpawnPikachu - ld a, [hl] - -UpdateNonPlayerSprite: - dec a - swap a - ld [$ff93], a ; $10 * sprite# - ld a, [wNPCMovementScriptSpriteOffset] ; some sprite offset? - ld b, a - ld a, [H_CURRENTSPRITEOFFSET] - cp b - jr nz, .unequal - jp DoScriptedNPCMovement -.unequal - jp UpdateNPCSprite - -; This detects if the current sprite (whose offset is at H_CURRENTSPRITEOFFSET) -; is going to collide with another sprite by looping over the other sprites. -; The current sprite's offset will be labelled with i (e.g. $c1i0). -; The loop sprite's offset will labelled with j (e.g. $c1j0). -; -; Note that the Y coordinate of the sprite (in [$c1k4]) is one of the following -; 9 values when the sprite is aligned with the grid: $fc, $0c, $1c, $2c, ..., $7c. -; The reason that 4 is added below to the coordinate is to make it align with a -; multiple of $10 to make comparisons easier. -DetectCollisionBetweenSprites: - ; nop - - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - ld l, a - - ld a, [hl] ; a = [$c1i0] (picture) (0 if slot is unused) - and a ; is this sprite slot slot used? - ret z ; return if not used - - ld a, l - add 3 - ld l, a - - ld a, [hli] ; a = [$c1i3] (delta Y) (-1, 0, or 1) - call SetSpriteCollisionValues - - ld a, [hli] ; a = [$C1i4] (Y screen coordinate) - add 4 ; align with multiple of $10 - -; The effect of the following 3 lines is to -; add 7 to a if moving south or -; subtract 7 from a if moving north. - add b - and $f0 - or c - - ld [$ff90], a ; store Y coordinate adjusted for direction of movement - - ld a, [hli] ; a = [$c1i5] (delta X) (-1, 0, or 1) - call SetSpriteCollisionValues - ld a, [hl] ; a = [$C1i6] (X screen coordinate) - -; The effect of the following 3 lines is to -; add 7 to a if moving east or -; subtract 7 from a if moving west. - add b - and $f0 - or c - - ld [$ff91], a ; store X coordinate adjusted for direction of movement - - ld a, l - add 7 - ld l, a - - xor a - ld [hld], a ; zero [$c1id] XXX what's [$c1id] for? - ld [hld], a ; zero [$c1ic] (directions in which collisions occurred) - - ld a, [$ff91] - ld [hld], a ; [$c1ib] = adjusted X coordinate - ld a, [$ff90] - ld [hl], a ; [$c1ia] = adjusted Y coordinate - - xor a ; zero the loop counter - -.loop - ld [$ff8f], a ; store loop counter - swap a - ld e, a - ld a, [H_CURRENTSPRITEOFFSET] - cp e ; does the loop sprite match the current sprite? - jp z, .next ; go to the next sprite if they match - - ld d, h - ld a, [de] ; a = [$c1j0] (picture) (0 if slot is unused) - and a ; is this sprite slot slot used? - jp z, .next ; go the next sprite if not used - - inc e - inc e - ld a, [de] ; a = [$c1j2] ($ff means the sprite is offscreen) - inc a - jp z, .next ; go the next sprite if offscreen - - ld a, [H_CURRENTSPRITEOFFSET] - add 10 - ld l, a - - inc e - ld a, [de] ; a = [$c1j3] (delta Y) - call SetSpriteCollisionValues - - inc e - ld a, [de] ; a = [$C1j4] (Y screen coordinate) - add 4 ; align with multiple of $10 - -; The effect of the following 3 lines is to -; add 7 to a if moving south or -; subtract 7 from a if moving north. - add b - and $f0 - or c - - sub [hl] ; subtract the adjusted Y coordinate of sprite i ([$c1ia]) from that of sprite j - -; calculate the absolute value of the difference to get the distance - jr nc, .noCarry1 - cpl - inc a -.noCarry1 - ld [$ff90], a ; store the distance between the two sprites' adjusted Y values - -; Use the carry flag set by the above subtraction to determine which sprite's -; Y coordinate is larger. This information is used later to set [$c1ic], -; which stores which direction the collision occurred in. -; The following 5 lines set the lowest 2 bits of c, which are later shifted left by 2. -; If sprite i's Y is larger, set lowest 2 bits of c to 10. -; If sprite j's Y is larger or both are equal, set lowest 2 bits of c to 01. - push af - rl c - pop af - ccf - rl c - -; If sprite i's delta Y is 0, then b = 7, else b = 9. - ld b, 7 - ld a, [hl] ; a = [$c1ia] (adjusted Y coordinate) - and $f - jr z, .next1 - ld b, 9 - -.next1 - ld a, [$ff90] ; a = distance between adjusted Y coordinates - sub b - ld [$ff92], a ; store distance adjusted using sprite i's direction - ld a, b - ld [$ff90], a ; store 7 or 9 depending on sprite i's delta Y - jr c, .checkXDistance - -; If sprite j's delta Y is 0, then b = 7, else b = 9. - ld b, 7 - dec e - ld a, [de] ; a = [$c1j3] (delta Y) - inc e - and a - jr z, .next2 - ld b, 9 - -.next2 - ld a, [$ff92] ; a = distance adjusted using sprite i's direction - sub b ; adjust distance using sprite j's direction - jr z, .checkXDistance - jr nc, .next ; go to next sprite if distance is still positive after both adjustments - -.checkXDistance - inc e - inc l - ld a, [de] ; a = [$c1j5] (delta X) - - push bc - - call SetSpriteCollisionValues - inc e - ld a, [de] ; a = [$c1j6] (X screen coordinate) - -; The effect of the following 3 lines is to -; add 7 to a if moving east or -; subtract 7 from a if moving west. - add b - and $f0 - or c - - pop bc - - sub [hl] ; subtract the adjusted X coordinate of sprite i ([$c1ib]) from that of sprite j - -; calculate the absolute value of the difference to get the distance - jr nc, .noCarry2 - cpl - inc a -.noCarry2 - ld [$ff91], a ; store the distance between the two sprites' adjusted X values - -; Use the carry flag set by the above subtraction to determine which sprite's -; X coordinate is larger. This information is used later to set [$c1ic], -; which stores which direction the collision occurred in. -; The following 5 lines set the lowest 2 bits of c. -; If sprite i's X is larger, set lowest 2 bits of c to 10. -; If sprite j's X is larger or both are equal, set lowest 2 bits of c to 01. - push af - rl c - pop af - ccf - rl c - -; If sprite i's delta X is 0, then b = 7, else b = 9. - ld b, 7 - ld a, [hl] ; a = [$c1ib] (adjusted X coordinate) - and $f - jr z, .next3 - ld b, 9 - -.next3 - ld a, [$ff91] ; a = distance between adjusted X coordinates - sub b - ld [$ff92], a ; store distance adjusted using sprite i's direction - ld a, b - ld [$ff91], a ; store 7 or 9 depending on sprite i's delta X - jr c, .collision - -; If sprite j's delta X is 0, then b = 7, else b = 9. - ld b, 7 - dec e - ld a, [de] ; a = [$c1j5] (delta X) - inc e - and a - jr z, .next4 - ld b, 9 - -.next4 - ld a, [$ff92] ; a = distance adjusted using sprite i's direction - sub b ; adjust distance using sprite j's direction - jr z, .collision - jr nc, .next ; go to next sprite if distance is still positive after both adjustments - -.collision - ld a, l - and $f0 ; collision with pikachu? - jr nz, .asm_4cd9 - xor a - ld [wd434], a - ld a, [$ff8f] - cp $f - jr nz, .asm_4cd9 - call Func_4d0a - jr .asm_4cef -.asm_4cd9 - ld a, [$ff91] ; a = 7 or 9 depending on sprite i's delta X - ld b, a - ld a, [$ff90] ; a = 7 or 9 depending on sprite i's delta Y - inc l - -; If delta X isn't 0 and delta Y is 0, then b = %0011, else b = %1100. -; (note that normally if delta X isn't 0, then delta Y must be 0 and vice versa) - cp b - jr c, .next5 - ld b, %1100 - jr .next6 -.next5 - ld b, %0011 - -.next6 - ld a, c ; c has 2 bits set (one of bits 0-1 is set for the X axis and one of bits 2-3 for the Y axis) - and b ; we select either the bit in bits 0-1 or bits 2-3 based on the calculation immediately above - or [hl] ; or with existing collision direction bits in [$c1ic] - ld [hl], a ; store new value - ld a, c ; useless code because a is overwritten before being used again - -; set bit in [$c1ie] or [$c1if] to indicate which sprite the collision occurred with - inc l - inc l -.asm_4cef - ld a, [$ff8f] ; a = loop counter - ld de, SpriteCollisionBitTable - add a - add e - ld e, a - jr nc, .noCarry3 - inc d -.noCarry3 - ld a, [de] - or [hl] - ld [hli], a - inc de - ld a, [de] - or [hl] - ld [hl], a - -.next - ld a, [$ff8f] ; a = loop counter - inc a - cp $10 - jp nz, .loop - ret - -; takes delta X or delta Y in a -; b = delta X/Y -; c = 0 if delta X/Y is 0 -; c = 7 if delta X/Y is 1 -; c = 9 if delta X/Y is -1 -Func_4d0a: - ld a, [$ff91] - ld b, a - ld a, [$ff90] - inc l - cp b - jr c, .asm_4d17 - ld b, %1100 - jr .asm_4d19 -.asm_4d17 - ld b, %11 -.asm_4d19 - ld a, c - and b - ld [wd434], a - ld a, c - inc l - inc l - ret - -SetSpriteCollisionValues: - and a - ld b, 0 - ld c, 0 - jr z, .done - ld c, 9 - cp -1 - jr z, .ok - ld c, 7 - ld a, 0 -.ok - ld b, a -.done - ret - -SpriteCollisionBitTable: - db %00000000,%00000001 - db %00000000,%00000010 - db %00000000,%00000100 - db %00000000,%00001000 - db %00000000,%00010000 - db %00000000,%00100000 - db %00000000,%01000000 - db %00000000,%10000000 - db %00000001,%00000000 - db %00000010,%00000000 - db %00000100,%00000000 - db %00001000,%00000000 - db %00010000,%00000000 - db %00100000,%00000000 - db %01000000,%00000000 - db %10000000,%00000000 diff --git a/engine/overworld/map_sprites.asm b/engine/overworld/map_sprites.asm index 3e2c3912..e31c0bd2 100755 --- a/engine/overworld/map_sprites.asm +++ b/engine/overworld/map_sprites.asm @@ -8,7 +8,7 @@ ; fields, respectively, within loops. The X is the loop index. ; If there is an inner loop, Y is the inner loop index, i.e. $C1Y* and $C2Y* ; denote fields of the sprite slots iterated over in the inner loop. -_InitMapSprites: +_InitMapSprites:: call InitOutsideMapSprites ret c ; return if the map is an outside map (already handled by above call) ; if the map is an inside map (i.e. mapID >= $25) @@ -21,7 +21,7 @@ _InitMapSprites: ; sets carry if the map is a city or route, unsets carry if not InitOutsideMapSprites: ld a, [wCurMap] - cp a, REDS_HOUSE_1F ; is the map a city or a route (map ID less than $25)? + cp FIRST_INDOOR_MAP ; is the map a city or a route? ret nc ; if not, return call GetSplitMapSpriteSetID ; if so, choose the appropriate one @@ -68,7 +68,7 @@ LoadSpriteSetFromMapHeader: ld a, 14 .storeVRAMSlotsLoop push af - ld a, [hl] ; $C1X0 (picture ID) (zero if sprite slot is not used) + ld a, [hl] ; [x#SPRITESTATEDATA1_PICTUREID] (zero if sprite slot is not used) and a ; is the sprite slot used? jr z, .continue ; if the sprite slot is not used ld c, a @@ -125,7 +125,7 @@ CheckForFourTileSprite: cp SPRITE_PIKACHU ; is this the Pikachu Sprite? ret z ; return if yes - cp SPRITE_BALL ; is this a four tile sprite? + cp FIRST_STILL_SPRITE ; is this a four tile sprite? jr nc, .notYellowSprite ; set carry if yes ; regular sprite and a @@ -138,7 +138,7 @@ CheckForFourTileSprite: LoadMapSpriteTilePatterns: ld a, 0 .loop - ld [hVRAMSlot], a + ldh [hVRAMSlot], a cp 9 jr nc, .fourTileSprite call LoadStillTilePattern @@ -148,7 +148,7 @@ LoadMapSpriteTilePatterns: .fourTileSprite call LoadStillTilePattern .continue - ld a, [hVRAMSlot] + ldh a, [hVRAMSlot] inc a cp 11 jr nz, .loop @@ -157,12 +157,12 @@ LoadMapSpriteTilePatterns: ReloadWalkingTilePatterns: xor a .loop - ld [hVRAMSlot], a + ldh [hVRAMSlot], a cp 9 jr nc, .fourTileSprite call LoadWalkingTilePattern .fourTileSprite - ld a, [hVRAMSlot] + ldh a, [hVRAMSlot] inc a cp 11 jr nz, .loop @@ -192,7 +192,7 @@ LoadWalkingTilePattern: GetSpriteVRAMAddress: push bc - ld a, [hVRAMSlot] + ldh a, [hVRAMSlot] ld c, a ld b, 0 ld hl, SpriteVRAMAddresses @@ -220,7 +220,7 @@ SpriteVRAMAddresses: dw vChars0 + $7c0 ; 4-tile sprites ReadSpriteSheetData: - ld a, [hVRAMSlot] + ldh a, [hVRAMSlot] ld e, a ld d, 0 ld hl, wSpriteSet @@ -257,20 +257,20 @@ Func_14150: ld a, $e ld hl, wSprite01StateData1 .loop - ld [hVRAMSlot], a ; store current sprite set slot as a counter - ld a, [hl] ; $c1x0 (picture ID) + ldh [hVRAMSlot], a ; store current sprite set slot as a counter + ld a, [hl] ; [x#SPRITESTATEDATA1_PICTUREID] and a ; is the sprite unused? jr z, .spriteUnused call Func_14179 push hl ld de, (wSpritePlayerStateData2ImageBaseOffset) - (wSpriteStateData1) ; $10e - add hl, de ; get $c2xe (sprite image base offset) + add hl, de ; [x#SPRITESTATEDATA2_IMAGEBASEOFFSET] ld [hl], a ; write offset pop hl .spriteUnused ld de, wSprite02StateData1 - wSprite01StateData1 add hl, de - ld a, [hVRAMSlot] + ldh a, [hVRAMSlot] dec a jr nz, .loop ret @@ -364,4 +364,6 @@ GetSplitMapSpriteSetID: ld a, $01 ret -INCLUDE "data/sprite_sets.asm" +INCLUDE "data/maps/sprite_sets.asm" + +INCLUDE "data/sprites/sprites.asm" diff --git a/engine/overworld/missable_objects.asm b/engine/overworld/missable_objects.asm index dd601451..358a9b9f 100644 --- a/engine/overworld/missable_objects.asm +++ b/engine/overworld/missable_objects.asm @@ -1,6 +1,6 @@ -MarkTownVisitedAndLoadMissableObjects: +MarkTownVisitedAndLoadMissableObjects:: ld a, [wCurMap] - cp ROUTE_1 + cp FIRST_ROUTE_MAP jr nc, .notInTown ld c, a ld b, FLAG_SET @@ -22,31 +22,31 @@ MarkTownVisitedAndLoadMissableObjects: ld l, a push hl ld a, l - sub MapHS00 & $ff ; calculate difference between out pointer and the base pointer + sub MissableObjects & $ff ; calculate difference between out pointer and the base pointer ld l, a ld a, h - sbc MapHS00 / $100 + sbc MissableObjects / $100 ld h, a ld a, h - ld [H_DIVIDEND], a + ldh [hDividend], a ld a, l - ld [H_DIVIDEND + 1], a + ldh [hDividend+1], a xor a - ld [H_DIVIDEND + 2], a - ld [H_DIVIDEND + 3], a + ldh [hDividend+2], a + ldh [hDividend+3], a ld a, $3 - ld [H_DIVISOR], a + ldh [hDivisor], a ld b, $2 call Divide ; divide difference by 3, resulting in the global offset (number of missable items before ours) ld a, [wCurMap] ld b, a - ld a, [H_DIVIDEND + 3] + ldh a, [hDividend+3] ld c, a ; store global offset in c ld de, wMissableObjectList pop hl .writeMissableObjectsListLoop ld a, [hli] - cp $ff + cp -1 jr z, .done ; end of list cp b jr nz, .done ; not for current map anymore @@ -60,7 +60,7 @@ MarkTownVisitedAndLoadMissableObjects: inc de jr .writeMissableObjectsListLoop .done - ld a, $ff + ld a, -1 ld [de], a ; write sentinel ret @@ -69,17 +69,17 @@ InitializeMissableObjectsFlags: ld bc, wMissableObjectFlagsEnd - wMissableObjectFlags xor a call FillMemory ; clear missable objects flags - ld hl, MapHS00 + ld hl, MissableObjects xor a ld [wMissableObjectCounter], a .missableObjectsLoop ld a, [hli] - cp $ff ; end of list + cp -1 ; end of list ret z push hl inc hl ld a, [hl] - cp Hide + cp HIDE jr nz, .skip ld hl, wMissableObjectFlags ld a, [wMissableObjectCounter] @@ -96,13 +96,13 @@ InitializeMissableObjectsFlags: ; tests if current sprite is a missable object that is hidden/has been removed IsObjectHidden: - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] swap a ld b, a ld hl, wMissableObjectList .loop ld a, [hli] - cp $ff + cp -1 jr z, .notHidden ; not missable -> not hidden cp b ld a, [hli] @@ -117,7 +117,7 @@ IsObjectHidden: .notHidden xor a .hidden - ld [$ffe5], a + ldh [hIsHiddenMissableObject], a ret ; adds missable object (items, leg. pokemon, etc.) to the map diff --git a/engine/overworld/movement.asm b/engine/overworld/movement.asm index f2334479..dadf2194 100644 --- a/engine/overworld/movement.asm +++ b/engine/overworld/movement.asm @@ -1,25 +1,25 @@ MAP_TILESET_SIZE EQU $60 UpdatePlayerSprite: - ld a, [wSpriteStateData2] + ld a, [wSpritePlayerStateData2WalkAnimationCounter] and a jr z, .checkIfTextBoxInFrontOfSprite cp $ff jr z, .disableSprite dec a - ld [wSpriteStateData2], a + ld [wSpritePlayerStateData2WalkAnimationCounter], a jr .disableSprite ; check if a text box is in front of the sprite by checking if the lower left ; background tile the sprite is standing on is greater than $5F, which is ; the maximum number for map tiles .checkIfTextBoxInFrontOfSprite - aCoord 8, 9 - ld [hTilePlayerStandingOn], a + lda_coord 8, 9 + ldh [hTilePlayerStandingOn], a cp MAP_TILESET_SIZE jr c, .lowerLeftTileIsMapTile .disableSprite ld a, $ff - ld [wSpriteStateData1 + 2], a + ld [wSpritePlayerStateData1ImageIndex], a ret .lowerLeftTileIsMapTile ld a, [wUpdateSpritesEnabled] @@ -29,7 +29,7 @@ UpdatePlayerSprite: call DetectCollisionBetweenSprites pop af ld [wUpdateSpritesEnabled], a - ld h, wSpriteStateData1 / $100 + ld h, HIGH(wSpriteStateData1) ld a, [wWalkCounter] and a jr nz, .moving @@ -62,8 +62,8 @@ UpdatePlayerSprite: .notMoving ; zero the animation counters xor a - ld [wSpriteStateData1 + 7], a - ld [wSpriteStateData1 + 8], a + ld [wSpritePlayerStateData1IntraAnimFrameCounter], a + ld [wSpritePlayerStateData1AnimFrameCounter], a call Func_4e32 jr .skipSpriteAnim .moving @@ -77,27 +77,27 @@ UpdatePlayerSprite: ; lower priority than the background so that it's partially obscured by the ; grass. Only the lower half of the sprite is permitted to have the priority ; bit set by later logic. - ld a, [hTilePlayerStandingOn] + ldh a, [hTilePlayerStandingOn] ld c, a ld a, [wGrassTile] cp c - ld a, $0 + ld a, 0 jr nz, .next2 - ld a, $80 + ld a, OAM_BEHIND_BG .next2 - ld [wSpriteStateData2 + $07], a + ld [wSpritePlayerStateData2GrassPriority], a ret Func_4e32: - ld a, [wSpriteStateData1 + 8] + ld a, [wSpritePlayerStateData1AnimFrameCounter] ld b, a ld a, [wSpritePlayerStateData1FacingDirection] add b - ld [wSpriteStateData1 + 2], a + ld [wSpritePlayerStateData1ImageIndex], a ret UpdateNPCSprite: - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] swap a dec a add a @@ -106,20 +106,20 @@ UpdateNPCSprite: ld l, a ld a, [hl] ; read movement byte 2 ld [wCurSpriteMovement2], a - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] ld l, a inc l - ld a, [hl] ; c1x1 + ld a, [hl] ; x#SPRITESTATEDATA1_MOVEMENTSTATUS and a jp z, InitializeSpriteStatus call CheckSpriteAvailability ret c ; if sprite is invisible, on tile >=MAP_TILESET_SIZE, in grass or player is currently walking - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] ld l, a inc l - ld a, [hl] ; c1x1 + ld a, [hl] ; x#SPRITESTATEDATA1_MOVEMENTSTATUS bit 7, a ; is the face player flag set? jp nz, MakeNPCFacePlayer ld b, a @@ -128,24 +128,24 @@ UpdateNPCSprite: jp nz, notYetMoving ld a, b cp $2 - jp z, UpdateSpriteMovementDelay ; c1x1 == 2 + jp z, UpdateSpriteMovementDelay ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] == 2 cp $3 - jp z, UpdateSpriteInWalkingAnimation ; c1x1 == 3 + jp z, UpdateSpriteInWalkingAnimation ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] == 3 cp $4 jp z, Func_5357 ld a, [wWalkCounter] and a ret nz ; don't do anything yet if player is currently moving (redundant, already tested in CheckSpriteAvailability) call InitializeSpriteScreenPosition - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] add $6 ld l, a - ld a, [hl] ; c2x6: movement byte 1 + ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1 inc a - jp z, .randomMovement ; value $FF + jp z, .randomMovement ; value STAY inc a - jp z, .randomMovement ; value $FE + jp z, .randomMovement ; value WALK ; scripted movement dec a ld [hl], a ; increment movement byte 1 (movement data index) @@ -156,7 +156,7 @@ UpdateNPCSprite: pop hl ld de, wNPCMovementDirections call LoadDEPlusA ; a = [wNPCMovementDirections + movement byte 1] - cp $e0 + cp NPC_CHANGE_FACING jp z, ChangeFacingDirection cp STAY jr nz, .next @@ -171,7 +171,7 @@ UpdateNPCSprite: .next cp WALK jr nz, .asm_4ecb -; current NPC movement data is $fe. this seems buggy +; current NPC movement data is WALK ($fe). this seems buggy ld [hl], $1 ; set movement byte 1 to $1 ld de, wNPCMovementDirections call LoadDEPlusA ; a = [wNPCMovementDirections + $fe] (?) @@ -188,20 +188,20 @@ UpdateNPCSprite: .determineDirection ld b, a ld a, [wCurSpriteMovement2] - cp $d0 - jr z, .moveDown ; movement byte 2 = $d0 forces down - cp $d1 - jr z, .moveUp ; movement byte 2 = $d1 forces up - cp $d2 - jr z, .moveLeft ; movement byte 2 = $d2 forces left - cp $d3 - jr z, .moveRight ; movement byte 2 = $d3 forces right + cp DOWN + jr z, .moveDown + cp UP + jr z, .moveUp + cp LEFT + jr z, .moveLeft + cp RIGHT + jr z, .moveRight ld a, b - cp $40 ; a < $40: down (or left) + cp NPC_MOVEMENT_UP ; NPC_MOVEMENT_DOWN <= a < NPC_MOVEMENT_UP: down (or left) jr nc, .notDown ld a, [wCurSpriteMovement2] - cp $2 - jr z, .moveLeft ; movement byte 2 = $2 only allows left or right + cp LEFT_RIGHT + jr z, .moveLeft .moveDown ld de, 2*SCREEN_WIDTH add hl, de ; move tile pointer two rows down @@ -209,11 +209,11 @@ UpdateNPCSprite: lb bc, 4, SPRITE_FACING_DOWN jr TryWalking .notDown - cp $80 ; $40 <= a < $80: up (or right) + cp NPC_MOVEMENT_LEFT ; NPC_MOVEMENT_UP <= a < NPC_MOVEMENT_LEFT: up (or right) jr nc, .notUp ld a, [wCurSpriteMovement2] - cp $2 - jr z, .moveRight ; movement byte 2 = $2 only allows left or right + cp LEFT_RIGHT + jr z, .moveRight .moveUp ld de, -2*SCREEN_WIDTH add hl, de ; move tile pointer two rows up @@ -221,21 +221,21 @@ UpdateNPCSprite: lb bc, 8, SPRITE_FACING_UP jr TryWalking .notUp - cp $c0 ; $80 <= a < $c0: left (or up) + cp NPC_MOVEMENT_RIGHT ; NPC_MOVEMENT_LEFT <= a < NPC_MOVEMENT_RIGHT: left (or up) jr nc, .notLeft ld a, [wCurSpriteMovement2] - cp $1 - jr z, .moveUp ; movement byte 2 = $1 only allows up or down + cp UP_DOWN + jr z, .moveUp .moveLeft dec hl dec hl ; move tile pointer two columns left lb de, 0, -1 lb bc, 2, SPRITE_FACING_LEFT jr TryWalking -.notLeft ; $c0 <= a: right (or down) +.notLeft ; NPC_MOVEMENT_RIGHT <= a: right (or down) ld a, [wCurSpriteMovement2] - cp $1 - jr z, .moveDown ; movement byte 2 = $1 only allows up or down + cp UP_DOWN + jr z, .moveDown .moveRight inc hl inc hl ; move tile pointer two columns right @@ -262,103 +262,104 @@ TryWalking: ld c, [hl] call CanWalkOntoTile pop de - ret c + ret c ; cannot walk there (reinitialization of delay values already done) call Func_5349 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] ld l, a - ld [hl], $10 ; c1x9 (update facing direction) + ld [hl], $10 ; [x#SPRITESTATEDATA2_WALKANIMATIONCOUNTER] = 16 dec h inc l - ld [hl], $3 + ld [hl], $3 ; x#SPRITESTATEDATA1_MOVEMENTSTATUS jp UpdateSpriteImage ; update the walking animation parameters for a sprite that is currently walking UpdateSpriteInWalkingAnimation: call Func_5274 -.noNextAnimationFrame - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $3 ld l, a - ld a, [hli] ; c1x3 (movement Y delta) + ld a, [hli] ; x#SPRITESTATEDATA1_YSTEPVECTOR ld b, a - ld a, [hl] ; c1x4 (screen Y position) + ld a, [hl] ; x#SPRITESTATEDATA1_YPIXELS add b - ld [hli], a ; update screen Y position - ld a, [hli] ; c1x5 (movement X delta) + ld [hli], a ; update [x#SPRITESTATEDATA1_YPIXELS] + ld a, [hli] ; x#SPRITESTATEDATA1_XSTEPVECTOR ld b, a - ld a, [hl] ; c1x6 (screen X position) + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS add b - ld [hl], a ; update screen X position - ld a, [H_CURRENTSPRITEOFFSET] + ld [hl], a ; update [x#SPRITESTATEDATA1_XPIXELS] + ldh a, [hCurrentSpriteOffset] ld l, a inc h - ld a, [hl] ; c2x0 (walk animation counter) + ld a, [hl] ; x#SPRITESTATEDATA2_WALKANIMATIONCOUNTER dec a ld [hl], a ; update walk animation counter ret nz ld a, $6 ; walking finished, update state add l ld l, a - ld a, [hl] ; c2x6 (movement byte 1) - cp $fe - jr nc, .initNextMovementCounter ; values $fe and $ff - ld a, [H_CURRENTSPRITEOFFSET] + ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1 + cp WALK + jr nc, .initNextMovementCounter ; values WALK or STAY + ldh a, [hCurrentSpriteOffset] inc a ld l, a dec h - ld [hl], $1 ; c1x1 = 1 (movement status ready) + ld [hl], $1 ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] = 1 (movement status ready) ret .initNextMovementCounter call Random - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $8 ld l, a - ld a, [hRandomAdd] + ldh a, [hRandomAdd] and $7f - ld [hl], a ; c2x8: set next movement delay to a random value in [0,$7f] - dec h ; note that value 0 actually makes the delay $100 (bug?) - ld a, [H_CURRENTSPRITEOFFSET] + ld [hl], a ; x#SPRITESTATEDATA2_MOVEMENTDELAY: + ; set next movement delay to a random value in [0,$7f] + ; note that value 0 actually makes the delay $100 (bug?) + dec h ; HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] inc a ld l, a - ld [hl], $2 ; c1x1 = 2 (movement status) + ld [hl], $2 ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] = 2 (movement status) inc l inc l xor a - ld b, [hl] ; c1x3 (movement Y delta) - ld [hli], a ; reset movement Y delta + ld b, [hl] ; x#SPRITESTATEDATA1_YSTEPVECTOR + ld [hli], a ; [x#SPRITESTATEDATA1_YSTEPVECTOR] = 0 inc l - ld c, [hl] ; c1x5 (movement X delta) - ld [hl], a ; reset movement X delta + ld c, [hl] ; x#SPRITESTATEDATA1_XSTEPVECTOR + ld [hl], a ; [x#SPRITESTATEDATA1_XSTEPVECTOR] = 0 ret -; update delay value (c2x8) for sprites in the delayed state (c1x1) +; update [x#SPRITESTATEDATA2_MOVEMENTDELAY] for sprites in the delayed state (x#SPRITESTATEDATA1_MOVEMENTSTATUS) UpdateSpriteMovementDelay: - ld h, $c2 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] add $6 ld l, a - ld a, [hl] ; c2x6: movement byte 1 + ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1 inc l inc l - cp $fe - jr nc, .tickMoveCounter ; values $fe or $ff + cp WALK + jr nc, .tickMoveCounter ; values WALK or STAY ld [hl], $0 jr .moving .tickMoveCounter - dec [hl] ; c2x8: frame counter until next movement + dec [hl] ; x#SPRITESTATEDATA2_MOVEMENTDELAY jr nz, notYetMoving .moving dec h - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] inc a ld l, a - ld [hl], $1 ; c1x1 = 1 (mark as ready to move) + ld [hl], $1 ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] = 1 (mark as ready to move) notYetMoving: - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $8 + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA1_ANIMFRAMECOUNTER ld l, a - ld [hl], $0 ; c1x8 = 0 (walk animation frame) + ld [hl], $0 ; [x#SPRITESTATEDATA1_ANIMFRAMECOUNTER] = 0 (walk animation frame) jp UpdateSpriteImage MakeNPCFacePlayer: @@ -388,48 +389,48 @@ MakeNPCFacePlayer: .notFacingRight ld c, SPRITE_FACING_LEFT .facingDirectionDetermined - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $9 ld l, a - ld [hl], c ; c1x9: set facing direction + ld [hl], c ; [x#SPRITESTATEDATA1_FACINGDIRECTION]: set facing direction jr notYetMoving InitializeSpriteStatus: - ld [hl], $1 ; $c1x1: set movement status to ready + ld [hl], $1 ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] = ready inc l - ld [hl], $ff ; $c1x2: set sprite image to $ff (invisible/off screen) - inc h - ld a, [H_CURRENTSPRITEOFFSET] + ld [hl], $ff ; [x#SPRITESTATEDATA1_IMAGEINDEX] = invisible/off screen + inc h ; HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] add $2 ld l, a ld a, $8 - ld [hli], a ; $c2x2: set Y displacement to 8 - ld [hl], a ; $c2x3: set X displacement to 8 + ld [hli], a ; [x#SPRITESTATEDATA2_YDISPLACEMENT] = 8 + ld [hl], a ; [x#SPRITESTATEDATA2_XDISPLACEMENT] = 8 call InitializeSpriteScreenPosition ; could have done fallthrough here ret -; calculates the sprite's screen position form its map position and the player position +; calculates the sprite's screen position from its map position and the player position InitializeSpriteScreenPosition: - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $4 + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA2_MAPY ld l, a ld a, [wYCoord] ld b, a - ld a, [hl] ; c2x4 (Y position + 4) + ld a, [hl] ; x#SPRITESTATEDATA2_MAPY sub b ; relative to player position call Func_5033 sub $4 ; - 4 dec h - ld [hli], a ; c1x4 (screen Y position) + ld [hli], a ; [x#SPRITESTATEDATA1_YPIXELS] inc h ld a, [wXCoord] ld b, a - ld a, [hli] ; c2x6 (X position + 4) + ld a, [hli] ; x#SPRITESTATEDATA2_MAPX sub b ; relative to player position call Func_5033 dec h - ld [hl], a ; c1x6 (screen X position) + ld [hl], a ; [x#SPRITESTATEDATA1_XPIXELS] ret Func_5033: @@ -447,35 +448,35 @@ Func_5033: ; tests if sprite is off screen or otherwise unable to do anything CheckSpriteAvailability: predef IsObjectHidden - ld a, [$ffe5] + ldh a, [hIsHiddenMissableObject] and a jp nz, .spriteInvisible - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $6 + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA2_MOVEMENTBYTE1 ld l, a - ld a, [hl] ; c2x6: movement byte 1 - cp $fe - jr c, .skipXVisibilityTest ; movement byte 1 < $fe (i.e. the sprite's movement is scripted) - ld a, [H_CURRENTSPRITEOFFSET] - add $4 + ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1 + cp WALK + jr c, .skipXVisibilityTest ; movement byte 1 < WALK (i.e. the sprite's movement is scripted) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA2_MAPY ld l, a - ld b, [hl] ; c2x4: Y pos (+4) + ld b, [hl] ; x#SPRITESTATEDATA2_MAPY ld a, [wYCoord] cp b jr z, .skipYVisibilityTest jr nc, .spriteInvisible ; above screen region - add $8 ; screen is 9 tiles high + add SCREEN_HEIGHT / 2 - 1 cp b jr c, .spriteInvisible ; below screen region .skipYVisibilityTest inc l - ld b, [hl] ; c2x5: X pos (+4) + ld b, [hl] ; x#SPRITESTATEDATA2_MAPX ld a, [wXCoord] cp b jr z, .skipXVisibilityTest jr nc, .spriteInvisible ; left of screen region - add $9 ; screen is 10 tiles wide + add SCREEN_WIDTH / 2 - 1 cp b jr c, .spriteInvisible ; right of screen region .skipXVisibilityTest @@ -489,7 +490,7 @@ CheckSpriteAvailability: ld a, [hld] cp d jr nc, .spriteInvisible ; standing on tile with ID >=MAP_TILESET_SIZE (bottom right tile) - ld bc, -20 + ld bc, -SCREEN_WIDTH add hl, bc ; go back one row of tiles ld a, [hli] cp d @@ -498,11 +499,11 @@ CheckSpriteAvailability: cp d jr c, .spriteVisible ; standing on tile with ID >=MAP_TILESET_SIZE (top right tile) .spriteInvisible - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $2 + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA1_IMAGEINDEX ld l, a - ld [hl], $ff ; c1x2 + ld [hl], $ff ; x#SPRITESTATEDATA1_IMAGEINDEX scf jr .done .spriteVisible @@ -512,37 +513,37 @@ CheckSpriteAvailability: jr nz, .done ; if player is currently walking, we're done call UpdateSpriteImage inc h - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $7 ld l, a ld a, [wGrassTile] cp c - ld a, $0 + ld a, 0 jr nz, .notInGrass - ld a, $80 + ld a, OAM_BEHIND_BG .notInGrass - ld [hl], a ; c2x7 + ld [hl], a ; x#SPRITESTATEDATA2_GRASSPRIORITY and a .done ret UpdateSpriteImage: - ld h, $c1 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] add $8 ld l, a - ld a, [hli] ; c1x8: walk animation frame + ld a, [hli] ; x#SPRITESTATEDATA1_ANIMFRAMECOUNTER ld b, a - ld a, [hl] ; c1x9: facing direction + ld a, [hl] ; x#SPRITESTATEDATA1_FACINGDIRECTION add b ld b, a - ld a, [$ff93] ; current sprite offset + ldh a, [hTilePlayerStandingOn] add b ld b, a - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $2 ld l, a - ld [hl], b ; c1x2: sprite to display + ld [hl], b ; x#SPRITESTATEDATA1_IMAGEINDEX ret ; tests if sprite can walk the specified direction @@ -552,37 +553,37 @@ UpdateSpriteImage: ; e: X movement delta (-1, 0 or 1) ; set carry on failure, clears carry on success CanWalkOntoTile: - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $6 + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA2_MOVEMENTBYTE1 ld l, a - ld a, [hl] ; c2x6 (movement byte 1) - cp $fe - jr nc, .notScripted ; values $fe and $ff + ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1 + cp WALK + jr nc, .notScripted ; values WALK or STAY ; always allow walking if the movement is scripted and a ret .notScripted call _IsTilePassable jr c, .impassable - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] add $6 ld l, a - ld a, [hl] ; $c2x6 (movement byte 1) + ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1 inc a jr z, .impassable ; if $ff, no movement allowed (however, changing direction is) - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $4 + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA1_YPIXELS ld l, a - ld a, [hli] ; c1x4 (screen Y pos) + ld a, [hli] ; x#SPRITESTATEDATA1_YPIXELS add $4 ; align to blocks (Y pos is always 4 pixels off) add d ; add Y delta cp $80 ; if value is >$80, the destination is off screen (either $81 or $FF underflow) jr nc, .impassable ; don't walk off screen inc l - ld a, [hl] ; c1x6 (screen X pos) + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS add e ; add X delta cp $90 ; if value is >$90, the destination is off screen (either $91 or $FF underflow) jr nc, .impassable ; don't walk off screen @@ -597,30 +598,36 @@ CanWalkOntoTile: ld [wUpdateSpritesEnabled], a pop bc pop de - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] add $c ld l, a - ld a, [hl] ; c1xc (directions in which sprite collision would occur) + ld a, [hl] ; x#SPRITESTATEDATA1_COLLISIONDATA (directions in which sprite collision would occur) and b ; check against chosen direction (1,2,4 or 8) jr nz, .impassable ; collision between sprites, don't go there - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $2 + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA2_YDISPLACEMENT ld l, a - ld a, [hli] ; c2x2 (sprite Y displacement, initialized at $8, keep track of where a sprite did go) + ld a, [hli] ; x#SPRITESTATEDATA2_YDISPLACEMENT (initialized at $8, keep track of where a sprite did go) bit 7, d ; check if going upwards (d=$ff) jr nz, .upwards add d + ; bug: these tests against $5 probably were supposed to prevent + ; sprites from walking out too far, but this line makes sprites get + ; stuck whenever they walked upwards 5 steps + ; on the other hand, the amount a sprite can walk out to the + ; right of bottom is not limited (until the counter overflows) + ; this was fixed in Yellow cp $5 - ;jr c, .impassable (bugfix) ; if c2x2+d < 5, don't go ;bug: this tests probably were supposed to prevent sprites - jr .checkHorizontal ; from walking out too far, but this line makes sprites get stuck -.upwards ; whenever they walked upwards 5 steps - sub $1 ; on the other hand, the amount a sprite can walk out to the - jr c, .impassable ; if d2x2 == 0, don't go ; right of bottom is not limited (until the counter overflows) + ;jr c, .impassable ; if [x#SPRITESTATEDATA2_YDISPLACEMENT]+d < 5, don't go + jr .checkHorizontal +.upwards + sub $1 + jr c, .impassable ; if [x#SPRITESTATEDATA2_YDISPLACEMENT] == 0, don't go .checkHorizontal ld d, a - ld a, [hl] ; c2x3 (sprite X displacement, initialized at $8, keep track of where a sprite did go) + ld a, [hl] ; x#SPRITESTATEDATA2_XDISPLACEMENT (initialized at $8, keep track of where a sprite did go) bit 7, e ; check if going left (e=$ff) jr nz, .left add e @@ -628,32 +635,32 @@ CanWalkOntoTile: jr .passable .left sub $1 - jr c, .impassable ; if d2x3 == 0, don't go + jr c, .impassable ; if [x#SPRITESTATEDATA2_XDISPLACEMENT] == 0, don't go .passable - ld [hld], a ; update c2x3 - ld [hl], d ; update c2x2 + ld [hld], a ; update x#SPRITESTATEDATA2_XDISPLACEMENT + ld [hl], d ; update x#SPRITESTATEDATA2_YDISPLACEMENT and a ; clear carry (marking success) ret .impassable - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] inc a ld l, a - ld [hl], $2 ; c1x1 = 2 (set movement status to delayed) + ld [hl], $2 ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] = 2 (delayed) inc l inc l xor a - ld [hli], a ; c1x3 = 0 (clear Y movement delta) + ld [hli], a ; [x#SPRITESTATEDATA1_YSTEPVECTOR] = 0 inc l - ld [hl], a ; c1x5 = 0 (clear X movement delta) + ld [hl], a ; [x#SPRITESTATEDATA1_XSTEPVECTOR] = 0 inc h - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $8 ld l, a call Random - ld a, [hRandomAdd] + ldh a, [hRandomAdd] and $7f - ld [hl], a ; c2x8: set next movement delay to a random value in [0,$7f] (again with delay $100 if value is 0) + ld [hl], a ; x#SPRITESTATEDATA2_MOVEMENTDELAY: set to a random value in [0,$7f] (again with delay $100 if value is 0) scf ; set carry (marking failure to walk) ret @@ -661,25 +668,25 @@ CanWalkOntoTile: ; this is always the lower left tile of the 2x2 tile blocks all sprites are snapped to ; hl: output pointer GetTileSpriteStandsOn: - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $4 + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA1_YPIXELS ld l, a - ld a, [hli] ; c1x4: screen Y position + ld a, [hli] ; x#SPRITESTATEDATA1_YPIXELS add $4 ; align to 2*2 tile blocks (Y position is always off 4 pixels to the top) and $f8 ; in case object is currently moving (XXX why changed to $f8?) srl a ; screen Y tile * 4 ld c, a ld b, $0 inc l - ld a, [hl] ; c1x6: screen X position + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS srl a srl a srl a ; screen X tile add SCREEN_WIDTH ; screen X tile + 20 ld d, $0 ld e, a - coord hl, 0, 0 + hlcoord 0, 0 add hl, bc add hl, bc add hl, bc @@ -754,7 +761,7 @@ DoScriptedNPCMovement: ld a, [hl] add b ld [hl], a - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $9 ld l, a ld a, c @@ -777,17 +784,17 @@ InitScriptedNPCMovement: jp AnimScriptedNPCMovement GetSpriteScreenYPointer: - ld a, $4 + ld a, SPRITESTATEDATA1_YPIXELS ld b, a jr GetSpriteScreenXYPointerCommon GetSpriteScreenXPointer: - ld a, $6 + ld a, SPRITESTATEDATA1_XPIXELS ld b, a GetSpriteScreenXYPointerCommon: ld hl, wSpriteStateData1 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add l add b ld l, a @@ -795,16 +802,16 @@ GetSpriteScreenXYPointerCommon: AnimScriptedNPCMovement: ld hl, wSpriteStateData2 - ld a, [H_CURRENTSPRITEOFFSET] - add $e + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA2_IMAGEBASEOFFSET ld l, a ld a, [hl] ; VRAM slot dec a swap a ld b, a ld hl, wSpriteStateData1 - ld a, [H_CURRENTSPRITEOFFSET] - add $9 + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA1_FACINGDIRECTION ld l, a ld a, [hl] ; facing direction cp SPRITE_FACING_DOWN @@ -819,42 +826,42 @@ AnimScriptedNPCMovement: .anim add b ld b, a - ld [hSpriteVRAMSlotAndFacing], a + ldh [hSpriteVRAMSlotAndFacing], a call AdvanceScriptedNPCAnimFrameCounter ld hl, wSpriteStateData1 - ld a, [H_CURRENTSPRITEOFFSET] - add $2 + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA1_IMAGEINDEX ld l, a - ld a, [hSpriteVRAMSlotAndFacing] + ldh a, [hSpriteVRAMSlotAndFacing] ld b, a - ld a, [hSpriteAnimFrameCounter] + ldh a, [hSpriteAnimFrameCounter] add b ld [hl], a ret AdvanceScriptedNPCAnimFrameCounter: call Func_5274 - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] add $8 ld l, a ld a, [hl] ; intra-animation frame counter and $3 - ld [hSpriteAnimFrameCounter], a + ldh [hSpriteAnimFrameCounter], a ret Func_5274: - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $7 ld l, a - ld h, wSpriteStateData1 / $100 - ld a, [hl] ; c1x7 (counter until next walk animation frame) + ld h, HIGH(wSpriteStateData1) + ld a, [hl] ; x#SPRITESTATEDATA1_INTRAANIMFRAMECOUNTER inc a and $3 - ld [hl], a ; c1x7 += 1 - ret nz ; c1x7 = 0 + ld [hl], a ; [x#SPRITESTATEDATA1_INTRAANIMFRAMECOUNTER]++ + ret nz inc l - ld a, [hl] ; c1x8 (walk animation frame) + ld a, [hl] ; x#SPRITESTATEDATA1_ANIMFRAMECOUNTER inc a and $3 ld [hl], a ; advance to next animation frame every 4 ticks (16 ticks total for one step) @@ -924,7 +931,7 @@ Func_5288: .asm_52e6 call Func_5337 call Func_5349 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] ld l, a ld [hl], $8 dec h @@ -936,7 +943,7 @@ Func_5288: .asm_52fa call Func_5337 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] ld l, a ld [hl], $8 dec h @@ -949,7 +956,7 @@ Func_5288: .asm_530b call Func_5337 call Func_5349 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] ld l, a ld [hl], $8 dec h @@ -980,39 +987,39 @@ Func_5331: ret Func_5337: - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $9 ld l, a - ld h, wSpriteStateData1 / $100 - ld [hl], c ; c1x9 (update facing direction) - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ld [hl], c ; x#SPRITESTATEDATA1_FACINGDIRECTION + ldh a, [hCurrentSpriteOffset] add $3 ld l, a - ld [hl], d ; c1x3 (update Y movement delta) + ld [hl], d ; x#SPRITESTATEDATA1_YSTEPVECTOR inc l inc l - ld [hl], e ; c1x5 (update X movement delta) + ld [hl], e ; x#SPRITESTATEDATA1_XSTEPVECTOR ret Func_5349: - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] add $4 ld l, a - ld a, [hl] ; c2x4: Y position + ld a, [hl] ; x#SPRITESTATEDATA2_MAPY add d ld [hli], a ; update Y position - ld a, [hl] ; c2x5: X position + ld a, [hl] ; x#SPRITESTATEDATA2_MAPX add e ld [hl], a ; update X position ret Func_5357: call Func_5274 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $3 ld l, a - ld h, wSpriteStateData1 / $100 + ld h, HIGH(wSpriteStateData1) ld a, [hli] add a ld b, a @@ -1025,9 +1032,9 @@ Func_5357: ld a, [hl] add b ld [hl], a - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] ld l, a - ld h, wSpriteStateData2 / $100 + ld h, HIGH(wSpriteStateData2) dec [hl] ret nz ld a, $6 @@ -1036,23 +1043,23 @@ Func_5357: ld a, [hl] cp $fe jr nc, .asm_5386 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] inc a ld l, a - ld h, wSpriteStateData1 / $100 + ld h, HIGH(wSpriteStateData1) ld [hl], $1 ret .asm_5386 call Random - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $8 ld l, a - ld h, wSpriteStateData2 / $100 - ld a, [hRandomAdd] + ld h, HIGH(wSpriteStateData2) + ldh a, [hRandomAdd] and $7f ld [hl], a dec h - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] inc a ld l, a ld [hl], $2 diff --git a/engine/overworld/npc_movement.asm b/engine/overworld/npc_movement.asm deleted file mode 100755 index 670cb121..00000000 --- a/engine/overworld/npc_movement.asm +++ /dev/null @@ -1,270 +0,0 @@ -PlayerStepOutFromDoor: - ld hl, wd730 - res 1, [hl] - call IsPlayerStandingOnDoorTile - jr nc, .notStandingOnDoor - ld a, $fc - ld [wJoyIgnore], a - ld hl, wd736 - set 1, [hl] - ld a, $1 - ld [wSimulatedJoypadStatesIndex], a - ld a, D_DOWN - ld [wSimulatedJoypadStatesEnd], a - xor a - ld [wSpriteStateData1 + 2], a - call StartSimulatingJoypadStates - ret -.notStandingOnDoor - xor a - ld [wWastedByteCD3A], a - ld [wSimulatedJoypadStatesIndex], a - ld [wSimulatedJoypadStatesEnd], a - ld hl, wd736 - res 0, [hl] - res 1, [hl] - ld hl, wd730 - res 7, [hl] - ret - -_EndNPCMovementScript: - ld hl, wd730 - res 7, [hl] - ld hl, wd72e - res 7, [hl] - ld hl, wd736 - res 0, [hl] - res 1, [hl] - xor a - ld [wNPCMovementScriptSpriteOffset], a - ld [wNPCMovementScriptFunctionNum], a - ld [wNPCMovementScriptPointerTableNum], a - ld [wWastedByteCD3A], a - ld [wSimulatedJoypadStatesIndex], a - ld [wSimulatedJoypadStatesEnd], a - ret - -PalletMovementScriptPointerTable: - dw PalletMovementScript_OakMoveLeft - dw PalletMovementScript_PlayerMoveLeft - dw PalletMovementScript_WaitAndWalkToLab - dw PalletMovementScript_WalkToLab - dw PalletMovementScript_Done - -PalletMovementScript_OakMoveLeft: - ld a, [wXCoord] - sub $a - ld [wNumStepsToTake], a - jr z, .playerOnLeftTile -; The player is on the right tile of the northern path out of Pallet Town and -; Prof. Oak is below. -; Make Prof. Oak step to the left. - ld b, 0 - ld c, a - ld hl, wNPCMovementDirections2 - ld a, NPC_MOVEMENT_LEFT - call FillMemory - ld [hl], $ff - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - ld de, wNPCMovementDirections2 - call MoveSprite - ld a, $1 - ld [wNPCMovementScriptFunctionNum], a - jr .done -; The player is on the left tile of the northern path out of Pallet Town and -; Prof. Oak is below. -; Prof. Oak is already where he needs to be. -.playerOnLeftTile - ld a, $3 - ld [wNPCMovementScriptFunctionNum], a -.done - ld a, BANK(Music_MuseumGuy) - ld c, a - ld a, MUSIC_MUSEUM_GUY - call PlayMusic - ld hl, wFlags_D733 - set 1, [hl] - ld a, $fc - ld [wJoyIgnore], a - ret - -PalletMovementScript_PlayerMoveLeft: - ld a, [wd730] - bit 0, a ; is an NPC being moved by a script? - ret nz ; return if Oak is still moving - ld a, [wNumStepsToTake] - ld [wSimulatedJoypadStatesIndex], a - ld [hNPCMovementDirections2Index], a - predef ConvertNPCMovementDirectionsToJoypadMasks - call StartSimulatingJoypadStates - ld a, $2 - ld [wNPCMovementScriptFunctionNum], a - ret - -PalletMovementScript_WaitAndWalkToLab: - ld a, [wSimulatedJoypadStatesIndex] - and a ; is the player done moving left yet? - ret nz - -PalletMovementScript_WalkToLab: - xor a - ld [wOverrideSimulatedJoypadStatesMask], a - ld a, [wSpriteIndex] - swap a - ld [wNPCMovementScriptSpriteOffset], a - xor a - ld [wSpriteStateData2 + $06], a - ld hl, wSimulatedJoypadStatesEnd - ld de, RLEList_PlayerWalkToLab - call DecodeRLEList - dec a - ld [wSimulatedJoypadStatesIndex], a - ld hl, wNPCMovementDirections2 - ld de, RLEList_ProfOakWalkToLab - call DecodeRLEList - ld hl, wd72e - res 7, [hl] - ld hl, wd730 - set 7, [hl] - ld a, $4 - ld [wNPCMovementScriptFunctionNum], a - ret - - -RLEList_ProfOakWalkToLab: - db NPC_MOVEMENT_DOWN, $06 ; differs from red - db NPC_MOVEMENT_LEFT, $01 - db NPC_MOVEMENT_DOWN, $05 - db NPC_MOVEMENT_RIGHT, $03 - db NPC_MOVEMENT_UP, $01 - db $E0, $01 ; stand still - db $FF - -RLEList_PlayerWalkToLab: - db D_UP, $02 - db D_RIGHT, $03 - db D_DOWN, $05 - db D_LEFT, $01 - db D_DOWN, $07 ; differs from red - db $FF - -PalletMovementScript_Done: - ld a, [wSimulatedJoypadStatesIndex] - and a - ret nz - ld a, HS_PALLET_TOWN_OAK - ld [wMissableObjectIndex], a - predef HideObject - ld hl, wd730 - res 7, [hl] - ld hl, wd72e - res 7, [hl] - jp EndNPCMovementScript - -PewterMuseumGuyMovementScriptPointerTable: - dw PewterMovementScript_WalkToMuseum - dw PewterMovementScript_Done - -PewterMovementScript_WalkToMuseum: - ld a, BANK(Music_MuseumGuy) - ld c, a - ld a, MUSIC_MUSEUM_GUY - call PlayMusic - ld a, [wSpriteIndex] - swap a - ld [wNPCMovementScriptSpriteOffset], a - call StartSimulatingJoypadStates - ld hl, wSimulatedJoypadStatesEnd - ld de, RLEList_PewterMuseumPlayer - call DecodeRLEList - dec a - ld [wSimulatedJoypadStatesIndex], a - xor a - ld [wWhichPewterGuy], a - call PewterGuys - ld hl, wNPCMovementDirections2 - ld de, RLEList_PewterMuseumGuy - call DecodeRLEList - ld hl, wd72e - res 7, [hl] - ld a, $1 - ld [wNPCMovementScriptFunctionNum], a - ret - -RLEList_PewterMuseumPlayer: - db 0, $01 - db D_UP, $03 - db D_LEFT, $0D - db D_UP, $06 - db $FF - -RLEList_PewterMuseumGuy: - db NPC_MOVEMENT_UP, $06 - db NPC_MOVEMENT_LEFT, $0D - db NPC_MOVEMENT_UP, $03 - db NPC_MOVEMENT_LEFT, $01 - db $FF - -PewterMovementScript_Done: - ld a, [wSimulatedJoypadStatesIndex] - and a - ret nz - ld hl, wd730 - res 7, [hl] - ld hl, wd72e - res 7, [hl] - jp EndNPCMovementScript - -PewterGymGuyMovementScriptPointerTable: - dw PewterMovementScript_WalkToGym - dw PewterMovementScript_Done - -PewterMovementScript_WalkToGym: - ld a, BANK(Music_MuseumGuy) - ld c, a - ld a, MUSIC_MUSEUM_GUY - call PlayMusic - ld a, [wSpriteIndex] - swap a - ld [wNPCMovementScriptSpriteOffset], a - xor a - ld [wSpriteStateData2 + $06], a - ld hl, wSimulatedJoypadStatesEnd - ld de, RLEList_PewterGymPlayer - call DecodeRLEList - dec a - ld [wSimulatedJoypadStatesIndex], a - ld a, 1 - ld [wWhichPewterGuy], a - call PewterGuys - ld hl, wNPCMovementDirections2 - ld de, RLEList_PewterGymGuy - call DecodeRLEList - ld hl, wd72e - res 7, [hl] - ld hl, wd730 - set 7, [hl] - ld a, $1 - ld [wNPCMovementScriptFunctionNum], a - ret - -RLEList_PewterGymPlayer: - db 0, $01 - db D_RIGHT, $02 - db D_DOWN, $05 - db D_LEFT, $0B - db D_UP, $05 - db D_LEFT, $0F - db $FF - -RLEList_PewterGymGuy: - db NPC_MOVEMENT_DOWN, $02 - db NPC_MOVEMENT_LEFT, $0F - db NPC_MOVEMENT_UP, $05 - db NPC_MOVEMENT_LEFT, $0B - db NPC_MOVEMENT_DOWN, $05 - db NPC_MOVEMENT_RIGHT, $03 - db $FF - -INCLUDE "engine/overworld/pewter_guys.asm" diff --git a/engine/overworld/npc_movement_2.asm b/engine/overworld/npc_movement_2.asm index 93d1afce..2ced9da6 100755 --- a/engine/overworld/npc_movement_2.asm +++ b/engine/overworld/npc_movement_2.asm @@ -1,4 +1,4 @@ -FreezeEnemyTrainerSprite: +FreezeEnemyTrainerSprite:: ld a, [wCurMap] cp POKEMON_TOWER_7F ret z ; the Rockets on Pokemon Tower 7F leave after battling, so don't freeze them @@ -7,18 +7,18 @@ FreezeEnemyTrainerSprite: ld b, a .loop ld a, [hli] - cp $ff + cp -1 jr z, .notRival cp b ret z ; the rival leaves after battling, so don't freeze him jr .loop .notRival ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a + ldh [hSpriteIndex], a jp SetSpriteMovementBytesToFF RivalIDs: - db OPP_SONY1 - db OPP_SONY2 - db OPP_SONY3 - db $ff + db OPP_RIVAL1 + db OPP_RIVAL2 + db OPP_RIVAL3 + db -1 ; end diff --git a/engine/overworld/oaks_aide.asm b/engine/overworld/oaks_aide.asm deleted file mode 100755 index f5068fda..00000000 --- a/engine/overworld/oaks_aide.asm +++ /dev/null @@ -1,71 +0,0 @@ -OaksAideScript: - ld hl, OaksAideHiText - call PrintText - call YesNoChoice - ld a, [wCurrentMenuItem] - and a - jr nz, .choseNo - ld hl, wPokedexOwned - ld b, wPokedexOwnedEnd - wPokedexOwned - call CountSetBits - ld a, [wNumSetBits] - ld [hOaksAideNumMonsOwned], a - ld b, a - ld a, [hOaksAideRequirement] - cp b - jr z, .giveItem - jr nc, .notEnoughOwnedMons -.giveItem - ld hl, OaksAideHereYouGoText - call PrintText - ld a, [hOaksAideRewardItem] - ld b, a - ld c, 1 - call GiveItem - jr nc, .bagFull - ld hl, OaksAideGotItemText - call PrintText - ld a, $1 - jr .done -.bagFull - ld hl, OaksAideNoRoomText - call PrintText - xor a - jr .done -.notEnoughOwnedMons - ld hl, OaksAideUhOhText - call PrintText - ld a, $80 - jr .done -.choseNo - ld hl, OaksAideComeBackText - call PrintText - ld a, $ff -.done - ld [hOaksAideResult], a - ret - -OaksAideHiText: - TX_FAR _OaksAideHiText - db "@" - -OaksAideUhOhText: - TX_FAR _OaksAideUhOhText - db "@" - -OaksAideComeBackText: - TX_FAR _OaksAideComeBackText - db "@" - -OaksAideHereYouGoText: - TX_FAR _OaksAideHereYouGoText - db "@" - -OaksAideGotItemText: - TX_FAR _OaksAideGotItemText - TX_SFX_ITEM_1 - db "@" - -OaksAideNoRoomText: - TX_FAR _OaksAideNoRoomText - db "@" diff --git a/engine/overworld/oam.asm b/engine/overworld/oam.asm deleted file mode 100644 index 5a831327..00000000 --- a/engine/overworld/oam.asm +++ /dev/null @@ -1,232 +0,0 @@ -PrepareOAMData: -; Determine OAM data for currently visible -; sprites and write it to wOAMBuffer. -; Yellow code has been changed to use registers more efficiently -; as well as tweaking the code to show gbc palettes - - ld a, [wUpdateSpritesEnabled] - dec a - jr z, .updateEnabled - - cp -1 - ret nz - ld [wUpdateSpritesEnabled], a - jp HideSprites - -.updateEnabled - xor a - ld [hOAMBufferOffset], a - -.spriteLoop - ld [hSpriteOffset2], a - - ld e, a - ld d, wSpriteStateData1 / $100 - - ld a, [de] ; c1x0 - and a - jp z, .nextSprite - - inc e - inc e - ld a, [de] ; c1x2 (facing/anim) - ld [wd5cd], a - cp $ff ; off-screen (don't draw) - jr nz, .visible - - call GetSpriteScreenXY - jr .nextSprite - -.visible - cp $a0 ; is the sprite unchanging like an item ball or boulder? - jr c, .usefacing - -; unchanging - ld a, $0 - jr .next - -.usefacing - and $f - -.next -; read the entry from the table - ld c, a - ld b, 0 - ld hl, SpriteFacingAndAnimationTable - add hl, bc - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a -; get sprite priority - push de - inc d - ld a, e - add $5 - ld e, a - ld a, [de] ; c2x7 - and $80 - ld [hSpritePriority], a ; temp store sprite priority - pop de - - - call GetSpriteScreenXY - - ld a, [hOAMBufferOffset] - add [hl] - cp $a0 - jr z, .hidden - jr nc, .asm_4a41 -.hidden - call Func_4a7b - ld [wd5cd], a - ld a, [hOAMBufferOffset] - - ld e, a - ld d, wOAMBuffer / $100 - -.tileLoop - ld a, [hli] - ld c, a -.loop - ld a, [hSpriteScreenY] ; temp for sprite Y position - add $10 ; Y=16 is top of screen (Y=0 is invisible) - add [hl] ; add Y offset from table - ld [de], a ; write new sprite OAM Y position - inc hl - inc e - ld a, [hSpriteScreenX] ; temp for sprite X position - add $8 ; X=8 is left of screen (X=0 is invisible) - add [hl] ; add X offset from table - ld [de], a - inc hl - inc e - ld a, [wd5cd] - add [hl] - cp $80 - jr c, .asm_4a1c - ld b, a - ld a, [$fffc] - add b -.asm_4a1c - ld [de], a ; tile id - inc hl - inc e - ld a, [hl] - bit 1, a ; is the tile allowed to set the sprite priority bit? - jr z, .skipPriority - ld a, [hSpritePriority] - or [hl] -.skipPriority - and $f0 - bit 4, a ; OBP0 or OBP1 - jr z, .spriteusesOBP0 - or %100 ; palettes 4-7 are OBP1 -.spriteusesOBP0 - ld [de], a - inc hl - inc e - dec c - jr nz, .loop - - ld a, e - ld [hOAMBufferOffset], a -.nextSprite - ld a, [hSpriteOffset2] - add $10 - cp $100 % $100 - jp nz, .spriteLoop - - ; Clear unused OAM. -.asm_4a41 - ld a, [wd736] - bit 6, a ; jumping down ledge or fishing animation? - ld c, $a0 - jr z, .clear - -; Don't clear the last 4 entries because they are used for the shadow in the -; jumping down ledge animation and the rod in the fishing animation. - ld c, $90 - -.clear - ld a, [hOAMBufferOffset] - cp c - ret nc - ld l, a - ld h, wOAMBuffer / $100 - ld a, c - ld de, $4 ; entry size - ld b, $a0 -.clearLoop - ld [hl], b - add hl, de - cp l - jr nz, .clearLoop - ret - -GetSpriteScreenXY: - inc e - inc e - ld a, [de] ; c1x4 - ld [hSpriteScreenY], a - inc e - inc e - ld a, [de] ; c1x6 - ld [hSpriteScreenX], a - ld a, 4 - add e - ld e, a - ld a, [hSpriteScreenY] - add 4 - and $f0 - ld [de], a ; c1xa (y) - inc e - ld a, [hSpriteScreenX] - and $f0 - ld [de], a ; c1xb (x) - ret - -Func_4a7b: - push bc - ld a, [wd5cd] ; temp copy of c1x2 - swap a ; high nybble determines sprite used (0 is always player sprite, next are some npcs) - and $f - - ; Sprites $a and $b have one face (and therefore 4 tiles instead of 12). - ; As a result, sprite $b's tile offset is less than normal. - cp $b - jr nz, .notFourTileSprite - ld a, $a * 12 + 4 ; $7c - jr .done - -.notFourTileSprite - ; a *= 12 - add a - add a - ld c, a - add a - add c -.done - pop bc - ret - -INCLUDE "engine/oam_dma.asm" - -_IsTilePassable:: - ld hl,wTilesetCollisionPtr ; pointer to list of passable tiles - ld a,[hli] - ld h,[hl] - ld l,a ; hl now points to passable tiles -.loop - ld a,[hli] - cp a,$ff - jr z,.tileNotPassable - cp c - jr nz,.loop - xor a - ret -.tileNotPassable - scf - ret - -INCLUDE "data/collision.asm" ; probably diff --git a/engine/overworld/pathfinding.asm b/engine/overworld/pathfinding.asm new file mode 100644 index 00000000..a824d337 --- /dev/null +++ b/engine/overworld/pathfinding.asm @@ -0,0 +1,201 @@ +FindPathToPlayer: + xor a + ld hl, hFindPathNumSteps + ld [hli], a ; hFindPathNumSteps + ld [hli], a ; hFindPathFlags + ld [hli], a ; hFindPathYProgress + ld [hl], a ; hFindPathXProgress + ld hl, wNPCMovementDirections2 + ld de, $0 +.loop + ldh a, [hFindPathYProgress] + ld b, a + ldh a, [hNPCPlayerYDistance] ; Y distance in steps + call CalcDifference + ld d, a + and a + jr nz, .asm_f76a + ldh a, [hFindPathFlags] + set 0, a ; current end of path matches the player's Y coordinate + ldh [hFindPathFlags], a +.asm_f76a + ldh a, [hFindPathXProgress] + ld b, a + ldh a, [hNPCPlayerXDistance] ; X distance in steps + call CalcDifference + ld e, a + and a + jr nz, .asm_f77c + ldh a, [hFindPathFlags] + set 1, a ; current end of path matches the player's X coordinate + ldh [hFindPathFlags], a +.asm_f77c + ldh a, [hFindPathFlags] + cp $3 ; has the end of the path reached the player's position? + jr z, .done +; Compare whether the X distance between the player and the current of the path +; is greater or if the Y distance is. Then, try to reduce whichever is greater. + ld a, e + cp d + jr c, .yDistanceGreater +; x distance is greater + ldh a, [hNPCPlayerRelativePosFlags] + bit 1, a + jr nz, .playerIsLeftOfNPC + ld d, NPC_MOVEMENT_RIGHT + jr .next1 +.playerIsLeftOfNPC + ld d, NPC_MOVEMENT_LEFT +.next1 + ldh a, [hFindPathXProgress] + add 1 + ldh [hFindPathXProgress], a + jr .storeDirection +.yDistanceGreater + ldh a, [hNPCPlayerRelativePosFlags] + bit 0, a + jr nz, .playerIsAboveNPC + ld d, NPC_MOVEMENT_DOWN + jr .next2 +.playerIsAboveNPC + ld d, NPC_MOVEMENT_UP +.next2 + ldh a, [hFindPathYProgress] + add 1 + ldh [hFindPathYProgress], a +.storeDirection + ld a, d + ld [hli], a + ldh a, [hFindPathNumSteps] + inc a + ldh [hFindPathNumSteps], a + jp .loop +.done + ld [hl], $ff + ret + +CalcPositionOfPlayerRelativeToNPC: + xor a + ldh [hNPCPlayerRelativePosFlags], a + ld a, [wSpritePlayerStateData1YPixels] + ld d, a + ld a, [wSpritePlayerStateData1XPixels] + ld e, a + ld hl, wSpriteStateData1 + ldh a, [hNPCSpriteOffset] + add l + add SPRITESTATEDATA1_YPIXELS + ld l, a + jr nc, .noCarry + inc h +.noCarry + ld a, d + ld b, a + ld a, [hli] ; NPC sprite screen Y position in pixels + call CalcDifference + jr nc, .NPCSouthOfOrAlignedWithPlayer +.NPCNorthOfPlayer + push hl + ld hl, hNPCPlayerRelativePosFlags + bit 0, [hl] + set 0, [hl] + pop hl + jr .divideYDistance +.NPCSouthOfOrAlignedWithPlayer + push hl + ld hl, hNPCPlayerRelativePosFlags + bit 0, [hl] + res 0, [hl] + pop hl +.divideYDistance + push hl + ld hl, hDividend2 + ld [hli], a + ld a, 16 + ld [hli], a + call DivideBytes ; divide Y absolute distance by 16 + ld a, [hl] ; quotient + ldh [hNPCPlayerYDistance], a + pop hl + inc hl + ld b, e + ld a, [hl] ; NPC sprite screen X position in pixels + call CalcDifference + jr nc, .NPCEastOfOrAlignedWithPlayer +.NPCWestOfPlayer + push hl + ld hl, hNPCPlayerRelativePosFlags + bit 1, [hl] + set 1, [hl] + pop hl + jr .divideXDistance +.NPCEastOfOrAlignedWithPlayer + push hl + ld hl, hNPCPlayerRelativePosFlags + bit 1, [hl] + res 1, [hl] + pop hl +.divideXDistance + ldh [hDividend2], a + ld a, 16 + ldh [hDivisor2], a + call DivideBytes ; divide X absolute distance by 16 + ldh a, [hQuotient2] + ldh [hNPCPlayerXDistance], a + ldh a, [hNPCPlayerRelativePosPerspective] + and a + ret z + ldh a, [hNPCPlayerRelativePosFlags] + cpl + and $3 + ldh [hNPCPlayerRelativePosFlags], a + ret + +ConvertNPCMovementDirectionsToJoypadMasks: + ldh a, [hNPCMovementDirections2Index] + ld [wNPCMovementDirections2Index], a + dec a + ld de, wSimulatedJoypadStatesEnd + ld hl, wNPCMovementDirections2 + add l + ld l, a + jr nc, .loop + inc h +.loop + ld a, [hld] + call ConvertNPCMovementDirectionToJoypadMask + ld [de], a + inc de + ldh a, [hNPCMovementDirections2Index] + dec a + ldh [hNPCMovementDirections2Index], a + jr nz, .loop + ret + +ConvertNPCMovementDirectionToJoypadMask: + push hl + ld b, a + ld hl, NPCMovementDirectionsToJoypadMasksTable +.loop + ld a, [hli] + cp $ff + jr z, .done + cp b + jr z, .loadJoypadMask + inc hl + jr .loop +.loadJoypadMask + ld a, [hl] +.done + pop hl + ret + +NPCMovementDirectionsToJoypadMasksTable: + db NPC_MOVEMENT_UP, D_UP + db NPC_MOVEMENT_DOWN, D_DOWN + db NPC_MOVEMENT_LEFT, D_LEFT + db NPC_MOVEMENT_RIGHT, D_RIGHT + db $ff + +; unreferenced + ret diff --git a/engine/overworld/pewter_guys.asm b/engine/overworld/pewter_guys.asm deleted file mode 100755 index 532fa4bf..00000000 --- a/engine/overworld/pewter_guys.asm +++ /dev/null @@ -1,102 +0,0 @@ -PewterGuys: - ld hl, wSimulatedJoypadStatesEnd - ld a, [wSimulatedJoypadStatesIndex] - dec a ; this decrement causes it to overwrite the last byte before $FF in the list - ld [wSimulatedJoypadStatesIndex], a - ld d, 0 - ld e, a - add hl, de - ld d, h - ld e, l - ld hl, PointerTable_37ce6 - ld a, [wWhichPewterGuy] - add a - ld b, 0 - ld c, a - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - ld a, [wYCoord] - ld b, a - ld a, [wXCoord] - ld c, a -.findMatchingCoordsLoop - ld a, [hli] - cp b - jr nz, .nextEntry1 - ld a, [hli] - cp c - jr nz, .nextEntry2 - ld a, [hli] - ld h, [hl] - ld l, a -.copyMovementDataLoop - ld a, [hli] - cp $ff - ret z - ld [de], a - inc de - ld a, [wSimulatedJoypadStatesIndex] - inc a - ld [wSimulatedJoypadStatesIndex], a - jr .copyMovementDataLoop -.nextEntry1 - inc hl -.nextEntry2 - inc hl - inc hl - jr .findMatchingCoordsLoop - -PointerTable_37ce6: - dw PewterMuseumGuyCoords - dw PewterGymGuyCoords - -; these are the four coordinates of the spaces below, above, to the left and -; to the right of the museum guy, and pointers to different movements for -; the player to make to get positioned before the main movement. -PewterMuseumGuyCoords: - db 18, 27 - dw .down - db 16, 27 - dw .up - db 17, 26 - dw .left - db 17, 28 - dw .right - -.down - db D_UP, D_UP, $ff -.up - db D_RIGHT, D_LEFT, $ff -.left - db D_UP, D_RIGHT, $ff -.right - db D_UP, D_LEFT, $ff - -; these are the five coordinates which trigger the gym guy and pointers to -; different movements for the player to make to get positioned before the -; main movement -; $00 is a pause -PewterGymGuyCoords: - db 16, 34 - dw .one - db 17, 35 - dw .two - db 18, 37 - dw .three - db 19, 37 - dw .four - db 17, 36 - dw .five - -.one - db D_LEFT, D_DOWN, D_DOWN, D_RIGHT, $ff -.two - db D_LEFT, D_DOWN, D_RIGHT, D_LEFT, $ff -.three - db D_LEFT, D_LEFT, D_LEFT, $00, $00, $00, $00, $00, $00, $00, $00, $ff -.four - db D_LEFT, D_LEFT, D_UP, D_LEFT, $ff -.five - db D_LEFT, D_DOWN, D_LEFT, $00, $00, $00, $00, $00, $00, $00, $00, $ff diff --git a/engine/overworld/player_animations.asm b/engine/overworld/player_animations.asm index d4ecec53..5056c0b2 100755 --- a/engine/overworld/player_animations.asm +++ b/engine/overworld/player_animations.asm @@ -1,7 +1,7 @@ -EnterMapAnim: +EnterMapAnim:: call InitFacingDirectionList ld a, $ec - ld [wSpriteStateData1 + 4], a ; player's sprite Y screen position + ld [wSpritePlayerStateData1YPixels], a call Delay3 push hl call GBFadeInFromWhite @@ -94,7 +94,7 @@ PlayerSpinWhileMovingDown: jp PlayerSpinWhileMovingUpOrDown -_LeaveMapAnim: +_LeaveMapAnim:: call Func_1510 call InitFacingDirectionList call IsPlayerStandingOnWarpPadOrHole @@ -232,19 +232,19 @@ DoFlyAnimation: ld a, [wFlyAnimBirdSpriteImageIndex] xor $1 ; make the bird flap its wings ld [wFlyAnimBirdSpriteImageIndex], a - ld [wSpriteStateData1 + 2], a + ld [wSpritePlayerStateData1ImageIndex], a call Delay3 ld a, [wFlyAnimUsingCoordList] cp $ff jr z, .skipCopyingCoords ; if the bird is flapping its wings in place - ld hl, wSpriteStateData1 + 4 + ld hl, wSpritePlayerStateData1YPixels ld a, [de] inc de - ld [hli], a + ld [hli], a ; y inc hl ld a, [de] inc de - ld [hl], a + ld [hl], a ; x .skipCopyingCoords ld a, [wFlyAnimCounter] dec a @@ -258,22 +258,22 @@ LoadBirdSpriteGraphics: ld c, $c ld hl, vNPCSprites call CopyVideoData - ld de, BirdSprite + $c0 ; moving animation sprite + ld de, BirdSprite tile 12 ; moving animation sprite ld b, BANK(BirdSprite) - ld c, $0c + ld c, 12 ld hl, vNPCSprites2 jp CopyVideoData InitFacingDirectionList: - ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction (image index is locked to standing images) + ld a, [wSpritePlayerStateData1ImageIndex] ; (image index is locked to standing images) ld [wSavedPlayerFacingDirection], a - ld a, [wSpriteStateData1 + 4] ; player's sprite Y screen position + ld a, [wSpritePlayerStateData1YPixels] ld [wSavedPlayerScreenY], a ld hl, PlayerSpinningFacingOrder ld de, wFacingDirectionList ld bc, 4 call CopyData - ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction (image index is locked to standing images) + ld a, [wSpritePlayerStateData1ImageIndex] ; (image index is locked to standing images) ld hl, wFacingDirectionList ; find the place in the list that matches the current facing direction .loop @@ -291,7 +291,7 @@ PlayerSpinningFacingOrder: SpinPlayerSprite: ; copy the current value from the list into the sprite data and rotate the list ld a, [hl] - ld [wSpriteStateData1 + 2], a ; player's sprite facing direction (image index is locked to standing images) + ld [wSpritePlayerStateData1ImageIndex], a ; (image index is locked to standing images) push hl ld hl, wFacingDirectionList ld de, wFacingDirectionList - 1 @@ -327,9 +327,9 @@ PlayerSpinWhileMovingUpOrDown: call SpinPlayerSprite ld a, [wPlayerSpinWhileMovingUpOrDownAnimDeltaY] ld c, a - ld a, [wSpriteStateData1 + 4] ; player's sprite Y screen position + ld a, [wSpritePlayerStateData1YPixels] add c - ld [wSpriteStateData1 + 4], a + ld [wSpritePlayerStateData1YPixels], a ld c, a ld a, [wPlayerSpinWhileMovingUpOrDownAnimMaxY] cp c @@ -341,9 +341,9 @@ PlayerSpinWhileMovingUpOrDown: RestoreFacingDirectionAndYScreenPos: ld a, [wSavedPlayerScreenY] - ld [wSpriteStateData1 + 4], a + ld [wSpritePlayerStateData1YPixels], a ld a, [wSavedPlayerFacingDirection] - ld [wSpriteStateData1 + 2], a + ld [wSpritePlayerStateData1ImageIndex], a ; (image index is locked to standing images) ret ; if SGB, 2 frames, else 3 frames @@ -354,9 +354,9 @@ GetPlayerTeleportAnimFrameDelay: inc a ret -IsPlayerStandingOnWarpPadOrHole: +IsPlayerStandingOnWarpPadOrHole:: ld b, 0 - ld hl, .warpPadAndHoleData + ld hl, WarpPadAndHoleData ld a, [wCurMapTileset] ld c, a .loop @@ -365,7 +365,7 @@ IsPlayerStandingOnWarpPadOrHole: jr z, .done cp c jr nz, .nextEntry - aCoord 8, 9 + lda_coord 8, 9 cp [hl] jr z, .foundMatch .nextEntry @@ -380,13 +380,7 @@ IsPlayerStandingOnWarpPadOrHole: ld [wStandingOnWarpPadOrHole], a ret -; format: db tileset id, tile id, value to be put in [wStandingOnWarpPadOrHole] -.warpPadAndHoleData: - db FACILITY, $20, 1 ; warp pad - db FACILITY, $11, 2 ; hole - db CAVERN, $22, 2 ; hole - db INTERIOR, $55, 1 ; warp pad - db $FF +INCLUDE "data/tilesets/warp_pad_hole_tile_ids.asm" FishingAnim: ld c, 10 @@ -396,12 +390,12 @@ FishingAnim: ld hl, vNPCSprites ld de, RedSprite ld b, BANK(RedSprite) - ld c, $c + ld c, 12 call CopyVideoData ld a, $4 ld hl, RedFishingTiles call LoadAnimSpriteGfx - ld a, [wSpriteStateData1 + 2] + ld a, [wSpritePlayerStateData1ImageIndex] ld c, a ld b, $0 ld hl, FishingRodOAM @@ -424,7 +418,7 @@ FishingAnim: ; shake the player's sprite vertically ld b, 10 .loop - ld hl, wSpriteStateData1 + 4 ; player's sprite Y screen position + ld hl, wSpritePlayerStateData1YPixels call .ShakePlayerSprite ld hl, wOAMBuffer + $9c call .ShakePlayerSprite @@ -434,7 +428,7 @@ FishingAnim: ; If the player is facing up, hide the fishing rod so it doesn't overlap with ; the exclamation bubble that will be shown next. - ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1ImageIndex] ; (image index is locked to standing images) cp SPRITE_FACING_UP jr nz, .skipHidingFishingRod ld a, $a0 @@ -448,7 +442,7 @@ FishingAnim: predef EmotionBubble ; If the player is facing up, unhide the fishing rod. - ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1ImageIndex] ; (image index is locked to standing images) cp SPRITE_FACING_UP jr nz, .skipUnhidingFishingRod ld a, $44 @@ -471,46 +465,38 @@ FishingAnim: ret NoNibbleText: - TX_FAR _NoNibbleText - db "@" + text_far _NoNibbleText + text_end NothingHereText: - TX_FAR _NothingHereText - db "@" + text_far _NothingHereText + text_end ItsABiteText: - TX_FAR _ItsABiteText - db "@" + text_far _ItsABiteText + text_end FishingRodOAM: ; specifies how the fishing rod should be drawn on the screen -; first byte = screen y coordinate -; second byte = screen x coordinate -; third byte = tile number -; fourth byte = sprite properties - db $5B, $4C, $FD, $00 ; player facing down - db $44, $4C, $FD, $00 ; player facing up - db $50, $40, $FE, $00 ; player facing left - db $50, $58, $FE, $20 ; player facing right ($20 means "horizontally flip the tile") + dbsprite 9, 11, 4, 3, $fd, 0 ; down + dbsprite 9, 8, 4, 4, $fd, 0 ; up + dbsprite 8, 10, 0, 0, $fe, 0 ; left + dbsprite 11, 10, 0, 0, $fe, OAM_HFLIP ; right + +fishing_gfx: MACRO + dw \1 + db \2 + db BANK(\1) + dw vNPCSprites tile \3 +ENDM RedFishingTiles: - dw RedFishingTilesFront - db 2, BANK(RedFishingTilesFront) - dw vNPCSprites + $20 - - dw RedFishingTilesBack - db 2, BANK(RedFishingTilesBack) - dw vNPCSprites + $60 - - dw RedFishingTilesSide - db 2, BANK(RedFishingTilesSide) - dw vNPCSprites + $a0 - - dw RedFishingRodTiles - db 3, BANK(RedFishingRodTiles) - dw vNPCSprites2 + $7d0 + fishing_gfx RedFishingTilesFront, 2, $02 + fishing_gfx RedFishingTilesBack, 2, $06 + fishing_gfx RedFishingTilesSide, 2, $0a + fishing_gfx RedFishingRodTiles, 3, $fd -_HandleMidJump: +_HandleMidJump:: ld a, [wPlayerJumpingYScreenCoordsIndex] ld c, a inc a @@ -521,7 +507,7 @@ _HandleMidJump: ld hl, PlayerJumpingYScreenCoords add hl, bc ld a, [hl] - ld [wSpriteStateData1 + 4], a ; player's sprite y coordinate + ld [wSpritePlayerStateData1YPixels], a ret .finishedJump ld a, [wWalkCounter] @@ -530,9 +516,9 @@ _HandleMidJump: call UpdateSprites call Delay3 xor a - ld [hJoyHeld], a - ld [hJoyPressed], a - ld [hJoyReleased], a + ldh [hJoyHeld], a + ldh [hJoyPressed], a + ldh [hJoyReleased], a ld [wPlayerJumpingYScreenCoordsIndex], a ld hl, wd736 res 6, [hl] ; not jumping down a ledge any more diff --git a/engine/overworld/player_state.asm b/engine/overworld/player_state.asm index 8cbacc61..c966c128 100644 --- a/engine/overworld/player_state.asm +++ b/engine/overworld/player_state.asm @@ -1,5 +1,5 @@ ; only used for setting bit 2 of wd736 upon entering a new map -IsPlayerStandingOnWarp: +IsPlayerStandingOnWarp:: ld a, [wNumberOfWarps] and a ret z @@ -17,7 +17,7 @@ IsPlayerStandingOnWarp: ld a, [hli] ; target warp ld [wDestinationWarpID], a ld a, [hl] ; target map - ld [hWarpDestinationMap], a + ldh [hWarpDestinationMap], a ld hl, wd736 set 2, [hl] ; standing on warp flag ret @@ -31,7 +31,7 @@ IsPlayerStandingOnWarp: jr nz, .loop ret -CheckForceBikeOrSurf: +CheckForceBikeOrSurf:: ld hl, wd732 bit 5, [hl] ret nz @@ -84,13 +84,13 @@ CheckForceBikeOrSurf: call ForceBikeOrSurf ret -INCLUDE "data/force_bike_surf.asm" +INCLUDE "data/maps/force_bike_surf.asm" -IsPlayerFacingEdgeOfMap: +IsPlayerFacingEdgeOfMap:: push hl push de push bc - ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction + ld a, [wSpritePlayerStateData1FacingDirection] srl a ld c, a ld b, $0 @@ -152,19 +152,19 @@ IsPlayerFacingEdgeOfMap: scf ret -IsWarpTileInFrontOfPlayer: +IsWarpTileInFrontOfPlayer:: push hl push de push bc call _GetTileAndCoordsInFrontOfPlayer ld a, [wCurMap] cp SS_ANNE_BOW - jr z, .ssAnne5 - ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction + jr z, IsSSAnneBowWarpTileInFrontOfPlayer + ld a, [wSpritePlayerStateData1FacingDirection] srl a ld c, a ld b, 0 - ld hl, .warpTileListPointers + ld hl, WarpTileListPointers add hl, bc ld a, [hli] ld h, [hl] @@ -178,39 +178,23 @@ IsWarpTileInFrontOfPlayer: pop hl ret -.warpTileListPointers: - dw .facingDownWarpTiles - dw .facingUpWarpTiles - dw .facingLeftWarpTiles - dw .facingRightWarpTiles +INCLUDE "data/tilesets/warp_carpet_tile_ids.asm" -.facingDownWarpTiles - db $01,$12,$17,$3D,$04,$18,$33,$FF - -.facingUpWarpTiles - db $01,$5C,$FF - -.facingLeftWarpTiles - db $1A,$4B,$FF - -.facingRightWarpTiles - db $0F,$4E,$FF - -.ssAnne5 +IsSSAnneBowWarpTileInFrontOfPlayer: ld a, [wTileInFrontOfPlayer] cp $15 jr nz, .notSSAnne5Warp scf - jr .done + jr IsWarpTileInFrontOfPlayer.done .notSSAnne5Warp and a - jr .done + jr IsWarpTileInFrontOfPlayer.done -IsPlayerStandingOnDoorTileOrWarpTile: +IsPlayerStandingOnDoorTileOrWarpTile:: push hl push de push bc - callba IsPlayerStandingOnDoorTile + farcall IsPlayerStandingOnDoorTile jr c, .done ld a, [wCurMapTileset] add a @@ -222,7 +206,7 @@ IsPlayerStandingOnDoorTileOrWarpTile: ld h, [hl] ld l, a ld de, $1 - aCoord 8, 9 + lda_coord 8, 9 call IsInArray jr nc, .done ld hl, wd736 @@ -233,35 +217,35 @@ IsPlayerStandingOnDoorTileOrWarpTile: pop hl ret -INCLUDE "data/warp_tile_ids.asm" +INCLUDE "data/tilesets/warp_tile_ids.asm" -PrintSafariZoneSteps: +PrintSafariZoneSteps:: ld a, [wCurMap] cp SAFARI_ZONE_EAST ret c cp CERULEAN_CAVE_2F ret nc - coord hl, 0, 0 + hlcoord 0, 0 lb bc, 3, 7 call TextBoxBorder - coord hl, 1, 1 + hlcoord 1, 1 ld de, wSafariSteps lb bc, 2, 3 call PrintNumber - coord hl, 4, 1 + hlcoord 4, 1 ld de, SafariSteps call PlaceString - coord hl, 1, 3 + hlcoord 1, 3 ld de, SafariBallText call PlaceString ld a, [wNumSafariBalls] cp 10 jr nc, .numSafariBallsTwoDigits - coord hl, 5, 3 + hlcoord 5, 3 ld a, " " ld [hl], a .numSafariBallsTwoDigits - coord hl, 6, 3 + hlcoord 6, 3 ld de, wNumSafariBalls lb bc, 1, 2 jp PrintNumber @@ -280,32 +264,32 @@ _GetTileAndCoordsInFrontOfPlayer: ld d, a ld a, [wXCoord] ld e, a - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] and a ; cp SPRITE_FACING_DOWN jr nz, .notFacingDown ; facing down - aCoord 8, 11 + lda_coord 8, 11 inc d jr .storeTile .notFacingDown cp SPRITE_FACING_UP jr nz, .notFacingUp ; facing up - aCoord 8, 7 + lda_coord 8, 7 dec d jr .storeTile .notFacingUp cp SPRITE_FACING_LEFT jr nz, .notFacingLeft ; facing left - aCoord 6, 9 + lda_coord 6, 9 dec e jr .storeTile .notFacingLeft cp SPRITE_FACING_RIGHT jr nz, .storeTile ; facing right - aCoord 10, 9 + lda_coord 10, 9 inc e .storeTile ld c, a @@ -314,45 +298,45 @@ _GetTileAndCoordsInFrontOfPlayer: GetTileTwoStepsInFrontOfPlayer: xor a - ld [$ffdb], a + ldh [hPlayerFacing], a ld hl, wYCoord ld a, [hli] ld d, a ld e, [hl] - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] and a ; cp SPRITE_FACING_DOWN jr nz, .notFacingDown ; facing down - ld hl, $ffdb + ld hl, hPlayerFacing set 0, [hl] - aCoord 8, 13 + lda_coord 8, 13 inc d jr .storeTile .notFacingDown cp SPRITE_FACING_UP jr nz, .notFacingUp ; facing up - ld hl, $ffdb + ld hl, hPlayerFacing set 1, [hl] - aCoord 8, 5 + lda_coord 8, 5 dec d jr .storeTile .notFacingUp cp SPRITE_FACING_LEFT jr nz, .notFacingLeft ; facing left - ld hl, $ffdb + ld hl, hPlayerFacing set 2, [hl] - aCoord 4, 9 + lda_coord 4, 9 dec e jr .storeTile .notFacingLeft cp SPRITE_FACING_RIGHT jr nz, .storeTile ; facing right - ld hl, $ffdb + ld hl, hPlayerFacing set 3, [hl] - aCoord 12, 9 + lda_coord 12, 9 inc e .storeTile ld c, a @@ -384,36 +368,36 @@ CheckForBoulderCollisionWithSprites: swap a ld d, 0 ld e, a - ld hl, wSpriteStateData2 + $14 + ld hl, wSprite01StateData2MapY add hl, de ld a, [hli] ; map Y position - ld [$ffdc], a + ldh [hPlayerYCoord], a ld a, [hl] ; map X position - ld [$ffdd], a + ldh [hPlayerXCoord], a ld a, [wNumSprites] ld c, a ld de, $f - ld hl, wSpriteStateData2 + $14 - ld a, [$ffdb] + ld hl, wSprite01StateData2MapY + ldh a, [hPlayerFacing] and $3 ; facing up or down? jr z, .pushingHorizontallyLoop .pushingVerticallyLoop inc hl - ld a, [$ffdd] + ldh a, [hPlayerXCoord] cp [hl] jr nz, .nextSprite1 ; if X coordinates don't match dec hl ld a, [hli] ld b, a - ld a, [$ffdb] + ldh a, [hPlayerFacing] rrca jr c, .pushingDown ; pushing up - ld a, [$ffdc] + ldh a, [hPlayerYCoord] dec a jr .compareYCoords .pushingDown - ld a, [$ffdc] + ldh a, [hPlayerYCoord] inc a .compareYCoords cp b @@ -426,19 +410,19 @@ CheckForBoulderCollisionWithSprites: .pushingHorizontallyLoop ld a, [hli] ld b, a - ld a, [$ffdc] + ldh a, [hPlayerYCoord] cp b jr nz, .nextSprite2 ld b, [hl] - ld a, [$ffdb] + ldh a, [hPlayerFacing] bit 2, a jr nz, .pushingLeft ; pushing right - ld a, [$ffdd] + ldh a, [hPlayerXCoord] inc a jr .compareXCoords .pushingLeft - ld a, [$ffdd] + ldh a, [hPlayerXCoord] dec a .compareXCoords cp b diff --git a/engine/overworld/poison.asm b/engine/overworld/poison.asm deleted file mode 100644 index 03fb8a65..00000000 --- a/engine/overworld/poison.asm +++ /dev/null @@ -1,151 +0,0 @@ -ApplyOutOfBattlePoisonDamage: - ld a, [wd730] - add a - jp c, .noBlackOut ; no black out if joypad states are being simulated - ld a, [wd492] - bit 7, a - jp nz, .noBlackOut - ld a, [wd72e] - bit 6, a - jp nz, .noBlackOut - ld a, [wPartyCount] - and a - jp z, .noBlackOut - call IncrementDayCareMonExp - call Func_c4c7 - ld a, [wStepCounter] - and $3 ; is the counter a multiple of 4? - jp nz, .skipPoisonEffectAndSound ; only apply poison damage every fourth step - ld [wWhichPokemon], a - ld hl, wPartyMon1Status - ld de, wPartySpecies -.applyDamageLoop - ld a, [hl] - and (1 << PSN) - jr z, .nextMon2 ; not poisoned - dec hl - dec hl - ld a, [hld] - ld b, a - ld a, [hli] - or b - jr z, .nextMon ; already fainted -; subtract 1 from HP - ld a, [hl] - dec a - ld [hld], a - inc a - jr nz, .noBorrow -; borrow 1 from upper byte of HP - dec [hl] - inc hl - jr .nextMon -.noBorrow - ld a, [hli] - or [hl] - jr nz, .nextMon ; didn't faint from damage -; the mon fainted from the damage - push hl - inc hl - inc hl - ld [hl], a - ld a, [de] - ld [wd11e], a - push de - ld a, [wWhichPokemon] - ld hl, wPartyMonNicks - call GetPartyMonName - xor a - ld [wJoyIgnore], a - call EnableAutoTextBoxDrawing - ld a, TEXT_MON_FAINTED - ld [hSpriteIndexOrTextID], a - call DisplayTextID - callab IsThisPartymonStarterPikachu_Party - jr nc, .curMonNotPlayerPikachu - ld e, $3 - callab PlayPikachuSoundClip - calladb_ModifyPikachuHappiness PIKAHAPPY_PSNFNT -.curMonNotPlayerPikachu - pop de - pop hl -.nextMon - inc hl - inc hl -.nextMon2 - inc de - ld a, [de] - inc a - jr z, .applyDamageLoopDone - ld bc, wPartyMon2 - wPartyMon1 - add hl, bc - push hl - ld hl, wWhichPokemon - inc [hl] - pop hl - jr .applyDamageLoop -.applyDamageLoopDone - ld hl, wPartyMon1Status - ld a, [wPartyCount] - ld d, a - ld e, 0 -.countPoisonedLoop - ld a, [hl] - and (1 << PSN) - or e - ld e, a - ld bc, wPartyMon2 - wPartyMon1 - add hl, bc - dec d - jr nz, .countPoisonedLoop - ld a, e - and a ; are any party members poisoned? - jr z, .skipPoisonEffectAndSound - ld b, $2 - predef ChangeBGPalColor0_4Frames ; change BG white to dark grey for 4 frames - ld a, SFX_POISONED - call PlaySound -.skipPoisonEffectAndSound - predef AnyPartyAlive - ld a, d - and a - jr nz, .noBlackOut - call EnableAutoTextBoxDrawing - ld a, TEXT_BLACKED_OUT - ld [hSpriteIndexOrTextID], a - call DisplayTextID - ld hl, wd72e - set 5, [hl] - ld a, $ff - jr .done -.noBlackOut - xor a -.done - ld [wOutOfBattleBlackout], a - ret - -Func_c4c7: - ld a, [wStepCounter] - and a - jr nz, .asm_c4de - call Random - and $1 - jr z, .asm_c4de - calladb_ModifyPikachuHappiness $6 -.asm_c4de - ld hl, wPikachuMood - ld a, [hl] - cp $80 - jr z, .asm_c4ef - jr c, .asm_c4ea - dec a - dec a -.asm_c4ea - inc a - ld [hl], a - cp $80 - ret nz -.asm_c4ef - xor a - ld [wd49c], a - ret diff --git a/engine/overworld/pokecenter.asm b/engine/overworld/pokecenter.asm deleted file mode 100755 index cf0159f9..00000000 --- a/engine/overworld/pokecenter.asm +++ /dev/null @@ -1,149 +0,0 @@ -DisplayPokemonCenterDialogue_: - ld a, [wCurMap] - cp PEWTER_POKECENTER - jr nz, .regularCenter - call CheckPikachuFollowingPlayer - jr z, .regularCenter - ld hl, LooksContentText ; if pikachu is sleeping, don't heal - call PrintText - ret -.regularCenter - call SaveScreenTilesToBuffer1 ; save screen - ld hl, PokemonCenterWelcomeText - call PrintText - ld hl, wd72e - bit 2, [hl] - set 1, [hl] - set 2, [hl] - jr nz, .skipShallWeHealYourPokemon - ld hl, ShallWeHealYourPokemonText - call PrintText -.skipShallWeHealYourPokemon - call YesNoChoicePokeCenter ; yes/no menu - call UpdateSprites - ld a, [wCurrentMenuItem] - and a - jp nz, .declinedHealing ; if the player chose No - call SetLastBlackoutMap - callab IsStarterPikachuInOurParty - jr nc, .notHealingPlayerPikachu - call CheckPikachuFollowingPlayer - jr nz, .notHealingPlayerPikachu - call LoadCurrentMapView - call Delay3 - call UpdateSprites - callab PikachuWalksToNurseJoy ; todo -.notHealingPlayerPikachu - ld hl, NeedYourPokemonText - call PrintText - ld c, 64 - call DelayFrames - call CheckPikachuFollowingPlayer - jr nz, .playerPikachuNotOnScreen - call DisablePikachuOverworldSpriteDrawing - callab IsStarterPikachuInOurParty - call c, Func_6eaa -.playerPikachuNotOnScreen - lb bc, 1, 8 - call Func_6ebb - ld c, 30 - call DelayFrames - callba AnimateHealingMachine ; do the healing machine animation - predef HealParty - xor a - ld [wAudioFadeOutControl], a - ld a, [wAudioSavedROMBank] - ld [wAudioROMBank], a - ld a, [wMapMusicSoundID] - ld [wLastMusicSoundID], a - ld [wNewSoundID], a - call PlaySound - call CheckPikachuFollowingPlayer - jr nz, .doNotReturnPikachu - callab IsStarterPikachuInOurParty - call c, Func_6eaa - ld a, $5 - ld [wPikachuSpawnState], a - call EnablePikachuOverworldSpriteDrawing -.doNotReturnPikachu - lb bc, 1, 0 - call Func_6ebb - ld hl, PokemonFightingFitText - call PrintText - callab IsStarterPikachuInOurParty - jr nc, .notInParty - lb bc, 15, 0 - call Func_6ebb -.notInParty - call LoadCurrentMapView - call Delay3 - call UpdateSprites - callab ReloadWalkingTilePatterns - ld a, $1 - ld [H_SPRITEINDEX], a - ld a, $1 - ld [hSpriteImageIndex], a - call SpriteFunc_34a1 - ld c, 40 - call DelayFrames - call UpdateSprites - call LoadFontTilePatterns - jr .done -.declinedHealing - call LoadScreenTilesFromBuffer1 ; restore screen -.done - ld hl, PokemonCenterFarewellText - call PrintText - call UpdateSprites - ret - -Func_6eaa: - ld a, $1 - ld [H_SPRITEINDEX], a - ld a, $4 - ld [hSpriteImageIndex], a - call SpriteFunc_34a1 - ld c, 64 - call DelayFrames - ret - -Func_6ebb: - ld a, b - ld [H_SPRITEINDEX], a - ld a, c - ld [hSpriteImageIndex], a - push bc - call SetSpriteFacingDirectionAndDelay - pop bc - ld a, b - ld [H_SPRITEINDEX], a - ld a, c - ld [hSpriteImageIndex], a - call SpriteFunc_34a1 - ret - -PokemonCenterWelcomeText: - TX_FAR _PokemonCenterWelcomeText - db "@" - -ShallWeHealYourPokemonText: - TX_DELAY - TX_FAR _ShallWeHealYourPokemonText - db "@" - -NeedYourPokemonText: - TX_FAR _NeedYourPokemonText - db "@" - -PokemonFightingFitText: - TX_FAR _PokemonFightingFitText - db "@" - -PokemonCenterFarewellText: - TX_DELAY - TX_FAR _PokemonCenterFarewellText - db "@" - -LooksContentText: - TX_FAR _LooksContentText - db "@" diff --git a/engine/overworld/pokemart.asm b/engine/overworld/pokemart.asm deleted file mode 100755 index dc5b29b5..00000000 --- a/engine/overworld/pokemart.asm +++ /dev/null @@ -1,272 +0,0 @@ -DisplayPokemartDialogue_: - ld a, [wListScrollOffset] - ld [wSavedListScrollOffset], a - call UpdateSprites - xor a - ld [wBoughtOrSoldItemInMart], a -.loop - xor a - ld [wListScrollOffset], a - ld [wCurrentMenuItem], a - ld [wPlayerMonNumber], a - inc a - ld [wPrintItemPrices], a - ld a, MONEY_BOX - ld [wTextBoxID], a - call DisplayTextBoxID - ld a, BUY_SELL_QUIT_MENU - ld [wTextBoxID], a - call DisplayTextBoxID - -; This code is useless. It copies the address of the pokemart's inventory to hl, -; but the address is never used. - ld hl, wItemListPointer - ld a, [hli] - ld l, [hl] - ld h, a - - ld a, [wMenuExitMethod] - cp CANCELLED_MENU - jp z, .done - ld a, [wChosenMenuItem] - and a ; buying? - jp z, .buyMenu - dec a ; selling? - jp z, .sellMenu - dec a ; quitting? - jp z, .done -.sellMenu - -; the same variables are set again below, so this code has no effect - xor a - ld [wPrintItemPrices], a - ld a, INIT_BAG_ITEM_LIST - ld [wInitListType], a - callab InitList - - ld a, [wNumBagItems] - and a - jp z, .bagEmpty - ld hl, PokemonSellingGreetingText - call PrintText - call SaveScreenTilesToBuffer1 ; save screen -.sellMenuLoop - call LoadScreenTilesFromBuffer1 ; restore saved screen - ld a, MONEY_BOX - ld [wTextBoxID], a - call DisplayTextBoxID ; draw money text box - ld hl, wNumBagItems - ld a, l - ld [wListPointer], a - ld a, h - ld [wListPointer + 1], a - xor a - ld [wPrintItemPrices], a - ld [wCurrentMenuItem], a - ld a, ITEMLISTMENU - ld [wListMenuID], a - call DisplayListMenuID - jp c, .returnToMainPokemartMenu ; if the player closed the menu -.confirmItemSale ; if the player is trying to sell a specific item - call IsKeyItem - ld a, [wIsKeyItem] - and a - jr nz, .unsellableItem - ld a, [wcf91] - call IsItemHM - jr c, .unsellableItem - ld a, PRICEDITEMLISTMENU - ld [wListMenuID], a - ld [hHalveItemPrices], a ; halve prices when selling - call DisplayChooseQuantityMenu - inc a - jr z, .sellMenuLoop ; if the player closed the choose quantity menu with the B button - ld hl, PokemartTellSellPriceText - lb bc, 14, 1 ; location that PrintText always prints to, this is useless - call PrintText - coord hl, 14, 7 - lb bc, 8, 15 - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID ; yes/no menu - ld a, [wMenuExitMethod] - cp CHOSE_SECOND_ITEM - jr z, .sellMenuLoop ; if the player chose No or pressed the B button - -; The following code is supposed to check if the player chose No, but the above -; check already catches it. - ld a, [wChosenMenuItem] - dec a - jr z, .sellMenuLoop - -.sellItem - ld a, [wBoughtOrSoldItemInMart] - and a - jr nz, .skipSettingFlag1 - inc a - ld [wBoughtOrSoldItemInMart], a -.skipSettingFlag1 - call AddAmountSoldToMoney - ld hl, wNumBagItems - call RemoveItemFromInventory - jp .sellMenuLoop -.unsellableItem - ld hl, PokemartUnsellableItemText - call PrintText - jp .returnToMainPokemartMenu -.bagEmpty - ld hl, PokemartItemBagEmptyText - call PrintText - call SaveScreenTilesToBuffer1 - jp .returnToMainPokemartMenu -.buyMenu - -; the same variables are set again below, so this code has no effect - ld a, 1 - ld [wPrintItemPrices], a - ld a, INIT_OTHER_ITEM_LIST - ld [wInitListType], a - callab InitList - - ld hl, PokemartBuyingGreetingText - call PrintText - call SaveScreenTilesToBuffer1 -.buyMenuLoop - call LoadScreenTilesFromBuffer1 - ld a, MONEY_BOX - ld [wTextBoxID], a - call DisplayTextBoxID - ld hl, wItemList - ld a, l - ld [wListPointer], a - ld a, h - ld [wListPointer + 1], a - xor a - ld [wCurrentMenuItem], a - inc a - ld [wPrintItemPrices], a - inc a ; a = 2 (PRICEDITEMLISTMENU) - ld [wListMenuID], a - call DisplayListMenuID - jr c, .returnToMainPokemartMenu ; if the player closed the menu - ld a, 99 - ld [wMaxItemQuantity], a - xor a - ld [hHalveItemPrices], a ; don't halve item prices when buying - call DisplayChooseQuantityMenu - inc a - jr z, .buyMenuLoop ; if the player closed the choose quantity menu with the B button - ld a, [wcf91] ; item ID - ld [wd11e], a ; store item ID for GetItemName - call GetItemName - call CopyStringToCF4B ; copy name to wcf4b - ld hl, PokemartTellBuyPriceText - call PrintText - coord hl, 14, 7 - lb bc, 8, 15 - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID ; yes/no menu - ld a, [wMenuExitMethod] - cp CHOSE_SECOND_ITEM - jp z, .buyMenuLoop ; if the player chose No or pressed the B button - -; The following code is supposed to check if the player chose No, but the above -; check already catches it. - ld a, [wChosenMenuItem] - dec a - jr z, .buyMenuLoop - -.buyItem - call .isThereEnoughMoney - jr c, .notEnoughMoney - ld hl, wNumBagItems - call AddItemToInventory - jr nc, .bagFull - call SubtractAmountPaidFromMoney - ld a, [wBoughtOrSoldItemInMart] - and a - jr nz, .skipSettingFlag2 - ld a, 1 - ld [wBoughtOrSoldItemInMart], a -.skipSettingFlag2 - ld a, SFX_PURCHASE - call PlaySoundWaitForCurrent - call WaitForSoundToFinish - ld hl, PokemartBoughtItemText - call PrintText - jp .buyMenuLoop -.returnToMainPokemartMenu - call LoadScreenTilesFromBuffer1 - ld a, MONEY_BOX - ld [wTextBoxID], a - call DisplayTextBoxID - ld hl, PokemartAnythingElseText - call PrintText - jp .loop -.isThereEnoughMoney - ld de, wPlayerMoney - ld hl, hMoney - ld c, 3 ; length of money in bytes - jp StringCmp -.notEnoughMoney - ld hl, PokemartNotEnoughMoneyText - call PrintText - jr .returnToMainPokemartMenu -.bagFull - ld hl, PokemartItemBagFullText - call PrintText - jr .returnToMainPokemartMenu -.done - ld hl, PokemartThankYouText - call PrintText - ld a, 1 - ld [wUpdateSpritesEnabled], a - call UpdateSprites - ld a, [wSavedListScrollOffset] - ld [wListScrollOffset], a - ret - -PokemartBuyingGreetingText: - TX_FAR _PokemartBuyingGreetingText - db "@" - -PokemartTellBuyPriceText: - TX_FAR _PokemartTellBuyPriceText - db "@" - -PokemartBoughtItemText: - TX_FAR _PokemartBoughtItemText - db "@" - -PokemartNotEnoughMoneyText: - TX_FAR _PokemartNotEnoughMoneyText - db "@" - -PokemartItemBagFullText: - TX_FAR _PokemartItemBagFullText - db "@" - -PokemonSellingGreetingText: - TX_FAR _PokemonSellingGreetingText - db "@" - -PokemartTellSellPriceText: - TX_FAR _PokemartTellSellPriceText - db "@" - -PokemartItemBagEmptyText: - TX_FAR _PokemartItemBagEmptyText - db "@" - -PokemartUnsellableItemText: - TX_FAR _PokemartUnsellableItemText - db "@" - -PokemartThankYouText: - TX_FAR _PokemartThankYouText - db "@" - -PokemartAnythingElseText: - TX_FAR _PokemartAnythingElseText - db "@" diff --git a/engine/overworld/push_boulder.asm b/engine/overworld/push_boulder.asm index 8a385345..09911ca3 100644 --- a/engine/overworld/push_boulder.asm +++ b/engine/overworld/push_boulder.asm @@ -1,4 +1,4 @@ -TryPushingBoulder: +TryPushingBoulder:: ld a, [wd728] bit 0, a ; using Strength? ret z @@ -8,15 +8,15 @@ Func_f0a7: bit 1, a ; has boulder dust animation from previous push played yet? ret nz xor a - ld [hSpriteIndexOrTextID], a + ldh [hSpriteIndexOrTextID], a call IsSpriteInFrontOfPlayer - ld a, [hSpriteIndexOrTextID] + ldh a, [hSpriteIndexOrTextID] ld [wBoulderSpriteIndex], a and a jp z, ResetBoulderPushFlags - ld hl, wSpriteStateData1 + 1 + ld hl, wSpritePlayerStateData1MovementStatus ld d, $0 - ld a, [hSpriteIndexOrTextID] + ldh a, [hSpriteIndexOrTextID] swap a ld e, a add hl, de @@ -29,16 +29,16 @@ Func_f0a7: bit 6, [hl] set 6, [hl] ; indicate that the player has tried pushing ret z ; the player must try pushing twice before the boulder will move - ld a, [hJoyHeld] + ldh a, [hJoyHeld] and D_RIGHT | D_LEFT | D_UP | D_DOWN ret z predef CheckForCollisionWhenPushingBoulder ld a, [wTileInFrontOfBoulderAndBoulderCollisionResult] and a ; was there a collision? jp nz, ResetBoulderPushFlags - ld a, [hJoyHeld] + ldh a, [hJoyHeld] ld b, a - ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] cp SPRITE_FACING_UP jr z, .pushBoulderUp cp SPRITE_FACING_LEFT @@ -73,28 +73,32 @@ Func_f0a7: ret PushBoulderUpMovementData: - db NPC_MOVEMENT_UP,$FF + db NPC_MOVEMENT_UP + db -1 ; end PushBoulderDownMovementData: - db NPC_MOVEMENT_DOWN,$FF + db NPC_MOVEMENT_DOWN + db -1 ; end PushBoulderLeftMovementData: - db NPC_MOVEMENT_LEFT,$FF + db NPC_MOVEMENT_LEFT + db -1 ; end PushBoulderRightMovementData: - db NPC_MOVEMENT_RIGHT,$FF + db NPC_MOVEMENT_RIGHT + db -1 ; end -DoBoulderDustAnimation: +DoBoulderDustAnimation:: ld a, [wd730] bit 0, a ret nz - callab AnimateBoulderDust + callfar AnimateBoulderDust call DiscardButtonPresses ld [wJoyIgnore], a call ResetBoulderPushFlags set 7, [hl] ld a, [wBoulderSpriteIndex] - ld [H_SPRITEINDEX], a + ldh [hSpriteIndex], a call GetSpriteMovementByte2Pointer ld [hl], $10 ld a, SFX_CUT diff --git a/engine/overworld/saffron_guards.asm b/engine/overworld/saffron_guards.asm deleted file mode 100755 index 3b26b6f8..00000000 --- a/engine/overworld/saffron_guards.asm +++ /dev/null @@ -1,16 +0,0 @@ -RemoveGuardDrink: - ld hl, GuardDrinksList -.drinkLoop - ld a, [hli] - ld [$ffdb], a - and a - ret z - push hl - ld b, a - call IsItemInBag - pop hl - jr z, .drinkLoop - jpba RemoveItemByID - -GuardDrinksList: - db FRESH_WATER, SODA_POP, LEMONADE, $00 diff --git a/engine/overworld/set_blackout_map.asm b/engine/overworld/set_blackout_map.asm deleted file mode 100644 index bac2f0ca..00000000 --- a/engine/overworld/set_blackout_map.asm +++ /dev/null @@ -1,29 +0,0 @@ -SetLastBlackoutMap: -; Set the map to return to when -; blacking out or using Teleport or Dig. -; Safari rest houses don't count. - - push hl - ld hl, SafariZoneRestHouses - ld a, [wCurMap] - ld b, a -.loop - ld a, [hli] - cp -1 - jr z, .notresthouse - cp b - jr nz, .loop - jr .done - -.notresthouse - ld a, [wLastMap] - ld [wLastBlackoutMap], a -.done - pop hl - ret - -SafariZoneRestHouses: - db SAFARI_ZONE_WEST_REST_HOUSE - db SAFARI_ZONE_EAST_REST_HOUSE - db SAFARI_ZONE_NORTH_REST_HOUSE - db -1 diff --git a/engine/overworld/special_warps.asm b/engine/overworld/special_warps.asm new file mode 100644 index 00000000..61356a03 --- /dev/null +++ b/engine/overworld/special_warps.asm @@ -0,0 +1,149 @@ +SpecialWarpIn:: + call LoadSpecialWarpData + predef LoadTilesetHeader + ld hl, wd732 + bit 2, [hl] ; dungeon warp or fly warp? + res 2, [hl] + jr z, .next +; if dungeon warp or fly warp + ld a, [wDestinationMap] + jr .next2 +.next + bit 1, [hl] + jr z, .next3 + call DebugStart +.next3 + ld a, 0 +.next2 + ld b, a + ld a, [wd72d] + and a + jr nz, .next4 + ld a, b +.next4 + ld hl, wd732 + bit 4, [hl] ; dungeon warp? + ret nz +; if not dungeon warp + ld [wLastMap], a + ret + +; gets the map ID, tile block map view pointer, tileset, and coordinates +LoadSpecialWarpData: + ld a, [wd72d] + cp TRADE_CENTER + jr nz, .notTradeCenter + ld hl, TradeCenterSpec1 + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK ; which gameboy is clocking determines who is on the left and who is on the right + jr z, .copyWarpData + ld hl, TradeCenterSpec2 + jr .copyWarpData +.notTradeCenter + cp COLOSSEUM + jr nz, .notColosseum + ld hl, ColosseumSpec1 + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr z, .copyWarpData + ld hl, ColosseumSpec2 + jr .copyWarpData +.notColosseum + ld a, [wd732] + bit 1, a + jr nz, .notFirstMap + bit 2, a + jr nz, .notFirstMap + ld hl, FirstMapSpec +.copyWarpData + ld de, wCurMap + ld c, $7 +.copyWarpDataLoop + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .copyWarpDataLoop + ld a, [hli] + ld [wCurMapTileset], a + xor a + jr .done +.notFirstMap + ld a, [wLastMap] ; this value is overwritten before it's ever read + ld hl, wd732 + bit 4, [hl] ; used dungeon warp (jumped down hole/waterfall)? + jr nz, .usedDunegonWarp + bit 6, [hl] ; return to last pokemon center (or player's house)? + res 6, [hl] + jr z, .otherDestination +; return to last pokemon center or player's house + ld a, [wLastBlackoutMap] + jr .usedFlyWarp +.usedDunegonWarp + ld hl, wd72d + res 4, [hl] + ld a, [wDungeonWarpDestinationMap] + ld b, a + ld [wCurMap], a + ld a, [wWhichDungeonWarp] + ld c, a + ld hl, DungeonWarpList + ld de, 0 + ld a, 6 + ld [wDungeonWarpDataEntrySize], a +.dungeonWarpListLoop + ld a, [hli] + cp b + jr z, .matchedDungeonWarpDestinationMap + inc hl + jr .nextDungeonWarp +.matchedDungeonWarpDestinationMap + ld a, [hli] + cp c + jr z, .matchedDungeonWarpID +.nextDungeonWarp + ld a, [wDungeonWarpDataEntrySize] + add e + ld e, a + jr .dungeonWarpListLoop +.matchedDungeonWarpID + ld hl, DungeonWarpData + add hl, de + jr .copyWarpData2 +.otherDestination + ld a, [wDestinationMap] +.usedFlyWarp + ld b, a + ld [wCurMap], a + ld hl, FlyWarpDataPtr +.flyWarpDataPtrLoop + ld a, [hli] + inc hl + cp b + jr z, .foundFlyWarpMatch + inc hl + inc hl + jr .flyWarpDataPtrLoop +.foundFlyWarpMatch + ld a, [hli] + ld h, [hl] + ld l, a +.copyWarpData2 + ld de, wCurrentTileBlockMapViewPointer + ld c, $6 +.copyWarpDataLoop2 + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .copyWarpDataLoop2 + xor a ; OVERWORLD + ld [wCurMapTileset], a +.done + ld [wYOffsetSinceLastSpecialWarp], a + ld [wXOffsetSinceLastSpecialWarp], a + ld a, $ff ; the player's coordinates have already been updated using a special warp, so don't use any of the normal warps + ld [wDestinationWarpID], a + ret + +INCLUDE "data/maps/special_warps.asm" diff --git a/engine/overworld/spinners.asm b/engine/overworld/spinners.asm new file mode 100644 index 00000000..0ac6380d --- /dev/null +++ b/engine/overworld/spinners.asm @@ -0,0 +1,65 @@ +LoadSpinnerArrowTiles:: + ld a, [wSpritePlayerStateData1ImageIndex] + srl a + srl a + ld hl, SpinnerPlayerFacingDirections + ld c, a + ld b, $0 + add hl, bc + ld a, [hl] + ld [wSpritePlayerStateData1ImageIndex], a + ld a, [wCurMapTileset] + cp FACILITY + ld hl, FacilitySpinnerArrows + jr z, .asm_44ff6 + ld hl, GymSpinnerArrows +.asm_44ff6 + ld a, [wSimulatedJoypadStatesIndex] + bit 0, a + jr nz, .asm_45001 + ld de, $18 + add hl, de +.asm_45001 + ld a, $4 + ld bc, $0 +.asm_45006 + push af + push hl + push bc + add hl, bc + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + ld a, [hli] + ld c, a + ld a, [hli] + ld b, a + ld a, [hli] + ld h, [hl] + ld l, a + call CopyVideoData + pop bc + ld a, $6 + add c + ld c, a + pop hl + pop af + dec a + jr nz, .asm_45006 + ret + +INCLUDE "data/tilesets/spinner_tiles.asm" + +SpinnerPlayerFacingDirections: +; This isn't the order of the facing directions. Rather, it's a list of +; the facing directions that come next. For example, when the player is +; facing down (00), the next facing direction is left (08). + db $08 ; down -> left + db $0C ; up -> right + db $04 ; left -> up + db $00 ; right -> down + +; these tiles are the animation for the tiles that push the player in dungeons like Rocket HQ +SpinnerArrowAnimTiles: + INCBIN "gfx/overworld/spinners.2bpp" diff --git a/engine/overworld/sprite_collisions.asm b/engine/overworld/sprite_collisions.asm new file mode 100644 index 00000000..db81977b --- /dev/null +++ b/engine/overworld/sprite_collisions.asm @@ -0,0 +1,392 @@ +_UpdateSprites:: + ld h, wSpriteStateData1 / $100 + inc h + ld a, SPRITESTATEDATA2_IMAGEBASEOFFSET +.spriteLoop + ld l, a + sub SPRITESTATEDATA2_IMAGEBASEOFFSET + ld c, a + ldh [hCurrentSpriteOffset], a + ld a, [hl] + and a + jr z, .skipSprite ; tests SPRITESTATEDATA2_IMAGEBASEOFFSET + push hl + push de + push bc + call .updateCurrentSprite + pop bc + pop de + pop hl +.skipSprite + ld a, l + add $10 ; move to next sprite + cp SPRITESTATEDATA2_IMAGEBASEOFFSET ; test for overflow (back at beginning) + jr nz, .spriteLoop + ret +.updateCurrentSprite + ldh a, [hCurrentSpriteOffset] + and a + jp z, UpdatePlayerSprite + cp $f0 ; pikachu + jp z, SpawnPikachu + ld a, [hl] + +UpdateNonPlayerSprite: + dec a + swap a + ldh [hTilePlayerStandingOn], a ; $10 * sprite# + ld a, [wNPCMovementScriptSpriteOffset] ; some sprite offset? + ld b, a + ldh a, [hCurrentSpriteOffset] + cp b + jr nz, .unequal + jp DoScriptedNPCMovement +.unequal + jp UpdateNPCSprite + +; This detects if the current sprite (whose offset is at hCurrentSpriteOffset) +; is going to collide with another sprite by looping over the other sprites. +; The current sprite's offset will be labelled with i (e.g. i#SPRITESTATEDATA1_PICTUREID). +; The loop sprite's offset will labelled with j (e.g. j#SPRITESTATEDATA1_PICTUREID). +; +; Note that the Y coordinate of the sprite (in [k#SPRITESTATEDATA1_YPIXELS]) +; is one of the following 9 values when the sprite is aligned with the grid: +; $fc, $0c, $1c, $2c, ..., $7c. +; The reason that 4 is added below to the coordinate is to make it align with a +; multiple of $10 to make comparisons easier. +DetectCollisionBetweenSprites: + ; nop + + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] + ld l, a + + ld a, [hl] ; a = [i#SPRITESTATEDATA1_PICTUREID] (0 if slot is unused) + and a ; is this sprite slot slot used? + ret z ; return if not used + + ld a, l + add 3 + ld l, a + + ld a, [hli] ; a = [i#SPRITESTATEDATA1_YSTEPVECTOR] (-1, 0, or 1) + call SetSpriteCollisionValues + + ld a, [hli] ; a = [i#SPRITESTATEDATA1_YPIXELS] + add 4 ; align with multiple of $10 + +; The effect of the following 3 lines is to +; add 7 to a if moving south or +; subtract 7 from a if moving north. + add b + and $f0 + or c + + ldh [hFF90], a ; store Y coordinate adjusted for direction of movement + + ld a, [hli] ; a = [i#SPRITESTATEDATA1_XSTEPVECTOR] (-1, 0, or 1) + call SetSpriteCollisionValues + ld a, [hl] ; a = [i#SPRITESTATEDATA1_XPIXELS] + +; The effect of the following 3 lines is to +; add 7 to a if moving east or +; subtract 7 from a if moving west. + add b + and $f0 + or c + + ldh [hFF91], a ; store X coordinate adjusted for direction of movement + + ld a, l + add 7 + ld l, a + + xor a + ld [hld], a ; zero [i#SPRITESTATEDATA1_0D] XXX what's this for? + ld [hld], a ; zero [i#SPRITESTATEDATA1_COLLISIONDATA] + + ldh a, [hFF91] + ld [hld], a ; [i#SPRITESTATEDATA1_XADJUSTED] + ldh a, [hFF90] + ld [hl], a ; [i#SPRITESTATEDATA1_YADJUSTED] + + xor a ; zero the loop counter + +.loop + ldh [hFF8F], a ; store loop counter + swap a + ld e, a + ldh a, [hCurrentSpriteOffset] + cp e ; does the loop sprite match the current sprite? + jp z, .next ; go to the next sprite if they match + + ld d, h + ld a, [de] ; a = [j#SPRITESTATEDATA1_PICTUREID] (0 if slot is unused) + and a ; is this sprite slot slot used? + jp z, .next ; go the next sprite if not used + + inc e + inc e + ld a, [de] ; a = [j#SPRITESTATEDATA1_IMAGEINDEX] ($ff means the sprite is offscreen) + inc a + jp z, .next ; go the next sprite if offscreen + + ldh a, [hCurrentSpriteOffset] + add 10 + ld l, a + + inc e + ld a, [de] ; a = [j#SPRITESTATEDATA1_YSTEPVECTOR] + call SetSpriteCollisionValues + + inc e + ld a, [de] ; a = [j#SPRITESTATEDATA1_YPIXELS] + add 4 ; align with multiple of $10 + +; The effect of the following 3 lines is to +; add 7 to a if moving south or +; subtract 7 from a if moving north. + add b + and $f0 + or c + + sub [hl] ; subtract [i#SPRITESTATEDATA1_YADJUSTED] from [j#SPRITESTATEDATA1_YADJUSTED] + +; calculate the absolute value of the difference to get the distance + jr nc, .noCarry1 + cpl + inc a +.noCarry1 + ldh [hFF90], a ; store the distance between the two sprites' adjusted Y values + +; Use the carry flag set by the above subtraction to determine which sprite's +; Y coordinate is larger. This information is used later to set +; [i#SPRITESTATEDATA1_COLLISIONDATA]. +; The following 5 lines set the lowest 2 bits of c, which are later shifted left by 2. +; If sprite i's Y is larger, set lowest 2 bits of c to 10. +; If sprite j's Y is larger or both are equal, set lowest 2 bits of c to 01. + push af + rl c + pop af + ccf + rl c + +; If sprite i's delta Y is 0, then b = 7, else b = 9. + ld b, 7 + ld a, [hl] ; a = [i#SPRITESTATEDATA1_YADJUSTED] + and $f + jr z, .next1 + ld b, 9 + +.next1 + ldh a, [hFF90] ; a = distance between adjusted Y coordinates + sub b + ldh [hFF92], a ; store distance adjusted using sprite i's direction + ld a, b + ldh [hFF90], a ; store 7 or 9 depending on sprite i's delta Y + jr c, .checkXDistance + +; If sprite j's delta Y is 0, then b = 7, else b = 9. + ld b, 7 + dec e + ld a, [de] ; a = [j#SPRITESTATEDATA1_YSTEPVECTOR] + inc e + and a + jr z, .next2 + ld b, 9 + +.next2 + ldh a, [hFF92] ; a = distance adjusted using sprite i's direction + sub b ; adjust distance using sprite j's direction + jr z, .checkXDistance + jr nc, .next ; go to next sprite if distance is still positive after both adjustments + +.checkXDistance + inc e + inc l + ld a, [de] ; a = [j#SPRITESTATEDATA1_XSTEPVECTOR] + + push bc + + call SetSpriteCollisionValues + inc e + ld a, [de] ; a = [j#SPRITESTATEDATA1_XPIXELS] + +; The effect of the following 3 lines is to +; add 7 to a if moving east or +; subtract 7 from a if moving west. + add b + and $f0 + or c + + pop bc + + sub [hl] ; subtract [i#SPRITESTATEDATA1_XADJUSTED] from [j#SPRITESTATEDATA1_XADJUSTED] + +; calculate the absolute value of the difference to get the distance + jr nc, .noCarry2 + cpl + inc a +.noCarry2 + ldh [hFF91], a ; store the distance between the two sprites' adjusted X values + +; Use the carry flag set by the above subtraction to determine which sprite's +; X coordinate is larger. This information is used later to set +; [i#SPRITESTATEDATA1_COLLISIONDATA]. +; The following 5 lines set the lowest 2 bits of c. +; If sprite i's X is larger, set lowest 2 bits of c to 10. +; If sprite j's X is larger or both are equal, set lowest 2 bits of c to 01. + push af + rl c + pop af + ccf + rl c + +; If sprite i's delta X is 0, then b = 7, else b = 9. + ld b, 7 + ld a, [hl] ; a = [i#SPRITESTATEDATA1_XADJUSTED] + and $f + jr z, .next3 + ld b, 9 + +.next3 + ldh a, [hFF91] ; a = distance between adjusted X coordinates + sub b + ldh [hFF92], a ; store distance adjusted using sprite i's direction + ld a, b + ldh [hFF91], a ; store 7 or 9 depending on sprite i's delta X + jr c, .collision + +; If sprite j's delta X is 0, then b = 7, else b = 9. + ld b, 7 + dec e + ld a, [de] ; a = [j#SPRITESTATEDATA1_XSTEPVECTOR] + inc e + and a + jr z, .next4 + ld b, 9 + +.next4 + ldh a, [hFF92] ; a = distance adjusted using sprite i's direction + sub b ; adjust distance using sprite j's direction + jr z, .collision + jr nc, .next ; go to next sprite if distance is still positive after both adjustments + +.collision + ld a, l + and $f0 ; collision with pikachu? + jr nz, .asm_4cd9 + xor a + ld [wd434], a + ldh a, [hFF8F] + cp $f + jr nz, .asm_4cd9 + call Func_4d0a + jr .asm_4cef +.asm_4cd9 + ldh a, [hFF91] ; a = 7 or 9 depending on sprite i's delta X + ld b, a + ldh a, [hFF90] ; a = 7 or 9 depending on sprite i's delta Y + inc l + +; If delta X isn't 0 and delta Y is 0, then b = %0011, else b = %1100. +; (note that normally if delta X isn't 0, then delta Y must be 0 and vice versa) + cp b + jr c, .next5 + ld b, %1100 + jr .next6 +.next5 + ld b, %0011 + +.next6 + ld a, c ; c has 2 bits set (one of bits 0-1 is set for the X axis and one of bits 2-3 for the Y axis) + and b ; we select either the bit in bits 0-1 or bits 2-3 based on the calculation immediately above + or [hl] ; or with existing collision direction bits in [i#SPRITESTATEDATA1_COLLISIONDATA] + ld [hl], a ; store new value + ld a, c ; useless code because a is overwritten before being used again + +; set bit in [i#SPRITESTATEDATA1_0E] or [i#SPRITESTATEDATA1_0F] +; to indicate which sprite the collision occurred with + inc l + inc l +.asm_4cef + ldh a, [hFF8F] ; a = loop counter + ld de, SpriteCollisionBitTable + add a + add e + ld e, a + jr nc, .noCarry3 + inc d +.noCarry3 + ld a, [de] + or [hl] + ld [hli], a + inc de + ld a, [de] + or [hl] + ld [hl], a + +.next + ldh a, [hFF8F] ; a = loop counter + inc a + cp $10 + jp nz, .loop + ret + +; takes delta X or delta Y in a +; b = delta X/Y +; c = 0 if delta X/Y is 0 +; c = 7 if delta X/Y is 1 +; c = 9 if delta X/Y is -1 +Func_4d0a: + ldh a, [hFF91] + ld b, a + ldh a, [hFF90] + inc l + cp b + jr c, .asm_4d17 + ld b, %1100 + jr .asm_4d19 +.asm_4d17 + ld b, %11 +.asm_4d19 + ld a, c + and b + ld [wd434], a + ld a, c + inc l + inc l + ret + +SetSpriteCollisionValues: + and a + ld b, 0 + ld c, 0 + jr z, .done + ld c, 9 + cp -1 + jr z, .ok + ld c, 7 + ld a, 0 +.ok + ld b, a +.done + ret + +SpriteCollisionBitTable: + db %00000000,%00000001 + db %00000000,%00000010 + db %00000000,%00000100 + db %00000000,%00001000 + db %00000000,%00010000 + db %00000000,%00100000 + db %00000000,%01000000 + db %00000000,%10000000 + db %00000001,%00000000 + db %00000010,%00000000 + db %00000100,%00000000 + db %00001000,%00000000 + db %00010000,%00000000 + db %00100000,%00000000 + db %01000000,%00000000 + db %10000000,%00000000 diff --git a/engine/overworld/ssanne.asm b/engine/overworld/ssanne.asm deleted file mode 100755 index cf3b1284..00000000 --- a/engine/overworld/ssanne.asm +++ /dev/null @@ -1,95 +0,0 @@ -AnimateBoulderDust: - ld a, $1 - ld [wWhichAnimationOffsets], a ; select the boulder dust offsets - ld a, [wUpdateSpritesEnabled] - push af - ld a, $ff - ld [wUpdateSpritesEnabled], a - ld a, %11100100 - ld [rOBP1], a - call UpdateGBCPal_OBP1 - call LoadSmokeTileFourTimes - callba WriteCutOrBoulderDustAnimationOAMBlock - ld c, 8 ; number of steps in animation -.loop - push bc - call GetMoveBoulderDustFunctionPointer - ld bc, .returnAddress - push bc - ld c, 4 - jp hl -.returnAddress - ld a, [rOBP1] - xor %01100100 - ld [rOBP1], a - call UpdateGBCPal_OBP1 - call Delay3 - pop bc - dec c - jr nz, .loop - pop af - ld [wUpdateSpritesEnabled], a - jp LoadPlayerSpriteGraphics - -GetMoveBoulderDustFunctionPointer: - ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction - ld hl, MoveBoulderDustFunctionPointerTable - ld c, a - ld b, $0 - add hl, bc - ld a, [hli] - ld [wCoordAdjustmentAmount], a - ld a, [hli] - ld e, a - ld a, [hli] - ld h, [hl] - ld l, a - push hl - ld hl, wOAMBuffer + $90 - ld d, $0 - add hl, de - ld e, l - ld d, h - pop hl - ret - -MoveBoulderDustFunctionPointerTable: -; facing down - db $FF,$00 - dw AdjustOAMBlockYPos - -; facing up - db $01,$00 - dw AdjustOAMBlockYPos - -; facing left - db $01,$01 - dw AdjustOAMBlockXPos - -; facing right - db $FF,$01 - dw AdjustOAMBlockXPos - -LoadSmokeTileFourTimes: - ld hl, vChars1 + $7c0 - ld c, $4 -.loop - push bc - push hl - call LoadSmokeTile - pop hl - ld bc, $10 - add hl, bc - pop bc - dec c - jr nz, .loop - ret - -LoadSmokeTile: - ld de, SSAnneSmokePuffTile - lb bc, BANK(SSAnneSmokePuffTile), (SSAnneSmokePuffTileEnd - SSAnneSmokePuffTile) / $10 - jp CopyVideoData - -SSAnneSmokePuffTile: - INCBIN "gfx/ss_anne_smoke_puff.2bpp" -SSAnneSmokePuffTileEnd: diff --git a/engine/overworld/tileset_header.asm b/engine/overworld/tileset_header.asm deleted file mode 100644 index 05061651..00000000 --- a/engine/overworld/tileset_header.asm +++ /dev/null @@ -1,51 +0,0 @@ -LoadTilesetHeader: - call GetPredefRegisters - push hl - ld d, 0 - ld a, [wCurMapTileset] - add a - add a - ld e, a - ld hl, Tilesets - add hl, de - add hl, de - add hl, de - ld de, wTilesetBank - ld bc, $b - call CopyData - ld a, [hl] - ld [hTilesetType], a - xor a - ld [$ffd8], a - pop hl - ld a, [wCurMapTileset] - push hl - push de - ld hl, DungeonTilesets - ld de, $1 - call IsInArray - pop de - pop hl - jr c, .notDungeonTileset - ld a, [wCurMapTileset] - ld b, a - ld a, [hPreviousTileset] - cp b - jr z, .done -.notDungeonTileset - ld a, [wDestinationWarpID] - cp $ff - jr z, .done - call LoadDestinationWarpPosition - ld a, [wYCoord] - and $1 - ld [wYBlockCoord], a - ld a, [wXCoord] - and $1 - ld [wXBlockCoord], a -.done - ret - -INCLUDE "data/dungeon_tilesets.asm" - -INCLUDE "data/tileset_headers.asm" diff --git a/engine/overworld/tilesets.asm b/engine/overworld/tilesets.asm new file mode 100644 index 00000000..686fa50c --- /dev/null +++ b/engine/overworld/tilesets.asm @@ -0,0 +1,51 @@ +LoadTilesetHeader: + call GetPredefRegisters + push hl + ld d, 0 + ld a, [wCurMapTileset] + add a + add a + ld e, a + ld hl, Tilesets + add hl, de + add hl, de + add hl, de + ld de, wTilesetBank + ld bc, $b + call CopyData + ld a, [hl] + ldh [hTilesetType], a + xor a + ldh [hMovingBGTilesCounter1], a + pop hl + ld a, [wCurMapTileset] + push hl + push de + ld hl, DungeonTilesets + ld de, $1 + call IsInArray + pop de + pop hl + jr c, .notDungeonTileset + ld a, [wCurMapTileset] + ld b, a + ldh a, [hPreviousTileset] + cp b + jr z, .done +.notDungeonTileset + ld a, [wDestinationWarpID] + cp $ff + jr z, .done + call LoadDestinationWarpPosition + ld a, [wYCoord] + and $1 + ld [wYBlockCoord], a + ld a, [wXCoord] + and $1 + ld [wXBlockCoord], a +.done + ret + +INCLUDE "data/tilesets/dungeon_tilesets.asm" + +INCLUDE "data/tilesets/tileset_headers.asm" diff --git a/engine/overworld/trainer_sight.asm b/engine/overworld/trainer_sight.asm new file mode 100755 index 00000000..816dea7f --- /dev/null +++ b/engine/overworld/trainer_sight.asm @@ -0,0 +1,349 @@ +_GetSpritePosition1:: + ld hl, wSpriteStateData1 + ld de, SPRITESTATEDATA1_YPIXELS + ld a, [wSpriteIndex] + ldh [hSpriteIndex], a + call GetSpriteDataPointer + ld a, [hli] ; x#SPRITESTATEDATA1_YPIXELS + ldh [hSpriteScreenYCoord], a + inc hl + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS + ldh [hSpriteScreenXCoord], a + ld de, wSpritePlayerStateData2MapY - wSpritePlayerStateData1XPixels + add hl, de + ld a, [hli] ; x#SPRITESTATEDATA2_MAPY + ldh [hSpriteMapYCoord], a + ld a, [hl] ; x#SPRITESTATEDATA2_MAPX + ldh [hSpriteMapXCoord], a + ret + +_GetSpritePosition2:: + ld hl, wSpriteStateData1 + ld de, SPRITESTATEDATA1_YPIXELS + ld a, [wSpriteIndex] + ldh [hSpriteIndex], a + call GetSpriteDataPointer + ld a, [hli] ; x#SPRITESTATEDATA1_YPIXELS + ld [wSavedSpriteScreenY], a + inc hl + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS + ld [wSavedSpriteScreenX], a + ld de, wSpritePlayerStateData2MapY - wSpritePlayerStateData1XPixels + add hl, de + ld a, [hli] ; x#SPRITESTATEDATA2_MAPY + ld [wSavedSpriteMapY], a + ld a, [hl] ; x#SPRITESTATEDATA2_MAPX + ld [wSavedSpriteMapX], a + ret + +_SetSpritePosition1:: + ld hl, wSpriteStateData1 + ld de, SPRITESTATEDATA1_YPIXELS + ld a, [wSpriteIndex] + ldh [hSpriteIndex], a + call GetSpriteDataPointer + ldh a, [hSpriteScreenYCoord] ; x#SPRITESTATEDATA1_YPIXELS + ld [hli], a + inc hl + ldh a, [hSpriteScreenXCoord] ; x#SPRITESTATEDATA1_XPIXELS + ld [hl], a + ld de, wSpritePlayerStateData2MapY - wSpritePlayerStateData1XPixels + add hl, de + ldh a, [hSpriteMapYCoord] ; x#SPRITESTATEDATA2_MAPY + ld [hli], a + ldh a, [hSpriteMapXCoord] ; x#SPRITESTATEDATA2_MAPX + ld [hl], a + ret + +_SetSpritePosition2:: + ld hl, wSpriteStateData1 + ld de, SPRITESTATEDATA1_YPIXELS + ld a, [wSpriteIndex] + ldh [hSpriteIndex], a + call GetSpriteDataPointer + ld a, [wSavedSpriteScreenY] + ld [hli], a ; x#SPRITESTATEDATA1_YPIXELS + inc hl + ld a, [wSavedSpriteScreenX] + ld [hl], a ; x#SPRITESTATEDATA1_XPIXELS + ld de, wSpritePlayerStateData2MapY - wSpritePlayerStateData1XPixels + add hl, de + ld a, [wSavedSpriteMapY] + ld [hli], a ; x#SPRITESTATEDATA2_MAPY + ld a, [wSavedSpriteMapX] + ld [hl], a ; x#SPRITESTATEDATA2_MAPX + ret + +TrainerWalkUpToPlayer:: + ld a, [wSpriteIndex] + swap a + ld [wTrainerSpriteOffset], a + call ReadTrainerScreenPosition + ld a, [wTrainerFacingDirection] + and a ; SPRITE_FACING_DOWN + jr z, .facingDown + cp SPRITE_FACING_UP + jr z, .facingUp + cp SPRITE_FACING_LEFT + jr z, .facingLeft + jr .facingRight +.facingDown + ld a, [wTrainerScreenY] + ld b, a + ld a, $3c ; (fixed) player screen Y pos + call CalcDifference + cp $10 ; trainer is right above player + ret z + swap a + dec a + ld c, a ; bc = steps yet to go to reach player + xor a + ld b, a ; a = direction to go to + jr .writeWalkScript +.facingUp + ld a, [wTrainerScreenY] + ld b, a + ld a, $3c ; (fixed) player screen Y pos + call CalcDifference + cp $10 ; trainer is right below player + ret z + swap a + dec a + ld c, a ; bc = steps yet to go to reach player + ld b, $0 + ld a, $40 ; a = direction to go to + jr .writeWalkScript +.facingRight + ld a, [wTrainerScreenX] + ld b, a + ld a, $40 ; (fixed) player screen X pos + call CalcDifference + cp $10 ; trainer is directly left of player + ret z + swap a + dec a + ld c, a ; bc = steps yet to go to reach player + ld b, $0 + ld a, $c0 ; a = direction to go to + jr .writeWalkScript +.facingLeft + ld a, [wTrainerScreenX] + ld b, a + ld a, $40 ; (fixed) player screen X pos + call CalcDifference + cp $10 ; trainer is directly right of player + ret z + swap a + dec a + ld c, a ; bc = steps yet to go to reach player + ld b, $0 + ld a, $80 ; a = direction to go to +.writeWalkScript + ld hl, wNPCMovementDirections2 + ld de, wNPCMovementDirections2 + call FillMemory ; write the necessary steps to reach player + ld [hl], $ff ; write end of list sentinel + ld a, [wSpriteIndex] + ldh [hSpriteIndex], a + jp MoveSprite_ + +; input: de = offset within sprite entry +; output: hl = pointer to sprite data +GetSpriteDataPointer: + push de + add hl, de + ldh a, [hSpriteIndex] + swap a + ld d, $0 + ld e, a + add hl, de + pop de + ret + +; tests if this trainer is in the right position to engage the player and do so if she is. +TrainerEngage: + push hl + push de + ld a, [wTrainerSpriteOffset] + add SPRITESTATEDATA1_IMAGEINDEX + ld d, $0 + ld e, a + ld hl, wSpriteStateData1 + add hl, de + ld a, [hl] ; x#SPRITESTATEDATA1_IMAGEINDEX + sub $ff + jr nz, .spriteOnScreen ; test if sprite is on screen + jp .noEngage +.spriteOnScreen + ld a, [wTrainerSpriteOffset] + add SPRITESTATEDATA1_FACINGDIRECTION + ld d, $0 + ld e, a + ld hl, wSpriteStateData1 + add hl, de + ld a, [hl] ; x#SPRITESTATEDATA1_FACINGDIRECTION + ld [wTrainerFacingDirection], a + call ReadTrainerScreenPosition + ld a, [wTrainerScreenY] ; sprite screen Y pos + ld b, a + ld a, $3c + cp b + jr z, .linedUpY + ld a, [wTrainerScreenX] ; sprite screen X pos + ld b, a + ld a, $40 + cp b + jr z, .linedUpX + xor a + jp .noEngage +.linedUpY + ld a, [wTrainerScreenX] ; sprite screen X pos + ld b, a + ld a, $40 ; (fixed) player X position + call CalcDifference ; calc distance + jr z, .noEngage ; exact same position as player + call CheckSpriteCanSeePlayer + jr c, .engage + xor a + jr .noEngage +.linedUpX + ld a, [wTrainerScreenY] ; sprite screen Y pos + ld b, a + ld a, $3c ; (fixed) player Y position + call CalcDifference ; calc distance + jr z, .noEngage ; exact same position as player + call CheckSpriteCanSeePlayer + jr c, .engage + xor a + jp .noEngage +.engage + call CheckPlayerIsInFrontOfSprite + ld a, [wTrainerSpriteOffset] + and a + jr z, .noEngage + ld hl, wFlags_0xcd60 + set 0, [hl] + call EngageMapTrainer + ld a, $ff +.noEngage + ld [wTrainerSpriteOffset], a + pop de + pop hl + ret + +; reads trainer's Y position to wTrainerScreenY and X position to wTrainerScreenX +ReadTrainerScreenPosition: + ld a, [wTrainerSpriteOffset] + add SPRITESTATEDATA1_YPIXELS + ld d, $0 + ld e, a + ld hl, wSpriteStateData1 + add hl, de + ld a, [hl] ; x#SPRITESTATEDATA1_YPIXELS + ld [wTrainerScreenY], a + ld a, [wTrainerSpriteOffset] + add SPRITESTATEDATA1_XPIXELS + ld d, $0 + ld e, a + ld hl, wSpriteStateData1 + add hl, de + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS + ld [wTrainerScreenX], a + ret + +; checks if the sprite is properly lined up with the player with respect to the direction it's looking. Also checks the distance between player and sprite +; note that this does not necessarily mean the sprite is seeing the player, he could be behind it's back +; a: distance player to sprite +CheckSpriteCanSeePlayer: + ld b, a + ld a, [wTrainerEngageDistance] ; how far the trainer can see + cp b + jr nc, .checkIfLinedUp + jr .notInLine ; player too far away +.checkIfLinedUp + ld a, [wTrainerFacingDirection] ; sprite facing direction + cp SPRITE_FACING_DOWN + jr z, .checkXCoord + cp SPRITE_FACING_UP + jr z, .checkXCoord + cp SPRITE_FACING_LEFT + jr z, .checkYCoord + cp SPRITE_FACING_RIGHT + jr z, .checkYCoord + jr .notInLine +.checkXCoord + ld a, [wTrainerScreenX] ; sprite screen X position + ld b, a + cp $40 + jr z, .inLine + jr .notInLine +.checkYCoord + ld a, [wTrainerScreenY] ; sprite screen Y position + ld b, a + cp $3c + jr nz, .notInLine +.inLine + scf + ret +.notInLine + and a + ret + +; tests if the player is in front of the sprite (rather than behind it) +CheckPlayerIsInFrontOfSprite: + ld a, [wCurMap] + cp POWER_PLANT + jp z, .engage ; bypass this for power plant to get voltorb fake items to work + ld a, [wTrainerSpriteOffset] + add SPRITESTATEDATA1_YPIXELS + ld d, $0 + ld e, a + ld hl, wSpriteStateData1 + add hl, de + ld a, [hl] ; x#SPRITESTATEDATA1_YPIXELS + cp $fc + jr nz, .notOnTopmostTile ; special case if sprite is on topmost tile (Y = $fc (-4)), make it come down a block + ld a, $c +.notOnTopmostTile + ld [wTrainerScreenY], a + ld a, [wTrainerSpriteOffset] + add SPRITESTATEDATA1_XPIXELS + ld d, $0 + ld e, a + ld hl, wSpriteStateData1 + add hl, de + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS + ld [wTrainerScreenX], a + ld a, [wTrainerFacingDirection] ; facing direction + cp SPRITE_FACING_DOWN + jr nz, .notFacingDown + ld a, [wTrainerScreenY] ; sprite screen Y pos + cp $3c + jr c, .engage ; sprite above player + jr .noEngage ; sprite below player +.notFacingDown + cp SPRITE_FACING_UP + jr nz, .notFacingUp + ld a, [wTrainerScreenY] ; sprite screen Y pos + cp $3c + jr nc, .engage ; sprite below player + jr .noEngage ; sprite above player +.notFacingUp + cp SPRITE_FACING_LEFT + jr nz, .notFacingLeft + ld a, [wTrainerScreenX] ; sprite screen X pos + cp $40 + jr nc, .engage ; sprite right of player + jr .noEngage ; sprite left of player +.notFacingLeft + ld a, [wTrainerScreenX] ; sprite screen X pos + cp $40 + jr nc, .noEngage ; sprite right of player +.engage + ld a, $ff + jr .done +.noEngage + xor a +.done + ld [wTrainerSpriteOffset], a + ret diff --git a/engine/overworld/trainers.asm b/engine/overworld/trainers.asm deleted file mode 100755 index 655c6b2a..00000000 --- a/engine/overworld/trainers.asm +++ /dev/null @@ -1,349 +0,0 @@ -_GetSpritePosition1: - ld hl, wSpriteStateData1 - ld de, $4 - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - call GetSpriteDataPointer - ld a, [hli] ; c1x4 (screen Y pos) - ld [$ffeb], a - inc hl - ld a, [hl] ; c1x6 (screen X pos) - ld [$ffec], a - ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6) - add hl, de - ld a, [hli] ; c2x4 (map Y pos) - ld [$ffed], a - ld a, [hl] ; c2x5 (map X pos) - ld [$ffee], a - ret - -_GetSpritePosition2: - ld hl, wSpriteStateData1 - ld de, $4 - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - call GetSpriteDataPointer - ld a, [hli] ; c1x4 (screen Y pos) - ld [wSavedSpriteScreenY], a - inc hl - ld a, [hl] ; c1x6 (screen X pos) - ld [wSavedSpriteScreenX], a - ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6) - add hl, de - ld a, [hli] ; c2x4 (map Y pos) - ld [wSavedSpriteMapY], a - ld a, [hl] ; c2x5 (map X pos) - ld [wSavedSpriteMapX], a - ret - -_SetSpritePosition1: - ld hl, wSpriteStateData1 - ld de, $4 - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - call GetSpriteDataPointer - ld a, [$ffeb] ; c1x4 (screen Y pos) - ld [hli], a - inc hl - ld a, [$ffec] ; c1x6 (screen X pos) - ld [hl], a - ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6) - add hl, de - ld a, [$ffed] ; c2x4 (map Y pos) - ld [hli], a - ld a, [$ffee] ; c2x5 (map X pos) - ld [hl], a - ret - -_SetSpritePosition2: - ld hl, wSpriteStateData1 - ld de, 4 - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - call GetSpriteDataPointer - ld a, [wSavedSpriteScreenY] - ld [hli], a ; c1x4 (screen Y pos) - inc hl - ld a, [wSavedSpriteScreenX] - ld [hl], a ; c1x6 (screen X pos) - ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6) - add hl, de - ld a, [wSavedSpriteMapY] - ld [hli], a ; c2x4 (map Y pos) - ld a, [wSavedSpriteMapX] - ld [hl], a ; c2x5 (map X pos) - ret - -TrainerWalkUpToPlayer: - ld a, [wSpriteIndex] - swap a - ld [wTrainerSpriteOffset], a - call ReadTrainerScreenPosition - ld a, [wTrainerFacingDirection] - and a ; SPRITE_FACING_DOWN - jr z, .facingDown - cp SPRITE_FACING_UP - jr z, .facingUp - cp SPRITE_FACING_LEFT - jr z, .facingLeft - jr .facingRight -.facingDown - ld a, [wTrainerScreenY] - ld b, a - ld a, $3c ; (fixed) player screen Y pos - call CalcDifference - cp $10 ; trainer is right above player - ret z - swap a - dec a - ld c, a ; bc = steps yet to go to reach player - xor a - ld b, a ; a = direction to go to - jr .writeWalkScript -.facingUp - ld a, [wTrainerScreenY] - ld b, a - ld a, $3c ; (fixed) player screen Y pos - call CalcDifference - cp $10 ; trainer is right below player - ret z - swap a - dec a - ld c, a ; bc = steps yet to go to reach player - ld b, $0 - ld a, $40 ; a = direction to go to - jr .writeWalkScript -.facingRight - ld a, [wTrainerScreenX] - ld b, a - ld a, $40 ; (fixed) player screen X pos - call CalcDifference - cp $10 ; trainer is directly left of player - ret z - swap a - dec a - ld c, a ; bc = steps yet to go to reach player - ld b, $0 - ld a, $c0 ; a = direction to go to - jr .writeWalkScript -.facingLeft - ld a, [wTrainerScreenX] - ld b, a - ld a, $40 ; (fixed) player screen X pos - call CalcDifference - cp $10 ; trainer is directly right of player - ret z - swap a - dec a - ld c, a ; bc = steps yet to go to reach player - ld b, $0 - ld a, $80 ; a = direction to go to -.writeWalkScript - ld hl, wNPCMovementDirections2 - ld de, wNPCMovementDirections2 - call FillMemory ; write the necessary steps to reach player - ld [hl], $ff ; write end of list sentinel - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - jp MoveSprite_ - -; input: de = offset within sprite entry -; output: hl = pointer to sprite data -GetSpriteDataPointer: - push de - add hl, de - ld a, [H_SPRITEINDEX] - swap a - ld d, $0 - ld e, a - add hl, de - pop de - ret - -; tests if this trainer is in the right position to engage the player and do so if she is. -TrainerEngage: - push hl - push de - ld a, [wTrainerSpriteOffset] - add $2 - ld d, $0 - ld e, a - ld hl, wSpriteStateData1 - add hl, de - ld a, [hl] ; c1x2: sprite image index - sub $ff - jr nz, .spriteOnScreen ; test if sprite is on screen - jp .noEngage -.spriteOnScreen - ld a, [wTrainerSpriteOffset] - add $9 - ld d, $0 - ld e, a - ld hl, wSpriteStateData1 - add hl, de - ld a, [hl] ; c1x9: facing direction - ld [wTrainerFacingDirection], a - call ReadTrainerScreenPosition - ld a, [wTrainerScreenY] ; sprite screen Y pos - ld b, a - ld a, $3c - cp b - jr z, .linedUpY - ld a, [wTrainerScreenX] ; sprite screen X pos - ld b, a - ld a, $40 - cp b - jr z, .linedUpX - xor a - jp .noEngage -.linedUpY - ld a, [wTrainerScreenX] ; sprite screen X pos - ld b, a - ld a, $40 ; (fixed) player X position - call CalcDifference ; calc distance - jr z, .noEngage ; exact same position as player - call CheckSpriteCanSeePlayer - jr c, .engage - xor a - jr .noEngage -.linedUpX - ld a, [wTrainerScreenY] ; sprite screen Y pos - ld b, a - ld a, $3c ; (fixed) player Y position - call CalcDifference ; calc distance - jr z, .noEngage ; exact same position as player - call CheckSpriteCanSeePlayer - jr c, .engage - xor a - jp .noEngage -.engage - call CheckPlayerIsInFrontOfSprite - ld a, [wTrainerSpriteOffset] - and a - jr z, .noEngage - ld hl, wFlags_0xcd60 - set 0, [hl] - call EngageMapTrainer - ld a, $ff -.noEngage - ld [wTrainerSpriteOffset], a - pop de - pop hl - ret - -; reads trainer's Y position to wTrainerScreenY and X position to wTrainerScreenX -ReadTrainerScreenPosition: - ld a, [wTrainerSpriteOffset] - add $4 - ld d, $0 - ld e, a - ld hl, wSpriteStateData1 - add hl, de - ld a, [hl] ; c1x4 (sprite Y pos) - ld [wTrainerScreenY], a - ld a, [wTrainerSpriteOffset] - add $6 - ld d, $0 - ld e, a - ld hl, wSpriteStateData1 - add hl, de - ld a, [hl] ; c1x6 (sprite X pos) - ld [wTrainerScreenX], a - ret - -; checks if the sprite is properly lined up with the player with respect to the direction it's looking. Also checks the distance between player and sprite -; note that this does not necessarily mean the sprite is seeing the player, he could be behind it's back -; a: distance player to sprite -CheckSpriteCanSeePlayer: - ld b, a - ld a, [wTrainerEngageDistance] ; how far the trainer can see - cp b - jr nc, .checkIfLinedUp - jr .notInLine ; player too far away -.checkIfLinedUp - ld a, [wTrainerFacingDirection] ; sprite facing direction - cp SPRITE_FACING_DOWN - jr z, .checkXCoord - cp SPRITE_FACING_UP - jr z, .checkXCoord - cp SPRITE_FACING_LEFT - jr z, .checkYCoord - cp SPRITE_FACING_RIGHT - jr z, .checkYCoord - jr .notInLine -.checkXCoord - ld a, [wTrainerScreenX] ; sprite screen X position - ld b, a - cp $40 - jr z, .inLine - jr .notInLine -.checkYCoord - ld a, [wTrainerScreenY] ; sprite screen Y position - ld b, a - cp $3c - jr nz, .notInLine -.inLine - scf - ret -.notInLine - and a - ret - -; tests if the player is in front of the sprite (rather than behind it) -CheckPlayerIsInFrontOfSprite: - ld a, [wCurMap] - cp POWER_PLANT - jp z, .engage ; bypass this for power plant to get voltorb fake items to work - ld a, [wTrainerSpriteOffset] - add $4 - ld d, $0 - ld e, a - ld hl, wSpriteStateData1 - add hl, de - ld a, [hl] ; c1x4 (sprite screen Y pos) - cp $fc - jr nz, .notOnTopmostTile ; special case if sprite is on topmost tile (Y = $fc (-4)), make it come down a block - ld a, $c -.notOnTopmostTile - ld [wTrainerScreenY], a - ld a, [wTrainerSpriteOffset] - add $6 - ld d, $0 - ld e, a - ld hl, wSpriteStateData1 - add hl, de - ld a, [hl] ; c1x6 (sprite screen X pos) - ld [wTrainerScreenX], a - ld a, [wTrainerFacingDirection] ; facing direction - cp SPRITE_FACING_DOWN - jr nz, .notFacingDown - ld a, [wTrainerScreenY] ; sprite screen Y pos - cp $3c - jr c, .engage ; sprite above player - jr .noEngage ; sprite below player -.notFacingDown - cp SPRITE_FACING_UP - jr nz, .notFacingUp - ld a, [wTrainerScreenY] ; sprite screen Y pos - cp $3c - jr nc, .engage ; sprite below player - jr .noEngage ; sprite above player -.notFacingUp - cp SPRITE_FACING_LEFT - jr nz, .notFacingLeft - ld a, [wTrainerScreenX] ; sprite screen X pos - cp $40 - jr nc, .engage ; sprite right of player - jr .noEngage ; sprite left of player -.notFacingLeft - ld a, [wTrainerScreenX] ; sprite screen X pos - cp $40 - jr nc, .noEngage ; sprite right of player -.engage - ld a, $ff - jr .done -.noEngage - xor a -.done - ld [wTrainerSpriteOffset], a - ret diff --git a/engine/overworld/update_map.asm b/engine/overworld/update_map.asm index 8577b9e7..53a5592d 100644 --- a/engine/overworld/update_map.asm +++ b/engine/overworld/update_map.asm @@ -50,20 +50,20 @@ RedrawMapView: ld a, [wIsInBattle] inc a ret z - ld a, [H_AUTOBGTRANSFERENABLED] + ldh a, [hAutoBGTransferEnabled] push af - ld a, [hTilesetType] + ldh a, [hTilesetType] push af xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld [hTilesetType], a ; no flower/water BG tile animations + ldh [hAutoBGTransferEnabled], a + ldh [hTilesetType], a ; no flower/water BG tile animations call LoadCurrentMapView call RunDefaultPaletteCommand ld hl, wMapViewVRAMPointer ld a, [hli] ld h, [hl] ld l, a - ld de, -2 * 32 + ld de, -2 * BG_MAP_WIDTH add hl, de ld a, h and $3 @@ -73,23 +73,23 @@ RedrawMapView: ld a, h ld [wBuffer + 1], a ; this copy of the address is not used ld a, 2 - ld [$ffbe], a - ld c, 9 ; number of rows of 2x2 tiles (this covers the whole screen) + ldh [hRedrawMapViewRowOffset], a + ld c, SCREEN_HEIGHT / 2 ; number of rows of 2x2 tiles (this covers the whole screen) .redrawRowLoop push bc push hl push hl ld hl, wTileMap - 2 * SCREEN_WIDTH ld de, SCREEN_WIDTH - ld a, [$ffbe] + ldh a, [hRedrawMapViewRowOffset] .calcWRAMAddrLoop add hl, de dec a jr nz, .calcWRAMAddrLoop call CopyToRedrawRowOrColumnSrcTiles pop hl - ld de, $20 - ld a, [$ffbe] + ld de, BG_MAP_WIDTH + ldh a, [hRedrawMapViewRowOffset] ld c, a .calcVRAMAddrLoop add hl, de @@ -98,13 +98,13 @@ RedrawMapView: or $98 dec c jr nz, .calcVRAMAddrLoop - ld [hRedrawRowOrColumnDest + 1], a + ldh [hRedrawRowOrColumnDest + 1], a ld a, l - ld [hRedrawRowOrColumnDest], a + ldh [hRedrawRowOrColumnDest], a ld a, REDRAW_ROW - ld [hRedrawRowOrColumnMode], a + ldh [hRedrawRowOrColumnMode], a call DelayFrame - ld hl, $ffbe + ld hl, hRedrawMapViewRowOffset inc [hl] inc [hl] pop hl @@ -112,9 +112,9 @@ RedrawMapView: dec c jr nz, .redrawRowLoop pop af - ld [hTilesetType], a + ldh [hTilesetType], a pop af - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ret CompareHLWithBC: diff --git a/engine/overworld/wild_mons.asm b/engine/overworld/wild_mons.asm index dae57f23..2593e0ec 100644 --- a/engine/overworld/wild_mons.asm +++ b/engine/overworld/wild_mons.asm @@ -1,4 +1,4 @@ -LoadWildData: +LoadWildData:: ld hl, WildDataPointers ld a, [wCurMap] @@ -16,10 +16,10 @@ LoadWildData: jr z, .NoGrassData ; if no grass data, skip to surfing data push hl ld de, wGrassMons ; otherwise, load grass data - ld bc, $0014 + ld bc, $14 call CopyData pop hl - ld bc, $0014 + ld bc, $14 add hl, bc .NoGrassData ld a, [hli] @@ -27,7 +27,7 @@ LoadWildData: and a ret z ; if no water data, we're done ld de, wWaterMons ; otherwise, load surfing data - ld bc, $0014 + ld bc, $14 jp CopyData -INCLUDE "data/wild_mons.asm" +INCLUDE "data/wild/grass_water.asm" -- cgit v1.3.1-sl0p