diff options
-rw-r--r-- | engines/cge2/cge2.cpp | 22 | ||||
-rw-r--r-- | engines/cge2/cge2.h | 19 | ||||
-rw-r--r-- | engines/cge2/cge2_main.cpp | 6 | ||||
-rw-r--r-- | engines/cge2/detection.cpp | 51 | ||||
-rw-r--r-- | engines/cge2/detection.h | 80 | ||||
-rw-r--r-- | engines/cge2/module.mk | 3 | ||||
-rw-r--r-- | engines/cge2/saveload.cpp | 197 |
7 files changed, 309 insertions, 69 deletions
diff --git a/engines/cge2/cge2.cpp b/engines/cge2/cge2.cpp index 6976a6fc82..1a9f48d317 100644 --- a/engines/cge2/cge2.cpp +++ b/engines/cge2/cge2.cpp @@ -35,7 +35,6 @@ #include "cge2/hero.h" #include "cge2/general.h" #include "cge2/spare.h" -#include "cge2/events.h" #include "cge2/talk.h" #include "cge2/cge2_main.h" #include "cge2/map.h" @@ -158,24 +157,9 @@ void CGE2Engine::deinit() { } bool CGE2Engine::hasFeature(EngineFeature f) const { - return false; -} - -bool CGE2Engine::canLoadGameStateCurrently() { - return false; -} -bool CGE2Engine::canSaveGameStateCurrently() { - return false; -} - -Common::Error CGE2Engine::loadGameState(int slot) { - warning("STUB: CGE2Engine::loadGameState()"); - return Common::kNoError; -} - -Common::Error CGE2Engine::saveGameState(int slot, const Common::String &desc) { - warning("STUB: CGE2Engine::saveGameState()"); - return Common::kNoError; + return + (f == kSupportsLoadingDuringRuntime) || + (f == kSupportsSavingDuringRuntime); } Common::Error CGE2Engine::run() { diff --git a/engines/cge2/cge2.h b/engines/cge2/cge2.h index c569bf9458..e3606b821b 100644 --- a/engines/cge2/cge2.h +++ b/engines/cge2/cge2.h @@ -29,6 +29,8 @@ #define CGE2_H #include "common/random.h" +#include "common/savefile.h" +#include "common/serializer.h" #include "engines/engine.h" #include "engines/advancedDetector.h" #include "common/system.h" @@ -59,6 +61,7 @@ class System; class EventManager; class Font; class Map; +struct SavegameHeader; #define kScrWidth 320 #define kScrHeight 240 @@ -105,6 +108,10 @@ class Map; #define kQuitText 201 #define kNoQuitText 202 +#define kSavegameVersion 1 +#define kSavegameStrSize 12 +#define kSavegameStr "SCUMMVM_CGE2" + enum CallbackType { kNullCB = 0, kQGame, kXScene, kSoundSetVolume }; @@ -119,22 +126,28 @@ class CGE2Engine : public Engine { private: uint32 _lastFrame, _lastTick; void tick(); + + Common::String generateSaveName(int slot); + void writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header); + void syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream); + void syncHeader(Common::Serializer &s); public: CGE2Engine(OSystem *syst, const ADGameDescription *gameDescription); virtual bool hasFeature(EngineFeature f) const; - virtual bool canLoadGameStateCurrently(); virtual bool canSaveGameStateCurrently(); - virtual Common::Error loadGameState(int slot); + virtual bool canLoadGameStateCurrently(); virtual Common::Error saveGameState(int slot, const Common::String &desc); + virtual Common::Error loadGameState(int slot); virtual Common::Error run(); + static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header); bool showTitle(const char *name); void cge2_main(); char *mergeExt(char *buf, const char *name, const char *ext); void inf(const char *text, ColorBank col = kCBInf); void movie(const char *ext); void runGame(); - void loadGame(); + void loadHeroes(); void loadScript(const char *fname); void loadSprite(const char *fname, int ref, int scene, V3D &pos); void badLab(const char *fn); diff --git a/engines/cge2/cge2_main.cpp b/engines/cge2/cge2_main.cpp index 75b9affc1a..77ad7181fc 100644 --- a/engines/cge2/cge2_main.cpp +++ b/engines/cge2/cge2_main.cpp @@ -726,12 +726,12 @@ void CGE2Engine::loadUser() { warning("STUB: CGE2Engine::loadUser()"); // Missing loading from file. TODO: Implement it with the saving/loading! loadScript("CGE.INI"); - loadGame(); + loadHeroes(); loadPos(); } -void CGE2Engine::loadGame() { - warning("STUB: CGE2Engine::loadGame()"); +void CGE2Engine::loadHeroes() { // Original name: loadGame() + warning("STUB: CGE2Engine::loadHeroes()"); // load sprites & pocket diff --git a/engines/cge2/detection.cpp b/engines/cge2/detection.cpp index cbe78dae4f..599934b57d 100644 --- a/engines/cge2/detection.cpp +++ b/engines/cge2/detection.cpp @@ -25,49 +25,10 @@ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon */ -#include "cge2/cge2.h" -#include "engines/advancedDetector.h" +#include "cge2/detection.h" namespace CGE2 { -static const PlainGameDescriptor CGE2Games[] = { - { "sfinx", "Sfinx" }, - { 0, 0 } -}; - -static const ADGameDescription gameDescriptions[] = { - { - "sfinx", "Sfinx Freeware", - { - { "vol.cat", 0, "21197b287d397c53261b6616bf0dd880", 129024 }, - { "vol.dat", 0, "de14291869a8eb7c2732ab783c7542ef", 34180844 }, - AD_LISTEND - }, - Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0() - }, - AD_TABLE_END_MARKER -}; - -class CGE2MetaEngine : public AdvancedMetaEngine { -public: - CGE2MetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(ADGameDescription), CGE2Games) { - _singleid = "sfinx"; - } - - virtual const char *getName() const { - return "CGE2"; - } - - virtual const char *getOriginalCopyright() const { - return "Sfinx (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon"; - } - - virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; - virtual bool hasFeature(MetaEngineFeature f) const; - - const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; -}; - bool CGE2MetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { if (desc) { *engine = new CGE2::CGE2Engine(syst, desc); @@ -76,7 +37,11 @@ bool CGE2MetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGame } bool CGE2MetaEngine::hasFeature(MetaEngineFeature f) const { - return false; + return + (f == kSupportsDeleteSave) || + (f == kSavesSupportMetaInfo) || + (f == kSavesSupportThumbnail) || + (f == kSavesSupportCreationDate); } const ADGameDescription *CGE2MetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { @@ -108,7 +73,7 @@ const ADGameDescription *CGE2MetaEngine::fallbackDetect(const FileMap &allFiles, } // End of namespace CGE2 #if PLUGIN_ENABLED_DYNAMIC(CGE2) - REGISTER_PLUGIN_DYNAMIC(CGE2, PLUGIN_TYPE_ENGINE, CGE2::CGE2MetaEngine); +REGISTER_PLUGIN_DYNAMIC(CGE2, PLUGIN_TYPE_ENGINE, CGE2::CGE2MetaEngine); #else - REGISTER_PLUGIN_STATIC(CGE2, PLUGIN_TYPE_ENGINE, CGE2::CGE2MetaEngine); +REGISTER_PLUGIN_STATIC(CGE2, PLUGIN_TYPE_ENGINE, CGE2::CGE2MetaEngine); #endif diff --git a/engines/cge2/detection.h b/engines/cge2/detection.h new file mode 100644 index 0000000000..556980774a --- /dev/null +++ b/engines/cge2/detection.h @@ -0,0 +1,80 @@ +/* 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. + * + */ + +/* + * This code is based on original Sfinx source code + * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon + */ + +#ifndef CGE2_DETECTION_H +#define CGE2_DETECTION_H + +#include "cge2/cge2.h" +#include "engines/advancedDetector.h" + +namespace CGE2 { + +static const PlainGameDescriptor CGE2Games[] = { + { "sfinx", "Sfinx" }, + { 0, 0 } +}; + +static const ADGameDescription gameDescriptions[] = { + { + "sfinx", "Sfinx Freeware", + { + { "vol.cat", 0, "21197b287d397c53261b6616bf0dd880", 129024 }, + { "vol.dat", 0, "de14291869a8eb7c2732ab783c7542ef", 34180844 }, + AD_LISTEND + }, + Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0() + }, + AD_TABLE_END_MARKER +}; + +class CGE2MetaEngine : public AdvancedMetaEngine { +public: + CGE2MetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(ADGameDescription), CGE2Games) { + _singleid = "sfinx"; + } + + virtual const char *getName() const { + return "CGE2"; + } + + virtual const char *getOriginalCopyright() const { + return "Sfinx (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon"; + } + + 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; + SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; + virtual void removeSaveState(const char *target, int slot) const; + + const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; +}; + +} // End of namespace CGE2 + +#endif // CGE2_DETECTION_H diff --git a/engines/cge2/module.mk b/engines/cge2/module.mk index 9a6e0cb595..cb2b51e5d3 100644 --- a/engines/cge2/module.mk +++ b/engines/cge2/module.mk @@ -15,7 +15,8 @@ MODULE_OBJS = \ talk.o \ events.o \ map.o \ - vmenu.o + vmenu.o \ + saveload.o # This module can be built as a plugin ifeq ($(ENABLE_CGE2), DYNAMIC_PLUGIN) diff --git a/engines/cge2/saveload.cpp b/engines/cge2/saveload.cpp new file mode 100644 index 0000000000..ac059e5d8f --- /dev/null +++ b/engines/cge2/saveload.cpp @@ -0,0 +1,197 @@ +/* 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. + * + */ + +/* + * This code is based on original Sfinx source code + * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon + */ + +#include "cge2/detection.h" +#include "common/config-manager.h" +#include "common/savefile.h" +#include "common/system.h" +#include "graphics/thumbnail.h" +#include "graphics/surface.h" +#include "graphics/palette.h" +#include "graphics/scaler.h" +#include "cge2/events.h" +#include "cge2/snail.h" +#include "cge2/hero.h" + +namespace CGE2 { + +struct SavegameHeader { + uint8 version; + Common::String saveName; + Graphics::Surface *thumbnail; + int saveYear, saveMonth, saveDay; + int saveHour, saveMinutes; +}; + +int CGE2MetaEngine::getMaximumSaveSlot() const { + return 99; +} + +SaveStateList CGE2MetaEngine::listSaves(const char *target) const { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray filenames; + Common::String pattern = target; + pattern += ".???"; + + filenames = saveFileMan->listSavefiles(pattern); + sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) + + SaveStateList saveList; + for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) { + // Obtain the last 3 digits of the filename, since they correspond to the save slot + int slotNum = atoi(filename->c_str() + filename->size() - 3); + + if (slotNum >= 0 && slotNum <= 99) { + + Common::InSaveFile *file = saveFileMan->openForLoading(*filename); + if (file) { + CGE2::SavegameHeader header; + + // Check to see if it's a ScummVM savegame or not + char buffer[kSavegameStrSize + 1]; + file->read(buffer, kSavegameStrSize + 1); + + if (!strncmp(buffer, kSavegameStr, kSavegameStrSize + 1)) { + // Valid savegame + if (CGE2::CGE2Engine::readSavegameHeader(file, header)) { + saveList.push_back(SaveStateDescriptor(slotNum, header.saveName)); + if (header.thumbnail) { + header.thumbnail->free(); + delete header.thumbnail; + } + } + } else { + // Must be an original format savegame + saveList.push_back(SaveStateDescriptor(slotNum, "Unknown")); + } + + delete file; + } + } + } + + return saveList; +} + +SaveStateDescriptor CGE2MetaEngine::querySaveMetaInfos(const char *target, int slot) const { + Common::String fileName = Common::String::format("%s.%03d", target, slot); + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName); + + if (f) { + CGE2::SavegameHeader header; + + // Check to see if it's a ScummVM savegame or not + char buffer[kSavegameStrSize + 1]; + f->read(buffer, kSavegameStrSize + 1); + + bool hasHeader = !strncmp(buffer, kSavegameStr, kSavegameStrSize + 1) && + CGE2::CGE2Engine::readSavegameHeader(f, header); + delete f; + + if (!hasHeader) { + // Original savegame perhaps? + SaveStateDescriptor desc(slot, "Unknown"); + return desc; + } else { + // Create the return descriptor + SaveStateDescriptor desc(slot, header.saveName); + desc.setThumbnail(header.thumbnail); + desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay); + desc.setSaveTime(header.saveHour, header.saveMinutes); + + // Slot 0 is used for the 'automatic save on exit' save in Soltys, thus + // we prevent it from being deleted or overwritten by accident. + desc.setDeletableFlag(slot != 0); + desc.setWriteProtectedFlag(slot == 0); + + return desc; + } + } + + return SaveStateDescriptor(); +} + +bool CGE2Engine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header) { + header.thumbnail = nullptr; + + // Get the savegame version + header.version = in->readByte(); + if (header.version > kSavegameVersion) + return false; + + // Read in the string + header.saveName.clear(); + char ch; + while ((ch = (char)in->readByte()) != '\0') + header.saveName += ch; + + // Get the thumbnail + header.thumbnail = Graphics::loadThumbnail(*in); + if (!header.thumbnail) + return false; + + // Read in save date/time + header.saveYear = in->readSint16LE(); + header.saveMonth = in->readSint16LE(); + header.saveDay = in->readSint16LE(); + header.saveHour = in->readSint16LE(); + header.saveMinutes = in->readSint16LE(); + + return true; +} + +void CGE2MetaEngine::removeSaveState(const char *target, int slot) const { + Common::String fileName = Common::String::format("%s.%03d", target, slot); + g_system->getSavefileManager()->removeSavefile(fileName); +} + +bool CGE2Engine::canSaveGameStateCurrently() { + bool isHeroVisible = false; + for (int i = 0; i < 2; i++) { + isHeroVisible = !_heroTab[i]->_ptr->_flags._hide; + if (isHeroVisible) + break; + } + return (_startupMode == 0) && _mouse->_active && + _commandHandler->idle() && isHeroVisible; +} + +bool CGE2Engine::canLoadGameStateCurrently() { + return (_startupMode == 0) && _mouse->_active; +} + +Common::Error CGE2Engine::saveGameState(int slot, const Common::String &desc) { + warning("STUB: CGE2Engine::saveGameState()"); + return Common::kNoError; +} + +Common::Error CGE2Engine::loadGameState(int slot) { + warning("STUB: CGE2Engine::loadGameState()"); + return Common::kNoError; +} + +} // End of namespace CGE2 |