From 51115cba86e4b77fca7e3b7fc3d7e726979fb5ae Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Sun, 25 Sep 2022 10:44:51 -0300 Subject: [PATCH] feat: read config.toml on program start We just read it, don't actually parse any of the TOML. Well, the library does, we just don't do anything /w it --- .gitmodules | 3 ++ build.zig | 3 ++ lib/zig-toml | 1 + src/main.zig | 95 ++++++++++++++++++++++++++++++++++------------------ 4 files changed, 70 insertions(+), 32 deletions(-) create mode 160000 lib/zig-toml diff --git a/.gitmodules b/.gitmodules index 2c14e46..78bd5b0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "lib/zig-datetime"] path = lib/zig-datetime url = https://github.com/frmdstryr/zig-datetime +[submodule "lib/zig-toml"] + path = lib/zig-toml + url = https://github.com/aeronavery/zig-toml diff --git a/build.zig b/build.zig index 2ecc83c..97a189d 100644 --- a/build.zig +++ b/build.zig @@ -28,6 +28,9 @@ pub fn build(b: *std.build.Builder) void { // Argument Parsing Library exe.addPackagePath("clap", "lib/zig-clap/clap.zig"); + // TOML Library + exe.addPackagePath("toml", "lib/zig-toml/src/toml.zig"); + // Zig SDL Bindings: https://github.com/MasterQ32/SDL.zig const sdk = Sdk.init(b); sdk.link(exe, .dynamic); diff --git a/lib/zig-toml b/lib/zig-toml new file mode 160000 index 0000000..5dfa919 --- /dev/null +++ b/lib/zig-toml @@ -0,0 +1 @@ +Subproject commit 5dfa919e03b446c66b295c04bef9bdecabd4276f diff --git a/src/main.zig b/src/main.zig index fd6cfeb..b7fddc3 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,8 +1,8 @@ const std = @import("std"); const builtin = @import("builtin"); - const known_folders = @import("known_folders"); const clap = @import("clap"); +const toml = @import("toml"); const Gui = @import("platform.zig").Gui; const Bus = @import("core/Bus.zig"); @@ -33,11 +33,27 @@ pub fn main() anyerror!void { defer std.debug.assert(!gpa.deinit()); const allocator = gpa.allocator(); + // TODO: Make Error message not Linux Specific + const data_path = try known_folders.getPath(allocator, .data) orelse exit("Unable to Determine XDG Data Path", .{}); + defer allocator.free(data_path); + + const config_path = try configFilePath(allocator, data_path); + defer allocator.free(config_path); + + const save_path = try savePath(allocator, data_path); + defer allocator.free(save_path); + + // Read Config File + log.info("Config File: {s}", .{config_path}); + const table = try toml.parseFile(allocator, config_path, null); + defer table.deinit(); + log.info("{?}", .{table}); + // Handle CLI Input const result = try clap.parse(clap.Help, ¶ms, clap.parsers.default, .{}); defer result.deinit(); - const paths = try handleArguments(allocator, &result); + const paths = try handleArguments(allocator, data_path, &result); defer if (paths.save) |path| allocator.free(path); const log_file: ?std.fs.File = if (cpu_logging) try std.fs.cwd().createFile("zba.log", .{}) else null; @@ -60,39 +76,15 @@ pub fn main() anyerror!void { try gui.run(&cpu, &scheduler); } -fn getSavePath(allocator: Allocator) !?[]const u8 { - const save_subpath = "zba" ++ [_]u8{std.fs.path.sep} ++ "save"; - - const maybe_data_path = try known_folders.getPath(allocator, .data); - defer if (maybe_data_path) |path| allocator.free(path); - - const save_path = if (maybe_data_path) |base| try std.fs.path.join(allocator, &[_][]const u8{ base, "zba", "save" }) else null; - - if (save_path) |_| { - // If we've determined what our save path should be, ensure the prereq directories - // are present so that we can successfully write to the path when necessary - const maybe_data_dir = try known_folders.open(allocator, .data, .{}); - if (maybe_data_dir) |data_dir| try data_dir.makePath(save_subpath); - } - - return save_path; -} - -fn getRomPath(result: *const clap.Result(clap.Help, ¶ms, clap.parsers.default)) ![]const u8 { - return switch (result.positionals.len) { - 1 => result.positionals[0], - 0 => std.debug.panic("ZBA requires a positional path to a GamePak ROM.\n", .{}), - else => std.debug.panic("ZBA received too many arguments.\n", .{}), - }; -} - -pub fn handleArguments(allocator: Allocator, result: *const clap.Result(clap.Help, ¶ms, clap.parsers.default)) !FilePaths { - const rom_path = try getRomPath(result); +pub fn handleArguments(allocator: Allocator, data_path: []const u8, result: *const clap.Result(clap.Help, ¶ms, clap.parsers.default)) !FilePaths { + const rom_path = romPath(result); log.info("ROM path: {s}", .{rom_path}); + const bios_path = result.args.bios; if (bios_path) |path| log.info("BIOS path: {s}", .{path}) else log.info("No BIOS provided", .{}); - const save_path = try getSavePath(allocator); - if (save_path) |path| log.info("Save path: {s}", .{path}); + + const save_path = try savePath(allocator, data_path); + log.info("Save path: {s}", .{save_path}); return FilePaths{ .rom = rom_path, @@ -100,3 +92,42 @@ pub fn handleArguments(allocator: Allocator, result: *const clap.Result(clap.Hel .save = save_path, }; } + +fn configFilePath(allocator: Allocator, data_path: []const u8) ![]const u8 { + const path = try std.fs.path.join(allocator, &[_][]const u8{ data_path, "zba", "config.toml" }); + + // We try to create the file exclusively, meaning that we err out if the file already exists. + // All we care about is a file being there so we can just ignore that error in particular and + // continue down the happy pathj + std.fs.accessAbsolute(path, .{}) catch { + const file_handle = try std.fs.createFileAbsolute(path, .{}); + file_handle.close(); + }; + + return path; +} + +fn savePath(allocator: Allocator, data_path: []const u8) ![]const u8 { + var dir = try std.fs.openDirAbsolute(data_path, .{}); + defer dir.close(); + + // Will either make the path recursively, or just exit early since it already exists + try dir.makePath("zba" ++ [_]u8{std.fs.path.sep} ++ "save"); + + // FIXME: Do we have to allocate? :sad: + return try std.fs.path.join(allocator, &[_][]const u8{ data_path, "zba", "save" }); +} + +fn romPath(result: *const clap.Result(clap.Help, ¶ms, clap.parsers.default)) []const u8 { + return switch (result.positionals.len) { + 1 => result.positionals[0], + 0 => exit("ZBA requires a path to a GamePak ROM\n", .{}), + else => exit("ZBA received too many positional arguments. \n", .{}), + }; +} + +fn exit(comptime format: []const u8, args: anytype) noreturn { + const stderr = std.io.getStdErr().writer(); + stderr.print(format, args) catch {}; // Just exit already... + std.os.exit(1); +}