aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/scicore/decompress1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/scicore/decompress1.cpp')
-rw-r--r--engines/sci/scicore/decompress1.cpp382
1 files changed, 0 insertions, 382 deletions
diff --git a/engines/sci/scicore/decompress1.cpp b/engines/sci/scicore/decompress1.cpp
deleted file mode 100644
index 06b7f05103..0000000000
--- a/engines/sci/scicore/decompress1.cpp
+++ /dev/null
@@ -1,382 +0,0 @@
-/* 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$
- *
- */
-
-// Reads data from a resource file and stores the result in memory
-
-#include "common/debug.h"
-#include "common/stream.h"
-#include "common/util.h"
-
-#include "sci/sci.h"
-#include "sci/sci_memory.h"
-#include "sci/scicore/resource.h"
-
-namespace Sci {
-
-// DEFLATE-DCL
-// Refer to the FreeSCI docs for a full description.
-
-#define HUFFMAN_LEAF 0x40000000
-
-struct bit_read_struct {
- int length;
- int bitpos;
- int bytepos;
- byte *data;
-};
-
-#define BRANCH_SHIFT 12
-#define BRANCH_NODE(pos, left, right) ((left << BRANCH_SHIFT) | (right)),
-#define LEAF_NODE(pos, value) ((value) | HUFFMAN_LEAF),
-
-
-static int length_tree[] = {
-#include "treedef.1"
- 0 // We need something witout a comma at the end
-};
-
-static int distance_tree[] = {
-#include "treedef.2"
- 0 // We need something witout a comma at the end
-};
-
-static int ascii_tree[] = {
-#include "treedef.3"
- 0 // We need something witout a comma at the end
-};
-
-#define CALLC(x) { if ((x) == -SCI_ERROR_DECOMPRESSION_OVERFLOW) return -SCI_ERROR_DECOMPRESSION_OVERFLOW; }
-
-static inline int getbits_msb_first(struct bit_read_struct *inp, int bits) {
- int morebytes = (bits + inp->bitpos - 1) >> 3;
- int result = 0;
- int i;
-
- if (inp->bytepos + morebytes >= inp->length) {
- warning("read out-of-bounds with bytepos %d + morebytes %d >= length %d",
- inp->bytepos, morebytes, inp->length);
- return -SCI_ERROR_DECOMPRESSION_OVERFLOW;
- }
-
- for (i = 0; i <= morebytes; i++)
- result |= (inp->data[inp->bytepos + i]) << (i << 3);
-
- result >>= inp->bitpos;
- result &= ~(~0 << bits);
-
- inp->bitpos += bits - (morebytes << 3);
- inp->bytepos += morebytes;
-
- return result;
-}
-
-static inline int getbits(struct bit_read_struct *inp, int bits) {
- int morebytes = (bits + inp->bitpos - 1) >> 3;
- int result = 0;
- int i;
-
- if (inp->bytepos + morebytes >= inp->length) {
- warning("read out-of-bounds with bytepos %d + morebytes %d >= length %d",
- inp->bytepos, morebytes, inp->length);
- return -SCI_ERROR_DECOMPRESSION_OVERFLOW;
- }
-
- for (i = 0; i <= morebytes; i++)
- result |= (inp->data[inp->bytepos + i]) << (i << 3);
-
- result >>= inp->bitpos;
- result &= ~((~0) << bits);
-
- inp->bitpos += bits - (morebytes << 3);
- inp->bytepos += morebytes;
-
- debugC(kDebugLevelDclInflate, "(%d:%04x)", bits, result);
-
- return result;
-}
-
-static int huffman_lookup(struct bit_read_struct *inp, int *tree) {
- int pos = 0;
- int bit;
-
- while (!(tree[pos] & HUFFMAN_LEAF)) {
- CALLC(bit = getbits(inp, 1));
- debugC(kDebugLevelDclInflate, "[%d]:%d->", pos, bit);
- if (bit)
- pos = tree[pos] & ~(~0 << BRANCH_SHIFT);
- else
- pos = tree[pos] >> BRANCH_SHIFT;
- }
- debugC(kDebugLevelDclInflate, "=%02x\n", tree[pos] & 0xffff);
- return tree[pos] & 0xffff;
-}
-
-#define VALUE_M(i) ((i == 0)? 7 : (VALUE_M(i - 1) + 2**i));
-
-#define DCL_ASCII_MODE 1
-
-int unpackDCL(uint8* dest, uint8* src, int length, int complength) {
- int mode, length_param, value, val_length, val_distance;
- int write_pos = 0;
- struct bit_read_struct reader;
-
- reader.length = complength;
- reader.bitpos = 0;
- reader.bytepos = 0;
- reader.data = src;
-
- CALLC(mode = getbits(&reader, 8));
- CALLC(length_param = getbits(&reader, 8));
-
- if (mode == DCL_ASCII_MODE) {
- warning("DCL-INFLATE: Decompressing ASCII mode (untested)");
- } else if (mode) {
- warning("DCL-INFLATE: Error: Encountered mode %02x, expected 00 or 01\n", mode);
- return -1;
- }
-
- if (Common::isDebugChannelEnabled(kDebugLevelDclInflate)) {
- for (int i = 0; i < reader.length; i++) {
- debugC(kDebugLevelDclInflate, "%02x ", reader.data[i]);
- if (!((i + 1) & 0x1f))
- debugC(kDebugLevelDclInflate, "\n");
- }
-
-
- debugC(kDebugLevelDclInflate, "\n---\n");
- }
-
-
- if (length_param < 3 || length_param > 6)
- warning("Unexpected length_param value %d (expected in [3,6])\n", length_param);
-
- while (write_pos < length) {
- CALLC(value = getbits(&reader, 1));
-
- if (value) { // (length,distance) pair
- CALLC(value = huffman_lookup(&reader, length_tree));
-
- if (value < 8)
- val_length = value + 2;
- else {
- int length_bonus;
-
- val_length = (1 << (value - 7)) + 8;
- CALLC(length_bonus = getbits(&reader, value - 7));
- val_length += length_bonus;
- }
-
- debugC(kDebugLevelDclInflate, " | ");
-
- CALLC(value = huffman_lookup(&reader, distance_tree));
-
- if (val_length == 2) {
- val_distance = value << 2;
-
- CALLC(value = getbits(&reader, 2));
- val_distance |= value;
- } else {
- val_distance = value << length_param;
-
- CALLC(value = getbits(&reader, length_param));
- val_distance |= value;
- }
- ++val_distance;
-
- debugC(kDebugLevelDclInflate, "\nCOPY(%d from %d)\n", val_length, val_distance);
-
- if (val_length + write_pos > length) {
- warning("DCL-INFLATE Error: Write out of bounds while copying %d bytes", val_length);
- return SCI_ERROR_DECOMPRESSION_OVERFLOW;
- }
-
- if (write_pos < val_distance) {
- warning("DCL-INFLATE Error: Attempt to copy from before beginning of input stream");
- return SCI_ERROR_DECOMPRESSION_INSANE;
- }
-
- while (val_length) {
- int copy_length = (val_length > val_distance) ? val_distance : val_length;
-
- memcpy(dest + write_pos, dest + write_pos - val_distance, copy_length);
-
- if (Common::isDebugChannelEnabled(kDebugLevelDclInflate)) {
- for (int i = 0; i < copy_length; i++)
- debugC(kDebugLevelDclInflate, "\33[32;31m%02x\33[37;37m ", dest[write_pos + i]);
- debugC(kDebugLevelDclInflate, "\n");
- }
-
- val_length -= copy_length;
- val_distance += copy_length;
- write_pos += copy_length;
- }
-
- } else { // Copy byte verbatim
- if (mode == DCL_ASCII_MODE) {
- CALLC(value = huffman_lookup(&reader, ascii_tree));
- } else {
- CALLC(value = getbits(&reader, 8));
- }
-
- dest[write_pos++] = value;
-
- debugC(kDebugLevelDclInflate, "\33[32;31m%02x \33[37;37m", value);
- }
- }
-
- return 0;
-}
-
-int decrypt3(uint8* dest, uint8* src, int length, int complength);
-
-int decompress1(Resource *result, Common::ReadStream &stream, int sci_version) {
- uint16 compressedLength;
- uint16 compressionMethod;
- uint8 *buffer;
- uint16 type;
-
- if (sci_version == SCI_VERSION_1_EARLY) {
- result->id = stream.readUint16LE();
- if (stream.err())
- return SCI_ERROR_IO_ERROR;
-
- result->number = result->id & 0x07ff;
- type = result->id >> 11;
-
- result->type = (ResourceType)type;
- } else {
- result->id = stream.readByte();
- if (stream.err())
- return SCI_ERROR_IO_ERROR;
-
- type = result->id & 0x7f;
- result->number = stream.readUint16LE();
- if (stream.err())
- return SCI_ERROR_IO_ERROR;
-
- result->type = (ResourceType)type;
- }
-
- if ((result->number > sci_max_resource_nr[sci_version]) || (type > kResourceTypeInvalid))
- return SCI_ERROR_DECOMPRESSION_INSANE;
-
- compressedLength = stream.readUint16LE();
- result->size = stream.readUint16LE();
- compressionMethod = stream.readUint16LE();
- if (stream.err())
- return SCI_ERROR_IO_ERROR;
-
- if (result->size > SCI_MAX_RESOURCE_SIZE)
- return SCI_ERROR_RESOURCE_TOO_BIG;
-
- if (compressedLength > 4)
- compressedLength -= 4;
- else { // Object has size zero (e.g. view.000 in sq3) (does this really exist?)
- result->data = 0;
- result->status = SCI_STATUS_NOMALLOC;
- return SCI_ERROR_EMPTY_OBJECT;
- }
-
- buffer = (uint8 *)sci_malloc(compressedLength);
- result->data = (unsigned char *)sci_malloc(result->size);
-
- if (stream.read(buffer, compressedLength) != compressedLength) {
- free(result->data);
- free(buffer);
- result->data = 0;
- return SCI_ERROR_IO_ERROR;
- };
-
-
-#ifdef _SCI_DECOMPRESS_DEBUG
- debug("Resource %i.%s encrypted with method SCI1%c/%hi at %.2f%% ratio",
- result->number, sci_resource_type_suffixes[result->type],
- early ? 'e' : 'l',
- compressionMethod,
- (result->size == 0) ? -1.0 :
- (100.0 * compressedLength / result->size));
- debug(" compressedLength = 0x%hx, actualLength=0x%hx",
- compressedLength, result->size);
-#endif
-
- switch (compressionMethod) {
- case 0: // no compression
- if (result->size != compressedLength) {
- free(result->data);
- result->data = NULL;
- result->status = SCI_STATUS_NOMALLOC;
- free(buffer);
- return SCI_ERROR_DECOMPRESSION_OVERFLOW;
- }
- memcpy(result->data, buffer, compressedLength);
- result->status = SCI_STATUS_ALLOCATED;
- break;
-
- case 1: // LZW
- if (unpackHuffman(result->data, buffer, result->size, compressedLength)) {
- free(result->data);
- result->data = 0; // So that we know that it didn't work
- result->status = SCI_STATUS_NOMALLOC;
- free(buffer);
- return SCI_ERROR_DECOMPRESSION_OVERFLOW;
- }
- result->status = SCI_STATUS_ALLOCATED;
- break;
-
- case 2: // ???
- case 3:
- case 4:
- if (decrypt3(result->data, buffer, result->size, compressedLength)) {
- free(result->data);
- result->data = 0; // So that we know that it didn't work
- result->status = SCI_STATUS_NOMALLOC;
- free(buffer);
- return SCI_ERROR_DECOMPRESSION_OVERFLOW;
- }
-
- if (compressionMethod == 3)
- result->data = view_reorder(result->data, result->size);
- if (compressionMethod == 4)
- result->data = pic_reorder(result->data, result->size);
- result->status = SCI_STATUS_ALLOCATED;
- break;
-
- default:
- warning("Resource %s.%03hi: Compression method SCI1/%hi not supported",
- getResourceTypeName(result->type), result->number,
- compressionMethod);
- free(result->data);
- result->data = 0; // So that we know that it didn't work
- result->status = SCI_STATUS_NOMALLOC;
- free(buffer);
- return SCI_ERROR_UNKNOWN_COMPRESSION;
- }
-
- free(buffer);
-
- return 0;
-}
-
-} // End of namespace Sci