Added watch command to debugger

It's a bit weirdly implemented because the Addressable trait doesn't
have access to System, so it has to set a flag on the Bus which is
then checked during the step function in System to activate the
breakpoint if a watched memory location was written to
This commit is contained in:
transistor 2021-12-26 16:32:15 -08:00
parent 588c0b56a2
commit 10ca0c7995
5 changed files with 81 additions and 6 deletions

View File

@ -194,6 +194,28 @@ before 2021-10-25
blanking bit reset at 16.6ms. I've now changed it to be proper, in that the blanking bit is set at
15ms, the count is reset at 16.6ms, and the blank bit is cleared at 1.2ms
2021-12-23
- looking into the coprocessor not working. I tried Mortal Kombat 2 and apart from something weird
going on during the character select screen, everything worked until combat started and then it
crashed due to an invalid memory access to address 0x0068eebb, which occurs at PC: 0xffff0245,
so something is causing it to execute ram, which is probably not what's supposed to happen
- It looks like it's swapping stacks, and that's making it hard to trace. At some point, it swaps
the stack and then does a rts, but the stack return value is invalid and that causes it to mess up.
It almost looks like it does put a valid return on the stack but then unintentionally overwrites it
due to overlapping memory areas (I could just be tracing this wrong). I'll come back to this later
2021-12-26
- looking into the scroll black bits, I checked the scroll table for Sonic2 in BlastEm and the values
are clearly different for Scroll B. The values in BlastEm are close to 0xffff but the ones in Moa
are 0x10f2, 0x11f2, etc. And it's wrong in the source ram (0xffe000 which is copied to 0xfc00 in VRAM)
- I added watcher debug commands to watch for modifications to a given memory location, and used that
to watch 0xffe322, which is an scroll value for Scroll B in an area near the end of the hscroll table
where the scroll value is different from BlastEm.
- breakpoint occurs at 0xc670 where that value is written to. The function starts at 0xC57E and
calculates scroll values.
- so far I'm suspecting the DIV followed by the EXTW at 0xc62a might be doing something incorrect,
and then when it adds the result in %d0 to %d3 before using that as the scroll value, it's adding
too large a value (that should have been cut off to a word)

View File

@ -102,6 +102,23 @@ impl Debugger {
}
}
},
"w" | "watch" => {
if args.len() != 2 {
println!("Usage: watch <addr>");
} else {
let addr = Address::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse address"))?;
system.get_bus().add_watcher(addr);
}
},
"rw" | "rwatch" | "remove_watch" => {
if args.len() != 2 {
println!("Usage: remove_watch <addr>");
} else {
let addr = Address::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse address"))?;
system.get_bus().remove_watcher(addr);
}
},
"d" | "dump" => {
if args.len() > 1 {
let addr = u32::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse address"))?;

View File

@ -118,8 +118,10 @@ pub struct Block {
}
pub struct Bus {
ignore_unmapped: bool,
blocks: Vec<Block>,
ignore_unmapped: bool,
watchers: Vec<Address>,
watcher_modified: bool,
}
impl Bus {
@ -127,6 +129,8 @@ impl Bus {
Bus {
ignore_unmapped: false,
blocks: vec!(),
watchers: vec!(),
watcher_modified: false,
}
}
@ -177,6 +181,23 @@ impl Bus {
println!("{}", line);
}
}
pub fn add_watcher(&mut self, addr: Address) {
self.watchers.push(addr);
}
pub fn remove_watcher(&mut self, addr: Address) {
self.watchers.push(addr);
if let Some(index) = self.watchers.iter().position(|a| *a == addr) {
self.watchers.remove(index);
}
}
pub fn check_and_reset_watcher_modified(&mut self) -> bool {
let result = self.watcher_modified;
self.watcher_modified = false;
result
}
}
impl Addressable for Bus {
@ -199,6 +220,11 @@ impl Addressable for Bus {
}
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
if let Some(_) = self.watchers.iter().position(|a| *a == addr) {
println!("watch: writing to address {:#06x} with {:?}", addr, data);
self.watcher_modified = true;
}
let (dev, relative_addr) = match self.get_device_at(addr, data.len()) {
Ok(result) => result,
Err(err) if self.ignore_unmapped => {

View File

@ -718,7 +718,7 @@ impl Addressable for Ym7101 {
0x20
}
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
fn read(&mut self, mut addr: Address, data: &mut [u8]) -> Result<(), Error> {
match addr {
// Read from Data Port
0x00 | 0x02 => {
@ -734,10 +734,16 @@ impl Addressable for Ym7101 {
},
// Read from Control Port
0x04 | 0x06 => {
0x04 | 0x05 | 0x06 | 0x07 => {
debug!("{}: read status byte {:x}", DEV_NAME, self.state.status);
data[0] = (self.state.status >> 8) as u8;
data[1] = (self.state.status & 0x00FF) as u8;
for i in 0..data.len() {
data[i] = if (addr % 2) == 0 {
(self.state.status >> 8) as u8
} else {
(self.state.status & 0x00FF) as u8
};
addr += 1;
}
},
_ => { println!("{}: !!! unhandled read from {:x}", DEV_NAME, addr); },

View File

@ -106,7 +106,11 @@ impl System {
self.check_debugger();
match self.process_one_event() {
Ok(()) => { }
Ok(()) => {
if self.get_bus().check_and_reset_watcher_modified() {
self.enable_debugging();
}
},
Err(err) if err.err == ErrorType::Breakpoint => {
println!("Breakpoint reached: {}", err.msg);
self.enable_debugging();