savestate option for vst

This commit is contained in:
Alex Janka 2023-03-16 10:48:08 +11:00
parent 36c252443c
commit 7dc6295ee8
2 changed files with 25 additions and 7 deletions

View file

@ -7,8 +7,9 @@ edition = "2021"
name = "vst" name = "vst"
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html default = []
savestate = []
[dependencies] [dependencies]
gb-emu-lib = { path = "../lib", features = ["async"] } gb-emu-lib = { path = "../lib", features = ["async"] }

View file

@ -1,27 +1,31 @@
use async_ringbuf::AsyncHeapConsumer; use async_ringbuf::AsyncHeapConsumer;
use futures::executor; use futures::executor;
use gb_emu_lib::{ use gb_emu_lib::{
connect::{ connect::{AudioOutput, DownsampleType, EmulatorMessage, JoypadButtons, RomFile, SerialTarget},
AudioOutput, CpuSaveState, DownsampleType, EmulatorMessage, JoypadButtons, RomFile,
SerialTarget,
},
EmulatorCore, EmulatorCore,
}; };
use nih_plug::midi::MidiResult::Basic;
use nih_plug::prelude::*; use nih_plug::prelude::*;
use nih_plug::{midi::MidiResult::Basic, params::persist::PersistentField};
use std::sync::{ use std::sync::{
mpsc::{self, channel, Receiver, Sender}, mpsc::{self, channel, Receiver, Sender},
Arc, Mutex, Arc, Mutex,
}; };
use ui::{Emulator, EmulatorRenderer}; use ui::{Emulator, EmulatorRenderer};
#[cfg(feature = "savestate")]
use gb_emu_lib::connect::CpuSaveState;
#[cfg(feature = "savestate")]
use nih_plug::params::persist::PersistentField;
mod ui; mod ui;
#[cfg(feature = "savestate")]
#[derive(Default)] #[derive(Default)]
struct SaveStateParam { struct SaveStateParam {
state: Arc<Mutex<Option<CpuSaveState<[u8; 4]>>>>, state: Arc<Mutex<Option<CpuSaveState<[u8; 4]>>>>,
} }
#[cfg(feature = "savestate")]
impl PersistentField<'_, Option<CpuSaveState<[u8; 4]>>> for SaveStateParam { impl PersistentField<'_, Option<CpuSaveState<[u8; 4]>>> for SaveStateParam {
fn set(&self, new_value: Option<CpuSaveState<[u8; 4]>>) { fn set(&self, new_value: Option<CpuSaveState<[u8; 4]>>) {
*self.state.lock().unwrap() = new_value; *self.state.lock().unwrap() = new_value;
@ -37,6 +41,7 @@ impl PersistentField<'_, Option<CpuSaveState<[u8; 4]>>> for SaveStateParam {
#[derive(Params, Default)] #[derive(Params, Default)]
struct EmuParams { struct EmuParams {
#[cfg(feature = "savestate")]
#[persist = "save_state"] #[persist = "save_state"]
last_save_state: SaveStateParam, last_save_state: SaveStateParam,
} }
@ -252,6 +257,7 @@ impl Plugin for GameboyEmu {
tx: None, tx: None,
}; };
#[cfg(feature = "savestate")]
let mut emulator_core = if let Some(state) = let mut emulator_core = if let Some(state) =
self.params.last_save_state.state.lock().unwrap().take() self.params.last_save_state.state.lock().unwrap().take()
{ {
@ -264,6 +270,16 @@ impl Plugin for GameboyEmu {
EmulatorCore::init(receiver, options, window, output, None) EmulatorCore::init(receiver, options, window, output, None)
}; };
#[cfg(not(feature = "savestate"))]
let mut emulator_core = {
let options = gb_emu_lib::Options::new(rom)
.with_bootrom(bootrom)
.with_serial_target(serial_target)
.force_no_save();
EmulatorCore::init(receiver, options, window, output, None)
};
emulator_core.run_until_buffer_full(); emulator_core.run_until_buffer_full();
self.vars = Some(EmuVars { self.vars = Some(EmuVars {
@ -292,6 +308,7 @@ impl Plugin for GameboyEmu {
impl GameboyEmu { impl GameboyEmu {
fn update_save_state(&mut self) { fn update_save_state(&mut self) {
#[cfg(feature = "savestate")]
if let Some(ref mut vars) = self.vars { if let Some(ref mut vars) = self.vars {
*self.params.last_save_state.state.lock().unwrap() = *self.params.last_save_state.state.lock().unwrap() =
Some(vars.emulator_core.get_save_state()); Some(vars.emulator_core.get_save_state());