feat(dma): implement all dma i/o reads

This commit is contained in:
Rekai Nyangadzayi Musuka 2022-10-29 01:30:12 -03:00
parent 3e62feacba
commit 268961262d
3 changed files with 34 additions and 14 deletions

View File

@ -10,6 +10,7 @@ const log = std.log.scoped(.DmaTransfer);
const setHi = util.setHi; const setHi = util.setHi;
const setLo = util.setLo; const setLo = util.setLo;
const shift = util.shift;
const rotr = @import("../../util.zig").rotr; const rotr = @import("../../util.zig").rotr;
@ -22,20 +23,38 @@ pub fn read(comptime T: type, dma: *const DmaTuple, addr: u32) ?T {
return switch (T) { return switch (T) {
u32 => switch (byte) { u32 => switch (byte) {
0xB8 => @as(T, dma.*[0].cnt.raw) << 16, 0xB0, 0xB4 => null, // DMA0SAD, DMA0DAD,
0xC4 => @as(T, dma.*[1].cnt.raw) << 16, 0xB8 => @as(T, dma.*[0].cnt.raw) << 16, // DMA0CNT_L is write-only
0xD0 => @as(T, dma.*[2].cnt.raw) << 16, 0xBC, 0xC0 => null, // DMA1SAD, DMA1DAD
0xDC => @as(T, dma.*[3].cnt.raw) << 16, 0xC4 => @as(T, dma.*[1].cnt.raw) << 16, // DMA1CNT_L is write-only
0xC8, 0xCC => null, // DMA2SAD, DMA2DAD
0xD0 => @as(T, dma.*[2].cnt.raw) << 16, // DMA2CNT_L is write-only
0xD4, 0xD8 => null, // DMA3SAD, DMA3DAD
0xDC => @as(T, dma.*[3].cnt.raw) << 16, // DMA3CNT_L is write-only
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, addr }), else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, addr }),
}, },
u16 => switch (byte) { u16 => switch (byte) {
0xB0...0xB8 => null, // DMA0SAD, DMA0DAD, DMA0CNT_L
0xBA => dma.*[0].cnt.raw, 0xBA => dma.*[0].cnt.raw,
0xBC...0xC4 => null, // DMA1SAD, DMA1DAD, DMA1CNT_L
0xC6 => dma.*[1].cnt.raw, 0xC6 => dma.*[1].cnt.raw,
0xC8...0xD0 => null, // DMA2SAD, DMA2DAD, DMA2CNT_L
0xD2 => dma.*[2].cnt.raw, 0xD2 => dma.*[2].cnt.raw,
0xD4...0xDC => null, // DMA3SAD, DMA3DAD, DMA3CNT_L
0xDE => dma.*[3].cnt.raw, 0xDE => dma.*[3].cnt.raw,
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, addr }), else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, addr }),
}, },
u8 => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, addr }), u8 => switch (byte) {
0xB0...0xB9 => null, // DMA0SAD, DMA0DAD, DMA0CNT_L
0xBA...0xBB => @truncate(T, dma.*[0].cnt.raw >> shift(byte)),
0xBC...0xC5 => null, // DMA1SAD, DMA1DAD, DMA1CNT_L
0xC6...0xC7 => @truncate(T, dma.*[1].cnt.raw >> shift(byte)),
0xC8...0xD1 => null, // DMA2SAD, DMA2DAD, DMA2CNT_L
0xD2...0xD3 => @truncate(T, dma.*[2].cnt.raw >> shift(byte)),
0xD4...0xDD => null, // DMA3SAD, DMA3DAD, DMA3CNT_L
0xDE...0xDF => @truncate(T, dma.*[3].cnt.raw >> shift(byte)),
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, addr }),
},
else => @compileError("DMA: Unsupported read width"), else => @compileError("DMA: Unsupported read width"),
}; };
} }

View File

@ -13,6 +13,7 @@ const log = std.log.scoped(.PPU);
const setHi = util.setHi; const setHi = util.setHi;
const setLo = util.setLo; const setLo = util.setLo;
const shift = util.shift;
const pollDmaOnBlank = @import("bus/dma.zig").pollDmaOnBlank; const pollDmaOnBlank = @import("bus/dma.zig").pollDmaOnBlank;
pub const width = 240; pub const width = 240;
@ -81,13 +82,6 @@ pub fn read(comptime T: type, ppu: *const Ppu, addr: u32) ?T {
}; };
} }
/// Calculates the correct shift offset for an aligned/unaligned u8 read
///
/// TODO: Rename this
inline fn shift(byte: u8) u4 {
return @truncate(u4, byte & 1) << 3;
}
pub fn write(comptime T: type, ppu: *Ppu, addr: u32, value: T) void { pub fn write(comptime T: type, ppu: *Ppu, addr: u32, value: T) void {
const byte = @truncate(u8, addr); // prefixed with 0x0400_00 const byte = @truncate(u8, addr); // prefixed with 0x0400_00

View File

@ -12,9 +12,9 @@ pub fn sext(comptime T: type, comptime U: type, value: T) T {
const iT = std.meta.Int(.signed, @typeInfo(T).Int.bits); const iT = std.meta.Int(.signed, @typeInfo(T).Int.bits);
const ExtU = if (@typeInfo(U).Int.signedness == .unsigned) T else iT; const ExtU = if (@typeInfo(U).Int.signedness == .unsigned) T else iT;
const shift = @intCast(Log2Int(T), @typeInfo(T).Int.bits - @typeInfo(U).Int.bits); const shift_amt = @intCast(Log2Int(T), @typeInfo(T).Int.bits - @typeInfo(U).Int.bits);
return @bitCast(T, @bitCast(iT, @as(ExtU, @truncate(U, value)) << shift) >> shift); return @bitCast(T, @bitCast(iT, @as(ExtU, @truncate(U, value)) << shift_amt) >> shift_amt);
} }
/// See https://godbolt.org/z/W3en9Eche /// See https://godbolt.org/z/W3en9Eche
@ -276,6 +276,13 @@ pub const audio = struct {
}; };
}; };
/// Calculates the correct shift offset for an aligned/unaligned u8 read
///
/// TODO: Rename this
pub inline fn shift(byte: u8) u4 {
return @truncate(u4, byte & 1) << 3;
}
/// Sets the high bits of an integer to a value /// Sets the high bits of an integer to a value
pub inline fn setLo(comptime T: type, left: T, right: HalfInt(T)) T { pub inline fn setLo(comptime T: type, left: T, right: HalfInt(T)) T {
return switch (T) { return switch (T) {