Skip to content

Reduce cycles and byte usage #135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions src/data/mult.asm

This file was deleted.

105 changes: 105 additions & 0 deletions src/data/mult_orient.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
; multiplication and orientation tables
; Combined to share a common page. Crossing page boundaries in table lookups
; costs an extra cycle and causes timing variance that can add up. One advantage
; of these tables taking nearly a full page is being able to use the end of the
; page for lookups to the multBy10Table. The game logic multiplies tetriminoY (or
; offsets determined by the orientation table) by 10 frequently. During these
; calculations, this value is never less than -2 and never greater than 20. A 256
; byte lookup table would be mostly wasteful except the first 20 and last 2 bytes.
; The repeated calls to isPositionValid used for harddrop and 0 arr see a massive
; impact from these optimisations.

; mult10Tail at end of this page allows table lookup for all possible values of tetriminoY (-2..=20)
multOrientBegin:
.assert <multOrientBegin = 0, warning, "multOrientBegin not aligned to page boundary"


; multyBy10Table needs to be first in this page with mult10Tail last
multBy10Table: ; 20
.byte $00,$0A,$14,$1E,$28,$32,$3C,$46
.byte $50,$5A,$64,$6E,$78,$82,$8C,$96
.byte $A0,$AA,$B4,$BE

multBy32Table: ; 8
.byte 0,32,64,96,128,160,192,224

multBy100Table: ; 10
.byte $00,$64,$C8,$2C,$90
.byte $F4,$58,$BC,$20,$84

spawnTable: ; 7
.byte $02,$07,$08,$0A,$0B,$0E,$12

tetriminoTypeFromOrientation: ; 19
.byte $00,$00,$00,$00 ; t
.byte $01,$01,$01,$01 ; j
.byte $02,$02 ; z
.byte $03 ; o
.byte $04,$04 ; s
.byte $05,$05,$05,$05 ; l
.byte $06,$06 ; i

tetriminoTileFromOrientation: ; 20
.byte $7B,$7B,$7B,$7B ; t
.byte $7D,$7D,$7D,$7D ; j
.byte $7C,$7C ; z
.byte $7B ; o
.byte $7D,$7D ; s
.byte $7C,$7C,$7C,$7C ; l
.byte $7B,$7B ; i
.byte $FF ; hidden

orientationTableY: ; 80
.byte $00,$00,$00,$FF ; $00 t up
.byte $FF,$00,$00,$01 ; $01 t right
.byte $00,$00,$00,$01 ; $02 t down
.byte $FF,$00,$00,$01 ; $03 t left
.byte $FF,$00,$01,$01 ; $04 j left
.byte $FF,$00,$00,$00 ; $05 j up
.byte $FF,$FF,$00,$01 ; $06 j right
.byte $00,$00,$00,$01 ; $07 j down
.byte $00,$00,$01,$01 ; $08 z horizontal
.byte $FF,$00,$00,$01 ; $09 z vertical
.byte $00,$00,$01,$01 ; $0a o
.byte $00,$00,$01,$01 ; $0b s horizontal
.byte $FF,$00,$00,$01 ; $0c s vertical
.byte $FF,$00,$01,$01 ; $0d l right
.byte $00,$00,$00,$01 ; $0e l down
.byte $FF,$FF,$00,$01 ; $0f l left
.byte $FF,$00,$00,$00 ; $10 l up
.byte $FE,$FF,$00,$01 ; $11 i vertical
.byte $00,$00,$00,$00 ; $12 i horizontal
.byte $00,$00,$00,$00 ; $13 hidden

orientationTableX: ; 80
.byte $FF,$00,$01,$00 ; $00 t up
.byte $00,$00,$01,$00 ; $01 t right
.byte $FF,$00,$01,$00 ; $02 t down
.byte $00,$FF,$00,$00 ; $03 t left
.byte $00,$00,$FF,$00 ; $04 j left
.byte $FF,$FF,$00,$01 ; $05 j up
.byte $00,$01,$00,$00 ; $06 j right
.byte $FF,$00,$01,$01 ; $07 j down
.byte $FF,$00,$00,$01 ; $08 z horizontal
.byte $01,$00,$01,$00 ; $09 z vertical
.byte $FF,$00,$FF,$00 ; $0a o
.byte $00,$01,$FF,$00 ; $0b s horizontal
.byte $00,$00,$01,$01 ; $0c s vertical
.byte $00,$00,$00,$01 ; $0d l right
.byte $FF,$00,$01,$FF ; $0e l down
.byte $FF,$00,$00,$00 ; $0f l left
.byte $01,$FF,$00,$01 ; $10 l up
.byte $00,$00,$00,$00 ; $11 i vertical
.byte $FE,$FF,$00,$01 ; $12 i horizontal
.byte $00,$00,$00,$00 ; $13 hidden

; unused. padding required for mult10Tail
.repeat 10
.byte $00
.endrepeat

; needs to be last table in this page
mult10Tail: ; 2
.byte $EC,$F6 ; -20,-10

.assert multBy10Table + $fe = mult10Tail, error, "mult10Tail is not multBy10Table + $FE"
39 changes: 0 additions & 39 deletions src/data/orientation.asm

This file was deleted.

6 changes: 3 additions & 3 deletions src/main.asm
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@ mainLoop:
.include "sprites/piece.asm"

.include "data/bytebcd.asm"
.include "data/orientation.asm"
.include "data/mult.asm"

.include "palettes.asm"
.include "nametables.asm"
Expand All @@ -93,7 +91,9 @@ mainLoop:
.include "modes/qtap.asm"
.include "modes/garbage.asm"

