fix(ppu): resolve mistakes in ppu i/o reads

This commit is contained in:
Rekai Nyangadzayi Musuka 2022-10-30 02:15:26 -03:00
parent 1d163fa56f
commit c9a423d094
2 changed files with 50 additions and 45 deletions

View File

@ -217,7 +217,7 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
},
u8 => switch (address) {
// Display
0x0400_0000...0x0400_0054 => ppu.write(T, &bus.ppu, address, value),
0x0400_0000...0x0400_0055 => ppu.write(T, &bus.ppu, address, value),
// Sound
0x0400_0060...0x0400_00A7 => apu.write(T, &bus.apu, address, value),

View File

@ -13,7 +13,7 @@ const log = std.log.scoped(.PPU);
const setHi = util.setHi;
const setLo = util.setLo;
const shift = util.shift;
const getHalf = util.shift;
const pollDmaOnBlank = @import("bus/dma.zig").pollDmaOnBlank;
pub const width = 240;
@ -21,24 +21,25 @@ pub const height = 160;
pub const framebuf_pitch = width * @sizeOf(u32);
pub fn read(comptime T: type, ppu: *const Ppu, addr: u32) ?T {
const byte = @truncate(u8, addr);
const byte_addr = @truncate(u8, addr);
return switch (T) {
u32 => switch (byte) {
u32 => switch (byte_addr) {
0x00 => ppu.dispcnt.raw, // Green Swap is in high half-word
0x04 => @as(T, ppu.vcount.raw) << 16 | ppu.dispstat.raw,
0x08 => @as(T, ppu.bg[1].bg1Cnt()) << 16 | ppu.bg[0].bg0Cnt(),
0x0C => @as(T, ppu.bg[3].cnt.raw) << 16 | ppu.bg[2].cnt.raw,
0x10...0x1C => null, // BGXHOFS/VOFS
0x20...0x3C => null, // BG2/3 Rot Scaling Registers
0x40...0x44 => null, // WINXH/V Registers
0x48 => @as(T, ppu.win.out()) << 16 | ppu.win.in(),
0x10, 0x14, 0x18, 0x1C => null, // BGXHOFS/VOFS
0x20, 0x24, 0x28, 0x2C => null, // BG2 Rot/Scaling
0x30, 0x34, 0x38, 0x3C => null, // BG3 Rot/Scaling
0x40, 0x44 => null, // WINXH/V Registers
0x48 => @as(T, ppu.win.getOut()) << 16 | ppu.win.getIn(),
0x4C => null, // MOSAIC, undefined in high byte
0x50 => @as(T, ppu.bld.getAlpha()) << 16 | ppu.bld.getCnt(),
0x54 => null, // BLDY, undefined in high half-wrd
else => util.io.read.err(T, log, "unaligned {} read from 0x{X:0>8}", .{ T, addr }),
},
u16 => switch (byte) {
u16 => switch (byte_addr) {
0x00 => ppu.dispcnt.raw,
0x02 => null, // Green Swap
0x04 => ppu.dispstat.raw,
@ -47,35 +48,39 @@ pub fn read(comptime T: type, ppu: *const Ppu, addr: u32) ?T {
0x0A => ppu.bg[1].bg1Cnt(),
0x0C => ppu.bg[2].cnt.raw,
0x0E => ppu.bg[3].cnt.raw,
0x10...0x1E => null, // BGXHOFS/VOFS
0x20...0x3E => null, // BG2/3 Rot Scaling Registers
0x40...0x46 => null, // WINXH/V Registers
0x48 => ppu.win.in(),
0x4A => ppu.win.out(),
0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E => null, // BGXHOFS/VOFS
0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E => null, // BG2 Rot/Scaling
0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E => null, // BG3 Rot/Scaling
0x40, 0x42, 0x44, 0x46 => null, // WINXH/V Registers
0x48 => ppu.win.getIn(),
0x4A => ppu.win.getOut(),
0x4C => null, // MOSAIC
0x4E => null,
0x50 => ppu.bld.getCnt(),
0x52 => ppu.bld.getAlpha(),
0x54 => null, // BLDY
else => util.io.read.err(T, log, "unaligned {} read from 0x{X:0>8}", .{ T, addr }),
},
u8 => switch (byte) {
0x00, 0x01 => @truncate(T, ppu.dispcnt.raw >> shift(byte)),
0x02...0x03 => null,
0x04, 0x05 => @truncate(T, ppu.dispstat.raw >> shift(byte)),
0x06, 0x07 => @truncate(T, ppu.vcount.raw >> shift(byte)),
0x08, 0x09 => @truncate(T, ppu.bg[0].bg0Cnt() >> shift(byte)),
0x0A, 0x0B => @truncate(T, ppu.bg[1].bg1Cnt() >> shift(byte)),
0x0C, 0x0D => @truncate(T, ppu.bg[2].cnt.raw >> shift(byte)),
0x0E, 0x0F => @truncate(T, ppu.bg[3].cnt.raw >> shift(byte)),
u8 => switch (byte_addr) {
0x00, 0x01 => @truncate(T, ppu.dispcnt.raw >> getHalf(byte_addr)),
0x02, 0x03 => null,
0x04, 0x05 => @truncate(T, ppu.dispstat.raw >> getHalf(byte_addr)),
0x06, 0x07 => @truncate(T, ppu.vcount.raw >> getHalf(byte_addr)),
0x08, 0x09 => @truncate(T, ppu.bg[0].bg0Cnt() >> getHalf(byte_addr)),
0x0A, 0x0B => @truncate(T, ppu.bg[1].bg1Cnt() >> getHalf(byte_addr)),
0x0C, 0x0D => @truncate(T, ppu.bg[2].cnt.raw >> getHalf(byte_addr)),
0x0E, 0x0F => @truncate(T, ppu.bg[3].cnt.raw >> getHalf(byte_addr)),
0x10...0x1F => null, // BGXHOFS/VOFS
0x20...0x3F => null, // BG2/3 Rot Scaling Registers
0x20...0x2F => null, // BG2 Rot/Scaling
0x30...0x3F => null, // BG3 Rot/Scaling
0x40...0x47 => null, // WINXH/V Registers
0x48, 0x49 => @truncate(T, ppu.win.in() >> shift(byte)),
0x4A, 0x4B => @truncate(T, ppu.win.out() >> shift(byte)),
0x4C...0x4D => null, // MOSAIC
0x50, 0x51 => @truncate(T, ppu.bld.getCnt() >> shift(byte)),
0x52, 0x53 => @truncate(T, ppu.bld.getAlpha() >> shift(byte)),
0x54...0x55 => null, // BLDY
0x48, 0x49 => @truncate(T, ppu.win.getIn() >> getHalf(byte_addr)),
0x4A, 0x4B => @truncate(T, ppu.win.getOut() >> getHalf(byte_addr)),
0x4C, 0x4D => null, // MOSAIC
0x4E, 0x4F => null,
0x50, 0x51 => @truncate(T, ppu.bld.getCnt() >> getHalf(byte_addr)),
0x52, 0x53 => @truncate(T, ppu.bld.getAlpha() >> getHalf(byte_addr)),
0x54, 0x55 => null, // BLDY
else => util.io.read.err(T, log, "unexpected {} read from 0x{X:0>8}", .{ T, addr }),
},
else => @compileError("PPU: Unsupported read width"),
@ -154,8 +159,8 @@ pub fn write(comptime T: type, ppu: *Ppu, addr: u32, value: T) void {
0x42 => ppu.win.h[1].raw = value,
0x44 => ppu.win.v[0].raw = value,
0x46 => ppu.win.v[1].raw = value,
0x48 => ppu.win._in.raw = value,
0x4A => ppu.win._out.raw = value,
0x48 => ppu.win.in.raw = value,
0x4A => ppu.win.out.raw = value,
0x4C => log.debug("Wrote 0x{X:0>4} to MOSAIC", .{value}),
0x50 => ppu.bld.cnt.raw = value,
0x52 => ppu.bld.alpha.raw = value,
@ -169,9 +174,9 @@ pub fn write(comptime T: type, ppu: *Ppu, addr: u32, value: T) void {
0x09 => ppu.bg[0].cnt.raw = setHi(u16, ppu.bg[0].cnt.raw, value),
0x0A => ppu.bg[1].cnt.raw = setLo(u16, ppu.bg[1].cnt.raw, value),
0x0B => ppu.bg[1].cnt.raw = setHi(u16, ppu.bg[1].cnt.raw, value),
0x48 => ppu.win._in.raw = setLo(u16, ppu.win._in.raw, value),
0x49 => ppu.win._in.raw = setHi(u16, ppu.win._in.raw, value),
0x4A => ppu.win._out.raw = setLo(u16, ppu.win._out.raw, value),
0x48 => ppu.win.in.raw = setLo(u16, ppu.win.in.raw, value),
0x49 => ppu.win.in.raw = setHi(u16, ppu.win.in.raw, value),
0x4A => ppu.win.out.raw = setLo(u16, ppu.win.out.raw, value),
0x54 => ppu.bld.y.raw = setLo(u16, ppu.bld.y.raw, value),
else => util.io.write.undef(log, "Tried to write 0x{X:0>2}{} to 0x{X:0>8}", .{ value, T, addr }),
},
@ -961,25 +966,25 @@ const Window = struct {
h: [2]io.WinH,
v: [2]io.WinV,
_out: io.WinOut,
_in: io.WinIn,
out: io.WinOut,
in: io.WinIn,
fn init() Self {
return .{
.h = [_]io.WinH{.{ .raw = 0 }} ** 2,
.v = [_]io.WinV{.{ .raw = 0 }} ** 2,
._out = .{ .raw = 0 },
._in = .{ .raw = 0 },
.out = .{ .raw = 0 },
.in = .{ .raw = 0 },
};
}
pub fn in(self: *const Self) u16 {
return self._in.raw & 0x3F3F;
pub fn getIn(self: *const Self) u16 {
return self.in.raw & 0x3F3F;
}
pub fn out(self: *const Self) u16 {
return self._out.raw & 0x3F3F;
pub fn getOut(self: *const Self) u16 {
return self.out.raw & 0x3F3F;
}
pub fn setH(self: *Self, value: u32) void {
@ -993,8 +998,8 @@ const Window = struct {
}
pub fn setIo(self: *Self, value: u32) void {
self._in.raw = @truncate(u16, value);
self._out.raw = @truncate(u16, value >> 16);
self.in.raw = @truncate(u16, value);
self.out.raw = @truncate(u16, value >> 16);
}
};