Compare commits
2 commits
main
...
pistoninpu
| Author | SHA1 | Date | |
|---|---|---|---|
| 279127677d | |||
| 82ed8948fb |
11 changed files with 683 additions and 14 deletions
56
Cargo.lock
generated
56
Cargo.lock
generated
|
|
@ -10,6 +10,7 @@ dependencies = [
|
||||||
"ftdi-embedded-hal",
|
"ftdi-embedded-hal",
|
||||||
"image",
|
"image",
|
||||||
"piston_window",
|
"piston_window",
|
||||||
|
"pistoncore-sdl2_window",
|
||||||
"unreal_asset",
|
"unreal_asset",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
@ -758,6 +759,15 @@ dependencies = [
|
||||||
"gl_generator 0.13.1",
|
"gl_generator 0.13.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gl"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a94edab108827d67608095e269cf862e60d920f144a5026d3dbcfd8b877fb404"
|
||||||
|
dependencies = [
|
||||||
|
"gl_generator 0.14.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gl_generator"
|
name = "gl_generator"
|
||||||
version = "0.13.1"
|
version = "0.13.1"
|
||||||
|
|
@ -1569,7 +1579,7 @@ version = "0.72.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "006f26dfaef3db5d3f29927a5aeedc62680e947707cd1d33015a7dba32234bdb"
|
checksum = "006f26dfaef3db5d3f29927a5aeedc62680e947707cd1d33015a7dba32234bdb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gl",
|
"gl 0.13.0",
|
||||||
"glutin",
|
"glutin",
|
||||||
"glutin-winit",
|
"glutin-winit",
|
||||||
"pistoncore-input",
|
"pistoncore-input",
|
||||||
|
|
@ -1591,6 +1601,19 @@ dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pistoncore-sdl2_window"
|
||||||
|
version = "0.71.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4a55932286299ac3b9aef1b97e2cfaa37b4daed00260da152736d9d435acd3a2"
|
||||||
|
dependencies = [
|
||||||
|
"gl 0.14.0",
|
||||||
|
"pistoncore-input",
|
||||||
|
"pistoncore-window",
|
||||||
|
"sdl2",
|
||||||
|
"shader_version",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pistoncore-window"
|
name = "pistoncore-window"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
@ -1905,6 +1928,29 @@ dependencies = [
|
||||||
"tiny-skia",
|
"tiny-skia",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sdl2"
|
||||||
|
version = "0.37.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b498da7d14d1ad6c839729bd4ad6fc11d90a57583605f3b4df2cd709a9cd380"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"lazy_static",
|
||||||
|
"libc",
|
||||||
|
"sdl2-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sdl2-sys"
|
||||||
|
version = "0.37.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "951deab27af08ed9c6068b7b0d05a93c91f0a8eb16b6b816a5e73452a43521d3"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"version-compare 0.1.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.210"
|
version = "1.0.210"
|
||||||
|
|
@ -2075,7 +2121,7 @@ dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
"toml",
|
"toml",
|
||||||
"version-compare",
|
"version-compare 0.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2329,6 +2375,12 @@ dependencies = [
|
||||||
"piston-float",
|
"piston-float",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version-compare"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version-compare"
|
name = "version-compare"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,15 @@ clap = { version = "4.5.17", features = ["derive"] }
|
||||||
ftdi-embedded-hal = { version = "0.22.0", features = ["libftd2xx"], optional = true }
|
ftdi-embedded-hal = { version = "0.22.0", features = ["libftd2xx"], optional = true }
|
||||||
image = "0.25.2"
|
image = "0.25.2"
|
||||||
piston_window = { version = "0.132.0", optional = true }
|
piston_window = { version = "0.132.0", optional = true }
|
||||||
|
pistoncore-sdl2_window = { version = "0.71.0", optional = true }
|
||||||
unreal_asset = "0.1.16"
|
unreal_asset = "0.1.16"
|
||||||
url = "2.5.2"
|
url = "2.5.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["ftdi","piston"]
|
default = ["ftdi","piston","pistoninput"]
|
||||||
ftdi = ["dep:ftdi-embedded-hal"]
|
ftdi = ["dep:ftdi-embedded-hal"]
|
||||||
piston = ["dep:piston_window"]
|
piston = ["dep:piston_window"]
|
||||||
|
pistoninput = ["dep:pistoncore-sdl2_window"]
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
|
||||||
1
elapseio/.gitignore
vendored
Normal file
1
elapseio/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/target
|
||||||
156
elapseio/Cargo.lock
generated
Normal file
156
elapseio/Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mercuryio"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"windows",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.101"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.62.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9579d0e6970fd5250aa29aba5994052385ff55cf7b28a059e484bb79ea842e42"
|
||||||
|
dependencies = [
|
||||||
|
"windows-collections",
|
||||||
|
"windows-core",
|
||||||
|
"windows-future",
|
||||||
|
"windows-link",
|
||||||
|
"windows-numerics",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-collections"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a90dd7a7b86859ec4cdf864658b311545ef19dbcf17a672b52ab7cefe80c336f"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.62.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57fe7168f7de578d2d8a05b07fd61870d2e73b4020e9f49aa00da8471723497c"
|
||||||
|
dependencies = [
|
||||||
|
"windows-implement",
|
||||||
|
"windows-interface",
|
||||||
|
"windows-link",
|
||||||
|
"windows-result",
|
||||||
|
"windows-strings",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-future"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2194dee901458cb79e1148a4e9aac2b164cc95fa431891e7b296ff0b2f1d8a6"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core",
|
||||||
|
"windows-link",
|
||||||
|
"windows-threading",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-implement"
|
||||||
|
version = "0.60.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-interface"
|
||||||
|
version = "0.59.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-link"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-numerics"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2ce3498fe0aba81e62e477408383196b4b0363db5e0c27646f932676283b43d8"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-result"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-strings"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-threading"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab47f085ad6932defa48855254c758cdd0e2f2d48e62a34118a268d8f345e118"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
13
elapseio/Cargo.toml
Normal file
13
elapseio/Cargo.toml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
cargo-features = ["per-package-target"]
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "elapseio"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
default-target="x86_64-pc-windows-gnu"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
windows = { version = "0.62.0", features = ["Win32_Foundation", "Win32_UI_WindowsAndMessaging", "Win32_System_WindowsProgramming", "Win32_UI_Input_KeyboardAndMouse", "Win32_System_Diagnostics_Debug", "Win32_System_Threading", "Win32_UI_Input_Touch", "Win32_UI_Controls", "Win32_Graphics_Gdi", "Win32_Devices_Communication", "Win32_Storage_FileSystem", "Win32_Security", "Win32_System_Diagnostics_ToolHelp"] }
|
||||||
2
elapseio/rust-toolchain.toml
Normal file
2
elapseio/rust-toolchain.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
[toolchain]
|
||||||
|
channel = "nightly"
|
||||||
204
elapseio/src/lib.rs
Normal file
204
elapseio/src/lib.rs
Normal file
|
|
@ -0,0 +1,204 @@
|
||||||
|
#![feature(slice_as_array)]
|
||||||
|
use std::ffi::c_void;
|
||||||
|
use std::net::{SocketAddr, UdpSocket};
|
||||||
|
use std::ptr::{self, NonNull};
|
||||||
|
use std::sync::{Mutex, OnceLock};
|
||||||
|
use std::thread::{self, JoinHandle};
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
use windows::Win32::Foundation::*;
|
||||||
|
use windows::core::*;
|
||||||
|
|
||||||
|
static SOCKET: OnceLock<UdpSocket> = OnceLock::new();
|
||||||
|
static LEDSOCKET: OnceLock<UdpSocket> = OnceLock::new();
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "system" fn mercury_io_get_api_version() -> u16 {
|
||||||
|
0x100
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "system" fn mercury_io_init() -> HRESULT {
|
||||||
|
let s = UdpSocket::bind("127.0.0.1:45052").unwrap();
|
||||||
|
let _ = s.set_read_timeout(Some(Duration::from_millis(8)));
|
||||||
|
let _ = SOCKET.set(s);
|
||||||
|
|
||||||
|
let _ = LEDSOCKET.set(UdpSocket::bind("0.0.0.0:0").unwrap());
|
||||||
|
|
||||||
|
S_OK
|
||||||
|
}
|
||||||
|
|
||||||
|
enum OpBtn {
|
||||||
|
Test = 0x01,
|
||||||
|
Service = 0x02,
|
||||||
|
Coin = 0x04,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GameBtn {
|
||||||
|
VolUp = 0x01,
|
||||||
|
VolDown = 0x02,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn interleave_slices(input: &[bool], group_size: usize) -> Vec<bool> {
|
||||||
|
let num_groups = input.len() / group_size;
|
||||||
|
let mut result = Vec::with_capacity(input.len());
|
||||||
|
|
||||||
|
for i in 0..group_size {
|
||||||
|
for j in 0..num_groups {
|
||||||
|
let index = j * group_size + i;
|
||||||
|
result.push(input[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
static OP_BTN_LOCK: Mutex<u8> = Mutex::new(0);
|
||||||
|
static GAME_BTN_LOCK: Mutex<u8> = Mutex::new(0);
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "system" fn mercury_io_poll() -> HRESULT {
|
||||||
|
let mut op_btn: u8 = 0;
|
||||||
|
let mut game_btn: u8 = 0;
|
||||||
|
|
||||||
|
*OP_BTN_LOCK.lock().unwrap() = op_btn;
|
||||||
|
*GAME_BTN_LOCK.lock().unwrap() = game_btn;
|
||||||
|
|
||||||
|
S_OK
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "system" fn mercury_io_get_opbtns(opbtn: *mut u8) {
|
||||||
|
if let Some(mut ptr) = NonNull::new(opbtn) {
|
||||||
|
unsafe {
|
||||||
|
// Safety: relies on parent hook developer
|
||||||
|
let op_btn_ref = ptr.as_mut();
|
||||||
|
*op_btn_ref = *OP_BTN_LOCK.lock().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "system" fn mercury_io_get_gamebtns(gamebtn: *mut u8) {
|
||||||
|
if let Some(mut ptr) = NonNull::new(gamebtn) {
|
||||||
|
unsafe {
|
||||||
|
// Safety: relies on parent hook developer
|
||||||
|
let game_btn_ref = ptr.as_mut();
|
||||||
|
*game_btn_ref = *GAME_BTN_LOCK.lock().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "system" fn mercury_io_touch_init() -> HRESULT {
|
||||||
|
S_OK
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
static _TOUCH_THREAD_HANDLE: Mutex<Option<JoinHandle<()>>> = Mutex::new(None);
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "system" fn mercury_io_touch_start(perform_scan: extern "C" fn(*mut bool)) {
|
||||||
|
if let Some(handle) = &*_TOUCH_THREAD_HANDLE.lock().unwrap() {
|
||||||
|
if !handle.is_finished() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let handle = std::thread::spawn(move || {
|
||||||
|
let mut buf = [0; 1500];
|
||||||
|
loop {
|
||||||
|
let start = Instant::now();
|
||||||
|
let mut cell_pressed: [bool; 240] = [false; 240];
|
||||||
|
match SOCKET.get() {
|
||||||
|
Some(socket) => {
|
||||||
|
match socket.recv_from(&mut buf) {
|
||||||
|
Ok((amt, _src)) => {
|
||||||
|
let bytes = buf[..amt].to_vec();
|
||||||
|
let bool_vec: Vec<bool> = bytes
|
||||||
|
.iter()
|
||||||
|
.flat_map(|&byte| {
|
||||||
|
(0..4).map(move |i| {
|
||||||
|
let bit1 = (byte >> (7 - i * 2)) & 1;
|
||||||
|
let bit2 = (byte >> (6 - i * 2)) & 1;
|
||||||
|
(bit1 | bit2) == 1
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
// let boolleft: &[bool; 240] = bool_vec[120..240].as_array().unwrap();
|
||||||
|
// let boolright: &[bool; 240] = bool_vec[..120];
|
||||||
|
let mut bl = [false; 240];
|
||||||
|
let mut br = [false; 240];
|
||||||
|
//left side
|
||||||
|
let mut v: Vec<bool> = Vec::new();
|
||||||
|
for x in bool_vec[..120].as_chunks::<4>().0.iter().rev() {
|
||||||
|
v.append(&mut x.to_vec());
|
||||||
|
}
|
||||||
|
cell_pressed[120..240].copy_from_slice(&interleave_slices(&v, 4));
|
||||||
|
//right side
|
||||||
|
cell_pressed[..120]
|
||||||
|
.copy_from_slice(&interleave_slices(&bool_vec[120..240], 4));
|
||||||
|
// let c: [bool; _] = *bool_vec[..240].as_array().unwrap();
|
||||||
|
}
|
||||||
|
Err(e) => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
println!("Socket hasn't been initialized yet")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if start.elapsed() < Duration::from_millis(8) {
|
||||||
|
let remaining_time = Duration::from_millis(8) - start.elapsed();
|
||||||
|
thread::sleep(remaining_time);
|
||||||
|
}
|
||||||
|
perform_scan(cell_pressed.as_mut_ptr());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*_TOUCH_THREAD_HANDLE.lock().unwrap() = Some(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RGB {
|
||||||
|
red: u8,
|
||||||
|
green: u8,
|
||||||
|
blue: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for RGB {
|
||||||
|
type Item = u8;
|
||||||
|
type IntoIter = std::array::IntoIter<u8, 3>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
IntoIterator::into_iter([self.red, self.green, self.blue])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flatten<T, const N: usize>(v: Vec<Vec<[T; N]>>) -> Vec<T> {
|
||||||
|
v.into_iter().flatten().flatten().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "system" fn mercury_io_touch_set_leds(ledsaddr: usize) {
|
||||||
|
let mut header: Vec<u8> = vec![2, 2];
|
||||||
|
let mut leds: Vec<RGB> = Vec::new();
|
||||||
|
for i in (3..1920).step_by(4) {
|
||||||
|
let n: u32 = unsafe { ptr::read((ledsaddr + i) as *const u32) };
|
||||||
|
let a: [u8; 4] = n.to_le_bytes();
|
||||||
|
leds.push(RGB {
|
||||||
|
red: a[1],
|
||||||
|
green: a[2],
|
||||||
|
blue: a[3],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let addr = SocketAddr::from(([127, 0, 0, 1], 21324));
|
||||||
|
let mut flattened: Vec<u8> = leds.into_iter().flatten().collect();
|
||||||
|
header.append(&mut flattened);
|
||||||
|
match SOCKET.get() {
|
||||||
|
Some(socket) => {
|
||||||
|
let sock: UdpSocket = socket.try_clone().unwrap();
|
||||||
|
let _ = sock.send_to(&header, addr);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
println!("Ledsocket hasn't been initialized yet")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
mod file;
|
mod file;
|
||||||
mod realtimeudp;
|
mod realtimeudp;
|
||||||
mod stdin;
|
mod stdin;
|
||||||
|
mod piston;
|
||||||
|
|
||||||
pub struct Input;
|
pub struct Input;
|
||||||
29
src/input/piston.rs
Normal file
29
src/input/piston.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
use std::{net::UdpSocket, sync::mpsc::Sender, thread};
|
||||||
|
|
||||||
|
use crate::input::Input;
|
||||||
|
|
||||||
|
impl Input {
|
||||||
|
pub fn piston(tx: Sender<Vec<[f32; 4]>>) {
|
||||||
|
thread::spawn(move || {
|
||||||
|
let socket = UdpSocket::bind("127.0.0.1:45052").unwrap();
|
||||||
|
let mut buf = [0; 1500];
|
||||||
|
loop {
|
||||||
|
let mut leds: Vec<[f32; 4]> = Vec::new();
|
||||||
|
let (amt, _src) = socket.recv_from(&mut buf).unwrap();
|
||||||
|
let bytes = buf[..amt].to_vec();
|
||||||
|
// let _ = tx.send();
|
||||||
|
for byte in bytes {
|
||||||
|
for i in 0..8 {
|
||||||
|
let bit = (byte >> i) & 1;
|
||||||
|
if bit == 1 {
|
||||||
|
leds.push([1.0,1.0,1.0,1.0])
|
||||||
|
} else {
|
||||||
|
leds.push([0.02,0.02,0.02,1.0])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = tx.send(leds.clone());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -26,6 +26,8 @@ fn main() {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
let (tx, rx): (Sender<Vec<[f32; 4]>>, Receiver<Vec<[f32; 4]>>) = mpsc::channel();
|
let (tx, rx): (Sender<Vec<[f32; 4]>>, Receiver<Vec<[f32; 4]>>) = mpsc::channel();
|
||||||
match args.input.as_str() {
|
match args.input.as_str() {
|
||||||
|
#[cfg(feature = "piston")]
|
||||||
|
"piston" => Input::piston(tx),
|
||||||
"-" | "stdin" => Input::stdin(tx),
|
"-" | "stdin" => Input::stdin(tx),
|
||||||
_ => {
|
_ => {
|
||||||
match Url::parse(&args.input) {
|
match Url::parse(&args.input) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
use piston_window::*;
|
|
||||||
use piston_window::graphics::math::Scalar;
|
use piston_window::graphics::math::Scalar;
|
||||||
|
use piston_window::*;
|
||||||
|
use std::net::UdpSocket;
|
||||||
|
use std::sync::mpsc::{self, Sender};
|
||||||
|
use std::time::Instant;
|
||||||
use std::{sync::mpsc::Receiver, time::Duration};
|
use std::{sync::mpsc::Receiver, time::Duration};
|
||||||
|
|
||||||
use crate::output::Output;
|
use crate::output::Output;
|
||||||
|
|
@ -9,14 +12,107 @@ use crate::utils::{compare, offset};
|
||||||
|
|
||||||
impl Output {
|
impl Output {
|
||||||
pub fn piston(rx: Receiver<Vec<[f32; 4]>>) {
|
pub fn piston(rx: Receiver<Vec<[f32; 4]>>) {
|
||||||
let mut window: PistonWindow =
|
let mut leds = vec![[0.02, 0.02, 0.02, 1.0]; 480];
|
||||||
WindowSettings::new("ELApse", [800, 800])
|
//Input init
|
||||||
.transparent(true)
|
let mut mousehold = false;
|
||||||
.exit_on_esc(true).build().unwrap();
|
let mut lastpos: Option<(i16, i16)> = None;
|
||||||
|
let mut timesince = Instant::now();
|
||||||
|
let mut buf = [0u8; 60];
|
||||||
|
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||||
|
let mut conx: f64 = 0.0;
|
||||||
|
let mut cony: f64 = 0.0;
|
||||||
|
|
||||||
|
//screen init
|
||||||
|
let mut window: PistonWindow<sdl2_window::Sdl2Window> = WindowSettings::new("ELApse", [800, 800])
|
||||||
|
.transparent(false)
|
||||||
|
.exit_on_esc(true)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
while let Some(e) = window.next() {
|
while let Some(e) = window.next() {
|
||||||
let r = match rx.recv_timeout(Duration::from_millis(66)) {
|
//Input code
|
||||||
Ok(e) => e,
|
if let Some(pos) = e.mouse_cursor_args() {
|
||||||
Err(_) => vec![[0.02, 0.02, 0.02, 1.0]; 480],
|
let size = window.size();
|
||||||
|
let wh = compare(size.height, size.width) * 0.75;
|
||||||
|
lastpos = calc_pos(pos, [size.width / 2.0, size.height / 2.0], wh);
|
||||||
|
}
|
||||||
|
if mousehold == true && lastpos.is_some() {
|
||||||
|
let mut n: usize = 0;
|
||||||
|
let mut bin = [0u8; 60];
|
||||||
|
let mut touch = [false; 480];
|
||||||
|
let l = lastpos.unwrap();
|
||||||
|
for x in 0..60 {
|
||||||
|
for y in 0..8 {
|
||||||
|
if x == l.0 && y == l.1 {
|
||||||
|
touch[n] = true;
|
||||||
|
};
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let oldbuf = buf.clone();
|
||||||
|
buf.copy_from_slice(&bitwise_or_arrays(&pack_bools_to_bytes(touch), &oldbuf).unwrap());
|
||||||
|
if timesince.elapsed() >= Duration::from_millis(8) {
|
||||||
|
let _ = socket.send_to(&buf, "127.0.0.1:45052");
|
||||||
|
buf = [0u8; 60];
|
||||||
|
timesince = Instant::now()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(Button::Mouse(button)) = e.press_args() {
|
||||||
|
println!("Pressed mouse button '{:?}'", button);
|
||||||
|
if button == MouseButton::Left && lastpos.is_some() {
|
||||||
|
mousehold = true;
|
||||||
|
let mut n: usize = 0;
|
||||||
|
let mut bin = [0u8; 60];
|
||||||
|
let mut touch = [false; 480];
|
||||||
|
let l = lastpos.unwrap();
|
||||||
|
for x in 0..60 {
|
||||||
|
for y in 0..8 {
|
||||||
|
if x == l.0 && y == l.1 {
|
||||||
|
touch[n] = true;
|
||||||
|
};
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let buf = pack_bools_to_bytes(touch);
|
||||||
|
let _ = socket.send_to(&buf, "127.0.0.1:45052");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(Button::Mouse(button)) = e.release_args() {
|
||||||
|
if button == MouseButton::Left {
|
||||||
|
mousehold = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Controller test
|
||||||
|
if let Some(Button::Controller(button)) = e.press_args() {
|
||||||
|
println!("Pressed mouse button '{:?}'", button);
|
||||||
|
}
|
||||||
|
if let Some(Button::Controller(button)) = e.release_args() {
|
||||||
|
println!("DePressed mouse button '{:?}'", button);
|
||||||
|
}
|
||||||
|
if let Some(args) = e.controller_axis_args() {
|
||||||
|
println!("DePressed mouse button '{:?}'", args);
|
||||||
|
if args.axis == 2 || args.axis == 5 {
|
||||||
|
if args.position > -0.5 {
|
||||||
|
mousehold = true
|
||||||
|
} else {
|
||||||
|
mousehold = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if args.axis == 0 {
|
||||||
|
conx = args.position;
|
||||||
|
let wh = compare(800.0,800.0) * 0.75;
|
||||||
|
lastpos = calc_pos_con([conx,cony], [400.0,400.0], wh);
|
||||||
|
}
|
||||||
|
if args.axis == 1 {
|
||||||
|
cony = args.position;
|
||||||
|
let wh = compare(800.0,800.0) * 0.75;
|
||||||
|
lastpos = calc_pos_con([conx,cony], [400.0,400.0], wh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Led receival
|
||||||
|
match rx.recv_timeout(Duration::from_millis(1)) {
|
||||||
|
Ok(e) => leds = e,
|
||||||
|
Err(_) => (),
|
||||||
};
|
};
|
||||||
|
|
||||||
let size = window.size();
|
let size = window.size();
|
||||||
|
|
@ -25,10 +121,121 @@ impl Output {
|
||||||
for e in 1..9 {
|
for e in 1..9 {
|
||||||
for i in 0..60 {
|
for i in 0..60 {
|
||||||
let rwh = wh * (1.0 - (e as f64 * 0.06));
|
let rwh = wh * (1.0 - (e as f64 * 0.06));
|
||||||
circle_arc(r[i*8+(e-1)], rwh/32.0, Scalar::deg_to_rad(offset((((360/60)*i)) as i16, 360, 90) as f64), Scalar::deg_to_rad(offset((((360/60)*i)+6) as i16, 360, 90) as f64), [(size.width/2.0)-(rwh/2.0), (size.height/2.0)-(rwh/2.0), rwh, rwh], c.transform, g);
|
circle_arc(
|
||||||
|
leds[i * 8 + (e - 1)],
|
||||||
|
rwh / 32.0,
|
||||||
|
Scalar::deg_to_rad(offset(((360 / 60) * i) as i16, 360, 90) as f64),
|
||||||
|
Scalar::deg_to_rad(
|
||||||
|
offset((((360 / 60) * i) + 6) as i16, 360, 90) as f64
|
||||||
|
),
|
||||||
|
[
|
||||||
|
(size.width / 2.0) - (rwh / 2.0),
|
||||||
|
(size.height / 2.0) - (rwh / 2.0),
|
||||||
|
rwh,
|
||||||
|
rwh,
|
||||||
|
],
|
||||||
|
c.transform,
|
||||||
|
g,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn calc_pos(point: [f64; 2], center: [f64; 2], wh: f64) -> Option<(i16, i16)> {
|
||||||
|
let dx = point[0] - center[0];
|
||||||
|
let dy = point[1] - center[1];
|
||||||
|
let distance = (dx * dx + dy * dy).sqrt();
|
||||||
|
|
||||||
|
let angle = dy.atan2(dx);
|
||||||
|
let mut deg = angle * 30.0 / std::f64::consts::PI;
|
||||||
|
if deg < 0.0 {
|
||||||
|
deg += 60.0;
|
||||||
|
}
|
||||||
|
let mut x = deg as i16-15;
|
||||||
|
if x < 0 {
|
||||||
|
x += 60
|
||||||
|
}
|
||||||
|
let mut y: Option<i16> = None;
|
||||||
|
for i in 0..8 {
|
||||||
|
let rwh = wh * (1.0 - (i as f64 * 0.065)) / 2.0;
|
||||||
|
let rwe = wh * (1.0 - ((i as f64 + 1.0) * 0.065)) / 2.0;
|
||||||
|
if distance <= rwh && distance >= rwe {
|
||||||
|
y = Some(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if y == None {
|
||||||
|
let min = wh * (1.0 - ((8.0) * 0.065)) / 2.0;
|
||||||
|
if distance <= min {
|
||||||
|
y = Some(7);
|
||||||
|
} else {
|
||||||
|
y = Some(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
y.map(|y_val| (x, y_val))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calc_pos_con(point: [f64; 2], center: [f64; 2], wh: f64) -> Option<(i16, i16)> {
|
||||||
|
let dx = point[0];
|
||||||
|
let dy = point[1];
|
||||||
|
let distance = (dx * dx + dy * dy).sqrt()*wh;
|
||||||
|
|
||||||
|
let angle = dy.atan2(dx);
|
||||||
|
let mut deg = angle * 30.0 / std::f64::consts::PI;
|
||||||
|
if deg < 0.0 {
|
||||||
|
deg += 60.0;
|
||||||
|
}
|
||||||
|
let mut x = deg as i16-15;
|
||||||
|
if x < 0 {
|
||||||
|
x += 60
|
||||||
|
}
|
||||||
|
let mut y: Option<i16> = None;
|
||||||
|
for i in 0..8 {
|
||||||
|
let rwh = wh * (1.0 - (i as f64 * 0.065)) / 2.0;
|
||||||
|
let rwe = wh * (1.0 - ((i as f64 + 1.0) * 0.065)) / 2.0;
|
||||||
|
if distance <= rwh && distance >= rwe {
|
||||||
|
y = Some(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if y == None {
|
||||||
|
let min = wh * (1.0 - ((8.0) * 0.065)) / 2.0;
|
||||||
|
if distance <= min {
|
||||||
|
y = Some(7);
|
||||||
|
} else {
|
||||||
|
y = Some(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
y.map(|y_val| (x, y_val))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pack_bools_to_bytes(bools: [bool; 480]) -> [u8; 60] {
|
||||||
|
let mut result = [0u8; 60];
|
||||||
|
|
||||||
|
for (i, &bit) in bools.iter().enumerate() {
|
||||||
|
let byte_index = i / 8;
|
||||||
|
let bit_index = i % 8;
|
||||||
|
|
||||||
|
if bit {
|
||||||
|
result[byte_index] |= 1 << bit_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bitwise_or_arrays<T: Copy + std::ops::BitOr<Output = T>>(arr1: &[T], arr2: &[T]) -> Result<Vec<T>, &'static str> {
|
||||||
|
if arr1.len() != arr2.len() {
|
||||||
|
return Err("Arrays must be the same length");
|
||||||
|
}
|
||||||
|
|
||||||
|
let result: Vec<T> = arr1.iter()
|
||||||
|
.zip(arr2.iter())
|
||||||
|
.map(|(&a, &b)| a | b)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue