Timed challenge rolls.

This commit is contained in:
Randy Thiemann 2023-11-09 20:56:44 +01:00
parent f61c4ff064
commit 100d40c4e6
13 changed files with 3559 additions and 3082 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -2009,11 +2009,15 @@ FieldDelay::
ldh [hBravo], a
; Kill screen?
ld a, [wInStaffRoll]
cp a, $FF
jr z, .noskip
ld a, [wKillScreenActive]
cp a, $FF
jr z, .skip
; Are there line clears?
.noskip
call ToShadowField
call FindClearedLines
ldh a, [hClearedLines]
@ -2228,6 +2232,14 @@ FieldDelay::
; Cycle the RNG.
.generatenextpiece
ld a, [wInStaffRoll]
cp a, $FF
jr z, .doit
ld a, [wShouldGoStaffRoll]
cp a, $FF
ret z
.doit
ldh a, [hNextPiece]
ldh [hCurrentPiece], a
call GetNextPiece
@ -4269,11 +4281,15 @@ BigFieldDelay::
ldh [hBravo], a
; Kill screen?
ld a, [wInStaffRoll]
cp a, $FF
jr z, .noskip
ld a, [wKillScreenActive]
cp a, $FF
jr z, .skip
; Are there line clears?
.noskip
call BigToShadowField
call BigFindClearedLines
ldh a, [hClearedLines]
@ -4490,6 +4506,14 @@ BigFieldDelay::
; Cycle the RNG.
.generatenextpiece
ld a, [wInStaffRoll]
cp a, $FF
jr z, .doit
ld a, [wShouldGoStaffRoll]
cp a, $FF
ret z
.doit
ldh a, [hNextPiece]
ldh [hCurrentPiece], a
call GetNextPiece

View File

@ -388,6 +388,7 @@ DEF MODE_DELAY EQU 18
DEF MODE_GAME_OVER EQU 21
DEF MODE_PRE_GAME_OVER EQU 24
DEF MODE_PAUSED EQU 27
DEF MODE_PREROLL EQU 30
; Helpers to avoid magic numbers
DEF SCORE_ONES EQU 7

View File

@ -44,10 +44,14 @@ wBoneActivationLevel: ds 2
wInvisActivationLevel: ds 2
wKillScreenActivationLevel: ds 2
wKillScreenActivationLevelBCD: ds 2
wLastLockLevel: ds 2
wStaffRollDuration:: ds 2
wBonesActive:: ds 1
wInvisActive:: ds 1
wKillScreenActive:: ds 1
wLockLevel:: ds 1
wShouldGoStaffRoll:: ds 1
wNoMoreLocks:: ds 1
SECTION "Level Functions", ROM0
@ -63,6 +67,8 @@ LevelInit::
ld [wInvisActive], a
ld [wKillScreenActive], a
ld [wLockLevel], a
ld [wShouldGoStaffRoll], a
ld [wNoMoreLocks], a
ldh a, [hStartSpeed]
ld l, a
@ -188,8 +194,16 @@ SpecialLevelInit:
ld [wKillScreenActivationLevel+1], a
ld a, [hl+]
ld [wKillScreenActivationLevelBCD], a
ld a, [hl]
ld a, [hl+]
ld [wKillScreenActivationLevelBCD+1], a
ld a, [hl+]
ld [wLastLockLevel], a
ld a, [hl+]
ld [wLastLockLevel+1], a
ld a, [hl+]
ld [wStaffRollDuration], a
ld a, [hl]
ld [wStaffRollDuration+1], a
ret
@ -348,6 +362,9 @@ LevelUp::
and a, [hl]
cp a, 9
jr nz, .leveljinglemaybe
ld a, [wNoMoreLocks]
cp a, $FF
jr z, .checkspeedup
ld a, $FF
ldh [hRequiresLineClear], a
ld a, SFX_LEVELLOCK
@ -457,12 +474,90 @@ DoSpeedUp:
CheckSpecialLevelConditions:
; Is our nlevel > our kill screen?
ld hl, wKillScreenActivationLevelBCD+1
ld a, [hl]
swap a
and a, $0F
ld b, a
ldh a, [hNLevel]
cp a, b
jr c, .nooverride
jr nz, .override
ld a, [hl-]
and a, $0F
ld b, a
ldh a, [hNLevel+1]
cp a, b
jr c, .nooverride
jr nz, .override
ld a, [hl]
swap a
and a, $0F
ld b, a
ldh a, [hNLevel+2]
cp a, b
jr c, .nooverride
jr nz, .override
ld a, [hl]
and a, $0F
ld b, a
ldh a, [hNLevel+3]
cp a, b
jr c, .nooverride
.override
ld hl, wKillScreenActivationLevelBCD
ld a, [hl]
and a, $0F
ldh [hNLevel+3], a
ld a, [hl+]
swap a
and a, $0F
ldh [hNLevel+2], a
ld a, [hl]
and a, $0F
ldh [hNLevel+1], a
ld a, [hl]
swap a
and a, $0F
ldh [hNLevel], a
; Get our level in bc
.nooverride
ldh a, [hLevel]
ld c, a
ldh a, [hLevel+1]
ld b, a
; Do we need to do a special lock?
.speciallock
ld hl, wLastLockLevel
ld a, [hl+]
cp a, $FF ; $FF means never.
jp z, .bones
; Load the level, binary in de.
ld e, a
ld d, [hl]
; Check if BC == DE...
ld a, b
cp a, d
jr nz, .bones
ld a, c
cp a, e
jr nz, .bones
; Jingle and level lock.
ld a, $FF
ldh [hRequiresLineClear], a
ld [wNoMoreLocks], a
ld a, SFX_LEVELLOCK
push bc
call SFXEnqueue
pop bc
; Bones?
.bones
ld hl, wBoneActivationLevel
@ -553,18 +648,7 @@ CheckSpecialLevelConditions:
ret c
.rip
ld a, 1
ldh [hCurrentARE], a
ldh [hCurrentLineARE], a
ldh [hCurrentDAS], a
ldh [hCurrentLockDelay], a
ldh [hCurrentLineClearDelay], a
ld a, 20
ldh [hCurrentIntegerGravity], a
xor a, a
ldh [hCurrentFractionalGravity], a
call SFXKill
ld a, $FF
ld [wKillScreenActive], a
@ -590,10 +674,37 @@ CheckSpecialLevelConditions:
ldh [hNLevel], a
ld a, $FF
ld [wLockLevel], a
; Since we triggered a kill screen, does this mean the game now just ends, or do we transition to the staff roll?
.staffroll
ld hl, wStaffRollDuration
ld a, [hl+]
cp a, $FF
jr z, .justkill
; Yes, tell the game that we should go to staff roll instead.
ld a, $FF
ld [wShouldGoStaffRoll], a
ret
.justkill
ld a, 1
ldh [hCurrentARE], a
ldh [hCurrentLineARE], a
ldh [hCurrentDAS], a
ldh [hCurrentLockDelay], a
ldh [hCurrentLineClearDelay], a
ld a, 20
ldh [hCurrentIntegerGravity], a
xor a, a
ldh [hCurrentFractionalGravity], a
ret
TriggerKillScreen::
call SFXKill
ld a, 1
ldh [hCurrentARE], a
ldh [hCurrentLineARE], a

View File

@ -79,6 +79,29 @@ sBigYouAreGM::
db " "
db " QUIT [B] "
sBigFinalChallenge::
db " "
db " "
db " "
db "EXCELLENT!"
db " "
db " "
db " BUT NOW "
db " "
db "TRY FINAL"
db " "
db "CHALLENGE!"
db " "
db " "
db " "
db " "
db " "
db " "
db " "
db " "
db " "
sBigPieceXOffsets:: ; How to draw each piece. X-offsets of the sprites.
db 0, 8, 16, 24 ; I
db 0, 8, 8, 16 ; Z

View File

@ -79,6 +79,30 @@ sYouAreGM::
db " "
db " QUIT [B] "
sFinalChallenge::
db " "
db " "
db " "
db "EXCELLENT!"
db " "
db " "
db " BUT NOW "
db " "
db "TRY FINAL"
db " "
db "CHALLENGE!"
db " "
db " "
db " "
db " "
db " "
db " "
db " "
db " "
db " "
sPieceXOffsets:: ; How to draw each piece. X-offsets of the sprites.
db 0, 8, 16, 24 ; I
db 0, 8, 8, 16 ; Z

View File

@ -196,6 +196,8 @@ sDMGTSpeedCurveSpecialData::
dw $FFFF ; When do blocks turn invisible?
dw 9999 ; When is the hard kill screen?
dw $9999 ; Same but in BCD.
dw 9998 ; If the last level lock isn't at x99, where is it?
dw 3600 ; How long does the staff roll last after the kill screen, in frames.
sTGM1SpeedCurve::
@ -331,7 +333,7 @@ sTGM1SpeedCurve::
db 20, $00
db 30, 30, 16, 30, 41
dw $0900, 900, $1000
dw $0900, 900, $0999
db 20, $00
db 30, 30, 16, 30, 41
@ -339,10 +341,12 @@ sTGM1SpeedCurveEnd::
dw $FFFF
sTGM1SpeedCurveSpecialData::
dw 1000 ; When do we get bones?
dw 999 ; When do we get bones?
dw $FFFF ; When do blocks turn invisible?
dw 1199 ; When is the hard kill screen?
dw $1199 ; Same but in BCD.
dw 999 ; When is the hard kill screen?
dw $0999 ; Same but in BCD.
dw 998 ; If the last level lock isn't at x99, where is it?
dw 3600 ; How long does the staff roll last after the kill screen, in frames.
sCHILSpeedCurve::
@ -442,6 +446,8 @@ sCHILSpeedCurveSpecialData::
dw $FFFF ; When do blocks turn invisible?
dw 9999 ; When is the hard kill screen?
dw $9999 ; Same but in BCD.
dw 9998 ; If the last level lock isn't at x99, where is it?
dw $FFFF ; How long does the staff roll last after the kill screen, in frames.
sTGM3SpeedCurve::
@ -589,7 +595,7 @@ sTGM3SpeedCurve::
db 20, $00
db 7, 7, 8, 15, 6
dw $1200, 1200, $1300
dw $1200, 1200, $1299
db 20, $00
db 6, 6, 8, 15, 6
@ -598,9 +604,11 @@ sTGM3SpeedCurveEnd::
sTGM3SpeedCurveSpecialData::
dw $FFFF ; When do we get bones?
dw 1300 ; When do blocks turn invisible?
dw 1499 ; When is the hard kill screen?
dw $1499 ; Same but in BCD.
dw 1299 ; When do blocks turn invisible?
dw 1299 ; When is the hard kill screen?
dw $1299 ; Same but in BCD.
dw 1298 ; If the last level lock isn't at x99, where is it?
dw 3600 ; How long does the staff roll last after the kill screen, in frames.
sDEATSpeedCurve::
dw $0000, 0, $0100
@ -639,7 +647,7 @@ sDEATSpeedCurve::
db 20, $00
db 6, 6, 8, 15, 4
dw $0900, 900, $1000
dw $0900, 900, $0999
db 20, $00
db 6, 6, 8, 15, 4
@ -648,9 +656,11 @@ sDEATSpeedCurveEnd::
sDEATSpeedCurveSpecialData::
dw $FFFF ; When do we get bones?
dw 1000 ; When do blocks turn invisible?
dw 1199 ; When is the hard kill screen?
dw $1199 ; Same but in BCD.
dw 999 ; When do blocks turn invisible?
dw 999 ; When is the hard kill screen?
dw $0999 ; Same but in BCD.
dw 998 ; If the last level lock isn't at x99, where is it?
dw 3600 ; How long does the staff roll last after the kill screen, in frames.
sSHIRSpeedCurve::
@ -688,8 +698,10 @@ sSHIRSpeedCurveEnd::
sSHIRSpeedCurveSpecialData::
dw 900 ; When do we get bones?
dw 1300 ; When do blocks turn invisible?
dw 1499 ; When is the hard kill screen?
dw $1499 ; Same but in BCD.
dw 1300 ; When is the hard kill screen?
dw $1300 ; Same but in BCD.
dw $FFFF ; If the last level lock isn't at x99, where is it?
dw 3600 ; How long does the staff roll last after the kill screen, in frames.
sMYCOSpeedCurve::
@ -801,6 +813,8 @@ sMYCOSpeedCurveSpecialData::
dw $FFFF ; When do blocks turn invisible?
dw 300 ; When is the hard kill screen?
dw $0300 ; Same but in BCD.
dw $FFFF ; If the last level lock isn't at x99, where is it?
dw $FFFF ; How long does the staff roll last after the kill screen, in frames.
sSharedTiles::

BIN
src/res/sources/final.fur Normal file

Binary file not shown.

View File

@ -37,6 +37,11 @@ hPrePause: ds 1
hRequestedJingle: ds 1
SECTION "Gameplay Variables", WRAM0
wRollLine: ds 1
wInStaffRoll:: ds 1
SECTION "Gameplay Function Trampolines", ROM0
; Trampolines to the banked function.
SwitchToGameplay::
@ -118,6 +123,7 @@ SwitchToGameplayB:
; We don't start with hold spent.
xor a, a
ldh [hHoldSpent], a
ld [wInStaffRoll], a
; Leady mode.
ld a, MODE_LEADY
@ -147,7 +153,23 @@ SwitchToGameplayB:
; Main gameplay event loop.
GamePlayEventLoopHandlerB::
; Are we in staff roll?
ld a, [wInStaffRoll]
cp a, $FF
jr nz, .normalevent
; Are we in a non-game over mode?
ldh a, [hMode]
cp a, MODE_GAME_OVER
jr z, .normalevent
; Did we run out of time?
ld a, [wCountDownZero]
cp a, $FF
jp z, .preGameOverMode
; What mode are we in?
.normalevent
ld hl, .modejumps
ldh a, [hMode]
ld b, 0
@ -166,6 +188,7 @@ GamePlayEventLoopHandlerB::
jp .gameOverMode
jp .preGameOverMode
jp .pauseMode
jp .preRollMode
; Draw "READY" and wait a bit.
@ -174,6 +197,8 @@ GamePlayEventLoopHandlerB::
ldh a, [hModeCounter]
cp a, LEADY_TIME
jr nz, .firstleadyiterskip
xor a, a
ld [wInStaffRoll], a
call SFXKill
ld a, SFX_READYGO
call SFXEnqueue
@ -398,9 +423,24 @@ GamePlayEventLoopHandlerB::
ldh a, [hRemainingDelay]
cp a, 0
jp nz, .drawStaticInfo
ld a, [wInStaffRoll]
cp a, $FF
jr z, .next
ld a, [wShouldGoStaffRoll]
cp a, $FF
jr z, .goroll
.next
ld a, MODE_PREFETCHED_PIECE
ldh [hMode], a
jp .drawStaticInfo
.goroll
ld a, MODE_PREROLL
ldh [hMode], a
xor a, a
ld [wRollLine], a
ld a, 10
ldh [hModeCounter], a
jp .drawStaticInfo
.preGameOverMode
@ -561,6 +601,7 @@ GamePlayEventLoopHandlerB::
call GradeInit
xor a, a
ldh [hHoldSpent], a
ld [wInStaffRoll], a
ld a, MODE_LEADY
ldh [hMode], a
ld a, LEADY_TIME
@ -629,6 +670,54 @@ GamePlayEventLoopHandlerB::
call UnsafeMemCopy
; Prepare for staff roll.
.preRollMode
ldh a, [hModeCounter]
dec a
ldh [hModeCounter], a
jr nz, .drawStaticInfo
; Copy one more line onto the field.
ld b, 0
ld a, [wRollLine]
ld c, a
ld hl, sFinalChallenge
add hl, bc
ld d, h
ld e, l
ld hl, wField+(3*10)
add hl, bc
ld bc, 10
call UnsafeMemCopy
; Update the offset.
ld a, [wRollLine]
add a, 10
cp a, 210 ; Done?
jr z, .predone
ld [wRollLine], a
ld a, 10
ldh [hModeCounter], a
jr .drawStaticInfo
.predone
call FieldClear
call ToShadowField
ld a, MODE_PREFETCHED_PIECE
ldh [hMode], a
ld a, $FF
ld [wInStaffRoll], a
ldh a, [hNextPiece]
ldh [hCurrentPiece], a
call GetNextPiece
call SFXKill
ld hl, wStaffRollDuration
ld a, [hl+]
ld c, a
ld b, [hl]
call StartCountdown
; Always draw the score, level, next piece, and held piece.
.drawStaticInfo
ldh a, [hNextPiece]
@ -781,6 +870,7 @@ SwitchToGameplayBigB:
; We don't start with hold spent.
xor a, a
ldh [hHoldSpent], a
ld [wInStaffRoll], a
; Leady mode.
ld a, MODE_LEADY
@ -810,7 +900,23 @@ SwitchToGameplayBigB:
; Main gameplay event loop.
GamePlayBigEventLoopHandlerB:
; Are we in staff roll?
ld a, [wInStaffRoll]
cp a, $FF
jr nz, .normalevent
; Are we in a non-game over mode?
ldh a, [hMode]
cp a, MODE_GAME_OVER
jr z, .normalevent
; Did we run out of time?
ld a, [wCountDownZero]
cp a, $FF
jp z, .preGameOverMode
; What mode are we in?
.normalevent
ld hl, .modejumps
ldh a, [hMode]
ld b, 0
@ -829,6 +935,7 @@ GamePlayBigEventLoopHandlerB:
jp .gameOverMode
jp .preGameOverMode
jp .pauseMode
jp .preRollMode
; Draw "READY" and wait a bit.
@ -837,6 +944,8 @@ GamePlayBigEventLoopHandlerB:
ldh a, [hModeCounter]
cp a, LEADY_TIME
jr nz, .firstleadyiterskip
xor a, a
ld [wInStaffRoll], a
call SFXKill
ld a, SFX_READYGO
call SFXEnqueue
@ -1059,9 +1168,24 @@ GamePlayBigEventLoopHandlerB:
ldh a, [hRemainingDelay]
cp a, 0
jp nz, .drawStaticInfo
ld a, [wInStaffRoll]
cp a, $FF
jr z, .next
ld a, [wShouldGoStaffRoll]
cp a, $FF
jr z, .goroll
.next
ld a, MODE_PREFETCHED_PIECE
ldh [hMode], a
jp .drawStaticInfo
.goroll
ld a, MODE_PREROLL
ldh [hMode], a
xor a, a
ld [wRollLine], a
ld a, 10
ldh [hModeCounter], a
jp .drawStaticInfo
.preGameOverMode
@ -1223,6 +1347,7 @@ GamePlayBigEventLoopHandlerB:
call GradeInit
xor a, a
ldh [hHoldSpent], a
ld [wInStaffRoll], a
ld a, MODE_LEADY
ldh [hMode], a
ld a, LEADY_TIME
@ -1261,7 +1386,7 @@ GamePlayBigEventLoopHandlerB:
xor a, a
ldh [hLeftState], a
ldh [hRightState], a
jr .drawStaticInfo
jp .drawStaticInfo
; Draw PAUSE all over the field.
.nounpause
@ -1291,6 +1416,54 @@ GamePlayBigEventLoopHandlerB:
call UnsafeMemCopy
; Prepare for staff roll.
.preRollMode
ldh a, [hModeCounter]
dec a
ldh [hModeCounter], a
jr nz, .drawStaticInfo
; Copy one more line onto the field.
ld b, 0
ld a, [wRollLine]
ld c, a
ld hl, sBigFinalChallenge
add hl, bc
ld d, h
ld e, l
ld hl, wWideBlittedField+(1*10)
add hl, bc
ld bc, 10
call UnsafeMemCopy
; Update the offset.
ld a, [wRollLine]
add a, 10
cp a, 210 ; Done?
jr z, .predone
ld [wRollLine], a
ld a, 10
ldh [hModeCounter], a
jr .drawStaticInfo
.predone
call BigFieldClear
call BigToShadowField
ld a, MODE_PREFETCHED_PIECE
ldh [hMode], a
ld a, $FF
ld [wInStaffRoll], a
ldh a, [hNextPiece]
ldh [hCurrentPiece], a
call GetNextPiece
call SFXKill
ld hl, wStaffRollDuration
ld a, [hl+]
ld c, a
ld b, [hl]
call StartCountdown
; Always draw the score, level, next piece, and held piece.
.drawStaticInfo
ldh a, [hNextPiece]

