From 89a12702d0846e75c76d0d78535673770b5aacdb Mon Sep 17 00:00:00 2001 From: "Matthew D. Steele" Date: Mon, 10 Jun 2024 18:07:07 -0400 Subject: [PATCH] Implement reverse gravity for ShadowDrill room --- src/avatar.asm | 89 ++++++++++++++++++++++++++++++++---- src/death.asm | 5 +- src/explore.asm | 15 ++++-- src/platform.asm | 82 +++++++++++++++++---------------- src/push.asm | 13 ++++-- src/rooms/shadow_descent.asm | 43 ++++++++++++++++- src/rooms/shadow_drill.asm | 78 +++++++++++++++++++++++++++---- src/rooms/shadow_drill.bg | 22 ++++----- src/rooms/shadow_hall.asm | 36 ++++++++++++++- src/rooms/shadow_trap.asm | 36 ++++++++++++++- src/tiles/shadow3.ahi | 60 ++++++++++++------------ src/tilesets/shadow.bg | 4 +- 12 files changed, 371 insertions(+), 112 deletions(-) diff --git a/src/avatar.asm b/src/avatar.asm index da66b249..7529734d 100644 --- a/src/avatar.asm +++ b/src/avatar.asm @@ -96,8 +96,9 @@ Zp_AvatarVelX_i16: .res 2 .EXPORTZP Zp_AvatarVelY_i16 Zp_AvatarVelY_i16: .res 2 -;;; The object flags to apply for the player avatar. In particular, if -;;; bObj::FlipH is set, then the avatar will face left instead of right. +;;; The object flags to apply for the player avatar. If bObj::FlipH is set, +;;; then the avatar will face left instead of right. If bObj::FlipV is set, +;;; the avatar is acting under reverse gravity. .EXPORTZP Zp_AvatarFlags_bObj Zp_AvatarFlags_bObj: .res 1 @@ -228,6 +229,13 @@ _SetAvatarPose: _SetPoseInAir: ;; The player avatar is airborne; set its pose based on its Y-velocity. lda Zp_AvatarVelY_i16 + 1 + bit Zp_AvatarFlags_bObj + .assert bObj::FlipV = bProc::Negative, error + bpl @normalGravity + @reverseGravity: + rsub #0 + @normalGravity: + tay bmi @jumping cmp #2 blt @hovering @@ -255,6 +263,7 @@ _SetPoseInWater: sta Zp_AvatarPose_eAvatar rts _SetPoseOnGround: + ;; TODO: Invert Up and Down buttons if gravity is reversed. lda Zp_AvatarState_bAvatar and #bAvatar::LandMask beq @standOrRun ; landing timer is zero @@ -314,27 +323,42 @@ _SetPoseOnGround: ;;; collisions. Sets Zp_AvatarExit_ePassage if the avatar hits a vertical ;;; passage. .PROC FuncA_Avatar_ApplyVelY + ;; Determine whether the player avatar is moving against gravity. + bit Zp_AvatarFlags_bObj + .assert bObj::FlipV = bProc::Negative, error + bpl @normalGravity + @reverseGravity: + lda #0 + sub Zp_AvatarVelY_i16 + 0 + lda #0 + sbc Zp_AvatarVelY_i16 + 1 + jmp @setOldVel + @normalGravity: + lda Zp_AvatarVelY_i16 + 1 + @setOldVel: + pha ; old gravity-relative Y-vel (hi); negative if moving against gravity +_UpdatePosition: lda Zp_AvatarVelY_i16 + 0 add Zp_AvatarSubY_u8 sta Zp_AvatarSubY_u8 lda Zp_AvatarVelY_i16 + 1 - pha ; old Y-velocity (hi) adc #0 sta Zp_AvatarPushDelta_i8 jsr Func_TryPushAvatarVert - pla ; old Y-velocity (hi) - bmi _NowAirborne ; avatar is moving up - sta T0 ; old Y-velocity (hi) +_CheckIfAirborne: + pla ; old gravity-relative Y-vel (hi); negative if moving against gravity + bmi _NowAirborne ; avatar is moving against gravity + sta T0 ; old vertical speed (hi) lda Zp_AvatarCollided_ePlatform .assert ePlatform::None = 0, error - beq _NowAirborne ; no downward collision + beq _NowAirborne ; no floor collision _NowGrounded: bit Zp_AvatarState_bAvatar .assert bAvatar::Airborne = bProc::Negative, error bpl @done ; avatar was already grounded @wasAirborne: lda #0 - ldy T0 ; old Y-velocity (hi) + ldy T0 ; old vertical speed (hi) bmi @setState lda DataA_Avatar_LandingFrames_u8_arr, y @setState: @@ -425,7 +449,8 @@ _Stop: ;;; button is held. .PROC FuncA_Avatar_ApplyDpadLeft ;; Face the player avatar to the left. - lda #bObj::FlipH | kPaletteObjAvatarNormal + lda Zp_AvatarFlags_bObj + ora #bObj::FlipH sta Zp_AvatarFlags_bObj _DetermineLimit: ;; Determine the (negative) X-velocity limit in pixels/frame, storing it in @@ -489,7 +514,8 @@ _AccelerateTowardsLimit: ;;; button is held. .PROC FuncA_Avatar_ApplyDpadRight ;; Face the player avatar to the right. - lda #kPaletteObjAvatarNormal + lda Zp_AvatarFlags_bObj + and #<~bObj::FlipH sta Zp_AvatarFlags_bObj _DetermineLimit: ;; Determine the (positive) X-velocity limit in pixels/frame, storing it in @@ -569,7 +595,15 @@ _Grounded: bpl @noJump lda #eSample::JumpAnna ; param: eSample to play jsr Func_PlaySfxSample + bit Zp_AvatarFlags_bObj + .assert bObj::FlipV = bProc::Negative, error + bpl @normalGravity + @reverseGravity: + ldax #$ffff & -kAvatarJumpVelocity + bpl @setVelocity ; unconditional + @normalGravity: ldax #kAvatarJumpVelocity + @setVelocity: stax Zp_AvatarVelY_i16 lda #bAvatar::Airborne | bAvatar::Jumping sta Zp_AvatarState_bAvatar @@ -585,12 +619,25 @@ _Airborne: bit Zp_P1ButtonsHeld_bJoypad .assert bJoypad::AButton = bProc::Negative, error bmi _Return ; A button is still held, so don't slow the jump + bit Zp_AvatarFlags_bObj + .assert bObj::FlipV = bProc::Negative, error + bpl @normalGravity + @reverseGravity: + lda Zp_AvatarVelY_i16 + 1 + bmi _Return ; avatar is moving upward, not downward + cmp #kAvatarStopJumpSpeed + blt _Return ; avatar is already below the downward speed cap + lda #kAvatarStopJumpSpeed + sta Zp_AvatarVelY_i16 + 1 + bne @zeroVelLo ; unconditional + @normalGravity: lda Zp_AvatarVelY_i16 + 1 bpl _Return ; avatar is moving downward, not upward cmp #$ff & -kAvatarStopJumpSpeed bge _Return ; avatar is already at or below the upward speed cap lda #$ff & -kAvatarStopJumpSpeed sta Zp_AvatarVelY_i16 + 1 + @zeroVelLo: lda #$00 sta Zp_AvatarVelY_i16 + 0 _Return: @@ -650,6 +697,10 @@ _InWater: @done: rts _InAir: + bit Zp_AvatarFlags_bObj + .assert bObj::FlipV = bProc::Negative, error + bmi _InAirReverseGravity +_InAirNormalGravity: ;; Accelerate the player avatar downwards. lda #kAvatarGravity add Zp_AvatarVelY_i16 + 0 @@ -668,6 +719,24 @@ _InAir: sta Zp_AvatarVelY_i16 + 1 _Done: rts +_InAirReverseGravity: + ;; Accelerate the player avatar upwards. + lda Zp_AvatarVelY_i16 + 0 + sub #kAvatarGravity + sta Zp_AvatarVelY_i16 + 0 + lda Zp_AvatarVelY_i16 + 1 + sbc #0 + ;; If moving upward, check for terminal velocity: + bpl @setVelYHi + .assert <-kAvatarMaxAirSpeedVert = 0, error + cmp #>-kAvatarMaxAirSpeedVert + bge @setVelYHi + lda #0 + sta Zp_AvatarVelY_i16 + 0 + lda #>-kAvatarMaxAirSpeedVert + @setVelYHi: + sta Zp_AvatarVelY_i16 + 1 + rts .ENDPROC ;;;=========================================================================;;; diff --git a/src/death.asm b/src/death.asm index 067a9f0d..a50957ea 100644 --- a/src/death.asm +++ b/src/death.asm @@ -175,7 +175,7 @@ _InitNumRollingDeathDigits: iny tya ; num consecutive 9's, plus 1 .assert kNumDeathDigits + 1 = 4, error - and #$03 ; A = A mod 4 + mod #4 sta Zp_NumRollingDeathDigits_u8 _InitTimers: lda #kDeathTotalAvatarAnimationFrames @@ -191,6 +191,9 @@ _FadeOut: ;;; Performs per-frame updates during the player avatar death animation. .PROC FuncA_Death_AnimateAvatar + lda Zp_AvatarFlags_bObj + and #<~bObj::FlipV + sta Zp_AvatarFlags_bObj _DecrementTimer: dec Zp_DeathTimer_u8 bne @done diff --git a/src/explore.asm b/src/explore.asm index 6f7bf20e..1fbea69e 100644 --- a/src/explore.asm +++ b/src/explore.asm @@ -49,7 +49,7 @@ .IMPORT FuncA_Objects_DrawFloatingHud .IMPORT FuncA_Objects_DrawPlayerAvatar .IMPORT FuncA_Objects_MoveShapeLeftHalfTile -.IMPORT FuncA_Objects_MoveShapeUpByA +.IMPORT FuncA_Objects_MoveShapeVert .IMPORT FuncA_Objects_SetShapePosToAvatarCenter .IMPORT FuncA_Room_CallRoomTick .IMPORT FuncA_Room_InitAllMachinesAndCallRoomEnter @@ -85,6 +85,7 @@ .IMPORT Sram_CarryingFlower_eFlag .IMPORT Sram_LastSafe_eRoom .IMPORTZP Zp_AvatarExit_ePassage +.IMPORTZP Zp_AvatarFlags_bObj .IMPORTZP Zp_AvatarHarmTimer_u8 .IMPORTZP Zp_AvatarPosX_i16 .IMPORTZP Zp_AvatarPosY_i16 @@ -550,8 +551,16 @@ _DrawObject: bne @noZigZag lda #$01 @noZigZag: - add #3 + kTileWidthPx * 2 ; param: offset - jsr FuncA_Objects_MoveShapeUpByA + bit Zp_AvatarFlags_bObj + .assert bObj::FlipV = bProc::Negative, error + bpl @normalGravity + @reverseGravity: + add #3 + kTileHeightPx + bne @moveShape ; unconditional + @normalGravity: + sub #5 + kTileHeightPx * 2 ; param: signed offset + @moveShape: + jsr FuncA_Objects_MoveShapeVert ;; Draw the object: ldy #kPaletteObjDevicePrompt ; param: object flags lda #kTileIdObjDevicePrompt ; param: tile ID diff --git a/src/platform.asm b/src/platform.asm index 0a4896f7..efc7ad68 100644 --- a/src/platform.asm +++ b/src/platform.asm @@ -28,6 +28,7 @@ .IMPORT Func_TryPushAvatarHorz .IMPORT Func_TryPushAvatarVert .IMPORTZP Zp_AvatarCollided_ePlatform +.IMPORTZP Zp_AvatarFlags_bObj .IMPORTZP Zp_AvatarPosX_i16 .IMPORTZP Zp_AvatarPosY_i16 .IMPORTZP Zp_AvatarPushDelta_i8 @@ -695,9 +696,13 @@ _Return: .PROC Func_AvatarCollideWithOnePlatformVert jsr Func_IsAvatarInPlatformHorz ; preserves X, returns Z beq _Return - ;; Check if the player is moving up or down. - bit Zp_AvatarPushDelta_i8 - bpl _MovingDown + ;; Check if the player avatar is moving up or down. + lda Zp_AvatarPushDelta_i8 + bmi _MovingUp + bne _MovingDown + bit Zp_AvatarFlags_bObj + .assert bObj::FlipV = bProc::Negative, error + bpl _MovingDown ; normal gravity; treat no vertical movement as "down" _MovingUp: ;; Check top edge of platform. lda Zp_AvatarPosY_i16 + 1 @@ -710,7 +715,7 @@ _MovingUp: @topEdgeHit: ;; Check bottom edge of platform. lda Ram_PlatformBottom_i16_0_arr, x - add #kAvatarBoundingBoxUp + add #kAvatarBoundingBoxUp ; TODO: handle reverse gravity sta T0 ; platform bottom edge + bbox (lo) lda Ram_PlatformBottom_i16_1_arr, x adc #0 @@ -728,6 +733,7 @@ _MovingUp: sta Zp_AvatarPosY_i16 + 0 lda T1 ; platform bottom edge + bbox (hi) sta Zp_AvatarPosY_i16 + 1 + ;; TODO: if reverse gravity, set Zp_AvatarPlatformIndex_u8 jmp _Collided _MovingDown: ;; Check bottom edge of platform. @@ -761,7 +767,7 @@ _MovingDown: lda T1 ; platform top edge - bbox (hi) sta Zp_AvatarPosY_i16 + 1 ;; Record that the avatar is now riding this platform. - stx Zp_AvatarPlatformIndex_u8 + stx Zp_AvatarPlatformIndex_u8 ; TODO: only for normal gravity _Collided: lda Ram_PlatformType_ePlatform_arr, x sta Zp_AvatarCollided_ePlatform @@ -780,7 +786,7 @@ _Return: bne @checkTop rts @checkTop: - .assert * = Func_AvatarDepthIntoPlatformTop, error, "fallthrough" + fall Func_AvatarDepthIntoPlatformTop ; preserves X, returns Z .ENDPROC ;;; Determines if the bottom of the avatar is below the top of the platform, @@ -804,21 +810,15 @@ _Return: tay ; depth (lo) lda T1 ; bottom of avatar (hi) sbc Ram_PlatformTop_i16_1_arr, x - bmi _NotInPlatform - bne _MaxDepth + bmi Func_AvatarNotInPlatform ; preserves X and T0+, returns A and Z + bne Func_AvatarAtMaxPlatformDepth ; preserves X and T0+, returns A and Z cpy #127 - bge _MaxDepth + bge Func_AvatarAtMaxPlatformDepth ; preserves X and T0+, returns A and Z ;; Set A equal to -Y. dey tya eor #$ff rts -_MaxDepth: - lda #<-127 - rts -_NotInPlatform: - lda #0 - rts .ENDPROC ;;; Determines if the top of the avatar is above the bottom of the platform, @@ -842,16 +842,32 @@ _NotInPlatform: tay ; depth (lo) lda Ram_PlatformBottom_i16_1_arr, x sbc T1 ; top of avatar (hi) - bmi _NotInPlatform - bne _MaxDepth + bmi Func_AvatarNotInPlatform ; preserves X and T0+, returns A and Z + bne Func_AvatarAtMaxPlatformDepth ; preserves X and T0+, returns A and Z cpy #127 - bge _MaxDepth + bge Func_AvatarAtMaxPlatformDepth ; preserves X and T0+, returns A and Z tya ; depth (lo) rts -_MaxDepth: +.ENDPROC + +;;; Helper function for Func_AvatarDepthIntoPlatform* functions. Returns a +;;; depth of 127, with Z cleared to indicate that the player avatar is within +;;; the platform along that direction. +;;; @return A Always 127. +;;; @return Z Always cleared. +;;; @preserve X, T0+ +.PROC Func_AvatarAtMaxPlatformDepth lda #127 rts -_NotInPlatform: +.ENDPROC + +;;; Helper function for Func_AvatarDepthIntoPlatform* functions. Returns a +;;; depth of zero, with Z set to indicate that the player avatar is fully +;;; outside the platform along that direction. +;;; @return A Always zero. +;;; @return Z Always set. +;;; @preserve X, T0+ +.PROC Func_AvatarNotInPlatform lda #0 rts .ENDPROC @@ -867,7 +883,7 @@ _NotInPlatform: bne @checkLeft rts @checkLeft: - .assert * = Func_AvatarDepthIntoPlatformLeft, error, "fallthrough" + fall Func_AvatarDepthIntoPlatformLeft ; preserves X, returns Z .ENDPROC ;;; Determines if the avatar's right side is to the right of the platform's @@ -891,21 +907,15 @@ _NotInPlatform: tay ; depth (lo) lda T1 ; avatar's right side (hi) sbc Ram_PlatformLeft_i16_1_arr, x - bmi _NotInPlatform - bne _MaxDepth + bmi Func_AvatarNotInPlatform ; preserves X and T0+, returns A and Z + bne Func_AvatarAtMaxPlatformDepth ; preserves X and T0+, returns A and Z cpy #127 - bge _MaxDepth + bge Func_AvatarAtMaxPlatformDepth ; preserves X and T0+, returns A and Z ;; Set A equal to -Y. dey tya eor #$ff rts -_MaxDepth: - lda #<-127 - rts -_NotInPlatform: - lda #0 - rts .ENDPROC ;;; Determines if the avatar's left side is to the left of the platform's right @@ -929,18 +939,12 @@ _NotInPlatform: tay ; depth (lo) lda Ram_PlatformRight_i16_1_arr, x sbc T1 ; avatar's left side (hi) - bmi _NotInPlatform - bne _MaxDepth + bmi Func_AvatarNotInPlatform ; preserves X and T0+, returns A and Z + bne Func_AvatarAtMaxPlatformDepth ; preserves X and T0+, returns A and Z cpy #127 - bge _MaxDepth + bge Func_AvatarAtMaxPlatformDepth ; preserves X and T0+, returns A and Z tya ; depth (lo) rts -_MaxDepth: - lda #127 - rts -_NotInPlatform: - lda #0 - rts .ENDPROC ;;;=========================================================================;;; diff --git a/src/push.asm b/src/push.asm index 06c24474..e55bc36b 100644 --- a/src/push.asm +++ b/src/push.asm @@ -34,6 +34,7 @@ .IMPORT Func_GetTerrainColumnPtrForPointX .IMPORT Func_HarmAvatar .IMPORT Func_KillAvatar +.IMPORTZP Zp_AvatarFlags_bObj .IMPORTZP Zp_AvatarPosX_i16 .IMPORTZP Zp_AvatarPosY_i16 .IMPORTZP Zp_AvatarSubX_u8 @@ -389,14 +390,18 @@ _NoHitPassage: ;; Get the terrain pointer for the right side of the avatar, storing it in ;; Zp_TerrainColumn_u8_arr_ptr. jsr Func_GetAvatarRightXAndTerrain ; preserves T0+ - ;; Check if the player is moving up or down. + ;; Check if the player avatar is moving up or down. lda Zp_AvatarPushDelta_i8 - bpl _MovingDown + bmi _MovingUp + bne _MovingDown + bit Zp_AvatarFlags_bObj + .assert bObj::FlipV = bProc::Negative, error + bpl _MovingDown ; normal gravity; treat no vertical movement as "down" _MovingUp: ;; Calculate the room block row index just above the avatar's head, and ;; store it in T2. lda Zp_AvatarPosY_i16 + 0 - sub #kAvatarBoundingBoxUp + sub #kAvatarBoundingBoxUp ; TODO: handle reverse gravity sta T2 lda Zp_AvatarPosY_i16 + 1 sbc #0 @@ -422,7 +427,7 @@ _MovingUp: .endrepeat tax lda T2 - add #kBlockHeightPx + kAvatarBoundingBoxUp + add #kBlockHeightPx + kAvatarBoundingBoxUp ; TODO: handle reverse gravity sta Zp_AvatarPosY_i16 + 0 txa adc #0 diff --git a/src/rooms/shadow_descent.asm b/src/rooms/shadow_descent.asm index 9cdac87d..7b545eca 100644 --- a/src/rooms/shadow_descent.asm +++ b/src/rooms/shadow_descent.asm @@ -22,15 +22,28 @@ .INCLUDE "../actors/townsfolk.inc" .INCLUDE "../device.inc" .INCLUDE "../macros.inc" +.INCLUDE "../oam.inc" .INCLUDE "../platform.inc" .INCLUDE "../platforms/lava.inc" .INCLUDE "../room.inc" +.INCLUDE "../spawn.inc" .IMPORT DataA_Room_Shadow_sTileset .IMPORT FuncA_Objects_AnimateLavaTerrain .IMPORT FuncA_Terrain_FadeInTallRoomWithLava .IMPORT Func_Noop .IMPORT Ppu_ChrObjShadow +.IMPORTZP Zp_AvatarFlags_bObj +.IMPORTZP Zp_AvatarPosY_i16 + +;;;=========================================================================;;; + +;;; The index of the passage that leads to the ShadowDrill room. +kDrillPassageIndex = 1 + +;;; The room pixel Y-position of the center of the passage that leads to the +;;; ShadowDrill room. +kDrillPassageCenterY = $0050 ;;;=========================================================================;;; @@ -57,7 +70,7 @@ _Ext_sRoomExt: d_addr Actors_sActor_arr_ptr, _Actors_sActor_arr d_addr Devices_sDevice_arr_ptr, _Devices_sDevice_arr d_addr Passages_sPassage_arr_ptr, _Passages_sPassage_arr - d_addr Enter_func_ptr, Func_Noop + d_addr Enter_func_ptr, FuncA_Room_ShadowDescent_EnterRoom d_addr FadeIn_func_ptr, FuncA_Terrain_FadeInTallRoomWithLava d_addr Tick_func_ptr, Func_Noop d_addr Draw_func_ptr, FuncA_Objects_AnimateLavaTerrain @@ -96,6 +109,7 @@ _Passages_sPassage_arr: d_byte SpawnBlock_u8, 5 d_byte SpawnAdjust_byte, 0 D_END + .assert * - :- = kDrillPassageIndex * .sizeof(sPassage), error D_STRUCT sPassage d_byte Exit_bPassage, ePassage::Eastern | 0 d_byte Destination_eRoom, eRoom::ShadowDrill @@ -118,3 +132,30 @@ _Passages_sPassage_arr: .ENDPROC ;;;=========================================================================;;; + +.SEGMENT "PRGA_Room" + +;;; @param A The bSpawn value for where the avatar is entering the room. +.PROC FuncA_Room_ShadowDescent_EnterRoom + ;; If entering from the ShadowDrill room, and gravity is still reversed, + ;; un-reverse it. + cmp #bSpawn::Passage | kDrillPassageIndex + bne @done ; not entering from ShadowDrill room + lda Zp_AvatarFlags_bObj + .assert bObj::FlipV = $80, error + bpl @done ; gravity is already normal + ;; Restore normal gravity. + and #<~bObj::FlipV + sta Zp_AvatarFlags_bObj + ;; Invert the avatar's Y-position within the passage. + lda #<(kDrillPassageCenterY * 2) + sub Zp_AvatarPosY_i16 + 0 + sta Zp_AvatarPosY_i16 + 0 + lda #>(kDrillPassageCenterY * 2) + sbc Zp_AvatarPosY_i16 + 1 + sta Zp_AvatarPosY_i16 + 1 + @done: + rts +.ENDPROC + +;;;=========================================================================;;; diff --git a/src/rooms/shadow_drill.asm b/src/rooms/shadow_drill.asm index 3ae24ef7..e1b63a29 100644 --- a/src/rooms/shadow_drill.asm +++ b/src/rooms/shadow_drill.asm @@ -28,6 +28,7 @@ .INCLUDE "../ppu.inc" .INCLUDE "../program.inc" .INCLUDE "../room.inc" +.INCLUDE "../spawn.inc" .IMPORT DataA_Room_Shadow_sTileset .IMPORT FuncA_Machine_GenericMoveTowardGoalHorz @@ -42,9 +43,23 @@ .IMPORT Func_MachineLaserReadRegC .IMPORT Func_Noop .IMPORT Func_SetMachineIndex +.IMPORT Func_WriteToLowerAttributeTable .IMPORT Ppu_ChrObjShadow .IMPORT Ram_MachineGoalHorz_u8_arr .IMPORT Ram_PlatformLeft_i16_0_arr +.IMPORTZP Zp_AvatarFlags_bObj +.IMPORTZP Zp_AvatarPosY_i16 + +;;;=========================================================================;;; + +;;; The index of the upper passage (which leads to the ShadowHall room). +kUpperPassageIndex = 0 + +;;; The room pixel Y-position of the center of the upper passage. +kUpperPassageCenterY = $0050 + +;;; The room pixel Y-position of the center of the lower passages. +kLowerPassageCenterY = $0150 ;;;=========================================================================;;; @@ -90,8 +105,8 @@ _Ext_sRoomExt: d_addr Actors_sActor_arr_ptr, _Actors_sActor_arr d_addr Devices_sDevice_arr_ptr, _Devices_sDevice_arr d_addr Passages_sPassage_arr_ptr, _Passages_sPassage_arr - d_addr Enter_func_ptr, Func_Noop - d_addr FadeIn_func_ptr, Func_Noop + d_addr Enter_func_ptr, FuncA_Room_ShadowDrill_EnterRoom + d_addr FadeIn_func_ptr, FuncA_Terrain_ShadowDrill_FadeInRoom d_addr Tick_func_ptr, FuncA_Room_ShadowDrill_TickRoom d_addr Draw_func_ptr, Func_Noop D_END @@ -128,6 +143,14 @@ _Platforms_sPlatform_arr: d_word Left_i16, kLaserInitPlatformLeft d_word Top_i16, $0020 D_END + ;; Acid: + D_STRUCT sPlatform + d_byte Type_ePlatform, ePlatform::Kill + d_word WidthPx_u16, $c0 + d_byte HeightPx_u8, $10 + d_word Left_i16, $0030 + d_word Top_i16, $016a + D_END .assert * - :- <= kMaxPlatforms * .sizeof(sPlatform), error .byte ePlatform::None _Actors_sActor_arr: @@ -171,21 +194,22 @@ _Actors_sActor_arr: .byte eActor::None _Devices_sDevice_arr: : D_STRUCT sDevice - d_byte Type_eDevice, eDevice::Console - d_byte BlockRow_u8, 6 - d_byte BlockCol_u8, 2 + d_byte Type_eDevice, eDevice::Console ; TODO: ConsoleCeiling + d_byte BlockRow_u8, 4 + d_byte BlockCol_u8, 3 d_byte Target_byte, kLaserMachineIndex D_END D_STRUCT sDevice - d_byte Type_eDevice, eDevice::Console - d_byte BlockRow_u8, 18 + d_byte Type_eDevice, eDevice::Console ; TODO: ConsoleCeiling + d_byte BlockRow_u8, 17 d_byte BlockCol_u8, 12 d_byte Target_byte, kLaserMachineIndex D_END .assert * - :- <= kMaxDevices * .sizeof(sDevice), error .byte eDevice::None _Passages_sPassage_arr: -: D_STRUCT sPassage +: .assert * - :- = kUpperPassageIndex * .sizeof(sPassage), error + D_STRUCT sPassage d_byte Exit_bPassage, ePassage::Eastern | 0 d_byte Destination_eRoom, eRoom::ShadowHall d_byte SpawnBlock_u8, 5 @@ -222,6 +246,31 @@ _ReadX: .SEGMENT "PRGA_Room" +;;; @param A The bSpawn value for where the avatar is entering the room. +.PROC FuncA_Room_ShadowDrill_EnterRoom + cmp #bSpawn::Passage | kUpperPassageIndex + beq @upperPassage + and #bSpawn::Passage + beq @done ; not spawning from a passage + @lowerPassage: + ldya #kLowerPassageCenterY * 2 + bpl @invertPositionY ; unconditional + @upperPassage: + ldya #kUpperPassageCenterY * 2 + @invertPositionY: + sub Zp_AvatarPosY_i16 + 0 + sta Zp_AvatarPosY_i16 + 0 + tya + sbc Zp_AvatarPosY_i16 + 1 + sta Zp_AvatarPosY_i16 + 1 + @done: +_SetGravityReversed: + lda Zp_AvatarFlags_bObj + ora #bObj::FlipV + sta Zp_AvatarFlags_bObj + rts +.ENDPROC + .PROC FuncA_Room_ShadowDrill_TickRoom ;; TODO: Once all goos are dead, set a flag to make them not reappear. ldx #kLaserMachineIndex @@ -266,3 +315,16 @@ _LaserBottom_i16_1_arr: .ENDPROC ;;;=========================================================================;;; + +.SEGMENT "PRGA_Terrain" + +;;; Sets one block row of the lower nametable to use BG palette 2. +;;; @prereq Rendering is disabled. +.PROC FuncA_Terrain_ShadowDrill_FadeInRoom + ldx #7 ; param: num bytes to write + ldy #$a0 ; param: attribute value + lda #$19 ; param: initial byte offset + jmp Func_WriteToLowerAttributeTable +.ENDPROC + +;;;=========================================================================;;; diff --git a/src/rooms/shadow_drill.bg b/src/rooms/shadow_drill.bg index fa1f0aa2..0ede24e5 100644 --- a/src/rooms/shadow_drill.bg +++ b/src/rooms/shadow_drill.bg @@ -10,11 +10,11 @@ ENEBEMECEGENEFEGEBEMEEENEBEAENENEFEM ENENEHEIENEBEGENENEHEDEAENENEFECEMEG EEENEBEMAFAFAFAFAFAFAFAFAFAFEMEMEGEB EMEAENEH EDEGENEN -EMFC AK EOCF -EDEC BDBC -ECEMAB EAEB EO EAEFEAEN -EHEGEF BDBC BJ AKEGENEF -ENEFEM EAENFDENFDENFDENENENEFECEM +EMEEEBAG EOCF +EDEMAK BDBC +ECED EAEB EO EAEFEAEN +EHFC BDBC BJ AKEGENEF +ENEFEC BDEAFDENFDENFDENENENEFECEM ECEMEM BDBC AK BJ EDEMEM EMEMEGENFDENENFDENFDENFDENEB FCEDEM EMEM BDBC BJ AKEEENEH @@ -23,10 +23,10 @@ EFED AK BDBC BJ AK EEEN EGENENENFDENENFDENENENFDENENEB EGEF EFFC BDBC AK BJ AK FCEG EGEF EAENENENFDEKFDENENENENENENENEF -EFEM BDCCCFEDCEBNCF EEEBEM -EMEGEB BD BCDABD BCAB EAEHEEEH +EFEM BDCCCFEDCEBNCFAG EEEBEM +EMEGEB BD BCDABD BC EAEHEEEH EGENENENENEB CKDBCL EAENENENENEHEA - BD EC BC - BD EM BC -ENEFECEAENEBEEEBEMEAENEFEEENEBEAENEN -EFEMEGENENENEHEEELEFECEMEDEEENENENEF + EC + EM +ENEFECAOAOAOAOAOEMAOAOAOAOAOAOEAENEN +EFEMEGENENENEFEEELEFEEENEBEEENENENEF diff --git a/src/rooms/shadow_hall.asm b/src/rooms/shadow_hall.asm index c0e40505..1e4ac0aa 100644 --- a/src/rooms/shadow_hall.asm +++ b/src/rooms/shadow_hall.asm @@ -26,11 +26,13 @@ .INCLUDE "../machines/minigun.inc" .INCLUDE "../macros.inc" .INCLUDE "../mmc3.inc" +.INCLUDE "../oam.inc" .INCLUDE "../platform.inc" .INCLUDE "../platforms/glass.inc" .INCLUDE "../ppu.inc" .INCLUDE "../program.inc" .INCLUDE "../room.inc" +.INCLUDE "../spawn.inc" .IMPORT DataA_Room_Shadow_sTileset .IMPORT Data_Empty_sActor_arr @@ -59,10 +61,19 @@ .IMPORT Ram_PlatformType_ePlatform_arr .IMPORT Sram_Programs_sProgram_arr .IMPORT Sram_ProgressFlags_arr +.IMPORTZP Zp_AvatarFlags_bObj +.IMPORTZP Zp_AvatarPosY_i16 .IMPORTZP Zp_RoomState ;;;=========================================================================;;; +;;; The index of the passage that leads to the ShadowDrill room. +kDrillPassageIndex = 0 + +;;; The room pixel Y-position of the center of the passage that leads to the +;;; ShadowDrill room. +kDrillPassageCenterY = $0050 + ;;; The platform indices for the breakable glass. kGlass1PlatformIndex = 0 kGlass2PlatformIndex = 1 @@ -233,7 +244,8 @@ _Devices_sDevice_arr: .assert * - :- <= kMaxDevices * .sizeof(sDevice), error .byte eDevice::None _Passages_sPassage_arr: -: D_STRUCT sPassage +: .assert * - :- = kDrillPassageIndex * .sizeof(sPassage), error + D_STRUCT sPassage d_byte Exit_bPassage, ePassage::Western | 0 d_byte Destination_eRoom, eRoom::ShadowDrill d_byte SpawnBlock_u8, 5 @@ -317,7 +329,7 @@ _MoveToBottom: _MoveToMiddleRight: lda #eResetSeq::MidRight sta Zp_RoomState + sState::Minigun_eResetSeq - .assert * = FuncC_Shadow_HallMinigun_Init, error, "fallthrough" + fall FuncC_Shadow_HallMinigun_Init .ENDPROC .PROC FuncC_Shadow_HallMinigun_Init @@ -351,7 +363,27 @@ _MoveToMiddleRight: D_END .ENDPROC +;;; @param A The bSpawn value for where the avatar is entering the room. .PROC FuncA_Room_ShadowHall_EnterRoom +_FixGravity: + ;; If entering from the ShadowDrill room, and gravity is still reversed, + ;; un-reverse it. + cmp #bSpawn::Passage | kDrillPassageIndex + bne @done ; not entering from ShadowDrill room + lda Zp_AvatarFlags_bObj + .assert bObj::FlipV = $80, error + bpl @done ; gravity is already normal + ;; Restore normal gravity. + and #<~bObj::FlipV + sta Zp_AvatarFlags_bObj + ;; Invert the avatar's Y-position within the passage. + lda #<(kDrillPassageCenterY * 2) + sub Zp_AvatarPosY_i16 + 0 + sta Zp_AvatarPosY_i16 + 0 + lda #>(kDrillPassageCenterY * 2) + sbc Zp_AvatarPosY_i16 + 1 + sta Zp_AvatarPosY_i16 + 1 + @done: _InitProgram: ldx #eFlag::ShadowHallInitialized ; param: flag jsr Func_SetFlag ; returns C diff --git a/src/rooms/shadow_trap.asm b/src/rooms/shadow_trap.asm index 341ba518..9c3fee9c 100644 --- a/src/rooms/shadow_trap.asm +++ b/src/rooms/shadow_trap.asm @@ -30,6 +30,7 @@ .INCLUDE "../ppu.inc" .INCLUDE "../program.inc" .INCLUDE "../room.inc" +.INCLUDE "../spawn.inc" .IMPORT DataA_Room_Shadow_sTileset .IMPORT Data_Empty_sActor_arr @@ -62,11 +63,22 @@ .IMPORT Ram_MachineGoalHorz_u8_arr .IMPORT Ram_PlatformLeft_i16_0_arr .IMPORT Sram_ProgressFlags_arr +.IMPORTZP Zp_AvatarFlags_bObj +.IMPORTZP Zp_AvatarPosY_i16 .IMPORTZP Zp_PointY_i16 .IMPORTZP Zp_RoomState ;;;=========================================================================;;; +;;; The index of the passage that leads to the ShadowDrill room. +kDrillPassageIndex = 0 + +;;; The room pixel Y-position of the center of the passage that leads to the +;;; ShadowDrill room. +kDrillPassageCenterY = $00a0 + +;;;=========================================================================;;; + ;;; The platform index for the zone that, when the player avatar enters it, ;;; triggers the trap in this room. kTrapZonePlatformIndex = 1 @@ -240,7 +252,8 @@ _Devices_sDevice_arr: .assert * - :- <= kMaxDevices * .sizeof(sDevice), error .byte eDevice::None _Passages_sPassage_arr: -: D_STRUCT sPassage +: .assert * - :- = kDrillPassageIndex * .sizeof(sPassage), error + D_STRUCT sPassage d_byte Exit_bPassage, ePassage::Western | 0 d_byte Destination_eRoom, eRoom::ShadowDrill d_byte SpawnBlock_u8, 10 @@ -278,7 +291,28 @@ _ReadX: .SEGMENT "PRGA_Room" +;;; @param A The bSpawn value for where the avatar is entering the room. .PROC FuncA_Room_ShadowTrap_EnterRoom +_FixGravity: + ;; If entering from the ShadowDrill room, and gravity is still reversed, + ;; un-reverse it. + cmp #bSpawn::Passage | kDrillPassageIndex + bne @done ; not entering from ShadowDrill room + lda Zp_AvatarFlags_bObj + .assert bObj::FlipV = $80, error + bpl @done ; gravity is already normal + ;; Restore normal gravity. + and #<~bObj::FlipV + sta Zp_AvatarFlags_bObj + ;; Invert the avatar's Y-position within the passage. + lda #<(kDrillPassageCenterY * 2) + sub Zp_AvatarPosY_i16 + 0 + sta Zp_AvatarPosY_i16 + 0 + lda #>(kDrillPassageCenterY * 2) + sbc Zp_AvatarPosY_i16 + 1 + sta Zp_AvatarPosY_i16 + 1 + @done: +_MaybeMarkSafe: flag_bit Sram_ProgressFlags_arr, eFlag::ShadowTrapDisarmed jne Func_MarkRoomSafe rts diff --git a/src/tiles/shadow3.ahi b/src/tiles/shadow3.ahi index 4105c41b..b26c4e29 100644 --- a/src/tiles/shadow3.ahi +++ b/src/tiles/shadow3.ahi @@ -38,40 +38,40 @@ ahi1 f0 p1 i12 w8 h8 21000210 12100100 -00000000 -00000000 -00000000 -00000000 -00000000 -00000000 -00000000 -00000000 +00022222 +00022222 +00022222 +00021112 +00022222 +00000022 +00022222 +00021111 -00000000 -00000000 -00000000 -00000000 -00000000 -00000000 -00000000 -00000000 +22222000 +22222000 +22222000 +21212000 +22222000 +22000000 +22222000 +11112200 -00000000 -00000000 -00000000 -00000000 -00000000 -00000000 -00000000 +00021111 +00021111 +00021111 +00021111 +00021111 +00021111 +00002222 00000000 -00000000 -00000000 -00000000 -00000000 -00000000 -00000000 -00000000 +11112200 +11112200 +11112200 +11112200 +11112200 +11112000 +22220000 00000000 00000000 diff --git a/src/tilesets/shadow.bg b/src/tilesets/shadow.bg index d5ac43bc..1ea43d08 100644 --- a/src/tilesets/shadow.bg +++ b/src/tilesets/shadow.bg @@ -9,8 +9,8 @@ >terrain_shared_0 >terrain_shared_1 - HMHN HCHDDODPICID ECEJEAEBEC FAFBCACBBB BAAAAAABAB - HOHPDMDN DODP EDEG ED FCFDCBCABD BCABABABAB + HMHN HCHDDODPICIDFEFFECEJEAEBEC FAFBCACBBB BAAAAAABAB + HOHPDMDN DODP FGFHEDEG ED FCFDCBCABD BCABABABAB EIEI EJ EJEJEI EJEIEIEJ EIEIEJEJEGEIEIEHEFEEEJEJ EIEIEJ EJEJ EIEJ EJEIEIEIEIEJEJEEEIEIEFEJEJEHEG EEEIEIEFEJ EJ EGEH EGEIEIEH EEEF EJEJ