should restore from save state... doesn't, but should

This commit is contained in:
Alex Janka 2023-03-15 14:05:19 +11:00
parent 5aa308f695
commit b5fa2e6690
2 changed files with 89 additions and 18 deletions

View file

@ -5,6 +5,7 @@ use gb_emu_lib::{
EmulatorCore,
};
use nih_plug::prelude::*;
use nih_plug::{midi::MidiResult::Basic, params::persist::PersistentField};
use std::sync::{
mpsc::{channel, Receiver, Sender},
Arc, Mutex,
@ -13,8 +14,29 @@ use ui::{Emulator, EmulatorRenderer};
mod ui;
#[derive(Default)]
struct SaveStateParam {
state: Arc<Mutex<Option<CpuSaveState<[u8; 4]>>>>,
}
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(Params, Default)]
struct EmuParams {}
struct EmuParams {
#[persist = "save_state"]
last_save_state: SaveStateParam,
}
struct EmuVars {
rx: AsyncHeapConsumer<[f32; 2]>,
@ -27,7 +49,7 @@ pub struct GameboyEmu {
vars: Option<EmuVars>,
frame_receiver: Arc<FrameReceiver>,
key_handler: Arc<JoypadSender>,
last_save_state: Option<CpuSaveState<[u8; 4]>>,
params: Arc<EmuParams>,
}
type FrameReceiver = Mutex<Option<Receiver<Vec<[u8; 4]>>>>;
@ -72,15 +94,18 @@ impl Plugin for GameboyEmu {
type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> {
Arc::new(EmuParams::default())
self.params.clone()
}
fn process(
&mut self,
buffer: &mut Buffer,
_: &mut AuxiliaryBuffers,
_: &mut impl ProcessContext<Self>,
_c: &mut impl ProcessContext<Self>,
) -> ProcessStatus {
while let Some(event) = _c.next_event() {
if let Some(Basic(_midi)) = event.as_midi() {}
}
if let Some(ref mut vars) = self.vars {
if buffer.channels() != 2 {
panic!()
@ -97,6 +122,7 @@ impl Plugin for GameboyEmu {
}
vars.emulator_core.run_until_buffer_full();
}
self.update_save_state();
ProcessStatus::KeepAlive
}
@ -148,20 +174,16 @@ impl Plugin for GameboyEmu {
let window = Box::new(renderer);
let mut emulator_core = if let Some(state) = self.last_save_state.take() {
EmulatorCore::from_save_state(state, rom, receiver, window, output)
} else {
let options = gb_emu_lib::Options {
rom,
save_path: None,
no_save: true,
bootrom,
connect_serial: false,
verbose: false,
};
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)
} else {
let options = gb_emu_lib::Options::new(rom)
.with_bootrom(bootrom)
.force_no_save();
EmulatorCore::init(receiver, options, window, output, None)
};
EmulatorCore::init(receiver, options, window, output, None)
};
emulator_core.run_until_buffer_full();
self.vars = Some(EmuVars {
@ -169,6 +191,7 @@ impl Plugin for GameboyEmu {
sender,
emulator_core,
});
self.update_save_state();
}
true
@ -176,8 +199,8 @@ impl Plugin for GameboyEmu {
fn deactivate(&mut self) {
nih_log!("deactivating");
self.update_save_state();
if let Some(ref mut vars) = self.vars {
self.last_save_state = Some(vars.emulator_core.get_save_state());
match vars.sender.send(EmulatorMessage::Stop) {
Ok(_) => self.vars = None,
Err(e) => nih_log!("error {e} sending message to emulator"),
@ -186,6 +209,15 @@ impl Plugin for GameboyEmu {
}
}
impl GameboyEmu {
fn update_save_state(&mut self) {
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 {
const VST3_CLASS_ID: [u8; 16] = *b"alexjankagbemula";

View file

@ -22,6 +22,7 @@ mod constants;
mod processor;
pub mod util;
#[non_exhaustive]
pub struct Options {
pub rom: RomFile,
pub save_path: Option<String>,
@ -31,6 +32,44 @@ pub struct Options {
pub verbose: bool,
}
impl Options {
pub fn new(rom: RomFile) -> Self {
Self {
rom,
save_path: None,
no_save: false,
bootrom: None,
connect_serial: false,
verbose: false,
}
}
pub fn with_save_path(mut self, path: String) -> Self {
self.save_path = Some(path);
self
}
pub fn force_no_save(mut self) -> Self {
self.no_save = true;
self
}
pub fn with_bootrom(mut self, bootrom: Option<RomFile>) -> Self {
self.bootrom = bootrom;
self
}
pub fn with_serial(mut self) -> Self {
self.connect_serial = true;
self
}
pub fn with_verbose(mut self) -> Self {
self.verbose = true;
self
}
}
static mut PAUSE_ENABLED: bool = false;
static mut PAUSE_QUEUED: bool = false;