core/gpu: Implement forced blanking

fixes #102


Former-commit-id: 8d0557a63121eab20f7299d75c4c7e577d5f5612
Former-commit-id: 668c728b5ebd6103bf9d15115cb3912ea8c6f4b6
This commit is contained in:
Michel Heily 2020-05-26 18:06:02 +03:00
parent 441f5ad906
commit 71074c9c87
2 changed files with 73 additions and 64 deletions

View file

@ -208,68 +208,6 @@ pub struct Gpu {
pub(super) frame_buffer: Vec<u32>, pub(super) frame_buffer: Vec<u32>,
} }
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 { impl Gpu {
pub fn new(interrupt_flags: SharedInterruptFlags) -> Gpu { pub fn new(interrupt_flags: SharedInterruptFlags) -> Gpu {
Gpu { Gpu {
@ -346,7 +284,9 @@ impl Gpu {
if index == 0 || (palette_bank != 0 && index % 16 == 0) { if index == 0 || (palette_bank != 0 && index % 16 == 0) {
return Rgb15::TRANSPARENT; 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 // top bit is ignored
Rgb15(value & 0x7FFF) Rgb15(value & 0x7FFF)
@ -371,6 +311,13 @@ impl Gpu {
} }
pub fn render_scanline(&mut self) { 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() { if self.dispcnt.enable_obj() {
self.render_objs(); 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)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View file

@ -72,7 +72,7 @@ bitfield! {
pub display_frame, set_display_frame: 4, 4; pub display_frame, set_display_frame: 4, 4;
pub hblank_interval_free, _: 5; pub hblank_interval_free, _: 5;
pub obj_character_vram_mapping, _: 6; pub obj_character_vram_mapping, _: 6;
pub forst_vblank, _: 7; pub force_blank, _: 7;
pub enable_bg0, _ : 8; pub enable_bg0, _ : 8;
pub enable_bg1, _ : 9; pub enable_bg1, _ : 9;
pub enable_bg2, _ : 10; pub enable_bg2, _ : 10;