Andrew Kesterson

"Love God. Live Righteously. Die Well."
Source Code || LinkedIn
38 Posts 9 Categories 0 Tags
Categories
Books 14
Philosophy 9
Faith 7
Technology 17
Outdoors 1
Current-Events 7
Leadership 8
History 1
Liberal-Education 1
hot tags

# Devlog Entry - 18 May 2026

2026-05-15 Technology 2k words

I just wanted to drop some notes on things I’ve been hacking on recently.

# Goodbye GitHub

I’ve become increasingly unhappy with Github for a variety of reasons. For that reason, I’ve moved all of my source code over to the Starfort Source Vault. My GitHub will now only host stuff that I do for my corporate job. I’ve also moved my personal website off of GitHub Pages and back in to Starfort’s local infrastructure. This is a control issue: I want to retain full control over my intellectual property and the way my online presence is presented. I’m also not interested in Microsoft scraping all of my source code to train their AI models, so I’m taking my marbles and going home.

# libakerror improvements

libakerror is a safe exception handling library for C. I’m baking it into all of my new projects that I’m writing in C, so it’s getting worked out quite a bit.

- Began namespacing the library into `akerr_`. All of the functions, types and global variables are in this namespace, but the macros are not. I’m not sure I like them not being namespaced, but I also don’t want to make them any longer to type. I may wind up leaving the macros.

- I found myself using large `ATTEMPT ... FINISH` blocks that would `CATCH` something but never actually do anything with the thing it caught. This was a lot of unnecessary typing. I added a new macro, `PASS`, that simply passes an error back up through the stack without actually doing anything to it. Saves a lot of typing, and is what I actually want to do probably >80% of the time (in my current projects anyway).

    PREPARE_ERROR(e);
    PASS(e, some_method_that_returns_errorcontext());
    SUCCEED_RETURN(e);

- Properly handling functions that don’t SUCCEED properly. Previously there was nothing stopping you from doing this:

    akerr_ErrorContext AKERR_NOIGNORE *func(void)
    {
        PREPARE_ERROR(e)
    	// do something
    	// don't return (e), OR, return(e) without calling SUCCEED
    }

This results in your function having an undefined (and invalid) pointer return value. When the DETECT() macro (invoked by CATCH(), FAIL_*(), or PASS()) inspected the value of your return function, it would see a non-NULL value, and then go about inspecting the datastructure. Unfortunately, in these careless cases, the pointer was invalid, so BAM segfault.

I introduced a new macro, VALID(), that first checks to see if the return value from the function is a valid exception - that’s an easy check, since all exceptions come from the global AKERR_ARRAY_ERROR which contains a known quantity of error objects. By checking to see if the akerr_ErrorContext pointer address is within the range of memory occupied by the array, we can be reasonably certain it is (or is not) a valid error. Invalid error return values get an `AKERR_BEHAVIOR` error thrown by the library.

- Documentation update to reflect the above changes

# libakstdlib

libakstdlib is a libc wrapper that implements `libakerror` error handling around those functions.

I find myself wrapping various libc/stdlib calls in `libakerror` macros frequently, so I’ve started a libc wrapper that does that for me. It doesn’t have much in it yet, just the functions I use the most:

    akerr_ErrorContext AKERR_NOIGNORE *aksl_fopen(char *pathname, char *mode, FILE **fp);
    akerr_ErrorContext AKERR_NOIGNORE *aksl_fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    akerr_ErrorContext AKERR_NOIGNORE *aksl_fwrite(void *ptr, size_t size, size_t nmemb, FILE *fp);
    akerr_ErrorContext AKERR_NOIGNORE *aksl_fclose(FILE *stream);

    akerr_ErrorContext AKERR_NOIGNORE *aksl_malloc(size_t size, void **dst);
    akerr_ErrorContext AKERR_NOIGNORE *aksl_memset(void *s, int c, size_t n);
    akerr_ErrorContext AKERR_NOIGNORE *aksl_memcpy(void *d, void *s, size_t n);
    akerr_ErrorContext AKERR_NOIGNORE *aksl_free(void *ptr);

    akerr_ErrorContext AKERR_NOIGNORE *aksl_printf(int *count, const char *restrict format, ...);
    akerr_ErrorContext AKERR_NOIGNORE *aksl_fprintf(int *count, FILE *restrict stream, const char *restrict format, ...);
    akerr_ErrorContext AKERR_NOIGNORE *aksl_sprintf(int *count, char *restrict str, const char *restrict format, ...);

    akerr_ErrorContext AKERR_NOIGNORE *aksl_atoi(const char *nptr, int *dest);
    akerr_ErrorContext AKERR_NOIGNORE *aksl_atol(const char *nptr, long *dest);
    akerr_ErrorContext AKERR_NOIGNORE *aksl_atoll(const char *nptr, long long *dest);

