Implement frame advance

This commit is contained in:
Simon Gellis 2025-02-25 00:04:07 -05:00
parent e96ce2af07
commit f2d3f5ec07
2 changed files with 40 additions and 1 deletions

View File

@ -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<()> { fn save_sram(&mut self, sim_id: SimId) -> Result<()> {
let sim = self.sims.get_mut(sim_id.to_index()); let sim = self.sims.get_mut(sim_id.to_index());
let cart = self.carts[sim_id.to_index()].as_mut(); let cart = self.carts[sim_id.to_index()].as_mut();
@ -366,6 +386,7 @@ impl Emulator {
debugger.stop_reason = None; debugger.stop_reason = None;
true true
} }
fn debug_step(&mut self, sim_id: SimId) { fn debug_step(&mut self, sim_id: SimId) {
if self.debug_continue(sim_id) { if self.debug_continue(sim_id) {
let Some(sim) = self.sims.get_mut(sim_id.to_index()) else { 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 // Don't emulate if the state is "paused", or if any sim is paused in the debugger
let running = match state { let running = match state {
EmulatorState::Paused => false, EmulatorState::Paused => false,
EmulatorState::Running => true, EmulatorState::Running | EmulatorState::Stepping => true,
EmulatorState::Debugging => self.debuggers.values().all(|d| d.stop_reason.is_none()), EmulatorState::Debugging => self.debuggers.values().all(|d| d.stop_reason.is_none()),
}; };
let p1_running = running && p1_state == SimState::Ready; let p1_running = running && p1_state == SimState::Ready;
@ -442,6 +463,10 @@ impl Emulator {
self.sims[SimId::Player2.to_index()].emulate(); self.sims[SimId::Player2.to_index()].emulate();
} }
if state == EmulatorState::Stepping {
self.state.store(EmulatorState::Paused, Ordering::Release);
}
// Debug state // Debug state
if state == EmulatorState::Debugging { if state == EmulatorState::Debugging {
for sim_id in SimId::values() { for sim_id in SimId::values() {
@ -539,6 +564,9 @@ impl Emulator {
EmulatorCommand::Resume => { EmulatorCommand::Resume => {
self.resume_sims(); self.resume_sims();
} }
EmulatorCommand::FrameAdvance => {
self.frame_advance();
}
EmulatorCommand::StartDebugging(sim_id, debugger) => { EmulatorCommand::StartDebugging(sim_id, debugger) => {
self.start_debugging(sim_id, debugger); self.start_debugging(sim_id, debugger);
} }
@ -665,6 +693,7 @@ pub enum EmulatorCommand {
StopSecondSim, StopSecondSim,
Pause, Pause,
Resume, Resume,
FrameAdvance,
StartDebugging(SimId, DebugSender), StartDebugging(SimId, DebugSender),
StopDebugging(SimId), StopDebugging(SimId),
DebugInterrupt(SimId), DebugInterrupt(SimId),
@ -700,6 +729,7 @@ pub enum SimState {
pub enum EmulatorState { pub enum EmulatorState {
Paused, Paused,
Running, Running,
Stepping,
Debugging, Debugging,
} }

View File

@ -86,6 +86,7 @@ impl GameWindow {
let is_ready = self.client.sim_state(self.sim_id) == SimState::Ready; let is_ready = self.client.sim_state(self.sim_id) == SimState::Ready;
let can_pause = is_ready && state == EmulatorState::Running; let can_pause = is_ready && state == EmulatorState::Running;
let can_resume = is_ready && state == EmulatorState::Paused; let can_resume = is_ready && state == EmulatorState::Paused;
let can_frame_advance = is_ready && state != EmulatorState::Debugging;
if state == EmulatorState::Running { if state == EmulatorState::Running {
if ui.add_enabled(can_pause, Button::new("Pause")).clicked() { if ui.add_enabled(can_pause, Button::new("Pause")).clicked() {
self.client.send_command(EmulatorCommand::Pause); self.client.send_command(EmulatorCommand::Pause);
@ -100,6 +101,14 @@ impl GameWindow {
.send_command(EmulatorCommand::Reset(self.sim_id)); .send_command(EmulatorCommand::Reset(self.sim_id));
ui.close_menu(); 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("Options", |ui| self.show_options_menu(ctx, ui));
ui.menu_button("Multiplayer", |ui| { ui.menu_button("Multiplayer", |ui| {