From 102b2c946b044c0eb3d850f1ba1b5a7d83dec48e Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Wed, 2 Nov 2022 07:54:06 -0300 Subject: [PATCH] fix(io): respect read-only bits in DISPSTAT Superstar Saga now renders correctly --- src/core/bus/io.zig | 9 +++++++++ src/core/ppu.zig | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/core/bus/io.zig b/src/core/bus/io.zig index d59c4c4..364c2aa 100644 --- a/src/core/bus/io.zig +++ b/src/core/bus/io.zig @@ -317,14 +317,23 @@ pub const DisplayControl = extern union { /// Read / Write pub const DisplayStatus = extern union { + /// read-only vblank: Bit(u16, 0), + /// read-only hblank: Bit(u16, 1), + // read-only coincidence: Bit(u16, 2), vblank_irq: Bit(u16, 3), hblank_irq: Bit(u16, 4), vcount_irq: Bit(u16, 5), vcount_trigger: Bitfield(u16, 8, 8), raw: u16, + + pub fn set(self: *DisplayStatus, value: u16) void { + const mask: u16 = 0x00C7; // set bits are read-only + + self.raw = (self.raw & mask) | (value & ~mask); + } }; /// Read Only diff --git a/src/core/ppu.zig b/src/core/ppu.zig index 7f35f3c..24a943f 100644 --- a/src/core/ppu.zig +++ b/src/core/ppu.zig @@ -94,7 +94,7 @@ pub fn write(comptime T: type, ppu: *Ppu, addr: u32, value: T) void { u32 => switch (byte_addr) { 0x00 => ppu.dispcnt.raw = @truncate(u16, value), 0x04 => { - ppu.dispstat.raw = @truncate(u16, value); + ppu.dispstat.set(@truncate(u16, value)); ppu.vcount.raw = @truncate(u16, value >> 16); }, 0x08 => ppu.setAdjCnts(0, value), @@ -130,7 +130,7 @@ pub fn write(comptime T: type, ppu: *Ppu, addr: u32, value: T) void { u16 => switch (byte_addr) { 0x00 => ppu.dispcnt.raw = value, 0x02 => {}, // Green Swap - 0x04 => ppu.dispstat.raw = value, + 0x04 => ppu.dispstat.set(value), 0x06 => {}, // VCOUNT 0x08 => ppu.bg[0].cnt.raw = value, @@ -178,7 +178,7 @@ pub fn write(comptime T: type, ppu: *Ppu, addr: u32, value: T) void { u8 => switch (byte_addr) { 0x00, 0x01 => ppu.dispcnt.raw = setHalf(u16, ppu.dispcnt.raw, byte_addr, value), 0x02, 0x03 => {}, // Green Swap - 0x04, 0x05 => ppu.dispstat.raw = setHalf(u16, ppu.dispstat.raw, byte_addr, value), + 0x04, 0x05 => ppu.dispstat.set(setHalf(u16, ppu.dispstat.raw, byte_addr, value)), 0x06, 0x07 => {}, // VCOUNT // BGXCNT