load from save state
This commit is contained in:
parent
5db1fc4127
commit
3d5ae32960
|
@ -166,4 +166,27 @@ impl<ColourFormat: From<Colour> + Clone> EmulatorCore<ColourFormat> {
|
||||||
pub fn get_save_state(&self) -> CpuSaveState<ColourFormat> {
|
pub fn get_save_state(&self) -> CpuSaveState<ColourFormat> {
|
||||||
CpuSaveState::create(&self.cpu)
|
CpuSaveState::create(&self.cpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_save_state(
|
||||||
|
state: CpuSaveState<ColourFormat>,
|
||||||
|
rom: RomFile,
|
||||||
|
receiver: Receiver<EmulatorMessage>,
|
||||||
|
window: Box<dyn Renderer<ColourFormat>>,
|
||||||
|
output: AudioOutput,
|
||||||
|
) -> 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),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,6 +276,29 @@ impl<ColourFormat: From<Colour> + Clone> Memory<ColourFormat> {
|
||||||
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 fn from_save_state(
|
||||||
|
state: MemorySaveState<ColourFormat>,
|
||||||
|
data: Vec<u8>,
|
||||||
|
window: Box<dyn Renderer<ColourFormat>>,
|
||||||
|
output: AudioOutput,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
bootrom: None,
|
||||||
|
rom: Rom::from_save_state(state.rom, data),
|
||||||
|
ram: state.ram,
|
||||||
|
cpu_ram: state.cpu_ram,
|
||||||
|
interrupts: state.interrupts,
|
||||||
|
ime: state.ime,
|
||||||
|
ime_scheduled: state.ime_scheduled,
|
||||||
|
dma_addr: state.dma_addr,
|
||||||
|
joypad: state.joypad,
|
||||||
|
gpu: Gpu::from_save_state(state.gpu, window, None),
|
||||||
|
apu: Apu::from_save_state(state.apu, output),
|
||||||
|
serial: state.serial,
|
||||||
|
timers: state.timers,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColourFormat: From<Colour> + Clone> Cpu<ColourFormat> {
|
impl<ColourFormat: From<Colour> + Clone> Cpu<ColourFormat> {
|
||||||
|
|
|
@ -90,6 +90,20 @@ 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,
|
||||||
|
buffer: state.buffer,
|
||||||
|
out_buffer: state.out_buffer,
|
||||||
|
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;
|
||||||
|
|
|
@ -132,6 +132,43 @@ impl<Format: From<Colour> + Clone> Gpu<Format> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_save_state(
|
||||||
|
state: GpuSaveState<Format>,
|
||||||
|
window: Box<dyn Renderer<Format>>,
|
||||||
|
tile_window_renderer: Option<Box<dyn Renderer<Format>>>,
|
||||||
|
) -> 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))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
buffer: state.buffer,
|
||||||
|
vram: state.vram,
|
||||||
|
oam: state.oam,
|
||||||
|
window,
|
||||||
|
is_bg_zero: state.is_bg_zero,
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tick(&mut self, steps: usize) -> GpuInterrupts {
|
pub fn tick(&mut self, steps: usize) -> GpuInterrupts {
|
||||||
let mut interrupts = GpuInterrupts::default();
|
let mut interrupts = GpuInterrupts::default();
|
||||||
if self.lcdc.enable {
|
if self.lcdc.enable {
|
||||||
|
|
|
@ -14,15 +14,28 @@ use self::mbcs::{
|
||||||
|
|
||||||
mod mbcs;
|
mod mbcs;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct MaybeBufferedSram {
|
struct MaybeBufferedSram {
|
||||||
buf: Vec<u8>,
|
buf: Vec<u8>,
|
||||||
length: usize,
|
length: usize,
|
||||||
#[serde(skip)]
|
|
||||||
inner: Option<File>,
|
inner: Option<File>,
|
||||||
unbuffered_writes: usize,
|
unbuffered_writes: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct SramSaveState {
|
||||||
|
buf: Vec<u8>,
|
||||||
|
length: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SramSaveState {
|
||||||
|
pub fn create(sram: &MaybeBufferedSram) -> Self {
|
||||||
|
Self {
|
||||||
|
buf: sram.buf.clone(),
|
||||||
|
length: sram.length,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const NUM_WRITES_TO_FLUSH: usize = 256;
|
const NUM_WRITES_TO_FLUSH: usize = 256;
|
||||||
|
|
||||||
impl MaybeBufferedSram {
|
impl MaybeBufferedSram {
|
||||||
|
@ -58,6 +71,16 @@ impl MaybeBufferedSram {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn from_save_state(state: SramSaveState) -> Self {
|
||||||
|
// TODO - restore file path
|
||||||
|
Self {
|
||||||
|
buf: state.buf,
|
||||||
|
length: state.length,
|
||||||
|
inner: None,
|
||||||
|
unbuffered_writes: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
self.length
|
self.length
|
||||||
}
|
}
|
||||||
|
@ -112,7 +135,7 @@ impl RomSaveState {
|
||||||
pub fn create(rom: &Rom) -> Self {
|
pub fn create(rom: &Rom) -> Self {
|
||||||
Self {
|
Self {
|
||||||
title: rom.title.clone(),
|
title: rom.title.clone(),
|
||||||
mbc: rom.mbc.get_savestate(),
|
mbc: rom.mbc.get_save_state(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,6 +149,18 @@ enum MbcSaveState {
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MbcSaveState {
|
||||||
|
fn get_mbc(self, data: Vec<u8>) -> 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)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Rom {
|
impl Rom {
|
||||||
pub fn load(data: Vec<u8>, save_path: Option<PathBuf>) -> Self {
|
pub fn load(data: Vec<u8>, save_path: Option<PathBuf>) -> Self {
|
||||||
let mut title_length = 0x143;
|
let mut title_length = 0x143;
|
||||||
|
@ -165,6 +200,13 @@ impl Rom {
|
||||||
Self { title, mbc }
|
Self { title, mbc }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_save_state(state: RomSaveState, data: Vec<u8>) -> Self {
|
||||||
|
Self {
|
||||||
|
title: state.title,
|
||||||
|
mbc: state.mbc.get_mbc(data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_title(&self) -> &String {
|
pub fn get_title(&self) -> &String {
|
||||||
&self.title
|
&self.title
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub(super) trait Mbc: Send {
|
||||||
fn set(&mut self, address: Address, data: u8);
|
fn set(&mut self, address: Address, data: u8);
|
||||||
fn set_ram(&mut self, address: Address, data: u8);
|
fn set_ram(&mut self, address: Address, data: u8);
|
||||||
fn mbc_type(&self) -> String;
|
fn mbc_type(&self) -> String;
|
||||||
fn get_savestate(&self) -> MbcSaveState;
|
fn get_save_state(&self) -> MbcSaveState;
|
||||||
fn is_rumbling(&self) -> bool {
|
fn is_rumbling(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ 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};
|
||||||
use crate::processor::memory::{
|
use crate::processor::memory::{
|
||||||
rom::{MaybeBufferedSram, MbcSaveState},
|
rom::{MaybeBufferedSram, MbcSaveState, SramSaveState},
|
||||||
Address,
|
Address,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ pub struct Mbc1SaveState {
|
||||||
rom_len: usize,
|
rom_len: usize,
|
||||||
rom_bank: u8,
|
rom_bank: u8,
|
||||||
ram_enabled: bool,
|
ram_enabled: bool,
|
||||||
ram: Option<Vec<u8>>,
|
ram: Option<SramSaveState>,
|
||||||
ram_bank: u8,
|
ram_bank: u8,
|
||||||
upper_banks: u8,
|
upper_banks: u8,
|
||||||
bank_mode: BankingMode,
|
bank_mode: BankingMode,
|
||||||
|
@ -88,6 +88,19 @@ impl Mbc1 {
|
||||||
_ => panic!("address {address} incompatible with MBC1"),
|
_ => panic!("address {address} incompatible with 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 {
|
||||||
|
@ -155,12 +168,12 @@ impl Mbc for Mbc1 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_savestate(&self) -> MbcSaveState {
|
fn get_save_state(&self) -> MbcSaveState {
|
||||||
MbcSaveState::Mbc1(Mbc1SaveState {
|
MbcSaveState::Mbc1(Mbc1SaveState {
|
||||||
rom_len: self.rom_len,
|
rom_len: self.rom_len,
|
||||||
rom_bank: self.rom_bank,
|
rom_bank: self.rom_bank,
|
||||||
ram_enabled: self.ram_enabled,
|
ram_enabled: self.ram_enabled,
|
||||||
ram: self.ram.as_ref().map(|v| v.buf.clone()),
|
ram: self.ram.as_ref().map(SramSaveState::create),
|
||||||
ram_bank: self.ram_bank,
|
ram_bank: self.ram_bank,
|
||||||
upper_banks: self.upper_banks,
|
upper_banks: self.upper_banks,
|
||||||
bank_mode: self.bank_mode,
|
bank_mode: self.bank_mode,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::path::PathBuf;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::processor::memory::{
|
use crate::processor::memory::{
|
||||||
rom::{MaybeBufferedSram, MbcSaveState},
|
rom::{MaybeBufferedSram, MbcSaveState, SramSaveState},
|
||||||
Address,
|
Address,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ pub struct Mbc2 {
|
||||||
pub struct Mbc2SaveState {
|
pub struct Mbc2SaveState {
|
||||||
rom_len: usize,
|
rom_len: usize,
|
||||||
rom_bank: u8,
|
rom_bank: u8,
|
||||||
ram: Vec<u8>,
|
ram: SramSaveState,
|
||||||
ram_enabled: bool,
|
ram_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,16 @@ 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 {
|
||||||
|
@ -89,11 +99,11 @@ impl Mbc for Mbc2 {
|
||||||
self.ram.flush();
|
self.ram.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_savestate(&self) -> MbcSaveState {
|
fn get_save_state(&self) -> MbcSaveState {
|
||||||
MbcSaveState::Mbc2(Mbc2SaveState {
|
MbcSaveState::Mbc2(Mbc2SaveState {
|
||||||
rom_len: self.rom_len,
|
rom_len: self.rom_len,
|
||||||
rom_bank: self.rom_bank,
|
rom_bank: self.rom_bank,
|
||||||
ram: self.ram.buf.clone(),
|
ram: SramSaveState::create(&self.ram),
|
||||||
ram_enabled: self.ram_enabled,
|
ram_enabled: self.ram_enabled,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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};
|
||||||
use crate::{
|
use crate::{
|
||||||
processor::memory::{
|
processor::memory::{
|
||||||
rom::{MaybeBufferedSram, MbcSaveState},
|
rom::{MaybeBufferedSram, MbcSaveState, SramSaveState},
|
||||||
Address,
|
Address,
|
||||||
},
|
},
|
||||||
util::set_or_clear_bit,
|
util::set_or_clear_bit,
|
||||||
|
@ -100,7 +100,7 @@ pub struct Mbc3 {
|
||||||
pub struct Mbc3SaveState {
|
pub struct Mbc3SaveState {
|
||||||
rom_bank: u8,
|
rom_bank: u8,
|
||||||
rom_size: usize,
|
rom_size: usize,
|
||||||
ram: Option<Vec<u8>>,
|
ram: Option<SramSaveState>,
|
||||||
ram_bank: RamBank,
|
ram_bank: RamBank,
|
||||||
ram_size: usize,
|
ram_size: usize,
|
||||||
ram_enabled: bool,
|
ram_enabled: bool,
|
||||||
|
@ -141,6 +141,20 @@ impl Mbc3 {
|
||||||
fn get_ram_addr(&self, address: Address, ram_bank: usize) -> usize {
|
fn get_ram_addr(&self, address: Address, ram_bank: usize) -> usize {
|
||||||
((address as usize - 0xA000) + (RAM_BANK_SIZE * ram_bank)) % self.ram_size
|
((address as usize - 0xA000) + (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 {
|
||||||
|
@ -245,11 +259,11 @@ impl Mbc for Mbc3 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_savestate(&self) -> MbcSaveState {
|
fn get_save_state(&self) -> MbcSaveState {
|
||||||
MbcSaveState::Mbc3(Mbc3SaveState {
|
MbcSaveState::Mbc3(Mbc3SaveState {
|
||||||
rom_bank: self.rom_bank,
|
rom_bank: self.rom_bank,
|
||||||
rom_size: self.rom_size,
|
rom_size: self.rom_size,
|
||||||
ram: self.ram.as_ref().map(|v| v.buf.clone()),
|
ram: self.ram.as_ref().map(SramSaveState::create),
|
||||||
ram_bank: self.ram_bank,
|
ram_bank: self.ram_bank,
|
||||||
ram_size: self.ram_size,
|
ram_size: self.ram_size,
|
||||||
ram_enabled: self.ram_enabled,
|
ram_enabled: self.ram_enabled,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
processor::memory::{
|
processor::memory::{
|
||||||
rom::{MaybeBufferedSram, MbcSaveState},
|
rom::{MaybeBufferedSram, MbcSaveState, SramSaveState},
|
||||||
Address,
|
Address,
|
||||||
},
|
},
|
||||||
util::get_bit,
|
util::get_bit,
|
||||||
|
@ -28,7 +28,7 @@ pub struct Mbc5 {
|
||||||
pub struct Mbc5SaveState {
|
pub struct Mbc5SaveState {
|
||||||
rom_bank: u16,
|
rom_bank: u16,
|
||||||
rom_size: usize,
|
rom_size: usize,
|
||||||
ram: Option<Vec<u8>>,
|
ram: Option<SramSaveState>,
|
||||||
ram_bank: u8,
|
ram_bank: u8,
|
||||||
ram_size: usize,
|
ram_size: usize,
|
||||||
ram_enabled: bool,
|
ram_enabled: bool,
|
||||||
|
@ -72,6 +72,20 @@ impl Mbc5 {
|
||||||
fn get_ram_addr(&self, address: Address) -> usize {
|
fn get_ram_addr(&self, address: Address) -> usize {
|
||||||
((address as usize - 0xA000) + (RAM_BANK_SIZE * self.ram_bank as usize)) % self.ram_size
|
((address as usize - 0xA000) + (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 {
|
||||||
|
@ -145,11 +159,11 @@ impl Mbc for Mbc5 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_savestate(&self) -> MbcSaveState {
|
fn get_save_state(&self) -> MbcSaveState {
|
||||||
MbcSaveState::Mbc5(Mbc5SaveState {
|
MbcSaveState::Mbc5(Mbc5SaveState {
|
||||||
rom_bank: self.rom_bank,
|
rom_bank: self.rom_bank,
|
||||||
rom_size: self.rom_size,
|
rom_size: self.rom_size,
|
||||||
ram: self.ram.as_ref().map(|v| v.buf.clone()),
|
ram: self.ram.as_ref().map(SramSaveState::create),
|
||||||
ram_bank: self.ram_bank,
|
ram_bank: self.ram_bank,
|
||||||
ram_size: self.ram_size,
|
ram_size: self.ram_size,
|
||||||
ram_enabled: self.ram_enabled,
|
ram_enabled: self.ram_enabled,
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl Mbc for None {
|
||||||
String::from("None")
|
String::from("None")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_savestate(&self) -> MbcSaveState {
|
fn get_save_state(&self) -> MbcSaveState {
|
||||||
MbcSaveState::None
|
MbcSaveState::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
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, MemorySaveState};
|
||||||
use crate::verbose_println;
|
use crate::{
|
||||||
|
connect::{AudioOutput, Renderer},
|
||||||
|
verbose_println,
|
||||||
|
};
|
||||||
|
|
||||||
mod instructions;
|
mod instructions;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
|
@ -150,6 +153,22 @@ impl<ColourFormat: From<Colour> + Clone> Cpu<ColourFormat> {
|
||||||
self.reg.pc = addr;
|
self.reg.pc = addr;
|
||||||
self.memory.ime = false;
|
self.memory.ime = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_save_state(
|
||||||
|
state: CpuSaveState<ColourFormat>,
|
||||||
|
data: Vec<u8>,
|
||||||
|
window: Box<dyn Renderer<ColourFormat>>,
|
||||||
|
output: AudioOutput,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
memory: Memory::from_save_state(state.memory, data, window, output),
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
|
Loading…
Reference in a new issue