Skip to main content

nes_sim/
api.rs

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}