DSPHLE: Try to make zelda ucode savestates safer (sorry, this'll break your current states, as usual).

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3788 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2009-07-13 20:56:49 +00:00
parent 48a5c4211c
commit fda61d91d5
8 changed files with 68 additions and 9 deletions

View File

@ -82,6 +82,7 @@ IUCode* CDSPHandler::GetUCode()
void CDSPHandler::SetUCode(u32 _crc) void CDSPHandler::SetUCode(u32 _crc)
{ {
delete m_pUCode; delete m_pUCode;
m_pUCode = NULL; m_pUCode = NULL;
m_MailHandler.Clear(); m_MailHandler.Clear();
m_pUCode = UCodeFactory(_crc, m_MailHandler); m_pUCode = UCodeFactory(_crc, m_MailHandler);

View File

@ -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<u32> 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);
}
}
}

View File

@ -21,6 +21,7 @@
#include <queue> #include <queue>
#include "Common.h" #include "Common.h"
#include "ChunkFile.h"
class CMailHandler class CMailHandler
{ {
@ -31,6 +32,7 @@ public:
void PushMail(u32 _Mail); void PushMail(u32 _Mail);
void Clear(); void Clear();
void Halt(bool _Halt); void Halt(bool _Halt);
void DoState(PointerWrap &p);
bool IsEmpty(); bool IsEmpty();
u16 ReadDSPMailboxHigh(); u16 ReadDSPMailboxHigh();

View File

@ -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_CRC);
p.Do(m_AFCCoefTable);
p.Do(m_MiscTable);
p.Do(m_bSyncInProgress); p.Do(m_bSyncInProgress);
p.Do(m_MaxVoice); p.Do(m_MaxVoice);
p.Do(m_SyncFlags); p.Do(m_SyncFlags);
@ -483,4 +490,8 @@ void CUCode_Zelda::DoState(PointerWrap &p) {
p.Do(m_NumPBs); p.Do(m_NumPBs);
p.Do(m_PBAddress); p.Do(m_PBAddress);
p.Do(m_PBAddress2); p.Do(m_PBAddress2);
m_rMailHandler.DoState(p);
m_csMix.Leave();
} }

View File

@ -273,7 +273,9 @@ private:
void RenderSynth_RectWave(ZeldaVoicePB &PB, s32* _Buffer, int _Size); void RenderSynth_RectWave(ZeldaVoicePB &PB, s32* _Buffer, int _Size);
void RenderSynth_SawWave(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_PCM16(ZeldaVoicePB& PB, s16* _Buffer, int _Size);
void RenderVoice_AFC(ZeldaVoicePB& PB, s16* _Buffer, int _Size); void RenderVoice_AFC(ZeldaVoicePB& PB, s16* _Buffer, int _Size);
void RenderVoice_Raw(ZeldaVoicePB& PB, s16* _Buffer, int _Size); void RenderVoice_Raw(ZeldaVoicePB& PB, s16* _Buffer, int _Size);

View File

@ -223,7 +223,7 @@ restart:
{ {
PB.ReachedEnd = 0; PB.ReachedEnd = 0;
// HACK: Looping doesn't work. // HACK: AFC looping doesn't work.
if (true || PB.RepeatMode == 0) if (true || PB.RepeatMode == 0)
{ {
PB.KeyOff = 1; PB.KeyOff = 1;
@ -252,7 +252,7 @@ restart:
// Prefill the decode buffer. // Prefill the decode buffer.
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format); 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; u32 SamplePosition = PB.Length - PB.RemLength;
while (sampleCount < _RealSize) while (sampleCount < _RealSize)
@ -275,7 +275,7 @@ restart:
prev_addr = PB.CurAddr; prev_addr = PB.CurAddr;
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format); 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. // Decoder0x21Core starts here.
u32 AX0 = _RealSize; 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 // 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) // only when the buffer is completely 0 (i.e. when the music has finished fading out)
if (PB.StopOnSilence || PB.RemLength < _RealSize) 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. // 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); Decoder21_ReadAudio(PB, PB.Unk36[0], _Buffer);
u32 ACC0 = _Size << 16; 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. // These are more "synth" formats - square wave, saw wave etc.
case 0x0002: 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 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; break;
default: default:
@ -559,7 +562,7 @@ ContinueWithBlock:
for (int count = 0; count < 8; count++) for (int count = 0; count < 8; count++)
{ {
// The 8 buffers to mix to: 0d00, 0d60, 0f40 0ca0 0e80 0ee0 0c00 0c50 // 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 value = b00[0x4 + count];
int delta = b00[0xC + count] << 11; int delta = b00[0xC + count] << 11;
@ -648,7 +651,7 @@ ContinueWithBlock:
// size is in stereo samples. // size is in stereo samples.
void CUCode_Zelda::MixAdd(short *_Buffer, int _Size) void CUCode_Zelda::MixAdd(short *_Buffer, int _Size)
{ {
// PanicAlert("mixadd"); m_csMix.Enter();
// Safety check // Safety check
if (_Size > 256 * 1024 - 8) if (_Size > 256 * 1024 - 8)
_Size = 256 * 1024 - 8; _Size = 256 * 1024 - 8;
@ -695,4 +698,5 @@ void CUCode_Zelda::MixAdd(short *_Buffer, int _Size)
_Buffer += 2; _Buffer += 2;
} }
m_csMix.Leave();
} }

View File

@ -20,6 +20,7 @@
#include "Common.h" #include "Common.h"
#include "ChunkFile.h" #include "ChunkFile.h"
#include "Thread.h"
#define UCODE_ROM 0x0000000 #define UCODE_ROM 0x0000000
#define UCODE_INIT_AUDIO_SYSTEM 0x0000001 #define UCODE_INIT_AUDIO_SYSTEM 0x0000001
@ -46,6 +47,7 @@ public:
protected: protected:
CMailHandler& m_rMailHandler; CMailHandler& m_rMailHandler;
Common::CriticalSection m_csMix;
}; };
extern IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler); extern IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler);