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
This commit is contained in:
gigaherz 2008-08-30 13:44:44 +00:00
parent 53afa1f900
commit 06f0b02ecd
4 changed files with 101 additions and 23 deletions

View File

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

View File

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

View File

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

View File

@ -277,8 +277,8 @@ Global
{805B34AA-82A5-4875-8DC7-3C85BDC0BCEE}.Release|x64.Build.0 = Release|x64
{521498BE-6089-4780-8223-E67C22F4E068}.Debug|Win32.ActiveCfg = Debug|Win32
{521498BE-6089-4780-8223-E67C22F4E068}.Debug|Win32.Build.0 = Debug|Win32
{521498BE-6089-4780-8223-E67C22F4E068}.Debug|x64.ActiveCfg = Debug|x64
{521498BE-6089-4780-8223-E67C22F4E068}.Debug|x64.Build.0 = Debug|x64
{521498BE-6089-4780-8223-E67C22F4E068}.Debug|x64.ActiveCfg = Release|x64
{521498BE-6089-4780-8223-E67C22F4E068}.Debug|x64.Build.0 = Release|x64
{521498BE-6089-4780-8223-E67C22F4E068}.DebugFast|Win32.ActiveCfg = DebugFast|Win32
{521498BE-6089-4780-8223-E67C22F4E068}.DebugFast|Win32.Build.0 = DebugFast|Win32
{521498BE-6089-4780-8223-E67C22F4E068}.DebugFast|x64.ActiveCfg = DebugFast|x64