GB Audio: Clock frame events on DIV
Vicki Pfau vi@endrift.com
Sat, 03 Feb 2018 23:56:10 -0800
4 files changed,
24 insertions(+),
5 deletions(-)
M
CHANGES
→
CHANGES
@@ -49,6 +49,7 @@ - Wii: Fix screen tear when unpausing
- 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)
M
include/mgba/internal/gb/audio.h
→
include/mgba/internal/gb/audio.h
@@ -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;
M
src/gb/audio.c
→
src/gb/audio.c
@@ -109,9 +109,11 @@ mTimingDeschedule(audio->timing, &audio->ch3Event);
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 } };@@ -486,7 +488,13 @@ }
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 @@ }
} 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 @@ audio->playingCh3 = !!(*audio->nr52 & 0x0004);
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);
M
src/gb/timer.c
→
src/gb/timer.c
@@ -30,6 +30,10 @@ if (!timer->p->memory.io[REG_TIMA]) {
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; }@@ -75,6 +79,10 @@ ++timer->p->memory.io[REG_TIMA];
if (!timer->p->memory.io[REG_TIMA]) { 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;