fix: reimplement DMA ticking
This commit is contained in:
parent
dba8873f76
commit
f5e401a4ee
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
32
src/cpu.zig
32
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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue