Compare commits

...

2 Commits

Author SHA1 Message Date
Randy Thiemann a4f41eee1f Release. 2023-10-24 14:38:19 +02:00
Randy Thiemann f46488e19d Redo SFX engine & speed curves. 2023-10-24 13:35:51 +02:00
11 changed files with 1749 additions and 386 deletions

Binary file not shown.

View File

@ -35,7 +35,7 @@ Select the rotation rules:
Select whether up performs a sonic drop, a hard drop, or nothing at all.
### Speed Curve
Check back later! For now you're stuck with the default.
Select between several speed curves including the DMGTRIS default speed curve, TGM1, 2, and 3, as well as DEATH and SHIRASE mode. Note that all modes use the same scoring and they are all infinite.
### Always 20G
Whether you want instant-drop gravity to be active at any level.
@ -51,7 +51,7 @@ After each piece is dropped, a check is made:
Combo is reset to 1 and no points are awarded.
### Lines were cleared
Lines = Lines cleared. In TGM3 modes, 3 lines are worth 4, and 4 lines are worth 6.
Lines = Lines cleared.
Level = The level before the lines were cleared.
@ -102,11 +102,6 @@ The game can be built using gnu make and the RGBDS toolchain.
- In very rare cases the frame time in TGM3 and TGW3 modes can be exceeded due to the way the RNG for those modes works. When this happens, the screen will appear slightly glitched for 1 frame but no frame drops will occur. This issues is fundamentally impossible to completely avoid though more optimization may cause it to occur less frequently.
## Future Goals
- Implement better sound engine.
- Add more speed curves.
## License
Copyright (C) 2023 - Randy Thiemann <randy.thiemann@gmail.com>

View File

