Go Back Programming  Go to Contents

TET Source/Documentation


;-----------------------------------------------------------------------------
;
;  []                       TET - 256 byte Tetris                  [][][]
;  [][]                                                            []
;  []                                by                                  []
;                []                                         []           []
;        [][][]  [][]        James David Chapman            [][]  [][]   []
;  [][][][]  []    []                                       []  [][]     []
;-----------------------------------------------------------------------------
;
;  Here is a 256 byte version of of the all time classic game Tetris...
;
;  To play, use the left and right SHIFT keys to move the current block, and
; the ALT key to rotate it.  Press CONTROL to exit.
;
;  I have not had the amount of time that I would have liked to write this
;program, so am sure that there is some optimization still left to be done. If
;you find a saving somewhere along the line, do let me know.
;
;  Another idea for a 256 compo? -  256 scramble.  Could be fun.
;
;                                                 James David Chapman 1999.
;-----------------------------------------------------------------------------
;Features:
;       Cool looking blocks             Almost as good as graphics mode ones.
;       Random shape                    Taken from the timer.
;       Random colours                  Also taken from timer.
;       Rotatable shape                 I hated writing this bit, as expected.
;       Block stop check                Stops blocks when they hit another one
;       Solidity                        Prevent sideways crashing into blocks.
;       Dual loop timing                Allows for multiple input per advance.
;       End of game effect              More of a useful side effect really!
;       Full lines removed              A quickly cobbled together routine.
;       Frame                           Sets a maximum 10 block width for game.
;       End program key                 Better than using Control-C etc.
;No space for:
;       Scoring                         +2 for a line, +4 if the bottom line..
;       Beeps                           a simple beep on line removal...
;       Speedup                         should increase in speed over time...
;       Graphics mode                   I had a lovely graphics version, and
;       Nice enlarge effect             a cool block effect which was too big.
;-----------------------------------------------------------------------------
        ;assembler startup              ;assembled with:
        .MODEL TINY                     ;TASM TET.ASM /m2 /uM520 /t >errors
        MASM51                          ;TLINK TET.OBJ /3 /x /t
        QUIRKS                          
        .386                            ;uses pusha/popa (286+)   
        .CODE                           ;uses fs segment register (386+)  
        .STARTUP                           
;-----------------------------------------------------------------------------
        ;setup segs and vars            
        MOV AX,1                        ;set colour screen mode 40 cols
        INT 10H                         ;call BIOS
        PUSH 040H                       ;set segment for keyboard flags
        POP FS                                                                                                             
        PUSH 0B800H                     ;colour text segment
        POP ES                          ;set ES to colour text segment 
        PUSH DS                         ;store data segment
        PUSH ES                         
        POP DS                          ;set DS to colour text segment
;-----------------------------------------------------------------------------                                         
        ;get a new random coloured tile
        NEWBLOCK:
        XOR AX,AX                       ;clear AX
        IN AL,40H                       ;get a random number from timer
        MOV BP,AX                       ;use top bits to select block shape
        SHR BP,5
        JZ NEWBLOCK                     ;only 7 shapes so redo if 0
        MOV BP,[BP+OFFSET SHAPETABLE-1] ;BP assumes SS, which saves segment
        SHL BP,4                        ; override here.
        AND BP,0FF0H                    ;convert data byte into word
        AND AL,0111B                    ;use bottom bits for colour
        OR AL,1000B                     ;make colours bright
        MOV AH,AL                       ;store colour
        MOV DI,-60                      ;set inital print position
;-----------------------------------------------------------------------------
        ;increase current block's row position
        @@:
        ADD DI,80                       ;advance block down screen

        ;do mainloop
        MOV BX,4                        ;do main game loop 4 times per
MAINLOOP:                               ; block advance, to allow for more
        DEC BX                          ; than one rotation/move per advance
        JZ @B                           
;-----------------------------------------------------------------------------        
        ;print game board frame, and clear any full lines
        PUSHA                           ;store all general purpose registers
        MOV SI,80*25+2                  ;set SI/DI to bottom left of board
        MOV DI,SI
        BOARDLOOP:
        XOR DX,DX                       ;zero block counter
        MOV CL,10                       ;each line is 10 blocks wide
        CHECKLINE:
        LODSW
        CMP AH,7                        ;check attribute of character to copy
        JBE @F
        INC DX                          ;count the number of consecutive blox
        @@:
        STOSW                           ;print the character/attribute
        LOOP CHECKLINE
        LODSW                           ;smaller form of add si,2
        MOV AX,09B1H                    ;print right hand column
        STOSW
        CMP DX,10                       ;check to see if there was a row of 10
        JB @F      
        ADD DI,80                       ;if there was, force di to skip a row
        @@:        
        SUB DI,80+24                    ;update di for next row
        SUB SI,80+24                    ;update si for next row
        STOSW                           ;print left hand column
        LODSW                           ;smaller form of add si,2
        JNC BOARDLOOP                   ;if sub causes si to cross 0 then end
        POPA                            ;restore general purpose registers
;-----------------------------------------------------------------------------
        ;get keyboard input
        XOR CX,CX                       ;clear cx -  allows cl usage*3 later
        MOV SI,DI                       ;store old position - possible restore
        PUSH BP                         ;store old rotation - possible restore
        MOV CL,FS:[17H]                 ;get keyboard flags
        RCR CL,1                        ;split on set bits
        JNC @F                          ;right shift-move block right          
        INC DI                          ;add 2 to position variable
        INC DI
        @@:
        RCR CL,1
        JNC @F                          ;left shift-move block left  
        DEC DI                          ;sub 2 from position variable
        DEC DI
        @@:
        RCR CL,1   
        JNC @F                          ;control-escape
        POP BP                          ;reset stack
        POP DS                          ;restore data segment
        RET                             ;end program
        @@:       
        RCR CL,1
        JNC @F                          ;alt-rotate block
;-----------------------------------------------------------------------------
;90 degree rotate function:
;
;ABCD EFGH IJKL MNOP     ABCD    =>     DHLP CGKO BFJN AEIM   DHLP
;                        EFGH                                 CGKO
;    -->  Displayed as:  IJKL              ->  Displayed as:  BFJN 
;                        MNOP                                 AEIM
;
;-----------------------------------------------------------------------------
        MOV CL,16                       ;create 16 bits in DX output
        MOV DX,0EEEEH                   ;set bits where no ROR is to be done
        RLOOP:                 
        ROL BP,4                        ;rotate bp, carry=last bit rotated
        RCL DX,1                        ;carry into dx, high dx into carry
        JC SKIPROR                      ;skip ROR for preset bits in dx
        ROR BP,1                        ;adjust bp back 1 every 4 bits
        SKIPROR:
        LOOP RLOOP
        MOV BP,DX                       ;store rotated value back into bp
        @@:
;-----------------------------------------------------------------------------
        ;check plot
        XOR DX,DX                       ;zero dl to supress ploting
        CALL PLOTBLOCK                  ;check if plot would cover a block
        JZ @F
        POP BP                          ;use old value for rotate
        MOV DI,SI                       ;use old value for position
        PUSH DX                         ;set stack so reset is ok
        @@:                             
        POP DX                          ;reset stack

        ;plot the current block
        MOV DX,BX                       ;set flag for normal plot block
        CALL PLOTBLOCK                  ;bx just used as a non zero number

        ;should block stop?
        JNZ NEWBLOCK                    ;there is a block below so do newblock
;-----------------------------------------------------------------------------
        ;wait for vertical retrace
        PUSH AX
        MOV CL,4                        ;do vertwait 6 times per gameloop
        VERTWAIT:                       ;this slows down the keyboard entry
        MOV DX,3DAH                     ;VGA status register
        @@:
        IN AL,DX
        TEST AL,8
        JZ @B                           ;wait for vertical retrace to start
        @@:          
        IN AL,DX      
        TEST AL,8      
        JNZ @B                          ;wait for vertical retrace to end
        LOOP VERTWAIT                   ;loop 6 times
;-----------------------------------------------------------------------------
        ;erase block
        XOR AX,AX                       ;clear colour
        CALL PLOTBLOCK                  ;print block again, this time with
        POP AX                          ;zero (black) attribute.
        JMP MAINLOOP                    ;restart game loop
;-----------------------------------------------------------------------------
PLOTBLOCK:
        ;write a 4*4 block to the screen
        PUSHA                           ;store registers
        MOV CX,16                       ;4*4=16
        MOV AL,8                        ;ascii 8 is the block we use, it
        PLOTLOOP:                       ;is also used for test below.
        TEST CX,11B                     ;every 4 prints...
        JNZ @F
        ADD DI,72                       ;change print position to next line
        @@:
        ROL BP,1                        ;test bp bits without disturbing bp
        JC @F                           ;if no carry, then no block is to
        SKIP:                           ;be printed here so skip over it.
        INC DI
        INC DI
        JMP SHORT NEXTPLOT
        @@:

        ;check overwrite
        OR DL,DL                        ;if in overwrite checking mode,
        JNZ @F                          ;do not print, report back on
        OR DH,[DI+1]                    ;what you will be printing over,
        JMP SHORT SKIP                  ;and skip printing.
        @@:

        ;check below block              ;if there is a block below this one
        OR DH,[DI+81]                   ;then newblock will need to be run
        CMP DI,80*24                    ;check for end of screen
        JB NOSTOP
        OR DH,AL                        ;force newblock if end of screen
        NOSTOP:

        STOSW                           ;print part of the block here
        NEXTPLOT:
        LOOP PLOTLOOP                   ;do 16 of these
        TEST DH,AL                      ;pass result of checks as zero flag
        POPA                            ;for gameloop to interpret
        RET
;-----------------------------------------------------------------------------
        ;data 
        ;OOO.  OO.   .OO  .O..  OOOO  .OO.  OOO.
        ;..O.  .OO.  OO.  OOO.  ....  .OO.  O...

        SHAPETABLE LABEL BYTE           ;the 7 tetris shapes used in the game
        DB 11100010B                    ;setbit=print a block at this position
        DB 11000110B                    ;loaded as words, cleared back to 
        DB 01101100B                    ;bytes and then shifted by a 4 bits to 
        DB 01001110B                    ;create blank top and bottom rows.
        DB 11110000B                    ;..as it turns out not much of a 
        DB 01100110B                    ;saving.
        DB 11101000B
;-----------------------------------------------------------------------------
        END                             ;end of tetris game, phew.
;-----------------------------------------------------------------------------
        ;(c) JDC 1999.
        ;jchap@globalnet.co.uk
        ;http://www.users.globalnet.co.uk/~jchap/
;-----------------------------------------------------------------------------

  A page from James David Chapman's website.
  Located at: http://www.users.globalnet.co.uk/~jchap/
  
Site mirrored here at: http://www.j.chap.btinternet.co.uk
Go back to the last page you viewed. Go to previous page on this website. Go on to the next page in this sub site. Go to the main contents list. Go to the help page. Please send me *your* home page address!. Go to the web form to simply and quickly send me your comments.
  This page last updated:
  
My rating for the page: How happy I am with this page...