mirror of https://github.com/mgba-emu/mgba.git
GB Audio: Clock frame events on DIV
This commit is contained in:
parent
7ea686a7d9
commit
2c870cacf4
1
CHANGES
1
CHANGES
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue