moa/frontends/moa-minifb/src/lib.rs

150 lines
4.5 KiB
Rust
Raw Normal View History

mod keys;
use std::time::Duration;
use std::sync::{Arc, Mutex};
use minifb::{self, Key};
use moa::error::Error;
use moa::system::System;
use moa::host::traits::{Host, JoystickDevice, JoystickUpdater, KeyboardUpdater, WindowUpdater};
use crate::keys::map_key;
2021-11-03 03:57:19 +00:00
const WIDTH: usize = 320;
const HEIGHT: usize = 224;
pub struct MiniFrontendBuilder {
pub window: Option<Box<dyn WindowUpdater>>,
pub joystick: Option<Box<dyn JoystickUpdater>>,
pub keyboard: Option<Box<dyn KeyboardUpdater>>,
pub finalized: bool,
}
impl MiniFrontendBuilder {
pub fn new() -> Self {
Self {
window: None,
joystick: None,
keyboard: None,
finalized: false,
}
}
pub fn finalize(&mut self) {
self.finalized = true;
}
pub fn build(&mut self) -> MiniFrontend {
let window = std::mem::take(&mut self.window);
let joystick = std::mem::take(&mut self.joystick);
let keyboard = std::mem::take(&mut self.keyboard);
MiniFrontend::new(window, joystick, keyboard)
}
}
impl Host for MiniFrontendBuilder {
fn add_window(&mut self, updater: Box<dyn WindowUpdater>) -> Result<(), Error> {
if self.window.is_some() {
return Err(Error::new("A window updater has already been registered with the frontend"));
}
self.window = Some(updater);
Ok(())
}
2021-10-31 18:00:14 +00:00
fn register_joystick(&mut self, device: JoystickDevice, input: Box<dyn JoystickUpdater>) -> Result<(), Error> {
2021-10-31 18:00:14 +00:00
if device != JoystickDevice::A {
return Ok(())
}
if self.joystick.is_some() {
return Err(Error::new("A joystick updater has already been registered with the frontend"));
}
self.joystick = Some(input);
Ok(())
}
fn register_keyboard(&mut self, input: Box<dyn KeyboardUpdater>) -> Result<(), Error> {
if self.keyboard.is_some() {
return Err(Error::new("A keyboard updater has already been registered with the frontend"));
2021-10-31 18:00:14 +00:00
}
self.keyboard = Some(input);
2021-10-31 18:00:14 +00:00
Ok(())
}
}
pub struct MiniFrontend {
pub buffer: Vec<u32>,
pub window: Option<Box<dyn WindowUpdater>>,
pub joystick: Option<Box<dyn JoystickUpdater>>,
pub keyboard: Option<Box<dyn KeyboardUpdater>>,
}
impl MiniFrontend {
pub fn new(window: Option<Box<dyn WindowUpdater>>, joystick: Option<Box<dyn JoystickUpdater>>, keyboard: Option<Box<dyn KeyboardUpdater>>) -> Self {
Self {
buffer: vec![0; WIDTH * HEIGHT],
window,
joystick,
keyboard,
}
}
pub fn start(&mut self, mut system: Option<System>) {
2021-11-03 03:57:19 +00:00
let mut options = minifb::WindowOptions::default();
options.scale = minifb::Scale::X2;
2021-11-03 03:57:19 +00:00
let mut window = minifb::Window::new(
"Test - ESC to exit",
WIDTH,
HEIGHT,
2021-11-03 03:57:19 +00:00
options,
)
.unwrap_or_else(|e| {
panic!("{}", e);
});
// Limit to max ~60 fps update rate
window.limit_update_rate(Some(Duration::from_micros(16600)));
while window.is_open() && !window.is_key_down(Key::Escape) {
if let Some(system) = system.as_mut() {
system.run_for(16_600_000).unwrap();
}
2021-10-31 18:00:14 +00:00
if let Some(keys) = window.get_keys_pressed(minifb::KeyRepeat::Yes) {
let mut modifiers: u16 = 0;
for key in keys {
if let Some(mut updater) = self.keyboard.as_mut() {
updater.update_keyboard(map_key(key), true);
}
2021-10-31 18:00:14 +00:00
match key {
Key::Enter => { modifiers |= 0xffff; },
Key::D => { system.as_ref().map(|s| s.enable_debugging()); },
2021-10-31 18:00:14 +00:00
_ => { },
}
}
if let Some(mut updater) = self.joystick.as_mut() {
2021-10-31 18:00:14 +00:00
updater.update_joystick(modifiers);
}
}
if let Some(keys) = window.get_keys_released() {
for key in keys {
if let Some(mut updater) = self.keyboard.as_mut() {
updater.update_keyboard(map_key(key), false);
}
}
}
2021-10-31 18:00:14 +00:00
if let Some(mut updater) = self.window.as_mut() {
updater.update_frame(WIDTH as u32, HEIGHT as u32, &mut self.buffer);
window.update_with_buffer(&self.buffer, WIDTH, HEIGHT).unwrap();
}
}
}
}