use bit_field::BitField;
const GPR1: *const u8 = 0x2008 as *const u8;
const GPR2: *const u8 = 0x2009 as *const u8;
#[inline(always)]
fn read_gpr1() -> u8 {
unsafe { core::ptr::read_volatile(GPR1) }
}
#[inline(always)]
fn read_gpr2() -> u8 {
unsafe { core::ptr::read_volatile(GPR2) }
}
#[derive(Debug, Copy, Clone)]
pub enum Buttons {
Start,
A,
B,
C,
Up,
Down,
Left,
Right
}
impl Buttons {
const fn idx(&self) -> usize {
match self {
Buttons::Start => 7,
Buttons::A => 6,
Buttons::B => 4,
Buttons::C => 5,
Buttons::Up => 3,
Buttons::Down => 2,
Buttons::Left => 1,
Buttons::Right => 0,
}
}
}
pub struct GenesisGamepad<const PORT: u8> {
pub buttons: u8,
pub buttons_last: u8,
}
impl<const PORT: u8> GenesisGamepad<PORT> {
pub const fn new() -> Self {
Self {
buttons: 0,
buttons_last: 0,
}
}
}
impl GenesisGamepad<1> {
#[inline(always)]
pub fn read(&mut self) {
let _ = read_gpr2();
let byte0 = read_gpr1();
let byte1 = read_gpr1();
self.buttons_last = self.buttons;
self.buttons = ((!byte0 << 2) & 0b1100_0000) | (!byte1 & 0b0011_1111);
}
}
impl GenesisGamepad<2> {
#[inline(always)]
pub fn read(&mut self) {
let _ = read_gpr1();
let byte0 = read_gpr2();
let byte1 = read_gpr2();
self.buttons_last = self.buttons;
self.buttons = ((!byte0 << 2) & 0b1100_0000) | (!byte1 & 0b0011_1111);
}
}
impl<const PORT: u8> GenesisGamepad<PORT> {
#[inline]
pub fn is_pressed(&self, button: Buttons) -> bool {
self.buttons.get_bit(button.idx())
}
#[inline]
pub fn was_pressed(&self, button: Buttons) -> bool {
self.buttons_last.get_bit(button.idx())
}
#[inline]
pub fn just_pressed(&self, button: Buttons) -> bool {
self.is_pressed(button) && !self.was_pressed(button)
}
#[inline]
pub fn just_released(&self, button: Buttons) -> bool {
!self.is_pressed(button) && self.was_pressed(button)
}
}