Merge branch 'GCMemcardUpdates'

This commit is contained in:
LPFaint99
2011-10-04 13:18:22 -07:00
13 changed files with 167 additions and 181 deletions

View File

@ -26,6 +26,7 @@
#include "EXI_Device.h"
#include "EXI_DeviceMemoryCard.h"
#include "Sram.h"
#include "GCMemcard.h"
#define MC_STATUS_BUSY 0x80
#define MC_STATUS_UNLOCKED 0x40
@ -34,6 +35,7 @@
#define MC_STATUS_PROGRAMEERROR 0x08
#define MC_STATUS_READY 0x01
#define SIZE_TO_Mb (1024 * 8 * 16)
#define MC_HDR_SIZE 0xA000
static CEXIMemoryCard *cards[2];
@ -84,7 +86,6 @@ CEXIMemoryCard::CEXIMemoryCard(const std::string& _rName, const std::string& _rF
INFO_LOG(EXPANSIONINTERFACE, "Reading memory card %s", m_strFilename.c_str());
pFile.ReadBytes(memory_card_content, memory_card_size);
SetCardFlashID(memory_card_content, card_index);
}
else
@ -94,11 +95,11 @@ CEXIMemoryCard::CEXIMemoryCard(const std::string& _rName, const std::string& _rF
memory_card_size = nintendo_card_id * SIZE_TO_Mb;
memory_card_content = new u8[memory_card_size];
memset(memory_card_content, 0xFF, memory_card_size);
GCMemcard::Format(memory_card_content, m_strFilename.find(".JAP.raw") != std::string::npos, nintendo_card_id);
memset(memory_card_content+MC_HDR_SIZE, 0xFF, memory_card_size-MC_HDR_SIZE);
WARN_LOG(EXPANSIONINTERFACE, "No memory card found. Will create new.");
Flush();
}
SetCardFlashID(memory_card_content, card_index);
}
void innerFlush(FlushData* data)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,259 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef __GCMEMCARD_h__
#define __GCMEMCARD_h__
#include "Common.h"
#include "Sram.h"
#include "StringUtil.h"
#include "EXI_DeviceIPL.h"
#define BE32(x) (Common::swap32(x))
#define BE16(x) (Common::swap16(x))
#define ArrayByteSwap(a) (ByteSwap(a, a+sizeof(u8)));
enum
{
SLOT_A = 0,
SLOT_B = 1,
GCI = 0,
SUCCESS,
NOMEMCARD,
OPENFAIL,
OUTOFBLOCKS,
OUTOFDIRENTRIES,
LENGTHFAIL,
INVALIDFILESIZE,
TITLEPRESENT,
DIRLEN = 0x7F,
SAV = 0x80,
SAVFAIL,
GCS = 0x110,
GCSFAIL,
FAIL,
WRITEFAIL,
DELETE_FAIL,
MC_FST_BLOCKS = 0x05,
MBIT_TO_BLOCKS = 0x10,
DENTRY_STRLEN = 0x20,
DENTRY_SIZE = 0x40,
BLOCK_SIZE = 0x2000,
MemCard59Mb = 0x04,
MemCard123Mb = 0x08,
MemCard251Mb = 0x10,
Memcard507Mb = 0x20,
MemCard1019Mb = 0x40,
MemCard2043Mb = 0x80,
CI8SHARED = 1,
RGB5A3,
CI8,
};
class GCMemcard : NonCopyable
{
private:
friend class CMemcardManagerDebug;
bool m_valid;
std::string m_fileName;
u32 maxBlock;
u32 mc_data_size;
u8* mc_data;
u16 m_sizeMb;
#pragma pack(push,1)
struct Header { //Offset Size Description
// Serial in libogc
u8 serial[12]; //0x0000 12 ?
u64 formatTime; //0x000c 8 time of format (OSTime value)
u8 SramBias[4]; //0x0014 4 sram bias at time of format
u8 SramLang[4]; //0x0018 4 sram language
u8 Unk2[4]; //0x001c 4 ? almost always 0
// end Serial in libogc
u8 deviceID[2]; //0x0020 2 0 if formated in slot A 1 if formated in slot B
u8 SizeMb[2]; //0x0022 2 size of memcard in Mbits
u8 Encoding[2]; //0x0024 2 encoding (ASCII or japanese)
u8 Unused1[468]; //0x0026 468 unused (0xff)
u8 UpdateCounter[2];//0x01fa 2 update Counter (?, probably unused)
u16 Checksum; //0x01fc 2 Additive Checksum
u16 Checksum_Inv; //0x01fe 2 Inverse Checksum
u8 Unused2[7680]; //0x0200 0x1e00 unused (0xff)
} hdr;
struct DEntry {
u8 Gamecode[4]; //0x00 0x04 Gamecode
u8 Markercode[2]; //0x04 0x02 Makercode
u8 Unused1; //0x06 0x01 reserved/unused (always 0xff, has no effect)
u8 BIFlags; //0x07 0x01 banner gfx format and icon animation (Image Key)
// bit(s) description
// 2 Icon Animation 0: forward 1: ping-pong
// 1 [--0: No Banner 1: Banner present--] WRONG! YAGCD LIES!
// 0 [--Banner Color 0: RGB5A3 1: CI8--] WRONG! YAGCD LIES!
// bits 0 and 1: image format
// 00 no banner
// 01 CI8 banner
// 01 RGB5A3 banner
// 11 ? maybe ==01? haven't seen it
//
u8 Filename[DENTRY_STRLEN]; //0x08 0x20 filename
u8 ModTime[4]; //0x28 0x04 Time of file's last modification in seconds since 12am, January 1st, 2000
u8 ImageOffset[4]; //0x2c 0x04 image data offset
u8 IconFmt[2]; //0x30 0x02 icon gfx format (2bits per icon)
// bits Description
// 00 no icon
// 01 CI8 with a shared color palette after the last frame
// 10 RGB5A3
// 11 CI8 with a unique color palette after itself
//
u8 AnimSpeed[2]; //0x32 0x02 animation speed (2bits per icon) (*1)
// bits Description
// 00 no icon
// 01 Icon lasts for 4 frames
// 10 Icon lasts for 8 frames
// 11 Icon lasts for 12 frames
//
u8 Permissions; //0x34 0x01 file-permissions
// bit permission Description
// 4 no move File cannot be moved by the IPL
// 3 no copy File cannot be copied by the IPL
// 2 public Can be read by any game
//
u8 CopyCounter; //0x35 0x01 copy counter (*2)
u8 FirstBlock[2]; //0x36 0x02 block no of first block of file (0 == offset 0)
u8 BlockCount[2]; //0x38 0x02 file-length (number of blocks in file)
u8 Unused2[2]; //0x3a 0x02 reserved/unused (always 0xffff, has no effect)
u8 CommentsAddr[4]; //0x3c 0x04 Address of the two comments within the file data (*3)
};
struct Directory {
DEntry Dir[DIRLEN]; //0x0000 Directory Entries (max 127)
u8 Padding[0x3a];
u8 UpdateCounter[2];//0x1ffa 2 update Counter
u16 Checksum; //0x1ffc 2 Additive Checksum
u16 Checksum_Inv; //0x1ffe 2 Inverse Checksum
} dir, dir_backup;
struct BlockAlloc {
u16 Checksum; //0x0000 2 Additive Checksum
u16 Checksum_Inv; //0x0002 2 Inverse Checksum
u8 UpdateCounter[2];//0x0004 2 update Counter
u8 FreeBlocks[2]; //0x0006 2 free Blocks
u8 LastAllocated[2];//0x0008 2 last allocated Block
u16 Map[0xFFB]; //0x000a 0x1ff8 Map of allocated Blocks
} bat,bat_backup;
struct GCMC_Header
{
Header *hdr;
Directory *dir, *dir_backup;
BlockAlloc *bat, *bat_backup;
};
#pragma pack(pop)
u32 ImportGciInternal(FILE* gcih, const char *inputFile, std::string outputFile);
static void FormatInternal(GCMC_Header &GCP);
public:
GCMemcard(const char* fileName, bool forceCreation=false, bool sjis=false);
bool IsValid() { return m_valid; }
bool IsAsciiEncoding();
bool Save();
bool Format(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);
u32 TestChecksums();
bool FixChecksums();
// get number of file entries in the directory
u8 GetNumFiles();
// get the free blocks from bat
u16 GetFreeBlocks();
// If title already on memcard returns index, otherwise returns -1
u8 TitlePresent(DEntry d);
// DEntry functions, all take u8 index < DIRLEN (127)
// Functions that have ascii output take a char *buffer
// buffer needs to be a char[5] or bigger
bool DEntry_GameCode(u8 index, char *buffer);
// buffer needs to be a char[2] or bigger
bool DEntry_Markercode(u8 index, char *buffer);
// buffer needs to be a char[9] or bigger
bool DEntry_BIFlags(u8 index, char *buffer);
// buffer needs to be a char[32] or bigger
bool DEntry_FileName(u8 index, char *buffer);
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
u16 DEntry_FirstBlock(u8 index);
// get file length in blocks
u16 DEntry_BlockCount(u8 index);
u32 DEntry_CommentsAddress(u8 index);
// buffer needs to be a char[32] or bigger
bool DEntry_Comment1(u8 index, char *buffer);
// 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
bool DEntry_Copy(u8 index, DEntry& data);
// assumes there's enough space in buffer
// 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
// TODO: find a function that works for all calls or split into 2 functions
u32 DEntry_GetSaveData(u8 index, u8* buffer, bool old);
// adds the file to the directory and copies its contents
// if remove > 0 it will pad bat.map with 0's sizeof remove
u32 ImportFile(DEntry& direntry, u8* contents, int remove);
// delete a file from the directory
u32 RemoveFile(u8 index);
// reads a save from another memcard, and imports the data into this memcard
u32 CopyFrom(GCMemcard& source, u8 index);
// reads a .gci/.gcs/.sav file and calls ImportFile or saves out a gci file
u32 ImportGci(const char* inputFile, std::string outputFile);
// writes a .gci file to disk containing index
u32 ExportGci(u8 index, const char* fileName, std::string* fileName2);
// GCI files are untouched, SAV files are byteswapped
// 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);
// reads the banner image
bool ReadBannerRGBA8(u8 index, u32* buffer);
// reads the animation frames
u32 ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays);
};
#endif