vst specific config
This commit is contained in:
parent
a24a49fdcb
commit
ebc84e24d7
4 changed files with 101 additions and 34 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3507,6 +3507,7 @@ dependencies = [
|
||||||
"keyboard-types",
|
"keyboard-types",
|
||||||
"nih_plug",
|
"nih_plug",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -8,9 +8,10 @@ name = "vst"
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["vulkan"]
|
default = ["pixels"]
|
||||||
pixels = ["gb-emu-lib/pixels-renderer"]
|
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]
|
[dependencies]
|
||||||
gb-emu-lib = { path = "../lib", features = ["config"] }
|
gb-emu-lib = { path = "../lib", features = ["config"] }
|
||||||
|
@ -20,3 +21,4 @@ async-ringbuf = "0.1"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
keyboard-types = "0.6.2"
|
keyboard-types = "0.6.2"
|
||||||
raw-window-handle = { version = "0.5", optional = true }
|
raw-window-handle = { version = "0.5", optional = true }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use async_ringbuf::AsyncHeapConsumer;
|
use async_ringbuf::AsyncHeapConsumer;
|
||||||
|
use baseview::Size;
|
||||||
use futures::executor;
|
use futures::executor;
|
||||||
use gb_emu_lib::{
|
use gb_emu_lib::{
|
||||||
config::ConfigManager,
|
config::ConfigManager,
|
||||||
|
@ -6,15 +7,16 @@ use gb_emu_lib::{
|
||||||
AudioOutput, CgbRomType, DownsampleType, EmulatorCoreTrait, EmulatorMessage,
|
AudioOutput, CgbRomType, DownsampleType, EmulatorCoreTrait, EmulatorMessage,
|
||||||
EmulatorOptions, JoypadButtons, NoCamera, RomFile, SerialTarget,
|
EmulatorOptions, JoypadButtons, NoCamera, RomFile, SerialTarget,
|
||||||
},
|
},
|
||||||
EmulatorCore,
|
EmulatorCore, HEIGHT, WIDTH,
|
||||||
};
|
};
|
||||||
use nih_plug::prelude::*;
|
use nih_plug::prelude::*;
|
||||||
use nih_plug::{midi::MidiResult::Basic, params::persist::PersistentField};
|
use nih_plug::{midi::MidiResult::Basic, params::persist::PersistentField};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::{
|
sync::{
|
||||||
mpsc::{self, channel, Receiver, Sender},
|
mpsc::{self, channel, Receiver, Sender},
|
||||||
Arc, Mutex, RwLock,
|
Arc, Mutex, OnceLock, RwLock,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use ui::{Emulator, EmulatorRenderer};
|
use ui::{Emulator, EmulatorRenderer};
|
||||||
|
@ -54,6 +56,48 @@ struct EmuVars {
|
||||||
serial_tx: Sender<u8>,
|
serial_tx: Sender<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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::<VstConfig>("vst");
|
||||||
|
|
||||||
|
if vst_config.rom.is_empty() {
|
||||||
|
panic!("no rom provided!!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
vst_config,
|
||||||
|
emu_config,
|
||||||
|
config_dir: config_manager.dir(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct GameboyEmu {
|
pub struct GameboyEmu {
|
||||||
vars: Option<EmuVars>,
|
vars: Option<EmuVars>,
|
||||||
|
@ -72,7 +116,7 @@ type JoypadSender = Mutex<Option<Sender<JoypadInfo>>>;
|
||||||
const BUFFERS_PER_FRAME: usize = 1;
|
const BUFFERS_PER_FRAME: usize = 1;
|
||||||
const DOWNSAMPLE_TYPE: DownsampleType = DownsampleType::Linear;
|
const DOWNSAMPLE_TYPE: DownsampleType = DownsampleType::Linear;
|
||||||
|
|
||||||
const ROM: &[u8; 65536] = include_bytes!("../../test-roms/mGB-save-patch.gb");
|
static CONFIGS: OnceLock<Configs> = OnceLock::new();
|
||||||
|
|
||||||
impl Plugin for GameboyEmu {
|
impl Plugin for GameboyEmu {
|
||||||
const NAME: &'static str = "Gameboy";
|
const NAME: &'static str = "Gameboy";
|
||||||
|
@ -204,10 +248,18 @@ impl Plugin for GameboyEmu {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn editor(&mut self, _: AsyncExecutor<Self>) -> Option<Box<dyn Editor>> {
|
fn editor(&mut self, _: AsyncExecutor<Self>) -> Option<Box<dyn Editor>> {
|
||||||
|
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(
|
Some(Box::new(Emulator::new(
|
||||||
self.frame_receiver.clone(),
|
self.frame_receiver.clone(),
|
||||||
self.key_handler.clone(),
|
self.key_handler.clone(),
|
||||||
self.shader_path.clone(),
|
self.shader_path.clone(),
|
||||||
|
size,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,18 +279,24 @@ impl Plugin for GameboyEmu {
|
||||||
vars.emulator_core.replace_output(output);
|
vars.emulator_core.replace_output(output);
|
||||||
vars.rx = rx;
|
vars.rx = rx;
|
||||||
} else {
|
} 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())
|
.load(gb_emu_lib::connect::SramType::None, NoCamera::default())
|
||||||
.expect("failed to load rom");
|
.expect("failed to load rom");
|
||||||
|
|
||||||
let config_manager = ConfigManager::get().expect("Could not open config folder");
|
let shader_path =
|
||||||
let config = config_manager.load_or_create_base_config();
|
if rom.rom_type == CgbRomType::CgbOnly || configs.emu_config.prefer_cgb {
|
||||||
let shader_path = if rom.rom_type == CgbRomType::CgbOnly || config.prefer_cgb {
|
configs.emu_config.vulkan_config.cgb_shader_path.as_ref()
|
||||||
config.vulkan_config.cgb_shader_path.as_ref()
|
} else {
|
||||||
} else {
|
configs.emu_config.vulkan_config.dmg_shader_path.as_ref()
|
||||||
config.vulkan_config.dmg_shader_path.as_ref()
|
}
|
||||||
}
|
.map(|v| configs.config_dir.join(v));
|
||||||
.map(|v| config_manager.dir().join(v));
|
|
||||||
|
|
||||||
let (sender, receiver) = channel::<EmulatorMessage>();
|
let (sender, receiver) = channel::<EmulatorMessage>();
|
||||||
|
|
||||||
|
@ -260,16 +318,20 @@ impl Plugin for GameboyEmu {
|
||||||
tx: None,
|
tx: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let will_skip_bootrom =
|
||||||
|
configs.vst_config.force_skip_bootrom || !configs.emu_config.show_bootrom;
|
||||||
|
|
||||||
let mut emulator_core = {
|
let mut emulator_core = {
|
||||||
let options = EmulatorOptions::new_with_config(
|
let options = EmulatorOptions::new_with_config(
|
||||||
config,
|
configs.emu_config.clone(),
|
||||||
config_manager.dir(),
|
configs.config_dir.clone(),
|
||||||
window,
|
window,
|
||||||
rom,
|
rom,
|
||||||
output,
|
output,
|
||||||
)
|
)
|
||||||
.with_serial_target(serial_target)
|
.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)
|
EmulatorCore::init(receiver, options, camera)
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,9 +6,7 @@ use std::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use baseview::{
|
use baseview::{Event, EventStatus, Size, Window, WindowEvent, WindowHandler, WindowOpenOptions};
|
||||||
Event, EventStatus, Size, Window, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions,
|
|
||||||
};
|
|
||||||
use gb_emu_lib::{
|
use gb_emu_lib::{
|
||||||
connect::{JoypadButtons, JoypadState, Renderer, ResolutionData, HEIGHT, WIDTH},
|
connect::{JoypadButtons, JoypadState, Renderer, ResolutionData, HEIGHT, WIDTH},
|
||||||
renderer::{RendererBackend, RendererBackendManager, WindowOptions},
|
renderer::{RendererBackend, RendererBackendManager, WindowOptions},
|
||||||
|
@ -16,12 +14,13 @@ use gb_emu_lib::{
|
||||||
use keyboard_types::{Code, KeyState};
|
use keyboard_types::{Code, KeyState};
|
||||||
use nih_plug::prelude::*;
|
use nih_plug::prelude::*;
|
||||||
|
|
||||||
use crate::{Frame, FrameReceiver, JoypadInfo, JoypadSender};
|
use crate::{Configs, Frame, FrameReceiver, JoypadInfo, JoypadSender, CONFIGS};
|
||||||
|
|
||||||
pub struct Emulator {
|
pub struct Emulator {
|
||||||
frame_receiver: Arc<FrameReceiver>,
|
frame_receiver: Arc<FrameReceiver>,
|
||||||
joypad_sender: Arc<JoypadSender>,
|
joypad_sender: Arc<JoypadSender>,
|
||||||
shader_path: Arc<Mutex<Option<PathBuf>>>,
|
shader_path: Arc<Mutex<Option<PathBuf>>>,
|
||||||
|
size: Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Emulator {
|
impl Emulator {
|
||||||
|
@ -29,17 +28,17 @@ impl Emulator {
|
||||||
frame_receiver: Arc<FrameReceiver>,
|
frame_receiver: Arc<FrameReceiver>,
|
||||||
joypad_sender: Arc<JoypadSender>,
|
joypad_sender: Arc<JoypadSender>,
|
||||||
shader_path: Arc<Mutex<Option<PathBuf>>>,
|
shader_path: Arc<Mutex<Option<PathBuf>>>,
|
||||||
|
size: Size,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
frame_receiver,
|
frame_receiver,
|
||||||
joypad_sender,
|
joypad_sender,
|
||||||
shader_path,
|
shader_path,
|
||||||
|
size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const EXTRA_SCALE: usize = 4;
|
|
||||||
|
|
||||||
impl Editor for Emulator {
|
impl Editor for Emulator {
|
||||||
fn spawn(
|
fn spawn(
|
||||||
&self,
|
&self,
|
||||||
|
@ -64,20 +63,27 @@ impl Editor for Emulator {
|
||||||
#[cfg(feature = "vulkan")]
|
#[cfg(feature = "vulkan")]
|
||||||
let shader_path = self.shader_path.lock().unwrap().clone();
|
let shader_path = self.shader_path.lock().unwrap().clone();
|
||||||
// let shader_path = None;
|
// 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(
|
Window::open_parented(
|
||||||
&parent,
|
&parent,
|
||||||
WindowOpenOptions {
|
WindowOpenOptions {
|
||||||
title: String::from("gb-emu"),
|
title: String::from("gb-emu"),
|
||||||
size: Size::new((WIDTH * EXTRA_SCALE) as f64, (HEIGHT * EXTRA_SCALE) as f64),
|
size,
|
||||||
scale: baseview::WindowScalePolicy::SystemScaleFactor,
|
scale: baseview::WindowScalePolicy::SystemScaleFactor,
|
||||||
gl_config: None,
|
gl_config: None,
|
||||||
},
|
},
|
||||||
|w| {
|
move |w| {
|
||||||
EmulatorWindow::new(
|
EmulatorWindow::new(
|
||||||
w,
|
w,
|
||||||
fr_cloned,
|
fr_cloned,
|
||||||
js_cloned,
|
js_cloned,
|
||||||
|
size,
|
||||||
#[cfg(feature = "vulkan")]
|
#[cfg(feature = "vulkan")]
|
||||||
shader_path,
|
shader_path,
|
||||||
)
|
)
|
||||||
|
@ -87,11 +93,12 @@ impl Editor for Emulator {
|
||||||
self.frame_receiver.clone(),
|
self.frame_receiver.clone(),
|
||||||
self.joypad_sender.clone(),
|
self.joypad_sender.clone(),
|
||||||
self.shader_path.clone(),
|
self.shader_path.clone(),
|
||||||
|
size,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(&self) -> (u32, u32) {
|
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 {
|
fn set_scale_factor(&self, _factor: f32) -> bool {
|
||||||
|
@ -118,17 +125,12 @@ impl EmulatorWindow {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
frame_receiver: Arc<FrameReceiver>,
|
frame_receiver: Arc<FrameReceiver>,
|
||||||
joypad_sender: Arc<JoypadSender>,
|
joypad_sender: Arc<JoypadSender>,
|
||||||
|
size: Size,
|
||||||
#[cfg(feature = "vulkan")] shader_path: Option<PathBuf>,
|
#[cfg(feature = "vulkan")] shader_path: Option<PathBuf>,
|
||||||
) -> Self {
|
) -> 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 {
|
let current_resolution = ResolutionData {
|
||||||
real_width: physical_size.width,
|
real_width: size.width as u32,
|
||||||
real_height: physical_size.height,
|
real_height: size.height as u32,
|
||||||
scaled_width: WIDTH as u32,
|
scaled_width: WIDTH as u32,
|
||||||
scaled_height: HEIGHT as u32,
|
scaled_height: HEIGHT as u32,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue