use crate::device::IoHandler;
use crate::hardware::{HardwareHandle, Key};
use crate::ic::Irq;
use crate::mmu::{MemRead, MemWrite, Mmu};
use log::*;
pub struct Joypad {
hw: HardwareHandle,
irq: Irq,
select: u8,
pressed: u8,
}
impl Joypad {
pub fn new(hw: HardwareHandle, irq: Irq) -> Self {
Self {
hw,
irq,
select: 0xff,
pressed: 0x0f,
}
}
pub fn poll(&mut self) {
let pressed = self.check();
for i in 0..4 {
let bit = 1 << i;
if self.pressed & bit != 0 && pressed & bit == 0 {
self.irq.joypad(true);
break;
}
}
self.pressed = pressed;
}
fn check(&self) -> u8 {
let p = |key| self.hw.get().borrow_mut().joypad_pressed(key);
let mut value = 0;
if self.select & 0x10 == 0 {
value |= if p(Key::Right) { 0x00 } else { 0x01 };
value |= if p(Key::Left) { 0x00 } else { 0x02 };
value |= if p(Key::Up) { 0x00 } else { 0x04 };
value |= if p(Key::Down) { 0x00 } else { 0x08 };
} else if self.select & 0x20 == 0 {
value |= if p(Key::A) { 0x00 } else { 0x01 };
value |= if p(Key::B) { 0x00 } else { 0x02 };
value |= if p(Key::Select) { 0x00 } else { 0x04 };
value |= if p(Key::Start) { 0x0 } else { 0x08 };
} else {
value = 0x0f;
}
value
}
}
impl IoHandler for Joypad {
fn on_read(&mut self, _mmu: &Mmu, addr: u16) -> MemRead {
if addr == 0xff00 {
debug!("Joypad read: dir: {:02x}", self.select);
MemRead::Replace(self.check())
} else {
MemRead::PassThrough
}
}
fn on_write(&mut self, _mmu: &Mmu, addr: u16, value: u8) -> MemWrite {
if addr == 0xff00 {
self.select = value & 0xf0;
}
MemWrite::PassThrough
}
}