From a4029a8e94a3dbbe03c0aa4571215e9a5b00058d Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Mon, 8 Aug 2011 15:38:27 +0100 Subject: [PATCH] RECORDER: Restore event recorder functionality. It was badly broken after refactoring into EventObserver. Fitst, deinit() method was never called which lead to bad record files. Then, the concept of counting pollEvent() calls was ignored. Introduced dispatchPoll() method of EventObserver which is implemented in EventRecorder. It counts calls so is able to inject events at more proper time. Additionally now event times are recorded. --- base/main.cpp | 4 +++ common/EventDispatcher.cpp | 13 +++++++- common/EventRecorder.cpp | 67 ++++++++++++++++++++++++++++---------- common/EventRecorder.h | 2 ++ common/events.h | 15 ++++++++- 5 files changed, 81 insertions(+), 20 deletions(-) diff --git a/base/main.cpp b/base/main.cpp index 717ccb33443..780015d307d 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -419,6 +419,10 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) { // Try to run the game Common::Error result = runGame(plugin, system, specialDebug); + // Flush Event recorder file. The recorder does not get reinitialized for next game + // which is intentional. Only single game per session is allowed. + g_eventRec.deinit(); + #if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) // do our best to prevent fragmentation by unloading as soon as we can PluginManager::instance().unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false); diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp index ce1ef0c1c86..4e3f671cfd7 100644 --- a/common/EventDispatcher.cpp +++ b/common/EventDispatcher.cpp @@ -45,6 +45,8 @@ EventDispatcher::~EventDispatcher() { void EventDispatcher::dispatch() { Event event; + dispatchPoll(); + for (List::iterator i = _sources.begin(); i != _sources.end(); ++i) { const bool allowMapping = i->source->allowMapping(); @@ -94,12 +96,13 @@ void EventDispatcher::unregisterSource(EventSource *source) { } } -void EventDispatcher::registerObserver(EventObserver *obs, uint priority, bool autoFree) { +void EventDispatcher::registerObserver(EventObserver *obs, uint priority, bool autoFree, bool notifyPoll) { ObserverEntry newEntry; newEntry.observer = obs; newEntry.priority = priority; newEntry.autoFree = autoFree; + newEntry.poll = notifyPoll; for (List::iterator i = _observers.begin(); i != _observers.end(); ++i) { if (i->priority < priority) { @@ -130,4 +133,12 @@ void EventDispatcher::dispatchEvent(const Event &event) { } } +void EventDispatcher::dispatchPoll() { + for (List::iterator i = _observers.begin(); i != _observers.end(); ++i) { + if (i->poll == true) + if (i->observer->notifyPoll()) + break; + } +} + } // End of namespace Common diff --git a/common/EventRecorder.cpp b/common/EventRecorder.cpp index f5d8641bd38..4be3ca41ec8 100644 --- a/common/EventRecorder.cpp +++ b/common/EventRecorder.cpp @@ -34,7 +34,28 @@ DECLARE_SINGLETON(EventRecorder); #define RECORD_SIGNATURE 0x54455354 #define RECORD_VERSION 1 -void readRecord(SeekableReadStream *inFile, uint32 &diff, Event &event) { +uint32 readTime(ReadStream *inFile) { + uint32 d = inFile->readByte(); + if (d == 0xff) { + d = inFile->readUint32LE(); + } + + return d; +} + +void writeTime(WriteStream *outFile, uint32 d) { + //Simple RLE compression + if (d >= 0xff) { + outFile->writeByte(0xff); + outFile->writeUint32LE(d); + } else { + outFile->writeByte(d); + } +} + +void readRecord(SeekableReadStream *inFile, uint32 &diff, Event &event, uint32 &millis) { + millis = readTime(inFile); + diff = inFile->readUint32LE(); event.type = (EventType)inFile->readUint32LE(); @@ -61,7 +82,9 @@ void readRecord(SeekableReadStream *inFile, uint32 &diff, Event &event) { } } -void writeRecord(WriteStream *outFile, uint32 diff, const Event &event) { +void writeRecord(WriteStream *outFile, uint32 diff, const Event &event, uint32 millis) { + writeTime(outFile, millis); + outFile->writeUint32LE(diff); outFile->writeUint32LE((uint32)event.type); @@ -99,6 +122,7 @@ EventRecorder::EventRecorder() { _eventCount = 0; _lastEventCount = 0; _lastMillis = 0; + _lastEventMillis = 0; _recordMode = kPassthrough; } @@ -177,6 +201,7 @@ void EventRecorder::init() { _recordCount = _playbackFile->readUint32LE(); _recordTimeCount = _playbackFile->readUint32LE(); + randomSourceCount = _playbackFile->readUint32LE(); for (uint i = 0; i < randomSourceCount; ++i) { RandomSourceRecord rec; @@ -194,7 +219,7 @@ void EventRecorder::init() { } g_system->getEventManager()->getEventDispatcher()->registerSource(this, false); - g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 1, false); + g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 1, false, true); } void EventRecorder::deinit() { @@ -242,8 +267,9 @@ void EventRecorder::deinit() { for (uint i = 0; i < _recordCount; ++i) { uint32 tempDiff; Event tempEvent; - readRecord(_playbackFile, tempDiff, tempEvent); - writeRecord(_recordFile, tempDiff, tempEvent); + uint32 millis; + readRecord(_playbackFile, tempDiff, tempEvent, millis); + writeRecord(_recordFile, tempDiff, tempEvent, millis); } _recordFile->finalize(); @@ -284,23 +310,16 @@ void EventRecorder::processMillis(uint32 &millis) { g_system->lockMutex(_timeMutex); if (_recordMode == kRecorderRecord) { - //Simple RLE compression d = millis - _lastMillis; - if (d >= 0xff) { - _recordTimeFile->writeByte(0xff); - _recordTimeFile->writeUint32LE(d); - } else { - _recordTimeFile->writeByte(d); - } + writeTime(_recordTimeFile, d); + _recordTimeCount++; } if (_recordMode == kRecorderPlayback) { if (_recordTimeCount > _playbackTimeCount) { - d = _playbackTimeFile->readByte(); - if (d == 0xff) { - d = _playbackTimeFile->readUint32LE(); - } + d = readTime(_playbackTimeFile); + millis = _lastMillis + d; _playbackTimeCount++; } @@ -321,15 +340,27 @@ bool EventRecorder::notifyEvent(const Event &ev) { StackLock lock(_recorderMutex); ++_eventCount; - writeRecord(_recordFile, _eventCount - _lastEventCount, ev); + writeRecord(_recordFile, _eventCount - _lastEventCount, ev, _lastMillis - _lastEventMillis); _recordCount++; _lastEventCount = _eventCount; + _lastEventMillis = _lastMillis; + + return false; +} + +bool EventRecorder::notifyPoll() { + if (_recordMode != kRecorderRecord) + return false; + + ++_eventCount; return false; } bool EventRecorder::pollEvent(Event &ev) { + uint32 millis; + if (_recordMode != kRecorderPlayback) return false; @@ -338,7 +369,7 @@ bool EventRecorder::pollEvent(Event &ev) { if (!_hasPlaybackEvent) { if (_recordCount > _playbackCount) { - readRecord(_playbackFile, const_cast(_playbackDiff), _playbackEvent); + readRecord(_playbackFile, const_cast(_playbackDiff), _playbackEvent, millis); _playbackCount++; _hasPlaybackEvent = true; } diff --git a/common/EventRecorder.h b/common/EventRecorder.h index e20419695af..43a08b08cd7 100644 --- a/common/EventRecorder.h +++ b/common/EventRecorder.h @@ -61,6 +61,7 @@ public: private: bool notifyEvent(const Event &ev); + bool notifyPoll(); bool pollEvent(Event &ev); bool allowMapping() const { return false; } @@ -75,6 +76,7 @@ private: volatile uint32 _recordCount; volatile uint32 _lastRecordEvent; volatile uint32 _recordTimeCount; + volatile uint32 _lastEventMillis; WriteStream *_recordFile; WriteStream *_recordTimeFile; MutexRef _timeMutex; diff --git a/common/events.h b/common/events.h index 7df27316872..d48060f314b 100644 --- a/common/events.h +++ b/common/events.h @@ -184,6 +184,14 @@ public: * false otherwise. */ virtual bool notifyEvent(const Event &event) = 0; + + /** + * Notifies the observer of pollEvent() query. + * + * @return true if the event should not be passed to other observers, + * false otherwise. + */ + virtual bool notifyPoll() { return false; } }; /** @@ -255,8 +263,11 @@ public: /** * Registers a new EventObserver with the Dispatcher. + * + * @param listenPools if set, then all pollEvent() calls are passed to observer + * currently it is used by keyMapper */ - void registerObserver(EventObserver *obs, uint priority, bool autoFree); + void registerObserver(EventObserver *obs, uint priority, bool autoFree, bool listenPolls = false); /** * Unregisters a EventObserver. @@ -280,11 +291,13 @@ private: struct ObserverEntry : public Entry { uint priority; EventObserver *observer; + bool poll; }; List _observers; void dispatchEvent(const Event &event); + void dispatchPoll(); }; class Keymapper;