#[derive(Default, Debug)] pub struct Timer { tima: u8, // Timer counter, interrupt on overflow tma: u8, tac: u8, // 00 = 4096 Hz [10240 ticks], 01 = 262144 Hz [160 ticks], 10 = 65536 Hz [640], 11 = 16384 Hz[2560]. Bit 2 0 = stop, 1 = start div: u8, // Incremented at speed of 16384Hz timer_interrupt: bool, tick_counter: u16, div_tick_counter: u16, gb_ticks: u16, } const TIMER_SPEED: [u16; 4] = [64, 1, 4, 16]; const TIMER_ENABLE: u8 = (1 << 2); impl Timer { pub fn new() -> Timer { Timer::default() } fn timer_clock_tick(&mut self) { // The div reg will always tick self.div_tick_counter += 1; if self.div_tick_counter >= TIMER_SPEED[3] { self.div = self.div.wrapping_add(1); self.div_tick_counter -= TIMER_SPEED[3]; } if (self.tac & TIMER_ENABLE) == TIMER_ENABLE { // Is timer enabled? self.tick_counter += 1; let req_ticks = TIMER_SPEED[(self.tac & 3) as usize]; if self.tick_counter >= req_ticks { if self.tima == 0xFF { self.timer_interrupt = true; self.tima = 0; } else { self.tima += 1; } self.tick_counter -= req_ticks; } } } pub fn tick(&mut self, ticks: u16) { // One tick 1/4.194304MHz on regular speed => 16 gb ticks self.gb_ticks += ticks; // If we're in GBC fast mode, we'd require 32 ticks instead of 16 while self.gb_ticks >= 16 { self.timer_clock_tick(); self.gb_ticks -= 16; } } pub fn write_byte(&mut self, addr: u16, val: u8) { match addr { 0xFF04 => self.div = 0, 0xFF05 => self.tima = val, 0xFF06 => self.tma = val, 0xFF07 => self.tac = val, _ => println!("Timer: Write {:02X} to {:04X} unsupported", val, addr), } } pub fn read_byte(&self, addr: u16) -> u8 { match addr { 0xFF04 => self.div, 0xFF05 => self.tima, 0xFF06 => self.tma, 0xFF07 => self.tac, _ => { println!("Timer: Read from {:04X} unsupported", addr); 0 } } } pub fn timer_interrupt(&mut self) -> bool { // Returns whether or not a vblank interrupt should be done // Yes, this is polling, and yes, this sucks.\ if self.timer_interrupt { self.timer_interrupt = false; true } else { false } } }