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}