<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>skyjake</title>
<link href="gemini://skyjake.fi/gemlog/" />
<link rel="self" type="application/atom+xml" href="gemini://skyjake.fi/gemlog/atom.xml" />
<id>gemini://skyjake.fi/gemlog/</id>
<updated>2026-05-12T19:27:39Z</updated>
<generator uri="gemini://skyjake.fi/gemlog/" version="1.0">gmi-hatch</generator>
<entry>
    <title>Spring Cleaning, Part 2</title>
    <author><name>Jaakko Keränen</name></author>
    <link href="gemini://skyjake.fi/gemlog/2026/05/spring-cleaning-part-2.gmi" rel="alternate" type="text/gemini" />
    <link href="https://gmi.skyjake.fi/gemlog/2026/05/spring-cleaning-part-2.gmi" rel="alternate" type="text/html" />
    <id>gemini://skyjake.fi/gemlog/2026-05_spring-cleaning-part-2.gmi</id>
    <published>2026-05-12T19:27:39Z</published>
    <updated>2026-05-12T19:27:39Z</updated>
    <content type="html"><![CDATA[
<p></p>
<p><span class="tag-icon">🏷</span> <a href="https://gmi.skyjake.fi/gemlog/topic/gemini.gmi">Gemini</a></p>
<p></p>
<p class="lede">Keeping with the theme of spring cleaning, I decided to spend some time improving the machinery that runs this gemlog.</p>
<p></p>
<p>The posts have been individual files in a flat /gemlog/ directory, but after six years things have gotten a tad cluttered. It made more sense to have year/month subdirectories that keep the files neatly organized. The topic indices were also moved to their own subdirectory.</p>
<p></p>
<p>I tried to be careful to not break any old URLs by applying redirections and content formatting rules that fix internal cross-references between posts. The end result should be that everything works as before, including any external links pointing to the gemlog, except now everything is also tidy.</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="/gemlog/atom.xml">The Atom feed has also been enhanced.</a></div>
<p>It should now have accurate publication and update timestamps for each entry (previously time was fixed at 12:00), and the entries now contain a full HTML-rendered version of the post. For that I reused some code from the web mirror.</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="/gemlog/">skyjake&apos;s Gemlog</a></div>
<p>CC-BY-SA 4.0</p>
    ]]></content>
</entry>
<entry>
    <title>Spring Cleaning</title>
    <author><name>Jaakko Keränen</name></author>
    <link href="gemini://skyjake.fi/gemlog/2026/05/spring-cleaning.gmi" rel="alternate" type="text/gemini" />
    <link href="https://gmi.skyjake.fi/gemlog/2026/05/spring-cleaning.gmi" rel="alternate" type="text/html" />
    <id>gemini://skyjake.fi/gemlog/2026-05_spring-cleaning.gmi</id>
    <published>2026-05-01T12:00:00Z</published>
    <updated>2026-05-01T12:00:00Z</updated>
    <content type="html"><![CDATA[
<p></p>
<p><span class="tag-icon">🏷</span> <a href="https://gmi.skyjake.fi/gemlog/topic/doomsday.gmi">Doomsday</a></p>
<p></p>
<p class="lede">I've been clearing cobwebs off the Doomsday codebase recently.</p>
<p></p>
<p>The project has been on hiatus. I last worked on this code 5-8 years ago. It's amazing how much of it I've forgotten. Doomsday represents a solid 20 years of invested time, and it shows. There is so much stuff: an amalgamation of Doom/Heretic/Hexen, a complete GUI framework, a smaller widget framework for the game menus, a scripting language, a document processing tool, partially finished next-gen renderer, scriptable 3D model system, and heaps of UI for configuration and package management.</p>
<p></p>
<p>The actual games having been largely left in vanilla state highlights where my focus has been over the years. I was never a game modder, concentrating instead on the scaffolding.</p>
<p></p>
<p>In practice, I've been making progress toward the 3.0 goals: SDL 3 migration, Qt 6 migration (still in use peripherally), superficial UI facelifts, better CMake structure and dependency management, completely functional MSVC build on Windows (instead of relying of MSYS or MinGW), and cleaning up the macOS and Linux builds. It's mostly maintenance, but I've appreciated the walk down memory lane. It's nice to see the games working as before.</p>
<p></p>
<p>Question is: do I still have interest in pushing Doomsday forward? The next-gen rendering is an interesting challenge, but it's also a huge investment.</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="https://gmi.skyjake.fi/gemlog/2026/05/./">skyjake&apos;s Gemlog</a></div>
<p>CC-BY-SA 4.0</p>
    ]]></content>
</entry>
<entry>
    <title>Lagrange on Powkiddy RGB30 (RK3566)</title>
    <author><name>Jaakko Keränen</name></author>
    <link href="gemini://skyjake.fi/gemlog/2026/03/rgb30.gmi" rel="alternate" type="text/gemini" />
    <link href="https://gmi.skyjake.fi/gemlog/2026/03/rgb30.gmi" rel="alternate" type="text/html" />
    <id>gemini://skyjake.fi/gemlog/2026-03_rgb30.gmi</id>
    <published>2026-03-18T12:00:00Z</published>
    <updated>2026-03-18T12:00:00Z</updated>
    <content type="html"><![CDATA[
<p></p>
<p><span class="tag-icon">🏷</span> <a href="https://gmi.skyjake.fi/gemlog/topic/lagrange.gmi">Lagrange</a>, <a href="https://gmi.skyjake.fi/gemlog/topic/gaming.gmi">Gaming</a></p>
<p></p>
<div class="link gemini-link"><span class="link-icon">🌐</span><a href="gemini://bbs.geminispace.org/u/skyjake/image/717.jpeg">Photo of the RGB30 with Lagrange and an on-screen keyboard</a></div>
<p></p>
<p>I've had a soft spot for the Sega Game Gear ever since I unwrapped one as a Christmas gift when I was about 11 years old. Handheld gaming has always been a bit of a magical experience; in the late 80s we had the Nintendo Game & Watch gadgets. Vivid memories of a particular orange Donkey Kong device have been burnt into my brain. The Game Gear really leveled up the experience, though, lackluster color LCD and poor battery life notwithstanding.</p>
<p></p>
<p>I did not get much into Nintendo handhelds until much later when I bought the Nintendo DS Lite and played an unhealthy amount of Puzzle Quest on it.</p>
<p></p>
<p>Anyway, nowadays we have awesome hardware in the form of ARM CPUs and GPUs. A random fedi post brought the Powkiddy RGB30 to my attention: a nice little Linux retro-oriented gaming handheld with a quad-core 1.8 GHz ARM Cortex-A55 CPU, Mali G52 GPU, 1 GB RAM, and a 720x720 4" display. Hard to believe this is mid-2000s desktop-class performance in a little pocketable Linux machine.</p>
<p></p>
<p>60€ and a couple of weeks later, I was marveling at the little device in person. Apart from retro gaming, I was immediately intrigued about the potential for running my own software on it.</p>
<p></p>
<h2 id="cross-compiling">Cross-compiling</h2>
<p></p>
<p>Out of the box, the device runs a build of JELOS from 2023 (a bare-bones aarch64 Linux) with glibc 2.38. There are apparently cross-compilation toolchains available somewhere (and a more modern ROCKNIX OS), but I did not want to bother with those. Surely I can just build on a comparable aarch64 Linux system and, given the dependencies are met, the binary should just work?</p>
<p></p>
<p>After a little sleuthing I settled on an arm64 Debian 12 Bookworm VM. This is only slightly older than the JELOS build, so library dependencies should be compatible.</p>
<p></p>
<p>I was playing around with SDL3 a while back and noticed it has official support for Rockchip GPUs via the `SDL_ROCKCHIP` build option, which depends on a library called libmali. Searching the web turned up multiple variants; fortunately, in the device logs I found details about which one to use (namely, "G52 g13p0"). Next thing I knew, I had a fully-functional build of SDL3 (and later, SDL2) running on the device with access to OpenGL ES 3.2, audio, and gamepad controls.</p>
<p></p>
<h2 id="handheld-lagrange">Handheld Lagrange</h2>
<p></p>
<p>The binary compiled on the arm64 Debian ran pretty much out of the box on the RGB30. Of course, the device has no keyboard and mouse, so there was no way to control the UI, or even quit the app.</p>
<p></p>
<p>I've been working on adding gamepad controls to Lagrange. It's somewhat of a mixture of mouse and keyboard input: a virtual pointer you can move with a thumbstick lets you click on arbitrary elements in the UI and page, while the D-pad and buttons are also used for navigation, clicking on buttons, and as shortcuts for actions like opening menus and focusing the URL field. It is really its own input modality alongside the existing mouse, keyboard, and touchscreen controls, remixing some elements while adding a few twists. Some gamepads, like PlayStation ones, also have their own touch input area that can be used as an alternative way to move the virtual pointer and click on buttons and links.</p>
<p></p>
<p>Having a method for entering text is crucial, and on a device that only has basic gamepad controls, text entry must happen using an on-screen keyboard (unless you plug in an external keyboard, I suppose). Given that Lagrange uses a homegrown GUI, there's no ready-made virtual keyboard. I decided to make my own. This was actually a pretty cool challenge. When you consider modern phone keyboards, they have all sorts of built-in language localization features, swipe gestures, mode switches, and emoji pickers. None of that is really mandatory, though. At a really basic level, a plain old U.S. English QWERTY keyboard is quite sufficient. It was fairly easy to make the keyboard configurable with alternative regional layouts. For instance, I wanted a Finnish/Swedish layout for myself. The system lets you lay out rows of keys using a config file, and keys can act as modifiers that switch to different pages of keys.</p>
<p></p>
<p>In the v1.20 release, both the gamepad controls and the handheld UI variant are still in a bit of an experimental state. They could use a little more polish. For instance, a GUI setting for selecting the virtual keyboard layout would be nice.</p>
<p></p>
<p>You can download an RK3566/aarch64 build of Handheld Lagrange here:</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="/lagrange/handheld-linux.gmi">Lagrange for Handheld Linux Consoles</a></div>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="https://gmi.skyjake.fi/gemlog/2026/03/./">skyjake&apos;s Gemlog</a></div>
<p>CC-BY-SA 4.0</p>
    ]]></content>
