Files
nesemu/src/native_core/bus.rs

106 lines
2.8 KiB
Rust

use crate::native_core::{apu::Apu, cpu::CpuBus, mapper::Mapper, ppu::Ppu};
const CPU_RAM_SIZE: usize = 0x0800;
const PPU_DOTS_PER_SCANLINE: u32 = 341;
const PPU_SCANLINES_PER_FRAME: u32 = 262;
const PPU_DOTS_PER_FRAME: u32 = PPU_DOTS_PER_SCANLINE * PPU_SCANLINES_PER_FRAME;
const PPU_VBLANK_START_SCANLINE: u32 = 241;
const PPU_PRERENDER_SCANLINE: u32 = 261;
pub struct NativeBus {
cpu_ram: [u8; CPU_RAM_SIZE],
ppu: Ppu,
apu: Apu,
cpu_open_bus: u8,
joypad_state: u8,
joypad_shift: u8,
joypad2_state: u8,
joypad2_shift: u8,
joypad_strobe: bool,
nmi_pending: bool,
suppress_vblank_this_frame: bool,
ppu_dot: u32,
odd_frame: bool,
in_vblank: bool,
frame_complete: bool,
cpu_cycles_since_poll: u32,
mmc3_a12_prev_high: bool,
mmc3_a12_low_dots: u16,
mmc3_last_irq_scanline: u32,
mapper: Box<dyn Mapper + Send>,
}
impl NativeBus {
pub fn new(mapper: Box<dyn Mapper + Send>) -> Self {
Self {
cpu_ram: [0; CPU_RAM_SIZE],
ppu: Ppu::new(),
apu: Apu::new(),
cpu_open_bus: 0,
joypad_state: 0,
joypad_shift: 0,
joypad2_state: 0,
joypad2_shift: 0,
joypad_strobe: false,
nmi_pending: false,
suppress_vblank_this_frame: false,
ppu_dot: 0,
odd_frame: false,
in_vblank: false,
frame_complete: false,
cpu_cycles_since_poll: 0,
mmc3_a12_prev_high: false,
mmc3_a12_low_dots: 8,
mmc3_last_irq_scanline: u32::MAX,
mapper,
}
}
pub fn apu_registers(&self) -> &[u8; 0x20] {
self.apu.registers()
}
pub fn apu_channel_outputs(&self) -> crate::native_core::apu::ChannelOutputs {
self.apu.channel_outputs()
}
pub fn render_frame(&self, out_rgba: &mut [u8], frame_number: u32, buttons: [bool; 8]) {
let _ = (frame_number, buttons);
let src = self.ppu.frame_buffer();
if out_rgba.len() >= src.len() {
out_rgba[..src.len()].copy_from_slice(src);
}
}
pub fn begin_frame(&mut self) {
self.frame_complete = false;
self.ppu.begin_frame();
}
pub fn take_frame_complete(&mut self) -> bool {
let out = self.frame_complete;
self.frame_complete = false;
out
}
pub fn clock_cpu(&mut self, cycles: u8) {
self.clock_cpu_cycles(cycles as u32);
}
pub fn take_cpu_cycles_since_poll(&mut self) -> u32 {
let cycles = self.cpu_cycles_since_poll;
self.cpu_cycles_since_poll = 0;
cycles
}
}
// CpuBus trait implementation (memory map + side effects).
mod cpu_bus_impl;
mod joypad;
// Save-state serialization helpers.
mod state;
mod timing;
#[cfg(test)]
mod tests;