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:
Shawn Hoffman 2008-10-12 06:09:52 +00:00
parent 3763b365d1
commit 633881eb7a
4 changed files with 308 additions and 125 deletions

View File

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

View File

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

View File

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

View File

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