use crate::apu::APU;
use crate::cart::Cart;
use crate::controller::ButtonState;
use crate::cpu::CPU;
use crate::memory::MemoryBus;
use crate::ports::{AudioDevice, VideoDevice};
use crate::ppu::PPU;
pub struct Console {
apu: APU,
cpu: CPU,
ppu: PPU,
}
impl Console {
pub fn new(cart: Cart, sample_rate: u32) -> Self {
let mut memory = MemoryBus::with_cart(cart);
let ppu = PPU::new(&mut memory);
let cpu = CPU::new(memory);
Console {
apu: APU::new(sample_rate),
cpu,
ppu,
}
}
pub fn step<'a, A, V>(&'a mut self, audio: &mut A, video: &mut V) -> i32
where
A: AudioDevice,
V: VideoDevice,
{
let cpucycles = self.cpu.step();
let m = &mut self.cpu.mem;
for _ in 0..cpucycles * 3 {
self.ppu.step(m, video);
}
for _ in 0..cpucycles {
self.apu.step(m, audio);
}
cpucycles
}
pub fn step_micros<'a, A, V>(&'a mut self, audio: &mut A, video: &mut V, micros: u32)
where
A: AudioDevice,
V: VideoDevice,
{
let mut cpu_cycles = ((micros * 179) / 100) as i32;
while cpu_cycles > 0 {
cpu_cycles -= self.step(audio, video);
}
}
pub fn step_frame<'a, A, V>(&'a mut self, audio: &mut A, video: &mut V)
where
A: AudioDevice,
V: VideoDevice,
{
let mut frame_happened = false;
while !frame_happened {
let cpucycles = self.cpu.step();
let m = &mut self.cpu.mem;
for _ in 0..cpucycles * 3 {
frame_happened = self.ppu.step(m, video) || frame_happened;
}
for _ in 0..cpucycles {
self.apu.step(m, audio);
}
}
}
pub fn update_controller(&mut self, buttons: ButtonState) {
self.cpu.set_buttons(buttons);
}
pub fn reset(&mut self) {
self.cpu.reset();
self.cpu.mem.reset();
self.ppu.reset(&mut self.cpu.mem);
self.ppu.clear_vbuffers();
}
}