diff --git a/Sprites/minecart.asm b/Sprites/Objects/minecart.asm similarity index 50% rename from Sprites/minecart.asm rename to Sprites/Objects/minecart.asm index a90421c..d153610 100644 --- a/Sprites/minecart.asm +++ b/Sprites/Objects/minecart.asm @@ -1,34 +1,34 @@ ; ========================================================= -; Sprite Properties +; Minecart Sprite Properties ; ========================================================= -!SPRID = $A3 ; The sprite ID you are overwriting (HEX) -!NbrTiles = 08 ; Number of tiles used in a frame -!Harmless = 01 ; 00 = Sprite is Harmful, 01 = Sprite is Harmless -!HVelocity = 00 ; Is your sprite going super fast? put 01 if it is -!Health = 00 ; Number of Health the sprite have -!Damage = 00 ; (08 is a whole heart), 04 is half heart -!DeathAnimation = 00 ; 00 = normal death, 01 = no death animation -!ImperviousAll = 01 ; 00 = Can be attack, 01 = attack will clink on it -!SmallShadow = 00 ; 01 = small shadow, 00 = no shadow -!Shadow = 00 ; 00 = don't draw shadow, 01 = draw a shadow -!Palette = 00 ; Unused in this template (can be 0 to 7) -!Hitbox = 00 ; 00 to 31, can be viewed in sprite draw tool -!Persist = 01 ; 01 = your sprite continue to live offscreen -!Statis = 00 ; 00 = is sprite is alive?, (kill all enemies room) -!CollisionLayer = 00 ; 01 = will check both layer for collision -!CanFall = 00 ; 01 sprite can fall in hole, 01 = can't fall -!DeflectArrow = 00 ; 01 = deflect arrows -!WaterSprite = 00 ; 01 = can only walk shallow water -!Blockable = 00 ; 01 = can be blocked by link's shield? -!Prize = 00 ; 00-15 = the prize pack the sprite will drop from -!Sound = 00 ; 01 = Play different sound when taking damage -!Interaction = 00 ; ?? No documentation -!Statue = 00 ; 01 = Sprite is statue -!DeflectProjectiles = 00 ; 01 = Sprite will deflect ALL projectiles -!ImperviousArrow = 00 ; 01 = Impervious to arrows -!ImpervSwordHammer = 00 ; 01 = Impervious to sword and hammer attacks -!Boss = 00 ; 00 = normal sprite, 01 = sprite is a boss +!SPRID = $A3 ; The sprite ID you are overwriting (HEX) +!NbrTiles = 08 ; Number of tiles used in a frame +!Harmless = 01 ; 00 = Sprite is Harmful, 01 = Sprite is Harmless +!HVelocity = 00 ; Is your sprite going super fast? put 01 if it is +!Health = 00 ; Number of Health the sprite have +!Damage = 00 ; (08 is a whole heart), 04 is half heart +!DeathAnimation = 00 ; 00 = normal death, 01 = no death animation +!ImperviousAll = 01 ; 00 = Can be attack, 01 = attack will clink on it +!SmallShadow = 00 ; 01 = small shadow, 00 = no shadow +!Shadow = 00 ; 00 = don't draw shadow, 01 = draw a shadow +!Palette = 00 ; Unused in this template (can be 0 to 7) +!Hitbox = 00 ; 00 to 31, can be viewed in sprite draw tool +!Persist = 01 ; 01 = your sprite continue to live offscreen +!Statis = 00 ; 00 = is sprite is alive?, (kill all enemies room) +!CollisionLayer = 00 ; 01 = will check both layer for collision +!CanFall = 00 ; 01 sprite can fall in hole, 01 = can't fall +!DeflectArrow = 00 ; 01 = deflect arrows +!WaterSprite = 00 ; 01 = can only walk shallow water +!Blockable = 00 ; 01 = can be blocked by link's shield? +!Prize = 00 ; 00-15 = the prize pack the sprite will drop from +!Sound = 00 ; 01 = Play different sound when taking damage +!Interaction = 00 ; ?? No documentation +!Statue = 00 ; 01 = Sprite is statue +!DeflectProjectiles = 00 ; 01 = Sprite will deflect ALL projectiles +!ImperviousArrow = 00 ; 01 = Impervious to arrows +!ImpervSwordHammer = 00 ; 01 = Impervious to sword and hammer attacks +!Boss = 00 ; 00 = normal sprite, 01 = sprite is a boss ; ========================================================= @@ -38,6 +38,31 @@ ; Link is in cart !LinkInCart = $35 +!MinecartSpeed = 20 +!DoubleSpeed = 30 + +; nesw +; 0 - north +; 1 - east +; 2 - south +; 3 - west +!MinecartDirection = $012B + +; $0DE0[0x10] - (Sprite) ;functions +; udlr +; 0 - up +; 1 - down +; 2 - left +; 3 - right +!SpriteDirection = $0DE0 + +; Bitfield for carry-related actions. +; .... ..tl +; t - tossing object +; l - lifting object +!LinkCarryOrToss = $0309 + +; ========================================================= Sprite_Minecart_Long: { @@ -57,50 +82,25 @@ Sprite_Minecart_Long: ; ========================================================= -!MinecartSpeed = 20 -!DoubleSpeed = 30 - -; nesw -; 0 - north -; 1 - east -; 2 - south -; 3 - west -!MinecartDirection = $012B - -; $0DE0[0x10] - (Sprite) ;functions -; udlr -; 0 - up -; 1 - down -; 2 - left -; 3 - right -!SpriteDirection = $0DE0 - -; Bitfield for carry-related actions. -; .... ..tl -; t - tossing object -; l - lifting object -!LinkCarryOrToss = $0309 - Sprite_Minecart_Prep: { - PHB : PHK : PLB - - ; If the subtype is > 4, then it's a dummy cart - LDA SprSubtype, X : CMP.b #$04 : BCC .continue - LDA SprSubtype, X : SEC : SBC.b #$04 : STA SprSubtype, X - ; If link is in a cart, then draw the dummy cart + PHB : PHK : PLB + + ; If the subtype is > 4, then it's a dummy cart + LDA SprSubtype, X : CMP.b #$04 : BCC .continue + LDA SprSubtype, X : SEC : SBC.b #$04 : STA SprSubtype, X + ; If link is in a cart, then draw the dummy cart - LDA !LinkInCart : BNE .dummy_continue - .clear_cart - STZ.w $0DD0, X ; Otherwise, clear the sprite - PLB - RTL + LDA !LinkInCart : BNE .dummy_continue + ; .clear_cart + STZ.w $0DD0, X ; Otherwise, clear the sprite + PLB + RTL .continue - + ; Unused dummy cart code ; LDA.w !LinkInCart : AND.b #$FF : BEQ .dummy_continue ; JMP .clear_cart - .dummy_continue LDA SprY, X : SEC : SBC.b #$04 : STA SprY, X @@ -132,7 +132,6 @@ Sprite_Minecart_Prep: JMP .done .south LDA #$02 : STA !MinecartDirection - ; LDA SprX, X : CLC : ADC.b #$01 : STA SprX, X %GotoAction(1) ; Minecart_WaitVert JMP .done .west @@ -140,7 +139,6 @@ Sprite_Minecart_Prep: %GotoAction(0) ; Minecart_WaitHoriz .done - PLB RTL } @@ -172,14 +170,21 @@ macro MoveCart() LDA #$35 : STA $012E ; Cart SFX endmacro +macro StopCart() + STZ $02F5 + STZ.w SprYSpeed, X + STZ.w SprXSpeed, X + STZ.w !LinkInCart +endmacro + +; TODO: Implement distance and gravity for cart tossing macro HandleLiftAndToss() LDA.w !LinkCarryOrToss : AND #$02 : BNE .not_tossing - ; Velocities for cart tossing - STZ.w SprXSpeed, X : STZ.w SprYSpeed, X - STZ.w $0F90, X : STZ.w $0F70, X + ; Velocities for cart tossing + STZ.w SprXSpeed, X : STZ.w SprYSpeed, X + STZ.w $0F90, X : STZ.w $0F70, X .not_tossing JSL Sprite_CheckIfLifted - JSL Sprite_MoveXyz endmacro @@ -202,36 +207,33 @@ Sprite_Minecart_Main: ; 0x00 Minecart_WaitHoriz: { - %PlayAnimation(0,1,8) - LDA SprTimerA, X : BNE .not_ready + %PlayAnimation(0,1,8) + LDA SprTimerA, X : BNE .not_ready - LDA !LinkCarryOrToss : AND #$03 : BNE .lifting - JSR CheckIfPlayerIsOn : BCC .not_ready + LDA !LinkCarryOrToss : AND #$03 : BNE .lifting + JSR CheckIfPlayerIsOn : BCC .not_ready + LDA $F4 : AND.b #$80 : BEQ .not_ready ; Check for B button - JSL Player_HaltDashAttack ; Stop the player from dashing - LDA #$02 : STA $02F5 ; Somaria platform and moving - LDA $0FDA : SEC : SBC #$0B : STA $20 ; Adjust player pos + JSL Player_HaltDashAttack ; Stop the player from dashing + LDA #$02 : STA $02F5 ; Somaria platform and moving + LDA $0FDA : SEC : SBC #$0B : STA $20 ; Adjust player pos + LDA #$01 : STA !LinkInCart ; Set Link in cart flag - LDA #$01 : STA !LinkInCart + ; Check if the cart is facing east or west + LDA SprSubtype, X : CMP.b #$03 : BNE .opposite_direction + STA.w !MinecartDirection + LDA #$02 : STA !SpriteDirection, X + %GotoAction(5) ; Minecart_MoveWest + RTS - ; Check if the cart is facing east or west - LDA SprSubtype,X : CMP.b #$03 : BNE .opposite_direction - STA.w !MinecartDirection - LDA #$02 : STA $0DE0, X - %GotoAction(5) ; Minecart_MoveWest - RTS + .opposite_direction + STA.w !MinecartDirection + LDA #$03 : STA !SpriteDirection, X + %GotoAction(3) ; Minecart_MoveEast - .opposite_direction - STA.w !MinecartDirection - LDA #$03 : STA $0DE0, X - %GotoAction(3) ; Minecart_MoveEast - - .not_ready - RTS - + .not_ready .lifting %HandleLiftAndToss() - RTS } @@ -239,34 +241,33 @@ Sprite_Minecart_Main: ; 0x01 Minecart_WaitVert: { - %PlayAnimation(2,3,8) - LDA SprTimerA, X : BNE .not_ready + %PlayAnimation(2,3,8) + LDA SprTimerA, X : BNE .not_ready - LDA !LinkCarryOrToss : AND #$03 : BNE .lifting - JSR CheckIfPlayerIsOn : BCC .not_ready + LDA !LinkCarryOrToss : AND #$03 : BNE .lifting + JSR CheckIfPlayerIsOn : BCC .not_ready + LDA $F4 : AND.b #$80 : BEQ .not_ready ; Check for B button - JSL Player_HaltDashAttack ; Stop the player from dashing - LDA #$02 : STA $02F5 ; Somaria platform and moving - LDA $0FDA : SEC : SBC #$0B : STA $20 ; Adjust player pos + JSL Player_HaltDashAttack ; Stop the player from dashing + LDA #$02 : STA $02F5 ; Somaria platform and moving + LDA $0FDA : SEC : SBC #$0B : STA $20 ; Adjust player pos + LDA #$01 : STA !LinkInCart ; Set Link in cart flag + + ; Check if the cart is facing north or south + LDA SprSubtype, X : BEQ .opposite_direction + STA.w !MinecartDirection + LDA #$01 : STA !SpriteDirection, X + %GotoAction(4) ; Minecart_MoveSouth + RTS + + .opposite_direction + STA.w !MinecartDirection + LDA #$00 : STA !SpriteDirection, X + %GotoAction(2) ; Minecart_MoveNorth - LDA #$01 : STA !LinkInCart - - ; Check if the cart is facing north or south - LDA SprSubtype, X : BEQ .opposite_direction - STA.w !MinecartDirection - LDA #$01 : STA $0DE0, X - %GotoAction(4) ; Minecart_MoveSouth - RTS - - .opposite_direction - STA.w !MinecartDirection - LDA #$00 : STA $0DE0, X - %GotoAction(2) ; Minecart_MoveNorth - - .not_ready + .not_ready .lifting %HandleLiftAndToss() - RTS } @@ -274,123 +275,128 @@ Sprite_Minecart_Main: ; 0x02 Minecart_MoveNorth: { - %PlayAnimation(2,3,8) - %InitMovement() + %PlayAnimation(2,3,8) + %InitMovement() - LDA $36 : BNE .fast_speed - LDA.b #-!MinecartSpeed : STA SprYSpeed, X - JMP .continue + LDA $36 : BNE .fast_speed + LDA.b #-!MinecartSpeed : STA SprYSpeed, X + JMP .continue .fast_speed LDA.b #-!DoubleSpeed : STA SprYSpeed, X .continue - JSL Sprite_MoveVert - JSL Sprite_BounceFromTileCollision + JSL Sprite_MoveVert + JSL Sprite_BounceFromTileCollision - JSR DragPlayer - JSR CheckForPlayerInput - %HandlePlayerCamera() - %MoveCart() + JSR DragPlayer + JSR CheckForPlayerInput + %HandlePlayerCamera() + %MoveCart() - RTS + RTS } ; ------------------------------------------------------- ; 0x03 Minecart_MoveEast: { - %PlayAnimation(0,1,8) - %InitMovement() - LDA $36 : BNE .fast_speed - LDA.b #!MinecartSpeed : STA $0D50, X - JMP .continue + %PlayAnimation(0,1,8) + %InitMovement() + LDA $36 : BNE .fast_speed + LDA.b #!MinecartSpeed : STA $0D50, X + JMP .continue .fast_speed - LDA.b #!DoubleSpeed : STA $0D50, X + LDA.b #!DoubleSpeed : STA $0D50, X .continue - JSL Sprite_MoveHoriz - JSL Sprite_BounceFromTileCollision - - JSR DragPlayer - JSR CheckForPlayerInput - %HandlePlayerCamera() - %MoveCart() + JSL Sprite_MoveHoriz + JSL Sprite_BounceFromTileCollision + + JSR DragPlayer + JSR CheckForPlayerInput + %HandlePlayerCamera() + %MoveCart() - RTS + RTS } ; ------------------------------------------------------- ; 0x04 Minecart_MoveSouth: { - %PlayAnimation(2,3,8) - %InitMovement() - LDA $36 : BNE .fast_speed - LDA.b #!MinecartSpeed : STA SprYSpeed, X - JMP .continue + %PlayAnimation(2,3,8) + %InitMovement() + LDA $36 : BNE .fast_speed + LDA.b #!MinecartSpeed : STA SprYSpeed, X + JMP .continue .fast_speed - LDA.b #!DoubleSpeed : STA SprYSpeed, X + LDA.b #!DoubleSpeed : STA SprYSpeed, X .continue - JSL Sprite_MoveVert - JSL Sprite_BounceFromTileCollision + JSL Sprite_MoveVert + JSL Sprite_BounceFromTileCollision - JSR DragPlayer - JSR CheckForPlayerInput - %HandlePlayerCamera() - %MoveCart() - - RTS + JSR DragPlayer + JSR CheckForPlayerInput + %HandlePlayerCamera() + %MoveCart() + + RTS } ; ------------------------------------------------------- ; 0x05 Minecart_MoveWest: { - %PlayAnimation(0,1,8) - %InitMovement() - LDA $36 : BNE .fast_speed - LDA.b #-!MinecartSpeed : STA $0D50, X - JMP .continue + %PlayAnimation(0,1,8) + %InitMovement() + LDA $36 : BNE .fast_speed + LDA.b #-!MinecartSpeed : STA $0D50, X + JMP .continue .fast_speed - LDA.b #-!DoubleSpeed : STA $0D50, X + LDA.b #-!DoubleSpeed : STA $0D50, X .continue - JSL Sprite_MoveHoriz - JSL Sprite_BounceFromTileCollision - - JSR DragPlayer - JSR CheckForPlayerInput - %HandlePlayerCamera() - %MoveCart() + JSL Sprite_MoveHoriz + JSL Sprite_BounceFromTileCollision + + JSR DragPlayer + JSR CheckForPlayerInput + %HandlePlayerCamera() + %MoveCart() - RTS + RTS } - macro StopCart() - STZ $02F5 - STZ.w SprYSpeed, X - STZ.w SprXSpeed, X - STZ.w !LinkInCart - endmacro ; ------------------------------------------------------- ; 0x06 Minecart_Release: { - %StopCart() + %StopCart() - LDA SprTimerD, X : BNE .not_ready - LDA #$40 : STA SprTimerA, X - %GotoAction(0) + LDA SprTimerD, X : BNE .not_ready + LDA #$40 : STA SprTimerA, X + %GotoAction(0) .not_ready RTS } } -; =========================================================================== +; ========================================================= +; The purpose of this routine is to determine the direction +; the sprite is facing and then adjust the X and Y positions +; of the tile interaction lookup based on that direction. +; If implemented correctly this would make sure the sprite +; stays centered on the tracks when it makes corner turns. +; Currently, depending on where the tile is placed the +; cart may make a turn too early and appear to be off center. + +North = $00 +East = $01 +South = $02 +West = $03 SetTileLookupPosBasedOnDirection: { - ; Based on the direction of the Minecart, adjust the lookup position - ; to be in front of the sprite - + ; Based on the direction of the Minecart, adjust the + ; lookup position to be in front of the sprite LDA.w !MinecartDirection : CMP.b #$00 : BEQ .north CMP.b #$01 : BEQ .east CMP.b #$02 : BEQ .south @@ -399,15 +405,15 @@ SetTileLookupPosBasedOnDirection: .north LDA.w SprY, X : SEC : SBC.b #$01 : STA.b $00 LDA.w SprX, X : STA.b $02 - JMP .return + JMP .return .east LDA.w SprX, X : CLC : ADC.b #$01 : STA.b $03 LDA.w SprY, X : STA.b $00 - JMP .return + JMP .return .south LDA.w SprY, X : SEC : SBC.b #$01 : STA.b $00 LDA.w SprX, X : STA.b $02 - JMP .return + JMP .return .west LDA.w SprX, X : AND #$F8 : SEC : SBC.b #$01 : STA.b $03 LDA.w SprY, X : STA.b $00 @@ -416,14 +422,16 @@ SetTileLookupPosBasedOnDirection: LDA.w SprYH, X : STA.b $01 LDA.w SprXH, X : STA.b $03 - LDA.w SprX, X : STA $0FD8 + LDA.w SprX, X : STA $0FD8 LDA.w SprXH, X : STA $0FD9 - LDA.w SprY, X : STA $0FDA + LDA.w SprY, X : STA $0FDA LDA.w SprYH, X : STA $0FDB - RTS + RTS } +; ========================================================= + print "HandleTileDirections ", pc HandleTileDirections: { @@ -438,66 +446,66 @@ HandleTileDirections: ; Load the tile index LDA $0FA5 : CLC : CMP.b #$01 : BNE .not_out_of_bounds - - ; If the tile is out of bounds, release the cart - LDA #$40 : STA SprTimerD, X - %GotoAction(6) ; Minecart_Release - RTS + ; If the tile is out of bounds, release the cart + LDA #$40 : STA SprTimerD, X + %GotoAction(6) ; Minecart_Release + RTS .not_out_of_bounds - ; Check if the tile is a stop tile CLC : CMP.b #$B7 : BCS .check_stop ; If tile ID is >= $B8, check for stop tiles - - .check_stop - CLC : CMP.b #$B7 : BEQ .stop_north - CLC : CMP.b #$B8 : BEQ .stop_south - CLC : CMP.b #$B9 : BEQ .stop_west - CLC : CMP.b #$BA : BEQ .stop_east - JMP .check_for_movement ; if none of the above, continue with normal logic + + .check_stop + CLC : CMP.b #$B7 : BEQ .stop_north + CLC : CMP.b #$B8 : BEQ .stop_south + CLC : CMP.b #$B9 : BEQ .stop_west + CLC : CMP.b #$BA : BEQ .stop_east + JMP .check_for_movement ; if none of the above, continue with normal logic - .stop_north - ; Set the new direction to north and flip the cart's orientation - LDA.b #South : STA SprSubtype, X : STA.w !MinecartDirection - LDA #$01 : STA $0DE0, X - JMP .go_vert - - .stop_south - ; Set the new direction to south and flip the cart's orientation - LDA.b #North : STA SprSubtype, X : STZ.w !MinecartDirection - LDA #$00 : STA $0DE0, X + .stop_north + ; Set the new direction to north and flip the cart's orientation + LDA.b #South : STA SprSubtype, X : STA.w !MinecartDirection + LDA #$01 : STA !SpriteDirection, X + JMP .go_vert - .go_vert - %SetTimerA($40) - %StopCart() - %GotoAction(1) ; Minecart_WaitVert - JSL Player_ResetState - RTS - - .stop_east - ; Set the new direction to east and flip the cart's orientation - LDA.b #West : STA SprSubtype, X : STA.w !MinecartDirection - LDA #$03 : STA $0DE0, X - JMP .go_horiz - - .stop_west - ; Set the new direction to west and flip the cart's orientation - LDA.b #East : STA SprSubtype, X : STA.w !MinecartDirection - LDA #$02 : STA $0DE0, X - .go_horiz - %SetTimerA($40) - %StopCart() - %GotoAction(0) ; Minecart_WaitHoriz - JSL Player_ResetState - RTS + .stop_south + ; Set the new direction to south and flip the cart's orientation + LDA.b #North : STA SprSubtype, X : STZ.w !MinecartDirection + LDA #$00 : STA !SpriteDirection, X + + ; ----------------------------------------------- + .go_vert + %SetTimerA($40) + %StopCart() + %GotoAction(1) ; Minecart_WaitVert + JSL Player_ResetState + RTS + + .stop_east + ; Set the new direction to east and flip the cart's orientation + LDA.b #West : STA SprSubtype, X : STA.w !MinecartDirection + LDA #$03 : STA !SpriteDirection, X + JMP .go_horiz + + .stop_west + ; Set the new direction to west and flip the cart's orientation + LDA.b #East : STA SprSubtype, X : STA.w !MinecartDirection + LDA #$02 : STA !SpriteDirection, X + + ; ----------------------------------------------- + .go_horiz + %SetTimerA($40) + %StopCart() + %GotoAction(0) ; Minecart_WaitHoriz + JSL Player_ResetState + RTS ; ------------------------------------------------------- .check_for_movement - ; Check for movement tiles CLC : CMP.b #$B2 : BEQ .check_direction CLC : CMP.b #$B3 : BEQ .check_direction CLC : CMP.b #$B4 : BEQ .check_direction CLC : CMP.b #$B5 : BEQ .check_direction - JMP .done + JMP .done ; Create a composite index based on current direction and tile type LDA SprSubtype, X ; Load the current direction subtype (0 to 3) @@ -508,161 +516,151 @@ HandleTileDirections: LDA $0FA5 : SEC : SBC.b #$B3 ; Add the row and column offsets to index into the lookup table CLC : ADC.w .DirectionTileLookup, Y : TAY - - ; Direction to move on tile collision - ; 00 - stop or nothing - ; 01 - north - ; 02 - east - ; 03 - south - ; 04 - west - - North = $00 - East = $01 - South = $02 - West = $03 - - .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 - } .check_direction LDA SprSubtype, X - BNE .not_zero - - .not_zero ASL #2 ; Multiply by 4 (shifting left by 2 bits) to offset rows in the lookup table STA $07 ; Store the action index in $07 LDA $0FA5 ; Load the tile type SEC : SBC.b #$B2 ; Subtract $B2 to normalize the tile type to 0 to 3 CLC : ADC.w $07 ; Add the action index to the tile type offset to get the composite index - TAY - - LDA.w .DirectionTileLookup, Y - TAY + TAY ; Transfer to Y to use as an offset for the rows + LDA.w .DirectionTileLookup, Y : TAY - .execute_action ; JSR ClampSpritePositionToGrid CPY #$01 : BEQ .move_north CPY #$02 : BEQ .move_east CPY #$03 : BEQ .move_south CPY #$04 : BEQ .move_west - JMP .done + JMP .done - .move_north - LDA #$00 : STA SprSubtype, X - STA $0DE0, X - %GotoAction(2) ; Minecart_MoveNorth - RTS - .move_east - LDA #$01 : STA SprSubtype, X - LDA #$03 : STA $0DE0, X - %GotoAction(3) ; Minecart_MoveEast - RTS - .move_south - LDA #$02 : STA SprSubtype, X - LDA #$01 : STA $0DE0, X - %GotoAction(4) ; Minecart_MoveSouth - RTS - .move_west - LDA #$03 : STA SprSubtype, X - LDA #$02 : STA $0DE0, X - %GotoAction(5) ; Minecart_MoveWest - .done - RTS + .move_north + LDA #$00 : STA SprSubtype, X + STA !SpriteDirection, X + %GotoAction(2) ; Minecart_MoveNorth + RTS + .move_east + LDA #$01 : STA SprSubtype, X + LDA #$03 : STA !SpriteDirection, X + %GotoAction(3) ; Minecart_MoveEast + RTS + .move_south + LDA #$02 : STA SprSubtype, X + LDA #$01 : STA !SpriteDirection, X + %GotoAction(4) ; Minecart_MoveSouth + RTS + .move_west + LDA #$03 : STA SprSubtype, X + LDA #$02 : STA !SpriteDirection, X + %GotoAction(5) ; Minecart_MoveWest + .done + RTS -.tile_ids - ; db $B0 ; - Horiz - ; db $B1 ; | Vert - ; TL, BL, TR, BR - db $B2, $B3, $B4, $B5 - ; db $B8 Stop North - ; db $B9 Stop South - ; db $BA Stop East - ; db $BB Stop West - - ; db $BE ; + any direction + ; 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_tile_ids + { + ; TL, BL, TR, BR + db $B2, $B3, $B4, $B5 + ; db $B0 - Horiz + ; db $B1 | Vert + ; db $B8 Stop North + ; db $B9 Stop South + ; db $BA Stop East + ; db $BB Stop West + ; db $BE + any direction + } } +; ========================================================= ; Clamp the sprite position to a 16x16 grid ; Slows the game down if you run it too often :( + ClampSpritePositionToGrid: { ; Check if SprX is already a multiple of 16 LDA.w SprX, X : AND #$0F : BEQ .x_aligned - LDA.w SprX, X : LSR : ASL : STA.w SprX, X + LDA.w SprX, X : LSR : ASL : STA.w SprX, X .x_aligned - ; Check if SprY is already a multiple of 16 LDA.w SprY, X : AND #$0F : BEQ .y_aligned - LDA.w SprY, X : LSR : ASL : STA.w SprY, X - .y_aligned + LDA.w SprY, X : LSR : ASL : STA.w SprY, X + .y_aligned RTS } +; ========================================================= +; 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 - JSR Link_SetupHitBox + PHX : LDA $02 : TAX + JSR Link_SetupHitBox - ; X is now the ID of the sprite $B0 - JSR Sprite_SetupHitBox - PLX - - JSL CheckIfHitBoxesOverlap : BCC .no_b0 + ; X is now the ID of the sprite $B0 + JSR Sprite_SetupHitBox + PLX + + JSL CheckIfHitBoxesOverlap : BCC .no_b0 - LDA !MinecartDirection : CMP.b #$00 : BEQ .east_or_west - CMP.b #$02 : BEQ .north_or_south + LDA !MinecartDirection : CMP.b #$00 : BEQ .east_or_west + CMP.b #$02 : BEQ .north_or_south - .east_or_west - - LDA SwitchRam : BNE .go_west + .east_or_west + LDA SwitchRam : BNE .go_west + LDA #$01 : STA SprSubtype, X + LDA #$03 : STA !SpriteDirection, X + %GotoAction(3) ; Minecart_MoveEast + RTS - LDA #$01 : STA SprSubtype, X - LDA #$03 : STA $0DE0, X - %GotoAction(3) ; Minecart_MoveEast - RTS + .go_west + LDA #$03 : STA SprSubtype, X + LDA #$02 : STA !SpriteDirection, X + %GotoAction(5) ; Minecart_MoveWest + RTS - .go_west - LDA #$03 : STA SprSubtype, X - LDA #$02 : STA $0DE0, X - %GotoAction(5) ; Minecart_MoveWest - RTS + .north_or_south + LDA SwitchRam : BNE .go_south + LDA #$00 : STA SprSubtype, X + STA !SpriteDirection, X + %GotoAction(2) ; Minecart_MoveNorth + RTS - .north_or_south - LDA SwitchRam : BNE .go_south - LDA #$00 : STA SprSubtype, X - STA $0DE0, X - %GotoAction(2) ; Minecart_MoveNorth - RTS - - .go_south - LDA #$02 : STA SprSubtype, X - LDA #$01 : STA $0DE0, X - %GotoAction(4) ; Minecart_MoveSouth - RTS + .go_south + LDA #$02 : STA SprSubtype, X + LDA #$01 : STA !SpriteDirection, X + %GotoAction(4) ; Minecart_MoveSouth + RTS .no_b0 - RTS } +; ========================================================= ; $00 = flag indicating presence of sprite ID $B0 + CheckSpritePresence: { PHX - CLC ; Assume sprite ID $B0 is not present - + CLC ; Assume sprite ID $B0 is not present LDX.b #$10 - .x_loop DEX @@ -694,7 +692,7 @@ DragYH = $0B7D DragPlayer: { ; Get direction of the cart (0 to 3) - LDY.w $0DE0, X + LDY.w !SpriteDirection, X LDA.w .drag_x_low, Y : CLC : ADC.w DragYL : STA.w DragYL LDA.w .drag_x_high, Y : ADC.w DragYH : STA DragYH @@ -747,6 +745,7 @@ DragPlayer: .drag_y_high db -1, 0, 0, 0 + ; Alternate drag values provided by Zarby ; .drag_x_high ; db 0, 0, -1, 0, -1 ; .drag_x_low @@ -757,110 +756,99 @@ DragPlayer: ; db -1, 0, 0, 0, -1, 0, -1, 0 } +; ========================================================= CheckForPlayerInput: { - LDA $5D : CMP #$02 : BEQ .release - CMP #$06 : BNE .continue -.release - ; Release player in recoil - %GotoAction(6) ; Minecart_Release - RTS + LDA $5D : CMP #$02 : BEQ .release + CMP #$06 : BNE .continue + .release + ; Release player in recoil + %GotoAction(6) ; Minecart_Release + RTS -.continue + .continue - ; 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 + ; 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 : BNE .cant_input - - ; Check for input from the user (u,d,l,r) + ; Fetch tile attributes based on current coordinates + LDA.b #$00 : JSL Sprite_GetTileAttr - LDY $0DE0, X - - LDA $F0 : AND .d_pad_press, Y : STA $00 : AND.b #$08 : BEQ .not_pressing_up - - LDA.b #$00 : STA $0DE0, X ; Moving Up - STA SprSubtype, X - %GotoAction(2) ; Minecart_MoveNorth - - BRA .return + ; Load the tile index + LDA $0FA5 : CLC : CMP.b #$B6 : BNE .cant_input -.not_pressing_up: + ; Check for input from the user (u,d,l,r) + LDY !SpriteDirection, X + LDA $F0 : AND .d_pad_press, Y : STA $00 : AND.b #$08 : BEQ .not_pressing_up + LDA.b #$00 : STA !SpriteDirection, X ; Moving Up + STA SprSubtype, X + %GotoAction(2) ; Minecart_MoveNorth + BRA .return - LDA $00 : AND.b #$04 : BEQ .not_pressing_down - - LDA.b #$01 : STA $0DE0, X - LDA #$02 : STA SprSubtype, X - %GotoAction(4) ; Minecart_MoveSouth + .not_pressing_up: + LDA $00 : AND.b #$04 : BEQ .not_pressing_down + LDA.b #$01 : STA !SpriteDirection, X + LDA #$02 : STA SprSubtype, X + %GotoAction(4) ; Minecart_MoveSouth + BRA .return - - BRA .return + .not_pressing_down + LDA $00 : AND.b #$02 : BEQ .not_pressing_left + LDA.b #$02 : STA !SpriteDirection, X + LDA #$03 : STA SprSubtype, X + %GotoAction(5) ; Minecart_MoveWest + BRA .return -.not_pressing_down + .not_pressing_left + LDA $00 : AND.b #$01 : BEQ .always + LDA.b #$03 : STA !SpriteDirection, X + STA SprSubtype, X + %GotoAction(3) ; Minecart_MoveEast - LDA $00 : AND.b #$02 : BEQ .not_pressing_left - - LDA.b #$02 : STA $0DE0, X - LDA #$03 : STA SprSubtype, X - %GotoAction(5) ; Minecart_MoveWest + .always - - BRA .return + ; LDA !SpriteDirection, X : CMP.b #$03 : BNE .not_going_right + ; ; Default heading in reaction to this tile is going up. + ; ; LDA.b #$00 : STA !SpriteDirection, X + ; .not_going_right + ; ;STZ $0D80, X -.not_pressing_left + .return + + .cant_input + RTS - LDA $00 : AND.b #$01 : BEQ .always - - LDA.b #$03 : STA $0DE0, X - STA SprSubtype, X - %GotoAction(3) ; Minecart_MoveEast - -.always - -; LDA $0DE0, X : CMP.b #$03 : BNE .not_going_right - -; ; Default heading in reaction to this tile is going up. -; ; LDA.b #$00 : STA $0DE0, X - -; .not_going_right - -; ;STZ $0D80, X - -.return - -.cant_input - RTS - -.d_pad_press - db $0B, $07, $0E, $0D + .d_pad_press + db $0B, $07, $0E, $0D } +; ========================================================= +; Sets carry if player is overlapping the sprite +; Clear carry if player is outside the bounds + CheckIfPlayerIsOn: { REP #$20 - LDA $22 : CLC : ADC #$0009 : CMP $0FD8 : BCC .OutsideLeft - LDA $22 : SEC : SBC #$0009 : CMP $0FD8 : BCS .OutsideRight + LDA $22 : CLC : ADC #$0009 : CMP $0FD8 : BCC .left + LDA $22 : SEC : SBC #$0009 : CMP $0FD8 : BCS .right - LDA $20 : CLC : ADC #$0012 : CMP $0FDA : BCC .OutsideUp - LDA $20 : SEC : SBC #$0012 : CMP $0FDA : BCS .OutsideDown + LDA $20 : CLC : ADC #$0012 : CMP $0FDA : BCC .up + LDA $20 : SEC : SBC #$0012 : CMP $0FDA : BCS .down SEP #$21 : RTS ; Return with carry set - .OutsideLeft - .OutsideRight - .OutsideDown - .OutsideUp + .left + .right + .up + .down SEP #$20 CLC : RTS ; Return with carry cleared } ; ========================================================= +; Draw the portion of the cart which is behind the player Sprite_Minecart_DrawTop: { @@ -950,6 +938,8 @@ Sprite_Minecart_DrawTop: db $02, $02 } +; ========================================================= +; Draw the portion of the cart which is in front of the player Sprite_Minecart_DrawBottom: { @@ -1006,6 +996,9 @@ Sprite_Minecart_DrawBottom: PLX + ; Debug box which draws in the location of the hitbox from + ; the code in HandleTileDirections / SetTileLookupPosBasedOnDirection + ; The latter of which is an experimental function ; { ; LDA $0FD8 : STA $00 ; LDA $0FDA : STA $02 diff --git a/Sprites/Objects/mineswitch.asm b/Sprites/Objects/mineswitch.asm index b09ebca..4b20c89 100644 --- a/Sprites/Objects/mineswitch.asm +++ b/Sprites/Objects/mineswitch.asm @@ -1,3 +1,6 @@ +; ========================================================= +; Sprite Properties +; ========================================================= !SPRID = $AF ; The sprite ID you are overwriting (HEX) !NbrTiles = 02 ; Number of tiles used in a frame @@ -29,6 +32,7 @@ %Set_Sprite_Properties(Sprite_LeverSwitch_Prep, Sprite_LeverSwitch_Long); +; ========================================================= Sprite_LeverSwitch_Long: { @@ -45,6 +49,7 @@ Sprite_LeverSwitch_Long: RTL ; Go back to original code } +; ========================================================= Sprite_LeverSwitch_Prep: { @@ -57,6 +62,7 @@ Sprite_LeverSwitch_Prep: RTL } +; ========================================================= Sprite_LeverSwitch_Main: { @@ -140,82 +146,82 @@ Sprite_LeverSwitch_Main: } } +; ========================================================= Sprite_LeverSwitch_Draw: { - JSL Sprite_PrepOamCoord - JSL Sprite_OAM_AllocateDeferToPlayer + JSL Sprite_PrepOamCoord + JSL Sprite_OAM_AllocateDeferToPlayer - LDA $0DC0, X : CLC : ADC $0D90, X : TAY;Animation Frame - LDA .start_index, Y : STA $06 + 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 + PHX + LDX .nbr_of_tiles, Y ;amount of tiles -1 + LDY.b #$00 .nextTile - PHX ; Save current Tile Index? - - TXA : CLC : ADC $06 ; Add Animation Index Offset + PHX ; Save current Tile Index? + + TXA : CLC : ADC $06 ; Add Animation Index Offset - PHA ; Keep the value with animation index offset? + PHA ; Keep the value with animation index offset? - ASL A : TAX + ASL A : TAX - REP #$20 + REP #$20 - LDA $00 : CLC : ADC .x_offsets, X : STA ($90), Y - AND.w #$0100 : STA $0E - INY - LDA $02 : CLC : ADC .y_offsets, X : STA ($90), Y - CLC : ADC #$0010 : CMP.w #$0100 - SEP #$20 - BCC .on_screen_y + LDA $00 : CLC : ADC .x_offsets, X : STA ($90), Y + AND.w #$0100 : STA $0E + INY + LDA $02 : CLC : ADC .y_offsets, X : STA ($90), Y + CLC : ADC #$0010 : CMP.w #$0100 + SEP #$20 + BCC .on_screen_y - LDA.b #$F0 : STA ($90), Y ;Put the sprite out of the way - STA $0E + LDA.b #$F0 : STA ($90), Y ;Put the sprite out of the way + STA $0E .on_screen_y - PLX ; Pullback Animation Index Offset (without the *2 not 16bit anymore) - INY - LDA .chr, X : STA ($90), Y - INY - LDA .properties, X : STA ($90), Y + PLX ; Pullback Animation Index Offset (without the *2 not 16bit anymore) + INY + LDA .chr, X : STA ($90), Y + INY + LDA .properties, X : STA ($90), Y - PHY - - TYA : LSR #2 : TAY - - LDA .sizes, X : ORA $0F : STA ($92), Y ; store size in oam buffer - - PLY : INY - - PLX : DEX : BPL .nextTile + PHY + + TYA : LSR #2 : TAY + + LDA .sizes, X : ORA $0F : STA ($92), Y ; store size in oam buffer + + PLY : INY + + PLX : DEX : BPL .nextTile - PLX + PLX - RTS + RTS .start_index - db $00, $01 + db $00, $01 .nbr_of_tiles - db 0, 0 + db 0, 0 .x_offsets - dw 0 - dw 0 + dw 0 + dw 0 .y_offsets - dw 0 - dw 0 + dw 0 + dw 0 .chr - db $64 - db $66 + db $64 + db $66 .properties - db $37 - db $37 + db $37 + db $37 .sizes - db $02 - db $02 - + db $02 + db $02 } \ No newline at end of file diff --git a/Sprites/Objects/switch_track.asm b/Sprites/Objects/switch_track.asm index 18ba6a6..20dfd14 100644 --- a/Sprites/Objects/switch_track.asm +++ b/Sprites/Objects/switch_track.asm @@ -1,3 +1,7 @@ +; ========================================================= +; Sprite Properties +; ========================================================= + !SPRID = $B0 ; The sprite ID you are overwriting (HEX) !NbrTiles = 04 ; Number of tiles used in a frame !Harmless = 00 ; 00 = Sprite is Harmful, 01 = Sprite is Harmless @@ -28,6 +32,8 @@ %Set_Sprite_Properties(Sprite_RotatingTrack_Prep, Sprite_RotatingTrack_Long); +; ========================================================= + Sprite_RotatingTrack_Long: { PHB : PHK : PLB @@ -43,12 +49,7 @@ Sprite_RotatingTrack_Long: RTL ; Go back to original code } -; Modes -; 0 = TopLeft -> TopRight -; 1 = TopRight -> BottomRight -; 2 = BottomRight -> BottomLeft -; 3 = BottomLeft -> TopLeft -; 4 = TopRight -> TopLeft +; ========================================================= Sprite_RotatingTrack_Prep: { @@ -61,18 +62,29 @@ Sprite_RotatingTrack_Prep: RTL } +; ========================================================= +; Modes +; 0 = TopLeft -> TopRight +; 1 = TopRight -> BottomRight +; 2 = BottomRight -> BottomLeft +; 3 = BottomLeft -> TopLeft +; 4 = TopRight -> TopLeft + SwitchRam = $37 Sprite_RotatingTrack_Main: { LDA.w SprAction, X JSL UseImplicitRegIndexedLocalJumpTable + dw TopLeftToTopRight dw TopRightToBottomRight dw BottomRightToBottomLeft dw BottomLeftToTopLeft dw TopRightToTopLeft + ; ------------------------------------------------------- + ; 00 = TopLeft -> TopRight TopLeftToTopRight: { LDA SwitchRam : BNE part2 @@ -87,6 +99,8 @@ Sprite_RotatingTrack_Main: RTS } + ; ------------------------------------------------------- + ; 01 = TopRight -> BottomRight TopRightToBottomRight: { LDA SwitchRam : BNE part2_a @@ -101,6 +115,8 @@ Sprite_RotatingTrack_Main: RTS } + ; ------------------------------------------------------- + ; 02 = BottomRight -> BottomLeft BottomRightToBottomLeft: { LDA SwitchRam : BNE part2_b @@ -115,6 +131,8 @@ Sprite_RotatingTrack_Main: RTS } + ; ------------------------------------------------------- + ; 03 = BottomLeft -> TopLeft BottomLeftToTopLeft: { LDA SwitchRam : BNE part2_c @@ -130,6 +148,8 @@ Sprite_RotatingTrack_Main: RTS } + ; ------------------------------------------------------- + ; 04 = TopRight -> TopLeft TopRightToTopLeft: { LDA SwitchRam : BNE part2_d @@ -147,88 +167,92 @@ Sprite_RotatingTrack_Main: } } +; ========================================================= + Sprite_RotatingTrack_Draw: -JSL Sprite_PrepOamCoord -JSL Sprite_OAM_AllocateDeferToPlayer +{ + JSL Sprite_PrepOamCoord + JSL Sprite_OAM_AllocateDeferToPlayer -LDA $0DC0, X : CLC : ADC $0D90, X : TAY;Animation Frame -LDA .start_index, Y : STA $06 + 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 -.nextTile + PHX + LDX .nbr_of_tiles, Y ;amount of tiles -1 + LDY.b #$00 + .nextTile -PHX ; Save current Tile Index? - -TXA : CLC : ADC $06 ; Add Animation Index Offset + PHX ; Save current Tile Index? + + TXA : CLC : ADC $06 ; Add Animation Index Offset -PHA ; Keep the value with animation index offset? + PHA ; Keep the value with animation index offset? -ASL A : TAX + ASL A : TAX -REP #$20 + REP #$20 -LDA $00 : CLC : ADC .x_offsets, X : STA ($90), Y -AND.w #$0100 : STA $0E -INY -LDA $02 : CLC : ADC .y_offsets, X : STA ($90), Y -CLC : ADC #$0010 : CMP.w #$0100 -SEP #$20 -BCC .on_screen_y + LDA $00 : CLC : ADC .x_offsets, X : STA ($90), Y + AND.w #$0100 : STA $0E + INY + LDA $02 : CLC : ADC .y_offsets, X : STA ($90), Y + CLC : ADC #$0010 : CMP.w #$0100 + SEP #$20 + BCC .on_screen_y -LDA.b #$F0 : STA ($90), Y ;Put the sprite out of the way -STA $0E -.on_screen_y + LDA.b #$F0 : STA ($90), Y ;Put the sprite out of the way + STA $0E + .on_screen_y -PLX ; Pullback Animation Index Offset (without the *2 not 16bit anymore) -INY -LDA .chr, X : STA ($90), Y -INY -LDA .properties, X : STA ($90), Y + PLX ; Pullback Animation Index Offset (without the *2 not 16bit anymore) + INY + LDA .chr, X : STA ($90), Y + INY + LDA .properties, X : STA ($90), Y -PHY - -TYA : LSR #2 : TAY - -LDA .sizes, X : ORA $0F : STA ($92), Y ; store size in oam buffer - -PLY : INY - -PLX : DEX : BPL .nextTile + PHY + + TYA : LSR #2 : TAY + + LDA .sizes, X : ORA $0F : STA ($92), Y ; store size in oam buffer + + PLY : INY + + PLX : DEX : BPL .nextTile -PLX + PLX -RTS + RTS -.start_index -db $00, $01, $02, $03 -.nbr_of_tiles -db 0, 0, 0, 0 -.x_offsets -dw 0 -dw 0 -dw 0 -dw 0 -.y_offsets -dw 0 -dw 0 -dw 0 -dw 0 -.chr -db $44 -db $44 -db $44 -db $44 -.properties -db $7D -db $3D -db $FD -db $BD -.sizes -db $02 -db $02 -db $02 -db $02 \ No newline at end of file + .start_index + db $00, $01, $02, $03 + .nbr_of_tiles + db 0, 0, 0, 0 + .x_offsets + dw 0 + dw 0 + dw 0 + dw 0 + .y_offsets + dw 0 + dw 0 + dw 0 + dw 0 + .chr + db $44 + db $44 + db $44 + db $44 + .properties + db $7D + db $3D + db $FD + db $BD + .sizes + db $02 + db $02 + db $02 + db $02 +} \ No newline at end of file diff --git a/Sprites/all_sprites.asm b/Sprites/all_sprites.asm index d540453..d7ef86b 100644 --- a/Sprites/all_sprites.asm +++ b/Sprites/all_sprites.asm @@ -69,7 +69,7 @@ print "End of mineswitch.asm ", pc incsrc "Sprites/NPCs/village_dog.asm" print "End of village_dog.asm ", pc -incsrc "Sprites/minecart.asm" +incsrc "Sprites/Objects/minecart.asm" print "End of minecart.asm ", pc incsrc "Sprites/Bosses/twinrova.asm"