@ -71,24 +71,6 @@ sGo:: db " GO "
sPause::
db "P A U S E "
db " P A U S E"
db "P A U S E "
db " P A U S E"
db "P A U S E "
db " P A U S E"
db "P A U S E "
db " P A U S E"
db "P A U S E "
db " P A U S E"
db "P A U S E "
db " P A U S E"
db "P A U S E "
db " P A U S E"
db "P A U S E "
db " P A U S E"
db "P A U S E "
db " P A U S E"
db "P A U S E "
db " P A U S E"
sOption0::
db "NORM"
db " INV"
@ -107,6 +89,11 @@ sOption3::
db "NONE"
sOption4::
db "DMGT"
db "TGM1"
db "TGM2"
db "TGM3"
db "DEAT"
db "SHIR"
sOption5::
db " NO"
db " YES"
@ -136,6 +123,388 @@ sPieceYOffsets:: ; How to draw each piece. Y-offsets of the sprites.
db 0, 7, 0, 7 ; O
db 0, 0, 7, 0 ; T
sTGM1SpeedCurve::
dw $0000, 0, $0100
db 1, 64
db 30, 16, 30, 41
dw $0030, 30, $0100
db 1, 42
db 30, 16, 30, 41
dw $0035, 35, $0100
db 1, 32
db 30, 16, 30, 41
dw $0040, 40, $0100
db 1, 25
db 30, 16, 30, 41
dw $0060, 60, $0100
db 1, 16
db 30, 16, 30, 41
dw $0070, 70, $0100
db 1, 8
db 30, 16, 30, 41
dw $0080, 80, $0100
db 1, 5
db 30, 16, 30, 41
dw $0100, 100, $0200
db 1, 3
db 30, 16, 30, 41
dw $0160, 160, $0200
db 1, 2
db 30, 16, 30, 41
dw $0200, 200, $0300
db 1, 64
db 30, 16, 30, 41
dw $0220, 220, $0300
db 1, 8
db 30, 16, 30, 41
dw $0230, 230, $0300
db 1, 4
db 30, 16, 30, 41
dw $0233, 233, $0300
db 1, 3
db 30, 16, 30, 41
dw $0236, 236, $0300
db 1, 2
db 30, 16, 30, 41
dw $0251, 251, $0300
db 1, 1
db 30, 16, 30, 41
dw $0300, 300, $0400
db 2, 1
db 30, 16, 30, 41
dw $0330, 330, $0400
db 3, 1
db 30, 16, 30, 41
dw $0360, 360, $0400
db 4, 1
db 30, 16, 30, 41
dw $0400, 400, $0500
db 5, 1
db 30, 16, 30, 41
dw $0420, 420, $0500
db 4, 1
db 30, 16, 30, 41
dw $0450, 450, $0500
db 3, 1
db 30, 16, 30, 41
dw $0500, 500, $0600
db 20, 1
db 30, 16, 30, 41
sTGM1SpeedCurveEnd::
dw $FFFF
sTGM2SpeedCurve::
dw $0000, 0, $0100
db 1, 64
db 27, 16, 30, 40
dw $0030, 30, $0100
db 1, 42
db 27, 16, 30, 40
dw $0035, 35, $0100
db 1, 32
db 27, 16, 30, 40
dw $0040, 40, $0100
db 1, 25
db 27, 16, 30, 40
dw $0060, 60, $0100
db 1, 16
db 27, 16, 30, 40
dw $0070, 70, $0100
db 1, 8
db 27, 16, 30, 40
dw $0080, 80, $0100
db 1, 5
db 27, 16, 30, 40
dw $0100, 100, $0200
db 1, 3
db 27, 16, 30, 40
dw $0160, 160, $0200
db 1, 2
db 27, 16, 30, 40
dw $0200, 200, $0300
db 1, 64
db 27, 16, 30, 40
dw $0220, 220, $0300
db 1, 8
db 27, 16, 30, 40
dw $0230, 230, $0300
db 1, 4
db 27, 16, 30, 40
dw $0233, 233, $0300
db 1, 3
db 27, 16, 30, 40
dw $0236, 236, $0300
db 1, 2
db 27, 16, 30, 40
dw $0251, 251, $0300
db 1, 1
db 27, 16, 30, 40
dw $0300, 300, $0400
db 2, 1
db 27, 16, 30, 40
dw $0330, 330, $0400
db 3, 1
db 27, 16, 30, 40
dw $0360, 360, $0400
db 4, 1
db 27, 16, 30, 40
dw $0400, 400, $0500
db 5, 1
db 27, 16, 30, 40
dw $0420, 420, $0500
db 4, 1
db 27, 16, 30, 40
dw $0450, 450, $0500
db 3, 1
db 27, 16, 30, 40
dw $0500, 500, $0600
db 20, 1
db 27, 10, 30, 25
dw $0601, 601, $0700
db 20, 1
db 27, 10, 30, 7
dw $0701, 701, $0800
db 20, 1
db 18, 10, 30, 7
dw $0801, 801, $0900
db 20, 1
db 14, 10, 30, 1
dw $0901, 901, $1000
db 20, 1
db 14, 6, 18, 1
sTGM2SpeedCurveEnd::
dw $FFFF
sTGM3SpeedCurve::
dw $0000, 0, $0100
db 1, 64
db 27, 16, 30, 40
dw $0030, 30, $0100
db 1, 42
db 27, 16, 30, 40
dw $0035, 35, $0100
db 1, 32
db 27, 16, 30, 40
dw $0040, 40, $0100
db 1, 25
db 27, 16, 30, 40
dw $0060, 60, $0100
db 1, 16
db 27, 16, 30, 40
dw $0070, 70, $0100
db 1, 8
db 27, 16, 30, 40
dw $0080, 80, $0100
db 1, 5
db 27, 16, 30, 40
dw $0100, 100, $0200
db 1, 3
db 27, 16, 30, 40
dw $0160, 160, $0200
db 1, 2
db 27, 16, 30, 40
dw $0200, 200, $0300
db 1, 64
db 27, 16, 30, 40
dw $0220, 220, $0300
db 1, 8
db 27, 16, 30, 40
dw $0230, 230, $0300
db 1, 4
db 27, 16, 30, 40
dw $0233, 233, $0300
db 1, 3
db 27, 16, 30, 40
dw $0236, 236, $0300
db 1, 2
db 27, 16, 30, 40
dw $0251, 251, $0300
db 1, 1
db 27, 16, 30, 40
dw $0300, 300, $0400
db 2, 1
db 27, 16, 30, 40
dw $0330, 330, $0400
db 3, 1
db 27, 16, 30, 40
dw $0360, 360, $0400
db 4, 1
db 27, 16, 30, 40
dw $0400, 400, $0500
db 5, 1
db 27, 16, 30, 40
dw $0420, 420, $0500
db 4, 1
db 27, 16, 30, 40
dw $0450, 450, $0500
db 3, 1
db 27, 16, 30, 40
dw $0500, 500, $0600
db 20, 1
db 27, 10, 30, 25
dw $0600, 600, $0700
db 20, 1
db 27, 10, 30, 7
dw $0700, 700, $0800
db 20, 1
db 18, 10, 30, 7
dw $0800, 800, $0900
db 20, 1
db 14, 10, 30, 1
dw $0900, 900, $1000
db 20, 1
db 14, 8, 18, 1
dw $1000, 1000, $1100
db 20, 1
db 8, 8, 18, 6
dw $1100, 1000, $1200
db 20, 1
db 7, 8, 14, 6
dw $1200, 1000, $1300
db 20, 1
db 6, 8, 14, 6
sTGM3SpeedCurveEnd::
dw $FFFF
sDEATSpeedCurve::
dw $0000, 0, $0100
db 20, 1
db 18, 12, 30, 12
dw $0100, 0, $0200
db 20, 1
db 14, 12, 25, 1
dw $0200, 0, $0300
db 20, 1
db 14, 11, 20, 1
dw $0300, 0, $0400
db 20, 1
db 8, 10, 18, 6
dw $0400, 0, $0500
db 20, 1
db 7, 8, 14, 5
dw $0500, 0, $0600
db 20, 1
db 6, 8, 14, 4
sDEATSpeedCurveEnd::
dw $FFFF
sSHIRSpeedCurve::
dw $0000, 0, $0100
db 20, 1
db 12, 10, 18, 6
dw $0100, 100, $0200
db 20, 1
db 12, 8, 18, 5
dw $0200, 200, $0300
db 20, 1
db 12, 8, 16, 4
dw $0300, 300, $0400
db 20, 1
db 6, 8, 14, 4
dw $0500, 500, $0600
db 20, 1
db 6, 6, 12, 2
dw $1100, 1100, $1200
db 20, 1
db 6, 6, 10, 2
dw $1200, 1200, $1300
db 20, 1
db 6, 6, 8, 2
sSHIRSpeedCurveEnd::
dw $FFFF
sSpeedCurve:: ; Speed curve of the game.
dw $0000, 0, $0100 ; Level 0000
db 1, 16 ; 1G every 16 frames

