aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Decals.zig4
-rw-r--r--src/Skeleton.cpp2
-rw-r--r--src/config.zig15
-rw-r--r--src/geom.zig14
-rw-r--r--src/main.zig22
-rw-r--r--src/misc.zig6
-rw-r--r--src/model.zig14
7 files changed, 42 insertions, 35 deletions
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);
}