;-----------------------------------------------; ; Game "Snake" Version 1.2 ; ; Copyright (c) 1991 by Alexander V. Lukianov ; ;-----------------------------------------------; space_code equ 39h left equ 4B00h right equ 4D00h min_score equ 60 score_factor equ 30 min_speed equ timnew/2 speed_factor equ min_speed/10-2 score_pos equ 1810h length_pos equ 1820h mode equ 1 wall equ 05000h body equ 00E01h headsym equ 00E02h rabbit equ 0F02Ah free equ 002B0h tim equ 11900 timold equ 18 timnew equ timold*16 player struc pname db 16 dup(?) pscore dw ? pspeed dw ? plength dw ? player ends locate macro x,y mov bh,0 mov dx,(y shl 8)+x mov ah,2 int 10h endm beep macro eee,time mov ax,tim/eee*100 mov cx,time*timnew/timold call _sound endm cls macro sym locate 0,0 mov cx,25*40 mov bx,(sym shr 8) mov ax,0900h+(sym and 255) int 10h endm cursor macro tp mov cx,stdcur ifidn , or ch,16 endif ifidn , mov ch,0 endif mov ah,1 int 10h endm code segment assume cs:code,ds:code,es:code,ss:code org 100h main proc far call read_table call save_screen call set_timer continue_game: call initgame call play call flush_kbd locate 0,24 mov si,offset OnceMore call printstr m109: call inkey or ax,ax jz m109 cmp al,'n' je exit1 cmp al,'N' je exit1 mov si,offset yes call printstr beep 100,2 beep 500,2 beep 700,2 jmp continue_game exit1: mov ax,0E00h+'N' int 10h mov ax,0E00h+'o' int 10h beep 300,1 beep 250,1 beep 100,8 exit: call restore_timer call restore_screen call write_table mov ax,4C00h int 21h main endp flush_kbd proc mov ah,1 int 16h jz done_flush mov ah,0 int 16h jmp flush_kbd done_flush: ret flush_kbd endp save_screen proc cld mov ah,15 int 10h mov oldmode,al mov ah,3 int 10h mov oldpos,dx mov oldsize,cx push ds xor ax,ax mov ds,ax mov si,word ptr [ds:044Eh] ; page offset mov di,offset screen mov cx,word ptr [ds:044Ch] ; page size mov ax,0B800h mov ds,ax mov es:scrlen,cx cmp cx,4000h ja no_save rep movsb no_save: pop ds mov ax,mode ; set screen mode (1 - color 40x25) int 10h mov ah,3 mov bh,0 int 10h mov stdcur,cx ; get cursor size ret save_screen endp restore_screen proc mov ah,0 mov al,oldmode int 10h mov cx,scrlen cmp cx,4000h ja no_restore push es mov ax,0B800h mov es,ax mov si,offset screen xor di,di rep movsb pop es mov ah,1 mov cx,oldsize mov bh,0 int 10h mov ah,2 mov dx,oldpos int 10h no_restore: ret restore_screen endp set_timer proc mov al,00110110b out 43h,al mov ax,tim/timnew nop out 40h,al mov al,ah out 40h,al mov ax,3508h int 21h mov word ptr old8,bx mov word ptr old8+2,es mov ax,3509h int 21h mov word ptr old9,bx mov word ptr old9+2,es push ds pop es mov dx,offset int8 mov ax,2508h int 21h mov dx,offset int9 mov ax,2509h int 21h ret set_timer endp restore_timer proc mov al,00110110b out 43h,al mov al,0 nop out 40h,al nop nop out 40h,al push ds lds dx,old8 mov ax,2508h int 21h lds dx,cs:old9 mov ax,2509h int 21h pop ds ret restore_timer endp play proc cursor off dec score pushf call score_display popf jz death mov cx,delay_count cmp space_pressed,0 je small_speed shr cx,1 shr cx,1 small_speed: call delay call key call move cmp ax,rabbit jne hun jmp eat hun: cmp ax,wall je death cmp ax,body je death dec count jnz play mov ax,wall_count mov count,ax call new_wall jmp play death: beep 200,10 locate ((40-GameOver_len)/2),11 mov bx,000Ch mov cx,GameOver_len mov ax,0900h int 10h mov si,offset GameOver call printstr beep 200,5 beep 300,1 beep 600,1 beep 1000,2 mov cx,10 call delay beep 200,20 mov cx,10 call delay beep 200,5 cursor on call handle_score ret eat: cursor big beep 600,2 beep 280,3 beep 50,7 cursor off mov ax,rabbit_price add score,ax inc _length call score_display call length_display sub tail,2 and tail,0FFFh mov bx,tail mov dx,buffer[ bx ] mov bh,0 mov ah,2 int 10h mov ax,0901h mov bl,0Fh mov cx,1 int 10h call new_rabbit jmp play play endp move proc mov bx,tail mov dx,buffer[ bx ] add bx,2 and bx,0FFFh mov tail,bx mov bh,0 mov ah,2 int 10h ;¯ĨāĨŦĨáâ¨âė ĒãāáŽā mov cx,1 mov bl,free shr 8 mov ax,0900h+(free and 255) int 10h ;áâĨāĨâė åĸŽáâ mov si,head mov dx,buffer[ si ] mov ah,2 int 10h mov cx,1 mov bl,body shr 8 mov ax,0900h+(body and 255) int 10h ;§ ŦĨ­¨âė ŖŽĢŽĸã âĨĢŽŦ mov bx,curr_direc add dx,directions[ bx ] mov bh,0 mov ah,2 int 10h mov ah,8 int 10h push ax add si,2 and si,0FFFh mov head,si mov buffer[ si ],dx mov cx,1 mov bl,headsym shr 8 mov ax,0900h+(headsym and 255) int 10h pop ax ret move endp initgame proc mov curr_direc,0 call enter_speed cls 0A00h mov bx,0000h+(free shr 8) mov ax,0900h+(free and 255) mov cx,40*23 int 10h mov cx,40 mov bx,0000h+(wall shr 8) mov ax,0900h+(wall and 255) int 10h mov dx,0100h mov cx,22 cycle: push cx mov ah,2 int 10h mov cx,1 mov ax,0900h+(wall and 255) int 10h mov dl,39 mov ah,2 int 10h mov cx,1 mov ax,0900h+(wall and 255) int 10h add dh,1 mov dl,0 pop cx loop cycle mov ah,2 int 10h mov cx,40 mov bx,0000h+(wall shr 8) mov ax,0900h+(wall and 255) int 10h mov ax,0C10h mov cx,5 mov _length,cx mov di,offset buffer cycle2: stosw inc ax loop cycle2 mov tail,0 mov head,8 mov dx,0C10h mov ah,2 int 10h mov ax,0900h+(body and 255) mov cx,4 mov bl,body shr 8 int 10h call move call new_rabbit locate 0,24 mov si,offset Info call printstr call length_display call score_display ret initgame endp key proc mov ah,1 int 16h jz key_end call inkey cmp ax,right je turn_right cmp ax,left jne key turn_left: sub curr_direc,4 turn_right: add curr_direc,2 and curr_direc,7 key_end: ret key endp new_rabbit proc call rndpos mov cx,1 mov ax,0900h+(rabbit and 255) mov bl,rabbit shr 8 mov bh,0 int 10h ret new_rabbit endp new_wall proc call rndpos mov cx,1 mov ax,0900h+(wall and 255) mov bl,wall shr 8 mov bh,0 int 10h ret new_wall endp random proc mov al,0 out 43,al nop nop in al,40h mov ah,al nop in al,40h xchg al,ah ret random endp rndpos proc cont: call random xchg al,ah mov bx,40 mov dx,0 add ax,0F000h div bx mov cx,dx call random mov bx,24 mov dx,0 add ax,0F000h div bx mov ch,dl mov dx,cx mov ah,2 mov bh,0 int 10h mov ah,8 int 10h cmp ax,free jne cont ret rndpos endp length_display proc mov dx,length_pos mov bh,0 mov ah,2 int 10h mov ax,_length call print_ax ret length_display endp score_display proc mov dx,score_pos mov bh,0 mov ah,2 int 10h mov ax,score call print_ax ret score_display endp print_ax proc push dx mov cx,5 m1111: xor dx,dx div ten add dl,'0' mov dh,14 push dx loop m1111 mov cx,4 m1212: pop ax cmp al,'0' je m1312 inc cx jmp m1311 m1312: mov al,' ' int 10h loop m1212 inc cx m1211: pop ax m1311: int 10h loop m1211 pop dx ret print_ax endp print_al proc push dx mov cx,2 _m1111: xor ah,ah div byte ptr ten add ah,'0' mov dl,ah mov dh,14 push dx loop _m1111 mov cx,1 pop ax cmp al,'0' je _m1312 inc cx jmp _m1311 _m1312: mov al,' ' int 10h _m1211: pop ax _m1311: int 10h loop _m1211 pop dx ret print_al endp enter_speed proc cls 0A00h mov si,offset help call printstr locate 0,23 mov ax,0900h mov bx,0070h mov cx,40 int 10h mov si,offset EnterSpeed call printstr more: beep 100,1 call inkey cmp al,'0' jb more cmp al,'9' ja more mov ah,0 push ax mov ah,14 int 10h beep 1000,1 pop ax sub ax,'0' mov speed,ax mov cx,ax mov ax,score_factor mul cx add ax,score_factor mov count,ax mov wall_count,ax mul cx shr ax,1 add ax,min_score mov rabbit_price,ax mov score,ax mov ax,min_speed xor dx,dx inc cx div cx sub ax,speed_factor mov delay_count,ax ret enter_speed endp printstr proc cycle10: lodsb or al,al jz stop mov ah,14 int 10h jmp short cycle10 stop: ret printstr endp handle_score proc mov si,offset table mov cx,20 h1: mov ax,score cmp ax,[si].pscore ja write jne h2 mov ax,speed cmp ax,[si].pspeed ja write jne h2 mov ax,_length cmp ax,[si].plength ja write h2: add si,size player loop h1 mov pos,-1 jmp quit write: push si mov al,23 sub al,cl mov pos,al mov ax,size player dec cx mul cx mov cx,ax mov si,size player*19+offset table-1 mov di,size player*20+offset table-1 std rep movsb cld locate 0,23 mov ax,0900h+(wall and 255) mov bx,wall shr 8 mov cx,40 int 10h mov si,offset EnterName call printstr pop si lea di,[si].pname mov cx,15 call inputstr mov ax,score mov [si].pscore,ax mov ax,speed mov [si].pspeed,ax mov ax,_length mov [si].plength,ax quit: beep 1000,1 call table_display ret handle_score endp inputstr proc push si mov maxlen,cx xor cx,cx _more: mov ah,0 int 16h cmp al,27 jne inp100 mov byte ptr [di],0 jmp exit inp100: cmp al,13 je done cmp al,8 je back cmp al,' ' jb _more inc cx cmp cx,maxlen jb i2 dec cx jmp _more i2: stosb mov ah,14 int 10h jmp _more back: jcxz _more dec cx dec di mov si,offset BS call printstr jmp _more done: mov byte ptr [di],0 pop si ret inputstr endp tab macro posn mov dl,posn mov bh,0 mov ah,2 int 10h endm table_display proc mov ax,0 int 10h mov si,offset game_title call printstr mov cx,20 mov di,offset table t1: push cx mov dh,23 sub dh,cl tab 1 mov al,21 sub al,cl call print_al tab 4 lea si,[di].pname call printstr tab 20 mov ax,[di].pscore call print_ax tab 26 mov ax,[di].plength call print_ax tab 33 mov ax,[di].pspeed call print_ax add di,size player pop cx loop t1 mov dh,pos mov dl,0 mov ah,2 mov bh,0 int 10h mov ax,0E2Ah int 10h locate 0,23 mov si,offset line call printstr pop si ret table_display endp read_table proc mov di,offset table mov cx,20 r1: mov [di].pname, 0 mov [di].pscore, 60 mov [di].pspeed, 0 ; clear player fields mov [di].plength, 5 add di,size player loop r1 mov dx,offset file mov ax,3D00h ; open the file for reading int 21h jc rstop mov bx,ax mov dx,offset table mov cx,size player*20 mov ah,3Fh ; read the file int 21h jc rstop mov ah,3Eh ; close the file int 21h rstop: ret read_table endp write_table proc xor cx,cx mov dx,offset file mov ah,3Ch ; create file int 21h jc wstop mov bx,ax mov dx,offset table mov cx,size player*20 mov ah,40h ; write file int 21h jc wstop mov ah,3Eh ; close file int 21h wstop: ret write_table endp inkey proc mov ah,0 int 16h cmp al,27 jne i01 jmp exit i01: cmp al,'s' je snd cmp al,'S' je snd ret snd: xor sound,1 xor ax,ax ret inkey endp _sound proc push ax mov al,10110110b out 43h,al pop ax out 42h,al mov al,ah nop out 42h,al in al,61h push ax cmp sound,0 jne _s1 or al,00000011b out 61h,al _s1: call delay pop ax out 61h,al ret _sound endp delay proc sti mov time_count,cx kill_time: cmp time_count,0 jne kill_time ret delay endp ;*****************************************************************************; ; Interrupts handlers ; ;*****************************************************************************; int8 proc far cmp cs:time_count,0 je null_time dec cs:time_count null_time: dec cs:tcount jnz quit8 mov cs:tcount,timnew/timold db 0EAh ; Far jump to old8 (timer handler) old8 dd ? quit8: push ax mov al,20h out 20h,al pop ax iret int8 endp int9 proc far push ax in al,60h cmp al,space_code jne no_space_pressed mov cs:space_pressed,1 jmp short no_space no_space_pressed: cmp al,space_code+80h jne no_space mov cs:space_pressed,0 no_space: pop ax db 0EAh ; Far jump to old9 (keyboard handler) old9 dd ? int9 endp ;*****************************************************************************; ; Program data ; ;*****************************************************************************; ; * * * * * ; game_title db ' 20 best players',10,13 db 'Num Name Score Length Speed ',10,13 line db '””” ””””””””””””””” ””””” ”””””” ”””””',0 help db 'Key Meaning',10,13 db '””””” ”””””””””””””””””””””””””””””””””' db ' ',1Bh,' turn to the left',10,13 db ' ',1Ah,' turn to the right',10,13 db 'SPACE speeding',10,13 db ' S sound on/off',10,13 db ' ESC quit',10,13 db '””””” ”””””””””””””””””””””””””””””””””' db ' This game was created by' db ' Alexander V. Lukyanov',10,13 db ' 1991 V1.2',0 yes db 'Yes',0 EnterSpeed db 'Enter speed [0..9] : ',0 GameOver db ' GAME OVER ',0 GameOver_len equ $-GameOver-1 OnceMore db 'Once more ? (Yes/No) : ',0 ; * * S * * L * ; Info db 'lav (c) Score : Length :',0 EnterName db 'Enter your name : ',0 directions dw 0001h,0100h,0FFFFh,0FF00h BS db 8,32,8,0 ten dw 10 file db 'snake.res',0 sound db 0 tcount db timnew/timold space_pressed db 0 time_count dw ? maxlen dw ? table db size player*20 dup(?) stdcur dw ? buffer dw 800h dup( ? ) head dw ? tail dw ? curr_direc dw ? score dw ? _length dw ? rabbit_price dw ? wall_count dw ? count dw ? speed dw ? delay_count dw ? pos db ? oldmode db ? oldpos dw ? oldsize dw ? scrlen dw ? screen label byte code ends end main