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

xarc.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 // Based on the Xentax Wiki documentation:
00024 // http://wiki.xentax.com/index.php?title=The_Longest_Journey_XARC
00025 
00026 #include "engines/stark/formats/xarc.h"
00027 #include "engines/stark/debug.h"
00028 
00029 #include "common/debug.h"
00030 #include "common/file.h"
00031 #include "common/substream.h"
00032 
00033 namespace Stark {
00034 namespace Formats {
00035 
00036 // ARCHIVE MEMBER
00037 
00038 class XARCMember : public Common::ArchiveMember {
00039 public:
00040     XARCMember(const XARCArchive *xarc, Common::ReadStream &stream, uint32 offset);
00041 
00042     Common::SeekableReadStream *createReadStream() const;
00043     Common::String getName() const { return _name; }
00044     uint32 getLength() const { return _length; }
00045     uint32 getOffset() const { return _offset; }
00046 
00047 private:
00048     const XARCArchive *_xarc;
00049     Common::String _name;
00050     uint32 _offset;
00051     uint32 _length;
00052 
00053     // Helper function
00054     Common::String readString(Common::ReadStream &stream);
00055 };
00056 
00057 XARCMember::XARCMember(const XARCArchive *xarc, Common::ReadStream &stream, uint32 offset) {
00058     _xarc = xarc;
00059 
00060     // Read the information about this archive member
00061     _name = readString(stream);
00062     _offset = offset;
00063     _length = stream.readUint32LE();
00064     debugC(20, kDebugArchive, "Stark::XARC Member: \"%s\" starts at offset=%d and has length=%d", _name.c_str(), _offset, _length);
00065 
00066     // Unknown value. English: 0, others: 1
00067     uint32 unknown = stream.readUint32LE();
00068     debugC(kDebugUnknown, "Stark::XARC Member: \"%s\" has unknown=%d", _name.c_str(), unknown);
00069     if (unknown != 0 && unknown != 1) {
00070         warning("Stark::XARC Member: \"%s\" has unknown=%d with unknown meaning", _name.c_str(), unknown);
00071     }
00072 }
00073 
00074 Common::SeekableReadStream *XARCMember::createReadStream() const {
00075     return _xarc->createReadStreamForMember(this);
00076 }
00077 
00078 Common::String XARCMember::readString(Common::ReadStream &stream) {
00079     Common::String str;
00080 
00081     // Read until we find a 0
00082     char c = 1;
00083     while (c != 0) {
00084         c = stream.readByte();
00085         if (stream.eos()) {
00086             c = 0;
00087         } else {
00088             str += c;
00089         }
00090     }
00091 
00092     return str;
00093 }
00094 
00095 
00096 // ARCHIVE
00097 
00098 bool XARCArchive::open(const Common::String &filename) {
00099     Common::File stream;
00100     if (!stream.open(filename)) {
00101         return false;
00102     }
00103 
00104     _filename = filename;
00105 
00106     // Unknown: always 1? version?
00107     uint32 unknown = stream.readUint32LE();
00108     debugC(kDebugUnknown, "Stark::XARC: \"%s\" has unknown=%d", _filename.c_str(), unknown);
00109     if (unknown != 1) {
00110         warning("Stark::XARC: \"%s\" has unknown=%d with unknown meaning", _filename.c_str(), unknown);
00111     }
00112 
00113     // Read the number of contained files
00114     uint32 numFiles = stream.readUint32LE();
00115     debugC(20, kDebugArchive, "Stark::XARC: \"%s\" contains %d files", _filename.c_str(), numFiles);
00116 
00117     // Read the offset to the contents of the first file
00118     uint32 offset = stream.readUint32LE();
00119     debugC(20, kDebugArchive, "Stark::XARC: \"%s\"'s first file has offset=%d", _filename.c_str(), offset);
00120 
00121     for (uint32 i = 0; i < numFiles; i++) {
00122         XARCMember *member = new XARCMember(this, stream, offset);
00123         _members.push_back(Common::ArchiveMemberPtr(member));
00124 
00125         // Set the offset to the next member
00126         offset += member->getLength();
00127     }
00128 
00129     return true;
00130 }
00131 
00132 Common::String XARCArchive::getFilename() const {
00133     return _filename;
00134 }
00135 
00136 bool XARCArchive::hasFile(const Common::String &name) const {
00137     for (Common::ArchiveMemberList::const_iterator it = _members.begin(); it != _members.end(); ++it) {
00138         if ((*it)->getName() == name) {
00139             // Found it
00140             return true;
00141         }
00142     }
00143 
00144     // Not found
00145     return false;
00146 }
00147 
00148 int XARCArchive::listMatchingMembers(Common::ArchiveMemberList &list, const Common::String &pattern) const {
00149     int matches = 0;
00150     for (Common::ArchiveMemberList::const_iterator it = _members.begin(); it != _members.end(); ++it) {
00151         if ((*it)->getName().matchString(pattern)) {
00152             // This file matches, add it
00153             list.push_back(*it);
00154             matches++;
00155         }
00156     }
00157 
00158     return matches;
00159 }
00160 
00161 int XARCArchive::listMembers(Common::ArchiveMemberList &list) const {
00162     int files = 0;
00163     for (Common::ArchiveMemberList::const_iterator it = _members.begin(); it != _members.end(); ++it) {
00164         // Add all the members to the list
00165         list.push_back(*it);
00166         files++;
00167     }
00168 
00169     return files;
00170 }
00171 
00172 const Common::ArchiveMemberPtr XARCArchive::getMember(const Common::String &name) const {
00173     for (Common::ArchiveMemberList::const_iterator it = _members.begin(); it != _members.end(); ++it) {
00174         if ((*it)->getName() == name) {
00175             // Found it
00176             return *it;
00177         }
00178     }
00179 
00180     // Not found, return an empty ptr
00181     return Common::ArchiveMemberPtr();
00182 }
00183 
00184 Common::SeekableReadStream *XARCArchive::createReadStreamForMember(const Common::String &name) const {
00185     for (Common::ArchiveMemberList::const_iterator it = _members.begin(); it != _members.end(); ++it) {
00186         if ((*it)->getName() == name) {
00187             // Found it
00188             return createReadStreamForMember((const XARCMember *)it->get());
00189         }
00190     }
00191 
00192     // Not found
00193     return 0;
00194 }
00195 
00196 Common::SeekableReadStream *XARCArchive::createReadStreamForMember(const XARCMember *member) const {
00197     // Open the xarc file
00198     Common::File *f = new Common::File;
00199     if (!f)
00200         return NULL;
00201 
00202     if (!f->open(_filename)) {
00203         delete f;
00204         return NULL;
00205     }
00206 
00207     // Return the substream that contains the archive member
00208     uint32 offset = member->getOffset();
00209     uint32 length = member->getLength();
00210     return new Common::SeekableSubReadStream(f, offset, offset + length, DisposeAfterUse::YES);
00211 
00212     // Different approach: keep the archive open and read full resources to memory
00213     //f.seek(member->getOffset());
00214     //return f.readStream(member->getLength());
00215 }
00216 
00217 } // End of namespace Formats
00218 } // End of namespace Stark


Generated on Sat Apr 20 2019 05:04:20 for ResidualVM by doxygen 1.7.1
curved edge   curved edge