diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index 7c9266e4f1..9806d9869f 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -1265,15 +1265,6 @@ set(pcsx2UtilitiesSources set(pcsx2UtilitiesHeaders Utilities/AsciiFile.h) -# Zip tools utilies sources -set(pcsx2ZipToolsSources - ZipTools/thread_gzip.cpp - ZipTools/thread_lzma.cpp) - -# Zip tools utilies headers -set(pcsx2ZipToolsHeaders - ZipTools/ThreadedZipTools.h) - # Windows sources set(pcsx2WindowsSources @@ -1408,9 +1399,7 @@ target_sources(PCSX2 PRIVATE ${pcsx2SystemSources} ${pcsx2SystemHeaders} ${pcsx2UtilitiesSources} - ${pcsx2UtilitiesHeaders} - ${pcsx2ZipToolsSources} - ${pcsx2ZipToolsHeaders}) + ${pcsx2UtilitiesHeaders}) # platform sources # Linux diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp index adf27cfd8e..fe6c97598b 100644 --- a/pcsx2/SaveState.cpp +++ b/pcsx2/SaveState.cpp @@ -28,8 +28,8 @@ #include "Elfheader.h" #include "Counters.h" #include "Patch.h" +#include "System/SysThreads.h" -#include "ZipTools/ThreadedZipTools.h" #include "common/pxStreams.h" #include "common/SafeArray.inl" #include "SPU2/spu2.h" @@ -44,6 +44,14 @@ #include "gui/ConsoleLogger.h" +#ifndef PCSX2_CORE +#include "gui/App.h" +#endif + +#include "common/pxStreams.h" +#include +#include + using namespace R5900; @@ -663,7 +671,7 @@ static void CheckVersion(pxInputStream& thr) void SaveState_DownloadState(ArchiveEntryList* destlist) { - if (!SysHasValidState()) + if (!GetCoreThread().HasActiveMachine()) throw Exception::RuntimeError() .SetDiagMsg(L"SysExecEvent_DownloadState: Cannot freeze/download an invalid VM state!") .SetUserMsg(_("There is no active virtual machine state to download or save.")); @@ -691,54 +699,13 @@ void SaveState_DownloadState(ArchiveEntryList* destlist) // -------------------------------------------------------------------------------------- // CompressThread_VmState // -------------------------------------------------------------------------------------- -class VmStateCompressThread : public BaseCompressThread +static void ZipStateToDiskOnThread(std::unique_ptr srclist, std::unique_ptr outbase, wxString filename, wxString tempfile) { - typedef BaseCompressThread _parent; +#ifndef PCSX2_CORE + wxGetApp().StartPendingSave(); +#endif -protected: - ScopedLock m_lock_Compress; - -public: - VmStateCompressThread() - { - m_lock_Compress.Assign(mtx_CompressToDisk); - } - - virtual ~VmStateCompressThread() = default; - -protected: - void OnStartInThread() - { - _parent::OnStartInThread(); - m_lock_Compress.Acquire(); - } - - void OnCleanupInThread() - { - m_lock_Compress.Release(); - _parent::OnCleanupInThread(); - } -}; - -void SaveState_ZipToDisk(ArchiveEntryList* srclist, const wxString& filename) -{ - // Provisionals for scoped cleanup, in case of exception: - std::unique_ptr elist(srclist); - - wxString tempfile(filename + L".tmp"); - - wxFFileOutputStream* woot = new wxFFileOutputStream(tempfile); - if (!woot->IsOk()) - throw Exception::CannotCreateStream(tempfile); - - // Scheduler hint (yield) -- creating and saving the file is low priority compared to - // the emulator/vm thread. Sleeping the executor thread briefly before doing file - // transactions should help reduce overhead. --air - - pxYield(4); - - // Write the version and screenshot: - std::unique_ptr out(new pxOutputStream(tempfile, new wxZipOutputStream(woot))); + std::unique_ptr out(new pxOutputStream(tempfile, new wxZipOutputStream(outbase.release()))); wxZipOutputStream* gzfp = (wxZipOutputStream*)out->GetWxStreamBase(); { @@ -749,8 +716,9 @@ void SaveState_ZipToDisk(ArchiveEntryList* srclist, const wxString& filename) gzfp->CloseEntry(); } +#if 0 + // This was never actually initialized... std::unique_ptr m_screenshot; - if (m_screenshot) { wxZipEntry* vent = new wxZipEntry(EntryFilename_Screenshot); @@ -759,16 +727,61 @@ void SaveState_ZipToDisk(ArchiveEntryList* srclist, const wxString& filename) m_screenshot->SaveFile(*gzfp, wxBITMAP_TYPE_JPEG); gzfp->CloseEntry(); } +#endif - (*new VmStateCompressThread()) - .SetSource(srclist) - .SetOutStream(out.get()) - .SetFinishedPath(filename) - .Start(); + uint listlen = srclist->GetLength(); + for (uint i = 0; i < listlen; ++i) + { + const ArchiveEntry& entry = (*srclist)[i]; + if (!entry.GetDataSize()) + continue; - // No errors? Release cleanup handlers: - elist.release(); - out.release(); + gzfp->PutNextEntry(entry.GetFilename()); + + static const uint BlockSize = 0x64000; + uint curidx = 0; + + do + { + uint thisBlockSize = std::min(BlockSize, entry.GetDataSize() - curidx); + gzfp->Write(srclist->GetPtr(entry.GetDataIndex() + curidx), thisBlockSize); + curidx += thisBlockSize; + } while (curidx < entry.GetDataSize()); + + gzfp->CloseEntry(); + } + + gzfp->Close(); + + if (!wxRenameFile(out->GetStreamName(), filename, true)) + { + Console.Error("Failed to rename save state '%s' to '%s'", static_cast(out->GetStreamName().c_str()), static_cast(filename.c_str())); +#ifndef PCSX2_CORE + Msgbox::Alert(_("The savestate was not properly saved. The temporary file was created successfully but could not be moved to its final resting place.")); +#endif + } + else + { + Console.WriteLn("(gzipThread) Data saved to disk without error."); + } + +#ifndef PCSX2_CORE + wxGetApp().ClearPendingSave(); +#endif +} + +void SaveState_ZipToDisk(ArchiveEntryList* srclist, const wxString& filename) +{ + // Provisionals for scoped cleanup, in case of exception: + std::unique_ptr elist(srclist); + + wxString tempfile(filename + L".tmp"); + std::unique_ptr out = std::make_unique(tempfile); + if (!out->IsOk()) + throw Exception::CannotCreateStream(tempfile); + + std::thread threaded_save(ZipStateToDiskOnThread, std::move(elist), std::move(out), filename, tempfile); + threaded_save.detach(); } void SaveState_UnzipFromDisk(const wxString& filename) diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index a9fe7d8093..4789f48f9c 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -179,6 +179,124 @@ protected: void InputRecordingFreeze(); }; +// -------------------------------------------------------------------------------------- +// 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() = default; + + 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; + std::unique_ptr m_data; + +public: + virtual ~ArchiveEntryList() = default; + + ArchiveEntryList() {} + + ArchiveEntryList(ArchiveDataBuffer* data) + : m_data(data) + { + } + + ArchiveEntryList(ArchiveDataBuffer& data) + : m_data(&data) + { + } + + const VmStateBuffer* GetBuffer() const + { + return m_data.get(); + } + + VmStateBuffer* GetBuffer() + { + return m_data.get(); + } + + 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]; + } +}; + // -------------------------------------------------------------------------------------- // Saving and Loading Specialized Implementations... // -------------------------------------------------------------------------------------- diff --git a/pcsx2/ZipTools/FolderDesc.txt b/pcsx2/ZipTools/FolderDesc.txt deleted file mode 100644 index 71d05a060b..0000000000 --- a/pcsx2/ZipTools/FolderDesc.txt +++ /dev/null @@ -1,10 +0,0 @@ - -------------------- - ZipTools (folder) -------------------- - -Contains C++ interfaces for zipping to/from various formats -(primarily gzip and 7zip). - -Notice: This folder is intended to be moved to a utility folder -outside the main PCSX2 folders at a later date. \ No newline at end of file diff --git a/pcsx2/ZipTools/ThreadedZipTools.h b/pcsx2/ZipTools/ThreadedZipTools.h deleted file mode 100644 index 50fe333b53..0000000000 --- a/pcsx2/ZipTools/ThreadedZipTools.h +++ /dev/null @@ -1,209 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#pragma once - -#include "common/PersistentThread.h" -#include "common/pxStreams.h" -#include "wx/zipstrm.h" - -using namespace Threading; - -// -------------------------------------------------------------------------------------- -// 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() = default; - - 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; - std::unique_ptr m_data; - -public: - virtual ~ArchiveEntryList() = default; - - ArchiveEntryList() {} - - ArchiveEntryList( ArchiveDataBuffer* data ) - : m_data(data) - { - } - - ArchiveEntryList( ArchiveDataBuffer& data ) - : m_data(&data) - { - } - - const VmStateBuffer* GetBuffer() const - { - return m_data.get(); - } - - VmStateBuffer* GetBuffer() - { - return m_data.get(); - } - - 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 -// -------------------------------------------------------------------------------------- -class BaseCompressThread - : public pxThread -{ - typedef pxThread _parent; - -protected: - pxOutputStream* m_gzfp; - ArchiveEntryList* m_src_list; - bool m_PendingSaveFlag; - - wxString m_final_filename; - -public: - virtual ~BaseCompressThread(); - - BaseCompressThread& SetSource( ArchiveEntryList* srcdata ) - { - m_src_list = srcdata; - return *this; - } - - BaseCompressThread& SetSource( ArchiveEntryList& srcdata ) - { - m_src_list = &srcdata; - return *this; - } - - BaseCompressThread& SetOutStream( pxOutputStream* out ) - { - m_gzfp = out; - return *this; - } - - BaseCompressThread& SetOutStream( pxOutputStream& out ) - { - m_gzfp = &out; - 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) - { - m_final_filename = filename; - return *this; - } - -protected: - BaseCompressThread() - { - m_gzfp = NULL; - m_src_list = NULL; - m_PendingSaveFlag = false; - } - - void SetPendingSave(); - void ExecuteTaskInThread(); - void OnCleanupInThread(); -}; diff --git a/pcsx2/ZipTools/thread_gzip.cpp b/pcsx2/ZipTools/thread_gzip.cpp deleted file mode 100644 index bc2a7d4001..0000000000 --- a/pcsx2/ZipTools/thread_gzip.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#include "PrecompiledHeader.h" - -#include "gui/App.h" -#include "SaveState.h" -#include "ThreadedZipTools.h" -#include "common/SafeArray.inl" -#include "wx/wfstream.h" - - -BaseCompressThread::~BaseCompressThread() -{ - try { - _parent::Cancel(); - if( m_PendingSaveFlag ) - { - wxGetApp().ClearPendingSave(); - m_PendingSaveFlag = false; - } - } - DESTRUCTOR_CATCHALL -} - -void BaseCompressThread::SetPendingSave() -{ - wxGetApp().StartPendingSave(); - m_PendingSaveFlag = true; -} - -void BaseCompressThread::ExecuteTaskInThread() -{ - // TODO : Add an API to PersistentThread for this! :) --air - //SetThreadPriority( THREAD_PRIORITY_BELOW_NORMAL ); - - // 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 ); - - 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(); - } - - m_gzfp->Close(); - - if( !wxRenameFile( m_gzfp->GetStreamName(), m_final_filename, true ) ) - throw Exception::BadStream( m_final_filename ) - .SetDiagMsg(L"Failed to move or copy the temporary archive to the destination filename.") - .SetUserMsg(_("The savestate was not properly saved. The temporary file was created successfully but could not be moved to its final resting place.")); - - Console.WriteLn( "(gzipThread) Data saved to disk without error." ); -} - -void BaseCompressThread::OnCleanupInThread() -{ - _parent::OnCleanupInThread(); - wxGetApp().DeleteThread( this ); - - safe_delete(m_gzfp); - safe_delete(m_src_list); -} - diff --git a/pcsx2/ZipTools/thread_lzma.cpp b/pcsx2/ZipTools/thread_lzma.cpp deleted file mode 100644 index 48c9329f20..0000000000 --- a/pcsx2/ZipTools/thread_lzma.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#include "PrecompiledHeader.h" - diff --git a/pcsx2/gui/SysState.cpp b/pcsx2/gui/SysState.cpp index cb3978a49f..5391fa0980 100644 --- a/pcsx2/gui/SysState.cpp +++ b/pcsx2/gui/SysState.cpp @@ -21,7 +21,6 @@ #include "SaveState.h" #include "VUmicro.h" -#include "ZipTools/ThreadedZipTools.h" #include "common/pxStreams.h" #include "SPU2/spu2.h" #include "USB/USB.h" diff --git a/pcsx2/pcsx2.vcxproj b/pcsx2/pcsx2.vcxproj index 6e22520c23..85116ec495 100644 --- a/pcsx2/pcsx2.vcxproj +++ b/pcsx2/pcsx2.vcxproj @@ -697,8 +697,6 @@ - - @@ -1089,7 +1087,6 @@ - diff --git a/pcsx2/pcsx2.vcxproj.filters b/pcsx2/pcsx2.vcxproj.filters index 8dbb9e1759..f186abedfa 100644 --- a/pcsx2/pcsx2.vcxproj.filters +++ b/pcsx2/pcsx2.vcxproj.filters @@ -863,12 +863,6 @@ AppHost - - Misc - - - Misc - Misc @@ -2017,9 +2011,6 @@ AppHost\Include - - Misc - Misc