made ucode saving more reliable (especially for the case of loading across boundaries where the ucode changes). I think this is related to the occasional memory corruption I was seeing upon loading a savestate.

This commit is contained in:
nitsuja 2011-12-17 16:56:23 -08:00
parent c68c8c388c
commit 1e4e05fdc3
16 changed files with 88 additions and 41 deletions

View File

@ -131,7 +131,51 @@ void DSPHLE::SwapUCode(u32 _crc)
void DSPHLE::DoState(PointerWrap &p) void DSPHLE::DoState(PointerWrap &p)
{ {
p.Do(m_InitMixer); p.Do(m_InitMixer);
GetUCode()->DoState(p); p.Do(m_DSPControl);
p.Do(m_dspState);
int ucode_crc = IUCode::GetCRC(m_pUCode);
int ucode_crc_beforeLoad = ucode_crc;
int lastucode_crc = IUCode::GetCRC(m_lastUCode);
int lastucode_crc_beforeLoad = lastucode_crc;
p.Do(ucode_crc);
p.Do(lastucode_crc);
// if a different type of ucode was being used when the savestate was created,
// we have to reconstruct the old type of ucode so that we have a valid thing to call DoState on.
IUCode* ucode = (ucode_crc == ucode_crc_beforeLoad) ? m_pUCode : UCodeFactory( ucode_crc, this, m_bWii);
IUCode* lastucode = (lastucode_crc != lastucode_crc_beforeLoad) ? m_lastUCode : UCodeFactory(lastucode_crc, this, m_bWii);
if (ucode)
ucode->DoState(p);
if (lastucode)
lastucode->DoState(p);
// if a different type of ucode was being used when the savestate was created,
// discard it if we're not loading, otherwise discard the old one and keep the new one.
if (ucode != m_pUCode)
{
if (p.GetMode() != PointerWrap::MODE_READ)
delete ucode;
else
{
delete m_pUCode;
m_pUCode = ucode;
}
}
if (lastucode != m_lastUCode)
{
if (p.GetMode() != PointerWrap::MODE_READ)
delete lastucode;
else
{
delete m_lastUCode;
m_lastUCode = lastucode;
}
}
m_MailHandler.DoState(p);
} }
// Mailbox fuctions // Mailbox fuctions

View File

