Implement stepping
This commit is contained in:
@@ -147,12 +147,18 @@ extern "C" fn on_execute(sim: *mut VB, address: u32, _code: *const u16, _length:
|
||||
// There is no way for the userdata to be null or otherwise invalid.
|
||||
let data: &mut VBState = unsafe { &mut *vb_get_user_data(sim).cast() };
|
||||
|
||||
if data.breakpoints.binary_search(&address).is_err() {
|
||||
return 0;
|
||||
let mut stopped = 0;
|
||||
if data.step_from.is_some_and(|s| s != address) {
|
||||
data.step_from = None;
|
||||
data.stop_reason = Some(StopReason::Stepped);
|
||||
stopped = 1;
|
||||
}
|
||||
if data.breakpoints.binary_search(&address).is_ok() {
|
||||
data.stop_reason = Some(StopReason::Breakpoint);
|
||||
stopped = 1;
|
||||
}
|
||||
|
||||
data.stop_reason = Some(StopReason::Breakpoint);
|
||||
1
|
||||
stopped
|
||||
}
|
||||
|
||||
const AUDIO_CAPACITY_SAMPLES: usize = 834 * 4;
|
||||
@@ -162,6 +168,7 @@ pub const EXPECTED_FRAME_SIZE: usize = 834 * 2;
|
||||
struct VBState {
|
||||
frame_seen: bool,
|
||||
stop_reason: Option<StopReason>,
|
||||
step_from: Option<u32>,
|
||||
breakpoints: Vec<u32>,
|
||||
}
|
||||
|
||||
@@ -172,6 +179,7 @@ pub struct Sim {
|
||||
|
||||
pub enum StopReason {
|
||||
Breakpoint,
|
||||
Stepped,
|
||||
}
|
||||
|
||||
impl Sim {
|
||||
@@ -183,12 +191,14 @@ impl Sim {
|
||||
let sim: *mut VB = Box::into_raw(memory.into_boxed_slice()).cast();
|
||||
unsafe { vb_init(sim) };
|
||||
unsafe { vb_set_option(sim, VBOption::PseudoHalt, 1) };
|
||||
unsafe { vb_set_keys(sim, VBKey::SGN.bits()) };
|
||||
unsafe { vb_reset(sim) };
|
||||
|
||||
// set up userdata
|
||||
let state = VBState {
|
||||
frame_seen: false,
|
||||
stop_reason: None,
|
||||
step_from: None,
|
||||
breakpoints: vec![],
|
||||
};
|
||||
unsafe { vb_set_user_data(sim, Box::into_raw(Box::new(state)).cast()) };
|
||||
@@ -361,21 +371,35 @@ impl Sim {
|
||||
let data = self.get_state();
|
||||
if let Ok(index) = data.breakpoints.binary_search(&address) {
|
||||
data.breakpoints.remove(index);
|
||||
if data.breakpoints.is_empty() {
|
||||
if data.step_from.is_none() && data.breakpoints.is_empty() {
|
||||
unsafe { vb_set_execute_callback(self.sim, None) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_breakpoints(&mut self) {
|
||||
pub fn step(&mut self) {
|
||||
let current_pc = unsafe { vb_get_program_counter(self.sim) };
|
||||
let data = self.get_state();
|
||||
data.step_from = Some(current_pc);
|
||||
unsafe {
|
||||
vb_set_execute_callback(self.sim, Some(on_execute));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_debug_state(&mut self) {
|
||||
let data = self.get_state();
|
||||
data.step_from = None;
|
||||
data.breakpoints.clear();
|
||||
unsafe { vb_set_execute_callback(self.sim, None) };
|
||||
}
|
||||
|
||||
pub fn stop_reason(&mut self) -> Option<StopReason> {
|
||||
let data = self.get_state();
|
||||
data.stop_reason.take()
|
||||
let reason = data.stop_reason.take();
|
||||
if data.step_from.is_none() && data.breakpoints.is_empty() {
|
||||
unsafe { vb_set_execute_callback(self.sim, None) };
|
||||
}
|
||||
reason
|
||||
}
|
||||
|
||||
fn get_state(&mut self) -> &mut VBState {
|
||||
|
||||
Reference in New Issue
Block a user