Compare commits

...

3 Commits

Author SHA1 Message Date
63ded22bfd more work on actual game logic 2025-07-10 22:55:18 +02:00
00cc777183 add warning flags 2025-07-10 20:59:32 +02:00
b94ebe30c8 add user input handling 2025-07-10 18:27:52 +02:00
6 changed files with 306 additions and 8 deletions

View File

@ -1,7 +1,7 @@
NASM = nasm
LD = ld
NASM_FLAGS := -felf64 -Isrc
NASM_FLAGS := -felf64 -Isrc -Ox -Ov -w+all -w-reloc-abs-dword -w-reloc-rel-dword
LD_FLAGS := --strip-all
DEBUG_LD_FLAGS := -g

View File

@ -9,9 +9,12 @@ section .bss
extern term_cols
extern gameboard_size
global simulation_running
simulation_running: RESB 1
next_frame_ptr: RESQ 1
section .rodata
clear: db ESC_CHAR, "[2J", 0
reset: db ESC_CHAR, "[0m", 0
@ -20,8 +23,8 @@ section .rodata
home_cursor: db ESC_CHAR, "[H", 0
statusbar: db ESC_CHAR, "[30;100m", "Use arrow keys to move cursor, enter to invert cell h/j to change simulation speed, p to simulation", 0
START_STOP_pos: equ $-statusbar-16
statusbar: db ESC_CHAR, "[30;100m", "Use arrow keys to move cursor, enter to invert cell j/k to change simulation speed, p to simulation", 0
START_STOP_pos: equ $-statusbar-17
start_str: db "START", 0
@ -31,6 +34,7 @@ section .text
extern print_str
extern string_copy
extern memory_set
extern alloc
global init_gameboard
init_gameboard:
@ -50,6 +54,7 @@ init_gameboard:
pop rdx
pop rdi
add rdi, rdx; get pointer to last char on screen
push rdx
push rdi
add rdi, ESC_chars_compensation_Len
lea rsi, [reset]
@ -62,15 +67,101 @@ init_gameboard:
lea rsi, [statusbar]
call string_copy
pop rdi
call alloc
mov [next_frame_ptr], rax
ret
global print_game_ui
print_game_ui:
lea rdi, [home_cursor]
call print_str
mov qword rdi, [gameboard_ptr]
push rdi
add rdi, [gameboard_size]
sub di, [term_cols]
add rdi, START_STOP_pos
mov cl, [simulation_running]
test cl,cl; test if simulation is running
jz .simulation_not_running
lea rsi, [stop_str]
jmp .end_simulation_running_check
.simulation_not_running:
lea rsi, [start_str]
.end_simulation_running_check:
call string_copy
pop rdi
call print_str
ret
%macro check_if_hashtag 1
cmp r8, %1
jl +7
cmp r9, %1
ja +5
mov r11b, [%1]
cmp r11b, '#'
jne +2
inc dl
%endmacro
global step_simulation:
step_simultion:
mov rdi, [next_frame_ptr]; destination
mov rsi, [gameboard_ptr]; source
mov rcx, [gameboard_size]; number of iterations
mov r8, rsi; store lowest address posible so we are not checking out of bounds
mov r9, rsi
add r9, rcx; store higest address posible so we are not checking out of bounds
mov r10, [term_cols]
;mov r11, [term_rows] this register has been confiscated since i cannot use ah because of error: cannot use high byte register in rex instruction
xor rax, rax; this shouldn't be needed but just to be sure
xor r11, r11
xor rdx, rdx; we will use dl as # counter
.for_every_column_on_gameboard:
mov al, [rdi]; NOTE to self if i need extra register i can shift this to ah and free up r11
inc rdi
check_if_hashtag rdi
dec rdi
check_if_hashtag rdi-1
add rdi, r10
check_if_hashtag rdi
inc rdi
check_if_hashtag rdi
dec rdi
check_if_hashtag rdi-1
sub rdi, r10
sub rdi, r10
check_if_hashtag rdi
inc rdi
check_if_hashtag rdi
dec rdi
check_if_hashtag rdi-1
add rdi, r10
; TODO create jump table
ret

View File

@ -1,12 +1,141 @@
%include "symbols.asm"
section .bss
cursor_rows: RESW 1
cursor_rows: RESW 1; TODO DONT FORGET TO INICIALIZE
cursor_cols: RESW 1
extern multipurpuse_buf
extern term_rows
extern term_cols
extern gameboard_ptr
extern simulation_running
section .rodata
cursor_up: db ESC_CHAR, "[1A", 0
cursor_down: db ESC_CHAR, "[1B", 0
cursor_right: db ESC_CHAR, "[1C", 0
cursor_left: db ESC_CHAR, "[1D", 0
arrow_switch_statement:
dq handle_user_input.arrow_up
dq handle_user_input.arrow_down
dq handle_user_input.arrow_right
dq handle_user_input.arrow_left
section .text
global handle_user_input
handle_user_input:
extern print_str
global handle_user_input
handle_user_input:; main loop of the program
.main_loop:
xor rax, rax
mov qword [multipurpuse_buf], rax; zeroout the buffer
mov rax, SYS_POLL
mov rdi, STDIN
mov rsi, 1; only one file descriptor is provided
mov rdx, 0; no timeout. maybe use this for final sleep but run if user inputs something TODO
syscall
test rax, rax; SYS_POLL returns 0 when no change happens within timeout
jz .no_input
mov rax, SYS_READ
mov rdi, STDIN
lea rsi, [multipurpuse_buf]
mov rdx, 8; size of multipurpuse buffer
syscall; read user input
mov rax, [multipurpuse_buf]
shr rax, 5; we need only 3 bytes for this inpus sceame
cmp eax, 0x001B5B44; check if input is more than left arrow
ja .handle_single_byte_chars
sub eax, 0x1B5B41
jmp [arrow_switch_statement+(rax*8)]; lets hope this works
.arrow_up:
dec word [cursor_rows]
lea rdi, [cursor_up]
call print_str
jmp .no_input
.arrow_down:
inc word [cursor_rows]
lea rdi, [cursor_down]
call print_str
jmp .no_input
.arrow_right:
inc word [cursor_cols]
lea rdi, [cursor_right]
call print_str
jmp .no_input
.arrow_left:
dec word [cursor_cols]
lea rdi, [cursor_left]
call print_str
jmp .no_input
.handle_single_byte_chars:
shr eax, 2; get the char to al
cmp al, 0xa; NEWLINE (enter key)
jne .check_p
xor rax, rax; zeroout rax
mov ax, [cursor_rows]
mul dword [term_cols]
add rax, [cursor_cols]
lea rdi, [gameboard_ptr+rax]
mov cl, [rdi]
cmp cl, '#'
je .hashtag_present
mov byte [rdi], '#'
jmp .no_input
.hashtag_present:
mov byte [rdi], ' '
jmp .no_input
.check_p:
cmp al, 'p'
jne .check_j
xor byte [simulation_running], 0x01; switch simulation on or off
jmp .no_input
.check_j:
cmp al, 'j'
jne .check_k
; TODO implement simulation speed
jmp .no_input
.check_k:
cmp al, 'k'
jne .no_input
; TODO implement simulation speed
.no_input:
jmp .main_loop
ret

View File

@ -3,6 +3,7 @@
section .bss
global multipurpuse_buf
multipurpuse_buf: RESB 8
global term_rows
@ -72,6 +73,13 @@ _start:
mov [gameboard_ptr], rax; stores pointer to gameboard array
call init_gameboard
; make stdin non-blocking in case polling somehow fails, or am i stupid
mov rax, SYS_FCNTL
mov rdi, STDIN
mov rsi, F_SETFL
mov rdx, O_NONBLOCK
syscall
call print_game_ui

View File

@ -141,3 +141,65 @@ memory_set:; takes destination in rdi, byte in sil and lenght in rdx
.true_function_exit:
mov rax, r9; return pointer to memory area same as memset in libc
ret
global memory_copy:
memory_copy:; takes destination in rdi, source in rsi and lenght in rdx
; first check if value is 16 byte alligned
mov r9, rdi
cmp rdx, 16
jnl .write_16_or_more_bytes
mov rcx, rdx
jmp .write_less_than_16_bytes
.write_16_or_more_bytes:
mov rax, rdi; move destination to rax
and rax, 0xF; offset is stored in rax
test al, al; check if resault is 0
jz .addr_is_16_Byte_alligned
mov cl, 16
sub cl, al; now offset to first higher 16 byte alligned address is stored in r8
movzx rcx, cl; remove ani posible garbage
.write_less_than_16_bytes:
sub rdx, rcx; we will write these bytes now
rep movsb
.addr_is_16_Byte_alligned:
mov r10, rdx
shr r10, 4; set it to how many 128bit(16Byte) chunk we need
test r10, r10; check if we need to write aditional 16 bytes at all
jz .function_exit
.move_16_bytes:
movdqa xmm8, [rsi]
movdqa [rdi], xmm8
add rdi, 16
add rsi, 16
sub rdx, 16
cmp rdx, 16; test if rdx is less than 16
jge .move_16_bytes
.function_exit:
test rdx, rdx; test if rdx is 0
jz .true_function_exit
movzx rcx, dl
jmp .write_less_than_16_bytes
.true_function_exit:
mov rax, r9; return pointer to memory area same as memset in libc
ret

View File

@ -1,10 +1,18 @@
SYS_EXIT equ 60
SYS_IOCTL equ 16
SYS_READ equ 0
SYS_WRITE equ 1
SYS_BRK equ 12
SYS_FCNTL equ 72
SYS_POLL equ 7
STDIN equ 0
STDOUT equ 1
TIOCGWINSZ equ 0x5413
POLLIN equ 1
F_SETFL equ 4
O_NONBLOCK equ 2048
ASCII_ZERO equ 48
ESC_CHAR equ 27