What are we building for?
Zig supports cross-compilation out the box. So all we gotta do is specify the correct target for the Wii.
Since I want to keep whatever game/engine I build cross-platform, I’ll put Wii-specific build config in config/platform/wii/build.zig
pub fn target(b: *std.Build) std.Build.ResolvedTarget {
return b.resolveTargetQuery(.{
.ofmt = .elf,
.os_tag = .freestanding,
.cpu_arch = .powerpc,
.cpu_model = .{ .explicit = &std.Target.powerpc.cpu.@"750" },
.cpu_features_add = std.Target.powerpc.featureSet(&.{.hard_float}),
.abi = .eabihf,
});
}The Wii’s Broadway CPU uses a hardware floating-point architecture which means it has a set of dedicated float registers. It’s crucial we set the ABI correctly, so Zig code uses the correct registers. I’ve lost several hours due to having the wrong ABI set trying to figure out why all my floats are wrong lol.
We compile to an executable ELF file.
We can start off small with a very simple build script that compiles main.zig for the above target:
const std = @import("std");
const wii = @import("config/platform/wii/build.zig");
pub fn build(b: *std.Build) void {
const target = wii.target(b);
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "wraith.elf",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.imports = &.{},
}),
});
b.installArtifact(exe);
}