core/gpu: Implement forced blanking
fixes #102 Former-commit-id: 8d0557a63121eab20f7299d75c4c7e577d5f5612 Former-commit-id: 668c728b5ebd6103bf9d15115cb3912ea8c6f4b6
This commit is contained in:
parent
441f5ad906
commit
71074c9c87
|
@ -208,68 +208,6 @@ pub struct Gpu {
|
|||
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 {
|
||||
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::*;
|
||||
|
|
|
@ -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;
|
||||
|
|
Reference in a new issue