asterick [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=10804 Updated 3D Engine <p> <table><tr><td> <a href="/bbs/?pid=57883#p"> <img src="/bbs/thumbs/pico57882.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=57883#p"> Updated 3D Engine</a><br><br> by <a href="/bbs/?uid=10804"> asterick</a> <br><br><br> <a href="/bbs/?pid=57883#p"> [Click to Play]</a> </td></tr></table> </p> <p>Working on a 3d engine to try to make a space game... This is the current iteration</p> https://www.lexaloffle.com/bbs/?tid=32061 https://www.lexaloffle.com/bbs/?tid=32061 Fri, 12 Oct 2018 21:53:17 UTC Old 3d cube engine I wrote <p> <table><tr><td> <a href="/bbs/?pid=57807#p"> <img src="/bbs/thumbs/pico57806.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=57807#p"> Old 3d cube engine I wrote</a><br><br> by <a href="/bbs/?uid=10804"> asterick</a> <br><br><br> <a href="/bbs/?pid=57807#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=32047 https://www.lexaloffle.com/bbs/?tid=32047 Wed, 10 Oct 2018 17:09:41 UTC Tri-color pattern dithering <p>I was experimenting with generating three-color pattern dither (2x2 matricies), and this is what I came up with. It's obviously too slow to use without building a dithering table (you could fit 4:5:4 color in the cartridge ram with cstore/restore), but I wanted to throw this out in the world incase someone else wanted to play with it.</p> <p> <table><tr><td> <a href="/bbs/?pid=18125#p"> <img src="/bbs/thumbs/pico18124.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=18125#p"> Tri-color pattern dithering</a><br><br> by <a href="/bbs/?uid=10804"> asterick</a> <br><br><br> <a href="/bbs/?pid=18125#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=2948 https://www.lexaloffle.com/bbs/?tid=2948 Sat, 02 Jan 2016 23:24:33 UTC Castlevania II: Game Over <p>I started translating a lot of the CV2 soundtrack to the Pico-8. This is one of the finished ones that I think turned out nice.</p> <p> <table><tr><td> <a href="/bbs/?pid=18034#p"> <img src="/bbs/thumbs/pico18033.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=18034#p"> Castlevania II: Game Over</a><br><br> by <a href="/bbs/?uid=10804"> asterick</a> <br><br><br> <a href="/bbs/?pid=18034#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=2931 https://www.lexaloffle.com/bbs/?tid=2931 Thu, 24 Dec 2015 20:55:14 UTC My utility functions <p>The more lua code I write in the pico-8, the more general purpose functions I wind up discovering. Here is my current utility library, I'll probably continue adding more as time progresses.</p> <p><strong>Quick sort</strong></p> <p>This one is pretty straight forward, you simply call it by providing a table and an optional comparator (for non-numeric lists), and it will in-place sort your table. It currently does not return anything, but it could me modified to return the table passed if you want to chain things.</p> <div> <div style="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> -- Inplace quick sort function qsort(tbl, cmp, first, last) first = first or 1 last = last or #tbl cmp = cmp or function (x,y) return x - y end if (first &gt;= last) then return end local pivot, pv, tail = first, tbl[pivot], last while pivot &lt; tail do local tv = tbl[tail] -- Tail is smaller than the pivot -- Shuffle things around if ( cmp(pv, tv) &gt; 0 ) then tbl[pivot], pivot = tv, pivot + 1 tbl[tail] = tbl[pivot] end tail = tail - 1 end tbl[pivot] = pv qsort(tbl, cmp, first, pivot - 1) qsort(tbl, cmp, pivot + 1, last) 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>Unpack is a useful function for converting a table into an argument list (similar to kargs in python), or assign a bunch of locals quickly:</p> <p>IE: local x, y, z = unpack(vector) or print(join(&quot;,&quot;, unpack(numbers)))</p> <div> <div style="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> -- Unpack table into spread values function unpack(y, i) i = i or 1 local g = y[i] if (g) return g, unpack(y, i + 1) 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>Enum does what you would expect, it's basically ipairs with an optional filter (in case you want to unpack the values, for example)</p> <div> <div style="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> -- Enumerate and potentially filter a table function enum(t, filter) local i = 0 filter = filter or function (v) return v end return function() local o = t[i] i += 1 if (o) return i, filter(o) 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>Join is my function for concatinating a list of arguments with a seperator. It's useful for displaying things like vectors.</p> <div> <div style="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> -- Join arguments by a seperator function join(a, b, ...) x = {...} for i = 1,#x do b = b .. a .. x[i] end return b 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=2872 https://www.lexaloffle.com/bbs/?tid=2872 Tue, 08 Dec 2015 15:05:15 UTC [Request] 16x16 draw color table <p>So, one of my favorite effects from the olden days was the ability to do glinting / pseudo transparency. Sadly, there is no way to do this in the PICO-8 due to cycle timing and memory issues. I would love to see the PAL call replaced with something that accepts three colors rather than two.</p> <p>something like: tpal c0 c1 c2, which would take all instances where c0 is drawn over c1 with c2. It would take 128 bytes of memory, but there is still plenty of headroom inside of the draw state structure to accommodate this.</p> https://www.lexaloffle.com/bbs/?tid=2448 https://www.lexaloffle.com/bbs/?tid=2448 Wed, 09 Sep 2015 17:33:52 UTC Getting past size limits: Hot-swapping <p>I don't know if anyone else has done a write up on this, but there is actually a pretty solid way to get around most of the data limits on the system, and it's kinda gross, and doesn't with the webplayer. The nice thing is that it gives you a legit file system, and basically limitless binary data!</p> <p>Here is a proof of concept, I created two files (this one is test.pb)</p> <div> <div style="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> CLS() PRINT(&quot;&quot;) PRINT(&quot;&quot;) RELOAD (0x6000, 0x4300, 128) LOAD (&quot;TEST2&quot;) RELOAD (0x6100, 0x4300, 128) FUNCTION _DRAW() END FUNCTION _UPDATE() 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>Test 2 contains nothing but garbage code that would crash the machine. </p> <p>The rational behind this is that:<br /> 1) If LOAD trashes execution, it would crash when the new program runs<br /> 2) If LOAD aborts the current thread, it would simply return to the prompt with TEST2 loaded<br /> 3) If LOAD doesn't allow shared state, it would copy the same thing out of the code area of the cartridge</p> <p>This test proves 3 things...</p> <p>1) RUN performs LUA compilation, so LOADing garbage data doesn't harm execution state<br /> 2) The existing machine state is preserved after a LOAD call, while altering the loaded filename and data stored with in the cartridge<br /> 3) Storage space is essentially limitless.</p> <p>Basic rundown of what happens with LOAD / RUN</p> <p>LOAD: Sets the active filename for the cartridge, loads the 32k cartridge into the cartridge buffer, and loads the first 0x4300 bytes into memory (tiles, maps, sounds and patterns)<br /> RUN: Disposes of existing Lua runtime state, discarding any global values, functions, etc, then parses and executes the code stored in the cartridge buffer.</p> <p>This also means that whatever is in ram at 0x4300~0x7FFF is PRESERVED BETWEEN RUNS. The only downside here is that LOAD will print garbage to the screen, so write to this area after you LOAD, but before you RUN the LOADed cartridge.</p> <p>So, if you want to get past the data storage limits, use a LOAD without running first.</p> <p>If you want to get past the CODE limits, store persistent data at 0x4300~0x7FFF and then RUN.</p> https://www.lexaloffle.com/bbs/?tid=2409 https://www.lexaloffle.com/bbs/?tid=2409 Thu, 03 Sep 2015 14:14:37 UTC Cartridge storage and code compression scheme <p>So, I've been spending quite a bit of time these last few days trying to figure out the innerworkings of the PICO-8, especially the cartridge storage and I've basically got everything figured out at this point. One thing I thought might be helpful is letting everyone get a glimpse into the compression format that is used inside of the .PNG format, so you can avoid hitting that pesky 32kB code wall!</p> <p>So, first I will start by breaking down the storage format for the current version of the .PNG. Note so far this has been a clean room RE, so if I'm duplicating anything that you already know, or has been described for you, just ignore me and move on.</p> <p>Cartridge data is stored in the 2 lowest bits of a color channel, so each color is 8-bits worth of data (1 byte). The channels are ordered (MSB to LSB) ARGB (this is not raw uint8 data order from the image container, so keep that in mind). The images are 160*205, giving you a theoretical size of 32800, although only 32769 bytes are used, Everything past this is discarded.</p> <div> <div style="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> 0x0000~0x42FF: Ram initalizer (simply copied to RAM on load, see manual memory map for details) 0x4300~0x7FFF: Code (version 0 is ASCII encoded, version 1 is 0x8000: File version </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 all fairly straight forward and should not surprise anyone. If the version is 1, it means the code is likely compressed and will follow the following format:</p> <div> <div style="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> 0x0~0x3: the string &quot;:c:\x00&quot; 0x4~0x5: length of code (decomressed, big-endian) 0x6~0x7: always zero (could be used for compression scheme in the future?) 0x8+: Compressed data </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Compressed data is an LZ like format, supporting a minimized character set so some text takes less space. It takes 8-bit codes to generate a chain of characters, this loops until the output data matches the value located in the header.</p> <p>The codes are as follows</p> <div> <div style="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> 0x00 xx: &quot;Extended&quot; code. The following byte is copied to the output stream 0x01: Emit a new line 0x02~0x3B: Maps to: &quot; 0123456789abcdefghijklmnopqrstuvwxyz!#%(){}[]&lt;&gt;+=/*:;.,~_&quot; 0x3C~0xFF xx: Copy from buffer </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>The 'copy' call copies N bytes from -X bytes from the end of the current stream.</p> <div> <div style="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> offset = (code - 0x3C) * 16 + (code2 &amp; 0xF); length = (code2 &gt;&gt; 4) + 2; </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>For a working example, this is what &quot;Hello hello&quot; would be encoded as.</p> <div> <div style="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> // Header &quot;3a&quot;, &quot;63&quot;, &quot;3a&quot;, &quot;0&quot;, &quot;0&quot;, &quot;b&quot;, &quot;0&quot;, &quot;0&quot;, // Encoded text &quot;0&quot;, &quot;48&quot;, // &quot;H&quot; &quot;11&quot;, &quot;18&quot;, &quot;18&quot;, &quot;1b&quot;, // &quot;ello&quot; &quot;2&quot;, // [space] &quot;14&quot;, // &quot;h&quot; &quot;3c&quot;, &quot;26&quot; // &quot;ello&quot;, 4 bytes copied from 6 bytes ago </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Note: There are no capital letters in the short form encoding, so don't ever use them in your program. Also the maximum number of characters that can be copied from a previous point in the stream is 17 characters, so try to keep your variable names below this threshold. Interestingly enough, minus signs are also not supported by the base character set.</p> https://www.lexaloffle.com/bbs/?tid=2400 https://www.lexaloffle.com/bbs/?tid=2400 Tue, 01 Sep 2015 23:48:52 UTC