void chacha_ivsetup(chacha_ctx_t *x,const unsigned char *iv) { x->input[12] = 0; x->input[13] = read32le((uint32_t *)(iv + 0)); /* Modified for 12-byte iv */ x->input[14] = read32le((uint32_t *)(iv + 4)); x->input[15] = read32le((uint32_t *)(iv + 8)); }
bool savestate_load(EMUFILE* is) { SAV_silent_fail_flag = false; char header[16]; is->fread(header,16); if(is->fail() || memcmp(header,magic,16)) return false; u32 ssversion,len,comprlen; if(!read32le(&ssversion,is)) return false; if(!read32le(&_DESMUME_version,is)) return false; if(!read32le(&len,is)) return false; if(!read32le(&comprlen,is)) return false; if(ssversion != SAVESTATE_VERSION) return false; std::vector<u8> buf(len); is->fread((char*)&buf[0],len-32); //GO!! READ THE SAVESTATE //THERE IS NO GOING BACK NOW //reset the emulator first to clean out the host's state NDS_Reset(); //reset some options to their old defaults which werent saved nds._DebugConsole = FALSE; //GPU_Reset(MainScreen.gpu, 0); //GPU_Reset(SubScreen.gpu, 1); //gfx3d_reset(); //gpu3D->NDS_3D_Reset(); //SPU_Reset(); EMUFILE_MEMORY mstemp(&buf); bool x = ReadStateChunks(&mstemp,(s32)len); if(!x && !SAV_silent_fail_flag) { msgbox->error("Error loading savestate. It failed halfway through;\nSince there is no savestate backup system, your current game session is wrecked"); return false; } loadstate(); if(nds.ConsoleType != CommonSettings.ConsoleType) { printf("WARNING: forcing console type to: ConsoleType=%d\n",nds.ConsoleType); } if((nds._DebugConsole!=0) != CommonSettings.DebugConsole) { printf("WARNING: forcing console debug mode to: debugmode=%s\n",nds._DebugConsole?"TRUE":"FALSE"); } return true; }
int readbool(bool *b, EMUFILE* is) { u32 temp; int ret = read32le(&temp,is); *b = temp!=0; return ret; }
int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp) { if(fp->type>=1) { uint8 t[4]; #ifndef LSB_FIRST uint8 x[4]; #endif if(fp->type>=2) { MEMWRAP *wz; wz=(MEMWRAP *)fp->fp; if(wz->location+4>wz->size) {return 0;} *(uint32 *)t=*(uint32 *)(wz->data+wz->location); wz->location+=4; } else if(fp->type==1) gzread(fp->fp,&t,4); #ifndef LSB_FIRST x[0]=t[3]; x[1]=t[2]; x[2]=t[1]; x[3]=t[0]; *(uint32*)Bufo=*(uint32*)x; #else *(uint32*)Bufo=*(uint32*)t; #endif return 1; } else { return read32le(Bufo,(FILE *)fp->fp); } }
static int ReadStateChunk(FILE *st, SFORMAT *sf, int size) { SFORMAT *tmp; int temp; temp=ftell(st); while(ftell(st)<temp+size) { uint32 tsize; char toa[4]; if(fread(toa,1,4,st)<=0) return 0; read32le(&tsize,st); if((tmp=CheckS(sf,tsize,toa))) { fread((uint8 *)tmp->v,1,tmp->s&(~RLSB),st); #ifndef LSB_FIRST if(tmp->s&RLSB) FlipByteOrder(tmp->v,tmp->s&(~RLSB)); #endif } else fseek(st,tsize,SEEK_CUR); } // while(...) return 1; }
static int ReadStateChunks(FILE *st, int32 totalsize) { int t; uint32 size; int ret=1; while(totalsize > 0) { t=fgetc(st); if(t==EOF) break; if(!read32le(&size,st)) break; totalsize -= size + 5; switch(t) { case 1:if(!ReadStateChunk(st,SFCPU,size)) ret=0;break; case 2:if(!ReadStateChunk(st,SFCPUC,size)) ret=0; else { X.mooPI=X.P; // Quick and dirty hack. } break; case 3:if(!ReadStateChunk(st,FCEUPPU_STATEINFO,size)) ret=0;break; case 4:if(!ReadStateChunk(st,FCEUCTRL_STATEINFO,size)) ret=0;break; case 5:if(!ReadStateChunk(st,FCEUSND_STATEINFO,size)) ret=0;break; case 0x10:if(!ReadStateChunk(st,SFMDATA,size)) ret=0; break; default: if(fseek(st,size,SEEK_CUR)<0) goto endo;break; } } endo: return ret; }
static int ReadStateChunk(FILE *st, SFORMAT *sf, int size) { //if(scan_chunks) // return fseek(st,size,SEEK_CUR) == 0; SFORMAT *tmp; int temp; temp=ftell(st); while(ftell(st)<temp+size) { uint32 tsize; char toa[4]; if(fread(toa,1,4,st)<=0) return 0; read32le(&tsize,st); if((tmp=CheckS(sf,tsize,toa))) { fread((uint8 *)tmp->v,1,tmp->s&(~RLSB),st); #ifndef LSB_FIRST if(tmp->s&RLSB) FlipByteOrder(tmp->v,tmp->s&(~RLSB)); #endif } else { fseek(st,tsize,SEEK_CUR); printf("ReadStateChunk: sect \"%c%c%c%c\" not handled\n", toa[0], toa[1], toa[2], toa[3]); } } // while(...) return 1; }
int readbuffer(std::vector<u8> &vec, EMUFILE* is) { u32 size; if(read32le(&size,is) != 1) return 0; vec.resize(size); if(size>0) is->fread((char*)&vec[0],size); return 1; }
static bool ReadStateChunk(EMUFILE* is, const SFORMAT *sf, int size) { const SFORMAT *tmp = NULL; const SFORMAT *guessSF = NULL; int temp = is->ftell(); while(is->ftell()<temp+size) { u32 sz, count; char toa[4]; is->fread(toa,4); if(is->fail()) return false; if(!read32le(&sz,is)) return false; if(!read32le(&count,is)) return false; if((tmp=CheckS(guessSF,sf,sz,count,toa))) { #ifdef MSB_FIRST if(sz == 1) { //special case: read a huge byte array is->fread((char *)tmp->v,count); } else { for(unsigned int i=0;i<count;i++) { is->fread((char *)tmp->v + i*sz,sz); FlipByteOrder((u8*)tmp->v + i*sz,sz); } } #else // no need to ever loop one at a time if not flipping byte order is->fread((char *)tmp->v,sz*count); #endif guessSF = tmp + 1; } else { is->fseek(sz*count,SEEK_CUR); guessSF = NULL; } } // while(...) return true; }
void EMUFILE::readMemoryStream(EMUFILE_MEMORY* ms) { s32 size = read32le(); if(size != 0) { std::vector<u8> temp(size); fread(&temp[0],size); ms->fwrite(&temp[0],size); } }
bool BackupDevice::load_state(EMUFILE* is) { u32 version; if(read32le(&version,is)!=1) return false; if(version>=0) { readbool(&write_enable,is); read32le(&com,is); read32le(&addr_size,is); read32le(&addr_counter,is); u32 temp; read32le(&temp,is); state = (STATE)temp; readbuffer(data,is); readbuffer(data_autodetect,is); } if(version>=1) read32le(&addr,is); if(version>=2) { read8le(&motionInitState,is); read8le(&motionFlag,is); } return true; }
bool BackupDevice::load_state(EMUFILE* is) { u32 version; u32 temp; std::vector<u8> data; if(read32le(&version,is)!=1) return false; if(version>=0) { readbool(&write_enable,is); read32le(&com,is); read32le(&addr_size,is); read32le(&addr_counter,is); read32le(&temp,is); state = (STATE)temp; readbuffer(data,is); readbuffer(data_autodetect,is); } if(version>=1) read32le(&addr,is); if(version>=2) { read8le(&motionInitState,is); read8le(&motionFlag,is); } if(version>=3) { readbool(&reset_command_state,is); } if(version>=4) { read8le(&write_protect,is); } fsize = data.size(); #ifndef _DONT_SAVE_BACKUP fpMC->fseek(0, SEEK_SET); if(data.size()!=0) fwrite((char*)&data[0], 1, fsize, fpMC->get_fp()); ensure(data.size(), fpMC); #endif if(version>=5) { read32le(&temp,is); fpMC->fseek(temp, SEEK_SET); } else fpMC->fseek(addr, SEEK_SET); return true; }
bool BackupDevice::load_state(std::istream* is) { int version; if(read32le(&version,is)!=1) return false; if(version==0 || version==1) { read32le(&write_enable,is); read32le(&com,is); read32le(&addr_size,is); read32le(&addr_counter,is); u32 temp; read32le(&temp,is); state = (STATE)temp; readbuffer(data,is); readbuffer(data_autodetect,is); if(version==1) read32le(&addr,is); } return true; }
static bool cp15_loadstate(EMUFILE* is, int size) { //read version u32 version; if(read32le(&version,is) != 1) return false; if(version > 1) return false; if(!cp15.loadone(is)) return false; if(version == 0) { //ARM7 not have coprocessor u8 *tmp_buf = new u8 [sizeof(armcp15_t)]; if (!tmp_buf) return false; if(!cp15.loadone(is)) return false; delete [] tmp_buf; tmp_buf = NULL; } return true; }
//! Decompress GBA LZ77 data. uint lz77gba_decompress(RECORD *dst, const RECORD *src) { assert(dst && src && src->data); if(dst==NULL || src==NULL || src->data==NULL) return 0; // Get and check header word u32 header= read32le(src->data); if((header&255) != CPRS_LZ77_TAG) return 0; u32 flags; int ii, jj, dstS= header>>8; u8 *srcL= src->data+4, *dstD= (BYTE*)malloc(dstS); for(ii=0, jj=-1; ii<dstS; jj--) { if(jj<0) // Get block flags { flags= *srcL++; jj= 7; } if(flags>>jj & 1) // Compressed stint { int count= (srcL[0]>>4)+THRESHOLD+1; int ofs= ((srcL[0]&15)<<8 | srcL[1])+1; srcL += 2; while(count--) { dstD[ii]= dstD[ii-ofs]; ii++; } } else // Single byte from source dstD[ii++]= *srcL++; }
// returns true if couldn't load bool SNAPSHOT::load(EMUFILE *is) { uint8 tmp; // read vars if (!read32le(&keyFrame, is)) return true; if (!read32le(&startFrame, is)) return true; if (!read32le(&endFrame, is)) return true; if (!read32le(&consecutivenessTag, is)) return true; if (!read32le(&recordedJoypadDifferenceBits, is)) return true; if (!read32le(&modificationType, is)) return true; // read description if (!read8le(&tmp, is)) return true; if (tmp >= SNAPSHOT_DESCRIPTION_MAX_LEN) return true; if (is->fread(&description[0], tmp) != tmp) return true; description[tmp] = 0; // add '0' because it wasn't saved in the file // load InputLog data if (inputlog.load(is)) return true; // load LagLog data if (laglog.load(is)) return true; // load Markers data if (markers.load(is)) return true; return false; }
static const char* convertToFCM(const char *fname, char *buffer) { #ifdef WIN32 justAutoConverted=0; // convert to fcm if not already const char* dot = strrchr(fname, '.'); if(dot) { int fmv = !stricmp(dot, ".fmv"); int nmv = !stricmp(dot, ".nmv"); int vmv = !stricmp(dot, ".vmv"); if(fmv || nmv || vmv) { strcpy(buffer, fname); buffer[dot-fname]='\0'; strcat(buffer,"-autoconverted.fcm"); int fceuver=0; if(fmv) fceuver=1; else if(nmv) fceuver=2; else if(vmv) fceuver=3; extern char lastLoadedGameName [2048]; char cmd [1024], offset[64], romInfo[1024]; if(movieConvertOK) sprintf(romInfo, "-smd5=\"%s\" -sromname=\"%s (MAYBE)\" -s", lastLoadedGameName, FileBase); else sprintf(romInfo, "-sromname=\"(unknown)\" -s"); if(movieConvertOffset2) sprintf(offset, "-o %d:%d", movieConvertOffset2,movieConvertOffset1); else sprintf(offset, "-o %d", movieConvertOffset1); sprintf(cmd, ".\\util\\nesmock\\nesmock.exe %s %s -spal=%c -sfceuver=%d \"%s\" \"%s\" ", offset, romInfo, FCEUI_GetCurrentVidSystem(0,0)?'1':'0', fceuver, fname, buffer); // FCEU_PrintError(cmd); executeCommand(cmd); FILE* file = FCEUD_UTF8fopen(buffer,"rb"); if(file) { fseek(file, 12, SEEK_SET); int frames=0; read32le(&frames, file); if(frames) { fname = buffer; justAutoConverted=1; } else { static int errAlready=0; if(!errAlready) { errAlready=1; FCEU_PrintError("For some reason, nesmock was unable to create a valid FCM from the given file.\nThe command given was:\n%s\nPerhaps the file specified is not a movie file or contains no input data,\nor perhaps it is a movie file of a version unsupported by nesmock.\n\n(This error message will self-destruct until you restart FCEU.)", cmd); } } fclose(file); } else { char str [512]; str[0] = '\0'; GetCurrentDirectory(512,str); strcat(str, "\\util\\nesmock\\nesmock.exe"); file = FCEUD_UTF8fopen(str, "rb"); if(file) { static int errAlready=0; if(!errAlready) { errAlready=1; FCEU_PrintError("For some reason, nesmock was unable to convert the movie to FCM format.\nThe command given was:\n%s\n\n(This error message will self-destruct until you restart FCEU.)", cmd); fclose(file); } } else { static int errAlready=0; if(!errAlready) { errAlready=1; FCEU_PrintError("Nesmock not found, so the movie could not be converted to FCM format.\nYou must place nesmock.exe at this location so FCEU can find it:\n%s\n\n(This error message will self-destruct until you restart FCEU.)", str); } } } } } #endif return fname; }
// returns true if couldn't load bool HISTORY::load(EMUFILE *is, unsigned int offset) { int i = -1; SNAPSHOT snap; BOOKMARK bookm; if (offset) { if (is->fseek(offset, SEEK_SET)) goto error; } else { reset(); return false; } // read "HISTORY" string char save_id[HISTORY_ID_LEN]; if ((int)is->fread(save_id, HISTORY_ID_LEN) < HISTORY_ID_LEN) goto error; if (!strcmp(historySkipSaveID, save_id)) { // string says to skip loading History FCEU_printf("No History in the file\n"); reset(); return false; } if (strcmp(historySaveID, save_id)) goto error; // string is not valid // delete old items snapshots.resize(historySize); bookmarkBackups.resize(historySize); currentBranchNumberBackups.resize(historySize); // read vars if (!read32le(&historyCursorPos, is)) goto error; if (!read32le(&historyTotalItems, is)) goto error; if (historyCursorPos > historyTotalItems) goto error; historyStartPos = 0; // read items int total = historyTotalItems; if (historyTotalItems > historySize) { // user can't afford that much undo levels, skip some items int num_items_to_skip = historyTotalItems - historySize; // first try to skip items over history_cursor_pos (future items), because "redo" is less important than "undo" int num_redo_items = historyTotalItems-1 - historyCursorPos; if (num_items_to_skip >= num_redo_items) { // skip all redo items historyTotalItems = historyCursorPos+1; num_items_to_skip -= num_redo_items; // and still need to skip some undo items for (i = 0; i < num_items_to_skip; ++i) { if (snap.skipLoad(is)) goto error; if (bookm.skipLoad(is)) goto error; if (is->fseek(1, SEEK_CUR)) goto error; // backup_current_branch } total -= num_items_to_skip; historyCursorPos -= num_items_to_skip; } historyTotalItems -= num_items_to_skip; } // load items for (i = 0; i < historyTotalItems; ++i) { if (snapshots[i].load(is)) goto error; if (bookmarkBackups[i].load(is)) goto error; if (is->fread(¤tBranchNumberBackups[i], 1) != 1) goto error; playback.setProgressbar(i, historyTotalItems); } // skip redo items if needed for (; i < total; ++i) { if (snap.skipLoad(is)) goto error; if (bookm.skipLoad(is)) goto error; if (is->fseek(1, SEEK_CUR)) goto error; // backup_current_branch } // everything went well // init vars undoHintPos = oldUndoHintPos = undoHintTimer = -1; oldShowUndoHint = showUndoHint = false; updateList(); redrawList(); return false; error: FCEU_printf("Error loading History\n"); reset(); return true; }
u32 EMUFILE::read32le() { u32 ret; read32le(&ret); return ret; }
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; } }
bool armcp15_t::loadone(EMUFILE* is) { if(!read32le(&IDCode,is)) return false; if(!read32le(&cacheType,is)) return false; if(!read32le(&TCMSize,is)) return false; if(!read32le(&ctrl,is)) return false; if(!read32le(&DCConfig,is)) return false; if(!read32le(&ICConfig,is)) return false; if(!read32le(&writeBuffCtrl,is)) return false; if(!read32le(&und,is)) return false; if(!read32le(&DaccessPerm,is)) return false; if(!read32le(&IaccessPerm,is)) return false; for(int i=0;i<8;i++) if(!read32le(&protectBaseSize[i],is)) return false; if(!read32le(&cacheOp,is)) return false; if(!read32le(&DcacheLock,is)) return false; if(!read32le(&IcacheLock,is)) return false; if(!read32le(&ITCMRegion,is)) return false; if(!read32le(&DTCMRegion,is)) return false; if(!read32le(&processID,is)) return false; if(!read32le(&RAM_TAG,is)) return false; if(!read32le(&testState,is)) return false; if(!read32le(&cacheDbg,is)) return false; for(int i=0;i<8;i++) if(!read32le(®ionWriteMask_USR[i],is)) return false; for(int i=0;i<8;i++) if(!read32le(®ionWriteMask_SYS[i],is)) return false; for(int i=0;i<8;i++) if(!read32le(®ionReadMask_USR[i],is)) return false; for(int i=0;i<8;i++) if(!read32le(®ionReadMask_SYS[i],is)) return false; for(int i=0;i<8;i++) if(!read32le(®ionExecuteMask_USR[i],is)) return false; for(int i=0;i<8;i++) if(!read32le(®ionExecuteMask_SYS[i],is)) return false; for(int i=0;i<8;i++) if(!read32le(®ionWriteSet_USR[i],is)) return false; for(int i=0;i<8;i++) if(!read32le(®ionWriteSet_SYS[i],is)) return false; for(int i=0;i<8;i++) if(!read32le(®ionReadSet_USR[i],is)) return false; for(int i=0;i<8;i++) if(!read32le(®ionReadSet_SYS[i],is)) return false; for(int i=0;i<8;i++) if(!read32le(®ionExecuteSet_USR[i],is)) return false; for(int i=0;i<8;i++) if(!read32le(®ionExecuteSet_SYS[i],is)) return false; return true; }
size_t EMUFILE::read32le(s32* Bufo) { return read32le((u32*)Bufo); }
void chacha_keysetup(chacha_ctx_t *x, const unsigned char *k, unsigned kbits) { const char *constants; x->input[4] = read32le((uint32_t *)(k + 0)); x->input[5] = read32le((uint32_t *)(k + 4)); x->input[6] = read32le((uint32_t *)(k + 8)); x->input[7] = read32le((uint32_t *)(k + 12)); if (kbits == 256) { /* recommended */ k += 16; constants = sigma; } else { /* kbits == 128 */ constants = tau; } x->input[8] = read32le((uint32_t *)(k + 0)); x->input[9] = read32le((uint32_t *)(k + 4)); x->input[10] = read32le((uint32_t *)(k + 8)); x->input[11] = read32le((uint32_t *)(k + 12)); x->input[0] = read32le((uint32_t *)(constants + 0)); x->input[1] = read32le((uint32_t *)(constants + 4)); x->input[2] = read32le((uint32_t *)(constants + 8)); x->input[3] = read32le((uint32_t *)(constants + 12)); }
// returns true if couldn't load bool GREENZONE::load(EMUFILE *is, unsigned int offset) { free(); if (offset) { if (is->fseek(offset, SEEK_SET)) goto error; } else { reset(); playback.restartPlaybackFromZeroGround(); // reset Playback cursor to frame 0 return false; } int frame = 0, prev_frame = -1, size = 0; int last_tick = 0; // read "GREENZONE" string char save_id[GREENZONE_ID_LEN]; if ((int)is->fread(save_id, GREENZONE_ID_LEN) < GREENZONE_ID_LEN) goto error; if (!strcmp(greenzone_skipsave_id, save_id)) { // string says to skip loading Greenzone // read LagLog lagLog.load(is); // read Playback cursor position if (read32le(&frame, is)) { currFrameCounter = frame; greenzoneSize = currFrameCounter + 1; savestates.resize(greenzoneSize); if (currFrameCounter) { // there must be one savestate in the file if (read32le(&size, is) && size >= 0) { savestates[frame].resize(size); if (is->fread(&savestates[frame][0], size) == size) { if (loadSavestateOfFrame(currFrameCounter)) { FCEU_printf("No Greenzone in the file\n"); return false; } } } } else { // literally no Greenzone in the file, but this is still not a error reset(); playback.restartPlaybackFromZeroGround(); // reset Playback cursor to frame 0 FCEU_printf("No Greenzone in the file, Playback at frame 0\n"); return false; } } goto error; } if (strcmp(greenzone_save_id, save_id)) goto error; // string is not valid // read LagLog lagLog.load(is); // read size if (read32le(&size, is) && size >= 0 && size <= currMovieData.getNumRecords()) { greenzoneSize = size; savestates.resize(greenzoneSize); // read Playback cursor position if (read32le(&frame, is)) { currFrameCounter = frame; int greenzone_tail_frame = currFrameCounter - taseditorConfig.greenzoneCapacity; int greenzone_tail_frame2 = greenzone_tail_frame - 2 * taseditorConfig.greenzoneCapacity; int greenzone_tail_frame4 = greenzone_tail_frame - 4 * taseditorConfig.greenzoneCapacity; int greenzone_tail_frame8 = greenzone_tail_frame - 8 * taseditorConfig.greenzoneCapacity; int greenzone_tail_frame16 = greenzone_tail_frame - 16 * taseditorConfig.greenzoneCapacity; // read savestates while(1) { if (!read32le(&frame, is)) break; if (frame < 0) break; // -1 = eof // update TASEditor progressbar from time to time if (frame / PROGRESSBAR_UPDATE_RATE > last_tick) { playback.setProgressbar(frame, greenzoneSize); last_tick = frame / PROGRESSBAR_UPDATE_RATE; } // read savestate if (!read32le(&size, is)) break; if (size < 0) break; if (frame <= greenzone_tail_frame16 || (frame <= greenzone_tail_frame8 && (frame & 0xF)) || (frame <= greenzone_tail_frame4 && (frame & 0x7)) || (frame <= greenzone_tail_frame2 && (frame & 0x3)) || (frame <= greenzone_tail_frame && (frame & 0x1))) { // skip loading this savestate if (is->fseek(size, SEEK_CUR) != 0) break; } else { // load this savestate if ((int)savestates.size() <= frame) savestates.resize(frame + 1); savestates[frame].resize(size); if ((int)is->fread(&savestates[frame][0], size) < size) break; prev_frame = frame; // successfully read one Greenzone frame info } } if (prev_frame+1 == greenzoneSize) { // everything went fine - load savestate at cursor position if (loadSavestateOfFrame(currFrameCounter)) return false; } // uh, okay, but maybe we managed to read at least something useful from the file // first see if original position of currFrameCounter was read successfully if (loadSavestateOfFrame(currFrameCounter)) { greenzoneSize = prev_frame+1; // cut greenZoneCount to last good frame FCEU_printf("Greenzone loaded partially\n"); return false; } // then at least jump to some frame that was read successfully for (; prev_frame >= 0; prev_frame--) { if (loadSavestateOfFrame(prev_frame)) { currFrameCounter = prev_frame; greenzoneSize = prev_frame+1; // cut greenZoneCount to this good frame FCEU_printf("Greenzone loaded partially, Playback moved to the end of greenzone\n"); return false; } } } } error: FCEU_printf("Error loading Greenzone\n"); reset(); playback.restartPlaybackFromZeroGround(); // reset Playback cursor to frame 0 return true; }
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 FILE* inf = fopen(filename.c_str(),"rb"); if(!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 = fopen(tmp,"rb"); if(!inf) { printf("Missing save file %s\n",filename.c_str()); return; } fclose(inf); load_raw(tmp); } else { //scan for desmume save footer const u32 cookieLen = strlen(kDesmumeSaveCookie); char *sigbuf = new char[cookieLen]; fseek(inf, -cookieLen, SEEK_END); fread(sigbuf,1,cookieLen,inf); 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"); fclose(inf); load_raw(filename.c_str()); return; } //desmume format fseek(inf, -cookieLen, SEEK_END); fseek(inf, -4, SEEK_CUR); u32 version = 0xFFFFFFFF; read32le(&version,inf); if(version!=0) { printf("Unknown save file format\n"); return; } fseek(inf, -24, SEEK_CUR); struct { u32 size,padSize,type,addr_size,mem_size; } info; read32le(&info.size,inf); read32le(&info.padSize,inf); read32le(&info.type,inf); read32le(&info.addr_size,inf); read32le(&info.mem_size,inf); //establish the save data data.resize(info.size); fseek(inf, 0, SEEK_SET); if(info.size>0) fread(&data[0],1,info.size,inf); //read all the raw data we have state = RUNNING; addr_size = info.addr_size; //none of the other fields are used right now fclose(inf); } }
uint32_t read32(bool be,void *p) { return (be)?(read32be(p)):(read32le(p)); }
static bool ReadStateChunks(EMUFILE* is, s32 totalsize) { bool ret = true; bool haveInfo = false; s64 save_time = 0; u32 romsize = 0; u8 version_major = 0; u8 version_minor = 0; u8 version_build = 0; NDS_header header; SFORMAT SF_INFO[]={ { "GINF", 1, sizeof(header), &header}, { "GRSZ", 1, 4, &romsize}, { "DVMJ", 1, 1, &version_major}, { "DVMI", 1, 1, &version_minor}, { "DSBD", 1, 1, &version_build}, { "GREV", 1, 4, &svn_rev}, { "GTIM", 1, 8, &save_time}, { 0 } }; memset(&header, 0, sizeof(header)); while(totalsize > 0) { u32 size = 0; u32 t = 0; if(!read32le(&t,is)) { ret=false; break; } if(t == 0xFFFFFFFF) break; if(!read32le(&size,is)) { ret=false; break; } switch(t) { case 1: if(!ReadStateChunk(is,SF_ARM9,size)) ret=false; break; case 2: if(!ReadStateChunk(is,SF_ARM7,size)) ret=false; break; case 3: if(!cp15_loadstate(is,size)) ret=false; break; case 4: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break; case 5: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break; case 51: if(!nds_loadstate(is,size)) ret=false; break; case 60: if(!ReadStateChunk(is,SF_MMU,size)) ret=false; break; case 61: if(!mmu_loadstate(is,size)) ret=false; break; case 7: if(!gpu_loadstate(is,size)) ret=false; break; case 8: if(!spu_loadstate(is,size)) ret=false; break; case 81: if(!mic_loadstate(is,size)) ret=false; break; case 90: if(!ReadStateChunk(is,SF_GFX3D,size)) ret=false; break; case 91: if(!gfx3d_loadstate(is,size)) ret=false; break; case 100: if(!ReadStateChunk(is,SF_MOVIE, size)) ret=false; break; case 101: break; case 110: if(!ReadStateChunk(is,SF_WIFI,size)) ret=false; break; case 120: if(!ReadStateChunk(is,SF_RTC,size)) ret=false; break; case 130: if(!ReadStateChunk(is,SF_INFO,size)) ret=false; break; case 140: if(!s_slot1_loadstate(is, size)) ret=false; break; case 150: if(!s_slot2_loadstate(is, size)) ret=false; break; // reserved for future versions case 160: case 170: case 180: if(!ReadStateChunk(is,reserveChunks,size)) ret=false; break; // ============================ default: return false; } if(!ret) return false; } return ret; }
static bool mmu_loadstate(EMUFILE* is, int size) { //read version u32 version; if(read32le(&version,is) != 1) return false; if(version == 0 || version == 1) { u32 bupmem_size; u32 addr_size; if(version == 0) { //version 0 was buggy and didnt save the type. //it would silently fail if there was a size mismatch SAV_silent_fail_flag = true; if(read32le(&bupmem_size,is) != 1) return false; //if(bupmem_size != MMU.bupmem.size) return false; //mismatch between current initialized and saved size addr_size = BackupDevice::addr_size_for_old_save_size(bupmem_size); } else if(version == 1) { //version 1 reinitializes the save system with the type that was saved u32 bupmem_type; if(read32le(&bupmem_type,is) != 1) return false; if(read32le(&bupmem_size,is) != 1) return false; addr_size = BackupDevice::addr_size_for_old_save_type(bupmem_type); if(addr_size == 0xFFFFFFFF) addr_size = BackupDevice::addr_size_for_old_save_size(bupmem_size); } if(addr_size == 0xFFFFFFFF) return false; u8* temp = new u8[bupmem_size]; is->fread((char*)temp,bupmem_size); MMU_new.backupDevice.load_old_state(addr_size,temp,bupmem_size); delete[] temp; if(is->fail()) return false; } if(version < 2) return true; bool ok = MMU_new.backupDevice.load_state(is); if(version < 3) return ok; ok &= MMU_new.gxstat.loadstate(is); for(int i=0;i<2;i++) for(int j=0;j<4;j++) ok &= MMU_new.dma[i][j].loadstate(is); ok &= MMU_timing.arm9codeFetch.loadstate(is, version); ok &= MMU_timing.arm9dataFetch.loadstate(is, version); ok &= MMU_timing.arm7codeFetch.loadstate(is, version); ok &= MMU_timing.arm7dataFetch.loadstate(is, version); ok &= MMU_timing.arm9codeCache.loadstate(is, version); ok &= MMU_timing.arm9dataCache.loadstate(is, version); if(version < 4) return ok; ok &= MMU_new.sqrt.loadstate(is,version); ok &= MMU_new.div.loadstate(is,version); //to prevent old savestates from confusing IF bits, mask out ones which had been stored but should have been generated MMU.reg_IF_bits[0] &= ~0x00200000; MMU.reg_IF_bits[1] &= ~0x00000000; MMU_new.gxstat.fifo_low = gxFIFO.size <= 127; MMU_new.gxstat.fifo_empty = gxFIFO.size == 0; if(version < 5) MMU.reg_DISP3DCNT_bits = T1ReadWord(MMU.ARM9_REG,0x60); if(version < 6) return ok; MMU_new.dsi_tsc.load_state(is); //version 6 if(version < 7) { //recover WRAMCNT from the stashed WRAMSTAT memory location MMU.WRAMCNT = MMU.MMU_MEM[ARMCPU_ARM7][0x40][0x241]; } if(version<8) return ok; //version 8: delete[] MMU.fw.data; MMU.fw.size = is->read32le(); MMU.fw.data = new u8[size]; is->fread(MMU.fw.data,MMU.fw.size); return ok; }
// PlayMovie / MoviePlay function void FCEUI_LoadMovie(char *fname, int _read_only) { char buffer [512]; fname = (char*)convertToFCM(fname,buffer); FILE *fp; char *fn = NULL; FCEUI_StopMovie(); #if 0 if(!fname) fname = fn = FCEU_MakeFName(FCEUMKF_MOVIE,CurrentMovie,0); #endif #if 0 char origname[512]; strcpy(origname,fname); #endif // check movie_readonly movie_readonly = _read_only; if(access(fname, W_OK)) movie_readonly = 2; fp = fopen(fname, (movie_readonly>=2) ? "rb" : "r+b"); if(fn) { free(fn); fname = NULL; } if(!fp) return; // read header { uint32 magic; uint32 version; uint8 flags[4]; read32le(&magic, fp); if(magic != MOVIE_MAGIC) { fclose(fp); return; } //DEBUG_COMPARE_RAM(__LINE__); read32le(&version, fp); if(version == 1) { // attempt to load previous version's format fclose(fp); printf("movie: trying movie v1\n"); FCEUI_LoadMovie_v1(fname, _read_only); return; } else if(version == MOVIE_VERSION) {} else { // unsupported version printf("movie: unsupported version\n"); fclose(fp); return; } fread(flags, 1, 4, fp); read32le(&framecount, fp); read32le(&rerecord_count, fp); read32le(&moviedatasize, fp); read32le(&savestate_offset, fp); read32le(&firstframeoffset, fp); if(fseek(fp, savestate_offset, SEEK_SET)) { fclose(fp); return; } // FCEU_PrintError("flags[0] & MOVIE_FLAG_NOSYNCHACK=%d",flags[0] & MOVIE_FLAG_NOSYNCHACK); if(flags[0] & MOVIE_FLAG_NOSYNCHACK) movieSyncHackOn=0; else movieSyncHackOn=1; } // fully reload the game to reinitialize everything before playing any movie // to try fixing nondeterministic playback of some games #if 0 // do we need this? { extern char lastLoadedGameName [2048]; #if 0 // TODO? extern int disableBatteryLoading, suppressAddPowerCommand; suppressAddPowerCommand=1; suppressMovieStop=1; #endif { FCEUGI * gi = FCEUI_LoadGame(lastLoadedGameName); if(!gi) PowerNES(); } #if 0 // TODO? suppressMovieStop=0; suppressAddPowerCommand=0; #endif } #endif // Loading new savestates doesn't work and even breaks FDS //if(!FCEUSS_LoadFP(fp,1)) return; ResetInputTypes(); fseek(fp, firstframeoffset, SEEK_SET); moviedata = (uint8*)realloc(moviedata, moviedatasize); fread(moviedata, 1, moviedatasize, fp); framecount = 0; // movies start at frame 0! frameptr = 0; current = CurrentMovie; slots[current] = fp; memset(joop,0,sizeof(joop)); current = -1 - current; framets=0; nextts=0; nextd = -1; MovieStatus[CurrentMovie] = 1; #if 0 if(!fname) FCEUI_SelectMovie(CurrentMovie,1); /* Quick hack to display status. */ else #endif FCEU_DispMessage("Movie playback started."); #if 0 strcpy(curMovieFilename, origname); #else strcpy(curMovieFilename, fname); #endif }