GB Audio: Skip frame if enabled when clock is high

This commit is contained in:
Vicki Pfau 2018-12-05 19:47:57 -08:00
parent 0332db8961
commit 6158a4fb8d
4 changed files with 21 additions and 1 deletions

View File

@ -187,6 +187,7 @@ struct GBAudio {
uint8_t* nr52;
int frame;
bool skipFrame;
int32_t sampleInterval;
enum GBAudioStyle style;

View File

@ -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);

View File

@ -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);

View File

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