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.
This commit is contained in:
parent
a4470edb29
commit
ed7fa6f7d7
3 changed files with 89 additions and 4 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -42,6 +42,10 @@
|
|||
|
||||
namespace Supernova {
|
||||
|
||||
#define SAVEGAME_HEADER MKTAG('M','S','N','1')
|
||||
#define SAVEGAME_VERSION 1
|
||||
|
||||
|
||||
struct ScreenBuffer {
|
||||
ScreenBuffer()
|
||||
: _x(0)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue