Compare commits
No commits in common. "0ceba17139543b5a17db04136b6f69b82fdd7196" and "dccd00782b656e5a9eb7fd589f7ccf3260e5b13c" have entirely different histories.
0ceba17139
...
dccd00782b
|
@ -35,11 +35,6 @@ pub fn DmaController(comptime id: u2) type {
|
||||||
/// Internal. Word Count
|
/// Internal. Word Count
|
||||||
_word_count: if (id == 3) u16 else u14,
|
_word_count: if (id == 3) u16 else u14,
|
||||||
|
|
||||||
/// Some DMA Transfers are enabled during Hblank / VBlank and / or
|
|
||||||
/// have delays. Thefore bit 15 of DMACNT isn't actually something
|
|
||||||
/// we can use to control when we do or do not execute a step in a DMA Transfer
|
|
||||||
enabled: bool,
|
|
||||||
|
|
||||||
pub fn init() Self {
|
pub fn init() Self {
|
||||||
return .{
|
return .{
|
||||||
.id = id,
|
.id = id,
|
||||||
|
@ -52,7 +47,6 @@ pub fn DmaController(comptime id: u2) type {
|
||||||
._sad = 0,
|
._sad = 0,
|
||||||
._dad = 0,
|
._dad = 0,
|
||||||
._word_count = 0,
|
._word_count = 0,
|
||||||
.enabled = false,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,9 +70,6 @@ pub fn DmaController(comptime id: u2) type {
|
||||||
self._sad = self.sad;
|
self._sad = self.sad;
|
||||||
self._dad = self.dad;
|
self._dad = self.dad;
|
||||||
self._word_count = if (self.word_count == 0) std.math.maxInt(@TypeOf(self._word_count)) else self.word_count;
|
self._word_count = if (self.word_count == 0) std.math.maxInt(@TypeOf(self._word_count)) else self.word_count;
|
||||||
|
|
||||||
// Only a Start Timing of 00 has a DMA Transfer immediately begin
|
|
||||||
self.enabled = new.start_timing.read() == 0b00;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cnt.raw = halfword;
|
self.cnt.raw = halfword;
|
||||||
|
@ -89,9 +80,7 @@ pub fn DmaController(comptime id: u2) type {
|
||||||
self.writeCntHigh(@truncate(u16, word >> 16));
|
self.writeCntHigh(@truncate(u16, word >> 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(self: *Self, bus: *Bus) bool {
|
pub fn step(self: *Self, bus: *Bus) void {
|
||||||
if (!self.enabled or !self.cnt.enabled.read()) return false;
|
|
||||||
|
|
||||||
const sad_adj = std.meta.intToEnum(Adjustment, self.cnt.sad_adj.read()) catch unreachable;
|
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 dad_adj = std.meta.intToEnum(Adjustment, self.cnt.dad_adj.read()) catch unreachable;
|
||||||
|
|
||||||
|
@ -134,46 +123,14 @@ pub fn DmaController(comptime id: u2) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cnt.enabled.unset();
|
self.cnt.enabled.unset();
|
||||||
self.enabled = 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 {
|
|
||||||
if (self.enabled) return;
|
|
||||||
|
|
||||||
switch (kind) {
|
|
||||||
.HBlank => self.enabled = self.cnt.enabled.read() and self.cnt.start_timing.read() == 0b10,
|
|
||||||
.VBlank => self.enabled = self.cnt.enabled.read() and self.cnt.start_timing.read() == 0b01,
|
|
||||||
.Immediate, .Special => {},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pollBlankingDma(bus: *Bus, comptime kind: DmaKind) void {
|
|
||||||
bus.io.dma0.pollBlankingDma(kind);
|
|
||||||
bus.io.dma1.pollBlankingDma(kind);
|
|
||||||
bus.io.dma2.pollBlankingDma(kind);
|
|
||||||
bus.io.dma3.pollBlankingDma(kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Adjustment = enum(u2) {
|
const Adjustment = enum(u2) {
|
||||||
Increment = 0,
|
Increment = 0,
|
||||||
Decrement = 1,
|
Decrement = 1,
|
||||||
Fixed = 2,
|
Fixed = 2,
|
||||||
IncrementReload = 3,
|
IncrementReload = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
const DmaKind = enum(u2) {
|
|
||||||
Immediate = 0,
|
|
||||||
HBlank,
|
|
||||||
VBlank,
|
|
||||||
Special,
|
|
||||||
};
|
|
||||||
|
|
28
src/cpu.zig
28
src/cpu.zig
|
@ -296,10 +296,30 @@ pub const Arm7tdmi = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleDMATransfers(self: *Self) bool {
|
fn handleDMATransfers(self: *Self) bool {
|
||||||
if (self.bus.io.dma0.step(self.bus)) return self.bus.io.dma0.isBlocking();
|
const dma0 = &self.bus.io.dma0;
|
||||||
if (self.bus.io.dma1.step(self.bus)) return self.bus.io.dma1.isBlocking();
|
const dma1 = &self.bus.io.dma1;
|
||||||
if (self.bus.io.dma2.step(self.bus)) return self.bus.io.dma2.isBlocking();
|
const dma2 = &self.bus.io.dma2;
|
||||||
if (self.bus.io.dma3.step(self.bus)) return self.bus.io.dma3.isBlocking();
|
const dma3 = &self.bus.io.dma3;
|
||||||
|
|
||||||
|
if (dma0.cnt.enabled.read() and dma0.cnt.start_timing.read() == 0) {
|
||||||
|
dma0.step(self.bus);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma1.cnt.enabled.read() and dma1.cnt.start_timing.read() == 0) {
|
||||||
|
dma1.step(self.bus);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma2.cnt.enabled.read() and dma2.cnt.start_timing.read() == 0) {
|
||||||
|
dma2.step(self.bus);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma3.cnt.enabled.read() and dma3.cnt.start_timing.read() == 0) {
|
||||||
|
dma3.step(self.bus);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
25
src/ppu.zig
25
src/ppu.zig
|
@ -366,28 +366,3 @@ const ScreenEntry = extern union {
|
||||||
palette_bank: Bitfield(u16, 12, 4),
|
palette_bank: Bitfield(u16, 12, 4),
|
||||||
raw: u16,
|
raw: u16,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Attr0 = extern union {
|
|
||||||
y: Bitfield(u16, 0, 8),
|
|
||||||
rot_scaling: Bit(u16, 8), // This SBZ
|
|
||||||
disabled: Bit(u16, 9),
|
|
||||||
mode: Bitfield(u16, 10, 2),
|
|
||||||
mosaic: Bit(u16, 12),
|
|
||||||
is_8bpp: Bit(u16, 13),
|
|
||||||
shape: Bit(u16, 14, 2),
|
|
||||||
raw: u16,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Attr1 = extern union {
|
|
||||||
x: Bitfield(u16, 0, 9),
|
|
||||||
h_flip: Bit(u16, 12),
|
|
||||||
v_flip: Bit(u16, 13),
|
|
||||||
size: Bitfield(u16, 14, 2),
|
|
||||||
raw: u16,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Attr2 = extern union {
|
|
||||||
tile_id: Bitfield(u16, 0, 10),
|
|
||||||
rel_prio: Bitfield(u16, 10, 2),
|
|
||||||
pal_id: Bitfield(u16, 12, 3),
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const pollBlankingDma = @import("bus/dma.zig").pollBlankingDma;
|
|
||||||
|
|
||||||
const Bus = @import("Bus.zig");
|
const Bus = @import("Bus.zig");
|
||||||
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
||||||
|
|
||||||
|
@ -70,9 +68,6 @@ pub const Scheduler = struct {
|
||||||
irq.vblank.set();
|
irq.vblank.set();
|
||||||
cpu.handleInterrupt();
|
cpu.handleInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if Vblank DMA is present and not enabled
|
|
||||||
pollBlankingDma(bus, .VBlank);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scanline == 227) stat.vblank.unset();
|
if (scanline == 227) stat.vblank.unset();
|
||||||
|
@ -89,9 +84,6 @@ pub const Scheduler = struct {
|
||||||
cpu.handleInterrupt();
|
cpu.handleInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if Hblank DMA is present and not enabled
|
|
||||||
pollBlankingDma(bus, .HBlank);
|
|
||||||
|
|
||||||
bus.ppu.dispstat.hblank.set();
|
bus.ppu.dispstat.hblank.set();
|
||||||
self.push(.HBlank, self.tick + (68 * 4));
|
self.push(.HBlank, self.tick + (68 * 4));
|
||||||
},
|
},
|
||||||
|
@ -104,9 +96,6 @@ pub const Scheduler = struct {
|
||||||
cpu.handleInterrupt();
|
cpu.handleInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if Hblank DMA is present and not enabled
|
|
||||||
pollBlankingDma(bus, .HBlank);
|
|
||||||
|
|
||||||
bus.ppu.dispstat.hblank.set();
|
bus.ppu.dispstat.hblank.set();
|
||||||
self.push(.HBlank, self.tick + (68 * 4));
|
self.push(.HBlank, self.tick + (68 * 4));
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue