2021-03-21 02:11:45 +00:00
|
|
|
use bitfield::bitfield;
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, Default)]
|
|
|
|
pub struct Joypad {
|
|
|
|
pub status: JoypadStatus,
|
2021-05-04 04:11:39 +00:00
|
|
|
pub interrupt: bool,
|
2021-03-21 02:21:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Joypad {
|
2021-06-07 00:14:28 +00:00
|
|
|
pub(crate) fn interrupt(&self) -> bool {
|
2021-03-21 02:21:39 +00:00
|
|
|
self.interrupt
|
|
|
|
}
|
|
|
|
|
2021-06-07 00:14:28 +00:00
|
|
|
pub(crate) fn set_interrupt(&mut self, value: bool) {
|
2021-03-21 02:21:39 +00:00
|
|
|
self.interrupt = value;
|
|
|
|
}
|
2021-03-21 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bitfield! {
|
|
|
|
pub struct JoypadStatus(u8);
|
|
|
|
impl Debug;
|
2021-05-04 04:11:39 +00:00
|
|
|
from into RowState, action_row, set_action_row: 5, 5;
|
|
|
|
from into RowState, direction_row, set_direction_row: 4, 4;
|
|
|
|
from into ButtonState, down_start, _set_down_start: 3, 3;
|
|
|
|
from into ButtonState, up_select, _set_up_select: 2, 2;
|
|
|
|
from into ButtonState, left_b, _set_left_b: 1, 1;
|
|
|
|
from into ButtonState, right_a, _set_right_a: 0, 0;
|
|
|
|
}
|
|
|
|
|
2021-05-04 04:37:30 +00:00
|
|
|
impl JoypadStatus {
|
|
|
|
pub(crate) fn update(&mut self, byte: u8) {
|
2021-05-06 00:23:01 +00:00
|
|
|
// Bytes 3 -> 0 are Read Only
|
|
|
|
let mask = 0b00001111;
|
2021-05-04 04:37:30 +00:00
|
|
|
|
2021-05-06 00:23:01 +00:00
|
|
|
let read_only = self.0 & mask;
|
|
|
|
self.0 = (byte & !mask) | read_only;
|
2021-05-04 04:37:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-04 04:11:39 +00:00
|
|
|
impl JoypadStatus {
|
|
|
|
pub fn set_down_start(&mut self, state: ButtonState, int: &mut bool) {
|
|
|
|
if !(*int) {
|
|
|
|
*int = self.down_start() == ButtonState::Released && state == ButtonState::Pressed;
|
|
|
|
}
|
|
|
|
|
|
|
|
self._set_down_start(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_up_select(&mut self, state: ButtonState, int: &mut bool) {
|
|
|
|
if !(*int) {
|
|
|
|
*int = self.up_select() == ButtonState::Released && state == ButtonState::Pressed;
|
|
|
|
}
|
|
|
|
|
|
|
|
self._set_up_select(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_left_b(&mut self, state: ButtonState, int: &mut bool) {
|
|
|
|
if !(*int) {
|
|
|
|
*int = self.left_b() == ButtonState::Released && state == ButtonState::Pressed;
|
|
|
|
}
|
|
|
|
|
|
|
|
self._set_left_b(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_right_a(&mut self, state: ButtonState, int: &mut bool) {
|
|
|
|
if !(*int) {
|
|
|
|
*int = self.right_a() == ButtonState::Released && state == ButtonState::Pressed;
|
|
|
|
}
|
|
|
|
|
|
|
|
self._set_right_a(state);
|
|
|
|
}
|
2021-05-03 08:27:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for JoypadStatus {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(0xFF)
|
|
|
|
}
|
2021-03-21 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Copy for JoypadStatus {}
|
|
|
|
impl Clone for JoypadStatus {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<JoypadStatus> for u8 {
|
2021-05-03 08:27:23 +00:00
|
|
|
fn from(status: JoypadStatus) -> Self {
|
|
|
|
status.0
|
2021-03-21 02:11:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-04 04:11:39 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
|
|
pub enum ButtonState {
|
2021-05-03 08:27:23 +00:00
|
|
|
Pressed = 0,
|
|
|
|
Released = 1,
|
|
|
|
}
|
2021-03-21 02:11:45 +00:00
|
|
|
|
2021-05-04 04:11:39 +00:00
|
|
|
impl From<u8> for ButtonState {
|
2021-05-03 08:27:23 +00:00
|
|
|
fn from(byte: u8) -> Self {
|
2021-05-19 07:52:32 +00:00
|
|
|
match byte & 0b01 {
|
2021-05-03 08:27:23 +00:00
|
|
|
0b00 => Self::Pressed,
|
|
|
|
0b01 => Self::Released,
|
|
|
|
_ => unreachable!("{:#04X} is not a valid value for ButtonStatus", byte),
|
2021-03-21 02:11:45 +00:00
|
|
|
}
|
|
|
|
}
|
2021-05-03 08:27:23 +00:00
|
|
|
}
|
2021-03-21 02:11:45 +00:00
|
|
|
|
2021-05-04 04:11:39 +00:00
|
|
|
impl From<ButtonState> for u8 {
|
|
|
|
fn from(status: ButtonState) -> Self {
|
2021-05-03 08:27:23 +00:00
|
|
|
status as u8
|
2021-03-21 02:11:45 +00:00
|
|
|
}
|
2021-05-03 08:27:23 +00:00
|
|
|
}
|
2021-03-21 02:11:45 +00:00
|
|
|
|
2021-05-04 04:11:39 +00:00
|
|
|
impl From<bool> for ButtonState {
|
2021-05-03 08:27:23 +00:00
|
|
|
fn from(value: bool) -> Self {
|
|
|
|
match value {
|
|
|
|
true => Self::Pressed,
|
|
|
|
false => Self::Released,
|
2021-03-21 02:11:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-04 04:11:39 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
|
|
enum RowState {
|
2021-05-03 08:27:23 +00:00
|
|
|
Selected,
|
|
|
|
Deselected,
|
2021-03-21 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2021-05-04 04:11:39 +00:00
|
|
|
impl From<u8> for RowState {
|
2021-03-21 02:11:45 +00:00
|
|
|
fn from(byte: u8) -> Self {
|
2021-05-19 07:52:32 +00:00
|
|
|
match byte & 0b01 {
|
2021-03-21 02:11:45 +00:00
|
|
|
0b00 => Self::Selected,
|
2021-05-03 08:27:23 +00:00
|
|
|
0b01 => Self::Deselected,
|
|
|
|
_ => unreachable!("{:#04X} is not a valid value for ButtonRowStatus", byte),
|
2021-03-21 02:11:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-04 04:11:39 +00:00
|
|
|
impl From<RowState> for u8 {
|
|
|
|
fn from(status: RowState) -> Self {
|
2021-05-03 08:27:23 +00:00
|
|
|
status as u8
|
2021-03-21 02:11:45 +00:00
|
|
|
}
|
|
|
|
}
|