diff --git a/16/main.s b/16/main.s new file mode 100644 index 0000000..8e853b1 --- /dev/null +++ b/16/main.s @@ -0,0 +1,502 @@ +%include "utils.s" + +global _start +[bits 32] +[section .text] + +%define LINE_LEN 111 ; real +%define FILENAME "input" +;%define LINE_LEN 11 ; test +;%define FILENAME "input_test" + +;%define ITER_PRINT + +_start: + +; bit 3 bit 2 bit 1 bit 0 +; up down left right + +; start top left going right +mov dword [test_edge_line], 0 +mov dword [test_edge_col], 0 +mov byte [test_edge_dir], 1 +mov byte [energized], 1 +jmp next_iteration +next_edge_tile: +; clear energized +mov edi, energized +xor eax, eax +mov ecx, (128*128)/4 +rep stosd + +mov eax, [test_edge_line] +mov ecx, [test_edge_col] +mov bl, [test_edge_dir] +cmp bl, 1 ; we're testing going right +jne .maybe_2 +; we're going down first col +cmp eax, LINE_LEN-2 ; check if last line +je .bl_corner +inc eax +jmp start_iterations +.bl_corner: +mov bl, 8 ; try going up +jmp start_iterations +.maybe_2: +cmp bl, 2 ; we're testing going left +jne .maybe_4 +; we're going up the last col +cmp eax, 0 ; check if first line +je .tr_corner +dec eax +jmp start_iterations +.tr_corner: +mov bl, 4 ; try going down +jmp start_iterations +.maybe_4: +cmp bl, 4 ; we're testing going down +jne .maybe_8 +; we're going along the top line backward +cmp ecx, 0 ; check if first col +je .tl_corner +dec ecx +jmp start_iterations +.tl_corner: +jmp game_over ; nothing to do! jump to exit +.maybe_8: ; we're testing going up +; we're going along the bottom line +cmp ecx, LINE_LEN-2 ; check if last col +je .br_corner +inc ecx +jmp start_iterations +.br_corner: +mov bl, 2 ; try going left +jmp start_iterations + +start_iterations: +mov [test_edge_line], eax +mov [test_edge_col], ecx +mov [test_edge_dir], bl +mov edx, LINE_LEN +mul edx +add eax, ecx +mov byte [energized+eax], bl + +next_iteration: + +%ifdef ITER_PRINT +; debug printing +dbg: +xor esi, esi ; top line +.for_lines: + xor ecx, ecx ; leftmost char + .for_chars: + movzx eax, byte [esi+ecx+energized] + movzx ebx, byte [esi+ecx+file] + pushad + test al, al + jz .prnt_char + p_string ansi_color_highbold_green + cmp bl, '.' + jne .prnt_char + popcnt ecx, eax + cmp ecx, 1 + jg .prnt_num + cmp al, 1 + je .prnt_right + cmp al, 2 + je .prnt_left + cmp al, 4 + je .prnt_down + .prnt_up: mov al, '^' + call print_char + jmp .prnt_done + .prnt_down: mov al, 'v' + call print_char + jmp .prnt_done + .prnt_left: mov al, '<' + call print_char + jmp .prnt_done + .prnt_right: mov al, '>' + call print_char + jmp .prnt_done + .prnt_num: + mov eax, ecx + call print_dec + jmp .prnt_done + .prnt_char: + mov al, [esi+ecx+file] + call print_char + .prnt_done: + p_string ansi_color_reset + popad + .for_chars_cont: + inc ecx + cmp ecx, LINE_LEN-2 + jbe .for_chars + .for_chars_done: +.for_lines_cont: +call newline +add esi, LINE_LEN +cmp esi, len(file) +jb .for_lines +call newline +; debug printing end +%endif + +xor esi, esi ; top line +for_lines: + xor ecx, ecx ; leftmost char + for_chars: + movzx eax, byte [esi+ecx+energized] + movzx ebx, byte [esi+ecx+file] + ; skip if not energized + test eax, eax + jz for_chars_cont + ; select thing + cmp bl, '.' + je empty + cmp bl, '/' + je mirror_one + cmp bl, '\' + je mirror_two + cmp bl, '-' + je horz_split + cmp bl, '|' + je vert_split + p_string what_the_fuck + jmp exit + empty: ; . + ; propagate + ; test right + bt eax, 0 + jnc .t_left + or byte [esi+ecx+energized+1], 1<<0 + .t_left: + bt eax, 1 + jnc .t_down + or byte [esi+ecx+energized-1], 1<<1 + .t_down: + bt eax, 2 + jnc .t_up + or byte [esi+ecx+energized+LINE_LEN], 1<<2 + .t_up: + bt eax, 3 + jnc .done + or byte [esi+ecx+energized-LINE_LEN], 1<<3 + .done: + jmp for_chars_cont + mirror_one: ; / + ; our energized is what hits us + ; test right >/ + bt eax, 0 + jnc .t_left + or byte [esi+ecx+energized-LINE_LEN], 1<<3 ; up char going up + .t_left: ; /< + bt eax, 1 + jnc .t_down + or byte [esi+ecx+energized+LINE_LEN], 1<<2 ; down going down + .t_down: + bt eax, 2 ; v + jnc .t_up ; / + or byte [esi+ecx+energized-1], 1<<1 ; left going left + .t_up: + bt eax, 3 ; / + jnc .done ; ^ + or byte [esi+ecx+energized+1], 1<<0 ; right going right + .done: + jmp for_chars_cont + mirror_two: ; \ + ; our energized is what hits us + ; test right >\ + bt eax, 0 + jnc .t_left + or byte [esi+ecx+energized+LINE_LEN], 1<<2 ; down char going down + .t_left: ; \< + bt eax, 1 + jnc .t_down + or byte [esi+ecx+energized-LINE_LEN], 1<<3 ; up going up + .t_down: + bt eax, 2 ; v + jnc .t_up ; \ + or byte [esi+ecx+energized+1], 1<<0 ; right going right + .t_up: + bt eax, 3 ; \ + jnc .done ; ^ + or byte [esi+ecx+energized-1], 1<<1 ; left going left + .done: + jmp for_chars_cont + horz_split: ; - + ; our energized is what hits us + ; right and left propagate + ; test right + bt eax, 0 + jnc .t_left + or byte [esi+ecx+energized+1], 1<<0 + .t_left: + bt eax, 1 + jnc .t_vert + or byte [esi+ecx+energized-1], 1<<1 + ; down and up go both left and right + .t_vert: + and eax, 1<<2 | 1<<3 + jz .done + or byte [esi+ecx+energized+1], 1<<0 ; right going right + or byte [esi+ecx+energized-1], 1<<1 ; left going left + .done: + jmp for_chars_cont + vert_split: ; | + ; our energized is what hits us + ; down and up propagate + ; test down + bt eax, 2 + jnc .t_up + or byte [esi+ecx+energized+LINE_LEN], 1<<2 + .t_up: + bt eax, 3 + jnc .t_vert + or byte [esi+ecx+energized-LINE_LEN], 1<<3 + ; left and right go both down and up + .t_vert: + and eax, 1<<0 | 1<<1 + jz .done + or byte [esi+ecx+energized+LINE_LEN], 1<<2 ; down going down + or byte [esi+ecx+energized-LINE_LEN], 1<<3 ; up going up + .done: + for_chars_cont: + inc ecx + cmp ecx, LINE_LEN-2 + jbe for_chars + for_chars_done: +for_lines_cont: +add esi, LINE_LEN +cmp esi, len(file) +jb for_lines + +xor ebp, ebp ; energized count +sub esi, LINE_LEN ; last line +; now go through backward +bkwd_for_lines: + mov ecx, LINE_LEN-2 ; rightmost char + bkwd_for_chars: + movzx eax, byte [esi+ecx+energized] + movzx ebx, byte [esi+ecx+file] + ; skip if not energized + test eax, eax + jz bkwd_for_chars_cont + inc ebp ; energized count + ; select thing + cmp bl, '.' + je bkwd_empty + cmp bl, '/' + je bkwd_mirror_one + cmp bl, '\' + je bkwd_mirror_two + cmp bl, '-' + je bkwd_horz_split + cmp bl, '|' + je bkwd_vert_split + p_string what_the_fuck + jmp exit + bkwd_empty: ; . + ; propagate + ; test right + bt eax, 0 + jnc .t_left + or byte [esi+ecx+energized+1], 1<<0 + .t_left: + bt eax, 1 + jnc .t_down + or byte [esi+ecx+energized-1], 1<<1 + .t_down: + bt eax, 2 + jnc .t_up + or byte [esi+ecx+energized+LINE_LEN], 1<<2 + .t_up: + bt eax, 3 + jnc .done + or byte [esi+ecx+energized-LINE_LEN], 1<<3 + .done: + jmp bkwd_for_chars_cont + bkwd_mirror_one: ; / + ; our energized is what hits us + ; test right >/ + bt eax, 0 + jnc .t_left + or byte [esi+ecx+energized-LINE_LEN], 1<<3 ; up char going up + .t_left: ; /< + bt eax, 1 + jnc .t_down + or byte [esi+ecx+energized+LINE_LEN], 1<<2 ; down going down + .t_down: + bt eax, 2 ; v + jnc .t_up ; / + or byte [esi+ecx+energized-1], 1<<1 ; left going left + .t_up: + bt eax, 3 ; / + jnc .done ; ^ + or byte [esi+ecx+energized+1], 1<<0 ; right going right + .done: + jmp bkwd_for_chars_cont + bkwd_mirror_two: ; \ + ; our energized is what hits us + ; test right >\ + bt eax, 0 + jnc .t_left + or byte [esi+ecx+energized+LINE_LEN], 1<<2 ; down char going down + .t_left: ; \< + bt eax, 1 + jnc .t_down + or byte [esi+ecx+energized-LINE_LEN], 1<<3 ; up going up + .t_down: + bt eax, 2 ; v + jnc .t_up ; \ + or byte [esi+ecx+energized+1], 1<<0 ; right going right + .t_up: + bt eax, 3 ; \ + jnc .done ; ^ + or byte [esi+ecx+energized-1], 1<<1 ; left going left + .done: + jmp bkwd_for_chars_cont + bkwd_horz_split: ; - + ; our energized is what hits us + ; right and left propagate + ; test right + bt eax, 0 + jnc .t_left + or byte [esi+ecx+energized+1], 1<<0 + .t_left: + bt eax, 1 + jnc .t_vert + or byte [esi+ecx+energized-1], 1<<1 + ; down and up go both left and right + .t_vert: + and eax, 1<<2 | 1<<3 + jz .done + or byte [esi+ecx+energized+1], 1<<0 ; right going right + or byte [esi+ecx+energized-1], 1<<1 ; left going left + .done: + jmp bkwd_for_chars_cont + bkwd_vert_split: ; | + ; our energized is what hits us + ; down and up propagate + ; test down + bt eax, 2 + jnc .t_up + or byte [esi+ecx+energized+LINE_LEN], 1<<2 + .t_up: + bt eax, 3 + jnc .t_vert + or byte [esi+ecx+energized-LINE_LEN], 1<<3 + ; left and right go both down and up + .t_vert: + and eax, 1<<0 | 1<<1 + jz .done + or byte [esi+ecx+energized+LINE_LEN], 1<<2 ; down going down + or byte [esi+ecx+energized-LINE_LEN], 1<<3 ; up going up + .done: + bkwd_for_chars_cont: + dec ecx + jnz bkwd_for_chars + bkwd_for_chars_done: +bkwd_for_lines_cont: +sub esi, LINE_LEN +jns bkwd_for_lines + +cmp ebp, [last_energized] +mov [last_energized], ebp +jne next_iteration + + +; print final +xor ebp, ebp +print_final: +xor esi, esi ; top line +.for_lines: + xor ecx, ecx ; leftmost char + .for_chars: + movzx eax, byte [esi+ecx+energized] + movzx ebx, byte [esi+ecx+file] + test al, al + jz .prnt_char + inc ebp + p_string ansi_color_highbold_green + cmp bl, '.' + jne .prnt_char + popcnt edx, eax + cmp edx, 1 + jg .prnt_num + cmp al, 1 + je .prnt_right + cmp al, 2 + je .prnt_left + cmp al, 4 + je .prnt_down + .prnt_up: mov al, '^' + call print_char + jmp .prnt_done + .prnt_down: mov al, 'v' + call print_char + jmp .prnt_done + .prnt_left: mov al, '<' + call print_char + jmp .prnt_done + .prnt_right: mov al, '>' + call print_char + jmp .prnt_done + .prnt_num: + mov eax, edx + call print_dec + jmp .prnt_done + .prnt_char: + mov al, [esi+ecx+file] + call print_char + .prnt_done: + p_string ansi_color_reset + .for_chars_cont: + inc ecx + cmp ecx, LINE_LEN-2 + jbe .for_chars + .for_chars_done: +.for_lines_cont: +call newline +add esi, LINE_LEN +cmp esi, len(file) +jb .for_lines +mov eax, ebp +call print_dec +call newline +call newline +cmp [final_value], ebp +cmova ebp, [final_value] +mov [final_value], ebp +jmp next_edge_tile + +game_over: +mov eax, [final_value] +call print_dec +call newline +jmp exit + +[section .data] +final_value: dd 0 +last_energized: dd 0 +test_edge_line: dd 0 +test_edge_col: dd 0 +test_edge_dir: dd 0 +file: incbin FILENAME +.over: + +[section .bss] +padding: resb 128 +energized: resb 128*128 + +[section .rodata] +what_the_fuck: db "Something is terribly wrong in this world." +.over: +ansi_color_reset: db `\e[0m` +.over: +ansi_color_green: db `\e[0;32m` +.over: +ansi_color_highbold_green: db `\e[1;92m` +.over: