diff --git a/src/emulator.rs b/src/emulator.rs index 672e5c9..814149b 100644 --- a/src/emulator.rs +++ b/src/emulator.rs @@ -141,6 +141,8 @@ pub struct Emulator { linked: Arc, renderers: HashMap, messages: HashMap>, + eye_contents: Vec, + audio_samples: Vec, } impl Emulator { @@ -164,6 +166,8 @@ impl Emulator { linked, renderers: HashMap::new(), messages: HashMap::new(), + eye_contents: vec![0u8; 384 * 224 * 2], + audio_samples: vec![0.0; EXPECTED_FRAME_SIZE], }) } @@ -257,56 +261,8 @@ impl Emulator { } pub fn run(&mut self) { - let mut eye_contents = vec![0u8; 384 * 224 * 2]; - let mut audio_samples = vec![]; loop { - let p1_running = self.running[SimId::Player1.to_index()].load(Ordering::Acquire); - let p2_running = self.running[SimId::Player2.to_index()].load(Ordering::Acquire); - let mut idle = p1_running || p2_running; - if p1_running && p2_running { - Sim::emulate_many(&mut self.sims); - } else if p1_running { - self.sims[SimId::Player1.to_index()].emulate(); - } else if p2_running { - self.sims[SimId::Player2.to_index()].emulate(); - } - - for sim_id in SimId::values() { - let Some(renderer) = self.renderers.get_mut(&sim_id) else { - continue; - }; - let Some(sim) = self.sims.get_mut(sim_id.to_index()) else { - continue; - }; - if sim.read_pixels(&mut eye_contents) { - idle = false; - if renderer.queue_render(&eye_contents).is_err() { - self.renderers.remove(&sim_id); - } - } - } - let p1_audio = - p1_running && self.audio_on[SimId::Player1.to_index()].load(Ordering::Acquire); - let p2_audio = - p2_running && self.audio_on[SimId::Player2.to_index()].load(Ordering::Acquire); - let weight = if p1_audio && p2_audio { 0.5 } else { 1.0 }; - if p1_audio { - if let Some(sim) = self.sims.get_mut(SimId::Player1.to_index()) { - sim.read_samples(&mut audio_samples, weight); - } - } - if p2_audio { - if let Some(sim) = self.sims.get_mut(SimId::Player2.to_index()) { - sim.read_samples(&mut audio_samples, weight); - } - } - if audio_samples.is_empty() { - audio_samples.resize(EXPECTED_FRAME_SIZE, 0.0); - } else { - idle = false; - } - self.audio.update(&audio_samples); - audio_samples.clear(); + let idle = self.tick(); if idle { // The game is paused, and we have output all the video/audio we have. // Block the thread until a new command comes in. @@ -331,6 +287,58 @@ impl Emulator { } } + // returns true if the emulator is "idle" (i.e. this didn't output anything) + pub fn tick(&mut self) -> bool { + let p1_running = self.running[SimId::Player1.to_index()].load(Ordering::Acquire); + let p2_running = self.running[SimId::Player2.to_index()].load(Ordering::Acquire); + let mut idle = p1_running || p2_running; + if p1_running && p2_running { + Sim::emulate_many(&mut self.sims); + } else if p1_running { + self.sims[SimId::Player1.to_index()].emulate(); + } else if p2_running { + self.sims[SimId::Player2.to_index()].emulate(); + } + + for sim_id in SimId::values() { + let Some(renderer) = self.renderers.get_mut(&sim_id) else { + continue; + }; + let Some(sim) = self.sims.get_mut(sim_id.to_index()) else { + continue; + }; + if sim.read_pixels(&mut self.eye_contents) { + idle = false; + if renderer.queue_render(&self.eye_contents).is_err() { + self.renderers.remove(&sim_id); + } + } + } + let p1_audio = + p1_running && self.audio_on[SimId::Player1.to_index()].load(Ordering::Acquire); + let p2_audio = + p2_running && self.audio_on[SimId::Player2.to_index()].load(Ordering::Acquire); + let weight = if p1_audio && p2_audio { 0.5 } else { 1.0 }; + if p1_audio { + if let Some(sim) = self.sims.get_mut(SimId::Player1.to_index()) { + sim.read_samples(&mut self.audio_samples, weight); + } + } + if p2_audio { + if let Some(sim) = self.sims.get_mut(SimId::Player2.to_index()) { + sim.read_samples(&mut self.audio_samples, weight); + } + } + if self.audio_samples.is_empty() { + self.audio_samples.resize(EXPECTED_FRAME_SIZE, 0.0); + } else { + idle = false; + } + self.audio.update(&self.audio_samples); + self.audio_samples.clear(); + idle + } + fn handle_command(&mut self, command: EmulatorCommand) { match command { EmulatorCommand::ConnectToSim(sim_id, renderer, messages) => {