summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/fruit.asm7
-rw-r--r--src/input.asm43
-rw-r--r--src/main.asm84
-rw-r--r--src/utils.asm68
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