223 lines
4.2 KiB
NASM
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
|