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:
stephena 2002-08-11 17:48:13 +00:00
parent a6d330fa2c
commit d34f42c679
5 changed files with 71 additions and 30 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// 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>
@ -27,41 +27,47 @@ Deserializer::Deserializer(void)
{
TruePattern = 0xfab1fab2;
FalsePattern = 0xbad1bad2;
myStream = (ifstream*) 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Deserializer::~Deserializer(void)
{
close();
if(myStream.is_open())
myStream.close();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Deserializer::open(string& fileName)
{
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)
{
if(myStream.is_open())
myStream.close();
if(myStream)
{
if(myStream->is_open())
myStream->close();
delete myStream;
myStream = (ifstream*) 0;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
long Deserializer::getLong(void)
{
if(myStream.eof())
if(myStream->eof())
throw "Deserializer: end of file";
long l;
myStream.read(reinterpret_cast<char *> (&l), sizeof (long));
if(myStream.bad())
myStream->read(reinterpret_cast<char *> (&l), sizeof (long));
if(myStream->bad())
throw "Deserializer: file read failed";
return l;
@ -73,9 +79,9 @@ string Deserializer::getString(void)
long len = getLong();
string str;
str.resize(len);
myStream.read(&str[0], len);
myStream->read(&str[0], len);
if(myStream.bad())
if(myStream->bad())
throw "Deserializer: file read failed";
return str;
@ -87,7 +93,7 @@ bool Deserializer::getBool(void)
bool result = false;
long b = getLong();
if(myStream.bad())
if(myStream->bad())
throw "Deserializer: file read failed";
if(b == TruePattern)

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// 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
@ -32,7 +32,7 @@
return.
@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
{
@ -88,7 +88,7 @@ class Deserializer
private:
// The stream to get the deserialized data from.
ifstream myStream;
ifstream* myStream;
// A long pattern that represents a boolean value of true.
long TruePattern;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// 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>
@ -27,6 +27,8 @@ Serializer::Serializer(void)
{
TruePattern = 0xfab1fab2;
FalsePattern = 0xbad1bad2;
myStream = (ofstream*) 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -39,23 +41,29 @@ Serializer::~Serializer(void)
bool Serializer::open(string& fileName)
{
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)
{
if(myStream.is_open())
myStream.close();
if(myStream)
{
if(myStream->is_open())
myStream->close();
delete myStream;
myStream = (ofstream*) 0;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Serializer::putLong(long value)
{
myStream.write(reinterpret_cast<char *> (&value), sizeof (long));
if(myStream.bad())
myStream->write(reinterpret_cast<char *> (&value), sizeof (long));
if(myStream->bad())
throw "Serializer: file write failed";
}
@ -64,9 +72,9 @@ void Serializer::putString(string& str)
{
int len = str.length();
putLong(len);
myStream.write(str.data(), len);
myStream->write(str.data(), len);
if(myStream.bad())
if(myStream->bad())
throw "Serializer: file write failed";
}
@ -76,6 +84,6 @@ void Serializer::putBool(bool b)
long l = b ? TruePattern: FalsePattern;
putLong(l);
if(myStream.bad ())
if(myStream->bad ())
throw "Serializer: file write failed";
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// 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
@ -33,7 +33,7 @@
Boolean values are written using a special pattern.
@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
{
@ -89,7 +89,7 @@ class Serializer
private:
// The stream to send the serialized data to.
ofstream myStream;
ofstream* myStream;
// A long pattern that represents a boolean value of true.
long TruePattern;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// 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>
@ -209,7 +209,10 @@ int System::saveState(string &fileName, string& md5sum)
{
// Open the file as a new Serializer
if(!serializer->open(fileName))
{
serializer->close();
return 2;
}
// Prepend the state file with the md5sum of this cartridge
// This is the first defensive check for an invalid state file
@ -217,17 +220,26 @@ int System::saveState(string &fileName, string& md5sum)
// First save state for this system
if(!save(*serializer))
{
serializer->close();
return 3;
}
// Next, save state for the CPU
if(!myM6502->save(*serializer))
{
serializer->close();
return 3;
}
// Now save the state of each device
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
{
if(!myDevices[i]->save(*serializer))
{
serializer->close();
return 3;
}
}
serializer->close();
@ -239,26 +251,41 @@ int System::loadState(string &fileName, string& md5sum)
{
// Open the file as a new Deserializer
if(!deserializer->open(fileName))
{
deserializer->close();
return 2;
}
// 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.
if(deserializer->getString() != md5sum)
{
deserializer->close();
return 3;
}
// First load state for this system
if(!load(*deserializer))
{
deserializer->close();
return 3;
}
// Next, load state for the CPU
if(!myM6502->load(*deserializer))
{
deserializer->close();
return 3;
}
// Now load the state of each device
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
{
if(!myDevices[i]->load(*deserializer))
{
deserializer->close();
return 3;
}
}
deserializer->close();