diff --git a/src/bus.rs b/src/bus.rs index 19b7160..05e8237 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -43,6 +43,9 @@ pub struct Bus { /// TODO: This should actually not be usuable unusable_ram: [u8; UNUSABLE_RAM_SIZE], + + /// Gets true when the user writes to OAM DMA register + pub(crate) needs_to_dispatch_oam_dma: bool, } #[rustfmt::skip] @@ -90,6 +93,7 @@ impl Bus { unusable_ram: [0u8; UNUSABLE_RAM_SIZE], video_ram: [0u8; VIDEO_RAM_SIZE], work_ram: [0u8; WORK_RAM_SIZE], + needs_to_dispatch_oam_dma: false, }) } @@ -105,6 +109,7 @@ impl Bus { unusable_ram: [0u8; UNUSABLE_RAM_SIZE], video_ram: [0u8; VIDEO_RAM_SIZE], work_ram: [0u8; WORK_RAM_SIZE], + needs_to_dispatch_oam_dma: false, } } } @@ -139,7 +144,13 @@ impl core::ops::IndexMut for Bus { 0xE000..=0xFDFF => &mut self.work_ram[(address - 0xE000) as usize], 0xFE00..=0xFE9F => &mut self.eom[(address - 0xFE00) as usize], 0xFEA0..=0xFEFF => &mut self.unusable_ram[(address - 0xFEA0) as usize], - 0xFF00..=0xFF7F => &mut self.io[(address - IO_START as u16) as usize], + 0xFF00..=0xFF7F => { + if address == DMA { + self.needs_to_dispatch_oam_dma = true; + } + + &mut self.io[(address - IO_START as u16) as usize] + } 0xFF80..=0xFFFE => &mut self.high_ram[(address - 0xFF80) as usize], 0xFFFF => &mut self.ie, } @@ -162,3 +173,15 @@ impl Bus { merge_two_u8s_into_u16(self.next(2, registers), self.next(1, registers)) } } + +impl Bus { + pub(crate) fn dispatch_oam_transfer(&mut self) { + let oam_dma_start = (self[DMA] as u16) << 8; + let oam_dma_end = oam_dma_start | 0x9F; + let difference = oam_dma_end - oam_dma_start; + + for i in 0..difference { + self[0xFE00 + i] = self[oam_dma_start + i]; + } + } +} diff --git a/src/consts.rs b/src/consts.rs index 40c9dac..e8dac89 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -8,6 +8,7 @@ pub mod bus { pub const WORK_RAM_SIZE: usize = 8192; pub const EXTERNAL_RAM_SIZE: usize = 8192; pub const UNUSABLE_RAM_SIZE: usize = 96; + pub const DMA: u16 = 0xFF46; } pub mod gpu { diff --git a/src/lib.rs b/src/lib.rs index 678b00b..fbb2d7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,6 +83,12 @@ impl GameBoy { self.cpu .execute_interrupts(&self.gpu, &mut self.registers, &mut self.bus); + // CPU - OAM DMA Transfer + if self.bus.needs_to_dispatch_oam_dma { + self.bus.dispatch_oam_transfer(); + self.bus.needs_to_dispatch_oam_dma = false; + } + // GPU for _ in 0..(cycles * 4) { // A GPU tick is 1/4 of a cycle, so it needs to be called 4 times for every