bios boots! ish!
This commit is contained in:
parent
c56e167c6b
commit
7d90d516ed
|
@ -212,7 +212,7 @@ where
|
|||
user_mode: false,
|
||||
dma: OamDma::default(),
|
||||
joypad: Joypad::default(),
|
||||
gpu: Gpu::new(output.window, output.tile_window),
|
||||
gpu: Gpu::new(cgb, output.window, output.tile_window),
|
||||
apu: Apu::new(output.audio),
|
||||
serial: Serial::new(output.serial_target),
|
||||
timers: Timer::init(),
|
||||
|
@ -339,7 +339,15 @@ where
|
|||
IoAddress::Cgb(address) => {
|
||||
if let WramBanks::Cgb { banks: _, selected } = &self.ram.banks {
|
||||
match address {
|
||||
CgbIoAddress::PrepareSpeed => todo!(),
|
||||
CgbIoAddress::VramBank => self.gpu.vram.get_vram_bank(),
|
||||
CgbIoAddress::VramDma(_) => todo!(),
|
||||
CgbIoAddress::Infrared => todo!(),
|
||||
CgbIoAddress::Palette(address) => self.gpu.get_cgb_palette(address),
|
||||
CgbIoAddress::ObjPriority => todo!(),
|
||||
CgbIoAddress::WramBank => ((*selected) & 0b111) as u8,
|
||||
CgbIoAddress::Pcm12 => todo!(),
|
||||
CgbIoAddress::Pcm34 => todo!(),
|
||||
CgbIoAddress::Unused(v) => {
|
||||
println!("attempt to get 0x{v:0>4X}");
|
||||
todo!()
|
||||
|
@ -391,7 +399,15 @@ where
|
|||
IoAddress::Cgb(address) => {
|
||||
if let WramBanks::Cgb { banks: _, selected } = &mut self.ram.banks {
|
||||
match address {
|
||||
CgbIoAddress::PrepareSpeed => todo!(),
|
||||
CgbIoAddress::VramBank => self.gpu.vram.set_vram_bank(data),
|
||||
CgbIoAddress::VramDma(_) => todo!(),
|
||||
CgbIoAddress::Infrared => todo!(),
|
||||
CgbIoAddress::Palette(address) => self.gpu.set_cgb_palette(address, data),
|
||||
CgbIoAddress::ObjPriority => todo!(),
|
||||
CgbIoAddress::WramBank => *selected = (data & 0b111).max(1) as usize,
|
||||
CgbIoAddress::Pcm12 => todo!(),
|
||||
CgbIoAddress::Pcm34 => todo!(),
|
||||
CgbIoAddress::Unused(v) => {
|
||||
println!("attempt to set 0x{v:0>4X} to 0x{data:0>2X}");
|
||||
todo!()
|
||||
|
|
|
@ -23,6 +23,9 @@ pub(crate) type AudioAddress = BoundedAddress<0xFF10, 0xFF27>;
|
|||
pub(crate) type WaveRamAddress = BoundedAddress<0xFF30, 0xFF40>;
|
||||
pub(crate) type VideoAddress = BoundedAddress<0xFF40, 0xFF4C>;
|
||||
|
||||
pub(crate) type VramDmaAddress = BoundedAddress<0xFF51, 0xFF56>;
|
||||
pub(crate) type CgbPaletteAddress = BoundedAddress<0xFF68, 0xFF6C>;
|
||||
|
||||
pub(crate) enum RomAddress {
|
||||
Bank0(Bank0Address),
|
||||
MappedBank(MappedBankAddress),
|
||||
|
@ -41,7 +44,15 @@ pub(crate) enum IoAddress {
|
|||
}
|
||||
|
||||
pub(crate) enum CgbIoAddress {
|
||||
PrepareSpeed,
|
||||
VramBank,
|
||||
VramDma(VramDmaAddress),
|
||||
Infrared,
|
||||
Palette(CgbPaletteAddress),
|
||||
ObjPriority,
|
||||
WramBank,
|
||||
Pcm12,
|
||||
Pcm34,
|
||||
Unused(u16),
|
||||
}
|
||||
|
||||
|
@ -119,7 +130,15 @@ impl TryInto<CgbIoAddress> for u16 {
|
|||
|
||||
fn try_into(self) -> Result<CgbIoAddress, Self::Error> {
|
||||
match self {
|
||||
0xFF4D => Ok(CgbIoAddress::PrepareSpeed),
|
||||
0xFF4F => Ok(CgbIoAddress::VramBank),
|
||||
0xFF51..0xFF56 => Ok(CgbIoAddress::VramDma(self.try_into().unwrap())),
|
||||
0xFF56 => Ok(CgbIoAddress::Infrared),
|
||||
0xFF68..0xFF6C => Ok(CgbIoAddress::Palette(self.try_into().unwrap())),
|
||||
0xFF6C => Ok(CgbIoAddress::ObjPriority),
|
||||
0xFF70 => Ok(CgbIoAddress::WramBank),
|
||||
0xFF76 => Ok(CgbIoAddress::Pcm12),
|
||||
0xFF77 => Ok(CgbIoAddress::Pcm34),
|
||||
0x0..0xFF4D | 0xFF78..=0xFFFF => Err(AddressError::OutOfBounds),
|
||||
_ => Ok(CgbIoAddress::Unused(self)),
|
||||
}
|
||||
|
@ -154,8 +173,16 @@ impl AddressMarker for IoAddress {
|
|||
impl AddressMarker for CgbIoAddress {
|
||||
fn inner(&self) -> u16 {
|
||||
match self {
|
||||
CgbIoAddress::Unused(v) => *v,
|
||||
CgbIoAddress::PrepareSpeed => 0xFF4D,
|
||||
CgbIoAddress::VramBank => 0xFF4F,
|
||||
CgbIoAddress::VramDma(v) => v.inner(),
|
||||
CgbIoAddress::Infrared => 0xFF56,
|
||||
CgbIoAddress::Palette(v) => v.inner(),
|
||||
CgbIoAddress::ObjPriority => 0xFF6C,
|
||||
CgbIoAddress::WramBank => 0xFF70,
|
||||
CgbIoAddress::Pcm12 => 0xFF76,
|
||||
CgbIoAddress::Pcm34 => 0xFF77,
|
||||
CgbIoAddress::Unused(v) => *v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::marker::PhantomData;
|
||||
|
||||
use self::{
|
||||
cgb::CgbData,
|
||||
tile_window::TileWindow,
|
||||
types::{
|
||||
DrawMode, GpuInterrupts, Lcdc, Oam, ObjPalette, ObjSize, Object, ObjectFlags, Palette,
|
||||
|
@ -20,6 +21,7 @@ use serde::{Deserialize, Serialize};
|
|||
pub use types::Colour;
|
||||
|
||||
mod addresses;
|
||||
mod cgb;
|
||||
mod tile_window;
|
||||
mod types;
|
||||
|
||||
|
@ -52,6 +54,7 @@ where
|
|||
wx: u8,
|
||||
wy: u8,
|
||||
prev_stat: bool,
|
||||
cgb_data: Option<CgbData>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
@ -79,6 +82,7 @@ where
|
|||
wx: u8,
|
||||
wy: u8,
|
||||
prev_stat: bool,
|
||||
cgb_data: Option<CgbData>,
|
||||
#[serde(skip)]
|
||||
spooky: PhantomData<R>,
|
||||
}
|
||||
|
@ -91,7 +95,7 @@ where
|
|||
pub fn create(gpu: &Gpu<ColourFormat, R>) -> Self {
|
||||
Self {
|
||||
buffer: gpu.buffer.clone(),
|
||||
vram: gpu.vram,
|
||||
vram: gpu.vram.clone(),
|
||||
oam: gpu.oam,
|
||||
is_bg_zero: gpu.is_bg_zero.clone(),
|
||||
lcdc: gpu.lcdc,
|
||||
|
@ -109,6 +113,7 @@ where
|
|||
wx: gpu.wx,
|
||||
wy: gpu.wy,
|
||||
prev_stat: gpu.prev_stat,
|
||||
cgb_data: gpu.cgb_data,
|
||||
spooky: PhantomData,
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +124,7 @@ where
|
|||
ColourFormat: From<Colour> + Clone,
|
||||
R: Renderer<ColourFormat>,
|
||||
{
|
||||
pub fn new(window: R, tile_window_renderer: Option<R>) -> Self {
|
||||
pub fn new(cgb: bool, window: R, tile_window_renderer: Option<R>) -> Self {
|
||||
let tile_window = if let Some(mut tile_window_renderer) = tile_window_renderer {
|
||||
tile_window_renderer.prepare(TILE_WINDOW_WIDTH, TILE_WINDOW_HEIGHT);
|
||||
Some(TileWindow::new(tile_window_renderer))
|
||||
|
@ -130,7 +135,7 @@ where
|
|||
|
||||
Self {
|
||||
buffer,
|
||||
vram: Vram::default(),
|
||||
vram: Vram::new(cgb),
|
||||
oam: Oam::default(),
|
||||
window,
|
||||
is_bg_zero: vec![true; WIDTH],
|
||||
|
@ -150,6 +155,7 @@ where
|
|||
wx: 0,
|
||||
wy: 0,
|
||||
prev_stat: false,
|
||||
cgb_data: if cgb { Some(CgbData::default()) } else { None },
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,6 +193,7 @@ where
|
|||
wx: state.wx,
|
||||
wy: state.wy,
|
||||
prev_stat: state.prev_stat,
|
||||
cgb_data: state.cgb_data,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
90
lib/src/processor/memory/mmio/gpu/cgb.rs
Normal file
90
lib/src/processor/memory/mmio/gpu/cgb.rs
Normal file
|
@ -0,0 +1,90 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
connect::Renderer,
|
||||
processor::memory::addresses::{AddressMarker, CgbPaletteAddress},
|
||||
util::get_bit,
|
||||
};
|
||||
|
||||
use super::{Colour, Gpu};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Default)]
|
||||
pub(super) struct CgbData {
|
||||
palettes: CgbPaletteRegisters,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Default)]
|
||||
struct CgbPaletteRegisters {
|
||||
bg: CgbPalette,
|
||||
obj: CgbPalette,
|
||||
}
|
||||
|
||||
#[serde_with::serde_as]
|
||||
#[derive(Serialize, Deserialize, Clone, Copy)]
|
||||
struct CgbPalette {
|
||||
auto_increment: bool,
|
||||
index: u8,
|
||||
#[serde_as(as = "[_; 0x40]")]
|
||||
data: [u8; 0x40],
|
||||
}
|
||||
|
||||
impl Default for CgbPalette {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
auto_increment: false,
|
||||
index: 0,
|
||||
data: [0; 0x40],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CgbPalette {
|
||||
fn set_control(&mut self, data: u8) {
|
||||
self.index = data & 0b111111;
|
||||
self.auto_increment = get_bit(data, 7);
|
||||
}
|
||||
|
||||
fn get_control(&self) -> u8 {
|
||||
(if self.auto_increment { 1 << 7 } else { 0 } | (self.index & 0b111111))
|
||||
}
|
||||
|
||||
fn set_data(&mut self, data: u8) {
|
||||
self.data[self.index as usize] = data;
|
||||
}
|
||||
|
||||
fn get_data(&self) -> u8 {
|
||||
self.data[self.index as usize]
|
||||
}
|
||||
}
|
||||
|
||||
impl<ColourFormat, R> Gpu<ColourFormat, R>
|
||||
where
|
||||
ColourFormat: From<Colour> + Clone,
|
||||
R: Renderer<ColourFormat>,
|
||||
{
|
||||
pub(crate) fn get_cgb_palette(&self, address: CgbPaletteAddress) -> u8 {
|
||||
if let Some(cgb_data) = &self.cgb_data {
|
||||
match address.inner() {
|
||||
0xFF68 => cgb_data.palettes.bg.get_control(),
|
||||
0xFF69 => cgb_data.palettes.bg.get_data(),
|
||||
0xFF6A => cgb_data.palettes.obj.get_control(),
|
||||
0xFF6B => cgb_data.palettes.obj.get_data(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
0xFF
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_cgb_palette(&mut self, address: CgbPaletteAddress, data: u8) {
|
||||
if let Some(cgb_data) = &mut self.cgb_data {
|
||||
match address.inner() {
|
||||
0xFF68 => cgb_data.palettes.bg.set_control(data),
|
||||
0xFF69 => cgb_data.palettes.bg.set_data(data),
|
||||
0xFF6A => cgb_data.palettes.obj.set_control(data),
|
||||
0xFF6B => cgb_data.palettes.obj.set_data(data),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -219,26 +219,72 @@ impl Default for Stat {
|
|||
}
|
||||
}
|
||||
|
||||
#[serde_with::serde_as]
|
||||
#[derive(Serialize, Deserialize, Clone, Copy)]
|
||||
pub struct Vram {
|
||||
#[serde_as(as = "[_; 8192]")]
|
||||
data: [u8; 8192],
|
||||
pub enum VramBank {
|
||||
Bank0 = 0,
|
||||
Bank1 = 1,
|
||||
}
|
||||
|
||||
#[serde_with::serde_as]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub enum Vram {
|
||||
Dmg {
|
||||
#[serde_as(as = "Box<[_; 8192]>")]
|
||||
inner: Box<[u8; 8192]>,
|
||||
},
|
||||
Cgb {
|
||||
#[serde_as(as = "Box<[[_; 8192];2]>")]
|
||||
inner: Box<[[u8; 8192]; 2]>,
|
||||
index: VramBank,
|
||||
},
|
||||
}
|
||||
|
||||
impl Vram {
|
||||
pub(crate) fn new(cgb: bool) -> Self {
|
||||
if cgb {
|
||||
Self::Cgb {
|
||||
inner: Box::new([[0; 8192]; 2]),
|
||||
index: VramBank::Bank0,
|
||||
}
|
||||
} else {
|
||||
Self::Dmg {
|
||||
inner: Box::new([0; 8192]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get(&self, address: VramAddress) -> u8 {
|
||||
self.data[address.get_local() as usize]
|
||||
match self {
|
||||
Vram::Dmg { inner } => inner[address.get_local() as usize],
|
||||
Vram::Cgb { inner, index } => inner[*index as usize][address.get_local() as usize],
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set(&mut self, address: VramAddress, data: u8) {
|
||||
self.data[address.get_local() as usize] = data;
|
||||
match self {
|
||||
Vram::Dmg { inner } => inner[address.get_local() as usize] = data,
|
||||
Vram::Cgb { inner, index } => {
|
||||
inner[*index as usize][address.get_local() as usize] = data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Vram {
|
||||
fn default() -> Self {
|
||||
Self { data: [0x0; 8192] }
|
||||
pub(crate) fn get_vram_bank(&self) -> u8 {
|
||||
if let Vram::Cgb { inner: _, index } = self {
|
||||
(*index as u8) | (!1)
|
||||
} else {
|
||||
0xFF
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_vram_bank(&mut self, data: u8) {
|
||||
if let Vram::Cgb { inner: _, index } = self {
|
||||
*index = if data & 0b1 == 0 {
|
||||
VramBank::Bank0
|
||||
} else {
|
||||
VramBank::Bank1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue