diff --git a/Common/ChunkFile.h b/Common/ChunkFile.h index 36df8a3a97..78a468f68d 100644 --- a/Common/ChunkFile.h +++ b/Common/ChunkFile.h @@ -42,6 +42,7 @@ #endif #include "Common.h" +#include "Core/Config.h" #include "FileUtil.h" #include "../ext/snappy/snappy-c.h" @@ -627,6 +628,12 @@ public: return false; } + if (strcmp(header.GitVersion, PPSSPP_GIT_VERSION) != 0) + { + WARN_LOG(COMMON, "This savestate was generated by a different version of PPSSPP, %s. It may not load properly.", + header.GitVersion); + } + // get size const int sz = (int)(fileSize - headerSize); if (header.ExpectedSize != sz) @@ -698,7 +705,8 @@ public: header.Revision = _Revision; header.ExpectedSize = (int)sz; header.UncompressedSize = (int)sz; - + strncpy(header.GitVersion, PPSSPP_GIT_VERSION, 32); + // Write to file if (compress) { size_t comp_len = snappy_max_compressed_length(sz); @@ -768,6 +776,7 @@ private: int Compress; int ExpectedSize; int UncompressedSize; + char GitVersion[32]; }; }; diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 58b23fb367..acf287cdab 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -175,14 +175,6 @@ void __KernelShutdown() void __KernelDoState(PointerWrap &p) { - std::string git_version = PPSSPP_GIT_VERSION; - p.Do(git_version); - if (git_version != PPSSPP_GIT_VERSION) - { - p.SetError(p.ERROR_WARNING); - WARN_LOG(HLE, "Warning: this savestate was generated by a different version of PPSSPP. It may not load properly."); - } - p.Do(kernelRunning); kernelObjects.DoState(p); p.DoMarker("KernelObjects"); diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 83885d3fc0..28a5aea7f7 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -141,19 +141,25 @@ namespace SaveState void LoadSlot(int slot, Callback callback, void *cbUserData) { std::string fn = GenerateSaveSlotFilename(slot); - if (!fn.empty()) + if (!fn.empty()) { Load(fn, callback, cbUserData); - else + } else { + I18NCategory *s = GetI18NCategory("Screen"); + osm.Show("Failed to load state. Error in the file system.", 2.0); (*callback)(false, cbUserData); + } } void SaveSlot(int slot, Callback callback, void *cbUserData) { std::string fn = GenerateSaveSlotFilename(slot); - if (!fn.empty()) + if (!fn.empty()) { Save(fn, callback, cbUserData); - else + } else { + I18NCategory *s = GetI18NCategory("Screen"); + osm.Show("Failed to save state. Error in the file system.", 2.0); (*callback)(false, cbUserData); + } } bool HasSaveInSlot(int slot) diff --git a/Core/SaveState.h b/Core/SaveState.h index 8023756ecc..eb3e075a11 100644 --- a/Core/SaveState.h +++ b/Core/SaveState.h @@ -24,8 +24,8 @@ namespace SaveState typedef void (*Callback)(bool status, void *cbUserData); // TODO: Better place for this? - const int REVISION = 2; - const int SAVESTATESLOTS = 4; + const int REVISION = 3; + const int SAVESTATESLOTS = 5; void Init(); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 60266feef1..42c1712969 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -52,7 +52,12 @@ #include "UI/GameInfoCache.h" #include "UI/MiscScreens.h" + EmuScreen::EmuScreen(const std::string &filename) : invalid_(true) { + bootGame(filename); +} + +void EmuScreen::bootGame(const std::string &filename) { CheckGLExtensions(); std::string fileToStart = filename; // This is probably where we should start up the emulated PSP. @@ -120,12 +125,24 @@ EmuScreen::~EmuScreen() { } void EmuScreen::dialogFinished(const Screen *dialog, DialogResult result) { + + // TODO: improve the way with which we got commands from PauseMenu. + // DR_CANCEL means clicked on "continue", DR_OK means clicked on "back to menu", + // DR_YES means a message sent to PauseMenu by NativeMessageReceived. if (result == DR_OK) { if (g_Config.bNewUI) screenManager()->switchScreen(new MainScreen()); else screenManager()->switchScreen(new MenuScreen()); } + else if (result == DR_YES) { + PauseScreen::Message* msg = (PauseScreen::Message*)((Screen*)dialog)->dialogData(); + if (msg != NULL) + { + NativeMessageReceived(msg->msg, msg->value); + delete msg; + } + } } void EmuScreen::sendMessage(const char *message, const char *value) { @@ -158,6 +175,10 @@ void EmuScreen::sendMessage(const char *message, const char *value) { } #endif } + else if (!strcmp(message, "boot")) { + PSP_Shutdown(); + bootGame(value); + } } inline float curve1(float x) { diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 422468d05a..8da8bde7ec 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -40,6 +40,8 @@ public: virtual void axis(const AxisInput &axis); private: + void bootGame(const std::string &filename); + void pspKey(int pspKeyCode, int flags); void onVKeyDown(int virtualKeyCode); void onVKeyUp(int virtualKeyCode); diff --git a/UI/MenuScreens.cpp b/UI/MenuScreens.cpp index cb3366d27f..439af5d5f6 100644 --- a/UI/MenuScreens.cpp +++ b/UI/MenuScreens.cpp @@ -396,8 +396,10 @@ void PauseScreen::update(InputState &input) { void PauseScreen::sendMessage(const char *msg, const char *value) { if (!strcmp(msg, "run")) { screenManager()->finishDialog(this, DR_CANCEL); - } else if (!strcmp(msg, "stop")) { - screenManager()->finishDialog(this, DR_OK); + } else if (!strcmp(msg, "stop") || !strcmp(msg, "reset") || !strcmp(msg, "boot")) { + // Close the menu and send the events to EmuScreen + m_data = new PauseScreen::Message(msg, value); + screenManager()->finishDialog(this, DR_YES); } } diff --git a/UI/MenuScreens.h b/UI/MenuScreens.h index c4af912ac4..3f9c000983 100644 --- a/UI/MenuScreens.h +++ b/UI/MenuScreens.h @@ -62,6 +62,25 @@ public: void update(InputState &input); void render(); virtual void sendMessage(const char *msg, const char *value); + + struct Message + { + Message(const char *m, const char *v) + : msg(m), value(v) {} + + const char *msg; + const char *value; + }; + + virtual void *dialogData() + { + return m_data; + } + + PauseScreen() : m_data(NULL) {} + +private: + Message* m_data; }; diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 9e52cce8a6..2f84448a49 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -307,8 +307,22 @@ namespace MainWindow filter[i] = '\0'; } + // pause if a game is being played + bool isPaused = false; + if (globalUIState == UISTATE_INGAME) + { + isPaused = Core_IsStepping(); + if (!isPaused) + Core_EnableStepping(true); + } + if (W32Util::BrowseForFileName(true, GetHWND(), "Load File", defaultPath.size() ? defaultPath.c_str() : 0, filter.c_str(),"*.pbp;*.elf;*.iso;*.cso;",fn)) { + if (globalUIState == UISTATE_INGAME || globalUIState == UISTATE_PAUSEMENU) + { + Core_EnableStepping(false); + } + // decode the filename with fullpath std::string fullpath = fn; char drive[MAX_PATH]; @@ -320,6 +334,11 @@ namespace MainWindow std::string executable = std::string(drive) + std::string(dir) + std::string(fname) + std::string(ext); NativeMessageReceived("boot", executable.c_str()); } + else + { + if (!isPaused) + Core_EnableStepping(false); + } } LRESULT CALLBACK DisplayProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) @@ -603,8 +622,6 @@ namespace MainWindow break; case ID_EMULATION_RESET: - if (globalUIState == UISTATE_PAUSEMENU) - NativeMessageReceived("run", ""); NativeMessageReceived("reset", ""); break; @@ -631,7 +648,7 @@ namespace MainWindow // TODO: Improve UI for multiple slots case ID_FILE_SAVESTATE_NEXT_SLOT: { - currentSavestateSlot = (currentSavestateSlot + 1)%5; + currentSavestateSlot = (currentSavestateSlot + 1)%SaveState::SAVESTATESLOTS; char msg[30]; sprintf(msg, "Using save state slot %d.", currentSavestateSlot + 1); osm.Show(msg); @@ -1102,8 +1119,6 @@ namespace MainWindow EnableMenuItem(menu,ID_EMULATION_RESET, ingameEnable); UINT menuEnable = globalUIState == UISTATE_MENU ? MF_ENABLED : MF_GRAYED; - EnableMenuItem(menu,ID_FILE_LOAD, menuEnable); - EnableMenuItem(menu,ID_FILE_LOAD_MEMSTICK, menuEnable); EnableMenuItem(menu,ID_FILE_SAVESTATEFILE, !menuEnable); EnableMenuItem(menu,ID_FILE_LOADSTATEFILE, !menuEnable); EnableMenuItem(menu,ID_FILE_QUICKSAVESTATE, !menuEnable); @@ -1219,8 +1234,6 @@ namespace MainWindow void SaveStateActionFinished(bool result, void *userdata) { - if (!result) - MessageBox(0, "Savestate failure. Using savestates between different PPSSPP versions is not supported.", "Sorry", MB_OK); SetCursor(LoadCursor(0, IDC_ARROW)); }