Almost all the gameplay is in.

This commit is contained in:
Randy Thiemann 2023-10-20 16:28:11 +02:00
parent 020a2dc3b2
commit 7922208559
7 changed files with 451 additions and 48 deletions

View File

@ -68,6 +68,38 @@ sPieceYOffsets:: ; How to draw each piece. Y-offsets of the sprites.
sSpeedCurve:: ; Speed curve of the game.
dw $0000 ; Level 0000
db 1, 16 ; 1G every 16 frames
db 25, 14, 30, 40 ; ARE, DAS, LOCK, LINECLEAR
dw $0015 ; Level 0015
db 1, 15 ; 1G every 15 frames
db 25, 14, 30, 40 ; ARE, DAS, LOCK, LINECLEAR
dw $0030 ; Level 0030
db 1, 14 ; 1G every 14 frames
db 25, 14, 30, 40 ; ARE, DAS, LOCK, LINECLEAR
dw $0040 ; Level 0040
db 1, 13 ; 1G every 13 frames
db 25, 14, 30, 40 ; ARE, DAS, LOCK, LINECLEAR
dw $0050 ; Level 0050
db 1, 12 ; 1G every 12 frames
db 25, 14, 30, 40 ; ARE, DAS, LOCK, LINECLEAR
dw $0060 ; Level 0060
db 1, 11 ; 1G every 11 frames
db 25, 14, 30, 40 ; ARE, DAS, LOCK, LINECLEAR
dw $0070 ; Level 0070
db 1, 10 ; 1G every 10 frames
db 25, 14, 30, 40 ; ARE, DAS, LOCK, LINECLEAR
dw $0080 ; Level 0080
db 1, 9 ; 1G every 9 frames
db 25, 14, 30, 40 ; ARE, DAS, LOCK, LINECLEAR
dw $0090 ; Level 0090
db 1, 8 ; 1G every 8 frames
db 25, 14, 30, 40 ; ARE, DAS, LOCK, LINECLEAR

View File

@ -5,6 +5,11 @@ DEF FIELD_ASM EQU 1
INCLUDE "globals.asm"
DEF DELAY_STATE_DETERMINE_DELAY EQU 0
DEF DELAY_STATE_LINE_CLEAR EQU 1
DEF DELAY_STATE_ARE EQU 2
SECTION "Field Variables", WRAM0
wField:: ds (10*24)
wShadowField:: ds (14*26)
@ -14,11 +19,17 @@ SECTION "Field High Variables", HRAM
hPieceDataBase: ds 2
hPieceDataOffset: ds 1
hCurrentLockDelayRemaining:: ds 1
hDeepestY: ds 1
hWantedTile: ds 1
hWantedG: ds 1
hActualG: ds 1
hTicksUntilG: ds 1
hWantX: ds 1
hYPosAtStartOfFrame: ds 1
hWantRotation: ds 1
hRemainingDelay:: ds 1
hDelayState: ds 1
hClearedLines: ds 4
SECTION "Field Functions", ROM0
@ -42,7 +53,7 @@ FieldClear::
ret
ToShadowField:
ToShadowField::
ld hl, wField
ld de, wShadowField+2
ld c, 24
@ -367,6 +378,10 @@ TrySpawnPiece::
ldh [hCurrentLockDelayRemaining], a
ldh a, [hCurrentFramesPerGravityTick]
ldh [hTicksUntilG], a
ld a, $FF
ldh [hRemainingDelay], a
ld a, DELAY_STATE_DETERMINE_DELAY
ldh [hDelayState], a
; Copy the field to the shadow field.
call ToShadowField
@ -507,6 +522,58 @@ DrawPiece:
ret
FindMaxG:
; Find the deepest the piece can go.
; We cache this pointer, cause it otherwise takes too much time.
ldh a, [hCurrentPieceY]
ld b, a
ldh a, [hCurrentPieceX]
call XYToSFieldPtr
push hl
ld a, 2
ldh [hActualG], a
.try
ld de, 28
pop hl
add hl, de
push hl
ld d, h
ld e, l
call GetPieceData
call CanPieceFit
cp a, $FF
jr nz, .foundmaybe
ldh a, [hActualG]
inc a
inc a
ldh [hActualG], a
jr .try
.foundmaybe
ldh a, [hActualG]
dec a
ldh [hActualG], a
ld de, -14
pop hl
add hl, de
push hl
ld d, h
ld e, l
call GetPieceData
call CanPieceFit
cp a, $FF
jr nz, .found
pop hl
ret
.found
pop hl
ldh a, [hActualG]
dec a
ldh [hActualG], a
ret
FieldProcess::
; Wipe out the piece.
ldh a, [hCurrentPieceY]
@ -523,11 +590,21 @@ FieldProcess::
ret nz
; How deep can we go?
: call FindMaxG
; If we press up, we want to do a sonic drop.
: ldh a, [hUpState]
ldh a, [hUpState]
cp a, 1
jr nz, :+
ld b, 20
ld a, 20
ldh [hWantedG], a
ldh a, [hTicksUntilG]
dec a
ldh [hTicksUntilG], a
jr nz, .grav
ldh a, [hCurrentFramesPerGravityTick]
ldh [hTicksUntilG], a
jr .grav
@ -546,39 +623,30 @@ FieldProcess::
jr nz, .nograv
ldh a, [hCurrentFramesPerGravityTick]
ldh [hTicksUntilG], a
; Move the piece down, but first check if there's still sufficient "down" to go.
ldh a, [hCurrentGravityPerTick]
ld b, a
ldh [hWantedG], a
.grav
: ldh a, [hCurrentPieceY]
add a, b
cp a, 23
jr c, :+
dec b
jr z, .nograv
jr :-
: push bc
ldh a, [hWantedG]
ld b, a
ldh a, [hActualG]
cp a, b
jr c, .smallg
.bigg
ldh a, [hWantedG]
ld b, a
ldh a, [hCurrentPieceY]
add a, b
ldh [hCurrentPieceY], a
jr .nograv
.smallg
ldh a, [hActualG]
ld b, a
ldh a, [hCurrentPieceX]
call XYToSFieldPtr
ld d, h
ld e, l
call GetPieceData
call CanPieceFit
cp a, $FF
jr z, .dolower
pop bc
dec b
jr z, .nograv
jr :-
.dolower
pop bc
ldh a, [hCurrentPieceY]
add a, b
ldh [hCurrentPieceY], a
@ -811,6 +879,9 @@ FieldProcess::
ldh a, [hYPosAtStartOfFrame]
cp a, b
jr z, :+
ldh a, [hDownState]
cp a, 0
jr nz, :+
ld a, SFX_DROP
call SFXEnqueue
; If the down button is held, lock.
@ -837,8 +908,34 @@ FieldProcess::
; Draw the piece.
.draw
; If the gravity is <= 1G, draw a ghost piece.
ldh a, [hWantedG]
cp a, 1
jr nz, :+
ldh a, [hEvenFrame]
cp a, 1
jr nz, :+
ldh a, [hYPosAtStartOfFrame]
ld b, a
ldh a, [hActualG]
add a, b
ld b, a
ldh a, [hCurrentPieceX]
call XYToFieldPtr
ld d, h
ld e, l
call GetPieceData
ld a, 0
ld b, a
push hl
push de
pop hl
pop de
call DrawPiece
; If the lock delay is at the highest value, draw the piece normally.
ldh a, [hCurrentPiece]
: ldh a, [hCurrentPiece]
ld b, TILE_PIECE_0
add a, b
ldh [hWantedTile], a
@ -1131,4 +1228,242 @@ GetTileShade:
ret
FieldDelay::
ldh a, [hDelayState]
cp DELAY_STATE_DETERMINE_DELAY
jr z, .determine
cp DELAY_STATE_LINE_CLEAR
jr z, .lineclear
cp DELAY_STATE_ARE
jr z, .are
.determine
call FindClearedLines
ldh a, [hClearedLines]
ld b, a
ldh a, [hClearedLines+1]
ld c, a
ldh a, [hClearedLines+2]
ld d, a
ldh a, [hClearedLines+3]
and a, b
and a, c
and a, d
cp a, $FF
jr z, .skip
ld a, DELAY_STATE_LINE_CLEAR
ldh [hDelayState], a
ldh a, [hCurrentLineClearDelay]
ldh [hRemainingDelay], a
call MarkClear
jr .lineclear
.skip
ld a, DELAY_STATE_ARE
ldh [hDelayState], a
ldh a, [hCurrentARE]
ldh [hRemainingDelay], a
jr .are
.lineclear
ldh a, [hRemainingDelay]
dec a
ldh [hRemainingDelay], a
cp a, 0
ret nz
call ClearLines
call SFXKill
ld a, SFX_DROP
call SFXEnqueue
ld a, DELAY_STATE_ARE
ldh [hDelayState], a
ldh a, [hCurrentARE]
ldh [hRemainingDelay], a
.are
ldh a, [hRemainingDelay]
dec a
ldh [hRemainingDelay], a
cp a, 0
ret nz
; If we're out of delay, spawn a new piece.
call SFXKill
ret
AppendClearedLine:
ldh a, [hClearedLines+2]
ldh [hClearedLines+3], a
ldh a, [hClearedLines+1]
ldh [hClearedLines+2], a
ldh a, [hClearedLines]
ldh [hClearedLines+1], a
ld a, b
ldh [hClearedLines], a
ret
FindClearedLines:
ld a, $FF
ld c, 0
ldh [hClearedLines], a
ldh [hClearedLines+1], a
ldh [hClearedLines+2], a
ldh [hClearedLines+3], a
DEF row = 23
REPT 24
ld hl, wShadowField+2+(row*14)
ld b, 11
: ld a, [hl+]
dec b
cp a, $FF
jr z, :+
cp a, TILE_FIELD_EMPTY
jr nz, :-
: xor a, a
cp a, b
jr nz, .next\@
ld b, 23-row
call AppendClearedLine
inc c
ld a, 4
cp a, c
ret z
DEF row -= 1
.next\@
ENDR
ret
MarkClear:
ld a, [hClearedLines]
cp a, $FF
ret z
ld hl, wField+(24*10)
: ld bc, -10
add hl, bc
dec a
cp a, $FF
jr nz, :-
ld bc, 10
ld d, TILE_CLEARING
call UnsafeMemSet
ld a, [hClearedLines+1]
cp a, $FF
ret z
ld hl, wField+(24*10)
: ld bc, -10
add hl, bc
dec a
cp a, $FF
jr nz, :-
ld bc, 10
ld d, TILE_CLEARING
call UnsafeMemSet
ld a, [hClearedLines+2]
cp a, $FF
ret z
ld hl, wField+(24*10)
: ld bc, -10
add hl, bc
dec a
cp a, $FF
jr nz, :-
ld bc, 10
ld d, TILE_CLEARING
call UnsafeMemSet
ld a, [hClearedLines+3]
cp a, $FF
ret z
ld hl, wField+(24*10)
: ld bc, -10
add hl, bc
dec a
cp a, $FF
jr nz, :-
ld bc, 10
ld d, TILE_CLEARING
call UnsafeMemSet
ret
ClearLines:
ld de, 0
DEF row = 23
REPT 24
; Check if the row begins with a clearing tile.
ld hl, wField+(row*10)
ld a, [hl]
cp a, TILE_CLEARING
; If it does, increment the clearing counter, but skip this line.
jr nz, .clear\@
inc de
inc de
inc de
inc de
inc de
inc de
inc de
inc de
inc de
inc de
jr .r\@
.clear\@
; If there's 0 lines that need to be moved down, skip this line.
xor a, a
cp a, e
jr z, .r\@
; Otherwise...
ld bc, wField+(row*10)
add hl, de
: ld a, [bc]
ld [hl+], a
inc bc
ld a, [bc]
ld [hl+], a
inc bc
ld a, [bc]
ld [hl+], a
inc bc
ld a, [bc]
ld [hl+], a
inc bc
ld a, [bc]
ld [hl+], a
inc bc
ld a, [bc]
ld [hl+], a
inc bc
ld a, [bc]
ld [hl+], a
inc bc
ld a, [bc]
ld [hl+], a
inc bc
ld a, [bc]
ld [hl+], a
inc bc
ld a, [bc]
ld [hl+], a
inc bc
.r\@
DEF row -= 1
ENDR
ret
ENDC

