From 5aa308f695358a08e43b40b262f583cdf6178c68 Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Wed, 15 Mar 2023 13:15:32 +1100 Subject: [PATCH] save state restore --- gb-vst/src/lib.rs | 49 +++++++++++++++++++++++++----------------- lib/src/connect/mod.rs | 1 + 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/gb-vst/src/lib.rs b/gb-vst/src/lib.rs index 0805235..c4389d9 100644 --- a/gb-vst/src/lib.rs +++ b/gb-vst/src/lib.rs @@ -1,7 +1,7 @@ use async_ringbuf::AsyncHeapConsumer; use futures::executor; use gb_emu_lib::{ - connect::{AudioOutput, DownsampleType, EmulatorMessage, JoypadButtons, RomFile}, + connect::{AudioOutput, CpuSaveState, DownsampleType, EmulatorMessage, JoypadButtons, RomFile}, EmulatorCore, }; use nih_plug::prelude::*; @@ -27,6 +27,7 @@ pub struct GameboyEmu { vars: Option, frame_receiver: Arc, key_handler: Arc, + last_save_state: Option>, } type FrameReceiver = Mutex>>>; @@ -36,6 +37,9 @@ const FRAMES_TO_BUFFER: usize = 1; const INCLUDE_BOOTROM: bool = false; const DOWNSAMPLE_TYPE: DownsampleType = DownsampleType::ZeroOrderHold; +const ROM: &[u8; 65536] = include_bytes!("../../test-roms/mGB1_3_0.gb"); +const BOOTROM: &[u8; 256] = include_bytes!("../../bootrom/dmg_boot.bin"); + impl Plugin for GameboyEmu { const NAME: &'static str = "Gameboy"; @@ -48,7 +52,7 @@ impl Plugin for GameboyEmu { const VERSION: &'static str = "0.1"; const AUDIO_IO_LAYOUTS: &'static [AudioIOLayout] = &[AudioIOLayout { - main_input_channels: NonZeroU32::new(2), + main_input_channels: None, main_output_channels: NonZeroU32::new(2), aux_input_ports: &[], @@ -60,6 +64,9 @@ impl Plugin for GameboyEmu { names: PortNames::const_default(), }]; + const MIDI_INPUT: MidiConfig = MidiConfig::MidiCCs; + const SAMPLE_ACCURATE_AUTOMATION: bool = true; + type SysExMessage = (); type BackgroundTask = (); @@ -118,25 +125,12 @@ impl Plugin for GameboyEmu { vars.rx = rx; } else { let bootrom = if INCLUDE_BOOTROM { - Some(RomFile::Raw( - include_bytes!("../../bootrom/dmg_boot.bin").to_vec(), - )) + Some(RomFile::Raw(BOOTROM.to_vec())) } else { None }; - let options = gb_emu_lib::Options { - rom: RomFile::Raw( - include_bytes!("../../test-roms/Tetris.gb") - .to_vec() - .to_vec(), - ), - save_path: None, - no_save: true, - bootrom, - connect_serial: false, - verbose: false, - }; + let rom = RomFile::Raw(ROM.to_vec()); let (sender, receiver) = channel::(); @@ -152,8 +146,22 @@ impl Plugin for GameboyEmu { *self.frame_receiver.lock().unwrap() = Some(frame_receiver); *self.key_handler.lock().unwrap() = Some(key_handler); - let mut emulator_core = - EmulatorCore::init(receiver, options, Box::new(renderer), output, None); + 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, + }; + + EmulatorCore::init(receiver, options, window, output, None) + }; emulator_core.run_until_buffer_full(); self.vars = Some(EmuVars { @@ -169,6 +177,7 @@ impl Plugin for GameboyEmu { fn deactivate(&mut self) { nih_log!("deactivating"); 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"), @@ -181,7 +190,7 @@ impl Vst3Plugin for GameboyEmu { const VST3_CLASS_ID: [u8; 16] = *b"alexjankagbemula"; const VST3_SUBCATEGORIES: &'static [Vst3SubCategory] = - &[Vst3SubCategory::Distortion, Vst3SubCategory::Dynamics]; + &[Vst3SubCategory::Instrument, Vst3SubCategory::Synth]; } nih_export_vst3!(GameboyEmu); diff --git a/lib/src/connect/mod.rs b/lib/src/connect/mod.rs index b8fcc2e..d89e41f 100644 --- a/lib/src/connect/mod.rs +++ b/lib/src/connect/mod.rs @@ -1,5 +1,6 @@ use crate::processor::memory::mmio::gpu::Colour; pub use crate::processor::memory::mmio::joypad::{JoypadButtons, JoypadState}; +pub use crate::processor::CpuSaveState; pub use crate::{HEIGHT, WIDTH}; use async_ringbuf::{AsyncHeapConsumer, AsyncHeapProducer, AsyncHeapRb};