Skip to content

Commit

Permalink
fix: support for pending number of bytes in DMA transfer
Browse files Browse the repository at this point in the history
This is a way of controlling the bytes that have already been written by the DMA controller.
  • Loading branch information
joamag committed Feb 25, 2024
1 parent 88d80ff commit 999f66d
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 2 deletions.
16 changes: 15 additions & 1 deletion src/dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct Dma {
source: u16,
destination: u16,
length: u16,
pending: u16,
mode: DmaMode,
active: bool,
}
Expand All @@ -23,6 +24,7 @@ impl Dma {
source: 0x0,
destination: 0x0,
length: 0x0,
pending: 0x0,
mode: DmaMode::General,
active: false,
}
Expand All @@ -32,6 +34,7 @@ impl Dma {
self.source = 0x0;
self.destination = 0x0;
self.length = 0x0;
self.pending = 0x0;
self.mode = DmaMode::General;
self.active = false;
}
Expand All @@ -41,7 +44,7 @@ impl Dma {
pub fn read(&mut self, addr: u16) -> u8 {
match addr {
// 0xFF55 — HDMA5: VRAM DMA length/mode/start (CGB only)
HDMA5_ADDR => ((self.length >> 4) - 1) as u8 | ((self.active as u8) << 7),
HDMA5_ADDR => ((self.pending >> 4) as u8).wrapping_sub(1) | ((!self.active as u8) << 7),
_ => {
warnln!("Reading from unknown DMA location 0x{:04x}", addr);
0xff
Expand All @@ -67,6 +70,7 @@ impl Dma {
1 => DmaMode::HBlank,
_ => DmaMode::General,
};
self.pending = self.length;
self.active = true;
}
_ => warnln!("Writing to unknown DMA location 0x{:04x}", addr),
Expand Down Expand Up @@ -97,6 +101,14 @@ impl Dma {
self.length = value;
}

pub fn pending(&self) -> u16 {
self.pending
}

pub fn set_pending(&mut self, value: u16) {
self.pending = value;
}

pub fn mode(&self) -> DmaMode {
self.mode
}
Expand Down Expand Up @@ -136,6 +148,7 @@ mod tests {
dma.source = 0x1234;
dma.destination = 0x5678;
dma.length = 0x9abc;
dma.pending = 0x9abc;
dma.mode = DmaMode::HBlank;
dma.active = true;

Expand All @@ -144,6 +157,7 @@ mod tests {
assert_eq!(dma.source, 0x0);
assert_eq!(dma.destination, 0x0);
assert_eq!(dma.length, 0x0);
assert_eq!(dma.pending, 0x0);
assert_eq!(dma.mode, DmaMode::General);
assert!(!dma.active);
}
Expand Down
3 changes: 2 additions & 1 deletion src/mmu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,10 @@ impl Mmu {
// this avoids issues when writing to DMG unmapped registers
// that would otherwise cause the system to crash
if self.mode == GameBoyMode::Cgb {
let data = self.read_many(self.dma.source(), self.dma.length());
let data = self.read_many(self.dma.source(), self.dma.pending());
self.write_many(self.dma.destination(), &data);
}
self.dma.set_pending(0);
self.dma.set_active(false);
}

Expand Down

0 comments on commit 999f66d

Please sign in to comment.