mirror of https://github.com/stella-emu/stella.git
Added initial support for state loading and saving. The relevant methods
are in System.cxx, and can be accessed from the various ports through the Console. To save state, call theConsole->system.saveState(string filename, string md5sum). The filename should include the full path and can be anything. The md5sum is obvious and is used to make sure that the filename is actually a state file for the current ROM. To load state, call theConsole->system().loadState(string filename, string md5sum. These variables have the same meaning as above. For now, only the SDL port has access to these. Support will be added for all ports when I do some more testing. I'd appreciate some bug reports, especially related to sound handing on state load. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@93 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
2cafb1d3f0
commit
3e3ca7d10e
|
@ -13,13 +13,15 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: Device.hxx,v 1.1.1.1 2001-12-27 19:54:29 bwmott Exp $
|
||||
// $Id: Device.hxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef DEVICE_HXX
|
||||
#define DEVICE_HXX
|
||||
|
||||
class System;
|
||||
class Serializer;
|
||||
class Deserializer;
|
||||
|
||||
#include "bspf.hxx"
|
||||
|
||||
|
@ -28,7 +30,7 @@ class System;
|
|||
based system.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@version $Id: Device.hxx,v 1.1.1.1 2001-12-27 19:54:29 bwmott Exp $
|
||||
@version $Id: Device.hxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
*/
|
||||
class Device
|
||||
{
|
||||
|
@ -71,6 +73,22 @@ class Device
|
|||
*/
|
||||
virtual void install(System& system) = 0;
|
||||
|
||||
/**
|
||||
Saves the current state of this device to the given Serializer.
|
||||
|
||||
@param out The serializer device to save to.
|
||||
@return The result of the save. True on success, false on failure.
|
||||
*/
|
||||
virtual bool save(Serializer& out) = 0;
|
||||
|
||||
/**
|
||||
Loads the current state of this device from the given Deserializer.
|
||||
|
||||
@param in The deserializer device to load from.
|
||||
@return The result of the load. True on success, false on failure.
|
||||
*/
|
||||
virtual bool load(Deserializer& in) = 0;
|
||||
|
||||
public:
|
||||
/**
|
||||
Get the byte at the specified address
|
||||
|
|
|
@ -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: M6502.hxx,v 1.1.1.1 2001-12-27 19:54:30 bwmott Exp $
|
||||
// $Id: M6502.hxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef M6502_HXX
|
||||
|
@ -21,6 +21,8 @@
|
|||
|
||||
class D6502;
|
||||
class M6502;
|
||||
class Serializer;
|
||||
class Deserializer;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "System.hxx"
|
||||
|
@ -31,7 +33,7 @@ class M6502;
|
|||
has a 64K addressing space.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@version $Id: M6502.hxx,v 1.1.1.1 2001-12-27 19:54:30 bwmott Exp $
|
||||
@version $Id: M6502.hxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
*/
|
||||
class M6502
|
||||
{
|
||||
|
@ -94,6 +96,29 @@ class M6502
|
|||
*/
|
||||
virtual void nmi();
|
||||
|
||||
/**
|
||||
Saves the current state of this device to the given Serializer.
|
||||
|
||||
@param out The serializer device to save to.
|
||||
@return The result of the save. True on success, false on failure.
|
||||
*/
|
||||
virtual bool save(Serializer& out) = 0;
|
||||
|
||||
/**
|
||||
Loads the current state of this device from the given Deserializer.
|
||||
|
||||
@param in The deserializer device to load from.
|
||||
@return The result of the load. True on success, false on failure.
|
||||
*/
|
||||
virtual bool load(Deserializer& in) = 0;
|
||||
|
||||
/**
|
||||
Get a null terminated string which is the processor's name (i.e. "M6532")
|
||||
|
||||
@return The name of the device
|
||||
*/
|
||||
virtual const char* name() const = 0;
|
||||
|
||||
public:
|
||||
/**
|
||||
Get the addressing mode of the specified instruction
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: M6502Hi.cxx,v 1.1.1.1 2001-12-27 19:54:30 bwmott Exp $
|
||||
// $Id: M6502Hi.cxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include "M6502Hi.hxx"
|
||||
#include "Serializer.hxx"
|
||||
#include "Deserializer.hxx"
|
||||
|
||||
#define debugStream cout
|
||||
|
||||
|
@ -167,3 +169,100 @@ void M6502High::interruptHandler()
|
|||
myExecutionStatus &= ~(MaskableInterruptBit | NonmaskableInterruptBit);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool M6502High::save(Serializer& out)
|
||||
{
|
||||
string CPU = name();
|
||||
|
||||
try
|
||||
{
|
||||
out.putString(CPU);
|
||||
|
||||
out.putLong(A); // Accumulator
|
||||
out.putLong(X); // X index register
|
||||
out.putLong(Y); // Y index register
|
||||
out.putLong(SP); // Stack Pointer
|
||||
out.putLong(IR); // Instruction register
|
||||
out.putLong(PC); // Program Counter
|
||||
|
||||
out.putBool(N); // N flag for processor status register
|
||||
out.putBool(V); // V flag for processor status register
|
||||
out.putBool(B); // B flag for processor status register
|
||||
out.putBool(D); // D flag for processor status register
|
||||
out.putBool(I); // I flag for processor status register
|
||||
out.putBool(notZ); // Z flag complement for processor status register
|
||||
out.putBool(C); // C flag for processor status register
|
||||
|
||||
out.putLong(myExecutionStatus);
|
||||
|
||||
// Indicates the number of distinct memory accesses
|
||||
out.putLong(myNumberOfDistinctAccesses);
|
||||
// Indicates the last address which was accessed
|
||||
out.putLong(myLastAddress);
|
||||
|
||||
}
|
||||
catch(char *msg)
|
||||
{
|
||||
cerr << msg << endl;
|
||||
return false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "Unknown error in save state for " << CPU << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool M6502High::load(Deserializer& in)
|
||||
{
|
||||
string CPU = name();
|
||||
|
||||
try
|
||||
{
|
||||
if(in.getString() != CPU)
|
||||
return false;
|
||||
|
||||
A = (uInt8) in.getLong(); // Accumulator
|
||||
X = (uInt8) in.getLong(); // X index register
|
||||
Y = (uInt8) in.getLong(); // Y index register
|
||||
SP = (uInt8) in.getLong(); // Stack Pointer
|
||||
IR = (uInt8) in.getLong(); // Instruction register
|
||||
PC = (uInt16) in.getLong(); // Program Counter
|
||||
|
||||
N = in.getBool(); // N flag for processor status register
|
||||
V = in.getBool(); // V flag for processor status register
|
||||
B = in.getBool(); // B flag for processor status register
|
||||
D = in.getBool(); // D flag for processor status register
|
||||
I = in.getBool(); // I flag for processor status register
|
||||
notZ = in.getBool(); // Z flag complement for processor status register
|
||||
C = in.getBool(); // C flag for processor status register
|
||||
|
||||
myExecutionStatus = (uInt8) in.getLong();
|
||||
|
||||
// Indicates the number of distinct memory accesses
|
||||
myNumberOfDistinctAccesses = (uInt32) in.getLong();
|
||||
// Indicates the last address which was accessed
|
||||
myLastAddress = (uInt16) in.getLong();
|
||||
}
|
||||
catch(char *msg)
|
||||
{
|
||||
cerr << msg << endl;
|
||||
return false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "Unknown error in load state for " << CPU << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const char* M6502High::name() const
|
||||
{
|
||||
return "M6502High";
|
||||
}
|
||||
|
|
|
@ -13,13 +13,15 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: M6502Hi.hxx,v 1.1.1.1 2001-12-27 19:54:30 bwmott Exp $
|
||||
// $Id: M6502Hi.hxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef M6502HIGH_HXX
|
||||
#define M6502HIGH_HXX
|
||||
|
||||
class M6502High;
|
||||
class Serializer;
|
||||
class Deserializer;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "M6502.hxx"
|
||||
|
@ -33,7 +35,7 @@ class M6502High;
|
|||
effects and for games which are very time sensitive.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@version $Id: M6502Hi.hxx,v 1.1.1.1 2001-12-27 19:54:30 bwmott Exp $
|
||||
@version $Id: M6502Hi.hxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
*/
|
||||
class M6502High : public M6502
|
||||
{
|
||||
|
@ -62,6 +64,29 @@ class M6502High : public M6502
|
|||
*/
|
||||
virtual bool execute(uInt32 number);
|
||||
|
||||
/**
|
||||
Saves the current state of this device to the given Serializer.
|
||||
|
||||
@param out The serializer device to save to.
|
||||
@return The result of the save. True on success, false on failure.
|
||||
*/
|
||||
virtual bool save(Serializer& out);
|
||||
|
||||
/**
|
||||
Loads the current state of this device from the given Deserializer.
|
||||
|
||||
@param in The deserializer device to load from.
|
||||
@return The result of the load. True on success, false on failure.
|
||||
*/
|
||||
virtual bool load(Deserializer& in);
|
||||
|
||||
/**
|
||||
Get a null terminated string which is the processors's name (i.e. "M6532")
|
||||
|
||||
@return The name of the device
|
||||
*/
|
||||
virtual const char* name() const;
|
||||
|
||||
public:
|
||||
/**
|
||||
Get the number of memory accesses to distinct memory locations
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: M6502Low.cxx,v 1.1.1.1 2001-12-27 19:54:31 bwmott Exp $
|
||||
// $Id: M6502Low.cxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include "M6502Low.hxx"
|
||||
#include "Serializer.hxx"
|
||||
#include "Deserializer.hxx"
|
||||
|
||||
#define debugStream cout
|
||||
|
||||
|
@ -157,3 +159,89 @@ void M6502Low::interruptHandler()
|
|||
myExecutionStatus &= ~(MaskableInterruptBit | NonmaskableInterruptBit);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool M6502Low::save(Serializer& out)
|
||||
{
|
||||
string CPU = name();
|
||||
|
||||
try
|
||||
{
|
||||
out.putString(CPU);
|
||||
|
||||
out.putLong(A); // Accumulator
|
||||
out.putLong(X); // X index register
|
||||
out.putLong(Y); // Y index register
|
||||
out.putLong(SP); // Stack Pointer
|
||||
out.putLong(IR); // Instruction register
|
||||
out.putLong(PC); // Program Counter
|
||||
|
||||
out.putBool(N); // N flag for processor status register
|
||||
out.putBool(V); // V flag for processor status register
|
||||
out.putBool(B); // B flag for processor status register
|
||||
out.putBool(D); // D flag for processor status register
|
||||
out.putBool(I); // I flag for processor status register
|
||||
out.putBool(notZ); // Z flag complement for processor status register
|
||||
out.putBool(C); // C flag for processor status register
|
||||
|
||||
out.putLong(myExecutionStatus);
|
||||
}
|
||||
catch(char *msg)
|
||||
{
|
||||
cerr << msg << endl;
|
||||
return false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "Unknown error in save state for " << CPU << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool M6502Low::load(Deserializer& in)
|
||||
{
|
||||
string CPU = name();
|
||||
|
||||
try
|
||||
{
|
||||
if(in.getString() != CPU)
|
||||
return false;
|
||||
|
||||
A = (uInt8) in.getLong(); // Accumulator
|
||||
X = (uInt8) in.getLong(); // X index register
|
||||
Y = (uInt8) in.getLong(); // Y index register
|
||||
SP = (uInt8) in.getLong(); // Stack Pointer
|
||||
IR = (uInt8) in.getLong(); // Instruction register
|
||||
PC = (uInt16) in.getLong(); // Program Counter
|
||||
|
||||
N = in.getBool(); // N flag for processor status register
|
||||
V = in.getBool(); // V flag for processor status register
|
||||
B = in.getBool(); // B flag for processor status register
|
||||
D = in.getBool(); // D flag for processor status register
|
||||
I = in.getBool(); // I flag for processor status register
|
||||
notZ = in.getBool(); // Z flag complement for processor status register
|
||||
C = in.getBool(); // C flag for processor status register
|
||||
|
||||
myExecutionStatus = (uInt8) in.getLong();
|
||||
}
|
||||
catch(char *msg)
|
||||
{
|
||||
cerr << msg << endl;
|
||||
return false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "Unknown error in load state for " << CPU << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const char* M6502Low::name() const
|
||||
{
|
||||
return "M6502Low";
|
||||
}
|
||||
|
|
|
@ -13,13 +13,15 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: M6502Low.hxx,v 1.1.1.1 2001-12-27 19:54:31 bwmott Exp $
|
||||
// $Id: M6502Low.hxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef M6507LOW_HXX
|
||||
#define M6507LOW_HXX
|
||||
|
||||
class M6507Low;
|
||||
class Serializer;
|
||||
class Deserializer;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "M6502.hxx"
|
||||
|
@ -39,7 +41,7 @@ class M6507Low;
|
|||
better compatibility is neccessary use one of the other 6502 classes.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@version $Id: M6502Low.hxx,v 1.1.1.1 2001-12-27 19:54:31 bwmott Exp $
|
||||
@version $Id: M6502Low.hxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
*/
|
||||
class M6502Low : public M6502
|
||||
{
|
||||
|
@ -68,6 +70,29 @@ class M6502Low : public M6502
|
|||
*/
|
||||
virtual bool execute(uInt32 number);
|
||||
|
||||
/**
|
||||
Saves the current state of this device to the given Serializer.
|
||||
|
||||
@param out The serializer device to save to.
|
||||
@return The result of the save. True on success, false on failure.
|
||||
*/
|
||||
virtual bool save(Serializer& out);
|
||||
|
||||
/**
|
||||
Loads the current state of this device from the given Deserializer.
|
||||
|
||||
@param in The deserializer device to load from.
|
||||
@return The result of the load. True on success, false on failure.
|
||||
*/
|
||||
virtual bool load(Deserializer& in);
|
||||
|
||||
/**
|
||||
Get a null terminated string which is the processors's name (i.e. "M6532")
|
||||
|
||||
@return The name of the device
|
||||
*/
|
||||
virtual const char* name() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
Called after an interrupt has be requested using irq() or nmi()
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: NullDev.cxx,v 1.1.1.1 2001-12-27 19:54:31 bwmott Exp $
|
||||
// $Id: NullDev.cxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include "NullDev.hxx"
|
||||
#include "Serializer.hxx"
|
||||
#include "Deserializer.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
NullDevice::NullDevice()
|
||||
|
@ -58,3 +60,14 @@ void NullDevice::poke(uInt16 address, uInt8 value)
|
|||
cerr << hex << "NullDevice: poke(" << address << "," << value << ")" << endl;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool NullDevice::save(Serializer& out)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool NullDevice::load(Deserializer& in)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -13,13 +13,15 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: NullDev.hxx,v 1.1.1.1 2001-12-27 19:54:31 bwmott Exp $
|
||||
// $Id: NullDev.hxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef NULLDEVICE_HXX
|
||||
#define NULLDEVICE_HXX
|
||||
|
||||
class System;
|
||||
class Serializer;
|
||||
class Deserializer;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Device.hxx"
|
||||
|
@ -30,7 +32,7 @@ class System;
|
|||
holes in the address space (i.e. no real device attached).
|
||||
|
||||
@author Bradford W. Mott
|
||||
@version $Id: NullDev.hxx,v 1.1.1.1 2001-12-27 19:54:31 bwmott Exp $
|
||||
@version $Id: NullDev.hxx,v 1.2 2002-05-13 19:10:25 stephena Exp $
|
||||
*/
|
||||
class NullDevice : public Device
|
||||
{
|
||||
|
@ -66,6 +68,22 @@ class NullDevice : public Device
|
|||
*/
|
||||
virtual void install(System& system);
|
||||
|
||||
/**
|
||||
Saves the current state of this device to the given Serializer.
|
||||
|
||||
@param out The serializer device to save to.
|
||||
@return The result of the save. True on success, false on failure.
|
||||
*/
|
||||
virtual bool save(Serializer& out);
|
||||
|
||||
/**
|
||||
Loads the current state of this device from the given Deserializer.
|
||||
|
||||
@param in The deserializer device to load from.
|
||||
@return The result of the load. True on success, false on failure.
|
||||
*/
|
||||
virtual bool load(Deserializer& in);
|
||||
|
||||
public:
|
||||
/**
|
||||
Get the byte at the specified address
|
||||
|
|
|
@ -13,13 +13,17 @@
|
|||
// 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.2 2001-12-30 18:36:02 bwmott Exp $
|
||||
// $Id: System.cxx,v 1.3 2002-05-13 19:10:25 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "Device.hxx"
|
||||
#include "M6502.hxx"
|
||||
#include "System.hxx"
|
||||
#include "Serializer.hxx"
|
||||
#include "Deserializer.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
System::System(uInt16 n, uInt16 m)
|
||||
|
@ -47,6 +51,10 @@ System::System(uInt16 n, uInt16 m)
|
|||
{
|
||||
setPageAccess(page, access);
|
||||
}
|
||||
|
||||
// Set up (de)serializer in case we are asked to save/load state
|
||||
serializer = new Serializer();
|
||||
deserializer = new Deserializer();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -63,6 +71,12 @@ System::~System()
|
|||
|
||||
// Free my page access table
|
||||
delete[] myPageAccessTable;
|
||||
|
||||
// Free the serializer stuff
|
||||
if(serializer)
|
||||
delete serializer;
|
||||
if(deserializer)
|
||||
delete deserializer;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -71,7 +85,7 @@ void System::reset()
|
|||
// Reset system cycle counter
|
||||
resetCycles();
|
||||
|
||||
// Frist we reset the devices attached to myself
|
||||
// First we reset the devices attached to myself
|
||||
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
|
||||
{
|
||||
myDevices[i]->reset();
|
||||
|
@ -106,10 +120,60 @@ void System::attach(M6502* m6502)
|
|||
myM6502->install(*this);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool System::save(Serializer& out)
|
||||
{
|
||||
string name = "System";
|
||||
|
||||
try
|
||||
{
|
||||
out.putString(name);
|
||||
out.putLong(myCycles);
|
||||
}
|
||||
catch(char *msg)
|
||||
{
|
||||
cerr << msg << endl;
|
||||
return false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "Unknown error in save state for " << name << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool System::load(Deserializer& in)
|
||||
{
|
||||
string name = "System";
|
||||
|
||||
try
|
||||
{
|
||||
if(in.getString() != name)
|
||||
return false;
|
||||
|
||||
myCycles = (uInt32) in.getLong();
|
||||
}
|
||||
catch(char *msg)
|
||||
{
|
||||
cerr << msg << endl;
|
||||
return false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "Unknown error in load state for " << name << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void System::resetCycles()
|
||||
{
|
||||
// Frist we let all of the device attached to me know about the reset
|
||||
// First we let all of the device attached to me know about the reset
|
||||
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
|
||||
{
|
||||
myDevices[i]->systemCyclesReset();
|
||||
|
@ -140,12 +204,73 @@ const System::PageAccess& System::getPageAccess(uInt16 page)
|
|||
return myPageAccessTable[page];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int System::saveState(string &fileName, string& md5sum)
|
||||
{
|
||||
// Open the file as a new Serializer
|
||||
if(!serializer->open(fileName))
|
||||
return 2;
|
||||
|
||||
// Prepend the state file with the md5sum of this cartridge
|
||||
// This is the first defensive check for an invalid state file
|
||||
serializer->putString(md5sum);
|
||||
|
||||
// First save state for this system
|
||||
if(!save(*serializer))
|
||||
return 3;
|
||||
|
||||
// Next, save state for the CPU
|
||||
if(!myM6502->save(*serializer))
|
||||
return 3;
|
||||
|
||||
// Now save the state of each device
|
||||
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
|
||||
{
|
||||
if(!myDevices[i]->save(*serializer))
|
||||
return 3;
|
||||
}
|
||||
|
||||
serializer->close();
|
||||
return 1; // success
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int System::loadState(string &fileName, string& md5sum)
|
||||
{
|
||||
// Open the file as a new Deserializer
|
||||
if(!deserializer->open(fileName))
|
||||
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)
|
||||
return 3;
|
||||
|
||||
// First load state for this system
|
||||
if(!load(*deserializer))
|
||||
return 3;
|
||||
|
||||
// Next, load state for the CPU
|
||||
if(!myM6502->load(*deserializer))
|
||||
return 3;
|
||||
|
||||
// Now load the state of each device
|
||||
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
|
||||
{
|
||||
if(!myDevices[i]->load(*deserializer))
|
||||
return 3;
|
||||
}
|
||||
|
||||
deserializer->close();
|
||||
return 1; // success
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
System::System(const System& s)
|
||||
: myAddressMask(s.myAddressMask),
|
||||
myPageShift(s.myPageShift),
|
||||
myPageMask(s.myPageMask),
|
||||
myNumberOfPages(s.myNumberOfPages)
|
||||
myNumberOfPages(s.myNumberOfPages)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
@ -157,5 +282,3 @@ System& System::operator = (const System&)
|
|||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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.hxx,v 1.2 2001-12-30 18:36:02 bwmott Exp $
|
||||
// $Id: System.hxx,v 1.3 2002-05-13 19:10:25 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef SYSTEM_HXX
|
||||
|
@ -22,6 +22,8 @@
|
|||
class Device;
|
||||
class M6502;
|
||||
class NullDevice;
|
||||
class Serializer;
|
||||
class Deserializer;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Device.hxx"
|
||||
|
@ -44,7 +46,7 @@ class NullDevice;
|
|||
dynamic code for that page of memory.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@version $Id: System.hxx,v 1.2 2001-12-30 18:36:02 bwmott Exp $
|
||||
@version $Id: System.hxx,v 1.3 2002-05-13 19:10:25 stephena Exp $
|
||||
*/
|
||||
class System
|
||||
{
|
||||
|
@ -70,6 +72,22 @@ class System
|
|||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
Saves the current state of this system class to the given Serializer.
|
||||
|
||||
@param out The serializer device to save to.
|
||||
@return The result of the save. True on success, false on failure.
|
||||
*/
|
||||
bool save(Serializer& out);
|
||||
|
||||
/**
|
||||
Loads the current state of this system class from the given Deserializer.
|
||||
|
||||
@param in The deserializer device to load from.
|
||||
@return The result of the load. True on success, false on failure.
|
||||
*/
|
||||
bool load(Deserializer& in);
|
||||
|
||||
public:
|
||||
/**
|
||||
Attach the specified device and claim ownership of it. The device
|
||||
|
@ -87,6 +105,30 @@ class System
|
|||
*/
|
||||
void attach(M6502* m6502);
|
||||
|
||||
/**
|
||||
Saves the current state of Stella to the given file. Calls
|
||||
save on every device and CPU attached to this system.
|
||||
|
||||
@param out The serializer device to save to.
|
||||
@return The result of the save. Error codes as follows:
|
||||
1 success
|
||||
2 file could not be opened for read/write
|
||||
3 invalid state file
|
||||
*/
|
||||
int saveState(string& fileName, string& md5sum);
|
||||
|
||||
/**
|
||||
Loads the current state of Stella from the given file. Calls
|
||||
load on every device and CPU attached to this system.
|
||||
|
||||
@param in The deserializer device to load from.
|
||||
@return The result of the load. Error codes as follows:
|
||||
1 success
|
||||
2 file could not be opened for read/write
|
||||
3 invalid state file
|
||||
*/
|
||||
int loadState(string& fileName, string& md5sum);
|
||||
|
||||
public:
|
||||
/**
|
||||
Answer the 6502 microprocessor attached to the system. If a
|
||||
|
@ -278,6 +320,12 @@ class System
|
|||
// The current state of the Data Bus
|
||||
uInt8 myDataBusState;
|
||||
|
||||
// The serializer for the system. Used to save state.
|
||||
Serializer* serializer;
|
||||
|
||||
// The deserializer for the system. Used to load state.
|
||||
Deserializer* deserializer;
|
||||
|
||||
private:
|
||||
// Copy constructor isn't supported by this class so make it private
|
||||
System(const System&);
|
||||
|
@ -332,4 +380,3 @@ inline void System::poke(uInt16 addr, uInt8 value)
|
|||
myDataBusState = value;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue