Homebrewers, try zig!
Discussing about zig for development of homebrew
If you read my last blog post (very badly written. i’m still improving my communication skills :p), you may know I’ve been dabbling with my previously stored 3DS (well, 2DS).
Well, since that post, a lot of things happened.
the current state of zig homebrew
What was only some start code and very basic abstractions now is a fully functional and almost type-safe API where everything from _start
to rendering a triangle is done explicitly by the user and for the first stable release, the SDK will try to never use global variables.
If you’ve seen any of the links or already know what zitrus
is, you’ll see that it is written in zig. I seriously think that it’s one of the best compilers/assemblers for homebrew, it is already known for its great cross-compilation capabilities.
However it doesn’t seem to be used anywhere near any homebrew project (except gba! at least as of today) and yes, I’m aware of zig-homebrew but if you take a little peek you’d see…
- zig-3ds last updated 3 years ago
- zig-switch last updated 3 years ago
- and so on…
Furthermore every sample online (not only from zig-homebrew
) has system dependencies and are not self-contained which makes developing and compiling much more cumbersome, now instead of downloading and adding one binary to my path I also have to download an entire toolchain and more. Experienced developers and users won’t have any problems but inexperienced or new ones will get frustrated just by trying to make a simple example compile or work.
zig as a build system
You don’t have to use the zig build system, only using it as a compiler is already a win. However, you can get deeper and learn and use the zig build system and zig as it has important advantages
A real world example of everything I told you is zitrus. Want to run a demo
?
git clone https://github.com/GasInfinity/zitrus/
cd zitrus/demo/<insert-demo>
# With `zig` in your path
zig build
That’s it! You can do this from every platform zig
supports. There’s only one problem, to support libc
we would need to port one or not, only time will tell. That doesn’t mean we can’t have a C API.
using zig
as a language
With zig
type-safety is a must, you can still develop without type-safety if you want, but using the rich type system that zig
provides is one of the best experiences you could have. If you do it correctly you can have almost any type-safe construct you can think of, here are some real world examples (from zitrus
again :p)
- Remember those bitfields defined with macros and lots of shifting? Say hello to
packed struct
s!
pub const FramebufferFormat = packed struct(u32) {
color_format: ColorFormat, // u3
_unknown0: u1 = 0,
interlacing_mode: FramebufferInterlacingMode, // u2
alternative_pixel_output: bool,
_unknown1: u1 = 0,
dma_size: DmaSize, // u2
_unknown2: u6 = 0,
_unknown3: u16 = 0,
};
- Not only type-safety can be achieved with zig,
comptime
is such a powerful tool that you can abstract lots of constructs safely and even in a easy to use way. Here’s another example extracted fromzitrus
: 3DS processes can communicate over IPC and for that a small amount of memory is allocated in a thread-local page, furthermore commands are just a series of words that begin with a header. Withinzitrus
commands are defined via structs serialized at comptime with an id, you only need to define the command beforehand, and there’s no need to modify the memory yourself (but you’re still able if you want to!)
that’s everything folks
I could keep talking about zig
but I like to think that you’ll never know how good (or bad) something until you try it, why don’t you give it a try if you’re not already using it :p?
thanks for reading!
zig is a language that moves really fast, latest version at this point is 0.15.1 so some things may have changed or improved!
Written in September 10, 2025 18:00 UTC