[org 0x0100]
jmp start
snake: times 240 db 0
lenght: times 240 dw 0
screenpositon: times 240 dw 0
orientation: dw 0
tickcount: dw 0
tickcount2: dw 0
lives: db 3
livesmessage: db 'Your Lives : '
timemessage: db 'Time left : '
minitues: db 3
seconds: dw 60
tickcount3: dw 0
speed: dw 32
score: dw 0
scoremessage: db 'Your Score : '
tickcount4: dw 0
positionoffruit: dw 0
generaterandom:
pusha
mov ax,[cs:tickcount4]
checkifitisonoraboveupperboarder:
cmp ax,642
ja checkifitisonorbelowlowerboarder
add ax,160
cmp ax,642
jbe checkifitisonoraboveupperboarder
checkifitisonorbelowlowerboarder:
cmp ax,3516
jna checkifboarder
sub ax,160
cmp ax,3516
jae checkifitisonorbelowlowerboarder
checkifboarder:
mov ch,0x09
mov cl,'$'
mov bx,ax
cmp word[es:bx],cx
jne checkifonsnake
add ax,6
checkifonsnake:
mov bx,0
mov cx,[cs:lenght]
loopforcheckifonsnake:
cmp ax,[cs:screenpositon+bx]
je outofoutoflop
add bx,2
loop loopforcheckifonsnake
outofoutoflop:
mov bx,[cs:lenght]
shl bx,1
sub bx,2
outofloop:
mov cx,[cs:screenpositon+bx]
add cx,6
mov ax,cx
storefruitposition:
mov word[cs:positionoffruit],ax
popa
ret
printfruit:
pusha
mov ax,0xb800
mov es,ax
mov di,[cs:positionoffruit]
mov ah,0x04
mov al,'@'
mov word[es:di],ax
popa
ret
printscore:
pusha
mov ax,0xb800
mov es,ax
mov cx,13
mov di,278
mov ah,0x03
mov bx,0
loopforscoremessage:
mov al,[cs:scoremessage+bx]
mov word[es:di],ax
add di,2
inc bx
loop loopforscoremessage
mov ax,[cs:score]
push ax
call printnumforscore
popa
ret
printnumforscore:
push bp
mov bp, sp
push es
push ax
push bx
push cx
push dx
push di
mov ax, 0xb800
mov es, ax ; point es to video base
mov ax, [bp+4] ; load number in ax
mov bx, 10 ; use base 10 for division
mov cx, 0 ; initialize count of digits
nextdigitforscore:
mov dx, 0 ; zero upper half of dividend
div bx ; divide by 10
add dl, 0x30 ; convert digit into ascii value
push dx ; save ascii value on stack
inc cx ; increment count of values
cmp ax, 0 ; is the quotient zero
jnz nextdigitforscore ; if no divide it again
mov di, 304
nextposforscore:
pop dx ; remove a digit from the stack
mov dh, 0x04 ; use normal attribute
mov [es:di], dx ; print char on screen
add di, 2 ; move to next screen location
loop nextposforscore ; repeat for all digits on stack
pop di
pop dx
pop cx
pop bx
pop ax
pop es
pop bp
ret 2
increasespeed:
pusha
cmp word[cs:speed],1
je endofincreasespeed
cmp word[cs:speed],2
jne cmpfor4
mov word[cs:speed],1
jmp endofincreasespeed
cmpfor4:
cmp word[cs:speed],4
jne cmpfor8
mov word[cs:speed],2
jmp endofincreasespeed
cmpfor8:
cmp word[cs:speed],8
jne cmpfor32
mov word[cs:speed],4
jmp endofincreasespeed
cmpfor32:
cmp word[cs:speed],32
jne cmpfor16
mov word[cs:speed],16
jmp endofincreasespeed
cmpfor16:
cmp word[cs:speed],16
jne endofincreasespeed
mov word[cs:speed],8
endofincreasespeed:
popa
ret
printnum:
push bp
mov bp, sp
push es
push ax
push bx
push cx
push dx
push di
mov ax, 0xb800
mov es, ax ; point es to video base
mov ax, [bp+4] ; load number in ax
mov bx, 10 ; use base 10 for division
mov cx, 0 ; initialize count of digits
nextdigit:
mov dx, 0 ; zero upper half of dividend
div bx ; divide by 10
add dl, 0x30 ; convert digit into ascii value
push dx ; save ascii value on stack
inc cx ; increment count of values
cmp ax, 0 ; is the quotient zero
jnz nextdigit ; if no divide it again
mov di, 248
nextpos:
pop dx ; remove a digit from the stack
mov dh, 0x04 ; use normal attribute
mov [es:di], dx ; print char on screen
add di, 2 ; move to next screen location
loop nextpos ; repeat for all digits on stack
pop di
pop dx
pop cx
pop bx
pop ax
pop es
pop bp
ret 2
printtime:
pusha
mov ax,0xb800
mov es,ax
mov cx,12
mov di,220
mov ah,0x03
mov bx,0
loopfortimemessage:
mov al,[cs:timemessage+bx]
mov word[es:di],ax
add di,2
inc bx
loop loopfortimemessage
mov ah,0x04
mov al,[cs:minitues]
add al,0x30
mov word[es:di],ax
mov ah,0x04
mov al,':'
mov word[es:di+2],ax
mov ax,[cs:seconds]
cmp word[cs:seconds],9
jbe printsimpleseconds
push ax
call printnum
jmp endofprintnum
printsimpleseconds:
mov bx,[cs:seconds]
mov al,bl
add al,0x30
mov ah,0x04
mov bh,0x04
mov bl,'0'
mov word[es:di+4],bx
mov word[es:di+6],ax
endofprintnum:
popa
ret
printlives:
pusha
mov ax,0xb800
mov es,ax
mov cx,13
mov di,160
mov ah,0x03
mov bx,0
loopforlivesmessage:
mov al,[cs:livesmessage+bx]
mov word[es:di],ax
add di,2
inc bx
loop loopforlivesmessage
mov ah,0x04
mov al,[cs:lives]
add al,0x30
mov word[es:di],ax
popa
ret
extendlength:
pusha
mov cx,[cs:lenght]
mov bx,[cs:lenght]
sub bx,1
loopforextendlength:
mov al,[cs:snake+bx]
mov [cs:snake+bx+4],al
dec bx
loop loopforextendlength
mov cx,[cs:lenght]
mov bx,[cs:lenght]
shl bx,1
sub bx,2
loopforextendlengthofscreenpositon:
mov ax,[cs:screenpositon+bx]
mov word[cs:screenpositon+bx+8],ax
sub bx,2
loop loopforextendlengthofscreenpositon
add word[cs:lenght],4
popa
ret
reset:
pusha
call clrscr
call printboarders
call initializesnake
call printsnake
call generaterandom
call printfruit
mov word[cs:speed],32
mov word[cs:orientation],1
mov word[cs:score],0
call printscore
mov byte al,[cs:lives]
sub al,1
mov byte[cs:lives],al
call printlives
cmp byte[cs:lives],0
jne printingnormaltime
mov word[cs:seconds],0
mov byte[cs:minitues],0
call printtime
jmp endofreset
printingnormaltime:
mov word[cs:seconds],60
mov byte[cs:minitues],3
call printtime
endofreset:
popa
ret
clrscr:
push es
push ax
push cx
push di
mov ax, 0xb800
mov es, ax
xor di, di
mov ax, 0x0720
mov cx, 2000
cld
rep stosw
pop di
pop cx
pop ax
pop es
ret
printboarders:
pusha
mov ax,0xb800
mov es,ax
mov di,480
mov cx,160
mov ah,0x09
mov al,'$'
printupperboarder:
mov word[es:di],ax
add di,2
dec cx
loop printupperboarder
mov di,3520
mov cx,160
printlowerboarder:
mov word[es:di],ax
add di,2
dec cx
loop printlowerboarder
mov di,480
mov cx,20
printleftboarder:
mov word[es:di],ax
add di,160
loop printleftboarder
mov di,638
mov cx,20
printrightboarder:
mov word[es:di],ax
add di,160
loop printrightboarder
popa
ret
printsnake:
pusha
mov ax,0xb800
mov es,ax
mov di,1980
mov word cx,[cs:lenght]
mov bx,0
mov ah,0x06
mov si,0
loopforprintsnake:
mov al,[cs:snake+bx]
mov word[es:di],ax
mov word[cs:screenpositon+si],di
inc bx
add di,2
add si,2
loop loopforprintsnake
popa
ret
initializesnake:
pusha
mov word[cs:lenght],20
mov cx,20
mov byte[cs:snake+19],'+'
dec cx
mov bx,0
loopforinitializesnake:
mov byte[cs:snake+bx],'-'
inc bx
loop loopforinitializesnake
popa
ret
movright:
pusha
mov ax,0xb800
mov es,ax
cmp word[cs:orientation],3
je endofmovright
mov word si,[cs:lenght]
shl si,1
sub si,2
colissioncheckright:
mov ah,0x09
mov al,'$'
mov di,[cs:screenpositon+si] ;Position OF HEAD
cmp ax,[es:di+2]
jne colissioncheckrightitself
call reset
jmp endofmovright
colissioncheckrightitself:
mov ah,0x06
mov al,'-'
mov di,[cs:screenpositon+si] ;Position OF HEAD
cmp ax,[es:di+2]
jne colissioncheckrightfruit
call reset
jmp endofmovright
colissioncheckrightfruit:
mov ah,0x04
mov al,'@'
mov di,[cs:screenpositon+si] ;Position OF HEAD
cmp ax,[es:di+2]
jne continuetomoveright
inc word[cs:score]
call generaterandom
call printfruit
call extendlength
mov si,[cs:screenpositon+8]
mov di,[cs:screenpositon+10]
sub di,si
checkupforrightfruit:
cmp di,160
jne checkdownforrightfruit
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placeupforrightfruit:
sub si,160
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placeupforrightfruit
jmp continuetomoveright
checkdownforrightfruit:
cmp di,-160
jne checkleftforrightfruit
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placedownforrightfruit:
add si,160
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placedownforrightfruit
jmp continuetomoveright
checkleftforrightfruit:
cmp di,2
jne checkrightforrightfruit
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placeleftforrightfruit:
sub si,2
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placeleftforrightfruit
jmp continuetomoveright
checkrightforrightfruit:
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placerightforrightfruit:
add si,2
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placerightforrightfruit
continuetomoveright:
mov word cx,[cs:lenght]
dec cx
mov word bx,[cs:lenght]
dec bx
mov word si,[cs:lenght]
shl si,1
sub si,2
mov ah,0x06
mov di,[cs:screenpositon+si] ;Position OF HEAD
mov al,[cs:snake+bx] ; Get value of HEAD
mov word[es:di+2],ax
add word[cs:screenpositon+si],2
loopformovingright:
mov bx,[cs:screenpositon+si-2]
mov ax,[es:bx]
mov word[es:di],ax
mov [cs:screenpositon+si-2],di
mov di,bx
sub si,2
loop loopformovingright
mov dx,0x0720
mov word[es:di],dx
mov word[cs:orientation],1
endofmovright:
popa
ret
movup:
pusha
mov ax,0xb800
mov es,ax
cmp word[cs:orientation],4
je endofmovingup
mov word si,[cs:lenght]
shl si,1
sub si,2
colissioncheckup:
mov ah,0x09
mov al,'$'
mov di,[cs:screenpositon+si]
cmp ax,[es:di-160]
jne colissioncheckupitself
call reset
jmp endofmovingup
colissioncheckupitself:
mov ah,0x06
mov al,'-'
mov di,[cs:screenpositon+si]
cmp ax,[es:di-160]
jne colissioncheckupfruit
call reset
jmp endofmovingup
colissioncheckupfruit:
mov ah,0x04
mov al,'@'
mov di,[cs:screenpositon+si]
cmp ax,[es:di-160]
jne continuetomoveup
inc word[cs:score]
call generaterandom
call printfruit
call extendlength
mov si,[cs:screenpositon+8]
mov di,[cs:screenpositon+10]
sub di,si
checkupforupfruit:
cmp di,160
jne checkdownforupfruit
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placeupforupfruit:
sub si,160
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placeupforupfruit
jmp continuetomoveup
checkdownforupfruit:
cmp di,-160
jne checkleftforupfruit
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placedownforupfruit:
add si,160
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placedownforupfruit
jmp continuetomoveup
checkleftforupfruit:
cmp di,2
jne checkrightforupfruit
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placeleftforupfruit:
sub si,2
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placeleftforupfruit
jmp continuetomoveup
checkrightforupfruit:
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placerightforupfruit:
add si,2
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placerightforupfruit
continuetomoveup:
mov word cx,[cs:lenght]
dec cx
mov word bx,[cs:lenght]
dec bx
mov word si,[cs:lenght]
shl si,1
sub si,2
mov ah,0x06
mov di,[cs:screenpositon+si] ;Position OF HEAD
mov al,[cs:snake+bx] ; Get value of HEAD
mov word[es:di-160],ax
sub word[cs:screenpositon+si],160
loopformovingup:
mov bx,[cs:screenpositon+si-2]
mov ax,[es:bx]
mov word[es:di],ax
mov [cs:screenpositon+si-2],di
mov di,bx
sub si,2
loop loopformovingup
mov dx,0x0720
mov word[es:di],dx
mov word[cs:orientation],2
endofmovingup:
popa
ret
movdown:
pusha
mov ax,0xb800
mov es,ax
cmp word[cs:orientation],2
je endofmovingdown
mov word si,[cs:lenght]
shl si,1
sub si,2
colissioncheckdown:
mov ah,0x09
mov al,'$'
mov di,[cs:screenpositon+si] ;Position OF HEAD
cmp ax,[es:di+160]
jne colissioncheckdownitself
call reset
jmp endofmovingdown
colissioncheckdownitself:
mov ah,0x06
mov al,'-'
mov di,[cs:screenpositon+si] ;Position OF HEAD
cmp ax,[es:di+160]
jne colissioncheckdownfruit
call reset
jmp endofmovingdown
colissioncheckdownfruit:
mov ah,0x04
mov al,'@'
mov di,[cs:screenpositon+si] ;Position OF HEAD
cmp ax,[es:di+160]
jne continuetomovedown
inc word[cs:score]
call generaterandom
call printfruit
call extendlength
mov si,[cs:screenpositon+8]
mov di,[cs:screenpositon+10]
sub di,si
checkupfordownfruit:
cmp di,160
jne checkdownfordownfruit
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placeupfordownfruit:
sub si,160
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placeupfordownfruit
jmp continuetomovedown
checkdownfordownfruit:
cmp di,-160
jne checkleftfordownfruit
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placedownfordownfruit:
add si,160
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placedownfordownfruit
jmp continuetomovedown
checkleftfordownfruit:
cmp di,2
jne checkrightfordownfruit
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placeleftfordownfruit:
sub si,2
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placeleftfordownfruit
jmp continuetomovedown
checkrightfordownfruit:
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placerightfordownfruit:
add si,2
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placerightfordownfruit
continuetomovedown:
mov word cx,[cs:lenght]
dec cx
mov word bx,[cs:lenght]
dec bx
mov word si,[cs:lenght]
shl si,1
sub si,2
mov ah,0x06
mov di,[cs:screenpositon+si] ;Position OF HEAD
mov al,[cs:snake+bx] ; Get value of HEAD
mov word[es:di+160],ax
add word[cs:screenpositon+si],160
loopformovingdown:
mov bx,[cs:screenpositon+si-2]
mov ax,[es:bx]
mov word[es:di],ax
mov [cs:screenpositon+si-2],di
mov di,bx
sub si,2
loop loopformovingdown
mov dx,0x0720
mov word[es:di],dx
mov word[cs:orientation],4
endofmovingdown:
popa
ret
movleft:
pusha
mov ax,0xb800
mov es,ax
cmp word[cs:orientation],1
je endofmovingleft
mov word si,[cs:lenght]
shl si,1
sub si,2
colissioncheckleft:
mov ah,0x09
mov al,'$'
mov di,[cs:screenpositon+si] ;Position OF HEAD
cmp ax,[es:di-2]
jne colissioncheckleftitself
call reset
jmp endofmovingleft
colissioncheckleftitself:
mov ah,0x06
mov al,'-'
mov di,[cs:screenpositon+si] ;Position OF HEAD
cmp ax,[es:di-2]
jne colissioncheckleftfruit
call reset
jmp endofmovingleft
colissioncheckleftfruit:
mov ah,0x04
mov al,'@'
mov di,[cs:screenpositon+si] ;Position OF HEAD
cmp ax,[es:di-2]
jne continuetomoveleft
inc word[cs:score]
call generaterandom
call printfruit
call extendlength
mov si,[cs:screenpositon+8]
mov di,[cs:screenpositon+10]
sub di,si
checkupforleftfruit:
cmp di,160
jne checkdownforleftfruit
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placeupforleftfruit:
sub si,160
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placeupforleftfruit
jmp continuetomoveleft
checkdownforleftfruit:
cmp di,-160
jne checkleftforleftfruit
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placedownforleftfruit:
add si,160
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placedownforleftfruit
jmp continuetomoveleft
checkleftforleftfruit:
cmp di,2
jne checkrightforleftfruit
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placeleftforleftfruit:
sub si,2
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placeleftforleftfruit
jmp continuetomoveleft
checkrightforleftfruit:
mov cx,4
mov ah,0x06
mov al,'-'
mov bx,6
placerightforleftfruit:
add si,2
mov word[es:si],ax
mov [cs:screenpositon+bx],si
sub bx,2
loop placerightforleftfruit
continuetomoveleft:
mov word cx,[cs:lenght]
dec cx
mov word bx,[cs:lenght]
dec bx
mov word si,[cs:lenght]
shl si,1
sub si,2
mov ah,0x06
mov di,[cs:screenpositon+si] ;Position OF HEAD
mov al,[cs:snake+bx] ; Get value of HEAD
mov word[es:di-2],ax
sub word[cs:screenpositon+si],2
loopformovingleft:
mov bx,[cs:screenpositon+si-2]
mov ax,[es:bx]
mov word[es:di],ax
mov [cs:screenpositon+si-2],di
mov di,bx
sub si,2
loop loopformovingleft
mov dx,0x0720
mov word[es:di],dx
mov word[cs:orientation],3
endofmovingleft:
popa
ret
timer:
pusha
inc word[cs:tickcount]
inc word[cs:tickcount2]
inc word[cs:tickcount3]
inc word[cs:tickcount4]
inc word[cs:tickcount4]
checkrandom:
cmp word[cs:tickcount4],4000
jne check20seconds
mov word[cs:tickcount4],0
check20seconds:
cmp word[cs:tickcount3],364
jne checklive
call increasespeed
mov word[cs:tickcount3],0
checklive:
cmp byte[cs:lives],0
je endoftimer
checkminitues:
cmp word[cs:seconds],0
jne checkseconds
cmp byte[cs:minitues],0
jne checkremaining
call reset
jmp endoftimer
checkremaining:
dec byte[cs:minitues]
mov byte[cs:seconds],60
jmp checktickcount
checkseconds:
cmp word[cs:tickcount2],18
jne checktickcount
dec word[cs:seconds]
mov byte[cs:tickcount2],0
call printtime
call printscore
checktickcount:
mov ax,[cs:speed]
cmp word[cs:tickcount],ax
jng endoftimer
ifright:
cmp word[cs:orientation],1
jne ifup
call movright
mov word[cs:tickcount],0
ifup:
cmp word[cs:orientation],2
jne ifleft
call movup
mov word[cs:tickcount],0
ifleft:
cmp word[cs:orientation],3
jne ifdown
call movleft
mov word[cs:tickcount],0
ifdown:
cmp word[cs:orientation],4
jne endoftimer
call movdown
mov word[cs:tickcount],0
endoftimer:
mov al, 0x20
out 0x20, al ; end of interrupt
popa
iret ; return from interrupt
kbisr:
pusha
cmp byte[cs:lives],0
je endofkbisr
in al,0x60
cmp al,0x4D ;compare with Right
jne compareUp
call movright
jmp endofkbisr
compareUp:
cmp al,0x48 ;compare
jne compareDown
call movup
jmp endofkbisr
compareDown:
cmp al,0x50
jne compareLeft
call movdown
jmp endofkbisr
compareLeft:
cmp al,0x4B
jne endofkbisr
call movleft
endofkbisr:
mov al,0x20
out 0x20,al
popa
iret
start:
call clrscr
call printboarders
call initializesnake
call printsnake
call printlives
call printtime
call printscore
;call generaterandom
mov ax,0xb800
mov es,ax
mov ah,0x04
mov al,'@'
mov [es:2060],ax
mov word[cs:orientation],1
xor ax, ax
mov es, ax ; point es to IVT base
cli ; disable interrupts
mov word [es:9*4], kbisr; store offset at n*4
mov [es:9*4+2], cs ; store segment at n*4+2
sti ; enable interrupts
xor ax, ax
mov es, ax ; point es to IVT base
cli ; disable interrupts
mov word [es:8*4], timer; store offset at n*4
mov [es:8*4+2], cs ; store segment at n*4+2
sti ; enable interrupts
exit:
mov ax, 0x4c00 ; terminate and stay resident
int 0x21