diff --git a/DMGTRIS.GB b/DMGTRIS.GB index 3395291..9132a86 100644 Binary files a/DMGTRIS.GB and b/DMGTRIS.GB differ diff --git a/README.md b/README.md index dd41c51..5f1b08b 100644 --- a/README.md +++ b/README.md @@ -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. There are five available game modes: -- TGM1: 4 history, 4 rerolls, no sonic drop, never start with O, S or Z. -- TGM2: 4 history, 6 rerolls, sonic drop, never start with O, S or Z. -- 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.) -- HELL: No history, no rerolls, no sonic drop, never start with O, S or Z. -- EASY: 6 history, 256 rerolls, 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 w/ 6 rerolls, never start with O, S or Z. Sonic drop. +- 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: Pure random piece generation. +- 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 diff --git a/src/constants.asm b/src/constants.asm index a91308f..2b053ee 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -467,5 +467,17 @@ sPieceRotationStates:: ; How each piece is rotated. db %0100 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 diff --git a/src/field.asm b/src/field.asm index f30286d..65eaca3 100644 --- a/src/field.asm +++ b/src/field.asm @@ -50,6 +50,7 @@ hDelayState: ds 1 hClearedLines: ds 4 hLineClearCt: ds 1 hComboCt: ds 1 +hLockDelayForce: ds 1 SECTION "Field Functions", ROM0 @@ -496,6 +497,8 @@ ForceSpawnPiece:: TrySpawnPiece:: ; Always reset these for a new piece. + xor a, a + ldh [hLockDelayForce], a ldh a, [hCurrentLockDelay] ldh [hCurrentLockDelayRemaining], a ldh a, [hCurrentFramesPerGravityTick] @@ -679,13 +682,15 @@ FindMaxG: FieldProcess:: + ; ************************************************************** + ; SETUP ; Wipe out the piece. ldh a, [hCurrentPieceY] ldh [hYPosAtStartOfFrame], a call FromShadowField - ; Check if we're about to hold. + ; Check if we're about to hold. Return if so. ldh a, [hSelectState] cp a, 1 jr nz, :+ @@ -693,19 +698,32 @@ FieldProcess:: cp a, $FF ret nz - ; How deep can we go? : 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 - jr z, :+ - cp a, MODE_HELL - jr z, :+ + + ; ************************************************************** + ; HANDLE UP + ; Is a hard/sonic drop requested? ldh a, [hUpState] 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 ldh [hWantedG], a ldh a, [hTicksUntilG] @@ -716,15 +734,32 @@ FieldProcess:: ldh [hTicksUntilG], a 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. -: ldh a, [hDownState] +.postdrop + ldh a, [hDownState] cp a, 0 jr z, :+ ld a, 1 ldh [hTicksUntilG], a - ; Gravity? : ldh a, [hTicksUntilG] dec a @@ -735,7 +770,7 @@ FieldProcess:: ldh a, [hCurrentGravityPerTick] ldh [hWantedG], a - + ; Can we drop the full requested distance? .grav ldh a, [hWantedG] ld b, a @@ -743,7 +778,7 @@ FieldProcess:: cp a, b jr c, .smallg - + ; Yes. Do it. .bigg ldh a, [hWantedG] ld b, a @@ -752,7 +787,7 @@ FieldProcess:: ldh [hCurrentPieceY], a jr .nograv - + ; No. Smaller distance. .smallg ldh a, [hActualG] ld b, a @@ -760,14 +795,16 @@ FieldProcess:: add a, b ldh [hCurrentPieceY], a - + ; No gravity, or post gravity. .nograv ldh a, [hCurrentPieceX] ldh [hWantX], a ldh a, [hCurrentPieceRotationState] ldh [hWantRotation], a - ; We check rotation first. + + ; ************************************************************** + ; HANDLE ROTATION ; Want rotate CCW? .wantrotccw ldh a, [hSwapAB] @@ -787,7 +824,6 @@ FieldProcess:: ldh [hWantRotation], a jr .tryrot - ; Want rotate CW? .wantrotcw ldh a, [hSwapAB] @@ -806,7 +842,6 @@ FieldProcess:: and a, $03 ldh [hWantRotation], a - ; Try the rotation. .tryrot ldh a, [hCurrentPieceY] @@ -836,26 +871,40 @@ FieldProcess:: call SetPieceDataOffset 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. .maybekick ld c, a ldh a, [hCurrentPiece] - cp a, PIECE_I - jr z, .norot + ; O pieces never kick, obviously. cp a, PIECE_O - jr z, .norot + jp z, .norot + + ; S/Z always kick. cp a, PIECE_S jr z, .trykickright cp a, PIECE_Z 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 - jr z, .norot + jr z, .maybetgm3rot cp a, 5 - jr z, .norot + jr z, .maybetgm3rot cp a, 9 - jr z, .norot + jr z, .maybetgm3rot ; A step to the right. .trykickright @@ -888,8 +937,7 @@ FieldProcess:: ldh a, [hWantRotation] ldh [hCurrentPieceRotationState], a call SetPieceDataOffset - jr .norot - + jp .norot ; And a step to the left. .trykickleft @@ -915,15 +963,185 @@ FieldProcess:: pop bc call CanPieceFitFast cp a, $FF - jr nz, .norot + jr nz, .maybetgm3rot ldh a, [hCurrentPieceX] dec a ldh [hCurrentPieceX], a ldh a, [hWantRotation] ldh [hCurrentPieceRotationState], a 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? .norot ldh a, [hLeftState] @@ -940,8 +1158,7 @@ FieldProcess:: ldh [hWantX], a jr .trymove - - ; Want right? + ; Do we want to move right? .wantright ldh a, [hRightState] cp a, 1 @@ -956,7 +1173,6 @@ FieldProcess:: inc a ldh [hWantX], a - ; Try the movement. .trymove ldh a, [hCurrentPieceY] @@ -973,6 +1189,8 @@ FieldProcess:: ldh [hCurrentPieceX], a + ; ************************************************************** + ; HANDLE LOCKING ; Are we grounded? .donemanipulating ldh a, [hCurrentPieceY] @@ -1011,18 +1229,32 @@ FieldProcess:: ldh [hCurrentLockDelayRemaining], a ; If we're out of lock delay, play a sound. cp a, 0 - jr nz, .draw + jr nz, .forcelockmaybe call SFXKill ld a, SFX_LOCK call SFXEnqueue 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 - ; Otherwise reset the lock delay. ldh a, [hCurrentLockDelay] ldh [hCurrentLockDelayRemaining], a + ; ************************************************************** + ; HANDLE DRAWING ; Draw the piece. .draw ; If the gravity is <= 1G, draw a ghost piece. diff --git a/src/include/globals.asm b/src/include/globals.asm index 6ccd625..a4b5036 100644 --- a/src/include/globals.asm +++ b/src/include/globals.asm @@ -164,6 +164,9 @@ DEF MODE_TGM2 EQU 1 DEF MODE_TGM3 EQU 2 DEF MODE_HELL EQU 3 DEF MODE_EASY EQU 4 +DEF MODE_TGW2 EQU 5 +DEF MODE_TGW3 EQU 6 +DEF MODE_EAWY EQU 7 ENDC diff --git a/src/res/sources/tiles.gbr b/src/res/sources/tiles.gbr index 9234f84..6aa75f2 100644 Binary files a/src/res/sources/tiles.gbr and b/src/res/sources/tiles.gbr differ diff --git a/src/res/sources/title_map.gbm b/src/res/sources/title_map.gbm index f206b47..b247a68 100644 Binary files a/src/res/sources/title_map.gbm and b/src/res/sources/title_map.gbm differ diff --git a/src/res/tiles.inc b/src/res/tiles.inc index 5a5f752..47403f2 100644 --- a/src/res/tiles.inc +++ b/src/res/tiles.inc @@ -432,18 +432,18 @@ Tiles:: DB $8A,$00,$EA,$00,$00,$00,$00,$00 DB $00,$00,$6A,$00,$8A,$00,$44,$00 DB $24,$00,$C4,$00,$00,$00,$00,$00 - DB $00,$00,$AA,$00,$AA,$00,$44,$00 - DB $AA,$00,$AA,$00,$00,$00,$00,$00 - DB $00,$00,$AA,$00,$AA,$00,$44,$00 - DB $AA,$00,$AA,$00,$00,$00,$00,$00 - DB $00,$00,$AA,$00,$AA,$00,$44,$00 - DB $AA,$00,$AA,$00,$00,$00,$00,$00 - DB $00,$00,$AA,$00,$AA,$00,$44,$00 - DB $AA,$00,$AA,$00,$00,$00,$00,$00 - DB $00,$00,$AA,$00,$AA,$00,$44,$00 - DB $AA,$00,$AA,$00,$00,$00,$00,$00 - DB $00,$00,$AA,$00,$AA,$00,$44,$00 - DB $AA,$00,$AA,$00,$00,$00,$00,$00 + DB $00,$00,$EE,$00,$48,$00,$4A,$00 + DB $4A,$00,$4E,$00,$00,$00,$00,$00 + DB $00,$00,$AC,$00,$A2,$00,$A4,$00 + DB $E8,$00,$AE,$00,$00,$00,$00,$00 + DB $00,$00,$EE,$00,$48,$00,$4A,$00 + DB $4A,$00,$4E,$00,$00,$00,$00,$00 + DB $00,$00,$AC,$00,$A2,$00,$A4,$00 + DB $E2,$00,$AC,$00,$00,$00,$00,$00 + DB $00,$00,$E4,$00,$8A,$00,$CE,$00 + DB $8A,$00,$EA,$00,$00,$00,$00,$00 + DB $00,$00,$AA,$00,$AA,$00,$A4,$00 + DB $E4,$00,$A4,$00,$00,$00,$00,$00 DB $7C,$7C,$42,$42,$41,$41,$5D,$48 DB $6E,$4C,$5B,$4A,$79,$49,$00,$00 DB $68,$58,$58,$68,$68,$58,$48,$78 @@ -508,30 +508,30 @@ Tiles:: DB $8A,$8A,$EA,$EA,$00,$00,$00,$00 DB $00,$00,$6A,$6A,$8A,$8A,$44,$44 DB $24,$24,$C4,$C4,$00,$00,$00,$00 - DB $00,$00,$AA,$AA,$AA,$AA,$44,$44 - DB $AA,$AA,$AA,$AA,$00,$00,$00,$00 - DB $00,$00,$AA,$AA,$AA,$AA,$44,$44 - DB $AA,$AA,$AA,$AA,$00,$00,$00,$00 - DB $00,$00,$AA,$AA,$AA,$AA,$44,$44 - DB $AA,$AA,$AA,$AA,$00,$00,$00,$00 - DB $00,$00,$AA,$AA,$AA,$AA,$44,$44 - DB $AA,$AA,$AA,$AA,$00,$00,$00,$00 - DB $00,$00,$AA,$AA,$AA,$AA,$44,$44 - DB $AA,$AA,$AA,$AA,$00,$00,$00,$00 - DB $00,$00,$AA,$AA,$AA,$AA,$44,$44 - DB $AA,$AA,$AA,$AA,$00,$00,$00,$00 - DB $00,$00,$00,$00,$00,$00,$00,$00 - DB $00,$00,$00,$00,$00,$00,$00,$00 - DB $FF,$00,$FF,$00,$FF,$00,$FF,$00 - DB $FF,$00,$FF,$00,$FF,$00,$FF,$00 - DB $00,$FF,$00,$FF,$00,$FF,$00,$FF - DB $00,$FF,$00,$FF,$00,$FF,$00,$FF - DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF - DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF - DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF - DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF - DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF - DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + DB $00,$00,$EE,$EE,$48,$48,$4A,$4A + DB $4A,$4A,$4E,$4E,$00,$00,$00,$00 + DB $00,$00,$AC,$AC,$A2,$A2,$A4,$A4 + DB $E8,$E8,$AE,$AE,$00,$00,$00,$00 + DB $00,$00,$EE,$EE,$48,$48,$4A,$4A + DB $4A,$4A,$4E,$4E,$00,$00,$00,$00 + DB $00,$00,$AC,$AC,$A2,$A2,$A4,$A4 + DB $E2,$E2,$AC,$AC,$00,$00,$00,$00 + DB $00,$00,$E4,$E4,$8A,$8A,$CE,$CE + DB $8A,$8A,$EA,$EA,$00,$00,$00,$00 + DB $00,$00,$AA,$AA,$AA,$AA,$A4,$A4 + DB $E4,$E4,$A4,$A4,$00,$00,$00,$00 + DB $00,$00,$00,$00,$A0,$A0,$A0,$A0 + DB $A0,$A0,$A0,$A0,$48,$48,$00,$00 + DB $00,$00,$00,$00,$C4,$C4,$2A,$2A + DB $4A,$4A,$8A,$8A,$E4,$E4,$00,$00 + DB $00,$00,$00,$00,$CC,$CC,$22,$22 + DB $4C,$4C,$82,$82,$EC,$EC,$00,$00 + DB $00,$00,$00,$00,$44,$44,$CA,$CA + DB $4A,$4A,$4A,$4A,$E4,$E4,$00,$00 + DB $00,$00,$00,$00,$CC,$CC,$22,$22 + DB $44,$44,$88,$88,$EE,$EE,$00,$00 + DB $00,$00,$00,$00,$04,$04,$0A,$0A + DB $0E,$0E,$0A,$0A,$0A,$0A,$00,$00 TilesEnd:: diff --git a/src/res/title_map.inc b/src/res/title_map.inc index 8a94b33..e212f0a 100644 --- a/src/res/title_map.inc +++ b/src/res/title_map.inc @@ -22,7 +22,7 @@ DEF TITLE_MAP_INC EQU 1 SECTION "Title Screen Tilemap", ROM0 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,$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 diff --git a/src/rng.asm b/src/rng.asm index 05b4b3c..0ee0f7e 100644 --- a/src/rng.asm +++ b/src/rng.asm @@ -24,10 +24,17 @@ INCLUDE "globals.asm" SECTION "High RNG Variables", HRAM hRNGSeed: ds 4 -hPieceHistory: ds 6 +hPieceHistory: ds 4 hNextPiece:: ds 1 +SECTION "TGM3 RNG Variables", WRAM0 +wTGM3Bag: ds 35 +wTGM3Droughts: ds 7 +wTGM3GeneratedIdx: ds 1 +wTGM3WorstDroughtIdx: ds 1 + + section "RNG Functions", ROM0 RNGInit:: ; Do some bit fuckery on the seed using the gameboy's free-running timers. @@ -47,18 +54,41 @@ RNGInit:: xor a, [hl] 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 ldh [hPieceHistory], a ldh [hPieceHistory+1], a - ldh [hPieceHistory+4], a - ldh [hPieceHistory+5], a + ldh [hPieceHistory+2], a + ldh [hPieceHistory+3], a + + ldh a, [hSimulationMode] + cp a, MODE_TGM1 + jr z, :+ ld a, PIECE_S ldh [hPieceHistory+2], a ldh [hPieceHistory+3], a ; Get the first piece and make sure it's not Z, S or O. -: call NextPiece +: call Next7Piece cp a, PIECE_Z jr z, :- cp a, PIECE_S @@ -66,99 +96,296 @@ RNGInit:: cp a, PIECE_O jr z, :- - ; Store it. + ; Save the generated piece and put it in the history. ldh [hPieceHistory], a ld [hNextPiece], a ret -GetNextPiece:: -: ldh a, [hSimulationMode] ; Hell? - 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 + ; Shift the generated piece into the history and save it. +ShiftHistory: 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 [hPieceHistory+3], a ldh a, [hPieceHistory+1] ldh [hPieceHistory+2], a ldh a, [hPieceHistory] ldh [hPieceHistory+1], a - ld a, b + ldh a, [hNextPiece] ldh [hPieceHistory], a ret -NextPiece: - call NextByte + ; A random piece. Get fucked. +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 cp a, 7 - ret nz - dec a + jr nc, :- ret + NextByte: ; Load seed ld hl, hRNGSeed+3 diff --git a/src/state_title.asm b/src/state_title.asm index 36477fb..0aee39a 100644 --- a/src/state_title.asm +++ b/src/state_title.asm @@ -95,7 +95,7 @@ TitleEventLoopHandler:: jr nz, :+ ldh a, [hSimulationMode] inc a - cp a, 5 + cp a, 8 jr nz, .write xor a, a .write