Implement GDB/LLDB compatible server #3

Merged
SonicSwordcane merged 33 commits from debugger into main 2025-01-19 00:13:43 +00:00
1 changed files with 26 additions and 14 deletions
Showing only changes of commit 856ee00999 - Show all commits

View File

@ -177,7 +177,7 @@ impl Emulator {
messages: HashMap::new(), messages: HashMap::new(),
debuggers: HashMap::new(), debuggers: HashMap::new(),
eye_contents: vec![0u8; 384 * 224 * 2], eye_contents: vec![0u8; 384 * 224 * 2],
audio_samples: vec![0.0; EXPECTED_FRAME_SIZE], audio_samples: Vec::with_capacity(EXPECTED_FRAME_SIZE),
}) })
} }
@ -286,6 +286,7 @@ impl Emulator {
self.renderers.remove(&SimId::Player2); self.renderers.remove(&SimId::Player2);
self.sims.truncate(1); self.sims.truncate(1);
self.sim_state[SimId::Player2.to_index()].store(SimState::Uninitialized, Ordering::Release); self.sim_state[SimId::Player2.to_index()].store(SimState::Uninitialized, Ordering::Release);
self.stop_debugging(SimId::Player2);
self.linked.store(false, Ordering::Release); self.linked.store(false, Ordering::Release);
Ok(()) Ok(())
} }
@ -303,7 +304,12 @@ impl Emulator {
fn stop_debugging(&mut self, sim_id: SimId) { fn stop_debugging(&mut self, sim_id: SimId) {
self.debuggers.remove(&sim_id); self.debuggers.remove(&sim_id);
if self.debuggers.is_empty() { if self.debuggers.is_empty() {
self.state.store(EmulatorState::Running, Ordering::Release); let _ = self.state.compare_exchange(
EmulatorState::Debugging,
EmulatorState::Running,
Ordering::AcqRel,
Ordering::Relaxed,
);
} }
} }
@ -364,6 +370,8 @@ impl Emulator {
let p1_state = self.sim_state[SimId::Player1.to_index()].load(Ordering::Acquire); let p1_state = self.sim_state[SimId::Player1.to_index()].load(Ordering::Acquire);
let p2_state = self.sim_state[SimId::Player2.to_index()].load(Ordering::Acquire); let p2_state = self.sim_state[SimId::Player2.to_index()].load(Ordering::Acquire);
let state = self.state.load(Ordering::Acquire); let state = self.state.load(Ordering::Acquire);
// Emulation
// 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,
@ -381,6 +389,7 @@ impl Emulator {
self.sims[SimId::Player2.to_index()].emulate(); self.sims[SimId::Player2.to_index()].emulate();
} }
// Video
for sim_id in SimId::values() { for sim_id in SimId::values() {
let Some(renderer) = self.renderers.get_mut(&sim_id) else { let Some(renderer) = self.renderers.get_mut(&sim_id) else {
continue; continue;
@ -395,24 +404,27 @@ impl Emulator {
} }
} }
} }
// Audio
// Audio playback speed is how we keep the emulator running in real time.
// Even if we're muted, call `read_samples` to know how many frames of silence to play.
let p1_audio = let p1_audio =
p1_running && self.audio_on[SimId::Player1.to_index()].load(Ordering::Acquire); p1_running && self.audio_on[SimId::Player1.to_index()].load(Ordering::Acquire);
let p2_audio = let p2_audio =
p2_running && self.audio_on[SimId::Player2.to_index()].load(Ordering::Acquire); p2_running && self.audio_on[SimId::Player2.to_index()].load(Ordering::Acquire);
let weight = if p1_audio && p2_audio { 0.5 } else { 1.0 }; let (p1_weight, p2_weight) = match (p1_audio, p2_audio) {
if p1_audio { (true, true) => (0.5, 0.5),
if let Some(sim) = self.sims.get_mut(SimId::Player1.to_index()) { (true, false) => (1.0, 0.0),
sim.read_samples(&mut self.audio_samples, weight); (false, true) => (0.0, 1.0),
} (false, false) => (0.0, 0.0),
};
if let Some(sim) = self.sims.get_mut(SimId::Player1.to_index()) {
sim.read_samples(&mut self.audio_samples, p1_weight);
} }
if p2_audio { if let Some(sim) = self.sims.get_mut(SimId::Player2.to_index()) {
if let Some(sim) = self.sims.get_mut(SimId::Player2.to_index()) { sim.read_samples(&mut self.audio_samples, p2_weight);
sim.read_samples(&mut self.audio_samples, weight);
}
} }
if self.audio_samples.is_empty() { if !self.audio_samples.is_empty() {
self.audio_samples.resize(EXPECTED_FRAME_SIZE, 0.0);
} else {
idle = false; idle = false;
} }
self.audio.update(&self.audio_samples); self.audio.update(&self.audio_samples);