From 68f628a211773fe478dc38b2689f848f9572d881 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 May 2022 20:40:14 -0700 Subject: [PATCH] GB Audio: Redo channels 1 and 2 --- include/mgba/internal/gb/audio.h | 6 +- include/mgba/internal/gb/serialize.h | 19 ++-- include/mgba/internal/gba/serialize.h | 15 +-- src/gb/audio.c | 145 +++++++++----------------- src/gb/io.c | 1 + src/gb/serialize.c | 2 +- src/gba/serialize.c | 2 +- 7 files changed, 76 insertions(+), 114 deletions(-) diff --git a/include/mgba/internal/gb/audio.h b/include/mgba/internal/gb/audio.h index 4f4fdef32..3e2d4c2f8 100644 --- a/include/mgba/internal/gb/audio.h +++ b/include/mgba/internal/gb/audio.h @@ -87,7 +87,6 @@ struct GBAudioSquareControl { int frequency; int length; bool stop; - int hi; }; struct GBAudioSweep { @@ -104,6 +103,8 @@ struct GBAudioSquareChannel { struct GBAudioSweep sweep; struct GBAudioEnvelope envelope; struct GBAudioSquareControl control; + int32_t lastUpdate; + uint8_t index; int8_t sample; }; @@ -194,8 +195,6 @@ struct GBAudio { enum GBAudioStyle style; struct mTimingEvent frameEvent; - struct mTimingEvent ch1Event; - struct mTimingEvent ch2Event; struct mTimingEvent ch3Event; struct mTimingEvent ch3Fade; struct mTimingEvent ch4Event; @@ -239,6 +238,7 @@ void GBAudioWriteNR50(struct GBAudio* audio, uint8_t); void GBAudioWriteNR51(struct GBAudio* audio, uint8_t); void GBAudioWriteNR52(struct GBAudio* audio, uint8_t); +void GBAudioRun(struct GBAudio* audio, int32_t timestamp); void GBAudioUpdateFrame(struct GBAudio* audio); void GBAudioUpdateChannel4(struct GBAudio* audio); diff --git a/include/mgba/internal/gb/serialize.h b/include/mgba/internal/gb/serialize.h index 6973d4e57..6043cc919 100644 --- a/include/mgba/internal/gb/serialize.h +++ b/include/mgba/internal/gb/serialize.h @@ -19,7 +19,7 @@ extern MGBA_EXPORT const uint32_t GBSavestateVersion; mLOG_DECLARE_CATEGORY(GB_STATE); /* Savestate format: - * 0x00000 - 0x00003: Version Magic (0x01000002) + * 0x00000 - 0x00003: Version Magic (0x00400003) * 0x00004 - 0x00007: ROM CRC32 * 0x00008: Game Boy model * 0x00009 - 0x0000B: Reserved (leave zero) @@ -56,20 +56,23 @@ mLOG_DECLARE_CATEGORY(GB_STATE); * | bits 0 - 6: Remaining length * | bits 7 - 9: Next step * | bits 10 - 20: Shadow frequency register - * | bits 21 - 31: Reserved + * | bits 21 - 23: Duty index + * | bits 24 - 31: Reserved * | 0x0004C - 0x0004F: Next frame * | 0x00050 - 0x00053: Next channel 3 fade * | 0x00054 - 0x00057: Sweep state * | bits 0 - 2: Timesteps * | bits 3 - 31: Reserved - * | 0x00058 - 0x0005B: Next event + * | 0x00058 - 0x0005B: Last update * 0x0005C - 0x0006B: Audio channel 2 state * | 0x0005C - 0x0005F: Envelepe timing * | bits 0 - 2: Remaining length * | bits 3 - 5: Next step - * | bits 6 - 31: Reserved + * | bits 6 - 20: Reserved + * | bits 21 - 23: Duty index + * | bits 24 - 31: Reserved * | 0x00060 - 0x00067: Reserved - * | 0x00068 - 0x0006B: Next event + * | 0x00068 - 0x0006B: Last update * 0x0006C - 0x00093: Audio channel 3 state * | 0x0006C - 0x0008B: Wave banks * | 0x0008C - 0x0008D: Remaining length @@ -208,7 +211,7 @@ DECL_BITFIELD(GBSerializedAudioEnvelope, uint32_t); DECL_BITS(GBSerializedAudioEnvelope, Length, 0, 7); DECL_BITS(GBSerializedAudioEnvelope, NextStep, 7, 3); DECL_BITS(GBSerializedAudioEnvelope, Frequency, 10, 11); - +DECL_BITS(GBSerializedAudioEnvelope, DutyIndex, 21, 3); DECL_BITFIELD(GBSerializedAudioSweep, uint32_t); DECL_BITS(GBSerializedAudioSweep, Time, 0, 3); @@ -219,12 +222,12 @@ struct GBSerializedPSGState { int32_t nextFrame; int32_t nextCh3Fade; GBSerializedAudioSweep sweep; - uint32_t nextEvent; + uint32_t lastUpdate; } ch1; struct { GBSerializedAudioEnvelope envelope; int32_t reserved[2]; - int32_t nextEvent; + uint32_t lastUpdate; } ch2; struct { uint32_t wavebanks[8]; diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index 203c4fb0c..b25b3aec0 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -20,7 +20,7 @@ extern MGBA_EXPORT const uint32_t GBASavestateVersion; mLOG_DECLARE_CATEGORY(GBA_STATE); /* Savestate format: - * 0x00000 - 0x00003: Version Magic (0x01000004) + * 0x00000 - 0x00003: Version Magic (0x01000005) * 0x00004 - 0x00007: BIOS checksum (e.g. 0xBAAE187F for official BIOS) * 0x00008 - 0x0000B: ROM CRC32 * 0x0000C - 0x0000F: Master cycles @@ -39,25 +39,28 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * | bits 0 - 6: Remaining length * | bits 7 - 9: Next step * | bits 10 - 20: Shadow frequency register - * | bits 21 - 31: Reserved + * | bits 21 - 23: Duty index + * | bits 24 - 31: Reserved * | 0x00134 - 0x00137: Next frame * | 0x00138 - 0x0013B: Next channel 3 fade * | 0x0013C - 0x0013F: Sweep state * | bits 0 - 2: Timesteps * | bits 3 - 7: Reserved - * | 0x00140 - 0x00143: Next event + * | 0x00140 - 0x00143: Last update * 0x00144 - 0x00153: Audio channel 2 state * | 0x00144 - 0x00147: Envelepe timing * | bits 0 - 2: Remaining length * | bits 3 - 5: Next step - * | bits 6 - 31: Reserved + * | bits 6 - 20: Reserved + * | bits 21 - 23: Duty index + * | bits 24 - 31: Reserved * | 0x00148 - 0x0014F: Reserved - * | 0x00150 - 0x00153: Next event + * | 0x00150 - 0x00153: Last update * 0x00154 - 0x0017B: Audio channel 3 state * | 0x00154 - 0x00173: Wave banks * | 0x00174 - 0x00175: Remaining length * | 0x00176 - 0x00177: Reserved - * | 0x00178 - 0x0017B: Next event + * | 0x00178 - 0x0017B: Last update * 0x0017C - 0x0018B: Audio channel 4 state * | 0x0017C - 0x0017F: Linear feedback shift register state * | 0x00180 - 0x00183: Envelepe timing diff --git a/src/gb/audio.c b/src/gb/audio.c index 5dc40ac62..e65bd106a 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -35,19 +35,21 @@ static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope); static bool _updateSweep(struct GBAudioSquareChannel* sweep, bool initial); static void _updateSquareSample(struct GBAudioSquareChannel* ch); -static int32_t _updateSquareChannel(struct GBAudioSquareChannel* ch); - -static int32_t _cyclesToInvert(struct GBAudioSquareChannel* ch); static int16_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch); static void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate); -static void _updateChannel1(struct mTiming* timing, void* user, uint32_t cyclesLate); -static void _updateChannel2(struct mTiming* timing, void* user, uint32_t cyclesLate); static void _updateChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate); static void _fadeChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate); static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate); +static const int _squareChannelDuty[4][8] = { + { 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 0, 0, 0, 1, 1, 1 }, + { 0, 1, 1, 1, 1, 1, 1, 0 }, +}; + void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAudioStyle style) { audio->samples = samples; audio->left = blip_new(BLIP_BUFFER_SIZE); @@ -73,14 +75,6 @@ void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAu audio->frameEvent.name = "GB Audio Frame Sequencer"; audio->frameEvent.callback = _updateFrame; audio->frameEvent.priority = 0x10; - audio->ch1Event.context = audio; - audio->ch1Event.name = "GB Audio Channel 1"; - audio->ch1Event.callback = _updateChannel1; - audio->ch1Event.priority = 0x11; - audio->ch2Event.context = audio; - audio->ch2Event.name = "GB Audio Channel 2"; - audio->ch2Event.callback = _updateChannel2; - audio->ch2Event.priority = 0x12; audio->ch3Event.context = audio; audio->ch3Event.name = "GB Audio Channel 3"; audio->ch3Event.callback = _updateChannel3; @@ -106,8 +100,6 @@ void GBAudioDeinit(struct GBAudio* audio) { void GBAudioReset(struct GBAudio* audio) { mTimingDeschedule(audio->timing, &audio->frameEvent); - mTimingDeschedule(audio->timing, &audio->ch1Event); - mTimingDeschedule(audio->timing, &audio->ch2Event); mTimingDeschedule(audio->timing, &audio->ch3Event); mTimingDeschedule(audio->timing, &audio->ch3Fade); mTimingDeschedule(audio->timing, &audio->ch4Event); @@ -168,32 +160,35 @@ void GBAudioResizeBuffer(struct GBAudio* audio, size_t samples) { } void GBAudioWriteNR10(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); if (!_writeSweep(&audio->ch1.sweep, value)) { - mTimingDeschedule(audio->timing, &audio->ch1Event); audio->playingCh1 = false; *audio->nr52 &= ~0x0001; } } void GBAudioWriteNR11(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); _writeDuty(&audio->ch1.envelope, value); audio->ch1.control.length = 64 - audio->ch1.envelope.length; } void GBAudioWriteNR12(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); if (!_writeEnvelope(&audio->ch1.envelope, value, audio->style)) { - mTimingDeschedule(audio->timing, &audio->ch1Event); audio->playingCh1 = false; *audio->nr52 &= ~0x0001; } } void GBAudioWriteNR13(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch1.control.frequency &= 0x700; audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value); } void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch1.control.frequency &= 0xFF; audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8); bool wasStop = audio->ch1.control.stop; @@ -201,12 +196,10 @@ void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) { if (!wasStop && audio->ch1.control.stop && audio->ch1.control.length && !(audio->frame & 1)) { --audio->ch1.control.length; if (audio->ch1.control.length == 0) { - mTimingDeschedule(audio->timing, &audio->ch1Event); audio->playingCh1 = false; } } if (GBAudioRegisterControlIsRestart(value << 8)) { - bool wasDead = !audio->playingCh1; audio->playingCh1 = _resetEnvelope(&audio->ch1.envelope); audio->ch1.sweep.realFrequency = audio->ch1.control.frequency; _resetSweep(&audio->ch1.sweep); @@ -220,35 +213,33 @@ void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) { } } _updateSquareSample(&audio->ch1); - if (wasDead && audio->playingCh1) { - mTimingSchedule(audio->timing, &audio->ch1Event, _cyclesToInvert(&audio->ch1)); - } else if (!audio->playingCh1) { - mTimingDeschedule(audio->timing, &audio->ch1Event); - } } *audio->nr52 &= ~0x0001; *audio->nr52 |= audio->playingCh1; } void GBAudioWriteNR21(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); _writeDuty(&audio->ch2.envelope, value); audio->ch2.control.length = 64 - audio->ch2.envelope.length; } void GBAudioWriteNR22(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); if (!_writeEnvelope(&audio->ch2.envelope, value, audio->style)) { - mTimingDeschedule(audio->timing, &audio->ch2Event); audio->playingCh2 = false; *audio->nr52 &= ~0x0002; } } void GBAudioWriteNR23(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch2.control.frequency &= 0x700; audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value); } void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch2.control.frequency &= 0xFF; audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8); bool wasStop = audio->ch2.control.stop; @@ -256,12 +247,10 @@ void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) { if (!wasStop && audio->ch2.control.stop && audio->ch2.control.length && !(audio->frame & 1)) { --audio->ch2.control.length; if (audio->ch2.control.length == 0) { - mTimingDeschedule(audio->timing, &audio->ch2Event); audio->playingCh2 = false; } } if (GBAudioRegisterControlIsRestart(value << 8)) { - bool wasDead = !audio->playingCh2; audio->playingCh2 = _resetEnvelope(&audio->ch2.envelope); if (!audio->ch2.control.length) { @@ -271,11 +260,6 @@ void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) { } } _updateSquareSample(&audio->ch2); - if (wasDead && audio->playingCh2) { - mTimingSchedule(audio->timing, &audio->ch2Event, _cyclesToInvert(&audio->ch2)); - } else if (!audio->playingCh2) { - mTimingDeschedule(audio->timing, &audio->ch2Event); - } } *audio->nr52 &= ~0x0002; *audio->nr52 |= audio->playingCh2 << 1; @@ -496,6 +480,26 @@ void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) { } } +void GBAudioRun(struct GBAudio* audio, int32_t timestamp) { + if (!audio->enable) { + return; + } + if (audio->playingCh1) { + int period = 4 * (2048 - audio->ch1.control.frequency) * audio->timingFactor; + int32_t diff = (timestamp - audio->ch1.lastUpdate) / period; + audio->ch1.index = (audio->ch1.index + diff) & 7; + audio->ch1.lastUpdate += diff * period; + _updateSquareSample(&audio->ch1); + } + if (audio->playingCh2) { + int period = 4 * (2048 - audio->ch2.control.frequency) * audio->timingFactor; + int32_t diff = (timestamp - audio->ch2.lastUpdate) / period; + audio->ch2.index = (audio->ch2.index + diff) & 7; + audio->ch2.lastUpdate += diff * period; + _updateSquareSample(&audio->ch2); + } +} + void GBAudioUpdateFrame(struct GBAudio* audio) { if (!audio->enable) { return; @@ -504,6 +508,8 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { audio->skipFrame = false; return; } + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + int frame = (audio->frame + 1) & 7; audio->frame = frame; @@ -516,9 +522,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { audio->playingCh1 = _updateSweep(&audio->ch1, false); *audio->nr52 &= ~0x0001; *audio->nr52 |= audio->playingCh1; - if (!audio->playingCh1) { - mTimingDeschedule(audio->timing, &audio->ch1Event); - } } } // Fall through @@ -527,7 +530,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { if (audio->ch1.control.length && audio->ch1.control.stop) { --audio->ch1.control.length; if (audio->ch1.control.length == 0) { - mTimingDeschedule(audio->timing, &audio->ch1Event); audio->playingCh1 = 0; *audio->nr52 &= ~0x0001; } @@ -536,7 +538,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { if (audio->ch2.control.length && audio->ch2.control.stop) { --audio->ch2.control.length; if (audio->ch2.control.length == 0) { - mTimingDeschedule(audio->timing, &audio->ch2Event); audio->playingCh2 = 0; *audio->nr52 &= ~0x0002; } @@ -565,9 +566,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { --audio->ch1.envelope.nextStep; if (audio->ch1.envelope.nextStep == 0) { _updateEnvelope(&audio->ch1.envelope); - if (audio->ch1.envelope.dead == 2) { - mTimingDeschedule(audio->timing, &audio->ch1Event); - } _updateSquareSample(&audio->ch1); } } @@ -576,9 +574,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { --audio->ch2.envelope.nextStep; if (audio->ch2.envelope.nextStep == 0) { _updateEnvelope(&audio->ch2.envelope); - if (audio->ch2.envelope.dead == 2) { - mTimingDeschedule(audio->timing, &audio->ch2Event); - } _updateSquareSample(&audio->ch2); } } @@ -626,6 +621,7 @@ void GBAudioUpdateChannel4(struct GBAudio* audio) { } void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); int dcOffset = audio->style == GB_AUDIO_GBA ? 0 : -0x8; int sampleLeft = dcOffset; int sampleRight = dcOffset; @@ -775,30 +771,7 @@ bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudi } static void _updateSquareSample(struct GBAudioSquareChannel* ch) { - ch->sample = ch->control.hi * ch->envelope.currentVolume; -} - -static int32_t _updateSquareChannel(struct GBAudioSquareChannel* ch) { - ch->control.hi = !ch->control.hi; - _updateSquareSample(ch); - return _cyclesToInvert(ch); -} - -static int32_t _cyclesToInvert(struct GBAudioSquareChannel* ch) { - int period = 4 * (2048 - ch->control.frequency); - switch (ch->envelope.duty) { - case 0: - return ch->control.hi ? period : period * 7; - case 1: - return ch->control.hi ? period * 2 : period * 6; - case 2: - return period * 4; - case 3: - return ch->control.hi ? period * 6 : period * 2; - default: - // This should never be hit - return period * 4; - } + ch->sample = _squareChannelDuty[ch->envelope.duty][ch->index] * ch->envelope.currentVolume; } static int16_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch) { @@ -870,20 +843,6 @@ static bool _updateSweep(struct GBAudioSquareChannel* ch, bool initial) { return true; } -static void _updateChannel1(struct mTiming* timing, void* user, uint32_t cyclesLate) { - struct GBAudio* audio = user; - struct GBAudioSquareChannel* ch = &audio->ch1; - int cycles = _updateSquareChannel(ch); - mTimingSchedule(timing, &audio->ch1Event, audio->timingFactor * cycles - cyclesLate); -} - -static void _updateChannel2(struct mTiming* timing, void* user, uint32_t cyclesLate) { - struct GBAudio* audio = user; - struct GBAudioSquareChannel* ch = &audio->ch2; - int cycles = _updateSquareChannel(ch); - mTimingSchedule(timing, &audio->ch2Event, audio->timingFactor * cycles - cyclesLate); -} - static void _updateChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate) { struct GBAudio* audio = user; struct GBAudioWaveChannel* ch = &audio->ch3; @@ -971,24 +930,24 @@ void GBAudioPSGSerialize(const struct GBAudio* audio, struct GBSerializedPSGStat flags = GBSerializedAudioFlagsSetCh1Volume(flags, audio->ch1.envelope.currentVolume); flags = GBSerializedAudioFlagsSetCh1Dead(flags, audio->ch1.envelope.dead); - flags = GBSerializedAudioFlagsSetCh1Hi(flags, audio->ch1.control.hi); flags = GBSerializedAudioFlagsSetCh1SweepEnabled(flags, audio->ch1.sweep.enable); flags = GBSerializedAudioFlagsSetCh1SweepOccurred(flags, audio->ch1.sweep.occurred); ch1Flags = GBSerializedAudioEnvelopeSetLength(ch1Flags, audio->ch1.control.length); ch1Flags = GBSerializedAudioEnvelopeSetNextStep(ch1Flags, audio->ch1.envelope.nextStep); ch1Flags = GBSerializedAudioEnvelopeSetFrequency(ch1Flags, audio->ch1.sweep.realFrequency); + ch1Flags = GBSerializedAudioEnvelopeSetDutyIndex(ch1Flags, audio->ch1.index); 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); + STORE_32LE(audio->ch1.lastUpdate - mTimingCurrentTime(audio->timing), 0, &state->ch1.lastUpdate); flags = GBSerializedAudioFlagsSetCh2Volume(flags, audio->ch2.envelope.currentVolume); flags = GBSerializedAudioFlagsSetCh2Dead(flags, audio->ch2.envelope.dead); - flags = GBSerializedAudioFlagsSetCh2Hi(flags, audio->ch2.control.hi); ch2Flags = GBSerializedAudioEnvelopeSetLength(ch2Flags, audio->ch2.control.length); ch2Flags = GBSerializedAudioEnvelopeSetNextStep(ch2Flags, audio->ch2.envelope.nextStep); + ch2Flags = GBSerializedAudioEnvelopeSetDutyIndex(ch2Flags, audio->ch2.index); STORE_32LE(ch2Flags, 0, &state->ch2.envelope); - STORE_32LE(audio->ch2Event.when - mTimingCurrentTime(audio->timing), 0, &state->ch2.nextEvent); + STORE_32LE(audio->ch2.lastUpdate - mTimingCurrentTime(audio->timing), 0, &state->ch2.lastUpdate); flags = GBSerializedAudioFlagsSetCh3Readable(flags, audio->ch3.readable); memcpy(state->ch3.wavebanks, audio->ch3.wavedata32, sizeof(state->ch3.wavebanks)); @@ -1039,7 +998,6 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt 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); @@ -1049,21 +1007,18 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt audio->ch1.control.length = GBSerializedAudioEnvelopeGetLength(ch1Flags); audio->ch1.envelope.nextStep = GBSerializedAudioEnvelopeGetNextStep(ch1Flags); audio->ch1.sweep.realFrequency = GBSerializedAudioEnvelopeGetFrequency(ch1Flags); - LOAD_32LE(when, 0, &state->ch1.nextEvent); - if (audio->ch1.envelope.dead < 2 && audio->playingCh1) { - mTimingSchedule(audio->timing, &audio->ch1Event, when); - } + audio->ch1.index = GBSerializedAudioEnvelopeGetDutyIndex(ch1Flags); + LOAD_32LE(audio->ch1.lastUpdate, 0, &state->ch1.lastUpdate); + audio->ch1.lastUpdate += mTimingCurrentTime(audio->timing); LOAD_32LE(ch2Flags, 0, &state->ch2.envelope); audio->ch2.envelope.currentVolume = GBSerializedAudioFlagsGetCh2Volume(flags); audio->ch2.envelope.dead = GBSerializedAudioFlagsGetCh2Dead(flags); - audio->ch2.control.hi = GBSerializedAudioFlagsGetCh2Hi(flags); audio->ch2.control.length = GBSerializedAudioEnvelopeGetLength(ch2Flags); audio->ch2.envelope.nextStep = GBSerializedAudioEnvelopeGetNextStep(ch2Flags); - LOAD_32LE(when, 0, &state->ch2.nextEvent); - if (audio->ch2.envelope.dead < 2 && audio->playingCh2) { - mTimingSchedule(audio->timing, &audio->ch2Event, when); - } + audio->ch2.index = GBSerializedAudioEnvelopeGetDutyIndex(ch2Flags); + LOAD_32LE(audio->ch2.lastUpdate, 0, &state->ch2.lastUpdate); + audio->ch2.lastUpdate += mTimingCurrentTime(audio->timing); audio->ch3.readable = GBSerializedAudioFlagsGetCh3Readable(flags); // TODO: Big endian? diff --git a/src/gb/io.c b/src/gb/io.c index deed1153f..a948403ec 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -620,6 +620,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) { if (gb->model < GB_MODEL_CGB) { mLOG(GB_IO, GAME_ERROR, "Reading from CGB register FF%02X in DMG mode", address); } else if (gb->audio.enable) { + GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing)); return (gb->audio.ch1.sample) | (gb->audio.ch2.sample << 4); } break; diff --git a/src/gb/serialize.c b/src/gb/serialize.c index d3fd8f12a..ad7ebe756 100644 --- a/src/gb/serialize.c +++ b/src/gb/serialize.c @@ -14,7 +14,7 @@ mLOG_DEFINE_CATEGORY(GB_STATE, "GB Savestate", "gb.serialize"); MGBA_EXPORT const uint32_t GBSavestateMagic = 0x00400000; -MGBA_EXPORT const uint32_t GBSavestateVersion = 0x00000002; +MGBA_EXPORT const uint32_t GBSavestateVersion = 0x00000003; void GBSerialize(struct GB* gb, struct GBSerializedState* state) { STORE_32LE(GBSavestateMagic + GBSavestateVersion, 0, &state->versionMagic); diff --git a/src/gba/serialize.c b/src/gba/serialize.c index a7294b6b5..d2bd5c5e8 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -15,7 +15,7 @@ #include MGBA_EXPORT const uint32_t GBASavestateMagic = 0x01000000; -MGBA_EXPORT const uint32_t GBASavestateVersion = 0x00000004; +MGBA_EXPORT const uint32_t GBASavestateVersion = 0x00000005; mLOG_DEFINE_CATEGORY(GBA_STATE, "GBA Savestate", "gba.serialize");