Support arbitrary markers

This commit is contained in:
Simon Gellis 2025-09-01 00:07:55 -04:00
parent 841ded3bee
commit 8f9922473e
1 changed files with 43 additions and 6 deletions

View File

@ -300,7 +300,7 @@ extern "C" fn on_read(
extern "C" fn on_write(
sim: *mut VB,
address: u32,
_type: VBDataType,
typ_: VBDataType,
value: *mut i32,
_cycles: *mut u32,
_cancel: *mut c_int,
@ -317,6 +317,29 @@ extern "C" fn on_write(
}
}
// If we have profiling enabled, track custom markers
if data.monitor.enabled {
let normalized_hw_address = address & 0x0700003f;
if normalized_hw_address == 0x02000038 && matches!(typ_, VBDataType::S32) {
assert!(data.monitor.queued_event.is_none());
// The game has written the address of a null-terminated string
// (whose length is at most 64 bytes). Read that string.
let str_address = unsafe { *value } as u32;
let mut bytes = [0u8; 64];
let mut len = 0;
for (dst, src_address) in bytes.iter_mut().zip(str_address..str_address + 64) {
let char = unsafe { vb_read(sim, src_address, VBDataType::U8) } as u8;
if char == 0 {
break;
}
*dst = char;
len += 1;
}
let name = String::from_utf8_lossy(&bytes[..len]).into_owned();
data.monitor.queued_event = Some(SimEvent::Marker(Cow::Owned(name)));
}
}
if let Some(start) = data.write_watchpoints.start_of_range_containing(address) {
let watch = if data.read_watchpoints.contains(address) {
VBWatchpointType::Access
@ -465,6 +488,10 @@ impl VBState {
|| !self.read_watchpoints.is_empty()
|| !self.write_watchpoints.is_empty()
}
fn needs_write_callback(&self) -> bool {
self.stdout.is_some() || self.monitor.enabled || !self.write_watchpoints.is_empty()
}
}
pub enum StopReason {
@ -529,12 +556,18 @@ impl Sim {
unsafe { vb_set_execute_callback(self.sim, Some(on_execute)) };
unsafe { vb_set_exception_callback(self.sim, Some(on_exception)) };
unsafe { vb_set_fetch_callback(self.sim, Some(on_fetch)) };
unsafe { vb_set_write_callback(self.sim, Some(on_write)) };
} else {
if !state.needs_execute_callback() {
let needs_execute = state.needs_execute_callback();
let needs_write = state.needs_write_callback();
if !needs_execute {
unsafe { vb_set_execute_callback(self.sim, None) };
}
unsafe { vb_set_exception_callback(self.sim, None) };
unsafe { vb_set_fetch_callback(self.sim, None) };
if !needs_write {
unsafe { vb_set_write_callback(self.sim, None) };
}
}
}
@ -776,9 +809,10 @@ impl Sim {
fn remove_write_watchpoint(&mut self, address: u32, length: usize) {
let state = self.get_state();
state.write_watchpoints.remove(address, length);
let needs_write = state.needs_write_callback();
let needs_execute = state.needs_execute_callback();
if state.write_watchpoints.is_empty() {
if state.stdout.is_none() {
if !needs_write {
unsafe { vb_set_write_callback(self.sim, None) };
}
if !needs_execute {
@ -802,12 +836,15 @@ impl Sim {
data.breakpoints.clear();
data.read_watchpoints.clear();
data.write_watchpoints.clear();
let needs_write = data.stdout.is_some();
let needs_write = data.needs_write_callback();
let needs_execute = data.needs_execute_callback();
unsafe { vb_set_read_callback(self.sim, None) };
if !needs_write {
unsafe { vb_set_write_callback(self.sim, None) };
}
unsafe { vb_set_execute_callback(self.sim, None) };
if !needs_execute {
unsafe { vb_set_execute_callback(self.sim, None) };
}
}
pub fn watch_stdout(&mut self, watch: bool) {
@ -819,7 +856,7 @@ impl Sim {
}
} else {
data.stdout.take();
if data.write_watchpoints.is_empty() {
if !data.needs_write_callback() {
unsafe { vb_set_write_callback(self.sim, None) };
}
}