Memory cards manager: bugfixes (all of them when multitap 1 is disabled) + better internal terminology:

Terminology:
Port (used only for presentation): actual PS2 port: 1-based index  (1 or 2 or multitap X port Y, whrere X is 1/2 and Y is 1/2/3/4 )
list-view-index: the running index (0-based) on the MCD viewable list (first always 0, last is always <num-items-on-the-list>-1).
Slot: pcsx2 internal slot representation. the slots are always fixed as follows:
slot 0: port 1 (or multitap 1 port 1 if multitap 1 is enabled)
slot 1: port 2 (or multitap 2 port 1 if multitap 2 is enabled)
slots 2,3,4: multitap 1: remaining 3 ports
slots 5,6,7: multitap 2: remaining 3 ports

The terms view-index and slot were used interchangeably (and always called 'slot'), and this was causing many bugs when multitap 1 is disabled (because on that specific case the view index doesn't align with the slot - because the multitap 1 items are not on the list). It should now be easier to follow the code and further modify it.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4410 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
avihal@gmail.com 2011-03-10 21:41:50 +00:00
parent f1b8b05043
commit b332a254f4
4 changed files with 123 additions and 106 deletions

View File

@ -118,7 +118,7 @@ bool FileMcd_IsMultitapSlot( uint slot )
{
return (slot > 1);
}
/*
wxFileName FileMcd_GetSimpleName(uint slot)
{
if( FileMcd_IsMultitapSlot(slot) )
@ -126,7 +126,7 @@ wxFileName FileMcd_GetSimpleName(uint slot)
else
return g_Conf->Folders.MemoryCards + wxsFormat( L"Mcd%03u.ps2", slot+1 );
}
*/
wxString FileMcd_GetDefaultName(uint slot)
{
if( FileMcd_IsMultitapSlot(slot) )

View File

@ -43,7 +43,7 @@ static bool IsMcdFormatted( wxFFile& fhand )
return memcmp( formatted_string, dest, fmtstrlen ) == 0;
}
bool EnumerateMemoryCard( McdListItem& dest, const wxFileName& filename )
bool EnumerateMemoryCard( McdSlotItem& dest, const wxFileName& filename )
{
dest.IsFormatted = false;
dest.IsPresent = false;
@ -69,7 +69,8 @@ bool EnumerateMemoryCard( McdListItem& dest, const wxFileName& filename )
return true;
}
//avih: unused??
//avih: unused
/*
static int EnumerateMemoryCards( McdList& dest, const wxArrayString& files )
{
int pushed = 0;
@ -77,7 +78,7 @@ static int EnumerateMemoryCards( McdList& dest, const wxArrayString& files )
for( size_t i=0; i<files.GetCount(); ++i )
{
ConsoleIndentScope con_indent;
McdListItem mcdItem;
McdSlotItem mcdItem;
if( EnumerateMemoryCard(mcdItem, files[i]) )
{
dest.push_back( mcdItem );
@ -91,28 +92,28 @@ static int EnumerateMemoryCards( McdList& dest, const wxArrayString& files )
return pushed;
}
*/
// --------------------------------------------------------------------------------------
// McdListItem (implementations)
// --------------------------------------------------------------------------------------
bool McdListItem::IsMultitapSlot() const
bool McdSlotItem::IsMultitapSlot() const
{
return FileMcd_IsMultitapSlot(Slot);
}
uint McdListItem::GetMtapPort() const
uint McdSlotItem::GetMtapPort() const
{
return FileMcd_GetMtapPort(Slot);
}
uint McdListItem::GetMtapSlot() const
uint McdSlotItem::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 McdSlotItem::operator==( const McdSlotItem& right ) const
{
bool fileEqu;
@ -127,7 +128,7 @@ bool McdListItem::operator==( const McdListItem& right ) const
OpEqu(DateCreated) && OpEqu(DateModified);
}
bool McdListItem::operator!=( const McdListItem& right ) const
bool McdSlotItem::operator!=( const McdSlotItem& right ) const
{
return operator==( right );
}
@ -218,19 +219,19 @@ class WXDLLEXPORT McdDataObject : public wxDataObjectSimple
DECLARE_NO_COPY_CLASS(McdDataObject)
protected:
int m_slot;
int m_viewIndex;
public:
McdDataObject(int slot = -1)
McdDataObject(int viewIndex = -1)
: wxDataObjectSimple( wxDF_PRIVATE )
{
m_slot = slot;
m_viewIndex = viewIndex;
}
uint GetSlot() const
uint GetViewIndex() const
{
pxAssumeDev( m_slot >= 0, "memory card Index is uninitialized (invalid drag&drop object state)" );
return (uint)m_slot;
pxAssumeDev( m_viewIndex >= 0, "memory card Index is uninitialized (invalid drag&drop object state)" );
return (uint)m_viewIndex;
}
size_t GetDataSize() const
@ -240,7 +241,7 @@ public:
bool GetDataHere(void *buf) const
{
*(u32*)buf = GetSlot();
*(u32*)buf = GetViewIndex();
return true;
}
@ -248,8 +249,8 @@ public:
{
if( !pxAssertDev( len == sizeof(u32), "Data length mismatch on memory card drag&drop operation." ) ) return false;
m_slot = *(u32*)buf;
return ( (uint)m_slot < 8 ); // sanity check (unsigned, so that -1 also is invalid) :)
m_viewIndex = *(u32*)buf;
return ( (uint)m_viewIndex < 8 ); // sanity check (unsigned, so that -1 also is invalid) :)
}
// Must provide overloads to avoid hiding them (and warnings about it)
@ -296,10 +297,10 @@ public:
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 );
int viewIndex = m_listview->HitTest( wxPoint(x,y), flags);
m_listview->SetTargetedItem( viewIndex );
if( wxNOT_FOUND == idx ) return wxDragNone;
if( wxNOT_FOUND == viewIndex ) return wxDragNone;
return def;
}
@ -315,8 +316,8 @@ public:
virtual bool OnDrop(wxCoord x, wxCoord y)
{
int flags = 0;
int idx = m_listview->HitTest( wxPoint(x,y), flags);
return ( wxNOT_FOUND != idx );
int viewIndex = m_listview->HitTest( wxPoint(x,y), flags);
return ( wxNOT_FOUND != viewIndex );
}
// may be called *only* from inside OnData() and will fill m_dataObject
@ -324,28 +325,32 @@ public:
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;
int destViewIndex = m_listview->HitTest( wxPoint(x,y), flags);
if( wxNOT_FOUND == destViewIndex )
return wxDragNone;
if ( !GetData() )
return wxDragNone;
McdDataObject *dobj = (McdDataObject *)m_dataObject;
int sourceViewIndex = dobj->GetViewIndex();
wxDragResult result = OnDropMcd(
m_listview->GetMcdProvider().GetCard(dobj->GetSlot()),
m_listview->GetMcdProvider().GetCard(idx),
m_listview->GetMcdProvider().GetCardForViewIndex( sourceViewIndex ),
m_listview->GetMcdProvider().GetCardForViewIndex( destViewIndex ),
def
);
if( wxDragNone == result ) return wxDragNone;
m_listview->GetMcdProvider().RefreshMcds();
if( wxDragNone == result )
return wxDragNone;
m_listview->GetMcdProvider().RefreshMcds();
return result;
}
virtual wxDragResult OnDropMcd( McdListItem& src, McdListItem& dest, wxDragResult def )
virtual wxDragResult OnDropMcd( McdSlotItem& src, McdSlotItem& dest, wxDragResult def )
{
if( src.Slot == dest.Slot ) return wxDragNone;
if( !pxAssert( (src.Slot >= 0) && (dest.Slot >= 0) ) ) return wxDragNone;
@ -365,9 +370,11 @@ public:
wxString content;
content.Printf(
pxE( "!Notice:Mcd:Overwrite",
L"This will copy the entire contents of the memory card in slot %u to the memory card in slot %u. "
L"All data on the memory card in slot %u will be lost. Are you sure?" ),
src.Slot+1, dest.Slot+1, dest.Slot+1
L"This will copy the entire contents of the memory card file '%s' (=slot %u) to the memory card file '%s' (=slot %u). "
L"All previous data on the memory card file '%s' will be lost. Are you sure?" ),
src.Filename.GetFullName().c_str(), src.Slot,
dest.Filename.GetFullName().c_str(), dest.Slot,
dest.Filename.GetFullName().c_str(), dest.Slot
);
result = Msgbox::YesNo( content, _("Overwrite memory card?") );
@ -381,8 +388,8 @@ public:
{
wxString heading;
heading.Printf( pxE( "!Notice:Mcd:Copy Failed",
L"Error! Could not copy the memory card into slot %u. The destination file is in use." ),
dest.Slot+1
L"Error! Could not copy the memory card into file '%s' (=slot %u). The destination file is in use." ),//xxx
dest.Filename.GetFullName().c_str(), dest.Slot
);
wxString content;
@ -507,7 +514,7 @@ void Panels::MemoryCardListPanel_Simple::UpdateUI()
return;
}
const McdListItem& item( m_Cards[sel] );
const McdSlotItem& item( GetCardForViewIndex(sel) );
m_button_Create->Enable();
m_button_Create->SetLabel( item.IsPresent ? _("Delete") : _("Create") );
@ -585,20 +592,23 @@ void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt)
{
ScopedCoreThreadClose closed_core;
const int slot = m_listview->GetFirstSelected();
if( wxNOT_FOUND == slot ) return;
const int selectedViewIndex = m_listview->GetFirstSelected();
if( wxNOT_FOUND == selectedViewIndex ) return;
if( m_Cards[slot].IsPresent )
McdSlotItem& card( GetCardForViewIndex(selectedViewIndex) );
if( card.IsPresent )
{
bool result = true;
if( m_Cards[slot].IsFormatted )
if( card.IsFormatted )
{
wxString content;
content.Printf(
pxE( "!Notice:Mcd:Delete",
L"You are about to delete the formatted memory card in slot %u. "
L"You are about to delete the formatted memory card file '%s' (=slot %u). "
L"All data on this card will be lost! Are you absolutely and quite positively sure?"
), slot+1
), card.Filename.GetFullName().c_str()
, card.Slot
);
result = Msgbox::YesNo( content, _("Delete memory card?") );
@ -606,14 +616,14 @@ void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt)
if( result )
{
wxFileName fullpath( m_FolderPicker->GetPath() + g_Conf->Mcd[slot].Filename.GetFullName() );
wxFileName fullpath( m_FolderPicker->GetPath() + g_Conf->Mcd[GetSlotIndexForViewIndex( selectedViewIndex )].Filename.GetFullName() );
wxRemoveFile( fullpath.GetFullPath() );
}
}
else
{
wxWindowID result = Dialogs::CreateMemoryCardDialog( this, slot, m_FolderPicker->GetPath() ).ShowModal();
m_Cards[slot].IsEnabled = (result != wxID_CANCEL);
wxWindowID result = Dialogs::CreateMemoryCardDialog( this, GetSlotIndexForViewIndex( selectedViewIndex ), m_FolderPicker->GetPath() ).ShowModal();
card.IsEnabled = (result != wxID_CANCEL);
}
RefreshSelections();
@ -629,11 +639,13 @@ void Panels::MemoryCardListPanel_Simple::OnMountCard(wxCommandEvent& evt)
{
evt.Skip();
const int slot = m_listview->GetFirstSelected();
if( wxNOT_FOUND == slot ) return;
const int selectedViewIndex = m_listview->GetFirstSelected();
if( wxNOT_FOUND == selectedViewIndex ) return;
McdSlotItem& card( GetCardForViewIndex(selectedViewIndex) );
m_Cards[slot].IsEnabled = !m_Cards[slot].IsEnabled;
m_listview->RefreshItem(slot);
card.IsEnabled = !card.IsEnabled;
m_listview->RefreshItem(selectedViewIndex);
UpdateUI();
}
@ -655,10 +667,10 @@ void Panels::MemoryCardListPanel_Simple::OnRelocateCard(wxCommandEvent& evt)
void Panels::MemoryCardListPanel_Simple::OnListDrag(wxListEvent& evt)
{
int selection = m_listview->GetFirstSelected();
int selectionViewIndex = m_listview->GetFirstSelected();
if( selection < 0 ) return;
McdDataObject my_data( selection );
if( selectionViewIndex < 0 ) return;
McdDataObject my_data( selectionViewIndex );
wxDropSource dragSource( m_listview );
dragSource.SetData( my_data );
@ -678,10 +690,10 @@ void Panels::MemoryCardListPanel_Simple::OnOpenItemContextMenu(wxListEvent& evt)
if( idx != wxNOT_FOUND )
{
const McdListItem& item( m_Cards[idx] );
const McdSlotItem& card( GetCardForViewIndex(idx) );
junk->Append( McdMenuId_Create, item.IsPresent ? _("Delete") : _("Create new...") );
junk->Append( McdMenuId_Mount, item.IsEnabled ? _("Disable") : _("Enable") );
junk->Append( McdMenuId_Create, card.IsPresent ? _("Delete") : _("Create new...") );
junk->Append( McdMenuId_Mount, card.IsEnabled ? _("Disable") : _("Enable") );
junk->Append( McdMenuId_Relocate, _("Relocate file...") );
junk->AppendSeparator();
@ -703,32 +715,34 @@ int Panels::MemoryCardListPanel_Simple::GetLength() const
return baselen;
}
McdListItem& Panels::MemoryCardListPanel_Simple::GetCard( int idx )
//Translates a list-view index (idx) to a memory card slot.
//This method effectively defines the arrangement of the card slots at the list view.
//The internal card slots array is fixed as sollows:
// slot 0: mcd1 (= MT1 slot 1)
// slot 1: mcd2 (= MT2 slot 1)
// slots 2,3,4: MT1 slots 2,3,4
// slots 5,6,7: MT2 slots 2,3,4
//
//however, the list-view doesn't show MT slots when this MT is disabled,
// so the view-index should "shift" to point at the real card slot.
//While we're at it, we can alternatively enforce any other arrangment of the view by
// using any other set of 'view-index-to-card-slot' translating that we'd like.
int Panels::MemoryCardListPanel_Simple::GetSlotIndexForViewIndex( int listViewIndex )
{
//calculate actual card slot (targetSlot) from list-view index (idx).
//card slots are fixed as sollows:
// slot 0: mcd1 (= MT1 slot 1)
// slot 1: mcd2 (= MT2 slot 1)
// slots 2,3,4: MT1 slots 2,3,4
// slots 5,6,7: MT2 slots 2,3,4
//
//however, the list-view doesn't show MT slots when this MT is disabled,
// so the view-index should "shift" to point at the real card slot.
int targetSlot=-1;
//this list-view arrangement is mostly kept aligned with the slots indexes, and only takes care
// of the case where MT1 is disabled (hence the MT2 slots "move backwards" 3 places on the view-index)
if (!m_MultitapEnabled[0] && idx>=2)
// of the case where MT1 is disabled (hence the MT2 slots 2,3,4 "move backwards" 3 places on the view-index)
if (!m_MultitapEnabled[0] && listViewIndex>=2)
{
//we got an MT2 slot.
assert(idx < 5);
targetSlot = idx+3;
assert(listViewIndex < 5);
targetSlot = listViewIndex+3;
}
else
{
targetSlot=idx;//identical view-index and card slot.
targetSlot=listViewIndex;//identical view-index and card slot.
}
@ -740,22 +754,29 @@ McdListItem& Panels::MemoryCardListPanel_Simple::GetCard( int idx )
if (m_MultitapEnabled[0]){
//MT1 enabled:
if (1<=idx && idx<=3){//MT1 slots 2/3/4 move one place backwards
targetSlot=idx+1;
}else if (idx==4){//mcd2 (=MT2 slot 1) moves 3 places forward
if (1<=listViewIndex && idx<=3){//MT1 slots 2/3/4 move one place backwards
targetSlot=listViewIndex+1;
}else if (listViewIndex==4){//mcd2 (=MT2 slot 1) moves 3 places forward
targetSlot=1;
} else {//mcd1 keeps it's pos as first, MT2 slots keep their pos at the end of the list.
targetSlot=idx;
targetSlot=listViewIndex;
}
} else {
//MT1 disabled: mcd1 and mcd2 stay put, MT2 slots 2,3,4 come next (move backwards 3 places)
if (2<=idx && idx<=4)
targetSlot=idx+3;
if (2<=listViewIndex && listViewIndex<=4)
targetSlot=listViewIndex+3;
else
targetSlot=idx;
targetSlot=listViewIndex;
}
*/
assert(targetSlot>=0);
return m_Cards[targetSlot];
return targetSlot;
}
McdSlotItem& Panels::MemoryCardListPanel_Simple::GetCardForViewIndex( int idx )
{
int slot = GetSlotIndexForViewIndex( idx );
return m_Cards[slot];
}

View File

@ -127,22 +127,16 @@ void MemoryCardListView_Simple::SetCardCount( int length )
wxString MemoryCardListView_Simple::OnGetItemText(long item, long column) const
{
if( !m_CardProvider ) return _parent::OnGetItemText(item, column);
const McdListItem& it( m_CardProvider->GetCard(item) );
const McdSlotItem& it( m_CardProvider->GetCardForViewIndex(item) );
switch( column )
{
// case McdColS_PortSlot: return pxsFmt( L"%u", item+1);
case McdColS_PortSlot: {
wxString desc=_("");
if (!it.IsMultitapSlot()){
return pxsFmt(L"Card-%u or Multitap-%u-Slot-1", it.GetMtapPort()+1, it.GetMtapPort()+1);
} else {
return pxsFmt(L" Multitap-%u-Slot-%u", it.GetMtapPort()+1, it.GetMtapSlot()+1);
}
wxString d2=pxsFmt(L"MT=%s, MTP=%u, MTS=%u", (it.IsMultitapSlot()?_("true"):_("false")), it.GetMtapPort(), (it.IsMultitapSlot()?it.GetMtapSlot():999));
return desc;
return pxsFmt( L"", item+1);
}
case McdColS_PortSlot:
if (!it.IsMultitapSlot())
return pxsFmt(L"Port-%u or Multitap-%u-Port-1", it.GetMtapPort()+1, it.GetMtapPort()+1);
return pxsFmt(L" Multitap-%u-Port-%u", it.GetMtapPort()+1, it.GetMtapSlot()+1);
case McdColS_Status: return it.IsPresent ? ( it.IsEnabled ? _("Enabled") : _("Disabled")) : _("Missing");
case McdColS_Size: return it.IsPresent ? pxsFmt( L"%u MB", it.SizeInMB ) : (wxString)_("N/A");
case McdColS_Formatted: return it.IsFormatted ? _("Yes") : _("No");
@ -187,7 +181,7 @@ wxListItemAttr* MemoryCardListView_Simple::OnGetItemAttr(long item) const
//m_targeted.SetBackgroundColour( wxColour(L"Yellow") );
if( !m_CardProvider ) return _parent::OnGetItemAttr(item);
const McdListItem& it( m_CardProvider->GetCard(item) );
const McdSlotItem& it( m_CardProvider->GetCardForViewIndex(item) );
m_ItemAttr = wxListItemAttr(); // Wipe it clean!

View File

@ -30,7 +30,7 @@ struct ListViewColumnInfo
// --------------------------------------------------------------------------------------
// McdListItem / IMcdList
// --------------------------------------------------------------------------------------
struct McdListItem
struct McdSlotItem
{
bool IsPresent;
bool IsEnabled;
@ -44,7 +44,7 @@ struct McdListItem
wxFileName Filename; // full pathname (optional)
McdListItem()
McdSlotItem()
{
//Port = -1;
Slot = -1;
@ -57,18 +57,19 @@ struct McdListItem
uint GetMtapPort() const;
uint GetMtapSlot() const;
bool operator==( const McdListItem& right ) const;
bool operator!=( const McdListItem& right ) const;
bool operator==( const McdSlotItem& right ) const;
bool operator!=( const McdSlotItem& right ) const;
};
typedef std::vector<McdListItem> McdList;
typedef std::vector<McdSlotItem> McdList;
class IMcdList
{
public:
virtual void RefreshMcds() const=0;
virtual int GetLength() const=0;
virtual McdListItem& GetCard( int idx )=0;
virtual McdSlotItem& GetCardForViewIndex( int idx )=0;
virtual int GetSlotIndexForViewIndex( int listViewIndex )=0;
virtual wxDirName GetMcdPath() const=0;
};
@ -182,7 +183,7 @@ namespace Panels
typedef BaseMcdListPanel _parent;
protected:
McdListItem m_Cards[8];
McdSlotItem m_Cards[8];
// Doubles as Create and Delete buttons
wxButton* m_button_Create;
@ -199,7 +200,8 @@ namespace Panels
// Interface Implementation for IMcdList
virtual int GetLength() const;
virtual McdListItem& GetCard( int idx );
virtual McdSlotItem& GetCardForViewIndex( int idx );
virtual int GetSlotIndexForViewIndex( int viewIndex );
protected:
void OnCreateCard(wxCommandEvent& evt);
@ -245,5 +247,5 @@ namespace Panels
};
//avih: is the first one used??
extern bool EnumerateMemoryCard( McdListItem& dest, const wxFileName& filename );
extern bool EnumerateMemoryCard( McdSlotItem& dest, const wxFileName& filename );
//extern bool EnumerateMemoryCard( SimpleMcdItem& dest, const wxFileName& filename );