Implement TGM3 and world modes fully.

This commit is contained in:
Randy Thiemann 2023-10-22 20:28:08 +02:00
parent f1f33b27d3
commit c9f7ab5fa9
11 changed files with 632 additions and 155 deletions

Binary file not shown.

View File

@ -12,11 +12,14 @@ The Randomizer uses a TGM2-style 4-history randomizer preloaded with SSZZ, and w
The game itself runs at a constant 60fps as well as at the traditional 20 row visible grid. The game itself runs at a constant 60fps as well as at the traditional 20 row visible grid.
There are five available game modes: There are five available game modes:
- TGM1: 4 history, 4 rerolls, no sonic drop, never start with O, S or Z. - TGM1: 4 history w/ 4 rerolls, never start with O, S or Z.
- TGM2: 4 history, 6 rerolls, sonic drop, never start with O, S or Z. - TGM2: 4 history w/ 6 rerolls, never start with O, S or Z. Sonic drop.
- TGM3: 6 history, 6 rerolls, sonic drop, never start with O, S or Z. (Note, not the actual 35-bag as used in TGM3, and floor kicks are not implemented (yet) either.) - TGM3: 4 history w/ 6 rerolls and drought protection, never start with O, S or Z. Sonic drop. Extra floor and wall kicks for I and T pieces.
- HELL: No history, no rerolls, no sonic drop, never start with O, S or Z. - HELL: Pure random piece generation.
- EASY: 6 history, 256 rerolls, sonic drop, never start with O, S or Z. - EASY: 4 history w/ 256 rerolls, never start with O, S or Z. Sonic drop.
- TGW2: TGM2 but with hard drop.
- TGW3: TGM3 but with hard drop.
- EAWY: EASY but with hard drop.
## Playing ## Playing

View File

@ -467,5 +467,17 @@ sPieceRotationStates:: ; How each piece is rotated.
db %0100 db %0100
db %0000 db %0000
sTGM3Bag::
db 0, 0, 0, 0, 0
db 1, 1, 1, 1, 1
db 2, 2, 2, 2, 2
db 3, 3, 3, 3, 3
db 4, 4, 4, 4, 4
db 5, 5, 5, 5, 5
db 6, 6, 6, 6, 6
sTGM3Droughts::
db 0, 0, 0, 0, 0, 0, 0
ENDC ENDC

View File

@ -50,6 +50,7 @@ hDelayState: ds 1
hClearedLines: ds 4 hClearedLines: ds 4
hLineClearCt: ds 1 hLineClearCt: ds 1
hComboCt: ds 1 hComboCt: ds 1
hLockDelayForce: ds 1
SECTION "Field Functions", ROM0 SECTION "Field Functions", ROM0
@ -496,6 +497,8 @@ ForceSpawnPiece::
TrySpawnPiece:: TrySpawnPiece::
; Always reset these for a new piece. ; Always reset these for a new piece.
xor a, a
ldh [hLockDelayForce], a
ldh a, [hCurrentLockDelay] ldh a, [hCurrentLockDelay]
ldh [hCurrentLockDelayRemaining], a ldh [hCurrentLockDelayRemaining], a
ldh a, [hCurrentFramesPerGravityTick] ldh a, [hCurrentFramesPerGravityTick]
@ -679,13 +682,15 @@ FindMaxG:
FieldProcess:: FieldProcess::
; **************************************************************
; SETUP
; Wipe out the piece. ; Wipe out the piece.
ldh a, [hCurrentPieceY] ldh a, [hCurrentPieceY]
ldh [hYPosAtStartOfFrame], a ldh [hYPosAtStartOfFrame], a
call FromShadowField call FromShadowField
; Check if we're about to hold. ; Check if we're about to hold. Return if so.
ldh a, [hSelectState] ldh a, [hSelectState]
cp a, 1 cp a, 1
jr nz, :+ jr nz, :+
@ -693,19 +698,32 @@ FieldProcess::
cp a, $FF cp a, $FF
ret nz ret nz
; How deep can we go? ; How deep can we go?
: call FindMaxG : call FindMaxG
; If we press up, we want to do a sonic drop, but not in TGM1 or HELL mode.
ldh a, [hSimulationMode] ; **************************************************************
cp a, MODE_TGM1 ; HANDLE UP
jr z, :+ ; Is a hard/sonic drop requested?
cp a, MODE_HELL
jr z, :+
ldh a, [hUpState] ldh a, [hUpState]
cp a, 1 cp a, 1
jr nz, :+ jr nz, .postdrop
; What kind, if any?
ldh a, [hSimulationMode]
cp a, MODE_TGM1
jr z, .postdrop
cp a, MODE_HELL
jr z, .postdrop
cp a, MODE_TGW2
jr z, .harddrop
cp a, MODE_TGW3
jr z, .harddrop
cp a, MODE_EAWY
jr z, .harddrop
; Sonic drop.
.sonicdrop
ld a, 20 ld a, 20
ldh [hWantedG], a ldh [hWantedG], a
ldh a, [hTicksUntilG] ldh a, [hTicksUntilG]
@ -716,15 +734,32 @@ FieldProcess::
ldh [hTicksUntilG], a ldh [hTicksUntilG], a
jr .grav jr .grav
; Hard drop.
.harddrop
ld a, 20
ld b, a
ldh a, [hActualG]
cp a, b
jr nc, :+
ld b, a
: ldh a, [hCurrentPieceY]
add a, b
ldh [hCurrentPieceY], a
xor a, a
ldh [hCurrentLockDelayRemaining], a
call SFXKill
ld a, SFX_LOCK
call SFXEnqueue
jp .draw
; If we press down, we want to do a soft drop. ; If we press down, we want to do a soft drop.
: ldh a, [hDownState] .postdrop
ldh a, [hDownState]
cp a, 0 cp a, 0
jr z, :+ jr z, :+
ld a, 1 ld a, 1
ldh [hTicksUntilG], a ldh [hTicksUntilG], a
; Gravity? ; Gravity?
: ldh a, [hTicksUntilG] : ldh a, [hTicksUntilG]
dec a dec a
@ -735,7 +770,7 @@ FieldProcess::
ldh a, [hCurrentGravityPerTick] ldh a, [hCurrentGravityPerTick]
ldh [hWantedG], a ldh [hWantedG], a
; Can we drop the full requested distance?
.grav .grav
ldh a, [hWantedG] ldh a, [hWantedG]
ld b, a ld b, a
@ -743,7 +778,7 @@ FieldProcess::
cp a, b cp a, b
jr c, .smallg jr c, .smallg
; Yes. Do it.
.bigg .bigg
ldh a, [hWantedG] ldh a, [hWantedG]
ld b, a ld b, a
@ -752,7 +787,7 @@ FieldProcess::
ldh [hCurrentPieceY], a ldh [hCurrentPieceY], a
jr .nograv jr .nograv
; No. Smaller distance.
.smallg .smallg
ldh a, [hActualG] ldh a, [hActualG]
ld b, a ld b, a
@ -760,14 +795,16 @@ FieldProcess::
add a, b add a, b
ldh [hCurrentPieceY], a ldh [hCurrentPieceY], a
; No gravity, or post gravity.
.nograv .nograv
ldh a, [hCurrentPieceX] ldh a, [hCurrentPieceX]
ldh [hWantX], a ldh [hWantX], a
ldh a, [hCurrentPieceRotationState] ldh a, [hCurrentPieceRotationState]
ldh [hWantRotation], a ldh [hWantRotation], a
; We check rotation first.
; **************************************************************
; HANDLE ROTATION
; Want rotate CCW? ; Want rotate CCW?
.wantrotccw .wantrotccw
ldh a, [hSwapAB] ldh a, [hSwapAB]
@ -787,7 +824,6 @@ FieldProcess::
ldh [hWantRotation], a ldh [hWantRotation], a
jr .tryrot jr .tryrot
; Want rotate CW? ; Want rotate CW?
.wantrotcw .wantrotcw
ldh a, [hSwapAB] ldh a, [hSwapAB]
@ -806,7 +842,6 @@ FieldProcess::
and a, $03 and a, $03
ldh [hWantRotation], a ldh [hWantRotation], a
; Try the rotation. ; Try the rotation.
.tryrot .tryrot
ldh a, [hCurrentPieceY] ldh a, [hCurrentPieceY]
@ -836,26 +871,40 @@ FieldProcess::
call SetPieceDataOffset call SetPieceDataOffset
jp .norot jp .norot
; Try kicks if the piece isn't I or O. And in the case of J L and T, only if the blocked side is the left or right. ; Try kicks if the piece isn't I or O. And in the case of J L and T, only if the blocked side is the left or right.
.maybekick .maybekick
ld c, a ld c, a
ldh a, [hCurrentPiece] ldh a, [hCurrentPiece]
cp a, PIECE_I ; O pieces never kick, obviously.
jr z, .norot
cp a, PIECE_O cp a, PIECE_O
jr z, .norot jp z, .norot
; S/Z always kick.
cp a, PIECE_S cp a, PIECE_S
jr z, .trykickright jr z, .trykickright
cp a, PIECE_Z cp a, PIECE_Z
jr z, .trykickright jr z, .trykickright
ld a, c
; I piece only kicks in TGM3/TGW3/EASY/EAWY
cp a, PIECE_I
jr nz, :+
ldh a, [hSimulationMode]
cp a, MODE_TGM1
jp z, .norot
cp a, MODE_TGM2
jp z, .norot
cp a, MODE_HELL
jp z, .norot
jr .trykickright
; T/L/J only kick if not through the middle axis.
: ld a, c
cp a, 1 cp a, 1
jr z, .norot jr z, .maybetgm3rot
cp a, 5 cp a, 5
jr z, .norot jr z, .maybetgm3rot
cp a, 9 cp a, 9
jr z, .norot jr z, .maybetgm3rot
; A step to the right. ; A step to the right.
.trykickright .trykickright
@ -888,8 +937,7 @@ FieldProcess::
ldh a, [hWantRotation] ldh a, [hWantRotation]
ldh [hCurrentPieceRotationState], a ldh [hCurrentPieceRotationState], a
call SetPieceDataOffset call SetPieceDataOffset
jr .norot jp .norot
; And a step to the left. ; And a step to the left.
.trykickleft .trykickleft
@ -915,15 +963,185 @@ FieldProcess::
pop bc pop bc
call CanPieceFitFast call CanPieceFitFast
cp a, $FF cp a, $FF
jr nz, .norot jr nz, .maybetgm3rot
ldh a, [hCurrentPieceX] ldh a, [hCurrentPieceX]
dec a dec a
ldh [hCurrentPieceX], a ldh [hCurrentPieceX], a
ldh a, [hWantRotation] ldh a, [hWantRotation]
ldh [hCurrentPieceRotationState], a ldh [hCurrentPieceRotationState], a
call SetPieceDataOffset call SetPieceDataOffset
jp .norot
; In TGM3, TGW3, EASY, and EAWY modes, there are a few other kicks possible.
.maybetgm3rot
ldh a, [hSimulationMode]
cp a, MODE_TGM1
jp z, .norot
cp a, MODE_TGM2
jp z, .norot
cp a, MODE_HELL
jp z, .norot
; In the case of a T piece, try the space above.
.checkt
ldh a, [hCurrentPiece]
cp a, PIECE_T
jr nz, .checki
ldh a, [hCurrentPieceY]
dec a
ld b, a
ldh a, [hCurrentPieceX]
call XYToSFieldPtr
ld d, h
ld e, l
ldh a, [hPieceDataBaseFast]
ld l, a
ldh a, [hPieceDataBaseFast+1]
ld h, a
ldh a, [hWantRotation]
rlc a
rlc a
push bc
ld c, a
xor a, a
ld b, a
add hl, bc
pop bc
call CanPieceFitFast
cp a, $FF
jp nz, .norot
ldh a, [hCurrentPieceY]
dec a
ldh [hCurrentPieceY], a
ldh a, [hWantRotation]
ldh [hCurrentPieceRotationState], a
call SetPieceDataOffset
ld a, $FF
ldh [hLockDelayForce], a
jp .norot
; In the case of an I piece...
.checki
ldh a, [hCurrentPiece]
cp a, PIECE_I
jp nz, .norot
; Are we grounded?
; If not, we can only kick right twice.
ldh a, [hActualG]
cp a, 0
jr nz, .tryiright2
; Try up once.
.tryiup1
ldh a, [hCurrentPieceY]
dec a
ld b, a
ldh a, [hCurrentPieceX]
call XYToSFieldPtr
ld d, h
ld e, l
ldh a, [hPieceDataBaseFast]
ld l, a
ldh a, [hPieceDataBaseFast+1]
ld h, a
ldh a, [hWantRotation]
rlc a
rlc a
push bc
ld c, a
xor a, a
ld b, a
add hl, bc
pop bc
call CanPieceFitFast
cp a, $FF
jr nz, .tryiup2
ldh a, [hCurrentPieceY]
dec a
ldh [hCurrentPieceY], a
ldh a, [hWantRotation]
ldh [hCurrentPieceRotationState], a
call SetPieceDataOffset
ld a, $FF
ldh [hLockDelayForce], a
jr .norot
; Try up twice.
.tryiup2
ldh a, [hCurrentPieceY]
dec a
dec a
ld b, a
ldh a, [hCurrentPieceX]
call XYToSFieldPtr
ld d, h
ld e, l
ldh a, [hPieceDataBaseFast]
ld l, a
ldh a, [hPieceDataBaseFast+1]
ld h, a
ldh a, [hWantRotation]
rlc a
rlc a
push bc
ld c, a
xor a, a
ld b, a
add hl, bc
pop bc
call CanPieceFitFast
cp a, $FF
jr nz, .tryiright2
ldh a, [hCurrentPieceY]
dec a
dec a
ldh [hCurrentPieceY], a
ldh a, [hWantRotation]
ldh [hCurrentPieceRotationState], a
call SetPieceDataOffset
ld a, $FF
ldh [hLockDelayForce], a
jr .norot
; Try right twice.
.tryiright2
ldh a, [hCurrentPieceY]
ld b, a
ldh a, [hCurrentPieceX]
inc a
inc a
call XYToSFieldPtr
ld d, h
ld e, l
ldh a, [hPieceDataBaseFast]
ld l, a
ldh a, [hPieceDataBaseFast+1]
ld h, a
ldh a, [hWantRotation]
rlc a
rlc a
push bc
ld c, a
xor a, a
ld b, a
add hl, bc
pop bc
call CanPieceFitFast
cp a, $FF
jr nz, .norot
ldh a, [hCurrentPieceX]
inc a
inc a
ldh [hCurrentPieceX], a
ldh a, [hWantRotation]
ldh [hCurrentPieceRotationState], a
call SetPieceDataOffset
; **************************************************************
; HANDLE MOVEMENT
; Do we want to move left? ; Do we want to move left?
.norot .norot
ldh a, [hLeftState] ldh a, [hLeftState]
@ -940,8 +1158,7 @@ FieldProcess::
ldh [hWantX], a ldh [hWantX], a
jr .trymove jr .trymove
; Do we want to move right?
; Want right?
.wantright .wantright
ldh a, [hRightState] ldh a, [hRightState]
cp a, 1 cp a, 1
@ -956,7 +1173,6 @@ FieldProcess::
inc a inc a
ldh [hWantX], a ldh [hWantX], a
; Try the movement. ; Try the movement.
.trymove .trymove
ldh a, [hCurrentPieceY] ldh a, [hCurrentPieceY]
@ -973,6 +1189,8 @@ FieldProcess::
ldh [hCurrentPieceX], a ldh [hCurrentPieceX], a
; **************************************************************
; HANDLE LOCKING
; Are we grounded? ; Are we grounded?
.donemanipulating .donemanipulating
ldh a, [hCurrentPieceY] ldh a, [hCurrentPieceY]
@ -1011,18 +1229,32 @@ FieldProcess::
ldh [hCurrentLockDelayRemaining], a ldh [hCurrentLockDelayRemaining], a
; If we're out of lock delay, play a sound. ; If we're out of lock delay, play a sound.
cp a, 0 cp a, 0
jr nz, .draw jr nz, .forcelockmaybe
call SFXKill call SFXKill
ld a, SFX_LOCK ld a, SFX_LOCK
call SFXEnqueue call SFXEnqueue
jr .draw jr .draw
; TGM3 sometimes forces a piece to immediately lock.
.forcelockmaybe
ldh a, [hLockDelayForce]
cp a, $FF
jr nz, .draw
xor a, a
ldh [hCurrentLockDelayRemaining], a
call SFXKill
ld a, SFX_LOCK
call SFXEnqueue
jr .draw
; If we weren't grounded, reset the lock delay.
.notgrounded .notgrounded
; Otherwise reset the lock delay.
ldh a, [hCurrentLockDelay] ldh a, [hCurrentLockDelay]
ldh [hCurrentLockDelayRemaining], a ldh [hCurrentLockDelayRemaining], a
; **************************************************************
; HANDLE DRAWING
; Draw the piece. ; Draw the piece.
.draw .draw
; If the gravity is <= 1G, draw a ghost piece. ; If the gravity is <= 1G, draw a ghost piece.

View File

@ -164,6 +164,9 @@ DEF MODE_TGM2 EQU 1
DEF MODE_TGM3 EQU 2 DEF MODE_TGM3 EQU 2
DEF MODE_HELL EQU 3 DEF MODE_HELL EQU 3
DEF MODE_EASY EQU 4 DEF MODE_EASY EQU 4
DEF MODE_TGW2 EQU 5
DEF MODE_TGW3 EQU 6
DEF MODE_EAWY EQU 7
ENDC ENDC

Binary file not shown.

Binary file not shown.

View File

@ -432,18 +432,18 @@ Tiles::
DB $8A,$00,$EA,$00,$00,$00,$00,$00 DB $8A,$00,$EA,$00,$00,$00,$00,$00
DB $00,$00,$6A,$00,$8A,$00,$44,$00 DB $00,$00,$6A,$00,$8A,$00,$44,$00
DB $24,$00,$C4,$00,$00,$00,$00,$00 DB $24,$00,$C4,$00,$00,$00,$00,$00
DB $00,$00,$AA,$00,$AA,$00,$44,$00 DB $00,$00,$EE,$00,$48,$00,$4A,$00
DB $AA,$00,$AA,$00,$00,$00,$00,$00 DB $4A,$00,$4E,$00,$00,$00,$00,$00
DB $00,$00,$AA,$00,$AA,$00,$44,$00 DB $00,$00,$AC,$00,$A2,$00,$A4,$00
DB $AA,$00,$AA,$00,$00,$00,$00,$00 DB $E8,$00,$AE,$00,$00,$00,$00,$00
DB $00,$00,$AA,$00,$AA,$00,$44,$00 DB $00,$00,$EE,$00,$48,$00,$4A,$00
DB $AA,$00,$AA,$00,$00,$00,$00,$00 DB $4A,$00,$4E,$00,$00,$00,$00,$00
DB $00,$00,$AA,$00,$AA,$00,$44,$00 DB $00,$00,$AC,$00,$A2,$00,$A4,$00
DB $AA,$00,$AA,$00,$00,$00,$00,$00 DB $E2,$00,$AC,$00,$00,$00,$00,$00
DB $00,$00,$AA,$00,$AA,$00,$44,$00 DB $00,$00,$E4,$00,$8A,$00,$CE,$00
DB $AA,$00,$AA,$00,$00,$00,$00,$00 DB $8A,$00,$EA,$00,$00,$00,$00,$00
DB $00,$00,$AA,$00,$AA,$00,$44,$00 DB $00,$00,$AA,$00,$AA,$00,$A4,$00
DB $AA,$00,$AA,$00,$00,$00,$00,$00 DB $E4,$00,$A4,$00,$00,$00,$00,$00
DB $7C,$7C,$42,$42,$41,$41,$5D,$48 DB $7C,$7C,$42,$42,$41,$41,$5D,$48
DB $6E,$4C,$5B,$4A,$79,$49,$00,$00 DB $6E,$4C,$5B,$4A,$79,$49,$00,$00
DB $68,$58,$58,$68,$68,$58,$48,$78 DB $68,$58,$58,$68,$68,$58,$48,$78
@ -508,30 +508,30 @@ Tiles::
DB $8A,$8A,$EA,$EA,$00,$00,$00,$00 DB $8A,$8A,$EA,$EA,$00,$00,$00,$00
DB $00,$00,$6A,$6A,$8A,$8A,$44,$44 DB $00,$00,$6A,$6A,$8A,$8A,$44,$44
DB $24,$24,$C4,$C4,$00,$00,$00,$00 DB $24,$24,$C4,$C4,$00,$00,$00,$00
DB $00,$00,$AA,$AA,$AA,$AA,$44,$44 DB $00,$00,$EE,$EE,$48,$48,$4A,$4A
DB $AA,$AA,$AA,$AA,$00,$00,$00,$00 DB $4A,$4A,$4E,$4E,$00,$00,$00,$00
DB $00,$00,$AA,$AA,$AA,$AA,$44,$44 DB $00,$00,$AC,$AC,$A2,$A2,$A4,$A4
DB $AA,$AA,$AA,$AA,$00,$00,$00,$00 DB $E8,$E8,$AE,$AE,$00,$00,$00,$00
DB $00,$00,$AA,$AA,$AA,$AA,$44,$44 DB $00,$00,$EE,$EE,$48,$48,$4A,$4A
DB $AA,$AA,$AA,$AA,$00,$00,$00,$00 DB $4A,$4A,$4E,$4E,$00,$00,$00,$00
DB $00,$00,$AA,$AA,$AA,$AA,$44,$44 DB $00,$00,$AC,$AC,$A2,$A2,$A4,$A4
DB $AA,$AA,$AA,$AA,$00,$00,$00,$00 DB $E2,$E2,$AC,$AC,$00,$00,$00,$00
DB $00,$00,$AA,$AA,$AA,$AA,$44,$44 DB $00,$00,$E4,$E4,$8A,$8A,$CE,$CE
DB $AA,$AA,$AA,$AA,$00,$00,$00,$00 DB $8A,$8A,$EA,$EA,$00,$00,$00,$00
DB $00,$00,$AA,$AA,$AA,$AA,$44,$44 DB $00,$00,$AA,$AA,$AA,$AA,$A4,$A4
DB $AA,$AA,$AA,$AA,$00,$00,$00,$00 DB $E4,$E4,$A4,$A4,$00,$00,$00,$00
DB $00,$00,$00,$00,$00,$00,$00,$00 DB $00,$00,$00,$00,$A0,$A0,$A0,$A0
DB $00,$00,$00,$00,$00,$00,$00,$00 DB $A0,$A0,$A0,$A0,$48,$48,$00,$00
DB $FF,$00,$FF,$00,$FF,$00,$FF,$00 DB $00,$00,$00,$00,$C4,$C4,$2A,$2A
DB $FF,$00,$FF,$00,$FF,$00,$FF,$00 DB $4A,$4A,$8A,$8A,$E4,$E4,$00,$00
DB $00,$FF,$00,$FF,$00,$FF,$00,$FF DB $00,$00,$00,$00,$CC,$CC,$22,$22
DB $00,$FF,$00,$FF,$00,$FF,$00,$FF DB $4C,$4C,$82,$82,$EC,$EC,$00,$00
DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF DB $00,$00,$00,$00,$44,$44,$CA,$CA
DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF DB $4A,$4A,$4A,$4A,$E4,$E4,$00,$00
DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF DB $00,$00,$00,$00,$CC,$CC,$22,$22
DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF DB $44,$44,$88,$88,$EE,$EE,$00,$00
DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF DB $00,$00,$00,$00,$04,$04,$0A,$0A
DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF DB $0E,$0E,$0A,$0A,$0A,$0A,$00,$00
TilesEnd:: TilesEnd::

