all repos — mgba @ 6158a4fb8d6bc8e7df42504bad7e18d9b5c667a3

mGBA Game Boy Advance Emulator

GB Audio: Skip frame if enabled when clock is high
Vicki Pfau vi@endrift.com
Wed, 05 Dec 2018 19:47:57 -0800
commit

6158a4fb8d6bc8e7df42504bad7e18d9b5c667a3

parent

0332db8961ef1b11b4f9e0326d3683b8e5d17730

M include/mgba/internal/gb/audio.hinclude/mgba/internal/gb/audio.h

@@ -187,6 +187,7 @@ bool playingCh4;

uint8_t* nr52; int frame; + bool skipFrame; int32_t sampleInterval; enum GBAudioStyle style;
M include/mgba/internal/gb/serialize.hinclude/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);
M src/gb/audio.csrc/gb/audio.c

@@ -470,7 +470,15 @@ }

} *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 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 @@ uint32_t ch2Flags = 0;

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 @@ }

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);
M src/gb/timer.csrc/gb/timer.c

@@ -80,7 +80,8 @@ if (!timer->p->memory.io[REG_TIMA]) {

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;