[Scummvm-git-logs] scummvm master -> 37791c4bd3b33aa042fc966d4ed2b1f5369b0939
bgK
bastien.bouclet at gmail.com
Sun May 20 15:18:31 CEST 2018
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
37791c4bd3 MOHAWK: RIVEN: Add Autosave Support
Commit: 37791c4bd3b33aa042fc966d4ed2b1f5369b0939
https://github.com/scummvm/scummvm/commit/37791c4bd3b33aa042fc966d4ed2b1f5369b0939
Author: David Fioramonti (dafioram at gmail.com)
Date: 2018-05-20T15:17:14+02:00
Commit Message:
MOHAWK: RIVEN: Add Autosave Support
The game will autosave to slot 0 using the save
period given in the scummvm config file.
Or when the user quits.
Autosaves are only allowed when an autosave is
in slot 0, there is no save in slot 0, or there
is a save, but it is corrupt.
This will not override any saves the player
has previously put in save slot 0. If there
is a save in slot 0 that is not an autosave
then there will be no autosaving.
Changed paths:
engines/mohawk/riven.cpp
engines/mohawk/riven.h
engines/mohawk/riven_saveload.cpp
engines/mohawk/riven_saveload.h
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 0bf4024..8139c1a 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -71,6 +71,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio
_optionsDialog = nullptr;
_card = nullptr;
_inventory = nullptr;
+ _lastSaveTime = 0;
DebugMan.addDebugChannel(kRivenDebugScript, "Script", "Track Script Execution");
DebugMan.addDebugChannel(kRivenDebugPatches, "Patches", "Track Script Patching");
@@ -240,6 +241,12 @@ void MohawkEngine_Riven::doFrame() {
loadGameStateAndDisplayError(_optionsDialog->getLoadSlot());
if (_optionsDialog->getSaveSlot() >= 0)
saveGameStateAndDisplayError(_optionsDialog->getSaveSlot(), _optionsDialog->getSaveDescription());
+
+ if (hasGameEnded()) {
+ // Attempt to autosave before exiting
+ tryAutoSaving();
+ }
+
_gfx->setTransitionMode((RivenTransitionMode) _vars["transitionmode"]);
_card->initializeZipMode();
break;
@@ -281,6 +288,11 @@ void MohawkEngine_Riven::doFrame() {
break;
}
break;
+ case Common::EVENT_QUIT:
+ case Common::EVENT_RTL:
+ // Attempt to autosave before exiting
+ tryAutoSaving();
+ break;
default:
break;
}
@@ -294,6 +306,10 @@ void MohawkEngine_Riven::doFrame() {
_scriptMan->runQueuedScripts();
}
+ if (shouldPerformAutoSave(_lastSaveTime)) {
+ tryAutoSaving();
+ }
+
_inventory->onFrame();
// Update the screen once per frame
@@ -575,7 +591,7 @@ void MohawkEngine_Riven::loadGameStateAndDisplayError(int slot) {
}
Common::Error MohawkEngine_Riven::saveGameState(int slot, const Common::String &desc) {
- return _saveLoad->saveGame(slot, desc);
+ return _saveLoad->saveGame(slot, desc, false);
}
void MohawkEngine_Riven::saveGameStateAndDisplayError(int slot, const Common::String &desc) {
@@ -589,6 +605,23 @@ void MohawkEngine_Riven::saveGameStateAndDisplayError(int slot, const Common::St
}
}
+void MohawkEngine_Riven::tryAutoSaving() {
+ if (!canSaveGameStateCurrently()) {
+ return; // Can't save right now, try again on the next frame
+ }
+
+ _lastSaveTime = _system->getMillis();
+
+ if (!_saveLoad->isAutoSaveAllowed()) {
+ return; // Can't autosave ever, try again after the next autosave delay
+ }
+
+ Common::Error saveError = _saveLoad->saveGame(RivenSaveLoad::kAutoSaveSlot, "Autosave", true);
+ if (saveError.getCode() != Common::kNoError)
+ warning("Attempt to autosave has failed.");
+}
+
+
void MohawkEngine_Riven::addZipVisitedCard(uint16 cardId, uint16 cardNameId) {
Common::String cardName = getStack()->getName(kCardNames, cardNameId);
if (cardName.empty())
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index 6ad1208..3dc19c7 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -121,6 +121,7 @@ private:
RivenStack *_stack;
bool _gameEnded;
+ uint32 _lastSaveTime;
// Variables
void initVars();
@@ -152,6 +153,7 @@ public:
// Save / Load
void runLoadDialog();
void runSaveDialog();
+ void tryAutoSaving();
void loadGameStateAndDisplayError(int slot);
void saveGameStateAndDisplayError(int slot, const Common::String &desc);
diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp
index 1d9ae21..5ba0e51 100644
--- a/engines/mohawk/riven_saveload.cpp
+++ b/engines/mohawk/riven_saveload.cpp
@@ -38,10 +38,11 @@ RivenSaveMetadata::RivenSaveMetadata() {
saveHour = 0;
saveMinute = 0;
totalPlayTime = 0;
+ autoSave = false;
}
bool RivenSaveMetadata::sync(Common::Serializer &s) {
- static const Common::Serializer::Version kCurrentVersion = 1;
+ static const Common::Serializer::Version kCurrentVersion = 2;
if (!s.syncVersion(kCurrentVersion)) {
return false;
@@ -54,10 +55,13 @@ bool RivenSaveMetadata::sync(Common::Serializer &s) {
s.syncAsByte(saveMinute);
s.syncString(saveDescription);
s.syncAsUint32BE(totalPlayTime);
+ s.syncAsByte(autoSave, 2);
return true;
}
+const int RivenSaveLoad::kAutoSaveSlot = 0;
+
RivenSaveLoad::RivenSaveLoad(MohawkEngine_Riven *vm, Common::SaveFileManager *saveFileMan) : _vm(vm), _saveFileMan(saveFileMan) {
}
@@ -105,22 +109,25 @@ Common::String RivenSaveLoad::querySaveDescription(const int slot) {
SaveStateDescriptor RivenSaveLoad::querySaveMetaInfos(const int slot) {
Common::String filename = buildSaveFilename(slot);
Common::InSaveFile *loadFile = g_system->getSavefileManager()->openForLoading(filename);
+ SaveStateDescriptor descriptor;
+ descriptor.setWriteProtectedFlag(slot == kAutoSaveSlot);
+
if (!loadFile) {
- return SaveStateDescriptor();
+ return descriptor;
}
MohawkArchive mhk;
if (!mhk.openStream(loadFile)) {
- return SaveStateDescriptor();
+ return descriptor;
}
if (!mhk.hasResource(ID_META, 1)) {
- return SaveStateDescriptor();
+ return descriptor;
}
Common::SeekableReadStream *metaStream = mhk.getResource(ID_META, 1);
if (!metaStream) {
- return SaveStateDescriptor();
+ return descriptor;
}
Common::Serializer serializer = Common::Serializer(metaStream, nullptr);
@@ -128,14 +135,14 @@ SaveStateDescriptor RivenSaveLoad::querySaveMetaInfos(const int slot) {
RivenSaveMetadata metadata;
if (!metadata.sync(serializer)) {
delete metaStream;
- return SaveStateDescriptor();
+ return descriptor;
}
- SaveStateDescriptor descriptor;
descriptor.setDescription(metadata.saveDescription);
descriptor.setPlayTime(metadata.totalPlayTime);
descriptor.setSaveDate(metadata.saveYear, metadata.saveMonth, metadata.saveDay);
descriptor.setSaveTime(metadata.saveHour, metadata.saveMinute);
+ descriptor.setDeletableFlag(slot != kAutoSaveSlot);
delete metaStream;
@@ -159,6 +166,40 @@ SaveStateDescriptor RivenSaveLoad::querySaveMetaInfos(const int slot) {
return descriptor;
}
+bool RivenSaveLoad::isAutoSaveAllowed() {
+ // Open autosave slot and see if it an autosave
+ // Autosaving will be enabled if it is an autosave or if there is no save in that slot
+
+ Common::String filename = buildSaveFilename(kAutoSaveSlot);
+ Common::InSaveFile *loadFile = g_system->getSavefileManager()->openForLoading(filename);
+ if (!loadFile) {
+ return true; // There is no save in the autosave slot, enable autosave
+ }
+
+ MohawkArchive mhk;
+ if (!mhk.openStream(loadFile)) {
+ return true; // Corrupt save, enable autosave
+ }
+
+ if (!mhk.hasResource(ID_META, 1)) {
+ return false; // don't autosave over saves that don't have a meta section (like saves from the original)
+ }
+
+ Common::ScopedPtr<Common::SeekableReadStream> metaStream(mhk.getResource(ID_META, 1));
+ if (!metaStream) {
+ return true; // corrupt save, enable autosave
+ }
+
+ Common::Serializer serializer = Common::Serializer(metaStream.get(), nullptr);
+
+ RivenSaveMetadata metadata;
+ if (!metadata.sync(serializer)) {
+ return true; // corrupt save, enable autosave
+ }
+
+ return metadata.autoSave;
+}
+
Common::Error RivenSaveLoad::loadGame(const int slot) {
if (_vm->getFeatures() & GF_DEMO) // Don't load games in the demo
return Common::kNoError;
@@ -379,7 +420,7 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genTHMBSection() const {
return stream;
}
-Common::MemoryWriteStreamDynamic *RivenSaveLoad::genMETASection(const Common::String &desc) const {
+Common::MemoryWriteStreamDynamic *RivenSaveLoad::genMETASection(const Common::String &desc, bool autoSave) const {
Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
Common::Serializer serializer = Common::Serializer(nullptr, stream);
@@ -394,12 +435,13 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genMETASection(const Common::St
metadata.saveMinute = t.tm_min;
metadata.saveDescription = desc;
metadata.totalPlayTime = _vm->getTotalPlayTime();
+ metadata.autoSave = autoSave;
metadata.sync(serializer);
return stream;
}
-Common::Error RivenSaveLoad::saveGame(const int slot, const Common::String &description) {
+Common::Error RivenSaveLoad::saveGame(const int slot, const Common::String &description, bool autoSave) {
// NOTE: This code is designed to only output a Mohawk archive
// for a Riven saved game. It's hardcoded to do this because
// (as of right now) this is the only place in the engine
@@ -415,7 +457,7 @@ Common::Error RivenSaveLoad::saveGame(const int slot, const Common::String &desc
debug (0, "Saving game to \'%s\'", filename.c_str());
- Common::MemoryWriteStreamDynamic *metaSection = genMETASection(description);
+ Common::MemoryWriteStreamDynamic *metaSection = genMETASection(description, autoSave);
Common::MemoryWriteStreamDynamic *nameSection = genNAMESection();
Common::MemoryWriteStreamDynamic *thmbSection = genTHMBSection();
Common::MemoryWriteStreamDynamic *varsSection = genVARSSection();
diff --git a/engines/mohawk/riven_saveload.h b/engines/mohawk/riven_saveload.h
index 34bfbdc..1432505 100644
--- a/engines/mohawk/riven_saveload.h
+++ b/engines/mohawk/riven_saveload.h
@@ -49,6 +49,8 @@ struct RivenSaveMetadata {
uint32 totalPlayTime;
+ bool autoSave;
+
Common::String saveDescription;
RivenSaveMetadata();
@@ -57,11 +59,14 @@ struct RivenSaveMetadata {
class RivenSaveLoad {
public:
+ static const int kAutoSaveSlot;
+
RivenSaveLoad(MohawkEngine_Riven*, Common::SaveFileManager*);
~RivenSaveLoad();
Common::Error loadGame(const int slot);
- Common::Error saveGame(const int slot, const Common::String &description);
+ Common::Error saveGame(const int slot, const Common::String &description, bool autoSave);
+ bool isAutoSaveAllowed();
static void deleteSave(const int slot);
static SaveStateDescriptor querySaveMetaInfos(const int slot);
@@ -74,7 +79,7 @@ private:
static Common::String buildSaveFilename(const int slot);
Common::MemoryWriteStreamDynamic *genNAMESection();
- Common::MemoryWriteStreamDynamic *genMETASection(const Common::String &desc) const;
+ Common::MemoryWriteStreamDynamic *genMETASection(const Common::String &desc, bool autoSave) const;
Common::MemoryWriteStreamDynamic *genTHMBSection() const;
Common::MemoryWriteStreamDynamic *genVARSSection();
Common::MemoryWriteStreamDynamic *genVERSSection();
More information about the Scummvm-git-logs
mailing list