Claim set · data/claims/tetris-demo.yaml

Tetris (NES) demo (CelestialAmber/TetrisNESDisasm)

Game: Tetris (NES).

Tetris (NES, US build) starts its demo when the title screen has waited for Start until the frame counter's high byte, cleared as the title appears, reaches 5: between 1,025 and 1,280 frames (computed), about 17 to 21 seconds. The demo stores 0 as the game type, which the disassembly's comment names A-type, and 0 as the start level. tetris-demo/start

About: Tetris (NES) Demo playback

Value
{
 "counterHighByte": 5,
 "framesMin": 1025,
 "framesMax": 1280
}
CodeTetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L603-L633lda #$00 sta frameCounter+1 … @waitForStartButton: jsr updateAudioWaitForNmiAndResetOamStaging lda newlyPressedButtons_player1 cmp #BUTTON_START beq @startButtonPressed lda frameCounter+1 cmp #$05 beq @timeout … …TetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L263-L269lda frameCounter clc adc #$01 sta frameCounter lda #$00 adc frameCounter+1 sta frameCounter+1TetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L3735-L3743gameMode_startDemo: lda #$00 sta gameType sta player1_startLevel … lda #$05 sta gameModeTetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L132-L133gameMode := $00C0 ; 0=legal, 1=title, 2=type menu, 3=level menu, 4=play and ending and high score, 5=demo, 6=start demo gameType := $00C1 ; A=0, B=1Checked by claude, 2026-10-22 — read the title screen's wait loop, the NMI's 16-bit frame counter, and gameMode_startDemo at the pinned commit; only the high byte is cleared, so the low byte's start sets where in 1,025-1,280 frames the timeout falls; the frame rate (60.1 Hz NTSC) scales the seconds

Cited by: Demo playback

The US build's demo plays a table of 256 pairs, a controller byte and a count; the demo code holds each byte for its count plus one frame, about 4,780 frames in all (computed), some 80 seconds. It writes the held buttons and the newly pressed ones into the same two bytes the controller routine fills, so the pieces move by the ordinary play code. The @recording branch of the same routine writes such pairs from the live controller when $D0 holds $FF, but the code's only store to $D0 writes 0. tetris-demo/buttons

About: Tetris (NES) Demo playback

Value
{
 "pairs": 256,
 "frames": 4784
}
CodeTetrisNESDisasm: a disassembly of Tetris (NES) · data/demo_data.asm#L1-L3; $80-a $40-b $20-select $10-start $08-up $04-down $02-left $01-right $00-no input ;2nd number is number of frames the input is held for demoButtonsTable:TetrisNESDisasm: a disassembly of Tetris (NES) · data/demo_data.asm#L69-L71.else .byte $00,$31,$40,$06,$00,$04,$40,$07TetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L3637-L3676@demoGameMode: lda $D0 cmp #$FF beq @recording jsr pollController … lda demo_repeats beq @finishedMove dec demo_repeats jmp @moveInProgress @finishedMove: ldx #$00 …TetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L5541-L5549diffOldAndNewButtons: … eor heldButtons_player1,x and newlyPressedButtons_player1,x sta newlyPressedButtons_player1,x sty heldButtons_player1,xTetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L282jsr pollControllerButtonsTetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L3687-L3720@recording: jsr pollController … lda heldButtons_player1 cmp demo_heldButtons beq @buttonsNotChanged ldx #$00 lda demo_heldButtons sta (demoButtonsAddr,x) … lda demo_repeats sta (demoButtonsAddr,x) …TetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L563sta $D0Checked by claude, 2026-10-22 — the US table (data/demo_data.asm L70-L133, the .else of PAL) holds 512 bytes, 256 pairs, whose counts sum to 4,528, plus one frame per pair = 4,784; the pair read on the frame the address reaches the piece table is not held, hence "about"; the recorder counts frames after a change (demo_repeats from 0), so a count is frames held minus one, not the frames the disassembly's comment gives; pollControllerButtons runs from the NMI (L282), once a frame; grep finds one write to $D0, `sta $D0` at L563 in gameMode_titleScreen after `lda #$00` (L561)

Cited by: Demo playback

The demo's pieces come from a fixed list, not the randomizer: in demo mode chooseNextTetrimino reads the next byte of the 256-byte demoTetriminoTypeTable, from 0 at each game start, and takes bits 4-6 as an index into the 7-entry spawn table. An index of 7 reads the byte after the table, $02, the T piece's spawn orientation, so 2 of the 8 index values give a T; 45 of the table's 256 bytes carry a 7 (computed). tetris-demo/pieces

About: Tetris (NES) Demo playback

Value
{
 "tableBytes": 256,
 "bits": "4-6",
 "indexSevenBytes": 45
}
CodeTetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L2949-L2962lda gameMode cmp #$05 bne pickRandomTetrimino ldx demoIndex inc demoIndex lda demoTetriminoTypeTable,x lsr a lsr a lsr a lsr a and #$07 tax …TetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L3013-L3020spawnTable: .byte tDown, jDown, zHoriz, oFixed, sHoriz, lDown, iHoriz ; unused portion of spawnTable: .if NWC = 1 .byte $12 .else .byte $02TetrisNESDisasm: a disassembly of Tetris (NES) · constants.asm#L123tDown = $02TetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L1229-L1236sta allegro sta demo_heldButtons sta demo_repeats sta demoIndexTetrisNESDisasm: a disassembly of Tetris (NES) · data/demo_data.asm#L136-L137demoTetriminoTypeTable: .byte $00,$14,$8A,$45,$22,$11,$88,$44Checked by claude, 2026-10-22 — read chooseNextTetrimino, spawnTable and the byte after it, and the demo resets in gameModeState_initGameState at the pinned commit; the zeroed bytes are stored from A = 0 (the stores begin with `lda #$00`); counted (byte >> 4) & 7 == 7 over the 256 bytes of data/demo_data.asm L137-L167; how many of the 256 the demo uses before it ends isn't read

Cited by: Demo playback

The demo stores 1 as the game mode, which the disassembly's comment names the title screen, when the button table runs out, its read address reaching the piece table's page, or when Start is pressed. The game-over routine has no demo case: a one-player game over, in the demo as in play, stores $03, which the comment names the level menu. tetris-demo/end

About: Tetris (NES) Demo playback

CodeTetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L412-L424@checkForDemoDataExhaustion: lda gameMode cmp #$05 bne @continue lda demoButtonsAddr+1 cmp #>demoTetriminoTypeTable bne @continue … lda #$01 sta gameModeTetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L3642-L3644lda newlyPressedButtons_player1 cmp #BUTTON_START beq @startButtonPressedTetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L3678-L3684@startButtonPressed: lda #>demoButtonsTable sta demoButtonsAddr+1 lda #$00 sta frameCounter+1 lda #$01 sta gameModeTetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L3545-L3591gameModeState_handleGameOver: … @onePlayerGameOver: … jsr handleHighScoreIfNecessary … lda #$03 sta gameModeTetrisNESDisasm: a disassembly of Tetris (NES) · main.asm#L132gameMode := $00C0 ; 0=legal, 1=title, 2=type menu, 3=level menu, 4=play and ending and high score, 5=demo, 6=start demoChecked by claude, 2026-10-22 — read the main loop's exhaustion test, pollControllerButtons' Start test, and gameModeState_handleGameOver at the pinned commit; the game-over routine never reads gameMode; whether the shipped demo ever tops out isn't read

Cited by: Demo playback