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: Fix some GBA ROM misdetection (fixes mgba.io/i/978)
- GBA Hardware: RTC accuracy improvements - GBA Hardware: RTC accuracy improvements
- GB Timer: Minor accuracy improvements - GB Timer: Minor accuracy improvements
- GB Audio: Clock frame events on DIV
Misc: Misc:
- GBA Timer: Use global cycles for timers - GBA Timer: Use global cycles for timers
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) - 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 GBAudioWriteNR51(struct GBAudio* audio, uint8_t);
void GBAudioWriteNR52(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); void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right);
struct GBSerializedPSGState; struct GBSerializedPSGState;

View File

@ -109,10 +109,12 @@ void GBAudioReset(struct GBAudio* audio) {
mTimingDeschedule(audio->timing, &audio->ch3Fade); mTimingDeschedule(audio->timing, &audio->ch3Fade);
mTimingDeschedule(audio->timing, &audio->ch4Event); mTimingDeschedule(audio->timing, &audio->ch4Event);
mTimingDeschedule(audio->timing, &audio->sampleEvent); mTimingDeschedule(audio->timing, &audio->sampleEvent);
mTimingSchedule(audio->timing, &audio->frameEvent, 0);
if (audio->style != GB_AUDIO_GBA) { if (audio->style != GB_AUDIO_GBA) {
mTimingSchedule(audio->timing, &audio->sampleEvent, 0); 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->ch1 = (struct GBAudioSquareChannel) { .envelope = { .dead = 2 } };
audio->ch2 = (struct GBAudioSquareChannel) { .envelope = { .dead = 2 } }; audio->ch2 = (struct GBAudioSquareChannel) { .envelope = { .dead = 2 } };
audio->ch3 = (struct GBAudioWaveChannel) { .bank = 0 }; 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) { void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) {
struct GBAudio* audio = user; 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; int frame = (audio->frame + 1) & 7;
audio->frame = frame; audio->frame = frame;
@ -576,8 +584,6 @@ void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) {
} }
break; break;
} }
mTimingSchedule(timing, &audio->frameEvent, audio->timingFactor * FRAME_CYCLES - cyclesLate);
} }
void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) { 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->playingCh4 = !!(*audio->nr52 & 0x0008);
audio->enable = GBAudioEnableGetEnable(*audio->nr52); audio->enable = GBAudioEnableGetEnable(*audio->nr52);
LOAD_32LE(when, 0, &state->ch1.nextFrame); if (audio->style == GB_AUDIO_GBA) {
mTimingSchedule(audio->timing, &audio->frameEvent, when); LOAD_32LE(when, 0, &state->ch1.nextFrame);
mTimingSchedule(audio->timing, &audio->frameEvent, when);
}
LOAD_32LE(flags, 0, flagsIn); LOAD_32LE(flags, 0, flagsIn);
audio->frame = GBSerializedAudioFlagsGetFrame(flags); 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)); 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->internalDiv;
timer->p->memory.io[REG_DIV] = timer->internalDiv >> 4; 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)); 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->p->memory.io[REG_DIV] = 0;
timer->internalDiv = 0; timer->internalDiv = 0;
timer->nextDiv = GB_DMG_DIV_PERIOD; timer->nextDiv = GB_DMG_DIV_PERIOD;