Support arbitrary markers
This commit is contained in:
parent
841ded3bee
commit
8f9922473e
|
@ -300,7 +300,7 @@ extern "C" fn on_read(
|
||||||
extern "C" fn on_write(
|
extern "C" fn on_write(
|
||||||
sim: *mut VB,
|
sim: *mut VB,
|
||||||
address: u32,
|
address: u32,
|
||||||
_type: VBDataType,
|
typ_: VBDataType,
|
||||||
value: *mut i32,
|
value: *mut i32,
|
||||||
_cycles: *mut u32,
|
_cycles: *mut u32,
|
||||||
_cancel: *mut c_int,
|
_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) {
|
if let Some(start) = data.write_watchpoints.start_of_range_containing(address) {
|
||||||
let watch = if data.read_watchpoints.contains(address) {
|
let watch = if data.read_watchpoints.contains(address) {
|
||||||
VBWatchpointType::Access
|
VBWatchpointType::Access
|
||||||
|
@ -465,6 +488,10 @@ impl VBState {
|
||||||
|| !self.read_watchpoints.is_empty()
|
|| !self.read_watchpoints.is_empty()
|
||||||
|| !self.write_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 {
|
pub enum StopReason {
|
||||||
|
@ -529,12 +556,18 @@ impl Sim {
|
||||||
unsafe { vb_set_execute_callback(self.sim, Some(on_execute)) };
|
unsafe { vb_set_execute_callback(self.sim, Some(on_execute)) };
|
||||||
unsafe { vb_set_exception_callback(self.sim, Some(on_exception)) };
|
unsafe { vb_set_exception_callback(self.sim, Some(on_exception)) };
|
||||||
unsafe { vb_set_fetch_callback(self.sim, Some(on_fetch)) };
|
unsafe { vb_set_fetch_callback(self.sim, Some(on_fetch)) };
|
||||||
|
unsafe { vb_set_write_callback(self.sim, Some(on_write)) };
|
||||||
} else {
|
} 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_execute_callback(self.sim, None) };
|
||||||
}
|
}
|
||||||
unsafe { vb_set_exception_callback(self.sim, None) };
|
unsafe { vb_set_exception_callback(self.sim, None) };
|
||||||
unsafe { vb_set_fetch_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) {
|
fn remove_write_watchpoint(&mut self, address: u32, length: usize) {
|
||||||
let state = self.get_state();
|
let state = self.get_state();
|
||||||
state.write_watchpoints.remove(address, length);
|
state.write_watchpoints.remove(address, length);
|
||||||
|
let needs_write = state.needs_write_callback();
|
||||||
let needs_execute = state.needs_execute_callback();
|
let needs_execute = state.needs_execute_callback();
|
||||||
if state.write_watchpoints.is_empty() {
|
if state.write_watchpoints.is_empty() {
|
||||||
if state.stdout.is_none() {
|
if !needs_write {
|
||||||
unsafe { vb_set_write_callback(self.sim, None) };
|
unsafe { vb_set_write_callback(self.sim, None) };
|
||||||
}
|
}
|
||||||
if !needs_execute {
|
if !needs_execute {
|
||||||
|
@ -802,13 +836,16 @@ impl Sim {
|
||||||
data.breakpoints.clear();
|
data.breakpoints.clear();
|
||||||
data.read_watchpoints.clear();
|
data.read_watchpoints.clear();
|
||||||
data.write_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) };
|
unsafe { vb_set_read_callback(self.sim, None) };
|
||||||
if !needs_write {
|
if !needs_write {
|
||||||
unsafe { vb_set_write_callback(self.sim, None) };
|
unsafe { vb_set_write_callback(self.sim, None) };
|
||||||
}
|
}
|
||||||
|
if !needs_execute {
|
||||||
unsafe { vb_set_execute_callback(self.sim, None) };
|
unsafe { vb_set_execute_callback(self.sim, None) };
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn watch_stdout(&mut self, watch: bool) {
|
pub fn watch_stdout(&mut self, watch: bool) {
|
||||||
let data = self.get_state();
|
let data = self.get_state();
|
||||||
|
@ -819,7 +856,7 @@ impl Sim {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data.stdout.take();
|
data.stdout.take();
|
||||||
if data.write_watchpoints.is_empty() {
|
if !data.needs_write_callback() {
|
||||||
unsafe { vb_set_write_callback(self.sim, None) };
|
unsafe { vb_set_write_callback(self.sim, None) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue