mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
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
This commit is contained in:
parent
18ed600abe
commit
6069dba988
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
@ -87,6 +89,22 @@ static const MadeGameDescription gameDescriptions[] = {
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
// 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
|
||||
{
|
||||
|
@ -6,6 +6,7 @@ MODULE_OBJS = \
|
||||
graphics.o \
|
||||
made.o \
|
||||
pmvplayer.o \
|
||||
redreader.o \
|
||||
resource.o \
|
||||
screen.o \
|
||||
script.o \
|
||||
|
422
engines/made/redreader.cpp
Normal file
422
engines/made/redreader.cpp
Normal file
@ -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 */
|
||||
}
|
||||
|
||||
}
|
108
engines/made/redreader.h
Normal file
108
engines/made/redreader.h
Normal file
@ -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 */
|
Loading…
Reference in New Issue
Block a user