From c8585a6f9aa6a7904295917d78921372529223c2 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Fri, 21 Oct 2022 05:12:50 -0300 Subject: [PATCH] fix: reimplement DMA ticking --- src/Bus.zig | 7 ------- src/bus/dma.zig | 11 +---------- src/cpu.zig | 32 ++++++++++++++++++++++++++------ src/emu.zig | 2 +- 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/Bus.zig b/src/Bus.zig index aa456da..d678170 100644 --- a/src/Bus.zig +++ b/src/Bus.zig @@ -64,13 +64,6 @@ pub fn attach(self: *Self, cpu: *Arm7tdmi) void { self.cpu = cpu; } -pub inline fn isDmaRunning(self: *const Self) bool { - return self.dma[0].active or - self.dma[1].active or - self.dma[2].active or - self.dma[3].active; -} - pub fn debugRead(self: *const Self, comptime T: type, address: u32) T { const cached = self.sched.tick; defer self.sched.tick = cached; diff --git a/src/bus/dma.zig b/src/bus/dma.zig index 3b3e7b0..9816988 100644 --- a/src/bus/dma.zig +++ b/src/bus/dma.zig @@ -178,9 +178,7 @@ fn DmaController(comptime id: u2) type { self.setCntH(@truncate(u16, word >> 16)); } - pub fn step(self: *Self, cpu: *Arm7tdmi) bool { - if (!self.active) return false; - + pub fn step(self: *Self, cpu: *Arm7tdmi) void { const is_fifo = (self.id == 1 or self.id == 2) and self.cnt.start_timing.read() == 0b11; const sad_adj = Self.adjustment(self.cnt.sad_adj.read()); const dad_adj = if (is_fifo) .Fixed else Self.adjustment(self.cnt.dad_adj.read()); @@ -232,13 +230,6 @@ fn DmaController(comptime id: u2) type { // timing window self.active = false; } - - return true; - } - - pub fn isBlocking(self: *const Self) bool { - // A DMA Transfer is Blocking if it is Immediate - return self.cnt.start_timing.read() == 0b00; } pub fn pollBlankingDma(self: *Self, comptime kind: DmaKind) void { diff --git a/src/cpu.zig b/src/cpu.zig index 98a5bb2..a61042a 100644 --- a/src/cpu.zig +++ b/src/cpu.zig @@ -271,13 +271,33 @@ pub const Arm7tdmi = struct { } } - pub fn handleDMATransfers(self: *Self) void { - while (self.bus.isDmaRunning()) { - if (self.bus.dma[0].step(self)) continue; - if (self.bus.dma[1].step(self)) continue; - if (self.bus.dma[2].step(self)) continue; - if (self.bus.dma[3].step(self)) continue; + pub fn stepDmaTransfer(self: *Self) bool { + const dma0 = &self.bus.dma[0]; + const dma1 = &self.bus.dma[1]; + const dma2 = &self.bus.dma[2]; + const dma3 = &self.bus.dma[3]; + + if (dma0.active) { + dma0.step(self); + return true; } + + if (dma1.active) { + dma1.step(self); + return true; + } + + if (dma2.active) { + dma2.step(self); + return true; + } + + if (dma3.active) { + dma3.step(self); + return true; + } + + return false; } pub fn handleInterrupt(self: *Self) void { diff --git a/src/emu.zig b/src/emu.zig index e963b25..ec0c092 100644 --- a/src/emu.zig +++ b/src/emu.zig @@ -52,8 +52,8 @@ pub fn runFrame(sched: *Scheduler, cpu: *Arm7tdmi) void { while (true) { while (sched.tick < std.math.min(frame_end, sched.nextTimestamp())) { + if (cpu.stepDmaTransfer()) continue; // DMA is blocking, ticks scheduler if (!cpu.isHalted()) cpu.step() else sched.tick += 1; - cpu.handleDMATransfers(); } if (sched.tick >= frame_end) break;