Make menu items functional
This commit is contained in:
+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!(
|
||||
|
||||
Reference in New Issue
Block a user