mirror of https://github.com/PCSX2/pcsx2.git
FolderMemoryCard: Only load data relevant to game. Please read commit description!
Essentially, I'm telling the memory card to re-index itself with a filter based on the game's disc serial every time a new executable boots in the emulator. This currently works for a lot of games, but fails in edge cases where the game disc's serial does not match the game serial that is written to the memory card as part of the save file's directory name. This affects mostly (only?) games that have multiple discs. We could circumvent this by adding a "save game serial" or something into the GameDatabase which tells us what we should filter by for those cases. Apart from this edge case, this appears to work surprisingly well. Try it and see if you can find other issues!
This commit is contained in:
parent
139e28988d
commit
880be6f602
|
@ -1109,7 +1109,9 @@ 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* reserved[7];
|
||||
void (PS2E_CALLBACK* McdReIndex)( PS2E_THISPTR thisptr, uint port, uint slot, const wxString& filter );
|
||||
|
||||
void* reserved[6];
|
||||
|
||||
} PS2E_ComponentAPI_Mcd;
|
||||
|
||||
|
|
|
@ -70,6 +70,10 @@ 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 );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Yay, order of this array shouldn't be important. :)
|
||||
//
|
||||
|
|
|
@ -242,6 +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 );
|
||||
|
||||
friend class SysCorePlugins;
|
||||
};
|
||||
|
|
|
@ -879,6 +879,20 @@ 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 );
|
||||
}
|
||||
}
|
||||
SetForceMcdEjectTimeoutNow();
|
||||
}
|
||||
|
||||
void SaveStateBase::sioFreeze()
|
||||
{
|
||||
// CRCs for memory cards.
|
||||
|
|
|
@ -86,6 +86,10 @@ struct _mcd
|
|||
void NextFrame() {
|
||||
SysPlugins.McdNextFrame( port, slot );
|
||||
}
|
||||
|
||||
void ReIndex(const wxString& filter = L"") {
|
||||
SysPlugins.McdReIndex( port, slot, filter );
|
||||
}
|
||||
};
|
||||
|
||||
struct _sio
|
||||
|
@ -124,3 +128,4 @@ extern void sioInterrupt();
|
|||
extern void InitializeSIO(u8 value);
|
||||
extern void SetForceMcdEjectTimeoutNow();
|
||||
extern void sioNextFrame();
|
||||
extern void sioSetGameSerial(const wxString& serial);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "Elfheader.h"
|
||||
#include "Patch.h"
|
||||
#include "R5900Exceptions.h"
|
||||
#include "Sio.h"
|
||||
|
||||
__aligned16 SysMtgsThread mtgsThread;
|
||||
__aligned16 AppCoreThread CoreThread;
|
||||
|
@ -382,6 +383,8 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src )
|
|||
}
|
||||
}
|
||||
|
||||
sioSetGameSerial( curGameKey );
|
||||
|
||||
if (gameName.IsEmpty() && gameSerial.IsEmpty() && gameCRC.IsEmpty())
|
||||
{
|
||||
// if all these conditions are met, it should mean that we're currently running BIOS code.
|
||||
|
|
|
@ -552,6 +552,20 @@ 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 ) {
|
||||
const uint combinedSlot = FileMcd_ConvertToSlot( port, slot );
|
||||
switch ( g_Conf->Mcd[combinedSlot].Type ) {
|
||||
//case MemoryCardType::MemoryCard_File:
|
||||
// thisptr->impl.ReIndex( combinedSlot, filter );
|
||||
// break;
|
||||
case MemoryCardType::MemoryCard_Folder:
|
||||
thisptr->implFolder.ReIndex( combinedSlot, filter );
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Component_FileMcd::Component_FileMcd()
|
||||
{
|
||||
memzero( api );
|
||||
|
@ -567,6 +581,7 @@ Component_FileMcd::Component_FileMcd()
|
|||
api.McdEraseBlock = FileMcd_EraseBlock;
|
||||
api.McdGetCRC = FileMcd_GetCRC;
|
||||
api.McdNextFrame = FileMcd_NextFrame;
|
||||
api.McdReIndex = FileMcd_ReIndex;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -47,6 +47,10 @@ bool FolderMemoryCard::IsFormatted() {
|
|||
}
|
||||
|
||||
void FolderMemoryCard::Open() {
|
||||
Open( L"" );
|
||||
}
|
||||
|
||||
void FolderMemoryCard::Open( const wxString& filter ) {
|
||||
InitializeInternalData();
|
||||
|
||||
wxFileName configuredFileName( g_Conf->FullpathToMcd( m_slot ) );
|
||||
|
@ -80,7 +84,7 @@ void FolderMemoryCard::Open() {
|
|||
if ( disabled ) return;
|
||||
|
||||
m_isEnabled = true;
|
||||
LoadMemoryCardData();
|
||||
LoadMemoryCardData( filter );
|
||||
|
||||
SetTimeLastWrittenToNow();
|
||||
m_framesUntilFlush = 0;
|
||||
|
@ -98,7 +102,7 @@ void FolderMemoryCard::Close() {
|
|||
}
|
||||
}
|
||||
|
||||
void FolderMemoryCard::LoadMemoryCardData() {
|
||||
void FolderMemoryCard::LoadMemoryCardData( const wxString& filter ) {
|
||||
bool formatted = false;
|
||||
|
||||
// read superblock if it exists
|
||||
|
@ -115,7 +119,7 @@ void FolderMemoryCard::LoadMemoryCardData() {
|
|||
CreateFat();
|
||||
CreateRootDir();
|
||||
MemoryCardFileEntry* const rootDirEntry = &m_fileEntryDict[m_superBlock.data.rootdir_cluster].entries[0];
|
||||
AddFolder( rootDirEntry, folderName.GetPath() );
|
||||
AddFolder( rootDirEntry, folderName.GetPath(), filter );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,7 +264,7 @@ MemoryCardFileEntry* FolderMemoryCard::AppendFileEntryToDir( MemoryCardFileEntry
|
|||
return newFileEntry;
|
||||
}
|
||||
|
||||
bool FolderMemoryCard::AddFolder( MemoryCardFileEntry* const dirEntry, const wxString& dirPath ) {
|
||||
bool FolderMemoryCard::AddFolder( MemoryCardFileEntry* const dirEntry, const wxString& dirPath, const wxString& filter ) {
|
||||
wxDir dir( dirPath );
|
||||
if ( dir.IsOpened() ) {
|
||||
Console.WriteLn( L"(FolderMcd) Adding folder: %s", WX_STR( dirPath ) );
|
||||
|
@ -286,6 +290,14 @@ bool FolderMemoryCard::AddFolder( MemoryCardFileEntry* const dirEntry, const wxS
|
|||
++entryNumber;
|
||||
}
|
||||
} else {
|
||||
// if possible filter added directories by game serial
|
||||
// this has the effective result of only files relevant to the current game being loaded into the memory card
|
||||
// which means every game essentially sees the memory card as if no other files exist
|
||||
if ( !filter.IsEmpty() && !fileName.Contains( filter ) ) {
|
||||
hasNext = dir.GetNext( &fileName );
|
||||
continue;
|
||||
}
|
||||
|
||||
// make sure we have enough space on the memcard for the directory
|
||||
const u32 newNeededClusters = ( dirEntry->entry.data.length % 2 ) == 0 ? 2 : 1;
|
||||
if ( newNeededClusters > GetAmountFreeDataClusters() ) {
|
||||
|
@ -1029,4 +1041,8 @@ void FolderMemoryCardAggregator::NextFrame( uint slot ) {
|
|||
m_cards[slot].NextFrame();
|
||||
}
|
||||
|
||||
void FolderMemoryCardAggregator::ReIndex( uint slot, const wxString& filter ) {
|
||||
m_cards[slot].Close();
|
||||
m_cards[slot].Open( filter );
|
||||
}
|
||||
|
||||
|
|
|
@ -169,6 +169,7 @@ public:
|
|||
void Unlock();
|
||||
|
||||
void Open();
|
||||
void Open( const wxString& filter );
|
||||
void Close();
|
||||
|
||||
s32 IsPresent();
|
||||
|
@ -219,7 +220,7 @@ protected:
|
|||
|
||||
|
||||
// loads files and folders from the host file system if a superblock exists in the root directory
|
||||
void LoadMemoryCardData();
|
||||
void LoadMemoryCardData( const wxString& filter );
|
||||
|
||||
// creates the FAT and indirect FAT
|
||||
void CreateFat();
|
||||
|
@ -252,7 +253,7 @@ protected:
|
|||
// adds a folder in the host file system to the memory card, including all files and subdirectories
|
||||
// - dirEntry: the entry of the directory in the parent directory, or the root "." entry
|
||||
// - dirPath: the full path to the directory in the host file system
|
||||
bool AddFolder( MemoryCardFileEntry* const dirEntry, const wxString& dirPath );
|
||||
bool AddFolder( MemoryCardFileEntry* const dirEntry, const wxString& dirPath, const wxString& filter = L"" );
|
||||
|
||||
// adds a file in the host file sytem to the memory card
|
||||
// - dirEntry: the entry of the directory in the parent directory, or the root "." entry
|
||||
|
@ -313,4 +314,5 @@ public:
|
|||
s32 EraseBlock( uint slot, u32 adr );
|
||||
u64 GetCRC( uint slot );
|
||||
void NextFrame( uint slot );
|
||||
void ReIndex( uint slot, const wxString& filter );
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue