abledbody [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=93379 Sound of Quicksort <p>A clone of <a href="https://panthema.net/2013/sound-of-sorting/">The Sound of Sorting</a> I made just to test and diagnose my QuickSort algorithm.<br /> It may sound a little ridiculous on web, since the array access sounds tend to get lumped together into far fewer frames.<br /> <table><tr><td> <a href="/bbs/?pid=148518#p"> <img src="/bbs/thumbs/pico64_sound_of_quicksort-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=148518#p"> sound_of_quicksort</a><br><br> by <a href="/bbs/?uid=93379"> abledbody</a> <br><br><br> <a href="/bbs/?pid=148518#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=142305 https://www.lexaloffle.com/bbs/?tid=142305 Fri, 17 May 2024 03:02:05 UTC The Lab Grows prototype <p>The response to this has been pretty positive, so I'm throwing this demo up here on the forums.<br /> This cart is a prototype for a point and click adventure with pre-rendered 3D graphics and a custom palette.<br /> <table><tr><td> <a href="/bbs/?pid=147629#p"> <img src="/bbs/thumbs/pico64_the_lab_grows-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=147629#p"> the_lab_grows</a><br><br> by <a href="/bbs/?uid=93379"> abledbody</a> <br><br><br> <a href="/bbs/?pid=147629#p"> [Click to Play]</a> </td></tr></table> <br /> Included in this cart are <a href="https://www.lexaloffle.com/bbs/?tid=140784">elgopher's require module</a> and <a href="https://www.lexaloffle.com/bbs/?pid=147383#p">snowkittykira's error explorer module</a></p> https://www.lexaloffle.com/bbs/?tid=142042 https://www.lexaloffle.com/bbs/?tid=142042 Wed, 01 May 2024 00:41:11 UTC abledbody's instrument pack 1 <p>32 synthesized instruments for your composing pleasure.</p> <p><code>#able_ipack_01-1</code></p> <img style="margin-bottom:16px" border=0 src="/media/93379/8_able_ipack_01.p64.png" alt="" /> <p>If you've got requests for the next instrument pack, let me know!</p> <p>Instrument names:<br /> <div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></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>00 - Wist 01 - Industrial Guitar 02 - Bell 03 - Industrial Bass 04 - Farout 05 - Closed Hat 06 - Open Hat 07 - Retro Snare 08 - Flat Kick 09 - Dial 10 - Glass Piano 11 - Flute 12 - Vibran 13 - Horn 14 - Grind Pad 15 - Smack Tom 16 - State Approved 17 - Disturbation 18 - Acoustic Snare 19 - Sweep Bass 20 - Bell 2 21 - Tropic Pan 22 - Funky Bass 23 - Crack 24 - Steel Guitar 25 - Saxophone 26 - Anchor 27 - Undercurrent Pad 28 - Sidestick 29 - Pop Bass 30 - Everywhere 31 - True Synth</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p></div></div></div></p> https://www.lexaloffle.com/bbs/?tid=141982 https://www.lexaloffle.com/bbs/?tid=141982 Fri, 26 Apr 2024 21:42:19 UTC able's ECS framework <p>I made it as easy to use and as performant as I could. You certainly won't be getting the performance boost normally associated with an ECS, since that particular optimization doesn't exist in picotron, but you'll still get the architecture.</p> <p>Here's a demo which showcases its use.<br /> <table><tr><td> <a href="/bbs/?pid=146516#p"> <img src="/bbs/thumbs/pico64_able_ecs-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=146516#p"> able_ecs</a><br><br> by <a href="/bbs/?uid=93379"> abledbody</a> <br><br><br> <a href="/bbs/?pid=146516#p"> [Click to Play]</a> </td></tr></table> </p> <p>You can find the latest version and the documentation on github.<br /> <a href="https://github.com/abledbody/picotron-ECS-framework/releases/">https://github.com/abledbody/picotron-ECS-framework/releases/</a><br /> <a href="https://github.com/abledbody/picotron-ECS-framework/blob/main/README.md">https://github.com/abledbody/picotron-ECS-framework/blob/main/README.md</a></p> https://www.lexaloffle.com/bbs/?tid=141689 https://www.lexaloffle.com/bbs/?tid=141689 Sat, 13 Apr 2024 04:37:05 UTC abledbody's Profiler <p>Does what it says on the tin. Lets you see what's eating up your CPU time. If you make an extension to this, I'd love to see it.</p> <h3>API:</h3> <p><code>profile.enabled(detailed,cpu)</code> Turns on and off profiling tools.<br /> <code>detailed</code>: Whether or not to display results of <code>profile</code> calls.<br /> <code>cpu</code>: Whether or not to display total CPU usage.</p> <p><code>profile(name,linger)</code> Starts or stops a profile. Accumulates between <code>profile.draw</code> calls. Extremely cheap when profiling is disabled.<br /> <code>name</code>: Arbitrary display name indicating which profile to start or stop.<br /> <code>linger</code>: Whether or not the profile should linger even if the profile is never called between draws.</p> <p><code>profile.draw()</code> Draws profile and CPU information to the screen if they are enabled. Extremely cheap when profiling is disabled.</p> <p><code>profile.clear_lingers()</code> Clears any lingering profile information.</p> <h3>Example:</h3> <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>include(&quot;profiler.lua&quot;) profile.enabled(true,true) local frames = 0 function _update() profile(&quot;_update&quot;) frames = frames+1 profile(&quot;_update&quot;) end function _draw() profile(&quot;_draw&quot;) if frames%2 == 0 then profile(&quot;displaying frame count&quot;,true) print(frames,80,0,7) profile(&quot;displaying frame count&quot;,true) end profile.draw() profile(&quot;_draw&quot;) end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <h2>Full script:</h2> <p><div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></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>--[[pod_format=&quot;raw&quot;,created=&quot;2024-04-09 22:52:04&quot;,modified=&quot;2024-04-11 17:26:16&quot;,revision=1003]] -- abledbody's profiler v1.1 local function do_nothing() end -- The metatable here is to make profile() possible. -- Why use a table at all? Because otherwise lua will try to cache the function call, -- which by default is do_nothing. local profile_meta = {__call = do_nothing} profile = {draw = do_nothing} setmetatable(profile,profile_meta) local running = {} -- All incomplete profiles -- All complete profiles. Note that if the profiles haven't been drawn yet, it will -- not be cleared, and further profiles of the same name will add to the usage metric. local profiles = {} -- All completed lingering profiles. These are never automatically cleared. local lingers = {} -- start_profile, stop_profile, and stop_linger are all internal functions, -- serving as paths for _profile to take. Lingers share start_profile. local function start_profile(name,linger) local source = profiles[name] running[name] = { linger = linger, } local active = running[name] active.start = stat(1) --Delaying CPU usage grab until the last possible second. end local function stop_profile(name,active,delta) local profile = profiles[name] if profile then profile.time = delta+profile.time else profiles[name] = { time = delta, name = name, } add(profiles,profiles[name]) end end local function stop_linger(name,active,delta) local profile = lingers[name] if profile then profile.time = profile.this_frame and delta+profile.time or delta profile.this_frame = true else lingers[name] = { time = delta, this_frame = true, } end end -- The main functionality lives here. -- Takes in the name of what you're profiling, and whether or not to -- make the profile linger. local function _profile(_,name,linger) local t = stat(1) local active = running[name] if active then local delta = t-active.start if active.linger then stop_linger(name,active,delta) else stop_profile(name,active,delta) end running[name] = nil else start_profile(name,linger) end end -- Clears all lingering profiles. function profile.clear_lingers() lingers = {} end local function draw_cpu() print(&quot;cpu:&quot;..string.sub(stat(1)*100,1,5)..&quot;%&quot;,1,1,7) end -- This draws the profiles, and then resets everything for the next frame. -- If it is not called, usage metrics will accumulate. -- Lingering profiles are always displayed after persistent profiles. local function display_profiles() local i = 1 for prof in all(profiles) do local usage = string.sub(prof.time*100,1,5)..&quot;%&quot; local to_print = prof.name..&quot;:&quot;..usage print(to_print,1,1+i*9,7) i = i+1 end for name,prof in pairs(lingers) do local usage = string.sub(prof.time*100,1,5)..&quot;%&quot; local to_print = name..(prof.this_frame and &quot;[X]:&quot; or &quot;[ ]:&quot;)..usage print(to_print,1,1+i*9,7) prof.this_frame = false i = i+1 end profiles = {} end local function display_both() draw_cpu() display_profiles() end -- This swaps out function calls depending on whether or not you want to have -- profiling. This is to make it as much as possible so that you don't have to -- think about cleaning up profile calls for efficiency. -- The first boolean is for detailed profiling, the second is for CPU usage. function profile.enabled(detailed,cpu) profile_meta.__call = detailed and _profile or do_nothing profile.draw = detailed and (cpu and display_both or display_profiles) or (cpu and draw_cpu or do_nothing) 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></div></div></div></p> https://www.lexaloffle.com/bbs/?tid=141662 https://www.lexaloffle.com/bbs/?tid=141662 Fri, 12 Apr 2024 04:30:18 UTC