diff --git a/rustboyadvance-core/src/debugger/command.rs b/rustboyadvance-core/src/debugger/command.rs index 15a904a..07459ba 100644 --- a/rustboyadvance-core/src/debugger/command.rs +++ b/rustboyadvance-core/src/debugger/command.rs @@ -105,16 +105,23 @@ impl Debugger { } println!("{}\n", self.gba.cpu); } - Continue => loop { + Continue => 'running: loop { self.gba.key_poll(); - match self.gba.check_breakpoint() { - Some(addr) => { - println!("Breakpoint reached! @{:x}", addr); - break; + if let Some(breakpoint) = self.gba.step_debugger() { + let mut bp_sym = None; + if let Some(symbols) = self.gba.sysbus.cartridge.get_symbols() { + for s in symbols.keys() { + if symbols.get(s).unwrap() == &breakpoint { + bp_sym = Some(s.clone()); + } + } } - _ => { - self.gba.cpu.step(&mut self.gba.sysbus); + if let Some(sym) = bp_sym { + println!("Breakpoint reached! @{}", sym); + } else { + println!("Breakpoint reached! @{:x}", breakpoint); } + break 'running; } }, Frame(count) => { diff --git a/rustboyadvance-core/src/gba.rs b/rustboyadvance-core/src/gba.rs index 2712880..432a8f6 100644 --- a/rustboyadvance-core/src/gba.rs +++ b/rustboyadvance-core/src/gba.rs @@ -174,8 +174,8 @@ impl GameBoyAdvance { pub fn check_breakpoint(&self) -> Option { let next_pc = self.cpu.get_next_pc(); for bp in &self.cpu.breakpoints { - if *bp == next_pc { - return Some(next_pc); + if (*bp & !1) == next_pc { + return Some(*bp); } } @@ -249,6 +249,43 @@ impl GameBoyAdvance { cycles } + #[cfg(feature = "debugger")] + /// 'step' function that checks for breakpoints + /// TODO avoid code duplication + pub fn step_debugger(&mut self) -> Option { + // I hate myself for doing this, but rust left me no choice. + let io = unsafe { + let ptr = &mut *self.sysbus as *mut SysBus; + &mut (*ptr).io as &mut IoDevices + }; + + // clear any pending DMAs + let mut irqs = IrqBitmask(0); + while io.dmac.is_active() { + io.dmac.perform_work(&mut self.sysbus, &mut irqs); + } + io.intc.request_irqs(irqs); + + let cycles = self.step_cpu(io); + let breakpoint = self.check_breakpoint(); + + irqs = IrqBitmask(0); + let mut _ignored = 0; + // update gpu & sound + io.timers.update(cycles, &mut self.sysbus, &mut irqs); + io.gpu.update( + cycles, + &mut irqs, + &mut _ignored, + self.sysbus.as_mut(), + &self.video_device, + ); + io.sound.update(cycles, &mut _ignored, &self.audio_device); + io.intc.request_irqs(irqs); + + breakpoint + } + /// Query the emulator for the recently drawn framebuffer. /// for use with implementations where the VideoInterface is not a viable option. pub fn get_frame_buffer(&self) -> &[u32] {