MemoryCard: Add options to convert FolderMemoryCards to 16MB, 32MB, and 64MB FileMemoryCards.

This commit is contained in:
Admiral H. Curtiss 2015-07-14 17:40:22 +02:00
parent 6bd578ccbe
commit 39e1de4d13
4 changed files with 61 additions and 26 deletions

View File

@ -256,7 +256,7 @@ namespace Dialogs
protected: protected:
void CreateControls( const MemoryCardType sourceType ); void CreateControls( const MemoryCardType sourceType );
void OnOk_Click( wxCommandEvent& evt ); void OnOk_Click( wxCommandEvent& evt );
bool ConvertToFile( const wxFileName& sourcePath, const wxFileName& targetPath ); bool ConvertToFile( const wxFileName& sourcePath, const wxFileName& targetPath, const u32 sizeInMB );
bool ConvertToFolder( const wxFileName& sourcePath, const wxFileName& targetPath ); bool ConvertToFolder( const wxFileName& sourcePath, const wxFileName& targetPath );
}; };
} }

View File

@ -21,6 +21,15 @@
#include "MemoryCardFolder.h" #include "MemoryCardFolder.h"
#include <wx/ffile.h> #include <wx/ffile.h>
enum MemoryCardConversionType {
MemoryCardConversion_File_8MB,
MemoryCardConversion_File_16MB,
MemoryCardConversion_File_32MB,
MemoryCardConversion_File_64MB,
MemoryCardConversion_Folder,
MemoryCardConversion_MaxCount
};
Dialogs::ConvertMemoryCardDialog::ConvertMemoryCardDialog( wxWindow* parent, const wxDirName& mcdPath, const AppConfig::McdOptions& mcdSourceConfig ) Dialogs::ConvertMemoryCardDialog::ConvertMemoryCardDialog( wxWindow* parent, const wxDirName& mcdPath, const AppConfig::McdOptions& mcdSourceConfig )
: wxDialogWithHelpers( parent, _( "Convert a memory card to a different format" ) ) : wxDialogWithHelpers( parent, _( "Convert a memory card to a different format" ) )
, m_mcdPath( mcdPath ) , m_mcdPath( mcdPath )
@ -52,7 +61,10 @@ Dialogs::ConvertMemoryCardDialog::ConvertMemoryCardDialog( wxWindow* parent, con
s_padding += m_radio_CardType | pxSizerFlags::StdExpand(); s_padding += m_radio_CardType | pxSizerFlags::StdExpand();
s_padding += Heading( pxE( L"WARNING: Converting a memory card may take several minutes! Please do not close the emulator during the conversion process, even if the emulator is no longer responding to input." ) ); if ( mcdSourceConfig.Type != MemoryCardType::MemoryCard_File ) {
s_padding += Heading( pxE( L"Please note that the resulting file may not actually contain all saves, depending on how many are in the source memory card." ) );
}
s_padding += Heading( pxE( L"WARNING: Converting a memory card may take a while! Please do not close the emulator during the conversion process, even if the emulator is no longer responding to input." ) );
s_padding += 12; s_padding += 12;
s_padding += s_buttons | pxSizerFlags::StdCenter(); s_padding += s_buttons | pxSizerFlags::StdCenter();
@ -69,13 +81,19 @@ Dialogs::ConvertMemoryCardDialog::ConvertMemoryCardDialog( wxWindow* parent, con
void Dialogs::ConvertMemoryCardDialog::CreateControls( const MemoryCardType sourceType ) { void Dialogs::ConvertMemoryCardDialog::CreateControls( const MemoryCardType sourceType ) {
m_text_filenameInput = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); m_text_filenameInput = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
RadioPanelItem toFile = RadioPanelItem( _( "File" ), pxE( L"Convert this memory card to a regular 8 MB .ps2 file. Please note that the resulting file may not actually contain all saves, depending on how many are in the source memory card." ) ) RadioPanelItem toFile8MB = RadioPanelItem( _( "8MB File" ), pxE( L"Convert this memory card to a standard 8 MB Memory Card .ps2 file." ) )
.SetInt( MemoryCardType::MemoryCard_File ); .SetInt( MemoryCardConversionType::MemoryCardConversion_File_8MB );
RadioPanelItem toFile16MB = RadioPanelItem( _( "16MB File" ), pxE( L"Convert this memory card to a 16 MB Memory Card .ps2 file." ) )
.SetInt( MemoryCardConversionType::MemoryCardConversion_File_16MB );
RadioPanelItem toFile32MB = RadioPanelItem( _( "32MB File" ), pxE( L"Convert this memory card to a 32 MB Memory Card .ps2 file." ) )
.SetInt( MemoryCardConversionType::MemoryCardConversion_File_32MB );
RadioPanelItem toFile64MB = RadioPanelItem( _( "64MB File" ), pxE( L"Convert this memory card to a 64 MB Memory Card .ps2 file." ) )
.SetInt( MemoryCardConversionType::MemoryCardConversion_File_64MB );
RadioPanelItem toFolder = RadioPanelItem( _( "Folder" ), _( "Convert this memory card to a folder of individual saves." ) ) RadioPanelItem toFolder = RadioPanelItem( _( "Folder" ), _( "Convert this memory card to a folder of individual saves." ) )
.SetInt( MemoryCardType::MemoryCard_Folder ); .SetInt( MemoryCardConversionType::MemoryCardConversion_Folder );
const RadioPanelItem tblForFile[] = { toFolder }; const RadioPanelItem tblForFile[] = { toFolder };
const RadioPanelItem tblForFolder[] = { toFile }; const RadioPanelItem tblForFolder[] = { toFile8MB, toFile16MB, toFile32MB, toFile64MB };
switch ( sourceType ) { switch ( sourceType ) {
case MemoryCardType::MemoryCard_File: case MemoryCardType::MemoryCard_File:
@ -110,13 +128,22 @@ void Dialogs::ConvertMemoryCardDialog::OnOk_Click( wxCommandEvent& evt ) {
wxFileName sourcePath = ( m_mcdPath + m_mcdSourceFilename ); wxFileName sourcePath = ( m_mcdPath + m_mcdSourceFilename );
wxFileName targetPath = ( m_mcdPath + composedName ); wxFileName targetPath = ( m_mcdPath + composedName );
if ( m_radio_CardType ) { if ( m_radio_CardType ) {
MemoryCardType targetType = (MemoryCardType)m_radio_CardType->SelectedItem().SomeInt; MemoryCardConversionType targetType = (MemoryCardConversionType)m_radio_CardType->SelectedItem().SomeInt;
switch ( targetType ) { switch ( targetType ) {
case MemoryCardType::MemoryCard_File: case MemoryCardConversionType::MemoryCardConversion_File_8MB:
success = ConvertToFile( sourcePath, targetPath ); success = ConvertToFile( sourcePath, targetPath, 8 );
break; break;
case MemoryCardType::MemoryCard_Folder: case MemoryCardConversionType::MemoryCardConversion_File_16MB:
success = ConvertToFile( sourcePath, targetPath, 16 );
break;
case MemoryCardConversionType::MemoryCardConversion_File_32MB:
success = ConvertToFile( sourcePath, targetPath, 32 );
break;
case MemoryCardConversionType::MemoryCardConversion_File_64MB:
success = ConvertToFile( sourcePath, targetPath, 64 );
break;
case MemoryCardConversionType::MemoryCardConversion_Folder:
success = ConvertToFolder( sourcePath, targetPath ); success = ConvertToFolder( sourcePath, targetPath );
break; break;
default: default:
@ -133,7 +160,7 @@ void Dialogs::ConvertMemoryCardDialog::OnOk_Click( wxCommandEvent& evt ) {
EndModal( wxID_OK ); EndModal( wxID_OK );
} }
bool Dialogs::ConvertMemoryCardDialog::ConvertToFile( const wxFileName& sourcePath, const wxFileName& targetPath ) { bool Dialogs::ConvertMemoryCardDialog::ConvertToFile( const wxFileName& sourcePath, const wxFileName& targetPath, const u32 sizeInMB ) {
// Conversion method: Open FolderMcd as usual, then read the raw data from it and write it to a file stream // Conversion method: Open FolderMcd as usual, then read the raw data from it and write it to a file stream
wxFFile targetFile( targetPath.GetFullPath(), L"wb" ); wxFFile targetFile( targetPath.GetFullPath(), L"wb" );
@ -145,25 +172,24 @@ bool Dialogs::ConvertMemoryCardDialog::ConvertToFile( const wxFileName& sourcePa
AppConfig::McdOptions config; AppConfig::McdOptions config;
config.Enabled = true; config.Enabled = true;
config.Type = MemoryCardType::MemoryCard_Folder; config.Type = MemoryCardType::MemoryCard_Folder;
sourceFolderMemoryCard.Open( sourcePath.GetFullPath(), config, false, L"" ); sourceFolderMemoryCard.Open( sourcePath.GetFullPath(), config, ( sizeInMB * 1024 * 1024 ) / FolderMemoryCard::ClusterSize, false, L"" );
u8 buffer[FolderMemoryCard::PageSizeRaw]; u8 buffer[FolderMemoryCard::PageSizeRaw];
u32 adr = 0; u32 adr = 0;
while ( adr < FolderMemoryCard::TotalSizeRaw ) { while ( adr < sourceFolderMemoryCard.GetSizeInClusters() * FolderMemoryCard::ClusterSizeRaw ) {
sourceFolderMemoryCard.Read( buffer, adr, FolderMemoryCard::PageSizeRaw ); sourceFolderMemoryCard.Read( buffer, adr, FolderMemoryCard::PageSizeRaw );
targetFile.Write( buffer, FolderMemoryCard::PageSizeRaw ); targetFile.Write( buffer, FolderMemoryCard::PageSizeRaw );
adr += FolderMemoryCard::PageSizeRaw; adr += FolderMemoryCard::PageSizeRaw;
} }
targetFile.Close(); targetFile.Close();
sourceFolderMemoryCard.Close(); sourceFolderMemoryCard.Close( false );
return true; return true;
} }
bool Dialogs::ConvertMemoryCardDialog::ConvertToFolder( const wxFileName& sourcePath, const wxFileName& targetPath ) { bool Dialogs::ConvertMemoryCardDialog::ConvertToFolder( const wxFileName& sourcePath, const wxFileName& targetPath ) {
// Conversion method: Read all pages of the FileMcd into a FolderMcd, then just write that out with the regular methods // Conversion method: Read all pages of the FileMcd into a FolderMcd, then just write that out with the regular methods
// TODO: Test if >8MB files don't super fuck up something
wxFFile sourceFile( sourcePath.GetFullPath(), L"rb" ); wxFFile sourceFile( sourcePath.GetFullPath(), L"rb" );
if ( !sourceFile.IsOpened() ) { if ( !sourceFile.IsOpened() ) {
@ -175,7 +201,7 @@ bool Dialogs::ConvertMemoryCardDialog::ConvertToFolder( const wxFileName& source
AppConfig::McdOptions config; AppConfig::McdOptions config;
config.Enabled = true; config.Enabled = true;
config.Type = MemoryCardType::MemoryCard_Folder; config.Type = MemoryCardType::MemoryCard_Folder;
targetFolderMemoryCard.Open( targetPath.GetFullPath(), config, false, L"" ); targetFolderMemoryCard.Open( targetPath.GetFullPath(), config, 0, false, L"" );
u32 adr = 0; u32 adr = 0;
while ( !sourceFile.Eof() ) { while ( !sourceFile.Eof() ) {
@ -191,7 +217,7 @@ bool Dialogs::ConvertMemoryCardDialog::ConvertToFolder( const wxFileName& source
if ( adr != FolderMemoryCard::TotalSizeRaw ) { if ( adr != FolderMemoryCard::TotalSizeRaw ) {
// reset memory card metrics in superblock to the default 8MB, since the converted card was different // reset memory card metrics in superblock to the default 8MB, since the converted card was different
targetFolderMemoryCard.Open( targetPath.GetFullPath(), config, true, L"" ); targetFolderMemoryCard.Open( targetPath.GetFullPath(), config, 0, true, L"" );
targetFolderMemoryCard.SetSizeInMB( 8 ); targetFolderMemoryCard.SetSizeInMB( 8 );
targetFolderMemoryCard.Close(); targetFolderMemoryCard.Close();
} }

View File

@ -52,10 +52,10 @@ bool FolderMemoryCard::IsFormatted() const {
} }
void FolderMemoryCard::Open( const bool enableFiltering, const wxString& filter ) { void FolderMemoryCard::Open( const bool enableFiltering, const wxString& filter ) {
Open( g_Conf->FullpathToMcd( m_slot ), g_Conf->Mcd[m_slot], enableFiltering, filter ); Open( g_Conf->FullpathToMcd( m_slot ), g_Conf->Mcd[m_slot], 0, enableFiltering, filter );
} }
void FolderMemoryCard::Open( const wxString& fullPath, const AppConfig::McdOptions& mcdOptions, const bool enableFiltering, const wxString& filter ) { void FolderMemoryCard::Open( const wxString& fullPath, const AppConfig::McdOptions& mcdOptions, const u32 sizeInClusters, const bool enableFiltering, const wxString& filter ) {
InitializeInternalData(); InitializeInternalData();
wxFileName configuredFileName( fullPath ); wxFileName configuredFileName( fullPath );
@ -89,16 +89,18 @@ void FolderMemoryCard::Open( const wxString& fullPath, const AppConfig::McdOptio
if ( disabled ) return; if ( disabled ) return;
m_isEnabled = true; m_isEnabled = true;
LoadMemoryCardData( enableFiltering, filter ); LoadMemoryCardData( sizeInClusters, enableFiltering, filter );
SetTimeLastWrittenToNow(); SetTimeLastWrittenToNow();
m_framesUntilFlush = 0; m_framesUntilFlush = 0;
} }
void FolderMemoryCard::Close() { void FolderMemoryCard::Close( bool flush ) {
if ( !m_isEnabled ) { return; } if ( !m_isEnabled ) { return; }
Flush(); if ( flush ) {
Flush();
}
m_cache.clear(); m_cache.clear();
m_oldDataCache.clear(); m_oldDataCache.clear();
@ -106,7 +108,7 @@ void FolderMemoryCard::Close() {
m_lastAccessedFile.Close(); m_lastAccessedFile.Close();
} }
void FolderMemoryCard::LoadMemoryCardData( const bool enableFiltering, const wxString& filter ) { void FolderMemoryCard::LoadMemoryCardData( const u32 sizeInClusters, const bool enableFiltering, const wxString& filter ) {
bool formatted = false; bool formatted = false;
// read superblock if it exists // read superblock if it exists
@ -118,6 +120,11 @@ void FolderMemoryCard::LoadMemoryCardData( const bool enableFiltering, const wxS
} }
} }
if ( sizeInClusters > 0 && sizeInClusters != GetSizeInClusters() ) {
SetSizeInClusters( sizeInClusters );
FlushBlock( 0 );
}
// if superblock was valid, load folders and files // if superblock was valid, load folders and files
if ( formatted ) { if ( formatted ) {
if ( enableFiltering ) { if ( enableFiltering ) {

View File

@ -293,8 +293,9 @@ public:
// Initialize & Load Memory Card with values configured in the Memory Card Manager // Initialize & Load Memory Card with values configured in the Memory Card Manager
void Open( const bool enableFiltering, const wxString& filter ); void Open( const bool enableFiltering, const wxString& filter );
// Initialize & Load Memory Card with provided custom values // Initialize & Load Memory Card with provided custom values
void Open( const wxString& fullPath, const AppConfig::McdOptions& mcdOptions, const bool enableFiltering, const wxString& filter ); void Open( const wxString& fullPath, const AppConfig::McdOptions& mcdOptions, const u32 sizeInClusters, const bool enableFiltering, const wxString& filter );
void Close(); // Close the memory card and flush changes to the file system. Set flush to false to not store changes.
void Close( bool flush = true );
s32 IsPresent() const; s32 IsPresent() const;
void GetSizeInfo( PS2E_McdSizeInfo& outways ) const; void GetSizeInfo( PS2E_McdSizeInfo& outways ) const;
@ -357,9 +358,10 @@ protected:
// loads files and folders from the host file system if a superblock exists in the root directory // loads files and folders from the host file system if a superblock exists in the root directory
// - sizeInClusters: total memory card size in clusters, 0 for default
// - enableFiltering: if set to true, only folders whose name contain the filter string are loaded // - enableFiltering: if set to true, only folders whose name contain the filter string are loaded
// - filter: can include multiple filters by separating them with "/" // - filter: can include multiple filters by separating them with "/"
void LoadMemoryCardData( const bool enableFiltering, const wxString& filter ); void LoadMemoryCardData( const u32 sizeInClusters, const bool enableFiltering, const wxString& filter );
// creates the FAT and indirect FAT // creates the FAT and indirect FAT
void CreateFat(); void CreateFat();