feat: pause emu when UI reads emu state
This commit is contained in:
		@@ -4,7 +4,7 @@ const config = @import("../config.zig");
 | 
			
		||||
 | 
			
		||||
const Scheduler = @import("scheduler.zig").Scheduler;
 | 
			
		||||
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
 | 
			
		||||
const FpsTracker = @import("../util.zig").FpsTracker;
 | 
			
		||||
const Tracker = @import("../util.zig").FpsTracker;
 | 
			
		||||
 | 
			
		||||
const Timer = std.time.Timer;
 | 
			
		||||
const Atomic = std.atomic.Atomic;
 | 
			
		||||
@@ -35,18 +35,18 @@ const RunKind = enum {
 | 
			
		||||
    LimitedFPS,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
pub fn run(quit: *Atomic(bool), scheduler: *Scheduler, cpu: *Arm7tdmi, tracker: *FpsTracker) void {
 | 
			
		||||
pub fn run(quit: *Atomic(bool), pause: *Atomic(bool), cpu: *Arm7tdmi, scheduler: *Scheduler, tracker: *Tracker) 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, quit, scheduler, cpu, tracker);
 | 
			
		||||
        inner(.LimitedFPS, audio_sync, quit, pause, cpu, scheduler, tracker);
 | 
			
		||||
    } else {
 | 
			
		||||
        inner(.UnlimitedFPS, audio_sync, quit, scheduler, cpu, tracker);
 | 
			
		||||
        inner(.UnlimitedFPS, audio_sync, quit, pause, cpu, scheduler, tracker);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn inner(comptime kind: RunKind, audio_sync: bool, quit: *Atomic(bool), scheduler: *Scheduler, cpu: *Arm7tdmi, tracker: ?*FpsTracker) void {
 | 
			
		||||
fn inner(comptime kind: RunKind, audio_sync: bool, quit: *Atomic(bool), pause: *Atomic(bool), cpu: *Arm7tdmi, scheduler: *Scheduler, tracker: ?*Tracker) void {
 | 
			
		||||
    if (kind == .UnlimitedFPS or kind == .LimitedFPS) {
 | 
			
		||||
        std.debug.assert(tracker != null);
 | 
			
		||||
        log.info("FPS tracking enabled", .{});
 | 
			
		||||
@@ -57,6 +57,8 @@ fn inner(comptime kind: RunKind, audio_sync: bool, quit: *Atomic(bool), schedule
 | 
			
		||||
            log.info("Emulation w/out video sync", .{});
 | 
			
		||||
 | 
			
		||||
            while (!quit.load(.Monotonic)) {
 | 
			
		||||
                if (pause.load(.Monotonic)) continue;
 | 
			
		||||
 | 
			
		||||
                runFrame(scheduler, cpu);
 | 
			
		||||
                audioSync(audio_sync, cpu.bus.apu.stream, &cpu.bus.apu.is_buffer_full);
 | 
			
		||||
 | 
			
		||||
@@ -69,6 +71,8 @@ fn inner(comptime kind: RunKind, audio_sync: bool, quit: *Atomic(bool), schedule
 | 
			
		||||
            var wake_time: u64 = frame_period;
 | 
			
		||||
 | 
			
		||||
            while (!quit.load(.Monotonic)) {
 | 
			
		||||
                if (pause.load(.Monotonic)) continue;
 | 
			
		||||
 | 
			
		||||
                runFrame(scheduler, cpu);
 | 
			
		||||
                const new_wake_time = videoSync(&timer, wake_time);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -389,8 +389,9 @@ pub const Gui = struct {
 | 
			
		||||
        const fbo_id = try Self.genFrameBufObject(out_tex);
 | 
			
		||||
        defer gl.deleteFramebuffers(1, &fbo_id);
 | 
			
		||||
 | 
			
		||||
        var quit = std.atomic.Atomic(bool).init(false);
 | 
			
		||||
        var tracker = FpsTracker.init();
 | 
			
		||||
        var quit = std.atomic.Atomic(bool).init(false);
 | 
			
		||||
        var pause = std.atomic.Atomic(bool).init(false);
 | 
			
		||||
 | 
			
		||||
        var title_buf: [0x100]u8 = undefined;
 | 
			
		||||
 | 
			
		||||
@@ -441,12 +442,6 @@ pub const Gui = struct {
 | 
			
		||||
                            SDL.SDLK_s => keyinput.shoulder_r.set(),
 | 
			
		||||
                            SDL.SDLK_RETURN => keyinput.start.set(),
 | 
			
		||||
                            SDL.SDLK_RSHIFT => keyinput.select.set(),
 | 
			
		||||
                            SDL.SDLK_i => {
 | 
			
		||||
                                comptime std.debug.assert(sample_format == SDL.AUDIO_U16);
 | 
			
		||||
                                log.err("Sample Count: {}", .{@intCast(u32, SDL.SDL_AudioStreamAvailable(cpu.bus.apu.stream)) / (2 * @sizeOf(u16))});
 | 
			
		||||
                            },
 | 
			
		||||
                            // SDL.SDLK_j => log.err("Scheduler Capacity: {} | Scheduler Event Count: {}", .{ scheduler.queue.capacity(), scheduler.queue.count() }),
 | 
			
		||||
                            SDL.SDLK_k => {},
 | 
			
		||||
                            else => {},
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
@@ -456,6 +451,14 @@ pub const Gui = struct {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // We Access non-atomic parts of the Emulator here
 | 
			
		||||
            {
 | 
			
		||||
                pause.store(true, .Monotonic);
 | 
			
		||||
                defer pause.store(false, .Monotonic);
 | 
			
		||||
 | 
			
		||||
                self.state.fps_hist.push(tracker.value()) catch {};
 | 
			
		||||
 | 
			
		||||
                // Draw GBA Screen to Texture
 | 
			
		||||
                {
 | 
			
		||||
                    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo_id);
 | 
			
		||||
                    defer gl.bindFramebuffer(gl.FRAMEBUFFER, 0);
 | 
			
		||||
@@ -465,18 +468,12 @@ pub const Gui = struct {
 | 
			
		||||
                    self.drawGbaTexture(obj_ids, emu_tex, buf);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            // Background
 | 
			
		||||
                // Background Colour
 | 
			
		||||
                const size = zgui.io.getDisplaySize();
 | 
			
		||||
                gl.viewport(0, 0, @floatToInt(c_int, size[0]), @floatToInt(c_int, size[1]));
 | 
			
		||||
                gl.clearColor(0, 0, 0, 1.0);
 | 
			
		||||
                gl.clear(gl.COLOR_BUFFER_BIT);
 | 
			
		||||
 | 
			
		||||
            zgui.backend.newFrame(width, height);
 | 
			
		||||
            self.draw(out_tex, cpu);
 | 
			
		||||
            zgui.backend.draw();
 | 
			
		||||
 | 
			
		||||
            SDL.SDL_GL_SwapWindow(self.window);
 | 
			
		||||
 | 
			
		||||
                if (tracker) |t| {
 | 
			
		||||
                    const emu_fps = t.value();
 | 
			
		||||
                    self.state.fps_hist.push(emu_fps) catch {};
 | 
			
		||||
@@ -484,9 +481,14 @@ pub const Gui = struct {
 | 
			
		||||
                    const dyn_title = std.fmt.bufPrintZ(&title_buf, "ZBA | {s} [Emu: {}fps] ", .{ self.title, emu_fps }) catch unreachable;
 | 
			
		||||
                    SDL.SDL_SetWindowTitle(self.window, dyn_title.ptr);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                zgui.backend.newFrame(width, height);
 | 
			
		||||
                self.draw(out_tex, cpu);
 | 
			
		||||
                zgui.backend.draw();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        quit.store(true, .Monotonic); // Terminate Emulator Thread
 | 
			
		||||
            SDL.SDL_GL_SwapWindow(self.window);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn glGetProcAddress(ctx: SDL.SDL_GLContext, proc: [:0]const u8) ?*anyopaque {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user