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 crate::ppu::Ppu;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use gilrs::Gilrs;
|
use gilrs::Gilrs;
|
||||||
use rodio::OutputStreamHandle;
|
|
||||||
use std::time::Duration;
|
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 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
|
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)
|
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);
|
let mut elapsed = Cycle::new(0);
|
||||||
|
|
||||||
while elapsed < pending {
|
while elapsed < pending {
|
||||||
elapsed += run_unsynced(game_boy, gamepad);
|
elapsed += run_unsynced(game_boy, gamepad, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed
|
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() {
|
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()
|
game_boy.step()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use gilrs::{Button, Event as GamepadEvent, EventType as GamepadEventType};
|
use gilrs::{Button, Event as GamepadEvent, EventType as GamepadEventType};
|
||||||
|
use winit_input_helper::WinitInputHelper;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Joypad {
|
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) {
|
pub fn handle_gamepad_input(pad: &mut Joypad, event: GamepadEvent) {
|
||||||
use Button::*;
|
use Button::*;
|
||||||
use GamepadEventType::*;
|
use GamepadEventType::*;
|
||||||
|
|
|
@ -127,7 +127,7 @@ fn main() -> Result<()> {
|
||||||
now = Instant::now();
|
now = Instant::now();
|
||||||
|
|
||||||
let pending = Cycle::new(delta / gb::emu::SM83_CYCLE_TIME.subsec_nanos());
|
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 {
|
if cycle_count >= gb::emu::CYCLES_IN_FRAME {
|
||||||
// Draw Frame
|
// Draw Frame
|
||||||
|
|
Loading…
Reference in New Issue