Felice [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=12874 @zep: Devkit keyboard missing keys <p><a href="https://www.lexaloffle.com/bbs/?uid=1"> @zep</a></p> <p>I'm trying to write a tool that has text editing, and I find that the devkit keyboard doesn't return a lot of the special keys that it easily could.</p> <p>You're returning a string, so there's no reason why it has to be just one character. So pressing the Home key could simply return the string &quot;home&quot;. No need for special characters, escape sequences, etc., since these verbose names would all be distinct from any single regular typed character.</p> <p>I'm mainly thinking of the standard navigation cluster: up, down, left, right, ins, del, home, end, pgup, pgdn.</p> <p>It'd also be nice if there were a second stat() value that had a bitmask of the modifier keys that are currently pressed, if the host has them. Like, left/right shift, left/right alt/cmd, maybe left/right win/opt, altgr, maybe capslock. Not crucial, but definitely helpful. It'd be nice to be able to support things like ^Z for undo in my tool.</p> <p><strong>I say all this because one of the things I love about PICO-8 is working entirely <em>within</em> PICO-8, so it's nice to write tools that work inside of the platform, but the devkit functionality is a little limited in this department.</strong></p> https://www.lexaloffle.com/bbs/?tid=32982 https://www.lexaloffle.com/bbs/?tid=32982 Mon, 21 Jan 2019 11:38:45 UTC @zep: Inline code is broken <p><a href="https://www.lexaloffle.com/bbs/?uid=1"> @zep</a></p> <p>If I type this:</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>Look at my `inline code` please.</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 get this, which I'm just going to let the BBS handle, so it might look right to anyone reading this after it's fixed:</p> <p>Look at my <span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">inline code please.</p> <p>The second backtick isn't closing the inline code.</p> <p>As an aside, I personally would prefer it if inline code were simply a monospaced font, and not inverted as it is now. It makes using inline code very ugly and hard on the eyes. :/</p> <p>I do like the old-printer-paper code block format though. :)</p> https://www.lexaloffle.com/bbs/?tid=32501 https://www.lexaloffle.com/bbs/?tid=32501 Fri, 07 Dec 2018 14:05:09 UTC @zep: Still some BBS unicode issues? <p><a href="https://www.lexaloffle.com/bbs/?uid=1"> @zep</a></p> <p>I notice Benjamin Soul&eacute;'s username doesn't show up right, even after your emoji fix.</p> <p>See here:</p> <p><a href="https://lexaloffle.com/bbs/?tid=3421">https://lexaloffle.com/bbs/?tid=3421</a></p> <p>Looks like this at my end:</p> <img style="" border=0 src="https://www.lexaloffle.com/bbs/files/12874/benjamin.png" alt="" /> <p>It seems to work fine inside this post's text though.</p> <p>Edit: Yeah, there's some kind of encoding issue, not a font issue, because if I copy and paste it here, it still comes out &quot;Benjamin Soul´┐Ż&quot;, even though I was able to write it correctly above.</p> https://www.lexaloffle.com/bbs/?tid=32499 https://www.lexaloffle.com/bbs/?tid=32499 Fri, 07 Dec 2018 09:17:29 UTC Spinning valve for Johan <p>Re: <a href="https://twitter.com/johanpeitz/status/1024750757944410112">https://twitter.com/johanpeitz/status/1024750757944410112</a></p> <p> <table><tr><td> <a href="/bbs/?pid=54586#p"> <img src="/bbs/thumbs/pico54585.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=54586#p"> Untitled</a><br><br> by <a href="/bbs/?uid=12874"> Felice</a> <br><br><br> <a href="/bbs/?pid=54586#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=31589 https://www.lexaloffle.com/bbs/?tid=31589 Wed, 01 Aug 2018 20:25:09 UTC JSON vs LTN <p>I've seen a lot of threads where people talk about using mini JSON (JavaScript Object Notation) parsers, but there are always caveats about the differences betwen JS and Lua.</p> <p>I've prototyped a little parser for what I call LTN (Lua Table Notation, pronounced &quot;loot'n&quot;), which effectively gives you the ability to specify a Lua table's contents, in Lua source format, inside a string. For instance, if you had this:</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> player= { name=&quot;lone wanderer&quot;, desc=&quot;alone.\nwandering.\n&quot;, x=123, y=456, attrs= { str=5,per=3,edr=5,chr=3,int=4,agi=3,lck=4, hp=100,mp=20 } } </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>You could swap out the outer curlies for Lua's multi-line string braces (&quot;[[ ... ]]&quot;) and add a call to my parser, omitting the parens since it's a single string param and Lua lets you do that:</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> player=ltn [[ name=&quot;lone wanderer&quot;, desc=&quot;alone.\nwandering.\n&quot;, x=123, y=456, attrs= { str=5,per=3,edr=5,chr=3,int=4,agi=3,lck=4, hp=100,mp=20 } ]] </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 particular case saves 41 tokens.</p> <p>Problem is, Lua's a bit squidgy as a language, so parsing its format, even with the assumption that everything is cleanly formatted and with support for comments and &quot;[literal]=value&quot; notation not included, costs about 310 tokens. (It's about 350-390 tokens with those, if you need either/both of them, but I think most people wouldn't.)</p> <p>Would that be a decent quality-of-life tradeoff for anyone, allowing you just to swap Lua init code for a string representing it like that, but at the cost of 310+ tokens? It feels like a lot of tokens for a table parser, but on the other hand, sometimes you can afford to be a little spendy as long as it saves enough tokens overall AND saves you time reformatting the data.</p> <p>Should I work on this further to clean it up and make it worthy of release? Or nah?</p> <hr /> <p>Technical notes:</p> <p>One reason why my parser assumes everything is cleanly formatted is because you can test the formatting by swapping ltn[[]] back to {} and running it directly to test. I do have a version with error-checking, but again, it adds a lot of tokens to do that.</p> <p>Also, I could probably make it a little smaller if I removed the option to specify a simple array table like this:</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> count_to_five_array=ltn[[1,2,3,4,5]] </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Depends on whether a person needs to initialize arrays or just objects.</p> https://www.lexaloffle.com/bbs/?tid=31457 https://www.lexaloffle.com/bbs/?tid=31457 Tue, 26 Jun 2018 13:46:45 UTC @zep - Fix tabs in code textboxes <p>In the expandable textarea you get when you click <strong>Code</strong> under a cart, tabs are defaulting to 8 spaces, which is really ugly and rapidly pushes off of the right.</p> <p>I found info <a href="https://stackoverflow.com/questions/3379091/is-it-possible-to-change-width-of-tab-symbol-in-textarea">here</a> on how to fix it. If we assume that you're setting tabs to a default of 2 spaces in 0.1.12, then you'd want to do this for the code textarea:</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> style: -moz-tab-size: 2; -o-tab-size: 2; tab-size: 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>Because intarwebz haz standardz. I mean, look at that crap. Not just three versions, but two start with hyphens. WTF.</p> <p>You should also do this for the div surrounding [code]...[/code] regions of posts.</p> <p>PS: Remember also to <a href="https://www.lexaloffle.com/bbs/?tid=30603">fix the broken glyph translation in the textarea</a>.</p> https://www.lexaloffle.com/bbs/?tid=31399 https://www.lexaloffle.com/bbs/?tid=31399 Sat, 09 Jun 2018 16:36:57 UTC @zep - pal() <p>I've noticed that with palt() you can leave off the boolean argument and it will default to true, letting you say &quot;palt(11)&quot; if you want index 11 to be transparent. <em>Edit: Uh, turns out I was wrong about this, but the rest of this is still a good suggestion, and as I say below, it'd actually be nice if palt(x) <strong>did</strong> work this way as well.</em></p> <p>There's no equivalent for pal() though. If you leave off the second argument, it acts like you didn't give any arguments and resets the entire palette.</p> <p>Suggestion: It'd be nice if pal(x) simply acted like pal(x,x), a quick way to reset a single entry to default.</p> https://www.lexaloffle.com/bbs/?tid=31381 https://www.lexaloffle.com/bbs/?tid=31381 Tue, 05 Jun 2018 20:49:20 UTC @zep - Another quality-of-life request <p>(Hoping to catch you before you finalize 0.1.12)</p> <p>Similar to how I felt ceil() was missing from the fundamental math toolset in PICO-8, I feel like there are a couple of fundamentals missing from the table toolset.</p> <p>Would it be reasonable to add these to the built-in table operators?</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> function ins(table, index, elem) local temp = elem while temp ~= nil do table[index],temp = temp,table[index] index = index + 1 end return elem end function pop(table) local elem = table[#table] table[#table] = nil return elem end -- (and possibly this alias, just for the sake of being symmetrical with pop) push = add </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 that I was tempted to suggest an extension to add() where we simply append an optional index, but I've looked at the underlying code you have for add(), and I think the additional code to check for that optional index could slow down existing games too much, so it's probably better to have a new, bespoke ins() function instead.)</p> <p>With just these two (and a half) additions, it becomes much more intuitive and simple to use tables as stacks, queues, and sets. I think that would be a real boon to both budding and established programmers without really taking the API to a higher level of abstraction.</p> https://www.lexaloffle.com/bbs/?tid=31335 https://www.lexaloffle.com/bbs/?tid=31335 Sat, 26 May 2018 11:44:26 UTC @zep - fixed-point modulo bug at 0x8000 <p>I discovered tonight that the modulo (%) operator is treating the nadir value, 0x8000, as if it is positive, whereas other math ops treat it as negative:</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> &gt; ?0x7ffe/10 3276.6 &gt; ?0x7fff/10 3276.7 &gt; ?0x8000/10 -3276.8 &lt;-- as expected, -32768/10 == -3276.8 &gt; ?0x8001/10 -3276.7 &gt; ?0x8002/10 -3276.6 &gt; ?0x7ffe%10 6 &gt; ?0x7fff%10 7 &gt; ?0x8000%10 8 &lt;-- unexpected, -32768%10 should be 2 &gt; ?0x8001%10 3 &gt; ?0x8002%10 4 </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'm guessing this is an edge-case side effect of whatever you do to make modulo not flip directions at 0 (which I'm <em>very</em> glad you do).</p> https://www.lexaloffle.com/bbs/?tid=31286 https://www.lexaloffle.com/bbs/?tid=31286 Mon, 14 May 2018 14:57:09 UTC OpenSimplex noise generator demo <p>Cabledragon was talking to me about perlin and simplex noise generation, and we were looking at various web pages on the subject. One of them was a novel implementation of a simplex noise generator, written by Kurt Spencer, a game dev who did not wish to be subject to Perlin's patent on his own version of simplex noise:</p> <p><a href="http://uniblock.tumblr.com/post/97868843242/noise">http://uniblock.tumblr.com/post/97868843242/noise</a></p> <p>With a public-domain javascript implementation of 2D, 3D, and 4D noise here:</p> <p><a href="https://gist.github.com/kdotjpg/b1270127455a94ac5d19">https://gist.github.com/kdotjpg/b1270127455a94ac5d19</a></p> <p>The 3D and especially the 4D code is rather long and spaghettilike, though I suspect for good reason, but I noticed the 2D code was not too bad, really, so I took a pair of Lua shears to it and made it fit on our little platform.</p> <p>It performs pretty well. It looks good, and while you can't efficiently use it to set every pixel on your screen, it's quite adequate for caching your terrain at app launch, or even for real-time generation of the area immediately around you, if you can be somewhat economical with how many times you sample the noise.</p> <p>Note that, as mentioned in the code, the shell I wrote around this adaptation isn't particularly useful. It's just a custom-made and optimized-to-the-point-of-being-ugly viewer for the noise generator.</p> <p><span style="color: #ffaabb;"><strong>The generator code is on the second tab, and that's what you'll want to look at if you want to use it yourself.</strong></span></p> <p>Usage of the generator code is simple:</p> <p>os2d_noise(seed)</p> <ul> <li>Initializes the noise generator with the given seed. Different seeds produce different noise patterns.</li> </ul> <p>os2d_eval(x,y)</p> <ul> <li>Evaluate the noise pattern at x,y, returning a fraction between -1 and +1.</li> </ul> <p>Edit: It's probably worth noting that the noise repeats, cleanly, at the length of the seed array generated by os2d_noise(). For larger fields, you'd want to increase the size of the array and accommodate that by adjusting the index masking that's done when referencing the array. I might actually make this configurable at some point.</p> <hr /> <p><strong><em>Edit: Note that this demo is set up to show off the results as slickly as possible, not as a sample. If you want to see a sample usage case, where I also add multiple layers of noise for a more crinkly look, see a later comment below.</em></strong></p> <p>Here's the demo. Use &#11013;&#65039;/&#10145;&#65039; to change the seed, &#11014;&#65039;/&#11015;&#65039; to change zoom, &#10062; to cycle colors, &#127358;&#65039; for help. Note that it's slowly caching the zoomed images in the background, so zooming in quickly might produce some tearing at first.</p> <p> <table><tr><td> <a href="/bbs/?pid=52128#p"> <img src="/bbs/thumbs/pico52171.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=52128#p"> OpenSimplex noise generator demo v1.2</a><br><br> by <a href="/bbs/?uid=12874"> Felice</a> <br><br><br> <a href="/bbs/?pid=52128#p"> [Click to Play]</a> </td></tr></table> </p> <p>V1.1: Turned off color cycling due to a complaint and put a toggle on X.</p> <p>V1.2: Caching indicator, because communicating with the 0 users who run this is important!</p> https://www.lexaloffle.com/bbs/?tid=31201 https://www.lexaloffle.com/bbs/?tid=31201 Sun, 29 Apr 2018 05:16:06 UTC @zep - Bug with system menu suppression <p>So you've told us we can suppress the system pause menu with this:</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> poke(0x5f30,1) </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>And that works great. However, I wanted to write something that allows you to access both the game pause and the system pause, by using short presses for game pause and long presses for system pause. Unfortunately, there's a bug/misfeature/oversight that prevents this:</p> <p>You're still debouncing the button at the system level, even if the system menu is disabled, so if the button is held down, it's only reported down on the first frame. This prevents me from detecting a long press.</p> <p>I'm guessing this is just because you check the menu-suppression flag <em>after</em> you've recognized and absorbed the button press, rather than wrapping the button check as well.</p> <p>Any chance of a fix in the next version? :)</p> https://www.lexaloffle.com/bbs/?tid=31183 https://www.lexaloffle.com/bbs/?tid=31183 Wed, 25 Apr 2018 14:19:00 UTC @zep - request for 0.2+ <p>I seem to recall that you said you might break some elements of backwards-compatibility in 0.2. If so, I have a request. I'm not sure it'd even break anything, to be honest.</p> <p>Current PICO-8 executables allow the use of // instead of -- for comments. This has the unfortunate side effect of preventing us from using lua's // operator, which is the 'idiv' operator, e.g. <span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">a//b == <span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">flr(a/b).</p> <p>I have <em>never</em> seen anyone upload code that uses &quot;//&quot; comments, so I think it might not even break anything. You'd probably know better, since you presumably have all of the uploaded carts in some kind of database. If nothing else, maybe you could disable it based on the version number you added to files recently?</p> <p>It'd just be nice sometimes to use that operator, and if it's already supported but masked by the alternate comment form, I'd hope it wouldn't be a big chore to unmask it.</p> <p>Thanks...</p> https://www.lexaloffle.com/bbs/?tid=30971 https://www.lexaloffle.com/bbs/?tid=30971 Sun, 18 Mar 2018 16:21:38 UTC Shifting without using SHR()/SHL() calls <p>Converting shr() <em>safely</em> to simple math:</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> shr(v, 16) ==&gt; v * 0x.0001 shr(v, 15) ==&gt; v * 0x.0002 ... shr(v, 2) ==&gt; v * 0x.4000 (or 0.25) shr(v, 1) ==&gt; v * 0x.8000 (or 0.5) </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Multiplying by the fraction avoids a hazard where a negative number can go to 0 when dividing by numbers greater than 1, which destroys the sign-extending upper bits you expect to keep with shr().</p> <p>It also allows shifts up to 16, whereas dividing only allows shifts up to 14. This is because PICO-8 can't represent any powers of 2 larger then 16384.</p> <p>Similarly, because it <em>is</em> safe to divide by a fractional number <em>less</em> than 1, you can use the same idea to shift left up to 16 bits:</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> shl(v, 16) ==&gt; v / 0x.0001 shl(v, 15) ==&gt; v / 0x.0002 ... shl(v, 2) ==&gt; v / 0x.4000 (or 0.25) shl(v, 1) ==&gt; v / 0x.8000 (or 0.5) </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 this case, it's down to style or the need to shift by more than 14. Unlike dividing, multiplying by values greater than 1 is safe, so you can also obviously just convert shl(v,2) to v*4. PICO-8 performs divides as fast as multiplies, so performance is the same either way.</p> <p>Basically, your safe bet is always to use the fractional power of two, whether dividing or multiplying. If you want to be sure, start your constant with &quot;0x.&quot; and you'll always get it the right way around. :)</p> <p>The reason some of us want to do this, rather than the more-intuitive shift calls, is that it saves one token per shift. That can add up quickly in a program heavy with binary math.</p> https://www.lexaloffle.com/bbs/?tid=30904 https://www.lexaloffle.com/bbs/?tid=30904 Wed, 07 Mar 2018 08:10:08 UTC @dddaaannn - preprocessors, picotool, programming philosophy, pizza <p>On yonder thread, where you wisely noted we should stop polluting its subject, you responded to me and said:</p> <p><table style="width:100%" cellspacing=0 cellpadding=10><tr><td bgcolor=#404040><span style="color: #101010;"><span style="color: #ffffff;">Static preprocessors like cpp are a weird fit for dynamic languages like Lua. For example, cpp-style includes have no order-dependent side effects in the languages they're used for (other than in the preprocessor macro language itself, I think?), so they can more simply insert code at first mention. This is not the case in Lua. Lua modules make the handling of side effects in the code explicit, so there's no confusion as to what a require() is expected to do. I'm very interested to know why a Pico-8 developer would prefer an #include-like to a require() because I can't think of a reason, as long as require() is implemented correctly.</p> <p>Re: defines and such, I think what we actually want, especially in the context of Pico-8, is build-time constant folding and dead code elimination.</p> <p>But we should take build tool discussion somewhere else, so people can use this thread to discuss Compos. :)</span><br></span></td></tr></table></p> <p>Well, I'm a C/C++ programmer at heart, and while I've certainly warmed to a lot of the dynamic aspects of non-static languages like python and Lua, I'm also aware of a lot of the inherent costs that zep tends to hide from us. I like to adhere to practices that wouldn't be suicidal, perf-wise, in a normal context, so long as they aren't detrimental in this context.</p> <p>Abstraction and modularity have their uses, but when your resources are limited, sometimes they get in the way. The importance of being super flexible is only as important as the width of the path you're walking. Like, consider tweetcarts... a very narrow path, no use for flexibility, just have to walk the <em>exact</em> line the cart needs to walk, or you'll fall off.</p> <p>A lot of senior programmers are very quick to mutter about premature optimization, and they're right to, but I think there needs to be a lot more muttering about premature generalization. I said to someone recently that you don't create an object to represent every pixel, with a getter and a setter, so obviously there's a point somewhere between reading the user's input and putting pixels on the screen where you stop trying to create general, re-usable solutions and start making specific, one-off solutions that will work best in the context.</p> <p>Anyway, the most direct answer as to why I'd prefer an #include-like solution is that it simply has the least overhead in the final executable. I'm very good about being modular in terms of keeping things in separate files and independent, because I <em>do</em> like re-usability, but that means that there's a non-negligible token cost (as in dozens, easily) to having a function wrapped around every require()d file.</p> <p>Oh, and yeah, constant folding would be amazing, but I won't hold my breath for zep to add that. He's clearly not going to upgrade the lua engine embedded in PICO-8. I'd love to have far more than just the folding. Actual binary ops (rather than functions) would be awesome, among other things. But I don't see it happening. So I thought I'd hit you up for more stopgap measures. :)</p> <p>I also wish for something along the lines of inlining. Just the ability to express something as a function, when it should be a function, rather than having to manually inline it all over because each inlined instance is one or two tokens fewer than calling it, due to the simplicity of the function.</p> <p>Hm, think that covers it.</p> <p>BTW, I only put pizza in the title because I wanted another 'P' word. As it happens, I personally prefer pepperoni pizza.</p> https://www.lexaloffle.com/bbs/?tid=30897 https://www.lexaloffle.com/bbs/?tid=30897 Mon, 05 Mar 2018 14:35:24 UTC @zep - time() bug <p>Pretty sure when you originally added _update60(), you compensated for the doubled frame rate when returning time() values, but these days time() is running at double speed when you have _update60() instead of _update().</p> <p>I noticed this when playing with a simple seven-segment-display demo. Here's one that uses update() and updates once per second as expected:</p> <p> <table><tr><td> <a href="/bbs/?pid=49958#p"> <img src="/bbs/thumbs/pico49956.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=49958#p"> LED with _update()</a><br><br> by <a href="/bbs/?uid=12874"> Felice</a> <br><br><br> <a href="/bbs/?pid=49958#p"> [Click to Play]</a> </td></tr></table> </p> <p>And this is the same cart, but switched to _update60() and runs twice as fast:</p> <p> <table><tr><td> <a href="/bbs/?pid=49958#p"> <img src="/bbs/thumbs/pico49957.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=49958#p"> LED with _update60()</a><br><br> by <a href="/bbs/?uid=12874"> Felice</a> <br><br><br> <a href="/bbs/?pid=49958#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=30894 https://www.lexaloffle.com/bbs/?tid=30894 Mon, 05 Mar 2018 09:23:49 UTC Counting the set bits in a number <p>Adapting a solution found ca. page 180 of this white paper:</p> <p><a href="https://support.amd.com/TechDocs/25112.PDF">https://support.amd.com/TechDocs/25112.PDF</a></p> <p>I finagled it into this PICO-8-specific form, which counts every bit (including fractional bits) in constant and pretty-brief time:</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> function popcount(v) v-=band(v*.5,0x5555.5555) v=band(v,0x3333.3333)+band(v*.25,0x3333.3333) return band((band(v+v*.0625,0x0f0f.0f0f)*0x0101.0101)*256,255) 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>It's a bit uglier than it would be in C/C++, but it's mostly the same operations, with a minor adaptation for the 16-bit shifts inherent in 16.16 fixed-point multiplies.</p> <p>Just leaving it here in case anyone ever needs it.</p> <p>PS: Apparently it's commonly called &quot;popcount&quot; or &quot;popcnt&quot;, after an SSE instruction that does it. Basically, it's the population-of-1's count. Had no idea it had a name.</p> https://www.lexaloffle.com/bbs/?tid=30874 https://www.lexaloffle.com/bbs/?tid=30874 Fri, 02 Mar 2018 03:29:27 UTC Finally figured out what stat(2) is <p>It's system/kernel/gpu time. Basically, it's all of the CPU time spent in code you can't see directly in the PICO-8 source editor.</p> <p>If you have an app that does nothing but call cls() around 68 times, then both stat(1) and stat(2) will be around 1.0 at the end of your _draw() function.</p> <p>If you have an app with an empty loop that iterates around 69905 times, and does nothing else, then stat(1) will be around 1.0 at the end of your _draw() function, but stat(2) will still be close to 0.</p> <p>I can't believe it took me this long to work that out. :)</p> <p>Caveat: I don't know exactly where the system/user border lies. Like, I haven't looked to see if what we think of as intrinsics, like abs() or flr(), are system time for the few cycles you're inside, or if they're considered user mode. Similarly, longer functions like sqrt()... could be system, could be user. I'll probably go through and figure them out at some point.</p> <p>Honestly, it's not a very useful piece of information for practically anyone... even me... but it's been bugging me for aaaaages and I'm <em>so</em> glad I finally got a little 3-watt lightbulb over my head about it.</p> https://www.lexaloffle.com/bbs/?tid=30832 https://www.lexaloffle.com/bbs/?tid=30832 Sun, 25 Feb 2018 09:49:58 UTC A slightly faster way to clamp 0..n or min/max with 0 <p>So if you've been around for a while, you've probably discovered that the PICO-8 call <span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">mid(a,b,c) can be used for clamping values to a range. The middle value in a set of (lo,val,hi) once you put them in order will either be val if it's between lo and hi, or if it's beyond, either lo or hi will be the middle. That's a clamp.</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> -- change volume but keep it in range volume = mid(0, volume + volume_adj, 1) </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>It's convenient, if a little unintuitive. Some folks might alias the function to make it read better:</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> clamp = mid -- change volume but keep it in range volume = clamp(0, volume + volume_adj, 1) </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Problem is, it's three args and each arg slows you down a bit. In most cases, one end of the range is 0. If you're writing a really tight inner loop, sometimes it'd be nice if you just had a function that assumed 0 for the top or bottom, instead of you having to pass it.</p> <p>But wait! A useful bit of info is that PICO-8 API calls usually accept <span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">nil, or a missing arg, as if it were 0. For instance, <span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">x=cos() sets x to cos(0), or 1. Not useful for sin/cos, but...</p> <p>Since <span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">mid() doesn't care what order the arguments are in, we can just leave off the third argument to implicitly pass it a 0 that way:</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> -- change volume but keep it in range volume = mid(volume + volume_adj, 1) </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 cycle counters out there, mid() with two local variables passed as args costs 5 cycles, vs 6 cycles with three.</p> <p>And remember, it doesn't have to be the bottom end. If you're clamping -1..0, that works too:</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> -- change the decay rate decay = mid(-1, decay + decay_adj) </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Following on from this, if you know your value is moving towards 0, but must stop AT 0, then you can use the same trick with <span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">min() and <span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">max():</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> -- slow down until we stop (velocity==0) velocity = max(velocity - friction) -- swim back to the surface depth = min(depth + desperation) </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 both cases, you're implicitly passing a '0' as the second argument. This, again, saves you 1 cycle in each case, with single-arg min and max being 4 cycles instead of 5 for double-args.</p> https://www.lexaloffle.com/bbs/?tid=30830 https://www.lexaloffle.com/bbs/?tid=30830 Sun, 25 Feb 2018 05:46:36 UTC Esoteria: What to call PICO-8's angular units <p>So, while it might be inconvenient for use in proper math, I've really come to love tho 0-360&deg; &#8594; 0-1 units on PICO-8 for trig functions (sin, cos).</p> <p>I've never been sure what to call them, though. They're not degrees, they're not radians, they're not gradians, etc.</p> <p>I think I came up with a good name.</p> <p>A &quot;radian&quot; is called that because the angle is expressed as how many radiuses of a unit circle you have to move around that circle's circumference to get to the desired angle. Like, on a circle of any given radius, you have to literally move a distance of 2*pi radiuses around the circle to go a full 360&deg; and end up where you started. A radian is such a distance, but specifically on a circle of radius 1.</p> <p>So if a radian is an expression of how many radiuses we move around the circle, and PICO-8's units represent how much of the circumference (or how many circumferences) we've moved around the circle, then the unit should be named something to do with the circumference.</p> <p>&quot;Circumferans&quot; and &quot;circians&quot; don't really work for me. I also considered twopidians, but that's also kinda awkward.</p> <p>But then, I remembered my discovery of how much better it usually is to use <em>tau</em> in most trig math. Tau, if you don't know, is just another name for 2*pi. One tau is basically one trip around the circle. Tau usually produces cleaner math because it doesn't involve that pesky constant.</p> <p>(For more on tau, see this classic piece by Vi Hart: <a href="https://www.youtube.com/watch?v=jG7vhMMXagQ">https://www.youtube.com/watch?v=jG7vhMMXagQ</a>)</p> <p>Thus, I propose: <strong>taudians</strong></p> <p>I think it works. Feels okay, it's actually kinda cute, and it's literally a correct way to describe the unit.</p> <p>Thoughts? :)</p> <p>(<a href="https://www.lexaloffle.com/bbs/?uid=1"> @zep</a>?)</p> https://www.lexaloffle.com/bbs/?tid=30785 https://www.lexaloffle.com/bbs/?tid=30785 Fri, 16 Feb 2018 23:49:08 UTC @zep - quality of life request <p>Would you mind tweaking the token counter so that these two statements...</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> x = -1 y = 1 </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>...use the same number of tokens each?</p> <p>It's frustrating that we lose a token to the unary minus on number literals.</p> <p>I could rewrite that code with hex to save a token...</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> x = 0xffff y = 1 </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>...but that's ugly, non-portable code.</p> <p>Basically, just elide any unary minus token if it's being applied to a number literal.</p> <p>Please?</p> https://www.lexaloffle.com/bbs/?tid=30772 https://www.lexaloffle.com/bbs/?tid=30772 Tue, 13 Feb 2018 22:19:48 UTC