From 1f426d245f46c23f66456aef37c055752ed4ac6e Mon Sep 17 00:00:00 2001 From: stephena Date: Wed, 28 Dec 2005 22:56:36 +0000 Subject: [PATCH] Some changes wrt to event recordings. Created EventStreamer class to deal with all related event recording/loading stuff, since it really didn't belong in either the EventHandler or Event classes. Loading a previously saved eventstream now loads the ROM state as well. All that's left to do (for basic functionality) is for the EventHandler to poll the EventStreamer for events, and then pass them directly to the Event class. Still TODO is decide on a GUI for all this, and what it means to 'interrupt' an eventstream (should we just stop the load, delay processing of it, lock out all user input until the stream is finished, etc). git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@931 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- stella/src/emucore/Event.cxx | 55 ++---------- stella/src/emucore/Event.hxx | 47 ++-------- stella/src/emucore/EventHandler.cxx | 109 ++++++++--------------- stella/src/emucore/EventHandler.hxx | 49 +++-------- stella/src/emucore/EventStreamer.cxx | 124 +++++++++++++++++++++++++++ stella/src/emucore/EventStreamer.hxx | 114 ++++++++++++++++++++++++ stella/src/emucore/module.mk | 1 + 7 files changed, 302 insertions(+), 197 deletions(-) create mode 100644 stella/src/emucore/EventStreamer.cxx create mode 100644 stella/src/emucore/EventStreamer.hxx diff --git a/stella/src/emucore/Event.cxx b/stella/src/emucore/Event.cxx index d8973f069..61c297f43 100644 --- a/stella/src/emucore/Event.cxx +++ b/stella/src/emucore/Event.cxx @@ -13,16 +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.6 2005-12-17 01:23:07 stephena Exp $ +// $Id: Event.cxx,v 1.7 2005-12-28 22:56:36 stephena Exp $ //============================================================================ #include "Event.hxx" -#include "Serializer.hxx" +#include "EventStreamer.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Event::Event() +Event::Event(EventStreamer* ev) : myNumberOfTypes(Event::LastType), - myEventRecordFlag(false) + myEventStreamer(ev) { // Set all of the events to 0 / false to start with clear(); @@ -31,7 +31,6 @@ Event::Event() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Event::~Event() { - myEventHistory.clear(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -46,55 +45,13 @@ void Event::set(Type type, Int32 value) myValues[type] = value; // Add to history if we're in recording mode - if(myEventRecordFlag) - { - myEventHistory.push_back(type); - myEventHistory.push_back(value); - } + if(myEventStreamer->isRecording()) + myEventStreamer->addEvent(type, value); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Event::clear() { for(int i = 0; i < myNumberOfTypes; ++i) - { myValues[i] = 0; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Event::record(bool enable) -{ - if(myEventRecordFlag == enable) - return; - else - myEventRecordFlag = enable; - - if(myEventRecordFlag) - myEventHistory.clear(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Event::nextFrame() -{ - if(myEventRecordFlag) - { - int idx = myEventHistory.size() - 1; - if(idx >= 0 && myEventHistory[idx] < 0) - --myEventHistory[idx]; - else - myEventHistory.push_back(-1); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Event::save(Serializer& out) -{ - int size = myEventHistory.size(); - out.putString("EventStream"); - out.putInt(size); - for(int i = 0; i < size; ++i) - out.putInt(myEventHistory[i]); - - return true; } diff --git a/stella/src/emucore/Event.hxx b/stella/src/emucore/Event.hxx index 88e9776c6..d0756e9e9 100644 --- a/stella/src/emucore/Event.hxx +++ b/stella/src/emucore/Event.hxx @@ -13,21 +13,20 @@ // 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.17 2005-12-17 22:48:24 stephena Exp $ +// $Id: Event.hxx,v 1.18 2005-12-28 22:56:36 stephena Exp $ //============================================================================ #ifndef EVENT_HXX #define EVENT_HXX -class Event; -class Serializer; - -#include "Array.hxx" #include "bspf.hxx" +class Event; +class EventStreamer; + /** @author Bradford W. Mott - @version $Id: Event.hxx,v 1.17 2005-12-17 22:48:24 stephena Exp $ + @version $Id: Event.hxx,v 1.18 2005-12-28 22:56:36 stephena Exp $ */ class Event { @@ -85,9 +84,9 @@ class Event public: /** - Create a new event object + Create a new event object and use the given eventstreamer */ - Event(); + Event(EventStreamer* ev); /** Destructor @@ -110,31 +109,6 @@ class Event */ virtual void clear(); - /** - Start/stop recording events to the event history - - @param enable Start or stop recording - */ - virtual void record(bool enable); - - /** - Indicate that a new frame has been processed - */ - 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; @@ -142,11 +116,8 @@ class Event // Array of values associated with each event type Int32 myValues[LastType]; - // Indicates if we're in recording mode - bool myEventRecordFlag; - - // Stores the history/record of all events that have been set - IntArray myEventHistory; + // The eventstreamer to record events to + EventStreamer* myEventStreamer; }; #endif diff --git a/stella/src/emucore/EventHandler.cxx b/stella/src/emucore/EventHandler.cxx index 6a41cc56f..e3012c534 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.134 2005-12-24 22:09:36 stephena Exp $ +// $Id: EventHandler.cxx,v 1.135 2005-12-28 22:56:36 stephena Exp $ //============================================================================ #include @@ -21,6 +21,7 @@ #include "Event.hxx" #include "EventHandler.hxx" +#include "EventStreamer.hxx" #include "FSNode.hxx" #include "Settings.hxx" #include "System.hxx" @@ -59,24 +60,27 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EventHandler::EventHandler(OSystem* osystem) : myOSystem(osystem), - myState(S_NONE), + myEvent(NULL), + myEventStreamer(NULL), myOverlay(NULL), + myState(S_NONE), myLSState(0), myPauseFlag(false), myQuitFlag(false), myGrabMouseFlag(false), myUseLauncherFlag(false), - myEmulateMouseFlag(false), - myPaddleMode(0), - myMouseMove(3) + myPaddleMode(0) { int i, j; // Add this eventhandler object to the OSystem myOSystem->attach(this); + // 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(); + myEvent = new Event(myEventStreamer); // Erase the key mapping array for(i = 0; i < SDLK_LAST; ++i) @@ -121,7 +125,6 @@ EventHandler::EventHandler(OSystem* osystem) setActionMappings(); myGrabMouseFlag = myOSystem->settings().getBool("grabmouse"); - myEmulateMouseFlag = myOSystem->settings().getBool("joymouse"); setPaddleMode(myOSystem->settings().getInt("paddle"), false); @@ -131,10 +134,8 @@ EventHandler::EventHandler(OSystem* osystem) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EventHandler::~EventHandler() { - stopRecording(); - - if(myEvent) - delete myEvent; + delete myEvent; + delete myEventStreamer; #ifdef JOYSTICK_SUPPORT if(SDL_WasInit(SDL_INIT_JOYSTICK) & SDL_INIT_JOYSTICK) @@ -148,12 +149,6 @@ EventHandler::~EventHandler() #endif } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Event* EventHandler::event() -{ - return myEvent; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventHandler::reset(State state) { @@ -445,6 +440,27 @@ void EventHandler::poll(uInt32 time) case SDLK_s: // Alt-s merges properties into user properties (user.pro) saveProperties(); break; + +// FIXME - these will be removed when a UI is added for event recording + case SDLK_e: // Alt-e starts/stops event recording + if(myEventStreamer->isRecording()) + { + if(myEventStreamer->stopRecording()) + myOSystem->frameBuffer().showMessage("Recording stopped"); + } + else + { + if(myEventStreamer->startRecording()) + myOSystem->frameBuffer().showMessage("Recording started"); + else + myOSystem->frameBuffer().showMessage("Error opening eventstream"); + } + break; + + case SDLK_l: // Alt-l loads a recording + myEventStreamer->loadRecording(); + break; +//////////////////////////////////////////////////////////////////////// } } } @@ -520,18 +536,6 @@ 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; @@ -772,9 +776,9 @@ void EventHandler::poll(uInt32 time) cheats[i]->evaluate(); #endif - // Tell the event object that another frame has finished + // Tell the eventstreamer that another frame has finished // This is used for event recording - myEvent->nextFrame(); + myEventStreamer->nextFrame(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1677,49 +1681,6 @@ void EventHandler::takeSnapshot() #endif } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void EventHandler::startRecording() -{ - if(myEvent->isRecording()) - return; - - string eventfile = /*myOSystem->baseDir() + BSPF_PATH_SEPARATOR +*/ "test.inp"; - 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(int num, bool showmessage) { diff --git a/stella/src/emucore/EventHandler.hxx b/stella/src/emucore/EventHandler.hxx index 35b877045..221924f41 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.69 2005-12-24 22:09:36 stephena Exp $ +// $Id: EventHandler.hxx,v 1.70 2005-12-28 22:56:36 stephena Exp $ //============================================================================ #ifndef EVENTHANDLER_HXX @@ -32,6 +32,7 @@ class Console; class OSystem; class DialogContainer; class EventMappingWidget; +class EventStreamer; enum MouseButton { EVENT_LBUTTONDOWN, @@ -100,7 +101,7 @@ struct JoyMouse { mapping can take place. @author Stephen Anthony - @version $Id: EventHandler.hxx,v 1.69 2005-12-24 22:09:36 stephena Exp $ + @version $Id: EventHandler.hxx,v 1.70 2005-12-28 22:56:36 stephena Exp $ */ class EventHandler { @@ -125,7 +126,7 @@ class EventHandler @return The event object */ - Event* event(); + Event* event() { return myEvent; } /** Set up any joysticks on the system. This must be called *after* the @@ -239,21 +240,6 @@ class EventHandler */ 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 +389,15 @@ class EventHandler // Global OSystem object OSystem* myOSystem; + // Global Event object + Event* myEvent; + + // The EventStreamer to use for loading/saving eventstreams + EventStreamer* myEventStreamer; + + // Indicates current overlay object + DialogContainer* myOverlay; + // Array of key events, indexed by SDLKey Event::Type myKeyTable[SDLK_LAST]; @@ -427,15 +422,6 @@ 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; - - // Global Event object - Event* myEvent; - // Indicates the current state to use for state loading/saving uInt32 myLSState; @@ -460,18 +446,9 @@ class EventHandler // Indicates which paddle the mouse currently emulates Int8 myPaddleMode; - // The current keymap in string form - string myKeymapString; - - // The current joymap in string form - string myJoymapString; - // Used for paddle emulation by keyboard or joystick JoyMouse myPaddle[4]; - // How far the joystick will move the mouse on each frame tick - int myMouseMove; - // Type of device on each controller port (based on ROM properties) Controller::Type myController[2]; diff --git a/stella/src/emucore/EventStreamer.cxx b/stella/src/emucore/EventStreamer.cxx new file mode 100644 index 000000000..a325f4e39 --- /dev/null +++ b/stella/src/emucore/EventStreamer.cxx @@ -0,0 +1,124 @@ +//============================================================================ +// +// 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-2005 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.1 2005-12-28 22:56:36 stephena Exp $ +//============================================================================ + +#include "bspf.hxx" + +#include "OSystem.hxx" +#include "Event.hxx" +#include "EventHandler.hxx" +#include "EventStreamer.hxx" +#include "System.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +EventStreamer::EventStreamer(OSystem* osystem) + : myOSystem(osystem), + myEventRecordFlag(false) +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +EventStreamer::~EventStreamer() +{ + stopRecording(); + + myEventHistory.clear(); + myStreamReader.close(); + myStreamWriter.close(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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"); + myOSystem->console().system().saveState(md5, myStreamWriter); + myEventHistory.clear(); + + return myEventRecordFlag = true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool EventStreamer::stopRecording() +{ + if(!myStreamWriter.isOpen() || !myEventRecordFlag) + return false; + + // Append the event history to the eventstream + int size = myEventHistory.size(); + myStreamWriter.putString("EventStream"); + myStreamWriter.putInt(size); + for(int i = 0; i < size; ++i) + myStreamWriter.putInt(myEventHistory[i]); + + 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"); + myOSystem->console().system().loadState(md5, myStreamReader); + + 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()); + +cerr << "event queue contains " << myEventHistory.size() << " items\n"; + + return myEventRecordFlag = false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EventStreamer::addEvent(int type, int value) +{ + if(myEventRecordFlag) + { + myEventHistory.push_back(type); + myEventHistory.push_back(value); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EventStreamer::nextFrame() +{ + if(myEventRecordFlag) + { + 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 new file mode 100644 index 000000000..ac7097cc1 --- /dev/null +++ b/stella/src/emucore/EventStreamer.hxx @@ -0,0 +1,114 @@ +//============================================================================ +// +// 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-2005 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.1 2005-12-28 22:56:36 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.1 2005-12-28 22:56:36 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); + + /** + Answers if we're in recording mode + */ + bool isRecording() { return myEventRecordFlag; } + + /** + Indicate that a new frame has been processed + */ + void nextFrame(); + + private: + + private: + // Global OSystem object + OSystem* myOSystem; + + // Indicates if we're in recording mode + bool myEventRecordFlag; + + // Serializer classes used to save/load the eventstream + Serializer myStreamWriter; + Deserializer myStreamReader; + + // Stores the history/record of all events that have been set + IntArray myEventHistory; +}; + +#endif diff --git a/stella/src/emucore/module.mk b/stella/src/emucore/module.mk index c58e9fe78..0bc218869 100644 --- a/stella/src/emucore/module.mk +++ b/stella/src/emucore/module.mk @@ -29,6 +29,7 @@ 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 \