diff --git a/src/processor/memory.rs b/src/processor/memory.rs index afed77e..542a2c0 100644 --- a/src/processor/memory.rs +++ b/src/processor/memory.rs @@ -186,6 +186,10 @@ impl Memory { self.joypad.update_pressed_keys(keys, gamepads) } + pub fn div_apu_tick(&mut self) { + self.apu.div_apu_tick(); + } + pub(super) fn cpu_ram_init(&mut self) { self.set(0xFF04, 0xAD); self.set(0xFF10, 0x80); diff --git a/src/processor/memory/mmio/apu.rs b/src/processor/memory/mmio/apu.rs index 83a9b57..260267e 100644 --- a/src/processor/memory/mmio/apu.rs +++ b/src/processor/memory/mmio/apu.rs @@ -45,6 +45,7 @@ pub struct Apu { vin: VinEnable, vol_left: u8, vol_right: u8, + div_apu: u8, } impl Default for Apu { @@ -56,11 +57,25 @@ impl Default for Apu { vin: VinEnable::default(), vol_left: 7, vol_right: 7, + div_apu: 0, } } } impl Apu { + pub fn div_apu_tick(&mut self) { + self.div_apu = self.div_apu.wrapping_add(1); + if self.div_apu % 8 == 0 { + // envelope sweep + } + if self.div_apu % 4 == 0 { + // ch1 frequency sweep + } + if self.div_apu % 2 == 0 { + // tick sound length timers + } + } + pub fn get_register(&self, addr: Address) -> u8 { if addr == 0xFF26 || addr == 0xFF11 diff --git a/src/processor/timer.rs b/src/processor/timer.rs index be8444c..4d641eb 100644 --- a/src/processor/timer.rs +++ b/src/processor/timer.rs @@ -19,6 +19,10 @@ impl Timers { } } +// this will need to change when cgb mode is implemented +// as it uses bit 5 in double speed mode +const AUDIO_BIT: u8 = 4; + impl Cpu { pub(super) fn increment_timers(&mut self, machine_cycles: u8) { let clock_cycles = (machine_cycles as usize) * 4; @@ -26,10 +30,25 @@ impl Cpu { self.advance_gpu_clock(clock_cycles); self.timers.div_counter += clock_cycles; - let div_diff = (self.timers.div_counter / 256) as u8; + let mut div_diff = (self.timers.div_counter / 256) as u8; + let mut last_div = self.memory.get(0xFF04); + let mut new_div = None; + while div_diff > 0 { + let div = last_div.wrapping_add(1); + + if (div & (1 << AUDIO_BIT)) < (last_div & (1 << AUDIO_BIT)) { + // trigger DIV-APU + self.memory.div_apu_tick(); + } + + new_div = Some(div); + last_div = div; + div_diff -= 1; + } self.timers.div_counter %= 256; - self.memory - .set(0xFF04, self.memory.get(0xFF04).wrapping_add(div_diff)); + if let Some(div) = new_div { + self.memory.set(0xFF04, div) + }; let (timer_enabled, timer_rate) = self.timer_scale(); if timer_enabled {