Wrapped fopen/close/read/write functions inside a simple "IOFile" class. Reading, writing, and error checking became simpler in most cases. It should be near impossible to forget to close a file now that the destructor takes care of it. (I hope this fixes Issue 3635) I have tested the functionality of most things, but it is possible I broke something. :p

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7328 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Jordan Woyak
2011-03-11 10:21:46 +00:00
parent 4f69672b2b
commit 59fd1008ca
68 changed files with 1112 additions and 1154 deletions

View File

@ -62,31 +62,28 @@ void decodeCI8image(u32* dst, u8* src, u16* pal, int width, int height)
}
GCMemcard::GCMemcard(const char *filename)
{
FILE *mcd = fopen(filename, "r+b");
mcdFile = mcd;
{
mcdFile.Open(filename, "r+b");
fail = false;
if (!mcd)
if (!mcdFile)
{
if (!AskYesNoT("\"%s\" does not exist.\n Create a new 16MB Memcard?", filename))
{
fail = true;
return;
}
mcd = fopen(filename, "wb");
if (!mcd)
mcdFile.Open(filename, "wb");
if (!mcdFile)
{
fail = true;
return;
}
mcdFile = mcd;
Format(!AskYesNoT("Format as ascii (NTSC\\PAL)?\nChoose no for sjis (NTSC-J)"));
fclose(mcd);
mcd = fopen(filename, "r+b");
mcdFile.Open(filename, "r+b");
}
else
{
//This function can be removed once more about hdr is known and we can check for a valid header
//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"))
@ -97,41 +94,39 @@ GCMemcard::GCMemcard(const char *filename)
}
}
fseeko(mcd, 0, SEEK_SET);
if (fread(&hdr, 1, BLOCK_SIZE, mcd) != BLOCK_SIZE)
mcdFile.Seek(0, SEEK_SET);
fail = true;
if (!mcdFile.ReadBytes(&hdr, BLOCK_SIZE))
{
fail = true;
PanicAlertT("Failed to read header correctly\n(0x0000-0x1FFF)");
return;
}
if (fread(&dir, 1, BLOCK_SIZE, mcd) != BLOCK_SIZE)
else if (!mcdFile.ReadBytes(&dir, BLOCK_SIZE))
{
fail = true;
PanicAlertT("Failed to read directory correctly\n(0x2000-0x3FFF)");
return;
}
if (fread(&dir_backup, 1, BLOCK_SIZE, mcd) != BLOCK_SIZE)
else if (!mcdFile.ReadBytes(&dir_backup, BLOCK_SIZE))
{
fail = true;
PanicAlertT("Failed to read directory backup correctly\n(0x4000-0x5FFF)");
return;
}
if (fread(&bat, 1, BLOCK_SIZE, mcd) != BLOCK_SIZE)
else if (!mcdFile.ReadBytes(&bat, BLOCK_SIZE))
{
fail = true;
PanicAlertT("Failed to read block allocation table correctly\n(0x6000-0x7FFF)");
return;
}
if (fread(&bat_backup, 1, BLOCK_SIZE, mcd) != BLOCK_SIZE)
else if (!mcdFile.ReadBytes(&bat_backup, BLOCK_SIZE))
{
fail = true;
PanicAlertT("Failed to read block allocation table backup correctly\n(0x8000-0x9FFF)");
return;
}
else
fail = false;
u32 csums = TestChecksums();
if (csums&1)
if (csums & 0x1)
{
// header checksum error!
// invalid files do not always get here
@ -140,9 +135,9 @@ GCMemcard::GCMemcard(const char *filename)
return;
}
if (csums&2) // directory checksum error!
if (csums & 0x2) // directory checksum error!
{
if (csums&4)
if (csums & 0x4)
{
// backup is also wrong!
fail = true;
@ -160,9 +155,9 @@ GCMemcard::GCMemcard(const char *filename)
}
}
if (csums&8) // BAT checksum error!
if (csums & 0x8) // BAT checksum error!
{
if (csums&16)
if (csums & 0x10)
{
// backup is also wrong!
fail = true;
@ -188,7 +183,7 @@ GCMemcard::GCMemcard(const char *filename)
// bat = bat_backup; // needed?
}
fseeko(mcd, 0xa000, SEEK_SET);
mcdFile.Seek(0xa000, SEEK_SET);
u16 sizeMb = BE16(hdr.SizeMb);
switch (sizeMb)
@ -204,8 +199,7 @@ GCMemcard::GCMemcard(const char *filename)
mc_data_size = (maxBlock - MC_FST_BLOCKS) * BLOCK_SIZE;
mc_data = new u8[mc_data_size];
size_t read = fread(mc_data, 1, mc_data_size, mcd);
if (mc_data_size != read)
if (!mcdFile.ReadBytes(mc_data, mc_data_size))
{
fail = true;
PanicAlertT("Failed to read save data\n(0xA000-)\nMemcard may be truncated");
@ -218,15 +212,9 @@ GCMemcard::GCMemcard(const char *filename)
}
}
GCMemcard::~GCMemcard()
{
if (!mcdFile) return;
fclose((FILE*)mcdFile);
}
bool GCMemcard::IsOpen()
{
return (mcdFile!=NULL);
return mcdFile.IsOpen();
}
bool GCMemcard::IsAsciiEncoding()
@ -236,16 +224,16 @@ bool GCMemcard::IsAsciiEncoding()
bool GCMemcard::Save()
{
bool completeWrite = true;
FILE *mcd=(FILE*)mcdFile;
fseeko(mcd, 0, SEEK_SET);
if (fwrite(&hdr, 1, BLOCK_SIZE, mcd) != BLOCK_SIZE) completeWrite = false;
if (fwrite(&dir, 1, BLOCK_SIZE, mcd) != BLOCK_SIZE) completeWrite = false;
if (fwrite(&dir_backup, 1, BLOCK_SIZE, mcd) != BLOCK_SIZE) completeWrite = false;
if (fwrite(&bat, 1, BLOCK_SIZE ,mcd) != BLOCK_SIZE) completeWrite = false;
if (fwrite(&bat_backup, 1, BLOCK_SIZE, mcd) != BLOCK_SIZE) completeWrite = false;
if (fwrite(mc_data, 1, mc_data_size, mcd) != mc_data_size) completeWrite = false;
return completeWrite;
mcdFile.Seek(0, SEEK_SET);
mcdFile.WriteBytes(&hdr, BLOCK_SIZE);
mcdFile.WriteBytes(&dir, BLOCK_SIZE);
mcdFile.WriteBytes(&dir_backup, BLOCK_SIZE);
mcdFile.WriteBytes(&bat, BLOCK_SIZE);
mcdFile.WriteBytes(&bat_backup, BLOCK_SIZE);
mcdFile.WriteBytes(mc_data, mc_data_size);
return mcdFile.IsGood();
}
void GCMemcard::calc_checksumsBE(u16 *buf, u32 num, u16 *c1, u16 *c2)
@ -269,7 +257,8 @@ void GCMemcard::calc_checksumsBE(u16 *buf, u32 num, u16 *c1, u16 *c2)
u32 GCMemcard::TestChecksums()
{
if (!mcdFile) return 0xFFFFFFFF;
if (!mcdFile)
return 0xFFFFFFFF;
u16 csum1=0,
csum2=0;
@ -296,12 +285,13 @@ u32 GCMemcard::TestChecksums()
if (BE16(bat_backup.CheckSum1) != csum1) results |= 16;
if (BE16(bat_backup.CheckSum2) != csum2) results |= 16;
return 0;
return results;
}
bool GCMemcard::FixChecksums()
{
if (!mcdFile) return false;
if (!mcdFile)
return false;
u16 csum1=0,
csum2=0;
@ -341,7 +331,9 @@ bool GCMemcard::FixChecksums()
u8 GCMemcard::GetNumFiles()
{
if (!mcdFile) return 0;
if (!mcdFile)
return 0;
u8 j = 0;
for (int i = 0; i < DIRLEN; i++)
{
@ -353,13 +345,16 @@ u8 GCMemcard::GetNumFiles()
u16 GCMemcard::GetFreeBlocks()
{
if (!mcdFile) return 0;
if (!mcdFile)
return 0;
return BE16(bat.FreeBlocks);
}
u8 GCMemcard::TitlePresent(DEntry d)
{
if (!mcdFile) return DIRLEN;
if (!mcdFile)
return DIRLEN;
u8 i = 0;
while(i < DIRLEN)
@ -379,7 +374,8 @@ u8 GCMemcard::TitlePresent(DEntry d)
bool GCMemcard::DEntry_GameCode(u8 index, char *buffer)
{
if (!mcdFile) return false;
if (!mcdFile)
return false;
memcpy(buffer, dir.Dir[index].Gamecode, 4);
buffer[4] = 0;
@ -388,14 +384,17 @@ bool GCMemcard::DEntry_GameCode(u8 index, char *buffer)
bool GCMemcard::DEntry_Markercode(u8 index, char *buffer)
{
if (!mcdFile) return false;
if (!mcdFile)
return false;
memcpy(buffer, dir.Dir[index].Markercode, 2);
buffer[2] = 0;
return true;
}
bool GCMemcard::DEntry_BIFlags(u8 index, char *buffer)
{
if (!mcdFile) return false;
if (!mcdFile)
return false;
int x = dir.Dir[index].BIFlags;
for (int i = 0; i < 8; i++)
@ -409,7 +408,9 @@ bool GCMemcard::DEntry_BIFlags(u8 index, char *buffer)
bool GCMemcard::DEntry_FileName(u8 index, char *buffer)
{
if (!mcdFile) return false;
if (!mcdFile)
return false;
memcpy (buffer, (const char*)dir.Dir[index].Filename, DENTRY_STRLEN);
buffer[31] = 0;
return true;
@ -463,7 +464,9 @@ u8 GCMemcard::DEntry_CopyCounter(u8 index)
u16 GCMemcard::DEntry_FirstBlock(u8 index)
{
if (!mcdFile) return 0xFFFF;
if (!mcdFile)
return 0xFFFF;
u16 block = BE16(dir.Dir[index].FirstBlock);
if (block > (u16) maxBlock) return 0xFFFF;
return block;
@ -471,7 +474,8 @@ u16 GCMemcard::DEntry_FirstBlock(u8 index)
u16 GCMemcard::DEntry_BlockCount(u8 index)
{
if (!mcdFile) return 0xFFFF;
if (!mcdFile)
return 0xFFFF;
u16 blocks = BE16(dir.Dir[index].BlockCount);
if (blocks > (u16) maxBlock) return 0xFFFF;
@ -485,7 +489,8 @@ u32 GCMemcard::DEntry_CommentsAddress(u8 index)
bool GCMemcard::DEntry_Comment1(u8 index, char* buffer)
{
if (!mcdFile) return false;
if (!mcdFile)
return false;
u32 Comment1 = BE32(dir.Dir[index].CommentsAddr);
u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - MC_FST_BLOCKS;
@ -501,7 +506,8 @@ bool GCMemcard::DEntry_Comment1(u8 index, char* buffer)
bool GCMemcard::DEntry_Comment2(u8 index, char* buffer)
{
if (!mcdFile) return false;
if (!mcdFile)
return false;
u32 Comment1 = BE32(dir.Dir[index].CommentsAddr);
u32 Comment2 = Comment1 + DENTRY_STRLEN;
@ -518,7 +524,8 @@ bool GCMemcard::DEntry_Comment2(u8 index, char* buffer)
bool GCMemcard::DEntry_Copy(u8 index, GCMemcard::DEntry& info)
{
if (!mcdFile) return false;
if (!mcdFile)
return false;
info = dir.Dir[index];
return true;
@ -526,7 +533,8 @@ bool GCMemcard::DEntry_Copy(u8 index, GCMemcard::DEntry& info)
u32 GCMemcard::DEntry_GetSaveData(u8 index, u8* dest, bool old)
{
if (!mcdFile) return NOMEMCARD;
if (!mcdFile)
return NOMEMCARD;
u16 block = DEntry_FirstBlock(index);
u16 saveLength = DEntry_BlockCount(index);
@ -564,7 +572,8 @@ u32 GCMemcard::DEntry_GetSaveData(u8 index, u8* dest, bool old)
u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents, int remove)
{
if (!mcdFile) return NOMEMCARD;
if (!mcdFile)
return NOMEMCARD;
if (GetNumFiles() >= DIRLEN)
{
@ -665,7 +674,8 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents, int remove)
u32 GCMemcard::RemoveFile(u8 index) //index in the directory array
{
if (!mcdFile) return NOMEMCARD;
if (!mcdFile)
return NOMEMCARD;
//error checking
u16 startingblock = 0;
@ -747,7 +757,8 @@ u32 GCMemcard::RemoveFile(u8 index) //index in the directory array
u32 GCMemcard::CopyFrom(GCMemcard& source, u8 index)
{
if (!mcdFile) return NOMEMCARD;
if (!mcdFile)
return NOMEMCARD;
DEntry tempDEntry;
if (!source.DEntry_Copy(index, tempDEntry)) return NOMEMCARD;
@ -773,18 +784,19 @@ u32 GCMemcard::CopyFrom(GCMemcard& source, u8 index)
u32 GCMemcard::ImportGci(const char *inputFile, std::string outputFile)
{
if (outputFile.empty() && !mcdFile) return OPENFAIL;
if (outputFile.empty() && !mcdFile)
return OPENFAIL;
FILE *gci = fopen(inputFile, "rb");
if (!gci) return OPENFAIL;
File::IOFile gci(inputFile, "rb");
if (!gci)
return OPENFAIL;
u32 result = ImportGciInternal(gci, inputFile, outputFile);
fclose(gci);
u32 result = ImportGciInternal(gci.ReleaseHandle(), inputFile, outputFile);
return result;
}
u32 GCMemcard::ImportGciInternal(FILE *gci, const char *inputFile, std::string outputFile)
u32 GCMemcard::ImportGciInternal(File::IOFile gci, const char *inputFile, std::string outputFile)
{
int offset;
char tmp[0xD];
@ -795,7 +807,7 @@ u32 GCMemcard::ImportGciInternal(FILE *gci, const char *inputFile, std::string o
offset = GCI;
else
{
fread(tmp, 1, 0xD, gci);
gci.ReadBytes(tmp, 0xD);
if (!strcasecmp(fileType.c_str(), ".gcs"))
{
if (!memcmp(tmp, "GCSAVE", 6)) // Header must be uppercase
@ -813,29 +825,29 @@ u32 GCMemcard::ImportGciInternal(FILE *gci, const char *inputFile, std::string o
else
return OPENFAIL;
}
fseeko(gci, offset, SEEK_SET);
gci.Seek(offset, SEEK_SET);
DEntry *tempDEntry = new DEntry;
fread(tempDEntry, 1, DENTRY_SIZE, gci);
int fStart = (int) ftello(gci);
fseeko(gci, 0, SEEK_END);
int length = (int) ftello(gci) - fStart;
fseeko(gci, offset + DENTRY_SIZE, SEEK_SET);
gci.ReadBytes(tempDEntry, DENTRY_SIZE);
const int fStart = (int)gci.Tell();
gci.Seek(0, SEEK_END);
const int length = (int)gci.Tell() - fStart;
gci.Seek(offset + DENTRY_SIZE, SEEK_SET);
Gcs_SavConvert(tempDEntry, offset, length);
if (length != BE16(tempDEntry->BlockCount) * BLOCK_SIZE)
return LENGTHFAIL;
if (ftello(gci) != offset + DENTRY_SIZE) // Verify correct file position
if (gci.Tell() != offset + DENTRY_SIZE) // Verify correct file position
return OPENFAIL;
u32 size = BE16((tempDEntry->BlockCount)) * BLOCK_SIZE;
u8 *tempSaveData = new u8[size];
fread(tempSaveData, 1, size, gci);
gci.ReadBytes(tempSaveData, size);
u32 ret;
if(!outputFile.empty())
if (!outputFile.empty())
{
FILE *gci2 = fopen(outputFile.c_str(), "wb");
File::IOFile gci2(outputFile, "wb");
bool completeWrite = true;
if (!gci2)
{
@ -843,18 +855,19 @@ u32 GCMemcard::ImportGciInternal(FILE *gci, const char *inputFile, std::string o
delete tempDEntry;
return OPENFAIL;
}
fseeko(gci2, 0, SEEK_SET);
gci2.Seek(0, SEEK_SET);
if (fwrite(tempDEntry, 1, DENTRY_SIZE, gci2) != DENTRY_SIZE)
if (!gci2.WriteBytes(tempDEntry, DENTRY_SIZE))
completeWrite = false;
int fileBlocks = BE16(tempDEntry->BlockCount);
fseeko(gci2, DENTRY_SIZE, SEEK_SET);
gci2.Seek(DENTRY_SIZE, SEEK_SET);
if (fwrite(tempSaveData, 1, BLOCK_SIZE * fileBlocks, gci2) != (unsigned)(BLOCK_SIZE * fileBlocks))
if (!gci2.WriteBytes(tempSaveData, BLOCK_SIZE * fileBlocks))
completeWrite = false;
fclose(gci2);
if (completeWrite) ret = GCS;
else ret = WRITEFAIL;
if (completeWrite)
ret = GCS;
else
ret = WRITEFAIL;
}
else
ret = ImportFile(*tempDEntry, tempSaveData, 0);
@ -866,7 +879,7 @@ u32 GCMemcard::ImportGciInternal(FILE *gci, const char *inputFile, std::string o
u32 GCMemcard::ExportGci(u8 index, const char *fileName, std::string *fileName2)
{
FILE *gci;
File::IOFile gci;
int offset = GCI;
if (!strcasecmp(fileName, "."))
{
@ -879,12 +892,12 @@ u32 GCMemcard::ExportGci(u8 index, const char *fileName, std::string *fileName2)
DEntry_GameCode(index, GameCode);
sprintf(filename, "%s/%s_%s.gci", fileName2->c_str(), GameCode, dir.Dir[index].Filename);
gci = fopen((const char *)filename, "wb");
gci.Open(filename, "wb");
delete[] filename;
}
else
{
gci = fopen(fileName, "wb");
gci.Open(fileName, "wb");
std::string fileType;
SplitPath(fileName, NULL, NULL, &fileType);
@ -898,10 +911,10 @@ u32 GCMemcard::ExportGci(u8 index, const char *fileName, std::string *fileName2)
}
}
if (!gci) return OPENFAIL;
bool completeWrite = true;
if (!gci)
return OPENFAIL;
fseeko(gci, 0, SEEK_SET);
gci.Seek(0, SEEK_SET);
switch(offset)
{
@ -909,54 +922,54 @@ u32 GCMemcard::ExportGci(u8 index, const char *fileName, std::string *fileName2)
u8 gcsHDR[GCS];
memset(gcsHDR, 0, GCS);
memcpy(gcsHDR, "GCSAVE", 6);
if (fwrite(gcsHDR, 1, GCS, gci) != GCS) completeWrite = false;
gci.WriteArray(gcsHDR, GCS);
break;
case SAV:
u8 savHDR[SAV];
memset(savHDR, 0, SAV);
memcpy(savHDR, "DATELGC_SAVE", 0xC);
if (fwrite(savHDR, 1, SAV, gci) != SAV) completeWrite = false;
gci.WriteArray(savHDR, SAV);
break;
}
DEntry tempDEntry;
if (!DEntry_Copy(index, tempDEntry))
{
fclose(gci);
return NOMEMCARD;
}
Gcs_SavConvert(&tempDEntry, offset);
if (fwrite(&tempDEntry, 1, DENTRY_SIZE, gci) != DENTRY_SIZE) completeWrite = false;
gci.WriteBytes(&tempDEntry, DENTRY_SIZE);
u32 size = DEntry_BlockCount(index);
if (size == 0xFFFF)
{
fclose(gci);
return FAIL;
}
size *= BLOCK_SIZE;
u8 *tempSaveData = new u8[size];
switch(DEntry_GetSaveData(index, tempSaveData, true))
{
case FAIL:
fclose(gci);
delete[] tempSaveData;
return FAIL;
case NOMEMCARD:
fclose(gci);
delete[] tempSaveData;
return NOMEMCARD;
}
fseeko(gci, DENTRY_SIZE + offset, SEEK_SET);
if (fwrite(tempSaveData, 1, size, gci) != size)
completeWrite = false;
fclose(gci);
gci.Seek(DENTRY_SIZE + offset, SEEK_SET);
gci.WriteBytes(tempSaveData, size);
delete[] tempSaveData;
if (completeWrite) return SUCCESS;
else return WRITEFAIL;
if (gci.IsGood())
return SUCCESS;
else
return WRITEFAIL;
}
void GCMemcard::Gcs_SavConvert(DEntry* tempDEntry, int saveType, int length)
@ -999,7 +1012,8 @@ void GCMemcard::Gcs_SavConvert(DEntry* tempDEntry, int saveType, int length)
bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer)
{
if (!mcdFile) return false;
if (!mcdFile)
return false;
int flags = dir.Dir[index].BIFlags;
// Timesplitters 2 is the only game that I see this in
@ -1039,7 +1053,8 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer)
u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays)
{
if (!mcdFile) return 0;
if (!mcdFile)
return 0;
// To ensure only one type of icon is used
// Sonic Heroes it the only game I have seen that tries to use a CI8 and RGB5A3 icon
@ -1137,12 +1152,10 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays)
bool GCMemcard::Format(bool sjis, bool New, int slot, u16 SizeMb, bool hdrOnly)
{
//Currently only formats cards for slot A
u32 data_size = BLOCK_SIZE * (SizeMb * MBIT_TO_BLOCKS - MC_FST_BLOCKS);
// Currently only formats cards for slot A
const u32 data_size = BLOCK_SIZE * (SizeMb * MBIT_TO_BLOCKS - MC_FST_BLOCKS);
SRAM m_SRAM;
FILE * pStream;
u64 time, rand;
if (New)
{
@ -1152,18 +1165,19 @@ bool GCMemcard::Format(bool sjis, bool New, int slot, u16 SizeMb, bool hdrOnly)
// Only Format 16MB memcards for now
if ((SizeMb != MemCard2043Mb) || (data_size != mc_data_size)) return false;
pStream = fopen(File::GetUserPath(F_GCSRAM_IDX).c_str(), "rb");
File::IOFile pStream(File::GetUserPath(F_GCSRAM_IDX), "rb");
if (pStream)
{
fread(&m_SRAM, 1, 64, pStream);
fclose(pStream);
pStream.ReadBytes(&m_SRAM, 64);
pStream.Close();
}
else
{
m_SRAM = sram_dump;
}
time = CEXIIPL::GetGCTime();
rand = Common::swap64(time);
const u64 time = CEXIIPL::GetGCTime();
u64 rand = Common::swap64(time);
memset(&hdr, 0xFF, BLOCK_SIZE);
for(int i = 0; i < 12; i++)
@ -1203,4 +1217,3 @@ bool GCMemcard::Format(bool sjis, bool New, int slot, u16 SizeMb, bool hdrOnly)
Save();
return true;
}

View File

@ -71,7 +71,7 @@ class GCMemcard
{
private:
friend class CMemcardManagerDebug;
void* mcdFile;
File::IOFile mcdFile;
u32 maxBlock;
u32 mc_data_size;
@ -167,12 +167,8 @@ private:
public:
bool fail;
// constructor
GCMemcard(const char* fileName);
// destructor
~GCMemcard();
bool IsOpen();
bool IsAsciiEncoding();
bool Save();
@ -232,7 +228,7 @@ public:
// if remove > 0 it will pad bat.map with 0's sizeof remove
u32 ImportFile(DEntry& direntry, u8* contents, int remove);
private:
u32 ImportGciInternal(FILE *gci, const char *inputFile, std::string outputFile);
u32 ImportGciInternal(File::IOFile gci, const char *inputFile, std::string outputFile);
public:
// delete a file from the directory

View File

@ -86,20 +86,20 @@ CWiiSaveCrypted::CWiiSaveCrypted(const char* FileName, u64 title)
void CWiiSaveCrypted::ReadHDR()
{
fpData_bin = fopen(pathData_bin, "rb");
File::IOFile fpData_bin(pathData_bin, "rb");
if (!fpData_bin)
{
PanicAlertT("Cannot open %s", pathData_bin);
b_valid = false;
return;
}
if (fread(&_encryptedHeader, HEADER_SZ, 1, fpData_bin) != 1)
if (!fpData_bin.ReadBytes(&_encryptedHeader, HEADER_SZ))
{
PanicAlertT("failed to read header");
b_valid = false;
return;
}
fclose(fpData_bin);
fpData_bin.Close();
AES_cbc_encrypt((const u8*)&_encryptedHeader, (u8*)&_header, HEADER_SZ, &m_AES_KEY, SD_IV, AES_DECRYPT);
_bannerSize = Common::swap32(_header.hdr.BannerSize);
@ -129,12 +129,8 @@ void CWiiSaveCrypted::ReadHDR()
if (!File::Exists(pathBanner_bin) || AskYesNoT("%s already exists, overwrite?", pathBanner_bin))
{
INFO_LOG(CONSOLE, "creating file %s", pathBanner_bin);
fpBanner_bin = fopen(pathBanner_bin, "wb");
if (fpBanner_bin)
{
fwrite(_header.BNR, _bannerSize, 1, fpBanner_bin);
fclose(fpBanner_bin);
}
File::IOFile fpBanner_bin(pathBanner_bin, "wb");
fpBanner_bin.WriteBytes(_header.BNR, _bannerSize);
}
}
@ -149,31 +145,24 @@ void CWiiSaveCrypted::WriteHDR()
memcpy(_header.hdr.Md5, MD5_BLANKER, 0x10);
_header.hdr.Permissions = 0x3C;//0x35;
fpBanner_bin = fopen(pathBanner_bin, "rb");
if (fpBanner_bin)
File::IOFile fpBanner_bin(pathBanner_bin, "rb");
if (!fpBanner_bin.ReadBytes(_header.BNR, Common::swap32(_header.hdr.BannerSize)))
{
if (fread(_header.BNR, Common::swap32(_header.hdr.BannerSize), 1, fpBanner_bin) != 1)
{
PanicAlertT("Failed to read banner.bin");
b_valid = false;
return;
}
fclose(fpBanner_bin);
PanicAlertT("Failed to read banner.bin");
b_valid = false;
return;
}
md5((u8*)&_header, HEADER_SZ, md5_calc);
memcpy(_header.hdr.Md5, md5_calc, 0x10);
AES_cbc_encrypt((const unsigned char *)&_header, (u8*)&_encryptedHeader, HEADER_SZ, &m_AES_KEY, SD_IV, AES_ENCRYPT);
fpData_bin = fopen(pathData_bin, "wb");
if (fpData_bin)
File::IOFile fpData_bin(pathData_bin, "wb");
if (!fpData_bin.WriteBytes(&_encryptedHeader, HEADER_SZ))
{
if (fwrite(&_encryptedHeader, HEADER_SZ, 1, fpData_bin) != 1)
{
PanicAlertT("Failed to write header for %s", pathData_bin);
b_valid = false;
}
fclose(fpData_bin);
PanicAlertT("Failed to write header for %s", pathData_bin);
b_valid = false;
}
}
@ -183,21 +172,21 @@ void CWiiSaveCrypted::ReadBKHDR()
{
if (!b_valid) return;
fpData_bin = fopen(pathData_bin, "rb");
File::IOFile fpData_bin(pathData_bin, "rb");
if (!fpData_bin)
{
PanicAlertT("Cannot open %s", pathData_bin);
b_valid = false;
return;
}
fseeko(fpData_bin, HEADER_SZ, SEEK_SET);
if (fread(&bkhdr, BK_SZ, 1, fpData_bin) != 1)
fpData_bin.Seek(HEADER_SZ, SEEK_SET);
if (!fpData_bin.ReadBytes(&bkhdr, BK_SZ))
{
PanicAlertT("failed to read bk header");
b_valid = false;
return;
}
fclose(fpData_bin);
fpData_bin.Close();
if (bkhdr.size != Common::swap32(BK_LISTED_SZ) ||
bkhdr.magic != Common::swap32(BK_HDR_MAGIC))
@ -215,8 +204,6 @@ void CWiiSaveCrypted::ReadBKHDR()
WARN_LOG(CONSOLE, "Size(%x) + cert(%x) does not equal totalsize(%x)", _sizeOfFiles, FULL_CERT_SZ, _totalSize);
if (_saveGameTitle != Common::swap64(bkhdr.SaveGameTitle))
WARN_LOG(CONSOLE, "encrypted title (%llx) does not match unencrypted title (%llx)", _saveGameTitle, Common::swap64(bkhdr.SaveGameTitle));
}
void CWiiSaveCrypted::WriteBKHDR()
@ -241,15 +228,11 @@ void CWiiSaveCrypted::WriteBKHDR()
//
memcpy(bkhdr.MACaddress, MAC, 6);
fpData_bin = fopen(pathData_bin, "ab");
if(fpData_bin)
File::IOFile fpData_bin(pathData_bin, "ab");
if (!fpData_bin.WriteBytes(&bkhdr, BK_SZ))
{
if (fwrite(&bkhdr, BK_SZ, 1, fpData_bin) != 1)
{
PanicAlertT("Failed to write bkhdr");
b_valid = false;
}
fclose(fpData_bin);
PanicAlertT("Failed to write bkhdr");
b_valid = false;
}
}
@ -257,7 +240,7 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
{
if (!b_valid) return;
fpData_bin = fopen(pathData_bin, "rb");
File::IOFile fpData_bin(pathData_bin, "rb");
if (!fpData_bin)
{
PanicAlertT("Cannot open %s", pathData_bin);
@ -272,19 +255,19 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
for(u32 i = 0; i < _numberOfFiles; i++)
{
fseeko(fpData_bin, lastpos, SEEK_SET);
fpData_bin.Seek(lastpos, SEEK_SET);
memset(&_tmpFileHDR, 0, FILE_HDR_SZ);
memset(IV, 0, 0x10);
_fileSize = 0;
if (fread(&_tmpFileHDR, FILE_HDR_SZ, 1, fpData_bin) != 1)
if (!fpData_bin.ReadBytes(&_tmpFileHDR, FILE_HDR_SZ))
{
PanicAlertT("Failed to write header for file %d", i);
b_valid = false;
}
lastpos += FILE_HDR_SZ;
if(Common::swap32(_tmpFileHDR.magic) != FILE_HDR_MAGIC)
if (Common::swap32(_tmpFileHDR.magic) != FILE_HDR_MAGIC)
{
PanicAlertT("Bad File Header");
break;
@ -306,7 +289,7 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
lastpos += ROUND_UP(_fileSize, BLOCK_SZ);
_encryptedData = new u8[_fileSize];
_data = new u8[_fileSize];
if (fread(_encryptedData, _fileSize, 1, fpData_bin) != 1)
if (!fpData_bin.ReadBytes(_encryptedData, _fileSize))
{
PanicAlertT("Failed to read data from file %d", i);
b_valid = false;
@ -322,19 +305,13 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
{
INFO_LOG(CONSOLE, "creating file %s", pathRawSave);
fpRawSaveFile = fopen(pathRawSave, "wb");
if (fpRawSaveFile)
{
fwrite(_data, _fileSize, 1, fpRawSaveFile);
fclose(fpRawSaveFile);
}
File::IOFile fpRawSaveFile(pathRawSave, "wb");
fpRawSaveFile.WriteBytes(_data, _fileSize);
}
delete []_data;
}
}
}
fclose(fpData_bin);
}
void CWiiSaveCrypted::ExportWiiSaveFiles()
@ -381,11 +358,9 @@ void CWiiSaveCrypted::ExportWiiSaveFiles()
}
strncpy((char *)tmpFileHDR.name, __name.c_str(), __name.length());
fpData_bin = fopen(pathData_bin, "ab");
if (fpData_bin)
{
fwrite(&tmpFileHDR, FILE_HDR_SZ, 1, fpData_bin);
fclose(fpData_bin);
File::IOFile fpData_bin(pathData_bin, "ab");
fpData_bin.WriteBytes(&tmpFileHDR, FILE_HDR_SZ);
}
if (tmpFileHDR.type == 1)
@ -396,7 +371,7 @@ void CWiiSaveCrypted::ExportWiiSaveFiles()
b_valid = false;
return;
}
fpRawSaveFile = fopen(FilesList[i].c_str(), "rb");
File::IOFile fpRawSaveFile(FilesList[i], "rb");
if (!fpRawSaveFile)
{
PanicAlertT("%s failed to open", FilesList[i].c_str());
@ -405,20 +380,17 @@ void CWiiSaveCrypted::ExportWiiSaveFiles()
__data = new u8[_roundedfileSize];
__ENCdata = new u8[_roundedfileSize];
memset(__data, 0, _roundedfileSize);
if (fread(__data, _fileSize, 1, fpRawSaveFile) != 1)
if (!fpRawSaveFile.ReadBytes(__data, _fileSize))
{
PanicAlertT("failed to read data from file: %s", FilesList[i].c_str());
b_valid = false;
}
fclose(fpRawSaveFile);
AES_cbc_encrypt((const u8*)__data, __ENCdata, _roundedfileSize, &m_AES_KEY, tmpFileHDR.IV, AES_ENCRYPT);
fpData_bin = fopen(pathData_bin, "ab");
if (fpData_bin)
{
fwrite(__ENCdata, _roundedfileSize, 1, fpData_bin);
fclose(fpData_bin);
}
File::IOFile fpData_bin(pathData_bin, "ab");
fpData_bin.WriteBytes(__ENCdata, _roundedfileSize);
delete [] __data;
delete [] __ENCdata;
@ -466,7 +438,7 @@ void CWiiSaveCrypted::do_sig()
data_size = Common::swap32(bkhdr.sizeOfFiles) + 0x80;
fpData_bin = fopen(pathData_bin, "rb");
File::IOFile fpData_bin(pathData_bin, "rb");
if (!fpData_bin)
{
b_valid = false;
@ -474,14 +446,15 @@ void CWiiSaveCrypted::do_sig()
}
data = new u8[data_size];
fseeko(fpData_bin, 0xf0c0, SEEK_SET);
if (fread(data, data_size, 1, fpData_bin) != 1)
fpData_bin.Seek(0xf0c0, SEEK_SET);
if (!fpData_bin.ReadBytes(data, data_size))
PanicAlert("read data for sig check");
sha1(data, data_size, hash);
sha1(hash, 20, hash);
fclose(fpData_bin);
delete []data;
fpData_bin = fopen(pathData_bin, "ab");
fpData_bin.Open(pathData_bin, "ab");
if (!fpData_bin)
{
b_valid = false;
@ -490,15 +463,12 @@ void CWiiSaveCrypted::do_sig()
generate_ecdsa(sig, sig + 30, ap_priv, hash);
*(u32*)(sig + 60) = Common::swap32(0x2f536969);
if (fwrite(sig, sizeof sig, 1, fpData_bin) != 1)
if (!fpData_bin.WriteArray(sig, sizeof(sig)))
PanicAlert("write sig");
if (fwrite(ng_cert, sizeof ng_cert, 1, fpData_bin) != 1)
if (!fpData_bin.WriteArray(ng_cert, sizeof(ng_cert)))
PanicAlert("write NG cert");
if (fwrite(ap_cert, sizeof ap_cert, 1, fpData_bin) != 1)
if (!fpData_bin.WriteArray(ap_cert, sizeof(ap_cert)))
PanicAlert("write AP cert");
fclose(fpData_bin);
}

View File

@ -48,11 +48,7 @@ public:
private:
AES_KEY m_AES_KEY;
u8 SD_IV[0x10];
std::vector<std::string> FilesList;
FILE *fpData_bin,
*fpBanner_bin,
*fpRawSaveFile;
std::vector<std::string> FilesList;
char pathData_bin[2048],
pathSavedir[2048],