diff options
Diffstat (limited to 'engine/overworld')
38 files changed, 2763 insertions, 1105 deletions
diff --git a/engine/overworld/cable_club_npc.asm b/engine/overworld/cable_club_npc.asm index bdab41a6..08067412 100755 --- a/engine/overworld/cable_club_npc.asm +++ b/engine/overworld/cable_club_npc.asm @@ -1,15 +1,14 @@ -CableClubNPC: ; 71c5 (1:71c5) +CableClubNPC: ld hl, CableClubNPCWelcomeText call PrintText - ld a, [wd74b] - bit 5, a ; received pokedex? + CheckEvent EVENT_GOT_POKEDEX jp nz, .receivedPokedex ; if the player hasn't received the pokedex - ld c, $3c + ld c, 60 call DelayFrames ld hl, CableClubNPCMakingPreparationsText call PrintText - jp Func_7298 + jp .didNotConnect .receivedPokedex ld a, $1 ld [wMenuJoypadPollCount], a @@ -57,7 +56,7 @@ CableClubNPC: ; 71c5 (1:71c5) jr nz, .choseNo callab SaveSAVtoSRAM call WaitForSoundToFinish - ld a, (SFX_02_5d - SFX_Headers_02) / 3 + ld a, SFX_SAVE call PlaySoundWaitForCurrent ld hl, CableClubNPCPleaseWaitText call PrintText @@ -72,31 +71,29 @@ CableClubNPC: ; 71c5 (1:71c5) ld hl, wUnknownSerialCounter ld a, [hli] inc a - jr nz, Func_72a8 ; 0x726b $3b + jr nz, .connected ld a, [hl] inc a - jr nz, Func_72a8 ; 0x726f $37 - ld b, $a -.asm_7273 + jr nz, .connected + ld b, 10 +.syncLoop call DelayFrame call Serial_SendZeroByte dec b - jr nz, .asm_7273 ; 0x727a $f7 + jr nz, .syncLoop call CloseLinkConnection ld hl, CableClubNPCLinkClosedBecauseOfInactivityText call PrintText - jr Func_7298 ; 0x7285 $11 + jr .didNotConnect .failedToEstablishConnection ld hl, CableClubNPCAreaReservedFor2FriendsLinkedByCableText call PrintText - jr Func_7298 ; 0x728d $9 + jr .didNotConnect .choseNo call CloseLinkConnection ld hl, CableClubNPCPleaseComeAgainText call PrintText - ; fall through - -Func_7298: ; 7298 (1:7298) +.didNotConnect xor a ld hl, wUnknownSerialCounter ld [hli], a @@ -106,44 +103,42 @@ Func_7298: ; 7298 (1:7298) xor a ld [wMenuJoypadPollCount], a ret - -Func_72a8: ; 72a8 (1:72a8) +.connected xor a ld [hld], a ld [hl], a - ld hl, LinkMenu - ld b, BANK(LinkMenu) - jp Bankswitch + jpab LinkMenu -CableClubNPCAreaReservedFor2FriendsLinkedByCableText: ; 72b3 (1:72b3) +CableClubNPCAreaReservedFor2FriendsLinkedByCableText: TX_FAR _CableClubNPCAreaReservedFor2FriendsLinkedByCableText db "@" -CableClubNPCWelcomeText: ; 72b8 (1:72b8) +CableClubNPCWelcomeText: TX_FAR _CableClubNPCWelcomeText db "@" -CableClubNPCPleaseApplyHereHaveToSaveText: ; 72bd (1:72bd) +CableClubNPCPleaseApplyHereHaveToSaveText: TX_FAR _CableClubNPCPleaseApplyHereHaveToSaveText db "@" -CableClubNPCPleaseWaitText: ; 72c2 (1:72c2) +CableClubNPCPleaseWaitText: TX_FAR _CableClubNPCPleaseWaitText - db $a, "@" + TX_DELAY + db "@" -CableClubNPCLinkClosedBecauseOfInactivityText: ; 72c8 (1:72c8) +CableClubNPCLinkClosedBecauseOfInactivityText: TX_FAR _CableClubNPCLinkClosedBecauseOfInactivityText db "@" -CableClubNPCPleaseComeAgainText: ; 72cd (1:72cd) +CableClubNPCPleaseComeAgainText: TX_FAR _CableClubNPCPleaseComeAgainText db "@" -CableClubNPCMakingPreparationsText: ; 72d2 (1:72d2) +CableClubNPCMakingPreparationsText: TX_FAR _CableClubNPCMakingPreparationsText db "@" -CloseLinkConnection: ; 72d7 (1:72d7) +CloseLinkConnection: call Delay3 ld a, CONNECTION_NOT_ESTABLISHED ld [hSerialConnectionStatus], a diff --git a/engine/overworld/card_key.asm b/engine/overworld/card_key.asm index c4df0d51..35495c82 100755 --- a/engine/overworld/card_key.asm +++ b/engine/overworld/card_key.asm @@ -1,6 +1,6 @@ -PrintCardKeyText: ; 52673 (14:6673) +PrintCardKeyText: ld hl, SilphCoMapList - ld a, [W_CURMAP] + ld a, [wCurMap] ld b, a .silphCoMapListLoop ld a, [hli] @@ -15,7 +15,7 @@ PrintCardKeyText: ; 52673 (14:6673) cp $24 jr z, .cardKeyDoorInFrontOfPlayer ld b, a - ld a, [W_CURMAP] + ld a, [wCurMap] cp SILPH_CO_11F ret nz ld a, b @@ -27,8 +27,8 @@ PrintCardKeyText: ; 52673 (14:6673) jr z, .noCardKey call GetCoordsInFrontOfPlayer push de - ld a, $1 - ld [H_DOWNARROWBLINKCNT2], a + tx_pre_id CardKeySuccessText + ld [hSpriteIndexOrTextID], a call PrintPredefTextID pop de srl d @@ -39,7 +39,7 @@ PrintCardKeyText: ; 52673 (14:6673) ld a, e ld c, a ld [wCardKeyDoorX], a - ld a, [W_CURMAP] + ld a, [wCurMap] cp SILPH_CO_11F jr nz, .notSilphCo11F ld a, $3 @@ -47,18 +47,18 @@ PrintCardKeyText: ; 52673 (14:6673) .notSilphCo11F ld a, $e .replaceCardKeyDoorTileBlock - ld [wd09f], a + ld [wNewTileBlockID], a predef ReplaceTileBlock - ld hl, wd126 + ld hl, wCurrentMapScriptFlags set 5, [hl] - ld a, (SFX_1f_57 - SFX_Headers_1f) / 3 + ld a, SFX_GO_INSIDE jp PlaySound .noCardKey - ld a, $2 - ld [H_DOWNARROWBLINKCNT2], a + tx_pre_id CardKeyFailText + ld [hSpriteIndexOrTextID], a jp PrintPredefTextID -SilphCoMapList: ; 526e3 (14:66e3) +SilphCoMapList: db SILPH_CO_2F db SILPH_CO_3F db SILPH_CO_4F @@ -71,22 +71,22 @@ SilphCoMapList: ; 526e3 (14:66e3) db SILPH_CO_11F db $FF -CardKeySuccessText: ; 526ee (14:66ee) +CardKeySuccessText: TX_FAR _CardKeySuccessText1 - db $0b + TX_SFX_ITEM_1 TX_FAR _CardKeySuccessText2 db "@" -CardKeyFailText: ; 526f8 (14:66f8) +CardKeyFailText: TX_FAR _CardKeyFailText db "@" ; d = Y ; e = X -GetCoordsInFrontOfPlayer: ; 526fd (14:66fd) - ld a, [W_YCOORD] +GetCoordsInFrontOfPlayer: + ld a, [wYCoord] ld d, a - ld a, [W_XCOORD] + ld a, [wXCoord] ld e, a ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction and a diff --git a/engine/overworld/cinnabar_lab.asm b/engine/overworld/cinnabar_lab.asm index eefa2176..13313746 100755 --- a/engine/overworld/cinnabar_lab.asm +++ b/engine/overworld/cinnabar_lab.asm @@ -1,37 +1,37 @@ -GiveFossilToCinnabarLab: ; 61006 (18:5006) +GiveFossilToCinnabarLab: ld hl, wd730 set 6, [hl] xor a - ld [wCurrentMenuItem], a ; wCurrentMenuItem - ld a, $3 - ld [wMenuWatchedKeys], a ; wMenuWatchedKeys - ld a, [wcd37] + ld [wCurrentMenuItem], a + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, [wFilteredBagItemsCount] dec a - ld [wMaxMenuItem], a ; wMaxMenuItem - ld a, $2 - ld [wTopMenuItemY], a ; wTopMenuItemY - ld a, $1 - ld [wTopMenuItemX], a ; wTopMenuItemX - ld a, [wcd37] + 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 + ld bc, 2 + ld hl, 3 call AddNTimes dec l ld b, l ld c, $d - ld hl, wTileMap + coord hl, 0, 0 call TextBoxBorder call UpdateSprites - call Func_610c2 + call PrintFossilsInBag ld hl, wd730 res 6, [hl] call HandleMenuInput - bit 1, a - jr nz, .asm_610a7 - ld hl, wcc5b - ld a, [wCurrentMenuItem] ; wCurrentMenuItem - ld d, $0 + 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] @@ -48,77 +48,76 @@ GiveFossilToCinnabarLab: ; 61006 (18:5006) .choseDomeFossil ld b, KABUTO .fossilSelected - ld [W_FOSSILITEM], a + ld [wFossilItem], a ld a, b - ld [W_FOSSILMON], a + ld [wFossilMon], a call LoadFossilItemAndMonName ld hl, LabFossil_610ae call PrintText call YesNoChoice - ld a, [wCurrentMenuItem] ; wCurrentMenuItem + ld a, [wCurrentMenuItem] and a - jr nz, .asm_610a7 + jr nz, .cancelledGivingFossil ld hl, LabFossil_610b3 call PrintText - ld a, [W_FOSSILITEM] - ld [$ffdb], a + ld a, [wFossilItem] + ld [hItemToRemoveID], a callba RemoveItemByID ld hl, LabFossil_610b8 call PrintText - ld hl, wd7a3 - set 0, [hl] - set 1, [hl] + SetEvents EVENT_GAVE_FOSSIL_TO_LAB, EVENT_LAB_STILL_REVIVING_FOSSIL ret -.asm_610a7 +.cancelledGivingFossil ld hl, LabFossil_610bd call PrintText ret -LabFossil_610ae: ; 610ae (18:50ae) +LabFossil_610ae: TX_FAR _Lab4Text_610ae db "@" -LabFossil_610b3: ; 610b3 (18:50b3) +LabFossil_610b3: TX_FAR _Lab4Text_610b3 db "@" -LabFossil_610b8: ; 610b8 (18:50b8) +LabFossil_610b8: TX_FAR _Lab4Text_610b8 db "@" -LabFossil_610bd: ; 610bd (18:50bd) +LabFossil_610bd: TX_FAR _Lab4Text_610bd db "@" -Func_610c2: ; 610c2 (18:50c2) - ld hl, wcc5b +PrintFossilsInBag: +; Prints each fossil in the player's bag on a separate line in the menu. + ld hl, wFilteredBagItems xor a - ld [$ffdb], a -.asm_610c8 + ld [hItemCounter], a +.loop ld a, [hli] cp $ff ret z push hl ld [wd11e], a call GetItemName - hlCoord 2, 2 - ld a, [$ffdb] - ld bc, $28 + coord hl, 2, 2 + ld a, [hItemCounter] + ld bc, SCREEN_WIDTH * 2 call AddNTimes ld de, wcd6d call PlaceString - ld hl, $ffdb + ld hl, hItemCounter inc [hl] pop hl - jr .asm_610c8 + jr .loop ; loads the names of the fossil item and the resulting mon -LoadFossilItemAndMonName: ; 610eb (18:50eb) - ld a, [W_FOSSILMON] +LoadFossilItemAndMonName: + ld a, [wFossilMon] ld [wd11e], a call GetMonName call CopyStringToCF4B - ld a, [W_FOSSILITEM] + ld a, [wFossilItem] ld [wd11e], a call GetItemName ret diff --git a/engine/overworld/clear_variables.asm b/engine/overworld/clear_variables.asm new file mode 100644 index 00000000..9a59cc7c --- /dev/null +++ b/engine/overworld/clear_variables.asm @@ -0,0 +1,20 @@ +ClearVariablesOnEnterMap: + ld a, SCREEN_HEIGHT_PIXELS + ld [hWY], a + ld [rWY], a + xor a + ld [H_AUTOBGTRANSFERENABLED], a + ld [wStepCounter], a + ld [wLoneAttackNo], a + ld [hJoyPressed], a + ld [hJoyReleased], a + ld [hJoyHeld], a + ld [wActionResultOrTookBattleTurn], a + ld [wUnusedD5A3], a + ld hl, wCardKeyDoorY + ld [hli], a + ld [hl], a + ld hl, wWhichTrade + ld bc, wStandingOnWarpPadOrHole - wWhichTrade + call FillMemory + ret diff --git a/engine/overworld/cut.asm b/engine/overworld/cut.asm index 7b92bca3..f6ae6468 100755 --- a/engine/overworld/cut.asm +++ b/engine/overworld/cut.asm @@ -1,43 +1,43 @@ -UsedCut: ; ef54 (3:6f54) +UsedCut: xor a - ld [wcd6a], a - ld a, [W_CURMAPTILESET] ; W_CURMAPTILESET + ld [wActionResultOrTookBattleTurn], a ; initialise to failure value + ld a, [wCurMapTileset] and a ; OVERWORLD - jr z, .asm_ef6b + jr z, .overworld cp GYM - jr nz, .asm_ef77 + jr nz, .nothingToCut ld a, [wTileInFrontOfPlayer] cp $50 ; gym cut tree - jr nz, .asm_ef77 - jr asm_ef82 -.asm_ef6b + jr nz, .nothingToCut + jr .canCut +.overworld dec a ld a, [wTileInFrontOfPlayer] cp $3d ; cut tree - jr z, asm_ef82 + jr z, .canCut cp $52 ; grass - jr z, asm_ef82 -.asm_ef77 - ld hl, NothingToCutText + jr z, .canCut +.nothingToCut + ld hl, .NothingToCutText jp PrintText -NothingToCutText: ; ef7d (3:6f7d) +.NothingToCutText TX_FAR _NothingToCutText db "@" -asm_ef82: ; ef82 (3:6f82) - ld [wcd4d], a - ld a, $1 - ld [wcd6a], a - ld a, [wWhichPokemon] ; wWhichPokemon - ld hl, wPartyMonNicks ; wPartyMonNicks +.canCut + ld [wCutTile], a + ld a, 1 + ld [wActionResultOrTookBattleTurn], a ; used cut + ld a, [wWhichPokemon] + ld hl, wPartyMonNicks call GetPartyMonName ld hl, wd730 set 6, [hl] call GBPalWhiteOutWithDelay3 call ClearSprites call RestoreScreenTilesAndReloadTilePatterns - ld a, $90 + ld a, SCREEN_HEIGHT_PIXELS ld [hWY], a call Delay3 call LoadGBPal @@ -53,79 +53,80 @@ asm_ef82: ; ef82 (3:6f82) res 6, [hl] ld a, $ff ld [wUpdateSpritesEnabled], a - call AnimateCutTree - ld de, CutTreeBlockSwaps ; $7100 - call Func_f09f + call InitCutAnimOAM + ld de, CutTreeBlockSwaps + call ReplaceTreeTileBlock call RedrawMapView - callba Func_79e96 + callba AnimCut ld a, $1 ld [wUpdateSpritesEnabled], a - ld a, (SFX_02_56 - SFX_Headers_02) / 3 + ld a, SFX_CUT call PlaySound ld a, $90 ld [hWY], a call UpdateSprites jp RedrawMapView -UsedCutText: ; eff2 (3:6ff2) +UsedCutText: TX_FAR _UsedCutText db "@" -AnimateCutTree: ; eff7 (3:6ff7) +InitCutAnimOAM: xor a - ld [wcd50], a - ld a, $e4 - ld [rOBP1], a ; $ff49 - ld a, [wcd4d] + ld [wWhichAnimationOffsets], a + ld a, %11100100 + ld [rOBP1], a + ld a, [wCutTile] cp $52 - jr z, .asm_f020 - ld de, Overworld_GFX + $2d0 ; $42d0 ; cuttable tree sprite top row + jr z, .grass +; tree + ld de, Overworld_GFX + $2d0 ; cuttable tree sprite top row ld hl, vChars1 + $7c0 - ld bc, (BANK(Overworld_GFX) << 8) + $02 + lb bc, BANK(Overworld_GFX), $02 call CopyVideoData - ld de, Overworld_GFX + $3d0 ; $43d0 ; cuttable tree sprite bottom row + ld de, Overworld_GFX + $3d0 ; cuttable tree sprite bottom row ld hl, vChars1 + $7e0 - ld bc, (BANK(Overworld_GFX) << 8) + $02 + lb bc, BANK(Overworld_GFX), $02 call CopyVideoData - jr WriteCutTreeBoulderDustAnimationOAMBlock -.asm_f020 + jr WriteCutOrBoulderDustAnimationOAMBlock +.grass ld hl, vChars1 + $7c0 - call LoadCutTreeAnimationTilePattern + call LoadCutGrassAnimationTilePattern ld hl, vChars1 + $7d0 - call LoadCutTreeAnimationTilePattern + call LoadCutGrassAnimationTilePattern ld hl, vChars1 + $7e0 - call LoadCutTreeAnimationTilePattern + call LoadCutGrassAnimationTilePattern ld hl, vChars1 + $7f0 - call LoadCutTreeAnimationTilePattern - call WriteCutTreeBoulderDustAnimationOAMBlock + call LoadCutGrassAnimationTilePattern + call WriteCutOrBoulderDustAnimationOAMBlock ld hl, wOAMBuffer + $93 - ld de, $4 + ld de, 4 ld a, $30 ld c, e -.asm_f044 +.loop ld [hl], a add hl, de xor $60 dec c - jr nz, .asm_f044 + jr nz, .loop ret -LoadCutTreeAnimationTilePattern: ; f04c (3:704c) - ld de, AnimationTileset2 + $60 ; $474e ; tile depicting a leaf - ld bc, (BANK(AnimationTileset2) << 8) + $01 +LoadCutGrassAnimationTilePattern: + ld de, AnimationTileset2 + $60 ; tile depicting a leaf + lb bc, BANK(AnimationTileset2), $01 jp CopyVideoData -WriteCutTreeBoulderDustAnimationOAMBlock: ; f055 (3:7055) - call GetCutTreeBoulderDustAnimationOffsets +WriteCutOrBoulderDustAnimationOAMBlock: + call GetCutOrBoulderDustAnimationOffsets ld a, $9 - ld de, CutTreeBoulderDustAnimationTilesAndAttributes + ld de, CutOrBoulderDustAnimationTilesAndAttributes jp WriteOAMBlock -CutTreeBoulderDustAnimationTilesAndAttributes: ; f060 (3:7060) +CutOrBoulderDustAnimationTilesAndAttributes: db $FC,$10,$FD,$10 db $FE,$10,$FF,$10 -GetCutTreeBoulderDustAnimationOffsets: ; f068 (3:7068) +GetCutOrBoulderDustAnimationOffsets: ld hl, wSpriteStateData1 + 4 ld a, [hli] ; player's sprite screen Y position ld b, a @@ -138,12 +139,12 @@ GetCutTreeBoulderDustAnimationOffsets: ; f068 (3:7068) srl a ld e, a ld d, $0 ; de holds direction (00: down, 02: up, 04: left, 06: right) - ld a, [wcd50] + ld a, [wWhichAnimationOffsets] and a - ld hl, CutTreeAnimationOffsets - jr z, .asm_f084 + ld hl, CutAnimationOffsets + jr z, .next ld hl, BoulderDustAnimationOffsets -.asm_f084 +.next add hl, de ld e, [hl] inc hl @@ -156,14 +157,14 @@ GetCutTreeBoulderDustAnimationOffsets: ; f068 (3:7068) ld c, a ret -CutTreeAnimationOffsets: ; f08f (3:708f) +CutAnimationOffsets: ; Each pair represents the x and y pixels offsets from the player of where the cut tree animation should be drawn db 8, 36 ; player is facing down db 8, 4 ; player is facing up db -8, 20 ; player is facing left db 24, 20 ; player is facing right -BoulderDustAnimationOffsets: ; f097 (3:7097) +BoulderDustAnimationOffsets: ; Each pair represents the x and y pixels offsets from the player of where the cut tree animation should be drawn ; These offsets represent 2 blocks away from the player db 8, 52 ; player is facing down @@ -171,79 +172,83 @@ BoulderDustAnimationOffsets: ; f097 (3:7097) db -24, 20 ; player is facing left db 40, 20 ; player is facing right -Func_f09f: ; f09f (3:709f) +ReplaceTreeTileBlock: +; Determine the address of the tile block that contains the tile in front of the +; player (i.e. where the tree is) and replace it with the corresponding tile +; block that doesn't have the tree. push de - ld a, [W_CURMAPWIDTH] ; wd369 - add $6 + ld a, [wCurMapWidth] + add 6 ld c, a - ld b, $0 - ld d, $0 + ld b, 0 + ld d, 0 ld hl, wCurrentTileBlockMapViewPointer ld a, [hli] ld h, [hl] ld l, a add hl, bc - ld a, [wSpriteStateData1 + 9] + ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction and a - jr z, .asm_f0c7 - cp $4 - jr z, .asm_f0cf - cp $8 - jr z, .asm_f0d7 - ld a, [W_XBLOCKCOORD] ; wd364 + jr z, .down + cp SPRITE_FACING_UP + jr z, .up + cp SPRITE_FACING_LEFT + jr z, .left +; right + ld a, [wXBlockCoord] and a - jr z, .asm_f0e0 - jr .asm_f0ec -.asm_f0c7 - ld a, [W_YBLOCKCOORD] ; wd363 + jr z, .centerTileBlock + jr .rightOfCenter +.down + ld a, [wYBlockCoord] and a - jr z, .asm_f0e0 - jr .asm_f0df -.asm_f0cf - ld a, [W_YBLOCKCOORD] ; wd363 + jr z, .centerTileBlock + jr .belowCenter +.up + ld a, [wYBlockCoord] and a - jr z, .asm_f0e1 - jr .asm_f0e0 -.asm_f0d7 - ld a, [W_XBLOCKCOORD] ; wd364 + jr z, .aboveCenter + jr .centerTileBlock +.left + ld a, [wXBlockCoord] and a - jr z, .asm_f0e6 - jr .asm_f0e0 -.asm_f0df + jr z, .leftOfCenter + jr .centerTileBlock +.belowCenter add hl, bc -.asm_f0e0 +.centerTileBlock add hl, bc -.asm_f0e1 +.aboveCenter ld e, $2 add hl, de - jr .asm_f0f0 -.asm_f0e6 + jr .next +.leftOfCenter ld e, $1 add hl, bc add hl, de - jr .asm_f0f0 -.asm_f0ec + jr .next +.rightOfCenter ld e, $3 add hl, bc add hl, de -.asm_f0f0 +.next pop de ld a, [hl] ld c, a -.asm_f0f3 +.loop ; find the matching tile block in the array ld a, [de] inc de inc de cp $ff ret z cp c - jr nz, .asm_f0f3 + jr nz, .loop dec de - ld a, [de] + ld a, [de] ; replacement tile block from matching array entry ld [hl], a ret -CutTreeBlockSwaps: ; f100 (3:7100) +CutTreeBlockSwaps: ; first byte = tileset block containing the cut tree ; second byte = corresponding tileset block after the cut animation happens db $32, $6D diff --git a/engine/overworld/cut2.asm b/engine/overworld/cut2.asm index de2b9d55..f16fed66 100755 --- a/engine/overworld/cut2.asm +++ b/engine/overworld/cut2.asm @@ -1,89 +1,89 @@ -Func_79e96: ; 79e96 (1e:5e96) - ld a, [wcd4d] +AnimCut: + ld a, [wCutTile] cp $52 - jr z, .asm_79ec8 + jr z, .grass ld c, $8 -.asm_79e9f +.cutTreeLoop push bc ld hl, wOAMBuffer + $91 - ld a, $1 - ld [wd08a], a - ld c, $2 + ld a, 1 + ld [wCoordAdjustmentAmount], a + ld c, 2 call AdjustOAMBlockXPos2 ld hl, wOAMBuffer + $99 - ld a, $ff - ld [wd08a], a - ld c, $2 + ld a, -1 + ld [wCoordAdjustmentAmount], a + ld c, 2 call AdjustOAMBlockXPos2 - ld a, [rOBP1] ; $ff49 + ld a, [rOBP1] xor $64 - ld [rOBP1], a ; $ff49 + ld [rOBP1], a call DelayFrame pop bc dec c - jr nz, .asm_79e9f + jr nz, .cutTreeLoop ret -.asm_79ec8 - ld c, $2 -.asm_79eca +.grass + ld c, 2 +.cutGrassLoop push bc ld c, $8 - call Func_79eed - call Func_79f30 + call AnimCutGrass_UpdateOAMEntries + call AnimCutGrass_SwapOAMEntries ld c, $8 - call Func_79eed - call Func_79f30 + call AnimCutGrass_UpdateOAMEntries + call AnimCutGrass_SwapOAMEntries ld hl, wOAMBuffer + $90 - ld a, $2 - ld [wd08a], a - ld c, $4 + ld a, 2 + ld [wCoordAdjustmentAmount], a + ld c, 4 call AdjustOAMBlockYPos2 pop bc dec c - jr nz, .asm_79eca + jr nz, .cutGrassLoop ret -Func_79eed: ; 79eed (1e:5eed) +AnimCutGrass_UpdateOAMEntries: push bc ld hl, wOAMBuffer + $91 - ld a, $1 - ld [wd08a], a - ld c, $1 + ld a, 1 + ld [wCoordAdjustmentAmount], a + ld c, 1 call AdjustOAMBlockXPos2 ld hl, wOAMBuffer + $95 - ld a, $2 - ld [wd08a], a - ld c, $1 + ld a, 2 + ld [wCoordAdjustmentAmount], a + ld c, 1 call AdjustOAMBlockXPos2 ld hl, wOAMBuffer + $99 - ld a, $fe - ld [wd08a], a - ld c, $1 + ld a, -2 + ld [wCoordAdjustmentAmount], a + ld c, 1 call AdjustOAMBlockXPos2 ld hl, wOAMBuffer + $9d - ld a, $ff - ld [wd08a], a - ld c, $1 + ld a, -1 + ld [wCoordAdjustmentAmount], a + ld c, 1 call AdjustOAMBlockXPos2 - ld a, [rOBP1] ; $ff49 + ld a, [rOBP1] xor $64 - ld [rOBP1], a ; $ff49 + ld [rOBP1], a call DelayFrame pop bc dec c - jr nz, Func_79eed + jr nz, AnimCutGrass_UpdateOAMEntries ret -Func_79f30: ; 79f30 (1e:5f30) +AnimCutGrass_SwapOAMEntries: ld hl, wOAMBuffer + $90 - ld de, wHPBarMaxHP + ld de, wBuffer ld bc, $8 call CopyData ld hl, wOAMBuffer + $98 ld de, wOAMBuffer + $90 ld bc, $8 call CopyData - ld hl, wHPBarMaxHP + ld hl, wBuffer ld de, wOAMBuffer + $98 ld bc, $8 jp CopyData diff --git a/engine/overworld/daycare_exp.asm b/engine/overworld/daycare_exp.asm new file mode 100644 index 00000000..dbe4023a --- /dev/null +++ b/engine/overworld/daycare_exp.asm @@ -0,0 +1,18 @@ +IncrementDayCareMonExp: + ld a, [wDayCareInUse] + and a + ret z + ld hl, wDayCareMonExp + 2 + inc [hl] + ret nz + dec hl + inc [hl] + ret nz + dec hl + inc [hl] + ld a, [hl] + cp $50 + ret c + ld a, $50 + ld [hl], a + ret diff --git a/engine/overworld/doors.asm b/engine/overworld/doors.asm index ac345af9..c39e096d 100755 --- a/engine/overworld/doors.asm +++ b/engine/overworld/doors.asm @@ -1,8 +1,8 @@ ; returns whether the player is standing on a door tile in carry -IsPlayerStandingOnDoorTile: ; 1a609 (6:6609) +IsPlayerStandingOnDoorTile: push de - ld hl, DoorTileIDPointers ; $662c - ld a, [W_CURMAPTILESET] ; W_CURMAPTILESET + ld hl, DoorTileIDPointers + ld a, [wCurMapTileset] ld de, $3 call IsInArray pop de @@ -25,64 +25,51 @@ IsPlayerStandingOnDoorTile: ; 1a609 (6:6609) and a ret -DoorTileIDPointers: ; 1a62c (6:662c) - db OVERWORLD - dw OverworldDoorTileIDs - db FOREST - dw ForestDoorTileIDs - db MART - dw MartDoorTileIDs - db HOUSE - dw HouseDoorTileIDs - db FOREST_GATE - dw TilesetMuseumDoorTileIDs - db MUSEUM - dw TilesetMuseumDoorTileIDs - db GATE - dw TilesetMuseumDoorTileIDs - db SHIP - dw ShipDoorTileIDs - db LOBBY - dw LobbyDoorTileIDs - db MANSION - dw MansionDoorTileIDs - db LAB - dw LabDoorTileIDs - db FACILITY - dw FacilityDoorTileIDs - db PLATEAU - dw PlateauDoorTileIDs +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 db $ff -OverworldDoorTileIDs: ; 1a654 (6:6654) +OverworldDoorTileIDs: db $1B,$58,$00 -ForestDoorTileIDs: ; 1a657 (6:6657) +ForestDoorTileIDs: db $3a,$00 -MartDoorTileIDs: ; 1a659 (6:6659) +MartDoorTileIDs: db $5e,$00 -HouseDoorTileIDs: ; 1a65b (6:665b) +HouseDoorTileIDs: db $54,$00 -TilesetMuseumDoorTileIDs: ; 1a65d (6:665d) +TilesetMuseumDoorTileIDs: db $3b,$00 -ShipDoorTileIDs: ; 1a65f (6:665f) +ShipDoorTileIDs: db $1e,$00 -LobbyDoorTileIDs: ; 1a661 (6:6661) +LobbyDoorTileIDs: db $1c,$38,$1a,$00 -MansionDoorTileIDs: ; 1a665 (6:6665) +MansionDoorTileIDs: db $1a,$1c,$53,$00 -LabDoorTileIDs: ; 1a669 (6:6669) +LabDoorTileIDs: db $34,$00 -FacilityDoorTileIDs: ; 1a66b (6:666b) +FacilityDoorTileIDs: db $43,$58,$1b,$00 -PlateauDoorTileIDs: ; 1a66f (6:666f) +PlateauDoorTileIDs: db $3b,$1b,$00 diff --git a/engine/overworld/elevator.asm b/engine/overworld/elevator.asm index 3a23d410..7ff4ff71 100755 --- a/engine/overworld/elevator.asm +++ b/engine/overworld/elevator.asm @@ -1,46 +1,48 @@ -ShakeElevator: ; 7bf15 (1e:7f15) - ld de, $ffe0 - call Func_7bf64 - ld de, $240 - call Func_7bf64 +ShakeElevator: + ld de, -$20 + call ShakeElevatorRedrawRow + ld de, SCREEN_HEIGHT * $20 + call ShakeElevatorRedrawRow call Delay3 ld a, $ff call PlaySound ld a, [hSCY] ld d, a ld e, $1 - ; number of times to play collision sfx - ld b, $64 -.asm_7bf30 + ld b, 100 +.shakeLoop ; scroll the BG up and down and play a sound effect ld a, e xor $fe ld e, a add d ld [hSCY], a push bc - ld c, BANK(SFX_02_5b) - ld a, (SFX_02_5b - SFX_Headers_02) / 3 + ld c, BANK(SFX_Collision_1) + ld a, SFX_COLLISION call PlayMusic pop bc - ld c, $2 + ld c, 2 call DelayFrames dec b - jr nz, .asm_7bf30 + jr nz, .shakeLoop ld a, d ld [hSCY], a ld a, $ff call PlaySound - ld c, BANK(SFX_02_5f) - ld a, (SFX_02_5f - SFX_Headers_02) / 3 + ld c, BANK(SFX_Safari_Zone_PA) + ld a, SFX_SAFARI_ZONE_PA call PlayMusic -.asm_7bf57 - ld a, [wc02a] - cp $b9 - jr z, .asm_7bf57 +.musicLoop + ld a, [wChannelSoundIDs + Ch4] + cp SFX_SAFARI_ZONE_PA + jr z, .musicLoop call UpdateSprites jp PlayDefaultMusic -Func_7bf64: ; 7bf64 (1e:7f64) +ShakeElevatorRedrawRow: +; This function is used to redraw certain portions of the screen, but it does +; not appear to ever result in any visible effect, so this function seems to +; be pointless. ld hl, wMapViewVRAMPointer + 1 ld a, [hld] push af @@ -54,7 +56,7 @@ Func_7bf64: ; 7bf64 (1e:7f64) add hl, de ld a, h and $3 - or $98 + or vBGMap0 / $100 ld d, a ld a, l pop hl diff --git a/engine/overworld/emotion_bubbles.asm b/engine/overworld/emotion_bubbles.asm index 7106063b..ac4276bd 100755 --- a/engine/overworld/emotion_bubbles.asm +++ b/engine/overworld/emotion_bubbles.asm @@ -1,30 +1,33 @@ -EmotionBubble: ; 17c47 (5:7c47) - ld a, [wcd50] +EmotionBubble: + ld a, [wWhichEmotionBubble] ld c, a - ld b, $0 - ld hl, EmotionBubblesPointerTable ; $7caf + ld b, 0 + ld hl, EmotionBubblesPointerTable add hl, bc add hl, bc ld e, [hl] inc hl ld d, [hl] ld hl, vChars1 + $780 - ld bc, (BANK(EmotionBubblesPointerTable) << 8) + $04 + lb bc, BANK(EmotionBubbles), $04 call CopyVideoData ld a, [wUpdateSpritesEnabled] push af ld a, $ff ld [wUpdateSpritesEnabled], a ld a, [wd736] - bit 6, a - ld hl, wOAMBuffer + $8f - ld de, wOAMBuffer + $9f - jr z, .asm_17c7a - ld hl, wOAMBuffer + $7f - ld de, wOAMBuffer + $8f -.asm_17c7a + bit 6, a ; are the last 4 OAM entries reserved for a shadow or fishing rod? + ld hl, wOAMBuffer + 4 * 35 + $3 ; $8f + ld de, wOAMBuffer + 4 * 39 + $3 ; $9f + jr z, .next + ld hl, wOAMBuffer + 4 * 31 + $3 ; $7f + ld de, wOAMBuffer + 4 * 35 + $3 ; $8f + +; Copy OAM data 16 bytes forward to make room for emotion bubble OAM data at the +; start of the OAM buffer. +.next ld bc, $90 -.asm_17c7d +.loop ld a, [hl] ld [de], a dec hl @@ -32,12 +35,14 @@ EmotionBubble: ; 17c47 (5:7c47) dec bc ld a, c or b - jr nz, .asm_17c7d + jr nz, .loop + +; get the screen coordinates of the sprite the bubble is to be displayed above ld hl, wSpriteStateData1 + 4 - ld a, [wcd4f] + ld a, [wEmotionBubbleSpriteIndex] swap a ld c, a - ld b, $0 + ld b, 0 add hl, bc ld a, [hli] ld b, a @@ -45,24 +50,25 @@ EmotionBubble: ; 17c47 (5:7c47) ld a, [hl] add $8 ld c, a - ld de, EmotionBubblesOAM ; $7cb5 + + ld de, EmotionBubblesOAM xor a call WriteOAMBlock - ld c, $3c + ld c, 60 call DelayFrames pop af ld [wUpdateSpritesEnabled], a call DelayFrame jp UpdateSprites -EmotionBubblesPointerTable: ; 17caf (5:7caf) +EmotionBubblesPointerTable: dw EmotionBubbles dw EmotionBubbles + $40 dw EmotionBubbles + $80 -EmotionBubblesOAM: ; 17cb5 (5:7cb5) +EmotionBubblesOAM: db $F8,$00,$F9,$00 db $FA,$00,$FB,$00 -EmotionBubbles: ; 17cbd (5:7cbd) +EmotionBubbles: INCBIN "gfx/emotion_bubbles.2bpp" diff --git a/engine/overworld/field_move_messages.asm b/engine/overworld/field_move_messages.asm new file mode 100644 index 00000000..69914bfc --- /dev/null +++ b/engine/overworld/field_move_messages.asm @@ -0,0 +1,57 @@ +PrintStrengthTxt: + ld hl, wd728 + set 0, [hl] + ld hl, UsedStrengthText + call PrintText + ld hl, CanMoveBouldersText + jp PrintText + +UsedStrengthText: + TX_FAR _UsedStrengthText + TX_ASM + ld a, [wcf91] + call PlayCry + call Delay3 + jp TextScriptEnd + +CanMoveBouldersText: + TX_FAR _CanMoveBouldersText + db "@" + +IsSurfingAllowed: +; Returns whether surfing is allowed in bit 1 of wd728. +; Surfing isn't allowed on the Cycling Road or in the lowest level of the +; Seafoam Islands before the current has been slowed with boulders. + ld hl, wd728 + set 1, [hl] + ld a, [wd732] + bit 5, a + jr nz, .forcedToRideBike + ld a, [wCurMap] + cp SEAFOAM_ISLANDS_5 + ret nz + CheckBothEventsSet EVENT_SEAFOAM4_BOULDER1_DOWN_HOLE, EVENT_SEAFOAM4_BOULDER2_DOWN_HOLE + ret z + ld hl, CoordsData_cdf7 + call ArePlayerCoordsInArray + ret nc + ld hl, wd728 + res 1, [hl] + ld hl, CurrentTooFastText + jp PrintText +.forcedToRideBike + ld hl, wd728 + res 1, [hl] + ld hl, CyclingIsFunText + jp PrintText + +CoordsData_cdf7: + db $0B,$07,$FF + +CurrentTooFastText: + TX_FAR _CurrentTooFastText + db "@" + +CyclingIsFunText: + TX_FAR _CyclingIsFunText + db "@" diff --git a/engine/overworld/healing_machine.asm b/engine/overworld/healing_machine.asm index 90d306c3..38a44cfb 100755 --- a/engine/overworld/healing_machine.asm +++ b/engine/overworld/healing_machine.asm @@ -1,71 +1,71 @@ -AnimateHealingMachine: ; 70433 (1c:4433) - ld de, PokeCenterFlashingMonitorAndHealBall ; $44b7 +AnimateHealingMachine: + ld de, PokeCenterFlashingMonitorAndHealBall ld hl, vChars0 + $7c0 - ld bc, (BANK(PokeCenterFlashingMonitorAndHealBall) << 8) + $03 + lb bc, BANK(PokeCenterFlashingMonitorAndHealBall), $03 ; loads one too many tiles call CopyVideoData ld hl, wUpdateSpritesEnabled ld a, [hl] push af ld [hl], $ff push hl - ld a, [rOBP1] ; $ff49 + ld a, [rOBP1] push af ld a, $e0 - ld [rOBP1], a ; $ff49 + ld [rOBP1], a ld hl, wOAMBuffer + $84 - ld de, PokeCenterOAMData ; $44d7 - call Func_70503 - ld a, $4 - ld [wMusicHeaderPointer], a + ld de, PokeCenterOAMData + call CopyHealingMachineOAM + ld a, 4 + ld [wAudioFadeOutControl], a ld a, $ff - ld [wc0ee], a + ld [wNewSoundID], a call PlaySound -.asm_70464 - ld a, [wMusicHeaderPointer] - and a - jr nz, .asm_70464 - ld a, [wPartyCount] ; wPartyCount +.waitLoop + ld a, [wAudioFadeOutControl] + and a ; is fade-out finished? + jr nz, .waitLoop ; if not, check again + ld a, [wPartyCount] ld b, a -.asm_7046e - call Func_70503 - ld a, (SFX_02_4a - SFX_Headers_02) / 3 +.partyLoop + call CopyHealingMachineOAM + ld a, SFX_HEALING_MACHINE call PlaySound - ld c, $1e + ld c, 30 call DelayFrames dec b - jr nz, .asm_7046e - ld a, [wc0ef] - cp $1f - ld [wc0f0], a - jr nz, .asm_70495 + jr nz, .partyLoop + ld a, [wAudioROMBank] + cp BANK(Audio3_UpdateMusic) + ld [wAudioSavedROMBank], a + jr nz, .next ld a, $ff - ld [wc0ee], a + ld [wNewSoundID], a call PlaySound ld a, BANK(Music_PkmnHealed) - ld [wc0ef], a -.asm_70495 + ld [wAudioROMBank], a +.next ld a, MUSIC_PKMN_HEALED - ld [wc0ee], a + ld [wNewSoundID], a call PlaySound ld d, $28 call FlashSprite8Times -.asm_704a2 - ld a, [wc026] - cp MUSIC_PKMN_HEALED - jr z, .asm_704a2 - ld c, $20 +.waitLoop2 + ld a, [wChannelSoundIDs] + cp MUSIC_PKMN_HEALED ; is the healed music still playing? + jr z, .waitLoop2 ; if so, check gain + ld c, 32 call DelayFrames pop af - ld [rOBP1], a ; $ff49 + ld [rOBP1], a pop hl pop af ld [hl], a jp UpdateSprites -PokeCenterFlashingMonitorAndHealBall: ; 704b7 (1c:44b7) +PokeCenterFlashingMonitorAndHealBall: INCBIN "gfx/pokecenter_ball.2bpp" -PokeCenterOAMData: ; 704d7 (1c:44d7) +PokeCenterOAMData: db $24,$34,$7C,$10 ; heal machine monitor db $2B,$30,$7D,$10 ; pokeballs 1-6 db $2B,$38,$7D,$30 @@ -75,7 +75,7 @@ PokeCenterOAMData: ; 704d7 (1c:44d7) db $35,$38,$7D,$30 ; d = value to xor with palette -FlashSprite8Times: ; 704f3 (1c:44f3) +FlashSprite8Times: ld b, 8 .loop ld a, [rOBP1] @@ -87,7 +87,8 @@ FlashSprite8Times: ; 704f3 (1c:44f3) jr nz, .loop ret -Func_70503: ; 70503 (1c:4503) +CopyHealingMachineOAM: +; copy one OAM entry and advance the pointers ld a, [de] inc de ld [hli], a diff --git a/engine/overworld/hidden_items.asm b/engine/overworld/hidden_items.asm index 17288a17..32783f83 100755 --- a/engine/overworld/hidden_items.asm +++ b/engine/overworld/hidden_items.asm @@ -1,45 +1,43 @@ -HiddenItems: ; 76688 (1d:6688) +HiddenItems: ld hl, HiddenItemCoords - call Func_76857 - ld [wTrainerScreenX], a - ld hl, wd6f0 - ld a, [wTrainerScreenX] + call FindHiddenItemOrCoinsIndex + ld [wHiddenItemOrCoinsIndex], a + ld hl, wObtainedHiddenItemsFlags + ld a, [wHiddenItemOrCoinsIndex] ld c, a - ld b, $2 + ld b, FLAG_TEST predef FlagActionPredef ld a, c and a ret nz call EnableAutoTextBoxDrawing - ld a, $1 + ld a, 1 ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ld a, [wWhichTrade] ; item ID + ld a, [wHiddenObjectFunctionArgument] ; item ID ld [wd11e], a call GetItemName - ld a, $24 - jp PrintPredefTextID + tx_pre_jump FoundHiddenItemText INCLUDE "data/hidden_item_coords.asm" -FoundHiddenItemText: ; 7675b (1d:675b) -; XXX where is the pointer to this? +FoundHiddenItemText: TX_FAR _FoundHiddenItemText - db $8 - ld a, [wWhichTrade] ; item ID + TX_ASM + ld a, [wHiddenObjectFunctionArgument] ; item ID ld b, a ld c, 1 call GiveItem - jr nc, .BagFull - ld hl, wd6f0 - ld a, [wTrainerScreenX] + jr nc, .bagFull + ld hl, wObtainedHiddenItemsFlags + ld a, [wHiddenItemOrCoinsIndex] ld c, a - ld b, $1 + ld b, FLAG_SET predef FlagActionPredef - ld a, (SFX_02_3b - SFX_Headers_02) / 3 - call PlaySoundWaitForCurrent ; play sound - call WaitForSoundToFinish ; wait for sound to finish playing + ld a, SFX_GET_ITEM_2 + call PlaySoundWaitForCurrent + call WaitForSoundToFinish jp TextScriptEnd -.BagFull +.bagFull call WaitForTextScrollButtonPress ; wait for button press xor a ld [wDoNotWaitForButtonPressAfterDisplayingText], a @@ -47,116 +45,117 @@ FoundHiddenItemText: ; 7675b (1d:675b) call PrintText jp TextScriptEnd -HiddenItemBagFullText: ; 76794 (1d:6794) +HiddenItemBagFullText: TX_FAR _HiddenItemBagFullText db "@" -HiddenCoins: ; 76799 (1d:6799) +HiddenCoins: ld b, COIN_CASE - predef IsItemInBag_ + predef GetQuantityOfItemInBag ld a, b and a ret z ld hl, HiddenCoinCoords - call Func_76857 - ld [wTrainerScreenX], a - ld hl, wd6fe - ld a, [wTrainerScreenX] + call FindHiddenItemOrCoinsIndex + ld [wHiddenItemOrCoinsIndex], a + ld hl, wObtainedHiddenCoinsFlags + ld a, [wHiddenItemOrCoinsIndex] ld c, a - ld b, $2 + ld b, FLAG_TEST predef FlagActionPredef ld a, c and a ret nz xor a - ld [$ff9f], a - ld [$ffa0], a - ld [$ffa1], a - ld a, [wWhichTrade] + 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 + jr z, .bcd20 ; should be bcd40 jr .bcd100 .bcd10 ld a, $10 - ld [$ffa1], a - jr .bcddone + ld [hCoins + 1], a + jr .bcdDone .bcd20 ld a, $20 - ld [$ffa1], a - jr .bcddone + ld [hCoins + 1], a + jr .bcdDone .bcd40 ; due to a typo, this is never used ld a, $40 - ld [$ffa1], a - jr .bcddone + ld [hCoins + 1], a + jr .bcdDone .bcd100 ld a, $1 - ld [$ffa0], a -.bcddone + ld [hCoins], a +.bcdDone ld de, wPlayerCoins + 1 - ld hl, $ffa1 + ld hl, hCoins + 1 ld c, $2 predef AddBCDPredef - ld hl, wd6fe - ld a, [wTrainerScreenX] + ld hl, wObtainedHiddenCoinsFlags + ld a, [wHiddenItemOrCoinsIndex] ld c, a - ld b, $1 + ld b, FLAG_SET predef FlagActionPredef call EnableAutoTextBoxDrawing ld a, [wPlayerCoins] cp $99 - jr nz, .RoomInCoinCase + jr nz, .roomInCoinCase ld a, [wPlayerCoins + 1] cp $99 - jr nz, .RoomInCoinCase - ld a, $2c + jr nz, .roomInCoinCase + tx_pre_id DroppedHiddenCoinsText jr .done -.RoomInCoinCase - ld a, $2b +.roomInCoinCase + tx_pre_id FoundHiddenCoinsText .done jp PrintPredefTextID INCLUDE "data/hidden_coins.asm" -FoundHiddenCoinsText: ; 76847 (1d:6847) +FoundHiddenCoinsText: TX_FAR _FoundHiddenCoinsText - db $10,"@" + TX_SFX_ITEM_2 + db "@" -DroppedHiddenCoinsText: ; 7684d (1d:684d) +DroppedHiddenCoinsText: TX_FAR _FoundHiddenCoins2Text - db $10 + TX_SFX_ITEM_2 TX_FAR _DroppedHiddenCoinsText db "@" -Func_76857: ; 76857 (1d:6857) - ld a, [wTrainerScreenY] +FindHiddenItemOrCoinsIndex: + ld a, [wHiddenObjectY] ld d, a - ld a, [wTrainerScreenX] + ld a, [wHiddenObjectX] ld e, a - ld a, [W_CURMAP] + ld a, [wCurMap] ld b, a - ld c, $ff + 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, .asm_76877 ; 0x7686b $a + jr nz, .next1 ld a, [hli] cp d - jr nz, .asm_76878 ; 0x7686f $7 + jr nz, .next2 ld a, [hli] cp e jr nz, .loop ld a, c ret -.asm_76877 +.next1 inc hl -.asm_76878 +.next2 inc hl jr .loop diff --git a/engine/overworld/hidden_objects.asm b/engine/overworld/hidden_objects.asm index ae67aeed..dcdf8537 100755 --- a/engine/overworld/hidden_objects.asm +++ b/engine/overworld/hidden_objects.asm @@ -1,4 +1,4 @@ -Func_46981: ; 46981 (11:6981) +IsPlayerOnDungeonWarp: xor a ld [wWhichDungeonWarp], a ld a, [wd72d] @@ -6,7 +6,7 @@ Func_46981: ; 46981 (11:6981) ret nz call ArePlayerCoordsInArray ret nc - ld a, [wWhichTrade] + ld a, [wCoordIndex] ld [wWhichDungeonWarp], a ld hl, wd72d set 4, [hl] @@ -15,7 +15,7 @@ Func_46981: ; 46981 (11:6981) ret ; if a hidden object was found, stores $00 in [$ffee], else stores $ff -CheckForHiddenObject: ; 469a0 (11:69a0) +CheckForHiddenObject: ld hl, $ffeb xor a ld [hli], a @@ -29,7 +29,7 @@ CheckForHiddenObject: ; 469a0 (11:69a0) ld b, a cp $ff jr z, .noMatch - ld a, [W_CURMAP] + ld a, [wCurMap] cp b jr z, .foundMatchingMap inc de @@ -58,7 +58,7 @@ CheckForHiddenObject: ; 469a0 (11:69a0) ld [wHiddenObjectX], a ld c, a call CheckIfCoordsInFrontOfPlayerMatch - ld a, [$ffea] + ld a, [hCoordsInFrontOfPlayerMatch] and a jr z, .foundMatchingObject inc hl @@ -85,8 +85,8 @@ CheckForHiddenObject: ; 469a0 (11:69a0) ret ; checks if the coordinates in front of the player's sprite match Y in b and X in c -; [$ffea] = $00 if they match, $ff if they don't match -CheckIfCoordsInFrontOfPlayerMatch: ; 46a01 (11:6a01) +; [hCoordsInFrontOfPlayerMatch] = $00 if they match, $ff if they don't match +CheckIfCoordsInFrontOfPlayerMatch: ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction cp SPRITE_FACING_UP jr z, .facingUp @@ -95,30 +95,30 @@ CheckIfCoordsInFrontOfPlayerMatch: ; 46a01 (11:6a01) cp SPRITE_FACING_RIGHT jr z, .facingRight ; facing down - ld a, [W_YCOORD] + ld a, [wYCoord] inc a jr .upDownCommon .facingUp - ld a, [W_YCOORD] + ld a, [wYCoord] dec a .upDownCommon cp b jr nz, .didNotMatch - ld a, [W_XCOORD] + ld a, [wXCoord] cp c jr nz, .didNotMatch jr .matched .facingLeft - ld a, [W_XCOORD] + ld a, [wXCoord] dec a jr .leftRightCommon .facingRight - ld a, [W_XCOORD] + ld a, [wXCoord] inc a .leftRightCommon cp c jr nz, .didNotMatch - ld a, [W_YCOORD] + ld a, [wYCoord] cp b jr nz, .didNotMatch .matched @@ -127,7 +127,7 @@ CheckIfCoordsInFrontOfPlayerMatch: ; 46a01 (11:6a01) .didNotMatch ld a, $ff .done - ld [$ffea], a + ld [hCoordsInFrontOfPlayerMatch], a ret INCLUDE "data/hidden_objects.asm" diff --git a/engine/overworld/is_player_just_outside_map.asm b/engine/overworld/is_player_just_outside_map.asm index 24e434b3..44690db0 100644 --- a/engine/overworld/is_player_just_outside_map.asm +++ b/engine/overworld/is_player_just_outside_map.asm @@ -1,13 +1,13 @@ ; returns whether the player is one tile outside the map in Z -IsPlayerJustOutsideMap: ; 128d8 (4:68d8) - ld a, [W_YCOORD] +IsPlayerJustOutsideMap: + ld a, [wYCoord] ld b, a - ld a, [W_CURMAPHEIGHT] + ld a, [wCurMapHeight] call .compareCoordWithMapDimension ret z - ld a, [W_XCOORD] + ld a, [wXCoord] ld b, a - ld a, [W_CURMAPWIDTH] + ld a, [wCurMapWidth] .compareCoordWithMapDimension add a cp b diff --git a/engine/overworld/item.asm b/engine/overworld/item.asm index a49fc268..9f19100a 100644 --- a/engine/overworld/item.asm +++ b/engine/overworld/item.asm @@ -1,9 +1,9 @@ -PickupItem: +PickUpItem: call EnableAutoTextBoxDrawing - ld a, [H_DOWNARROWBLINKCNT2] ; $ff8c + ld a, [hSpriteIndexOrTextID] ld b, a - ld hl, W_MISSABLEOBJECTLIST + ld hl, wMissableObjectList .missableObjectsListLoop ld a, [hli] cp $ff @@ -17,8 +17,8 @@ PickupItem: ld a, [hl] ld [$ffdb], a - ld hl, W_MAPSPRITEEXTRADATA - ld a, [H_DOWNARROWBLINKCNT2] ; $ff8c + ld hl, wMapSpriteExtraData + ld a, [hSpriteIndexOrTextID] dec a add a ld d, 0 @@ -31,7 +31,7 @@ PickupItem: jr nc, .BagFull ld a, [$ffdb] - ld [wcc4d], a + ld [wMissableObjectIndex], a predef HideObject ld a, 1 ld [wDoNotWaitForButtonPressAfterDisplayingText], a @@ -46,7 +46,7 @@ PickupItem: FoundItemText: TX_FAR _FoundItemText - db $0B + TX_SFX_ITEM_1 db "@" NoMoreRoomForItemText: diff --git a/engine/overworld/ledges.asm b/engine/overworld/ledges.asm index b8c19181..342540b2 100755 --- a/engine/overworld/ledges.asm +++ b/engine/overworld/ledges.asm @@ -1,8 +1,8 @@ -HandleLedges: ; 1a672 (6:6672) +HandleLedges: ld a, [wd736] bit 6, a ; already jumping down ledge ret nz - ld a, [W_CURMAPTILESET] ; W_CURMAPTILESET + ld a, [wCurMapTileset] and a ; OVERWORLD ret nz predef GetTileAndCoordsInFrontOfPlayer @@ -50,12 +50,12 @@ HandleLedges: ; 1a672 (6:6672) ld a, $2 ld [wSimulatedJoypadStatesIndex], a call LoadHoppingShadowOAM - ld a, (SFX_02_4e - SFX_Headers_02) / 3 + ld a, SFX_LEDGE call PlaySound ret ; (player direction) (tile player standing on) (ledge tile) (input required) -LedgeTiles: ; 1a6cf (6:66cf) +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 @@ -66,20 +66,21 @@ LedgeTiles: ; 1a6cf (6:66cf) db SPRITE_FACING_RIGHT,$39,$0D,D_RIGHT db $FF -LoadHoppingShadowOAM: ; 1a6f0 (6:66f0) +LoadHoppingShadowOAM: ld hl, vChars1 + $7f0 ld de, LedgeHoppingShadow - ld bc, (BANK(LedgeHoppingShadow) << 8) + $01 + lb bc, BANK(LedgeHoppingShadow), (LedgeHoppingShadowEnd - LedgeHoppingShadow) / $8 call CopyVideoDataDouble ld a, $9 - ld bc, $5448 ; b, c = y, x coordinates of shadow + lb bc, $54, $48 ; b, c = y, x coordinates of shadow ld de, LedgeHoppingShadowOAM call WriteOAMBlock ret -LedgeHoppingShadow: ; 1a708 (6:6708) +LedgeHoppingShadow: INCBIN "gfx/ledge_hopping_shadow.1bpp" +LedgeHoppingShadowEnd: -LedgeHoppingShadowOAM: ; 1a710 (6:6710) +LedgeHoppingShadowOAM: db $FF,$10,$FF,$20 db $FF,$40,$FF,$60 diff --git a/engine/overworld/map_sprite_functions1.asm b/engine/overworld/map_sprite_functions1.asm new file mode 100644 index 00000000..d1a411fa --- /dev/null +++ b/engine/overworld/map_sprite_functions1.asm @@ -0,0 +1,356 @@ +_UpdateSprites: + ld h, $c1 + inc h + ld a, $e ; wSpriteStateData2 + $0e +.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 + cp $1 + jp nz, UpdateNonPlayerSprite + jp UpdatePlayerSprite + +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] + add wSpriteStateData1 % $100 + 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, [$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 + 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 +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 df39d112..05588321 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 interated over in the inner loop. -InitMapSprites: ; 1785b (5:785b) +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) @@ -29,17 +29,17 @@ InitMapSprites: ; 1785b (5:785b) ; This is used for both inside and outside maps, since it is called by ; InitOutsideMapSprites. ; Loads tile pattern data for sprites into VRAM. -LoadMapSpriteTilePatterns: ; 17871 (5:7871) - ld a,[W_NUMSPRITES] +LoadMapSpriteTilePatterns: + ld a,[wNumSprites] and a ; are there any sprites? jr nz,.spritesExist ret .spritesExist - ld c,a ; c = [W_NUMSPRITES] + ld c,a ; c = [wNumSprites] ld b,$10 ; number of sprite slots ld hl,wSpriteStateData2 + $0d xor a - ld [$ff8e],a ; 4-tile sprite counter + ld [hFourTileSpriteCount],a .copyPictureIDLoop ; loop to copy picture ID from $C2XD to $C2XE ld a,[hli] ; $C2XD (sprite picture ID) ld [hld],a ; $C2XE @@ -98,14 +98,14 @@ LoadMapSpriteTilePatterns: ; 17871 (5:7871) cp a,SPRITE_BALL ; is it a 4-tile sprite? jr c,.notFourTileSprite pop af - ld a,[$ff8e] ; 4-tile sprite counter + ld a,[hFourTileSpriteCount] add a,11 jr .storeVRAMSlot .notFourTileSprite pop af .storeVRAMSlot ld [hl],a ; store VRAM slot at $C2XE - ld [$ff8d],a ; used to determine if it's 4-tile sprite later + ld [hVRAMSlot],a ; used to determine if it's 4-tile sprite later ld a,b ; a = current sprite picture ID dec a add a @@ -128,7 +128,7 @@ LoadMapSpriteTilePatterns: ; 17871 (5:7871) push bc ld hl,vNPCSprites ; VRAM base address ld bc,$c0 ; number of bytes per VRAM slot - ld a,[$ff8d] + ld a,[hVRAMSlot] cp a,11 ; is it a 4-tile sprite? jr nc,.fourTileSpriteVRAMAddr ld d,a @@ -142,13 +142,13 @@ LoadMapSpriteTilePatterns: ; 17871 (5:7871) jr .loadStillTilePattern .fourTileSpriteVRAMAddr ld hl,vSprites + $7c0 ; address for second 4-tile sprite - ld a,[$ff8e] ; 4-tile sprite counter - and a ; is it the first 4-tile sprite? + ld a,[hFourTileSpriteCount] + and a jr nz,.loadStillTilePattern ; if it's the first 4-tile sprite ld hl,vSprites + $780 ; address for first 4-tile sprite inc a - ld [$ff8e],a ; 4-tile sprite counter + ld [hFourTileSpriteCount],a .loadStillTilePattern pop bc pop de @@ -168,7 +168,7 @@ LoadMapSpriteTilePatterns: ; 17871 (5:7871) .skipFirstLoad pop de pop hl - ld a,[$ff8d] + ld a,[hVRAMSlot] cp a,11 ; is it a 4-tile sprite? jr nc,.skipSecondLoad ; if so, there is no second block push de @@ -236,7 +236,7 @@ LoadMapSpriteTilePatterns: ; 17871 (5:7871) ; de = pointer to sprite sheet ; bc = length in bytes ; a = ROM bank -ReadSpriteSheetData: ; 17971 (5:7971) +ReadSpriteSheetData: ld a,[hli] ld e,a ld a,[hli] @@ -250,8 +250,8 @@ ReadSpriteSheetData: ; 17971 (5:7971) ; Loads sprite set for outside maps (cities and routes) and sets VRAM slots. ; sets carry if the map is a city or route, unsets carry if not -InitOutsideMapSprites: ; 1797b (5:797b) - ld a,[W_CURMAP] +InitOutsideMapSprites: + ld a,[wCurMap] cp a,REDS_HOUSE_1F ; is the map a city or a route (map ID less than $25)? ret nc ; if not, return ld hl,MapSpriteSets @@ -267,12 +267,12 @@ InitOutsideMapSprites: ; 1797b (5:797b) ld a,[wFontLoaded] bit 0,a ; reloading upper half of tile patterns after displaying text? jr nz,.loadSpriteSet ; if so, forcibly reload the sprite set - ld a,[W_SPRITESETID] + ld a,[wSpriteSetID] cp b ; has the sprite set ID changed? jr z,.skipLoadingSpriteSet ; if not, don't load it again .loadSpriteSet ld a,b - ld [W_SPRITESETID],a + ld [wSpriteSetID],a dec a ld b,a sla a @@ -291,7 +291,7 @@ InitOutsideMapSprites: ; 1797b (5:797b) ld hl,wSpriteStateData2 + $0d ld a,SPRITE_RED ld [hl],a - ld bc,W_SPRITESET + ld bc,wSpriteSet ; Load the sprite set into RAM. ; This loop also fills $C2XD (sprite picture ID) where X is from $0 to $A ; with picture ID's. This is done so that LoadMapSpriteTilePatterns will @@ -317,13 +317,13 @@ InitOutsideMapSprites: ; 1797b (5:797b) ld [hl],a ; $C2XD (sprite picture ID) dec b jr nz,.zeroRemainingSlotsLoop - ld a,[W_NUMSPRITES] + ld a,[wNumSprites] push af ; save number of sprites ld a,11 ; 11 sprites in sprite set - ld [W_NUMSPRITES],a + ld [wNumSprites],a call LoadMapSpriteTilePatterns pop af - ld [W_NUMSPRITES],a ; restore number of sprites + ld [wNumSprites],a ; restore number of sprites ld hl,wSpriteStateData2 + $1e ld b,$0f ; The VRAM tile pattern slots that LoadMapSpriteTilePatterns set are in the @@ -352,7 +352,7 @@ InitOutsideMapSprites: ; 1797b (5:797b) and a ; is the sprite slot used? jr z,.skipGettingPictureIndex ; if the sprite slot is not used ld b,a ; b = picture ID - ld de,W_SPRITESET + ld de,wSpriteSet ; Loop to find the index of the sprite's picture ID within the sprite set. .getPictureIndexLoop inc c @@ -380,7 +380,7 @@ InitOutsideMapSprites: ; 1797b (5:797b) ; Chooses the correct sprite set ID depending on the player's position within ; the map for maps with two sprite sets. -GetSplitMapSpriteSetID: ; 17a1a (5:7a1a) +GetSplitMapSpriteSetID: cp a,$f8 jr z,.route20 ld hl,SplitMapSpriteSets @@ -399,10 +399,10 @@ GetSplitMapSpriteSetID: ; 17a1a (5:7a1a) ld b,a jr z,.eastWestDivide .northSouthDivide - ld a,[W_YCOORD] + ld a,[wYCoord] jr .compareCoord .eastWestDivide - ld a,[W_XCOORD] + ld a,[wXCoord] .compareCoord cp b jr c,.loadSpriteSetID @@ -415,7 +415,7 @@ GetSplitMapSpriteSetID: ; 17a1a (5:7a1a) ; Route 20 is a special case because the two map sections have a more complex ; shape instead of the map simply being split horizontally or vertically. .route20 - ld hl,W_XCOORD + ld hl,wXCoord ld a,[hl] cp a,$2b ld a,$01 @@ -430,7 +430,7 @@ GetSplitMapSpriteSetID: ; 17a1a (5:7a1a) jr nc,.next ld b,$0d .next - ld a,[W_YCOORD] + ld a,[wYCoord] cp b ld a,$0a ret c diff --git a/engine/overworld/missable_objects.asm b/engine/overworld/missable_objects.asm new file mode 100644 index 00000000..8587c0f7 --- /dev/null +++ b/engine/overworld/missable_objects.asm @@ -0,0 +1,215 @@ +MarkTownVisitedAndLoadMissableObjects: + ld a, [wCurMap] + cp ROUTE_1 + jr nc, .notInTown + ld c, a + ld b, FLAG_SET + ld hl, wTownVisitedFlag ; mark town as visited (for flying) + predef FlagActionPredef +.notInTown + ld hl, MapHSPointers + ld a, [wCurMap] + ld b, $0 + ld c, a + add hl, bc + add hl, bc + ld a, [hli] ; load missable objects pointer in hl + ld h, [hl] + ; fall through + +LoadMissableObjects: + ld l, a + push hl + ld de, MapHS00 ; calculate difference between out pointer and the base pointer + ld a, l + sub e + jr nc, .asm_f13c + dec h +.asm_f13c + ld l, a + ld a, h + sub d + ld h, a + ld a, h + ld [H_DIVIDEND], a + ld a, l + ld [H_DIVIDEND+1], a + xor a + ld [H_DIVIDEND+2], a + ld [H_DIVIDEND+3], a + ld a, $3 + ld [H_DIVISOR], 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] + ld c, a ; store global offset in c + ld de, wMissableObjectList + pop hl +.writeMissableObjectsListLoop + ld a, [hli] + cp $ff + jr z, .done ; end of list + cp b + jr nz, .done ; not for current map anymore + ld a, [hli] + inc hl + ld [de], a ; write (map-local) sprite ID + inc de + ld a, c + inc c + ld [de], a ; write (global) missable object index + inc de + jr .writeMissableObjectsListLoop +.done + ld a, $ff + ld [de], a ; write sentinel + ret + +InitializeMissableObjectsFlags: + ld hl, wMissableObjectFlags + ld bc, wMissableObjectFlagsEnd - wMissableObjectFlags + xor a + call FillMemory ; clear missable objects flags + ld hl, MapHS00 + xor a + ld [wMissableObjectCounter], a +.missableObjectsLoop + ld a, [hli] + cp $ff ; end of list + ret z + push hl + inc hl + ld a, [hl] + cp Hide + jr nz, .skip + ld hl, wMissableObjectFlags + ld a, [wMissableObjectCounter] + ld c, a + ld b, FLAG_SET + call MissableObjectFlagAction ; set flag if Item is hidden +.skip + ld hl, wMissableObjectCounter + inc [hl] + pop hl + inc hl + inc hl + jr .missableObjectsLoop + +; tests if current sprite is a missable object that is hidden/has been removed +IsObjectHidden: + ld a, [H_CURRENTSPRITEOFFSET] + swap a + ld b, a + ld hl, wMissableObjectList +.loop + ld a, [hli] + cp $ff + jr z, .notHidden ; not missable -> not hidden + cp b + ld a, [hli] + jr nz, .loop + ld c, a + ld b, FLAG_TEST + ld hl, wMissableObjectFlags + call MissableObjectFlagAction + ld a, c + and a + jr nz, .hidden +.notHidden + xor a +.hidden + ld [$ffe5], a + ret + +; adds missable object (items, leg. pokemon, etc.) to the map +; [wMissableObjectIndex]: index of the missable object to be added (global index) +ShowObject: +ShowObject2: + ld hl, wMissableObjectFlags + ld a, [wMissableObjectIndex] + ld c, a + ld b, FLAG_RESET + call MissableObjectFlagAction ; reset "removed" flag + jp UpdateSprites + +; removes missable object (items, leg. pokemon, etc.) from the map +; [wMissableObjectIndex]: index of the missable object to be removed (global index) +HideObject: + ld hl, wMissableObjectFlags + ld a, [wMissableObjectIndex] + ld c, a + ld b, FLAG_SET + call MissableObjectFlagAction ; set "removed" flag + jp UpdateSprites + +MissableObjectFlagAction: +; identical to FlagAction + + push hl + push de + push bc + + ; bit + ld a, c + ld d, a + and 7 + ld e, a + + ; byte + ld a, d + srl a + srl a + srl a + add l + ld l, a + jr nc, .ok + inc h +.ok + + ; d = 1 << e (bitmask) + inc e + ld d, 1 +.shift + dec e + jr z, .shifted + sla d + jr .shift +.shifted + + ld a, b + and a + jr z, .reset + cp 2 + jr z, .read + +.set + ld a, [hl] + ld b, a + ld a, d + or b + ld [hl], a + jr .done + +.reset + ld a, [hl] + ld b, a + ld a, d + xor $ff + and b + ld [hl], a + jr .done + +.read + ld a, [hl] + ld b, a + ld a, d + and b + +.done + pop bc + pop de + pop hl + ld c, a + ret diff --git a/engine/overworld/movement.asm b/engine/overworld/movement.asm index c4482700..6d05859e 100644 --- a/engine/overworld/movement.asm +++ b/engine/overworld/movement.asm @@ -1,4 +1,4 @@ -UpdatePlayerSprite: ; 4e31 (1:4e31) +UpdatePlayerSprite: ld a, [wSpriteStateData2] and a jr z, .checkIfTextBoxInFrontOfSprite @@ -12,7 +12,7 @@ UpdatePlayerSprite: ; 4e31 (1:4e31) ; the maximum number for map tiles .checkIfTextBoxInFrontOfSprite aCoord 8, 9 - ld [$ff93], a + ld [hTilePlayerStandingOn], a cp $60 jr c, .lowerLeftTileIsMapTile .disableSprite @@ -21,52 +21,54 @@ UpdatePlayerSprite: ; 4e31 (1:4e31) ret .lowerLeftTileIsMapTile call DetectCollisionBetweenSprites - ld h, $c1 - ld a, [wWalkCounter] ; wcfc5 + ld h, wSpriteStateData1 / $100 + ld a, [wWalkCounter] and a - jr nz, .asm_4e90 - ld a, [wd528] - bit 2, a - jr z, .asm_4e65 - xor a - jr .asm_4e86 -.asm_4e65 - bit 3, a - jr z, .asm_4e6d - ld a, $4 - jr .asm_4e86 -.asm_4e6d - bit 1, a - jr z, .asm_4e75 - ld a, $8 - jr .asm_4e86 -.asm_4e75 - bit 0, a - jr z, .asm_4e7d - ld a, $c - jr .asm_4e86 -.asm_4e7d + jr nz, .moving + ld a, [wPlayerMovingDirection] +; check if down + bit PLAYER_DIR_BIT_DOWN, a + jr z, .checkIfUp + xor a ; ld a, SPRITE_FACING_DOWN + jr .next +.checkIfUp + bit PLAYER_DIR_BIT_UP, a + jr z, .checkIfLeft + ld a, SPRITE_FACING_UP + jr .next +.checkIfLeft + bit PLAYER_DIR_BIT_LEFT, a + jr z, .checkIfRight + ld a, SPRITE_FACING_LEFT + jr .next +.checkIfRight + bit PLAYER_DIR_BIT_RIGHT, a + jr z, .notMoving + ld a, SPRITE_FACING_RIGHT + jr .next +.notMoving +; zero the animation counters xor a ld [wSpriteStateData1 + 7], a ld [wSpriteStateData1 + 8], a - jr .asm_4eab -.asm_4e86 - ld [wSpriteStateData1 + 9], a + jr .calcImageIndex +.next + ld [wSpriteStateData1 + 9], a ; facing direction ld a, [wFontLoaded] bit 0, a - jr nz, .asm_4e7d -.asm_4e90 + jr nz, .notMoving +.moving ld a, [wd736] - bit 7, a - jr nz, .asm_4eb6 + bit 7, a ; is the player sprite spinning due to a spin tile? + jr nz, .skipSpriteAnim ld a, [H_CURRENTSPRITEOFFSET] add $7 ld l, a ld a, [hl] inc a ld [hl], a - cp $4 - jr nz, .asm_4eab + cp 4 + jr nz, .calcImageIndex xor a ld [hl], a inc hl @@ -74,28 +76,32 @@ UpdatePlayerSprite: ; 4e31 (1:4e31) inc a and $3 ld [hl], a -.asm_4eab +.calcImageIndex ld a, [wSpriteStateData1 + 8] ld b, a ld a, [wSpriteStateData1 + 9] add b ld [wSpriteStateData1 + 2], a -.asm_4eb6 - ld a, [$ff93] +.skipSpriteAnim +; If the player is standing on a grass tile, make the player's sprite have +; lower priority than the background so that it's partially obscured by the +; grass. Only the lower half of the sprite is permitted to have the priority +; bit set by later logic. + ld a, [hTilePlayerStandingOn] ld c, a - ld a, [W_GRASSTILE] + ld a, [wGrassTile] cp c ld a, $0 - jr nz, .asm_4ec3 + jr nz, .next2 ld a, $80 -.asm_4ec3 - ld [wSpriteStateData2 + $07], a +.next2 + ld [wSpriteStateData2 + 7], a ret -Func_4ec7: ; 4ec7 (1:4ec7) +UnusedReadSpriteDataFunction: push bc push af - ld a, [$ffda] + ld a, [H_CURRENTSPRITEOFFSET] ld c, a pop af add c @@ -103,12 +109,12 @@ Func_4ec7: ; 4ec7 (1:4ec7) pop bc ret -Func_4ed1: ; 4ed1 (1:4ed1) +UpdateNPCSprite: ld a, [H_CURRENTSPRITEOFFSET] swap a dec a add a - ld hl, W_MAPSPRITEDATA ; wd4e4 + ld hl, wMapSpriteData add l ld l, a ld a, [hl] ; read movement byte 2 @@ -127,8 +133,8 @@ Func_4ed1: ; 4ed1 (1:4ed1) ld l, a inc l ld a, [hl] ; c1x1 - bit 7, a - jp nz, InitializeSpriteFacingDirection ; c1x1 >= $80 + bit 7, a ; is the face player flag set? + jp nz, MakeNPCFacePlayer ld b, a ld a, [wFontLoaded] bit 0, a @@ -138,7 +144,7 @@ Func_4ed1: ; 4ed1 (1:4ed1) jp z, UpdateSpriteMovementDelay ; c1x1 == 2 cp $3 jp z, UpdateSpriteInWalkingAnimation ; c1x1 == 3 - ld a, [wWalkCounter] ; wcfc5 + ld a, [wWalkCounter] and a ret nz ; don't do anything yet if player is currently moving (redundant, already tested in CheckSpriteAvailability) call InitializeSpriteScreenPosition @@ -148,40 +154,43 @@ Func_4ed1: ; 4ed1 (1:4ed1) ld l, a ld a, [hl] ; c2x6: movement byte 1 inc a - jr z, .asm_4f59 ; value $FF + jr z, .randomMovement ; value $FF inc a - jr z, .asm_4f59 ; value $FE + jr z, .randomMovement ; value $FE +; scripted movement dec a - ld [hl], a ; (temporarily) increment movement byte 1 + ld [hl], a ; increment movement byte 1 (movement data index) dec a push hl - ld hl, wcf0f - dec [hl] ; decrement wcf0f + ld hl, wNPCNumScriptedSteps + dec [hl] ; decrement wNPCNumScriptedSteps pop hl - ld de, wcc5b - call LoadDEPlusA ; a = [wcc5b + movement byte 1] + ld de, wNPCMovementDirections + call LoadDEPlusA ; a = [wNPCMovementDirections + movement byte 1] cp $e0 jp z, ChangeFacingDirection - cp $ff - jr nz, .asm_4f4b - ld [hl], a ; reset movement byte 1 to initial value + cp STAY + jr nz, .next +; reached end of wNPCMovementDirections list + ld [hl], a ; store $ff in movement byte 1, disabling scripted movement ld hl, wd730 res 0, [hl] xor a ld [wSimulatedJoypadStatesIndex], a ld [wWastedByteCD3A], a ret -.asm_4f4b - cp $fe - jr nz, .asm_4f5f +.next + cp WALK + jr nz, .determineDirection +; current NPC movement data is $fe. this seems buggy ld [hl], $1 ; set movement byte 1 to $1 - ld de, wcc5b - call LoadDEPlusA ; a = [wcc5b + $fe] (?) - jr .asm_4f5f -.asm_4f59 - call getTileSpriteStandsOn + ld de, wNPCMovementDirections + call LoadDEPlusA ; a = [wNPCMovementDirections + $fe] (?) + jr .determineDirection +.randomMovement + call GetTileSpriteStandsOn call Random -.asm_4f5f +.determineDirection ld b, a ld a, [wCurSpriteMovement2] cp $d0 @@ -199,11 +208,10 @@ Func_4ed1: ; 4ed1 (1:4ed1) cp $2 jr z, .moveLeft ; movement byte 2 = $2 only allows left or right .moveDown - ld de, 2*20 + ld de, 2*SCREEN_WIDTH add hl, de ; move tile pointer two rows down - ld de, $100 - - ld bc, $400 + lb de, 1, 0 + lb bc, 4, SPRITE_FACING_DOWN jr TryWalking .notDown cp $80 ; $40 <= a < $80: up (or right) @@ -212,10 +220,10 @@ Func_4ed1: ; 4ed1 (1:4ed1) cp $2 jr z, .moveRight ; movement byte 2 = $2 only allows left or right .moveUp - ld de, -2*20 ; $ffd8 + ld de, -2*SCREEN_WIDTH add hl, de ; move tile pointer two rows up - ld de, $ff00 - ld bc, $804 + lb de, -1, 0 + lb bc, 8, SPRITE_FACING_UP jr TryWalking .notUp cp $c0 ; $80 <= a < $c0: left (or up) @@ -226,8 +234,8 @@ Func_4ed1: ; 4ed1 (1:4ed1) .moveLeft dec hl dec hl ; move tile pointer two columns left - ld de, $ff - ld bc, $208 + lb de, 0, -1 + lb bc, 2, SPRITE_FACING_LEFT jr TryWalking .notLeft ; $c0 <= a: right (or down) ld a, [wCurSpriteMovement2] @@ -236,12 +244,12 @@ Func_4ed1: ; 4ed1 (1:4ed1) .moveRight inc hl inc hl ; move tile pointer two columns right - ld de, $1 - ld bc, $10c + lb de, 0, 1 + lb bc, 1, SPRITE_FACING_RIGHT jr TryWalking ; changes facing direction by zeroing the movement delta and calling TryWalking -ChangeFacingDirection: ; 4fc8 (1:4fc8) +ChangeFacingDirection: ld de, $0 ; fall through @@ -249,9 +257,9 @@ ChangeFacingDirection: ; 4fc8 (1:4fc8) ; c: new facing direction (0,4,8 or $c) ; d: Y movement delta (-1, 0 or 1) ; e: X movement delta (-1, 0 or 1) -; hl: pointer to tile the sprite would wlak onto +; hl: pointer to tile the sprite would walk onto ; set carry on failure, clears carry on success -TryWalking: ; 4fcb (1:4fcb) +TryWalking: push hl ld h, $c1 ld a, [H_CURRENTSPRITEOFFSET] @@ -290,7 +298,7 @@ TryWalking: ; 4fcb (1:4fcb) jp UpdateSpriteImage ; update the walking animation parameters for a sprite that is currently walking -UpdateSpriteInWalkingAnimation: ; 4ffe (1:4ffe) +UpdateSpriteInWalkingAnimation: ld a, [H_CURRENTSPRITEOFFSET] add $7 ld l, a @@ -363,7 +371,7 @@ UpdateSpriteInWalkingAnimation: ; 4ffe (1:4ffe) ret ; update delay value (c2x8) for sprites in the delayed state (c1x1) -UpdateSpriteMovementDelay: ; 5057 (1:5057) +UpdateSpriteMovementDelay: ld h, $c2 ld a, [H_CURRENTSPRITEOFFSET] add $6 @@ -384,36 +392,40 @@ UpdateSpriteMovementDelay: ; 5057 (1:5057) inc a ld l, a ld [hl], $1 ; c1x1 = 1 (mark as ready to move) -notYetMoving: ; 5073 (1:5073) - ld h, $c1 +notYetMoving: + ld h, wSpriteStateData1 / $100 ld a, [H_CURRENTSPRITEOFFSET] add $8 ld l, a ld [hl], $0 ; c1x8 = 0 (walk animation frame) jp UpdateSpriteImage -InitializeSpriteFacingDirection: ; 507f (1:507f) +MakeNPCFacePlayer: +; Make an NPC face the player if the player has spoken to him or her. + +; Check if the behaviour of the NPC facing the player when spoken to is +; disabled. This is only done when rubbing the S.S. Anne captain's back. ld a, [wd72d] bit 5, a jr nz, notYetMoving res 7, [hl] - ld a, [wd52a] - bit 3, a + ld a, [wPlayerDirection] + bit PLAYER_DIR_BIT_UP, a jr z, .notFacingDown - ld c, $0 ; make sprite face down + ld c, SPRITE_FACING_DOWN jr .facingDirectionDetermined .notFacingDown - bit 2, a + bit PLAYER_DIR_BIT_DOWN, a jr z, .notFacingUp - ld c, $4 ; make sprite face up + ld c, SPRITE_FACING_UP jr .facingDirectionDetermined .notFacingUp - bit 1, a + bit PLAYER_DIR_BIT_LEFT, a jr z, .notFacingRight - ld c, $c ; make sprite face right + ld c, SPRITE_FACING_RIGHT jr .facingDirectionDetermined .notFacingRight - ld c, $8 ; make sprite face left + ld c, SPRITE_FACING_LEFT .facingDirectionDetermined ld a, [H_CURRENTSPRITEOFFSET] add $9 @@ -421,7 +433,7 @@ InitializeSpriteFacingDirection: ; 507f (1:507f) ld [hl], c ; c1x9: set facing direction jr notYetMoving -InitializeSpriteStatus: ; 50ad (1:50ad) +InitializeSpriteStatus: ld [hl], $1 ; $c1x1: set movement status to ready inc l ld [hl], $ff ; $c1x2: set sprite image to $ff (invisible/off screen) @@ -435,12 +447,12 @@ InitializeSpriteStatus: ; 50ad (1:50ad) ret ; calculates the spprite's scrren position form its map position and the player position -InitializeSpriteScreenPosition: ; 50bd (1:50bd) - ld h, $c2 +InitializeSpriteScreenPosition: + ld h, wSpriteStateData2 / $100 ld a, [H_CURRENTSPRITEOFFSET] add $4 ld l, a - ld a, [W_YCOORD] ; wd361 + ld a, [wYCoord] ld b, a ld a, [hl] ; c2x4 (Y position + 4) sub b ; relative to player position @@ -449,7 +461,7 @@ InitializeSpriteScreenPosition: ; 50bd (1:50bd) dec h ld [hli], a ; c1x4 (screen Y position) inc h - ld a, [W_XCOORD] ; wd362 + ld a, [wXCoord] ld b, a ld a, [hli] ; c2x6 (X position + 4) sub b ; relative to player position @@ -459,23 +471,23 @@ InitializeSpriteScreenPosition: ; 50bd (1:50bd) ret ; tests if sprite is off screen or otherwise unable to do anything -CheckSpriteAvailability: ; 50dc (1:50dc) +CheckSpriteAvailability: predef IsObjectHidden ld a, [$ffe5] and a jp nz, .spriteInvisible - ld h, $c2 + ld h, wSpriteStateData2 / $100 ld a, [H_CURRENTSPRITEOFFSET] add $6 ld l, a ld a, [hl] ; c2x6: movement byte 1 cp $fe - jr c, .skipXVisibilityTest ; movement byte 1 < $fe + jr c, .skipXVisibilityTest ; movement byte 1 < $fe (i.e. the sprite's movement is scripted) ld a, [H_CURRENTSPRITEOFFSET] add $4 ld l, a ld b, [hl] ; c2x4: Y pos (+4) - ld a, [W_YCOORD] ; wd361 + ld a, [wYCoord] cp b jr z, .skipYVisibilityTest jr nc, .spriteInvisible ; above screen region @@ -485,7 +497,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc) .skipYVisibilityTest inc l ld b, [hl] ; c2x5: X pos (+4) - ld a, [W_XCOORD] ; wd362 + ld a, [wXCoord] cp b jr z, .skipXVisibilityTest jr nc, .spriteInvisible ; left of screen region @@ -495,7 +507,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc) .skipXVisibilityTest ; make the sprite invisible if a text box is in front of it ; $5F is the maximum number for map tiles - call getTileSpriteStandsOn + call GetTileSpriteStandsOn ld d, $60 ld a, [hli] cp d @@ -503,7 +515,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc) ld a, [hld] cp d jr nc, .spriteInvisible ; standing on tile with ID >=$60 (bottom right tile) - ld bc, -20 ; $ffec + ld bc, -20 add hl, bc ; go back one row of tiles ld a, [hli] cp d @@ -512,7 +524,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc) cp d jr c, .spriteVisible ; standing on tile with ID >=$60 (top right tile) .spriteInvisible - ld h, $c1 + ld h, wSpriteStateData1 / $100 ld a, [H_CURRENTSPRITEOFFSET] add $2 ld l, a @@ -521,7 +533,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc) jr .done .spriteVisible ld c, a - ld a, [wWalkCounter] ; wcfc5 + ld a, [wWalkCounter] and a jr nz, .done ; if player is currently walking, we're done call UpdateSpriteImage @@ -529,7 +541,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc) ld a, [H_CURRENTSPRITEOFFSET] add $7 ld l, a - ld a, [W_GRASSTILE] + ld a, [wGrassTile] cp c ld a, $0 jr nz, .notInGrass @@ -540,7 +552,7 @@ CheckSpriteAvailability: ; 50dc (1:50dc) .done ret -UpdateSpriteImage: ; 5157 (1:5157) +UpdateSpriteImage: ld h, $c1 ld a, [H_CURRENTSPRITEOFFSET] add $8 @@ -565,20 +577,21 @@ UpdateSpriteImage: ; 5157 (1:5157) ; d: Y movement delta (-1, 0 or 1) ; e: X movement delta (-1, 0 or 1) ; set carry on failure, clears carry on success -CanWalkOntoTile: ; 516e (1:516e) - ld h, $c2 +CanWalkOntoTile: + ld h, wSpriteStateData2 / $100 ld a, [H_CURRENTSPRITEOFFSET] add $6 ld l, a ld a, [hl] ; c2x6 (movement byte 1) cp $fe - jr nc, .canMove ; values $fe and $ff + jr nc, .notScripted ; values $fe and $ff +; always allow walking if the movement is scripted and a ret -.canMove - ld a, [W_TILESETCOLLISIONPTR] +.notScripted + ld a, [wTilesetCollisionPtr] ld l, a - ld a, [W_TILESETCOLLISIONPTR+1] + ld a, [wTilesetCollisionPtr+1] ld h, a .tilePassableLoop ld a, [hli] @@ -593,7 +606,7 @@ CanWalkOntoTile: ; 516e (1:516e) ld a, [hl] ; $c2x6 (movement byte 1) inc a jr z, .impassable ; if $ff, no movement allowed (however, changing direction is) - ld h, $c1 + ld h, wSpriteStateData1 / $100 ld a, [H_CURRENTSPRITEOFFSET] add $4 ld l, a @@ -612,14 +625,14 @@ CanWalkOntoTile: ; 516e (1:516e) call DetectCollisionBetweenSprites pop bc pop de - ld h, $c1 + ld h, wSpriteStateData1 / $100 ld a, [H_CURRENTSPRITEOFFSET] add $c ld l, a ld a, [hl] ; c1xc (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, $c2 + ld h, wSpriteStateData2 / $100 ld a, [H_CURRENTSPRITEOFFSET] add $2 ld l, a @@ -675,8 +688,8 @@ CanWalkOntoTile: ; 516e (1:516e) ; calculates the tile pointer pointing to the tile the current sprite stancs on ; this is always the lower left tile of the 2x2 tile blocks all sprites are snapped to ; hl: output pointer -getTileSpriteStandsOn: ; 5207 (1:5207) - ld h, $c1 +GetTileSpriteStandsOn: + ld h, wSpriteStateData1 / $100 ld a, [H_CURRENTSPRITEOFFSET] add $4 ld l, a @@ -690,11 +703,11 @@ getTileSpriteStandsOn: ; 5207 (1:5207) ld a, [hl] ; c1x6: screen Y position srl a srl a - srl a ; screen X tile - add $14 ; screen X tile + 20 + srl a ; screen X tile + add SCREEN_WIDTH ; screen X tile + 20 ld d, $0 ld e, a - ld hl, wTileMap + coord hl, 0, 0 add hl, bc add hl, bc add hl, bc @@ -704,7 +717,7 @@ getTileSpriteStandsOn: ; 5207 (1:5207) ret ; loads [de+a] into a -LoadDEPlusA: ; 522f (1:522f) +LoadDEPlusA: add e ld e, a jr nc, .noCarry @@ -713,53 +726,58 @@ LoadDEPlusA: ; 522f (1:522f) ld a, [de] ret -Func_5236: ; 5236 (1:5236) +DoScriptedNPCMovement: +; This is an alternative method of scripting an NPC's movement and is only used +; a few times in the game. It is used when the NPC and player must walk together +; in sync, such as when the player is following the NPC somewhere. An NPC can't +; be moved in sync with the player using the other method. ld a, [wd730] bit 7, a ret z ld hl, wd72e bit 7, [hl] set 7, [hl] - jp z, Func_52a6 + jp z, InitScriptedNPCMovement ld hl, wNPCMovementDirections2 ld a, [wNPCMovementDirections2Index] add l ld l, a - jr nc, .asm_5251 + jr nc, .noCarry inc h -.asm_5251 +.noCarry ld a, [hl] - cp $40 - jr nz, .asm_525f - call Func_52b2 - ld c, $4 - ld a, $fe - jr .asm_5289 -.asm_525f - cp $0 - jr nz, .asm_526c - call Func_52b2 - ld c, $0 - ld a, $2 - jr .asm_5289 -.asm_526c - cp $80 - jr nz, .asm_5279 - call Func_52b7 - ld c, $8 - ld a, $fe - jr .asm_5289 -.asm_5279 - cp $c0 - jr nz, .asm_5286 - call Func_52b7 - ld c, $c - ld a, $2 - jr .asm_5289 -.asm_5286 +; check if moving up + cp NPC_MOVEMENT_UP + jr nz, .checkIfMovingDown + call GetSpriteScreenYPointer + ld c, SPRITE_FACING_UP + ld a, -2 + jr .move +.checkIfMovingDown + cp NPC_MOVEMENT_DOWN + jr nz, .checkIfMovingLeft + call GetSpriteScreenYPointer + ld c, SPRITE_FACING_DOWN + ld a, 2 + jr .move +.checkIfMovingLeft + cp NPC_MOVEMENT_LEFT + jr nz, .checkIfMovingRight + call GetSpriteScreenXPointer + ld c, SPRITE_FACING_LEFT + ld a, -2 + jr .move +.checkIfMovingRight + cp NPC_MOVEMENT_RIGHT + jr nz, .noMatch + call GetSpriteScreenXPointer + ld c, SPRITE_FACING_RIGHT + ld a, 2 + jr .move +.noMatch cp $ff ret -.asm_5289 +.move ld b, a ld a, [hl] add b @@ -768,33 +786,34 @@ Func_5236: ; 5236 (1:5236) add $9 ld l, a ld a, c - ld [hl], a - call Func_52c3 - ld hl, wcf18 + ld [hl], a ; facing direction + call AnimScriptedNPCMovement + ld hl, wScriptedNPCWalkCounter dec [hl] ret nz - ld a, $8 - ld [wcf18], a + ld a, 8 + ld [wScriptedNPCWalkCounter], a ld hl, wNPCMovementDirections2Index inc [hl] ret -Func_52a6: ; 52a6 (1:52a6) +InitScriptedNPCMovement: xor a ld [wNPCMovementDirections2Index], a - ld a, $8 - ld [wcf18], a - jp Func_52c3 + ld a, 8 + ld [wScriptedNPCWalkCounter], a + jp AnimScriptedNPCMovement -Func_52b2: ; 52b2 (1:52b2) +GetSpriteScreenYPointer: ld a, $4 ld b, a - jr asm_52ba + jr GetSpriteScreenXYPointerCommon -Func_52b7: ; 52b7 (1:52b7) +GetSpriteScreenXPointer: ld a, $6 ld b, a -asm_52ba: ; 52ba (1:52ba) + +GetSpriteScreenXYPointerCommon: ld hl, wSpriteStateData1 ld a, [H_CURRENTSPRITEOFFSET] add l @@ -802,12 +821,12 @@ asm_52ba: ; 52ba (1:52ba) ld l, a ret -Func_52c3: ; 52c3 (1:52c3) +AnimScriptedNPCMovement: ld hl, wSpriteStateData2 ld a, [H_CURRENTSPRITEOFFSET] add $e ld l, a - ld a, [hl] + ld a, [hl] ; VRAM slot dec a swap a ld b, a @@ -815,47 +834,47 @@ Func_52c3: ; 52c3 (1:52c3) ld a, [H_CURRENTSPRITEOFFSET] add $9 ld l, a - ld a, [hl] - cp $0 - jr z, .asm_52ea - cp $4 - jr z, .asm_52ea - cp $8 - jr z, .asm_52ea - cp $c - jr z, .asm_52ea + ld a, [hl] ; facing direction + cp SPRITE_FACING_DOWN + jr z, .anim + cp SPRITE_FACING_UP + jr z, .anim + cp SPRITE_FACING_LEFT + jr z, .anim + cp SPRITE_FACING_RIGHT + jr z, .anim ret -.asm_52ea +.anim add b ld b, a - ld [$ffe9], a - call Func_5301 + ld [hSpriteVRAMSlotAndFacing], a + call AdvanceScriptedNPCAnimFrameCounter ld hl, wSpriteStateData1 ld a, [H_CURRENTSPRITEOFFSET] add $2 ld l, a - ld a, [$ffe9] + ld a, [hSpriteVRAMSlotAndFacing] ld b, a - ld a, [$ffea] + ld a, [hSpriteAnimFrameCounter] add b ld [hl], a ret -Func_5301: ; 5301 (1:5301) +AdvanceScriptedNPCAnimFrameCounter: ld a, [H_CURRENTSPRITEOFFSET] add $7 ld l, a - ld a, [hl] + ld a, [hl] ; intra-animation frame counter inc a ld [hl], a - cp $4 + cp 4 ret nz xor a - ld [hl], a + ld [hl], a ; reset intra-animation frame counter inc l - ld a, [hl] + ld a, [hl] ; animation frame counter inc a and $3 ld [hl], a - ld [$ffea], a + ld [hSpriteAnimFrameCounter], a ret diff --git a/engine/overworld/npc_movement.asm b/engine/overworld/npc_movement.asm index 84e39853..98d1b7a7 100755 --- a/engine/overworld/npc_movement.asm +++ b/engine/overworld/npc_movement.asm @@ -1,4 +1,4 @@ -PlayerStepOutFromDoor: ; 1a3e0 (6:63e0) +PlayerStepOutFromDoor: ld hl, wd730 res 1, [hl] call IsPlayerStandingOnDoorTile @@ -27,7 +27,7 @@ PlayerStepOutFromDoor: ; 1a3e0 (6:63e0) res 7, [hl] ret -_EndNPCMovementScript: ; 1a41d (6:641d) +_EndNPCMovementScript: ld hl, wd730 res 7, [hl] ld hl, wd72e @@ -44,60 +44,66 @@ _EndNPCMovementScript: ; 1a41d (6:641d) ld [wSimulatedJoypadStatesEnd], a ret -ProfOakMovementScriptPointerTable: ; 1a442 (6:6442) - dw Func_1a44c - dw Func_1a485 - dw Func_1a4a1 - dw Func_1a4a6 - dw Func_1a4f4 +PalletMovementScriptPointerTable: + dw PalletMovementScript_OakMoveLeft + dw PalletMovementScript_PlayerMoveLeft + dw PalletMovementScript_WaitAndWalkToLab + dw PalletMovementScript_WalkToLab + dw PalletMovementScript_Done -Func_1a44c: ; 1a44c (6:644c) - ld a, [W_XCOORD] ; wd362 +PalletMovementScript_OakMoveLeft: + ld a, [wXCoord] sub $a - ld [wcca1], a - jr z, .asm_1a475 - ld b, $0 + 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, $80 + ld a, NPC_MOVEMENT_LEFT call FillMemory ld [hl], $ff ld a, [wSpriteIndex] - ld [H_DOWNARROWBLINKCNT2], a ; $ff8c + ld [H_SPRITEINDEX], a ld de, wNPCMovementDirections2 call MoveSprite ld a, $1 ld [wNPCMovementScriptFunctionNum], a - jr .asm_1a47a -.asm_1a475 + 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 -.asm_1a47a - ld hl, W_FLAGS_D733 +.done + ld hl, wFlags_D733 set 1, [hl] ld a, $fc ld [wJoyIgnore], a ret -Func_1a485: ; 1a485 (6:6485) +PalletMovementScript_PlayerMoveLeft: ld a, [wd730] - bit 0, a - ret nz - ld a, [wcca1] + 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 [$ff95], a + ld [hNPCMovementDirections2Index], a predef ConvertNPCMovementDirectionsToJoypadMasks call StartSimulatingJoypadStates ld a, $2 ld [wNPCMovementScriptFunctionNum], a ret -Func_1a4a1: ; 1a4a1 (6:64a1) +PalletMovementScript_WaitAndWalkToLab: ld a, [wSimulatedJoypadStatesIndex] - and a + and a ; is the player done moving left yet? ret nz -Func_1a4a6: ; 1a4a6 (6:64a6) +PalletMovementScript_WalkToLab: xor a ld [wOverrideSimulatedJoypadStatesMask], a ld a, [wSpriteIndex] @@ -121,16 +127,16 @@ Func_1a4a6: ; 1a4a6 (6:64a6) ld [wNPCMovementScriptFunctionNum], a ret -RLEList_ProfOakWalkToLab: ; 1a4dc (6:64dc) - db $00, $05 - db $80, $01 - db $00, $05 - db $C0, $03 - db $40, $01 - db $E0, $01 +RLEList_ProfOakWalkToLab: + db NPC_MOVEMENT_DOWN, $05 + 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: ; 1a4e9 (6:64e9) +RLEList_PlayerWalkToLab: db D_UP, $02 db D_RIGHT, $03 db D_DOWN, $05 @@ -138,12 +144,12 @@ RLEList_PlayerWalkToLab: ; 1a4e9 (6:64e9) db D_DOWN, $06 db $FF -Func_1a4f4: ; 1a4f4 (6:64f4) +PalletMovementScript_Done: ld a, [wSimulatedJoypadStatesIndex] and a ret nz ld a, $0 - ld [wcc4d], a + ld [wMissableObjectIndex], a predef HideObject ld hl, wd730 res 7, [hl] @@ -151,16 +157,16 @@ Func_1a4f4: ; 1a4f4 (6:64f4) res 7, [hl] jp EndNPCMovementScript -PewterMuseumGuyMovementScriptPointerTable: ; 1a510 (6:6510) - dw Func_1a514 - dw PewterMovementScriptDone +PewterMuseumGuyMovementScriptPointerTable: + dw PewterMovementScript_WalkToMuseum + dw PewterMovementScript_Done -Func_1a514: ; 1a514 (6:6514) +PewterMovementScript_WalkToMuseum: ld a, BANK(Music_MuseumGuy) - ld [wc0ef], a - ld [wc0f0], a + ld [wAudioROMBank], a + ld [wAudioSavedROMBank], a ld a, MUSIC_MUSEUM_GUY - ld [wc0ee], a + ld [wNewSoundID], a call PlaySound ld a, [wSpriteIndex] swap a @@ -172,7 +178,7 @@ Func_1a514: ; 1a514 (6:6514) dec a ld [wSimulatedJoypadStatesIndex], a xor a - ld [wd12f], a + ld [wWhichPewterGuy], a predef PewterGuys ld hl, wNPCMovementDirections2 ld de, RLEList_PewterMuseumGuy @@ -183,21 +189,21 @@ Func_1a514: ; 1a514 (6:6514) ld [wNPCMovementScriptFunctionNum], a ret -RLEList_PewterMuseumPlayer: ; 1a559 (6:6559) +RLEList_PewterMuseumPlayer: db 0, $01 db D_UP, $03 db D_LEFT, $0D db D_UP, $06 db $FF -RLEList_PewterMuseumGuy: ; 1a562 (6:6562) - db $40, $06 - db $80, $0D - db $40, $03 - db $80, $01 +RLEList_PewterMuseumGuy: + db NPC_MOVEMENT_UP, $06 + db NPC_MOVEMENT_LEFT, $0D + db NPC_MOVEMENT_UP, $03 + db NPC_MOVEMENT_LEFT, $01 db $FF -PewterMovementScriptDone: ; 1a56b (6:656b) +PewterMovementScript_Done: ld a, [wSimulatedJoypadStatesIndex] and a ret nz @@ -207,16 +213,16 @@ PewterMovementScriptDone: ; 1a56b (6:656b) res 7, [hl] jp EndNPCMovementScript -PewterGymGuyMovementScriptPointerTable: ; 1a57d (6:657d) - dw Func_1a581 - dw PewterMovementScriptDone +PewterGymGuyMovementScriptPointerTable: + dw PewterMovementScript_WalkToGym + dw PewterMovementScript_Done -Func_1a581: ; 1a581 (6:6581) +PewterMovementScript_WalkToGym: ld a, BANK(Music_MuseumGuy) - ld [wc0ef], a - ld [wc0f0], a + ld [wAudioROMBank], a + ld [wAudioSavedROMBank], a ld a, MUSIC_MUSEUM_GUY - ld [wc0ee], a + ld [wNewSoundID], a call PlaySound ld a, [wSpriteIndex] swap a @@ -228,8 +234,8 @@ Func_1a581: ; 1a581 (6:6581) call DecodeRLEList dec a ld [wSimulatedJoypadStatesIndex], a - ld a, $1 - ld [wd12f], a + ld a, 1 + ld [wWhichPewterGuy], a predef PewterGuys ld hl, wNPCMovementDirections2 ld de, RLEList_PewterGymGuy @@ -242,7 +248,7 @@ Func_1a581: ; 1a581 (6:6581) ld [wNPCMovementScriptFunctionNum], a ret -RLEList_PewterGymPlayer: ; 1a5cd (6:65cd) +RLEList_PewterGymPlayer: db 0, $01 db D_RIGHT, $02 db D_DOWN, $05 @@ -251,17 +257,17 @@ RLEList_PewterGymPlayer: ; 1a5cd (6:65cd) db D_LEFT, $0F db $FF -RLEList_PewterGymGuy: ; 1a5da (6:65da) - db $00, $02 - db $80, $0F - db $40, $05 - db $80, $0B - db $00, $05 - db $C0, $03 +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 -FreezeEnemyTrainerSprite: ; 1a5e7 (6:65e7) - ld a, [W_CURMAP] +FreezeEnemyTrainerSprite: + ld a, [wCurMap] cp POKEMONTOWER_7 ret z ; the Rockets on Pokemon Tower 7F leave after battling, so don't freeze them ld hl, RivalIDs @@ -279,8 +285,8 @@ FreezeEnemyTrainerSprite: ; 1a5e7 (6:65e7) ld [H_SPRITEINDEX], a jp SetSpriteMovementBytesToFF -RivalIDs: ; 1a605 (6:6605) - db SONY1 + $c8 - db SONY2 + $c8 - db SONY3 + $c8 +RivalIDs: + db OPP_SONY1 + db OPP_SONY2 + db OPP_SONY3 db $ff diff --git a/engine/overworld/oaks_aide.asm b/engine/overworld/oaks_aide.asm index 68135287..f5068fda 100755 --- a/engine/overworld/oaks_aide.asm +++ b/engine/overworld/oaks_aide.asm @@ -1,71 +1,71 @@ -OaksAideScript ; 0x59035 +OaksAideScript: ld hl, OaksAideHiText call PrintText call YesNoChoice ld a, [wCurrentMenuItem] and a - jr nz, .asm_59086 ; 0x59042 $42 + jr nz, .choseNo ld hl, wPokedexOwned ld b, wPokedexOwnedEnd - wPokedexOwned call CountSetBits - ld a, [wd11e] - ld [$ffdd], a + ld a, [wNumSetBits] + ld [hOaksAideNumMonsOwned], a ld b, a - ld a, [$ffdb] + ld a, [hOaksAideRequirement] cp b - jr z, .asm_59059 ; 0x59055 $2 - jr nc, .asm_5907c ; 0x59057 $23 -.asm_59059 + jr z, .giveItem + jr nc, .notEnoughOwnedMons +.giveItem ld hl, OaksAideHereYouGoText call PrintText - ld a, [$ffdc] + ld a, [hOaksAideRewardItem] ld b, a ld c, 1 call GiveItem - jr nc, .BagFull + jr nc, .bagFull ld hl, OaksAideGotItemText call PrintText ld a, $1 - jr .asm_5908e ; 0x59071 $1b -.BagFull + jr .done +.bagFull ld hl, OaksAideNoRoomText call PrintText xor a - jr .asm_5908e ; 0x5907a $12 -.asm_5907c + jr .done +.notEnoughOwnedMons ld hl, OaksAideUhOhText call PrintText ld a, $80 - jr .asm_5908e ; 0x59084 $8 -.asm_59086 + jr .done +.choseNo ld hl, OaksAideComeBackText call PrintText ld a, $ff -.asm_5908e - ld [$ffdb], a +.done + ld [hOaksAideResult], a ret -OaksAideHiText: ; 59091 (16:5091) +OaksAideHiText: TX_FAR _OaksAideHiText db "@" -OaksAideUhOhText: ; 59096 (16:5096) +OaksAideUhOhText: TX_FAR _OaksAideUhOhText db "@" -OaksAideComeBackText: ; 5909b (16:509b) +OaksAideComeBackText: TX_FAR _OaksAideComeBackText db "@" -OaksAideHereYouGoText: ; 590a0 (16:50a0) +OaksAideHereYouGoText: TX_FAR _OaksAideHereYouGoText db "@" -OaksAideGotItemText: ; 590a5 (16:50a5) +OaksAideGotItemText: TX_FAR _OaksAideGotItemText - db $0b + TX_SFX_ITEM_1 db "@" -OaksAideNoRoomText: ; 590ab (16:50ab) +OaksAideNoRoomText: TX_FAR _OaksAideNoRoomText db "@" diff --git a/engine/overworld/oam.asm b/engine/overworld/oam.asm index b4247257..2c2a3dff 100644 --- a/engine/overworld/oam.asm +++ b/engine/overworld/oam.asm @@ -4,25 +4,26 @@ PrepareOAMData: ld a, [wUpdateSpritesEnabled] dec a - jr z, .asm_4b1e + jr z, .updateEnabled - cp 0 - 1 + cp -1 ret nz ld [wUpdateSpritesEnabled], a jp HideSprites -.asm_4b1e +.updateEnabled xor a - ld [$ff90], a -.asm_4b21 - ld [$ff8f], a + ld [hOAMBufferOffset], a + +.spriteLoop + ld [hSpriteOffset2], a ld d, wSpriteStateData1 / $100 - ld a, [$ff8f] + ld a, [hSpriteOffset2] ld e, a ld a, [de] ; c1x0 and a - jp z, .asm_4bad + jp z, .nextSprite inc e inc e @@ -31,21 +32,25 @@ PrepareOAMData: cp $ff ; off-screen (don't draw) jr nz, .visible - call Func_4bd1 - jr .asm_4bad + call GetSpriteScreenXY + jr .nextSprite .visible - cp $a0 + cp $a0 ; is the sprite unchanging like an item ball or boulder? jr c, .usefacing + +; unchanging and $f - add $10 - jr .asm_4b48 + add $10 ; skip to the second half of the table which doesn't account for facing direction + jr .next .usefacing and $f -.asm_4b48 + +.next ld l, a +; get sprite priority push de inc d ld a, e @@ -53,15 +58,15 @@ PrepareOAMData: ld e, a ld a, [de] ; c2x7 and $80 - ld [$ff94], a ; temp store sprite priority + ld [hSpritePriority], a ; temp store sprite priority pop de +; read the entry from the table ld h, 0 ld bc, SpriteFacingAndAnimationTable add hl, hl add hl, hl add hl, bc - ld a, [hli] ld c, a ld a, [hli] @@ -70,24 +75,25 @@ PrepareOAMData: ld h, [hl] ld l, a - call Func_4bd1 + call GetSpriteScreenXY - ld a, [$ff90] + ld a, [hOAMBufferOffset] ld e, a ld d, wOAMBuffer / $100 -.tile - ld a, [$ff92] ; temp for sprite Y position + +.tileLoop + 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 - ld a, [$ff91] ; temp for sprite X position + 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 inc e ld [de], a ; write new sprite OAM X position inc e - ld a, [bc] ; read pattern number offset (accomodates orientation (offset 0,4 or 8) and animation (offset 0 or $80)) + ld a, [bc] ; read pattern number offset (accommodates orientation (offset 0,4 or 8) and animation (offset 0 or $80)) inc bc push bc ld b, a @@ -99,55 +105,60 @@ PrepareOAMData: ; 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, .offset + jr nz, .notFourTileSprite ld a, $a * 12 + 4 - jr .gotoffset + jr .next2 -.offset +.notFourTileSprite ; a *= 12 sla a sla a ld c, a sla a add c -.gotoffset - add b ; which frame + +.next2 + add b ; add the tile offset from the table (based on frame and facing direction) pop bc ld [de], a ; tile id inc hl inc e ld a, [hl] - bit 1, a ; sprite priority - jr z, .fg - ld a, [$ff94] ; facing priority + bit 1, a ; is the tile allowed to set the sprite priority bit? + jr z, .skipPriority + ld a, [hSpritePriority] or [hl] -.fg +.skipPriority inc hl ld [de], a inc e bit 0, a ; OAMFLAG_ENDOFDATA - jr z, .tile + jr z, .tileLoop ld a, e - ld [$ff90], a + ld [hOAMBufferOffset], a -.asm_4bad - ld a, [$ff8f] +.nextSprite + ld a, [hSpriteOffset2] add $10 cp $100 % $100 - jp nz, .asm_4b21 + jp nz, .spriteLoop ; Clear unused OAM. - ld a, [$ff90] + ld a, [hOAMBufferOffset] ld l, a ld h, wOAMBuffer / $100 ld de, $4 ld b, $a0 ld a, [wd736] - bit 6, a + bit 6, a ; jumping down ledge or fishing animation? ld a, $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 a, $90 + .clear cp l ret z @@ -155,24 +166,24 @@ PrepareOAMData: add hl, de jr .clear -Func_4bd1: ; 4bd1 (1:4bd1) +GetSpriteScreenXY: inc e inc e ld a, [de] ; c1x4 - ld [$ff92], a + ld [hSpriteScreenY], a inc e inc e ld a, [de] ; c1x6 - ld [$ff91], a - ld a, $4 + ld [hSpriteScreenX], a + ld a, 4 add e ld e, a - ld a, [$ff92] - add $4 + ld a, [hSpriteScreenY] + add 4 and $f0 ld [de], a ; c1xa (y) inc e - ld a, [$ff91] + ld a, [hSpriteScreenX] and $f0 ld [de], a ; c1xb (x) ret diff --git a/engine/overworld/pewter_guys.asm b/engine/overworld/pewter_guys.asm index eb6dd5ac..532fa4bf 100755 --- a/engine/overworld/pewter_guys.asm +++ b/engine/overworld/pewter_guys.asm @@ -1,4 +1,4 @@ -PewterGuys: ; 37ca1 (d:7ca1) +PewterGuys: ld hl, wSimulatedJoypadStatesEnd ld a, [wSimulatedJoypadStatesIndex] dec a ; this decrement causes it to overwrite the last byte before $FF in the list @@ -9,7 +9,7 @@ PewterGuys: ; 37ca1 (d:7ca1) ld d, h ld e, l ld hl, PointerTable_37ce6 - ld a, [wd12f] + ld a, [wWhichPewterGuy] add a ld b, 0 ld c, a @@ -17,21 +17,21 @@ PewterGuys: ; 37ca1 (d:7ca1) ld a, [hli] ld h, [hl] ld l, a - ld a, [W_YCOORD] + ld a, [wYCoord] ld b, a - ld a, [W_XCOORD] + ld a, [wXCoord] ld c, a -.asm_37cc7 +.findMatchingCoordsLoop ld a, [hli] cp b - jr nz, .asm_37ce1 + jr nz, .nextEntry1 ld a, [hli] cp c - jr nz, .asm_37ce2 + jr nz, .nextEntry2 ld a, [hli] ld h, [hl] ld l, a -.asm_37cd2 +.copyMovementDataLoop ld a, [hli] cp $ff ret z @@ -40,22 +40,22 @@ PewterGuys: ; 37ca1 (d:7ca1) ld a, [wSimulatedJoypadStatesIndex] inc a ld [wSimulatedJoypadStatesIndex], a - jr .asm_37cd2 -.asm_37ce1 + jr .copyMovementDataLoop +.nextEntry1 inc hl -.asm_37ce2 +.nextEntry2 inc hl inc hl - jr .asm_37cc7 + jr .findMatchingCoordsLoop -PointerTable_37ce6: ; 37ce6 (d:7ce6) +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: ; 37cea (d:7cea) +PewterMuseumGuyCoords: db 18, 27 dw .down db 16, 27 @@ -66,18 +66,19 @@ PewterMuseumGuyCoords: ; 37cea (d:7cea) dw .right .down - db $40, $40, $ff + db D_UP, D_UP, $ff .up - db $10, $20, $ff + db D_RIGHT, D_LEFT, $ff .left - db $40, $10, $ff + db D_UP, D_RIGHT, $ff .right - db $40, $20, $ff + 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 -PewterGymGuyCoords: ; 37d06 (d:7d06) +; $00 is a pause +PewterGymGuyCoords: db 16, 34 dw .one db 17, 35 @@ -90,12 +91,12 @@ PewterGymGuyCoords: ; 37d06 (d:7d06) dw .five .one - db $20, $80, $80, $10, $ff + db D_LEFT, D_DOWN, D_DOWN, D_RIGHT, $ff .two - db $20, $80, $10, $20, $ff + db D_LEFT, D_DOWN, D_RIGHT, D_LEFT, $ff .three - db $20, $20, $20, $00, $00, $00, $00, $00, $00, $00, $00, $ff + db D_LEFT, D_LEFT, D_LEFT, $00, $00, $00, $00, $00, $00, $00, $00, $ff .four - db $20, $20, $40, $20, $ff + db D_LEFT, D_LEFT, D_UP, D_LEFT, $ff .five - db $20, $80, $20, $00, $00, $00, $00, $00, $00, $00, $00, $ff + 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 6602cedd..a17e67bd 100755 --- a/engine/overworld/player_animations.asm +++ b/engine/overworld/player_animations.asm @@ -1,15 +1,15 @@ -EnterMapAnim: ; 70510 (1c:4510) - call InitFacingDirectionBuffer +EnterMapAnim: + call InitFacingDirectionList ld a, $ec ld [wSpriteStateData1 + 4], a ; player's sprite Y screen position call Delay3 push hl call GBFadeInFromWhite - ld hl, W_FLAGS_D733 + ld hl, wFlags_D733 bit 7, [hl] ; used fly out of battle? res 7, [hl] jr nz, .flyAnimation - ld a, (SFX_02_4c - SFX_Headers_02) / 3 + ld a, SFX_TELEPORT_ENTER_1 call PlaySound ld hl, wd732 bit 4, [hl] ; used dungeon warp? @@ -17,7 +17,7 @@ EnterMapAnim: ; 70510 (1c:4510) pop hl jr nz, .dungeonWarpAnimation call PlayerSpinWhileMovingDown - ld a, (SFX_02_4f - SFX_Headers_02) / 3 + ld a, SFX_TELEPORT_ENTER_2 call PlaySound call IsPlayerStandingOnWarpPadOrHole ld a, b @@ -32,7 +32,7 @@ EnterMapAnim: ; 70510 (1c:4510) ld a, $8 ld [hli], a ; wPlayerSpinInPlaceAnimFrameDelayEndValue ld [hl], $ff ; wPlayerSpinInPlaceAnimSoundID - ld hl, wcd48 + ld hl, wFacingDirectionList call PlayerSpinInPlace .restoreDefaultMusic call PlayDefaultMusic @@ -47,10 +47,10 @@ EnterMapAnim: ; 70510 (1c:4510) pop hl ld de, BirdSprite ld hl, vNPCSprites - ld bc, (BANK(BirdSprite) << 8) + $0c + lb bc, BANK(BirdSprite), $0c call CopyVideoData call LoadBirdSpriteGraphics - ld a, (SFX_02_50 - SFX_Headers_02) / 3 + ld a, SFX_FLY call PlaySound ld hl, wFlyAnimUsingCoordList xor a ; is using coord list @@ -58,12 +58,12 @@ EnterMapAnim: ; 70510 (1c:4510) ld a, 12 ld [hli], a ; wFlyAnimCounter ld [hl], $8 ; wFlyAnimBirdSpriteImageIndex (facing right) - ld de, FlyAnimationEnterScreenCoords ; $4592 + ld de, FlyAnimationEnterScreenCoords call DoFlyAnimation call LoadPlayerSpriteGraphics jr .restoreDefaultMusic -FlyAnimationEnterScreenCoords: ; 70592 (1c:4592) +FlyAnimationEnterScreenCoords: ; y, x pairs ; This is the sequence of screen coordinates used by the overworld ; Fly animation when the player is entering a map. @@ -80,7 +80,7 @@ FlyAnimationEnterScreenCoords: ; 70592 (1c:4592) db $3C, $48 db $3C, $40 -PlayerSpinWhileMovingDown: ; 705aa (1c:45aa) +PlayerSpinWhileMovingDown: ld hl, wPlayerSpinWhileMovingUpOrDownAnimDeltaY ld a, $10 ld [hli], a ; wPlayerSpinWhileMovingUpOrDownAnimDeltaY @@ -90,8 +90,8 @@ PlayerSpinWhileMovingDown: ; 705aa (1c:45aa) ld [hl], a ; wPlayerSpinWhileMovingUpOrDownAnimFrameDelay jp PlayerSpinWhileMovingUpOrDown -_LeaveMapAnim: ; 705ba (1c:45ba) - call InitFacingDirectionBuffer +_LeaveMapAnim: + call InitFacingDirectionList call IsPlayerStandingOnWarpPadOrHole ld a, b and a @@ -99,7 +99,7 @@ _LeaveMapAnim: ; 705ba (1c:45ba) dec a jp nz, LeaveMapThroughHoleAnim .spinWhileMovingUp - ld a, (SFX_02_4b - SFX_Headers_02) / 3 + ld a, SFX_TELEPORT_EXIT_1 call PlaySound ld hl, wPlayerSpinWhileMovingUpOrDownAnimDeltaY ld a, -$10 @@ -133,8 +133,8 @@ _LeaveMapAnim: ; 705ba (1c:45ba) ld [hli], a ; wPlayerSpinInPlaceAnimFrameDelayDelta xor a ld [hli], a ; wPlayerSpinInPlaceAnimFrameDelayEndValue - ld [hl], (SFX_02_4d - SFX_Headers_02) / 3 ; wPlayerSpinInPlaceAnimSoundID - ld hl, wcd48 + ld [hl], SFX_TELEPORT_EXIT_2 ; wPlayerSpinInPlaceAnimSoundID + ld hl, wFacingDirectionList call PlayerSpinInPlace jr .spinWhileMovingUp .flyAnimation @@ -146,7 +146,7 @@ _LeaveMapAnim: ; 705ba (1c:45ba) ld [hli], a ; wFlyAnimCounter ld [hl], $c ; wFlyAnimBirdSpriteImageIndex call DoFlyAnimation - ld a, (SFX_02_50 - SFX_Headers_02) / 3 + ld a, SFX_FLY call PlaySound ld hl, wFlyAnimUsingCoordList xor a ; is using coord list @@ -154,7 +154,7 @@ _LeaveMapAnim: ; 705ba (1c:45ba) ld a, $c ld [hli], a ; wFlyAnimCounter ld [hl], $c ; wFlyAnimBirdSpriteImageIndex (facing right) - ld de, FlyAnimationScreenCoords1 ; $464f + ld de, FlyAnimationScreenCoords1 call DoFlyAnimation ld c, 40 call DelayFrames @@ -162,12 +162,12 @@ _LeaveMapAnim: ; 705ba (1c:45ba) ld a, 11 ld [hli], a ; wFlyAnimCounter ld [hl], $8 ; wFlyAnimBirdSpriteImageIndex (facing left) - ld de, FlyAnimationScreenCoords2 ; $4667 + ld de, FlyAnimationScreenCoords2 call DoFlyAnimation call GBFadeOutToWhite jp RestoreFacingDirectionAndYScreenPos -FlyAnimationScreenCoords1: ; 7064f (1c:464f) +FlyAnimationScreenCoords1: ; y, x pairs ; This is the sequence of screen coordinates used by the first part ; of the Fly overworld animation. @@ -184,7 +184,7 @@ FlyAnimationScreenCoords1: ; 7064f (1c:464f) db $2A, $98 db $27, $A0 -FlyAnimationScreenCoords2: ; 70667 (1c:4667) +FlyAnimationScreenCoords2: ; y, x pairs ; This is the sequence of screen coordinates used by the second part ; of the Fly overworld animation. @@ -201,7 +201,7 @@ FlyAnimationScreenCoords2: ; 70667 (1c:4667) db $F0, $00 -LeaveMapThroughHoleAnim: ; 7067d (1c:467d) +LeaveMapThroughHoleAnim: ld a, $ff ld [wUpdateSpritesEnabled], a ; disable UpdateSprites ; shift upper half of player's sprite down 8 pixels and hide lower half @@ -214,7 +214,7 @@ LeaveMapThroughHoleAnim: ; 7067d (1c:467d) ld [wOAMBuffer + 1 * 4], a ld c, 2 call DelayFrames - ; hide lower half of player's sprite + ; hide upper half of player's sprite ld a, $a0 ld [wOAMBuffer + 2 * 4], a ld [wOAMBuffer + 3 * 4], a @@ -223,7 +223,7 @@ LeaveMapThroughHoleAnim: ; 7067d (1c:467d) ld [wUpdateSpritesEnabled], a ; enable UpdateSprites jp RestoreFacingDirectionAndYScreenPos -DoFlyAnimation: ; 706ae (1c:46ae) +DoFlyAnimation: ld a, [wFlyAnimBirdSpriteImageIndex] xor $1 ; make the bird flap its wings ld [wFlyAnimBirdSpriteImageIndex], a @@ -231,7 +231,7 @@ DoFlyAnimation: ; 706ae (1c:46ae) call Delay3 ld a, [wFlyAnimUsingCoordList] cp $ff - jr z, .asm_706cd + jr z, .skipCopyingCoords ; if the bird is flapping its wings in place ld hl, wSpriteStateData1 + 4 ld a, [de] inc de @@ -240,34 +240,35 @@ DoFlyAnimation: ; 706ae (1c:46ae) ld a, [de] inc de ld [hl], a -.asm_706cd +.skipCopyingCoords ld a, [wFlyAnimCounter] dec a ld [wFlyAnimCounter], a jr nz, DoFlyAnimation ret -LoadBirdSpriteGraphics: ; 706d7 (1c:46d7) - ld de, BirdSprite ; $4d80 +LoadBirdSpriteGraphics: + ld de, BirdSprite ld hl, vNPCSprites - ld bc, (BANK(BirdSprite) << 8) + $0c + lb bc, BANK(BirdSprite), $0c call CopyVideoData - ld de, BirdSprite + $c0 ; $4e40 ; moving amination sprite + ld de, BirdSprite + $c0 ; moving animation sprite ld hl, vNPCSprites2 - ld bc, (BANK(BirdSprite) << 8) + $0c + lb bc, BANK(BirdSprite), $0c jp CopyVideoData -InitFacingDirectionBuffer: ; 706ef (1c:46ef) +InitFacingDirectionList: ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction (image index is locked to standing images) - ld [wcd50], a + ld [wSavedPlayerFacingDirection], a ld a, [wSpriteStateData1 + 4] ; player's sprite Y screen position - ld [wcd4f], a + ld [wSavedPlayerScreenY], a ld hl, PlayerSpinningFacingOrder - ld de, wcd48 - ld bc, $4 + 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 hl, wcd48 + ld hl, wFacingDirectionList +; find the place in the list that matches the current facing direction .loop cp [hl] inc hl @@ -275,34 +276,36 @@ InitFacingDirectionBuffer: ; 706ef (1c:46ef) dec hl ret -PlayerSpinningFacingOrder: ; 70713 (1c:4713) +PlayerSpinningFacingOrder: ; The order of the direction the player's sprite is facing when teleporting ; away. Creates a spinning effect. db SPRITE_FACING_DOWN, SPRITE_FACING_LEFT, SPRITE_FACING_UP, SPRITE_FACING_RIGHT -SpinPlayerSprite: ; 70717 (1c:4717) +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) push hl - ld hl, wcd48 - ld de, wcd47 - ld bc, $4 + ld hl, wFacingDirectionList + ld de, wFacingDirectionList - 1 + ld bc, 4 call CopyData - ld a, [wcd47] - ld [wcd4b], a + ld a, [wFacingDirectionList - 1] + ld [wFacingDirectionList + 3], a pop hl ret -PlayerSpinInPlace: ; 70730 (1c:4730) +PlayerSpinInPlace: call SpinPlayerSprite ld a, [wPlayerSpinInPlaceAnimFrameDelay] ld c, a and $3 - jr nz, .asm_70743 + jr nz, .skipPlayingSound +; when the last delay was a multiple of 4, play a sound if there is one ld a, [wPlayerSpinInPlaceAnimSoundID] cp $ff call nz, PlaySound -.asm_70743 +.skipPlayingSound ld a, [wPlayerSpinInPlaceAnimFrameDelayDelta] add c ld [wPlayerSpinInPlaceAnimFrameDelay], a @@ -313,7 +316,7 @@ PlayerSpinInPlace: ; 70730 (1c:4730) call DelayFrames jr PlayerSpinInPlace -PlayerSpinWhileMovingUpOrDown: ; 70755 (1c:4755) +PlayerSpinWhileMovingUpOrDown: call SpinPlayerSprite ld a, [wPlayerSpinWhileMovingUpOrDownAnimDeltaY] ld c, a @@ -329,25 +332,25 @@ PlayerSpinWhileMovingUpOrDown: ; 70755 (1c:4755) call DelayFrames jr PlayerSpinWhileMovingUpOrDown -RestoreFacingDirectionAndYScreenPos: ; 70772 (1c:4772) - ld a, [wcd4f] +RestoreFacingDirectionAndYScreenPos: + ld a, [wSavedPlayerScreenY] ld [wSpriteStateData1 + 4], a - ld a, [wcd50] + ld a, [wSavedPlayerFacingDirection] ld [wSpriteStateData1 + 2], a ret ; if SGB, 2 frames, else 3 frames -GetPlayerTeleportAnimFrameDelay: ; 7077f (1c:477f) +GetPlayerTeleportAnimFrameDelay: ld a, [wOnSGB] xor $1 inc a inc a ret -IsPlayerStandingOnWarpPadOrHole: ; 70787 (1c:4787) +IsPlayerStandingOnWarpPadOrHole: ld b, 0 ld hl, .warpPadAndHoleData - ld a, [W_CURMAPTILESET] + ld a, [wCurMapTileset] ld c, a .loop ld a, [hli] @@ -367,99 +370,111 @@ IsPlayerStandingOnWarpPadOrHole: ; 70787 (1c:4787) ld b, [hl] .done ld a, b - ld [wcd5b], a + ld [wStandingOnWarpPadOrHole], a ret -; format: db tileset id, tile id, value to be put in wcd5b -.warpPadAndHoleData: ; 707a9 (1c:47a9) +; 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 -Func_707b6: ; 707b6 (1c:47b6) - ld c, $a +FishingAnim: + ld c, 10 call DelayFrames ld hl, wd736 - set 6, [hl] - ld de, RedSprite ; $4180 + set 6, [hl] ; reserve the last 4 OAM entries + ld de, RedSprite ld hl, vNPCSprites - ld bc, (BANK(RedSprite) << 8) + $0c + lb bc, BANK(RedSprite), $c call CopyVideoData ld a, $4 - ld hl, RedFishingTiles ; $4866 + ld hl, RedFishingTiles call LoadAnimSpriteGfx ld a, [wSpriteStateData1 + 2] ld c, a ld b, $0 - ld hl, FishingRodGfxProperties ; $4856 + ld hl, FishingRodOAM add hl, bc ld de, wOAMBuffer + $9c ld bc, $4 call CopyData - ld c, $64 + ld c, 100 call DelayFrames - ld a, [wWhichTrade] ; wWhichTrade + ld a, [wRodResponse] and a ld hl, NoNibbleText - jr z, .asm_70836 + jr z, .done cp $2 ld hl, NothingHereText - jr z, .asm_70836 - ld b, $a -.asm_707fe - ld hl, wSpriteStateData1 + 4 - call Func_70842 + jr z, .done + +; there was a bite + +; shake the player's sprite vertically + ld b, 10 +.loop + ld hl, wSpriteStateData1 + 4 ; player's sprite Y screen position + call .ShakePlayerSprite ld hl, wOAMBuffer + $9c - call Func_70842 + call .ShakePlayerSprite call Delay3 dec b - jr nz, .asm_707fe - ld a, [wSpriteStateData1 + 2] - cp $4 - jr nz, .asm_7081c + jr nz, .loop + +; 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 + cp SPRITE_FACING_UP + jr nz, .skipHidingFishingRod ld a, $a0 ld [wOAMBuffer + $9c], a -.asm_7081c - ld hl, wcd4f + +.skipHidingFishingRod + ld hl, wEmotionBubbleSpriteIndex xor a - ld [hli], a - ld [hl], a + ld [hli], a ; player's sprite + ld [hl], a ; EXCLAMATION_BUBBLE predef EmotionBubble - ld a, [wSpriteStateData1 + 2] - cp $4 - jr nz, .asm_70833 + +; If the player is facing up, unhide the fishing rod. + ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction + cp SPRITE_FACING_UP + jr nz, .skipUnhidingFishingRod ld a, $44 ld [wOAMBuffer + $9c], a -.asm_70833 + +.skipUnhidingFishingRod ld hl, ItsABiteText -.asm_70836 + +.done call PrintText ld hl, wd736 - res 6, [hl] + res 6, [hl] ; unreserve the last 4 OAM entries call LoadFontTilePatterns ret -Func_70842: ; 70842 (1c:4842) +.ShakePlayerSprite ld a, [hl] xor $1 ld [hl], a ret -NoNibbleText: ; 70847 (1c:4847) +NoNibbleText: TX_FAR _NoNibbleText db "@" -NothingHereText: ; 7084c (1c:484c) +NothingHereText: TX_FAR _NothingHereText db "@" -ItsABiteText: ; 70851 (1c:4851) +ItsABiteText: TX_FAR _ItsABiteText db "@" -FishingRodGfxProperties: ; 70856 (1c:4856) +FishingRodOAM: ; specifies how the fishing rod should be drawn on the screen ; first byte = screen y coordinate ; second byte = screen x coordinate @@ -470,7 +485,7 @@ FishingRodGfxProperties: ; 70856 (1c:4856) db $50, $40, $FE, $00 ; player facing left db $50, $58, $FE, $20 ; player facing right ($20 means "horizontally flip the tile") -RedFishingTiles: ; 70866 (1c:4866) +RedFishingTiles: dw RedFishingTilesFront db 2, BANK(RedFishingTilesFront) dw vNPCSprites + $20 @@ -487,7 +502,7 @@ RedFishingTiles: ; 70866 (1c:4866) db 3, BANK(RedFishingRodTiles) dw vNPCSprites2 + $7d0 -_HandleMidJump: ; 7087e (1c:487e) +_HandleMidJump: ld a, [wPlayerJumpingYScreenCoordsIndex] ld c, a inc a @@ -519,6 +534,6 @@ _HandleMidJump: ; 7087e (1c:487e) ld [wJoyIgnore], a ret -PlayerJumpingYScreenCoords: ; 708ba (1c:48ba) +PlayerJumpingYScreenCoords: ; Sequence of y screen coordinates for player's sprite when jumping over a ledge. db $38, $36, $34, $32, $31, $30, $30, $30, $31, $32, $33, $34, $36, $38, $3C, $3C diff --git a/engine/overworld/player_state.asm b/engine/overworld/player_state.asm new file mode 100644 index 00000000..79f755b9 --- /dev/null +++ b/engine/overworld/player_state.asm @@ -0,0 +1,463 @@ +; only used for setting bit 2 of wd736 upon entering a new map +IsPlayerStandingOnWarp: + ld a, [wNumberOfWarps] + and a + ret z + ld c, a + ld hl, wWarpEntries +.loop + ld a, [wYCoord] + cp [hl] + jr nz, .nextWarp1 + inc hl + ld a, [wXCoord] + cp [hl] + jr nz, .nextWarp2 + inc hl + ld a, [hli] ; target warp + ld [wDestinationWarpID], a + ld a, [hl] ; target map + ld [hWarpDestinationMap], a + ld hl, wd736 + set 2, [hl] ; standing on warp flag + ret +.nextWarp1 + inc hl +.nextWarp2 + inc hl + inc hl + inc hl + dec c + jr nz, .loop + ret + +CheckForceBikeOrSurf: + ld hl, wd732 + bit 5, [hl] + ret nz + ld hl, ForcedBikeOrSurfMaps + ld a, [wYCoord] + ld b, a + ld a, [wXCoord] + ld c, a + ld a, [wCurMap] + ld d, a +.loop + ld a, [hli] + cp $ff + ret z ;if we reach FF then it's not part of the list + cp d ;compare to current map + jr nz, .incorrectMap + ld a, [hli] + cp b ;compare y-coord + jr nz, .incorrectY + ld a, [hli] + cp c ;compare x-coord + jr nz, .loop ; incorrect x-coord, check next item + ld a, [wCurMap] + cp SEAFOAM_ISLANDS_4 + ld a, $2 + ld [wSeafoamIslands4CurScript], a + jr z, .forceSurfing + ld a, [wCurMap] + cp SEAFOAM_ISLANDS_5 + ld a, $2 + ld [wSeafoamIslands5CurScript], a + jr z, .forceSurfing + ;force bike riding + ld hl, wd732 + set 5, [hl] + ld a, $1 + ld [wWalkBikeSurfState], a + ld [wWalkBikeSurfStateCopy], a + jp ForceBikeOrSurf +.incorrectMap + inc hl +.incorrectY + inc hl + jr .loop +.forceSurfing + ld a, $2 + ld [wWalkBikeSurfState], a + ld [wWalkBikeSurfStateCopy], a + jp ForceBikeOrSurf + +INCLUDE "data/force_bike_surf.asm" + +IsPlayerFacingEdgeOfMap: + push hl + push de + push bc + ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction + srl a + ld c, a + ld b, $0 + ld hl, .functionPointerTable + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wYCoord] + ld b, a + ld a, [wXCoord] + ld c, a + ld de, .asm_c41e + push de + jp [hl] +.asm_c41e + pop bc + pop de + pop hl + ret + +.functionPointerTable + dw .facingDown + dw .facingUp + dw .facingLeft + dw .facingRight + +.facingDown + ld a, [wCurMapHeight] + add a + dec a + cp b + jr z, .setCarry + jr .resetCarry + +.facingUp + ld a, b + and a + jr z, .setCarry + jr .resetCarry + +.facingLeft + ld a, c + and a + jr z, .setCarry + jr .resetCarry + +.facingRight + ld a, [wCurMapWidth] + add a + dec a + cp c + jr z, .setCarry + jr .resetCarry +.resetCarry + and a + ret +.setCarry + scf + ret + +IsWarpTileInFrontOfPlayer: + push hl + push de + push bc + call _GetTileAndCoordsInFrontOfPlayer + ld a, [wCurMap] + cp SS_ANNE_5 + jr z, .ssAnne5 + ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction + srl a + ld c, a + ld b, 0 + ld hl, .warpTileListPointers + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wTileInFrontOfPlayer] + ld de, $1 + call IsInArray +.done + pop bc + pop de + pop hl + ret + +.warpTileListPointers: + dw .facingDownWarpTiles + dw .facingUpWarpTiles + dw .facingLeftWarpTiles + dw .facingRightWarpTiles + +.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 + ld a, [wTileInFrontOfPlayer] + cp $15 + jr nz, .notSSAnne5Warp + scf + jr .done +.notSSAnne5Warp + and a + jr .done + +IsPlayerStandingOnDoorTileOrWarpTile: + push hl + push de + push bc + callba IsPlayerStandingOnDoorTile + jr c, .done + ld a, [wCurMapTileset] + add a + ld c, a + ld b, $0 + ld hl, WarpTileIDPointers + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld de, $1 + aCoord 8, 9 + call IsInArray + jr nc, .done + ld hl, wd736 + res 2, [hl] +.done + pop bc + pop de + pop hl + ret + +INCLUDE "data/warp_tile_ids.asm" + +PrintSafariZoneSteps: + ld a, [wCurMap] + cp SAFARI_ZONE_EAST + ret c + cp UNKNOWN_DUNGEON_2 + ret nc + coord hl, 0, 0 + ld b, 3 + ld c, 7 + call TextBoxBorder + coord hl, 1, 1 + ld de, wSafariSteps + lb bc, 2, 3 + call PrintNumber + coord hl, 4, 1 + ld de, SafariSteps + call PlaceString + coord hl, 1, 3 + ld de, SafariBallText + call PlaceString + ld a, [wNumSafariBalls] + cp 10 + jr nc, .asm_c56d + coord hl, 5, 3 + ld a, " " + ld [hl], a +.asm_c56d + coord hl, 6, 3 + ld de, wNumSafariBalls + lb bc, 1, 2 + jp PrintNumber + +SafariSteps: + db "/500@" + +SafariBallText: + db "BALL×× @" + +GetTileAndCoordsInFrontOfPlayer: + call GetPredefRegisters + +_GetTileAndCoordsInFrontOfPlayer: + ld a, [wYCoord] + ld d, a + ld a, [wXCoord] + ld e, a + ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + and a ; cp SPRITE_FACING_DOWN + jr nz, .notFacingDown +; facing down + aCoord 8, 11 + inc d + jr .storeTile +.notFacingDown + cp SPRITE_FACING_UP + jr nz, .notFacingUp +; facing up + aCoord 8, 7 + dec d + jr .storeTile +.notFacingUp + cp SPRITE_FACING_LEFT + jr nz, .notFacingLeft +; facing left + aCoord 6, 9 + dec e + jr .storeTile +.notFacingLeft + cp SPRITE_FACING_RIGHT + jr nz, .storeTile +; facing right + aCoord 10, 9 + inc e +.storeTile + ld c, a + ld [wTileInFrontOfPlayer], a + ret + +GetTileTwoStepsInFrontOfPlayer: + xor a + ld [$ffdb], a + ld hl, wYCoord + ld a, [hli] + ld d, a + ld e, [hl] + ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + and a ; cp SPRITE_FACING_DOWN + jr nz, .notFacingDown +; facing down + ld hl, $ffdb + set 0, [hl] + aCoord 8, 13 + inc d + jr .storeTile +.notFacingDown + cp SPRITE_FACING_UP + jr nz, .notFacingUp +; facing up + ld hl, $ffdb + set 1, [hl] + aCoord 8, 5 + dec d + jr .storeTile +.notFacingUp + cp SPRITE_FACING_LEFT + jr nz, .notFacingLeft +; facing left + ld hl, $ffdb + set 2, [hl] + aCoord 4, 9 + dec e + jr .storeTile +.notFacingLeft + cp SPRITE_FACING_RIGHT + jr nz, .storeTile +; facing right + ld hl, $ffdb + set 3, [hl] + aCoord 12, 9 + inc e +.storeTile + ld c, a + ld [wTileInFrontOfBoulderAndBoulderCollisionResult], a + ld [wTileInFrontOfPlayer], a + ret + +CheckForCollisionWhenPushingBoulder: + call GetTileTwoStepsInFrontOfPlayer + ld hl, wTilesetCollisionPtr + ld a, [hli] + ld h, [hl] + ld l, a +.loop + ld a, [hli] + cp $ff + jr z, .done ; if the tile two steps ahead is not passable + cp c + jr nz, .loop + ld hl, TilePairCollisionsLand + call CheckForTilePairCollisions2 + ld a, $ff + jr c, .done ; if there is an elevation difference between the current tile and the one two steps ahead + ld a, [wTileInFrontOfBoulderAndBoulderCollisionResult] + cp $15 ; stairs tile + ld a, $ff + jr z, .done ; if the tile two steps ahead is stairs + call CheckForBoulderCollisionWithSprites +.done + ld [wTileInFrontOfBoulderAndBoulderCollisionResult], a + ret + +; sets a to $ff if there is a collision and $00 if there is no collision +CheckForBoulderCollisionWithSprites: + ld a, [wBoulderSpriteIndex] + dec a + swap a + ld d, 0 + ld e, a + ld hl, wSpriteStateData2 + $14 + add hl, de + ld a, [hli] ; map Y position + ld [$ffdc], a + ld a, [hl] ; map X position + ld [$ffdd], a + ld a, [wNumSprites] + ld c, a + ld de, $f + ld hl, wSpriteStateData2 + $14 + ld a, [$ffdb] + and $3 ; facing up or down? + jr z, .pushingHorizontallyLoop +.pushingVerticallyLoop + inc hl + ld a, [$ffdd] + cp [hl] + jr nz, .nextSprite1 ; if X coordinates don't match + dec hl + ld a, [hli] + ld b, a + ld a, [$ffdb] + rrca + jr c, .pushingDown +; pushing up + ld a, [$ffdc] + dec a + jr .compareYCoords +.pushingDown + ld a, [$ffdc] + inc a +.compareYCoords + cp b + jr z, .failure +.nextSprite1 + dec c + jr z, .success + add hl, de + jr .pushingVerticallyLoop +.pushingHorizontallyLoop + ld a, [hli] + ld b, a + ld a, [$ffdc] + cp b + jr nz, .nextSprite2 + ld b, [hl] + ld a, [$ffdb] + bit 2, a + jr nz, .pushingLeft +; pushing right + ld a, [$ffdd] + inc a + jr .compareXCoords +.pushingLeft + ld a, [$ffdd] + dec a +.compareXCoords + cp b + jr z, .failure +.nextSprite2 + dec c + jr z, .success + add hl, de + jr .pushingHorizontallyLoop +.failure + ld a, $ff + ret +.success + xor a + ret diff --git a/engine/overworld/poison.asm b/engine/overworld/poison.asm new file mode 100644 index 00000000..5d8eb9fd --- /dev/null +++ b/engine/overworld/poison.asm @@ -0,0 +1,112 @@ +ApplyOutOfBattlePoisonDamage: + ld a, [wd730] + add a + jp c, .noBlackOut ; no black out if joypad states are being simulated + ld a, [wPartyCount] + and a + jp z, .noBlackOut + call IncrementDayCareMonExp + ld a, [wStepCounter] + and $3 ; is the counter a multiple of 4? + jp nz, .noBlackOut ; 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 + 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 diff --git a/engine/overworld/pokecenter.asm b/engine/overworld/pokecenter.asm index 3c640d8e..f26bedf8 100755 --- a/engine/overworld/pokecenter.asm +++ b/engine/overworld/pokecenter.asm @@ -1,4 +1,4 @@ -DisplayPokemonCenterDialogue_: ; 6fe6 (1:6fe6) +DisplayPokemonCenterDialogue_: call SaveScreenTilesToBuffer1 ; save screen ld hl, PokemonCenterWelcomeText call PrintText @@ -24,12 +24,12 @@ DisplayPokemonCenterDialogue_: ; 6fe6 (1:6fe6) predef HealParty callba AnimateHealingMachine ; do the healing machine animation xor a - ld [wMusicHeaderPointer], a - ld a, [wc0f0] - ld [wc0ef], a - ld a, [wd35b] - ld [wcfca], a - ld [wc0ee], a + ld [wAudioFadeOutControl], a + ld a, [wAudioSavedROMBank] + ld [wAudioROMBank], a + ld a, [wMapMusicSoundID] + ld [wLastMusicSoundID], a + ld [wNewSoundID], a call PlaySound ld hl, PokemonFightingFitText call PrintText @@ -43,26 +43,26 @@ DisplayPokemonCenterDialogue_: ; 6fe6 (1:6fe6) .done ld hl, PokemonCenterFarewellText call PrintText - jp UpdateSprites ; move sprites + jp UpdateSprites -PokemonCenterWelcomeText: ; 705d (1:705d) +PokemonCenterWelcomeText: TX_FAR _PokemonCenterWelcomeText db "@" -ShallWeHealYourPokemonText: ; 7062 (1:7062) - db $a +ShallWeHealYourPokemonText: + TX_DELAY TX_FAR _ShallWeHealYourPokemonText db "@" -NeedYourPokemonText: ; 7068 (1:7068) +NeedYourPokemonText: TX_FAR _NeedYourPokemonText db "@" -PokemonFightingFitText: ; 706d (1:706d) +PokemonFightingFitText: TX_FAR _PokemonFightingFitText db "@" -PokemonCenterFarewellText: ; 7072 (1:7072) - db $a +PokemonCenterFarewellText: + TX_DELAY TX_FAR _PokemonCenterFarewellText db "@" diff --git a/engine/overworld/pokemart.asm b/engine/overworld/pokemart.asm index 8325b93f..823939b1 100755 --- a/engine/overworld/pokemart.asm +++ b/engine/overworld/pokemart.asm @@ -1,30 +1,34 @@ -DisplayPokemartDialogue_: ; 6c20 (1:6c20) +DisplayPokemartDialogue_: ld a,[wListScrollOffset] - ld [wd07e],a - call UpdateSprites ; move sprites + ld [wSavedListScrollOffset],a + call UpdateSprites xor a - ld [wcf0a],a ; flag that is set if something is sold or bought + ld [wBoughtOrSoldItemInMart],a .loop xor a ld [wListScrollOffset],a ld [wCurrentMenuItem],a ld [wPlayerMonNumber],a inc a - ld [wcf93],a + ld [wPrintItemPrices],a ld a,MONEY_BOX ld [wTextBoxID],a - call DisplayTextBoxID ; draw money text box + call DisplayTextBoxID ld a,BUY_SELL_QUIT_MENU ld [wTextBoxID],a - call DisplayTextBoxID ; do buy/sell/quit menu - ld hl,wd128 ; pointer to this pokemart's inventory + 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 ; hl = address of inventory - ld a,[wd12e] - cp a,$02 + ld h,a + + ld a,[wMenuExitMethod] + cp a,CANCELLED_MENU jp z,.done - ld a,[wd12d] ; ID of the chosen menu item + ld a,[wChosenMenuItem] and a ; buying? jp z,.buyMenu dec a ; selling? @@ -32,11 +36,14 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20) dec a ; quitting? jp z,.done .sellMenu + +; the same variables are set again below, so this code has no effect xor a - ld [wcf93],a - ld a,$02 - ld [wd11b],a - callab Func_39bd5 + ld [wPrintItemPrices],a + ld a,INIT_BAG_ITEM_LIST + ld [wInitListType],a + callab InitList + ld a,[wNumBagItems] and a jp z,.bagEmpty @@ -50,19 +57,19 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20) call DisplayTextBoxID ; draw money text box ld hl,wNumBagItems ld a,l - ld [wList],a + ld [wListPointer],a ld a,h - ld [wList + 1],a + ld [wListPointer + 1],a xor a - ld [wcf93],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 ; check if item is unsellable - ld a,[wd124] + call IsKeyItem + ld a,[wIsKeyItem] and a jr nz,.unsellableItem ld a,[wcf91] @@ -70,30 +77,34 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20) jr c,.unsellableItem ld a,PRICEDITEMLISTMENU ld [wListMenuID],a - ld [$ff8e],a ; halve prices when selling + 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 - ld bc,$0e01 + lb bc, 14, 1 ; location that PrintText always prints to, this is useless call PrintText - hlCoord 14, 7 - ld bc,$080f + coord hl, 14, 7 + lb bc, 8, 15 ld a,TWO_OPTION_MENU ld [wTextBoxID],a call DisplayTextBoxID ; yes/no menu - ld a,[wd12e] - cp a,$02 - jr z,.sellMenuLoop ; if the player pressed the B button - ld a,[wd12d] ; ID of the chosen menu item + ld a,[wMenuExitMethod] + cp a,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 ; if the player chose No + jr z,.sellMenuLoop + .sellItem - ld a,[wcf0a] ; flag that is set if something is sold or bought + ld a,[wBoughtOrSoldItemInMart] and a jr nz,.skipSettingFlag1 inc a - ld [wcf0a],a + ld [wBoughtOrSoldItemInMart],a .skipSettingFlag1 call AddAmountSoldToMoney ld hl,wNumBagItems @@ -106,39 +117,42 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20) .bagEmpty ld hl,PokemartItemBagEmptyText call PrintText - call SaveScreenTilesToBuffer1 ; save screen + call SaveScreenTilesToBuffer1 jp .returnToMainPokemartMenu .buyMenu - ld a,$01 - ld [wcf93],a - ld a,$03 - ld [wd11b],a - callab Func_39bd5 + +; 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 ; save screen + call SaveScreenTilesToBuffer1 .buyMenuLoop - call LoadScreenTilesFromBuffer1 ; restore saved screen + call LoadScreenTilesFromBuffer1 ld a,MONEY_BOX ld [wTextBoxID],a - call DisplayTextBoxID ; draw money text box - ld hl,wStringBuffer2 + 11 + call DisplayTextBoxID + ld hl,wItemList ld a,l - ld [wList],a + ld [wListPointer],a ld a,h - ld [wList + 1],a + ld [wListPointer + 1],a xor a ld [wCurrentMenuItem],a inc a - ld [wcf93],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,$63 - ld [wcf97],a + ld a,99 + ld [wMaxItemQuantity],a xor a - ld [$ff8e],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 @@ -148,17 +162,21 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20) call CopyStringToCF4B ; copy name to wcf4b ld hl,PokemartTellBuyPriceText call PrintText - hlCoord 14, 7 - ld bc,$080f + coord hl, 14, 7 + lb bc, 8, 15 ld a,TWO_OPTION_MENU ld [wTextBoxID],a call DisplayTextBoxID ; yes/no menu - ld a,[wd12e] - cp a,$02 - jp z,.buyMenuLoop ; if the player pressed the B button - ld a,[wd12d] ; ID of the chosen menu item + ld a,[wMenuExitMethod] + cp a,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 ; if the player chose No + jr z,.buyMenuLoop + .buyItem call .isThereEnoughMoney jr c,.notEnoughMoney @@ -166,13 +184,13 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20) call AddItemToInventory jr nc,.bagFull call SubtractAmountPaidFromMoney - ld a,[wcf0a] ; flag that is set if something is sold or bought + ld a,[wBoughtOrSoldItemInMart] and a jr nz,.skipSettingFlag2 - ld a,$01 - ld [wcf0a],a + ld a,1 + ld [wBoughtOrSoldItemInMart],a .skipSettingFlag2 - ld a,(SFX_02_5a - SFX_Headers_02) / 3 + ld a,SFX_PURCHASE call PlaySoundWaitForCurrent call WaitForSoundToFinish ld hl,PokemartBoughtItemText @@ -182,13 +200,13 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20) call LoadScreenTilesFromBuffer1 ld a,MONEY_BOX ld [wTextBoxID],a - call DisplayTextBoxID ; draw money text box + call DisplayTextBoxID ld hl,PokemartAnythingElseText call PrintText jp .loop .isThereEnoughMoney ld de,wPlayerMoney - ld hl,$ff9f ; item price + ld hl,hMoney ld c,3 ; length of money in bytes jp StringCmp .notEnoughMoney @@ -202,53 +220,53 @@ DisplayPokemartDialogue_: ; 6c20 (1:6c20) .done ld hl,PokemartThankYouText call PrintText - ld a,$01 + ld a,1 ld [wUpdateSpritesEnabled],a - call UpdateSprites ; move sprites - ld a,[wd07e] + call UpdateSprites + ld a,[wSavedListScrollOffset] ld [wListScrollOffset],a ret -PokemartBuyingGreetingText: ; 6e0c (1:6e0c) +PokemartBuyingGreetingText: TX_FAR _PokemartBuyingGreetingText db "@" -PokemartTellBuyPriceText: ; 6e11 (1:6e11) +PokemartTellBuyPriceText: TX_FAR _PokemartTellBuyPriceText db "@" -PokemartBoughtItemText: ; 6e16 (1:6e16) +PokemartBoughtItemText: TX_FAR _PokemartBoughtItemText db "@" -PokemartNotEnoughMoneyText: ; 6e1b (1:6e1b) +PokemartNotEnoughMoneyText: TX_FAR _PokemartNotEnoughMoneyText db "@" -PokemartItemBagFullText: ; 6e20 (1:6e20) +PokemartItemBagFullText: TX_FAR _PokemartItemBagFullText db "@" -PokemonSellingGreetingText: ; 6e25 (1:6e25) +PokemonSellingGreetingText: TX_FAR _PokemonSellingGreetingText db "@" -PokemartTellSellPriceText: ; 6e2a (1:6e2a) +PokemartTellSellPriceText: TX_FAR _PokemartTellSellPriceText db "@" -PokemartItemBagEmptyText: ; 6e2f (1:6e2f) +PokemartItemBagEmptyText: TX_FAR _PokemartItemBagEmptyText db "@" -PokemartUnsellableItemText: ; 6e34 (1:6e34) +PokemartUnsellableItemText: TX_FAR _PokemartUnsellableItemText db "@" -PokemartThankYouText: ; 6e39 (1:6e39) +PokemartThankYouText: TX_FAR _PokemartThankYouText db "@" -PokemartAnythingElseText: ; 6e3e (1:6e3e) +PokemartAnythingElseText: TX_FAR _PokemartAnythingElseText db "@" diff --git a/engine/overworld/push_boulder.asm b/engine/overworld/push_boulder.asm new file mode 100644 index 00000000..c91605a8 --- /dev/null +++ b/engine/overworld/push_boulder.asm @@ -0,0 +1,105 @@ +TryPushingBoulder: + ld a, [wd728] + bit 0, a ; using Strength? + ret z + ld a, [wFlags_0xcd60] + bit 1, a ; has boulder dust animation from previous push played yet? + ret nz + xor a + ld [hSpriteIndexOrTextID], a + call IsSpriteInFrontOfPlayer + ld a, [hSpriteIndexOrTextID] + ld [wBoulderSpriteIndex], a + and a + jp z, ResetBoulderPushFlags + ld hl, wSpriteStateData1 + 1 + ld d, $0 + ld a, [hSpriteIndexOrTextID] + swap a + ld e, a + add hl, de + res 7, [hl] + call GetSpriteMovementByte2Pointer + ld a, [hl] + cp BOULDER_MOVEMENT_BYTE_2 + jp nz, ResetBoulderPushFlags + ld hl, wFlags_0xcd60 + 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] + 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] + ld b, a + ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + cp SPRITE_FACING_UP + jr z, .pushBoulderUp + cp SPRITE_FACING_LEFT + jr z, .pushBoulderLeft + cp SPRITE_FACING_RIGHT + jr z, .pushBoulderRight +.pushBoulderDown + bit 7, b + ret z + ld de, PushBoulderDownMovementData + jr .done +.pushBoulderUp + bit 6, b + ret z + ld de, PushBoulderUpMovementData + jr .done +.pushBoulderLeft + bit 5, b + ret z + ld de, PushBoulderLeftMovementData + jr .done +.pushBoulderRight + bit 4, b + ret z + ld de, PushBoulderRightMovementData +.done + call MoveSprite + ld a, SFX_PUSH_BOULDER + call PlaySound + ld hl, wFlags_0xcd60 + set 1, [hl] + ret + +PushBoulderUpMovementData: + db NPC_MOVEMENT_UP,$FF + +PushBoulderDownMovementData: + db NPC_MOVEMENT_DOWN,$FF + +PushBoulderLeftMovementData: + db NPC_MOVEMENT_LEFT,$FF + +PushBoulderRightMovementData: + db NPC_MOVEMENT_RIGHT,$FF + +DoBoulderDustAnimation: + ld a, [wd730] + bit 0, a + ret nz + callab AnimateBoulderDust + call DiscardButtonPresses + ld [wJoyIgnore], a + call ResetBoulderPushFlags + set 7, [hl] + ld a, [wBoulderSpriteIndex] + ld [H_SPRITEINDEX], a + call GetSpriteMovementByte2Pointer + ld [hl], $10 + ld a, SFX_CUT + jp PlaySound + +ResetBoulderPushFlags: + ld hl, wFlags_0xcd60 + res 1, [hl] + res 6, [hl] + ret diff --git a/engine/overworld/saffron_guards.asm b/engine/overworld/saffron_guards.asm index 8e584a2d..3b26b6f8 100755 --- a/engine/overworld/saffron_guards.asm +++ b/engine/overworld/saffron_guards.asm @@ -1,4 +1,4 @@ -RemoveGuardDrink: ; 5a59f (16:659f) +RemoveGuardDrink: ld hl, GuardDrinksList .drinkLoop ld a, [hli] @@ -10,9 +10,7 @@ RemoveGuardDrink: ; 5a59f (16:659f) call IsItemInBag pop hl jr z, .drinkLoop - ld b, BANK(RemoveItemByID) - ld hl, RemoveItemByID - jp Bankswitch + jpba RemoveItemByID -GuardDrinksList: ; 5a5b7 (16:65b7) +GuardDrinksList: db FRESH_WATER, SODA_POP, LEMONADE, $00 diff --git a/engine/overworld/set_blackout_map.asm b/engine/overworld/set_blackout_map.asm new file mode 100644 index 00000000..9bfe82bd --- /dev/null +++ b/engine/overworld/set_blackout_map.asm @@ -0,0 +1,29 @@ +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_REST_HOUSE_2 + db SAFARI_ZONE_REST_HOUSE_3 + db SAFARI_ZONE_REST_HOUSE_4 + db -1 diff --git a/engine/overworld/ssanne.asm b/engine/overworld/ssanne.asm index f1a8ecf9..712c53ed 100755 --- a/engine/overworld/ssanne.asm +++ b/engine/overworld/ssanne.asm @@ -1,6 +1,6 @@ -AnimateBoulderDust: ; 79f54 (1e:5f54) +AnimateBoulderDust: ld a, $1 - ld [wcd50], a ; select the boulder dust offsets + ld [wWhichAnimationOffsets], a ; select the boulder dust offsets ld a, [wUpdateSpritesEnabled] push af ld a, $ff @@ -8,14 +8,14 @@ AnimateBoulderDust: ; 79f54 (1e:5f54) ld a, %11100100 ld [rOBP1], a call LoadSmokeTileFourTimes - callba WriteCutTreeBoulderDustAnimationOAMBlock + callba WriteCutOrBoulderDustAnimationOAMBlock ld c, 8 ; number of steps in animation .loop push bc call GetMoveBoulderDustFunctionPointer ld bc, .returnAddress push bc - ld c, $4 + ld c, 4 jp [hl] .returnAddress ld a, [rOBP1] @@ -29,14 +29,14 @@ AnimateBoulderDust: ; 79f54 (1e:5f54) ld [wUpdateSpritesEnabled], a jp LoadPlayerSpriteGraphics -GetMoveBoulderDustFunctionPointer: ; 79f92 (1e:5f92) +GetMoveBoulderDustFunctionPointer: ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction ld hl, MoveBoulderDustFunctionPointerTable ld c, a ld b, $0 add hl, bc ld a, [hli] - ld [wd08a], a + ld [wCoordAdjustmentAmount], a ld a, [hli] ld e, a ld a, [hli] @@ -51,7 +51,7 @@ GetMoveBoulderDustFunctionPointer: ; 79f92 (1e:5f92) pop hl ret -MoveBoulderDustFunctionPointerTable: ; 79fb0 (1e:5fb0) +MoveBoulderDustFunctionPointerTable: ; facing down db $FF,$00 dw AdjustOAMBlockYPos @@ -68,7 +68,7 @@ MoveBoulderDustFunctionPointerTable: ; 79fb0 (1e:5fb0) db $FF,$01 dw AdjustOAMBlockXPos -LoadSmokeTileFourTimes: ; 79fc0 (1e:5fc0) +LoadSmokeTileFourTimes: ld hl, vChars1 + $7c0 ld c, $4 .loop @@ -83,10 +83,11 @@ LoadSmokeTileFourTimes: ; 79fc0 (1e:5fc0) jr nz, .loop ret -LoadSmokeTile: ; 79fd4 (1e:5fd4) - ld de, SSAnneSmokePuffTile ; $5fdd - ld bc, (BANK(SSAnneSmokePuffTile) << 8) + $01 +LoadSmokeTile: + ld de, SSAnneSmokePuffTile + lb bc, BANK(SSAnneSmokePuffTile), (SSAnneSmokePuffTileEnd - SSAnneSmokePuffTile) / $10 jp CopyVideoData -SSAnneSmokePuffTile: ; 79fdd (1e:5fdd) +SSAnneSmokePuffTile: INCBIN "gfx/ss_anne_smoke_puff.2bpp" +SSAnneSmokePuffTileEnd: diff --git a/engine/overworld/tileset_header.asm b/engine/overworld/tileset_header.asm new file mode 100644 index 00000000..6e33974f --- /dev/null +++ b/engine/overworld/tileset_header.asm @@ -0,0 +1,60 @@ +LoadTilesetHeader: + call GetPredefRegisters + push hl + ld d, 0 + ld a, [wCurMapTileset] + add a + add a + ld b, a + add a + add b ; a = tileset * 12 + jr nc, .noCarry + inc d +.noCarry + ld e, a + ld hl, Tilesets + add hl, de + ld de, wTilesetBank + ld c, $b +.copyTilesetHeaderLoop + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .copyTilesetHeaderLoop + 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, .asm_c797 + ld a, [wCurMapTileset] + ld b, a + ld a, [hPreviousTileset] + cp b + jr z, .done +.asm_c797 + 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/trainers.asm b/engine/overworld/trainers.asm index 4aaab3ed..655c6b2a 100755 --- a/engine/overworld/trainers.asm +++ b/engine/overworld/trainers.asm @@ -1,42 +1,42 @@ -_GetSpritePosition1: ; 567f9 (15:67f9) +_GetSpritePosition1: ld hl, wSpriteStateData1 ld de, $4 ld a, [wSpriteIndex] ld [H_SPRITEINDEX], a call GetSpriteDataPointer - ld a, [hli] + ld a, [hli] ; c1x4 (screen Y pos) ld [$ffeb], a inc hl - ld a, [hl] + ld a, [hl] ; c1x6 (screen X pos) ld [$ffec], a - ld de, $fe + ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6) add hl, de - ld a, [hli] + ld a, [hli] ; c2x4 (map Y pos) ld [$ffed], a - ld a, [hl] + ld a, [hl] ; c2x5 (map X pos) ld [$ffee], a ret -_GetSpritePosition2: ; 56819 (15:6819) +_GetSpritePosition2: ld hl, wSpriteStateData1 ld de, $4 ld a, [wSpriteIndex] ld [H_SPRITEINDEX], a call GetSpriteDataPointer ld a, [hli] ; c1x4 (screen Y pos) - ld [wd130], a + ld [wSavedSpriteScreenY], a inc hl ld a, [hl] ; c1x6 (screen X pos) - ld [wd131], a - ld de, $104 - $6 + ld [wSavedSpriteScreenX], a + ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6) add hl, de ld a, [hli] ; c2x4 (map Y pos) - ld [wd132], a + ld [wSavedSpriteMapY], a ld a, [hl] ; c2x5 (map X pos) - ld [wd133], a + ld [wSavedSpriteMapX], a ret -_SetSpritePosition1: ; 5683d (15:683d) +_SetSpritePosition1: ld hl, wSpriteStateData1 ld de, $4 ld a, [wSpriteIndex] @@ -47,7 +47,7 @@ _SetSpritePosition1: ; 5683d (15:683d) inc hl ld a, [$ffec] ; c1x6 (screen X pos) ld [hl], a - ld de, $104 - $6 + ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6) add hl, de ld a, [$ffed] ; c2x4 (map Y pos) ld [hli], a @@ -55,36 +55,36 @@ _SetSpritePosition1: ; 5683d (15:683d) ld [hl], a ret -_SetSpritePosition2: ; 5685d (15:685d) +_SetSpritePosition2: ld hl, wSpriteStateData1 - ld de, $0004 + ld de, 4 ld a, [wSpriteIndex] ld [H_SPRITEINDEX], a call GetSpriteDataPointer - ld a, [wd130] - ld [hli], a + ld a, [wSavedSpriteScreenY] + ld [hli], a ; c1x4 (screen Y pos) inc hl - ld a, [wd131] - ld [hl], a - ld de, $00fe + ld a, [wSavedSpriteScreenX] + ld [hl], a ; c1x6 (screen X pos) + ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6) add hl, de - ld a, [wd132] - ld [hli], a - ld a, [wd133] - ld [hl], a + ld a, [wSavedSpriteMapY] + ld [hli], a ; c2x4 (map Y pos) + ld a, [wSavedSpriteMapX] + ld [hl], a ; c2x5 (map X pos) ret -TrainerWalkUpToPlayer: ; 56881 (15:6881) +TrainerWalkUpToPlayer: ld a, [wSpriteIndex] swap a - ld [wTrainerSpriteOffset], a ; wWhichTrade + ld [wTrainerSpriteOffset], a call ReadTrainerScreenPosition ld a, [wTrainerFacingDirection] - and a + and a ; SPRITE_FACING_DOWN jr z, .facingDown - cp $4 + cp SPRITE_FACING_UP jr z, .facingUp - cp $8 + cp SPRITE_FACING_LEFT jr z, .facingLeft jr .facingRight .facingDown @@ -148,8 +148,8 @@ TrainerWalkUpToPlayer: ; 56881 (15:6881) jp MoveSprite_ ; input: de = offset within sprite entry -; output: de = pointer to sprite data -GetSpriteDataPointer: ; 56903 (15:6903) +; output: hl = pointer to sprite data +GetSpriteDataPointer: push de add hl, de ld a, [H_SPRITEINDEX] @@ -161,10 +161,10 @@ GetSpriteDataPointer: ; 56903 (15:6903) ret ; tests if this trainer is in the right position to engage the player and do so if she is. -TrainerEngage: ; 5690f (15:690f) +TrainerEngage: push hl push de - ld a, [wTrainerSpriteOffset] ; wWhichTrade + ld a, [wTrainerSpriteOffset] add $2 ld d, $0 ld e, a @@ -175,7 +175,7 @@ TrainerEngage: ; 5690f (15:690f) jr nz, .spriteOnScreen ; test if sprite is on screen jp .noEngage .spriteOnScreen - ld a, [wTrainerSpriteOffset] ; wWhichTrade + ld a, [wTrainerSpriteOffset] add $9 ld d, $0 ld e, a @@ -218,57 +218,57 @@ TrainerEngage: ; 5690f (15:690f) jp .noEngage .engage call CheckPlayerIsInFrontOfSprite - ld a, [wTrainerSpriteOffset] ; wWhichTrade + ld a, [wTrainerSpriteOffset] and a jr z, .noEngage ld hl, wFlags_0xcd60 set 0, [hl] call EngageMapTrainer ld a, $ff -.noEngage: ; 56988 (15:6988) - ld [wTrainerSpriteOffset], a ; wWhichTrade +.noEngage + ld [wTrainerSpriteOffset], a pop de pop hl ret ; reads trainer's Y position to wTrainerScreenY and X position to wTrainerScreenX -ReadTrainerScreenPosition: ; 5698e (15:698e) - ld a, [wTrainerSpriteOffset] ; wWhichTrade +ReadTrainerScreenPosition: + ld a, [wTrainerSpriteOffset] add $4 ld d, $0 ld e, a ld hl, wSpriteStateData1 add hl, de - ld a, [hl] + ld a, [hl] ; c1x4 (sprite Y pos) ld [wTrainerScreenY], a - ld a, [wTrainerSpriteOffset] ; wWhichTrade + ld a, [wTrainerSpriteOffset] add $6 ld d, $0 ld e, a ld hl, wSpriteStateData1 add hl, de - ld a, [hl] + 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: ; 569af (15:69af) +CheckSpriteCanSeePlayer: ld b, a - ld a, [wTrainerEngageDistance] ; sprite line of sight (engage distance) + 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 $0 ; down + cp SPRITE_FACING_DOWN jr z, .checkXCoord - cp $4 ; up + cp SPRITE_FACING_UP jr z, .checkXCoord - cp $8 ; left + cp SPRITE_FACING_LEFT jr z, .checkYCoord - cp $c ; right + cp SPRITE_FACING_RIGHT jr z, .checkYCoord jr .notInLine .checkXCoord @@ -290,11 +290,11 @@ CheckSpriteCanSeePlayer: ; 569af (15:69af) ret ; tests if the player is in front of the sprite (rather than behind it) -CheckPlayerIsInFrontOfSprite: ; 569e3 (15:69e3) - ld a, [W_CURMAP] ; W_CURMAP +CheckPlayerIsInFrontOfSprite: + ld a, [wCurMap] cp POWER_PLANT - jp z, .engage ; XXX not sure why bypass this for power plant (maybe to get voltorb fake items to work?) - ld a, [wTrainerSpriteOffset] ; wWhichTrade + 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 @@ -306,7 +306,7 @@ CheckPlayerIsInFrontOfSprite: ; 569e3 (15:69e3) ld a, $c .notOnTopmostTile ld [wTrainerScreenY], a - ld a, [wTrainerSpriteOffset] ; wWhichTrade + ld a, [wTrainerSpriteOffset] add $6 ld d, $0 ld e, a @@ -315,21 +315,21 @@ CheckPlayerIsInFrontOfSprite: ; 569e3 (15:69e3) ld a, [hl] ; c1x6 (sprite screen X pos) ld [wTrainerScreenX], a ld a, [wTrainerFacingDirection] ; facing direction - cp $0 + 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 $4 + 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 $8 + cp SPRITE_FACING_LEFT jr nz, .notFacingLeft ld a, [wTrainerScreenX] ; sprite screen X pos cp $40 @@ -345,5 +345,5 @@ CheckPlayerIsInFrontOfSprite: ; 569e3 (15:69e3) .noEngage xor a .done - ld [wTrainerSpriteOffset], a ; wWhichTrade + ld [wTrainerSpriteOffset], a ret diff --git a/engine/overworld/update_map.asm b/engine/overworld/update_map.asm new file mode 100644 index 00000000..8577b9e7 --- /dev/null +++ b/engine/overworld/update_map.asm @@ -0,0 +1,126 @@ +; replaces a tile block with the one specified in [wNewTileBlockID] +; and redraws the map view if necessary +; b = Y +; c = X +ReplaceTileBlock: + call GetPredefRegisters + ld hl, wOverworldMap + ld a, [wCurMapWidth] + add $6 + ld e, a + ld d, $0 + add hl, de + add hl, de + add hl, de + ld e, $3 + add hl, de + ld e, a + ld a, b + and a + jr z, .addX +; add width * Y +.addWidthYTimesLoop + add hl, de + dec b + jr nz, .addWidthYTimesLoop +.addX + add hl, bc ; add X + ld a, [wNewTileBlockID] + ld [hl], a + ld a, [wCurrentTileBlockMapViewPointer] + ld c, a + ld a, [wCurrentTileBlockMapViewPointer + 1] + ld b, a + call CompareHLWithBC + ret c ; return if the replaced tile block is below the map view in memory + push hl + ld l, e + ld h, $0 + ld e, $6 + ld d, h + add hl, hl + add hl, hl + add hl, de + add hl, bc + pop bc + call CompareHLWithBC + ret c ; return if the replaced tile block is above the map view in memory + +RedrawMapView: + ld a, [wIsInBattle] + inc a + ret z + ld a, [H_AUTOBGTRANSFERENABLED] + push af + ld a, [hTilesetType] + push af + xor a + ld [H_AUTOBGTRANSFERENABLED], a + ld [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 + add hl, de + ld a, h + and $3 + or $98 + ld a, l + ld [wBuffer], a + 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) +.redrawRowLoop + push bc + push hl + push hl + ld hl, wTileMap - 2 * SCREEN_WIDTH + ld de, SCREEN_WIDTH + ld a, [$ffbe] +.calcWRAMAddrLoop + add hl, de + dec a + jr nz, .calcWRAMAddrLoop + call CopyToRedrawRowOrColumnSrcTiles + pop hl + ld de, $20 + ld a, [$ffbe] + ld c, a +.calcVRAMAddrLoop + add hl, de + ld a, h + and $3 + or $98 + dec c + jr nz, .calcVRAMAddrLoop + ld [hRedrawRowOrColumnDest + 1], a + ld a, l + ld [hRedrawRowOrColumnDest], a + ld a, REDRAW_ROW + ld [hRedrawRowOrColumnMode], a + call DelayFrame + ld hl, $ffbe + inc [hl] + inc [hl] + pop hl + pop bc + dec c + jr nz, .redrawRowLoop + pop af + ld [hTilesetType], a + pop af + ld [H_AUTOBGTRANSFERENABLED], a + ret + +CompareHLWithBC: + ld a, h + sub b + ret nz + ld a, l + sub c + ret diff --git a/engine/overworld/wild_mons.asm b/engine/overworld/wild_mons.asm new file mode 100644 index 00000000..6444ab7e --- /dev/null +++ b/engine/overworld/wild_mons.asm @@ -0,0 +1,33 @@ +LoadWildData: + ld hl,WildDataPointers + ld a,[wCurMap] + + ; get wild data for current map + ld c,a + ld b,0 + add hl,bc + add hl,bc + ld a,[hli] + ld h,[hl] + ld l,a ; hl now points to wild data for current map + ld a,[hli] + ld [wGrassRate],a + and a + jr z,.NoGrassData ; if no grass data, skip to surfing data + push hl + ld de,wGrassMons ; otherwise, load grass data + ld bc,$0014 + call CopyData + pop hl + ld bc,$0014 + add hl,bc +.NoGrassData + ld a,[hli] + ld [wWaterRate],a + and a + ret z ; if no water data, we're done + ld de,wWaterMons ; otherwise, load surfing data + ld bc,$0014 + jp CopyData + +INCLUDE "data/wild_mons.asm" |