diff --git a/src/gba/gba-audio.c b/src/gba/gba-audio.c index 4a2a8cdde..8d40af5b3 100644 --- a/src/gba/gba-audio.c +++ b/src/gba/gba-audio.c @@ -2,6 +2,7 @@ #include "gba.h" #include "gba-io.h" +#include "gba-serialize.h" #include "gba-thread.h" #include @@ -606,3 +607,71 @@ static void _sample(struct GBAAudio* audio) { unsigned produced = CircleBufferSize(&audio->left); GBASyncProduceAudio(audio->p->sync, produced >= GBA_AUDIO_SAMPLES * 3); } + +void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state) { + state->audio.ch1Volume = audio->ch1.envelope.currentVolume; + state->audio.ch1Dead = audio->ch1.envelope.dead; + state->audio.ch1Hi = audio->ch1.control.hi; + state->audio.ch1.envelopeNextStep = audio->ch1.envelope.nextStep; + state->audio.ch1.waveNextStep = audio->ch1.control.nextStep; + state->audio.ch1.sweepNextStep = audio->ch1.nextSweep; + state->audio.ch1.endTime = audio->ch1.control.endTime; + state->audio.ch1.nextEvent = audio->nextCh1; + + state->audio.ch2Volume = audio->ch2.envelope.currentVolume; + state->audio.ch2Dead = audio->ch2.envelope.dead; + state->audio.ch2Hi = audio->ch2.control.hi; + state->audio.ch2.envelopeNextStep = audio->ch2.envelope.nextStep; + state->audio.ch2.waveNextStep = audio->ch2.control.nextStep; + state->audio.ch2.endTime = audio->ch2.control.endTime; + state->audio.ch2.nextEvent = audio->nextCh2; + + memcpy(state->audio.ch3.wavebanks, audio->ch3.wavedata, sizeof(state->audio.ch3.wavebanks)); + state->audio.ch3.endTime = audio->ch3.control.endTime; + state->audio.ch3.nextEvent = audio->nextCh3; + + state->audio.ch4Volume = audio->ch4.envelope.currentVolume; + state->audio.ch4Dead = audio->ch4.envelope.dead; + state->audio.ch4.envelopeNextStep = audio->ch4.envelope.nextStep; + state->audio.ch4.lfsr = audio->ch4.lfsr; + state->audio.ch4.endTime = audio->ch4.control.endTime; + state->audio.ch4.nextEvent = audio->nextCh4; + + state->audio.nextEvent = audio->nextEvent; + state->audio.eventDiff = audio->eventDiff; + state->audio.nextSample = audio->nextSample; +} + +void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState* state) { + audio->ch1.envelope.currentVolume = state->audio.ch1Volume; + audio->ch1.envelope.dead = state->audio.ch1Dead; + audio->ch1.control.hi = state->audio.ch1Hi; + audio->ch1.envelope.nextStep = state->audio.ch1.envelopeNextStep; + audio->ch1.control.nextStep = state->audio.ch1.waveNextStep; + audio->ch1.nextSweep = state->audio.ch1.sweepNextStep; + audio->ch1.control.endTime = state->audio.ch1.endTime; + audio->nextCh1 = state->audio.ch1.nextEvent; + + audio->ch2.envelope.currentVolume = state->audio.ch2Volume; + audio->ch2.envelope.dead = state->audio.ch2Dead; + audio->ch2.control.hi = state->audio.ch2Hi; + audio->ch2.envelope.nextStep = state->audio.ch2.envelopeNextStep; + audio->ch2.control.nextStep = state->audio.ch2.waveNextStep; + audio->ch2.control.endTime = state->audio.ch2.endTime; + audio->nextCh2 = state->audio.ch2.nextEvent; + + memcpy(audio->ch3.wavedata, state->audio.ch3.wavebanks, sizeof(audio->ch3.wavedata)); + audio->ch3.control.endTime = state->audio.ch3.endTime; + audio->nextCh3 = state->audio.ch3.nextEvent; + + audio->ch4.envelope.currentVolume = state->audio.ch4Volume; + audio->ch4.envelope.dead = state->audio.ch4Dead; + audio->ch4.envelope.nextStep = state->audio.ch4.envelopeNextStep; + audio->ch4.lfsr = state->audio.ch4.lfsr; + audio->ch4.control.endTime = state->audio.ch4.endTime; + audio->nextCh4 = state->audio.ch4.nextEvent; + + audio->nextEvent = state->audio.nextEvent; + audio->eventDiff = state->audio.eventDiff; + audio->nextSample = state->audio.nextSample; +} diff --git a/src/gba/gba-audio.h b/src/gba/gba-audio.h index eca9da2e8..1a058cd23 100644 --- a/src/gba/gba-audio.h +++ b/src/gba/gba-audio.h @@ -230,4 +230,8 @@ void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles); unsigned GBAAudioCopy(struct GBAAudio* audio, void* left, void* right, unsigned nSamples); +struct GBASerializedState; +void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state); +void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState* state); + #endif diff --git a/src/gba/gba-serialize.c b/src/gba/gba-serialize.c index dabcf072b..5f8796968 100644 --- a/src/gba/gba-serialize.c +++ b/src/gba/gba-serialize.c @@ -1,5 +1,6 @@ #include "gba-serialize.h" +#include "gba-audio.h" #include "gba-io.h" #include "memory.h" @@ -28,6 +29,7 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* state) { GBAMemorySerialize(&gba->memory, state); GBAIOSerialize(gba, state); GBAVideoSerialize(&gba->video, state); + GBAAudioSerialize(&gba->audio, state); } void GBADeserialize(struct GBA* gba, struct GBASerializedState* state) { @@ -57,6 +59,7 @@ void GBADeserialize(struct GBA* gba, struct GBASerializedState* state) { GBAMemoryDeserialize(&gba->memory, state); GBAIODeserialize(gba, state); GBAVideoDeserialize(&gba->video, state); + GBAAudioDeserialize(&gba->audio, state); } static int _getStateFd(struct GBA* gba, int slot) { diff --git a/src/gba/gba-serialize.h b/src/gba/gba-serialize.h index 32f3c0ca5..b0e5035c4 100644 --- a/src/gba/gba-serialize.h +++ b/src/gba/gba-serialize.h @@ -19,37 +19,48 @@ const uint32_t GBA_SAVESTATE_MAGIC; * | 0x0006C - 0x0006F: Cycles until next event * | 0x00070 - 0x00117: Banked registers * | 0x00118 - 0x0012F: Banked SPSRs - * 0x00130 - 0x00147: Audio channel 1 state - * | 0x00130 - 0x00130: Current volume - * | 0x00131 - 0x00131: Is channel dead? - * | 0x00132 - 0x00132: Is channel high? - * | 0x00133 - 0x00133: Reserved - * | 0x00134 - 0x00137: Next envelope step - * | 0x00137 - 0x0013B: Next square wave step - * | 0x0013C - 0x0013G: Next sweep step - * | 0x00140 - 0x00143: Channel end cycle - * | 0x00144 - 0x00147: Next event - * 0x00148 - 0x0015F: Audio channel 2/4 state - * | 0x00148 - 0x00148: Current volume - * | 0x00149 - 0x00149: Is channel dead? - * | 0x0014A - 0x0014A: Is channel high? - * | 0x0014B - 0x0014B: Reserved - * | 0x0014C - 0x0014F: Next envelope step - * | 0x00150 - 0x00153: Next square wave step - * | 0x00154 - 0x00157: Audio channel 4 LFSR - * | 0x00158 - 0x0015B: Channel end cycle - * | 0x0015C - 0x0015F: Next Event - * 0x00160 - 0x0017F: Audio channel 3 wave banks - * 0x00180 - 0x0019F: Audio FIFO 1 - * 0x001A0 - 0x001BF: Audio FIFO 2 - * 0x001C0 - 0x001DF: Audio miscellaneous state - * | 0x001C0 - 0x001C3: Next event - * | 0x001C4 - 0x001C7: Event diff - * | 0x001C8 - 0x001CB: Next channel 3 event - * | 0x001CC - 0x001CF: Next channel 4 event - * | 0x001D0 - 0x001D3: Next sample - * | 0x001D4 - 0x001D7: FIFO size - * | 0x001D8 - 0x001DF: Reserved + * 0x00130 - 0x00143: Audio channel 1 state + * | 0x00130 - 0x00133: Next envelope step + * | 0x00134 - 0x00137: Next square wave step + * | 0x00138 - 0x0013B: Next sweep step + * | 0x0013C - 0x0013F: Channel end cycle + * | 0x00140 - 0x00143: Next event + * 0x00144 - 0x00153: Audio channel 2 state + * | 0x00144 - 0x00147: Next envelope step + * | 0x00148 - 0x0014B: Next square wave step + * | 0x0014C - 0x0014F: Channel end cycle + * | 0x00150 - 0x00153: Next event + * 0x00154 - 0x0017B: Audio channel 3 state + * | 0x00154 - 0x00173: Wave banks + * | 0x00174 - 0x00177: Channel end cycle + * | 0x00178 - 0x0017B: Next event + * 0x0017C - 0x0018B: Audio channel 4 state + * | 0x0017C - 0x0017F: Linear feedback shift register state + * | 0x00180 - 0x00183: Next enveleope step + * | 0x00184 - 0x00187: Channel end cycle + * | 0x00188 - 0x0018B: Next event + * 0x0018C - 0x001AB: Audio FIFO 1 + * 0x001AC - 0x001CB: Audio FIFO 2 + * 0x001CC - 0x001DF: Audio miscellaneous state + * | 0x001CC - 0x001CF: Next event + * | 0x001D0 - 0x001D3: Event diff + * | 0x001D4 - 0x001D7: Next sample + * | 0x001D8 - 0x001DB: FIFO size + * | 0x001DC - 0x001DC: Channel 1 envelope state + * | bits 0 - 3: Current volume + * | bit 4: Is dead? + * | bit 5: Is high? + * | bits 6 - 7: Reserved + * | 0x001DD - 0x001DD: Channel 2 envelope state + * | bits 0 - 3: Current volume + * | bit 4: Is dead? + * | bit 5: Is high? + * | bits 6 - 7: Reserved + * | 0x001DE - 0x001DE: Channel 4 envelope state + * | bits 0 - 3: Current volume + * | bit 4: Is dead? + * | bits 5 - 7: Reserved + * | 0x001DF - 0x001DF: Reserved * 0x001E0 - 0x001FF: Video miscellaneous state * | 0x001E0 - 0x001E3: Next event * | 0x001E4 - 0x001E7: Event diff @@ -139,10 +150,6 @@ struct GBASerializedState { struct { struct { - int8_t volume; - int8_t dead; - int8_t hi; - int8_t : 8; int32_t envelopeNextStep; int32_t waveNextStep; int32_t sweepNextStep; @@ -150,27 +157,40 @@ struct GBASerializedState { int32_t nextEvent; } ch1; struct { - int8_t volume; - int8_t dead; - int8_t hi; - int8_t : 8; int32_t envelopeNextStep; int32_t waveNextStep; - int32_t ch4Lfsr; int32_t endTime; int32_t nextEvent; } ch2; - uint32_t ch3[8]; + struct { + uint32_t wavebanks[8]; + int32_t endTime; + int32_t nextEvent; + } ch3; + struct { + int32_t lfsr; + int32_t envelopeNextStep; + int32_t endTime; + int32_t nextEvent; + } ch4; uint32_t fifoA[8]; uint32_t fifoB[8]; int32_t nextEvent; int32_t eventDiff; - int32_t nextCh3; - int32_t nextCh4; int32_t nextSample; int32_t fifoSize; - int32_t : 32; - int32_t : 32; + unsigned ch1Volume : 4; + unsigned ch1Dead : 1; + unsigned ch1Hi : 1; + unsigned : 2; + unsigned ch2Volume : 4; + unsigned ch2Dead : 1; + unsigned ch2Hi : 1; + unsigned : 2; + unsigned ch4Volume : 4; + unsigned ch4Dead : 1; + unsigned : 3; + unsigned : 8; } audio; struct {