aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippos Karapetis2016-09-20 10:50:59 +0300
committerFilippos Karapetis2016-10-03 00:33:16 +0300
commit8ab1846f59504dc7edd8d26b7702d520e3bab631 (patch)
treef33463e08dede2a9a636c4b4567567de6cbe534f
parentb7e4bcf3f20dc38ccd465acc07f42cb62557a2c9 (diff)
downloadscummvm-rg350-8ab1846f59504dc7edd8d26b7702d520e3bab631.tar.gz
scummvm-rg350-8ab1846f59504dc7edd8d26b7702d520e3bab631.tar.bz2
scummvm-rg350-8ab1846f59504dc7edd8d26b7702d520e3bab631.zip
CHEWY: Add support for SFX and speech resources to the resource manager
-rw-r--r--engines/chewy/console.cpp9
-rw-r--r--engines/chewy/graphics.cpp2
-rw-r--r--engines/chewy/resource.cpp130
-rw-r--r--engines/chewy/resource.h55
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;
};