Пример #1
0
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;
}
Пример #2
0
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;
}