lemur/src/emulator.rs

94 lines
2.3 KiB
Rust

use std::{
fs,
path::Path,
sync::mpsc::{self, TryRecvError},
};
use anyhow::Result;
use crate::{renderer::GameRenderer, shrooms_vb_core::CoreVB};
pub struct Emulator {
sim: CoreVB,
commands: mpsc::Receiver<EmulatorCommand>,
renderer: Option<GameRenderer>,
}
impl Emulator {
pub fn new() -> (Self, EmulatorClient) {
let (sink, source) = mpsc::channel();
let emu = Emulator {
sim: CoreVB::new(),
commands: source,
renderer: None,
};
let queue = EmulatorClient { queue: sink };
(emu, queue)
}
pub fn load_rom(&mut self, path: &Path) -> Result<()> {
let bytes = fs::read(path)?;
self.sim.load_rom(bytes)?;
Ok(())
}
pub fn run(&mut self) {
let mut eye_contents = vec![0u8; 384 * 224 * 2];
loop {
self.sim.emulate_frame();
if let Some(renderer) = &mut self.renderer {
if self.sim.read_pixels(&mut eye_contents) {
renderer.render(&eye_contents);
}
}
loop {
match self.commands.try_recv() {
Ok(command) => self.handle_command(command),
Err(TryRecvError::Empty) => {
break;
}
Err(TryRecvError::Disconnected) => {
return;
}
}
}
}
}
fn handle_command(&mut self, command: EmulatorCommand) {
match command {
EmulatorCommand::SetRenderer(renderer) => {
self.renderer = Some(renderer);
}
EmulatorCommand::PressStart => {
self.sim.set_keys(0x1003);
}
EmulatorCommand::ReleaseStart => {
self.sim.set_keys(0x0003);
}
}
}
}
#[derive(Debug)]
pub enum EmulatorCommand {
SetRenderer(GameRenderer),
PressStart,
ReleaseStart,
}
pub struct EmulatorClient {
queue: mpsc::Sender<EmulatorCommand>,
}
impl EmulatorClient {
pub fn send_command(&self, command: EmulatorCommand) {
if let Err(err) = self.queue.send(command) {
eprintln!(
"could not send command {:?} as emulator is shut down",
err.0
);
}
}
}