mod avg32_game;
mod reallive_game;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
mod uk2_game;
use std::path::Path;
use anyhow::{Result, bail};
use engine_detect::EngineKind;
use crate::nls::Nls;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GameKey {
Enter,
Escape,
Space,
Up,
Down,
Left,
Right,
PageUp,
PageDown,
Home,
End,
Backspace,
Tab,
Ctrl,
Shift,
F(u8),
Char(char),
}
impl GameKey {
pub fn from_code(code: u32) -> Option<Self> {
Some(match code {
1 => Self::Enter,
2 => Self::Escape,
3 => Self::Space,
4 => Self::Up,
5 => Self::Down,
6 => Self::Left,
7 => Self::Right,
8 => Self::PageUp,
9 => Self::PageDown,
10 => Self::Home,
11 => Self::End,
12 => Self::Backspace,
13 => Self::Tab,
14 => Self::Ctrl,
15 => Self::Shift,
0x101..=0x10c => Self::F((code - 0x100) as u8),
0x10000.. => Self::Char(char::from_u32(code - 0x10000)?),
_ => return None,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PointerButton {
Left,
Right,
}
pub trait FramebufferGame {
fn size(&self) -> (u32, u32);
fn step(&mut self, dt_ms: u32) -> bool;
fn frame(&self) -> &[u8];
fn pointer_move(&mut self, x: i32, y: i32);
fn pointer_button(&mut self, button: PointerButton, pressed: bool);
fn wheel(&mut self, up: bool);
fn key(&mut self, key: GameKey, pressed: bool);
fn text(&mut self, text: &str);
fn cursor_visible(&self) -> bool {
true
}
fn title(&self) -> String;
fn shutdown(&mut self);
}
pub fn open(root: &Path, engine: EngineKind, nls: Option<Nls>) -> Result<Box<dyn FramebufferGame>> {
let engine = if engine == EngineKind::Unknown {
engine_detect::detect(root)?
} else {
engine
};
if let Err(reason) = crate::probe::platform_supports(engine) {
bail!("{reason}");
}
let nls = Nls::for_engine(engine, nls);
Ok(match engine {
EngineKind::Avg32 => Box::new(avg32_game::Avg32Game::open(root, nls)?),
EngineKind::RealLive => Box::new(reallive_game::RealLiveGame::open(root, nls)?),
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
EngineKind::Uk2 => Box::new(uk2_game::Uk2FramebufferGame::open(root, nls)?),
EngineKind::Siglus => {
bail!("SiglusEngine games run through the Siglus platform host")
}
other => bail!("{} games are not supported", other.name()),
})
}