feat(dma): implement all dma i/o reads
This commit is contained in:
parent
3e62feacba
commit
268961262d
|
@ -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"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
11
src/util.zig
11
src/util.zig
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue