1use crate::{ControllerState, FRAME_WIDTH};
2
3pub const VIDEO_FRAME_PITCH: usize = FRAME_WIDTH;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6pub enum PixelFormat {
7 Indexed8,
8}
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq)]
11pub struct VideoFrame<'a> {
12 pub width: usize,
13 pub height: usize,
14 pub pitch: usize,
15 pub format: PixelFormat,
16 pub frame_number: u64,
17 pub pixels: &'a [u8],
18}
19
20#[derive(Clone, Copy, Debug, PartialEq)]
21pub struct AudioBatch<'a> {
22 pub channels: u8,
23 pub sample_rate: u32,
24 pub samples: &'a [f32],
25}
26
27impl<'a> Default for AudioBatch<'a> {
28 fn default() -> Self {
29 Self {
30 channels: 1,
31 sample_rate: 44_100,
32 samples: &[],
33 }
34 }
35}
36
37#[derive(Clone, Debug, PartialEq, Eq)]
38pub enum CoreCommand {
39 Reset,
40 SetControllerState {
41 port: usize,
42 state: ControllerState,
43 },
44 RunFrame,
45 StepCpuInstruction,
46 #[cfg(feature = "debug")]
47 AddBreakpoint(Breakpoint),
48 #[cfg(feature = "debug")]
49 RemoveBreakpoint(Breakpoint),
50 #[cfg(feature = "debug")]
51 SetPaused(bool),
52}
53
54#[derive(Clone, Copy, Debug, PartialEq, Eq)]
55pub enum CoreEvent {
56 None,
57 ResetComplete,
58 ControllerStateUpdated { port: usize },
59 FrameReady { frame_number: u64 },
60 CpuInstructionComplete { instruction_counter: u64 },
61}
62
63#[derive(Clone, Copy, Debug, PartialEq, Eq)]
64pub struct CoreResponse {
65 pub event: CoreEvent,
66 pub master_clock: u64,
67}
68
69#[derive(Clone, Copy, Debug, PartialEq, Eq)]
70pub struct CpuDebugSnapshot {
71 pub a: u8,
72 pub x: u8,
73 pub y: u8,
74 pub sp: u8,
75 pub pc: u16,
76 pub status: u8,
77 pub clocks: u64,
78 pub cycles_remaining: u64,
79 pub instruction_counter: u64,
80 pub irq_pending: bool,
81 pub nmi_line: bool,
82}
83
84#[derive(Clone, Copy, Debug, PartialEq, Eq)]
85pub struct PpuDebugSnapshot {
86 pub frame: u64,
87 pub scanline: i16,
88 pub in_vblank: bool,
89 pub nmi_line: bool,
90 pub oam_addr: u8,
91 #[cfg(feature = "debug")]
92 pub cycles: u16,
93 #[cfg(feature = "debug")]
94 pub ctrl: u8,
95 #[cfg(feature = "debug")]
96 pub mask: u8,
97 #[cfg(feature = "debug")]
98 pub status: u8,
99 #[cfg(feature = "debug")]
100 pub fine_x: u8,
101 #[cfg(feature = "debug")]
102 pub vram_addr: u16,
103 #[cfg(feature = "debug")]
104 pub temp_vram_addr: u16,
105 #[cfg(feature = "debug")]
106 pub write_latch: bool,
107 #[cfg(feature = "debug")]
108 pub bg_on: bool,
109 #[cfg(feature = "debug")]
110 pub sprites_on: bool,
111 #[cfg(feature = "debug")]
112 pub rendering_on: bool,
113 #[cfg(feature = "debug")]
114 pub odd_frame: bool,
115}
116
117#[derive(Clone, Copy, Debug, PartialEq, Eq)]
118pub struct DebugSnapshot {
119 pub master_clock: u64,
120 pub cpu: CpuDebugSnapshot,
121 pub ppu: PpuDebugSnapshot,
122}
123
124#[cfg(feature = "debug")]
125#[derive(Clone, Debug, PartialEq, Eq)]
126pub struct DisassembledInstruction {
127 pub address: u16,
128 pub bytes: [u8; 3],
129 pub len: u8,
130 pub mnemonic: String,
131 pub operand: String,
132}
133
134#[cfg(feature = "debug")]
135#[derive(Clone, Debug, PartialEq, Eq)]
136pub struct DisassemblyResult {
137 pub instructions: Vec<DisassembledInstruction>,
138 pub pc_index: usize,
139}
140
141#[derive(Clone, Copy, Debug, PartialEq, Eq)]
142pub struct MemorySnapshot<'a> {
143 pub ram: &'a [u8; 0x800],
144 pub vram: &'a [u8; 0x1000],
145 pub chr: &'a [u8; 0x2000],
146 pub palette: &'a [u8; 0x20],
147 pub oam: &'a [u8; 256],
148}
149
150#[cfg(feature = "debug")]
151#[derive(Debug, Clone, Copy, PartialEq, Eq)]
152pub enum Breakpoint {
153 Address(u16),
154 MemoryRead(u16),
155 MemoryWrite(u16),
156 PpuScanline(i16),
157 Vblank,
158}
159
160#[cfg(feature = "debug")]
161#[derive(Debug, Clone, Default)]
162pub struct Debugger {
163 breakpoints: Vec<Breakpoint>,
164 paused: bool,
165}
166
167#[cfg(feature = "debug")]
168impl Debugger {
169 pub fn new() -> Self {
170 Self::default()
171 }
172
173 pub fn add_breakpoint(&mut self, bp: Breakpoint) {
174 if !self.breakpoints.contains(&bp) {
175 self.breakpoints.push(bp);
176 }
177 }
178
179 pub fn remove_breakpoint(&mut self, bp: &Breakpoint) {
180 self.breakpoints.retain(|b| b != bp);
181 }
182
183 pub fn clear_breakpoints(&mut self) {
184 self.breakpoints.clear();
185 }
186
187 pub fn breakpoints(&self) -> &[Breakpoint] {
188 &self.breakpoints
189 }
190
191 pub fn set_paused(&mut self, paused: bool) {
192 self.paused = paused;
193 }
194
195 pub fn paused(&self) -> bool {
196 self.paused
197 }
198}