commit 63445aa008d5c68aecd6348b5d199f7a37cd1572 Author: Simon Holmberg Date: Sun Nov 30 15:11:02 2014 +0100 OK LETS GIT HOLY SHIT diff --git a/.session.vim b/.session.vim new file mode 100644 index 0000000..0a41f15 --- /dev/null +++ b/.session.vim @@ -0,0 +1,79 @@ +let SessionLoad = 1 +if &cp | set nocp | endif +let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 +let v:this_session=expand(":p") +silent only +cd ~/Skolarbete/Prestandaoptimering/Projekt\ 1\ -\ Nibbles +if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' + let s:wipebuf = bufnr('%') +endif +set shortmess=aoO +badd +1 cnibbles.c +badd +1 nibbles.S +argglobal +silent! argdel * +edit nibbles.S +set splitbelow splitright +wincmd _ | wincmd | +vsplit +1wincmd h +wincmd w +set nosplitbelow +set nosplitright +wincmd t +set winheight=1 winwidth=1 +exe 'vert 1resize ' . ((&columns * 137 + 137) / 274) +exe '2resize ' . ((&lines * 60 + 31) / 62) +exe 'vert 2resize ' . ((&columns * 136 + 137) / 274) +argglobal +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let s:l = 23 - ((22 * winheight(0) + 30) / 61) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +23 +normal! 042| +wincmd w +argglobal +edit cnibbles.c +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let s:l = 141 - ((41 * winheight(0) + 30) / 60) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +141 +normal! 041| +wincmd w +exe 'vert 1resize ' . ((&columns * 137 + 137) / 274) +exe '2resize ' . ((&lines * 60 + 31) / 62) +exe 'vert 2resize ' . ((&columns * 136 + 137) / 274) +tabnext 1 +if exists('s:wipebuf') + silent exe 'bwipe ' . s:wipebuf +endif +unlet! s:wipebuf +set winheight=1 winwidth=20 shortmess=filnxtToO +let s:sx = expand(":p:r")."x.vim" +if file_readable(s:sx) + exe "source " . fnameescape(s:sx) +endif +let &so = s:so_save | let &siso = s:siso_save +doautoall SessionLoadPost +unlet SessionLoad +" vim: set ft=vim : diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..52dd91d --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +# Makefile for the nibbles lab. +# ---> Compile with gamke on BSD systems! <--- + +all: nibbles_asm nibbles_asm_start + +# Rule for compiling C source +.c.o: + gcc -Os -std=c11 -m32 -march=i686 -Wall -g -c $< + +# Rule for compiling assembly source +.s.o: + #as -gstabs $^ -o $@ + gcc -m32 -march=i686 -c $< + + +# C game +nibbles_c: main.o cnibbles.o + gcc -lcurses $^ -o $@ + +# ASM game +nibbles_asm: main.o nibbles.o helpers.o + gcc -m32 -lcurses $^ -o $@ + +# ASM game +nibbles_asm_start: start.o nibbles.o helpers.o + gcc -m32 -lcurses -lc -nostdlib $^ -o $@ + +clean: + rm -f *~ + rm -f *.o + rm -f nibbles_c nibbles_asm nibbles_asm_start diff --git a/cnibbles.S b/cnibbles.S new file mode 100644 index 0000000..dcdb059 --- /dev/null +++ b/cnibbles.S @@ -0,0 +1,744 @@ + .file "cnibbles.c" + .local p_screen + .comm p_screen,8,8 + .text + .globl nib_poll_kbd + .type nib_poll_kbd, @function +nib_poll_kbd: +.LFB0: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + subq $16, %rsp + movq stdscr@GOTPCREL(%rip), %rax + movq (%rax), %rax + movq %rax, %rdi + call wgetch@PLT + movl %eax, -4(%rbp) + movl -4(%rbp), %eax + leave + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE0: + .size nib_poll_kbd, .-nib_poll_kbd + .section .rodata +.LC0: + .string "%c" + .text + .globl nib_put_scr + .type nib_put_scr, @function +nib_put_scr: +.LFB1: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + subq $16, %rsp + movl %edi, -4(%rbp) + movl %esi, -8(%rbp) + movl %edx, -12(%rbp) + movl -12(%rbp), %edx + movl -4(%rbp), %esi + movl -8(%rbp), %eax + movl %edx, %ecx + leaq .LC0(%rip), %rdx + movl %eax, %edi + movl $0, %eax + call mvprintw@PLT + movq p_screen(%rip), %rax + movq %rax, %rdi + call wrefresh@PLT + leave + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE1: + .size nib_put_scr, .-nib_put_scr + .globl nib_init + .type nib_init, @function +nib_init: +.LFB2: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movl $0, %edi + call time@PLT + movl %eax, %edi + call srand@PLT + call initscr@PLT + movq %rax, p_screen(%rip) + call start_color@PLT + movl $0, %edi + call curs_set@PLT + call noecho@PLT + movq p_screen(%rip), %rax + movl $1, %esi + movq %rax, %rdi + call keypad@PLT + movq p_screen(%rip), %rax + movl $1, %esi + movq %rax, %rdi + call nodelay@PLT + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE2: + .size nib_init, .-nib_init + .globl nib_end + .type nib_end, @function +nib_end: +.LFB3: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + call endwin@PLT + movl $0, %edi + call exit@PLT + .cfi_endproc +.LFE3: + .size nib_end, .-nib_end + .globl startLength + .bss + .align 4 + .type startLength, @object + .size startLength, 4 +startLength: + .zero 4 + .globl startApples + .align 4 + .type startApples, @object + .size startApples, 4 +startApples: + .zero 4 + .comm currentTick,4,4 + .comm snake,9600,64 + .comm snakeLength,4,4 + .comm snakeX,4,4 + .comm snakeY,4,4 + .comm snakeDirX,4,4 + .comm snakeDirY,4,4 + .comm numApples,4,4 + .text + .globl start_game + .type start_game, @function +start_game: +.LFB4: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + subq $48, %rsp + movl %edi, -36(%rbp) + movl %esi, -40(%rbp) + movl startLength(%rip), %eax + testl %eax, %eax + jne .L7 + movl -36(%rbp), %eax + movl %eax, startLength(%rip) +.L7: + movl startApples(%rip), %eax + testl %eax, %eax + jne .L8 + movl -40(%rbp), %eax + movl %eax, startApples(%rip) +.L8: + movq currentTick@GOTPCREL(%rip), %rax + movl $0, (%rax) + movl -36(%rbp), %edx + movq snakeLength@GOTPCREL(%rip), %rax + movl %edx, (%rax) + movl -40(%rbp), %edx + movq numApples@GOTPCREL(%rip), %rax + movl %edx, (%rax) + call nib_init + movl $0, -20(%rbp) + jmp .L9 +.L10: + movq snakeLength@GOTPCREL(%rip), %rax + movl (%rax), %eax + movl %eax, %ecx + movq snake@GOTPCREL(%rip), %rax + movl -20(%rbp), %edx + movl %ecx, (%rax,%rdx,4) + addl $1, -20(%rbp) +.L9: + cmpl $2399, -20(%rbp) + jbe .L10 + movq snakeX@GOTPCREL(%rip), %rax + movl $30, (%rax) + movq snakeY@GOTPCREL(%rip), %rax + movl $20, (%rax) + movq snakeDirX@GOTPCREL(%rip), %rax + movl $0, (%rax) + movq snakeDirY@GOTPCREL(%rip), %rax + movl $-1, (%rax) + movl $0, -16(%rbp) + jmp .L11 +.L12: + movq snakeX@GOTPCREL(%rip), %rax + movl (%rax), %ecx + movl $-2004318071, %edx + movl %ecx, %eax + mull %edx + movl %edx, %eax + shrl $5, %eax + movl %eax, -8(%rbp) + movl -8(%rbp), %eax + movl %eax, %edx + leal 0(,%rdx,4), %eax + movl %eax, %edx + movl %edx, %eax + sall $4, %eax + subl %edx, %eax + subl %eax, %ecx + movl %ecx, %eax + movl %eax, -8(%rbp) + movq snakeY@GOTPCREL(%rip), %rax + movl (%rax), %edx + movl -16(%rbp), %eax + leal (%rdx,%rax), %ecx + movl $-858993459, %edx + movl %ecx, %eax + mull %edx + movl %edx, %eax + shrl $5, %eax + movl %eax, -4(%rbp) + movl -4(%rbp), %edx + movl %edx, %eax + sall $2, %eax + addl %edx, %eax + sall $3, %eax + subl %eax, %ecx + movl %ecx, %eax + movl %eax, -4(%rbp) + movl -4(%rbp), %eax + sall $2, %eax + movl %eax, %edx + sall $4, %edx + subl %eax, %edx + movl -8(%rbp), %eax + leal (%rdx,%rax), %ecx + movl -16(%rbp), %edx + movq snake@GOTPCREL(%rip), %rax + movl %ecx, %ecx + movl %edx, (%rax,%rcx,4) + addl $1, -16(%rbp) +.L11: + movq snakeLength@GOTPCREL(%rip), %rax + movl (%rax), %eax + cmpl %eax, -16(%rbp) + jb .L12 + movl $0, %edi + call time@PLT + movl %eax, %edi + call srand@PLT + movl $0, -12(%rbp) + jmp .L13 +.L14: + movl $0, %eax + call spawnApple + addl $1, -12(%rbp) +.L13: + movq numApples@GOTPCREL(%rip), %rax + movl (%rax), %eax + cmpl %eax, -12(%rbp) + jb .L14 +.L15: + movl $0, %eax + call tick + movl $0, %eax + call draw + jmp .L15 + .cfi_endproc +.LFE4: + .size start_game, .-start_game + .globl spawnApple + .type spawnApple, @function +spawnApple: +.LFB5: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + subq $16, %rsp + call rand@PLT + movl %eax, %ecx + movl $-2004318071, %edx + movl %ecx, %eax + imull %edx + leal (%rdx,%rcx), %eax + sarl $5, %eax + movl %eax, %edx + movl %ecx, %eax + sarl $31, %eax + subl %eax, %edx + movl %edx, %eax + movl %eax, %edx + leal 0(,%rdx,4), %eax + movl %eax, %edx + movl %edx, %eax + sall $4, %eax + subl %edx, %eax + subl %eax, %ecx + movl %ecx, %eax + movl %eax, -8(%rbp) + call rand@PLT + movl %eax, %ecx + movl $1717986919, %edx + movl %ecx, %eax + imull %edx + sarl $4, %edx + movl %ecx, %eax + sarl $31, %eax + subl %eax, %edx + movl %edx, %eax + sall $2, %eax + addl %edx, %eax + sall $3, %eax + subl %eax, %ecx + movl %ecx, %edx + movl %edx, -4(%rbp) + jmp .L17 +.L18: + call rand@PLT + movl %eax, %ecx + movl $-2004318071, %edx + movl %ecx, %eax + imull %edx + leal (%rdx,%rcx), %eax + sarl $5, %eax + movl %eax, %edx + movl %ecx, %eax + sarl $31, %eax + subl %eax, %edx + movl %edx, %eax + movl %eax, %edx + leal 0(,%rdx,4), %eax + movl %eax, %edx + movl %edx, %eax + sall $4, %eax + subl %edx, %eax + subl %eax, %ecx + movl %ecx, %eax + movl %eax, -8(%rbp) + call rand@PLT + movl %eax, %ecx + movl $1717986919, %edx + movl %ecx, %eax + imull %edx + sarl $4, %edx + movl %ecx, %eax + sarl $31, %eax + subl %eax, %edx + movl %edx, %eax + sall $2, %eax + addl %edx, %eax + sall $3, %eax + subl %eax, %ecx + movl %ecx, %edx + movl %edx, -4(%rbp) +.L17: + movl -4(%rbp), %eax + sall $2, %eax + movl %eax, %edx + sall $4, %edx + subl %eax, %edx + movl -8(%rbp), %eax + addl %eax, %edx + movq snake@GOTPCREL(%rip), %rax + movl %edx, %edx + movl (%rax,%rdx,4), %eax + movl %eax, %edx + movq snakeLength@GOTPCREL(%rip), %rax + movl (%rax), %eax + cmpl %eax, %edx + jb .L18 + movl -4(%rbp), %eax + sall $2, %eax + movl %eax, %edx + sall $4, %edx + subl %eax, %edx + movl -8(%rbp), %eax + addl %eax, %edx + movq snake@GOTPCREL(%rip), %rax + movl %edx, %edx + movl $-1, (%rax,%rdx,4) + leave + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE5: + .size spawnApple, .-spawnApple + .globl tick + .type tick, @function +tick: +.LFB6: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + subq $16, %rsp + movq currentTick@GOTPCREL(%rip), %rax + movl (%rax), %eax + leal 1(%rax), %edx + movq currentTick@GOTPCREL(%rip), %rax + movl %edx, (%rax) + movl $0, -16(%rbp) + jmp .L20 +.L22: + movq snake@GOTPCREL(%rip), %rax + movl -16(%rbp), %edx + movl (%rax,%rdx,4), %eax + movl %eax, -12(%rbp) + cmpl $0, -12(%rbp) + js .L21 + cmpl $0, -12(%rbp) + js .L21 + movl -12(%rbp), %edx + movq snakeLength@GOTPCREL(%rip), %rax + movl (%rax), %eax + cmpl %eax, %edx + ja .L21 + movq snake@GOTPCREL(%rip), %rax + movl -16(%rbp), %edx + movl (%rax,%rdx,4), %eax + leal 1(%rax), %ecx + movq snake@GOTPCREL(%rip), %rax + movl -16(%rbp), %edx + movl %ecx, (%rax,%rdx,4) +.L21: + addl $1, -16(%rbp) +.L20: + cmpl $2399, -16(%rbp) + jbe .L22 + call nib_poll_kbd + movl %eax, -8(%rbp) + cmpl $119, -8(%rbp) + jne .L23 + movq snakeDirY@GOTPCREL(%rip), %rax + movl (%rax), %eax + cmpl $1, %eax + je .L23 + movq snakeDirX@GOTPCREL(%rip), %rax + movl $0, (%rax) + movq snakeDirY@GOTPCREL(%rip), %rax + movl $-1, (%rax) +.L23: + cmpl $115, -8(%rbp) + jne .L24 + movq snakeDirY@GOTPCREL(%rip), %rax + movl (%rax), %eax + cmpl $-1, %eax + je .L24 + movq snakeDirX@GOTPCREL(%rip), %rax + movl $0, (%rax) + movq snakeDirY@GOTPCREL(%rip), %rax + movl $1, (%rax) +.L24: + cmpl $97, -8(%rbp) + jne .L25 + movq snakeDirX@GOTPCREL(%rip), %rax + movl (%rax), %eax + cmpl $1, %eax + je .L25 + movq snakeDirX@GOTPCREL(%rip), %rax + movl $-1, (%rax) + movq snakeDirY@GOTPCREL(%rip), %rax + movl $0, (%rax) +.L25: + cmpl $100, -8(%rbp) + jne .L26 + movq snakeDirX@GOTPCREL(%rip), %rax + movl (%rax), %eax + cmpl $-1, %eax + je .L26 + movq snakeDirX@GOTPCREL(%rip), %rax + movl $1, (%rax) + movq snakeDirY@GOTPCREL(%rip), %rax + movl $0, (%rax) +.L26: + movq snakeX@GOTPCREL(%rip), %rax + movl (%rax), %edx + movq snakeDirX@GOTPCREL(%rip), %rax + movl (%rax), %eax + addl %edx, %eax + leal 60(%rax), %ecx + movl $-2004318071, %edx + movl %ecx, %eax + mull %edx + movl %edx, %eax + shrl $5, %eax + movl %eax, %edx + leal 0(,%rdx,4), %eax + movl %eax, %edx + movl %edx, %eax + sall $4, %eax + subl %edx, %eax + subl %eax, %ecx + movl %ecx, %eax + movq snakeX@GOTPCREL(%rip), %rdx + movl %eax, (%rdx) + movq snakeY@GOTPCREL(%rip), %rax + movl (%rax), %edx + movq snakeDirY@GOTPCREL(%rip), %rax + movl (%rax), %eax + addl %edx, %eax + leal 40(%rax), %ecx + movl $-858993459, %edx + movl %ecx, %eax + mull %edx + shrl $5, %edx + movl %edx, %eax + sall $2, %eax + addl %edx, %eax + sall $3, %eax + subl %eax, %ecx + movl %ecx, %edx + movq snakeY@GOTPCREL(%rip), %rax + movl %edx, (%rax) + movq snakeY@GOTPCREL(%rip), %rax + movl (%rax), %eax + sall $2, %eax + movl %eax, %edx + sall $4, %edx + subl %eax, %edx + movq snakeX@GOTPCREL(%rip), %rax + movl (%rax), %eax + addl %eax, %edx + movq snake@GOTPCREL(%rip), %rax + movl %edx, %edx + movl (%rax,%rdx,4), %eax + movl %eax, -4(%rbp) + movl -4(%rbp), %edx + movq snakeLength@GOTPCREL(%rip), %rax + movl (%rax), %eax + cmpl %eax, %edx + jae .L27 + cmpl $0, -4(%rbp) + js .L27 + movl startApples(%rip), %eax + movl %eax, %edx + movl startLength(%rip), %eax + movl %edx, %esi + movl %eax, %edi + call start_game +.L27: + cmpl $0, -4(%rbp) + jns .L28 + movl $0, %eax + call spawnApple + movq snakeLength@GOTPCREL(%rip), %rax + movl (%rax), %eax + leal 1(%rax), %edx + movq snakeLength@GOTPCREL(%rip), %rax + movl %edx, (%rax) +.L28: + movq snakeY@GOTPCREL(%rip), %rax + movl (%rax), %eax + sall $2, %eax + movl %eax, %edx + sall $4, %edx + subl %eax, %edx + movq snakeX@GOTPCREL(%rip), %rax + movl (%rax), %eax + addl %eax, %edx + movq snake@GOTPCREL(%rip), %rax + movl %edx, %edx + movl $0, (%rax,%rdx,4) + leave + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE6: + .size tick, .-tick + .globl draw + .type draw, @function +draw: +.LFB7: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + subq $64, %rsp + movq %fs:40, %rax + movq %rax, -8(%rbp) + xorl %eax, %eax + movabsq $23438616898455886, %rax + movq %rax, -16(%rbp) + movl $-1, -52(%rbp) + jmp .L30 +.L43: + movl $-1, -48(%rbp) + jmp .L31 +.L42: + cmpl $-1, -48(%rbp) + je .L32 + cmpl $-1, -52(%rbp) + je .L32 + cmpl $60, -48(%rbp) + je .L32 + cmpl $40, -52(%rbp) + jne .L33 +.L32: + cmpl $-1, -48(%rbp) + je .L34 + cmpl $-1, -52(%rbp) + jne .L35 +.L34: + movl -48(%rbp), %eax + addl $1, %eax + movl %eax, -24(%rbp) + movl -52(%rbp), %eax + addl $1, %eax + movl %eax, -20(%rbp) + movl -20(%rbp), %ecx + movl -24(%rbp), %eax + movl $35, %edx + movl %ecx, %esi + movl %eax, %edi + call nib_put_scr + nop + jmp .L37 +.L35: + movl -48(%rbp), %eax + addl $1, %eax + movl %eax, -32(%rbp) + movl -52(%rbp), %eax + addl $1, %eax + movl %eax, -28(%rbp) + movl -28(%rbp), %ecx + movl -32(%rbp), %eax + movl $35, %edx + movl %ecx, %esi + movl %eax, %edi + call nib_put_scr + jmp .L37 +.L33: + movl -52(%rbp), %eax + sall $2, %eax + movl %eax, %edx + sall $4, %edx + subl %eax, %edx + movl -48(%rbp), %eax + addl %eax, %edx + movq snake@GOTPCREL(%rip), %rax + movslq %edx, %rdx + movl (%rax,%rdx,4), %eax + movl %eax, -44(%rbp) + movl -48(%rbp), %eax + addl $1, %eax + movl %eax, -40(%rbp) + movl -52(%rbp), %eax + addl $1, %eax + movl %eax, -36(%rbp) + cmpl $0, -44(%rbp) + js .L38 + movl -44(%rbp), %edx + movq snakeLength@GOTPCREL(%rip), %rax + movl (%rax), %eax + cmpl %eax, %edx + jae .L38 + movl -48(%rbp), %edx + movq snakeX@GOTPCREL(%rip), %rax + movl (%rax), %eax + cmpl %eax, %edx + jne .L39 + movl -52(%rbp), %edx + movq snakeY@GOTPCREL(%rip), %rax + movl (%rax), %eax + cmpl %eax, %edx + jne .L39 + movl -36(%rbp), %ecx + movl -40(%rbp), %eax + movl $64, %edx + movl %ecx, %esi + movl %eax, %edi + call nib_put_scr + jmp .L37 +.L39: + movl -44(%rbp), %eax + leal -1(%rax), %ecx + movl $-1840700269, %edx + movl %ecx, %eax + imull %edx + leal (%rdx,%rcx), %eax + sarl $2, %eax + movl %eax, %edx + movl %ecx, %eax + sarl $31, %eax + subl %eax, %edx + movl %edx, %eax + movl %eax, %edx + sall $3, %edx + subl %eax, %edx + movl %ecx, %eax + subl %edx, %eax + cltq + movzbl -16(%rbp,%rax), %eax + movsbl %al, %edx + movl -36(%rbp), %ecx + movl -40(%rbp), %eax + movl %ecx, %esi + movl %eax, %edi + call nib_put_scr + jmp .L37 +.L38: + cmpl $0, -44(%rbp) + jns .L41 + movl -36(%rbp), %ecx + movl -40(%rbp), %eax + movl $111, %edx + movl %ecx, %esi + movl %eax, %edi + call nib_put_scr + jmp .L37 +.L41: + movl -36(%rbp), %ecx + movl -40(%rbp), %eax + movl $32, %edx + movl %ecx, %esi + movl %eax, %edi + call nib_put_scr +.L37: + addl $1, -48(%rbp) +.L31: + cmpl $60, -48(%rbp) + jle .L42 + addl $1, -52(%rbp) +.L30: + cmpl $40, -52(%rbp) + jle .L43 + movq -8(%rbp), %rax + xorq %fs:40, %rax + je .L44 + call __stack_chk_fail@PLT +.L44: + leave + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE7: + .size draw, .-draw + .ident "GCC: (GNU) 4.9.2" + .section .note.GNU-stack,"",@progbits diff --git a/cnibbles.c b/cnibbles.c new file mode 100644 index 0000000..d336e46 --- /dev/null +++ b/cnibbles.c @@ -0,0 +1,178 @@ +#include +#include +#include "helpers.c" + +#define WIDTH 60 +#define HEIGHT 40 +#define DEBUG false + +unsigned int startLength = 0; +unsigned int startApples = 0; + +unsigned int currentTick; +int snake[WIDTH*HEIGHT]; +unsigned int snakeLength; +unsigned int snakeX; +unsigned int snakeY; +int snakeDirX; +int snakeDirY; +unsigned int numApples; + +void spawnApple(); +void tick(); +void draw(); + +void start_game(int len, int n_apples) +{ + if (startLength == 0) + startLength = len; + if (startApples == 0) + startApples = n_apples; + + // Initialize variables + currentTick = 0; + snakeLength = len; + numApples = n_apples; + + nib_init(); + + //printf("Started with worm length %i and %i apples!\n", snakeLength, numApples); + + // Initialize the snake array + // Set every cell to a time value greater than the snake length + for (unsigned int i = 0; i < WIDTH*HEIGHT; ++i) { + snake[i] = snakeLength; + } + + // Place the snake head in the middle + snakeX = WIDTH / 2; + snakeY = HEIGHT / 2; + snakeDirX = 0; + snakeDirY = -1; + + // Place the initial snake segments, downwards or something + for (unsigned int i = 0; i < snakeLength; ++i) { + unsigned int x = snakeX % WIDTH; + unsigned int y = (snakeY + i) % HEIGHT; + snake[x + y*WIDTH] = i; + } + + // Place apples + srand(time(0)); + for (unsigned int i = 0; i < numApples; ++i) { + spawnApple(); + } + + while (true) { + tick(); + draw(); + } +} + +void spawnApple() +{ + unsigned int x = rand() % WIDTH; + unsigned int y = rand() % HEIGHT; + while (snake[x + y*WIDTH] < snakeLength) { + x = rand() % WIDTH; + y = rand() % HEIGHT; + } + //printf("Placing apple at (%i,%i)\n", x, y); + snake[x + y*WIDTH] = -1; +} + +void tick() +{ + currentTick++; + // Increment cell times + for (unsigned int i = 0; i < WIDTH*HEIGHT; ++i) { + int val = snake[i]; + + if (val < 0) { + // Apple lifetime + //snake[i]--; + } else if (val >= 0 && val <= snakeLength) { + // Other cells + snake[i]++; + } + } + + int key = nib_poll_kbd(); + if (key == 'w' && snakeDirY != 1) { + snakeDirX = 0; + snakeDirY = -1; + } + if (key == 's' && snakeDirY != -1) { + snakeDirX = 0; + snakeDirY = 1; + } + if (key == 'a' && snakeDirX != 1) { + snakeDirX = -1; + snakeDirY = 0; + } + if (key == 'd' && snakeDirX != -1) { + snakeDirX = 1; + snakeDirY = 0; + } + + // Move snake + snakeX = (snakeX + snakeDirX + WIDTH) % WIDTH; + snakeY = (snakeY + snakeDirY + HEIGHT) % HEIGHT; + // On collision with self + int val = snake[snakeX + snakeY*WIDTH]; + if (val < snakeLength && val >= 0) { + //nib_end(); + start_game(startLength, startApples); + } + // ON collision with apple + if (val < 0) { + // Spawn a new apple somewhere + spawnApple(); + // Increase our length! + snakeLength++; + } + snake[snakeX + snakeY*WIDTH] = 0; +} + +void draw() +{ + char body[] = "NIBBLES"; + + for (int y = -1; y <= HEIGHT; ++y) { + for (int x = -1; x <= WIDTH; ++x) { + + if (x == -1 || y == -1 || x == WIDTH || y == HEIGHT) { + if (x == -1 || y == -1) { + unsigned int screenX = x + 1; + unsigned int screenY = y + 1; + nib_put_scr(screenX, screenY, '#'); + } else { + unsigned int screenX = x + 1; + unsigned int screenY = y + 1; + nib_put_scr(screenX, screenY, '#'); + } + } else { + int snakeVal = snake[x + y*WIDTH]; + unsigned int screenX = x + 1; + unsigned int screenY = y + 1; + + if (DEBUG) { + nib_put_scr(screenX, screenY, '0' + snakeVal); + continue; + } + + if (snakeVal >= 0 && snakeVal < snakeLength) { + if (x == snakeX && y == snakeY) { + nib_put_scr(screenX, screenY, '@'); + } else { + nib_put_scr(screenX, screenY, body[(snakeVal - 1) % 7]); + } + } else if (snakeVal < 0) { + nib_put_scr(screenX, screenY, 'o'); + } else { + nib_put_scr(screenX, screenY, ' '); + } + } + } + } +} diff --git a/helpers.c b/helpers.c new file mode 100644 index 0000000..f050e8a --- /dev/null +++ b/helpers.c @@ -0,0 +1,48 @@ +/********************************************************************* + * + * Copyright (C) 2003, Blekinge Institute of Technology + * + * Filename: helpers.c + * Author: Simon Kagstrom + * Description: Library with helpers for the nibbles game + * + * $Id: helpers.c 4937 2005-10-06 12:50:50Z ska $ + * + ********************************************************************/ +#include +#include +#include +#include + +static WINDOW *p_screen; + +int nib_poll_kbd(void) +{ + int key = getch(); + + return key; +} + +void nib_put_scr(int x, int y, int ch) +{ + mvprintw(y, x, "%c", ch); + wrefresh(p_screen); +} + +void nib_init(void) +{ + + srand(time(0)); /* Init randomiser */ + p_screen = initscr(); /* Create the window */ + start_color(); /* We use color (well...) */ + curs_set(0); /* Make cursor invisible */ + noecho(); /* Don't output chars on screen when written */ + keypad(p_screen, TRUE); /* Give p_screen keyboard focus */ + nodelay(p_screen, TRUE); /* Make getch nonblocking */ +} + +void nib_end(void) +{ + endwin(); + exit(0); +} diff --git a/main.c b/main.c new file mode 100644 index 0000000..9a1e7b9 --- /dev/null +++ b/main.c @@ -0,0 +1,33 @@ +/********************************************************************* + * + * Copyright (C) 2003, Blekinge Institute of Technology + * + * Filename: main.c + * Author: Simon Kagstrom + * Description: main function for nibbles game. + * + * $Id: main.c 1369 2005-01-20 20:57:54Z ska $ + * + ********************************************************************/ +#include /* printf */ +#include /* atoi */ + +extern void start_game(int len, int n_apples); + +int main(int argc, char *argv[]) +{ + int len, apples; + + if (argc < 3) + { + printf("Usage: %s LEN APPLES\n", argv[0]); + return 1; + } + + len = atoi(argv[1]); + apples = atoi(argv[2]); + + start_game(len, apples); + + return 0; +} diff --git a/main.o b/main.o new file mode 100644 index 0000000..2db6472 Binary files /dev/null and b/main.o differ diff --git a/nibbles.S b/nibbles.S new file mode 100644 index 0000000..9213b40 --- /dev/null +++ b/nibbles.S @@ -0,0 +1,369 @@ +#define WIDTH 60 +#define HEIGHT 40 + +.bss +# Array of longs representing the game field +.align 4 +world: .space WIDTH*HEIGHT*4 + +.data +# Current length of the snake +snakeLength: .long 0 +# Snake position +snakePosX: .long WIDTH / 2 +snakePosY: .long HEIGHT / 2 +# Snake direction +snakeDirX: .long 1 +snakeDirY: .long 0 +# Number of apples +numApples: .long 0 +# Optional score-keeping +score: .long 0 +# Utility strings +snibbles: .ascii "NIBBLES" +sgameover: .string " Game over! Score: %i " +sgameover_end: +string1: .string "Started with snake length %i and %i apples!\n" +string2: .string "Snake position: (%i, %i)\n" +stringi: .string "%i\n" +stringtest: .string "> %i %i %c\n" + +.text +.global start_game +start_game: + # snakeLength = len + movl 4(%esp), %eax + movl %eax, snakeLength + # numApples = n_apples + movl 8(%esp), %eax + movl %eax, numApples + + pushl %ebx + pushl %edi + + # Call nib_init + call nib_init + # Seed randomness + pushl $0 + call time + addl $4, %esp + pushl %eax + call srand + addl $4, %esp + + # Print our arguments + #pushl numApples + #pushl snakeLength + #pushl $string1 + #call printf + #addl $4*3, %esp + + # Print worm position + #pushl snakePosY + #pushl snakePosX + #pushl $string2 + #call printf + #addl $4*3, %esp + + # Initialize the snake array + # Set every cell to a time value greater than the snake length + movl $world, %edi + movl snakeLength, %eax + movl $WIDTH*HEIGHT, %ebx + xorl %ecx, %ecx +1: + movl %eax, (%edi, %ecx, 4) + incl %ecx + cmpl %ebx, %ecx + jl 1b + + # Spawn initial apples + movl numApples, %ecx +1: + pushl %ecx + call spawnApple + popl %ecx + loop 1b + + # Loop forever +loop: + # Sleep for 150 ms + pushl $500*1000 + call usleep + addl $4, %esp + jmp tick + + popl %edi + popl %ebx + ret + +# Update stuff +tick: + movl $world, %edi + + # Increment cell times + movl snakeLength, %ebx + xorl %ecx, %ecx +1: + movl (%edi, %ecx, 4), %eax + # If the value is negative it's an apple we don't want to disappear + test %eax, %eax + js 2f + # No need to increment if it's already greater than snakeLength + cmpl %ebx, %eax + jg 2f + # Increment the cell value + incl %eax + movl %eax, (%edi, %ecx, 4) +2: incl %ecx # Loop increment + cmpl $WIDTH*HEIGHT, %ecx + jne 1b + + # Input + call nib_poll_kbd + # Down + movl $258, %ebx + cmpl %eax, %ebx + jne 1f + movl $0, snakeDirX + movl $1, snakeDirY +1: # Up + movl $259, %ebx + cmpl %eax, %ebx + jne 1f + movl $0, snakeDirX + movl $-1, snakeDirY +1: # Left + movl $260, %ebx + cmpl %eax, %ebx + jne 1f + movl $-1, snakeDirX + movl $0, snakeDirY +1: # Right + movl $261, %ebx + cmpl %eax, %ebx + jne 1f + movl $1, snakeDirX + movl $0, snakeDirY +1: + + # Move snake + # snakePosX = (snakePosX + snakeDirY + WIDTH) % WIDTH + movl snakePosX, %eax + movl snakeDirX, %ebx + addl %ebx, %eax + addl $WIDTH, %eax # For modulo wrap-around + xorl %edx, %edx + movl $WIDTH, %ecx + divl %ecx + mov %edx, snakePosX + # snakePosY = (snakePosY + snakeDirY + HEIGHT) % HEIGHT + movl snakePosY, %eax + movl snakeDirY, %ebx + addl %ebx, %eax + addl $HEIGHT, %eax # For modulo wrap-around + xorl %edx, %edx + movl $HEIGHT, %ecx + divl %ecx + mov %edx, snakePosY + + # Get value at head position + movl snakePosY, %eax + movl $WIDTH, %edx + mull %edx + addl snakePosX, %eax + movl (%edi, %eax, 4), %edx + + # Collision with apple if negative + test %edx, %edx + js 1f + # No need to increment if it's already greater than snakeLength + movl snakeLength, %ebx + cmpl %ebx, %edx + jg 2f + # End the game when the snake collides with itself + jmp gameOver +1: # Spawn a new apple + pushl %edi + pushl %eax + call spawnApple + popl %eax + popl %edi + # Extend the snake! + incl snakeLength +2: + + # Set time value to 0 at snake head position + # i = x + y * WIDTH + # %edi = %ebx + %ecx * $WIDTH + movl $0, (%edi, %eax, 4) + + jmp draw + #jmp debug_draw + +# Draw stuff +draw: + # Loop Y + movl $HEIGHT, %ecx +1: + # Loop X + movl $WIDTH, %ebx +2: + # Save loop registers + pushl %ecx + pushl %ebx + subl $1, %ecx + subl $1, %ebx + + # Call nib_put_scr + + # i = x + y * WIDTH + # %eax = %ebx + %ecx * $WIDTH + movl %ecx, %eax + movl $WIDTH, %edx + mull %edx + addl %ebx, %eax + # Fetch the value of the cell + movl $world, %edi + movl (%edi, %eax, 4), %eax + + # Compare with the snake length + cmpl snakeLength, %eax + # If the value is negative, it's an apple + test %eax, %eax + js 4f + # If it's greater or equal to snakeLength, it's empty + cmpl snakeLength, %eax + jge 3f + # Else, it's part of the snake + pushl $'@' + jmp 5f +3: pushl $' ' + jmp 5f +4: pushl $'o' +5: + + movl %ecx, %eax # Y + pushl %eax + + movl %ebx, %eax # X + pushl %eax + + call nib_put_scr + addl $4*3, %esp + + # Restore loop registers + popl %ebx + popl %ecx + + decl %ebx # Decrement X + jnz 2b # End of X loop + loop 1b # End of Y loop + + jmp loop + +# Debug drawing +debug_draw: + # Loop Y + movl $HEIGHT, %ecx +1: + # Loop X + movl $WIDTH, %ebx +2: + # Save loop registers + pushl %ecx + pushl %ebx + subl $1, %ecx + subl $1, %ebx + + # Call nib_put_scr + + # i = x + y * WIDTH + # %edi = %ebx + %ecx * $WIDTH + movl %ecx, %eax + movl $WIDTH, %edx + mull %edx + addl %ebx, %eax + # Fetch the value of the cell + movl $world, %edi + movl (%edi, %eax, 4), %eax + pushl %eax + + movl %ecx, %eax # Y + pushl %eax + + movl %ebx, %eax # X + pushl %eax + + call nib_put_scr + addl $4*3, %esp + + # Restore loop registers + popl %ebx + popl %ecx + + decl %ebx # Decrement X + jnz 2b # End of X loop + loop 1b # End of Y loop + + jmp loop + +gameOver: + # Calculate string length + movl $sgameover_end, %eax + subl $sgameover, %eax + subl $1, %eax # Discount null terminator + + # Calculate X-pos + movl $2, %ebx + xorl %edx, %edx + divl %ebx + negl %eax + addl $WIDTH/2, %eax + + # Print game over message + pushl snakeLength + pushl $sgameover + pushl %eax # X + pushl $HEIGHT/2 # Y + call mvprintw + add $4*3, %esp + call refresh + + pushl $3000*1000 + call usleep + addl $4, %esp + call nib_end + +spawnApple: + pushl %ebx + + # %ecx = rand() % HEIGHT + call rand + xorl %edx, %edx + movl $HEIGHT, %ebx + divl %ebx + movl %edx, %ecx + # %ebx = rand() % WIDTH + pushl %ecx + call rand + xorl %edx, %edx + movl $WIDTH, %ebx + divl %ebx + movl %edx, %ebx + popl %ecx + + # i = x + y * WIDTH + # %eax = %ebx + %ecx * $WIDTH + movl %ecx, %eax + movl $WIDTH, %edx + mull %edx + addl %ebx, %eax + + # Set the cell negative to represent an apple + movl $world, %ecx + movl $-1, %edx + movl %edx, (%ecx, %eax, 4) + + popl %ebx + ret diff --git a/start.S b/start.S new file mode 100644 index 0000000..252d351 --- /dev/null +++ b/start.S @@ -0,0 +1,12 @@ +.text +.global _start +_start: + # n_apples + pushl $10 + # len + pushl $3 + call start_game + addl $4*2, %esp + + movl $0, %eax + ret diff --git a/test.c b/test.c new file mode 100644 index 0000000..909c7e4 --- /dev/null +++ b/test.c @@ -0,0 +1,9 @@ +int main(int argc, char* argv[]) +{ + for (int x = 0; x < 10; ++x) { + for (int y = 0; y < 20; ++y) { + nib_put_scr(x, y, '@'); + } + } + return 0; +} diff --git a/test.s b/test.s new file mode 100644 index 0000000..57ffda4 --- /dev/null +++ b/test.s @@ -0,0 +1,85 @@ + .file "test.c" + .section .text.unlikely,"ax",@progbits +.LCOLDB0: + .section .text.startup,"ax",@progbits +.LHOTB0: + .p2align 4,,15 + .globl main + .type main, @function +main: +.LFB0: + .cfi_startproc + leal 4(%esp), %ecx + .cfi_def_cfa 1, 0 + andl $-16, %esp + pushl -4(%ecx) + pushl %ebp + .cfi_escape 0x10,0x5,0x2,0x75,0 + movl %esp, %ebp + pushl %edi + pushl %esi + pushl %ebx + pushl %ecx + .cfi_escape 0xf,0x3,0x75,0x70,0x6 + .cfi_escape 0x10,0x7,0x2,0x75,0x7c + .cfi_escape 0x10,0x6,0x2,0x75,0x78 + .cfi_escape 0x10,0x3,0x2,0x75,0x74 + xorl %edi, %edi + call __x86.get_pc_thunk.bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx + subl $8, %esp + .p2align 4,,10 + .p2align 3 +.L2: + xorl %esi, %esi + .p2align 4,,10 + .p2align 3 +.L3: + subl $4, %esp + pushl $64 + pushl %esi + addl $1, %esi + pushl %edi + call nib_put_scr@PLT + addl $16, %esp + cmpl $20, %esi + jne .L3 + addl $1, %edi + cmpl $10, %edi + jne .L2 + leal -16(%ebp), %esp + xorl %eax, %eax + popl %ecx + .cfi_restore 1 + .cfi_def_cfa 1, 0 + popl %ebx + .cfi_restore 3 + popl %esi + .cfi_restore 6 + popl %edi + .cfi_restore 7 + popl %ebp + .cfi_restore 5 + leal -4(%ecx), %esp + .cfi_def_cfa 4, 4 + ret + .cfi_endproc +.LFE0: + .size main, .-main + .section .text.unlikely +.LCOLDE0: + .section .text.startup +.LHOTE0: + .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat + .globl __x86.get_pc_thunk.bx + .hidden __x86.get_pc_thunk.bx + .type __x86.get_pc_thunk.bx, @function +__x86.get_pc_thunk.bx: +.LFB1: + .cfi_startproc + movl (%esp), %ebx + ret + .cfi_endproc +.LFE1: + .ident "GCC: (GNU) 4.9.2" + .section .note.GNU-stack,"",@progbits diff --git a/workaround.S b/workaround.S new file mode 100644 index 0000000..a3197d4 --- /dev/null +++ b/workaround.S @@ -0,0 +1,9 @@ +.data + +.globl __progname +__progname: + .int 0 + +.globl environ +environ: + .byte 0