2021-10-28 04:01:18 +00:00
|
|
|
|
2021-11-07 04:44:25 +00:00
|
|
|
mod keys;
|
|
|
|
|
2021-10-28 04:01:18 +00:00
|
|
|
use std::time::Duration;
|
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
|
|
|
|
use minifb::{self, Key};
|
|
|
|
|
|
|
|
use moa::error::Error;
|
|
|
|
use moa::system::System;
|
2021-11-07 04:44:25 +00:00
|
|
|
use moa::host::traits::{Host, JoystickDevice, JoystickUpdater, KeyboardUpdater, WindowUpdater};
|
|
|
|
|
|
|
|
use crate::keys::map_key;
|
2021-10-28 04:01:18 +00:00
|
|
|
|
|
|
|
|
2021-11-03 03:57:19 +00:00
|
|
|
const WIDTH: usize = 320;
|
|
|
|
const HEIGHT: usize = 224;
|
2021-10-28 04:01:18 +00:00
|
|
|
|
2021-11-07 04:44:25 +00:00
|
|
|
pub struct MiniFrontendBuilder {
|
|
|
|
pub window: Option<Box<dyn WindowUpdater>>,
|
|
|
|
pub joystick: Option<Box<dyn JoystickUpdater>>,
|
|
|
|
pub keyboard: Option<Box<dyn KeyboardUpdater>>,
|
|
|
|
pub finalized: bool,
|
2021-10-28 04:01:18 +00:00
|
|
|
}
|
|
|
|
|
2021-11-07 04:44:25 +00:00
|
|
|
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() {
|
2021-10-28 04:01:18 +00:00
|
|
|
return Err(Error::new("A window updater has already been registered with the frontend"));
|
|
|
|
}
|
2021-11-07 04:44:25 +00:00
|
|
|
self.window = Some(updater);
|
2021-10-28 04:01:18 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2021-10-31 18:00:14 +00:00
|
|
|
|
2021-11-07 04:44:25 +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(())
|
|
|
|
}
|
|
|
|
|
2021-11-07 04:44:25 +00:00
|
|
|
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
|
|
|
}
|
2021-11-07 04:44:25 +00:00
|
|
|
self.keyboard = Some(input);
|
2021-10-31 18:00:14 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2021-10-28 04:01:18 +00:00
|
|
|
}
|
|
|
|
|
2021-11-07 04:44:25 +00:00
|
|
|
|
|
|
|
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>>,
|
|
|
|
}
|
|
|
|
|
2021-10-28 04:01:18 +00:00
|
|
|
impl MiniFrontend {
|
2021-11-07 04:44:25 +00:00
|
|
|
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,
|
2021-10-28 04:01:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-07 04:44:25 +00:00
|
|
|
pub fn start(&mut self, mut system: Option<System>) {
|
2021-11-03 03:57:19 +00:00
|
|
|
let mut options = minifb::WindowOptions::default();
|
2021-11-07 04:44:25 +00:00
|
|
|
options.scale = minifb::Scale::X2;
|
2021-11-03 03:57:19 +00:00
|
|
|
|
2021-10-28 04:01:18 +00:00
|
|
|
let mut window = minifb::Window::new(
|
|
|
|
"Test - ESC to exit",
|
|
|
|
WIDTH,
|
|
|
|
HEIGHT,
|
2021-11-03 03:57:19 +00:00
|
|
|
options,
|
2021-10-28 04:01:18 +00:00
|
|
|
)
|
|
|
|
.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) {
|
2021-11-07 04:44:25 +00:00
|
|
|
if let Some(system) = system.as_mut() {
|
|
|
|
system.run_for(16_600_000).unwrap();
|
|
|
|
}
|
2021-10-28 04:01:18 +00:00
|
|
|
|
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 {
|
2021-11-07 04:44:25 +00:00
|
|
|
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; },
|
2021-11-07 04:44:25 +00:00
|
|
|
Key::D => { system.as_ref().map(|s| s.enable_debugging()); },
|
2021-10-31 18:00:14 +00:00
|
|
|
_ => { },
|
|
|
|
}
|
|
|
|
}
|
2021-11-07 04:44:25 +00:00
|
|
|
if let Some(mut updater) = self.joystick.as_mut() {
|
2021-10-31 18:00:14 +00:00
|
|
|
updater.update_joystick(modifiers);
|
|
|
|
}
|
|
|
|
}
|
2021-11-07 04:44:25 +00:00
|
|
|
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
|
|
|
|
2021-11-07 04:44:25 +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();
|
2021-10-28 04:01:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|