From 268961262ddee506c554515792fa9716497a6b89 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Sat, 29 Oct 2022 01:30:12 -0300 Subject: [PATCH] feat(dma): implement all dma i/o reads --- src/core/bus/dma.zig | 29 ++++++++++++++++++++++++----- src/core/ppu.zig | 8 +------- src/util.zig | 11 +++++++++-- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/core/bus/dma.zig b/src/core/bus/dma.zig index a0404df..97b86d7 100644 --- a/src/core/bus/dma.zig +++ b/src/core/bus/dma.zig @@ -10,6 +10,7 @@ const log = std.log.scoped(.DmaTransfer); const setHi = util.setHi; const setLo = util.setLo; +const shift = util.shift; 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) { u32 => switch (byte) { - 0xB8 => @as(T, dma.*[0].cnt.raw) << 16, - 0xC4 => @as(T, dma.*[1].cnt.raw) << 16, - 0xD0 => @as(T, dma.*[2].cnt.raw) << 16, - 0xDC => @as(T, dma.*[3].cnt.raw) << 16, + 0xB0, 0xB4 => null, // DMA0SAD, DMA0DAD, + 0xB8 => @as(T, dma.*[0].cnt.raw) << 16, // DMA0CNT_L is write-only + 0xBC, 0xC0 => null, // DMA1SAD, DMA1DAD + 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 }), }, u16 => switch (byte) { + 0xB0...0xB8 => null, // DMA0SAD, DMA0DAD, DMA0CNT_L 0xBA => dma.*[0].cnt.raw, + 0xBC...0xC4 => null, // DMA1SAD, DMA1DAD, DMA1CNT_L 0xC6 => dma.*[1].cnt.raw, + 0xC8...0xD0 => null, // DMA2SAD, DMA2DAD, DMA2CNT_L 0xD2 => dma.*[2].cnt.raw, + 0xD4...0xDC => null, // DMA3SAD, DMA3DAD, DMA3CNT_L 0xDE => dma.*[3].cnt.raw, 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"), }; } diff --git a/src/core/ppu.zig b/src/core/ppu.zig index 1dfef6a..d9a3f4a 100644 --- a/src/core/ppu.zig +++ b/src/core/ppu.zig @@ -13,6 +13,7 @@ const log = std.log.scoped(.PPU); const setHi = util.setHi; const setLo = util.setLo; +const shift = util.shift; const pollDmaOnBlank = @import("bus/dma.zig").pollDmaOnBlank; 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 { const byte = @truncate(u8, addr); // prefixed with 0x0400_00 diff --git a/src/util.zig b/src/util.zig index 4dc1c52..4d73bb3 100644 --- a/src/util.zig +++ b/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 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 @@ -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 pub inline fn setLo(comptime T: type, left: T, right: HalfInt(T)) T { return switch (T) {