[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