</entry>
<entry>
    <title>Lagrange v1.20: SOCKS5, Handheld Port, Gamepads, UI/Audio Improvements</title>
    <author><name>Jaakko Keränen</name></author>
    <link href="gemini://skyjake.fi/gemlog/2026/03/lagrange-1.20.gmi" rel="alternate" type="text/gemini" />
    <link href="https://gmi.skyjake.fi/gemlog/2026/03/lagrange-1.20.gmi" rel="alternate" type="text/html" />
    <id>gemini://skyjake.fi/gemlog/2026-03_lagrange-1.20.gmi</id>
    <published>2026-03-18T12:00:00Z</published>
    <updated>2026-03-18T12:00:00Z</updated>
    <content type="html"><![CDATA[
<p></p>
<p class="lede">This release focuses on feature requests that have been hanging around for a long time, addressing a few important platform-specific shortcomings. There is also a nice bunch of smaller quality-of-life improvements and bug fixes.</p>
<p></p>
<div class="link web-link"><span class="link-icon">🌐</span><a href="https://codeberg.org/skyjake/lagrange/releases/tag/v1.20.5">Download Lagrange v1.20</a></div>
<p></p>
<h2 id="socks5-proxy">SOCKS5 proxy</h2>
<p></p>
<p>SOCKS5 proxy support has been on the list of requested features for five years now, so continuing to ignore it was getting a bit awkward. In the end, implementing SOCKS5 proxying was not that difficult. It mainly affects the opening of network connections and how domain name resolution is handled.</p>
<p></p>
<p>SOCKS5 can be useful in a couple of ways. One prominent use case is routing traffic through Tor for anonymity. Another common use is tunneling through an SSH SOCKS proxy, which is a handy way to work around network restrictions or to browse as if you were on a different machine. For example, opening an SSH proxy on port 1080 is as easy as:</p>
<p></p>
<pre>
ssh -D 1080 -N user@example.com
</pre>
<p></p>
<p>The proxy settings can be found in Preferences > Network. Once configured, all network connections go through the proxy.</p>
<p></p>
<h2 id="native-audio-playback-on-android">Native audio playback on Android</h2>
<p></p>
<p>The Android port has been lagging behind iOS when it comes to audio playback. For this release, I've implemented new native audio decoding that works even better than the iOS version: the audio data is fed to a native Android MediaPlayer via a streaming buffer so it can take advantage of hardware acceleration and can continue playing even when the app is in the background. This is more efficient than the previous versions and supports a larger number of codecs.</p>
<p></p>
<p>I wrote more about the new audio code in another post:</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="https://gmi.skyjake.fi/gemlog/2026/03/2026-03_android-streaming.gmi">Audio Streaming in Lagrange for Android</a></div>
<p></p>
<p>The audio improvements were not confined solely to Android. Several behavioral glitches were addressed when it comes to the inline audio players for all platforms. For example, the player would not automatically stop itself when reaching the end of the content, nor would it release its decoder resources if the user navigated back in history.</p>
<p></p>
<h2 id="gamepad-controls-and-handheld-ui-variant">Gamepad controls and handheld UI variant</h2>
<p></p>
<p>My December/Christmas project last year was porting Lagrange to the Powkiddy RGB30. It is a small handheld game console that runs Linux, so technically the port was mostly about cross-compiling. I did end up implementing a couple of handheld-specific features, most prominently a virtual keyboard one can operate via the gamepad.</p>
<p></p>
<p>Gamepad controls are now available on all platforms thanks to SDL. Alas, they don't play nice with the native UI controls, so when using the gamepad, the build should have all native UI integration disabled. Hence, I'm still designating gamepad support as "experimental".</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="https://gmi.skyjake.fi/gemlog/2026/03/2026-03_rgb30.gmi">Lagrange on Powkiddy RGB30 (RK3566)</a></div>
<p></p>
<h2 id="windows-dark-mode">Windows dark mode</h2>
<p></p>
<p>Another old entrant on the feature requests list is support for the system dark mode on Windows. This is now fully implemented: the app checks the system dark mode setting at launch and observes whether it changes at runtime. The only thing you need to do is check if the new toggle "Use system theme" is enabled in Preferences > Appearance.</p>
<p></p>
<h2 id="middle-button-scrolling">Middle-button scrolling</h2>
<p></p>
<p>At least on Windows, it is a common mouse gesture to scroll content by holding the middle button and moving the mouse up or down. This has been implemented application-wide, so any scrollable content can be scrolled with a middle button drag.</p>
<p></p>
<p>The feature is available on all platforms.</p>
<p></p>
<h2 id="input-prompt-at-bottom">Input prompt at bottom</h2>
<p></p>
<p>The input prompt dialog can now be moved to the bottom of the window. This can be useful if the dialog would obscure important page content at the top. The position can be toggled via the […] menu, or set as a default in Preferences > Appearance.</p>
<p></p>
<h2 id="message-context-menus">Message context menus</h2>
<p></p>
<p>Error and warning messages displayed inline on a page are not selectable text, which has made it awkward to copy them, for example when reporting a problem. These special messages now have a context menu that includes an action to copy the text to the clipboard. You can also right-click on input prompts to copy them, too.</p>
<p></p>
<h2 id="other-changes-and-fixes">Other changes and fixes</h2>
<p></p>
<ul>
<li>Plain text lines wrap to the maximum available width when the &quot;expand to long lines&quot; option is enabled. Gopher pages in particular are often plain text, so no they can be displayed without unnecessary wrapping if the window has enough room.</li>
<li>For those on networks where both IPv4 and IPv6 are available, there is now an option to prefer IPv6 in DNS resolution. (This option has no effect if SOCKS5 is enabled.)</li>
<li>Improved warning message when there is a problem with the proxy server certificate.</li>
<li>Opening a link context menu via keyboard now correctly remembers which link was highlighted by keyboard navigation.</li>
<li>Gopher: fixed misdetected menu styling, particularly with non-ASCII characters.</li>
<li>Crash in the simple text renderer (TUI) when encountering a Backspace character.</li>
<li>OpenSSL error messages are no longer printed to stderr.</li>
</ul>
<p></p>
<p><span class="tag-icon">🏷</span> <a href="https://gmi.skyjake.fi/gemlog/topic/lagrange.gmi">Lagrange</a></p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="https://gmi.skyjake.fi/gemlog/2026/03/./">skyjake&apos;s Gemlog</a></div>
<p>CC-BY-SA 4.0</p>
    ]]></content>
