oldos/programs/snake.asm

274 lines
8.9 KiB
NASM
Raw Permalink Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; ;;;;;; ;;;;;; ;;
;; ;; ;; ;; ;;
;; ;; ;; ;;;;;; ;;; ;; ;; ;; ;; ;;; ;; ;; ;;;;;; ;;
;; ;;;;;; ;; ;; ;; ;; ;;;;;;; ;;; ;; ;; ;; ;; ;; ;; ;;
;; ;; ;; ;;;;; ;; ;; ;; ;; ;; ; ;; ;; ;; ;;;; ;;;;;; ;;
;; ;; ;; ;; ;;;;;;; ;; ;; ;; ;;; ;;;;;;; ;; ;; ;; ;;
;; ;; ;; ;;;;;; ;; ;; ;;;;;; ;;;;;; ;; ;; ;; ;; ;; ;; ;;;;;; ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Snake like game writen in x86 real mode assembly. ;;
;; Copyright (C) 2014 Piotr Majkrzak <petrol.91@gmail.com> ;;
;; ;;
;; This program is free software: you can redistribute it and/or modify ;;
;; it under the terms of the GNU General Public License as published by ;;
;; the Free Software Foundation, either version 3 of the License, or ;;
;; (at your option) any later version. ;;
;; ;;
;; This program is distributed in the hope that it will be useful, ;;
;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;
;; GNU General Public License for more details. ;;
;; ;;
;; You should have received a copy of the GNU General Public License ;;
;; along with this program. If not, see <http://www.gnu.org/licenses/>. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; ;;
;; About ;;
;;------- ;;
;; ;;
;; This game is written in Intel's x86 real mode assembly. It is designed ;;
;; to fit in the boot sector, so it must have at most 510 bytes. Therefore, ;;
;; it has very limited functionalities and spaghetti code. You are able to ;;
;; change snake's head direction, eat fruits and restart the game. ;;
;; ;;
;; ;;
;; Assembly ;;
;;---------- ;;
;; ;;
;; To build this code you need to have NASM installed, you can get it from ;;
;; this website: (http://www.nasm.us/). ;;
;; Execute following command: ;;
;; ;;
;; nasm -fbin snake.asm -o snake.bin ;;
;; ;;
;; ;;
;; Launch ;;
;;-------- ;;
;; ;;
;; Now you have `snake.bin` file, which can be installed or loaded into ;;
;; virtual machine like QEMU, which you can get from (www.qemu.org/). ;;
;; ;;
;; qemu-system-i386 snake.bin ;;
;; ;;
;; ;;
;; Gameplay ;;
;;---------- ;;
;; ;;
;; When the game will be launched, you will see huge green rectangle in the ;;
;; middle of the screen. Snake is hidden now in top left corner. To move it ;;
;; you should set its head direction, using arrow keys. If you are stuck or ;;
;; you just want to restart the game, you should press space bar. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[org 0x1000]
%DEFINE EMPTY 0b0000_0000
%DEFINE SNAKE 0b0000_0001
%DEFINE FRUIT 0b0000_0010
%DEFINE EATEN 0b0000_0100
%DEFINE WRECK 0b0000_1000
%DEFINE DIRUP 0b0001_0000
%DEFINE DIRDO 0b0010_0000
%DEFINE DIRLE 0b0100_0000
%DEFINE DIRRI 0b1000_0000
%define map(i) byte [es:i]
%define head word [es:1024]
%define tail word [es:1026]
%define fpos word [es:1028]
%define ftim word [es:1030]
%define rand word [es:1032]
db 0x7A
init:
.random:
mov ah, 0
int 0x1A
mov rand, dx
.display:
mov ah, 0x00
mov al, 0x13
int 0x10
.interrupt:
mov [fs:0x08*4], word timer
mov [fs:0x08*4+2], ds
mov [fs:0x09*4], word keyboard
mov [fs:0x09*4+2], ds
main:
hlt
jmp main
;; () -> (ax); ax,cx,dx
random:
mov ax, rand
mov dx, 7993
mov cx, 9781
mul dx
add ax, cx
mov rand, ax
ret
;; (si) -> (di,ah:al) ; cx,dx
movement:
mov cl, map(si)
mov ax, si
mov dl, 32
div dl
test cl, DIRUP
jz $+4
dec al
test cl, DIRDO
jz $+4
inc al
test cl, DIRLE
jz $+4
dec ah
test cl, DIRRI
jz $+4
inc ah
and al, 31
and ah, 31
movzx di, al
rol di, 5
movzx cx, ah
add di,cx
ret
keyboard:
in al, 0x60
mov bx, head
mov ah, map(bx)
cmp al, 0x39
jne $+12
mov cx, 1032
mov al, 0
mov di, 0
rep stosb
and ah, 0x0F
cmp al, 0x48
jne $+5
or ah, DIRUP
cmp al, 0x50
jne $+5
or ah, DIRDO
cmp al, 0x4b
jne $+5
or ah, DIRLE
cmp al, 0x4d
jne $+5
or ah, DIRRI
test ah, 0xF0
jz $+4
mov map(bx), ah
mov al, 0x61
out 0x20, al
iret
timer:
.tick_rtc:
int 0x70
.move_head:
mov si, head
call movement
mov ah, map(di)
mov al, map(si)
test al, WRECK
jz $+3
iret
test ah, SNAKE|EATEN
jz $+7
mov map(si), WRECK
iret
test ah, FRUIT
jz $+20
mov ftim, 0
mov fpos, -1
mov bl, EATEN
jmp $+4
mov bl, SNAKE
and al, 0xF0
or bl, al
mov map(di), bl
mov head, di
.move_tail:
mov si, tail
call movement
mov al, map(si)
test al, SNAKE
jz $+11
mov map(si), EMPTY
mov tail, di
jnz $+9
and al, 0xF0
or al, SNAKE
mov map(si), al
.move_fruit:
cmp ftim, 0
jne $+42
mov bx, fpos
mov map(bx), EMPTY
call random
mov bx, ax
and bx, 1023
cmp map(bx), EMPTY
jne $-13
mov map(bx), FRUIT
mov fpos, bx
mov ftim, 64
dec ftim
.redraw:
mov cx, 0
mov ax, cx
mov dl, 32
div dl
mov bx, ax
movzx ax, bl
add ax, 9
mov dx, 320
mul dx
movzx dx, bh
add ax, dx
add ax, 24
mov dx, 4
mul dx
mov di, cx
mov dl, map(di)
and dl, 0x0F
cmp dl, EMPTY
jne $+8
mov ebx, 0x02020202
cmp dl, SNAKE
jne $+8
mov ebx, 0x01010101
cmp dl, FRUIT
jne $+8
mov ebx, 0x04040404
cmp dl, EATEN
jne $+8
mov ebx, 0x05050505
mov di, ax
mov [gs:di],ebx
add di, 320
mov [gs:di],ebx
add di, 320
mov [gs:di],ebx
add di, 320
mov [gs:di],ebx
inc cx
cmp cx, 1024
jne .redraw+3
iret
times 510-($-$$) db 0
dw 0AA55h