debug.rsannotateddebug.rssource159 lines · 4.4 KB · raw
1use crate::WordRam;
2use crate::api::SegaCd;
3use crate::cddrive::cdc::Rchip;
4use crate::rf5c164::Rf5c164;
5use jgenesis_common::debug::{DebugMemoryView, DebugWordsView, Endian};
6use jgenesis_proc_macros::EnumAll;
7use m68000_emu::M68000;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumAll)]
10pub enum SegaCdMemoryArea {
11    BiosRom,
12    PrgRam,
13    WordRam,
14    PcmRam,
15    CdcRam,
16}
17
18#[derive(Debug, Clone)]
19pub struct SegaCdDebugState {
20    sub_cpu: M68000,
21    bios_rom: Box<[u16]>,
22    prg_ram: Box<[u16]>,
23    word_ram: WordRam,
24    pcm: Rf5c164,
25    cdc: Rchip,
26    prg_ram_bank: u8,
27}
28
29impl SegaCdDebugState {
30    #[must_use]
31    pub fn sub_cpu(&self) -> &M68000 {
32        &self.sub_cpu
33    }
34
35    #[must_use]
36    pub fn bios_rom(&self) -> &[u16] {
37        &self.bios_rom
38    }
39
40    #[must_use]
41    pub fn prg_ram(&self) -> &[u16] {
42        &self.prg_ram
43    }
44
45    #[must_use]
46    pub fn main_cpu_prg_ram_bank(&self) -> u8 {
47        self.prg_ram_bank
48    }
49
50    #[must_use]
51    pub fn word_ram(&self) -> &WordRam {
52        &self.word_ram
53    }
54
55    #[must_use]
56    pub fn scd_memory_view(
57        &mut self,
58        memory_area: SegaCdMemoryArea,
59    ) -> Box<dyn DebugMemoryView + '_> {
60        match memory_area {
61            SegaCdMemoryArea::BiosRom => Box::new(DebugWordsView(&mut self.bios_rom, Endian::Big)),
62            SegaCdMemoryArea::PrgRam => Box::new(DebugWordsView(&mut self.prg_ram, Endian::Big)),
63            SegaCdMemoryArea::WordRam => Box::new(self.word_ram.debug_view()),
64            SegaCdMemoryArea::PcmRam => Box::new(self.pcm.debug_ram_view()),
65            SegaCdMemoryArea::CdcRam => Box::new(self.cdc.debug_ram_view()),
66        }
67    }
68}
69
70pub struct SegaCdDebugView<'scd> {
71    pub(crate) sub_cpu: &'scd mut M68000,
72    pub(crate) bios_rom: &'scd mut [u16],
73    pub(crate) prg_ram: &'scd mut [u16],
74    pub(crate) word_ram: &'scd mut WordRam,
75    pub(crate) pcm: &'scd mut Rf5c164,
76    pub(crate) cdc: &'scd mut Rchip,
77    pub(crate) prg_ram_bank: u8,
78}
79
80impl SegaCdDebugView<'_> {
81    #[must_use]
82    pub fn to_debug_state(&self) -> SegaCdDebugState {
83        SegaCdDebugState {
84            sub_cpu: self.sub_cpu.clone(),
85            bios_rom: self.bios_rom.to_vec().into_boxed_slice(),
86            prg_ram: self.prg_ram.to_vec().into_boxed_slice(),
87            word_ram: self.word_ram.clone(),
88            pcm: self.pcm.clone(),
89            cdc: self.cdc.clone(),
90            prg_ram_bank: self.prg_ram_bank,
91        }
92    }
93
94    pub fn apply_memory_edit(&mut self, memory_area: SegaCdMemoryArea, address: usize, value: u8) {
95        match memory_area {
96            SegaCdMemoryArea::BiosRom => {
97                DebugWordsView(self.bios_rom, Endian::Big).write(address, value);
98            }
99            SegaCdMemoryArea::PrgRam => {
100                DebugWordsView(self.prg_ram, Endian::Big).write(address, value);
101            }
102            SegaCdMemoryArea::WordRam => {
103                self.word_ram.debug_view().write(address, value);
104            }
105            SegaCdMemoryArea::PcmRam => {
106                self.pcm.debug_ram_view().write(address, value);
107            }
108            SegaCdMemoryArea::CdcRam => {
109                self.cdc.debug_ram_view().write(address, value);
110            }
111        }
112    }
113}
114
115impl SegaCd {
116    pub fn as_debug_view(&mut self) -> SegaCdDebugView<'_> {
117        self.bus.as_debug_view(&mut self.sub_cpu)
118    }
119}
120
121pub trait SegaCdDebugger {
122    fn check_sub_read_breakpoint<const WORD: bool>(&mut self, address: u32) -> bool;
123
124    fn check_sub_write_breakpoint<const WORD: bool>(&mut self, address: u32, value: u16) -> bool;
125
126    fn check_sub_execute_breakpoint(&mut self, pc: u32) -> bool;
127
128    fn check_sub_interrupt_breakpoint(&mut self, interrupt_level: u8) -> bool;
129
130    fn handle_sub_breakpoint(&mut self, debug_view: SegaCdDebugView<'_>);
131}
132
133pub struct DummySegaCdDebugger;
134
135#[allow(unused_variables)]
136impl SegaCdDebugger for DummySegaCdDebugger {
137    #[inline(always)]
138    fn check_sub_read_breakpoint<const WORD: bool>(&mut self, address: u32) -> bool {
139        false
140    }
141
142    #[inline(always)]
143    fn check_sub_write_breakpoint<const WORD: bool>(&mut self, address: u32, value: u16) -> bool {
144        false
145    }
146
147    #[inline(always)]
148    fn check_sub_execute_breakpoint(&mut self, pc: u32) -> bool {
149        false
150    }
151
152    #[inline(always)]
153    fn check_sub_interrupt_breakpoint(&mut self, interrupt_level: u8) -> bool {
154        false
155    }
156
157    #[inline(always)]
158    fn handle_sub_breakpoint(&mut self, debug_view: SegaCdDebugView<'_>) {}
159}