From 6158a4fb8d6bc8e7df42504bad7e18d9b5c667a3 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 5 Dec 2018 19:47:57 -0800 Subject: [PATCH] GB Audio: Skip frame if enabled when clock is high --- include/mgba/internal/gb/audio.h | 1 + include/mgba/internal/gb/serialize.h | 1 + src/gb/audio.c | 17 +++++++++++++++++ src/gb/timer.c | 3 ++- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/mgba/internal/gb/audio.h b/include/mgba/internal/gb/audio.h index 837e0a1b3..ed3a76325 100644 --- a/include/mgba/internal/gb/audio.h +++ b/include/mgba/internal/gb/audio.h @@ -187,6 +187,7 @@ struct GBAudio { uint8_t* nr52; int frame; + bool skipFrame; int32_t sampleInterval; enum GBAudioStyle style; diff --git a/include/mgba/internal/gb/serialize.h b/include/mgba/internal/gb/serialize.h index 14cfd12d4..7b1feb93e 100644 --- a/include/mgba/internal/gb/serialize.h +++ b/include/mgba/internal/gb/serialize.h @@ -195,6 +195,7 @@ DECL_BITS(GBSerializedAudioFlags, Frame, 22, 3); DECL_BIT(GBSerializedAudioFlags, Ch1SweepEnabled, 25); DECL_BIT(GBSerializedAudioFlags, Ch1SweepOccurred, 26); DECL_BIT(GBSerializedAudioFlags, Ch3Readable, 27); +DECL_BIT(GBSerializedAudioFlags, SkipFrame, 28); DECL_BITFIELD(GBSerializedAudioEnvelope, uint32_t); DECL_BITS(GBSerializedAudioEnvelope, Length, 0, 7); diff --git a/src/gb/audio.c b/src/gb/audio.c index ee5ec9ed8..08ba1fa9e 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -470,7 +470,15 @@ void GBAudioWriteNR52(struct GBAudio* audio, uint8_t value) { } *audio->nr52 &= ~0x000F; } else if (!wasEnable) { + audio->skipFrame = false; audio->frame = 7; + + if (audio->p) { + unsigned timingFactor = 0x400 >> !audio->p->doubleSpeed; + if (audio->p->timer.internalDiv & timingFactor) { + audio->skipFrame = true; + } + } } } @@ -483,6 +491,13 @@ void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) { } void GBAudioUpdateFrame(struct GBAudio* audio, struct mTiming* timing) { + if (!audio->enable) { + return; + } + if (audio->skipFrame) { + audio->skipFrame = false; + return; + } int frame = (audio->frame + 1) & 7; audio->frame = frame; @@ -929,6 +944,7 @@ void GBAudioPSGSerialize(const struct GBAudio* audio, struct GBSerializedPSGStat uint32_t ch4Flags = 0; flags = GBSerializedAudioFlagsSetFrame(flags, audio->frame); + flags = GBSerializedAudioFlagsSetSkipFrame(flags, audio->skipFrame); STORE_32LE(audio->frameEvent.when - mTimingCurrentTime(audio->timing), 0, &state->ch1.nextFrame); flags = GBSerializedAudioFlagsSetCh1Volume(flags, audio->ch1.envelope.currentVolume); @@ -987,6 +1003,7 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt LOAD_32LE(flags, 0, flagsIn); audio->frame = GBSerializedAudioFlagsGetFrame(flags); + audio->skipFrame = GBSerializedAudioFlagsGetSkipFrame(flags); LOAD_32LE(ch1Flags, 0, &state->ch1.envelope); audio->ch1.envelope.currentVolume = GBSerializedAudioFlagsGetCh1Volume(flags); diff --git a/src/gb/timer.c b/src/gb/timer.c index 32c9efdc5..e990b3534 100644 --- a/src/gb/timer.c +++ b/src/gb/timer.c @@ -80,7 +80,8 @@ void GBTimerDivReset(struct GBTimer* timer) { mTimingSchedule(&timer->p->timing, &timer->irq, 7 - (timer->p->cpu->executionState & 3)); } } - if (timer->internalDiv & 0x200) { + unsigned timingFactor = 0x400 >> !timer->p->doubleSpeed; + if (timer->internalDiv & timingFactor) { GBAudioUpdateFrame(&timer->p->audio, &timer->p->timing); } timer->p->memory.io[REG_DIV] = 0;