From 49fad58b2a1555da765b0ac1c20ea480fcb3b9a9 Mon Sep 17 00:00:00 2001 From: upthorn Date: Tue, 22 May 2012 14:22:57 -0700 Subject: COMPOSER: Preliminary (non-functional) game saving/loading support --- engines/composer/composer.h | 10 ++ engines/composer/detection.cpp | 58 +++++++++- engines/composer/saveload.cpp | 243 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 engines/composer/saveload.cpp (limited to 'engines') diff --git a/engines/composer/composer.h b/engines/composer/composer.h index d1a85e975a..b570d16229 100644 --- a/engines/composer/composer.h +++ b/engines/composer/composer.h @@ -150,6 +150,13 @@ class ComposerEngine : public Engine { protected: Common::Error run(); +#ifdef SAVING_ANYWHERE + bool canLoadGameStateCurrently() { return true; } + Common::Error loadGameState(int slot); + bool canSaveGameStateCurrently() { return true; } + Common::Error saveGameState(int slot, const Common::String &desc); +#endif + public: ComposerEngine(OSystem *syst, const ComposerGameDescription *gameDesc); virtual ~ComposerEngine(); @@ -210,6 +217,9 @@ private: uint16 _mouseSpriteId; Common::Point _mouseOffset; +#ifdef SAVING_ANYWHERE + Common::String makeSaveGameName(int slot); +#endif Common::String getStringFromConfig(const Common::String §ion, const Common::String &key); Common::String getFilename(const Common::String §ion, uint id); Common::String mangleFilename(Common::String filename); diff --git a/engines/composer/detection.cpp b/engines/composer/detection.cpp index 689a72a743..1157623de4 100644 --- a/engines/composer/detection.cpp +++ b/engines/composer/detection.cpp @@ -21,6 +21,11 @@ */ #include "base/plugins.h" +#ifdef SAVING_ANYWHERE +#include "common/savefile.h" +#include "common/serializer.h" +#include "common/str-array.h" +#endif //SAVING_ANYWHERE #include "engines/advancedDetector.h" #include "composer/composer.h" @@ -448,6 +453,8 @@ public: virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; virtual bool hasFeature(MetaEngineFeature f) const; + virtual int getMaximumSaveSlot() const; + virtual SaveStateList listSaves(const char* target) const; }; bool ComposerMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { @@ -459,11 +466,60 @@ bool ComposerMetaEngine::createInstance(OSystem *syst, Engine **engine, const AD } bool ComposerMetaEngine::hasFeature(MetaEngineFeature f) const { +#ifdef SAVING_ANYWHERE + return (f == kSupportsListSaves); +#else return false; +#endif //SAVING_ANYWHERE +} + +#ifdef SAVING_ANYWHERE +Common::String getSaveName(Common::InSaveFile *in) { + Common::Serializer ser(in,NULL); + Common::String name; + uint32 tmp; + ser.syncAsUint32LE(tmp); + ser.syncAsUint32LE(tmp); + ser.syncString(name); + return name; +} +int ComposerMetaEngine::getMaximumSaveSlot() const { + return 99; +} +SaveStateList ComposerMetaEngine::listSaves(const char *target) const { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray filenames; + Common::String saveDesc; + Common::String pattern = Common::String::format("%s.??",target); + + filenames = saveFileMan->listSavefiles(pattern); + sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) + + SaveStateList saveList; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + // Obtain the last 3 digits of the filename, since they correspond to the save slot + int slotNum = atoi(file->c_str() + file->size() - 2); + + if (slotNum >= 0 && slotNum <= 99) { + Common::InSaveFile *in = saveFileMan->openForLoading(*file); + if (in) { + saveDesc = getSaveName(in); + saveList.push_back(SaveStateDescriptor(slotNum, saveDesc)); + delete in; + } + } + } + + return saveList; } +#endif //SAVING_ANYWHERE bool Composer::ComposerEngine::hasFeature(EngineFeature f) const { - return (f == kSupportsRTL); + return (f == kSupportsRTL +#ifdef SAVING_ANYWHERE + || f == kSupportsSavingDuringRuntime || f == kSupportsLoadingDuringRuntime +#endif //SAVING_ANYWHERE + ); } #if PLUGIN_ENABLED_DYNAMIC(COMPOSER) diff --git a/engines/composer/saveload.cpp b/engines/composer/saveload.cpp new file mode 100644 index 0000000000..2ce32ee793 --- /dev/null +++ b/engines/composer/saveload.cpp @@ -0,0 +1,243 @@ +/* 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. + * + */ + +#ifdef SAVING_ANYWHERE +#include "common/config-manager.h" +#include "common/memstream.h" +#include "common/savefile.h" +#include "common/serializer.h" +#include "common/system.h" +#include "common/zlib.h" +#include "graphics/palette.h" + +#include "composer/composer.h" +#include "composer/graphics.h" + +namespace Composer { +Common::String ComposerEngine::makeSaveGameName(int slot) { + return (_targetName + Common::String::format(".%02d",slot)); +} + +Common::Error ComposerEngine::loadGameState(int slot) { + Common::String filename = makeSaveGameName(slot); + Common::InSaveFile *in; + if (!(in = _saveFileMan->openForLoading(filename))) + return Common::kPathNotFile; + + Common::Serializer ser(in, NULL); + byte magic[4]; + ser.syncBytes(magic,4); + if (magic[0] != 'C' || magic[1] != 'M' || magic[2] != 'P' || magic[3] != 'S') + return Common::kUnknownError; + + for (Common::List::iterator i = _anims.begin(); i != _anims.end(); i++) { + delete *i; + } + _anims.clear(); + + for (Common::List::iterator i = _pipes.begin(); i != _pipes.end(); i++) { + delete *i; + } + _pipes.clear(); + + ser.syncVersion(0); + Common::String desc; + ser.syncString(desc); + uint32 tmp; + ser.syncAsUint32LE(tmp); + _rnd->setSeed(tmp); + ser.syncAsUint32LE(_currentTime); + uint32 timeDelta = _system->getMillis() - _currentTime; + _currentTime += timeDelta; + ser.syncAsUint32LE(_lastTime); + _lastTime += timeDelta; + ser.syncString(_bookGroup); + _libraries.clear(); + ser.syncAsUint32LE(tmp); + for (uint32 i = tmp; i >0; i--) { + uint16 id; + ser.syncAsUint16LE(id); + loadLibrary(id); + } + _sprites.clear(); + ser.syncAsUint32LE(tmp); + for (uint32 i = tmp; i >0; i--) { + uint16 id; + ser.syncAsUint16LE(id); + Sprite sprite; + sprite._id = id; + initSprite(sprite); + _sprites.push_back(sprite); + } + + _pendingPageChanges.clear(); + ser.syncAsUint32LE(tmp); + for (uint32 i = tmp; i >0; i--) { + uint16 id; + bool remove; + ser.syncAsUint16LE(id); + ser.syncAsByte(remove); + _pendingPageChanges.push_back(PendingPageChange(id,remove)); + } + _stack.clear(); + ser.syncAsUint32LE(tmp); + for (uint32 i = tmp; i >0; i--) { + uint16 svar; + ser.syncAsUint16LE(svar); + _stack.push_back(svar); + } + _vars.clear(); + ser.syncAsUint32LE(tmp); + for (uint32 i = tmp; i >0; i--) { + uint16 var; + ser.syncAsUint16LE(var); + _vars.push_back(var); + } + + for (Common::List::iterator i = _oldScripts.begin(); i != _oldScripts.end(); i++) { + delete *i; + } + _oldScripts.clear(); + ser.syncAsUint32LE(tmp); + for (uint32 i = tmp; i >0; i--) { + uint16 id; + uint32 delay; + ser.syncAsUint16LE(id); + ser.syncAsUint32LE(delay); + OldScript *oTmp = new OldScript(id,getResource(ID_SCRP, id)); + oTmp->_currDelay = delay; + _oldScripts.push_back(oTmp); + } + _queuedScripts.clear(); + ser.syncAsUint32LE(tmp); + for (uint32 i = tmp; i >0; i--) { + QueuedScript qTmp; + ser.syncAsUint32LE(qTmp._baseTime); + qTmp._baseTime += timeDelta; + ser.syncAsUint32LE(qTmp._duration); + ser.syncAsUint32LE(qTmp._count); + if(qTmp._count !=0) { + assert(qTmp._count != 0); + } + ser.syncAsUint16LE(qTmp._scriptId); + _queuedScripts.push_back(qTmp); + } + + ser.syncAsByte(_mouseEnabled); + ser.syncAsByte(_mouseVisible); + ser.syncAsUint16LE(_mouseSpriteId); + _dirtyRects.clear(); + + _dirtyRects.push_back(Common::Rect(0,0,640,480)); + byte palbuf[256 * 3]; + ser.syncBytes(palbuf,256 * 3); + _system->getPaletteManager()->setPalette(palbuf,0,256); + _needsUpdate = true; + + return Common::kNoError; +} + +Common::Error ComposerEngine::saveGameState(int slot, const Common::String &desc) { + Common::String filename = makeSaveGameName(slot); + Common::OutSaveFile *out; + if (!(out = _saveFileMan->openForSaving(filename))) + return Common::kWritingFailed; + + Common::Serializer ser(NULL, out); + byte magic[4] = {'C', 'M', 'P', 'S'}; + ser.syncBytes(magic,4); + ser.syncVersion(0); + Common::String desctmp = desc; + ser.syncString(desctmp); + uint32 tmp = _rnd->getSeed(); + ser.syncAsUint32LE(tmp); + ser.syncAsUint32LE(_currentTime); + ser.syncAsUint32LE(_lastTime); + ser.syncString(_bookGroup); + tmp = _libraries.size(); + ser.syncAsUint32LE(tmp); + for (Common::List::const_iterator i = _libraries.begin(); i != _libraries.end(); i++) { + uint16 tmp = (*i)._id; + ser.syncAsUint16LE(tmp); + } + tmp = _sprites.size(); + ser.syncAsUint32LE(tmp); + for (Common::List::const_iterator i = _sprites.begin(); i != _sprites.end(); i++) { + uint16 tmp = (*i)._id; + ser.syncAsUint16LE(tmp); + } + tmp = _pendingPageChanges.size(); + ser.syncAsUint32LE(tmp); + for (Common::Array::const_iterator i = _pendingPageChanges.begin(); i != _pendingPageChanges.end(); i++) { + uint16 tmp = (*i)._pageId; + bool tmpb = (*i)._remove; + ser.syncAsUint16LE(tmp); + ser.syncAsByte(tmpb); + } + tmp = _stack.size(); + ser.syncAsUint32LE(tmp); + for (Common::Array::const_iterator i = _stack.begin(); i != _stack.end(); i++) { + uint16 tmp = (*i); + ser.syncAsUint16LE(tmp); + } + tmp = _vars.size(); + ser.syncAsUint32LE(tmp); + for (Common::Array::const_iterator i = _vars.begin(); i != _vars.end(); i++) { + uint16 tmp = (*i); + ser.syncAsUint16LE(tmp); + } + tmp = _oldScripts.size(); + ser.syncAsUint32LE(tmp); + for (Common::List::const_iterator i = _oldScripts.begin(); i != _oldScripts.end(); i++) { + uint16 tmp16 = (*i)->_id; + tmp = (*i)->_currDelay; + ser.syncAsUint16LE(tmp16); + ser.syncAsUint32LE(tmp); + } + tmp = _queuedScripts.size(); + ser.syncAsUint32LE(tmp); + for (Common::Array::const_iterator i = _queuedScripts.begin(); i != _queuedScripts.end(); i++) { + tmp = (*i)._baseTime; + ser.syncAsUint32LE(tmp); + tmp = (*i)._duration; + ser.syncAsUint32LE(tmp); + tmp = (*i)._count; + if(tmp !=0) { + assert(tmp != 0); + } + uint16 tmp16 = (*i)._scriptId; + ser.syncAsUint32LE(tmp); + ser.syncAsUint16LE(tmp16); + } + ser.syncAsByte(_mouseEnabled); + ser.syncAsByte(_mouseVisible); + ser.syncAsUint16LE(_mouseSpriteId); + + byte palbuf[256 * 3]; + _system->getPaletteManager()->grabPalette(palbuf,0,256); + ser.syncBytes(palbuf,256 * 3); + + out->finalize(); + return Common::kNoError; +} +} +#endif -- cgit v1.2.3