View File

@ -95,6 +95,7 @@ DEF FIELD_TOP_LEFT EQU $9800+1
DEF TILE_FIELD_EMPTY EQU 4
DEF TILE_PIECE_0 EQU 10
DEF TILE_0 EQU 66
DEF TILE_CLEARING EQU 0
DEF NEXT_BASE_X EQU 120
DEF NEXT_BASE_Y EQU 40
DEF HOLD_BASE_X EQU 120

View File

@ -1241,6 +1241,18 @@ SFXEnqueue::
ret
SFXKill::
ld a, $FF
ldh [hPlayQueue], a
ldh [hPlayQueue+1], a
ldh [hPlayQueue+2], a
ldh [hPlayQueue+3], a
xor a, a
ldh [hPlayhead], a
ldh [hPlayhead+1], a
ret
; This play routine must be called every frame.
SFXPlay::
; Load the playhead position into HL.

View File

@ -253,13 +253,22 @@ pieceInMotionMode:
jr nz, :+
ld a, MODE_DELAY
ld [wMode], a
call ToShadowField
; No fall through this time.
: jr drawStaticInfo
delayMode:
; TODO.
call FieldDelay
ldh a, [hRemainingDelay]
cp a, 0
jr nz, :+
ld a, MODE_FETCH_PIECE
ld [wMode], a
: jr drawStaticInfo
gameOverMode:
@ -268,11 +277,11 @@ gameOverMode:
ld bc, 10
call UnsafeMemCopy
ld de, sGameOver2
ld hl, wField+(11*10)
ld hl, wField+(12*10)
ld bc, 10
call UnsafeMemCopy
ld de, sGameOver3
ld hl, wField+(12*10)
ld hl, wField+(14*10)
ld bc, 10
call UnsafeMemCopy

View File

@ -1,5 +1,6 @@
#Emulicious settings file
#Fri Oct 20 12:46:32 CEST 2023
#Fri Oct 20 16:26:17 CEST 2023
WindowProfilerWindowOpen=false
WindowEventViewerWindowHeight=1416
WindowEventViewerWindowDivider=876
WindowMemoryTracerWindowY=631
@ -7,14 +8,19 @@ WindowMemoryTracerWindowX=383
Update=2
AudioSync=false
DebuggerMemoryTabVisibleRect=0,0,0,0
WindowProfilerWindowWidth=1073
UninitializedMemoryBreakpointSuspend=true
GameBoyErrorBreakpointEnabled32=false
SMSGamepadBThreshold=50
RegistersGameBoy=AF,BC,DE,HL,SP,PC,LCDC,STAT,LY,DIV,IE,IF
SMSbuttonsThreshold=50
ProfileInterruptsInSeparateRoots=true
WindowRAMWatchWindowY=737
WindowRAMWatchWindowX=1766
GBGamepadThreshold=50
GameBoyErrorBreakpointEnabled20=false
StretchToWindow=false
WindowProfilerWindowHeight=563
WindowTileViewerOpen=false
DebuggerWestPanelSelectedTab=0
WindowMemoryTracerWindowWidth=1136
@ -72,7 +78,7 @@ InterruptBreakpointEnabled=false
OutlineWidth=425
DebuggerEventFiltersGameBoy=
GameBoyErrorBreakpointSuspend9=true
WindowMemoryEditorOpen=true
WindowMemoryEditorOpen=false
GameBoyErrorBreakpointSuspend8=true
GameBoyErrorBreakpointSuspend7=true
WindowPaletteViewerY=619
@ -99,7 +105,7 @@ Gamepad1Key30=-1
BankSwapAtPCBreakpointEnabled=false
DebuggerMemorySelectedTab=HRAM
WindowVideoViewerOpen=false
WindowMemoryEditorTabVisibleRect=0,496,583,384
WindowMemoryEditorTabVisibleRect=0,0,583,128
Gamepad1Key29=-1
Gamepad1Key28=-1
Gamepad1Key27=-1
@ -126,9 +132,9 @@ Key1=75
Key0=74
Gamepad1Key19=-1
Gamepad1Key18=-1
WindowEventViewerWindowY=99
WindowEventViewerWindowY=24
Gamepad1Key17=-1
WindowEventViewerWindowX=570
WindowEventViewerWindowX=0
Gamepad1Key16=-1
Gamepad1Key15=-1
Gamepad1Key14=-1
@ -136,7 +142,7 @@ Gamepad1Key13=-1
Gamepad1Key12=-1
Gamepad1Key11=-1
Gamepad1Key10=-1
WindowMemoryEditorSelectedAddress=503
WindowMemoryEditorSelectedAddress=37
WindowMemoryEditorWidth=665
GameBoyErrorBreakpointCondition9=
GameBoyErrorBreakpointCondition8=
@ -155,7 +161,7 @@ Gamepad0Key35=-1
Gamepad0Key34=-1
Gamepad0Key33=-1
Gamepad0Key32=-1
WindowMemoryEditorSelectedTab=RAM
WindowMemoryEditorSelectedTab=HRAM
Gamepad0Key31=-1
Gamepad0Key30=-1
SMSGamepadAThreshold=50
@ -178,8 +184,8 @@ Gamepad0Key20=-1
DebuggerSouthPanelSelectedTab=1
WindowEmuliciousWidth=816
WindowVideoViewerWidth=980
WindowMemoryEditorY=732
WindowMemoryEditorX=2558
WindowMemoryEditorY=695
WindowMemoryEditorX=243
Gamepad0Key19=-1
Gamepad0Key18=-1
Gamepad0Key17=-1
@ -199,8 +205,8 @@ GameBoyErrorBreakpointMessage32=
InterruptBreakpointCondition=
Recent0=C\:\\workspace\\dmgtris\\bin\\out.gb
GameBoyErrorBreakpointMessage20=
WindowEmuliciousY=302
WindowEmuliciousX=153
WindowEmuliciousY=367
WindowEmuliciousX=982
GameBoyErrorBreakpointEnabled9=false
GameBoyErrorBreakpointEnabled8=false
GameBoyErrorBreakpointEnabled7=false
@ -264,14 +270,16 @@ Gamepad0Key3=-1
Gamepad0Key2=-1
Gamepad0Key1=-1
Gamepad0Key0=-1
WindowDebuggerY=201
WindowDebuggerX=727
WindowDebuggerY=730
WindowDebuggerX=1234
InterruptBreakpointSuspend=true
SMSGamepadAKeyboard=false
GameBoyErrorBreakpointSuspend32=true
WindowRAMWatchWindowHeight=470
SMSGamepadB=-1
SMSGamepadA=-1
WindowEventViewerWindowWidth=2576
WindowRAMWatchWindowOpen=false
BankSwapAtPCBreakpointCondition=
GameBoyErrorBreakpointSuspend20=true
SouthPanelHeight=635
@ -285,7 +293,11 @@ GameBoyErrorBreakpointSuspend19=true
GameBoyErrorBreakpointSuspend18=true
GameBoyErrorBreakpointSuspend17=true
GameBoyErrorBreakpointSuspend16=true
WindowRAMWatchWindowWidth=376
GameBoyErrorBreakpointSuspend10=true
WindowSpriteViewerOpen=false
WindowProfilerWindowY=639
WindowProfilerWindowX=461
Scale=5.0
KeyboardRequireWindowFocus=true
WindowProfilerWindowProcedureProfiler=true

View File

@ -9,3 +9,5 @@ hPieceDataOffset 1 Hexadecimal
hCurrentPiece 1 Hexadecimal
hCurrentPieceY 1 Hexadecimal
hUpState 1 Hexadecimal
hActualG 1 Hexadecimal
hClearedLines 4 Hexadecimal