;
; Tiny,tiny snake game by Ghoul/Xenon
; Sample programs which comes with Alab v1.2.
; Edited in Alab v1.2 [:)]
; Do what you want with it.
;
code Segment para public 'code'
assume cs:code,ds:code,es:code
locals ; remove is you want to assemble
jumps ; with Masm
.386
org 100h
REALTIMING equ 0 ; 1=same delay on all computers
; 0=simple delay loop (varies with MHz)
; 1 = 14 bytes longer program
bptr equ Byte Ptr
wptr equ Word Ptr
dptr equ Dword Ptr
UP equ 72
DOWN equ 80
LEFT equ 75
RIGHT equ 77
INITSNAKELEN equ 10 ; length of snake at initialization
FOODINCREMENT equ 50 ; how many pixels to increment body
start: ; entry point
;1 push 0a000h ; this is 1 byte shorter than
;2 pop gs ; mov ax, 0a000h - mov gs, ax
mov eax, 0a000h ; i have to clear 16 MSB in EAX
mov gs, ax ; i just use this instead of [1,2,3]
push 40h ; points to bios data area
pop fs ; for random number at 40:6ch
;3 xor eax, eax ;
IF REALTIMING
mov al, 36h
out 43h, al
mov ax, 20000 ; try lower values for faster moving
out 40h, al
mov al, ah
out 40h, al
ENDIF
; -- menu --
mov dx, offset [menustr]
menuloop:
mov ax, 3
int 10h ; 80x25 textmode
mov ah, 9
int 21h ; show menu
mov ah, 0
int 16h ; wait for keypress
cmp al, 'Q'
je @exit
;
mov ax, 13h ; 320x200x256
int 10h
mov bx, 1 ; snake current length
mov cx, INITSNAKELEN
mov bp, 60000 ; points to head of snake
mov bptr gs:[80*320+160], 14; first yellow point (food to eat)
playloop:
; -- draw snake --
mov dx, bx ; dx = snake length
mov si, bp ; si points to head of snake
mov di, [si] ; load snake head position
cmp bptr gs:[di], 14 ; compare with food byte
ja @snakecrashed ; above = a white point = crash
jnz drawbody ; if not food, don't increment length
add cx, FOODINCREMENT ; increment snake length
mov di, wptr fs:[6ch] ; get random number
shl di, 8 ; di = (byte at 40:6ch) * 256
mov bptr gs:[di], 14 ; store new food point
drawbody:
lodsw ; load body pixel offset
mov bptr gs:[eax], 15 ; show snake body point (eax msw=0!)
dec dx ; decrement snake length
jnz drawbody
mov bptr gs:[eax], 0 ; clear snake tale
; -- check for keypress --
mov ah, 1
int 16h
jz movesnake
mov ah, 0
int 16h ; get key
cmp al, 'Q'
je endsnake ; 'Q' pressed -> exit to menu
mov [dir], ah ; store new direction
; -- move snake --
movesnake:
mov dl, [dir] ; dh is always 0 at this point!
mov ax, [bp] ; load snake head offset
dec bp ; move body -
dec bp ; 1 byte shorter than 'sub bp, 2'
cmp dl, UP ; shorter than 'cmp [dir], UP'
jne @checkdown2
sub ax, 321 ; move head 1 line up
; jmp @moveheadend
@checkdown2:
cmp dl, DOWN
jne @checkleft2
add ax, 319 ; move head 1 line down
; jmp @moveheadend
@checkleft2: ; we have either LEFT or RIGHT dir
cmp dl, LEFT
jne @itisright
dec ax
dec ax
@itisright:
inc ax
; add ax, dx ; if dir = LEFT = 75 it is 75-76 = -1
; sub ax, 76 ; if dir =RIGHT = 77 it is 77-76 = +1
@moveheadend:
mov [bp], ax ; store new head offset
cmp bx, cx ; cmp current length with full length
adc bx, 0 ; bx<cx -> increment bx
; cmp bx, cx ; cmp current length with full length
; jz @lenequal
; inc bx ; continue increment snake length
;@lenequal:
; -- move end --
; -- a little delay --
IF REALTIMING
hlt ; correct delay
ELSE
mov edx, 140000 ; simple delay
@@nops:
dec edx
jnz @@nops
ENDIF
jmp playloop
@snakecrashed:
mov dx, offset [crashedstr] - offset [menustr]
endsnake:
add dx, offset [menustr] ; because dx is always 0 here
jmp menuloop
@exit:
IF REALTIMING ; reset PIT
mov al, 36h
out 43h, al
mov al, 0
out 40h, al
out 40h, al
ENDIF
ret ; exit program
; -- DATA --
crashedstr db 'Dead!',10
menustr db 'P:Play Q:End$'
dir db RIGHT ; direction, init to RIGHT
code Ends
End start