1use crate::savestate::{SaveStateError, StateReader, StateWriter};
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq)]
4pub enum ControllerButton {
5 A,
6 B,
7 Select,
8 Start,
9 Up,
10 Down,
11 Left,
12 Right,
13}
14
15impl ControllerButton {
16 const fn bit(self) -> u8 {
17 match self {
18 Self::A => 0x01,
19 Self::B => 0x02,
20 Self::Select => 0x04,
21 Self::Start => 0x08,
22 Self::Up => 0x10,
23 Self::Down => 0x20,
24 Self::Left => 0x40,
25 Self::Right => 0x80,
26 }
27 }
28}
29
30#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
31pub struct ControllerState {
32 bits: u8,
33}
34
35impl ControllerState {
36 pub const fn new() -> Self {
37 Self { bits: 0 }
38 }
39
40 pub const fn from_bits(bits: u8) -> Self {
41 Self { bits }
42 }
43
44 pub const fn bits(self) -> u8 {
45 self.bits
46 }
47
48 pub const fn pressed(self, button: ControllerButton) -> bool {
49 (self.bits & button.bit()) != 0
50 }
51
52 pub fn set_pressed(&mut self, button: ControllerButton, pressed: bool) {
53 if pressed {
54 self.bits |= button.bit();
55 } else {
56 self.bits &= !button.bit();
57 }
58 }
59}
60
61#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
62pub(crate) struct Joypad {
63 strobe: bool,
64 state: ControllerState,
65 shift: u8,
66}
67
68impl Joypad {
69 pub(crate) const fn new() -> Self {
70 Self {
71 strobe: false,
72 state: ControllerState::new(),
73 shift: 0,
74 }
75 }
76
77 pub(crate) fn set_state(&mut self, state: ControllerState) {
78 self.state = state;
79 if self.strobe {
80 self.shift = state.bits();
81 }
82 }
83
84 pub(crate) fn write(&mut self, data: u8) {
85 self.strobe = (data & 0x01) != 0;
86 if self.strobe {
87 self.shift = self.state.bits();
88 }
89 }
90
91 pub(crate) fn read(&mut self) -> u8 {
92 if self.strobe {
93 return u8::from(self.state.pressed(ControllerButton::A));
94 }
95
96 let bit = self.shift & 0x01;
97 self.shift = (self.shift >> 1) | 0x80;
98 bit
99 }
100
101 pub(crate) fn save_state(&self, writer: &mut StateWriter) {
102 writer.write_bool(self.strobe);
103 writer.write_u8(self.state.bits());
104 writer.write_u8(self.shift);
105 }
106
107 pub(crate) fn load_state(
108 &mut self,
109 reader: &mut StateReader<'_>,
110 ) -> Result<(), SaveStateError> {
111 self.strobe = reader.read_bool()?;
112 self.state = ControllerState::from_bits(reader.read_u8()?);
113 self.shift = reader.read_u8()?;
114 Ok(())
115 }
116}