From ccdc2cbad4f09f9469e089ef48a29e88e52cd1d6 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Tue, 23 May 2023 22:48:58 -0500 Subject: [PATCH] chore(ui): rewrite channel implementation --- lib/zba-util | 2 +- src/core/emu.zig | 28 +++++++++------------ src/main.zig | 14 +++++------ src/platform.zig | 64 +++++++++++++++++++++++------------------------- 4 files changed, 49 insertions(+), 59 deletions(-) diff --git a/lib/zba-util b/lib/zba-util index 7234945..77d11c9 160000 --- a/lib/zba-util +++ b/lib/zba-util @@ -1 +1 @@ -Subproject commit 72349459ec29ee2d910a3dd3274be00254a7acd4 +Subproject commit 77d11c9903d7f4a3a31ef59fc954421d7dfa0eb1 diff --git a/src/core/emu.zig b/src/core/emu.zig index 94fb39d..c67f492 100644 --- a/src/core/emu.zig +++ b/src/core/emu.zig @@ -5,7 +5,9 @@ const config = @import("../config.zig"); const Scheduler = @import("scheduler.zig").Scheduler; const Arm7tdmi = @import("cpu.zig").Arm7tdmi; const Tracker = @import("../util.zig").FpsTracker; -const TwoWayChannel = @import("zba-util").TwoWayChannel; +const Channel = @import("zba-util").Channel(Message, 0x100); + +pub const Message = enum { Pause, Resume, Quit }; const Timer = std.time.Timer; @@ -35,18 +37,18 @@ const RunKind = enum { LimitedFPS, }; -pub fn run(cpu: *Arm7tdmi, scheduler: *Scheduler, tracker: *Tracker, channel: *TwoWayChannel) void { +pub fn run(cpu: *Arm7tdmi, scheduler: *Scheduler, tracker: *Tracker, rx: Channel.Receiver) void { const audio_sync = config.config().guest.audio_sync and !config.config().host.mute; if (audio_sync) log.info("Audio sync enabled", .{}); if (config.config().guest.video_sync) { - inner(.LimitedFPS, audio_sync, cpu, scheduler, tracker, channel); + inner(.LimitedFPS, audio_sync, cpu, scheduler, tracker, rx); } else { - inner(.UnlimitedFPS, audio_sync, cpu, scheduler, tracker, channel); + inner(.UnlimitedFPS, audio_sync, cpu, scheduler, tracker, rx); } } -fn inner(comptime kind: RunKind, audio_sync: bool, cpu: *Arm7tdmi, scheduler: *Scheduler, tracker: ?*Tracker, channel: *TwoWayChannel) void { +fn inner(comptime kind: RunKind, audio_sync: bool, cpu: *Arm7tdmi, scheduler: *Scheduler, tracker: ?*Tracker, rx: Channel.Receiver) void { if (kind == .UnlimitedFPS or kind == .LimitedFPS) { std.debug.assert(tracker != null); log.info("FPS tracking enabled", .{}); @@ -59,13 +61,9 @@ fn inner(comptime kind: RunKind, audio_sync: bool, cpu: *Arm7tdmi, scheduler: *S log.info("Emulation w/out video sync", .{}); while (true) { - if (channel.emu.pop()) |e| switch (e) { + if (rx.recv()) |m| switch (m) { .Quit => break, - .Resume => paused = false, - .Pause => { - paused = true; - channel.gui.push(.Paused); - }, + .Resume, .Pause => paused = m == .Pause, }; if (paused) continue; @@ -82,13 +80,9 @@ fn inner(comptime kind: RunKind, audio_sync: bool, cpu: *Arm7tdmi, scheduler: *S var wake_time: u64 = frame_period; while (true) { - if (channel.emu.pop()) |e| switch (e) { + if (rx.recv()) |m| switch (m) { .Quit => break, - .Resume => paused = false, - .Pause => { - paused = true; - channel.gui.push(.Paused); - }, + .Resume, .Pause => paused = m == .Pause, }; if (paused) continue; diff --git a/src/main.zig b/src/main.zig index 5706257..09702c4 100644 --- a/src/main.zig +++ b/src/main.zig @@ -6,7 +6,7 @@ const clap = @import("clap"); const config = @import("config.zig"); const emu = @import("core/emu.zig"); -const TwoWayChannel = @import("zba-util").TwoWayChannel; +const Channel = @import("zba-util").Channel(emu.Message, 0x100); const Gui = @import("platform.zig").Gui; const Bus = @import("core/Bus.zig"); const Arm7tdmi = @import("core/cpu.zig").Arm7tdmi; @@ -98,8 +98,8 @@ pub fn main() void { var quit = std.atomic.Atomic(bool).init(false); - var items: [0x100]u8 = undefined; - var channel = TwoWayChannel.init(&items); + var ch = Channel.init(allocator) catch |e| exitln("failed to initialize ui -> emu thread message channel: {}", .{e}); + defer ch.deinit(allocator); if (result.args.gdb != 0) { const Server = @import("gdbstub").Server; @@ -122,22 +122,22 @@ pub fn main() void { gui.run(.Debug, .{ .cpu = &cpu, .scheduler = &scheduler, - .channel = &channel, + .ch = ch.tx, }) catch |e| exitln("main thread panicked: {}", .{e}); } else { var tracker = FpsTracker.init(); // emu should start paused if there's no ROM to run if (paths.rom == null) - channel.emu.push(.Pause); + ch.tx.send(.Pause); - const thread = std.Thread.spawn(.{}, emu.run, .{ &cpu, &scheduler, &tracker, &channel }) catch |e| exitln("emu thread panicked: {}", .{e}); + const thread = std.Thread.spawn(.{}, emu.run, .{ &cpu, &scheduler, &tracker, ch.rx }) catch |e| exitln("emu thread panicked: {}", .{e}); defer thread.join(); gui.run(.Standard, .{ .cpu = &cpu, .scheduler = &scheduler, - .channel = &channel, + .ch = ch.tx, .tracker = &tracker, }) catch |e| exitln("main thread panicked: {}", .{e}); } diff --git a/src/platform.zig b/src/platform.zig index 3f8d84d..792cb87 100644 --- a/src/platform.zig +++ b/src/platform.zig @@ -11,7 +11,7 @@ const Apu = @import("core/apu.zig").Apu; const Arm7tdmi = @import("core/cpu.zig").Arm7tdmi; const Scheduler = @import("core/scheduler.zig").Scheduler; const FpsTracker = @import("util.zig").FpsTracker; -const TwoWayChannel = @import("zba-util").TwoWayChannel; +const Channel = @import("zba-util").Channel(emu.Message, 0x100); const KeyInput = @import("core/bus/io.zig").KeyInput; const gba_width = @import("core/ppu.zig").width; @@ -94,7 +94,7 @@ pub const Gui = struct { } const RunOptions = struct { - channel: *TwoWayChannel, + ch: Channel.Sender, tracker: ?*FpsTracker = null, cpu: *Arm7tdmi, scheduler: *Scheduler, @@ -105,7 +105,7 @@ pub const Gui = struct { pub fn run(self: *Self, comptime mode: RunMode, opt: RunOptions) !void { const cpu = opt.cpu; const tracker = opt.tracker; - const channel = opt.channel; + const ch = opt.ch; const objects = opengl_impl.createObjects(); defer gl.deleteBuffers(3, @as(*const [3]GLuint, &.{ objects.vao, objects.vbo, objects.ebo })); @@ -193,54 +193,50 @@ pub const Gui = struct { switch (self.state.emulation) { .Transition => |inner| switch (inner) { .Active => { - _ = channel.gui.pop(); - - channel.emu.push(.Resume); + ch.send(.Resume); if (!config.config().host.mute) SDL.SDL_PauseAudioDevice(self.audio.device, 0); self.state.emulation = .Active; }, .Inactive => { // Assert that double pausing is impossible - if (channel.gui.peek()) |value| - std.debug.assert(value != .Paused); SDL.SDL_PauseAudioDevice(self.audio.device, 1); - channel.emu.push(.Pause); + ch.send(.Pause); self.state.emulation = .Inactive; }, }, - .Active => skip_draw: { + .Active => { const is_std = mode == .Standard; - if (is_std) channel.emu.push(.Pause); - defer if (is_std) channel.emu.push(.Resume); + if (is_std) ch.send(.Pause); + defer if (is_std) ch.send(.Resume); - switch (mode) { - .Standard => blk: { - const limit = 15; // TODO: What should this be? + // switch (mode) { + // .Standard => blk: { + // const limit = 15; // TODO: What should this be? - // TODO: learn more about std.atomic.spinLoopHint(); - for (0..limit) |_| { - const message = channel.gui.pop() orelse continue; + // // TODO: learn more about std.atomic.spinLoopHint(); + // for (0..limit) |_| { + // const message = channel.gui.pop() orelse continue; - switch (message) { - .Paused => break :blk, - .Quit => unreachable, - } - } + // switch (message) { + // .Paused => break :blk, + // .Quit => unreachable, + // } + // } - log.info("timed out waiting for emu thread to pause (limit: {})", .{limit}); - break :skip_draw; - }, - .Debug => blk: { - switch (channel.gui.pop() orelse break :blk) { - .Paused => unreachable, // only in standard mode - .Quit => break :emu_loop, // FIXME: gdb side of emu is seriously out-of-date... - } - }, - } + // log.info("timed out waiting for emu thread to pause (limit: {})", .{limit}); + // break :skip_draw; + // }, + // .Debug => blk: { + // switch (channel.gui.pop() orelse break :blk) { + // .Paused => unreachable, // only in standard mode + // .Quit => break :emu_loop, // FIXME: gdb side of emu is seriously out-of-date... + // } + // }, + // } // Add FPS count to the histogram if (tracker) |t| self.state.fps_hist.push(t.value()) catch {}; @@ -279,7 +275,7 @@ pub const Gui = struct { SDL.SDL_GL_SwapWindow(self.window); } - channel.emu.push(.Quit); + ch.send(.Quit); } fn glGetProcAddress(ctx: SDL.SDL_GLContext, proc: [:0]const u8) ?*anyopaque {