diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp index dbe74da60b..24e470cf91 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp @@ -82,6 +82,7 @@ IUCode* CDSPHandler::GetUCode() void CDSPHandler::SetUCode(u32 _crc) { delete m_pUCode; + m_pUCode = NULL; m_MailHandler.Clear(); m_pUCode = UCodeFactory(_crc, m_MailHandler); diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/HLEMixer.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/HLEMixer.cpp index 90b4055bc8..c23a278e60 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/HLEMixer.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/HLEMixer.cpp @@ -23,7 +23,7 @@ void HLEMixer::MixUCode(short *samples, int numSamples) { // if this was called directly from the HLE, and not by timeout if (g_Config.m_EnableHLEAudio && IsHLEReady()) { - IUCode* pUCode = CDSPHandler::GetInstance().GetUCode(); + IUCode *pUCode = CDSPHandler::GetInstance().GetUCode(); if (pUCode && samples) pUCode->MixAdd(samples, numSamples); } diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.cpp index 047e61c85c..ebe3d431f5 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.cpp @@ -93,4 +93,41 @@ void CMailHandler::Update() } } +void CMailHandler::DoState(PointerWrap &p) +{ + if (p.GetMode() == PointerWrap::MODE_READ) + { + Clear(); + int sz; + p.Do(sz); + for (int i = 0; i < sz; i++) + { + u32 mail; + p.Do(mail); + m_Mails.push(mail); + } + } + else // WRITE and MEASURE + { + std::queue temp; + int sz = m_Mails.size(); + p.Do(sz); + for (int i = 0; i < sz; i++) + { + u32 value = m_Mails.front(); + m_Mails.pop(); + p.Do(value); + temp.push(value); + } + if (!m_Mails.empty()) + PanicAlert("CMailHandler::DoState - WTF?"); + // Restore queue. + for (int i = 0; i < sz; i++) + { + u32 value = temp.front(); + temp.pop(); + m_Mails.push(value); + } + } +} diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.h b/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.h index 8a017e93ce..ac60967f20 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.h +++ b/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.h @@ -21,6 +21,7 @@ #include #include "Common.h" +#include "ChunkFile.h" class CMailHandler { @@ -31,6 +32,7 @@ public: void PushMail(u32 _Mail); void Clear(); void Halt(bool _Halt); + void DoState(PointerWrap &p); bool IsEmpty(); u16 ReadDSPMailboxHigh(); diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp index 8032dc7bfc..bfbdde2686 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp @@ -445,9 +445,16 @@ void CUCode_Zelda::ExecuteList() } -void CUCode_Zelda::DoState(PointerWrap &p) { +void CUCode_Zelda::DoState(PointerWrap &p) +{ + // It's bad if we try to save during Mix() + m_csMix.Enter(); + p.Do(m_CRC); + p.Do(m_AFCCoefTable); + p.Do(m_MiscTable); + p.Do(m_bSyncInProgress); p.Do(m_MaxVoice); p.Do(m_SyncFlags); @@ -483,4 +490,8 @@ void CUCode_Zelda::DoState(PointerWrap &p) { p.Do(m_NumPBs); p.Do(m_PBAddress); p.Do(m_PBAddress2); + + m_rMailHandler.DoState(p); + + m_csMix.Leave(); } diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h index be3cc3e5f4..f7687b8d98 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h @@ -273,7 +273,9 @@ private: void RenderSynth_RectWave(ZeldaVoicePB &PB, s32* _Buffer, int _Size); void RenderSynth_SawWave(ZeldaVoicePB &PB, s32* _Buffer, int _Size); + void RenderVoice_PCM8(ZeldaVoicePB& PB, s16* _Buffer, int _Size); void RenderVoice_PCM16(ZeldaVoicePB& PB, s16* _Buffer, int _Size); + void RenderVoice_AFC(ZeldaVoicePB& PB, s16* _Buffer, int _Size); void RenderVoice_Raw(ZeldaVoicePB& PB, s16* _Buffer, int _Size); diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Voice.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Voice.cpp index 91193dbbdd..bb70a7d617 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Voice.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Voice.cpp @@ -223,7 +223,7 @@ restart: { PB.ReachedEnd = 0; - // HACK: Looping doesn't work. + // HACK: AFC looping doesn't work. if (true || PB.RepeatMode == 0) { PB.KeyOff = 1; @@ -252,7 +252,7 @@ restart: // Prefill the decode buffer. AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format); - PB.CurAddr += 9; + PB.CurAddr += PB.Format; // 9 or 5 u32 SamplePosition = PB.Length - PB.RemLength; while (sampleCount < _RealSize) @@ -275,7 +275,7 @@ restart: prev_addr = PB.CurAddr; AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format); - PB.CurAddr += 9; + PB.CurAddr += PB.Format; // 9 or 5 } } @@ -310,6 +310,8 @@ void CUCode_Zelda::RenderVoice_Raw(ZeldaVoicePB &PB, s16 *_Buffer, int _Size) // Decoder0x21Core starts here. u32 AX0 = _RealSize; + // ERROR_LOG(DSPHLE, "0x21 volume mode: %i , stop: %i ", PB.VolumeMode, PB.StopOnSilence); + // The PB.StopOnSilence check is a hack, we should check the buffers and enter this // only when the buffer is completely 0 (i.e. when the music has finished fading out) if (PB.StopOnSilence || PB.RemLength < _RealSize) @@ -343,7 +345,7 @@ void CUCode_Zelda::RenderVoice_Raw(ZeldaVoicePB &PB, s16 *_Buffer, int _Size) { // There's something wrong with this looping code. - // ERROR_LOG(DSPHLE, "Raw loop: ReadAudio size = %04x 34:%04x %08x", PB.Unk36[0], PB.raw[0x34 ^ 1], (int)ACC0); + ERROR_LOG(DSPHLE, "Raw loop: ReadAudio size = %04x 34:%04x %08x", PB.Unk36[0], PB.raw[0x34 ^ 1], (int)ACC0); Decoder21_ReadAudio(PB, PB.Unk36[0], _Buffer); u32 ACC0 = _Size << 16; @@ -478,8 +480,9 @@ void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _Righ // These are more "synth" formats - square wave, saw wave etc. case 0x0002: + case 0x0007: // Example: Pikmin 2 in a cave, not sure what sound it is. case 0x000c: // Example: beam of death/yellow force-field in Temple of the Gods, ZWW - WARN_LOG(DSPHLE, "Synthesizing 0x%04x", PB.Format); + WARN_LOG(DSPHLE, "Not synthesizing unreversed-engineerd format 0x%04x", PB.Format); break; default: @@ -559,7 +562,7 @@ ContinueWithBlock: for (int count = 0; count < 8; count++) { // The 8 buffers to mix to: 0d00, 0d60, 0f40 0ca0 0e80 0ee0 0c00 0c50 - // We just mix to the first to and call it stereo :p + // We just mix to the first two and call it stereo :p int value = b00[0x4 + count]; int delta = b00[0xC + count] << 11; @@ -648,7 +651,7 @@ ContinueWithBlock: // size is in stereo samples. void CUCode_Zelda::MixAdd(short *_Buffer, int _Size) { - // PanicAlert("mixadd"); + m_csMix.Enter(); // Safety check if (_Size > 256 * 1024 - 8) _Size = 256 * 1024 - 8; @@ -695,4 +698,5 @@ void CUCode_Zelda::MixAdd(short *_Buffer, int _Size) _Buffer += 2; } + m_csMix.Leave(); } \ No newline at end of file diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.h index fe9ed08e05..9cf03fb3ce 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.h +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.h @@ -20,6 +20,7 @@ #include "Common.h" #include "ChunkFile.h" +#include "Thread.h" #define UCODE_ROM 0x0000000 #define UCODE_INIT_AUDIO_SYSTEM 0x0000001 @@ -46,6 +47,7 @@ public: protected: CMailHandler& m_rMailHandler; + Common::CriticalSection m_csMix; }; extern IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler);