From 3b7ba395909dabf421ca2e8e9dbe428e97595b95 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 2 Apr 2016 03:40:59 +0200 Subject: [PATCH 1/2] Fix potential access of free'd memory when re-opening an already open folder memory card. --- pcsx2/gui/MemoryCardFolder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pcsx2/gui/MemoryCardFolder.cpp b/pcsx2/gui/MemoryCardFolder.cpp index 4cd336059b..0aa7c7ff6e 100644 --- a/pcsx2/gui/MemoryCardFolder.cpp +++ b/pcsx2/gui/MemoryCardFolder.cpp @@ -42,11 +42,11 @@ void FolderMemoryCard::InitializeInternalData() { memset( &m_backupBlock2, 0xFF, sizeof( m_backupBlock2 ) ); m_cache.clear(); m_oldDataCache.clear(); + m_lastAccessedFile.CloseAll(); m_fileMetadataQuickAccess.clear(); m_timeLastWritten = 0; m_isEnabled = false; m_framesUntilFlush = 0; - m_lastAccessedFile.CloseAll(); m_performFileWrites = true; } From 97a68becb9060d117cb5caa9c83c576acd75c188 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 2 Apr 2016 03:44:11 +0200 Subject: [PATCH 2/2] Handle filter management in the folder memcard class rather than outside. This prevents desync between what is assumed to be the active filter and what is actually the active filter, fixing errors like #1179 where the memory cards are closed and reopened for whatever reason. --- common/include/PluginCallbacks.h | 2 +- pcsx2/PluginManager.cpp | 4 ++-- pcsx2/Plugins.h | 2 +- pcsx2/Sio.cpp | 34 ++++++++++++++++++++------------ pcsx2/Sio.h | 4 ++-- pcsx2/gui/MemoryCardFile.cpp | 8 ++++---- pcsx2/gui/MemoryCardFolder.cpp | 30 +++++++++++++++++++++++----- pcsx2/gui/MemoryCardFolder.h | 11 ++++++++++- 8 files changed, 66 insertions(+), 29 deletions(-) diff --git a/common/include/PluginCallbacks.h b/common/include/PluginCallbacks.h index 7fdec1bf57..db4635d927 100644 --- a/common/include/PluginCallbacks.h +++ b/common/include/PluginCallbacks.h @@ -1109,7 +1109,7 @@ typedef struct _PS2E_ComponentAPI_Mcd // Used by the FolderMemoryCard to find a good time to flush written data to the host file system. void (PS2E_CALLBACK* McdNextFrame)( PS2E_THISPTR thisptr, uint port, uint slot ); - void (PS2E_CALLBACK* McdReIndex)( PS2E_THISPTR thisptr, uint port, uint slot, const wxString& filter ); + bool (PS2E_CALLBACK* McdReIndex)( PS2E_THISPTR thisptr, uint port, uint slot, const wxString& filter ); void* reserved[6]; diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp index 1a29b8db19..585f3a383f 100644 --- a/pcsx2/PluginManager.cpp +++ b/pcsx2/PluginManager.cpp @@ -70,8 +70,8 @@ void SysPluginBindings::McdNextFrame( uint port, uint slot ) { Mcd->McdNextFrame( (PS2E_THISPTR) Mcd, port, slot ); } -void SysPluginBindings::McdReIndex( uint port, uint slot, const wxString& filter ) { - Mcd->McdReIndex( (PS2E_THISPTR) Mcd, port, slot, filter ); +bool SysPluginBindings::McdReIndex( uint port, uint slot, const wxString& filter ) { + return Mcd->McdReIndex( (PS2E_THISPTR) Mcd, port, slot, filter ); } // ---------------------------------------------------------------------------- diff --git a/pcsx2/Plugins.h b/pcsx2/Plugins.h index 1bfe4f6629..d08a87a7f2 100644 --- a/pcsx2/Plugins.h +++ b/pcsx2/Plugins.h @@ -242,7 +242,7 @@ public: void McdEraseBlock( uint port, uint slot, u32 adr ); u64 McdGetCRC( uint port, uint slot ); void McdNextFrame( uint port, uint slot ); - void McdReIndex( uint port, uint slot, const wxString& filter ); + bool McdReIndex( uint port, uint slot, const wxString& filter ); friend class SysCorePlugins; }; diff --git a/pcsx2/Sio.cpp b/pcsx2/Sio.cpp index fa9f10a784..c55c1fd350 100644 --- a/pcsx2/Sio.cpp +++ b/pcsx2/Sio.cpp @@ -53,18 +53,30 @@ wxString GetTimeMsStr(){ } //allow timeout also for the mcd manager panel +void SetForceMcdEjectTimeoutNow( uint port, uint slot ) +{ + mcds[port][slot].ForceEjection_Timeout = FORCED_MCD_EJECTION_MAX_TRIES; +} void SetForceMcdEjectTimeoutNow() { - for( u8 port=0; port<2; ++port ) - for( u8 slot=0; slot<4; ++slot ) - mcds[port][slot].ForceEjection_Timeout = FORCED_MCD_EJECTION_MAX_TRIES; + for ( uint port = 0; port < 2; ++port ) { + for ( uint slot = 0; slot < 4; ++slot ) { + SetForceMcdEjectTimeoutNow( port, slot ); + } + } } +void ClearMcdEjectTimeoutNow( uint port, uint slot ) +{ + mcds[port][slot].ForceEjection_Timeout = 0; +} void ClearMcdEjectTimeoutNow() { - for( u8 port=0; port<2; ++port ) - for( u8 slot=0; slot<4; ++slot ) - mcds[port][slot].ForceEjection_Timeout = 0; + for ( uint port = 0; port < 2; ++port ) { + for ( uint slot = 0; slot < 4; ++slot ) { + ClearMcdEjectTimeoutNow( port, slot ); + } + } } // SIO Inline'd IRQs : Calls the SIO interrupt handlers directly instead of @@ -886,18 +898,14 @@ void sioNextFrame() { } } -// Used to figure out when a new game boots, so that memory cards can re-index themselves and only load data relevant to that game. -wxString SioCurrentGameSerial = L""; void sioSetGameSerial( const wxString& serial ) { - if ( serial == SioCurrentGameSerial ) { return; } - SioCurrentGameSerial = serial; - for ( uint port = 0; port < 2; ++port ) { for ( uint slot = 0; slot < 4; ++slot ) { - mcds[port][slot].ReIndex( serial ); + if ( mcds[port][slot].ReIndex( serial ) ) { + SetForceMcdEjectTimeoutNow( port, slot ); + } } } - SetForceMcdEjectTimeoutNow(); } void SaveStateBase::sioFreeze() diff --git a/pcsx2/Sio.h b/pcsx2/Sio.h index 512fc3009d..c77d8252dc 100644 --- a/pcsx2/Sio.h +++ b/pcsx2/Sio.h @@ -87,8 +87,8 @@ struct _mcd SysPlugins.McdNextFrame( port, slot ); } - void ReIndex(const wxString& filter = L"") { - SysPlugins.McdReIndex( port, slot, filter ); + bool ReIndex(const wxString& filter = L"") { + return SysPlugins.McdReIndex( port, slot, filter ); } }; diff --git a/pcsx2/gui/MemoryCardFile.cpp b/pcsx2/gui/MemoryCardFile.cpp index 07d2e64a3f..09b1f25775 100644 --- a/pcsx2/gui/MemoryCardFile.cpp +++ b/pcsx2/gui/MemoryCardFile.cpp @@ -562,17 +562,17 @@ static void PS2E_CALLBACK FileMcd_NextFrame( PS2E_THISPTR thisptr, uint port, ui } } -static void PS2E_CALLBACK FileMcd_ReIndex( PS2E_THISPTR thisptr, uint port, uint slot, const wxString& filter ) { +static bool PS2E_CALLBACK FileMcd_ReIndex( PS2E_THISPTR thisptr, uint port, uint slot, const wxString& filter ) { const uint combinedSlot = FileMcd_ConvertToSlot( port, slot ); switch ( g_Conf->Mcd[combinedSlot].Type ) { //case MemoryCardType::MemoryCard_File: - // thisptr->impl.ReIndex( combinedSlot, filter ); + // return thisptr->impl.ReIndex( combinedSlot, filter ); // break; case MemoryCardType::MemoryCard_Folder: - thisptr->implFolder.ReIndex( combinedSlot, g_Conf->EmuOptions.McdFolderAutoManage, filter ); + return thisptr->implFolder.ReIndex( combinedSlot, g_Conf->EmuOptions.McdFolderAutoManage, filter ); break; default: - return; + return false; } } diff --git a/pcsx2/gui/MemoryCardFolder.cpp b/pcsx2/gui/MemoryCardFolder.cpp index 0aa7c7ff6e..6b72c5cfa6 100644 --- a/pcsx2/gui/MemoryCardFolder.cpp +++ b/pcsx2/gui/MemoryCardFolder.cpp @@ -32,6 +32,8 @@ FolderMemoryCard::FolderMemoryCard() { m_performFileWrites = false; m_framesUntilFlush = 0; m_timeLastWritten = 0; + m_filteringEnabled = false; + m_filteringString = L""; } void FolderMemoryCard::InitializeInternalData() { @@ -48,6 +50,8 @@ void FolderMemoryCard::InitializeInternalData() { m_isEnabled = false; m_framesUntilFlush = 0; m_performFileWrites = true; + m_filteringEnabled = false; + m_filteringString = L""; } bool FolderMemoryCard::IsFormatted() const { @@ -94,6 +98,8 @@ void FolderMemoryCard::Open( const wxString& fullPath, const AppConfig::McdOptio if ( disabled ) return; m_isEnabled = true; + m_filteringEnabled = enableFiltering; + m_filteringString = filter; LoadMemoryCardData( sizeInClusters, enableFiltering, filter ); SetTimeLastWrittenToNow(); @@ -113,6 +119,18 @@ void FolderMemoryCard::Close( bool flush ) { m_fileMetadataQuickAccess.clear(); } +bool FolderMemoryCard::ReIndex( bool enableFiltering, const wxString& filter ) { + if ( !m_isEnabled ) { return false; } + + if ( m_filteringEnabled != enableFiltering || m_filteringString != filter ) { + Close(); + Open( enableFiltering, filter ); + return true; + } + + return false; +} + void FolderMemoryCard::LoadMemoryCardData( const u32 sizeInClusters, const bool enableFiltering, const wxString& filter ) { bool formatted = false; @@ -1648,11 +1666,13 @@ void FolderMemoryCardAggregator::NextFrame( uint slot ) { m_cards[slot].NextFrame(); } -void FolderMemoryCardAggregator::ReIndex( uint slot, const bool enableFiltering, const wxString& filter ) { - m_cards[slot].Close(); - m_cards[slot].Open( enableFiltering, filter ); +bool FolderMemoryCardAggregator::ReIndex( uint slot, const bool enableFiltering, const wxString& filter ) { + if ( m_cards[slot].ReIndex( enableFiltering, filter ) ) { + SetFiltering( enableFiltering ); + m_lastKnownFilter = filter; + return true; + } - SetFiltering( enableFiltering ); - m_lastKnownFilter = filter; + return false; } diff --git a/pcsx2/gui/MemoryCardFolder.h b/pcsx2/gui/MemoryCardFolder.h index da320e36ba..cd6934d3ac 100644 --- a/pcsx2/gui/MemoryCardFolder.h +++ b/pcsx2/gui/MemoryCardFolder.h @@ -327,6 +327,10 @@ protected: // if set to false, nothing is actually written to the file system while flushing, and data is discarded instead bool m_performFileWrites; + // currently active filter settings + bool m_filteringEnabled; + wxString m_filteringString; + public: FolderMemoryCard(); virtual ~FolderMemoryCard() throw() {} @@ -341,6 +345,11 @@ public: // Close the memory card and flush changes to the file system. Set flush to false to not store changes. void Close( bool flush = true ); + // Closes and reopens card with given filter options if they differ from the current ones (returns true), + // or does nothing if they match already (returns false). + // Does nothing and returns false when called on a closed memory card. + bool ReIndex( bool enableFiltering, const wxString& filter ); + s32 IsPresent() const; void GetSizeInfo( PS2E_McdSizeInfo& outways ) const; bool IsPSX() const; @@ -562,5 +571,5 @@ public: s32 EraseBlock( uint slot, u32 adr ); u64 GetCRC( uint slot ); void NextFrame( uint slot ); - void ReIndex( uint slot, const bool enableFiltering, const wxString& filter ); + bool ReIndex( uint slot, const bool enableFiltering, const wxString& filter ); };