From 6cd8eda9bd81283e63e7d2784aa278e2f774de22 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 17 Apr 2008 16:38:26 +0000 Subject: Implemented support for Kyra3 TLK files. svn-id: r31540 --- engines/kyra/kyra_v3.cpp | 3 +- engines/kyra/resource.cpp | 104 ++++++++++++++++++++++++++++++++++++++++++++++ engines/kyra/resource.h | 1 + 3 files changed, 106 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index 6a4c2ee2d0..4567e5777b 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -619,8 +619,7 @@ void KyraEngine_v3::openTalkFile(int file) { } _currentTalkFile = file; - //TODO: support Kyra3 TLK files - //_res->loadPakFile(talkFilename); + _res->loadPakFile(talkFilename); } #pragma mark - diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 142f50e789..10fdd60b5e 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -630,9 +630,113 @@ Common::SeekableReadStream *ResLoaderIns::loadFileFromArchive(const Common::Stri return stream; } +class ResLoaderTlk : public ResArchiveLoader { +public: + bool checkFilename(Common::String filename) const; + bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const; + bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const; + Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const; + + ResFileEntry::kType getType() const { + return ResFileEntry::kTlk; + } + +private: + static bool sortTlkFileList(const File &l, const File &r); + static FileList::const_iterator nextFile(const FileList &list, FileList::const_iterator iter); +}; + +bool ResLoaderTlk::checkFilename(Common::String filename) const { + filename.toUppercase(); + return (filename.hasSuffix(".TLK")); +} + +bool ResLoaderTlk::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { + uint16 entries = stream.readUint16LE(); + uint32 entryTableSize = (entries * 8); + + if (entryTableSize + 2 > stream.size()) + return false; + + uint32 offset = 0; + + for (uint i = 0; i < entries; ++i) { + stream.readUint32LE(); + offset = stream.readUint32LE(); + + if (offset > stream.size()) + return false; + } + + return true; +} + +bool ResLoaderTlk::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const { + uint16 entries = stream.readUint16LE(); + + for (uint i = 0; i < entries; ++i) { + ResFileEntry entry; + entry.parent = filename; + entry.type = ResFileEntry::kAutoDetect; + entry.mounted = false; + entry.preload = false; + entry.prot = false; + + uint32 filename = stream.readUint32LE(); + uint32 offset = stream.readUint32LE(); + + entry.offset = offset; + entry.size = 0; + + char realFilename[20]; + snprintf(realFilename, 20, "%.08u.AUD", filename); + + files.push_back(FileList::value_type(realFilename, entry)); + } + + Common::sort(files.begin(), files.end(), ResLoaderTlk::sortTlkFileList); + + for (FileList::iterator iter = files.begin(); iter != files.end(); ++iter) { + FileList::const_iterator next = ResLoaderTlk::nextFile(files, iter); + uint32 endOffset = (next == files.end() ? stream.size() : next->entry.offset); + + assert(endOffset >= iter->entry.offset); + + iter->entry.size = endOffset - iter->entry.offset; + } + + return true; +} + +Common::SeekableReadStream *ResLoaderTlk::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const { + assert(archive); + + archive->seek(entry.offset, SEEK_SET); + Common::SeekableSubReadStream *stream = new Common::SeekableSubReadStream(archive, entry.offset, entry.offset + entry.size, true); + assert(stream); + return stream; +} + +bool ResLoaderTlk::sortTlkFileList(const File &l, const File &r) { + return (l.entry.offset < r.entry.offset); +} + +ResLoaderTlk::FileList::const_iterator ResLoaderTlk::nextFile(const FileList &list, FileList::const_iterator iter) { + ResArchiveLoader::FileList::const_iterator next = iter; + while ((++next) != list.end()) { + if (next->entry.offset != iter->entry.offset) + return next; + } + + return next; +} + +#pragma mark - + void Resource::initializeLoaders() { _loaders.push_back(LoaderList::value_type(new ResLoaderPak())); _loaders.push_back(LoaderList::value_type(new ResLoaderIns())); + _loaders.push_back(LoaderList::value_type(new ResLoaderTlk())); } const ResArchiveLoader *Resource::getLoader(ResFileEntry::kType type) const { diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 3d50b0c8a1..e8f5484a74 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -53,6 +53,7 @@ struct ResFileEntry { kRaw = 0, kPak = 1, kIns = 2, + kTlk = 3, kAutoDetect }; kType type; -- cgit v1.2.3