Common::Error Saver::save(int slot, const Common::String &saveName) { assert(!getMacroRestoreFlag()); Common::StackLock slock1(g_globals->_soundManager._serverDisabledMutex); // Signal any objects registered for notification _saveNotifiers.notify(false); // Set fields _macroSaveFlag = true; _saveSlot = slot; // Try and create the save file Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(g_vm->generateSaveName(slot)); if (!saveFile) return Common::kCreatingFileFailed; // Set up the serializer Serializer serializer(NULL, saveFile); serializer.setSaveVersion(TSAGE_SAVEGAME_VERSION); // Write out the savegame header tSageSavegameHeader header; header.saveName = saveName; header.version = TSAGE_SAVEGAME_VERSION; writeSavegameHeader(saveFile, header); // Save out objects that need to come at the start of the savegame for (SynchronizedList<SaveListener *>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) { (*i)->listenerSynchronize(serializer); } // Save each registered SaveObject descendant object into the savegame file for (SynchronizedList<SavedObject *>::iterator i = _objList.begin(); i != _objList.end(); ++i) { SavedObject *so = *i; serializer.validate(so->getClassName()); so->synchronize(serializer); } // Save file complete saveFile->writeString("END"); saveFile->finalize(); delete saveFile; // Final post-save notification _macroSaveFlag = false; _saveNotifiers.notify(true); return Common::kNoError; }
Common::Error Saver::restore(int slot) { assert(!getMacroRestoreFlag()); Common::StackLock slock1(g_globals->_soundManager._serverDisabledMutex); // Signal any objects registered for notification _loadNotifiers.notify(false); // Set fields _macroRestoreFlag = true; _unresolvedPtrs.clear(); // Set up the serializer Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(g_vm->generateSaveName(slot)); if (!saveFile) return Common::kReadingFailed; Serializer serializer(saveFile, NULL); // Read in the savegame header tSageSavegameHeader header; readSavegameHeader(saveFile, header); if (header.thumbnail) header.thumbnail->free(); delete header.thumbnail; serializer.setSaveVersion(header.version); // Load in data for objects that need to come at the start of the savegame for (Common::List<SaveListener *>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) { (*i)->listenerSynchronize(serializer); } // Loop through each registered object to load in the data for (SynchronizedList<SavedObject *>::iterator i = _objList.begin(); i != _objList.end(); ++i) { serializer.validate((*i)->getClassName()); (*i)->synchronize(serializer); } // Loop through the remaining data of the file, instantiating new objects. // 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 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()); // Populate the contents of the object savedObject->synchronize(serializer); // Move to next object serializer.syncString(className); } // Post-process any unresolved pointers to get the correct pointer resolveLoadPointers(); delete saveFile; // Final post-restore notifications _macroRestoreFlag = false; _loadNotifiers.notify(true); return Common::kNoError; }