diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/fruit.asm | 7 | ||||
| -rw-r--r-- | src/input.asm | 43 | ||||
| -rw-r--r-- | src/main.asm | 84 | ||||
| -rw-r--r-- | src/utils.asm | 68 |
4 files changed, 194 insertions, 8 deletions
diff --git a/src/fruit.asm b/src/fruit.asm index 31226af..48c718e 100644 --- a/src/fruit.asm +++ b/src/fruit.asm @@ -22,11 +22,14 @@ spawn_fruit: rdtsc shr ax, 5 div byte [width] + inc ah mov byte [fruit_x], ah -;; TODO + + ; y position rdtsc shr ax, 5 div byte [height] + inc ah mov byte [fruit_y], ah ret @@ -46,7 +49,7 @@ _31:call move_cursor_down cmp bl, 0 jnz _31 - mov rax, '*' + mov rax, '-' call write_byte pop rbx diff --git a/src/input.asm b/src/input.asm index f411eed..66794f1 100644 --- a/src/input.asm +++ b/src/input.asm @@ -3,8 +3,13 @@ section .bss section .text global input + global read_input + global start_screen extern direction extern exit + extern timespec + extern write_pause_message + extern write_start_message input: call read_input @@ -12,7 +17,6 @@ input: ret handle_input: - mov al, byte [input_buffer] mov ah, byte [direction] cmp al, 'w' je _input_up @@ -23,7 +27,11 @@ handle_input: cmp al, 'd' je _input_right cmp al, 27 ; escape - je exit + je _pause + ret +_pause: + mov byte [input_buffer], 'w' + call pause ret _input_up: @@ -61,4 +69,35 @@ read_input: mov rsi, input_buffer mov rdx, 250 syscall + mov al, byte [input_buffer] + ret + +pause: + call write_pause_message + mov rax, 35 + lea rdi, [timespec] + xor rsi, rsi + syscall + + call read_input + cmp al, 'q' + je exit + cmp al, 27 ; esc + jne pause + mov byte [input_buffer], '0' + ret + +start_screen: + call write_start_message + mov rax, 35 + lea rdi, [timespec] + xor rsi, rsi + syscall + + call read_input + cmp al, 'q' + je exit + cmp al, 32 ; space + jne start_screen + mov byte [input_buffer], '0' ret diff --git a/src/main.asm b/src/main.asm index c50c33f..0e96b0b 100644 --- a/src/main.asm +++ b/src/main.asm @@ -1,8 +1,6 @@ section .data ; example messages for later - message1 db "Hello, World!", 0xA - msg_len1 equ $ - message1 message2 db "Hello 2!", 0xA msg_len2 equ $ - message2 @@ -20,8 +18,9 @@ section .data direction db 0 ; delay of the game loop (0.5s in the beginning) + global timespec timespec dq 0 - dq 500000000 + dq 250000000 section .rodata ; width and height of the playable area @@ -32,6 +31,8 @@ section .rodata height db 10 section .text + extern write_game_over_message + extern start_screen extern fruit_x extern fruit_y extern spawn_fruit @@ -45,6 +46,7 @@ section .text extern move_cursor_down extern hide_cursor extern show_cursor + extern read_input global _start global exit @@ -108,7 +110,7 @@ _11:push rdx jnz _11 push rdx - mov rax, 'x' + mov rax, 'X' call write_byte call reset_cursor pop rdx @@ -137,6 +139,8 @@ _move_body: jmp _move_body _move_head: + mov ah, byte [width] + mov al, byte [height] cmp byte [direction], 0 je _move_right cmp byte [direction], 1 @@ -148,18 +152,44 @@ _move_head: ret ; should not be accessed _move_right: + cmp byte [snake], ah + jz _to_left_border inc byte [snake] ret _move_down: + cmp byte [snake+1], al + jz _to_top_border inc byte [snake+1] ret _move_left: + cmp byte [snake], 1 + jz _to_right_border dec byte [snake] ret _move_up: + cmp byte [snake+1], 1 + jz _to_bottom_border dec byte [snake+1] ret +_to_left_border: + mov byte [snake], 1 + ret + +_to_right_border: + mov al, byte [width] + mov byte [snake], al + ret + +_to_top_border: + mov byte [snake+1], 1 + ret + +_to_bottom_border: + mov al, byte [height] + mov byte [snake+1], al + ret + check_eat_fruit: mov ah, byte [fruit_x] mov al, byte [fruit_y] @@ -176,14 +206,45 @@ _same_position: call spawn_fruit ret +check_loose: + xor rcx, rcx + mov cl, byte [snake_length] + mov ah, byte [snake] + mov al, byte [snake+1] +_loop_through_snake: + cmp rcx, 4 + jle _loop_return + + mov dh, byte [snake+(2*rcx)-2] + mov dl, byte [snake+(2*rcx)-1] + + dec rcx + + cmp ah, dh + jnz _loop_through_snake + cmp al, dl + jnz _loop_through_snake + jmp game_over + +_loop_return: + ret + _start: + call clear_screen + call draw_border call hide_cursor + call start_screen + +_start_game: + mov byte [snake], 5 mov byte [snake+1], 5 mov byte [snake+2], 4 mov byte [snake+3], 5 mov byte [snake+4], 3 mov byte [snake+5], 5 + mov byte [snake_length], 3 + mov byte [direction], 0 call spawn_fruit main_loop: @@ -199,10 +260,25 @@ main_loop: call input call move_snake + call check_loose call check_eat_fruit jmp main_loop +game_over: + call write_game_over_message + mov rax, 35 + lea rdi, [timespec] + xor rsi, rsi + syscall + + call read_input ; writes input byte into al + cmp al, 32 ; space + je _start_game + cmp al, 'q' ; escape + je exit + jmp game_over + exit: ; exit syscall with return code 0 call show_cursor call clear_screen diff --git a/src/utils.asm b/src/utils.asm index 9281ed2..dfdb09f 100644 --- a/src/utils.asm +++ b/src/utils.asm @@ -1,4 +1,12 @@ section .data + ; messages + game_over_message db "gameover", 0xA, "space - retry", 0xA, "q - quit", 0xA + game_over_message_len equ $ - game_over_message + pause_message db "pause", 0xA, "esc - unpause", 0xA, "q - quit", 0xA + pause_message_len equ $ - pause_message + start_message db "snake", 0xA, "space - start", 0xA, "q - quit", 0xA + start_message_len equ $ - start_message + ; escape code for clearing the screen clear db 0x1B, '[2J', 0x1B, '[H', 0 clear_len equ $ - clear @@ -26,6 +34,10 @@ section .text global reset_cursor global hide_cursor global show_cursor + global write_game_over_message + global write_pause_message + global write_start_message + extern height hide_cursor: push rdi @@ -100,6 +112,62 @@ write_byte: pop rdi ret +cursor_to_message_position: + push rbx + call reset_cursor + mov bl, byte [height] + +_loop_message: + call move_cursor_down + dec bl + cmp bl, -2 + jne _loop_message + + pop rbx + ret + +write_game_over_message: + push rdi + + call cursor_to_message_position + + mov rax, 1 + mov rdi, 1 + mov rsi, game_over_message + mov rdx, game_over_message_len + syscall + + pop rdi + ret + +write_pause_message: + push rdi + + call cursor_to_message_position + + mov rax, 1 + mov rdi, 1 + mov rsi, pause_message + mov rdx, pause_message_len + syscall + + pop rdi + ret + +write_start_message: + push rdi + + call cursor_to_message_position + + mov rax, 1 + mov rdi, 1 + mov rsi, start_message + mov rdx, start_message_len + syscall + + pop rdi + ret + clear_screen: push rdi |