From e693ad8a3c3674cd1ca78846dbb7d802bfd2a927 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Sun, 3 Jan 2021 01:21:19 -0600 Subject: [PATCH] feat: create timer struct and stub 0xff07 --- src/bus.rs | 13 ++++++++-- src/lib.rs | 1 + src/timer.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/timer.rs diff --git a/src/bus.rs b/src/bus.rs index 8e84fd4..ffba980 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -1,5 +1,6 @@ use super::cartridge::Cartridge; use super::ppu::PPU; +use super::timer::Timer; use super::work_ram::{VariableWorkRAM, WorkRAM}; #[derive(Debug, Clone)] pub struct Bus { @@ -8,6 +9,7 @@ pub struct Bus { ppu: PPU, wram: WorkRAM, vwram: VariableWorkRAM, + timer: Timer, } impl Default for Bus { @@ -18,6 +20,7 @@ impl Default for Bus { ppu: Default::default(), wram: Default::default(), vwram: Default::default(), + timer: Default::default(), } } } @@ -86,7 +89,10 @@ impl Bus { 0xFEA0..=0xFEFF => unimplemented!("{:#06X} is not allowed to be used", addr), 0xFF00..=0xFF7F => { // IO Registers - unimplemented!("Unable to read {:#06X} in I/O Registers", addr); + match addr { + 0xFF07 => self.timer.control.into(), + _ => unimplemented!("Unable to read {:#06X} in I/O Registers", addr), + } } 0xFF80..=0xFFFE => { // High RAM @@ -139,7 +145,10 @@ impl Bus { 0xFEA0..=0xFEFF => unimplemented!("{:#06X} is not allowed to be used", addr), 0xFF00..=0xFF7F => { // IO Registers - unimplemented!("Unable to write to {:#06X} in I/O Registers", addr); + match addr { + 0xFF07 => self.timer.control = byte.into(), + _ => unimplemented!("Unable to write to {:#06X} in I/O Registers", addr), + }; } 0xFF80..=0xFFFE => { // High RAM diff --git a/src/lib.rs b/src/lib.rs index 5d4215f..266f13d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,4 +3,5 @@ mod cartridge; pub mod cpu; mod instruction; mod ppu; +mod timer; mod work_ram; diff --git a/src/timer.rs b/src/timer.rs new file mode 100644 index 0000000..a1f1fd9 --- /dev/null +++ b/src/timer.rs @@ -0,0 +1,68 @@ +#[derive(Debug, Clone, Copy)] +pub struct Timer { + pub control: TimerControl, +} + +impl Default for Timer { + fn default() -> Self { + Self { + control: 0x00.into(), + } + } +} + +#[derive(Debug, Clone, Copy)] +enum TimerSpeed { + Freq4096Hz, + Freq262144Hz, + Freq65536Hz, + Freq16384Hz, +} + +impl From for TimerSpeed { + fn from(byte: u8) -> Self { + match byte { + 0x00 => Self::Freq4096Hz, + 0x01 => Self::Freq262144Hz, + 0x10 => Self::Freq65536Hz, + 0x11 => Self::Freq16384Hz, + _ => unreachable!(), + } + } +} + +impl From for u8 { + fn from(speed: TimerSpeed) -> Self { + match speed { + TimerSpeed::Freq4096Hz => 0x00, + TimerSpeed::Freq262144Hz => 0x01, + TimerSpeed::Freq65536Hz => 0x10, + TimerSpeed::Freq16384Hz => 0x11, + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct TimerControl { + enabled: bool, + speed: TimerSpeed, +} + +impl From for TimerControl { + fn from(byte: u8) -> Self { + let byte = byte & 0x07; // Clear everything but last 3 bits + + Self { + enabled: (byte >> 2) == 0x01, + speed: (byte & 0x03).into(), // Clear everything but last 2 bits + } + } +} + +impl From for u8 { + fn from(control: TimerControl) -> Self { + let byte: u8 = control.speed.into(); // Get bit 1 and 0. + + (byte & !(1u8 << 2)) | ((control.enabled as u8) << 2) // specifically manibulate bit 2 + } +}