From 40ca0abb7211b6cce168a332bf9832c4624ff9ec Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Fri, 9 Jul 2021 19:19:52 -0500 Subject: [PATCH] feat: implement keyboard controls --- src/emu.rs | 17 ++++++++++----- src/joypad.rs | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 2 +- 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/emu.rs b/src/emu.rs index 140d438..e04785f 100644 --- a/src/emu.rs +++ b/src/emu.rs @@ -4,8 +4,8 @@ use crate::joypad; use crate::ppu::Ppu; use anyhow::Result; use gilrs::Gilrs; -use rodio::OutputStreamHandle; use std::time::Duration; +use winit_input_helper::WinitInputHelper; pub const SM83_CYCLE_TIME: Duration = Duration::from_nanos(1_000_000_000 / SM83_CLOCK_SPEED); pub const CYCLES_IN_FRAME: Cycle = Cycle::new(456 * 154); // 456 Cycles times 154 scanlines @@ -28,19 +28,26 @@ pub fn rom_title(game_boy: &SM83) -> &str { game_boy.rom_title().unwrap_or(DEFAULT_TITLE) } -pub fn run(game_boy: &mut SM83, gamepad: &mut Gilrs, pending: Cycle) -> Cycle { +pub fn run( + game_boy: &mut SM83, + gamepad: &mut Gilrs, + input: &WinitInputHelper, + pending: Cycle, +) -> Cycle { let mut elapsed = Cycle::new(0); while elapsed < pending { - elapsed += run_unsynced(game_boy, gamepad); + elapsed += run_unsynced(game_boy, gamepad, input); } elapsed } -pub fn run_unsynced(game_boy: &mut SM83, gamepad: &mut Gilrs) -> Cycle { +pub fn run_unsynced(game_boy: &mut SM83, gamepad: &mut Gilrs, input: &WinitInputHelper) -> Cycle { if let Some(event) = gamepad.next_event() { - joypad::handle_gamepad_input(&mut game_boy.joypad_mut(), event); + joypad::handle_gamepad_input(game_boy.joypad_mut(), event); + } else { + joypad::handle_keyboard_input(game_boy.joypad_mut(), input); } game_boy.step() diff --git a/src/joypad.rs b/src/joypad.rs index 3fd6bc7..d475bd1 100644 --- a/src/joypad.rs +++ b/src/joypad.rs @@ -1,4 +1,5 @@ use gilrs::{Button, Event as GamepadEvent, EventType as GamepadEventType}; +use winit_input_helper::WinitInputHelper; #[derive(Debug, Clone, Copy)] pub struct Joypad { @@ -109,6 +110,63 @@ impl ButtonEvent { } } +pub fn handle_keyboard_input(pad: &mut Joypad, input: &WinitInputHelper) { + use winit::event::VirtualKeyCode; + + // TODO: What do I have to do to get a match statement here? + + let state = &mut pad.ext; + let irq = &mut pad.interrupt; + + if input.key_pressed(VirtualKeyCode::Down) { + state.dpad_down.update(true, irq); + } else if input.key_released(VirtualKeyCode::Down) { + state.dpad_down.update(false, irq); + } + + if input.key_pressed(VirtualKeyCode::Up) { + state.dpad_up.update(true, irq); + } else if input.key_released(VirtualKeyCode::Up) { + state.dpad_up.update(false, irq); + } + + if input.key_pressed(VirtualKeyCode::Left) { + state.dpad_left.update(true, irq); + } else if input.key_released(VirtualKeyCode::Left) { + state.dpad_left.update(false, irq); + } + + if input.key_pressed(VirtualKeyCode::Right) { + state.dpad_right.update(true, irq); + } else if input.key_released(VirtualKeyCode::Right) { + state.dpad_right.update(false, irq); + } + + if input.key_pressed(VirtualKeyCode::T) { + state.start.update(true, irq); + } else if input.key_released(VirtualKeyCode::T) { + state.start.update(false, irq); + } + + if input.key_pressed(VirtualKeyCode::Y) { + state.select.update(true, irq); + } else if input.key_released(VirtualKeyCode::Y) { + state.select.update(false, irq); + } + + if input.key_pressed(VirtualKeyCode::Z) { + state.south.update(true, irq); + } else if input.key_released(VirtualKeyCode::Z) { + state.south.update(false, irq); + } + + if input.key_pressed(VirtualKeyCode::X) { + state.east.update(true, irq); + } else if input.key_released(VirtualKeyCode::X) { + state.east.update(false, irq); + } +} + pub fn handle_gamepad_input(pad: &mut Joypad, event: GamepadEvent) { use Button::*; use GamepadEventType::*; diff --git a/src/main.rs b/src/main.rs index 3b57b19..dbfebca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -127,7 +127,7 @@ fn main() -> Result<()> { now = Instant::now(); let pending = Cycle::new(delta / gb::emu::SM83_CYCLE_TIME.subsec_nanos()); - cycle_count += gb::emu::run(&mut game_boy, &mut gamepad, pending); + cycle_count += gb::emu::run(&mut game_boy, &mut gamepad, &input, pending); if cycle_count >= gb::emu::CYCLES_IN_FRAME { // Draw Frame