From 938249cd717078f70a0f934e8773206ffa32474c Mon Sep 17 00:00:00 2001 From: stephena Date: Sun, 23 Sep 2007 17:04:17 +0000 Subject: [PATCH] Reworked state load and save, placing it in a new StateManager class, and removing it from EventHandler. For now, this is just a code re-arrangment, but eventually state recording and rewinding will be added to this new class as well. Since this new class will now do the job of the (buggy) EventStreamer code, that class has been removed. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1381 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- stella/src/debugger/Debugger.cxx | 7 +- stella/src/emucore/Event.cxx | 14 +- stella/src/emucore/Event.hxx | 12 +- stella/src/emucore/EventHandler.cxx | 123 ++------------- stella/src/emucore/EventHandler.hxx | 20 +-- stella/src/emucore/EventStreamer.cxx | 200 ------------------------ stella/src/emucore/EventStreamer.hxx | 131 ---------------- stella/src/emucore/OSystem.cxx | 13 +- stella/src/emucore/OSystem.hxx | 15 +- stella/src/emucore/StateManager.cxx | 151 ++++++++++++++++++ stella/src/emucore/StateManager.hxx | 85 ++++++++++ stella/src/emucore/m6502/src/System.cxx | 4 +- stella/src/emucore/module.mk | 2 +- 13 files changed, 284 insertions(+), 493 deletions(-) delete mode 100644 stella/src/emucore/EventStreamer.cxx delete mode 100644 stella/src/emucore/EventStreamer.hxx create mode 100644 stella/src/emucore/StateManager.cxx create mode 100644 stella/src/emucore/StateManager.hxx diff --git a/stella/src/debugger/Debugger.cxx b/stella/src/debugger/Debugger.cxx index 45d8dad4a..422c535a4 100644 --- a/stella/src/debugger/Debugger.cxx +++ b/stella/src/debugger/Debugger.cxx @@ -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: Debugger.cxx,v 1.115 2007-09-03 18:37:22 stephena Exp $ +// $Id: Debugger.cxx,v 1.116 2007-09-23 17:04:17 stephena Exp $ //============================================================================ #include "bspf.hxx" @@ -29,6 +29,7 @@ #include "Settings.hxx" #include "DebuggerDialog.hxx" #include "DebuggerParser.hxx" +#include "StateManager.hxx" #include "Console.hxx" #include "System.hxx" @@ -671,13 +672,13 @@ const string Debugger::dumpTIA() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Debugger::saveState(int state) { - myOSystem->eventHandler().saveState(state); + myOSystem->state().saveState(state); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Debugger::loadState(int state) { - myOSystem->eventHandler().loadState(state); + myOSystem->state().loadState(state); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/emucore/Event.cxx b/stella/src/emucore/Event.cxx index 4d8d5bd19..b95d45c79 100644 --- a/stella/src/emucore/Event.cxx +++ b/stella/src/emucore/Event.cxx @@ -13,16 +13,14 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Event.cxx,v 1.11 2007-01-01 18:04:47 stephena Exp $ +// $Id: Event.cxx,v 1.12 2007-09-23 17:04:17 stephena Exp $ //============================================================================ #include "Event.hxx" -#include "EventStreamer.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Event::Event(EventStreamer* ev) - : myNumberOfTypes(Event::LastType), - myEventStreamer(ev) +Event::Event() + : myNumberOfTypes(Event::LastType) { // Set all of the events to 0 / false to start with, // including analog paddle events. Doing it this way @@ -50,12 +48,6 @@ Int32 Event::get(Type type) const void Event::set(Type type, Int32 value) { myValues[type] = value; - -/* FIXME - add full functionality at some point - // Add to history if we're in recording mode - if(myEventStreamer->isRecording()) - myEventStreamer->addEvent(type, value); -*/ } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/emucore/Event.hxx b/stella/src/emucore/Event.hxx index 1385767cc..c4a247884 100644 --- a/stella/src/emucore/Event.hxx +++ b/stella/src/emucore/Event.hxx @@ -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: Event.hxx,v 1.28 2007-01-30 17:13:07 stephena Exp $ +// $Id: Event.hxx,v 1.29 2007-09-23 17:04:17 stephena Exp $ //============================================================================ #ifndef EVENT_HXX @@ -22,11 +22,10 @@ #include "bspf.hxx" class Event; -class EventStreamer; /** @author Bradford W. Mott - @version $Id: Event.hxx,v 1.28 2007-01-30 17:13:07 stephena Exp $ + @version $Id: Event.hxx,v 1.29 2007-09-23 17:04:17 stephena Exp $ */ class Event { @@ -88,9 +87,9 @@ class Event public: /** - Create a new event object and use the given eventstreamer + Create a new event object */ - Event(EventStreamer* ev); + Event(); /** Destructor @@ -119,9 +118,6 @@ class Event // Array of values associated with each event type Int32 myValues[LastType]; - - // The eventstreamer to record events to - EventStreamer* myEventStreamer; }; #endif diff --git a/stella/src/emucore/EventHandler.cxx b/stella/src/emucore/EventHandler.cxx index fe817514c..bcd2a0900 100644 --- a/stella/src/emucore/EventHandler.cxx +++ b/stella/src/emucore/EventHandler.cxx @@ -14,7 +14,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: EventHandler.cxx,v 1.209 2007-09-20 00:13:35 stephena Exp $ +// $Id: EventHandler.cxx,v 1.210 2007-09-23 17:04:17 stephena Exp $ //============================================================================ #include @@ -24,10 +24,8 @@ #include "CommandMenu.hxx" #include "Console.hxx" -#include "Deserializer.hxx" #include "DialogContainer.hxx" #include "Event.hxx" -#include "EventStreamer.hxx" #include "FrameBuffer.hxx" #include "FSNode.hxx" #include "Launcher.hxx" @@ -35,11 +33,10 @@ #include "OSystem.hxx" #include "PropsSet.hxx" #include "ScrollBarWidget.hxx" -#include "Serializer.hxx" #include "Settings.hxx" #include "Snapshot.hxx" #include "Sound.hxx" -#include "System.hxx" +#include "StateManager.hxx" #include "EventHandler.hxx" @@ -62,10 +59,8 @@ EventHandler::EventHandler(OSystem* osystem) : myOSystem(osystem), myEvent(NULL), - myEventStreamer(NULL), myOverlay(NULL), myState(S_NONE), - myLSState(0), myGrabMouseFlag(false), myUseLauncherFlag(false), myAllowAllDirectionsFlag(false), @@ -73,11 +68,8 @@ EventHandler::EventHandler(OSystem* osystem) myPaddleMode(0), myPaddleThreshold(0) { - // Create the streamer used for accessing eventstreams/recordings - myEventStreamer = new EventStreamer(myOSystem); - // Create the event object which will be used for this handler - myEvent = new Event(myEventStreamer); + myEvent = new Event(); // Erase the key mapping array for(int i = 0; i < SDLK_LAST; ++i) @@ -125,7 +117,6 @@ EventHandler::EventHandler(OSystem* osystem) EventHandler::~EventHandler() { delete myEvent; - delete myEventStreamer; #ifdef JOYSTICK_SUPPORT if(SDL_WasInit(SDL_INIT_JOYSTICK) & SDL_INIT_JOYSTICK) @@ -165,9 +156,10 @@ void EventHandler::reset(State state) { setEventState(state); - myLSState = 0; myEvent->clear(); + myOSystem->state().reset(); + if(myState == S_LAUNCHER) myUseLauncherFlag = true; @@ -183,8 +175,6 @@ void EventHandler::reset(State state) setPaddleSpeed(1, myOSystem->settings().getInt("p1speed")); setPaddleSpeed(2, myOSystem->settings().getInt("p2speed")); setPaddleSpeed(3, myOSystem->settings().getInt("p3speed")); - -// myEventStreamer->reset(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -357,6 +347,7 @@ void EventHandler::mapStelladaptors(const string& sa1, const string& sa2) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventHandler::poll(uInt32 time) { +// FIXME - change this to use StateManager stuff // Check if we have an event from the eventstreamer // TODO - should we lock out input from the user while getting synthetic events? // int type, value; @@ -846,6 +837,7 @@ void EventHandler::poll(uInt32 time) // Tell the eventstreamer that another frame has finished // This is used for event recording // myEventStreamer->nextFrame(); +// FIXME - change this to use StateManager stuff } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1176,15 +1168,15 @@ void EventHandler::handleEvent(Event::Type event, int state) return; case Event::SaveState: - if(state) saveState(); + if(state) myOSystem->state().saveState(); return; case Event::ChangeState: - if(state) changeState(); + if(state) myOSystem->state().changeState(); return; case Event::LoadState: - if(state) loadState(); + if(state) myOSystem->state().loadState(); return; case Event::TakeSnapshot: @@ -2022,101 +2014,6 @@ inline bool EventHandler::isJitter(int paddle, int value) return jitter; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void EventHandler::saveState() -{ - const string& name = myOSystem->console().properties().get(Cartridge_Name); - const string& md5 = myOSystem->console().properties().get(Cartridge_MD5); - - ostringstream buf; - buf << myOSystem->stateDir() << BSPF_PATH_SEPARATOR - << name << ".st" << myLSState; - - // Make sure the file can be opened for writing - Serializer out; - if(!out.open(buf.str())) - { - myOSystem->frameBuffer().showMessage("Error saving state file"); - return; - } - - // Do a state save using the System - buf.str(""); - if(myOSystem->console().system().saveState(md5, out)) - { - buf << "State " << myLSState << " saved"; - if(myOSystem->settings().getBool("autoslot")) - { - changeState(false); // don't show a message for state change - buf << ", switching to slot " << myLSState; - } - } - else - buf << "Error saving state " << myLSState; - - out.close(); - myOSystem->frameBuffer().showMessage(buf.str()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void EventHandler::saveState(int state) -{ - myLSState = state; - saveState(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void EventHandler::changeState(bool show) -{ - myLSState = (myLSState + 1) % 10; - - // Print appropriate message - if(show) - { - ostringstream buf; - buf << "Changed to slot " << myLSState; - myOSystem->frameBuffer().showMessage(buf.str()); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void EventHandler::loadState() -{ - const string& name = myOSystem->console().properties().get(Cartridge_Name); - const string& md5 = myOSystem->console().properties().get(Cartridge_MD5); - - ostringstream buf; - buf << myOSystem->stateDir() << BSPF_PATH_SEPARATOR - << name << ".st" << myLSState; - - // Make sure the file can be opened for reading - Deserializer in; - if(!in.open(buf.str())) - { - buf.str(""); - buf << "Error loading state " << myLSState; - myOSystem->frameBuffer().showMessage(buf.str()); - return; - } - - // Do a state load using the System - buf.str(""); - if(myOSystem->console().system().loadState(md5, in)) - buf << "State " << myLSState << " loaded"; - else - buf << "Invalid state " << myLSState << " file"; - - in.close(); - myOSystem->frameBuffer().showMessage(buf.str()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void EventHandler::loadState(int state) -{ - myLSState = state; - loadState(); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventHandler::takeSnapshot() { diff --git a/stella/src/emucore/EventHandler.hxx b/stella/src/emucore/EventHandler.hxx index 7221b38c1..0ea97b84c 100644 --- a/stella/src/emucore/EventHandler.hxx +++ b/stella/src/emucore/EventHandler.hxx @@ -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: EventHandler.hxx,v 1.103 2007-09-03 18:37:22 stephena Exp $ +// $Id: EventHandler.hxx,v 1.104 2007-09-23 17:04:17 stephena Exp $ //============================================================================ #ifndef EVENTHANDLER_HXX @@ -62,7 +62,7 @@ enum EventMode { mapping can take place. @author Stephen Anthony - @version $Id: EventHandler.hxx,v 1.103 2007-09-03 18:37:22 stephena Exp $ + @version $Id: EventHandler.hxx,v 1.104 2007-09-23 17:04:17 stephena Exp $ */ class EventHandler { @@ -191,16 +191,6 @@ class EventHandler */ void quit() { handleEvent(Event::Quit, 1); } - /** - Save state to explicit state number (debugger uses this) - */ - void saveState(int state); - - /** - Load state from explicit state number (debugger uses this) - */ - void loadState(int state); - /** Sets the mouse to act as paddle 'num' @@ -454,9 +444,6 @@ class EventHandler */ inline bool isJitter(int paddle, int value); - void saveState(); - void changeState(bool show = true); - void loadState(); void setEventState(State state); private: @@ -538,9 +525,6 @@ class EventHandler // Indicates the current state of the system (ie, which mode is current) State myState; - // Indicates the current state to use for state loading/saving - uInt32 myLSState; - // Indicates whether the mouse cursor is grabbed bool myGrabMouseFlag; diff --git a/stella/src/emucore/EventStreamer.cxx b/stella/src/emucore/EventStreamer.cxx deleted file mode 100644 index ba9775476..000000000 --- a/stella/src/emucore/EventStreamer.cxx +++ /dev/null @@ -1,200 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: EventStreamer.cxx,v 1.9 2007-09-03 18:37:22 stephena Exp $ -//============================================================================ - -#include "bspf.hxx" - -#include "Console.hxx" -#include "EventHandler.hxx" -#include "Event.hxx" -#include "OSystem.hxx" -#include "System.hxx" -#include "EventStreamer.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -EventStreamer::EventStreamer(OSystem* osystem) - : myOSystem(osystem), - myEventWriteFlag(false), - myEventReadFlag(false), - myFrameCounter(-1), - myEventPos(0) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -EventStreamer::~EventStreamer() -{ - stopRecording(); - - myEventHistory.clear(); - myStreamReader.close(); - myStreamWriter.close(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void EventStreamer::reset() -{ -//cerr << "EventStreamer::reset()\n"; - myEventWriteFlag = false; - myEventReadFlag = false; - myFrameCounter = -1; - myEventPos = 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool EventStreamer::startRecording() -{ - string eventfile = /*myOSystem->baseDir() + BSPF_PATH_SEPARATOR +*/ "test.inp"; - if(!myStreamWriter.open(eventfile)) - return false; - - // And save the current state to it - string md5 = myOSystem->console().properties().get(Cartridge_MD5); - if(!myOSystem->console().system().saveState(md5, myStreamWriter)) - return false; - myEventHistory.clear(); - - reset(); - return myEventWriteFlag = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool EventStreamer::stopRecording() -{ - if(!myStreamWriter.isOpen() || !myEventWriteFlag) - return false; - - // Append the event history to the eventstream - int size = myEventHistory.size(); - - try - { - myStreamWriter.putString("EventStream"); - myStreamWriter.putInt(size); - for(int i = 0; i < size; ++i) - myStreamWriter.putInt(myEventHistory[i]); - } - catch(char *msg) - { - cerr << msg << endl; - return false; - } - catch(...) - { - cerr << "Error saving eventstream" << endl; - return false; - } - - myStreamWriter.close(); - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool EventStreamer::loadRecording() -{ -cerr << "EventStreamer::loadRecording()\n"; - string eventfile = /*myOSystem->baseDir() + BSPF_PATH_SEPARATOR +*/ "test.inp"; - if(!myStreamReader.open(eventfile)) - return false; - - // Load ROM state - string md5 = myOSystem->console().properties().get(Cartridge_MD5); - if(!myOSystem->console().system().loadState(md5, myStreamReader)) - return false; - - try - { - if(myStreamReader.getString() != "EventStream") - return false; - - // Now load the event stream - myEventHistory.clear(); - int size = myStreamReader.getInt(); - for(int i = 0; i < size; ++i) - myEventHistory.push_back(myStreamReader.getInt()); - } - catch(char *msg) - { - cerr << msg << endl; - return false; - } - catch(...) - { - cerr << "Error loading eventstream" << endl; - return false; - } - - reset(); - myEventReadFlag = myEventHistory.size() > 0; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void EventStreamer::addEvent(int type, int value) -{ - if(myEventWriteFlag) - { - myEventHistory.push_back(type); - myEventHistory.push_back(value); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool EventStreamer::pollEvent(int& type, int& value) -{ - if(!myEventReadFlag) - return false; - - bool status = false; - - // Read a new event from the stream when we've waited the appropriate - // number of frames - ++myFrameCounter; - if(myFrameCounter >= 0) - { - int first = myEventHistory[myEventPos++]; - if(first < 0) - { - myFrameCounter = first; - cerr << "wait " << -myFrameCounter << " frames\n"; - } - else if(myEventPos < (int)myEventHistory.size()) - { - type = first; - value = myEventHistory[myEventPos++]; -cerr << "type = " << type << ", value = " << value << endl; - status = true; - } - } - - myEventReadFlag = myEventPos < (int)myEventHistory.size() - 2; - return status; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void EventStreamer::nextFrame() -{ - if(myEventWriteFlag) - { - int idx = myEventHistory.size() - 1; - if(idx >= 0 && myEventHistory[idx] < 0) - --myEventHistory[idx]; - else - myEventHistory.push_back(-1); - } -} diff --git a/stella/src/emucore/EventStreamer.hxx b/stella/src/emucore/EventStreamer.hxx deleted file mode 100644 index 33a417ee5..000000000 --- a/stella/src/emucore/EventStreamer.hxx +++ /dev/null @@ -1,131 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: EventStreamer.hxx,v 1.5 2007-01-01 18:04:48 stephena Exp $ -//============================================================================ - -#ifndef EVENTSTREAMER_HXX -#define EVENTSTREAMER_HXX - -#include "Array.hxx" -#include "Deserializer.hxx" -#include "Serializer.hxx" - -class OSystem; - -/** - This class takes care of event streams, which consist of a ROM state - file and appended event data. This appended data is defined as a - string of integers which are grouped as follows: - - event; event ; ... ; -framewait; event ... ; -framewait; ... - - 'event' consists of type/value pairs (each event in Stella is an - enumerated type with an associated value) - 'framewait' is the number of frames to wait until executing all - the following events - - The EventStreamer can load and save eventstream recordings. When in - 'save' mode, all events are queued from the Event class, and appended to - the ROM state when recording was started. - - When in 'load' mode, the ROM state is loaded from the eventstream, and - the appended event data is available in a queue for polling. - It's the responsibility of the calling object (most likely the EventHandler) - to poll for data; this class simply makes the queued events available in - the correct order at the correct time. - - @author Stephen Anthony - @version $Id: EventStreamer.hxx,v 1.5 2007-01-01 18:04:48 stephena Exp $ -*/ -class EventStreamer -{ - public: - /** - Create a new event streamer object - */ - EventStreamer(OSystem* osystem); - - /** - Destructor - */ - virtual ~EventStreamer(); - - public: - /** - Start recording event-stream to disk - */ - bool startRecording(); - - /** - Stop recording event-stream - */ - bool stopRecording(); - - /** - Load recorded event-stream into the system - */ - bool loadRecording(); - - /** - Adds the given event to the event history - */ - void addEvent(int type, int value); - - /** - Gets the next event from the event history - */ - bool pollEvent(int& type, int& value); - - /** - Answers if we're in recording mode - */ - bool isRecording() { return myEventWriteFlag; } - - /** - Indicate that a new frame has been processed - */ - void nextFrame(); - - /** - Reset to base state (not saving or loading an eventstream) - */ - void reset(); - - private: - - private: - // Global OSystem object - OSystem* myOSystem; - - // Indicates if we're in save/write or load/read mode - bool myEventWriteFlag; - bool myEventReadFlag; - - // Current frame count (used for waiting while polling) - int myFrameCounter; - - // Current position in the event history queue - int myEventPos; - - // Stores the history/record of all events that have been set - IntArray myEventHistory; - - // Serializer classes used to save/load the eventstream - Serializer myStreamWriter; - Deserializer myStreamReader; -}; - -#endif diff --git a/stella/src/emucore/OSystem.cxx b/stella/src/emucore/OSystem.cxx index a9f01c63c..243db3fc6 100644 --- a/stella/src/emucore/OSystem.cxx +++ b/stella/src/emucore/OSystem.cxx @@ -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: OSystem.cxx,v 1.110 2007-09-03 18:37:22 stephena Exp $ +// $Id: OSystem.cxx,v 1.111 2007-09-23 17:04:17 stephena Exp $ //============================================================================ #include @@ -21,6 +21,8 @@ #include #include +#include "bspf.hxx" + #include "MediaFactory.hxx" #ifdef DEBUGGER_SUPPORT @@ -43,10 +45,11 @@ #include "Font.hxx" #include "StellaFont.hxx" #include "ConsoleFont.hxx" -#include "bspf.hxx" -#include "OSystem.hxx" #include "Widget.hxx" #include "Console.hxx" +#include "StateManager.hxx" + +#include "OSystem.hxx" #define MAX_ROM_SIZE 512 * 1024 @@ -63,6 +66,7 @@ OSystem::OSystem() myLauncher(NULL), myDebugger(NULL), myCheatManager(NULL), + myStateManager(NULL), myQuitLoop(false), myRomFile(""), myFeatures(""), @@ -144,8 +148,10 @@ OSystem::~OSystem() delete myCheatManager; #endif + delete myStateManager; delete myPropSet; delete myEventHandler; + } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -183,6 +189,7 @@ bool OSystem::create() #ifdef DEBUGGER_SUPPORT myDebugger = new Debugger(this); #endif + myStateManager = new StateManager(this); // Create the sound object; the sound subsystem isn't actually // opened until needed, so this is non-blocking (on those systems diff --git a/stella/src/emucore/OSystem.hxx b/stella/src/emucore/OSystem.hxx index 2c9238e9a..57e2ddc01 100644 --- a/stella/src/emucore/OSystem.hxx +++ b/stella/src/emucore/OSystem.hxx @@ -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: OSystem.hxx,v 1.58 2007-09-12 00:57:51 stephena Exp $ +// $Id: OSystem.hxx,v 1.59 2007-09-23 17:04:17 stephena Exp $ //============================================================================ #ifndef OSYSTEM_HXX @@ -30,6 +30,7 @@ class Properties; class PropertiesSet; class Settings; class Sound; +class StateManager; class VideoDialog; namespace GUI { @@ -54,7 +55,7 @@ typedef Common::Array ResolutionList; other objects belong. @author Stephen Anthony - @version $Id: OSystem.hxx,v 1.58 2007-09-12 00:57:51 stephena Exp $ + @version $Id: OSystem.hxx,v 1.59 2007-09-23 17:04:17 stephena Exp $ */ class OSystem { @@ -148,6 +149,13 @@ class OSystem */ inline Launcher& launcher(void) const { return *myLauncher; } + /** + Get the state manager of the system. + + @return The statemanager object + */ + inline StateManager& state(void) const { return *myStateManager; } + #ifdef DEBUGGER_SUPPORT /** Get the ROM debugger of the system. @@ -473,6 +481,9 @@ class OSystem // Pointer to the CheatManager object CheatManager* myCheatManager; + // Pointer to the StateManager object + StateManager* myStateManager; + // Maximum dimensions of the desktop area uInt32 myDesktopWidth, myDesktopHeight; diff --git a/stella/src/emucore/StateManager.cxx b/stella/src/emucore/StateManager.cxx new file mode 100644 index 000000000..b9b0ab14d --- /dev/null +++ b/stella/src/emucore/StateManager.cxx @@ -0,0 +1,151 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: StateManager.cxx,v 1.1 2007-09-23 17:04:17 stephena Exp $ +//============================================================================ + +#include + +#include "OSystem.hxx" +#include "Serializer.hxx" +#include "Deserializer.hxx" +#include "Settings.hxx" +#include "Console.hxx" +#include "System.hxx" + +#include "StateManager.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +StateManager::StateManager(OSystem* osystem) + : myOSystem(osystem), + myCurrentSlot(0) +{ + reset(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +StateManager::~StateManager() +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void StateManager::loadState(int slot) +{ + if(&myOSystem->console()) + { + if(slot < 0) slot = myCurrentSlot; + + const string& name = myOSystem->console().properties().get(Cartridge_Name); + const string& md5 = myOSystem->console().properties().get(Cartridge_MD5); + + ostringstream buf; + buf << myOSystem->stateDir() << BSPF_PATH_SEPARATOR + << name << ".st" << slot; + + // Make sure the file can be opened for reading + Deserializer in; + if(!in.open(buf.str())) + { + buf.str(""); + buf << "Error loading state " << slot; + myOSystem->frameBuffer().showMessage(buf.str()); + return; + } + + // Do a state load using the System + buf.str(""); + if(myOSystem->console().system().loadState(md5, in)) + buf << "State " << slot << " loaded"; + else + buf << "Invalid state " << slot << " file"; + + in.close(); + myOSystem->frameBuffer().showMessage(buf.str()); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void StateManager::saveState(int slot) +{ + if(&myOSystem->console()) + { + if(slot < 0) slot = myCurrentSlot; + + const string& name = myOSystem->console().properties().get(Cartridge_Name); + const string& md5 = myOSystem->console().properties().get(Cartridge_MD5); + + ostringstream buf; + buf << myOSystem->stateDir() << BSPF_PATH_SEPARATOR + << name << ".st" << slot; + + // Make sure the file can be opened for writing + Serializer out; + if(!out.open(buf.str())) + { + myOSystem->frameBuffer().showMessage("Error saving state file"); + return; + } + + // Do a state save using the System + buf.str(""); +//int start = myOSystem->getTicks(); + if(myOSystem->console().system().saveState(md5, out)) + { +//int end = myOSystem->getTicks(); +//cerr << "ticks to save a state slot: " << (end - start) << endl; + + buf << "State " << slot << " saved"; + if(myOSystem->settings().getBool("autoslot")) + { + myCurrentSlot = (slot + 1) % 10; + buf << ", switching to slot " << slot; + } + } + else + buf << "Error saving state " << slot; + + out.close(); + myOSystem->frameBuffer().showMessage(buf.str()); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void StateManager::changeState() +{ + myCurrentSlot = (myCurrentSlot + 1) % 10; + + // Print appropriate message + ostringstream buf; + buf << "Changed to slot " << myCurrentSlot; + myOSystem->frameBuffer().showMessage(buf.str()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void StateManager::reset() +{ + myCurrentSlot = 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +StateManager::StateManager(const StateManager&) +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +StateManager& StateManager::operator = (const StateManager&) +{ + assert(false); + return *this; +} diff --git a/stella/src/emucore/StateManager.hxx b/stella/src/emucore/StateManager.hxx new file mode 100644 index 000000000..a11821efa --- /dev/null +++ b/stella/src/emucore/StateManager.hxx @@ -0,0 +1,85 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: StateManager.hxx,v 1.1 2007-09-23 17:04:17 stephena Exp $ +//============================================================================ + +#ifndef STATE_MANAGER_HXX +#define STATE_MANAGER_HXX + +class OSystem; + +/** + This class provides an interface to all things related to emulation state. + States can be loaded or saved here, as well as recorded, rewound, and later + played back. + + @author Stephen Anthony + @version $Id: StateManager.hxx,v 1.1 2007-09-23 17:04:17 stephena Exp $ +*/ +class StateManager +{ + public: + /** + Create a new statemananger class + */ + StateManager(OSystem* osystem); + + /** + Destructor + */ + virtual ~StateManager(); + + public: + /** + Load a state into the current system + + @param slot The state 'slot' to load state from + */ + void loadState(int slot = -1); + + /** + Save the current state from the system + + @param slot The state 'slot' to save into + */ + void saveState(int slot = -1); + + /** + Switches to the next higher state slot (circular queue style) + */ + void changeState(); + + /** + Resets manager to defaults + */ + void reset(); + + private: + // Copy constructor isn't supported by this class so make it private + StateManager(const StateManager&); + + // Assignment operator isn't supported by this class so make it private + StateManager& operator = (const StateManager&); + + private: + // The parent OSystem object + OSystem* myOSystem; + + // The current slot for load/save states + int myCurrentSlot; +}; + +#endif diff --git a/stella/src/emucore/m6502/src/System.cxx b/stella/src/emucore/m6502/src/System.cxx index 83286f817..7b4aabb2b 100644 --- a/stella/src/emucore/m6502/src/System.cxx +++ b/stella/src/emucore/m6502/src/System.cxx @@ -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.21 2007-01-01 18:04:51 stephena Exp $ +// $Id: System.cxx,v 1.22 2007-09-23 17:04:17 stephena Exp $ //============================================================================ #include @@ -205,7 +205,6 @@ const System::PageAccess& System::getPageAccess(uInt16 page) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool System::saveState(const string& md5sum, Serializer& out) { - // Open the file as a new Serializer if(!out.isOpen()) return false; @@ -245,7 +244,6 @@ bool System::saveState(const string& md5sum, Serializer& out) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool System::loadState(const string& md5sum, Deserializer& in) { - // Open the file as a new Deserializer if(!in.isOpen()) return false; diff --git a/stella/src/emucore/module.mk b/stella/src/emucore/module.mk index 6ebfca95d..0c9e8dab9 100644 --- a/stella/src/emucore/module.mk +++ b/stella/src/emucore/module.mk @@ -32,7 +32,6 @@ MODULE_OBJS := \ src/emucore/Driving.o \ src/emucore/Event.o \ src/emucore/EventHandler.o \ - src/emucore/EventStreamer.o \ src/emucore/FrameBuffer.o \ src/emucore/FSNode.o \ src/emucore/Joystick.o \ @@ -49,6 +48,7 @@ MODULE_OBJS := \ src/emucore/Settings.o \ src/emucore/SpeakJet.o \ src/emucore/Switches.o \ + src/emucore/StateManager.o \ src/emucore/TIA.o \ src/emucore/TIASnd.o \ src/emucore/unzip.o \