Fixes to backup savestate system, starting of undo savestate implementation.
This commit is contained in:
parent
20ef5a722c
commit
93c48afbb6
|
@ -336,6 +336,7 @@ BEGIN
|
|||
MENUITEM "&Replay Movie", FCEUX_CONTEXT_REPLAYMOVIE
|
||||
MENUITEM "Record Movie", FCEUX_CONTEXT_RECORDMOVIE
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Undo savestate", FCEUX_CONTEXT_UNDOSAVESTATE
|
||||
MENUITEM "Undo loadstate", FCEUX_CONTEXT_UNDOLOADSTATE
|
||||
MENUITEM "Rewind to last auto-save", FCEUX_CONTEXT_REWINDTOLASTAUTO
|
||||
MENUITEM "Screenshot", FCEUX_CONTEXT_SCREENSHOT
|
||||
|
|
|
@ -381,7 +381,6 @@
|
|||
#define MEMW_EDIT03RMADDRESS 1191
|
||||
#define IDC_DEBUGGER_RESTORESIZE 1191
|
||||
#define MEMW_EDIT04RMADDRESS 1192
|
||||
#define IDC_MOVIE_CANCEL 1192
|
||||
#define IDC_MOVIE_CLOSE 1192
|
||||
#define EDIT00_RESULTS 1193
|
||||
#define IDC_MOVIE_PAUSEAFTERPLAYBACK 1193
|
||||
|
@ -636,6 +635,8 @@
|
|||
#define FCEUX_CONTEXT_MAKEBACKUP 40320
|
||||
#define ID_CONFIG_MOVIEOPTIONS 40321
|
||||
#define MENU_MOVIEOPTIONS 40322
|
||||
#define ID_GAME_UNDOSAVESTATE 40323
|
||||
#define FCEUX_CONTEXT_UNDOSAVESTATE 40324
|
||||
#define IDC_DEBUGGER_ICONTRAY 55535
|
||||
#define MW_ValueLabel2 65423
|
||||
#define MW_ValueLabel1 65426
|
||||
|
@ -645,7 +646,7 @@
|
|||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 125
|
||||
#define _APS_NEXT_COMMAND_VALUE 40323
|
||||
#define _APS_NEXT_COMMAND_VALUE 40325
|
||||
#define _APS_NEXT_CONTROL_VALUE 1199
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
|
|
|
@ -93,8 +93,8 @@ char *md5_asciistr(uint8 digest[16]);
|
|||
void ShowNetplayConsole(void); //mbg merge 7/17/06 YECH had to add
|
||||
void MapInput(void);
|
||||
extern BOOL CALLBACK ReplayMetadataDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); //Metadata dialog
|
||||
|
||||
extern bool CheckFileExists(const char* filename); //Receives a filename (fullpath) and checks to see if that file exists
|
||||
extern void SwapSaveState();
|
||||
|
||||
//AutoFire-----------------------------------------------
|
||||
void SetAutoFirePattern(int onframes, int offframes);
|
||||
|
@ -1301,6 +1301,11 @@ UpdateContextMenuItems(hfceuxcontextsub, whichContext);
|
|||
CreateDialog(fceu_hInstance, "IDD_REPLAY_METADATA", hWnd, ReplayMetadataDialogProc);
|
||||
break;
|
||||
|
||||
//Undo Savestate
|
||||
case FCEUX_CONTEXT_UNDOSAVESTATE:
|
||||
SwapSaveState();
|
||||
break;
|
||||
|
||||
//Undo Loadstate
|
||||
case FCEUX_CONTEXT_UNDOLOADSTATE:
|
||||
if (CheckBackupSaveStateExist())
|
||||
|
|
|
@ -1301,10 +1301,10 @@ bool CheckFileExists(const char* filename)
|
|||
{
|
||||
//This function simply checks to see if the given filename exists
|
||||
string checkFilename;
|
||||
|
||||
|
||||
if (filename)
|
||||
checkFilename = filename;
|
||||
|
||||
FCEUI_printf("Checking file %s\n",checkFilename.c_str());
|
||||
//Check if this filename exists
|
||||
fstream test;
|
||||
test.open(checkFilename.c_str(),fstream::in);
|
||||
|
@ -1312,11 +1312,11 @@ bool CheckFileExists(const char* filename)
|
|||
if (test.fail())
|
||||
{
|
||||
test.close();
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
test.close();
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
141
src/state.cpp
141
src/state.cpp
|
@ -59,6 +59,9 @@ static int StateShow;
|
|||
//tells the save system innards that we're loading the old format
|
||||
bool FCEU_state_loading_old_format;
|
||||
|
||||
char lastSavestateMade[2048]; //Stores the last savestate made (needed for UndoSavestate)
|
||||
bool redoSS = false; //This will be true if UndoSaveState is run, will turn false when a new savestate is made
|
||||
|
||||
#define SFMDATA_SIZE (64)
|
||||
static SFORMAT SFMDATA[SFMDATA_SIZE];
|
||||
static int SFEXINDEX;
|
||||
|
@ -425,17 +428,37 @@ void FCEUSS_Save(const char *fname)
|
|||
return;
|
||||
}
|
||||
|
||||
if(fname)
|
||||
if(fname) //If filename is given use it.
|
||||
{
|
||||
//backup existing savestate first
|
||||
if (CheckFileExists(fname))
|
||||
{
|
||||
CreateBackupSaveState(fname); //Make a backup of previous savestate before overwriting it
|
||||
strcpy(lastSavestateMade,fname); //Remember what the last savestate filename was (for undoing later)
|
||||
redoSS = true; //Backup was created so redo is possible
|
||||
}
|
||||
else
|
||||
redoSS = false; //No backup was needed, so lastSavestateMade does not contain a file that has a backup
|
||||
|
||||
st =FCEUD_UTF8_fstream(fname, "wb");
|
||||
else
|
||||
}
|
||||
else //Else, generate one
|
||||
{
|
||||
//FCEU_PrintError("daCurrentState=%d",CurrentState);
|
||||
fn = strdup(FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0).c_str());
|
||||
st = FCEUD_UTF8_fstream(fn,"wb");
|
||||
|
||||
//backup existing savestate first
|
||||
if (CheckFileExists(fn)) CreateBackupSaveState(fn);
|
||||
|
||||
if (CheckFileExists(fn))
|
||||
{
|
||||
CreateBackupSaveState(fn); //Make a backup of previous savestate before overwriting it
|
||||
strcpy(lastSavestateMade,fn); //Remember what the last savestate filename was (for undoing later)
|
||||
FCEUI_printf("Last save made: %s\n",lastSavestateMade);
|
||||
redoSS = true; //Backup was created so redo is possible
|
||||
}
|
||||
else
|
||||
redoSS = false; //No backup was needed, so lastSavestateMade does not contain a file that has a backup
|
||||
|
||||
st = FCEUD_UTF8_fstream(fn,"wb");
|
||||
free(fn);
|
||||
}
|
||||
|
||||
|
@ -848,6 +871,90 @@ void FCEU_DrawSaveStates(uint8 *XBuf)
|
|||
StateShow--;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
//Savestate backup functions
|
||||
//(Used when making savestates)
|
||||
//*************************************************************************
|
||||
|
||||
string GenerateBackupSaveStateFn(const char *fname)
|
||||
{
|
||||
//This backup is for the backup "slot" for any savestate made. Example: smb.fc0 becomes smb-bak.fc0
|
||||
string filename;
|
||||
filename = fname; //Convert fname to a string object
|
||||
int x = filename.find_last_of("."); //Find file extension
|
||||
filename.insert(x,"-bak"); //add "-bak" before the dot.
|
||||
FCEUI_printf("Generating filename of %s\n",filename.c_str());
|
||||
return filename;
|
||||
}
|
||||
|
||||
|
||||
void CreateBackupSaveState(const char *fname)
|
||||
{
|
||||
string filename = GenerateBackupSaveStateFn(fname);
|
||||
std::fstream* st = 0;
|
||||
st = FCEUD_UTF8_fstream(filename.c_str(),"wb");
|
||||
|
||||
if(st == NULL)
|
||||
{
|
||||
FCEU_DispMessage("State %d save error.",filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if(FCEUMOV_Mode(MOVIEMODE_INACTIVE))
|
||||
FCEUSS_SaveMS(st,-1);
|
||||
else
|
||||
FCEUSS_SaveMS(st,0);
|
||||
|
||||
delete st;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//Logic - undo available until a new savestate is made,game is closed, or fcuex is closed
|
||||
|
||||
//What we need is a concept of if you are undoing or redoing as well
|
||||
//Undo should know there is a bak file before making a decision. the main platform code should know this before calling it.
|
||||
//Once it is undone, it should know this and call it a redo if called again on the same file. It should remember as long as it knows about undo.
|
||||
//The undo redo is meaningless information for this function as it simply swaps.
|
||||
//perhaps a combo of flag(s) and a function to handle flag situations is called for?
|
||||
//This function would then simply swap the files, which means it is both undo and redo
|
||||
//And extra function needs to be in charge of flags to keep up with which one is being done, but that is purely cosmetic
|
||||
|
||||
void SwapSaveState()
|
||||
{
|
||||
if (!lastSavestateMade) return; //If there is no last savestate, can't undo
|
||||
string backup = GenerateBackupSaveStateFn(lastSavestateMade); //Get filename of backup state
|
||||
if (!CheckFileExists(backup.c_str()))
|
||||
{
|
||||
FCEUI_printf("%s exists",backup.c_str());
|
||||
return; //If no backup, can't undo
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
//So both exists, now swap the last savestate and its backup
|
||||
//--------------------------------------------------------------------------------------------
|
||||
string temp; //Create a temp string object
|
||||
temp = backup; //Put backup filename in temp
|
||||
temp.append("x"); //Add x
|
||||
|
||||
FILE* backupf = fopen(backup.c_str(),"r"); //Open backup file
|
||||
FILE* currentf = fopen(lastSavestateMade,"w"); //create temp file
|
||||
|
||||
rename(backup.c_str(),temp.c_str()); //rename backup file to temp file
|
||||
rename(lastSavestateMade,backup.c_str()); //rename current as backup
|
||||
rename(temp.c_str(),lastSavestateMade); //rename backup as current
|
||||
|
||||
fclose(backupf); //Cleanup, close backup file
|
||||
fclose(currentf); //Cleanup, close current file
|
||||
FCEUI_DispMessage("%s restored",backup.c_str());
|
||||
FCEUI_printf("%s restored\n",backup.c_str());
|
||||
//TODO: deal with error handling if any of these files does/doesn't exist unexpectedly
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//*************************************************************************
|
||||
//Loadstate backup functions
|
||||
//(Used when Loading savestates)
|
||||
//*************************************************************************
|
||||
|
||||
string GetBackupFileName()
|
||||
{
|
||||
//This backup savestate is a special one specifically made whenever a loadstate occurs so that the user's place in a movie/game is never lost
|
||||
|
@ -863,30 +970,6 @@ string GetBackupFileName()
|
|||
return filename;
|
||||
}
|
||||
|
||||
void CreateBackupSaveState(const char *fname)
|
||||
{
|
||||
string filename;
|
||||
filename = fname; //Convert fname to a string object
|
||||
int x = filename.find_last_of("."); //Find file extension
|
||||
filename.insert(x-1,"-bak"); //add "-bak" before the dot. Ex: smb.fc0 becomes smb-bak.fc0
|
||||
|
||||
std::fstream* st = 0;
|
||||
st = FCEUD_UTF8_fstream(filename.c_str(),"wb");
|
||||
|
||||
if(st == NULL)
|
||||
{
|
||||
FCEU_DispMessage("State %d save error.",CurrentState);
|
||||
return;
|
||||
}
|
||||
|
||||
if(FCEUMOV_Mode(MOVIEMODE_INACTIVE))
|
||||
FCEUSS_SaveMS(st,-1);
|
||||
else
|
||||
FCEUSS_SaveMS(st,0);
|
||||
|
||||
delete st;
|
||||
}
|
||||
|
||||
void BackupLoadState()
|
||||
{
|
||||
string filename = GetBackupFileName();
|
||||
|
|
|
@ -63,4 +63,5 @@ void FCEU_DrawSaveStates(uint8 *XBuf);
|
|||
|
||||
void CreateBackupSaveState(const char *fname); //backsup a savestate before overwriting it with a new one
|
||||
void BackupLoadState(); //Makes a backup savestate before any loadstate
|
||||
void LoadBackup(); //Loads the backupsavestate
|
||||
void LoadBackup(); //Loads the backupsavestate
|
||||
void SwapSaveState(); //Swaps a savestate with its backup state
|
Loading…
Reference in New Issue