From ebc84e24d75be1396ca0b0a4fb3b344b53bcc366 Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Thu, 5 Oct 2023 12:42:03 +1100 Subject: [PATCH] vst specific config --- Cargo.lock | 1 + gb-vst/Cargo.toml | 6 ++-- gb-vst/src/lib.rs | 92 +++++++++++++++++++++++++++++++++++++++-------- gb-vst/src/ui.rs | 36 ++++++++++--------- 4 files changed, 101 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e7413d2..12c7769 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3507,6 +3507,7 @@ dependencies = [ "keyboard-types", "nih_plug", "raw-window-handle", + "serde", ] [[package]] diff --git a/gb-vst/Cargo.toml b/gb-vst/Cargo.toml index cddf377..ea976ff 100644 --- a/gb-vst/Cargo.toml +++ b/gb-vst/Cargo.toml @@ -8,9 +8,10 @@ name = "vst" crate-type = ["cdylib", "rlib"] [features] -default = ["vulkan"] +default = ["pixels"] pixels = ["gb-emu-lib/pixels-renderer"] -vulkan = ["dep:raw-window-handle", "gb-emu-lib/vulkan-static"] +vulkan = ["dep:raw-window-handle", "gb-emu-lib/vulkan-renderer"] +vulkan-static = ["vulkan", "gb-emu-lib/vulkan-static"] [dependencies] gb-emu-lib = { path = "../lib", features = ["config"] } @@ -20,3 +21,4 @@ async-ringbuf = "0.1" futures = "0.3" keyboard-types = "0.6.2" raw-window-handle = { version = "0.5", optional = true } +serde = { version = "1.0", features = ["derive"] } diff --git a/gb-vst/src/lib.rs b/gb-vst/src/lib.rs index 176dccf..3d4facd 100644 --- a/gb-vst/src/lib.rs +++ b/gb-vst/src/lib.rs @@ -1,4 +1,5 @@ use async_ringbuf::AsyncHeapConsumer; +use baseview::Size; use futures::executor; use gb_emu_lib::{ config::ConfigManager, @@ -6,15 +7,16 @@ use gb_emu_lib::{ AudioOutput, CgbRomType, DownsampleType, EmulatorCoreTrait, EmulatorMessage, EmulatorOptions, JoypadButtons, NoCamera, RomFile, SerialTarget, }, - EmulatorCore, + EmulatorCore, HEIGHT, WIDTH, }; use nih_plug::prelude::*; use nih_plug::{midi::MidiResult::Basic, params::persist::PersistentField}; +use serde::{Deserialize, Serialize}; use std::{ path::PathBuf, sync::{ mpsc::{self, channel, Receiver, Sender}, - Arc, Mutex, RwLock, + Arc, Mutex, OnceLock, RwLock, }, }; use ui::{Emulator, EmulatorRenderer}; @@ -54,6 +56,48 @@ struct EmuVars { serial_tx: Sender, } +#[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(default)] +pub struct VstConfig { + scale_factor: usize, + rom: String, + force_skip_bootrom: bool, +} + +impl Default for VstConfig { + fn default() -> Self { + Self { + scale_factor: 3, + rom: String::from(""), + force_skip_bootrom: true, + } + } +} + +struct Configs { + vst_config: VstConfig, + emu_config: gb_emu_lib::config::Config, + config_dir: PathBuf, +} + +impl Configs { + fn get() -> Self { + let config_manager = ConfigManager::get().expect("Could not open config folder"); + let emu_config = config_manager.load_or_create_base_config(); + let vst_config = config_manager.load_or_create_config::("vst"); + + if vst_config.rom.is_empty() { + panic!("no rom provided!!"); + } + + Self { + vst_config, + emu_config, + config_dir: config_manager.dir(), + } + } +} + #[derive(Default)] pub struct GameboyEmu { vars: Option, @@ -72,7 +116,7 @@ type JoypadSender = Mutex>>; const BUFFERS_PER_FRAME: usize = 1; const DOWNSAMPLE_TYPE: DownsampleType = DownsampleType::Linear; -const ROM: &[u8; 65536] = include_bytes!("../../test-roms/mGB-save-patch.gb"); +static CONFIGS: OnceLock = OnceLock::new(); impl Plugin for GameboyEmu { const NAME: &'static str = "Gameboy"; @@ -204,10 +248,18 @@ impl Plugin for GameboyEmu { } fn editor(&mut self, _: AsyncExecutor) -> Option> { + let configs = CONFIGS.get_or_init(Configs::get); + + let size = Size::new( + (WIDTH * configs.vst_config.scale_factor) as f64, + (HEIGHT * configs.vst_config.scale_factor) as f64, + ); + Some(Box::new(Emulator::new( self.frame_receiver.clone(), self.key_handler.clone(), self.shader_path.clone(), + size, ))) } @@ -227,18 +279,24 @@ impl Plugin for GameboyEmu { vars.emulator_core.replace_output(output); vars.rx = rx; } else { - let (rom, camera) = RomFile::Raw(ROM.to_vec()) + let configs = CONFIGS.get_or_init(Configs::get); + + let rom_path = configs.config_dir.join(configs.vst_config.rom.clone()); + if !rom_path.is_file() { + panic!("{rom_path:?} is not a file!"); + } + + let (rom, camera) = RomFile::Path(rom_path) .load(gb_emu_lib::connect::SramType::None, NoCamera::default()) .expect("failed to load rom"); - let config_manager = ConfigManager::get().expect("Could not open config folder"); - let config = config_manager.load_or_create_base_config(); - let shader_path = if rom.rom_type == CgbRomType::CgbOnly || config.prefer_cgb { - config.vulkan_config.cgb_shader_path.as_ref() - } else { - config.vulkan_config.dmg_shader_path.as_ref() - } - .map(|v| config_manager.dir().join(v)); + let shader_path = + if rom.rom_type == CgbRomType::CgbOnly || configs.emu_config.prefer_cgb { + configs.emu_config.vulkan_config.cgb_shader_path.as_ref() + } else { + configs.emu_config.vulkan_config.dmg_shader_path.as_ref() + } + .map(|v| configs.config_dir.join(v)); let (sender, receiver) = channel::(); @@ -260,16 +318,20 @@ impl Plugin for GameboyEmu { tx: None, }; + let will_skip_bootrom = + configs.vst_config.force_skip_bootrom || !configs.emu_config.show_bootrom; + let mut emulator_core = { let options = EmulatorOptions::new_with_config( - config, - config_manager.dir(), + configs.emu_config.clone(), + configs.config_dir.clone(), window, rom, output, ) .with_serial_target(serial_target) - .with_sram_buffer(self.params.sram_save.state.clone()); + .with_sram_buffer(self.params.sram_save.state.clone()) + .with_show_bootrom(!will_skip_bootrom); EmulatorCore::init(receiver, options, camera) }; diff --git a/gb-vst/src/ui.rs b/gb-vst/src/ui.rs index 3a13a6e..44718a1 100644 --- a/gb-vst/src/ui.rs +++ b/gb-vst/src/ui.rs @@ -6,9 +6,7 @@ use std::{ }, }; -use baseview::{ - Event, EventStatus, Size, Window, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions, -}; +use baseview::{Event, EventStatus, Size, Window, WindowEvent, WindowHandler, WindowOpenOptions}; use gb_emu_lib::{ connect::{JoypadButtons, JoypadState, Renderer, ResolutionData, HEIGHT, WIDTH}, renderer::{RendererBackend, RendererBackendManager, WindowOptions}, @@ -16,12 +14,13 @@ use gb_emu_lib::{ use keyboard_types::{Code, KeyState}; use nih_plug::prelude::*; -use crate::{Frame, FrameReceiver, JoypadInfo, JoypadSender}; +use crate::{Configs, Frame, FrameReceiver, JoypadInfo, JoypadSender, CONFIGS}; pub struct Emulator { frame_receiver: Arc, joypad_sender: Arc, shader_path: Arc>>, + size: Size, } impl Emulator { @@ -29,17 +28,17 @@ impl Emulator { frame_receiver: Arc, joypad_sender: Arc, shader_path: Arc>>, + size: Size, ) -> Self { Self { frame_receiver, joypad_sender, shader_path, + size, } } } -const EXTRA_SCALE: usize = 4; - impl Editor for Emulator { fn spawn( &self, @@ -64,20 +63,27 @@ impl Editor for Emulator { #[cfg(feature = "vulkan")] let shader_path = self.shader_path.lock().unwrap().clone(); // let shader_path = None; + let scale_factor = CONFIGS.get_or_init(Configs::get).vst_config.scale_factor; + + let size = Size::new( + (WIDTH * scale_factor) as f64, + (HEIGHT * scale_factor) as f64, + ); Window::open_parented( &parent, WindowOpenOptions { title: String::from("gb-emu"), - size: Size::new((WIDTH * EXTRA_SCALE) as f64, (HEIGHT * EXTRA_SCALE) as f64), + size, scale: baseview::WindowScalePolicy::SystemScaleFactor, gl_config: None, }, - |w| { + move |w| { EmulatorWindow::new( w, fr_cloned, js_cloned, + size, #[cfg(feature = "vulkan")] shader_path, ) @@ -87,11 +93,12 @@ impl Editor for Emulator { self.frame_receiver.clone(), self.joypad_sender.clone(), self.shader_path.clone(), + size, )) } fn size(&self) -> (u32, u32) { - ((WIDTH * EXTRA_SCALE) as u32, (HEIGHT * EXTRA_SCALE) as u32) + (self.size.width as u32, self.size.height as u32) } fn set_scale_factor(&self, _factor: f32) -> bool { @@ -118,17 +125,12 @@ impl EmulatorWindow { window: &mut Window, frame_receiver: Arc, joypad_sender: Arc, + size: Size, #[cfg(feature = "vulkan")] shader_path: Option, ) -> Self { - let info = WindowInfo::from_logical_size( - Size::new(WIDTH as f64, HEIGHT as f64), - EXTRA_SCALE as f64, - ); - let physical_size = info.physical_size(); - let current_resolution = ResolutionData { - real_width: physical_size.width, - real_height: physical_size.height, + real_width: size.width as u32, + real_height: size.height as u32, scaled_width: WIDTH as u32, scaled_height: HEIGHT as u32, };