summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJohn Peterson <john.s.peterson@live.com>2012-11-08 08:40:49 +0100
committerJohn Peterson <john.s.peterson@live.com>2013-04-30 04:13:55 +0200
commitef2e0a87d06eb498f0e2eaebe6be2785740e54dd (patch)
tree1306a47d1d8602e019d84725c04c05bb09cac863 /Source/Core
parent4f5832827e8bf52077f74d01403f96b29d06b5e3 (diff)
Adding option to save and load state by timestamp
Load by timestamp: load last state is expanded from 1 to 8 actions, for newest to oldest state Save by timestamp: overwrite the oldest state (or use an empty slot if available) Adding remaining hardcoded state keys to hotkey dialog Adding a program exit hotkey
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/ConfigManager.cpp15
-rw-r--r--Source/Core/Core/Src/CoreParameter.h14
-rw-r--r--Source/Core/Core/Src/State.cpp108
-rw-r--r--Source/Core/Core/Src/State.h21
-rw-r--r--Source/Core/DolphinWX/Src/Frame.cpp175
-rw-r--r--Source/Core/DolphinWX/Src/Frame.h1
-rw-r--r--Source/Core/DolphinWX/Src/FrameTools.cpp50
-rw-r--r--Source/Core/DolphinWX/Src/Globals.h10
-rw-r--r--Source/Core/DolphinWX/Src/HotkeyDlg.cpp16
9 files changed, 258 insertions, 152 deletions
diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp
index 485c1ab259..1eec9fd7b7 100644
--- a/Source/Core/Core/Src/ConfigManager.cpp
+++ b/Source/Core/Core/Src/ConfigManager.cpp
@@ -35,6 +35,7 @@ static const struct {
{ "ToggleFullscreen", 70 /* 'F' */, 2 /* wxMOD_CMD */ },
{ "Screenshot", 83 /* 'S' */, 2 /* wxMOD_CMD */ },
+ { "Exit", 0, 0 /* wxMOD_NONE */ },
{ "Wiimote1Connect", 49 /* '1' */, 2 /* wxMOD_CMD */ },
{ "Wiimote2Connect", 50 /* '2' */, 2 /* wxMOD_CMD */ },
@@ -57,6 +58,7 @@ static const struct {
{ "ToggleFullscreen", 13 /* WXK_RETURN */, 1 /* wxMOD_ALT */ },
{ "Screenshot", 348 /* WXK_F9 */, 0 /* wxMOD_NONE */ },
+ { "Exit", 0, 0 /* wxMOD_NONE */ },
{ "Wiimote1Connect", 344 /* WXK_F5 */, 1 /* wxMOD_ALT */ },
{ "Wiimote2Connect", 345 /* WXK_F6 */, 1 /* wxMOD_ALT */ },
@@ -81,6 +83,19 @@ static const struct {
{ "SaveStateSlot6", 345 /* WXK_F6 */, 4 /* wxMOD_SHIFT */ },
{ "SaveStateSlot7", 346 /* WXK_F7 */, 4 /* wxMOD_SHIFT */ },
{ "SaveStateSlot8", 347 /* WXK_F8 */, 4 /* wxMOD_SHIFT */ },
+
+ { "LoadLastState1", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState2", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState3", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState4", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState5", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState6", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState7", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState8", 0, 0 /* wxMOD_NONE */ },
+
+ { "SaveFirstState", 0, 0 /* wxMOD_NONE */ },
+ { "UndoLoadState", 351 /* WXK_F12 */, 0 /* wxMOD_NONE */ },
+ { "UndoSaveState", 351 /* WXK_F12 */, 4 /* wxMOD_SHIFT */ },
};
SConfig::SConfig()
diff --git a/Source/Core/Core/Src/CoreParameter.h b/Source/Core/Core/Src/CoreParameter.h
index 9652b84618..6f2219e9f8 100644
--- a/Source/Core/Core/Src/CoreParameter.h
+++ b/Source/Core/Core/Src/CoreParameter.h
@@ -26,6 +26,7 @@ enum Hotkey
HK_FULLSCREEN,
HK_SCREENSHOT,
+ HK_EXIT,
HK_WIIMOTE1_CONNECT,
HK_WIIMOTE2_CONNECT,
@@ -50,6 +51,19 @@ enum Hotkey
HK_SAVE_STATE_SLOT_7,
HK_SAVE_STATE_SLOT_8,
+ HK_LOAD_LAST_STATE_1,
+ HK_LOAD_LAST_STATE_2,
+ HK_LOAD_LAST_STATE_3,
+ HK_LOAD_LAST_STATE_4,
+ HK_LOAD_LAST_STATE_5,
+ HK_LOAD_LAST_STATE_6,
+ HK_LOAD_LAST_STATE_7,
+ HK_LOAD_LAST_STATE_8,
+
+ HK_SAVE_FIRST_STATE,
+ HK_UNDO_LOAD_STATE,
+ HK_UNDO_SAVE_STATE,
+
NUM_HOTKEYS,
};
diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp
index 3be8470d14..09653ac9ad 100644
--- a/Source/Core/Core/Src/State.cpp
+++ b/Source/Core/Core/Src/State.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "Common.h"
+#include "Timer.h"
#include "State.h"
#include "Core.h"
#include "ConfigManager.h"
@@ -58,13 +59,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system
-static const u32 STATE_VERSION = 16;
-
-struct StateHeader
-{
- u8 gameID[6];
- size_t size;
-};
+static const u32 STATE_VERSION = 17;
enum
{
@@ -159,17 +154,59 @@ void VerifyBuffer(std::vector<u8>& buffer)
Core::PauseAndLock(false, wasUnpaused);
}
+// return state number not in map
+int GetEmptySlot(std::map<double, int> m)
+{
+ for (int i = 1; i <= NUM_STATES; i++)
+ {
+ bool found = false;
+ for (std::map<double, int>::iterator it = m.begin(); it != m.end(); it++)
+ {
+ if (it->second == i)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found) return i;
+ }
+ return -1;
+}
+
+// read state timestamps
+std::map<double, int> GetSavedStates()
+{
+ StateHeader header;
+ std::map<double, int> m;
+ for (int i = 1; i <= NUM_STATES; i++)
+ {
+ if (File::Exists(MakeStateFilename(i)))
+ {
+ if (ReadHeader(MakeStateFilename(i), header))
+ {
+ double d = Common::Timer::GetDoubleTime() - header.time;
+ // increase time until unique value is obtained
+ while (m.find(d) != m.end()) d += .001;
+ m.insert(std::pair<double,int>(d, i));
+ }
+ }
+ }
+ return m;
+}
+
struct CompressAndDumpState_args
{
std::vector<u8>* buffer_vector;
std::mutex* buffer_mutex;
std::string filename;
+ bool wait;
};
void CompressAndDumpState(CompressAndDumpState_args save_args)
{
std::lock_guard<std::mutex> lk(*save_args.buffer_mutex);
- g_compressAndDumpStateSyncEvent.Set();
+ if (!save_args.wait)
+ g_compressAndDumpStateSyncEvent.Set();
const u8* const buffer_data = &(*(save_args.buffer_vector))[0];
const size_t buffer_size = (save_args.buffer_vector)->size();
@@ -201,6 +238,7 @@ void CompressAndDumpState(CompressAndDumpState_args save_args)
if (!f)
{
Core::DisplayMessage("Could not save state", 2000);
+ g_compressAndDumpStateSyncEvent.Set();
return;
}
@@ -208,6 +246,7 @@ void CompressAndDumpState(CompressAndDumpState_args save_args)
StateHeader header;
memcpy(header.gameID, SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), 6);
header.size = g_use_compression ? buffer_size : 0;
+ header.time = Common::Timer::GetDoubleTime();
f.WriteArray(&header, 1);
@@ -244,9 +283,10 @@ void CompressAndDumpState(CompressAndDumpState_args save_args)
Core::DisplayMessage(StringFromFormat("Saved State to %s",
filename.c_str()).c_str(), 2000);
+ g_compressAndDumpStateSyncEvent.Set();
}
-void SaveAs(const std::string& filename)
+void SaveAs(const std::string& filename, bool wait)
{
// Pause the core while we save the state
bool wasUnpaused = Core::PauseAndLock(true);
@@ -274,6 +314,7 @@ void SaveAs(const std::string& filename)
save_args.buffer_vector = &g_current_buffer;
save_args.buffer_mutex = &g_cs_current_buffer;
save_args.filename = filename;
+ save_args.wait = wait;
Flush();
g_save_thread = std::thread(CompressAndDumpState, save_args);
@@ -291,6 +332,20 @@ void SaveAs(const std::string& filename)
Core::PauseAndLock(false, wasUnpaused);
}
+bool ReadHeader(const std::string filename, StateHeader& header)
+{
+ Flush();
+ File::IOFile f(filename, "rb");
+ if (!f)
+ {
+ Core::DisplayMessage("State not found", 2000);
+ return false;
+ }
+
+ f.ReadArray(&header, 1);
+ return true;
+}
+
void LoadFileStateData(const std::string& filename, std::vector<u8>& ret_data)
{
Flush();
@@ -496,9 +551,9 @@ static std::string MakeStateFilename(int number)
SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), number);
}
-void Save(int slot)
+void Save(int slot, bool wait)
{
- SaveAs(MakeStateFilename(slot));
+ SaveAs(MakeStateFilename(slot), wait);
}
void Load(int slot)
@@ -511,12 +566,35 @@ void Verify(int slot)
VerifyAt(MakeStateFilename(slot));
}
-void LoadLastSaved()
+void LoadLastSaved(int i)
{
- if (g_last_filename.empty())
- Core::DisplayMessage("There is no last saved state", 2000);
+ std::map<double, int> savedStates = GetSavedStates();
+
+ if (i > savedStates.size())
+ Core::DisplayMessage("State doesn't exist", 2000);
else
- LoadAs(g_last_filename);
+ {
+ std::map<double, int>::iterator it = savedStates.begin();
+ std::advance(it, i-1);
+ Load(it->second);
+ }
+}
+
+// must wait for state to be written because it must know if all slots are taken
+void SaveFirstSaved()
+{
+ std::map<double, int> savedStates = GetSavedStates();
+
+ // save to an empty slot
+ if (savedStates.size() < NUM_STATES)
+ Save(GetEmptySlot(savedStates), true);
+ // overwrite the oldest state
+ else
+ {
+ std::map<double, int>::iterator it = savedStates.begin();
+ std::advance(it, savedStates.size()-1);
+ Save(it->second, true);
+ }
}
void Flush()
diff --git a/Source/Core/Core/Src/State.h b/Source/Core/Core/Src/State.h
index db88cef766..14e77bae5c 100644
--- a/Source/Core/Core/Src/State.h
+++ b/Source/Core/Core/Src/State.h
@@ -14,22 +14,34 @@
namespace State
{
+// number of states
+static const u32 NUM_STATES = 8;
+
+struct StateHeader
+{
+ u8 gameID[6];
+ u32 size;
+ double time;
+};
+
void Init();
void Shutdown();
void EnableCompression(bool compression);
+bool ReadHeader(const std::string filename, StateHeader& header);
+
// These don't happen instantly - they get scheduled as events.
// ...But only if we're not in the main cpu thread.
// If we're in the main cpu thread then they run immediately instead
// because some things (like Lua) need them to run immediately.
// Slots from 0-99.
-void Save(int slot);
+void Save(int slot, bool wait = false);
void Load(int slot);
void Verify(int slot);
-void SaveAs(const std::string &filename);
+void SaveAs(const std::string &filename, bool wait = false);
void LoadAs(const std::string &filename);
void VerifyAt(const std::string &filename);
@@ -37,7 +49,10 @@ void SaveToBuffer(std::vector<u8>& buffer);
void LoadFromBuffer(std::vector<u8>& buffer);
void VerifyBuffer(std::vector<u8>& buffer);
-void LoadLastSaved();
+static std::string MakeStateFilename(int number);
+
+void LoadLastSaved(int i = 1);
+void SaveFirstSaved();
void UndoSaveState();
void UndoLoadState();
diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp
index 2ed76f6214..1e0e0c756c 100644
--- a/Source/Core/DolphinWX/Src/Frame.cpp
+++ b/Source/Core/DolphinWX/Src/Frame.cpp
@@ -204,13 +204,14 @@ EVT_MENU_RANGE(IDM_LOGWINDOW, IDM_VIDEOWINDOW, CFrame::OnToggleWindow)
EVT_MENU(IDM_PURGECACHE, CFrame::GameListChanged)
-EVT_MENU(IDM_LOADLASTSTATE, CFrame::OnLoadLastState)
+EVT_MENU(IDM_SAVEFIRSTSTATE, CFrame::OnSaveFirstState)
EVT_MENU(IDM_UNDOLOADSTATE, CFrame::OnUndoLoadState)
EVT_MENU(IDM_UNDOSAVESTATE, CFrame::OnUndoSaveState)
EVT_MENU(IDM_LOADSTATEFILE, CFrame::OnLoadStateFromFile)
EVT_MENU(IDM_SAVESTATEFILE, CFrame::OnSaveStateToFile)
EVT_MENU_RANGE(IDM_LOADSLOT1, IDM_LOADSLOT8, CFrame::OnLoadState)
+EVT_MENU_RANGE(IDM_LOADLAST1, IDM_LOADLAST8, CFrame::OnLoadLastState)
EVT_MENU_RANGE(IDM_SAVESLOT1, IDM_SAVESLOT8, CFrame::OnSaveState)
EVT_MENU_RANGE(IDM_FRAMESKIP0, IDM_FRAMESKIP9, CFrame::OnFrameSkip)
EVT_MENU_RANGE(IDM_DRIVE1, IDM_DRIVE24, CFrame::OnBootDrive)
@@ -719,104 +720,56 @@ int GetCmdForHotkey(unsigned int key)
{
switch (key)
{
- case HK_OPEN:
- return wxID_OPEN;
-
- case HK_CHANGE_DISC:
- return IDM_CHANGEDISC;
-
- case HK_REFRESH_LIST:
- return wxID_REFRESH;
-
- case HK_PLAY_PAUSE:
- return IDM_PLAY;
-
- case HK_STOP:
- return IDM_STOP;
-
- case HK_RESET:
- return IDM_RESET;
-
- case HK_FRAME_ADVANCE:
- return IDM_FRAMESTEP;
-
- case HK_START_RECORDING:
- return IDM_RECORD;
-
- case HK_PLAY_RECORDING:
- return IDM_PLAYRECORD;
-
- case HK_EXPORT_RECORDING:
- return IDM_RECORDEXPORT;
-
- case HK_READ_ONLY_MODE:
- return IDM_RECORDREADONLY;
-
- case HK_FULLSCREEN:
- return IDM_TOGGLE_FULLSCREEN;
-
- case HK_SCREENSHOT:
- return IDM_SCREENSHOT;
-
- case HK_WIIMOTE1_CONNECT:
- return IDM_CONNECT_WIIMOTE1;
-
- case HK_WIIMOTE2_CONNECT:
- return IDM_CONNECT_WIIMOTE2;
-
- case HK_WIIMOTE3_CONNECT:
- return IDM_CONNECT_WIIMOTE3;
-
- case HK_WIIMOTE4_CONNECT:
- return IDM_CONNECT_WIIMOTE4;
-
- case HK_LOAD_STATE_SLOT_1:
- return IDM_LOADSLOT1;
-
- case HK_LOAD_STATE_SLOT_2:
- return IDM_LOADSLOT2;
-
- case HK_LOAD_STATE_SLOT_3:
- return IDM_LOADSLOT3;
-
- case HK_LOAD_STATE_SLOT_4:
- return IDM_LOADSLOT4;
-
- case HK_LOAD_STATE_SLOT_5:
- return IDM_LOADSLOT5;
-
- case HK_LOAD_STATE_SLOT_6:
- return IDM_LOADSLOT6;
-
- case HK_LOAD_STATE_SLOT_7:
- return IDM_LOADSLOT7;
-
- case HK_LOAD_STATE_SLOT_8:
- return IDM_LOADSLOT8;
-
- case HK_SAVE_STATE_SLOT_1:
- return IDM_SAVESLOT1;
-
- case HK_SAVE_STATE_SLOT_2:
- return IDM_SAVESLOT2;
-
- case HK_SAVE_STATE_SLOT_3:
- return IDM_SAVESLOT3;
-
- case HK_SAVE_STATE_SLOT_4:
- return IDM_SAVESLOT4;
-
- case HK_SAVE_STATE_SLOT_5:
- return IDM_SAVESLOT5;
-
- case HK_SAVE_STATE_SLOT_6:
- return IDM_SAVESLOT6;
-
- case HK_SAVE_STATE_SLOT_7:
- return IDM_SAVESLOT7;
-
- case HK_SAVE_STATE_SLOT_8:
- return IDM_SAVESLOT8;
+ case HK_OPEN: return wxID_OPEN;
+ case HK_CHANGE_DISC: return IDM_CHANGEDISC;
+ case HK_REFRESH_LIST: return wxID_REFRESH;
+ case HK_PLAY_PAUSE: return IDM_PLAY;
+ case HK_STOP: return IDM_STOP;
+ case HK_RESET: return IDM_RESET;
+ case HK_FRAME_ADVANCE: return IDM_FRAMESTEP;
+ case HK_START_RECORDING: return IDM_RECORD;
+ case HK_PLAY_RECORDING: return IDM_PLAYRECORD;
+ case HK_EXPORT_RECORDING: return IDM_RECORDEXPORT;
+ case HK_READ_ONLY_MODE: return IDM_RECORDREADONLY;
+ case HK_FULLSCREEN: return IDM_TOGGLE_FULLSCREEN;
+ case HK_SCREENSHOT: return IDM_SCREENSHOT;
+ case HK_EXIT: return wxID_EXIT;
+
+ case HK_WIIMOTE1_CONNECT: return IDM_CONNECT_WIIMOTE1;
+ case HK_WIIMOTE2_CONNECT: return IDM_CONNECT_WIIMOTE2;
+ case HK_WIIMOTE3_CONNECT: return IDM_CONNECT_WIIMOTE3;
+ case HK_WIIMOTE4_CONNECT: return IDM_CONNECT_WIIMOTE4;
+
+ case HK_LOAD_STATE_SLOT_1: return IDM_LOADSLOT1;
+ case HK_LOAD_STATE_SLOT_2: return IDM_LOADSLOT2;
+ case HK_LOAD_STATE_SLOT_3: return IDM_LOADSLOT3;
+ case HK_LOAD_STATE_SLOT_4: return IDM_LOADSLOT4;
+ case HK_LOAD_STATE_SLOT_5: return IDM_LOADSLOT5;
+ case HK_LOAD_STATE_SLOT_6: return IDM_LOADSLOT6;
+ case HK_LOAD_STATE_SLOT_7: return IDM_LOADSLOT7;
+ case HK_LOAD_STATE_SLOT_8: return IDM_LOADSLOT8;
+
+ case HK_SAVE_STATE_SLOT_1: return IDM_SAVESLOT1;
+ case HK_SAVE_STATE_SLOT_2: return IDM_SAVESLOT2;
+ case HK_SAVE_STATE_SLOT_3: return IDM_SAVESLOT3;
+ case HK_SAVE_STATE_SLOT_4: return IDM_SAVESLOT4;
+ case HK_SAVE_STATE_SLOT_5: return IDM_SAVESLOT5;
+ case HK_SAVE_STATE_SLOT_6: return IDM_SAVESLOT6;
+ case HK_SAVE_STATE_SLOT_7: return IDM_SAVESLOT7;
+ case HK_SAVE_STATE_SLOT_8: return IDM_SAVESLOT8;
+
+ case HK_LOAD_LAST_STATE_1: return IDM_LOADLAST1;
+ case HK_LOAD_LAST_STATE_2: return IDM_LOADLAST2;
+ case HK_LOAD_LAST_STATE_3: return IDM_LOADLAST3;
+ case HK_LOAD_LAST_STATE_4: return IDM_LOADLAST4;
+ case HK_LOAD_LAST_STATE_5: return IDM_LOADLAST5;
+ case HK_LOAD_LAST_STATE_6: return IDM_LOADLAST6;
+ case HK_LOAD_LAST_STATE_7: return IDM_LOADLAST7;
+ case HK_LOAD_LAST_STATE_8: return IDM_LOADLAST8;
+
+ case HK_SAVE_FIRST_STATE: return IDM_SAVEFIRSTSTATE;
+ case HK_UNDO_LOAD_STATE: return IDM_UNDOLOADSTATE;
+ case HK_UNDO_SAVE_STATE: return IDM_UNDOSAVESTATE;
}
return -1;
@@ -859,6 +812,8 @@ void CFrame::OnKeyDown(wxKeyEvent& event)
// Screenshot hotkey
else if (IsHotkey(event, HK_SCREENSHOT))
Core::SaveScreenShot();
+ else if (IsHotkey(event, HK_EXIT))
+ wxPostEvent(this, wxCommandEvent(wxID_EXIT));
// Wiimote connect and disconnect hotkeys
else if (IsHotkey(event, HK_WIIMOTE1_CONNECT))
WiimoteId = 0;
@@ -868,28 +823,6 @@ void CFrame::OnKeyDown(wxKeyEvent& event)
WiimoteId = 2;
else if (IsHotkey(event, HK_WIIMOTE4_CONNECT))
WiimoteId = 3;
- // State save and state load hotkeys
- /*else if (event.GetKeyCode() >= WXK_F1 && event.GetKeyCode() <= WXK_F8)
- {
- int slot_number = event.GetKeyCode() - WXK_F1 + 1;
- if (event.GetModifiers() == wxMOD_NONE)
- State::Load(slot_number);
- else if (event.GetModifiers() == wxMOD_SHIFT)
- State::Save(slot_number);
- else
- event.Skip();
- }*/
- else if (event.GetKeyCode() == WXK_F11 && event.GetModifiers() == wxMOD_NONE)
- State::LoadLastSaved();
- else if (event.GetKeyCode() == WXK_F12)
- {
- if (event.GetModifiers() == wxMOD_NONE)
- State::UndoSaveState();
- else if (event.GetModifiers() == wxMOD_SHIFT)
- State::UndoLoadState();
- else
- event.Skip();
- }
else
{
unsigned int i = NUM_HOTKEYS;
diff --git a/Source/Core/DolphinWX/Src/Frame.h b/Source/Core/DolphinWX/Src/Frame.h
index 6657c62013..0a29fffd37 100644
--- a/Source/Core/DolphinWX/Src/Frame.h
+++ b/Source/Core/DolphinWX/Src/Frame.h
@@ -289,6 +289,7 @@ private:
void OnLoadStateFromFile(wxCommandEvent& event);
void OnSaveStateToFile(wxCommandEvent& event);
void OnLoadLastState(wxCommandEvent& event);
+ void OnSaveFirstState(wxCommandEvent& event);
void OnUndoLoadState(wxCommandEvent& event);
void OnUndoSaveState(wxCommandEvent& event);
diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp
index ef0aa81e9d..57c465abfa 100644
--- a/Source/Core/DolphinWX/Src/FrameTools.cpp
+++ b/Source/Core/DolphinWX/Src/FrameTools.cpp
@@ -150,26 +150,25 @@ void CFrame::CreateMenu()
emulationMenu->Append(IDM_SAVESTATE, _("Sa&ve State"), saveMenu);
saveMenu->Append(IDM_SAVESTATEFILE, _("Save State..."));
- loadMenu->Append(IDM_UNDOSAVESTATE, _("Last Overwritten State") + wxString(wxT("\tF12")));
+ saveMenu->Append(IDM_SAVEFIRSTSTATE, GetMenuLabel(HK_SAVE_FIRST_STATE));
+ loadMenu->Append(IDM_UNDOSAVESTATE, GetMenuLabel(HK_UNDO_SAVE_STATE));
saveMenu->AppendSeparator();
loadMenu->Append(IDM_LOADSTATEFILE, _("Load State..."));
-
- // Reserve F11 for the "step into" function in the debugger
- if (g_pCodeWindow)
- loadMenu->Append(IDM_LOADLASTSTATE, _("Last Saved State"));
- else
- loadMenu->Append(IDM_LOADLASTSTATE, _("Last Saved State") + wxString(wxT("\tF11")));
- loadMenu->Append(IDM_UNDOLOADSTATE, _("Undo Load State") + wxString(wxT("\tShift+F12")));
+ loadMenu->Append(IDM_UNDOLOADSTATE, GetMenuLabel(HK_UNDO_LOAD_STATE));
loadMenu->AppendSeparator();
- for (int i = 1; i <= 8; i++)
+ for (int i = 1; i <= State::NUM_STATES; i++)
{
loadMenu->Append(IDM_LOADSLOT1 + i - 1, GetMenuLabel(HK_LOAD_STATE_SLOT_1 + i - 1));
saveMenu->Append(IDM_SAVESLOT1 + i - 1, GetMenuLabel(HK_SAVE_STATE_SLOT_1 + i - 1));
}
+ loadMenu->AppendSeparator();
+ for (int i = 1; i <= State::NUM_STATES; i++)
+ loadMenu->Append(IDM_LOADLAST1 + i - 1, GetMenuLabel(HK_LOAD_LAST_STATE_1 + i - 1));
+
m_MenuBar->Append(emulationMenu, _("&Emulation"));
// Options menu
@@ -360,6 +359,9 @@ wxString CFrame::GetMenuLabel(int Id)
case HK_SCREENSHOT:
Label = _("Take Screenshot");
break;
+ case HK_EXIT:
+ Label = _("Exit");
+ break;
case HK_WIIMOTE1_CONNECT:
case HK_WIIMOTE2_CONNECT:
@@ -393,6 +395,22 @@ wxString CFrame::GetMenuLabel(int Id)
Id - HK_SAVE_STATE_SLOT_1 + 1);
break;
+ case HK_LOAD_LAST_STATE_1:
+ case HK_LOAD_LAST_STATE_2:
+ case HK_LOAD_LAST_STATE_3:
+ case HK_LOAD_LAST_STATE_4:
+ case HK_LOAD_LAST_STATE_5:
+ case HK_LOAD_LAST_STATE_6:
+ case HK_LOAD_LAST_STATE_7:
+ case HK_LOAD_LAST_STATE_8:
+ Label = wxString::Format(_("Last %i"),
+ Id - HK_LOAD_LAST_STATE_1 + 1);
+ break;
+
+ case HK_SAVE_FIRST_STATE: Label = wxString("Save Oldest State"); break;
+ case HK_UNDO_LOAD_STATE: Label = wxString("Undo Load State"); break;
+ case HK_UNDO_SAVE_STATE: Label = wxString("Undo Save State"); break;
+
default:
Label = wxString::Format(_("Undefined %i"), Id);
}
@@ -1437,10 +1455,20 @@ void CFrame::OnSaveStateToFile(wxCommandEvent& WXUNUSED (event))
State::SaveAs(WxStrToStr(path));
}
-void CFrame::OnLoadLastState(wxCommandEvent& WXUNUSED (event))
+void CFrame::OnLoadLastState(wxCommandEvent& event)
{
if (Core::IsRunningAndStarted())
- State::LoadLastSaved();
+ {
+ int id = event.GetId();
+ int slot = id - IDM_LOADLAST1 + 1;
+ State::LoadLastSaved(slot);
+ }
+}
+
+void CFrame::OnSaveFirstState(wxCommandEvent& WXUNUSED(event))
+{
+ if (Core::GetState() != Core::CORE_UNINITIALIZED)
+ State::SaveFirstSaved();
}
void CFrame::OnUndoLoadState(wxCommandEvent& WXUNUSED (event))
diff --git a/Source/Core/DolphinWX/Src/Globals.h b/Source/Core/DolphinWX/Src/Globals.h
index 8229af059a..144eafe40f 100644
--- a/Source/Core/DolphinWX/Src/Globals.h
+++ b/Source/Core/DolphinWX/Src/Globals.h
@@ -25,7 +25,7 @@ enum
{
IDM_LOADSTATE = 200, // File menu
IDM_SAVESTATE,
- IDM_LOADLASTSTATE,
+ IDM_SAVEFIRSTSTATE,
IDM_UNDOLOADSTATE,
IDM_UNDOSAVESTATE,
IDM_LOADSTATEFILE,
@@ -46,6 +46,14 @@ enum
IDM_LOADSLOT6,
IDM_LOADSLOT7,
IDM_LOADSLOT8,
+ IDM_LOADLAST1,
+ IDM_LOADLAST2,
+ IDM_LOADLAST3,
+ IDM_LOADLAST4,
+ IDM_LOADLAST5,
+ IDM_LOADLAST6,
+ IDM_LOADLAST7,
+ IDM_LOADLAST8,
IDM_FRAMESKIP0,
IDM_FRAMESKIP1,
IDM_FRAMESKIP2,
diff --git a/Source/Core/DolphinWX/Src/HotkeyDlg.cpp b/Source/Core/DolphinWX/Src/HotkeyDlg.cpp
index f841b412c6..5ee94deb59 100644
--- a/Source/Core/DolphinWX/Src/HotkeyDlg.cpp
+++ b/Source/Core/DolphinWX/Src/HotkeyDlg.cpp
@@ -179,6 +179,7 @@ void HotkeyConfigDialog::CreateHotkeyGUIControls(void)
_("Toggle Fullscreen"),
_("Take Screenshot"),
+ _("Exit"),
_("Connect Wiimote 1"),
_("Connect Wiimote 2"),
@@ -201,7 +202,20 @@ void HotkeyConfigDialog::CreateHotkeyGUIControls(void)
_("Save State Slot 5"),
_("Save State Slot 6"),
_("Save State Slot 7"),
- _("Save State Slot 8")
+ _("Save State Slot 8"),
+
+ _("Load State Last 1"),
+ _("Load State Last 2"),
+ _("Load State Last 3"),
+ _("Load State Last 4"),
+ _("Load State Last 5"),
+ _("Load State Last 6"),
+ _("Load State Last 7"),
+ _("Load State Last 8"),
+
+ _("Save Oldest State"),
+ _("Undo Load State"),
+ _("Undo Save State")
};
const int page_breaks[3] = {HK_OPEN, HK_LOAD_STATE_SLOT_1, NUM_HOTKEYS};