diff --git a/stella/src/common/Array.hxx b/stella/src/common/Array.hxx index 529d1d2a2..aaca8c35a 100644 --- a/stella/src/common/Array.hxx +++ b/stella/src/common/Array.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: Array.hxx,v 1.1 2005-12-09 01:16:13 stephena Exp $ +// $Id: Array.hxx,v 1.2 2005-12-09 19:09:49 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -45,7 +45,7 @@ class Array Array(const Array& array) : _capacity(0), _size(0), _data(0) { _size = array._size; - _capacity = _size + 32; + _capacity = _size + 128; _data = new T[_capacity]; for(int i = 0; i < _size; i++) _data[i] = array._data[i]; @@ -115,7 +115,7 @@ class Array if (_data) delete [] _data; _size = array._size; - _capacity = _size + 32; + _capacity = _size + 128; _data = new T[_capacity]; for(int i = 0; i < _size; i++) _data[i] = array._data[i]; @@ -177,7 +177,7 @@ class Array return; T *old_data = _data; - _capacity = new_len + 32; + _capacity = new_len + 128; _data = new T[_capacity]; if (old_data) diff --git a/stella/src/emucore/Deserializer.cxx b/stella/src/emucore/Deserializer.cxx index 772def4d3..28555d61e 100644 --- a/stella/src/emucore/Deserializer.cxx +++ b/stella/src/emucore/Deserializer.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: Deserializer.cxx,v 1.5 2005-10-29 18:11:29 stephena Exp $ +// $Id: Deserializer.cxx,v 1.6 2005-12-09 19:09:49 stephena Exp $ //============================================================================ #include @@ -43,7 +43,7 @@ bool Deserializer::open(const string& fileName) close(); myStream = new ifstream(fileName.c_str(), ios::in | ios::binary); - return (myStream && myStream->is_open()); + return isOpen(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -59,6 +59,12 @@ void Deserializer::close(void) } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool Deserializer::isOpen(void) +{ + return myStream && myStream->is_open(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - long Deserializer::getLong(void) { diff --git a/stella/src/emucore/Deserializer.hxx b/stella/src/emucore/Deserializer.hxx index 9aee6cdee..2e32080ee 100644 --- a/stella/src/emucore/Deserializer.hxx +++ b/stella/src/emucore/Deserializer.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: Deserializer.hxx,v 1.6 2005-06-16 01:11:27 stephena Exp $ +// $Id: Deserializer.hxx,v 1.7 2005-12-09 19:09:49 stephena Exp $ //============================================================================ #ifndef DESERIALIZER_HXX @@ -32,7 +32,7 @@ return. @author Stephen Anthony - @version $Id: Deserializer.hxx,v 1.6 2005-06-16 01:11:27 stephena Exp $ + @version $Id: Deserializer.hxx,v 1.7 2005-12-09 19:09:49 stephena Exp $ */ class Deserializer { @@ -65,6 +65,11 @@ class Deserializer */ void close(void); + /** + Answers whether the deserializer is currently opened + */ + bool isOpen(void); + /** Reads a long value from the current input stream. diff --git a/stella/src/emucore/Event.cxx b/stella/src/emucore/Event.cxx index 178c45574..7b10f0932 100644 --- a/stella/src/emucore/Event.cxx +++ b/stella/src/emucore/Event.cxx @@ -13,15 +13,16 @@ // 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.4 2005-12-09 01:16:13 stephena Exp $ +// $Id: Event.cxx,v 1.5 2005-12-09 19:09:49 stephena Exp $ //============================================================================ #include "Event.hxx" +#include "Serializer.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Event::Event() : myNumberOfTypes(Event::LastType), - myEventRecordFlag(true) + myEventRecordFlag(false) { // Set all of the events to 0 / false to start with clear(); @@ -30,27 +31,6 @@ Event::Event() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Event::~Event() { - int events = 0, waits = 0, totalwaits = 0; - cerr << "Event history contains " << myEventHistory.size()/2 << " events\n"; - for(unsigned int i = 0; i < myEventHistory.size(); ++i) - { - int tmp = myEventHistory[i]; - if(tmp < 0) - { - ++waits; - totalwaits += -tmp; - } - else - ++events; - - cerr << tmp << " "; - } - cerr << endl - << "events pairs = " << events/2 - << ", frame waits = " << waits - << ", total frame waits = " << totalwaits - << endl; - myEventHistory.clear(); } @@ -106,3 +86,15 @@ void Event::nextFrame() myEventHistory.push_back(-1); } } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool Event::save(Serializer& out) +{ + int size = myEventHistory.size(); + out.putString("EventStream"); + out.putLong(size); + for(int i = 0; i < size; ++i) + out.putLong(myEventHistory[i]); + + return true; +} diff --git a/stella/src/emucore/Event.hxx b/stella/src/emucore/Event.hxx index 8f06b4704..48e706114 100644 --- a/stella/src/emucore/Event.hxx +++ b/stella/src/emucore/Event.hxx @@ -13,20 +13,21 @@ // 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.14 2005-12-09 01:16:13 stephena Exp $ +// $Id: Event.hxx,v 1.15 2005-12-09 19:09:49 stephena Exp $ //============================================================================ #ifndef EVENT_HXX #define EVENT_HXX class Event; +class Serializer; #include "Array.hxx" #include "bspf.hxx" /** @author Bradford W. Mott - @version $Id: Event.hxx,v 1.14 2005-12-09 01:16:13 stephena Exp $ + @version $Id: Event.hxx,v 1.15 2005-12-09 19:09:49 stephena Exp $ */ class Event { @@ -105,11 +106,6 @@ class Event */ virtual void clear(); - /** - Returns the history for this event - */ - virtual const IntArray& history() { return myEventHistory; } - /** Start/stop recording events to the event history @@ -122,6 +118,19 @@ class Event */ virtual void nextFrame(); + /** + Answers if we're in recording mode + */ + virtual bool isRecording() { return myEventRecordFlag; } + + /** + Saves the current event history 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); + protected: // Number of event types there are const Int32 myNumberOfTypes; diff --git a/stella/src/emucore/EventHandler.cxx b/stella/src/emucore/EventHandler.cxx index c42ada6fc..3ccda0424 100644 --- a/stella/src/emucore/EventHandler.cxx +++ b/stella/src/emucore/EventHandler.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: EventHandler.cxx,v 1.124 2005-12-09 01:16:13 stephena Exp $ +// $Id: EventHandler.cxx,v 1.125 2005-12-09 19:09:49 stephena Exp $ //============================================================================ #include @@ -33,6 +33,8 @@ #include "CommandMenu.hxx" #include "Launcher.hxx" #include "GuiUtils.hxx" +#include "Deserializer.hxx" +#include "Serializer.hxx" #include "bspf.hxx" #ifdef DEVELOPER_SUPPORT @@ -139,6 +141,8 @@ EventHandler::EventHandler(OSystem* osystem) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EventHandler::~EventHandler() { + stopRecording(); + if(myEvent) delete myEvent; @@ -524,6 +528,18 @@ void EventHandler::poll(uInt32 time) myOSystem->createConsole(); break; +// FIXME - these will be removed when a UI is added for event recording + case SDLK_e: // Ctrl-e starts/stops event recording + if(myEvent->isRecording()) + stopRecording(); + else + startRecording(); + break; + + case SDLK_l: // Ctrl-l loads a recording + loadRecording(); + break; +//////////////////////////////////////////////////////////////////////// case SDLK_END: // Ctrl-End increases Width myOSystem->console().changeWidth(1); break; @@ -1682,22 +1698,26 @@ inline bool EventHandler::eventIsAnalog(Event::Type event) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventHandler::saveState() { - // Do a state save using the System string md5 = myOSystem->console().properties().get("Cartridge.MD5"); ostringstream buf; buf << myOSystem->stateDir() << BSPF_PATH_SEPARATOR << md5 << ".st" << myLSState; - int result = myOSystem->console().system().saveState(buf.str(), md5); + // Make sure the file can be opened for writing + Serializer out; + if(!out.open(buf.str())) + { + myOSystem->frameBuffer().showMessage("Error saving state file"); + return; + } - // Print appropriate message + // Do a state save using the System buf.str(""); - if(result == 1) + if(myOSystem->console().system().saveState(md5, out)) buf << "State " << myLSState << " saved"; - else if(result == 2) - buf << "Error saving state " << myLSState; - else if(result == 3) + else buf << "Invalid state " << myLSState << " file"; + out.close(); myOSystem->frameBuffer().showMessage(buf.str()); } @@ -1723,22 +1743,28 @@ void EventHandler::changeState() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventHandler::loadState() { - // Do a state save using the System string md5 = myOSystem->console().properties().get("Cartridge.MD5"); ostringstream buf; buf << myOSystem->stateDir() << BSPF_PATH_SEPARATOR << md5 << ".st" << myLSState; - int result = myOSystem->console().system().loadState(buf.str(), md5); - - // Print appropriate message - buf.str(""); - if(result == 1) - buf << "State " << myLSState << " loaded"; - else if(result == 2) + // Make sure the file can be opened for reading + Deserializer in; + if(!in.open(buf.str())) + { + buf.str(""); buf << "Error loading state " << myLSState; - else if(result == 3) + 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()); } @@ -1806,6 +1832,50 @@ void EventHandler::takeSnapshot() #endif } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EventHandler::startRecording() +{ + if(myEvent->isRecording()) + return; + + string eventfile = /*myOSystem->baseDir() + BSPF_PATH_SEPARATOR +*/ "test.inp"; + myEventStream.close(); + if(!myEventStream.open(eventfile)) + { + myOSystem->frameBuffer().showMessage("Error opening eventstream"); + return; + } + + // And save the current state to it + string md5 = myOSystem->console().properties().get("Cartridge.MD5"); + myOSystem->console().system().saveState(md5, myEventStream); + + myEvent->record(true); + myOSystem->frameBuffer().showMessage("Recording started"); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EventHandler::stopRecording() +{ + if(!myEvent->isRecording()) + return; + + // Append the event history to the eventstream + myEvent->save(myEventStream); + + // And reset the state + myEvent->record(false); + myOSystem->frameBuffer().showMessage("Recording stopped"); + + myEventStream.close(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EventHandler::loadRecording() +{ +cerr << "load recording!\n"; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventHandler::setPaddleMode(uInt32 num, bool showmessage) { diff --git a/stella/src/emucore/EventHandler.hxx b/stella/src/emucore/EventHandler.hxx index 289f7b188..7fe1daa73 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.62 2005-12-08 19:01:38 stephena Exp $ +// $Id: EventHandler.hxx,v 1.63 2005-12-09 19:09:49 stephena Exp $ //============================================================================ #ifndef EVENTHANDLER_HXX @@ -26,6 +26,7 @@ #include "Array.hxx" #include "Control.hxx" #include "StringList.hxx" +#include "Serializer.hxx" class Console; class OSystem; @@ -90,7 +91,7 @@ struct Stella_Joystick { mapping can take place. @author Stephen Anthony - @version $Id: EventHandler.hxx,v 1.62 2005-12-08 19:01:38 stephena Exp $ + @version $Id: EventHandler.hxx,v 1.63 2005-12-09 19:09:49 stephena Exp $ */ class EventHandler { @@ -220,12 +221,27 @@ class EventHandler /** Save state to explicit state number (debugger uses this) */ - void saveState(int state); + void saveState(int state); /** Load state from explicit state number (debugger uses this) */ - void loadState(int state); + void loadState(int state); + + /** + Start recording event-stream to disk + */ + void startRecording(); + + /** + Stop recording event-stream + */ + void stopRecording(); + + /** + Load recorded event-stream into the system + */ + void loadRecording(); /** Sets the mouse to act as paddle 'num' @@ -403,6 +419,9 @@ class EventHandler // Indicates the current state of the system (ie, which mode is current) State myState; + // The serializer to use for saving eventstreams + Serializer myEventStream; + // Indicates current overlay object DialogContainer* myOverlay; diff --git a/stella/src/emucore/Serializer.cxx b/stella/src/emucore/Serializer.cxx index 8d63ab7af..c5644d12d 100644 --- a/stella/src/emucore/Serializer.cxx +++ b/stella/src/emucore/Serializer.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: Serializer.cxx,v 1.5 2005-06-16 01:11:28 stephena Exp $ +// $Id: Serializer.cxx,v 1.6 2005-12-09 19:09:49 stephena Exp $ //============================================================================ #include @@ -43,7 +43,7 @@ bool Serializer::open(const string& fileName) close(); myStream = new ofstream(fileName.c_str(), ios::out | ios::binary); - return (myStream && myStream->is_open()); + return isOpen(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -59,6 +59,12 @@ void Serializer::close(void) } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool Serializer::isOpen(void) +{ + return myStream && myStream->is_open(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Serializer::putLong(long value) { diff --git a/stella/src/emucore/Serializer.hxx b/stella/src/emucore/Serializer.hxx index c428acd04..530ca8237 100644 --- a/stella/src/emucore/Serializer.hxx +++ b/stella/src/emucore/Serializer.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: Serializer.hxx,v 1.7 2005-06-16 01:11:28 stephena Exp $ +// $Id: Serializer.hxx,v 1.8 2005-12-09 19:09:49 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.7 2005-06-16 01:11:28 stephena Exp $ + @version $Id: Serializer.hxx,v 1.8 2005-12-09 19:09:49 stephena Exp $ */ class Serializer { @@ -66,6 +66,11 @@ class Serializer */ void close(void); + /** + Answers whether the serializer is currently opened + */ + bool isOpen(void); + /** Writes a long value to the current output stream. diff --git a/stella/src/emucore/m6502/src/System.cxx b/stella/src/emucore/m6502/src/System.cxx index 76e53b8ab..c1e04814e 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.13 2005-07-09 23:44:08 urchlay Exp $ +// $Id: System.cxx,v 1.14 2005-12-09 19:09:49 stephena Exp $ //============================================================================ #include @@ -54,10 +54,6 @@ 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(); - // Bus starts out unlocked (in other words, peek() changes myDataBusState) myDataBusLocked = false; } @@ -76,12 +72,6 @@ System::~System() // Free my page access table delete[] myPageAccessTable; - - // Free the serializer stuff - if(serializer) - delete serializer; - if(deserializer) - delete deserializer; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -135,11 +125,9 @@ void System::attach(TIA* tia) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool System::save(Serializer& out) { - string name = "System"; - try { - out.putString(name); + out.putString("System"); out.putLong(myCycles); } catch(char *msg) @@ -149,7 +137,7 @@ bool System::save(Serializer& out) } catch(...) { - cerr << "Unknown error in save state for " << name << endl; + cerr << "Unknown error in save state for \'System\'" << endl; return false; } @@ -159,11 +147,9 @@ bool System::save(Serializer& out) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool System::load(Deserializer& in) { - string name = "System"; - try { - if(in.getString() != name) + if(in.getString() != "System") return false; myCycles = (uInt32) in.getLong(); @@ -175,7 +161,7 @@ bool System::load(Deserializer& in) } catch(...) { - cerr << "Unknown error in load state for " << name << endl; + cerr << "Unknown error in load state for \'System\'" << endl; return false; } @@ -217,91 +203,58 @@ const System::PageAccess& System::getPageAccess(uInt16 page) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int System::saveState(const string& fileName, const string& md5sum) +bool System::saveState(const string& md5sum, Serializer& out) { // Open the file as a new Serializer - if(!serializer->open(fileName)) - { - serializer->close(); - return 2; - } + if(!out.isOpen()) + return false; // Prepend the state file with the md5sum of this cartridge // This is the first defensive check for an invalid state file - serializer->putString(md5sum); + out.putString(md5sum); // First save state for this system - if(!save(*serializer)) - { - serializer->close(); - return 3; - } + if(!save(out)) + return false; // Next, save state for the CPU - if(!myM6502->save(*serializer)) - { - serializer->close(); - return 3; - } + if(!myM6502->save(out)) + return false; // Now save the state of each device for(uInt32 i = 0; i < myNumberOfDevices; ++i) - { - if(!myDevices[i]->save(*serializer)) - { - serializer->close(); - return 3; - } - } + if(!myDevices[i]->save(out)) + return false; - serializer->close(); - return 1; // success + return true; // success } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int System::loadState(const string &fileName, const string& md5sum) +bool System::loadState(const string& md5sum, Deserializer& in) { // Open the file as a new Deserializer - if(!deserializer->open(fileName)) - { - deserializer->close(); - return 2; - } + if(!in.isOpen()) + return false; // 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; - } + if(in.getString() != md5sum) + return false; // First load state for this system - if(!load(*deserializer)) - { - deserializer->close(); - return 3; - } + if(!load(in)) + return false; // Next, load state for the CPU - if(!myM6502->load(*deserializer)) - { - deserializer->close(); - return 3; - } + if(!myM6502->load(in)) + return false; // Now load the state of each device for(uInt32 i = 0; i < myNumberOfDevices; ++i) - { - if(!myDevices[i]->load(*deserializer)) - { - deserializer->close(); - return 3; - } - } + if(!myDevices[i]->load(in)) + return false; - deserializer->close(); - return 1; // success + return true; // success } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/emucore/m6502/src/System.hxx b/stella/src/emucore/m6502/src/System.hxx index 0db0480dc..d9193a3cb 100644 --- a/stella/src/emucore/m6502/src/System.hxx +++ b/stella/src/emucore/m6502/src/System.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: System.hxx,v 1.11 2005-08-24 22:54:30 stephena Exp $ +// $Id: System.hxx,v 1.12 2005-12-09 19:09:49 stephena Exp $ //============================================================================ #ifndef SYSTEM_HXX @@ -47,7 +47,7 @@ class Deserializer; dynamic code for that page of memory. @author Bradford W. Mott - @version $Id: System.hxx,v 1.11 2005-08-24 22:54:30 stephena Exp $ + @version $Id: System.hxx,v 1.12 2005-12-09 19:09:49 stephena Exp $ */ class System { @@ -118,25 +118,23 @@ class System 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 + @param md5sum MD5 of the current ROM + @param out The serializer device to save to + + @return False on any errors, else true */ - int saveState(const string& fileName, const string& md5sum); + bool saveState(const string& md5sum, Serializer& out); /** 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 + @param md5sum MD5 of the current ROM + @param in The deserializer device to load from + + @return False on any errors, else true */ - int loadState(const string& fileName, const string& md5sum); + bool loadState(const string& md5sum, Deserializer& in); public: /** @@ -359,12 +357,6 @@ class System // debugger is active. bool myDataBusLocked; - // 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&);