mirror of
https://github.com/transistorfet/moa.git
synced 2024-11-21 19:30:52 +00:00
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:
parent
588c0b56a2
commit
10ca0c7995
22
docs/log.txt
22
docs/log.txt
@ -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)
|
||||
|
||||
|
||||
|
||||
|
@ -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"))?;
|
||||
|
@ -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 => {
|
||||
|
@ -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); },
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user