asm-game-of-life/src/drawing.asm
2025-07-12 16:09:39 +02:00

223 lines
4.2 KiB
NASM

%include "symbols.asm"
section .bss
extern gameboard_ptr
extern term_rows
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
resetLen: equ $-reset-1
global resetLen
home_cursor: db ESC_CHAR, "[H", 0
statusbar: db ESC_CHAR, "[32;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
stop_str: db "STOP ", 0
alive_switch_statement:
dq step_simulation.die; 0
dq step_simulation.die; 1
dq step_simulation.live; 2
dq step_simulation.live; 3
dq step_simulation.die; 4
dq step_simulation.die; 5
dq step_simulation.die; 6
dq step_simulation.die; 7
dq step_simulation.die; 8
section .text
extern print_str
extern string_copy
extern memory_set
extern memory_copy
extern alloc
global init_gameboard
init_gameboard:
xor rax, rax
xor rcx, rcx
mov rdi, [gameboard_ptr]
push rdi
mov rsi, 0x20; set rsi to SPACE character
mov rdx, [gameboard_size]
push rdx
add rdx, ESC_chars_compensation_Len; I dont know how this work but it works so i wont touch it
call memory_set
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]
call string_copy
pop rdi
xor rax, rax
mov ax, [term_cols]
sub rdi, rax
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 2
cmp %1, r8
jl .no_count_%2
cmp %1, r9
ja .no_count_%2
mov r11b, [%1]
cmp r11b, '#'
jne .no_count_%2
inc dl
.no_count_%2:
%endmacro
global step_simulation:
step_simulation:
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
xor r10, r10
mov r10w, [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
sub rcx, r10; remove status bar
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:
xor dl, dl
mov al, [rsi]; NOTE to self if i need extra register i can shift this to ah and free up r11
inc rsi
check_if_hashtag rsi, 1; check column to the to the right
dec rsi
dec rsi
check_if_hashtag rsi, 2; check the one to the left
inc rsi
add rsi, r10
check_if_hashtag rsi, 3; check the one to the down
inc rsi
check_if_hashtag rsi, 4; check the one to the down-right
dec rsi
dec rsi
check_if_hashtag rsi, 5; check the one to the down-left
inc rsi
sub rsi, r10
sub rsi, r10
check_if_hashtag rsi, 6; check the one to the up
inc rsi
check_if_hashtag rsi, 7; check the one to the up-right
dec rsi
dec rsi
check_if_hashtag rsi, 8; check the one to the up-left
inc rsi
add rsi, r10
cmp al, '#'
jne .dead_cell
jmp [alive_switch_statement+(rdx*8)]
.die:
mov byte [rdi], 0x20; SPACE
jmp .end_check
.live:
mov byte [rdi], '#'
jmp .end_check
.dead_cell:
cmp dl, 3
jne .fill_space_there
mov byte [rdi], '#'
jmp .end_check
.fill_space_there:
mov byte [rdi], 0x20; SPACE
.end_check:
dec rcx
inc rdi
inc rsi
test rcx, rcx
jnz .for_every_column_on_gameboard
mov rsi, [next_frame_ptr]; source
mov rdi, [gameboard_ptr]; destination
mov rdx, [gameboard_size]; number of iterations
sub rdx, r10; remove statusbar
call memory_copy
ret