Add more grading stuff. Again courtesy of CreeperCraftYT

This commit is contained in:
Randy Thiemann 2023-11-02 07:42:45 +01:00
parent 7b37de2bf3
commit 119756a90c
10 changed files with 2955 additions and 2433 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

487
src/grading.asm Normal file
View File

@ -0,0 +1,487 @@
; DMGTRIS
; Copyright (C) 2023 - Randy Thiemann <randy.thiemann@gmail.com>
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <https://www.gnu.org/licenses/>.
IF !DEF(GRADING_ASM)
DEF GRADING_ASM EQU 1
INCLUDE "globals.asm"
SECTION "Grade Variables", WRAM0
wDecayRate: ds 1
wGradePoints: ds 1
wInternalGrade: ds 1
wDisplayedGrade:: ds 1
wEffectTimer:: ds 1
wRankingDisqualified:: ds 1
SECTION "Grading Data", ROM0
; The Score Thresholds are 3/4th of the original ones.
sTGM1GradeScores:
dw $0003 ;00 — 8
dw $0006 ;00 — 7
dw $0009 ;00 — 6
dw $0015 ;00 — 5
dw $0021 ;00 — 4
dw $0039 ;00 — 3
dw $0060 ;00 — 2
dw $0090 ;00 — 1
dw $0120 ;00 — S1
dw $0165 ;00 — S2
dw $0225 ;00 — S3
dw $0300 ;00 — S4
dw $0390 ;00 — S5
dw $0495 ;00 — S6
dw $0615 ;00 — S7
dw $0750 ;00 — S8
dw $0900 ;00 — S9
sTGM3InternalGradeSystem:
db 125, 10, 20, 40, 50 ;Decay rate, (Internal grade points awarded for:) Single, Double, Triple, Tetris
db 80, 10, 20, 30, 40
db 80, 10, 20, 30, 40
db 50, 10, 15, 30, 40
db 45, 5, 15, 20, 40
db 45, 5, 15, 20, 30
db 45, 5, 10, 20, 30
db 40, 5, 10, 15, 30
db 40, 5, 10, 15, 30
db 40, 5, 10, 15, 30
db 40, 2, 12, 13, 30
db 40, 2, 12, 13, 30
db 30, 2, 12, 13, 30
db 30, 2, 12, 13, 30
db 30, 2, 12, 13, 30
db 20, 2, 12, 13, 30
db 20, 2, 12, 13, 30
db 20, 2, 12, 13, 30
db 20, 2, 12, 13, 30
db 20, 2, 12, 13, 30
db 15, 2, 12, 13, 30
db 15, 2, 12, 13, 30
db 15, 2, 12, 13, 30
db 15, 2, 12, 13, 30
db 15, 2, 12, 13, 30
db 15, 2, 12, 13, 30
db 15, 2, 12, 13, 30
db 15, 2, 12, 13, 30
db 15, 2, 12, 13, 30
db 15, 2, 12, 13, 30
db 10, 2, 12, 13, 30
db 10, 2, 12, 13, 30
sTGM3GradeBoosts:
db 0
db 1
db 2
db 3
db 4
db 5
db 5
db 6
db 6
db 7
db 7
db 7
db 8
db 8
db 8
db 9
db 9
db 10
db 11
db 12
db 12
db 12
db 13
db 13
db 14
db 14
db 15
db 15
db 16
db 16
db 17
; sTGM3ComboMultipliers:
; db 1, 1.0, 1.0, 1.0, 1.0 ; Combo size, (Multiplier for: ) Single, Double, Triple, Tetris
; db 2, 1.0, 1.2, 1.4, 1.5
; db 3, 1.0, 1.2, 1.5, 1.8
; db 4, 1.0, 1.4, 1.6, 2.0
; db 5, 1.0, 1.4, 1.7, 2.2
; db 6, 1.0, 1.4, 1.8, 2.3
; db 7, 1.0, 1.4, 1.9, 2.4
; db 8, 1.0, 1.5, 2.0, 2.5
; db 9, 1.0, 1.5, 2.1, 2.6
; db 10, 2.0, 2.5, 3.0, 3.0
sTGM3LevelMultiplier:
db 1 ; 000-249
db 2 ; 250-499
db 3 ; 500-749
db 4 ; 750-999
sTGM3BaselineCOOL:
db 52 ;070 (value in seconds)
db 52 ;170
db 49 ;270
db 45 ;370
db 45 ;470
db 42 ;570
db 42 ;670
db 38 ;770
db 38 ;870
sTGM3REGRETConditions:
db 1, 30 ;minutes, seconds
db 1, 15
db 1, 15
db 1, 8
db 1, 0
db 1, 0
db 0, 50
db 0, 50
db 0, 50
db 0, 50
SECTION "Grading Functions", ROM0
; Wipe the grading variables.
GradeInit::
xor a, a
ld [wDecayRate], a
ld [wGradePoints], a
ld [wInternalGrade], a
ld [wDisplayedGrade], a
ld [wRankingDisqualified], a
ld [wEffectTimer], a
; Not all modes start at 9.
; Death starts ungraded.
ld a, [wSpeedCurveState]
cp a, SCURVE_DEAT
jr nz, .notdeat
ld a, GRADE_NONE
ld [wDisplayedGrade], a
jr UpdateGrade
.notdeat
; Shirase starts ungraded.
ld a, [wSpeedCurveState]
cp a, SCURVE_SHIR
jr nz, .notshir
ld a, GRADE_NONE
ld [wDisplayedGrade], a
jr UpdateGrade
.notshir
; All the rest start at 9.
ld a, GRADE_9
ld [wDisplayedGrade], a
jr UpdateGrade
; Jumps to the grade update function for the current mode.
UpdateGrade::
ld hl, .gradejumptable
ld a, [wSpeedCurveState]
ld b, a
add a, b
add a, b
ld b, 0
ld c, a
add hl, bc
jp hl
.gradejumptable
jp UpdateGradeTGM1 ;DMGT
jp UpdateGradeTGM1 ;TGM1
jp UpdateGradeTGM1 ;TGM3
jp UpdateGradeDEAT ;DEAT
jp UpdateGradeSHIR ;SHIR
jp UpdateGradeTGM1 ;CHIL
; Get the four most significant figures of the score in BC as BCD.
PrepareScore:
ld a, [hScore+3]
ld b, a
ld a, [hScore+2]
swap a
or b
ld c, a
ld a, [hScore+1]
ld b, a
ld a, [hScore]
swap a
or b
ld b, a
ret
UpdateGradeTGM1:
; Bail if we're already GM.
ld a, [wDisplayedGrade]
cp a, GRADE_GM
ret z
; Skip to GM check if already S9.
cp a, GRADE_S9
jr nc, .maybegm
.trygradeup
; Otherwise, check if we can increase the grade.
; Get our score into BC
call PrepareScore
; Double our current grade and use it as an offset into the scoring table.
ld a, [wDisplayedGrade]
add a
ld d, 0
ld e, a
; Have HL point to the next required score and get it into DE.
ld hl, sTGM1GradeScores
add hl, de
; LSB
ld a, [hl+]
ld e, a
; MSB
ld a, [hl]
ld d, a
; Check if BC >= DE...
; Return if B < D.
ld a, b
cp a, d
ret c
; We can confidently increase the grade if B > D.
jr nz, .increasegrade
; If B == D, we need to check C and E...
; Return if C < E. Otherwise increase the grade.
ld a, c
cp a, e
ret c
.increasegrade
; Add 1 to the grade.
ld a, [wDisplayedGrade]
inc a
ld [wDisplayedGrade], a
; Play the jingle, if not already doing so.
ldh a, [hCurrentlyPlaying]
cp a, SFX_RANKUP
jr z, .skipjingle
ld a, SFX_RANKUP
call SFXEnqueue
; Prepare the effect stuff
.skipjingle
ld a, $0F
ld [wEffectTimer], a
; Loop and see if we can increment more grades.
ld a, [wDisplayedGrade]
cp a, GRADE_S9 ; Don't go past S9.
ret z
jr .trygradeup
.maybegm
; Level needs to be 1000 or greater.
ld a, [hCLevel] ; Level, thousands digit.
cp a, 1
ret c
; Set the grade to GM
ld a, GRADE_GM
ld [wDisplayedGrade], a
; Sound effect
ld a, SFX_RANKGM
jp SFXEnqueue
; Prepare the effect stuff
ld a, $0F
ld [wEffectTimer], a
; Return
ret
UpdateGradeDEAT:
; If we're disqualified, don't update the grade.
ld a, [wRankingDisqualified]
cp a, $FF
ret z
; If we are already GM, don't do anything.
ld a, [wDisplayedGrade]
cp a, GRADE_GM
ret z
.notgm
; If we're M, check if we should be GM.
cp a, GRADE_M
jr nz, .notm
; We should be GM if we're at or past level 1000.
ldh a, [hCLevel] ; Level, thousands digit.
cp a, 1
ret c ; If less than 1000, return.
; Otherwise give the grade!
ld a, GRADE_GM
ld [wDisplayedGrade], a
; Play the jingle.
ld a, SFX_RANKGM
call SFXEnqueue
; Prepare the effect stuff
ld a, $0F
ld [wEffectTimer], a
ret
.notm
; If we're not M, check if we should be M.
ldh a, [hCLevel+1] ; Level, hundreds digit.
cp a, 5
ret c ; If less than 500, return.
; There's a 3:25 torikan for M.
ld b, 3
ld c, 25
call CheckTorikan
; If we failed the Torikan, disqualify from ranking.
cp a, $FF
jr nz, .disqualify
; Otherwise award M.
ld a, GRADE_M
ld [wDisplayedGrade], a
; Play the jingle.
ld a, SFX_RANKUP
call SFXEnqueue
; Prepare the effect stuff
ld a, $0F
ld [wEffectTimer], a
ret
.disqualify
; Disqualify from ranking.
ld a, $FF
ld [wRankingDisqualified], a
ret
UpdateGradeSHIR:
; If we're disqualified, don't update the grade any higher.
ld a, [wRankingDisqualified]
cp a, $FF
ret z
; If we are already GM, don't do anything.
ld a, [wDisplayedGrade]
cp a, GRADE_S13
ret z
; We don't give out a grade until level 100.
ldh a, [hCLevel+1] ; Level, hundreds digit.
cp a, 0
ret z
; Get the hundreds and thousands of the level as a hex number.
ld b, a ; Hundreds
ldh a, [hCLevel] ; Thousands
swap a
or b
; Convert the BCD to hex.
ld c, a ; C = A
and a, $F0 ; A = A & $F0. A is now $00 to $90 if the number was correct BCD.
srl a ; A = A >> 1
ld b, a ; B = A
srl a
srl a ; A = A >> 2
add a, b ; A += B
ld b, a ; B = A. At this point B is 10, 20, 30, ... 90.
ld a, c ; A = C
and a, $0F ; A = A & $0F. A is now $00 to $09 if the number was correct BCD.
add a, b ; Adding B to A gives us the converted number.
; Adding GRADE_1 to this will give us the grade.
add a, GRADE_1
ld b, a
ld a, [wDisplayedGrade]
cp a, b
ret z ; If the grade is already correct, return.
ld [wDisplayedGrade], a ; Otherwise, set the grade.
; Play the jingle.
ld a, SFX_RANKUP
call SFXEnqueue
; Prepare the effect stuff
ld a, $0F
ld [wEffectTimer], a
; There's a few torikans for Shirase.
ld a, [wDisplayedGrade]
.s5torikan
cp a, GRADE_S5
jr nz, .s10torikan
; There's a 2:28 torikan after S5.
ld b, 2
ld c, 28
call CheckTorikan
; If we failed the Torikan, disqualify from ranking up further.
cp a, $FF
jr nz, .disqualify
ret
.s10torikan
cp a, GRADE_S10
ret nz
; There's a 4:56 torikan after S10.
ld b, 4
ld c, 56
call CheckTorikan
; If we failed the Torikan, disqualify from ranking up further.
cp a, $FF
jr nz, .disqualify
ret
.disqualify
ld a, $FF
ld [wRankingDisqualified], a
ret
ENDC

View File

@ -1,164 +0,0 @@
; DMGTRIS
; Copyright (C) 2023 - Randy Thiemann <randy.thiemann@gmail.com>
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <https://www.gnu.org/licenses/>.
IF !DEF(GRADING_SYSTEMS_ASM)
DEF GRADING_SYSTEMS_ASM EQU 1
INCLUDE "globals.asm"
SECTION "Grade Variables", WRAM0
wDecayRate: ds 1
wGradePoints: ds 1
wInternalGrade: ds 1
wDisplayedGrade:: ds 1
SECTION "Grading Data", ROM0
sGradeScores:
dw $0004 ;00 — 8
dw $0008 ;00 — 7
dw $0014 ;00 — 6
dw $0020 ;00 — 5
dw $0035 ;00 — 4
dw $0055 ;00 — 3
dw $0080 ;00 — 2
dw $0120 ;00 — 1
dw $0160 ;00 — S1
dw $0220 ;00 — S2
dw $0300 ;00 — S3
dw $0400 ;00 — S4
dw $0520 ;00 — S5
dw $0660 ;00 — S6
dw $0820 ;00 — S7
dw $1000 ;00 — S8
dw $1200 ;00 — S9
SECTION "Grading Functions", ROM0
; Wipe the grading variables.
GradeInit::
xor a, a
ld [wDecayRate], a
ld [wGradePoints], a
ld [wInternalGrade], a
ld [wDisplayedGrade], a
ret
; Gets the highest grade the player qualifies for.
UpdateGrade::
; Skip to GM check if past S9.
ld a, [wDisplayedGrade]
cp a, GRADE_S9
jr c, .trygradeup
jr CheckForGM
.trygradeup
; Get our score into BC
call PrepareScore
; Double our current grade and use it as an offset into the scoring table.
ld a, [wDisplayedGrade]
add a
ld d, 0
ld e, a
; Have HL point to the next required score and get it into DE.
ld hl, sGradeScores
add hl, de
; LSB
ld a, [hl+]
ld e, a
; MSB
ld a, [hl]
ld d, a
; Check if BC >= DE...
; Return if B < D.
ld a, b
cp a, d
ret c
; We can confidently increase the grade if B > D.
jr nz, .increasegrade
; If B == D, we need to check C and E...
; Return if C < E. Otherwise increase the grade.
ld a, c
cp a, e
ret c
.increasegrade
; Add 1 to the grade.
ld a, [wDisplayedGrade]
inc a
ld [wDisplayedGrade], a
; Play the jingle.
ld a, SFX_RANKUP
call SFXEnqueue
; Loop and see if we can increment more grades.
ld a, [wDisplayedGrade]
cp a, GRADE_S9
ret z
jr .trygradeup
CheckForGM:
; Grade has to be S9.
ld a, [wDisplayedGrade]
cp a, GRADE_S9
ret nz
; Level needs to be 1000 or greater.
ld a, [hCLevel]
cp a, 1
ret c
; Set the grade to GM
ld a, GRADE_GM
ld [wDisplayedGrade], a
; Sound effect
ld a, SFX_RANKGM
jp SFXEnqueue
; Get the four most significant figures of the score in BC as BCD.
PrepareScore:
ld a, [hScore+3]
ld b, a
ld a, [hScore+2]
swap a
or b
ld c, a
ld a, [hScore+1]
ld b, a
ld a, [hScore]
swap a
or b
ld b, a
ret
ENDC

View File

@ -326,6 +326,25 @@ DEF GRADE_S6 EQU 14
DEF GRADE_S7 EQU 15
DEF GRADE_S8 EQU 16
DEF GRADE_S9 EQU 17
DEF GRADE_GM EQU 18
DEF GRADE_S10 EQU 18
DEF GRADE_S11 EQU 19
DEF GRADE_S12 EQU 20
DEF GRADE_S13 EQU 21
DEF GRADE_M1 EQU 22
DEF GRADE_M2 EQU 23
DEF GRADE_M3 EQU 24
DEF GRADE_M4 EQU 25
DEF GRADE_M5 EQU 26
DEF GRADE_M6 EQU 27
DEF GRADE_M7 EQU 28
DEF GRADE_M8 EQU 29
DEF GRADE_M9 EQU 30
DEF GRADE_M EQU 31
DEF GRADE_MK EQU 32
DEF GRADE_MV EQU 33
DEF GRADE_MO EQU 34
DEF GRADE_MM EQU 35
DEF GRADE_GM EQU 36
DEF GRADE_NONE EQU 37
ENDC

View File

@ -615,20 +615,44 @@ GradeRendering::
add a, $8
ld [wGrade1+1], a
; Set the palette of the grade objects.
ld a, $7
ld [wGrade0+3], a
ld [wGrade1+3], a
; Set the grades to blank
ld a, $1
ld a, TILE_BLANK
ld [wGrade0+2], a
ld [wGrade1+2], a
; Is the grade S1 or better?
; If our grade is GRADE_NONE, we don't need to do anything else.
ld a, [wDisplayedGrade]
cp a, GRADE_NONE
ret z
; If the effect timer is greater than 0, decrement it and do some palette magic.
ld a, [wEffectTimer]
cp a, 0
jr z, .noeffect
dec a
ld [wEffectTimer], a
; Cycle the palette of the grade objects.
.effect
ld a, [wGrade0+3]
inc a
and a, OAMF_PALMASK
or a, OAMF_PAL1
ld [wGrade0+3], a
ld [wGrade1+3], a
jr .drawgrade
; Set the palette of the grade objects to the normal palette.
.noeffect
ld a, 7 | OAMF_PAL1
ld [wGrade0+3], a
ld [wGrade1+3], a
; Do we draw this as a regular grade?
.drawgrade
ld a, [wDisplayedGrade]
cp a, GRADE_S1
jr nc, .sgrade
jr nc, .sgrade ; No. S or better.
.regulargrade
; Draw as a regular grade.
@ -639,9 +663,9 @@ GradeRendering::
ret
.sgrade
; Is the grade a GM?
cp a, GRADE_GM
jr z, .gmgrade
; Is the grade M1 or better?
cp a, GRADE_M1
jr nc, .mgrade
; Draw as S grade.
ld a, "S"
@ -654,6 +678,63 @@ GradeRendering::
ld [wGrade1+2], a
ret
.mgrade
; Is the grade one of the letter grades?
cp a, GRADE_M
jr nc, .lettergrade
; Draw as M grade.
ld a, "M"
ld [wGrade0+2], a
ld a, [wDisplayedGrade]
sub a, GRADE_M1
ld b, a
ld a, "1"
add a, b
ld [wGrade1+2], a
ret
.lettergrade
; Is the grade GM?
cp a, GRADE_GM
jr z, .gmgrade
; Draw as MX grade.
ld a, "M"
ld [wGrade0+2], a
ld a, [wDisplayedGrade]
cp a, GRADE_M
ret z ; No second letter for M.
; Otherwise jump to the right letter.
cp a, GRADE_MK
jr z, .mk
cp a, GRADE_MV
jr z, .mv
cp a, GRADE_MO
jr z, .mo
jr .mm
.mk
ld a, "K"
ld [wGrade1+2], a
ret
.mv
ld a, "V"
ld [wGrade1+2], a
ret
.mo
ld a, "O"
ld [wGrade1+2], a
ret
.mm
ld a, "M"
ld [wGrade1+2], a
ret
.gmgrade
; Draw as GM grade.
ld a, "G"

