ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

stateprovider.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/services/stateprovider.h"
00024 
00025 #include "common/memstream.h"
00026 
00027 #include "engines/stark/resources/level.h"
00028 #include "engines/stark/resources/location.h"
00029 #include "engines/stark/resources/object.h"
00030 
00031 namespace Stark {
00032 
00033 StateReadStream::StateReadStream(Common::SeekableReadStream *parentStream, DisposeAfterUse::Flag disposeParentStream) :
00034         SeekableSubReadStream(parentStream, 0, parentStream->size(), disposeParentStream) {
00035 }
00036 
00037 StateReadStream::~StateReadStream() {
00038 }
00039 
00040 Common::String StateReadStream::readString() {
00041     // Read the string length
00042     uint32 length = readUint32LE();
00043 
00044     // Read the string
00045     char *data = new char[length];
00046     read(data, length);
00047     Common::String string(data, length);
00048     delete[] data;
00049 
00050     return string;
00051 }
00052 
00053 StateProvider::ResourceTreeState::ResourceTreeState(uint32 size, byte *data, uint32 version) :
00054     _size(size),
00055     _data(data),
00056     _version(version) {
00057 }
00058 
00059 StateProvider::ResourceTreeState::~ResourceTreeState() {
00060     free(_data);
00061 }
00062 
00063 StateProvider::~StateProvider() {
00064     clear();
00065 }
00066 
00067 void StateProvider::clear() {
00068     for (ResourceTreeStateMap::iterator it = _stateStore.begin(); it != _stateStore.end(); it++) {
00069         delete it->_value;
00070     }
00071     _stateStore.clear();
00072 }
00073 
00074 void StateProvider::restoreLevelState(Resources::Level *level) {
00075     Common::String storeKey = level->getName();
00076 
00077     restoreResourceTreeState(storeKey, level, false);
00078 }
00079 
00080 void StateProvider::restoreCurrentLevelState(Resources::Level *level) {
00081     restoreResourceTreeState("Current", level, true);
00082 }
00083 
00084 void StateProvider::restoreLocationState(Resources::Level *level, Resources::Location *location) {
00085     Common::String storeKey = level->getName() + location->getName();
00086 
00087     restoreResourceTreeState(storeKey, location, false);
00088 }
00089 
00090 void StateProvider::restoreCurrentLocationState(Resources::Level *level, Resources::Location *location) {
00091     restoreResourceTreeState("CurrentCurrent", location, true);
00092 }
00093 
00094 void StateProvider::restoreGlobalState(Resources::Level *level) {
00095     restoreResourceTreeState("CurrentGlobal", level, true);
00096 }
00097 
00098 void StateProvider::restoreResourceTreeState(const Common::String &storeKey, Resources::Object *root, bool current) {
00099     if (_stateStore.contains(storeKey)) {
00100         ResourceTreeState *state = _stateStore[storeKey];
00101 
00102         Common::MemoryReadStream stream(state->getData(), state->getSize(), DisposeAfterUse::NO);
00103         readResourceTree(root, &stream, current, state->getVersion());
00104     }
00105 }
00106 
00107 void StateProvider::readResourceTree(Resources::Object *resource, Common::SeekableReadStream *stream, bool current, uint32 version) {
00108     // Read the resource to the source stream
00109     /* byte type = */ stream->readByte();
00110     /* byte subType = */ stream->readByte();
00111     uint32 size = stream->readUint32LE();
00112 
00113     if (size > 0) {
00114         Common::SeekableReadStream *resourceStream = stream->readStream(size);
00115         ResourceSerializer serializer(resourceStream, nullptr, version);
00116 
00117         // Deserialize the resource state from stream
00118         if (current) {
00119             resource->saveLoadCurrent(&serializer);
00120         } else {
00121             resource->saveLoad(&serializer);
00122         }
00123 
00124         delete resourceStream;
00125     }
00126 
00127     // Deserialize the resource children
00128     Common::Array<Resources::Object *> children = resource->listChildren<Resources::Object>();
00129     for (uint i = 0; i < children.size(); i++) {
00130         readResourceTree(children[i], stream, current, version);
00131     }
00132 }
00133 
00134 void StateProvider::saveLevelState(Resources::Level *level) {
00135     Common::String storeKey = level->getName();
00136 
00137     saveResourceTreeState(storeKey, level, false);
00138 }
00139 
00140 void StateProvider::saveCurrentLevelState(Resources::Level *level) {
00141     saveResourceTreeState("Current", level, true);
00142 }
00143 
00144 void StateProvider::saveLocationState(Resources::Level *level, Resources::Location *location) {
00145     Common::String storeKey = level->getName() + location->getName();
00146 
00147     saveResourceTreeState(storeKey, location, false);
00148 }
00149 
00150 void StateProvider::saveCurrentLocationState(Resources::Level *level, Resources::Location *location) {
00151     saveResourceTreeState("CurrentCurrent", location, true);
00152 }
00153 
00154 void StateProvider::saveGlobalState(Resources::Level *level) {
00155     saveResourceTreeState("CurrentGlobal", level, true);
00156 }
00157 
00158 void StateProvider::saveResourceTreeState(const Common::String &storeKey, Resources::Object *root, bool current) {
00159     // Delete any previous data
00160     if (_stateStore.contains(storeKey)) {
00161         delete _stateStore[storeKey];
00162         _stateStore.erase(storeKey);
00163     }
00164 
00165     // Write the tree state to memory
00166     Common::MemoryWriteStreamDynamic stream(DisposeAfterUse::NO);
00167     writeResourceTree(root, &stream, current);
00168 
00169     // Add the state to the store
00170     _stateStore[storeKey] = new ResourceTreeState(stream.size(), stream.getData(), kSaveVersion);
00171 }
00172 
00173 void StateProvider::writeResourceTree(Resources::Object *resource, Common::WriteStream *stream, bool current) {
00174     // Explicit scope to control the lifespan of the memory stream
00175     {
00176         Common::MemoryWriteStreamDynamic resourceStream(DisposeAfterUse::YES);
00177         ResourceSerializer serializer(nullptr, &resourceStream, kSaveVersion);
00178 
00179         // Serialize the resource to a memory stream
00180         if (current) {
00181             resource->saveLoadCurrent(&serializer);
00182         } else {
00183             resource->saveLoad(&serializer);
00184         }
00185 
00186         // Write the resource to the target stream
00187         stream->writeByte(resource->getType().get());
00188         stream->writeByte(resource->getSubType());
00189         stream->writeUint32LE(resourceStream.size());
00190         stream->write(resourceStream.getData(), resourceStream.size());
00191     }
00192 
00193     // Serialize the resource children
00194     Common::Array<Resources::Object *> children = resource->listChildren<Resources::Object>();
00195     for (uint i = 0; i < children.size(); i++) {
00196         writeResourceTree(children[i], stream, current);
00197     }
00198 }
00199 
00200 void StateProvider::readStateFromStream(StateReadStream *stream, uint saveVersion) {
00201     clear();
00202 
00203     uint32 treeCount = stream->readUint32LE();
00204     for (uint i = 0; i < treeCount; i++) {
00205         // Read the store key
00206         Common::String key = stream->readString();
00207 
00208         // Each resource tree state needs to have its own version because
00209         // some may never be made active again and serialized in the latest version.
00210         // In that case they stay in a previous version.
00211         uint treeVersion = 6;
00212         if (saveVersion > 6) {
00213             treeVersion = stream->readUint32LE();
00214         }
00215 
00216         // Read the data size
00217         uint32 dataSize = stream->readUint32LE();
00218 
00219         // Read the data
00220         byte *data = (byte *) malloc(dataSize);
00221         stream->read(data, dataSize);
00222 
00223         _stateStore[key] = new ResourceTreeState(dataSize, data, treeVersion);
00224     }
00225 }
00226 
00227 void StateProvider::writeStateToStream(Common::WriteStream *stream) {
00228     stream->writeUint32LE(_stateStore.size());
00229 
00230     for (ResourceTreeStateMap::iterator it = _stateStore.begin(); it != _stateStore.end(); it++) {
00231         stream->writeUint32LE(it->_key.size());
00232         stream->writeString(it->_key);
00233         stream->writeUint32LE(it->_value->getVersion());
00234         stream->writeUint32LE(it->_value->getSize());
00235         stream->write(it->_value->getData(), it->_value->getSize());
00236     }
00237 }
00238 
00239 ResourceSerializer::ResourceSerializer(Common::SeekableReadStream *in, Common::WriteStream *out, uint32 version) :
00240         Common::Serializer(in, out) {
00241     _version = version;
00242 }
00243 
00244 void ResourceSerializer::syncAsFloat(float &value) {
00245     if (isLoading()) {
00246         value = _loadStream->readFloatLE();
00247     } else {
00248         _saveStream->writeFloatLE(value);
00249     }
00250 }
00251 
00252 void ResourceSerializer::syncAsVector3d(Math::Vector3d &value) {
00253     syncAsFloat(value.x());
00254     syncAsFloat(value.y());
00255     syncAsFloat(value.z());
00256 }
00257 
00258 void ResourceSerializer::syncAsResourceReference(ResourceReference &reference) {
00259     if (isLoading()) {
00260         reference.loadFromStream(_loadStream);
00261     } else {
00262         reference.saveToStream(_saveStream);
00263     }
00264 }
00265 
00266 void ResourceSerializer::syncAsString32(Common::String &string) {
00267     if (isLoading()) {
00268         string.clear();
00269 
00270         uint32 length = _loadStream->readUint32LE();
00271         for (uint i = 0; i < length; i++) {
00272             char c = _loadStream->readByte();
00273             string += c;
00274         }
00275 
00276         _bytesSynced += 4 + length;
00277     } else {
00278         _saveStream->writeUint32LE(string.size());
00279         _saveStream->writeString(string);
00280         _bytesSynced += 4 + string.size();
00281     }
00282 }
00283 
00284 } // End of namespace Stark


Generated on Sat May 18 2019 05:01:21 for ResidualVM by doxygen 1.7.1
curved edge   curved edge