zba/src/main.zig

103 lines
3.7 KiB
Zig
Raw Normal View History

2021-12-29 21:09:00 +00:00
const std = @import("std");
const builtin = @import("builtin");
2021-12-29 21:09:00 +00:00
2022-10-21 08:12:54 +00:00
const known_folders = @import("known_folders");
const clap = @import("clap");
2022-10-21 08:11:51 +00:00
2022-10-21 08:13:01 +00:00
const Gui = @import("platform.zig").Gui;
2022-10-21 08:12:55 +00:00
const Bus = @import("core/Bus.zig");
2022-10-21 08:12:54 +00:00
const Arm7tdmi = @import("core/cpu.zig").Arm7tdmi;
const Scheduler = @import("core/scheduler.zig").Scheduler;
2022-10-21 08:13:02 +00:00
const FilePaths = @import("util.zig").FilePaths;
2022-10-21 08:12:54 +00:00
const Allocator = std.mem.Allocator;
2022-10-21 08:13:01 +00:00
const log = std.log.scoped(.Cli);
2022-10-21 08:12:54 +00:00
const width = @import("core/ppu.zig").width;
const height = @import("core/ppu.zig").height;
const cpu_logging = @import("core/emu.zig").cpu_logging;
pub const log_level = if (builtin.mode != .Debug) .info else std.log.default_level;
2022-10-21 08:12:54 +00:00
// TODO: Reimpl Logging
2022-10-21 08:12:03 +00:00
2022-10-21 08:12:44 +00:00
// CLI Arguments + Help Text
const params = clap.parseParamsComptime(
\\-h, --help Display this help and exit.
\\-b, --bios <str> Optional path to a GBA BIOS ROM.
\\<str> Path to the GBA GamePak ROM
\\
);
2021-12-29 21:09:00 +00:00
pub fn main() anyerror!void {
2022-10-21 08:12:54 +00:00
// Main Allocator for ZBA
2021-12-29 21:09:00 +00:00
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
2022-10-21 08:11:47 +00:00
defer std.debug.assert(!gpa.deinit());
2022-10-21 08:12:54 +00:00
const allocator = gpa.allocator();
2021-12-29 21:09:00 +00:00
2022-10-21 08:12:54 +00:00
// Handle CLI Input
const result = try clap.parse(clap.Help, &params, clap.parsers.default, .{});
defer result.deinit();
2022-10-21 08:11:45 +00:00
2022-10-21 08:12:54 +00:00
const paths = try handleArguments(allocator, &result);
defer if (paths.save) |path| allocator.free(path);
2022-10-21 08:12:13 +00:00
const log_file: ?std.fs.File = if (cpu_logging) try std.fs.cwd().createFile("zba.log", .{}) else null;
2022-10-21 08:12:56 +00:00
defer if (log_file) |file| file.close();
2022-10-21 08:12:54 +00:00
// TODO: Take Emulator Init Code out of main.zig
var scheduler = Scheduler.init(allocator);
2022-10-21 08:11:47 +00:00
defer scheduler.deinit();
2022-10-21 08:12:56 +00:00
var bus: Bus = undefined;
var cpu = Arm7tdmi.init(&scheduler, &bus, log_file);
if (paths.bios == null) cpu.fastBoot();
2022-10-21 08:12:03 +00:00
try bus.init(allocator, &scheduler, &cpu, paths);
2022-10-21 08:12:56 +00:00
defer bus.deinit();
2022-10-21 08:13:01 +00:00
var gui = Gui.init(&bus.pak.title, &bus.apu, width, height);
2022-10-21 08:12:54 +00:00
defer gui.deinit();
2022-10-21 08:12:03 +00:00
try gui.run(&cpu, &scheduler);
}
2022-10-21 08:12:54 +00:00
fn getSavePath(allocator: Allocator) !?[]const u8 {
2022-10-21 08:12:44 +00:00
const save_subpath = "zba" ++ [_]u8{std.fs.path.sep} ++ "save";
2022-10-21 08:12:54 +00:00
const maybe_data_path = try known_folders.getPath(allocator, .data);
defer if (maybe_data_path) |path| allocator.free(path);
2022-10-21 08:12:44 +00:00
2022-10-21 08:12:54 +00:00
const save_path = if (maybe_data_path) |base| try std.fs.path.join(allocator, &[_][]const u8{ base, "zba", "save" }) else null;
2022-10-21 08:12:44 +00:00
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
2022-10-21 08:12:54 +00:00
const maybe_data_dir = try known_folders.open(allocator, .data, .{});
2022-10-21 08:12:44 +00:00
if (maybe_data_dir) |data_dir| try data_dir.makePath(save_subpath);
}
return save_path;
}
2022-10-21 08:12:54 +00:00
fn getRomPath(result: *const clap.Result(clap.Help, &params, 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, &params, clap.parsers.default)) !FilePaths {
const rom_path = try getRomPath(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});
return FilePaths{
.rom = rom_path,
.bios = bios_path,
.save = save_path,
2022-10-21 08:12:44 +00:00
};
}