aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorJohannes Schickel2008-04-17 16:38:26 +0000
committerJohannes Schickel2008-04-17 16:38:26 +0000
commit6cd8eda9bd81283e63e7d2784aa278e2f774de22 (patch)
treee43cef272ad1ad1d81daf268fd66fe20da623fbf /engines
parent7ec2b87fb677a6765631ab1338b30c0d56d1dacf (diff)
downloadscummvm-rg350-6cd8eda9bd81283e63e7d2784aa278e2f774de22.tar.gz
scummvm-rg350-6cd8eda9bd81283e63e7d2784aa278e2f774de22.tar.bz2
scummvm-rg350-6cd8eda9bd81283e63e7d2784aa278e2f774de22.zip
Implemented support for Kyra3 TLK files.
svn-id: r31540
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/kyra_v3.cpp3
-rw-r--r--engines/kyra/resource.cpp104
-rw-r--r--engines/kyra/resource.h1
3 files changed, 106 insertions, 2 deletions
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;