diff options
author | Johannes Schickel | 2010-08-24 15:48:17 +0000 |
---|---|---|
committer | Johannes Schickel | 2010-08-24 15:48:17 +0000 |
commit | 51939fe743fa0682a2a037352565dfb8d2aea4dd (patch) | |
tree | f15690ad06b9b7bc57c9880697ab57ff3a052086 | |
parent | 501d7cbb84d33fbbbe40431ca66285dfefe5d5b1 (diff) | |
download | scummvm-rg350-51939fe743fa0682a2a037352565dfb8d2aea4dd.tar.gz scummvm-rg350-51939fe743fa0682a2a037352565dfb8d2aea4dd.tar.bz2 scummvm-rg350-51939fe743fa0682a2a037352565dfb8d2aea4dd.zip |
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.
svn-id: r52347
-rw-r--r-- | engines/kyra/resource_intern.cpp | 122 | ||||
-rw-r--r-- | engines/kyra/resource_intern.h | 18 |
2 files changed, 107 insertions, 33 deletions
diff --git a/engines/kyra/resource_intern.cpp b/engines/kyra/resource_intern.cpp index b6e6cc1f46..85d47f1fd4 100644 --- a/engines/kyra/resource_intern.cpp +++ b/engines/kyra/resource_intern.cpp @@ -84,6 +84,88 @@ PlainArchive::Entry PlainArchive::getFileEntry(const Common::String &name) const 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 @@ bool ResLoaderTlk::isLoadable(const Common::String &filename, Common::SeekableRe } 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 diff --git a/engines/kyra/resource_intern.h b/engines/kyra/resource_intern.h index f5a3321b53..ad4ee0eb1d 100644 --- a/engines/kyra/resource_intern.h +++ b/engines/kyra/resource_intern.h @@ -63,6 +63,24 @@ private: 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 { |