<pclass="author-description"><center><i>"Love God. Live Righteously. Die Well."</i><br/><br/><atarget="_blank"rel="noopener"href="https://source.starfort.tech/andrew">Source Code</a> || <atarget="_blank"rel="noopener"href="https://www.linkedin.com/in/andrewkesterson/">LinkedIn</a><br/></center></p>
<olclass="toc"><liclass="toc-item toc-level-2"><aclass="toc-link"href="#libakstdlib"><spanclass="toc-text">libakstdlib</span></a></li><liclass="toc-item toc-level-2"><aclass="toc-link"href="#libakgl"><spanclass="toc-text">libakgl</span></a><olclass="toc-child"><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Locking-game-state-for-thread-safety"><spanclass="toc-text">Locking game state for thread safety</span></a></li><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Controllers"><spanclass="toc-text">Controllers</span></a></li><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Pluggable-rendering-backends"><spanclass="toc-text">Pluggable rendering backends</span></a></li></ol></li><liclass="toc-item toc-level-2"><aclass="toc-link"href="#Pluggable-physics-systems"><spanclass="toc-text">Pluggable physics systems</span></a><olclass="toc-child"><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Tests-and-Documentation"><spanclass="toc-text">Tests and Documentation</span></a></li></ol></li><liclass="toc-item toc-level-2"><aclass="toc-link"href="#ESP32-projects"><spanclass="toc-text">ESP32 projects</span></a><olclass="toc-child"><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Flowing-LED-lights-with-a-button"><spanclass="toc-text">Flowing LED lights with a button</span></a></li><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Controlling-buzzers-with-transistors"><spanclass="toc-text">Controlling buzzers with transistors</span></a></li><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Communicating-over-Serial-UART"><spanclass="toc-text">Communicating over Serial UART</span></a></li></ol></li></ol>
<h2id="libakstdlib"><ahref="#libakstdlib"class="headerlink"title="libakstdlib"></a>libakstdlib</h2><p>Several improvements were driven into <atarget="_blank"rel="noopener"href="https://source.starfort.tech/andrew/libakstdlib/">libakstdlib</a>, my libc layer that wraps my platform’s native libc in <atarget="_blank"rel="noopener"href="https://source.starfort.tech/andrew/libakerror/">libakerror</a>.</p>
<ul>
<li>Added <code>aksl_atol</code></li>
<li>Added <code>aksl_atoll</code></li>
<li>Added <code>aksl_atoi</code></li>
<li>Fixed a bug in <code>aksl_sprintf</code>, it wasn’t using va_args properly, leading to segfault</li>
<li>Added <code>aksl_atof</code></li>
<li>Added <code>aksl_realpath</code>, which takes a string that contains a filesystem path which may or may not be relative, and populates a destination string with the absolute path to that file reference</li>
<h2id="libakgl"><ahref="#libakgl"class="headerlink"title="libakgl"></a>libakgl</h2><p>I made several improvements to my C/SDL3 game library.</p>
<h3id="Locking-game-state-for-thread-safety"><ahref="#Locking-game-state-for-thread-safety"class="headerlink"title="Locking game state for thread safety"></a>Locking game state for thread safety</h3><p>The SDL3 implementation is, by default, implemented with threaded events. For the <atarget="_blank"rel="noopener"href="https://source.starfort.tech/andrew/akgl-test/">akgl-test demonstration app</a> I’m writing alongside <code>libakgl</code>, this eventually reared its ugly head as some nasty race conditions on the various <code>AKGL_HEAP</code> objects that are statically allocated and centrally managed. Consider this:</p>
<ul>
<li>Input processing happens during <code>SDL_AppEvent</code></li>
<li>Physics and rendering happens during <code>SDL_AppIterate</code></li>
<li>The player presses <code>ESC</code> to go back to the main menu to select a different demonstration</li>
<li>Part of that process is that the <code>AKGL_HEAP_ACTORS</code> is reset</li>
<li>While that is happening, the <code>SDL_AppIterate</code> fires from another thread. It goes to render actors that are in the process of being reset.</li>
<li>KABOOM</li>
</ul>
<p>To resolve this quickly, I added a <code>SDL_Mutex</code> object to the global <code>akgl_Game</code> object. Anything that modifies the core game state (like the <code>AKGL_HEAP</code> objects) calls <code>akgl_game_state_lock()</code> to lock the state, and <code>akgl_game_state_unlock()</code> when they are done. This resolved the race condition.</p>
<p>Right now this is being applied on some really large operations. It can probably be applied in a far more granular fashion. But for right now it works.</p>
<h3id="Controllers"><ahref="#Controllers"class="headerlink"title="Controllers"></a>Controllers</h3><p>Added a method (<code>akgl_controller_open_gamepads()</code>) that automatically opens all connected gamepads at the time of <code>akgl_game_init()</code>. </p>
<ul>
<li>The user doesn’t have to call this, it’s done automatically</li>
<li>You have to open a gamepad before you can receive events from it. So asking the player “Press any button on the controller” to figure out which controller they’re using doesn’t work until those gamepads are open. There may be consequences to opening gamepads we don’t need - I don’t know yet. If that comes up, it’s easy enough to close the ones we aren’t using.</li>
</ul>
<h3id="Pluggable-rendering-backends"><ahref="#Pluggable-rendering-backends"class="headerlink"title="Pluggable rendering backends"></a>Pluggable rendering backends</h3><p>At some point I am going to want to use the SDL3 GPU renderer as the primary renderer for my engine. Right now I’m using the Rendering API because it’s familiar, comfortable, and very simple for the 2D stuff I’m doing right now. But I need to reduce the coupling between the rendering API and the rest of the game logic. So I abstracted away the existing SDL_Renderer rendering backend into a new <code>akgl_RenderBackend</code> structure, and refactored everything to call the methods on that structure instead of touching the renderer directly.</p>
<p>The <code>akgl_render_init2d</code> function sets up the renderer with a bunch of backend functions that know how to render the various on-screen parts of libakgl (like <code>akgl_Actor</code>, <code>akgl_Sprite</code>, <code>akgl_Tilemap</code>, etc) through the SDL Rendering API. All of this detail is transparent to theuser, and to the library author as well, because they just do things <code>renderer->draw_texture(&renderer)</code> and <code>renderer->draw_world(&renderer)</code>. The real detail of how that all gets done is tucked away <atarget="_blank"rel="noopener"href="https://source.starfort.tech/andrew/libakgl/src/branch/main/src/renderer.c">in those functions</a>.</p>
<p>Now <code>SDL_AppIterate</code> can look like this to draw the world and all the actors in it:</p>
<p>… because <code>akgl_game_update</code> calls <code>renderer->draw_world()</code> for you.</p>
<p>Now when I want to implement a GPU renderer (or any other kind of renderer, really - ASCII ncurses anyone?), all I have to do is write some new pluggable methods, write an initializer function like <code>akgl_render_init2d()</code> that populates a renderer structure, and we’re off to the races.</p>
<p>At least that’s the idea. We’ll see what happens when I implement SDL3 GPU at some point in the future.</p>
<h2id="Pluggable-physics-systems"><ahref="#Pluggable-physics-systems"class="headerlink"title="Pluggable physics systems"></a>Pluggable physics systems</h2><p>Following on the pluggable rendering system, I am at the point where I need to put in some amount of physics simulation before I can start making games with this thing. So I followed the same basic pattern I did with the rendering backend, and made a structure that holds a bunch of function pointers and other information</p>
<p>… and <atarget="_blank"rel="noopener"href="https://source.starfort.tech/andrew/libakgl/src/branch/main/src/physics.c">the physics backend</a> takes care of calculating acceleration, velocity, movement, and (soon) collisions.</p>
<p>Collision detection isn’t there yet. It’s coming soon, with both other actors and world geometry.</p>
<h3id="Tests-and-Documentation"><ahref="#Tests-and-Documentation"class="headerlink"title="Tests and Documentation"></a>Tests and Documentation</h3><p>This thing is basically completely undocumented. That’s okay, because I’m only really writing it for myself, but as the complexit grows, I really should write some docs. I’ll put <em>something</em> together. </p>
<p>I really need to write some new tests. I was very disciplined about that in the early days of this library. But then again, back then, I didn’t have demo games to work with. So the testing harness was the only metric for success I had. But I’ve gotten away from writing or even checking the test harness, and that’s bad. Future updates will see me do <em>something</em> about this.</p>
<h2id="ESP32-projects"><ahref="#ESP32-projects"class="headerlink"title="ESP32 projects"></a>ESP32 projects</h2><p>I’ve started studying embedded development. I’ve got a long road ahead of me, but it all starts with an ESP32-S3 Arduino kit. Even with the experience I have with technology, I figured it was best to start somewhere simple before diving in to RTOS and FPGA on more complex platforms. I completed 3 projects on my Freenove ESP32-S3 WROOM devkit this week.</p>
<h3id="Flowing-LED-lights-with-a-button"><ahref="#Flowing-LED-lights-with-a-button"class="headerlink"title="Flowing LED lights with a button"></a>Flowing LED lights with a button</h3><blockquoteclass="twitter-tweet"><plang="en"dir="ltr">The journey of a thousand miles begins with an esp32, some blinking leds and a button <atarget="_blank"rel="noopener"href="https://t.co/i9rOphuY60">pic.twitter.com/i9rOphuY60</a></p>— Andrew Kesterson (@AKLabsDotNet) <atarget="_blank"rel="noopener"href="https://x.com/AKLabsDotNet/status/2058655798591476058?ref_src=twsrc%5Etfw">May 24, 2026</a></blockquote><scriptasyncsrc="https://platform.x.com/widgets.js"charset="utf-8"></script>
<p><atarget="_blank"rel="noopener"href="https://source.starfort.tech/andrew/esp32-learning/src/branch/main/01-flowing_light_with_button/flowing_light_with_button.ino">This program</a> sends a cascading light effect through the LED bar that fades on either side of a strong central point. It normally flows in one direction, but if you press the button, it changes direction.</p>
<p>I learned several things from this project:</p>
<ul>
<li>How to use the Arduino IDE to deploy code to the ESP32-S3 WROOM</li>
<li>How to use the Arduino IDE debugger to step through code running on the device</li>
<li>How to configure GPIO pins on the ESP32-S3 as input or output</li>
<li>How to read and write data to and from those GPIO pins</li>
<li>Using a physical button to control program flow in the microcontroller</li>
<li>Debouncing mechanical buttons</li>
<li>What is pulse width modulation and how do we control it on the ESP32-S3</li>
<li>Using pulse width modulation with an LED to create a smooth visual effect simulating an analog curve</li>
</ul>
<p>There is a more detailed writeup about this project <atarget="_blank"rel="noopener"href="https://source.starfort.tech/andrew/esp32-learning/src/branch/main/01-flowing_light_with_button">in my source repository</a></p>
<h3id="Controlling-buzzers-with-transistors"><ahref="#Controlling-buzzers-with-transistors"class="headerlink"title="Controlling buzzers with transistors"></a>Controlling buzzers with transistors</h3><blockquoteclass="twitter-tweet"><plang="en"dir="ltr">Love it when the manufacturers tutorials have bugs in them. Still better than diagnosing istio problems in kubernetes. One project down, thousands more to go. <atarget="_blank"rel="noopener"href="https://t.co/53WQetCTmQ">pic.twitter.com/53WQetCTmQ</a></p>— Andrew Kesterson (@AKLabsDotNet) <atarget="_blank"rel="noopener"href="https://x.com/AKLabsDotNet/status/2059735218622538228?ref_src=twsrc%5Etfw">May 27, 2026</a></blockquote><scriptasyncsrc="https://platform.x.com/widgets.js"charset="utf-8"></script>
<p>These <atarget="_blank"rel="noopener"href="https://source.starfort.tech/andrew/esp32-learning/src/branch/main/02-buzzers_with_transistors/buzzer-npn-lowside-switching/buzzer-npn-lowside-switching.ino">two</a><atarget="_blank"rel="noopener"href="https://source.starfort.tech/andrew/esp32-learning/src/branch/main/02-buzzers_with_transistors/activebuzzer_npn_lowside_switching/activebuzzer_npn_lowside_switching.ino">programs</a> allow you to control a buzzer with a button to make a noise on command. They both use the exact same breadboard, the only difference is that one uses a passive buzzer, while the other uses an active buzzer (pn TMB12A05).</p>
<p>I learned several things from these projects:</p>
<ul>
<li>The differences in active vs passive buzzers</li>
<li>How transistors work, and how you can use them to control the flow of power in a circuit</li>
<li>Why you might place a transistor upstream or downstream of the component whose power you are controlling</li>
<li>How to turn a transistor on or off using the GPIO pin on an ESP32</li>
<li>How to use my oscilloscope to diagnose PWM output issues</li>
</ul>
<p>There is a more detailed writeup about this project <atarget="_blank"rel="noopener"href="https://source.starfort.tech/andrew/esp32-learning/src/branch/main/02-buzzers_with_transistors">in my source repository</a></p>
<h3id="Communicating-over-Serial-UART"><ahref="#Communicating-over-Serial-UART"class="headerlink"title="Communicating over Serial UART"></a>Communicating over Serial UART</h3><blockquoteclass="twitter-tweet"><plang="en"dir="ltr">A good digital logic analyzer is worth its weight in gold<br><br>Thankfully they tend to be lightweight devices <atarget="_blank"rel="noopener"href="https://t.co/FlSPL95DyW">pic.twitter.com/FlSPL95DyW</a></p>— Andrew Kesterson (@AKLabsDotNet) <atarget="_blank"rel="noopener"href="https://x.com/AKLabsDotNet/status/2060156789111316602?ref_src=twsrc%5Etfw">May 29, 2026</a></blockquote><scriptasyncsrc="https://platform.x.com/widgets.js"charset="utf-8"></script>
<p>This project shows using the ESP32-S3 serial port for communication via UART.</p>
<p>Lessons Learned:</p>
<ul>
<li>The Arduino HAL is surprisingly thick</li>
<li>You can’t use the ESP32-S3 UART for communication via USB when you’re debugging</li>
<li>libc is libc anywhere you go</li>
<li>How to use my digital logic analyzer to snoop on, record and inspect UART protocol traffic</li>
<li>How to use my oscilloscope to look at UART traffic over the wire, and how that compares to using the logic analyzer</li>
</ul>
<p>There is a more detailed writeup about this project <atarget="_blank"rel="noopener"href="https://source.starfort.tech/andrew/esp32-learning/src/branch/main/03-serialuart">in my source repository</a></p>
<divclass="nav-title">Devlog Entry - 18 May 2026 </div>
</div>
<iclass="iconfont icon-right nav-next-icon"></i>
</a>
</div>
</div>
<div
class="card card-content toc-card"
id="mobiletoc">
<divclass="toc-header">
<i
class="iconfont icon-menu"
style="padding-right: 2px;">
</i>TOC
</div>
<olclass="toc"><liclass="toc-item toc-level-2"><aclass="toc-link"href="#libakstdlib"><spanclass="toc-text">libakstdlib</span></a></li><liclass="toc-item toc-level-2"><aclass="toc-link"href="#libakgl"><spanclass="toc-text">libakgl</span></a><olclass="toc-child"><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Locking-game-state-for-thread-safety"><spanclass="toc-text">Locking game state for thread safety</span></a></li><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Controllers"><spanclass="toc-text">Controllers</span></a></li><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Pluggable-rendering-backends"><spanclass="toc-text">Pluggable rendering backends</span></a></li></ol></li><liclass="toc-item toc-level-2"><aclass="toc-link"href="#Pluggable-physics-systems"><spanclass="toc-text">Pluggable physics systems</span></a><olclass="toc-child"><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Tests-and-Documentation"><spanclass="toc-text">Tests and Documentation</span></a></li></ol></li><liclass="toc-item toc-level-2"><aclass="toc-link"href="#ESP32-projects"><spanclass="toc-text">ESP32 projects</span></a><olclass="toc-child"><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Flowing-LED-lights-with-a-button"><spanclass="toc-text">Flowing LED lights with a button</span></a></li><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Controlling-buzzers-with-transistors"><spanclass="toc-text">Controlling buzzers with transistors</span></a></li><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Communicating-over-Serial-UART"><spanclass="toc-text">Communicating over Serial UART</span></a></li></ol></li></ol>
</div>
</main>
<asideclass="right-column">
<divclass="sticky-widescreen">
<articleclass="card card-content toc-card">
<divclass="toc-header">
<i
class="iconfont icon-menu"
style="padding-right: 2px;">
</i>TOC
</div>
<olclass="toc"><liclass="toc-item toc-level-2"><aclass="toc-link"href="#libakstdlib"><spanclass="toc-text">libakstdlib</span></a></li><liclass="toc-item toc-level-2"><aclass="toc-link"href="#libakgl"><spanclass="toc-text">libakgl</span></a><olclass="toc-child"><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Locking-game-state-for-thread-safety"><spanclass="toc-text">Locking game state for thread safety</span></a></li><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Controllers"><spanclass="toc-text">Controllers</span></a></li><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Pluggable-rendering-backends"><spanclass="toc-text">Pluggable rendering backends</span></a></li></ol></li><liclass="toc-item toc-level-2"><aclass="toc-link"href="#Pluggable-physics-systems"><spanclass="toc-text">Pluggable physics systems</span></a><olclass="toc-child"><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Tests-and-Documentation"><spanclass="toc-text">Tests and Documentation</span></a></li></ol></li><liclass="toc-item toc-level-2"><aclass="toc-link"href="#ESP32-projects"><spanclass="toc-text">ESP32 projects</span></a><olclass="toc-child"><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Flowing-LED-lights-with-a-button"><spanclass="toc-text">Flowing LED lights with a button</span></a></li><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Controlling-buzzers-with-transistors"><spanclass="toc-text">Controlling buzzers with transistors</span></a></li><liclass="toc-item toc-level-3"><aclass="toc-link"href="#Communicating-over-Serial-UART"><spanclass="toc-text">Communicating over Serial UART</span></a></li></ol></li></ol>