From b5fa2e6690551eb2048c276ce79c5cbf27827576 Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Wed, 15 Mar 2023 14:05:19 +1100 Subject: [PATCH] should restore from save state... doesn't, but should --- gb-vst/src/lib.rs | 68 ++++++++++++++++++++++++++++++++++------------- lib/src/lib.rs | 39 +++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 18 deletions(-) diff --git a/gb-vst/src/lib.rs b/gb-vst/src/lib.rs index c4389d9..1d5b0e3 100644 --- a/gb-vst/src/lib.rs +++ b/gb-vst/src/lib.rs @@ -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>>>, +} + +impl PersistentField<'_, Option>> for SaveStateParam { + fn set(&self, new_value: Option>) { + *self.state.lock().unwrap() = new_value; + } + + fn map(&self, f: F) -> R + where + F: Fn(&Option>) -> 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, frame_receiver: Arc, key_handler: Arc, - last_save_state: Option>, + params: Arc, } type FrameReceiver = Mutex>>>; @@ -72,15 +94,18 @@ impl Plugin for GameboyEmu { type BackgroundTask = (); fn params(&self) -> Arc { - Arc::new(EmuParams::default()) + self.params.clone() } fn process( &mut self, buffer: &mut Buffer, _: &mut AuxiliaryBuffers, - _: &mut impl ProcessContext, + _c: &mut impl ProcessContext, ) -> 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"; diff --git a/lib/src/lib.rs b/lib/src/lib.rs index c87f729..01e5edb 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -22,6 +22,7 @@ mod constants; mod processor; pub mod util; +#[non_exhaustive] pub struct Options { pub rom: RomFile, pub save_path: Option, @@ -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) -> 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;