rilden [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=44887 Game of Life at 390 fps <p> <table><tr><td> <a href="/bbs/?pid=94115#p"> <img src="/bbs/thumbs/pico8_rld_conway-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=94115#p"> rld_conway</a><br><br> by <a href="/bbs/?uid=44887"> rilden</a> <br><br><br> <a href="/bbs/?pid=94115#p"> [Click to Play]</a> </td></tr></table> <br /> With the release of pico 0.2.3 the code slowed down a bit and exceeded 100% cpu, so I lowered the maximum fps from 420 to 390.</p> <p>Controls: change color with left and right, change speed with up and down.<br /> You can change the initial board by changing the spritesheet. Use colors 0 and 7.</p> <p>The board is stored as a bitmap, 1 bit per cell at address 0x4300.</p> <p>Updating the board:<br /> 32 cells are processed in parallel using bitwise operations.<br /> The bits are added together using the following functions:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> function add2(a, b) sum = a ^^ b carry = a &amp; b return sum, carry end function add3(a, b, c) tmp = a ^^ b sum = tmp ^^ c carry = a &amp; b | tmp &amp; c return sum, carry end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Let's use the following map to refer to the neighboring cells:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> abc -- above d.e -- current fgh -- below</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>We get the sum of b+g using add2(above, below).<br /> We get the sum of a+d+f and the sum of c+e+h by using add3(above, current, below). To access the sum of a+d+f or c+e+h we shift the result left or right by 1.<br /> Now we have the 3 sums as 2 digit binary numbers:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> sum bit0 bit1 b+g: s0 c0 a+d+f: s1 c1 c+e+h: s2 c2</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>We add these numbers one column at a time to get bit0 and bit1 of the final sum:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> bit0, c = add3(s0, s1, s2) sum, carry = add3(c0, c1, c2) bit1 = sum ^^ c</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>A cell is alive in the next generation if:</p> <ol> <li>it has 3 neighbors, or</li> <li>it's alive now and has 2 neighbors.</li> </ol> <p>In the 1st case: 3=11 in binary so the sum is 3 if bit0=1 and bit1=1 and carry=0. The formula is bit0 &amp; bit1 &amp; ~carry<br /> Similarly in the 2nd case the formula is: current_cell &amp; ~bit0 &amp; bit1 &amp; ~carry<br /> The result is: bit0 &amp; bit1 &amp; ~carry | current_cell &amp; ~bit0 &amp; bit1 &amp; ~carry<br /> This can be simplified to (bit0 | current_cell &amp; ~bit0) &amp; bit1 &amp; ~carry, which is equal to (bit0 | current_cell) &amp; bit1 &amp; ~carry</p> <p>To speed up the main loop the add2 and add3 functions are inlined, redundant computations are removed and the loop is unrolled 4 times.</p> <p>Drawing:<br /> The board is expanded from 8 bits to 32 bits using a lookup table and poked to screen memory.</p> https://www.lexaloffle.com/bbs/?tid=43556 https://www.lexaloffle.com/bbs/?tid=43556 Sun, 27 Jun 2021 00:20:07 UTC