Added gci importing/exporting to the memcardmanager (thanks to lpfaint99, see issue 229). Also improved GCMemcard a bit.
I have loaded a raw dump from a real gamecube in dolphin successfully, then used FixChecksums on it (which actually changes some data...), and it continued to act correctly in dolphin. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@841 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
3763b365d1
commit
633881eb7a
|
@ -16,7 +16,6 @@
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
|
|
||||||
#include "MemcardManager.h"
|
#include "MemcardManager.h"
|
||||||
|
|
||||||
#include "wx/mstream.h"
|
#include "wx/mstream.h"
|
||||||
|
@ -54,7 +53,7 @@ wxBitmap wxBitmapFromMemoryRGBA(const unsigned char* data, int width, int height
|
||||||
|
|
||||||
u8 *pixelData = pdata + sizeof(hdr);
|
u8 *pixelData = pdata + sizeof(hdr);
|
||||||
|
|
||||||
for(int y=0;y<height;y++)
|
for (int y=0;y<height;y++)
|
||||||
{
|
{
|
||||||
memcpy(pixelData+y*stride,data+(height-y-1)*stride,stride);
|
memcpy(pixelData+y*stride,data+(height-y-1)*stride,stride);
|
||||||
}
|
}
|
||||||
|
@ -73,11 +72,15 @@ wxBitmap wxBitmapFromMemoryRGBA(const unsigned char* data, int width, int height
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(CMemcardManager, wxDialog)
|
BEGIN_EVENT_TABLE(CMemcardManager, wxDialog)
|
||||||
EVT_CLOSE(CMemcardManager::OnClose)
|
EVT_CLOSE(CMemcardManager::OnClose)
|
||||||
EVT_BUTTON(ID_COPYRIGHT,CMemcardManager::CopyDeleteClick)
|
|
||||||
EVT_BUTTON(ID_COPYLEFT,CMemcardManager::CopyDeleteClick)
|
EVT_BUTTON(ID_COPYLEFT,CMemcardManager::CopyDeleteClick)
|
||||||
|
EVT_BUTTON(ID_COPYRIGHT,CMemcardManager::CopyDeleteClick)
|
||||||
EVT_BUTTON(ID_FIXCHECKSUM,CMemcardManager::CopyDeleteClick)
|
EVT_BUTTON(ID_FIXCHECKSUM,CMemcardManager::CopyDeleteClick)
|
||||||
EVT_BUTTON(ID_DELETERIGHT,CMemcardManager::CopyDeleteClick)
|
|
||||||
EVT_BUTTON(ID_DELETELEFT,CMemcardManager::CopyDeleteClick)
|
EVT_BUTTON(ID_DELETELEFT,CMemcardManager::CopyDeleteClick)
|
||||||
|
EVT_BUTTON(ID_DELETERIGHT,CMemcardManager::CopyDeleteClick)
|
||||||
|
EVT_BUTTON(ID_GCIOPENRIGHT,CMemcardManager::CopyDeleteClick)
|
||||||
|
EVT_BUTTON(ID_GCISAVERIGHT,CMemcardManager::CopyDeleteClick)
|
||||||
|
EVT_BUTTON(ID_GCIOPENLEFT,CMemcardManager::CopyDeleteClick)
|
||||||
|
EVT_BUTTON(ID_GCISAVELEFT,CMemcardManager::CopyDeleteClick)
|
||||||
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()
|
||||||
|
@ -92,11 +95,13 @@ CMemcardManager::CMemcardManager(wxWindow* parent, wxWindowID id, const wxString
|
||||||
|
|
||||||
CMemcardManager::~CMemcardManager()
|
CMemcardManager::~CMemcardManager()
|
||||||
{
|
{
|
||||||
if (memoryCard[0]) {
|
if (memoryCard[0])
|
||||||
|
{
|
||||||
delete memoryCard[0];
|
delete memoryCard[0];
|
||||||
memoryCard[0] = NULL;
|
memoryCard[0] = NULL;
|
||||||
}
|
}
|
||||||
if (memoryCard[1]) {
|
if (memoryCard[1])
|
||||||
|
{
|
||||||
delete memoryCard[1];
|
delete memoryCard[1];
|
||||||
memoryCard[1] = NULL;
|
memoryCard[1] = NULL;
|
||||||
}
|
}
|
||||||
|
@ -105,25 +110,30 @@ CMemcardManager::~CMemcardManager()
|
||||||
void CMemcardManager::CreateGUIControls()
|
void CMemcardManager::CreateGUIControls()
|
||||||
{
|
{
|
||||||
// buttons
|
// buttons
|
||||||
m_CopyRight = new wxButton(this, ID_COPYRIGHT, wxT("->Copy->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
|
||||||
m_CopyLeft = new wxButton(this, ID_COPYLEFT, wxT("<-Copy<-"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
m_CopyLeft = new wxButton(this, ID_COPYLEFT, wxT("<-Copy<-"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
m_CopyRight = new wxButton(this, ID_COPYRIGHT, wxT("->Copy->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
|
||||||
m_FixChecksum = new wxButton(this, ID_FIXCHECKSUM, wxT("Fix\nchecksum"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
m_FixChecksum = new wxButton(this, ID_FIXCHECKSUM, wxT("<-Fix\nChecksum"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
|
||||||
|
m_GciOpenLeft = new wxButton(this, ID_GCIOPENLEFT, wxT("<-Import GCI"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
m_GciSaveLeft = new wxButton(this, ID_GCISAVELEFT, wxT("<-Export GCI"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
m_GciOpenRight = new wxButton(this, ID_GCIOPENRIGHT, wxT("Import GCI->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
m_GciSaveRight = new wxButton(this, ID_GCISAVERIGHT, wxT("Export GCI->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||||
|
|
||||||
m_DeleteRight = new wxButton(this, ID_DELETERIGHT, wxT("Delete->"), 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);
|
||||||
|
|
||||||
// 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
|
||||||
// will change Mem*.raw to *.raw, when loading invalid .raw files doesn't crash the app :/
|
// Will change Mem*.raw to *.raw, when loading invalid .raw files doesn't 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("Dolphin memcards (Mem*.raw)|Mem*.raw"), wxDefaultPosition, wxDefaultSize, wxFLP_USE_TEXTCTRL|wxFLP_FILE_MUST_EXIST|wxFLP_OPEN);
|
wxT("Dolphin memcards (Mem*.raw)|Mem*.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:"),
|
||||||
wxT("Dolphin memcards (Mem*.raw)|Mem*.raw"), wxDefaultPosition, wxDefaultSize, wxFLP_USE_TEXTCTRL|wxFLP_FILE_MUST_EXIST|wxFLP_OPEN);
|
wxT("Dolphin memcards (Mem*.raw)|Mem*.raw"), wxDefaultPosition, wxDefaultSize, wxFLP_USE_TEXTCTRL|wxFLP_FILE_MUST_EXIST|wxFLP_OPEN);
|
||||||
|
|
||||||
m_MemcardList[0] = new wxListCtrl(this, ID_MEMCARD1LIST, wxDefaultPosition, wxSize(350,400),
|
m_MemcardList[0] = new wxListCtrl(this, ID_MEMCARD1LIST, wxDefaultPosition, wxSize(350,400),
|
||||||
wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL);
|
wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL);
|
||||||
m_MemcardList[1] = new wxListCtrl(this, ID_MEMCARD2LIST, wxDefaultPosition, wxSize(350,400),
|
m_MemcardList[1] = new wxListCtrl(this, ID_MEMCARD2LIST, wxDefaultPosition, wxSize(350,400),
|
||||||
|
@ -135,14 +145,20 @@ void CMemcardManager::CreateGUIControls()
|
||||||
// mmmm sizer goodness
|
// mmmm sizer goodness
|
||||||
wxBoxSizer* sButtons;
|
wxBoxSizer* sButtons;
|
||||||
sButtons = new wxBoxSizer(wxVERTICAL);
|
sButtons = new wxBoxSizer(wxVERTICAL);
|
||||||
|
sButtons->AddStretchSpacer(2);
|
||||||
|
sButtons->Add(m_CopyLeft, 0, wxEXPAND, 5);
|
||||||
|
sButtons->Add(m_CopyRight, 0, wxEXPAND, 5);
|
||||||
sButtons->AddStretchSpacer(1);
|
sButtons->AddStretchSpacer(1);
|
||||||
sButtons->Add(m_CopyRight, 0, 0, 5);
|
sButtons->Add(m_FixChecksum, 0, wxEXPAND, 5);
|
||||||
sButtons->Add(m_CopyLeft, 0, 0, 5);
|
sButtons->AddStretchSpacer(1);
|
||||||
sButtons->AddStretchSpacer(2);
|
sButtons->Add(m_GciOpenLeft, 0, wxEXPAND, 5);
|
||||||
sButtons->Add(m_FixChecksum, 0, 0, 5);
|
sButtons->Add(m_GciSaveLeft, 0, wxEXPAND, 5);
|
||||||
sButtons->AddStretchSpacer(2);
|
sButtons->AddStretchSpacer(1);
|
||||||
sButtons->Add(m_DeleteRight, 0, 0, 5);
|
sButtons->Add(m_GciOpenRight, 0, wxEXPAND, 5);
|
||||||
sButtons->Add(m_DeleteLeft, 0, 0, 5);
|
sButtons->Add(m_GciSaveRight, 0, wxEXPAND, 5);
|
||||||
|
sButtons->AddStretchSpacer(1);
|
||||||
|
sButtons->Add(m_DeleteLeft, 0, wxEXPAND, 5);
|
||||||
|
sButtons->Add(m_DeleteRight, 0, wxEXPAND, 5);
|
||||||
sButtons->AddStretchSpacer(1);
|
sButtons->AddStretchSpacer(1);
|
||||||
|
|
||||||
sMemcard1->Add(m_Memcard1Path, 0, wxEXPAND|wxALL, 5);
|
sMemcard1->Add(m_Memcard1Path, 0, wxEXPAND|wxALL, 5);
|
||||||
|
@ -157,6 +173,7 @@ void CMemcardManager::CreateGUIControls()
|
||||||
|
|
||||||
this->SetSizer(sMain);
|
this->SetSizer(sMain);
|
||||||
sMain->SetSizeHints(this);
|
sMain->SetSizeHints(this);
|
||||||
|
Fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMemcardManager::OnClose(wxCloseEvent& WXUNUSED (event))
|
void CMemcardManager::OnClose(wxCloseEvent& WXUNUSED (event))
|
||||||
|
@ -166,14 +183,15 @@ void CMemcardManager::OnClose(wxCloseEvent& WXUNUSED (event))
|
||||||
|
|
||||||
void CMemcardManager::OnPathChange(wxFileDirPickerEvent& event)
|
void CMemcardManager::OnPathChange(wxFileDirPickerEvent& event)
|
||||||
{
|
{
|
||||||
switch(event.GetId())
|
|
||||||
|
switch (event.GetId())
|
||||||
{
|
{
|
||||||
case ID_MEMCARD1PATH:
|
case ID_MEMCARD1PATH:
|
||||||
ReloadMemcard(event.GetPath().mb_str(), 0);
|
ReloadMemcard(event.GetPath().mb_str(), 0);
|
||||||
break;
|
break;
|
||||||
case ID_MEMCARD2PATH:
|
case ID_MEMCARD2PATH:
|
||||||
ReloadMemcard(event.GetPath().mb_str(), 1);
|
ReloadMemcard(event.GetPath().mb_str(), 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,53 +202,129 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
||||||
|
|
||||||
switch(event.GetId())
|
switch(event.GetId())
|
||||||
{
|
{
|
||||||
case ID_COPYRIGHT:
|
case ID_COPYLEFT:
|
||||||
if(index0 != -1 && m_MemcardList[1]->GetItemCount() > 0)
|
if ((index1 != -1) && (memoryCard[0] != NULL))
|
||||||
|
{
|
||||||
|
memoryCard[0]->CopyFrom(*memoryCard[1], index1);
|
||||||
|
memoryCard[0]->Save();
|
||||||
|
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ID_COPYRIGHT:
|
||||||
|
if ((index0 != -1) && (memoryCard[1] != NULL))
|
||||||
|
{
|
||||||
|
memoryCard[1]->CopyFrom(*memoryCard[0], index0);
|
||||||
|
memoryCard[1]->Save();
|
||||||
|
ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ID_FIXCHECKSUM:
|
||||||
|
if (m_MemcardList[0]->GetItemCount() > 0)
|
||||||
|
{
|
||||||
|
// Fix checksums and save the changes
|
||||||
|
memoryCard[0]->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);
|
||||||
|
memoryCard[0]->Save();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ID_GCIOPENLEFT:
|
||||||
|
if (memoryCard[0] != NULL)
|
||||||
|
{
|
||||||
|
wxString temp = wxFileSelector(_T("Select the GCI file to import"),
|
||||||
|
wxEmptyString, wxEmptyString, wxEmptyString,wxString::Format
|
||||||
|
(
|
||||||
|
_T("GCI File(*.gci)|*.gci|All files (%s)|%s"),
|
||||||
|
wxFileSelectorDefaultWildcardStr,
|
||||||
|
wxFileSelectorDefaultWildcardStr
|
||||||
|
),
|
||||||
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
|
const char * fileName = temp.ToAscii();
|
||||||
|
|
||||||
|
if (temp.length()>0)
|
||||||
{
|
{
|
||||||
memoryCard[1]->CopyFrom(*memoryCard[0], index0);
|
memoryCard[0]->AddGci(fileName);
|
||||||
memoryCard[1]->Save();
|
|
||||||
ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ID_COPYLEFT:
|
|
||||||
if(index1 != -1 && m_MemcardList[0]->GetItemCount() > 0)
|
|
||||||
{
|
|
||||||
memoryCard[0]->CopyFrom(*memoryCard[1], index1);
|
|
||||||
memoryCard[0]->Save();
|
memoryCard[0]->Save();
|
||||||
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
|
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case ID_FIXCHECKSUM:
|
break;
|
||||||
if(m_MemcardList[0]->GetItemCount() > 0)
|
case ID_GCIOPENRIGHT:
|
||||||
|
if (memoryCard[1] != NULL)
|
||||||
|
{
|
||||||
|
wxString temp = wxFileSelector(_T("Select the GCI file to import"),
|
||||||
|
wxEmptyString, wxEmptyString, wxEmptyString,wxString::Format
|
||||||
|
(
|
||||||
|
_T("GCI File(*.gci)|*.gci|All files (%s)|%s"),
|
||||||
|
wxFileSelectorDefaultWildcardStr,
|
||||||
|
wxFileSelectorDefaultWildcardStr
|
||||||
|
),
|
||||||
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
|
const char * fileName = temp.ToAscii();
|
||||||
|
|
||||||
|
if (temp.length()>0)
|
||||||
{
|
{
|
||||||
// Fix checksums and save the changes
|
memoryCard[1]->AddGci(fileName);
|
||||||
memoryCard[0]->FixChecksums();
|
|
||||||
memoryCard[0]->Save();
|
|
||||||
wxMessageBox(wxT("The checksum was successfully fixed"), wxT("Message"), wxOK);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ID_DELETERIGHT:
|
|
||||||
if(index1 != -1)
|
|
||||||
{
|
|
||||||
memoryCard[1]->RemoveFile(index1);
|
|
||||||
memoryCard[1]->Save();
|
memoryCard[1]->Save();
|
||||||
ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ID_DELETELEFT:
|
|
||||||
if(index0 != -1)
|
|
||||||
{
|
|
||||||
memoryCard[0]->RemoveFile(index0);
|
|
||||||
memoryCard[0]->Save();
|
|
||||||
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
|
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
case ID_GCISAVELEFT:
|
||||||
|
if (index0 != -1)
|
||||||
|
{
|
||||||
|
wxString temp = wxFileSelector(_T("Save GCI as.."),
|
||||||
|
wxEmptyString, wxEmptyString, _T(".gci"), wxString::Format
|
||||||
|
(
|
||||||
|
_T("GCI File(*.gci)|*.gci"),
|
||||||
|
wxFileSelectorDefaultWildcardStr,
|
||||||
|
wxFileSelectorDefaultWildcardStr
|
||||||
|
),
|
||||||
|
wxFD_OVERWRITE_PROMPT|wxFD_SAVE);
|
||||||
|
const char * fileName = temp.ToAscii();
|
||||||
|
|
||||||
|
if (temp.length()>0)
|
||||||
|
memoryCard[0]->SaveGci(index0, fileName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ID_GCISAVERIGHT:
|
||||||
|
if (index1 != -1)
|
||||||
|
{
|
||||||
|
wxString temp = wxFileSelector(_T("Save GCI as.."),
|
||||||
|
wxEmptyString, wxEmptyString, _T(".gci"), wxString::Format
|
||||||
|
(
|
||||||
|
_T("GCI File(*.gci)|*.gci"),
|
||||||
|
wxFileSelectorDefaultWildcardStr,
|
||||||
|
wxFileSelectorDefaultWildcardStr
|
||||||
|
),
|
||||||
|
wxFD_OVERWRITE_PROMPT|wxFD_SAVE);
|
||||||
|
const char * fileName = temp.ToAscii();
|
||||||
|
|
||||||
|
if (temp.length()>0)
|
||||||
|
memoryCard[1]->SaveGci(index1, fileName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ID_DELETELEFT:
|
||||||
|
if (index0 != -1)
|
||||||
|
{
|
||||||
|
memoryCard[0]->RemoveFile(index0);
|
||||||
|
memoryCard[0]->Save();
|
||||||
|
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ID_DELETERIGHT:
|
||||||
|
if (index1 != -1)
|
||||||
|
{
|
||||||
|
memoryCard[1]->RemoveFile(index1);
|
||||||
|
memoryCard[1]->Save();
|
||||||
|
ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMemcardManager::ReloadMemcard(const char *fileName, int card)
|
void CMemcardManager::ReloadMemcard(const char *fileName, int card)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
@ -248,7 +342,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];
|
||||||
|
@ -256,17 +350,17 @@ void CMemcardManager::ReloadMemcard(const char *fileName, int card)
|
||||||
|
|
||||||
int numFrames = memoryCard[card]->ReadAnimRGBA8(i,animData,animDelay);
|
int numFrames = memoryCard[card]->ReadAnimRGBA8(i,animData,animDelay);
|
||||||
|
|
||||||
if(!memoryCard[card]->ReadBannerRGBA8(i,pxdata))
|
if (!memoryCard[card]->ReadBannerRGBA8(i,pxdata))
|
||||||
{
|
{
|
||||||
memset(pxdata,0,96*32*4);
|
memset(pxdata,0,96*32*4);
|
||||||
|
|
||||||
if(numFrames>0) // just use the first one
|
if (numFrames>0) // Just use the first one
|
||||||
{
|
{
|
||||||
u32 *icdata = animData;
|
u32 *icdata = animData;
|
||||||
|
|
||||||
for(int y=0;y<32;y++)
|
for (int y=0;y<32;y++)
|
||||||
{
|
{
|
||||||
for(int x=0;x<32;x++)
|
for (int x=0;x<32;x++)
|
||||||
{
|
{
|
||||||
pxdata[y*96+x+32] = icdata[y*32+x] /* | 0xFF000000 */;
|
pxdata[y*96+x+32] = icdata[y*32+x] /* | 0xFF000000 */;
|
||||||
}
|
}
|
||||||
|
@ -277,35 +371,35 @@ void CMemcardManager::ReloadMemcard(const char *fileName, int card)
|
||||||
wxBitmap map = wxBitmapFromMemoryRGBA((u8*)pxdata,96,32);
|
wxBitmap map = wxBitmapFromMemoryRGBA((u8*)pxdata,96,32);
|
||||||
images[i*2] = list->Add(map);
|
images[i*2] = list->Add(map);
|
||||||
|
|
||||||
if(numFrames>0)
|
if (numFrames>0)
|
||||||
{
|
{
|
||||||
memset(pxdata,0,96*32*4);
|
memset(pxdata,0,96*32*4);
|
||||||
|
|
||||||
int frames=3;
|
int frames=3;
|
||||||
|
|
||||||
if(numFrames<frames) frames=numFrames;
|
if (numFrames<frames) frames=numFrames;
|
||||||
for(int f=0;f<frames;f++)
|
for (int f=0;f<frames;f++)
|
||||||
{
|
{
|
||||||
for(int y=0;y<32;y++)
|
for (int y=0;y<32;y++)
|
||||||
{
|
{
|
||||||
for(int x=0;x<32;x++)
|
for (int x=0;x<32;x++)
|
||||||
{
|
{
|
||||||
pxdata[y*96 + x + 32*f] = animData[f*32*32 + y*32 + x];
|
pxdata[y*96 + x + 32*f] = animData[f*32*32 + y*32 + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wxBitmap icon = wxBitmapFromMemoryRGBA((u8*)pxdata,96,32);
|
wxBitmap icon = wxBitmapFromMemoryRGBA((u8*)pxdata,96,32);
|
||||||
images[i*2+1] = list->Add(icon);
|
images[i*2+1] = list->Add(icon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0;i<nFiles;i++)
|
for (int i=0;i<nFiles;i++)
|
||||||
{
|
{
|
||||||
char title[32];
|
char title[32];
|
||||||
char comment[32];
|
char comment[32];
|
||||||
|
|
||||||
if(!memoryCard[card]->GetComment1(i,title)) title[0]=0;
|
if (!memoryCard[card]->GetComment1(i,title)) title[0]=0;
|
||||||
if(!memoryCard[card]->GetComment2(i,comment)) comment[0]=0;
|
if (!memoryCard[card]->GetComment2(i,comment)) comment[0]=0;
|
||||||
|
|
||||||
int index = m_MemcardList[card]->InsertItem(i, wxT("row"));
|
int index = m_MemcardList[card]->InsertItem(i, wxT("row"));
|
||||||
m_MemcardList[card]->SetItem(index, COLUMN_BANNER, wxEmptyString);
|
m_MemcardList[card]->SetItem(index, COLUMN_BANNER, wxEmptyString);
|
||||||
|
@ -313,19 +407,20 @@ void CMemcardManager::ReloadMemcard(const char *fileName, int card)
|
||||||
m_MemcardList[card]->SetItem(index, COLUMN_COMMENT, wxString::FromAscii(comment));
|
m_MemcardList[card]->SetItem(index, COLUMN_COMMENT, wxString::FromAscii(comment));
|
||||||
m_MemcardList[card]->SetItem(index, COLUMN_ICON, wxEmptyString);
|
m_MemcardList[card]->SetItem(index, COLUMN_ICON, wxEmptyString);
|
||||||
|
|
||||||
if(images[i]>=0)
|
if (images[i]>=0)
|
||||||
{
|
{
|
||||||
m_MemcardList[card]->SetItemImage(index, images[i*2]);
|
m_MemcardList[card]->SetItemImage(index, images[i*2]);
|
||||||
m_MemcardList[card]->SetItemColumnImage(index, COLUMN_ICON, images[i*2+1]);
|
m_MemcardList[card]->SetItemColumnImage(index, COLUMN_ICON, images[i*2+1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_MemcardList[card]->Show();
|
|
||||||
|
|
||||||
delete[] images;
|
delete[] images;
|
||||||
|
|
||||||
// automatic column width
|
// 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++)
|
||||||
{
|
{
|
||||||
m_MemcardList[card]->SetColumnWidth(i, wxLIST_AUTOSIZE);
|
m_MemcardList[card]->SetColumnWidth(i, wxLIST_AUTOSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_MemcardList[card]->Show();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
//updated to 677
|
||||||
#ifndef __MEMCARD_MANAGER_h__
|
#ifndef __MEMCARD_MANAGER_h__
|
||||||
#define __MEMCARD_MANAGER_h__
|
#define __MEMCARD_MANAGER_h__
|
||||||
|
|
||||||
|
@ -35,27 +35,29 @@ class CMemcardManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CMemcardManager(wxWindow* parent, wxWindowID id = 1, const wxString& title = wxT("Memory Card Manager WARNING-Make backups before using, will probably mangle stuff!"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = MEMCARD_MANAGER_STYLE);
|
CMemcardManager(wxWindow *parent, wxWindowID id = 1, const wxString& title = wxT("Memory Card Manager WARNING-Make backups before using, will probably mangle stuff!"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = MEMCARD_MANAGER_STYLE);
|
||||||
virtual ~CMemcardManager();
|
virtual ~CMemcardManager();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE();
|
DECLARE_EVENT_TABLE();
|
||||||
|
|
||||||
wxBoxSizer* sMain;
|
wxBoxSizer *sMain;
|
||||||
wxButton* m_CopyRight;
|
wxButton *m_CopyLeft;
|
||||||
wxButton* m_CopyLeft;
|
wxButton *m_CopyRight;
|
||||||
wxButton* m_FixChecksum;
|
wxButton *m_FixChecksum;
|
||||||
wxButton* m_DeleteRight;
|
wxButton *m_GciOpenLeft;
|
||||||
wxButton* m_DeleteLeft;
|
wxButton *m_GciSaveLeft;
|
||||||
wxStaticBoxSizer* sMemcard1;
|
wxButton *m_GciOpenRight;
|
||||||
wxStaticBoxSizer* sMemcard2;
|
wxButton *m_GciSaveRight;
|
||||||
wxFilePickerCtrl* m_Memcard1Path;
|
wxButton *m_DeleteLeft;
|
||||||
wxFilePickerCtrl* m_Memcard2Path;
|
wxButton *m_DeleteRight;
|
||||||
wxListCtrl* m_MemcardList[2];
|
wxStaticBoxSizer *sMemcard1;
|
||||||
wxTimer* m_Timer;
|
wxStaticBoxSizer *sMemcard2;
|
||||||
|
wxFilePickerCtrl *m_Memcard1Path;
|
||||||
|
wxFilePickerCtrl *m_Memcard2Path;
|
||||||
|
|
||||||
int nframe;
|
wxListCtrl *m_MemcardList[2];
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -66,6 +68,10 @@ class CMemcardManager
|
||||||
ID_DELETELEFT,
|
ID_DELETELEFT,
|
||||||
ID_MEMCARD1PATH,
|
ID_MEMCARD1PATH,
|
||||||
ID_MEMCARD2PATH,
|
ID_MEMCARD2PATH,
|
||||||
|
ID_GCISAVERIGHT,
|
||||||
|
ID_GCISAVELEFT,
|
||||||
|
ID_GCIOPENRIGHT,
|
||||||
|
ID_GCIOPENLEFT,
|
||||||
ID_MEMCARD1LIST,
|
ID_MEMCARD1LIST,
|
||||||
ID_MEMCARD2LIST,
|
ID_MEMCARD2LIST,
|
||||||
ID_DUMMY_VALUE_ //don't remove this value unless you have other enum values
|
ID_DUMMY_VALUE_ //don't remove this value unless you have other enum values
|
||||||
|
|
|
@ -1,5 +1,20 @@
|
||||||
// gcmc.cpp: define el punto de entrada de la aplicación de consola.
|
// Copyright (C) 2003-2008 Dolphin Project.
|
||||||
//
|
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
|
// This program 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 2.0 for more details.
|
||||||
|
|
||||||
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
|
// Official SVN repository and contact information can be found at
|
||||||
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -249,16 +264,20 @@ bool GCMemcard::GetFileData(u32 index, u8*dest) //index in the directory array
|
||||||
if(!mcdFile) return false;
|
if(!mcdFile) return false;
|
||||||
|
|
||||||
int block = BE16(dir.Dir[index].FirstBlock);
|
int block = BE16(dir.Dir[index].FirstBlock);
|
||||||
|
int saveLength = BE16(dir.Dir[index].BlockCount);
|
||||||
|
int memcardSize = BE16(hdr.Size) * 0x0010;
|
||||||
assert((block!=0xFFFF)&&(block>0));
|
assert((block!=0xFFFF)&&(block>0));
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
int nextblock=bswap16(bat.Map[block-5]);
|
|
||||||
assert(nextblock>0);
|
|
||||||
|
|
||||||
memcpy(dest,mc_data + 0x2000*(block-5),0x2000);
|
memcpy(dest,mc_data + 0x2000*(block-5),0x2000);
|
||||||
dest+=0x2000;
|
dest+=0x2000;
|
||||||
|
|
||||||
block=nextblock;
|
if(block + saveLength != memcardSize)
|
||||||
|
{
|
||||||
|
int nextblock=bswap16(bat.Map[block-5]);
|
||||||
|
assert(nextblock>0);
|
||||||
|
block=nextblock;
|
||||||
|
}else block=0xffff;
|
||||||
}
|
}
|
||||||
while(block!=0xffff);
|
while(block!=0xffff);
|
||||||
|
|
||||||
|
@ -540,46 +559,38 @@ u32 GCMemcard::TestChecksums()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GCMemcard::FixChecksums()
|
||||||
// ==========================================================================================
|
|
||||||
// Fix checksums - I'll begin with fixing Directory and Directory backup. Feel free to add the
|
|
||||||
// other blocks.
|
|
||||||
// ------------------------------------------------------------------------------------------
|
|
||||||
u32 GCMemcard::FixChecksums()
|
|
||||||
{
|
{
|
||||||
if(!mcdFile) return 0xFFFFFFFF;
|
if(!mcdFile) return false;
|
||||||
|
|
||||||
u16 csum1=0,csum2=0;
|
u16 csum1=0,csum2=0;
|
||||||
|
|
||||||
u32 results = 0;
|
|
||||||
|
|
||||||
calc_checksumsBE((u16*)&dir,0xFFE,&csum1,&csum2);
|
calc_checksumsBE((u16*)&dir,0xFFE,&csum1,&csum2);
|
||||||
if(BE16(dir.CheckSum1) != csum1) results |= 2;
|
|
||||||
if(BE16(dir.CheckSum2) != csum2) results |= 2;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
|
||||||
// Save the values we just read
|
|
||||||
dir.CheckSum1[0]=u8(csum1>>8);
|
dir.CheckSum1[0]=u8(csum1>>8);
|
||||||
dir.CheckSum1[1]=u8(csum1);
|
dir.CheckSum1[1]=u8(csum1);
|
||||||
dir.CheckSum2[0]=u8(csum2>>8);
|
dir.CheckSum2[0]=u8(csum2>>8);
|
||||||
dir.CheckSum2[1]=u8(csum2);
|
dir.CheckSum2[1]=u8(csum2);
|
||||||
// ------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
calc_checksumsBE((u16*)&dir_backup,0xFFE,&csum1,&csum2);
|
calc_checksumsBE((u16*)&dir_backup,0xFFE,&csum1,&csum2);
|
||||||
if(BE16(dir_backup.CheckSum1) != csum1) results |= 4;
|
|
||||||
if(BE16(dir_backup.CheckSum2) != csum2) results |= 4;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
|
||||||
// Save the values we just read
|
|
||||||
dir_backup.CheckSum1[0]=u8(csum1>>8);
|
dir_backup.CheckSum1[0]=u8(csum1>>8);
|
||||||
dir_backup.CheckSum1[1]=u8(csum1);
|
dir_backup.CheckSum1[1]=u8(csum1);
|
||||||
dir_backup.CheckSum2[0]=u8(csum2>>8);
|
dir_backup.CheckSum2[0]=u8(csum2>>8);
|
||||||
dir_backup.CheckSum2[1]=u8(csum2);
|
dir_backup.CheckSum2[1]=u8(csum2);
|
||||||
// ------------------------------------------------------------------------------------------
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// ==========================================================================================
|
|
||||||
|
|
||||||
|
calc_checksumsBE((u16*)(((u8*)&bat)+4),0xFFE,&csum1,&csum2);
|
||||||
|
bat.CheckSum1[0]=u8(csum1>>8);
|
||||||
|
bat.CheckSum1[1]=u8(csum1);
|
||||||
|
bat.CheckSum2[0]=u8(csum2>>8);
|
||||||
|
bat.CheckSum2[1]=u8(csum2);
|
||||||
|
|
||||||
|
calc_checksumsBE((u16*)(((u8*)&bat_backup)+4),0xFFE,&csum1,&csum2);
|
||||||
|
bat_backup.CheckSum1[0]=u8(csum1>>8);
|
||||||
|
bat_backup.CheckSum1[1]=u8(csum1);
|
||||||
|
bat_backup.CheckSum2[0]=u8(csum2>>8);
|
||||||
|
bat_backup.CheckSum2[1]=u8(csum2);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
u32 GCMemcard::CopyFrom(GCMemcard& source, u32 index)
|
u32 GCMemcard::CopyFrom(GCMemcard& source, u32 index)
|
||||||
{
|
{
|
||||||
|
@ -598,6 +609,53 @@ u32 GCMemcard::CopyFrom(GCMemcard& source, u32 index)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 GCMemcard::AddGci(const char *fileName)
|
||||||
|
{
|
||||||
|
if(!mcdFile) return 0;
|
||||||
|
|
||||||
|
FILE *gci=fopen(fileName,"rb");
|
||||||
|
|
||||||
|
if(!gci) return 0;
|
||||||
|
|
||||||
|
DEntry *d = new DEntry;
|
||||||
|
fread(d,1,0x40,gci);
|
||||||
|
|
||||||
|
u32 size=BE16((d->BlockCount))*0x2000;
|
||||||
|
u8 *t = new u8[size];
|
||||||
|
fread(t,1,size,gci);
|
||||||
|
u32 ret = ImportFile(*d,t);
|
||||||
|
delete[] t;
|
||||||
|
delete d;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GCMemcard::SaveGci(u32 index, const char *fileName)
|
||||||
|
{
|
||||||
|
FILE *gci=fopen(fileName,"wb");
|
||||||
|
|
||||||
|
if(!gci) return false;
|
||||||
|
|
||||||
|
fseek(gci,0,SEEK_SET);
|
||||||
|
|
||||||
|
DEntry d;
|
||||||
|
if(!this->GetFileInfo(index,d)) return false;
|
||||||
|
fwrite(&d,1,0x40,gci);
|
||||||
|
|
||||||
|
u8 *t = new u8[this->GetFileSize(index)*0x2000];
|
||||||
|
|
||||||
|
if(!this->GetFileData(index,t)) return false;
|
||||||
|
|
||||||
|
int fileBlocks=BE16(d.BlockCount);
|
||||||
|
|
||||||
|
fseek(gci,0x40,SEEK_SET);
|
||||||
|
fwrite(t,1,0x2000*fileBlocks,gci);
|
||||||
|
|
||||||
|
fclose(gci);
|
||||||
|
delete[] t;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool GCMemcard::Save()
|
bool GCMemcard::Save()
|
||||||
{
|
{
|
||||||
if(!mcdFile) return false;
|
if(!mcdFile) return false;
|
||||||
|
@ -683,6 +741,7 @@ GCMemcard::GCMemcard(const char *filename)
|
||||||
|
|
||||||
fseek(mcd,0xa000,SEEK_SET);
|
fseek(mcd,0xa000,SEEK_SET);
|
||||||
|
|
||||||
|
assert(BE16(hdr.Size)!=0xFFFF);
|
||||||
mc_data_size=(((u32)BE16(hdr.Size)*16)-5)*0x2000;
|
mc_data_size=(((u32)BE16(hdr.Size)*16)-5)*0x2000;
|
||||||
mc_data = new u8[mc_data_size];
|
mc_data = new u8[mc_data_size];
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,20 @@
|
||||||
|
// Copyright (C) 2003-2008 Dolphin Project.
|
||||||
|
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
|
// This program 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 2.0 for more details.
|
||||||
|
|
||||||
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
|
// Official SVN repository and contact information can be found at
|
||||||
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
typedef unsigned char u8;
|
typedef unsigned char u8;
|
||||||
|
@ -128,8 +145,8 @@ public:
|
||||||
bool IsOpen();
|
bool IsOpen();
|
||||||
|
|
||||||
u32 TestChecksums();
|
u32 TestChecksums();
|
||||||
u32 FixChecksums();
|
bool FixChecksums();
|
||||||
|
|
||||||
// get number of file entries in the directory
|
// get number of file entries in the directory
|
||||||
u32 GetNumFiles();
|
u32 GetNumFiles();
|
||||||
|
|
||||||
|
@ -160,6 +177,12 @@ public:
|
||||||
// reads a save from another memcard, and imports the data into this memcard
|
// reads a save from another memcard, and imports the data into this memcard
|
||||||
u32 CopyFrom(GCMemcard& source, u32 index);
|
u32 CopyFrom(GCMemcard& source, u32 index);
|
||||||
|
|
||||||
|
// writes a .gci file to disk containing index
|
||||||
|
bool SaveGci(u32 index, const char* fileName);
|
||||||
|
|
||||||
|
// reads a .gci file and calls ImportFile
|
||||||
|
u32 AddGci(const char* fileName);
|
||||||
|
|
||||||
// reads the banner image
|
// reads the banner image
|
||||||
bool ReadBannerRGBA8(u32 index, u32* buffer);
|
bool ReadBannerRGBA8(u32 index, u32* buffer);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue