diff options
Diffstat (limited to 'engines/sci/scicore/decompress1.cpp')
-rw-r--r-- | engines/sci/scicore/decompress1.cpp | 382 |
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 |