From 20abbde7b7b559acf702e505b152d73e7e2449fe Mon Sep 17 00:00:00 2001 From: Imre Kaloz Date: Fri, 14 Aug 2026 18:22:48 +0200 Subject: [PATCH] rex3: frame narrow DCB stores by access width, not store address write8 and write16 position a narrow store inside the 32-bit dcb_write value by the store's low address bits, but REX3_DCBDATA0 is a fixed auto-incrementing port: the hardware left-justifies a narrow value by its access width. A halfword store at the port's base address gets shift 0 instead of 16, dcb_write's MSB-first extraction reads two zero bytes, and every CMAP ADDRESS_LOW write lands on palette index 0 - NetBSD's console palette collapses into slot 0 and the console renders white on white. Shift by the access width instead. --- src/rex3.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/rex3.rs b/src/rex3.rs index 8c24c66..48c3a45 100644 --- a/src/rex3.rs +++ b/src/rex3.rs @@ -5111,8 +5111,15 @@ impl BusDevice for Rex3 { dlog_dev!(LogModule::Rex3, "REX3 Write8: Offset {:04x} Val {:02x}", offset, val); if is_dcb { - dlog_dev!(LogModule::Dcb, "DCB Write8: Offset {:04x} Val {:02x} -> dcb_write({:08x})", offset, val, val as u32); - self.dcb_write((val as u32) << ((offset & 3) << 3)); + // DCBDATA0/1 is a fixed-address, auto-incrementing DCB port, not a + // byte-addressable register: the DCB protocol left-justifies any + // narrower-than-32-bit CPU store into the MSB of the transferred + // word, regardless of which low address bits the CPU used to + // issue the access. Shifting by the offset instead of the fixed + // access width mis-frames every 8-bit CMAP/XMAP/RAMDAC/VC2 write + // whose address isn't already MSB-aligned. + dlog_dev!(LogModule::Dcb, "DCB Write8: Offset {:04x} Val {:02x} -> dcb_write({:08x})", offset, val, (val as u32) << 24); + self.dcb_write((val as u32) << 24); return BUS_OK; } eprintln!("REX3 Write8: unhandled offset {:04x} val {:02x}", offset, val); @@ -5145,8 +5152,10 @@ impl BusDevice for Rex3 { dlog_dev!(LogModule::Rex3, "REX3 Write16: Offset {:04x} Val {:04x}", offset, val); if is_dcb { - dlog_dev!(LogModule::Dcb, "DCB Write16: Offset {:04x} Val {:04x} -> dcb_write({:08x})", offset, val, (val as u32) << ((offset & 2) << 3)); - self.dcb_write((val as u32) << ((offset & 2) << 3)); + // Same fixed-address DCB port framing as write8() above: a 16-bit + // CPU store always occupies the top half of the DCB word. + dlog_dev!(LogModule::Dcb, "DCB Write16: Offset {:04x} Val {:04x} -> dcb_write({:08x})", offset, val, (val as u32) << 16); + self.dcb_write((val as u32) << 16); return BUS_OK; } eprintln!("REX3 Write16: unhandled offset {:04x} val {:04x}", offset, val);