This commit is contained in:
Theron 2019-12-17 20:38:15 -06:00
parent 20ded5f56c
commit 2cc8df766e
1 changed files with 30 additions and 11 deletions

View File

@ -1,4 +1,4 @@
const duty_cycle_sequences: [[u8; 8]; 4] = [ const DUTY_CYCLE_SEQUENCES: [[u8; 8]; 4] = [
[0, 1, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 0, 0, 0], [0, 1, 1, 1, 1, 0, 0, 0],
@ -11,20 +11,20 @@ pub struct Square {
duty_counter: u8, duty_counter: u8,
length_counter_halt: bool, // (this bit is also the envelope's loop flag) length_counter_halt: bool, // (this bit is also the envelope's loop flag)
constant_volume_flag: bool, // (0: use volume from envelope; 1: use constant volume) constant_volume_flag: bool, // (0: use volume from envelope; 1: use constant volume)
timer: usize, timer: u16,
pub length_counter: usize, pub length_counter: u8,
envelope: usize, envelope: u8,
sweep: usize, sweep: u8,
pub enabled: bool, pub enabled: bool,
decay_counter: u8, decay_counter: u8,
start: bool, start: bool,
divider: usize, divider: u8,
} }
impl Square { impl Square {
pub fn new() -> Self { pub fn new() -> Self {
Square { Square {
duty_cycle: duty_cycle_sequences[0], duty_cycle: DUTY_CYCLE_SEQUENCES[0],
duty_counter: 0, duty_counter: 0,
length_counter_halt: false, length_counter_halt: false,
constant_volume_flag: false, constant_volume_flag: false,
@ -49,17 +49,36 @@ impl Square {
} }
pub fn clock_envelope(&mut self) { pub fn clock_envelope(&mut self) {
if self.start { // When clocked by the frame counter, one of two actions occurs:
self.envelope -= 1; // if the start flag is clear, the divider is clocked,
self.start = false; if !self.start {
self.clock_divider();
} else { } else {
self.start = false; // otherwise the start flag is cleared,
self.decay_counter = 15; // the decay level counter is loaded with 15,
self.divider = self.envelope; // and the divider's period is immediately reloaded
}
}
fn clock_divider(&mut self) {
// When the divider is clocked while at 0, it is loaded with V and clocks the decay level counter.
if self.divider == 0 {
self.divider = self.envelope;
// Then one of two actions occurs: If the counter is non-zero, it is decremented,
if self.decay_counter != 0 {
self.decay_counter -= 1;
} else if self.length_counter_halt {
// otherwise if the loop flag is set, the decay level counter is loaded with 15.
self.decay_counter = 15;
}
} else {
self.divider -= 1;
} }
} }
// $4000/$4004 // $4000/$4004
pub fn duty(&mut self, value: u8) { pub fn duty(&mut self, value: u8) {
self.duty_cycle = duty_cycle_sequences[(value >> 6) as usize]; self.duty_cycle = DUTY_CYCLE_SEQUENCES[(value >> 6) as usize];
self.length_counter_halt = value & (1<<5) != 0; self.length_counter_halt = value & (1<<5) != 0;
self.constant_volume_flag = value & (1<<4) != 0; self.constant_volume_flag = value & (1<<4) != 0;
if self.constant_volume_flag { if self.constant_volume_flag {