fix(apu): increase accuracy of apu emulation

Reintroduce the Frame Sequencer and it's state enum (needed so that we
can reset the FS on NR52 enable)
This commit is contained in:
2021-08-17 22:18:40 -05:00
parent 8fea8eb1ff
commit 22f96a10e7
2 changed files with 103 additions and 31 deletions

View File

@@ -73,7 +73,7 @@ pub(crate) mod ch1 {
}
}
pub(crate) mod ch3 {
pub(super) mod ch3 {
#[derive(Debug, Clone, Copy)]
pub(crate) enum Volume {
Mute = 0,
@@ -102,7 +102,7 @@ pub(crate) mod ch3 {
}
}
pub(crate) mod ch4 {
pub(super) mod ch4 {
use super::bitfield;
bitfield! {
@@ -217,7 +217,7 @@ pub(crate) mod ch4 {
}
}
pub(crate) mod common {
pub(super) mod common {
use super::bitfield;
bitfield! {
@@ -508,3 +508,56 @@ impl From<ChannelControl> for u8 {
ctrl.0
}
}
pub(super) mod fs {
#[derive(Debug)]
pub(crate) struct FrameSequencer {
step: u8,
state: FrameSequencerState,
}
impl Default for FrameSequencer {
fn default() -> Self {
Self {
step: Default::default(),
state: FrameSequencerState::Length,
}
}
}
impl FrameSequencer {
pub(crate) fn next(&mut self) {
use FrameSequencerState::*;
self.step = (self.step + 1) % 8;
self.state = match self.step {
0 => Length,
1 => Nothing,
2 => LengthAndSweep,
3 => Nothing,
4 => Length,
5 => Nothing,
6 => LengthAndSweep,
7 => Envelope,
_ => unreachable!("Step {} is invalid for the Frame Sequencer", self.step),
};
}
pub(crate) fn state(&self) -> FrameSequencerState {
self.state
}
pub(crate) fn reset(&mut self) {
self.step = Default::default();
self.state = FrameSequencerState::Length;
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) enum FrameSequencerState {
Length,
Nothing,
LengthAndSweep,
Envelope,
}
}