Newer
Older
//! Gamepad related functions and structures.
use crate::{mmu::BusComponent, warnln};
#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;
#[cfg_attr(feature = "wasm", wasm_bindgen)]
pub enum PadKey {
Up,
Down,
Left,
Right,
Start,
Select,
A,
B,
}
impl PadKey {
pub fn from_u8(value: u8) -> Self {
match value {
1 => PadKey::Up,
2 => PadKey::Down,
3 => PadKey::Left,
4 => PadKey::Right,
5 => PadKey::Start,
6 => PadKey::Select,
7 => PadKey::A,
8 => PadKey::B,
_ => panic!("Invalid pad key value: {}", value),
}
}
}
impl From<u8> for PadKey {
fn from(value: u8) -> Self {
Self::from_u8(value)
}
}
pub struct Pad {
down: bool,
up: bool,
left: bool,
right: bool,
start: bool,
select: bool,
b: bool,
a: bool,
selection: PadSelection,
impl Pad {
pub fn new() -> Self {
Self {
down: false,
up: false,
left: false,
right: false,
start: false,
select: false,
b: false,
a: false,
match addr {
// 0xFF00 — P1/JOYP: Joypad
0xff00 => {
PadSelection::Action =>
{
#[allow(clippy::bool_to_int_with_if)]
| if self.b { 0x00 } else { 0x02 }
| if self.select { 0x00 } else { 0x04 }
PadSelection::Direction =>
{
#[allow(clippy::bool_to_int_with_if)]
| if self.left { 0x00 } else { 0x02 }
| if self.up { 0x00 } else { 0x04 }
value |= match self.selection {
PadSelection::Action => 0x10,
PadSelection::Direction => 0x20,
PadSelection::None => 0x30,
_ => {
warnln!("Reading from unknown Pad location 0x{:04x}", addr);
}
}
pub fn write(&mut self, addr: u16, value: u8) {
match addr {
// 0xFF00 — P1/JOYP: Joypad
0xff00 => {
self.selection = match value & 0x30 {
0x10 => PadSelection::Action,
0x20 => PadSelection::Direction,
0x30 => PadSelection::None,
_ => PadSelection::None,
};
_ => warnln!("Writing to unknown Pad location 0x{:04x}", addr),
pub fn key_press(&mut self, key: PadKey) {
match key {
PadKey::Up => self.up = true,
PadKey::Down => self.down = true,
PadKey::Left => self.left = true,
PadKey::Right => self.right = true,
PadKey::Start => self.start = true,
PadKey::Select => self.select = true,
PadKey::A => self.a = true,
PadKey::B => self.b = true,
}
// signals that a JoyPad interrupt is pending to be
// handled as a key press has been performed
}
pub fn key_lift(&mut self, key: PadKey) {
match key {
PadKey::Up => self.up = false,
PadKey::Down => self.down = false,
PadKey::Left => self.left = false,
PadKey::Right => self.right = false,
PadKey::Start => self.start = false,
PadKey::Select => self.select = false,
PadKey::A => self.a = false,
PadKey::B => self.b = false,
}
}
pub fn int_pad(&self) -> bool {
self.int_pad
}
pub fn set_int_pad(&mut self, value: bool) {
self.int_pad = value;
}
pub fn ack_pad(&mut self) {
self.set_int_pad(false);
}
impl BusComponent for Pad {
self.read(addr)
}
fn write(&mut self, addr: u16, value: u8) {
self.write(addr, value);
}
}
impl Default for Pad {
fn default() -> Self {
Self::new()
}
}