2009-12-29 23:18:24 +00:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
* $ URL $
* $ Id $
*
*/
2010-01-22 03:43:57 +00:00
# include "mohawk/resource.h"
2009-12-29 23:18:24 +00:00
# include "common/util.h"
namespace Mohawk {
2010-01-22 03:43:57 +00:00
MohawkArchive : : MohawkArchive ( ) {
2009-12-29 23:18:24 +00:00
_mhk = NULL ;
_types = NULL ;
_fileTable = NULL ;
}
2010-01-22 03:43:57 +00:00
void MohawkArchive : : open ( Common : : String filename ) {
2009-12-29 23:18:24 +00:00
Common : : File * file = new Common : : File ( ) ;
if ( ! file - > open ( filename . c_str ( ) ) )
error ( " Could not open file \' %s \' " , filename . c_str ( ) ) ;
_curFile = filename ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
open ( file ) ;
}
2010-01-22 03:43:57 +00:00
void MohawkArchive : : close ( ) {
2010-01-25 01:39:44 +00:00
delete _mhk ; _mhk = NULL ;
2009-12-29 23:18:24 +00:00
delete [ ] _types ; _types = NULL ;
delete [ ] _fileTable ; _fileTable = NULL ;
2010-01-25 01:39:44 +00:00
2009-12-30 23:01:16 +00:00
_curFile . clear ( ) ;
2009-12-29 23:18:24 +00:00
}
2010-01-22 03:43:57 +00:00
void MohawkArchive : : open ( Common : : SeekableReadStream * stream ) {
2009-12-29 23:18:24 +00:00
// Make sure no other file is open...
close ( ) ;
_mhk = stream ;
if ( _mhk - > readUint32BE ( ) ! = ID_MHWK )
error ( " Could not find tag \' MHWK \' " ) ;
_fileSize = _mhk - > readUint32BE ( ) ;
if ( _mhk - > readUint32BE ( ) ! = ID_RSRC )
error ( " Could not find tag \' RSRC \' " ) ;
2010-01-26 23:05:52 +00:00
_rsrc . version = _mhk - > readUint16BE ( ) ;
if ( _rsrc . version ! = 0x100 )
error ( " Unsupported Mohawk resource version %d.%d " , ( _rsrc . version > > 8 ) & 0xff , _rsrc . version & 0xff ) ;
_rsrc . compaction = _mhk - > readUint16BE ( ) ; // Only used in creation, not in reading
2009-12-29 23:18:24 +00:00
_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 ) ;
/////////////////////////////////
//Resource Dir
2010-01-25 01:39:44 +00:00
/////////////////////////////////
2009-12-29 23:18:24 +00:00
// Type Table
_mhk - > seek ( _rsrc . abs_offset ) ;
_typeTable . name_offset = _mhk - > readUint16BE ( ) ;
_typeTable . resource_types = _mhk - > readUint16BE ( ) ;
debug ( 0 , " Name List Offset = %04x Number of Resource Types = %04x " , _typeTable . name_offset , _typeTable . resource_types ) ;
_types = new Type [ _typeTable . resource_types ] ;
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 ( ) ;
// 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 ) ;
2010-06-26 17:21:50 +00:00
// Resource Table
2009-12-29 23:18:24 +00:00
_mhk - > seek ( _rsrc . abs_offset + _types [ i ] . resource_table_offset ) ;
_types [ i ] . resTable . resources = _mhk - > readUint16BE ( ) ;
debug ( 3 , " Resources = %04x " , _types [ i ] . resTable . resources ) ;
_types [ i ] . resTable . entries = new Type : : ResourceTable : : Entries [ _types [ i ] . resTable . resources ] ;
2009-12-30 07:30:04 +00:00
2009-12-29 23:18:24 +00:00
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 ( ) ;
2010-01-25 01:39:44 +00:00
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 ) ;
2009-12-29 23:18:24 +00:00
}
// Name Table
_mhk - > seek ( _rsrc . abs_offset + _types [ i ] . name_table_offset ) ;
_types [ i ] . nameTable . num = _mhk - > readUint16BE ( ) ;
debug ( 3 , " Names = %04x " , _types [ i ] . nameTable . num ) ;
_types [ i ] . nameTable . entries = new Type : : NameTable : : Entries [ _types [ i ] . nameTable . num ] ;
2009-12-30 07:30:04 +00:00
2009-12-29 23:18:24 +00:00
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 ( ) ;
debug ( 4 , " Entry[%02x]: Name List Offset = %04x Index = %04x " , j , _types [ i ] . nameTable . entries [ j ] . offset , _types [ i ] . nameTable . entries [ j ] . index ) ;
// 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 ( ) ;
}
debug ( 3 , " Name = \' %s \' " , _types [ i ] . nameTable . entries [ j ] . name . c_str ( ) ) ;
// Get back to next entry
_mhk - > seek ( pos ) ;
}
// Return to next TypeTable entry
_mhk - > seek ( _rsrc . abs_offset + ( i + 1 ) * 8 + 4 ) ;
debug ( 3 , " \n " ) ;
}
_mhk - > seek ( _rsrc . abs_offset + _rsrc . file_table_offset ) ;
_fileTableAmount = _mhk - > readUint32BE ( ) ;
_fileTable = new FileTable [ _fileTableAmount ] ;
2009-12-30 07:30:04 +00:00
2009-12-29 23:18:24 +00:00
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 ( ) ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
// 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 ;
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 ) ;
}
}
2010-01-22 03:43:57 +00:00
bool MohawkArchive : : hasResource ( uint32 tag , uint16 id ) {
2009-12-29 23:18:24 +00:00
if ( ! _mhk )
return false ;
int16 typeIndex = getTypeIndex ( tag ) ;
if ( typeIndex < 0 )
return false ;
return ( getIdIndex ( typeIndex , id ) > = 0 ) ;
}
2010-01-22 03:43:57 +00:00
uint32 MohawkArchive : : getOffset ( uint32 tag , uint16 id ) {
2009-12-31 00:37:40 +00:00
assert ( _mhk ) ;
int16 typeIndex = getTypeIndex ( tag ) ;
assert ( typeIndex > = 0 ) ;
int16 idIndex = getIdIndex ( typeIndex , id ) ;
assert ( idIndex > = 0 ) ;
2010-01-25 01:39:44 +00:00
2009-12-31 00:37:40 +00:00
return _fileTable [ _types [ typeIndex ] . resTable . entries [ idIndex ] . index - 1 ] . offset ;
}
2010-01-22 03:43:57 +00:00
Common : : SeekableReadStream * MohawkArchive : : getRawData ( uint32 tag , uint16 id ) {
2009-12-29 23:18:24 +00:00
if ( ! _mhk )
2010-01-22 03:43:57 +00:00
error ( " MohawkArchive::getRawData - No File in Use " ) ;
2009-12-29 23:18:24 +00:00
int16 typeIndex = getTypeIndex ( tag ) ;
if ( typeIndex < 0 )
error ( " Could not find a tag of \' %s \' in file \' %s \' " , tag2str ( tag ) , _curFile . c_str ( ) ) ;
int16 idIndex = getIdIndex ( typeIndex , id ) ;
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 ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
// 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 )
return new Common : : SeekableSubReadStream ( _mhk , _fileTable [ fileTableIndex ] . offset , _mhk - > size ( ) ) ;
else
return new Common : : SeekableSubReadStream ( _mhk , _fileTable [ fileTableIndex ] . offset , _fileTable [ fileTableIndex + 1 ] . offset ) ;
}
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
return new Common : : SeekableSubReadStream ( _mhk , _fileTable [ fileTableIndex ] . offset , _fileTable [ fileTableIndex ] . offset + _fileTable [ fileTableIndex ] . dataSize ) ;
}
2010-01-22 03:43:57 +00:00
void LivingBooksArchive_v1 : : open ( Common : : SeekableReadStream * stream ) {
2009-12-29 23:18:24 +00:00
close ( ) ;
_mhk = stream ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
// 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.
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
uint32 headerSize = _mhk - > readUint32BE ( ) ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
// NOTE: There are differences besides endianness! (Subtle changes,
// but different).
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
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 ] ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
debug ( 0 , " Old Mohawk File (Macintosh): Number of Resource Types = %04x " , _typeTable . resource_types ) ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
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?)
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
debug ( 3 , " Type[%02d]: Tag = \' %s \' ResTable Offset = %04x " , i , tag2str ( _types [ i ] . tag ) , _types [ i ] . resource_table_offset ) ;
uint32 oldPos = _mhk - > pos ( ) ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
// 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 ] ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
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?)
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
debug ( 4 , " Entry[%02x]: ID = %04x (%d) \t Offset = %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 ) ;
}
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
_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 ] ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
debug ( 0 , " Old Mohawk File (Windows): Number of Resource Types = %04x " , _typeTable . resource_types ) ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
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?)
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
debug ( 3 , " Type[%02d]: Tag = \' %s \' ResTable Offset = %04x " , i , tag2str ( _types [ i ] . tag ) , _types [ i ] . resource_table_offset ) ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
uint32 oldPos = _mhk - > pos ( ) ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
// 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 ] ;
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
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 - > readUint16LE ( ) ;
_mhk - > readUint32LE ( ) ; // Unknown (always 0?)
2010-01-25 01:39:44 +00:00
debug ( 4 , " Entry[%02x]: ID = %04x (%d) \t Offset = %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 ) ;
2009-12-29 23:18:24 +00:00
}
2010-01-25 01:39:44 +00:00
2009-12-29 23:18:24 +00:00
_mhk - > seek ( oldPos ) ;
debug ( 3 , " \n " ) ;
}
} else
error ( " Could not determine type of Old Mohawk resource " ) ;
}
2010-01-22 03:43:57 +00:00
uint32 LivingBooksArchive_v1 : : getOffset ( uint32 tag , uint16 id ) {
2009-12-31 00:37:40 +00:00
assert ( _mhk ) ;
int16 typeIndex = getTypeIndex ( tag ) ;
assert ( typeIndex > = 0 ) ;
int16 idIndex = getIdIndex ( typeIndex , id ) ;
assert ( idIndex > = 0 ) ;
2010-01-25 01:39:44 +00:00
2009-12-31 00:37:40 +00:00
return _types [ typeIndex ] . resTable . entries [ idIndex ] . offset ;
}
2010-01-22 03:43:57 +00:00
Common : : SeekableReadStream * LivingBooksArchive_v1 : : getRawData ( uint32 tag , uint16 id ) {
2009-12-29 23:18:24 +00:00
if ( ! _mhk )
2010-01-22 03:43:57 +00:00
error ( " LivingBooksArchive_v1::getRawData - No File in Use " ) ;
2009-12-29 23:18:24 +00:00
int16 typeIndex = getTypeIndex ( tag ) ;
if ( typeIndex < 0 )
error ( " Could not find a tag of \' %s \' in file \' %s \' " , tag2str ( tag ) , _curFile . c_str ( ) ) ;
int16 idIndex = getIdIndex ( typeIndex , id ) ;
if ( idIndex < 0 )
error ( " Could not find \' %s \' %04x in file \' %s \' " , tag2str ( tag ) , id , _curFile . c_str ( ) ) ;
return new Common : : SeekableSubReadStream ( _mhk , _types [ typeIndex ] . resTable . entries [ idIndex ] . offset , _types [ typeIndex ] . resTable . entries [ idIndex ] . offset + _types [ typeIndex ] . resTable . entries [ idIndex ] . size ) ;
}
} // End of namespace Mohawk