From 7652fe9f7ae13b4e3d5b29e0ebf869d7503b22cc Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 10 Aug 2020 18:11:54 -0700 Subject: [PATCH] GB Audio: Fix serializing sweep time --- CHANGES | 1 + include/mgba/internal/gb/serialize.h | 27 +++++++++++++++++---------- include/mgba/internal/gba/serialize.h | 21 +++++++++++++-------- src/gb/audio.c | 9 +++++++++ 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/CHANGES b/CHANGES index 1a1972ec2..c9879267b 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,7 @@ Emulation fixes: - ARM: Fix STR storing PC after address calculation - GB: Partially fix timing for skipped BIOS - GB Audio: Fix initial sweep state + - GB Audio: Fix serializing sweep time - GB MBC: Fix MBC1 mode changing behavior - GB Video: Fix state after skipping BIOS (fixes mgba.io/i/1715 and mgba.io/i/1716) - GBA: Fix timing advancing too quickly in rare cases diff --git a/include/mgba/internal/gb/serialize.h b/include/mgba/internal/gb/serialize.h index 7d3a73be5..6df5d2859 100644 --- a/include/mgba/internal/gb/serialize.h +++ b/include/mgba/internal/gb/serialize.h @@ -59,7 +59,9 @@ mLOG_DECLARE_CATEGORY(GB_STATE); * | bits 21 - 31: Reserved * | 0x0004C - 0x0004F: Next frame * | 0x00050 - 0x00053: Next channel 3 fade - * | 0x00054 - 0x00057: Reserved + * | 0x00054 - 0x00057: Sweep state + * | bits 0 - 2: Timesteps + * | bits 3 - 31: Reserved * | 0x00058 - 0x0005B: Next event * 0x0005C - 0x0006B: Audio channel 2 state * | 0x0005C - 0x0005F: Envelepe timing @@ -87,22 +89,23 @@ mLOG_DECLARE_CATEGORY(GB_STATE); * | bits 0 - 3: Current volume * | bits 4 - 5: Is dead? * | bit 6: Is high? +* | bit 7: Reserved * | 0x000A5: Channel 2 envelope state * | bits 0 - 3: Current volume * | bits 4 - 5: Is dead? * | bit 6: Is high? -* | bits 7: Reserved +* | bit 7: Reserved * | 0x000A6: Channel 4 envelope state * | bits 0 - 3: Current volume * | bits 4 - 5: Is dead? - * | bit 6: Is high? -* | bits 7: Reserved + * | bits 6 - 7: Current frame (continued) * | 0x000A7: Miscellaneous audio flags - * | bits 0 - 3: Current frame - * | bit 4: Is channel 1 sweep enabled? - * | bit 5: Has channel 1 sweep occurred? - * | bit 6: Is channel 3's memory readable? - * | bit 7: Reserved + * | bit 0: Current frame (continuation) + * | bit 1: Is channel 1 sweep enabled? + * | bit 2: Has channel 1 sweep occurred? + * | bit 3: Is channel 3's memory readable? + * | bit 4: Skip frame + * | bits 5 - 7: Reserved * | 0x000A8 - 0x000AB: Left capacitor charge * | 0x000AC - 0x000AF: Right capacitor charge * | 0x000B0 - 0x000B3: Next sample @@ -203,12 +206,16 @@ DECL_BITS(GBSerializedAudioEnvelope, Length, 0, 7); DECL_BITS(GBSerializedAudioEnvelope, NextStep, 7, 3); DECL_BITS(GBSerializedAudioEnvelope, Frequency, 10, 11); + +DECL_BITFIELD(GBSerializedAudioSweep, uint32_t); +DECL_BITS(GBSerializedAudioSweep, Time, 0, 3); + struct GBSerializedPSGState { struct { GBSerializedAudioEnvelope envelope; int32_t nextFrame; int32_t nextCh3Fade; - int32_t reserved; + GBSerializedAudioSweep sweep; uint32_t nextEvent; } ch1; struct { diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index e9ef92cee..24cc1b85c 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -41,7 +41,10 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * | bits 10 - 20: Shadow frequency register * | bits 21 - 31: Reserved * | 0x00134 - 0x00137: Next frame - * | 0x00138 - 0x0013F: Reserved + * | 0x00138 - 0x0013B: Next channel 3 fade + * | 0x0013C - 0x0013F: Sweep state + * | bits 0 - 2: Timesteps + * | bits 3 - 7: Reserved * | 0x00140 - 0x00143: Next event * 0x00144 - 0x00153: Audio channel 2 state * | 0x00144 - 0x00147: Envelepe timing @@ -75,21 +78,23 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * | bits 0 - 3: Current volume * | bits 4 - 5: Is dead? * | bit 6: Is high? +* | bit 7: Reserved * | 0x001DD - 0x001DD: Channel 2 envelope state * | bits 0 - 3: Current volume * | bits 4 - 5: Is dead? * | bit 6: Is high? -* | bits 7: Reserved +* | bit 7: Reserved * | 0x001DE - 0x001DE: Channel 4 envelope state * | bits 0 - 3: Current volume * | bits 4 - 5: Is dead? - * | bit 6: Is high? -* | bits 7: Reserved + * | bits 6 - 7: Current frame (continued) * | 0x001DF - 0x001DF: Miscellaneous audio flags - * | bits 0 - 3: Current frame - * | bit 4: Is channel 1 sweep enabled? - * | bit 5: Has channel 1 sweep occurred? - * | bits 6 - 7: Reserved + * | bit 0: Current frame (continuation) + * | bit 1: Is channel 1 sweep enabled? + * | bit 2: Has channel 1 sweep occurred? + * | bit 3: Is channel 3's memory readable? + * | bit 4: Skip frame + * | bits 5 - 7: Reserved * 0x001E0 - 0x001FF: Video miscellaneous state * | 0x001E0 - 0x001E3: Next event * | 0x001E4 - 0x001F7: Reserved diff --git a/src/gb/audio.c b/src/gb/audio.c index 9a2a2aa67..be3b8a6b3 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -964,6 +964,7 @@ static void _updateChannel4(struct mTiming* timing, void* user, uint32_t cyclesL void GBAudioPSGSerialize(const struct GBAudio* audio, struct GBSerializedPSGState* state, uint32_t* flagsOut) { uint32_t flags = 0; + uint32_t sweep = 0; uint32_t ch1Flags = 0; uint32_t ch2Flags = 0; uint32_t ch4Flags = 0; @@ -980,7 +981,9 @@ void GBAudioPSGSerialize(const struct GBAudio* audio, struct GBSerializedPSGStat ch1Flags = GBSerializedAudioEnvelopeSetLength(ch1Flags, audio->ch1.control.length); ch1Flags = GBSerializedAudioEnvelopeSetNextStep(ch1Flags, audio->ch1.envelope.nextStep); ch1Flags = GBSerializedAudioEnvelopeSetFrequency(ch1Flags, audio->ch1.sweep.realFrequency); + sweep = GBSerializedAudioSweepSetTime(sweep, audio->ch1.sweep.time & 7); STORE_32LE(ch1Flags, 0, &state->ch1.envelope); + STORE_32LE(sweep, 0, &state->ch1.sweep); STORE_32LE(audio->ch1Event.when - mTimingCurrentTime(audio->timing), 0, &state->ch1.nextEvent); flags = GBSerializedAudioFlagsSetCh2Volume(flags, audio->ch2.envelope.currentVolume); @@ -1011,6 +1014,7 @@ void GBAudioPSGSerialize(const struct GBAudio* audio, struct GBSerializedPSGStat void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGState* state, const uint32_t* flagsIn) { uint32_t flags; + uint32_t sweep; uint32_t ch1Flags = 0; uint32_t ch2Flags = 0; uint32_t ch4Flags = 0; @@ -1032,11 +1036,16 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt audio->skipFrame = GBSerializedAudioFlagsGetSkipFrame(flags); LOAD_32LE(ch1Flags, 0, &state->ch1.envelope); + LOAD_32LE(sweep, 0, &state->ch1.sweep); audio->ch1.envelope.currentVolume = GBSerializedAudioFlagsGetCh1Volume(flags); audio->ch1.envelope.dead = GBSerializedAudioFlagsGetCh1Dead(flags); audio->ch1.control.hi = GBSerializedAudioFlagsGetCh1Hi(flags); audio->ch1.sweep.enable = GBSerializedAudioFlagsGetCh1SweepEnabled(flags); audio->ch1.sweep.occurred = GBSerializedAudioFlagsGetCh1SweepOccurred(flags); + audio->ch1.sweep.time = GBSerializedAudioSweepGetTime(sweep); + if (!audio->ch1.sweep.time) { + audio->ch1.sweep.time = 8; + } audio->ch1.control.length = GBSerializedAudioEnvelopeGetLength(ch1Flags); audio->ch1.envelope.nextStep = GBSerializedAudioEnvelopeGetNextStep(ch1Flags); audio->ch1.sweep.realFrequency = GBSerializedAudioEnvelopeGetFrequency(ch1Flags);