zba/src/main.zig

141 lines
5.3 KiB
Zig
Raw Normal View History

2021-12-29 21:09:00 +00:00
const std = @import("std");
const builtin = @import("builtin");
2022-07-22 23:19:31 +00:00
const known_folders = @import("known_folders");
const clap = @import("clap");
const config = @import("config.zig");
2022-01-09 00:30:57 +00:00
2022-09-18 08:54:44 +00:00
const Gui = @import("platform.zig").Gui;
2022-07-27 16:44:24 +00:00
const Bus = @import("core/Bus.zig");
2022-07-22 23:19:31 +00:00
const Arm7tdmi = @import("core/cpu.zig").Arm7tdmi;
const Scheduler = @import("core/scheduler.zig").Scheduler;
2022-09-19 19:07:19 +00:00
const FilePaths = @import("util.zig").FilePaths;
2022-07-22 23:19:31 +00:00
const Allocator = std.mem.Allocator;
2022-09-18 08:54:44 +00:00
const log = std.log.scoped(.Cli);
2022-07-22 23:19:31 +00:00
const width = @import("core/ppu.zig").width;
const height = @import("core/ppu.zig").height;
pub const log_level = if (builtin.mode != .Debug) .info else std.log.default_level;
2022-05-23 15:38:44 +00:00
// CLI Arguments + Help Text
const params = clap.parseParamsComptime(
\\-h, --help Display this help and exit.
2022-10-17 20:25:04 +00:00
\\-s, --skip Skip BIOS.
2022-05-23 15:38:44 +00:00
\\-b, --bios <str> Optional path to a GBA BIOS ROM.
2022-10-17 20:25:04 +00:00
\\<str> Path to the GBA GamePak ROM.
2022-05-23 15:38:44 +00:00
\\
);
2021-12-29 21:09:00 +00:00
pub fn main() anyerror!void {
2022-07-22 23:19:31 +00:00
// Main Allocator for ZBA
2021-12-29 21:09:00 +00:00
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
2022-01-04 02:08:55 +00:00
defer std.debug.assert(!gpa.deinit());
2022-07-22 23:19:31 +00:00
const allocator = gpa.allocator();
2021-12-29 21:09:00 +00:00
// Determine the Data Directory (stores saves, config file, etc.)
const data_path = blk: {
const result = known_folders.getPath(allocator, .data);
const option = result catch |e| exitln("interrupted while attempting to find a data directory: {}", .{e});
break :blk option orelse exitln("no valid data directory could be found", .{});
};
defer allocator.free(data_path);
// Parse CLI
const result = clap.parse(clap.Help, &params, clap.parsers.default, .{}) catch |e| exitln("failed to parse cli: {}", .{e});
defer result.deinit();
// TODO: Move config file to XDG Config directory?
const config_path = configFilePath(allocator, data_path) catch |e| exitln("failed to determine the config file path for ZBA: {}", .{e});
defer allocator.free(config_path);
config.load(allocator, config_path) catch |e| exitln("failed to read config file: {}", .{e});
2022-01-02 05:37:21 +00:00
const paths = handleArguments(allocator, data_path, &result) catch |e| exitln("failed to handle cli arguments: {}", .{e});
2022-07-22 23:19:31 +00:00
defer if (paths.save) |path| allocator.free(path);
2022-02-04 05:55:14 +00:00
const log_file = if (config.config().debug.cpu_trace) blk: {
break :blk std.fs.cwd().createFile("zba.log", .{}) catch |e| exitln("failed to create trace log file: {}", .{e});
} else null;
2022-08-29 05:32:41 +00:00
defer if (log_file) |file| file.close();
2022-07-22 23:19:31 +00:00
// TODO: Take Emulator Init Code out of main.zig
var scheduler = Scheduler.init(allocator);
2022-01-04 02:08:55 +00:00
defer scheduler.deinit();
2022-08-29 05:32:41 +00:00
var bus: Bus = undefined;
var cpu = Arm7tdmi.init(&scheduler, &bus, log_file);
2022-01-28 20:33:38 +00:00
bus.init(allocator, &scheduler, &cpu, paths) catch |e| exitln("failed to init zba bus: {}", .{e});
2022-08-29 05:32:41 +00:00
defer bus.deinit();
2022-10-17 20:31:07 +00:00
if (config.config().guest.skip_bios or result.args.skip or paths.bios == null) {
2022-10-17 20:25:04 +00:00
cpu.fastBoot();
}
2022-09-18 08:54:44 +00:00
var gui = Gui.init(&bus.pak.title, &bus.apu, width, height);
2022-07-22 23:19:31 +00:00
defer gui.deinit();
2022-01-28 20:33:38 +00:00
gui.run(&cpu, &scheduler) catch |e| exitln("failed to run gui thread: {}", .{e});
}
pub fn handleArguments(allocator: Allocator, data_path: []const u8, result: *const clap.Result(clap.Help, &params, 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.warn("No BIOS provided", .{});
const save_path = try savePath(allocator, data_path);
log.info("Save path: {s}", .{save_path});
return .{
.rom = rom_path,
.bios = bios_path,
.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" });
errdefer allocator.free(path);
// 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, .{});
defer file_handle.close();
// TODO: Write Default valeus to config file
};
return path;
}
2022-05-23 15:38:44 +00:00
fn savePath(allocator: Allocator, data_path: []const u8) ![]const u8 {
var dir = try std.fs.openDirAbsolute(data_path, .{});
defer dir.close();
2022-05-23 15:38:44 +00:00
// Will either make the path recursively, or just exit early since it already exists
try dir.makePath("zba" ++ [_]u8{std.fs.path.sep} ++ "save");
2022-05-23 15:38:44 +00:00
// FIXME: Do we have to allocate? :sad:
return try std.fs.path.join(allocator, &[_][]const u8{ data_path, "zba", "save" });
2022-05-23 15:38:44 +00:00
}
fn romPath(result: *const clap.Result(clap.Help, &params, clap.parsers.default)) []const u8 {
2022-07-22 23:19:31 +00:00
return switch (result.positionals.len) {
1 => result.positionals[0],
0 => exitln("ZBA requires a path to a GamePak ROM", .{}),
else => exitln("ZBA received too many positional arguments.", .{}),
2022-07-22 23:19:31 +00:00
};
}
fn exitln(comptime format: []const u8, args: anytype) noreturn {
const stderr = std.io.getStdErr().writer();
stderr.print(format, args) catch {}; // Just exit already...
stderr.writeByte('\n') catch {};
std.os.exit(1);
2022-05-23 15:38:44 +00:00
}