diff --git a/common/include/Utilities/Dependencies.h b/common/include/Utilities/Dependencies.h
index f36cac9d1d..ec977b25ef 100644
--- a/common/include/Utilities/Dependencies.h
+++ b/common/include/Utilities/Dependencies.h
@@ -26,6 +26,7 @@ class wxOutputStream;
class wxFileOutputStream;
class wxFFileOutputStream;
+class wxStreamBase;
class wxInputStream;
class wxFileInputStream;
class wxFFileInputStream;
diff --git a/common/include/Utilities/SafeArray.h b/common/include/Utilities/SafeArray.h
index 6e6d940b97..96c373cb26 100644
--- a/common/include/Utilities/SafeArray.h
+++ b/common/include/Utilities/SafeArray.h
@@ -86,8 +86,14 @@ public:
// Gets a pointer to the requested allocation index.
// DevBuilds : Generates assertion if the index is invalid.
- T *GetPtr( uint idx=0 ) { return _getPtr( idx ); }
- const T *GetPtr( uint idx=0 ) const { return _getPtr( idx ); }
+ T* GetPtr( uint idx=0 ) { return _getPtr( idx ); }
+ const T* GetPtr( uint idx=0 ) const { return _getPtr( idx ); }
+
+ // Gets a pointer to the element directly after the last element in the array.
+ // This is equivalent to doing GetPtr(GetLength()), except that this call *avoids*
+ // the out-of-bounds assertion check that typically occurs when you do that. :)
+ T* GetPtrEnd( uint idx=0 ) { return &m_ptr[m_size]; }
+ const T* GetPtrEnd( uint idx=0 ) const { return &m_ptr[m_size]; }
// Gets an element of this memory allocation much as if it were an array.
// DevBuilds : Generates assertion if the index is invalid.
diff --git a/common/include/Utilities/pxStreams.h b/common/include/Utilities/pxStreams.h
index 1eb07714d1..326965231e 100644
--- a/common/include/Utilities/pxStreams.h
+++ b/common/include/Utilities/pxStreams.h
@@ -13,31 +13,58 @@
* If not, see .
*/
+#pragma once
+
// --------------------------------------------------------------------------------------
-// pxStreamWriter
+// pxStreamBase
// --------------------------------------------------------------------------------------
-class pxStreamWriter
+class pxStreamBase
{
- DeclareNoncopyableObject(pxStreamWriter);
+ DeclareNoncopyableObject(pxStreamBase);
protected:
- wxString m_filename;
- ScopedPtr m_outstream;
+ // Filename of the stream, provided by the creator/caller. This is typically used *only*
+ // for generating comprehensive error messages when an error occurs (the stream name is
+ // passed to the exception handlers).
+ wxString m_filename;
public:
- pxStreamWriter(const wxString& filename, ScopedPtr& output);
- pxStreamWriter(const wxString& filename, wxOutputStream* output);
+ pxStreamBase(const wxString& filename);
+ virtual ~pxStreamBase() throw() {}
- virtual ~pxStreamWriter() throw() {}
+ // Implementing classes should return the base wxStream object (usually either a wxInputStream
+ // or wxOputStream derivative).
+ virtual wxStreamBase* GetWxStreamBase() const=0;
+ virtual void Close()=0;
+
+ bool IsOk() const;
+ wxString GetStreamName() const { return m_filename; }
+};
+
+
+// --------------------------------------------------------------------------------------
+// pxOutputStream
+// --------------------------------------------------------------------------------------
+class pxOutputStream : public pxStreamBase
+{
+ DeclareNoncopyableObject(pxOutputStream);
+
+protected:
+ ScopedPtr m_stream_out;
+
+public:
+ pxOutputStream(const wxString& filename, ScopedPtr& output);
+ pxOutputStream(const wxString& filename, wxOutputStream* output);
+
+ virtual ~pxOutputStream() throw() {}
virtual void Write( const void* data, size_t size );
- void Close() { m_outstream.Delete(); }
- wxOutputStream* GetBaseStream() const { return m_outstream; }
-
void SetStream( const wxString& filename, ScopedPtr& stream );
void SetStream( const wxString& filename, wxOutputStream* stream );
-
- wxString GetStreamName() const { return m_filename; }
+
+ void Close() { m_stream_out.Delete(); }
+
+ virtual wxStreamBase* GetWxStreamBase() const;
template< typename T >
void Write( const T& data )
@@ -47,30 +74,28 @@ public:
};
// --------------------------------------------------------------------------------------
-// pxStreamReader
+// pxInputStream
// --------------------------------------------------------------------------------------
-class pxStreamReader
+class pxInputStream : public pxStreamBase
{
- DeclareNoncopyableObject(pxStreamReader);
+ DeclareNoncopyableObject(pxInputStream);
protected:
- wxString m_filename;
- ScopedPtr m_stream;
+ ScopedPtr m_stream_in;
public:
- pxStreamReader(const wxString& filename, ScopedPtr& input);
- pxStreamReader(const wxString& filename, wxInputStream* input);
+ pxInputStream(const wxString& filename, ScopedPtr& input);
+ pxInputStream(const wxString& filename, wxInputStream* input);
- virtual ~pxStreamReader() throw() {}
+ virtual ~pxInputStream() throw() {}
virtual void Read( void* dest, size_t size );
void SetStream( const wxString& filename, ScopedPtr& stream );
void SetStream( const wxString& filename, wxInputStream* stream );
- wxInputStream* GetBaseStream() const { return m_stream; }
- void Close() { m_stream.Delete(); }
+ void Close() { m_stream_in.Delete(); }
- wxString GetStreamName() const { return m_filename; }
+ virtual wxStreamBase* GetWxStreamBase() const;
template< typename T >
void Read( T& dest )
diff --git a/common/src/Utilities/Exceptions.cpp b/common/src/Utilities/Exceptions.cpp
index 64037aa4d1..65670f0e19 100644
--- a/common/src/Utilities/Exceptions.cpp
+++ b/common/src/Utilities/Exceptions.cpp
@@ -292,7 +292,7 @@ wxString Exception::BadStream::FormatDisplayMessage() const
return retval;
}
-void Exception::BadStream::_formatDiagMsg( FastFormatUnicode& dest ) const
+void Exception::BadStream::_formatDiagMsg( FastFormatUnicode& dest ) const
{
dest.Write( L"Path: " );
if (!StreamName.IsEmpty())
diff --git a/common/src/Utilities/pxStreams.cpp b/common/src/Utilities/pxStreams.cpp
index 3d960a430c..00eed7a253 100644
--- a/common/src/Utilities/pxStreams.cpp
+++ b/common/src/Utilities/pxStreams.cpp
@@ -22,39 +22,55 @@
#include
// --------------------------------------------------------------------------------------
-// pxStreamReader (implementations)
+// pxStreamBase (implementations)
+// --------------------------------------------------------------------------------------
+pxStreamBase::pxStreamBase(const wxString& filename)
+ : m_filename( filename )
+{
+}
+
+bool pxStreamBase::IsOk() const
+{
+ wxStreamBase* woot = GetWxStreamBase();
+ return woot && woot->IsOk();
+}
+
+// --------------------------------------------------------------------------------------
+// pxInputStream (implementations)
// --------------------------------------------------------------------------------------
// Interface for reading data from a gzip stream.
//
-pxStreamReader::pxStreamReader(const wxString& filename, ScopedPtr& input)
- : m_filename( filename )
- , m_stream( input.DetachPtr() )
+pxInputStream::pxInputStream(const wxString& filename, ScopedPtr& input)
+ : pxStreamBase( filename )
+ , m_stream_in( input.DetachPtr() )
{
}
-pxStreamReader::pxStreamReader(const wxString& filename, wxInputStream* input)
- : m_filename( filename )
- , m_stream( input )
+pxInputStream::pxInputStream(const wxString& filename, wxInputStream* input)
+ : pxStreamBase( filename )
+ , m_stream_in( input )
{
}
-void pxStreamReader::SetStream( const wxString& filename, ScopedPtr& stream )
+wxStreamBase* pxInputStream::GetWxStreamBase() const { return m_stream_in.GetPtr(); }
+
+void pxInputStream::SetStream( const wxString& filename, ScopedPtr& stream )
{
m_filename = filename;
- m_stream = stream.DetachPtr();
+ m_stream_in = stream.DetachPtr();
}
-void pxStreamReader::SetStream( const wxString& filename, wxInputStream* stream )
+void pxInputStream::SetStream( const wxString& filename, wxInputStream* stream )
{
m_filename = filename;
- m_stream = stream;
+ m_stream_in = stream;
}
-void pxStreamReader::Read( void* dest, size_t size )
+void pxInputStream::Read( void* dest, size_t size )
{
- m_stream->Read(dest, size);
- if (m_stream->GetLastError() == wxSTREAM_READ_ERROR)
+ m_stream_in->Read(dest, size);
+ if (m_stream_in->GetLastError() == wxSTREAM_READ_ERROR)
{
int err = errno;
if (!err)
@@ -69,43 +85,46 @@ void pxStreamReader::Read( void* dest, size_t size )
// must always use the explicit check against the number of bytes read to determine
// end-of-stream conditions.
- if ((size_t)m_stream->LastRead() < size)
+ if ((size_t)m_stream_in->LastRead() < size)
throw Exception::EndOfStream( m_filename );
}
// --------------------------------------------------------------------------------------
-// pxStreamWriter
+// pxOutputStream
// --------------------------------------------------------------------------------------
-pxStreamWriter::pxStreamWriter(const wxString& filename, ScopedPtr& output)
- : m_filename( filename )
- , m_outstream( output.DetachPtr() )
+pxOutputStream::pxOutputStream(const wxString& filename, ScopedPtr& output)
+ : pxStreamBase( filename )
+ , m_stream_out( output.DetachPtr() )
{
}
-pxStreamWriter::pxStreamWriter(const wxString& filename, wxOutputStream* output)
- : m_filename( filename )
- , m_outstream( output )
+pxOutputStream::pxOutputStream(const wxString& filename, wxOutputStream* output)
+ : pxStreamBase( filename )
+ , m_stream_out( output )
{
}
-void pxStreamWriter::SetStream( const wxString& filename, ScopedPtr& stream )
+wxStreamBase* pxOutputStream::GetWxStreamBase() const { return m_stream_out.GetPtr(); }
+
+
+void pxOutputStream::SetStream( const wxString& filename, ScopedPtr& stream )
{
m_filename = filename;
- m_outstream = stream.DetachPtr();
+ m_stream_out = stream.DetachPtr();
}
-void pxStreamWriter::SetStream( const wxString& filename, wxOutputStream* stream )
+void pxOutputStream::SetStream( const wxString& filename, wxOutputStream* stream )
{
m_filename = filename;
- m_outstream = stream;
+ m_stream_out = stream;
}
-void pxStreamWriter::Write( const void* src, size_t size )
+void pxOutputStream::Write( const void* src, size_t size )
{
- m_outstream->Write(src, size);
- if(m_outstream->GetLastError() == wxSTREAM_WRITE_ERROR)
+ m_stream_out->Write(src, size);
+ if(m_stream_out->GetLastError() == wxSTREAM_WRITE_ERROR)
{
int err = errno;
if (!err)
diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp
index c6333e951a..70ace94b46 100644
--- a/pcsx2/SaveState.cpp
+++ b/pcsx2/SaveState.cpp
@@ -20,6 +20,7 @@
#include "ps2/BiosTools.h"
#include "COP0.h"
+#include "VUmicro.h"
#include "Cache.h"
#include "AppConfig.h"
@@ -163,6 +164,12 @@ void SaveStateBase::FreezeMainMemory()
FreezeMem(iopMem->Main, Ps2MemSize::IopRam); // 2 MB main memory
FreezeMem(iopHw, Ps2MemSize::IopHardware); // hardware memory
+
+ FreezeMem(vuRegs[0].Micro, VU0_PROGSIZE);
+ FreezeMem(vuRegs[0].Mem, VU0_MEMSIZE);
+
+ FreezeMem(vuRegs[1].Micro, VU1_PROGSIZE);
+ FreezeMem(vuRegs[1].Mem, VU1_MEMSIZE);
}
void SaveStateBase::FreezeRegisters()
@@ -378,16 +385,24 @@ void memSavingState::FreezeMem( void* data, int size )
m_idx += size;
}
-void memSavingState::FreezeAll()
+void memSavingState::MakeRoomForData()
{
pxAssumeDev( m_memory, "Savestate memory/buffer pointer is null!" );
m_memory->ChunkSize = ReallocThreshold;
m_memory->MakeRoomFor( m_idx + MemoryBaseAllocSize );
+}
+// Saving of state data to a memory buffer
+void memSavingState::FreezeAll()
+{
+ MakeRoomForData();
_parent::FreezeAll();
}
+// --------------------------------------------------------------------------------------
+// memLoadingState (implementations)
+// --------------------------------------------------------------------------------------
memLoadingState::memLoadingState( const SafeArray& load_from )
: SaveStateBase( const_cast&>(load_from) )
{
@@ -400,7 +415,7 @@ memLoadingState::memLoadingState( const SafeArray* load_from )
memLoadingState::~memLoadingState() throw() { }
-// Loading of state data
+// Loading of state data from a memory buffer...
void memLoadingState::FreezeMem( void* data, int size )
{
const u8* const src = m_memory->GetPtr(m_idx);
diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h
index 4022a646b3..e4bba1ddbd 100644
--- a/pcsx2/SaveState.h
+++ b/pcsx2/SaveState.h
@@ -118,7 +118,7 @@ protected:
u32 m_version; // version of the savestate being loaded.
- int m_idx; // current read/write index of the allocation
+ int m_idx; // current read/write index of the allocation
int m_sectid;
int m_pid;
@@ -163,10 +163,20 @@ public:
void PrepBlock( int size );
+ uint GetCurrentPos() const
+ {
+ return m_idx;
+ }
+
u8* GetBlockPtr()
{
return m_memory->GetPtr(m_idx);
}
+
+ u8* GetPtrEnd() const
+ {
+ return m_memory->GetPtrEnd();
+ }
void CommitBlock( int size )
{
@@ -244,7 +254,8 @@ public:
memSavingState( VmStateBuffer& save_to );
memSavingState( VmStateBuffer* save_to );
- // Saving of state data to a memory buffer
+ void MakeRoomForData();
+
void FreezeMem( void* data, int size );
void FreezeAll();
@@ -259,7 +270,6 @@ public:
memLoadingState( const VmStateBuffer& load_from );
memLoadingState( const VmStateBuffer* load_from );
- // Loading of state data from a memory buffer...
void FreezeMem( void* data, int size );
bool SeekToSection( PluginsEnum_t pid );
diff --git a/pcsx2/ZipTools/ThreadedZipTools.h b/pcsx2/ZipTools/ThreadedZipTools.h
index d12adfb159..f56242705b 100644
--- a/pcsx2/ZipTools/ThreadedZipTools.h
+++ b/pcsx2/ZipTools/ThreadedZipTools.h
@@ -21,6 +21,140 @@
using namespace Threading;
+// --------------------------------------------------------------------------------------
+// BaseArchiveEntry
+// --------------------------------------------------------------------------------------
+class BaseArchiveEntry
+{
+protected:
+ BaseArchiveEntry() {}
+ virtual ~BaseArchiveEntry() throw() {}
+
+public:
+ virtual wxString GetFilename() const=0;
+ virtual u8* GetDataPtr() const=0;
+ virtual uint GetDataSize() const=0;
+};
+
+
+// --------------------------------------------------------------------------------------
+// ArchiveEntry
+// --------------------------------------------------------------------------------------
+class ArchiveEntry
+{
+protected:
+ wxString m_filename;
+ uptr m_dataidx;
+ size_t m_datasize;
+
+public:
+ ArchiveEntry( const wxString& filename=wxEmptyString )
+ : m_filename( filename )
+ {
+ m_dataidx = 0;
+ m_datasize = 0;
+ }
+
+ virtual ~ArchiveEntry() throw() {}
+
+ ArchiveEntry& SetDataIndex( uptr idx )
+ {
+ m_dataidx = idx;
+ return *this;
+ }
+
+ ArchiveEntry& SetDataSize( size_t size )
+ {
+ m_datasize = size;
+ return *this;
+ }
+
+ wxString GetFilename() const
+ {
+ return m_filename;
+ }
+
+ uptr GetDataIndex() const
+ {
+ return m_dataidx;
+ }
+
+ uint GetDataSize() const
+ {
+ return m_datasize;
+ }
+};
+
+typedef SafeArray< u8 > ArchiveDataBuffer;
+
+// --------------------------------------------------------------------------------------
+// ArchiveEntryList
+// --------------------------------------------------------------------------------------
+class ArchiveEntryList
+{
+ DeclareNoncopyableObject( ArchiveEntryList );
+
+protected:
+ std::vector m_list;
+ ScopedPtr m_data;
+
+public:
+ ArchiveEntryList() {}
+
+ ArchiveEntryList( ArchiveDataBuffer* data )
+ {
+ m_data = data;
+ }
+
+ ArchiveEntryList( ScopedPtr& data )
+ {
+ m_data = data.DetachPtr();
+ }
+
+ virtual ~ArchiveEntryList() throw() {}
+
+ const VmStateBuffer* GetBuffer() const
+ {
+ return m_data;
+ }
+
+ VmStateBuffer* GetBuffer()
+ {
+ return m_data;
+ }
+
+ u8* GetPtr( uint idx )
+ {
+ return &(*m_data)[idx];
+ }
+
+ const u8* GetPtr( uint idx ) const
+ {
+ return &(*m_data)[idx];
+ }
+
+ ArchiveEntryList& Add( const ArchiveEntry& src )
+ {
+ m_list.push_back( src );
+ return *this;
+ }
+
+ size_t GetLength() const
+ {
+ return m_list.size();
+ }
+
+ ArchiveEntry& operator[](uint idx)
+ {
+ return m_list[idx];
+ }
+
+ const ArchiveEntry& operator[](uint idx) const
+ {
+ return m_list[idx];
+ }
+};
+
// --------------------------------------------------------------------------------------
// BaseCompressThread
// --------------------------------------------------------------------------------------
@@ -30,33 +164,45 @@ class BaseCompressThread
typedef pxThread _parent;
protected:
- ScopedPtr< SafeArray< u8 > > m_src_buffer;
- ScopedPtr< pxStreamWriter > m_gzfp;
+ ScopedPtr< ArchiveEntryList > m_src_list;
+ ScopedPtr< pxOutputStream > m_gzfp;
bool m_PendingSaveFlag;
wxString m_final_filename;
- BaseCompressThread( SafeArray* srcdata, pxStreamWriter* outarchive)
- : m_src_buffer( srcdata )
+public:
+ virtual ~BaseCompressThread() throw();
+
+ BaseCompressThread& SetSource( ArchiveEntryList* srcdata )
{
- m_gzfp = outarchive;
- m_PendingSaveFlag = false;
+ m_src_list = srcdata;
+ return *this;
}
- BaseCompressThread( SafeArray* srcdata, ScopedPtr& outarchive)
- : m_src_buffer( srcdata )
+ BaseCompressThread& SetSource( ScopedPtr< ArchiveEntryList >& srcdata )
{
- m_gzfp = outarchive.DetachPtr();
- m_PendingSaveFlag = false;
+ m_src_list = srcdata.DetachPtr();
+ return *this;
}
-
- virtual ~BaseCompressThread() throw();
-
- void SetPendingSave();
- void ExecuteTaskInThread();
- void OnCleanupInThread();
-
-public:
+
+ BaseCompressThread& SetOutStream( pxOutputStream* out )
+ {
+ m_gzfp = out;
+ return *this;
+ }
+
+ BaseCompressThread& SetOutStream( ScopedPtr< pxOutputStream >& out )
+ {
+ m_gzfp = out.DetachPtr();
+ return *this;
+ }
+
+ BaseCompressThread& SetFinishedPath( const wxString& path )
+ {
+ m_final_filename = path;
+ return *this;
+ }
+
wxString GetStreamName() const { return m_gzfp->GetStreamName(); }
BaseCompressThread& SetTargetFilename(const wxString& filename)
@@ -64,4 +210,14 @@ public:
m_final_filename = filename;
return *this;
}
+
+protected:
+ BaseCompressThread()
+ {
+ m_PendingSaveFlag = false;
+ }
+
+ void SetPendingSave();
+ void ExecuteTaskInThread();
+ void OnCleanupInThread();
};
diff --git a/pcsx2/ZipTools/thread_gzip.cpp b/pcsx2/ZipTools/thread_gzip.cpp
index aea95b766d..8832922982 100644
--- a/pcsx2/ZipTools/thread_gzip.cpp
+++ b/pcsx2/ZipTools/thread_gzip.cpp
@@ -43,26 +43,38 @@ void BaseCompressThread::ExecuteTaskInThread()
// TODO : Add an API to PersistentThread for this! :) --air
//SetThreadPriority( THREAD_PRIORITY_BELOW_NORMAL );
- if( !m_src_buffer ) return;
+ // Notes:
+ // * Safeguard against corruption by writing to a temp file, and then copying the final
+ // result over the original.
+
+ if( !m_src_list ) return;
SetPendingSave();
Yield( 3 );
- static const int BlockSize = 0x64000;
- int curidx = 0;
+ uint listlen = m_src_list->GetLength();
+ for( uint i=0; iGetWxStreamBase();
+ woot.PutNextEntry( entry.GetFilename() );
+
+ static const uint BlockSize = 0x64000;
+ uint curidx = 0;
+
+ do {
+ uint thisBlockSize = std::min( BlockSize, entry.GetDataSize() - curidx );
+ m_gzfp->Write(m_src_list->GetPtr( entry.GetDataIndex() + curidx ), thisBlockSize);
+ curidx += thisBlockSize;
+ Yield( 2 );
+ } while( curidx < entry.GetDataSize() );
+
+ woot.CloseEntry();
+ }
- do {
- int thisBlockSize = std::min( BlockSize, m_src_buffer->GetSizeInBytes() - curidx );
- m_gzfp->Write(m_src_buffer->GetPtr(curidx), thisBlockSize);
- curidx += thisBlockSize;
- Yield( 2 );
- } while( curidx < m_src_buffer->GetSizeInBytes() );
- //m_gzfp->CloseEntry();
m_gzfp->Close();
if( !wxRenameFile( m_gzfp->GetStreamName(), m_final_filename, true ) )
diff --git a/pcsx2/gui/SysState.cpp b/pcsx2/gui/SysState.cpp
index 527ff9e67a..018f793105 100644
--- a/pcsx2/gui/SysState.cpp
+++ b/pcsx2/gui/SysState.cpp
@@ -19,10 +19,11 @@
#include "System/SysThreads.h"
#include "SaveState.h"
+#include "VUmicro.h"
#include "ZipTools/ThreadedZipTools.h"
-#include "wx/wfstream.h"
+#include
// Used to hold the current state backup (fullcopy of PS2 memory and plugin states).
//static VmStateBuffer state_buffer( L"Public Savestate Buffer" );
@@ -31,54 +32,88 @@ static const wxChar* EntryFilename_StateVersion = L"PCSX2 Savestate Version.id
static const wxChar* EntryFilename_Screenshot = L"Screenshot.jpg";
static const wxChar* EntryFilename_InternalStructures = L"PCSX2 Internal Structures.bin";
-class BaseSavestateEntry
-{
-public:
- virtual const wxChar* GetFilename() const=0;
- virtual void* GetDataPtr() const=0;
- virtual uint GetDataSize() const=0;
-};
-class SavestateEntry_EmotionMemory : public BaseSavestateEntry
+// --------------------------------------------------------------------------------------
+// SavestateEntry_* (EmotionMemory, IopMemory, etc)
+// --------------------------------------------------------------------------------------
+// Implementation Rationale:
+// The address locations of PS2 virtual memory components is fully dynamic, so we need to
+// resolve the pointers at the time they are requested (eeMem, iopMem, etc). Thusly, we
+// cannot use static struct member initializers -- we need virtual functions that compute
+// and resolve the addresses on-demand instead... --air
+
+class SavestateEntry_EmotionMemory : public BaseArchiveEntry
{
public:
- const wxChar* GetFilename() const { return L"eeMemory.bin"; }
- void* GetDataPtr() const { return eeMem->Main; }
+ wxString GetFilename() const { return L"eeMemory.bin"; }
+ u8* GetDataPtr() const { return eeMem->Main; }
uint GetDataSize() const { return sizeof(eeMem->Main); }
};
-class SavestateEntry_IopMemory : public BaseSavestateEntry
+class SavestateEntry_IopMemory : public BaseArchiveEntry
{
public:
- const wxChar* GetFilename() const { return L"iopMemory.bin"; }
- void* GetDataPtr() const { return iopMem->Main; }
+ wxString GetFilename() const { return L"iopMemory.bin"; }
+ u8* GetDataPtr() const { return iopMem->Main; }
uint GetDataSize() const { return sizeof(iopMem->Main); }
};
-class SavestateEntry_HwRegs : public BaseSavestateEntry
+class SavestateEntry_HwRegs : public BaseArchiveEntry
{
public:
- const wxChar* GetFilename() const { return L"eeHwRegs.bin"; }
- void* GetDataPtr() const { return eeHw; }
+ wxString GetFilename() const { return L"eeHwRegs.bin"; }
+ u8* GetDataPtr() const { return eeHw; }
uint GetDataSize() const { return sizeof(eeHw); }
};
-class SavestateEntry_IopHwRegs : public BaseSavestateEntry
+class SavestateEntry_IopHwRegs : public BaseArchiveEntry
{
public:
- const wxChar* GetFilename() const { return L"iopHwRegs.bin"; }
- void* GetDataPtr() const { return iopHw; }
+ wxString GetFilename() const { return L"iopHwRegs.bin"; }
+ u8* GetDataPtr() const { return iopHw; }
uint GetDataSize() const { return sizeof(iopHw); }
};
-class SavestateEntry_Scratchpad : public BaseSavestateEntry
+class SavestateEntry_Scratchpad : public BaseArchiveEntry
{
public:
- const wxChar* GetFilename() const { return L"Scratchpad.bin"; }
- void* GetDataPtr() const { return eeMem->Scratch; }
+ wxString GetFilename() const { return L"Scratchpad.bin"; }
+ u8* GetDataPtr() const { return eeMem->Scratch; }
uint GetDataSize() const { return sizeof(eeMem->Scratch); }
};
+class SavestateEntry_VU0mem : public BaseArchiveEntry
+{
+public:
+ wxString GetFilename() const { return L"vu0Memory.bin"; }
+ u8* GetDataPtr() const { return vuRegs[0].Mem; }
+ uint GetDataSize() const { return VU0_MEMSIZE; }
+};
+
+class SavestateEntry_VU1mem : public BaseArchiveEntry
+{
+public:
+ wxString GetFilename() const { return L"vu1Memory.bin"; }
+ u8* GetDataPtr() const { return vuRegs[1].Mem; }
+ uint GetDataSize() const { return VU1_MEMSIZE; }
+};
+
+class SavestateEntry_VU0prog : public BaseArchiveEntry
+{
+public:
+ wxString GetFilename() const { return L"vu0Programs.bin"; }
+ u8* GetDataPtr() const { return vuRegs[0].Micro; }
+ uint GetDataSize() const { return VU0_PROGSIZE; }
+};
+
+class SavestateEntry_VU1prog : public BaseArchiveEntry
+{
+public:
+ wxString GetFilename() const { return L"vu1Programs.bin"; }
+ u8* GetDataPtr() const { return vuRegs[1].Micro; }
+ uint GetDataSize() const { return VU1_PROGSIZE; }
+};
+
// [TODO] : Add other components as files to the savestate gzip?
// * VU0/VU1 memory banks? VU0prog, VU1prog, VU0data, VU1data.
// * GS register data?
@@ -88,13 +123,17 @@ public:
// would not be useful).
//
-static const BaseSavestateEntry* const SavestateEntries[] =
+static const BaseArchiveEntry* const SavestateEntries[] =
{
new SavestateEntry_EmotionMemory,
new SavestateEntry_IopMemory,
new SavestateEntry_HwRegs,
new SavestateEntry_IopHwRegs,
new SavestateEntry_Scratchpad,
+ new SavestateEntry_VU0mem,
+ new SavestateEntry_VU1mem,
+ new SavestateEntry_VU0prog,
+ new SavestateEntry_VU1prog,
};
static const uint NumSavestateEntries = ArraySize(SavestateEntries);
@@ -107,7 +146,7 @@ static const uint NumSavestateEntries = ArraySize(SavestateEntries);
//
static Mutex mtx_CompressToDisk;
-static void CheckVersion( pxStreamReader& thr )
+static void CheckVersion( pxInputStream& thr )
{
u32 savever;
thr.Read( savever );
@@ -135,16 +174,16 @@ static void CheckVersion( pxStreamReader& thr )
class SysExecEvent_DownloadState : public SysExecEvent
{
protected:
- VmStateBuffer* m_dest_buffer;
+ ArchiveEntryList* m_dest_list;
public:
wxString GetEventName() const { return L"VM_Download"; }
virtual ~SysExecEvent_DownloadState() throw() {}
SysExecEvent_DownloadState* Clone() const { return new SysExecEvent_DownloadState( *this ); }
- SysExecEvent_DownloadState( VmStateBuffer* dest=NULL )
+ SysExecEvent_DownloadState( ArchiveEntryList* dest_list=NULL )
{
- m_dest_buffer = dest;
+ m_dest_list = dest_list;
}
bool IsCriticalEvent() const { return true; }
@@ -160,9 +199,25 @@ protected:
.SetDiagMsg(L"SysExecEvent_DownloadState: Cannot freeze/download an invalid VM state!")
.SetUserMsg(L"There is no active virtual machine state to download or save." );
- memSavingState saveme( m_dest_buffer );
+ memSavingState saveme( m_dest_list->GetBuffer() );
+ ArchiveEntry internals( EntryFilename_InternalStructures );
+ internals.SetDataIndex( saveme.GetCurrentPos() );
+
saveme.FreezeAll();
+ internals.SetDataSize( saveme.GetCurrentPos() - internals.GetDataIndex() );
+ m_dest_list->Add( internals );
+
+ for (uint i=0; iAdd( ArchiveEntry( SavestateEntries[i]->GetFilename() )
+ .SetDataIndex( saveme.GetCurrentPos() )
+ .SetDataSize( SavestateEntries[i]->GetDataSize() )
+ );
+
+ saveme.FreezeMem( SavestateEntries[i]->GetDataPtr(), SavestateEntries[i]->GetDataSize() );
+ }
+
UI_EnableStateActions();
paused_core.AllowResume();
}
@@ -180,14 +235,7 @@ protected:
ScopedLock m_lock_Compress;
public:
- VmStateCompressThread( VmStateBuffer* srcdata, pxStreamWriter* outarchive )
- : _parent( srcdata, outarchive )
- {
- m_lock_Compress.Assign(mtx_CompressToDisk);
- }
-
- VmStateCompressThread( ScopedPtr& srcdata, ScopedPtr& outarchive )
- : _parent( srcdata, outarchive )
+ VmStateCompressThread()
{
m_lock_Compress.Assign(mtx_CompressToDisk);
}
@@ -216,7 +264,7 @@ protected:
class SysExecEvent_ZipToDisk : public SysExecEvent
{
protected:
- VmStateBuffer* m_src_buffer;
+ ArchiveEntryList* m_src_list;
wxString m_filename;
public:
@@ -228,16 +276,16 @@ public:
SysExecEvent_ZipToDisk* Clone() const { return new SysExecEvent_ZipToDisk( *this ); }
- SysExecEvent_ZipToDisk( ScopedPtr& src, const wxString& filename )
+ SysExecEvent_ZipToDisk( ScopedPtr& srclist, const wxString& filename )
: m_filename( filename )
{
- m_src_buffer = src.DetachPtr();
+ m_src_list = srclist.DetachPtr();
}
- SysExecEvent_ZipToDisk( VmStateBuffer* src, const wxString& filename )
+ SysExecEvent_ZipToDisk( ArchiveEntryList* srclist, const wxString& filename )
: m_filename( filename )
{
- m_src_buffer = src;
+ m_src_list = srclist;
}
bool IsCriticalEvent() const { return true; }
@@ -246,6 +294,9 @@ public:
protected:
void InvokeEvent()
{
+ // Provisionals for scoped cleanup, in case of exception:
+ ScopedPtr elist( m_src_list );
+
wxString tempfile( m_filename + L".tmp" );
wxFFileOutputStream* woot = new wxFFileOutputStream(tempfile);
@@ -253,8 +304,8 @@ protected:
throw Exception::CannotCreateStream(tempfile);
// Write the version and screenshot:
- ScopedPtr out( new pxStreamWriter(tempfile, new wxZipOutputStream(woot)) );
- wxZipOutputStream* gzfp = (wxZipOutputStream*)out->GetBaseStream();
+ ScopedPtr out( new pxOutputStream(tempfile, new wxZipOutputStream(woot)) );
+ wxZipOutputStream* gzfp = (wxZipOutputStream*)out->GetWxStreamBase();
{
wxZipEntry* vent = new wxZipEntry(EntryFilename_StateVersion);
@@ -277,16 +328,21 @@ protected:
//m_gzfp->PutNextEntry(EntryFilename_Screenshot);
- //m_gzfp->Write();
+ //m_gzfp->Write();
//m_gzfp->CloseEntry();
- (new VmStateCompressThread( m_src_buffer, out ))->
- SetTargetFilename(m_filename).Start();
+ (*new VmStateCompressThread())
+ .SetSource(m_src_list)
+ .SetOutStream(out)
+ .SetFinishedPath(m_filename)
+ .Start();
+
+ // No errors? Release cleanup handlers:
+ elist.DetachPtr();
}
void CleanupEvent()
{
- m_src_buffer = NULL;
}
};
@@ -325,8 +381,7 @@ protected:
if (!woot->IsOk())
throw Exception::CannotCreateStream( m_filename ).SetDiagMsg(L"Cannot open file for reading.");
-
- ScopedPtr reader( new pxStreamReader(m_filename, new wxZipInputStream(woot)) );
+ ScopedPtr reader( new pxInputStream(m_filename, new wxZipInputStream(woot)) );
woot.DetachPtr();
if (!reader->IsOk())
@@ -336,7 +391,7 @@ protected:
.SetUserMsg(_("This savestate cannot be loaded because it is not a valid gzip archive. It may have been created by an older unsupported version of PCSX2, or it may be corrupted."));
}
- wxZipInputStream* gzreader = (wxZipInputStream*)reader->GetBaseStream();
+ wxZipInputStream* gzreader = (wxZipInputStream*)reader->GetWxStreamBase();
// look for version and screenshot information in the zip stream:
@@ -359,12 +414,14 @@ protected:
DevCon.WriteLn(L" ... found '%s'", EntryFilename_StateVersion);
foundVersion = true;
CheckVersion(*reader);
+ continue;
}
if (entry->GetName().CmpNoCase(EntryFilename_InternalStructures) == 0)
{
DevCon.WriteLn(L" ... found '%s'", EntryFilename_InternalStructures);
foundInternal = entry.DetachPtr();
+ continue;
}
// No point in finding screenshots when loading states -- the screenshots are
@@ -411,6 +468,7 @@ protected:
// *ALWAYS* start execution after the new savestate is loaded.
GetCoreThread().Pause();
+ SysClearExecutionCache();
for (uint i=0; iGetSize(), L"StateBuffer_UnzipFromDisk" ); // start with an 8 meg buffer to avoid frequent reallocation.
reader->Read( buffer.GetPtr(), foundInternal->GetSize() );
- //GetCoreThread().UploadStateCopy( buffer );
memLoadingState( buffer ).FreezeAll();
GetCoreThread().Resume(); // force resume regardless of emulation state earlier.
}
@@ -451,9 +508,10 @@ void StateCopy_SaveToFile( const wxString& file )
{
UI_DisableStateActions();
- ScopedPtr zipbuf(new VmStateBuffer( L"Zippable Savestate" ));
- GetSysExecutorThread().PostEvent(new SysExecEvent_DownloadState( zipbuf ));
- GetSysExecutorThread().PostEvent(new SysExecEvent_ZipToDisk( zipbuf, file ));
+ ScopedPtr ziplist (new ArchiveEntryList( new VmStateBuffer( L"Zippable Savestate" ) ));
+
+ GetSysExecutorThread().PostEvent(new SysExecEvent_DownloadState ( ziplist ));
+ GetSysExecutorThread().PostEvent(new SysExecEvent_ZipToDisk ( ziplist, file ));
}
void StateCopy_LoadFromFile( const wxString& file )