Deprecate InputDevice trait

Former-commit-id: 4d25e16d0a6a0a55a5204c28230620dba3531e08
Former-commit-id: da149cb9ebb1258693272a4e9daa615902d99e6e
This commit is contained in:
Michel Heily 2022-09-12 00:11:50 +03:00
parent 91bb17f6dc
commit 407818d32a
10 changed files with 91 additions and 148 deletions

View file

@ -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 ?

View file

@ -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<RefCell<dyn VideoInterface>>,
pub audio_device: Rc<RefCell<dyn AudioInterface>>,
pub input_device: Rc<RefCell<dyn InputInterface>>,
}
#[derive(Serialize, Deserialize)]
@ -70,7 +69,6 @@ impl GameBoyAdvance {
gamepak: Cartridge,
#[cfg(not(feature = "no_video_interface"))] video_device: Rc<RefCell<dyn VideoInterface>>,
audio_device: Rc<RefCell<dyn AudioInterface>>,
input_device: Rc<RefCell<dyn InputInterface>>,
) -> 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<RefCell<dyn VideoInterface>>,
audio_device: Rc<RefCell<dyn AudioInterface>>,
input_device: Rc<RefCell<dyn InputInterface>>,
) -> bincode::Result<GameBoyAdvance> {
let decoded: Box<SaveState> = 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();

View file

@ -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 {

View file

@ -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};
}

View file

@ -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();

View file

@ -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();

View file

@ -18,15 +18,31 @@ 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) {
impl AudioInterface for AudioDevice {
fn push_sample(&mut self, samples: &[i16]) {
let prod = self.audio_ring_buffer.producer();
for s in samples.iter() {
let _ = prod.push(*s);
}
}
}
#[derive(Default)]
struct RustBoyAdvanceCore {
gba: Option<GameBoyAdvance>,
game_data: Option<GameData>,
audio: Option<Rc<RefCell<AudioDevice>>>,
}
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,
@ -40,30 +56,7 @@ impl HwInterface {
JoypadButton::R1 => GbaButton::ButtonR,
_ => unreachable!(),
};
self.key_state.set_bit(mapped_button as usize, !is_pressed);
}
}
impl AudioInterface for HwInterface {
fn push_sample(&mut self, samples: &[i16]) {
let prod = self.audio_ring_buffer.producer();
for s in samples.iter() {
let _ = prod.push(*s);
}
}
}
impl InputInterface for HwInterface {
fn poll(&mut self) -> u16 {
self.key_state
}
}
#[derive(Default)]
struct RustBoyAdvanceCore {
gba: Option<GameBoyAdvance>,
game_data: Option<GameData>,
hwif: Option<Rc<RefCell<HwInterface>>>,
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]);

View file

@ -1,50 +1,38 @@
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)
}
}
impl Sdl2Input {
pub fn on_keyboard_key_down(&mut self, scancode: Scancode) {
pub fn on_keyboard_key_down(gba: &mut GameBoyAdvance, scancode: Scancode) {
if let Some(key) = scancode_to_keypad(scancode) {
self.keyinput.set_bit(key as usize, false);
gba.get_key_state_mut().set_bit(key as usize, false);
}
}
pub fn on_keyboard_key_up(&mut self, scancode: Scancode) {
pub fn on_keyboard_key_up(gba: &mut GameBoyAdvance, scancode: Scancode) {
if let Some(key) = scancode_to_keypad(scancode) {
self.keyinput.set_bit(key as usize, true);
gba.get_key_state_mut().set_bit(key as usize, true);
}
}
pub fn on_controller_button_down(&mut self, button: Button) {
pub fn on_controller_button_down(gba: &mut GameBoyAdvance, button: Button) {
if let Some(key) = controller_button_to_keypad(button) {
self.keyinput.set_bit(key as usize, false);
gba.get_key_state_mut().set_bit(key as usize, false);
}
}
pub fn on_controller_button_up(&mut self, button: Button) {
pub fn on_controller_button_up(gba: &mut GameBoyAdvance, button: Button) {
if let Some(key) = controller_button_to_keypad(button) {
self.keyinput.set_bit(key as usize, true);
gba.get_key_state_mut().set_bit(key as usize, true);
}
}
pub fn on_axis_motion(&mut self, axis: Axis, val: i16) {
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),
@ -56,17 +44,17 @@ impl Sdl2Input {
}
};
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 };
self.axis_keyinput.set_bit(key as usize, false);
key_state.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);
}
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<gba_keypad::Keys> {
_ => None,
}
}
pub fn create_input() -> Sdl2Input {
Sdl2Input {
keyinput: gba_keypad::KEYINPUT_ALL_RELEASED,
axis_keyinput: gba_keypad::KEYINPUT_ALL_RELEASED,
}
}

View file

@ -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<dyn std::error::Error>> {
..
} => 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<dyn std::error::Error>> {
}
}
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<dyn std::error::Error>> {
gamepak,
video.clone(),
audio.clone(),
input.clone(),
);
gba.skip_bios();
}

View file

@ -23,7 +23,6 @@ pub struct Emulator {
struct Interface {
frame: Vec<u8>,
keyinput: u16,
sample_rate: i32,
audio_ctx: AudioContext,
audio_ring_buffer: AudioRingBuffer,
@ -39,7 +38,6 @@ impl Interface {
fn new(audio_ctx: AudioContext) -> Result<Interface, JsValue> {
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);
}
}