Participating in #DecemberAdventure this year! I'll be working on porting my fennel fantasy console (https://selfsame.itch.io/jumpminster) from Rust/Miniquad to C/SDL3. Which is already going well, I started last month and most the API is working with the demo game in good working order.
This is my first C project and I'm finding it surprisingly approachable, obviously slow going but the code tends to compile and actually work once I've puzzled it out.
I have some plans for new features as well, mainly an API for render textures which apps can draw to, with an initial 'window' render texture when an app is launched.
After that I'd like to do something more like a desktop & window manager for the system app.
I might also spend a bit of time working on https://github.com/selfsame/localnotes, which I am writing this log in, to
A little thing but I added a draw_9patch to the API which uses SDL's https://wiki.libsdl.org/SDL3/SDL_RenderTexture9Grid
Thought I was going to knock out font loading and rendering tonight but it's a lot more complicated than I'd expected! SDL doesn't have any built in font rendering, just the debug ASCII text. I successfully linked https://github.com/libsdl-org/SDL_ttf, which has freetype and harfbuzz (harfbuzz being the standard way to do complex glyphs and RTl languages), and is probably what I will use, but it's a 17MB .so!
There's some other options:
TBH I will probably sleep on it, and move on to other features. Font rendering wasn't on top of my list and I'm hesitant to have the executable be 30 MB all of a sudden.
As an aside I am very weirded out with C package inclusion where you clone a giant repo into vendored, maybe as a submodule (maybe even recursively??) or run a script that downloads other vendored repositories. Maybe do some platform specific building in these repos, then link and build. I guess you're just manually doing what a package manager does in the background but not looking forwards to cleaning this up to be buildable by other people.
Spent some time trying to slim down libSDL3.so by turning features off, which didn't make a drastic difference, and then remembered that debug builds are bigger and the release size of SDL is like 3.5 MB. Also tried statically linking SDL and gave up.
After that I decided I did want to use stb_truetype.h for text rendering, and maybe even try to use harfbuzz if things go well. I got as far as loading a ttf file and baking a texture atlas from it. Then I can convert that to a 4 channel 8 bit image format and make an SDL_Texture, which is great!
From here I can map text char to subrect and do a draw text function that iterates a string drawing each glyph while tracking ax offset. This is where harfbuzz could come in to convert a string into a properly positioned list of glyph codes, but we'll see.
I also have to do something about my 2 bit color constraints, but I am thinking when i switch to render textures I can have a shader enforce that.
Wrote a function that can render ASCII text from the atlas, which wasn't that complicated with the baked data from stbtt_backedchar.
There's blurriness issues especially with pixel perfect fonts, but I think there some integer rounding that can fix that.
Rounding the glyph and destination rects did help with blurry aliasing, but as the texture atlas itself had aliasing, I ended up putting a threshold on the alpha channel. This is fine as fen2 is a black & white fantasy console.
Non pixel fonts look a bit crusty.
It looks especially bad at small sizes
I am now wondering how pixel perfect fonts that support a range of sizes would work with modern font formats, as you'd need specific shaping for specific sizes. I am thinking that's not a thing, and that pixel truetype fonts are made for one specific size (or multiples of 2)
Tired but I did some things tonight: Font atlas is smaller and scaled with the font size. I'm using SDL_SetTextureColorMod to draw the text in either black or white, so until I decide to support unicode and bidi text I can consider that bit done.
I also moved all the bound API functions into their own .c file which I include, which is nice but the editor is confused so maybe I have to look into how to organize C src code a bit.
Started working on the new feature where apps will have textures they can allocate and render to, instead of just drawing everything to the renderer every update tick.
Apps will have an initial texture (0) set to full screen, and would be able to request arbitrary sized textures.
I have the texture allocation stuff in, just need to actually draw to them and figure out how I'd like the API. Maybe setting render target is part of app_update but the app should be able to set the render texture as well.
Also thinking the system app is now responsible for rendering other app's textures, so like:
Actually using rendertextures, which is working great with no effect on performance. There's two new fennel api functions: draw_rendertexture and draw_app_rendertexture for the system_app to draw whichever apps it's presenting.
I think from here i need a few api bindings to create/destroy rendertextures. I also need to think through how apps and the system_app set dimensions on the initial texture:
Fleshing out some API for:
In this screenshot I've created a rendertexture with (var rtex (create_rendertexture 512 512)) then during update i can target it for drawing, then target the app's main texture 0 and draw rtex twice. It's cool, it's exactly the kind of thing I wanted to be doing with fen2.
Some thoughts on what's next:
lua_tointegerx et cetera)Also thinking what if would look like if apps didn't have to grind update at 100% CPU. I could throttle to vsync but what's beyond that? Event driven updates? Dirty flags when an app has rendered so the system doesn't have to draw the texture every frame?
I did unify the draw functions into (draw_img "img/foo.png" x y sx? sy? sw? sh? dw? dh?), which is versatile if not a little long, but for basic sprite stuff you're just doing (draw_img "tilesheet.png" x y sx sy sw sh).
Not much else tonight mainly reading about audio in SDL3, which doesn't look that simple!
Added a fullscreen toggle with f11. If the screen is big enough the display gets drawn at 2x scale, and it's centered as well. Debating if I want to just use the window size instead of 640x480 but that introduces complications.
Finding that SDL3 has anything I could ask for, so things like centering my renderer's viewport, scale, and then getting the mouse coords as very easy.
What's left on my plate for December? I think:
Bit of work adding repeating pattern drawing and getting ready to start making a window manager.
Sorted out several issues related to maintaining state for the app currently having lua code run. Moved all of that into the app_eval function so it restores state after it's finished, which prevents that class of bug.
More work on the window management. There's plenty to do but I think it will go like: