GasInfinity/zitrus
Pure zig 3DS homebrew SDK
14ab564b8683d6e7498ea455e47bd0dd08e4eb761929cbae9d41c7e1178e494e42aa7b349a68cd8af309c3b5ab2fbd566755a875aa4df5854777709ed7717b3617d58160635623fe86d4bf86065498e03DS homebrew sdk written entirely in zig.
NOTE Not even the language this project is written in is 1.0
You acknowledge that any amount of breaking changes may occur until the first stable (minor) release, a.k.a
0.1.0. No ETA is given.
zig fetch --save git+https://github.com/GasInfinity/zitrus
Then add this to your build.zig:
const zitrus = @import("zitrus");
const zitrus_dep = b.dependency("zitrus", .{});
// zitrus contains code useful for tooling outside of a 3DS environment.
const zitrus_mod = zitrus_dep.module("zitrus");
const exe = b.addExecutable(.{
.name = "panic.elf",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = b.resolveTargetQuery(zitrus.target.arm11.horizon.query), // zig 0.16.0 will add 'arm-3ds' and this will be deprecated!
.optimize = optimize,
.single_threaded = true, // XXX: Currently needed for page_allocator.
.imports = &.{
.{ .name = "zitrus", .module = zitrus_mod },
},
}),
});
// 3DSX's are PIE's
exe.pie = true;
// Needed for any binary which targets the 3DS
exe.setLinkerScript(zitrus_dep.path(zitrus.target.arm11.horizon.linker_script));
// You can skip installing the elf but it is recommended to keep it for debugging purposes
b.installArtifact(exe);
const smdh: zitrus.MakeSmdh = .init(zitrus_dep, .{
.settings = b.path("path-to-smdh-settings.zon"), // look at any demo for a quick sample.
.icon = b.path("path-to-icon.png/jpg/..."), // supported formats depends on zigimg image decoding.
});
// See `MakeRomFs` if you need something patchable unlike `@embedFile`.
// WARNING: Won't be properly cached as there's an issue upstream.
// This step will convert your executable to 3dsx (the defacto homebrew executable format) to execute it in an emulator or real 3DS
const final_3dsx: zitrus.Make3dsx = .init(zitrus_dep, .{ .exe = exe, .smdh = smdh });
final_3dsx.install(b, .default);
In your root file, you must also add this, as there's no way to implicitly tell zig to evaluate/import it automagically:
pub const panic = zitrus.horizon.panic;
comptime {
_ = zitrus;
}
Currently there are multiple examples in the demo/ directory. To build them, you must have zig 0.15.1 in your path and run zig build.
mango contains samples of how to use the mango graphics api.
panic is a simple example that panics when opened to test panics and traces.
info is a simple app that currently shows the console region and model (will be updated to show more info over time).
bitmap is a port of the bitmap example in libctru's 3ds-examples.
flappy is a simple fully functional flappy bird clone written entirely with software blitting.
gpu is a playground for mango, bleeding edge features are tested there. Not really an example per-se.
You can (and are encouraged) to look at the tools directory as it is a good example of how to use the API's zitrus provides outside (and inside!) of a 3DS environment. Almost all tools are self-contained and span 50-300 LOC.
โ ๏ธ Feature regressed temporarily due to dependency or upstream (usually when zig updates this can happen)
โ Blocked due to upstream. Impossible to do until something gets fixed or added, usually listed in https://github.com/GasInfinity/zitrus/issues/1
๐ข Fully implemented ๐ก Partially implemented ๐ด Implementation not started/missing critical things
๐ High priority ๐ชซ Low priority
threadlocal variables.srv:err:fAPT:S/A/Uhid:SPRV/USERir:rstfs:USER/LDRcfg:u/s/igsp::Gpugsp::Lcdns:sns:p/ccsnd:SNDpm:apppm:dbgsoc:Ups:pspxi:ps9Loadererrorswkbdfreestanding usage)Double or Triple buffered in Mailbox or Fifo.CommandBuffer submission)PresentationEngine)SemaphoresDeviceMemoryBuffersSamplerImages / ImageViewsCommandPoolsPipelinesCommandBuffersWhether register bits are present and/or relevant tooling (assemblers, disassemblers, etc...)
I wanted to learn arm and always wanted to develop 3DS homebrew, also I searched and I haven't found any kind of zig package that doesn't use libctru, so I just started reading a lot and doing things. Furthermore, using only zig has a lot of advantages:
zig executable, that's it. The tools zitrus provides also have no dependencies, they'll work on any platform that zig supports! You can still use devkitPRO's binutils if you need.Debug and ReleaseSafe modes. Zitrus currently uses the ErrDisp port to report panics and returned errors. The only missing thing is reporting return traces with debugging symbols (Currently only addresses are logged)build.zig is really small and makefiles are really arcane)