diff options
-rw-r--r-- | engines/chewy/console.cpp | 32 | ||||
-rw-r--r-- | engines/chewy/console.h | 1 | ||||
-rw-r--r-- | engines/chewy/graphics.cpp | 12 | ||||
-rw-r--r-- | engines/chewy/resource.cpp | 166 | ||||
-rw-r--r-- | engines/chewy/resource.h | 48 | ||||
-rw-r--r-- | engines/chewy/sound.cpp | 24 | ||||
-rw-r--r-- | engines/chewy/sound.h | 6 |
7 files changed, 171 insertions, 118 deletions
diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp index b610dddf65..298e10baf4 100644 --- a/engines/chewy/console.cpp +++ b/engines/chewy/console.cpp @@ -32,6 +32,7 @@ namespace Chewy { Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) { registerCmd("dump", WRAP_METHOD(Console, Cmd_Dump)); + registerCmd("dump_bg", WRAP_METHOD(Console, Cmd_DumpBg)); registerCmd("draw", WRAP_METHOD(Console, Cmd_Draw)); registerCmd("play_sound", WRAP_METHOD(Console, Cmd_PlaySound)); registerCmd("play_speech", WRAP_METHOD(Console, Cmd_PlaySpeech)); @@ -55,10 +56,6 @@ bool Console::Cmd_Dump(int argc, const char **argv) { 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); @@ -72,6 +69,33 @@ bool Console::Cmd_Dump(int argc, const char **argv) { return true; } +bool Console::Cmd_DumpBg(int argc, const char **argv) { + if (argc < 4) { + debugPrintf("Usage: dump_bg <file> <resource number> <dump file name>\n"); + return true; + } + + Common::String filename = argv[1]; + int resNum = atoi(argv[2]); + Common::String dumpFilename = argv[3]; + + BackgroundResource *res = new BackgroundResource(filename); + TBFChunk *image = res->getImage(resNum); + + Common::DumpFile outFile; + outFile.open(dumpFilename); + outFile.write(image->data, image->size); + outFile.flush(); + outFile.close(); + + delete[] image->data; + delete image; + delete res; + + return true; +} + + bool Console::Cmd_Draw(int argc, const char **argv) { if (argc < 3) { debugPrintf("Usage: draw <file> <resource number>\n"); diff --git a/engines/chewy/console.h b/engines/chewy/console.h index 9877824fff..873359db40 100644 --- a/engines/chewy/console.h +++ b/engines/chewy/console.h @@ -38,6 +38,7 @@ private: ChewyEngine *_vm; bool Cmd_Dump(int argc, const char **argv); + bool Cmd_DumpBg(int argc, const char **argv); bool Cmd_Draw(int argc, const char **argv); bool Cmd_PlaySound(int argc, const char **argv); bool Cmd_PlaySpeech(int argc, const char **argv); diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp index ba16cfb74f..c3b29febff 100644 --- a/engines/chewy/graphics.cpp +++ b/engines/chewy/graphics.cpp @@ -29,13 +29,15 @@ namespace Chewy { void Graphics::drawImage(Common::String filename, int imageNum) { - Resource *res = new Resource(filename); - TBFChunk *cur = res->getTBFChunk(imageNum); - byte *buf = res->getChunkData(imageNum); + BackgroundResource *res = new BackgroundResource(filename); + TBFChunk *image = res->getImage(imageNum); - g_system->getPaletteManager()->setPalette(cur->palette, 0, 256); - g_system->copyRectToScreen(buf, cur->width, 0, 0, cur->width, cur->height); + g_system->getPaletteManager()->setPalette(image->palette, 0, 256); + g_system->copyRectToScreen(image->data, image->width, 0, 0, image->width, image->height); g_system->updateScreen(); + + delete[] image->data; + delete image; delete res; } diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp index 233e8cd4f4..1bd9583a72 100644 --- a/engines/chewy/resource.cpp +++ b/engines/chewy/resource.cpp @@ -43,12 +43,6 @@ Resource::Resource(Common::String filename) { cur.type = (ResourceType)_stream.readUint16LE(); cur.pos = _stream.pos(); - if (cur.type == kResourceTBF) { - cur.pos += TBF_CHUNK_HEADER_SIZE; - cur.size -= TBF_CHUNK_HEADER_SIZE; - readTBFChunk(); - } - _stream.skip(cur.size); _chunkList.push_back(cur); } @@ -56,26 +50,9 @@ Resource::Resource(Common::String filename) { Resource::~Resource() { _chunkList.clear(); - _tbfChunkList.clear(); _stream.close(); } -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(); } @@ -84,77 +61,98 @@ Chunk *Resource::getChunk(int num) { return &_chunkList[num]; } -TBFChunk *Resource::getTBFChunk(int num) { - assert(_resType == kResourceTGP); - return &_tbfChunkList[num]; +byte *Resource::getChunkData(int num) { + Chunk *chunk = &_chunkList[num]; + byte *data = new byte[chunk->size]; + + _stream.seek(chunk->pos, SEEK_SET); + _stream.read(data, chunk->size); + + return data; } -byte *Resource::getChunkData(int num) { +TBFChunk *BackgroundResource::getImage(int num) { Chunk *chunk = &_chunkList[num]; - byte *data; + TBFChunk *tbf = new TBFChunk(); _stream.seek(chunk->pos, SEEK_SET); - 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; - } + if (_stream.readUint32BE() != MKTAG('T', 'B', 'F', '\0')) + error("Corrupt TBF resource"); + + tbf->screenMode = _stream.readUint16LE(); + tbf->compressionFlag = _stream.readUint16LE(); + tbf->size = _stream.readUint32LE(); + tbf->width = _stream.readUint16LE(); + tbf->height = _stream.readUint16LE(); + for (int j = 0; j < 3 * 256; j++) + tbf->palette[j] = _stream.readByte() << 2; + + tbf->data = new byte[tbf->size]; + + if (!tbf->compressionFlag) { + _stream.read(tbf->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 < tbf->size; i++) { + count = _stream.readByte(); + value = _stream.readByte(); + for (byte j = 0; j < count; j++) { + tbf->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; + return tbf; +} + +SoundChunk *SoundResource::getSound(int num) { + Chunk *chunk = &_chunkList[num]; + SoundChunk *sound = new SoundChunk(); + + _stream.seek(chunk->pos, SEEK_SET); + + // 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 + sound->size = totalLength; + sound->data = new byte[totalLength]; + byte *ptr = sound->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); + + return sound; } } // End of namespace Chewy diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h index e0b4230b71..50a0d1b8fb 100644 --- a/engines/chewy/resource.h +++ b/engines/chewy/resource.h @@ -36,12 +36,12 @@ namespace Chewy { enum ResourceType { kResourcePCX = 0, // unused - kResourceTBF = 1, // contained in TGPs + kResourceTBF = 1, // background art, contained in TGPs kResourceTAF = 2, kResourceTFF = 3, - kResourceVOC = 4, // contained in TVPs + kResourceVOC = 4, // speech and SFX, contained in TVPs kResourceTPF = 5, // unused - kResourceTMF = 6, // unused + kResourceTMF = 6, // music, similar to a MOD file, contained in details.tap kResourceMOD = 7, // unused kResourceRAW = 8, // unused kResourceLBM = 9, // unused @@ -56,10 +56,10 @@ enum ResourceType { 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 + kResourceTGP = 21, // container for background art, used in back/comic.tgp, back/episode1.tgp and back/gbook.tgp + kResourceTVP = 22, // container for 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 + kResourceTAP = 24, // container for 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) }; @@ -67,21 +67,30 @@ enum ResourceType { // 4 + 2 + 2 + 4 + 2 + 2 + 768 = 784 bytes #define TBF_CHUNK_HEADER_SIZE 784 +// Generic chunk header struct Chunk { uint32 size; ResourceType type; uint32 pos; // position of the actual data }; +// TBF (background) chunk header struct TBFChunk { // TBF chunk header // ID (TBF, followed by a zero) uint16 screenMode; uint16 compressionFlag; - uint32 unpackedSize; + uint32 size; uint16 width; uint16 height; byte palette[3 * 256]; + byte *data; +}; + +// Sound chunk header +struct SoundChunk { + uint32 size; + byte *data; }; typedef Common::Array<Chunk> ChunkList; @@ -90,24 +99,35 @@ typedef Common::Array<TBFChunk> TBFChunkList; class Resource { public: Resource(Common::String filename); - ~Resource(); + virtual ~Resource(); ResourceType getType() const { return _resType; } uint32 getChunkCount() const; Chunk *getChunk(int num); - TBFChunk *getTBFChunk(int num); - byte *getChunkData(int num); + virtual byte *getChunkData(int num); protected: Common::File _stream; uint16 _chunkCount; ResourceType _resType; -private: - void readTBFChunk(); - ChunkList _chunkList; - TBFChunkList _tbfChunkList; +}; + +class BackgroundResource : public Resource { +public: + BackgroundResource(Common::String filename) : Resource(filename) {} + ~BackgroundResource() {} + + TBFChunk *getImage(int num); +}; + +class SoundResource : public Resource { +public: + SoundResource(Common::String filename) : Resource(filename) {} + ~SoundResource() {} + + SoundChunk *getSound(int num); }; } // End of namespace Chewy diff --git a/engines/chewy/sound.cpp b/engines/chewy/sound.cpp index 41f91d0886..9ef4df97d9 100644 --- a/engines/chewy/sound.cpp +++ b/engines/chewy/sound.cpp @@ -31,8 +31,8 @@ namespace Chewy { Sound::Sound() { - _speechRes = new Resource("speech.tvp"); - _soundRes = new Resource("details.tap"); + _speechRes = new SoundResource("speech.tvp"); + _soundRes = new SoundResource("details.tap"); } Sound::~Sound() { @@ -41,16 +41,20 @@ Sound::~Sound() { } void Sound::playSound(int num, bool loop) { - Chunk *chunk = _soundRes->getChunk(num); - byte *data = _soundRes->getChunkData(num); + SoundChunk *sound = _soundRes->getSound(num); + byte *data = (byte *)malloc(sound->size); + memcpy(data, sound->data, sound->size); Audio::AudioStream *stream = Audio::makeLoopingAudioStream( Audio::makeRawStream(data, - chunk->size, 22050, Audio::FLAG_UNSIGNED, + sound->size, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::NO), loop ? 0 : 1); g_engine->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream); + + delete[] sound->data; + delete sound; } void Sound::playMusic(int num, bool loop) { @@ -72,16 +76,20 @@ void Sound::playMusic(int num, bool loop) { } void Sound::playSpeech(int num) { - Chunk *chunk = _speechRes->getChunk(num); - byte *data = _speechRes->getChunkData(num); + SoundChunk *sound = _speechRes->getSound(num); + byte *data = (byte *)malloc(sound->size); + memcpy(data, sound->data, sound->size); Audio::AudioStream *stream = Audio::makeLoopingAudioStream( Audio::makeRawStream(data, - chunk->size, 22050, Audio::FLAG_UNSIGNED, + sound->size, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::NO), 1); g_engine->_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream); + + delete[] sound->data; + delete sound; } } // End of namespace Chewy diff --git a/engines/chewy/sound.h b/engines/chewy/sound.h index 6537f3eabe..23610272e5 100644 --- a/engines/chewy/sound.h +++ b/engines/chewy/sound.h @@ -28,7 +28,7 @@ namespace Chewy { -class Resource; +class SoundResource; class Sound { public: @@ -44,8 +44,8 @@ private: Audio::SoundHandle _musicHandle; Audio::SoundHandle _speechHandle; - Resource *_speechRes; - Resource *_soundRes; + SoundResource *_speechRes; + SoundResource *_soundRes; }; } // End of namespace Chewy |