From 3c9b5bbf7b98702a34d3c5336c62ef0c5eebec3a Mon Sep 17 00:00:00 2001 From: "XTra.KrazzY" Date: Wed, 22 Jul 2009 22:50:52 +0000 Subject: [PATCH] Fixed the load-state memory leak, also fixed various other savestate issues. Found (probably) the cause of load-state crashing Dolphin: BPWrites. Tried to put a CriticalSection around BPWritten but it only causes Dolphin to hang when loading a state. Can someone find why it hangs? git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3873 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/State.cpp | 85 ++++++++++--------- Source/Core/VideoCommon/Src/BPStructs.cpp | 17 +++- .../Plugin_DSP_HLE/Src/MailHandler.cpp | 3 +- 3 files changed, 62 insertions(+), 43 deletions(-) diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index 04a12d255a..aca7331acb 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -84,6 +84,8 @@ void DoState(PointerWrap &p) pm.GetVideo()->DoState(p.GetPPtr(), p.GetMode()); pm.GetDSP()->DoState(p.GetPPtr(), p.GetMode()); pm.GetPad(0)->DoState(p.GetPPtr(), p.GetMode()); + if(Core::g_CoreStartupParameter.bWii) + pm.GetWiimote(0)->DoState(p.GetPPtr(), p.GetMode()); PowerPC::DoState(p); HW::DoState(p); CoreTiming::DoState(p); @@ -124,6 +126,9 @@ void SaveBufferStateCallback(u64 userdata, int cyclesLate) DoState(p); sz = (size_t)ptr; + if(*cur_buffer) + delete[] (*cur_buffer); + *cur_buffer = new u8[sz]; ptr = *cur_buffer; p.SetMode(PointerWrap::MODE_WRITE); @@ -155,6 +160,7 @@ THREAD_RETURN CompressAndDumpState(void *pArgs) FILE *f = fopen(filename.c_str(), "wb"); if(f == NULL) { Core::DisplayMessage("Could not save state", 2000); + delete [] buffer; return 0; } @@ -165,30 +171,27 @@ THREAD_RETURN CompressAndDumpState(void *pArgs) fwrite(&header, sizeof(state_header), 1, f); if (bCompressed) { - if (lzo_init() != LZO_E_OK) - PanicAlert("Internal LZO Error - lzo_init() failed"); - else { - lzo_uint cur_len; - lzo_uint i = 0; + lzo_uint cur_len; + lzo_uint i = 0; - for(;;) { - if((i + IN_LEN) >= sz) - cur_len = sz - i; - else - cur_len = IN_LEN; + for(;;) { + if((i + IN_LEN) >= sz) + cur_len = sz - i; + else + cur_len = IN_LEN; - if(lzo1x_1_compress((buffer + i), cur_len, out, &out_len, wrkmem) != LZO_E_OK) - PanicAlert("Internal LZO Error - compression failed"); + if(lzo1x_1_compress((buffer + i), cur_len, out, &out_len, wrkmem) != LZO_E_OK) + PanicAlert("Internal LZO Error - compression failed"); - // The size of the data to write is 'out_len' - fwrite(&out_len, sizeof(int), 1, f); - fwrite(out, out_len, 1, f); + // The size of the data to write is 'out_len' + fwrite(&out_len, sizeof(int), 1, f); + fwrite(out, out_len, 1, f); - if(cur_len != IN_LEN) - break; - i += cur_len; - } + if(cur_len != IN_LEN) + break; + i += cur_len; } + } else fwrite(buffer, sz, 1, f); @@ -278,28 +281,31 @@ void LoadStateCallback(u64 userdata, int cyclesLate) if (bCompressedState) { Core::DisplayMessage("Decompressing State...", 500); - if (lzo_init() != LZO_E_OK) - PanicAlert("Internal LZO Error - lzo_init() failed"); - else { - lzo_uint i = 0; - buffer = new u8[sz]; - - for (;;) { - if (fread(&cur_len, 1, sizeof(int), f) == 0) - break; - fread(out, 1, cur_len, f); + lzo_uint i = 0; + buffer = new u8[sz]; + if(!buffer) { + PanicAlert("Error allocating buffer"); + return; + } - int res = lzo1x_decompress(out, cur_len, (buffer + i), &new_len, NULL); - if(res != LZO_E_OK) { - PanicAlert("Internal LZO Error - decompression failed (%d)\n" - "Try loading the state again", res); - fclose(f); - return; - } - // The size of the data to read to our buffer is 'new_len' - i += new_len; + for (;;) { + if (fread(&cur_len, 1, sizeof(int), f) == 0) + break; + fread(out, 1, cur_len, f); + + int res = lzo1x_decompress(out, cur_len, (buffer + i), &new_len, NULL); + if(res != LZO_E_OK) { + PanicAlert("Internal LZO Error - decompression failed (%d) (%d, %d) \n" + "Try loading the state again", res, i, new_len); + fclose(f); + + delete[] buffer; + return; } + + // The size of the data to read to our buffer is 'new_len' + i += new_len; } } else { fseek(f, 0, SEEK_END); @@ -331,6 +337,9 @@ void State_Init() ev_Save = CoreTiming::RegisterEvent("SaveState", &SaveStateCallback); ev_BufferLoad = CoreTiming::RegisterEvent("LoadBufferState", &LoadBufferStateCallback); ev_BufferSave = CoreTiming::RegisterEvent("SaveBufferState", &SaveBufferStateCallback); + + if (lzo_init() != LZO_E_OK) + PanicAlert("Internal LZO Error - lzo_init() failed"); } void State_Shutdown() diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp index e330e984cb..171bfc5147 100644 --- a/Source/Core/VideoCommon/Src/BPStructs.cpp +++ b/Source/Core/VideoCommon/Src/BPStructs.cpp @@ -27,15 +27,20 @@ #include "OpcodeDecoding.h" #include "VertexLoader.h" #include "VertexShaderManager.h" +#include "Thread.h" using namespace BPFunctions; +// FIXME: Hangs load-state, but should fix graphic-heavy games state loading +//Common::CriticalSection s_bpCritical; + void BPInit() { memset(&bpmem, 0, sizeof(bpmem)); bpmem.bpMask = 0xFFFFFF; } + // ---------------------------------------------------------------------------------------------------------- // Write to the Bypass Memory (Bypass Raster State Registers) /* ------------------ @@ -73,6 +78,9 @@ void BPWritten(const Bypass& bp) //default: break; //} + // FIXME: Hangs load-state, but should fix graphic-heavy games state loading + //s_bpCritical.Enter(); + FlushPipeline(); ((u32*)&bpmem)[bp.address] = bp.newvalue; @@ -605,10 +613,11 @@ void BPWritten(const Bypass& bp) default: WARN_LOG(VIDEO, "Unknown BP opcode: address = 0x%08x value = 0x%08x", bp.address, bp.newvalue); break; - } - - } - + } } + + // FIXME: Hangs load-state, but should fix graphic-heavy games state loading + //s_bpCritical.Leave(); +} } diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.cpp index ebe3d431f5..a0527d3a61 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.cpp @@ -53,7 +53,8 @@ u16 CMailHandler::ReadDSPMailboxLow() if (!m_Mails.empty()) { u16 result = m_Mails.front() & 0xFFFF; - m_Mails.pop(); + + m_Mails.pop(); Update();