1use core::ops::Deref;
2use core::time::Duration;
3
4use crate::{Button, Error, Rom, Screen, AudioSpeaker, SerialOutput};
5use crate::bus::Bus;
6use crate::cpu::{Cpu, CLOCK_SPEED};
7
8pub const DEFAULT_FRAME_RATE: u32 = 60;
9
10pub struct System<T: Deref<Target=[u8]>,
11 S: Screen,
12 SO: SerialOutput,
13 AS: AudioSpeaker> {
14 bus: Bus<T>,
16 cpu: Cpu,
18 screen: S,
20 serial_output: SO,
22 speaker: AS,
24 cycles_per_frame: u32,
26}
27
28impl<T: Deref<Target=[u8]>,
29 S: Screen,
30 SO: SerialOutput,
31 AS: AudioSpeaker> System<T, S, SO, AS> {
32 pub fn new(rom: Rom<T>, screen: S, serial_output: SO, speaker: AS) -> Self {
33 let bus = Bus::new(rom);
34 let cpu = Cpu::new();
35
36 System {
37 bus,
38 cpu,
39 screen,
40 serial_output,
41 speaker,
42 cycles_per_frame: CLOCK_SPEED / DEFAULT_FRAME_RATE,
43 }
44 }
45
46 pub fn reset(&mut self) {
47 self.bus.ppu.reset();
48 self.bus.timer.reset();
49 self.bus.serial.reset();
50 self.bus.joypad.reset();
51 self.bus.it.reset();
52 self.cpu.reset();
53 }
54
55 pub fn load_bin(&mut self, bytes: T) -> Result<(), Error> {
57 let rom = Rom::load(bytes)?;
58
59 self.reset();
60 self.bus.set_rom(rom);
61 Ok(())
62 }
63
64 pub fn load_rom(&mut self, rom: Rom<T>) {
66 self.bus.set_rom(rom);
67 self.reset();
68 }
69
70 pub fn step(&mut self) -> u8 {
72 let ticks = self.cpu.step(&mut self.bus);
73
74 for _ in 0..ticks {
75 self.bus.apu.step(&mut self.speaker);
76 self.bus.ppu.step(&mut self.screen, &mut self.bus.it);
77 self.bus.timer.step(&mut self.bus.it);
78 }
79
80 self.bus.serial.step(&mut self.serial_output, &mut self.bus.it);
81
82 self.bus.dma_tick();
83
84 ticks
85 }
86
87 pub fn rom(&self) -> &Rom<T> {
89 &self.bus.rom
90 }
91
92 pub fn screen(&mut self) -> &mut S {
94 &mut self.screen
95 }
96
97 pub fn serial(&mut self) -> &mut SO {
99 &mut self.serial_output
100 }
101
102 pub fn speaker(&mut self) -> &mut AS {
104 &mut self.speaker
105 }
106
107 pub fn set_button(&mut self, button: Button, is_pressed: bool) {
119 self.bus.joypad.set_button(button, is_pressed, &mut self.bus.it);
120 }
121
122 pub fn set_frame_rate(&mut self, fps: u32) {
124 if fps > 0 && fps < CLOCK_SPEED {
125 self.cycles_per_frame = CLOCK_SPEED / fps;
126 }
127 }
128
129 pub fn update_frame(&mut self) -> u32 {
150 let mut cycles = 0u32;
151 while cycles < self.cycles_per_frame {
152 cycles += self.step() as u32;
153 }
154 self.screen.update();
155 cycles
156 }
157
158 pub fn min_frame_time(&self) -> Duration {
161 Duration::from_millis(1000 / (CLOCK_SPEED / self.cycles_per_frame) as u64)
162 }
163}