bios boots! ish!

This commit is contained in:
Alex Janka 2023-04-20 16:45:45 +10:00
parent c56e167c6b
commit 7d90d516ed
5 changed files with 201 additions and 15 deletions

View file

@ -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!()

View file

@ -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,
}
}
}

View file

@ -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,
}
}

View 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!(),
}
}
}
}

View file

@ -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
}
}
}
}