mirror of
https://github.com/JanNeuendorf/SVC16.git
synced 2025-06-06 19:45:27 +00:00
Moved the controller support into a cargo feature that needs to be turned on explicitely. This makes the emulator more portable.
This commit is contained in:
parent
890c2b7b79
commit
f5ea5b88fe
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1813,7 +1813,7 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "svc16"
|
name = "svc16"
|
||||||
version = "0.6.1"
|
version = "0.7.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "svc16"
|
name = "svc16"
|
||||||
version = "0.6.1"
|
version = "0.7.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Jan Neuendorf"]
|
authors = ["Jan Neuendorf"]
|
||||||
description = "An emulator for a simple virtual computer"
|
description = "An emulator for a simple virtual computer"
|
||||||
@ -9,10 +9,13 @@ license="MIT"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.93"
|
anyhow = "1.0.93"
|
||||||
clap = { version = "4.5.21", features = ["derive"] }
|
clap = { version = "4.5.21", features = ["derive"] }
|
||||||
gilrs = { version = "0.11.0"}
|
gilrs = { version = "0.11.0",optional=true}
|
||||||
# There seems to be some incompatibility with the latest crates.io version of pixels?
|
# There seems to be some incompatibility with the latest crates.io version of pixels?
|
||||||
pixels = { git = "https://github.com/parasyte/pixels.git", rev = "d4df286"}
|
pixels = { git = "https://github.com/parasyte/pixels.git", rev = "d4df286"}
|
||||||
thiserror = "2.0.3"
|
thiserror = "2.0.3"
|
||||||
winit = "0.29.15"
|
winit = "0.29.15"
|
||||||
winit-input-map = "0.4.1"
|
winit-input-map = {version="0.4.1",optional=true}
|
||||||
winit_input_helper = "0.16.0"
|
winit_input_helper = "0.16.0"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
gamepad = ["gilrs","winit-input-map"]
|
||||||
|
@ -15,6 +15,9 @@ This repo contains an emulator to run games or programs. It can be installed wit
|
|||||||
cargo install --git https://github.com/JanNeuendorf/SVC16
|
cargo install --git https://github.com/JanNeuendorf/SVC16
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> For controller support, compile with `--features="gamepad"`. Support varies by platform and it might require additional libraries to be installed.
|
||||||
|
|
||||||
You can then run a program from the cli:
|
You can then run a program from the cli:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
@ -6,6 +6,7 @@ use anyhow::{anyhow, Result};
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use cli::Cli;
|
use cli::Cli;
|
||||||
use engine::Engine;
|
use engine::Engine;
|
||||||
|
#[cfg(feature = "gamepad")]
|
||||||
use gilrs::Gilrs;
|
use gilrs::Gilrs;
|
||||||
use pixels::{Pixels, SurfaceTexture};
|
use pixels::{Pixels, SurfaceTexture};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
@ -20,6 +21,7 @@ const FRAMETIME: Duration = Duration::from_nanos((1000000000. / 30.) as u64);
|
|||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
#[cfg(feature = "gamepad")]
|
||||||
let mut girls = Gilrs::new().expect("Could not read gamepad inputs.");
|
let mut girls = Gilrs::new().expect("Could not read gamepad inputs.");
|
||||||
let initial_state = read_u16s_from_file(&cli.program)?;
|
let initial_state = read_u16s_from_file(&cli.program)?;
|
||||||
// The initial state is cloned, so we keep it around for a restart.
|
// The initial state is cloned, so we keep it around for a restart.
|
||||||
@ -27,6 +29,7 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
let event_loop = EventLoop::new()?;
|
let event_loop = EventLoop::new()?;
|
||||||
let mut input = WinitInputHelper::new();
|
let mut input = WinitInputHelper::new();
|
||||||
|
#[cfg(feature = "gamepad")]
|
||||||
let mut gamepad = build_gamepad_map();
|
let mut gamepad = build_gamepad_map();
|
||||||
if cli.scaling < 1 {
|
if cli.scaling < 1 {
|
||||||
return Err(anyhow!("The minimal scaling factor is 1"));
|
return Err(anyhow!("The minimal scaling factor is 1"));
|
||||||
@ -99,8 +102,12 @@ fn main() -> Result<()> {
|
|||||||
ipf += 1;
|
ipf += 1;
|
||||||
}
|
}
|
||||||
let engine_elapsed = engine_start.elapsed();
|
let engine_elapsed = engine_start.elapsed();
|
||||||
|
#[cfg(not(feature = "gamepad"))]
|
||||||
|
let (c1, c2) = get_input_code(&input, &pixels);
|
||||||
|
#[cfg(feature = "gamepad")]
|
||||||
gamepad.update_with_gilrs(&mut girls);
|
gamepad.update_with_gilrs(&mut girls);
|
||||||
let (c1, c2) = get_input_code(&input, &gamepad, &pixels);
|
#[cfg(feature = "gamepad")]
|
||||||
|
let (c1, c2) = get_input_code_gamepad(&input, &gamepad, &pixels);
|
||||||
engine.perform_sync(c1, c2, &mut raw_buffer);
|
engine.perform_sync(c1, c2, &mut raw_buffer);
|
||||||
update_image_buffer(pixels.frame_mut(), &raw_buffer);
|
update_image_buffer(pixels.frame_mut(), &raw_buffer);
|
||||||
|
|
||||||
|
46
src/utils.rs
46
src/utils.rs
@ -1,16 +1,17 @@
|
|||||||
use crate::RES;
|
use crate::RES;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use pixels::Pixels;
|
use pixels::Pixels;
|
||||||
use std::hash::Hash;
|
|
||||||
use winit::{
|
use winit::{
|
||||||
event::MouseButton,
|
event::MouseButton,
|
||||||
event_loop::EventLoopWindowTarget,
|
event_loop::EventLoopWindowTarget,
|
||||||
keyboard::{Key, KeyCode},
|
keyboard::{Key, KeyCode},
|
||||||
};
|
};
|
||||||
use winit_input_helper::WinitInputHelper;
|
use winit_input_helper::WinitInputHelper;
|
||||||
|
#[cfg(feature = "gamepad")]
|
||||||
use winit_input_map::{input_map, GamepadButton, InputMap};
|
use winit_input_map::{input_map, GamepadButton, InputMap};
|
||||||
|
|
||||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
#[cfg(feature = "gamepad")]
|
||||||
|
#[derive(Debug, std::hash::Hash, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum NesInput {
|
pub enum NesInput {
|
||||||
Up,
|
Up,
|
||||||
Down,
|
Down,
|
||||||
@ -22,6 +23,7 @@ pub enum NesInput {
|
|||||||
Select,
|
Select,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gamepad")]
|
||||||
pub fn build_gamepad_map() -> InputMap<NesInput> {
|
pub fn build_gamepad_map() -> InputMap<NesInput> {
|
||||||
input_map!(
|
input_map!(
|
||||||
(NesInput::A, GamepadButton::East),
|
(NesInput::A, GamepadButton::East),
|
||||||
@ -67,8 +69,8 @@ pub fn update_image_buffer(imbuff: &mut [u8], screen: &[u16; RES * RES]) {
|
|||||||
*imbuff.get_mut(4 * i + 3).expect("Error with image buffer") = 255;
|
*imbuff.get_mut(4 * i + 3).expect("Error with image buffer") = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "gamepad")]
|
||||||
pub fn get_input_code(
|
pub fn get_input_code_gamepad(
|
||||||
input: &WinitInputHelper,
|
input: &WinitInputHelper,
|
||||||
gamepad: &InputMap<NesInput>,
|
gamepad: &InputMap<NesInput>,
|
||||||
pxls: &Pixels,
|
pxls: &Pixels,
|
||||||
@ -129,3 +131,39 @@ pub fn handle_event_loop_error(handle: &EventLoopWindowTarget<()>, msg: impl AsR
|
|||||||
eprintln!("{}", msg.as_ref());
|
eprintln!("{}", msg.as_ref());
|
||||||
handle.exit();
|
handle.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "gamepad"))]
|
||||||
|
pub fn get_input_code(input: &WinitInputHelper, pxls: &Pixels) -> (u16, u16) {
|
||||||
|
let raw_mp = input.cursor().unwrap_or((0., 0.));
|
||||||
|
let mp = match pxls.window_pos_to_pixel(raw_mp) {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(ev) => pxls.clamp_pixel_pos(ev),
|
||||||
|
};
|
||||||
|
let pos_code = (mp.1 as u16 * 256) + mp.0 as u16;
|
||||||
|
let mut key_code = 0_u16;
|
||||||
|
if input.key_held(KeyCode::Space) || input.mouse_held(MouseButton::Left) {
|
||||||
|
key_code += 1;
|
||||||
|
}
|
||||||
|
if input.key_held_logical(Key::Character("b")) || input.mouse_held(MouseButton::Right) {
|
||||||
|
key_code += 2;
|
||||||
|
}
|
||||||
|
if input.key_held_logical(Key::Character("w")) || input.key_held(KeyCode::ArrowUp) {
|
||||||
|
key_code += 4;
|
||||||
|
}
|
||||||
|
if input.key_held_logical(Key::Character("s")) || input.key_held(KeyCode::ArrowDown) {
|
||||||
|
key_code += 8;
|
||||||
|
}
|
||||||
|
if input.key_held_logical(Key::Character("a")) || input.key_held(KeyCode::ArrowLeft) {
|
||||||
|
key_code += 16;
|
||||||
|
}
|
||||||
|
if input.key_held_logical(Key::Character("d")) || input.key_held(KeyCode::ArrowRight) {
|
||||||
|
key_code += 32;
|
||||||
|
}
|
||||||
|
if input.key_held_logical(Key::Character("n")) {
|
||||||
|
key_code += 64;
|
||||||
|
}
|
||||||
|
if input.key_held_logical(Key::Character("m")) {
|
||||||
|
key_code += 128;
|
||||||
|
}
|
||||||
|
(pos_code, key_code)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user