diff options
Diffstat (limited to 'engines/chewy/resource.cpp')
-rw-r--r-- | engines/chewy/resource.cpp | 130 |
1 files changed, 95 insertions, 35 deletions
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp index 40db53abe6..233e8cd4f4 100644 --- a/engines/chewy/resource.cpp +++ b/engines/chewy/resource.cpp @@ -34,64 +34,124 @@ Resource::Resource(Common::String filename) { uint32 magicBytes = MKTAG('N', 'G', 'S', '\0'); if (_stream.readUint32BE() != magicBytes) error("Invalid resource - %s", filename.c_str()); - _stream.skip(2); // type + _resType = (ResourceType)_stream.readUint16LE(); _chunkCount = _stream.readUint16LE(); - uint32 tbfID = MKTAG('T', 'B', 'F', '\0'); - for (uint i = 0; i < _chunkCount; i++) { - TBFChunk cur; - cur.packedSize = _stream.readUint32LE() - TBF_CHUNK_HEADER_SIZE; - cur.type = _stream.readUint16LE(); - if (_stream.readUint32BE() != tbfID) - error("Corrupt resource %s", filename.c_str()); - - cur.screenMode = _stream.readUint16LE(); - cur.compressionFlag = _stream.readUint16LE(); - cur.unpackedSize = _stream.readUint32LE(); - cur.width = _stream.readUint16LE(); - cur.height = _stream.readUint16LE(); - for (int j = 0; j < 3 * 256; j++) - cur.palette[j] = _stream.readByte() << 2; + Chunk cur; + cur.size = _stream.readUint32LE(); + cur.type = (ResourceType)_stream.readUint16LE(); cur.pos = _stream.pos(); - _stream.skip(cur.packedSize); + if (cur.type == kResourceTBF) { + cur.pos += TBF_CHUNK_HEADER_SIZE; + cur.size -= TBF_CHUNK_HEADER_SIZE; + readTBFChunk(); + } - _tbfChunkList.push_back(cur); + _stream.skip(cur.size); + _chunkList.push_back(cur); } - } Resource::~Resource() { + _chunkList.clear(); _tbfChunkList.clear(); _stream.close(); } -TBFChunk *Resource::getChunk(int num) { +void Resource::readTBFChunk() { + TBFChunk cur; + if (_stream.readUint32BE() != MKTAG('T', 'B', 'F', '\0')) + error("Corrupt TBF resource"); + + cur.screenMode = _stream.readUint16LE(); + cur.compressionFlag = _stream.readUint16LE(); + cur.unpackedSize = _stream.readUint32LE(); + cur.width = _stream.readUint16LE(); + cur.height = _stream.readUint16LE(); + for (int j = 0; j < 3 * 256; j++) + cur.palette[j] = _stream.readByte() << 2; + + _tbfChunkList.push_back(cur); +} + +uint32 Resource::getChunkCount() const { + return _chunkList.size(); +} + +Chunk *Resource::getChunk(int num) { + return &_chunkList[num]; +} + +TBFChunk *Resource::getTBFChunk(int num) { + assert(_resType == kResourceTGP); return &_tbfChunkList[num]; } byte *Resource::getChunkData(int num) { - TBFChunk *chunk = &_tbfChunkList[num]; - byte *data = new byte[chunk->unpackedSize]; + Chunk *chunk = &_chunkList[num]; + byte *data; _stream.seek(chunk->pos, SEEK_SET); - if (!chunk->compressionFlag) { - _stream.read(data, chunk->packedSize); - } else { - // Compressed resources are packed using a very simple RLE compression - byte count; - byte value; - uint32 outPos = 0; - - for (uint i = 0; i < (chunk->packedSize) / 2 && outPos < chunk->unpackedSize; i++) { - count = _stream.readByte(); - value = _stream.readByte(); - for (byte j = 0; j < count; j++) { - data[outPos++] = value; + if (chunk->type == kResourceTBF) { + TBFChunk *tbfChunk = &_tbfChunkList[num]; + data = new byte[tbfChunk->unpackedSize]; + + if (!tbfChunk->compressionFlag) { + _stream.read(data, chunk->size); + } else { + // Compressed images are packed using a very simple RLE compression + byte count; + byte value; + uint32 outPos = 0; + + for (uint i = 0; i < (chunk->size) / 2 && outPos < tbfChunk->unpackedSize; i++) { + count = _stream.readByte(); + value = _stream.readByte(); + for (byte j = 0; j < count; j++) { + data[outPos++] = value; + } } } + } else if (chunk->type == kResourceVOC) { + // Voice files are split in blocks, so reassemble them here + byte blocksRemaining; + uint32 totalLength = 0; + uint32 blockSize; + + // Find the total length of the voice file + do { + blocksRemaining = _stream.readByte(); + blockSize = + _stream.readByte() + + (_stream.readByte() << 8) + + (_stream.readByte() << 16); + + totalLength += blockSize; + _stream.skip(blockSize); + } while (blocksRemaining > 1); + + // Read the voice data + data = new byte[totalLength]; + byte *ptr = data; + + _stream.seek(chunk->pos, SEEK_SET); + + do { + blocksRemaining = _stream.readByte(); + blockSize = + _stream.readByte() + + (_stream.readByte() << 8) + + (_stream.readByte() << 16); + + _stream.read(ptr, blockSize); + ptr += blockSize; + } while (blocksRemaining > 1); + } else { + data = new byte[chunk->size]; + _stream.read(data, chunk->size); } return data; |