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 {} struct BenchmarkHardware {}
impl AudioInterface for BenchmarkHardware {} impl AudioInterface for BenchmarkHardware {}
impl InputInterface for BenchmarkHardware {}
fn create_gba() -> GameBoyAdvance { fn create_gba() -> GameBoyAdvance {
// TODO: do I really want this file in my repository ? // 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::sysbus::SysBus;
use super::timer::Timers; use super::timer::Timers;
use super::AudioInterface;
#[cfg(not(feature = "no_video_interface"))] #[cfg(not(feature = "no_video_interface"))]
use super::VideoInterface; use super::VideoInterface;
use super::{AudioInterface, InputInterface};
use arm7tdmi::{self, Arm7tdmiCore}; use arm7tdmi::{self, Arm7tdmiCore};
use rustboyadvance_utils::Shared; use rustboyadvance_utils::Shared;
@ -31,7 +31,6 @@ pub struct GameBoyAdvance {
#[cfg(not(feature = "no_video_interface"))] #[cfg(not(feature = "no_video_interface"))]
pub video_device: Rc<RefCell<dyn VideoInterface>>, pub video_device: Rc<RefCell<dyn VideoInterface>>,
pub audio_device: Rc<RefCell<dyn AudioInterface>>, pub audio_device: Rc<RefCell<dyn AudioInterface>>,
pub input_device: Rc<RefCell<dyn InputInterface>>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -70,7 +69,6 @@ impl GameBoyAdvance {
gamepak: Cartridge, gamepak: Cartridge,
#[cfg(not(feature = "no_video_interface"))] video_device: Rc<RefCell<dyn VideoInterface>>, #[cfg(not(feature = "no_video_interface"))] video_device: Rc<RefCell<dyn VideoInterface>>,
audio_device: Rc<RefCell<dyn AudioInterface>>, audio_device: Rc<RefCell<dyn AudioInterface>>,
input_device: Rc<RefCell<dyn InputInterface>>,
) -> GameBoyAdvance { ) -> GameBoyAdvance {
// Warn the user if the bios is not the real one // Warn the user if the bios is not the real one
match check_real_bios(&bios_rom) { match check_real_bios(&bios_rom) {
@ -110,14 +108,10 @@ impl GameBoyAdvance {
cpu, cpu,
sysbus, sysbus,
io_devs, io_devs,
#[cfg(not(feature = "no_video_interface"))] #[cfg(not(feature = "no_video_interface"))]
video_device, video_device,
audio_device, audio_device,
input_device,
scheduler, scheduler,
interrupt_flags, interrupt_flags,
}; };
@ -132,7 +126,6 @@ impl GameBoyAdvance {
rom: Box<[u8]>, rom: Box<[u8]>,
#[cfg(not(feature = "no_video_interface"))] video_device: Rc<RefCell<dyn VideoInterface>>, #[cfg(not(feature = "no_video_interface"))] video_device: Rc<RefCell<dyn VideoInterface>>,
audio_device: Rc<RefCell<dyn AudioInterface>>, audio_device: Rc<RefCell<dyn AudioInterface>>,
input_device: Rc<RefCell<dyn InputInterface>>,
) -> bincode::Result<GameBoyAdvance> { ) -> bincode::Result<GameBoyAdvance> {
let decoded: Box<SaveState> = bincode::deserialize_from(savestate)?; let decoded: Box<SaveState> = bincode::deserialize_from(savestate)?;
@ -162,14 +155,10 @@ impl GameBoyAdvance {
cpu: arm7tdmi, cpu: arm7tdmi,
sysbus, sysbus,
io_devs, io_devs,
interrupt_flags: interrupts, interrupt_flags: interrupts,
#[cfg(not(feature = "no_video_interface"))] #[cfg(not(feature = "no_video_interface"))]
video_device, video_device,
audio_device, audio_device,
input_device,
scheduler, scheduler,
}) })
} }
@ -218,12 +207,16 @@ impl GameBoyAdvance {
} }
#[inline] #[inline]
pub fn key_poll(&mut self) { pub fn get_key_state(&mut self) -> &u16 {
self.sysbus.io.keyinput = self.input_device.borrow_mut().poll(); &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) { pub fn frame(&mut self) {
self.key_poll();
static mut OVERSHOOT: usize = 0; static mut OVERSHOOT: usize = 0;
unsafe { unsafe {
OVERSHOOT = self.run(CYCLES_FULL_REFRESH - OVERSHOOT); OVERSHOOT = self.run(CYCLES_FULL_REFRESH - OVERSHOOT);
@ -419,7 +412,6 @@ mod tests {
#[cfg(not(feature = "no_video_interface"))] #[cfg(not(feature = "no_video_interface"))]
impl VideoInterface for DummyInterface {} impl VideoInterface for DummyInterface {}
impl AudioInterface for DummyInterface {} impl AudioInterface for DummyInterface {}
impl InputInterface for DummyInterface {}
fn make_mock_gba(rom: &[u8]) -> GameBoyAdvance { fn make_mock_gba(rom: &[u8]) -> GameBoyAdvance {
let bios = vec![0; 0x4000].into_boxed_slice(); let bios = vec![0; 0x4000].into_boxed_slice();
@ -436,7 +428,6 @@ mod tests {
#[cfg(not(feature = "no_video_interface"))] #[cfg(not(feature = "no_video_interface"))]
dummy.clone(), dummy.clone(),
dummy.clone(), dummy.clone(),
dummy.clone(),
); );
gba.skip_bios(); gba.skip_bios();

View file

@ -76,6 +76,10 @@ impl IoDevices {
pub fn set_sysbus_ptr(&mut self, ptr: SysBusPtr) { pub fn set_sysbus_ptr(&mut self, ptr: SysBusPtr) {
self.sysbus_ptr = ptr; self.sysbus_ptr = ptr;
} }
pub(crate) fn set_key_state(&mut self, state: u16) {
self.keyinput = state;
}
} }
impl InterruptConnect for IoDevices { impl InterruptConnect for IoDevices {

View file

@ -131,7 +131,7 @@ pub mod prelude {
pub use super::Bus; pub use super::Bus;
#[cfg(not(feature = "no_video_interface"))] #[cfg(not(feature = "no_video_interface"))]
pub use super::VideoInterface; pub use super::VideoInterface;
pub use super::{AudioInterface, InputInterface, StereoSample}; pub use super::{AudioInterface, StereoSample};
pub use super::{GBAError, GBAResult, GameBoyAdvance}; pub use super::{GBAError, GBAResult, GameBoyAdvance};
pub use rustboyadvance_utils::{read_bin_file, write_bin_file}; pub use rustboyadvance_utils::{read_bin_file, write_bin_file};
} }

View file

@ -16,7 +16,6 @@ impl BenchmarkHardware {
impl VideoInterface for BenchmarkHardware {} impl VideoInterface for BenchmarkHardware {}
impl AudioInterface for BenchmarkHardware {} impl AudioInterface for BenchmarkHardware {}
impl InputInterface for BenchmarkHardware {}
fn main() { fn main() {
if env::args().count() < 3 { if env::args().count() < 3 {
@ -44,7 +43,6 @@ fn main() {
gamepak, gamepak,
dummy.clone(), dummy.clone(),
dummy.clone(), dummy.clone(),
dummy.clone(),
); );
gba.skip_bios(); 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 { struct Renderer {
renderer_ref: GlobalRef, renderer_ref: GlobalRef,
frame_buffer_ref: GlobalRef, frame_buffer_ref: GlobalRef,
@ -325,7 +319,7 @@ impl EmulatorContext {
let start_time = Instant::now(); let start_time = Instant::now();
// check key state // 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 // run frame
self.gba.frame(); self.gba.frame();

View file

@ -18,15 +18,31 @@ use rustboyadvance_utils::audio::AudioRingBuffer;
use std::path::Path; use std::path::Path;
use std::cell::RefCell; use std::cell::RefCell;
use std::default::Default;
use std::rc::Rc; use std::rc::Rc;
struct HwInterface { #[derive(Default)]
key_state: u16, struct AudioDevice {
audio_ring_buffer: AudioRingBuffer, audio_ring_buffer: AudioRingBuffer,
} }
impl HwInterface { impl AudioInterface for AudioDevice {
fn set_button_state(&mut self, button: JoypadButton, is_pressed: bool) { 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 { let mapped_button = match button {
JoypadButton::A => GbaButton::ButtonA, JoypadButton::A => GbaButton::ButtonA,
JoypadButton::B => GbaButton::ButtonB, JoypadButton::B => GbaButton::ButtonB,
@ -40,30 +56,7 @@ impl HwInterface {
JoypadButton::R1 => GbaButton::ButtonR, JoypadButton::R1 => GbaButton::ButtonR,
_ => unreachable!(), _ => unreachable!(),
}; };
self.key_state.set_bit(mapped_button as usize, !is_pressed); 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>>>,
} }
impl libretro_backend::Core for RustBoyAdvanceCore { impl libretro_backend::Core for RustBoyAdvanceCore {
@ -113,18 +106,10 @@ impl libretro_backend::Core for RustBoyAdvanceCore {
.video(240, 160, 60.0, PixelFormat::ARGB8888) .video(240, 160, 60.0, PixelFormat::ARGB8888)
.audio(44100.0); .audio(44100.0);
let hwif = Rc::new(RefCell::new(HwInterface { let audio = Rc::new(RefCell::new(AudioDevice::default()));
key_state: rustboyadvance_core::keypad::KEYINPUT_ALL_RELEASED, let gba = GameBoyAdvance::new(bios.into_boxed_slice(), gamepak, audio.clone());
audio_ring_buffer: Default::default(),
}));
let gba = GameBoyAdvance::new(
bios.into_boxed_slice(),
gamepak,
hwif.clone(),
hwif.clone(),
);
self.hwif = Some(hwif); self.audio = Some(audio);
self.gba = Some(gba); self.gba = Some(gba);
self.game_data = Some(game_data); self.game_data = Some(game_data);
LoadGameResult::Success(av_info) LoadGameResult::Success(av_info)
@ -136,17 +121,19 @@ impl libretro_backend::Core for RustBoyAdvanceCore {
fn on_run(&mut self, handle: &mut RuntimeHandle) { fn on_run(&mut self, handle: &mut RuntimeHandle) {
let joypad_port = 0; 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 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 { macro_rules! update_controllers {
( $( $button:ident ),+ ) => ( ( $( $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); 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 // upload sound samples
{ {
let mut audio_samples = [0; 4096 * 2]; let mut audio_samples = [0; 4096 * 2];
let mut hwif = hwif.borrow_mut(); let mut audio = audio.borrow_mut();
let consumer = hwif.audio_ring_buffer.consumer(); let consumer = audio.audio_ring_buffer.consumer();
let count = consumer.pop_slice(&mut audio_samples); let count = consumer.pop_slice(&mut audio_samples);
handle.upload_audio_frame(&audio_samples[..count]); handle.upload_audio_frame(&audio_samples[..count]);

View file

@ -1,50 +1,38 @@
use rustboyadvance_core::GameBoyAdvance;
use sdl2::controller::Axis; use sdl2::controller::Axis;
use sdl2::controller::Button; use sdl2::controller::Button;
use sdl2::keyboard::Scancode; use sdl2::keyboard::Scancode;
use rustboyadvance_core::keypad as gba_keypad; use rustboyadvance_core::keypad as gba_keypad;
use rustboyadvance_core::InputInterface;
use bit; use bit;
use bit::BitIndex; use bit::BitIndex;
pub struct Sdl2Input { pub fn on_keyboard_key_down(gba: &mut GameBoyAdvance, scancode: Scancode) {
keyinput: u16, if let Some(key) = scancode_to_keypad(scancode) {
axis_keyinput: u16, gba.get_key_state_mut().set_bit(key as usize, false);
}
impl InputInterface for Sdl2Input {
fn poll(&mut self) -> u16 {
!(!self.keyinput | !self.axis_keyinput)
} }
} }
impl Sdl2Input { pub fn on_keyboard_key_up(gba: &mut GameBoyAdvance, scancode: Scancode) {
pub fn on_keyboard_key_down(&mut self, scancode: Scancode) {
if let Some(key) = scancode_to_keypad(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, true);
}
} }
}
pub fn on_keyboard_key_up(&mut self, scancode: Scancode) { pub fn on_controller_button_down(gba: &mut GameBoyAdvance, button: Button) {
if let Some(key) = scancode_to_keypad(scancode) {
self.keyinput.set_bit(key as usize, true);
}
}
pub fn on_controller_button_down(&mut self, button: Button) {
if let Some(key) = controller_button_to_keypad(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) { 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; use gba_keypad::Keys as GbaKeys;
let keys = match axis { let keys = match axis {
Axis::LeftX => (GbaKeys::Left, GbaKeys::Right), 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 // Axis motion is an absolute value in the range
// [-32768, 32767]. Let's simulate a very rough dead // [-32768, 32767]. Let's simulate a very rough dead
// zone to ignore spurious events. // zone to ignore spurious events.
let dead_zone = 10_000; let dead_zone = 10_000;
if val > dead_zone || val < -dead_zone { if val > dead_zone || val < -dead_zone {
let key = if val < 0 { keys.0 } else { keys.1 }; 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 { } else {
self.axis_keyinput.set_bit(keys.0 as usize, true); key_state.set_bit(keys.0 as usize, true);
self.axis_keyinput.set_bit(keys.1 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, _ => 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; mod video;
use audio::{create_audio_player, create_dummy_player}; use audio::{create_audio_player, create_dummy_player};
use input::create_input; use input;
use video::{create_video_interface, SCREEN_HEIGHT, SCREEN_WIDTH}; use video::{create_video_interface, SCREEN_HEIGHT, SCREEN_WIDTH};
use rustboyadvance_core::cartridge::BackupType; use rustboyadvance_core::cartridge::BackupType;
@ -253,7 +253,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.. ..
} => match scancode { } => match scancode {
Scancode::Space => frame_limiter = false, 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 { Event::KeyUp {
scancode: Some(scancode), scancode: Some(scancode),
@ -291,17 +291,17 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
} }
Scancode::Space => frame_limiter = true, 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 { Event::ControllerButtonDown { button, .. } => match button {
Button::RightStick => frame_limiter = !frame_limiter, 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, .. } => { Event::ControllerButtonUp { button, .. } => {
input.borrow_mut().on_controller_button_up(button); input::on_controller_button_up(&mut gba, button);
} }
Event::ControllerAxisMotion { axis, value, .. } => { Event::ControllerAxisMotion { axis, value, .. } => {
input.borrow_mut().on_axis_motion(axis, value); input::on_axis_motion(&mut gba, axis, value);
} }
Event::ControllerDeviceRemoved { which, .. } => { Event::ControllerDeviceRemoved { which, .. } => {
let removed = if let Some(active_controller) = &active_controller { let removed = if let Some(active_controller) = &active_controller {
@ -339,7 +339,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
gamepak, gamepak,
video.clone(), video.clone(),
audio.clone(), audio.clone(),
input.clone(),
); );
gba.skip_bios(); gba.skip_bios();
} }

View file

@ -23,7 +23,6 @@ pub struct Emulator {
struct Interface { struct Interface {
frame: Vec<u8>, frame: Vec<u8>,
keyinput: u16,
sample_rate: i32, sample_rate: i32,
audio_ctx: AudioContext, audio_ctx: AudioContext,
audio_ring_buffer: AudioRingBuffer, audio_ring_buffer: AudioRingBuffer,
@ -39,7 +38,6 @@ impl Interface {
fn new(audio_ctx: AudioContext) -> Result<Interface, JsValue> { fn new(audio_ctx: AudioContext) -> Result<Interface, JsValue> {
Ok(Interface { Ok(Interface {
frame: vec![0; 240 * 160 * 4], frame: vec![0; 240 * 160 * 4],
keyinput: gba_keypad::KEYINPUT_ALL_RELEASED,
sample_rate: audio_ctx.sample_rate() as i32, sample_rate: audio_ctx.sample_rate() as i32,
audio_ctx: audio_ctx, audio_ctx: audio_ctx,
audio_ring_buffer: Default::default(), 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] #[wasm_bindgen]
impl Emulator { impl Emulator {
#[wasm_bindgen(constructor)] #[wasm_bindgen(constructor)]
@ -141,17 +133,15 @@ impl Emulator {
pub fn key_down(&mut self, event_key: &str) { pub fn key_down(&mut self, event_key: &str) {
debug!("Key down: {}", event_key); debug!("Key down: {}", event_key);
let mut interface = self.interface.borrow_mut();
if let Some(key) = Emulator::map_key(event_key) { 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) { pub fn key_up(&mut self, event_key: &str) {
debug!("Key up: {}", event_key); debug!("Key up: {}", event_key);
let mut interface = self.interface.borrow_mut();
if let Some(key) = Emulator::map_key(event_key) { 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);
} }
} }