</entry>
<entry>
    <title>Audio Streaming in Lagrange for Android</title>
    <author><name>Jaakko Keränen</name></author>
    <link href="gemini://skyjake.fi/gemlog/2026/03/android-streaming.gmi" rel="alternate" type="text/gemini" />
    <link href="https://gmi.skyjake.fi/gemlog/2026/03/android-streaming.gmi" rel="alternate" type="text/html" />
    <id>gemini://skyjake.fi/gemlog/2026-03_android-streaming.gmi</id>
    <published>2026-03-15T12:00:00Z</published>
    <updated>2026-03-15T12:00:00Z</updated>
    <content type="html"><![CDATA[
<p></p>
<p><span class="tag-icon">🏷</span> <a href="https://gmi.skyjake.fi/gemlog/topic/lagrange.gmi">Lagrange</a>, <a href="https://gmi.skyjake.fi/gemlog/topic/android.gmi">Android</a></p>
<p></p>
<p class="lede">I've been working on improving Lagrange's Android port this week. It has been a bit of a learning experience — of the major computing platforms, Android is probably the least familiar to me.</p>
<p></p>
<p>Prior to the Beta 46 build, audio support has been somewhat broken on Android. The platform-independent Vorbis decoder that plays audio through SDL has been limping along while other codecs haven't worked that well, if at all. However, now in Beta 46/47, there are major changes:</p>
<p></p>
<ul>
<li>The system attempts to use native Android decoders for all audio formats. This means you&apos;ll get the best possible performance and smallest hit on battery life.</li>
<li>Playback begins as soon as the native media player is able to start its decoding, meaning if the content supports streamed decoding, you can listen while downloading.</li>
<li>Audio playback can continue when the app goes to the background. Android is actually looking out for you here by making the app jump through a bunch of hoops. One needs to request special permissions to be able to run anything while in the background, and you specifically have to declare why you are running (e.g., media playback). You are also required to put up a system notification letting the user know that there is something going on in the background (&quot;Playing audio&quot;), which means requesting permission for the app to show notifications.</li>
<li>It gets even better: if the device is locked (screen turns off), the CPU and radios by default want to go to sleep to preserve power. The app needs to request keeping the device in a higher power state during the media playback. This is especially important for the streaming, since that involves both radios and the CPU threads handling the data. If the app was a typical Android app using Google&apos;s high-level media APIs, most of this stuff would be handled automatically, but I&apos;m doing the audio playback on a lower level as we are going Gemini requests to fetch the data, and handing the data over to Android via streaming memory buffers.</li>
<li>The Ogg container format gets a (dis)honorable mention: Android&apos;s media player does not support streamed decoding of Ogg content, because it wants to first know the duration of the content by skipping to the end. Therefore, I had to resort to using the old stb_vorbis & SDL audio solution for Ogg Vorbis. (Ogg Opus still doesn&apos;t stream.) On the plus side, this code path should also now fully support background playback and streaming.</li>
</ul>
<p></p>
<p>Long story short, you can now do both background audio playback and background audio streaming in the Android port. This is a step above the current iOS implementation that doesn't barely supports  streaming playback at all.</p>
<p></p>
<p>You can find the Android Beta builds in the recently rebuilt Lagrange F-Droid repository (now using fdroid v2 format):</p>
<p></p>
<div class="link web-link"><span class="link-icon">🌐</span><a href="https://skyjake.github.io/fdroid/repo">https://skyjake.github.io/fdroid/repo</a></div>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="https://gmi.skyjake.fi/gemlog/2026/03/./">skyjake&apos;s Gemlog</a></div>
<p>CC-BY-SA 4.0</p>
    ]]></content>
</entry>
<entry>
    <title>Lagrange in the Apple App Store</title>
    <author><name>Jaakko Keränen</name></author>
    <link href="gemini://skyjake.fi/gemlog/2026/02/lagrange-in-app-store.gmi" rel="alternate" type="text/gemini" />
    <link href="https://gmi.skyjake.fi/gemlog/2026/02/lagrange-in-app-store.gmi" rel="alternate" type="text/html" />
    <id>gemini://skyjake.fi/gemlog/2026-02_lagrange-in-app-store.gmi</id>
    <published>2026-02-11T12:00:00Z</published>
    <updated>2026-02-11T12:00:00Z</updated>
    <content type="html"><![CDATA[
<p></p>
<div class="link web-link"><span class="link-icon">🌐</span><a href="https://apps.apple.com/us/app/lagrange-smallnet-browser/id1554714615">Lagrange Smallnet Browser (Apple App Store)</a></div>
<p></p>
<p>Lagrange is now available in the App Store. This is the same build that has been in TestFlight for a while, with a couple of finishing touches like a Help page tailored for iOS.</p>
<p></p>
<p>The TestFlight will continue with beta builds. I expect this public version to be updated pretty infrequently.</p>
<p></p>
<h2 id="modern-personal-computers">Modern personal computers</h2>
<p></p>
<p>Mobile phones are undoubtedly the primary computing devices for most people today. Making Gemini available and accessible on phones is therefore an important goal.</p>
<p></p>
<p>I don't consider this important because Gemini needs to grow or become more popular, but to make it a more natural part of life for the people who actually enjoy this text-focused, no-frills protocol — we may like sitting down at the computer and fully focusing on reading and writing for an hour, but realistically it is difficult to find time for such a commitment compared to pulling out a phone and checking a post or two. (In my experience, at least.) There is great value in both approaches, though: the former results in higher quality and impact; the latter excels in engagement and promptness.</p>
<p></p>
<p>There are a couple of mobile apps for Gemini, of course, and beta versions of Lagrange have been available for years.</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="https://gmi.skyjake.fi/gemlog/2026/02/2021-03_testflight.gmi">It has been almost five years since the iOS beta builds first became available.</a></div>
<p></p>
<p>Beta builds are useful in many ways, but they are hindered by barriers: you need to sign up, deal with feedback, etc. TestFlight builds also expire in 90 days — a surprisingly short span of time whose end may sometimes sneak up on you. An app one can install with a single tap is much nicer for everyone.</p>
<p></p>
<p>I imagine that the Apple and Google app stores are nowadays the main distribution channel for software that people use in their daily lives (web stuff notwithstanding), so being available in either or both is quite significant.</p>
<p></p>
<h2 id="technical-status">Technical status</h2>
<p></p>
<p>While the core of the app remains the same on all platforms, over the years the mobile port has gained special features and additional platform-specific integrations. The most important ones have been native text fields and popup menus, and access to the system file picker. I also enjoy the subtle haptic feedback in the iOS builds (e.g., reloading the page). These contribute to making the app feel more like it belongs on iOS even though the UI is otherwise non-native and based on custom UI controls.</p>
<p></p>
<p>I wouldn't say the app is perfect by any means, but by now it's certainly time-tested. I use it daily for browsing Gemini and managing bbs.geminispace.org on both the iPhone and iPad, and it has been quite a smooth experience for months (years?) now.</p>
<p></p>
<p>I can think of several ways the app could utilize iOS more thoroughly, particularly for accessibility, but realistically that would require first writing a new iOS-native UI for it. Who knows, maybe that will happen at some point down the road.</p>
<p></p>
<h2 id="google-owns-the-gemini-brand">Google owns the &quot;Gemini&quot; brand</h2>
<p></p>
<p>There was a bit of back and forth with App Review about the word "Gemini". You may note that the app's store page does not feature that word anywhere. So, if you were wondering how things are going with Google usurping Gemini as their brand name, I conclude it's best to avoid using that word entirely lest casual app shoppers confuse this app with Google's AI offerings.</p>
<p></p>
<p>With so much of the tech world focusing on AI, brand names like Google's Gemini have a lot of exposure. It makes sense that something of that magnitude might lead to incorrect assumptions when people aren't familiar with the Gemini Protocol. (This would be the vast majority of people.). The folks of Geminispace have zero leverage here, unfortunately.</p>
<p></p>
<p>When Google Gemini first became a thing, personally I expected the brand to be sunsetted rather quickly in favor of the next hot AI product, but Google appears to be sticking with it. We are fortunately in no hurry here, so as long as Google doesn't start actively protecting their brand name, the Gemini Protocol can sit and wait until the winds begin blowing in a different direction.</p>
<p></p>
<p>All this means that the title of the app in the store is "Lagrange Smallnet Browser". Admittedly, that is more accurate than "Gemini Browser" since several other protocols are also supported.</p>
<p></p>
<h2 id="play-store">Play Store...?</h2>
<p></p>
<p>There is one piece of the mobile puzzle missing: the Android port still needs a public version, too. This is a slightly bigger challenge. I don't regularly use Android phones, so I have a poorer grasp of platform conventions and what the current betas are like when used as a daily driver. I get the sense that there are more bugs and more sharp edges that need tweaking, to make the app feel more "Android-y".</p>
<p></p>
<p><span class="tag-icon">🏷</span> <a href="https://gmi.skyjake.fi/gemlog/topic/lagrange.gmi">Lagrange</a>, <a href="https://gmi.skyjake.fi/gemlog/topic/apple.gmi">Apple</a></p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="https://gmi.skyjake.fi/gemlog/2026/02/./">skyjake&apos;s Gemlog</a></div>
<p>CC-BY-SA 4.0</p>
    ]]></content>
</entry>
<entry>
    <title>Anticipating 2026</title>
    <author><name>Jaakko Keränen</name></author>
    <link href="gemini://skyjake.fi/gemlog/2026/01/anticipating.gmi" rel="alternate" type="text/gemini" />
    <link href="https://gmi.skyjake.fi/gemlog/2026/01/anticipating.gmi" rel="alternate" type="text/html" />
    <id>gemini://skyjake.fi/gemlog/2026-01_anticipating.gmi</id>
    <published>2026-01-01T12:00:00Z</published>
    <updated>2026-01-01T12:00:00Z</updated>
    <content type="html"><![CDATA[
<p></p>
<p><span class="tag-icon">🏷</span> <a href="https://gmi.skyjake.fi/gemlog/topic/programming.gmi">Programming</a>, <a href="https://gmi.skyjake.fi/gemlog/topic/lagrange.gmi">Lagrange</a>, <a href="https://gmi.skyjake.fi/gemlog/topic/gaming.gmi">Gaming</a></p>
<p></p>
<p class="lede">The annual tradition of intro/retrospection is upon us, as 2025 wraps up and a new year begins.</p>
<p></p>
<p>I don't generally like to share future plans because I can't commit to actually following through with any of them, due to limitations on time and/or energy. Sometimes it feels like future plans have a bit of Heisenberg's indeterminacy to them, in that you can either discuss them or implement them, but never do both. There's something to holding an idea close to the vest, enjoying that extra boost of excitement about revealing the surprise only once finished.</p>
<p></p>
<p>Anyway, this is more of a note-to-self kind of post about things I'd like to get around to working on, focusing on projects at a higher level. Maybe this will give me some clarity as to all of these swirling ideas and plans that are challenging to wrangle during hectic everyday life.</p>
<p></p>
<h2 id="handheld-lagrange-and-gamepad-support">Handheld Lagrange and gamepad support</h2>
<p></p>
<p>I've been working toward getting Lagrange to run on the RGB30, which is a little Linux-based retro-oriented handheld. (That is, it ships with a bunch of emulators on the system disk and Emulation Station as the main UI.) Lagrange works rather well on it now. Would be nice to finalize the gamepad support for Lagrange version 1.20 and release an official build for the RGB30. I can see gamepad controls being particularly useful in TV & couch and HMD VR use cases, and you could also consider it an accessibility feature since there are gamepads for limited mobility scenarios.</p>
<p></p>
<p>The recently updated iOS TestFlight build includes WIP gamepad support, so you can plug in a controller and use the sticks to scroll the page and move a pointer around for clicking on links. It isn't compatible with the native menus and text input, but I suppose I could use the non-native ones whenever one is actually using a gamepad?</p>
<p></p>
<p>Speaking of Lagrange, my to-do list remains as long as ever, but it's fair to say that the threshold for implementing new features keeps rising. I don't really want the app to keep growing larger and larger. Instead, it would be great to focus on usability, quality, and platform integration improvements.</p>
<p></p>
<h2 id="gemini-things">Gemini things</h2>
<p></p>
<p>Of course, I have my various other Gemini projects simmering (on low heat):</p>
<p></p>
<ul>
<li>Bubble bulleting board system</li>
<li>GmCapsule server</li>
<li>Cosmos aggregator</li>
</ul>
<p></p>
<p>It's virtually a certainty that these will be worked on in 2026.</p>
<p></p>
<h2 id="platform-puzzler">Platform puzzler</h2>
<p></p>
<p>The RGB30 is an enticing device for my slowly-progressing Amiga-like fantasy console project called Mach-V ("Mach Five"). It would be amazing to actually build an Amiga-style platform game on this. It would be a ton of work, though, both in terms of coding and art assets.</p>
<p></p>
<p>I did outline a nice story for such a game, though, with influences from ancient Egypt and Indiana Jones. It would be puzzle heavy.</p>
<p></p>
<h2 id="mach-v">Mach-V</h2>
<p></p>
<p>Speaking of Mach-V, I'm quite proud of what I've managed to achieve so far with this fantasy console in terms of technical features:</p>
<p></p>
<ul>
<li>The virtual CPU is fairly simple: it has a handful of 16-bit registers, is able to reference a 32-bit address space, it keeps track of the stack and supports interrupts. Designing this was truly fascinating, starting with the instruction set and instruction encoding. I mostly based it around what I could recall from x86 assembly from the early 2000s, without all the unnecessary cruft like memory segmenting. After diving into the details of, for example, how individual operands are encoded, what kind of addressing modes can be used, the registers and how they are referenced, I have to say it boggles the mind how all of this can be done on real hardware, in actual CPUs. I feel like I could write a series of blog posts about this; there&apos;s a lot to discuss.</li>
</ul>
<p></p>
<ul>
<li>The Mach-V assembler is not entirely low level in that it supports if/else branching directives (generating the necessary compare/jump instructions as needed), and also C-like function calls. It was a massive learning experience writing the assembler, since it basically deals with all of the parts of low-level C compilation: symbols, modules, linking, data and code segments, data structures, memory addressing in arrays and nested structures, etc. The objective was to create an assembly language that&apos;s &quot;fun&quot; to write code in. A major convenience to this end are the C-like function calls where the arguments are automatically pushed on and popped off the stack. If one added more higher-level syntax and a code optimizer, it would essentially be an actual &quot;real&quot; compiler.</li>
</ul>
<p></p>
<ul>
<li>There are &quot;hardware&quot; sprites for efficiently drawing and moving 2D objects around the screen, with collision detection that gets reported to the program via CPU interrupts.</li>
</ul>
<p></p>
<ul>
<li>I spent quite a number of hours tweaking a shader for emulating CRT like graphics, with the appropriate blooming and shadow mask effects. Having grown up with CRT monitors, emulating their visual appearance is rather key to an authentic experience.</li>
</ul>
<p></p>
<ul>
<li>During a bout of C64 nostalgia, I created a text prompt interface akin to C64 BASIC; a text-based buffer that scrolls in one direction and where you can move the cursor freely around.</li>
</ul>
<p></p>
<ul>
<li>During another bout of nostalgia, for the Amiga this time, I made a Workbench-like windowing environment where one can navigate files on mounted disks (host computer directories). The aforementioned text-buffer interface can run in a window in this GUI environment.</li>
</ul>
<p></p>
<ul>
<li>Mach-V incorporates the Bitwise Harmony audio engine as the &quot;audio chipset&quot;, essentially a SID chip style multi-track waveform-based synthesizer for sound effects and music.</li>
</ul>
<p></p>
<p>This entire system is now full-featured enough to actually implement software on. Earlier, as a test, I made a very simple side-scrolling shooter where you move a spaceship around the screen, firing at enemies coming in from the right. Sound effects are used for firing and explosions. It was really great seeing this run on the RGB30 without any additional effort; a real retro game of my own creation, albeit a trivially simple one.</p>
<p></p>
<h2 id="jked">jked</h2>
<p></p>
<p>My text editor is in good shape. (I am writing this post using it, of course.) There are a few nice-to-haves and quality-of-life improvements that could be worked on, and probably will be sometime in 2026.</p>
<p></p>
<h2 id="retro-racing">Retro racing</h2>
<p></p>
<p>For literal decades I've been wanting to create a 3D driving game in the vein of Stunts (or "4D Sports: Driving"). I've had various goes at this over the years, but haven't actually finished any of them. I recognize the motivation comes from nostalgic memories playing games like Lotus Turbo Challenge, Test Drive III, and the aforementioned Stunts, but nevertheless I have a bunch of exciting ideas about the mechanics of such a game, particularly about how the tracks could be built.</p>
<p></p>
<p>I have a stub of an engine readied from a few years ago with basic shaders and 3D rendering. It's just waiting for me to start building the track construction system and the physics simulation. This is perhaps my biggest temptation at the moment, but somehow I doubt I'll actually get around to it in 2026.</p>
<p></p>
<h2 id="sci-fi-if">Sci-fi IF</h2>
<p></p>
<p>A couple of years ago I started working on a non-parser (dynamic menu) interaction fiction game, and looking at the basic engine now, it seems to have enough potential for building an actual game. However, writing IF is a purely creative endeavor very similar to writing regular fiction that requires focus and careful planning; given my rather hectic schedule at the moment, it's difficult to find suitable time for this. Would be lovely to actually construct a full-blown story/game, though.</p>
<p></p>
<h2 id="adventure">Adventure</h2>
<p></p>
<p>"Adventure" is an untitled 16-bit-style 2D fantasy RPG. This is the first project I based on the_Foundation, and it was great fun to build the map and lighting system, not to mention doing 16-color pixel art for the map tile set. The world has a daily cycle between day, dusk, night, and dawn, affecting the general light level in outside regions. Objects can emit light around them, and there are ray-cast shadows. The basic mechanics are in place, but then I started working on a scripting system to implement various artifact effects, and it started getting a wee bit too complicated. I suspect I was procrastinating with that, avoiding figuring out the actual game behavior... A scripting system kind of makes sense, though, since it allows implementing quests/storylines as well, in a way that is not hardcoded and manageable as data instead of code.</p>
<p></p>
<p>I'm still undecided whether I want this to be more like a Nethack roguelike with a totally RNG world, or should it have a more hand-crafted story. Perhaps some combination of the two?</p>
<p></p>
<p>I've been coming back to Adventure every year or so since 2019, so doing a brief stint in 2026 is likely.</p>
<p></p>
<h2 id="text-based-roguelike">Text-based roguelike</h2>
<p></p>
<p>Nethack left a big impression on me back in the day, and I've always wanted to make my own text/character-based roguelike. I've tried it a few times, but my downfall has been that I tend to overcomplicate the game mechanics with too many details. Do I really need to simulate each arm and leg of the characters separately so combat can have more interesting outcomes? In the Adventure project I've tried to consciously limit the realism to keep everything simplified, but when the visuals are text-based and super simple on their own, the focus of the game design kind of shifts to the internal mechanisms, so there is a temptation to make things too sophisticated.</p>
<p></p>
<h2 id="music">Music</h2>
<p></p>
<p>It would be great to devote some time to making new music, probably in Logic Pro or Bitwise Harmony. This activity could support the game-making endeavors: a reasonable objective could be to make some background and/or title music.</p>
<p></p>
<h2 id="unforeseen-projects">Unforeseen projects</h2>
<p></p>
<p>Sometimes inspiration strikes and I find myself compelled to work on something unexpected. Who knows, maybe this will happen again in 2026?</p>
<p></p>
<h2 id="scant-time">Scant time</h2>
<p></p>
<p>The realistic outcome is that in 2026 I won't have the opportunity to work on many of these projects. I suppose thinking and planning counts as something, too? It's always fun to make notes in my private wiki, diving deep every now and then to sketch out this or that idea.</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="https://gmi.skyjake.fi/gemlog/2026/01/./">skyjake&apos;s Gemlog</a></div>
<p>CC-BY-SA 4.0</p>
    ]]></content>