View File

@ -1255,6 +1255,9 @@ FieldProcess::
ldh [hCurrentPieceY], a
xor a, a
ldh [hCurrentLockDelayRemaining], a
ldh a, [hCurrentGravityPerTick]
cp a, 1
jp nz, .draw
call SFXKill
ld a, SFX_LOCK
call SFXEnqueue
@ -1339,8 +1342,11 @@ FieldProcess::
.playfirmdropsound
ldh a, [hCurrentLockDelay]
ldh [hCurrentLockDelayRemaining], a
ldh a, [hCurrentGravityPerTick]
cp a, 1
jr nz, .postcheckforfirmdropsound
call SFXKill
ld a, SFX_MOVE
ld a, SFX_LAND
call SFXEnqueue
; If the down button is held, lock.
@ -1385,6 +1391,9 @@ FieldProcess::
; Play the locking sound and draw the piece.
.dolock
ldh a, [hCurrentGravityPerTick]
cp a, 1
jr nz, .draw
call SFXKill
ld a, SFX_LOCK
call SFXEnqueue
@ -1812,27 +1821,6 @@ FieldDelay::
jr nz, :-
ldh [hBravo], a
; Check if we are in a TGM3 mode and thus need to handle line counts of 3 and 4 differently.
ldh a, [hLineClearCt]
ld e, a
ld a, [wRotModeState]
cp a, ROT_MODE_ARSTI
jr z, .modifylines
jr .applylines
.modifylines
ldh a, [hLineClearCt]
cp a, 1
jr z, .applylines
cp a, 2
jr z, .applylines
cp a, 3
jr z, .addone
inc a
.addone
inc a
ld e, a
ldh [hLineClearCt], a
; Increment the level counter by the amount of lines.
.applylines
call LevelUp
@ -1915,11 +1903,14 @@ FieldDelay::
ret nz
call ClearLines
ldh a, [hCurrentGravityPerTick]
cp a, 1
jr nz, :+
call SFXKill
ld a, SFX_DROP
ld a, SFX_LINE_CLEAR
call SFXEnqueue
ldh a, [hCurrentARE]
: ldh a, [hCurrentARE]
ldh [hRemainingDelay], a

View File

