diff options
author | Johannes Schickel | 2010-08-24 15:47:53 +0000 |
---|---|---|
committer | Johannes Schickel | 2010-08-24 15:47:53 +0000 |
commit | 501d7cbb84d33fbbbe40431ca66285dfefe5d5b1 (patch) | |
tree | a318654e54ddaa1fae49fcf62df9f23329f79b92 | |
parent | 01a8fc604b00279be181c0ce8decfc8e44242270 (diff) | |
download | scummvm-rg350-501d7cbb84d33fbbbe40431ca66285dfefe5d5b1.tar.gz scummvm-rg350-501d7cbb84d33fbbbe40431ca66285dfefe5d5b1.tar.bz2 scummvm-rg350-501d7cbb84d33fbbbe40431ca66285dfefe5d5b1.zip |
KYRA: Simplify PAK/INS/TLK loading.
This also reduces the number of seeks done while loading TLK files.
svn-id: r52346
-rw-r--r-- | engines/kyra/resource_intern.cpp | 144 | ||||
-rw-r--r-- | engines/kyra/resource_intern.h | 16 |
2 files changed, 79 insertions, 81 deletions
diff --git a/engines/kyra/resource_intern.cpp b/engines/kyra/resource_intern.cpp index b695890e58..b6e6cc1f46 100644 --- a/engines/kyra/resource_intern.cpp +++ b/engines/kyra/resource_intern.cpp @@ -35,16 +35,8 @@ namespace Kyra { // -> 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 @@ Common::SeekableReadStream *PlainArchive::createReadStreamForMember(const Common 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 @@ Common::String readString(Common::SeekableReadStream &stream) { 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 @@ Common::Archive *ResLoaderPak::load(Common::SharedPtr<Common::ArchiveMember> mem 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 @@ Common::Archive *ResLoaderPak::load(Common::SharedPtr<Common::ArchiveMember> mem 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,14 +258,8 @@ Common::Archive *ResLoaderPak::load(Common::SharedPtr<Common::ArchiveMember> mem if (!endoffset) endoffset = filesize; - if (startoffset != endoffset) { - PlainArchive::InputEntry entry; - entry.size = endoffset - startoffset; - entry.offset = startoffset; - entry.name = file; - - files.push_back(entry); - } + if (startoffset != endoffset) + result->addFileEntry(file, PlainArchive::Entry(startoffset, endoffset - startoffset)); if (endoffset == filesize) break; @@ -278,38 +267,32 @@ Common::Archive *ResLoaderPak::load(Common::SharedPtr<Common::ArchiveMember> mem 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 @@ bool ResLoaderInsMalcolm::isLoadable(const Common::String &filename, Common::See 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 @@ Common::Archive *ResLoaderInsMalcolm::load(Common::SharedPtr<Common::ArchiveMemb 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); - - files.push_back(entry); + const uint32 fileSize = stream.readUint32LE(); + const uint32 fileOffset = stream.pos(); + + 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 @@ bool ResLoaderTlk::isLoadable(const Common::String &filename, Common::SeekableRe } 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(); + + // 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]; - files.push_back(entry); + const Common::String name = Common::String::printf("%.08u.AUD", entry[0]); + result->addFileEntry(name, PlainArchive::Entry(entry[1], entry[2])); } - return new PlainArchive(file, files); + return result.release(); } // InstallerLoader implementation diff --git a/engines/kyra/resource_intern.h b/engines/kyra/resource_intern.h index bceccc34b7..f5a3321b53 100644 --- a/engines/kyra/resource_intern.h +++ b/engines/kyra/resource_intern.h @@ -38,27 +38,25 @@ class Resource; 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; |