From 50ad3a8bf5a977f9f0b37df6f46454985849b684 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Thu, 11 Jun 2015 22:04:11 +0200 Subject: [PATCH] FolderMemoryCard: Clean PS2 filenames that would be illegal in Windows and write the actual names into the metadata files. This fixes issues with game such as Rayman Revolution, http://forums.pcsx2.net/Thread-New-feature-Needs-testing-Automatically-managed-Folder-Memory-Card-Public-Test?pid=463482#pid463482 --- pcsx2/gui/MemoryCardFolder.cpp | 67 +++++++++++++++++++++++++--------- pcsx2/gui/MemoryCardFolder.h | 7 +++- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/pcsx2/gui/MemoryCardFolder.cpp b/pcsx2/gui/MemoryCardFolder.cpp index 9f66bc91ab..1b90d8f13a 100644 --- a/pcsx2/gui/MemoryCardFolder.cpp +++ b/pcsx2/gui/MemoryCardFolder.cpp @@ -409,24 +409,27 @@ bool FolderMemoryCard::AddFile( MemoryCardFileEntry* const dirEntry, const wxStr fileInfo.GetTimes( NULL, &modificationTime, &creationTime ); // set file entry metadata - memset( &newFileEntry->entry.raw[0], 0x00, 0x200 ); + memset( &newFileEntry->entry.raw[0], 0x00, sizeof( newFileEntry->entry.raw ) ); wxFileName metaFileName( dirPath, fileName ); metaFileName.AppendDir( L"_pcsx2_meta" ); wxFFile metaFile; if ( metaFileName.FileExists() && metaFile.Open( metaFileName.GetFullPath(), L"rb" ) ) { - metaFile.Read( &newFileEntry->entry.raw, 0x40 ); + size_t bytesRead = metaFile.Read( &newFileEntry->entry.raw, sizeof( newFileEntry->entry.raw ) ); metaFile.Close(); + if ( bytesRead < 0x60 ) { + strcpy( (char*)&newFileEntry->entry.data.name[0], fileName.mbc_str() ); + } } else { newFileEntry->entry.data.mode = MemoryCardFileEntry::DefaultFileMode; newFileEntry->entry.data.timeCreated = MemoryCardFileEntryDateTime::FromWxDateTime( creationTime ); newFileEntry->entry.data.timeModified = MemoryCardFileEntryDateTime::FromWxDateTime( modificationTime ); + strcpy( (char*)&newFileEntry->entry.data.name[0], fileName.mbc_str() ); } newFileEntry->entry.data.length = filesize; u32 fileDataStartingCluster = GetFreeDataCluster(); newFileEntry->entry.data.cluster = fileDataStartingCluster; - strcpy( (char*)&newFileEntry->entry.data.name[0], fileName.mbc_str() ); // mark the appropriate amount of clusters as used u32 dataCluster = fileDataStartingCluster; @@ -478,18 +481,6 @@ void FolderMemoryCard::AddFileEntryToMetadataQuickAccess( MemoryCardFileEntry* c } while ( ( fileCluster = m_fat.data[0][0][fileCluster] ) != 0xFFFFFFFFu ); } -void MemoryCardFileMetadataReference::GetPath( wxFileName* fileName ) { - if ( parent ) { - parent->GetPath( fileName ); - } - - if ( entry->IsDir() ) { - fileName->AppendDir( wxString::FromAscii( (const char*)entry->entry.data.name ) ); - } else if ( entry->IsFile() ) { - fileName->SetName( wxString::FromAscii( (const char*)entry->entry.data.name ) ); - } -} - s32 FolderMemoryCard::IsPresent() { return m_isEnabled; } @@ -1116,7 +1107,7 @@ wxFFile* FileAccessHelper::Open( const wxFileName& folderName, MemoryCardFileMet this->Close(); wxFileName fn( folderName ); - fileRef->GetPath( &fn ); + bool cleanedFilename = fileRef->GetPath( &fn ); wxString filename( fn.GetFullPath() ); if ( !fn.FileExists() ) { @@ -1136,13 +1127,13 @@ wxFFile* FileAccessHelper::Open( const wxFileName& folderName, MemoryCardFileMet // write metadata of file if it's nonstandard fn.AppendDir( L"_pcsx2_meta" ); - if ( entry->entry.data.mode != MemoryCardFileEntry::DefaultFileMode || entry->entry.data.attr != 0 ) { + if ( cleanedFilename || entry->entry.data.mode != MemoryCardFileEntry::DefaultFileMode || entry->entry.data.attr != 0 ) { if ( !fn.DirExists() ) { fn.Mkdir(); } wxFFile metaFile( fn.GetFullPath(), L"wb" ); if ( metaFile.IsOpened() ) { - metaFile.Write( entry->entry.raw, 0x40 ); + metaFile.Write( entry->entry.raw, sizeof( entry->entry.raw ) ); metaFile.Close(); } } else { @@ -1178,6 +1169,46 @@ void FileAccessHelper::Close() { } } +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 + // there's less restrictions on Linux but by cleaning them always we keep the folders cross-compatible + const char illegalChars[] = { '\\', '%', ':', '|', '"', '<', '>' }; + bool cleaned = false; + + for ( int i = 0; i < sizeof( illegalChars ); ++i ) { + // this sizeof looks really odd but I couldn't get MemoryCardFileEntry::entry.data.name (or variants) working, feel free to replace with something equivalent but nicer looking + for ( int j = 0; j < sizeof( ( (MemoryCardFileEntry*)0 )->entry.data.name ); ++j ) { + if ( name[j] == illegalChars[i] ) { + name[j] = '_'; + cleaned = true; + } + } + } + + return cleaned; +} + + +bool MemoryCardFileMetadataReference::GetPath( wxFileName* fileName ) { + bool parentCleaned = false; + if ( parent ) { + parentCleaned = parent->GetPath( fileName ); + } + + char cleanName[sizeof( entry->entry.data.name )]; + memcpy( cleanName, (const char*)entry->entry.data.name, sizeof( cleanName ) ); + bool localCleaned = FileAccessHelper::CleanMemcardFilename( cleanName ); + + if ( entry->IsDir() ) { + fileName->AppendDir( wxString::FromAscii( cleanName ) ); + } else if ( entry->IsFile() ) { + fileName->SetName( wxString::FromAscii( cleanName ) ); + } + + return parentCleaned || localCleaned; +} + FolderMemoryCardAggregator::FolderMemoryCardAggregator() { for ( uint i = 0; i < TotalCardSlots; ++i ) { diff --git a/pcsx2/gui/MemoryCardFolder.h b/pcsx2/gui/MemoryCardFolder.h index 53a6aaaeff..ba80018cc1 100644 --- a/pcsx2/gui/MemoryCardFolder.h +++ b/pcsx2/gui/MemoryCardFolder.h @@ -140,7 +140,8 @@ struct MemoryCardFileMetadataReference { MemoryCardFileEntry* entry; u32 consecutiveCluster; - void GetPath( wxFileName* fileName ); + // returns true if filename was modified and metadata containing the actual filename should be written + bool GetPath( wxFileName* fileName ); }; // -------------------------------------------------------------------------------------- @@ -162,6 +163,10 @@ public: // Close an open file, if any void Close(); + // 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 ); + protected: // Open a new file and remember it for later wxFFile* Open( const wxFileName& folderName, MemoryCardFileMetadataReference* fileRef, const wxString& mode, bool writeMetadata = false );