nesfuzz/src/apu/square.rs

130 lines
3.1 KiB
Rust
Raw Normal View History

2019-12-18 02:38:15 +00:00
const DUTY_CYCLE_SEQUENCES: [[u8; 8]; 4] = [
2019-12-17 04:06:00 +00:00
[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)
2019-12-18 02:38:15 +00:00
timer: u16,
pub length_counter: u8,
envelope: u8,
sweep: u8,
2019-12-17 04:06:00 +00:00
pub enabled: bool,
2019-12-17 05:43:10 +00:00
decay_counter: u8,
start: bool,
2019-12-18 02:38:15 +00:00
divider: u8,
2019-12-17 04:06:00 +00:00
}
impl Square {
2019-11-27 01:11:51 +00:00
pub fn new() -> Self {
2019-12-17 04:06:00 +00:00
Square {
2019-12-18 02:38:15 +00:00
duty_cycle: DUTY_CYCLE_SEQUENCES[0],
2019-12-17 04:06:00 +00:00
duty_counter: 0,
2019-11-27 01:11:51 +00:00
length_counter_halt: false,
constant_volume_flag: false,
timer: 0,
length_counter: 0,
envelope: 0,
sweep: 0,
2019-12-05 02:57:05 +00:00
sample: 0,
2019-12-15 00:15:06 +00:00
enabled: false,
2019-12-17 05:43:10 +00:00
decay_counter: 0,
start: false,
divider: 0,
2019-11-27 01:11:51 +00:00
}
}
2019-12-05 02:57:05 +00:00
pub fn clock(&mut self) {
}
2019-12-17 05:43:10 +00:00
pub fn clock_frame_counter(&mut self) {
}
pub fn clock_envelope(&mut self) {
2019-12-18 02:38:15 +00:00
// When clocked by the frame counter, one of two actions occurs:
// if the start flag is clear, the divider is clocked,
if !self.start {
self.clock_divider();
2019-12-17 05:43:10 +00:00
} else {
2019-12-18 02:38:15 +00:00
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
}
}
2019-12-19 05:35:04 +00:00
pub fn clock_length_counter(&mut self) {
}
2019-12-17 05:43:10 +00:00
2019-12-18 02:38:15 +00:00
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;
2019-12-17 05:43:10 +00:00
}
}
// $4000/$4004
2019-12-05 02:57:05 +00:00
pub fn duty(&mut self, value: u8) {
2019-12-18 02:38:15 +00:00
self.duty_cycle = DUTY_CYCLE_SEQUENCES[(value >> 6) as usize];
2019-12-17 04:06:00 +00:00
self.length_counter_halt = value & (1<<5) != 0;
self.constant_volume_flag = value & (1<<4) != 0;
2019-12-17 05:43:10 +00:00
if self.constant_volume_flag {
self.envelope = value & 0b1111;
} else {
self.envelope = self.decay_counter;
}
2019-12-05 02:57:05 +00:00
}
2019-12-17 05:43:10 +00:00
// $4001/$4005
2019-12-05 02:57:05 +00:00
pub fn sweep(&mut self, value: u8) {
}
2019-12-17 05:43:10 +00:00
// $4002/$4006
2019-12-05 02:57:05 +00:00
pub fn timer_low(&mut self, value: u8) {
}
2019-12-17 05:43:10 +00:00
// $4003/$4007
2019-12-05 02:57:05 +00:00
pub fn timer_high(&mut self, value: u8) {
}
2019-12-10 03:22:53 +00:00
}
struct EnvelopeGenerator {
}
struct SweepUnit {
}
struct Timer {
}
struct Sequencer {
}
struct LengthCounter {
}