mirror of https://github.com/stella-emu/stella.git
Fixed state loading and saving. When a load failed on a previous attempt,
the next load would cause the program to abort. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@106 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
a6d330fa2c
commit
d34f42c679
|
@ -13,7 +13,7 @@
|
||||||
// See the file "license" for information on usage and redistribution of
|
// See the file "license" for information on usage and redistribution of
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//
|
//
|
||||||
// $Id: Deserializer.cxx,v 1.1 2002-05-13 19:14:17 stephena Exp $
|
// $Id: Deserializer.cxx,v 1.2 2002-08-11 17:48:13 stephena Exp $
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -27,41 +27,47 @@ Deserializer::Deserializer(void)
|
||||||
{
|
{
|
||||||
TruePattern = 0xfab1fab2;
|
TruePattern = 0xfab1fab2;
|
||||||
FalsePattern = 0xbad1bad2;
|
FalsePattern = 0xbad1bad2;
|
||||||
|
|
||||||
|
myStream = (ifstream*) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Deserializer::~Deserializer(void)
|
Deserializer::~Deserializer(void)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
if(myStream.is_open())
|
|
||||||
myStream.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool Deserializer::open(string& fileName)
|
bool Deserializer::open(string& fileName)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
myStream.open(fileName.c_str(), ios::in | ios::binary);
|
myStream = new ifstream(fileName.c_str(), ios::in | ios::binary);
|
||||||
|
|
||||||
return myStream.is_open();
|
return (myStream && myStream->is_open());
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Deserializer::close(void)
|
void Deserializer::close(void)
|
||||||
{
|
{
|
||||||
if(myStream.is_open())
|
if(myStream)
|
||||||
myStream.close();
|
{
|
||||||
|
if(myStream->is_open())
|
||||||
|
myStream->close();
|
||||||
|
|
||||||
|
delete myStream;
|
||||||
|
myStream = (ifstream*) 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
long Deserializer::getLong(void)
|
long Deserializer::getLong(void)
|
||||||
{
|
{
|
||||||
if(myStream.eof())
|
if(myStream->eof())
|
||||||
throw "Deserializer: end of file";
|
throw "Deserializer: end of file";
|
||||||
|
|
||||||
long l;
|
long l;
|
||||||
myStream.read(reinterpret_cast<char *> (&l), sizeof (long));
|
myStream->read(reinterpret_cast<char *> (&l), sizeof (long));
|
||||||
if(myStream.bad())
|
if(myStream->bad())
|
||||||
throw "Deserializer: file read failed";
|
throw "Deserializer: file read failed";
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
|
@ -73,9 +79,9 @@ string Deserializer::getString(void)
|
||||||
long len = getLong();
|
long len = getLong();
|
||||||
string str;
|
string str;
|
||||||
str.resize(len);
|
str.resize(len);
|
||||||
myStream.read(&str[0], len);
|
myStream->read(&str[0], len);
|
||||||
|
|
||||||
if(myStream.bad())
|
if(myStream->bad())
|
||||||
throw "Deserializer: file read failed";
|
throw "Deserializer: file read failed";
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
|
@ -87,7 +93,7 @@ bool Deserializer::getBool(void)
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
long b = getLong();
|
long b = getLong();
|
||||||
if(myStream.bad())
|
if(myStream->bad())
|
||||||
throw "Deserializer: file read failed";
|
throw "Deserializer: file read failed";
|
||||||
|
|
||||||
if(b == TruePattern)
|
if(b == TruePattern)
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the file "license" for information on usage and redistribution of
|
// See the file "license" for information on usage and redistribution of
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//
|
//
|
||||||
// $Id: Deserializer.hxx,v 1.3 2002-05-14 15:22:28 stephena Exp $
|
// $Id: Deserializer.hxx,v 1.4 2002-08-11 17:48:13 stephena Exp $
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#ifndef DESERIALIZER_HXX
|
#ifndef DESERIALIZER_HXX
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
return.
|
return.
|
||||||
|
|
||||||
@author Stephen Anthony
|
@author Stephen Anthony
|
||||||
@version $Id: Deserializer.hxx,v 1.3 2002-05-14 15:22:28 stephena Exp $
|
@version $Id: Deserializer.hxx,v 1.4 2002-08-11 17:48:13 stephena Exp $
|
||||||
*/
|
*/
|
||||||
class Deserializer
|
class Deserializer
|
||||||
{
|
{
|
||||||
|
@ -88,7 +88,7 @@ class Deserializer
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The stream to get the deserialized data from.
|
// The stream to get the deserialized data from.
|
||||||
ifstream myStream;
|
ifstream* myStream;
|
||||||
|
|
||||||
// A long pattern that represents a boolean value of true.
|
// A long pattern that represents a boolean value of true.
|
||||||
long TruePattern;
|
long TruePattern;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the file "license" for information on usage and redistribution of
|
// See the file "license" for information on usage and redistribution of
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//
|
//
|
||||||
// $Id: Serializer.cxx,v 1.1 2002-05-13 19:14:17 stephena Exp $
|
// $Id: Serializer.cxx,v 1.2 2002-08-11 17:48:13 stephena Exp $
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -27,6 +27,8 @@ Serializer::Serializer(void)
|
||||||
{
|
{
|
||||||
TruePattern = 0xfab1fab2;
|
TruePattern = 0xfab1fab2;
|
||||||
FalsePattern = 0xbad1bad2;
|
FalsePattern = 0xbad1bad2;
|
||||||
|
|
||||||
|
myStream = (ofstream*) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -39,23 +41,29 @@ Serializer::~Serializer(void)
|
||||||
bool Serializer::open(string& fileName)
|
bool Serializer::open(string& fileName)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
myStream.open(fileName.c_str(), ios::out | ios::binary);
|
myStream = new ofstream(fileName.c_str(), ios::out | ios::binary);
|
||||||
|
|
||||||
return myStream.is_open();
|
return (myStream && myStream->is_open());
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Serializer::close(void)
|
void Serializer::close(void)
|
||||||
{
|
{
|
||||||
if(myStream.is_open())
|
if(myStream)
|
||||||
myStream.close();
|
{
|
||||||
|
if(myStream->is_open())
|
||||||
|
myStream->close();
|
||||||
|
|
||||||
|
delete myStream;
|
||||||
|
myStream = (ofstream*) 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Serializer::putLong(long value)
|
void Serializer::putLong(long value)
|
||||||
{
|
{
|
||||||
myStream.write(reinterpret_cast<char *> (&value), sizeof (long));
|
myStream->write(reinterpret_cast<char *> (&value), sizeof (long));
|
||||||
if(myStream.bad())
|
if(myStream->bad())
|
||||||
throw "Serializer: file write failed";
|
throw "Serializer: file write failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,9 +72,9 @@ void Serializer::putString(string& str)
|
||||||
{
|
{
|
||||||
int len = str.length();
|
int len = str.length();
|
||||||
putLong(len);
|
putLong(len);
|
||||||
myStream.write(str.data(), len);
|
myStream->write(str.data(), len);
|
||||||
|
|
||||||
if(myStream.bad())
|
if(myStream->bad())
|
||||||
throw "Serializer: file write failed";
|
throw "Serializer: file write failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +84,6 @@ void Serializer::putBool(bool b)
|
||||||
long l = b ? TruePattern: FalsePattern;
|
long l = b ? TruePattern: FalsePattern;
|
||||||
putLong(l);
|
putLong(l);
|
||||||
|
|
||||||
if(myStream.bad ())
|
if(myStream->bad ())
|
||||||
throw "Serializer: file write failed";
|
throw "Serializer: file write failed";
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the file "license" for information on usage and redistribution of
|
// See the file "license" for information on usage and redistribution of
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//
|
//
|
||||||
// $Id: Serializer.hxx,v 1.3 2002-05-14 15:22:28 stephena Exp $
|
// $Id: Serializer.hxx,v 1.4 2002-08-11 17:48:13 stephena Exp $
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#ifndef SERIALIZER_HXX
|
#ifndef SERIALIZER_HXX
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
Boolean values are written using a special pattern.
|
Boolean values are written using a special pattern.
|
||||||
|
|
||||||
@author Stephen Anthony
|
@author Stephen Anthony
|
||||||
@version $Id: Serializer.hxx,v 1.3 2002-05-14 15:22:28 stephena Exp $
|
@version $Id: Serializer.hxx,v 1.4 2002-08-11 17:48:13 stephena Exp $
|
||||||
*/
|
*/
|
||||||
class Serializer
|
class Serializer
|
||||||
{
|
{
|
||||||
|
@ -89,7 +89,7 @@ class Serializer
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The stream to send the serialized data to.
|
// The stream to send the serialized data to.
|
||||||
ofstream myStream;
|
ofstream* myStream;
|
||||||
|
|
||||||
// A long pattern that represents a boolean value of true.
|
// A long pattern that represents a boolean value of true.
|
||||||
long TruePattern;
|
long TruePattern;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the file "license" for information on usage and redistribution of
|
// See the file "license" for information on usage and redistribution of
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//
|
//
|
||||||
// $Id: System.cxx,v 1.3 2002-05-13 19:10:25 stephena Exp $
|
// $Id: System.cxx,v 1.4 2002-08-11 17:48:13 stephena Exp $
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -209,7 +209,10 @@ int System::saveState(string &fileName, string& md5sum)
|
||||||
{
|
{
|
||||||
// Open the file as a new Serializer
|
// Open the file as a new Serializer
|
||||||
if(!serializer->open(fileName))
|
if(!serializer->open(fileName))
|
||||||
|
{
|
||||||
|
serializer->close();
|
||||||
return 2;
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
// Prepend the state file with the md5sum of this cartridge
|
// Prepend the state file with the md5sum of this cartridge
|
||||||
// This is the first defensive check for an invalid state file
|
// This is the first defensive check for an invalid state file
|
||||||
|
@ -217,18 +220,27 @@ int System::saveState(string &fileName, string& md5sum)
|
||||||
|
|
||||||
// First save state for this system
|
// First save state for this system
|
||||||
if(!save(*serializer))
|
if(!save(*serializer))
|
||||||
|
{
|
||||||
|
serializer->close();
|
||||||
return 3;
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
// Next, save state for the CPU
|
// Next, save state for the CPU
|
||||||
if(!myM6502->save(*serializer))
|
if(!myM6502->save(*serializer))
|
||||||
|
{
|
||||||
|
serializer->close();
|
||||||
return 3;
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
// Now save the state of each device
|
// Now save the state of each device
|
||||||
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
|
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
|
||||||
{
|
{
|
||||||
if(!myDevices[i]->save(*serializer))
|
if(!myDevices[i]->save(*serializer))
|
||||||
|
{
|
||||||
|
serializer->close();
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
serializer->close();
|
serializer->close();
|
||||||
return 1; // success
|
return 1; // success
|
||||||
|
@ -239,27 +251,42 @@ int System::loadState(string &fileName, string& md5sum)
|
||||||
{
|
{
|
||||||
// Open the file as a new Deserializer
|
// Open the file as a new Deserializer
|
||||||
if(!deserializer->open(fileName))
|
if(!deserializer->open(fileName))
|
||||||
|
{
|
||||||
|
deserializer->close();
|
||||||
return 2;
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
// Look at the beginning of the state file. It should contain the md5sum
|
// Look at the beginning of the state file. It should contain the md5sum
|
||||||
// of the current cartridge. If it doesn't, this state file is invalid.
|
// of the current cartridge. If it doesn't, this state file is invalid.
|
||||||
if(deserializer->getString() != md5sum)
|
if(deserializer->getString() != md5sum)
|
||||||
|
{
|
||||||
|
deserializer->close();
|
||||||
return 3;
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
// First load state for this system
|
// First load state for this system
|
||||||
if(!load(*deserializer))
|
if(!load(*deserializer))
|
||||||
|
{
|
||||||
|
deserializer->close();
|
||||||
return 3;
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
// Next, load state for the CPU
|
// Next, load state for the CPU
|
||||||
if(!myM6502->load(*deserializer))
|
if(!myM6502->load(*deserializer))
|
||||||
|
{
|
||||||
|
deserializer->close();
|
||||||
return 3;
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
// Now load the state of each device
|
// Now load the state of each device
|
||||||
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
|
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
|
||||||
{
|
{
|
||||||
if(!myDevices[i]->load(*deserializer))
|
if(!myDevices[i]->load(*deserializer))
|
||||||
|
{
|
||||||
|
deserializer->close();
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
deserializer->close();
|
deserializer->close();
|
||||||
return 1; // success
|
return 1; // success
|
||||||
|
|
Loading…
Reference in New Issue