diff --git a/src/cpu.rs b/src/cpu.rs index ba60309df8aa7978a605b6e61a7a145f9dd2f8ca..39bb3c0166ab8b16101557d52d8c592ed92a52a4 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -3,6 +3,7 @@ use std::{cell::RefCell, rc::Rc}; use crate::{ apu::Apu, debugln, + dma::Dma, gb::GameBoyConfig, inst::{EXTENDED, INSTRUCTIONS}, mmu::Mmu, @@ -334,6 +335,16 @@ impl Cpu { self.mmu_i().apu_i() } + #[inline(always)] + pub fn dma(&mut self) -> &mut Dma { + self.mmu().dma() + } + + #[inline(always)] + pub fn dma_i(&self) -> &Dma { + self.mmu_i().dma_i() + } + #[inline(always)] pub fn pad(&mut self) -> &mut Pad { self.mmu().pad() diff --git a/src/dma.rs b/src/dma.rs new file mode 100644 index 0000000000000000000000000000000000000000..9f6d014ca38a3c1281c9bb2d0bb5d31d60be2a67 --- /dev/null +++ b/src/dma.rs @@ -0,0 +1,17 @@ +pub struct Dma {} + +impl Dma { + pub fn new() -> Self { + Self {} + } + + pub fn reset(&mut self) {} + + pub fn clock(&mut self, cycles: u8) {} +} + +impl Default for Dma { + fn default() -> Self { + Self::new() + } +} diff --git a/src/gb.rs b/src/gb.rs index 9be41c408a550be3156c9de614200801fc38eaa8..9de814b63f4935e0f118327f3a68b2f2b2e37eea 100644 --- a/src/gb.rs +++ b/src/gb.rs @@ -10,6 +10,7 @@ use crate::{ cpu::Cpu, data::{BootRom, CGB_BOOT, DMG_BOOT, DMG_BOOTIX, MGB_BOOTIX, SGB_BOOT}, devices::{printer::PrinterDevice, stdout::StdoutDevice}, + dma::Dma, gen::{COMPILATION_DATE, COMPILATION_TIME, COMPILER, COMPILER_VERSION, VERSION}, mmu::Mmu, pad::{Pad, PadKey}, @@ -133,6 +134,9 @@ pub struct GameBoyConfig { /// If the APU is enabled, it will be clocked. apu_enabled: bool, + /// if the DMA is enabled, it will be clocked. + dma_enabled: bool, + /// If the timer is enabled, it will be clocked. timer_enabled: bool, @@ -186,6 +190,14 @@ impl GameBoyConfig { self.apu_enabled = value; } + pub fn dma_enabled(&self) -> bool { + self.dma_enabled + } + + pub fn set_dma_enabled(&mut self, value: bool) { + self.dma_enabled = value; + } + pub fn timer_enabled(&self) -> bool { self.timer_enabled } @@ -217,6 +229,7 @@ impl Default for GameBoyConfig { mode: GameBoyMode::Dmg, ppu_enabled: true, apu_enabled: true, + dma_enabled: true, timer_enabled: true, serial_enabled: true, clock_freq: GameBoy::CPU_FREQ, @@ -246,6 +259,11 @@ pub struct GameBoy { /// kept for performance reasons. apu_enabled: bool, + /// If the DMA is enabled, it will be clocked. + /// This is a clone of the configuration value + /// kept for performance reasons. + dma_enabled: bool, + /// If the timer is enabled, it will be clocked. /// This is a clone of the configuration value /// kept for performance reasons. @@ -314,6 +332,7 @@ impl GameBoy { mode, ppu_enabled: true, apu_enabled: true, + dma_enabled: true, timer_enabled: true, serial_enabled: true, clock_freq: GameBoy::CPU_FREQ, @@ -321,16 +340,18 @@ impl GameBoy { let ppu = Ppu::new(mode, gbc.clone()); let apu = Apu::default(); + let dma = Dma::default(); let pad = Pad::default(); let timer = Timer::default(); let serial = Serial::default(); - let mmu = Mmu::new(ppu, apu, pad, timer, serial, mode, gbc.clone()); + let mmu = Mmu::new(ppu, apu, dma, pad, timer, serial, mode, gbc.clone()); let cpu = Cpu::new(mmu, gbc.clone()); Self { mode, ppu_enabled: true, apu_enabled: true, + dma_enabled: true, timer_enabled: true, serial_enabled: true, clock_freq: GameBoy::CPU_FREQ, @@ -356,6 +377,9 @@ impl GameBoy { if self.apu_enabled { self.apu_clock(cycles); } + if self.dma_enabled { + self.dma_clock(cycles); + } if self.timer_enabled { self.timer_clock(cycles); } @@ -385,6 +409,10 @@ impl GameBoy { self.apu().clock(cycles) } + pub fn dma_clock(&mut self, cycles: u8) { + self.dma().clock(cycles) + } + pub fn timer_clock(&mut self, cycles: u8) { self.timer().clock(cycles) } @@ -735,6 +763,14 @@ impl GameBoy { self.cpu.apu_i() } + pub fn dma(&mut self) -> &mut Dma { + self.cpu.dma() + } + + pub fn dma_i(&self) -> &Dma { + self.cpu.dma_i() + } + pub fn pad(&mut self) -> &mut Pad { self.cpu.pad() } diff --git a/src/lib.rs b/src/lib.rs index 80f4f5b8e995c1081e8319a0c9b396a73503375a..d25f5ac6f5082c43cfa6f03b76f2f88425e7bef6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ pub mod apu; pub mod cpu; pub mod data; pub mod devices; +pub mod dma; pub mod gb; pub mod gen; pub mod inst; diff --git a/src/mmu.rs b/src/mmu.rs index c6a0eea171f475bbe224711e8c46841ac47fa6b8..6b7ebe86cb995120b7984992a50aedf907e6d711 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -3,6 +3,7 @@ use std::{cell::RefCell, rc::Rc}; use crate::{ apu::Apu, debugln, + dma::Dma, gb::{GameBoyConfig, GameBoyMode, GameBoySpeed}, pad::Pad, ppu::Ppu, @@ -44,6 +45,11 @@ pub struct Mmu { /// some of the access operations. apu: Apu, + /// Reference to the DMA (Direct Memory Access) controller that is going + /// to be used for quick and CPU offloaded memory transfers. + /// There are multiple execution modes for the DMA. + dma: Dma, + /// Reference to the Gamepad structure that is going to control /// the I/O access to this device. pad: Pad, @@ -95,6 +101,7 @@ impl Mmu { pub fn new( ppu: Ppu, apu: Apu, + dma: Dma, pad: Pad, timer: Timer, serial: Serial, @@ -104,6 +111,7 @@ impl Mmu { Self { ppu, apu, + dma, pad, timer, serial, @@ -161,6 +169,14 @@ impl Mmu { &self.apu } + pub fn dma(&mut self) -> &mut Dma { + &mut self.dma + } + + pub fn dma_i(&self) -> &Dma { + &self.dma + } + pub fn pad(&mut self) -> &mut Pad { &mut self.pad }