GB Audio: Clock frame events on DIV

This commit is contained in:
Vicki Pfau 2018-02-03 23:56:10 -08:00
parent 7ea686a7d9
commit 2c870cacf4
4 changed files with 24 additions and 5 deletions

View File

@ -49,6 +49,7 @@ Bugfixes:
- GBA: Fix some GBA ROM misdetection (fixes mgba.io/i/978)
- GBA Hardware: RTC accuracy improvements
- GB Timer: Minor accuracy improvements
- GB Audio: Clock frame events on DIV
Misc:
- GBA Timer: Use global cycles for timers
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)

View File

@ -232,6 +232,8 @@ void GBAudioWriteNR50(struct GBAudio* audio, uint8_t);
void GBAudioWriteNR51(struct GBAudio* audio, uint8_t);
void GBAudioWriteNR52(struct GBAudio* audio, uint8_t);
void GBAudioUpdateFrame(struct GBAudio* audio, struct mTiming* timing);
void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right);
struct GBSerializedPSGState;

View File

@ -109,10 +109,12 @@ void GBAudioReset(struct GBAudio* audio) {
mTimingDeschedule(audio->timing, &audio->ch3Fade);
mTimingDeschedule(audio->timing, &audio->ch4Event);
mTimingDeschedule(audio->timing, &audio->sampleEvent);
mTimingSchedule(audio->timing, &audio->frameEvent, 0);
if (audio->style != GB_AUDIO_GBA) {
mTimingSchedule(audio->timing, &audio->sampleEvent, 0);
}
if (audio->style == GB_AUDIO_GBA) {
mTimingSchedule(audio->timing, &audio->frameEvent, 0);
}
audio->ch1 = (struct GBAudioSquareChannel) { .envelope = { .dead = 2 } };
audio->ch2 = (struct GBAudioSquareChannel) { .envelope = { .dead = 2 } };
audio->ch3 = (struct GBAudioWaveChannel) { .bank = 0 };
@ -486,7 +488,13 @@ void GBAudioWriteNR52(struct GBAudio* audio, uint8_t value) {
void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) {
struct GBAudio* audio = user;
GBAudioUpdateFrame(audio, timing);
if (audio->style == GB_AUDIO_GBA) {
mTimingSchedule(timing, &audio->frameEvent, audio->timingFactor * FRAME_CYCLES - cyclesLate);
}
}
void GBAudioUpdateFrame(struct GBAudio* audio, struct mTiming* timing) {
int frame = (audio->frame + 1) & 7;
audio->frame = frame;
@ -576,8 +584,6 @@ void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) {
}
break;
}
mTimingSchedule(timing, &audio->frameEvent, audio->timingFactor * FRAME_CYCLES - cyclesLate);
}
void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) {
@ -959,8 +965,10 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt
audio->playingCh4 = !!(*audio->nr52 & 0x0008);
audio->enable = GBAudioEnableGetEnable(*audio->nr52);
LOAD_32LE(when, 0, &state->ch1.nextFrame);
mTimingSchedule(audio->timing, &audio->frameEvent, when);
if (audio->style == GB_AUDIO_GBA) {
LOAD_32LE(when, 0, &state->ch1.nextFrame);
mTimingSchedule(audio->timing, &audio->frameEvent, when);
}
LOAD_32LE(flags, 0, flagsIn);
audio->frame = GBSerializedAudioFlagsGetFrame(flags);

View File

@ -30,6 +30,10 @@ static void _GBTimerDivIncrement(struct GBTimer* timer, uint32_t cyclesLate) {
mTimingSchedule(&timer->p->timing, &timer->irq, 7 - ((timer->p->cpu->executionState - cyclesLate) & 3));
}
}
int timingFactor = 0x3FF >> !timer->p->doubleSpeed;
if ((timer->internalDiv & timingFactor) == timingFactor) {
GBAudioUpdateFrame(&timer->p->audio, &timer->p->timing);
}
++timer->internalDiv;
timer->p->memory.io[REG_DIV] = timer->internalDiv >> 4;
}
@ -76,6 +80,10 @@ void GBTimerDivReset(struct GBTimer* timer) {
mTimingSchedule(&timer->p->timing, &timer->irq, 7 - (timer->p->cpu->executionState & 3));
}
}
int timingFactor = 0x200 >> !timer->p->doubleSpeed;
if (timer->internalDiv & 0x200) {
GBAudioUpdateFrame(&timer->p->audio, &timer->p->timing);
}
timer->p->memory.io[REG_DIV] = 0;
timer->internalDiv = 0;
timer->nextDiv = GB_DMG_DIV_PERIOD;