Implement fake stdout

This commit is contained in:
2025-05-30 23:52:16 -04:00
parent 2d18aeaba2
commit a2a5884a2a
3 changed files with 80 additions and 18 deletions
+44 -3
View File
@@ -230,7 +230,7 @@ extern "C" fn on_write(
sim: *mut VB,
address: u32,
_type: VBDataType,
_value: *mut i32,
value: *mut i32,
_cycles: *mut u32,
_cancel: *mut c_int,
) -> c_int {
@@ -238,6 +238,14 @@ extern "C" fn on_write(
// 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 we're monitoring stdout, track this write
if let Some(stdout) = data.stdout.as_mut() {
let normalized_hw_address = address & 0x0700003f;
if normalized_hw_address == 0x02000030 {
stdout.push(unsafe { *value } as u8);
}
}
if let Some(start) = data.write_watchpoints.start_of_range_containing(address) {
let watch = if data.read_watchpoints.contains(address) {
VBWatchpointType::Access
@@ -263,6 +271,7 @@ struct VBState {
breakpoints: Vec<u32>,
read_watchpoints: AddressSet,
write_watchpoints: AddressSet,
stdout: Option<Vec<u8>>,
}
impl VBState {
@@ -306,6 +315,7 @@ impl Sim {
breakpoints: vec![],
read_watchpoints: AddressSet::new(),
write_watchpoints: AddressSet::new(),
stdout: None,
};
unsafe { vb_set_user_data(sim, Box::into_raw(Box::new(state)).cast()) };
unsafe { vb_set_frame_callback(sim, Some(on_frame)) };
@@ -564,7 +574,9 @@ impl Sim {
state.write_watchpoints.remove(address, length);
let needs_execute = state.needs_execute_callback();
if state.write_watchpoints.is_empty() {
unsafe { vb_set_write_callback(self.sim, None) };
if state.stdout.is_none() {
unsafe { vb_set_write_callback(self.sim, None) };
}
if !needs_execute {
unsafe { vb_set_execute_callback(self.sim, None) };
}
@@ -586,11 +598,40 @@ impl Sim {
data.breakpoints.clear();
data.read_watchpoints.clear();
data.write_watchpoints.clear();
let needs_write = data.stdout.is_some();
unsafe { vb_set_read_callback(self.sim, None) };
unsafe { vb_set_write_callback(self.sim, None) };
if !needs_write {
unsafe { vb_set_write_callback(self.sim, None) };
}
unsafe { vb_set_execute_callback(self.sim, None) };
}
pub fn watch_stdout(&mut self, watch: bool) {
let data = self.get_state();
if watch {
if data.stdout.is_none() {
data.stdout = Some(vec![]);
unsafe { vb_set_write_callback(self.sim, Some(on_write)) };
}
} else {
data.stdout.take();
if data.write_watchpoints.is_empty() {
unsafe { vb_set_write_callback(self.sim, None) };
}
}
}
pub fn take_stdout(&mut self) -> Option<String> {
let data = self.get_state();
let stdout = data.stdout.take()?;
let string = match String::from_utf8(stdout) {
Ok(str) => str,
Err(err) => String::from_utf8_lossy(err.as_bytes()).into_owned(),
};
data.stdout = Some(vec![]);
Some(string)
}
pub fn stop_reason(&mut self) -> Option<StopReason> {
let data = self.get_state();
let reason = data.stop_reason.take();