2007-05-30 21:56:52 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
2006-07-09 11:47:17 +00:00
|
|
|
*
|
|
|
|
* 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; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* 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 for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
2009-01-01 15:06:43 +00:00
|
|
|
*
|
2006-07-09 11:47:17 +00:00
|
|
|
*/
|
2008-09-15 22:43:20 +00:00
|
|
|
#ifdef GBA_SRAM_SAVE
|
|
|
|
|
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
#include "ramsave.h"
|
|
|
|
#include "nds.h"
|
|
|
|
#include "compressor/lz.h"
|
|
|
|
|
|
|
|
#define CART_RAM ((vu8 *) (0x0A000000))
|
2006-11-03 23:16:29 +00:00
|
|
|
#define SRAM_SAVE_MAX (65533)
|
2006-07-09 11:47:17 +00:00
|
|
|
|
|
|
|
DSSaveFile::DSSaveFile() {
|
|
|
|
ptr = 0;
|
|
|
|
saveCompressed = false;
|
|
|
|
save.isValid = false;
|
|
|
|
ownsData = false;
|
|
|
|
isOpenFlag = true;
|
|
|
|
isTempFile = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DSSaveFile::DSSaveFile(SCUMMSave* s, bool compressed, u8* data) {
|
|
|
|
save = *s;
|
|
|
|
saveData = data;
|
|
|
|
ptr = 0;
|
|
|
|
saveCompressed = compressed;
|
|
|
|
isOpenFlag = true;
|
|
|
|
|
|
|
|
if (saveCompressed) {
|
|
|
|
u8* uncompressed = new unsigned char[save.size];
|
|
|
|
if (!uncompressed) consolePrintf("Out of memory allocating %d!\n", save.size);
|
|
|
|
LZ_Uncompress(saveData, uncompressed, save.compressedSize);
|
|
|
|
saveData = uncompressed;
|
|
|
|
ownsData = true;
|
|
|
|
saveCompressed = false;
|
|
|
|
// consolePrintf("Decompressed. name=%s size=%d (%d)", save.name, save.size, save.compressedSize);
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
} else {
|
|
|
|
ownsData = false;
|
|
|
|
origHeader = s;
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
if (save.magic == (int) 0xBEEFCAFE) {
|
|
|
|
save.isValid = true;
|
|
|
|
} else {
|
|
|
|
save.isValid = false;
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
isTempFile = false;
|
2008-09-14 22:28:53 +00:00
|
|
|
eosReached = false;
|
2006-07-09 11:47:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DSSaveFile::~DSSaveFile() {
|
|
|
|
if (!ownsData) {
|
|
|
|
*origHeader = save;
|
|
|
|
DSSaveFileManager::instance()->flushToSaveRAM();
|
|
|
|
}
|
|
|
|
if (ownsData) {
|
|
|
|
delete saveData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DSSaveFile::loadFromSaveRAM(vu8* address) {
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
SCUMMSave newSave;
|
|
|
|
|
|
|
|
for (int t = 0; t < (int) sizeof(newSave); t++) {
|
|
|
|
((char *) (&newSave))[t] = *(address + t);
|
|
|
|
}
|
2006-11-03 23:16:29 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
if (newSave.magic == 0xBEEFCAFE) {
|
|
|
|
newSave.isValid = true;
|
|
|
|
|
|
|
|
*((u16 *) (0x4000204)) |= 0x3;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
saveData = new unsigned char[newSave.compressedSize];
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
for (int t = 0; t < (int) newSave.compressedSize; t++) {
|
|
|
|
((char *) (saveData))[t] = *(address + t + sizeof(newSave));
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
if (ownsData) delete this->saveData;
|
|
|
|
save = newSave;
|
|
|
|
saveCompressed = true;
|
|
|
|
this->saveData = saveData;
|
|
|
|
ownsData = true;
|
|
|
|
ptr = 0;
|
2006-11-03 23:16:29 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
return true;
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSSaveFile::compress() {
|
|
|
|
if (!saveCompressed) {
|
|
|
|
unsigned char* compBuffer = new unsigned char[(save.size * 110) / 100];
|
|
|
|
int compSize = LZ_Compress((u8 *) saveData, compBuffer, save.size);
|
|
|
|
save.compressedSize = compSize;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
delete saveData;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
// Make the save smaller
|
|
|
|
saveData = (u8 *) realloc(compBuffer, save.compressedSize);
|
|
|
|
saveCompressed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int DSSaveFile::saveToSaveRAM(vu8* address) {
|
|
|
|
|
|
|
|
unsigned char* compBuffer;
|
|
|
|
bool failed;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
|
|
|
|
int compSize;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
compress();
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
compSize = save.compressedSize;
|
|
|
|
compBuffer = saveData;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
if (DSSaveFileManager::instance()->getBytesFree() >= getRamUsage()) {
|
|
|
|
|
|
|
|
DSSaveFileManager::instance()->addBytesFree(-getRamUsage());
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
// Write header
|
|
|
|
for (int t = 0; t < sizeof(save); t++) {
|
|
|
|
while (*(address + t) != ((char *) (&save))[t]) {
|
|
|
|
*(address + t) = ((char *) (&save))[t];
|
|
|
|
}
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
// Write compressed buffer
|
|
|
|
for (int t = sizeof(save); t < (int) sizeof(save) + compSize; t++) {
|
|
|
|
while (*(address + t) != compBuffer[t - sizeof(save)]) {
|
|
|
|
*(address + t) = compBuffer[t - sizeof(save)];
|
|
|
|
}
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
failed = false;
|
|
|
|
} else {
|
|
|
|
failed = true;
|
|
|
|
}
|
|
|
|
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
return failed? 0: compSize + sizeof(save);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSSaveFile::reset() {
|
|
|
|
ptr = 0;
|
2008-09-14 22:28:53 +00:00
|
|
|
eosReached = false;
|
2006-07-09 11:47:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 DSSaveFile::read(void *buf, uint32 size) {
|
|
|
|
if (ptr + size > save.size) {
|
|
|
|
size = save.size - ptr;
|
2008-09-14 22:28:53 +00:00
|
|
|
eosReached = true;
|
2006-07-09 11:47:17 +00:00
|
|
|
if (size < 0) size = 0;
|
|
|
|
}
|
|
|
|
memcpy(buf, saveData + ptr, size);
|
|
|
|
// consolePrintf("byte: %d ", ((u8 *) (buf))[0]);
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
ptr += size;
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2008-09-13 16:51:46 +00:00
|
|
|
int32 DSSaveFile::pos() const {
|
2006-07-09 11:47:17 +00:00
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2008-09-13 16:51:46 +00:00
|
|
|
int32 DSSaveFile::size() const {
|
2006-07-09 11:47:17 +00:00
|
|
|
return save.size;
|
|
|
|
}
|
|
|
|
|
2008-09-13 16:51:46 +00:00
|
|
|
bool DSSaveFile::seek(int32 pos, int whence) {
|
2006-07-09 11:47:17 +00:00
|
|
|
switch (whence) {
|
|
|
|
case SEEK_SET: {
|
|
|
|
ptr = pos;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SEEK_CUR: {
|
|
|
|
ptr += pos;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SEEK_END: {
|
|
|
|
ptr = save.size - pos;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-09-14 22:28:53 +00:00
|
|
|
eosReached = false;
|
2008-09-13 16:51:46 +00:00
|
|
|
return true;
|
2006-07-09 11:47:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool DSSaveFile::eos() const {
|
2008-09-14 22:28:53 +00:00
|
|
|
return eosReached;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSSaveFile::clearErr() {
|
|
|
|
eosReached = false;
|
2006-07-09 11:47:17 +00:00
|
|
|
}
|
|
|
|
|
2008-09-13 16:51:46 +00:00
|
|
|
bool DSSaveFile::skip(uint32 bytes) {
|
2006-07-09 11:47:17 +00:00
|
|
|
ptr = ptr + bytes;
|
|
|
|
if (ptr > (int) save.size) ptr = save.size;
|
2008-09-13 16:51:46 +00:00
|
|
|
return true;
|
2006-07-09 11:47:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 DSSaveFile::write(const void *buf, uint32 size) {
|
|
|
|
|
|
|
|
if (ptr + size > DS_MAX_SAVE_SIZE) {
|
|
|
|
size = DS_MAX_SAVE_SIZE - ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(saveData + ptr, buf, size);
|
|
|
|
ptr += size;
|
|
|
|
save.size += size;
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2008-09-15 22:43:20 +00:00
|
|
|
bool DSSaveFile::matches(const char *prefix, int num) {
|
2006-07-09 11:47:17 +00:00
|
|
|
char str[16];
|
|
|
|
if (isValid()) {
|
|
|
|
sprintf(str, "%s%02d", prefix, num);
|
|
|
|
if (!strcmp(str, save.name)) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-15 22:43:20 +00:00
|
|
|
bool DSSaveFile::matches(const char *filename) {
|
2006-07-09 11:47:17 +00:00
|
|
|
if (isValid()) {
|
|
|
|
return !strcmp(save.name, filename);
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
void DSSaveFile::setName(char *name) {
|
|
|
|
save.isValid = true;
|
|
|
|
save.magic = 0xBEEFCAFE;
|
|
|
|
ownsData = true;
|
|
|
|
save.size = 0;
|
|
|
|
save.compressedSize = 0;
|
|
|
|
saveData = new unsigned char[DS_MAX_SAVE_SIZE];
|
|
|
|
strcpy(save.name, name);
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
if ((strstr(name, ".s99")) || (strstr(name, ".c"))) {
|
|
|
|
isTempFile = true;
|
|
|
|
} else {
|
|
|
|
isTempFile = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSSaveFile::clearData() {
|
|
|
|
save.size = 0;
|
|
|
|
|
|
|
|
if (saveCompressed) {
|
|
|
|
if (ownsData) {
|
|
|
|
delete saveData;
|
|
|
|
DSSaveFileManager::instance()->addBytesFree(getRamUsage());
|
|
|
|
}
|
|
|
|
saveData = new unsigned char[DS_MAX_SAVE_SIZE];
|
|
|
|
saveCompressed = false;
|
|
|
|
ownsData = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSSaveFile::deleteFile() {
|
|
|
|
if (isValid()) {
|
|
|
|
if (ownsData) {
|
|
|
|
DSSaveFileManager::instance()->addBytesFree(getRamUsage());
|
|
|
|
delete saveData;
|
|
|
|
saveData = NULL;
|
|
|
|
}
|
|
|
|
ptr = 0;
|
|
|
|
saveCompressed = false;
|
|
|
|
save.isValid = false;
|
|
|
|
ownsData = false;
|
|
|
|
isOpenFlag = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DSSaveFileManager::DSSaveFileManager() {
|
|
|
|
instancePtr = this;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
*((u16 *) (0x4000204)) |= 0x3;
|
|
|
|
swiWaitForVBlank();
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
loadAllFromSRAM();
|
|
|
|
}
|
|
|
|
|
|
|
|
DSSaveFileManager::~DSSaveFileManager() {
|
|
|
|
instancePtr = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSSaveFileManager::loadAllFromSRAM() {
|
|
|
|
int addr = 1;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
for (int r = 0; r < 8; r++) {
|
|
|
|
gbaSave[r].deleteFile();
|
|
|
|
}
|
|
|
|
|
2006-11-03 23:16:29 +00:00
|
|
|
sramBytesFree = SRAM_SAVE_MAX;
|
2006-07-09 11:47:17 +00:00
|
|
|
|
|
|
|
// Try to find saves in save RAM
|
|
|
|
for (int r = 0; r < 8; r++) {
|
|
|
|
if (gbaSave[r].loadFromSaveRAM(CART_RAM + addr)) {
|
|
|
|
addr += gbaSave[r].getRamUsage();
|
|
|
|
sramBytesFree -= gbaSave[r].getRamUsage();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSSaveFileManager::formatSram() {
|
2006-11-03 23:16:29 +00:00
|
|
|
for (int r = 0; r < SRAM_SAVE_MAX; r++) {
|
2006-07-09 11:47:17 +00:00
|
|
|
*(CART_RAM + r) = 0;
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
loadAllFromSRAM();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSSaveFileManager::listFiles() {
|
|
|
|
for (int r = 0; r < 8; r++) {
|
|
|
|
if (gbaSave[r].isValid()) {
|
|
|
|
consolePrintf("'%s': %d bytes\n", gbaSave[r].getName(), gbaSave[r].getRamUsage());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
consolePrintf("SRAM free: %d bytes\n", getBytesFree());
|
|
|
|
}
|
|
|
|
|
|
|
|
DSSaveFileManager* DSSaveFileManager::instancePtr = NULL;
|
|
|
|
|
2007-02-17 22:11:00 +00:00
|
|
|
DSSaveFile *DSSaveFileManager::openSavefile(const char* filename, bool saveOrLoad) {
|
2006-07-09 11:47:17 +00:00
|
|
|
for (int r = 0; r < 8; r++) {
|
|
|
|
if (gbaSave[r].isValid() && (gbaSave[r].matches((char *) filename))) {
|
|
|
|
// consolePrintf("Matched save %d (%d)\n", r, gbaSave[r].getSize());
|
|
|
|
gbaSave[r].reset();
|
|
|
|
//consolePrintf("reset ");
|
|
|
|
if (saveOrLoad) gbaSave[r].clearData();
|
|
|
|
// consolePrintf("cleared ");
|
|
|
|
return gbaSave[r].clone();
|
|
|
|
}
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
if (saveOrLoad) {
|
|
|
|
return makeSaveFile(filename, saveOrLoad);
|
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DSSaveFile* DSSaveFile::clone() {
|
|
|
|
// consolePrintf("Clone %s %d\n", save.name, save.size);
|
|
|
|
return new DSSaveFile(&save, saveCompressed, saveData);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSSaveFileManager::deleteFile(char* name) {
|
|
|
|
// consolePrintf("Deleting %s", name);
|
|
|
|
for (int r = 0; r < 8; r++) {
|
|
|
|
if (gbaSave[r].isValid() && (gbaSave[r].matches((char *) name))) {
|
|
|
|
gbaSave[r].deleteFile();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
flushToSaveRAM();
|
|
|
|
}
|
|
|
|
|
2008-05-14 06:59:23 +00:00
|
|
|
bool DSSaveFileManager::removeSavefile(const char *filename) {
|
|
|
|
consolePrintf("DSSaveFileManager::removeSavefile : Not implemented yet.\n");
|
|
|
|
assert(false);
|
|
|
|
//TODO: Implement this. Most likely, you just have to use the code of deleteFile?
|
|
|
|
return false;
|
2007-12-30 13:05:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Common::StringList DSSaveFileManager::listSavefiles(const char *pattern) {
|
2008-05-14 06:59:23 +00:00
|
|
|
consolePrintf("DSSaveFileManager::listSavefiles : Not implemented yet.\n");
|
|
|
|
assert(false);
|
|
|
|
return Common::StringList();
|
|
|
|
/*
|
2007-12-30 13:05:38 +00:00
|
|
|
TODO: Implement this. If you don't understand what it should do, just ask
|
|
|
|
(e.g. on scummvm-devel or Fingolfin). It should be pretty simple if you
|
|
|
|
use Common::matchString from common/util.h and read the Doxygen docs,
|
|
|
|
then combine this with the old code below...
|
2008-05-14 06:59:23 +00:00
|
|
|
*/
|
2008-05-15 22:12:51 +00:00
|
|
|
}
|
|
|
|
|
2007-12-30 13:05:38 +00:00
|
|
|
|
|
|
|
/*
|
2006-07-09 11:47:17 +00:00
|
|
|
void DSSaveFileManager::listSavefiles(const char *prefix, bool *marks, int num) {
|
2006-08-19 11:11:18 +00:00
|
|
|
memset(marks, true, num * sizeof(bool));
|
|
|
|
return;
|
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
memset(marks, false, num*sizeof(bool));
|
|
|
|
|
|
|
|
for (int saveNum = 0; saveNum < num; saveNum++) {
|
|
|
|
for (int r = 0; r < 8; r++) {
|
|
|
|
if (gbaSave[r].isValid() && (gbaSave[r].matches((char *) prefix, saveNum))) {
|
|
|
|
marks[saveNum] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2007-12-30 13:05:38 +00:00
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
|
2007-02-17 22:11:00 +00:00
|
|
|
DSSaveFile *DSSaveFileManager::makeSaveFile(const char *filename, bool saveOrLoad) {
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
// Find a free save slot
|
|
|
|
int r = 0;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
while ((r < 8) && (gbaSave[r].isValid())) {
|
|
|
|
r++;
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
if ((r == 8) && (gbaSave[r].isValid())) {
|
|
|
|
// No more saves
|
|
|
|
return NULL;
|
|
|
|
} else {
|
|
|
|
// Allocate this save
|
|
|
|
// consolePrintf("Allocated save %d\n", r);
|
|
|
|
gbaSave[r].setName((char *) filename);
|
|
|
|
gbaSave[r].reset();
|
|
|
|
return gbaSave[r].clone();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSSaveFileManager::flushToSaveRAM() {
|
|
|
|
int cartAddr = 1;
|
|
|
|
int s;
|
2006-11-03 23:16:29 +00:00
|
|
|
int extraData = DSSaveFileManager::getExtraData();
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
*((u16 *) (0x4000204)) |= 0x3;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
swiWaitForVBlank();
|
|
|
|
|
|
|
|
int size = 0;
|
|
|
|
for (int r = 0; (r < 8); r++) {
|
|
|
|
if (gbaSave[r].isValid()) {
|
|
|
|
gbaSave[r].compress();
|
|
|
|
if (!gbaSave[r].isTemp()) size += gbaSave[r].getRamUsage();
|
|
|
|
}
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-11-03 23:16:29 +00:00
|
|
|
if (size <= SRAM_SAVE_MAX) {
|
2006-07-09 11:47:17 +00:00
|
|
|
|
2006-11-03 23:16:29 +00:00
|
|
|
for (int r = 0; r < SRAM_SAVE_MAX; r++) {
|
2006-07-09 11:47:17 +00:00
|
|
|
*(CART_RAM + r) = 0;
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-11-03 23:16:29 +00:00
|
|
|
sramBytesFree = SRAM_SAVE_MAX;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
for (int r = 0; (r < 8); r++) {
|
|
|
|
if (gbaSave[r].isValid() && (!gbaSave[r].isTemp())) {
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
cartAddr += s = gbaSave[r].saveToSaveRAM(CART_RAM + cartAddr);
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
/* if (s == 0) {
|
|
|
|
consolePrintf("WARNING: Save didn't fit in cart RAM and has been lost!! Delete files and save again.", gbaSave[r].getName());
|
|
|
|
failed = true;
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
consolePrintf("WARNING: Save didn't fit in cart RAM and has been lost!! Delete files and save again.");
|
|
|
|
loadAllFromSRAM();
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2006-07-09 11:47:17 +00:00
|
|
|
}
|
2006-11-03 23:16:29 +00:00
|
|
|
|
|
|
|
DSSaveFileManager::setExtraData(extraData);
|
2006-07-09 11:47:17 +00:00
|
|
|
// consolePrintf("SRAM free: %d bytes\n", getBytesFree());
|
|
|
|
}
|
2006-11-03 23:16:29 +00:00
|
|
|
|
|
|
|
void DSSaveFileManager::setExtraData(int data) {
|
|
|
|
// Offset of extra data is 31. This overlaps the padding and reserved bytes of the first save entry.
|
|
|
|
// which have not been used up until now. So it should be safe.
|
|
|
|
|
|
|
|
vu8* sram = CART_RAM + 31;
|
|
|
|
|
|
|
|
*(sram + 0) = 0xF0; // This is an identifier to check
|
|
|
|
*(sram + 1) = 0x0D; // that extra data is present.
|
|
|
|
|
|
|
|
*(sram + 2) = (data & 0xFF000000) >> 24; // Now write the actual data
|
|
|
|
*(sram + 3) = (data & 0x00FF0000) >> 16; // taking care to use single
|
|
|
|
*(sram + 4) = (data & 0x0000FF00) >> 8; // byte writes (it's an 8-bit bus)
|
|
|
|
*(sram + 5) = (data & 0x000000FF);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DSSaveFileManager::isExtraDataPresent() {
|
|
|
|
vu8* sram = CART_RAM + 31;
|
|
|
|
|
|
|
|
// Check for the identifier
|
|
|
|
return ((*(sram + 0) == 0xF0) && (*(sram + 1) == 0x0D));
|
|
|
|
}
|
|
|
|
|
|
|
|
int DSSaveFileManager::getExtraData() {
|
|
|
|
vu8* sram = CART_RAM + 31;
|
|
|
|
|
|
|
|
if (isExtraDataPresent()) {
|
|
|
|
int value = (*(sram + 2) << 24) | (*(sram + 3) << 16) | (*(sram + 4) << 8) | (*(sram + 5));
|
|
|
|
return value;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2008-09-15 22:43:20 +00:00
|
|
|
|
|
|
|
#endif
|