Most libc functions set `errno` when they fail (but not all), so most failure operations from these wrappers will throw the value of `errno` as their exception. I need to explicitly document where these functions throw something else. The functions are pretty easy drop-in replacements for their libc counterparts, with the exception that they no longer return values, they return error state. So you have to pass additional pointer arguments for them to place their outputs.

    FILE *fp = NULL;
    char membuf[512];
    PREPARE_ERROR(e);
    PASS(e, fopen("somefile.txt", "rb", &fp);
    PASS(e, fread((void *)&membuf, 1, 512, fp));
    SUCCEED_RETURN(e);

# libakgl

libakgl is an SDL3 game programming library.

With the release of SDL version 3 last year, I’ve started working on a new (?) C game library (not an engine) built around SDL3 as a fun side project.

I say “new” in quotes because it is very much a spiritual successor to a defunct SDL2 game library I wrote over a decade ago. That engine was largely an ode to (and a grieving process for) the Adobe Flash player as a game platform. The terminology I used there was heavily influenced by Flash, and that terminology lives on in the new `libakgl`. However `libakgl` is C++ and used a lot of standard template library types and operations, very closely mimicking the code flow from ActionScript; `libakgl` is pure C and therefore looks and flows a bit different. Regardless, my work on this library really represents a rebellion against complexity and vendor lock-in.

First, in my day job, I spend a ton of time working with infinite layers of complexity in the DevSecOps space without ever actually touching much real code at all. There’s barely even a computer involved - it’s more like I work with several dozen abstractions of a computer.

Second, in the game space, everything has moved towards complex game engines using higher level languages to accomplish anything. Tools like Unity or Unreal Engine, even open source tools like Godot or Phaser, I personally find that they feel too complex. Given that my fondest game dev memories are from the Flash/ActionScript days, I do wonder a little bit about this feeling - in terms of user experience, tools like GameMaker or Phaser are much closer to Flash than `libakgl`. But they all require me to learn their interface, their quirks, and to confine whatever idea I have into their box. Maybe complexity is the wrong word, but when I look at the majority of modern engines, I wind up thinking, “I don’t want to deal with all that complexity”.

Third, this library is 100% pure C (I’ve tried to keep it C99, but I make no promises, and there are some GNU-isms in there that may not work right outside of GCC). Writing the old `libsdlgame` in C++ was fun, the STL felt like it was making things faster, but it eventually became a total shitshow. I’m sure some of that was my own fault, but some of it was because the STL is notoriously slow. Then there’s the fact that I was doing tons and tons of dynamic memory management in the old version - there are all kinds of dangers associated with that. There were also many pitfalls in the extensive usage of C++’s object oriented model. Here’s a great example from the old codebase that probably says more about my skill as a programmer at that time than it does about the pitfalls of C++’s object oriented model :

    // THE PROJECTILE/CHARACTER SUBCLASSING IS FUCKED. THE ORDER OF THE 'damage' ELEMENT AND OTHER
    // ITEMS CAUSES UNEXPECTED RESULTS AS ITEMS SUCH AS PROJECTILES ARE TYPECAST AS A (Character *)
    // AND PASSED AROUND THRU COLLISION FUNCTIONS. CHANGE THE ORDER THAT THE 'damage' ELEMENT IS DEFINED
    // IN THE CHARACTER CLASS AND YOU'LL SEE THE LASERS START DOING WIERD SHIT AS A RESULT.

… so in this version of the library, we are abandoning as much complexity as possible. Specifically:

1. No dynamic memory allocation. Everything comes from static arrays of objects defined at compile time. SDL still performs some dynamic memory allocation, but that will be converted to use a custom arena memory allocator.
2. Everything is a fatty struct (in the style of the old Quake games, and with a nod to Casey Muratori)
3. Entity behavior can be controlled through setting function pointers on the fatty structs, but there is no inheritance, RTTI or dynamic dispatch

Last, I’m building this library because I don’t like being locked in to any particular engine. Godot, Unreal, Unity, GameMaker, RPG Maker, they’re all fine tools. But they all have their own ecosystems, their own expectations, and their own hard limits. Sometimes I might need to change engines to execute one idea versus another one. By just rolling my own library, I gain lots of flexibility. And it’s all my code, so I have nobody to blame but myself when something breaks - and I also own 100% of the opportunity to make it better.

Last, I’m building this project with cmake, as opposed to the Makefiles I’m so used to. I find that cmake is actually making it really easy to string projects together as dependencies - for example I have a test program for this library which is able to use git submodules to keep all its dependencies together in a monorepo, and cmake does a great job of building and linking everything, without me having to keep track of versions installed on my system.

Right now the library can:

- Load and animate sprites from JSON files describing a spritesheet reference and how to extract frames from the spritesheet
- Load characters from JSON files that describe a collection of sprites that map to a given set of state flags (for example “use sprite ‘walking left’ when actor has state ‘ACTOR_STATE_MOVELEFT’)
- Create actors on the stage, assign them a character, and ensure the correct sprite is shown animating for the correct state
- Load and display orthogonal tilemaps (as exported by Tiled). This includes:
  - Image layers
  - Object layers
    - Object layers can spawn actors at a given point on the map, each being displayed with a given character and starting with a given state
  - Tile layers
    - Actors have a layer ID on the screen, so actors can be drawn between tile layers for depth
- Manage input from the keyboard or gamepads
  - Control maps connect a given Actor object to a given C function via a given SDL input event
  - Multiple control maps can be defined, so that you can easily swap out control schemes (for example use different control schemes for your menu screen, your inventory screen, and your main gameplay screen)

Some of the library has unit tests, which is nice, but it’s hard to conceptualize how to test some of what it does. That might just be me being lazy.

There’s a lot more to be done (see the TODO file for my current shortlist of deliverables), but it’s a fun project. I’ll probably start making real things with it soon.

# akgltest

akgl-test is just a testbed for libakgl. It illustrates:

- Loading assets
  - Sprites from JSON
  - Characters from JSON
  - Tilemaps
- Setting up control maps
  - ESC sends you back to the main menu
  - M toggles music
  - UP moves a character up the screen with a walking animation
  - DOWN moves a character down the screen with a walking animation
  - LEFT moves a character to the left with a walking animation
  - RIGHT moves a character to the right with a walking animation
- Changing through various game states (a loading screen, menu screen, and gameplay)
- Loading and changing tilemaps
  - Creating actors on the screen based off the tilemap
  - Using forced perspective on an image map to create the illusion of depth when using 2D sprites on a prerendered 3D background image

Once I get collision detection working in `libakgl` I’ll start producing small games with it. I think I’ll start with a breakout clone.

Recent Posts
2026-07-10
News-2026-Week-2
2026-07-09
News - 2026 - Week - 28
2026-06-30
Just Be Yourself ... Whoever that is
2026-06-30
You Cant Go Home Again