@ -130,15 +130,15 @@ DEF PIECE_O EQU 5
DEF PIECE_T EQU 6
DEF PIECE_NONE EQU 255
DEF SFX_IRS EQU 7
DEF SFX_DROP EQU 8
DEF SFX_LOCK EQU 9
DEF SFX_BELL EQU 10
DEF SFX_MOVE EQU 11
DEF SFX_RANK_UP EQU 12
DEF SFX_LEVEL_UP EQU 13
DEF SFX_IHS EQU 14
DEF SFX_READY_GO EQU 15
DEF SFX_IRS EQU $80
DEF SFX_IHS EQU 10
DEF SFX_LINE_CLEAR EQU 11
DEF SFX_LAND EQU 12
DEF SFX_LOCK EQU 13
DEF SFX_LEVELLOCK EQU 14
DEF SFX_LEVELUP EQU 15
DEF SFX_RANKUP EQU 16
DEF SFX_READYGO EQU 17
DEF STACK_SIZE EQU 64
DEF GAME_OVER_R10 EQU 133
@ -172,7 +172,12 @@ DEF DROP_MODE_NONE EQU 2
DEF DROP_MODE_COUNT EQU 3
DEF SCURVE_DMGT EQU 0
DEF SCURVE_COUNT EQU 1
DEF SCURVE_TGM1 EQU 1
DEF SCURVE_TGM2 EQU 2
DEF SCURVE_TGM3 EQU 3
DEF SCURVE_DEAT EQU 4
DEF SCURVE_SHIR EQU 5
DEF SCURVE_COUNT EQU 6
DEF TILE_HIG_MODE_BASE EQU 232
DEF HIG_MODE_OFF EQU 0

View File

@ -192,7 +192,7 @@ LevelUp::
ldh [hCLevel+2], a
ldh [hCLevel+3], a
call DoSpeedUp
ld a, SFX_RANK_UP
ld a, SFX_RANKUP
call SFXEnqueue
ret
@ -221,7 +221,7 @@ LevelUp::
jr nz, .checkspeedup
ld a, $FF
ldh [hRequiresLineClear], a
ld a, SFX_BELL
ld a, SFX_LEVELLOCK
call SFXEnqueue
jr .leveljinglemaybe
@ -257,7 +257,7 @@ LevelUp::
jr nz, .leveljinglemaybe
ld a, $FF
ldh [hRequiresLineClear], a
ld a, SFX_BELL
ld a, SFX_LEVELLOCK
call SFXEnqueue
.leveljinglemaybe
@ -266,7 +266,7 @@ LevelUp::
ldh a, [hCLevel+1]
cp a, b
jr z, .checkspeedup
ld a, SFX_LEVEL_UP
ld a, SFX_LEVELUP
call SFXEnqueue
.checkspeedup

View File

@ -187,7 +187,6 @@ sfx_names = [
"sSFXLevelLock",
"sSFXLevelUp",
"sSFXRankUp",
"sSFXIHS",
"sSFXReadyGo",
]

View File

@ -185,7 +185,7 @@ IncreaseScore::
; If it has, reset the score.
xor a, a
ldh [hScore], a
ld a, SFX_RANK_UP
ld a, SFX_RANKUP
call SFXEnqueue
ret

File diff suppressed because it is too large Load Diff

View File

