1use crate::interrupts::InterruptRegisters; 2use crate::sm83::InterruptType; 3use bincode::{Decode, Encode}; 4use jgenesis_common::num::GetBit; 5 6#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode)] 7enum ClockSelect { 8 Zero, 9 One, 10 Two, 11 Three, 12} 13 14impl ClockSelect { 15 fn from_byte(byte: u8) -> Self { 16 match byte & 0x3 { 17 0x0 => Self::Zero, 18 0x1 => Self::One, 19 0x2 => Self::Two, 20 0x3 => Self::Three, 21 _ => unreachable!("value & 0x3 is always <= 0x3"), 22 } 23 } 24 25 fn to_bits(self) -> u8 { 26 match self { 27 Self::Zero => 0, 28 Self::One => 1, 29 Self::Two => 2, 30 Self::Three => 3, 31 } 32 } 33 34 fn timer_bit(self) -> u8 { 35 match self { 36 // 4 KHz 37 Self::Zero => 9, 38 // 256 KHz 39 Self::One => 3, 40 // 64 KHz 41 Self::Two => 5, 42 // 16 KHz 43 Self::Three => 7, 44 } 45 } 46} 47 48#[derive(Debug, Clone, Encode, Decode)] 49pub struct GbTimer { 50 timer: u16, 51 enabled: bool, 52 counter: u8, 53 modulo: u8, 54 clock_select: ClockSelect, 55 previous_timer_bit: bool, 56 overflow: bool, 57} 58 59impl GbTimer { 60 pub fn new() -> Self { 61 Self { 62 timer: 0, 63 enabled: false, 64 counter: 0, 65 modulo: 0, 66 clock_select: ClockSelect::Zero, 67 previous_timer_bit: false, 68 overflow: false, 69 } 70 } 71 72 pub fn tick_m_cycle(&mut self, interrupt_registers: &mut InterruptRegisters) { 73 // Full 16-bit timer always ticks, even when the timer is disabled 74 self.timer = self.timer.wrapping_add(4); 75 76 if !self.enabled { 77 return; 78 } 79 80 // Reset counter and flag interrupt if counter increment overflowed on the last M-cycle 81 if self.overflow { 82 self.counter = self.modulo; 83 interrupt_registers.set_flag(InterruptType::Timer); 84 self.overflow = false; 85 86 return; 87 } 88 89 self.check_for_counter_increment(); 90 } 91 92 fn check_for_counter_increment(&mut self) { 93 let counter_bit = self.timer.bit(self.clock_select.timer_bit()); 94 if self.previous_timer_bit && !counter_bit { 95 let (new_counter, overflow) = self.counter.overflowing_add(1); 96 self.counter = new_counter; 97 self.overflow = overflow; 98 } 99 100 self.previous_timer_bit = counter_bit; 101 } 102 103 pub fn write_div(&mut self) { 104 // Writing any value resets the timer to 0 105 self.timer = 0; 106 107 self.check_for_counter_increment(); 108 } 109 110 // DIV: Divider 111 pub fn read_div(&self) -> u8 { 112 // DIV reads out as the highest 8 bits of the internal timer 113 (self.timer >> 8) as u8 114 } 115 116 // TIMA: Timer counter 117 pub fn write_tima(&mut self, value: u8) { 118 self.counter = value; 119 } 120 121 pub fn read_tima(&self) -> u8 { 122 self.counter 123 } 124 125 // TMA: Timer modulo 126 pub fn write_tma(&mut self, value: u8) { 127 self.modulo = value; 128 } 129 130 pub fn read_tma(&self) -> u8 { 131 self.modulo 132 } 133 134 // TAC: Timer control 135 pub fn write_tac(&mut self, value: u8) { 136 self.enabled = value.bit(2); 137 self.clock_select = ClockSelect::from_byte(value); 138 139 self.check_for_counter_increment(); 140 } 141 142 pub fn read_tac(&self) -> u8 { 143 0xF8 | (u8::from(self.enabled) << 2) | self.clock_select.to_bits() 144 } 145}