#[derive(Clone, Copy, Debug, Default)]
pub struct PadState {
pub up: bool,
pub right: bool,
pub down: bool,
pub left: bool,
pub select: bool,
pub run: bool,
pub button_i: bool,
pub button_ii: bool,
}
#[derive(Clone, Copy, Debug, Default)]
pub struct IoPort {
select: bool,
clear: bool,
pad: PadState,
japanese: bool,
cd_attached: bool,
}
impl IoPort {
#[must_use]
pub const fn new() -> Self {
Self {
select: false,
clear: false,
pad: PadState {
up: false,
right: false,
down: false,
left: false,
select: false,
run: false,
button_i: false,
button_ii: false,
},
japanese: false,
cd_attached: false,
}
}
pub const fn set_japanese(&mut self, japanese: bool) {
self.japanese = japanese;
}
pub const fn set_cd_attached(&mut self, attached: bool) {
self.cd_attached = attached;
}
pub const fn set_pad(&mut self, pad: PadState) {
self.pad = pad;
}
pub const fn write(&mut self, value: u8) {
self.select = value & 0x01 != 0;
self.clear = value & 0x02 != 0;
}
#[must_use]
pub fn read(&self) -> u8 {
let mut high = 0x30; if !self.cd_attached {
high |= 0x80; }
if self.japanese {
high |= 0x40; }
if self.clear {
return high;
}
let nibble = if self.select {
(u8::from(self.pad.left) << 3)
| (u8::from(self.pad.down) << 2)
| (u8::from(self.pad.right) << 1)
| u8::from(self.pad.up)
} else {
(u8::from(self.pad.run) << 3)
| (u8::from(self.pad.select) << 2)
| (u8::from(self.pad.button_ii) << 1)
| u8::from(self.pad.button_i)
};
high | (!nibble & 0x0F)
}
}