@ -41,10 +41,10 @@ hCurrentPieceY:: ds 1
hCurrentPieceRotationState:: ds 1
hHeldPiece:: ds 1
hHoldSpent:: ds 1
hSkipJingle: ds 1
hMode: ds 1
hModeCounter: ds 1
hPrePause: ds 1
hRequestedJingle: ds 1
SECTION "Gameplay Functions", ROM0
@ -158,7 +158,7 @@ leadyMode:
cp a, LEADY_TIME
jr nz, :+
call SFXKill
ld a, SFX_READY_GO
ld a, SFX_READYGO
call SFXEnqueue
ldh a, [hModeCounter]
: dec a
@ -205,12 +205,13 @@ postGoMode:
; Fetch the next piece.
prefetchedPieceMode:
; A piece will spawn in the middle, at the top of the screen, not rotated by default.
ld a, $FF
ldh [hRequestedJingle], a
ld a, 5
ldh [hCurrentPieceX], a
ld a, 3
ldh [hCurrentPieceY], a
xor a, a
ldh [hSkipJingle], a
ldh [hCurrentPieceRotationState], a
ldh [hHoldSpent], a
@ -219,10 +220,14 @@ prefetchedPieceMode:
.checkIHS
ldh a, [hSelectState]
cp a, 0
jr z, .checkIRSA
jr z, .loaddefaultjingle
call DoHold
; Holding does its own IRS check.
jr .checkJingle
jr .postjingle
; Enqueue the jingle.
.loaddefaultjingle
ldh a, [hNextPiece]
ldh [hRequestedJingle], a
; Check if IRS is requested.
; Apply the rotation if so.
@ -246,8 +251,12 @@ prefetchedPieceMode:
.cp1
ld a, 3
ldh [hCurrentPieceRotationState], a
ldh a, [hNextPiece]
ld b, a
ld a, SFX_IRS
call SFXEnqueue
or a, b
ldh [hRequestedJingle], a
jr .postjingle
.checkIRSB
ld a, [wSwapABState]
@ -256,33 +265,27 @@ prefetchedPieceMode:
.lda2
ldh a, [hAState]
cp a, 0
jr z, .checkJingle
jr z, .postjingle
ld a, $FF
ldh [hAState], a
jr .cp2
.ldb2
ldh a, [hBState]
cp a, 0
jr z, .checkJingle
jr z, .postjingle
ld a, $FF
ldh [hBState], a
.cp2
ld a, 1
ldh [hCurrentPieceRotationState], a
ld a, SFX_IRS
call SFXEnqueue
.checkJingle
ldh a, [hSkipJingle]
cp a, 0
jr nz, .skipJingle
.playNextJingle
ldh a, [hCurrentGravityPerTick]
cp a, 1
jr nz, .skipJingle
ldh a, [hNextPiece]
call SFXEnqueue
.skipJingle
ld b, a
ld a, SFX_IRS
or a, b
ldh [hRequestedJingle], a
jr .postjingle
.postjingle
ld a, MODE_SPAWN_PIECE
ldh [hMode], a
; State falls through to the next.
@ -299,6 +302,15 @@ spawnPieceMode:
: ld a, MODE_PIECE_IN_MOTION
ldh [hMode], a
; Play the next jingle... maybe!
ldh a, [hHoldSpent]
cp a, $FF
jr z, pieceInMotionMode
ldh a, [hRequestedJingle]
cp a, $FF
jr z, pieceInMotionMode
call SFXEnqueue
; This mode lasts for as long as the piece is in motion.
; Field will let us know when it has locked in place.
@ -327,8 +339,6 @@ pieceInMotionMode:
ldh [hCurrentPieceX], a
ld a, 3
ldh [hCurrentPieceY], a
xor a, a
ldh [hSkipJingle], a
ldh [hCurrentPieceRotationState], a
call DoHold
ld a, MODE_SPAWN_PIECE
@ -482,12 +492,12 @@ gameOverMode:
ldh [hMode], a
ld a, LEADY_TIME
ldh [hModeCounter], a
jr drawStaticInfo
jp drawStaticInfo
; Quit
: ldh a, [hBState]
cp a, 1
jr nz, drawStaticInfo
jp nz, drawStaticInfo
call SwitchToTitle
jp EventLoopPostHandler
@ -504,7 +514,43 @@ pauseMode:
; Draw PAUSE all over the field.
: ld de, sPause
ld hl, wField+(4*10)
ld bc, 200
ld bc, 20
call UnsafeMemCopy
ld de, sPause
ld hl, wField+(6*10)
ld bc, 20
call UnsafeMemCopy
ld de, sPause
ld hl, wField+(8*10)
ld bc, 20
call UnsafeMemCopy
ld de, sPause
ld hl, wField+(10*10)
ld bc, 20
call UnsafeMemCopy
ld de, sPause
ld hl, wField+(12*10)
ld bc, 20
call UnsafeMemCopy
ld de, sPause
ld hl, wField+(14*10)
ld bc, 20
call UnsafeMemCopy
ld de, sPause
ld hl, wField+(16*10)
ld bc, 20
call UnsafeMemCopy
ld de, sPause
ld hl, wField+(18*10)
ld bc, 20
call UnsafeMemCopy
ld de, sPause
ld hl, wField+(20*10)
ld bc, 20
call UnsafeMemCopy
ld de, sPause
ld hl, wField+(22*10)
ld bc, 20
call UnsafeMemCopy
jr drawStaticInfo
@ -538,8 +584,6 @@ DoHold:
; Mark hold as spent.
ld a, $FF
ldh [hHoldSpent], a
ld a, SFX_IHS
call SFXEnqueue
; Check if IRS is requested.
; Apply the rotation if so.
@ -563,7 +607,8 @@ DoHold:
.cp3
ld a, 3
ldh [hCurrentPieceRotationState], a
ld a, SFX_IRS
call SFXKill
ld a, SFX_IRS | SFX_IHS
call SFXEnqueue
jr .doHoldOperation
@ -587,11 +632,15 @@ DoHold:
.cp4
ld a, 1
ldh [hCurrentPieceRotationState], a
ld a, SFX_IRS
call SFXKill
ld a, SFX_IRS | SFX_IHS
call SFXEnqueue
jr .doHoldOperation
.noRotation
call SFXKill
ld a, SFX_IHS
call SFXEnqueue
ld a, 0
ldh [hCurrentPieceRotationState], a
@ -602,8 +651,6 @@ DoHold:
ldh [hHeldPiece], a
ld a, b
ldh [hCurrentPiece], a
ld a, $FF
ldh [hSkipJingle], a
ret

View File

@ -114,6 +114,9 @@ SwitchToTitle::
; GBC init
call GBCTitleInit
; Make sure the speed curve is aimed at the right place.
call InitSpeedCurve
; Install the event loop handlers.
ld a, 0
ldh [hGameState], a
@ -261,10 +264,12 @@ DecrementOption:
dec a
ld [wSpeedCurveState], a
ld [rSpeedCurveState], a
call InitSpeedCurve
jp EventLoopPostHandler
: ld a, SCURVE_COUNT-1
ld [wSpeedCurveState], a
ld [rSpeedCurveState], a
call InitSpeedCurve
jp EventLoopPostHandler
.opt5
@ -372,10 +377,12 @@ IncrementOption:
inc a
ld [wSpeedCurveState], a
ld [rSpeedCurveState], a
call InitSpeedCurve
jp EventLoopPostHandler
: xor a, a
ld [wSpeedCurveState], a
ld [rSpeedCurveState], a
call InitSpeedCurve
jp EventLoopPostHandler
.opt5
@ -409,32 +416,102 @@ IncrementLevel:
ldh [hStartSpeed], a
ld a, h
ldh [hStartSpeed+1], a
jr CheckLevelRange
jp CheckLevelRange
InitSpeedCurve:
ld a, [wSpeedCurveState]
call GetStart
.set
ld a, l
ldh [hStartSpeed], a
ld a, h
ldh [hStartSpeed+1], a
ret
GetEnd:
ld a, [wSpeedCurveState]
cp a, SCURVE_DMGT
jr nz, :+
ld bc, sSpeedCurveEnd
ret
: cp a, SCURVE_TGM1
jr nz, :+
ld bc, sTGM1SpeedCurveEnd
ret
: cp a, SCURVE_TGM2
jr nz, :+
ld bc, sTGM2SpeedCurveEnd
ret
: cp a, SCURVE_TGM3
jr nz, :+
ld bc, sTGM3SpeedCurveEnd
ret
: cp a, SCURVE_DEAT
jr nz, :+
ld bc, sDEATSpeedCurveEnd
ret
: ld bc, sSHIRSpeedCurveEnd
ret
GetStart:
ld a, [wSpeedCurveState]
cp a, SCURVE_DMGT
jr nz, :+
ld hl, sSpeedCurve
ret
: cp a, SCURVE_TGM1
jr nz, :+
ld hl, sTGM1SpeedCurve
ret
: cp a, SCURVE_TGM2
jr nz, :+
ld hl, sTGM2SpeedCurve
ret
: cp a, SCURVE_TGM3
jr nz, :+
ld hl, sTGM2SpeedCurve
ret
: cp a, SCURVE_DEAT
jr nz, :+
ld hl, sDEATSpeedCurve
ret
: ld hl, sSHIRSpeedCurve
ret
CheckLevelRange:
; At end?
ld bc, sSpeedCurveEnd
call GetEnd
ldh a, [hStartSpeed]
cp a, c
jr nz, .notatend
ldh a, [hStartSpeed+1]
cp a, b
jr nz, .notatend
ld hl, sSpeedCurve
call GetStart
ld a, l
ldh [hStartSpeed], a
ld a, h
ldh [hStartSpeed+1], a
.notatend
ld bc, sSpeedCurve-12
ld de, -12
call GetStart
add hl, de
ldh a, [hStartSpeed]
cp a, c
cp a, l
jr nz, .notatstart
ldh a, [hStartSpeed+1]
cp a, b
cp a, h
jr nz, .notatstart
ld hl, sSpeedCurveEnd-12
call GetEnd
ld h, b
ld l, c
add hl, de
ld a, l
ldh [hStartSpeed], a
ld a, h