mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Reset the game when loading a state fails.
This way it doesn't crash.
This commit is contained in:
parent
16fc684578
commit
418d6c1e83
4 changed files with 72 additions and 25 deletions
|
@ -628,9 +628,15 @@ inline PointerWrapSection::~PointerWrapSection() {
|
|||
class CChunkFileReader
|
||||
{
|
||||
public:
|
||||
enum Error {
|
||||
ERROR_NONE,
|
||||
ERROR_BAD_FILE,
|
||||
ERROR_BROKEN_STATE,
|
||||
};
|
||||
|
||||
// Load file template
|
||||
template<class T>
|
||||
static bool Load(const std::string& _rFilename, int _Revision, const char *_VersionString, T& _class, std::string* _failureReason)
|
||||
static Error Load(const std::string& _rFilename, int _Revision, const char *_VersionString, T& _class, std::string* _failureReason)
|
||||
{
|
||||
INFO_LOG(COMMON, "ChunkReader: Loading %s" , _rFilename.c_str());
|
||||
_failureReason->clear();
|
||||
|
@ -640,7 +646,7 @@ public:
|
|||
_failureReason->clear();
|
||||
_failureReason->append("LoadStateDoesntExist");
|
||||
ERROR_LOG(COMMON, "ChunkReader: File doesn't exist");
|
||||
return false;
|
||||
return ERROR_BAD_FILE;
|
||||
}
|
||||
|
||||
// Check file size
|
||||
|
@ -649,14 +655,14 @@ public:
|
|||
if (fileSize < headerSize)
|
||||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: File too small");
|
||||
return false;
|
||||
return ERROR_BAD_FILE;
|
||||
}
|
||||
|
||||
File::IOFile pFile(_rFilename, "rb");
|
||||
if (!pFile)
|
||||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: Can't open file for reading");
|
||||
return false;
|
||||
return ERROR_BAD_FILE;
|
||||
}
|
||||
|
||||
// read the header
|
||||
|
@ -664,7 +670,7 @@ public:
|
|||
if (!pFile.ReadArray(&header, 1))
|
||||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: Bad header size");
|
||||
return false;
|
||||
return ERROR_BAD_FILE;
|
||||
}
|
||||
|
||||
// Check revision
|
||||
|
@ -672,7 +678,7 @@ public:
|
|||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: Wrong file revision, got %d expected %d",
|
||||
header.Revision, _Revision);
|
||||
return false;
|
||||
return ERROR_BAD_FILE;
|
||||
}
|
||||
|
||||
if (strcmp(header.GitVersion, _VersionString) != 0)
|
||||
|
@ -687,7 +693,7 @@ public:
|
|||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: Bad file size, got %d expected %d",
|
||||
sz, header.ExpectedSize);
|
||||
return false;
|
||||
return ERROR_BAD_FILE;
|
||||
}
|
||||
|
||||
// read the state
|
||||
|
@ -695,7 +701,7 @@ public:
|
|||
if (!pFile.ReadBytes(buffer, sz))
|
||||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: Error reading file");
|
||||
return false;
|
||||
return ERROR_BAD_FILE;
|
||||
}
|
||||
|
||||
u8 *ptr = buffer;
|
||||
|
@ -717,12 +723,16 @@ public:
|
|||
delete[] buf;
|
||||
|
||||
INFO_LOG(COMMON, "ChunkReader: Done loading %s" , _rFilename.c_str());
|
||||
return p.error != p.ERROR_FAILURE;
|
||||
if (p.error != p.ERROR_FAILURE) {
|
||||
return ERROR_NONE;
|
||||
} else {
|
||||
return ERROR_BROKEN_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
// Save file template
|
||||
template<class T>
|
||||
static bool Save(const std::string& _rFilename, int _Revision, const char *_VersionString, T& _class)
|
||||
static Error Save(const std::string& _rFilename, int _Revision, const char *_VersionString, T& _class)
|
||||
{
|
||||
INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str());
|
||||
|
||||
|
@ -730,7 +740,7 @@ public:
|
|||
if (!pFile)
|
||||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: Error opening file for write");
|
||||
return false;
|
||||
return ERROR_BAD_FILE;
|
||||
}
|
||||
|
||||
bool compress = true;
|
||||
|
@ -765,11 +775,11 @@ public:
|
|||
if (!pFile.WriteArray(&header, 1))
|
||||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: Failed writing header");
|
||||
return false;
|
||||
return ERROR_BAD_FILE;
|
||||
}
|
||||
if (!pFile.WriteBytes(&compressed_buffer[0], comp_len)) {
|
||||
ERROR_LOG(COMMON,"ChunkReader: Failed writing compressed data");
|
||||
return false;
|
||||
return ERROR_BAD_FILE;
|
||||
} else {
|
||||
INFO_LOG(COMMON, "Savestate: Compressed %i bytes into %i", (int)sz, (int)comp_len);
|
||||
}
|
||||
|
@ -778,23 +788,27 @@ public:
|
|||
if (!pFile.WriteArray(&header, 1))
|
||||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: Failed writing header");
|
||||
return false;
|
||||
return ERROR_BAD_FILE;
|
||||
}
|
||||
if (!pFile.WriteBytes(&buffer[0], sz))
|
||||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: Failed writing data");
|
||||
return false;
|
||||
return ERROR_BAD_FILE;
|
||||
}
|
||||
delete [] buffer;
|
||||
}
|
||||
|
||||
INFO_LOG(COMMON,"ChunkReader: Done writing %s",
|
||||
_rFilename.c_str());
|
||||
return p.error != p.ERROR_FAILURE;
|
||||
if (p.error != p.ERROR_FAILURE) {
|
||||
return ERROR_NONE;
|
||||
} else {
|
||||
return ERROR_BROKEN_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static bool Verify(T& _class)
|
||||
static Error Verify(T& _class)
|
||||
{
|
||||
u8 *ptr = 0;
|
||||
|
||||
|
@ -814,7 +828,7 @@ public:
|
|||
p.SetMode(PointerWrap::MODE_VERIFY);
|
||||
_class.DoState(p);
|
||||
|
||||
return true;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -197,6 +197,9 @@ reswitch:
|
|||
|
||||
// Check if there's any pending savestate actions.
|
||||
SaveState::Process();
|
||||
if (coreState == CORE_POWERDOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
// wait for step command..
|
||||
#if defined(USING_QT_UI) || defined(_DEBUG)
|
||||
|
|
|
@ -24,13 +24,14 @@
|
|||
#include "Core/Config.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HLE/sceKernel.h"
|
||||
#include "HW/MemoryStick.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/MIPS/JitCommon/JitCommon.h"
|
||||
#include "Core/System.h"
|
||||
#include "UI/OnScreenDisplay.h"
|
||||
#include "i18n/i18n.h"
|
||||
|
||||
|
@ -202,6 +203,21 @@ namespace SaveState
|
|||
return copy;
|
||||
}
|
||||
|
||||
void HandleFailure()
|
||||
{
|
||||
PSP_Shutdown();
|
||||
std::string resetError;
|
||||
if (!PSP_Init(PSP_CoreParameter(), &resetError))
|
||||
{
|
||||
ERROR_LOG(BOOT, "Error resetting: %s", resetError.c_str());
|
||||
// TODO: This probably doesn't clean up well enough.
|
||||
Core_Stop();
|
||||
return;
|
||||
}
|
||||
host->BootDone();
|
||||
host->UpdateDisassembly();
|
||||
}
|
||||
|
||||
void Process()
|
||||
{
|
||||
if (!needsProcess)
|
||||
|
@ -220,7 +236,8 @@ namespace SaveState
|
|||
for (size_t i = 0, n = operations.size(); i < n; ++i)
|
||||
{
|
||||
Operation &op = operations[i];
|
||||
bool result;
|
||||
CChunkFileReader::Error result;
|
||||
bool callbackResult;
|
||||
std::string reason;
|
||||
|
||||
I18NCategory *s = GetI18NCategory("Screen");
|
||||
|
@ -232,10 +249,15 @@ namespace SaveState
|
|||
MIPSComp::jit->ClearCache();
|
||||
INFO_LOG(COMMON, "Loading state from %s", op.filename.c_str());
|
||||
result = CChunkFileReader::Load(op.filename, REVISION, PPSSPP_GIT_VERSION, state, &reason);
|
||||
if (result) {
|
||||
if (result == CChunkFileReader::ERROR_NONE) {
|
||||
osm.Show(s->T("Loaded State"), 2.0);
|
||||
callbackResult = true;
|
||||
} else if (result == CChunkFileReader::ERROR_BROKEN_STATE) {
|
||||
HandleFailure();
|
||||
callbackResult = false;
|
||||
} else {
|
||||
osm.Show(s->T(reason.c_str(), "Load savestate failed"), 2.0);
|
||||
callbackResult = false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -244,26 +266,31 @@ namespace SaveState
|
|||
MIPSComp::jit->ClearCache();
|
||||
INFO_LOG(COMMON, "Saving state to %s", op.filename.c_str());
|
||||
result = CChunkFileReader::Save(op.filename, REVISION, PPSSPP_GIT_VERSION, state);
|
||||
if (result) {
|
||||
if (result == CChunkFileReader::ERROR_NONE) {
|
||||
osm.Show(s->T("Saved State"), 2.0);
|
||||
callbackResult = true;
|
||||
} else if (result == CChunkFileReader::ERROR_BROKEN_STATE) {
|
||||
HandleFailure();
|
||||
callbackResult = false;
|
||||
} else {
|
||||
osm.Show(s->T("Save State Failed"), 2.0);
|
||||
callbackResult = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case SAVESTATE_VERIFY:
|
||||
INFO_LOG(COMMON, "Verifying save state system");
|
||||
result = CChunkFileReader::Verify(state);
|
||||
callbackResult = CChunkFileReader::Verify(state) == CChunkFileReader::ERROR_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(COMMON, "Savestate failure: unknown operation type %d", op.type);
|
||||
result = false;
|
||||
callbackResult = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (op.callback)
|
||||
op.callback(result, op.cbUserData);
|
||||
op.callback(callbackResult, op.cbUserData);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -302,6 +302,9 @@ void PSP_Shutdown() {
|
|||
|
||||
void PSP_RunLoopUntil(u64 globalticks) {
|
||||
SaveState::Process();
|
||||
if (coreState == CORE_POWERDOWN || coreState == CORE_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cpuThread != NULL) {
|
||||
cpuThreadUntil = globalticks;
|
||||
|
|
Loading…
Add table
Reference in a new issue