diff --git a/.build.yml b/.build.yml
deleted file mode 100644
index 7ef127b..0000000
--- a/.build.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-image: alpine/edge
-packages:
- - glfw-dev
- - glu-dev
- - libsndfile-dev
- - openal-soft-dev
- - reuse
- - zig
-sources:
- - https://git.sr.ht/~cnx/blackshades
-tasks:
- - build: |
- cd blackshades
- zig build -Doptimize=ReleaseSafe
- - reuse: reuse --root blackshades lint
diff --git a/.gitignore b/.gitignore
index e73c965..3389c86 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-zig-cache/
+.zig-cache/
zig-out/
diff --git a/.gitmodules b/.gitmodules
index c564c4d..43b758c 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,15 +1,6 @@
-[submodule "lib/zeal"]
- path = lib/zeal
- url = https://git.sr.ht/~cnx/zeal
-[submodule "lib/loca"]
- path = lib/loca
- url = https://git.sr.ht/~cnx/zig-loca
[submodule "lib/ini"]
path = lib/ini
url = https://github.com/ziglibs/ini
-[submodule "lib/gfz"]
- path = lib/gfz
- url = https://git.sr.ht/~cnx/gfz
[submodule "lib/qoi"]
path = lib/qoi
- url = https://github.com/MasterQ32/zig-qoi
+ url = https://github.com/ikskuh/zig-qoi
diff --git a/.reuse/dep5 b/.reuse/dep5
deleted file mode 100644
index d51c471..0000000
--- a/.reuse/dep5
+++ /dev/null
@@ -1,102 +0,0 @@
-Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Source: https://sr.ht/~cnx/blackshades
-Upstream-Name: Black Shades
-Upstream-Contact: Nguyễn Gia Phong <cnx@loang.net>
-
-Files: *.cpp *.h *.zig
-Copyright: See individual files
-License: GPL-3.0-or-later
-
-Files:
- *.tsv
- data/models/blocks/*
- data/models/collide/*
- data/models/knife.off
- data/models/skeleton/*
- data/models/streets/*
- data/sounds/Lose.ogg
- data/sounds/bounce.ogg
- data/sounds/bounce2.ogg
- data/sounds/disguise-kill.ogg
- data/sounds/explosion.ogg
- data/sounds/footstep/*
- data/sounds/handlerelease.ogg
- data/sounds/headland.ogg
- data/sounds/headshot.ogg
- data/sounds/riflewhack.ogg
- data/sounds/soul-in.ogg
- data/sounds/soul-out.ogg
- data/sounds/underwater.ogg
- data/textures/blood/*
- data/textures/flare.qoi
- data/textures/font.qoi
- data/textures/scope.qoi
- data/textures/sprites/blood.qoi
- data/textures/sprites/flash-hit.qoi
- data/textures/sprites/flash-muzzle.qoi
- data/textures/sprites/person-dead.qoi
- data/textures/sprites/person.qoi
- data/textures/sprites/smoke.qoi
-Copyright: David Rosen
-License: GPL-3.0-or-later
-
-Files: data/levels.ini
-Copyright:
- David Rosen
- Nguyễn Gia Phong
-License: GPL-3.0-or-later
-
-Files:
- data/models/grenade/*
- data/models/guns/*
-Copyright: David Drew
-License: GPL-3.0-or-later
-
-Files:
- data/sounds/gun/*
- data/sounds/impact/body-fall.wav
- data/sounds/impact/body-hit.wav
- data/sounds/impact/knife-stab.wav
- data/sounds/impact/munch.wav
- data/sounds/music/menu.opus
- data/sounds/rain.ogg
- data/textures/black.qoi
- data/textures/bullet-hole.qoi
- data/textures/sprites/snowflake.qoi
- data/textures/sprites/white.qoi
-Copyright: N/A
-License: CC0-1.0
-
-Files: data/sounds/grenade/*
-Copyright: CGEffex
-License: CC-BY-3.0
-
-Files: data/sounds/gun/near-bullet.wav
-Copyright: _def
-License: CC-BY-3.0
-
-Files: data/sounds/music/assassin.opus
-Copyright: remaxim
-License: CC-BY-4.0
-
-Files: data/sounds/music/zombie.opus
-Copyright: remaxim
-License: CC-BY-SA-3.0
-
-Files: data/sounds/impact/wall-hit.wav
-Copyright: toxicwafflezz
-License: CC-BY-3.0
-
-Files: screenshot.png
-Copyright: Wolfire Games
-License: GPL-3.0-or-later
-
-Files:
- .build.yml
- .gitignore
- .gitmodules
- CHANGES
- README.md
- data/config.ini
-Copyright: N/A
-License: CC0-1.0
diff --git a/REUSE.toml b/REUSE.toml
new file mode 100644
index 0000000..fd19dcd
--- /dev/null
+++ b/REUSE.toml
@@ -0,0 +1,101 @@
+version = 1
+
+[[annotations]]
+path = ["**.cpp", "**.h", "**.zig"]
+SPDX-FileCopyrightText = "See individual files"
+SPDX-License-Identifier = "GPL-3.0-or-later"
+
+[[annotations]]
+path = [ "data/models/grenade/*.off", "data/models/guns/*.off" ]
+SPDX-FileCopyrightText = "David Drew"
+SPDX-License-Identifier = "GPL-3.0-or-later"
+
+[[annotations]]
+path = [ "**.tsv", "**.off",
+ "data/sounds/Lose.ogg",
+ "data/sounds/bounce.ogg",
+ "data/sounds/bounce2.ogg",
+ "data/sounds/disguise-kill.ogg",
+ "data/sounds/explosion.ogg",
+ "data/sounds/footstep/*.ogg",
+ "data/sounds/handlerelease.ogg",
+ "data/sounds/headland.ogg",
+ "data/sounds/headshot.ogg",
+ "data/sounds/riflewhack.ogg",
+ "data/sounds/soul-in.ogg",
+ "data/sounds/soul-out.ogg",
+ "data/sounds/underwater.ogg",
+ "data/textures/blood/*.qoi",
+ "data/textures/flare.qoi",
+ "data/textures/font.qoi",
+ "data/textures/scope.qoi",
+ "data/textures/sprites/blood.qoi",
+ "data/textures/sprites/flash-hit.qoi",
+ "data/textures/sprites/flash-muzzle.qoi",
+ "data/textures/sprites/person-dead.qoi",
+ "data/textures/sprites/person.qoi",
+ "data/textures/sprites/smoke.qoi" ]
+SPDX-FileCopyrightText = "David Rosen"
+SPDX-License-Identifier = "GPL-3.0-or-later"
+
+[[annotations]]
+path = "data/levels.ini"
+precedence = "aggregate"
+SPDX-FileCopyrightText = [ "David Rosen", "Nguyễn Gia Phong" ]
+SPDX-License-Identifier = "GPL-3.0-or-later"
+
+[[annotations]]
+path = [ "data/sounds/gun/**.wav",
+ "data/sounds/impact/body-fall.wav",
+ "data/sounds/impact/body-hit.wav",
+ "data/sounds/impact/knife-stab.wav",
+ "data/sounds/impact/munch.wav",
+ "data/sounds/music/menu.opus",
+ "data/sounds/rain.ogg",
+ "data/textures/black.qoi",
+ "data/textures/bullet-hole.qoi",
+ "data/textures/sprites/snowflake.qoi",
+ "data/textures/sprites/white.qoi"]
+SPDX-FileCopyrightText = "None"
+SPDX-License-Identifier = "CC0-1.0"
+
+[[annotations]]
+path = "data/sounds/grenade/**"
+SPDX-FileCopyrightText = "CGEffex"
+SPDX-License-Identifier = "CC-BY-3.0"
+
+[[annotations]]
+path = "data/sounds/gun/near-bullet.wav"
+SPDX-FileCopyrightText = "_def"
+SPDX-License-Identifier = "CC-BY-3.0"
+
+[[annotations]]
+path = "data/sounds/music/assassin.opus"
+SPDX-FileCopyrightText = "remaxim"
+SPDX-License-Identifier = "CC-BY-4.0"
+
+[[annotations]]
+path = "data/sounds/music/zombie.opus"
+SPDX-FileCopyrightText = "remaxim"
+SPDX-License-Identifier = "CC-BY-SA-3.0"
+
+[[annotations]]
+path = "data/sounds/impact/wall-hit.wav"
+SPDX-FileCopyrightText = "toxicwafflezz"
+SPDX-License-Identifier = "CC-BY-3.0"
+
+[[annotations]]
+path = "screenshot.png"
+SPDX-FileCopyrightText = "Wolfire Games"
+SPDX-License-Identifier = "GPL-3.0-or-later"
+
+[[annotations]]
+path = [ ".gitignore",
+ ".gitmodules",
+ "CHANGES",
+ "README.md",
+ "REUSE.toml",
+ "build.zig.zon",
+ "data/config.ini" ]
+SPDX-FileCopyrightText = "None"
+SPDX-License-Identifier = "CC0-1.0"
diff --git a/build.zig b/build.zig
index 8c5c4c8..97957bd 100644
--- a/build.zig
+++ b/build.zig
@@ -1,5 +1,5 @@
// Build recipe
-// Copyright (C) 2021-2023 Nguyễn Gia Phong
+// Copyright (C) 2021-2023, 2025 Nguyễn Gia Phong
//
// This file is part of Black Shades.
//
@@ -18,61 +18,51 @@
const Build = @import("std").Build;
const Compile = Build.Step.Compile;
-const InstallDirectoryOptions = Build.InstallDirectoryOptions;
-
-const data = InstallDirectoryOptions{
- .source_dir = .{ .path = "data" },
- .install_dir = .{ .custom = "share" },
- .install_subdir = "blackshades",
-};
pub fn build(b: *Build) void {
- const bin = b.addExecutable(.{
- .name = "blackshades",
- .root_source_file = .{ .path = "src/main.zig" },
+ const mod = b.createModule(.{
+ .root_source_file = b.path("src/main.zig"),
.target = b.standardTargetOptions(.{}),
.optimize = b.standardOptimizeOption(.{}),
});
- bin.addIncludePath(.{ .path = "src" });
- bin.addCSourceFiles(&.{
- "src/GameDraw.cpp",
- "src/GameInitDispose.cpp",
- "src/GameLoop.cpp",
- "src/GameTick.cpp",
- "src/Globals.cpp",
- "src/Person.cpp",
- "src/Skeleton.cpp",
- "src/Sprites.cpp",
- }, &.{ "--std=c++17", "-Wall", "-Werror", "-fno-sanitize=undefined" });
-
- for ([_]struct { []const u8, []const u8 }{
- .{ "gfz", "lib/gfz/src/gfz.zig" },
- .{ "ini", "lib/ini/src/ini.zig" },
- .{ "loca", "lib/loca/src/main.zig" },
- .{ "qoi", "lib/qoi/src/qoi.zig" },
- .{ "zeal", "lib/zeal/src/zeal.zig" },
- }) |lib|
- bin.addModule(lib[0], b.createModule(.{
- .source_file = .{ .path = lib[1] },
- }));
- @import("lib/gfz/build.zig").link(bin);
- @import("lib/zeal/build.zig").link(bin);
- bin.linkSystemLibrary("GL");
- bin.linkSystemLibrary("GLU");
- bin.linkSystemLibrary("c++");
+ mod.addIncludePath(b.path("src"));
+ mod.addCSourceFiles(.{
+ .files = &.{
+ "src/GameDraw.cpp",
+ "src/GameInitDispose.cpp",
+ "src/GameLoop.cpp",
+ "src/GameTick.cpp",
+ "src/Globals.cpp",
+ "src/Person.cpp",
+ "src/Skeleton.cpp",
+ "src/Sprites.cpp",
+ },
+ .flags = &.{ "--std=c++17", "-Wall", "-Werror" },
+ });
+ mod.linkSystemLibrary("GL", .{});
+ mod.linkSystemLibrary("GLU", .{});
+ mod.linkSystemLibrary("c++", .{});
+ inline for (.{ "gfz", "ini", "known-folders", "qoi", "zeal" }) |lib|
+ mod.addImport(lib, b.dependency(lib, .{}).module(lib));
+ const data = Build.Step.InstallDir.Options{
+ .source_dir = b.path("data"),
+ .install_dir = .{ .custom = "share" },
+ .install_subdir = "blackshades",
+ };
b.installDirectory(data);
const options = b.addOptions();
const data_dir = b.getInstallPath(data.install_dir, data.install_subdir);
options.addOption([]const u8, "data_dir", data_dir);
- bin.addOptions("build_options", options);
- b.installArtifact(bin);
+ mod.addOptions("build_options", options);
+ const bin = b.addExecutable(.{ .name = "blackshades", .root_module = mod });
+ b.installArtifact(bin);
const run_cmd = b.addRunArtifact(bin);
- run_cmd.step.dependOn(b.getInstallStep());
+ //run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args|
run_cmd.addArgs(args);
- const run_step = b.step("run", "Run the app");
+ const run_step = b.step("run", "Run the game");
run_step.dependOn(&run_cmd.step);
}
diff --git a/build.zig.zon b/build.zig.zon
new file mode 100644
index 0000000..e5e0969
--- /dev/null
+++ b/build.zig.zon
@@ -0,0 +1,36 @@
+.{
+ .name = .blackshades,
+ .version = "2.5.3",
+ .fingerprint = 0xd1f5f56cdf18153,
+ .minimum_zig_version = "0.14.0",
+ .dependencies = .{
+ .gfz = .{
+ .url = "git+https://trong.loang.net/~cnx/gfz?ref=0.1.0#601c886f4b40d6a513563b5a883010633e52bf43",
+ .hash = "gfz-0.1.0-3UBgOH-DAAD1E3l0QB8DihsttSChM4VWHeU1QKeG6btY",
+ },
+ .ini = .{
+ .url = "lib/ini",
+ .hash = "ini-0.1.0-AAAAAJ4lAAAeuOSEbouG5uNtHCmngXktnF3PTsfjxvDq",
+ },
+ .@"known-folders" = .{
+ .url = "git+https://github.com/ziglibs/known-folders#aa24df42183ad415d10bc0a33e6238c437fc0f59",
+ .hash = "known_folders-0.0.0-Fy-PJtLDAADGDOwYwMkVydMSTp_aN-nfjCZw6qPQ2ECL",
+ },
+ .qoi = .{
+ .url = "lib/qoi",
+ .hash = "qoi-0.1.0-5Hmo8rpqAAD1pnE4OYX2tdvxLupff9nkjBGxuxVNtky8",
+ },
+ .zeal = .{
+ .url = "git+https://trong.loang.net/~cnx/zeal?ref=0.1.0#7580c25a081e39732afaaa7a630d7f58005d5ab1",
+ .hash = "zeal-0.1.0-90hghYyhAAAKkKkGWzVjxtxlZiwyRD2YNd3xDZRqrC9a",
+ },
+ },
+ .paths = .{
+ "LICENSES",
+ "README.md",
+ "build.zig",
+ "build.zig.zon",
+ "data",
+ "src",
+ },
+}
diff --git a/lib/gfz b/lib/gfz
deleted file mode 160000
-Subproject d30ae1d4a46ad4b1f7b3c45c59dee268ab95c6b
diff --git a/lib/ini b/lib/ini
-Subproject 2b11e8fef86d0eefb225156e695be1c1d5c35cb
+Subproject 684113312f9d8a70fa6cf928277a77be3316fc7
diff --git a/lib/loca b/lib/loca
deleted file mode 160000
-Subproject aac1315920bb9f2c1e3492825c69f764d4a8525
diff --git a/lib/qoi b/lib/qoi
-Subproject 524efec9e9522f8e2b72e9d67b36d5d5e69a767
+Subproject 63caa52c9d590ef76405922f419540e47bf393d
diff --git a/lib/zeal b/lib/zeal
deleted file mode 160000
-Subproject eb65c5633e1bfae26ae95c6183cc74c2b593794
diff --git a/src/Decals.zig b/src/Decals.zig
index ecbc71c..b81b030 100644
--- a/src/Decals.zig
+++ b/src/Decals.zig
@@ -1,7 +1,7 @@
// Decal construction and drawing
// Copyright (C) 2002 David Rosen
// Copyright (C) 2003 Steven Fuller
-// Copyright (C) 2023 Nguyễn Gia Phong
+// Copyright (C) 2023, 2025 Nguyễn Gia Phong
//
// This file is part of Black Shades.
//
@@ -83,7 +83,7 @@ export fn addDecal(d: *Decals, kind: Kind, location: XYZ,
size: f32, normal: XYZ, poly: c_int,
m: *const Model, move: XYZ, rot: f32) void {
const n: @Vector(3, f32) = @bitCast(normal);
- const abs_n = @fabs(n);
+ const abs_n = @abs(n);
var major: u2 = 0;
if (abs_n[1] > abs_n[major])
major = 1;
diff --git a/src/Skeleton.cpp b/src/Skeleton.cpp
index 8692213..b7f1684 100644
--- a/src/Skeleton.cpp
+++ b/src/Skeleton.cpp
@@ -450,7 +450,7 @@ void Skeleton::reload()
lowforwardjoints[2] = lefthip;
num_muscles = 29;
- MuscleData muscles_data[num_muscles];
+ MuscleData muscles_data[29];
loadMuscles(muscles_data);
for (int i = 0; i < num_muscles; ++i) {
muscles[i].length = muscles_data[i].length;
diff --git a/src/config.zig b/src/config.zig
index 0d18223..723e95c 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -1,5 +1,5 @@
// Configuration parser
-// Copyright (C) 2021-2022 Nguyễn Gia Phong
+// Copyright (C) 2021-2022, 2025 Nguyễn Gia Phong
//
// This file is part of Black Shades.
//
@@ -23,6 +23,7 @@ const allocator = std.heap.c_allocator;
const cwd = std.fs.cwd;
const endian = @import("builtin").target.cpu.arch.endian();
const eql = std.mem.eql;
+const free = std.c.free;
const join = std.fs.path.join;
const maxInt = std.math.maxInt;
const mkdir = std.os.mkdir;
@@ -30,7 +31,7 @@ const parseFloat = std.fmt.parseFloat;
const parseInt = std.fmt.parseInt;
const std = @import("std");
const stringToEnum = std.meta.stringToEnum;
-const tokenize = std.mem.tokenize;
+const tokenizeScalar = std.mem.tokenizeScalar;
const Key = @import("gfz").Key;
const ini = @import("ini");
@@ -69,7 +70,7 @@ fn parseLevels(dir_path: []const u8, length: usize) ![*]Level {
defer input.close();
const levels = try allocator.alloc(Level, length);
errdefer allocator.free(levels);
- var parser = ini.parse(allocator, input.reader());
+ var parser = ini.parse(allocator, input.reader(), "#;");
defer parser.deinit();
var i: usize = maxInt(usize);
@@ -92,7 +93,7 @@ fn parseLevels(dir_path: []const u8, length: usize) ![*]Level {
else return error.InvalidData;
} else if (eql(u8, kv.key, "evil weapons")) {
var weapons = IntegerBitSet(8).initEmpty();
- var enums = tokenize(u8, kv.value, " ");
+ var enums = tokenizeScalar(u8, kv.value, ' ');
while (enums.next()) |weapon|
weapons.set(try parseInt(u3, weapon, 10));
levels[i].evil_weapons = weapons.mask;
@@ -145,6 +146,10 @@ pub const Config = extern struct {
levels: extern struct { ptr: [*]Level = undefined, len: usize = 0 } = .{},
debug: bool = false,
+
+ pub fn deinit(self: Config) void {
+ defer free(self.levels.ptr);
+ }
};
/// Parse config.ini in the given base directory.
@@ -155,7 +160,7 @@ pub fn parse(base_dir: []const u8) !Config {
defer dir.close();
const input = try openData(dir, "config.ini");
defer input.close();
- var parser = ini.parse(allocator, input.reader());
+ var parser = ini.parse(allocator, input.reader(), "#;");
defer parser.deinit();
var config = Config{};
diff --git a/src/geom.zig b/src/geom.zig
index d86c682..4bb92e1 100644
--- a/src/geom.zig
+++ b/src/geom.zig
@@ -1,6 +1,6 @@
// Geometry functions
// Copyright (C) 2002 David Rosen
-// Copyright (C) 2023 Nguyễn Gia Phong
+// Copyright (C) 2023, 2025 Nguyễn Gia Phong
//
// This file is part of Black Shades.
//
@@ -81,9 +81,9 @@ pub fn rotate2d(i: *f32, j: *f32, a: f32) void {
export fn rotate(v: XYZ, deg_x: f32, deg_y: f32, deg_z: f32) XYZ {
var u = v;
// TODO: optimize
- rotate2d(&u.x, &u.y, degreesToRadians(f32, deg_z));
- rotate2d(&u.z, &u.x, degreesToRadians(f32, deg_y));
- rotate2d(&u.y, &u.z, degreesToRadians(f32, deg_x));
+ rotate2d(&u.x, &u.y, degreesToRadians(deg_z));
+ rotate2d(&u.z, &u.x, degreesToRadians(deg_y));
+ rotate2d(&u.y, &u.z, degreesToRadians(deg_x));
return u;
}
@@ -106,7 +106,7 @@ pub export fn segCrossTrigon(start: XYZ, end: XYZ,
const q: @Vector(3, f32) = @bitCast(end);
const n: @Vector(3, f32) = @bitCast(normal.*);
const denom = dot(q - p, n);
- if (@fabs(denom) < floatEps(f32))
+ if (@abs(denom) < floatEps(f32))
return false; // parallel segment and triangle
const a: @Vector(3, f32) = @bitCast(p_a.*);
@@ -116,7 +116,7 @@ pub export fn segCrossTrigon(start: XYZ, end: XYZ,
return false; // intersection not within segment
// Check if intersection is in the triangle
- const n_abs = @fabs(n);
+ const n_abs = @abs(n);
const n_max = @reduce(.Max, n_abs);
const k: struct { usize, usize } = if (n_max == n_abs[0])
.{ 1, 2 }
@@ -132,7 +132,7 @@ pub export fn segCrossTrigon(start: XYZ, end: XYZ,
const v = @Vector(3, f32){ i[k[1]], b[k[1]], c[k[1]] } - splat(3, a[k[1]]);
intersection.* = @bitCast(i);
- if (@fabs(u[1]) < floatEps(f32)) {
+ if (@abs(u[1]) < floatEps(f32)) {
const s = u[0] / u[2];
if (s >= 0 and s <= 1) {
const t = (v[0] - s * v[2]) / v[1];
diff --git a/src/main.zig b/src/main.zig
index 9accfc8..08c84ab 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -1,5 +1,5 @@
// Main function
-// Copyright (C) 2021-2023 Nguyễn Gia Phong
+// Copyright (C) 2021-2023, 2025 Nguyễn Gia Phong
//
// This file is part of Black Shades.
//
@@ -16,13 +16,12 @@
// You should have received a copy of the GNU General Public License
// along with Black Shades. If not, see <https://www.gnu.org/licenses/>.
-const DefaultPrng = std.rand.DefaultPrng;
+const DefaultPrng = std.Random.DefaultPrng;
const allocator = std.heap.c_allocator;
-const free = std.c.free;
const std = @import("std");
-const Loca = @import("loca").Loca;
const al = @import("zeal");
+const folders = @import("known-folders");
const gf = @import("gfz");
const gl = @import("zgl");
@@ -84,10 +83,10 @@ fn click(window: gf.Window, button: gf.MouseButton,
}
pub fn main() !void {
- const loca = try Loca.init(allocator, .{});
- defer loca.deinit();
- const config = try configuration.parse(loca.user_config);
- defer free(config.levels.ptr);
+ const user_config = (try folders.getPath(allocator, .local_configuration)).?;
+ defer allocator.free(user_config);
+ const config = try configuration.parse(user_config);
+ defer config.deinit();
try gf.init();
defer gf.deinit() catch unreachable;
@@ -100,10 +99,11 @@ pub fn main() !void {
defer textures.deinit();
var decals = Decals.init(allocator, &textures);
defer decals.deinit();
+ const user_data = (try folders.getPath(allocator, .data)).?;
+ defer allocator.free(user_data);
game = c.makeGame(&decals, @bitCast(config),
- @bitCast(try loadScores(loca.user_data))).?;
- defer saveScores(loca.user_data, @bitCast(c.getScores(game)))
- catch unreachable;
+ @bitCast(try loadScores(user_data))).?;
+ defer saveScores(user_data, @bitCast(c.getScores(game))) catch unreachable;
try window.setSizeCallback(resizeWindow);
try gf.swapInterval(@intFromBool(config.vsync));
diff --git a/src/misc.zig b/src/misc.zig
index 46237cb..3bed694 100644
--- a/src/misc.zig
+++ b/src/misc.zig
@@ -1,6 +1,6 @@
// Miscellaneous functions
// Copyright (C) 2002 David Rosen
-// Copyright (C) 2021-2023 Nguyễn Gia Phong
+// Copyright (C) 2021-2023, 2025 Nguyễn Gia Phong
//
// This file is part of Black Shades.
//
@@ -193,7 +193,7 @@ pub fn loadScores(base_dir: []const u8) !Scores {
const path = "blackshades" ++ [_]u8{ sep } ++ "scores.ini";
const input = dir.openFile(path, .{}) catch return scores;
defer input.close();
- var parser = ini.parse(allocator, input.reader());
+ var parser = ini.parse(allocator, input.reader(), "#;");
defer parser.deinit();
while (try parser.next()) |record|
@@ -241,7 +241,7 @@ pub fn saveScores(base_dir: []const u8, current: Scores) !void {
previous.completed or current.completed,
});
defer allocator.free(data);
- try dir.writeFile("scores.ini", data);
+ try dir.writeFile(.{ .sub_path = "scores.ini", .data = data });
}
const Text = struct {
diff --git a/src/model.zig b/src/model.zig
index 9773027..3acfe9d 100644
--- a/src/model.zig
+++ b/src/model.zig
@@ -1,6 +1,6 @@
// 3D model
// Copyright (C) 2002 David Rosen
-// Copyright (C) 2023 Nguyễn Gia Phong
+// Copyright (C) 2023, 2025 Nguyễn Gia Phong
//
// This file is part of Black Shades.
//
@@ -25,7 +25,7 @@ const c = @import("cimport.zig");
const crossProduct = geom.crossProduct;
const cwd = std.fs.cwd;
const data_dir = misc.data_dir;
-const degToRad = std.math.degreesToRadians;
+const degreesToRadians = std.math.degreesToRadians;
const endsWith = std.mem.endsWith;
const eql = std.mem.eql;
const floatMax = std.math.floatMax;
@@ -63,7 +63,9 @@ const OffIterator = struct {
token_iterator: TokenIterator,
pub fn init(buffer: []const u8) OffIterator {
- var self = .{ .token_iterator = tokenizeScalar(u8, buffer, '\n') };
+ var self = OffIterator{
+ .token_iterator = tokenizeScalar(u8, buffer, '\n'),
+ };
if (!endsWith(u8, self.token_iterator.next().?, "OFF"))
self.token_iterator.reset();
return self;
@@ -198,12 +200,12 @@ pub export fn segCrossModelTrans(start: XYZ, end: XYZ, m: *const Model,
intersection: *XYZ) c_int {
const t: @Vector(3, f32) = @bitCast(move);
var p = @as(@Vector(3, f32), @bitCast(start)) - t;
- rotate2d(&p[2], &p[0], degToRad(f32, -rot));
+ rotate2d(&p[2], &p[0], degreesToRadians(-rot));
var q = @as(@Vector(3, f32), @bitCast(end)) - t;
- rotate2d(&q[2], &q[0], degToRad(f32, -rot));
+ rotate2d(&q[2], &q[0], degreesToRadians(-rot));
defer {
- rotate2d(&intersection.z, &intersection.x, degToRad(f32, rot));
+ rotate2d(&intersection.z, &intersection.x, degreesToRadians(rot));
intersection.* = @bitCast(@as(@Vector(3, f32),
@bitCast(intersection.*)) + t);
}
|