mirror of https://github.com/PCSX2/pcsx2.git
Merge pull request #980 from AdmiralCurtiss/ff12mcdfix
FolderMemoryCard: Fix issue #976: Corrupted FF12 saves when overwriting data.
This commit is contained in:
commit
d3ec74be2b
|
@ -109,8 +109,8 @@ void FolderMemoryCard::Close( bool flush ) {
|
|||
|
||||
m_cache.clear();
|
||||
m_oldDataCache.clear();
|
||||
m_fileMetadataQuickAccess.clear();
|
||||
m_lastAccessedFile.CloseAll();
|
||||
m_fileMetadataQuickAccess.clear();
|
||||
}
|
||||
|
||||
void FolderMemoryCard::LoadMemoryCardData( const u32 sizeInClusters, const bool enableFiltering, const wxString& filter ) {
|
||||
|
@ -142,6 +142,10 @@ void FolderMemoryCard::LoadMemoryCardData( const u32 sizeInClusters, const bool
|
|||
CreateRootDir();
|
||||
MemoryCardFileEntry* const rootDirEntry = &m_fileEntryDict[m_superBlock.data.rootdir_cluster].entries[0];
|
||||
AddFolder( rootDirEntry, m_folderName.GetPath(), nullptr, enableFiltering, filter );
|
||||
|
||||
#ifdef DEBUG_WRITE_FOLDER_CARD_IN_MEMORY_TO_FILE_ON_CHANGE
|
||||
WriteToFile( m_folderName.GetFullPath().RemoveLast() + L"-debug_" + wxDateTime::Now().Format( L"%Y-%m-%d-%H-%M-%S" ) + L"_load.ps2" );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -842,6 +846,10 @@ void FolderMemoryCard::NextFrame() {
|
|||
void FolderMemoryCard::Flush() {
|
||||
if ( m_cache.empty() ) { return; }
|
||||
|
||||
#ifdef DEBUG_WRITE_FOLDER_CARD_IN_MEMORY_TO_FILE_ON_CHANGE
|
||||
WriteToFile( m_folderName.GetFullPath().RemoveLast() + L"-debug_" + wxDateTime::Now().Format( L"%Y-%m-%d-%H-%M-%S" ) + L"_pre-flush.ps2" );
|
||||
#endif
|
||||
|
||||
Console.WriteLn( L"(FolderMcd) Writing data for slot %u to file system...", m_slot );
|
||||
const u64 timeFlushStart = wxGetLocalTimeMillis().GetValue();
|
||||
|
||||
|
@ -896,10 +904,15 @@ void FolderMemoryCard::Flush() {
|
|||
}
|
||||
|
||||
m_lastAccessedFile.FlushAll();
|
||||
m_lastAccessedFile.ClearMetadataWriteState();
|
||||
m_oldDataCache.clear();
|
||||
|
||||
const u64 timeFlushEnd = wxGetLocalTimeMillis().GetValue();
|
||||
Console.WriteLn( L"(FolderMcd) Done! Took %u ms.", timeFlushEnd - timeFlushStart );
|
||||
|
||||
#ifdef DEBUG_WRITE_FOLDER_CARD_IN_MEMORY_TO_FILE_ON_CHANGE
|
||||
WriteToFile( m_folderName.GetFullPath().RemoveLast() + L"-debug_" + wxDateTime::Now().Format( L"%Y-%m-%d-%H-%M-%S" ) + L"_post-flush.ps2" );
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FolderMemoryCard::FlushPage( const u32 page ) {
|
||||
|
@ -1344,6 +1357,20 @@ void FolderMemoryCard::CalculateECC( u8* ecc, const u8* data ) {
|
|||
return;
|
||||
}
|
||||
|
||||
void FolderMemoryCard::WriteToFile( const wxString& filename ) {
|
||||
wxFFile targetFile( filename, L"wb" );
|
||||
|
||||
u8 buffer[FolderMemoryCard::PageSizeRaw];
|
||||
u32 adr = 0;
|
||||
while ( adr < GetSizeInClusters() * FolderMemoryCard::ClusterSizeRaw ) {
|
||||
Read( buffer, adr, FolderMemoryCard::PageSizeRaw );
|
||||
targetFile.Write( buffer, FolderMemoryCard::PageSizeRaw );
|
||||
adr += FolderMemoryCard::PageSizeRaw;
|
||||
}
|
||||
|
||||
targetFile.Close();
|
||||
}
|
||||
|
||||
|
||||
FileAccessHelper::FileAccessHelper() {
|
||||
m_files.clear();
|
||||
|
@ -1370,7 +1397,13 @@ wxFFile* FileAccessHelper::Open( const wxFileName& folderName, MemoryCardFileMet
|
|||
|
||||
const MemoryCardFileEntry* const entry = fileRef->entry;
|
||||
wxFFile* file = new wxFFile( filename, L"r+b" );
|
||||
m_files.emplace( entry, file );
|
||||
|
||||
std::string internalPath;
|
||||
fileRef->GetInternalPath( &internalPath );
|
||||
MemoryCardFileHandleStructure handleStruct;
|
||||
handleStruct.fileHandle = file;
|
||||
handleStruct.fileRef = fileRef;
|
||||
m_files.emplace( internalPath, handleStruct );
|
||||
|
||||
if ( writeMetadata ) {
|
||||
fn.AppendDir( L"_pcsx2_meta" );
|
||||
|
@ -1418,7 +1451,9 @@ void FileAccessHelper::WriteMetadata( bool metadataIsNonstandard, wxFileName& me
|
|||
}
|
||||
|
||||
wxFFile* FileAccessHelper::ReOpen( const wxFileName& folderName, MemoryCardFileMetadataReference* fileRef, bool writeMetadata ) {
|
||||
auto it = m_files.find( fileRef->entry );
|
||||
std::string internalPath;
|
||||
fileRef->GetInternalPath( &internalPath );
|
||||
auto it = m_files.find( internalPath );
|
||||
if ( it != m_files.end() ) {
|
||||
// we already have a handle to this file
|
||||
|
||||
|
@ -1434,7 +1469,10 @@ wxFFile* FileAccessHelper::ReOpen( const wxFileName& folderName, MemoryCardFileM
|
|||
}
|
||||
}
|
||||
|
||||
return it->second;
|
||||
// update the fileRef in the map since it might have been modified or deleted
|
||||
it->second.fileRef = fileRef;
|
||||
|
||||
return it->second.fileHandle;
|
||||
} else {
|
||||
return this->Open( folderName, fileRef, writeMetadata );
|
||||
}
|
||||
|
@ -1458,9 +1496,9 @@ void FileAccessHelper::CloseMatching( const wxString& path ) {
|
|||
fn.Normalize();
|
||||
wxString pathNormalized = fn.GetFullPath();
|
||||
for ( auto it = m_files.begin(); it != m_files.end(); ) {
|
||||
wxString openPath = it->second->GetName();
|
||||
wxString openPath = it->second.fileHandle->GetName();
|
||||
if ( openPath.StartsWith( pathNormalized ) ) {
|
||||
CloseFileHandle( it->second, it->first );
|
||||
CloseFileHandle( it->second.fileHandle, it->second.fileRef->entry );
|
||||
it = m_files.erase( it );
|
||||
} else {
|
||||
++it;
|
||||
|
@ -1470,17 +1508,21 @@ void FileAccessHelper::CloseMatching( const wxString& path ) {
|
|||
|
||||
void FileAccessHelper::CloseAll() {
|
||||
for ( auto it = m_files.begin(); it != m_files.end(); ++it ) {
|
||||
CloseFileHandle( it->second, it->first );
|
||||
CloseFileHandle( it->second.fileHandle, it->second.fileRef->entry );
|
||||
}
|
||||
m_files.clear();
|
||||
}
|
||||
|
||||
void FileAccessHelper::FlushAll() {
|
||||
for ( auto it = m_files.begin(); it != m_files.end(); ++it ) {
|
||||
it->second->Flush();
|
||||
it->second.fileHandle->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
void FileAccessHelper::ClearMetadataWriteState() {
|
||||
m_lastWrittenFileRef = nullptr;
|
||||
}
|
||||
|
||||
bool FileAccessHelper::CleanMemcardFilename( char* name ) {
|
||||
// invalid characters for filenames in the PS2 file system: { '/', '?', '*' }
|
||||
// the following characters are valid in a PS2 memcard file system but invalid in Windows
|
||||
|
@ -1521,6 +1563,17 @@ bool MemoryCardFileMetadataReference::GetPath( wxFileName* fileName ) const {
|
|||
return parentCleaned || localCleaned;
|
||||
}
|
||||
|
||||
void MemoryCardFileMetadataReference::GetInternalPath( std::string* fileName ) const {
|
||||
if ( parent ) {
|
||||
parent->GetInternalPath( fileName );
|
||||
}
|
||||
|
||||
fileName->append( (const char*)entry->entry.data.name );
|
||||
|
||||
if ( entry->IsDir() ) {
|
||||
fileName->append( "/" );
|
||||
}
|
||||
}
|
||||
|
||||
FolderMemoryCardAggregator::FolderMemoryCardAggregator() {
|
||||
for ( uint i = 0; i < TotalCardSlots; ++i ) {
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include "PluginCallbacks.h"
|
||||
#include "AppConfig.h"
|
||||
|
||||
//#define DEBUG_WRITE_FOLDER_CARD_IN_MEMORY_TO_FILE_ON_CHANGE
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Superblock Header Struct
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -195,6 +197,14 @@ struct MemoryCardFileMetadataReference {
|
|||
|
||||
// returns true if filename was modified and metadata containing the actual filename should be written
|
||||
bool GetPath( wxFileName* fileName ) const;
|
||||
|
||||
// gives the internal memory card file system path, not to be used for writes to the host file system
|
||||
void GetInternalPath( std::string* fileName ) const;
|
||||
};
|
||||
|
||||
struct MemoryCardFileHandleStructure {
|
||||
MemoryCardFileMetadataReference* fileRef;
|
||||
wxFFile* fileHandle;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -203,7 +213,7 @@ struct MemoryCardFileMetadataReference {
|
|||
// Small helper class to keep memory card files opened between calls to Read()/Save()
|
||||
class FileAccessHelper {
|
||||
protected:
|
||||
std::map<const MemoryCardFileEntry* const, wxFFile*> m_files;
|
||||
std::map<std::string, MemoryCardFileHandleStructure> m_files;
|
||||
MemoryCardFileMetadataReference* m_lastWrittenFileRef; // we remember this to reduce redundant metadata checks/writes
|
||||
|
||||
public:
|
||||
|
@ -219,6 +229,9 @@ public:
|
|||
// Flush the written data of all open files to the file system
|
||||
void FlushAll();
|
||||
|
||||
// Force metadata to be written on next file access, not sure if this is necessary but it can't hurt.
|
||||
void ClearMetadataWriteState();
|
||||
|
||||
// removes characters from a PS2 file name that would be illegal in a Windows file system
|
||||
// returns true if any changes were made
|
||||
static bool CleanMemcardFilename( char* name );
|
||||
|
@ -348,6 +361,8 @@ public:
|
|||
|
||||
static void CalculateECC( u8* ecc, const u8* data );
|
||||
|
||||
void WriteToFile( const wxString& filename );
|
||||
|
||||
protected:
|
||||
// initializes memory card data, as if it was fresh from the factory
|
||||
void InitializeInternalData();
|
||||
|
|
Loading…
Reference in New Issue