all repos — mgba @ 2c870cacf4e820a9a3afb7c36d0bcc2450360e07

mGBA Game Boy Advance Emulator

GB Audio: Clock frame events on DIV
Vicki Pfau vi@endrift.com
Sat, 03 Feb 2018 23:56:10 -0800
commit

2c870cacf4e820a9a3afb7c36d0bcc2450360e07

parent

7ea686a7d937de42533ca15989d3a48d6bf6d51d

4 files changed, 24 insertions(+), 5 deletions(-)

jump to
M CHANGESCHANGES

@@ -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.hinclude/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.csrc/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.csrc/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;