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;  } | 
