Compare commits

..

No commits in common. "55da5a29d88bdd93cc59f3b8a22057e9680acc95" and "80a15039e064143a1b9e973c242a8598de0126a3" have entirely different histories.

4 changed files with 59 additions and 18 deletions

View File

@ -13,8 +13,8 @@ pub(crate) const BOOT_SIZE: usize = 0x100;
#[derive(Debug)] #[derive(Debug)]
pub struct Bus { pub struct Bus {
boot: Option<[u8; BOOT_SIZE]>, // Boot ROM is 256b long boot: Option<[u8; BOOT_SIZE]>, // Boot ROM is 256b long
pub(crate) cart: Option<Cartridge>, cart: Option<Cartridge>,
pub(crate) ppu: Ppu, ppu: Ppu,
work_ram: WorkRam, work_ram: WorkRam,
var_ram: VariableWorkRam, var_ram: VariableWorkRam,
timer: Timer, timer: Timer,
@ -22,7 +22,7 @@ pub struct Bus {
apu: Apu, apu: Apu,
high_ram: HighRam, high_ram: HighRam,
serial: Serial, serial: Serial,
pub(crate) joyp: Joypad, joypad: Joypad,
} }
impl Default for Bus { impl Default for Bus {
@ -38,7 +38,7 @@ impl Default for Bus {
apu: Default::default(), apu: Default::default(),
high_ram: Default::default(), high_ram: Default::default(),
serial: Default::default(), serial: Default::default(),
joyp: Default::default(), joypad: Default::default(),
} }
} }
} }
@ -86,10 +86,30 @@ impl Bus {
} }
} }
#[inline]
pub(crate) fn joyp_mut(&mut self) -> &mut Joypad {
&mut self.joypad
}
#[inline]
pub(crate) fn cart(&self) -> Option<&Cartridge> {
self.cart.as_ref()
}
#[inline]
pub(crate) fn cart_mut(&mut self) -> Option<&mut Cartridge> {
self.cart.as_mut()
}
#[inline] #[inline]
pub(crate) fn apu_mut(&mut self) -> &mut Apu { pub(crate) fn apu_mut(&mut self) -> &mut Apu {
&mut self.apu &mut self.apu
} }
#[inline]
pub fn ppu(&self) -> &Ppu {
&self.ppu
}
} }
impl Bus { impl Bus {
@ -219,7 +239,7 @@ impl BusIo for Bus {
// Every address here starts with 0xFF so we can just check the // Every address here starts with 0xFF so we can just check the
// low byte to figure out which register it is // low byte to figure out which register it is
match addr & 0x00FF { match addr & 0x00FF {
0x00 => self.joyp.p1, 0x00 => self.joypad.p1,
0x01 => self.serial.next, 0x01 => self.serial.next,
0x02 => self.serial.ctrl.into(), 0x02 => self.serial.ctrl.into(),
0x04 => (self.timer.divider >> 8) as u8, 0x04 => (self.timer.divider >> 8) as u8,
@ -317,7 +337,7 @@ impl BusIo for Bus {
// Every address here starts with 0xFF so we can just check the // Every address here starts with 0xFF so we can just check the
// low byte to figure out which register it is // low byte to figure out which register it is
match addr & 0x00FF { match addr & 0x00FF {
0x00 => self.joyp.update(byte), 0x00 => self.joypad.update(byte),
0x01 => self.serial.next = byte, 0x01 => self.serial.next = byte,
0x02 => self.serial.ctrl = byte.into(), 0x02 => self.serial.ctrl = byte.into(),
0x04 => self.timer.divider = 0x0000, 0x04 => self.timer.divider = 0x0000,
@ -381,7 +401,7 @@ impl Bus {
let lcd_stat = self.ppu.int.lcd_stat(); let lcd_stat = self.ppu.int.lcd_stat();
// Read the current interrupt information from the Joypad // Read the current interrupt information from the Joypad
let joypad = self.joyp.interrupt(); let joypad = self.joypad.interrupt();
// Read the current interrupt information from the Timer // Read the current interrupt information from the Timer
let timer = self.timer.interrupt(); let timer = self.timer.interrupt();
@ -411,7 +431,7 @@ impl Bus {
self.ppu.int.set_lcd_stat(lcd_stat); self.ppu.int.set_lcd_stat(lcd_stat);
// Update the Joypad's instance of the following interrupts // Update the Joypad's instance of the following interrupts
self.joyp.set_interrupt(joypad); self.joypad.set_interrupt(joypad);
// Update the Timer's instance of the following interrupts // Update the Timer's instance of the following interrupts
self.timer.set_interrupt(timer); self.timer.set_interrupt(timer);

View File

@ -151,6 +151,16 @@ impl BusIo for Cpu {
} }
impl Cpu { impl Cpu {
#[inline]
pub(crate) fn bus(&self) -> &Bus {
&self.bus
}
#[inline]
pub(crate) fn bus_mut(&mut self) -> &mut Bus {
&mut self.bus
}
fn handle_ei(&mut self) { fn handle_ei(&mut self) {
match self.ime { match self.ime {
ImeState::EiExecuted => self.ime = ImeState::Pending, ImeState::EiExecuted => self.ime = ImeState::Pending,

View File

@ -1,6 +1,7 @@
use crate::apu::gen::SampleProducer; use crate::apu::gen::SampleProducer;
use crate::bus::BOOT_SIZE; use crate::bus::BOOT_SIZE;
use crate::cpu::Cpu; use crate::cpu::Cpu;
use crate::joypad::{self, Joypad};
use crate::{Cycle, GB_HEIGHT, GB_WIDTH}; use crate::{Cycle, GB_HEIGHT, GB_WIDTH};
use clap::crate_name; use clap::crate_name;
use gilrs::Gilrs; use gilrs::Gilrs;
@ -19,9 +20,9 @@ pub fn run_frame(emu: &mut Emulator, gamepad: &mut Gilrs, key: &WinitInputHelper
let mut elapsed = 0; let mut elapsed = 0;
if let Some(event) = gamepad.next_event() { if let Some(event) = gamepad.next_event() {
crate::joypad::handle_gamepad_input(&mut emu.cpu.bus.joyp, event); joypad::handle_gamepad_input(emu.joyp_mut(), event);
} }
crate::joypad::handle_keyboard_input(&mut emu.cpu.bus.joyp, key); joypad::handle_keyboard_input(emu.joyp_mut(), key);
while elapsed < CYCLES_IN_FRAME { while elapsed < CYCLES_IN_FRAME {
elapsed += emu.step(); elapsed += emu.step();
@ -31,7 +32,7 @@ pub fn run_frame(emu: &mut Emulator, gamepad: &mut Gilrs, key: &WinitInputHelper
} }
pub fn draw_frame(emu: &Emulator, buf: &mut [u8; GB_HEIGHT * GB_WIDTH * 4]) { pub fn draw_frame(emu: &Emulator, buf: &mut [u8; GB_HEIGHT * GB_WIDTH * 4]) {
buf.copy_from_slice(emu.cpu.bus.ppu.frame_buf.as_ref()); buf.copy_from_slice(emu.cpu.bus().ppu().frame_buf());
} }
pub struct Emulator { pub struct Emulator {
@ -80,20 +81,25 @@ impl Emulator {
} }
fn load_rom(&mut self, rom: Vec<u8>) { fn load_rom(&mut self, rom: Vec<u8>) {
self.cpu.bus.load_cart(rom); self.cpu.bus_mut().load_cart(rom);
}
#[inline]
fn joyp_mut(&mut self) -> &mut Joypad {
self.cpu.bus_mut().joyp_mut()
} }
pub fn set_prod(&mut self, prod: SampleProducer<f32>) { pub fn set_prod(&mut self, prod: SampleProducer<f32>) {
self.cpu.bus.apu_mut().attach_producer(prod) self.cpu.bus_mut().apu_mut().attach_producer(prod)
} }
pub fn title(&self) -> &str { pub fn title(&self) -> &str {
self.cpu.bus.cart_title().unwrap_or(DEFAULT_TITLE) self.cpu.bus().cart_title().unwrap_or(DEFAULT_TITLE)
} }
pub fn try_write_sav(&self) -> std::io::Result<()> { pub fn try_write_sav(&self) -> std::io::Result<()> {
if let Some(ext_ram) = self.cpu.bus.cart.as_ref().map(|c| c.ext_ram()).flatten() { if let Some(ext_ram) = self.cpu.bus().cart().map(|c| c.ext_ram()).flatten() {
if let Some(title) = self.cpu.bus.cart_title() { if let Some(title) = self.cpu.bus().cart_title() {
let mut save_path = Self::data_path().unwrap_or_else(|| PathBuf::from(".")); let mut save_path = Self::data_path().unwrap_or_else(|| PathBuf::from("."));
save_path.push(title); save_path.push(title);
save_path.set_extension("sav"); save_path.set_extension("sav");
@ -107,7 +113,7 @@ impl Emulator {
} }
pub fn try_load_sav(&mut self) -> std::io::Result<()> { pub fn try_load_sav(&mut self) -> std::io::Result<()> {
if let Some(cart) = &mut self.cpu.bus.cart { if let Some(cart) = self.cpu.bus_mut().cart_mut() {
if let Some(title) = cart.title() { if let Some(title) = cart.title() {
let mut save_path = Self::data_path().unwrap_or_else(|| PathBuf::from(".")); let mut save_path = Self::data_path().unwrap_or_else(|| PathBuf::from("."));
save_path.push(title); save_path.push(title);

View File

@ -48,7 +48,7 @@ pub struct Ppu {
fetch: PixelFetcher, fetch: PixelFetcher,
fifo: PixelFifo, fifo: PixelFifo,
obj_buffer: ObjectBuffer, obj_buffer: ObjectBuffer,
pub(crate) frame_buf: Box<[u8; GB_WIDTH * GB_HEIGHT * 4]>, frame_buf: Box<[u8; GB_WIDTH * GB_HEIGHT * 4]>,
win_stat: WindowStatus, win_stat: WindowStatus,
scanline_start: bool, scanline_start: bool,
@ -423,6 +423,11 @@ impl Ppu {
self.frame_buf.swap_with_slice(&mut blank); self.frame_buf.swap_with_slice(&mut blank);
} }
#[inline]
pub(crate) fn frame_buf(&self) -> &[u8; GB_HEIGHT * GB_WIDTH * 4] {
&self.frame_buf
}
fn clock_fifo(&mut self) -> Option<GrayShade> { fn clock_fifo(&mut self) -> Option<GrayShade> {
use RenderPriority::*; use RenderPriority::*;