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, } impl NativeBus { pub fn new(mapper: Box) -> 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;