aboutsummaryrefslogtreecommitdiff
path: root/engines/mohawk/resource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/mohawk/resource.cpp')
-rw-r--r--engines/mohawk/resource.cpp602
1 files changed, 273 insertions, 329 deletions
diff --git a/engines/mohawk/resource.cpp b/engines/mohawk/resource.cpp
index 3a95b83199..9b39692958 100644
--- a/engines/mohawk/resource.cpp
+++ b/engines/mohawk/resource.cpp
@@ -29,23 +29,25 @@
namespace Mohawk {
-MohawkArchive::MohawkArchive() {
- _mhk = NULL;
- _types = NULL;
- _fileTable = NULL;
+// Base Archive code
+
+Archive::Archive() {
+ _stream = 0;
+}
+
+Archive::~Archive() {
+ close();
}
-bool MohawkArchive::open(const Common::String &filename) {
+bool Archive::openFile(const Common::String &fileName) {
Common::File *file = new Common::File();
- if (!file->open(filename)) {
+ if (!file->open(fileName)) {
delete file;
return false;
}
- _curFile = filename;
-
- if (!open(file)) {
+ if (!openStream(file)) {
close();
return false;
}
@@ -53,431 +55,371 @@ bool MohawkArchive::open(const Common::String &filename) {
return true;
}
-void MohawkArchive::close() {
- delete _mhk; _mhk = NULL;
- delete[] _types; _types = NULL;
- delete[] _fileTable; _fileTable = NULL;
-
- _curFile.clear();
+void Archive::close() {
+ _types.clear();
+ delete _stream; _stream = 0;
}
-bool MohawkArchive::open(Common::SeekableReadStream *stream) {
- // Make sure no other file is open...
- close();
- _mhk = stream;
-
- if (_mhk->readUint32BE() != ID_MHWK) {
- warning("Could not find tag 'MHWK'");
+bool Archive::hasResource(uint32 tag, uint16 id) const {
+ if (!_types.contains(tag))
return false;
- }
-
- /* uint32 fileSize = */ _mhk->readUint32BE();
- if (_mhk->readUint32BE() != ID_RSRC) {
- warning("Could not find tag \'RSRC\'");
- return false;
- }
+ return _types[tag].contains(id);
+}
- _rsrc.version = _mhk->readUint16BE();
-
- if (_rsrc.version != 0x100) {
- warning("Unsupported Mohawk resource version %d.%d", (_rsrc.version >> 8) & 0xff, _rsrc.version & 0xff);
+bool Archive::hasResource(uint32 tag, const Common::String &resName) const {
+ if (!_types.contains(tag) || resName.empty())
return false;
- }
-
- _rsrc.compaction = _mhk->readUint16BE(); // Only used in creation, not in reading
- _rsrc.filesize = _mhk->readUint32BE();
- _rsrc.abs_offset = _mhk->readUint32BE();
- _rsrc.file_table_offset = _mhk->readUint16BE();
- _rsrc.file_table_size = _mhk->readUint16BE();
- debug (3, "Absolute Offset = %08x", _rsrc.abs_offset);
+ const ResourceMap &resMap = _types[tag];
- /////////////////////////////////
- //Resource Dir
- /////////////////////////////////
+ for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++)
+ if (it->_value.name.matchString(resName))
+ return true;
- // Type Table
- _mhk->seek(_rsrc.abs_offset);
- _typeTable.name_offset = _mhk->readUint16BE();
- _typeTable.resource_types = _mhk->readUint16BE();
+ return false;
+}
- debug (0, "Name List Offset = %04x Number of Resource Types = %04x", _typeTable.name_offset, _typeTable.resource_types);
+Common::SeekableReadStream *Archive::getResource(uint32 tag, uint16 id) {
+ if (!_types.contains(tag))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
- _types = new Type[_typeTable.resource_types];
+ const ResourceMap &resMap = _types[tag];
- for (uint16 i = 0; i < _typeTable.resource_types; i++) {
- _types[i].tag = _mhk->readUint32BE();
- _types[i].resource_table_offset = _mhk->readUint16BE();
- _types[i].name_table_offset = _mhk->readUint16BE();
+ if (!resMap.contains(id))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
- // HACK: Zoombini's SND resource starts will a NULL.
- if (_types[i].tag == ID_SND)
- debug (3, "Type[%02d]: Tag = \'SND\' ResTable Offset = %04x NameTable Offset = %04x", i, _types[i].resource_table_offset, _types[i].name_table_offset);
- else
- debug (3, "Type[%02d]: Tag = \'%s\' ResTable Offset = %04x NameTable Offset = %04x", i, tag2str(_types[i].tag), _types[i].resource_table_offset, _types[i].name_table_offset);
-
- // Resource Table
- _mhk->seek(_rsrc.abs_offset + _types[i].resource_table_offset);
- _types[i].resTable.resources = _mhk->readUint16BE();
+ const Resource &res = resMap[id];
- debug (3, "Resources = %04x", _types[i].resTable.resources);
+ return new Common::SeekableSubReadStream(_stream, res.offset, res.offset + res.size);
+}
- _types[i].resTable.entries = new Type::ResourceTable::Entries[_types[i].resTable.resources];
+uint32 Archive::getOffset(uint32 tag, uint16 id) const {
+ if (!_types.contains(tag))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
- for (uint16 j = 0; j < _types[i].resTable.resources; j++) {
- _types[i].resTable.entries[j].id = _mhk->readUint16BE();
- _types[i].resTable.entries[j].index = _mhk->readUint16BE();
+ const ResourceMap &resMap = _types[tag];
- debug (4, "Entry[%02x]: ID = %04x (%d) Index = %04x", j, _types[i].resTable.entries[j].id, _types[i].resTable.entries[j].id, _types[i].resTable.entries[j].index);
- }
+ if (!resMap.contains(id))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
- // Name Table
- _mhk->seek(_rsrc.abs_offset + _types[i].name_table_offset);
- _types[i].nameTable.num = _mhk->readUint16BE();
+ return resMap[id].offset;
+}
- debug (3, "Names = %04x", _types[i].nameTable.num);
+uint16 Archive::findResourceID(uint32 tag, const Common::String &resName) const {
+ if (!_types.contains(tag) || resName.empty())
+ return 0xFFFF;
- _types[i].nameTable.entries = new Type::NameTable::Entries[_types[i].nameTable.num];
+ const ResourceMap &resMap = _types[tag];
- for (uint16 j = 0; j < _types[i].nameTable.num; j++) {
- _types[i].nameTable.entries[j].offset = _mhk->readUint16BE();
- _types[i].nameTable.entries[j].index = _mhk->readUint16BE();
+ for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++)
+ if (it->_value.name.matchString(resName))
+ return it->_key;
- debug (4, "Entry[%02x]: Name List Offset = %04x Index = %04x", j, _types[i].nameTable.entries[j].offset, _types[i].nameTable.entries[j].index);
+ return 0xFFFF;
+}
- // Name List
- uint32 pos = _mhk->pos();
- _mhk->seek(_rsrc.abs_offset + _typeTable.name_offset + _types[i].nameTable.entries[j].offset);
- char c = (char)_mhk->readByte();
- while (c != 0) {
- _types[i].nameTable.entries[j].name += c;
- c = (char)_mhk->readByte();
- }
+Common::String Archive::getName(uint32 tag, uint16 id) const {
+ if (!_types.contains(tag))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
- debug (3, "Name = \'%s\'", _types[i].nameTable.entries[j].name.c_str());
+ const ResourceMap &resMap = _types[tag];
- // Get back to next entry
- _mhk->seek(pos);
- }
+ if (!resMap.contains(id))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
- // Return to next TypeTable entry
- _mhk->seek(_rsrc.abs_offset + (i + 1) * 8 + 4);
+ return resMap[id].name;
+}
- debug (3, "\n");
- }
+Common::Array<uint32> Archive::getResourceTypeList() const {
+ Common::Array<uint32> typeList;
- _mhk->seek(_rsrc.abs_offset + _rsrc.file_table_offset);
- _fileTableAmount = _mhk->readUint32BE();
- _fileTable = new FileTable[_fileTableAmount];
+ for (TypeMap::const_iterator it = _types.begin(); it != _types.end(); it++)
+ typeList.push_back(it->_key);
- for (uint32 i = 0; i < _fileTableAmount; i++) {
- _fileTable[i].offset = _mhk->readUint32BE();
- _fileTable[i].dataSize = _mhk->readUint16BE();
- _fileTable[i].dataSize += _mhk->readByte() << 16; // Get bits 15-24 of dataSize too
- _fileTable[i].flags = _mhk->readByte();
- _fileTable[i].unk = _mhk->readUint16BE();
+ return typeList;
+}
- // Add in another 3 bits for file size from the flags.
- // The flags are useless to us except for doing this ;)
- _fileTable[i].dataSize += (_fileTable[i].flags & 7) << 24;
+Common::Array<uint16> Archive::getResourceIDList(uint32 type) const {
+ Common::Array<uint16> idList;
- debug (4, "File[%02x]: Offset = %08x DataSize = %07x Flags = %02x Unk = %04x", i, _fileTable[i].offset, _fileTable[i].dataSize, _fileTable[i].flags, _fileTable[i].unk);
- }
+ if (!_types.contains(type))
+ return idList;
- return true;
-}
+ const ResourceMap &resMap = _types[type];
-int MohawkArchive::getTypeIndex(uint32 tag) {
- for (uint16 i = 0; i < _typeTable.resource_types; i++)
- if (_types[i].tag == tag)
- return i;
- return -1; // not found
-}
+ for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++)
+ idList.push_back(it->_key);
-int MohawkArchive::getIDIndex(int typeIndex, uint16 id) {
- for (uint16 i = 0; i < _types[typeIndex].resTable.resources; i++)
- if (_types[typeIndex].resTable.entries[i].id == id)
- return i;
- return -1; // not found
+ return idList;
}
-int MohawkArchive::getIDIndex(int typeIndex, const Common::String &resName) {
- int index = -1;
+// Mohawk Archive code
- for (uint16 i = 0; i < _types[typeIndex].nameTable.num; i++)
- if (_types[typeIndex].nameTable.entries[i].name.matchString(resName)) {
- index = _types[typeIndex].nameTable.entries[i].index;
- break;
- }
+struct FileTableEntry {
+ uint32 offset;
+ uint32 size;
+ byte flags;
+ uint16 unknown;
+};
- if (index < 0)
- return -1; // Not found
+struct NameTableEntry {
+ uint16 index;
+ Common::String name;
+};
- for (uint16 i = 0; i < _types[typeIndex].resTable.resources; i++)
- if (_types[typeIndex].resTable.entries[i].index == index)
- return i;
-
- return -1; // Not found
-}
-
-uint16 MohawkArchive::findResourceID(uint32 type, const Common::String &resName) {
- int typeIndex = getTypeIndex(type);
+bool MohawkArchive::openStream(Common::SeekableReadStream *stream) {
+ // Make sure no other file is open...
+ close();
- if (typeIndex < 0)
- return 0xFFFF;
+ if (stream->readUint32BE() != ID_MHWK) {
+ warning("Could not find tag 'MHWK'");
+ return false;
+ }
- int idIndex = getIDIndex(typeIndex, resName);
+ /* uint32 fileSize = */ stream->readUint32BE();
- if (idIndex < 0)
- return 0xFFFF;
+ if (stream->readUint32BE() != ID_RSRC) {
+ warning("Could not find tag \'RSRC\'");
+ return false;
+ }
- return _types[typeIndex].resTable.entries[idIndex].id;
-}
+ uint16 version = stream->readUint16BE();
-bool MohawkArchive::hasResource(uint32 tag, uint16 id) {
- if (!_mhk)
+ if (version != 0x100) {
+ warning("Unsupported Mohawk resource version %d.%d", (version >> 8) & 0xff, version & 0xff);
return false;
+ }
- int16 typeIndex = getTypeIndex(tag);
+ /* uint16 compaction = */ stream->readUint16BE(); // Only used in creation, not in reading
+ /* uint32 rsrcSize = */ stream->readUint32BE();
+ uint32 absOffset = stream->readUint32BE();
+ uint16 fileTableOffset = stream->readUint16BE();
+ /* uint16 fileTableSize = */ stream->readUint16BE();
- if (typeIndex < 0)
- return false;
+ // First, read in the file table
+ stream->seek(absOffset + fileTableOffset);
+ Common::Array<FileTableEntry> fileTable;
+ fileTable.resize(stream->readUint32BE());
- return getIDIndex(typeIndex, id) >= 0;
-}
+ debug(4, "Reading file table with %d entries", fileTable.size());
-bool MohawkArchive::hasResource(uint32 tag, const Common::String &resName) {
- if (!_mhk)
- return false;
+ for (uint32 i = 0; i < fileTable.size(); i++) {
+ fileTable[i].offset = stream->readUint32BE();
+ fileTable[i].size = stream->readUint16BE();
+ fileTable[i].size += stream->readByte() << 16; // Get bits 15-24 of size too
+ fileTable[i].flags = stream->readByte();
+ fileTable[i].unknown = stream->readUint16BE();
- int16 typeIndex = getTypeIndex(tag);
+ // Add in another 3 bits for file size from the flags.
+ // The flags are useless to us except for doing this ;)
+ fileTable[i].size += (fileTable[i].flags & 7) << 24;
- if (typeIndex < 0)
- return false;
+ debug(4, "File[%02x]: Offset = %08x Size = %07x Flags = %02x Unknown = %04x", i, fileTable[i].offset, fileTable[i].size, fileTable[i].flags, fileTable[i].unknown);
+ }
- return getIDIndex(typeIndex, resName) >= 0;
-}
+ // Now go in an read in each of the types
+ stream->seek(absOffset);
+ uint16 stringTableOffset = stream->readUint16BE();
+ uint16 typeCount = stream->readUint16BE();
-Common::String MohawkArchive::getName(uint32 tag, uint16 id) {
- if (!_mhk)
- return 0;
+ debug(0, "Name List Offset = %04x Number of Resource Types = %04x", stringTableOffset, typeCount);
- int16 typeIndex = getTypeIndex(tag);
+ for (uint16 i = 0; i < typeCount; i++) {
+ uint32 tag = stream->readUint32BE();
+ uint16 resourceTableOffset = stream->readUint16BE();
+ uint16 nameTableOffset = stream->readUint16BE();
- if (typeIndex < 0)
- return 0;
+ // HACK: Zoombini's SND resource starts will a NULL.
+ if (tag == ID_SND)
+ debug(3, "Type[%02d]: Tag = \'SND\' ResTable Offset = %04x NameTable Offset = %04x", i, resourceTableOffset, nameTableOffset);
+ else
+ debug(3, "Type[%02d]: Tag = \'%s\' ResTable Offset = %04x NameTable Offset = %04x", i, tag2str(tag), resourceTableOffset, nameTableOffset);
- int16 idIndex = -1;
+ // Name Table
+ stream->seek(absOffset + nameTableOffset);
+ Common::Array<NameTableEntry> nameTable;
+ nameTable.resize(stream->readUint16BE());
- for (uint16 i = 0; i < _types[typeIndex].resTable.resources; i++)
- if (_types[typeIndex].resTable.entries[i].id == id) {
- idIndex = _types[typeIndex].resTable.entries[i].index;
- break;
- }
+ debug(3, "Names = %04x", nameTable.size());
- assert(idIndex >= 0);
+ for (uint16 j = 0; j < nameTable.size(); j++) {
+ uint16 offset = stream->readUint16BE();
+ nameTable[j].index = stream->readUint16BE();
- for (uint16 i = 0; i < _types[typeIndex].nameTable.num; i++)
- if (_types[typeIndex].nameTable.entries[i].index == idIndex)
- return _types[typeIndex].nameTable.entries[i].name;
+ debug(4, "Entry[%02x]: Name List Offset = %04x Index = %04x", j, offset, nameTable[j].index);
- return 0; // not found
-}
+ // Name List
+ uint32 pos = stream->pos();
+ stream->seek(absOffset + stringTableOffset + offset);
+ char c = (char)stream->readByte();
+ while (c != 0) {
+ nameTable[j].name += c;
+ c = (char)stream->readByte();
+ }
-uint32 MohawkArchive::getOffset(uint32 tag, uint16 id) {
- assert(_mhk);
+ debug(3, "Name = \'%s\'", nameTable[j].name.c_str());
- int16 typeIndex = getTypeIndex(tag);
- assert(typeIndex >= 0);
+ // Get back to next entry
+ stream->seek(pos);
+ }
- int16 idIndex = getIDIndex(typeIndex, id);
- assert(idIndex >= 0);
+ // Resource Table
+ stream->seek(absOffset + resourceTableOffset);
+ uint16 resourceCount = stream->readUint16BE();
- return _fileTable[_types[typeIndex].resTable.entries[idIndex].index - 1].offset;
-}
+ debug(3, "Resource count = %04x", resourceCount);
+
+ ResourceMap &resMap = _types[tag];
-Common::SeekableReadStream *MohawkArchive::getResource(uint32 tag, uint16 id) {
- if (!_mhk)
- error("MohawkArchive::getResource(): No File in Use");
+ for (uint16 j = 0; j < resourceCount; j++) {
+ uint16 id = stream->readUint16BE();
+ uint16 index = stream->readUint16BE();
- int16 typeIndex = getTypeIndex(tag);
+ Resource &res = resMap[id];
- if (typeIndex < 0)
- error("Could not find a tag of '%s' in file '%s'", tag2str(tag), _curFile.c_str());
+ // Pull out the name from the name table
+ for (uint32 k = 0; k < nameTable.size(); k++) {
+ if (nameTable[k].index == index) {
+ res.name = nameTable[k].name;
+ break;
+ }
+ }
- int16 idIndex = getIDIndex(typeIndex, id);
+ // Pull out our offset/size too
+ res.offset = fileTable[index - 1].offset;
+
+ // WORKAROUND: tMOV resources pretty much ignore the size part of the file table,
+ // as the original just passed the full Mohawk file to QuickTime and the offset.
+ // We need to do this because of the way Mohawk is set up (this is much more "proper"
+ // than passing _stream at the right offset). We may want to do that in the future, though.
+ if (tag == ID_TMOV) {
+ if (index == fileTable.size() - 1)
+ res.size = stream->size() - fileTable[index - 1].offset;
+ else
+ res.size = fileTable[index].offset - fileTable[index - 1].offset;
+ } else
+ res.size = fileTable[index - 1].size;
+
+ debug(4, "Entry[%02x]: ID = %04x (%d) Index = %04x", j, id, id, index);
+ }
- if (idIndex < 0)
- error("Could not find '%s' %04x in file '%s'", tag2str(tag), id, _curFile.c_str());
- // Note: the fileTableIndex is based off 1, not 0. So, subtract 1
- uint16 fileTableIndex = _types[typeIndex].resTable.entries[idIndex].index - 1;
+ // Return to next TypeTable entry
+ stream->seek(absOffset + (i + 1) * 8 + 4);
- // WORKAROUND: tMOV resources pretty much ignore the size part of the file table,
- // as the original just passed the full Mohawk file to QuickTime and the offset.
- // We need to do this because of the way Mohawk is set up (this is much more "proper"
- // than passing _mhk at the right offset). We may want to do that in the future, though.
- if (_types[typeIndex].tag == ID_TMOV) {
- if (fileTableIndex == _fileTableAmount - 1)
- return new Common::SeekableSubReadStream(_mhk, _fileTable[fileTableIndex].offset, _mhk->size());
- else
- return new Common::SeekableSubReadStream(_mhk, _fileTable[fileTableIndex].offset, _fileTable[fileTableIndex + 1].offset);
+ debug(3, "\n");
}
- return new Common::SeekableSubReadStream(_mhk, _fileTable[fileTableIndex].offset, _fileTable[fileTableIndex].offset + _fileTable[fileTableIndex].dataSize);
+ _stream = stream;
+ return true;
}
-bool LivingBooksArchive_v1::open(Common::SeekableReadStream *stream) {
+// Living Books Archive code
+
+bool LivingBooksArchive_v1::openStream(Common::SeekableReadStream *stream) {
close();
- _mhk = stream;
// This is for the "old" Mohawk resource format used in some older
// Living Books. It is very similar, just missing the MHWK tag and
// some other minor differences, especially with the file table
// being merged into the resource table.
- uint32 headerSize = _mhk->readUint32BE();
+ uint32 headerSize = stream->readUint32BE();
// NOTE: There are differences besides endianness! (Subtle changes,
// but different).
if (headerSize == 6) { // We're in Big Endian mode (Macintosh)
- _mhk->readUint16BE(); // Resource Table Size
- _typeTable.resource_types = _mhk->readUint16BE();
- _types = new OldType[_typeTable.resource_types];
+ stream->readUint16BE(); // Resource Table Size
+ uint16 typeCount = stream->readUint16BE();
- debug (0, "Old Mohawk File (Macintosh): Number of Resource Types = %04x", _typeTable.resource_types);
+ debug(0, "Old Mohawk File (Macintosh): Number of Resource Types = %04x", typeCount);
- for (uint16 i = 0; i < _typeTable.resource_types; i++) {
- _types[i].tag = _mhk->readUint32BE();
- _types[i].resource_table_offset = (uint16)_mhk->readUint32BE() + 6;
- _mhk->readUint32BE(); // Unknown (always 0?)
+ for (uint16 i = 0; i < typeCount; i++) {
+ uint32 tag = stream->readUint32BE();
+ uint32 resourceTableOffset = stream->readUint32BE() + 6;
+ stream->readUint32BE(); // Unknown (always 0?)
- debug (3, "Type[%02d]: Tag = \'%s\' ResTable Offset = %04x", i, tag2str(_types[i].tag), _types[i].resource_table_offset);
+ debug(3, "Type[%02d]: Tag = \'%s\' ResTable Offset = %04x", i, tag2str(tag), resourceTableOffset);
- uint32 oldPos = _mhk->pos();
+ uint32 oldPos = stream->pos();
// Resource Table/File Table
- _mhk->seek(_types[i].resource_table_offset);
- _types[i].resTable.resources = _mhk->readUint16BE();
- _types[i].resTable.entries = new OldType::ResourceTable::Entries[_types[i].resTable.resources];
-
- for (uint16 j = 0; j < _types[i].resTable.resources; j++) {
- _types[i].resTable.entries[j].id = _mhk->readUint16BE();
- _types[i].resTable.entries[j].offset = _mhk->readUint32BE();
- _types[i].resTable.entries[j].size = _mhk->readByte() << 16;
- _types[i].resTable.entries[j].size += _mhk->readUint16BE();
- _mhk->skip(5); // Unknown (always 0?)
-
- debug (4, "Entry[%02x]: ID = %04x (%d)\tOffset = %08x, Size = %08x", j, _types[i].resTable.entries[j].id, _types[i].resTable.entries[j].id, _types[i].resTable.entries[j].offset, _types[i].resTable.entries[j].size);
- }
+ stream->seek(resourceTableOffset);
+ uint16 resourceCount = stream->readUint16BE();
- _mhk->seek(oldPos);
- debug (3, "\n");
- }
- } else if (SWAP_BYTES_32(headerSize) == 6) { // We're in Little Endian mode (Windows)
- _mhk->readUint16LE(); // Resource Table Size
- _typeTable.resource_types = _mhk->readUint16LE();
- _types = new OldType[_typeTable.resource_types];
-
- debug (0, "Old Mohawk File (Windows): Number of Resource Types = %04x", _typeTable.resource_types);
-
- for (uint16 i = 0; i < _typeTable.resource_types; i++) {
- _types[i].tag = _mhk->readUint32LE();
- _types[i].resource_table_offset = _mhk->readUint16LE() + 6;
- _mhk->readUint16LE(); // Unknown (always 0?)
+ ResourceMap &resMap = _types[tag];
- debug (3, "Type[%02d]: Tag = \'%s\' ResTable Offset = %04x", i, tag2str(_types[i].tag), _types[i].resource_table_offset);
+ for (uint16 j = 0; j < resourceCount; j++) {
+ uint16 id = stream->readUint16BE();
- uint32 oldPos = _mhk->pos();
+ Resource &res = resMap[id];
- // Resource Table/File Table
- _mhk->seek(_types[i].resource_table_offset);
- _types[i].resTable.resources = _mhk->readUint16LE();
- _types[i].resTable.entries = new OldType::ResourceTable::Entries[_types[i].resTable.resources];
-
- for (uint16 j = 0; j < _types[i].resTable.resources; j++) {
- _types[i].resTable.entries[j].id = _mhk->readUint16LE();
- _types[i].resTable.entries[j].offset = _mhk->readUint32LE();
- _types[i].resTable.entries[j].size = _mhk->readUint32LE();
- _mhk->readUint16LE(); // Unknown (always 0?)
+ res.offset = stream->readUint32BE();
+ res.size = stream->readByte() << 16;
+ res.size |= stream->readUint16BE();
+ stream->skip(5); // Unknown (always 0?)
- debug (4, "Entry[%02x]: ID = %04x (%d)\tOffset = %08x, Size = %08x", j, _types[i].resTable.entries[j].id, _types[i].resTable.entries[j].id, _types[i].resTable.entries[j].offset, _types[i].resTable.entries[j].size);
+ debug(4, "Entry[%02x]: ID = %04x (%d)\tOffset = %08x, Size = %08x", j, id, id, res.offset, res.size);
}
- _mhk->seek(oldPos);
- debug (3, "\n");
+ stream->seek(oldPos);
+ debug(3, "\n");
}
- } else {
- warning("Could not determine type of Old Mohawk resource");
- return false;
- }
-
- return true;
-}
-
-uint32 LivingBooksArchive_v1::getOffset(uint32 tag, uint16 id) {
- assert(_mhk);
+ } else if (SWAP_BYTES_32(headerSize) == 6) { // We're in Little Endian mode (Windows)
+ stream->readUint16LE(); // Resource Table Size
+ uint16 typeCount = stream->readUint16LE();
- int16 typeIndex = getTypeIndex(tag);
- assert(typeIndex >= 0);
+ debug(0, "Old Mohawk File (Windows): Number of Resource Types = %04x", typeCount);
- int16 idIndex = getIDIndex(typeIndex, id);
- assert(idIndex >= 0);
+ for (uint16 i = 0; i < typeCount; i++) {
+ uint32 tag = stream->readUint32LE();
+ uint16 resourceTableOffset = stream->readUint16LE() + 6;
+ stream->readUint16LE(); // Unknown (always 0?)
- return _types[typeIndex].resTable.entries[idIndex].offset;
-}
+ debug(3, "Type[%02d]: Tag = \'%s\' ResTable Offset = %04x", i, tag2str(tag), resourceTableOffset);
-Common::SeekableReadStream *LivingBooksArchive_v1::getResource(uint32 tag, uint16 id) {
- if (!_mhk)
- error("LivingBooksArchive_v1::getResource(): No File in Use");
+ uint32 oldPos = stream->pos();
- int16 typeIndex = getTypeIndex(tag);
-
- if (typeIndex < 0)
- error("Could not find a tag of \'%s\' in file \'%s\'", tag2str(tag), _curFile.c_str());
+ // Resource Table/File Table
+ stream->seek(resourceTableOffset);
+ uint16 resourceCount = stream->readUint16LE();
- int16 idIndex = getIDIndex(typeIndex, id);
+ ResourceMap &resMap = _types[tag];
- if (idIndex < 0)
- error("Could not find \'%s\' %04x in file \'%s\'", tag2str(tag), id, _curFile.c_str());
+ for (uint16 j = 0; j < resourceCount; j++) {
+ uint16 id = stream->readUint16LE();
- return new Common::SeekableSubReadStream(_mhk, _types[typeIndex].resTable.entries[idIndex].offset, _types[typeIndex].resTable.entries[idIndex].offset + _types[typeIndex].resTable.entries[idIndex].size);
-}
+ Resource &res = resMap[id];
-bool LivingBooksArchive_v1::hasResource(uint32 tag, uint16 id) {
- if (!_mhk)
- return false;
+ res.offset = stream->readUint32LE();
+ res.size = stream->readUint32LE();
+ stream->readUint16LE(); // Unknown (always 0?)
- int16 typeIndex = getTypeIndex(tag);
+ debug(4, "Entry[%02x]: ID = %04x (%d)\tOffset = %08x, Size = %08x", j, id, id, res.offset, res.size);
+ }
- if (typeIndex < 0)
+ stream->seek(oldPos);
+ debug(3, "\n");
+ }
+ } else {
+ // Not a valid Living Books Archive
return false;
+ }
- return getIDIndex(typeIndex, id) >= 0;
+ _stream = stream;
+ return true;
}
-int LivingBooksArchive_v1::getTypeIndex(uint32 tag) {
- for (uint16 i = 0; i < _typeTable.resource_types; i++)
- if (_types[i].tag == tag)
- return i;
- return -1; // not found
-}
-
-int LivingBooksArchive_v1::getIDIndex(int typeIndex, uint16 id) {
- for (uint16 i = 0; i < _types[typeIndex].resTable.resources; i++)
- if (_types[typeIndex].resTable.entries[i].id == id)
- return i;
- return -1; // not found
-}
+// DOS Archive (v2) code
// Partially based on the Prince of Persia Format Specifications
// See http://sdfg.com.ar/git/?p=fp-git.git;a=blob;f=FP/doc/FormatSpecifications
// However, I'm keeping with the terminology we've been using with the
// later archive formats.
-bool DOSArchive_v2::open(Common::SeekableReadStream *stream) {
+bool DOSArchive_v2::openStream(Common::SeekableReadStream *stream) {
close();
uint32 typeTableOffset = stream->readUint32LE();
@@ -488,36 +430,38 @@ bool DOSArchive_v2::open(Common::SeekableReadStream *stream) {
stream->seek(typeTableOffset);
- _typeTable.resource_types = stream->readUint16LE();
- _types = new OldType[_typeTable.resource_types];
+ uint16 typeCount = stream->readUint16LE();
- for (uint16 i = 0; i < _typeTable.resource_types; i++) {
- _types[i].tag = stream->readUint32LE();
- _types[i].resource_table_offset = stream->readUint16LE();
+ for (uint16 i = 0; i < typeCount; i++) {
+ uint32 tag = stream->readUint32LE();
+ uint16 resourceTableOffset = stream->readUint16LE();
- debug(3, "Type[%02d]: Tag = \'%s\' ResTable Offset = %04x", i, tag2str(_types[i].tag), _types[i].resource_table_offset);
+ debug(3, "Type[%02d]: Tag = \'%s\' ResTable Offset = %04x", i, tag2str(tag), resourceTableOffset);
uint32 oldPos = stream->pos();
// Resource Table/File Table
- stream->seek(_types[i].resource_table_offset + typeTableOffset);
- _types[i].resTable.resources = stream->readUint16LE();
- _types[i].resTable.entries = new OldType::ResourceTable::Entries[_types[i].resTable.resources];
+ stream->seek(resourceTableOffset + typeTableOffset);
+ uint16 resourceCount = stream->readUint16LE();
+
+ ResourceMap &resMap = _types[tag];
+
+ for (uint16 j = 0; j < resourceCount; j++) {
+ uint16 id = stream->readUint16LE();
- for (uint16 j = 0; j < _types[i].resTable.resources; j++) {
- _types[i].resTable.entries[j].id = stream->readUint16LE();
- _types[i].resTable.entries[j].offset = stream->readUint32LE() + 1; // Need to add one to the offset to skip the checksum byte
- _types[i].resTable.entries[j].size = stream->readUint16LE();
- stream->skip(3); // Skip the useless flags
+ Resource &res = resMap[id];
+ res.offset = stream->readUint32LE() + 1; // Need to add one to the offset to skip the checksum byte
+ res.size = stream->readUint16LE();
+ stream->skip(3); // Skip (useless) flags
- debug (4, "Entry[%02x]: ID = %04x (%d)\tOffset = %08x, Size = %08x", j, _types[i].resTable.entries[j].id, _types[i].resTable.entries[j].id, _types[i].resTable.entries[j].offset, _types[i].resTable.entries[j].size);
+ debug(4, "Entry[%02x]: ID = %04x (%d)\tOffset = %08x, Size = %08x", j, id, id, res.offset, res.size);
}
stream->seek(oldPos);
- debug (3, "\n");
+ debug(3, "\n");
}
- _mhk = stream;
+ _stream = stream;
return true;
}