diff options
Diffstat (limited to 'common')
129 files changed, 2589 insertions, 988 deletions
diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp index 012a2dfce5..2650d795b7 100644 --- a/common/EventDispatcher.cpp +++ b/common/EventDispatcher.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -24,7 +24,7 @@ namespace Common { -EventDispatcher::EventDispatcher() : _mapper(0) { +EventDispatcher::EventDispatcher() : _autoFreeMapper(false), _mapper(0) { } EventDispatcher::~EventDispatcher() { @@ -38,7 +38,9 @@ EventDispatcher::~EventDispatcher() { delete i->observer; } - delete _mapper; + if (_autoFreeMapper) { + delete _mapper; + } _mapper = 0; } @@ -68,11 +70,15 @@ void EventDispatcher::dispatch() { } } -void EventDispatcher::registerMapper(EventMapper *mapper) { - delete _mapper; +void EventDispatcher::registerMapper(EventMapper *mapper, bool autoFree) { + if (_autoFreeMapper) { + delete _mapper; + } _mapper = mapper; + _autoFreeMapper = autoFree; } + void EventDispatcher::registerSource(EventSource *source, bool autoFree) { SourceEntry newEntry; diff --git a/common/EventMapper.cpp b/common/EventMapper.cpp index 5f6771a71d..cf65946d50 100644 --- a/common/EventMapper.cpp +++ b/common/EventMapper.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -30,18 +30,46 @@ namespace Common { List<Event> DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) { List<Event> events; Event mappedEvent; +#ifdef ENABLE_VKEYBD + // Trigger virtual keyboard on long press of more than 1 second + // of middle mouse button. + const uint32 vkeybdTime = 1000; + + static bool vkeybd = false; + static uint32 vkeybdThen = 0; + + if (ev.type == EVENT_MBUTTONDOWN) { + vkeybdThen = g_system->getMillis(); + } + + if (ev.type == EVENT_MBUTTONUP) { + if ((g_system->getMillis() - vkeybdThen) >= vkeybdTime) { + mappedEvent.type = EVENT_VIRTUAL_KEYBOARD; + + // Avoid blocking event from engine. + addDelayedEvent(100, ev); + } + } +#endif + if (ev.type == EVENT_KEYDOWN) { if (ev.kbd.hasFlags(KBD_CTRL) && ev.kbd.keycode == KEYCODE_F5) { mappedEvent.type = EVENT_MAINMENU; } #ifdef ENABLE_VKEYBD - else if (ev.kbd.keycode == KEYCODE_F7 && ev.kbd.hasFlags(0)) { + else if (ev.kbd.hasFlags(KBD_CTRL) && ev.kbd.keycode == KEYCODE_F7) { mappedEvent.type = EVENT_VIRTUAL_KEYBOARD; + + // Avoid blocking CTRL-F7 events from engine. + addDelayedEvent(100, ev); } #endif #ifdef ENABLE_KEYMAPPER - else if (ev.kbd.keycode == KEYCODE_F8 && ev.kbd.hasFlags(0)) { + else if (ev.kbd.hasFlags(KBD_CTRL) && ev.kbd.keycode == KEYCODE_F8) { mappedEvent.type = EVENT_KEYMAPPER_REMAP; + + // Avoid blocking CTRL-F8 events from engine. + addDelayedEvent(100, ev); } #endif } diff --git a/common/EventRecorder.cpp b/common/EventRecorder.cpp deleted file mode 100644 index 5e24f128c3..0000000000 --- a/common/EventRecorder.cpp +++ /dev/null @@ -1,428 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/EventRecorder.h" - -#include "common/bufferedstream.h" -#include "common/config-manager.h" -#include "common/random.h" -#include "common/savefile.h" -#include "common/textconsole.h" - -namespace Common { - -DECLARE_SINGLETON(EventRecorder); - -#define RECORD_SIGNATURE 0x54455354 -#define RECORD_VERSION 1 - -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(); - - switch (event.type) { - case EVENT_KEYDOWN: - case EVENT_KEYUP: - event.kbd.keycode = (KeyCode)inFile->readSint32LE(); - event.kbd.ascii = inFile->readUint16LE(); - event.kbd.flags = inFile->readByte(); - break; - case EVENT_MOUSEMOVE: - case EVENT_LBUTTONDOWN: - case EVENT_LBUTTONUP: - case EVENT_RBUTTONDOWN: - case EVENT_RBUTTONUP: - case EVENT_WHEELUP: - case EVENT_WHEELDOWN: - case EVENT_MBUTTONDOWN: - case EVENT_MBUTTONUP: - event.mouse.x = inFile->readSint16LE(); - event.mouse.y = inFile->readSint16LE(); - break; - default: - break; - } -} - -void writeRecord(WriteStream *outFile, uint32 diff, const Event &event, uint32 millis) { - writeTime(outFile, millis); - - outFile->writeUint32LE(diff); - - outFile->writeUint32LE((uint32)event.type); - - switch (event.type) { - case EVENT_KEYDOWN: - case EVENT_KEYUP: - outFile->writeSint32LE(event.kbd.keycode); - outFile->writeUint16LE(event.kbd.ascii); - outFile->writeByte(event.kbd.flags); - break; - case EVENT_MOUSEMOVE: - case EVENT_LBUTTONDOWN: - case EVENT_LBUTTONUP: - case EVENT_RBUTTONDOWN: - case EVENT_RBUTTONUP: - case EVENT_WHEELUP: - case EVENT_WHEELDOWN: - case EVENT_MBUTTONDOWN: - case EVENT_MBUTTONUP: - outFile->writeSint16LE(event.mouse.x); - outFile->writeSint16LE(event.mouse.y); - break; - default: - break; - } -} - -EventRecorder::EventRecorder() { - _recordFile = NULL; - _recordTimeFile = NULL; - _playbackFile = NULL; - _playbackTimeFile = NULL; - _timeMutex = g_system->createMutex(); - _recorderMutex = g_system->createMutex(); - - _eventCount = 0; - _lastEventCount = 0; - _lastMillis = 0; - _lastEventMillis = 0; - - _recordMode = kPassthrough; -} - -EventRecorder::~EventRecorder() { - deinit(); - - g_system->deleteMutex(_timeMutex); - g_system->deleteMutex(_recorderMutex); -} - -void EventRecorder::init() { - String recordModeString = ConfMan.get("record_mode"); - if (recordModeString.compareToIgnoreCase("record") == 0) { - _recordMode = kRecorderRecord; - - debug(3, "EventRecorder: record"); - } else { - if (recordModeString.compareToIgnoreCase("playback") == 0) { - _recordMode = kRecorderPlayback; - debug(3, "EventRecorder: playback"); - } else { - _recordMode = kPassthrough; - debug(3, "EventRecorder: passthrough"); - } - } - - _recordFileName = ConfMan.get("record_file_name"); - if (_recordFileName.empty()) { - _recordFileName = "record.bin"; - } - _recordTempFileName = ConfMan.get("record_temp_file_name"); - if (_recordTempFileName.empty()) { - _recordTempFileName = "record.tmp"; - } - _recordTimeFileName = ConfMan.get("record_time_file_name"); - if (_recordTimeFileName.empty()) { - _recordTimeFileName = "record.time"; - } - - // recorder stuff - if (_recordMode == kRecorderRecord) { - _recordCount = 0; - _recordTimeCount = 0; - _recordFile = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving(_recordTempFileName), 128 * 1024); - _recordTimeFile = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving(_recordTimeFileName), 128 * 1024); - _recordSubtitles = ConfMan.getBool("subtitles"); - } - - uint32 sign; - uint32 randomSourceCount; - if (_recordMode == kRecorderPlayback) { - _playbackCount = 0; - _playbackTimeCount = 0; - _playbackFile = wrapBufferedSeekableReadStream(g_system->getSavefileManager()->openForLoading(_recordFileName), 128 * 1024, DisposeAfterUse::YES); - _playbackTimeFile = wrapBufferedSeekableReadStream(g_system->getSavefileManager()->openForLoading(_recordTimeFileName), 128 * 1024, DisposeAfterUse::YES); - - if (!_playbackFile) { - warning("Cannot open playback file %s. Playback was switched off", _recordFileName.c_str()); - _recordMode = kPassthrough; - } - - if (!_playbackTimeFile) { - warning("Cannot open playback time file %s. Playback was switched off", _recordTimeFileName.c_str()); - _recordMode = kPassthrough; - } - } - - if (_recordMode == kRecorderPlayback) { - sign = _playbackFile->readUint32LE(); - if (sign != RECORD_SIGNATURE) { - error("Unknown record file signature"); - } - - _playbackFile->readUint32LE(); // version - - // conf vars - ConfMan.setBool("subtitles", _playbackFile->readByte() != 0); - - _recordCount = _playbackFile->readUint32LE(); - _recordTimeCount = _playbackFile->readUint32LE(); - - randomSourceCount = _playbackFile->readUint32LE(); - for (uint i = 0; i < randomSourceCount; ++i) { - RandomSourceRecord rec; - rec.name = ""; - uint32 sLen = _playbackFile->readUint32LE(); - for (uint j = 0; j < sLen; ++j) { - char c = _playbackFile->readSByte(); - rec.name += c; - } - rec.seed = _playbackFile->readUint32LE(); - _randomSourceRecords.push_back(rec); - } - - _hasPlaybackEvent = false; - } - - g_system->getEventManager()->getEventDispatcher()->registerSource(this, false); - g_system->getEventManager()->getEventDispatcher()->registerObserver(this, EventManager::kEventRecorderPriority, false, true); -} - -void EventRecorder::deinit() { - debug(3, "EventRecorder: deinit"); - - g_system->getEventManager()->getEventDispatcher()->unregisterSource(this); - g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); - - g_system->lockMutex(_timeMutex); - g_system->lockMutex(_recorderMutex); - _recordMode = kPassthrough; - g_system->unlockMutex(_timeMutex); - g_system->unlockMutex(_recorderMutex); - - delete _playbackFile; - delete _playbackTimeFile; - - if (_recordFile != NULL) { - _recordFile->finalize(); - delete _recordFile; - _recordTimeFile->finalize(); - delete _recordTimeFile; - - _playbackFile = g_system->getSavefileManager()->openForLoading(_recordTempFileName); - - assert(_playbackFile); - - _recordFile = g_system->getSavefileManager()->openForSaving(_recordFileName); - _recordFile->writeUint32LE(RECORD_SIGNATURE); - _recordFile->writeUint32LE(RECORD_VERSION); - - // conf vars - _recordFile->writeByte(_recordSubtitles ? 1 : 0); - - _recordFile->writeUint32LE(_recordCount); - _recordFile->writeUint32LE(_recordTimeCount); - - _recordFile->writeUint32LE(_randomSourceRecords.size()); - for (uint i = 0; i < _randomSourceRecords.size(); ++i) { - _recordFile->writeUint32LE(_randomSourceRecords[i].name.size()); - _recordFile->writeString(_randomSourceRecords[i].name); - _recordFile->writeUint32LE(_randomSourceRecords[i].seed); - } - - for (uint i = 0; i < _recordCount; ++i) { - uint32 tempDiff; - Event tempEvent; - uint32 millis; - readRecord(_playbackFile, tempDiff, tempEvent, millis); - writeRecord(_recordFile, tempDiff, tempEvent, millis); - } - - _recordFile->finalize(); - delete _recordFile; - delete _playbackFile; - - //TODO: remove recordTempFileName'ed file - } -} - -void EventRecorder::registerRandomSource(RandomSource &rnd, const String &name) { - if (_recordMode == kRecorderRecord) { - RandomSourceRecord rec; - rec.name = name; - rec.seed = rnd.getSeed(); - _randomSourceRecords.push_back(rec); - } - - if (_recordMode == kRecorderPlayback) { - for (uint i = 0; i < _randomSourceRecords.size(); ++i) { - if (_randomSourceRecords[i].name == name) { - rnd.setSeed(_randomSourceRecords[i].seed); - _randomSourceRecords.remove_at(i); - break; - } - } - } -} - -void EventRecorder::processMillis(uint32 &millis) { - uint32 d; - if (_recordMode == kPassthrough) { - return; - } - - g_system->lockMutex(_timeMutex); - if (_recordMode == kRecorderRecord) { - d = millis - _lastMillis; - writeTime(_recordTimeFile, d); - - _recordTimeCount++; - } - - if (_recordMode == kRecorderPlayback) { - if (_recordTimeCount > _playbackTimeCount) { - d = readTime(_playbackTimeFile); - - while ((_lastMillis + d > millis) && (_lastMillis + d - millis > 50)) { - _recordMode = kPassthrough; - g_system->delayMillis(50); - millis = g_system->getMillis(); - _recordMode = kRecorderPlayback; - } - - millis = _lastMillis + d; - _playbackTimeCount++; - } - } - - _lastMillis = millis; - g_system->unlockMutex(_timeMutex); -} - -bool EventRecorder::processDelayMillis(uint &msecs) { - if (_recordMode == kRecorderPlayback) { - _recordMode = kPassthrough; - - uint32 millis = g_system->getMillis(); - - _recordMode = kRecorderPlayback; - - if (_lastMillis > millis) { - // Skip delay if we're getting late - return true; - } - } - - return false; -} - -bool EventRecorder::notifyEvent(const Event &ev) { - if (_recordMode != kRecorderRecord) - return false; - - StackLock lock(_recorderMutex); - ++_eventCount; - - 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; - - StackLock lock(_recorderMutex); - ++_eventCount; - - if (!_hasPlaybackEvent) { - if (_recordCount > _playbackCount) { - readRecord(_playbackFile, const_cast<uint32&>(_playbackDiff), _playbackEvent, millis); - _playbackCount++; - _hasPlaybackEvent = true; - } - } - - if (_hasPlaybackEvent) { - if (_playbackDiff <= (_eventCount - _lastEventCount)) { - switch (_playbackEvent.type) { - case EVENT_MOUSEMOVE: - case EVENT_LBUTTONDOWN: - case EVENT_LBUTTONUP: - case EVENT_RBUTTONDOWN: - case EVENT_RBUTTONUP: - case EVENT_WHEELUP: - case EVENT_WHEELDOWN: - g_system->warpMouse(_playbackEvent.mouse.x, _playbackEvent.mouse.y); - break; - default: - break; - } - ev = _playbackEvent; - _hasPlaybackEvent = false; - _lastEventCount = _eventCount; - return true; - } - } - - return false; -} - -} // End of namespace Common diff --git a/common/EventRecorder.h b/common/EventRecorder.h deleted file mode 100644 index 43a08b08cd..0000000000 --- a/common/EventRecorder.h +++ /dev/null @@ -1,110 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef COMMON_EVENTRECORDER_H -#define COMMON_EVENTRECORDER_H - -#include "common/scummsys.h" -#include "common/events.h" -#include "common/singleton.h" -#include "common/mutex.h" -#include "common/array.h" - -#define g_eventRec (Common::EventRecorder::instance()) - -namespace Common { - -class RandomSource; -class SeekableReadStream; -class WriteStream; - -/** - * Our generic event recorder. - * - * TODO: Add more documentation. - */ -class EventRecorder : private EventSource, private EventObserver, public Singleton<EventRecorder> { - friend class Singleton<SingletonBaseType>; - EventRecorder(); - ~EventRecorder(); -public: - void init(); - void deinit(); - - /** Register random source so it can be serialized in game test purposes */ - void registerRandomSource(RandomSource &rnd, const String &name); - - /** TODO: Add documentation, this is only used by the backend */ - void processMillis(uint32 &millis); - - /** TODO: Add documentation, this is only used by the backend */ - bool processDelayMillis(uint &msecs); - -private: - bool notifyEvent(const Event &ev); - bool notifyPoll(); - bool pollEvent(Event &ev); - bool allowMapping() const { return false; } - - class RandomSourceRecord { - public: - String name; - uint32 seed; - }; - Array<RandomSourceRecord> _randomSourceRecords; - - bool _recordSubtitles; - volatile uint32 _recordCount; - volatile uint32 _lastRecordEvent; - volatile uint32 _recordTimeCount; - volatile uint32 _lastEventMillis; - WriteStream *_recordFile; - WriteStream *_recordTimeFile; - MutexRef _timeMutex; - MutexRef _recorderMutex; - volatile uint32 _lastMillis; - - volatile uint32 _playbackCount; - volatile uint32 _playbackDiff; - volatile bool _hasPlaybackEvent; - volatile uint32 _playbackTimeCount; - Event _playbackEvent; - SeekableReadStream *_playbackFile; - SeekableReadStream *_playbackTimeFile; - - volatile uint32 _eventCount; - volatile uint32 _lastEventCount; - - enum RecordMode { - kPassthrough = 0, - kRecorderRecord = 1, - kRecorderPlayback = 2 - }; - volatile RecordMode _recordMode; - String _recordFileName; - String _recordTempFileName; - String _recordTimeFileName; -}; - -} // End of namespace Common - -#endif diff --git a/common/algorithm.h b/common/algorithm.h index 7a0eed89ce..6453073ae5 100644 --- a/common/algorithm.h +++ b/common/algorithm.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_ALGORITHM_H diff --git a/common/archive.cpp b/common/archive.cpp index 57ebeb2ca6..36d420561f 100644 --- a/common/archive.cpp +++ b/common/archive.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/archive.h b/common/archive.h index 2f9736f032..9293b937af 100644 --- a/common/archive.h +++ b/common/archive.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/array.h b/common/array.h index ca89523a0b..f240a9c2f5 100644 --- a/common/array.h +++ b/common/array.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_ARRAY_H diff --git a/common/bitstream.h b/common/bitstream.h index c8c8c11fca..b789f2ac8d 100644 --- a/common/bitstream.h +++ b/common/bitstream.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -52,6 +52,9 @@ public: /** Skip the specified amount of bits. */ virtual void skip(uint32 n) = 0; + /** Skip the bits to closest data value border. */ + virtual void align() = 0; + /** Read a bit from the bit stream. */ virtual uint32 getBit() = 0; @@ -276,6 +279,12 @@ public: getBit(); } + /** Skip the bits to closest data value border. */ + void align() { + while (_inValue) + getBit(); + } + /** Return the stream position in bits. */ uint32 pos() const { if (_stream->pos() == 0) diff --git a/common/bufferedstream.h b/common/bufferedstream.h index 6c859c98fe..bbd25722a8 100644 --- a/common/bufferedstream.h +++ b/common/bufferedstream.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/c++11-compat.h b/common/c++11-compat.h index 50d79bd79e..a56b79514c 100644 --- a/common/c++11-compat.h +++ b/common/c++11-compat.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -31,12 +31,20 @@ // Custom nullptr replacement. This is not type safe as the real C++11 nullptr // though. // +#if !defined(nullptr) // XCode 5.0.1 has __cplusplus=199711 but defines this +// MSVC 2010 and newer fully support nullptr: http://msdn.microsoft.com/en-us/library/hh567368.aspx +#if !defined(_MSC_VER) || _MSC_VER < 1600 #define nullptr 0 +#endif +#endif // // Replacement for the override keyword. This allows compilation of code // which uses it, but does not feature any semantic. // +// MSVC 2012 and newer fully support override: http://msdn.microsoft.com/en-us/library/hh567368.aspx +#if !defined(_MSC_VER) || _MSC_VER < 1700 #define override +#endif #endif diff --git a/common/config-manager.cpp b/common/config-manager.cpp index aaa812bc94..24c877a4e9 100644 --- a/common/config-manager.cpp +++ b/common/config-manager.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -597,7 +597,7 @@ void ConfigManager::setActiveDomain(const String &domName) { _activeDomain = 0; } else { assert(isValidDomainName(domName)); - _activeDomain = & _gameDomains[domName]; + _activeDomain = &_gameDomains[domName]; } _activeDomainName = domName; } @@ -626,6 +626,10 @@ void ConfigManager::addMiscDomain(const String &domName) { void ConfigManager::removeGameDomain(const String &domName) { assert(!domName.empty()); assert(isValidDomainName(domName)); + if (domName == _activeDomainName) { + _activeDomainName.clear(); + _activeDomain = 0; + } _gameDomains.erase(domName); } @@ -638,6 +642,10 @@ void ConfigManager::removeMiscDomain(const String &domName) { void ConfigManager::renameGameDomain(const String &oldName, const String &newName) { renameDomain(oldName, newName, _gameDomains); + if (_activeDomainName == oldName) { + _activeDomainName = newName; + _activeDomain = &_gameDomains[newName]; + } } void ConfigManager::renameMiscDomain(const String &oldName, const String &newName) { diff --git a/common/config-manager.h b/common/config-manager.h index d43a7bec51..14f911f69d 100644 --- a/common/config-manager.h +++ b/common/config-manager.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -24,7 +24,6 @@ #define COMMON_CONFIG_MANAGER_H #include "common/array.h" -//#include "common/config-file.h" #include "common/hashmap.h" #include "common/singleton.h" #include "common/str.h" @@ -47,12 +46,33 @@ class ConfigManager : public Singleton<ConfigManager> { public: - class Domain : public StringMap { + class Domain { private: + StringMap _entries; StringMap _keyValueComments; String _domainComment; public: + typedef StringMap::const_iterator const_iterator; + const_iterator begin() const { return _entries.begin(); } + const_iterator end() const { return _entries.end(); } + + bool empty() const { return _entries.empty(); } + + bool contains(const String &key) const { return _entries.contains(key); } + + String &operator[](const String &key) { return _entries[key]; } + const String &operator[](const String &key) const { return _entries[key]; } + + void setVal(const String &key, const String &value) { _entries.setVal(key, value); } + + String &getVal(const String &key) { return _entries.getVal(key); } + const String &getVal(const String &key) const { return _entries.getVal(key); } + + void clear() { _entries.clear(); } + + void erase(const String &key) { _entries.erase(key); } + void setDomainComment(const String &comment); const String &getDomainComment() const; @@ -143,7 +163,8 @@ public: bool hasMiscDomain(const String &domName) const; const DomainMap & getGameDomains() const { return _gameDomains; } - DomainMap & getGameDomains() { return _gameDomains; } + DomainMap::iterator beginGameDomains() { return _gameDomains.begin(); } + DomainMap::iterator endGameDomains() { return _gameDomains.end(); } static void defragment(); // move in memory to reduce fragmentation void copyFrom(ConfigManager &source); diff --git a/common/coroutines.cpp b/common/coroutines.cpp index 849b881177..248777febd 100644 --- a/common/coroutines.cpp +++ b/common/coroutines.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #include "common/coroutines.h" diff --git a/common/coroutines.h b/common/coroutines.h index 834c67f6e4..4fef1a0d4e 100644 --- a/common/coroutines.h +++ b/common/coroutines.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_COROUTINES_H @@ -128,7 +129,7 @@ public: */ #define CORO_BEGIN_CONTEXT \ struct CoroContextTag : Common::CoroBaseContext { \ - CoroContextTag() : CoroBaseContext(SCUMMVM_CURRENT_FUNCTION) {} \ + CoroContextTag() : CoroBaseContext(SCUMMVM_CURRENT_FUNCTION) { DUMMY = 0; } \ int DUMMY /** @@ -146,6 +147,7 @@ public: #define CORO_BEGIN_CODE(x) \ if (&coroParam == &Common::nullContext) assert(!Common::nullContext); \ if (!x) { coroParam = x = new CoroContextTag(); } \ + x->DUMMY = 0; \ Common::CoroContextHolder tmpHolder(coroParam); \ switch (coroParam->_line) { case 0:; diff --git a/common/cosinetables.cpp b/common/cosinetables.cpp index 3b245750fa..4bee1f24ea 100644 --- a/common/cosinetables.cpp +++ b/common/cosinetables.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/cosinetables.h b/common/cosinetables.h index f5c95ec003..0ff01e40d6 100644 --- a/common/cosinetables.h +++ b/common/cosinetables.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/dcl.cpp b/common/dcl.cpp index 1879be992d..5993c218cb 100644 --- a/common/dcl.cpp +++ b/common/dcl.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -30,18 +30,15 @@ namespace Common { class DecompressorDCL { public: - bool unpack(ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked); + bool unpack(SeekableReadStream *sourceStream, WriteStream *targetStream, uint32 targetSize, bool targetFixedSize); protected: /** * Initialize decompressor. - * @param src source stream to read from - * @param dest destination stream to write to - * @param nPacked size of packed data - * @param nUnpacket size of unpacked data - * @return 0 on success, non-zero on error + * @param sourceStream source stream to read from + * @param targetStream target memory stream to write to */ - void init(ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked); + void init(SeekableReadStream *sourceStream, WriteStream *targetStream, uint32 targetSize, bool targetFixedSize); /** * Get a number of bits from _src stream, starting with the least @@ -67,36 +64,38 @@ protected: int huffman_lookup(const int *tree); - uint32 _dwBits; ///< bits buffer - byte _nBits; ///< number of unread bits in _dwBits - uint32 _szPacked; ///< size of the compressed data - uint32 _szUnpacked; ///< size of the decompressed data - uint32 _dwRead; ///< number of bytes read from _src - uint32 _dwWrote; ///< number of bytes written to _dest - ReadStream *_src; - byte *_dest; + uint32 _dwBits; ///< bits buffer + byte _nBits; ///< number of unread bits in _dwBits + uint32 _sourceSize; ///< size of the source stream + uint32 _targetSize; ///< size of the target stream (if fixed) + bool _targetFixedSize; ///< if target stream is fixed size or dynamic size + uint32 _bytesRead; ///< number of bytes read from _sourceStream + uint32 _bytesWritten; ///< number of bytes written to _targetStream + SeekableReadStream *_sourceStream; + WriteStream *_targetStream; }; -void DecompressorDCL::init(ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) { - _src = src; - _dest = dest; - _szPacked = nPacked; - _szUnpacked = nUnpacked; +void DecompressorDCL::init(SeekableReadStream *sourceStream, WriteStream *targetStream, uint32 targetSize, bool targetFixedSize) { + _sourceStream = sourceStream; + _targetStream = targetStream; + _sourceSize = sourceStream->size(); + _targetSize = targetSize; + _targetFixedSize = targetFixedSize; _nBits = 0; - _dwRead = _dwWrote = 0; + _bytesRead = _bytesWritten = 0; _dwBits = 0; } void DecompressorDCL::fetchBitsLSB() { while (_nBits <= 24) { - _dwBits |= ((uint32)_src->readByte()) << _nBits; + _dwBits |= ((uint32)_sourceStream->readByte()) << _nBits; _nBits += 8; - _dwRead++; + _bytesRead++; } } uint32 DecompressorDCL::getBitsLSB(int n) { - // fetching more data to buffer if needed + // Fetching more data to buffer if needed if (_nBits < n) fetchBitsLSB(); uint32 ret = (_dwBits & ~((~0) << n)); @@ -110,7 +109,8 @@ byte DecompressorDCL::getByteLSB() { } void DecompressorDCL::putByte(byte b) { - _dest[_dwWrote++] = b; + _targetStream->writeByte(b); + _bytesWritten++; } #define HUFFMAN_LEAF 0x40000000 @@ -332,95 +332,189 @@ int DecompressorDCL::huffman_lookup(const int *tree) { #define DCL_BINARY_MODE 0 #define DCL_ASCII_MODE 1 -bool DecompressorDCL::unpack(ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) { - init(src, dest, nPacked, nUnpacked); +#define MIDI_SETUP_BUNDLE_FILE_MAXIMUM_DICTIONARY_SIZE 4096 +bool DecompressorDCL::unpack(SeekableReadStream *sourceStream, WriteStream *targetStream, uint32 targetSize, bool targetFixedSize) { + byte dictionary[MIDI_SETUP_BUNDLE_FILE_MAXIMUM_DICTIONARY_SIZE]; + uint16 dictionaryPos = 0; + uint16 dictionarySize = 0; + uint16 dictionaryMask = 0; int value; - uint32 val_distance, val_length; + uint16 tokenOffset = 0; + uint16 tokenLength = 0; - int mode = getByteLSB(); - int length_param = getByteLSB(); + init(sourceStream, targetStream, targetSize, targetFixedSize); + + byte mode = getByteLSB(); + byte dictionaryType = getByteLSB(); if (mode != DCL_BINARY_MODE && mode != DCL_ASCII_MODE) { warning("DCL-INFLATE: Error: Encountered mode %02x, expected 00 or 01", mode); return false; } - if (length_param < 3 || length_param > 6) - warning("Unexpected length_param value %d (expected in [3,6])", length_param); + // TODO: original code supported 3 as well??? + // Was this an accident or on purpose? And the original code did just give out a warning + // and didn't error out at all + switch (dictionaryType) { + case 4: + dictionarySize = 1024; + break; + case 5: + dictionarySize = 2048; + break; + case 6: + dictionarySize = 4096; + break; + default: + warning("DCL-INFLATE: Error: unsupported dictionary type %02x", dictionaryType); + return false; + } + dictionaryMask = dictionarySize - 1; - while (_dwWrote < _szUnpacked) { + while ((!targetFixedSize) || (_bytesWritten < _targetSize)) { if (getBitsLSB(1)) { // (length,distance) pair value = huffman_lookup(length_tree); if (value < 8) - val_length = value + 2; + tokenLength = value + 2; else - val_length = 8 + (1 << (value - 7)) + getBitsLSB(value - 7); + tokenLength = 8 + (1 << (value - 7)) + getBitsLSB(value - 7); + + if (tokenLength == 519) + break; // End of stream signal debug(8, " | "); value = huffman_lookup(distance_tree); - if (val_length == 2) - val_distance = (value << 2) | getBitsLSB(2); + if (tokenLength == 2) + tokenOffset = (value << 2) | getBitsLSB(2); else - val_distance = (value << length_param) | getBitsLSB(length_param); - val_distance ++; + tokenOffset = (value << dictionaryType) | getBitsLSB(dictionaryType); + tokenOffset++; - debug(8, "\nCOPY(%d from %d)\n", val_length, val_distance); + debug(8, "\nCOPY(%d from %d)\n", tokenLength, tokenOffset); - if (val_length + _dwWrote > _szUnpacked) { - warning("DCL-INFLATE Error: Write out of bounds while copying %d bytes", val_length); - return false; + if (_targetFixedSize) { + if (tokenLength + _bytesWritten > _targetSize) { + warning("DCL-INFLATE Error: Write out of bounds while copying %d bytes (declared unpacked size is %d bytes, current is %d + %d bytes)", + tokenLength, _targetSize, _bytesWritten, tokenLength); + return false; + } } - if (_dwWrote < val_distance) { - warning("DCL-INFLATE Error: Attempt to copy from before beginning of input stream"); + if (_bytesWritten < tokenOffset) { + warning("DCL-INFLATE Error: Attempt to copy from before beginning of input stream (declared unpacked size is %d bytes, current is %d bytes)", + _targetSize, _bytesWritten); return false; } - while (val_length) { - uint32 copy_length = (val_length > val_distance) ? val_distance : val_length; - assert(val_distance >= copy_length); - uint32 pos = _dwWrote - val_distance; - for (uint32 i = 0; i < copy_length; i++) - putByte(dest[pos + i]); + uint16 dictionaryBaseIndex = (dictionaryPos - tokenOffset) & dictionaryMask; + uint16 dictionaryIndex = dictionaryBaseIndex; + uint16 dictionaryNextIndex = dictionaryPos; + + while (tokenLength) { + // Write byte from dictionary + putByte(dictionary[dictionaryIndex]); + debug(9, "\33[32;31m%02x\33[37;37m ", dictionary[dictionaryIndex]); + + dictionary[dictionaryNextIndex] = dictionary[dictionaryIndex]; + + dictionaryNextIndex = (dictionaryNextIndex + 1) & dictionaryMask; + dictionaryIndex = (dictionaryIndex + 1) & dictionaryMask; - for (uint32 i = 0; i < copy_length; i++) - debug(9, "\33[32;31m%02x\33[37;37m ", dest[pos + i]); - debug(9, "\n"); + if (dictionaryIndex == dictionaryPos) + dictionaryIndex = dictionaryBaseIndex; + if (dictionaryNextIndex == dictionarySize) + dictionaryNextIndex = 0; - val_length -= copy_length; - val_distance += copy_length; + tokenLength--; } + dictionaryPos = dictionaryNextIndex; + debug(9, "\n"); } else { // Copy byte verbatim value = (mode == DCL_ASCII_MODE) ? huffman_lookup(ascii_tree) : getByteLSB(); putByte(value); + + // Also remember it inside dictionary + dictionary[dictionaryPos] = value; + dictionaryPos++; + if (dictionaryPos >= dictionarySize) + dictionaryPos = 0; + debug(9, "\33[32;31m%02x \33[37;37m", value); } } - return _dwWrote == _szUnpacked; + if (_targetFixedSize) { + return _bytesWritten == _targetSize; + } + return true; // For targets featuring dynamic size we always succeed } bool decompressDCL(ReadStream *src, byte *dest, uint32 packedSize, uint32 unpackedSize) { + bool success = false; + DecompressorDCL dcl; + if (!src || !dest) return false; + byte *sourceBufferPtr = (byte *)malloc(packedSize); + if (!sourceBufferPtr) + return false; + + // Read source into memory + src->read(sourceBufferPtr, packedSize); + + Common::MemoryReadStream *sourceStream = new MemoryReadStream(sourceBufferPtr, packedSize, DisposeAfterUse::NO); + Common::MemoryWriteStream *targetStream = new MemoryWriteStream(dest, unpackedSize); + + success = dcl.unpack(sourceStream, targetStream, unpackedSize, true); + delete sourceStream; + delete targetStream; + return success; +} + +SeekableReadStream *decompressDCL(SeekableReadStream *sourceStream, uint32 packedSize, uint32 unpackedSize) { + bool success = false; + byte *targetPtr = nullptr; + Common::MemoryWriteStream *targetStream; DecompressorDCL dcl; - return dcl.unpack(src, dest, packedSize, unpackedSize); + + targetPtr = (byte *)malloc(unpackedSize); + if (!targetPtr) + return nullptr; + + targetStream = new MemoryWriteStream(targetPtr, unpackedSize); + + success = dcl.unpack(sourceStream, targetStream, unpackedSize, true); + delete targetStream; + + if (!success) { + free(targetPtr); + return nullptr; + } + return new MemoryReadStream(targetPtr, unpackedSize, DisposeAfterUse::YES); } -SeekableReadStream *decompressDCL(ReadStream *src, uint32 packedSize, uint32 unpackedSize) { - byte *data = (byte *)malloc(unpackedSize); +// This one figures out the unpacked size by itself +// Needed for at least Simon 2, because the unpacked size is not stored anywhere +SeekableReadStream *decompressDCL(SeekableReadStream *sourceStream) { + Common::MemoryWriteStreamDynamic *targetStream; + DecompressorDCL dcl; - if (decompressDCL(src, data, packedSize, unpackedSize)) - return new MemoryReadStream(data, unpackedSize, DisposeAfterUse::YES); + targetStream = new MemoryWriteStreamDynamic(DisposeAfterUse::NO); - free(data); - return 0; + if (dcl.unpack(sourceStream, targetStream, 0, false)) { + byte *targetPtr = targetStream->getData(); + uint32 unpackedSize = targetStream->size(); + delete targetStream; + return new MemoryReadStream(targetPtr, unpackedSize, DisposeAfterUse::YES); + } + delete targetStream; + return nullptr; } } // End of namespace Common diff --git a/common/dcl.h b/common/dcl.h index 78ffa631ed..f90bc23c8d 100644 --- a/common/dcl.h +++ b/common/dcl.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -22,7 +22,8 @@ /** * @file - * PKWARE DCL ("explode") decompressor used in engines: + * PKWARE DCL ("explode") ("PKWARE data compression library") decompressor used in engines: + * - agos (exclusively for Simon 2 setup.shr file) * - mohawk * - sci */ @@ -38,16 +39,22 @@ class ReadStream; class SeekableReadStream; /** - * Try to decompress a PKWARE DCL compressed stream. Returns true if + * Try to decompress a PKWARE DCL (PKWARE data compression library) compressed stream. Returns true if * successful. */ -bool decompressDCL(ReadStream *src, byte *dest, uint32 packedSize, uint32 unpackedSize); +bool decompressDCL(ReadStream *sourceStream, byte *dest, uint32 packedSize, uint32 unpackedSize); /** - * Try to decompress a PKWARE DCL compressed stream. Returns a valid pointer + * Try to decompress a PKWARE DCL (PKWARE data compression library) compressed stream. Returns a valid pointer * if successful and 0 otherwise. */ -SeekableReadStream *decompressDCL(ReadStream *src, uint32 packedSize, uint32 unpackedSize); +SeekableReadStream *decompressDCL(SeekableReadStream *sourceStream, uint32 packedSize, uint32 unpackedSize); + +/** + * Try to decompress a PKWARE DCL (PKWARE data compression library) compressed stream. Returns a valid pointer + * if successful and 0 otherwise. This method is meant for cases, where the unpacked size is not known. + */ +SeekableReadStream *decompressDCL(SeekableReadStream *sourceStream); } // End of namespace Common diff --git a/common/dct.cpp b/common/dct.cpp index 38b4fbcff2..27e0c0bf41 100644 --- a/common/dct.cpp +++ b/common/dct.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -73,7 +73,7 @@ void DCT::calc(float *data) { void DCT::calcDCTI(float *data) { int n = 1 << _bits; - float next = -0.5 * (data[0] - data[n]); + float next = -0.5f * (data[0] - data[n]); for (int i = 0; i < (n / 2); i++) { float tmp1 = data[i ]; @@ -87,7 +87,7 @@ void DCT::calcDCTI(float *data) { next += c; - tmp1 = (tmp1 + tmp2) * 0.5; + tmp1 = (tmp1 + tmp2) * 0.5f; data[i ] = tmp1 - s; data[n - i] = tmp1 + s; @@ -113,7 +113,7 @@ void DCT::calcDCTII(float *data) { s *= tmp1 - tmp2; - tmp1 = (tmp1 + tmp2) * 0.5; + tmp1 = (tmp1 + tmp2) * 0.5f; data[i ] = tmp1 + s; data[n - i - 1] = tmp1 - s; @@ -121,7 +121,7 @@ void DCT::calcDCTII(float *data) { _rdft->calc(data); - float next = data[1] * 0.5; + float next = data[1] * 0.5f; data[1] *= -1; @@ -143,7 +143,7 @@ void DCT::calcDCTIII(float *data) { int n = 1 << _bits; float next = data[n - 1]; - float inv_n = 1.0 / n; + float inv_n = 1.0f / n; for (int i = n - 2; i >= 2; i -= 2) { float val1 = data[i ]; @@ -184,7 +184,7 @@ void DCT::calcDSTI(float *data) { float s = SIN(n, 2 * i); s *= tmp1 + tmp2; - tmp1 = (tmp1 - tmp2) * 0.5; + tmp1 = (tmp1 - tmp2) * 0.5f; data[i ] = s + tmp1; data[n - i] = s - tmp1; @@ -194,7 +194,7 @@ void DCT::calcDSTI(float *data) { _rdft->calc(data); - data[0] *= 0.5; + data[0] *= 0.5f; for (int i = 1; i < (n - 2); i += 2) { data[i + 1] += data[i - 1]; diff --git a/common/dct.h b/common/dct.h index 085423ddff..882856a8a9 100644 --- a/common/dct.h +++ b/common/dct.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/debug-channels.h b/common/debug-channels.h index 40d1ea667e..1414a1053a 100644 --- a/common/debug-channels.h +++ b/common/debug-channels.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_DEBUG_CHANNELS_H @@ -94,8 +95,6 @@ public: */ bool disableDebugChannel(const String &name); - - typedef List<DebugChannel> DebugChannelList; /** @@ -105,6 +104,15 @@ public: */ DebugChannelList listDebugChannels(); + /** + * Enable all debug channels. + */ + void enableAllDebugChannels(); + + /** + * Disable all debug channels. + */ + void disableAllDebugChannels(); /** * Test whether the given debug channel is enabled. diff --git a/common/debug.cpp b/common/debug.cpp index ba5479c34d..182b28afdf 100644 --- a/common/debug.cpp +++ b/common/debug.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #include "common/debug.h" @@ -45,6 +46,11 @@ struct DebugLevelComperator { } // end of anonymous namespace bool DebugManager::addDebugChannel(uint32 channel, const String &name, const String &description) { + if (name.equalsIgnoreCase("all")) { + warning("Debug channel 'all' is reserved for internal use"); + return false; + } + if (gDebugChannels.contains(name)) warning("Duplicate declaration of engine debug channel '%s'", name.c_str()); @@ -84,7 +90,6 @@ bool DebugManager::disableDebugChannel(const String &name) { } } - DebugManager::DebugChannelList DebugManager::listDebugChannels() { DebugChannelList tmp; for (DebugChannelMap::iterator i = gDebugChannels.begin(); i != gDebugChannels.end(); ++i) @@ -94,6 +99,16 @@ DebugManager::DebugChannelList DebugManager::listDebugChannels() { return tmp; } +void DebugManager::enableAllDebugChannels() { + for (DebugChannelMap::iterator i = gDebugChannels.begin(); i != gDebugChannels.end(); ++i) + enableDebugChannel(i->_value.name); +} + +void DebugManager::disableAllDebugChannels() { + for (DebugChannelMap::iterator i = gDebugChannels.begin(); i != gDebugChannels.end(); ++i) + disableDebugChannel(i->_value.name); +} + bool DebugManager::isDebugChannelEnabled(uint32 channel) { // Debug level 11 turns on all special debug level messages if (gDebugLevel == 11) diff --git a/common/debug.h b/common/debug.h index dc94839082..b6e0679a12 100644 --- a/common/debug.h +++ b/common/debug.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_DEBUG_H @@ -117,5 +118,9 @@ void debugCN(uint32 debugChannels, const char *s, ...) GCC_PRINTF(2, 3); */ extern int gDebugLevel; +//Global constant for EventRecorder debug channel +enum GlobalDebugLevels { + kDebugLevelEventRec = 1 << 30 +}; #endif diff --git a/common/endian.h b/common/endian.h index 759513efef..7278265961 100644 --- a/common/endian.h +++ b/common/endian.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -49,6 +49,18 @@ # error No endianness defined #endif +#ifdef HAVE_INT64 +#define SWAP_CONSTANT_64(a) \ + ((uint64)((((a) >> 56) & 0x000000FF) | \ + (((a) >> 40) & 0x0000FF00) | \ + (((a) >> 24) & 0x00FF0000) | \ + (((a) >> 8) & 0xFF000000) | \ + (((a) & 0xFF000000) << 8) | \ + (((a) & 0x00FF0000) << 24) | \ + (((a) & 0x0000FF00) << 40) | \ + (((a) & 0x000000FF) << 56) )) +#endif + #define SWAP_CONSTANT_32(a) \ ((uint32)((((a) >> 24) & 0x00FF) | \ (((a) >> 8) & 0xFF00) | \ @@ -59,6 +71,36 @@ ((uint16)((((a) >> 8) & 0x00FF) | \ (((a) << 8) & 0xFF00) )) + + +/** + * Swap the bytes in a 16 bit word in order to convert LE encoded data to BE + * and vice versa. + */ + +// compilerspecific variants come first, fallback last + +// Test for GCC and if the target has the MIPS rel.2 instructions (we know the psp does) +#if defined(__GNUC__) && (defined(__psp__) || defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)) + + FORCEINLINE uint16 SWAP_BYTES_16(const uint16 a) { + if (__builtin_constant_p(a)) { + return SWAP_CONSTANT_16(a); + } else { + uint16 result; + __asm__ ("wsbh %0,%1" : "=r" (result) : "r" (a)); + return result; + } + } +#else + + inline uint16 SWAP_BYTES_16(const uint16 a) { + return (a >> 8) | (a << 8); + } +#endif + + + /** * Swap the bytes in a 32 bit word in order to convert LE encoded data to BE * and vice versa. @@ -92,8 +134,7 @@ return __builtin_bswap32(a); } -// test for MSVC 7 or newer -#elif defined(_MSC_VER) && _MSC_VER >= 1300 +#elif defined(_MSC_VER) FORCEINLINE uint32 SWAP_BYTES_32(uint32 a) { return _byteswap_ulong(a); @@ -109,32 +150,60 @@ } #endif +#ifdef HAVE_INT64 /** - * Swap the bytes in a 16 bit word in order to convert LE encoded data to BE + * Swap the bytes in a 64 bit word in order to convert LE encoded data to BE * and vice versa. */ -// compilerspecific variants come first, fallback last +// machine/compiler-specific variants come first, fallback last // Test for GCC and if the target has the MIPS rel.2 instructions (we know the psp does) +// #if defined(__GNUC__) && (defined(__psp__) || defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)) - FORCEINLINE uint16 SWAP_BYTES_16(const uint16 a) { + FORCEINLINE uint64 SWAP_BYTES_64(const uint64 a) { if (__builtin_constant_p(a)) { - return SWAP_CONSTANT_16(a); + return SWAP_CONSTANT_64(a); } else { - uint16 result; - __asm__ ("wsbh %0,%1" : "=r" (result) : "r" (a)); - return result; + uint32 low = (uint32)a, high = (uint32)(a >> 32); + low = SWAP_BYTES_32(low); + high = SWAP_BYTES_32(high); + + return (((uint64)low) << 32) | high; } } + +// Test for GCC >= 4.3.0 as this version added the bswap builtin +#elif GCC_ATLEAST(4, 3) + + FORCEINLINE uint64 SWAP_BYTES_64(uint64 a) { + return __builtin_bswap64(a); + } + +#elif defined(_MSC_VER) + + FORCEINLINE uint64 SWAP_BYTES_64(uint64 a) { + return _byteswap_uint64(a); + } + +// generic fallback #else - inline uint16 SWAP_BYTES_16(const uint16 a) { - return (a >> 8) | (a << 8); + inline uint64 SWAP_BYTES_64(uint64 a) { + uint32 low = (uint32)a, high = (uint32)(a >> 32); + uint16 lowLow = (uint16)low, lowHigh = (uint16)(low >> 16), + highLow = (uint16)high, highHigh = (uint16)(high >> 16); + + return ((uint64)(((uint32)(uint16)((lowLow >> 8) | (lowLow << 8)) << 16) | + (uint16)((lowHigh >> 8) | (lowHigh << 8))) << 32) | + (((uint32)(uint16)((highLow >> 8) | (highLow << 8)) << 16) | + (uint16)((highHigh >> 8) | (highHigh << 8))); } #endif +#endif // HAVE_INT64 + /** * A wrapper macro used around four character constants, like 'DATA', to @@ -184,6 +253,18 @@ ((Unaligned32 *)ptr)->val = value; } +#ifdef HAVE_INT64 + FORCEINLINE uint64 READ_UINT64(const void *ptr) { + struct Unaligned64 { uint64 val; } __attribute__ ((__packed__, __may_alias__)); + return ((const Unaligned64 *)ptr)->val; + } + + FORCEINLINE void WRITE_UINT64(void *ptr, uint64 value) { + struct Unaligned64 { uint64 val; } __attribute__((__packed__, __may_alias__)); + ((Unaligned64 *)ptr)->val = value; + } +#endif + #elif !defined(SCUMM_NEED_ALIGNMENT) FORCEINLINE uint16 READ_UINT16(const void *ptr) { @@ -202,6 +283,16 @@ *(uint32 *)(ptr) = value; } +#ifdef HAVE_INT64 + FORCEINLINE uint64 READ_UINT64(const void *ptr) { + return *(const uint64 *)(ptr); + } + + FORCEINLINE void WRITE_UINT64(void *ptr, uint64 value) { + *(uint64 *)(ptr) = value; + } +#endif + // use software fallback by loading each byte explicitely #else @@ -228,6 +319,23 @@ b[2] = (uint8)(value >> 16); b[3] = (uint8)(value >> 24); } +#ifdef HAVE_INT64 + inline uint64 READ_UINT64(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return ((uint64)b[7] << 56) | ((uint64)b[6] << 48) | ((uint64)b[5] << 40) | ((uint64)b[4] << 32) | ((uint64)b[3] << 24) | ((uint64)b[2] << 16) | ((uint64)b[1] << 8) | ((uint64)b[0]); + } + inline void WRITE_UINT64(void *ptr, uint64 value) { + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 0); + b[1] = (uint8)(value >> 8); + b[2] = (uint8)(value >> 16); + b[3] = (uint8)(value >> 24); + b[4] = (uint8)(value >> 32); + b[5] = (uint8)(value >> 40); + b[6] = (uint8)(value >> 48); + b[7] = (uint8)(value >> 56); + } +#endif # elif defined(SCUMM_BIG_ENDIAN) @@ -251,6 +359,23 @@ b[2] = (uint8)(value >> 8); b[3] = (uint8)(value >> 0); } +#ifdef HAVE_INT64 + inline uint64 READ_UINT64(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return ((uint64)b[0] << 56) | ((uint64)b[1] << 48) | ((uint64)b[2] << 40) | ((uint64)b[3] << 32) | ((uint64)b[4] << 24) | ((uint64)b[5] << 16) | ((uint64)b[6] << 8) | ((uint64)b[7]); + } + inline void WRITE_UINT64(void *ptr, uint64 value) { + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 56); + b[1] = (uint8)(value >> 48); + b[2] = (uint8)(value >> 40); + b[3] = (uint8)(value >> 32); + b[4] = (uint8)(value >> 24); + b[5] = (uint8)(value >> 16); + b[6] = (uint8)(value >> 8); + b[7] = (uint8)(value >> 0); + } +#endif # endif @@ -284,6 +409,17 @@ #define CONSTANT_BE_32(a) SWAP_CONSTANT_32(a) #define CONSTANT_BE_16(a) SWAP_CONSTANT_16(a) +#ifdef HAVE_INT64 + #define READ_LE_UINT64(a) READ_UINT64(a) + #define WRITE_LE_UINT64(a, v) WRITE_UINT64(a, v) + #define FROM_LE_64(a) ((uint64)(a)) + #define FROM_BE_64(a) SWAP_BYTES_64(a) + #define TO_LE_64(a) ((uint64)(a)) + #define TO_BE_64(a) SWAP_BYTES_64(a) + #define CONSTANT_LE_64(a) ((uint64)(a)) + #define CONSTANT_BE_64(a) SWAP_CONSTANT_64(a) +#endif + // if the unaligned load and the byteswap take alot instructions its better to directly read and invert # if defined(SCUMM_NEED_ALIGNMENT) && !defined(__mips__) @@ -307,6 +443,24 @@ b[2] = (uint8)(value >> 8); b[3] = (uint8)(value >> 0); } +#ifdef HAVE_INT64 + inline uint64 READ_BE_UINT64(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return ((uint64)b[0] << 56) | ((uint64)b[1] << 48) | ((uint64)b[2] << 40) | ((uint64)b[3] << 32) | ((uint64)b[4] << 24) | ((uint64)b[5] << 16) | ((uint64)b[6] << 8) | ((uint64)b[7]); + } + inline void WRITE_BE_UINT64(void *ptr, uint64 value) { + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 56); + b[1] = (uint8)(value >> 48); + b[2] = (uint8)(value >> 40); + b[3] = (uint8)(value >> 32); + b[4] = (uint8)(value >> 24); + b[5] = (uint8)(value >> 16); + b[6] = (uint8)(value >> 8); + b[7] = (uint8)(value >> 0); + } +#endif + # else inline uint16 READ_BE_UINT16(const void *ptr) { @@ -321,6 +475,14 @@ inline void WRITE_BE_UINT32(void *ptr, uint32 value) { WRITE_UINT32(ptr, SWAP_BYTES_32(value)); } +#ifdef HAVE_INT64 + inline uint64 READ_BE_UINT64(const void *ptr) { + return SWAP_BYTES_64(READ_UINT64(ptr)); + } + inline void WRITE_BE_UINT64(void *ptr, uint64 value) { + WRITE_UINT64(ptr, SWAP_BYTES_64(value)); + } +#endif # endif // if defined(SCUMM_NEED_ALIGNMENT) @@ -350,6 +512,17 @@ #define CONSTANT_BE_32(a) ((uint32)(a)) #define CONSTANT_BE_16(a) ((uint16)(a)) +#ifdef HAVE_INT64 + #define READ_BE_UINT64(a) READ_UINT64(a) + #define WRITE_BE_UINT64(a, v) WRITE_UINT64(a, v) + #define FROM_LE_64(a) SWAP_BYTES_64(a) + #define FROM_BE_64(a) ((uint64)(a)) + #define TO_LE_64(a) SWAP_BYTES_64(a) + #define TO_BE_64(a) ((uint64)(a)) + #define CONSTANT_LE_64(a) SWAP_CONSTANT_64(a) + #define CONSTANT_BE_64(a) ((uint64)(a)) +#endif + // if the unaligned load and the byteswap take alot instructions its better to directly read and invert # if defined(SCUMM_NEED_ALIGNMENT) && !defined(__mips__) @@ -373,6 +546,25 @@ b[2] = (uint8)(value >> 16); b[3] = (uint8)(value >> 24); } + +#ifdef HAVE_INT64 + inline uint64 READ_LE_UINT64(const void *ptr) { + const uint8 *b = (const uint8 *)ptr; + return ((uint64)b[7] << 56) | ((uint64)b[6] << 48) | ((uint64)b[5] << 40) | ((uint64)b[4] << 32) | ((uint64)b[3] << 24) | ((uint64)b[2] << 16) | ((uint64)b[1] << 8) | ((uint64)b[0]); + } + inline void WRITE_LE_UINT64(void *ptr, uint64 value) { + uint8 *b = (uint8 *)ptr; + b[0] = (uint8)(value >> 0); + b[1] = (uint8)(value >> 8); + b[2] = (uint8)(value >> 16); + b[3] = (uint8)(value >> 24); + b[4] = (uint8)(value >> 32); + b[5] = (uint8)(value >> 40); + b[6] = (uint8)(value >> 48); + b[7] = (uint8)(value >> 56); + } +#endif + # else inline uint16 READ_LE_UINT16(const void *ptr) { @@ -387,6 +579,14 @@ inline void WRITE_LE_UINT32(void *ptr, uint32 value) { WRITE_UINT32(ptr, SWAP_BYTES_32(value)); } +#ifdef HAVE_INT64 + inline uint64 READ_LE_UINT64(const void *ptr) { + return SWAP_BYTES_64(READ_UINT64(ptr)); + } + inline void WRITE_LE_UINT64(void *ptr, uint64 value) { + WRITE_UINT64(ptr, SWAP_BYTES_64(value)); + } +#endif # endif // if defined(SCUMM_NEED_ALIGNMENT) diff --git a/common/error.cpp b/common/error.cpp index 78178f8e27..53cd8cec55 100644 --- a/common/error.cpp +++ b/common/error.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/error.h b/common/error.h index 7043862eea..3e0a7b556f 100644 --- a/common/error.h +++ b/common/error.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/events.h b/common/events.h index 7366c51d36..484564e3db 100644 --- a/common/events.h +++ b/common/events.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -288,11 +288,14 @@ public: * to the EventDispatcher, thus it will be deleted * with "delete", when EventDispatcher is destroyed. * - * Note there is only one mapper per EventDispatcher - * possible, thus when this method is called twice, - * the former mapper will be destroied. + * @param autoFree Destroy previous mapper [default] + * Normally we allow only one event mapper to exists, + * However Event Recorder must intervent into normal + * event flow without altering its semantics. Thus during + * Event Recorder playback and recording we allow + * two mappers. */ - void registerMapper(EventMapper *mapper); + void registerMapper(EventMapper *mapper, bool autoFree = true); /** * Queries the setup event mapper. @@ -314,7 +317,7 @@ public: /** * Registers a new EventObserver with the Dispatcher. * - * @param listenPools if set, then all pollEvent() calls are passed to observer + * @param listenPolls if set, then all pollEvent() calls are passed to observer * currently it is used by keyMapper */ void registerObserver(EventObserver *obs, uint priority, bool autoFree, bool listenPolls = false); @@ -326,6 +329,7 @@ public: */ void unregisterObserver(EventObserver *obs); private: + bool _autoFreeMapper; EventMapper *_mapper; struct Entry { diff --git a/common/fft.cpp b/common/fft.cpp index a9c58ead9b..27a04abb6a 100644 --- a/common/fft.cpp +++ b/common/fft.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -56,11 +56,19 @@ FFT::FFT(int bits, int inverse) : _bits(bits), _inverse(inverse) { } FFT::~FFT() { + for (int i = 0; i < ARRAYSIZE(_cosTables); i++) { + delete _cosTables[i]; + } + delete[] _revTab; delete[] _expTab; delete[] _tmpBuf; } +const uint16 *FFT::getRevTab() const { + return _revTab; +} + void FFT::permute(Complex *z) { int np = 1 << _bits; diff --git a/common/fft.h b/common/fft.h index ef5f6e95ad..ed66d32b71 100644 --- a/common/fft.h +++ b/common/fft.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -47,6 +47,8 @@ public: FFT(int bits, int inverse); ~FFT(); + const uint16 *getRevTab() const; + /** Do the permutation needed BEFORE calling calc(). */ void permute(Complex *z); diff --git a/common/file.cpp b/common/file.cpp index 7ad6bc2e81..16e6a0df1a 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/file.h b/common/file.h index b6319dfc3c..c055acc57d 100644 --- a/common/file.h +++ b/common/file.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -82,8 +82,7 @@ public: * those cases gracefully. * @note Must not be called if this file already is open (i.e. if isOpen returns true). * - * @param filename the name of the file to open - * @param archive the archive in which to search for the file + * @param node the node to consider. * @return true if file was opened successfully, false otherwise */ virtual bool open(const FSNode &node); diff --git a/common/forbidden.h b/common/forbidden.h index 9050114442..d6fd9c42fe 100644 --- a/common/forbidden.h +++ b/common/forbidden.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/frac.h b/common/frac.h index d402878825..d71d31645b 100644 --- a/common/frac.h +++ b/common/frac.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/fs.cpp b/common/fs.cpp index 19a01074ea..3a7026b1cc 100644 --- a/common/fs.cpp +++ b/common/fs.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #include "common/system.h" diff --git a/common/fs.h b/common/fs.h index fadd672bb1..b5b88ba8cb 100644 --- a/common/fs.h +++ b/common/fs.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_FS_H diff --git a/common/func.h b/common/func.h index a4a80e5406..b58474b2f3 100644 --- a/common/func.h +++ b/common/func.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_FUNC_H diff --git a/common/gui_options.cpp b/common/gui_options.cpp index e463232276..d79bf1b82f 100644 --- a/common/gui_options.cpp +++ b/common/gui_options.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/gui_options.h b/common/gui_options.h index 447fff43ed..78e9cc7199 100644 --- a/common/gui_options.h +++ b/common/gui_options.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/hash-str.h b/common/hash-str.h index 190e6922eb..82af6cca93 100644 --- a/common/hash-str.h +++ b/common/hash-str.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_HASH_STR_H diff --git a/common/hashmap.cpp b/common/hashmap.cpp index e505d1dd25..99840993ce 100644 --- a/common/hashmap.cpp +++ b/common/hashmap.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/hashmap.h b/common/hashmap.h index 42509d67e5..d7ba100571 100644 --- a/common/hashmap.h +++ b/common/hashmap.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/huffman.cpp b/common/huffman.cpp index a8ebe4142a..afb4fa00b6 100644 --- a/common/huffman.cpp +++ b/common/huffman.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/huffman.h b/common/huffman.h index 3b23340b2e..5ba7deca87 100644 --- a/common/huffman.h +++ b/common/huffman.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/iff_container.cpp b/common/iff_container.cpp index 9c6e5f124a..1eee7ad71e 100644 --- a/common/iff_container.cpp +++ b/common/iff_container.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/iff_container.h b/common/iff_container.h index a730930b2c..e684f253b2 100644 --- a/common/iff_container.h +++ b/common/iff_container.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_IFF_CONTAINER_H diff --git a/common/config-file.cpp b/common/ini-file.cpp index 0ce6dcf0c8..7fa17da76c 100644 --- a/common/config-file.cpp +++ b/common/ini-file.cpp @@ -8,19 +8,19 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ -#include "common/config-file.h" +#include "common/ini-file.h" #include "common/file.h" #include "common/savefile.h" #include "common/system.h" @@ -28,24 +28,24 @@ namespace Common { -bool ConfigFile::isValidName(const String &name) { +bool INIFile::isValidName(const String &name) { const char *p = name.c_str(); while (*p && (isAlnum(*p) || *p == '-' || *p == '_' || *p == '.')) p++; return *p == 0; } -ConfigFile::ConfigFile() { +INIFile::INIFile() { } -ConfigFile::~ConfigFile() { +INIFile::~INIFile() { } -void ConfigFile::clear() { +void INIFile::clear() { _sections.clear(); } -bool ConfigFile::loadFromFile(const String &filename) { +bool INIFile::loadFromFile(const String &filename) { File file; if (file.open(filename)) return loadFromStream(file); @@ -53,7 +53,7 @@ bool ConfigFile::loadFromFile(const String &filename) { return false; } -bool ConfigFile::loadFromSaveFile(const char *filename) { +bool INIFile::loadFromSaveFile(const String &filename) { assert(g_system); SaveFileManager *saveFileMan = g_system->getSavefileManager(); SeekableReadStream *loadFile; @@ -67,7 +67,7 @@ bool ConfigFile::loadFromSaveFile(const char *filename) { return status; } -bool ConfigFile::loadFromStream(SeekableReadStream &stream) { +bool INIFile::loadFromStream(SeekableReadStream &stream) { Section section; KeyValue kv; String comment; @@ -112,9 +112,9 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) { p++; if (*p == '\0') - error("ConfigFile::loadFromStream: missing ] in line %d", lineno); + error("INIFile::loadFromStream: missing ] in line %d", lineno); else if (*p != ']') - error("ConfigFile::loadFromStream: Invalid character '%c' occurred in section name in line %d", *p, lineno); + error("INIFile::loadFromStream: Invalid character '%c' occurred in section name in line %d", *p, lineno); // Previous section is finished now, store it. if (!section.name.empty()) @@ -140,7 +140,7 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) { // If no section has been set, this config file is invalid! if (section.name.empty()) { - error("ConfigFile::loadFromStream: Key/value pair found outside a section in line %d", lineno); + error("INIFile::loadFromStream: Key/value pair found outside a section in line %d", lineno); } // Split string at '=' into 'key' and 'value'. First, find the "=" delimeter. @@ -173,7 +173,7 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) { return (!stream.err() || stream.eos()); } -bool ConfigFile::saveToFile(const String &filename) { +bool INIFile::saveToFile(const String &filename) { DumpFile file; if (file.open(filename)) return saveToStream(file); @@ -181,7 +181,7 @@ bool ConfigFile::saveToFile(const String &filename) { return false; } -bool ConfigFile::saveToSaveFile(const char *filename) { +bool INIFile::saveToSaveFile(const String &filename) { assert(g_system); SaveFileManager *saveFileMan = g_system->getSavefileManager(); WriteStream *saveFile; @@ -195,7 +195,7 @@ bool ConfigFile::saveToSaveFile(const char *filename) { return status; } -bool ConfigFile::saveToStream(WriteStream &stream) { +bool INIFile::saveToStream(WriteStream &stream) { for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) { // Write out the section comment, if any if (! i->comment.empty()) { @@ -226,7 +226,7 @@ bool ConfigFile::saveToStream(WriteStream &stream) { return !stream.err(); } -void ConfigFile::addSection(const String §ion) { +void INIFile::addSection(const String §ion) { Section *s = getSection(section); if (s) return; @@ -236,7 +236,7 @@ void ConfigFile::addSection(const String §ion) { _sections.push_back(newSection); } -void ConfigFile::removeSection(const String §ion) { +void INIFile::removeSection(const String §ion) { assert(isValidName(section)); for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) { if (section.equalsIgnoreCase(i->name)) { @@ -246,13 +246,13 @@ void ConfigFile::removeSection(const String §ion) { } } -bool ConfigFile::hasSection(const String §ion) const { +bool INIFile::hasSection(const String §ion) const { assert(isValidName(section)); const Section *s = getSection(section); return s != 0; } -void ConfigFile::renameSection(const String &oldName, const String &newName) { +void INIFile::renameSection(const String &oldName, const String &newName) { assert(isValidName(oldName)); assert(isValidName(newName)); @@ -262,7 +262,7 @@ void ConfigFile::renameSection(const String &oldName, const String &newName) { // HACK: For now we just print a warning, for more info see the TODO // below. if (ns) - warning("ConfigFile::renameSection: Section name \"%s\" already used", newName.c_str()); + warning("INIFile::renameSection: Section name \"%s\" already used", newName.c_str()); else os->name = newName; } @@ -274,7 +274,7 @@ void ConfigFile::renameSection(const String &oldName, const String &newName) { } -bool ConfigFile::hasKey(const String &key, const String §ion) const { +bool INIFile::hasKey(const String &key, const String §ion) const { assert(isValidName(key)); assert(isValidName(section)); @@ -284,7 +284,7 @@ bool ConfigFile::hasKey(const String &key, const String §ion) const { return s->hasKey(key); } -void ConfigFile::removeKey(const String &key, const String §ion) { +void INIFile::removeKey(const String &key, const String §ion) { assert(isValidName(key)); assert(isValidName(section)); @@ -293,7 +293,7 @@ void ConfigFile::removeKey(const String &key, const String §ion) { s->removeKey(key); } -bool ConfigFile::getKey(const String &key, const String §ion, String &value) const { +bool INIFile::getKey(const String &key, const String §ion, String &value) const { assert(isValidName(key)); assert(isValidName(section)); @@ -307,7 +307,7 @@ bool ConfigFile::getKey(const String &key, const String §ion, String &value) return true; } -void ConfigFile::setKey(const String &key, const String §ion, const String &value) { +void INIFile::setKey(const String &key, const String §ion, const String &value) { assert(isValidName(key)); assert(isValidName(section)); // TODO: Verify that value is valid, too. In particular, it shouldn't @@ -329,13 +329,13 @@ void ConfigFile::setKey(const String &key, const String §ion, const String & } } -const ConfigFile::SectionKeyList ConfigFile::getKeys(const String §ion) const { +const INIFile::SectionKeyList INIFile::getKeys(const String §ion) const { const Section *s = getSection(section); return s->getKeys(); } -ConfigFile::Section *ConfigFile::getSection(const String §ion) { +INIFile::Section *INIFile::getSection(const String §ion) { for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) { if (section.equalsIgnoreCase(i->name)) { return &(*i); @@ -344,7 +344,7 @@ ConfigFile::Section *ConfigFile::getSection(const String §ion) { return 0; } -const ConfigFile::Section *ConfigFile::getSection(const String §ion) const { +const INIFile::Section *INIFile::getSection(const String §ion) const { for (List<Section>::const_iterator i = _sections.begin(); i != _sections.end(); ++i) { if (section.equalsIgnoreCase(i->name)) { return &(*i); @@ -353,11 +353,11 @@ const ConfigFile::Section *ConfigFile::getSection(const String §ion) const { return 0; } -bool ConfigFile::Section::hasKey(const String &key) const { +bool INIFile::Section::hasKey(const String &key) const { return getKey(key) != 0; } -const ConfigFile::KeyValue* ConfigFile::Section::getKey(const String &key) const { +const INIFile::KeyValue* INIFile::Section::getKey(const String &key) const { for (List<KeyValue>::const_iterator i = keys.begin(); i != keys.end(); ++i) { if (key.equalsIgnoreCase(i->key)) { return &(*i); @@ -366,7 +366,7 @@ const ConfigFile::KeyValue* ConfigFile::Section::getKey(const String &key) const return 0; } -void ConfigFile::Section::setKey(const String &key, const String &value) { +void INIFile::Section::setKey(const String &key, const String &value) { for (List<KeyValue>::iterator i = keys.begin(); i != keys.end(); ++i) { if (key.equalsIgnoreCase(i->key)) { i->value = value; @@ -380,7 +380,7 @@ void ConfigFile::Section::setKey(const String &key, const String &value) { keys.push_back(newKV); } -void ConfigFile::Section::removeKey(const String &key) { +void INIFile::Section::removeKey(const String &key) { for (List<KeyValue>::iterator i = keys.begin(); i != keys.end(); ++i) { if (key.equalsIgnoreCase(i->key)) { keys.erase(i); diff --git a/common/config-file.h b/common/ini-file.h index 8bba851110..f27a8b9425 100644 --- a/common/config-file.h +++ b/common/ini-file.h @@ -8,20 +8,20 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ -#ifndef COMMON_CONFIG_FILE_H -#define COMMON_CONFIG_FILE_H +#ifndef COMMON_INI_FILE_H +#define COMMON_INI_FILE_H #include "common/hash-str.h" #include "common/list.h" @@ -34,9 +34,6 @@ class WriteStream; /** * This class allows reading/writing INI style config files. - * It is used by the ConfigManager for storage, but can also - * be used by other code if it needs to read/write custom INI - * files. * * Lines starting with a '#' are ignored (i.e. treated as comments). * Some effort is made to preserve comments, though. @@ -47,10 +44,8 @@ class WriteStream; * from/to files, but of course is not appropriate for fast access. * The main reason is that this class is indeed geared toward doing precisely * that! - * If you need fast access to the game config, use higher level APIs, like the - * one provided by ConfigManager. */ -class ConfigFile { +class INIFile { public: struct KeyValue { String key; @@ -60,12 +55,12 @@ public: typedef List<KeyValue> SectionKeyList; - /** A section in a config file. I.e. corresponds to something like this: + /** A section in a ini file. I.e. corresponds to something like this: * [mySection] * key=value * * Comments are also stored, to keep users happy who like editing their - * config files manually. + * ini files manually. */ struct Section { String name; @@ -82,8 +77,8 @@ public: typedef List<Section> SectionList; public: - ConfigFile(); - ~ConfigFile(); + INIFile(); + ~INIFile(); // TODO: Maybe add a copy constructor etc.? @@ -95,14 +90,14 @@ public: */ static bool isValidName(const String &name); - /** Reset everything stored in this config file. */ + /** Reset everything stored in this ini file. */ void clear(); bool loadFromFile(const String &filename); - bool loadFromSaveFile(const char *filename); + bool loadFromSaveFile(const String &filename); bool loadFromStream(SeekableReadStream &stream); bool saveToFile(const String &filename); - bool saveToSaveFile(const char *filename); + bool saveToSaveFile(const String &filename); bool saveToStream(WriteStream &stream); bool hasSection(const String §ion) const; @@ -127,14 +122,6 @@ private: const Section *getSection(const String §ion) const; }; -/* -- ConfigMan owns a config file -- allow direct access to that config file (for the launcher) -- simplify and unify the regular ConfigMan API in exchange - - -*/ - } // End of namespace Common #endif diff --git a/common/installshield_cab.cpp b/common/installshield_cab.cpp index e25d14741a..e9e8586185 100644 --- a/common/installshield_cab.cpp +++ b/common/installshield_cab.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/installshield_cab.h b/common/installshield_cab.h index 7c4f294578..d3c584815e 100644 --- a/common/installshield_cab.h +++ b/common/installshield_cab.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/keyboard.h b/common/keyboard.h index 3262a15c3f..e6e1f5948b 100644 --- a/common/keyboard.h +++ b/common/keyboard.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/language.cpp b/common/language.cpp index 898adf8d0e..97c515b45a 100644 --- a/common/language.cpp +++ b/common/language.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #include "common/language.h" @@ -28,6 +29,7 @@ namespace Common { const LanguageDescription g_languages[] = { { "zh-cn", "zh_CN", "Chinese (China)", ZH_CNA }, { "zh", "zh_TW", "Chinese (Taiwan)", ZH_TWN }, + { "hr", "hr_HR", "Croatian", HR_HRV }, { "cz", "cs_CZ", "Czech", CZ_CZE }, { "nl", "nl_NL", "Dutch", NL_NLD }, { "en", "en", "English", EN_ANY }, // Generic English (when only one game version exist) @@ -38,11 +40,11 @@ const LanguageDescription g_languages[] = { { "gr", "el_GR", "Greek", GR_GRE }, { "he", "he_IL", "Hebrew", HE_ISR }, { "hb", "he_IL", "Hebrew", HE_ISR }, // Deprecated - { "hr", "hr_HR", "Croatian", HR_HRV }, { "hu", "hu_HU", "Hungarian", HU_HUN }, { "it", "it_IT", "Italian", IT_ITA }, { "jp", "ja_JP", "Japanese", JA_JPN }, { "kr", "ko_KR", "Korean", KO_KOR }, + { "lv", "lv_LV", "Latvian", LV_LAT }, { "nb", "nb_NO", "Norwegian Bokm\xE5l", NB_NOR }, // TODO Someone should verify the unix locale { "pl", "pl_PL", "Polish", PL_POL }, { "br", "pt_BR", "Portuguese", PT_BRA }, diff --git a/common/language.h b/common/language.h index 03b9ebaf8e..ac3c7267ab 100644 --- a/common/language.h +++ b/common/language.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_LANGUAGE_H @@ -34,6 +35,7 @@ class String; enum Language { ZH_CNA, ZH_TWN, + HR_HRV, CZ_CZE, NL_NLD, EN_ANY, // Generic English (when only one game version exist) @@ -43,11 +45,11 @@ enum Language { DE_DEU, GR_GRE, HE_ISR, - HR_HRV, HU_HUN, IT_ITA, JA_JPN, KO_KOR, + LV_LAT, NB_NOR, PL_POL, PT_BRA, diff --git a/common/list.h b/common/list.h index 9792042239..1bb4a2a5df 100644 --- a/common/list.h +++ b/common/list.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_LIST_H diff --git a/common/list_intern.h b/common/list_intern.h index fef32fbe1e..b4f347561b 100644 --- a/common/list_intern.h +++ b/common/list_intern.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_LIST_INTERN_H diff --git a/common/localization.cpp b/common/localization.cpp index afd31b8d22..d08583d955 100644 --- a/common/localization.cpp +++ b/common/localization.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #include "common/localization.h" diff --git a/common/localization.h b/common/localization.h index e908485b99..51803279e7 100644 --- a/common/localization.h +++ b/common/localization.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_LOCALIZATION_H @@ -34,7 +35,7 @@ namespace Common { * * @param id Language id * @param keyYes Key code for yes - * @param keyYes Key code for no + * @param keyNo Key code for no */ void getLanguageYesNo(Language id, KeyCode &keyYes, KeyCode &keyNo); @@ -43,7 +44,7 @@ void getLanguageYesNo(Language id, KeyCode &keyYes, KeyCode &keyNo); * language of the ScummVM GUI. * * @param keyYes Key code for yes - * @param keyYes Key code for no + * @param keyNo Key code for no */ void getLanguageYesNo(KeyCode &keyYes, KeyCode &keyNo); diff --git a/common/macresman.cpp b/common/macresman.cpp index 00562f746a..d83bde8fd8 100644 --- a/common/macresman.cpp +++ b/common/macresman.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -102,18 +102,18 @@ String MacResManager::computeResForkMD5AsString(uint32 length) const { return computeStreamMD5AsString(resForkStream, MIN<uint32>(length, _resForkSize)); } -bool MacResManager::open(String filename) { +bool MacResManager::open(const String &fileName) { close(); #ifdef MACOSX // Check the actual fork on a Mac computer - String fullPath = ConfMan.get("path") + "/" + filename + "/..namedfork/rsrc"; + String fullPath = ConfMan.get("path") + "/" + fileName + "/..namedfork/rsrc"; FSNode resFsNode = FSNode(fullPath); if (resFsNode.exists()) { SeekableReadStream *macResForkRawStream = resFsNode.createReadStream(); if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { - _baseFileName = filename; + _baseFileName = fileName; return true; } @@ -123,38 +123,39 @@ bool MacResManager::open(String filename) { File *file = new File(); - // First, let's try to see if the Mac converted name exists - if (file->open(constructAppleDoubleName(filename)) && loadFromAppleDouble(*file)) { - _baseFileName = filename; + // Prefer standalone files first, starting with raw forks + if (file->open(fileName + ".rsrc") && loadFromRawFork(*file)) { + _baseFileName = fileName; return true; } file->close(); - // Check .bin too - if (file->open(filename + ".bin") && loadFromMacBinary(*file)) { - _baseFileName = filename; + // Then try for AppleDouble using Apple's naming + if (file->open(constructAppleDoubleName(fileName)) && loadFromAppleDouble(*file)) { + _baseFileName = fileName; return true; } file->close(); - // Maybe we have a dumped fork? - if (file->open(filename + ".rsrc") && loadFromRawFork(*file)) { - _baseFileName = filename; + // Check .bin for MacBinary next + if (file->open(fileName + ".bin") && loadFromMacBinary(*file)) { + _baseFileName = fileName; return true; } file->close(); - // Fine, what about just the data fork? - if (file->open(filename)) { - _baseFileName = filename; + // As a last resort, see if just the data fork exists + if (file->open(fileName)) { + _baseFileName = fileName; + // FIXME: Is this really needed? if (isMacBinary(*file)) { - file->seek(0, SEEK_SET); + file->seek(0); if (loadFromMacBinary(*file)) return true; } - file->seek(0, SEEK_SET); + file->seek(0); _stream = file; return true; } @@ -165,18 +166,18 @@ bool MacResManager::open(String filename) { return false; } -bool MacResManager::open(FSNode path, String filename) { +bool MacResManager::open(const FSNode &path, const String &fileName) { close(); #ifdef MACOSX // Check the actual fork on a Mac computer - String fullPath = path.getPath() + "/" + filename + "/..namedfork/rsrc"; + String fullPath = path.getPath() + "/" + fileName + "/..namedfork/rsrc"; FSNode resFsNode = FSNode(fullPath); if (resFsNode.exists()) { SeekableReadStream *macResForkRawStream = resFsNode.createReadStream(); if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { - _baseFileName = filename; + _baseFileName = fileName; return true; } @@ -184,52 +185,53 @@ bool MacResManager::open(FSNode path, String filename) { } #endif - // First, let's try to see if the Mac converted name exists - FSNode fsNode = path.getChild(constructAppleDoubleName(filename)); + // Prefer standalone files first, starting with raw forks + FSNode fsNode = path.getChild(fileName + ".rsrc"); if (fsNode.exists() && !fsNode.isDirectory()) { SeekableReadStream *stream = fsNode.createReadStream(); - if (loadFromAppleDouble(*stream)) { - _baseFileName = filename; + if (loadFromRawFork(*stream)) { + _baseFileName = fileName; return true; } delete stream; } - // Check .bin too - fsNode = path.getChild(filename + ".bin"); + // Then try for AppleDouble using Apple's naming + fsNode = path.getChild(constructAppleDoubleName(fileName)); if (fsNode.exists() && !fsNode.isDirectory()) { SeekableReadStream *stream = fsNode.createReadStream(); - if (loadFromMacBinary(*stream)) { - _baseFileName = filename; + if (loadFromAppleDouble(*stream)) { + _baseFileName = fileName; return true; } delete stream; } - // Maybe we have a dumped fork? - fsNode = path.getChild(filename + ".rsrc"); + // Check .bin for MacBinary next + fsNode = path.getChild(fileName + ".bin"); if (fsNode.exists() && !fsNode.isDirectory()) { SeekableReadStream *stream = fsNode.createReadStream(); - if (loadFromRawFork(*stream)) { - _baseFileName = filename; + if (loadFromMacBinary(*stream)) { + _baseFileName = fileName; return true; } delete stream; } - // Fine, what about just the data fork? - fsNode = path.getChild(filename); + // As a last resort, see if just the data fork exists + fsNode = path.getChild(fileName); if (fsNode.exists() && !fsNode.isDirectory()) { SeekableReadStream *stream = fsNode.createReadStream(); - _baseFileName = filename; + _baseFileName = fileName; + // FIXME: Is this really needed? if (isMacBinary(*stream)) { - stream->seek(0, SEEK_SET); + stream->seek(0); if (loadFromMacBinary(*stream)) return true; } - stream->seek(0, SEEK_SET); + stream->seek(0); _stream = stream; return true; } @@ -238,22 +240,22 @@ bool MacResManager::open(FSNode path, String filename) { return false; } -bool MacResManager::exists(const String &filename) { +bool MacResManager::exists(const String &fileName) { // Try the file name by itself - if (Common::File::exists(filename)) + if (File::exists(fileName)) return true; // Try the .rsrc extension - if (Common::File::exists(filename + ".rsrc")) + if (File::exists(fileName + ".rsrc")) return true; // Check if we have a MacBinary file - Common::File tempFile; - if (tempFile.open(filename + ".bin") && isMacBinary(tempFile)) + File tempFile; + if (tempFile.open(fileName + ".bin") && isMacBinary(tempFile)) return true; // Check if we have an AppleDouble file - if (tempFile.open(constructAppleDoubleName(filename)) && tempFile.readUint32BE() == 0x00051607) + if (tempFile.open(constructAppleDoubleName(fileName)) && tempFile.readUint32BE() == 0x00051607) return true; return false; @@ -480,10 +482,10 @@ SeekableReadStream *MacResManager::getResource(uint32 typeID, uint16 resID) { return _stream->readStream(len); } -SeekableReadStream *MacResManager::getResource(const String &filename) { +SeekableReadStream *MacResManager::getResource(const String &fileName) { for (uint32 i = 0; i < _resMap.numTypes; i++) { for (uint32 j = 0; j < _resTypes[i].items; j++) { - if (_resLists[i][j].nameOffset != -1 && filename.equalsIgnoreCase(_resLists[i][j].name)) { + if (_resLists[i][j].nameOffset != -1 && fileName.equalsIgnoreCase(_resLists[i][j].name)) { _stream->seek(_dataOffset + _resLists[i][j].dataOffset); uint32 len = _stream->readUint32BE(); @@ -499,13 +501,13 @@ SeekableReadStream *MacResManager::getResource(const String &filename) { return 0; } -SeekableReadStream *MacResManager::getResource(uint32 typeID, const String &filename) { +SeekableReadStream *MacResManager::getResource(uint32 typeID, const String &fileName) { for (uint32 i = 0; i < _resMap.numTypes; i++) { if (_resTypes[i].id != typeID) continue; for (uint32 j = 0; j < _resTypes[i].items; j++) { - if (_resLists[i][j].nameOffset != -1 && filename.equalsIgnoreCase(_resLists[i][j].name)) { + if (_resLists[i][j].nameOffset != -1 && fileName.equalsIgnoreCase(_resLists[i][j].name)) { _stream->seek(_dataOffset + _resLists[i][j].dataOffset); uint32 len = _stream->readUint32BE(); @@ -574,7 +576,7 @@ void MacResManager::readMap() { } } -Common::String MacResManager::constructAppleDoubleName(Common::String name) { +String MacResManager::constructAppleDoubleName(String name) { // Insert "._" before the last portion of a path name for (int i = name.size() - 1; i >= 0; i--) { if (i == 0) { diff --git a/common/macresman.h b/common/macresman.h index ed74da9cc6..43ec8d8e2c 100644 --- a/common/macresman.h +++ b/common/macresman.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -54,27 +54,32 @@ public: /** * Open a Mac data/resource fork pair. - * @param filename The base file name of the file + * + * This uses SearchMan to find the data/resource forks. This should only be used + * from inside an engine. + * + * @param fileName The base file name of the file * @note This will check for the raw resource fork, MacBinary, and AppleDouble formats. * @return True on success */ - bool open(String filename); + bool open(const String &fileName); /** * Open a Mac data/resource fork pair. + * * @param path The path that holds the forks - * @param filename The base file name of the file + * @param fileName The base file name of the file * @note This will check for the raw resource fork, MacBinary, and AppleDouble formats. * @return True on success */ - bool open(FSNode path, String filename); + bool open(const FSNode &path, const String &fileName); /** * See if a Mac data/resource fork pair exists. - * @param filename The base file name of the file + * @param fileName The base file name of the file * @return True if either a data fork or resource fork with this name exists */ - static bool exists(const String &filename); + static bool exists(const String &fileName); /** * Close the Mac data/resource fork pair. @@ -94,12 +99,6 @@ public: bool hasResFork() const; /** - * Check if the given stream is in the MacBinary format. - * @param stream The stream we're checking - */ - static bool isMacBinary(SeekableReadStream &stream); - - /** * Read resource from the MacBinary file * @param typeID FourCC of the type * @param resID Resource ID to fetch @@ -176,7 +175,13 @@ private: bool loadFromMacBinary(SeekableReadStream &stream); bool loadFromAppleDouble(SeekableReadStream &stream); - static Common::String constructAppleDoubleName(Common::String name); + static String constructAppleDoubleName(String name); + + /** + * Check if the given stream is in the MacBinary format. + * @param stream The stream we're checking + */ + static bool isMacBinary(SeekableReadStream &stream); enum { kResForkNone = 0, diff --git a/common/math.h b/common/math.h index b85ec0d22a..f91f7a2eec 100644 --- a/common/math.h +++ b/common/math.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -52,14 +52,6 @@ #endif #endif -#ifndef M_SQRT1_2 - #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ -#endif - -#ifndef M_PI - #define M_PI 3.14159265358979323846 -#endif - #ifndef FLT_MIN #define FLT_MIN 1E-37 #endif @@ -116,11 +108,11 @@ inline int intLog2(uint32 v) { #endif inline float rad2deg(float rad) { - return rad * 180.0 / M_PI; + return rad * 180.0f / (float)M_PI; } inline float deg2rad(float deg) { - return deg * M_PI / 180.0; + return deg * (float)M_PI / 180.0f; } } // End of namespace Common diff --git a/common/md5.cpp b/common/md5.cpp index 52fe8b8f8d..6a6eeaf048 100644 --- a/common/md5.cpp +++ b/common/md5.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ /* diff --git a/common/md5.h b/common/md5.h index d1be8c8e39..640326efe7 100644 --- a/common/md5.h +++ b/common/md5.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_MD5_H diff --git a/common/memory.h b/common/memory.h index 0e5a97c20b..c32af42ba5 100644 --- a/common/memory.h +++ b/common/memory.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_MEMORY_H diff --git a/common/memorypool.cpp b/common/memorypool.cpp index e3742eeae0..1a9bfe2e29 100644 --- a/common/memorypool.cpp +++ b/common/memorypool.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/memorypool.h b/common/memorypool.h index 1cd725b99d..b84012232c 100644 --- a/common/memorypool.h +++ b/common/memorypool.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/memstream.h b/common/memstream.h index 260fb64d84..5ecc553454 100644 --- a/common/memstream.h +++ b/common/memstream.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -89,8 +89,9 @@ public: */ class MemoryWriteStream : public WriteStream { private: - byte *_ptr; const uint32 _bufSize; +protected: + byte *_ptr; uint32 _pos; bool _err; public: @@ -117,6 +118,40 @@ public: }; /** + * MemoryWriteStream subclass with ability to set stream position indicator. + */ +class SeekableMemoryWriteStream : public MemoryWriteStream { +private: + byte *_ptrOrig; +public: + SeekableMemoryWriteStream(byte *buf, uint32 len) : MemoryWriteStream(buf, len), _ptrOrig(buf) {} + uint32 seek(uint32 offset, int whence = SEEK_SET) { + switch (whence) { + case SEEK_END: + // SEEK_END works just like SEEK_SET, only 'reversed', + // i.e. from the end. + offset = size() + offset; + // Fall through + case SEEK_SET: + _ptr = _ptrOrig + offset; + _pos = offset; + break; + case SEEK_CUR: + _ptr += offset; + _pos += offset; + break; + } + // Post-Condition + if (_pos > size()) { + _pos = size(); + _ptr = _ptrOrig + _pos; + } + return _pos; + } +}; + + +/** * A sort of hybrid between MemoryWriteStream and Array classes. A stream * that grows as it's written to. */ diff --git a/common/module.mk b/common/module.mk index d96b11ee40..67c498df00 100644 --- a/common/module.mk +++ b/common/module.mk @@ -2,7 +2,6 @@ MODULE := common MODULE_OBJS := \ archive.o \ - config-file.o \ config-manager.o \ coroutines.o \ dcl.o \ @@ -10,12 +9,12 @@ MODULE_OBJS := \ error.o \ EventDispatcher.o \ EventMapper.o \ - EventRecorder.o \ file.o \ fs.o \ gui_options.o \ hashmap.o \ iff_container.o \ + ini-file.o \ installshield_cab.o \ language.o \ localization.o \ @@ -36,6 +35,7 @@ MODULE_OBJS := \ translation.o \ unarj.o \ unzip.o \ + ustr.o \ util.o \ winexe.o \ winexe_ne.o \ @@ -51,5 +51,10 @@ MODULE_OBJS += \ rdft.o \ sinetables.o +ifdef ENABLE_EVENTRECORDER +MODULE_OBJS += \ + recorderfile.o +endif + # Include common rules include $(srcdir)/rules.mk diff --git a/common/mutex.cpp b/common/mutex.cpp index f912e79591..a7b34eb334 100644 --- a/common/mutex.cpp +++ b/common/mutex.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/mutex.h b/common/mutex.h index 26f69a3996..6e467cfddf 100644 --- a/common/mutex.h +++ b/common/mutex.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/noncopyable.h b/common/noncopyable.h index 0cbe41388a..24021f42a6 100644 --- a/common/noncopyable.h +++ b/common/noncopyable.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/pack-end.h b/common/pack-end.h index 04633b7635..5fed5e577b 100644 --- a/common/pack-end.h +++ b/common/pack-end.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #if defined(SCUMMVM_USE_PRAGMA_PACK) diff --git a/common/pack-start.h b/common/pack-start.h index 631a6529d3..cfb8968a57 100644 --- a/common/pack-start.h +++ b/common/pack-start.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #if defined(SCUMMVM_USE_PRAGMA_PACK) diff --git a/common/platform.cpp b/common/platform.cpp index 20ed970385..636c1ddb52 100644 --- a/common/platform.cpp +++ b/common/platform.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #include "common/platform.h" diff --git a/common/platform.h b/common/platform.h index ac8772fa94..17a332b851 100644 --- a/common/platform.h +++ b/common/platform.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_PLATFORM_H diff --git a/common/ptr.h b/common/ptr.h index f734ec133f..ebdd77cf3c 100644 --- a/common/ptr.h +++ b/common/ptr.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_PTR_H diff --git a/common/queue.h b/common/queue.h index 3a2d6aad4b..ee14d5b364 100644 --- a/common/queue.h +++ b/common/queue.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_QUEUE_H diff --git a/common/quicktime.cpp b/common/quicktime.cpp index a3efc2b443..76880e1016 100644 --- a/common/quicktime.cpp +++ b/common/quicktime.cpp @@ -368,9 +368,6 @@ int QuickTimeParser::readMVHD(Atom atom) { int QuickTimeParser::readTRAK(Atom atom) { Track *track = new Track(); - if (!track) - return -1; - track->codecType = CODEC_TYPE_MOV_OTHER; track->startTime = 0; // XXX: check _tracks.push_back(track); @@ -532,7 +529,7 @@ int QuickTimeParser::readSTSD(Atom atom) { _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags uint32 entryCount = _fd->readUint32BE(); - track->sampleDescs.resize(entryCount); + track->sampleDescs.reserve(entryCount); for (uint32 i = 0; i < entryCount; i++) { // Parsing Sample description table Atom a = { 0, 0, 0 }; @@ -544,7 +541,7 @@ int QuickTimeParser::readSTSD(Atom atom) { _fd->readUint16BE(); // reserved _fd->readUint16BE(); // index - track->sampleDescs[i] = readSampleDesc(track, format, size - 16); + track->sampleDescs.push_back(readSampleDesc(track, format, size - 16)); debug(0, "size=%d 4CC= %s codec_type=%d", size, tag2str(format), track->codecType); @@ -695,8 +692,14 @@ int QuickTimeParser::readWAVE(Atom atom) { if (atom.size > (1 << 30)) return -1; - if (track->sampleDescs[0]->getCodecTag() == MKTAG('Q', 'D', 'M', '2')) // Read extra data for QDM2 - track->extraData = _fd->readStream(atom.size); + // We should only get here within an stsd atom + if (track->sampleDescs.empty()) + return -1; + + SampleDesc *sampleDesc = track->sampleDescs.back(); + + if (sampleDesc->getCodecTag() == MKTAG('Q', 'D', 'M', '2')) // Read extra data for QDM2 + sampleDesc->_extraData = _fd->readStream(atom.size); else if (atom.size > 8) return readDefault(atom); else @@ -738,6 +741,12 @@ int QuickTimeParser::readESDS(Atom atom) { Track *track = _tracks.back(); + // We should only get here within an stsd atom + if (track->sampleDescs.empty()) + return -1; + + SampleDesc *sampleDesc = track->sampleDescs.back(); + _fd->readUint32BE(); // version + flags byte tag; @@ -753,7 +762,7 @@ int QuickTimeParser::readESDS(Atom atom) { if (tag != kMP4DecConfigDescTag) return 0; - track->objectTypeMP4 = _fd->readByte(); + sampleDesc->_objectTypeMP4 = _fd->readByte(); _fd->readByte(); // stream type _fd->readUint16BE(); _fd->readByte(); // buffer size _fd->readUint32BE(); // max bitrate @@ -764,9 +773,9 @@ int QuickTimeParser::readESDS(Atom atom) { if (tag != kMP4DecSpecificDescTag) return 0; - track->extraData = _fd->readStream(length); + sampleDesc->_extraData = _fd->readStream(length); - debug(0, "MPEG-4 object type = %02x", track->objectTypeMP4); + debug(0, "MPEG-4 object type = %02x", sampleDesc->_objectTypeMP4); return 0; } @@ -776,8 +785,14 @@ int QuickTimeParser::readSMI(Atom atom) { Track *track = _tracks.back(); + // We should only get here within an stsd atom + if (track->sampleDescs.empty()) + return -1; + + SampleDesc *sampleDesc = track->sampleDescs.back(); + // This atom just contains SVQ3 extra data - track->extraData = _fd->readStream(atom.size); + sampleDesc->_extraData = _fd->readStream(atom.size); return 0; } @@ -797,6 +812,12 @@ void QuickTimeParser::close() { QuickTimeParser::SampleDesc::SampleDesc(Track *parentTrack, uint32 codecTag) { _parentTrack = parentTrack; _codecTag = codecTag; + _extraData = 0; + _objectTypeMP4 = 0; +} + +QuickTimeParser::SampleDesc::~SampleDesc() { + delete _extraData; } QuickTimeParser::Track::Track() { @@ -817,11 +838,9 @@ QuickTimeParser::Track::Track() { codecType = CODEC_TYPE_MOV_OTHER; editCount = 0; editList = 0; - extraData = 0; frameCount = 0; duration = 0; startTime = 0; - objectTypeMP4 = 0; mediaDuration = 0; } @@ -832,7 +851,6 @@ QuickTimeParser::Track::~Track() { delete[] sampleSizes; delete[] keyframes; delete[] editList; - delete extraData; for (uint32 i = 0; i < sampleDescs.size(); i++) delete sampleDescs[i]; diff --git a/common/quicktime.h b/common/quicktime.h index caa92578b1..f74d1ed0d9 100644 --- a/common/quicktime.h +++ b/common/quicktime.h @@ -74,7 +74,7 @@ public: /** * Set the beginning offset of the video so we can modify the offsets in the stco * atom of videos inside the Mohawk archives - * @param the beginning offset of the video + * @param offset the beginning offset of the video */ void setChunkBeginOffset(uint32 offset) { _beginOffset = offset; } @@ -108,10 +108,13 @@ protected: class SampleDesc { public: SampleDesc(Track *parentTrack, uint32 codecTag); - virtual ~SampleDesc() {} + virtual ~SampleDesc(); uint32 getCodecTag() const { return _codecTag; } + SeekableReadStream *_extraData; + byte _objectTypeMP4; + protected: Track *_parentTrack; uint32 _codecTag; @@ -150,16 +153,12 @@ protected: uint32 editCount; EditListEntry *editList; - SeekableReadStream *extraData; - uint32 frameCount; uint32 duration; uint32 mediaDuration; uint32 startTime; Rational scaleFactorX; Rational scaleFactorY; - - byte objectTypeMP4; }; virtual SampleDesc *readSampleDesc(Track *track, uint32 format, uint32 descSize) = 0; diff --git a/common/random.cpp b/common/random.cpp index fd75534c44..86bde77e82 100644 --- a/common/random.cpp +++ b/common/random.cpp @@ -17,11 +17,12 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #include "common/random.h" #include "common/system.h" -#include "common/EventRecorder.h" +#include "gui/EventRecorder.h" namespace Common { @@ -30,13 +31,12 @@ RandomSource::RandomSource(const String &name) { // Use system time as RNG seed. Normally not a good idea, if you are using // a RNG for security purposes, but good enough for our purposes. assert(g_system); - uint32 seed = g_system->getMillis(); - setSeed(seed); - // Register this random source with the event recorder. This may end - // up querying or resetting the current seed, so we must call it - // *after* the initial seed has been set. - g_eventRec.registerRandomSource(*this, name); +#ifdef ENABLE_EVENTRECORDER + setSeed(g_eventRec.getRandomSeed(name)); +#else + setSeed(g_system->getMillis()); +#endif } void RandomSource::setSeed(uint32 seed) { diff --git a/common/random.h b/common/random.h index c8aec58946..48cde26dc5 100644 --- a/common/random.h +++ b/common/random.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_RANDOM_H diff --git a/common/rational.cpp b/common/rational.cpp index f5495da3a9..90e44576a7 100644 --- a/common/rational.cpp +++ b/common/rational.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #include "common/debug.h" diff --git a/common/rational.h b/common/rational.h index 8270d2194e..55fb361774 100644 --- a/common/rational.h +++ b/common/rational.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_RATIONAL_H diff --git a/common/rdft.cpp b/common/rdft.cpp index bfd6818fbd..89d39112e6 100644 --- a/common/rdft.cpp +++ b/common/rdft.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -29,7 +29,7 @@ namespace Common { RDFT::RDFT(int bits, TransformType trans) : _bits(bits), _sin(bits), _cos(bits), _fft(0) { - assert ((_bits >= 4) && (_bits <= 16)); + assert((_bits >= 4) && (_bits <= 16)); _inverse = trans == IDFT_C2R || trans == DFT_C2R; _signConvention = trans == IDFT_R2C || trans == DFT_C2R ? 1 : -1; @@ -49,12 +49,12 @@ RDFT::~RDFT() { void RDFT::calc(float *data) { const int n = 1 << _bits; - const float k1 = 0.5; - const float k2 = 0.5 - _inverse; + const float k1 = 0.5f; + const float k2 = 0.5f - _inverse; if (!_inverse) { - _fft->permute((Complex *) data); - _fft->calc ((Complex *) data); + _fft->permute((Complex *)data); + _fft->calc ((Complex *)data); } Complex ev, od; @@ -91,8 +91,8 @@ void RDFT::calc(float *data) { data[0] *= k1; data[1] *= k1; - _fft->permute((Complex *) data); - _fft->calc ((Complex *) data); + _fft->permute((Complex *)data); + _fft->calc ((Complex *)data); } } diff --git a/common/rdft.h b/common/rdft.h index 76e95c363a..ae06c72ef8 100644 --- a/common/rdft.h +++ b/common/rdft.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/recorderfile.cpp b/common/recorderfile.cpp new file mode 100644 index 0000000000..71f8272b44 --- /dev/null +++ b/common/recorderfile.cpp @@ -0,0 +1,716 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/system.h" +#include "gui/EventRecorder.h" +#include "common/md5.h" +#include "common/recorderfile.h" +#include "common/savefile.h" +#include "common/bufferedstream.h" +#include "graphics/thumbnail.h" +#include "graphics/surface.h" +#include "graphics/scaler.h" + +#define RECORD_VERSION 1 + +namespace Common { + +PlaybackFile::PlaybackFile() : _tmpRecordFile(_tmpBuffer, kRecordBuffSize), _tmpPlaybackFile(_tmpBuffer, kRecordBuffSize) { + _readStream = NULL; + _writeStream = NULL; + _screenshotsFile = NULL; + _mode = kClosed; + + _recordFile = 0; + _headerDumped = false; + _recordCount = 0; + _eventsSize = 0; + memset(_tmpBuffer, 1, kRecordBuffSize); + + _playbackParseState = kFileStateCheckFormat; +} + +PlaybackFile::~PlaybackFile() { + close(); +} + +bool PlaybackFile::openWrite(const String &fileName) { + close(); + _header.fileName = fileName; + _writeStream = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving(fileName), 128 * 1024); + _headerDumped = false; + _recordCount = 0; + if (_writeStream == NULL) { + return false; + } + _mode = kWrite; + return true; +} + +bool PlaybackFile::openRead(const String &fileName) { + close(); + _header.fileName = fileName; + _eventsSize = 0; + _tmpPlaybackFile.seek(0); + _readStream = wrapBufferedSeekableReadStream(g_system->getSavefileManager()->openForLoading(fileName), 128 * 1024, DisposeAfterUse::YES); + if (_readStream == NULL) { + debugC(1, kDebugLevelEventRec, "playback:action=\"Load File\" result=fail reason=\"file %s not found\"", fileName.c_str()); + return false; + } + if (!parseHeader()) { + debugC(1, kDebugLevelEventRec, "playback:action=\"Load File\" result=fail reason=\"header parsing failed\""); + return false; + } + _screenshotsFile = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving("screenshots.bin"), 128 * 1024); + debugC(1, kDebugLevelEventRec, "playback:action=\"Load File\" result=success"); + _mode = kRead; + return true; +} + +void PlaybackFile::close() { + delete _readStream; + _readStream = NULL; + if (_writeStream != NULL) { + dumpRecordsToFile(); + _writeStream->finalize(); + delete _writeStream; + _writeStream = NULL; + updateHeader(); + } + if (_screenshotsFile != NULL) { + _screenshotsFile->finalize(); + delete _screenshotsFile; + _screenshotsFile = NULL; + } + for (HashMap<String, SaveFileBuffer>::iterator i = _header.saveFiles.begin(); i != _header.saveFiles.end(); ++i) { + free(i->_value.buffer); + } + _header.saveFiles.clear(); + _mode = kClosed; +} + +bool PlaybackFile::parseHeader() { + PlaybackFileHeader result; + ChunkHeader nextChunk; + _playbackParseState = kFileStateCheckFormat; + if (!readChunkHeader(nextChunk)) { + _playbackParseState = kFileStateError; + return false; + } + while ((_playbackParseState != kFileStateDone) && (_playbackParseState != kFileStateError)) { + if (processChunk(nextChunk)) { + if (!readChunkHeader(nextChunk)) { + warning("Error in header parsing"); + _playbackParseState = kFileStateError; + } + } + } + return _playbackParseState == kFileStateDone; +} + +bool PlaybackFile::checkPlaybackFileVersion() { + uint32 version; + version = _readStream->readUint32LE(); + if (version != RECORD_VERSION) { + warning("Incorrect playback file version. Expected version %d, but got %d.", RECORD_VERSION, version); + return false; + } + return true; +} + + +String PlaybackFile::readString(int len) { + String result; + char buf[50]; + int readSize = 49; + while (len > 0) { + if (len <= 49) { + readSize = len; + } + _readStream->read(buf, readSize); + buf[readSize] = 0; + result += buf; + len -= readSize; + } + return result; +} + +bool PlaybackFile::readChunkHeader(PlaybackFile::ChunkHeader &nextChunk) { + nextChunk.id = (FileTag)_readStream->readUint32LE(); + nextChunk.len = _readStream->readUint32LE(); + return !_readStream->err() && !_readStream->eos(); +} + +bool PlaybackFile::processChunk(ChunkHeader &nextChunk) { + switch (_playbackParseState) { + case kFileStateCheckFormat: + if (nextChunk.id == kFormatIdTag) { + _playbackParseState = kFileStateCheckVersion; + } else { + warning("Unknown playback file signature"); + _playbackParseState = kFileStateError; + } + break; + case kFileStateCheckVersion: + if ((nextChunk.id == kVersionTag) && checkPlaybackFileVersion()) { + _playbackParseState = kFileStateSelectSection; + } else { + _playbackParseState = kFileStateError; + } + break; + case kFileStateSelectSection: + switch (nextChunk.id) { + case kHeaderSectionTag: + _playbackParseState = kFileStateProcessHeader; + break; + case kHashSectionTag: + _playbackParseState = kFileStateProcessHash; + break; + case kRandomSectionTag: + _playbackParseState = kFileStateProcessRandom; + break; + case kEventTag: + case kScreenShotTag: + _readStream->seek(-8, SEEK_CUR); + _playbackParseState = kFileStateDone; + return false; + case kSaveTag: + _playbackParseState = kFileStateProcessSave; + break; + case kSettingsSectionTag: + _playbackParseState = kFileStateProcessSettings; + warning("Loading record header"); + break; + default: + _readStream->skip(nextChunk.len); + break; + } + break; + case kFileStateProcessSave: + if (nextChunk.id == kSaveRecordTag) { + readSaveRecord(); + } else { + _playbackParseState = kFileStateSelectSection; + return false; + } + break; + case kFileStateProcessHeader: + switch (nextChunk.id) { + case kAuthorTag: + _header.author = readString(nextChunk.len); + break; + case kCommentsTag: + _header.notes = readString(nextChunk.len); + break; + case kNameTag: + _header.name = readString(nextChunk.len); + break; + default: + _playbackParseState = kFileStateSelectSection; + return false; + } + break; + case kFileStateProcessHash: + if (nextChunk.id == kHashRecordTag) { + readHashMap(nextChunk); + } else { + _playbackParseState = kFileStateSelectSection; + return false; + } + break; + case kFileStateProcessRandom: + if (nextChunk.id == kRandomRecordTag) { + processRndSeedRecord(nextChunk); + } else { + _playbackParseState = kFileStateSelectSection; + return false; + } + break; + case kFileStateProcessSettings: + if (nextChunk.id == kSettingsRecordTag) { + if (!processSettingsRecord()) { + _playbackParseState = kFileStateError; + return false; + } + } else { + _playbackParseState = kFileStateSelectSection; + return false; + } + break; + default: + return false; + } + return true; +} + +void PlaybackFile::returnToChunkHeader() { + _readStream->seek(-8, SEEK_CUR); +} + +void PlaybackFile::readHashMap(ChunkHeader chunk) { + String hashName = readString(chunk.len - 32); + String hashMd5 = readString(32); + _header.hashRecords[hashName] = hashMd5; +} + +void PlaybackFile::processRndSeedRecord(ChunkHeader chunk) { + String randomSourceName = readString(chunk.len - 4); + uint32 randomSourceSeed = _readStream->readUint32LE(); + _header.randomSourceRecords[randomSourceName] = randomSourceSeed; +} + +bool PlaybackFile::processSettingsRecord() { + ChunkHeader keyChunk; + if (!readChunkHeader(keyChunk) || (keyChunk.id != kSettingsRecordKeyTag)) { + warning("Invalid format of settings section"); + return false; + } + String key = readString(keyChunk.len); + ChunkHeader valueChunk; + if (!readChunkHeader(valueChunk) || (valueChunk.id != kSettingsRecordValueTag)) { + warning("Invalid format of settings section"); + return false; + } + String value = readString(valueChunk.len); + _header.settingsRecords[key] = value; + return true; +} + + +bool PlaybackFile::readSaveRecord() { + ChunkHeader fileNameChunk; + if (!readChunkHeader(fileNameChunk) || (fileNameChunk.id != kSaveRecordNameTag)) { + warning("Invalid format of save section"); + return false; + } + String fileName = readString(fileNameChunk.len); + ChunkHeader saveBufferChunk; + if (!readChunkHeader(saveBufferChunk) || (saveBufferChunk.id != kSaveRecordBufferTag)) { + warning("Invalid format of save section"); + return false; + } + SaveFileBuffer buf; + buf.size = saveBufferChunk.len; + buf.buffer = (byte *)malloc(saveBufferChunk.len); + _readStream->read(buf.buffer, buf.size); + _header.saveFiles[fileName] = buf; + debugC(1, kDebugLevelEventRec, "playback:action=\"Load save file\" filename=%s len=%d", fileName.c_str(), buf.size); + return true; +} + + + +RecorderEvent PlaybackFile::getNextEvent() { + assert(_mode == kRead); + if (isEventsBufferEmpty()) { + PlaybackFile::ChunkHeader header; + header.id = kFormatIdTag; + while (header.id != kEventTag) { + if (!readChunkHeader(header) || _readStream->eos()) { + break; + } + switch (header.id) { + case kEventTag: + readEventsToBuffer(header.len); + break; + case kScreenShotTag: + _readStream->seek(-4, SEEK_CUR); + header.len = _readStream->readUint32BE(); + _readStream->skip(header.len-8); + break; + case kMD5Tag: + checkRecordedMD5(); + break; + default: + _readStream->skip(header.len); + break; + } + } + } + RecorderEvent result; + readEvent(result); + return result; +} + +bool PlaybackFile::isEventsBufferEmpty() { + return (uint32)_tmpPlaybackFile.pos() == _eventsSize; +} + +void PlaybackFile::readEvent(RecorderEvent& event) { + event.recordedtype = (RecorderEventType)_tmpPlaybackFile.readByte(); + switch (event.recordedtype) { + case kRecorderEventTypeTimer: + event.time = _tmpPlaybackFile.readUint32LE(); + break; + case kRecorderEventTypeNormal: + event.type = (EventType)_tmpPlaybackFile.readUint32LE(); + switch (event.type) { + case EVENT_KEYDOWN: + case EVENT_KEYUP: + event.time = _tmpPlaybackFile.readUint32LE(); + event.kbd.keycode = (KeyCode)_tmpPlaybackFile.readSint32LE(); + event.kbd.ascii = _tmpPlaybackFile.readUint16LE(); + event.kbd.flags = _tmpPlaybackFile.readByte(); + break; + case EVENT_MOUSEMOVE: + case EVENT_LBUTTONDOWN: + case EVENT_LBUTTONUP: + case EVENT_RBUTTONDOWN: + case EVENT_RBUTTONUP: + case EVENT_WHEELUP: + case EVENT_WHEELDOWN: + case EVENT_MBUTTONDOWN: + case EVENT_MBUTTONUP: + event.time = _tmpPlaybackFile.readUint32LE(); + event.mouse.x = _tmpPlaybackFile.readSint16LE(); + event.mouse.y = _tmpPlaybackFile.readSint16LE(); + break; + default: + event.time = _tmpPlaybackFile.readUint32LE(); + break; + } + break; + } + event.synthetic = true; +} + +void PlaybackFile::readEventsToBuffer(uint32 size) { + _readStream->read(_tmpBuffer, size); + _tmpPlaybackFile.seek(0); + _eventsSize = size; +} + +void PlaybackFile::saveScreenShot(Graphics::Surface &screen, byte md5[16]) { + dumpRecordsToFile(); + _writeStream->writeUint32LE(kMD5Tag); + _writeStream->writeUint32LE(16); + _writeStream->write(md5, 16); + Graphics::saveThumbnail(*_writeStream, screen); +} + +void PlaybackFile::dumpRecordsToFile() { + if (!_headerDumped) { + dumpHeaderToFile(); + _headerDumped = true; + } + if (_recordCount == 0) { + return; + } + _writeStream->writeUint32LE(kEventTag); + _writeStream->writeUint32LE(_tmpRecordFile.pos()); + _writeStream->write(_tmpBuffer, _tmpRecordFile.pos()); + _tmpRecordFile.seek(0); + _recordCount = 0; +} + +void PlaybackFile::dumpHeaderToFile() { + _writeStream->writeUint32LE(kFormatIdTag); + // Specify size for first tag as NULL since we cannot calculate + // size of the file at time of the header dumping + _writeStream->writeUint32LE(0); + _writeStream->writeUint32LE(kVersionTag); + _writeStream->writeUint32LE(4); + _writeStream->writeUint32LE(RECORD_VERSION); + writeHeaderSection(); + writeGameHash(); + writeRandomRecords(); + writeGameSettings(); + writeSaveFilesSection(); +} + +void PlaybackFile::writeHeaderSection() { + uint32 headerSize = 0; + if (!_header.author.empty()) { + headerSize = _header.author.size() + 8; + } + if (!_header.notes.empty()) { + headerSize += _header.notes.size() + 8; + } + if (!_header.name.empty()) { + headerSize += _header.name.size() + 8; + } + if (headerSize == 0) { + return; + } + _writeStream->writeUint32LE(kHeaderSectionTag); + _writeStream->writeUint32LE(headerSize); + if (!_header.author.empty()) { + _writeStream->writeUint32LE(kAuthorTag); + _writeStream->writeUint32LE(_header.author.size()); + _writeStream->writeString(_header.author); + } + if (!_header.notes.empty()) { + _writeStream->writeUint32LE(kCommentsTag); + _writeStream->writeUint32LE(_header.notes.size()); + _writeStream->writeString(_header.notes); + } + if (!_header.name.empty()) { + _writeStream->writeUint32LE(kNameTag); + _writeStream->writeUint32LE(_header.name.size()); + _writeStream->writeString(_header.name); + } +} + +void PlaybackFile::writeGameHash() { + uint32 hashSectionSize = 0; + for (StringMap::iterator i = _header.hashRecords.begin(); i != _header.hashRecords.end(); ++i) { + hashSectionSize = hashSectionSize + i->_key.size() + i->_value.size() + 8; + } + if (_header.hashRecords.size() == 0) { + return; + } + _writeStream->writeUint32LE(kHashSectionTag); + _writeStream->writeUint32LE(hashSectionSize); + for (StringMap::iterator i = _header.hashRecords.begin(); i != _header.hashRecords.end(); ++i) { + _writeStream->writeUint32LE(kHashRecordTag); + _writeStream->writeUint32LE(i->_key.size() + i->_value.size()); + _writeStream->writeString(i->_key); + _writeStream->writeString(i->_value); + } +} + +void PlaybackFile::writeRandomRecords() { + uint32 randomSectionSize = 0; + for (RandomSeedsDictionary::iterator i = _header.randomSourceRecords.begin(); i != _header.randomSourceRecords.end(); ++i) { + randomSectionSize = randomSectionSize + i->_key.size() + 12; + } + if (_header.randomSourceRecords.size() == 0) { + return; + } + _writeStream->writeUint32LE(kRandomSectionTag); + _writeStream->writeUint32LE(randomSectionSize); + for (RandomSeedsDictionary::iterator i = _header.randomSourceRecords.begin(); i != _header.randomSourceRecords.end(); ++i) { + _writeStream->writeUint32LE(kRandomRecordTag); + _writeStream->writeUint32LE(i->_key.size() + 4); + _writeStream->writeString(i->_key); + _writeStream->writeUint32LE(i->_value); + } +} + +void PlaybackFile::writeEvent(const RecorderEvent &event) { + assert(_mode == kWrite); + _recordCount++; + _tmpRecordFile.writeByte(event.recordedtype); + switch (event.recordedtype) { + case kRecorderEventTypeTimer: + _tmpRecordFile.writeUint32LE(event.time); + break; + case kRecorderEventTypeNormal: + _tmpRecordFile.writeUint32LE((uint32)event.type); + switch(event.type) { + case EVENT_KEYDOWN: + case EVENT_KEYUP: + _tmpRecordFile.writeUint32LE(event.time); + _tmpRecordFile.writeSint32LE(event.kbd.keycode); + _tmpRecordFile.writeUint16LE(event.kbd.ascii); + _tmpRecordFile.writeByte(event.kbd.flags); + break; + case EVENT_MOUSEMOVE: + case EVENT_LBUTTONDOWN: + case EVENT_LBUTTONUP: + case EVENT_RBUTTONDOWN: + case EVENT_RBUTTONUP: + case EVENT_WHEELUP: + case EVENT_WHEELDOWN: + case EVENT_MBUTTONDOWN: + case EVENT_MBUTTONUP: + _tmpRecordFile.writeUint32LE(event.time); + _tmpRecordFile.writeSint16LE(event.mouse.x); + _tmpRecordFile.writeSint16LE(event.mouse.y); + break; + default: + _tmpRecordFile.writeUint32LE(event.time); + break; + } + break; + } + if (_recordCount == kMaxBufferedRecords) { + dumpRecordsToFile(); + } +} + +void PlaybackFile::writeGameSettings() { + _writeStream->writeUint32LE(kSettingsSectionTag); + uint32 settingsSectionSize = 0; + for (StringMap::iterator i = _header.settingsRecords.begin(); i != _header.settingsRecords.end(); ++i) { + settingsSectionSize += i->_key.size() + i->_value.size() + 24; + } + _writeStream->writeUint32LE(settingsSectionSize); + for (StringMap::iterator i = _header.settingsRecords.begin(); i != _header.settingsRecords.end(); ++i) { + _writeStream->writeUint32LE(kSettingsRecordTag); + _writeStream->writeUint32LE(i->_key.size() + i->_value.size() + 16); + _writeStream->writeUint32LE(kSettingsRecordKeyTag); + _writeStream->writeUint32LE(i->_key.size()); + _writeStream->writeString(i->_key); + _writeStream->writeUint32LE(kSettingsRecordValueTag); + _writeStream->writeUint32LE(i->_value.size()); + _writeStream->writeString(i->_value); + } +} + +int PlaybackFile::getScreensCount() { + if (_mode != kRead) { + return 0; + } + _readStream->seek(0); + int result = 0; + while (skipToNextScreenshot()) { + uint32 size = _readStream->readUint32BE(); + _readStream->skip(size-8); + ++result; + } + return result; +} + +bool PlaybackFile::skipToNextScreenshot() { + while (true) { + FileTag id = (FileTag)_readStream->readUint32LE(); + if (_readStream->eos()) { + break; + } + if (id == kScreenShotTag) { + return true; + } + else { + uint32 size = _readStream->readUint32LE(); + _readStream->skip(size); + } + } + return false; +} + +Graphics::Surface *PlaybackFile::getScreenShot(int number) { + if (_mode != kRead) { + return NULL; + } + _readStream->seek(0); + int screenCount = 1; + while (skipToNextScreenshot()) { + if (screenCount == number) { + screenCount++; + _readStream->seek(-4, SEEK_CUR); + return Graphics::loadThumbnail(*_readStream); + } else { + uint32 size = _readStream->readUint32BE(); + _readStream->skip(size-8); + screenCount++; + } + } + return NULL; +} + +void PlaybackFile::updateHeader() { + if (_mode == kWrite) { + _readStream = g_system->getSavefileManager()->openForLoading(_header.fileName); + } + _readStream->seek(0); + skipHeader(); + String tmpFilename = "_" + _header.fileName; + _writeStream = g_system->getSavefileManager()->openForSaving(tmpFilename); + dumpHeaderToFile(); + uint32 readedSize = 0; + do { + readedSize = _readStream->read(_tmpBuffer, kRecordBuffSize); + _writeStream->write(_tmpBuffer, readedSize); + } while (readedSize != 0); + delete _writeStream; + _writeStream = NULL; + delete _readStream; + _readStream = NULL; + g_system->getSavefileManager()->removeSavefile(_header.fileName); + g_system->getSavefileManager()->renameSavefile(tmpFilename, _header.fileName); + if (_mode == kRead) { + openRead(_header.fileName); + } +} + +void PlaybackFile::skipHeader() { + while (true) { + uint32 id = _readStream->readUint32LE(); + if (_readStream->eos()) { + break; + } + if ((id == kScreenShotTag) || (id == kEventTag) || (id == kMD5Tag)) { + _readStream->seek(-4, SEEK_CUR); + return; + } + else { + uint32 size = _readStream->readUint32LE(); + _readStream->skip(size); + } + } +} + +void PlaybackFile::addSaveFile(const String &fileName, InSaveFile *saveStream) { + uint oldPos = saveStream->pos(); + saveStream->seek(0); + _header.saveFiles[fileName].buffer = (byte *)malloc(saveStream->size()); + _header.saveFiles[fileName].size = saveStream->size(); + saveStream->read(_header.saveFiles[fileName].buffer, saveStream->size()); + saveStream->seek(oldPos); +} + +void PlaybackFile::writeSaveFilesSection() { + uint size = 0; + for (HashMap<String, SaveFileBuffer>::iterator i = _header.saveFiles.begin(); i != _header.saveFiles.end(); ++i) { + size += i->_value.size + i->_key.size() + 24; + } + if (size == 0) { + return; + } + _writeStream->writeSint32LE(kSaveTag); + _writeStream->writeSint32LE(size); + for (HashMap<String, SaveFileBuffer>::iterator i = _header.saveFiles.begin(); i != _header.saveFiles.end(); ++i) { + _writeStream->writeSint32LE(kSaveRecordTag); + _writeStream->writeSint32LE(i->_key.size() + i->_value.size + 16); + _writeStream->writeSint32LE(kSaveRecordNameTag); + _writeStream->writeSint32LE(i->_key.size()); + _writeStream->writeString(i->_key); + _writeStream->writeSint32LE(kSaveRecordBufferTag); + _writeStream->writeSint32LE(i->_value.size); + _writeStream->write(i->_value.buffer, i->_value.size); + } +} + + +void PlaybackFile::checkRecordedMD5() { + uint8 currentMD5[16]; + uint8 savedMD5[16]; + Graphics::Surface screen; + _readStream->read(savedMD5, 16); + if (!g_eventRec.grabScreenAndComputeMD5(screen, currentMD5)) { + return; + } + uint32 seconds = g_system->getMillis(true) / 1000; + String screenTime = String::format("%.2d:%.2d:%.2d", seconds / 3600 % 24, seconds / 60 % 60, seconds % 60); + if (memcmp(savedMD5, currentMD5, 16) != 0) { + debugC(1, kDebugLevelEventRec, "playback:action=\"Check screenshot\" time=%s result = fail", screenTime.c_str()); + warning("Recorded and current screenshots are different"); + } else { + debugC(1, kDebugLevelEventRec, "playback:action=\"Check screenshot\" time=%s result = success", screenTime.c_str()); + } + Graphics::saveThumbnail(*_screenshotsFile, screen); + screen.free(); +} + + +} diff --git a/common/recorderfile.h b/common/recorderfile.h new file mode 100644 index 0000000000..d34a442604 --- /dev/null +++ b/common/recorderfile.h @@ -0,0 +1,180 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef COMMON_RECORDERFILE_H +#define COMMON_RECORDERFILE_H + +#include "common/scummsys.h" +#include "common/events.h" +#include "common/mutex.h" +#include "common/memstream.h" +#include "common/config-manager.h" +#include "common/savefile.h" + +//capacity of records buffer +#define kMaxBufferedRecords 10000 +#define kRecordBuffSize sizeof(RecorderEvent) * kMaxBufferedRecords + +namespace Common { + +enum RecorderEventType { + kRecorderEventTypeNormal = 0, + kRecorderEventTypeTimer = 1 +}; + +struct RecorderEvent : Event { + RecorderEventType recordedtype; + uint32 time; +}; + + + +class PlaybackFile { + typedef HashMap<String, uint32, IgnoreCase_Hash, IgnoreCase_EqualTo> RandomSeedsDictionary; + enum fileMode { + kRead = 0, + kWrite = 1, + kClosed = 2 + }; + enum PlaybackFileState { + kFileStateCheckFormat, + kFileStateCheckVersion, + kFileStateProcessHash, + kFileStateProcessHeader, + kFileStateProcessRandom, + kFileStateSelectSection, + kFileStateProcessSettings, + kFileStateProcessSave, + kFileStateDone, + kFileStateError + }; + enum FileTag { + kFormatIdTag = MKTAG('P','B','C','K'), + kVersionTag = MKTAG('V','E','R','S'), + kHeaderSectionTag = MKTAG('H','E','A','D'), + kHashSectionTag = MKTAG('H','A','S','H'), + kRandomSectionTag = MKTAG('R','A','N','D'), + kEventTag = MKTAG('E','V','N','T'), + kScreenShotTag = MKTAG('B','M','H','T'), + kSettingsSectionTag = MKTAG('S','E','T','T'), + kAuthorTag = MKTAG('H','A','U','T'), + kCommentsTag = MKTAG('H','C','M','T'), + kNameTag = MKTAG('H','N','A','M'), + kHashRecordTag = MKTAG('H','R','C','D'), + kRandomRecordTag = MKTAG('R','R','C','D'), + kSettingsRecordTag = MKTAG('S','R','E','C'), + kSettingsRecordKeyTag = MKTAG('S','K','E','Y'), + kSettingsRecordValueTag = MKTAG('S','V','A','L'), + kSaveTag = MKTAG('S','A','V','E'), + kSaveRecordTag = MKTAG('R','S','A','V'), + kSaveRecordNameTag = MKTAG('S','N','A','M'), + kSaveRecordBufferTag = MKTAG('S','B','U','F'), + kMD5Tag = MKTAG('M','D','5',' ') + }; + struct ChunkHeader { + FileTag id; + uint32 len; + }; +public: + struct SaveFileBuffer { + byte *buffer; + uint32 size; + }; + struct PlaybackFileHeader { + String fileName; + String author; + String name; + String notes; + String description; + StringMap hashRecords; + StringMap settingsRecords; + HashMap<String, SaveFileBuffer> saveFiles; + RandomSeedsDictionary randomSourceRecords; + }; + PlaybackFile(); + ~PlaybackFile(); + + bool openWrite(const String &fileName); + bool openRead(const String &fileName); + void close(); + + RecorderEvent getNextEvent(); + void writeEvent(const RecorderEvent &event); + + void saveScreenShot(Graphics::Surface &screen, byte md5[16]); + Graphics::Surface *getScreenShot(int number); + int getScreensCount(); + + bool isEventsBufferEmpty(); + PlaybackFileHeader &getHeader() {return _header;} + void updateHeader(); + void addSaveFile(const String &fileName, InSaveFile *saveStream); +private: + WriteStream *_recordFile; + WriteStream *_writeStream; + WriteStream *_screenshotsFile; + MemoryReadStream _tmpPlaybackFile; + SeekableReadStream *_readStream; + SeekableMemoryWriteStream _tmpRecordFile; + + fileMode _mode; + bool _headerDumped; + int _recordCount; + uint32 _eventsSize; + byte _tmpBuffer[kRecordBuffSize]; + PlaybackFileHeader _header; + PlaybackFileState _playbackParseState; + + void skipHeader(); + bool parseHeader(); + bool processChunk(ChunkHeader &nextChunk); + void returnToChunkHeader(); + + bool readSaveRecord(); + void checkRecordedMD5(); + bool readChunkHeader(ChunkHeader &nextChunk); + void processRndSeedRecord(ChunkHeader chunk); + bool processSettingsRecord(); + + bool checkPlaybackFileVersion(); + + void dumpHeaderToFile(); + void writeSaveFilesSection(); + void writeGameSettings(); + void writeHeaderSection(); + void writeGameHash(); + void writeRandomRecords(); + + void dumpRecordsToFile(); + + String readString(int len); + void readHashMap(ChunkHeader chunk); + + bool skipToNextScreenshot(); + void readEvent(RecorderEvent& event); + void readEventsToBuffer(uint32 size); + bool grabScreenAndComputeMD5(Graphics::Surface &screen, uint8 md5[16]); +}; + +} // End of namespace Common + +#endif diff --git a/common/rect.h b/common/rect.h index 5790cf7c0f..32424d3e6a 100644 --- a/common/rect.h +++ b/common/rect.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/rendermode.cpp b/common/rendermode.cpp index e8f3146630..6115666399 100644 --- a/common/rendermode.cpp +++ b/common/rendermode.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/rendermode.h b/common/rendermode.h index 945c4e7d9d..59fa860c6c 100644 --- a/common/rendermode.h +++ b/common/rendermode.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/savefile.h b/common/savefile.h index 19536da54f..b0c4d31f53 100644 --- a/common/savefile.h +++ b/common/savefile.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/scummsys.h b/common/scummsys.h index 291de87dc9..b8cf7678a4 100644 --- a/common/scummsys.h +++ b/common/scummsys.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -23,6 +23,10 @@ #ifndef COMMON_SCUMMSYS_H #define COMMON_SCUMMSYS_H +#ifndef __has_feature // Optional of course. + #define __has_feature(x) 0 // Compatibility with non-clang compilers. +#endif + // This is a convenience macro to test whether the compiler used is a GCC // version, which is at least major.minor. #define GCC_ATLEAST(major, minor) (defined(__GNUC__) && (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))) @@ -42,7 +46,7 @@ #if defined(WIN32) - #ifdef _MSC_VER + #if defined(_MSC_VER) && _MSC_VER <= 1800 // FIXME: The placement of the workaround functions for MSVC below // require us to include stdio.h and stdarg.h for MSVC here. This @@ -144,6 +148,63 @@ #endif #endif +// The following math constants are usually defined by the system math.h header, but +// they are not part of the ANSI C++ standards and so can NOT be relied upon to be +// present i.e. when -std=c++11 is passed to GCC, enabling strict ANSI compliance. +// As we rely on these being present, we define them if they are not set. + +#ifndef M_E + #define M_E 2.7182818284590452354 /* e */ +#endif + +#ifndef M_LOG2E + #define M_LOG2E 1.4426950408889634074 /* log_2 e */ +#endif + +#ifndef M_LOG10E + #define M_LOG10E 0.43429448190325182765 /* log_10 e */ +#endif + +#ifndef M_LN2 + #define M_LN2 0.69314718055994530942 /* log_e 2 */ +#endif + +#ifndef M_LN10 + #define M_LN10 2.30258509299404568402 /* log_e 10 */ +#endif + +#ifndef M_PI + #define M_PI 3.14159265358979323846 /* pi */ +#endif + +#ifndef M_PI_2 + #define M_PI_2 1.57079632679489661923 /* pi/2 */ +#endif + +#ifndef M_PI_4 + #define M_PI_4 0.78539816339744830962 /* pi/4 */ +#endif + +#ifndef M_1_PI + #define M_1_PI 0.31830988618379067154 /* 1/pi */ +#endif + +#ifndef M_2_PI + #define M_2_PI 0.63661977236758134308 /* 2/pi */ +#endif + +#ifndef M_2_SQRTPI + #define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +#endif + +#ifndef M_SQRT2 + #define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#endif + +#ifndef M_SQRT1_2 + #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif + // Include our C++11 compatability header for pre-C++11 compilers. #if __cplusplus < 201103L #include "common/c++11-compat.h" @@ -344,6 +405,13 @@ typedef unsigned int uint32; typedef signed int int32; typedef unsigned int uint; + #ifdef __PLAYSTATION2__ + typedef signed long int64; + typedef unsigned long uint64; + #else + typedef signed long long int64; + typedef unsigned long long uint64; + #endif #endif diff --git a/common/serializer.h b/common/serializer.h index 4d97c9e930..ef8fca9906 100644 --- a/common/serializer.h +++ b/common/serializer.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/sinetables.cpp b/common/sinetables.cpp index 7338166d39..c01705e3dc 100644 --- a/common/sinetables.cpp +++ b/common/sinetables.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/sinetables.h b/common/sinetables.h index 3489663661..67225c0bcb 100644 --- a/common/sinetables.h +++ b/common/sinetables.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/singleton.h b/common/singleton.h index 6e47f119ba..9bcd590183 100644 --- a/common/singleton.h +++ b/common/singleton.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -44,8 +44,8 @@ private: * and you specialise makeInstance to return an instance of a subclass. */ //template<class T> -#if defined(_WIN32_WCE) || defined(_MSC_VER) || defined(__WINS__) -//FIXME evc4 and msvc7 doesn't like it as private member +#if defined(__WINS__) +//FIXME verify if __WINS__ needs this still public: #endif static T *makeInstance() { diff --git a/common/stack.h b/common/stack.h index bc5de9ac7f..cba3fb124d 100644 --- a/common/stack.h +++ b/common/stack.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_STACK_H diff --git a/common/str-array.h b/common/str-array.h index 57c76bf305..7a52a314e1 100644 --- a/common/str-array.h +++ b/common/str-array.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/str.cpp b/common/str.cpp index 4a10792373..faf84d722f 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #include "common/hash-str.h" diff --git a/common/str.h b/common/str.h index 6b4475e1c4..dede87a005 100644 --- a/common/str.h +++ b/common/str.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_STRING_H @@ -165,7 +166,6 @@ public: * String: monkey.s101 Pattern: monkey.s* => true * String: monkey.s99 Pattern: monkey.s*1 => false * - * @param str Text to be matched against the given pattern. * @param pat Glob pattern. * @param ignoreCase Whether to ignore the case when doing pattern match * @param pathMode Whether to use path mode, i.e., whether slashes must be matched explicitly. @@ -234,6 +234,13 @@ public: static String vformat(const char *fmt, va_list args); public: + typedef char value_type; + /** + * Unsigned version of the underlying type. This can be used to cast + * individual string characters to bigger integer types without sign + * extension happening. + */ + typedef unsigned char unsigned_type; typedef char * iterator; typedef const char * const_iterator; diff --git a/common/stream.cpp b/common/stream.cpp index f49603c882..45060b9db5 100644 --- a/common/stream.cpp +++ b/common/stream.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/stream.h b/common/stream.h index 33ebc95a86..abe5192b70 100644 --- a/common/stream.h +++ b/common/stream.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -125,6 +125,13 @@ public: write(&value, 4); } +#ifdef HAVE_INT64 + void writeUint64LE(uint64 value) { + value = TO_LE_64(value); + write(&value, 8); + } +#endif + void writeUint16BE(uint16 value) { value = TO_BE_16(value); write(&value, 2); @@ -135,6 +142,13 @@ public: write(&value, 4); } +#ifdef HAVE_INT64 + void writeUint64BE(uint64 value) { + value = TO_BE_64(value); + write(&value, 8); + } +#endif + FORCEINLINE void writeSint16LE(int16 value) { writeUint16LE((uint16)value); } @@ -143,6 +157,12 @@ public: writeUint32LE((uint32)value); } +#ifdef HAVE_INT64 + FORCEINLINE void writeSint64LE(int64 value) { + writeUint64LE((uint64)value); + } +#endif + FORCEINLINE void writeSint16BE(int16 value) { writeUint16BE((uint16)value); } @@ -151,6 +171,12 @@ public: writeUint32BE((uint32)value); } +#ifdef HAVE_INT64 + FORCEINLINE void writeSint64BE(int64 value) { + writeUint64BE((uint64)value); + } +#endif + /** * Write the given string to the stream. * This writes str.size() characters, but no terminating zero byte. @@ -241,6 +267,21 @@ public: return FROM_LE_32(val); } +#ifdef HAVE_INT64 + /** + * Read an unsigned 64-bit word stored in little endian (LSB first) order + * from the stream and return it. + * Performs no error checking. The return value is undefined + * if a read error occurred (for which client code can check by + * calling err() and eos() ). + */ + uint64 readUint64LE() { + uint64 val; + read(&val, 8); + return FROM_LE_64(val); + } +#endif + /** * Read an unsigned 16-bit word stored in big endian (MSB first) order * from the stream and return it. @@ -267,6 +308,21 @@ public: return FROM_BE_32(val); } +#ifdef HAVE_INT64 + /** + * Read an unsigned 64-bit word stored in big endian (MSB first) order + * from the stream and return it. + * Performs no error checking. The return value is undefined + * if a read error occurred (for which client code can check by + * calling err() and eos() ). + */ + uint64 readUint64BE() { + uint64 val; + read(&val, 8); + return FROM_BE_64(val); + } +#endif + /** * Read a signed 16-bit word stored in little endian (LSB first) order * from the stream and return it. @@ -289,6 +345,19 @@ public: return (int32)readUint32LE(); } +#ifdef HAVE_INT64 + /** + * Read a signed 64-bit word stored in little endian (LSB first) order + * from the stream and return it. + * Performs no error checking. The return value is undefined + * if a read error occurred (for which client code can check by + * calling err() and eos() ). + */ + FORCEINLINE int64 readSint64LE() { + return (int64)readUint64LE(); + } +#endif + /** * Read a signed 16-bit word stored in big endian (MSB first) order * from the stream and return it. @@ -311,6 +380,19 @@ public: return (int32)readUint32BE(); } +#ifdef HAVE_INT64 + /** + * Read a signed 64-bit word stored in big endian (MSB first) order + * from the stream and return it. + * Performs no error checking. The return value is undefined + * if a read error occurred (for which client code can check by + * calling err() and eos() ). + */ + FORCEINLINE int64 readSint64BE() { + return (int64)readUint64BE(); + } +#endif + /** * Read the specified amount of data into a malloc'ed buffer * which then is wrapped into a MemoryReadStream. @@ -390,7 +472,7 @@ public: * @note This methods is closely modeled after the standard fgets() * function from stdio.h. * - * @param buf the buffer to store into + * @param s the buffer to store into * @param bufSize the size of the buffer * @return a pointer to the read string, or NULL if an error occurred */ @@ -435,6 +517,14 @@ public: return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val); } +#ifdef HAVE_INT64 + uint64 readUint64() { + uint64 val; + read(&val, 8); + return (_bigEndian) ? TO_BE_64(val) : TO_LE_64(val); + } +#endif + FORCEINLINE int16 readSint16() { return (int16)readUint16(); } @@ -442,6 +532,12 @@ public: FORCEINLINE int32 readSint32() { return (int32)readUint32(); } + +#ifdef HAVE_INT64 + FORCEINLINE int64 readSint64() { + return (int64)readUint64(); + } +#endif }; /** diff --git a/common/substream.h b/common/substream.h index 01686529aa..e3161c0a53 100644 --- a/common/substream.h +++ b/common/substream.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/system.cpp b/common/system.cpp index 59210544ab..53f28cafa1 100644 --- a/common/system.cpp +++ b/common/system.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -30,6 +30,9 @@ #include "common/taskbar.h" #include "common/updates.h" #include "common/textconsole.h" +#ifdef ENABLE_EVENTRECORDER +#include "gui/EventRecorder.h" +#endif #include "backends/audiocd/default/default-audiocd.h" #include "backends/fs/fs-factory.h" @@ -84,7 +87,7 @@ void OSystem::initBackend() { error("Backend failed to instantiate audio CD manager"); if (!_eventManager) error("Backend failed to instantiate event manager"); - if (!_timerManager) + if (!getTimerManager()) error("Backend failed to instantiate timer manager"); // TODO: We currently don't check _savefileManager, because at least @@ -152,3 +155,15 @@ Common::String OSystem::getDefaultConfigFileName() { Common::String OSystem::getSystemLanguage() const { return "en_US"; } + +Common::TimerManager *OSystem::getTimerManager() { + return _timerManager; +} + +Common::SaveFileManager *OSystem::getSavefileManager() { +#ifdef ENABLE_EVENTRECORDER + return g_eventRec.getSaveManager(_savefileManager); +#else + return _savefileManager; +#endif +} diff --git a/common/system.h b/common/system.h index 99b947d7f3..8896554f76 100644 --- a/common/system.h +++ b/common/system.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -890,8 +890,14 @@ public: /** @name Events and Time */ //@{ - /** Get the number of milliseconds since the program was started. */ - virtual uint32 getMillis() = 0; + /** Get the number of milliseconds since the program was started. + + @param skipRecord Skip recording of this value by event recorder. + This could be needed particularly when we are in + an on-screen GUI loop where player can pause + the recording. + */ + virtual uint32 getMillis(bool skipRecord = false) = 0; /** Delay/sleep for the specified amount of milliseconds. */ virtual void delayMillis(uint msecs) = 0; @@ -907,9 +913,7 @@ public: * Return the timer manager singleton. For more information, refer * to the TimerManager documentation. */ - inline Common::TimerManager *getTimerManager() { - return _timerManager; - } + virtual Common::TimerManager *getTimerManager(); /** * Return the event manager singleton. For more information, refer @@ -1086,9 +1090,7 @@ public: * and other modifiable persistent game data. For more information, * refer to the SaveFileManager documentation. */ - inline Common::SaveFileManager *getSavefileManager() { - return _savefileManager; - } + Common::SaveFileManager *getSavefileManager(); #if defined(USE_TASKBAR) /** diff --git a/common/textconsole.cpp b/common/textconsole.cpp index a721c121d5..5c69e42379 100644 --- a/common/textconsole.cpp +++ b/common/textconsole.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #define FORBIDDEN_SYMBOL_EXCEPTION_exit diff --git a/common/textconsole.h b/common/textconsole.h index 12f15e5e4b..e7654dd7e5 100644 --- a/common/textconsole.h +++ b/common/textconsole.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_CONSOLE_H diff --git a/common/timer.h b/common/timer.h index 3db32df76a..2db163327d 100644 --- a/common/timer.h +++ b/common/timer.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_TIMER_H diff --git a/common/tokenizer.cpp b/common/tokenizer.cpp index 46ba7a8d8b..2547f88168 100644 --- a/common/tokenizer.cpp +++ b/common/tokenizer.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #include "common/tokenizer.h" diff --git a/common/tokenizer.h b/common/tokenizer.h index 8485094997..dd831f3431 100644 --- a/common/tokenizer.h +++ b/common/tokenizer.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_TOKENIZER_H diff --git a/common/translation.cpp b/common/translation.cpp index 2bc31c617b..01665bf876 100644 --- a/common/translation.cpp +++ b/common/translation.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #if defined(WIN32) diff --git a/common/translation.h b/common/translation.h index 77e2fdfc07..e316507fdb 100644 --- a/common/translation.h +++ b/common/translation.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_TRANSLATION_H diff --git a/common/types.h b/common/types.h index ab86f3afc2..dd5408daa5 100644 --- a/common/types.h +++ b/common/types.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_TYPES_H diff --git a/common/unarj.cpp b/common/unarj.cpp index fe3c17a2ac..e8aed7cbd1 100644 --- a/common/unarj.cpp +++ b/common/unarj.cpp @@ -95,6 +95,12 @@ class ArjDecoder { public: ArjDecoder(const ArjHeader *hdr) { _compsize = hdr->compSize; + _compressed = 0; + _outstream = 0; + _bitbuf = 0; + _bytebuf = 0; + _bitcount = 0; + _blocksize = 0; } ~ArjDecoder() { @@ -112,7 +118,6 @@ public: uint16 _bitbuf; uint16 _bytebuf; int32 _compsize; - byte _subbitbuf; int _bitcount; void init_getbits(); @@ -132,9 +137,6 @@ public: private: byte _ntext[ARJ_FDICSIZ]; - int16 _getlen; - int16 _getbuf; - uint16 _left[2 * ARJ_NC - 1]; uint16 _right[2 * ARJ_NC - 1]; byte _c_len[ARJ_NC]; @@ -656,7 +658,6 @@ void ArjDecoder::decode_f(int32 origsize) { init_getbits(); ncount = 0; - _getlen = _getbuf = 0; r = 0; while (ncount < (uint32)origsize) { diff --git a/common/unzip.cpp b/common/unzip.cpp index 69b9ff67cb..1f4e601989 100644 --- a/common/unzip.cpp +++ b/common/unzip.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ /* unzip.c -- IO on .zip files using zlib @@ -333,8 +334,10 @@ int unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len); #define SIZEZIPLOCALHEADER (0x1e) +#if 0 const char unz_copyright[] = " unzip 0.15 Copyright 1998 Gilles Vollant "; +#endif /* unz_file_info_interntal contain internal info about a file in zipfile*/ typedef struct { diff --git a/common/unzip.h b/common/unzip.h index 2e0dae831a..f249c5db19 100644 --- a/common/unzip.h +++ b/common/unzip.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_UNZIP_H diff --git a/common/updates.h b/common/updates.h index 0012808a17..4c30987c38 100644 --- a/common/updates.h +++ b/common/updates.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/ustr.cpp b/common/ustr.cpp new file mode 100644 index 0000000000..35b5502a6d --- /dev/null +++ b/common/ustr.cpp @@ -0,0 +1,330 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/ustr.h" +#include "common/memorypool.h" +#include "common/util.h" + +namespace Common { + +extern MemoryPool *g_refCountPool; + +static uint32 computeCapacity(uint32 len) { + // By default, for the capacity we use the next multiple of 32 + return ((len + 32 - 1) & ~0x1F); +} + +U32String::U32String(const value_type *str) : _size(0), _str(_storage) { + if (str == 0) { + _storage[0] = 0; + _size = 0; + } else { + uint32 len = 0; + const value_type *s = str; + while (*s++) { + ++len; + } + initWithCStr(str, len); + } +} + +U32String::U32String(const value_type *str, uint32 len) : _size(0), _str(_storage) { + initWithCStr(str, len); +} + +U32String::U32String(const value_type *beginP, const value_type *endP) : _size(0), _str(_storage) { + assert(endP >= beginP); + initWithCStr(beginP, endP - beginP); +} + +U32String::U32String(const U32String &str) + : _size(str._size) { + if (str.isStorageIntern()) { + // String in internal storage: just copy it + memcpy(_storage, str._storage, _builtinCapacity * sizeof(value_type)); + _str = _storage; + } else { + // String in external storage: use refcount mechanism + str.incRefCount(); + _extern._refCount = str._extern._refCount; + _extern._capacity = str._extern._capacity; + _str = str._str; + } + assert(_str != 0); +} + +U32String::~U32String() { + decRefCount(_extern._refCount); +} + +U32String &U32String::operator=(const U32String &str) { + if (&str == this) + return *this; + + if (str.isStorageIntern()) { + decRefCount(_extern._refCount); + _size = str._size; + _str = _storage; + memcpy(_str, str._str, (_size + 1) * sizeof(value_type)); + } else { + str.incRefCount(); + decRefCount(_extern._refCount); + + _extern._refCount = str._extern._refCount; + _extern._capacity = str._extern._capacity; + _size = str._size; + _str = str._str; + } + + return *this; +} + +U32String &U32String::operator+=(const U32String &str) { + if (&str == this) { + return operator+=(U32String(str)); + } + + int len = str._size; + if (len > 0) { + ensureCapacity(_size + len, true); + + memcpy(_str + _size, str._str, (len + 1) * sizeof(value_type)); + _size += len; + } + return *this; +} + +U32String &U32String::operator+=(value_type c) { + ensureCapacity(_size + 1, true); + + _str[_size++] = c; + _str[_size] = 0; + + return *this; +} + +bool U32String::equals(const U32String &x) const { + if (this == &x || _str == x._str) { + return true; + } + + if (x.size() != _size) { + return false; + } + + return !memcmp(_str, x._str, _size * sizeof(value_type)); +} + +bool U32String::contains(value_type x) const { + for (uint32 i = 0; i < _size; ++i) { + if (_str[i] == x) { + return true; + } + } + + return false; +} + +void U32String::deleteChar(uint32 p) { + assert(p < _size); + + makeUnique(); + while (p++ < _size) + _str[p - 1] = _str[p]; + _size--; +} + +void U32String::clear() { + decRefCount(_extern._refCount); + + _size = 0; + _str = _storage; + _storage[0] = 0; +} + +void U32String::toLowercase() { + makeUnique(); + for (uint32 i = 0; i < _size; ++i) { + if (_str[i] < 128) { + _str[i] = tolower(_str[i]); + } + } +} + +void U32String::toUppercase() { + makeUnique(); + for (uint32 i = 0; i < _size; ++i) { + if (_str[i] < 128) { + _str[i] = toupper(_str[i]); + } + } +} + +uint32 U32String::find(const U32String &str, uint32 pos) const { + if (pos >= _size) { + return npos; + } + + const value_type *strP = str.c_str(); + + for (const_iterator cur = begin() + pos; *cur; ++cur) { + uint i = 0; + while (true) { + if (!strP[i]) { + return cur - begin(); + } + + if (cur[i] != strP[i]) { + break; + } + + ++i; + } + } + + return npos; +} + +void U32String::makeUnique() { + ensureCapacity(_size, true); +} + +void U32String::ensureCapacity(uint32 new_size, bool keep_old) { + bool isShared; + uint32 curCapacity, newCapacity; + value_type *newStorage; + int *oldRefCount = _extern._refCount; + + if (isStorageIntern()) { + isShared = false; + curCapacity = _builtinCapacity; + } else { + isShared = (oldRefCount && *oldRefCount > 1); + curCapacity = _extern._capacity; + } + + // Special case: If there is enough space, and we do not share + // the storage, then there is nothing to do. + if (!isShared && new_size < curCapacity) + return; + + if (isShared && new_size < _builtinCapacity) { + // We share the storage, but there is enough internal storage: Use that. + newStorage = _storage; + newCapacity = _builtinCapacity; + } else { + // We need to allocate storage on the heap! + + // Compute a suitable new capacity limit + // If the current capacity is sufficient we use the same capacity + if (new_size < curCapacity) + newCapacity = curCapacity; + else + newCapacity = MAX(curCapacity * 2, computeCapacity(new_size+1)); + + // Allocate new storage + newStorage = new value_type[newCapacity]; + assert(newStorage); + } + + // Copy old data if needed, elsewise reset the new storage. + if (keep_old) { + assert(_size < newCapacity); + memcpy(newStorage, _str, (_size + 1) * sizeof(value_type)); + } else { + _size = 0; + newStorage[0] = 0; + } + + // Release hold on the old storage ... + decRefCount(oldRefCount); + + // ... in favor of the new storage + _str = newStorage; + + if (!isStorageIntern()) { + // Set the ref count & capacity if we use an external storage. + // It is important to do this *after* copying any old content, + // else we would override data that has not yet been copied! + _extern._refCount = 0; + _extern._capacity = newCapacity; + } +} + +void U32String::incRefCount() const { + assert(!isStorageIntern()); + if (_extern._refCount == 0) { + if (g_refCountPool == 0) { + g_refCountPool = new MemoryPool(sizeof(int)); + assert(g_refCountPool); + } + + _extern._refCount = (int *)g_refCountPool->allocChunk(); + *_extern._refCount = 2; + } else { + ++(*_extern._refCount); + } +} + +void U32String::decRefCount(int *oldRefCount) { + if (isStorageIntern()) + return; + + if (oldRefCount) { + --(*oldRefCount); + } + if (!oldRefCount || *oldRefCount <= 0) { + // The ref count reached zero, so we free the string storage + // and the ref count storage. + if (oldRefCount) { + assert(g_refCountPool); + g_refCountPool->freeChunk(oldRefCount); + } + delete[] _str; + + // Even though _str points to a freed memory block now, + // we do not change its value, because any code that calls + // decRefCount will have to do this afterwards anyway. + } +} + +void U32String::initWithCStr(const value_type *str, uint32 len) { + assert(str); + + _storage[0] = 0; + + _size = len; + + if (len >= _builtinCapacity) { + // Not enough internal storage, so allocate more + _extern._capacity = computeCapacity(len+1); + _extern._refCount = 0; + _str = new value_type[_extern._capacity]; + assert(_str != 0); + } + + // Copy the string into the storage area + memmove(_str, str, len * sizeof(value_type)); + _str[len] = 0; +} + +} // End of namespace Common diff --git a/common/ustr.h b/common/ustr.h new file mode 100644 index 0000000000..0059a1eb96 --- /dev/null +++ b/common/ustr.h @@ -0,0 +1,195 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef COMMON_USTR_H +#define COMMON_USTR_H + +#include "common/scummsys.h" + +namespace Common { + +/** + * Very simple string class for UTF-32 strings in ScummVM. The main intention + * behind this class is to feature a simple way of displaying UTF-32 strings + * through the Graphics::Font API. + * + * Please note that operations like equals, deleteCharacter, toUppercase, etc. + * are only very simplified convenience operations. They might not fully work + * as you would expect for a proper UTF-32 string class. + * + * The presence of \0 characters in the string will cause undefined + * behavior in some operations. + */ +class U32String { +public: + static const uint32 npos = 0xFFFFFFFF; + + typedef uint32 value_type; + typedef uint32 unsigned_type; +private: + /** + * The size of the internal storage. Increasing this means less heap + * allocations are needed, at the cost of more stack memory usage, + * and of course lots of wasted memory. + */ + static const uint32 _builtinCapacity = 32; + + /** + * Length of the string. + */ + uint32 _size; + + /** + * Pointer to the actual string storage. Either points to _storage, + * or to a block allocated on the heap via malloc. + */ + value_type *_str; + + + union { + /** + * Internal string storage. + */ + value_type _storage[_builtinCapacity]; + /** + * External string storage data -- the refcounter, and the + * capacity of the string _str points to. + */ + struct { + mutable int *_refCount; + uint32 _capacity; + } _extern; + }; + + inline bool isStorageIntern() const { + return _str == _storage; + } + +public: + /** Construct a new empty string. */ + U32String() : _size(0), _str(_storage) { _storage[0] = 0; } + + /** Construct a new string from the given NULL-terminated C string. */ + explicit U32String(const value_type *str); + + /** Construct a new string containing exactly len characters read from address str. */ + U32String(const value_type *str, uint32 len); + + /** Construct a new string containing the characters between beginP (including) and endP (excluding). */ + U32String(const value_type *beginP, const value_type *endP); + + /** Construct a copy of the given string. */ + U32String(const U32String &str); + + ~U32String(); + + U32String &operator=(const U32String &str); + U32String &operator+=(const U32String &str); + U32String &operator+=(value_type c); + + /** + * Equivalence comparison operator. + * @see equals + */ + bool operator==(const U32String &x) const { return equals(x); } + + /** + * Compares whether two U32String are the same based on memory comparison. + * This does *not* do comparison based on canonical equivalence. + */ + bool equals(const U32String &x) const; + + bool contains(value_type x) const; + + inline const value_type *c_str() const { return _str; } + inline uint32 size() const { return _size; } + + inline bool empty() const { return (_size == 0); } + + value_type operator[](int idx) const { + assert(_str && idx >= 0 && idx < (int)_size); + return _str[idx]; + } + + /** + * Removes the value at position p from the string. + * Using this on decomposed characters will not remove the whole + * character! + */ + void deleteChar(uint32 p); + + /** Clears the string, making it empty. */ + void clear(); + + /** + * Convert all characters in the string to lowercase. + * + * Be aware that this only affects the case of ASCII characters. All + * other characters will not be touched at all. + */ + void toLowercase(); + + /** + * Convert all characters in the string to uppercase. + * + * Be aware that this only affects the case of ASCII characters. All + * other characters will not be touched at all. + */ + void toUppercase(); + + uint32 find(const U32String &str, uint32 pos = 0) const; + + typedef value_type * iterator; + typedef const value_type * const_iterator; + + iterator begin() { + // Since the user could potentially + // change the string via the returned + // iterator we have to assure we are + // pointing to a unique storage. + makeUnique(); + + return _str; + } + + iterator end() { + return begin() + size(); + } + + const_iterator begin() const { + return _str; + } + + const_iterator end() const { + return begin() + size(); + } +private: + void makeUnique(); + void ensureCapacity(uint32 new_size, bool keep_old); + void incRefCount() const; + void decRefCount(int *oldRefCount); + void initWithCStr(const value_type *str, uint32 len); +}; + +} // End of namespace Common + +#endif diff --git a/common/util.cpp b/common/util.cpp index 3d40fffff5..8e0a2fd61f 100644 --- a/common/util.cpp +++ b/common/util.cpp @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #define FORBIDDEN_SYMBOL_EXCEPTION_isalnum diff --git a/common/util.h b/common/util.h index 4ca1c42929..f51aa00925 100644 --- a/common/util.h +++ b/common/util.h @@ -17,6 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ #ifndef COMMON_UTIL_H @@ -41,10 +42,10 @@ #undef MAX #endif -template<typename T> inline T ABS (T x) { return (x>=0) ? x : -x; } -template<typename T> inline T MIN (T a, T b) { return (a<b) ? a : b; } -template<typename T> inline T MAX (T a, T b) { return (a>b) ? a : b; } -template<typename T> inline T CLIP (T v, T amin, T amax) +template<typename T> inline T ABS(T x) { return (x >= 0) ? x : -x; } +template<typename T> inline T MIN(T a, T b) { return (a < b) ? a : b; } +template<typename T> inline T MAX(T a, T b) { return (a > b) ? a : b; } +template<typename T> inline T CLIP(T v, T amin, T amax) { if (v < amin) return amin; else if (v > amax) return amax; else return v; } /** @@ -71,7 +72,7 @@ template<typename T> inline void SWAP(T &a, T &b) { T tmp = a; a = b; b = tmp; } # define SCUMMVM_CURRENT_FUNCTION __PRETTY_FUNCTION__ #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) # define SCUMMVM_CURRENT_FUNCTION __func__ -#elif defined(_MSC_VER) && _MSC_VER >= 1300 +#elif defined(_MSC_VER) # define SCUMMVM_CURRENT_FUNCTION __FUNCTION__ #else # define SCUMMVM_CURRENT_FUNCTION "<unknown>" diff --git a/common/winexe.cpp b/common/winexe.cpp index 877ab6baa1..fc389f6ea6 100644 --- a/common/winexe.cpp +++ b/common/winexe.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/winexe.h b/common/winexe.h index bec156d2e7..cfadbf882d 100644 --- a/common/winexe.h +++ b/common/winexe.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/winexe_ne.cpp b/common/winexe_ne.cpp index 6bb40e0980..ccf1fd17e5 100644 --- a/common/winexe_ne.cpp +++ b/common/winexe_ne.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -187,7 +187,7 @@ uint32 NEResources::getResourceTableOffset() { static const char *s_resTypeNames[] = { "", "cursor", "bitmap", "icon", "menu", "dialog", "string", "font_dir", "font", "accelerator", "rc_data", "msg_table", - "group_cursor", "group_icon", "", "", "version", "dlg_include", + "group_cursor", "", "group_icon", "", "version", "dlg_include", "", "plug_play", "vxd", "ani_cursor", "ani_icon", "html", "manifest" }; @@ -231,7 +231,7 @@ bool NEResources::readResourceTable(uint32 offset) { if (id & 0x8000) res.id = id & 0x7FFF; else - res.id = getResourceString(*_exe, offset + id); + res.id = getResourceString(*_exe, offset + id); if (typeID & 0x8000 && ((typeID & 0x7FFF) < ARRAYSIZE(s_resTypeNames)) && s_resTypeNames[typeID & 0x7FFF][0] != 0) debug(2, "Found resource %s %s", s_resTypeNames[typeID & 0x7FFF], res.id.toString().c_str()); diff --git a/common/winexe_ne.h b/common/winexe_ne.h index f00941412f..d6698e6cf0 100644 --- a/common/winexe_ne.h +++ b/common/winexe_ne.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -46,7 +46,7 @@ enum NEResourceType { kNERCData = 0x0A, kNEMessageTable = 0x0B, kNEGroupCursor = 0x0C, - kNEGroupIcon = 0x0D, + kNEGroupIcon = 0x0E, kNEVersion = 0x10, kNEDlgInclude = 0x11, kNEPlugPlay = 0x13, diff --git a/common/winexe_pe.cpp b/common/winexe_pe.cpp index b3c45ffe73..969ea5d923 100644 --- a/common/winexe_pe.cpp +++ b/common/winexe_pe.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/winexe_pe.h b/common/winexe_pe.h index b38f2f78f5..b163bd15d2 100644 --- a/common/winexe_pe.h +++ b/common/winexe_pe.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index c80d5e15be..67a3d36cec 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -69,7 +69,7 @@ bool XMLParser::loadBuffer(const byte *buffer, uint32 size, DisposeAfterUse::Fla bool XMLParser::loadStream(SeekableReadStream *stream) { _stream = stream; _fileName = "File Stream"; - return true; + return _stream != nullptr; } void XMLParser::close() { diff --git a/common/zlib.cpp b/common/zlib.cpp index 920338e57e..c22ea1e660 100644 --- a/common/zlib.cpp +++ b/common/zlib.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -27,6 +27,8 @@ #include "common/ptr.h" #include "common/util.h" #include "common/stream.h" +#include "common/debug.h" +#include "common/textconsole.h" #if defined(USE_ZLIB) #ifdef __SYMBIAN32__ @@ -139,6 +141,10 @@ bool inflateZlibInstallShield(byte *dst, uint dstLen, const byte *src, uint srcL return true; } +#ifndef RELEASE_BUILD +static bool _shownBackwardSeekingWarning = false; +#endif + /** * A simple wrapper class which can be used to wrap around an arbitrary * other SeekableReadStream and will then provide on-the-fly decompression support. @@ -241,13 +247,17 @@ public: } bool seek(int32 offset, int whence = SEEK_SET) { int32 newPos = 0; - assert(whence != SEEK_END); // SEEK_END not supported switch (whence) { case SEEK_SET: newPos = offset; break; case SEEK_CUR: newPos = _pos + offset; + break; + case SEEK_END: + // NOTE: This can be an expensive operation (see below). + newPos = size() + offset; + break; } assert(newPos >= 0); @@ -256,9 +266,17 @@ public: // To search backward, we have to restart the whole decompression // from the start of the file. A rather wasteful operation, best // to avoid it. :/ -#if DEBUG - warning("Backward seeking in GZipReadStream detected"); + +#ifndef RELEASE_BUILD + if (!_shownBackwardSeekingWarning) { + // We only throw this warning once per stream, to avoid + // getting the console swarmed with warnings when consecutive + // seeks are made. + debug(1, "Backward seeking in GZipReadStream detected"); + _shownBackwardSeekingWarning = true; + } #endif + _pos = 0; _wrapped->seek(0, SEEK_SET); _zlibErr = inflateReset(&_stream); diff --git a/common/zlib.h b/common/zlib.h index d940f3f3a1..5adba64076 100644 --- a/common/zlib.h +++ b/common/zlib.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -68,7 +68,7 @@ bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long * @param dst the buffer to store into. * @param dstLen the size of the destination buffer. * @param src the data to be decompressed. - * @param dstLen the size of the compressed data. + * @param srcLen the size of the compressed data. * @param dict (optional) a decompress dictionary. * @param dictLen (optional) the size of the dictionary. * Mandatory if dict is not 0. @@ -90,7 +90,7 @@ bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen, * @param dst the buffer to store into. * @param dstLen the size of the destination buffer. * @param src the data to be decompressed. - * @param dstLen the size of the compressed data. + * @param srcLen the size of the compressed data. * * @return true on success (Z_OK or Z_STREAM_END), false otherwise. */ |