use crate::nes::input::Button;
use crate::nes::input::arkanoid_controller::ArkanoidState;
use crate::nes::input::nes_joypad::JoypadState;
use crate::nes::input::power_pad::PowerPadState;
use crate::nes::input::snes_adapter::SnesAdapterState;
use crate::nes::input::zapper::ZapperState;
#[derive(Debug, Clone)]
pub enum ControllerState {
Joypad(JoypadState),
SnesAdapter(SnesAdapterState),
Paddle(ArkanoidState),
Zapper(ZapperState),
PowerPad(PowerPadState),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ControllerType {
Joypad,
SnesAdapter,
SnesController,
SnesMouse,
Arkanoid,
Zapper,
PowerPad,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SnesButton {
B,
Y,
Select,
Start,
Up,
Down,
Left,
Right,
A,
X,
L,
R,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PowerPadButton {
One = 0,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Ten,
Eleven,
Twelve,
}
impl ControllerType {
pub fn display_label(self) -> &'static str {
match self {
Self::Joypad => "Joypad",
Self::SnesAdapter => "SNES Adapter",
Self::SnesController => "SNES Controller",
Self::SnesMouse => "SNES Mouse",
Self::Arkanoid => "Arkanoid",
Self::Zapper => "Zapper",
Self::PowerPad => "Power Pad",
}
}
pub fn parse(value: &str) -> Option<Self> {
match value.to_lowercase().as_str() {
"joypad" => Some(Self::Joypad),
"snes-controller" | "snes_controller" | "snescontroller" => Some(Self::SnesController),
"snes-mouse" | "snes_mouse" | "snesmouse" => Some(Self::SnesMouse),
"arkanoid" | "paddle" => Some(Self::Arkanoid),
"zapper" => Some(Self::Zapper),
"power-pad" | "power_pad" | "powerpad" => Some(Self::PowerPad),
_ => None,
}
}
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ControllerInput {
Gamepad,
Keyboard,
Mouse,
}
pub fn controller_input_type(controller_type: ControllerType) -> ControllerInput {
match controller_type {
ControllerType::Joypad => ControllerInput::Gamepad,
ControllerType::SnesAdapter => ControllerInput::Gamepad,
ControllerType::SnesController => ControllerInput::Gamepad,
ControllerType::SnesMouse => ControllerInput::Mouse,
ControllerType::Arkanoid => ControllerInput::Mouse,
ControllerType::Zapper => ControllerInput::Mouse,
ControllerType::PowerPad => ControllerInput::Keyboard,
}
}
pub trait Controller {
fn write_strobe(&mut self, value: u8);
fn read(&mut self, is_dummy_read: bool) -> u8;
fn capture_state(&self) -> ControllerState;
fn restore_state(&mut self, state: &ControllerState);
fn set_button(&mut self, button: Button, pressed: bool) -> bool;
fn set_snes_button(&mut self, _button: SnesButton, _pressed: bool) -> bool {
false
}
fn set_power_pad_button(&mut self, _button: PowerPadButton, _pressed: bool) -> bool {
false
}
fn set_mouse_x_position(&mut self, position: u8) -> bool;
fn set_mouse_y_position(&mut self, position: u8) -> bool;
fn set_mouse_left_button(&mut self, pressed: bool) -> bool;
fn add_mouse_delta(&mut self, _dx: i16, _dy: i16) -> bool {
false
}
fn set_mouse_right_button(&mut self, _pressed: bool) -> bool {
false
}
fn is_snes_mouse(&self) -> bool {
false
}
fn input_type(&self) -> ControllerInput;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn controller_type_parse_supports_explicit_snes_controller_and_snes_mouse() {
assert_eq!(
ControllerType::parse("snes-controller"),
Some(ControllerType::SnesController)
);
assert_eq!(
ControllerType::parse("snes-mouse"),
Some(ControllerType::SnesMouse)
);
assert_eq!(ControllerType::parse("snes-adapter"), None);
assert_eq!(ControllerType::parse("snes"), None);
}
#[test]
fn controller_type_parse_supports_power_pad_aliases() {
assert_eq!(
ControllerType::parse("power-pad"),
Some(ControllerType::PowerPad)
);
assert_eq!(
ControllerType::parse("power_pad"),
Some(ControllerType::PowerPad)
);
assert_eq!(
ControllerType::parse("powerpad"),
Some(ControllerType::PowerPad)
);
}
#[test]
fn controller_input_type_reports_expected_inputs_for_explicit_snes_types() {
assert_eq!(
controller_input_type(ControllerType::SnesController),
ControllerInput::Gamepad
);
assert_eq!(
controller_input_type(ControllerType::SnesMouse),
ControllerInput::Mouse
);
}
#[test]
fn controller_input_type_reports_keyboard_for_power_pad() {
assert_eq!(
controller_input_type(ControllerType::PowerPad),
ControllerInput::Keyboard
);
}
}