Profiling #7
			
				
			
		
		
		
	| 
						 | 
					@ -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,12 +836,15 @@ 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) };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        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) {
 | 
					    pub fn watch_stdout(&mut self, watch: bool) {
 | 
				
			||||||
| 
						 | 
					@ -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