gamebridge: Twitch Control #2

Merged
cadey merged 29 commits from gamebridge into master 2020-05-11 22:40:05 +00:00
4 changed files with 131 additions and 3 deletions
Showing only changes of commit 26b6c1dfd3 - Show all commits

7
Cargo.lock generated
View File

@ -26,6 +26,12 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "0.1.10" version = "0.1.10"
@ -50,6 +56,7 @@ name = "gamebridge"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bitflags",
"log", "log",
"pretty_env_logger", "pretty_env_logger",
] ]

View File

@ -8,5 +8,6 @@ edition = "2018"
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0"
bitflags = "1.2"
log = "0.4" log = "0.4"
pretty_env_logger = "0.4" pretty_env_logger = "0.4"

View File

@ -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);
}
}

View File

@ -1,20 +1,51 @@
#[macro_use]
extern crate bitflags;
pub(crate) mod controller;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use std::{ use std::{
fs::{File, OpenOptions}, fs::{File, OpenOptions},
io::{Read, Write}, io::{Read, Write},
str::from_utf8, str::from_utf8,
sync::{Arc, RwLock},
thread::spawn,
time::Instant,
}; };
#[derive(Debug)]
pub(crate) struct State {
controller: [u8; 4],
last_got: Box<Instant>,
ok: bool,
}
pub(crate) type MTState = Arc<RwLock<State>>;
fn main() -> Result<()> { fn main() -> Result<()> {
pretty_env_logger::try_init()?; pretty_env_logger::try_init()?;
let mut controller_data = [0; 4];
let mut vblank = File::open("vblank")?; let mut vblank = File::open("vblank")?;
let mut input = OpenOptions::new().write(true).open("input")?; 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"); info!("ready");
{
let st = st.clone();
spawn(move || controller::test(st));
}
loop { loop {
let mut data = [0; 3]; let mut data = [0; 3];
debug!("waiting for vblank"); debug!("waiting for vblank");
@ -23,11 +54,14 @@ fn main() -> Result<()> {
debug!("got data: {}", str); debug!("got data: {}", str);
match str { match str {
"OK\n" => input.write(&controller_data)?, "OK\n" => {
let data = st.read().unwrap();
input.write(&data.controller)?
}
"BYE" => { "BYE" => {
warn!("asked to exit by the game"); warn!("asked to exit by the game");
return Ok(()); return Ok(());
}, }
_ => { _ => {
error!("got unknown FIFO data {}", str); error!("got unknown FIFO data {}", str);
return Err(anyhow!("unknown FIFO data received")); return Err(anyhow!("unknown FIFO data received"));