aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/cge2/cge2.cpp22
-rw-r--r--engines/cge2/cge2.h19
-rw-r--r--engines/cge2/cge2_main.cpp6
-rw-r--r--engines/cge2/detection.cpp51
-rw-r--r--engines/cge2/detection.h80
-rw-r--r--engines/cge2/module.mk3
-rw-r--r--engines/cge2/saveload.cpp197
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