summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorXTra.KrazzY <XTra.KrazzY@gmail.com>2009-06-28 01:11:35 +0000
committerXTra.KrazzY <XTra.KrazzY@gmail.com>2009-06-28 01:11:35 +0000
commit7ea2bc5da9681bca748f783f433ccaf689f7b604 (patch)
treea7d079da83407e9fe64fb58d10d836416b431c31 /Source
parent2ea850f5a0ab6b6bf39bde5d17d8c12f58e2afc5 (diff)
Save States:
1. Added a header, including the Game ID (old states are obsolete unless the gameid is appended to the beginning) so states from different games can't be cross-loaded 2. Added loading/saving from/to file 3. Added loading of last saved state (F11) 4. Added "Undo State": Load the backed up last overwritten state (if you press save instead of load) (F12) 5. State code cleanup git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3560 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/Src/Core.cpp8
-rw-r--r--Source/Core/Core/Src/State.cpp90
-rw-r--r--Source/Core/Core/Src/State.h12
-rw-r--r--Source/Core/DolphinWX/Src/Frame.cpp5
-rw-r--r--Source/Core/DolphinWX/Src/Frame.h4
-rw-r--r--Source/Core/DolphinWX/Src/FrameTools.cpp76
-rw-r--r--Source/Core/DolphinWX/Src/Globals.h4
7 files changed, 169 insertions, 30 deletions
diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp
index 71e071667b..d82d190209 100644
--- a/Source/Core/Core/Src/Core.cpp
+++ b/Source/Core/Core/Src/Core.cpp
@@ -863,6 +863,14 @@ void Callback_KeyPress(int key, bool shift, bool control)
State_Load(slot_number);
}
}
+
+ // 0x7a == VK_F11
+ if (key == 0x7a)
+ State_LoadLastSaved();
+
+ // 0x7a == VK_F12
+ if (key == 0x7b)
+ State_LoadAs(FULL_STATESAVES_DIR "lastState.sav");
}
// Callback_WiimoteLog
diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp
index 5bac051599..2c8f635b8c 100644
--- a/Source/Core/Core/Src/State.cpp
+++ b/Source/Core/Core/Src/State.cpp
@@ -52,12 +52,13 @@ static HEAP_ALLOC(wrkmem,LZO1X_1_MEM_COMPRESS);
static int ev_Save;
static int ev_Load;
-static std::string cur_filename;
+static std::string cur_filename, lastFilename;
static bool const bCompressed = true;
-enum {
- version = 1
+enum
+{
+ version = 1,
};
void DoState(PointerWrap &p)
@@ -84,22 +85,31 @@ THREAD_RETURN CompressAndDumpState(void *pArgs)
u8 *buffer = saveArg->buffer;
size_t sz = saveArg->size;
lzo_uint out_len = 0;
+ state_header header;
+ std::string filename = cur_filename;
delete saveArg;
- FILE *f = fopen(cur_filename.c_str(), "wb");
+ // Moving to last overwritten save-state
+ if(File::Exists(cur_filename.c_str())) {
+ if(File::Exists(FULL_STATESAVES_DIR "lastState.sav"))
+ File::Delete(FULL_STATESAVES_DIR "lastState.sav");
+
+ if(!File::Rename(cur_filename.c_str(), FULL_STATESAVES_DIR "lastState.sav"))
+ Core::DisplayMessage("Failed to move previous state to state undo backup", 1000);
+ }
+
+ FILE *f = fopen(filename.c_str(), "wb");
if(f == NULL) {
Core::DisplayMessage("Could not save state", 2000);
return 0;
}
- if (bCompressed) {
- fwrite(&sz, sizeof(int), 1, f);
- } else {
- int zero = 0;
- fwrite(&zero, sizeof(int), 1, f);
- }
+ // Setting up the header
+ memcpy(header.gameID, Core::GetStartupParameter().GetUniqueID().c_str(), 6);
+ header.sz = bCompressed ? sz : 0;
+ fwrite(&header, sizeof(state_header), 1, f);
if (bCompressed) {
if (lzo_init() != LZO_E_OK)
@@ -134,7 +144,7 @@ THREAD_RETURN CompressAndDumpState(void *pArgs)
delete [] buffer;
Core::DisplayMessage(StringFromFormat("Saved State to %s",
- cur_filename.c_str()).c_str(), 2000);
+ filename.c_str()).c_str(), 2000);
return 0;
}
@@ -176,22 +186,43 @@ void LoadStateCallback(u64 userdata, int cyclesLate)
bool bCompressedState;
+ // If saving state, wait for it to finish
+ if(saveThread)
+ {
+ delete saveThread;
+ saveThread = NULL;
+ }
+
FILE *f = fopen(cur_filename.c_str(), "rb");
if (!f) {
Core::DisplayMessage("State not found", 2000);
return;
}
- jit.ClearCache();
-
u8 *buffer = NULL;
+ state_header header;
+ size_t sz;
+
+ fread(&header, sizeof(state_header), 1, f);
+
+ if(memcmp(Core::GetStartupParameter().GetUniqueID().c_str(), header.gameID, 6))
+ {
+ char gameID[7] = {0};
+ memcpy(gameID, header.gameID, 6);
+ Core::DisplayMessage(StringFromFormat("State belongs to a different game (ID %s)",
+ gameID), 2000);
+
+ fclose(f);
- int sz;
- fread(&sz, sizeof(int), 1, f);
+ return;
+ }
+ sz = header.sz;
bCompressedState = (sz != 0);
if (bCompressedState) {
+ Core::DisplayMessage("Decompressing State...", 500);
+
if (lzo_init() != LZO_E_OK)
PanicAlert("Internal LZO Error - lzo_init() failed");
else {
@@ -225,6 +256,8 @@ void LoadStateCallback(u64 userdata, int cyclesLate)
fclose(f);
+ jit.ClearCache();
+
u8 *ptr = buffer;
PointerWrap p(&ptr, PointerWrap::MODE_READ);
DoState(p);
@@ -253,14 +286,33 @@ std::string MakeStateFilename(int state_number)
return StringFromFormat(FULL_STATESAVES_DIR "%s.s%02i", Core::GetStartupParameter().GetUniqueID().c_str(), state_number);
}
-void State_Save(int slot)
+void State_SaveAs(const std::string &filename)
{
- cur_filename = MakeStateFilename(slot);
+ cur_filename = filename;
+ lastFilename = filename;
CoreTiming::ScheduleEvent_Threadsafe(0, ev_Save);
}
-void State_Load(int slot)
+void State_Save(int slot)
+{
+ State_SaveAs(MakeStateFilename(slot));
+}
+
+void State_LoadAs(const std::string &filename)
{
- cur_filename = MakeStateFilename(slot);
+ cur_filename = filename;
CoreTiming::ScheduleEvent_Threadsafe(0, ev_Load);
}
+
+void State_Load(int slot)
+{
+ State_LoadAs(MakeStateFilename(slot));
+}
+
+void State_LoadLastSaved()
+{
+ if(lastFilename.empty())
+ Core::DisplayMessage("There is no last saved state", 2000);
+ else
+ State_LoadAs(lastFilename);
+}
diff --git a/Source/Core/Core/Src/State.h b/Source/Core/Core/Src/State.h
index 19313b2c85..b22df727d8 100644
--- a/Source/Core/Core/Src/State.h
+++ b/Source/Core/Core/Src/State.h
@@ -28,10 +28,22 @@ void State_Shutdown();
void State_Save(int slot);
void State_Load(int slot);
+void State_SaveAs(const std::string &filename);
+void State_LoadAs(const std::string &filename);
+
+void State_LoadLastSaved();
+
typedef struct
{
u8 *buffer;
size_t size;
} saveStruct;
+
+typedef struct
+{
+ u8 gameID[6];
+ size_t sz;
+} state_header;
+
#endif
diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp
index 050d98c50f..438622b4d8 100644
--- a/Source/Core/DolphinWX/Src/Frame.cpp
+++ b/Source/Core/DolphinWX/Src/Frame.cpp
@@ -285,6 +285,11 @@ EVT_MENU(IDM_LISTPAL, CFrame::GameListChanged)
EVT_MENU(IDM_LISTUSA, CFrame::GameListChanged)
EVT_MENU(IDM_PURGECACHE, CFrame::GameListChanged)
+EVT_MENU(IDM_LOADLASTSTATE, CFrame::OnLoadLastState)
+EVT_MENU(IDM_UNDOSTATE, CFrame::OnUndoState)
+EVT_MENU(IDM_LOADSTATEFILE, CFrame::OnLoadStateFromFile)
+EVT_MENU(IDM_SAVESTATEFILE, CFrame::OnSaveStateToFile)
+
EVT_MENU_RANGE(IDM_LOADSLOT1, IDM_LOADSLOT10, CFrame::OnLoadState)
EVT_MENU_RANGE(IDM_SAVESLOT1, IDM_SAVESLOT10, CFrame::OnSaveState)
EVT_MENU_RANGE(IDM_DRIVE1, IDM_DRIVE24, CFrame::OnBootDrive)
diff --git a/Source/Core/DolphinWX/Src/Frame.h b/Source/Core/DolphinWX/Src/Frame.h
index 1bacd0b7c4..08d0c96198 100644
--- a/Source/Core/DolphinWX/Src/Frame.h
+++ b/Source/Core/DolphinWX/Src/Frame.h
@@ -185,6 +185,10 @@ class CFrame : public wxFrame
void OnClose(wxCloseEvent &event);
void OnLoadState(wxCommandEvent& event);
void OnSaveState(wxCommandEvent& event);
+ void OnLoadStateFromFile(wxCommandEvent& event);
+ void OnSaveStateToFile(wxCommandEvent& event);
+ void OnLoadLastState(wxCommandEvent& event);
+ void OnUndoState(wxCommandEvent& event);
void OnConfigMain(wxCommandEvent& event); // Options
void OnPluginGFX(wxCommandEvent& event);
diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp
index d7cda0e5dd..da76aed608 100644
--- a/Source/Core/DolphinWX/Src/FrameTools.cpp
+++ b/Source/Core/DolphinWX/Src/FrameTools.cpp
@@ -139,11 +139,20 @@ void CFrame::CreateMenu()
emulationMenu->AppendSeparator();
wxMenu *saveMenu = new wxMenu;
wxMenu *loadMenu = new wxMenu;
- m_pSubMenuLoad = emulationMenu->AppendSubMenu(saveMenu, _T("&Load State"));
- m_pSubMenuSave = emulationMenu->AppendSubMenu(loadMenu, _T("Sa&ve State"));
+ m_pSubMenuLoad = emulationMenu->AppendSubMenu(loadMenu, _T("&Load State"));
+ m_pSubMenuSave = emulationMenu->AppendSubMenu(saveMenu, _T("Sa&ve State"));
+
+ saveMenu->Append(IDM_SAVESTATEFILE, _T("Save State..."));
+ saveMenu->AppendSeparator();
+
+ loadMenu->Append(IDM_LOADSTATEFILE, _T("Load State..."));
+ loadMenu->Append(IDM_LOADLASTSTATE, _T("Last Saved State\tF11"));
+ loadMenu->Append(IDM_UNDOSTATE, _T("Last Overwritten State\tF12"));
+ loadMenu->AppendSeparator();
+
for (int i = 1; i < 10; i++) {
- saveMenu->Append(IDM_LOADSLOT1 + i - 1, wxString::Format(_T("Slot %i\tF%i"), i, i));
- loadMenu->Append(IDM_SAVESLOT1 + i - 1, wxString::Format(_T("Slot %i\tShift+F%i"), i, i));
+ loadMenu->Append(IDM_LOADSLOT1 + i - 1, wxString::Format(_T("Slot %i\tF%i"), i, i));
+ saveMenu->Append(IDM_SAVESLOT1 + i - 1, wxString::Format(_T("Slot %i\tShift+F%i"), i, i));
}
menuBar->Append(emulationMenu, _T("&Emulation"));
@@ -717,6 +726,52 @@ void CFrame::OnToggleSkipIdle(wxCommandEvent& WXUNUSED (event))
SConfig::GetInstance().SaveSettings();
}
+void CFrame::OnLoadStateFromFile(wxCommandEvent& WXUNUSED (event))
+{
+ wxString path = wxFileSelector(
+ _T("Select the state to load"),
+ wxEmptyString, wxEmptyString, wxEmptyString,
+ wxString::Format
+ (
+ _T("All Save States (sav, s##)|*.sav;*.s??|All files (%s)|%s"),
+ wxFileSelectorDefaultWildcardStr,
+ wxFileSelectorDefaultWildcardStr
+ ),
+ wxFD_OPEN | wxFD_PREVIEW | wxFD_FILE_MUST_EXIST,
+ this);
+
+ if(path)
+ State_LoadAs(path.ToAscii());
+}
+
+void CFrame::OnSaveStateToFile(wxCommandEvent& WXUNUSED (event))
+{
+ wxString path = wxFileSelector(
+ _T("Select the state to save"),
+ wxEmptyString, wxEmptyString, wxEmptyString,
+ wxString::Format
+ (
+ _T("All Save States (sav, s##)|*.sav;*.s??|All files (%s)|%s"),
+ wxFileSelectorDefaultWildcardStr,
+ wxFileSelectorDefaultWildcardStr
+ ),
+ wxFD_SAVE,
+ this);
+
+ if(path)
+ State_SaveAs(path.ToAscii());
+}
+
+void CFrame::OnLoadLastState(wxCommandEvent& WXUNUSED (event))
+{
+ State_LoadLastSaved();
+}
+
+void CFrame::OnUndoState(wxCommandEvent& WXUNUSED (event))
+{
+ State_LoadAs(FULL_STATESAVES_DIR "lastState.sav");
+}
+
void CFrame::OnLoadState(wxCommandEvent& event)
{
int id = event.GetId();
@@ -724,13 +779,6 @@ void CFrame::OnLoadState(wxCommandEvent& event)
State_Load(slot);
}
-void CFrame::OnResize(wxSizeEvent& event)
-{
- FitInside();
- DoMoveIcons(); // In FrameWiimote.cpp
- event.Skip();
-}
-
void CFrame::OnSaveState(wxCommandEvent& event)
{
int id = event.GetId();
@@ -738,6 +786,12 @@ void CFrame::OnSaveState(wxCommandEvent& event)
State_Save(slot);
}
+void CFrame::OnResize(wxSizeEvent& event)
+{
+ FitInside();
+ DoMoveIcons(); // In FrameWiimote.cpp
+ event.Skip();
+}
// Enable and disable the toolbar
void CFrame::OnToggleToolbar(wxCommandEvent& event)
diff --git a/Source/Core/DolphinWX/Src/Globals.h b/Source/Core/DolphinWX/Src/Globals.h
index ab84a08bef..7dae1f508d 100644
--- a/Source/Core/DolphinWX/Src/Globals.h
+++ b/Source/Core/DolphinWX/Src/Globals.h
@@ -31,6 +31,10 @@ enum
{
IDM_LOADSTATE = 200, // File menu
IDM_SAVESTATE,
+ IDM_LOADLASTSTATE,
+ IDM_UNDOSTATE,
+ IDM_LOADSTATEFILE,
+ IDM_SAVESTATEFILE,
IDM_SAVESLOT1,
IDM_SAVESLOT2,
IDM_SAVESLOT3,