View File

@ -31,6 +31,8 @@ SECTION "Time Variables", WRAM0
wMinutes:: ds 1
wSeconds:: ds 1
wFrames:: ds 1
wCountDown:: ds 2
wCountDownZero:: ds 1
SECTION "Time Data", ROM0
@ -57,11 +59,27 @@ TimeInit::
ld [wMinutes], a
ld [wSeconds], a
ld [wFrames], a
ld [wCountDown], a
ld [wCountDown+1], a
ld a , $FF
ld [wCountDownZero], a
ld a, TACF_262KHZ | TACF_START
ldh [rTAC], a
ret
; Set the countdown timer (in frames) to start at the number in BC.
StartCountdown::
xor a, a
ld [wCountDownZero], a
dec bc
ld a, c
ld [wCountDown], a
ld a, b
ld [wCountDown+1], a
ret
; Resets the minute-second timer.
ResetGameTime::
xor a, a
@ -119,6 +137,30 @@ HandleTimers::
ret z
cp a, MODE_PRE_GAME_OVER
ret z
; Get countdown in BC
ld a, [wCountDown]
ld c, a
ld a, [wCountDown+1]
ld b, a
; Is it zero?
or a, c
jr nz, .reduce
ld a , $FF
ld [wCountDownZero], a
jr .clock
.reduce
xor a, a
ld [wCountDownZero], a
dec bc
ld a, c
ld [wCountDown], a
ld a, b
ld [wCountDown+1], a
.clock
ld a, [wKillScreenActive]
cp a, $FF
ret z