core/gpu: Fix bitmap mode displaying invalid sprites

fixes #107


Former-commit-id: 4b307c80f0519a5034dad1188d285cb44a2c8eeb
Former-commit-id: 8879aababad1aef0690adb0a88cdeb36368c024a
This commit is contained in:
Michel Heily 2020-05-30 13:41:10 +03:00
parent dc59d7f71f
commit f65e22cc41
3 changed files with 30 additions and 7 deletions

View file

@ -51,6 +51,9 @@ pub mod consts {
pub const CYCLES_FULL_REFRESH: usize = 280896; pub const CYCLES_FULL_REFRESH: usize = 280896;
pub const TILE_SIZE: u32 = 0x20; pub const TILE_SIZE: u32 = 0x20;
pub(super) const VRAM_OBJ_TILES_START_TEXT: u32 = 0x1_0000;
pub(super) const VRAM_OBJ_TILES_START_BITMAP: u32 = 0x1_4000;
} }
pub use self::consts::*; pub use self::consts::*;
@ -201,6 +204,8 @@ pub struct Gpu {
pub vram: BoxedMemory, pub vram: BoxedMemory,
pub oam: BoxedMemory, pub oam: BoxedMemory,
pub(super) vram_obj_tiles_start: u32,
#[debug_stub = "Sprite Buffer"] #[debug_stub = "Sprite Buffer"]
pub obj_buffer: Vec<ObjBufferEntry>, pub obj_buffer: Vec<ObjBufferEntry>,
@ -230,6 +235,8 @@ impl Gpu {
bldalpha: BlendAlpha(0), bldalpha: BlendAlpha(0),
bldy: 0, bldy: 0,
vram_obj_tiles_start: VRAM_OBJ_TILES_START_TEXT,
state: HDraw, state: HDraw,
vcount: 0, vcount: 0,
cycles_left_for_current_state: CYCLES_HDRAW, cycles_left_for_current_state: CYCLES_HDRAW,
@ -244,6 +251,21 @@ impl Gpu {
} }
} }
pub fn write_dispcnt(&mut self, value: u16) {
let new_dispcnt = DisplayControl(value);
let old_mode = self.dispcnt.mode();
let new_mode = new_dispcnt.mode();
if old_mode != new_mode {
debug!("[GPU] Display mode changed! {} -> {}", old_mode, new_mode);
self.vram_obj_tiles_start = if new_dispcnt.mode() >= 3 {
VRAM_OBJ_TILES_START_BITMAP
} else {
VRAM_OBJ_TILES_START_TEXT
};
}
self.dispcnt = new_dispcnt;
}
pub fn skip_bios(&mut self) { pub fn skip_bios(&mut self) {
for i in 0..2 { for i in 0..2 {
self.bg_aff[i].pa = 0x100; self.bg_aff[i].pa = 0x100;
@ -543,12 +565,7 @@ impl Bus for Gpu {
if ofs > 0x18000 { if ofs > 0x18000 {
ofs -= 0x8000; ofs -= 0x8000;
} }
let obj_offset = if self.dispcnt.mode() >= 3 { if ofs < self.vram_obj_tiles_start {
0x14000
} else {
0x10000
};
if ofs < obj_offset {
self.vram.write_16(ofs & !1, expand_value(value)); self.vram.write_16(ofs & !1, expand_value(value));
} }
} }

View file

@ -98,6 +98,9 @@ impl Gpu {
} }
let tile_base = OVRAM - VRAM_ADDR + 0x20 * (attrs.2.tile() as u32); let tile_base = OVRAM - VRAM_ADDR + 0x20 * (attrs.2.tile() as u32);
if tile_base < self.vram_obj_tiles_start {
return;
}
let (tile_size, pixel_format) = attrs.tile_format(); let (tile_size, pixel_format) = attrs.tile_format();
let palette_bank = match pixel_format { let palette_bank = match pixel_format {
@ -191,6 +194,9 @@ impl Gpu {
} }
let tile_base = OVRAM - VRAM_ADDR + 0x20 * (attrs.2.tile() as u32); let tile_base = OVRAM - VRAM_ADDR + 0x20 * (attrs.2.tile() as u32);
if tile_base < self.vram_obj_tiles_start {
return;
}
let (tile_size, pixel_format) = attrs.tile_format(); let (tile_size, pixel_format) = attrs.tile_format();
let palette_bank = match pixel_format { let palette_bank = match pixel_format {

View file

@ -161,7 +161,7 @@ impl Bus for IoDevices {
} }
match io_addr { match io_addr {
REG_DISPCNT => io.gpu.dispcnt.0 = value, REG_DISPCNT => io.gpu.write_dispcnt(value),
REG_DISPSTAT => io.gpu.dispstat.0 = value | (io.gpu.dispstat.0 & 7), REG_DISPSTAT => io.gpu.dispstat.0 = value | (io.gpu.dispstat.0 & 7),
REG_BG0CNT => io.gpu.backgrounds[0].bgcnt.0 = value, REG_BG0CNT => io.gpu.backgrounds[0].bgcnt.0 = value,
REG_BG1CNT => io.gpu.backgrounds[1].bgcnt.0 = value, REG_BG1CNT => io.gpu.backgrounds[1].bgcnt.0 = value,