Tetris

From NES Hacker Wiki
Jump to: navigation, search

Tetris is a puzzle game where you manipulate shapes to try and form lines. It is based off of the Russian game of the same name. This particular version was produced by Nintendo and is the only official version released in North America for the NES. Japan's version was produced by BPS, and Tengen's version was unauthorized.

Easy Cheats

Icon Addr Val Cmp Description
Icon-Powerup.png 00BF 12 - Next Block Is a Line
How do I use these?

North America

Tetris.png

Memory Addresses

0000-0001 - General Temporary (Often Used as 16-bit Pointer for Indirect Addressing)

0017-0018 - Random Number (16-bit Linear Feedback Shift Register)

0019 - Previous Block (To Lessen Chance of Same Block in a Row)
001A - Total Block Count (Starts at 02)

0033 - VBlank Flag (Set to 01 on VBlank NMI; Cleared When Waiting for Next VBlank)

0040-005F - Copy of 0060-7F.
0060 - Shape X
0061 - Shape Y
0062 - Shape Type + Rotation
	00 - T Up
	01 - T Right
	02 - T Down
	03 - T Left
	04 - J Left
	05 - J Up
	06 - J Right
	07 - J Down
	08 - Z 
	09 - Z Rotated
	0A - O
	0B - S
	0C - S Rotated
	0D - L Right
	0E - L Down
	0F - L Left
	10 - L Up
	11 - I
	12 - I Rotated

0064 - Level
0070 - Lines in A-Game/Remaining in B-Game
0073 - Score: xxxx99
0074 - Score: xx99xx
0075 - Score: 99xxxx

00A6 - 
00A8 - Copyright Screen Timeout to Game Type Screen
       Used as a Temporary in Other Places
 
00B1 - Frame Counter x1 (Incremented on VBlank NMI)
00B2 - Frame Counter x256

00BF - Next Block (Valid: 02, 07, 08, 0A, 0B, 0E, 12)

00C0 - Game State
	00 - Copyright
	01 - Title Screen
	02 - Game Type
	03 - Level Select
	04 - Playing / High Score / Victory Animation / Pause
	05 - Demo
00C1 - Game Type
00C2 - Music Type
00C3 - Copyright Screen Must Read Timeout

00D3 - Current Block In the Demo

00D8 - Singles
00D9 - Doubles
00DA - Triples
00DB - Quads

00F7 - Controller 1 Poll

00FC - Saved PPUSCROLL Y
00FD - Saved PPUSCROLL X
00FE - Saved PPUMASK
00FF - Saved PPUCTRL

0100-01FF - 6502 Runtime Stack (Grows Backwards from $1FF)
0200-02FF - Sprite Data (DMAed to OAM on every VBlank NMI)

03F0 - Stats: T
03F2 - Stats: J
03F4 - Stats: Z
03F6 - Stats: O
03F8 - Stats: S
03FA - Stats: L
03FC - Stats: I

0400-04FF - Pieces In the Well

High Score Table

On power-on or reset, the game checks if there's a fixed memory pattern at the end of the RAM high score table. If no pattern, then it copies the default high scores from a ROM location. The RAM and ROM data layout is identical. The high score tables also use a private character mapping for the names.

A-Type High Scores (1st Place Top Score is Displayed In-Game)

0700-0705 - 1st Place Name
0706-070B - 2nd Place Name
070C-0711 - 3rd Place Name

0730 - 1st Place Top Score: 99xxxx
0731 - 1st Place Top Score: xx99xx
0732 - 1st Place Top Score: xxxx99
0733 - 2nd Place Top Score: 99xxxx
0734 - 2nd Place Top Score: xx99xx
0735 - 2nd Place Top Score: xxxx99
0736 - 3rd Place Top Score: 99xxxx
0737 - 3rd Place Top Score: xx99xx
0738 - 3rd Place Top Score: xxxx99

0748 - 1st Place Level
0749 - 2nd Place Level
074A - 3rd Place Level

B-Type High Scores (1st Place Top Score is Displayed In-Game)

0718-071D - 1st Place Name
071E-0723 - 2nd Place Name
0724-0729 - 3rd Place Name

073C - 1st Place Top Score: 99xxxx
073D - 1st Place Top Score: xx99xx
073E - 1st Place Top Score: xxxx99
073F - 2nd Place Top Score: 99xxxx
0740 - 2nd Place Top Score: xx99xx
0741 - 2nd Place Top Score: xxxx99
0742 - 3rd Place Top Score: 99xxxx
0743 - 3rd Place Top Score: xx99xx
0744 - 3rd Place Top Score: xxxx99

074C - 1st Place Level
074D - 2nd Place Level
074E - 3rd Place Level

0750-0754 - Fixed Pattern: 12 34 56 78 9A

AD67 - Default High Score Table in ROM

Code

Pseudorandom Number Generator

The game uses a 16-bit Linear Feedback Shift Register (LFSB) to generate random numbers for choosing the next block and such. RAM locations $17-$18 store the LFSB value, but code that actually needs a random number only ever uses $17.

; Code to initialize $17 and $18 after reset
80BC:A2 89     LDX #$89
80BE:86 17     STX $0017 ; Store #$89 in $0017
80C0:CA        DEX
80C1:86 18     STX $0018 ; Store #$88 in $0018

; To generate a new random number in $17-$18 the game calls $AB47
; with this code sequence in a bunch of places:
xxxx:A2 17     LDX #$17  ; Address of first byte in the LFSR
xxxx:A0 02     LDY #$02  ; Length of the LFSR in bytes
xxxx:20 47 AB  JSR $AB47

; This subroutine implements a LFSR with polynomial: x^15 + x^7 + 1
; The schematic of the 16-bit LFSR would look like this where <(( is the XOR:
;
; $17:76543210 -> $18:76543210
;     ^     v               v
;     |     |               |
;     +---<((---------------+
;
; Each call to this code shifts the entire register by 1 bit
;
AB47:B5 00     LDA $00,X      ; Load A with 1st LFSR byte in $0017
AB49:29 02     AND #$02       ; Mask all bits in A to zero except bit 1
AB4B:85 00     STA $0000      ; Store ($0017 AND #$02) in temporary $0000
AB4D:B5 01     LDA $01,X      ; Load A with 2nd LFSR byte in $0018
AB4F:29 02     AND #$02       ; Mask all bits in A to zero except bit 1
AB51:45 00     EOR $0000      ; Compute ($0018 AND #$02) XOR ($0017 AND #$02)
AB53:18        CLC            ; Clear carry flag (i.e. shift 0 into bit 7 with ROR)
AB54:F0 01     BEQ $AB57      ; If XOR was 0 (i.e. equal) then carry will remain clear
AB56:38        SEC            ; If XOR was 1 then set carry (i.e. shift 1 into bit 7 with ROR)
AB57:76 00     ROR $00,X      ; Rotate right $0017 then $0018; carry out from $0017 shifts into $0018
AB59:E8        INX            ; Increment X pointer so 2nd pass will access $0018
AB5A:88        DEY            ; Decrement the pass counter in Y
AB5B:D0 FA     BNE $AB57      ; Loop until Y equals 0 after doing 2 passes
AB5D:60        RTS            ; $0017-$0018 now have the next pseudorandom number in sequence

Load Next Block

Loading the next block into the current block.

988E:A5 49     LDA $0049
9890:C9 20     CMP #$20
9892:30 56     BMI $98EA
9894:A5 BE     LDA $00BE
9896:C9 01     CMP #$01
9898:F0 20     BEQ $98BA
989A:A5 A4     LDA $00A4
989C:C9 00     CMP #$00
989E:D0 0E     BNE $98AE
98A0:E6 A4     INC $00A4
98A2:A5 B7     LDA $00B7
98A4:85 A5     STA $00A5
98A6:20 EB 98  JSR $98EB
98A9:85 A6     STA $00A6
98AB:4C EA 98  JMP $98EA
98AE:A5 A5     LDA $00A5
98B0:C5 B7     CMP $00B7
98B2:D0 36     BNE $98EA
98B4:A5 A4     LDA $00A4
98B6:C9 1C     CMP #$1C
98B8:D0 30     BNE $98EA
98BA:A9 00     LDA #$00
98BC:85 A4     STA $00A4
98BE:85 45     STA $0045
98C0:85 41     STA $0041
98C2:A9 01     LDA #$01
98C4:85 48     STA $0048

98C6:A9 05     LDA #$05       ; 
98C8:85 40     STA $0040      ; Reset the block's X position to 5.
98CA:A6 BF     LDX $00BF      ; Read the Next Block
98CC:BD 56 99  LDA $9956,X    ; Get the block type from the Next Block Table.
98CF:85 42     STA $0042      ; Store the next block into the current block.
98D1:20 69 99  JSR $9969
98D4:A5 BE     LDA $00BE
98D6:C9 01     CMP #$01
98D8:F0 07     BEQ $98E1
98DA:A5 A6     LDA $00A6      ; Load $00A6 into A.
98DC:85 BF     STA $00BF      ; Store $00A6 into Next Block
98DE:4C E6 98  JMP $98E6      ; Set $004E to #$00.
98E1:20 EB 98  JSR $98EB      ; Get the next block and store it into A
98E4:85 BF     STA $00BF      ; Store A into the Next Block
98E6:A9 00     LDA #$00       ; Clear A
98E8:85 4E     STA $004E      ; Clear $004E
98EA:60        RTS

; If we're in the demo, load a preset list of blocks.
98EB:A5 C0     LDA $00C0      ; Load Game State
98ED:C9 05     CMP #$05       ; If Game State != Demo
98EF:D0 12     BNE $9903      ; Goto $9903
98F1:A6 D3     LDX $00D3      ; Load the Current Demo Block into X
98F3:E6 D3     INC $00D3      ; Increment the Current Demo Block
98F5:BD 00 DF  LDA $DF00,X    ; Load the next block from the Demo Block Table
98F8:4A        LSR
98F9:4A        LSR
98FA:4A        LSR
98FB:4A        LSR
98FC:29 07     AND #$07
98FE:AA        TAX
98FF:BD 4E 99  LDA $994E,X
9902:60        RTS
9903:20 07 99  JSR $9907      ; Get a random block
9906:60        RTS

; Get the next block based on a random number 00-06.
9907:E6 1A     INC $001A      ; Increment the total Block Count
9909:A5 17     LDA $0017      ; Load $0017 into memory.
990B:18        CLC            ; Clear Carry
990C:65 1A     ADC $001A      ; Add Block Count to $0017
990E:29 07     AND #$07       ; AND A with #$07
9910:C9 07     CMP #$07       ; If result != #$07 Then
9912:F0 08     BEQ $991C      ; Goto $991C
9914:AA        TAX
9915:BD 4E 99  LDA $994E,X    ; Load the Next Block from the New Block Table.
9918:C5 19     CMP $0019
991A:D0 1C     BNE $9938
991C:A2 17     LDX #$17
991E:A0 02     LDY #$02
9920:20 47 AB  JSR $AB47
9923:A5 17     LDA $0017
9925:29 07     AND #$07
9927:18        CLC
9928:65 19     ADC $0019
992A:C9 07     CMP #$07
992C:90 06     BCC $9934
992E:38        SEC
992F:E9 07     SBC #$07
9931:4C 2A 99  JMP $992A
9934:AA        TAX
9935:BD 4E 99  LDA $994E,X    ; Load the Next Block from the New Block Table.
9938:85 19     STA $0019      ; Store Next Block.
993A:60        RTS

Block Tables

When the program needs to get the next block, it generates a random number between 0-6 and uses this table to get the result.

; Block Offset Table.
993B:00 00 00 00     ; T
993F:01 01 01 01     ; J
9943:02 02           ; Z
9945:03              ; O
9946:04 04           ; S
9948:05 05 05 05     ; L
994C:06 06           ; I

; New Block Table - Offset by a random number ($00-$06)
994E:02              ; T
994F:07              ; J
9950:08              ; Z
9951:0A              ; O
9952:0B              ; S
9953:0E              ; L
9954:12              ; I

; Next Block Table - Offset by the Next Block ($00BF)
9956:02 02 02 02     ; T
995A:07 07 07 07     ; J
995E:08 08           ; Z
9960:0A              ; O
9961:0B 0B           ; S
9963:0E 0E 0E 0E     ; L
9967:12 12           ; I

Text

Tetris uses three main character sets. The title screens has a full set with some symbols, the messages have another set with different symbols, and the screen during game play has its own limited set.

Title / Menus

00=0
01=1
02=2
03=3
04=4
05=5
06=6
07=7
08=8
09=9
0A=A
0B=B
0C=C
0D=D
0E=E
0F=F
10=G
11=H
12=I
13=J
14=K
15=L
16=M
17=N
18=O
19=P
1A=Q
1B=R
1C=S
1D=T
1E=U
1F=V
20=W
21=X
22=Y
23=Z
24=-
25=,
26=°
27=»
4F=/
52=!
53=<
54=>
5E=(
5F=)
6E="
6F=.
F5=©
FF= 

Game

00=0
01=1
02=2
03=3
04=4
05=5
06=6
07=7
08=8
09=9
0A=S
0B=C
0C=O
0D=R
0E=E
0F=L
10=V
11=H
12=I
13=G
14=T
15=A
FF= 

Messages

00=0
01=1
02=2
03=3
04=4
05=5
06=6
07=7
08=8
09=9
0A=A
0B=B
0C=C
0D=D
0E=E
0F=F
10=G
11=H
12=I
13=J
14=K
15=L
16=M
17=N
18=O
19=P
1A=Q
1B=R
1C=S
1D=T
1E=U
1F=V
20=W
21=X
22=Y
23=Z
24=-
25=,
26=°
27=»
28=!
29=h
FF= 

High Scores

00=-
01=A
02=B
03=C
04=D
05=E
06=F
07=G
08=H
09=I
0A=J
0B=K
0C=L
0D=M
0E=N
0F=O
10=P
11=Q
12=R
13=S
14=T
15=U
16=V
17=W
18=X
19=Y
1A=Z
1B=0
1C=1
1D=2
1E=3
1F=4
20=5
21=6
22=7
23=8
24=9
25=,
26=/
27=(
28=)
29="
2A=.
2B=


Links