void BackupDevice::loadfile() { //never use save files if we are in movie mode if(isMovieMode) return; if(filename.length() ==0) return; //No sense crashing if no filename supplied EMUFILE_FILE* inf = new EMUFILE_FILE(filename.c_str(),"rb"); if(inf->fail()) { delete inf; //no dsv found; we need to try auto-importing a file with .sav extension printf("DeSmuME .dsv save file not found. Trying to load an old raw .sav file.\n"); //change extension to sav char tmp[MAX_PATH]; strcpy(tmp,filename.c_str()); tmp[strlen(tmp)-3] = 0; strcat(tmp,"sav"); inf = new EMUFILE_FILE(tmp,"rb"); if(inf->fail()) { delete inf; printf("Missing save file %s\n",filename.c_str()); return; } delete inf; if (!load_no_gba(tmp)) load_raw(tmp); } else { //scan for desmume save footer const s32 cookieLen = (s32)strlen(kDesmumeSaveCookie); char *sigbuf = new char[cookieLen]; inf->fseek(-cookieLen, SEEK_END); inf->fread(sigbuf,cookieLen); int cmp = memcmp(sigbuf,kDesmumeSaveCookie,cookieLen); delete[] sigbuf; if(cmp) { //maybe it is a misnamed raw save file. try loading it that way printf("Not a DeSmuME .dsv save file. Trying to load as raw.\n"); delete inf; if (!load_no_gba(filename.c_str())) load_raw(filename.c_str()); return; } //desmume format inf->fseek(-cookieLen, SEEK_END); inf->fseek(-4, SEEK_CUR); u32 version = 0xFFFFFFFF; read32le(&version,inf); if(version!=0) { printf("Unknown save file format\n"); return; } inf->fseek(-24, SEEK_CUR); read32le(&info.size,inf); read32le(&info.padSize,inf); read32le(&info.type,inf); read32le(&info.addr_size,inf); read32le(&info.mem_size,inf); u32 left = 0; if (CommonSettings.autodetectBackupMethod == 1) { if (advsc.isLoaded()) { info.type = advsc.getSaveType(); if (info.type != 0xFF || info.type != 0xFE) { u32 adv_size = save_types[info.type+1][1]; if (info.size > adv_size) info.size = adv_size; else if (info.size < adv_size) { left = adv_size - info.size; info.size = adv_size; } } } } //establish the save data resize(info.size); inf->fseek(0, SEEK_SET); if(info.size>0) inf->fread(&data[0],info.size - left); //read all the raw data we have state = RUNNING; addr_size = info.addr_size; //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.size * 8 / 1024; if (ss >= 1024) { ss /= 1024; printf("Backup size: %i Mbit\n", ss); } else printf("Backup size: %i Kbit\n", ss); delete inf; } }
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(); }