TETRIS.ASM by FrankTheCodor 
Author Message
 TETRIS.ASM by FrankTheCodor

;Coded by Francisco Charrua

;I will add comments if people ask me to :)

;To build with Tasm:    tasm tetris.asm
;                       tlink /t tetris.obj

;To build with Masm:    masm tetris.asm
;                       link /T tetris.obj

tetris                  segment 'code'
                        assume  cs:tetris,ds:tetris
                        org     100h
                        .486
Number_of_Columns       equ     20
Number_of_Rows          equ     40
Grid_Size               equ     Number_of_Columns*Number_of_Rows
Initial_Position        equ    
Number_of_Columns*(Number_of_Rows-2)+Number_of_Columns/2

the_game:               mov     ax,13h
                        int     10h

                        mov     ax,cs
                        mov     ds,ax
                        mov     es,ax

                        call    Clear_All_Rows
                        call    Initialize_Piece
                        call    Place_Piece
                        call    Show_Game

Keep_On_Playing_Tetris: call    Read_Key
                        mov     al,[Previous_Keypress]
                        cmp     al,[Keypress]
                        je      Ignore_Keypress

                        call    Remove_Piece
                        cmp     [Keypress],4eh
                        jne     Dont_Increase_Delay
                        add     dword ptr [Variable_Delay],10000
                        add     dword ptr [Delay_Value],10000
Dont_Increase_Delay:    cmp     [Keypress],4ah
                        jne     Dont_Decrease_Delay
                        cmp     dword ptr [Variable_Delay],10000
                        jbe     Dont_Decrease_Delay
                        sub     dword ptr [Variable_Delay],10000
                        sub     dword ptr [Delay_Value],10000
Dont_Decrease_Delay:    cmp     [Keypress],50h
                        jne     Down_Key_Wasnt_Pressed
                        mov     dword ptr [Delay],10
                        mov     dword ptr [Delay_Value],10
Down_Key_Wasnt_Pressed: cmp     [Keypress],4bh
                        jne     Left_Key_Wasnt_Pressed
                        call    Move_Piece_Left
Left_Key_Wasnt_Pressed: cmp     [Keypress],4dh
                        jne     Right_Key_Wasnt_Pressed
                        call    Move_Piece_Right
Right_Key_Wasnt_Pressed:cmp     [Keypress],4ch
                        jne     No_Keys_Were_Pressed
                        call    Rotate_Piece
No_Keys_Were_Pressed:   call    Place_Piece
                        call    Show_Game

Ignore_Keypress:        dec     dword ptr [Delay]
                        jnz     Do_Not_Move_Down
                        call    Remove_Piece
                        call    Move_Piece_Down
                        jc      Reached_The_Bottom
                        call    Place_Piece
                        call    show_Game
                        jmp     Didnt_Reach_The_Bottom
Reached_The_Bottom:     mov     eax,[Variable_Delay]
                        mov     [Delay_Value],eax
                        call    Place_Piece
                        call    Last_Row
                        call    Eliminate_Rows
                        mov     ecx,[delay_Value]
To_Look_At_Empty_Rows:  loopd   To_Look_At_Empty_Rows
                        call    Show_Game
                        call    Collapse_Rows
                        mov     ecx,[delay_Value]
Wait_For_The_Next_Piece:loopd   Wait_For_The_Next_Piece
                        call    Show_Game
                        call    Initialize_Piece
                        call    Good_Move
                        jc      Start_A_New_Game
                        call    Place_Piece
                        call    Show_Game
                        jmp     Continue_Playing
Start_A_New_Game:       call    Clear_All_Rows
                        call    Place_Piece
                        call    Show_Game
Continue_Playing:
Didnt_Reach_The_Bottom: mov     eax,[Delay_Value]
                        mov     [Delay],eax

Do_Not_Move_Down:       mov     al,[Keypress]
                        mov     [Previous_Keypress],al

                        cmp     [Keypress],1
                        jne     Keep_On_Playing_Tetris

                        mov     ax,3
                        int     10h
                        jmp     the_game-100h

