samhocevar [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=14958 Pent8cle <p>Hi!</p> <p>It&rsquo;s been ages since I did anything for Ludum Dare. This time the theme was &ldquo;Summoning&rdquo;, so this is my attempt at a puzzle game where you need to complete a pentacle in order to summon whatever it is you summon. I did not spend too much time on this and could not find game mechanics that were both fun and challenging, so don&rsquo;t expect anything great&hellip;</p> <p>Left/Right arrows: browse runes (in select mode) or rotate rune (in placement mode)<br /> Z/C: select rune (in select mode) or place rune (in placement mode)<br /> X: cancel rune placement and return to select mode</p> <p>Compo entry page <a href="https://ldjam.com/events/ludum-dare/55/$391423">is here</a>.</p> <p> <table><tr><td> <a href="/bbs/?pid=146659#p"> <img src="/bbs/thumbs/pico8_pent8cle-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=146659#p"> pent8cle</a><br><br> by <a href="/bbs/?uid=14958"> samhocevar</a> <br><br><br> <a href="/bbs/?pid=146659#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=141733 https://www.lexaloffle.com/bbs/?tid=141733 Mon, 15 Apr 2024 01:02:35 UTC Insecure format string handling in export() <p>PICO-8 will gladly accept <code>export(&quot;sfx_%x_%d.wav&quot;)</code> because the string argument contains <code>%d</code>, but the format string is not sanitised and the SFX index will be caught by <code>%x</code>, and <code>%d</code> will then pick who knows what memory location.</p> <p>Funny things can also happen with <code>%s</code>, <code>%*s</code> etc.; <code>export(&quot;%s%s%s%s%s%s%s%s%s%s%s%s%d&quot;)</code> is almost a guaranteed crash.</p> https://www.lexaloffle.com/bbs/?tid=140298 https://www.lexaloffle.com/bbs/?tid=140298 Thu, 22 Feb 2024 17:18:56 UTC Combining short while and short if confuses parser <p>Here&rsquo;s a simple example:</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> a=0 while(a&lt;4) a+=1 if(a!=3) ?a print('lol') </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Expected output:</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> 1 2 4 lol </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Actual output:</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> 1 lol 2 lol lol 4 lol </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=140066 https://www.lexaloffle.com/bbs/?tid=140066 Thu, 01 Feb 2024 07:06:10 UTC Improved sin() and cos() precision <p>The sin() and cos() functions seem to be using some kind of lookup table at &frac14; the number resolution, with clamping. It is easy to use linear interpolation instead and improve the precision of these functions by calling them twice:</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 trig(f,x) local a, b = f(x &amp; 0x.fffc), f(x | 0x.0003) return a + (b - a) * (x &lt;&lt; 14 &amp; 0x.c) end function xsin(x) return trig(sin,x) end function xcos(x) return trig(cos,x) 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><a href="https://www.lexaloffle.com/bbs/?uid=1"> @zep</a> I think PICO-8 could very well do this internally, as the extra cost seems negligible. The same goes with atan2(), especially since in that case it is significantly more difficult to do in PICO-8 user land.</p> <p> <table><tr><td> <a href="/bbs/?pid=140387#p"> <img src="/bbs/thumbs/pico8_precise_sincos-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=140387#p"> precise_sincos</a><br><br> by <a href="/bbs/?uid=14958"> samhocevar</a> <br><br><br> <a href="/bbs/?pid=140387#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=139914 https://www.lexaloffle.com/bbs/?tid=139914 Sun, 21 Jan 2024 10:46:06 UTC atan2() picks wrong quadrant when dy=0x8000.0000 <p>atan2(1,0x8000.0001) returns 0.25, as expected. However atan2(1,0x8000.0000) returns 0.75.</p> <p>This is the kind of stuff that could be compiler-specific because 0x80000000 is a bit special, however I get this on both Windows and Linux (64-bit).</p> https://www.lexaloffle.com/bbs/?tid=139912 https://www.lexaloffle.com/bbs/?tid=139912 Sat, 20 Jan 2024 23:47:02 UTC Fast sort function (97 tokens) / faster sort function (111 tokens) <p>Here is a simple implementation of merge sort in 97 tokens. It uses less PICO-8 CPU than anything else I&rsquo;ve tried (with a caveat, see below).</p> <p>A small benchmark comparing CPU usage, sorting an array of 200 random numbers:</p> <ul> <li>this merge sort: 12% CPU</li> <li>ce_heap_sort (<a href="https://github.com/morgan3d/misc/tree/master/p8sort">casual effect&rsquo;s heap sort</a>): 12% CPU (but 191 tokens)</li> <li>iqsort (<a href="https://www.lexaloffle.com/bbs/?tid=38679">dual-pivot quicksort by Felice</a>): 74% CPU in degenerate cases (already sorted list), 10% CPU otherwise</li> <li>zsort (<a href="https://www.lexaloffle.com/bbs/?pid=35182#p">quicksort by musurca</a>): 125% CPU in degenerate cases, 18% CPU otherwise</li> </ul> <p>Note that non-randomised quicksort suffers from very bad performance on quasi sorted lists, so the above benchmark does not represent what you would get in real life. Always test in your own application.</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 sort(t, a, b) local a, b = a or 1, b or #t if (a &gt;= b) return local m = (a + b) \ 2 local j, k = a, m + 1 sort(t, a, m) sort(t, k, b) local v = { unpack(t) } for i = a, b do if (k &gt; b or j &lt;= m and v[j] &lt;= v[k]) t[i] = v[j] j += 1 else t[i] = v[k] k += 1 end 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>In real life merge sort performs worse than <em>e.g.</em> quicksort because it suffers from poor locality of reference (cache misses), but in a high level language such as Lua this becomes meaningless.</p> <p>To any computer scientist this specific implementation would be badly written and would appear to perform extremely poorly because {unpack(t)} effectively copies the whole array <del>n&times;log(n)</del> n times. However, in PICO-8 world <strong>this function is ridiculously fast</strong> because for the virtual CPU the operation is almost free. Use at your own risk because the actual CPU running PICO-8 will still perform the operations!</p> <p>Another limitation: does not support arrays of more than 16384 elements because of the overflow in (a+b)\2. Just replace with (a/2+b/2)\1 if necessary.</p> <p><strong>Edit</strong>: here is a version that performs log(n) full array copies and is thus much lighter on the CPU. It is also about 10% faster. The drawback is that it&rsquo;s now 111 tokens, but that&rsquo;s still pretty good.</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 sort(t) local function f(a, b) if a &lt; b then local d = (b - a) \ 2 + 1 f(a, a + d - 1) f(a + d, b) local v, j, k = { unpack(t, a, b) }, 1, d + 1 local vj, vk = v[j], v[k] for i = a, b do if (not vk or j &lt;= d and vj &lt;= vk) t[i] = vj vj = v[j] j += 1 else t[i] = vk vk = v[k] k += 1 end end end f(1, #t) end </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=38706 https://www.lexaloffle.com/bbs/?tid=38706 Mon, 06 Jul 2020 16:04:51 UTC Wrong token count for signed constants <p>Here are a few token count discrepancies:</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> print(12) -- 3 tokens print(-12) -- 3 tokens print(~12) -- 3 tokens print(-~12) -- 4 tokens print(~-12) -- 5 tokens print(~~12) -- 4 tokens ?12 -- 2 tokens ?-12 -- 3 tokens ?~12 -- 2 tokens ?-~12 -- 3 tokens ?~-12 -- 4 tokens ?~~12 -- 3 tokens </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Also this inconsistent behaviour with spaces:</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> print(-12) -- 3 tokens print(- 12) -- 4 tokens print(~12) -- 3 tokens print(~ 12) -- 3 tokens </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=38344 https://www.lexaloffle.com/bbs/?tid=38344 Tue, 09 Jun 2020 10:18:49 UTC Feature proposal: extend the PNG cart compression algorithm <p>I recently <a href="https://www.lexaloffle.com/bbs/?pid=77060#p">wrote a post</a> about storing random data as strings in carts and studying the built-in compression algorithm. It led, among other conclusions, to the following two observations:</p> <ul> <li>PICO-8 is not very good at compressing random strings that use more than 64 different characters; those get actually expanded by about log₂(n)/6. For instance a random string of length 1000 that uses 128 different characters will use 1000*log₂(128)/6 = 1167 bytes in the cart.</li> <li>The <a href="https://pico-8.fandom.com/wiki/P8PNGFileFormat#New_Compressed_Format">new compression format</a> is redundant and allows for sequences that are not needed. For instance 011 01111 001 and 010 0000001111 001 both encode a back reference of length 4 at offset -16.</li> </ul> <p>Most other compression schemes have some sort of fallback mechanism when they are unable to compress a block. For instance the DEFLATE format (for zip or gzip) has <a href="https://www.w3.org/Graphics/PNG/RFC-1951#noncompressed">non-compressed blocks</a>. In the above thread I <a href="https://www.lexaloffle.com/bbs/?pid=77060#p">made a suggestion</a> to extend the compression format in a similar way, but here I have a much simpler proposal:</p> <ul> <li><strong>010 00000 marks the start of a zero-terminated sequence of uncompressed bytes</strong></li> </ul> <p>This works because:</p> <ul> <li>010 00000 never happens in a compressed stream; anything that would start with that sequence could start with 011 instead and be much shorter</li> <li>the null byte is not allowed in the code</li> <li>the overhead is only two bytes; it can be more efficient than the current format for some strings as short as 7 characters</li> <li>it should be easy to adapt the existing compressor so that when it realises the last X bytes have compressed badly it backtracks and stores the bytes instead</li> </ul> https://www.lexaloffle.com/bbs/?tid=38342 https://www.lexaloffle.com/bbs/?tid=38342 Tue, 09 Jun 2020 09:33:38 UTC Feature proposal: shorthand poke <p>I would like to propose the following syntax extensions to PICO-8 for symmetry with the shorthand peek operators. Basically it means treating the peek operators result as an lvalue:</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> @x = y -- short for poke(x,y) %x = y -- short for poke2(x,y) $x = y -- short for poke4(x,y) @x += z -- short for poke(x, @x + z) %12 |= %42 -- short for poke2(12, %12 | %42) $x &gt;&gt;&lt;= 4 -- short for poke4(x, $x &gt;&gt;&lt; 4) </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=38341 https://www.lexaloffle.com/bbs/?tid=38341 Tue, 09 Jun 2020 08:41:47 UTC Wrong token count for some operators <p>The following operators cost 2 tokens instead of the usual 1 for compound assignment operators:</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> \= ^= &gt;&gt;&lt;= &lt;&lt;&gt;= ..= </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p><em>edit</em>: I confused &gt;&gt;&gt;= and ^= in my initial post.</p> https://www.lexaloffle.com/bbs/?tid=38334 https://www.lexaloffle.com/bbs/?tid=38334 Mon, 08 Jun 2020 17:43:44 UTC Parsing issues with short if() cause bugs <p>I&rsquo;m writing a minifier and I still can&rsquo;t really wrap my head around the parser.</p> <p>Here are two similar snippets that differ only in whitespace and do not do the same thing:</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> &gt; for i=1,2 do &gt; if(i)print(i) end &gt; print(3) 1 2 3 </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <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> &gt; for i=1,2 do &gt; if(i)print(i) end print(3) 1 3 2 3 </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=38323 https://www.lexaloffle.com/bbs/?tid=38323 Sun, 07 Jun 2020 22:07:09 UTC Large P8 carts get corrupted (0.2.0i) <p>When attempting to load a .p8 cart that exceeds the 65535 character limit (one that may have been created by an external editor or tool), PICO-8 silently drops lines at the end of the cart and does not report errors. It then accepts to save the (now corrupted) cart when pressing Ctrl-S, overwriting the original file.</p> <p>Here is a <a href="https://paste.debian.net/plain/1149085">sample cartridge</a> for testing purposes; notice that the last print() line disappears when loading it.</p> <p>One more observation: <em>sometimes</em>, when the 65535 character threshold lies in the middle of a Lua statement, a loading error does appear. I have been unable to identify when exactly.</p> https://www.lexaloffle.com/bbs/?tid=38157 https://www.lexaloffle.com/bbs/?tid=38157 Wed, 27 May 2020 08:54:07 UTC Small PNG carts get corrupted (0.2.0i) <p>I created a cart containing the following code:</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> print(&quot;hello&quot;) </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Then in the shell:</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> save foobar.p8.png </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>If I close PICO-8 and reopen foobar.p8.png, I get gibberish in the code section:</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/14958/pico8-save-bug.png" alt="" /> https://www.lexaloffle.com/bbs/?tid=38144 https://www.lexaloffle.com/bbs/?tid=38144 Tue, 26 May 2020 17:09:53 UTC Parsing inconsistencies <p>Due to the preprocessor parsing numbers differently than Lua, here are some issues:</p> <p>Valid code (1e-3 is a valid number in Lua): </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> a=1e-3 </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Invalid code (1e-3 is parsed as 1 e - 3 by the preprocessor): </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> a+=1e-3 </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Invalid code (2b is an invalid number in Lua): </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> a=1+2b=3 </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Valid code (2b is parsed as 2 b by the preprocessor): </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> a+=1+2b=3 </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=38038 https://www.lexaloffle.com/bbs/?tid=38038 Tue, 19 May 2020 21:47:05 UTC Unusual memory behaviour at 0x5f4c <p>Not sure if it is really a bug, but poking at the 8 bytes starting at 0x5f4c then immediately peeking will discard the two highest bits:</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> &gt; p=0x5f4c poke(p,255) print(@p) 63 </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>I know this is a special area and the memory is modified by the virtual hardware between frames, but no other location discards bits like that.</p> https://www.lexaloffle.com/bbs/?tid=38030 https://www.lexaloffle.com/bbs/?tid=38030 Tue, 19 May 2020 08:55:25 UTC Infinite recursion in 0.2.0f bit shift operators <p>The new shift operator behaviour where a&gt;&gt;n returns a&lt;&lt;-n when n is negative causes an infinite loop and freezes PICO-8 when shifting by -32768:</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> ?1&lt;&lt;-32768 ?1&gt;&gt;-32768 ?1&gt;&gt;&gt;-32768 </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=37768 https://www.lexaloffle.com/bbs/?tid=37768 Tue, 05 May 2020 21:52:54 UTC &gt;&gt;&gt; not exactly the same as lshr() <p>shr(x,n) and lshr(x,n) have always handled shift values outside the 0&hellip;31 range in a peculiar way: negative values of n are treated like n&amp;31, while values &ge; 32 always return 0 (or 0xffff.ffff for a signed shift).</p> <p>But now the new &gt;&gt;&gt; operator diverges from lshr by treating n &ge; 32 like n&amp;31, so we get:</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> 1 &gt;&gt; 32 = 0 shr(1,32) = 0 1 &gt;&gt;&gt; 32 = 1 lshr(1,32) = 0 </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p><em>edit</em>: same with &lt;&lt; which no longer behaves like shl()</p> https://www.lexaloffle.com/bbs/?tid=37712 https://www.lexaloffle.com/bbs/?tid=37712 Sat, 02 May 2020 13:43:57 UTC Encoding random data in the code section <p>Just a few things I thought I&rsquo;d share. Sorry if it&rsquo;s gibberish and/or uninteresting to most people.</p> <p>Many carts store extra data in the code section, most of the time inside strings. Some people will store structured data such as JSON or JSON-like data and let the PICO-8 compression mechanism deal with it, but you must have seen people who rolled their own compression mechanism and use custom formats such as modified base64 that takes advantage of the 59 &ldquo;good&rdquo; characters (i.e. the ones that needed only one byte of storage in the .p8.png format instead of two).</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> -- custom base64 data local data = &quot;e*!jfg57yfl+[7dmrin_bt#0/g6!1y68(.xh.ata_kn3j7!un_s+jn5..a)s8xi/ou0/{ff)ec}[&quot; </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Such base64 data encodes 6 bits of information per character, and requires an average of 8.625 bits per character on the old format cartridge (pre-0.2.0). It means that this &ldquo;alphabet&rdquo; gave us about <strong>5.565 bits of information per byte on the cartridge</strong> (8 * 6 / 8.625).</p> <p>The new compression format is now charset-agnostic; there is no reason to use custom encodings and favour those 59 characters. We can therefore use standard base64 as far as only storage is concerned (when thinking about decoder complexity, using a contiguous alphabet would be smart):</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> -- base64 local data = &quot;RpUpAUT80Jf6CQakfKLHz+1BSpUxFUYa/JDtdeAo4cyC1tHDx6gpazu0kdJqFdX+e4rMvfA+Ua0L&quot; </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>This data still encodes 6 bits of information per character, but now requires an average of 8 bits per character on the new format cartridge, giving us exactly <strong>6 bits of information per byte on the cartridge</strong> (better than the old compression method).</p> <p>So I wondered: what about other alphabets? (of more or less than 64 characters)</p> <p>Here are the theoretical results, assuming perfectly random data and ignoring the fact that the compression algorithm may emit back references:</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/14958/pico8-compression-efficiency.png" alt="" /> <p>Here are my conclusions:</p> <ul> <li>the new compression algorithm always outperforms the old one for random data</li> <li>starting from about 40, alphabet size no longer really matters (there are &ldquo;peaks&rdquo; around 48 and 112 but probably not worth exploiting)</li> </ul> <p>In a future post I will study the effect of the back reference emission (which are rare on random data but non-negligible with small alphabet sizes), but I&rsquo;ll wait for 0.2.0e to be out since Zep mentioned on Twitter that he fixed something in the compression.</p> https://www.lexaloffle.com/bbs/?tid=37694 https://www.lexaloffle.com/bbs/?tid=37694 Fri, 01 May 2020 07:03:31 UTC ! undocumented <p>Not really a bug, but I accidentally discovered that '!' now gets replaced with 'self' at runtime, except when followed by '=':</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> &gt; !ish = 42 &gt; ?selfish 42 </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>This is a bit confusing because in other languages, ! is an operator, whereas here it behaves almost like any other letter.</p> https://www.lexaloffle.com/bbs/?tid=37488 https://www.lexaloffle.com/bbs/?tid=37488 Mon, 20 Apr 2020 21:34:44 UTC PICO-8 plugin for Tiled <p>I made a tiny plugin that lets <a href="https://www.mapeditor.org">Tiled</a> load .p8 cartridges, edit the map section, and save them back without breaking the code or other sections. Works great for me, so I hope you may find it interesting!</p> <p>Available on GitHub: <a href="https://github.com/samhocevar/tiled-pico8">https://github.com/samhocevar/tiled-pico8</a></p> <p>Here is what it looks like with a dark theme and the grid color set to white:</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/14958/tiled-pico8.png" alt="" /> <p><strong>Update 2021/02/20</strong>: The plugin was ported to JavaScript for compatibility with all OSes. Requires a preview version of Tiled (1.5.0) for now.</p> https://www.lexaloffle.com/bbs/?tid=37431 https://www.lexaloffle.com/bbs/?tid=37431 Sat, 18 Apr 2020 16:44:27 UTC