page 91 %bin 24 %text 53 locals __ model tiny BACKGROUND equ 08h BORDER equ 05B0h POINT equ 0B0h+BACKGROUND shl 8 WELL_WIDTH equ 10 WELL_HEIGHT equ 22 WELL_POS equ (160-WELL_WIDTH*4-16)/2 START_POS equ (WELL_POS+(WELL_WIDTH-4)*2+4-160)+1 NEXT_POS equ (160*20+20)+1 BLANK equ 0420h GAMEOVER_ATTR equ 0Ch NUM_ATTR equ 0Eh COPYRIGHT_ATTR equ 0Eh NAME_LEN equ 16 HSCORETBL_SIZE equ 30 NAME_ATTR equ 0Bh COLORS_POS equ 160*9+55*2 COLOR_LEN equ 20 SCORE_FOR_NEXT equ 5 HiScore struc HScoreL dw ? HScoreH dw ? HLevel db ? HSLevel db ? HColors db ? HName db NAME_LEN dup(?) HiScore ends ScoreForFigure macro mov al,3 mul Level add al,ColorsNum add al,26 sub al,NextDec call AddScoreW endm ScoreForMoveDown macro mov al,-1 call AddScoreB endm .code org 100h start: mov di,offset BssStart mov cx,BssEnd-BssStart xor al,al rep stosb mov ax,3D00h mov dx,offset ResFile int 21h mov bh,3Fh call RdWr mov ax,3 int 10h mov OldTimer+2,cs call SwapVec mov al,es:[0417h] and al,20h xor al,20h mov OldNumLock,al xor es:[0417h],al sti mov ax,0B800h mov es,ax call Cursor mov dh,COPYRIGHT_ATTR call MultiPrint dw 160*7+40 db 'C o l o r e d',2,'S m a l l',2,'T e t r i s',0 dw 160*9+32 db 'Copyright (C) Dec 1993 by Alexander V. Lukyanov',0 dw 160*11+48 db 'Some ideas by Dmitry V. Lukyanov',0 dw 160*13+50 db 'Game by Alexander V. Lukyanov',0 dw -1 __game: call ReadKey call InitGame call Play call DisplayTable jmp __game Terminate: mov ax,3 int 10h call SwapVec mov al,OldNumLock xor es:[0417h],al mov dx,offset ResFile xor cx,cx mov ah,3Ch int 21h mov bh,40h call RdWr int 20h WaitKeyAt proc mov bh,0 mov ah,2 int 10h ReadKey proc xor ah,ah int 16h cmp al,27 je Terminate ret ReadKey endp WaitKeyAt endp RdWr proc jc __done xchg ax,bx mov dx,offset HiScoresTbl mov cx,HSCORETBL_SIZE*type HiScore int 21h mov ah,3Eh int 21h __done: ret RdWr endp SwapVec proc xor bx,bx mov es,bx cli mov ax,OldTimer xchg es:[bx+1Ch*4],ax mov OldTimer,ax mov ax,OldTimer+2 xchg es:[bx+1Ch*4+2],ax mov OldTimer+2,ax ret SwapVec endp .code FigTbl label byte db 164,4,156,4 ; ; db 164,4,156,4 ; лллл ; db 164,4,156,4 ; лллл ; db 164,4,156,4 ; ; db 168,4,152,4 ; ; db 4,160,4,160 ; лллл; db 168,4,152,4 ; лллл ; db 4,160,4,160 ; ; db 160,4,160,4 ; ; db 8,156,4,156 ;лллл ; db 160,4,160,4 ; лллл ; db 8,156,4,156 ; ; db 160,4,4,4 ; ; db 8,160,160,160 ;лллллллл; db 160,4,4,4 ; ; db 8,160,160,160 ; ; db 160,4,4,156 ; ; db 4,160,4,156 ;лллллл ; db 4,156,4,4 ; лл ; db 4,156,4,160 ; ; db 160,4,4,160 ; ; db 4,4,156,160 ;лллллл ; db 160,160,4,4 ; лл ; db 8,160,156,4 ; ; db 160,4,4,152 ; ; db 4,160,160,4 ;лллллл ; db 168,152,4,4 ;лл ; db 4,4,160,160 ; ; ResFile db 'cst.res',0 .data? BssStart label word CurrFigState label word CurrFigOrient db ? CurrFigNo db ? CurrFigPos dw ? NextFigNo db ? Counter db ? Random dw ? CurrColor db ? NextColor db ? Next db ? NextDec db ? Full dw ? NewHiScore label HiScore ScoreL dw ? ScoreH dw ? Level db ? SLevel db ? ColorsNum db ? NewName db NAME_LEN dup(?) HiScoresTbl label HiScore db HSCORETBL_SIZE*type HiScore dup(?) OldNumLock db ? TblPos dw ? Saved db 4 dup(?) BssEnd label word .code GetFigAddr proc mov cl,2 shl ax,cl shl ah,cl add al,ah cbw add ax,offset FigTbl mov si,ax mov cx,4 mov ah,0 ret GetFigAddr endp ClearNext proc DrawNext proc mov bl,NextColor xor bl,BLANK shr 8 mov ah,NextFigNo mov al,0 mov di,NEXT_POS cmp Next,0 je __done call GetFigAddr __drawing: lodsb add di,ax xor es:[di],bl xor es:[di+2],bl loop __drawing __done: ret DrawNext endp ClearNext endp ClearCurr proc mov ax,CurrFigState mov di,CurrFigPos call GetFigAddr mov bx,offset Saved __restoring: lodsb add di,ax js __skip mov al,[bx] mov es:[di],al mov es:[di+2],al __skip: inc bx loop __restoring ret ClearCurr endp CheckFig proc mov bl,CurrColor call GetFigAddr __checking: lodsb add di,ax js __loop cmp byte ptr es:[di],bl jae __bad cmp byte ptr es:[di],BORDER shr 8 je __bad cmp byte ptr es:[di+2],BORDER shr 8 je __bad __loop: loop __checking stc __bad: cmc ret CheckFig endp PrintStr proc __next: mov cx,1 lodsb or al,al jz __done cmp al,' ' jae __letter add cl,al mov al,' ' __letter: rep stosw jmp __next ClearScr proc xor di,di mov cx,1000h mov ax,BLANK rep stosw ClearScr endp __done: ret PrintStr endp MultiPrint proc pop si __cycle: lodsw or ax,ax js __done mov di,ax mov ah,dh call PrintStr jmp __cycle Print proc pop si call PrintStr Print endp __done: jmp si MultiPrint endp ColorToAttr proc mov al,dl mov bl,7 mul bl div ColorsNum mov ah,al mov cl,4 shl ah,cl or ah,al ret ColorToAttr endp InitGame proc call ClearScr mov di,12*160+60 call Print db 'Start level:',0 call Cursor __readlevel: mov dx,0C2Bh call WaitKeyAt sub al,'0' jb __readlevel cmp al,9 ja __readlevel mov ah,al mov word ptr Level,ax call ClearScr mov di,12*160+58 call Print db 'Colors number:',0 __readcolors: mov dx,0C2Ch call WaitKeyAt sub al,'1' jb __readcolors inc ax cmp al,7 ja __readcolors mov ColorsNum,al call Cursor call ClearScr xchg ax,dx call MultiPrint dw 0 db 'Your level:',0 dw 160 db 'Full lines:',0 dw 160*3 db 'SCORE:',0 dw 160*19 db 'Next:',0 dw 160*8 db '7',4,'- move left',0 dw 160*9 db '8',4,'- rotate',0 dw 160*10 db '9',4,'- move right',0 dw 160*11 db 'SPACE - drop',0 dw 160*12 db '0',4,'- pause',0 dw 160*13 db '1',4,'- next on/off',0 dw 160*14 db 'ESC',2,'- exit',0 dw -1 mov di,WELL_POS mov cx,WELL_HEIGHT mov ax,BORDER __drawell: stosw stosw push ax mov dx,WELL_WIDTH mov ax,POINT test di,20h jz __line1 __line: xor al,(POINT and 255) xor ' ' __line1: stosw stosw dec dx jnz __line pop ax stosw stosw add di,160-WELL_WIDTH*4-8 loop __drawell mov cx,WELL_WIDTH*2+4 rep stosw mov di,COLORS_POS+6*160 mov dl,ColorsNum ;assert(dh==0) dec dx jz __done inc dx __colors: call ColorToAttr mov cx,COLOR_LEN rep stosw sub di,160+2*COLOR_LEN dec dx jnz __colors __done: xor ax,ax mov di,offset Next mov cx,8 push es cs pop es rep stosb pop es call Delay9 RandomFig proc call Rand mov bl,7 div bx mov NextFigNo,dl call Rand mov bl,ColorsNum div bx inc dx call ColorToAttr mov NextColor,ah ret RandomFig endp InitGame endp Rand proc mov ah,0 int 1ah in al,40h mov ah,al in al,40h add ax,dx xor dx,dx xor ax,Random ror ax,1 mov Random,ax xor bx,bx ret Rand endp CheckFull proc mov di,WELL_POS+4 mov cx,WELL_HEIGHT __checking: mov bx,WELL_WIDTH*4-3 mov al,es:[di+bx] cmp al,BACKGROUND je __notfull __chkline: cmp es:[di+bx],al jne __notfull sub bx,4 jnc __chkline __full: mov bx,di dec bx __remove: mov dx,WELL_WIDTH*2 sub bx,160-WELL_WIDTH*4 jc __done __copy: mov al,es:[bx] mov es:[bx+160],al dec bx dec bx dec dx jnz __copy jmp __remove __done: push di push cx mov di,WELL_POS+4 mov cx,WELL_WIDTH*2 mov al,BACKGROUND __clear: inc di stosb loop __clear pop cx pop di inc Full __notfull: add di,160 loop __checking ret CheckFull endp MoveDown proc mov dx,160 Move proc call ClearCurr add dx,CurrFigPos mov di,dx mov ax,CurrFigState call CheckFig jc __bad mov CurrFigPos,dx __bad: DrawCurr proc pushf mov ax,CurrFigState mov di,CurrFigPos call GetFigAddr mov bx,offset Saved push di __saving: lodsb add di,ax mov al,es:[di] mov [bx],al inc bx loop __saving mov bl,CurrColor mov ax,CurrFigState call GetFigAddr pop di __drawing: lodsb add di,ax js __skip mov es:[di],bl mov es:[di+2],bl __skip: loop __drawing popf ret DrawCurr endp Move endp MoveDown endp PrintByte: xor ah,ah PrintWord: xor dx,dx PrintNum proc push bx mov bx,10 std __print: xchg ax,cx xchg ax,dx xor dx,dx div bx xchg ax,cx div bx xchg ax,dx add ax,'0'+NUM_ATTR shl 8 stosw xchg ax,cx xchg ax,dx or dx,dx jnz __print or ax,ax jnz __print cld pop bx ret PrintNum endp HandleKey proc call ReadKey cmp al,' ' je __drop cmp al,'1' je __next cmp al,'7' je __left cmp al,'9' je __right cmp al,'8' je __turn cmp al,'0' jne __ret __pause: mov dl,Counter call ReadKey mov Counter,dl __ret: ret __next: call ClearNext xor Next,SCORE_FOR_NEXT call DrawNext mov al,Next or NextDec,al ret __right: mov dx,4 jmp short __move __left: mov dx,-4 __move: jmp Move __turn: call ClearCurr mov di,CurrFigPos mov ax,CurrFigState inc ax and al,3 mov dx,ax call CheckFig jc __bad mov CurrFigState,dx __bad: jmp DrawCurr __drop: pop ax jmp Drop HandleKey endp AddScoreB proc cbw AddScoreW proc cwd add ScoreL,ax adc ScoreH,dx ret AddScoreW endp AddScoreB endp Play proc mov al,NextColor mov CurrColor,al mov al,Level mov di,30 call PrintByte mov ax,Full mov di,30+160 call PrintWord mov ax,ScoreL mov dx,ScoreH mov di,30+160*3 call PrintNum mov ah,NextFigNo ;assert(al==0) mov CurrFigState,ax mov di,START_POS mov CurrFigPos,di call CheckFig jc __gameover call ClearNext call RandomFig call DrawNext call DrawCurr __play: mov al,10 sub al,Level mov Counter,al __wait: mov ah,1 int 16h jz __checkcounter call HandleKey __checkcounter: cmp Counter,0 jne __wait ScoreForMoveDown call MoveDown jnc __play __fix: call CheckFull ScoreForFigure mov al,Next mov NextDec,al mov al,Level cmp al,9 je __jmpplay inc al mov ah,10 mul ah cmp ax,Full ja __jmpplay inc Level __jmpplay: jmp Play Drop: call MoveDown jc __fix ; or __play jmp Drop __gameover: mov ah,GAMEOVER_ATTR mov di,160*23+WELL_POS+6 call Print db 'G A M E',3,'O V E R',0 call Delay9 __flush: mov ah,1 int 16h pushf call ReadKey popf jnz __flush mov bx,(type HiScoresTbl)*HSCORETBL_SIZE mov TblPos,bx mov di,offset HiScoresTbl __search: sub bx,type HiScoresTbl jc __done mov ax,ScoreH cmp ax,[di+bx].HScoreH jb __search ja __found mov ax,ScoreL cmp ax,[di+bx].HScoreL jb __search ja __found mov al,ColorsNum cmp al,[di+bx].HColors jb __search ja __found mov al,Level cmp al,[di+bx].HLevel jb __search ja __found mov al,SLevel cmp al,[di+bx].HSLevel jb __search __found: push bx add bx,offset HiScoresTbl mov TblPos,bx push di call GetName pop di mov si,di add si,type HiScoresTbl pop cx push es cs pop es rep movsb mov si,offset NewHiScore mov cx,type HiScoresTbl rep movsb pop es __done: ret Play endp Delay9 proc mov Counter,9 __wait: cmp Counter,0 jne __wait ret Delay9 endp GetName proc call Cursor mov di,160*24 mov ah,BLANK shr 8 call Print db 'Enter your name: ',0 ; the last space is necessery mov si,offset NewName xor bp,bp __input: mov dx,bp add dx,24*256+17 call WaitKeyAt cmp al,13 je __done cmp al,8 je __backspace cmp al,32 jb __input cmp bp,NAME_LEN-1 je __input mov [bp+si],al inc bp mov ah,NAME_ATTR stosw jmp __input __backspace: or bp,bp jz __input dec di dec di mov word ptr es:[di],BLANK dec bp jmp __input __done: mov byte ptr [si+bp],0 Cursor proc mov ah,3 int 10h xor ch,20h mov ah,1 int 10h ret Cursor endp GetName endp DisplayPlayerInfo proc inc cx sub bx,type HiScoresTbl mov ax,[bx].HScoreL mov dx,[bx].HScoreH or ax,ax jnz __good or dx,dx jz __bad __good: push cx mov di,bp call PrintNum lea di,[bp-(12*2)] mov al,[bx].HColors call PrintByte lea di,[bp-(12*2)-4] mov al,[bx].HLevel call PrintByte mov word ptr es:[di],NUM_ATTR shl 8 + '-' dec di dec di mov al,[bx].HSLevel call PrintByte lea di,[bp-(16+16)*2-4] lea si,[bx].HName mov ah,NAME_ATTR call PrintStr pop ax push ax lea di,[bp-(16+16+3)*2-4] call PrintWord lea di,[bp-(16+16+3)*2+2-4] mov ax,(NUM_ATTR shl 8) + '.' cmp bx,TblPos jne __nocurr or ah,80h __nocurr: stosw pop cx __bad: add bp,160 ret DisplayPlayerInfo endp DisplayTable proc call ClearScr mov di,40 call Print db 'Highest results of Colored Small Tetris',0 mov bx,(type HiScoresTbl)*HSCORETBL_SIZE+offset HiScoresTbl xor cx,cx mov bp,160*2+114 __print1: call DisplayPlayerInfo cmp cx,10 jb __print1 mov bp,160*13+76 __print2: call DisplayPlayerInfo cmp cx,20 jb __print2 mov bp,160*13+158 __print3: call DisplayPlayerInfo cmp cx,30 jb __print3 __done: ret DisplayTable endp Timer proc sub cs:Counter,1 adc cs:Counter,0 db 0EAh ; far jump to previous handler OldTimer dw offset Timer,? Timer endp end start