remove save states (they didnt work)
This commit is contained in:
parent
f1b3cabef9
commit
087bef7dc4
18 changed files with 18 additions and 696 deletions
|
@ -9,7 +9,6 @@ crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
savestate = []
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gb-emu-lib = { path = "../lib" }
|
gb-emu-lib = { path = "../lib" }
|
||||||
|
|
|
@ -15,31 +15,8 @@ use std::sync::{
|
||||||
};
|
};
|
||||||
use ui::{Emulator, EmulatorRenderer};
|
use ui::{Emulator, EmulatorRenderer};
|
||||||
|
|
||||||
#[cfg(feature = "savestate")]
|
|
||||||
use gb_emu_lib::connect::CpuSaveState;
|
|
||||||
|
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
#[cfg(feature = "savestate")]
|
|
||||||
#[derive(Default)]
|
|
||||||
struct SaveStateParam {
|
|
||||||
state: Arc<Mutex<Option<CpuSaveState<[u8; 4]>>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "savestate")]
|
|
||||||
impl PersistentField<'_, Option<CpuSaveState<[u8; 4]>>> for SaveStateParam {
|
|
||||||
fn set(&self, new_value: Option<CpuSaveState<[u8; 4]>>) {
|
|
||||||
*self.state.lock().unwrap() = new_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn map<F, R>(&self, f: F) -> R
|
|
||||||
where
|
|
||||||
F: Fn(&Option<CpuSaveState<[u8; 4]>>) -> R,
|
|
||||||
{
|
|
||||||
f(&self.state.lock().unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct SramParam {
|
struct SramParam {
|
||||||
state: Arc<RwLock<Vec<u8>>>,
|
state: Arc<RwLock<Vec<u8>>>,
|
||||||
|
@ -64,9 +41,6 @@ impl PersistentField<'_, Vec<u8>> for SramParam {
|
||||||
struct EmuParams {
|
struct EmuParams {
|
||||||
#[persist = "sram"]
|
#[persist = "sram"]
|
||||||
sram_save: SramParam,
|
sram_save: SramParam,
|
||||||
// #[cfg(feature = "savestate")]
|
|
||||||
// #[persist = "save_state"]
|
|
||||||
// last_save_state: SaveStateParam,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EmuVars {
|
struct EmuVars {
|
||||||
|
@ -218,7 +192,6 @@ impl Plugin for GameboyEmu {
|
||||||
} else {
|
} else {
|
||||||
while context.next_event().is_some() {}
|
while context.next_event().is_some() {}
|
||||||
}
|
}
|
||||||
self.update_save_state();
|
|
||||||
ProcessStatus::KeepAlive
|
ProcessStatus::KeepAlive
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,19 +239,6 @@ impl Plugin for GameboyEmu {
|
||||||
tx: None,
|
tx: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "savestate")]
|
|
||||||
let mut emulator_core = if let Some(state) =
|
|
||||||
self.params.last_save_state.state.lock().unwrap().take()
|
|
||||||
{
|
|
||||||
EmulatorCore::from_save_state(state, rom, receiver, window, output, serial_target)
|
|
||||||
} else {
|
|
||||||
let options = gb_emu_lib::Options::new(window, rom, output)
|
|
||||||
.with_serial_target(serial_target)
|
|
||||||
.force_no_save();
|
|
||||||
|
|
||||||
EmulatorCore::init(receiver, options)
|
|
||||||
};
|
|
||||||
#[cfg(not(feature = "savestate"))]
|
|
||||||
let mut emulator_core = {
|
let mut emulator_core = {
|
||||||
let options = EmulatorOptions::new(window, rom, output)
|
let options = EmulatorOptions::new(window, rom, output)
|
||||||
.with_serial_target(serial_target)
|
.with_serial_target(serial_target)
|
||||||
|
@ -295,14 +255,12 @@ impl Plugin for GameboyEmu {
|
||||||
emulator_core,
|
emulator_core,
|
||||||
serial_tx,
|
serial_tx,
|
||||||
});
|
});
|
||||||
self.update_save_state();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deactivate(&mut self) {
|
fn deactivate(&mut self) {
|
||||||
self.update_save_state();
|
|
||||||
if let Some(ref mut vars) = self.vars {
|
if let Some(ref mut vars) = self.vars {
|
||||||
match vars.sender.send(EmulatorMessage::Stop) {
|
match vars.sender.send(EmulatorMessage::Stop) {
|
||||||
Ok(_) => self.vars = None,
|
Ok(_) => self.vars = None,
|
||||||
|
@ -312,16 +270,6 @@ impl Plugin for GameboyEmu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameboyEmu {
|
|
||||||
fn update_save_state(&mut self) {
|
|
||||||
#[cfg(feature = "savestate")]
|
|
||||||
if let Some(ref mut vars) = self.vars {
|
|
||||||
*self.params.last_save_state.state.lock().unwrap() =
|
|
||||||
Some(vars.emulator_core.get_save_state());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Vst3Plugin for GameboyEmu {
|
impl Vst3Plugin for GameboyEmu {
|
||||||
const VST3_CLASS_ID: [u8; 16] = *b"alexjankagbemula";
|
const VST3_CLASS_ID: [u8; 16] = *b"alexjankagbemula";
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ use std::sync::{Arc, Mutex, RwLock};
|
||||||
pub use crate::processor::memory::mmio::gpu::Colour;
|
pub use crate::processor::memory::mmio::gpu::Colour;
|
||||||
pub use crate::processor::memory::mmio::joypad::{JoypadButtons, JoypadState};
|
pub use crate::processor::memory::mmio::joypad::{JoypadButtons, JoypadState};
|
||||||
pub use crate::processor::memory::mmio::serial::SerialTarget;
|
pub use crate::processor::memory::mmio::serial::SerialTarget;
|
||||||
pub use crate::processor::CpuSaveState;
|
|
||||||
pub use crate::{HEIGHT, WIDTH};
|
pub use crate::{HEIGHT, WIDTH};
|
||||||
use async_ringbuf::{AsyncHeapConsumer, AsyncHeapProducer, AsyncHeapRb};
|
use async_ringbuf::{AsyncHeapConsumer, AsyncHeapProducer, AsyncHeapRb};
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use connect::{
|
use connect::{
|
||||||
AudioOutput, CameraWrapper, CameraWrapperRef, EmulatorCoreTrait, EmulatorMessage,
|
AudioOutput, CameraWrapper, CameraWrapperRef, EmulatorCoreTrait, EmulatorMessage,
|
||||||
EmulatorOptions, NoCamera, PocketCamera, Renderer, RomFile, SerialTarget, SramType,
|
EmulatorOptions, PocketCamera, Renderer, RomFile, SramType,
|
||||||
};
|
};
|
||||||
use processor::{
|
use processor::{
|
||||||
memory::{
|
memory::{
|
||||||
|
@ -14,7 +14,7 @@ use processor::{
|
||||||
rom::{sram_save::SaveDataLocation, CgbRomType},
|
rom::{sram_save::SaveDataLocation, CgbRomType},
|
||||||
OutputTargets, Rom,
|
OutputTargets, Rom,
|
||||||
},
|
},
|
||||||
Cpu, CpuSaveState,
|
Cpu,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
fs::{self},
|
fs::{self},
|
||||||
|
@ -186,13 +186,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get_save_state(&self) -> CpuSaveState<ColourFormat, R>
|
|
||||||
where
|
|
||||||
ColourFormat: From<Colour> + Clone,
|
|
||||||
R: Renderer<ColourFormat>,
|
|
||||||
{
|
|
||||||
CpuSaveState::create(&self.cpu)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColourFormat, R, C> EmulatorCoreTrait for EmulatorCore<ColourFormat, R, C>
|
impl<ColourFormat, R, C> EmulatorCoreTrait for EmulatorCore<ColourFormat, R, C>
|
||||||
|
@ -254,41 +247,3 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColourFormat, R> EmulatorCore<ColourFormat, R, NoCamera>
|
|
||||||
where
|
|
||||||
ColourFormat: From<Colour> + Clone,
|
|
||||||
R: Renderer<ColourFormat>,
|
|
||||||
{
|
|
||||||
pub fn from_save_state(
|
|
||||||
state: CpuSaveState<ColourFormat, R>,
|
|
||||||
rom: RomFile,
|
|
||||||
receiver: Receiver<EmulatorMessage>,
|
|
||||||
window: R,
|
|
||||||
output: AudioOutput,
|
|
||||||
serial_target: SerialTarget,
|
|
||||||
) -> Self {
|
|
||||||
let data = match rom {
|
|
||||||
RomFile::Path(path) => match fs::read(path) {
|
|
||||||
Ok(data) => data,
|
|
||||||
Err(e) => {
|
|
||||||
println!("Error reading ROM: {e}");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
RomFile::Raw(data) => data,
|
|
||||||
};
|
|
||||||
Self {
|
|
||||||
receiver,
|
|
||||||
cpu: Cpu::from_save_state(
|
|
||||||
state,
|
|
||||||
data,
|
|
||||||
window,
|
|
||||||
output,
|
|
||||||
serial_target,
|
|
||||||
Arc::new(Mutex::new(CameraWrapper::new(NoCamera::default()))),
|
|
||||||
),
|
|
||||||
spooky: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,13 +4,10 @@ pub use self::rom::Rom;
|
||||||
use self::{
|
use self::{
|
||||||
addresses::{Address, AddressMarker, CgbIoAddress, IoAddress},
|
addresses::{Address, AddressMarker, CgbIoAddress, IoAddress},
|
||||||
mmio::{
|
mmio::{
|
||||||
apu::ApuSaveState,
|
|
||||||
cgb::{DoubleSpeed, Infrared, VramDma},
|
cgb::{DoubleSpeed, Infrared, VramDma},
|
||||||
gpu::{Colour, GpuSaveState},
|
gpu::Colour,
|
||||||
serial::SerialSaveState,
|
|
||||||
Apu, Gpu, Joypad, OamDma, Serial, Timer,
|
Apu, Gpu, Joypad, OamDma, Serial, Timer,
|
||||||
},
|
},
|
||||||
rom::RomSaveState,
|
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
connect::{AudioOutput, CameraWrapperRef, JoypadState, PocketCamera, Renderer, SerialTarget},
|
connect::{AudioOutput, CameraWrapperRef, JoypadState, PocketCamera, Renderer, SerialTarget},
|
||||||
|
@ -112,56 +109,6 @@ where
|
||||||
cgb_peripherals: Option<CgbPeripherals>,
|
cgb_peripherals: Option<CgbPeripherals>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[serde_with::serde_as]
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct MemorySaveState<ColourFormat, R>
|
|
||||||
where
|
|
||||||
ColourFormat: From<Colour> + Clone,
|
|
||||||
R: Renderer<ColourFormat>,
|
|
||||||
{
|
|
||||||
rom: RomSaveState,
|
|
||||||
ram: Wram,
|
|
||||||
#[serde_as(as = "[_; 128]")]
|
|
||||||
cpu_ram: [u8; 128],
|
|
||||||
pub(super) interrupts: Interrupts,
|
|
||||||
pub(super) ime: bool,
|
|
||||||
pub(super) ime_scheduled: u8,
|
|
||||||
pub(super) user_mode: bool,
|
|
||||||
oam_dma: OamDma,
|
|
||||||
joypad: Joypad,
|
|
||||||
gpu: GpuSaveState<ColourFormat, R>,
|
|
||||||
apu: ApuSaveState,
|
|
||||||
serial: SerialSaveState,
|
|
||||||
timers: Timer,
|
|
||||||
cgb_peripherals: Option<CgbPeripherals>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<ColourFormat, R> MemorySaveState<ColourFormat, R>
|
|
||||||
where
|
|
||||||
ColourFormat: From<Colour> + Clone,
|
|
||||||
R: Renderer<ColourFormat>,
|
|
||||||
// C: PocketCamera + Send + 'static,
|
|
||||||
{
|
|
||||||
pub fn create<C: PocketCamera + Send + 'static>(memory: &Memory<ColourFormat, R, C>) -> Self {
|
|
||||||
Self {
|
|
||||||
rom: RomSaveState::create(&memory.rom),
|
|
||||||
ram: memory.ram.clone(),
|
|
||||||
cpu_ram: memory.cpu_ram,
|
|
||||||
interrupts: memory.interrupts,
|
|
||||||
ime: memory.ime,
|
|
||||||
ime_scheduled: memory.ime_scheduled,
|
|
||||||
user_mode: memory.user_mode,
|
|
||||||
oam_dma: memory.oam_dma,
|
|
||||||
joypad: memory.joypad,
|
|
||||||
gpu: GpuSaveState::create(&memory.gpu),
|
|
||||||
apu: ApuSaveState::create(&memory.apu),
|
|
||||||
serial: SerialSaveState::create(&memory.serial),
|
|
||||||
timers: memory.timers,
|
|
||||||
cgb_peripherals: memory.cgb_peripherals,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct OutputTargets<ColourFormat, R, C>
|
pub(crate) struct OutputTargets<ColourFormat, R, C>
|
||||||
where
|
where
|
||||||
ColourFormat: From<Colour> + Clone,
|
ColourFormat: From<Colour> + Clone,
|
||||||
|
@ -455,34 +402,6 @@ where
|
||||||
pub fn replace_output(&mut self, new: AudioOutput) {
|
pub fn replace_output(&mut self, new: AudioOutput) {
|
||||||
self.apu.replace_output(new);
|
self.apu.replace_output(new);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_save_state(
|
|
||||||
state: MemorySaveState<ColourFormat, R>,
|
|
||||||
data: Vec<u8>,
|
|
||||||
window: R,
|
|
||||||
output: AudioOutput,
|
|
||||||
serial_target: SerialTarget,
|
|
||||||
camera: CameraWrapperRef<C>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
bootrom: None,
|
|
||||||
rom: Rom::from_save_state(state.rom, data, camera.clone()),
|
|
||||||
ram: state.ram,
|
|
||||||
cpu_ram: state.cpu_ram,
|
|
||||||
interrupts: state.interrupts,
|
|
||||||
ime: state.ime,
|
|
||||||
ime_scheduled: state.ime_scheduled,
|
|
||||||
user_mode: state.user_mode,
|
|
||||||
oam_dma: state.oam_dma,
|
|
||||||
joypad: state.joypad,
|
|
||||||
gpu: Gpu::from_save_state(state.gpu, window, None),
|
|
||||||
apu: Apu::from_save_state(state.apu, output),
|
|
||||||
serial: Serial::from_save_state(state.serial, serial_target),
|
|
||||||
timers: state.timers,
|
|
||||||
camera,
|
|
||||||
cgb_peripherals: state.cgb_peripherals,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColourFormat, R, C> Cpu<ColourFormat, R, C>
|
impl<ColourFormat, R, C> Cpu<ColourFormat, R, C>
|
||||||
|
|
|
@ -9,7 +9,6 @@ use crate::{
|
||||||
};
|
};
|
||||||
use futures::executor;
|
use futures::executor;
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
mod channels;
|
mod channels;
|
||||||
mod downsampler;
|
mod downsampler;
|
||||||
|
@ -46,27 +45,6 @@ pub struct Apu {
|
||||||
output: AudioOutput,
|
output: AudioOutput,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct ApuSaveState {
|
|
||||||
apu_enable: bool,
|
|
||||||
channels: Channels,
|
|
||||||
vin: VinEnable,
|
|
||||||
mixer: Mixer,
|
|
||||||
div_apu: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ApuSaveState {
|
|
||||||
pub fn create(apu: &Apu) -> Self {
|
|
||||||
Self {
|
|
||||||
apu_enable: apu.apu_enable,
|
|
||||||
channels: apu.channels,
|
|
||||||
vin: apu.vin,
|
|
||||||
mixer: apu.mixer,
|
|
||||||
div_apu: apu.div_apu,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Apu {
|
impl Apu {
|
||||||
pub fn new(output: AudioOutput) -> Self {
|
pub fn new(output: AudioOutput) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -80,18 +58,6 @@ impl Apu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_save_state(state: ApuSaveState, output: AudioOutput) -> Self {
|
|
||||||
Self {
|
|
||||||
apu_enable: state.apu_enable,
|
|
||||||
channels: state.channels,
|
|
||||||
vin: state.vin,
|
|
||||||
mixer: state.mixer,
|
|
||||||
div_apu: state.div_apu,
|
|
||||||
converter: Downsampler::new(output.sample_rate, output.downsample_type),
|
|
||||||
output,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn replace_output(&mut self, new: AudioOutput) {
|
pub fn replace_output(&mut self, new: AudioOutput) {
|
||||||
self.converter = Downsampler::new(new.sample_rate, new.downsample_type);
|
self.converter = Downsampler::new(new.sample_rate, new.downsample_type);
|
||||||
self.output = new;
|
self.output = new;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
pub(crate) use self::types::DrawMode;
|
pub(crate) use self::types::DrawMode;
|
||||||
use self::{
|
use self::{
|
||||||
cgb::CgbData,
|
cgb::CgbData,
|
||||||
|
@ -15,7 +13,6 @@ use crate::{
|
||||||
util::{clear_bit, get_bit},
|
util::{clear_bit, get_bit},
|
||||||
HEIGHT, WIDTH,
|
HEIGHT, WIDTH,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
pub use types::Colour;
|
pub use types::Colour;
|
||||||
|
|
||||||
mod addresses;
|
mod addresses;
|
||||||
|
@ -56,70 +53,6 @@ where
|
||||||
cgb_data: Option<CgbData>,
|
cgb_data: Option<CgbData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct GpuSaveState<ColourFormat, R>
|
|
||||||
where
|
|
||||||
ColourFormat: From<Colour> + Clone,
|
|
||||||
R: Renderer<ColourFormat>,
|
|
||||||
{
|
|
||||||
buffer: Vec<ColourFormat>,
|
|
||||||
vram: Vram,
|
|
||||||
oam: Oam,
|
|
||||||
is_bg_zero: Vec<bool>,
|
|
||||||
is_bg_priority: Vec<bool>,
|
|
||||||
lcdc: Lcdc,
|
|
||||||
stat: Stat,
|
|
||||||
mode_clock: usize,
|
|
||||||
scanline: u8,
|
|
||||||
lyc: u8,
|
|
||||||
window_lc: u8,
|
|
||||||
has_window_been_enabled: bool,
|
|
||||||
bg_palette: Palette,
|
|
||||||
obj_palette_0: Palette,
|
|
||||||
obj_palette_1: Palette,
|
|
||||||
scx: u8,
|
|
||||||
scy: u8,
|
|
||||||
wx: u8,
|
|
||||||
wy: u8,
|
|
||||||
prev_stat: bool,
|
|
||||||
cgb_data: Option<CgbData>,
|
|
||||||
#[serde(skip)]
|
|
||||||
spooky: PhantomData<R>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<ColourFormat, R> GpuSaveState<ColourFormat, R>
|
|
||||||
where
|
|
||||||
ColourFormat: From<Colour> + Clone,
|
|
||||||
R: Renderer<ColourFormat>,
|
|
||||||
{
|
|
||||||
pub fn create(gpu: &Gpu<ColourFormat, R>) -> Self {
|
|
||||||
Self {
|
|
||||||
buffer: gpu.buffer.clone(),
|
|
||||||
vram: gpu.vram.clone(),
|
|
||||||
oam: gpu.oam,
|
|
||||||
is_bg_zero: gpu.is_bg_zero.clone(),
|
|
||||||
is_bg_priority: gpu.is_bg_priority.clone(),
|
|
||||||
lcdc: gpu.lcdc,
|
|
||||||
stat: gpu.stat,
|
|
||||||
mode_clock: gpu.mode_clock,
|
|
||||||
scanline: gpu.scanline,
|
|
||||||
lyc: gpu.lyc,
|
|
||||||
window_lc: gpu.window_lc,
|
|
||||||
has_window_been_enabled: gpu.has_window_been_enabled,
|
|
||||||
bg_palette: gpu.bg_palette,
|
|
||||||
obj_palette_0: gpu.obj_palette_0,
|
|
||||||
obj_palette_1: gpu.obj_palette_1,
|
|
||||||
scx: gpu.scx,
|
|
||||||
scy: gpu.scy,
|
|
||||||
wx: gpu.wx,
|
|
||||||
wy: gpu.wy,
|
|
||||||
prev_stat: gpu.prev_stat,
|
|
||||||
cgb_data: gpu.cgb_data,
|
|
||||||
spooky: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<ColourFormat, R> Gpu<ColourFormat, R>
|
impl<ColourFormat, R> Gpu<ColourFormat, R>
|
||||||
where
|
where
|
||||||
ColourFormat: From<Colour> + Clone,
|
ColourFormat: From<Colour> + Clone,
|
||||||
|
@ -157,47 +90,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_save_state(
|
|
||||||
state: GpuSaveState<ColourFormat, R>,
|
|
||||||
window: R,
|
|
||||||
tile_window_renderer: Option<R>,
|
|
||||||
) -> Self {
|
|
||||||
let tile_window = if let Some(tile_window_renderer) = tile_window_renderer {
|
|
||||||
Some(TileWindow::new(
|
|
||||||
tile_window_renderer,
|
|
||||||
state.cgb_data.is_some(),
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
|
||||||
buffer: state.buffer,
|
|
||||||
vram: state.vram,
|
|
||||||
oam: state.oam,
|
|
||||||
window,
|
|
||||||
is_bg_zero: state.is_bg_zero,
|
|
||||||
is_bg_priority: state.is_bg_priority,
|
|
||||||
lcdc: state.lcdc,
|
|
||||||
stat: state.stat,
|
|
||||||
mode_clock: state.mode_clock,
|
|
||||||
scanline: state.scanline,
|
|
||||||
lyc: state.lyc,
|
|
||||||
tile_window,
|
|
||||||
window_lc: state.window_lc,
|
|
||||||
has_window_been_enabled: state.has_window_been_enabled,
|
|
||||||
bg_palette: state.bg_palette,
|
|
||||||
obj_palette_0: state.obj_palette_0,
|
|
||||||
obj_palette_1: state.obj_palette_1,
|
|
||||||
scx: state.scx,
|
|
||||||
scy: state.scy,
|
|
||||||
wx: state.wx,
|
|
||||||
wy: state.wy,
|
|
||||||
prev_stat: state.prev_stat,
|
|
||||||
cgb_data: state.cgb_data,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn get_mode(&self) -> DrawMode {
|
pub(crate) fn get_mode(&self) -> DrawMode {
|
||||||
self.stat.mode
|
self.stat.mode
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,31 +111,6 @@ pub struct Serial {
|
||||||
clock_inc: usize,
|
clock_inc: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct SerialSaveState {
|
|
||||||
byte: u8,
|
|
||||||
output_byte: u8,
|
|
||||||
input_byte: InputByte,
|
|
||||||
bits_remaining: u8,
|
|
||||||
control: SerialControl,
|
|
||||||
#[cfg(feature = "clocked-serial")]
|
|
||||||
clock_inc: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SerialSaveState {
|
|
||||||
pub fn create(serial: &Serial) -> Self {
|
|
||||||
Self {
|
|
||||||
byte: serial.byte,
|
|
||||||
output_byte: serial.output_byte,
|
|
||||||
input_byte: serial.input_byte,
|
|
||||||
bits_remaining: serial.bits_remaining,
|
|
||||||
control: serial.control,
|
|
||||||
#[cfg(feature = "clocked-serial")]
|
|
||||||
clock_inc: serial.clock_inc,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serial {
|
impl Serial {
|
||||||
pub fn new(target: SerialTarget) -> Self {
|
pub fn new(target: SerialTarget) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -150,19 +125,6 @@ impl Serial {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_save_state(state: SerialSaveState, target: SerialTarget) -> Self {
|
|
||||||
Self {
|
|
||||||
byte: state.byte,
|
|
||||||
output_byte: state.output_byte,
|
|
||||||
input_byte: state.input_byte,
|
|
||||||
bits_remaining: state.bits_remaining,
|
|
||||||
control: state.control,
|
|
||||||
target,
|
|
||||||
#[cfg(feature = "clocked-serial")]
|
|
||||||
clock_inc: state.clock_inc,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_connected(&self) -> bool {
|
fn is_connected(&self) -> bool {
|
||||||
!matches!(&self.target, SerialTarget::None)
|
!matches!(&self.target, SerialTarget::None)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
use self::{
|
use self::{
|
||||||
mbcs::{
|
mbcs::{Mbc, Mbc1, Mbc2, Mbc3, Mbc5, None, PocketCamera},
|
||||||
Mbc, Mbc1, Mbc1SaveState, Mbc2, Mbc2SaveState, Mbc3, Mbc3SaveState, Mbc5, Mbc5SaveState,
|
|
||||||
None, PocketCamera, PocketCameraSaveState,
|
|
||||||
},
|
|
||||||
sram_save::SaveDataLocation,
|
sram_save::SaveDataLocation,
|
||||||
};
|
};
|
||||||
use crate::connect::{CameraWrapperRef, PocketCamera as PocketCameraTrait};
|
use crate::connect::{CameraWrapperRef, PocketCamera as PocketCameraTrait};
|
||||||
|
@ -31,50 +28,6 @@ where
|
||||||
spooky: PhantomData<C>,
|
spooky: PhantomData<C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct RomSaveState {
|
|
||||||
title: String,
|
|
||||||
mbc: MbcSaveState,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RomSaveState {
|
|
||||||
pub fn create<C: PocketCameraTrait>(rom: &Rom<C>) -> Self {
|
|
||||||
Self {
|
|
||||||
title: rom.title.clone(),
|
|
||||||
mbc: rom.mbc.get_save_state(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
enum MbcSaveState {
|
|
||||||
Mbc1(Mbc1SaveState),
|
|
||||||
Mbc2(Mbc2SaveState),
|
|
||||||
Mbc3(Mbc3SaveState),
|
|
||||||
Mbc5(Mbc5SaveState),
|
|
||||||
PocketCamera(PocketCameraSaveState),
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MbcSaveState {
|
|
||||||
fn get_mbc<C: PocketCameraTrait + Send + 'static>(
|
|
||||||
self,
|
|
||||||
data: Vec<u8>,
|
|
||||||
camera: CameraWrapperRef<C>,
|
|
||||||
) -> Box<dyn Mbc> {
|
|
||||||
match self {
|
|
||||||
MbcSaveState::Mbc1(state) => Box::new(Mbc1::from_save_state(state, data)),
|
|
||||||
MbcSaveState::Mbc2(state) => Box::new(Mbc2::from_save_state(state, data)),
|
|
||||||
MbcSaveState::Mbc3(state) => Box::new(Mbc3::from_save_state(state, data)),
|
|
||||||
MbcSaveState::Mbc5(state) => Box::new(Mbc5::from_save_state(state, data)),
|
|
||||||
MbcSaveState::None => Box::new(None::init(data)),
|
|
||||||
MbcSaveState::PocketCamera(state) => {
|
|
||||||
Box::new(PocketCamera::from_save_state(state, data, camera))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C> Rom<C>
|
impl<C> Rom<C>
|
||||||
where
|
where
|
||||||
C: PocketCameraTrait + Send + 'static,
|
C: PocketCameraTrait + Send + 'static,
|
||||||
|
@ -135,20 +88,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_save_state(
|
|
||||||
state: RomSaveState,
|
|
||||||
data: Vec<u8>,
|
|
||||||
camera: CameraWrapperRef<C>,
|
|
||||||
) -> Self {
|
|
||||||
let rom_type = get_cgb_rom_type(data[0x143]);
|
|
||||||
Self {
|
|
||||||
title: state.title,
|
|
||||||
mbc: state.mbc.get_mbc(data, camera),
|
|
||||||
rom_type,
|
|
||||||
spooky: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_title(&self) -> &String {
|
pub fn get_title(&self) -> &String {
|
||||||
&self.title
|
&self.title
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,12 @@ mod mbc3;
|
||||||
mod mbc5;
|
mod mbc5;
|
||||||
mod none;
|
mod none;
|
||||||
mod pocketcamera;
|
mod pocketcamera;
|
||||||
pub use mbc1::{Mbc1, Mbc1SaveState};
|
pub use mbc1::Mbc1;
|
||||||
pub use mbc2::{Mbc2, Mbc2SaveState};
|
pub use mbc2::Mbc2;
|
||||||
pub use mbc3::{Mbc3, Mbc3SaveState};
|
pub use mbc3::Mbc3;
|
||||||
pub use mbc5::{Mbc5, Mbc5SaveState};
|
pub use mbc5::Mbc5;
|
||||||
pub use none::None;
|
pub use none::None;
|
||||||
pub use pocketcamera::{PocketCamera, PocketCameraSaveState};
|
pub use pocketcamera::PocketCamera;
|
||||||
|
|
||||||
use super::MbcSaveState;
|
|
||||||
|
|
||||||
pub(super) const KB: usize = 1024;
|
pub(super) const KB: usize = 1024;
|
||||||
const ROM_BANK_SIZE: usize = 16 * KB;
|
const ROM_BANK_SIZE: usize = 16 * KB;
|
||||||
|
@ -27,7 +25,6 @@ pub(super) trait Mbc: Send {
|
||||||
fn set(&mut self, address: RomAddress, data: u8);
|
fn set(&mut self, address: RomAddress, data: u8);
|
||||||
fn set_ram(&mut self, address: CartRamAddress, data: u8);
|
fn set_ram(&mut self, address: CartRamAddress, data: u8);
|
||||||
fn mbc_type(&self) -> String;
|
fn mbc_type(&self) -> String;
|
||||||
fn get_save_state(&self) -> MbcSaveState;
|
|
||||||
fn is_rumbling(&self) -> bool {
|
fn is_rumbling(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
use super::{ram_size_kb, rom_banks, Mbc, KB, RAM_BANK_SIZE, ROM_BANK_SIZE};
|
use super::{ram_size_kb, rom_banks, Mbc, KB, RAM_BANK_SIZE, ROM_BANK_SIZE};
|
||||||
use crate::processor::memory::{
|
use crate::processor::memory::{
|
||||||
addresses::{AddressMarker, CartRamAddress, RomAddress},
|
addresses::{AddressMarker, CartRamAddress, RomAddress},
|
||||||
rom::{
|
rom::sram_save::{BufferedSramTrait, MaybeBufferedSram, SaveDataLocation},
|
||||||
sram_save::{BufferedSramTrait, MaybeBufferedSram, SaveDataLocation, SramSaveState},
|
|
||||||
MbcSaveState,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -25,17 +22,6 @@ pub struct Mbc1 {
|
||||||
bank_mode: BankingMode,
|
bank_mode: BankingMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Mbc1SaveState {
|
|
||||||
rom_len: usize,
|
|
||||||
rom_bank: u8,
|
|
||||||
ram_enabled: bool,
|
|
||||||
ram: Option<SramSaveState>,
|
|
||||||
ram_bank: u8,
|
|
||||||
upper_banks: u8,
|
|
||||||
bank_mode: BankingMode,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mbc1 {
|
impl Mbc1 {
|
||||||
pub fn init(
|
pub fn init(
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
|
@ -86,19 +72,6 @@ impl Mbc1 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_save_state(state: Mbc1SaveState, data: Vec<u8>) -> Self {
|
|
||||||
Self {
|
|
||||||
data,
|
|
||||||
rom_len: state.rom_len,
|
|
||||||
rom_bank: state.rom_bank,
|
|
||||||
ram_enabled: state.ram_enabled,
|
|
||||||
ram: state.ram.map(MaybeBufferedSram::from_save_state),
|
|
||||||
ram_bank: state.ram_bank,
|
|
||||||
upper_banks: state.upper_banks,
|
|
||||||
bank_mode: state.bank_mode,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mbc for Mbc1 {
|
impl Mbc for Mbc1 {
|
||||||
|
@ -165,16 +138,4 @@ impl Mbc for Mbc1 {
|
||||||
ram.flush();
|
ram.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_save_state(&self) -> MbcSaveState {
|
|
||||||
MbcSaveState::Mbc1(Mbc1SaveState {
|
|
||||||
rom_len: self.rom_len,
|
|
||||||
rom_bank: self.rom_bank,
|
|
||||||
ram_enabled: self.ram_enabled,
|
|
||||||
ram: self.ram.as_ref().map(SramSaveState::create),
|
|
||||||
ram_bank: self.ram_bank,
|
|
||||||
upper_banks: self.upper_banks,
|
|
||||||
bank_mode: self.bank_mode,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
|
use super::{rom_banks, Mbc, ROM_BANK_SIZE};
|
||||||
use crate::processor::memory::{
|
use crate::processor::memory::{
|
||||||
addresses::{AddressMarker, CartRamAddress, RomAddress},
|
addresses::{AddressMarker, CartRamAddress, RomAddress},
|
||||||
rom::{
|
rom::sram_save::{BufferedSramTrait, MaybeBufferedSram, SaveDataLocation},
|
||||||
sram_save::{BufferedSramTrait, MaybeBufferedSram, SaveDataLocation, SramSaveState},
|
|
||||||
MbcSaveState,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use super::{rom_banks, Mbc, ROM_BANK_SIZE};
|
|
||||||
|
|
||||||
pub struct Mbc2 {
|
pub struct Mbc2 {
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
|
@ -17,14 +12,6 @@ pub struct Mbc2 {
|
||||||
ram_enabled: bool,
|
ram_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Mbc2SaveState {
|
|
||||||
rom_len: usize,
|
|
||||||
rom_bank: u8,
|
|
||||||
ram: SramSaveState,
|
|
||||||
ram_enabled: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mbc2 {
|
impl Mbc2 {
|
||||||
pub fn init(data: Vec<u8>, rom_size: u8, save_file: Option<SaveDataLocation>) -> Self {
|
pub fn init(data: Vec<u8>, rom_size: u8, save_file: Option<SaveDataLocation>) -> Self {
|
||||||
let rom_len = rom_banks(rom_size) * ROM_BANK_SIZE;
|
let rom_len = rom_banks(rom_size) * ROM_BANK_SIZE;
|
||||||
|
@ -38,16 +25,6 @@ impl Mbc2 {
|
||||||
ram_enabled: false,
|
ram_enabled: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_save_state(state: Mbc2SaveState, data: Vec<u8>) -> Self {
|
|
||||||
Self {
|
|
||||||
data,
|
|
||||||
rom_len: state.rom_len,
|
|
||||||
rom_bank: state.rom_bank,
|
|
||||||
ram: MaybeBufferedSram::from_save_state(state.ram),
|
|
||||||
ram_enabled: state.ram_enabled,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mbc for Mbc2 {
|
impl Mbc for Mbc2 {
|
||||||
|
@ -97,13 +74,4 @@ impl Mbc for Mbc2 {
|
||||||
fn flush(&mut self) {
|
fn flush(&mut self) {
|
||||||
self.ram.flush();
|
self.ram.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_save_state(&self) -> MbcSaveState {
|
|
||||||
MbcSaveState::Mbc2(Mbc2SaveState {
|
|
||||||
rom_len: self.rom_len,
|
|
||||||
rom_bank: self.rom_bank,
|
|
||||||
ram: SramSaveState::create(&self.ram),
|
|
||||||
ram_enabled: self.ram_enabled,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,7 @@ use super::{ram_size_kb, rom_banks, Mbc, KB, RAM_BANK_SIZE, ROM_BANK_SIZE};
|
||||||
use crate::{
|
use crate::{
|
||||||
processor::memory::{
|
processor::memory::{
|
||||||
addresses::{AddressMarker, CartRamAddress, RomAddress},
|
addresses::{AddressMarker, CartRamAddress, RomAddress},
|
||||||
rom::{
|
rom::sram_save::{BufferedSramTrait, MaybeBufferedSram, SaveDataLocation},
|
||||||
sram_save::{BufferedSramTrait, MaybeBufferedSram, SaveDataLocation, SramSaveState},
|
|
||||||
MbcSaveState,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
util::set_or_clear_bit,
|
util::set_or_clear_bit,
|
||||||
};
|
};
|
||||||
|
@ -95,16 +92,6 @@ pub struct Mbc3 {
|
||||||
// TODO - save/load rtc!!
|
// TODO - save/load rtc!!
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Mbc3SaveState {
|
|
||||||
rom_bank: u8,
|
|
||||||
rom_size: usize,
|
|
||||||
ram: Option<SramSaveState>,
|
|
||||||
ram_bank: RamBank,
|
|
||||||
ram_size: usize,
|
|
||||||
ram_enabled: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mbc3 {
|
impl Mbc3 {
|
||||||
pub fn init(
|
pub fn init(
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
|
@ -139,20 +126,6 @@ impl Mbc3 {
|
||||||
fn get_ram_addr(&self, address: CartRamAddress, ram_bank: usize) -> usize {
|
fn get_ram_addr(&self, address: CartRamAddress, ram_bank: usize) -> usize {
|
||||||
((address.get_local() as usize) + (RAM_BANK_SIZE * ram_bank)) % self.ram_size
|
((address.get_local() as usize) + (RAM_BANK_SIZE * ram_bank)) % self.ram_size
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_save_state(state: Mbc3SaveState, data: Vec<u8>) -> Self {
|
|
||||||
// TODO - FIX RTC!!!
|
|
||||||
Self {
|
|
||||||
data,
|
|
||||||
rom_bank: state.rom_bank,
|
|
||||||
rom_size: state.rom_size,
|
|
||||||
ram: state.ram.map(MaybeBufferedSram::from_save_state),
|
|
||||||
ram_bank: state.ram_bank,
|
|
||||||
ram_size: state.ram_size,
|
|
||||||
ram_enabled: state.ram_enabled,
|
|
||||||
rtc: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mbc for Mbc3 {
|
impl Mbc for Mbc3 {
|
||||||
|
@ -255,15 +228,4 @@ impl Mbc for Mbc3 {
|
||||||
ram.flush();
|
ram.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_save_state(&self) -> MbcSaveState {
|
|
||||||
MbcSaveState::Mbc3(Mbc3SaveState {
|
|
||||||
rom_bank: self.rom_bank,
|
|
||||||
rom_size: self.rom_size,
|
|
||||||
ram: self.ram.as_ref().map(SramSaveState::create),
|
|
||||||
ram_bank: self.ram_bank,
|
|
||||||
ram_size: self.ram_size,
|
|
||||||
ram_enabled: self.ram_enabled,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
processor::memory::{
|
processor::memory::{
|
||||||
addresses::{AddressMarker, CartRamAddress, RomAddress},
|
addresses::{AddressMarker, CartRamAddress, RomAddress},
|
||||||
rom::{
|
rom::sram_save::{BufferedSramTrait, MaybeBufferedSram, SaveDataLocation},
|
||||||
sram_save::{BufferedSramTrait, MaybeBufferedSram, SaveDataLocation, SramSaveState},
|
|
||||||
MbcSaveState,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
util::get_bit,
|
util::get_bit,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use super::{ram_size_kb, rom_banks, Mbc, KB, RAM_BANK_SIZE, ROM_BANK_SIZE};
|
use super::{ram_size_kb, rom_banks, Mbc, KB, RAM_BANK_SIZE, ROM_BANK_SIZE};
|
||||||
|
|
||||||
|
@ -24,18 +20,6 @@ pub struct Mbc5 {
|
||||||
is_rumbling: bool,
|
is_rumbling: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Mbc5SaveState {
|
|
||||||
rom_bank: u16,
|
|
||||||
rom_size: usize,
|
|
||||||
ram: Option<SramSaveState>,
|
|
||||||
ram_bank: u8,
|
|
||||||
ram_size: usize,
|
|
||||||
ram_enabled: bool,
|
|
||||||
rumble: bool,
|
|
||||||
is_rumbling: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mbc5 {
|
impl Mbc5 {
|
||||||
pub fn init(
|
pub fn init(
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
|
@ -71,20 +55,6 @@ impl Mbc5 {
|
||||||
fn get_ram_addr(&self, address: CartRamAddress) -> usize {
|
fn get_ram_addr(&self, address: CartRamAddress) -> usize {
|
||||||
((address.get_local() as usize) + (RAM_BANK_SIZE * self.ram_bank as usize)) % self.ram_size
|
((address.get_local() as usize) + (RAM_BANK_SIZE * self.ram_bank as usize)) % self.ram_size
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_save_state(state: Mbc5SaveState, data: Vec<u8>) -> Self {
|
|
||||||
Self {
|
|
||||||
data,
|
|
||||||
rom_bank: state.rom_bank,
|
|
||||||
rom_size: state.rom_size,
|
|
||||||
ram: state.ram.map(MaybeBufferedSram::from_save_state),
|
|
||||||
ram_bank: state.ram_bank,
|
|
||||||
ram_size: state.ram_size,
|
|
||||||
ram_enabled: state.ram_enabled,
|
|
||||||
rumble: state.rumble,
|
|
||||||
is_rumbling: state.is_rumbling,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mbc for Mbc5 {
|
impl Mbc for Mbc5 {
|
||||||
|
@ -157,17 +127,4 @@ impl Mbc for Mbc5 {
|
||||||
ram.flush();
|
ram.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_save_state(&self) -> MbcSaveState {
|
|
||||||
MbcSaveState::Mbc5(Mbc5SaveState {
|
|
||||||
rom_bank: self.rom_bank,
|
|
||||||
rom_size: self.rom_size,
|
|
||||||
ram: self.ram.as_ref().map(SramSaveState::create),
|
|
||||||
ram_bank: self.ram_bank,
|
|
||||||
ram_size: self.ram_size,
|
|
||||||
ram_enabled: self.ram_enabled,
|
|
||||||
rumble: self.rumble,
|
|
||||||
is_rumbling: self.is_rumbling,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
use super::Mbc;
|
use super::Mbc;
|
||||||
use crate::processor::memory::{
|
use crate::processor::memory::addresses::{AddressMarker, CartRamAddress, RomAddress};
|
||||||
addresses::{AddressMarker, CartRamAddress, RomAddress},
|
|
||||||
rom::MbcSaveState,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct None {
|
pub struct None {
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
|
@ -30,8 +27,4 @@ impl Mbc for None {
|
||||||
fn mbc_type(&self) -> String {
|
fn mbc_type(&self) -> String {
|
||||||
String::from("None")
|
String::from("None")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_save_state(&self) -> MbcSaveState {
|
|
||||||
MbcSaveState::None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,9 @@ use crate::{
|
||||||
connect::{CameraWrapperRef, PocketCamera as PocketCameraTrait},
|
connect::{CameraWrapperRef, PocketCamera as PocketCameraTrait},
|
||||||
processor::memory::{
|
processor::memory::{
|
||||||
addresses::{AddressMarker, CartRamAddress, RomAddress},
|
addresses::{AddressMarker, CartRamAddress, RomAddress},
|
||||||
rom::{
|
rom::sram_save::{BufferedSramTrait, MaybeBufferedSram, SaveDataLocation},
|
||||||
sram_save::{BufferedSramTrait, MaybeBufferedSram, SaveDataLocation},
|
|
||||||
MbcSaveState,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
enum RamBank {
|
enum RamBank {
|
||||||
Ram(u8),
|
Ram(u8),
|
||||||
|
@ -32,9 +28,6 @@ where
|
||||||
camera_ram: [u8; 53],
|
camera_ram: [u8; 53],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct PocketCameraSaveState;
|
|
||||||
|
|
||||||
impl<C> PocketCamera<C>
|
impl<C> PocketCamera<C>
|
||||||
where
|
where
|
||||||
C: PocketCameraTrait,
|
C: PocketCameraTrait,
|
||||||
|
@ -76,14 +69,6 @@ where
|
||||||
((address.get_local() as usize) + (RAM_BANK_SIZE * bank as usize)) % self.ram_size
|
((address.get_local() as usize) + (RAM_BANK_SIZE * bank as usize)) % self.ram_size
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_save_state(
|
|
||||||
_state: PocketCameraSaveState,
|
|
||||||
_data: Vec<u8>,
|
|
||||||
_camera: CameraWrapperRef<C>,
|
|
||||||
) -> Self {
|
|
||||||
todo!();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_cam_reg(&self, address: CartRamAddress) -> u8 {
|
fn get_cam_reg(&self, address: CartRamAddress) -> u8 {
|
||||||
match address.inner() {
|
match address.inner() {
|
||||||
0xA000 => {
|
0xA000 => {
|
||||||
|
@ -202,8 +187,4 @@ where
|
||||||
ram.flush();
|
ram.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_save_state(&self) -> MbcSaveState {
|
|
||||||
MbcSaveState::PocketCamera(PocketCameraSaveState)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::{
|
use std::{
|
||||||
fs::{File, OpenOptions},
|
fs::{File, OpenOptions},
|
||||||
io::{Read, Seek, SeekFrom, Write},
|
io::{Read, Seek, SeekFrom, Write},
|
||||||
|
@ -28,10 +27,6 @@ impl MaybeBufferedSram {
|
||||||
None => Self::Unbuffered(UnbufferedSram::new(length)),
|
None => Self::Unbuffered(UnbufferedSram::new(length)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_save_state(state: SramSaveState) -> Self {
|
|
||||||
Self::Unbuffered(UnbufferedSram::new(state.length))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct UnbufferedSram {
|
pub(crate) struct UnbufferedSram {
|
||||||
|
@ -228,17 +223,6 @@ impl BufferedSramTrait for MaybeBufferedSram {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub(crate) struct SramSaveState {
|
|
||||||
length: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SramSaveState {
|
|
||||||
pub fn create(sram: &MaybeBufferedSram) -> Self {
|
|
||||||
Self { length: sram.len() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for MaybeBufferedSram {
|
impl Drop for MaybeBufferedSram {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.flush();
|
self.flush();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use self::memory::{mmio::gpu::Colour, Interrupt, Memory, MemorySaveState};
|
use self::memory::{mmio::gpu::Colour, Interrupt, Memory};
|
||||||
use crate::connect::{AudioOutput, CameraWrapperRef, PocketCamera, Renderer, SerialTarget};
|
use crate::connect::{PocketCamera, Renderer};
|
||||||
|
|
||||||
mod instructions;
|
mod instructions;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
|
@ -36,39 +36,6 @@ where
|
||||||
pub(crate) is_skipping: bool,
|
pub(crate) is_skipping: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct CpuSaveState<ColourFormat, R>
|
|
||||||
where
|
|
||||||
ColourFormat: From<Colour> + Clone,
|
|
||||||
R: Renderer<ColourFormat>,
|
|
||||||
{
|
|
||||||
memory: MemorySaveState<ColourFormat, R>,
|
|
||||||
reg: Registers,
|
|
||||||
last_instruction: u8,
|
|
||||||
last_instruction_addr: u16,
|
|
||||||
halted: bool,
|
|
||||||
should_halt_bug: bool,
|
|
||||||
cycle_count: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<ColourFormat, R> CpuSaveState<ColourFormat, R>
|
|
||||||
where
|
|
||||||
ColourFormat: From<Colour> + Clone,
|
|
||||||
R: Renderer<ColourFormat>,
|
|
||||||
{
|
|
||||||
pub fn create<C: PocketCamera + Send + 'static>(cpu: &Cpu<ColourFormat, R, C>) -> Self {
|
|
||||||
Self {
|
|
||||||
memory: MemorySaveState::create(&cpu.memory),
|
|
||||||
reg: cpu.reg,
|
|
||||||
last_instruction: cpu.last_instruction,
|
|
||||||
last_instruction_addr: cpu.last_instruction_addr,
|
|
||||||
halted: cpu.halted,
|
|
||||||
should_halt_bug: cpu.should_halt_bug,
|
|
||||||
cycle_count: cpu.cycle_count,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<ColourFormat, R, C> Cpu<ColourFormat, R, C>
|
impl<ColourFormat, R, C> Cpu<ColourFormat, R, C>
|
||||||
where
|
where
|
||||||
ColourFormat: From<Colour> + Clone,
|
ColourFormat: From<Colour> + Clone,
|
||||||
|
@ -178,33 +145,6 @@ where
|
||||||
self.reg.pc = addr;
|
self.reg.pc = addr;
|
||||||
self.memory.ime = false;
|
self.memory.ime = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_save_state(
|
|
||||||
state: CpuSaveState<ColourFormat, R>,
|
|
||||||
data: Vec<u8>,
|
|
||||||
window: R,
|
|
||||||
output: AudioOutput,
|
|
||||||
serial_target: SerialTarget,
|
|
||||||
camera: CameraWrapperRef<C>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
memory: Memory::from_save_state(
|
|
||||||
state.memory,
|
|
||||||
data,
|
|
||||||
window,
|
|
||||||
output,
|
|
||||||
serial_target,
|
|
||||||
camera,
|
|
||||||
),
|
|
||||||
reg: state.reg,
|
|
||||||
last_instruction: state.last_instruction,
|
|
||||||
last_instruction_addr: state.last_instruction_addr,
|
|
||||||
halted: state.halted,
|
|
||||||
should_halt_bug: state.should_halt_bug,
|
|
||||||
cycle_count: state.cycle_count,
|
|
||||||
is_skipping: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
|
Loading…
Add table
Reference in a new issue