diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/chewy/console.cpp | 9 | ||||
-rw-r--r-- | engines/chewy/graphics.cpp | 2 | ||||
-rw-r--r-- | engines/chewy/resource.cpp | 130 | ||||
-rw-r--r-- | engines/chewy/resource.h | 55 |
4 files changed, 151 insertions, 45 deletions
diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp index dab5d5a113..386654ba16 100644 --- a/engines/chewy/console.cpp +++ b/engines/chewy/console.cpp @@ -48,12 +48,17 @@ bool Console::Cmd_Dump(int argc, const char **argv) { Common::String dumpFilename = argv[3]; Resource *res = new Resource(filename); - TBFChunk *chunk = res->getChunk(resNum); + Chunk *chunk = res->getChunk(resNum); byte *data = res->getChunkData(resNum); + uint32 size = chunk->size; + if (chunk->type == kResourceTBF) { + TBFChunk *tbf = res->getTBFChunk(resNum); + size = tbf->unpackedSize; + } Common::DumpFile outFile; outFile.open(dumpFilename); - outFile.write(data, chunk->unpackedSize); + outFile.write(data, size); outFile.flush(); outFile.close(); diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp index 7f2b89c759..ba16cfb74f 100644 --- a/engines/chewy/graphics.cpp +++ b/engines/chewy/graphics.cpp @@ -30,7 +30,7 @@ namespace Chewy { void Graphics::drawImage(Common::String filename, int imageNum) { Resource *res = new Resource(filename); - TBFChunk *cur = res->getChunk(imageNum); + TBFChunk *cur = res->getTBFChunk(imageNum); byte *buf = res->getChunkData(imageNum); g_system->getPaletteManager()->setPalette(cur->palette, 0, 256); 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; diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h index 622ffa4084..e0b4230b71 100644 --- a/engines/chewy/resource.h +++ b/engines/chewy/resource.h @@ -34,13 +34,46 @@ namespace Chewy { +enum ResourceType { + kResourcePCX = 0, // unused + kResourceTBF = 1, // contained in TGPs + kResourceTAF = 2, + kResourceTFF = 3, + kResourceVOC = 4, // contained in TVPs + kResourceTPF = 5, // unused + kResourceTMF = 6, // unused + kResourceMOD = 7, // unused + kResourceRAW = 8, // unused + kResourceLBM = 9, // unused + kResourceRDI = 10, + kResourceTXT = 11, + kResourceIIB = 12, + kResourceSIB = 13, + kResourceEIB = 14, + kResourceATS = 15, // unused + kResourceSAA = 16, // unused + kResourceFLC = 17, // unused + kResourceAAD = 18, // unused + kResourceADS = 19, // unused + kResourceADH = 20, // used in txt/diah.adh + kResourceTGP = 21, // background, used in back/comic.tgp, back/episode1.tgp and back/gbook.tgp + kResourceTVP = 22, // speech, used in sound/speech.tvp + kResourceTTP = 23, // unused + kResourceTAP = 24, // sound effects, music and cutscenes, used in sound/details.tap and cut/cut.tap + kResourceCFO = 25, // unused + kResourceTCF = 26 // error messages, used in err/err_e.tcf (English) and err/err_d.tcf (German) +}; + // 4 + 2 + 2 + 4 + 2 + 2 + 768 = 784 bytes #define TBF_CHUNK_HEADER_SIZE 784 -struct TBFChunk { - uint32 packedSize; // includes header - uint16 type; +struct Chunk { + uint32 size; + ResourceType type; + uint32 pos; // position of the actual data +}; +struct TBFChunk { // TBF chunk header // ID (TBF, followed by a zero) uint16 screenMode; @@ -49,10 +82,9 @@ struct TBFChunk { uint16 width; uint16 height; byte palette[3 * 256]; - - uint32 pos; // position of the actual data }; +typedef Common::Array<Chunk> ChunkList; typedef Common::Array<TBFChunk> TBFChunkList; class Resource { @@ -60,12 +92,21 @@ public: Resource(Common::String filename); ~Resource(); - TBFChunk *getChunk(int num); + ResourceType getType() const { return _resType; } + uint32 getChunkCount() const; + Chunk *getChunk(int num); + TBFChunk *getTBFChunk(int num); byte *getChunkData(int num); -private: +protected: Common::File _stream; uint16 _chunkCount; + ResourceType _resType; + +private: + void readTBFChunk(); + + ChunkList _chunkList; TBFChunkList _tbfChunkList; }; |