Initial commit
This commit is contained in:
119
engines/chamber/decompr.cpp
Normal file
119
engines/chamber/decompr.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "chamber/chamber.h"
|
||||
|
||||
namespace Chamber {
|
||||
|
||||
|
||||
static struct {
|
||||
byte codes[256];
|
||||
byte prefix[256];
|
||||
byte suffix[256];
|
||||
byte coddict[256];
|
||||
byte codlink[256];
|
||||
byte stackpos;
|
||||
} DecompCtx;
|
||||
|
||||
byte decode_string(byte code, byte prev_n, byte *stack) {
|
||||
byte n;
|
||||
while ((n = DecompCtx.coddict[code]) != 0) {
|
||||
while (n >= prev_n) {
|
||||
n = DecompCtx.codlink[n];
|
||||
if (n == 0)
|
||||
return code;
|
||||
}
|
||||
/*if(DecompCtx.stackpos == 255) exit("stack exploded");*/
|
||||
stack[DecompCtx.stackpos++] = prev_n = n;
|
||||
code = DecompCtx.prefix[n];
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
uint32 decompress(byte *data, byte *result) {
|
||||
byte dict_size, more;
|
||||
uint16 compsize;
|
||||
uint16 i;
|
||||
byte code, n, suffix;
|
||||
byte stack[256];
|
||||
uint32 decompsize = 0;
|
||||
|
||||
do {
|
||||
dict_size = *data++;
|
||||
more = *data++;
|
||||
compsize = *data++;
|
||||
compsize |= (*data++) << 8;
|
||||
|
||||
if (dict_size == 0) {
|
||||
/* uncompressed block */
|
||||
decompsize += compsize;
|
||||
while (compsize--)
|
||||
*result++ = *data++;
|
||||
} else {
|
||||
/* compressed block */
|
||||
/*
|
||||
memcpy(DecompCtx.codes + 1, data, dict_size); data += dict_size;
|
||||
memcpy(DecompCtx.prefix + 1, data, dict_size); data += dict_size;
|
||||
memcpy(DecompCtx.suffix + 1, data, dict_size); data += dict_size;
|
||||
*/
|
||||
for (n = 1, i = 0; i < dict_size; n++, i++) DecompCtx.codes[n] = *data++;
|
||||
for (n = 1, i = 0; i < dict_size; n++, i++) DecompCtx.prefix[n] = *data++;
|
||||
for (n = 1, i = 0; i < dict_size; n++, i++) DecompCtx.suffix[n] = *data++;
|
||||
|
||||
memset(DecompCtx.coddict, 0, 256);
|
||||
for (n = 1, i = 0; i < dict_size; n++, i++) {
|
||||
code = DecompCtx.codes[n];
|
||||
DecompCtx.codlink[n] = DecompCtx.coddict[code];
|
||||
DecompCtx.coddict[code] = n;
|
||||
}
|
||||
|
||||
while (compsize-- > 0) {
|
||||
code = *data++;
|
||||
|
||||
if (DecompCtx.coddict[code] == 0) {
|
||||
/* literal */
|
||||
*result++ = code;
|
||||
decompsize += 1;
|
||||
} else {
|
||||
/* string */
|
||||
DecompCtx.stackpos = 0;
|
||||
|
||||
n = DecompCtx.coddict[code];
|
||||
|
||||
stack[DecompCtx.stackpos++] = n;
|
||||
|
||||
for (code = DecompCtx.prefix[n];; code = DecompCtx.suffix[n]) {
|
||||
suffix = decode_string(code, n, stack);
|
||||
*result++ = suffix;
|
||||
decompsize += 1;
|
||||
if (DecompCtx.stackpos == 0)
|
||||
break;
|
||||
n = stack[--DecompCtx.stackpos];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (more != 0);
|
||||
|
||||
return decompsize;
|
||||
}
|
||||
|
||||
} // End of namespace Chamber
|
||||
Reference in New Issue
Block a user