diff --git a/.gitmodules b/.gitmodules index 1f9cdd2..1ecf591 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,4 +15,7 @@ url = https://github.com/aeronavery/zig-toml [submodule "lib/zgui"] path = lib/zgui - url = https://git.musuka.dev/paoda/zgui \ No newline at end of file + url = https://git.musuka.dev/paoda/zgui +[submodule "lib/nfd-zig"] + path = lib/nfd-zig + url = https://github.com/fabioarnold/nfd-zig diff --git a/build.zig b/build.zig index fb03833..eb7ba8e 100644 --- a/build.zig +++ b/build.zig @@ -3,6 +3,7 @@ const builtin = @import("builtin"); const Sdk = @import("lib/SDL.zig/Sdk.zig"); const zgui = @import("lib/zgui/build.zig"); +const nfd = @import("lib/nfd-zig/build.zig"); pub fn build(b: *std.build.Builder) void { // Minimum Zig Version @@ -43,6 +44,10 @@ pub fn build(b: *std.build.Builder) void { // OpenGL 3.3 Bindings exe.addPackagePath("gl", "lib/gl.zig"); + // NativeFileDialog(ue) Bindings + exe.linkLibrary(nfd.makeLib(b, mode, target)); + exe.addPackage(nfd.getPackage("nfd")); + // Zig SDL Bindings: https://github.com/MasterQ32/SDL.zig const sdk = Sdk.init(b, null); sdk.link(exe, .dynamic); @@ -51,8 +56,8 @@ pub fn build(b: *std.build.Builder) void { // Dear ImGui bindings const zgui_options = zgui.BuildOptionsStep.init(b, .{ .backend = .sdl2_opengl3 }); const zgui_pkg = zgui.getPkg(&.{zgui_options.getPkg()}); - exe.addPackage(zgui_pkg); zgui.link(exe, zgui_options); + exe.addPackage(zgui_pkg); exe.setBuildMode(mode); exe.install(); diff --git a/lib/nfd-zig b/lib/nfd-zig new file mode 160000 index 0000000..75acefd --- /dev/null +++ b/lib/nfd-zig @@ -0,0 +1 @@ +Subproject commit 75acefd571ede5361514b3a8ae9c8b36c6908d36 diff --git a/src/platform.zig b/src/platform.zig index f86fde0..1fd5d7b 100644 --- a/src/platform.zig +++ b/src/platform.zig @@ -2,6 +2,7 @@ const std = @import("std"); const SDL = @import("sdl2"); const gl = @import("gl"); const zgui = @import("zgui"); +const nfd = @import("nfd"); const emu = @import("core/emu.zig"); const config = @import("config.zig"); @@ -34,6 +35,7 @@ pub const Gui = struct { const State = struct { fps_hist: RingBuffer(u32), + should_quit: bool = false, pub fn init(allocator: Allocator) !@This() { const history = try allocator.alloc(u32, 0x400); @@ -261,6 +263,36 @@ pub const Gui = struct { fn draw(self: *Self, tex_id: GLuint, cpu: *const Arm7tdmi) void { const win_scale = config.config().host.win_scale; + { + _ = zgui.beginMainMenuBar(); + defer zgui.endMainMenuBar(); + + if (zgui.beginMenu("File", true)) { + defer zgui.endMenu(); + + if (zgui.menuItem("Quit", .{})) self.state.should_quit = true; + if (zgui.menuItem("Insert ROM", .{})) blk: { + const maybe_path = nfd.openFileDialog("gba", null) catch |e| { + log.err("failed to open file dialog: {?}", .{e}); + break :blk; + }; + + if (maybe_path) |file_path| { + defer nfd.freePath(file_path); + log.info("user chose: \"{s}\"", .{file_path}); + + // emu.loadRom(cpu, file_path); + } + } + } + + if (zgui.beginMenu("Emulation", true)) { + defer zgui.endMenu(); + + if (zgui.menuItem("Restart", .{})) log.warn("TODO: Restart Emulator", .{}); + } + } + { const w = @intToFloat(f32, gba_width * win_scale); const h = @intToFloat(f32, gba_height * win_scale); @@ -410,6 +442,9 @@ pub const Gui = struct { emu_loop: while (true) { var event: SDL.SDL_Event = undefined; + // Quit Signal from Dear Imgui + if (self.state.should_quit) break :emu_loop; + while (SDL.SDL_PollEvent(&event) != 0) { _ = zgui.backend.processEvent(&event);