</entry>
<entry>
    <title>Not So Merry Christmas</title>
    <author><name>Jaakko Keränen</name></author>
    <link href="gemini://skyjake.fi/gemlog/2025/12/not-so-merry-christmas.gmi" rel="alternate" type="text/gemini" />
    <link href="https://gmi.skyjake.fi/gemlog/2025/12/not-so-merry-christmas.gmi" rel="alternate" type="text/html" />
    <id>gemini://skyjake.fi/gemlog/2025-12_not-so-merry-christmas.gmi</id>
    <published>2025-12-21T12:00:00Z</published>
    <updated>2025-12-21T12:00:00Z</updated>
    <content type="html"><![CDATA[
<p></p>
<p><span class="tag-icon">🏷</span> <a href="https://gmi.skyjake.fi/gemlog/topic/life.gmi">Life</a></p>
<p></p>
<p class="lede">In February 2013, a rambunctious yellow labrador retriever puppy arrived into our house.</p>
<p></p>
<p>On December 20th, 2025, just three days shy of his 13th birthday, our goodest boy left us.</p>
<p></p>
<p>Just a day earlier, he had grown weak and had lost his appetite. As the condition did not improve, I took him to the vet and they found a sizable tumor. He was laid to rest just hours later as we comforted him and said our final farewells.</p>
<p></p>
<p>This situation comes inevitably for any pet owner. It all happened very suddenly, though, taking us almost by surprise, so it has been quite the gut punch. I am glad there was no prolonged suffering, even if it hits us harder this way.</p>
<p></p>
<p>13 years is a high and respectable age for a dog to reach. However, it is a long time to form habits and patterns that will now break; getting a dog is life-changing, and losing one will be likewise. In the short term, with the Christmas holidays looming, this will undoubtedly cast a shadow over the festivities. At least we can come to terms with this change without needing to worry about work and other daily tasks.</p>
<p></p>
<p>I still haven't found the courage to collect his things — toys, bed, what's left of his food — and put them away.</p>
<p></p>
<p>Too much finality to contend with.</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="https://gmi.skyjake.fi/gemlog/2025/12/./">skyjake&apos;s Gemlog</a></div>
<p>CC-BY-SA 4.0</p>
    ]]></content>
