From 492d65c135459156cef2f5df39a1aeb1fc8eb6ba Mon Sep 17 00:00:00 2001 From: Jared_Brian_ Date: Thu, 16 Jan 2025 22:10:19 -0700 Subject: [PATCH 1/9] added my testing stuff to git ignore and initial upload --- .gitignore | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.gitignore b/.gitignore index 2636fd6..1bb62b3 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,14 @@ oos111x.sfc oos111x.smp.sym oos111x.srm oos111x.sym +zcompress.exe +oos165.sfc +oos165x-1.bst +oos165x-2.bst +oos165x-3.bst +oos165x.bp +oos165x.cpu.sym +oos165x.sfc +oos165x.smp.sym +oos165x.srm +buildJ.bat From 002b8b7f33d40f0c90126b886fae86087b846ab6 Mon Sep 17 00:00:00 2001 From: Jared_Brian_ Date: Thu, 16 Jan 2025 22:10:30 -0700 Subject: [PATCH 2/9] woopse --- Sprites/Objects/minecart.asm | 166 ++++++++++++++++++++++++++++------- 1 file changed, 136 insertions(+), 30 deletions(-) diff --git a/Sprites/Objects/minecart.asm b/Sprites/Objects/minecart.asm index 8027f8e..3254156 100644 --- a/Sprites/Objects/minecart.asm +++ b/Sprites/Objects/minecart.asm @@ -233,7 +233,7 @@ Minecart_HandleLiftAndToss: Sprite_Minecart_Main: { LDA.w SprAction, X - JSL UseImplicitRegIndexedLocalJumpTable + JSL UseImplicitRegIndexedLocalJumpTable dw Minecart_WaitHoriz ; 0x00 dw Minecart_WaitVert ; 0x01 @@ -274,7 +274,7 @@ Sprite_Minecart_Main: RTS .not_ready .lifting - JSR Minecart_HandleLiftAndToss + ;JSR Minecart_HandleLiftAndToss RTS } @@ -309,7 +309,7 @@ Sprite_Minecart_Main: RTS .not_ready .lifting - JSR Minecart_HandleLiftAndToss + ;JSR Minecart_HandleLiftAndToss RTS } @@ -319,12 +319,15 @@ Sprite_Minecart_Main: { %PlayAnimation(2,3,8) JSR InitMovement + + ; Used for an un-implemented speed switch feature. LDA $36 : BNE .fast_speed LDA.b #-!MinecartSpeed : STA.w SprYSpeed, X JMP + .fast_speed LDA.b #-!DoubleSpeed : STA.w SprYSpeed, X + + JSL Sprite_MoveVert ; Get direction of the cart (0 to 3) @@ -332,6 +335,10 @@ Sprite_Minecart_Main: JSL DragPlayer JSR CheckForPlayerInput JSR HandlePlayerCameraAndMoveCart + + JSR HandleTileDirections + JSR HandleDynamicSwitchTileDirections + RTS } @@ -341,12 +348,15 @@ Sprite_Minecart_Main: { %PlayAnimation(0,1,8) JSR InitMovement + + ; Used for an un-implemented speed switch feature. LDA $36 : BNE .fast_speed LDA.b #!MinecartSpeed : STA.w SprXSpeed, X JMP + .fast_speed LDA.b #!DoubleSpeed : STA.w SprXSpeed, X + + JSL Sprite_MoveHoriz ; Get direction of the cart (0 to 3) @@ -354,6 +364,10 @@ Sprite_Minecart_Main: JSL DragPlayer JSR CheckForPlayerInput JSR HandlePlayerCameraAndMoveCart + + JSR HandleTileDirections + JSR HandleDynamicSwitchTileDirections + RTS } @@ -363,12 +377,15 @@ Sprite_Minecart_Main: { %PlayAnimation(2,3,8) JSR InitMovement + + ; Used for an un-implemented speed switch feature. LDA $36 : BNE .fast_speed LDA.b #!MinecartSpeed : STA.w SprYSpeed, X JMP + .fast_speed LDA.b #!DoubleSpeed : STA.w SprYSpeed, X + + JSL Sprite_MoveVert ; Get direction of the cart (0 to 3) @@ -376,6 +393,10 @@ Sprite_Minecart_Main: JSL DragPlayer JSR CheckForPlayerInput JSR HandlePlayerCameraAndMoveCart + + JSR HandleTileDirections + JSR HandleDynamicSwitchTileDirections + RTS } @@ -385,12 +406,15 @@ Sprite_Minecart_Main: { %PlayAnimation(0,1,8) JSR InitMovement - LDA $36 : BNE .fast_speed + + ; Used for an un-implemented speed switch feature. + LDA $36 : BNE .fast_speed LDA.b #-!MinecartSpeed : STA.w SprXSpeed, X JMP + .fast_speed LDA.b #-!DoubleSpeed : STA.w SprXSpeed, X + + JSL Sprite_MoveHoriz ; Get direction of the cart (0 to 3) @@ -398,6 +422,10 @@ Sprite_Minecart_Main: JSL DragPlayer JSR CheckForPlayerInput JSR HandlePlayerCameraAndMoveCart + + JSR HandleTileDirections + JSR HandleDynamicSwitchTileDirections + RTS } @@ -433,8 +461,6 @@ HandlePlayerCameraAndMoveCart: JSL Link_CancelDash PLX - JSR HandleTileDirections - JSR HandleDynamicSwitchTileDirections LDA #$35 : STA $012E ; Cart SFX RTS } @@ -485,7 +511,6 @@ Minecart_SetDirectionWest: RTS } - ; ========================================================= ; A = $0FA5 @@ -495,25 +520,55 @@ CheckForOutOfBounds: ; If the tile is out of bounds, release the cart LDA #$40 : STA.w SprTimerD, X %GotoAction(6) ; Minecart_Release + + SEC RTS .not_out_of_bounds + + CLC RTS } +; CLC if no stop occured, SEC if stop occured. CheckForStopTiles: { + CMP.b #$B7 : BEQ .check_direction + CMP.b #$B8 : BEQ .check_direction + CMP.b #$B9 : BEQ .check_direction + CMP.b #$BA : BEQ .check_direction + .exit + CLC + RTS + .check_direction + + LDA.w SprSubtype, X + ASL #2 ; Multiply by 4 to offset rows in the lookup table + STA $07 ; Store the action index in $07 + + ; Subtract $B7 to normalize the tile type to 0 to 3 + LDA.w SPRTILE : SEC : SBC.b #$B7 + + CLC : ADC.w $07 : TAY + LDA.w .DirectionTileLookup, Y : TAY + ; Check if the tile is a stop tile - CMP.b #$B7 : BEQ .stop_north - CMP.b #$B8 : BEQ .stop_south - CMP.b #$B9 : BEQ .stop_west - CMP.b #$BA : BEQ .stop_east + CPY.b #$01 : BEQ .stop_north + CPY.b #$02 : BEQ .stop_east + CPY.b #$03 : BEQ .stop_south + CPY.b #$04 : BEQ .stop_west + CLC + RTS .stop_north + ; If the direction is already south, that means we have already stopped + ; or are heading south and don't need to stop. JSR Minecart_SetDirectionSouth JMP .go_vert .stop_south + ; If the direction is already north, that means we have already stopped + ; or are heading north and don't need to stop. JSR Minecart_SetDirectionNorth .go_vert @@ -521,13 +576,19 @@ CheckForStopTiles: JSR StopCart %GotoAction(1) ; Minecart_WaitVert JSL Link_ResetProperties_A + + SEC RTS .stop_east + ; If the direction is already west, that means we have already stopped + ; or are heading west and don't need to stop. JSR Minecart_SetDirectionWest JMP .go_horiz .stop_west + ; If the direction is already east, that means we have already stopped + ; or are heading east and don't need to stop. JSR Minecart_SetDirectionEast .go_horiz @@ -535,7 +596,24 @@ CheckForStopTiles: JSR StopCart %GotoAction(0) ; Minecart_WaitHoriz JSL Link_ResetProperties_A + + SEC RTS + + ; Direction to move on tile collision + ; 00 - stop or nothing + ; 01 - north + ; 02 - east + ; 03 - south + ; 04 - west + .DirectionTileLookup + { + ; north east south west + db $01, $00, $00, $00 ; North + db $00, $00, $00, $02 ; East + db $00, $03, $00, $00 ; South + db $00, $00, $04, $00 ; West + } } CheckForCornerTiles: @@ -544,7 +622,8 @@ CheckForCornerTiles: CMP.b #$B3 : BEQ .check_direction CMP.b #$B4 : BEQ .check_direction CMP.b #$B5 : BEQ .check_direction - SEC + .exit + CLC RTS .check_direction LDA.w SprSubtype, X @@ -561,34 +640,29 @@ CheckForCornerTiles: CPY #$02 : BEQ .move_east CPY #$03 : BEQ .move_south CPY #$04 : BEQ .move_west - JMP .done + JMP .exit .move_north JSR Minecart_SetDirectionNorth %GotoAction(2) ; Minecart_MoveNorth - LDA.w SprX, X : AND #$F8 : STA.w SprX, X JMP .done .move_east JSR Minecart_SetDirectionEast - LDA #$03 : STA !SpriteDirection, X - LDA.w SprY, X : AND #$F8 : STA.w SprY, X %GotoAction(3) ; Minecart_MoveEast JMP .done .move_south JSR Minecart_SetDirectionSouth %GotoAction(4) ; Minecart_MoveSouth - LDA.w SprX, X : AND #$F8 : STA.w SprX, X JMP .done .move_west JSR Minecart_SetDirectionWest - LDA.w SprY, X : AND #$F8 : STA.w SprY, X %GotoAction(5) ; Minecart_MoveWest .done - CLC + SEC RTS ; Direction to move on tile collision @@ -638,9 +712,9 @@ CheckForTrackTiles: HandleTileDirections: { - LDA.w SprTimerA, X : BEQ + - RTS - + + ;LDA.w SprTimerA, X : BEQ + + ; RTS + ;+ ; If the cart got disconnected from the player, release them. JSR CheckIfPlayerIsOn : BCS .player_on_cart @@ -649,19 +723,51 @@ HandleTileDirections: .player_on_cart ; Setup Minecart position to look for tile IDs - ; We use AND #$F8 to clamp to a 16x16 grid, however this needs work. - LDA.w SprY, X : AND #$F8 : STA.b $00 : LDA.w SprYH, X : STA.b $01 - LDA.w SprX, X : AND #$F8 : STA.b $02 : LDA.w SprXH, X : STA.b $03 + ; We use AND #$F8 to clamp to a 16x16 grid. + LDA.w SprY, X : AND #$F8 : STA.b $00 + LDA.w SprYH, X : STA.b $01 + + LDA.w SprX, X : AND #$F8 : STA.b $02 + LDA.w SprXH, X : STA.b $03 ; Fetch tile attributes based on current coordinates LDA.b #$00 : JSL Sprite_GetTileAttr - LDA.w $0FA5 - JSR CheckForOutOfBounds - JSR CheckForStopTiles + + ; Debug: put the tile type into the rupee SRM. + STA.l $7EF362 : STA.l $7EF360 + LDA.b #$00 : STA.l $7EF363 : STA.l $7EF361 + + print "adfsddddddddddddddddddddddddddddddddddddddddddddddddd: ", pc + + LDA.w SPRTILE + JSR CheckForOutOfBounds : BCC .notOutOfBounds + JSR RoundCoords + + BRA .done + + .notOutOfBounds + + JSR CheckForStopTiles : BCC .noStop + JSR RoundCoords + + BRA .done + .noStop + JSR CheckForCornerTiles : BCC .done - ; JSR CheckForTrackTiles + JSR RoundCoords + .done - LDA #$0F : STA.w SprTimerA, X + RTS +} + +RoundCoords: +{ + ; Clamp the Y coord to the nearest multiple of 8. + LDA.b $00 : CLC : ADC.b #$04 : AND.b #$F8 : STA.b $00 : STA.w SprY, x + + ; Clamp the X coord to the nearest multiple of 8. + LDA.b $02 : CLC : ADC.b #$04 : AND.b #$F8 : STA.b $02 : STA.w SprX, x + RTS } From 46e557e82e0d67ce04c517005c5b69f7cb7ca42f Mon Sep 17 00:00:00 2001 From: Jared_Brian_ Date: Tue, 21 Jan 2025 22:44:26 -0700 Subject: [PATCH 3/9] Added the multi cart per room setup --- .gitignore | 1 + Sprites/NPCs/followers.asm | 16 +- Sprites/Objects/minecart.asm | 426 +++++++++++++++++++++++++---------- 3 files changed, 313 insertions(+), 130 deletions(-) diff --git a/.gitignore b/.gitignore index 1bb62b3..0c0212c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ oos165x.sfc oos165x.smp.sym oos165x.srm buildJ.bat +oos165x.cht diff --git a/Sprites/NPCs/followers.asm b/Sprites/NPCs/followers.asm index 118c46f..eb894a4 100644 --- a/Sprites/NPCs/followers.asm +++ b/Sprites/NPCs/followers.asm @@ -784,10 +784,10 @@ MinecartFollower_TransitionToSprite: JSL Sprite_SpawnDynamically TYX JSL Sprite_SetSpawnedCoords - LDA.w !MinecartDirection : CMP.b #$00 : BEQ .vert_adjust + LDA.w !MinecartDirection, X : CMP.b #$00 : BEQ .vert_adjust CMP.b #$02 : BEQ .vert_adjust LDA.w POSY : CLC : ADC #$08 : STA.w SprY, X - LDA.w POSX : STA.w SprX, X + LDA.w POSX : STA.w SprX, X JMP .finish_prep .vert_adjust LDA.w POSY : STA.w SprY, X @@ -795,9 +795,11 @@ MinecartFollower_TransitionToSprite: .finish_prep LDA.w POSYH : STA.w SprYH, X LDA.w POSXH : STA.w SprXH, X - LDA.w !MinecartDirection - CLC : ADC.b #$04 - STA.w SprSubtype, X + LDA.w !MinecartDirection, X + CLC : ADC.b #$04 : STA.w SprMiscB, X + + ; Tell the newly spawned cart which track it is on. + LDA.w !MinecartTrackCache : STA.w SprSubtype, X LDA Minecart_AnimDirection, X : STA $0D90, X JSL Sprite_Minecart_Prep @@ -810,7 +812,7 @@ DrawMinecartFollower: { JSL $099EFC ; Follower_Initialize - LDX !MinecartDirection + LDA.w !MinecartDirection, X : TAX LDA Minecart_AnimDirection, X : STA $02CF JSR FollowerDraw_CachePosition @@ -951,7 +953,7 @@ LinkState_Minecart: STZ.b $48 ; Move Link based on the direction of the cart - LDA.w !MinecartDirection : BNE .not_north + LDA.w !MinecartDirection, X : BNE .not_north LDY.b #$00 LDA.w .drag_y_low, Y : CLC : ADC.w $0B7E : STA.w $0B7E LDA.w .drag_y_high, Y : ADC.w $0B7F : STA.w $0B7F diff --git a/Sprites/Objects/minecart.asm b/Sprites/Objects/minecart.asm index 3254156..2b38fd1 100644 --- a/Sprites/Objects/minecart.asm +++ b/Sprites/Objects/minecart.asm @@ -7,7 +7,7 @@ ; ; The cart begins in an inactive state, horizontal or vertical ; and is activated by the player when they stand on the hitbox -; and press the B button. Based on the subtype of the cart, +; and press the B button. Based on the SprMiscB of the cart, ; it will move in that direction until it encounters one of the ; following scenarions: ; @@ -62,7 +62,7 @@ !MinecartSpeed = 20 !DoubleSpeed = 30 -; SprSubtype and Minecart movement direction +; SprMiscB and Minecart movement direction ; nesw ; 0 - north ; 1 - east @@ -72,7 +72,7 @@ North = $00 East = $01 South = $02 West = $03 -!MinecartDirection = $012B +!MinecartDirection = $0DE0 ; = SprMiscC ; Sprite Facing Direction ; udlr @@ -86,6 +86,34 @@ Left = $02 Right = $03 !SpriteDirection = $0DE0 + +; A "track" is one minecart that can exist in multiple different places. +; Allowing the player to leave a minecart in one room and then still find +; it in the same place upon returning to that room. + +; There is a total possibility of 0x20 different subtypes that can be set. +; Therefore there can be a total of 0x20 different tracks. + +; This value is used to keep track of which room the minecart was left +; in. Currently #$00 is reserved to keep track of new tracks that have +; not been used yet so tracks will not work when stopped in room 00. Up +; to $0768 used which is all free ram. +!MinecartTrackRoom = $0728 + +; Track X position. This is used to keep track of the possibility of +; there being more than one stop per track in the same room. Up to $07A8 +; used which is all free ram. +!MinecartTrackX = $0768 + +; Track X position. This is used to keep track of the possibility of +; there being more than one stop per track in the same room. Up to $07E8 +; used which is all free ram. +!MinecartTrackY = $07A8 + +; This is used to keep track of which track we are on while riding +; the cart. We can only use one cart at a time so this is only 1 byte. +!MinecartTrackCache = $07E8 + ; ========================================================= Sprite_Minecart_Long: @@ -101,131 +129,157 @@ Sprite_Minecart_Long: } ; ========================================================= -; The subtype of the minecart determines the direction it -; will move in, so if the subtype is 0 the cart will move +; The SprMiscB of the minecart determines the direction it +; will move in, so if the SprMiscB is 0 the cart will move ; north and start in WaitVert mode. Sprite_Minecart_Prep: { PHB : PHK : PLB + print "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: ", pc + + JSR UpdateCachedCoords + + LDA.w SprSubtype, X : ASL : TAY + + ; If Link is in a cart AND he is on the same track as this cart's + ; track, kill the cart. + CMP.w !MinecartTrackCache : BNE .notSameTrack + LDA.b !LinkInCart : BEQ .notInCart + BRA .killMinecart + .notInCart + .notSameTrack + + REP #$20 + ; Check if the track has already been initialized. If not we need to + ; tell the game where the cart on the track starts + LDA.w !MinecartTrackRoom, Y : BNE .trackAlreadySetUp + LDA.w .TrackStartingX, Y : STA.w !MinecartTrackX, Y + LDA.w .TrackStartingY, Y : STA.w !MinecartTrackY, Y + LDA.w .TrackStartingRooms, Y : STA.w !MinecartTrackRoom, Y + .trackAlreadySetUp + + ; Check if we are currently in the room where the track was left. + CMP.b $A0 : BEQ .inRoom + .killMinecart + SEP #$20 + STZ.w SprState, X + + PLB + RTL + .inRoom + + ; Check if the coordinates match, if not kill the sprite. + LDA.w !MinecartTrackX, Y : CMP.w SprCachedX : BNE .killMinecart + LDA.w !MinecartTrackY, Y : CMP.w SprCachedY : BNE .killMinecart + SEP #$20 + STZ.w SprMiscF, X ; Clear the auto-move flag STZ.w SprMiscG, X ; Clear the active tossing flag - ; If the subtype is > 4, then it's an active cart - LDA.w SprSubtype, X : CMP.b #$04 : BCC + - LDA.w SprSubtype, X : SEC : SBC.b #$04 : STA.w SprSubtype, X - LDA.b #$01 : STA.w SprMiscF, X ; Set the auto-move flag - + - LDA.b #$04 : STA.w SprNbrOAM, X ; Nbr Oam Entries LDA.b #$40 : STA.w SprGfxProps, X ; Impervious props LDA.b #$E0 : STA.w SprHitbox, X ; Persist outside camera STZ.w SprDefl, X ; Sprite persist in dungeon STZ.w SprBump, X ; No bump damage STZ.w SprTileDie, X ; Set interactive hitbox - STZ.w !MinecartDirection + + STZ.w !MinecartDirection, X STZ.w !SpriteDirection, X - LDA.w SprSubtype, X : CMP.b #$00 : BEQ .north - CMP.b #$01 : BEQ .east - CMP.b #$02 : BEQ .south - CMP.b #$03 : BEQ .west + ; If the SprMiscB is > 4, then it's an active cart. This should only + ; be the case when transitioning from a follower. + LDA.w SprMiscB, X : CMP.b #$04 : BCC .notActive + LDA.w SprMiscB, X : SEC : SBC.b #$04 : STA.w SprMiscB, X + LDA.b #$01 : STA.w SprMiscF, X ; Set the auto-move flag + + BRA .active + .notActive + ; Setup Minecart position to look for tile IDs + ; We use AND #$F8 to clamp to a 8x8 grid. + LDA.w SprY, X : AND #$F8 : STA.b $00 + LDA.w SprYH, X : STA.b $01 + + LDA.w SprX, X : AND #$F8 : STA.b $02 + LDA.w SprXH, X : STA.b $03 + + ; Fetch tile attributes based on current coordinates + LDA.b #$00 : JSL Sprite_GetTileAttr + + ; Set our starting direction based on the stop tile we are on. + ; This means minecarts should always be placed on top of a stop tile. + LDA.w SPRTILE + CMP.b #$B7 : BEQ .goSouth + CMP.b #$B8 : BEQ .goNorth + CMP.b #$B9 : BEQ .goEast + CMP.b #$BA : BEQ .goWest + .goNorth + LDA.b #North : STA.w SprMiscB, X + JMP .done2 + .goEast + LDA.b #East : STA.w SprMiscB, X + JMP .done2 + .goSouth + LDA.b #South : STA.w SprMiscB, X + JMP .done2 + .goWest + LDA.b #West : STA.w SprMiscB, X + .done2 + .active + + LDA.w SprMiscB, X : CMP.b #$00 : BEQ .north + CMP.b #$01 : BEQ .east + CMP.b #$02 : BEQ .south + CMP.b #$03 : BEQ .west .north + ; Both !MinecartDirection and !SpriteDirection set to 0 earlier. %GotoAction(1) ; Minecart_WaitVert - JMP .done + JMP .done .east - LDA.b #East : STA !MinecartDirection + LDA.b #East : STA !MinecartDirection, X LDA.b #Right : STA !SpriteDirection, X %GotoAction(0) ; Minecart_WaitHoriz JMP .done .south - LDA.b #South : STA !MinecartDirection - LDA.b #Down : STA !SpriteDirection, X + LDA.b #South : STA !MinecartDirection, X + LDA.b #Down : STA !SpriteDirection, X %GotoAction(1) ; Minecart_WaitVert JMP .done .west - LDA.b #West : STA !MinecartDirection + LDA.b #West : STA !MinecartDirection, X LDA.b #Left : STA !SpriteDirection, X %GotoAction(0) ; Minecart_WaitHoriz .done PLB RTL -} -; ========================================================= -; Handle the tossing of the cart -; Changes the subtype of the cart to indicate the direction -; the cart is facing and sets the velocity of the cart -; based on the direction it is facing. + ; This is which room each track should start in if it hasn't already + ; been given a track. + .TrackStartingRooms + dw $0089, $0089, $0089, $0089, $0089, $0089, $0089, $0089 + dw $0089, $0089, $0089, $0089, $0089, $0089, $0089, $0089 + dw $0089, $0089, $0089, $0089, $0089, $0089, $0089, $0089 + dw $0089, $0089, $0089, $0089, $0089, $0089, $0089, $0089 -Minecart_HandleToss: -{ - LDA.b #$30 : STA.w SprTimerA, X - ; Check links facing direction $2F and apply velocity - LDA $2F : CMP.b #$00 : BEQ .toss_north - CMP.b #$02 : BEQ .toss_south - CMP.b #$04 : BEQ .toss_east - CMP.b #$06 : BEQ .toss_west - .toss_north - LDA.b #-!DoubleSpeed : STA.w SprYSpeed, X - LDA #$00 : STA.w SprSubtype, X : STA !SpriteDirection, X - %GotoAction(1) ; Minecart_WaitVert - JMP .continue - .toss_south - LDA.b #!DoubleSpeed : STA.w SprYSpeed, X - LDA #$02 : STA.w SprSubtype, X - LDA #$01 : STA !SpriteDirection, X - %GotoAction(1) ; Minecart_WaitVert - JMP .continue - .toss_east - LDA.b #-!DoubleSpeed : STA.w SprXSpeed, X - LDA #$01 : STA.w SprSubtype, X - LDA #$03 : STA !SpriteDirection, X - %GotoAction(0) ; Minecart_WaitHoriz - JMP .continue - .toss_west - LDA.b #!DoubleSpeed : STA.w SprXSpeed, X - LDA #$03 : STA.w SprSubtype, X - LDA #$02 : STA !SpriteDirection, X - %GotoAction(0) ; Minecart_WaitHoriz - .continue - LDA #$01 : STA.w SprMiscG, X - LDA #$12 : STA.w SprTimerC, X - STA.w SprYRound, X : STA.w SprXRound, X - RTS -} + ; This is where within the room each track should start in if it hasn't + ; already been given a position. This is necessary to allow for more + ; than one stopping point to be in one room. + .TrackStartingX + dw $1320, $12D0, $1300, $1300, $1300, $1300, $1300, $1300 + dw $1300, $1300, $1300, $1300, $1300, $1300, $1300, $1300 + dw $1300, $1300, $1300, $1300, $1300, $1300, $1300, $1300 + dw $1300, $1300, $1300, $1300, $1300, $1300, $1300, $1300 -Minecart_HandleTossedCart: -{ - LDA.w SprMiscG, X : BEQ .not_tossed - LDA.w SprHeight, X : BEQ .low_enough - DEC.w SprHeight, X - RTS - .low_enough + .TrackStartingY + dw $11C0, $1120, $1100, $1100, $1100, $1100, $1100, $1100 + dw $1100, $1100, $1100, $1100, $1100, $1100, $1100, $1100 + dw $1100, $1100, $1100, $1100, $1100, $1100, $1100, $1100 + dw $1100, $1100, $1100, $1100, $1100, $1100, $1100, $1100 - LDA.w SprTimerC, X : BNE .not_tossed - LDA.w SprX, X : AND.b #$F8 : STA.w SprX, X - LDA.w SprY, X : AND.b #$F8 : STA.w SprY, X - STZ.w SprMiscG, X - STZ.w SprYSpeed, X - STZ.w SprXSpeed, X - STZ.w SprHeight, X - .not_tossed - RTS -} - -Minecart_HandleLiftAndToss: -{ - JSR CheckIfPlayerIsOn : BCC .not_tossing - LDA.w LinkCarryOrToss : CMP.b #$02 : BNE .not_tossing - JSR Minecart_HandleToss - .not_tossing - JSL Sprite_CheckIfLifted - JSL Sprite_Move - JSR Minecart_HandleTossedCart - JSL ThrownSprite_TileAndSpriteInteraction_long - RTS + ; NOTE TO SCAWFUL: All of these values will need to be set when you + ; place the carts within ZS. I set them all to spawn in the middle of + ; room 0x89 just for testing purposes. } ; ========================================================= @@ -248,6 +302,7 @@ Sprite_Minecart_Main: Minecart_WaitHoriz: { %PlayAnimation(0,1,8) + LDA.w LinkCarryOrToss : AND #$03 : BNE .lifting LDA.w SprTimerA, X : BNE .not_ready JSR CheckIfPlayerIsOn : BCC .not_ready @@ -257,14 +312,17 @@ Sprite_Minecart_Main: LDA $F4 : AND.b #$80 : BEQ .not_ready .active_cart + ; Save what track we are currently riding. + LDA.w SprSubtype, X : STA.w !MinecartTrackCache + JSL Link_CancelDash - LDA #$02 : STA.w LinkSomaria - LDA #$01 : STA !LinkInCart + LDA.b #$02 : STA.w LinkSomaria + LDA.b #$01 : STA.w !LinkInCart ; Adjust player pos LDA.w SprCachedY : SEC : SBC #$0B : STA $20 ; Check if the cart is facing east or west - LDA.w SprSubtype, X : CMP.b #$03 : BNE + + LDA.w SprMiscB, X : CMP.b #$03 : BNE + JSR Minecart_SetDirectionWest %GotoAction(5) ; Minecart_MoveWest RTS @@ -274,6 +332,7 @@ Sprite_Minecart_Main: RTS .not_ready .lifting + ;JSR Minecart_HandleLiftAndToss RTS } @@ -283,6 +342,7 @@ Sprite_Minecart_Main: Minecart_WaitVert: { %PlayAnimation(2,3,8) + LDA.w LinkCarryOrToss : AND #$03 : BNE .lifting LDA.w SprTimerA, X : BNE .not_ready JSR CheckIfPlayerIsOn : BCC .not_ready @@ -292,6 +352,9 @@ Sprite_Minecart_Main: LDA $F4 : AND.b #$80 : BEQ .not_ready .active_cart + ; Save what track we are currently riding. + LDA.w SprSubtype, X : STA.w !MinecartTrackCache + JSL Link_CancelDash LDA.b #$02 : STA.w LinkSomaria LDA.b #$01 : STA.w !LinkInCart @@ -299,7 +362,7 @@ Sprite_Minecart_Main: LDA.w SprCachedY : SEC : SBC #$0B : STA $20 ; Check if the cart is facing north or south - LDA.w SprSubtype, X : BEQ + + LDA.w SprMiscB, X : BEQ + JSR Minecart_SetDirectionSouth %GotoAction(4) ; Minecart_MoveSouth RTS @@ -309,6 +372,7 @@ Sprite_Minecart_Main: RTS .not_ready .lifting + ;JSR Minecart_HandleLiftAndToss RTS } @@ -443,7 +507,7 @@ Sprite_Minecart_Main: %GotoAction(1) ; Minecart_WaitVert RTS .horiz - %GotoAction(0) + %GotoAction(0) ; Minecart_WaitHoriz .not_ready RTS } @@ -471,6 +535,17 @@ StopCart: STZ.w SprYSpeed, X STZ.w SprXSpeed, X STZ.w !LinkInCart + + JSR RoundCoords + + LDA.w SprSubtype, X : ASL : TAY + + REP #$20 + LDA.w SprCachedX : STA.w !MinecartTrackX, Y + LDA.w SprCachedY : STA.w !MinecartTrackY, Y + LDA.w $A0 : STA.w !MinecartTrackRoom, Y + SEP #$20 + RTS } @@ -485,28 +560,28 @@ InitMovement: Minecart_SetDirectionNorth: { - LDA.b #North : STA.w SprSubtype, X : STZ.w !MinecartDirection - LDA.b #Up : STA !SpriteDirection, X + LDA.b #North : STA.w SprMiscB, X : STZ.w !MinecartDirection, X + LDA.b #Up : STA !SpriteDirection, X RTS } Minecart_SetDirectionEast: { - LDA.b #East : STA.w SprSubtype, X : STA.w !MinecartDirection - LDA.b #Right : STA !SpriteDirection, X + LDA.b #East : STA.w SprMiscB, X : STA.w !MinecartDirection, X + LDA.b #Right : STA !SpriteDirection, X RTS } Minecart_SetDirectionSouth: { - LDA.b #South : STA.w SprSubtype, X : STA.w !MinecartDirection - LDA.b #Down : STA.w !SpriteDirection, X + LDA.b #South : STA.w SprMiscB, X : STA.w !MinecartDirection, X + LDA.b #Down : STA.w !SpriteDirection, X RTS } Minecart_SetDirectionWest: { - LDA.b #West : STA.w SprSubtype, X : STA.w !MinecartDirection + LDA.b #West : STA.w SprMiscB, X : STA.w !MinecartDirection, X LDA.b #Left : STA.w !SpriteDirection, X RTS } @@ -541,7 +616,7 @@ CheckForStopTiles: RTS .check_direction - LDA.w SprSubtype, X + LDA.w SprMiscB, X ASL #2 ; Multiply by 4 to offset rows in the lookup table STA $07 ; Store the action index in $07 @@ -626,7 +701,7 @@ CheckForCornerTiles: CLC RTS .check_direction - LDA.w SprSubtype, X + LDA.w SprMiscB, X ASL #2 ; Multiply by 4 to offset rows in the lookup table STA $07 ; Store the action index in $07 @@ -691,17 +766,17 @@ CheckForTrackTiles: .horiz ; Are we moving left or right? - LDA.w SprSubtype, X : CMP.b #$03 : BEQ .inverse_horiz_velocity + LDA.w SprMiscB, X : CMP.b #$03 : BEQ .inverse_horiz_velocity LDA.b #!MinecartSpeed : STA.w SprXSpeed, X - LDA.b #East : STA !MinecartDirection + LDA.b #East : STA !MinecartDirection, X JMP .done .inverse_horiz_velocity LDA.b #-!MinecartSpeed : STA.w SprXSpeed, X - LDA.b #West : STA !MinecartDirection + LDA.b #West : STA !MinecartDirection, X JMP .done .vert ; Are we moving up or down? - LDA.w SprSubtype, X : CMP.b #$00 : BEQ .inverse_vert_velocity + LDA.w SprMiscB, X : CMP.b #$00 : BEQ .inverse_vert_velocity LDA.b #!MinecartSpeed : STA.w SprYSpeed, X JMP .done .inverse_vert_velocity @@ -723,12 +798,12 @@ HandleTileDirections: .player_on_cart ; Setup Minecart position to look for tile IDs - ; We use AND #$F8 to clamp to a 16x16 grid. + ; We use AND #$F8 to clamp to a 8x8 grid. LDA.w SprY, X : AND #$F8 : STA.b $00 - LDA.w SprYH, X : STA.b $01 + LDA.w SprYH, X : STA.b $01 LDA.w SprX, X : AND #$F8 : STA.b $02 - LDA.w SprXH, X : STA.b $03 + LDA.w SprXH, X : STA.b $03 ; Fetch tile attributes based on current coordinates LDA.b #$00 : JSL Sprite_GetTileAttr @@ -737,8 +812,6 @@ HandleTileDirections: STA.l $7EF362 : STA.l $7EF360 LDA.b #$00 : STA.l $7EF363 : STA.l $7EF361 - print "adfsddddddddddddddddddddddddddddddddddddddddddddddddd: ", pc - LDA.w SPRTILE JSR CheckForOutOfBounds : BCC .notOutOfBounds JSR RoundCoords @@ -760,13 +833,45 @@ HandleTileDirections: RTS } +; NOTE TO SCAWFUL: This function could really go in a generic sprite +; functions file but I'll leave that up to you. +UpdateCachedCoords: +{ + LDA.w SprY, X : STA.w SprCachedY+0 + LDA.w SprX, X : STA.w SprCachedX+0 + LDA.w SprYH, X : STA.w SprCachedY+1 + LDA.w SprXH, X : STA.w SprCachedX+1 + + RTS +} + +; NOTE TO SCAWFUL: This function could really go in a generic sprite +; functions file but I'll leave that up to you. RoundCoords: { ; Clamp the Y coord to the nearest multiple of 8. - LDA.b $00 : CLC : ADC.b #$04 : AND.b #$F8 : STA.b $00 : STA.w SprY, x + LDA.b $00 : CLC : ADC.b #$04 : AND.b #$F8 : STA.b $00 : STA.w SprY, X ; Clamp the X coord to the nearest multiple of 8. - LDA.b $02 : CLC : ADC.b #$04 : AND.b #$F8 : STA.b $02 : STA.w SprX, x + LDA.b $02 : CLC : ADC.b #$04 : AND.b #$F8 : STA.b $02 : STA.w SprX, X + + JSR UpdateCachedCoords + + RTS +} + +; TODO: Hook this up to a dungeon loading routine +; mask_routines or gbc_form maybe. +ResetTrackVars: +{ + LDA.b #$00 : STA.w !MinecartTrackCache + LDX.b #$41 + .loop + DEX + STA.w !MinecartTrackRoom, X + STA.w !MinecartTrackX, X + STA.w !MinecartTrackY, X + CPX.b #$00 : BNE .loop RTS } @@ -785,10 +890,10 @@ HandleDynamicSwitchTileDirections: JSL Sprite_SetupHitBox ; X is now the ID of the sprite $B0 PLX JSL CheckIfHitBoxesOverlap : BCC .no_b0 - LDA !MinecartDirection : CMP.b #$00 : BEQ .east_or_west - CMP.b #$01 : BEQ .north_or_south - CMP.b #$02 : BEQ .east_or_west - CMP.b #$03 : BEQ .north_or_south + LDA !MinecartDirection, X : CMP.b #$00 : BEQ .east_or_west + CMP.b #$01 : BEQ .north_or_south + CMP.b #$02 : BEQ .east_or_west + CMP.b #$03 : BEQ .north_or_south .no_b0 RTS @@ -827,12 +932,12 @@ CheckSpritePresence: .y_loop DEY LDA $0E20, X : CMP.b #$B0 : BEQ .set_flag - BRA .not_b0 + BRA .not_b0 .set_flag SEC ; Set flag indicating sprite ID $B0 is present STX.w $02 - BRA .done + BRA .done .not_b0 CPY.b #$00 : BNE .y_loop @@ -911,6 +1016,81 @@ CheckIfPlayerIsOn: RTS ; Return with carry cleared } +; ========================================================= +; Handle the tossing of the cart +; Changes the SprMiscB of the cart to indicate the direction +; the cart is facing and sets the velocity of the cart +; based on the direction it is facing. + +Minecart_HandleToss: +{ + LDA.b #$30 : STA.w SprTimerA, X + ; Check links facing direction $2F and apply velocity + LDA $2F : CMP.b #$00 : BEQ .toss_north + CMP.b #$02 : BEQ .toss_south + CMP.b #$04 : BEQ .toss_east + CMP.b #$06 : BEQ .toss_west + .toss_north + LDA.b #-!DoubleSpeed : STA.w SprYSpeed, X + LDA #$00 : STA.w SprMiscB, X : STA !SpriteDirection, X + %GotoAction(1) ; Minecart_WaitVert + JMP .continue + .toss_south + LDA.b #!DoubleSpeed : STA.w SprYSpeed, X + LDA #$02 : STA.w SprMiscB, X + LDA #$01 : STA !SpriteDirection, X + %GotoAction(1) ; Minecart_WaitVert + JMP .continue + .toss_east + LDA.b #-!DoubleSpeed : STA.w SprXSpeed, X + LDA #$01 : STA.w SprMiscB, X + LDA #$03 : STA !SpriteDirection, X + %GotoAction(0) ; Minecart_WaitHoriz + JMP .continue + .toss_west + LDA.b #!DoubleSpeed : STA.w SprXSpeed, X + LDA #$03 : STA.w SprMiscB, X + LDA #$02 : STA !SpriteDirection, X + %GotoAction(0) ; Minecart_WaitHoriz + .continue + LDA #$01 : STA.w SprMiscG, X + LDA #$12 : STA.w SprTimerC, X + STA.w SprYRound, X : STA.w SprXRound, X + RTS +} + +Minecart_HandleTossedCart: +{ + LDA.w SprMiscG, X : BEQ .not_tossed + LDA.w SprHeight, X : BEQ .low_enough + DEC.w SprHeight, X + RTS + .low_enough + + LDA.w SprTimerC, X : BNE .not_tossed + LDA.w SprX, X : AND.b #$F8 : STA.w SprX, X + LDA.w SprY, X : AND.b #$F8 : STA.w SprY, X + STZ.w SprMiscG, X + STZ.w SprYSpeed, X + STZ.w SprXSpeed, X + STZ.w SprHeight, X + .not_tossed + RTS +} + +Minecart_HandleLiftAndToss: +{ + JSR CheckIfPlayerIsOn : BCC .not_tossing + LDA.w LinkCarryOrToss : CMP.b #$02 : BNE .not_tossing + JSR Minecart_HandleToss + .not_tossing + JSL Sprite_CheckIfLifted + JSL Sprite_Move + JSR Minecart_HandleTossedCart + JSL ThrownSprite_TileAndSpriteInteraction_long + RTS +} + ; ========================================================= ; Draw the portion of the cart which is behind the player From e203e5718389bcafe3d8874dd3afed2bdad5ec5e Mon Sep 17 00:00:00 2001 From: Jared_Brian_ Date: Wed, 22 Jan 2025 23:32:23 -0700 Subject: [PATCH 4/9] Added the T junction logic --- Sprites/Objects/minecart.asm | 140 +++++++++++++++++++++++------------ 1 file changed, 92 insertions(+), 48 deletions(-) diff --git a/Sprites/Objects/minecart.asm b/Sprites/Objects/minecart.asm index 2b38fd1..bc23094 100644 --- a/Sprites/Objects/minecart.asm +++ b/Sprites/Objects/minecart.asm @@ -137,8 +137,6 @@ Sprite_Minecart_Prep: { PHB : PHK : PLB - print "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: ", pc - JSR UpdateCachedCoords LDA.w SprSubtype, X : ASL : TAY @@ -324,7 +322,7 @@ Sprite_Minecart_Main: ; Check if the cart is facing east or west LDA.w SprMiscB, X : CMP.b #$03 : BNE + JSR Minecart_SetDirectionWest - %GotoAction(5) ; Minecart_MoveWest + %GotoAction(5) ; Minecart_MoveWest RTS + JSR Minecart_SetDirectionEast @@ -397,7 +395,6 @@ Sprite_Minecart_Main: ; Get direction of the cart (0 to 3) LDY.w !SpriteDirection, X JSL DragPlayer - JSR CheckForPlayerInput JSR HandlePlayerCameraAndMoveCart JSR HandleTileDirections @@ -426,7 +423,6 @@ Sprite_Minecart_Main: ; Get direction of the cart (0 to 3) LDY.w !SpriteDirection, X JSL DragPlayer - JSR CheckForPlayerInput JSR HandlePlayerCameraAndMoveCart JSR HandleTileDirections @@ -455,7 +451,6 @@ Sprite_Minecart_Main: ; Get direction of the cart (0 to 3) LDY.w !SpriteDirection, X JSL DragPlayer - JSR CheckForPlayerInput JSR HandlePlayerCameraAndMoveCart JSR HandleTileDirections @@ -484,7 +479,6 @@ Sprite_Minecart_Main: ; Get direction of the cart (0 to 3) LDY.w !SpriteDirection, X JSL DragPlayer - JSR CheckForPlayerInput JSR HandlePlayerCameraAndMoveCart JSR HandleTileDirections @@ -591,7 +585,7 @@ Minecart_SetDirectionWest: CheckForOutOfBounds: { - CMP.b #$02 : BNE .not_out_of_bounds + LDA.w SPRTILE : CMP.b #$02 : BNE .not_out_of_bounds ; If the tile is out of bounds, release the cart LDA #$40 : STA.w SprTimerD, X %GotoAction(6) ; Minecart_Release @@ -607,11 +601,11 @@ CheckForOutOfBounds: ; CLC if no stop occured, SEC if stop occured. CheckForStopTiles: { + LDA.w SPRTILE CMP.b #$B7 : BEQ .check_direction CMP.b #$B8 : BEQ .check_direction CMP.b #$B9 : BEQ .check_direction CMP.b #$BA : BEQ .check_direction - .exit CLC RTS .check_direction @@ -632,7 +626,6 @@ CheckForStopTiles: CPY.b #$03 : BEQ .stop_south CPY.b #$04 : BEQ .stop_west CLC - RTS .stop_north @@ -693,6 +686,7 @@ CheckForStopTiles: CheckForCornerTiles: { + LDA.w SPRTILE CMP.b #$B2 : BEQ .check_direction CMP.b #$B3 : BEQ .check_direction CMP.b #$B4 : BEQ .check_direction @@ -812,7 +806,6 @@ HandleTileDirections: STA.l $7EF362 : STA.l $7EF360 LDA.b #$00 : STA.l $7EF363 : STA.l $7EF361 - LDA.w SPRTILE JSR CheckForOutOfBounds : BCC .notOutOfBounds JSR RoundCoords @@ -820,15 +813,25 @@ HandleTileDirections: .notOutOfBounds + print "SDFL:KDFSDFSDFSFSFSDFSDFSFSFSDFSFSFSDFSD: ", pc + JSR CheckForPlayerInput : BCC .noInput + JSR RoundCoords + + BRA .done + + .noInput + JSR CheckForStopTiles : BCC .noStop JSR RoundCoords BRA .done .noStop - JSR CheckForCornerTiles : BCC .done + JSR CheckForCornerTiles : BCC .noCorner JSR RoundCoords + .noCorner + .done RTS } @@ -860,10 +863,21 @@ RoundCoords: RTS } -; TODO: Hook this up to a dungeon loading routine -; mask_routines or gbc_form maybe. +pushpc + +org $0DFA68 + RebuildHUD_Keys: + +org $028260 + JSL ResetTrackVars + +pullpc + ResetTrackVars: { + ; Replaced code. + JSL.l RebuildHUD_Keys + LDA.b #$00 : STA.w !MinecartTrackCache LDX.b #$41 .loop @@ -873,7 +887,7 @@ ResetTrackVars: STA.w !MinecartTrackY, X CPX.b #$00 : BNE .loop - RTS + RTL } ; ========================================================= @@ -949,49 +963,79 @@ CheckSpritePresence: ; ========================================================= ; Check for input from the user (u,d,l,r) on tile B6, BD +; CLC if not on an input tile or there was no input recieved. CheckForPlayerInput: { - ; Setup Minecart position to look for tile IDs - LDA.w SprY, X : AND #$F8 : STA.b $00 : LDA.w SprYH, X : STA.b $01 - LDA.w SprX, X : AND #$F8 : STA.b $02 : LDA.w SprXH, X : STA.b $03 - - ; Fetch tile attributes based on current coordinates - LDA.b #$00 : JSL Sprite_GetTileAttr - ; Load the tile index - LDA $0FA5 : CLC : CMP.b #$B6 : BEQ .can_input - CMP.b #$BD : BEQ .can_input - BRA .cant_input + LDA.w SPRTILE : CMP.b #$B6 : BEQ .can_input ; Intersection + CMP.b #$BB : BEQ .can_input ; North T + CMP.b #$BC : BEQ .can_input ; South T + CMP.b #$BD : BEQ .can_input ; East T + CMP.b #$BE : BEQ .can_input ; West T + CLC + RTS .can_input - LDY !SpriteDirection, X - LDA $F0 : AND .d_pad_press, Y : STA $00 : AND.b #$08 : BEQ .not_pressing_up + ; Normalize the tile. + SEC : SBC.b #$B6 : TAY + + ; Get an offset based on the tile the get the allowed directions. + LDA.w .intersectionMap, Y + + ; Add the direction the cart is going to prevent the cart from + ; returning from where it came from. + CLC : ADC.w !SpriteDirection, X : TAY + + ; Filter the input. + LDA $F0 : AND.w .d_pad_press, Y : STA $05 : AND.b #$08 : BEQ .not_pressing_up JSR Minecart_SetDirectionNorth + %GotoAction(2) ; Minecart_MoveNorth - BRA .return - - .not_pressing_up - LDA.b $00 : AND.b #$04 : BEQ .not_pressing_down - JSR Minecart_SetDirectionSouth - %GotoAction(4) ; Minecart_MoveSouth - BRA .return - - .not_pressing_down - LDA.b $00 : AND.b #$02 : BEQ .not_pressing_left - JSR Minecart_SetDirectionWest - %GotoAction(5) ; Minecart_MoveWest - BRA .return - - .not_pressing_left - LDA.b $00 : AND.b #$01 : BEQ .return - JSR Minecart_SetDirectionEast - %GotoAction(3) ; Minecart_MoveEast - .return - .cant_input + SEC RTS + .not_pressing_up + LDA.b $05 : AND.b #$04 : BEQ .not_pressing_down + JSR Minecart_SetDirectionSouth + + %GotoAction(4) ; Minecart_MoveSouth + SEC + RTS + + .not_pressing_down + LDA.b $05 : AND.b #$02 : BEQ .not_pressing_left + JSR Minecart_SetDirectionWest + + %GotoAction(5) ; Minecart_MoveWest + SEC + RTS + + .not_pressing_left + LDA.b $05 : AND.b #$01 : BEQ .return + JSR Minecart_SetDirectionEast + + %GotoAction(3) ; Minecart_MoveEast + SEC + RTS + .return + + ; If we made it here that means there was no matching input. + CLC + RTS + .d_pad_press - db $0B, $07, $0E, $0D + ; udlr + ; up, down, left, right + db $00, $00, $00, $00 ; Nothing + db $0B, $07, $0E, $0D ; Intersection + db $03, $03, $04, $04 ; North T + db $03, $03, $08, $08 ; South T + db $02, $02, $0C, $0C ; East T + db $01, $01, $0C, $0C ; West T + + .intersectionMap + ; B6, B7, B8, B9, BA, BB, BC, BD, BE + db $04, $00, $00, $00, $00, $08, $0C, $10, $14 } ; ========================================================= From ed439e28ed4d9603b22e0e4ec108b2511f57c99b Mon Sep 17 00:00:00 2001 From: Jared_Brian_ Date: Mon, 27 Jan 2025 21:47:19 -0700 Subject: [PATCH 5/9] Added the default directions for junction interaction. Made the corner change direction animation more snappy. Made the initial animation frame for vertical carts actually be vertical. --- Core/sprite_macros.asm | 8 +-- Sprites/Objects/minecart.asm | 104 ++++++++++++++++++++++++++++------- 2 files changed, 89 insertions(+), 23 deletions(-) diff --git a/Core/sprite_macros.asm b/Core/sprite_macros.asm index 2de7780..b4d0b54 100644 --- a/Core/sprite_macros.asm +++ b/Core/sprite_macros.asm @@ -132,9 +132,9 @@ macro PlayAnimation(frame_start, frame_end, frame_wait) { LDA.w SprTimerB, X : BNE + LDA.w SprFrame, X : INC : STA.w SprFrame, X - CMP.b #+1 : BCC .noframereset + CMP.b #+1 : BCC ++ LDA.b # : STA.w SprFrame, X - .noframereset + ++ LDA.b # : STA.w SprTimerB, X + } @@ -143,9 +143,9 @@ endmacro macro PlayAnimBackwards(frame_start, frame_end, frame_wait) LDA.w SprTimerB, X : BNE + LDA.w SprFrame, X : DEC : STA.w SprFrame, X - CMP.b # : BCS .noframereset + CMP.b # : BCS ++ LDA.b # : STA.w SprFrame, X - .noframereset + ++ LDA.b # : STA.w SprTimerB, X + endmacro diff --git a/Sprites/Objects/minecart.asm b/Sprites/Objects/minecart.asm index bc23094..7e5be14 100644 --- a/Sprites/Objects/minecart.asm +++ b/Sprites/Objects/minecart.asm @@ -225,6 +225,8 @@ Sprite_Minecart_Prep: LDA.b #West : STA.w SprMiscB, X .done2 .active + + STZ.w SprTimerB, X LDA.w SprMiscB, X : CMP.b #$00 : BEQ .north CMP.b #$01 : BEQ .east @@ -232,22 +234,35 @@ Sprite_Minecart_Prep: CMP.b #$03 : BEQ .west .north ; Both !MinecartDirection and !SpriteDirection set to 0 earlier. - %GotoAction(1) ; Minecart_WaitVert - JMP .done - .east - LDA.b #East : STA !MinecartDirection, X - LDA.b #Right : STA !SpriteDirection, X - %GotoAction(0) ; Minecart_WaitHoriz - JMP .done + BRA .vert + .south LDA.b #South : STA !MinecartDirection, X LDA.b #Down : STA !SpriteDirection, X + + .vert + %PlayAnimation(2,3,8) + LDA.b #$02 : STA.w $0D90, X + %GotoAction(1) ; Minecart_WaitVert - JMP .done + + BRA .done + .east + LDA.b #East : STA !MinecartDirection, X + LDA.b #Right : STA !SpriteDirection, X + + BRA .horz + .west LDA.b #West : STA !MinecartDirection, X LDA.b #Left : STA !SpriteDirection, X + + .horz + %PlayAnimation(0,1,8) + LDA.b #$00 : STA.w $0D90, X + %GotoAction(0) ; Minecart_WaitHoriz + .done PLB RTL @@ -362,11 +377,11 @@ Sprite_Minecart_Main: ; Check if the cart is facing north or south LDA.w SprMiscB, X : BEQ + JSR Minecart_SetDirectionSouth - %GotoAction(4) ; Minecart_MoveSouth + %GotoAction(4) ; Minecart_MoveSouth RTS + JSR Minecart_SetDirectionNorth - %GotoAction(2) ; Minecart_MoveNorth + %GotoAction(2) ; Minecart_MoveNorth RTS .not_ready .lifting @@ -554,6 +569,11 @@ InitMovement: Minecart_SetDirectionNorth: { + ; Reset the animation timer and set the animation early to make it + ; more snappy. + STZ.w SprTimerB, X + %PlayAnimation(2,3,8) + LDA.b #North : STA.w SprMiscB, X : STZ.w !MinecartDirection, X LDA.b #Up : STA !SpriteDirection, X RTS @@ -561,6 +581,11 @@ Minecart_SetDirectionNorth: Minecart_SetDirectionEast: { + ; Reset the animation timer and set the animation early to make it + ; more snappy. + STZ.w SprTimerB, X + %PlayAnimation(0,1,8) + LDA.b #East : STA.w SprMiscB, X : STA.w !MinecartDirection, X LDA.b #Right : STA !SpriteDirection, X RTS @@ -568,6 +593,11 @@ Minecart_SetDirectionEast: Minecart_SetDirectionSouth: { + ; Reset the animation timer and set the animation early to make it + ; more snappy. + STZ.w SprTimerB, X + %PlayAnimation(2,3,8) + LDA.b #South : STA.w SprMiscB, X : STA.w !MinecartDirection, X LDA.b #Down : STA.w !SpriteDirection, X RTS @@ -575,6 +605,11 @@ Minecart_SetDirectionSouth: Minecart_SetDirectionWest: { + ; Reset the animation timer and set the animation early to make it + ; more snappy. + STZ.w SprTimerB, X + %PlayAnimation(0,1,8) + LDA.b #West : STA.w SprMiscB, X : STA.w !MinecartDirection, X LDA.b #Left : STA.w !SpriteDirection, X RTS @@ -813,7 +848,6 @@ HandleTileDirections: .notOutOfBounds - print "SDFL:KDFSDFSDFSFSFSDFSDFSFSFSDFSFSFSDFSD: ", pc JSR CheckForPlayerInput : BCC .noInput JSR RoundCoords @@ -984,10 +1018,11 @@ CheckForPlayerInput: ; Add the direction the cart is going to prevent the cart from ; returning from where it came from. - CLC : ADC.w !SpriteDirection, X : TAY + CLC : ADC.w !SpriteDirection, X : STA.b $06 : TAY ; Filter the input. LDA $F0 : AND.w .d_pad_press, Y : STA $05 : AND.b #$08 : BEQ .not_pressing_up + .north JSR Minecart_SetDirectionNorth %GotoAction(2) ; Minecart_MoveNorth @@ -996,6 +1031,7 @@ CheckForPlayerInput: .not_pressing_up LDA.b $05 : AND.b #$04 : BEQ .not_pressing_down + .south JSR Minecart_SetDirectionSouth %GotoAction(4) ; Minecart_MoveSouth @@ -1004,6 +1040,7 @@ CheckForPlayerInput: .not_pressing_down LDA.b $05 : AND.b #$02 : BEQ .not_pressing_left + .west JSR Minecart_SetDirectionWest %GotoAction(5) ; Minecart_MoveWest @@ -1012,6 +1049,7 @@ CheckForPlayerInput: .not_pressing_left LDA.b $05 : AND.b #$01 : BEQ .return + .east JSR Minecart_SetDirectionEast %GotoAction(3) ; Minecart_MoveEast @@ -1019,19 +1057,47 @@ CheckForPlayerInput: RTS .return - ; If we made it here that means there was no matching input. + ; If no input was detected, we will assign a direction based on our + ; current direction and what junction we are encountering, this is to + ; prevent us from going off the top of a north junction or down off a + ; south one for example. + LDY.b $06 + LDA.w .defaultDirection, Y : CMP.b #North : BEQ .north + CMP.b #South : BEQ .south + CMP.b #East : BEQ .east + CMP.b #West : BEQ .west + + ; If we made it here, no input was found and no default directions were + ; chosen. CLC RTS + ; When setting the values for the "allowed" directions the cart can go + ; on the junctions for both tables we do not allow the direction we are + ; already going. If do allow the current direction the cart will get + ; locked on the junction because it will constantly be coordinate + ; clamped to within the junction tile, preventing it from escaping that + ; tile. .d_pad_press ; udlr ; up, down, left, right - db $00, $00, $00, $00 ; Nothing - db $0B, $07, $0E, $0D ; Intersection - db $03, $03, $04, $04 ; North T - db $03, $03, $08, $08 ; South T - db $02, $02, $0C, $0C ; East T - db $01, $01, $0C, $0C ; West T + db $0F, $0F, $0F, $0F ; Nothing + db $0B, $07, $0E, $0D ; $B6 Intersection + db $03, $03, $04, $04 ; $BB North T + db $03, $03, $08, $08 ; $BC South T + db $02, $02, $0C, $0C ; $BD East T + db $01, $01, $0C, $0C ; $BE West T + + ; #$04 is don't change direction. + .defaultDirection + ; udlr + ; up, down, left, right + db $04, $04, $04, $04 ; Nothing + db $04, $04, $04, $04 ; $B6 Intersection + db East, $04, $04, $04 ; $BB North T + db $04, East, $04, $04 ; $BC South T + db $04, $04, $04, North ; $BD East T + db $04, $04, North, $04 ; $BE West T .intersectionMap ; B6, B7, B8, B9, BA, BB, BC, BD, BE From e112bed2649ea077e20f593ee22594d690d110c8 Mon Sep 17 00:00:00 2001 From: Jared_Brian_ Date: Sat, 1 Feb 2025 19:08:57 -0700 Subject: [PATCH 6/9] Made it so the minecart sprite to follower to sprite hand off is much smoother by telling the old sprite cart not to draw after the follower spawns, adjusting the positioning of the follower draw itself, and also made it so it won't always be vertical Fixed the bug that made it so the minecart would auto grab you sometimes after getting off and then there was another bug that had accidently been introduced that made carts on track 00 not work --- Sprites/NPCs/followers.asm | 61 +++++++++++++++---------- Sprites/Objects/minecart.asm | 88 +++++++++++++++++++++++------------- 2 files changed, 95 insertions(+), 54 deletions(-) diff --git a/Sprites/NPCs/followers.asm b/Sprites/NPCs/followers.asm index eb894a4..56ca926 100644 --- a/Sprites/NPCs/followers.asm +++ b/Sprites/NPCs/followers.asm @@ -98,13 +98,13 @@ ZoraBaby_RevertToSprite: PHX TAX - LDA.w $1A64, X : AND.b #$03 : STA.w SprMiscE,Y : STA.w SprMiscC,Y - LDA.w $1A00, X : CLC : ADC.b #$02 : STA.w SprY,Y - LDA.w $1A14, X : ADC.b #$00 : STA.w SprYH,Y - LDA.w $1A28, X : CLC : ADC.b #$10 : STA.w SprX,Y - LDA.w $1A3C, X : ADC.b #$00 : STA.w SprXH,Y - LDA.b $EE : STA.w $0F20,Y - LDA.b #$01 : STA.w SprBulletproof,Y : STA.w $0E80,Y + LDA.w $1A64, X : AND.b #$03 : STA.w SprMiscE, Y : STA.w SprMiscC, Y + LDA.w $1A00, X : CLC : ADC.b #$02 : STA.w SprY, Y + LDA.w $1A14, X : ADC.b #$00 : STA.w SprYH, Y + LDA.w $1A28, X : CLC : ADC.b #$10 : STA.w SprX, Y + LDA.w $1A3C, X : ADC.b #$00 : STA.w SprXH, Y + LDA.b $EE : STA.w $0F20, Y + LDA.b #$01 : STA.w SprBulletproof, Y : STA.w $0E80, Y LDA.b #$04 : STA.w SprAction, Y LDA.b #$FF : STA.w SprTimerB, Y PLX @@ -168,8 +168,8 @@ ZoraBaby_CheckForWaterSwitchSprite: PHX LDX #$10 - - LDA.w SprType, X - CMP #$21 : BEQ ZoraBaby_CheckForWaterGateSwitch_found_switch + LDA.w SprType, X + CMP #$21 : BEQ ZoraBaby_CheckForWaterGateSwitch_found_switch DEX : BPL - ; Water gate switch not found PLX @@ -185,9 +185,9 @@ ZoraBaby_CheckForWaterGateSwitch: LDX #$10 - LDA.w SprType, X : CMP #$04 : BEQ .found_switch - DEX : BPL - - ; Water gate switch not found - PLX + DEX : BPL - + ; Water gate switch not found + PLX .not_on_switch CLC RTS @@ -203,8 +203,8 @@ ZoraBaby_CheckForWaterGateSwitch: LDA.w SprX, X : SEC : SBC #$09 : CMP.w SprX, Y : BCS .not_on_switch LDA.w SprY, X : CLC : ADC #$12 : CMP.w SprY, Y : BCC .not_on_switch LDA.w SprY, X : SEC : SBC #$12 : CMP.w SprY, Y : BCS .not_on_switch - SEC - RTS + SEC + RTS } ZoraBaby_GlobalBehavior: @@ -295,9 +295,9 @@ Sprite_39_ZoraBaby: JSL JumpTableLocal dw LockSmith_Chillin - dw ZoraBaby_FollowLink ; Becomes Follower - dw ZoraBaby_OfferService ; I can help! (Follow/Stay) - dw ZoraBaby_RespondToAnswer ; Goto FollowLink or JustPromiseOkay + dw ZoraBaby_FollowLink ; Becomes Follower + dw ZoraBaby_OfferService ; I can help! (Follow/Stay) + dw ZoraBaby_RespondToAnswer ; Goto FollowLink or JustPromiseOkay dw ZoraBaby_AgreeToWait dw ZoraBaby_PullSwitch dw ZoraBaby_PostSwitch @@ -609,17 +609,17 @@ pullpc FollowerDraw_CalculateOAMCoords: { REP #$20 - LDA.b $02 : STA.b ($90),Y + LDA.b $02 : STA.b ($90), Y INY CLC : ADC.w #$0080 : CMP.w #$0180 : BCS .off_screen LDA.b $02 : AND.w #$0100 : STA.b $74 - LDA.b $00 : STA.b ($90),Y + LDA.b $00 : STA.b ($90), Y CLC : ADC.w #$0010 : CMP.w #$0100 : BCC .on_screen .off_screen: - LDA.w #$00F0 : STA.b ($90),Y + LDA.w #$00F0 : STA.b ($90), Y .on_screen: SEP #$20 @@ -784,7 +784,8 @@ MinecartFollower_TransitionToSprite: JSL Sprite_SpawnDynamically TYX JSL Sprite_SetSpawnedCoords - LDA.w !MinecartDirection, X : CMP.b #$00 : BEQ .vert_adjust + LDA.w !MinecartDirectionCache : STA.w !MinecartDirection, X + CMP.b #$00 : BEQ .vert_adjust CMP.b #$02 : BEQ .vert_adjust LDA.w POSY : CLC : ADC #$08 : STA.w SprY, X LDA.w POSX : STA.w SprX, X @@ -802,6 +803,7 @@ MinecartFollower_TransitionToSprite: LDA.w !MinecartTrackCache : STA.w SprSubtype, X LDA Minecart_AnimDirection, X : STA $0D90, X + JSL Sprite_Minecart_Prep LDA.b #$00 : STA.l $7EF3CC RTL @@ -812,7 +814,7 @@ DrawMinecartFollower: { JSL $099EFC ; Follower_Initialize - LDA.w !MinecartDirection, X : TAX + LDA.w !MinecartDirectionCache : TAX LDA Minecart_AnimDirection, X : STA $02CF JSR FollowerDraw_CachePosition @@ -838,6 +840,13 @@ FollowerDraw_CachePosition: LDA.w $1A3C, X : STA.b $03 LDA.w $1A64, X : STA.b $05 + ; Adjust the coordinate a bit to place it more in line where the + ; minecart should be relative to Link. + REP #$20 + LDA.b $00 : SEC : SBC.w #$0008 : STA.b $00 + LDA.b $02 : CLC : ADC.w #$0002 : STA.b $02 + SEP #$20 + ; ------------------------- AND.b #$20 LSR A @@ -853,7 +862,7 @@ FollowerDraw_CachePosition: ; variables based on the follower here and manipulate $72 ; if the player was immobile. - CLC : ADC $04 : STA $04 + CLC : ADC $04 : STA $04 TYA : CLC : ADC $04 : STA $04 ; ------------------------- @@ -929,6 +938,12 @@ CheckForFollowerInterroomTransition: { LDA.w !LinkInCart : BEQ .not_in_cart LDA.b #$0B : STA $7EF3CC + + ; Pause the current cart so that it doesn't draw anymore + PHX + LDX.w !MinecartCurrent + LDA.b #$01 : STA $0F00, X + PLX .not_in_cart JSL $01873A ; Underworld_LoadRoom RTL diff --git a/Sprites/Objects/minecart.asm b/Sprites/Objects/minecart.asm index 7e5be14..5a118ae 100644 --- a/Sprites/Objects/minecart.asm +++ b/Sprites/Objects/minecart.asm @@ -114,13 +114,23 @@ Right = $03 ; the cart. We can only use one cart at a time so this is only 1 byte. !MinecartTrackCache = $07E8 +; This is used to keep track of which direction we are going during room +; transitions. We can only use one cart at a time so this is only 1 byte. +!MinecartDirectionCache = $07E9 + +; This is used to keep track of which cart in a room we are riding. This +; is based of the X value used to index sprite arrays. +!MinecartCurrent = $07EA + ; ========================================================= Sprite_Minecart_Long: { PHB : PHK : PLB + JSR Sprite_Minecart_DrawTop ; Draw behind Link JSR Sprite_Minecart_DrawBottom ; Draw in front of Link + JSL Sprite_CheckActive : BCC .SpriteIsNotActive JSR Sprite_Minecart_Main .SpriteIsNotActive @@ -140,12 +150,15 @@ Sprite_Minecart_Prep: JSR UpdateCachedCoords LDA.w SprSubtype, X : ASL : TAY - - ; If Link is in a cart AND he is on the same track as this cart's - ; track, kill the cart. - CMP.w !MinecartTrackCache : BNE .notSameTrack + + ; If Link is on the same track as this cart's track AND this cart is + ; not the active cart, kill the cart. + LDA.w SprSubtype, X : CMP.w !MinecartTrackCache : BNE .notSameTrack LDA.b !LinkInCart : BEQ .notInCart - BRA .killMinecart + ; If the SprMiscB is > 4, then it's an active cart. This should only + ; be the case when transitioning from a follower. + LDA.w SprMiscB, X : CMP.b #$04 : BCS .active1 + BRA .killMinecart .notInCart .notSameTrack @@ -173,7 +186,8 @@ Sprite_Minecart_Prep: LDA.w !MinecartTrackY, Y : CMP.w SprCachedY : BNE .killMinecart SEP #$20 - STZ.w SprMiscF, X ; Clear the auto-move flag + .active1 + STZ.w SprMiscG, X ; Clear the active tossing flag LDA.b #$04 : STA.w SprNbrOAM, X ; Nbr Oam Entries @@ -189,10 +203,13 @@ Sprite_Minecart_Prep: ; If the SprMiscB is > 4, then it's an active cart. This should only ; be the case when transitioning from a follower. LDA.w SprMiscB, X : CMP.b #$04 : BCC .notActive - LDA.w SprMiscB, X : SEC : SBC.b #$04 : STA.w SprMiscB, X - LDA.b #$01 : STA.w SprMiscF, X ; Set the auto-move flag + SEC : SBC.b #$04 : STA.w SprMiscB, X - BRA .active + ; Go directly to the direction action we are facing. We add 2 to + ; skip the Minecart_WaitHoriz and Minecart_WaitVert actions. + CLC : ADC.b #$02 : STA.w SprAction, X + + BRA .active2 .notActive ; Setup Minecart position to look for tile IDs ; We use AND #$F8 to clamp to a 8x8 grid. @@ -214,17 +231,21 @@ Sprite_Minecart_Prep: CMP.b #$BA : BEQ .goWest .goNorth LDA.b #North : STA.w SprMiscB, X + %GotoAction(1) ; Minecart_WaitVert JMP .done2 .goEast LDA.b #East : STA.w SprMiscB, X + %GotoAction(0) ; Minecart_WaitHoriz JMP .done2 .goSouth LDA.b #South : STA.w SprMiscB, X + %GotoAction(1) ; Minecart_WaitVert JMP .done2 .goWest LDA.b #West : STA.w SprMiscB, X + %GotoAction(0) ; Minecart_WaitHoriz .done2 - .active + .active2 STZ.w SprTimerB, X @@ -244,8 +265,6 @@ Sprite_Minecart_Prep: %PlayAnimation(2,3,8) LDA.b #$02 : STA.w $0D90, X - %GotoAction(1) ; Minecart_WaitVert - BRA .done .east LDA.b #East : STA !MinecartDirection, X @@ -260,8 +279,6 @@ Sprite_Minecart_Prep: .horz %PlayAnimation(0,1,8) LDA.b #$00 : STA.w $0D90, X - - %GotoAction(0) ; Minecart_WaitHoriz .done PLB @@ -270,7 +287,7 @@ Sprite_Minecart_Prep: ; This is which room each track should start in if it hasn't already ; been given a track. .TrackStartingRooms - dw $0089, $0089, $0089, $0089, $0089, $0089, $0089, $0089 + dw $0089, $0089, $0089, $0088, $0089, $0089, $0089, $0089 dw $0089, $0089, $0089, $0089, $0089, $0089, $0089, $0089 dw $0089, $0089, $0089, $0089, $0089, $0089, $0089, $0089 dw $0089, $0089, $0089, $0089, $0089, $0089, $0089, $0089 @@ -279,13 +296,13 @@ Sprite_Minecart_Prep: ; already been given a position. This is necessary to allow for more ; than one stopping point to be in one room. .TrackStartingX - dw $1320, $12D0, $1300, $1300, $1300, $1300, $1300, $1300 + dw $1320, $12D0, $1300, $1100, $1300, $1300, $1300, $1300 dw $1300, $1300, $1300, $1300, $1300, $1300, $1300, $1300 dw $1300, $1300, $1300, $1300, $1300, $1300, $1300, $1300 dw $1300, $1300, $1300, $1300, $1300, $1300, $1300, $1300 .TrackStartingY - dw $11C0, $1120, $1100, $1100, $1100, $1100, $1100, $1100 + dw $11C0, $1120, $1100, $10D0, $1100, $1100, $1100, $1100 dw $1100, $1100, $1100, $1100, $1100, $1100, $1100, $1100 dw $1100, $1100, $1100, $1100, $1100, $1100, $1100, $1100 dw $1100, $1100, $1100, $1100, $1100, $1100, $1100, $1100 @@ -319,11 +336,8 @@ Sprite_Minecart_Main: LDA.w LinkCarryOrToss : AND #$03 : BNE .lifting LDA.w SprTimerA, X : BNE .not_ready JSR CheckIfPlayerIsOn : BCC .not_ready - ; If the cart is active, we move immediately - LDA.w SprMiscF, X : BNE .active_cart - ; Check for B button - LDA $F4 : AND.b #$80 : BEQ .not_ready - .active_cart + ; Check for B button + LDA $F4 : AND.b #$80 : BEQ .not_ready ; Save what track we are currently riding. LDA.w SprSubtype, X : STA.w !MinecartTrackCache @@ -359,11 +373,8 @@ Sprite_Minecart_Main: LDA.w LinkCarryOrToss : AND #$03 : BNE .lifting LDA.w SprTimerA, X : BNE .not_ready JSR CheckIfPlayerIsOn : BCC .not_ready - ; If the cart is active, we move immediately - LDA.w SprMiscF, X : BNE .active_cart - ; Check for B button - LDA $F4 : AND.b #$80 : BEQ .not_ready - .active_cart + ; Check for B button + LDA $F4 : AND.b #$80 : BEQ .not_ready ; Save what track we are currently riding. LDA.w SprSubtype, X : STA.w !MinecartTrackCache @@ -555,6 +566,8 @@ StopCart: LDA.w $A0 : STA.w !MinecartTrackRoom, Y SEP #$20 + STZ.w !MinecartCurrent + RTS } @@ -574,8 +587,11 @@ Minecart_SetDirectionNorth: STZ.w SprTimerB, X %PlayAnimation(2,3,8) - LDA.b #North : STA.w SprMiscB, X : STZ.w !MinecartDirection, X + LDA.b #North : STA.w SprMiscB, X + STA.w !MinecartDirection, X : STA.w !MinecartDirectionCache LDA.b #Up : STA !SpriteDirection, X + + TXA : STA.w !MinecartCurrent RTS } @@ -586,8 +602,11 @@ Minecart_SetDirectionEast: STZ.w SprTimerB, X %PlayAnimation(0,1,8) - LDA.b #East : STA.w SprMiscB, X : STA.w !MinecartDirection, X + LDA.b #East : STA.w SprMiscB, X + STA.w !MinecartDirection, X : STA.w !MinecartDirectionCache LDA.b #Right : STA !SpriteDirection, X + + TXA : STA.w !MinecartCurrent RTS } @@ -598,8 +617,11 @@ Minecart_SetDirectionSouth: STZ.w SprTimerB, X %PlayAnimation(2,3,8) - LDA.b #South : STA.w SprMiscB, X : STA.w !MinecartDirection, X + LDA.b #South : STA.w SprMiscB, X + STA.w !MinecartDirection, X : STA.w !MinecartDirectionCache LDA.b #Down : STA.w !SpriteDirection, X + + TXA : STA.w !MinecartCurrent RTS } @@ -610,8 +632,11 @@ Minecart_SetDirectionWest: STZ.w SprTimerB, X %PlayAnimation(0,1,8) - LDA.b #West : STA.w SprMiscB, X : STA.w !MinecartDirection, X + LDA.b #West : STA.w SprMiscB, X + STA.w !MinecartDirection, X : STA.w !MinecartDirectionCache LDA.b #Left : STA.w !SpriteDirection, X + + TXA : STA.w !MinecartCurrent RTS } @@ -785,6 +810,7 @@ CheckForCornerTiles: } } +; Unused? CheckForTrackTiles: { CMP.b #$B0 : BEQ .horiz From 717d9fb108da9267bc2349663abb5a7195aabb4a Mon Sep 17 00:00:00 2001 From: Jared_Brian_ Date: Mon, 3 Feb 2025 23:14:46 -0700 Subject: [PATCH 7/9] Fixed the switch track logic --- Sprites/Objects/minecart.asm | 652 ++++++++++++++++--------------- Sprites/Objects/mineswitch.asm | 15 +- Sprites/Objects/switch_track.asm | 34 +- 3 files changed, 362 insertions(+), 339 deletions(-) diff --git a/Sprites/Objects/minecart.asm b/Sprites/Objects/minecart.asm index 5a118ae..00153ad 100644 --- a/Sprites/Objects/minecart.asm +++ b/Sprites/Objects/minecart.asm @@ -86,7 +86,6 @@ Left = $02 Right = $03 !SpriteDirection = $0DE0 - ; A "track" is one minecart that can exist in multiple different places. ; Allowing the player to leave a minecart in one room and then still find ; it in the same place upon returning to that room. @@ -128,6 +127,8 @@ Sprite_Minecart_Long: { PHB : PHK : PLB + print "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: ", pc + JSR Sprite_Minecart_DrawTop ; Draw behind Link JSR Sprite_Minecart_DrawBottom ; Draw in front of Link @@ -424,7 +425,6 @@ Sprite_Minecart_Main: JSR HandlePlayerCameraAndMoveCart JSR HandleTileDirections - JSR HandleDynamicSwitchTileDirections RTS } @@ -452,7 +452,6 @@ Sprite_Minecart_Main: JSR HandlePlayerCameraAndMoveCart JSR HandleTileDirections - JSR HandleDynamicSwitchTileDirections RTS } @@ -480,7 +479,6 @@ Sprite_Minecart_Main: JSR HandlePlayerCameraAndMoveCart JSR HandleTileDirections - JSR HandleDynamicSwitchTileDirections RTS } @@ -508,7 +506,6 @@ Sprite_Minecart_Main: JSR HandlePlayerCameraAndMoveCart JSR HandleTileDirections - JSR HandleDynamicSwitchTileDirections RTS } @@ -641,7 +638,64 @@ Minecart_SetDirectionWest: } ; ========================================================= -; A = $0FA5 + +HandleTileDirections: +{ + ; If the cart got disconnected from the player, release them. + JSR CheckIfPlayerIsOn : BCS .player_on_cart + %GotoAction(6) ; Minecart_Release + RTS + .player_on_cart + + ; Setup Minecart position to look for tile IDs + ; We use AND #$F8 to clamp to a 8x8 grid. + LDA.w SprY, X : AND #$F8 : STA.b $00 + LDA.w SprYH, X : STA.b $01 + + LDA.w SprX, X : AND #$F8 : STA.b $02 + LDA.w SprXH, X : STA.b $03 + + ; Fetch tile attributes based on current coordinates + LDA.b #$00 : JSL Sprite_GetTileAttr + + ; Debug: put the tile type into the rupee SRM. + STA.l $7EF362 : STA.l $7EF360 + LDA.b #$00 : STA.l $7EF363 : STA.l $7EF361 + + JSR CheckForOutOfBounds : BCC .notOutOfBounds + JSR RoundCoords + + BRA .done + .notOutOfBounds + + JSR CheckForStopTiles : BCC .noStop + JSR RoundCoords + + BRA .done + .noStop + + JSR CheckForPlayerInput : BCC .noInput + JSR RoundCoords + + BRA .done + .noInput + + JSR CheckForCornerTiles : BCC .noCorner + JSR RoundCoords + + BRA .done + .noCorner + + JSR HandleDynamicSwitchTileDirections : BCC .noSwitch + JSR RoundCoords + + .noSwitch + + .done + RTS +} + +; ========================================================= CheckForOutOfBounds: { @@ -678,13 +732,13 @@ CheckForStopTiles: LDA.w SPRTILE : SEC : SBC.b #$B7 CLC : ADC.w $07 : TAY - LDA.w .DirectionTileLookup, Y : TAY + LDA.w .DirectionTileLookup, Y ; Check if the tile is a stop tile - CPY.b #$01 : BEQ .stop_north - CPY.b #$02 : BEQ .stop_east - CPY.b #$03 : BEQ .stop_south - CPY.b #$04 : BEQ .stop_west + CMP.b #$01 : BEQ .stop_north + CMP.b #$02 : BEQ .stop_east + CMP.b #$03 : BEQ .stop_south + CMP.b #$04 : BEQ .stop_west CLC RTS @@ -744,287 +798,8 @@ CheckForStopTiles: } } -CheckForCornerTiles: -{ - LDA.w SPRTILE - CMP.b #$B2 : BEQ .check_direction - CMP.b #$B3 : BEQ .check_direction - CMP.b #$B4 : BEQ .check_direction - CMP.b #$B5 : BEQ .check_direction - .exit - CLC - RTS - .check_direction - LDA.w SprMiscB, X - ASL #2 ; Multiply by 4 to offset rows in the lookup table - STA $07 ; Store the action index in $07 - - ; Subtract $B2 to normalize the tile type to 0 to 3 - LDA.w SPRTILE : SEC : SBC.b #$B2 - ; Add action index to tile type offset for the composite index - ; Transfer to Y to use as an offset for the rows - CLC : ADC.w $07 : TAY - LDA.w .DirectionTileLookup, Y : TAY - CPY #$01 : BEQ .move_north - CPY #$02 : BEQ .move_east - CPY #$03 : BEQ .move_south - CPY #$04 : BEQ .move_west - JMP .exit - - .move_north - JSR Minecart_SetDirectionNorth - %GotoAction(2) ; Minecart_MoveNorth - JMP .done - - .move_east - JSR Minecart_SetDirectionEast - %GotoAction(3) ; Minecart_MoveEast - JMP .done - - .move_south - JSR Minecart_SetDirectionSouth - %GotoAction(4) ; Minecart_MoveSouth - JMP .done - - .move_west - JSR Minecart_SetDirectionWest - %GotoAction(5) ; Minecart_MoveWest - - .done - SEC - RTS - - ; Direction to move on tile collision - ; 00 - stop or nothing - ; 01 - north - ; 02 - east - ; 03 - south - ; 04 - west - .DirectionTileLookup - { - ; TL, BL, TR, BR, Stop - db $02, $00, $04, $00 ; North - db $00, $00, $03, $01 ; East - db $00, $02, $00, $04 ; South - db $03, $01, $00, $00 ; West - } -} - -; Unused? -CheckForTrackTiles: -{ - CMP.b #$B0 : BEQ .horiz - CMP.b #$B1 : BEQ .vert - CMP.b #$BB : BEQ .horiz - CMP.b #$BC : BEQ .vert - JMP .done - - .horiz - ; Are we moving left or right? - LDA.w SprMiscB, X : CMP.b #$03 : BEQ .inverse_horiz_velocity - LDA.b #!MinecartSpeed : STA.w SprXSpeed, X - LDA.b #East : STA !MinecartDirection, X - JMP .done - .inverse_horiz_velocity - LDA.b #-!MinecartSpeed : STA.w SprXSpeed, X - LDA.b #West : STA !MinecartDirection, X - JMP .done - .vert - ; Are we moving up or down? - LDA.w SprMiscB, X : CMP.b #$00 : BEQ .inverse_vert_velocity - LDA.b #!MinecartSpeed : STA.w SprYSpeed, X - JMP .done - .inverse_vert_velocity - LDA.b #-!MinecartSpeed : STA.w SprYSpeed, X - .done - RTS -} - -HandleTileDirections: -{ - ;LDA.w SprTimerA, X : BEQ + - ; RTS - ;+ - - ; If the cart got disconnected from the player, release them. - JSR CheckIfPlayerIsOn : BCS .player_on_cart - %GotoAction(6) ; Minecart_Release - RTS - .player_on_cart - - ; Setup Minecart position to look for tile IDs - ; We use AND #$F8 to clamp to a 8x8 grid. - LDA.w SprY, X : AND #$F8 : STA.b $00 - LDA.w SprYH, X : STA.b $01 - - LDA.w SprX, X : AND #$F8 : STA.b $02 - LDA.w SprXH, X : STA.b $03 - - ; Fetch tile attributes based on current coordinates - LDA.b #$00 : JSL Sprite_GetTileAttr - - ; Debug: put the tile type into the rupee SRM. - STA.l $7EF362 : STA.l $7EF360 - LDA.b #$00 : STA.l $7EF363 : STA.l $7EF361 - - JSR CheckForOutOfBounds : BCC .notOutOfBounds - JSR RoundCoords - - BRA .done - - .notOutOfBounds - - JSR CheckForPlayerInput : BCC .noInput - JSR RoundCoords - - BRA .done - - .noInput - - JSR CheckForStopTiles : BCC .noStop - JSR RoundCoords - - BRA .done - .noStop - - JSR CheckForCornerTiles : BCC .noCorner - JSR RoundCoords - - .noCorner - - .done - RTS -} - -; NOTE TO SCAWFUL: This function could really go in a generic sprite -; functions file but I'll leave that up to you. -UpdateCachedCoords: -{ - LDA.w SprY, X : STA.w SprCachedY+0 - LDA.w SprX, X : STA.w SprCachedX+0 - LDA.w SprYH, X : STA.w SprCachedY+1 - LDA.w SprXH, X : STA.w SprCachedX+1 - - RTS -} - -; NOTE TO SCAWFUL: This function could really go in a generic sprite -; functions file but I'll leave that up to you. -RoundCoords: -{ - ; Clamp the Y coord to the nearest multiple of 8. - LDA.b $00 : CLC : ADC.b #$04 : AND.b #$F8 : STA.b $00 : STA.w SprY, X - - ; Clamp the X coord to the nearest multiple of 8. - LDA.b $02 : CLC : ADC.b #$04 : AND.b #$F8 : STA.b $02 : STA.w SprX, X - - JSR UpdateCachedCoords - - RTS -} - -pushpc - -org $0DFA68 - RebuildHUD_Keys: - -org $028260 - JSL ResetTrackVars - -pullpc - -ResetTrackVars: -{ - ; Replaced code. - JSL.l RebuildHUD_Keys - - LDA.b #$00 : STA.w !MinecartTrackCache - LDX.b #$41 - .loop - DEX - STA.w !MinecartTrackRoom, X - STA.w !MinecartTrackX, X - STA.w !MinecartTrackY, X - CPX.b #$00 : BNE .loop - - RTL -} - -; ========================================================= -; Check for the switch_track sprite and move based on the -; state of that sprite. - -HandleDynamicSwitchTileDirections: -{ - ; Find out if the sprite $B0 is in the room - JSR CheckSpritePresence : BCC .no_b0 - PHX - LDA $02 : TAX - JSL Link_SetupHitBox - JSL Sprite_SetupHitBox ; X is now the ID of the sprite $B0 - PLX - JSL CheckIfHitBoxesOverlap : BCC .no_b0 - LDA !MinecartDirection, X : CMP.b #$00 : BEQ .east_or_west - CMP.b #$01 : BEQ .north_or_south - CMP.b #$02 : BEQ .east_or_west - CMP.b #$03 : BEQ .north_or_south - .no_b0 - RTS - - .east_or_west - LDA.w SwitchRam : BNE .go_west - JSR Minecart_SetDirectionEast - %GotoAction(3) ; Minecart_MoveEast - RTS - .go_west - JSR Minecart_SetDirectionWest - %GotoAction(5) ; Minecart_MoveWest - RTS - - .north_or_south - LDA.w SwitchRam : BNE .go_south - JSR Minecart_SetDirectionNorth - %GotoAction(2) ; Minecart_MoveNorth - RTS - .go_south - JSR Minecart_SetDirectionSouth - %GotoAction(4) ; Minecart_MoveSouth - RTS -} - -; ========================================================= -; $00 = flag indicating presence of sprite ID $B0 - -CheckSpritePresence: -{ - PHX - CLC ; Assume sprite ID $B0 is not present - LDX.b #$10 - .x_loop - DEX - LDY.b #$04 - .y_loop - DEY - LDA $0E20, X : CMP.b #$B0 : BEQ .set_flag - BRA .not_b0 - - .set_flag - SEC ; Set flag indicating sprite ID $B0 is present - STX.w $02 - BRA .done - - .not_b0 - CPY.b #$00 : BNE .y_loop - CPX.b #$00 : BNE .x_loop - .done - PLX - RTS -} - -; ========================================================= ; Check for input from the user (u,d,l,r) on tile B6, BD ; CLC if not on an input tile or there was no input recieved. - CheckForPlayerInput: { ; Load the tile index @@ -1050,8 +825,8 @@ CheckForPlayerInput: LDA $F0 : AND.w .d_pad_press, Y : STA $05 : AND.b #$08 : BEQ .not_pressing_up .north JSR Minecart_SetDirectionNorth - %GotoAction(2) ; Minecart_MoveNorth + SEC RTS @@ -1059,8 +834,8 @@ CheckForPlayerInput: LDA.b $05 : AND.b #$04 : BEQ .not_pressing_down .south JSR Minecart_SetDirectionSouth - %GotoAction(4) ; Minecart_MoveSouth + SEC RTS @@ -1068,8 +843,8 @@ CheckForPlayerInput: LDA.b $05 : AND.b #$02 : BEQ .not_pressing_left .west JSR Minecart_SetDirectionWest - %GotoAction(5) ; Minecart_MoveWest + SEC RTS @@ -1077,8 +852,8 @@ CheckForPlayerInput: LDA.b $05 : AND.b #$01 : BEQ .return .east JSR Minecart_SetDirectionEast - %GotoAction(3) ; Minecart_MoveEast + SEC RTS .return @@ -1118,22 +893,248 @@ CheckForPlayerInput: .defaultDirection ; udlr ; up, down, left, right - db $04, $04, $04, $04 ; Nothing - db $04, $04, $04, $04 ; $B6 Intersection - db East, $04, $04, $04 ; $BB North T - db $04, East, $04, $04 ; $BC South T + db $04, $04, $04, $04 ; Nothing + db $04, $04, $04, $04 ; $B6 Intersection + db East, $04, $04, $04 ; $BB North T + db $04, East, $04, $04 ; $BC South T db $04, $04, $04, North ; $BD East T - db $04, $04, North, $04 ; $BE West T + db $04, $04, North, $04 ; $BE West T .intersectionMap ; B6, B7, B8, B9, BA, BB, BC, BD, BE db $04, $00, $00, $00, $00, $08, $0C, $10, $14 } +CheckForCornerTiles: +{ + LDA.w SPRTILE + CMP.b #$B2 : BEQ .check_direction ; TL + CMP.b #$B3 : BEQ .check_direction ; BL + CMP.b #$B4 : BEQ .check_direction ; TR + CMP.b #$B5 : BEQ .check_direction ; BR + CLC + RTS + .check_direction + LDA.w SprMiscB, X + ASL #2 ; Multiply by 4 to offset rows in the lookup table + STA $07 ; Store the action index in $07 + + ; Subtract $B2 to normalize the tile type to 0 to 3 + LDA.w SPRTILE : SEC : SBC.b #$B2 + ; Add action index to tile type offset for the composite index + ; Transfer to Y to use as an offset for the rows + CLC : ADC.b $07 : TAY + LDA.w .DirectionTileLookup, Y + CMP.b #$01 : BEQ .move_north + CMP.b #$02 : BEQ .move_east + CMP.b #$03 : BEQ .move_south + CMP.b #$04 : BEQ .move_west + CLC + RTS + + .move_north + JSR Minecart_SetDirectionNorth + %GotoAction(2) ; Minecart_MoveNorth + BRA .done + + .move_east + JSR Minecart_SetDirectionEast + %GotoAction(3) ; Minecart_MoveEast + BRA .done + + .move_south + JSR Minecart_SetDirectionSouth + %GotoAction(4) ; Minecart_MoveSouth + BRA .done + + .move_west + JSR Minecart_SetDirectionWest + %GotoAction(5) ; Minecart_MoveWest + + .done + SEC + RTS + + ; Direction to move on tile collision + ; 00 - stop or nothing + ; 01 - north + ; 02 - east + ; 03 - south + ; 04 - west + .DirectionTileLookup + { + ; TL, BL, TR, BR Coming from the: + db $02, $00, $04, $00 ; North + db $00, $00, $03, $01 ; East + db $00, $02, $00, $04 ; South + db $03, $01, $00, $00 ; West + } +} + +; Check for the switch_track sprite and move based on the +; state of that sprite. +HandleDynamicSwitchTileDirections: +{ + ; Check for the switch tile. + LDA.w SPRTILE : CMP.b #$BF : BEQ .onSwitchTile + CLC + RTS + .onSwitchTile + + ; Find out if the sprite $B0 is in the room. + JSR CheckSpritePresence : BCS .B0Present + CLC + RTS + .B0Present + + LDA.w SprMiscB, X + ASL #3 ; Multiply by 8 to offset rows in the lookup table + STA.b $07 ; Store the action index in $07 + + ; Get the type (TL, BL, TR, BL) of the track by taking the subtype and + ; cutting out the extra data. Then x2 so we get the correct data from + ; the table. + LDY.b $04 + LDA.w SprSubtype, Y : AND.b #$18 : LSR #2 + + ; Add the current direction and the state of the switch to determine + ; which direction we should go next. + CLC : ADC.b SwitchRam : CLC : ADC.b $07 : TAY + LDA.w .DirectionTileLookup, Y + CMP.b #$01 : BEQ .move_north + CMP.b #$02 : BEQ .move_east + CMP.b #$03 : BEQ .move_south + CMP.b #$04 : BEQ .move_west + CLC + RTS + + .move_north + JSR Minecart_SetDirectionNorth + %GotoAction(2) ; Minecart_MoveNorth + BRA .done + + .move_east + JSR Minecart_SetDirectionEast + %GotoAction(3) ; Minecart_MoveEast + BRA .done + + .move_south + JSR Minecart_SetDirectionSouth + %GotoAction(4) ; Minecart_MoveSouth + BRA .done + + .move_west + JSR Minecart_SetDirectionWest + %GotoAction(5) ; Minecart_MoveWest + + .done + SEC + RTS + + ; Direction to move on tile collision + ; 00 - stop or nothing + ; 01 - north + ; 02 - east + ; 03 - south + ; 04 - west + .DirectionTileLookup + { + ; Off, On, Off, On, Off, On, Off, On + ; TL, TL, BL, BL, TR, TR, BR, BR Coming from the: + db $02, $04, $00, $02, $04, $00, $00, $00 ; North + db $00, $03, $00, $00, $03, $01, $01, $00 ; East + db $00, $00, $02, $00, $00, $04, $04, $02 ; South + db $03, $00, $01, $03, $00, $00, $00, $01 ; West + } + + ; TL turns into TR when on. + ; TR turns into BR when on. + ; BR turns into BL when on. + ; BL turns into TL when on. +} + +; Unused? +CheckForTrackTiles: +{ + CMP.b #$B0 : BEQ .horiz + CMP.b #$B1 : BEQ .vert + CMP.b #$BB : BEQ .horiz + CMP.b #$BC : BEQ .vert + JMP .done + + .horiz + ; Are we moving left or right? + LDA.w SprMiscB, X : CMP.b #$03 : BEQ .inverse_horiz_velocity + LDA.b #!MinecartSpeed : STA.w SprXSpeed, X + LDA.b #East : STA !MinecartDirection, X + JMP .done + .inverse_horiz_velocity + LDA.b #-!MinecartSpeed : STA.w SprXSpeed, X + LDA.b #West : STA !MinecartDirection, X + JMP .done + .vert + ; Are we moving up or down? + LDA.w SprMiscB, X : CMP.b #$00 : BEQ .inverse_vert_velocity + LDA.b #!MinecartSpeed : STA.w SprYSpeed, X + JMP .done + .inverse_vert_velocity + LDA.b #-!MinecartSpeed : STA.w SprYSpeed, X + .done + RTS +} + ; ========================================================= + +; NOTE TO SCAWFUL: This function could really go in a generic sprite +; functions file but I'll leave that up to you. +UpdateCachedCoords: +{ + LDA.w SprY, X : STA.w SprCachedY+0 + LDA.w SprX, X : STA.w SprCachedX+0 + LDA.w SprYH, X : STA.w SprCachedY+1 + LDA.w SprXH, X : STA.w SprCachedX+1 + + RTS +} + +; NOTE TO SCAWFUL: This function could really go in a generic sprite +; functions file but I'll leave that up to you. +RoundCoords: +{ + ; Clamp the Y coord to the nearest multiple of 8. + LDA.b $00 : CLC : ADC.b #$04 : AND.b #$F8 : STA.b $00 : STA.w SprY, X + + ; Clamp the X coord to the nearest multiple of 8. + LDA.b $02 : CLC : ADC.b #$04 : AND.b #$F8 : STA.b $02 : STA.w SprX, X + + JSR UpdateCachedCoords + + RTS +} + +; $04 = sprite index of sprite ID $B0 +; SEC if sprite is present. +CheckSpritePresence: +{ + PHX + CLC ; Assume sprite ID $B0 is not present + LDX.b #$10 + .x_loop + DEX + LDA $0E20, X : CMP.b #$B0 : BNE .not_b0 + SEC ; Set flag indicating sprite ID $B0 is present + STX.w $04 + BRA .done + .not_b0 + CPX.b #$00 : BNE .x_loop + + .done + PLX + RTS +} + ; Sets carry if player is overlapping the sprite ; Clear carry if player is outside the bounds - CheckIfPlayerIsOn: { REP #$20 @@ -1152,6 +1153,35 @@ CheckIfPlayerIsOn: RTS ; Return with carry cleared } +; ========================================================= + +pushpc + +org $0DFA68 + RebuildHUD_Keys: + +org $028260 + JSL ResetTrackVars + +pullpc + +ResetTrackVars: +{ + ; Replaced code. + JSL.l RebuildHUD_Keys + + LDA.b #$00 : STA.w !MinecartTrackCache + LDX.b #$41 + .loop + DEX + STA.w !MinecartTrackRoom, X + STA.w !MinecartTrackX, X + STA.w !MinecartTrackY, X + CPX.b #$00 : BNE .loop + + RTL +} + ; ========================================================= ; Handle the tossing of the cart ; Changes the SprMiscB of the cart to indicate the direction @@ -1261,8 +1291,8 @@ Sprite_Minecart_DrawTop: BCC .on_screen_y LDA.b #$F0 : STA ($90), Y ;Put the sprite out of the way - STA $0E - .on_screen_y + STA $0E + .on_screen_y PLX ; Pullback Animation Index Offset (without the *2 not 16bit anymore) INY @@ -1274,11 +1304,11 @@ Sprite_Minecart_DrawTop: TYA : LSR #2 : TAY LDA .sizes, X : ORA $0F : STA ($92), Y ; store size in oam buffer PLY : INY - PLX : DEX : BPL .nextTile + PLX : DEX : BPL .nextTile - PLX + PLX - RTS + RTS .start_index db $00, $02, $04, $06 @@ -1323,7 +1353,6 @@ Sprite_Minecart_DrawBottom: LDA $0DC0, X : CLC : ADC $0D90, X : TAY;Animation Frame LDA .start_index, Y : STA $06 - PHX LDX .nbr_of_tiles, Y ;amount of tiles -1 LDY.b #$00 @@ -1347,8 +1376,8 @@ Sprite_Minecart_DrawBottom: BCC .on_screen_y LDA.b #$F0 : STA ($90), Y ;Put the sprite out of the way - STA $0E - .on_screen_y + STA $0E + .on_screen_y PLX ; Pullback Animation Index Offset (without the *2 not 16bit anymore) INY @@ -1360,11 +1389,11 @@ Sprite_Minecart_DrawBottom: TYA : LSR #2 : TAY LDA .sizes, X : ORA $0F : STA ($92), Y ; store size in oam buffer PLY : INY - PLX : DEX : BPL .nextTile + PLX : DEX : BPL .nextTile - PLX + PLX - RTS + RTS .start_index db $00, $02, $04, $06 @@ -1429,3 +1458,4 @@ pushpc pullpc +; ========================================================= diff --git a/Sprites/Objects/mineswitch.asm b/Sprites/Objects/mineswitch.asm index 173c4ee..a400e3e 100644 --- a/Sprites/Objects/mineswitch.asm +++ b/Sprites/Objects/mineswitch.asm @@ -52,7 +52,7 @@ Sprite_LeverSwitch_Prep: PHB : PHK : PLB LDA.b #$00 : STA.w SprDefl, X - LDA.w SprSubtype, X : STA.w SprAction, X + LDA.w SwitchRam : STA.w SprAction, X : STA.w SprFrame, X LDA.b #$00 : STA.w SprTileDie, X STZ.w SprBulletproof, X @@ -81,7 +81,8 @@ Sprite_LeverSwitch_Main: JSL Sprite_CheckDamageFromPlayer : BCC .NoDamage LDA #$25 : STA $012F - STZ.w $37 + ; Turn the switch on. + LDA #$01 : STA.b SwitchRam LDA #$10 : STA.w SprTimerA, X %GotoAction(1) .NoDamage @@ -94,7 +95,9 @@ Sprite_LeverSwitch_Main: LDA.w SprTimerA, X : BNE .NoDamage JSL Sprite_CheckDamageFromPlayer : BCC .NoDamage LDA #$25 : STA $012F - LDA #$01 : STA $37 + + ; Turn the switch off. + STZ.w SwitchRam LDA #$10 : STA.w SprTimerA, X %GotoAction(0) .NoDamage @@ -129,9 +132,9 @@ Sprite_LeverSwitch_Main: Sprite_LeverSwitch_Draw: { JSL Sprite_PrepOamCoord - JSL Sprite_OAM_AllocateDeferToPlayer + LDA.b #$04 : JSL Sprite_OAM_AllocateDeferToPlayer - LDA $0DC0, X : CLC : ADC $0D90, X : TAY;Animation Frame + LDA $0DC0, X : CLC : ADC $0D90, X : TAY ;Animation Frame LDA .start_index, Y : STA $06 @@ -194,8 +197,8 @@ Sprite_LeverSwitch_Draw: dw 0 dw 0 .chr - db $64 db $66 + db $64 .properties db $37 db $37 diff --git a/Sprites/Objects/switch_track.asm b/Sprites/Objects/switch_track.asm index 8c46a9d..8481b96 100644 --- a/Sprites/Objects/switch_track.asm +++ b/Sprites/Objects/switch_track.asm @@ -50,7 +50,11 @@ Sprite_RotatingTrack_Prep: { PHB : PHK : PLB LDA.b #$80 : STA.w SprDefl, X - LDA.w SprSubtype, X : STA.w SprAction,X + LDA.w SprSubtype, X : AND.b #$18 : LSR #3 + + ; Run the main frame once so that the animation frame is + ; started correctly. + JSR Sprite_RotatingTrack_Main PLB RTL } @@ -61,7 +65,6 @@ Sprite_RotatingTrack_Prep: ; 1 = TopRight -> BottomRight ; 2 = BottomRight -> BottomLeft ; 3 = BottomLeft -> TopLeft -; 4 = TopRight -> TopLeft SwitchRam = $37 @@ -74,7 +77,6 @@ Sprite_RotatingTrack_Main: dw TopRightToBottomRight dw BottomRightToBottomLeft dw BottomLeftToTopLeft - dw TopRightToTopLeft ; ------------------------------------------------------- ; 00 = TopLeft -> TopRight @@ -119,19 +121,6 @@ Sprite_RotatingTrack_Main: %PlayAnimation(0,0,4) RTS } - - ; ------------------------------------------------------- - ; 04 = TopRight -> TopLeft - TopRightToTopLeft: - { - LDA.w SwitchRam : BNE part2_d - %StartOnFrame(1) - %PlayAnimation(1,1,4) - part2_d: - %StartOnFrame(0) - %PlayAnimation(0,0,4) - RTS - } } ; ========================================================= @@ -139,7 +128,7 @@ Sprite_RotatingTrack_Main: Sprite_RotatingTrack_Draw: { JSL Sprite_PrepOamCoord - JSL Sprite_OAM_AllocateDeferToPlayer + LDA.b #$04 : JSL OAM_AllocateFromRegionB LDA $0DC0, X : CLC : ADC $0D90, X : TAY;Animation Frame LDA .start_index, Y : STA $06 @@ -191,7 +180,6 @@ Sprite_RotatingTrack_Draw: RTS - .start_index db $00, $01, $02, $03 .nbr_of_tiles @@ -202,8 +190,10 @@ Sprite_RotatingTrack_Draw: db $44 db $44 .properties - db $7D - db $3D - db $FD - db $BD + db $0D + db $4D + db $CD + db $8D } + +; ========================================================= From 7f3fbad7aed60e53a79e4637036d3d8241142dbb Mon Sep 17 00:00:00 2001 From: Jared_Brian_ Date: Sat, 8 Feb 2025 11:55:46 -0700 Subject: [PATCH 8/9] Changed the switch tracks to allow for more than just one switch --- Sprites/Objects/minecart.asm | 68 +++++++++++++--------- Sprites/Objects/mineswitch.asm | 16 +++++- Sprites/Objects/switch_track.asm | 99 +++++++++++++++++++------------- 3 files changed, 113 insertions(+), 70 deletions(-) diff --git a/Sprites/Objects/minecart.asm b/Sprites/Objects/minecart.asm index 00153ad..f3178d6 100644 --- a/Sprites/Objects/minecart.asm +++ b/Sprites/Objects/minecart.asm @@ -127,8 +127,6 @@ Sprite_Minecart_Long: { PHB : PHK : PLB - print "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: ", pc - JSR Sprite_Minecart_DrawTop ; Draw behind Link JSR Sprite_Minecart_DrawBottom ; Draw in front of Link @@ -976,30 +974,35 @@ CheckForCornerTiles: HandleDynamicSwitchTileDirections: { ; Check for the switch tile. - LDA.w SPRTILE : CMP.b #$BF : BEQ .onSwitchTile + LDA.w SPRTILE : CMP.b #$D0 : BEQ .onSwitchTile + CMP.b #$D1 : BEQ .onSwitchTile + CMP.b #$D2 : BEQ .onSwitchTile + CMP.b #$D3 : BEQ .onSwitchTile CLC RTS .onSwitchTile - ; Find out if the sprite $B0 is in the room. - JSR CheckSpritePresence : BCS .B0Present + ; Find out if the sprite $B0 is in the room and if we are + ; currently touching it. + JSR CheckTrackSpritePresence : BCS .B0Present CLC RTS .B0Present LDA.w SprMiscB, X - ASL #3 ; Multiply by 8 to offset rows in the lookup table + ASL #3 ; Multiply by 8 to offset rows in the lookup table STA.b $07 ; Store the action index in $07 - ; Get the type (TL, BL, TR, BL) of the track by taking the subtype and - ; cutting out the extra data. Then x2 so we get the correct data from - ; the table. - LDY.b $04 - LDA.w SprSubtype, Y : AND.b #$18 : LSR #2 + ; Get the subtype of the track so that we can get its on/off state. + LDA.w SprSubtype, Y : TAY + + ; Normalize the tile data and get the type of track (TL, BL, TR, BR) and + ; x2 so that we can read the correct column in the table. + LDA.w SPRTILE : SEC : SBC.b #$D0 : ASL ; Add the current direction and the state of the switch to determine ; which direction we should go next. - CLC : ADC.b SwitchRam : CLC : ADC.b $07 : TAY + CLC : ADC.w SwitchRam, Y : CLC : ADC.b $07 : TAY LDA.w .DirectionTileLookup, Y CMP.b #$01 : BEQ .move_north CMP.b #$02 : BEQ .move_east @@ -1047,10 +1050,11 @@ HandleDynamicSwitchTileDirections: db $03, $00, $01, $03, $00, $00, $00, $01 ; West } - ; TL turns into TR when on. - ; TR turns into BR when on. - ; BR turns into BL when on. - ; BL turns into TL when on. + ; $D0 TL turns into TR when on. + ; $D1 BL turns into TL when on. + ; $D2 TR turns into BR when on. + ; $D3 BR turns into BL when on. + } ; Unused? @@ -1114,22 +1118,30 @@ RoundCoords: ; $04 = sprite index of sprite ID $B0 ; SEC if sprite is present. -CheckSpritePresence: +CheckTrackSpritePresence: { - PHX - CLC ; Assume sprite ID $B0 is not present - LDX.b #$10 - .x_loop - DEX - LDA $0E20, X : CMP.b #$B0 : BNE .not_b0 - SEC ; Set flag indicating sprite ID $B0 is present - STX.w $04 - BRA .done + LDY.b #$10 + .loop + DEY + ; Check if the sprite is $B0 + LDA.w $0E20, Y : CMP.b #$B0 : BNE .not_b0 + ; Check if the high bytes of the coordinates match. + LDA.w SprYH, X : CMP.w SprYH, Y : BNE .not_b0 + LDA.w SprXH, X : CMP.w SprXH, Y : BNE .not_b0 + ; Check if the low bytes match but round the cart's coordinates. + ; Offset the Y by 8 so that we match the cart + LDA.w SprY, X : CLC : ADC.b #$04 : AND.b #$F8 : CLC : ADC.b #$08 + CMP.w SprY, Y : BNE .not_b0 + LDA.w SprX, X : CLC : ADC.b #$04 : AND.b #$F8 + CMP.w SprX, Y : BNE .not_b0 + STY.b $04 + SEC ; Set flag indicating sprite ID $B0 is present. + BRA .done .not_b0 - CPX.b #$00 : BNE .x_loop + CPY.b #$00 : BNE .loop + CLC ; Assume sprite ID $B0 is not present .done - PLX RTS } diff --git a/Sprites/Objects/mineswitch.asm b/Sprites/Objects/mineswitch.asm index a400e3e..8187c89 100644 --- a/Sprites/Objects/mineswitch.asm +++ b/Sprites/Objects/mineswitch.asm @@ -52,7 +52,11 @@ Sprite_LeverSwitch_Prep: PHB : PHK : PLB LDA.b #$00 : STA.w SprDefl, X - LDA.w SwitchRam : STA.w SprAction, X : STA.w SprFrame, X + + ; Get the subtype of the switch so that we can get its on/off state. + LDA.w SprSubtype, X : TAY + + LDA.w SwitchRam, Y : STA.w SprAction, X : STA.w SprFrame, X LDA.b #$00 : STA.w SprTileDie, X STZ.w SprBulletproof, X @@ -81,8 +85,11 @@ Sprite_LeverSwitch_Main: JSL Sprite_CheckDamageFromPlayer : BCC .NoDamage LDA #$25 : STA $012F + ; Get the subtype of the switch so that we can get its on/off state. + LDA.w SprSubtype, X : TAY + ; Turn the switch on. - LDA #$01 : STA.b SwitchRam + LDA #$01 : STA.w SwitchRam, Y LDA #$10 : STA.w SprTimerA, X %GotoAction(1) .NoDamage @@ -95,9 +102,12 @@ Sprite_LeverSwitch_Main: LDA.w SprTimerA, X : BNE .NoDamage JSL Sprite_CheckDamageFromPlayer : BCC .NoDamage LDA #$25 : STA $012F + + ; Get the subtype of the switch so that we can get its on/off state. + LDA.w SprSubtype, X : TAY ; Turn the switch off. - STZ.w SwitchRam + LDA #$00 : STA.w SwitchRam, Y LDA #$10 : STA.w SprTimerA, X %GotoAction(0) .NoDamage diff --git a/Sprites/Objects/switch_track.asm b/Sprites/Objects/switch_track.asm index 8481b96..29bfd0e 100644 --- a/Sprites/Objects/switch_track.asm +++ b/Sprites/Objects/switch_track.asm @@ -50,7 +50,20 @@ Sprite_RotatingTrack_Prep: { PHB : PHK : PLB LDA.b #$80 : STA.w SprDefl, X - LDA.w SprSubtype, X : AND.b #$18 : LSR #3 + + ; Setup Minecart position to look for tile IDs + ; We use AND #$F8 to clamp to a 8x8 grid. + ; Subtract 8 from the Y position to get the tile right above instead. + LDA.w SprY, X : AND #$F8 : SEC : SBC.b #$08 : STA.b $00 + LDA.w SprYH, X : STA.b $01 + + LDA.w SprX, X : AND #$F8 : STA.b $02 + LDA.w SprXH, X : STA.b $03 + + ; Fetch tile attributes based on current coordinates + LDA.b #$00 : JSL Sprite_GetTileAttr + + LDA.w SPRTILE : SEC : SBC.b #$D0 : STA.w SprAction, X ; Run the main frame once so that the animation frame is ; started correctly. @@ -66,59 +79,67 @@ Sprite_RotatingTrack_Prep: ; 2 = BottomRight -> BottomLeft ; 3 = BottomLeft -> TopLeft -SwitchRam = $37 +; The state of each switch. Up to $0250 used which is all free ram. +SwitchRam = $0230 Sprite_RotatingTrack_Main: { + ; Get the subtype of the track so that we can get its on/off state. + LDA.w SprSubtype, X : TAY + LDA.w SprAction, X JSL UseImplicitRegIndexedLocalJumpTable dw TopLeftToTopRight + dw BottomLeftToTopLeft dw TopRightToBottomRight dw BottomRightToBottomLeft - dw BottomLeftToTopLeft - + ; ------------------------------------------------------- ; 00 = TopLeft -> TopRight TopLeftToTopRight: { - LDA.w SwitchRam : BNE part2 - %PlayAnimation(0,0,4) - part2: - %PlayAnimation(1,1,4) + LDA.w SwitchRam, Y : BNE .part2 + LDA.b #$00 : STA.w SprFrame, X + RTS + .part2 + LDA.b #$01 : STA.w SprFrame, X RTS } ; ------------------------------------------------------- - ; 01 = TopRight -> BottomRight - TopRightToBottomRight: - { - LDA.w SwitchRam : BNE part2_a - %PlayAnimation(1,1,4) - part2_a: - %PlayAnimation(2,2,4) - RTS - } - - ; ------------------------------------------------------- - ; 02 = BottomRight -> BottomLeft - BottomRightToBottomLeft: - { - LDA.w SwitchRam : BEQ part2_b - %PlayAnimation(2,2,4) - part2_b: - %PlayAnimation(3,3,4) - RTS - } - - ; ------------------------------------------------------- - ; 03 = BottomLeft -> TopLeft + ; 01 = BottomLeft -> TopLeft BottomLeftToTopLeft: { - LDA.w SwitchRam : BNE part2_c - %PlayAnimation(3,3,4) - part2_c: - %PlayAnimation(0,0,4) + LDA.w SwitchRam, Y : BNE .part2_c + LDA.b #$03 : STA.w SprFrame, X + RTS + .part2_c + LDA.b #$00 : STA.w SprFrame, X + RTS + } + + ; ------------------------------------------------------- + ; 02 = TopRight -> BottomRight + TopRightToBottomRight: + { + LDA.w SwitchRam, Y : BNE .part2_a + LDA.b #$01 : STA.w SprFrame, X + RTS + .part2_a + LDA.b #$02 : STA.w SprFrame, X + RTS + } + + ; ------------------------------------------------------- + ; 03 = BottomRight -> BottomLeft + BottomRightToBottomLeft: + { + LDA.w SwitchRam, Y : BEQ .part2_b + LDA.b #$03 : STA.w SprFrame, X + RTS + .part2_b + LDA.b #$02 : STA.w SprFrame, X RTS } } @@ -190,10 +211,10 @@ Sprite_RotatingTrack_Draw: db $44 db $44 .properties - db $0D - db $4D - db $CD - db $8D + db $3D + db $7D + db $FD + db $BD } ; ========================================================= From 3b12b9f5968acb3bf2185cb2c8f72ad0484e9489 Mon Sep 17 00:00:00 2001 From: Jared_Brian_ Date: Sat, 8 Feb 2025 12:08:15 -0700 Subject: [PATCH 9/9] added collision legend --- Sprites/Objects/minecart.asm | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/Sprites/Objects/minecart.asm b/Sprites/Objects/minecart.asm index f3178d6..56b3ee1 100644 --- a/Sprites/Objects/minecart.asm +++ b/Sprites/Objects/minecart.asm @@ -121,6 +121,34 @@ Right = $03 ; is based of the X value used to index sprite arrays. !MinecartCurrent = $07EA +; ========================================================= +; Collision setup: + +; 0xB0 - Horizontal straight +; 0xB1 - Vertical straight +; 0xB2 - Top left corner +; 0xB3 - Bottom left corner +; 0xB4 - Top right corner +; 0xB5 - Bottom right corner +; 0xB6 - 4 way intersection +; 0xB7 - Stop north +; 0xB8 - Stop south +; 0xB9 - Stop west +; 0xBA - Stop east +; 0xBB - North T intersection +; 0xBC - South T intersection +; 0xBD - East T intersection +; 0xBE - West T intersection +; 0xD0 - Top left switch +; 0xD1 - Bottom left switch +; 0xD2 - Top right switch +; 0xD3 - Bottom right switch + +; TL switch turns into TR when on +; BL switch turns into TL when on +; TR switch turns into BR when on +; BR switch turns into BL when on + ; ========================================================= Sprite_Minecart_Long: @@ -1054,7 +1082,6 @@ HandleDynamicSwitchTileDirections: ; $D1 BL turns into TL when on. ; $D2 TR turns into BR when on. ; $D3 BR turns into BL when on. - } ; Unused?