CHEWY: Add support for encrypted text resources

These are mainly used for error messages
This commit is contained in:
Filippos Karapetis 2016-09-20 13:00:19 +03:00
parent c6ccd8bbe8
commit a196bfff57
4 changed files with 95 additions and 12 deletions

View File

@ -37,6 +37,7 @@ Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) {
registerCmd("play_sound", WRAP_METHOD(Console, Cmd_PlaySound));
registerCmd("play_speech", WRAP_METHOD(Console, Cmd_PlaySpeech));
registerCmd("play_music", WRAP_METHOD(Console, Cmd_PlayMusic));
registerCmd("text", WRAP_METHOD(Console, Cmd_Text));
}
Console::~Console() {
@ -148,4 +149,21 @@ bool Console::Cmd_PlayMusic(int argc, const char **argv) {
return true;
}
bool Console::Cmd_Text(int argc, const char **argv) {
if (argc < 2) {
debugPrintf("Usage: <file> <text number>\n");
return true;
}
Common::String filename = argv[1];
int resNum = atoi(argv[2]);
TextResource *res = new TextResource(filename);
Common::String str = res->getText(resNum);
this->debugPrintf("Text: %s\n", str.c_str());
delete res;
return true;
}
} // End of namespace Chewy

View File

@ -43,6 +43,7 @@ private:
bool Cmd_PlaySound(int argc, const char **argv);
bool Cmd_PlaySpeech(int argc, const char **argv);
bool Cmd_PlayMusic(int argc, const char **argv);
bool Cmd_Text(int argc, const char **argv);
};
} // End of namespace Chewy

View File

@ -30,17 +30,37 @@
namespace Chewy {
Resource::Resource(Common::String filename) {
const uint32 headerGeneric = MKTAG('N', 'G', 'S', '\0');
const uint32 headerTxtDec = MKTAG('T', 'C', 'F', '\0');
const uint32 headerTxtEnc = MKTAG('T', 'C', 'F', '\1');
_stream.open(filename);
uint32 magicBytes = MKTAG('N', 'G', 'S', '\0');
if (_stream.readUint32BE() != magicBytes)
uint32 header = _stream.readUint32BE();
bool isText = header == headerTxtDec || header == headerTxtEnc;
if (header != headerGeneric && !isText)
error("Invalid resource - %s", filename.c_str());
_resType = (ResourceType)_stream.readUint16LE();
if (isText) {
_resType = kResourceTCF;
_encrypted = (header == headerTxtEnc);
} else {
_resType = (ResourceType)_stream.readUint16LE();
_encrypted = false;
}
_chunkCount = _stream.readUint16LE();
for (uint i = 0; i < _chunkCount; i++) {
Chunk cur;
cur.size = _stream.readUint32LE();
cur.type = (ResourceType)_stream.readUint16LE();
if (!isText)
cur.type = (ResourceType)_stream.readUint16LE();
else
cur.num = _stream.readUint16LE();
cur.pos = _stream.pos();
_stream.skip(cur.size);
@ -57,11 +77,15 @@ uint32 Resource::getChunkCount() const {
return _chunkList.size();
}
Chunk *Resource::getChunk(int num) {
Chunk *Resource::getChunk(uint num) {
assert(num < _chunkList.size());
return &_chunkList[num];
}
byte *Resource::getChunkData(int num) {
byte *Resource::getChunkData(uint num) {
assert(num < _chunkList.size());
Chunk *chunk = &_chunkList[num];
byte *data = new byte[chunk->size];
@ -71,7 +95,9 @@ byte *Resource::getChunkData(int num) {
return data;
}
TBFChunk *BackgroundResource::getImage(int num) {
TBFChunk *BackgroundResource::getImage(uint num) {
assert(num < _chunkList.size());
Chunk *chunk = &_chunkList[num];
TBFChunk *tbf = new TBFChunk();
@ -111,7 +137,9 @@ TBFChunk *BackgroundResource::getImage(int num) {
return tbf;
}
SoundChunk *SoundResource::getSound(int num) {
SoundChunk *SoundResource::getSound(uint num) {
assert(num < _chunkList.size());
Chunk *chunk = &_chunkList[num];
SoundChunk *sound = new SoundChunk();
@ -155,4 +183,30 @@ SoundChunk *SoundResource::getSound(int num) {
return sound;
}
Common::String TextResource::getText(uint num) {
assert(num < _chunkList.size());
Chunk *chunk = &_chunkList[num];
Common::String str;
byte *data = new byte[chunk->size];
_stream.seek(chunk->pos, SEEK_SET);
_stream.read(data, chunk->size);
if (_encrypted) {
byte *c = data;
for (uint i = 0; i < chunk->size; i++) {
*c = -(*c);
++c;
}
}
str = (char *)data;
delete[] data;
return str;
}
} // End of namespace Chewy

View File

@ -70,6 +70,7 @@ enum ResourceType {
// Generic chunk header
struct Chunk {
uint32 size;
uint16 num; // same as the type below, used in chunks where the type is substituted with count
ResourceType type;
uint32 pos; // position of the actual data
};
@ -103,13 +104,14 @@ public:
ResourceType getType() const { return _resType; }
uint32 getChunkCount() const;
Chunk *getChunk(int num);
virtual byte *getChunkData(int num);
Chunk *getChunk(uint num);
virtual byte *getChunkData(uint num);
protected:
Common::File _stream;
uint16 _chunkCount;
ResourceType _resType;
byte _encrypted;
ChunkList _chunkList;
};
@ -119,7 +121,7 @@ public:
BackgroundResource(Common::String filename) : Resource(filename) {}
~BackgroundResource() {}
TBFChunk *getImage(int num);
TBFChunk *getImage(uint num);
};
class SoundResource : public Resource {
@ -127,7 +129,15 @@ public:
SoundResource(Common::String filename) : Resource(filename) {}
~SoundResource() {}
SoundChunk *getSound(int num);
SoundChunk *getSound(uint num);
};
class TextResource : public Resource {
public:
TextResource(Common::String filename) : Resource(filename) {}
~TextResource() {}
Common::String getText(uint num);
};
} // End of namespace Chewy