diff options
author | Benjamin Haisch | 2008-04-23 08:08:37 +0000 |
---|---|---|
committer | Benjamin Haisch | 2008-04-23 08:08:37 +0000 |
commit | 6069dba988e9940b4d5285d6abc01b83967f8702 (patch) | |
tree | 3e70fa2ecffca571d1dde627a5f052653a44ae57 | |
parent | 18ed600abea41fee47f92fa798f6fe49c5c37d25 (diff) | |
download | scummvm-rg350-6069dba988e9940b4d5285d6abc01b83967f8702.tar.gz scummvm-rg350-6069dba988e9940b4d5285d6abc01b83967f8702.tar.bz2 scummvm-rg350-6069dba988e9940b4d5285d6abc01b83967f8702.zip |
Implemented direct loading of rtzcd.dat from the archive rtzcd.red, i.e. the game doesn't have to be installed first to get rtzcd.dat. Also added the respective detection entry.
svn-id: r31661
-rw-r--r-- | engines/made/database.cpp | 75 | ||||
-rw-r--r-- | engines/made/database.h | 6 | ||||
-rw-r--r-- | engines/made/detection.cpp | 18 | ||||
-rw-r--r-- | engines/made/module.mk | 1 | ||||
-rw-r--r-- | engines/made/redreader.cpp | 422 | ||||
-rw-r--r-- | engines/made/redreader.h | 108 |
6 files changed, 605 insertions, 25 deletions
diff --git a/engines/made/database.cpp b/engines/made/database.cpp index d8330278ec..816df58510 100644 --- a/engines/made/database.cpp +++ b/engines/made/database.cpp @@ -117,6 +117,16 @@ const char *Object::getString() { return NULL; } +void Object::setString(const char *str) { + if (getClass() == 0x7FFF) { + char *objStr = (char*)getData(); + if (str) + strncpy(objStr, str, getSize()); + else + objStr[0] = '\0'; + } +} + bool Object::isObject() { return getClass() < 0x7FFE; } @@ -181,31 +191,48 @@ GameDatabase::~GameDatabase() { } void GameDatabase::open(const char *filename) { - _fd.open(filename); + debug(1, "GameDatabase::open() Loading from %s", filename); + Common::File fd; + if (!fd.open(filename)) + error("GameDatabase::open() Could not open %s", filename); + load(fd); + fd.close(); +} + +void GameDatabase::openFromRed(const char *redFilename, const char *filename) { + debug(1, "GameDatabase::openFromRed() Loading from %s->%s", redFilename, filename); + Common::MemoryReadStream *fileS = RedReader::loadFromRed(redFilename, filename); + if (!fileS) + error("GameDatabase::openFromRed() Could not load %s from %s", filename, redFilename); + load(*fileS); + delete fileS; +} + +void GameDatabase::load(Common::SeekableReadStream &sourceS) { // TODO: Read/verifiy header - _fd.seek(0x1E); + sourceS.seek(0x1E); - uint32 objectIndexOffs = _fd.readUint32LE(); - uint16 objectCount = _fd.readUint16LE(); - uint32 gameStateOffs = _fd.readUint32LE(); - _gameStateSize = _fd.readUint32LE(); - uint32 objectsOffs = _fd.readUint32LE(); - uint32 objectsSize = _fd.readUint32LE(); - _mainCodeObjectIndex = _fd.readUint16LE(); + uint32 objectIndexOffs = sourceS.readUint32LE(); + uint16 objectCount = sourceS.readUint16LE(); + uint32 gameStateOffs = sourceS.readUint32LE(); + _gameStateSize = sourceS.readUint32LE(); + uint32 objectsOffs = sourceS.readUint32LE(); + uint32 objectsSize = sourceS.readUint32LE(); + _mainCodeObjectIndex = sourceS.readUint16LE(); debug(2, "objectIndexOffs = %08X; objectCount = %d; gameStateOffs = %08X; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n", objectIndexOffs, objectCount, gameStateOffs, _gameStateSize, objectsOffs, objectsSize); _gameState = new byte[_gameStateSize]; - _fd.seek(gameStateOffs); - _fd.read(_gameState, _gameStateSize); + sourceS.seek(gameStateOffs); + sourceS.read(_gameState, _gameStateSize); Common::Array<uint32> objectOffsets; - _fd.seek(objectIndexOffs); + sourceS.seek(objectIndexOffs); for (uint32 i = 0; i < objectCount; i++) - objectOffsets.push_back(_fd.readUint32LE()); + objectOffsets.push_back(sourceS.readUint32LE()); for (uint32 i = 0; i < objectCount; i++) { Object *obj = new Object(); @@ -218,8 +245,8 @@ void GameDatabase::open(const char *filename) { if (objectOffsets[i] & 1) { debug(2, "-> const %08X\n", objectsOffs + objectOffsets[i] - 1); - _fd.seek(objectsOffs + objectOffsets[i] - 1); - obj->load(_fd); + sourceS.seek(objectsOffs + objectOffsets[i] - 1); + obj->load(sourceS); } else { debug(2, "-> var\n"); obj->load(_gameState + objectOffsets[i]); @@ -253,11 +280,11 @@ int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, i while (count2-- > 0) { if ((READ_LE_UINT16(prop) & 0x3FFF) == propertyId) { if (READ_LE_UINT16(prop) & 0x4000) { - debug(2, "! L1.1\n"); + //debug(2, "! L1.1\n"); propertyFlag = 1; return (int16*)_gameState + READ_LE_UINT16(propPtr1); } else { - debug(2, "! L1.2\n"); + //debug(2, "! L1.2\n"); propertyFlag = obj->getFlags() & 1; return propPtr1; } @@ -269,13 +296,13 @@ int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, i // Now check in the object hierarchy of the given object int16 parentObjectIndex = obj->getClass(); if (parentObjectIndex == 0) { - debug(2, "! NULL(np)\n"); + //debug(2, "! NULL(np)\n"); return NULL; } while (parentObjectIndex != 0) { - debug(2, "parentObjectIndex = %04X\n", parentObjectIndex); + //debug(2, "parentObjectIndex = %04X\n", parentObjectIndex); obj = getObject(parentObjectIndex); @@ -290,11 +317,11 @@ int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, i if (!(READ_LE_UINT16(prop) & 0x8000)) { if ((READ_LE_UINT16(prop) & 0x3FFF) == propertyId) { if (*prop & 0x4000) { - debug(2, "! L2.1\n"); + //debug(2, "! L2.1\n"); propertyFlag = 1; return (int16*)_gameState + READ_LE_UINT16(propPtr1); } else { - debug(2, "! L2.2\n"); + //debug(2, "! L2.2\n"); propertyFlag = obj->getFlags() & 1; return propPtr1; } @@ -304,11 +331,11 @@ int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, i } else { if ((READ_LE_UINT16(prop) & 0x3FFF) == propertyId) { if (*prop & 0x4000) { - debug(2, "! L3.1\n"); + //debug(2, "! L3.1\n"); propertyFlag = 1; return (int16*)_gameState + READ_LE_UINT16(propertyPtr); } else { - debug(2, "! L3.2\n"); + //debug(2, "! L3.2\n"); propertyFlag = obj->getFlags() & 1; return propertyPtr; } @@ -322,7 +349,7 @@ int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, i } - debug(2, "! NULL(nf)\n"); + //debug(2, "! NULL(nf)\n"); return NULL; } diff --git a/engines/made/database.h b/engines/made/database.h index e96be5e24c..5e88b0919f 100644 --- a/engines/made/database.h +++ b/engines/made/database.h @@ -31,6 +31,8 @@ #include "common/file.h" #include "common/stream.h" +#include "made/redreader.h" + namespace Made { class Object { @@ -49,6 +51,7 @@ public: byte *getData(); const char *getString(); + void setString(const char *str); bool isObject(); bool isVector(); @@ -73,6 +76,7 @@ public: ~GameDatabase(); void open(const char *filename); + void openFromRed(const char *redFilename, const char *filename); Object *getObject(int16 index) const { if (index >= 1) @@ -93,11 +97,11 @@ public: void dumpObject(int16 index); protected: - Common::File _fd; Common::Array<Object*> _objects; byte *_gameState; uint32 _gameStateSize; int16 _mainCodeObjectIndex; + void load(Common::SeekableReadStream &sourceS); }; } // End of namespace Made diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp index e8b63a0aca..9406f1fc53 100644 --- a/engines/made/detection.cpp +++ b/engines/made/detection.cpp @@ -73,6 +73,8 @@ static const MadeGameDescription gameDescriptions[] = { { // Return to Zork - English CD version + // NOTE: This detects the game via the rtzcd.dat which is inside rtzcd.red. + // The entry below detects via rtzcd.red directly, which is the "official" way. { "rtz", "CD", @@ -88,6 +90,22 @@ static const MadeGameDescription gameDescriptions[] = { }, { + // Return to Zork - English CD version + { + "rtz", + "CD", + AD_ENTRY1("rtzcd.red", "c4e2430e6b6c6ff1562a80fb4a9df24c"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + 0, + 0, + 0, + 0, + }, + + { // Return to Zork - Demo { "rtz", diff --git a/engines/made/module.mk b/engines/made/module.mk index 727a785dbc..1f4cf73cb8 100644 --- a/engines/made/module.mk +++ b/engines/made/module.mk @@ -6,6 +6,7 @@ MODULE_OBJS = \ graphics.o \ made.o \ pmvplayer.o \ + redreader.o \ resource.o \ screen.o \ script.o \ diff --git a/engines/made/redreader.cpp b/engines/made/redreader.cpp new file mode 100644 index 0000000000..96ed2a4c15 --- /dev/null +++ b/engines/made/redreader.cpp @@ -0,0 +1,422 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "made/redreader.h" + +namespace Made { + + +Common::MemoryReadStream *RedReader::load(const char *redFilename, const char *filename) { + + Common::File fd; + FileEntry fileEntry; + + if (!fd.open(redFilename)) + error("RedReader::RedReader() Could not open %s", redFilename); + + if (!seekFile(fd, fileEntry, filename)) + error("RedReader::RedReader() Could not find %s in archive %s", filename, redFilename); + + byte *fileBuf = new byte[fileEntry.origSize]; + + LzhDecompressor lzhDec; + lzhDec.decompress(fd, fileBuf, fileEntry.compSize, fileEntry.origSize); + + return new Common::MemoryReadStream(fileBuf, fileEntry.origSize, true); + +} + +Common::MemoryReadStream *RedReader::loadFromRed(const char *redFilename, const char *filename) { + RedReader redReader; + return redReader.load(redFilename, filename); +} + +bool RedReader::seekFile(Common::File &fd, FileEntry &fileEntry, const char *filename) { + char arcFilename[13]; + while (!fd.eof()) { + fd.skip(8); // skip unknown + fileEntry.compSize = fd.readUint32LE(); + fileEntry.origSize = fd.readUint32LE(); + fd.skip(10); // skip unknown + fd.read(arcFilename, 13); + fd.skip(2); // skip unknown + // Check if we have found the file + if (!scumm_stricmp(arcFilename, filename)) + return true; + // Skip compressed data + fd.skip(fileEntry.compSize); + } + return false; +} + +LzhDecompressor::LzhDecompressor() { +} + +LzhDecompressor::~LzhDecompressor() { +} + +int LzhDecompressor::decompress(Common::SeekableReadStream &source, byte *dest, uint32 sourceLen, uint32 destLen) { + + int bufsize; + byte buffer[DICSIZ]; + + _source = &source; + _compSize = sourceLen; + + count_len_depth = 0; + + _blockPos = 0; + + decode_start(); + while (destLen > 0) { + bufsize = ((destLen > DICSIZ) ? DICSIZ : destLen); + decode(bufsize, buffer); + memcpy(dest, buffer, bufsize); + dest += bufsize; + destLen -= bufsize; + } + + return 0; +} + +byte LzhDecompressor::readByte() { + if (_blockPos == 0xFFE) { + _blockPos = 0; + _source->skip(2); // skip unknown value + } + byte temp = _source->readByte(); + _blockPos++; + return temp; +} + +void LzhDecompressor::fillbuf(int count) { + _bitbuf <<= count; + while (count > _bitcount) { + _bitbuf |= _subbitbuf << (count -= _bitcount); + if (_compSize != 0) { + _compSize--; + _subbitbuf = readByte(); + } else _subbitbuf = 0; + _bitcount = 8; + } + _bitbuf |= _subbitbuf >> (_bitcount -= count); +} + +uint LzhDecompressor::getbits(int count) { + uint x; + x = _bitbuf >> (BITBUFSIZ - count); + fillbuf(count); + return x; +} + +void LzhDecompressor::init_getbits() { + _bitbuf = 0; + _subbitbuf = 0; + _bitcount = 0; + fillbuf(BITBUFSIZ); +} + +void LzhDecompressor::decode_start() { + huf_decode_start(); + decode_j = 0; +} + +void LzhDecompressor::decode(uint count, byte buffer[]) { + uint r, c; + r = 0; + while (--decode_j >= 0) { + buffer[r] = buffer[decode_i]; + decode_i = (decode_i + 1) & (DICSIZ - 1); + if (++r == count) return; + } + for ( ; ; ) { + c = decode_c(); + if (c <= 255) { + buffer[r] = c; + if (++r == count) return; + } else { + decode_j = c - (255 + 1 - THRESHOLD); + decode_i = (r - decode_p() - 1) & (DICSIZ - 1); + while (--decode_j >= 0) { + buffer[r] = buffer[decode_i]; + decode_i = (decode_i + 1) & (DICSIZ - 1); + if (++r == count) return; + } + } + } +} + +void LzhDecompressor::read_pt_len(int nn, int nbit, int i_special) { + int i, c, v; + unsigned int mask; + v = getbits(nbit); + if (v == 0) { + c = getbits(nbit); + for (i = 0; i < nn; i++) _pt_len[i] = 0; + for (i = 0; i < 256; i++) _pt_table[i] = c; + } else { + i = 0; + while (i < v) { + c = _bitbuf >> (BITBUFSIZ - 3); + if (c == 7) { + mask = 1U << (BITBUFSIZ - 1 - 3); + while (mask & _bitbuf) { mask >>= 1; c++; } + } + fillbuf((c < 7) ? 3 : c - 3); + _pt_len[i++] = c; + if (i == i_special) { + c = getbits(2); + while (--c >= 0) _pt_len[i++] = 0; + } + } + while (i < nn) _pt_len[i++] = 0; + make_table(nn, _pt_len, 8, _pt_table); + } +} + +void LzhDecompressor::read_c_len() { + uint i, v; + int c; + unsigned int mask; + v = getbits(CBIT); + if (v == 0) { + c = getbits(CBIT); + for (i = 0; i < NC; i++) _c_len[i] = 0; + for (i = 0; i < 4096; i++) _c_table[i] = c; + } else { + i = 0; + while (i < v) { + c = _pt_table[_bitbuf >> (BITBUFSIZ - 8)]; + if (c >= NT) { + mask = 1U << (BITBUFSIZ - 1 - 8); + do { + if (_bitbuf & mask) c = _right[c]; + else c = _left [c]; + mask >>= 1; + } while (c >= NT); + } + fillbuf(_pt_len[c]); + if (c <= 2) { + if (c == 0) c = 1; + else if (c == 1) c = getbits(4) + 3; + else c = getbits(CBIT) + 20; + while (--c >= 0) _c_len[i++] = 0; + } else _c_len[i++] = c - 2; + } + while (i < NC) _c_len[i++] = 0; + make_table(NC, _c_len, 12, _c_table); + } +} + +unsigned int LzhDecompressor::decode_c(void) { + uint j, mask; + if (_blocksize == 0) { + _blocksize = getbits(16); + read_pt_len(NT, TBIT, 3); + read_c_len(); + read_pt_len(NP, PBIT, -1); + } + _blocksize--; + j = _c_table[_bitbuf >> (BITBUFSIZ - 12)]; + if (j >= NC) { + mask = 1U << (BITBUFSIZ - 1 - 12); + do { + if (_bitbuf & mask) j = _right[j]; + else j = _left [j]; + mask >>= 1; + } while (j >= NC); + } + fillbuf(_c_len[j]); + return j; +} + +unsigned int LzhDecompressor::decode_p() { + unsigned int j, mask; + j = _pt_table[_bitbuf >> (BITBUFSIZ - 8)]; + if (j >= NP) { + mask = 1U << (BITBUFSIZ - 1 - 8); + do { + if (_bitbuf & mask) j = _right[j]; + else j = _left [j]; + mask >>= 1; + } while (j >= NP); + } + fillbuf(_pt_len[j]); + if (j != 0) j = (1U << (j - 1)) + getbits(j - 1); + return j; +} + +void LzhDecompressor::huf_decode_start() { + init_getbits(); + _blocksize = 0; +} + +void LzhDecompressor::make_table(uint nchar, byte bitlen[], uint tablebits, uint16 table[]) { + uint16 count[17], weight[17], start[18], *p; + uint i, k, len, ch, jutbits, avail, nextcode, mask; + for (i = 1; i <= 16; i++) count[i] = 0; + for (i = 0; i < nchar; i++) count[bitlen[i]]++; + start[1] = 0; + for (i = 1; i <= 16; i++) + start[i + 1] = start[i] + (count[i] << (16 - i)); + if (start[17] != (uint16)(1U << 16)) + error("LzhDecompressor::make_table() Bad table\n"); + jutbits = 16 - tablebits; + for (i = 1; i <= tablebits; i++) { + start[i] >>= jutbits; + weight[i] = 1U << (tablebits - i); + } + while (i <= 16) weight[i++] = 1U << (16 - i); + i = start[tablebits + 1] >> jutbits; + if (i != (uint16)(1U << 16)) { + k = 1U << tablebits; + while (i != k) table[i++] = 0; + } + avail = nchar; + mask = 1U << (15 - tablebits); + for (ch = 0; ch < nchar; ch++) { + if ((len = bitlen[ch]) == 0) continue; + nextcode = start[len] + weight[len]; + if (len <= tablebits) { + for (i = start[len]; i < nextcode; i++) table[i] = ch; + } else { + k = start[len]; + p = &table[k >> jutbits]; + i = len - tablebits; + while (i != 0) { + if (*p == 0) { + _right[avail] = _left[avail] = 0; + *p = avail++; + } + if (k & mask) p = &_right[*p]; + else p = &_left[*p]; + k <<= 1; i--; + } + *p = ch; + } + start[len] = nextcode; + } +} + +/* call with i = root */ +void LzhDecompressor::count_len(int i) { + if (i < tree_n) + len_cnt[(count_len_depth < 16) ? count_len_depth : 16]++; + else { + count_len_depth++; + count_len(_left [i]); + count_len(_right[i]); + count_len_depth--; + } +} + +void LzhDecompressor::make_len(int root) { + int i, k; + uint cum; + for (i = 0; i <= 16; i++) len_cnt[i] = 0; + count_len(root); + cum = 0; + for (i = 16; i > 0; i--) + cum += len_cnt[i] << (16 - i); + while (cum != (1U << 16)) { + len_cnt[16]--; + for (i = 15; i > 0; i--) { + if (len_cnt[i] != 0) { + len_cnt[i]--; + len_cnt[i+1] += 2; + break; + } + } + cum--; + } + for (i = 16; i > 0; i--) { + k = len_cnt[i]; + while (--k >= 0) len_table[*sortptr++] = i; + } +} + +void LzhDecompressor::downheap(int i) { + int j, k; + k = heap[i]; + while ((j = 2 * i) <= heapsize) { + if (j < heapsize && freq[heap[j]] > freq[heap[j + 1]]) + j++; + if (freq[k] <= freq[heap[j]]) break; + heap[i] = heap[j]; i = j; + } + heap[i] = k; +} + +void LzhDecompressor::make_code(int n, byte len[], uint16 code[]) { + int i; + uint16 start[18]; + start[1] = 0; + for (i = 1; i <= 16; i++) + start[i + 1] = (start[i] + len_cnt[i]) << 1; + for (i = 0; i < n; i++) code[i] = start[len[i]]++; +} + +/* make tree, calculate len[], return root */ +int LzhDecompressor::make_tree(int nparm, uint16 freqparm[], byte lenparm[], uint16 codeparm[]) { + int i, j, k, avail; + + tree_n = nparm; + freq = freqparm; + len_table = lenparm; + avail = tree_n; + heapsize = 0; + heap[1] = 0; + for (i = 0; i < tree_n; i++) { + len_table[i] = 0; + if (freq[i]) heap[++heapsize] = i; + } + if (heapsize < 2) { + codeparm[heap[1]] = 0; + return heap[1]; + } + for (i = heapsize / 2; i >= 1; i--) + downheap(i); /* make priority queue */ + sortptr = codeparm; + do { /* while queue has at least two entries */ + i = heap[1]; /* take out least-freq entry */ + if (i < tree_n) *sortptr++ = i; + heap[1] = heap[heapsize--]; + downheap(1); + j = heap[1]; /* next least-freq entry */ + if (j < tree_n) *sortptr++ = j; + k = avail++; /* generate new node */ + freq[k] = freq[i] + freq[j]; + heap[1] = k; + downheap(1); /* put into queue */ + _left[k] = i; + _right[k] = j; + } while (heapsize > 1); + sortptr = codeparm; + make_len(k); + make_code(nparm, lenparm, codeparm); + return k; /* return root */ +} + +} diff --git a/engines/made/redreader.h b/engines/made/redreader.h new file mode 100644 index 0000000000..362a94706e --- /dev/null +++ b/engines/made/redreader.h @@ -0,0 +1,108 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef MADE_REDREADER_H +#define MADE_REDREADER_H + +#include "common/util.h" +#include "common/file.h" +#include "common/stream.h" + +namespace Made { + +class RedReader { +public: + Common::MemoryReadStream *load(const char *redFilename, const char *filename); + static Common::MemoryReadStream *loadFromRed(const char *redFilename, const char *filename); +private: + struct FileEntry { + uint32 compSize, origSize; + }; + bool seekFile(Common::File &fd, FileEntry &fileEntry, const char *filename); +}; + +const uint BITBUFSIZ = 16; +const uint DICBIT = 13; +const uint DICSIZ = 1 << DICBIT; +const uint MATCHBIT = 8; +const uint MAXMATCH = 256; +const uint THRESHOLD = 3; +const uint NC = 255 + MAXMATCH + 2 - THRESHOLD; +const uint CBIT = 9; +const uint CODE_BIT = 16; +const uint NP = DICBIT + 1; +const int NT = CODE_BIT + 3; +const uint PBIT = 4; +const uint TBIT = 5; +const uint NPT = NT; + +class LzhDecompressor { +public: + LzhDecompressor(); + ~LzhDecompressor(); + int decompress(Common::SeekableReadStream &source, byte *dest, uint32 compSize, uint32 origSize); +private: + Common::SeekableReadStream *_source; + uint32 _compSize, _blockPos; + + uint16 _bitbuf; + uint _subbitbuf; + int _bitcount; + uint16 _left[2 * NC - 1], _right[2 * NC - 1]; + byte _c_len[NC], _pt_len[NPT]; + uint _blocksize; + uint16 _c_table[4096], _pt_table[256]; + int tree_n, heapsize; + short heap[NC + 1]; + uint16 *freq, *sortptr, len_cnt[17]; + byte *len_table; + + int decode_i, decode_j; + int count_len_depth; + + byte readByte(); + + void fillbuf(int count); + uint getbits(int count); + void init_getbits(void); + void decode_start(void); + void decode(uint count, byte text[]); + void huf_decode_start(void); + unsigned int decode_c(void); + unsigned int decode_p(); + void read_pt_len(int nn, int nbit, int i_special); + void read_c_len(); + void count_len(int i); + void make_len(int root); + void downheap(int i); + void make_code(int n, byte len[], uint16 code[]); + void make_table(uint nchar, byte bitlen[], uint tablebits, uint16 table[]); + int make_tree(int nparm, uint16 freqparm[], byte lenparm[], uint16 codeparm[]); + +}; + +} // End of namespace Made + +#endif /* MADE_H */ |