diff --git a/bin/DMGTRIS.GBC b/bin/DMGTRIS.GBC index 4ada00d..41d46de 100644 Binary files a/bin/DMGTRIS.GBC and b/bin/DMGTRIS.GBC differ diff --git a/bin/DMGTRIS.pocket b/bin/DMGTRIS.pocket index 2404940..b703ac0 100644 Binary files a/bin/DMGTRIS.pocket and b/bin/DMGTRIS.pocket differ diff --git a/src/field.asm b/src/field.asm index c3c4a28..5915aca 100644 --- a/src/field.asm +++ b/src/field.asm @@ -33,6 +33,8 @@ SECTION "Field Variables", WRAM0 wField:: ds (10*24) wBackupField:: ds (10*24) wShadowField:: ds (14*26) +wWideField:: ds (5*10) +wWideBlittedField:: ds (20*10) wDelayState: ds 1 @@ -118,6 +120,62 @@ BlitField:: jp EventLoop + ; Blits the field onto the tile map. + ; On the GBC, this chain calls into a special version that takes + ; advantage of the GBC's CPU. +BigBlitField:: + ld a, [wInitialA] + cp a, $11 + jp z, GBCBlitField + + ; What to copy + ld de, wWideBlittedField + ; Where to put it + ld hl, FIELD_TOP_LEFT + ; How much to increment hl after each row + ld bc, 32-10 + + ; The first 14 rows can be blitted without checking for vram access. + REPT 14 + REPT 10 + ld a, [de] + ld [hl+], a + inc de + ENDR + add hl, bc + ENDR + +: ldh a, [rLY] + cp a, 0 + jr nz, :- + + ; The last 6 rows need some care. + REPT 6 + ; Wait until start of drawing, then insert 35 nops. +: ldh a, [rSTAT] + and a, 3 + cp a, 3 + jr nz, :- + REPT 35 + nop + ENDR + + ; Blit a line. + REPT 10 + ld a, [de] + ld [hl+], a + inc de + ENDR + + ; Increment HL so that the next line can be blitted. + add hl, bc + ENDR + + ; This function is actually called as the vblank handler for the gameplay state. + ; This is why it jumps straight back to the event loop. + jp EventLoop + + SECTION "Field Function Banked Gameplay", ROMX, BANK[BANK_GAMEPLAY] ; Initializes the field completely blank. ; Initializes the combo counter to 1. @@ -2173,6 +2231,10 @@ BigFieldInit:: ld bc, 10*24 ld d, TILE_BLANK call UnsafeMemSet + ld hl, wWideBlittedField + ld bc, 10*20 + ld d, TILE_BLANK + call UnsafeMemSet ld hl, wShadowField ld bc, 14*26 ld d, $FF @@ -3667,7 +3729,8 @@ BigFieldProcess:: pop hl pop de call BigDrawPiece - ret + jp WidenField + ; Performs a lookup to see how "locked" the piece is. BigGetTileShade: @@ -3966,7 +4029,7 @@ BigFieldDelay:: dec a ldh [hRemainingDelay], a cp a, 0 - ret nz + jp nz, WidenField call BigClearLines ld a, SFX_LINE_CLEAR @@ -4000,7 +4063,7 @@ BigFieldDelay:: dec a ldh [hRemainingDelay], a cp a, 0 - ret nz + jp nz, WidenField ; Add one level if we're not at a breakpoint. ldh a, [hRequiresLineClear] @@ -4228,4 +4291,60 @@ BigClearLines: ret +WidenField:: + ld de, wField+(4*10) + ld hl, wWideField + ld bc, 5 + call UnsafeMemCopy + ld de, wField+(5*10) + ld hl, wWideField+5 + ld bc, 5 + call UnsafeMemCopy + ld de, wField+(6*10) + ld hl, wWideField+10 + ld bc, 5 + call UnsafeMemCopy + ld de, wField+(7*10) + ld hl, wWideField+15 + ld bc, 5 + call UnsafeMemCopy + ld de, wField+(8*10) + ld hl, wWideField+20 + ld bc, 5 + call UnsafeMemCopy + ld de, wField+(9*10) + ld hl, wWideField+25 + ld bc, 5 + call UnsafeMemCopy + ld de, wField+(10*10) + ld hl, wWideField+30 + ld bc, 5 + call UnsafeMemCopy + ld de, wField+(11*10) + ld hl, wWideField+35 + ld bc, 5 + call UnsafeMemCopy + ld de, wField+(12*10) + ld hl, wWideField+40 + ld bc, 5 + call UnsafeMemCopy + ld de, wField+(13*10) + ld hl, wWideField+45 + ld bc, 5 + call UnsafeMemCopy + + DEF piece = 0 + REPT 50 + ld a, [wWideField+piece] + ld hl, wWideBlittedField+((piece/5)*20)+((piece%5) * 2) + ld [hl+], a + ld [hl], a + ld hl, wWideBlittedField+((piece/5)*20)+((piece%5) * 2)+10 + ld [hl+], a + ld [hl], a + DEF piece += 1 + ENDR + ret + + ENDC diff --git a/src/gbc.asm b/src/gbc.asm index 4e5f960..f43001a 100644 --- a/src/gbc.asm +++ b/src/gbc.asm @@ -919,6 +919,223 @@ GBCGameplayProcess:: ret +GBCBigGameplayProcess:: + ld a, [wInitialA] + cp a, $11 + ret nz + + ; Color based on mode. + ld a, [wSpeedCurveState] + cp a, SCURVE_DMGT + ld a, $05 ;Blue + jr z, .goverride + ld a, [wSpeedCurveState] + cp a, SCURVE_TGM1 + ld a, $06 ;Cyan + jr z, .goverride + ld a, [wSpeedCurveState] + cp a, SCURVE_TGM3 + ld a, $03 ;Blue + jr z, .goverride + ld a, [wSpeedCurveState] + cp a, SCURVE_DEAT + ld a, $00 ;Red + jr z, .goverride + ld a, [wSpeedCurveState] + cp a, SCURVE_SHIR + ld a, $00 ;Red + jr z, .goverride ;Always red + ld a, [wSpeedCurveState] + cp a, SCURVE_CHIL + ld a, $01 ;Green + + ; Are we 20G? +.goverride + ld d, a + ldh a, [hCurrentIntegerGravity] + cp a, 20 + jr c, :+ + ld a, $00 + ld d, a + jr .colorfield +: cp a, 3 + jr c, :+ + ld a, $04 + ld d, a + jr .colorfield +: cp a, 2 + jr c, :+ + ld a, $05 + ld d, a + jr .colorfield +: ldh a, [hCurrentFractionalGravity] + cp a, 0 + jr nz, .colorfield + ld a, $05 + ld d, a + +.colorfield + ld hl, wShadowTileAttrs + ld bc, 32-12 + + ld a, 21 + ld [wOuterReps], a +.outer0 + ld a, 12 + ld [wInnerReps], a +.inner0 + ld [hl], d + inc hl + ld a, [wInnerReps] + dec a + ld [wInnerReps], a + jr nz, .inner0 + + add hl, bc + ld a, [wOuterReps] + dec a + ld [wOuterReps], a + jr nz, .outer0 + + + ; What to copy +: ld de, wWideBlittedField + ; Where to put it + ld hl, wShadowTilemap + 1 + ; How much to increment hl after each row + ld bc, 32-10 + + ; Blit me up daddy. + ld a, 20 + ld [wOuterReps], a +.outer1 + ld a, 10 + ld [wInnerReps], a +.inner1 + ld a, [de] + ld [hl+], a + inc de + ld a, [wInnerReps] + dec a + ld [wInnerReps], a + jr nz, .inner1 + + add hl, bc + ld a, [wOuterReps] + dec a + ld [wOuterReps], a + jr nz, .outer1 + + + ; What to copy + ld de, wWideBlittedField + ; Where to put it + ld hl, wShadowTileAttrs + 1 + ; How much to increment hl after each row + ld bc, 32-10 + + ; Blit me up daddy. + ld a, 20 + ld [wOuterReps], a +.outer2 + ld a, 10 + ld [wInnerReps], a +.inner2 + ld a, [de] + cp a, 10 + jr c, .empty + cp a, 10 + (1*7) + jr c, .sub10 + cp a, 10 + (2*7) + jr c, .sub17 + cp a, 10 + (3*7) + jr c, .sub24 + cp a, 10 + (4*7) + jr c, .sub31 + cp a, 10 + (5*7) + jr c, .sub38 + cp a, 10 + (6*7) + jr c, .sub45 + cp a, 10 + (7*7) + jr c, .sub52 + cp a, 10 + (8*7) + jr c, .sub59 +.empty + ld a, $07 + jr .done +.sub59 + sub a, 7 +.sub52 + sub a, 7 +.sub45 + sub a, 7 +.sub38 + sub a, 7 +.sub31 + sub a, 7 +.sub24 + sub a, 7 +.sub17 + sub a, 7 +.sub10 + sub a, 10 +.done + ld [hl+], a + inc de + ld a, [wInnerReps] + dec a + ld [wInnerReps], a + jr nz, .inner2 + + add hl, bc + ld a, [wOuterReps] + dec a + ld [wOuterReps], a + jr nz, .outer2 + + ; Maybe flash numbers. + ldh a, [hCurrentIntegerGravity] + cp a, 20 + jr nz, .black + + ld hl, hFrameCtr + bit 4, [hl] + jr z, .lighter + +.darker + ld a, OCPSF_AUTOINC | (7*8)+(3*2) + ldh [rOCPS], a + ld bc, R1 | G1 + wait_vram + ld a, c + ldh [rOCPD], a + ld a, b + ldh [rOCPD], a + ret + +.lighter + ld a, OCPSF_AUTOINC | (7*8)+(3*2) + ldh [rOCPS], a + ld bc, R2 | G2 + wait_vram + ld a, c + ldh [rOCPD], a + ld a, b + ldh [rOCPD], a + ret + +.black + ld a, OCPSF_AUTOINC | (7*8)+(3*2) + ldh [rOCPS], a + ld bc, R2 | B0 + wait_vram + ld a, c + ldh [rOCPD], a + ld a, b + ldh [rOCPD], a + ret + + ; Copies the shadow tile maps to VRAM using HDMA. The attributes are copied using instant mode ; The tile data is done using hblank mode. GBCBlitField:: diff --git a/src/main.asm b/src/main.asm index e1f5f54..6df3f78 100644 --- a/src/main.asm +++ b/src/main.asm @@ -156,7 +156,7 @@ EventLoopPostHandler:: .vblankjumps jp TitleVBlankHandler jp BlitField - jp BlitField + jp BigBlitField ; The VBlank Handler is expected to end with jp EventLoop. diff --git a/src/state_gameplay.asm b/src/state_gameplay.asm index e174984..14d038c 100644 --- a/src/state_gameplay.asm +++ b/src/state_gameplay.asm @@ -797,7 +797,7 @@ GamePlayBigEventLoopHandlerB: ld a, GO_TIME : ldh [hModeCounter], a ld de, sBigLeady - ld hl, wField+(14*10) + ld hl, wWideBlittedField+(10*10) ld bc, 10 call UnsafeMemCopy jp .drawStaticInfo @@ -813,7 +813,7 @@ GamePlayBigEventLoopHandlerB: xor a, a : ldh [hModeCounter], a ld de, sBigGo - ld hl, wField+(14*10) + ld hl, wWideBlittedField+(10*10) ld bc, 10 call UnsafeMemCopy jp .drawStaticInfo @@ -1010,10 +1010,11 @@ GamePlayBigEventLoopHandlerB: .preGameOverMode ; Spawn the failed piece. call BigForceSpawnPiece + call WidenField ; Draw the field in grey. ; Yes. This really unrolls the loop that many times. - ld hl, wField+(4*10) + ld hl, wWideBlittedField REPT 60 ld a, [hl] cp a, TILE_FIELD_EMPTY @@ -1159,43 +1160,43 @@ GamePlayBigEventLoopHandlerB: ; Draw PAUSE all over the field. : ld de, sBigPause - ld hl, wField+(4*10) + ld hl, wWideBlittedField ld bc, 20 call UnsafeMemCopy ld de, sBigPause - ld hl, wField+(6*10) + ld hl, wWideBlittedField+20 ld bc, 20 call UnsafeMemCopy ld de, sBigPause - ld hl, wField+(8*10) + ld hl, wWideBlittedField+40 ld bc, 20 call UnsafeMemCopy ld de, sBigPause - ld hl, wField+(10*10) + ld hl, wWideBlittedField+60 ld bc, 20 call UnsafeMemCopy ld de, sBigPause - ld hl, wField+(12*10) + ld hl, wWideBlittedField+80 ld bc, 20 call UnsafeMemCopy ld de, sBigPause - ld hl, wField+(14*10) + ld hl, wWideBlittedField+100 ld bc, 20 call UnsafeMemCopy ld de, sBigPause - ld hl, wField+(16*10) + ld hl, wWideBlittedField+120 ld bc, 20 call UnsafeMemCopy ld de, sBigPause - ld hl, wField+(18*10) + ld hl, wWideBlittedField+140 ld bc, 20 call UnsafeMemCopy ld de, sBigPause - ld hl, wField+(20*10) + ld hl, wWideBlittedField+160 ld bc, 20 call UnsafeMemCopy ld de, sBigPause - ld hl, wField+(22*10) + ld hl, wWideBlittedField+180 ld bc, 20 call UnsafeMemCopy jr .drawStaticInfo @@ -1221,7 +1222,7 @@ GamePlayBigEventLoopHandlerB: ld de, hNLevel call ApplyNumbers - jp GBCGameplayProcess + jp GBCBigGameplayProcess ; Do the hold action.