diff --git a/src/Bus.zig b/src/Bus.zig index 47bc644..533d1e5 100644 --- a/src/Bus.zig +++ b/src/Bus.zig @@ -64,16 +64,7 @@ pub fn attach(self: *Self, cpu: *Arm7tdmi) void { self.cpu = cpu; } -pub fn handleDMATransfers(self: *Self) void { - while (self.isDmaRunning()) { - if (self.dma[1].step(self)) continue; - if (self.dma[0].step(self)) continue; - if (self.dma[2].step(self)) continue; - if (self.dma[3].step(self)) continue; - } -} - -inline fn isDmaRunning(self: *const Self) bool { +pub inline fn isDmaRunning(self: *const Self) bool { return self.dma[0].active or self.dma[1].active or self.dma[2].active or diff --git a/src/bus/dma.zig b/src/bus/dma.zig index 565a569..a38a49c 100644 --- a/src/bus/dma.zig +++ b/src/bus/dma.zig @@ -2,6 +2,7 @@ const std = @import("std"); const DmaControl = @import("io.zig").DmaControl; const Bus = @import("../Bus.zig"); +const Arm7tdmi = @import("../cpu.zig").Arm7tdmi; pub const DmaTuple = std.meta.Tuple(&[_]type{ DmaController(0), DmaController(1), DmaController(2), DmaController(3) }); const log = std.log.scoped(.DmaTransfer); @@ -98,44 +99,20 @@ fn DmaController(comptime id: u2) type { self.writeCntHigh(@truncate(u16, word >> 16)); } - pub fn step(self: *Self, bus: *Bus) bool { + pub fn step(self: *Self, cpu: *Arm7tdmi) bool { if (!self.active) return false; const sad_adj = std.meta.intToEnum(Adjustment, self.cnt.sad_adj.read()) catch unreachable; const dad_adj = std.meta.intToEnum(Adjustment, self.cnt.dad_adj.read()) catch unreachable; const is_fifo = (self.id == 1 or self.id == 2) and self.cnt.start_timing.read() == 0b11; - // // if (is_fifo) { - // // const offset = @sizeOf(u32); - // // bus.write(u32, self._dad, bus.read(u32, self._sad)); - - // // // TODO: Deduplicate - // // switch (sad_adj) { - // // .Increment => self._sad +%= offset, - // // .Decrement => self._sad -%= offset, - // // .Fixed => {}, - - // // // TODO: Figure out correct behaviour on Illegal Source Addr Control Type - // // .IncrementReload => std.debug.panic("panic(DmaTransfer): {} is an illegal src addr adjustment type", .{sad_adj}), - // // } - - // // self._fifo_word_count -= 1; - - // // if (self._fifo_word_count == 0) { - // // self._fifo_word_count = 4; - // // self.active = false; - // // } - - // // return true; - // // } - const transfer_type = self.cnt.transfer_type.read() or is_fifo; const offset: u32 = if (transfer_type) @sizeOf(u32) else @sizeOf(u16); if (transfer_type) { - bus.write(u32, self._dad, bus.read(u32, self._sad)); + cpu.bus.write(u32, self._dad, cpu.bus.read(u32, self._sad)); } else { - bus.write(u16, self._dad, bus.read(u16, self._sad)); + cpu.bus.write(u16, self._dad, cpu.bus.read(u16, self._sad)); } switch (sad_adj) { @@ -162,12 +139,15 @@ fn DmaController(comptime id: u2) type { // If we're not repeating, Fire the IRQs and disable the DMA if (self.cnt.irq.read()) { switch (id) { - 0 => bus.io.irq.dma0.set(), - 1 => bus.io.irq.dma0.set(), - 2 => bus.io.irq.dma0.set(), - 3 => bus.io.irq.dma0.set(), + 0 => cpu.bus.io.irq.dma0.set(), + 1 => cpu.bus.io.irq.dma0.set(), + 2 => cpu.bus.io.irq.dma0.set(), + 3 => cpu.bus.io.irq.dma0.set(), } + + cpu.handleInterrupt(); } + self.cnt.enabled.unset(); } diff --git a/src/cpu.zig b/src/cpu.zig index e75253d..fb79db2 100644 --- a/src/cpu.zig +++ b/src/cpu.zig @@ -267,6 +267,15 @@ pub const Arm7tdmi = struct { } } + pub fn handleDMATransfers(self: *Self) void { + while (self.bus.isDmaRunning()) { + if (self.bus.dma[1].step(self)) continue; + if (self.bus.dma[0].step(self)) continue; + if (self.bus.dma[2].step(self)) continue; + if (self.bus.dma[3].step(self)) continue; + } + } + pub fn handleInterrupt(self: *Self) void { const should_handle = self.bus.io.ie.raw & self.bus.io.irq.raw; diff --git a/src/emu.zig b/src/emu.zig index 64f3dd0..7ec4841 100644 --- a/src/emu.zig +++ b/src/emu.zig @@ -48,7 +48,7 @@ pub fn runFrame(sched: *Scheduler, cpu: *Arm7tdmi) void { while (sched.tick < frame_end) { if (cpu.bus.io.haltcnt == .Halt) sched.tick += 1; if (cpu.bus.io.haltcnt == .Execute) cpu.step(); - cpu.bus.handleDMATransfers(); + cpu.handleDMATransfers(); while (sched.tick >= sched.nextTimestamp()) { sched.handleEvent(cpu);