diff options
author | Thierry Crozat | 2017-09-04 22:48:50 +0100 |
---|---|---|
committer | Thierry Crozat | 2018-01-23 02:15:31 +0000 |
commit | ed7fa6f7d79933dc5cec6b7d4f2bc4080378ecc1 (patch) | |
tree | d1dbab888d2c5d8a36b30806a8664c28692f08d9 | |
parent | a4470edb290573d4e87736212a47299b3681eb01 (diff) | |
download | scummvm-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.
-rw-r--r-- | engines/supernova/detection.cpp | 72 | ||||
-rw-r--r-- | engines/supernova/supernova.cpp | 17 | ||||
-rw-r--r-- | engines/supernova/supernova.h | 4 |
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) |