GasInfinity / zitrus

Pure zig 3DS homebrew SDK

Home Page:https://gasinfinity.github.io/zitrus/

Repository from Github https://github.comGasInfinity/zitrusRepository from Github https://github.comGasInfinity/zitrus

Zitrus Logo


Zig support

3DS homebrew sdk written entirely in zig.

Installation

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", .{});
const zitrus_mod = zitrus_dep.module("zitrus");
// zitrus contains code useful for tooling outside of a 3DS environment.

// You must use the same target as `zitrus_mod`
const exe_mod = b.createModule(.{
    .root_source_file = b.path("src/your_main.zig"),
    .target = zitrus.horizon_arm11, // this is currently deprecated as we will now have 'arm-3ds' in zig: https://github.com/ziglang/zig/pull/24938
    .optimize = optimize,
});

exe_mod.addImport("zitrus", zitrus_mod);

const exe = zitrus.addExecutable(b, .{
    .name = "homebrew.elf",
    .root_module = exe_mod,
});

// You can skip installing the elf but it is recommended to keep it for debugging purposes
b.installArtifact(exe);

const homebrew_smdh = zitrus.addMakeSmdh(b, .{
    .name = "homebrew.icn",
    .settings = b.path("path-to-smdh-settings.ziggy"), // look at any demo for a quick example or the schema in tools/make-smdh/settings.ziggy-schema
    .icon = b.path("path-to-icon.png/jpg/..."), // supported formats depends on zigimg image decoding.
});

// XXX: Blocked by upstream, cache isn't caching.
// See `addMakeRomFs` if you need something patchable unlike `@embedFile`.

// 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.addMake3dsx(b, .{ .name = "homebrew.3dsx", .exe = exe, .smdh = homebrew_smdh });
b.getInstallStep().dependOn(&b.addInstallBinFile(final_3dsx, "homebrew.3dsx").step);

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;
}

Examples / Demos

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.

Legend

⚠️ 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 #1

🟒 Fully implemented 🟑 Partially implemented πŸ”΄ Implementation not started/missing critical things

πŸ”‹ High priority πŸͺ« Low priority

Tooling coverage

  • 🟒 Smdh creation (tools/Smdh)

  • 🟒 Elf -> 3dsx conversion (tools/3dsx)

  • 🟒 PICA200 shader assembler/disassembler (tools/Pica):

    • 🟒 Instruction encoding/decoding
    • 🟒 Assembler
    • πŸ”΄πŸͺ« Disassembler
    • 🟒 Diagnostics
    • 🟒 Output ZPSH files.
    • πŸ”΄πŸͺ« Output SHBIN/RAW files
  • 🟑 NCCH (tools/Ncch):

    • 🟒 ExeFS (tools/ExeFs)
    • 🟒 RomFS (tools/RomFs)
    • πŸ”΄ elf -> ExeFS .code
  • πŸ”΄ Everything not listed here

  • 🟑πŸͺ« Dumping, a.k.a: 3dsx/exefs --> bin/elf, smdh -> config + icons, etc...

    • 🟒 Smdh -> config + icons
    • 🟑 NCCH:
      • 🟒 LZrev decompressor.
      • 🟒 ExeFS
      • πŸ”΄ RomFS
    • πŸ”΄ Everything not listed here

HOS Coverage

Zitrus is currently very work in progress, it's able to run basic homebrew but lots of things are missing (services, io, etc...)

  • 🟑 Tests
  • 🟑 C API
  • 🟑 Docs

Runtime support

  • 🟒 crt0/startup code
  • πŸ”΄β›” Thread local variables.
  • πŸŸ‘β›”πŸ”‹ panic and error reporting and tracing.
  • πŸ”΄β›”πŸ”‹ Io interface support (zig 0.16).
  • πŸŸ‘β›”πŸ”‹ Application Test runner.

Gpu Support

  • 🟒 Software rendering with Framebuffers
  • 🟒 GX Commands
  • 🟒 2D/3D Acceleration (a.k.a: REALLY using the Gpu to do things)
  • πŸŸ‘πŸ”‹πŸ”‹ mango, a low-level, vulkan-like graphics api for the PICA200.

Port/Service Support

  • 🟒 srv:

  • 🟒 err:f

  • 🟑 APT:S/A/U

  • 🟑 hid:SPRV/USER

  • 🟒 ir:rst

  • 🟑 fs:USER/LDR

  • 🟑 cfg:u/s/i

  • 🟒 gsp::Gpu

  • 🟑πŸͺ« gsp::Lcd

  • 🟑 ns:s

  • 🟒 ns:p/c

  • 🟑 csnd:SND

  • 🟑πŸͺ« pm:app

  • 🟒 pm:dbg

  • πŸ”΄ All other services not listed here

Applet Support

  • 🟒 error
  • 🟑 swkbd
  • πŸ”΄ All other applets not listed here.

Mango coverage

  • πŸ”΄ Tests

  • 🟑 C API

  • 🟑 Docs

  • 🟑 Device HOS implementation.

  • 🟑 Queues

    • 🟑 Fill (clear and fill operations)
    • 🟑 Transfer (copy and blit operations)
    • 🟒 Submit (CommandBuffer submission)
    • 🟑 Present (see PresentationEngine support)
  • 🟑 Memory / Buffers

  • 🟑 Pipelines

  • 🟑 CommandPool

    • 🟒 CommandBuffer recycling
    • πŸ”΄ Native buffer pooling/reusing
    • πŸ”΄ Prewarm parameters.
  • 🟑 CommandBuffer's

  • 🟑 Images / ImageViews

    • 🟑 Up to 8 Image layers
    • 🟑 Up to 8 mipmap levels (1024x1024 -> 8x8)
  • 🟑 Image Sampling

  • 🟒 Synchronization primitives / driver thread.

  • 🟑 Presentation engine.

    • 🟒 2D (Top and bottom)
    • 🟒 3D (Top, 2 layers per image)
    • 🟑 Full resolution (Top 240x800 swapchain, needs testing but should work)
  • πŸ”΄πŸͺ« Device HAL abstraction.

  • πŸ”΄πŸͺ« Device baremetal implementation (prerequsite: HAL abstraction).

Why?

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:

  • Really simplified and easy development. You don't need complex toolchains, you just need the zig executable, that's it! (However, obviously it is recommended that you use devkitPRO's tools as I'm sure you'll need them. You want to use gdb, don't you?)
  • Safety in 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)
  • Really useful and simple build-system (as you've seen the example build.zig is really small and makefiles are really arcane)

Credits

  • 3dbrew is seriously the best resource if you need info about the 3DS hardware/software.
  • gbatek is the second best resource for low level info about the 3DS hardware.
  • @devkitPro for the tooling, a starting point/reference for this project and reference for unknown/undocumented/unspecified things (e.g: libctru and how tf jumping to home menu worked).
  • @azahar-emu/azahar for providing an emulator to quickly test changes and the initial iterations.
  • @LumaTeam/Luma3DS for literally saving my life when trying to debug things in my 2DS.

About

Pure zig 3DS homebrew SDK

https://gasinfinity.github.io/zitrus/

License:MIT License


Languages

Language:Zig 99.8%Language:Linker Script 0.1%Language:Nix 0.1%