GBA Serialize: Fix audio serialization for desynced FIFOs

This commit is contained in:
Vicki Pfau 2020-01-24 21:51:15 -08:00
parent 93633ea605
commit 1285aa2749
3 changed files with 21 additions and 8 deletions

View File

@ -5,6 +5,7 @@ Emulation fixes:
- GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320)
- GBA Memory: Misaligned SRAM writes are ignored - GBA Memory: Misaligned SRAM writes are ignored
- GBA Serialize: Fix serializing DMA transfer register - GBA Serialize: Fix serializing DMA transfer register
- GBA Serialize: Fix audio serialization for desynced FIFOs
Other fixes: Other fixes:
- Qt: Only dynamically reset video scale if a game is running - Qt: Only dynamically reset video scale if a game is running
- Qt: Fix race condition with proxied video events - Qt: Fix race condition with proxied video events

View File

@ -66,9 +66,10 @@ mLOG_DECLARE_CATEGORY(GBA_STATE);
* 0x0018C - 0x001AB: Audio FIFO 1 * 0x0018C - 0x001AB: Audio FIFO 1
* 0x001AC - 0x001CB: Audio FIFO 2 * 0x001AC - 0x001CB: Audio FIFO 2
* 0x001CC - 0x001DF: Audio miscellaneous state * 0x001CC - 0x001DF: Audio miscellaneous state
* | 0x001CC - 0x001D3: Reserved * | 0x001CC - 0x001CF: FIFO 1 size
* | 0x001D0 - 0x001D3: Reserved
* | 0x001D4 - 0x001D7: Next sample * | 0x001D4 - 0x001D7: Next sample
* | 0x001D8 - 0x001DB: FIFO size * | 0x001D8 - 0x001DB: FIFO 2 size
* | TODO: Fix this, they're in big-endian order, but field is little-endian * | TODO: Fix this, they're in big-endian order, but field is little-endian
* | 0x001DC - 0x001DC: Channel 1 envelope state * | 0x001DC - 0x001DC: Channel 1 envelope state
* | bits 0 - 3: Current volume * | bits 0 - 3: Current volume
@ -170,7 +171,8 @@ mLOG_DECLARE_CATEGORY(GBA_STATE);
* | bits 9 - 23: Reserved * | bits 9 - 23: Reserved
* 0x002C4 - 0x002C7: Game Boy Player next event * 0x002C4 - 0x002C7: Game Boy Player next event
* 0x002C8 - 0x002CB: Current DMA transfer word * 0x002C8 - 0x002CB: Current DMA transfer word
* 0x002CC - 0x002DF: Reserved (leave zero) * 0x002CC - 0x002CF: Last DMA transfer PC
* 0x002D0 - 0x002DF: Reserved (leave zero)
* 0x002E0 - 0x002EF: Savedata state * 0x002E0 - 0x002EF: Savedata state
* | 0x002E0 - 0x002E0: Savedata type * | 0x002E0 - 0x002E0: Savedata type
* | 0x002E1 - 0x002E1: Savedata command (see savedata.h) * | 0x002E1 - 0x002E1: Savedata command (see savedata.h)
@ -256,9 +258,10 @@ struct GBASerializedState {
struct GBSerializedPSGState psg; struct GBSerializedPSGState psg;
uint8_t fifoA[32]; uint8_t fifoA[32];
uint8_t fifoB[32]; uint8_t fifoB[32];
int32_t reserved[2]; uint32_t fifoSizeA;
int32_t reserved;
int32_t nextSample; int32_t nextSample;
uint32_t fifoSize; uint32_t fifoSizeB;
GBSerializedAudioFlags flags; GBSerializedAudioFlags flags;
} audio; } audio;

View File

@ -348,7 +348,9 @@ void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState*
CircleBufferDump(&audio->chA.fifo, state->audio.fifoA, sizeof(state->audio.fifoA)); CircleBufferDump(&audio->chA.fifo, state->audio.fifoA, sizeof(state->audio.fifoA));
CircleBufferDump(&audio->chB.fifo, state->audio.fifoB, sizeof(state->audio.fifoB)); CircleBufferDump(&audio->chB.fifo, state->audio.fifoB, sizeof(state->audio.fifoB));
uint32_t fifoSize = CircleBufferSize(&audio->chA.fifo); uint32_t fifoSize = CircleBufferSize(&audio->chA.fifo);
STORE_32(fifoSize, 0, &state->audio.fifoSize); STORE_32(fifoSize, 0, &state->audio.fifoSizeA);
fifoSize = CircleBufferSize(&audio->chB.fifo);
STORE_32(fifoSize, 0, &state->audio.fifoSizeB);
STORE_32(audio->sampleEvent.when - mTimingCurrentTime(&audio->p->timing), 0, &state->audio.nextSample); STORE_32(audio->sampleEvent.when - mTimingCurrentTime(&audio->p->timing), 0, &state->audio.nextSample);
} }
@ -358,13 +360,20 @@ void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState
CircleBufferClear(&audio->chA.fifo); CircleBufferClear(&audio->chA.fifo);
CircleBufferClear(&audio->chB.fifo); CircleBufferClear(&audio->chB.fifo);
uint32_t fifoSize; uint32_t fifoSize;
LOAD_32(fifoSize, 0, &state->audio.fifoSize); LOAD_32(fifoSize, 0, &state->audio.fifoSizeA);
if (state->audio.fifoSize > CircleBufferCapacity(&audio->chA.fifo)) { if (fifoSize > CircleBufferCapacity(&audio->chA.fifo)) {
fifoSize = CircleBufferCapacity(&audio->chA.fifo); fifoSize = CircleBufferCapacity(&audio->chA.fifo);
} }
size_t i; size_t i;
for (i = 0; i < fifoSize; ++i) { for (i = 0; i < fifoSize; ++i) {
CircleBufferWrite8(&audio->chA.fifo, state->audio.fifoA[i]); CircleBufferWrite8(&audio->chA.fifo, state->audio.fifoA[i]);
}
LOAD_32(fifoSize, 0, &state->audio.fifoSizeB);
if (fifoSize > CircleBufferCapacity(&audio->chB.fifo)) {
fifoSize = CircleBufferCapacity(&audio->chB.fifo);
}
for (i = 0; i < fifoSize; ++i) {
CircleBufferWrite8(&audio->chB.fifo, state->audio.fifoB[i]); CircleBufferWrite8(&audio->chB.fifo, state->audio.fifoB[i]);
} }