diff options
Diffstat (limited to 'engines/mohawk/resource.cpp')
-rw-r--r-- | engines/mohawk/resource.cpp | 602 |
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; } |