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 serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::interrupt::IrqBitmask;
|
use super::interrupt::IrqBitmask;
|
||||||
|
pub use super::sysbus::consts::*;
|
||||||
use super::sysbus::{BoxedMemory, SysBus};
|
use super::sysbus::{BoxedMemory, SysBus};
|
||||||
use super::Bus;
|
|
||||||
use super::VideoInterface;
|
use super::VideoInterface;
|
||||||
|
use super::{Addr, Bus};
|
||||||
|
|
||||||
use crate::bitfield::Bit;
|
use crate::bitfield::Bit;
|
||||||
use crate::num::FromPrimitive;
|
use crate::num::FromPrimitive;
|
||||||
|
@ -30,11 +31,11 @@ pub use regs::*;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub mod consts {
|
pub mod consts {
|
||||||
|
pub use super::VRAM_ADDR;
|
||||||
pub const VIDEO_RAM_SIZE: usize = 128 * 1024;
|
pub const VIDEO_RAM_SIZE: usize = 128 * 1024;
|
||||||
pub const PALETTE_RAM_SIZE: usize = 1 * 1024;
|
pub const PALETTE_RAM_SIZE: usize = 1 * 1024;
|
||||||
pub const OAM_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_WIDTH: usize = 240;
|
||||||
pub const DISPLAY_HEIGHT: usize = 160;
|
pub const DISPLAY_HEIGHT: usize = 160;
|
||||||
pub const VBLANK_LINES: usize = 68;
|
pub const VBLANK_LINES: usize = 68;
|
||||||
|
@ -203,6 +204,68 @@ 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.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 {
|
impl Gpu {
|
||||||
pub fn new() -> Gpu {
|
pub fn new() -> Gpu {
|
||||||
Gpu {
|
Gpu {
|
||||||
|
|
|
@ -255,15 +255,7 @@ macro_rules! memory_map {
|
||||||
};
|
};
|
||||||
$sb.io.$read_fn(addr)
|
$sb.io.$read_fn(addr)
|
||||||
}
|
}
|
||||||
PALRAM_ADDR => $sb.io.gpu.palette_ram.$read_fn($addr & 0x3ff),
|
PALRAM_ADDR | VRAM_ADDR | OAM_ADDR => $sb.io.gpu.$read_fn($addr),
|
||||||
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),
|
|
||||||
GAMEPAK_WS0_LO | GAMEPAK_WS0_HI | GAMEPAK_WS1_LO | GAMEPAK_WS1_HI | GAMEPAK_WS2_LO => {
|
GAMEPAK_WS0_LO | GAMEPAK_WS0_HI | GAMEPAK_WS1_LO | GAMEPAK_WS1_HI | GAMEPAK_WS2_LO => {
|
||||||
$sb.cartridge.$read_fn($addr)
|
$sb.cartridge.$read_fn($addr)
|
||||||
}
|
}
|
||||||
|
@ -289,15 +281,7 @@ macro_rules! memory_map {
|
||||||
};
|
};
|
||||||
$sb.io.$write_fn(addr, $value)
|
$sb.io.$write_fn(addr, $value)
|
||||||
}
|
}
|
||||||
PALRAM_ADDR => $sb.io.gpu.palette_ram.$write_fn($addr & 0x3ff, $value),
|
PALRAM_ADDR | VRAM_ADDR | OAM_ADDR => $sb.io.gpu.$write_fn($addr, $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),
|
|
||||||
GAMEPAK_WS0_LO | GAMEPAK_WS0_HI => {}
|
GAMEPAK_WS0_LO | GAMEPAK_WS0_HI => {}
|
||||||
GAMEPAK_WS2_HI => $sb.cartridge.$write_fn($addr, $value),
|
GAMEPAK_WS2_HI => $sb.cartridge.$write_fn($addr, $value),
|
||||||
SRAM_LO | SRAM_HI => $sb.cartridge.$write_fn($addr, $value),
|
SRAM_LO | SRAM_HI => $sb.cartridge.$write_fn($addr, $value),
|
||||||
|
|
Reference in a new issue