MemoryCard: Add support for folder memcards in GUI and make both implementation function side-by-side.

This commit is contained in:
Admiral H. Curtiss 2015-05-09 03:22:17 +02:00
parent 1d46800888
commit f15c07653c
9 changed files with 281 additions and 61 deletions

View File

@ -431,10 +431,8 @@ static __fi void VSyncEnd(u32 sCycle)
psxVBlankEnd(); // psxCounters vBlank End psxVBlankEnd(); // psxCounters vBlank End
if (gates) rcntEndGate(true, sCycle); // Counters End Gate Code if (gates) rcntEndGate(true, sCycle); // Counters End Gate Code
#ifdef MEMORYCARD_USE_FOLDER
// FolderMemoryCard needs information on how much time has passed since the last write // FolderMemoryCard needs information on how much time has passed since the last write
sioNextFrame(); sioNextFrame();
#endif
frameLimit(); // limit FPS frameLimit(); // limit FPS

View File

@ -611,6 +611,10 @@ void AppConfig::LoadSaveMemcards( IniInterface& ini )
Mcd[slot].Enabled, Mcd[slot].Enabled ); Mcd[slot].Enabled, Mcd[slot].Enabled );
ini.Entry( pxsFmt( L"Slot%u_Filename", slot+1 ), ini.Entry( pxsFmt( L"Slot%u_Filename", slot+1 ),
Mcd[slot].Filename, Mcd[slot].Filename ); Mcd[slot].Filename, Mcd[slot].Filename );
int type = (int)Mcd[slot].Type;
ini.Entry( pxsFmt( L"Slot%u_Type", slot + 1 ),
type, (int)MemoryCardType::MemoryCard_File );
Mcd[slot].Type = (MemoryCardType)type;
} }
for( uint slot=2; slot<8; ++slot ) for( uint slot=2; slot<8; ++slot )
@ -622,6 +626,10 @@ void AppConfig::LoadSaveMemcards( IniInterface& ini )
Mcd[slot].Enabled, Mcd[slot].Enabled ); Mcd[slot].Enabled, Mcd[slot].Enabled );
ini.Entry( pxsFmt( L"Multitap%u_Slot%u_Filename", mtport, mtslot ), ini.Entry( pxsFmt( L"Multitap%u_Slot%u_Filename", mtport, mtslot ),
Mcd[slot].Filename, Mcd[slot].Filename ); Mcd[slot].Filename, Mcd[slot].Filename );
int type = (int)Mcd[slot].Type;
ini.Entry( pxsFmt( L"Multitap%u_Slot%u_Type", mtport, mtslot ),
type, (int)MemoryCardType::MemoryCard_File );
Mcd[slot].Type = (MemoryCardType)type;
} }
} }

View File

@ -98,6 +98,14 @@ enum AspectRatioType
AspectRatio_MaxCount AspectRatio_MaxCount
}; };
enum MemoryCardType
{
MemoryCard_None,
MemoryCard_File,
MemoryCard_Folder,
MemoryCard_MaxCount
};
// ===================================================================================================== // =====================================================================================================
// Pcsx2 Application Configuration. // Pcsx2 Application Configuration.
// ===================================================================================================== // =====================================================================================================
@ -182,6 +190,7 @@ public:
{ {
wxFileName Filename; // user-configured location of this memory card wxFileName Filename; // user-configured location of this memory card
bool Enabled; // memory card enabled (if false, memcard will not show up in-game) bool Enabled; // memory card enabled (if false, memcard will not show up in-game)
MemoryCardType Type; // the memory card implementation that should be used
}; };
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -153,17 +153,31 @@ void Dialogs::CreateMemoryCardDialog::OnOk_Click( wxCommandEvent& evt )
return; return;
} }
wxString fullPath=(m_mcdpath + composedName).GetFullPath(); wxString fullPath = ( m_mcdpath + composedName ).GetFullPath();
if( !CreateIt( if ( m_radio_CardSize && m_radio_CardSize->SelectedItem().SomeInt == 0 ) {
fullPath, // user selected to create a folder memory card
m_radio_CardSize ? m_radio_CardSize->SelectedItem().SomeInt : 8 if ( !wxFileName::Mkdir( fullPath ) ) {
) ) Msgbox::Alert(
{ _( "Error: The directory for the memory card could not be created." ),
Msgbox::Alert( _( "Create memory card" )
_("Error: The memory card could not be created."), );
_("Create memory card") } else {
); // also create an empty superblock so we can recognize memory card folders based on if they have a superblock
return; wxFFile superblock( wxFileName( fullPath, L"_pcsx2_superblock" ).GetFullPath(), L"wb" );
superblock.Close();
}
} else {
// otherwise create a file
if ( !CreateIt(
fullPath,
m_radio_CardSize ? m_radio_CardSize->SelectedItem().SomeInt : 8
) ) {
Msgbox::Alert(
_( "Error: The memory card could not be created." ),
_( "Create memory card" )
);
return;
}
} }
result_createdMcdFilename = composedName; result_createdMcdFilename = composedName;
@ -205,7 +219,11 @@ void Dialogs::CreateMemoryCardDialog::CreateControls()
RadioPanelItem(_("64 MB"), _("Low compatibility warning: Yes it's very big, but may not work with many games.")) RadioPanelItem(_("64 MB"), _("Low compatibility warning: Yes it's very big, but may not work with many games."))
. SetToolTip(_t("Use at your own risk. Erratic memory card behavior is possible (though unlikely).")) . SetToolTip(_t("Use at your own risk. Erratic memory card behavior is possible (though unlikely)."))
. SetInt(64) . SetInt(64),
RadioPanelItem(_("Folder [experimental]"), _("Store memory card contents in the host filesystem instead of a file."))
. SetToolTip(_t("Automatically manages memory card contents so that the console only sees files related to the currently running software. Allows you to drag-and-drop files in and out of the memory card with your standard file explorer. This is still experimental, so use at your own risk!"))
. SetInt(0)
}; };
m_radio_CardSize = new pxRadioPanel( this, tbl_CardSizes ); m_radio_CardSize = new pxRadioPanel( this, tbl_CardSizes );

View File

@ -75,6 +75,8 @@ public:
s32 EraseBlock ( uint slot, u32 adr ); s32 EraseBlock ( uint slot, u32 adr );
u64 GetCRC ( uint slot ); u64 GetCRC ( uint slot );
void NextFrame( uint slot );
protected: protected:
bool Seek( wxFFile& f, u32 adr ); bool Seek( wxFFile& f, u32 adr );
bool Create( const wxString& mcdFile, uint sizeInMB ); bool Create( const wxString& mcdFile, uint sizeInMB );
@ -171,7 +173,12 @@ void FileMemoryCard::Open()
cont = true; cont = true;
} }
Console.WriteLn( cont ? Color_Gray : Color_Green, L"McdSlot %u: " + str, slot ); if ( g_Conf->Mcd[slot].Type != MemoryCardType::MemoryCard_File ) {
str = L"[is not memcard file]";
cont = true;
}
Console.WriteLn( cont ? Color_Gray : Color_Green, L"McdSlot %u [File]: " + str, slot );
if( cont ) continue; if( cont ) continue;
const wxULongLong fsz = fname.GetSize(); const wxULongLong fsz = fname.GetSize();
@ -401,18 +408,20 @@ u64 FileMemoryCard::GetCRC( uint slot )
return retval; return retval;
} }
void FileMemoryCard::NextFrame( uint slot )
{
}
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// MemoryCard Component API Bindings // MemoryCard Component API Bindings
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
struct Component_FileMcd struct Component_FileMcd
{ {
PS2E_ComponentAPI_Mcd api; // callbacks the plugin provides back to the emulator PS2E_ComponentAPI_Mcd api; // callbacks the plugin provides back to the emulator
#ifdef MEMORYCARD_USE_FOLDER FileMemoryCard impl; // class-based implementations we refer to when API is invoked
FolderMemoryCardAggregator impl; FolderMemoryCardAggregator implFolder;
#else
FileMemoryCard impl; // class-based implementations we refer to when API is invoked
#endif
Component_FileMcd(); Component_FileMcd();
}; };
@ -427,52 +436,120 @@ uint FileMcd_ConvertToSlot( uint port, uint slot )
static void PS2E_CALLBACK FileMcd_EmuOpen( PS2E_THISPTR thisptr, const PS2E_SessionInfo *session ) static void PS2E_CALLBACK FileMcd_EmuOpen( PS2E_THISPTR thisptr, const PS2E_SessionInfo *session )
{ {
thisptr->impl.Open(); thisptr->impl.Open();
thisptr->implFolder.Open();
} }
static void PS2E_CALLBACK FileMcd_EmuClose( PS2E_THISPTR thisptr ) static void PS2E_CALLBACK FileMcd_EmuClose( PS2E_THISPTR thisptr )
{ {
thisptr->implFolder.Close();
thisptr->impl.Close(); thisptr->impl.Close();
} }
static s32 PS2E_CALLBACK FileMcd_IsPresent( PS2E_THISPTR thisptr, uint port, uint slot ) static s32 PS2E_CALLBACK FileMcd_IsPresent( PS2E_THISPTR thisptr, uint port, uint slot )
{ {
return thisptr->impl.IsPresent( FileMcd_ConvertToSlot( port, slot ) ); const uint combinedSlot = FileMcd_ConvertToSlot( port, slot );
switch ( g_Conf->Mcd[combinedSlot].Type ) {
case MemoryCardType::MemoryCard_File:
return thisptr->impl.IsPresent( combinedSlot );
case MemoryCardType::MemoryCard_Folder:
return thisptr->implFolder.IsPresent( combinedSlot );
default:
return false;
}
} }
static void PS2E_CALLBACK FileMcd_GetSizeInfo( PS2E_THISPTR thisptr, uint port, uint slot, PS2E_McdSizeInfo* outways ) static void PS2E_CALLBACK FileMcd_GetSizeInfo( PS2E_THISPTR thisptr, uint port, uint slot, PS2E_McdSizeInfo* outways )
{ {
thisptr->impl.GetSizeInfo( FileMcd_ConvertToSlot( port, slot ), *outways ); const uint combinedSlot = FileMcd_ConvertToSlot( port, slot );
switch ( g_Conf->Mcd[combinedSlot].Type ) {
case MemoryCardType::MemoryCard_File:
thisptr->impl.GetSizeInfo( combinedSlot, *outways );
break;
case MemoryCardType::MemoryCard_Folder:
thisptr->implFolder.GetSizeInfo( combinedSlot, *outways );
break;
default:
return;
}
} }
static bool PS2E_CALLBACK FileMcd_IsPSX( PS2E_THISPTR thisptr, uint port, uint slot ) static bool PS2E_CALLBACK FileMcd_IsPSX( PS2E_THISPTR thisptr, uint port, uint slot )
{ {
return thisptr->impl.IsPSX( FileMcd_ConvertToSlot( port, slot ) ); const uint combinedSlot = FileMcd_ConvertToSlot( port, slot );
switch ( g_Conf->Mcd[combinedSlot].Type ) {
case MemoryCardType::MemoryCard_File:
return thisptr->impl.IsPSX( combinedSlot );
case MemoryCardType::MemoryCard_Folder:
return thisptr->implFolder.IsPSX( combinedSlot );
default:
return false;
}
} }
static s32 PS2E_CALLBACK FileMcd_Read( PS2E_THISPTR thisptr, uint port, uint slot, u8 *dest, u32 adr, int size ) static s32 PS2E_CALLBACK FileMcd_Read( PS2E_THISPTR thisptr, uint port, uint slot, u8 *dest, u32 adr, int size )
{ {
return thisptr->impl.Read( FileMcd_ConvertToSlot( port, slot ), dest, adr, size ); const uint combinedSlot = FileMcd_ConvertToSlot( port, slot );
switch ( g_Conf->Mcd[combinedSlot].Type ) {
case MemoryCardType::MemoryCard_File:
return thisptr->impl.Read( combinedSlot, dest, adr, size );
case MemoryCardType::MemoryCard_Folder:
return thisptr->implFolder.Read( combinedSlot, dest, adr, size );
default:
return 0;
}
} }
static s32 PS2E_CALLBACK FileMcd_Save( PS2E_THISPTR thisptr, uint port, uint slot, const u8 *src, u32 adr, int size ) static s32 PS2E_CALLBACK FileMcd_Save( PS2E_THISPTR thisptr, uint port, uint slot, const u8 *src, u32 adr, int size )
{ {
return thisptr->impl.Save( FileMcd_ConvertToSlot( port, slot ), src, adr, size ); const uint combinedSlot = FileMcd_ConvertToSlot( port, slot );
switch ( g_Conf->Mcd[combinedSlot].Type ) {
case MemoryCardType::MemoryCard_File:
return thisptr->impl.Save( combinedSlot, src, adr, size );
case MemoryCardType::MemoryCard_Folder:
return thisptr->implFolder.Save( combinedSlot, src, adr, size );
default:
return 0;
}
} }
static s32 PS2E_CALLBACK FileMcd_EraseBlock( PS2E_THISPTR thisptr, uint port, uint slot, u32 adr ) static s32 PS2E_CALLBACK FileMcd_EraseBlock( PS2E_THISPTR thisptr, uint port, uint slot, u32 adr )
{ {
return thisptr->impl.EraseBlock( FileMcd_ConvertToSlot( port, slot ), adr ); const uint combinedSlot = FileMcd_ConvertToSlot( port, slot );
switch ( g_Conf->Mcd[combinedSlot].Type ) {
case MemoryCardType::MemoryCard_File:
return thisptr->impl.EraseBlock( combinedSlot, adr );
case MemoryCardType::MemoryCard_Folder:
return thisptr->implFolder.EraseBlock( combinedSlot, adr );
default:
return 0;
}
} }
static u64 PS2E_CALLBACK FileMcd_GetCRC( PS2E_THISPTR thisptr, uint port, uint slot ) static u64 PS2E_CALLBACK FileMcd_GetCRC( PS2E_THISPTR thisptr, uint port, uint slot )
{ {
return thisptr->impl.GetCRC( FileMcd_ConvertToSlot( port, slot ) ); const uint combinedSlot = FileMcd_ConvertToSlot( port, slot );
switch ( g_Conf->Mcd[combinedSlot].Type ) {
case MemoryCardType::MemoryCard_File:
return thisptr->impl.GetCRC( combinedSlot );
case MemoryCardType::MemoryCard_Folder:
return thisptr->implFolder.GetCRC( combinedSlot );
default:
return 0;
}
} }
static void PS2E_CALLBACK FileMcd_NextFrame( PS2E_THISPTR thisptr, uint port, uint slot ) { static void PS2E_CALLBACK FileMcd_NextFrame( PS2E_THISPTR thisptr, uint port, uint slot ) {
#ifdef MEMORYCARD_USE_FOLDER const uint combinedSlot = FileMcd_ConvertToSlot( port, slot );
thisptr->impl.NextFrame( FileMcd_ConvertToSlot( port, slot ) ); switch ( g_Conf->Mcd[combinedSlot].Type ) {
#endif case MemoryCardType::MemoryCard_File:
thisptr->impl.NextFrame( combinedSlot );
break;
case MemoryCardType::MemoryCard_Folder:
thisptr->implFolder.NextFrame( combinedSlot );
break;
default:
return;
}
} }
Component_FileMcd::Component_FileMcd() Component_FileMcd::Component_FileMcd()
@ -586,6 +663,11 @@ bool isValidNewFilename( wxString filenameStringToTest, wxDirName atBasePath, wx
out_errorMessage = _("File name already exists"); out_errorMessage = _("File name already exists");
return false; return false;
} }
if ( wxDirExists( (atBasePath + wxFileName(filenameStringToTest)).GetFullPath() ))
{
out_errorMessage = _( "File name already exists" );
return false;
}
wxFile fp; wxFile fp;
if( !fp.Create( (atBasePath + wxFileName(filenameStringToTest)).GetFullPath() )) if( !fp.Create( (atBasePath + wxFileName(filenameStringToTest)).GetFullPath() ))

View File

@ -15,9 +15,6 @@
#pragma once #pragma once
// define this to use the FolderMemoryCard implementation instead of the regular FileMemoryCard one
//#define MEMORYCARD_USE_FOLDER
// NOTICE! This file is intended as a temporary placebo only, until such time that the // NOTICE! This file is intended as a temporary placebo only, until such time that the
// memorycard system is properly extracted into a plugin system (which would make it a // memorycard system is properly extracted into a plugin system (which would make it a
// separate project file). // separate project file).

View File

@ -54,19 +54,47 @@ bool EnumerateMemoryCard( McdSlotItem& dest, const wxFileName& filename, const w
{ {
dest.IsFormatted = false; dest.IsFormatted = false;
dest.IsPresent = false; dest.IsPresent = false;
dest.Type = MemoryCardType::MemoryCard_None;
const wxString fullpath( filename.GetFullPath() ); const wxString fullpath( filename.GetFullPath() );
if( !filename.FileExists() ) return false;
//DevCon.WriteLn( fullpath ); //DevCon.WriteLn( fullpath );
wxFFile mcdFile( fullpath ); if ( filename.FileExists() ) {
if( !mcdFile.IsOpened() ) return false; // wx should log the error for us. // might be a memory card file
wxFFile mcdFile( fullpath );
if ( !mcdFile.IsOpened() ) { return false; } // wx should log the error for us.
wxFileOffset length = mcdFile.Length(); wxFileOffset length = mcdFile.Length();
if( length < (1024*528) && length != 0x20000 ) if( length < (1024*528) && length != 0x20000 )
{ {
Console.Warning( "... MemoryCard appears to be truncated. Ignoring." ); Console.Warning( "... MemoryCard appears to be truncated. Ignoring." );
return false;
}
dest.SizeInMB = (uint)( length / ( 1024 * 528 * 2 ) );
if ( length == 0x20000 ) {
dest.IsPSX = true; // PSX memcard;
dest.SizeInMB = 1; // MegaBIT
}
dest.Type = MemoryCardType::MemoryCard_File;
dest.IsFormatted = IsMcdFormatted( mcdFile );
filename.GetTimes( NULL, &dest.DateModified, &dest.DateCreated );
} else if ( filename.DirExists() ) {
// might be a memory card folder
wxFileName superBlockFileName( fullpath, L"_pcsx2_superblock" );
if ( !superBlockFileName.FileExists() ) { return false; }
wxFFile mcdFile( superBlockFileName.GetFullPath() );
if ( !mcdFile.IsOpened() ) { return false; }
dest.SizeInMB = 0;
dest.Type = MemoryCardType::MemoryCard_Folder;
dest.IsFormatted = IsMcdFormatted( mcdFile );
superBlockFileName.GetTimes( NULL, &dest.DateModified, &dest.DateCreated );
} else {
// is neither
return false; return false;
} }
@ -75,17 +103,6 @@ bool EnumerateMemoryCard( McdSlotItem& dest, const wxFileName& filename, const w
if( filename.GetFullPath() == (basePath+filename.GetFullName()).GetFullPath() ) if( filename.GetFullPath() == (basePath+filename.GetFullName()).GetFullPath() )
dest.Filename = filename.GetFullName(); dest.Filename = filename.GetFullName();
dest.SizeInMB = (uint)(length / (1024 * 528 * 2));
if(length == 0x20000)
{
dest.IsPSX = true; // PSX memcard;
dest.SizeInMB = 1; // MegaBIT
}
dest.IsFormatted = IsMcdFormatted( mcdFile );
filename.GetTimes( NULL, &dest.DateModified, &dest.DateCreated );
return true; return true;
} }
@ -595,6 +612,7 @@ void Panels::MemoryCardListPanel_Simple::Apply()
Console.WriteLn( L"Apply Memory cards:" ); Console.WriteLn( L"Apply Memory cards:" );
for( uint slot=0; slot<8; ++slot ) for( uint slot=0; slot<8; ++slot )
{ {
g_Conf->Mcd[slot].Type = m_Cards[slot].Type;
g_Conf->Mcd[slot].Enabled = m_Cards[slot].IsEnabled && m_Cards[slot].IsPresent; g_Conf->Mcd[slot].Enabled = m_Cards[slot].IsEnabled && m_Cards[slot].IsPresent;
if (m_Cards[slot].IsPresent) if (m_Cards[slot].IsPresent)
g_Conf->Mcd[slot].Filename = m_Cards[slot].Filename; g_Conf->Mcd[slot].Filename = m_Cards[slot].Filename;
@ -623,7 +641,7 @@ void Panels::MemoryCardListPanel_Simple::AppStatusEvent_OnSettingsApplied()
//automatically create the enabled but non-existing file such that it can be managed (else will get created anyway on boot) //automatically create the enabled but non-existing file such that it can be managed (else will get created anyway on boot)
wxString targetFile = (GetMcdPath() + m_Cards[slot].Filename.GetFullName()).GetFullPath(); wxString targetFile = (GetMcdPath() + m_Cards[slot].Filename.GetFullName()).GetFullPath();
if ( m_Cards[slot].IsEnabled && !wxFileExists( targetFile ) ) if ( m_Cards[slot].IsEnabled && !( wxFileExists( targetFile ) || wxDirExists( targetFile ) ) )
{ {
wxString errMsg; wxString errMsg;
if (isValidNewFilename(m_Cards[slot].Filename.GetFullName(), GetMcdPath(), errMsg, 5)) if (isValidNewFilename(m_Cards[slot].Filename.GetFullName(), GetMcdPath(), errMsg, 5))
@ -639,7 +657,7 @@ void Panels::MemoryCardListPanel_Simple::AppStatusEvent_OnSettingsApplied()
} }
} }
if ( !m_Cards[slot].IsEnabled || !wxFileExists( targetFile ) ) if ( !m_Cards[slot].IsEnabled || !( wxFileExists( targetFile ) || wxDirExists( targetFile ) ) )
{ {
m_Cards[slot].IsEnabled = false; m_Cards[slot].IsEnabled = false;
m_Cards[slot].IsPresent = false; m_Cards[slot].IsPresent = false;
@ -728,6 +746,72 @@ void Panels::MemoryCardListPanel_Simple::UiCreateNewCard( McdSlotItem& card )
closed_core.AllowResume(); closed_core.AllowResume();
} }
bool CopyDirectory( const wxString& from, const wxString& to ) {
wxDir src( from );
if ( !src.IsOpened() ) {
return false;
}
wxMkdir( to );
wxDir dst( to );
if ( !dst.IsOpened() ) {
return false;
}
wxString filename;
// copy directories
if ( src.GetFirst( &filename, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN ) ) {
do {
if ( !CopyDirectory( wxFileName( from, filename ).GetFullPath(), wxFileName( to, filename ).GetFullPath() ) ) {
return false;
}
} while ( src.GetNext( &filename ) );
}
// copy files
if ( src.GetFirst( &filename, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN ) ) {
do {
if ( !wxCopyFile( wxFileName( from, filename ).GetFullPath(), wxFileName( to, filename ).GetFullPath() ) ) {
return false;
}
} while ( src.GetNext( &filename ) );
}
return true;
}
bool RemoveDirectory( const wxString& dirname ) {
{
wxDir dir( dirname );
if ( !dir.IsOpened() ) {
return false;
}
wxString filename;
// delete subdirs recursively
if ( dir.GetFirst( &filename, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN ) ) {
do {
if ( !RemoveDirectory( wxFileName( dirname, filename ).GetFullPath() ) ) {
return false;
}
} while ( dir.GetNext( &filename ) );
}
// delete files
if ( dir.GetFirst( &filename, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN ) ) {
do {
if ( !wxRemoveFile( wxFileName( dirname, filename ).GetFullPath() ) ) {
return false;
}
} while ( dir.GetNext( &filename ) );
}
}
// oddly enough this has different results compared to the more sensible dirname.Rmdir(), don't change!
return wxFileName::Rmdir( dirname );
}
void Panels::MemoryCardListPanel_Simple::UiDeleteCard( McdSlotItem& card ) void Panels::MemoryCardListPanel_Simple::UiDeleteCard( McdSlotItem& card )
{ {
@ -757,7 +841,12 @@ void Panels::MemoryCardListPanel_Simple::UiDeleteCard( McdSlotItem& card )
card.IsEnabled=false; card.IsEnabled=false;
Apply(); Apply();
wxRemoveFile( fullpath.GetFullPath() );
if ( fullpath.FileExists() ) {
wxRemoveFile( fullpath.GetFullPath() );
} else {
RemoveDirectory( fullpath.GetFullPath() );
}
RefreshSelections(); RefreshSelections();
closed_core.AllowResume(); closed_core.AllowResume();
@ -817,7 +906,8 @@ bool Panels::MemoryCardListPanel_Simple::UiDuplicateCard(McdSlotItem& src, McdSl
ScopedBusyCursor doh( Cursor_ReallyBusy ); ScopedBusyCursor doh( Cursor_ReallyBusy );
ScopedCoreThreadClose closed_core; ScopedCoreThreadClose closed_core;
if( !wxCopyFile( srcfile.GetFullPath(), destfile.GetFullPath(), true ) ) if( !( ( srcfile.FileExists() && wxCopyFile( srcfile.GetFullPath(), destfile.GetFullPath(), true ) )
|| ( !srcfile.FileExists() && CopyDirectory( srcfile.GetFullPath(), destfile.GetFullPath() ) ) ) )
{ {
wxString heading; wxString heading;
heading.Printf( pxE( L"Failed: Destination memory card '%s' is in use." ), heading.Printf( pxE( L"Failed: Destination memory card '%s' is in use." ),
@ -1106,9 +1196,26 @@ void Panels::MemoryCardListPanel_Simple::ReadFilesAtMcdFolder(){
wxArrayString memcardList; wxArrayString memcardList;
wxDir::GetAllFiles(m_FolderPicker->GetPath().ToString(), &memcardList, L"*.ps2", wxDIR_FILES); wxString filename = m_FolderPicker->GetPath().ToString();
wxDir::GetAllFiles(m_FolderPicker->GetPath().ToString(), &memcardList, L"*.mcd", wxDIR_FILES); wxDir memcardDir( filename );
wxDir::GetAllFiles(m_FolderPicker->GetPath().ToString(), &memcardList, L"*.mcr", wxDIR_FILES); if ( memcardDir.IsOpened() ) {
// add memory card files
wxDir::GetAllFiles( filename, &memcardList, L"*.ps2", wxDIR_FILES );
wxDir::GetAllFiles( filename, &memcardList, L"*.mcd", wxDIR_FILES );
wxDir::GetAllFiles( filename, &memcardList, L"*.mcr", wxDIR_FILES );
// add memory card folders
wxString dirname;
if ( memcardDir.GetFirst( &dirname, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN ) ) {
do {
wxFileName superBlockFileName( wxFileName( filename, dirname ).GetFullPath(), L"_pcsx2_superblock" );
if ( superBlockFileName.FileExists() ) {
memcardList.Add( superBlockFileName.GetPath() );
}
} while ( memcardDir.GetNext( &dirname ) );
}
}
for(uint i = 0; i < memcardList.size(); i++) { for(uint i = 0; i < memcardList.size(); i++) {
McdSlotItem currentCardFile; McdSlotItem currentCardFile;

View File

@ -156,7 +156,7 @@ wxString MemoryCardListView_Simple::OnGetItemText(long item, long column) const
return prefix + res; return prefix + res;
} }
*/ */
case McdColS_Size: return prefix + ( !it.IsPresent ? L"" : (it.IsPSX? pxsFmt( L"%u MBit", it.SizeInMB ) : pxsFmt( L"%u MiB", it.SizeInMB )) ); case McdColS_Size: return prefix + ( !it.IsPresent ? L"" : (it.IsPSX? pxsFmt( L"%u MBit", it.SizeInMB ) : ( it.SizeInMB > 0 ? pxsFmt( L"%u MiB", it.SizeInMB ) : L"Auto" ) ) );
case McdColS_Formatted: return prefix + ( !it.IsPresent ? L"" : ( it.IsFormatted ? _("Yes") : _("No")) ); case McdColS_Formatted: return prefix + ( !it.IsPresent ? L"" : ( it.IsFormatted ? _("Yes") : _("No")) );
case McdColS_Type: return prefix + ( !it.IsPresent ? L"" : ( it.IsPSX? _("PSX") : _("PS2")) ); case McdColS_Type: return prefix + ( !it.IsPresent ? L"" : ( it.IsPSX? _("PSX") : _("PS2")) );
case McdColS_DateModified: return prefix + ( !it.IsPresent ? L"" : it.DateModified.FormatDate() ); case McdColS_DateModified: return prefix + ( !it.IsPresent ? L"" : it.DateModified.FormatDate() );

View File

@ -40,6 +40,7 @@ struct McdSlotItem
{ {
int Slot; //0-7: internal slot. -1: unrelated to an internal slot (the rest of the files at the folder). int Slot; //0-7: internal slot. -1: unrelated to an internal slot (the rest of the files at the folder).
bool IsPresent; //Whether or not a file is associated with this item (true/false when 0<=Slot<=7. Always true when Slot==-1) bool IsPresent; //Whether or not a file is associated with this item (true/false when 0<=Slot<=7. Always true when Slot==-1)
MemoryCardType Type; //The implementation used for this memory card
//Only meaningful when IsPresent==true (a file exists for this item): //Only meaningful when IsPresent==true (a file exists for this item):
wxFileName Filename; // full pathname wxFileName Filename; // full pathname