Reset the game when loading a state fails.

This way it doesn't crash.
This commit is contained in:
Unknown W. Brackets 2013-09-14 21:19:10 -07:00
parent 16fc684578
commit 418d6c1e83
4 changed files with 72 additions and 25 deletions

View file

@ -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:

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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;