From 8c9790bb3bd8ac8c388c11d131333236796af194 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 8 Jul 2014 00:02:39 -0700 Subject: [PATCH] Add audio FIFOs to savestates --- src/gba/gba-audio.c | 12 ++++++++++++ src/gba/gba-io.c | 17 ++++++++++++----- src/util/circle-buffer.c | 29 ++++++++++++++++++++++++++--- src/util/circle-buffer.h | 2 ++ 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/gba/gba-audio.c b/src/gba/gba-audio.c index 39b4d0e68..9c7b052d2 100644 --- a/src/gba/gba-audio.c +++ b/src/gba/gba-audio.c @@ -692,6 +692,10 @@ void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state->audio.ch4.endTime = audio->ch4.control.endTime; state->audio.ch4.nextEvent = audio->nextCh4; + CircleBufferDump(&audio->chA.fifo, state->audio.fifoA, sizeof(state->audio.fifoA)); + CircleBufferDump(&audio->chB.fifo, state->audio.fifoB, sizeof(state->audio.fifoB)); + state->audio.fifoSize = CircleBufferSize(&audio->chA.fifo); + state->audio.nextEvent = audio->nextEvent; state->audio.eventDiff = audio->eventDiff; state->audio.nextSample = audio->nextSample; @@ -726,6 +730,14 @@ void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState audio->ch4.control.endTime = state->audio.ch4.endTime; audio->nextCh4 = state->audio.ch4.nextEvent; + CircleBufferClear(&audio->chA.fifo); + CircleBufferClear(&audio->chB.fifo); + unsigned i; + for (i = 0; i < state->audio.fifoSize / sizeof(uint32_t); ++i) { + CircleBufferWrite32(&audio->chA.fifo, state->audio.fifoA[i]); + CircleBufferWrite32(&audio->chB.fifo, state->audio.fifoB[i]); + } + audio->nextEvent = state->audio.nextEvent; audio->eventDiff = state->audio.eventDiff; audio->nextSample = state->audio.nextSample; diff --git a/src/gba/gba-io.c b/src/gba/gba-io.c index 430dc0d4b..53c5863c1 100644 --- a/src/gba/gba-io.c +++ b/src/gba/gba-io.c @@ -61,9 +61,9 @@ static const int _isSpecialRegister[REG_MAX >> 1] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // DMA - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Timers @@ -466,12 +466,19 @@ void GBAIODeserialize(struct GBA* gba, struct GBASerializedState* state) { } } + gba->timersEnabled = 0; + memcpy(gba->timers, state->timers, sizeof(gba->timers)); for (i = 0; i < 4; ++i) { gba->memory.dma[i].nextSource = state->dma[i].nextSource; gba->memory.dma[i].nextDest = state->dma[i].nextDest; gba->memory.dma[i].nextCount = state->dma[i].nextCount; gba->memory.dma[i].nextEvent = state->dma[i].nextEvent; - } + if (gba->memory.dma[i].timing != DMA_TIMING_NOW) { + GBAMemoryScheduleDMA(gba, i, &gba->memory.dma[i]); + } - memcpy(state->timers, gba->timers, sizeof(gba->timers)); + if (gba->timers[i].enable) { + gba->timersEnabled |= 1 << i; + } + } } diff --git a/src/util/circle-buffer.c b/src/util/circle-buffer.c index d7b14a91b..f98569be5 100644 --- a/src/util/circle-buffer.c +++ b/src/util/circle-buffer.c @@ -18,9 +18,7 @@ static int _checkIntegrity(struct CircleBuffer* buffer) { void CircleBufferInit(struct CircleBuffer* buffer, unsigned capacity) { buffer->data = malloc(capacity); buffer->capacity = capacity; - buffer->size = 0; - buffer->readPtr = buffer->data; - buffer->writePtr = buffer->data; + CircleBufferClear(buffer); } void CircleBufferDeinit(struct CircleBuffer* buffer) { @@ -32,6 +30,12 @@ unsigned CircleBufferSize(const struct CircleBuffer* buffer) { return buffer->size; } +void CircleBufferClear(struct CircleBuffer* buffer) { + buffer->size = 0; + buffer->readPtr = buffer->data; + buffer->writePtr = buffer->data; +} + int CircleBufferWrite8(struct CircleBuffer* buffer, int8_t value) { int8_t* data = buffer->writePtr; if (buffer->size + sizeof(int8_t) > buffer->capacity) { @@ -166,3 +170,22 @@ int CircleBufferRead(struct CircleBuffer* buffer, void* output, size_t length) { #endif return length; } + +int CircleBufferDump(const struct CircleBuffer* buffer, void* output, size_t length) { + int8_t* data = buffer->readPtr; + if (buffer->size == 0) { + return 0; + } + if (length > buffer->size) { + length = buffer->size; + } + size_t remaining = buffer->capacity - ((int8_t*) data - (int8_t*) buffer->data); + if (length <= remaining) { + memcpy(output, data, length); + } else { + memcpy(output, data, remaining); + memcpy((int8_t*) output + remaining, buffer->data, length - remaining); + } + + return length; +} diff --git a/src/util/circle-buffer.h b/src/util/circle-buffer.h index 3a3939b5f..2e6ec55d2 100644 --- a/src/util/circle-buffer.h +++ b/src/util/circle-buffer.h @@ -14,10 +14,12 @@ struct CircleBuffer { void CircleBufferInit(struct CircleBuffer* buffer, unsigned capacity); void CircleBufferDeinit(struct CircleBuffer* buffer); unsigned CircleBufferSize(const struct CircleBuffer* buffer); +void CircleBufferClear(struct CircleBuffer* buffer); int CircleBufferWrite8(struct CircleBuffer* buffer, int8_t value); int CircleBufferWrite32(struct CircleBuffer* buffer, int32_t value); int CircleBufferRead8(struct CircleBuffer* buffer, int8_t* value); int CircleBufferRead32(struct CircleBuffer* buffer, int32_t* value); int CircleBufferRead(struct CircleBuffer* buffer, void* output, size_t length); +int CircleBufferDump(const struct CircleBuffer* buffer, void* output, size_t length); #endif