From d00bbceb34ef42b0dfc0370f6d8ed1bb2682d403 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 24 Mar 2011 22:57:35 +0800 Subject: [PATCH] GRIM: Add support for parsing MI4 lab files --- engines/grim/detection.cpp | 2 +- engines/grim/lab.cpp | 64 +++++++++++++++++++++++++++++++------- engines/grim/lab.h | 2 ++ engines/grim/resource.cpp | 5 --- 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/engines/grim/detection.cpp b/engines/grim/detection.cpp index d311f9f1e8e..4a1bdd3a924 100644 --- a/engines/grim/detection.cpp +++ b/engines/grim/detection.cpp @@ -126,7 +126,7 @@ static const GrimGameDescription gameDescriptions[] = { GUIO_NONE }, GF_DEMO, - GType_GRIM + GType_MONKEY4 }, diff --git a/engines/grim/lab.cpp b/engines/grim/lab.cpp index 3b970a4d013..a0b39b6abb4 100644 --- a/engines/grim/lab.cpp +++ b/engines/grim/lab.cpp @@ -26,6 +26,7 @@ #include "common/endian.h" #include "common/file.h" +#include "engines/grim/grim.h" #include "engines/grim/lab.h" #include "engines/grim/lua/lua.h" @@ -40,28 +41,37 @@ bool Lab::open(const Common::String &filename) { if (!_f->open(filename)) return false; - char header[16]; - _f->read(header, sizeof(header)); - if (READ_BE_UINT32(header) != MKID_BE('LABN')) { + if (_f->readUint32BE() != MKID_BE('LABN')) { close(); return false; } - uint32 entryCount = READ_LE_UINT32(header + 8); + _f->readUint32LE(); // version - int string_table_size = READ_LE_UINT32(header + 12); - char *string_table = new char[string_table_size]; + if (g_grim->getGameType() == GType_GRIM) + parseGrimFileTable(); + else + parseMonkey4FileTable(); + + return true; +} + +void Lab::parseGrimFileTable() { + uint32 entryCount = _f->readUint32LE(); + uint32 stringTableSize = _f->readUint32LE(); + + char *stringTable = new char[stringTableSize]; _f->seek(16 * (entryCount + 1)); - _f->read(string_table, string_table_size); + _f->read(stringTable, stringTableSize); _f->seek(16); for (uint32 i = 0; i < entryCount; i++) { - int fname_offset = _f->readUint32LE(); + int fnameOffset = _f->readUint32LE(); int start = _f->readUint32LE(); int size = _f->readUint32LE(); _f->readUint32LE(); - Common::String fname = string_table + fname_offset; + Common::String fname = stringTable + fnameOffset; LabEntry entry; entry.offset = start; @@ -70,8 +80,40 @@ bool Lab::open(const Common::String &filename) { _entries[fname] = entry; } - delete[] string_table; - return true; + delete[] stringTable; +} + +void Lab::parseMonkey4FileTable() { + uint32 entryCount = _f->readUint32LE(); + uint32 stringTableSize = _f->readUint32LE(); + uint32 stringTableOffset = _f->readUint32LE() - 0x13d0f; + + char *stringTable = new char[stringTableSize]; + _f->seek(stringTableOffset); + _f->read(stringTable, stringTableSize); + _f->seek(20); + + // Decrypt the string table + for (uint32 i = 0; i < stringTableSize; i++) + if (stringTable[i] != 0) + stringTable[i] ^= 0x96; + + for (uint32 i = 0; i < entryCount; i++) { + int fnameOffset = _f->readUint32LE(); + int start = _f->readUint32LE(); + int size = _f->readUint32LE(); + _f->readUint32LE(); + + Common::String fname = stringTable + fnameOffset; + + LabEntry entry; + entry.offset = start; + entry.len = size; + + _entries[fname] = entry; + } + + delete[] stringTable; } bool Lab::fileExists(const Common::String &filename) const { diff --git a/engines/grim/lab.h b/engines/grim/lab.h index 6959d1918db..9407a208d04 100644 --- a/engines/grim/lab.h +++ b/engines/grim/lab.h @@ -72,6 +72,8 @@ public: }; private: + void parseGrimFileTable(); + void parseMonkey4FileTable(); Common::File *_f; typedef Common::HashMap LabMap; diff --git a/engines/grim/resource.cpp b/engines/grim/resource.cpp index 8500142b265..7a6b5e2e451 100644 --- a/engines/grim/resource.cpp +++ b/engines/grim/resource.cpp @@ -43,11 +43,6 @@ ResourceLoader::ResourceLoader() { _cacheDirty = false; _cacheMemorySize = 0; - // We don't support MI4's LAB format yet - // It's been slightly modified and the strings have been XOR encrypted - if (g_grim->getGameType() == GType_MONKEY4) - return; - Lab *l; Common::ArchiveMemberList files;