core: Handle 8bit writes to video memory
fixes #96 Former-commit-id: efdb6c0af0ef6ee2a74042b8725306103703fcfe Former-commit-id: 1f0e7f7135649ab13c4adcb72bc5e9b432a4905f
This commit is contained in:
parent
63bf7d6dbb
commit
309ae2f795
|
@ -5,9 +5,10 @@ use std::rc::Rc;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::interrupt::IrqBitmask;
|
||||
pub use super::sysbus::consts::*;
|
||||
use super::sysbus::{BoxedMemory, SysBus};
|
||||
use super::Bus;
|
||||
use super::VideoInterface;
|
||||
use super::{Addr, Bus};
|
||||
|
||||
use crate::bitfield::Bit;
|
||||
use crate::num::FromPrimitive;
|
||||
|
@ -30,11 +31,11 @@ pub use regs::*;
|
|||
|
||||
#[allow(unused)]
|
||||
pub mod consts {
|
||||
pub use super::VRAM_ADDR;
|
||||
pub const VIDEO_RAM_SIZE: usize = 128 * 1024;
|
||||
pub const PALETTE_RAM_SIZE: usize = 1 * 1024;
|
||||
pub const OAM_SIZE: usize = 1 * 1024;
|
||||
|
||||
pub const VRAM_ADDR: u32 = 0x0600_0000;
|
||||
pub const DISPLAY_WIDTH: usize = 240;
|
||||
pub const DISPLAY_HEIGHT: usize = 160;
|
||||
pub const VBLANK_LINES: usize = 68;
|
||||
|
@ -203,6 +204,68 @@ 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.oam.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() -> Gpu {
|
||||
Gpu {
|
||||
|
|
|
@ -255,15 +255,7 @@ macro_rules! memory_map {
|
|||
};
|
||||
$sb.io.$read_fn(addr)
|
||||
}
|
||||
PALRAM_ADDR => $sb.io.gpu.palette_ram.$read_fn($addr & 0x3ff),
|
||||
VRAM_ADDR => {
|
||||
let mut ofs = $addr & ((VIDEO_RAM_SIZE as u32) - 1);
|
||||
if ofs > 0x18000 {
|
||||
ofs -= 0x8000;
|
||||
}
|
||||
$sb.io.gpu.vram.$read_fn(ofs)
|
||||
}
|
||||
OAM_ADDR => $sb.io.gpu.oam.$read_fn($addr & 0x3ff),
|
||||
PALRAM_ADDR | VRAM_ADDR | OAM_ADDR => $sb.io.gpu.$read_fn($addr),
|
||||
GAMEPAK_WS0_LO | GAMEPAK_WS0_HI | GAMEPAK_WS1_LO | GAMEPAK_WS1_HI | GAMEPAK_WS2_LO => {
|
||||
$sb.cartridge.$read_fn($addr)
|
||||
}
|
||||
|
@ -289,15 +281,7 @@ macro_rules! memory_map {
|
|||
};
|
||||
$sb.io.$write_fn(addr, $value)
|
||||
}
|
||||
PALRAM_ADDR => $sb.io.gpu.palette_ram.$write_fn($addr & 0x3ff, $value),
|
||||
VRAM_ADDR => {
|
||||
let mut ofs = $addr & ((VIDEO_RAM_SIZE as u32) - 1);
|
||||
if ofs > 0x18000 {
|
||||
ofs -= 0x8000;
|
||||
}
|
||||
$sb.io.gpu.vram.$write_fn(ofs, $value)
|
||||
}
|
||||
OAM_ADDR => $sb.io.gpu.oam.$write_fn($addr & 0x3ff, $value),
|
||||
PALRAM_ADDR | VRAM_ADDR | OAM_ADDR => $sb.io.gpu.$write_fn($addr, $value),
|
||||
GAMEPAK_WS0_LO | GAMEPAK_WS0_HI => {}
|
||||
GAMEPAK_WS2_HI => $sb.cartridge.$write_fn($addr, $value),
|
||||
SRAM_LO | SRAM_HI => $sb.cartridge.$write_fn($addr, $value),
|
||||
|
|
Reference in a new issue