From 20ded5f56c9ba6839b682e7b2783af6804a95331 Mon Sep 17 00:00:00 2001 From: Theron Spiegl Date: Mon, 16 Dec 2019 23:43:10 -0600 Subject: [PATCH] apu --- src/apu/mod.rs | 4 +++- src/apu/square.rs | 29 ++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/apu/mod.rs b/src/apu/mod.rs index 9bfb431..1cd7e42 100644 --- a/src/apu/mod.rs +++ b/src/apu/mod.rs @@ -21,6 +21,8 @@ use dmc::DMC; // need all samples, it needs one from the stream 44100 time per second. So just an if statement, if time has passed grab a sample. // But then that won't be running during PPU 60Hz sleep... So run audio in its own thread... Except then it won't work on Windows because of SDL... // So just run the console in its own thread and video/audio in the main thread... But that's annoying. +// No. Don't have to be concerned about the audio device, that's solved by the buffer, and the 44100 samples get fed in batches of 4096 from the large buffer, +// when the device needs them, which is accomplished just by calling .resume() before the main loop starts. So a large buffer really should allow for the 60Hz sleep lock. pub struct Apu { square1: Square, @@ -84,6 +86,7 @@ impl Apu { 0x4006 => self.square2.timer_low(value), 0x4007 => self.square2.timer_high(value), 0x4008 => self.triangle.counter(value), + 0x4009 => (), 0x400A => self.triangle.timer_low(value), 0x400B => self.triangle.timer_high(value), 0x400C => self.noise.envelope(value), @@ -204,7 +207,6 @@ impl Apu { if self.dmc.interrupt { val |= 1<<7; } - // Reading this register clears the frame interrupt flag (but not the DMC interrupt flag). self.frame_interrupt = false; diff --git a/src/apu/square.rs b/src/apu/square.rs index 699f5fc..779e504 100644 --- a/src/apu/square.rs +++ b/src/apu/square.rs @@ -16,6 +16,9 @@ pub struct Square { envelope: usize, sweep: usize, pub enabled: bool, + decay_counter: u8, + start: bool, + divider: usize, } impl Square { @@ -31,6 +34,9 @@ impl Square { sweep: 0, sample: 0, enabled: false, + decay_counter: 0, + start: false, + divider: 0, } } @@ -38,21 +44,42 @@ impl Square { } + pub fn clock_frame_counter(&mut self) { + + } + + pub fn clock_envelope(&mut self) { + if self.start { + self.envelope -= 1; + self.start = false; + } else { + + } + } + + // $4000/$4004 pub fn duty(&mut self, value: u8) { self.duty_cycle = duty_cycle_sequences[(value >> 6) as usize]; self.length_counter_halt = value & (1<<5) != 0; self.constant_volume_flag = value & (1<<4) != 0; - + if self.constant_volume_flag { + self.envelope = value & 0b1111; + } else { + self.envelope = self.decay_counter; + } } + // $4001/$4005 pub fn sweep(&mut self, value: u8) { } + // $4002/$4006 pub fn timer_low(&mut self, value: u8) { } + // $4003/$4007 pub fn timer_high(&mut self, value: u8) { }