use crate::sys::kernel;
use core::marker::PhantomData;
use core::mem::size_of;
use core::mem::MaybeUninit;
use core::ptr::read_volatile;
const BUFFER_SIZE: usize = 68 / size_of::<u32>();
pub struct Gamepad<'a> {
buf1: *mut u16,
buf2: *mut u16,
_buf: PhantomData<&'a mut [u32; BUFFER_SIZE]>,
}
pub struct Buttons {
value: u16,
iter_idx: u16,
}
pub struct JoyStick(u16);
#[allow(missing_docs)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Button {
Select = 0,
L3,
R3,
Start,
Up,
Right,
Down,
Left,
L2,
R2,
L1,
R1,
Triangle,
Circle,
Cross,
Square,
}
impl Button {
fn from_bit(n: u16) -> Option<Self> {
match n {
0 => Some(Button::Select),
1 => Some(Button::L3),
2 => Some(Button::R3),
3 => Some(Button::Start),
4 => Some(Button::Up),
5 => Some(Button::Right),
6 => Some(Button::Down),
7 => Some(Button::Left),
8 => Some(Button::L2),
9 => Some(Button::R2),
10 => Some(Button::L1),
11 => Some(Button::R1),
12 => Some(Button::Triangle),
13 => Some(Button::Circle),
14 => Some(Button::Cross),
15 => Some(Button::Square),
_ => None,
}
}
}
#[allow(missing_docs)]
pub mod buttons {
use super::Button;
pub const SELECT: Button = Button::Select;
pub const L3: Button = Button::L3;
pub const R3: Button = Button::R3;
pub const START: Button = Button::Start;
pub const UP: Button = Button::Up;
pub const RIGHT: Button = Button::Right;
pub const DOWN: Button = Button::Down;
pub const LEFT: Button = Button::Left;
pub const L2: Button = Button::L2;
pub const R2: Button = Button::R2;
pub const L1: Button = Button::L1;
pub const R1: Button = Button::R1;
pub const TRIANGLE: Button = Button::Triangle;
pub const CIRCLE: Button = Button::Circle;
pub const CROSS: Button = Button::Cross;
pub const SQUARE: Button = Button::Square;
}
impl<'a> Gamepad<'a> {
pub fn new() -> Self {
static mut BUFFER1: MaybeUninit<[u32; BUFFER_SIZE]> = MaybeUninit::uninit();
static mut BUFFER2: MaybeUninit<[u32; BUFFER_SIZE]> = MaybeUninit::uninit();
unsafe { Self::new_with_buffer(&mut BUFFER1, &mut BUFFER2) }
}
pub unsafe fn new_with_buffer(
buf1: &'a mut MaybeUninit<[u32; BUFFER_SIZE]>,
buf2: &'a mut MaybeUninit<[u32; BUFFER_SIZE]>,
) -> Self {
let buf1 = buf1.as_mut_ptr().cast::<u16>();
let buf2 = buf2.as_mut_ptr().cast::<u16>();
kernel::psx_init_pad(buf1 as *mut u8, 0x22, buf2 as *mut u8, 0x22);
buf1.cast::<u8>().write_volatile(0xFF);
buf1.add(1).write_volatile(0xFFFF);
buf1.cast::<u32>().add(1).write_volatile(0x8080_8080);
kernel::psx_start_pad();
kernel::psx_change_clear_pad(1);
Self {
buf1,
buf2,
_buf: PhantomData,
}
}
pub fn poll_p1(&mut self) -> Buttons {
Buttons {
value: unsafe { read_volatile(self.buf1.add(1)) },
iter_idx: 0,
}
}
pub fn poll_rstick_p1(&mut self) -> JoyStick {
unsafe { JoyStick(read_volatile(self.buf1.add(2))) }
}
pub fn poll_lstick_p1(&mut self) -> JoyStick {
unsafe { JoyStick(read_volatile(self.buf1.add(3))) }
}
pub fn poll_p2(&mut self) -> Buttons {
Buttons {
value: unsafe { read_volatile(self.buf2.add(1)) },
iter_idx: 0,
}
}
pub fn poll_rstick_p2(&mut self) -> JoyStick {
unsafe { JoyStick(read_volatile(self.buf2.add(2))) }
}
pub fn poll_lstick_p2(&mut self) -> JoyStick {
unsafe { JoyStick(read_volatile(self.buf2.add(3))) }
}
}
impl<'a> Drop for Gamepad<'a> {
fn drop(&mut self) {
unsafe {
kernel::psx_stop_pad();
}
}
}
impl Iterator for Buttons {
type Item = Button;
fn next(&mut self) -> Option<Self::Item> {
if self.iter_idx == 16 {
return None
}
let this_bit = self.iter_idx;
let bit_value = (self.value >> (this_bit as u16)) & 1;
self.iter_idx += 1;
if bit_value == 0 {
Button::from_bit(this_bit)
} else {
self.next()
}
}
}
impl Buttons {
pub fn pressed(&self, button: Button) -> bool {
let bit = (self.value >> (button as u16)) & 1;
bit == 0
}
pub fn released(&self, button: Button) -> bool {
let bit = (self.value >> (button as u16)) & 1;
bit != 0
}
}
impl JoyStick {
pub fn horizontal(&self) -> i8 {
(self.0 as u8).wrapping_sub(0x80) as i8
}
pub fn vertical(&self) -> i8 {
((self.0 >> 8) as u8).wrapping_sub(0x80) as i8
}
}