View File

@ -22,7 +22,7 @@ DEF TITLE_MAP_INC EQU 1
SECTION "Title Screen Tilemap", ROM0 SECTION "Title Screen Tilemap", ROM0
TitleScreenTilemap:: TitleScreenTilemap::
DB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01 DB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01
DB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01 DB $01,$01,$01,$01,$FA,$FB,$FC,$FD,$FE,$FF
DB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01 DB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01
DB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01 DB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01
DB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01 DB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01

View File

@ -24,10 +24,17 @@ INCLUDE "globals.asm"
SECTION "High RNG Variables", HRAM SECTION "High RNG Variables", HRAM
hRNGSeed: ds 4 hRNGSeed: ds 4
hPieceHistory: ds 6 hPieceHistory: ds 4
hNextPiece:: ds 1 hNextPiece:: ds 1
SECTION "TGM3 RNG Variables", WRAM0
wTGM3Bag: ds 35
wTGM3Droughts: ds 7
wTGM3GeneratedIdx: ds 1
wTGM3WorstDroughtIdx: ds 1
section "RNG Functions", ROM0 section "RNG Functions", ROM0
RNGInit:: RNGInit::
; Do some bit fuckery on the seed using the gameboy's free-running timers. ; Do some bit fuckery on the seed using the gameboy's free-running timers.
@ -47,18 +54,41 @@ RNGInit::
xor a, [hl] xor a, [hl]
ldh [hRNGSeed+3], a ldh [hRNGSeed+3], a
; Initialize the next history. ; TGM3 vars
ld de, sTGM3Bag
ld hl, wTGM3Bag
ld bc, 35
call UnsafeMemCopy
ld de, sTGM3Droughts
ld hl, wTGM3Droughts
ld bc, 7
call UnsafeMemCopy
; If we're in HELL mode, we don't care about anything but a random piece to start with.
ldh a, [hSimulationMode]
cp a, MODE_HELL
jr nz, .complexinit
call Next7Piece
ld [hNextPiece], a
ret
; Otherwise do complex init.
.complexinit
ld a, PIECE_Z ld a, PIECE_Z
ldh [hPieceHistory], a ldh [hPieceHistory], a
ldh [hPieceHistory+1], a ldh [hPieceHistory+1], a
ldh [hPieceHistory+4], a ldh [hPieceHistory+2], a
ldh [hPieceHistory+5], a ldh [hPieceHistory+3], a
ldh a, [hSimulationMode]
cp a, MODE_TGM1
jr z, :+
ld a, PIECE_S ld a, PIECE_S
ldh [hPieceHistory+2], a ldh [hPieceHistory+2], a
ldh [hPieceHistory+3], a ldh [hPieceHistory+3], a
; Get the first piece and make sure it's not Z, S or O. ; Get the first piece and make sure it's not Z, S or O.
: call NextPiece : call Next7Piece
cp a, PIECE_Z cp a, PIECE_Z
jr z, :- jr z, :-
cp a, PIECE_S cp a, PIECE_S
@ -66,99 +96,296 @@ RNGInit::
cp a, PIECE_O cp a, PIECE_O
jr z, :- jr z, :-
; Store it. ; Save the generated piece and put it in the history.
ldh [hPieceHistory], a ldh [hPieceHistory], a
ld [hNextPiece], a ld [hNextPiece], a
ret ret
GetNextPiece:: ; Shift the generated piece into the history and save it.
: ldh a, [hSimulationMode] ; Hell? ShiftHistory:
cp a, MODE_HELL
jr nz, :+
call NextPiece
jr .donerolling
: ldh a, [hSimulationMode] ; TGM1?
cp a, MODE_TGM1
jr nz, :+
ld a, 5
ld e, a
jr .rollloop
: ldh a, [hSimulationMode] ; EASY?
cp a, MODE_EASY
jr nz, :+
ld a, 0
ld e, a
jr .rollloop
: ld a, 7 ; TGM2/3.
ld e, a
.rollloop
dec e
jr z, .donerolling
call NextPiece
ld hl, hPieceHistory
cp a, [hl]
jr z, .rollloop
inc hl
cp a, [hl]
jr z, .rollloop
inc hl
cp a, [hl]
jr z, .rollloop
inc hl
cp a, [hl]
jr z, .rollloop
; Are we in TGM3 or EASY mode?
ld b, a
ldh a, [hSimulationMode]
cp a, MODE_TGM3
jr z, .6hist
cp a, MODE_EASY
jr z, .6hist
jr .donerolling ; If not, we're done rolling.
; If we are, extend the history by 2.
.6hist
ld a, b
inc hl
cp a, [hl]
jr z, .rollloop
inc hl
cp a, [hl]
jr z, .rollloop
.donerolling
ldh [hNextPiece], a ldh [hNextPiece], a
ld b, a
ldh a, [hPieceHistory+4]
ldh [hPieceHistory+5], a
ldh a, [hPieceHistory+3]
ldh [hPieceHistory+4], a
ldh a, [hPieceHistory+2] ldh a, [hPieceHistory+2]
ldh [hPieceHistory+3], a ldh [hPieceHistory+3], a
ldh a, [hPieceHistory+1] ldh a, [hPieceHistory+1]
ldh [hPieceHistory+2], a ldh [hPieceHistory+2], a
ldh a, [hPieceHistory] ldh a, [hPieceHistory]
ldh [hPieceHistory+1], a ldh [hPieceHistory+1], a
ld a, b ldh a, [hNextPiece]
ldh [hPieceHistory], a ldh [hPieceHistory], a
ret ret
NextPiece: ; A random piece. Get fucked.
call NextByte GetNextHellPiece:
call Next7Piece
ldh [hNextPiece], a
ret
; 4 history, 4 rerolls.
GetNextTGM1Piece:
ld a, 5
ld e, a
: dec e
jr z, :+
call Next7Piece
ld hl, hPieceHistory
cp a, [hl]
jr z, :-
inc hl
cp a, [hl]
jr z, :-
inc hl
cp a, [hl]
jr z, :-
inc hl
cp a, [hl]
jr z, :-
: jr ShiftHistory
; 4 history, 6 rerolls.
GetNextTGM2Piece:
ld a, 7
ld e, a
: dec e
jr z, :+
call Next7Piece
ld hl, hPieceHistory
cp a, [hl]
jr z, :-
inc hl
cp a, [hl]
jr z, :-
inc hl
cp a, [hl]
jr z, :-
inc hl
cp a, [hl]
jr z, :-
: jr ShiftHistory
; 4 History, (basically) infinite rerolls.
GetNextEasyPiece:
ld a, 0
ld e, a
: dec e
jr z, :+
call Next7Piece
ld hl, hPieceHistory
cp a, [hl]
jr z, :-
inc hl
cp a, [hl]
jr z, :-
inc hl
cp a, [hl]
jr z, :-
inc hl
cp a, [hl]
jr z, :-
: jr ShiftHistory
; TGM3 mode... It's complex.
GetNextTGM3Piece:
ld a, 7
ld e, a
: dec e
jr z, :+
; Get a random index into the 35bag
call Next35Piece
ld [wTGM3GeneratedIdx], a
; Fetch the piece from the 35bag.
ld c, a
xor a, a
ld b, a
ld hl, wTGM3Bag
add hl, bc
ld a, [hl]
; Is it in the history?
ld hl, hPieceHistory
cp a, [hl]
jr z, :-
inc hl
cp a, [hl]
jr z, :-
inc hl
cp a, [hl]
jr z, :-
inc hl
cp a, [hl]
jr z, :-
; We have a piece. Save it.
: call ShiftHistory
; Increment all drought counters.
: ld hl, wTGM3Droughts
inc [hl]
inc hl
inc [hl]
inc hl
inc [hl]
inc hl
inc [hl]
inc hl
inc [hl]
inc hl
inc [hl]
inc hl
inc [hl]
; Set the drought of our most recently drawn piece to 0.
: ldh a, [hCurrentPiece]
ld c, a
xor a, a
ld b, a
ld hl, wTGM3Droughts
add hl, bc
ld [hl], a
; We pick an arbitrary piece to have the worst drought.
: call Next7Piece
ld [wTGM3WorstDroughtIdx], a
; And then save that drought in e.
ld c, a
xor a, a
ld b, a
ld hl, wTGM3Droughts
add hl, bc
ld e, [hl]
; Is idx 0 worse?
: ld hl, wTGM3Droughts
ld a, [hl+]
cp a, e
jr z, :+ ; Same.
jr c, :+ ; Nope.
ld e, a
ld a, 0
ld [wTGM3WorstDroughtIdx], a
; Is idx 1 worse?
: ld a, [hl+]
cp a, e
jr z, :+ ; Same.
jr c, :+ ; Nope.
ld e, a
ld a, 1
ld [wTGM3WorstDroughtIdx], a
; Is idx 2 worse?
: ld a, [hl+]
cp a, e
jr z, :+ ; Same.
jr c, :+ ; Nope.
ld e, a
ld a, 2
ld [wTGM3WorstDroughtIdx], a
; Is idx 3 worse?
: ld a, [hl+]
cp a, e
jr z, :+ ; Same.
jr c, :+ ; Nope.
ld e, a
ld a, 3
ld [wTGM3WorstDroughtIdx], a
; Is idx 4 worse?
: ld a, [hl+]
cp a, e
jr z, :+ ; Same.
jr c, :+ ; Nope.
ld e, a
ld a, 4
ld [wTGM3WorstDroughtIdx], a
; Is idx 5 worse?
: ld a, [hl+]
cp a, e
jr z, :+ ; Same.
jr c, :+ ; Nope.
ld e, a
ld a, 5
ld [wTGM3WorstDroughtIdx], a
; Is idx 6 worse?
: ld a, [hl+]
cp a, e
jr z, :+ ; Same.
jr c, :+ ; Nope.
ld e, a
ld a, 6
ld [wTGM3WorstDroughtIdx], a
; We now have the worst drought index as well as the slot in the bag that needs to be replaced.
: ld a, [wTGM3GeneratedIdx]
ld c, a
xor a, a
ld b, a
ld hl, wTGM3Bag
add hl, bc
ld a, [wTGM3WorstDroughtIdx]
; Replace that slot.
ld [hl], a
ret
GetNextPiece::
ldh a, [hSimulationMode]
cp a, MODE_HELL
jp z, GetNextHellPiece
cp a, MODE_TGM1
jp z, GetNextTGM1Piece
cp a, MODE_TGM2
jp z, GetNextTGM2Piece
cp a, MODE_TGW2
jp z, GetNextTGM2Piece
cp a, MODE_TGM3
jp z, GetNextTGM3Piece
cp a, MODE_TGW3
jp z, GetNextTGM3Piece
cp a, MODE_EASY
jp z, GetNextEasyPiece
cp a, MODE_EAWY
jp z, GetNextEasyPiece
Next35Piece:
: call NextByte
and a, $3F
cp a, 35
jr nc, :-
ret
Next7Piece:
: call NextByte
and a, $07 and a, $07
cp a, 7 cp a, 7
ret nz jr nc, :-
dec a
ret ret
NextByte: NextByte:
; Load seed ; Load seed
ld hl, hRNGSeed+3 ld hl, hRNGSeed+3

View File

@ -95,7 +95,7 @@ TitleEventLoopHandler::
jr nz, :+ jr nz, :+
ldh a, [hSimulationMode] ldh a, [hSimulationMode]
inc a inc a
cp a, 5 cp a, 8
jr nz, .write jr nz, .write
xor a, a xor a, a
.write .write