Make menu items functional
This commit is contained in:
+14
-4
@@ -350,18 +350,28 @@ impl ApplicationHandler for App {
|
||||
height = ui.window_size()[1];
|
||||
ui.menu("ROM", || {
|
||||
if ui.menu_item("Open ROM") {
|
||||
println!("clicked");
|
||||
let rom = native_dialog::FileDialog::new()
|
||||
.add_filter("Virtual Boy ROMs", &["vb", "vbrom"])
|
||||
.show_open_single_file()
|
||||
.unwrap();
|
||||
if let Some(path) = rom {
|
||||
self.client.send_command(EmulatorCommand::LoadGame(path));
|
||||
}
|
||||
}
|
||||
if ui.menu_item("Quit") {
|
||||
event_loop.exit();
|
||||
}
|
||||
});
|
||||
ui.menu("Emulation", || {
|
||||
if ui.menu_item("Pause") {
|
||||
println!("clicked");
|
||||
if self.client.is_running() {
|
||||
if ui.menu_item("Pause") {
|
||||
self.client.send_command(EmulatorCommand::Pause);
|
||||
}
|
||||
} else if ui.menu_item("Resume") {
|
||||
self.client.send_command(EmulatorCommand::Resume);
|
||||
}
|
||||
if ui.menu_item("Reset") {
|
||||
println!("clicked");
|
||||
self.client.send_command(EmulatorCommand::Reset);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+48
-5
@@ -1,7 +1,11 @@
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
sync::mpsc::{self, TryRecvError},
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
mpsc::{self, TryRecvError},
|
||||
Arc,
|
||||
},
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
@@ -11,6 +15,7 @@ use crate::{audio::Audio, renderer::GameRenderer, shrooms_vb_core::CoreVB};
|
||||
pub struct EmulatorBuilder {
|
||||
rom: Option<PathBuf>,
|
||||
commands: mpsc::Receiver<EmulatorCommand>,
|
||||
running: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl EmulatorBuilder {
|
||||
@@ -19,8 +24,12 @@ impl EmulatorBuilder {
|
||||
let builder = Self {
|
||||
rom: None,
|
||||
commands,
|
||||
running: Arc::new(AtomicBool::new(false)),
|
||||
};
|
||||
let client = EmulatorClient {
|
||||
queue,
|
||||
running: builder.running.clone(),
|
||||
};
|
||||
let client = EmulatorClient { queue };
|
||||
(builder, client)
|
||||
}
|
||||
|
||||
@@ -32,7 +41,7 @@ impl EmulatorBuilder {
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<Emulator> {
|
||||
let mut emulator = Emulator::new(self.commands)?;
|
||||
let mut emulator = Emulator::new(self.commands, self.running)?;
|
||||
if let Some(path) = self.rom {
|
||||
emulator.load_rom(&path)?;
|
||||
}
|
||||
@@ -45,21 +54,28 @@ pub struct Emulator {
|
||||
audio: Audio,
|
||||
commands: mpsc::Receiver<EmulatorCommand>,
|
||||
renderer: Option<GameRenderer>,
|
||||
running: Arc<AtomicBool>,
|
||||
has_game: bool,
|
||||
}
|
||||
|
||||
impl Emulator {
|
||||
fn new(commands: mpsc::Receiver<EmulatorCommand>) -> Result<Self> {
|
||||
fn new(commands: mpsc::Receiver<EmulatorCommand>, running: Arc<AtomicBool>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
sim: CoreVB::new(),
|
||||
audio: Audio::init()?,
|
||||
commands,
|
||||
renderer: None,
|
||||
running,
|
||||
has_game: false,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn load_rom(&mut self, path: &Path) -> Result<()> {
|
||||
let bytes = fs::read(path)?;
|
||||
self.sim.reset();
|
||||
self.sim.load_rom(bytes)?;
|
||||
self.has_game = true;
|
||||
self.running.store(true, Ordering::Release);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -67,7 +83,9 @@ impl Emulator {
|
||||
let mut eye_contents = vec![0u8; 384 * 224 * 2];
|
||||
let mut audio_samples = vec![];
|
||||
loop {
|
||||
self.sim.emulate_frame();
|
||||
if self.running.load(Ordering::Acquire) {
|
||||
self.sim.emulate_frame();
|
||||
}
|
||||
if let Some(renderer) = &mut self.renderer {
|
||||
if self.sim.read_pixels(&mut eye_contents) {
|
||||
renderer.render(&eye_contents);
|
||||
@@ -97,6 +115,23 @@ impl Emulator {
|
||||
EmulatorCommand::SetRenderer(renderer) => {
|
||||
self.renderer = Some(renderer);
|
||||
}
|
||||
EmulatorCommand::LoadGame(path) => {
|
||||
if let Err(error) = self.load_rom(&path) {
|
||||
eprintln!("error loading rom: {}", error);
|
||||
}
|
||||
}
|
||||
EmulatorCommand::Pause => {
|
||||
self.running.store(false, Ordering::Release);
|
||||
}
|
||||
EmulatorCommand::Resume => {
|
||||
if self.has_game {
|
||||
self.running.store(true, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
EmulatorCommand::Reset => {
|
||||
self.sim.reset();
|
||||
self.running.store(true, Ordering::Release);
|
||||
}
|
||||
EmulatorCommand::PressStart => {
|
||||
self.sim.set_keys(0x1003);
|
||||
}
|
||||
@@ -110,15 +145,23 @@ impl Emulator {
|
||||
#[derive(Debug)]
|
||||
pub enum EmulatorCommand {
|
||||
SetRenderer(GameRenderer),
|
||||
LoadGame(PathBuf),
|
||||
Pause,
|
||||
Resume,
|
||||
Reset,
|
||||
PressStart,
|
||||
ReleaseStart,
|
||||
}
|
||||
|
||||
pub struct EmulatorClient {
|
||||
queue: mpsc::Sender<EmulatorCommand>,
|
||||
running: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl EmulatorClient {
|
||||
pub fn is_running(&self) -> bool {
|
||||
self.running.load(Ordering::Acquire)
|
||||
}
|
||||
pub fn send_command(&self, command: EmulatorCommand) {
|
||||
if let Err(err) = self.queue.send(command) {
|
||||
eprintln!(
|
||||
|
||||
+13
-5
@@ -1,4 +1,4 @@
|
||||
use std::{path::PathBuf, thread};
|
||||
use std::{path::PathBuf, process, thread};
|
||||
|
||||
use anyhow::Result;
|
||||
use app::App;
|
||||
@@ -14,16 +14,24 @@ mod shrooms_vb_core;
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Args {
|
||||
rom: PathBuf,
|
||||
rom: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let args = Args::parse();
|
||||
|
||||
let (builder, client) = EmulatorBuilder::new();
|
||||
let builder = builder.with_rom(&args.rom);
|
||||
let (mut builder, client) = EmulatorBuilder::new();
|
||||
if let Some(path) = args.rom {
|
||||
builder = builder.with_rom(&path);
|
||||
}
|
||||
thread::spawn(move || {
|
||||
let mut emulator = builder.build().unwrap();
|
||||
let mut emulator = match builder.build() {
|
||||
Ok(e) => e,
|
||||
Err(err) => {
|
||||
eprintln!("Error initializing emulator: {err}");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
emulator.run();
|
||||
});
|
||||
|
||||
|
||||
@@ -119,6 +119,10 @@ impl CoreVB {
|
||||
CoreVB { sim }
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
unsafe { vb_reset(self.sim) };
|
||||
}
|
||||
|
||||
pub fn load_rom(&mut self, rom: Vec<u8>) -> Result<()> {
|
||||
self.unload_rom();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user