From f2d3f5ec071a2ae4a69b047fd49e7827c11a700c Mon Sep 17 00:00:00 2001 From: Simon Gellis Date: Tue, 25 Feb 2025 00:04:07 -0500 Subject: [PATCH] Implement frame advance --- src/emulator.rs | 32 +++++++++++++++++++++++++++++++- src/window/game.rs | 9 +++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/emulator.rs b/src/emulator.rs index 066e318..94156fe 100644 --- a/src/emulator.rs +++ b/src/emulator.rs @@ -291,6 +291,26 @@ impl Emulator { ); } + fn frame_advance(&mut self) { + if self + .state + .compare_exchange( + EmulatorState::Paused, + EmulatorState::Stepping, + Ordering::AcqRel, + Ordering::Acquire, + ) + .is_err_and(|s| s == EmulatorState::Running) + { + let _ = self.state.compare_exchange( + EmulatorState::Running, + EmulatorState::Stepping, + Ordering::AcqRel, + Ordering::Relaxed, + ); + } + } + fn save_sram(&mut self, sim_id: SimId) -> Result<()> { let sim = self.sims.get_mut(sim_id.to_index()); let cart = self.carts[sim_id.to_index()].as_mut(); @@ -366,6 +386,7 @@ impl Emulator { debugger.stop_reason = None; true } + fn debug_step(&mut self, sim_id: SimId) { if self.debug_continue(sim_id) { let Some(sim) = self.sims.get_mut(sim_id.to_index()) else { @@ -428,7 +449,7 @@ impl Emulator { // Don't emulate if the state is "paused", or if any sim is paused in the debugger let running = match state { EmulatorState::Paused => false, - EmulatorState::Running => true, + EmulatorState::Running | EmulatorState::Stepping => true, EmulatorState::Debugging => self.debuggers.values().all(|d| d.stop_reason.is_none()), }; let p1_running = running && p1_state == SimState::Ready; @@ -442,6 +463,10 @@ impl Emulator { self.sims[SimId::Player2.to_index()].emulate(); } + if state == EmulatorState::Stepping { + self.state.store(EmulatorState::Paused, Ordering::Release); + } + // Debug state if state == EmulatorState::Debugging { for sim_id in SimId::values() { @@ -539,6 +564,9 @@ impl Emulator { EmulatorCommand::Resume => { self.resume_sims(); } + EmulatorCommand::FrameAdvance => { + self.frame_advance(); + } EmulatorCommand::StartDebugging(sim_id, debugger) => { self.start_debugging(sim_id, debugger); } @@ -665,6 +693,7 @@ pub enum EmulatorCommand { StopSecondSim, Pause, Resume, + FrameAdvance, StartDebugging(SimId, DebugSender), StopDebugging(SimId), DebugInterrupt(SimId), @@ -700,6 +729,7 @@ pub enum SimState { pub enum EmulatorState { Paused, Running, + Stepping, Debugging, } diff --git a/src/window/game.rs b/src/window/game.rs index 53d6484..ce78bd2 100644 --- a/src/window/game.rs +++ b/src/window/game.rs @@ -86,6 +86,7 @@ impl GameWindow { let is_ready = self.client.sim_state(self.sim_id) == SimState::Ready; let can_pause = is_ready && state == EmulatorState::Running; let can_resume = is_ready && state == EmulatorState::Paused; + let can_frame_advance = is_ready && state != EmulatorState::Debugging; if state == EmulatorState::Running { if ui.add_enabled(can_pause, Button::new("Pause")).clicked() { self.client.send_command(EmulatorCommand::Pause); @@ -100,6 +101,14 @@ impl GameWindow { .send_command(EmulatorCommand::Reset(self.sim_id)); ui.close_menu(); } + ui.separator(); + if ui + .add_enabled(can_frame_advance, Button::new("Frame Advance")) + .clicked() + { + self.client.send_command(EmulatorCommand::FrameAdvance); + ui.close_menu(); + } }); ui.menu_button("Options", |ui| self.show_options_menu(ctx, ui)); ui.menu_button("Multiplayer", |ui| {