[Scummvm-cvs-logs] SF.net SVN: scummvm:[52346] scummvm/trunk/engines/kyra
lordhoto at users.sourceforge.net
lordhoto at users.sourceforge.net
Tue Aug 24 17:47:54 CEST 2010
Revision: 52346
http://scummvm.svn.sourceforge.net/scummvm/?rev=52346&view=rev
Author: lordhoto
Date: 2010-08-24 15:47:53 +0000 (Tue, 24 Aug 2010)
Log Message:
-----------
KYRA: Simplify PAK/INS/TLK loading.
This also reduces the number of seeks done while loading TLK files.
Modified Paths:
--------------
scummvm/trunk/engines/kyra/resource_intern.cpp
scummvm/trunk/engines/kyra/resource_intern.h
Modified: scummvm/trunk/engines/kyra/resource_intern.cpp
===================================================================
--- scummvm/trunk/engines/kyra/resource_intern.cpp 2010-08-24 15:11:53 UTC (rev 52345)
+++ scummvm/trunk/engines/kyra/resource_intern.cpp 2010-08-24 15:47:53 UTC (rev 52346)
@@ -35,16 +35,8 @@
// -> PlainArchive implementation
-PlainArchive::PlainArchive(Common::SharedPtr<Common::ArchiveMember> file, const FileInputList &files)
+PlainArchive::PlainArchive(Common::SharedPtr<Common::ArchiveMember> file)
: _file(file), _files() {
- for (FileInputList::const_iterator i = files.begin(); i != files.end(); ++i) {
- Entry entry;
-
- entry.offset = i->offset;
- entry.size = i->size;
-
- _files[i->name] = entry;
- }
}
bool PlainArchive::hasFile(const Common::String &name) {
@@ -81,6 +73,17 @@
return new Common::SeekableSubReadStream(parent, fDesc->_value.offset, fDesc->_value.offset + fDesc->_value.size, DisposeAfterUse::YES);
}
+void PlainArchive::addFileEntry(const Common::String &name, const Entry entry) {
+ _files[name] = entry;
+}
+
+PlainArchive::Entry PlainArchive::getFileEntry(const Common::String &name) const {
+ FileMap::const_iterator fDesc = _files.find(name);
+ if (fDesc == _files.end())
+ return Entry();
+ return fDesc->_value;
+}
+
// -> CachedArchive implementation
CachedArchive::CachedArchive(const FileInputList &files)
@@ -154,16 +157,6 @@
return result;
}
-struct PlainArchiveListSearch {
- PlainArchiveListSearch(const Common::String &search) : _search(search) {}
-
- bool operator()(const PlainArchive::InputEntry &entry) {
- return _search.equalsIgnoreCase(entry.name);
- }
-
- const Common::String _search;
-};
-
} // end of anonymous namespace
bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const {
@@ -215,6 +208,10 @@
if (filesize < 0)
return 0;
+ Common::ScopedPtr<PlainArchive> result(new PlainArchive(memberFile));
+ if (!result)
+ return 0;
+
int32 startoffset = 0, endoffset = 0;
bool switchEndian = false;
bool firstFile = true;
@@ -225,8 +222,6 @@
startoffset = SWAP_BYTES_32(startoffset);
}
- PlainArchive::FileInputList files;
-
Common::String file;
while (!stream.eos()) {
// The start offset of a file should never be in the filelist
@@ -263,53 +258,41 @@
if (!endoffset)
endoffset = filesize;
- if (startoffset != endoffset) {
- PlainArchive::InputEntry entry;
- entry.size = endoffset - startoffset;
- entry.offset = startoffset;
- entry.name = file;
+ if (startoffset != endoffset)
+ result->addFileEntry(file, PlainArchive::Entry(startoffset, endoffset - startoffset));
- files.push_back(entry);
- }
-
if (endoffset == filesize)
break;
startoffset = endoffset;
}
- PlainArchive::FileInputList::const_iterator iter = Common::find_if(files.begin(), files.end(), PlainArchiveListSearch("LINKLIST"));
- if (iter != files.end()) {
- stream.seek(iter->offset, SEEK_SET);
+ PlainArchive::Entry linklistFile = result->getFileEntry("LINKLIST");
+ if (linklistFile.size != 0) {
+ stream.seek(linklistFile.offset, SEEK_SET);
- uint32 magic = stream.readUint32BE();
+ const uint32 magic = stream.readUint32BE();
if (magic != MKID_BE('SCVM'))
error("LINKLIST file does not contain 'SCVM' header");
- uint32 links = stream.readUint32BE();
- for (uint i = 0; i < links; ++i) {
- Common::String linksTo = readString(stream);
- uint32 sources = stream.readUint32BE();
+ const uint32 links = stream.readUint32BE();
+ for (uint32 i = 0; i < links; ++i) {
+ const Common::String linksTo = readString(stream);
+ const uint32 sources = stream.readUint32BE();
- iter = Common::find_if(files.begin(), files.end(), PlainArchiveListSearch(linksTo));
- if (iter == files.end())
+ PlainArchive::Entry destination = result->getFileEntry(linksTo);
+ if (destination.size == 0)
error("PAK file link destination '%s' not found", linksTo.c_str());
- for (uint j = 0; j < sources; ++j) {
- Common::String dest = readString(stream);
-
- PlainArchive::InputEntry link = *iter;
- link.name = dest;
- files.push_back(link);
-
- // Better safe than sorry, we update the 'iter' value, in case push_back invalidated it
- iter = Common::find_if(files.begin(), files.end(), PlainArchiveListSearch(linksTo));
+ for (uint32 j = 0; j < sources; ++j) {
+ const Common::String dest = readString(stream);
+ result->addFileEntry(dest, destination);
}
}
}
- return new PlainArchive(memberFile, files);
+ return result.release();
}
// -> ResLoaderInsMalcolm implementation
@@ -337,7 +320,9 @@
Common::Archive *ResLoaderInsMalcolm::load(Common::SharedPtr<Common::ArchiveMember> memberFile, Common::SeekableReadStream &stream) const {
Common::List<Common::String> filenames;
- PlainArchive::FileInputList files;
+ Common::ScopedPtr<PlainArchive> result(new PlainArchive(memberFile));
+ if (!result)
+ return 0;
// thanks to eriktorbjorn for this code (a bit modified though)
stream.seek(3, SEEK_SET);
@@ -366,17 +351,14 @@
stream.seek(3, SEEK_SET);
for (Common::List<Common::String>::iterator file = filenames.begin(); file != filenames.end(); ++file) {
- PlainArchive::InputEntry entry;
- entry.size = stream.readUint32LE();
- entry.offset = stream.pos();
- entry.name = *file;
- entry.name.toLowercase();
- stream.seek(entry.size, SEEK_CUR);
+ const uint32 fileSize = stream.readUint32LE();
+ const uint32 fileOffset = stream.pos();
- files.push_back(entry);
+ result->addFileEntry(*file, PlainArchive::Entry(fileOffset, fileSize));
+ stream.seek(fileSize, SEEK_CUR);
}
- return new PlainArchive(memberFile, files);
+ return result.release();
}
bool ResLoaderTlk::checkFilename(Common::String filename) const {
@@ -405,27 +387,45 @@
}
Common::Archive *ResLoaderTlk::load(Common::SharedPtr<Common::ArchiveMember> file, Common::SeekableReadStream &stream) const {
- uint16 entries = stream.readUint16LE();
- PlainArchive::FileInputList files;
+ const uint16 entries = stream.readUint16LE();
+ assert(entries > 0);
+ Common::ScopedPtr<PlainArchive> result(new PlainArchive(file));
+ if (!result)
+ return 0;
+
+ uint32 *fileEntries = new uint32[entries * 3];
+ assert(fileEntries);
+
+ // Read the file index
for (uint i = 0; i < entries; ++i) {
- PlainArchive::InputEntry entry;
+ fileEntries[i * 3 + 0] = stream.readUint32LE();
+ fileEntries[i * 3 + 1] = stream.readUint32LE();
+ }
- uint32 resFilename = stream.readUint32LE();
- uint32 resOffset = stream.readUint32LE();
+ // Read in the the file sizes
+ for (uint i = 0; i < entries; ++i) {
+ uint32 * const entry = &fileEntries[i * 3];
- entry.offset = resOffset+4;
- entry.name = Common::String::printf("%.08u.AUD", resFilename);
+ // Seek to the file entry
+ stream.seek(entry[1], SEEK_SET);
- uint32 curOffset = stream.pos();
- stream.seek(resOffset, SEEK_SET);
- entry.size = stream.readUint32LE();
- stream.seek(curOffset, SEEK_SET);
+ // Read the file size
+ entry[2] = stream.readUint32LE();
- files.push_back(entry);
+ // Adjust the file offset
+ entry[1] += 4;
}
- return new PlainArchive(file, files);
+ // Add all the files to the archive
+ for (uint i = 0; i < entries; ++i) {
+ const uint32 * const entry = &fileEntries[i * 3];
+
+ const Common::String name = Common::String::printf("%.08u.AUD", entry[0]);
+ result->addFileEntry(name, PlainArchive::Entry(entry[1], entry[2]));
+ }
+
+ return result.release();
}
// InstallerLoader implementation
Modified: scummvm/trunk/engines/kyra/resource_intern.h
===================================================================
--- scummvm/trunk/engines/kyra/resource_intern.h 2010-08-24 15:11:53 UTC (rev 52345)
+++ scummvm/trunk/engines/kyra/resource_intern.h 2010-08-24 15:47:53 UTC (rev 52346)
@@ -38,27 +38,25 @@
class PlainArchive : public Common::Archive {
public:
- struct InputEntry {
- Common::String name;
+ struct Entry {
+ Entry() : offset(0), size(0) {}
+ Entry(uint32 o, uint32 s) : offset(o), size(s) {}
uint32 offset;
uint32 size;
};
- typedef Common::List<InputEntry> FileInputList;
+ PlainArchive(Common::SharedPtr<Common::ArchiveMember> file);
- PlainArchive(Common::SharedPtr<Common::ArchiveMember> file, const FileInputList &files);
+ void addFileEntry(const Common::String &name, const Entry entry);
+ Entry getFileEntry(const Common::String &name) const;
+ // Common::Archive API implementation
bool hasFile(const Common::String &name);
int listMembers(Common::ArchiveMemberList &list);
Common::ArchiveMemberPtr getMember(const Common::String &name);
Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
private:
- struct Entry {
- uint32 offset;
- uint32 size;
- };
-
typedef Common::HashMap<Common::String, Entry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
Common::SharedPtr<Common::ArchiveMember> _file;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list