Skip to content

Commit

Permalink
Fix intermittent modulator bug
Browse files Browse the repository at this point in the history
  • Loading branch information
Gumball2415 committed Apr 19, 2024
1 parent 9c9afeb commit 2852b9e
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Core/NES/Mappers/FDS/BaseFdsChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class BaseFdsChannel : public ISerializable
}
}

virtual bool TickEnvelope(uint8_t wavePosition)
bool TickEnvelope(uint8_t wavePosition)
{
// "Changes to the volume envelope only take effect while the wavetable
// pointer (top 6 bits of wave accumulator) is 0."
Expand Down
4 changes: 2 additions & 2 deletions Core/NES/Mappers/FDS/FdsAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ void FdsAudio::Serialize(Serializer& s)

void FdsAudio::ClockAudio()
{
int frequency = _volume.GetFrequency();
uint16_t frequency = _volume.GetFrequency();
if(!_haltWaveform && !_disableEnvelopes) {
_volume.TickEnvelope(_wavePosition);
if(_mod.TickEnvelope(_wavePosition)) {
if(_mod.TickEnvelope()) {
_mod.UpdateOutput(frequency);
}
}
Expand Down
42 changes: 25 additions & 17 deletions Core/NES/Mappers/FDS/ModChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
class ModChannel : public BaseFdsChannel
{
private:
const int32_t ModReset = 0xFF;
const int32_t _modLut[8] = { 0,1,2,4,ModReset,-4,-2,-1 };
const int16_t ModReset = 0xFF;
const int16_t _modLut[8] = { 0,1,2,4,ModReset,-4,-2,-1 };

int8_t _counter = 0;
bool _modulationDisabled = false;
Expand All @@ -16,7 +16,7 @@ class ModChannel : public BaseFdsChannel
uint8_t _modM2Counter = 0;
uint8_t _modTable[32] = {};
uint8_t _modTablePosition = 0;
int32_t _output = 0;
uint8_t _output = 0;

protected:
void Serialize(Serializer& s) override
Expand All @@ -27,6 +27,19 @@ class ModChannel : public BaseFdsChannel
SV(_counter); SV(_modulationDisabled); SV(_forceCarryOut); SV(_modTablePosition); SV(_modAccumulator); SV(_modM2Counter); SV(_output);
}

void IncrementAccumulator(uint32_t value)
{
_modAccumulator += value;
if(_modAccumulator > 0x3FFFF) {
_modAccumulator -= 0x40000;
}
}

void UpdateModPosition()
{
_modTablePosition = (_modAccumulator >> 13) & 0x1F;
}

public:
virtual void WriteReg(uint16_t addr, uint8_t value) override
{
Expand All @@ -45,13 +58,13 @@ class ModChannel : public BaseFdsChannel
_forceCarryOut = (value & 0x40) == 0x40;
if(_modulationDisabled) {
// "Bits 0-12 are reset by 4087.7=1. Bits 13-17 have no reset."
_modAccumulator &= 0x3F000;
_modAccumulator &= 0x3E000;
}
break;
}
}

virtual bool TickEnvelope(uint8_t wavePosition) override
bool TickEnvelope()
{
if(!_envelopeOff && _masterSpeed > 0) {
_timer--;
Expand All @@ -73,12 +86,10 @@ class ModChannel : public BaseFdsChannel
{
//"This register has no effect unless the mod unit is disabled via the high bit of $4087."
if(_modulationDisabled) {
// "ghost" modtable address bit(0) makes mod unit step thru each entry twice
_modTable[_modTablePosition] = value & 0x07;
_modTable[_modTablePosition] = value & 0x07;
// "Writing $4088 increments the address (bits 13-17) when 4087.7=1."
_modAccumulator += 0x2000;
_modTablePosition = (_modAccumulator >> 13) & 0x1F;
_modTable[_modTablePosition] = value & 0x07;
IncrementAccumulator(0x2000);
UpdateModPosition();
}
}

Expand All @@ -101,17 +112,14 @@ class ModChannel : public BaseFdsChannel
{
if(IsEnabled()) {
if(++_modM2Counter == 16) {
_modAccumulator += _frequency;
if(_modAccumulator > 0x3FFFF) {
_modAccumulator -= 0x40000;
}
IncrementAccumulator(_frequency);

// "On a carry out from bit 11, update the mod counter (increment $4085 with modtable)."
// "4087.6 forces a carry out from bit 11."
if((_modAccumulator & 0xFFF) < _frequency || _forceCarryOut) {
int32_t offset = _modLut[_modTable[_modTablePosition]];
int16_t offset = _modLut[_modTable[_modTablePosition]];
UpdateCounter(offset == ModReset ? 0 : _counter + offset);
_modTablePosition = (_modAccumulator >> 13) & 0x1F;
UpdateModPosition();
}

_modM2Counter = 0;
Expand All @@ -137,7 +145,7 @@ class ModChannel : public BaseFdsChannel
_output = temp;
}

int32_t GetOutput()
uint8_t GetOutput()
{
return _output;
}
Expand Down

0 comments on commit 2852b9e

Please sign in to comment.