From d8ba646de2ce9817dceff0ed9d3f23a9a6f4ee05 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Sun, 23 May 2010 15:20:52 +0000 Subject: [PATCH] Even more memorycard work! Dialog box is mostly functional now (still missing a couple options and refinements) -- WARNING: settings/ini storage has changed. If you're using non-default memorycard settings, you'll need to go and edit your ini again. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3066 96395faa-99c1-11dd-bbfe-3dabce05a288 --- common/include/Utilities/pxRadioPanel.h | 23 + common/include/Utilities/wxGuiTools.h | 2 +- common/src/Utilities/pxRadioPanel.cpp | 9 + nsis/pcsx2_installer_script.nsi | 8 +- pcsx2/gui/AppConfig.cpp | 40 +- pcsx2/gui/AppConfig.h | 9 +- pcsx2/gui/Dialogs/ConfigurationDialog.h | 11 +- pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp | 146 +++++-- pcsx2/gui/Dialogs/McdConfigDialog.cpp | 4 +- pcsx2/gui/MemoryCardFile.cpp | 198 +++++---- pcsx2/gui/MemoryCardFile.h | 29 ++ pcsx2/gui/MessageBoxes.cpp | 4 +- pcsx2/gui/Panels/BiosSelectorPanel.cpp | 9 +- pcsx2/gui/Panels/ConfigurationPanels.h | 9 +- pcsx2/gui/Panels/MemoryCardListPanel.cpp | 421 +++++++++++++++---- pcsx2/gui/Panels/MemoryCardListView.cpp | 31 +- pcsx2/gui/Panels/MemoryCardPanels.h | 81 ++-- pcsx2/gui/Panels/MemoryCardsPanel.cpp | 42 +- pcsx2/windows/VCprojects/pcsx2_2008.vcproj | 4 + 19 files changed, 791 insertions(+), 289 deletions(-) create mode 100644 pcsx2/gui/MemoryCardFile.h diff --git a/common/include/Utilities/pxRadioPanel.h b/common/include/Utilities/pxRadioPanel.h index 4b0e7306e..f4a43a8e9 100644 --- a/common/include/Utilities/pxRadioPanel.h +++ b/common/include/Utilities/pxRadioPanel.h @@ -29,11 +29,16 @@ struct RadioPanelItem wxString SubText; wxString ToolTip; + int SomeInt; + void* SomePtr; + RadioPanelItem( const wxString& label, const wxString& subtext=wxEmptyString, const wxString& tooltip=wxEmptyString ) : Label( label ) , SubText( subtext ) , ToolTip( tooltip ) { + SomeInt = 0; + SomePtr = NULL; } RadioPanelItem& SetToolTip( const wxString& tip ) @@ -47,6 +52,18 @@ struct RadioPanelItem SubText = text; return *this; } + + RadioPanelItem& SetInt( int intval ) + { + SomeInt = intval; + return *this; + } + + RadioPanelItem& SetPtr( void* ptrval ) + { + SomePtr = ptrval; + return *this; + } }; @@ -114,10 +131,16 @@ public: pxRadioPanel& SetDefaultItem( int idx ); pxRadioPanel& EnableItem( int idx, bool enable=true ); + const RadioPanelItem& Item(int idx) const; + RadioPanelItem& Item(int idx); + int GetSelection() const; wxWindowID GetSelectionId() const; bool IsSelected( int idx ) const; + const RadioPanelItem& SelectedItem() const { return Item(GetSelection()); } + RadioPanelItem& SelectedItem() { return Item(GetSelection()); } + wxRadioButton* GetButton( int idx ); const wxRadioButton* GetButton( int idx ) const; diff --git a/common/include/Utilities/wxGuiTools.h b/common/include/Utilities/wxGuiTools.h index 0a125c692..45aeff35c 100644 --- a/common/include/Utilities/wxGuiTools.h +++ b/common/include/Utilities/wxGuiTools.h @@ -307,7 +307,7 @@ protected: bool m_hasContextHelp; int m_idealWidth; wxBoxSizer* m_extraButtonSizer; - + public: wxDialogWithHelpers(); wxDialogWithHelpers(wxWindow* parent, const wxString& title, bool hasContextHelp=false, bool resizable=false ); diff --git a/common/src/Utilities/pxRadioPanel.cpp b/common/src/Utilities/pxRadioPanel.cpp index 3a4456c1e..90f527ab9 100644 --- a/common/src/Utilities/pxRadioPanel.cpp +++ b/common/src/Utilities/pxRadioPanel.cpp @@ -177,6 +177,15 @@ pxRadioPanel& pxRadioPanel::EnableItem( int idx, bool enable ) return *this; } +const RadioPanelItem& pxRadioPanel::Item(int idx) const +{ + return m_buttonStrings[idx]; +} + +RadioPanelItem& pxRadioPanel::Item(int idx) +{ + return m_buttonStrings[idx]; +} int pxRadioPanel::GetSelection() const { diff --git a/nsis/pcsx2_installer_script.nsi b/nsis/pcsx2_installer_script.nsi index 9ae2eaa3a..c31c77c94 100644 --- a/nsis/pcsx2_installer_script.nsi +++ b/nsis/pcsx2_installer_script.nsi @@ -11,7 +11,7 @@ !endif !ifndef INC_CRT_2008 - !define INC_CRT_2008 1 + !define INC_CRT_2008 0 !endif !ifndef INC_CRT_2010 @@ -313,7 +313,13 @@ LangString DESC_DIRECTX ${LANG_ENGLISH} "Only uncheck this if you are quite c !insertmacro MUI_DESCRIPTION_TEXT ${SEC_STARTMENU} $(DESC_STARTMENU) !insertmacro MUI_DESCRIPTION_TEXT ${SEC_DESKTOP} $(DESC_DESKTOP) +!if ${INC_CRT_2008} > 0 !insertmacro MUI_DESCRIPTION_TEXT ${SEC_CRT2008} $(DESC_CRT2008) +!endif + +!if ${INC_CRT_2010} > 0 !insertmacro MUI_DESCRIPTION_TEXT ${SEC_CRT2010} $(DESC_CRT2010) +!endif + !insertmacro MUI_DESCRIPTION_TEXT ${SEC_DIRECTX} $(DESC_DIRECTX) !insertmacro MUI_FUNCTION_DESCRIPTION_END diff --git a/pcsx2/gui/AppConfig.cpp b/pcsx2/gui/AppConfig.cpp index a49a6719d..5ed4b747e 100644 --- a/pcsx2/gui/AppConfig.cpp +++ b/pcsx2/gui/AppConfig.cpp @@ -19,6 +19,8 @@ #include "IniInterface.h" #include "Plugins.h" +#include "MemoryCardFile.h" + #include #include "DebugTools/Debug.h" @@ -336,9 +338,9 @@ wxString GetSettingsFilename() wxString AppConfig::FullpathToBios() const { return Path::Combine( Folders.Bios, BaseFilenames.Bios ); } -wxString AppConfig::FullpathToMcd( uint port, uint slot ) const +wxString AppConfig::FullpathToMcd( uint slot ) const { - return Path::Combine( Folders.MemoryCards, Mcd[port][slot].Filename ); + return Path::Combine( Folders.MemoryCards, Mcd[slot].Filename ); } AppConfig::AppConfig() @@ -363,13 +365,11 @@ AppConfig::AppConfig() CdvdSource = CDVDsrc_Iso; - for( uint port=0; port<2; ++port ) + // To be moved to FileMemoryCard pluign (someday) + for( uint slot=0; slot<8; ++slot ) { - for( uint slot=0; slot<4; ++slot ) - { - Mcd[port][slot].Enabled = (slot==0); // enables main 2 slots - Mcd[port][slot].Filename = FilenameDefs::Memcard( port, slot ); - } + Mcd[slot].Enabled = !FileMcd_IsMultitapSlot(slot); // enables main 2 slots + Mcd[slot].Filename = FileMcd_GetDefaultName( slot ); } } @@ -409,15 +409,23 @@ void AppConfig::LoadSaveMemcards( IniInterface& ini ) AppConfig defaults; IniScopedGroup path( ini, L"MemoryCards" ); - for( uint port=0; port<2; ++port ) + for( uint slot=0; slot<2; ++slot ) { - for( int slot=0; slot<4; ++slot ) - { - ini.Entry( wxsFormat( L"Port%d_Slot%d_Enable", port, slot ), - Mcd[port][slot].Enabled, defaults.Mcd[port][slot].Enabled ); - ini.Entry( wxsFormat( L"Port%d_Slot%d_Filename", port, slot ), - Mcd[port][slot].Filename, defaults.Mcd[port][slot].Filename ); - } + ini.Entry( wxsFormat( L"Slot%u_Enable", slot+1 ), + Mcd[slot].Enabled, defaults.Mcd[slot].Enabled ); + ini.Entry( wxsFormat( L"Slot%u_Filename", slot+1 ), + Mcd[slot].Filename, defaults.Mcd[slot].Filename ); + } + + for( uint slot=2; slot<8; ++slot ) + { + int mtport = FileMcd_GetMtapPort(slot)+1; + int mtslot = FileMcd_GetMtapSlot(slot)+1; + + ini.Entry( wxsFormat( L"Multitap%u_Slot%d_Enable", mtport, mtslot ), + Mcd[slot].Enabled, defaults.Mcd[slot].Enabled ); + ini.Entry( wxsFormat( L"Multitap%u_Slot%d_Filename", mtport, mtslot ), + Mcd[slot].Filename, defaults.Mcd[slot].Filename ); } } diff --git a/pcsx2/gui/AppConfig.h b/pcsx2/gui/AppConfig.h index aca4ce5bb..dbe751c1d 100644 --- a/pcsx2/gui/AppConfig.h +++ b/pcsx2/gui/AppConfig.h @@ -222,7 +222,10 @@ public: wxString CurrentELF; CDVD_SourceType CdvdSource; - McdOptions Mcd[2][4]; + // Memorycard options - first 2 are default slots, last 6 are multitap 1 and 2 + // slots (3 each) + McdOptions Mcd[8]; + ConsoleLogOptions ProgLogBox; FolderOptions Folders; FilenameOptions BaseFilenames; @@ -239,7 +242,7 @@ public: AppConfig(); wxString FullpathToBios() const; - wxString FullpathToMcd( uint port, uint slot ) const; + wxString FullpathToMcd( uint slot ) const; wxString FullpathTo( PluginsEnum_t pluginId ) const; bool FullpathMatchTest( PluginsEnum_t pluginId, const wxString& cmpto ) const; @@ -254,7 +257,7 @@ public: struct ConfigOverrides { AppConfig::FilenameOptions Filenames; - wxString SettingsFolder; + wxString SettingsFolder; }; extern ConfigOverrides OverrideOptions; diff --git a/pcsx2/gui/Dialogs/ConfigurationDialog.h b/pcsx2/gui/Dialogs/ConfigurationDialog.h index cf4fb672f..ad2581ce3 100644 --- a/pcsx2/gui/Dialogs/ConfigurationDialog.h +++ b/pcsx2/gui/Dialogs/ConfigurationDialog.h @@ -152,6 +152,10 @@ namespace Dialogs class CreateMemoryCardDialog : public wxDialogWithHelpers { protected: + uint m_slot; + wxDirName m_mcdpath; + wxString m_mcdfile; + wxFilePickerCtrl* m_filepicker; pxRadioPanel* m_radio_CardSize; @@ -161,10 +165,13 @@ namespace Dialogs public: virtual ~CreateMemoryCardDialog() throw() {} - CreateMemoryCardDialog( wxWindow* parent, uint port, uint slot, const wxString& filepath=wxEmptyString ); + //CreateMemoryCardDialog( wxWindow* parent, uint port, uint slot, const wxString& filepath=wxEmptyString ); + CreateMemoryCardDialog( wxWindow* parent, uint port, const wxDirName& mcdpath, const wxString& mcdfile=wxEmptyString ); + + wxDirName GetPathToMcds() const; protected: + void CreateControls(); void OnOk_Click( wxCommandEvent& evt ); - void OnDoubleClicked( wxCommandEvent& evt ); }; } diff --git a/pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp b/pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp index b743a740a..a79b10462 100644 --- a/pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp +++ b/pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp @@ -15,6 +15,9 @@ #include "PrecompiledHeader.h" #include "ConfigurationDialog.h" +#include "System.h" + +#include "MemoryCardFile.h" #include #include @@ -38,14 +41,106 @@ wxFilePickerCtrl* CreateMemoryCardFilePicker( wxWindow* parent, uint portidx, ui L"Deletes the existing memory card and creates a new one. All existing card contents will be lost." ) );*/ -Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint port, uint slot, const wxString& filepath ) - : wxDialogWithHelpers( parent, _("Create a new MemoryCard..."), wxVERTICAL ) +Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint slot, const wxDirName& mcdpath, const wxString& mcdfile ) + : wxDialogWithHelpers( parent, _("Create new MemoryCard"), wxVERTICAL ) + , m_mcdpath( mcdpath.IsOk() ? mcdpath : (wxDirName)g_Conf->Mcd[slot].Filename.GetPath() ) + , m_mcdfile( mcdfile.IsEmpty() ? g_Conf->Mcd[slot].Filename.GetFullName() : mcdfile ) { - m_idealWidth = 620; + m_idealWidth = 472; + m_filepicker = NULL; + m_slot = slot; + + CreateControls(); + + //m_filepicker = CreateMemoryCardFilePicker( this, m_port, m_slot, filepath ); + + // ---------------------------- + // Sizers and Layout + // ---------------------------- + + if( m_radio_CardSize ) m_radio_CardSize->Realize(); + + wxBoxSizer& s_buttons( *new wxBoxSizer(wxHORIZONTAL) ); + s_buttons += new wxButton( this, wxID_OK ) | pxProportion(2); + s_buttons += pxStretchSpacer(3); + s_buttons += new wxButton( this, wxID_CANCEL ) | pxProportion(2); wxBoxSizer& s_padding( *new wxBoxSizer(wxVERTICAL) ); - *this += s_padding | StdExpand(); + //s_padding += Heading(_("Select the size for your new MemoryCard.")); + + if( m_filepicker ) + s_padding += m_filepicker | StdExpand(); + else + { + s_padding += Heading( _( "(new card will be saved to:" ) ); + s_padding += Heading( (m_mcdpath + m_mcdfile).GetFullPath() ); + } + + s_padding += m_radio_CardSize | StdExpand(); + #ifdef __WXMSW__ + if( m_check_CompressNTFS ) s_padding += m_check_CompressNTFS | StdExpand(); + #endif + + s_padding += 12; + s_padding += s_buttons | StdCenter(); + + *this += s_padding | StdExpand(); + + + FindItem( wxID_OK )->SetLabel(_("Create")); + Connect( wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CreateMemoryCardDialog::OnOk_Click ) ); + //Connect( wxID_APPLY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CreateMemoryCardDialog::OnApply_Click ) ); +} + +wxDirName Dialogs::CreateMemoryCardDialog::GetPathToMcds() const +{ + return m_filepicker ? (wxDirName)m_filepicker->GetPath() : m_mcdpath; +} + +// When this GUI is moved itno the FileMemoryCard plugin (where it eventually belongs), +// this function will be removed and the MemoryCardFile::Create() function will be used +// instead. +static bool CreateIt( const wxString& mcdFile, uint sizeInMB ) +{ + //int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0}; + + u8 m_effeffs[528*16]; + memset8<0xff>( m_effeffs ); + + Console.WriteLn( L"(FileMcd) Creating new %uMB MemoryCard: " + mcdFile, sizeInMB ); + + wxFFile fp( mcdFile, L"wb" ); + if( !fp.IsOpened() ) return false; + + static const int MC2_MBSIZE = 1024 * 528 * 2; // Size of a single megabyte of card data + + for( uint i=0; i<(MC2_MBSIZE*sizeInMB)/sizeof(m_effeffs); i++ ) + { + if( fp.Write( m_effeffs, sizeof(m_effeffs) ) == 0 ) + return false; + } + return true; +} + +void Dialogs::CreateMemoryCardDialog::OnOk_Click( wxCommandEvent& evt ) +{ + if( !CreateIt( + m_filepicker ? m_filepicker->GetPath() : m_mcdfile, + m_radio_CardSize ? m_radio_CardSize->SelectedItem().SomeInt : 8 + ) ) + { + Msgbox::Alert( + _("Error: The MemoryCard could not be created."), + _("MemoryCard creation error") + ); + return; + } + EndModal( wxID_OK ); +} + +void Dialogs::CreateMemoryCardDialog::CreateControls() +{ #ifdef __WXMSW__ m_check_CompressNTFS = new pxCheckBox( this, _("Use NTFS compression on this card"), @@ -53,39 +148,26 @@ Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint ); #endif - pxE( ".Dialog:Memorycards:NeedsFormatting", - L"Your new MemoryCard needs to be formatted. Some games can format the card for you, while " - L"others may require you do so using the BIOS. To boot into the BIOS, select the NoDisc option " - L"as your CDVD Source." - ); - const RadioPanelItem tbl_CardSizes[] = { - RadioPanelItem(_("8 MB [most compatible]")) - . SetToolTip(_("8 meg carts are 'small' but are pretty well sure to work for any and all games.")), + RadioPanelItem(_("8 MB [most compatible]"), _("This is the standard Sony-provisioned size, and is supported by all games and BIOS versions.")) + . SetToolTip(_("Always use this option if you want the safest and surest MemoryCard behavior.")) + . SetInt(8), - RadioPanelItem(_("16 MB")) - . SetToolTip(_("16 and 32 MB cards have roughly the same compatibility factor. Most games see them fine, others may not.")), + RadioPanelItem(_("16 MB"), _("A typical size for 3rd-party MemoryCards which should work with most games.")) + . SetToolTip(_("16 and 32 MB cards have roughly the same compatibility factor.")) + . SetInt(16), - RadioPanelItem(_("32 MB")) - . SetToolTip(_("16 and 32 MB cards have roughly the same compatibility factor. Most games see them fine, others may not.")), + RadioPanelItem(_("32 MB"), _("A typical size for 3rd-party MemoryCards which should work with most games.")) + . SetToolTip(_("16 and 32 MB cards have roughly the same compatibility factor.")) + . SetInt(32), - RadioPanelItem(_("64 MB"), _("Low compatibility! Use at your own risk.")) - . SetToolTip(_("Yes it's very big. Unfortunately a lot of games don't really work with them properly.")) + RadioPanelItem(_("64 MB"), _("Low compatibility warning: Yes it's very big, but may not work with many games.")) + . SetToolTip(_("Use at your own risk. Erratic memorycard behavior is possible (though unlikely).")) + . SetInt(64) }; - m_radio_CardSize = &(new pxRadioPanel( this, tbl_CardSizes ))->SetDefaultItem(0); - - m_filepicker = CreateMemoryCardFilePicker( this, port, slot, filepath ); - - // ---------------------------- - // Sizers and Layout - // ---------------------------- - - s_padding += m_filepicker | StdExpand(); - s_padding += m_radio_CardSize | StdExpand(); - - #ifdef __WXMSW__ - s_padding += m_check_CompressNTFS; - #endif + m_radio_CardSize = new pxRadioPanel( this, tbl_CardSizes ); + m_radio_CardSize->SetDefaultItem(0); } + diff --git a/pcsx2/gui/Dialogs/McdConfigDialog.cpp b/pcsx2/gui/Dialogs/McdConfigDialog.cpp index 5528e63b6..20e1f9d62 100644 --- a/pcsx2/gui/Dialogs/McdConfigDialog.cpp +++ b/pcsx2/gui/Dialogs/McdConfigDialog.cpp @@ -89,8 +89,8 @@ void Panels::McdConfigPanel_Toggles::AppStatusEvent_OnSettingsApplied() Panels::McdConfigPanel_Standard::McdConfigPanel_Standard(wxWindow *parent) : _parent( parent ) { - m_panel_cardinfo[0] = new MemoryCardInfoPanel( this, 0, 0 ); - m_panel_cardinfo[1] = new MemoryCardInfoPanel( this, 1, 0 ); + m_panel_cardinfo[0] = new MemoryCardInfoPanel( this, 0 ); + m_panel_cardinfo[1] = new MemoryCardInfoPanel( this, 1 ); for( uint port=0; port<2; ++port ) { diff --git a/pcsx2/gui/MemoryCardFile.cpp b/pcsx2/gui/MemoryCardFile.cpp index c15bf3367..7ce1fa6d4 100644 --- a/pcsx2/gui/MemoryCardFile.cpp +++ b/pcsx2/gui/MemoryCardFile.cpp @@ -16,6 +16,8 @@ #include "PrecompiledHeader.h" #include "Utilities/SafeArray.h" +#include "MemoryCardFile.h" + // IMPORTANT! If this gets a macro redefinition error it means PluginCallbacks.h is included // in a global-scope header, and that's a BAD THING. Include it only into modules that need // it, because some need to be able to alter its behavior using defines. Like this: @@ -32,8 +34,10 @@ struct Component_FileMcd; #include -static const int MCD_SIZE = 1024 * 8 * 16; // Legacy PSX card default size -static const int MC2_SIZE = 1024 * 528 * 16; // PS2 card default size. +static const int MCD_SIZE = 1024 * 8 * 16; // Legacy PSX card default size + +static const int MC2_MBSIZE = 1024 * 528 * 2; // Size of a single megabyte of card data +static const int MC2_SIZE = MC2_SIZE * 8; // PS2 card default size (8MB) // -------------------------------------------------------------------------------------- // FileMemoryCard @@ -43,7 +47,7 @@ static const int MC2_SIZE = 1024 * 528 * 16; // PS2 card default size. class FileMemoryCard { protected: - wxFFile m_file[2][4]; + wxFFile m_file[8]; u8 m_effeffs[528*16]; SafeArray m_currentdata; @@ -54,68 +58,116 @@ public: void Lock(); void Unlock(); - s32 IsPresent( uint port, uint slot ); - s32 Read( uint port, uint slot, u8 *dest, u32 adr, int size ); - s32 Save( uint port, uint slot, const u8 *src, u32 adr, int size ); - s32 EraseBlock( uint port, uint slot, u32 adr ); - u64 GetCRC( uint port, uint slot ); + s32 IsPresent ( uint slot ); + s32 Read ( uint slot, u8 *dest, u32 adr, int size ); + s32 Save ( uint slot, const u8 *src, u32 adr, int size ); + s32 EraseBlock ( uint slot, u32 adr ); + u64 GetCRC ( uint slot ); protected: bool Seek( wxFFile& f, u32 adr ); - bool Create( const wxString& mcdFile ); + bool Create( const wxString& mcdFile, uint sizeInMB ); - wxString GetDisabledMessage( uint port, uint slot ) const + wxString GetDisabledMessage( uint slot ) const { return pxE( ".Popup:MemoryCard:HasBeenDisabled", wxsFormat( - L"The MemoryCard in port %d/slot %d has been automatically disabled. You can correct the problem\n" + L"The MemoryCard in slot %d has been automatically disabled. You can correct the problem\n" L"and re-enable the MemoryCard at any time using Config:MemoryCards from the main menu.", - port, slot + slot ) ); } }; +uint FileMcd_GetMtapPort(uint slot) +{ + switch( slot ) + { + case 0: case 2: case 3: case 4: return 0; + case 1: case 5: case 6: case 7: return 1; + + jNO_DEFAULT + } + + return 0; // technically unreachable. +} + +uint FileMcd_GetMtapSlot(uint slot) +{ + switch( slot ) + { + case 0: case 1: + pxFailDev( "Invalid parameter in call to GetMtapSlot -- specified slot is one of the base slots, not a Multitap slot." ); + break; + + case 2: case 3: case 4: return 0; + case 5: case 6: case 7: return 1; + + jNO_DEFAULT + } + + return 0; // technically unreachable. +} + +bool FileMcd_IsMultitapSlot( uint slot ) +{ + return (slot > 1); +} + +wxFileName FileMcd_GetSimpleName(uint slot) +{ + if( FileMcd_IsMultitapSlot(slot) ) + return g_Conf->Folders.MemoryCards + wxsFormat( L"Mcd-Multitap%u-Slot%02u.ps2", FileMcd_GetMtapPort(slot)+1, FileMcd_GetMtapSlot(slot)+1 ); + else + return g_Conf->Folders.MemoryCards + wxsFormat( L"Mcd%03u.ps2", slot+1 ); +} + +wxString FileMcd_GetDefaultName(uint slot) +{ + if( FileMcd_IsMultitapSlot(slot) ) + return wxsFormat( L"Mcd-Multitap%u-Slot%02u.ps2", FileMcd_GetMtapPort(slot)+1, FileMcd_GetMtapSlot(slot)+1 ); + else + return wxsFormat( L"Mcd%03u.ps2", slot+1 ); +} + FileMemoryCard::FileMemoryCard() { memset8<0xff>( m_effeffs ); - for( int port=0; port<2; ++port ) + for( int slot=0; slot<8; ++slot ) { - for( int slot=0; slot<4; ++slot ) + if( !g_Conf->Mcd[slot].Enabled || g_Conf->Mcd[slot].Filename.GetFullName().IsEmpty() ) continue; + + wxFileName fname( g_Conf->FullpathToMcd( slot ) ); + wxString str( fname.GetFullPath() ); + + const wxULongLong fsz = fname.GetSize(); + if( (fsz == 0) || (fsz == wxInvalidSize) ) { - if( !g_Conf->Mcd[port][slot].Enabled || g_Conf->Mcd[port][slot].Filename.GetFullName().IsEmpty() ) continue; - - wxFileName fname( g_Conf->FullpathToMcd( port, slot ) ); - wxString str( fname.GetFullPath() ); - - const wxULongLong fsz = fname.GetSize(); - if( (fsz == 0) || (fsz == wxInvalidSize) ) + if( !Create( str, 8 ) ) { - if( !Create( str ) ) - { - Msgbox::Alert( - wxsFormat( _( "Could not create a MemoryCard file: \n\n%s\n\n" ), str.c_str() ) + - GetDisabledMessage( port, slot ) - ); - } - } - - // [TODO] : Add memcard size detection and report it to the console log. - // (8MB, 256Mb, whatever) - -#ifdef __WXMSW__ - NTFS_CompressFile( str, g_Conf->McdCompressNTFS ); -#endif - - if( !m_file[port][slot].Open( str.c_str(), L"r+b" ) ) - { - // Translation note: detailed description should mention that the memory card will be disabled - // for the duration of this session. Msgbox::Alert( - wxsFormat( _( "Access denied to MemoryCard file: \n\n%s\n\n" ), str.c_str() ) + - GetDisabledMessage( port, slot ) + wxsFormat(_( "Could not create a MemoryCard file: \n\n%s\n\n" ), str.c_str()) + + GetDisabledMessage( slot ) ); } } + + // [TODO] : Add memcard size detection and report it to the console log. + // (8MB, 256Mb, whatever) + +#ifdef __WXMSW__ + NTFS_CompressFile( str, g_Conf->McdCompressNTFS ); +#endif + + if( !m_file[slot].Open( str.c_str(), L"r+b" ) ) + { + // Translation note: detailed description should mention that the memory card will be disabled + // for the duration of this session. + Msgbox::Alert( + wxsFormat(_( "Access denied to MemoryCard file: \n\n%s\n\n" ), str.c_str()) + + GetDisabledMessage( slot ) + ); + } } } @@ -143,14 +195,16 @@ bool FileMemoryCard::Seek( wxFFile& f, u32 adr ) } // returns FALSE if an error occurred (either permission denied or disk full) -bool FileMemoryCard::Create( const wxString& mcdFile ) +bool FileMemoryCard::Create( const wxString& mcdFile, uint sizeInMB ) { //int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0}; + Console.WriteLn( L"(FileMcd) Creating new %uMB MemoryCard: " + mcdFile, sizeInMB ); + wxFFile fp( mcdFile, L"wb" ); if( !fp.IsOpened() ) return false; - for( uint i=0; iimpl.IsPresent( port, slot ); + return thisptr->impl.IsPresent( FileMcd_ConvertToSlot( port, slot ) ); } static s32 PS2E_CALLBACK FileMcd_Read( PS2E_THISPTR thisptr, uint port, uint slot, u8 *dest, u32 adr, int size ) { - return thisptr->impl.Read( port, slot, dest, adr, size ); + return thisptr->impl.Read( FileMcd_ConvertToSlot( port, slot ), dest, adr, 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( port, slot, src, adr, size ); + return thisptr->impl.Save( FileMcd_ConvertToSlot( port, slot ), src, adr, size ); } static s32 PS2E_CALLBACK FileMcd_EraseBlock( PS2E_THISPTR thisptr, uint port, uint slot, u32 adr ) { - return thisptr->impl.EraseBlock( port, slot, adr ); + return thisptr->impl.EraseBlock( FileMcd_ConvertToSlot( port, slot ), adr ); } static u64 PS2E_CALLBACK FileMcd_GetCRC( PS2E_THISPTR thisptr, uint port, uint slot ) { - return thisptr->impl.GetCRC( port, slot ); + return thisptr->impl.GetCRC( FileMcd_ConvertToSlot( port, slot ) ); } Component_FileMcd::Component_FileMcd() @@ -354,8 +415,9 @@ extern "C" const PS2E_LibraryAPI* FileMcd_InitAPI( const PS2E_EmulatorInfo* emui } // -------------------------------------------------------------------------------------- -// Currently Unused Superblock Header Structs +// Currently Unused Superblock Header Struct // -------------------------------------------------------------------------------------- +// (provided for reference purposes) struct superblock { @@ -376,17 +438,3 @@ struct superblock u8 card_type; // 0x150 u8 card_flags; // 0x151 }; - -#if 0 // unused code? -struct McdBlock -{ - s8 Title[48]; - s8 ID[14]; - s8 Name[16]; - int IconCount; - u16 Icon[16*16*3]; - u8 Flags; -}; - -void GetMcdBlockInfo(int mcd, int block, McdBlock *info); -#endif diff --git a/pcsx2/gui/MemoryCardFile.h b/pcsx2/gui/MemoryCardFile.h new file mode 100644 index 000000000..d2a311482 --- /dev/null +++ b/pcsx2/gui/MemoryCardFile.h @@ -0,0 +1,29 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2010 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ + +#pragma once + +// 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 +// separate project file). +// +// Please do not move contents from MemoryCardfile.cpp, such as class definitions, into +// this file. I'd prefer they stay in MemoryCardFile.cpp for now. --air + +extern uint FileMcd_GetMtapPort(uint slot); +extern uint FileMcd_GetMtapSlot(uint slot); +extern bool FileMcd_IsMultitapSlot( uint slot ); +extern wxFileName FileMcd_GetSimpleName(uint slot); +extern wxString FileMcd_GetDefaultName(uint slot); diff --git a/pcsx2/gui/MessageBoxes.cpp b/pcsx2/gui/MessageBoxes.cpp index 4536c5dc1..70e5546e9 100644 --- a/pcsx2/gui/MessageBoxes.cpp +++ b/pcsx2/gui/MessageBoxes.cpp @@ -172,9 +172,7 @@ namespace Msgbox // Always returns false. bool Alert( const wxString& text, const wxString& caption, int icon ) { - MsgButtons buttons( MsgButtons().OK() ); - - ShowModal( caption, text, buttons ); + ShowModal( caption, text, MsgButtons().OK() ); return false; } diff --git a/pcsx2/gui/Panels/BiosSelectorPanel.cpp b/pcsx2/gui/Panels/BiosSelectorPanel.cpp index 521d01b34..c668a997c 100644 --- a/pcsx2/gui/Panels/BiosSelectorPanel.cpp +++ b/pcsx2/gui/Panels/BiosSelectorPanel.cpp @@ -61,12 +61,17 @@ bool Panels::BaseSelectorPanel::Show( bool visible ) return BaseApplicableConfigPanel::Show( visible ); } -void Panels::BaseSelectorPanel::OnRefresh( wxCommandEvent& evt ) +void Panels::BaseSelectorPanel::RefreshSelections() { ValidateEnumerationStatus(); DoRefresh(); } +void Panels::BaseSelectorPanel::OnRefreshSelections( wxCommandEvent& evt ) +{ + RefreshSelections(); +} + void Panels::BaseSelectorPanel::OnFolderChanged( wxFileDirPickerEvent& evt ) { evt.Skip(); @@ -100,7 +105,7 @@ Panels::BiosSelectorPanel::BiosSelectorPanel( wxWindow* parent, int idealWidth ) *this += 8; *this += m_FolderPicker | StdExpand(); - Connect( refreshButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BaseSelectorPanel::OnRefresh) ); + Connect( refreshButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BiosSelectorPanel::OnRefreshSelections) ); } Panels::BiosSelectorPanel::~BiosSelectorPanel() throw () diff --git a/pcsx2/gui/Panels/ConfigurationPanels.h b/pcsx2/gui/Panels/ConfigurationPanels.h index f87e6a273..d9ee66dc5 100644 --- a/pcsx2/gui/Panels/ConfigurationPanels.h +++ b/pcsx2/gui/Panels/ConfigurationPanels.h @@ -378,12 +378,15 @@ namespace Panels virtual ~BaseSelectorPanel() throw(); BaseSelectorPanel( wxWindow* parent ); + virtual void RefreshSelections(); + virtual bool Show( bool visible=true ); - virtual void OnRefresh( wxCommandEvent& evt ); virtual void OnShown(); virtual void OnFolderChanged( wxFileDirPickerEvent& evt ); protected: + void OnRefreshSelections( wxCommandEvent& evt ); + virtual void DoRefresh()=0; virtual bool ValidateEnumerationStatus()=0; void OnShow(wxShowEvent& evt); @@ -420,11 +423,11 @@ namespace Panels { protected: MemoryCardListPanel_Advanced* m_panel_AllKnownCards; - MemoryCardInfoPanel* m_panel_cardinfo[2][4]; + MemoryCardInfoPanel* m_panel_cardinfo[8]; pxCheckBox* m_check_Ejection; pxCheckBox* m_check_Multitap[2]; - uint m_Bindings[2][4]; + uint m_Bindings[8]; public: MemoryCardsPanel( wxWindow* parent ); diff --git a/pcsx2/gui/Panels/MemoryCardListPanel.cpp b/pcsx2/gui/Panels/MemoryCardListPanel.cpp index b35b1dc2e..6fc828185 100644 --- a/pcsx2/gui/Panels/MemoryCardListPanel.cpp +++ b/pcsx2/gui/Panels/MemoryCardListPanel.cpp @@ -16,10 +16,14 @@ #include "PrecompiledHeader.h" #include "ConfigurationPanels.h" #include "MemoryCardPanels.h" +#include "System.h" #include #include #include +#include "Dialogs/ConfigurationDialog.h" + +#include "MemoryCardFile.h" using namespace pxSizerFlags; @@ -86,6 +90,48 @@ static int EnumerateMemoryCards( McdList& dest, const wxArrayString& files ) return pushed; } +// -------------------------------------------------------------------------------------- +// McdListItem (implementations) +// -------------------------------------------------------------------------------------- +bool McdListItem::IsMultitapSlot() const +{ + return FileMcd_IsMultitapSlot(Slot); +} + +uint McdListItem::GetMtapPort() const +{ + return FileMcd_GetMtapPort(Slot); +} + +uint McdListItem::GetMtapSlot() const +{ + return FileMcd_GetMtapSlot(Slot); +} + +// Compares two cards -- If this equality comparison is used on items where +// no filename is specified, then the check will include port and slot. +bool McdListItem::operator==( const McdListItem& right ) const +{ + bool fileEqu; + + if( Filename.GetFullName().IsEmpty() ) + fileEqu = OpEqu(Slot); + else + fileEqu = OpEqu(Filename); + + return fileEqu && + OpEqu(IsPresent) && OpEqu(IsEnabled) && + OpEqu(SizeInMB) && OpEqu(IsFormatted) && + OpEqu(DateCreated) && OpEqu(DateModified); +} + +bool McdListItem::operator!=( const McdListItem& right ) const +{ + return operator==( right ); +} + +//DEFINE_EVENT_TYPE( pxEvt_RefreshSelections ); + // ===================================================================================================== // BaseMcdListPanel (implementations) // ===================================================================================================== @@ -101,9 +147,23 @@ Panels::BaseMcdListPanel::BaseMcdListPanel( wxWindow* parent ) m_btn_Refresh = new wxButton( this, wxID_ANY, _("Refresh list") ); - Connect( m_btn_Refresh->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BaseMcdListPanel::OnRefresh) ); + Connect( m_btn_Refresh->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BaseMcdListPanel::OnRefreshSelections) ); + //Connect( pxEvt_RefreshSelections, wxCommandEventHandler(BaseMcdListPanel::OnRefreshSelections) ); } +void Panels::BaseMcdListPanel::RefreshMcds() const +{ + wxCommandEvent refit( wxEVT_COMMAND_BUTTON_CLICKED ); + refit.SetId( m_btn_Refresh->GetId() ); + GetEventHandler()->AddPendingEvent( refit ); +} + +/*void Panels::BaseMcdListPanel::OnEvent_McdRefresh( wxCommandEvent& evt ) const +{ + RefreshSelections(); + evt.Skip(); +}*/ + void Panels::BaseMcdListPanel::CreateLayout() { if( m_listview ) m_listview->SetMinSize( wxSize( m_idealWidth, 140 ) ); @@ -145,8 +205,8 @@ Panels::MemoryCardListPanel_Advanced::MemoryCardListPanel_Advanced( wxWindow* pa CreateLayout(); *s_leftside_buttons += button_Create | StdSpace(); - Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(MemoryCardListPanel_Advanced::OnListDrag)); - Connect( button_Create->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MemoryCardListPanel_Advanced::OnCreateNewCard)); + Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler (MemoryCardListPanel_Advanced::OnListDrag)); + Connect( button_Create->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MemoryCardListPanel_Advanced::OnCreateNewCard)); } void Panels::MemoryCardListPanel_Advanced::Apply() @@ -185,7 +245,7 @@ bool Panels::MemoryCardListPanel_Advanced::ValidateEnumerationStatus() if( !m_KnownCards || (*mcdlist != *m_KnownCards) ) validated = false; - m_listview->SetInterface( NULL ); + m_listview->SetMcdProvider( NULL ); m_KnownCards.SwapPtr( mcdlist ); return validated; @@ -199,10 +259,9 @@ void Panels::MemoryCardListPanel_Advanced::DoRefresh() { McdListItem& mcditem( (*m_KnownCards)[i] ); - for( int port=0; port<2; ++port ) - for( int slot=0; slot<4; ++slot ) + for( int slot=0; slot<8; ++slot ) { - wxFileName right( g_Conf->FullpathToMcd(port, slot) ); + wxFileName right( g_Conf->FullpathToMcd(slot) ); right.MakeAbsolute(); wxFileName left( mcditem.Filename ); @@ -210,13 +269,12 @@ void Panels::MemoryCardListPanel_Advanced::DoRefresh() if( left == right ) { - mcditem.Port = port; mcditem.Slot = slot; } } } - m_listview->SetInterface( this ); + m_listview->SetMcdProvider( this ); //m_listview->SetCardCount( m_KnownCards->size() ); } @@ -232,7 +290,7 @@ void Panels::MemoryCardListPanel_Advanced::OnListDrag(wxListEvent& evt) wxDropSource dragSource( m_listview ); dragSource.SetData( my_data ); - wxDragResult result = dragSource.DoDragDrop(); + wxDragResult result = dragSource.DoDragDrop(wxDrag_AllowMove); } int Panels::MemoryCardListPanel_Advanced::GetLength() const @@ -252,17 +310,223 @@ McdListItem& Panels::MemoryCardListPanel_Advanced::GetCard( int idx ) return (*m_KnownCards)[idx]; } -uint Panels::MemoryCardListPanel_Advanced::GetPort( int idx ) const +// -------------------------------------------------------------------------------------- +// McdDataObject +// -------------------------------------------------------------------------------------- +class WXDLLEXPORT McdDataObject : public wxDataObjectSimple { - pxAssume(!!m_KnownCards); - return (*m_KnownCards)[idx].Port; -} + DECLARE_NO_COPY_CLASS(McdDataObject) -uint Panels::MemoryCardListPanel_Advanced::GetSlot( int idx ) const +protected: + int m_slot; + +public: + McdDataObject(int slot = -1) + : wxDataObjectSimple( wxDF_PRIVATE ) + { + m_slot = slot; + } + + uint GetSlot() const + { + pxAssumeDev( m_slot >= 0, "Memorycard Index is uninitialized (invalid drag&drop object state)" ); + return (uint)m_slot; + } + + size_t GetDataSize() const + { + return sizeof(u32); + } + + bool GetDataHere(void *buf) const + { + *(u32*)buf = GetSlot(); + return true; + } + + virtual bool SetData(size_t len, const void *buf) + { + if( !pxAssertDev( len == sizeof(u32), "Data length mismatch on memorycard drag&drop operation." ) ) return false; + + m_slot = *(u32*)buf; + return ( (uint)m_slot < 8 ); // sanity check (unsigned, so that -1 also is invalid) :) + } + + // Must provide overloads to avoid hiding them (and warnings about it) + virtual size_t GetDataSize(const wxDataFormat&) const + { + return GetDataSize(); + } + + virtual bool GetDataHere(const wxDataFormat&, void *buf) const + { + return GetDataHere(buf); + } + + virtual bool SetData(const wxDataFormat&, size_t len, const void *buf) + { + return SetData(len, buf); + } +}; + +class McdDropTarget : public wxDropTarget { - pxAssume(!!m_KnownCards); - return (*m_KnownCards)[idx].Slot; -} +protected: + BaseMcdListView* m_listview; + +public: + McdDropTarget( BaseMcdListView* listview=NULL ) + { + m_listview = listview; + SetDataObject(new McdDataObject()); + } + + // these functions are called when data is moved over position (x, y) and + // may return either wxDragCopy, wxDragMove or wxDragNone depending on + // what would happen if the data were dropped here. + // + // the last parameter is what would happen by default and is determined by + // the platform-specific logic (for example, under Windows it's wxDragCopy + // if Ctrl key is pressed and wxDragMove otherwise) except that it will + // always be wxDragNone if the carried data is in an unsupported format. + + + // called when the mouse moves in the window - shouldn't take long to + // execute or otherwise mouse movement would be too slow. + virtual wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult def) + { + int flags = 0; + int idx = m_listview->HitTest( wxPoint(x,y), flags); + m_listview->SetTargetedItem( idx ); + + if( wxNOT_FOUND == idx ) return wxDragNone; + + return def; + } + + virtual void OnLeave() + { + m_listview->SetTargetedItem( wxNOT_FOUND ); + } + + // this function is called when data is dropped at position (x, y) - if it + // returns true, OnData() will be called immediately afterwards which will + // allow to retrieve the data dropped. + virtual bool OnDrop(wxCoord x, wxCoord y) + { + int flags = 0; + int idx = m_listview->HitTest( wxPoint(x,y), flags); + return ( wxNOT_FOUND != idx ); + } + + // may be called *only* from inside OnData() and will fill m_dataObject + // with the data from the drop source if it returns true + virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def) + { + m_listview->SetTargetedItem( wxNOT_FOUND ); + + int flags = 0; + int idx = m_listview->HitTest( wxPoint(x,y), flags); + if( wxNOT_FOUND == idx ) return wxDragNone; + + if ( !GetData() ) return wxDragNone; + + McdDataObject *dobj = (McdDataObject *)m_dataObject; + + wxDragResult result = OnDropMcd( + m_listview->GetMcdProvider().GetCard(dobj->GetSlot()), + m_listview->GetMcdProvider().GetCard(idx), + def + ); + + if( wxDragNone == result ) return wxDragNone; + m_listview->GetMcdProvider().RefreshMcds(); + + return result; + } + + virtual wxDragResult OnDropMcd( const McdListItem& src, const McdListItem& dest, wxDragResult def ) + { + if( src.Slot == dest.Slot ) return wxDragNone; + if( !pxAssert( (src.Slot >= 0) && (dest.Slot >= 0) ) ) return wxDragNone; + + const wxDirName basepath( m_listview->GetMcdProvider().GetMcdPath() ); + wxFileName srcfile( basepath + g_Conf->Mcd[src.Slot].Filename ); + wxFileName destfile( basepath + g_Conf->Mcd[dest.Slot].Filename ); + + if( wxDragCopy == def ) + { + // user is force invoking copy mode, which means we need to check the destination + // and prompt if it looks valuable (formatted). + + if( dest.IsPresent && dest.IsFormatted ) + { + wxsFormat( pxE( ".Popup:Mcd:Overwrite", + L"This will copy the contents of the MemoryCard in slot %u over the Memorycard in slot %u. " + L"All data on the target slot will be lost. Are you sure?" ), + src.Slot, dest.Slot + ); + + //if( !Msgbox::OkCancel( ) ) + // return wxDragNone; + } + + ScopedBusyCursor doh( Cursor_ReallyBusy ); + if( !wxCopyFile( srcfile.GetFullPath(), destfile.GetFullPath(), true ) ) + { + wxString heading; + heading.Printf( pxE( ".Error:Mcd:Copy Failed", + L"Error! Could not copy the MemoryCard into slot %u. The destination file is in use." ), + dest.Slot + ); + + wxString content; + + Msgbox::Alert( heading + L"\n\n" + content, _("Copy failed!") ); + return wxDragNone; + } + } + else if( wxDragMove == def ) + { + // Move always performs a swap :) + + const bool srcExists( srcfile.FileExists() ); + const bool destExists( destfile.FileExists() ); + + bool result = true; + + if( destExists && srcExists) + { + wxFileName tempname; + tempname.AssignTempFileName( basepath.ToString() ); + + // Neat trick to handle errors. + result = result && wxRenameFile( srcfile.GetFullPath(), tempname.GetFullPath(), true ); + result = result && wxRenameFile( destfile.GetFullPath(), srcfile.GetFullPath(), false ); + result = result && wxRenameFile( tempname.GetFullPath(), srcfile.GetFullPath(), true ); + } + else if( destExists ) + { + result = wxRenameFile( destfile.GetFullPath(), srcfile.GetFullPath() ); + } + else if( srcExists ) + { + result = wxRenameFile( srcfile.GetFullPath(), destfile.GetFullPath() ); + } + + if( !result ) + { + // TODO : Popup an error to the user. + + Console.Error( "(McdFile) Memorycard swap failed." ); + Console.Indent().WriteLn( L"Src : " + srcfile.GetFullPath() ); + Console.Indent().WriteLn( L"Dest: " + destfile.GetFullPath() ); + } + } + + return def; + } +}; // ===================================================================================================== // MemoryCardListPanel_Simple (implementations) @@ -274,6 +538,7 @@ Panels::MemoryCardListPanel_Simple::MemoryCardListPanel_Simple( wxWindow* parent m_MultitapEnabled[1] = false; m_listview = new MemoryCardListView_Simple(this); + m_listview->SetDropTarget( new McdDropTarget(m_listview) ); m_button_Create = new wxButton(this, wxID_ANY, _("Create")); m_button_Mount = new wxButton(this, wxID_ANY, _("Mount")); @@ -291,7 +556,7 @@ Panels::MemoryCardListPanel_Simple::MemoryCardListPanel_Simple( wxWindow* parent Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(MemoryCardListPanel_Simple::OnListDrag)); Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(MemoryCardListPanel_Simple::OnListSelectionChanged)); - Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(MemoryCardListPanel_Simple::OnListSelectionChanged)); + Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler(MemoryCardListPanel_Simple::OnListSelectionChanged)); Connect( m_button_Mount->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnMountCard)); Connect( m_button_Create->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnCreateCard)); @@ -303,6 +568,13 @@ void Panels::MemoryCardListPanel_Simple::UpdateUI() int sel = m_listview->GetFirstSelected(); + if( wxNOT_FOUND == sel ) + { + m_button_Create->Disable(); + m_button_Mount->Disable(); + return; + } + /*if( !pxAssertDev( m_listview->GetItemData(sel), "Selected memorycard item data is NULL!" ) ) { m_button_Create->Disable(); @@ -310,9 +582,9 @@ void Panels::MemoryCardListPanel_Simple::UpdateUI() return; }*/ - //const McdListItem& item( *(McdListItem*)m_listview->GetItemData(sel) ); - const McdListItem& item( m_Cards[GetPort(sel)][GetSlot(sel)] ); + const McdListItem& item( m_Cards[sel] ); + m_button_Create->Enable(); m_button_Create->SetLabel( item.IsPresent ? _("Delete") : _("Create") ); pxSetToolTip( m_button_Create, item.IsPresent @@ -348,55 +620,88 @@ bool Panels::MemoryCardListPanel_Simple::OnDropFiles(wxCoord x, wxCoord y, const return false; } -static wxString GetAutoMcdName(uint port, uint slot) -{ - if( slot > 0 ) - return wxsFormat( L"mcd-port%u-slot%02u.ps2", port+1, slot+1 ); - else - return wxsFormat( L"Mcd%03u.ps2", port+1 ); -} - bool Panels::MemoryCardListPanel_Simple::ValidateEnumerationStatus() { - if( m_listview ) m_listview->SetInterface( NULL ); + if( m_listview ) m_listview->SetMcdProvider( NULL ); return false; } void Panels::MemoryCardListPanel_Simple::DoRefresh() { - for( uint port=0; port<2; ++port ) + for( uint slot=0; slot<8; ++slot ) { - for( uint slot=0; slot<4; ++slot ) - { - wxFileName fullpath( m_FolderPicker->GetPath() + GetAutoMcdName(port,slot) ); - EnumerateMemoryCard( m_Cards[port][slot], fullpath ); + wxFileName fullpath( m_FolderPicker->GetPath() + g_Conf->Mcd[slot].Filename.GetFullName() ); + EnumerateMemoryCard( m_Cards[slot], fullpath ); - if( (slot > 0) && !m_MultitapEnabled[port] ) - m_Cards[port][slot].IsEnabled = false; - } + m_Cards[slot].Slot = slot; + + if( FileMcd_IsMultitapSlot(slot) && !m_MultitapEnabled[FileMcd_GetMtapPort(slot)] ) + m_Cards[slot].IsEnabled = false; } - if( m_listview ) m_listview->SetInterface( this ); + if( m_listview ) m_listview->SetMcdProvider( this ); + UpdateUI(); } void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt) { + const int sel = m_listview->GetFirstSelected(); + if( wxNOT_FOUND == sel ) return; + const uint slot = sel; + if( m_Cards[slot].IsPresent ) + { + wxWindowID result = wxID_YES; + if( m_Cards[slot].IsFormatted ) + { + wxString content; + content.Printf(wxsFormat( + pxE(".Popup:DeleteMemoryCard", + L"You are about to delete the formatted memory card in slot %u. " + L"All data on this card will be lost! Are you absolutely and quite positively sure?" + ), slot ) + ); + + result = Msgbox::YesNo( content, _("Delete MemoryCard?") ); + } + + if( result == wxID_YES ) + { + wxFileName fullpath( m_FolderPicker->GetPath() + g_Conf->Mcd[slot].Filename.GetFullName() ); + wxRemoveFile( fullpath.GetFullPath() ); + } + } + else + Dialogs::CreateMemoryCardDialog( this, slot, m_FolderPicker->GetPath() ).ShowModal(); + + RefreshSelections(); } +/*void Panels::MemoryCardListPanel_Simple::OnSwapPorts(wxCommandEvent& evt) +{ + +}*/ + void Panels::MemoryCardListPanel_Simple::OnMountCard(wxCommandEvent& evt) { + const int sel = m_listview->GetFirstSelected(); + if( wxNOT_FOUND == sel ) return; + const uint slot = sel; + m_Cards[slot].IsEnabled = !m_Cards[slot].IsEnabled; + RefreshSelections(); } void Panels::MemoryCardListPanel_Simple::OnListDrag(wxListEvent& evt) { - wxFileDataObject my_data; - /*my_data.AddFile( (*m_KnownCards)[m_listview->GetItemData(m_listview->GetFirstSelected())].Filename.GetFullPath() ); + int selection = m_listview->GetFirstSelected(); + if( selection < 0 ) return; + McdDataObject my_data( selection ); + wxDropSource dragSource( m_listview ); dragSource.SetData( my_data ); - wxDragResult result = dragSource.DoDragDrop();*/ + wxDragResult result = dragSource.DoDragDrop( wxDrag_AllowMove ); } void Panels::MemoryCardListPanel_Simple::OnListSelectionChanged(wxListEvent& evt) @@ -415,38 +720,10 @@ int Panels::MemoryCardListPanel_Simple::GetLength() const const McdListItem& Panels::MemoryCardListPanel_Simple::GetCard( int idx ) const { - return m_Cards[GetPort(idx)][GetSlot(idx)]; + return m_Cards[idx]; } McdListItem& Panels::MemoryCardListPanel_Simple::GetCard( int idx ) { - return m_Cards[GetPort(idx)][GetSlot(idx)]; -} - -uint Panels::MemoryCardListPanel_Simple::GetPort( int idx ) const -{ - if( !m_MultitapEnabled[0] && !m_MultitapEnabled[1] ) - { - pxAssume( idx < 2 ); - return idx; - } - - if( !m_MultitapEnabled[0] ) - return (idx==0) ? 0 : 1; - else - return idx / 4; -} - -uint Panels::MemoryCardListPanel_Simple::GetSlot( int idx ) const -{ - if( !m_MultitapEnabled[0] && !m_MultitapEnabled[1] ) - { - pxAssume( idx < 2 ); - return 0; - } - - if( !m_MultitapEnabled[0] ) - return (idx==0) ? 0 : (idx-1); - else - return idx & 3; + return m_Cards[idx]; } diff --git a/pcsx2/gui/Panels/MemoryCardListView.cpp b/pcsx2/gui/Panels/MemoryCardListView.cpp index 0a6d1eb34..9e3f8fa3e 100644 --- a/pcsx2/gui/Panels/MemoryCardListView.cpp +++ b/pcsx2/gui/Panels/MemoryCardListView.cpp @@ -59,7 +59,6 @@ MemoryCardListView_Simple::MemoryCardListView_Simple( wxWindow* parent ) : _parent( parent ) { CreateColumns(); - Connect( wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(MemoryCardListView_Advanced::OnListDrag)); } void MemoryCardListView_Simple::SetCardCount( int length ) @@ -69,11 +68,6 @@ void MemoryCardListView_Simple::SetCardCount( int length ) Refresh(); } -void MemoryCardListView_Simple::OnListDrag(wxListEvent& evt) -{ - evt.Skip(); -} - // return the text for the given column of the given item wxString MemoryCardListView_Simple::OnGetItemText(long item, long column) const { @@ -83,16 +77,15 @@ wxString MemoryCardListView_Simple::OnGetItemText(long item, long column) const switch( column ) { - case McdColS_PortSlot: return wxsFormat( L"%u/%u", m_CardProvider->GetPort(item)+1, m_CardProvider->GetSlot(item)+1); + case McdColS_PortSlot: return wxsFormat( L"%u", item+1); case McdColS_Status: return it.IsPresent ? ( it.IsEnabled ? _("Enabled") : _("Disabled")) : _("Missing"); case McdColS_Size: return it.IsPresent ? wxsFormat( L"%u MB", it.SizeInMB ) : (wxString)_("N/A"); case McdColS_Formatted: return it.IsFormatted ? _("Yes") : _("No"); case McdColS_DateModified: return it.IsPresent ? it.DateModified.FormatDate() : (wxString)_("N/A"); case McdColS_DateCreated: return it.IsPresent ? it.DateCreated.FormatDate() : (wxString)_("N/A"); - //case McdCol_Path: return it.Filename.GetPath(); } - pxFail( "Unknown column index in MemoryCardListView_Advanced -- returning an empty string." ); + pxFail( "Unknown column index in MemoryCardListView -- returning an empty string." ); return wxEmptyString; } @@ -110,10 +103,24 @@ int MemoryCardListView_Simple::OnGetItemColumnImage(long item, long column) cons return _parent::OnGetItemColumnImage( item, column ); } +static wxListItemAttr m_ItemAttr; + // return the attribute for the item (may return NULL if none) wxListItemAttr* MemoryCardListView_Simple::OnGetItemAttr(long item) const { - wxListItemAttr* retval = _parent::OnGetItemAttr(item); - //const McdListItem& it( (*m_KnownCards)[item] ); - return retval; + //m_disabled.SetTextColour( wxLIGHT_GREY ); + //m_targeted.SetBackgroundColour( wxColour(L"Yellow") ); + + if( !m_CardProvider ) return _parent::OnGetItemAttr(item); + const McdListItem& it( m_CardProvider->GetCard(item) ); + + m_ItemAttr = wxListItemAttr(); // Wipe it clean! + + if( !it.IsEnabled ) + m_ItemAttr.SetTextColour( *wxLIGHT_GREY ); + + if( m_TargetedItem == item ) + m_ItemAttr.SetBackgroundColour( wxColour(L"Wheat") ); + + return &m_ItemAttr; } diff --git a/pcsx2/gui/Panels/MemoryCardPanels.h b/pcsx2/gui/Panels/MemoryCardPanels.h index c88f16668..af015598c 100644 --- a/pcsx2/gui/Panels/MemoryCardPanels.h +++ b/pcsx2/gui/Panels/MemoryCardPanels.h @@ -33,41 +33,25 @@ struct McdListItem wxDateTime DateCreated; wxDateTime DateModified; - int Port; int Slot; wxFileName Filename; // full pathname (optional) McdListItem() { - Port = -1; - Slot = -1; + //Port = -1; + Slot = -1; IsPresent = false; IsEnabled = false; } + + bool IsMultitapSlot() const; + uint GetMtapPort() const; + uint GetMtapSlot() const; - // Compares two cards -- If this equality comparison is used on items where - // no filename is specified, then the check will include port and slot. - bool operator==( const McdListItem& right ) const - { - bool fileEqu; - - if( Filename.GetFullName().IsEmpty() ) - fileEqu = OpEqu(Port) && OpEqu(Slot); - else - fileEqu = OpEqu(Filename); - - return fileEqu && - OpEqu(IsPresent) && OpEqu(IsEnabled) && - OpEqu(SizeInMB) && OpEqu(IsFormatted) && - OpEqu(DateCreated) && OpEqu(DateModified); - } - - bool operator!=( const McdListItem& right ) const - { - return operator==( right ); - } + bool operator==( const McdListItem& right ) const; + bool operator!=( const McdListItem& right ) const; }; typedef std::vector McdList; @@ -75,12 +59,12 @@ typedef std::vector McdList; class IMcdList { public: + virtual void RefreshMcds() const=0; virtual int GetLength() const=0; virtual const McdListItem& GetCard( int idx ) const=0; virtual McdListItem& GetCard( int idx )=0; - virtual uint GetPort( int idx ) const=0; - virtual uint GetSlot( int idx ) const=0; + virtual wxDirName GetMcdPath() const=0; }; class BaseMcdListView : public wxListView @@ -90,6 +74,9 @@ class BaseMcdListView : public wxListView protected: const IMcdList* m_CardProvider; + // specifies the target of a drag&drop operation + int m_TargetedItem; + public: virtual ~BaseMcdListView() throw() { } BaseMcdListView( wxWindow* parent ) @@ -100,11 +87,26 @@ public: virtual void SetCardCount( int length )=0; - virtual void SetInterface( IMcdList* face ) + virtual void SetMcdProvider( IMcdList* face ) { m_CardProvider = face; SetCardCount( m_CardProvider ? m_CardProvider->GetLength() : 0 ); } + + virtual const IMcdList& GetMcdProvider() const + { + pxAssume( m_CardProvider ); + return *m_CardProvider; + } + + virtual void SetTargetedItem( int sel ) + { + if( m_TargetedItem == sel ) return; + + if( m_TargetedItem >= 0 ) RefreshItem( m_TargetedItem ); + m_TargetedItem = sel; + RefreshItem( sel ); + } }; // -------------------------------------------------------------------------------------- @@ -118,7 +120,6 @@ public: virtual ~MemoryCardListView_Simple() throw() { } MemoryCardListView_Simple( wxWindow* parent ); - virtual void OnListDrag(wxListEvent& evt); void CreateColumns(); virtual void SetCardCount( int length ); @@ -142,7 +143,6 @@ public: virtual ~MemoryCardListView_Advanced() throw() { } MemoryCardListView_Advanced( wxWindow* parent ); - virtual void OnListDrag(wxListEvent& evt); void CreateColumns(); virtual void SetCardCount( int length ); @@ -162,6 +162,7 @@ namespace Panels class BaseMcdListPanel : public BaseSelectorPanel , public wxFileDropTarget + , public IMcdList // derived classes need to implement this { typedef BaseSelectorPanel _parent; @@ -173,6 +174,14 @@ namespace Panels wxBoxSizer* s_leftside_buttons; wxBoxSizer* s_rightside_buttons; + virtual void RefreshMcds() const; + + virtual wxDirName GetMcdPath() const + { + pxAssume(m_FolderPicker); + return m_FolderPicker->GetPath(); + } + public: virtual ~BaseMcdListPanel() throw() {} BaseMcdListPanel( wxWindow* parent ); @@ -185,12 +194,11 @@ namespace Panels // -------------------------------------------------------------------------------------- class MemoryCardListPanel_Simple : public BaseMcdListPanel - , public IMcdList { typedef BaseMcdListPanel _parent; protected: - McdListItem m_Cards[2][4]; + McdListItem m_Cards[8]; // Doubles as Create and Delete buttons wxButton* m_button_Create; @@ -208,10 +216,9 @@ namespace Panels // Interface Implementation for IMcdList virtual int GetLength() const; + virtual const McdListItem& GetCard( int idx ) const; virtual McdListItem& GetCard( int idx ); - virtual uint GetPort( int idx ) const; - virtual uint GetSlot( int idx ) const; protected: void OnCreateCard(wxCommandEvent& evt); @@ -232,7 +239,6 @@ namespace Panels // -------------------------------------------------------------------------------------- class MemoryCardListPanel_Advanced : public BaseMcdListPanel - , public IMcdList { typedef BaseMcdListPanel _parent; @@ -247,8 +253,6 @@ namespace Panels virtual int GetLength() const; virtual const McdListItem& GetCard( int idx ) const; virtual McdListItem& GetCard( int idx ); - virtual uint GetPort( int idx ) const; - virtual uint GetSlot( int idx ) const; protected: void OnCreateNewCard(wxCommandEvent& evt); @@ -268,7 +272,7 @@ namespace Panels class MemoryCardInfoPanel : public BaseApplicableConfigPanel { protected: - uint m_port; + //uint m_port; uint m_slot; wxString m_DisplayName; @@ -277,7 +281,7 @@ namespace Panels public: virtual ~MemoryCardInfoPanel() throw() {} - MemoryCardInfoPanel( wxWindow* parent, uint port, uint slot ); + MemoryCardInfoPanel( wxWindow* parent, uint slot ); void Apply(); void Eject(); @@ -332,7 +336,6 @@ namespace Panels protected: int m_port; - pxCheckBox* m_check_Multitap; public: diff --git a/pcsx2/gui/Panels/MemoryCardsPanel.cpp b/pcsx2/gui/Panels/MemoryCardsPanel.cpp index 2d6943c95..b463108bb 100644 --- a/pcsx2/gui/Panels/MemoryCardsPanel.cpp +++ b/pcsx2/gui/Panels/MemoryCardsPanel.cpp @@ -72,12 +72,6 @@ MemoryCardListView_Advanced::MemoryCardListView_Advanced( wxWindow* parent ) : _parent( parent ) { CreateColumns(); - Connect( wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(MemoryCardListView_Advanced::OnListDrag)); -} - -void MemoryCardListView_Advanced::OnListDrag(wxListEvent& evt) -{ - evt.Skip(); } // return the text for the given column of the given item @@ -91,8 +85,8 @@ wxString MemoryCardListView_Advanced::OnGetItemText(long item, long column) cons { case McdCol_Mounted: { - if( (it.Port == -1) && (it.Slot == -1) ) return L"No"; - return wxsFormat( L"%u / %u", it.Port+1, it.Slot+1); + if( !it.IsEnabled ) return _("No"); + return wxsFormat( L"%u", it.Slot+1); } case McdCol_Filename: return it.Filename.GetName(); @@ -133,10 +127,9 @@ wxListItemAttr* MemoryCardListView_Advanced::OnGetItemAttr(long item) const // ===================================================================================================== // MemoryCardInfoPanel // ===================================================================================================== -MemoryCardInfoPanel::MemoryCardInfoPanel( wxWindow* parent, uint port, uint slot ) +MemoryCardInfoPanel::MemoryCardInfoPanel( wxWindow* parent, uint slot ) : BaseApplicableConfigPanel( parent, wxVERTICAL ) //, wxEmptyString ) { - m_port = port; m_slot = slot; SetMinSize( wxSize(128, 48) ); @@ -198,11 +191,11 @@ void MemoryCardInfoPanel::Apply() Eject(); throw Exception::CannotApplySettings( this, // Diagnostic - wxsFormat( L"Memorycard in Port %u, Slot %u conflicts with an existing directory.", m_port, m_slot ), + wxsFormat( L"Memorycard in slot %u conflicts with an existing directory.", m_slot ), // Translated wxsFormat( - _("Cannot use or create the memorycard in Port %u, Slot %u: the filename conflicts with an existing directory."), - m_port, m_slot + _("Cannot use or create the memorycard in slot %u: the filename conflicts with an existing directory."), + m_slot ) ); } @@ -212,24 +205,24 @@ void MemoryCardInfoPanel::Apply() Eject(); throw Exception::CannotApplySettings( this, // Diagnostic - wxsFormat( L"Memorycard in Port %u, Slot %u is no longer valid.", m_port, m_slot ), + wxsFormat( L"Memorycard in slot %u is no longer valid.", m_slot ), // Translated wxsFormat( - _("The configured memorycard in Port %u, Slot %u no longer exists. Please create a new memory card, or leave the slot unmounted."), - m_port, m_slot + _("The configured memorycard in slot %u no longer exists. Please create a new memory card, or leave the slot unmounted."), + m_slot ) ); } - g_Conf->Mcd[m_port][m_slot].Filename = m_cardInfo->Filename; - g_Conf->Mcd[m_port][m_slot].Enabled = true; + g_Conf->Mcd[m_slot].Filename = m_cardInfo->Filename; + g_Conf->Mcd[m_slot].Enabled = true; } else { // Card is either disabled or in an error state. - g_Conf->Mcd[m_port][m_slot].Enabled = false; - g_Conf->Mcd[m_port][m_slot].Filename.Clear(); + g_Conf->Mcd[m_slot].Enabled = false; + g_Conf->Mcd[m_slot].Filename.Clear(); } } @@ -239,7 +232,7 @@ void MemoryCardInfoPanel::AppStatusEvent_OnSettingsApplied() // Collect Info and Format Strings - wxString fname( g_Conf->Mcd[m_port][m_slot].Filename.GetFullPath() ); + wxString fname( g_Conf->Mcd[m_slot].Filename.GetFullPath() ); if( fname.IsEmpty() ) { m_DisplayName = _("No Card (empty)"); @@ -277,12 +270,9 @@ Panels::MemoryCardsPanel::MemoryCardsPanel( wxWindow* parent ) { m_panel_AllKnownCards = new MemoryCardListPanel_Advanced( this ); - for( uint port=0; port<2; ++port ) + for( uint slot=0; slot<2; ++slot ) { - for( uint slot=0; slot<1; ++slot ) - { - m_panel_cardinfo[port][slot] = new MemoryCardInfoPanel( this, port, slot ); - } + m_panel_cardinfo[slot] = new MemoryCardInfoPanel( this, slot ); } // ------------------------------------ diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index 0c0a2eb70..0a82118ef 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -2769,6 +2769,10 @@ RelativePath="..\..\gui\MainFrame.h" > + +