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

archiveloader.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/archiveloader.h"
00024 
00025 #include "engines/stark/formats/xrc.h"
00026 #include "engines/stark/resources/level.h"
00027 #include "engines/stark/resources/location.h"
00028 
00029 namespace Stark {
00030 
00031 ArchiveLoader::LoadedArchive::LoadedArchive(const Common::String& archiveName) :
00032         _filename(archiveName),
00033         _root(nullptr),
00034         _useCount(0) {
00035     if (!_xarc.open(archiveName)) {
00036         error("Unable to open archive '%s'", archiveName.c_str());
00037     }
00038 }
00039 
00040 ArchiveLoader::LoadedArchive::~LoadedArchive() {
00041     // Resource lifecycle update
00042     _root->onPreDestroy();
00043 
00044     delete _root;
00045 }
00046 
00047 void ArchiveLoader::LoadedArchive::importResources() {
00048     // Import the resource tree
00049     _root = Formats::XRCReader::importTree(&_xarc);
00050 }
00051 
00052 ArchiveLoader::~ArchiveLoader() {
00053     for (LoadedArchiveList::iterator it = _archives.begin(); it != _archives.end(); it++) {
00054         delete *it;
00055     }
00056 }
00057 
00058 bool ArchiveLoader::load(const Common::String &archiveName) {
00059     if (hasArchive(archiveName)) {
00060         // Already loaded
00061         return false;
00062     }
00063 
00064     LoadedArchive *archive = new LoadedArchive(archiveName);
00065     _archives.push_back(archive);
00066 
00067     archive->importResources();
00068 
00069     return true;
00070 }
00071 
00072 void ArchiveLoader::unloadUnused() {
00073     for (LoadedArchiveList::iterator it = _archives.begin(); it != _archives.end(); it++) {
00074         if (!(*it)->isInUse()) {
00075             delete *it;
00076             it = _archives.erase(it);
00077             it--;
00078         }
00079     }
00080 }
00081 
00082 ArchiveReadStream *ArchiveLoader::getFile(const Common::String &fileName, const Common::String &archiveName) {
00083     LoadedArchive *archive = findArchive(archiveName);
00084     const Formats::XARCArchive &xarc = archive->getXArc();
00085 
00086     Common::SeekableReadStream *stream = xarc.createReadStreamForMember(fileName);
00087     if (!stream) {
00088         return nullptr;
00089     }
00090 
00091     return new ArchiveReadStream(stream);
00092 }
00093 
00094 bool ArchiveLoader::returnRoot(const Common::String &archiveName) {
00095     LoadedArchive *archive = findArchive(archiveName);
00096     archive->decUsage();
00097 
00098     return !archive->isInUse();
00099 }
00100 
00101 bool ArchiveLoader::hasArchive(const Common::String &archiveName) const {
00102     for (LoadedArchiveList::const_iterator it = _archives.begin(); it != _archives.end(); it++) {
00103         if ((*it)->getFilename() == archiveName) {
00104             return true;
00105         }
00106     }
00107 
00108     return false;
00109 }
00110 
00111 ArchiveLoader::LoadedArchive *ArchiveLoader::findArchive(const Common::String &archiveName) const {
00112     for (LoadedArchiveList::const_iterator it = _archives.begin(); it != _archives.end(); it++) {
00113         if ((*it)->getFilename() == archiveName) {
00114             return *it;
00115         }
00116     }
00117 
00118     error("The archive with name '%s' is not loaded.", archiveName.c_str());
00119 }
00120 
00121 Common::String ArchiveLoader::buildArchiveName(Resources::Level *level, Resources::Location *location) const {
00122     Common::String archive;
00123 
00124     if (!location) {
00125         switch (level->getSubType()) {
00126         case 1:
00127             archive = Common::String::format("%s/%s.xarc", level->getName().c_str(), level->getName().c_str());
00128             break;
00129         case 2:
00130             archive = Common::String::format("%02x/%02x.xarc", level->getIndex(), level->getIndex());
00131             break;
00132         default:
00133             error("Unknown level type %d", level->getSubType());
00134         }
00135     } else {
00136         archive = Common::String::format("%02x/%02x/%02x.xarc", level->getIndex(), location->getIndex(), location->getIndex());
00137     }
00138 
00139     return archive;
00140 }
00141 
00142 Common::String ArchiveLoader::getExternalFilePath(const Common::String &fileName, const Common::String &archiveName) const {
00143     static const char separator = '/';
00144 
00145     // Build a path of the type 45/00/
00146     Common::String filePath = archiveName;
00147     while (filePath.lastChar() != separator && !filePath.empty()) {
00148         filePath.deleteLastChar();
00149     }
00150     filePath += "xarc/" + fileName;
00151 
00152     return filePath;
00153 }
00154 
00155 Common::SeekableReadStream *ArchiveLoader::getExternalFile(const Common::String &fileName, const Common::String &archiveName) const {
00156     Common::String filePath = getExternalFilePath(fileName, archiveName);
00157     return SearchMan.createReadStreamForMember(filePath);
00158 }
00159 
00160 ArchiveReadStream::ArchiveReadStream(
00161         Common::SeekableReadStream *parentStream, DisposeAfterUse::Flag disposeParentStream) :
00162         SeekableSubReadStream(parentStream, 0, parentStream->size(), disposeParentStream) {
00163 }
00164 
00165 ArchiveReadStream::~ArchiveReadStream() {
00166 }
00167 
00168 Common::String ArchiveReadStream::readString() {
00169     // Read the string length
00170     uint32 length = readUint32LE();
00171 
00172     // Read the string
00173     char *data = new char[length + 1];
00174     read(data, length);
00175     data[length] = '\0';
00176 
00177     Common::String string(data);
00178     delete[] data;
00179 
00180     return string;
00181 }
00182 
00183 Common::String ArchiveReadStream::readString16() {
00184     // Read the string length
00185     uint16 length = readUint16LE();
00186 
00187     // Read the string
00188     char *data = new char[length + 1];
00189     read(data, length);
00190     data[length] = '\0';
00191 
00192     Common::String string(data);
00193     delete[] data;
00194 
00195     return string;
00196 }
00197 
00198 Math::Vector3d ArchiveReadStream::readVector3() {
00199     Math::Vector3d v;
00200     v.readFromStream(this);
00201     return v;
00202 }
00203 
00204 Math::Quaternion ArchiveReadStream::readQuaternion() {
00205     Math::Quaternion q;
00206     q.readFromStream(this);
00207     return q;
00208 }
00209 
00210 float ArchiveReadStream::readFloat() {
00211     float f;
00212     read(&f, sizeof(float));
00213     return f;
00214 }
00215 
00216 } // End of namespace Stark


Generated on Sat Jul 20 2019 05:00:58 for ResidualVM by doxygen 1.7.1
curved edge   curved edge