@ -28,9 +28,8 @@
#include "UCode_AX_Voice.h" #include "UCode_AX_Voice.h"
CUCode_AX::CUCode_AX(DSPHLE *dsp_hle, u32 l_CRC) CUCode_AX::CUCode_AX(DSPHLE *dsp_hle, u32 l_CRC)
: IUCode(dsp_hle) : IUCode(dsp_hle, l_CRC)
, m_addressPBs(0xFFFFFFFF) , m_addressPBs(0xFFFFFFFF)
, _CRC(l_CRC)
{ {
// we got loaded // we got loaded
m_rMailHandler.PushMail(DSP_INIT); m_rMailHandler.PushMail(DSP_INIT);
@ -175,7 +174,7 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
ProcessUpdates(PB); ProcessUpdates(PB);
if (_CRC != 0x3389a79e) if (m_CRC != 0x3389a79e)
VoiceHacks(PB); VoiceHacks(PB);
MixAddVoice(PB, templbuffer, temprbuffer, _iSize); MixAddVoice(PB, templbuffer, temprbuffer, _iSize);
@ -463,11 +462,8 @@ void CUCode_AX::DoState(PointerWrap &p)
{ {
std::lock_guard<std::mutex> lk(m_csMix); std::lock_guard<std::mutex> lk(m_csMix);
p.Do(_CRC);
p.Do(numPBaddr); p.Do(numPBaddr);
p.Do(m_addressPBs); p.Do(m_addressPBs);
p.Do(PBaddr); p.Do(PBaddr);
p.Do(m_UploadSetupInProgress); p.Do(m_UploadSetupInProgress);
m_rMailHandler.DoState(p);
} }

View File

@ -41,7 +41,6 @@ public:
u8 numPBaddr; u8 numPBaddr;
u32 PBaddr[8]; //2 needed for MP2 u32 PBaddr[8]; //2 needed for MP2
u32 m_addressPBs; u32 m_addressPBs;
u32 _CRC;
private: private:
enum enum

View File

@ -28,9 +28,8 @@
CUCode_AXWii::CUCode_AXWii(DSPHLE *dsp_hle, u32 l_CRC) CUCode_AXWii::CUCode_AXWii(DSPHLE *dsp_hle, u32 l_CRC)
: IUCode(dsp_hle) : IUCode(dsp_hle, l_CRC)
, m_addressPBs(0xFFFFFFFF) , m_addressPBs(0xFFFFFFFF)
, _CRC(l_CRC)
{ {
// we got loaded // we got loaded
m_rMailHandler.PushMail(DSP_INIT); m_rMailHandler.PushMail(DSP_INIT);
@ -38,7 +37,7 @@ CUCode_AXWii::CUCode_AXWii(DSPHLE *dsp_hle, u32 l_CRC)
templbuffer = new int[1024 * 1024]; templbuffer = new int[1024 * 1024];
temprbuffer = new int[1024 * 1024]; temprbuffer = new int[1024 * 1024];
wiisportsHack = _CRC == 0xfa450138; wiisportsHack = m_CRC == 0xfa450138;
} }
CUCode_AXWii::~CUCode_AXWii() CUCode_AXWii::~CUCode_AXWii()
@ -260,10 +259,7 @@ void CUCode_AXWii::DoState(PointerWrap &p)
{ {
std::lock_guard<std::mutex> lk(m_csMix); std::lock_guard<std::mutex> lk(m_csMix);
p.Do(_CRC);
p.Do(m_addressPBs); p.Do(m_addressPBs);
p.Do(wiisportsHack); p.Do(wiisportsHack);
p.Do(m_UploadSetupInProgress); p.Do(m_UploadSetupInProgress);
m_rMailHandler.DoState(p);
} }

View File

@ -21,8 +21,8 @@
#include "../../DSP.h" #include "../../DSP.h"
CUCode_CARD::CUCode_CARD(DSPHLE *dsp_hle) CUCode_CARD::CUCode_CARD(DSPHLE *dsp_hle, u32 crc)
: IUCode(dsp_hle) : IUCode(dsp_hle, crc)
{ {
DEBUG_LOG(DSPHLE, "CUCode_CARD - initialized"); DEBUG_LOG(DSPHLE, "CUCode_CARD - initialized");
m_rMailHandler.PushMail(DSP_INIT); m_rMailHandler.PushMail(DSP_INIT);

View File

@ -23,7 +23,7 @@
class CUCode_CARD : public IUCode class CUCode_CARD : public IUCode
{ {
public: public:
CUCode_CARD(DSPHLE *dsp_hle); CUCode_CARD(DSPHLE *dsp_hle, u32 crc);
virtual ~CUCode_CARD(); virtual ~CUCode_CARD();
void HandleMail(u32 _uMail); void HandleMail(u32 _uMail);

View File

@ -20,8 +20,8 @@
#include "../../DSP.h" #include "../../DSP.h"
CUCode_GBA::CUCode_GBA(DSPHLE *dsp_hle) CUCode_GBA::CUCode_GBA(DSPHLE *dsp_hle, u32 crc)
: IUCode(dsp_hle) : IUCode(dsp_hle, crc)
{ {
m_rMailHandler.PushMail(DSP_INIT); m_rMailHandler.PushMail(DSP_INIT);
} }

View File

@ -21,7 +21,7 @@
struct CUCode_GBA : public IUCode struct CUCode_GBA : public IUCode
{ {
CUCode_GBA(DSPHLE *dsp_hle); CUCode_GBA(DSPHLE *dsp_hle, u32 crc);
virtual ~CUCode_GBA(); virtual ~CUCode_GBA();
void HandleMail(u32 _uMail); void HandleMail(u32 _uMail);

View File

@ -18,8 +18,8 @@
#include "UCodes.h" #include "UCodes.h"
#include "UCode_InitAudioSystem.h" #include "UCode_InitAudioSystem.h"
CUCode_InitAudioSystem::CUCode_InitAudioSystem(DSPHLE *dsp_hle) CUCode_InitAudioSystem::CUCode_InitAudioSystem(DSPHLE *dsp_hle, u32 crc)
: IUCode(dsp_hle) : IUCode(dsp_hle, crc)
{ {
DEBUG_LOG(DSPHLE, "CUCode_InitAudioSystem - initialized"); DEBUG_LOG(DSPHLE, "CUCode_InitAudioSystem - initialized");
} }

View File

@ -23,7 +23,7 @@
class CUCode_InitAudioSystem : public IUCode class CUCode_InitAudioSystem : public IUCode
{ {
public: public:
CUCode_InitAudioSystem(DSPHLE *dsp_hle); CUCode_InitAudioSystem(DSPHLE *dsp_hle, u32 crc);
virtual ~CUCode_InitAudioSystem(); virtual ~CUCode_InitAudioSystem();
void HandleMail(u32 _uMail); void HandleMail(u32 _uMail);

View File

@ -20,8 +20,8 @@
#include "Hash.h" #include "Hash.h"
#include "../../Memmap.h" #include "../../Memmap.h"
CUCode_Rom::CUCode_Rom(DSPHLE *dsp_hle) CUCode_Rom::CUCode_Rom(DSPHLE *dsp_hle, u32 crc)
: IUCode(dsp_hle) : IUCode(dsp_hle, crc)
, m_CurrentUCode() , m_CurrentUCode()
, m_BootTask_numSteps(0) , m_BootTask_numSteps(0)
, m_NextParameter(0) , m_NextParameter(0)
@ -117,4 +117,10 @@ void CUCode_Rom::BootUCode()
m_DSPHLE->SetUCode(ector_crc); m_DSPHLE->SetUCode(ector_crc);
} }
void CUCode_Rom::DoState(PointerWrap &p)
{
p.Do(m_CurrentUCode);
p.Do(m_BootTask_numSteps);
p.Do(m_NextParameter);
}

View File

@ -23,12 +23,14 @@
class CUCode_Rom : public IUCode class CUCode_Rom : public IUCode
{ {
public: public:
CUCode_Rom(DSPHLE *dsp_hle); CUCode_Rom(DSPHLE *dsp_hle, u32 _crc);
virtual ~CUCode_Rom(); virtual ~CUCode_Rom();
void HandleMail(u32 _uMail); void HandleMail(u32 _uMail);
void Update(int cycles); void Update(int cycles);
void DoState(PointerWrap &p);
private: private:
struct SUCode struct SUCode
{ {

View File

@ -31,8 +31,7 @@
CUCode_Zelda::CUCode_Zelda(DSPHLE *dsp_hle, u32 _CRC) CUCode_Zelda::CUCode_Zelda(DSPHLE *dsp_hle, u32 _CRC)
: :
IUCode(dsp_hle), IUCode(dsp_hle, _CRC),
m_CRC(_CRC),
m_bSyncInProgress(false), m_bSyncInProgress(false),
m_MaxVoice(0), m_MaxVoice(0),
@ -572,8 +571,6 @@ void CUCode_Zelda::DoState(PointerWrap &p)
// It's bad if we try to save during Mix() // It's bad if we try to save during Mix()
std::lock_guard<std::mutex> lk(m_csMix); std::lock_guard<std::mutex> lk(m_csMix);
p.Do(m_CRC);
p.Do(m_AFCCoefTable); p.Do(m_AFCCoefTable);
p.Do(m_MiscTable); p.Do(m_MiscTable);
@ -616,6 +613,4 @@ void CUCode_Zelda::DoState(PointerWrap &p)
p.Do(m_PBAddress2); p.Do(m_PBAddress2);
p.Do(m_UploadSetupInProgress); p.Do(m_UploadSetupInProgress);
m_rMailHandler.DoState(p);
} }

View File

@ -212,8 +212,6 @@ private:
} }
} }
u32 m_CRC;
// These are the only dynamically allocated things allowed in the ucode. // These are the only dynamically allocated things allowed in the ucode.
s32* m_VoiceBuffer; s32* m_VoiceBuffer;
s16* m_ResampleBuffer; s16* m_ResampleBuffer;

View File

@ -32,19 +32,19 @@ IUCode* UCodeFactory(u32 _CRC, DSPHLE *dsp_hle, bool bWii)
{ {
case UCODE_ROM: case UCODE_ROM:
INFO_LOG(DSPHLE, "Switching to ROM ucode"); INFO_LOG(DSPHLE, "Switching to ROM ucode");
return new CUCode_Rom(dsp_hle); return new CUCode_Rom(dsp_hle, _CRC);
case UCODE_INIT_AUDIO_SYSTEM: case UCODE_INIT_AUDIO_SYSTEM:
INFO_LOG(DSPHLE, "Switching to INIT ucode"); INFO_LOG(DSPHLE, "Switching to INIT ucode");
return new CUCode_InitAudioSystem(dsp_hle); return new CUCode_InitAudioSystem(dsp_hle, _CRC);
case 0x65d6cc6f: // CARD case 0x65d6cc6f: // CARD
INFO_LOG(DSPHLE, "Switching to CARD ucode"); INFO_LOG(DSPHLE, "Switching to CARD ucode");
return new CUCode_CARD(dsp_hle); return new CUCode_CARD(dsp_hle, _CRC);
case 0xdd7e72d5: case 0xdd7e72d5:
INFO_LOG(DSPHLE, "Switching to GBA ucode"); INFO_LOG(DSPHLE, "Switching to GBA ucode");
return new CUCode_GBA(dsp_hle); return new CUCode_GBA(dsp_hle, _CRC);
case 0x3ad3b7ac: // Naruto3, Paper Mario - The Thousand Year Door case 0x3ad3b7ac: // Naruto3, Paper Mario - The Thousand Year Door
case 0x3daf59b9: // Alien Hominid case 0x3daf59b9: // Alien Hominid
@ -103,6 +103,9 @@ IUCode* UCodeFactory(u32 _CRC, DSPHLE *dsp_hle, bool bWii)
PanicAlert("DSPHLE: Unknown ucode (CRC = %08x) - forcing AX.\n\nTry LLE emulator if this is homebrew.", _CRC); PanicAlert("DSPHLE: Unknown ucode (CRC = %08x) - forcing AX.\n\nTry LLE emulator if this is homebrew.", _CRC);
return new CUCode_AX(dsp_hle, _CRC); return new CUCode_AX(dsp_hle, _CRC);
} }
case UCODE_NULL:
break;
} }
return NULL; return NULL;

View File

@ -25,8 +25,9 @@
#include "../DSPHLE.h" #include "../DSPHLE.h"
#include "../../Memmap.h" #include "../../Memmap.h"
#define UCODE_ROM 0x0000000 #define UCODE_ROM 0x00000000
#define UCODE_INIT_AUDIO_SYSTEM 0x0000001 #define UCODE_INIT_AUDIO_SYSTEM 0x00000001
#define UCODE_NULL 0xFFFFFFFF
class CMailHandler; class CMailHandler;
@ -73,10 +74,11 @@ inline void* HLEMemory_Get_Pointer(u32 _uAddress)
class IUCode class IUCode
{ {
public: public:
IUCode(DSPHLE *dsphle) IUCode(DSPHLE *dsphle, u32 _crc)
: m_rMailHandler(dsphle->AccessMailHandler()) : m_rMailHandler(dsphle->AccessMailHandler())
, m_UploadSetupInProgress(false) , m_UploadSetupInProgress(false)
, m_DSPHLE(dsphle) , m_DSPHLE(dsphle)
, m_CRC(_crc)
, m_NextUCode() , m_NextUCode()
, m_NextUCode_steps(0) , m_NextUCode_steps(0)
, m_NeedsResumeMail(false) , m_NeedsResumeMail(false)
@ -93,6 +95,8 @@ public:
virtual void DoState(PointerWrap &p) {} virtual void DoState(PointerWrap &p) {}
static u32 GetCRC(IUCode* pUCode) { return pUCode ? pUCode->m_CRC : UCODE_NULL; }
protected: protected:
void PrepareBootUCode(u32 mail); void PrepareBootUCode(u32 mail);
@ -121,6 +125,10 @@ protected:
// Need a pointer back to DSPHLE to switch ucodes. // Need a pointer back to DSPHLE to switch ucodes.
DSPHLE *m_DSPHLE; DSPHLE *m_DSPHLE;
// used for reconstruction when loading saves,
// and for variations within certain ucodes.
u32 m_CRC;
private: private:
struct SUCode struct SUCode
{ {