.code
.align $100
; these tables benefit from page alignment
.include "data/mult_orient.asm"

.segment "PRG_chunk3": absolute

Expand Down
32 changes: 12 additions & 20 deletions src/playstate/active.asm
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,8 @@ harddrop_tetrimino:
beq playState_playerControlsActiveTetrimino_return
lda tetriminoY
sta tmpY
@loop:
inc tetriminoY
jsr isPositionValid
beq @loop
dec tetriminoY
lda hardDropGhostY ; value set by previous frame's sprite staging
sta tetriminoY

; sonic drop
lda newlyPressedButtons
Expand Down Expand Up @@ -119,16 +116,13 @@ harddropMarkCleared:
sta harddropAddr

; check for empty row
ldy #$0
ldy #$9
@minoLoop:
lda (harddropAddr), y
cmp #EMPTY_TILE
beq @noLineClear
bmi @noLineClear ; EMPTY_TILE sets negative flag, normal tiles do not

iny
cpy #$A
beq @lineClear
jmp @minoLoop
dey
bpl @minoLoop

@lineClear:
lda #1
Expand Down Expand Up @@ -196,14 +190,13 @@ harddropShift:
sbc lineOffset
sta harddropAddr+2

ldy #0
ldy #9
@shiftLineLoop:
lda (harddropAddr+2), y
sta (harddropAddr), y

iny
cpy #$A
bne @shiftLineLoop
dey
bpl @shiftLineLoop

@nextLine:
dec tmpY
Expand All @@ -222,12 +215,11 @@ harddropShift:
sta completedLines
; emty top row
lda #EMPTY_TILE
ldx #0
ldx #9
@topRowLoop:
sta playfield, x
inx
cpx #$A
bne @topRowLoop
dex
bpl @topRowLoop
; lda #TETRIMINO_X_HIDE
; sta tetriminoX

Expand Down
37 changes: 12 additions & 25 deletions src/playstate/lock.asm
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
playState_lockTetrimino:
@currentTile = generalCounter5
jsr isPositionValid
beq @notGameOver
@gameOver:
Expand Down Expand Up @@ -32,49 +33,35 @@ playState_lockTetrimino:
lda vramRow
cmp #$20
bmi @ret
lda tetriminoY
asl a
sta generalCounter
asl a
asl a
ldy tetriminoY
lda multBy10Table,y
clc
adc generalCounter
adc tetriminoX
sta generalCounter
lda currentPiece
asl a
ldx currentPiece
lda tetriminoTileFromOrientation,x
sta @currentTile
txa
asl a
sta generalCounter2
asl a
clc
adc generalCounter2
tax
ldy #$00
lda #$04
sta generalCounter3
; Copies a single square of the tetrimino to the playfield
@lockSquare:
lda orientationTable,x
asl a
sta generalCounter4
asl a
asl a
clc
adc generalCounter4
ldy orientationTableY,x
lda multBy10Table,y
clc
adc generalCounter
sta positionValidTmp
inx
lda orientationTable,x
sta generalCounter5
inx
lda orientationTable,x
lda orientationTableX,x
clc
adc positionValidTmp
tay
lda generalCounter5
lda @currentTile
; BLOCK_TILES
sta (playfieldAddr),y
sta playfield,y
inx
dec generalCounter3
bne @lockSquare
Expand Down
39 changes: 12 additions & 27 deletions src/playstate/util.asm
Original file line number Diff line number Diff line change
@@ -1,53 +1,38 @@
isPositionValid:
lda tetriminoY
asl a
sta generalCounter
asl a
asl a
ldy tetriminoY
lda multBy10Table,y
clc
adc generalCounter
adc tetriminoX
sta generalCounter
lda currentPiece
asl a
asl a
sta generalCounter2
asl a
clc
adc generalCounter2
tax
ldy #$00
lda #$04
sta generalCounter3
; Checks one square within the tetrimino
@checkSquare:
lda orientationTable,x
lda orientationTableY,x
clc
adc tetriminoY
adc #$02
adc #$02 ; carry may be set for this add but doesn't have any noticeable impact

cmp #$16
bcs @invalid
lda orientationTable,x
asl a
sta generalCounter4
asl a
asl a
clc
adc generalCounter4
clc

ldy orientationTableY,x
lda multBy10Table,y
; clc omitted, carry is clear from cmp instruction above that branches away on carry set
adc generalCounter
sta positionValidTmp
inx
inx
lda orientationTable,x
lda orientationTableX,x
clc
adc positionValidTmp
tay
lda (playfieldAddr),y
cmp #EMPTY_TILE
bcc @invalid
lda orientationTable,x
lda playfield,y
bpl @invalid ; tiles do not set negative flag
lda orientationTableX,x
clc
adc tetriminoX
cmp #$0A
Expand Down
3 changes: 2 additions & 1 deletion src/ram.asm
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,9 @@ dasOnlyShiftDisabled: .res 1 ; $63A
invisibleFlag: .res 1 ; $63B ; 0 for normal mode, non-zero for Invisible playfield rendering. Reset on game init and game over.
currentFloor: .res 1 ; $63C floorModifier is copied here at game init. Set to 0 otherwise and incremented when linecap floor.
mapperId: .res 1 ; $63D ; For INES_MAPPER 1000 (autodetect). 0 = CNROM. 1 = MMC1.
hardDropGhostY: .res 1 ; ghost Y used as a shortcut for hard/sonic drop

.res $37
.res $36

.if KEYBOARD
newlyPressedKeys: .res 1 ; $0675
Expand Down
Loading