feat: implement Joypad register
This commit is contained in:
parent
fc303b6265
commit
36e572b783
|
@ -2,6 +2,7 @@ use super::cartridge::Cartridge;
|
||||||
use super::high_ram::HighRam;
|
use super::high_ram::HighRam;
|
||||||
use super::instruction::Cycles;
|
use super::instruction::Cycles;
|
||||||
use super::interrupt::{Interrupt, InterruptFlag};
|
use super::interrupt::{Interrupt, InterruptFlag};
|
||||||
|
use super::joypad::Joypad;
|
||||||
use super::ppu::Ppu;
|
use super::ppu::Ppu;
|
||||||
use super::serial::Serial;
|
use super::serial::Serial;
|
||||||
use super::sound::Sound;
|
use super::sound::Sound;
|
||||||
|
@ -23,6 +24,7 @@ pub struct Bus {
|
||||||
sound: Sound,
|
sound: Sound,
|
||||||
hram: HighRam,
|
hram: HighRam,
|
||||||
serial: Serial,
|
serial: Serial,
|
||||||
|
joypad: Joypad,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Bus {
|
impl Default for Bus {
|
||||||
|
@ -38,6 +40,7 @@ impl Default for Bus {
|
||||||
sound: Default::default(),
|
sound: Default::default(),
|
||||||
hram: Default::default(),
|
hram: Default::default(),
|
||||||
serial: Default::default(),
|
serial: Default::default(),
|
||||||
|
joypad: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,6 +120,7 @@ impl Bus {
|
||||||
0xFF00..=0xFF7F => {
|
0xFF00..=0xFF7F => {
|
||||||
// IO Registers
|
// IO Registers
|
||||||
match addr {
|
match addr {
|
||||||
|
0xFF00 => self.joypad.status.into(),
|
||||||
0xFF01 => self.serial.next,
|
0xFF01 => self.serial.next,
|
||||||
0xFF02 => self.serial.control.into(),
|
0xFF02 => self.serial.control.into(),
|
||||||
0xFF07 => self.timer.control.into(),
|
0xFF07 => self.timer.control.into(),
|
||||||
|
@ -202,6 +206,7 @@ impl Bus {
|
||||||
0xFF00..=0xFF7F => {
|
0xFF00..=0xFF7F => {
|
||||||
// IO Registers
|
// IO Registers
|
||||||
match addr {
|
match addr {
|
||||||
|
0xFF00 => self.joypad.status = byte.into(),
|
||||||
0xFF01 => self.serial.next = byte,
|
0xFF01 => self.serial.next = byte,
|
||||||
0xFF02 => self.serial.control = byte.into(),
|
0xFF02 => self.serial.control = byte.into(),
|
||||||
0xFF07 => self.timer.control = byte.into(),
|
0xFF07 => self.timer.control = byte.into(),
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
use bitfield::bitfield;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct Joypad {
|
||||||
|
pub status: JoypadStatus,
|
||||||
|
pub interrupt: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
bitfield! {
|
||||||
|
pub struct JoypadStatus(u8);
|
||||||
|
impl Debug;
|
||||||
|
pub from into ButtonSelection, action_buttons, select_action_buttons: 5, 5;
|
||||||
|
pub from into ButtonSelection, direction_buttons, select_direction_buttons: 4, 4;
|
||||||
|
_down, _set_down: 3;
|
||||||
|
_up, _set_up: 2;
|
||||||
|
_left, _set_left: 1;
|
||||||
|
_right, _set_right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Copy for JoypadStatus {}
|
||||||
|
impl Clone for JoypadStatus {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for JoypadStatus {
|
||||||
|
fn default() -> Self {
|
||||||
|
// Selected Direction Buttons
|
||||||
|
// All Buttons are not pressed
|
||||||
|
Self(0b00011111)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for JoypadStatus {
|
||||||
|
fn from(byte: u8) -> Self {
|
||||||
|
Self(byte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<JoypadStatus> for u8 {
|
||||||
|
fn from(joypad: JoypadStatus) -> Self {
|
||||||
|
joypad.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JoypadStatus {
|
||||||
|
pub fn start(&self) -> bool {
|
||||||
|
self.down()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_start(&mut self, pressed: bool) -> Option<JoypadAction> {
|
||||||
|
self.set_down(pressed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn select(&self) -> bool {
|
||||||
|
self.up()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_select(&mut self, pressed: bool) -> Option<JoypadAction> {
|
||||||
|
self.set_up(pressed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn b(&self) -> bool {
|
||||||
|
self.left()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_b(&mut self, pressed: bool) -> Option<JoypadAction> {
|
||||||
|
self.set_left(pressed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn a(&self) -> bool {
|
||||||
|
self.right()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_a(&mut self, pressed: bool) -> Option<JoypadAction> {
|
||||||
|
self.set_right(pressed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn down(&self) -> bool {
|
||||||
|
self._down()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_down(&mut self, pressed: bool) -> Option<JoypadAction> {
|
||||||
|
self._set_down(pressed);
|
||||||
|
|
||||||
|
if !self._down() && pressed {
|
||||||
|
Some(JoypadAction::TriggerInterrupt)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn up(&self) -> bool {
|
||||||
|
self._up()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_up(&mut self, pressed: bool) -> Option<JoypadAction> {
|
||||||
|
self._set_up(pressed);
|
||||||
|
|
||||||
|
if !self._up() && pressed {
|
||||||
|
Some(JoypadAction::TriggerInterrupt)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn left(&self) -> bool {
|
||||||
|
self._left()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_left(&mut self, pressed: bool) -> Option<JoypadAction> {
|
||||||
|
self._set_left(pressed);
|
||||||
|
|
||||||
|
if !self._left() && pressed {
|
||||||
|
Some(JoypadAction::TriggerInterrupt)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn right(&self) -> bool {
|
||||||
|
self._right()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_right(&mut self, pressed: bool) -> Option<JoypadAction> {
|
||||||
|
self._set_right(pressed);
|
||||||
|
|
||||||
|
if !self._right() && pressed {
|
||||||
|
Some(JoypadAction::TriggerInterrupt)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum JoypadAction {
|
||||||
|
TriggerInterrupt,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum ButtonSelection {
|
||||||
|
Selected = 0,
|
||||||
|
NotSelected,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for ButtonSelection {
|
||||||
|
fn from(byte: u8) -> Self {
|
||||||
|
match byte {
|
||||||
|
0b00 => Self::Selected,
|
||||||
|
0b01 => Self::NotSelected,
|
||||||
|
_ => unreachable!("{:#04X} is not a valid value for ButtonSelection", byte),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ButtonSelection> for u8 {
|
||||||
|
fn from(selection: ButtonSelection) -> Self {
|
||||||
|
selection as Self
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ mod cpu;
|
||||||
mod high_ram;
|
mod high_ram;
|
||||||
mod instruction;
|
mod instruction;
|
||||||
mod interrupt;
|
mod interrupt;
|
||||||
|
mod joypad;
|
||||||
mod ppu;
|
mod ppu;
|
||||||
mod serial;
|
mod serial;
|
||||||
mod sound;
|
mod sound;
|
||||||
|
|
Loading…
Reference in New Issue