Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
- name: Setup Zig
uses: mlugg/setup-zig@v2
with:
version: 0.16.0
version: 0.17.0

- name: Resolve artifact version
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ on:
- published
workflow_dispatch:
env:
zig_version: 0.16.0
zig_version: 0.17.0

jobs:
build-macos:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Setup Zig
uses: mlugg/setup-zig@v2
with:
version: 0.16.0
version: 0.17.0

- name: Resolve artifact version
shell: pwsh
Expand Down
2 changes: 1 addition & 1 deletion .mise.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[tools]
zig = "0.16.0"
zig = "0.17.0"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ It also incorporates several open-source components:

### Prerequisites

* [Zig 0.16.0-dev](https://ziglang.org/download/) or later.
* [Zig 0.17.0](https://ziglang.org/download/) or later.

### macOS

Expand Down
4 changes: 2 additions & 2 deletions assets/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.1</string>
<string>1.0.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>2</string>
<string>3</string>
<key>CFBundleIconFile</key>
<string>AppIcon</string>
<key>CFBundleIconName</key>
Expand Down
117 changes: 72 additions & 45 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub fn build(b: *std.Build) void {
// build.zig.zon and compile only the backend matching the target OS.
const dep_nfd = b.dependency("nfd_extended", .{});
exe.root_module.addIncludePath(dep_nfd.path("src/include"));
const nfd_cflags = &[_][]const u8{ "-fno-sanitize=all" };
const nfd_cflags = &[_][]const u8{"-fno-sanitize=all"};
switch (target.result.os.tag) {
.macos => {
addMacFrameworkPathFromSdkRoot(b, exe.root_module);
Expand All @@ -100,7 +100,7 @@ pub fn build(b: *std.Build) void {
exe.root_module.linkSystemLibrary("shell32", .{});
// Link as a GUI app (not console) so launching the .exe does not
// also spawn a console ("DOS") window alongside the main window.
exe.subsystem = .Windows;
exe.subsystem = .windows;
// Embed a manifest that sets the process ACP to UTF-8 so
// C runtime fopen()/CRT path APIs round-trip non-ASCII paths.
exe.root_module.addWin32ResourceFile(.{
Expand Down Expand Up @@ -281,6 +281,52 @@ pub fn build(b: *std.Build) void {
.flags = &.{ "-fno-sanitize=all", b.fmt("-D{s}", .{nk_backend_define}) },
});

// C headers for the Zig side (Zig 0.17 removed @cImport; each module is
// produced by a translate-c step from an entry header in src/cimport/).
const np2_c = b.addTranslateC(.{
.root_source_file = b.path("src/cimport/np2_c.h"),
.target = target,
.optimize = optimize,
});
for (np2_includes) |include| {
np2_c.addIncludePath(b.path(include));
}
for (np2_defines) |define| {
np2_c.defineCMacroRaw(define);
}

const nfd_c = b.addTranslateC(.{
.root_source_file = b.path("src/cimport/nfd_c.h"),
.target = target,
.optimize = optimize,
});
nfd_c.addIncludePath(dep_nfd.path("src/include"));

const nk_c = b.addTranslateC(.{
.root_source_file = b.path("src/cimport/nk_c.h"),
.target = target,
.optimize = optimize,
});
nk_c.addIncludePath(b.path("third_party/nuklear"));
nk_c.addIncludePath(b.path("third_party/sokol"));
nk_c.addIncludePath(dep_sokol.path("src/sokol/c"));

const stdio_c = b.addTranslateC(.{
.root_source_file = b.path("src/cimport/stdio_c.h"),
.target = target,
.optimize = optimize,
});

const c_imports = [_]struct { []const u8, *std.Build.Module }{
.{ "np2_c", np2_c.createModule() },
.{ "nfd_c", nfd_c.createModule() },
.{ "nk_c", nk_c.createModule() },
.{ "stdio_c", stdio_c.createModule() },
};
for (c_imports) |imp| {
exe.root_module.addImport(imp[0], imp[1]);
}

exe.root_module.link_libc = true;
exe.root_module.link_libcpp = true;

Expand All @@ -295,56 +341,31 @@ pub fn build(b: *std.Build) void {
const macos_dir = b.fmt("{s}/MacOS", .{contents_dir});
const resources_dir = b.fmt("{s}/Resources", .{contents_dir});

// 1. Create directory structure
const mkdir = b.addSystemCommand(&.{ "mkdir", "-p" });
mkdir.addArgs(&.{
b.getInstallPath(.prefix, macos_dir),
b.getInstallPath(.prefix, resources_dir),
// Install steps create the directory structure themselves.
// 1. Copy the executable
const install_exe = b.addInstallArtifact(exe, .{
.dest_dir = .{ .override = .{ .custom = macos_dir } },
});
bundle_step.dependOn(&mkdir.step);

// 2. Copy the executable
const cp_exe = b.addSystemCommand(&.{ "cp" });
cp_exe.addArtifactArg(exe);
cp_exe.addArg(b.getInstallPath(.prefix, macos_dir));
cp_exe.step.dependOn(&mkdir.step);
bundle_step.dependOn(&cp_exe.step);

// 3. Copy Info.plist
const cp_plist = b.addSystemCommand(&.{ "cp", "assets/Info.plist" });
cp_plist.addArg(b.getInstallPath(.prefix, b.fmt("{s}/Info.plist", .{contents_dir})));
cp_plist.step.dependOn(&mkdir.step);
bundle_step.dependOn(&cp_plist.step);

// 4. Copy AppIcon.icns
const cp_icon = b.addSystemCommand(&.{ "cp", "assets/AppIcon.icns" });
cp_icon.addArg(b.getInstallPath(.prefix, b.fmt("{s}/AppIcon.icns", .{resources_dir})));
cp_icon.step.dependOn(&mkdir.step);
bundle_step.dependOn(&cp_icon.step);

// 5. Copy the bundled font's OFL license text. M PLUS 1p is embedded in
bundle_step.dependOn(&install_exe.step);

// 2. Copy Info.plist
const install_plist = b.addInstallFile(b.path("assets/Info.plist"), b.fmt("{s}/Info.plist", .{contents_dir}));
bundle_step.dependOn(&install_plist.step);

// 3. Copy AppIcon.icns
const install_icon = b.addInstallFile(b.path("assets/AppIcon.icns"), b.fmt("{s}/AppIcon.icns", .{resources_dir}));
bundle_step.dependOn(&install_icon.step);

// 4. Copy the bundled font's OFL license text. M PLUS 1p is embedded in
// the binary, so the SIL Open Font License 1.1 + copyright notice must
// travel with the distributed .app per the OFL's redistribution terms.
const cp_ofl = b.addSystemCommand(&.{ "cp", "assets/fonts/OFL.txt" });
cp_ofl.addArg(b.getInstallPath(.prefix, b.fmt("{s}/MPLUS1p-OFL.txt", .{resources_dir})));
cp_ofl.step.dependOn(&mkdir.step);
bundle_step.dependOn(&cp_ofl.step);

// 6. Touch the bundle to refresh Finder cache
const touch = b.addSystemCommand(&.{ "touch" });
touch.addArg(b.getInstallPath(.prefix, app_name));
touch.step.dependOn(&cp_exe.step);
touch.step.dependOn(&cp_plist.step);
touch.step.dependOn(&cp_icon.step);
touch.step.dependOn(&cp_ofl.step);
bundle_step.dependOn(&touch.step);
const install_ofl = b.addInstallFile(b.path("assets/fonts/OFL.txt"), b.fmt("{s}/MPLUS1p-OFL.txt", .{resources_dir}));
bundle_step.dependOn(&install_ofl.step);
}

const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
run_cmd.addPassthruArgs();

const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
Expand All @@ -361,6 +382,9 @@ pub fn build(b: *std.Build) void {
}),
});
zig_tests.root_module.addImport("sokol", dep_sokol.module("sokol"));
for (c_imports) |imp| {
zig_tests.root_module.addImport(imp[0], imp[1]);
}
for (np2_includes) |include| {
zig_tests.root_module.addIncludePath(b.path(include));
}
Expand Down Expand Up @@ -396,6 +420,9 @@ pub fn build(b: *std.Build) void {
}),
});
path_tests.root_module.addImport("sokol", dep_sokol.module("sokol"));
for (c_imports) |imp| {
path_tests.root_module.addImport(imp[0], imp[1]);
}
for (np2_includes) |include| {
path_tests.root_module.addIncludePath(b.path(include));
}
Expand Down
12 changes: 6 additions & 6 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
.name = .UsaProject,
// This is a [Semantic Version](https://semver.org/).
// In a future version of Zig it will be used for package deduplication.
.version = "1.0.1",
.version = "1.0.2",
// Together with name, this represents a globally unique package
// identifier. This field is generated by the Zig toolchain when the
// package is first created, and then *never changes*. This allows
Expand All @@ -25,20 +25,20 @@
.fingerprint = 0x14ba4c43ad61d144, // Changing this has security and trust implications.
// Tracks the earliest Zig version that the package considers to be a
// supported use case.
.minimum_zig_version = "0.16.0-dev.3142+5ccfeb926",
.minimum_zig_version = "0.17.0",
// This field is optional.
// Each dependency must either provide a `url` and `hash`, or a `path`.
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
// Once all dependencies are fetched, `zig build` no longer requires
// internet connectivity.
.dependencies = .{
.sokol = .{
.url = "git+https://github.com/floooh/sokol-zig?ref=master#712ff4bf36761592656a7f648b2e80c59bfa6c95",
.hash = "sokol-0.1.0-pb1HK8RqNwCA1y9yR1y0VNeYPv0m2TxtWsQP9y3w6rrS",
.url = "git+https://github.com/floooh/sokol-zig?ref=master#3990b6629704f988041ac7e76ed010348eabd098",
.hash = "sokol-0.1.0-pb1HK6dlQgAVK2z6p9B8rDIzrWEdxn0DeVTcpZrXmATG",
},
.nfd_extended = .{
.url = "git+https://github.com/btzy/nativefiledialog-extended#c9cc7baf287f969686561674a555af5be7ac82b1",
.hash = "N-V-__8AAKkPCwAjJKxq_ALyZqptz0YE1UmwjlUlTGABdCPR",
.url = "git+https://github.com/btzy/nativefiledialog-extended?ref=v1.4.1#65b2f070a0fcfee0d453a64e770a217ab0b6ff4f",
.hash = "N-V-__8AAEXCCwCK8Vr9EDrBMGx0bV1Lt7QiWcrFZ3X2DA75",
},
},
.paths = .{
Expand Down
6 changes: 3 additions & 3 deletions src/archive.zig
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ fn extractPlaylist(io: std.Io, allocator: std.mem.Allocator, m3u_path: [:0]const
const cwd = std.Io.Dir.cwd();
var list: std.ArrayList(Image) = .empty;
for (entries.items) |e| {
const p = a.dupeZ(u8, e.path) catch return Error.OutOfMemory;
const p = a.dupeSentinel(u8, e.path, 0) catch return Error.OutOfMemory;
cwd.access(io, p, .{}) catch {
std.debug.print("!! playlist entry not found, skipping: {s}\n", .{p});
continue;
Expand Down Expand Up @@ -526,13 +526,13 @@ fn dirname(path: []const u8) []const u8 {
fn displayName(a: std.mem.Allocator, raw: []const u8, index: usize) ![:0]const u8 {
if (raw.len == 0 or hasBlankStem(raw))
return std.fmt.allocPrintSentinel(a, "Disk {d}", .{index + 1}, 0);
return a.dupeZ(u8, raw);
return a.dupeSentinel(u8, raw, 0);
}

/// Derive a renderable source label (archive/folder name) from a real path's
/// basename — used verbatim (UTF-8) — falling back to `fallback` when empty.
fn displaySource(a: std.mem.Allocator, raw: []const u8, fallback: []const u8) ![:0]const u8 {
return a.dupeZ(u8, if (raw.len == 0) fallback else raw);
return a.dupeSentinel(u8, if (raw.len == 0) fallback else raw, 0);
}

/// Drop the "<NNNN>_" extraction prefix that unpackImages prepends, recovering
Expand Down
6 changes: 3 additions & 3 deletions src/audio.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ pub fn convertPcmToFloat(dst: []f32, src: [*]const i32, samples: usize) void {
}

test "convertPcmToFloat handles boundary values" {
var dst = [_]f32{0.0} ** 6;
var dst: [6]f32 = @splat(0.0);
const src = [_]i32{
32767, -32768, // Max / Min
0, 1, // Zero / Small positive
-1, 16384, // Small negative / Half max
0, 1, // Zero / Small positive
-1, 16384, // Small negative / Half max
};

convertPcmToFloat(&dst, &src, 3);
Expand Down
13 changes: 1 addition & 12 deletions src/c.zig
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
pub const c = @cImport({
@cInclude("compiler.h");
@cInclude("pccore.h");
@cInclude("dosio.h");
@cInclude("scrnmng.h");
@cInclude("soundmng.h");
@cInclude("sysmng.h");
@cInclude("taskmng.h");
@cInclude("keystat.h");
@cInclude("vram/scrndraw.h");
@cInclude("sound/sound.h");
});
pub const c = @import("np2_c");

// NP2kai core entry points (re-exported through c.zig so callers don't
// need to mix cz.foo and c.bar).
Expand Down
2 changes: 2 additions & 0 deletions src/cimport/nfd_c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// translate-c entry point for nativefiledialog-extended (imported as "nfd_c").
#include "nfd.h"
13 changes: 13 additions & 0 deletions src/cimport/nk_c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// translate-c entry point for Nuklear + sokol_nuklear (imported as "nk_c").
#include "sokol_gfx.h"
#include "sokol_app.h"
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_BUTTON_TRIGGER_ON_RELEASE
#include "nuklear.h"
#include "sokol_nuklear.h"
11 changes: 11 additions & 0 deletions src/cimport/np2_c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// translate-c entry point for the NP2kai core (imported as "np2_c").
#include "compiler.h"
#include "pccore.h"
#include "dosio.h"
#include "scrnmng.h"
#include "soundmng.h"
#include "sysmng.h"
#include "taskmng.h"
#include "keystat.h"
#include "vram/scrndraw.h"
#include "sound/sound.h"
2 changes: 2 additions & 0 deletions src/cimport/stdio_c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// translate-c entry point for libc stdio (imported as "stdio_c").
#include <stdio.h>
10 changes: 5 additions & 5 deletions src/cli.zig
Original file line number Diff line number Diff line change
Expand Up @@ -118,23 +118,23 @@ pub fn parse(allocator: std.mem.Allocator, args: []const []const u8) ParseError!
if (i >= args.len) return error.MissingValue;
const v = args[i];
if (v.len > model_max_len) return error.ModelTooLong;
opts.model = try allocator.dupeZ(u8, v);
opts.model = try allocator.dupeSentinel(u8, v, 0);
continue;
}
if (std.mem.startsWith(u8, a, "--model=")) {
const v = a["--model=".len..];
if (v.len > model_max_len) return error.ModelTooLong;
opts.model = try allocator.dupeZ(u8, v);
opts.model = try allocator.dupeSentinel(u8, v, 0);
continue;
}
if (std.mem.eql(u8, a, "--audio-capture")) {
i += 1;
if (i >= args.len) return error.MissingValue;
opts.audio_capture = try allocator.dupeZ(u8, args[i]);
opts.audio_capture = try allocator.dupeSentinel(u8, args[i], 0);
continue;
}
if (std.mem.startsWith(u8, a, "--audio-capture=")) {
opts.audio_capture = try allocator.dupeZ(u8, a["--audio-capture=".len..]);
opts.audio_capture = try allocator.dupeSentinel(u8, a["--audio-capture=".len..], 0);
continue;
}
if (std.mem.eql(u8, a, "--audio-autotest")) {
Expand Down Expand Up @@ -164,7 +164,7 @@ pub fn parse(allocator: std.mem.Allocator, args: []const []const u8) ParseError!
// enforced when the contained images are mounted.
.archive => {},
}
const path = try allocator.dupeZ(u8, a);
const path = try allocator.dupeSentinel(u8, a, 0);
try disks.append(allocator, .{ .kind = kind, .path = path });
}

Expand Down
Loading
Loading