nes_rust/
lib.rs

1pub mod register;
2pub mod cpu;
3pub mod ppu;
4pub mod apu;
5pub mod rom;
6pub mod memory;
7pub mod mapper;
8pub mod button;
9pub mod joypad;
10pub mod input;
11pub mod audio;
12pub mod display;
13pub mod default_input;
14pub mod default_audio;
15pub mod default_display;
16
17use cpu::Cpu;
18use rom::Rom;
19use button::Button;
20use input::Input;
21use display::Display;
22use audio::Audio;
23
24/// NES emulator.
25///
26/// ```ignore
27/// use std::fs::File;
28/// use std::io::Read;
29/// use std::time::Duration;
30/// use nes_rust::Nes;
31/// use nes_rust::rom::Rom;
32/// use nes_rust::default_input::DefaultInput;
33/// use nes_rust::default_audio::DefaultAudio;
34/// use nes_rust::default_display::DefaultDisplay;
35///
36/// let input = Box::new(DefaultInput::new());
37/// let display = Box::new(DefaultDisplay::new());
38/// let audio = Box::new(DefaultAudio::new());
39/// let mut nes = Nes::new(input, display, audio);
40///
41/// // Load and set Rom from rom image binary
42/// let filename = &args[1];
43/// let mut file = File::open(filename)?;
44/// let mut contents = vec![];
45/// file.read_to_end(&mut contents)?;
46/// let rom = Rom::new(contents);
47/// nes.set_rom(rom);
48///
49/// // Go!
50/// nes.bootup();
51/// let mut rgba_pixels = [256 * 240 * 4];
52/// loop {
53///   nes.step_frame();
54///   nes.copy_pixels(rgba_pixels);
55///   // Render rgba_pixels
56///   // @TODO: Audio buffer sample code is T.B.D.
57///   // Adjust sleep time for your platform
58///   std::thread::sleep(Duration::from_millis(1));
59/// }
60/// ```
61pub struct Nes {
62	cpu: Cpu
63}
64
65impl Nes {
66	/// Creates a new `Nes`.
67    /// You need to pass [`input::Input`](./input/trait.Input.html),
68    /// [`display::Display`](./display/trait.Display.html), and
69    /// [`audio::Audio`](./audio/trait.Audio.html) traits for your platform
70    /// specific Input/Output.
71    ///
72    /// # Arguments
73    /// * `input` For pad input
74    /// * `display` For screen output
75    /// * `audio` For audio output
76	pub fn new(input: Box<dyn Input>, display: Box<dyn Display>,
77		audio: Box<dyn Audio>) -> Self {
78		Nes {
79			cpu: Cpu::new(
80				input,
81				display,
82				audio
83			)
84		}
85	}
86
87	/// Sets up NES rom
88	///
89	/// # Arguments
90	/// * `rom`
91	pub fn set_rom(&mut self, rom: Rom) {
92		self.cpu.set_rom(rom);
93	}
94
95	/// Boots up
96	pub fn bootup(&mut self) {
97		self.cpu.bootup();
98	}
99
100	/// Resets
101	pub fn reset(&mut self) {
102		self.cpu.reset();
103	}
104
105	/// Executes a CPU cycle
106	pub fn step(&mut self) {
107		self.cpu.step();
108	}
109
110	/// Executes a PPU (screen refresh) frame
111	pub fn step_frame(&mut self) {
112		self.cpu.step_frame();
113	}
114
115	/// Copies RGB pixels of screen to passed pixels.
116	/// The length and result should be specific to `display` passed via the constructor.
117	///
118	/// # Arguments
119	/// * `pixels`
120	pub fn copy_pixels(&self, pixels: &mut [u8]) {
121		self.cpu.get_ppu().get_display().copy_to_rgba_pixels(pixels);
122	}
123
124	/// Copies audio buffer to passed buffer.
125	/// The length and result should be specific to `audio` passed via the constructor.
126	///
127	/// # Arguments
128	/// * `buffer`
129	pub fn copy_sample_buffer(&mut self, buffer: &mut [f32]) {
130		self.cpu.get_mut_apu().get_mut_audio().copy_sample_buffer(buffer);
131	}
132
133	/// Presses a pad button
134	///
135	/// # Arguments
136	/// * `button`
137	pub fn press_button(&mut self, button: Button) {
138		self.cpu.get_mut_input().press(button);
139	}
140
141	/// Releases a pad button
142	///
143	/// # Arguments
144	/// * `buffer`
145	pub fn release_button(&mut self, button: Button) {
146		self.cpu.get_mut_input().release(button);
147	}
148}