MemcardManager no longer crashes when opening an
invalid file. Only opens .raw and .gcp files that have correct hdr.size and checksums. it is no longer possible to open the same memcard on each side Buttons are now only available when memcard is loaded. memcard is loaded into a maximum of 8 pages with 16 entries perpage. added fixchecksum to Slot B. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1265 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
441072d31e
commit
3fdfd6e234
|
@ -74,7 +74,8 @@ BEGIN_EVENT_TABLE(CMemcardManager, wxDialog)
|
||||||
EVT_CLOSE(CMemcardManager::OnClose)
|
EVT_CLOSE(CMemcardManager::OnClose)
|
||||||
EVT_BUTTON(ID_COPYTOLEFT,CMemcardManager::CopyDeleteClick)
|
EVT_BUTTON(ID_COPYTOLEFT,CMemcardManager::CopyDeleteClick)
|
||||||
EVT_BUTTON(ID_COPYTORIGHT,CMemcardManager::CopyDeleteClick)
|
EVT_BUTTON(ID_COPYTORIGHT,CMemcardManager::CopyDeleteClick)
|
||||||
EVT_BUTTON(ID_FIXCHECKSUM,CMemcardManager::CopyDeleteClick)
|
EVT_BUTTON(ID_FIXCHECKSUMLEFT,CMemcardManager::CopyDeleteClick)
|
||||||
|
EVT_BUTTON(ID_FIXCHECKSUMRIGHT,CMemcardManager::CopyDeleteClick)
|
||||||
EVT_BUTTON(ID_DELETELEFT,CMemcardManager::CopyDeleteClick)
|
EVT_BUTTON(ID_DELETELEFT,CMemcardManager::CopyDeleteClick)
|
||||||
EVT_BUTTON(ID_DELETERIGHT,CMemcardManager::CopyDeleteClick)
|
EVT_BUTTON(ID_DELETERIGHT,CMemcardManager::CopyDeleteClick)
|
||||||
EVT_BUTTON(ID_SAVEIMPORTRIGHT,CMemcardManager::CopyDeleteClick)
|
EVT_BUTTON(ID_SAVEIMPORTRIGHT,CMemcardManager::CopyDeleteClick)
|
||||||
|
@ -82,6 +83,10 @@ BEGIN_EVENT_TABLE(CMemcardManager, wxDialog)
|
||||||
EVT_BUTTON(ID_SAVEIMPORTLEFT,CMemcardManager::CopyDeleteClick)
|
EVT_BUTTON(ID_SAVEIMPORTLEFT,CMemcardManager::CopyDeleteClick)
|
||||||
EVT_BUTTON(ID_SAVEEXPORTLEFT,CMemcardManager::CopyDeleteClick)
|
EVT_BUTTON(ID_SAVEEXPORTLEFT,CMemcardManager::CopyDeleteClick)
|
||||||
EVT_BUTTON(ID_CONVERTTOGCI,CMemcardManager::CopyDeleteClick)
|
EVT_BUTTON(ID_CONVERTTOGCI,CMemcardManager::CopyDeleteClick)
|
||||||
|
EVT_BUTTON(ID_MEMCARD1PREVPAGE, CMemcardManager::OnPageChange)
|
||||||
|
EVT_BUTTON(ID_MEMCARD1NEXTPAGE, CMemcardManager::OnPageChange)
|
||||||
|
EVT_BUTTON(ID_MEMCARD2PREVPAGE, CMemcardManager::OnPageChange)
|
||||||
|
EVT_BUTTON(ID_MEMCARD2NEXTPAGE, CMemcardManager::OnPageChange)
|
||||||
EVT_FILEPICKER_CHANGED(ID_MEMCARD1PATH,CMemcardManager::OnPathChange)
|
EVT_FILEPICKER_CHANGED(ID_MEMCARD1PATH,CMemcardManager::OnPathChange)
|
||||||
EVT_FILEPICKER_CHANGED(ID_MEMCARD2PATH,CMemcardManager::OnPathChange)
|
EVT_FILEPICKER_CHANGED(ID_MEMCARD2PATH,CMemcardManager::OnPathChange)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
@ -110,29 +115,39 @@ CMemcardManager::~CMemcardManager()
|
||||||
|
|
||||||
void CMemcardManager::CreateGUIControls()
|
void CMemcardManager::CreateGUIControls()
|
||||||
{
|
{
|
||||||
|
t_StatusLeft = new wxStaticText(this, 0, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxEmptyString);
|
||||||
|
t_StatusRight = new wxStaticText(this, 0, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxEmptyString);
|
||||||
|
|
||||||
// buttons
|
// buttons
|
||||||
m_CopyToLeft = new wxButton(this, ID_COPYTOLEFT, wxT("<-Copy<-"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
m_CopyToLeft = new wxButton(this, ID_COPYTOLEFT, wxT("<-Copy<-"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
m_CopyToRight = new wxButton(this, ID_COPYTORIGHT, wxT("->Copy->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
m_CopyToRight = new wxButton(this, ID_COPYTORIGHT, wxT("->Copy->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
|
||||||
m_FixChecksum = new wxButton(this, ID_FIXCHECKSUM, wxT("<-Fix\nChecksum"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
m_FixChecksumLeft = new wxButton(this, ID_FIXCHECKSUMLEFT, wxT("<-Fix Checksum"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
m_FixChecksumRight = new wxButton(this, ID_FIXCHECKSUMRIGHT, wxT("Fix Checksum->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
|
||||||
m_SaveImportLeft = new wxButton(this, ID_SAVEIMPORTLEFT, wxT("<-Import GCI"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
m_SaveImportLeft = new wxButton(this, ID_SAVEIMPORTLEFT, wxT("<-Import GCI"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
m_SaveExportLeft = new wxButton(this, ID_SAVEEXPORTLEFT, wxT("<-Export GCI"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
|
||||||
m_SaveImportRight = new wxButton(this, ID_SAVEIMPORTRIGHT, wxT("Import GCI->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
m_SaveImportRight = new wxButton(this, ID_SAVEIMPORTRIGHT, wxT("Import GCI->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
|
||||||
|
m_SaveExportLeft = new wxButton(this, ID_SAVEEXPORTLEFT, wxT("<-Export GCI"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
m_SaveExportRight = new wxButton(this, ID_SAVEEXPORTRIGHT, wxT("Export GCI->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
m_SaveExportRight = new wxButton(this, ID_SAVEEXPORTRIGHT, wxT("Export GCI->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
//Added to test GCS and SAV import, until ImportFile is fixed
|
|
||||||
//rather than needing to import and then export
|
|
||||||
m_ConvertToGci = new wxButton(this, ID_CONVERTTOGCI, wxT("Convert to GCI"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
m_ConvertToGci = new wxButton(this, ID_CONVERTTOGCI, wxT("Convert to GCI"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
|
||||||
m_DeleteLeft = new wxButton(this, ID_DELETELEFT, wxT("<-Delete"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
m_DeleteLeft = new wxButton(this, ID_DELETELEFT, wxT("<-Delete"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
m_DeleteRight = new wxButton(this, ID_DELETERIGHT, wxT("Delete->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
m_DeleteRight = new wxButton(this, ID_DELETERIGHT, wxT("Delete->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
|
||||||
|
m_Memcard1PrevPage = new wxButton(this, ID_MEMCARD1PREVPAGE, wxT("Prev Page"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
m_Memcard2PrevPage = new wxButton(this, ID_MEMCARD2PREVPAGE, wxT("Prev Page"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
|
||||||
|
m_Memcard1NextPage = new wxButton(this, ID_MEMCARD1NEXTPAGE, wxT("Next Page"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
m_Memcard2NextPage = new wxButton(this, ID_MEMCARD2NEXTPAGE, wxT("Next Page"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
|
||||||
// Sizers that double as wxStaticBoxes
|
// Sizers that double as wxStaticBoxes
|
||||||
sMemcard1 = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Memory Card 1"));
|
sMemcard1 = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Memory Card 1"));
|
||||||
sMemcard2 = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Memory Card 2"));
|
sMemcard2 = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Memory Card 2"));
|
||||||
|
|
||||||
// Create the controls for both memcards
|
// Create the controls for both memcards
|
||||||
// Loading invalid .raw files still crash the app, but eh, needed this for testing
|
// Loading invalid .raw files should no longer crash the app
|
||||||
m_Memcard1Path = new wxFilePickerCtrl(this, ID_MEMCARD1PATH, wxEmptyString, wxT("Choose a memory card:"),
|
m_Memcard1Path = new wxFilePickerCtrl(this, ID_MEMCARD1PATH, wxEmptyString, wxT("Choose a memory card:"),
|
||||||
wxT("Raw memcards (*.raw)|*.raw"), wxDefaultPosition, wxDefaultSize, wxFLP_USE_TEXTCTRL|wxFLP_FILE_MUST_EXIST|wxFLP_OPEN);
|
wxT("Raw memcards (*.raw)|*.raw"), wxDefaultPosition, wxDefaultSize, wxFLP_USE_TEXTCTRL|wxFLP_FILE_MUST_EXIST|wxFLP_OPEN);
|
||||||
m_Memcard2Path = new wxFilePickerCtrl(this, ID_MEMCARD2PATH, wxEmptyString, wxT("Choose a memory card:"),
|
m_Memcard2Path = new wxFilePickerCtrl(this, ID_MEMCARD2PATH, wxEmptyString, wxT("Choose a memory card:"),
|
||||||
|
@ -153,7 +168,8 @@ void CMemcardManager::CreateGUIControls()
|
||||||
sButtons->Add(m_CopyToLeft, 0, wxEXPAND, 5);
|
sButtons->Add(m_CopyToLeft, 0, wxEXPAND, 5);
|
||||||
sButtons->Add(m_CopyToRight, 0, wxEXPAND, 5);
|
sButtons->Add(m_CopyToRight, 0, wxEXPAND, 5);
|
||||||
sButtons->AddStretchSpacer(1);
|
sButtons->AddStretchSpacer(1);
|
||||||
sButtons->Add(m_FixChecksum, 0, wxEXPAND, 5);
|
sButtons->Add(m_FixChecksumLeft, 0, wxEXPAND, 5);
|
||||||
|
sButtons->Add(m_FixChecksumRight, 0, wxEXPAND, 5);
|
||||||
sButtons->AddStretchSpacer(1);
|
sButtons->AddStretchSpacer(1);
|
||||||
sButtons->Add(m_SaveImportLeft, 0, wxEXPAND, 5);
|
sButtons->Add(m_SaveImportLeft, 0, wxEXPAND, 5);
|
||||||
sButtons->Add(m_SaveExportLeft, 0, wxEXPAND, 5);
|
sButtons->Add(m_SaveExportLeft, 0, wxEXPAND, 5);
|
||||||
|
@ -167,19 +183,47 @@ void CMemcardManager::CreateGUIControls()
|
||||||
sButtons->Add(m_DeleteRight, 0, wxEXPAND, 5);
|
sButtons->Add(m_DeleteRight, 0, wxEXPAND, 5);
|
||||||
sButtons->AddStretchSpacer(1);
|
sButtons->AddStretchSpacer(1);
|
||||||
|
|
||||||
|
sPagesLeft = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
sPagesRight = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
|
sPagesLeft->Add(m_Memcard1PrevPage, 0, wxEXPAND|wxALL, 1);
|
||||||
|
sPagesLeft->Add(t_StatusLeft,0, wxEXPAND|wxALL, 5);
|
||||||
|
sPagesLeft->Add(0, 0, 1, wxEXPAND|wxALL, 0);
|
||||||
|
sPagesLeft->Add(m_Memcard1NextPage, 0, wxEXPAND|wxALL, 1);
|
||||||
|
sPagesRight->Add(m_Memcard2PrevPage, 0, wxEXPAND|wxALL, 1);
|
||||||
|
sPagesRight->Add(t_StatusRight, 0, wxEXPAND|wxALL, 5);
|
||||||
|
sPagesRight->Add(0, 0, 1, wxEXPAND|wxALL, 0);
|
||||||
|
sPagesRight->Add(m_Memcard2NextPage, 0, wxEXPAND|wxALL, 1);
|
||||||
|
|
||||||
sMemcard1->Add(m_Memcard1Path, 0, wxEXPAND|wxALL, 5);
|
sMemcard1->Add(m_Memcard1Path, 0, wxEXPAND|wxALL, 5);
|
||||||
sMemcard1->Add(m_MemcardList[0], 1, wxEXPAND|wxALL, 5);
|
sMemcard1->Add(m_MemcardList[0], 1, wxEXPAND|wxALL, 5);
|
||||||
|
sMemcard1->Add(sPagesLeft, 0, wxEXPAND|wxALL, 1);
|
||||||
sMemcard2->Add(m_Memcard2Path, 0, wxEXPAND|wxALL, 5);
|
sMemcard2->Add(m_Memcard2Path, 0, wxEXPAND|wxALL, 5);
|
||||||
sMemcard2->Add(m_MemcardList[1], 1, wxEXPAND|wxALL, 5);
|
sMemcard2->Add(m_MemcardList[1], 1, wxEXPAND|wxALL, 5);
|
||||||
|
sMemcard2->Add(sPagesRight, 0, wxEXPAND|wxALL, 1);
|
||||||
|
|
||||||
sMain = new wxBoxSizer(wxHORIZONTAL);
|
sMain = new wxBoxSizer(wxHORIZONTAL);
|
||||||
sMain->Add(sMemcard1, 1, wxEXPAND|wxALL, 5);
|
sMain->Add(sMemcard1, 1, wxEXPAND|wxALL, 5);
|
||||||
sMain->Add(sButtons, 0, wxEXPAND, 0);
|
sMain->Add(sButtons, 0, wxEXPAND, 0);
|
||||||
sMain->Add(sMemcard2, 1, wxEXPAND|wxALL, 5);
|
sMain->Add(sMemcard2, 1, wxEXPAND|wxALL, 5);
|
||||||
|
|
||||||
this->SetSizer(sMain);
|
this->SetSizer(sMain);
|
||||||
sMain->SetSizeHints(this);
|
sMain->SetSizeHints(this);
|
||||||
Fit();
|
Fit();
|
||||||
|
m_Memcard1PrevPage->Disable();
|
||||||
|
m_Memcard1NextPage->Disable();
|
||||||
|
m_Memcard2PrevPage->Disable();
|
||||||
|
m_Memcard2NextPage->Disable();
|
||||||
|
m_CopyToLeft->Disable();
|
||||||
|
m_CopyToRight->Disable();
|
||||||
|
m_FixChecksumLeft->Disable();
|
||||||
|
m_FixChecksumRight->Disable();
|
||||||
|
m_SaveImportLeft->Disable();
|
||||||
|
m_SaveExportLeft->Disable();
|
||||||
|
m_SaveImportRight->Disable();
|
||||||
|
m_SaveExportRight->Disable();
|
||||||
|
m_DeleteLeft->Disable();
|
||||||
|
m_DeleteRight->Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMemcardManager::OnClose(wxCloseEvent& WXUNUSED (event))
|
void CMemcardManager::OnClose(wxCloseEvent& WXUNUSED (event))
|
||||||
|
@ -192,10 +236,100 @@ void CMemcardManager::OnPathChange(wxFileDirPickerEvent& event)
|
||||||
switch (event.GetId())
|
switch (event.GetId())
|
||||||
{
|
{
|
||||||
case ID_MEMCARD1PATH:
|
case ID_MEMCARD1PATH:
|
||||||
ReloadMemcard(event.GetPath().mb_str(), 0);
|
page1 = 0;
|
||||||
|
if (m_Memcard1PrevPage->IsEnabled()) m_Memcard1PrevPage->Disable();
|
||||||
|
if (!strcasecmp(m_Memcard1Path->GetPath().mb_str(),m_Memcard2Path->GetPath().mb_str()))
|
||||||
|
{
|
||||||
|
wxMessageBox(wxT("Memcard already opened"), wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
m_Memcard1Path->SetPath(wxEmptyString);
|
||||||
|
m_MemcardList[0]->ClearAll();
|
||||||
|
t_StatusLeft->SetLabel(wxEmptyString);
|
||||||
|
}
|
||||||
|
else if (ReloadMemcard(event.GetPath().mb_str(), 0, page1))
|
||||||
|
{
|
||||||
|
m_FixChecksumLeft->Enable();
|
||||||
|
m_SaveImportLeft->Enable();
|
||||||
|
m_SaveExportLeft->Enable();
|
||||||
|
m_DeleteLeft->Enable();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_Memcard1Path->SetPath(wxEmptyString);
|
||||||
|
m_MemcardList[0]->ClearAll();
|
||||||
|
t_StatusLeft->SetLabel(wxEmptyString);
|
||||||
|
m_FixChecksumLeft->Disable();
|
||||||
|
m_SaveImportLeft->Disable();
|
||||||
|
m_SaveExportLeft->Disable();
|
||||||
|
m_DeleteLeft->Disable();
|
||||||
|
m_Memcard1PrevPage->Disable();
|
||||||
|
m_Memcard1NextPage->Disable();
|
||||||
break;
|
break;
|
||||||
case ID_MEMCARD2PATH:
|
case ID_MEMCARD2PATH:
|
||||||
ReloadMemcard(event.GetPath().mb_str(), 1);
|
page2 = 0;
|
||||||
|
if (m_Memcard2PrevPage->IsEnabled()) m_Memcard2PrevPage->Disable();
|
||||||
|
if (!strcasecmp(m_Memcard1Path->GetPath().mb_str(),m_Memcard2Path->GetPath().mb_str()))
|
||||||
|
{
|
||||||
|
wxMessageBox(wxT("Memcard already opened"), wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
}
|
||||||
|
else if (ReloadMemcard(event.GetPath().mb_str(), 1, page2))
|
||||||
|
{
|
||||||
|
m_FixChecksumRight->Enable();
|
||||||
|
m_SaveImportRight->Enable();
|
||||||
|
m_SaveExportRight->Enable();
|
||||||
|
m_DeleteRight->Enable();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_Memcard2Path->SetPath(wxEmptyString);
|
||||||
|
m_MemcardList[1]->ClearAll();
|
||||||
|
t_StatusRight->SetLabel(wxEmptyString);
|
||||||
|
m_FixChecksumRight->Disable();
|
||||||
|
m_SaveImportRight->Disable();
|
||||||
|
m_SaveExportRight->Disable();
|
||||||
|
m_DeleteRight->Disable();
|
||||||
|
m_Memcard2PrevPage->Disable();
|
||||||
|
m_Memcard2NextPage->Disable();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (m_DeleteRight->IsEnabled() && m_DeleteLeft->IsEnabled())
|
||||||
|
{
|
||||||
|
m_CopyToLeft->Enable();
|
||||||
|
m_CopyToRight->Enable();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_CopyToLeft->Disable();
|
||||||
|
m_CopyToRight->Disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemcardManager::OnPageChange(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
switch (event.GetId())
|
||||||
|
{
|
||||||
|
case ID_MEMCARD1NEXTPAGE:
|
||||||
|
if (!m_Memcard1PrevPage->IsEnabled()) m_Memcard1PrevPage->Enable();
|
||||||
|
if (!m_Memcard1NextPage->IsEnabled()) m_Memcard1NextPage->Enable();
|
||||||
|
page1++;
|
||||||
|
if (page1 == 7) m_Memcard1NextPage->Disable();
|
||||||
|
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0, page1);
|
||||||
|
break;
|
||||||
|
case ID_MEMCARD2NEXTPAGE:
|
||||||
|
if (!m_Memcard2PrevPage->IsEnabled()) m_Memcard2PrevPage->Enable();
|
||||||
|
if (!m_Memcard2NextPage->IsEnabled()) m_Memcard2NextPage->Enable();
|
||||||
|
page2++;
|
||||||
|
if (page2 == 7) m_Memcard2NextPage->Disable();
|
||||||
|
ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1, page2);
|
||||||
|
break;
|
||||||
|
case ID_MEMCARD1PREVPAGE:
|
||||||
|
if (!m_Memcard1NextPage->IsEnabled()) m_Memcard1NextPage->Enable();
|
||||||
|
page1--;
|
||||||
|
if (page1 == 0) m_Memcard1PrevPage->Disable();
|
||||||
|
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0, page1);
|
||||||
|
break;
|
||||||
|
case ID_MEMCARD2PREVPAGE:
|
||||||
|
if (!m_Memcard2NextPage->IsEnabled()) m_Memcard2NextPage->Enable();
|
||||||
|
page2--;
|
||||||
|
if (page2 == 0) m_Memcard2PrevPage->Disable();
|
||||||
|
ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1, page2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,7 +341,6 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
||||||
int slot = 1;
|
int slot = 1;
|
||||||
int index2 = index1;
|
int index2 = index1;
|
||||||
std::string fileName2("");
|
std::string fileName2("");
|
||||||
int freeBlocks = 0;
|
|
||||||
wxString blocksOpen;
|
wxString blocksOpen;
|
||||||
|
|
||||||
switch (event.GetId())
|
switch (event.GetId())
|
||||||
|
@ -225,11 +358,15 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
memoryCard[0]->Save();
|
memoryCard[0]->Save();
|
||||||
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
|
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxMessageBox(wxT("You have not selected a save to copy"), wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ID_COPYTORIGHT:
|
case ID_COPYTORIGHT:
|
||||||
if ((index0 != -1) && (memoryCard[1] != NULL))
|
if ((index0 != -1) && (memoryCard[1] != NULL))
|
||||||
|
@ -246,19 +383,29 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
memoryCard[1]->Save();
|
memoryCard[1]->Save();
|
||||||
ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1);
|
ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxMessageBox(wxT("You have not selected a save to copy"), wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ID_FIXCHECKSUM:
|
case ID_FIXCHECKSUMLEFT:
|
||||||
if (memoryCard[0] != NULL)
|
slot = 0;
|
||||||
|
case ID_FIXCHECKSUMRIGHT:
|
||||||
|
if (memoryCard[slot] != NULL)
|
||||||
{
|
{
|
||||||
// Fix checksums and save the changes
|
// Fix checksums and save the changes
|
||||||
memoryCard[0]->FixChecksums() ? wxMessageBox(wxT("The checksum was successfully fixed"), wxT("Success"), wxOK)
|
memoryCard[slot]->FixChecksums() ? wxMessageBox(wxT("The checksum was successfully fixed"), wxT("Success"), wxOK)
|
||||||
: wxMessageBox(wxT("The checksum could not be successfully fixed"), wxT("Error"), wxOK|wxICON_ERROR);
|
: wxMessageBox(wxT("The checksum could not be successfully fixed"), wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
memoryCard[0]->Save();
|
memoryCard[slot]->Save();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxMessageBox(wxT("memorycard is not loaded"), wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ID_CONVERTTOGCI:
|
case ID_CONVERTTOGCI:
|
||||||
fileName2 = "convert";
|
fileName2 = "convert";
|
||||||
|
@ -268,7 +415,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
||||||
case ID_SAVEIMPORTRIGHT:
|
case ID_SAVEIMPORTRIGHT:
|
||||||
if (memoryCard[slot] != NULL || !fileName2.empty())
|
if (memoryCard[slot] != NULL || !fileName2.empty())
|
||||||
{
|
{
|
||||||
wxString temp = wxFileSelector(_T("Select the GCI file to import"),
|
wxString temp = wxFileSelector(_T("Select a save file to import"),
|
||||||
wxEmptyString, wxEmptyString, wxEmptyString,wxString::Format
|
wxEmptyString, wxEmptyString, wxEmptyString,wxString::Format
|
||||||
(
|
(
|
||||||
_T("Gamecube save files(*.gci,*.gcs,*.sav)|*.gci;*.gcs;*.sav|"
|
_T("Gamecube save files(*.gci,*.gcs,*.sav)|*.gci;*.gcs;*.sav|"
|
||||||
|
@ -290,6 +437,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
||||||
wxFileSelectorDefaultWildcardStr
|
wxFileSelectorDefaultWildcardStr
|
||||||
),
|
),
|
||||||
wxFD_OVERWRITE_PROMPT|wxFD_SAVE);
|
wxFD_OVERWRITE_PROMPT|wxFD_SAVE);
|
||||||
|
if (temp2.empty()) break;
|
||||||
fileName2 = temp2.mb_str();
|
fileName2 = temp2.mb_str();
|
||||||
}
|
}
|
||||||
if (temp.length() > 0)
|
if (temp.length() > 0)
|
||||||
|
@ -320,8 +468,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
||||||
wxT("Success"), wxOK);
|
wxT("Success"), wxOK);
|
||||||
break;
|
break;
|
||||||
case OUTOFBLOCKS:
|
case OUTOFBLOCKS:
|
||||||
freeBlocks = BE16(memoryCard[slot]->bat.FreeBlocks);
|
blocksOpen.Printf(wxT("Only %d blocks available"), memoryCard[slot]->GetFreeBlocks());
|
||||||
blocksOpen.Printf(wxT("Only %d blocks available"), freeBlocks);
|
|
||||||
wxMessageBox(blocksOpen, wxT("Error"), wxOK|wxICON_ERROR);
|
wxMessageBox(blocksOpen, wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
break;
|
break;
|
||||||
case OUTOFDIRENTRIES:
|
case OUTOFDIRENTRIES:
|
||||||
|
@ -342,12 +489,16 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
memoryCard[slot]->Save();
|
memoryCard[slot]->Save();
|
||||||
slot == 1 ? ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1)
|
slot == 1 ? ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1, 0)
|
||||||
: ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
|
: ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxMessageBox(wxT("Memory card is not loaded"), wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ID_SAVEEXPORTLEFT:
|
case ID_SAVEEXPORTLEFT:
|
||||||
slot=0;
|
slot=0;
|
||||||
|
@ -387,6 +538,10 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxMessageBox(wxT("You have not selected a save to export"), wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ID_DELETELEFT:
|
case ID_DELETELEFT:
|
||||||
slot=0;
|
slot=0;
|
||||||
|
@ -406,28 +561,41 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
memoryCard[slot]->Save();
|
memoryCard[slot]->Save();
|
||||||
slot == 1 ? ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1)
|
slot == 1 ? ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1, 0)
|
||||||
: ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
|
: ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxMessageBox(wxT("You have not selected a save to delete"), wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMemcardManager::ReloadMemcard(const char *fileName, int card)
|
bool CMemcardManager::ReloadMemcard(const char *fileName, int card, int page)
|
||||||
{
|
{
|
||||||
|
wxString wxBlock;
|
||||||
|
wxString wxFirstBlock;
|
||||||
|
wxString wxLabel;
|
||||||
|
int j;
|
||||||
|
|
||||||
if (memoryCard[card]) delete memoryCard[card];
|
if (memoryCard[card]) delete memoryCard[card];
|
||||||
|
|
||||||
// TODO: add error checking and animate icons
|
// TODO: add error checking and animate icons
|
||||||
memoryCard[card] = new GCMemcard(fileName);
|
memoryCard[card] = new GCMemcard(fileName);
|
||||||
|
|
||||||
|
if (ReadError(memoryCard[card])) return false;
|
||||||
|
|
||||||
m_MemcardList[card]->Hide();
|
m_MemcardList[card]->Hide();
|
||||||
m_MemcardList[card]->ClearAll();
|
m_MemcardList[card]->ClearAll();
|
||||||
m_MemcardList[card]->InsertColumn(COLUMN_BANNER, _T("Banner"));
|
m_MemcardList[card]->InsertColumn(COLUMN_BANNER, _T("Banner"));
|
||||||
m_MemcardList[card]->InsertColumn(COLUMN_TITLE, _T("Title"));
|
m_MemcardList[card]->InsertColumn(COLUMN_TITLE, _T("Title"));
|
||||||
m_MemcardList[card]->InsertColumn(COLUMN_COMMENT, _T("Comment"));
|
m_MemcardList[card]->InsertColumn(COLUMN_COMMENT, _T("Comment"));
|
||||||
m_MemcardList[card]->InsertColumn(COLUMN_ICON, _T("Icon"));
|
m_MemcardList[card]->InsertColumn(COLUMN_ICON, _T("Icon"));
|
||||||
|
m_MemcardList[card]->InsertColumn(COLUMN_BLOCKS, _T("Blocks"));
|
||||||
|
m_MemcardList[card]->InsertColumn(COLUMN_FIRSTBLOCK, _T("First Block"));
|
||||||
|
|
||||||
wxImageList *list = m_MemcardList[card]->GetImageList(wxIMAGE_LIST_SMALL);
|
wxImageList *list = m_MemcardList[card]->GetImageList(wxIMAGE_LIST_SMALL);
|
||||||
list->RemoveAll();
|
list->RemoveAll();
|
||||||
|
@ -435,7 +603,7 @@ void CMemcardManager::ReloadMemcard(const char *fileName, int card)
|
||||||
int nFiles = memoryCard[card]->GetNumFiles();
|
int nFiles = memoryCard[card]->GetNumFiles();
|
||||||
|
|
||||||
int *images = new int[nFiles*2];
|
int *images = new int[nFiles*2];
|
||||||
for (int i=0;i<nFiles;i++)
|
for (int i = 0;i < nFiles;i++)
|
||||||
{
|
{
|
||||||
static u32 pxdata[96*32];
|
static u32 pxdata[96*32];
|
||||||
static u8 animDelay[8];
|
static u8 animDelay[8];
|
||||||
|
@ -483,27 +651,43 @@ void CMemcardManager::ReloadMemcard(const char *fileName, int card)
|
||||||
images[i*2+1] = list->Add(icon);
|
images[i*2+1] = list->Add(icon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (j = page * 16;(j < nFiles) && (j < (page + 1)* 16);j++)
|
||||||
for (int i=0;i<nFiles;i++)
|
|
||||||
{
|
{
|
||||||
char title[32];
|
char title[32];
|
||||||
char comment[32];
|
char comment[32];
|
||||||
|
u16 blocks;
|
||||||
|
u16 firstblock;
|
||||||
|
|
||||||
if (!memoryCard[card]->GetComment1(i,title)) title[0]=0;
|
if (!memoryCard[card]->GetComment1(j, title)) title[0]=0;
|
||||||
if (!memoryCard[card]->GetComment2(i,comment)) comment[0]=0;
|
if (!memoryCard[card]->GetComment2(j, comment)) comment[0]=0;
|
||||||
int index = m_MemcardList[card]->InsertItem(i, wxT("row"));
|
int index = m_MemcardList[card]->InsertItem(j, wxT("row"));
|
||||||
m_MemcardList[card]->SetItem(index, COLUMN_BANNER, wxEmptyString);
|
m_MemcardList[card]->SetItem(index, COLUMN_BANNER, wxEmptyString);
|
||||||
m_MemcardList[card]->SetItem(index, COLUMN_TITLE, wxString::FromAscii(title));
|
m_MemcardList[card]->SetItem(index, COLUMN_TITLE, wxString::FromAscii(title));
|
||||||
m_MemcardList[card]->SetItem(index, COLUMN_COMMENT, wxString::FromAscii(comment));
|
m_MemcardList[card]->SetItem(index, COLUMN_COMMENT, wxString::FromAscii(comment));
|
||||||
|
if (!memoryCard[card]->GetNumBlocks(j, &blocks)) blocks = 0;
|
||||||
|
wxBlock.Printf("%10d", blocks);
|
||||||
|
if (!memoryCard[card]->GetFirstBlock(j,&firstblock)) firstblock = 0;
|
||||||
|
wxFirstBlock.Printf("%10d", firstblock-4);
|
||||||
|
m_MemcardList[card]->SetItem(index,COLUMN_BLOCKS, wxBlock);
|
||||||
|
m_MemcardList[card]->SetItem(index,COLUMN_FIRSTBLOCK, wxFirstBlock);
|
||||||
m_MemcardList[card]->SetItem(index, COLUMN_ICON, wxEmptyString);
|
m_MemcardList[card]->SetItem(index, COLUMN_ICON, wxEmptyString);
|
||||||
|
|
||||||
if (images[i]>=0)
|
if (images[j] >= 0)
|
||||||
{
|
{
|
||||||
m_MemcardList[card]->SetItemImage(index, images[i*2]);
|
m_MemcardList[card]->SetItemImage(index, images[j*2]);
|
||||||
m_MemcardList[card]->SetItemColumnImage(index, COLUMN_ICON, images[i*2+1]);
|
m_MemcardList[card]->SetItemColumnImage(index, COLUMN_ICON, images[j*2+1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (j == nFiles)
|
||||||
|
{
|
||||||
|
card ? m_Memcard2NextPage->Disable() : m_Memcard1NextPage->Disable();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
card ? m_Memcard2NextPage->Enable() : m_Memcard1NextPage->Enable();
|
||||||
|
}
|
||||||
|
|
||||||
delete[] images;
|
delete[] images;
|
||||||
// Automatic column width and then show the list
|
// Automatic column width and then show the list
|
||||||
for (int i = 0; i < m_MemcardList[card]->GetColumnCount(); i++)
|
for (int i = 0; i < m_MemcardList[card]->GetColumnCount(); i++)
|
||||||
|
@ -511,4 +695,43 @@ void CMemcardManager::ReloadMemcard(const char *fileName, int card)
|
||||||
m_MemcardList[card]->SetColumnWidth(i, wxLIST_AUTOSIZE);
|
m_MemcardList[card]->SetColumnWidth(i, wxLIST_AUTOSIZE);
|
||||||
}
|
}
|
||||||
m_MemcardList[card]->Show();
|
m_MemcardList[card]->Show();
|
||||||
|
wxLabel.Printf("%d Free Blocks; %d Free Dir Entries",
|
||||||
|
memoryCard[card]->GetFreeBlocks(), 127 - nFiles);
|
||||||
|
card ? t_StatusRight->SetLabel(wxLabel) : t_StatusLeft->SetLabel(wxLabel);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMemcardManager::ReadError(GCMemcard *memcard)
|
||||||
|
{
|
||||||
|
if (!memcard->fail[0]) return false;
|
||||||
|
wxString wxBlock;
|
||||||
|
if (memcard->fail[HDR_READ_ERROR]) wxMessageBox(wxT("Failed to read header correctly\n(0x0000-0x1FFF)"),
|
||||||
|
wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
if (memcard->fail[DIR_READ_ERROR]) wxMessageBox(wxT("Failed to read directory correctly\n(0x2000-0x3FFF)"),
|
||||||
|
wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
if (memcard->fail[DIR_BAK_READ_ERROR]) wxMessageBox(wxT("Failed to read directory backup correctly\n(0x4000-0x5FFF)"),
|
||||||
|
wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
if (memcard->fail[BAT_READ_ERROR]) wxMessageBox(wxT("Failed to read block allocation table correctly\n(0x6000-0x7FFF)"),
|
||||||
|
wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
if (memcard->fail[BAT_BAK_READ_ERROR]) wxMessageBox(wxT("Failed to read block allocation table backup correctly\n(0x8000-0x9FFF)"),
|
||||||
|
wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
if (memcard->fail[HDR_CSUM_FAIL]) wxMessageBox(wxT("Header checksum failed"),
|
||||||
|
wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
if (memcard->fail[DIR_CSUM_FAIL])
|
||||||
|
{
|
||||||
|
wxMessageBox(wxT("Directory checksum failed"),
|
||||||
|
wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
wxMessageBox(wxT("Directory backup checksum failed"),
|
||||||
|
wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
}
|
||||||
|
if (memcard->fail[BAT_CSUM_FAIL]) wxMessageBox(wxT("Block Allocation Table checksum failed"),
|
||||||
|
wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
if (memcard->fail[DATA_READ_FAIL]) wxMessageBox(wxT("Failed to read save data\n(0xA000-)\nMemcard may be truncated"),
|
||||||
|
wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
if (memcard->fail[HDR_SIZE_FFFF]) wxMessageBox(wxT("Memcard failed to load\n Card size is invalid"),
|
||||||
|
wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
if (memcard->fail[NOTRAWORGCP]) wxMessageBox(wxT("File does not have a valid extension (.raw/.gcp)"),
|
||||||
|
wxT("Error"), wxOK|wxICON_ERROR);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include <wx/imaglist.h>
|
#include <wx/imaglist.h>
|
||||||
|
|
||||||
#include "MemoryCards/GCMemcard.h"
|
#include "MemoryCards/GCMemcard.h"
|
||||||
#define BE16(x) ((u16((x)[0])<<8) | u16((x)[1]))
|
|
||||||
#undef MEMCARD_MANAGER_STYLE
|
#undef MEMCARD_MANAGER_STYLE
|
||||||
#define MEMCARD_MANAGER_STYLE wxCAPTION | wxSYSTEM_MENU | wxDIALOG_NO_PARENT | wxCLOSE_BOX | wxRESIZE_BORDER | wxMAXIMIZE_BOX
|
#define MEMCARD_MANAGER_STYLE wxCAPTION | wxSYSTEM_MENU | wxDIALOG_NO_PARENT | wxCLOSE_BOX | wxRESIZE_BORDER | wxMAXIMIZE_BOX
|
||||||
|
|
||||||
|
@ -42,10 +41,18 @@ class CMemcardManager
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE();
|
DECLARE_EVENT_TABLE();
|
||||||
|
|
||||||
|
int page1,
|
||||||
|
page2;
|
||||||
|
|
||||||
wxBoxSizer *sMain;
|
wxBoxSizer *sMain;
|
||||||
|
wxBoxSizer *sPagesLeft;
|
||||||
|
wxBoxSizer *sPagesRight;
|
||||||
|
wxStaticText *t_StatusLeft;
|
||||||
|
wxStaticText *t_StatusRight;
|
||||||
wxButton *m_CopyToLeft;
|
wxButton *m_CopyToLeft;
|
||||||
wxButton *m_CopyToRight;
|
wxButton *m_CopyToRight;
|
||||||
wxButton *m_FixChecksum;
|
wxButton *m_FixChecksumLeft;
|
||||||
|
wxButton *m_FixChecksumRight;
|
||||||
wxButton *m_SaveImportLeft;
|
wxButton *m_SaveImportLeft;
|
||||||
wxButton *m_SaveExportLeft;
|
wxButton *m_SaveExportLeft;
|
||||||
wxButton *m_SaveImportRight;
|
wxButton *m_SaveImportRight;
|
||||||
|
@ -53,6 +60,10 @@ class CMemcardManager
|
||||||
wxButton *m_ConvertToGci;
|
wxButton *m_ConvertToGci;
|
||||||
wxButton *m_DeleteLeft;
|
wxButton *m_DeleteLeft;
|
||||||
wxButton *m_DeleteRight;
|
wxButton *m_DeleteRight;
|
||||||
|
wxButton *m_Memcard1PrevPage;
|
||||||
|
wxButton *m_Memcard1NextPage;
|
||||||
|
wxButton *m_Memcard2PrevPage;
|
||||||
|
wxButton *m_Memcard2NextPage;
|
||||||
wxStaticBoxSizer *sMemcard1;
|
wxStaticBoxSizer *sMemcard1;
|
||||||
wxStaticBoxSizer *sMemcard2;
|
wxStaticBoxSizer *sMemcard2;
|
||||||
wxFilePickerCtrl *m_Memcard1Path;
|
wxFilePickerCtrl *m_Memcard1Path;
|
||||||
|
@ -64,11 +75,16 @@ class CMemcardManager
|
||||||
{
|
{
|
||||||
ID_COPYTORIGHT = 1000,
|
ID_COPYTORIGHT = 1000,
|
||||||
ID_COPYTOLEFT,
|
ID_COPYTOLEFT,
|
||||||
ID_FIXCHECKSUM,
|
ID_FIXCHECKSUMRIGHT,
|
||||||
|
ID_FIXCHECKSUMLEFT,
|
||||||
ID_DELETERIGHT,
|
ID_DELETERIGHT,
|
||||||
ID_DELETELEFT,
|
ID_DELETELEFT,
|
||||||
ID_MEMCARD1PATH,
|
ID_MEMCARD1PATH,
|
||||||
ID_MEMCARD2PATH,
|
ID_MEMCARD2PATH,
|
||||||
|
ID_MEMCARD1NEXTPAGE,
|
||||||
|
ID_MEMCARD1PREVPAGE,
|
||||||
|
ID_MEMCARD2NEXTPAGE,
|
||||||
|
ID_MEMCARD2PREVPAGE,
|
||||||
ID_SAVEEXPORTRIGHT,
|
ID_SAVEEXPORTRIGHT,
|
||||||
ID_SAVEEXPORTLEFT,
|
ID_SAVEEXPORTLEFT,
|
||||||
ID_SAVEIMPORTRIGHT,
|
ID_SAVEIMPORTRIGHT,
|
||||||
|
@ -85,6 +101,8 @@ class CMemcardManager
|
||||||
COLUMN_TITLE,
|
COLUMN_TITLE,
|
||||||
COLUMN_COMMENT,
|
COLUMN_COMMENT,
|
||||||
COLUMN_ICON,
|
COLUMN_ICON,
|
||||||
|
COLUMN_BLOCKS,
|
||||||
|
COLUMN_FIRSTBLOCK,
|
||||||
NUMBER_OF_COLUMN
|
NUMBER_OF_COLUMN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,9 +111,10 @@ class CMemcardManager
|
||||||
void CreateGUIControls();
|
void CreateGUIControls();
|
||||||
void OnClose(wxCloseEvent& event);
|
void OnClose(wxCloseEvent& event);
|
||||||
void CopyDeleteClick(wxCommandEvent& event);
|
void CopyDeleteClick(wxCommandEvent& event);
|
||||||
void ReloadMemcard(const char *fileName, int card);
|
bool ReloadMemcard(const char *fileName, int card, int page);
|
||||||
|
void OnPageChange(wxCommandEvent& event);
|
||||||
void OnPathChange(wxFileDirPickerEvent& event);
|
void OnPathChange(wxFileDirPickerEvent& event);
|
||||||
void OnTimer(wxTimerEvent& event);
|
bool ReadError(GCMemcard *memcard);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
|
|
||||||
// i think there is support for this stuff in the common lib... if not there should be support
|
// i think there is support for this stuff in the common lib... if not there should be support
|
||||||
// and to get a file exentions there is a function called SplitPath()
|
|
||||||
#define BE16(x) ((u16((x)[0])<<8) | u16((x)[1]))
|
#define BE16(x) ((u16((x)[0])<<8) | u16((x)[1]))
|
||||||
#define BE32(x) ((u32((x)[0])<<24) | (u32((x)[1])<<16) | (u32((x)[2])<<8) | u32((x)[3]))
|
#define BE32(x) ((u32((x)[0])<<24) | (u32((x)[1])<<16) | (u32((x)[2])<<8) | u32((x)[3]))
|
||||||
#define ArrayByteSwap(a) (ByteSwap(a, a+sizeof(u8)));
|
#define ArrayByteSwap(a) (ByteSwap(a, a+sizeof(u8)));
|
||||||
|
@ -54,24 +53,30 @@ u32 __inline bswap32(u32 s)
|
||||||
|
|
||||||
void GCMemcard::calc_checksumsBE(u16 *buf, u32 num, u16 *c1, u16 *c2)
|
void GCMemcard::calc_checksumsBE(u16 *buf, u32 num, u16 *c1, u16 *c2)
|
||||||
{
|
{
|
||||||
*c1 = 0;*c2 = 0;
|
*c1 = 0;*c2 = 0;
|
||||||
for (u32 i = 0; i < num; ++i)
|
for (u32 i = 0; i < num; ++i)
|
||||||
{
|
{
|
||||||
//weird warnings here
|
//weird warnings here
|
||||||
*c1 += bswap16(buf[i]);
|
*c1 += bswap16(buf[i]);
|
||||||
*c2 += bswap16((u16)(buf[i] ^ 0xffff));
|
*c2 += bswap16((u16)(buf[i] ^ 0xffff));
|
||||||
}
|
}
|
||||||
if (*c1 == 0xffff)
|
if (*c1 == 0xffff)
|
||||||
{
|
{
|
||||||
*c1 = 0;
|
*c1 = 0;
|
||||||
}
|
}
|
||||||
if (*c2 == 0xffff)
|
if (*c2 == 0xffff)
|
||||||
{
|
{
|
||||||
*c2 = 0;
|
*c2 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GCMemcard::GetNumFiles()
|
u16 GCMemcard::GetFreeBlocks(void)
|
||||||
|
{
|
||||||
|
if (!mcdFile) return 0;
|
||||||
|
return BE16(bat.FreeBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GCMemcard::GetNumFiles()
|
||||||
{
|
{
|
||||||
if (!mcdFile) return 0;
|
if (!mcdFile) return 0;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
@ -83,7 +88,7 @@ u32 GCMemcard::GetNumFiles()
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GCMemcard::titlePresent(DEntry d)
|
bool GCMemcard::TitlePresent(DEntry d)
|
||||||
{
|
{
|
||||||
//TODO: Clean up this function
|
//TODO: Clean up this function
|
||||||
bool equal = false;
|
bool equal = false;
|
||||||
|
@ -114,6 +119,20 @@ bool GCMemcard::titlePresent(DEntry d)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GCMemcard::GetNumBlocks(u32 index, u16* buffer)
|
||||||
|
{
|
||||||
|
if (!mcdFile) return false;
|
||||||
|
*buffer = BE16(dir.Dir[index].BlockCount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GCMemcard::GetFirstBlock(u32 index, u16* buffer)
|
||||||
|
{
|
||||||
|
if (!mcdFile) return false;
|
||||||
|
*buffer = BE16(dir.Dir[index].FirstBlock);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
u32 GCMemcard::RemoveFile(u32 index) //index in the directory array
|
u32 GCMemcard::RemoveFile(u32 index) //index in the directory array
|
||||||
{
|
{
|
||||||
if (!mcdFile) return NOMEMCARD;
|
if (!mcdFile) return NOMEMCARD;
|
||||||
|
@ -130,7 +149,7 @@ u32 GCMemcard::RemoveFile(u32 index) //index in the directory array
|
||||||
|
|
||||||
int i = index + 1;
|
int i = index + 1;
|
||||||
memset(&(dir.Dir[index]), 0xFF, 0x40);
|
memset(&(dir.Dir[index]), 0xFF, 0x40);
|
||||||
|
|
||||||
while (i < 127)
|
while (i < 127)
|
||||||
{
|
{
|
||||||
DEntry * d = new DEntry;
|
DEntry * d = new DEntry;
|
||||||
|
@ -196,7 +215,7 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents, int remove)
|
||||||
{
|
{
|
||||||
return OUTOFBLOCKS;
|
return OUTOFBLOCKS;
|
||||||
}
|
}
|
||||||
if (!remove && titlePresent(direntry)) return TITLEPRESENT;
|
if (!remove && TitlePresent(direntry)) return TITLEPRESENT;
|
||||||
|
|
||||||
// find first free data block -- assume no freespace fragmentation
|
// find first free data block -- assume no freespace fragmentation
|
||||||
int totalspace = (((u32)BE16(hdr.Size) * 16) - 5);
|
int totalspace = (((u32)BE16(hdr.Size) * 16) - 5);
|
||||||
|
@ -293,9 +312,9 @@ u32 GCMemcard::GetFileData(u32 index, u8*dest, bool old) //index in the director
|
||||||
{
|
{
|
||||||
if (!mcdFile) return NOMEMCARD;
|
if (!mcdFile) return NOMEMCARD;
|
||||||
|
|
||||||
int block = BE16(dir.Dir[index].FirstBlock);
|
u16 block = BE16(dir.Dir[index].FirstBlock);
|
||||||
int saveLength = BE16(dir.Dir[index].BlockCount);
|
u16 saveLength = BE16(dir.Dir[index].BlockCount);
|
||||||
int memcardSize = BE16(hdr.Size) * 0x0010;
|
u16 memcardSize = BE16(hdr.Size) * 0x0010;
|
||||||
|
|
||||||
if (block + saveLength > memcardSize)
|
if (block + saveLength > memcardSize)
|
||||||
{
|
{
|
||||||
|
@ -308,27 +327,24 @@ u32 GCMemcard::GetFileData(u32 index, u8*dest, bool old) //index in the director
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(block != 0xFFFF);
|
|
||||||
assert(block > 0);
|
assert(block > 0);
|
||||||
do
|
while (block != 0xffff)
|
||||||
{
|
{
|
||||||
memcpy(dest,mc_data + 0x2000 * (block - 5), 0x2000);
|
memcpy(dest,mc_data + 0x2000 * (block - 5), 0x2000);
|
||||||
dest+=0x2000;
|
dest+=0x2000;
|
||||||
|
|
||||||
|
u16 nextblock = bswap16(bat.Map[block - 5]);
|
||||||
int nextblock = bswap16(bat.Map[block - 5]);
|
if (block + saveLength != memcardSize && nextblock > 0)
|
||||||
if (block + saveLength != memcardSize && nextblock > 0)
|
{//Fixes for older memcards that were not initialized with FF
|
||||||
{//Fixes for older memcards that were not initialized with FF
|
block = nextblock;
|
||||||
block = nextblock;
|
}
|
||||||
}
|
else break;
|
||||||
else block = 0xffff;
|
}
|
||||||
}
|
|
||||||
while (block != 0xffff);
|
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GCMemcard::GetFileSize(u32 index) //index in the directory array
|
u32 GCMemcard::GetFileSize(u32 index) //index in the directory array
|
||||||
{
|
{
|
||||||
if (!mcdFile) return 0;
|
if (!mcdFile) return 0;
|
||||||
|
|
||||||
|
@ -342,6 +358,7 @@ bool GCMemcard::GetFileInfo(u32 index, GCMemcard::DEntry& info) //index in the d
|
||||||
info = dir.Dir[index];
|
info = dir.Dir[index];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GCMemcard::GetFileName(u32 index, char *fn) //index in the directory array
|
bool GCMemcard::GetFileName(u32 index, char *fn) //index in the directory array
|
||||||
{
|
{
|
||||||
if (!mcdFile) return false;
|
if (!mcdFile) return false;
|
||||||
|
@ -387,14 +404,13 @@ bool GCMemcard::GetComment2(u32 index, char *fn) //index in the directory array
|
||||||
u32 decode5A3(u16 val)
|
u32 decode5A3(u16 val)
|
||||||
{
|
{
|
||||||
const int lut5to8[] = { 0x00,0x08,0x10,0x18,0x20,0x29,0x31,0x39,
|
const int lut5to8[] = { 0x00,0x08,0x10,0x18,0x20,0x29,0x31,0x39,
|
||||||
0x41,0x4A,0x52,0x5A,0x62,0x6A,0x73,0x7B,
|
0x41,0x4A,0x52,0x5A,0x62,0x6A,0x73,0x7B,
|
||||||
0x83,0x8B,0x94,0x9C,0xA4,0xAC,0xB4,0xBD,
|
0x83,0x8B,0x94,0x9C,0xA4,0xAC,0xB4,0xBD,
|
||||||
0xC5,0xCD,0xD5,0xDE,0xE6,0xEE,0xF6,0xFF};
|
0xC5,0xCD,0xD5,0xDE,0xE6,0xEE,0xF6,0xFF};
|
||||||
const int lut4to8[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,
|
const int lut4to8[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,
|
||||||
0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
|
0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
|
||||||
const int lut3to8[] = { 0x00,0x24,0x48,0x6D,0x91,0xB6,0xDA,0xFF};
|
const int lut3to8[] = { 0x00,0x24,0x48,0x6D,0x91,0xB6,0xDA,0xFF};
|
||||||
|
|
||||||
|
|
||||||
int r,g,b,a;
|
int r,g,b,a;
|
||||||
if ((val&0x8000))
|
if ((val&0x8000))
|
||||||
{
|
{
|
||||||
|
@ -433,11 +449,11 @@ void decode5A3image(u32* dst, u16* src, int width, int height)
|
||||||
|
|
||||||
void decodeCI8image(u32* dst, u8* src, u16* pal, int width, int height)
|
void decodeCI8image(u32* dst, u8* src, u16* pal, int width, int height)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < height; y += 4)
|
for (int y = 0; y < height; y += 4)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < width; x += 8)
|
for (int x = 0; x < width; x += 8)
|
||||||
{
|
{
|
||||||
for (int iy = 0; iy < 4; iy++, src += 8)
|
for (int iy = 0; iy < 4; iy++, src += 8)
|
||||||
{
|
{
|
||||||
u32 *tdst = dst+(y+iy)*width+x;
|
u32 *tdst = dst+(y+iy)*width+x;
|
||||||
for (int ix = 0; ix < 8; ix++)
|
for (int ix = 0; ix < 8; ix++)
|
||||||
|
@ -486,7 +502,7 @@ bool GCMemcard::ReadBannerRGBA8(u32 index, u32* buffer)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GCMemcard::ReadAnimRGBA8(u32 index, u32* buffer, u8 *delays)
|
u32 GCMemcard::ReadAnimRGBA8(u32 index, u32* buffer, u8 *delays)
|
||||||
{
|
{
|
||||||
if (!mcdFile) return 0;
|
if (!mcdFile) return 0;
|
||||||
|
|
||||||
|
@ -614,7 +630,7 @@ bool GCMemcard::FixChecksums()
|
||||||
hdr.CheckSum1[1] = u8(csum1);
|
hdr.CheckSum1[1] = u8(csum1);
|
||||||
hdr.CheckSum2[0] = u8(csum2 >> 8);
|
hdr.CheckSum2[0] = u8(csum2 >> 8);
|
||||||
hdr.CheckSum2[1] = u8(csum2);
|
hdr.CheckSum2[1] = u8(csum2);
|
||||||
|
|
||||||
calc_checksumsBE((u16*)&dir, 0xFFE, &csum1, &csum2);
|
calc_checksumsBE((u16*)&dir, 0xFFE, &csum1, &csum2);
|
||||||
dir.CheckSum1[0] = u8(csum1 >> 8);
|
dir.CheckSum1[0] = u8(csum1 >> 8);
|
||||||
dir.CheckSum1[1] = u8(csum1);
|
dir.CheckSum1[1] = u8(csum1);
|
||||||
|
@ -641,7 +657,7 @@ bool GCMemcard::FixChecksums()
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
u32 GCMemcard::CopyFrom(GCMemcard& source, u32 index)
|
u32 GCMemcard::CopyFrom(GCMemcard& source, u32 index)
|
||||||
{
|
{
|
||||||
if (!mcdFile) return NOMEMCARD;
|
if (!mcdFile) return NOMEMCARD;
|
||||||
|
|
||||||
|
@ -667,7 +683,7 @@ u32 GCMemcard::CopyFrom(GCMemcard& source, u32 index)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 GCMemcard::ImportGci(const char *fileName, std::string fileName2)
|
s32 GCMemcard::ImportGci(const char *fileName, std::string fileName2)
|
||||||
{
|
{
|
||||||
if (fileName2.empty() && !mcdFile) return OPENFAIL;
|
if (fileName2.empty() && !mcdFile) return OPENFAIL;
|
||||||
|
|
||||||
|
@ -685,7 +701,7 @@ s32 GCMemcard::ImportGci(const char *fileName, std::string fileName2)
|
||||||
{
|
{
|
||||||
fread(tmp, 1, 0xD, gci);
|
fread(tmp, 1, 0xD, gci);
|
||||||
if (!strcasecmp(fileType.c_str(), ".gcs"))
|
if (!strcasecmp(fileType.c_str(), ".gcs"))
|
||||||
{
|
{
|
||||||
if (!memcmp(tmp, "GCSAVE", 6)) // Header must be uppercase
|
if (!memcmp(tmp, "GCSAVE", 6)) // Header must be uppercase
|
||||||
offset = GCS;
|
offset = GCS;
|
||||||
else
|
else
|
||||||
|
@ -760,7 +776,7 @@ s32 GCMemcard::ImportGci(const char *fileName, std::string fileName2)
|
||||||
u32 size = BE16((d->BlockCount)) * 0x2000;
|
u32 size = BE16((d->BlockCount)) * 0x2000;
|
||||||
u8 *t = new u8[size];
|
u8 *t = new u8[size];
|
||||||
fread(t, 1, size, gci);
|
fread(t, 1, size, gci);
|
||||||
fclose(gci);
|
fclose(gci);
|
||||||
u32 ret;
|
u32 ret;
|
||||||
if(!fileName2.empty())
|
if(!fileName2.empty())
|
||||||
{
|
{
|
||||||
|
@ -805,7 +821,6 @@ u32 GCMemcard::ExportGci(u32 index, const char *fileName)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fseek(gci, 0x40, SEEK_SET);
|
fseek(gci, 0x40, SEEK_SET);
|
||||||
assert(fwrite(t, 1, 0x2000 * BE16(d.BlockCount), gci)== (unsigned) (0x2000 * BE16(d.BlockCount)));
|
assert(fwrite(t, 1, 0x2000 * BE16(d.BlockCount), gci)== (unsigned) (0x2000 * BE16(d.BlockCount)));
|
||||||
fclose(gci);
|
fclose(gci);
|
||||||
|
@ -837,21 +852,62 @@ GCMemcard::GCMemcard(const char *filename)
|
||||||
{
|
{
|
||||||
FILE *mcd = fopen(filename,"r+b");
|
FILE *mcd = fopen(filename,"r+b");
|
||||||
mcdFile = mcd;
|
mcdFile = mcd;
|
||||||
|
fail[0] = true;
|
||||||
if (!mcd) return;
|
if (!mcd) return;
|
||||||
|
|
||||||
|
for(int i=0;i<12;i++)fail[i]=false;
|
||||||
|
|
||||||
|
//This function can be removed once more about hdr is known and we can check for a valid header
|
||||||
|
std::string fileType;
|
||||||
|
SplitPath(filename, NULL, NULL, &fileType);
|
||||||
|
if (strcasecmp(fileType.c_str(), ".raw") && strcasecmp(fileType.c_str(), ".gcp"))
|
||||||
|
{
|
||||||
|
fail[0] = true;
|
||||||
|
fail[NOTRAWORGCP] = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fseek(mcd, 0x0000, SEEK_SET);
|
fseek(mcd, 0x0000, SEEK_SET);
|
||||||
assert(fread(&hdr, 1, 0x2000, mcd) == 0x2000);
|
if (fread(&hdr, 1, 0x2000, mcd) != 0x2000)
|
||||||
assert(fread(&dir, 1, 0x2000, mcd) == 0x2000);
|
{
|
||||||
assert(fread(&dir_backup, 1, 0x2000, mcd) == 0x2000);
|
fail[0] = true;
|
||||||
assert(fread(&bat, 1, 0x2000, mcd) == 0x2000);
|
fail[HDR_READ_ERROR] = true;
|
||||||
assert(fread(&bat_backup, 1, 0x2000, mcd) == 0x2000);
|
return;
|
||||||
|
}
|
||||||
|
if (fread(&dir, 1, 0x2000, mcd) != 0x2000)
|
||||||
|
{
|
||||||
|
fail[0] = true;
|
||||||
|
fail[DIR_READ_ERROR] = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fread(&dir_backup, 1, 0x2000, mcd) != 0x2000)
|
||||||
|
{
|
||||||
|
fail[0] = true;
|
||||||
|
fail[DIR_BAK_READ_ERROR] = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fread(&bat, 1, 0x2000, mcd) != 0x2000)
|
||||||
|
{
|
||||||
|
fail[0] = true;
|
||||||
|
fail[BAT_READ_ERROR] = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fread(&bat_backup, 1, 0x2000, mcd) != 0x2000)
|
||||||
|
{
|
||||||
|
fail[0] = true;
|
||||||
|
fail[BAT_BAK_READ_ERROR] = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
u32 csums = TestChecksums();
|
u32 csums = TestChecksums();
|
||||||
|
|
||||||
if (csums&1)
|
if (csums&1)
|
||||||
{
|
{
|
||||||
// header checksum error!
|
// header checksum error!
|
||||||
// TODO: fail to load
|
// invalid files do not always get here
|
||||||
|
fail[0] = true;
|
||||||
|
fail[HDR_CSUM_FAIL] = true;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (csums&2) // directory checksum error!
|
if (csums&2) // directory checksum error!
|
||||||
|
@ -859,7 +915,9 @@ GCMemcard::GCMemcard(const char *filename)
|
||||||
if (csums&4)
|
if (csums&4)
|
||||||
{
|
{
|
||||||
// backup is also wrong!
|
// backup is also wrong!
|
||||||
// TODO: fail to load
|
fail[0] = true;
|
||||||
|
fail[DIR_CSUM_FAIL] = true;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -877,7 +935,9 @@ GCMemcard::GCMemcard(const char *filename)
|
||||||
if (csums&16)
|
if (csums&16)
|
||||||
{
|
{
|
||||||
// backup is also wrong!
|
// backup is also wrong!
|
||||||
// TODO: fail to load
|
fail[0] = true;
|
||||||
|
fail[BAT_CSUM_FAIL] = true;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -900,15 +960,30 @@ GCMemcard::GCMemcard(const char *filename)
|
||||||
|
|
||||||
fseek(mcd, 0xa000, SEEK_SET);
|
fseek(mcd, 0xa000, SEEK_SET);
|
||||||
|
|
||||||
assert(BE16(hdr.Size) != 0xFFFF);
|
u16 size = BE16(hdr.Size);
|
||||||
mc_data_size = (((u32)BE16(hdr.Size) * 16) - 5) * 0x2000;
|
if ((size== 0x0080) || (size == 0x0040) ||
|
||||||
mc_data = new u8[mc_data_size];
|
(size == 0x0020) || (size == 0x0010) ||
|
||||||
|
(size == 0x0008) || (size == 0x0004))
|
||||||
|
{
|
||||||
|
mc_data_size = (((u32)size * 16) - 5) * 0x2000;
|
||||||
|
mc_data = new u8[mc_data_size];
|
||||||
|
|
||||||
size_t read = fread(mc_data, 1, mc_data_size, mcd);
|
size_t read = fread(mc_data, 1, mc_data_size, mcd);
|
||||||
assert(mc_data_size == read);
|
if (mc_data_size != read)
|
||||||
|
{
|
||||||
|
fail[0] = true;
|
||||||
|
fail[DATA_READ_FAIL] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fail[0] = true;
|
||||||
|
fail[HDR_SIZE_FFFF] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GCMemcard::~GCMemcard()
|
GCMemcard::~GCMemcard()
|
||||||
{
|
{
|
||||||
|
if (!mcdFile) return;
|
||||||
fclose((FILE*)mcdFile);
|
fclose((FILE*)mcdFile);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,17 @@ enum
|
||||||
SAVFAIL,
|
SAVFAIL,
|
||||||
OPENFAIL,
|
OPENFAIL,
|
||||||
GCI,
|
GCI,
|
||||||
|
HDR_READ_ERROR,
|
||||||
|
DIR_READ_ERROR,
|
||||||
|
DIR_BAK_READ_ERROR,
|
||||||
|
BAT_READ_ERROR,
|
||||||
|
BAT_BAK_READ_ERROR,
|
||||||
|
HDR_CSUM_FAIL,
|
||||||
|
DIR_CSUM_FAIL,
|
||||||
|
BAT_CSUM_FAIL,
|
||||||
|
DATA_READ_FAIL,
|
||||||
|
HDR_SIZE_FFFF,
|
||||||
|
NOTRAWORGCP,
|
||||||
SAV = 0x80,
|
SAV = 0x80,
|
||||||
GCS = 0x110,
|
GCS = 0x110,
|
||||||
OUTOFBLOCKS,
|
OUTOFBLOCKS,
|
||||||
|
@ -38,9 +49,9 @@ enum
|
||||||
FAIL
|
FAIL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class GCMemcard
|
class GCMemcard
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
void* mcdFile;
|
void* mcdFile;
|
||||||
|
|
||||||
u32 mc_data_size;
|
u32 mc_data_size;
|
||||||
|
@ -48,8 +59,6 @@ class GCMemcard
|
||||||
|
|
||||||
void calc_checksumsBE(u16 *buf, u32 num, u16 *c1, u16 *c2);
|
void calc_checksumsBE(u16 *buf, u32 num, u16 *c1, u16 *c2);
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
#pragma pack(push,1)
|
#pragma pack(push,1)
|
||||||
struct OSTime {
|
struct OSTime {
|
||||||
u32 low;
|
u32 low;
|
||||||
|
@ -133,6 +142,9 @@ public:
|
||||||
} bat,bat_backup;
|
} bat,bat_backup;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool fail[12];
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
GCMemcard(const char* fileName);
|
GCMemcard(const char* fileName);
|
||||||
|
|
||||||
|
@ -148,7 +160,7 @@ public:
|
||||||
u32 GetNumFiles();
|
u32 GetNumFiles();
|
||||||
|
|
||||||
// Returns true if title already on memcard
|
// Returns true if title already on memcard
|
||||||
bool titlePresent(DEntry d);
|
bool TitlePresent(DEntry d);
|
||||||
|
|
||||||
// read directory entry
|
// read directory entry
|
||||||
bool GetFileInfo(u32 index, DEntry& data);
|
bool GetFileInfo(u32 index, DEntry& data);
|
||||||
|
@ -156,6 +168,12 @@ public:
|
||||||
// buffer needs to be a char[32] or bigger
|
// buffer needs to be a char[32] or bigger
|
||||||
bool GetFileName(u32 index, char* buffer);
|
bool GetFileName(u32 index, char* buffer);
|
||||||
|
|
||||||
|
bool GetNumBlocks(u32 index, u16* buffer);
|
||||||
|
|
||||||
|
u16 GetFreeBlocks(void);
|
||||||
|
|
||||||
|
bool GetFirstBlock(u32 index, u16* buffer);
|
||||||
|
|
||||||
// buffer needs to be a char[32] or bigger
|
// buffer needs to be a char[32] or bigger
|
||||||
bool GetComment1(u32 index, char* buffer);
|
bool GetComment1(u32 index, char* buffer);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue