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)
{
delete m_pUCode;
m_pUCode = NULL;
m_MailHandler.Clear();
m_pUCode = UCodeFactory(_crc, m_MailHandler);

View File

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

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 "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();

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_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();
}

View File

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

View File

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

View File

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