diff --git a/src/apu.rs b/src/apu.rs index 711e8115e28c80dce8d5af0a479e240ae51372dd..030299b01aa215df4d14c401ae37662a3c6ef3aa 100644 --- a/src/apu.rs +++ b/src/apu.rs @@ -1,6 +1,6 @@ use std::collections::VecDeque; -use crate::{gb::GameBoy, warnln}; +use crate::{gb::GameBoy, mmu::BusComponent, warnln}; const DUTY_TABLE: [[u8; 8]; 4] = [ [0, 0, 0, 0, 0, 0, 0, 1], @@ -1076,6 +1076,16 @@ impl Apu { } } +impl BusComponent for Apu { + fn read(&mut self, addr: u16) -> u8 { + self.read(addr) + } + + fn write(&mut self, addr: u16, value: u8) { + self.write(addr, value); + } +} + impl Default for Apu { fn default() -> Self { Self::new(44100, 2, 1.0, GameBoy::CPU_FREQ) diff --git a/src/dma.rs b/src/dma.rs index f3110d26c39a801e86bc8c55356992e0d80cfb88..634cfa301e2dda7e6de8a916a33b34a67c471f79 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -1,5 +1,6 @@ use crate::{ consts::{DMA_ADDR, HDMA1_ADDR, HDMA2_ADDR, HDMA3_ADDR, HDMA4_ADDR, HDMA5_ADDR}, + mmu::BusComponent, warnln, }; @@ -173,6 +174,16 @@ impl Dma { } } +impl BusComponent for Dma { + fn read(&mut self, addr: u16) -> u8 { + self.read(addr) + } + + fn write(&mut self, addr: u16, value: u8) { + self.write(addr, value); + } +} + impl Default for Dma { fn default() -> Self { Self::new() diff --git a/src/mmu.rs b/src/mmu.rs index 3a7c5edfc1126594e83a1c192042e09e0a4e6adb..350abcf7aa5ab34264555a4caec7389b6a1cb835 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -21,6 +21,21 @@ pub const BOOT_SIZE_CGB: usize = 2304; pub const RAM_SIZE_DMG: usize = 8192; pub const RAM_SIZE_CGB: usize = 32768; +pub trait BusComponent { + fn read(&mut self, addr: u16) -> u8; + fn write(&mut self, addr: u16, value: u8); + fn read_many(&mut self, addr: u16, count: usize) -> Vec<u8> { + (0..count) + .map(|offset| self.read(addr + offset as u16)) + .collect() + } + fn write_many(&mut self, addr: u16, values: &[u8]) { + for (offset, &value) in values.iter().enumerate() { + self.write(addr + offset as u16, value); + } + } +} + pub struct Mmu { /// Register that controls the interrupts that are considered /// to be enabled and should be triggered. diff --git a/src/pad.rs b/src/pad.rs index be3a94b697d1fb55c11e3ad0a9360a99453a9a42..37cb34fc6a7751e9e9bbd3e282825e368d1b1883 100644 --- a/src/pad.rs +++ b/src/pad.rs @@ -1,6 +1,6 @@ //! Gamepad related functions and structures. -use crate::warnln; +use crate::{mmu::BusComponent, warnln}; #[cfg(feature = "wasm")] use wasm_bindgen::prelude::*; @@ -167,6 +167,16 @@ impl Pad { } } +impl BusComponent for Pad { + fn read(&mut self, addr: u16) -> u8 { + self.read(addr) + } + + fn write(&mut self, addr: u16, value: u8) { + self.write(addr, value); + } +} + impl Default for Pad { fn default() -> Self { Self::new() diff --git a/src/ppu.rs b/src/ppu.rs index 196618bd08cfd8920df29f93df7cbb7022f81b86..bd1d06b10df74c902a56b4a319038a770efa9bc2 100644 --- a/src/ppu.rs +++ b/src/ppu.rs @@ -11,6 +11,7 @@ use std::{ use crate::{ gb::{GameBoyConfig, GameBoyMode}, + mmu::BusComponent, util::SharedThread, warnln, }; @@ -2091,6 +2092,16 @@ impl Ppu { } } +impl BusComponent for Ppu { + fn read(&mut self, addr: u16) -> u8 { + self.read(addr) + } + + fn write(&mut self, addr: u16, value: u8) { + self.write(addr, value); + } +} + impl Default for Ppu { fn default() -> Self { Self::new( diff --git a/src/rom.rs b/src/rom.rs index c5fb6c86a7064aa863f258a4a8088c58501d28b1..541ef6a106054249246d58133943b935e4bbfb41 100644 --- a/src/rom.rs +++ b/src/rom.rs @@ -10,6 +10,7 @@ use crate::{ debugln, error::Error, gb::GameBoyMode, + mmu::BusComponent, util::read_file, warnln, }; @@ -370,7 +371,7 @@ impl Cartridge { Self::from_data(&data) } - pub fn read(&self, addr: u16) -> u8 { + pub fn read(&mut self, addr: u16) -> u8 { match addr & 0xf000 { 0x0000 | 0x1000 | 0x2000 | 0x3000 | 0x4000 | 0x5000 | 0x6000 | 0x7000 => { (self.handler.read_rom)(self, addr) @@ -823,6 +824,16 @@ impl Cartridge { } } +impl BusComponent for Cartridge { + fn read(&mut self, addr: u16) -> u8 { + self.read(addr) + } + + fn write(&mut self, addr: u16, value: u8) { + self.write(addr, value); + } +} + impl Default for Cartridge { fn default() -> Self { Self::new() diff --git a/src/serial.rs b/src/serial.rs index 4147e1b1af711df47a6930a4324248c529f2ac59..786e63ad6ba3c40e437c174befe298712a52b103 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -1,4 +1,4 @@ -use crate::warnln; +use crate::{mmu::BusComponent, warnln}; pub trait SerialDevice { /// Sends a byte (u8) to the attached serial connection. @@ -202,6 +202,16 @@ impl Serial { } } +impl BusComponent for Serial { + fn read(&mut self, addr: u16) -> u8 { + self.read(addr) + } + + fn write(&mut self, addr: u16, value: u8) { + self.write(addr, value); + } +} + impl Default for Serial { fn default() -> Self { Self::new() diff --git a/src/timer.rs b/src/timer.rs index 057cdeb97ead5025f48715710bfdf1af79624811..311c43706b57fac85b4fd556c04854504b8b61ce 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -1,5 +1,6 @@ use crate::{ consts::{DIV_ADDR, TAC_ADDR, TIMA_ADDR, TMA_ADDR}, + mmu::BusComponent, warnln, }; @@ -147,6 +148,16 @@ impl Timer { } } +impl BusComponent for Timer { + fn read(&mut self, addr: u16) -> u8 { + self.read(addr) + } + + fn write(&mut self, addr: u16, value: u8) { + self.write(addr, value); + } +} + impl Default for Timer { fn default() -> Self { Self::new()