BackupDevice::BackupDevice() { size_t elements_read, elements_written; fpMC = NULL; fsize = 0; addr_size = 0; isMovieMode = false; //default for most games; will be altered where appropriate //usually 0xFF, but occasionally others. If these exceptions could be related to a particular backup memory type, that would be helpful. //at first we assumed it would be 0x00, but baby pals proved that it should be 0xFF: // the game reads its initial sound volumes from uninitialized data, and if it is 0, the game will be silent // if it is 0xFF then the game starts with its sound and music at max, as presumably it is supposed to. // so in r3303 we finally changed it (no$ appears definitely to initialize to 0xFF) uninitializedValue = 0xFF; if (gameInfo.romsize == 0) return; char buf[MAX_PATH] = {0}; memset(buf, 0, MAX_PATH); path.getpathnoext(path.BATTERY, buf); filename = std::string(buf) + ".dsv"; MCLOG("MC: %s\n", filename.c_str()); bool fexists = (access(filename.c_str(), 0) == 0)?true:false; if (fexists && CommonSettings.backupSave) { std::string tmp_fsav = std::string(buf) + ".dsv.bak"; EMUFILE_FILE *in = new EMUFILE_FILE(filename, "rb"); if (!in->fail()) { u32 sz = in->size(); if (sz > 0) { EMUFILE_FILE *out = new EMUFILE_FILE(tmp_fsav, "wb"); if (!out->fail()) { u8 *data = new u8[sz]; elements_read = fread(data, 1, sz, in->get_fp()); elements_written = fwrite(data, 1, sz, out->get_fp()); if (elements_read != sz || elements_written != sz) printf("Possibly incomplete data read/write.\n"); delete [] data; } delete out; } } delete in; } if (!fexists) { printf("DeSmuME .dsv save file not found. Trying to load an old raw .sav file.\n"); std::string tmp_fsav = std::string(buf) + ".sav"; EMUFILE_FILE *fpTmp = new EMUFILE_FILE(tmp_fsav, "rb"); if (!fpTmp->fail()) { u32 sz = fpTmp->size(); if (sz > 0) { EMUFILE_FILE *fpOut = new EMUFILE_FILE(filename, "wb"); if (!fpOut->fail()) { u8 *buf = new u8[sz + 1]; if ((buf) && (fread(buf, 1, sz, fpTmp->get_fp()) == sz)) { if (no_gba_unpack(buf, sz)) printf("Converted from no$gba save.\n"); else sz = trim(buf, sz); if (fwrite(buf, 1, sz, fpOut->get_fp()) == sz) { u8 res = searchFileSaveType(sz); if (res != 0xFF) { info.type = (res + 1); addr_size = info.addr_size = save_types[info.type].addr_size; info.size = fsize = sz; ensure(sz, fpOut); fsize = 0; } else info.type = 0; fexists = true; } } delete [] buf; } delete fpOut; } } delete fpTmp; } fpMC = new EMUFILE_FILE(filename, fexists?"rb+":"wb+"); if (!fpMC->fail()) { fsize = fpMC->size(); if (fsize < saveSizes[0]) fpMC->truncate(0); if (readFooter() == 0) fsize -= (strlen(kDesmumeSaveCookie) + strlen(DESMUME_BACKUP_FOOTER_TXT) + 24); else { memset(&info, 0, sizeof(info)); fsize = 0; } fpMC->fseek(0, SEEK_SET); u32 left = 0; if (CommonSettings.autodetectBackupMethod == 1) { if (advsc.isLoaded()) { info.type = advsc.getSaveType(); if (info.type != 0xFF && info.type != 0xFE) { info.type++; u32 adv_size = save_types[info.type].size; if (info.size > adv_size) { info.size = adv_size; fpMC->truncate(adv_size); ensure(adv_size, fpMC); } else if (info.size < adv_size) { left = adv_size - info.size; info.size = adv_size; ensure(adv_size); } fsize = adv_size; } } } addr_size = info.addr_size; info.padSize = fsize; //none of the other fields are used right now if (CommonSettings.autodetectBackupMethod != 1 && info.type == 0) { info.type = searchFileSaveType(info.size); if (info.type == 0xFF) info.type = 0; } u32 ss = (info.padSize * 8) / 1024; bool _Mbit = false; if (ss >= 1024) { ss /= 1024; _Mbit = true; } if (ss > 0) printf("Backup size: %u %cbit\n", ss, _Mbit?'M':'K'); } state = (fsize > 0)?RUNNING:DETECTING; reset(); }
BackupDevice::BackupDevice() { fpMC = NULL; fsize = 0; addr_size = 0; isMovieMode = false; if (gameInfo.romsize == 0) return; char buf[MAX_PATH] = {0}; memset(buf, 0, MAX_PATH); path.getpathnoext(path.BATTERY, buf); filename = std::string(buf) + ".dsv"; // DeSmuME memory card MCLOG("MC: %s\n", filename.c_str()); bool fexists = (access(filename.c_str(), 0) == 0)?true:false; if (fexists && CommonSettings.backupSave) { std::string tmp_fsav = std::string(buf) + ".dsv.bak"; EMUFILE_FILE *in = new EMUFILE_FILE(filename, "rb"); if (!in->fail()) { u32 sz = in->size(); if (sz > 0) { EMUFILE_FILE *out = new EMUFILE_FILE(tmp_fsav, "wb"); if (!out->fail()) { u8 *data = new u8[sz]; fread(data, 1, sz, in->get_fp()); fwrite(data, 1, sz, out->get_fp()); delete [] data; } delete out; } } delete in; } if (!fexists) { printf("DeSmuME .dsv save file not found. Trying to load an old raw .sav file.\n"); std::string tmp_fsav = std::string(buf) + ".sav"; EMUFILE_FILE *fpTmp = new EMUFILE_FILE(tmp_fsav, "rb"); if (!fpTmp->fail()) { u32 sz = fpTmp->size(); if (sz > 0) { EMUFILE_FILE *fpOut = new EMUFILE_FILE(filename, "wb"); if (!fpOut->fail()) { u8 *buf = new u8[sz + 1]; if ((buf) && (fread(buf, 1, sz, fpTmp->get_fp()) == sz)) { if (no_gba_unpack(buf, sz)) printf("Converted from no$gba save.\n"); else sz = trim(buf, sz); if (fwrite(buf, 1, sz, fpOut->get_fp()) == sz) { u8 res = searchFileSaveType(sz); if (res != 0xFF) { info.type = (res + 1); addr_size = info.addr_size = save_types[info.type].addr_size; info.size = fsize = sz; ensure(sz, fpOut); fsize = 0; } else info.type = 0; fexists = true; } } delete [] buf; } delete fpOut; } } delete fpTmp; } fpMC = new EMUFILE_FILE(filename, fexists?"rb+":"wb+"); if (!fpMC->fail()) { fsize = fpMC->size(); if (fsize < saveSizes[0]) fpMC->truncate(0); if (readFooter() == 0) fsize -= (strlen(kDesmumeSaveCookie) + strlen(DESMUME_BACKUP_FOOTER_TXT) + 24); else { memset(&info, 0, sizeof(info)); fsize = 0; } fpMC->fseek(0, SEEK_SET); u32 left = 0; if (CommonSettings.autodetectBackupMethod == 1) { if (advsc.isLoaded()) { info.type = advsc.getSaveType(); if (info.type != 0xFF && info.type != 0xFE) { info.type++; u32 adv_size = save_types[info.type].size; if (info.size > adv_size) { info.size = adv_size; fpMC->truncate(adv_size); ensure(adv_size, fpMC); } else if (info.size < adv_size) { left = adv_size - info.size; info.size = adv_size; ensure(adv_size); } fsize = adv_size; } } } addr_size = info.addr_size; info.padSize = fsize; //none of the other fields are used right now if (CommonSettings.autodetectBackupMethod != 1 && info.type == 0) { info.type = searchFileSaveType(info.size); if (info.type == 0xFF) info.type = 0; } u32 ss = (info.padSize * 8) / 1024; bool _Mbit = false; if (ss >= 1024) { ss /= 1024; _Mbit = true; } if (ss > 0) printf("Backup size: %u %cbit\n", ss, _Mbit?'M':'K'); } state = (fsize > 0)?RUNNING:DETECTING; reset(); }