summary refs log tree commit diff
path: root/src/config.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/config.zig')
-rw-r--r--src/config.zig101
1 files changed, 49 insertions, 52 deletions
diff --git a/src/config.zig b/src/config.zig
index f382d77..380a866 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -18,6 +18,7 @@
 
 const Allocator = std.mem.Allocator;
 const createFile = std.fs.createFileAbsolute;
+const cwd = std.fs.cwd;
 const eql = std.mem.eql;
 const ini = @import("ini");
 const join = std.fs.path.join;
@@ -29,17 +30,19 @@ const std = @import("std");
 
 /// Game configuration.
 pub const Config = extern struct {
-    width: c_int = 640,
-    height: c_int = 480,
-    mouse_sensitivity: f32 = 0.7,
-    debug: bool = false,
+    width: c_int = 800,
+    height: c_int = 600,
     vsync: bool = true,
-    blood: bool = true,
     blur: bool = false,
+    blood: bool = true,
+
+    music: bool = true,
+
+    mouse_sensitivity: f32 = 0.7,
+
     menu: bool = true,
     custom_levels: bool = false,
-    music: bool = true,
-    azerty: bool = false,
+    debug: bool = false,
 };
 
 /// Parse boolean values.
@@ -51,34 +54,16 @@ fn parseBool(s: []const u8) !bool {
     return error.InvalidCharacter;
 }
 
-/// Parse settings.ini in the given base directory.
+/// Parse config.ini in the given base directory.
 pub fn parse(allocator: *Allocator, base_dir: []const u8) !Config {
     const config_dir = try join(allocator, &.{ base_dir, "blackshades" });
     defer allocator.free(config_dir);
-    const path = try join(allocator, &.{ config_dir, "settings.ini" });
-    defer allocator.free(path);
+    var dir = try cwd().makeOpenPath(config_dir, .{});
+    defer dir.close();
 
     var config = Config{};
-    const input = openFile(path, .{}) catch {
-        mkdir(config_dir, 0o644) catch |err| switch (err) {
-            error.PathAlreadyExists => {},
-            else => return err,
-        };
-        const output = try createFile(path, .{});
-        defer output.close();
-        const writer = output.writer();
-        try writer.print("screen width = {}\n", .{ config.width });
-        try writer.print("screen height = {}\n", .{ config.height });
-        try writer.print("mouse sensitivity = {d:.1}\n",
-                         .{ config.mouse_sensitivity });
-        try writer.print("debug = {}\n", .{ config.debug });
-        try writer.print("vsync = {}\n", .{ config.vsync });
-        try writer.print("blood = {}\n", .{ config.blood });
-        try writer.print("blur = {}\n", .{ config.blur });
-        try writer.print("menu = {}\n", .{ config.menu });
-        try writer.print("custom levels = {}\n", .{ config.custom_levels });
-        try writer.print("music = {}\n", .{ config.music });
-        try writer.print("azerty = {}\n", .{ config.azerty });
+    const input = dir.openFile("config.ini", .{}) catch {
+        try dir.writeFile("config.ini", @embedFile("config.ini"));
         return config;
     };
     defer input.close();
@@ -86,31 +71,43 @@ pub fn parse(allocator: *Allocator, base_dir: []const u8) !Config {
     var parser = ini.parse(allocator, input.reader());
     defer parser.deinit();
 
+    var section: []u8 = "";
+    defer allocator.free(section);
     while (try parser.next()) |record|
         switch (record) {
-            .property => |kv| if (eql(u8, kv.key, "screen width")) {
-                config.width = try parseInt(c_int, kv.value, 10);
-            } else if (eql(u8, kv.key, "screen height")) {
-                config.height = try parseInt(c_int, kv.value, 10);
-            } else if (eql(u8, kv.key, "mouse_sensitivity")) {
-                config.mouse_sensitivity = try parseFloat(f32, kv.value);
-            } else if (eql(u8, kv.key, "debug")) {
-                config.debug = try parseBool(kv.value);
-            } else if (eql(u8, kv.key, "vsync")) {
-                config.vsync = try parseBool(kv.value);
-            } else if (eql(u8, kv.key, "blood")) {
-                config.blood = try parseBool(kv.value);
-            } else if (eql(u8, kv.key, "blur")) {
-                config.blur = try parseBool(kv.value);
-            } else if (eql(u8, kv.key, "menu")) {
-                config.menu = try parseBool(kv.value);
-            } else if (eql(u8, kv.key, "custom levels")) {
-                config.custom_levels = try parseBool(kv.value);
-            } else if (eql(u8, kv.key, "music")) {
-                config.music = try parseBool(kv.value);
-            } else if (eql(u8, kv.key, "azerty")) {
-                config.azerty = try parseBool(kv.value);
+            .section => |heading| {
+                allocator.free(section);
+                section = try allocator.dupe(u8, heading);
             },
+            .property => |kv| if (eql(u8, section, "graphics")) {
+                if (eql(u8, kv.key, "width"))
+                    config.width = try parseInt(c_int, kv.value, 10)
+                else if (eql(u8, kv.key, "height"))
+                    config.height = try parseInt(c_int, kv.value, 10)
+                else if (eql(u8, kv.key, "vsync"))
+                    config.vsync = try parseBool(kv.value)
+                else if (eql(u8, kv.key, "blur"))
+                    config.blur = try parseBool(kv.value)
+                else if (eql(u8, kv.key, "blood"))
+                    config.blood = try parseBool(kv.value)
+                else unreachable;
+            } else if (eql(u8, section, "audio")) {
+                if (eql(u8, kv.key, "music"))
+                    config.music = try parseBool(kv.value)
+                else unreachable;
+            } else if (eql(u8, section, "input")) {
+                if (eql(u8, kv.key, "mouse sensitivity"))
+                    config.mouse_sensitivity = try parseFloat(f32, kv.value)
+                else unreachable;
+            } else if (eql(u8, section, "misc")) {
+                if (eql(u8, kv.key, "menu"))
+                    config.menu = try parseBool(kv.value)
+                else if (eql(u8, kv.key, "custom levels"))
+                    config.custom_levels = try parseBool(kv.value)
+                else if (eql(u8, kv.key, "debug"))
+                    config.debug = try parseBool(kv.value)
+                else unreachable;
+            } else unreachable,
             else => unreachable,
         };
     return config;