wow! ding!

This commit is contained in:
Alex Janka 2023-04-20 21:07:15 +10:00
parent 37be5599d2
commit 2a5d8b816c
3 changed files with 65 additions and 10 deletions

View file

@ -101,6 +101,7 @@ where
serial: Serial, serial: Serial,
timers: Timer, timers: Timer,
camera: CameraWrapperRef<C>, camera: CameraWrapperRef<C>,
is_cgb: bool,
} }
#[serde_with::serde_as] #[serde_with::serde_as]
@ -124,6 +125,7 @@ where
apu: ApuSaveState, apu: ApuSaveState,
serial: SerialSaveState, serial: SerialSaveState,
timers: Timer, timers: Timer,
is_cgb: bool,
} }
impl<ColourFormat, R> MemorySaveState<ColourFormat, R> impl<ColourFormat, R> MemorySaveState<ColourFormat, R>
@ -147,6 +149,7 @@ where
apu: ApuSaveState::create(&memory.apu), apu: ApuSaveState::create(&memory.apu),
serial: SerialSaveState::create(&memory.serial), serial: SerialSaveState::create(&memory.serial),
timers: memory.timers, timers: memory.timers,
is_cgb: memory.is_cgb,
} }
} }
} }
@ -217,6 +220,7 @@ where
serial: Serial::new(output.serial_target), serial: Serial::new(output.serial_target),
timers: Timer::init(), timers: Timer::init(),
camera: output.camera, camera: output.camera,
is_cgb: cgb,
} }
} }
@ -240,11 +244,19 @@ where
Address::Rom(address) => { Address::Rom(address) => {
// rom access // rom access
// todo - switchable rom banks // todo - switchable rom banks
if let Some(bootrom) = &self.bootrom && (address.inner() as usize) < bootrom.len() { if let Some(bootrom) = &self.bootrom {
bootrom[address.inner() as usize] if self.is_cgb {
} else { if address.inner() < 0x100
self.rom.get(address) || (address.inner() >= 0x200
&& ((address.inner()) as usize) < bootrom.len())
{
return bootrom[address.inner() as usize];
}
} else if (address.inner() as usize) < bootrom.len() {
return bootrom[address.inner() as usize];
}
} }
self.rom.get(address)
} }
Address::Vram(address) => self.gpu.get_vram(address), Address::Vram(address) => self.gpu.get_vram(address),
Address::CartRam(address) => self.rom.get_ram(address), Address::CartRam(address) => self.rom.get_ram(address),
@ -344,7 +356,7 @@ where
CgbIoAddress::VramDma(_) => todo!(), CgbIoAddress::VramDma(_) => todo!(),
CgbIoAddress::Infrared => todo!(), CgbIoAddress::Infrared => todo!(),
CgbIoAddress::Palette(address) => self.gpu.get_cgb_palette(address), CgbIoAddress::Palette(address) => self.gpu.get_cgb_palette(address),
CgbIoAddress::ObjPriority => todo!(), CgbIoAddress::ObjPriority => self.gpu.get_obj_priority(),
CgbIoAddress::WramBank => ((*selected) & 0b111) as u8, CgbIoAddress::WramBank => ((*selected) & 0b111) as u8,
CgbIoAddress::Pcm12 => todo!(), CgbIoAddress::Pcm12 => todo!(),
CgbIoAddress::Pcm34 => todo!(), CgbIoAddress::Pcm34 => todo!(),
@ -362,6 +374,7 @@ where
} }
fn set_io(&mut self, address: IoAddress, data: u8) { fn set_io(&mut self, address: IoAddress, data: u8) {
// println!("set 0x{:0>4X} to 0x{:0>2X}", address.inner(), data);
match address { match address {
IoAddress::Joypad => self.joypad.mmio_write(data), IoAddress::Joypad => self.joypad.mmio_write(data),
IoAddress::Serial(address) => match address.inner() { IoAddress::Serial(address) => match address.inner() {
@ -404,7 +417,7 @@ where
CgbIoAddress::VramDma(_) => todo!(), CgbIoAddress::VramDma(_) => todo!(),
CgbIoAddress::Infrared => todo!(), CgbIoAddress::Infrared => todo!(),
CgbIoAddress::Palette(address) => self.gpu.set_cgb_palette(address, data), CgbIoAddress::Palette(address) => self.gpu.set_cgb_palette(address, data),
CgbIoAddress::ObjPriority => todo!(), CgbIoAddress::ObjPriority => self.gpu.set_obj_priority(data),
CgbIoAddress::WramBank => *selected = (data & 0b111).max(1) as usize, CgbIoAddress::WramBank => *selected = (data & 0b111).max(1) as usize,
CgbIoAddress::Pcm12 => todo!(), CgbIoAddress::Pcm12 => todo!(),
CgbIoAddress::Pcm34 => todo!(), CgbIoAddress::Pcm34 => todo!(),
@ -485,6 +498,7 @@ where
serial: Serial::from_save_state(state.serial, serial_target), serial: Serial::from_save_state(state.serial, serial_target),
timers: state.timers, timers: state.timers,
camera, camera,
is_cgb: state.is_cgb,
} }
} }
} }
@ -522,14 +536,14 @@ where
let gpu_interrupts = self.memory.gpu.tick(steps); let gpu_interrupts = self.memory.gpu.tick(steps);
self.memory
.interrupts
.set_interrupt(Interrupt::Vblank, gpu_interrupts.vblank);
self.memory self.memory
.interrupts .interrupts
.set_interrupt(Interrupt::LcdStat, gpu_interrupts.lcd_stat); .set_interrupt(Interrupt::LcdStat, gpu_interrupts.lcd_stat);
if gpu_interrupts.vblank { if gpu_interrupts.vblank {
self.memory
.interrupts
.set_interrupt(Interrupt::Vblank, true);
let latest_state = self.memory.gpu.window.latest_joypad_state(); let latest_state = self.memory.gpu.window.latest_joypad_state();
let joypad_interrupt = self.memory.update_pressed_keys(latest_state); let joypad_interrupt = self.memory.update_pressed_keys(latest_state);
self.memory self.memory

View file

@ -26,11 +26,13 @@ pub(crate) type VideoAddress = BoundedAddress<0xFF40, 0xFF4C>;
pub(crate) type VramDmaAddress = BoundedAddress<0xFF51, 0xFF56>; pub(crate) type VramDmaAddress = BoundedAddress<0xFF51, 0xFF56>;
pub(crate) type CgbPaletteAddress = BoundedAddress<0xFF68, 0xFF6C>; pub(crate) type CgbPaletteAddress = BoundedAddress<0xFF68, 0xFF6C>;
#[derive(Clone, Copy)]
pub(crate) enum RomAddress { pub(crate) enum RomAddress {
Bank0(Bank0Address), Bank0(Bank0Address),
MappedBank(MappedBankAddress), MappedBank(MappedBankAddress),
} }
#[derive(Clone, Copy)]
pub(crate) enum IoAddress { pub(crate) enum IoAddress {
Joypad, Joypad,
Serial(SerialAddress), Serial(SerialAddress),
@ -43,6 +45,7 @@ pub(crate) enum IoAddress {
Unused(u16), Unused(u16),
} }
#[derive(Clone, Copy)]
pub(crate) enum CgbIoAddress { pub(crate) enum CgbIoAddress {
PrepareSpeed, PrepareSpeed,
VramBank, VramBank,
@ -56,6 +59,7 @@ pub(crate) enum CgbIoAddress {
Unused(u16), Unused(u16),
} }
#[derive(Clone, Copy)]
pub(crate) enum Address { pub(crate) enum Address {
Rom(RomAddress), Rom(RomAddress),
Vram(VramAddress), Vram(VramAddress),

View file

@ -8,9 +8,25 @@ use crate::{
use super::{Colour, Gpu}; use super::{Colour, Gpu};
#[derive(Serialize, Deserialize, Clone, Copy, Default)] #[derive(Serialize, Deserialize, Clone, Copy)]
pub(super) struct CgbData { pub(super) struct CgbData {
palettes: CgbPaletteRegisters, palettes: CgbPaletteRegisters,
object_priority_mode: ObjectPriorityMode,
}
impl Default for CgbData {
fn default() -> Self {
Self {
palettes: Default::default(),
object_priority_mode: ObjectPriorityMode::Coordinate,
}
}
}
#[derive(Serialize, Deserialize, Clone, Copy)]
enum ObjectPriorityMode {
OamLocation = 0,
Coordinate = 1,
} }
#[derive(Serialize, Deserialize, Clone, Copy, Default)] #[derive(Serialize, Deserialize, Clone, Copy, Default)]
@ -50,6 +66,9 @@ impl CgbPalette {
fn set_data(&mut self, data: u8) { fn set_data(&mut self, data: u8) {
self.data[self.index as usize] = data; self.data[self.index as usize] = data;
if self.auto_increment {
self.index = (self.index + 1) & 0b111111
}
} }
fn get_data(&self) -> u8 { fn get_data(&self) -> u8 {
@ -87,4 +106,22 @@ where
} }
} }
} }
pub(crate) fn get_obj_priority(&self) -> u8 {
if let Some(cgb_data) = &self.cgb_data {
cgb_data.object_priority_mode as u8
} else {
0xFF
}
}
pub(crate) fn set_obj_priority(&mut self, data: u8) {
if let Some(cgb_data) = &mut self.cgb_data {
cgb_data.object_priority_mode = if data & 0b1 == 0 {
ObjectPriorityMode::OamLocation
} else {
ObjectPriorityMode::Coordinate
}
}
}
} }