ir + cleaning

This commit is contained in:
Alex Janka 2023-04-21 10:38:51 +10:00
parent 9ff6196ecf
commit fbae48596e
4 changed files with 59 additions and 31 deletions

View file

@ -7,7 +7,7 @@ use self::{
apu::ApuSaveState, apu::ApuSaveState,
gpu::{Colour, GpuSaveState}, gpu::{Colour, GpuSaveState},
serial::SerialSaveState, serial::SerialSaveState,
Apu, Gpu, Joypad, OamDma, Serial, Timer, VramDma, Apu, Gpu, Infrared, Joypad, OamDma, Serial, Timer, VramDma,
}, },
rom::RomSaveState, rom::RomSaveState,
}; };
@ -80,6 +80,12 @@ impl Wram {
} }
} }
#[derive(Clone, Copy, Serialize, Deserialize, Default)]
struct CgbPeripherals {
vram_dma: VramDma,
infrared: Infrared,
}
pub struct Memory<ColourFormat, R, C> pub struct Memory<ColourFormat, R, C>
where where
ColourFormat: From<Colour> + Clone, ColourFormat: From<Colour> + Clone,
@ -95,14 +101,13 @@ where
pub(super) ime_scheduled: u8, pub(super) ime_scheduled: u8,
pub(super) user_mode: bool, pub(super) user_mode: bool,
oam_dma: OamDma, oam_dma: OamDma,
vram_dma: Option<VramDma>,
joypad: Joypad, joypad: Joypad,
gpu: Gpu<ColourFormat, R>, gpu: Gpu<ColourFormat, R>,
apu: Apu, apu: Apu,
serial: Serial, serial: Serial,
timers: Timer, timers: Timer,
camera: CameraWrapperRef<C>, camera: CameraWrapperRef<C>,
is_cgb: bool, cgb_peripherals: Option<CgbPeripherals>,
} }
#[serde_with::serde_as] #[serde_with::serde_as]
@ -121,13 +126,12 @@ where
pub(super) ime_scheduled: u8, pub(super) ime_scheduled: u8,
pub(super) user_mode: bool, pub(super) user_mode: bool,
oam_dma: OamDma, oam_dma: OamDma,
vram_dma: Option<VramDma>,
joypad: Joypad, joypad: Joypad,
gpu: GpuSaveState<ColourFormat, R>, gpu: GpuSaveState<ColourFormat, R>,
apu: ApuSaveState, apu: ApuSaveState,
serial: SerialSaveState, serial: SerialSaveState,
timers: Timer, timers: Timer,
is_cgb: bool, cgb_peripherals: Option<CgbPeripherals>,
} }
impl<ColourFormat, R> MemorySaveState<ColourFormat, R> impl<ColourFormat, R> MemorySaveState<ColourFormat, R>
@ -146,13 +150,12 @@ where
ime_scheduled: memory.ime_scheduled, ime_scheduled: memory.ime_scheduled,
user_mode: memory.user_mode, user_mode: memory.user_mode,
oam_dma: memory.oam_dma, oam_dma: memory.oam_dma,
vram_dma: memory.vram_dma,
joypad: memory.joypad, joypad: memory.joypad,
gpu: GpuSaveState::create(&memory.gpu), gpu: GpuSaveState::create(&memory.gpu),
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, cgb_peripherals: memory.cgb_peripherals,
} }
} }
} }
@ -217,14 +220,17 @@ where
ime_scheduled: 0x0, ime_scheduled: 0x0,
user_mode: false, user_mode: false,
oam_dma: OamDma::default(), oam_dma: OamDma::default(),
vram_dma: if cgb { Some(VramDma::default()) } else { None },
joypad: Joypad::default(), joypad: Joypad::default(),
gpu: Gpu::new(cgb, output.window, output.tile_window), gpu: Gpu::new(cgb, output.window, output.tile_window),
apu: Apu::new(output.audio), apu: Apu::new(output.audio),
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, cgb_peripherals: if cgb {
Some(CgbPeripherals::default())
} else {
None
},
} }
} }
@ -249,7 +255,7 @@ where
// rom access // rom access
// todo - switchable rom banks // todo - switchable rom banks
if let Some(bootrom) = &self.bootrom { if let Some(bootrom) = &self.bootrom {
if self.is_cgb { if self.cgb_peripherals.is_some() {
if address.inner() < 0x100 if address.inner() < 0x100
|| (address.inner() >= 0x200 || (address.inner() >= 0x200
&& ((address.inner()) as usize) < bootrom.len()) && ((address.inner()) as usize) < bootrom.len())
@ -353,12 +359,12 @@ where
0x0..0xFF40 | 0xFF4C..=0xFFFF => unreachable!(), 0x0..0xFF40 | 0xFF4C..=0xFFFF => unreachable!(),
}, },
IoAddress::Cgb(address) => { IoAddress::Cgb(address) => {
if let WramBanks::Cgb { banks: _, selected } = &self.ram.banks && let Some(vram_dma) = &self.vram_dma { if let WramBanks::Cgb { banks: _, selected } = &self.ram.banks && let Some(cgb_peripherals) = &self.cgb_peripherals {
match address { match address {
CgbIoAddress::PrepareSpeed => todo!(), CgbIoAddress::PrepareSpeed => todo!(),
CgbIoAddress::VramBank => self.gpu.vram.get_vram_bank(), CgbIoAddress::VramBank => self.gpu.vram.get_vram_bank(),
CgbIoAddress::VramDma(address) => vram_dma.get_register(address), CgbIoAddress::VramDma(address) => cgb_peripherals.vram_dma.get_register(address),
CgbIoAddress::Infrared => todo!(), CgbIoAddress::Infrared => cgb_peripherals.infrared.get(),
CgbIoAddress::Palette(address) => self.gpu.get_cgb_palette(address), CgbIoAddress::Palette(address) => self.gpu.get_cgb_palette(address),
CgbIoAddress::ObjPriority => self.gpu.get_obj_priority(), CgbIoAddress::ObjPriority => self.gpu.get_obj_priority(),
CgbIoAddress::WramBank => ((*selected) & 0b111) as u8, CgbIoAddress::WramBank => ((*selected) & 0b111) as u8,
@ -412,12 +418,12 @@ where
0x0..0xFF40 | 0xFF4C..=0xFFFF => unreachable!(), 0x0..0xFF40 | 0xFF4C..=0xFFFF => unreachable!(),
}, },
IoAddress::Cgb(address) => { IoAddress::Cgb(address) => {
if let WramBanks::Cgb { banks: _, selected } = &mut self.ram.banks && let Some(vram_dma) = &mut self.vram_dma { if let WramBanks::Cgb { banks: _, selected } = &mut self.ram.banks && let Some(cgb_peripherals) = &mut self.cgb_peripherals {
match address { match address {
CgbIoAddress::PrepareSpeed => todo!(), CgbIoAddress::PrepareSpeed => todo!(),
CgbIoAddress::VramBank => self.gpu.vram.set_vram_bank(data), CgbIoAddress::VramBank => self.gpu.vram.set_vram_bank(data),
CgbIoAddress::VramDma(address) => vram_dma.set_register(address, data), CgbIoAddress::VramDma(address) => cgb_peripherals.vram_dma.set_register(address, data),
CgbIoAddress::Infrared => todo!(), CgbIoAddress::Infrared => cgb_peripherals.infrared.set(data),
CgbIoAddress::Palette(address) => self.gpu.set_cgb_palette(address, data), CgbIoAddress::Palette(address) => self.gpu.set_cgb_palette(address, data),
CgbIoAddress::ObjPriority => self.gpu.set_obj_priority(data), 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,
@ -493,14 +499,13 @@ where
ime_scheduled: state.ime_scheduled, ime_scheduled: state.ime_scheduled,
user_mode: state.user_mode, user_mode: state.user_mode,
oam_dma: state.oam_dma, oam_dma: state.oam_dma,
vram_dma: state.vram_dma,
joypad: state.joypad, joypad: state.joypad,
gpu: Gpu::from_save_state(state.gpu, window, None), gpu: Gpu::from_save_state(state.gpu, window, None),
apu: Apu::from_save_state(state.apu, output), apu: Apu::from_save_state(state.apu, output),
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, cgb_peripherals: state.cgb_peripherals,
} }
} }
} }

View file

@ -0,0 +1,20 @@
use serde::{Deserialize, Serialize};
use crate::util::get_bit;
#[derive(Default, Clone, Copy, Serialize, Deserialize)]
pub struct Infrared {
led: bool,
read_enable: bool,
}
impl Infrared {
pub(crate) fn get(&self) -> u8 {
0b111110 | if self.led { 1 } else { 0 } | if self.read_enable { 0b11 << 6 } else { 0 }
}
pub(crate) fn set(&mut self, data: u8) {
self.led = get_bit(data, 0);
self.read_enable = get_bit(data, 6) && get_bit(data, 7);
}
}

View file

@ -1,5 +1,6 @@
pub(crate) mod apu; pub(crate) mod apu;
pub(crate) mod gpu; pub(crate) mod gpu;
mod ir;
pub(crate) mod joypad; pub(crate) mod joypad;
mod oam_dma; mod oam_dma;
pub(crate) mod serial; pub(crate) mod serial;
@ -7,6 +8,7 @@ mod timer;
mod vram_dma; mod vram_dma;
pub use apu::Apu; pub use apu::Apu;
pub use gpu::Gpu; pub use gpu::Gpu;
pub use ir::Infrared;
pub use joypad::Joypad; pub use joypad::Joypad;
pub use oam_dma::OamDma; pub use oam_dma::OamDma;
pub use serial::Serial; pub use serial::Serial;

View file

@ -69,12 +69,6 @@ impl VramDma {
} else { } else {
DmaMode::Waiting DmaMode::Waiting
}; };
println!("vram dma - entered mode {:?}", self.mode);
println!(
" for transfer from 0x{:0>4X} to 0x{:0>4X}",
self.source, self.destination
);
println!(" num bytes/lines: 0x{num:X}");
} }
_ => unreachable!(), _ => unreachable!(),
} }
@ -89,20 +83,28 @@ where
{ {
pub(crate) fn vram_dma_tick(&mut self) -> usize { pub(crate) fn vram_dma_tick(&mut self) -> usize {
let mut copy = None; let mut copy = None;
let returning = if let Some(vram_dma) = &mut self.vram_dma { let returning = if let Some(cgb_peripherals) = &mut self.cgb_peripherals {
match vram_dma.mode { match cgb_peripherals.vram_dma.mode {
DmaMode::Halt(l) => { DmaMode::Halt(l) => {
copy = Some((vram_dma.destination, vram_dma.source, 16 * ((l as u16) + 1))); copy = Some((
vram_dma.mode = DmaMode::Waiting; cgb_peripherals.vram_dma.destination,
cgb_peripherals.vram_dma.source,
16 * ((l as u16) + 1),
));
cgb_peripherals.vram_dma.mode = DmaMode::Waiting;
((l as usize) + 1) * 8 ((l as usize) + 1) * 8
} }
DmaMode::Hblank(l, ref mut progress) => { DmaMode::Hblank(l, ref mut progress) => {
if self.gpu.get_mode() == DrawMode::HBlank { if self.gpu.get_mode() == DrawMode::HBlank {
let offset = *progress * 16; let offset = *progress * 16;
copy = Some((vram_dma.destination + offset, vram_dma.source + offset, 16)); copy = Some((
cgb_peripherals.vram_dma.destination + offset,
cgb_peripherals.vram_dma.source + offset,
16,
));
*progress += 1; *progress += 1;
if *progress > (l as u16) { if *progress > (l as u16) {
vram_dma.mode = DmaMode::Waiting cgb_peripherals.vram_dma.mode = DmaMode::Waiting
} }
8 8
} else { } else {
@ -115,7 +117,6 @@ where
0 0
}; };
if let Some((source, dest, length)) = copy { if let Some((source, dest, length)) = copy {
println!("copying 0x{length:X} bytes from {source:0>4X} to {dest:0>4X}");
for i in 0..length { for i in 0..length {
self.set(dest + i, self.get(source + i)); self.set(dest + i, self.get(source + i));
} }