parent
d54202bf8b
commit
9183e6850d
|
@ -17,13 +17,10 @@ const Timer = std.time.Timer;
|
||||||
pub const Synchro = struct {
|
pub const Synchro = struct {
|
||||||
const AtomicBool = std.atomic.Atomic(bool);
|
const AtomicBool = std.atomic.Atomic(bool);
|
||||||
|
|
||||||
// UI -> Emulator
|
|
||||||
ui_busy: AtomicBool = AtomicBool.init(false),
|
|
||||||
paused: AtomicBool = AtomicBool.init(true), // FIXME: can ui_busy and paused be the same?
|
paused: AtomicBool = AtomicBool.init(true), // FIXME: can ui_busy and paused be the same?
|
||||||
should_quit: AtomicBool = AtomicBool.init(false),
|
should_quit: AtomicBool = AtomicBool.init(false),
|
||||||
|
|
||||||
// Emulator -> UI
|
emu_access: std.Thread.Mutex = .{},
|
||||||
did_pause: AtomicBool = AtomicBool.init(false),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 4 Cycles in 1 dot
|
/// 4 Cycles in 1 dot
|
||||||
|
@ -71,18 +68,16 @@ fn inner(comptime kind: RunKind, audio_sync: bool, cpu: *Arm7tdmi, scheduler: *S
|
||||||
|
|
||||||
const bus_ptr: *Bus = @ptrCast(@alignCast(cpu.bus.ptr));
|
const bus_ptr: *Bus = @ptrCast(@alignCast(cpu.bus.ptr));
|
||||||
|
|
||||||
|
// FIXME: audioSync accesses emulator state without any guarantees
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
.Unlimited, .UnlimitedFPS => {
|
.Unlimited, .UnlimitedFPS => {
|
||||||
log.info("Emulation w/out video sync", .{});
|
log.info("Emulation w/out video sync", .{});
|
||||||
|
|
||||||
while (!sync.should_quit.load(.Monotonic)) {
|
while (!sync.should_quit.load(.Monotonic)) {
|
||||||
if (sync.ui_busy.load(.Monotonic) or sync.paused.load(.Monotonic)) {
|
if (sync.paused.load(.Monotonic)) continue;
|
||||||
sync.did_pause.store(true, .Monotonic);
|
|
||||||
|
|
||||||
continue;
|
runFrame(sync, scheduler, cpu);
|
||||||
}
|
|
||||||
|
|
||||||
runFrame(scheduler, cpu);
|
|
||||||
audioSync(audio_sync, bus_ptr.apu.stream, &bus_ptr.apu.is_buffer_full);
|
audioSync(audio_sync, bus_ptr.apu.stream, &bus_ptr.apu.is_buffer_full);
|
||||||
|
|
||||||
if (kind == .UnlimitedFPS) tracker.?.tick();
|
if (kind == .UnlimitedFPS) tracker.?.tick();
|
||||||
|
@ -94,13 +89,9 @@ fn inner(comptime kind: RunKind, audio_sync: bool, cpu: *Arm7tdmi, scheduler: *S
|
||||||
var wake_time: u64 = frame_period;
|
var wake_time: u64 = frame_period;
|
||||||
|
|
||||||
while (!sync.should_quit.load(.Monotonic)) {
|
while (!sync.should_quit.load(.Monotonic)) {
|
||||||
if (sync.ui_busy.load(.Monotonic) or sync.paused.load(.Monotonic)) {
|
if (sync.paused.load(.Monotonic)) continue;
|
||||||
sync.did_pause.store(true, .Release);
|
|
||||||
|
|
||||||
continue;
|
runFrame(sync, scheduler, cpu);
|
||||||
}
|
|
||||||
|
|
||||||
runFrame(scheduler, cpu);
|
|
||||||
const new_wake_time = videoSync(&timer, wake_time);
|
const new_wake_time = videoSync(&timer, wake_time);
|
||||||
|
|
||||||
// Spin to make up the difference of OS scheduler innacuracies
|
// Spin to make up the difference of OS scheduler innacuracies
|
||||||
|
@ -118,7 +109,10 @@ fn inner(comptime kind: RunKind, audio_sync: bool, cpu: *Arm7tdmi, scheduler: *S
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn runFrame(sched: *Scheduler, cpu: *Arm7tdmi) void {
|
pub fn runFrame(sync: *Synchro, sched: *Scheduler, cpu: *Arm7tdmi) void {
|
||||||
|
sync.emu_access.lock();
|
||||||
|
defer sync.emu_access.unlock();
|
||||||
|
|
||||||
const frame_end = sched.tick + cycles_per_frame;
|
const frame_end = sched.tick + cycles_per_frame;
|
||||||
|
|
||||||
while (sched.tick < frame_end) {
|
while (sched.tick < frame_end) {
|
||||||
|
|
|
@ -206,21 +206,9 @@ pub const Gui = struct {
|
||||||
self.state.emulation = .Inactive;
|
self.state.emulation = .Inactive;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.Active => blk: {
|
.Active => {
|
||||||
sync.ui_busy.store(true, .Monotonic);
|
sync.emu_access.lock();
|
||||||
defer sync.ui_busy.store(false, .Monotonic);
|
defer sync.emu_access.unlock();
|
||||||
|
|
||||||
// spin until we know the emu is paused :)
|
|
||||||
|
|
||||||
const timeout = 0x100000;
|
|
||||||
wait_loop: for (0..timeout) |i| {
|
|
||||||
const ret = sync.did_pause.compareAndSwap(true, false, .Acquire, .Monotonic);
|
|
||||||
if (ret == null) break :wait_loop;
|
|
||||||
|
|
||||||
if (i == timeout - 1) break :blk;
|
|
||||||
}
|
|
||||||
|
|
||||||
// while (sync.did_pause.compareAndSwap(true, false, .Acquire, .Acquire) != null) std.atomic.spinLoopHint();
|
|
||||||
|
|
||||||
// Add FPS count to the histogram
|
// Add FPS count to the histogram
|
||||||
if (tracker) |t| self.state.fps_hist.push(t.value()) catch {};
|
if (tracker) |t| self.state.fps_hist.push(t.value()) catch {};
|
||||||
|
|
Loading…
Reference in New Issue