aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorThierry Crozat2017-09-04 22:48:50 +0100
committerThierry Crozat2018-01-23 02:15:31 +0000
commited7fa6f7d79933dc5cec6b7d4f2bc4080378ecc1 (patch)
treed1dbab888d2c5d8a36b30806a8664c28692f08d9 /engines
parenta4470edb290573d4e87736212a47299b3681eb01 (diff)
downloadscummvm-rg350-ed7fa6f7d79933dc5cec6b7d4f2bc4080378ecc1.tar.gz
scummvm-rg350-ed7fa6f7d79933dc5cec6b7d4f2bc4080378ecc1.tar.bz2
scummvm-rg350-ed7fa6f7d79933dc5cec6b7d4f2bc4080378ecc1.zip
SUPERNOVA: Improve save state handling
The saved game files now start with a header and version which allows to do some sanity check and will allow to change the format in the future if needed. Also the MetaEngine can now be queried for the meta infos of a save state.
Diffstat (limited to 'engines')
-rw-r--r--engines/supernova/detection.cpp72
-rw-r--r--engines/supernova/supernova.cpp17
-rw-r--r--engines/supernova/supernova.h4
3 files changed, 89 insertions, 4 deletions
diff --git a/engines/supernova/detection.cpp b/engines/supernova/detection.cpp
index 5770871406..b587dbb623 100644
--- a/engines/supernova/detection.cpp
+++ b/engines/supernova/detection.cpp
@@ -24,6 +24,7 @@
#include "common/file.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "graphics/thumbnail.h"
#include "engines/advancedDetector.h"
#include "supernova/supernova.h"
@@ -83,6 +84,7 @@ public:
virtual int getMaximumSaveSlot() const {
return 99;
}
+ virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
};
bool SupernovaMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -92,6 +94,13 @@ bool SupernovaMetaEngine::hasFeature(MetaEngineFeature f) const {
case kSupportsListSaves:
// fallthrough
case kSupportsDeleteSave:
+ // fallthrough
+ case kSavesSupportMetaInfo:
+ // fallthrough
+ case kSavesSupportThumbnail:
+ // fallthrough
+ case kSavesSupportCreationDate:
+ // fallthrough
return true;
default:
return false;
@@ -120,10 +129,17 @@ SaveStateList SupernovaMetaEngine::listSaves(const char *target) const {
if (saveSlot >= 0 && saveSlot <= getMaximumSaveSlot()) {
Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(*file);
if (savefile) {
- savefile->skip(2);
- savefile->read(saveFileDesc, sizeof(saveFileDesc));
- saveFileList.push_back(SaveStateDescriptor(saveSlot, saveFileDesc));
-
+ uint saveHeader = savefile->readUint32LE();
+ if (saveHeader == SAVEGAME_HEADER) {
+ byte saveVersion = savefile->readByte();
+ if (saveVersion <= SAVEGAME_VERSION) {
+ int saveFileDescSize = savefile->readSint16LE();
+ char* saveFileDesc = new char[saveFileDescSize];
+ savefile->read(saveFileDesc, saveFileDescSize);
+ saveFileList.push_back(SaveStateDescriptor(saveSlot, saveFileDesc));
+ delete [] saveFileDesc;
+ }
+ }
delete savefile;
}
}
@@ -138,6 +154,54 @@ void SupernovaMetaEngine::removeSaveState(const char *target, int slot) const {
g_system->getSavefileManager()->removeSavefile(filename);
}
+SaveStateDescriptor SupernovaMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ Common::String fileName = Common::String::format("msn_save.%03d", slot);
+ Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(fileName);
+
+ if (savefile) {
+ uint saveHeader = savefile->readUint32LE();
+ if (saveHeader != SAVEGAME_HEADER) {
+ delete savefile;
+ return SaveStateDescriptor();
+ }
+ byte saveVersion = savefile->readByte();
+ if (saveVersion > SAVEGAME_VERSION){
+ delete savefile;
+ return SaveStateDescriptor();
+ }
+
+ int descriptionSize = savefile->readSint16LE();
+ char* description = new char[descriptionSize];
+ savefile->read(description, descriptionSize);
+ SaveStateDescriptor desc(slot, description);
+ delete [] description;
+
+ uint32 saveDate = savefile->readUint32LE();
+ int day = (saveDate >> 24) & 0xFF;
+ int month = (saveDate >> 16) & 0xFF;
+ int year = saveDate & 0xFFFF;
+ desc.setSaveDate(year, month, day);
+
+ uint16 saveTime = savefile->readUint16LE();
+ int hour = (saveTime >> 8) & 0xFF;
+ int minutes = saveTime & 0xFF;
+ desc.setSaveTime(hour, minutes);
+
+
+ if (Graphics::checkThumbnailHeader(*savefile)) {
+ Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*savefile);
+ desc.setThumbnail(thumbnail);
+ }
+
+ delete savefile;
+
+ return desc;
+ }
+
+ return SaveStateDescriptor();
+}
+
+
#if PLUGIN_ENABLED_DYNAMIC(SUPERNOVA)
REGISTER_PLUGIN_DYNAMIC(SUPERNOVA, PLUGIN_TYPE_ENGINE, SupernovaMetaEngine);
#else
diff --git a/engines/supernova/supernova.cpp b/engines/supernova/supernova.cpp
index 5128a1c531..17033dadd4 100644
--- a/engines/supernova/supernova.cpp
+++ b/engines/supernova/supernova.cpp
@@ -814,6 +814,20 @@ bool SupernovaEngine::loadGame(int slot) {
if (!savefile)
return false;
+ uint saveHeader = savefile->readUint32LE();
+ if (saveHeader != SAVEGAME_HEADER) {
+ warning("No header found in '%s'", filename.c_str());
+ delete savefile;
+ return Common::kUnknownError;
+ }
+
+ byte saveVersion = savefile->readByte();
+ if (saveVersion > SAVEGAME_VERSION) {
+ warning("Save game version %i not supported", saveVersion);
+ delete savefile;
+ return Common::kUnknownError;
+ }
+
int descriptionSize = savefile->readSint16LE();
savefile->skip(descriptionSize);
savefile->skip(6);
@@ -833,6 +847,9 @@ bool SupernovaEngine::saveGame(int slot, const Common::String &description) {
Common::OutSaveFile *savefile = _saveFileMan->openForSaving(filename);
if (!savefile)
return false;
+
+ savefile->writeUint32LE(SAVEGAME_HEADER);
+ savefile->writeByte(SAVEGAME_VERSION);
TimeDate currentDate;
_system->getTimeAndDate(currentDate);
diff --git a/engines/supernova/supernova.h b/engines/supernova/supernova.h
index 2073c0f300..df9108ec6e 100644
--- a/engines/supernova/supernova.h
+++ b/engines/supernova/supernova.h
@@ -42,6 +42,10 @@
namespace Supernova {
+#define SAVEGAME_HEADER MKTAG('M','S','N','1')
+#define SAVEGAME_VERSION 1
+
+
struct ScreenBuffer {
ScreenBuffer()
: _x(0)