pass by reference instead of pointer in several places,

return std::strings instead of filling a buffer,
move gci filename generation to a function inside gcmemcard instead of the gui code
 change all functions that do not modify the object to const

Conflicts:

	Source/Core/Core/Src/HW/GCMemcard.cpp
	Source/Core/DolphinWX/Src/MemcardManager.cpp

Signed-off-by: LPFaint99 <lpfaint99@gmail.com>
This commit is contained in:
LPFaint99 2011-12-10 15:44:08 -08:00
parent d5c393fe96
commit dfe890e8f1
3 changed files with 173 additions and 188 deletions

View File

@ -16,7 +16,6 @@
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "GCMemcard.h" #include "GCMemcard.h"
#include "ColorUtil.h" #include "ColorUtil.h"
static void ByteSwap(u8 *valueA, u8 *valueB) static void ByteSwap(u8 *valueA, u8 *valueB)
{ {
u8 tmp = *valueA; u8 tmp = *valueA;
@ -225,7 +224,7 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis)
mcdFile.Close(); mcdFile.Close();
} }
bool GCMemcard::IsAsciiEncoding() bool GCMemcard::IsAsciiEncoding() const
{ {
return hdr.Encoding == 0; return hdr.Encoding == 0;
} }
@ -267,7 +266,7 @@ void GCMemcard::calc_checksumsBE(u16 *buf, u32 length, u16 *csum, u16 *inv_csum)
} }
} }
u32 GCMemcard::TestChecksums() u32 GCMemcard::TestChecksums() const
{ {
u16 csum=0, u16 csum=0,
csum_inv=0; csum_inv=0;
@ -306,7 +305,7 @@ bool GCMemcard::FixChecksums()
return true; return true;
} }
u8 GCMemcard::GetNumFiles() u8 GCMemcard::GetNumFiles() const
{ {
if (!m_valid) if (!m_valid)
return 0; return 0;
@ -320,13 +319,13 @@ u8 GCMemcard::GetNumFiles()
return j; return j;
} }
u8 GCMemcard::GetFileIndex(u8 fileNumber) u8 GCMemcard::GetFileIndex(u8 fileNumber) const
{ {
if (m_valid) if (m_valid)
{ {
u8 j = 0; u8 j = 0;
for (int i = 0; i < DIRLEN; i++) for (u8 i = 0; i < DIRLEN; i++)
{ {
if (BE32(dir.Dir[i].Gamecode)!= 0xFFFFFFFF) if (BE32(dir.Dir[i].Gamecode)!= 0xFFFFFFFF)
{ {
@ -338,10 +337,10 @@ u8 GCMemcard::GetFileIndex(u8 fileNumber)
} }
} }
} }
return -1; return 0xFF;
} }
u16 GCMemcard::GetFreeBlocks() u16 GCMemcard::GetFreeBlocks() const
{ {
if (!m_valid) if (!m_valid)
return 0; return 0;
@ -349,7 +348,7 @@ u16 GCMemcard::GetFreeBlocks()
return BE16(bat.FreeBlocks); return BE16(bat.FreeBlocks);
} }
u8 GCMemcard::TitlePresent(DEntry d) u8 GCMemcard::TitlePresent(DEntry d) const
{ {
if (!m_valid) if (!m_valid)
return DIRLEN; return DIRLEN;
@ -367,102 +366,113 @@ u8 GCMemcard::TitlePresent(DEntry d)
return i; return i;
} }
bool GCMemcard::GCI_FileName(u8 index, std::string &filename) const
{
if (!m_valid || index > DIRLEN || (BE32(dir.Dir[index].Gamecode) == 0xFFFFFFFF))
return false;
filename = std::string((char*)dir.Dir[index].Gamecode, 4) + '_' + (char*)dir.Dir[index].Filename + ".gci";
return true;
}
// DEntry functions, all take u8 index < DIRLEN (127) // DEntry functions, all take u8 index < DIRLEN (127)
// Functions that have ascii output take a char *buffer // Functions that have ascii output take a char *buffer
bool GCMemcard::DEntry_GameCode(u8 index, char *buffer) std::string GCMemcard::DEntry_GameCode(u8 index) const
{ {
if (!m_valid) if (!m_valid || index > DIRLEN)
return false; return "";
return std::string((const char*)dir.Dir[index].Gamecode, 4);
memcpy(buffer, dir.Dir[index].Gamecode, 4);
buffer[4] = 0;
return true;
} }
bool GCMemcard::DEntry_Markercode(u8 index, char *buffer) std::string GCMemcard::DEntry_Makercode(u8 index) const
{ {
if (!m_valid) if (!m_valid || index > DIRLEN)
return false; return "";
return std::string((const char*)dir.Dir[index].Makercode, 2);
memcpy(buffer, dir.Dir[index].Markercode, 2);
buffer[2] = 0;
return true;
} }
bool GCMemcard::DEntry_BIFlags(u8 index, char *buffer)
{
if (!m_valid)
return false;
std::string GCMemcard::DEntry_BIFlags(u8 index) const
{
if (!m_valid || index > DIRLEN)
return "";
std::string flags;
int x = dir.Dir[index].BIFlags; int x = dir.Dir[index].BIFlags;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
buffer[i] = (x & 0x80) ? '1' : '0'; flags.push_back((x & 0x80) ? '1' : '0');
x = x << 1; x = x << 1;
} }
buffer[8] = 0; flags.push_back(0);
return true; return flags;
} }
bool GCMemcard::DEntry_FileName(u8 index, char *buffer) std::string GCMemcard::DEntry_FileName(u8 index) const
{ {
if (!m_valid) if (!m_valid || index > DIRLEN)
return false; return "";
return std::string((const char*)dir.Dir[index].Filename, DENTRY_STRLEN);
memcpy (buffer, (const char*)dir.Dir[index].Filename, DENTRY_STRLEN);
buffer[31] = 0;
return true;
} }
u32 GCMemcard::DEntry_ModTime(u8 index) u32 GCMemcard::DEntry_ModTime(u8 index) const
{ {
if (!m_valid || index > DIRLEN)
return 0xFFFFFFFF;
return BE32(dir.Dir[index].ModTime); return BE32(dir.Dir[index].ModTime);
} }
u32 GCMemcard::DEntry_ImageOffset(u8 index) u32 GCMemcard::DEntry_ImageOffset(u8 index) const
{ {
if (!m_valid || index > DIRLEN)
return 0xFFFFFFFF;
return BE32(dir.Dir[index].ImageOffset); return BE32(dir.Dir[index].ImageOffset);
} }
bool GCMemcard::DEntry_IconFmt(u8 index, char *buffer) std::string GCMemcard::DEntry_IconFmt(u8 index) const
{ {
if (!m_valid) return false; if (!m_valid || index > DIRLEN)
return "";
int x = dir.Dir[index].IconFmt[0]; int x = dir.Dir[index].IconFmt[0];
std::string format;
for(int i = 0; i < 16; i++) for(int i = 0; i < 16; i++)
{ {
if (i == 8) x = dir.Dir[index].IconFmt[1]; if (i == 8) x = dir.Dir[index].IconFmt[1];
buffer[i] = (x & 0x80) ? '1' : '0'; format.push_back((x & 0x80) ? '1' : '0');
x = x << 1; x = x << 1;
} }
buffer[16] = 0; format.push_back(0);
return true; return format;
} }
u16 GCMemcard::DEntry_AnimSpeed(u8 index) u16 GCMemcard::DEntry_AnimSpeed(u8 index) const
{ {
if (!m_valid || index > DIRLEN)
return 0;
return BE16(dir.Dir[index].AnimSpeed); return BE16(dir.Dir[index].AnimSpeed);
} }
bool GCMemcard::DEntry_Permissions(u8 index, char *fn) std::string GCMemcard::DEntry_Permissions(u8 index) const
{ {
if (!m_valid) return false; if (!m_valid || index > DIRLEN)
fn[0] = (dir.Dir[index].Permissions & 16) ? 'x' : 'M'; return "";
fn[1] = (dir.Dir[index].Permissions & 8) ? 'x' : 'C'; u8 Permissions = dir.Dir[index].Permissions;
fn[2] = (dir.Dir[index].Permissions & 4) ? 'P' : 'x'; std::string permissionsString;
fn[3] = 0; permissionsString.push_back((Permissions & 16) ? 'x' : 'M');
return true; permissionsString.push_back((Permissions & 8) ? 'x' : 'C');
permissionsString.push_back((Permissions & 4) ? 'P' : 'x');
permissionsString.push_back(0);
return permissionsString;
} }
u8 GCMemcard::DEntry_CopyCounter(u8 index) u8 GCMemcard::DEntry_CopyCounter(u8 index) const
{ {
if (!m_valid || index > DIRLEN)
return 0xFF;
return dir.Dir[index].CopyCounter; return dir.Dir[index].CopyCounter;
} }
u16 GCMemcard::DEntry_FirstBlock(u8 index) u16 GCMemcard::DEntry_FirstBlock(u8 index) const
{ {
if (!m_valid) if (!m_valid || index > DIRLEN)
return 0xFFFF; return 0xFFFF;
u16 block = BE16(dir.Dir[index].FirstBlock); u16 block = BE16(dir.Dir[index].FirstBlock);
@ -470,9 +480,9 @@ u16 GCMemcard::DEntry_FirstBlock(u8 index)
return block; return block;
} }
u16 GCMemcard::DEntry_BlockCount(u8 index) u16 GCMemcard::DEntry_BlockCount(u8 index) const
{ {
if (!m_valid) if (!m_valid || index > DIRLEN)
return 0xFFFF; return 0xFFFF;
u16 blocks = BE16(dir.Dir[index].BlockCount); u16 blocks = BE16(dir.Dir[index].BlockCount);
@ -480,56 +490,51 @@ u16 GCMemcard::DEntry_BlockCount(u8 index)
return blocks; return blocks;
} }
u32 GCMemcard::DEntry_CommentsAddress(u8 index) u32 GCMemcard::DEntry_CommentsAddress(u8 index) const
{ {
if (!m_valid || index > DIRLEN)
return 0xFFFF;
return BE32(dir.Dir[index].CommentsAddr); return BE32(dir.Dir[index].CommentsAddr);
} }
bool GCMemcard::DEntry_Comment1(u8 index, char* buffer) std::string GCMemcard::GetSaveComment1(u8 index) const
{ {
if (!m_valid) if (!m_valid || index > DIRLEN)
return false; return "";
u32 Comment1 = BE32(dir.Dir[index].CommentsAddr); u32 Comment1 = BE32(dir.Dir[index].CommentsAddr);
u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - MC_FST_BLOCKS; u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - MC_FST_BLOCKS;
if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF)) if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF))
{ {
buffer[0] = 0; return "";
return false;
} }
memcpy(buffer, mc_data + (DataBlock * BLOCK_SIZE) + Comment1, DENTRY_STRLEN); return std::string((const char *)mc_data + (DataBlock * BLOCK_SIZE) + Comment1, DENTRY_STRLEN);
buffer[31] = 0;
return true;
} }
bool GCMemcard::DEntry_Comment2(u8 index, char* buffer) std::string GCMemcard::GetSaveComment2(u8 index) const
{ {
if (!m_valid) if (!m_valid || index > DIRLEN)
return false; return "";
u32 Comment1 = BE32(dir.Dir[index].CommentsAddr); u32 Comment1 = BE32(dir.Dir[index].CommentsAddr);
u32 Comment2 = Comment1 + DENTRY_STRLEN; u32 Comment2 = Comment1 + DENTRY_STRLEN;
u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - MC_FST_BLOCKS; u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - MC_FST_BLOCKS;
if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF)) if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF))
{ {
buffer[0] = 0; return "";
return false;
} }
memcpy(buffer, mc_data + (DataBlock * BLOCK_SIZE) + Comment2, DENTRY_STRLEN); return std::string((const char *)mc_data + (DataBlock * BLOCK_SIZE) + Comment2, DENTRY_STRLEN);
buffer[31] = 0;
return true;
} }
bool GCMemcard::DEntry_Copy(u8 index, GCMemcard::DEntry& info) bool GCMemcard::GetDEntry(u8 index, DEntry &dest) const
{ {
if (!m_valid) if (!m_valid || index > DIRLEN)
return false; return false;
dest = dir.Dir[index];
info = dir.Dir[index];
return true; return true;
} }
u32 GCMemcard::DEntry_GetSaveData(u8 index, u8* dest, bool old) u32 GCMemcard::DEntry_GetSaveData(u8 index, u8* dest, bool old) const
{ {
if (!m_valid) if (!m_valid)
return NOMEMCARD; return NOMEMCARD;
@ -687,13 +692,13 @@ u32 GCMemcard::RemoveFile(u8 index) //index in the directory array
while (nextIndex < DIRLEN) while (nextIndex < DIRLEN)
{ {
DEntry * tempDEntry = new DEntry; DEntry tempDEntry;
DEntry_Copy(nextIndex, *tempDEntry); GetDEntry(nextIndex, tempDEntry);
u8 * tempSaveData = NULL; u8 * tempSaveData = NULL;
//Only get file data if it is a valid dir entry //Only get file data if it is a valid dir entry
if (BE16(tempDEntry->FirstBlock) != 0xFFFF) if (BE16(tempDEntry.FirstBlock) != 0xFFFF)
{ {
*(u16*)&bat.FreeBlocks = BE16(BE16(bat.FreeBlocks) - BE16(tempDEntry->BlockCount)); *(u16*)&bat.FreeBlocks = BE16(BE16(bat.FreeBlocks) - BE16(tempDEntry.BlockCount));
u16 size = DEntry_BlockCount(nextIndex); u16 size = DEntry_BlockCount(nextIndex);
if (size != 0xFFFF) if (size != 0xFFFF)
@ -707,7 +712,6 @@ u32 GCMemcard::RemoveFile(u8 index) //index in the directory array
break; break;
case FAIL: case FAIL:
delete[] tempSaveData; delete[] tempSaveData;
delete tempDEntry;
return FAIL; return FAIL;
} }
} }
@ -716,10 +720,9 @@ u32 GCMemcard::RemoveFile(u8 index) //index in the directory array
//Only call import file if DEntry_GetSaveData returns SUCCESS //Only call import file if DEntry_GetSaveData returns SUCCESS
if (tempSaveData != NULL) if (tempSaveData != NULL)
{ {
ImportFile(*tempDEntry, tempSaveData, blocks_left); ImportFile(tempDEntry, tempSaveData, blocks_left);
delete[] tempSaveData; delete[] tempSaveData;
} }
delete tempDEntry;
nextIndex++; nextIndex++;
} }
@ -737,13 +740,14 @@ u32 GCMemcard::RemoveFile(u8 index) //index in the directory array
return SUCCESS; return SUCCESS;
} }
u32 GCMemcard::CopyFrom(GCMemcard& source, u8 index) u32 GCMemcard::CopyFrom(const GCMemcard& source, u8 index)
{ {
if (!m_valid) if (!m_valid || !source.m_valid)
return NOMEMCARD; return NOMEMCARD;
DEntry tempDEntry; DEntry tempDEntry;
if (!source.DEntry_Copy(index, tempDEntry)) return NOMEMCARD; if (!source.GetDEntry(index, tempDEntry))
return NOMEMCARD;
u32 size = source.DEntry_BlockCount(index); u32 size = source.DEntry_BlockCount(index);
if (size == 0xFFFF) return INVALIDFILESIZE; if (size == 0xFFFF) return INVALIDFILESIZE;
@ -764,7 +768,7 @@ u32 GCMemcard::CopyFrom(GCMemcard& source, u8 index)
} }
} }
u32 GCMemcard::ImportGci(const char *inputFile, std::string outputFile) u32 GCMemcard::ImportGci(const char *inputFile, const std::string &outputFile)
{ {
if (outputFile.empty() && !m_valid) if (outputFile.empty() && !m_valid)
return OPENFAIL; return OPENFAIL;
@ -778,7 +782,7 @@ u32 GCMemcard::ImportGci(const char *inputFile, std::string outputFile)
return result; return result;
} }
u32 GCMemcard::ImportGciInternal(FILE* gcih, const char *inputFile, std::string outputFile) u32 GCMemcard::ImportGciInternal(FILE* gcih, const char *inputFile, const std::string &outputFile)
{ {
File::IOFile gci(gcih); File::IOFile gci(gcih);
unsigned int offset; unsigned int offset;
@ -810,8 +814,8 @@ u32 GCMemcard::ImportGciInternal(FILE* gcih, const char *inputFile, std::string
} }
gci.Seek(offset, SEEK_SET); gci.Seek(offset, SEEK_SET);
DEntry *tempDEntry = new DEntry; DEntry tempDEntry;
gci.ReadBytes(tempDEntry, DENTRY_SIZE); gci.ReadBytes(&tempDEntry, DENTRY_SIZE);
const int fStart = (int)gci.Tell(); const int fStart = (int)gci.Tell();
gci.Seek(0, SEEK_END); gci.Seek(0, SEEK_END);
const int length = (int)gci.Tell() - fStart; const int length = (int)gci.Tell() - fStart;
@ -819,12 +823,12 @@ u32 GCMemcard::ImportGciInternal(FILE* gcih, const char *inputFile, std::string
Gcs_SavConvert(tempDEntry, offset, length); Gcs_SavConvert(tempDEntry, offset, length);
if (length != BE16(tempDEntry->BlockCount) * BLOCK_SIZE) if (length != BE16(tempDEntry.BlockCount) * BLOCK_SIZE)
return LENGTHFAIL; return LENGTHFAIL;
if (gci.Tell() != offset + DENTRY_SIZE) // Verify correct file position if (gci.Tell() != offset + DENTRY_SIZE) // Verify correct file position
return OPENFAIL; return OPENFAIL;
u32 size = BE16((tempDEntry->BlockCount)) * BLOCK_SIZE; u32 size = BE16((tempDEntry.BlockCount)) * BLOCK_SIZE;
u8 *tempSaveData = new u8[size]; u8 *tempSaveData = new u8[size];
gci.ReadBytes(tempSaveData, size); gci.ReadBytes(tempSaveData, size);
u32 ret; u32 ret;
@ -835,14 +839,13 @@ u32 GCMemcard::ImportGciInternal(FILE* gcih, const char *inputFile, std::string
if (!gci2) if (!gci2)
{ {
delete[] tempSaveData; delete[] tempSaveData;
delete tempDEntry;
return OPENFAIL; return OPENFAIL;
} }
gci2.Seek(0, SEEK_SET); gci2.Seek(0, SEEK_SET);
if (!gci2.WriteBytes(tempDEntry, DENTRY_SIZE)) if (!gci2.WriteBytes(&tempDEntry, DENTRY_SIZE))
completeWrite = false; completeWrite = false;
int fileBlocks = BE16(tempDEntry->BlockCount); int fileBlocks = BE16(tempDEntry.BlockCount);
gci2.Seek(DENTRY_SIZE, SEEK_SET); gci2.Seek(DENTRY_SIZE, SEEK_SET);
if (!gci2.WriteBytes(tempSaveData, BLOCK_SIZE * fileBlocks)) if (!gci2.WriteBytes(tempSaveData, BLOCK_SIZE * fileBlocks))
@ -853,14 +856,13 @@ u32 GCMemcard::ImportGciInternal(FILE* gcih, const char *inputFile, std::string
ret = WRITEFAIL; ret = WRITEFAIL;
} }
else else
ret = ImportFile(*tempDEntry, tempSaveData, 0); ret = ImportFile(tempDEntry, tempSaveData, 0);
delete[] tempSaveData; delete[] tempSaveData;
delete tempDEntry;
return ret; return ret;
} }
u32 GCMemcard::ExportGci(u8 index, const char *fileName, std::string *fileName2) u32 GCMemcard::ExportGci(u8 index, const char* fileName, const std::string &directory) const
{ {
File::IOFile gci; File::IOFile gci;
int offset = GCI; int offset = GCI;
@ -868,15 +870,8 @@ u32 GCMemcard::ExportGci(u8 index, const char *fileName, std::string *fileName2)
{ {
if (BE32(dir.Dir[index].Gamecode) == 0xFFFFFFFF) return SUCCESS; if (BE32(dir.Dir[index].Gamecode) == 0xFFFFFFFF) return SUCCESS;
size_t length = fileName2->length() + 42; std::string outpuName = directory + DIR_SEP + DEntry_GameCode(index) + '_' + (char*)dir.Dir[index].Filename + ".gci";
char *filename = new char[length]; gci.Open(outpuName, "wb");
char GameCode[5];
DEntry_GameCode(index, GameCode);
sprintf(filename, "%s/%s_%s.gci", fileName2->c_str(), GameCode, dir.Dir[index].Filename);
gci.Open(filename, "wb");
delete[] filename;
} }
else else
{ {
@ -917,12 +912,12 @@ u32 GCMemcard::ExportGci(u8 index, const char *fileName, std::string *fileName2)
} }
DEntry tempDEntry; DEntry tempDEntry;
if (!DEntry_Copy(index, tempDEntry)) if (!GetDEntry(index, tempDEntry))
{ {
return NOMEMCARD; return NOMEMCARD;
} }
Gcs_SavConvert(&tempDEntry, offset); Gcs_SavConvert(tempDEntry, offset);
gci.WriteBytes(&tempDEntry, DENTRY_SIZE); gci.WriteBytes(&tempDEntry, DENTRY_SIZE);
u32 size = DEntry_BlockCount(index); u32 size = DEntry_BlockCount(index);
@ -955,7 +950,7 @@ u32 GCMemcard::ExportGci(u8 index, const char *fileName, std::string *fileName2)
return WRITEFAIL; return WRITEFAIL;
} }
void GCMemcard::Gcs_SavConvert(DEntry* tempDEntry, int saveType, int length) void GCMemcard::Gcs_SavConvert(DEntry &tempDEntry, int saveType, int length)
{ {
switch(saveType) switch(saveType)
{ {
@ -965,7 +960,7 @@ void GCMemcard::Gcs_SavConvert(DEntry* tempDEntry, int saveType, int length)
// It is stored only within the corresponding GSV file. // It is stored only within the corresponding GSV file.
// If the GCS file is added without using the GameSaves software, // If the GCS file is added without using the GameSaves software,
// the value stored is always "1" // the value stored is always "1"
*(u16*)&tempDEntry->BlockCount = BE16(length / BLOCK_SIZE); *(u16*)&tempDEntry.BlockCount = BE16(length / BLOCK_SIZE);
} }
break; break;
case SAV: case SAV:
@ -974,24 +969,24 @@ void GCMemcard::Gcs_SavConvert(DEntry* tempDEntry, int saveType, int length)
// 0x34 and 0x35, 0x36 and 0x37, 0x38 and 0x39, 0x3A and 0x3B, // 0x34 and 0x35, 0x36 and 0x37, 0x38 and 0x39, 0x3A and 0x3B,
// 0x3C and 0x3D,0x3E and 0x3F. // 0x3C and 0x3D,0x3E and 0x3F.
// It seems that sav files also swap the BIFlags... // It seems that sav files also swap the BIFlags...
ByteSwap(&tempDEntry->Unused1, &tempDEntry->BIFlags); ByteSwap(&tempDEntry.Unused1, &tempDEntry.BIFlags);
ArrayByteSwap((tempDEntry->ImageOffset)); ArrayByteSwap((tempDEntry.ImageOffset));
ArrayByteSwap(&(tempDEntry->ImageOffset[2])); ArrayByteSwap(&(tempDEntry.ImageOffset[2]));
ArrayByteSwap((tempDEntry->IconFmt)); ArrayByteSwap((tempDEntry.IconFmt));
ArrayByteSwap((tempDEntry->AnimSpeed)); ArrayByteSwap((tempDEntry.AnimSpeed));
ByteSwap(&tempDEntry->Permissions, &tempDEntry->CopyCounter); ByteSwap(&tempDEntry.Permissions, &tempDEntry.CopyCounter);
ArrayByteSwap((tempDEntry->FirstBlock)); ArrayByteSwap((tempDEntry.FirstBlock));
ArrayByteSwap((tempDEntry->BlockCount)); ArrayByteSwap((tempDEntry.BlockCount));
ArrayByteSwap((tempDEntry->Unused2)); ArrayByteSwap((tempDEntry.Unused2));
ArrayByteSwap((tempDEntry->CommentsAddr)); ArrayByteSwap((tempDEntry.CommentsAddr));
ArrayByteSwap(&(tempDEntry->CommentsAddr[2])); ArrayByteSwap(&(tempDEntry.CommentsAddr[2]));
break; break;
default: default:
break; break;
} }
} }
bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const
{ {
if (!m_valid) if (!m_valid)
return false; return false;
@ -1032,7 +1027,7 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer)
return true; return true;
} }
u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays) u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays) const
{ {
if (!m_valid) if (!m_valid)
return 0; return 0;

View File

@ -19,6 +19,7 @@
#define __GCMEMCARD_h__ #define __GCMEMCARD_h__
#include "Common.h" #include "Common.h"
#include "CommonPaths.h"
#include "Sram.h" #include "Sram.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "EXI_DeviceIPL.h" #include "EXI_DeviceIPL.h"
@ -101,7 +102,7 @@ private:
struct DEntry { struct DEntry {
u8 Gamecode[4]; //0x00 0x04 Gamecode u8 Gamecode[4]; //0x00 0x04 Gamecode
u8 Markercode[2]; //0x04 0x02 Makercode u8 Makercode[2]; //0x04 0x02 Makercode
u8 Unused1; //0x06 0x01 reserved/unused (always 0xff, has no effect) u8 Unused1; //0x06 0x01 reserved/unused (always 0xff, has no effect)
u8 BIFlags; //0x07 0x01 banner gfx format and icon animation (Image Key) u8 BIFlags; //0x07 0x01 banner gfx format and icon animation (Image Key)
// bit(s) description // bit(s) description
@ -168,67 +169,58 @@ private:
}; };
#pragma pack(pop) #pragma pack(pop)
u32 ImportGciInternal(FILE* gcih, const char *inputFile, std::string outputFile); u32 ImportGciInternal(FILE* gcih, const char *inputFile, const std::string &outputFile);
static void FormatInternal(GCMC_Header &GCP); static void FormatInternal(GCMC_Header &GCP);
public: public:
GCMemcard(const char* fileName, bool forceCreation=false, bool sjis=false); GCMemcard(const char* fileName, bool forceCreation=false, bool sjis=false);
bool IsValid() { return m_valid; } bool IsValid() const { return m_valid; }
bool IsAsciiEncoding(); bool IsAsciiEncoding() const;
bool Save(); bool Save();
bool Format(bool sjis = false, u16 SizeMb = MemCard2043Mb); bool Format(bool sjis = false, u16 SizeMb = MemCard2043Mb);
static bool Format(u8 * card_data, bool sjis = false, u16 SizeMb = MemCard2043Mb); static bool Format(u8 * card_data, bool sjis = false, u16 SizeMb = MemCard2043Mb);
static void calc_checksumsBE(u16 *buf, u32 length, u16 *csum, u16 *inv_csum); static void calc_checksumsBE(u16 *buf, u32 length, u16 *csum, u16 *inv_csum);
u32 TestChecksums(); u32 TestChecksums() const;
bool FixChecksums(); bool FixChecksums();
// get number of file entries in the directory // get number of file entries in the directory
u8 GetNumFiles(); u8 GetNumFiles() const;
u8 GetFileIndex(u8 fileNumber); u8 GetFileIndex(u8 fileNumber) const;
// get the free blocks from bat // get the free blocks from bat
u16 GetFreeBlocks(); u16 GetFreeBlocks() const;
// If title already on memcard returns index, otherwise returns -1 // If title already on memcard returns index, otherwise returns -1
u8 TitlePresent(DEntry d); u8 TitlePresent(DEntry d) const;
bool GCI_FileName(u8 index, std::string &filename) const;
// DEntry functions, all take u8 index < DIRLEN (127) // DEntry functions, all take u8 index < DIRLEN (127)
// Functions that have ascii output take a char *buffer std::string DEntry_GameCode(u8 index) const;
std::string DEntry_Makercode(u8 index) const;
// buffer needs to be a char[5] or bigger std::string DEntry_BIFlags(u8 index) const;
bool DEntry_GameCode(u8 index, char *buffer); std::string DEntry_FileName(u8 index) const;
// buffer needs to be a char[2] or bigger u32 DEntry_ModTime(u8 index) const;
bool DEntry_Markercode(u8 index, char *buffer); u32 DEntry_ImageOffset(u8 index) const;
// buffer needs to be a char[9] or bigger std::string DEntry_IconFmt(u8 index) const;
bool DEntry_BIFlags(u8 index, char *buffer); u16 DEntry_AnimSpeed(u8 index) const;
// buffer needs to be a char[32] or bigger std::string DEntry_Permissions(u8 index) const;
bool DEntry_FileName(u8 index, char *buffer); u8 DEntry_CopyCounter(u8 index) const;
u32 DEntry_ModTime(u8 index);
u32 DEntry_ImageOffset(u8 index);
// buffer needs to be a char[17] or bigger
bool DEntry_IconFmt(u8 index, char *buffer);
u16 DEntry_AnimSpeed(u8 index);
// buffer needs to be a char[4] or bigger
bool DEntry_Permissions(u8 index, char *buffer);
u8 DEntry_CopyCounter(u8 index);
// get first block for file // get first block for file
u16 DEntry_FirstBlock(u8 index); u16 DEntry_FirstBlock(u8 index) const;
// get file length in blocks // get file length in blocks
u16 DEntry_BlockCount(u8 index); u16 DEntry_BlockCount(u8 index) const;
u32 DEntry_CommentsAddress(u8 index); u32 DEntry_CommentsAddress(u8 index) const;
// buffer needs to be a char[32] or bigger std::string GetSaveComment1(u8 index) const;
bool DEntry_Comment1(u8 index, char *buffer); std::string GetSaveComment2(u8 index) const;
// buffer needs to be a char[32] or bigger
bool DEntry_Comment2(u8 index, char *buffer);
// Copies a DEntry from u8 index to DEntry& data // Copies a DEntry from u8 index to DEntry& data
bool DEntry_Copy(u8 index, DEntry& data); bool GetDEntry(u8 index, DEntry &dest) const;
// assumes there's enough space in buffer // assumes there's enough space in buffer
// old determines if function uses old or new method of copying data // old determines if function uses old or new method of copying data
// some functions only work with old way, some only work with new way // some functions only work with old way, some only work with new way
// TODO: find a function that works for all calls or split into 2 functions // TODO: find a function that works for all calls or split into 2 functions
u32 DEntry_GetSaveData(u8 index, u8* buffer, bool old); u32 DEntry_GetSaveData(u8 index, u8* buffer, bool old) const;
// adds the file to the directory and copies its contents // adds the file to the directory and copies its contents
// if remove > 0 it will pad bat.map with 0's sizeof remove // if remove > 0 it will pad bat.map with 0's sizeof remove
@ -238,23 +230,23 @@ public:
u32 RemoveFile(u8 index); u32 RemoveFile(u8 index);
// 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, u8 index); u32 CopyFrom(const GCMemcard& source, u8 index);
// reads a .gci/.gcs/.sav file and calls ImportFile or saves out a gci file // reads a .gci/.gcs/.sav file and calls ImportFile or saves out a gci file
u32 ImportGci(const char* inputFile, std::string outputFile); u32 ImportGci(const char* inputFile,const std::string &outputFile);
// writes a .gci file to disk containing index // writes a .gci file to disk containing index
u32 ExportGci(u8 index, const char* fileName, std::string* fileName2); u32 ExportGci(u8 index, const char* fileName, const std::string &directory) const;
// GCI files are untouched, SAV files are byteswapped // GCI files are untouched, SAV files are byteswapped
// GCS files have the block count set, default is 1 (For export as GCS) // GCS files have the block count set, default is 1 (For export as GCS)
void Gcs_SavConvert(DEntry* tempDEntry, int saveType, int length = BLOCK_SIZE); static void Gcs_SavConvert(DEntry &tempDEntry, int saveType, int length = BLOCK_SIZE);
// reads the banner image // reads the banner image
bool ReadBannerRGBA8(u8 index, u32* buffer); bool ReadBannerRGBA8(u8 index, u32* buffer) const;
// reads the animation frames // reads the animation frames
u32 ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays); u32 ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays) const;
}; };
#endif #endif

View File

@ -546,15 +546,16 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
index = memoryCard[slot]->GetFileIndex(index); index = memoryCard[slot]->GetFileIndex(index);
if (index != wxNOT_FOUND) if (index != wxNOT_FOUND)
{ {
char tempC[10 + DENTRY_STRLEN], std::string gciFilename;
tempC2[DENTRY_STRLEN]; if (!memoryCard[slot]->GCI_FileName(index, gciFilename))
memoryCard[slot]->DEntry_GameCode(index,tempC); {
memoryCard[slot]->DEntry_FileName(index,tempC2); PanicAlert("invalid index");
sprintf(tempC, "%s_%s.gci", tempC, tempC2); return;
}
wxString fileName = wxFileSelector( wxString fileName = wxFileSelector(
_("Export save as..."), _("Export save as..."),
wxString::From8BitData(DefaultIOPath.c_str()), wxString::From8BitData(DefaultIOPath.c_str()),
wxString::From8BitData(tempC), wxT(".gci"), wxString::From8BitData(gciFilename.c_str()), wxT(".gci"),
_("Native GCI files(*.gci)") + wxString(wxT("|*.gci|")) + _("Native GCI files(*.gci)") + wxString(wxT("|*.gci|")) +
_("MadCatz Gameshark files(*.gcs)") + wxString(wxT("|*.gcs|")) + _("MadCatz Gameshark files(*.gcs)") + wxString(wxT("|*.gcs|")) +
_("Datel MaxDrive/Pro files(*.sav)") + wxString(wxT("|*.sav")), _("Datel MaxDrive/Pro files(*.sav)") + wxString(wxT("|*.sav")),
@ -562,7 +563,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
if (fileName.length() > 0) if (fileName.length() > 0)
{ {
if (!CopyDeleteSwitch(memoryCard[slot]->ExportGci(index, fileName.mb_str(), NULL), -1)) if (!CopyDeleteSwitch(memoryCard[slot]->ExportGci(index, fileName.mb_str(), ""), -1))
{ {
File::Delete(std::string(fileName.mb_str())); File::Delete(std::string(fileName.mb_str()));
} }
@ -582,7 +583,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
"%s\nand have the same name as a file on your memcard\nContinue?", path1.c_str())) "%s\nand have the same name as a file on your memcard\nContinue?", path1.c_str()))
for (int i = 0; i < DIRLEN; i++) for (int i = 0; i < DIRLEN; i++)
{ {
CopyDeleteSwitch(memoryCard[slot]->ExportGci(i, ".", &path1), -1); CopyDeleteSwitch(memoryCard[slot]->ExportGci(i, NULL, path1), -1);
} }
break; break;
} }
@ -614,8 +615,7 @@ bool CMemcardManager::ReloadMemcard(const char *fileName, int card)
wxComment, wxComment,
wxBlock, wxBlock,
wxFirstBlock, wxFirstBlock,
wxLabel, wxLabel;
tString;
m_MemcardList[card]->Hide(); m_MemcardList[card]->Hide();
@ -689,8 +689,6 @@ bool CMemcardManager::ReloadMemcard(const char *fileName, int card)
for (j = page[card] * itemsPerPage; (j < nFiles) && (j < pagesMax); j++) for (j = page[card] * itemsPerPage; (j < nFiles) && (j < pagesMax); j++)
{ {
char title[DENTRY_STRLEN];
char comment[DENTRY_STRLEN];
u16 blocks; u16 blocks;
u16 firstblock; u16 firstblock;
u8 fileIndex = memoryCard[card]->GetFileIndex(j); u8 fileIndex = memoryCard[card]->GetFileIndex(j);
@ -700,8 +698,8 @@ bool CMemcardManager::ReloadMemcard(const char *fileName, int card)
m_MemcardList[card]->SetItem(index, COLUMN_BANNER, wxEmptyString); m_MemcardList[card]->SetItem(index, COLUMN_BANNER, wxEmptyString);
if (!memoryCard[card]->DEntry_Comment1(fileIndex, title)) title[0]=0; std::string title = memoryCard[card]->GetSaveComment1(fileIndex);
if (!memoryCard[card]->DEntry_Comment2(fileIndex, comment)) comment[0]=0; std::string comment = memoryCard[card]->GetSaveComment2(fileIndex);
bool ascii = memoryCard[card]->IsAsciiEncoding(); bool ascii = memoryCard[card]->IsAsciiEncoding();
@ -721,8 +719,8 @@ bool CMemcardManager::ReloadMemcard(const char *fileName, int card)
// it returns CP-932, in order to use iconv we need to use CP932 // it returns CP-932, in order to use iconv we need to use CP932
wxCSConv SJISConv(wxT("CP932")); wxCSConv SJISConv(wxT("CP932"));
#endif #endif
wxTitle = wxString(title, ascii ? *wxConvCurrent : SJISConv); wxTitle = wxString(title.c_str(), ascii ? *wxConvCurrent : SJISConv);
wxComment = wxString(comment, ascii ? *wxConvCurrent : SJISConv); wxComment = wxString(comment.c_str(), ascii ? *wxConvCurrent : SJISConv);
m_MemcardList[card]->SetItem(index, COLUMN_TITLE, wxTitle); m_MemcardList[card]->SetItem(index, COLUMN_TITLE, wxTitle);
m_MemcardList[card]->SetItem(index, COLUMN_COMMENT, wxComment); m_MemcardList[card]->SetItem(index, COLUMN_COMMENT, wxComment);