int S9xMovieOpen (const char* filename, bool8 read_only) { FILE* fd; STREAM stream; int result; int fn; char movie_filename [_MAX_PATH]; #ifdef __WIN32__ _fullpath(movie_filename, filename, _MAX_PATH); #else strcpy(movie_filename, filename); #endif if(!(fd=fopen(movie_filename, "rb+"))) if(!(fd=fopen(movie_filename, "rb"))) return FILE_NOT_FOUND; else read_only = TRUE; const bool8 wasPaused = Settings.Paused; // stop current movie before opening change_state(MOVIE_STATE_NONE); // read header if((result=read_movie_header(fd, &Movie))!=SUCCESS) { fclose(fd); return result; } read_movie_extrarominfo(fd, &Movie); fn=dup(fileno(fd)); fclose(fd); // apparently this lseek is necessary lseek(fn, Movie.SaveStateOffset, SEEK_SET); if(!(stream=REOPEN_STREAM(fn, "rb"))) return FILE_NOT_FOUND; // store previous, before changing to the movie's settings store_previous_settings(); // set from movie restore_movie_settings(); if(Movie.Opts & MOVIE_OPT_FROM_RESET) { Movie.State = MOVIE_STATE_PLAY; // prevent NSRT controller switching (in S9xPostRomInit) if(!Memory.LoadLastROM()) S9xReset(); Memory.ClearSRAM(false); // in case the SRAM read fails Movie.State = MOVIE_STATE_NONE; S9xMovieResetControls(); // save only SRAM for a from-reset snapshot result=(READ_STREAM(Memory.SRAM, 0x20000, stream) == 0x20000) ? SUCCESS : WRONG_FORMAT; } else { result=S9xUnfreezeFromStream(stream); } CLOSE_STREAM(stream); if(result!=SUCCESS) { return result; } if(!(fd=fopen(movie_filename, "rb+"))) if(!(fd=fopen(movie_filename, "rb"))) return FILE_NOT_FOUND; else read_only = TRUE; if(fseek(fd, Movie.ControllerDataOffset, SEEK_SET)) return WRONG_FORMAT; // read controller data Movie.File=fd; Movie.BytesPerSample=bytes_per_sample(); Movie.InputBufferPtr=Movie.InputBuffer; uint32 to_read=Movie.BytesPerSample * (Movie.MaxSample+1); reserve_buffer_space(to_read); fread(Movie.InputBufferPtr, 1, to_read, fd); // read "baseline" controller data if(Movie.MaxSample && Movie.MaxFrame) read_frame_controller_data(true); strncpy(Movie.Filename, movie_filename, _MAX_PATH); Movie.Filename[_MAX_PATH-1]='\0'; Movie.CurrentFrame=0; Movie.CurrentSample=0; Movie.ReadOnly=read_only; change_state(MOVIE_STATE_PLAY); Settings.Paused = wasPaused; Movie.RecordedThisSession = false; S9xUpdateFrameCounter(-1); S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_REPLAY); return SUCCESS; }
int S9xMovieOpen (const char* filename, bool8 read_only, uint8 sync_flags, uint8 sync_flags2) { FILE* fd; STREAM stream; int result; int fn; char movie_filename [_MAX_PATH]; #ifdef WIN32 _fullpath(movie_filename, filename, _MAX_PATH); #else strcpy(movie_filename, filename); #endif if(!(fd=fopen(movie_filename, "rb+"))) if(!(fd=fopen(movie_filename, "rb"))) return FILE_NOT_FOUND; else read_only = TRUE; const bool8 wasPaused = Settings.Paused; const uint32 prevFrameTime = Settings.FrameTime; // stop current movie before opening change_state(MOVIE_STATE_NONE); // read header if((result=read_movie_header(fd, &Movie))!=SUCCESS) { fclose(fd); return result; } read_movie_extrarominfo(fd, &Movie); fn=dup(fileno(fd)); fclose(fd); // apparently this lseek is necessary lseek(fn, Movie.SaveStateOffset, SEEK_SET); if(!(stream=REOPEN_STREAM(fn, "rb"))) return FILE_NOT_FOUND; // store previous, before changing to the movie's settings store_previous_settings(); // store default if (sync_flags & MOVIE_SYNC_DATA_EXISTS) { Settings.UseWIPAPUTiming = (sync_flags & MOVIE_SYNC_WIP1TIMING) ? TRUE : FALSE; Settings.SoundEnvelopeHeightReading = (sync_flags & MOVIE_SYNC_VOLUMEENVX) ? TRUE : FALSE; Settings.FakeMuteFix = (sync_flags & MOVIE_SYNC_FAKEMUTE) ? TRUE : FALSE; Settings.UpAndDown = (sync_flags & MOVIE_SYNC_LEFTRIGHT) ? TRUE : FALSE; // doesn't actually affect synchronization Settings.SoundSync = (sync_flags & MOVIE_SYNC_SYNCSOUND) ? TRUE : FALSE; // doesn't seem to affect synchronization Settings.InitFastROMSetting = (sync_flags2 & MOVIE_SYNC2_INIT_FASTROM) ? TRUE : FALSE; //Settings.ShutdownMaster = (sync_flags & MOVIE_SYNC_NOCPUSHUTDOWN) ? FALSE : TRUE; } // set from movie restore_movie_settings(); if(Movie.Opts & MOVIE_OPT_FROM_RESET) { Movie.State = MOVIE_STATE_PLAY; // prevent NSRT controller switching (in S9xPostRomInit) if(!Memory.LoadLastROM()) S9xReset(); Memory.ClearSRAM(false); // in case the SRAM read fails Movie.State = MOVIE_STATE_NONE; // save only SRAM for a from-reset snapshot result=(READ_STREAM(Memory.SRAM, 0x20000, stream) == 0x20000) ? SUCCESS : WRONG_FORMAT; } else { result=S9xUnfreezeFromStream(stream); } CLOSE_STREAM(stream); if(result!=SUCCESS) { return result; } if(!(fd=fopen(movie_filename, "rb+"))) if(!(fd=fopen(movie_filename, "rb"))) return FILE_NOT_FOUND; else read_only = TRUE; if(fseek(fd, Movie.ControllerDataOffset, SEEK_SET)) return WRONG_FORMAT; // read controller data Movie.File=fd; Movie.BytesPerFrame=bytes_per_frame(); Movie.InputBufferPtr=Movie.InputBuffer; uint32 to_read=Movie.BytesPerFrame * (Movie.MaxFrame+1); reserve_buffer_space(to_read); fread(Movie.InputBufferPtr, 1, to_read, fd); // read "baseline" controller data if(Movie.MaxFrame) read_frame_controller_data(); strncpy(Movie.Filename, movie_filename, _MAX_PATH); Movie.Filename[_MAX_PATH-1]='\0'; Movie.CurrentFrame=0; Movie.ReadOnly=read_only; change_state(MOVIE_STATE_PLAY); Settings.Paused = wasPaused; Settings.FrameTime = prevFrameTime; // restore emulation speed Movie.RecordedThisSession = false; S9xUpdateFrameCounter(-1); Movie.RequiresReset = false; S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_REPLAY); return SUCCESS; }