separate prepare and run emulator

This commit is contained in:
Alex Janka 2023-11-04 10:12:29 +11:00
parent f7e3f2b6e9
commit 6ae2697a39
4 changed files with 92 additions and 31 deletions

View file

@ -5,9 +5,9 @@ use camera::Webcam;
use clap::{ArgGroup, Parser, Subcommand, ValueEnum};
use gb_emu_lib::{
config::ConfigManager,
connect::{SerialTarget, SramType, StdoutType},
connect::{EmulatorMessage, SerialTarget, SramType, StdoutType},
};
use std::path::PathBuf;
use std::{path::PathBuf, sync::mpsc::channel};
#[cfg(all(feature = "vulkan", feature = "pixels"))]
compile_error!("select only one rendering backend!");
@ -159,6 +159,15 @@ fn main() {
}
}
} else {
gb_emu::run(args.into());
let (sender, receiver) = channel::<EmulatorMessage>();
{
let sender = sender.clone();
ctrlc::set_handler(move || {
sender.send(EmulatorMessage::Exit).unwrap();
})
.unwrap();
}
gb_emu::run(gb_emu::prepare(args.into(), sender, receiver));
}
}

View file

@ -1,4 +1,5 @@
use std::path::PathBuf;
use std::sync::mpsc::channel;
use std::sync::RwLock;
use cacao::appkit::menu::{Menu, MenuItem};
@ -6,6 +7,7 @@ use cacao::appkit::window::{Window, WindowConfig, WindowStyle, WindowToolbarStyl
use cacao::appkit::{App, AppDelegate};
use cacao::filesystem::FileSelectPanel;
use cacao::notification_center::Dispatcher;
use gb_emu_lib::connect::EmulatorMessage;
use self::preferences::{PreferencesMessage, PreferencesUi};
@ -40,8 +42,12 @@ impl TwincUiApp {
}
fn open_file(path: PathBuf) {
println!("open {path:?}");
// gb_emu::run(gb_emu::RunOptions::new(path));
let (sender, receiver) = channel::<EmulatorMessage>();
gb_emu::run(gb_emu::prepare(
gb_emu::RunOptions::new(path),
sender,
receiver,
));
}
impl Default for TwincUiApp {

View file

@ -6,15 +6,18 @@ use debug::Debugger;
use gb_emu_lib::{
config::{ConfigManager, NamedConfig},
connect::{
CgbRomType, EmulatorCoreTrait, EmulatorMessage, EmulatorOptions, NoCamera, RomFile,
SerialTarget, SramType,
AudioOutput, CameraWrapper, CgbRomType, EmulatorCoreTrait, EmulatorMessage,
EmulatorOptions, NoCamera, Rom, RomFile, SerialTarget, SramType,
},
EmulatorCore,
};
use serde::{Deserialize, Serialize};
use std::{
path::PathBuf,
sync::{mpsc::channel, OnceLock},
sync::{
mpsc::{Receiver, Sender},
Arc, Mutex, OnceLock,
},
time::{Duration, Instant},
};
use window::WindowManager;
@ -96,17 +99,31 @@ impl RunOptions {
}
}
pub fn run(options: RunOptions) -> ! {
let (sender, receiver) = channel::<EmulatorMessage>();
pub struct PreparedEmulator<C>
where
C: gb_emu_lib::connect::PocketCamera,
{
let sender = sender.clone();
ctrlc::set_handler(move || {
sender.send(EmulatorMessage::Exit).unwrap();
})
.unwrap();
sender: Sender<EmulatorMessage>,
stream: cpal::Stream,
scale_override: usize,
shader_path: Option<PathBuf>,
resizable: bool,
rom: Rom<C>,
output: AudioOutput,
receiver: Receiver<EmulatorMessage>,
camera: Arc<Mutex<CameraWrapper<C>>>,
serial: SerialTarget,
tile_window: bool,
layer_window: bool,
debug: bool,
record: bool,
}
pub fn prepare(
options: RunOptions,
sender: Sender<EmulatorMessage>,
receiver: Receiver<EmulatorMessage>,
) -> PreparedEmulator<NoCamera> {
let config_manager = ConfigManager::get().expect("Could not open config folder");
let config = config_manager.load_or_create_base_config();
let standalone_config: StandaloneConfig = config_manager.load_or_create_config();
@ -152,25 +169,54 @@ pub fn run(options: RunOptions) -> ! {
}
.unwrap_or(configs.standalone_config.scale_factor);
let mut window_manager = WindowManager::new(sender, stream, options.record);
PreparedEmulator {
sender,
stream,
scale_override,
shader_path,
resizable,
rom,
output,
receiver,
camera,
serial: options.serial,
tile_window: options.tile_window,
layer_window: options.layer_window,
debug: options.debug,
record: options.record,
}
}
let window = window_manager.add_main(scale_override, shader_path, resizable);
pub fn run(prepared: PreparedEmulator<NoCamera>) -> ! {
let configs = access_config();
let mut window_manager = WindowManager::new(prepared.sender, prepared.stream, prepared.record);
let tile_window = if options.tile_window {
let window = window_manager.add_main(
prepared.scale_override,
prepared.shader_path,
prepared.resizable,
);
let tile_window = if prepared.tile_window {
Some(window_manager.add(configs.standalone_config.scale_factor, None, false))
} else {
None
};
let layer_window = if options.layer_window {
let layer_window = if prepared.layer_window {
Some(window_manager.add(configs.standalone_config.scale_factor.min(2), None, false))
} else {
None
};
let emulator_options =
EmulatorOptions::new_with_config(config, config_manager.dir(), window, rom, output)
.with_serial_target(options.serial)
let emulator_options = EmulatorOptions::new_with_config(
configs.emu_config.clone(),
configs.config_dir.clone(),
window,
prepared.rom,
prepared.output,
)
.with_serial_target(prepared.serial)
.with_tile_window(tile_window)
.with_layer_window(layer_window);
@ -192,9 +238,9 @@ pub fn run(options: RunOptions) -> ! {
// EmulatorTypes::Normal(core)
// };
let mut core = EmulatorCore::init(true, receiver, emulator_options, camera);
let mut core = EmulatorCore::init(true, prepared.receiver, emulator_options, prepared.camera);
if options.debug {
if prepared.debug {
let mut debugger = Debugger::new(Box::new(core));
let mut since = Instant::now();
loop {

View file

@ -9,7 +9,7 @@ pub use crate::processor::memory::mmio::joypad::{JoypadButtons, JoypadState};
pub use crate::processor::memory::mmio::serial::{SerialTarget, StdoutType};
use crate::processor::memory::rom::sram_save::SaveDataLocation;
pub use crate::processor::memory::rom::CgbRomType;
use crate::processor::memory::Rom;
pub use crate::processor::memory::Rom;
pub use crate::{HEIGHT, WIDTH};
use async_ringbuf::{AsyncHeapConsumer, AsyncHeapProducer, AsyncHeapRb};
@ -211,7 +211,7 @@ where
}
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum SramType {
File(PathBuf),
RawBuffer(Arc<RwLock<Vec<u8>>>),