mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 06:39:46 -06:00
My first commit, renames AddGci and SaveGci to ImportGci and ExportGci
adds Madcatz gameshark .gcs, and Datel Maxdrive/pro .sav file support to function importgci adds conversion from .gcs and .sav to .gci, added to speed up testing for .gcs and .sav until ImportFile is fixed git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@856 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@ -19,8 +19,8 @@
|
||||
#include "stdafx.h"
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
#include "wx/ffile.h"
|
||||
|
||||
#include "GCMemcard.h"
|
||||
|
||||
@ -609,37 +609,139 @@ u32 GCMemcard::CopyFrom(GCMemcard& source, u32 index)
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 GCMemcard::AddGci(const char *fileName)
|
||||
u32 GCMemcard::ImportGci(const char *fileName, int endFile, const char *fileName2)
|
||||
{
|
||||
if(!mcdFile) return 0;
|
||||
if(!mcdFile && !fileName2) return 0;
|
||||
|
||||
FILE *gci=fopen(fileName,"rb");
|
||||
wxFFile gci(fileName,"rb");
|
||||
if(!gci.IsOpened())return 0;
|
||||
|
||||
if(!gci) return 0;
|
||||
enum
|
||||
{
|
||||
GCI = 0,
|
||||
SAV = 0x80,
|
||||
GCS = 0x110
|
||||
};
|
||||
int offset;
|
||||
char * tmp = new char[0xD];
|
||||
u16 tmpU16;
|
||||
|
||||
const char * fileType= (char*)fileName+ endFile-3;
|
||||
|
||||
if(!_stricmp(fileType,"gci") && !fileName2)//Extension can be either case
|
||||
offset = GCI;
|
||||
else
|
||||
{
|
||||
gci.Read(tmp,0xD);
|
||||
if(!_stricmp(fileType,"gcs"))//Extension can be either case
|
||||
{
|
||||
if(!memcmp(tmp,"GCSAVE",6)) //Header must be uppercase
|
||||
offset = GCS;
|
||||
else
|
||||
{
|
||||
//TODO error message, file has gsc extension but does not have a correct header
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(!_stricmp(fileType,"sav"))//Extension can be either case
|
||||
{
|
||||
if(!memcmp(tmp,"DATELGC_SAVE",0xC))//Header must be uppercase
|
||||
offset = SAV;
|
||||
else
|
||||
{
|
||||
//TODO error message, file has sav extension but does not have a correct header
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO error message, file has invalid extension
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
gci.Seek(offset,wxFromStart);
|
||||
|
||||
DEntry *d = new DEntry;
|
||||
fread(d,1,0x40,gci);
|
||||
gci.Read(d,0x40);
|
||||
|
||||
switch(offset){
|
||||
case GCS:
|
||||
//field containing the Block count as displayed within the GameSaves software
|
||||
//is not stored in the GCS file.
|
||||
//It is stored only within the corresponding GSV file.
|
||||
//If the GCS file is added without using the GameSaves software,
|
||||
//the value stored is always "1"
|
||||
tmpU16 =(((int)gci.Length()-offset-0x40)/0x2000);
|
||||
if(tmpU16<0x100){
|
||||
d->BlockCount[1] = (u8)tmpU16;
|
||||
}
|
||||
else{
|
||||
d->BlockCount[0] = (u8)(tmpU16-0xFF);
|
||||
d->BlockCount[1] = 0xFF;
|
||||
}
|
||||
break;
|
||||
case SAV:
|
||||
//swap byte pairs
|
||||
//0x2C and 0x2D,0x2E and 0x2F,0x30 and 0x31,0x32 and 0x33,0x34 and 0x35,
|
||||
//0x36 and 0x37,0x38 and 0x39,0x3A and 0x3B,0x3C and 0x3D,0x3E and 0x3F.
|
||||
SWAP((d->ImageOffset));
|
||||
SWAP(&(d->ImageOffset[2]));
|
||||
SWAP((d->IconFmt));
|
||||
SWAP((d->AnimSpeed));
|
||||
varSwap(&d->Permissions,&d->CopyCounter);
|
||||
SWAP((d->FirstBlock));
|
||||
SWAP((d->BlockCount));
|
||||
SWAP((d->Unused2));
|
||||
SWAP((d->CommentsAddr));
|
||||
SWAP(&(d->CommentsAddr[2]));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//TODO verify file length
|
||||
assert(((int)gci.Length()-offset)== ((BE16(d->BlockCount)* 0x2000) + 0x40));
|
||||
|
||||
|
||||
u32 size=BE16((d->BlockCount))*0x2000;
|
||||
u8 *t = new u8[size];
|
||||
fread(t,1,size,gci);
|
||||
u32 ret = ImportFile(*d,t);
|
||||
gci.Read(t,size);
|
||||
|
||||
gci.Close();
|
||||
|
||||
u32 ret = 0;
|
||||
if(!fileName2)
|
||||
{
|
||||
wxFFile gci2(fileName2,"wb");
|
||||
if(!gci2.IsOpened())return 0;
|
||||
gci2.Seek(0,wxFromStart);
|
||||
gci2.Write(d,0x40);
|
||||
int fileBlocks=BE16(d->BlockCount);
|
||||
gci2.Seek(0x40,wxFromStart);
|
||||
gci2.Write(t,0x2000*fileBlocks);
|
||||
gci2.Close();
|
||||
}
|
||||
else ret = ImportFile(*d,t);
|
||||
|
||||
|
||||
delete[] t;
|
||||
delete[] tmp;
|
||||
delete d;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool GCMemcard::SaveGci(u32 index, const char *fileName)
|
||||
bool GCMemcard::ExportGci(u32 index, const char *fileName)
|
||||
{
|
||||
FILE *gci=fopen(fileName,"wb");
|
||||
|
||||
if(!gci) return false;
|
||||
|
||||
fseek(gci,0,SEEK_SET);
|
||||
wxFFile gci(fileName,"wb");
|
||||
|
||||
if(!gci.IsOpened())return false;
|
||||
|
||||
gci.Seek(0,wxFromStart);
|
||||
|
||||
DEntry d;
|
||||
if(!this->GetFileInfo(index,d)) return false;
|
||||
fwrite(&d,1,0x40,gci);
|
||||
gci.Write(&d,0x40);
|
||||
|
||||
u8 *t = new u8[this->GetFileSize(index)*0x2000];
|
||||
|
||||
@ -647,10 +749,10 @@ bool GCMemcard::SaveGci(u32 index, const char *fileName)
|
||||
|
||||
int fileBlocks=BE16(d.BlockCount);
|
||||
|
||||
fseek(gci,0x40,SEEK_SET);
|
||||
fwrite(t,1,0x2000*fileBlocks,gci);
|
||||
gci.Seek(0x40,wxFromStart);
|
||||
gci.Write(t,0x2000*fileBlocks);
|
||||
|
||||
fclose(gci);
|
||||
gci.Close();
|
||||
delete[] t;
|
||||
|
||||
return true;
|
||||
@ -753,3 +855,9 @@ GCMemcard::~GCMemcard()
|
||||
{
|
||||
fclose((FILE*)mcdFile);
|
||||
}
|
||||
|
||||
void varSwap(u8 *valueA,u8 *valueB){
|
||||
u8 temp = *valueA;
|
||||
*valueA = *valueB;
|
||||
*valueB = temp;
|
||||
}
|
@ -15,12 +15,18 @@
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
|
||||
|
||||
#define SWAP(a) (varSwap(a,a+sizeof(u8)));
|
||||
|
||||
void varSwap(u8 *valueA,u8 *valueB);
|
||||
|
||||
u16 __inline bswap16(u16 s)
|
||||
{
|
||||
return (s>>8) | (s<<8);
|
||||
@ -178,10 +184,10 @@ public:
|
||||
u32 CopyFrom(GCMemcard& source, u32 index);
|
||||
|
||||
// writes a .gci file to disk containing index
|
||||
bool SaveGci(u32 index, const char* fileName);
|
||||
bool ExportGci(u32 index, const char* fileName);
|
||||
|
||||
// reads a .gci file and calls ImportFile
|
||||
u32 AddGci(const char* fileName);
|
||||
// reads a .gci/.gcs/.sav file and calls ImportFile or saves out a gci file
|
||||
u32 ImportGci(const char* fileName, int endFile,const char* fileName2);
|
||||
|
||||
// reads the banner image
|
||||
bool ReadBannerRGBA8(u32 index, u32* buffer);
|
||||
|
Reference in New Issue
Block a user