diff --git a/Cargo.lock b/Cargo.lock index 4c79be1..4853d4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + [[package]] name = "cfg-if" version = "0.1.10" @@ -50,6 +56,7 @@ name = "gamebridge" version = "0.1.0" dependencies = [ "anyhow", + "bitflags", "log", "pretty_env_logger", ] diff --git a/gamebridge/Cargo.toml b/gamebridge/Cargo.toml index 5f31f62..155c798 100644 --- a/gamebridge/Cargo.toml +++ b/gamebridge/Cargo.toml @@ -8,5 +8,6 @@ edition = "2018" [dependencies] anyhow = "1.0" +bitflags = "1.2" log = "0.4" pretty_env_logger = "0.4" diff --git a/gamebridge/src/controller.rs b/gamebridge/src/controller.rs new file mode 100644 index 0000000..d0b0e6b --- /dev/null +++ b/gamebridge/src/controller.rs @@ -0,0 +1,86 @@ +bitflags! { + // 0x0100 Digital Pad Right + // 0x0200 Digital Pad Left + // 0x0400 Digital Pad Down + // 0x0800 Digital Pad Up + // 0x1000 Start + // 0x2000 Z + // 0x4000 B + // 0x8000 A + pub(crate) struct HiButtons: u8 { + const NONE = 0x00; + const DPAD_RIGHT = 0x01; + const DPAD_LEFT = 0x02; + const DPAD_DOWN = 0x04; + const DPAD_UP = 0x08; + const START = 0x10; + const Z_BUTTON = 0x20; + const B_BUTTON = 0x40; + const A_BUTTON = 0x80; + } +} + +impl HiButtons { + pub fn clear(&mut self) { + self.bits = 0; + } +} + +bitflags! { + // 0x0001 C-Right + // 0x0002 C-Left + // 0x0004 C-Down + // 0x0008 C-Up + // 0x0010 R + // 0x0020 L + // 0x0040 (reserved) + // 0x0080 (reserved) + pub(crate) struct LoButtons: u8 { + const NONE = 0x00; + const C_RIGHT = 0x01; + const C_LEFT = 0x02; + const C_DOWN = 0x04; + const C_UP = 0x08; + const R_BUTTON = 0x10; + const L_BUTTON = 0x20; + } +} + +impl LoButtons { + pub fn clear(&mut self) { + self.bits = 0; + } +} + +pub(crate) fn test(st: crate::MTState) { + let mut lo: LoButtons = LoButtons::NONE; + let mut hi: HiButtons = HiButtons::NONE; + + loop { + use std::{thread::sleep, time::Duration}; + let one_second = Duration::new(1, 0); + + hi = HiButtons::A_BUTTON | HiButtons::START; + + { + println!("pressing a + start"); + let mut data = st.write().unwrap(); + data.controller[0] = hi.bits as u8; + data.controller[1] = lo.bits as u8; + } + + sleep(one_second); + + hi.clear(); + lo.clear(); + + { + println!("releasing a + start"); + let mut data = st.write().unwrap(); + data.controller[0] = hi.bits as u8; + data.controller[1] = lo.bits as u8; + } + + sleep(one_second); + } +} diff --git a/gamebridge/src/main.rs b/gamebridge/src/main.rs index d91f73c..12410d9 100644 --- a/gamebridge/src/main.rs +++ b/gamebridge/src/main.rs @@ -1,20 +1,51 @@ +#[macro_use] +extern crate bitflags; + +pub(crate) mod controller; + use anyhow::{anyhow, Result}; use log::{debug, error, info, warn}; use std::{ fs::{File, OpenOptions}, io::{Read, Write}, str::from_utf8, + sync::{Arc, RwLock}, + thread::spawn, + time::Instant, }; +#[derive(Debug)] +pub(crate) struct State { + controller: [u8; 4], + last_got: Box, + ok: bool, +} + +pub(crate) type MTState = Arc>; + fn main() -> Result<()> { pretty_env_logger::try_init()?; - let mut controller_data = [0; 4]; let mut vblank = File::open("vblank")?; let mut input = OpenOptions::new().write(true).open("input")?; + let st = { + let st = State { + controller: [0; 4], + last_got: Box::new(Instant::now()), + ok: true, + }; + + Arc::new(RwLock::new(st)) + }; + info!("ready"); + { + let st = st.clone(); + spawn(move || controller::test(st)); + } + loop { let mut data = [0; 3]; debug!("waiting for vblank"); @@ -23,11 +54,14 @@ fn main() -> Result<()> { debug!("got data: {}", str); match str { - "OK\n" => input.write(&controller_data)?, + "OK\n" => { + let data = st.read().unwrap(); + input.write(&data.controller)? + } "BYE" => { warn!("asked to exit by the game"); return Ok(()); - }, + } _ => { error!("got unknown FIFO data {}", str); return Err(anyhow!("unknown FIFO data received"));