View File

@ -225,6 +225,7 @@ GamePlayEventLoopHandlerB::
ldh a, [hNextPiece]
ldh [hCurrentPiece], a
call GetNextPiece
call ResetGameTime
jp .drawStaticInfo
@ -848,6 +849,7 @@ GamePlayBigEventLoopHandlerB:
ldh a, [hNextPiece]
ldh [hCurrentPiece], a
call GetNextPiece
call ResetGameTime
jp .drawStaticInfo

View File

@ -49,13 +49,46 @@ TimeInit::
; Resets the minute-second timer.
ResetTime::
ResetGameTime::
xor a, a
ld [wMinutes], a
ld [wSeconds], a
ld [wFrames], a
ret
; Checks if the minute-second timer has reached a certain value.
; Call with max minutes in B and max seconds in C.
; A will be $FF if the torikan has succeeded, and $00 otherwise.
CheckTorikan::
; Okay if minutes are less than max minutes.
ld a, [wMinutes]
cp a, b
jr c, .success
; Check seconds if minutes are equal.
jr nz, .failure
; Okay if seconds are less than max seconds.
ld a, [wSeconds]
cp a, c
jr c, .success
; Check frames if seconds are equal.
jr nz, .failure
; Okay if frames are exactly 0.
ld a, [wFrames]
cp a, 0
jr z, .success
.failure
xor a, a
ret
.success
ld a, $FF
ret
; Increments the global timer. Also saves whether we're on an even frame.
HandleTimers::