[Scummvm-cvs-logs] SF.net SVN: scummvm:[52347] scummvm/trunk/engines/kyra

lordhoto at users.sourceforge.net lordhoto at users.sourceforge.net
Tue Aug 24 17:48:17 CEST 2010


Revision: 52347
          http://scummvm.svn.sourceforge.net/scummvm/?rev=52347&view=rev
Author:   lordhoto
Date:     2010-08-24 15:48:17 +0000 (Tue, 24 Aug 2010)

Log Message:
-----------
KYRA: Implement new handling of KYRA3's TLK files.

This speeds up loading of KYRA3's TLK files by a lot, since only the index
table will be load now. This should help the startup time for KYRA3 when
playing from CD or other slow storages.

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:47:53 UTC (rev 52346)
+++ scummvm/trunk/engines/kyra/resource_intern.cpp	2010-08-24 15:48:17 UTC (rev 52347)
@@ -84,6 +84,88 @@
 	return fDesc->_value;
 }
 
+// -> TlkArchive implementation
+
+TlkArchive::TlkArchive(Common::SharedPtr<Common::ArchiveMember> file, uint16 entryCount, const uint32 *fileEntries)
+	: _file(file), _entryCount(entryCount), _fileEntries(fileEntries) {
+}
+
+TlkArchive::~TlkArchive() {
+	delete[] _fileEntries;
+}
+
+bool TlkArchive::hasFile(const Common::String &name) {
+	return (findFile(name) != 0);
+}
+
+int TlkArchive::listMembers(Common::ArchiveMemberList &list) {
+	uint count = 0;
+
+	for (; count < _entryCount; ++count) {
+		const Common::String name = Common::String::printf("%08u.AUD", _fileEntries[count * 2 + 0]);
+		list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(name, this)));
+	}
+
+	return count;
+}
+
+Common::ArchiveMemberPtr TlkArchive::getMember(const Common::String &name) {
+	if (!hasFile(name))
+		return Common::ArchiveMemberPtr();
+
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *TlkArchive::createReadStreamForMember(const Common::String &name) const {
+	const uint32 *fileDesc = findFile(name);
+	if (!fileDesc)
+		return 0;
+
+	Common::SeekableReadStream *parent = _file->createReadStream();
+	if (!parent)
+		return 0;
+
+	parent->seek(fileDesc[1], SEEK_SET);
+	const uint32 size = parent->readUint32LE();
+	const uint32 fileStart = fileDesc[1] + 4;
+
+	return new Common::SeekableSubReadStream(parent, fileStart, fileStart + size, DisposeAfterUse::YES);
+}
+
+const uint32 *TlkArchive::findFile(const Common::String &name) const {
+	Common::String uppercaseName = name;
+	uppercaseName.toUppercase();
+
+	if (!uppercaseName.hasSuffix(".AUD"))
+		return 0;
+
+	uint32 id;
+	if (sscanf(uppercaseName.c_str(), "%08u.AUD", &id) != 1)
+		return 0;
+
+	// Binary search for the file entry
+	int leftIndex = 0;
+	int rightIndex = _entryCount - 1;
+
+	while (leftIndex <= rightIndex) {
+		int mid = (leftIndex + rightIndex) / 2;
+
+		const uint32 key = _fileEntries[mid * 2];
+		if (key == id) {
+			// Found
+			return &_fileEntries[mid * 2];
+		} else if (key > id) {
+			// Take the left sub-tree
+			rightIndex = mid - 1;
+		} else {
+			// Take the right sub-tree
+			leftIndex = mid + 1;
+		}
+	}
+
+	return 0;
+}
+
 // -> CachedArchive implementation
 
 CachedArchive::CachedArchive(const FileInputList &files)
@@ -387,45 +469,19 @@
 }
 
 Common::Archive *ResLoaderTlk::load(Common::SharedPtr<Common::ArchiveMember> file, Common::SeekableReadStream &stream) const {
-	const uint16 entries = stream.readUint16LE();
-	assert(entries > 0);
+	const uint16 entryCount = stream.readUint16LE();
 
-	Common::ScopedPtr<PlainArchive> result(new PlainArchive(file));
-	if (!result)
-		return 0;
-
-	uint32 *fileEntries = new uint32[entries * 3];
+	uint32 *fileEntries = new uint32[entryCount * 2];
 	assert(fileEntries);
+	stream.read(fileEntries, sizeof(uint32) * entryCount * 2);
 
-	// Read the file index
-	for (uint i = 0; i < entries; ++i) {
-		fileEntries[i * 3 + 0] = stream.readUint32LE();
-		fileEntries[i * 3 + 1] = stream.readUint32LE();
+	for (uint i = 0; i < entryCount; ++i) {
+		fileEntries[i * 2 + 0] = READ_LE_UINT32(&fileEntries[i * 2 + 0]);
+		fileEntries[i * 2 + 1] = READ_LE_UINT32(&fileEntries[i * 2 + 1]);
 	}
 
-	// Read in the the file sizes
-	for (uint i = 0; i < entries; ++i) {
-		uint32 * const entry = &fileEntries[i * 3];
 
-		// Seek to the file entry
-		stream.seek(entry[1], SEEK_SET);
-
-		// Read the file size
-		entry[2] = stream.readUint32LE();
-
-		// Adjust the file offset
-		entry[1] += 4;
-	}
-
-	// 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();
+	return new TlkArchive(file, entryCount, fileEntries);
 }
 
 // InstallerLoader implementation

Modified: scummvm/trunk/engines/kyra/resource_intern.h
===================================================================
--- scummvm/trunk/engines/kyra/resource_intern.h	2010-08-24 15:47:53 UTC (rev 52346)
+++ scummvm/trunk/engines/kyra/resource_intern.h	2010-08-24 15:48:17 UTC (rev 52347)
@@ -63,6 +63,24 @@
 	FileMap _files;
 };
 
+class TlkArchive : public Common::Archive {
+public:
+	TlkArchive(Common::SharedPtr<Common::ArchiveMember> file, uint16 entryCount, const uint32 *fileEntries);
+	~TlkArchive();
+
+	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:
+	Common::SharedPtr<Common::ArchiveMember> _file;
+
+	const uint32 *findFile(const Common::String &name) const;
+
+	const uint16 _entryCount;
+	const uint32 * const _fileEntries;
+};
+
 class CachedArchive : public Common::Archive {
 public:
 	struct InputEntry {


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