Permalink
Browse files

GB Audio: Clock frame events on DIV

  • Loading branch information...
endrift committed Feb 4, 2018
1 parent 7ea686a commit 2c870cacf4e820a9a3afb7c36d0bcc2450360e07
Showing with 24 additions and 5 deletions.
  1. +1 −0 CHANGES
  2. +2 −0 include/mgba/internal/gb/audio.h
  3. +13 −5 src/gb/audio.c
  4. +8 −0 src/gb/timer.c
View
@@ -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)
@@ -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
@@ -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
@@ -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;

0 comments on commit 2c870ca

Please sign in to comment.