diff options
| author | gigaherz <gigaherz@gmail.com> | 2008-08-30 13:44:44 +0000 |
|---|---|---|
| committer | gigaherz <gigaherz@gmail.com> | 2008-08-30 13:44:44 +0000 |
| commit | 06f0b02ecda6654c5931a6482bb65daf3da18812 (patch) | |
| tree | 093074e8fbca153a939cd97b7b4af9e4c3551995 /Source/Core | |
| parent | 53afa1f90087999930ea8559bf8ddf3125e1391e (diff) | |
Fixed a few bugs with the memcard manager, and memcard classes:
- Now the GCMemcard class will use the backup dir/bat if the main one is outdated/corrupted.
- I fixed a few bugs in Delete. It still doesn't work, but at least it doesn't make the program crash.
I included a small changei n the sln so that debug/x64 builds use release/x64 njoy, this way there's no build errors annoying people trying to debug Dolphin. ;)
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@384 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/DolphinWX/src/MemcardManager.cpp | 10 | ||||
| -rw-r--r-- | Source/Core/DolphinWX/src/MemoryCards/GCMemcard.cpp | 108 | ||||
| -rw-r--r-- | Source/Core/DolphinWX/src/MemoryCards/GCMemcard.h | 2 |
3 files changed, 99 insertions, 21 deletions
diff --git a/Source/Core/DolphinWX/src/MemcardManager.cpp b/Source/Core/DolphinWX/src/MemcardManager.cpp index 66cb0b2733..94712114b9 100644 --- a/Source/Core/DolphinWX/src/MemcardManager.cpp +++ b/Source/Core/DolphinWX/src/MemcardManager.cpp @@ -32,11 +32,15 @@ END_EVENT_TABLE() CMemcardManager::CMemcardManager(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& position, const wxSize& size, long style)
: wxDialog(parent, id, title, position, size, style)
{
+ memoryCard[0]=NULL;
+ memoryCard[1]=NULL;
CreateGUIControls();
}
CMemcardManager::~CMemcardManager()
{
+ if(memoryCard[0]) delete memoryCard[0];
+ if(memoryCard[1]) delete memoryCard[1];
}
void CMemcardManager::CreateGUIControls()
@@ -135,7 +139,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) case ID_DELETERIGHT:
if(index1 != -1)
{
- memoryCard[1]->DeleteFile(index1);
+ memoryCard[1]->RemoveFile(index1);
memoryCard[1]->Save();
ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1);
}
@@ -143,7 +147,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) case ID_DELETELEFT:
if(index0 != -1)
{
- memoryCard[0]->DeleteFile(index0);
+ memoryCard[0]->RemoveFile(index0);
memoryCard[0]->Save();
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
}
@@ -153,6 +157,8 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) void CMemcardManager::ReloadMemcard(const char *fileName, int card)
{
+ if(memoryCard[card]) delete memoryCard[card];
+
// TODO: add error checking and banners/icons
memoryCard[card] = new GCMemcard(fileName);
diff --git a/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.cpp b/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.cpp index 877fe8e522..2baac40844 100644 --- a/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.cpp +++ b/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.cpp @@ -32,7 +32,7 @@ u32 GCMemcard::GetNumFiles() {
if(!mcdFile) return 0;
- for(int i=0;i<127;i++)
+ for(int i=0;i<126;i++)
{
if(BE32(dir.Dir[i].Gamecode)==0xFFFFFFFF)
return i;
@@ -40,7 +40,7 @@ u32 GCMemcard::GetNumFiles() return 127;
}
-bool GCMemcard::DeleteFile(u32 index) //index in the directory array
+bool GCMemcard::RemoveFile(u32 index) //index in the directory array
{
if(!mcdFile) return false;
@@ -71,17 +71,17 @@ bool GCMemcard::DeleteFile(u32 index) //index in the directory array while((block!=0xffff)&&(blocks_left>0));
//delete directory entry
- for(int i=index;i<126;i++)
+ for(int i=index;i<125;i++)
{
dir.Dir[i]=dir.Dir[i+1];
}
- memset(&(dir.Dir[126]),0xFF,sizeof(DEntry));
+ memset(&(dir.Dir[125]),0xFF,sizeof(DEntry));
//pack blocks to remove free space partitioning, assume no fragmentation.
u8 *mc_data2 = new u8[mc_data_size];
int firstFree=0;
- for(int i=0;i<127;i++)
+ for(int i=0;i<126;i++)
{
if(BE32(dir.Dir[i].Gamecode)==0xFFFFFFFF)
{
@@ -102,8 +102,8 @@ bool GCMemcard::DeleteFile(u32 index) //index in the directory array }
bat.Map[firstFree+bc-1] = 0xFFFF;
- dir.Dir[i].FirstBlock[0] = u8(firstFree>>8);
- dir.Dir[i].FirstBlock[1] = u8(firstFree);
+ dir.Dir[i].FirstBlock[0] = u8((firstFree+5)>>8);
+ dir.Dir[i].FirstBlock[1] = u8((firstFree+5));
firstFree += bc;
}
@@ -126,6 +126,11 @@ bool GCMemcard::DeleteFile(u32 index) //index in the directory array bat.FreeBlocks[0] = u8(freespace1>>8);
bat.FreeBlocks[1] = u8(freespace1);
+ // ... and update counter
+ int updateCtr = BE16(dir.UpdateCounter)+1;
+ dir.UpdateCounter[0] = u8(updateCtr>>8);
+ dir.UpdateCounter[1] = u8(updateCtr);
+
//fix checksums
u16 csum1=0,csum2=0;
calc_checksumsBE((u16*)&dir,0xFFE,&csum1,&csum2);
@@ -139,6 +144,9 @@ bool GCMemcard::DeleteFile(u32 index) //index in the directory array bat.CheckSum2[0]=u8(csum2>>8);
bat.CheckSum2[1]=u8(csum2);
+ dir_backup=dir;
+ bat_backup=bat;
+
return true;
}
@@ -167,7 +175,7 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents) }
int firstFree3 = 0;
- for(int i=0;i<127;i++)
+ for(int i=0;i<126;i++)
{
if(BE32(dir.Dir[i].Gamecode)==0xFFFFFFFF)
{
@@ -182,6 +190,12 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents) if(firstFree2 > firstFree1) firstFree1 = firstFree2;
if(firstFree3 > firstFree1) firstFree1 = firstFree3;
+ if(firstFree1>=126)
+ {
+ // TODO: show messagebox about the error
+ return 0;
+ }
+
// find first free dir entry
int index=-1;
for(int i=0;i<127;i++)
@@ -192,6 +206,7 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents) dir.Dir[i] = direntry;
dir.Dir[i].FirstBlock[0] = u8(firstFree1>>8);
dir.Dir[i].FirstBlock[1] = u8(firstFree1);
+ dir.Dir[i].CopyCounter = dir.Dir[i].CopyCounter+1;
break;
}
}
@@ -208,6 +223,11 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents) bat.FreeBlocks[0] = u8(freespace1>>8);
bat.FreeBlocks[1] = u8(freespace1);
+ // ... and update counter
+ int updateCtr = BE16(dir.UpdateCounter)+1;
+ dir.UpdateCounter[0] = u8(updateCtr>>8);
+ dir.UpdateCounter[1] = u8(updateCtr);
+
//fix checksums
u16 csum1=0,csum2=0;
calc_checksumsBE((u16*)&dir,0xFFE,&csum1,&csum2);
@@ -309,25 +329,27 @@ u32 GCMemcard::TestChecksums() u16 csum1=0,csum2=0;
+ u32 results = 0;
+
calc_checksumsBE((u16*)&hdr, 0xFE ,&csum1,&csum2);
- if(BE16(hdr.CheckSum1)!=csum1) return 1;
- if(BE16(hdr.CheckSum2)!=csum2) return 1;
+ if(BE16(hdr.CheckSum1)!=csum1) results |= 1;
+ if(BE16(hdr.CheckSum2)!=csum2) results |= 1;
calc_checksumsBE((u16*)&dir,0xFFE,&csum1,&csum2);
- if(BE16(dir.CheckSum1)!=csum1) return 2;
- if(BE16(dir.CheckSum2)!=csum2) return 2;
+ if(BE16(dir.CheckSum1)!=csum1) results |= 2;
+ if(BE16(dir.CheckSum2)!=csum2) results |= 2;
calc_checksumsBE((u16*)&dir_backup,0xFFE,&csum1,&csum2);
- if(BE16(dir_backup.CheckSum1)!=csum1) return 3;
- if(BE16(dir_backup.CheckSum2)!=csum2) return 3;
+ if(BE16(dir_backup.CheckSum1)!=csum1) results |= 4;
+ if(BE16(dir_backup.CheckSum2)!=csum2) results |= 4;
calc_checksumsBE((u16*)(((u8*)&bat)+4),0xFFE,&csum1,&csum2);
- if(BE16(bat.CheckSum1)!=csum1) return 4;
- if(BE16(bat.CheckSum2)!=csum2) return 4;
+ if(BE16(bat.CheckSum1)!=csum1) results |= 8;
+ if(BE16(bat.CheckSum2)!=csum2) results |= 8;
calc_checksumsBE((u16*)(((u8*)&bat_backup)+4),0xFFE,&csum1,&csum2);
- if(BE16(bat_backup.CheckSum1)!=csum1) return 5;
- if(BE16(bat_backup.CheckSum2)!=csum2) return 5;
+ if(BE16(bat_backup.CheckSum1)!=csum1) results |= 16;
+ if(BE16(bat_backup.CheckSum2)!=csum2) results |= 16;
return 0;
}
@@ -382,6 +404,56 @@ GCMemcard::GCMemcard(const char *filename) assert(fread(&bat, 1,0x2000,mcd)==0x2000);
assert(fread(&bat_backup,1,0x2000,mcd)==0x2000);
+ u32 csums = TestChecksums();
+
+ if(csums&1)
+ {
+ // header checksum error!
+ // TODO: fail to load
+ }
+
+ if(csums&2) // directory checksum error!
+ {
+ if(csums&4)
+ {
+ // backup is also wrong!
+ // TODO: fail to load
+ }
+ else
+ {
+ // backup is correct, restore
+ dir = dir_backup;
+ bat = bat_backup;
+
+ // update checksums
+ csums = TestChecksums();
+ }
+ }
+
+ if(csums&8) // BAT checksum error!
+ {
+ if(csums&16)
+ {
+ // backup is also wrong!
+ // TODO: fail to load
+ }
+ else
+ {
+ // backup is correct, restore
+ dir = dir_backup;
+ bat = bat_backup;
+
+ // update checksums
+ csums = TestChecksums();
+ }
+ }
+
+ if(BE16(dir_backup.UpdateCounter) > BE16(dir.UpdateCounter)) //check if the backup is newer
+ {
+ dir = dir_backup;
+ bat = bat_backup; // needed?
+ }
+
fseek(mcd,0xa000,SEEK_SET);
mc_data_size=(((u32)BE16(hdr.Size)*16)-5)*0x2000;
diff --git a/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.h b/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.h index 94cfe96b34..c9ae243a61 100644 --- a/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.h +++ b/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.h @@ -146,7 +146,7 @@ public: bool GetFileData(u32 index, u8* buffer);
// delete a file from the directory
- bool DeleteFile(u32 index);
+ bool RemoveFile(u32 index);
// adds the file to the directory and copies its contents
u32 ImportFile(DEntry& direntry, u8* contents);
|
