mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-06 09:48:39 +00:00
MTROPOLIS: Add auto-save option and add versioning to save files.
This commit is contained in:
parent
47226d69f9
commit
cd54d61de7
@ -59,6 +59,17 @@ static const ADExtraGuiOptionsMap optionsList[] = {
|
||||
0
|
||||
}
|
||||
},
|
||||
{
|
||||
GAMEOPTION_AUTO_SAVE,
|
||||
{
|
||||
_s("Save Progress Automatically"),
|
||||
_s("Automatically saves the game at certain progress points."),
|
||||
"mtropolis_mod_auto_save",
|
||||
true,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
{
|
||||
GAMEOPTION_LAUNCH_DEBUG,
|
||||
{
|
||||
|
@ -30,6 +30,7 @@
|
||||
#define GAMEOPTION_DYNAMIC_MIDI GUIO_GAMEOPTIONS2
|
||||
#define GAMEOPTION_LAUNCH_DEBUG GUIO_GAMEOPTIONS3
|
||||
#define GAMEOPTION_LAUNCH_BREAK GUIO_GAMEOPTIONS4
|
||||
#define GAMEOPTION_AUTO_SAVE GUIO_GAMEOPTIONS5
|
||||
|
||||
namespace MTropolis {
|
||||
|
||||
@ -51,7 +52,7 @@ static const MTropolisGameDescription gameDescriptions[] = {
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformMacintosh,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO1(GAMEOPTION_WIDESCREEN_MOD)
|
||||
GUIO2(GAMEOPTION_WIDESCREEN_MOD, GAMEOPTION_AUTO_SAVE)
|
||||
},
|
||||
GID_OBSIDIAN,
|
||||
0,
|
||||
@ -78,7 +79,7 @@ static const MTropolisGameDescription gameDescriptions[] = {
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO1(GAMEOPTION_WIDESCREEN_MOD)
|
||||
GUIO2(GAMEOPTION_WIDESCREEN_MOD, GAMEOPTION_AUTO_SAVE)
|
||||
},
|
||||
GID_OBSIDIAN,
|
||||
0,
|
||||
|
@ -34,7 +34,7 @@ class CompoundVarLoader : public ISaveReader {
|
||||
public:
|
||||
explicit CompoundVarLoader(RuntimeObject *object);
|
||||
|
||||
bool readSave(Common::ReadStream *stream) override;
|
||||
bool readSave(Common::ReadStream *stream, uint32 saveFileVersion) override;
|
||||
|
||||
private:
|
||||
RuntimeObject *_object;
|
||||
@ -43,7 +43,7 @@ private:
|
||||
CompoundVarLoader::CompoundVarLoader(RuntimeObject *object) : _object(object) {
|
||||
}
|
||||
|
||||
bool CompoundVarLoader::readSave(Common::ReadStream *stream) {
|
||||
bool CompoundVarLoader::readSave(Common::ReadStream *stream, uint32 saveFileVersion) {
|
||||
if (_object == nullptr || !_object->isModifier())
|
||||
return false;
|
||||
|
||||
@ -52,7 +52,7 @@ bool CompoundVarLoader::readSave(Common::ReadStream *stream) {
|
||||
if (!saveLoad)
|
||||
return false;
|
||||
|
||||
if (!saveLoad->load(modifier, stream))
|
||||
if (!saveLoad->load(modifier, stream, saveFileVersion))
|
||||
return false;
|
||||
|
||||
if (stream->err())
|
||||
@ -63,9 +63,6 @@ bool CompoundVarLoader::readSave(Common::ReadStream *stream) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool BehaviorModifier::load(ModifierLoaderContext &context, const Data::BehaviorModifier &data) {
|
||||
if (data.numChildren > 0) {
|
||||
ChildLoaderContext loaderContext;
|
||||
@ -1733,7 +1730,7 @@ void CompoundVariableModifier::SaveLoad::saveInternal(Common::WriteStream *strea
|
||||
childSL.saveLoad->save(childSL.modifier, stream);
|
||||
}
|
||||
|
||||
bool CompoundVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream) {
|
||||
bool CompoundVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
|
||||
const uint32 numChildren = stream->readUint32BE();
|
||||
if (stream->err())
|
||||
return false;
|
||||
@ -1742,7 +1739,7 @@ bool CompoundVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream
|
||||
return false;
|
||||
|
||||
for (const ChildSaveLoad &childSL : _childrenSaveLoad) {
|
||||
if (!childSL.saveLoad->load(childSL.modifier, stream))
|
||||
if (!childSL.saveLoad->load(childSL.modifier, stream, saveFileVersion))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1825,7 +1822,7 @@ void BooleanVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream
|
||||
stream->writeByte(_value ? 1 : 0);
|
||||
}
|
||||
|
||||
bool BooleanVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream) {
|
||||
bool BooleanVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
|
||||
byte b = stream->readByte();
|
||||
if (stream->err())
|
||||
return false;
|
||||
@ -1896,7 +1893,7 @@ void IntegerVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream
|
||||
stream->writeSint32BE(_value);
|
||||
}
|
||||
|
||||
bool IntegerVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream) {
|
||||
bool IntegerVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
|
||||
_value = stream->readSint32BE();
|
||||
|
||||
if (stream->err())
|
||||
@ -1985,7 +1982,7 @@ void IntegerRangeVariableModifier::SaveLoad::saveInternal(Common::WriteStream *s
|
||||
stream->writeSint32BE(_range.max);
|
||||
}
|
||||
|
||||
bool IntegerRangeVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream) {
|
||||
bool IntegerRangeVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
|
||||
_range.min = stream->readSint32BE();
|
||||
_range.max = stream->readSint32BE();
|
||||
|
||||
@ -2075,7 +2072,7 @@ void VectorVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream)
|
||||
stream->writeDoubleBE(_vector.magnitude);
|
||||
}
|
||||
|
||||
bool VectorVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream) {
|
||||
bool VectorVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
|
||||
_vector.angleDegrees = stream->readDoubleBE();
|
||||
_vector.magnitude = stream->readDoubleBE();
|
||||
|
||||
@ -2167,7 +2164,7 @@ void PointVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream)
|
||||
stream->writeSint16BE(_value.y);
|
||||
}
|
||||
|
||||
bool PointVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream) {
|
||||
bool PointVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
|
||||
_value.x = stream->readSint16BE();
|
||||
_value.y = stream->readSint16BE();
|
||||
|
||||
@ -2233,7 +2230,7 @@ void FloatingPointVariableModifier::SaveLoad::saveInternal(Common::WriteStream *
|
||||
stream->writeDoubleBE(_value);
|
||||
}
|
||||
|
||||
bool FloatingPointVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream) {
|
||||
bool FloatingPointVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
|
||||
_value = stream->readDoubleBE();
|
||||
|
||||
if (stream->err())
|
||||
@ -2297,7 +2294,7 @@ void StringVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream)
|
||||
stream->writeString(_value);
|
||||
}
|
||||
|
||||
bool StringVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream) {
|
||||
bool StringVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
|
||||
uint32 size = stream->readUint32BE();
|
||||
|
||||
if (stream->err())
|
||||
|
@ -690,7 +690,7 @@ private:
|
||||
explicit SaveLoad(CompoundVariableModifier *modifier);
|
||||
|
||||
void saveInternal(Common::WriteStream *stream) const override;
|
||||
bool loadInternal(Common::ReadStream *stream) override;
|
||||
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
|
||||
void commitLoad() const override;
|
||||
|
||||
private:
|
||||
@ -744,7 +744,7 @@ private:
|
||||
private:
|
||||
void commitLoad() const override;
|
||||
void saveInternal(Common::WriteStream *stream) const override;
|
||||
bool loadInternal(Common::ReadStream *stream) override;
|
||||
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
|
||||
|
||||
BooleanVariableModifier *_modifier;
|
||||
bool _value;
|
||||
@ -779,7 +779,7 @@ private:
|
||||
private:
|
||||
void commitLoad() const override;
|
||||
void saveInternal(Common::WriteStream *stream) const override;
|
||||
bool loadInternal(Common::ReadStream *stream) override;
|
||||
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
|
||||
|
||||
IntegerVariableModifier *_modifier;
|
||||
int32 _value;
|
||||
@ -817,7 +817,7 @@ private:
|
||||
private:
|
||||
void commitLoad() const override;
|
||||
void saveInternal(Common::WriteStream *stream) const override;
|
||||
bool loadInternal(Common::ReadStream *stream) override;
|
||||
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
|
||||
|
||||
IntegerRangeVariableModifier *_modifier;
|
||||
IntRange _range;
|
||||
@ -855,7 +855,7 @@ private:
|
||||
private:
|
||||
void commitLoad() const override;
|
||||
void saveInternal(Common::WriteStream *stream) const override;
|
||||
bool loadInternal(Common::ReadStream *stream) override;
|
||||
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
|
||||
|
||||
VectorVariableModifier *_modifier;
|
||||
AngleMagVector _vector;
|
||||
@ -893,7 +893,7 @@ private:
|
||||
private:
|
||||
void commitLoad() const override;
|
||||
void saveInternal(Common::WriteStream *stream) const override;
|
||||
bool loadInternal(Common::ReadStream *stream) override;
|
||||
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
|
||||
|
||||
PointVariableModifier *_modifier;
|
||||
Common::Point _value;
|
||||
@ -928,7 +928,7 @@ private:
|
||||
private:
|
||||
void commitLoad() const override;
|
||||
void saveInternal(Common::WriteStream *stream) const override;
|
||||
bool loadInternal(Common::ReadStream *stream) override;
|
||||
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
|
||||
|
||||
FloatingPointVariableModifier *_modifier;
|
||||
double _value;
|
||||
@ -963,7 +963,7 @@ private:
|
||||
private:
|
||||
void commitLoad() const override;
|
||||
void saveInternal(Common::WriteStream *stream) const override;
|
||||
bool loadInternal(Common::ReadStream *stream) override;
|
||||
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
|
||||
|
||||
StringVariableModifier *_modifier;
|
||||
Common::String _value;
|
||||
|
@ -120,7 +120,9 @@ Common::Error MTropolisEngine::run() {
|
||||
enhancedColorDepthMode = kColorDepthMode32Bit;
|
||||
|
||||
HackSuites::addObsidianBugFixes(*_gameDescription, _runtime->getHacks());
|
||||
HackSuites::addObsidianAutoSaves(*_gameDescription, _runtime->getHacks(), this);
|
||||
|
||||
if (ConfMan.getBool("mtropolis_mod_auto_save"))
|
||||
HackSuites::addObsidianAutoSaves(*_gameDescription, _runtime->getHacks(), this);
|
||||
|
||||
if (ConfMan.getBool("mtropolis_mod_obsidian_widescreen")) {
|
||||
_runtime->getHacks().reportDisplaySize = Common::Point(640, 480);
|
||||
|
@ -70,6 +70,9 @@ protected:
|
||||
void pauseEngineIntern(bool pause) override;
|
||||
|
||||
private:
|
||||
static const uint kCurrentSaveFileVersion = 1;
|
||||
static const uint kSavegameSignature = 0x6d545356; // mTSV
|
||||
|
||||
Common::ScopedPtr<Runtime> _runtime;
|
||||
};
|
||||
|
||||
|
@ -2201,7 +2201,7 @@ void ObjectReferenceVariableModifier::SaveLoad::saveInternal(Common::WriteStream
|
||||
stream->writeString(_objectPath);
|
||||
}
|
||||
|
||||
bool ObjectReferenceVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream) {
|
||||
bool ObjectReferenceVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
|
||||
uint32 stringLen = stream->readUint32BE();
|
||||
if (stream->err())
|
||||
return false;
|
||||
@ -2805,7 +2805,7 @@ void ListVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream) c
|
||||
recursiveWriteList(_list.get(), stream);
|
||||
}
|
||||
|
||||
bool ListVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream) {
|
||||
bool ListVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
|
||||
Common::SharedPtr<DynamicList> list = recursiveReadList(stream);
|
||||
if (list) {
|
||||
_list = list;
|
||||
|
@ -178,7 +178,7 @@ private:
|
||||
private:
|
||||
void commitLoad() const override;
|
||||
void saveInternal(Common::WriteStream *stream) const override;
|
||||
bool loadInternal(Common::ReadStream *stream) override;
|
||||
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
|
||||
|
||||
ObjectReferenceVariableModifier *_modifier;
|
||||
Common::String _objectPath;
|
||||
@ -326,7 +326,7 @@ private:
|
||||
private:
|
||||
void commitLoad() const override;
|
||||
void saveInternal(Common::WriteStream *stream) const override;
|
||||
bool loadInternal(Common::ReadStream *stream) override;
|
||||
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
|
||||
|
||||
static void recursiveWriteList(DynamicList *list, Common::WriteStream *stream);
|
||||
static Common::SharedPtr<DynamicList> recursiveReadList(Common::ReadStream *stream);
|
||||
|
@ -7520,7 +7520,7 @@ void ModifierSaveLoad::save(Modifier *modifier, Common::WriteStream *stream) {
|
||||
saveInternal(stream);
|
||||
}
|
||||
|
||||
bool ModifierSaveLoad::load(Modifier *modifier, Common::ReadStream *stream) {
|
||||
bool ModifierSaveLoad::load(Modifier *modifier, Common::ReadStream *stream, uint32 saveFileVersion) {
|
||||
uint32 checkGUID = stream->readUint32BE();
|
||||
uint16 nameLen = stream->readUint16BE();
|
||||
|
||||
@ -7544,7 +7544,7 @@ bool ModifierSaveLoad::load(Modifier *modifier, Common::ReadStream *stream) {
|
||||
if (modifier->getStaticGUID() != checkGUID)
|
||||
return false;
|
||||
|
||||
return loadInternal(stream);
|
||||
return loadInternal(stream, saveFileVersion);
|
||||
}
|
||||
|
||||
ModifierHooks::~ModifierHooks() {
|
||||
|
@ -2547,7 +2547,7 @@ public:
|
||||
virtual ~ModifierSaveLoad();
|
||||
|
||||
void save(Modifier *modifier, Common::WriteStream *stream);
|
||||
bool load(Modifier *modifier, Common::ReadStream *stream);
|
||||
bool load(Modifier *modifier, Common::ReadStream *stream, uint32 saveFileVersion);
|
||||
virtual void commitLoad() const = 0;
|
||||
|
||||
protected:
|
||||
@ -2556,7 +2556,7 @@ protected:
|
||||
|
||||
// Loads the modifier state from a stream into the save/load state and returns true
|
||||
// if successful. This will not trigger any actual changes until "commit" is called.
|
||||
virtual bool loadInternal(Common::ReadStream *stream) = 0;
|
||||
virtual bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) = 0;
|
||||
};
|
||||
|
||||
class ModifierHooks {
|
||||
|
@ -20,8 +20,10 @@
|
||||
*/
|
||||
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "gui/message.h"
|
||||
#include "gui/saveload.h"
|
||||
|
||||
#include "mtropolis/mtropolis.h"
|
||||
@ -74,6 +76,10 @@ bool MTropolisEngine::promptSave(ISaveWriter *writer) {
|
||||
|
||||
Common::String saveFileName = getSaveStateName(slot);
|
||||
Common::SharedPtr<Common::OutSaveFile> out(_saveFileMan->openForSaving(saveFileName, false));
|
||||
|
||||
out->writeUint32BE(kSavegameSignature);
|
||||
out->writeUint32BE(kCurrentSaveFileVersion);
|
||||
|
||||
if (!writer->writeSave(out.get()) || out->err())
|
||||
warning("An error occurred while writing file '%s'", saveFileName.c_str());
|
||||
|
||||
@ -96,7 +102,37 @@ bool MTropolisEngine::promptLoad(ISaveReader *reader) {
|
||||
|
||||
Common::String saveFileName = getSaveStateName(slot);
|
||||
Common::SharedPtr<Common::InSaveFile> in(_saveFileMan->openForLoading(saveFileName));
|
||||
if (!reader->readSave(in.get())) {
|
||||
|
||||
uint32 signature = in->readUint32BE();
|
||||
uint32 saveFileVersion = in->readUint32BE();
|
||||
if (in->err()) {
|
||||
GUI::MessageDialog dialog(_("Failed to read version information from save file"));
|
||||
dialog.runModal();
|
||||
|
||||
warning("An error occurred while reading the save file version from '%s'", saveFileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (signature != kSavegameSignature) {
|
||||
GUI::MessageDialog dialog(_("Failed to load save, the save file doesn't contain valid version information."));
|
||||
dialog.runModal();
|
||||
|
||||
warning("Save file '%s' version is above the current save file version", saveFileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (saveFileVersion > kCurrentSaveFileVersion) {
|
||||
GUI::MessageDialog dialog(_("Failed to load save, the save file was created by a newer version of ScummVM."));
|
||||
dialog.runModal();
|
||||
|
||||
warning("Save file '%s' version is above the current save file version", saveFileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!reader->readSave(in.get(), saveFileVersion)) {
|
||||
GUI::MessageDialog dialog(_("Failed to load save, an error occurred when reading the save game data."));
|
||||
dialog.runModal();
|
||||
|
||||
warning("An error occurred while reading file '%s'", saveFileName.c_str());
|
||||
return false;
|
||||
}
|
||||
@ -109,11 +145,17 @@ bool MTropolisEngine::autoSave(ISaveWriter *writer) {
|
||||
|
||||
Common::String saveFileName = getSaveStateName(slot);
|
||||
Common::SharedPtr<Common::OutSaveFile> out(_saveFileMan->openForSaving(saveFileName, false));
|
||||
|
||||
out->writeUint32BE(kSavegameSignature);
|
||||
out->writeUint32BE(kCurrentSaveFileVersion);
|
||||
|
||||
if (!writer->writeSave(out.get()) || out->err())
|
||||
warning("An error occurred while writing file '%s'", saveFileName.c_str());
|
||||
|
||||
getMetaEngine()->appendExtendedSave(out.get(), getTotalPlayTime(), "Auto Save", true);
|
||||
|
||||
g_system->displayMessageOnOSD(_("Progress Saved"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ struct ISaveWriter : public IInterfaceBase {
|
||||
};
|
||||
|
||||
struct ISaveReader : public IInterfaceBase {
|
||||
virtual bool readSave(Common::ReadStream *stream) = 0;
|
||||
virtual bool readSave(Common::ReadStream *stream, uint32 saveFileVersion) = 0;
|
||||
};
|
||||
|
||||
struct ISaveUIProvider : public IInterfaceBase {
|
||||
|
Loading…
Reference in New Issue
Block a user