</entry>
<entry>
    <title>Geminaut Age Survey Results</title>
    <author><name>Jaakko Keränen</name></author>
    <link href="gemini://skyjake.fi/gemlog/2025/11/age-survey.gmi" rel="alternate" type="text/gemini" />
    <link href="https://gmi.skyjake.fi/gemlog/2025/11/age-survey.gmi" rel="alternate" type="text/html" />
    <id>gemini://skyjake.fi/gemlog/2025-11_age-survey.gmi</id>
    <published>2025-11-22T12:00:00Z</published>
    <updated>2025-11-22T12:00:00Z</updated>
    <content type="html"><![CDATA[
<p></p>
<p><span class="tag-icon">🏷</span> <a href="https://gmi.skyjake.fi/gemlog/topic/gemini.gmi">Gemini</a></p>
<p></p>
<p class="lede">Recently, there was a poll on BBS about the approximate age of Geminauts. The poll has been open for about three weeks, with 104 responses so far, making this likely the most comprehensive survey of Gemini demographics to date.</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">🌐</span><a href="gemini://bbs.geminispace.org/s/Gemini/34084">Gemini Age Survey (by nana4)</a></div>
<p></p>
<p>First, what do these 104 people represent? Obviously, there is self-selection bias here as all the respondents are active users of bbs.geminispace.org. Looking at the overall capsule activity, BBS has about a hundred people posting and/or commenting per month, so we can say that most of the people currently active on BBS have now responded. This makes the results well-representative of this particular capsule. What about the wider Geminispace, though? The survey excludes anyone who just writes gemlogs or occasionally reads posts on Antenna, i.e., "passive" users. Large hubs like Midnight/Smol Pub, Flounder, and SDF are not necessarily represented at all. I don't think there is any way to accurately estimate the overall ratio of active vs. passive users, but typically online you get about an order of magnitude more passive users compared to active ones. Gemini might be somewhat different given the small size of the community and the builder/explorer mentality. After all, one gets more out of Gemini when actively participating and not just sitting back and lurking.</p>
<p></p>
<p>Other multi-user capsules do not publish active user statistics, but the number of total users is around 2000 on Station and 2500 on Astrobotany, which is roughly comparable to BBS (1500). It is plausible to assume that these other large capsules see active users in the low hundreds, too. For example, there are 240 live plants on Astrobotany, which suggests around 200 active users watering them. This gives us further leeway in viewing this survey as representing a meaningful subset of the overall Geminaut population.</p>
<p></p>
<p>The survey results are as follows:</p>
<p></p>
<ul>
<li>34% of users — a third — are in the 40-50 range. (Including me!) This is the largest bracket of users. I would describe this as the age range most befitting Gemini. Born in 1975-1985, we grew up in the era of 8-bit home computers, listened to screeching modems while dialing into actual BBSes, witnessed first-hand the rise of the Web in the mid-90s, and used Gopher and Usenet during their heyday. And all this in our formative teenage years! I can only speak for myself, but it left quite the mark. At least I have a wealth of nostalgic appreciation for Gemini&apos;s flavor of primitive, do-it-yourself internet.</li>
</ul>
<p></p>
<ul>
<li>The 20-40 range represents 40% of users. Furthermore, 40 seems to be the halfway point that splits the user base in roughly equal portions: half are younger than 40, and half older. I think this shows that Gemini appeals not only to the older crowd with experience from the 90s but also to people born in the current millennium. For these users, the web was an established component of life already at a young age. This is total speculation, but perhaps they acutely feel the decline of the modern web, as it is being overrun by commercial interests, social silos, complex software solutions, and lately, AI slop and overbearing crawlers. Gemini might represent a refreshing resprite from the madness.</li>
</ul>
<p></p>
<ul>
<li>Interestingly, we have 8% of users in the teenager or younger bracket. 1 in 12 is not insignificant. I can imagine that Gemini can have a contrarian underground appeal that feels cool even if you have not experienced the early days of the web, and you&apos;ve been calibrated to accept LLMs, boundless virtual worlds like Minecraft, and photorealistic games as the mundane baseline of technology. One also cannot discount the power that comes from the simple software stack, making self-hosting and homegrown software implementations feasible. Having full control of one&apos;s online presence can be attractive, at least if you have the mentality of a pioneer and don&apos;t worry too much about your peer group&apos;s attitudes and attention.</li>
</ul>
<p></p>
<ul>
<li>A plausible estimate of the &quot;student&quot; demographic, in high school, college or university, would be the 10-30 range that covers ~20% of users. I would imagine the aforementioned technological agency being a big draw here, too. Maybe these people are relatively more active gemloggers than BBSers, though; my intuition based on exploring Geminispace somehow pegged this group as a little larger.</li>
</ul>
<p></p>
<ul>
<li>Users aged 50 or older is a total of 20% as well. If I were to guess, people in this age range have more limited experiences with home computing, nowadays living a casual mobile phone & web (dare I say, Facebook) centric life, so Gemini is not something they would come across that frequently or see a need for.</li>
</ul>
<p></p>
<p>That was perhaps a few too many conclusions to draw from a small survey, so take these thoughts with the appropriate grain of salt. 🙂</p>
<p></p>
<p>I will update this post in case the results change significantly in the future.</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="https://gmi.skyjake.fi/gemlog/2025/11/./">skyjake&apos;s Gemlog</a></div>
<p>CC-BY-SA 4.0</p>
    ]]></content>
</entry>
<entry>
    <title>Lagrange Turns 5</title>
    <author><name>Jaakko Keränen</name></author>
    <link href="gemini://skyjake.fi/gemlog/2025/09/lagrange-five.gmi" rel="alternate" type="text/gemini" />
    <link href="https://gmi.skyjake.fi/gemlog/2025/09/lagrange-five.gmi" rel="alternate" type="text/html" />
    <id>gemini://skyjake.fi/gemlog/2025-09_lagrange-five.gmi</id>
    <published>2025-09-13T12:00:00Z</published>
    <updated>2025-09-13T12:00:00Z</updated>
    <content type="html"><![CDATA[
<p></p>
<p><span class="tag-icon">🏷</span> <a href="https://gmi.skyjake.fi/gemlog/topic/lagrange.gmi">Lagrange</a></p>
<p></p>
<p class="lede">Today marks the fifth anniversary of the first release of Lagrange.</p>
<p></p>
<p>Five years is quite a hefty chunk of time! While the first couple of years saw rapid development, recently the app has been stabilizing, the monthly releases turning into yearly ones. Save for some lingering bugs that still avoid capture, the slowing of the pace is right and proper. Gemini is not a moving target so there isn't a continual need to bolt on new features. The focus is now squarely on improving the features that are already there — particularly the ones that never advanced far beyond the initial Minimum Viable stage.</p>
<p></p>
<p>Version 0.1.0 was published on September 13, 2020, via an announcement post on the Project Gemini mailing list. It can be found in Acidus's archives:</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">🌐</span><a href="gemini://gemi.dev/gemini-mailing-list/000377.gmi">gemini://gemi.dev/gemini-mailing-list/000377.gmi</a></div>
<p></p>
<blockquote> In the spirit of Gemini, the guiding principle has been to trim things down to the bare bones. To keep the app as portable and small as possible, it&apos;s written in C and doesn&apos;t depend on existing UI frameworks. Instead, SDL2 is used for low-level graphics/input and the rest is built on top of that. TLS is provided by OpenSSL.</blockquote>
<p></p>
<p>The introductory description still rings true. While the custom GUI approach has its drawbacks (like lack of accessibility features beyond UI scaling), it has given a lot of flexibility when it comes to portability. Lagrange now runs on all the major (and some minor) desktop and mobile operating systems, even in text-mode inside a terminal.</p>
<p></p>
<p>I continue to use Lagrange daily on my phone, iPad, and laptop. It is a strong contender to be my most-used app (duking it out with Reeder). It is even a decent source of local news for me via the YLE teletext interface. Browsing Gemini on the app remains a delightful and mostly stress-free experience. I do occasionally cycle through fontpacks to freshen things up, though. (Current favorite: Manrope + Crimson Pro.)</p>
<p></p>
<p>When it comes to the mobile ports, one huge step still remains: publishing to app stores. I'm battling with perfectionism here somewhat. While the port is quite functional at least on iOS (according to 1800 testers), the UI can be a bit flaky. The integration with native UI controls like input fields and the virtual keyboard can glitch out sometimes, for example. The only true fix would be to write a fully native UI, one for iOS and one for Android. At this point, leaving that to a hypothetical version 2 of the app seems like the most sensible approach.</p>
<p></p>
<p>Speaking of a version 2, I do have ideas for leveling up the UX in various ways. However, with the COVID-19 lockdowns long gone, it is much more difficult to find time to invest in hobby programming. This year has mirrored the previous one in that after the vacations there have been opportunities to work on the app, but as the fall begins in earnest, we shall see how much time and energy remains.</p>
<p></p>
<div class="link gemini-link"><span class="link-icon">➤</span><a href="https://gmi.skyjake.fi/gemlog/2025/09/./">skyjake&apos;s Gemlog</a></div>
<p>CC-BY-SA 4.0</p>
    ]]></content>
</entry>
</feed>
