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
This commit is contained in:
Jake.Stine 2010-05-23 15:20:52 +00:00
parent 0b7bbdc723
commit d8ba646de2
19 changed files with 791 additions and 289 deletions

View File

@ -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;

View File

@ -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 );

View File

@ -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
{

View File

@ -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

View File

@ -19,6 +19,8 @@
#include "IniInterface.h"
#include "Plugins.h"
#include "MemoryCardFile.h"
#include <wx/stdpaths.h>
#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 );
}
}

View File

@ -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;

View File

@ -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 );
};
}

View File

@ -15,6 +15,9 @@
#include "PrecompiledHeader.h"
#include "ConfigurationDialog.h"
#include "System.h"
#include "MemoryCardFile.h"
#include <wx/filepicker.h>
#include <wx/ffile.h>
@ -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);
}

View File

@ -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 )
{

View File

@ -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 <wx/ffile.h>
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<u8> 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; i<MC2_SIZE/sizeof(m_effeffs); i++ )
for( uint i=0; i<(MC2_MBSIZE*sizeInMB)/sizeof(m_effeffs); i++ )
{
if( fp.Write( m_effeffs, sizeof(m_effeffs) ) == 0 )
return false;
@ -158,14 +212,14 @@ bool FileMemoryCard::Create( const wxString& mcdFile )
return true;
}
s32 FileMemoryCard::IsPresent( uint port, uint slot )
s32 FileMemoryCard::IsPresent( uint slot )
{
return m_file[port][slot].IsOpened();
return m_file[slot].IsOpened();
}
s32 FileMemoryCard::Read( uint port, uint slot, u8 *dest, u32 adr, int size )
s32 FileMemoryCard::Read( uint slot, u8 *dest, u32 adr, int size )
{
wxFFile& mcfp( m_file[port][slot] );
wxFFile& mcfp( m_file[slot] );
if( !mcfp.IsOpened() )
{
DevCon.Error( "MemoryCard: Ignoring attempted read from disabled card." );
@ -176,9 +230,9 @@ s32 FileMemoryCard::Read( uint port, uint slot, u8 *dest, u32 adr, int size )
return mcfp.Read( dest, size ) != 0;
}
s32 FileMemoryCard::Save( uint port, uint slot, const u8 *src, u32 adr, int size )
s32 FileMemoryCard::Save( uint slot, const u8 *src, u32 adr, int size )
{
wxFFile& mcfp( m_file[port][slot] );
wxFFile& mcfp( m_file[slot] );
if( !mcfp.IsOpened() )
{
@ -201,9 +255,9 @@ s32 FileMemoryCard::Save( uint port, uint slot, const u8 *src, u32 adr, int size
return mcfp.Write( m_currentdata.GetPtr(), size ) != 0;
}
s32 FileMemoryCard::EraseBlock( uint port, uint slot, u32 adr )
s32 FileMemoryCard::EraseBlock( uint slot, u32 adr )
{
wxFFile& mcfp( m_file[port][slot] );
wxFFile& mcfp( m_file[slot] );
if( !mcfp.IsOpened() )
{
@ -215,9 +269,9 @@ s32 FileMemoryCard::EraseBlock( uint port, uint slot, u32 adr )
return mcfp.Write( m_effeffs, sizeof(m_effeffs) ) != 0;
}
u64 FileMemoryCard::GetCRC( uint port, uint slot )
u64 FileMemoryCard::GetCRC( uint slot )
{
wxFFile& mcfp( m_file[port][slot] );
wxFFile& mcfp( m_file[slot] );
if( !mcfp.IsOpened() ) return 0;
if( !Seek( mcfp, 0 ) ) return 0;
@ -247,29 +301,36 @@ struct Component_FileMcd
Component_FileMcd();
};
uint FileMcd_ConvertToSlot( uint port, uint slot )
{
if( slot == 0 ) return port;
if( port == 0 ) return slot+1; // multitap 1
return slot + 4; // multitap 2
}
static s32 PS2E_CALLBACK FileMcd_IsPresent( PS2E_THISPTR thisptr, uint port, uint slot )
{
return thisptr->impl.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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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);

View File

@ -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;
}

View File

@ -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 ()

View File

@ -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 );

View File

@ -16,10 +16,14 @@
#include "PrecompiledHeader.h"
#include "ConfigurationPanels.h"
#include "MemoryCardPanels.h"
#include "System.h"
#include <wx/filepicker.h>
#include <wx/ffile.h>
#include <wx/dir.h>
#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];
}

View File

@ -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;
}

View File

@ -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<McdListItem> McdList;
@ -75,12 +59,12 @@ typedef std::vector<McdListItem> 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:

View File

@ -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 );
}
// ------------------------------------

View File

@ -2769,6 +2769,10 @@
RelativePath="..\..\gui\MainFrame.h"
>
</File>
<File
RelativePath="..\..\gui\MemoryCardFile.h"
>
</File>
<File
RelativePath="..\..\gui\pxEventThread.h"
>