diff --git a/src/apu/dmc.rs b/src/apu/dmc.rs index 504e182..57e1b75 100644 --- a/src/apu/dmc.rs +++ b/src/apu/dmc.rs @@ -1,6 +1,14 @@ -impl super::DMC { +pub struct DMC { + pub sample: u16, + pub enabled: bool, + pub interrupt: bool, + pub length_counter: usize, + pub bytes_remaining: usize, +} + +impl DMC { pub fn new() -> Self { - super::DMC { + DMC { sample: 0, enabled: false, bytes_remaining: 0, diff --git a/src/apu/mod.rs b/src/apu/mod.rs index be1e492..9bfb431 100644 --- a/src/apu/mod.rs +++ b/src/apu/mod.rs @@ -3,6 +3,11 @@ mod square; mod triangle; mod dmc; +use noise::Noise; +use square::Square; +use triangle::Triangle; +use dmc::DMC; + // APU clock ticks every other CPU cycle. // Frame counter only ticks every 3728.5 APU ticks, and in audio frames of 4 or 5. // Length counter controls note durations. @@ -33,48 +38,6 @@ pub struct Apu { frame_interrupt: bool, } -struct Square { - sample: u16, - duty_cycle: u8, - 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) - timer: usize, - length_counter: usize, - envelope: usize, - sweep: usize, - enabled: bool, -} - -// $4008 Hlll.llll Triangle channel length counter halt and linear counter load (write) -// bit 7 H--- ---- Halt length counter (this bit is also the linear counter's control flag) -struct Triangle { - sample: u16, - timer: usize, - length_counter: usize, // (this bit is also the linear counter's control flag) - linear_counter: usize, - enabled: bool, -} - -// $400E M---.PPPP Mode and period (write) -// bit 7 M--- ---- Mode flag -struct Noise { - sample: u16, - timer: usize, - length_counter: usize, - envelope: usize, - linear_feedback_sr: u16, - mode: bool, // also called loop noise, bit 7 of $400E - enabled: bool, -} - -struct DMC { - sample: u16, - enabled: bool, - interrupt: bool, - length_counter: usize, - bytes_remaining: usize, -} - struct Envelope { start_flag: bool, divider: usize, diff --git a/src/apu/noise.rs b/src/apu/noise.rs index bc00cfa..a7a3870 100644 --- a/src/apu/noise.rs +++ b/src/apu/noise.rs @@ -1,6 +1,19 @@ -impl super::Noise { + +// $400E M---.PPPP Mode and period (write) +// bit 7 M--- ---- Mode flag +pub struct Noise { + pub sample: u16, + timer: usize, + pub length_counter: usize, + envelope: usize, + linear_feedback_sr: u16, + mode: bool, // also called loop noise, bit 7 of $400E + pub enabled: bool, +} + +impl Noise { pub fn new() -> Self { - super::Noise { + Noise { timer: 0, length_counter: 0, envelope: 0, diff --git a/src/apu/square.rs b/src/apu/square.rs index 40c8dda..699f5fc 100644 --- a/src/apu/square.rs +++ b/src/apu/square.rs @@ -1,7 +1,28 @@ -impl super::Square { +const duty_cycle_sequences: [[u8; 8]; 4] = [ + [0, 1, 0, 0, 0, 0, 0, 0], + [0, 1, 1, 0, 0, 0, 0, 0], + [0, 1, 1, 1, 1, 0, 0, 0], + [1, 0, 0, 1, 1, 1, 1, 1], +]; + +pub struct Square { + pub sample: u16, + duty_cycle: [u8; 8], + duty_counter: u8, + 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) + timer: usize, + pub length_counter: usize, + envelope: usize, + sweep: usize, + pub enabled: bool, +} + +impl Square { pub fn new() -> Self { - super::Square { - duty_cycle: 0, + Square { + duty_cycle: duty_cycle_sequences[0], + duty_counter: 0, length_counter_halt: false, constant_volume_flag: false, timer: 0, @@ -18,8 +39,10 @@ impl super::Square { } pub fn duty(&mut self, value: u8) { - self.duty_cycle = value >> 6; - // self.length_counter_halt = + 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; + } pub fn sweep(&mut self, value: u8) { diff --git a/src/apu/triangle.rs b/src/apu/triangle.rs index 5f156a7..a7f050b 100644 --- a/src/apu/triangle.rs +++ b/src/apu/triangle.rs @@ -1,6 +1,17 @@ -impl super::Triangle { + +// $4008 Hlll.llll Triangle channel length counter halt and linear counter load (write) +// bit 7 H--- ---- Halt length counter (this bit is also the linear counter's control flag) +pub struct Triangle { + pub sample: u16, + timer: usize, + pub length_counter: usize, // (this bit is also the linear counter's control flag) + linear_counter: usize, + pub enabled: bool, +} + +impl Triangle { pub fn new() -> Self { - super::Triangle { + Triangle { timer: 0, length_counter: 0, linear_counter: 0,