Blocks:
db  20, 00,-20,-40, -01, 00, 01, 02,  20, 00,-20,-40, -01, 00, 01, 02
db  20, 00,-01,-20, -01, 00, 01,-20,  20, 00, 01,-20, -01, 00, 01, 20
db  21, 01,-19,-20,  21, 20, 19, 01,  20, 19,-01,-21, -01,-19,-20,-21
db -21,-01, 19,-20,  01,-19,-20,-21,  20,-19, 01, 21,  21, 20, 19,-01
db  21, 01, 00,-20,  20, 19, 00, 01,  21, 01, 00,-20,  20, 19, 00, 01
db  19,-01, 00,-20, -20,-21, 00, 01,  19,-01, 00,-20, -20,-21, 00, 01
db  21, 20, 01, 00,  21, 20, 01, 00,  21, 20, 01, 00,  21, 20, 01, 00

Grid                    db      Grid_Size dup(0)

Current_Block           dw      0
Current_Position        dw      0
Upper_Limit             dw      0
score                   dd      0
cleared_rows            dd      0

Keypress                db      0
Previous_Keypress       db      0
Delay                   dd      600000
Delay_Value             dd      600000
Variable_Delay          dd      600000

Clear_All_Rows:         mov     bx,offset Grid
                        mov     cx,Grid_Size
Until_Rows_Are_Clear:   mov     byte ptr [bx],0
                        inc     bx
                        loop    Until_Rows_Are_Clear
                        xor     eax,eax
                        mov     [score],eax
                        mov     [cleared_rows],eax
                        retn

Eliminate_Rows:         mov     bx,offset Grid
                        xor     di,di
Is_The_Next_Row_Full:   call    Full_Row
                        jc      Row_Is_Not_Full
                        call    Clear_Row
                        inc     [cleared_rows]
Row_Is_Not_Full:        add     di,Number_of_Columns
                        cmp     di,Grid_Size
                        jb      Is_The_Next_Row_Full
                        retn

Collapse_Rows:          mov     dword ptr [increment],1
                        mov     dword ptr [score_increment],0
                        mov     bx,offset Grid
                        xor     di,di
Is_The_Row_Empty:       call    Empty_Row
                        jc      Row_Is_Not_Empty
                        call    Cascade_Rows
                        mov     eax,[increment]
                        add     [score_increment],eax
                        shl     dword ptr [increment],1
                        jmp     Row_Was_Empty
Row_Is_Not_Empty:       add     di,Number_of_Columns
                        mov     eax,[score_increment]
                        add     [score],eax
                        mov     dword ptr [score_increment],0
                        mov     dword ptr [increment],1
Row_Was_Empty:          cmp     di,[Upper_Limit]
                        jbe     Is_The_Row_Empty
                        retn
increment               dd      0
score_increment         dd      1

Cascade_Rows:           push    di
Copy_Another_Row:       call    Copy_Row
                        add     di,Number_of_Columns
                        cmp     di,[Upper_Limit]
                        jbe     Copy_Another_Row
                        sub     [Upper_Limit],Number_of_Columns
                        pop     di
                        retn

Copy_Row:               push    di
                        mov     cx,Number_of_Columns
Copy_Cell:              mov     al,[bx+di+Number_of_Columns]
                        mov     [bx+di],al
                        inc     di
                        loop    Copy_Cell
                        pop     di
                        retn

Clear_Row:              push    di
                        xor     al,al
                        mov     cx,Number_of_Columns
Clear_Cell:             mov     [bx+di],al
                        inc     di
                        loop    Clear_Cell
                        pop     di
                        retn

Last_Row:               mov     bx,offset Grid
                        mov     di,Grid_Size-1
                        mov     cx,Grid_Size
Upto_The_Last_Row:      cmp     byte ptr [bx+di],0
                        jne     Found_The_Last_Row
                        dec     di
                        loop    Upto_The_Last_Row
Found_The_Last_Row:     mov     ax,di
                        xor     dx,dx
                        mov     cx,Number_of_Columns
                        div     cx
                        sub     di,dx
                        mov     [Upper_Limit],di
                        retn

Full_Row:               push    di
                        mov     cx,Number_of_Columns
Looking_For_A_Zero:     cmp     byte ptr [bx+di],0
                        jne     Not_A_Zero
                        stc
                        pop     di
                        retn
Not_A_Zero:             inc     di
                        loop    Looking_For_A_Zero
                        clc
                        pop     di
                        retn

Empty_Row:              push    di
                        mov     cx,Number_of_Columns
Looking_For_Zeros:      cmp     byte ptr [bx+di],0
                        je      A_Zero
                        stc
                        pop     di
                        retn
A_Zero:                 inc     di
                        loop    Looking_For_Zeros
                        clc
                        pop     di
                        retn

Initialize_Piece:       in      al,40h
                        xor     ah,ah
                        mov     cl,7
                        div     cl
                        shl     ah,4
                        mov     byte ptr [Current_Block],ah
                        mov     [Current_Position],Initial_Position
                        retn

Place_Piece:            mov     al,byte ptr [Current_Block]
                        shr     al,4
                        inc     al
                        mov     bx,offset Blocks
                        mov     di,[Current_Block]
                        mov     cx,4
For_Four_Blocks:        movsx   si,byte ptr [bx+di]
                        add     si,[Current_Position]
                        add     si,offset Grid
                        mov     [si],al
                        inc     di
                        loop    For_Four_Blocks
                        retn

Remove_Piece:           mov     bx,offset Blocks
                        mov     di,[Current_Block]
                        mov     cx,4
For_4_Blocks:           movsx   si,byte ptr [bx+di]
                        add     si,[Current_Position]
                        add     si,offset Grid
                        mov     byte ptr [si],0
                        inc     di
                        loop    For_4_Blocks
                        retn

Rotate_Piece:           mov     al,byte ptr [Current_Block]
                        mov     [Block_Before_Spin],al
                        push    ax
                        mov     cl,16
                        div     cl
                        cmp     ah,12
                        pop     ax
                        jne     Rotate
                        sub     byte ptr [Current_Block],12
                        jmp     Am_I_Allowed_Rotate
Rotate:                 add     byte ptr [Current_Block],4
Am_I_Allowed_Rotate:    call    Bottom_Bound
                        jc      What_About_The_Walls
                        mov     al,[Block_Before_Spin]
                        mov     byte ptr [Current_Block],al
                        retn
What_About_The_Walls:   call    Left_Bound
                        jc      Other_Blocks
                        call    Right_Bound
                        jc      Other_Blocks
                        mov     al,[Block_Before_Spin]
                        mov     byte ptr [Current_Block],al
                        retn
Other_Blocks:           call    Good_Move
                        jnc     Free_To_Spin
                        mov     al,[Block_Before_Spin]
                        mov     byte ptr [Current_Block],al
Free_To_Spin:           retn
Block_Before_Spin       db      0

Move_Piece_Right:       call    Right_Bound
                        jc      No_Right_Boundary
                        retn
No_Right_Boundary:      mov     ax,[Current_Position]
                        mov     [Before_Moving_Right],ax
                        dec     [Current_Position]
                        call    Good_Move
                        jnc     Right_Side_Free
                        mov     ax,[Before_Moving_Right]
                        mov     [Current_Position],ax
Right_Side_Free:        retn
Before_Moving_Right     dw      0

Move_Piece_Left:        call    Left_Bound
                        jc      No_Left_Boundary
                        retn
No_Left_Boundary:       mov     ax,[Current_Position]
                        mov     [Before_Moving_Left],ax
                        inc     [Current_Position]
                        call    Good_Move
                        jnc     Left_Side_Free
                        mov     ax,[Before_Moving_Left]
                        mov     [Current_Position],ax
Left_Side_Free:         retn
Before_Moving_Left      dw      0

Move_Piece_Down:        call    Bottom_Bound
                        jc      No_Bottom_Boundary
                        stc
                        retn
No_Bottom_Boundary:     mov     ax,[Current_Position]
                        mov     [Before_Moving_Down],ax
                        sub     [Current_Position],Number_of_Columns
                        call    Good_Move
                        jnc     Bottom_Side_Free
                        mov     ax,[Before_Moving_Down]
                        mov     [Current_Position],ax
Bottom_Side_Free:       retn
Before_Moving_Down      dw      0

Good_Move:              mov     bx,offset Blocks
                        mov     di,[Current_Block]
                        mov     cx,4
Is_It_Empty:            movsx   si,byte ptr [bx+di]
                        add     si,[Current_Position]
                        add     si,offset Grid
                        cmp     byte ptr [si],0
                        je      Its_Empty
                        stc
                        retn
Its_Empty:              inc     di
                        loop    Is_It_Empty
                        clc
                        retn

Left_Bound:             mov     bx,offset Blocks
                        mov     di,[Current_Block]
                        mov     cx,4
Left_Boundary_Search:   push    cx
                        movsx   ax,byte ptr [bx+di]
                        add     ax,[Current_Position]
                        mov     cx,Number_of_Columns
                        xor     dx,dx
                        div     cx
                        cmp     dx,Number_of_Columns-1
                        pop     cx
                        jne     Not_Left_Bound
                        clc
                        retn
Not_Left_Bound:         inc     di
                        loop    Left_Boundary_Search
                        stc
                        retn

Right_Bound:            mov     bx,offset Blocks
                        mov     di,[Current_Block]
                        mov     cx,4
Right_Boundary_Search:  push    cx
                        movsx   ax,byte ptr [bx+di]
                        add     ax,[Current_Position]
                        mov     cx,Number_of_Columns
                        xor     dx,dx
                        div     cx
                        cmp     dx,0
                        pop     cx
                        jne     Not_Right_Bound
                        clc
                        retn
Not_Right_Bound:        inc     di
                        loop    Right_Boundary_Search
                        stc
                        retn

Bottom_Bound:           mov     bx,offset Blocks
                        mov     di,[Current_Block]
                        mov     cx,4
Bottom_Boundary_Search: movsx   ax,byte ptr [bx+di]
                        add     ax,[Current_Position]
                        cmp     ax,Number_of_Columns
                        jae     Not_Bottom_Bound
                        clc
                        retn
Not_Bottom_Bound:       inc     di
                        loop    Bottom_Boundary_Search
                        stc
                        retn

Show_Game:              push    6000h
                        pop     es
                        xor     di,di
                        mov     cx,64000/2
                        mov     ax,1616h
                        rep     stosw

                        xor     si,si
                        mov     bx,offset Grid+Grid_Size-1

                        mov     cx,Number_of_Rows
Display_All_Rows:       push    cx
                        mov     cx,Number_of_Columns
Display_One_Row:        push    cx

                        mov     di,si
                        add     di,100
                        mov     al,byte ptr cs:[bx]
                        mov     cx,5
block:                  push    cx
                        mov     cx,5
                        rep     stosb
                        add     di,320-5
                        pop     cx
                        loop    block

                        pop     cx
                        dec     bx
                        add     si,5
                        loop    Display_One_Row
                        pop     cx
                        add     si,5*320-5*20
                        loop    Display_All_Rows

                        push    es
                        pop     ds
                        push    0a000h
                        pop     es
                        mov     cx,64000/2
                        xor     di,di
                        xor     si,si
                        rep     movsw
                        push    cs
                        pop     ds
                        retn

Read_Key:               push    0
                        pop     ds
poll:                   mov     ax,word ptr ds:[41ah]
                        mov     bx,word ptr ds:[41ch]
                        push    ax
                        push    bx
                        cmp     bx,word ptr ds:[41ah]
                        jne     no_tail
                        sub     bx,2
                        cmp     bl,1ch
                        jne     no_tail
                        mov     bl,3ch
no_tail:                mov     bh,4
                        sub     bl,2
                        cmp     bl,1ch
                        jne     no_wrap
                        mov     bl,3ch
no_wrap:                mov     al,[bx+1]
                        mov     cs:[keypress],al
                        mov     byte ptr [bx+1],0
                        pop     bx
                        pop     ax
                        cmp     al,1eh
                        jne     not_at_41e
                        cmp     bl,3ch
                        jne     the_end
                        mov     word ptr ds:[41ch],1eh
                        jmp     the_end
not_at_41e:             push    bx
                        add     bx,2
                        cmp     ax,bx
                        pop     bx
                        jne     the_end
                        add     bx,2
                        mov     word ptr ds:[41ch],bx
the_end:                push    cs
                        pop     ds
                        retn

tetris                  ends
                        end     the_game



Sat, 22 May 1999 03:00:00 GMT  
 
 [ 1 post ] 

 Relevant Pages 

1. TETRIS PROGRAMMED IN SMALLTALK FOR VISUALWORKS 2.5

2. CwTris - a tetris game written CW

3. tetris

4. Tetris for LabVIEW

5. Tetris in Clipper anyone?

6. Compiling Tetris

7. Games for SystemV4: Tetris & Minesweeper

8. Tetris (next release) and some questions

9. Tetris for System3 2.0

10. Tetris is broken?

11. tetris game

12. The 256 bytes Tetris compo

 

 
Powered by phpBB® Forum Software