diff --git a/core/benches/performance.rs b/core/benches/performance.rs index 23bb29b..fe7968d 100644 --- a/core/benches/performance.rs +++ b/core/benches/performance.rs @@ -9,7 +9,6 @@ use rustboyadvance_core::prelude::*; struct BenchmarkHardware {} impl AudioInterface for BenchmarkHardware {} -impl InputInterface for BenchmarkHardware {} fn create_gba() -> GameBoyAdvance { // TODO: do I really want this file in my repository ? diff --git a/core/src/gba.rs b/core/src/gba.rs index baff346..6e8b2b9 100644 --- a/core/src/gba.rs +++ b/core/src/gba.rs @@ -15,9 +15,9 @@ use super::sound::SoundController; use super::sysbus::SysBus; use super::timer::Timers; +use super::AudioInterface; #[cfg(not(feature = "no_video_interface"))] use super::VideoInterface; -use super::{AudioInterface, InputInterface}; use arm7tdmi::{self, Arm7tdmiCore}; use rustboyadvance_utils::Shared; @@ -31,7 +31,6 @@ pub struct GameBoyAdvance { #[cfg(not(feature = "no_video_interface"))] pub video_device: Rc>, pub audio_device: Rc>, - pub input_device: Rc>, } #[derive(Serialize, Deserialize)] @@ -70,7 +69,6 @@ impl GameBoyAdvance { gamepak: Cartridge, #[cfg(not(feature = "no_video_interface"))] video_device: Rc>, audio_device: Rc>, - input_device: Rc>, ) -> GameBoyAdvance { // Warn the user if the bios is not the real one match check_real_bios(&bios_rom) { @@ -110,14 +108,10 @@ impl GameBoyAdvance { cpu, sysbus, io_devs, - #[cfg(not(feature = "no_video_interface"))] video_device, audio_device, - input_device, - scheduler, - interrupt_flags, }; @@ -132,7 +126,6 @@ impl GameBoyAdvance { rom: Box<[u8]>, #[cfg(not(feature = "no_video_interface"))] video_device: Rc>, audio_device: Rc>, - input_device: Rc>, ) -> bincode::Result { let decoded: Box = bincode::deserialize_from(savestate)?; @@ -162,14 +155,10 @@ impl GameBoyAdvance { cpu: arm7tdmi, sysbus, io_devs, - interrupt_flags: interrupts, - #[cfg(not(feature = "no_video_interface"))] video_device, audio_device, - input_device, - scheduler, }) } @@ -218,12 +207,16 @@ impl GameBoyAdvance { } #[inline] - pub fn key_poll(&mut self) { - self.sysbus.io.keyinput = self.input_device.borrow_mut().poll(); + pub fn get_key_state(&mut self) -> &u16 { + &self.sysbus.io.keyinput + } + + #[inline] + pub fn get_key_state_mut(&mut self) -> &mut u16 { + &mut self.sysbus.io.keyinput } pub fn frame(&mut self) { - self.key_poll(); static mut OVERSHOOT: usize = 0; unsafe { OVERSHOOT = self.run(CYCLES_FULL_REFRESH - OVERSHOOT); @@ -419,7 +412,6 @@ mod tests { #[cfg(not(feature = "no_video_interface"))] impl VideoInterface for DummyInterface {} impl AudioInterface for DummyInterface {} - impl InputInterface for DummyInterface {} fn make_mock_gba(rom: &[u8]) -> GameBoyAdvance { let bios = vec![0; 0x4000].into_boxed_slice(); @@ -436,7 +428,6 @@ mod tests { #[cfg(not(feature = "no_video_interface"))] dummy.clone(), dummy.clone(), - dummy.clone(), ); gba.skip_bios(); diff --git a/core/src/iodev.rs b/core/src/iodev.rs index c30ff3c..0ccc46a 100644 --- a/core/src/iodev.rs +++ b/core/src/iodev.rs @@ -76,6 +76,10 @@ impl IoDevices { pub fn set_sysbus_ptr(&mut self, ptr: SysBusPtr) { self.sysbus_ptr = ptr; } + + pub(crate) fn set_key_state(&mut self, state: u16) { + self.keyinput = state; + } } impl InterruptConnect for IoDevices { diff --git a/core/src/lib.rs b/core/src/lib.rs index 1d20eaf..471606c 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -131,7 +131,7 @@ pub mod prelude { pub use super::Bus; #[cfg(not(feature = "no_video_interface"))] pub use super::VideoInterface; - pub use super::{AudioInterface, InputInterface, StereoSample}; + pub use super::{AudioInterface, StereoSample}; pub use super::{GBAError, GBAResult, GameBoyAdvance}; pub use rustboyadvance_utils::{read_bin_file, write_bin_file}; } diff --git a/fps_bench/src/main.rs b/fps_bench/src/main.rs index 06b6678..16f292b 100644 --- a/fps_bench/src/main.rs +++ b/fps_bench/src/main.rs @@ -16,7 +16,6 @@ impl BenchmarkHardware { impl VideoInterface for BenchmarkHardware {} impl AudioInterface for BenchmarkHardware {} -impl InputInterface for BenchmarkHardware {} fn main() { if env::args().count() < 3 { @@ -44,7 +43,6 @@ fn main() { gamepak, dummy.clone(), dummy.clone(), - dummy.clone(), ); gba.skip_bios(); diff --git a/platform/rustboyadvance-jni/src/emulator.rs b/platform/rustboyadvance-jni/src/emulator.rs index 992f0c1..d54054e 100644 --- a/platform/rustboyadvance-jni/src/emulator.rs +++ b/platform/rustboyadvance-jni/src/emulator.rs @@ -38,12 +38,6 @@ impl AudioInterface for Hardware { } } -impl InputInterface for Hardware { - fn poll(&mut self) -> u16 { - self.key_state - } -} - struct Renderer { renderer_ref: GlobalRef, frame_buffer_ref: GlobalRef, @@ -325,7 +319,7 @@ impl EmulatorContext { let start_time = Instant::now(); // check key state - self.hwif.borrow_mut().key_state = self.keypad.get_key_state(env); + *self.gba.get_key_state_mut() = self.keypad.get_key_state(env); // run frame self.gba.frame(); diff --git a/platform/rustboyadvance-libretro/src/lib.rs b/platform/rustboyadvance-libretro/src/lib.rs index c5c75b9..812d7e4 100644 --- a/platform/rustboyadvance-libretro/src/lib.rs +++ b/platform/rustboyadvance-libretro/src/lib.rs @@ -18,33 +18,15 @@ use rustboyadvance_utils::audio::AudioRingBuffer; use std::path::Path; use std::cell::RefCell; +use std::default::Default; use std::rc::Rc; -struct HwInterface { - key_state: u16, +#[derive(Default)] +struct AudioDevice { audio_ring_buffer: AudioRingBuffer, } -impl HwInterface { - fn set_button_state(&mut self, button: JoypadButton, is_pressed: bool) { - let mapped_button = match button { - JoypadButton::A => GbaButton::ButtonA, - JoypadButton::B => GbaButton::ButtonB, - JoypadButton::Start => GbaButton::Start, - JoypadButton::Select => GbaButton::Select, - JoypadButton::Left => GbaButton::Left, - JoypadButton::Up => GbaButton::Up, - JoypadButton::Right => GbaButton::Right, - JoypadButton::Down => GbaButton::Down, - JoypadButton::L1 => GbaButton::ButtonL, - JoypadButton::R1 => GbaButton::ButtonR, - _ => unreachable!(), - }; - self.key_state.set_bit(mapped_button as usize, !is_pressed); - } -} - -impl AudioInterface for HwInterface { +impl AudioInterface for AudioDevice { fn push_sample(&mut self, samples: &[i16]) { let prod = self.audio_ring_buffer.producer(); for s in samples.iter() { @@ -53,17 +35,28 @@ impl AudioInterface for HwInterface { } } -impl InputInterface for HwInterface { - fn poll(&mut self) -> u16 { - self.key_state - } -} - #[derive(Default)] struct RustBoyAdvanceCore { gba: Option, game_data: Option, - hwif: Option>>, + audio: Option>>, +} + +fn set_button_state(key_state: &mut u16, button: JoypadButton, is_pressed: bool) { + let mapped_button = match button { + JoypadButton::A => GbaButton::ButtonA, + JoypadButton::B => GbaButton::ButtonB, + JoypadButton::Start => GbaButton::Start, + JoypadButton::Select => GbaButton::Select, + JoypadButton::Left => GbaButton::Left, + JoypadButton::Up => GbaButton::Up, + JoypadButton::Right => GbaButton::Right, + JoypadButton::Down => GbaButton::Down, + JoypadButton::L1 => GbaButton::ButtonL, + JoypadButton::R1 => GbaButton::ButtonR, + _ => unreachable!(), + }; + key_state.set_bit(mapped_button as usize, !is_pressed); } impl libretro_backend::Core for RustBoyAdvanceCore { @@ -113,18 +106,10 @@ impl libretro_backend::Core for RustBoyAdvanceCore { .video(240, 160, 60.0, PixelFormat::ARGB8888) .audio(44100.0); - let hwif = Rc::new(RefCell::new(HwInterface { - key_state: rustboyadvance_core::keypad::KEYINPUT_ALL_RELEASED, - audio_ring_buffer: Default::default(), - })); - let gba = GameBoyAdvance::new( - bios.into_boxed_slice(), - gamepak, - hwif.clone(), - hwif.clone(), - ); + let audio = Rc::new(RefCell::new(AudioDevice::default())); + let gba = GameBoyAdvance::new(bios.into_boxed_slice(), gamepak, audio.clone()); - self.hwif = Some(hwif); + self.audio = Some(audio); self.gba = Some(gba); self.game_data = Some(game_data); LoadGameResult::Success(av_info) @@ -136,17 +121,19 @@ impl libretro_backend::Core for RustBoyAdvanceCore { fn on_run(&mut self, handle: &mut RuntimeHandle) { let joypad_port = 0; - // gba and hwif are `Some` after the game is loaded, so avoiding overhead of unwrap + // gba and audio are `Some` after the game is loaded, so avoiding overhead of unwrap let gba = unsafe { self.gba.as_mut().unsafe_unwrap() }; - let hwif = unsafe { self.hwif.as_mut().unsafe_unwrap() }; + let audio = unsafe { self.audio.as_mut().unsafe_unwrap() }; + let key_state = gba.borrow_mut().get_key_state_mut(); macro_rules! update_controllers { ( $( $button:ident ),+ ) => ( $( - hwif.borrow_mut().set_button_state( JoypadButton::$button, handle.is_joypad_button_pressed( joypad_port, JoypadButton::$button ) ); + set_button_state(key_state, JoypadButton::$button, handle.is_joypad_button_pressed( joypad_port, JoypadButton::$button ) ); )+ ) } + drop(key_state); update_controllers!(A, B, Start, Select, Left, Up, Right, Down, L1, R1); @@ -166,8 +153,8 @@ impl libretro_backend::Core for RustBoyAdvanceCore { // upload sound samples { let mut audio_samples = [0; 4096 * 2]; - let mut hwif = hwif.borrow_mut(); - let consumer = hwif.audio_ring_buffer.consumer(); + let mut audio = audio.borrow_mut(); + let consumer = audio.audio_ring_buffer.consumer(); let count = consumer.pop_slice(&mut audio_samples); handle.upload_audio_frame(&audio_samples[..count]); diff --git a/platform/rustboyadvance-sdl2/src/input.rs b/platform/rustboyadvance-sdl2/src/input.rs index ad524dc..17365f2 100644 --- a/platform/rustboyadvance-sdl2/src/input.rs +++ b/platform/rustboyadvance-sdl2/src/input.rs @@ -1,72 +1,60 @@ +use rustboyadvance_core::GameBoyAdvance; use sdl2::controller::Axis; use sdl2::controller::Button; use sdl2::keyboard::Scancode; use rustboyadvance_core::keypad as gba_keypad; -use rustboyadvance_core::InputInterface; use bit; use bit::BitIndex; -pub struct Sdl2Input { - keyinput: u16, - axis_keyinput: u16, -} - -impl InputInterface for Sdl2Input { - fn poll(&mut self) -> u16 { - !(!self.keyinput | !self.axis_keyinput) +pub fn on_keyboard_key_down(gba: &mut GameBoyAdvance, scancode: Scancode) { + if let Some(key) = scancode_to_keypad(scancode) { + gba.get_key_state_mut().set_bit(key as usize, false); } } -impl Sdl2Input { - pub fn on_keyboard_key_down(&mut self, scancode: Scancode) { - if let Some(key) = scancode_to_keypad(scancode) { - self.keyinput.set_bit(key as usize, false); - } +pub fn on_keyboard_key_up(gba: &mut GameBoyAdvance, scancode: Scancode) { + if let Some(key) = scancode_to_keypad(scancode) { + gba.get_key_state_mut().set_bit(key as usize, true); } +} - pub fn on_keyboard_key_up(&mut self, scancode: Scancode) { - if let Some(key) = scancode_to_keypad(scancode) { - self.keyinput.set_bit(key as usize, true); - } +pub fn on_controller_button_down(gba: &mut GameBoyAdvance, button: Button) { + if let Some(key) = controller_button_to_keypad(button) { + gba.get_key_state_mut().set_bit(key as usize, false); } +} - pub fn on_controller_button_down(&mut self, button: Button) { - if let Some(key) = controller_button_to_keypad(button) { - self.keyinput.set_bit(key as usize, false); - } +pub fn on_controller_button_up(gba: &mut GameBoyAdvance, button: Button) { + if let Some(key) = controller_button_to_keypad(button) { + gba.get_key_state_mut().set_bit(key as usize, true); } +} - pub fn on_controller_button_up(&mut self, button: Button) { - if let Some(key) = controller_button_to_keypad(button) { - self.keyinput.set_bit(key as usize, true); +pub fn on_axis_motion(gba: &mut GameBoyAdvance, axis: Axis, val: i16) { + use gba_keypad::Keys as GbaKeys; + let keys = match axis { + Axis::LeftX => (GbaKeys::Left, GbaKeys::Right), + Axis::LeftY => (GbaKeys::Up, GbaKeys::Down), + Axis::TriggerLeft => (GbaKeys::ButtonL, GbaKeys::ButtonL), + Axis::TriggerRight => (GbaKeys::ButtonR, GbaKeys::ButtonR), + _ => { + return; } - } + }; - pub fn on_axis_motion(&mut self, axis: Axis, val: i16) { - use gba_keypad::Keys as GbaKeys; - let keys = match axis { - Axis::LeftX => (GbaKeys::Left, GbaKeys::Right), - Axis::LeftY => (GbaKeys::Up, GbaKeys::Down), - Axis::TriggerLeft => (GbaKeys::ButtonL, GbaKeys::ButtonL), - Axis::TriggerRight => (GbaKeys::ButtonR, GbaKeys::ButtonR), - _ => { - return; - } - }; - - // Axis motion is an absolute value in the range - // [-32768, 32767]. Let's simulate a very rough dead - // zone to ignore spurious events. - let dead_zone = 10_000; - if val > dead_zone || val < -dead_zone { - let key = if val < 0 { keys.0 } else { keys.1 }; - self.axis_keyinput.set_bit(key as usize, false); - } else { - self.axis_keyinput.set_bit(keys.0 as usize, true); - self.axis_keyinput.set_bit(keys.1 as usize, true); - } + let key_state = gba.get_key_state_mut(); + // Axis motion is an absolute value in the range + // [-32768, 32767]. Let's simulate a very rough dead + // zone to ignore spurious events. + let dead_zone = 10_000; + if val > dead_zone || val < -dead_zone { + let key = if val < 0 { keys.0 } else { keys.1 }; + key_state.set_bit(key as usize, false); + } else { + key_state.set_bit(keys.0 as usize, true); + key_state.set_bit(keys.1 as usize, true); } } @@ -101,10 +89,3 @@ fn controller_button_to_keypad(button: Button) -> Option { _ => None, } } - -pub fn create_input() -> Sdl2Input { - Sdl2Input { - keyinput: gba_keypad::KEYINPUT_ALL_RELEASED, - axis_keyinput: gba_keypad::KEYINPUT_ALL_RELEASED, - } -} diff --git a/platform/rustboyadvance-sdl2/src/main.rs b/platform/rustboyadvance-sdl2/src/main.rs index ad9e01b..b3c95c6 100644 --- a/platform/rustboyadvance-sdl2/src/main.rs +++ b/platform/rustboyadvance-sdl2/src/main.rs @@ -37,7 +37,7 @@ mod input; mod video; use audio::{create_audio_player, create_dummy_player}; -use input::create_input; +use input; use video::{create_video_interface, SCREEN_HEIGHT, SCREEN_WIDTH}; use rustboyadvance_core::cartridge::BackupType; @@ -253,7 +253,7 @@ fn main() -> Result<(), Box> { .. } => match scancode { Scancode::Space => frame_limiter = false, - k => input.borrow_mut().on_keyboard_key_down(k), + k => input::on_keyboard_key_down(&mut gba, k), }, Event::KeyUp { scancode: Some(scancode), @@ -291,17 +291,17 @@ fn main() -> Result<(), Box> { } } Scancode::Space => frame_limiter = true, - k => input.borrow_mut().on_keyboard_key_up(k), + k => input::on_keyboard_key_up(&mut gba, k), }, Event::ControllerButtonDown { button, .. } => match button { Button::RightStick => frame_limiter = !frame_limiter, - b => input.borrow_mut().on_controller_button_down(b), + b => input::on_controller_button_down(&mut gba, b), }, Event::ControllerButtonUp { button, .. } => { - input.borrow_mut().on_controller_button_up(button); + input::on_controller_button_up(&mut gba, button); } Event::ControllerAxisMotion { axis, value, .. } => { - input.borrow_mut().on_axis_motion(axis, value); + input::on_axis_motion(&mut gba, axis, value); } Event::ControllerDeviceRemoved { which, .. } => { let removed = if let Some(active_controller) = &active_controller { @@ -339,7 +339,6 @@ fn main() -> Result<(), Box> { gamepak, video.clone(), audio.clone(), - input.clone(), ); gba.skip_bios(); } diff --git a/platform/rustboyadvance-wasm/src/emulator.rs b/platform/rustboyadvance-wasm/src/emulator.rs index b8c6ea5..48ba0aa 100644 --- a/platform/rustboyadvance-wasm/src/emulator.rs +++ b/platform/rustboyadvance-wasm/src/emulator.rs @@ -23,7 +23,6 @@ pub struct Emulator { struct Interface { frame: Vec, - keyinput: u16, sample_rate: i32, audio_ctx: AudioContext, audio_ring_buffer: AudioRingBuffer, @@ -39,7 +38,6 @@ impl Interface { fn new(audio_ctx: AudioContext) -> Result { Ok(Interface { frame: vec![0; 240 * 160 * 4], - keyinput: gba_keypad::KEYINPUT_ALL_RELEASED, sample_rate: audio_ctx.sample_rate() as i32, audio_ctx: audio_ctx, audio_ring_buffer: Default::default(), @@ -77,12 +75,6 @@ impl AudioInterface for Interface { } } -impl InputInterface for Interface { - fn poll(&mut self) -> u16 { - self.keyinput - } -} - #[wasm_bindgen] impl Emulator { #[wasm_bindgen(constructor)] @@ -141,17 +133,15 @@ impl Emulator { pub fn key_down(&mut self, event_key: &str) { debug!("Key down: {}", event_key); - let mut interface = self.interface.borrow_mut(); if let Some(key) = Emulator::map_key(event_key) { - interface.keyinput.set_bit(key as usize, false); + self.gba.get_key_state().set_bit(key as usize, false); } } pub fn key_up(&mut self, event_key: &str) { debug!("Key up: {}", event_key); - let mut interface = self.interface.borrow_mut(); if let Some(key) = Emulator::map_key(event_key) { - interface.keyinput.set_bit(key as usize, true); + self.gba.get_key_state().set_bit(key as usize, true); } }