feat: implement keyboard controls
This commit is contained in:
		
							
								
								
									
										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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user