debug.rsannotateddebug.rssource134 lines · 3.9 KB · raw
1use crate::api::debug::{SegaCdDebugView, SegaCdDebugger};
2use crate::bus::SegaCdBus;
3use m68000_emu::debug::M68000Debugger;
4use m68000_emu::{BusInterface, M68000};
5
6pub struct DebugSegaCdBus<'bus, 'debugger, Debugger> {
7    bus: &'bus mut SegaCdBus,
8    debugger: &'debugger mut Debugger,
9}
10
11impl<'bus, 'debugger, Debugger> DebugSegaCdBus<'bus, 'debugger, Debugger> {
12    pub fn new(bus: &'bus mut SegaCdBus, debugger: &'debugger mut Debugger) -> Self {
13        Self { bus, debugger }
14    }
15}
16
17impl SegaCdBus {
18    pub fn as_debug_view<'slf, 'cpu, 'ret>(
19        &'slf mut self,
20        sub_cpu: &'cpu mut M68000,
21    ) -> SegaCdDebugView<'ret>
22    where
23        'slf: 'ret,
24        'cpu: 'ret,
25    {
26        SegaCdDebugView {
27            sub_cpu,
28            bios_rom: self.bios.0.as_mut(),
29            prg_ram: self.prg_ram.as_mut_slice(),
30            word_ram: &mut self.word_ram,
31            pcm: &mut self.pcm,
32            cdc: self.disc_drive.cdc_mut(),
33            prg_ram_bank: self.registers.prg_ram_bank,
34        }
35    }
36}
37
38pub struct BusDebugView<'debugbus, 'bus, 'debugger, Debugger>(
39    &'debugbus mut DebugSegaCdBus<'bus, 'debugger, Debugger>,
40);
41
42impl<Debugger: SegaCdDebugger> M68000Debugger for BusDebugView<'_, '_, '_, Debugger> {
43    fn check_read<const WORD: bool>(&mut self, address: u32, cpu: &mut M68000) {
44        if self.0.debugger.check_sub_read_breakpoint::<WORD>(address) {
45            log::info!("Sub 68000 triggered read breakpoint: {address:06X}");
46
47            let debug_view = self.0.bus.as_debug_view(cpu);
48            self.0.debugger.handle_sub_breakpoint(debug_view);
49        }
50    }
51
52    fn check_write<const WORD: bool>(&mut self, address: u32, value: u16, cpu: &mut M68000) {
53        if self.0.debugger.check_sub_write_breakpoint::<WORD>(address, value) {
54            log::info!("Sub 68000 triggered write breakpoint: {address:06X} {value:04X}");
55
56            let debug_view = self.0.bus.as_debug_view(cpu);
57            self.0.debugger.handle_sub_breakpoint(debug_view);
58        }
59    }
60
61    fn check_execute(&mut self, pc: u32, cpu: &mut M68000) {
62        if self.0.debugger.check_sub_execute_breakpoint(pc) {
63            log::info!("Sub 68000 triggered execute breakpoint: PC={pc:06X}");
64
65            let debug_view = self.0.bus.as_debug_view(cpu);
66            self.0.debugger.handle_sub_breakpoint(debug_view);
67        }
68    }
69
70    fn check_interrupt(&mut self, interrupt_level: u8, cpu: &mut M68000) {
71        if self.0.debugger.check_sub_interrupt_breakpoint(interrupt_level) {
72            log::info!(
73                "Sub 68000 triggered interrupt breakpoint, interrupt level {interrupt_level}"
74            );
75
76            let debug_view = self.0.bus.as_debug_view(cpu);
77            self.0.debugger.handle_sub_breakpoint(debug_view);
78        }
79    }
80}
81
82impl<'bus, 'debugger, Debugger: SegaCdDebugger> BusInterface
83    for DebugSegaCdBus<'bus, 'debugger, Debugger>
84{
85    type DebugView<'a>
86        = BusDebugView<'a, 'bus, 'debugger, Debugger>
87    where
88        Self: 'a;
89
90    #[inline]
91    fn read_byte(&mut self, address: u32) -> u8 {
92        self.bus.read_byte(address)
93    }
94
95    #[inline]
96    fn read_word(&mut self, address: u32) -> u16 {
97        self.bus.read_word(address)
98    }
99
100    #[inline]
101    fn write_byte(&mut self, address: u32, value: u8) {
102        self.bus.write_byte(address, value);
103    }
104
105    #[inline]
106    fn write_word(&mut self, address: u32, value: u16) {
107        self.bus.write_word(address, value);
108    }
109
110    #[inline]
111    fn interrupt_level(&self) -> u8 {
112        self.bus.interrupt_level()
113    }
114
115    #[inline]
116    fn acknowledge_interrupt(&mut self, interrupt_level: u8) {
117        self.bus.acknowledge_interrupt(interrupt_level);
118    }
119
120    #[inline]
121    fn halt(&self) -> bool {
122        self.bus.halt()
123    }
124
125    #[inline]
126    fn reset(&self) -> bool {
127        <SegaCdBus as BusInterface>::reset(self.bus)
128    }
129
130    #[inline]
131    fn debug_view(&mut self) -> Option<Self::DebugView<'_>> {
132        Some(BusDebugView(self))
133    }
134}