feat: implement keyboard controls
This commit is contained in:
parent
468f7c0f83
commit
40ca0abb72
17
src/emu.rs
17
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()
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue