From 557a3b67db7c4ee58a64a6341978845e59cee6e0 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 17 Mar 2024 19:53:41 -0700 Subject: [PATCH] GB Audio: Fix audio envelope timing resetting too often (fixes #3164) --- CHANGES | 1 + src/gb/audio.c | 27 ++++++++++++++++----------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index 6d94248d2..f511b8c78 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,6 @@ 0.10.4: (Future) Emulation fixes: + - GB Audio: Fix audio envelope timing resetting too often (fixes mgba.io/i/3164) - GBA SIO: Fix MULTI mode SIOCNT bit 7 writes on secondary GBAs (fixes mgba.io/i/3110) Other fixes: - Updater: Fix updating appimage across filesystems diff --git a/src/gb/audio.c b/src/gb/audio.c index 6f2535a65..64edb9010 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -33,10 +33,10 @@ static void _writeDuty(struct GBAudioEnvelope* envelope, uint8_t value); static bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudioStyle style); static void _resetSweep(struct GBAudioSweep* sweep); -static bool _resetEnvelope(struct GBAudioEnvelope* sweep); +static bool _resetEnvelope(struct GBAudioEnvelope* sweep, enum GBAudioStyle style); static void _updateEnvelope(struct GBAudioEnvelope* envelope); -static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope); +static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope, enum GBAudioStyle style); static bool _updateSweep(struct GBAudioSquareChannel* sweep, bool initial); static void _updateSquareSample(struct GBAudioSquareChannel* ch); @@ -192,7 +192,7 @@ void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) { } } if (GBAudioRegisterControlIsRestart(value << 8)) { - audio->playingCh1 = _resetEnvelope(&audio->ch1.envelope); + audio->playingCh1 = _resetEnvelope(&audio->ch1.envelope, audio->style); audio->ch1.sweep.realFrequency = audio->ch1.control.frequency; _resetSweep(&audio->ch1.sweep); if (audio->playingCh1 && audio->ch1.sweep.shift) { @@ -243,7 +243,7 @@ void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) { } } if (GBAudioRegisterControlIsRestart(value << 8)) { - audio->playingCh2 = _resetEnvelope(&audio->ch2.envelope); + audio->playingCh2 = _resetEnvelope(&audio->ch2.envelope, audio->style); if (!audio->ch2.control.length) { audio->ch2.control.length = 64; @@ -383,7 +383,7 @@ void GBAudioWriteNR44(struct GBAudio* audio, uint8_t value) { } } if (GBAudioRegisterNoiseControlIsRestart(value)) { - audio->playingCh4 = _resetEnvelope(&audio->ch4.envelope); + audio->playingCh4 = _resetEnvelope(&audio->ch4.envelope, audio->style); if (audio->ch4.power) { audio->ch4.lfsr = 0x7F; @@ -847,9 +847,10 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { mTimingSchedule(timing, &audio->sampleEvent, audio->sampleInterval * audio->timingFactor - cyclesLate); } -bool _resetEnvelope(struct GBAudioEnvelope* envelope) { +bool _resetEnvelope(struct GBAudioEnvelope* envelope, enum GBAudioStyle style) { envelope->currentVolume = envelope->initialVolume; - _updateEnvelopeDead(envelope); + envelope->nextStep = envelope->stepTime; + _updateEnvelopeDead(envelope, style); return envelope->initialVolume || envelope->direction; } @@ -902,7 +903,7 @@ bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudi } envelope->currentVolume &= 0xF; } - _updateEnvelopeDead(envelope); + _updateEnvelopeDead(envelope, style); return envelope->initialVolume || envelope->direction; } @@ -938,16 +939,20 @@ static void _updateEnvelope(struct GBAudioEnvelope* envelope) { } } -static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope) { +static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope, enum GBAudioStyle style) { if (!envelope->stepTime) { envelope->dead = envelope->currentVolume ? 1 : 2; } else if (!envelope->direction && !envelope->currentVolume) { envelope->dead = 2; } else if (envelope->direction && envelope->currentVolume == 0xF) { envelope->dead = 1; - } else { + } else if (envelope->dead) { + // TODO: Figure out if this happens on DMG/CGB or just AGB + // TODO: Figure out the exact circumstances that lead to reloading the step + if (style == GB_AUDIO_GBA) { + envelope->nextStep = envelope->stepTime; + } envelope->dead = 0; - envelope->nextStep = envelope->stepTime; } }