%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 ; top left starts going right mov byte [energized], 1 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 call newline game_over: mov eax, ebp call print_dec call newline jmp exit [section .data] final_value: dd 0 last_energized: 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: