Add a GUI to ZBA #7
|
@ -19,3 +19,6 @@
|
||||||
[submodule "lib/zgui"]
|
[submodule "lib/zgui"]
|
||||||
path = lib/zgui
|
path = lib/zgui
|
||||||
url = https://git.musuka.dev/paoda/zgui
|
url = https://git.musuka.dev/paoda/zgui
|
||||||
|
[submodule "lib/nfd-zig"]
|
||||||
|
path = lib/nfd-zig
|
||||||
|
url = https://github.com/fabioarnold/nfd-zig
|
||||||
|
|
|
@ -4,6 +4,7 @@ const builtin = @import("builtin");
|
||||||
const Sdk = @import("lib/SDL.zig/Sdk.zig");
|
const Sdk = @import("lib/SDL.zig/Sdk.zig");
|
||||||
const gdbstub = @import("lib/zba-gdbstub/build.zig");
|
const gdbstub = @import("lib/zba-gdbstub/build.zig");
|
||||||
const zgui = @import("lib/zgui/build.zig");
|
const zgui = @import("lib/zgui/build.zig");
|
||||||
|
const nfd = @import("lib/nfd-zig/build.zig");
|
||||||
|
|
||||||
pub fn build(b: *std.build.Builder) void {
|
pub fn build(b: *std.build.Builder) void {
|
||||||
// Minimum Zig Version
|
// Minimum Zig Version
|
||||||
|
@ -45,6 +46,9 @@ pub fn build(b: *std.build.Builder) void {
|
||||||
|
|
||||||
// gdbstub
|
// gdbstub
|
||||||
gdbstub.link(exe);
|
gdbstub.link(exe);
|
||||||
|
// NativeFileDialog(ue) Bindings
|
||||||
|
exe.linkLibrary(nfd.makeLib(b, mode, target));
|
||||||
|
exe.addPackage(nfd.getPackage("nfd"));
|
||||||
|
|
||||||
// Zig SDL Bindings: https://github.com/MasterQ32/SDL.zig
|
// Zig SDL Bindings: https://github.com/MasterQ32/SDL.zig
|
||||||
const sdk = Sdk.init(b, null);
|
const sdk = Sdk.init(b, null);
|
||||||
|
@ -54,8 +58,8 @@ pub fn build(b: *std.build.Builder) void {
|
||||||
// Dear ImGui bindings
|
// Dear ImGui bindings
|
||||||
const zgui_options = zgui.BuildOptionsStep.init(b, .{ .backend = .sdl2_opengl3 });
|
const zgui_options = zgui.BuildOptionsStep.init(b, .{ .backend = .sdl2_opengl3 });
|
||||||
const zgui_pkg = zgui.getPkg(&.{zgui_options.getPkg()});
|
const zgui_pkg = zgui.getPkg(&.{zgui_options.getPkg()});
|
||||||
exe.addPackage(zgui_pkg);
|
|
||||||
zgui.link(exe, zgui_options);
|
zgui.link(exe, zgui_options);
|
||||||
|
exe.addPackage(zgui_pkg);
|
||||||
|
|
||||||
exe.setBuildMode(mode);
|
exe.setBuildMode(mode);
|
||||||
exe.install();
|
exe.install();
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 75acefd571ede5361514b3a8ae9c8b36c6908d36
|
|
@ -2,6 +2,7 @@ const std = @import("std");
|
||||||
const SDL = @import("sdl2");
|
const SDL = @import("sdl2");
|
||||||
const gl = @import("gl");
|
const gl = @import("gl");
|
||||||
const zgui = @import("zgui");
|
const zgui = @import("zgui");
|
||||||
|
const nfd = @import("nfd");
|
||||||
|
|
||||||
const emu = @import("core/emu.zig");
|
const emu = @import("core/emu.zig");
|
||||||
const config = @import("config.zig");
|
const config = @import("config.zig");
|
||||||
|
@ -34,6 +35,7 @@ pub const Gui = struct {
|
||||||
|
|
||||||
const State = struct {
|
const State = struct {
|
||||||
fps_hist: RingBuffer(u32),
|
fps_hist: RingBuffer(u32),
|
||||||
|
should_quit: bool = false,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator) !@This() {
|
pub fn init(allocator: Allocator) !@This() {
|
||||||
const history = try allocator.alloc(u32, 0x400);
|
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 {
|
fn draw(self: *Self, tex_id: GLuint, cpu: *const Arm7tdmi) void {
|
||||||
const win_scale = config.config().host.win_scale;
|
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 w = @intToFloat(f32, gba_width * win_scale);
|
||||||
const h = @intToFloat(f32, gba_height * win_scale);
|
const h = @intToFloat(f32, gba_height * win_scale);
|
||||||
|
@ -422,6 +454,8 @@ pub const Gui = struct {
|
||||||
// This might be true if the emu is running via a gdbstub server
|
// This might be true if the emu is running via a gdbstub server
|
||||||
// and the gdb stub exits first
|
// and the gdb stub exits first
|
||||||
if (quit.load(.Monotonic)) break :emu_loop;
|
if (quit.load(.Monotonic)) break :emu_loop;
|
||||||
|
// Quit Signal from Dear Imgui
|
||||||
|
if (self.state.should_quit) break :emu_loop;
|
||||||
|
|
||||||
while (SDL.SDL_PollEvent(&event) != 0) {
|
while (SDL.SDL_PollEvent(&event) != 0) {
|
||||||
_ = zgui.backend.processEvent(&event);
|
_ = zgui.backend.processEvent(&event);
|
||||||
|
|
Loading…
Reference in New Issue