Kirsle.nethttps://www.kirsle.net2024-03-19T10:19:51ZNoahroot@kirsle.netDream Journal: Healthcare Robot2024-03-17T22:12:23Ztag:www.kirsle.net,2024-03-17:/dream-journal-healthcare-robot<p>I frequently have pretty vivid, detailed and crazy <a href"https://www.kirsle.net/tagged/Dreams" rel="nofollow">dreams</a> and when I have a particularly interesting one, I write it down in my dream journal. The one I awoke from this morning left such a strong impression on me that I also feel like sharing it here on my blog!</p>
<p>It involves artificial intelligence, humanoid robots and morally bankrupt billionaire corporations. I like to think I can tell a good story, so I hope you'll check this one out!</p>
<hr>
<p>So at the start of this dream, I had received a mysterious package in the mail. It was a medium sized box, maybe three feet tall, and had no return address but it was addressed to me, and it wasn't anything that I ordered myself.</p>
<p>Inside the box was a humanoid robot, covered in sleek white panels and looking like something that Apple might design. I powered it on, and it was able to speak with me in plain English and seemed to have a level of intelligence on par with ChatGPT. It had arms and legs and a robot face and everything. Presumably it could walk and move around as well. When it would enter an idle mode (maybe to recharge), it would "turtle up" and retreat into its shell, taking up less space in the room, a few feet tall. When standing, it was the size of a small adult human, maybe 5 feet tall or so.</p>
<blockquote>
<p><img src"https://www.kirsle.net/creativity/articles/dream-robot.jpg" alt="An A.I. generated image of what this sleek humanoid robot may have looked like. The photo depicts a robot covered with shiny white plastic, a blank white face, and arms and legs standing in front of a cyberpunk green circuit board background texture."></p>
<p><em>An A.I. generated image of what this robot may have looked like, created on <a href="https://deepai.org" rel="nofollow">deepai.org</a>.</em></p>
</blockquote>
<p>On a different day in this dream, I was hanging out in the living room and I had a couple of friends over, and the robot was in its idle pose nearby. Suddenly, the robot whirred to life, and panels on its body opened up, and then I can only describe that it 'attacked' me. Out of these panels, a bunch of wires shot out quickly, some with needles on the ends, which all found their way to my body. One such needle went into my arm, into a vein, reminiscient of when you are put on an IV drip at a hospital. I don't remember where the other wires landed.</p>
<p>The robot then injected me with something: tiny little machines. Some of them assembled themselves together inside my body, forming a larger disc shaped structure a couple of inches across, and I could see it move around under my skin and could feel it if I touched it. Most of the other tiny machines navigated their way through my veins, arteries and other ducts in my body.</p>
<p>I could <em>feel</em> all of these things moving around, and especially around my lower abdomen. I've never experienced having kidney stones before, but I imagine it could be similar, though instead of painful, the movement felt ticklish and highly sensitive, similar to post-orgasm sensitivity, as they worked their way around my body.</p>
<p>Naturally, I was freaking the fuck out, but I was also afraid to respond too violently to all of this in case I broke the robot and left its work in a half-complete state, which could result in a much worse outcome for me. My friends in the room with me were watching all this happen and they were shocked and didn't know what to do either.</p>
<p>During this time, the robot was unresponsive and didn't respond to any voice commands. It was in its idle pose, but clearly busy computing something, with lights on its chassis flashing and everything.</p>
<p>After no more than 10 minutes or so, the robot was done and it disengaged from my body, retracting all the wires and tools back into itself, closing its panels and then transforming into its humanoid social form to talk to me.</p>
<p>Of course, I asked it what the fuck just happened. It explained to me that it is a healthcare robot and it had just finished giving me an examination. It told me I had some plaque buildup in my arteries that it cleaned out for me, and that while my kidneys were in the range of normal healthy function, they were a bit on the lower end of that range (whatever that meant).</p>
<p>Naturally, I had a <em>whole</em> lot of questions. This robot was made from some highly sophisticated technology that I had never seen the likes of before.</p>
<p>I asked it who built it. The robot replied that it was created by a major multi-billion dollar pharmaceutical company. It told me the name of the company, though I don't remember it now.</p>
<p>I asked it why it was delivered to my house. It explained that the company who created it was facing some problems: they weren't cleared yet to begin human trials on the new technology, and they were facing fines or regulations and were at risk of going bankrupt or forced to shut down. They mailed these units out for free to random people as a way to circumvent the law, get some human test subjects, and (hopefully) prove that the machine is safe and effective. I was just one of the "lucky" ones who received one of these units.</p>
<p>I asked the robot whether I can opt-out of their test program, and the robot said I could not. In the room with us was a small figurine of Baymax from <em>Big Hero 6</em>. I picked it up and showed it to the robot and said: "in the movie <em>Big Hero 6</em>, they had healthcare robots and you could say to the robot 'I am satisfied with my care' and they will power down and stay that way" and the robot told me that that wouldn't work on it, and that it was designed for long-term active care.</p>
<p>I asked the robot whether I could tell people about all of this - I had a good mind to, at the very least, write about this experience on my blog. It strongly advised against me telling anybody about it. It didn't threaten me or tell me what would happen if I disobeyed, and I <em>know</em> I never signed a non-disclosure agreement about this, but given the highly advanced technology it had just displayed for me, I decided I would comply with it - at least for now. But I had found the whole thing highly sketchy and unethical and was beginning to contemplate what my next steps should be, before finally waking up from this dream.</p>
What is your favorite memory of Bot-Depot?2023-12-04T20:37:54Ztag:www.kirsle.net,2023-12-04:/what-is-your-favorite-memory-of-bot-depot<blockquote>
<p><strong>Anonymous</strong> asks:</p>
<p>What is your favorite memory of Bot-Depot?</p>
</blockquote>
<p>Oh, that's a name I haven't heard in a long time! I have many fond memories of Bot-Depot but one immediately jumped to mind which I'll write about below.</p>
<p>For some context for others: Bot-Depot was a forum site about chatbots that was most active somewhere in the range of the year 2002-08 or so, during what (I call) the "<a href"https://www.kirsle.net/rivescript-original-niche" rel="nofollow">first wave</a> of chatbots" (it was the first wave I lived through, anyway) - there was an active community of botmasters writing chatbots for the likes of AOL Instant Messenger, MSN Messenger, Yahoo! Messenger, and similar apps around that time (also ICQ, IRC, and anything else we could connect a bot to). The "second wave" was when Facebook Messenger, Microsoft Bot Platform, and so on came and left around the year 2016 or so.</p>
<p>My favorite memory about Bot-Depot was in how collaborative and innovative everyone was there: several of us had our own open source chatbot projects, which we'd release on the forum for others to download and use, and we'd learn from each other's code and make better and bigger chatbot programs. Some of my old chatbots have their code available at <a href="https://github.com/aichaos/graveyard" rel="nofollow">https://github.com/aichaos/graveyard</a>, with the Juggernaut and Leviathan bots being some of my biggest that were written at the height of the Bot-Depot craze. Many of those programs aren't very useful anymore, since all the instant messengers they connected to no longer exist, and hence I put them up on a git repo named "graveyard" for "where chatbots from 2004 go to die" to archive their code but not forget these projects.</p>
<p>Most of the bots on Bot-Depot were written in Perl, and one particular chatbot I found interesting (and learned a "mind blowing" trick I could apply to my own bots) was a program called Andromeda written by Eric256, because it laid down a really cool pattern for how we could better collaborate on "plugins" or "commands" for our bots.</p>
<p>Many of the Bot-Depot bots would use some kind of general reply engine (like my <a href="https://www.rivescript.com" rel="nofollow">RiveScript</a>), and they'd also have "commands" like you could type <code>/weather</code> or <code>/jokes</code> in a message and it would run some custom bit of Perl code to do something useful separately from the regular reply engine. Before Andromeda gave us a better idea how to manage these, commands were a little tedious to manage: we'd often put a <code>/help</code> or <code>/menu</code> command in our bots, where we'd manually write a list of commands to let the users know what's available, and if we added a new command we'd have to update our <code>/help</code> command to mention it there.</p>
<p>Perl is a dynamic language that can import new Perl code at runtime, so we'd usually have a "commands" folder on disk, and the bot would look in that folder and <code>require()</code> everything in there when it starts up, so adding a new command was as easy as dropping a new <code>.pl</code> file in that folder; but if we forgot to update the <code>/help</code> command, users wouldn't know about the new command. Most of the time, when you write a Perl module that you expect to be imported, you would end the module with a line of code like this:</p>
<p><div class="highlight"><pre><span></span><span class="mi">1</span><span class="p">;</span>
</pre></div>
</p>
<p>And that's because: in Perl when you write a statement like <code>require "./commands/help.pl";</code> Perl would load that code and expect the final statement of that code to be something truthy; if you forgot the "1;" at the end, Perl would throw an error saying it couldn't import the module because it didn't end in a truthy statement. So me and many others thought of the "1;" as just standard required boilerplate that you always needed when you want to import Perl modules into your program.</p>
<p>What the Andromeda bot showed us, though, is that you can use <em>other</em> 'truthy' objects in place of the "1;" <em>and</em> the calling program can get the value out of require(). So, Andromeda set down a pattern of having "self-documenting commands" where your command script might look something like:</p>
<p><div class="highlight"><pre><span></span><span class="c1"># The command function itself, e.g. for a "/random 100" command that would</span>
<span class="c1"># generate a random number between 0 and 100.</span>
<span class="k">sub</span> <span class="nf">random</span> <span class="p">{</span>
<span class="k">my</span> <span class="p">(</span><span class="nv">$bot</span><span class="p">,</span> <span class="nv">$username</span><span class="p">,</span> <span class="nv">$message</span><span class="p">)</span> <span class="o">=</span> <span class="nv">@_</span><span class="p">;</span>
<span class="k">my</span> <span class="nv">$result</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">rand</span><span class="p">(</span><span class="nv">$message</span><span class="p">));</span>
<span class="k">return</span> <span class="s">"Your random number is: $result"</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1"># Normally, the "1;" would go here so the script can be imported, but instead</span>
<span class="c1"># of the "1;" you could return a hash map that describes this command:</span>
<span class="p">{</span>
<span class="n">command</span> <span class="o">=></span> <span class="s">"/random"</span><span class="p">,</span>
<span class="n">usage</span> <span class="o">=></span> <span class="s">"/random [number]"</span><span class="p">,</span>
<span class="n">example</span> <span class="o">=></span> <span class="s">"/random 100"</span><span class="p">,</span>
<span class="n">description</span> <span class="o">=></span> <span class="s">"Pick a random number between 0 and the number you provide."</span><span class="p">,</span>
<span class="n">author</span> <span class="o">=></span> <span class="s">"Kirsle"</span><span class="p">,</span>
<span class="p">};</span>
</pre></div>
</p>
<p>The chatbot program, then, when it imports your folder full of commands, it would <em>collect</em> these self-documenting objects from the require statements, like</p>
<p><div class="highlight"><pre><span></span><span class="c1"># A hash map of commands to their descriptions</span>
<span class="k">my</span> <span class="nv">%commands</span> <span class="o">=</span> <span class="p">();</span>
<span class="c1"># Load all the command scripts from disk</span>
<span class="k">foreach</span> <span class="k">my</span> <span class="nv">$filename</span> <span class="p">(</span><span class="sr"><./commands/*.pl></span><span class="p">)</span> <span class="p">{</span>
<span class="k">my</span> <span class="nv">$info</span> <span class="o">=</span> <span class="k">require</span> <span class="nv">$filename</span><span class="p">;</span>
<span class="c1"># Store their descriptions related to the command itself</span>
<span class="nv">$commands</span><span class="p">{</span> <span class="nv">$info</span><span class="o">-></span><span class="p">{</span><span class="s">'command'</span><span class="p">}</span> <span class="p">}</span> <span class="o">=</span> <span class="nv">$info</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</p>
<p>And: now your <code>/help</code> or <code>/menu</code> command could be written to be dynamic, having it loop over all the loaded commands and <em>automatically</em> come up with the list of commands (with examples and descriptions) for the user. Then: to add a new command to your bot, all you do is drop the .pl file into the right folder and restart your bot and your <code>/help</code> command automatically tells a user about the new command!</p>
<p>For an example: in my Leviathan bot I had a "guess my number" game in the commands folder: <a href="https://github.com/aichaos/graveyard/blob/master/Leviathan/commands/games/guess.pl" rel="nofollow">https://github.com/aichaos/graveyard/blob/master/Leviathan/commands/games/guess.pl</a></p>
<p>Or a fortune cookie command: <a href="https://github.com/aichaos/graveyard/blob/master/Leviathan/commands/funstuff/fortune.pl" rel="nofollow">https://github.com/aichaos/graveyard/blob/master/Leviathan/commands/funstuff/fortune.pl</a></p>
<p>After we saw Andromeda set the pattern for self-documenting commands like this, I applied it to my own bots; members on Bot-Depot would pick one bot program or another that they liked, and then the community around that program would write their own commands and put them up for download and users could easily download and drop the .pl file into the right folder and easily add the command to their own bots!</p>
<p>I think there was some effort to make a common interface for commands so they could be shared between <em>types</em> of chatbot programs, too; but this level of collaboration and innovation on Bot-Depot is something I've rarely seen anywhere else since then.</p>
<p>We had also gone on to apply that pattern to instant messenger interfaces and chatbot brains, as well - so, Leviathan had a <a href="https://github.com/aichaos/graveyard/tree/master/Leviathan/brains" rel="nofollow">"brains" folder</a> which followed a similar pattern: it came with a lot of options for A.I. engine to power your bot's general responses with, including Chatbot::Alpha (the precursor to my <a href"https://www.kirsle.net/rivescript" rel="nofollow">RiveScript</a>), Chatbot::Eliza (an implementation of the classic 1970s <a href="https://en.wikipedia.org/wiki/ELIZA" rel="nofollow">ELIZA</a> bot), and a handful of other odds and ends - designed in a "pluggable", self-documenting way where somebody could contribute a new type of brain for Leviathan and users could just drop a .pl file into the right folder and use it immediately. Some of our bots had similar interfaces for the instant messengers (AIM, MSN, YMSG, etc.) - so if somebody wanted to add something new and esoteric, like a <a href="https://mystonline.com/forums/viewtopic.php?p=402386" rel="nofollow">CyanChat</a> client, they could do so in a way that it was easily shareable with other botmasters.</p>
<p>For more nostalgic reading, a long time ago I wrote a blog post about <a href="https://www.kirsle.net/smarterchild-and-other-aim-bots" rel="nofollow">SmarterChild and other AOL chatbots</a> from around this time. I was meaning to follow up with an article about MSN Messenger but had never gotten around to it!</p>
What we once had (at the height of the XMPP era of the Internet)2023-08-04T00:18:52Ztag:www.kirsle.net,2023-08-04:/what-we-once-had-at-the-height-of-the-xmpp-era-of-the-internet<p>A discussion thread I got pulled into on Mastodon had me suddenly nostalgic for something we once had on the Internet, and which was really nice while it lasted: the <strong>Extensible Messaging and Presence Protocol</strong>, or <a href="https://en.wikipedia.org/wiki/XMPP" rel="nofollow">XMPP</a>, or sometimes referred to by its original name, <strong>Jabber.</strong></p>
<p>What kicked off the discussion was somebody asking about a more modern "decentralized chat platform" known as <a href="https://matrix.org/" rel="nofollow">Matrix</a> (not the movie). A lot of people online talk about how they like Matrix, but I one time had a go at self-hosting my own Matrix node (which I feel I should rant about briefly, below), and the discussion turned back towards something that we used to have which was (in my opinion) <em>loads</em> better, XMPP.</p>
<p></p>
<h3><a name="my-experience-with-self-hosting-matrix" class="anchor" href="#my-experience-with-self-hosting-matrix" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
My experience with self-hosting Matrix</h3>
<p>So, to briefly summarize Matrix: <em>in theory</em> it is a decentralized instant messenger where anybody could set up their own Matrix server if they wanted to (on their own custom domain name), and regardless of which server your account is signed up on, you can chat with and interact with other Matrix users on their respective servers. It's a bit like <a href="https://joinmastodon.org" rel="nofollow">Mastodon</a> or the <a href="https://en.wikipedia.org/wiki/Fediverse" rel="nofollow">the Fediverse</a> of social <em>websites</em> but for instant messaging and chat.</p>
<p>Sounds great. Is it?</p>
<p>In my opinion (and based on my direct experience in trying to set up my own Matrix node, just for myself, on my @kirsle.net domain name), I think Matrix has a severe scaling problem and that you will <em>only</em> have a good experience using it if you stick <em>only</em> to the flagship <a href="https://matrix.org" rel="nofollow">matrix.org</a> instance for your account (or sign up on a third-party server run by somebody who has <strong>deep</strong> pockets for running the sort of monstrously beefy server machine that it requires to run a Matrix server well).</p>
<p>Here's my story with it. So, I have a smartphone that runs GNU/Linux, the <a href"https://www.kirsle.net/tagged/Pinephone" rel="nofollow">Pinephone</a>, and I basically wanted to use Discord or Slack on it. The problem is, there is no Discord or Slack app that runs on ARM Linux or on the small form-factor of a mobile phone screen. There <em>are</em> Matrix apps that fit the bill, and I heard that Matrix can set up <a href="https://matrix.org/ecosystem/bridges/" rel="nofollow">bridges</a> to Slack and Discord and a bunch of other useful things, to where I might use a Matrix client and (connecting through my server) get what I wanted out of my Pinephone.</p>
<p>But, you basically need to run <em>your own</em> Matrix server to do this. Not a problem: I am well versed in self-hosting apps. I elected to install the standard Matrix Synapse server on my kirsle.net machine (which had 4 GB RAM -- <em>plenty plenty</em> to run <em>nearly everything</em> that I would want to install for personal use). This was apparently a mistake.</p>
<p>So here's what happened: I got it all set up and I logged on using a desktop Matrix client and, like any new Matrix user would probably want to do, I joined "the" Matrix channel on <code>matrix.org#matrix</code> - the big, "main" channel that everybody would want to join. It would be a good test that my server federates correctly with matrix.org and everything as well.</p>
<p>And: my modest little web server <em>could not cope</em>. Apparently, the way Matrix federates between servers is that your server needs to <strong>download the entire world</strong> of <strong>all the chat history</strong> since <strong>the beginning of all time</strong> on that remote chat room. In my desktop client I was seeing spinning, timeouts, and connection errors. I only knew my server was busy doing <em>something</em> because I could watch its log file. Now, mind you, my Matrix server was only for myself, I was the only user on it. Imagine I had a second user, and their Matrix client is hanging and stalling and timing out, and <em>they don't know why</em> and what a sour taste they would get about this whole Matrix thing.</p>
<p>For me to run my own <em>single user</em> Matrix instance, <em>just for myself</em> and join the <code>matrix.org#matrix</code> channel (<em>the</em> channel), I would need at least twice the server hardware specs and that is just too high of a price tag for it to <em>ever</em> be worth it (e.g. $40/mo. at minimum, and that's <em>all</em> for Matrix, as any other app I run on that server would compete for those resources; and a $40/mo. "subscription" for a single-user Matrix instance is just absurd).</p>
<p>Anyway, let's move on to XMPP because that shit was actually <em>nice</em> to run.</p>
<h3><a name="what-xmpp-was-like" class="anchor" href="#what-xmpp-was-like" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
What XMPP was like</h3>
<p>So, XMPP was a similar idea. Anybody could run their own XMPP server and your username looked like an e-mail address and you could add your friends to your buddy list and chat, share files or go on webcam with each other (depending on the capabilities of each of your servers - XMPP was <em>extensible</em> after all and things like video sharing were extensions added on).</p>
<p>But the best part of XMPP was how well it played with the wider Internet community:</p>
<ul>
<li>Google Talk and Facebook Messenger both had XMPP bridges to their networks. From my @kirsle.net XMPP account I could add my friends @facebook.com to my buddy list and chat with them right from there, and same for Google Talk.</li>
<li>Like Matrix, XMPP had bridges to other instant messengers such as <abbr title="AOL Instant Messenger">AIM</abbr> and MSN. Now, back in the day we had desktop apps like Trillian or Pidgin that allowed you to sign on to <em>all your messengers</em> from a single buddy list, but XMPP bridges were done on the <em>server side</em>. So my Pidgin would log in <em>only</em> to my @kirsle.net XMPP server and I would automatically be on AIM, MSN, Yahoo! Messenger and elsewhere. When my AIM buddies would send me a message, their XMPP 'e-mail address' ended with an @aim.kirsle.net domain suffix under my server domain.</li>
</ul>
<p>Also importantly: XMPP server software ran <em>lightweight as fuck</em>. My favorite XMPP server software was called Openfire, and it has been <strong>by far</strong> the best experience I'd <em>ever</em> had installing any kind of server. I simply <code>apt install openfire</code> and it's running, and had a nice web UI for me to set up the admin account and configure my app. I literally had to not touch a single config file. Not at all like Matrix for example where I needed to configure my NGINX reverse proxy and fuck with a bunch of files on disk to get it working.</p>
<p>Anyway. XMPP still <em>technically</em> "exists" but nobody uses it anymore. Well, some companies use it for their own internal purposes. On Android, apps such as Kik and Grindr use XMPP for their messenger service, but their servers don't federate with others and act as private walled gardens.</p>
<p>Google and Facebook had <em>long ago</em> closed down their XMPP bridges in favor of holding their users hostage. AIM, MSN and other classic instant messengers no longer exist. It's a bit sad: if you look for XMPP server software today you still see references to AIM or MSN bridges but they won't work anymore, and bridges for more modern networks like Discord are either hard to find or non-existent.</p>
<p>In my opinion, the height of the open Internet was exemplified by XMPP and how it inter-operated with all the messengers people used and even the big sites like Google and Facebook were open to federating with XMPP servers. Nowadays, while you <em>could</em> still install an XMPP server (it is free and open source, and an open standard network protocol, and nothing about that has changed), you would be on a lonely island to yourself since <em>basically</em> nobody uses it anymore.</p>
<p>It's what Matrix <em>should</em> be, if only Matrix were better designed and didn't have that scalability problem that it currently faces.</p>
<p>You shouldn't require a monster server with 32 GB+ RAM and a 5 Terabyte hard drive just to run a Matrix node and have breathing room besides. I used to be able to run XMPP alongside a dozen other self-hosted apps. I <em>could</em> run XMPP alongside things like Nextcloud, Gitea, my kirsle.net blog, a Minecraft server, a Jellyfin server, and probably a dozen other apps who would all <em>comfortably</em> share a modest server with only 4 GB of memory on it. Hell, 2 GB would be plenty for most single-user self-hosting purposes, if you kick out the Minecraft server.</p>
<p>Anyway, I was just feeling nostalgic and sad about how there isn't anything <em>quite like</em> XMPP in the modern era and Matrix is <em>far, far</em> from it and I don't know of anything better than Matrix anymore.</p>
<p>I am optimistic recently about Mastodon and the Fediverse, with sites like Threads (Meta) or Tumblr (Automattic) considering federation with these apps via the ActivityPub protocol. We might get back to a more friendly, more open Internet again -- hopefully these companies won't pull another XMPP move and defederate again once they see a shot they can take to hold their users hostage again (the ol' reliable <a href="https://en.wikipedia.org/wiki/Embrace,_extend,_and_extinguish" rel="nofollow">EEE</a> strategy).</p>
Lucid dreams and exploring my consciousness2023-07-08T07:19:18Ztag:www.kirsle.net,2023-07-08:/lucid-dreams-and-exploring-my-consciousness<p>One of the many things I get <em>really</em> interested in is the nature of "reality" or at least the conscious parts of it (e.g. my <em>perception</em> of reality). The mind is such a curious and powerful thing -- like how none of us has ever actually 'seen' Objective Reality, because our brains are trapped in our dark skulls and all we <em>really</em> get are electrical signals sent by our eyes and other sensors. The brain then <em>makes up</em> all the stuff you see and call reality: a multimedia simulation based on what your brain <em>thinks</em> is going on out there in the world. We've all heard questions like "is my green, your red?" and how you'll never know for sure what somebody else sees in their reality.</p>
<p>In recent years I have been getting into meditation and really paying attention, really <em>studying</em> the way my mind works and I have found a few interesting things that I haven't seen talked about much online. I am currently suspicious that there is a connection between lucid dreaming, closed-eye visuals during wakeful consciousness, and the place in between the two: psychedelic visuals, which you can apparently just meditate your way into seeing, no entheogens required.</p>
<h3><a name="closed-eye-visuals" class="anchor" href="#closed-eye-visuals" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Closed eye visuals</h3>
<p>Let's start with the easy one. When I close my eyes and look into the darkness of my eyelids, I frequently will see some shapes and colors. From what I've heard from other people, this seems fairly common - you might see these too.</p>
<p>My regular closed-eye visuals tend to just be vague, formless blobs of color, maybe a blue blob here and a green one there. All kind of meandering around on their own, but very low resolution. Maybe they might vaguely form a face or some recognizable shape, but just loosely -- like seeing shapes in the clouds -- nothing very exciting.</p>
<p>But spoiler alert: they can get <em>much</em> more exciting.</p>
<h3><a name="closed-eye-visuals-when-i-wake-up-from-dreaming-are-intense" class="anchor" href="#closed-eye-visuals-when-i-wake-up-from-dreaming-are-intense" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Closed-eye visuals when I wake up from dreaming are INTENSE</h3>
<p>One night, I woke up from dreaming at maybe 3:00 in the morning (who knows), to get up and use the bathroom as one does. When I got back in bed I closed my eyes and I decided to <em>look for</em> my closed eye visuals (often if I'm not deliberately trying to see them, they go unnoticed by me and I think I just "see" blackness with my eyes closed).</p>
<p>I was expecting to see the usual amorphous blobs, but what I instead saw blew me away: my closed eye visuals (henceforth called <strong>CEVs</strong>) were breathtakingly sharp, vivid, colorful and <em>crisp</em>. I was seeing a colleidoscope of random images flashing before my eyes. It reminded me a lot of the Marvel movie opening logo. But every image I saw was just <em>so</em> crystal clear, with sharp lines and edges and vivid colors -- a far cry from the usual vague shapes my CEVs take on during the daytime.</p>
<p>I attribute this to the fact I had woken up from dreaming (REM sleep) and my brain was still close to that dream state. I have a suspicion that CEVs have a whole spectrum of forms they take: the vague blobbies is on one end of the spectrum, and full-color life-like hallucinations that we call "dreams" are at the opposite end.</p>
<p>And in between those two poles are other states that some people are familiar with.</p>
<h3><a name="i-learned-how-to-meditate-my-way-into-seeing-psychedelic-visuals" class="anchor" href="#i-learned-how-to-meditate-my-way-into-seeing-psychedelic-visuals" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
I learned how to meditate my way into seeing psychedelic visuals</h3>
<p>A couple of years ago, quite by accident, I managed to meditate my way into seeing psychedelic visuals over top of reality. And you can probably learn to do this, too. I will save you the long story (I <a href"https://www.kirsle.net/visual-perception-and-peeking-thru-the-veil" rel="nofollow">had written about it before</a> if curious) and cut straight to the chase -- here is how I've been able to consistently pull this off on command.</p>
<p>The trick is to just lock your eyes onto as fine a point as you can manage, and resist the urge to twitch your eyes even as your vision begins to play tricks on you. Many of you have probably experienced this much already: you know if you stare at a thing for too long, your vision plays tricks and things start disappearing or acting weird because of the sensory satiation, and darting your eyes will "reset" your vision to normal. But try and resist the urge to dart your eyes and just let your visuals do what they shall.</p>
<p>What happens next for me is: I will begin to see my <strong>closed eye visuals</strong> project themselves over top of reality, with my eyes open. The blobby, amorphous shapes I see with my eyes closed appear while they're open. But then my CEVs will begin to "play off of" or interact with my reality: where the border of one of the blobs touched a ridge on my ceiling that I was staring at, the ridge would wiggle or bounce back, as if my CEVs are interacting with it.</p>
<p>These visuals slowly ramp up and I'll begin seeing geometric patterns, fractals, <em>lots</em> of colors, and as these fractals interact with the scene I am staring at, they get <em>everything</em> to start wiggling and dancing. It can take me about 30 minutes into my meditation before I am seeing fully, 100% authentic, height of the strongest acid or mushroom trip I'd ever been on, visuals projected out onto whatever I was staring at during my meditation.</p>
<p>And when I've decided I had enough: I just look somewhere else and <em>snap!</em> everything is back in its place, in much the same way that darting your eyes during the earliest part of all of that "resets" your vision to normal.</p>
<h3><a name="i-have-recently-learned-how-to-continue-my-dreams-after-i-wake-up" class="anchor" href="#i-have-recently-learned-how-to-continue-my-dreams-after-i-wake-up" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
I have recently learned how to continue my dreams after I wake up</h3>
<p>Tell me if this sounds familiar: when I was a kid I would sometimes be woken up from a <em>really good dream</em> and wished I could have stayed in my dream a little bit longer to see how it ended. I could try and "make up" the ending myself, daydream how I think it might have gone, but it never felt right -- when you're in a dream, it's like your subconscious is telling you a story, and you can't quite predict what's going to come next. There's something magical about dreams that when I try and make up the ending myself, it doesn't come out right.</p>
<p>Well -- and I don't know exactly when this started, but it was in recent months at least -- I have somehow gained the ability to let my imagination wander freely and I can actually let my dreams finish themselves out, autonomously, after I wake up and I'll be fully aware I'm awake (and feel my body in bed, be able to hear my surroundings) but still <em>visually see and hear</em> the dream at the same time.</p>
<p>I attribute this to my practice with meditation -- I don't know of concrete steps that someone could try (not like my previous section) but I suspect the ability to "let go" of your mind, or to just watch it and not mess with it, was a feature here. I'll give you an example of what I mean.</p>
<p>A couple years ago I was reading some of Carl Jung and he talked about "active imagination" where he was able to visualize a scene in his head with characters in it, and then set his imagination free, and he could interrogate the characters and ask them questions and he would get responses from them that he couldn't predict (in very much the same way as dream characters). It's different to regular conscious daydreaming where you are controlling the dialogue of all the characters. It's more like when you are dreaming, and your dream characters talk to you and you can't quite predict what they're going to say because it's a different part of your mind that controls them: your subconscious.</p>
<p>After reading this I was trying, and failing, to do active imagination myself. I could set up the scene, and ask my characters a question, but I always felt like it was I who was dictating their responses -- I was just daydreaming consciously with myself. I haven't yet tried active imagination again, but this ability to let my subconscious wander and finish my dreams out seems to be very close to what I was thinking here.</p>
<h3><a name="lucid-dreaming" class="anchor" href="#lucid-dreaming" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Lucid dreaming</h3>
<p>There's already a <strong>lot</strong> of literature out there about lucid dreaming so I won't go too deep here.</p>
<p>Lucid dreaming is basically when you become aware that you're dreaming. You may be having some crazy dream about something nonsensical happening and have the epiphany: "oh shit, this is a dream!" and you can have a lot of fun with it. You can decide to change anything you want about the dream, or fly through the air like Superman, or summon specific dream characters that you want to talk to. I've had a good handful of lucid dreams in my life, but never very consistently. In many cases I'll realize I'm dreaming, and then just let my dream tell its story without meddling with it too much. I've found that if I meddle <em>too</em> much, my dream "gives up" on its story and just gives me all the controls, and it becomes a little bit less fun for me. I have "god mode" control but much less of the dream is unpredictable or surprising then (though my dream characters are still unpredictable in what they say).</p>
<p>From talking to my dream characters and asking them deep and personal questions about myself, and getting surprising answers back from them, I am suspicious that talking to a dream character is the same as talking directly to my inner subconscious, in plain English.</p>
<h3><a name="that-s-all-for-now" class="anchor" href="#that-s-all-for-now" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
That's all for now!</h3>
<p>Just thought I'd jot down some of my latest findings. I have told some friends about these and some of them have experienced similar things, if not to the same extent I have yet. I hope this may have sparked your curiosity and if others may be able to reproduce some of my findings themselves.</p>
<p>I have more posts like this on my <a href"https://www.kirsle.net/tagged/42" rel="nofollow">#42</a> blog tag where I write about life, the universe, and everything. It's a lot of stuff about consciousness and occasionally spiritual stuff (the two have many likes alike, and all the characters and archetypes that Jung says are in our consciousness have mirrors in religious figures from all cultures which I also find very fascinating!)</p>
Is Safari the new Internet Explorer - or worse?2023-03-30T21:19:55Ztag:www.kirsle.net,2023-03-30:/is-safari-the-new-internet-explorer-or-worse<p>So I haven't posted a good rant on my blog in quite some time - I had chilled out a lot in my older years, but I just have to tell this story about Safari and my struggles in getting it to work <a href"https://www.kirsle.net/an-open-source-video-chat-room" rel="nofollow">with my chat room</a> I had built recently.</p>
<p>My chat room is a fairly basic app - it's <a href="https://github.com/kirsle/BareRTC" rel="nofollow">open source</a> and written "from scratch" using WebSockets to handle the client/server communication and they pass basic JSON messages around. All fairly standard stuff and shouldn't be a big ask for any modern web browser that supports modern web standards. It works flawlessly in Google Chrome as well as <em>all</em> other Chromium derivatives (including Edge, Brave, etc.), and it works flawlessly on Firefox, and when you run either browser on your Windows, Linux or Mac OS computer. It even works great on all Androids, too - using Chromium or Firefox browser engines.</p>
<p>But then there's Safari. Safari "supports" WebSockets but it doesn't do so <em>very well</em> and I've been fighting this for weeks now trying to chip away at this problem. Both when you run Safari on your Mac OS Ventura desktop or on your iPhone or iPad, Safari is <em>very easy</em> to overwhelm and it will disconnect from the chat room at the slightest hiccup of an issue.</p>
<p>My rant here actually is about three different problems that have made my life difficult trying to get Safari to work:</p>
<ol>
<li>The way that Safari just has to "do things differently" and have kneecapped limitations and quirky bugs that Chrome and Firefox don't experience at all.</li>
<li>The way that <strong>all web browsers on iOS are really just Safari</strong> and so iPhones and iPads simply <em>can not</em> use my chat room regardless of browser.</li>
<li>The way Apple designed their closed ecosystem where, if I want to debug this on iOS and see <em>what kind of error message Safari is even throwing</em>, I am required to purchase an iPad + a Macbook because only Apple's hardware can do iOS development and pair with one another (where by comparison, I can debug an Android browser using any kind of PC I want).</li>
</ol>
<h3><a name="safari-and-websockets-protocol-errors" class="anchor" href="#safari-and-websockets-protocol-errors" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Safari and WebSockets: "Protocol errors"</h3>
<p>I don't own a Macbook or an iOS device and so would have no way to even debug or look into this problem, but at least there is an option to run Mac OS inside of a virtual machine (using something like <a href="https://github.com/kholia/OSX-KVM" rel="nofollow">OSX-KVM</a>) so <em>at least</em> I can look into the desktop Safari browser and see what its deal is.</p>
<p>First - here is how my chat basically works: you connect, send your username to log in, the chat tells everyone you joined, sends everyone the new Who's Online roster, and sends some "welcome messages" to the one who joined where I can send my rules or new feature announcements to you.</p>
<p>What I would see when a Safari user logged in was: they'd connect, log in, receive all those welcome messages and then they would <em>immediately</em> hangup the connection and log off. On their side, the web browser gives a very unhelpful error message regarding the WebSocket:</p>
<blockquote>
<p>Protocol error.</p>
</blockquote>
<p>That's it - it doesn't say what the error was. Even when I have a Safari browser in front of me, they give me no help at all to find out what's wrong!</p>
<p>Through trial and error, I found out:</p>
<ul>
<li>If I remove all the welcome messages (to reduce the noise I send to Safari on join), it was able to log in to chat OK and send and receive messages!</li>
<li>From more poking, I found that <strong>there seems to be a length limitation!?</strong> And I'm not even talking about huge messages either - if I just type about 500 characters of text and send it, Safari will immediately disconnect with "Protocol error"!</li>
<li>So I also root caused: in those welcome messages, where I listed some rules or new features, those messages were "too long" for Safari and scared it away!</li>
</ul>
<p>...and that kind of <strong>thoroughly sucks.</strong> I can remove all the welcome messages so as to allow Safari to <em>at least</em> log on, but then just one user posting a paragraph of text will kick all the Safari users out of the chat room!</p>
<p>Chrome and Firefox don't experience this issue. A while ago I added picture sharing in chat - you send your picture over WebSocket and it echoes it as a <code>data:</code> URL to all the chatters, passing those bytes directly back out; Firefox and Chrome can cope with this perfectly, but that would <strong>for sure</strong> kick Safari users off for too long of a message!</p>
<h3><a name="all-web-browsers-on-ios-are-safari" class="anchor" href="#all-web-browsers-on-ios-are-safari" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
All web browsers on iOS are Safari</h3>
<p>So, when it comes to Mac OS users I can tell them: Chrome and Firefox work better. But this advice does not fly on iPads or iPhones because, per Apple's rules, web browsers on iOS are not allowed to bring their own browser engines - they all are just custom wrappers around Mobile Safari.</p>
<p>And you guessed it: Mobile Safari doesn't like my WebSockets either!</p>
<p>I am hoping that with EU pressure placed on Apple to where they will allow competing browser engines to join their platform, that at least some of my iOS users will have <strong>a way</strong> to use my chat room. But how it stands currently is: iPads and iPhones simply can't use my chat room at all, or if they can get on (maybe it's the "too long of message" issue with them as well), they will be fragile and easy to boot offline just by writing too long of a message.</p>
<p>Apple will not innovate on Safari and make it support modern web standards, and they've made sure that <strong>nobody else can innovate either.</strong> The Blink engine from Chromium and Gecko from Firefox both work great with WebSockets and if only they were allowed to exist in their true forms on Apple mobiles, I wouldn't be ranting about this right now, I could just say "don't use Safari."</p>
<p>And side rant: the reason Apple won't allow Chrome or Firefox to compete with them is because they are <em>scared shitless</em> about <a href="https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps" rel="nofollow">Progressive Web Apps</a>, which could compete with their native app store. They won't innovate on Safari at all until their feet are held to the fire (thanks for that as well, EU!), their web browser sucks (as this WebSockets thing illustrates), they're holding everybody back - the new Internet Explorer 6.0!</p>
<h3><a name="vendor-lock-in-means-i-can-t-even-debug-this-properly" class="anchor" href="#vendor-lock-in-means-i-can-t-even-debug-this-properly" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Vendor lock-in means I can't even debug this properly</h3>
<p>Even if I owned an iPad, it wouldn't help - you can't get to the browser logs on an iPad browser to even see what kind of error message it's throwing. Though I imagine the error message would be <em>just as helpful</em> as desktop Safari, anyway: "Protocol error."</p>
<p>In order to get logs off an iOS web browser, you need to pair it with a Macbook computer -- the only kind of device that is allowed to run the iOS development kits and is the <em>only way</em> to debug anything that happens on your iPad.</p>
<p>With Mac OS, at least there is <em>a way</em> I can spin up a virtual machine and get my hands on Safari. There is no way to do this for iOS. There's no virtual machine where I can run the genuine Mobile Safari app and have a look at this issue myself. I wish Apple weren't so closed in their ecosystem - comparing it to Android for example, you can debug an Android app using any kind of computer: Windows, Linux, Mac OS, even another Android, even on-device on the same Android.</p>
<p>I am not an iOS developer, I don't care to be an iOS developer, and I don't own any Apple hardware, and it really sucks when I run into a <strong>web app issue</strong> that should have <em>nothing to do with</em> Apple specific software, and I simply can not even get in and look at the error messages.</p>
<p>I'd been chipping away at this for weeks, basically <strong>blindly</strong> trying things and throwing shit at the walls and hoping one of my Apple using friends tries my chat room once in a while to see if any of my efforts have worked (spoiler: they haven't worked).</p>
<p>I've also tried reaching out to developers on Mastodon and other social media: my chat room is open source, could somebody with Apple hardware help me debug and see if they can find out what I can do better to get Safari to like my chat room. Maybe I didn't reach the right ears because I've gotten only crickets in response. Meanwhile about a third of my users still can not get onto my chat room at all.</p>
<p>Where I've landed so far is: it seems Safari can connect, but that < 500 character limit issue seems horribly broken and I don't want Safari users getting kicked off left and right by surprise, it's a bad user experience.</p>
<h3><a name="maybe-i-ll-just-wait-until-chrome-and-firefox-can-come-to-ios-properly" class="anchor" href="#maybe-i-ll-just-wait-until-chrome-and-firefox-can-come-to-ios-properly" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Maybe I'll just wait until Chrome and Firefox can come to iOS properly</h3>
<p>If I wait it out long enough (and if the EU is successful), Apple <a href="https://9to5mac.com/2023/02/07/new-iphone-browsers/" rel="nofollow">may permit actually good web browser engines</a> on their platform and then my chat will work perfectly on them. It may just take a couple of years though - first Apple would have to be successfully sued into submission, and then Google/Mozilla would have to port their browser engines over which could be its own long tail of development work.</p>
<p>Maybe as a consequence of that regulation, Apple will <em>actually</em> put some new work into Safari instead of just neglecting it and they'll fix their shit. Currently it seems like my WebSocket messages need to be smaller than a tweet on Twitter, and it honestly won't be worth all the effort it would take me to reimagine my whole chat room and come up with a clever protocol to break messages apart into tiny bite sized chunks when it's only <strong>one</strong>, non-standards compliant web browser, which drags its stick thru the mud as badly as Internet Explorer ever did, that has the issue here.</p>
<p>So are they the new Internet Explorer, or somehow even worse?</p>
<hr>
<p><small>I have sometimes had people visit my blog because they were Googling around in general about Apple and they like to fight me in the comments because I dissed their favorite brand. If this is you, at least say something constructive in the comments: have you ever built a WebSockets app and do you have experience to share in how to get Safari to behave? If you're simply an end user fanboy and never installed Xcode in your life, save your comments, please.</small></p>
BotW Save Hacking Question2023-02-13T21:15:11Ztag:www.kirsle.net,2023-02-13:/ask-20230213211436<blockquote>
<p><strong>Cardell</strong> asks:</p>
<p>So this is related to <a href"https://www.kirsle.net/breath-of-the-wild-save-hacking" rel="nofollow">The Breath of the Wild save hacking</a>. I play on the Yuzu emulator now. I just want the Mster Cycle earlyish and fresh vanilla game.
Have found a save file editor but it doesn't let you add runes so I can't get the cycle.
How did you add it to your save files on the blog?
I'm sorry to bother you with something so insignificant but what I'm trying to do is so niche I can't find anything lol</p>
</blockquote>
<p>I'm not sure about the Switch version but may have some ideas to get you started.</p>
<p>The <a href="https://www.marcrobledo.com/savegame-editors/zelda-botw/" rel="nofollow">savegame editor</a> I used may be for the WiiU only and it provided a simple "Motorcycle" checkbox that adds the rune. If the Switch save editor doesn't do that, but does give you 'advanced' access to the various game flags, maybe setting the flag <code>IsGet_Obj_Motorcycle</code> may do it - the flag is set in my WiiU save files. Or otherwise browse and search around in the flags - there are a lot of them that control all sorts of features in the game, and sometimes they have uintuitive names (IsGet_Obj_RemoteBomb does the bomb rune, IsGet_Obj_StopTimer is the stasis rune, IsGet_Obj_Magnetglove is the magnesis rune, IsGet_Obj_IceMaker for cryonis).</p>
<p>There is also a caveat around runes at all when you're talking <em>very</em> early game: you can hack all these runes in to your profile, but you can't <em>use</em> them in-game until you have picked up a rune yourself. The D-pad shortcut doesn't work otherwise. What I did for my WiiU save files was to:</p>
<ol>
<li>Mod my game to add all runes + motorcycle + paraglider so I could leave the Plateau immediately.</li>
<li>Do the main quests in Kakariko and Hateno Village until I get the Camera rune from Pura.</li>
</ol>
<p>With the Camera rune added, the D-pad shortcut unlocks and I can now use <em>all</em> of the runes, including the motorcycle, despite never entering one of the Plateau tutorial shrines. (Doing those tutorial shrines would also unlock your rune ability - you just need a rune added "normally" for the tutorial to advance enough to let you use them!)</p>
<p>Good luck!</p>
Error Message Generator 2.02023-01-22T21:00:32Ztag:www.kirsle.net,2023-01-22:/error-message-generator-2-0<p>I have just released a new toy program on my website: <a href"https://www.kirsle.net/errorgen" rel="nofollow"><strong>Error Message Generator 2.0</strong></a>, or <strong>ErrorGen</strong> for short.</p>
<p>ErrorGen is a simple program that lets a user configure customized error dialog pop-ups, with a custom icon, message and buttons, to prank their friends with or to put to good use by shell scripts if you want to ask the user a quick question from your external program.</p>
<p>My <a href"https://www.kirsle.net/errorgen-classic" rel="nofollow">original ErrorGen</a> was inspired by a web tool called "Atom Smasher's Error Message Generator" which would produce images of error dialogs that you could save to disk. My program, however, created "real" dialogs on your desktop PC that you could drag around the screen and interact with. The original version was written using Perl/Tk in 2006 and hasn't been updated a lot since - with the latest release built in 2008 for Windows XP and it hasn't aged well and doesn't run as easily on modern Windows anymore.</p>
<p>In 2022, Atom Smasher's page <a href="https://www.reddit.com/r/windowsxp/comments/wb04ft/rip_atom_smasher_error_generator/" rel="nofollow">went offline</a> and I have seen an uptick of interest in my old ErrorGen program ever since: it is recently the #1 most requested page on my website!</p>
<p>So, on January 21, 2023 I decided to reinvent my ErrorGen program from scratch, this time programming it in <a href="https://golang.org" rel="nofollow">Go</a> and to explore the <a href="https://fyne.io" rel="nofollow">Fyne UI toolkit</a> which I had seen around but hadn't played with before. ErrorGen 2.0 has equivalent features to what my original Perl version had, but with a fresh and modern look based on Material Design that comes with Fyne and built for the modern era. I also have some plans to extend ErrorGen 2.0 with new features and especially make it more useful for command line interfaces, to make something on par with GNOME's <a href="https://help.gnome.org/users/zenity/stable/" rel="nofollow">Zenity</a> tool.</p>
<p><img src"https://www.kirsle.net/projects/ErrorGen2/screenshot.png" alt="Screenshot of ErrorGen 2.0"></p>
<p>You can check out the new ErrorGen on my <a href"https://www.kirsle.net/errorgen" rel="nofollow">Error Message Generator</a> page. The classic Perl version from 2006 is still available <a href"https://www.kirsle.net/errorgen-classic" rel="nofollow">here</a> if you want it.</p>
Is ZenMsg a virus?2023-01-02T01:27:48Ztag:www.kirsle.net,2023-01-02:/is-zenmsg-a-virus<blockquote>
<p><strong>Is Zenmsg a virus?</strong> asks:</p>
<p>It only opened a command box, and nothing else happened. Is this a virus?</p>
</blockquote>
<p>No, it's not. 😊 <a href"https://www.kirsle.net/errorgen" rel="nofollow">ZenMsg</a> is a command-line program (so it opens your DOS prompt if double-clicked on), but it requires command-line options to tell it what to do. When run without any options, it prints its usage information to the terminal and then exits; so when double-clicked on, your DOS prompt appeared and then closed because ZenMsg exited.</p>
<p>You'll want to run it from a PowerShell or Command Prompt window first (so that the console sticks around after the program exits), and you can see it just prints its usage information:</p>
<pre><code>C:\Users\Noah\Downloads> ZenMsg.exe
Usage:
ZenMsg [--error --alert --info --question]
[--title] [--text] [--button label]
[--icon name_or_file]
[--default label] [--cancel label]
[--disabled n]
[--version] [--help]
Use the "--help" option for more help.
(and it goes into detail on all the options)
</code></pre>
<p>If you call it with <code>ZenMsg --help</code> it goes into full detail (the same documentation that's in the ZenMsg.html page the program ships with), including all the names of built-in icons. Every icon available on the <a href"https://www.kirsle.net/errorgen" rel="nofollow">Error Message Generator</a> is built in to ZenMsg, and you can point it to a custom image on disk to use your own icon:</p>
<pre><code>BUILT-IN ICONS
Here is a list of all the built-in icons that you can use by name:
aim_guy - Blue AIM guy icon
aol_icon - Blue AOL icon
attention - Yellow triangle around an exclamation mark
bomb - Round black bomb icon
bomb_dynamite - Icon of a bundle of dynamite and a trigger
bomb_grenade - Icon of a grenade
bulb - White light bulb
butterfly - MSN Butterfly icon
cake - Slice of pink cake on a blue plate
circularsaw - Icon of a handheld circular saw
control_panel - Generic control panel icon
cow - Icon of a cow and a computer tower
defrag - Disk Defragmenter icon
disk_blue - Generic blue floppy disk icon
disk_blue_label - Blue floppy disk with a label
disk_orange - Generic orange floppy disk
disk_red - Generic red floppy disk
disk_red_label - Red floppy disk with a label
disk_skull - Gray floppy disk with skull and crossbones
disk_yellow - Generic yellow floppy disk
error - Old-school X in a red circle error dialog icon
error2 - Modern, shiny incarnation of an error dialog icon
error3 - Beveled error dialog icon (like Windows XP)
error4 - A red X icon
file_cabinet - File cabinet icon
find - Find Files icon
floppy_drive - Generic floppy drive icon
fortunecookie - Icon of a fortune cookie
garbage_empty - Empty garbage can
garbage_full - Bloated garabage can
gun - Icon of a revolver pistol
hammer - Icon of a hammer
heart - Icon of a shiny red heart
help - Old-school Windows Help icon
hub - Icon of a hardware hub of sorts (networking?)
hwinfo - Icon of a PCI device with blue "i" bubble above it
ie5 - Icon of old-school Internet Explorer
info - Speech bubble with an "i" inside
keys - Generic icon of keys
keys2 - Old Windows key icon
keys3 - Generic key and padlock icon
labtec - Icon of a server or something?
mac - Striped colorful Apple logo
mail - Generic icon of an envelope
mail_deleted - Same envelope with a red X emblem in the corner.
mailbox - Mailbox with the flag down
mouth - Smiling mouth icon
msdos - MS-DOS icon
mycomputer - A "My Computer" icon
mycomputer2 - A "My Computer" icon
mycomputer3 - A "My Computer" icon
newspaper - Generic newspaper icon
peripheral - Generic computer peripheral icon
plant_leaf - A certain green leafy plant
pocketknife - A swiss army pocket knife
question - Icon of a speech bubble with a "?" inside
radiation - Yellow and black radiation symbol
ram - Icon of a couple sticks of RAM
recycle - Green recycle arrows logo
recycle2 - Recycle arrows enveloping a globe of Earth
scanner - Generic scanner icon
screw - Golden screw icon
screw2 - Gray screw icon
setup - Generic icon for "setup.exe" type programs
skull - Black skull and crossbones
skull2 - Picture of a skull
skull3 - White skull and crossbones
tux - Icon of our favorite Linux mascot
tux_config - Tux dressed up like a repairman
ups - Icon of an uninterruptible power supply
zipdisk - Icon of a single zip disk
zipdisks - Icon of numerous zipdisks
</code></pre>
<p>You can call ZenMsg from a batch file or any other program (e.g. a Python or Perl script could call ZenMsg.exe and send it parameters). For example, open Notepad and save the following as "example.bat" (with quotes, ensuring that it gets a .bat extension and not .bat.txt) and place it in the same folder next to ZenMsg.exe:</p>
<p><div class="highlight"><pre><span></span><span class="p">@</span><span class="k">echo</span> off
ZenMsg --alert --title <span class="s2">"Critical Error"</span> --text <span class="s2">"Now you've done it."</span> <span class="se">^</span>
<span class="se"> </span>--button <span class="s2">"Ok"</span> --button <span class="s2">"Cancel"</span> --button <span class="s2">"Accept blame"</span> <span class="se">^</span>
<span class="se"> </span>--disabled 1 --disabled 2 <span class="p">></span> zenmsg-answer.txt
<span class="k">echo</span> The user had selected:
<span class="k">type</span> zenmsg-answer.txt
<span class="k">del</span> zenmsg-answer.txt
</pre></div>
</p>
<p><img src"https://www.kirsle.net/creativity/articles/ZenMsg-gnome.png"></p>
<p>Double-clicking your example.bat file would then pop up that alert box. ZenMsg prints the user's selected button to its standard output, which we captured above by piping it into zenmsg-answer.txt (it's possible to get output from commands in e.g. Perl scripts too, so your program can ask the user a question and then have branching behavior depending on which button the user clicked on).</p>
Favorite music2022-11-21T23:22:26Ztag:www.kirsle.net,2022-11-21:/favorite-music<blockquote>
<p><strong>NNN</strong> asks:</p>
<p>What kind of music do you listen to?</p>
</blockquote>
<p>I listen to all sorts of things but most frequently are the following:</p>
<p>I generally like a lot of indie & electronic music in recent years. I have <a href="https://open.spotify.com/playlist/5Cjfj3OHIR5qYl2ZOCm45A" rel="nofollow">a Spotify playlist</a> of several artists I like. Depending on my mood, some of my top go-to artists are <a href="https://open.spotify.com/artist/1RHcj161jldxUFQxuv2smS" rel="nofollow">Plantrae</a> or <a href="https://open.spotify.com/artist/0hc2qwaU2xy7LUd0FRjcHK" rel="nofollow">Dirtwire</a> if I just want some cool music with no/minimal vocals. Plantrae is also a great one to put on as some ambient music at the background of a party. Otherwise <a href="https://open.spotify.com/artist/28j8lBWDdDSHSSt5oPlsX2" rel="nofollow">ZHU</a> is often the one I click on and let Spotify have its way with me. <a href="https://open.spotify.com/artist/6LHsnRBUYhFyt01PdKXAF5" rel="nofollow">Bob Moses</a> is another favorite if I want something a little more bass-ey to jam out to.</p>
<p>I listen to a fair amount of pop music too, my top exposure to it being my car radio when I'm driving around, so whatever's on the Top 40 at a given time. Sometimes those songs will get stuck in my head and I'll play one on Spotify and let it wander and play similar songs for me. I also have a number of country artists/songs I like when I'm in the right mood and I have a short playlist on YouTube of <a href="https://www.youtube.com/playlist?list=PLt40IIcKfmGDnwIAMG715FNk2avMGo07u" rel="nofollow">sad songs</a> when I need to get some emotions out.</p>
<p>And probably my #1 most favorite song in the world (which I don't let myself listen to very often, so that I don't ruin it for myself) is <a href="https://www.youtube.com/watch?v=RBx-Ue28KUE" rel="nofollow">Canon in D</a>.</p>
ErrorGen and ZenMsg Q&A2022-10-19T21:20:10Ztag:www.kirsle.net,2022-10-19:/ask-20221019211956<blockquote>
<p><strong>Ax Wilson</strong> asks:</p>
<p>For some reason it is not opening the ZenMsg file how do i make it work.</p>
</blockquote>
<p><a href"https://www.kirsle.net/errorgen" rel="nofollow">ZenMsg</a> is a command-line program designed to be invoked by batch scripts or similar apps when you want to show a customized alert box pop-up. When you run the program without any command-line parameters (including if you just double-clicked on ZenMsg.exe from your file browser), the program just prints out its usage instructions to your command prompt and then exits; if you double-clicked to run it, exiting means you saw a cmd window for a brief second which then closed immediately.</p>
<p>To run it properly, open Command Prompt (or Powershell) first, navigate into the directory you placed ZenMsg.exe in, and run "ZenMsg" at the command prompt to see its usage instructions. For an "easy" way to get a Command Prompt opened to the right directory, you can open Windows Notepad and type this text into it:</p>
<p><div class="highlight"><pre><span></span><span class="p">@</span><span class="k">echo</span> off
cmd
</pre></div>
</p>
<p>And save it as "terminal.bat" (with quotations on it! so that it saves with a ".bat" extension, and not "terminal.bat.txt") in the same folder as ZenMsg.exe; then double-clicking on the terminal.bat will open a Command Prompt already pointed at the current directory, so you can just type "ZenMsg" to run the other program. For more info about the Command Prompt, see the <a href="https://www.computerhope.com/issues/chusedos.htm" rel="nofollow">DOS tutorial on ComputerHope.com</a> which is where I myself learned how to use the Command Prompt, way back in the day!</p>
<blockquote>
<p><strong>Anonymous</strong> asks:</p>
<p>Why is ZenMsg a command line program?</p>
</blockquote>
<p>My <a href"https://www.kirsle.net/errorgen" rel="nofollow">Error Message Generator</a> program is a GUI where you can build your custom alert box message visually, and ZenMsg is a command-line version that can pop up your alert box without the ErrorGen GUI being needed.</p>
<p>The reason that ZenMsg is a CLI tool is so that you can invoke it from other programs easily, including from <a href="https://www.computerhope.com/issues/ch001666.htm" rel="nofollow">batch files</a> or scripts written in Perl, Python or anything else. Actually, it's name, "ZenMsg" is based on the GNU/Linux program, <a href="https://help.gnome.org/users/zenity/stable/usage.html.en" rel="nofollow">Zenity</a> from the GNOME project.</p>
<p>You should also be able to create a Windows shortcut file that runs ZenMsg with parameters so you can have a desktop icon that, when double-clicked, pops up a ZenMsg alert box with custom icon, message and buttons if you want to prank your friends or something.</p>
Meaning of Kirsle2022-10-19T21:05:54Ztag:www.kirsle.net,2022-10-19:/meaning-of-kirsle<blockquote>
<p><strong>Anonymous</strong> asks:</p>
<p>What does your sites name kirsle come from/ what’s the meaning?</p>
</blockquote>
<p>The short answer is that Kirsle is just an AOL screen name I came up with back in middle school and doesn't mean anything; and it turned out to be such a unique name (that most all Google results for it were about me), that I decided to keep it around forever.</p>
<p>The longer answer is that it was originally inspired by a videogame character on the game <em>NiGHTS: Into Dreams</em> for the Sega Saturn. One of the baddies in the game was named Kircle, with a C, but when I read it I thought the C should've been pronounced like an S but anyway my screen name was based on Kircle for a time. But after multiple people (including text-to-speech programs) were "mispronouncing" it, I swapped the C out for an S and in doing so found a very unique username for myself.</p>
<p>Also, fun trivia: kirsle.net was the first ever domain name I registered, back in 2005 when I was in high school (my mom had to buy the domain for me!) I took the ".net" extension instead of ".com" because I thought "kirsle.com" didn't roll off the tongue very well; and because I didn't have a bank account to just buy my own domain names, but I already had several different websites, I thought a ".net" suffix would go well to put a bunch of subdomains beneath ".kirsle.net" to host all my various sites on one domain name! (Before kirsle.net, my other sites were hosted on random free subdomains I could find online, also had a few free .tk domains back in the day!) I do now have kirsle.com and kirsle.org and they just redirect to kirsle.net because that name still sounds the best to me!</p>
Sketchy Maze v0.12.02022-03-28T05:23:49Ztag:www.kirsle.net,2022-03-28:/sketchy-maze-v0-12-0<p>It's been a while since I posted an update about my videogame project,
<a href="https://www.sketchymaze.com/" rel="nofollow">Sketchy Maze</a> but I've still been working on it
and had released a <em>handful</em> of updates since my last post about
<a href"https://www.kirsle.net/sketchy-maze-v0-7-1" rel="nofollow">v0.7.1</a> and my game is starting to get interesting. 😉</p>
<p>Sketchy Maze is a drawing-based maze game where you can draw your own levels
freehand (like MS Paint) and make them look like anything you want. You can draw
a castle, a cave or a giant boat, and then play it as a 2D platformer game.
You can drag and drop some <a href="https://www.sketchymaze.com/guidebook/doodads.html" rel="nofollow">"doodads"</a>
such as buttons, keys, doors and enemies into your level to make it exciting.
And as for those doodads? You can also create your own, too, and
<a href="https://www.sketchymaze.com/guidebook/custom-doodads/scripts.html" rel="nofollow">program them in JavaScript</a>
to do whatever you want. The game also includes a built-in Story Mode of example
levels to simply play and/or learn from.</p>
<p><img src"https://www.kirsle.net/creativity/articles/sketchymaze-v0.12.0.png" alt="v0.12.0-title.png"></p>
<p>Since my last update about v0.7.1 the game has got:</p>
<ul>
<li>8 new levels (now 12 in total across three built-in levelpacks)</li>
<li>15+ new <a href="https://www.sketchymaze.com/guidebook/doodads.html" rel="nofollow">doodads</a>,
including: Anvil, Electric Trapdoor, pushable Box, Thief, Azulians,
<strong>Checkpoint Flags</strong>, and a handful of technical (invisible)
doodads for things like a custom Goal Region or Checkpoint Region if you
don't want the flags.</li>
<li>Scoring and progression system, and hostile enemy creatures you need to dodge.</li>
<li>Controls added for touch screens and Xbox-style game controllers including
Switch Pro Controllers.</li>
<li>Proper platformer physics with velocity, acceleration and jumping.</li>
<li>New drawing tools for the editor: Text Tool, Flood Fill/Paintbucket, Zoom in/out.</li>
<li>A <strong>much</strong> more capable <a href="https://www.sketchymaze.com/guidebook/custom-doodads/api-reference.html" rel="nofollow">JavaScript API</a>
for custom doodad scripts to enable more interesting behaviors.</li>
<li>Many user interface improvements.</li>
<li>32-bit Windows and Linux support added.</li>
</ul>
<p>The full change log is always available <a href="https://www.sketchymaze.com/guidebook/changes.html" rel="nofollow">on the Guidebook</a>
for more details.</p>
<p>If you haven't seen my game yet, <a href="https://www.sketchymaze.com/" rel="nofollow">check it out!</a>
It's still in beta so it may be buggy or crash sometimes, but any feedback is
welcome!</p>
Week 2 of daily driving the Pinephone2021-11-15T20:30:50Ztag:www.kirsle.net,2021-11-15:/week-2-of-daily-driving-the-pinephone<p>About two weeks ago I again <a href"https://www.kirsle.net/pinephone-with-a-sim-card" rel="nofollow">put my SIM card into my Pinephone</a>
to see whether I can make it a daily driver device. The last time I tried this was
nearly a year ago so I have that benchmark to compare it to as well as some new
information now.</p>
<p>The stack:</p>
<ul>
<li>Operating system: <a href="https://mobian-project.org/" rel="nofollow">Mobian</a> with the Phosh UI.</li>
<li>Carrier: T-Mobile (US)</li>
</ul>
<p>The highlights:</p>
<ul>
<li>I have MMS messaging <em>sorta</em> working: I can receive picture and group chat messages
perfectly fine, but I can not <em>send</em> out an MMS myself. I can reply to a picture
message as SMS but for group chats, if I need to respond, I can just pick somebody
and send them an SMS out-of-band if need be.</li>
<li>Battery life is <em>okay</em> - not great, but given how often I actually use my phone,
it's not bad either. Every other night I'll plug in my Pinephone <em>or</em> my Pixel 3
to charge, and my Pinephone gets me thru the day and then some (I can leave it
<em>not</em> charging overnight, and it doesn't suffer too much for it).</li>
<li>Reliability for incoming phone calls while the phone is deep sleeping seem to
be improved since last year. My Pinephone was sitting on my desk one day,
removed from power, sleeping, and it rang and I answered it.</li>
<li>Other cell phone functionality all working OK: calls, SMS, 4G LTE data, and
hotspot sharing over WiFi all working.</li>
<li>Waydroid seems more stable on Mobian and it runs my Android apps okay, and with
KDE Connect I can get notifications from Android apps in my Phosh UI.</li>
<li>GPS location accuracy may be a challenge to sort out.</li>
</ul>
<p>The details:</p>
<p></p>
<h2><a name="apns-4g-and-mms" class="anchor" href="#apns-4g-and-mms" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
APNs, 4G and MMS</h2>
<p>Firstly let's talk about cell tower APNs (access point names?).</p>
<p>My Pinephone automatically detected my T-Mobile SIM card and set up the APN
named <code>mobilenet</code> in my Phosh settings. Apparently T-Mobile also has an APN
named <code>fast.t-mobile.net</code> and you can use either value for your APN host name.
For T-Mobile there is no username/password needed for their APN, only one of
these two names. The <a href="https://wiki.pine64.org/wiki/PinePhone_APN_Settings" rel="nofollow">Pine64 wiki</a>
has a bunch of these settings for a lot of other carriers in case you don't use
T-Mobile.</p>
<p>For MMS support, it <em>currently</em> seems that ModemManager can only deal with a
single APN at a time. For T-Mobile this is OK because their 4G data and MMS go
over the same APN, but some carriers use different APNs for MMS and this may
cause problems there. For my Pinephone I set <code>mobilenet</code> as the APN both for
4G data (in GNOME Settings) as well as for my MMS config (editable in Chatty
with the latest branch, or in ~/.mms/modemmanager/mms config).</p>
<h2><a name="mms" class="anchor" href="#mms" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
MMS</h2>
<blockquote>
<p><strong>Updates:</strong> (Dec 15 2021)</p>
<p>Mobian now has mmsd-tng packaged in their normal testing repo, so I could
<code>apt install</code> it and stop running my compiled-from-source copy. But, their
mmsd-tng still seems unable to <em>send</em> MMS, but can only receive it.</p>
<p>Chatty v0.5.0 seems "coming soon" and I've pulled the updated code from Purism's
repo; Mobian's MMS wiki page says 0.5.0 (mistakenly written as 5.0.0) will be
their planned release that integrates well with mmsd-tng. Their current packaged
Chatty is the older 0.4.0 without MMS support. When both are fully packaged for
Mobian I will probably reinstall the OS to get my hand-compiled copies cleanly
out of my system.</p>
</blockquote>
<p>The main feature I've been waiting on has been MMS support. It is still a very
popular service in the US and I get roped in to group chat threads frequently.
However, this has been the slowest developing feature on the Pinephone; I've
had this device since May 2020 and MMS support has always been "coming soon"
the whole entire time.</p>
<p>I have heard that <a href="https://wiki.pine64.org/wiki/PinePhone_Software_Releases#Manjaro_ARM" rel="nofollow">Manjaro</a>
had MMS working out-of-box, however Manjaro doesn't have an installer image capable
of setting full disk encryption on my phone. I consider full disk encryption to be
<em>crucial</em> in a portable device: envision the case where your phone fell out of your
pocket on the train and a random stranger finds it. I would prefer that the root
filesystem and SD card are encrypted so that the stranger doesn't <em>immediately</em>
gain access to my SSH keys, saved passwords in Firefox, cookies that logged me in
to various sites, the password for my email inbox, and so on. To my knowledge so far,
only Mobian and postmarketOS have an option for encryption and the latter doesn't
run the GNU stack which makes things complicated for me as a developer.</p>
<p>Anyway, the Mobian wiki has a <a href="https://wiki.mobian-project.org/doku.php?id=mms" rel="nofollow">page about MMS</a>
and you basically need to compile some stuff yourself to get it working. I decided
I had lost patience waiting for this to be fully packaged nicely and that I would
see what I could get working from their wiki instructions.</p>
<p>There are two main parts: <code>mmsd-tng</code> provides a sort of MMS daemon and there is
a newer build of Chatty (the texting app) that understands MMS. For <code>mmsd-tng</code>,
Mobian has it packaged now on their unstable branch, but I decided to compile
it from source code instead -- I don't want to upgrade my entire Mobian to unstable,
as then I will run into likely problems with Waydroid or other third-party software
that doesn't track unstable; and I wanted to avoid any kind of Frankendebian that
I would wind up with if I were to <em>try</em> and get the mmsd-tng.deb from their unstable
repo to install onto my otherwise testing branch.</p>
<p>Source repo: <a href="https://gitlab.com/kop316/mmsd" rel="nofollow">https://gitlab.com/kop316/mmsd</a></p>
<p>It was fairly straightforward to compile and install. The build steps will point
out any missing dev dependency and it took a little trial-and-error until I got
them all.</p>
<p>For Chatty: Mobian already had one installed and I didn't want <em>any</em> risk of
conflict for building my own version, so I carefully removed Chatty first before
compiling it from source:</p>
<p><div class="highlight"><pre><span></span><span class="c1"># Remove Chatty CAREFULLY without taking out Phosh with it!</span>
dpkg -r --force-depends chatty
</pre></div>
</p>
<p>Be careful! If you simply did an <code>apt remove chatty</code> it will try and uninstall
Phosh and a bunch of stuff with it! For some reason Phosh <em>depends on</em> Chatty so
remove it carefully before installing your own.</p>
<p><strong>The end result:</strong> Chatty has an updated UI with a paperclip button to attach
a picture to my message, and it 'appears' to send the picture, but nothing
actually goes out. However, <em>incoming</em> picture messages from others work fine,
and if I get into a group MMS chat, that works fine too - I can see the numbers
and names of the participants, I can see picture messages they send in the chat,
but I can not <em>respond</em> to the chat - my message appears to send, but nobody
actually sees it.</p>
<p>For my needs, though, this works okay: so long as I know when I <em>got</em> an MMS and
I can <em>see</em> what it was, that's enough for me. It was rough before when MMS was
just "not working" or you needed a command-line hacky script to get them, with
no notification you even got one.</p>
<p>From further poking, I think the "<em>sending</em> MMS" problem is in mmsd-tng itself
and not in Chatty; mmsd-tng contains some test scripts in Python for sending MMS
out and I tested those and they fail to deliver MMS too, despite them <em>thinking</em>
they got back a confirmed delivery response from the network.</p>
<h3><a name="troubleshooting-download-mms-message-while-connected-to-wifi" class="anchor" href="#troubleshooting-download-mms-message-while-connected-to-wifi" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Troubleshooting: Download MMS message while connected to WiFi</h3>
<p>At first I ran into this problem: if my Pinephone is connected to my WiFi network,
it was <em>unable</em> to download MMS messages at all, despite having a functional LTE
modem connected to 4G.</p>
<p>Apparently the root of the problem is: in the MMS payload there is a URL to the
attached image asset (or w/e) but this URL is protected with credentials and the
phone <em>must</em> access it over the 4G modem and not over WiFi; but when your WiFi
is connected, it will prefer that for its network gateway and be unable to
authenticate to get the MMS URL.</p>
<p><strong>The fix:</strong> in my ~/.mms/modemmanager/mms config I set <code>ForceCAres=true</code> to make
it use the C-Ares library for DNS rather than systemd. With this, it was able to
download MMS messages even while I was on WiFi!</p>
<h2><a name="battery-life" class="anchor" href="#battery-life" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Battery Life</h2>
<p>The battery life on the Pinephone is just <em>okay</em> and in the couple weeks I've
been daily driving my Pinephone I simulated a few common cases to see whether the
battery would be a complete deal breaker. For example, I charged it to 100% and
then unplugged it and left it overnight as I slept to see how it fared by the
morning.</p>
<h3><a name="screen-on-time" class="anchor" href="#screen-on-time" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Screen-on Time</h3>
<p>The battery is not great for active screen-on use.</p>
<p>I'll wake up at 9 AM, unplug my Pinephone (full charge), play around on it for
one hour, scrolling Reddit or checking my e-mail or whatever: and it will have
dropped from 95% charge down to 75% charge in just that one hour of use. My
screen brightness was set below the 50% mark (probably closer to 30%) to
maximize its battery life and this is about how fast it will drain with active
use.</p>
<p>But for how often I actually play on my phones, this isn't actually so bad for
me. I work from home and have laptops to play on instead, it's mainly just an
hour in the morning and an hour in the evening that I play on my phone and just
check it periodically thru the day for any SMS or Telegram chats that came in.</p>
<h3><a name="screen-off-time" class="anchor" href="#screen-off-time" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Screen-off Time</h3>
<p>The deep sleep feature on the Pinephone does <em>very</em> well to prolong the battery
life while idle. Sometimes I would unplug my Pinephone to charge my Pixel instead,
and then forget about the Pinephone for <strong>three</strong> days, and it will still be
hanging in there with 20% battery remaining.</p>
<p>Leaving it just overnight off its charger, it would go from 95% charged and
still have maybe 91% in the morning or thereabouts.</p>
<h3><a name="charging-it-every-other-day" class="anchor" href="#charging-it-every-other-day" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Charging it every other day</h3>
<p>I still have my Pixel phone which is now WiFi-only because it can control my
Chromecasts and it runs certain Android apps better than the Pinephone does. But,
I don't have a whole ton of phone chargers around my house!</p>
<p>If my Pinephone is at 75% or more battery and my Pixel is at 50% or less, I'll
opt to plug my Pixel in to charge overnight and not my Pinephone; and the next
night, the Pinephone will obviously be needing it more and I'll plug <em>that</em> in
and leave my Pixel off the charger.</p>
<p>And after doing this a few days back to back, it works for me!</p>
<p>So despite the relatively poor battery in the Pinephone, it's actually not
<em>terrible</em> in practice for my needs and usage patterns for my mobile devices.</p>
<h3><a name="alarm-clocks" class="anchor" href="#alarm-clocks" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Alarm clocks</h3>
<p>There is an issue with alarm clocks when the phone is deep sleeping: basically,
only the cell modem will wake the phone and everything else is suspended so
normal alarm clock apps (such as GNOME Clocks) will not trigger at the right
time.</p>
<p>If you plug your phone in to charge overnight (and you have faith that there
won't be a power outage in the morning) it should trigger fine. If you are on
battery, though, there is a hacky workaround:</p>
<p><a href="https://wiki.mobian-project.org/doku.php?id=wake-mobile" rel="nofollow">Wake-Mobile</a> is a simple
alarm clock app that uses systemd timers to wake the phone from sleep. It's
<em>very</em> barebones and its alarm clock noise is annoying without an ability to
customize it, but it'll work in a pinch.</p>
<p>If I were staying at a hotel or something, I'd probably use the hotel's alarm
clock as a backup just in case.</p>
<h2><a name="android-apps-with-waydroid" class="anchor" href="#android-apps-with-waydroid" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Android apps with Waydroid</h2>
<p>I wrote <a href"https://www.kirsle.net/waydroid-on-the-pinephone-is-a-game-changer" rel="nofollow">about Waydroid recently</a>
and it still works well. On Mobian it seems to be more stable recently than it
had been; not long after I had excitedly written that article, an <code>apt upgrade</code>
broke Waydroid for me and it needed some manual debugging to get it sorted out,
and the comment thread has someone else who struggled to get it working on Mobian.</p>
<p>Apparently people have found that Waydroid "just works" on Manjaro but I can't
use Manjaro for the aforementioned lack of full disk encryption. But anyway: for
weeks now Waydroid has been stable and reliable for me on Mobian, it hasn't
broken on me in some time.</p>
<p>Mobian's wiki <a href="https://wiki.mobian-project.org/doku.php?id=waydroid" rel="nofollow">has instructions</a>
that you should check out if you wanna try this. There are a few little gotchas
and caveats to getting it set up.</p>
<h3><a name="waydroid-and-battery-life" class="anchor" href="#waydroid-and-battery-life" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Waydroid and battery life</h3>
<p>Waydroid currently has a problem where it interferes with deep sleep on the
Pinephone. Right when the phone would want to start suspend, instead the screen
lights up and stays lit up, eating your battery; and if you turn the screen off,
it will turn back on again next time it tries to suspend.</p>
<p>I had <a href="https://github.com/waydroid/waydroid/issues/168" rel="nofollow">filed an issue on their GitHub</a>
about this, but for now a work-around is to stop Waydroid when I'm not using it.
I put a .desktop launcher in my ~/.local/share/applications to do this:</p>
<p><div class="highlight"><pre><span></span><span class="k">[Desktop Entry]</span>
<span class="na">Type</span><span class="o">=</span><span class="s">Application</span>
<span class="na">Name</span><span class="o">=</span><span class="s">Waydroid Stop</span>
<span class="na">Exec</span><span class="o">=</span><span class="s">waydroid session stop</span>
<span class="na">Icon</span><span class="o">=</span><span class="s">/usr/lib/waydroid/data/AppIcon.png</span>
</pre></div>
</p>
<p>The down side is: I'll need to wait the slow 2 minutes next time I launch an
Android app so that Waydroid can fully boot up (once Waydroid is warmed up,
Android apps launch and function well). However, this works okay enough for my
needs; if I'm sitting down for an extended play session with my phone, I'll boot
up Waydroid so I can scroll Twitter or whatever, and then I just stop Waydroid
when I'm finished so my battery will last the rest of the day.</p>
<h3><a name="kde-connect" class="anchor" href="#kde-connect" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
KDE Connect</h3>
<p>KDE Connect really makes my experience with Waydroid a lot better. Since Waydroid
is container-based, the Android filesystem and clipboard are isolated away from
the host system, so transferring files back and forth is a chore.</p>
<p>Install KDE Connect on both Linux and Android and they can see each other right
away and pair up; then Android notifications can get synced to my Phosh desktop
and I can push and pull files both directions. I think clipboard sharing should
work too but I don't know if I tested that.</p>
<h3><a name="phone-call-reliability" class="anchor" href="#phone-call-reliability" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Phone call reliability</h3>
<p>The last time I tested my Pinephone in January, I was especially concerned with
the deep sleep feature and what that would mean for incoming phone calls or text
messages. Previously: if the phone was sleeping and an incoming call was placed,
the phone's screen would light up within a couple seconds and I would watch the
cell indicator connect, and only if it did so quickly enough, would the phone
actually ring (I counted 11 seconds one time before the ring). But more often,
it was too slow and the calling side would get a voicemail prompt instead.</p>
<p>But this time: I one time had my Pinephone sitting on my desk, unplugged, sleeping,
and to my surprise it began ringing and I was able to answer it. Luckily for me,
it was an important phone call that I'm glad I didn't miss.</p>
<p>I haven't extensively tested incoming calls otherwise but this one anecdote
suggests that reliability has been improved in the last year!</p>
<h3><a name="gps-maps-and-navigation" class="anchor" href="#gps-maps-and-navigation" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
GPS, Maps and Navigation</h3>
<p>This part is not great.</p>
<p>GNOME Maps and Firefox are able to get a location but the location they get is
not very accurate:</p>
<ul>
<li>If I am connected to my home WiFi router: my Pinephone believes I am still
living at my old address from several years ago. It accurately pinpoints the
spot where my router used to be, but alas, I am no longer there.</li>
<li>If I take my phone <em>off</em> WiFi so it has 4G instead: it thinks my location is
off the coast of Seattle, which is several hundred miles away from me. I
suspect that it is geolocating me by my IP address given by the cell carrier
and this is their nearest hub or where the IP is registered to.</li>
</ul>
<p>Mobian's wiki has a <a href="https://wiki.mobian-project.org/doku.php?id=location" rel="nofollow">page about location</a>
to get into the weeds with this stuff, but what I've determined so far is:</p>
<ul>
<li>It makes use of Mozilla Location Services which is how it "knows" where my WiFi
router is when I'm at home; but Mozilla's database is terribly out of date for
mine. I have tried using Firefox for Android and opting in to help their database
but haven't seen any change over several months.</li>
<li>It can allegedly triangulate the GPS satellites directly if you give it a clear
view of the sky and about 20 minutes to calibrate, which I have not had the
patience or willpower to do.</li>
</ul>
<p>Interestingly, on my laptop running Fedora Linux, Firefox is able to very accurately
get my real location despite my laptop only having WiFi; from some research it seems
Firefox usually prefers Google Location Services (where they have the whole Android
userbase and Streetview cars contributing to their WiFi router database) which is
probably how it does this; but the Firefox shipped with Mobian is an especially
privacy-hardened one that has Google services ripped out. There may be some things
you could install and configure on the Pinephone to improve GPS accuracy by using
Google's services, but I'm not sure off hand what those are.</p>
<p>GPS problems aside, between GNOME Maps or various maps sites in Firefox you can
at least get access to street maps, search for addresses and such; so if you're
lost you could pull over to the side of the road and get yourself sorted out.</p>
<p>I think for a while I will carry my Pixel 3 with me, so in a pinch, I can tether
it to my Pinephone and use it for navigation.</p>
<h2><a name="see-also" class="anchor" href="#see-also" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
See also</h2>
<p>Some other blog posts I've written about the daily driver-ability of the Pinephone:</p>
<ul>
<li><a href"https://www.kirsle.net/status-of-mobile-linux-apps-on-pinephone-screenshots" rel="nofollow">Mobile Linux apps</a>:
screenshots and info about some of my favorite Linux apps.</li>
<li><a href"https://www.kirsle.net/waydroid-on-the-pinephone-is-a-game-changer" rel="nofollow">Android apps with Waydroid</a>:
basically most apps that'll work on a de-googled Android should be workable
on the Pinephone.</li>
</ul>
Waydroid on the Pinephone is a game changer2021-09-24T19:20:38Ztag:www.kirsle.net,2021-09-24:/waydroid-on-the-pinephone-is-a-game-changer<p>This week, some news about <a href="https://waydro.id/" rel="nofollow">Waydroid</a> made its way to the
<a href="https://www.reddit.com/r/linux" rel="nofollow">r/linux</a> subreddit and in the comments I saw a
<a href="https://www.pine64.org/pinephone/" rel="nofollow">Pinephone</a> owner write about their experience
with Waydroid and none of his complaints had anything to do with it being slow
or clunky or broken, which is about what my experience was the last time I tested
out <a href="https://anbox.io/" rel="nofollow">Anbox</a> about a year ago.</p>
<p>So it prompted me to check Waydroid out, and... it works remarkably well! It
really surprised me. Waydroid makes use of containers to run Android directly on
your own Linux kernel, without emulation, and so it performs <em>very</em> well -- some
Android apps even run more smoothly than their native Linux counterparts!</p>
<p>I wasn't expecting that the Pinephone was <em>ever</em> going to be able to run Android
apps smoothly on a GNU/Linux system, but now that it does, and does so <em>this</em>
well, this is a game changer in terms of the Pinephone being "daily driver"
ready. Finally, I have a way to use Slack and Discord from my Pinephone, something
that was basically not possible at all before!</p>
<p><img src"https://www.kirsle.net/creativity/articles/waydroid/pinephone-discord.png" alt="Screenshot of Discord (Android) running on Mobian"></p>
<p>Now, to be clear: even without Android, there <em>are</em> a very good collection of
Linux apps that already work well on the Pinephone. Having the option of Android
for the odd proprietary app like Slack or Signal is nice to have. Read on to the
full blog post for how Waydroid works right now, what are some of its pain points
still, and a few screenshots of my Phosh app drawer showing everything I have
installed on my Pinephone.</p>
<p></p>
<h2><a name="the-user-experience" class="anchor" href="#the-user-experience" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
The User Experience</h2>
<p>This is how Waydroid behaves once installed:</p>
<p>There is a "Waydroid" app launcher in my drawer and this brings up the "Full UI"
screen for Waydroid -- you see the LineageOS home screen and can see the home
screen apps, swipe up for the Android app drawer, swipe down for the Android
notifications drawer, and the Android task switcher works to switch between the
various running apps.</p>
<p>In addition to this Full UI launcher, every Android app installed also gets a
launcher icon directly in your Phosh app drawer, alongside your other Linux
apps. You can directly run the apps from here as normal.</p>
<p>The window manager in Phosh generally separates the Android apps into distinct
tasks as you'd expect, one window per app. It's sometimes a little janky, you'll
switch to the Slack window but Discord came up instead.</p>
<p>LineageOS comes with a handful of "redundant" apps such as Contacts, Calendar,
Clocks, Settings, and others that are similar to GNOME apps and clutter my app
drawer; but you can remove their launchers from your ~/.local/share/applications
folder and clean that up. For the Android apps I would literally <em>never</em> want
to launch from Phosh they can be removed this way; you can always reach them
from the "Full UI" and going thru the Android apps drawer.</p>
<h2><a name="waydroid-caveats" class="anchor" href="#waydroid-caveats" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Waydroid Caveats</h2>
<p>Waydroid is still in development and many of the below issues will surely be
resolved over time. But Waydroid is already working <strong>way</strong> better than I ever
expected at such an early stage!</p>
<p>The Mobian wiki has <a href="https://wiki.mobian-project.org/doku.php?id=waydroid" rel="nofollow">instructions</a>
how to set up Waydroid. Apparently, the upstream project hosts their own dpkg
repo for Ubuntu and Debian which is nice - so I'll get updates directly from the
source as they're released.</p>
<p>A few strange quirks that Waydroid currently has:</p>
<ul>
<li><strong>Initial startup time is slow.</strong> After a fresh reboot of the phone, launching
your <em>first</em> Android app takes a considerably long time, like over 30 seconds
of staring at your Phosh desktop waiting for an app window to appear.</li>
<li><strong>Once warmed up, it runs fast!</strong> After that first app launch it works really
well! Launching a new Android app has the app window appear within just a
couple of seconds. I was easily able to run ~6 Android apps or so at the same
time without the phone showing signs of being burdened yet. I haven't stress
tested how far I can push that, though.</li>
<li><strong>Scrolling and animations are "smooth"</strong> - not as fast and snappy as a flagship
Android phone, but not as slow and choppy as some Linux apps either! Twitter
for Android is <em>very</em> usable where all the other options on the Pinephone were
sub-par (Firefox struggles on their mobile site, Chromium is better but has its
own rendering issues and blurry text, etc.)</li>
<li><strong>Sometimes window management is finicky.</strong> An Android app may appear to "crash"
suddenly, but really only its window has gone away. Reopening another Android
app will bring a Waydroid window back up and you can task switch and see your
original app still there where you left it.</li>
<li><strong>The camera and microphone don't work yet.</strong> But these are not important for
my needs right now anyway, and I'm sure support will come with time.</li>
<li><strong>The filesystem and clipboard are isolated.</strong> You can copy/paste within
Android but the clipboard doesn't share across the Android/Linux boundary. To
share a picture from my Pinephone thru an Android app I need to first download
the picture into Android's environment. With creativity you can probably set
up file sharing with SMB, FTP, <a href="https://www.reddit.com/r/PinePhoneOfficial/comments/q4uos8/small_tip_you_can_install_kde_connect_on_waydroid/" rel="nofollow">KDE Connect</a> or so on.</li>
<li><strong>Keep your Phosh on-screen keyboard CLOSED while Waydroid initializes.</strong> If
your keyboard is open, Waydroid will pick a window size that leaves room for
the keyboard, and then stays that size forever (until you reboot the phone)
even if you close your keyboard. The Mobian wiki suggests launching an app like
Clocks that doesn't open your keyboard while you wait for Waydroid to come up.</li>
</ul>
<p>And on the topic of keyboards: Android will use its own keyboard for Android
apps, and the Phosh keyboard doesn't currently interact well with Android
anyways. So while you are using Android apps you'll keep your Phosh keyboard
hidden away, and the Android keyboard will appear when needed. It's a little
weird having two keyboards, but oh well! Since Waydroid doesn't resize its
window your Phosh keyboard would appear "on top" so even if you could type into
Android apps with it, you wouldn't see the text you were writing because the
text box is at the bottom of the Android screen, "below" your Phosh keyboard!</p>
<h2><a name="it-is-basically-lineageos-without-google-play-services" class="anchor" href="#it-is-basically-lineageos-without-google-play-services" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
It is basically LineageOS without Google Play Services</h2>
<p>Waydroid uses a minimal LineageOS image as its Android base.</p>
<p>In Waydroid you can install the <a href="https://f-droid.org" rel="nofollow">F-Droid</a> app store and,
through that, install the Aurora Store -- a third-party client for the Google
Play Store. With Aurora you can download all your usual Android apps such as
Slack, Discord, Netflix, and so on.</p>
<p>Like any de-googled Android ROM, some apps from the Play Store won't function
without the Google services and other apps may have limited functionality.
See my <a href"https://www.kirsle.net/wiki/Degoogle" rel="nofollow">Degoogle Wiki</a> for some of my notes on de-googling
Android and some apps that still work fine without the Play Services.</p>
<p>Notable apps that will <em>not</em> work on Waydroid include:</p>
<ul>
<li>Lyft and Uber because they require the Google Location API. But, these two
have good working web apps that you can use from just Firefox on Linux on
the Pinephone.</li>
<li>Google's first-party apps (YouTube, Gmail, etc.) 100% depend on the Play Services.</li>
<li>Snapchat is notoriously difficult to use from a de-googled phone, it makes use
of Google SafetyNet and employs all kinds of tricks so that it does NOT sign in
on suspicious Android devices -- they <em>really</em> don't trust their users!</li>
</ul>
<p>But many apps that I personally use will work fine without Google services.</p>
<h2><a name="android-apps-i-have-tested" class="anchor" href="#android-apps-i-have-tested" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Android apps I have tested</h2>
<p><strong>Slack</strong> was the first one I installed. My workplace uses it and it's a crucial
app for me to have so I can stay responsive to work in case I'm away from my
laptop for a while. There was previously <em>NO</em> good way to use Slack from the
Pinephone -- their mobile website just directs you to the Play Store, and their
desktop web app isn't optimized at all for the phone's screen size; you need to
zoom out the page quite a ways to see the UI properly but then text size is
very small. Workable in a pinch but not great. I have looked at Pidgin plugins
and Matrix bridges for Slack but options are not good. It is <em>very</em> nice having
the Android Slack app easily runnable on the Pinephone!</p>
<p><strong>Discord</strong> also works well -- see the screenshot at the top of this blog post.
Keep in mind that the camera and microphone aren't working yet, but for just
chat and sharing files and pictures all is fine!</p>
<p><strong>Bank of America</strong> works (updated Oct 11 2021), this has been my bank for ages
and they have a fully functional mobile website that would work in Firefox but
also their Android app works in Waydroid. I had trouble searching in Aurora Store
for the app but used the link from their website and installed it; could sign in
and everything. On de-googled Androids I've tried the BofA app even supports the
fingerprint reader! The Pinephone doesn't have one of those (yet) and I wouldn't
expect Waydroid to pass it thru yet even if it <em>did</em> but all the basic features
of the BofA app are working!</p>
<p><strong>Signal</strong> works fine. I needed to <a href="https://signal.org/android/apk/" rel="nofollow">manually download the .apk</a>
from Signal's website because the Aurora Store said the app "wasn't compatible"
with my phone - but it works fine! The manually downloaded APK even has a
work-around for the lack of push notifications. I was able to activate a new
account (using my Google Voice number) within Waydroid on Pinephone and send
messages.</p>
<p><strong>Telegram</strong> also works -- and it works <em>better</em> than the native Linux client
does! Under Mobian, Telegram Desktop takes a very long time to log on whereas
the Android app comes right up (provided Waydroid is warmed up already).</p>
<p><strong>Spotify</strong> works -- I could log in and play music. I tested this app to verify
whether DRM-heavy apps will function, and it seems to! I have not tested Netflix
or Hulu though, as I have little interest to watch video on my phone and there
is no Chromecast support anyway.</p>
<p><strong>Twitter</strong> works great. They have a mobile website too which is OK and there
were already a few options to access Twitter on the Pinephone without Android.
Even on my Pixel phone I prefer Twitter in a web browser over their native app,
but the web browsers on Pinephone struggle a bit with their website, so it is
nice to have the native app available.</p>
<p><strong>VLC Media Player</strong> works! It plays videos back really well too, at least for
the h.264 encoded video I tested it with. Your mileage may vary with other
video codecs. While VLC has built-in Chromecast support, it does not seem to
work under Waydroid.</p>
<p><strong>Jellyfin</strong> doesn't really work. Its in-built Chromecast feature, too, can not
detect any actual Chromecast on my network. When I stream a video, I can hear
the audio but the video output is just black.</p>
<h2><a name="screenshots-of-my-pinephone-apps-drawer" class="anchor" href="#screenshots-of-my-pinephone-apps-drawer" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Screenshots of my Pinephone Apps Drawer</h2>
<p>The Pinephone was already getting close to "daily driver ready" before Waydroid
and now it's even better! Here are the full set of apps I currently have
installed on my Pinephone, a few of which now are Android apps!</p>
<p><img src"https://www.kirsle.net/creativity/articles/waydroid/pinephone-apps-1.png" alt="Home Screen 1"> <img src"https://www.kirsle.net/creativity/articles/waydroid/pinephone-apps-2.png" alt="Home Screen 2"></p>
<p><img src"https://www.kirsle.net/creativity/articles/waydroid/pinephone-apps-3.png" alt="Home Screen 3"> <img src"https://www.kirsle.net/creativity/articles/waydroid/pinephone-apps-4.png" alt="Home Screen 4"></p>
<p>The app list in text form:</p>
<ul>
<li>Chatty (Linux): SMS messenger.</li>
<li>Contacts (Linux)</li>
<li>Firefox (Linux)</li>
<li>King's Cross (Linux): Terminal emulator.</li>
<li>Advanced Network Config (Linux)</li>
<li>Archive Manager (Linux)</li>
<li>Aurora Store (Android): Google Play Store client.</li>
<li>Axolotl (Linux): third party Signal client (I haven't got it working)</li>
<li>Blanket (Linux): sleep sounds generator</li>
<li>Browser (Android): runs fine! Sometimes faster, sometimes slower than native Linux browsers.</li>
<li>Calculator (Linux)</li>
<li>Calendar (Linux)</li>
<li>Calls (Linux)</li>
<li>Cawbird (Linux): a Twitter client, works OK, doesn't do notifications well and DM's are a bit jank.</li>
<li>Chromium (Linux)</li>
<li>Clapper (Linux): a hardware-accelerated video player for Pinephone.</li>
<li>Clocks (Linux)</li>
<li>Dialect (Linux): a language translation app.</li>
<li>Dictionary (Linux)</li>
<li>Discord (Android)</li>
<li>Document Viewer (Linux): PDF viewer.</li>
<li>DoorDash (Chromium web app; Linux)</li>
<li>Email (Android)</li>
<li>F-Droid (Android): free and open source Android app store.</li>
<li>Files (Linux)</li>
<li>Flashlight (Linux)</li>
<li>Flatseal (Linux): permissions manager for Flatpak apps.</li>
<li>Gallery (Android)</li>
<li>Geary (Linux): an e-mail client optimized for mobile phones.</li>
<li>Giara (Linux): a Reddit client, a bit buggy and crashes a lot.</li>
<li>Gtkeddit (Linux): a better Reddit client, works very very well already!</li>
<li>Help (Linux): GNOME documentation.</li>
<li>Image Viewer (Linux)</li>
<li>Jellyfin (Android): doesn't work super great right now.</li>
<li>KeePassXC (Linux): works decently! It "scales-to-fit" and is usable and it supports 2FA TOTP codes.</li>
<li>Lollypop (Linux): offline music player for your MP3 collection.</li>
<li>Maps (Linux): GNOME Maps.</li>
<li>Megapixels (Linux): the only working camera for the Pinephone.</li>
<li>Password Safe (Linux): a KeePass client that is optimized for mobile.</li>
<li>Passwords and Keys (Linux): manage your GNOME keyring etc.</li>
<li>Portfolio (Linux): a simple file browser.</li>
<li>Powersupply (Linux)</li>
<li>Pure Maps (Linux): another Maps application.</li>
<li>Screenshot (Linux): the GNOME Screenshooter tool.</li>
<li>Settings (Linux): GNOME Settings.</li>
<li>Shortwave (Linux): Internet radio.</li>
<li>Signal (Android)</li>
<li>Slack (Android)</li>
<li>Software (Linux): the GNOME Software Store.</li>
<li>Sound Recorder (Linux)</li>
<li>Spotify (Android)</li>
<li>Tangram (Linux): a Matrix client?</li>
<li>Telegram Desktop (Linux)</li>
<li>Telegram FOSS (Android)</li>
<li>Termit (Linux): a terminal emulator - I'm not sure how this got installed.</li>
<li>Text Editor (Linux)</li>
<li>To Do (Linux)</li>
<li>Twitter (Android)</li>
<li>Twitter Web (Chromium web app; Linux)</li>
<li>Ungoogled Chromium (Linux)</li>
<li>Usage (Linux): CPU usage monitor.</li>
<li>Videos (Linux)</li>
<li>VLC for Android</li>
<li>Waydroid (Android Full UI)</li>
<li>Weather (Linux)</li>
<li>Web (Linux): the GNOME Web browser, Epiphany.</li>
<li>What IP (Linux): simple IP address tool.</li>
</ul>
<p>53 native Linux apps to 13 Android apps - not a terrible ratio to have!</p>
<p>All of the above apps work well on the Pinephone except where noted otherwise.</p>
Developing a game from scratch2021-07-21T03:03:18Ztag:www.kirsle.net,2021-07-21:/developing-a-game-from-scratch<p>For the past few years, on and off (sometimes more off than on), I've been working
on a videogame called <a href="https://www.sketchymaze.com/" rel="nofollow">Sketchy Maze</a> and had been
taking screenshots of it along the way. This blog post will be a bit of a retrospective and a series of screenshots
showing it from its <em>very first</em> prototype up to the state that it's in now.</p>
<p>I wasn't even sure I was going to get very far on this project. I had once
attempted <a href"https://www.kirsle.net/tagged/KAGE" rel="nofollow">programming a game in Perl</a> and lost steam after barely
having a working prototype. I had dabbled <em>a few</em> times getting started programming
a game but then decided my brilliant idea of an RPG game wasn't worth all the
<em>programming.</em> Stubbornly, I never wanted to just use a game engine like Unity or
Unreal but wanted to program it all <em>myself.</em> And programming from scratch is
considerably the harder way to go, so your game idea had <strong>better</strong> be worth it in the end!</p>
<p>The game idea that won out is a personal and nostalgic one. Back in the 90's when I was
growing up with videogames like <em>Sonic the Hedgehog</em> and <em>Super Mario Bros.</em>, I would
often draw my own "mazes" or levels like on a 2D platformer game, with pencil and paper
and then "play" it with my imagination. I'd imagine the player character advancing
through my maze, collecting keys that unlock doors, pushing buttons that activate
traps somewhere else on the page. I'd write little annotations about which button
did what, or draw a dotted line connecting things together. My mazes borrowed all
kinds of features from videogames I liked, all your standard platformer stuff:
buttons, trapdoors, conveyor belts, slippy steep slopes, spikes and water and
whatever I wanted.</p>
<p>So my game concept was basically:</p>
<ul>
<li>Players can draw their own mazes completely freehand, with w/e colors they want</li>
<li>Players can drag 'doodads' like buttons and keys into their level, and link buttons to devices, etc.</li>
<li>And it should be mod-friendly af: players can make custom doodads with custom behavior (programming)</li>
</ul>
<p>See the full blog post to read <em>how I even got this started</em> and see screenshots
of progression between the "Before and After" pictured below. My first target goal
was just a <em>stupid simple</em> white window that I can click on to turn pixels black
and save it as a PNG image. If I could get that far, I could do all the rest.</p>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/before-after.png" alt="Before and After"></p>
<p></p>
<hr>
<h1><a name="a-progression-in-screenshots" class="anchor" href="#a-progression-in-screenshots" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
A Progression in Screenshots</h1>
<h2><a name="my-first-milestone-was-very-modest-click-to-set-pixels-on-a-window-june-2018" class="anchor" href="#my-first-milestone-was-very-modest-click-to-set-pixels-on-a-window-june-2018" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
My first milestone was very modest: click to set pixels on a window (June 2018)</h2>
<p>Thinking too much about the "big picture end result" of my game would probably
have paralyzed me into not even getting started.</p>
<p>So at first I just set some <strong>very simple</strong> goals for myself. I'm not making
a game yet, I'm just playing around with some minimal possible prototypes,
something with a clear spec in mind and a clear definition of "done."</p>
<p>I just wanted a blank white window that I can click on to turn pixels black.</p>
<p>This is the very first screenshot of my project:</p>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2018-06-17_10-42-47.png" alt="Screenshot of a blank white window with a small crudely drawn picture"></p>
<p>For my choice of software stack I chose the <a href="https://golang.org" rel="nofollow">Go</a> programming
language and the <a href="https://www.libsdl.org" rel="nofollow">SDL2</a> library for handling graphics,
controller inputs and audio. SDL2 provides a <em>rather</em> low level and barebones API
to handle getting pixels on a screen; nothing fancy, just functions like DrawPoint,
DrawLine, DrawRect and loading and copying bitmap images to a window. It takes care
of all the <em>really</em> low-level tedium of dealing with various kinds of basic hardware
devices, but it doesn't offer you much in the way of making a game on top of it.
All the heavy lifting is still up to you; particle effects and fancy features like
that won't come to my game unless I feel up for programming those algorithms myself.</p>
<p>But, I do enjoy having that level of control and learning how game fundamentals
<em>actually</em> function, instead of just "checkbox for Gravity" like Unity would give
me and I don't know how it <em>works.</em></p>
<p>My <strong>actual</strong> notes to self about my first milestone of "basic SDL2 paint program"
read as follows:</p>
<ul>
<li><input type="checkbox" checked="" disabled=""> Create a basic SDL window that you can click on to color pixels.
<ul>
<li><input type="checkbox" checked="" disabled=""> Connect the pixels while the mouse is down to cover gaps.</li>
</ul></li>
<li><input type="checkbox" checked="" disabled=""> Implement a "screenshot" button that translates the canvas to a PNG
image on disk.
<ul>
<li><code>F12</code> key to take a screenshot of your drawing.</li>
<li>It reproduces a PNG image using its in-memory knowledge of the pixels you
have drawn, <em>not</em> by reading the SDL canvas. This will be important for
making the custom level format later.</li>
<li>The PNG I draw looks slightly different to what you see on the SDL canvas;
maybe difference between <code>Renderer.DrawLine()</code> and my own algorithm or
the anti-aliasing.</li>
</ul></li>
<li><input type="checkbox" checked="" disabled=""> Create a custom map file format (protobufs maybe) and "screenshot" the
canvas into this custom file format.</li>
<li><input type="checkbox" checked="" disabled=""> Make the program able to read this file format and reproduce the same
pixels on the canvas.</li>
<li><input type="checkbox" checked="" disabled=""> Abstract away SDL logic into a small corner so it can be replaced with
OpenGL or something later on.</li>
<li><input type="checkbox" checked="" disabled=""> Implement a command line shell in-game to ease development before a user
interface is created.
<ul>
<li><input type="checkbox" checked="" disabled=""> Add support for the shell to pop itself open and ask the user for
input prompts.</li>
</ul></li>
</ul>
<h2><a name="first-screenshot-of-gameplay-july-2018" class="anchor" href="#first-screenshot-of-gameplay-july-2018" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
First screenshot of "gameplay" (July 2018)</h2>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2018-07-21_17-42-13.png" alt="First screenshot of gameplay"></p>
<p>Pictured above is the very first screenshot of "gameplay." The player character
is represented by a magenta square, and I think I didn't even <em>really</em> have
collision detection hooked up, so the character could move freely and I just
positioned it to <em>look like</em> it's sitting on top of one of the platforms I had
drawn.</p>
<p>At this stage in development, my prototype was able to save and restore your
drawings in a custom (JSON) format and you could toggle between Edit Mode and
Play Mode to draw your level and "play" it.</p>
<h2><a name="the-developer-shell" class="anchor" href="#the-developer-shell" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
The Developer Shell</h2>
<p>One of the <strong>very first features</strong> I ever programmed into my game was the
developer console. You'd press <code>Enter</code> to open a command prompt at the bottom
of the screen in-game, and you could type commands like <code>new</code> or <code>save</code> to
run various game functions in lieu of a proper user interface.</p>
<p>Remember, I'm using SDL2 here, everything I draw on screen I have to come up
with myself, and drawing buttons and user interface elements would take some
work. A text-based command shell to debug my game at run-time or invoke game
features was <em>crucial.</em></p>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2018-07-21_20-41-58.png" alt="First screenshot of the developer shell"></p>
<p>An important feature of the developer shell also was that it can pop open on
its own to ask the user a question. The game still uses the developer shell
today for that purpose: when you save your level for the first time and it
asks you to give it a file name, the developer shell pops open with the question
for you to type a response to.</p>
<p>When I program text input controls for my user interface, this use of the
Developer Shell can be replaced with a better alternative.</p>
<h2><a name="flawless-collision-detection" class="anchor" href="#flawless-collision-detection" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Flawless Collision Detection</h2>
<p>Before putting any more work into user interfaces or the level editor, I <em>needed</em>
to make sure I could get the collision detection working in Play Mode.</p>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2018-07-24_22-25-39.png" alt="First screenshot with collision detection working"></p>
<p>There are plenty of tutorials how collision detection works for 2D platformer
games, but <em>none</em> of them applied to my project. Players can draw their own level
<em>completely</em> freehand, putting pixels <em>anywhere</em> they want, and these pixels should
behave as solid ground during gameplay and pixel-perfect collision detection is
needed. Most 2D platformers are tile-based and collisions are checked whole
regions at a time, but my game needed to <em>literally</em> check every pixel during
movement because any one of them could be solid or fire or whatever.</p>
<p>In the above screenshot the player character, now drawn as a <em>yellow</em> box with
colored collision debug lines on its edges, is perfectly nestled in a corner
of this hill.</p>
<p>The way my algorithm works took advantage of Go's built-in concurrency features:</p>
<ul>
<li>The 4 edges of the player's bounding box (each a different color in the above
screenshot) are scanned end-to-end against the level data to see which drawn
pixels it overlaps with.</li>
<li>These scans run <em>in parallel</em> using goroutines, or background tasks, which
massively sped up the process compared to doing them sequentially like normal.</li>
<li>When moving, these 4 collision line scans are simulated for each pixel-step
along the way from your current X,Y position to the X,Y you are wanting to
wind up at.</li>
</ul>
<p>It seems to work okay for the scope and concept of my game so far!</p>
<h2><a name="creating-a-ui-toolkit" class="anchor" href="#creating-a-ui-toolkit" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Creating a UI Toolkit</h2>
<p>Now, my game is <em>really</em> in need of a user interface. The level editor will need
buttons to select drawing tools, and panels and frames to arrange the interface
in a <em>sane</em> way for my own mental health, and any other kind of UI widget I can
manage to program: checkboxes, menus, windows.</p>
<p>Now, there <em>might've</em> already existed some UI toolkits that use SDL2 but they
would probably be written in C and I am programming in Go. I was fortunate that
my Go SDL2 module came with instructions how I could cross-compile my game for
Windows while running on Linux, so I could avoid a world of hurt trying to ship
my game later down the road; but I didn't want to press my luck bringing in
<em>additional</em> C libraries into my game. SDL2 was a gamble enough!</p>
<p>So I needed to develop <em>my own</em> user interface toolkit in Go. By the way, I have
released this as an open source project alongside my render engine: see
<a href="https://git.kirsle.net/go/ui" rel="nofollow">go/ui</a> and <a href="https://git.kirsle.net/go/render" rel="nofollow">go/render</a>.</p>
<p>The very first UI widgets I programmed were the <strong>Label</strong> and the <strong>Button:</strong></p>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2018-07-25_08-58-48.png" alt="Early UI screenshot showing labels and buttons"></p>
<p>I programmed my UI toolkit to work in layers of abstractions. The <strong>Label</strong> is
the simplest of all widgets: it has a position and a size and it contains text
(provided easily by SDL2_ttf). Then a <strong>Button</strong> is able to wrap <em>around</em> a
child widget, such as a Label, and provide a raised border and click event
handlers. Many of the widgets "extend" or wrap around simpler widgets and produce
increasing layers of complexity.</p>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2018-08-01_18-41-02.png" alt="Screenshot of my GUI Test Screen"></p>
<p>I did my initial experimentation with my UI toolkit <strong>in-game</strong> in a hidden
test screen of my app. The screen is still in the game today! Typing <code>guitest</code>
in the developer console brings up this screen.</p>
<p>Buttons and Labels are one thing, but a real UI toolkit needs to have Frames
too that can parent the other widgets and position them <em>sanely</em> using relative
configuration so that I don't need to micro-manage the X,Y position and size of <em>every</em>
tiny little thing on the screen.</p>
<p>The GUITest was a way to develop, test and debug various widgets and placement
algorithms until I got it somewhat stable enough to spruce up my Level Editor
with.</p>
<h2><a name="first-level-editor-ui-august-2018" class="anchor" href="#first-level-editor-ui-august-2018" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
First Level Editor UI (August 2018)</h2>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2018-08-11_17-25-21.png"></p>
<p>This is an early screenshot of the Level Editor User Interface.</p>
<p>Along the top of the window was a black frame having "menu buttons" for
"New Level", "Save", "Load", etc.; these were just buttons that ran actions
when clicked, as I hadn't programmed proper menus into my UI toolkit yet.</p>
<p>The right side of the screen was a "Palette Drawer" having <strong>RadioButtons</strong>
that set the color I'll draw with. The RadioButton widget extended the Button
by tracking a variable state and works how you'd expect: only the selected
color's RadioButton is pressed "in" at the exclusion of the other colors.</p>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2018-10-08_18-17-25.png" alt="The Doodads Palette"></p>
<p>The <strong>Doodads Palette</strong> was introduced in October: doodads are like reusable
drawings you can drag onto your level.</p>
<p>The Palette drawer on the right became a "tabbed" interface: RadioButtons at
the top could have you choose between "Palette" and "Doodads" to either see your
color swatches or, well, doodads.</p>
<p>Doodads could be dragged out of the palette drawer and onto your level to place
copies of them in your level.</p>
<h2><a name="debug-features-october-2018" class="anchor" href="#debug-features-october-2018" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Debug Features (October 2018)</h2>
<p>For a developer's own mental health, they'll build in "debug features" to help
visualize <em>what the heck</em> is going on while they're trying to fix bugs or figure
out some tricky maths.</p>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2018-10-19_13-12-35.png" alt="Screenshot showing many debug features active"></p>
<p>In the above screenshot, many debug features are active helping me to visualize
game state and positioning of objects. Each <strong>Canvas</strong> widget is outlined in a
red square and has a name in the top-right corner. The two doodads inside my
level additionally have their level coordinates (world position, or WP) shown.
Drawings are subdivided into "chunks" and they are highlighted in yellow; parts
of the level not drawn on have no chunk created yet.</p>
<p>The Canvas widget builds on my UI toolkit but is <em>entirely</em> tied up in my game
logic. It represents a "drawing" which is a general name for Levels and Doodads;
your level is drawn in a Canvas widget and all doodads, in your level and in the
Palette drawer, are also Canvases. The Canvas can scroll and pan and allow
drawing and lots of other features that are used where they make sense.</p>
<p>At this stage in the game, the Doodads were just some nonsense images I sketched
out in-game and had no logic to them, you could just place copies of them around
your level. They wouldn't interact or collide with the player during gameplay.</p>
<h2><a name="some-real-doodads-april-2019" class="anchor" href="#some-real-doodads-april-2019" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Some "Real" Doodads (April 2019)</h2>
<p>Almost one full year into development, this is the first screenshot having "real"
doodads in them: the ones I was designing for real for eventual use in the game,
and not just throwaway sketches.</p>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2019-04-16_23-31-37.png" alt="Doors, Keys and Buttons"></p>
<p>The first doodads created were <strong>Colored Locked Doors & Keys</strong>, <strong>Buttons</strong> and
the <strong>Electric Door</strong> which only opens if powered by a linked Button that gets
pressed by the player.</p>
<p>As you can guess, these were <em>not</em> drawn in-game; the editor was too crude for
that. I drew them in <a href="https://gimp.org" rel="nofollow">The GIMP</a> and, along with my game, I
programmed a command-line tool that understands my game's file formats and is
able to generate a Doodad file based on PNG images, and attach their JavaScript
programming.</p>
<h2><a name="webassembly-june-2019" class="anchor" href="#webassembly-june-2019" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
WebAssembly!? (June 2019)</h2>
<p>So, remember how early on I was using SDL2 for my game? Well, I didn't want to
<em>tie myself down</em> to SDL2, in case later on I wanted to use OpenGL or Vulkan
or some other toolkit in place of it. And also because SDL2 is a C library and
I'm using Go, which has nice high-level data types and features, and using a C
library from Go means you need to write Go <em>like</em> C and that feels clunky and
awkward.</p>
<p>So <em>very</em> early on I had written my own <strong>render library</strong> that would "wrap"
around SDL2 and provide <em>to me</em> a nice Go API that does what I want in terms
that make sense for my program. I want to just DrawRect(Rect, Color) and get a
rectangle on my screen, I don't want to care about the SDL2 API calls that go
into selecting a color and managing the render state.</p>
<p>And my abstraction layer meant I could replace the SDL2 implementation with, oh
I dunno, HTML5 Canvas API calls for JavaScript/WebAssembly.</p>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2019-06-26_23-40-48.png" alt="Screenshot of my game running in a web browser with WebAssembly"></p>
<p>Pictured above was an early version of my game running <em>inside a web browser</em>
because I had compiled it for WebAssembly. On page load it calls the web browser's
API, in a way much like JavaScript would, to select a <code><canvas></code> tag and draw
pixels onto it with the <a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D" rel="nofollow">CanvasRenderingContext2D</a>
API instead of SDL2 and my game could run none the wiser.</p>
<p>The 99% of my game's code knows nothing about SDL2, it knows my render library,
so when I swap out SDL2 for Canvas/WebAssembly my game easily ported to run in
a web browser.</p>
<p>Now, performance wasn't great then, and it's even worse now that my game has
gotten more complicated. A bulk of the bottleneck is in my UI toolkit; a screen
full of buttons incurs <em>many</em> draw calls that I <em>could</em> optimize in the future
by caching textures or something. A dragon to tackle another day.</p>
<p>By the way, my render engine is released as an open source project at
<a href="https://git.kirsle.net/go/render" rel="nofollow">go/render</a> so you can create graphical apps
in Go targeting SDL2 or WebAssembly too.</p>
<h2><a name="level-editor-toolbox-july-2019" class="anchor" href="#level-editor-toolbox-july-2019" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Level Editor Toolbox (July 2019)</h2>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2019-07-08_19-38-40.png" alt="Editor screenshot showing a toolbox on the left edge of the window"></p>
<p>More love for the level editor, I added a left-side toolbox panel housing
RadioButtons with icon images to select from various draw tools:</p>
<ul>
<li>Freehand (pencil, the old default/only way to draw)</li>
<li>Line Tool</li>
<li>Rectangle Tool</li>
<li>Doodad Tool (shows the Doodads Palette in the right drawer when active)</li>
<li>Link Tool</li>
</ul>
<p>The Link Tool provides the channel on which a Button could open an Electric Door
when pressed. You drag a Button and an Electric Door into your level and connect
them with the Link Tool and then they can send signals to each other in-game.</p>
<h3><a name="what-are-doodads-programmed-in" class="anchor" href="#what-are-doodads-programmed-in" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
What are Doodads programmed in?</h3>
<p>Doodads in my game are programmed using JavaScript. And it's not the cool, modern
JavaScript either, but the old ES5 JavaScript we had before <em>Google Chrome.</em> I
would've liked to use something nicer but out of my options this was the best fit.</p>
<p>I'm using <a href="https://github.com/robertkrimen/otto" rel="nofollow">robertkrimen/otto</a> which implements
a JavaScript interpreter <strong>in pure Go.</strong> That is useful because Otto lets me expose
my native Go types and structs <em>directly</em> to the JavaScript interpreter so that
Doodad scripts can call functions in my game <em>easily</em> without any tedious data
translation dances like what you'd get bridging across C language.</p>
<h2><a name="a-gameplay-screenshot-december-2019" class="anchor" href="#a-gameplay-screenshot-december-2019" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
A gameplay screenshot (December 2019)</h2>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2019-12-30_18-00-05.png" alt="Early alpha version gameplay"></p>
<p>The level editor UI had been the fastest evolving side of my game, but here's
a check-in on what gameplay looked like.</p>
<p>I didn't have a player character design yet, so a stand-in was the blue Azulian.
What's an Azulian? It's <a href"https://www.kirsle.net/kanian-azulian-war" rel="nofollow">an inside thing</a>, a character I had
made up in middle school. Since <em>very</em> early versions of my game you played as
a Blue Azulian, and the Red Azulian as an "enemy mob" is still in the game today
(as of time of writing). Both of them will likely go the way of hidden easter eggs
in some future release of my game.</p>
<p>In the above screenshot I had new doodads including the Start Flag, Crumbly Floors,
and blue and orange State Blocks that toggle opposite each other when their
ON/OFF button is hit.</p>
<h2><a name="ui-popup-windows-july-2020" class="anchor" href="#ui-popup-windows-july-2020" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
UI Popup Windows (July 2020)</h2>
<p>Eventually, I programmed "pop-up windows" for my Go UI toolkit which meant I
could shove even more features into my game by stuffing them into pop-up windows
that can be moved around the screen and closed when not needed.</p>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2020-07-09_15-53-25.png" alt="Screenshot of popup windows in the Level Editor"></p>
<p>The general inspiration for my User Interface goals are Rollercoaster Tycoon (1 & 2),
having toolbars and pop-up windows for various tasks.</p>
<p>By this stage in the game, the Toolbox on the left gained an Ellipse and Eraser
Tool, Brush Size/thickness feature, and the Doodads Palette was turned into a
pop-up window so that the Color Palette on the right could shrink in size and
leave more room for your drawing.</p>
<blockquote>
<p><strong>An easter egg?</strong></p>
<p>In my game if you open the developer console with the tilde/grave key and
type in:</p>
<pre><code>boolProp show-hidden-doodads true
</code></pre>
<p>then the Blue Azulian and Boy (player character) become available in the Doodads
window to drop into your level. They both have have no behavior: they are
affected by gravity but don't do much else. These two were the Player Character and
depended on controller inputs to move them, so they do nothing when loaded as
another doodad on your level!</p>
</blockquote>
<h2><a name="gameplay-december-2020" class="anchor" href="#gameplay-december-2020" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Gameplay (December 2020)</h2>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2020-12-29_20-22-44.png" alt="Gameplay screenshot"></p>
<p>By this time I had designed sprites for the player character so that the Blue
Azulian could be retired, and added several new doodads including Warp Doors
and the Red Bird. The Colored Doors also had a re-design away from their original,
front-facing sprite and towards a side-angle profile view of the door.</p>
<h2><a name="and-beyond-today" class="anchor" href="#and-beyond-today" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
And beyond! (Today)</h2>
<p><img src"https://www.kirsle.net/creativity/articles/doodle-dev/Screenshot_2021-07-20_17-26-25.png" alt="Screenshot of v0.7.2"></p>
<p>The above is a screenshot of the latest version of the game. It's still in alpha
release mode, but it has come a <strong>long</strong> way from that first painting prototype
SDL2 program!</p>
<p>It has a <em>bunch</em> of doodads, five example levels built-in, an editable palette,
brush texture patterns (those were fun to program!), you can embed custom doodads
<em>inside</em> level files for easy transport to another computer, and it's <em>rapidly</em>
approaching my definition of "1.0" release status.</p>
<p>I want it to have a "story mode" built-in with a series of levels that automatically
play in sequence, and more doodads and features they can take advantage of, and
get a solid platform going that I can keep on adding to and making better over
time.</p>
<h1><a name="a-forever-project" class="anchor" href="#a-forever-project" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
A "Forever Project"</h1>
<p>Going back to the whole "I wanna make a game!" bit at the beginning... at a certain
point in my life, I realize I don't want to make "a game." Game developers make
games, they work on it for a year, release it, and never look at it again because
they're working on their next project. That's not what I wanted to do.</p>
<p>I wanted a "game project" that I could improve and add features to for as long
as I found it interesting. Like Minecraft. When I begin selling my game at some
point, you'll buy it once and get free updates for as long as I make them. The
game may be clunky and basic now, but who knows how it will evolve? My UI toolkit
looks like "Windows 95" now, because those are easy shapes to draw with primitive
draw calls, but I can add theme support to my UI toolkit and my game <em>immediately</em>
gets a make-over and benefits all at once from it.</p>
<p>And you can even help me with that! My UI toolkit is open source and
<a href="https://github.com/kirsle/ui" rel="nofollow">on GitHub too</a>. As a side consequence of making
my game I'm also making an increasingly featureful UI toolkit that could be used
for <em>other</em> graphical applications for Go developers!</p>
<h1><a name="check-it-out" class="anchor" href="#check-it-out" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Check it out!</h1>
<p>Check out my game's website at <a href="https://www.sketchymaze.com/" rel="nofollow">SketchyMaze.com</a>!
I currently release this game for most desktop PCs (GNU/Linux, Windows, macOS)
as 64-bit x86. Sometimes I release builds for Linux on ARM64 (my game "kind of"
runs on the <a href="https://www.pine64.org/pinephone/" rel="nofollow">Pine64 Pinephone</a>!)</p>
<p>Also check out its <a href="https://www.sketchymaze.com/guidebook/" rel="nofollow">Guidebook Site</a>, the
user manual included with the game. It's full of screenshots and descriptions of
the built-in doodads and how every feature of the game works. If I weren't a
software engineer, I'd have been a writer, I <em>love</em> writing documentation and
you should check it out!</p>
Sketchy Maze v0.7.12021-07-11T22:57:03Ztag:www.kirsle.net,2021-07-11:/sketchy-maze-v0-7-1<p>It's been a while since I <a href"https://www.kirsle.net/project-doodle-on-pinephone" rel="nofollow">last wrote</a> about my
videogame project, Project: Doodle, which has now been given a proper name:
<strong><a href="https://www.sketchymaze.com/" rel="nofollow">Sketchy Maze</a></strong>. There have been a few
releases of the game since I last wrote about <a href"https://www.kirsle.net/project-doodle-v0-4-0" rel="nofollow">version 0.4.0</a>
and they bring some exciting new features!</p>
<p><img src"https://www.kirsle.net/creativity/articles/sketchymaze-0.7.1.png" alt="Screenshot of the title screen of Sketchy Maze"></p>
<p></p>
<hr>
<h1><a name="what-is-sketchy-maze" class="anchor" href="#what-is-sketchy-maze" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
What is Sketchy Maze?</h1>
<p><em>Sketchy Maze</em> is a drawing-based maze game themed around hand-drawn maps on
paper. There are a few built-in example levels (and will eventually have single
player story campaigns), and you can also draw your own levels and make them look
like anything you want, and play them like a 2D platformer game. You get to pick
what colors to draw with, which colors are for solid floors and which ones are
fire, and drag-and-drop some 'doodads' such as Buttons, Keys and Doors to add
interactive elements and create puzzles and obstacles.</p>
<p>And those doodads? You can create your own, too, and program them in JavaScript
to do whatever you want. Or you can download and play custom maps and custom
doodads made by other players. Your imagination is the limit!</p>
<p><img src"https://www.kirsle.net/creativity/articles/sketchymaze-0.7.1-gameplay.png" alt="Screenshot of gameplay"></p>
<p>The inspiration for this game came from my own childhood. I'm a 90's kid, and when
I was growing up with videogames like <em>Sonic the Hedgehog</em> and <em>Super Mario Bros.</em>,
I would often draw my own "levels" with pencil and paper of a 2D platformer
style game. I would borrow ideas from all the games I liked, and would draw mazes
that had features like buttons, keys and doors, and then "play" my level with my
imagination, envisioning a character working their way through my maze, and
keeping score in my head about which keys were found and what doors can be
unlocked, or how a button might open a door somewhere else in the level (and I'd
draw a little dotted-line connecting the button to the door so I wouldn't forget).</p>
<p>When you're drawing a level on paper, it can be whatever you want. You can draw
a castle or a cave. This game is a manifestation of my childhood imagination.</p>
<p>Check outs its website at <a href="https://www.sketchymaze.com/" rel="nofollow">SketchyMaze.com</a>!</p>
<h1><a name="what-s-new" class="anchor" href="#what-s-new" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
What's New?</h1>
<p>There have been a handful of releases since my last blog post. You can always
check the latest change log <a href="https://www.sketchymaze.com/guidebook/changes.html" rel="nofollow">on the Guidebook site</a>.</p>
<p>Some of the key highlights include:</p>
<ul>
<li><strong>Bundle custom doodads <em>with</em> your custom levels!</strong> If you've created a custom
map and it makes use of a bunch of custom doodads, there is now an ability to
"publish" your level for easy sharing! All of its custom doodads will come embedded
<em>inside</em> of the .level file, so that it will "just play" on someone else's
computer.
<ul>
<li>Note: this feature is <a href="https://www.sketchymaze.com/register/" rel="nofollow">not available in the free version</a> of the game. Buy me
a beer to get a full version forever. Options to monetize the game are being
sorted out eventually.</li>
</ul></li>
<li><strong>Custom level wallpaper images:</strong> if you don't like the built-in, paper-themed
level wallpapers, you can browse and pick your own image to use. Your image
bundles <em>with</em> the level so it will appear as expected on someone else's
computer. The free version of the game <strong>can</strong> use this feature!</li>
<li><strong>Stylish brush patterns:</strong> in the Palette Editor you can choose from a variety
of patterns that affect the look of a color when it's drawn onto your level.
The idea is to have your strokes appear as pencil graphite or marker rather
than solid colored pixels.</li>
<li><strong>New doodads:</strong> the Warp Doors and Small Key Door. Also, several doodads have
been increased in size to better patch the recently updated player character.</li>
<li><strong>New wallpapers:</strong> Graph paper and Dotted paper were added to be lighter
variants of the Blueprint.</li>
</ul>
<p><img src"https://www.kirsle.net/creativity/articles/sketchymaze-0.7.1-editor.png" alt="Screenshot of the level editor"></p>
<h1><a name="downloads" class="anchor" href="#downloads" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Downloads</h1>
<p><em>Sketchy Maze</em> is available for free on all desktop computers, including GNU/Linux,
Windows and Mac OS (Intel).</p>
<p>It is still in <strong>early alpha release mode.</strong> The game is functional as a proof
of concept but still needs polish and more built-in levels and doodads.</p>
<p>Check out the <a href="https://www.sketchymaze.com/download/" rel="nofollow">Sketchy Maze website</a> for
downloads and more information about the game. The
<a href="https://www.sketchymaze.com/guidebook/" rel="nofollow">Guidebook</a> site contains a lot of
screenshots and in-depth documentation about the game's features.</p>
"Just compile it yourself!" and other misguided security suggestions2021-06-09T18:55:14Ztag:www.kirsle.net,2021-06-09:/just-compile-it-yourself-and-other-misguided-security-suggestions<p>On forums like <a href="https://www.reddit.com/r/privacy" rel="nofollow">r/privacy</a> people often discuss
the role of open source software when it comes to privacy and end-to-end encrypted
messaging applications. The general consensus is: a privacy focused app <strong>must</strong>
be open source so that people can get their eyes on the source code and audit it
for security vulnerabilities, verify it's doing what it says in the tin and
without any secret government backdoors built in that would undermine the security
and reveal peoples' private chats.</p>
<p>These are all well and good: if the source code is not open, you can't verify the
code <em>isn't</em> doing something sneaky like uploading your encryption keys to the
service provider or whatever. But, open source alone isn't a silver bullet to
help guarantee the security of the app:</p>
<ul>
<li>Just because the code is readable and somebody <em>could</em> audit it for bugs, doesn't
actually mean anybody <em>does</em>. Some vendors of such software may hire security
firms to deliberately audit their code, but for random small projects that haven't
been formally audited, "open source != automatically secure" -- but still, it
is better than closed source where <em>nobody</em> can audit the code.</li>
<li>Just because the source code is available doesn't mean the program you download
from the App Store is built on exactly the same code. Google Chrome, for example,
is built on top of the open source Chromium browser but after Google injects a
few proprietary services and features; the Chrome program released by Google has
features not found in the Chromium source code. This can be helped by so-called
"reproducible builds" and I'll cover that below, but reproducible builds do not
come "for free."</li>
</ul>
<p>In this post I'll address a few common tired things I hear people on r/privacy
say in regards to this topic and how it's never quite that simple.</p>
<p></p>
<h2><a name="just-compile-it-yourself-from-the-open-source-code" class="anchor" href="#just-compile-it-yourself-from-the-open-source-code" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
"Just compile it yourself from the open source code!"</h2>
<p>Take the Signal messenger app for example: it's an end-to-end encrypted messenger
and the client apps are open source (but the server-side code is not). You can
audit Signal's app source and verify it's encrypting messages locally on your
device and that it handles the encryption keys well, so that <em>even though</em> the
server side isn't open source, one can verify that the client app is encrypting
and the service provider couldn't get access to your chats if they wanted to.</p>
<p>Signal releases their app on the mobile app store markets, and when you download
it from here, you're downloading a pre-built binary program that the company
built from the source code, but with binary releases there's always a <em>chance</em>
that the binary has something 'extra' added that isn't available in the source.</p>
<p>So to be the most security-conscious, you might download the Signal source code,
read through it yourself and audit its security, and then compile <em>your own</em>
Android .apk package from the source code you have sitting in front of you. Then
you <em>know</em> what code your app is running.</p>
<p>All good and doable in theory, but has many practical problems in practice:</p>
<ul>
<li>Many users don't know how to compile software from source code.</li>
<li>And even if they did, keeping on top of updates becomes a chore, as you
always need to re-download the latest source, re-compile it yourself.</li>
<li>If you use 20 different open source Android apps and you're compiling all of
them from source all the time, this problem magnifies massively.</li>
</ul>
<p>I'll give you a practical example from my life:</p>
<p>In GNU/Linux, most software is open source and compiling software yourself is
typically not difficult at all. It's almost always a matter of just getting the
source and running "./configure; make; make install" and it's built, whether we're
talking about Firefox or the Apache web server program.</p>
<p>One time, I had a web server running a RedHat based Linux distribution, and I
had need to build my own Apache web server from sources. Apache has a feature
called "suexec" where, if a website includes some PHP or Perl CGI scripts, that
Apache would run the script <em>as the user who owns the file</em>, so that any files
created by the script would be owned as the user and permissions are all sane.</p>
<p>For example: /home/kirsle/www is where the user kirsle keeps their website, and
they installed WordPress or something there; it's better if WordPress's PHP scripts
run <em>as</em> kirsle so that config files and uploads are owned by kirsle and are put
in kirsle's home directory, rather than the default of all PHP scripts being run
as the Apache user and not having write permission to kirsle's home folder and
any files it creates are owned by Apache and not by kirsle.</p>
<p>So I wanted Apache's suexec root to be /home instead of the default /var/www,
only this is a <em>compile-time option</em>, so you must rebuild Apache from source code
and tell it the suexec root at that time. The vendor-provided Apache binary
shipped by RedHat was built with the suexec root being /var/www and I could not
have user websites under /home with their build of Apache.</p>
<p>So, I compiled it myself.</p>
<p>And then a week later, RedHat pushes software updates and included in those is
a bugfix release of Apache; if I simply updated my software, I'd get RedHat's new
Apache which would <em>break my shit</em> because RedHat's Apache doesn't use my suexec
root. Instead, I'd need to go and fetch the new Apache myself, compile it myself,
and do this every single week whenever RedHat pushes a new Apache, and if I ever
got lazy or wasn't paying attention, all my websites break!</p>
<p>I eventually left the RedHat ecosystem for Debian, which had an optional package,
<code>apache2-suexec-custom</code> which gave Apache a config file to set the suexec root
<em>at run time</em> so I didn't need to re-compile it.</p>
<p>Anyway: building Linux apps is easy, but you don't want to maintain your own
fork, it was hard enough with just one program. On Android, building apps is
significantly more complex than this, you need to download the full Android Studio SDK
and run a bunch of steps, and still you'd end up needing to maintain your own
builds of your apps forever, keeping on top of updates and rebuilding the app all
the time.</p>
<p>If you have 20 open source apps on Android and you want to build them all from
source on every update... are you really going to? I doubt it. You'll either end
up with grossly out-of-date apps (where the upstream company had released security
patches and bugfixes, but you haven't gone and re-compiled all your apps in a while),
or else you make "app compilation" into a full time job.</p>
<h2><a name="reproducible-builds-bro" class="anchor" href="#reproducible-builds-bro" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Reproducible Builds, bro!</h2>
<p>So to address the problem that "the binary release you get from the App Store
might not perfectly reflect the original source code that it allegedly was
built from", we have <a href="https://reproducible-builds.org/" rel="nofollow">Reproducible Builds</a>
which a lot of non-technical users (who are <em>not</em> software developers) tout around
as being some kind of magic silver bullet.</p>
<p>The idea is that, with reproducible builds, you can download the source code to
a program, build it to a binary, and get exactly the same binary bit-for-bit no
matter <em>who</em> built the program. So for Signal's case: you'd download the binary
Signal release from the Google Play Store, take a checksum hash of their binary,
and then you compile <em>your own</em> Signal from source code, and take a hash of
<em>your</em> binary. With Reproducible Builds, the two hashes should be perfectly
identical: your copy is bit-for-bit the same as the one Signal released to the
app store, giving you the confidence that Signal Co. built their app from the
exact same sources you did and there's no room for them sneaking in a change that
wasn't represented in the source code.</p>
<p>This is all good, and it does work where it's been implemented, but Reproducible
Builds are by no means "free" and they incur significant work by the original
software developers of a program to make their builds reproducible.</p>
<p>I'll give you a practical example you can test yourself:</p>
<p><div class="highlight"><pre><span></span><span class="kn">package</span> <span class="nx">main</span>
<span class="kn">import</span> <span class="s">"fmt"</span>
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">"Hello world!"</span><span class="p">)</span>
<span class="p">}</span>
</pre></div>
</p>
<p>This is a "Hello world" program in the Go programming language. Very short and
simple, you'd expect that this program compiles to the exact same binary version
every time, but no!</p>
<p><div class="highlight"><pre><span></span><span class="c1"># When hello.go was at /home/kirsle/Documents</span>
$ go build -o hello hello.go
$ md5sum hello
db0db0a8828d0768a7862938322fc94f
<span class="c1"># Let's move hello.go into a different folder, and try again</span>
$ cp hello.go /home/kirsle/Pictures/
$ <span class="nb">cd</span> /home/kirsle/Pictures
$ go build -o hello hello.go
$ md5sum hello
05f11df0b806ad18078c4498af4a9f45
<span class="c1"># To be clear, both md5 sums together:</span>
$ md5sum ~/Documents/hello ~/Pictures/hello
05f11df0b806ad18078c4498af4a9f45 /home/kirsle/Pictures/hello
db0db0a8828d0768a7862938322fc94f /home/kirsle/Documents/hello
</pre></div>
</p>
<p>How could such a simple program come out to two different binaries, when both
were built on the same computer by the same user with the same software environment?</p>
<p>Because the folder the source code is in was different! If I build the binary
from ~/Documents a second time, I do get a matching binary back out:</p>
<p><div class="highlight"><pre><span></span>~/Documents$ go build -o hello hello.go
~/Documents$ go build -o hello2 hello.go
~/Documents$ md5sum hello hello2
db0db0a8828d0768a7862938322fc94f hello
db0db0a8828d0768a7862938322fc94f hello2
</pre></div>
</p>
<p>I picked on the Go programming language here because one of the things Go builds
in to your binary is the file paths of the source code, but issues <em>like</em> this
affect all programming languages. Sometimes the date and time of the build will
affect the output; sometimes the <em>version of your C compiler</em> will affect the
output; sometimes the fact you built it on Fedora and I built mine on Ubuntu will
cause us to get different outputs. <strong>By default,</strong> software is not reproducible,
and you actually need to go pretty far out of your way to design software that
<em>is</em>. Seriously: just browse around the <a href="https://reproducible-builds.org/" rel="nofollow">Reproducible Builds</a>
website and read their guidelines of what problems you encounter and how to get
around them.</p>
<p>What you end up doing for Reproducible Builds is defining a very strict build
environment, like:</p>
<ul>
<li>Using a very particular Linux distribution (e.g. Ubuntu 21.04)</li>
<li>Using very specific versions of all your software (same C compiler version,
same versions of all shared libraries that go into your program, etc.)</li>
<li>Using a very specific build path: like all code must live in /opt/source and
be built from there, as, building code in a user's own home directory can
affect the result as seen in the Go example above.</li>
<li>Sometimes, using a very specific system clock time: if you can't remove all
time-sensitive parts in your code, but the system clock is still making your
builds not reproducible, you need to control for the system clock as well.</li>
</ul>
<p>You end up getting something resembling a <a href"https://www.kirsle.net/linux-containers" rel="nofollow">full fat virtual machine</a>
environment just to pin down all the moving parts. This all requires lots of man hours
of effort on the part of the software vendor; if you're Signal Co. and your whole product
is about security, and you have a large staff of developers to throw at the problem,
you go through this effort. But if you're a random lone developer working on a small
hobby project, you don't have the time or energy to do this. Reproducible Builds
are not a golden ticket solution to this problem because Reproducible Builds do
not come cheap.</p>
<p>And even when an app does offer reproducible builds: how do you, the ordinary
consumer, verify to yourself that your source code of Signal built to the same
binary as the app store? The version of Signal you built out of your home
directory <strong>will not</strong> be bit-for-bit identical to the Play Store release of the
app. To verify the build yourself, you'll need to reproduce <em>exactly</em> the precise
dev environment that Signal built theirs under and these are hard steps to follow
<em>even if</em> you're a developer yourself and are well versed in all the technologies
needed to do so.</p>
<p>And you're going to do that 20 times over for the 20 open source apps you run
on Android? Yeah right.</p>
<h2><a name="so-what-can-i-do" class="anchor" href="#so-what-can-i-do" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
So what can I do?</h2>
<p>Start by defining what your threat model actually is: what data of yours do you
want to keep secret, and from who do you want to keep it from? If your threat
model involves hiding from nation state intelligence angencies, good luck! If
they want to get you, they'll get you. But unless you're Edward Snowden this is
probably not your threat model.</p>
<p>Do you just want to keep advertisers out of your biz? Keep Google from reading
your chats and selling you ads and propaganda? Keep your boss from reading your
emails? Keep your friends from going through your phone? For most of these kind
of "ordinary" threat models, you're probably fine just downloading Signal from
the app store and not worrying too much about the whole thing.</p>
<p>But if you did have a requirement that, absolutely 100% for certain, your chats
can NOT leak and you have a very strong requirement around this: then this would
be a perfect time to compile your own apps from source code, verify with
reproducible builds, audit the source yourself to make sure its security is tight,
and so on, and only for the specific apps you need (doing all this work for 20
different apps would be too much, imho).</p>
<p>I'll just tell you about the balance I take with this personally:</p>
<ul>
<li>Running a Linux distribution, <em>most</em> of my software was built by the maintainers
of my distro, from open sources, and I trust them to do a good job and to respond
quickly to security concerns. Fedora, Debian, Ubuntu etc. always tend to get patches
out by the next day whenever security vulnerabilities are discovered.</li>
<li>On Android, I prefer to get my apps from the <a href="https://f-droid.org" rel="nofollow">F-Droid</a> open
source app store rather than Google Play; for example, Nextcloud is available on
both F-Droid and Google Play and I prefer the F-Droid versions. This is because
F-Droid builds all apps <em>themselves</em>: developers submit their source code to F-Droid
and then F-Droid's maintainers build it, in a model similar to Linux distributions,
and the developer would have a more difficult time sneaking in some dirty code when
it must be there in the source for F-Droid to see.</li>
<li>And I stay mindful about which apps I'm using and their features. <a href"https://www.kirsle.net/why-i-don-t-use-signal" rel="nofollow">I use Telegram</a>
as my main messenger, despite the fact that it is not end-to-end encrypted: normal
chats are encrypted between you and the server, but on the server they are readable
in clear text and the company could read them if they wanted. If I want to discuss
something sensitive that I want E2E encryption for, I would use a different app
better tailored for that, like Signal. Telegram is "private <em>enough</em>" for my
everyday mundane conversations but I'm always conscious that it's not "truly
end-to-end secure" and that my chats could leak or be subpoena'd one day.</li>
</ul>
Blockchain in a nutshell2021-05-09T22:50:41Ztag:www.kirsle.net,2021-05-09:/blockchain-in-a-nutshell<p>Have you ever wondered <em>basically</em> how blockchains work and what it means to
"mine a Bitcoin" and why it's a time-consuming (and energy-intensive) process to mine
one? In this blog post I'll summarize what <em>basically</em> drives blockchains and how
they work, from my understanding of them anyway.</p>
<p>If you're <em>anywhere</em> close to a novice web developer or have ever hashed a password
in your life, you already know the basic technology at play here. And even if
you haven't, I think I can get you caught up pretty quickly.</p>
<p>The explanation I give below is surely <em>super simplified</em> and is based on my reading
of how these work, along with several "Create your own blockchain in under 200 lines of
code" type of tutorials which you could find for <a href="https://dzone.com/articles/how-to-create-your-own-cryptocurrency-blockchain-i" rel="nofollow">Python</a>,
or <a href="https://freestartupkits.com/articles/technology/cryptocurrency-news-and-tips/how-to-build-a-blockchain-in-javascript-in-20-minutes/" rel="nofollow">JavaScript</a> or anything. It <em>doesn't</em> cover how the decentralized networking aspects work or
any of those details, but just the basics on the cryptography side.</p>
<p></p>
<h2><a name="hashing-algorithms" class="anchor" href="#hashing-algorithms" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Hashing algorithms</h2>
<p>A hashing algorithm takes some data as input and it produces a "random" looking
output of a fixed length. Historically, hashing algorithms have been used by
websites to store user passwords <em>without</em> the website owner being able to find
out what everyone's password is.</p>
<p>While the output of a hash function <em>looks</em> random, you actually get exactly the
same output hash given the same inputs. For example, with the <a href="https://en.wikipedia.org/wiki/MD5" rel="nofollow">MD5</a>
hashing algorithm and an input of the word <code>password</code> you <strong>always</strong> get the MD5 hash of
<code>5f4dcc3b5aa765d61d8327deb882cf99</code> out. If you add a number to the end
(<code>password1</code>), the hash is <code>7c6a180b36896a0a8c02787eeafb0e4c</code> which looks
<em>wildly</em> different. Here are a few more examples:</p>
<ul>
<li><code>password2</code> = <code>6cb75f652a9b52798eb6cf2201057c73</code></li>
<li><code>password3</code> = <code>819b0643d6b89dc9b579fdfc9094f28e</code></li>
<li><code>Password</code> = <code>dc647eb65e6711e155375218212b3964</code></li>
<li><code>MyB$GSecretP@ssW0rd12345</code> = <code>f8963d1c3c7b402c7e6539c21a3f1833</code></li>
</ul>
<p>So even if you modify the input value <em>just a tiny bit</em>, the output looks wildly
random and different to before; but every single time <code>MyB$GSecretP@ssW0rd12345</code>
is hashed as MD5, it always comes out as <code>f8963d1c3c7b402c7e6539c21a3f1833</code>, and
so a website would store just the output hash and that way it can prove you entered
the correct password if it hashes to the same value the website stored in its
database.</p>
<blockquote>
<p><strong>Note:</strong> MD5 is now well-known to be a <strong>very</strong> weak and insecure algorithm
and has several major flaws. It used to be an industry standard algorithm for
password hashing before ~2005 or so, but is no longer suitable for most modern
applications. Nonetheless, the size of hash it produces is short & sweet and
it's a fast enough algorithm for the purposes of this blog post.</p>
<p>Also, real blockchains use longer and more modern hashing algorithms, but
they all function the same in principal.</p>
</blockquote>
<h2><a name="looking-for-interesting-hashes" class="anchor" href="#looking-for-interesting-hashes" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Looking for "interesting" hashes</h2>
<p>You'll notice above that I showed the example hashes of the words password1,
password2 and password3 -- all are basically the word 'password' plus a number
that starts at 1 and incremented each time, to see how the hash turns out.</p>
<p>The hash looks "random" each time, but eventually, if you go for long enough,
you might happen upon a hash that has an interesting property, like that maybe
6 of its right-most digits would come out as zeroes instead of random noise.</p>
<p>In fact, the magical number that does this is 10,456,925:</p>
<ul>
<li>MD5("password10456925") == "5eb62e644f71a22369b5a2d172<strong>000000</strong>"</li>
</ul>
<p>The right-most six digits of this hash came out as zeroes. How did I come to
the number of 10,456,925 though? By trial-and-error, starting from 1 and counting
up and up until I found the hash that fit this criteria of ending with six zeroes.</p>
<p>Well actually, I wrote a script to compute this for me, and it took about 3.6
seconds on my laptop; this is because MD5 is very fast and looking for six zeroes
wasn't so big of an ask; what if I wanted <em>seven</em> zeroes on the end of it?</p>
<ul>
<li>6 zeroes: 10,456,925; MD5("password10456925") == "5eb62e644f71a22369b5a2d172000000" <strong>(3.6 seconds)</strong></li>
<li>7 zeroes: 85,950,218; MD5("password85950218") == "88d8efac3879874c50814cef40000000" <strong>(29.59 seconds)</strong></li>
<li>8 zeroes: you tell me, I gave up after waiting 10 minutes.</li>
</ul>
<p>While it took some time for me to compute the magic number that produced an
interesting hash, it takes no time at all for a computer to verify my finding:
producing a single hash of a single input takes virtually no time at all, and
a computer can see that "password" + "85950218" produces the hash with seven
trailing zeroes without needing to reproduce all of the work that went in to
finding that number in the first place.</p>
<h2><a name="mining-a-coin" class="anchor" href="#mining-a-coin" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Mining a coin</h2>
<p>In a blockchain-based cryptocurrency, the word "password" in the above example is
replaced with a transaction log (a record of who is sending money to who), and
the miners on the network take that transaction message and add a number to it,
called a 'nonce,' beginning at 1 and counting up and up until the magic number
is found that produces a hash with an interesting property like this, such as
a number of trailing zeroes on the end.</p>
<p>The difficulty is controlled in how many zeroes you want back; we saw that
six zeroes took basically no time, seven took a bit longer, and eight took
exponentially longer still; if coins are being mined too quickly, the network
changes the difficulty factor to slow down the next coin.</p>
<h2><a name="what-makes-it-a-chain-then" class="anchor" href="#what-makes-it-a-chain-then" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
What makes it a 'chain' then?</h2>
<p>The way you create a validated <em>chain</em> of such hashes is that you take the
previous hash as part of the message you're computing.</p>
<p>Say the very first message ever mined had a hash of 88d8efac3879874c50814cef40000000
with seven zeroes at the end. The next message to mine then might look like this:</p>
<pre><code>parent: 88d8efac3879874c50814cef40000000
message: password
nonce: 1
</code></pre>
<p>The MD5 hash of the above message is 4419e1e83f3cb7e13cfba489382fecbb; then you
make the "nonce:" be 2 and try again, then 3 and try again, and so on. The next
winning hash becomes e5f2ac163622785bbfef6710c0000000 with a nonce value of
338,188,800 calculated after 3 minutes 15 seconds on my laptop:</p>
<pre><code>parent: 88d8efac3879874c50814cef40000000
message: password
nonce: 338188800
</code></pre>
<h2><a name="a-script-you-can-play-with" class="anchor" href="#a-script-you-can-play-with" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
A script you can play with</h2>
<p>Here is a simple Perl script I wrote for this blog post. Every programming
language has an MD5 hashing library available, and this Perl script probably
will work out-of-box on any Linux and Mac OS system:</p>
<p><div class="highlight"><pre><span></span><span class="ch">#!/usr/bin/env perl</span>
<span class="k">use</span> <span class="nn">Digest::MD5</span> <span class="sx">qw(md5_hex)</span><span class="p">;</span>
<span class="k">my</span> <span class="nv">$message</span> <span class="o">=</span> <span class="s">"password"</span><span class="p">;</span>
<span class="k">my</span> <span class="nv">$nonce</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">my</span> <span class="nv">$difficulty</span> <span class="o">=</span> <span class="mi">7</span><span class="p">;</span> <span class="c1"># number of zeroes you want to find</span>
<span class="k">while</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="k">my</span> <span class="nv">$test</span> <span class="o">=</span> <span class="nv">$message</span> <span class="o">.</span> <span class="nv">$nonce</span><span class="p">;</span>
<span class="k">my</span> <span class="nv">$md5</span> <span class="o">=</span> <span class="n">md5_hex</span><span class="p">(</span><span class="nv">$test</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$md5</span> <span class="o">=~</span><span class="sr"> /0{$difficulty}$/x</span><span class="p">)</span> <span class="p">{</span>
<span class="k">print</span><span class="p">(</span><span class="s">"FOUND IT: nonce=$nonce hash=$md5\n"</span><span class="p">);</span>
<span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1"># Uncomment this if you want to see every single try:</span>
<span class="c1">#print("$test: $md5\n");</span>
<span class="nv">$nonce</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</p>
<p>You can play with the $difficulty value to look for more or fewer zeroes at
the end, or change the $message to a different string and notice that the magic
winning $nonce will be a wildly different number then. Uncomment out the print()
towards the end and you can see every guess attempted and what its hash was,
though this will drastically slow down the script; a modest consumer PC can crank
out tens-of-millions of MD5 hashes per second but printing a line of text to
your terminal window takes a drastic amount of time comparatively.</p>
<h2><a name="addendum-git-is-basically-a-blockchain" class="anchor" href="#addendum-git-is-basically-a-blockchain" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Addendum: Git is <em>basically</em> a blockchain</h2>
<p>Git is a popular version control system for developers. If you've used Git,
this section is for you, and if not -- no worries!</p>
<p>Git users may be familiar with the concept of a "revision hash" which tracks a
specific change made in the history of your source code. You author a bunch of
changes, run <code>git commit</code> and write a description about your change, and it goes
into the <code>git log</code> along with a random hash; with that hash, a different developer
could check out exactly the version of code you wrote.</p>
<p>The git commit history is <em>basically</em> a blockchain: the hash is generated by
taking the changes you've prepared + your commit message describing those changes +
the "parent commit" hash all together.</p>
<p>This is why if you go back and revise an old commit from months ago in your
project, you break everybody else, because the history of "this commit came after
that commit" is hashed as part of subsequent commits all the way down the chain;
revising a historical commit causes <em>every</em> subsequent commit to be hashed differently
and you'll piss off all the other developers who now have broken copies of the
code history!</p>
<p>You could play with your git commit history by repeatedly doing "git commit --amend"
and modifying your commit message, including a nonce counter from 1 to n, until
the commit hash has some property you like.</p>
<p><div class="highlight"><pre><span></span>% git init
Initialized empty Git repository in /home/kirsle/git/test/.git/
% <span class="nb">echo</span> <span class="s1">'Hello'</span> > README.md
% git add .
% git commit -m <span class="s2">"Initial commit"</span>
% git show
commit 0bb4980598954dbb042e9d9716e3db5f81a14a38 <span class="o">(</span>HEAD -> master<span class="o">)</span>
Author: kirsle
Date: Sun May <span class="m">9</span> <span class="m">15</span>:28:37 <span class="m">2021</span> -0700
Initial commit
<span class="c1"># Play with nonces and re-roll that commit hash...</span>
% git commit --amend -m <span class="s2">"Initial commit + 1"</span>
% git show
commit e0ae47bd3599e576ff39ed5a46bbddf93a25afed <span class="o">(</span>HEAD -> master<span class="o">)</span>
Author: kirsle
Date: Sun May <span class="m">9</span> <span class="m">15</span>:28:37 <span class="m">2021</span> -0700
Initial commit + <span class="m">1</span>
<span class="c1"># Again...</span>
% git commit --amend -m <span class="s2">"Initial commit + 2"</span>
% git show
commit 343946b2fb12db5422e4efd1a7e3af1674a6718e <span class="o">(</span>HEAD -> master<span class="o">)</span>
Author: kirsle
Date: Sun May <span class="m">9</span> <span class="m">15</span>:28:37 <span class="m">2021</span> -0700
Initial commit + <span class="m">2</span>
</pre></div>
</p>
Visual perception and peeking thru the veil2021-04-02T21:17:55Ztag:www.kirsle.net,2021-04-02:/visual-perception-and-peeking-thru-the-veil<p>Among my <strong>many</strong> diverse interests, one thing that fascinates me is to
contemplate the nature of the universe and what Reality is made of, or at least,
what my <em>perception</em> of Reality is made of and how the inner mind works.</p>
<p>To that end, topics such as quantum physics, simulation theory, and esoteric
writings from the world's oldest religions like Hinduism and Gnosticism are
interesting to me, and I like to <a href"https://www.kirsle.net/42" rel="nofollow">talk crazy</a> about that sort of thing
from time to time.</p>
<p>In this post, though, I'm going to write strictly about <strong>visual perceptions</strong>
that I've experienced at different times in my life. Many are related to
psychotropic compounds, including cannabis, but now I'm able to experience some
crazy things just by meditating while sober too.</p>
<h3><a name="i-learned-how-to-meditate-my-way-into-tripping-balls-sober" class="anchor" href="#i-learned-how-to-meditate-my-way-into-tripping-balls-sober" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
I learned how to meditate my way into tripping balls, sober.</h3>
<p>The other day, quite by accident, I learned how to enter a fully "tripping balls"
state of mind, while completely sober, purely by meditating and staring blankly
out into space.</p>
<p>All I was trying to do was meditate, and keep my mind shushed and quiet, for as
long as I could manage to, and push to set a new personal record for myself. I'd
been practicing meditation for a couple of years, since my
<a href"https://www.kirsle.net/spiritual-awakening-in-practical-terms" rel="nofollow">spiritual awakening</a> in 2018. So I was
just focused on keeping my mind still, but kept my eyes open, and was staring
blankly out at the walls of my apartment, which had a complex surface to them.</p>
<blockquote>
<p>Complex surface? By this I mean, my walls had a sort of "sprayed on" finish to
them, similar to ceilings in many homes, so instead of a smooth finish or tiles
or w/e, the wall is 'chaotic' and messy, with ridges and dents and lines and
complexity. Any complex surface will do.</p>
</blockquote>
<p>So I was just staring, focused on a single point on the wall, mind still, and
I kept this up even while my visual perception began to fall apart (as it does
due to the sensory tolerance of staring at the same image for so long -- this
much I knew would happen even from my early childhood when I'd zone out and
daydream while staring at trees or things). It <em>is</em> a bit hard to pull off, I
get a strong urge to blink or move my eyes when my perception begins to fall
apart, but with some practice you can power through this part.</p>
<p>What happened next is where it started to get interesting.</p>
<p>You know those <a href="https://en.wikipedia.org/wiki/Closed-eye_hallucination" rel="nofollow">"closed eye" visuals</a>
you get when your eyes are shut? Random colors and blobby shapes and so on. Well,
I began to see these same sorts of visuals while my eyes were open. They were
overlaid on top of the image of the wall I was staring at. Only then, instead of
the colorful blobs doing their own thing, they started to "play off of" the
patterns on the wall; they'd cling to the ridges and edges, and make the details
on the wall begin to wiggle a bit, interacting with it instead of the blobs simply
doing their own (usual) thing over top.</p>
<p>Eventually from the colored visuals emerged some fractal-like patterns, and before
too much longer, the visuals came to reach full-on 'tripping balls' territory, like
the peak of a psychedelic trip on mushrooms or similar. Rainbow colors washing over
the wall, every little detail is wiggling and dancing around, fractal patterns,
and even these <em>tiny</em> details I didn't even notice were there emerged and those
were wiggling and moving around too. If you've dabbled in psychedelics, you know
what I'm talking about, only no such substances were necessary: I meditated my way
into seeing this stuff. I didn't even expect this was possible!</p>
<p>And as soon as I'd look away? Gone. Back to normal, nothing wiggling around
anymore, Reality is back in its place.</p>
<p>Now, the <em>first</em> time I pulled this off, I <em>had</em> smoked a single hit of cannabis,
as I do many days of the week (it's legal for adults in Oregon). But when I pulled
this off, nothing about the experience felt related to the weed in particular, and
that I should be able to do this while completely sober, and can bring on these
visualizations <em>at will</em> any time I choose.</p>
<p>The next day I tested exactly this: no weed, no nothing, just laid on my bed and
stared at my ceiling while meditating and waited for the visuals to come on.</p>
<blockquote>
<p>Try it yourself, I'm curious if others can turn up the same results.</p>
<ol>
<li>Meditate, trying to keep your mind quiet, turn off noisy chatter. This may
take some practice. If you're a beginner, just meditate by focusing on your
breath, and breathe in and out; don't <em>control</em> your breath, just watch it,
and if your mind wanders, and you realize you've wandered, just come back
to your breath and keep trying, don't beat yourself up for it.</li>
<li>Do this while staring at a fixed point in the room, preferably on a complex
surface. Don't blink or look away even while your visuals begin to do weird
things; power through it.</li>
<li>Don't focus on seeing trippy visuals as a goal; when I thought too much about
seeing visuals, they wouldn't come on, I'd have to <em>just</em> focus on keeping
my mind quiet, and the visuals happen naturally.</li>
</ol>
</blockquote>
<p>While I was "meditation tripping," I thought to myself, "is this what people mean
when they talk about 'flashbacks' where you get psychedelic visuals later in life
after you've used these substances once before?" -- it fully, 100% looked like
height-of-the-trip visuals. But, they were <em>completely</em> under control, in that I
willed myself into it, and they were gone like *snap* as soon as I looked away.</p>
<p>The visuals were always my favorite part of psychedelics, anyway, and I can do
without the "ego death" and the "impressionable mind" aspects of a trip. As I
continue my meditation practice, now I know how I can give myself a laser light
show to watch while at the same time extending my tolerance for keeping my mind
still and quieted.</p>
<h3><a name="hexagonal-2d-pattern-overlaid-on-3d-reality" class="anchor" href="#hexagonal-2d-pattern-overlaid-on-3d-reality" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Hexagonal 2D pattern overlaid on 3D reality</h3>
<p>This story is related to the above which will become clear after a while.</p>
<p>So, I'd been using cannabis since <em>about</em> 2016 and all was normal and fine for
a while, but in the last couple of years especially, very often after I'd smoke
I would start to see a sort of "hexogonal pattern" emerge over my view of Reality.</p>
<p>It was like a 2D honeycomb texture overlaid on top of all the 3D things I was
seeing in my space; sort of like the pixels you see if you look <em>really</em> closely
at a computer screen. Or like, it was as though 3D reality was actually a
<em>projection</em> onto a flat 2D surface and that this hexogonal honeycomb pattern
were the "pixels" that make Reality function.</p>
<p>They were <em>especially</em> noticeable when I'd look at a bright white computer screen,
like the background of most web pages, because the solid white color removes all
visual distraction and I could see the honeycomb pattern the most clearly.</p>
<p>I can't really say what <em>color</em> the hexagon pattern is, as the whole thing seems
to flash colors like red and blue, like TV static, but the static is structured
and organized into a clear pattern.</p>
<p>If I was reading some text on my screen, the letters would wiggle and interact
with the hexagons where the letter touched a border between two cells. It's pretty
reliable for me to see this pattern pretty much any time I smoke weed now.</p>
<p>One of the first times I noticed this pattern, I was curious about it and tried
to focus and see it more clearly and figure out what it was. I was staring at my
white computer screen as it was the easiest to distinguish the pattern on, and
as I focused on it, it was like the veil of Reality began to disintegrate and fall
apart, like "holes" appeared in my monitor and I could see "through" reality to
get a better look at what was behind it.</p>
<p>What I began to see, though, frightened me and I stopped. I had seen it, in all
its terrifying glory, once before in my life - story below.</p>
<p>How it relates to meditating myself into tripping? The earlier parts of the visuals
I was seeing <em>started out</em> much the same as this hexogonal pattern, before it
changed and became fractals and making the wall dance around. I feel the two are
the same phenomenon in different forms.</p>
<h3><a name="the-infinite-grid-of-colorful-spheres" class="anchor" href="#the-infinite-grid-of-colorful-spheres" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
The infinite grid of colorful spheres</h3>
<p>So, going <em>all the way</em> back to my very first time smoking weed, in 2013 or 2014
or so. I tried it the first time, and I <strong>fully</strong> tripped balls and left reality
all together, with full-visual hallucinations and I was <strong>gone</strong> from Earth.</p>
<p>This is <strong>not</strong> a usual reaction people have to weed. I haven't tried DMT or
other hard psychedelics like that, but this story is the closest I've come to
something similar.</p>
<p>This guy I was seeing at the time got me to try weed, and he had just a small
bong (water pipe) and I took a few hits, wasn't really feeling much yet from it.
But then his friend comes over, and he brings this <em>huge</em> bong, one of the 2-foot
tall kinds and they had ice cubes in it and everything, and we started passing
that around.</p>
<p>I didn't even take a full drag off this thing, I just cleared the smoke in it
left by the other guy. Instantly I felt nauseous, and then after that, I was just
<em>gone.</em></p>
<p>What I was seeing in front of my eyes was an infinite 3D grid of colorful spheres,
tiled out as far as I could see. I didn't have a body. I could see, but I couldn't
move my "head", my vision was locked and staring at this grid of spheres. I could
feel my eyes and knew the difference between opening and closing them, but it
didn't matter, I was seeing these spheres all the same whether my eyes were opened
or not. The real world was just <em>gone</em>, I was in <em>this</em> place now.</p>
<p>I immediately got some crazy ideas in my head, like: the simulation has ended, the
Earth has been destroyed, and what I was seeing now were a bunch of <em>other</em> simulations,
each sphere being its own separate universe. And that the people who were running
these simulations were now studying the end results of ours that had just ended.</p>
<p>Occasionally I'd see a "screen" appear, a window where I could look through and
see the real world, and I saw my friends looking in at me and asking "Are you okay?
Do you need some water?", again and again on a loop. I interpreted this to be like
video clips being pulled from the simulation for study by whoever it is that was
running the simulation; that it wasn't "real" anymore, just a video clip, and it
was repetitive with my friends asking me over and over again.</p>
<p>I could not speak out loud.</p>
<p>I could think to myself, and I could hear my thoughts just fine, but I just could
not talk out loud. At least not on purpose. Occasionally I would manage to say
something, and I could feel my throat vibrate and hear my voice, but I never knew
<em>when</em> it would happen, and what I'd <em>say</em> would be just whatever random train of
thought I was currently on in my head.</p>
<p>Sometimes I could manage to scream, and this would finally get a reaction out of
my friends, who would finally say or do something different instead of just
repeating the same questions over and over again.</p>
<p>When I'd struggle to get out of that place, I'd get to see the real world, only it
was spinning in front of my eyes quickly as though I were shitfaced drunk on
alcohol, and when I'd give up and relax I'd be back in colorful land seeing this
grid of spheres once again.</p>
<p>It felt like I was there for an eternity.</p>
<p>I would've eventually just given up, relaxed, accepted my fate, etc., except there
was a constant auditory tone that was ringing in my ears the entire time which
kept me on edge and I couldn't fully just relax into it.</p>
<p>Eventually, I started to come down. I saw the spinning world again, only this time
it was sticking around longer than before, and I started to remember how I had
gotten myself into this situation. At this point I realized I was now standing on
my feet and twirling in circles to keep up with my spinning world. I still could
not speak, but I raised a finger in the air as if to signal "ah ha!" and that I
realized my situation and that I'm on my way back down to Earth. Earlier in this
'trip', my friends had me pinned on the ground for my own safety and I scratched
one of their arms for not believing they were even real during the trip.</p>
<p>Crazy stuff! The closest visual to this I've seen on the Internet is
<a href="https://en.wikipedia.org/wiki/Indra%27s_net" rel="nofollow">Indra's Net</a> but really I've never
seen anything else quite like it since.</p>
<p>I've never had such a reaction from weed since then, and tbh it kinda scared me
off trying it again for another couple of years. By that stage all I'd ever tried
was alcohol and I never contemplated such crazy ideas of simulations or things
before this.</p>
<p>So when I studied the hexogonal patterns I see on weed now, what started to emerge
from "behind the veil" looked an awful lot like the infinite grid of spheres and
I noped right back to reality instead.</p>
<h3><a name="the-time-i-lost-my-depth-perception-and-saw-reality-in-2d" class="anchor" href="#the-time-i-lost-my-depth-perception-and-saw-reality-in-2d" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
The time I lost my depth perception and saw reality in 2D</h3>
<p>Unrelated to the above stories, but an interesting story nonetheless.</p>
<p>One day I was in a car driving down the highway, and I was chiefing on a weed
vape pen, when suddenly I lost my depth perception to a certain degree.</p>
<p>The other cars on the road ahead of me started to appear as flat, 2D cardboard
cut-outs, like those you might find at a shooting gallery. The cars still had
reflections, highlights and shadows, to convey the illusion of 3D depth, only
the car as a whole looked like a flat 2D sprite.</p>
<p>The 2D cards did still have <em>relative</em> depth compared to others, like, I could
tell the difference between a car further ahead on the road compared to one
closer to me; just each individual car, itself, was a flat sprite to my eyes
with no localized depth to it.</p>
<p>I found it rather interesting and studied the rest of my visual perception to
understand how it all worked. Like, way way off in the distance, there were some
mountains covered in trees, only the whole mountain looked like a flat painting.
It was <em>so</em> far away, that there was no panoramic effect as the car drove closer,
it all just looked flat, like it was painted on, like the skybox of a videogame.</p>
<p>The cars nearby had relative depth, but far away, the horizon was flat. I thought,
"where is the dividing line at? How far out do things stop having depth to them
and it all looks flat on the horizon?" I estimated the line to be about 60 feet
in front of me. Cars closer by than 60 feet, I could tell how far each car was
from me and from the other cars; further out than that, everything may as well
just be a flat matte painting on a wall, there's no more depth perception to be
had at that distance.</p>
<p>I continued to study my perception in this state of mind and came up with the
following ways to describe it:</p>
<ul>
<li>Imagine a cylindrical room; the walls are a circle and there's a floor and a
ceiling, and the room has a diameter of about 60 feet from one side to the other.</li>
<li>Poke a hole in the wall of the room, and imagine that your eyeballs are in this
hole, looking into the room but you and your body are 'outside' the room.
Your visual perception then is basically <em>right</em> on the wall of the room.</li>
<li>The "far away horizon", the mountain with trees, the things so far off that they
no longer have local depth perception... these are painted on to the walls of
the room.</li>
<li>In the middle of the cylindrical room are where actors and stage props appear.
For me, these were the cars and other local objects (street signs, lights,
nearby trees and things). The actors all have local depth to them because they're
all physical objects inside the cylindrical room. But 60+ feet out, and it's a
flat painting on the wall instead.</li>
</ul>
<p>And then imagine you have <em>never</em> left this room your entire life. You've never
moved from that location, you've never turned your head. Instead, the paintings
on the walls change and the actors come and go and change shape and form to make
up your immediate environment. This was more or less what it "seemed" like in
this moment.</p>
<h3><a name="i-don-t-believe-any-of-this-stuff" class="anchor" href="#i-don-t-believe-any-of-this-stuff" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
I don't "believe" ANY of this stuff!</h3>
<p>I've written a lot of crazy stuff above, but don't worry, I don't take any of it
too seriously! In my normal daily life I'm still a skeptical, science-minded
kind of guy, and I even considered myself an Atheist for a good 10 years of my
life, in between being raised a Christian from childhood and then re-discovering
God in my own way in 2018.</p>
<p>All I know about the Universe is that I don't know <em>anything</em> about the Universe.</p>
<p>I like to dabble and explore my mind, and I fully acknowledge that this may be
<em>all it is</em>, is my brain chemistry playing tricks. I can't make any claims that
we're in a simulated universe or that gods or angels exist, or any kind of
external magick like that.</p>
<p>Even from a material science perspective: our brains never see the Real Reality.
We have eyes and ears and senses which feed electrical signals to our brain, and
our brain does its best to simulate what might be going on in the external world.
In that regard, we all <em>do</em> live in our own tiny little realities, and our own
brains simulate our universes and no two people could ever know, for sure, whether
what they call "red" is the same color as the other person.</p>
<p>There are surely some real dangers for your mental health if you delve into this
kind of thing unprepared, or without the mental framework to handle it. Personally,
I've always handled psychotropic drugs well, even during a "bad trip" where my
external reality gets scary and out of control, I never lost sight of <em>how I got there</em>
and I knew it was all mental and it too would pass and I'd be back to normal.</p>
<p>If there's interest I can talk about some psychedelic trip reports, too, though
the above blog post is not really the same as "trip reports" and proper trip
reports tend to be <em>so</em> random and chaotic, they don't even make sense to the
reader, much like when somebody tells you about the crazy dream they had last
night. Hopefully the above stories make some sense, though, and I explained some
of it well.</p>
<p>Disclaimers: don't do drugs, etc., but if you <em>do</em> do them anyway, do your research
and partake safely. <a href="https://www.erowid.org/" rel="nofollow">Erowid</a> is a good resource for that.</p>
<p>They say, of <strong>all</strong> drugs, that all they do is activate features in your brain
that it's <em>already</em> capable of, oftentimes playing with your dopamine, serotonin
or cannibinoid receptors, and that seasoned Buddhist monks (for example) can play
in that space purely through meditation, just that it takes a while to master and
drugs are a fast shortcut. A psychedelic trip can give you a peek through the veil
and give you a glimpse at the nature of your perception of reality, but beware of
unearned wisdom, and it's much safer to take the slower path there so you don't
risk turning yourself completely crazy.</p>
<blockquote>
<p>“The psychotic drowns in the same waters in which the mystic swims with delight.”</p>
<p>-Joseph Campbell.</p>
</blockquote>
VNC Server for Pinephone2021-04-01T21:39:42Ztag:www.kirsle.net,2021-04-01:/vnc-server-for-pinephone<p>I didn't find this documented very many places but it's possible to get a
<a href="https://en.wikipedia.org/wiki/Virtual_Network_Computing" rel="nofollow">VNC server</a> running
for "remote desktop" to access and control your <a href"https://www.kirsle.net/tagged/Pinephone" rel="nofollow">Pinephone</a>
display from your laptop.</p>
<p>Quick list of related technologies:</p>
<ul>
<li>To take <strong>screenshots</strong> of your Pinephone, use the <code>grim</code> command.</li>
<li>To record <strong>videos</strong> of your Pinephone's screen, use <code>wf-recorder</code>.</li>
<li>To run a VNC Server, use <a href="https://github.com/any1/wayvnc" rel="nofollow">wayvnc</a>.</li>
</ul>
<p><a href="https://mobian-project.org/" rel="nofollow">Mobian</a> already packages <code>grim</code> and <code>wf-recorder</code>
so these are just an apt install away, and these are <a href="https://wiki.mobian-project.org/doku.php?id=tweaks" rel="nofollow">documented</a>
on Mobian's wiki. But wayvnc is <em>not</em> yet packaged in Mobian and you gotta build
it from source code yourself.</p>
<p>Follow the directions on the <a href="https://github.com/any1/wayvnc" rel="nofollow">git repo</a>, including
cloning down the neatvnc and aml dependencies. The README has instructions to
build it for Fedora and Arch but the Debian instructions are missing! I found by
trial-and-error the dependencies I needed to install to build this program for
Debian:</p>
<p><div class="highlight"><pre><span></span>sudo apt install gcc meson ninja-build pkg-config libpixman-1-dev <span class="se">\</span>
libdrm-dev libxbcommon-dev libwayland-dev
</pre></div>
</p>
<p>I ran the built binary like <code>wayvnc 0.0.0.0</code> to start the server and connected
with the TigerVNC client from my desktop.</p>
<p>It has a couple of quirks to watch out for:</p>
<ul>
<li>The mouse cursor only appears on the Pinephone's screen, but not in the VNC
viewer window, making some UIs hard to work with (the lock screen in particular).
<strong>Edit:</strong> use <code>-r --render-cursor</code> options to get the cursor to work. Thanks,
anonymous commenter!</li>
<li>The Pinephone display was "too tall" to fit on my screen when in portrait
orientation. My desktop monitor is 1920x1080 but the Pinephone display is
720x1280 so it ran off the bottom of my screen by 200 pixels. Switching the
display to Landscape fit better.</li>
</ul>
<p><img src"https://www.kirsle.net/static/photos/4bf28cd4a224293a8b2f8d2a22f04163dfa5d5437ace3746b9a5d4f411d1bb55.png" alt="wayvnc.png"></p>