Skip to content

Commit

Permalink
TSAGE: Fix loading savegames with unreferenced dynamic objects
Browse files Browse the repository at this point in the history
  • Loading branch information
dreammaster committed Nov 22, 2017
1 parent 89d20ba commit 13f7402
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 3 deletions.
14 changes: 12 additions & 2 deletions engines/tsage/saveload.cpp
Expand Up @@ -211,12 +211,14 @@ Common::Error Saver::restore(int slot) {
// Note: I don't store pointers to instantiated objects here, because it's not necessary - the mere act
// of instantiating a saved object registers it with the saver, and will then be resolved to whatever
// object originally had a pointer to it as part of the post-processing step
DynObjects dynObjects;
Common::String className;
serializer.syncString(className);
while (className != "END") {
SavedObject *savedObject;
if (!_factoryPtr || ((savedObject = _factoryPtr(className)) == NULL))
error("Unknown class name '%s' encountered trying to restore savegame", className.c_str());
dynObjects.push_back(savedObject);

// Populate the contents of the object
savedObject->synchronize(serializer);
Expand All @@ -226,7 +228,12 @@ Common::Error Saver::restore(int slot) {
}

// Post-process any unresolved pointers to get the correct pointer
resolveLoadPointers();
resolveLoadPointers(dynObjects);

// Post-process safety check: if any dynamically created objects didn't get any
// references, then delete them, since they'd never be freed otherwise
for (DynObjects::iterator i = dynObjects.begin(); i != dynObjects.end(); ++i)
delete *i;

delete saveFile;

Expand Down Expand Up @@ -392,7 +399,7 @@ void Saver::listObjects() {
/**
* Returns the pointer associated with the specified object index
*/
void Saver::resolveLoadPointers() {
void Saver::resolveLoadPointers(DynObjects &dynObjects) {
if (_unresolvedPtrs.size() == 0)
// Nothing to resolve
return;
Expand All @@ -410,6 +417,9 @@ void Saver::resolveLoadPointers() {
SavedObject **objPP = r._savedObject;
*objPP = pObj;
iPtr = _unresolvedPtrs.erase(iPtr);

// If it's a dynamic object, remove it from the dynamic objects list
dynObjects.remove(pObj);
} else {
++iPtr;
}
Expand Down
3 changes: 2 additions & 1 deletion engines/tsage/saveload.h
Expand Up @@ -201,6 +201,7 @@ class SavedObjectRef {
typedef SavedObject *(*SavedObjectFactory)(const Common::String &className);

class Saver {
typedef Common::List<SavedObject *> DynObjects;
private:
Common::List<SavedObject *> _objList;
FunctionList<bool> _saveNotifiers;
Expand All @@ -213,7 +214,7 @@ class Saver {
bool _macroSaveFlag;
bool _macroRestoreFlag;

void resolveLoadPointers();
void resolveLoadPointers(DynObjects &dynObjects);
public:
Saver();
~Saver();
Expand Down

0 comments on commit 13f7402

Please sign in to comment.