From 71074c9c87cc2c3de999a23589cfac26245ee9b3 Mon Sep 17 00:00:00 2001 From: Michel Heily Date: Tue, 26 May 2020 18:06:02 +0300 Subject: [PATCH] core/gpu: Implement forced blanking fixes #102 Former-commit-id: 8d0557a63121eab20f7299d75c4c7e577d5f5612 Former-commit-id: 668c728b5ebd6103bf9d15115cb3912ea8c6f4b6 --- rustboyadvance-core/src/gpu/mod.rs | 135 +++++++++++++++------------- rustboyadvance-core/src/gpu/regs.rs | 2 +- 2 files changed, 73 insertions(+), 64 deletions(-) diff --git a/rustboyadvance-core/src/gpu/mod.rs b/rustboyadvance-core/src/gpu/mod.rs index 06a181e..9c47667 100644 --- a/rustboyadvance-core/src/gpu/mod.rs +++ b/rustboyadvance-core/src/gpu/mod.rs @@ -208,68 +208,6 @@ pub struct Gpu { pub(super) frame_buffer: Vec, } -impl Bus for Gpu { - fn read_8(&self, addr: Addr) -> u8 { - let page = (addr >> 24) as usize; - match page { - PAGE_PALRAM => self.palette_ram.read_8(addr & 0x3ff), - PAGE_VRAM => { - // complicated - let mut ofs = addr & ((VIDEO_RAM_SIZE as u32) - 1); - if ofs > 0x18000 { - ofs -= 0x8000; - } - self.vram.read_8(ofs) - } - PAGE_OAM => self.oam.read_8(addr & 0x3ff), - _ => unreachable!(), - } - } - - fn write_16(&mut self, addr: Addr, value: u16) { - let page = (addr >> 24) as usize; - match page { - PAGE_PALRAM => self.palette_ram.write_16(addr & 0x3fe, value), - PAGE_VRAM => { - let mut ofs = addr & ((VIDEO_RAM_SIZE as u32) - 1); - if ofs > 0x18000 { - ofs -= 0x8000; - } - self.vram.write_16(ofs, value) - } - PAGE_OAM => self.oam.write_16(addr & 0x3fe, value), - _ => unreachable!(), - } - } - - fn write_8(&mut self, addr: Addr, value: u8) { - fn expand_value(value: u8) -> u16 { - (value as u16) * 0x101 - } - - let page = (addr >> 24) as usize; - match page { - PAGE_PALRAM => self.palette_ram.write_16(addr & 0x3fe, expand_value(value)), - PAGE_VRAM => { - let mut ofs = addr & ((VIDEO_RAM_SIZE as u32) - 1); - if ofs > 0x18000 { - ofs -= 0x8000; - } - let obj_offset = if self.dispcnt.mode() >= 3 { - 0x14000 - } else { - 0x10000 - }; - if ofs < obj_offset { - self.vram.write_16(ofs & !1, expand_value(value)); - } - } - PAGE_OAM => { /* OAM can't be written with 8bit store */ } - _ => unreachable!(), - }; - } -} - impl Gpu { pub fn new(interrupt_flags: SharedInterruptFlags) -> Gpu { Gpu { @@ -346,7 +284,9 @@ impl Gpu { if index == 0 || (palette_bank != 0 && index % 16 == 0) { return Rgb15::TRANSPARENT; } - let value = self.palette_ram.read_16(offset + 2 * index + 0x20 * palette_bank); + let value = self + .palette_ram + .read_16(offset + 2 * index + 0x20 * palette_bank); // top bit is ignored Rgb15(value & 0x7FFF) @@ -371,6 +311,13 @@ impl Gpu { } pub fn render_scanline(&mut self) { + if self.dispcnt.force_blank() { + for x in self.frame_buffer[self.vcount * DISPLAY_WIDTH..].iter_mut().take(DISPLAY_WIDTH) { + *x = 0xf8f8f8; + } + return; + } + if self.dispcnt.enable_obj() { self.render_objs(); } @@ -546,6 +493,68 @@ impl Gpu { } } +impl Bus for Gpu { + fn read_8(&self, addr: Addr) -> u8 { + let page = (addr >> 24) as usize; + match page { + PAGE_PALRAM => self.palette_ram.read_8(addr & 0x3ff), + PAGE_VRAM => { + // complicated + let mut ofs = addr & ((VIDEO_RAM_SIZE as u32) - 1); + if ofs > 0x18000 { + ofs -= 0x8000; + } + self.vram.read_8(ofs) + } + PAGE_OAM => self.oam.read_8(addr & 0x3ff), + _ => unreachable!(), + } + } + + fn write_16(&mut self, addr: Addr, value: u16) { + let page = (addr >> 24) as usize; + match page { + PAGE_PALRAM => self.palette_ram.write_16(addr & 0x3fe, value), + PAGE_VRAM => { + let mut ofs = addr & ((VIDEO_RAM_SIZE as u32) - 1); + if ofs > 0x18000 { + ofs -= 0x8000; + } + self.vram.write_16(ofs, value) + } + PAGE_OAM => self.oam.write_16(addr & 0x3fe, value), + _ => unreachable!(), + } + } + + fn write_8(&mut self, addr: Addr, value: u8) { + fn expand_value(value: u8) -> u16 { + (value as u16) * 0x101 + } + + let page = (addr >> 24) as usize; + match page { + PAGE_PALRAM => self.palette_ram.write_16(addr & 0x3fe, expand_value(value)), + PAGE_VRAM => { + let mut ofs = addr & ((VIDEO_RAM_SIZE as u32) - 1); + if ofs > 0x18000 { + ofs -= 0x8000; + } + let obj_offset = if self.dispcnt.mode() >= 3 { + 0x14000 + } else { + 0x10000 + }; + if ofs < obj_offset { + self.vram.write_16(ofs & !1, expand_value(value)); + } + } + PAGE_OAM => { /* OAM can't be written with 8bit store */ } + _ => unreachable!(), + }; + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/rustboyadvance-core/src/gpu/regs.rs b/rustboyadvance-core/src/gpu/regs.rs index 26aca24..4bc923c 100644 --- a/rustboyadvance-core/src/gpu/regs.rs +++ b/rustboyadvance-core/src/gpu/regs.rs @@ -72,7 +72,7 @@ bitfield! { pub display_frame, set_display_frame: 4, 4; pub hblank_interval_free, _: 5; pub obj_character_vram_mapping, _: 6; - pub forst_vblank, _: 7; + pub force_blank, _: 7; pub enable_bg0, _ : 8; pub enable_bg1, _ : 9; pub enable_bg2, _ : 10;