#!/usr/bin/env ruby # http://metasm.cr0.org/ require 'metasm' pat = <= 0 ? s.unpack('SS') : [80, 25] end w = (get_terminal_size[1]-3) w = pat.to_a.first.chomp.length h = get_terminal_size[0]-2 dy = (h-pat.to_a.length)/2 dx = (w-pat.to_a.map { |l| l.chomp.length }.max)/2 init = [] pat.to_a.each_with_index { |p, y| y += dy x = dx p.unpack('C*').each { |c| case c when ?.; x += 1 when ?O; init << "set(#{x},#{y})" ; x += 1 end } } src = < #define coord(x, y) ((y)*W+(x)) #define value(x, y) byte ptr [ebp+coord(x, y)] #define set(x, y) mov value(x, y), 1 .text iter: // calc count table mov ebp, table mov edi, count // 1st line xor eax, eax #ifdef CIRCULAR add al, value(W-1, H-1) add al, value(0, H-1) add al, value(1, H-1) add al, value(W-1, 0) add al, value(W-1, 1) #endif add al, value(1, 0) add al, value(0, 1) add al, value(1, 1) stosb mov ecx, 1 loopl1: // TODO sub al, col(-2) ; add al, col(1) xor eax, eax #ifdef CIRCULAR add al, value(ecx-1, H-1) add al, value(ecx, H-1) add al, value(ecx+1, H-1) #endif add al, value(ecx-1, 0) add al, value(ecx+1, 0) add al, value(ecx-1, 1) add al, value(ecx, 1) add al, value(ecx+1, 1) stosb inc ecx cmp ecx, W-1 jb loopl1 xor eax, eax #ifdef CIRCULAR add al, value(W-2, H-1) add al, value(W-1, H-1) add al, value(0, H-1) add al, value(0, 0) add al, value(0, 1) #endif add al, value(W-2, 0) add al, value(W-2, 1) add al, value(W-1, 1) stosb mov ebx, 1 // line nr loopbody: add ebp, W xor eax, eax #ifdef CIRCULAR add al, value(W-1, -1) add al, value(W-1, 0) add al, value(W-1, 1) #endif add al, value(1, 0) add al, value(0, 1) add al, value(1, 1) add al, value(0, -1) add al, value(1, -1) stosb mov ecx, 1 loopl: xor eax, eax add al, value(ecx-1, -1) add al, value(ecx, -1) add al, value(ecx+1, -1) add al, value(ecx-1, 0) add al, value(ecx+1, 0) add al, value(ecx-1, 1) add al, value(ecx, 1) add al, value(ecx+1, 1) stosb inc ecx cmp ecx, W-1 jb loopl xor eax, eax #ifdef CIRCULAR add al, value(0, -1) add al, value(0, 0) add al, value(0, 1) #endif add al, value(W-2, -1) add al, value(W-1, -1) add al, value(W-2, 0) add al, value(W-2, 1) add al, value(W-1, 1) stosb inc ebx cmp ebx, H-1 jb loopbody // last line mov ebp, table xor eax, eax #ifdef CIRCULAR add al, value(W-1, 0) add al, value(0, 0) add al, value(1, 0) add al, value(W-1, H-2) add al, value(W-1, H-1) #endif add al, value(0, H-2) add al, value(1, H-2) add al, value(1, H-1) stosb mov ecx, 1 loopll: xor eax, eax #ifdef CIRCULAR add al, value(ecx-1, 0) add al, value(ecx, 0) add al, value(ecx+1, 0) #endif add al, value(ecx-1, H-2) add al, value(ecx, H-2) add al, value(ecx+1, H-2) add al, value(ecx-1, H-1) add al, value(ecx+1, H-1) stosb inc ecx cmp ecx, W-1 jb loopll xor eax, eax #ifdef CIRCULAR add al, value(0, H-2) add al, value(0, H-1) add al, value(W-2, 0) add al, value(W-1, 0) add al, value(0, 0) #endif add al, value(W-2, H-2) add al, value(W-1, H-2) add al, value(W-2, H-1) stosb // update table, fill buffer mov ebx, buffer-2 mov edi, table-1 mov esi, count nextc: #ifdef RANDGLIDER add edx, 1 cmp edx, RANDGLIDER jbe noswap xor edx, edx cmp edi, table+2*W+1 jbe noswap xor byte ptr [edi], 1 xor byte ptr [edi-1], 1 xor byte ptr [edi-2], 1 xor byte ptr [edi-W], 1 xor byte ptr [edi-2*W-1], 1 noswap: #endif add ebx, 2 inc edi cmp esi, count+H*W jae donec lodsb cmp al, 2 je skipc cmp al, 3 je setc mov byte ptr [edi], 0 mov byte ptr [ebx], ' ' jmp nextc setc: mov byte ptr [edi], 1 mov byte ptr [ebx], 'x' jmp nextc skipc: mov al, byte ptr [edi] movzx eax, al imul eax, 'x'-' ' add eax, ' ' mov byte ptr [ebx], al jmp nextc donec: ret display: // print buffer push edx mov edx, bufferend-prebuffer mov ecx, prebuffer mov ebx, 1 mov eax, __NR_write int 80h pop edx ret init: mov edx, initbufferend-initbuffer mov ecx, initbuffer mov ebx, 1 mov eax, __NR_write int 80h #ifdef CUSTOM_INIT mov ebp, table CUSTOM_INIT #else // randomize table xor ecx, ecx mov ebx, timestruct mov eax, __NR_gettimeofday int 80h mov ebx, [timestruct] mov edi, table mov ecx, W*H randloop: imul ebx, 214013 add ebx, 2531011 mov eax, ebx shr eax, 28 and eax, 1 stosb loop randloop #endif ret iterloop: call iter call display xor ecx, ecx mov ebx, timestruct mov dword ptr [ebx], SLEEP_MS/1000 mov dword ptr [ebx+4], SLEEP_MS*1000000 mov eax, __NR_nanosleep int 80h jmp iterloop ret .entrypoint call init call iterloop mov ebx, 0 mov eax, __NR_exit int 80h .data timestruct dd 0, 0 prebuffer db "\e[H" // move cursor home buffer db H dup(W-1 dup ("x "), "x\n") bufferend: initbuffer db "\e[H\e[J" // move cursor home & clear screen initbufferend: .bss table db H*W dup(?) count db H*W dup(?) .pt_gnu_stack rw .interp none