diff options
Diffstat (limited to 'engines/sci/scicore/decompress0.cpp')
-rw-r--r-- | engines/sci/scicore/decompress0.cpp | 336 |
1 files changed, 0 insertions, 336 deletions
diff --git a/engines/sci/scicore/decompress0.cpp b/engines/sci/scicore/decompress0.cpp deleted file mode 100644 index fda253b31e..0000000000 --- a/engines/sci/scicore/decompress0.cpp +++ /dev/null @@ -1,336 +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. -** This is for SCI version 0 style compression. -*/ - -#include "common/stream.h" -#include "common/endian.h" - -#include "sci/sci_memory.h" -#include "sci/scicore/resource.h" - -namespace Sci { - -//#define _SCI_DECOMPRESS_DEBUG - -// 9-12 bit LZW encoding -int unpackLZW(uint8 *dest, uint8 *src, int length, int complength) { - // Doesn't do length checking yet - /* Theory: Considering the input as a bit stream, we get a series of - ** 9 bit elements in the beginning. Every one of them is a 'token' - ** and either represents a literal (if < 0x100), or a link to a previous - ** token (tokens start at 0x102, because 0x101 is the end-of-stream - ** indicator and 0x100 is used to reset the bit stream decoder). - ** If it's a link, the indicated token and the character following it are - ** placed into the output stream. Note that the 'indicated token' may - ** very well consist of a link-token-plus-literal construct again, so - ** it's possible to represent strings longer than 2 recursively. - ** If the maximum number of tokens has been reached, the bit length is - ** increased by one, up to a maximum of 12 bits. - ** This implementation remembers the position each token was print to in - ** the output array, and the length of this token. This method should - ** be faster than the recursive approach. - */ - - uint16 bitlen = 9; // no. of bits to read (max. 12) - uint16 bitmask = 0x01ff; - uint16 bitctr = 0; // current bit position - uint16 bytectr = 0; // current byte position - uint16 token; // The last received value - uint16 maxtoken = 0x200; // The biggest token - - uint16 tokenlist[4096]; // pointers to dest[] - uint16 tokenlengthlist[4096]; // char length of each token - uint16 tokenctr = 0x102; // no. of registered tokens (starts here) - - uint16 tokenlastlength = 0; - - uint16 destctr = 0; - - while (bytectr < complength) { - - uint32 tokenmaker = src[bytectr++] >> bitctr; - if (bytectr < complength) - tokenmaker |= (src[bytectr] << (8 - bitctr)); - if (bytectr + 1 < complength) - tokenmaker |= (src[bytectr+1] << (16 - bitctr)); - - token = tokenmaker & bitmask; - - bitctr += bitlen - 8; - - while (bitctr >= 8) { - bitctr -= 8; - bytectr++; - } - - if (token == 0x101) - return 0; // terminator - if (token == 0x100) { // reset command - maxtoken = 0x200; - bitlen = 9; - bitmask = 0x01ff; - tokenctr = 0x0102; - } else { - { - int i; - - if (token > 0xff) { - if (token >= tokenctr) { -#ifdef _SCI_DECOMPRESS_DEBUG - warning("unpackLZW: Bad token %x", token); -#endif - // Well this is really bad - // May be it should throw something like SCI_ERROR_DECOMPRESSION_INSANE - } else { - tokenlastlength = tokenlengthlist[token] + 1; - if (destctr + tokenlastlength > length) { -#ifdef _SCI_DECOMPRESS_DEBUG - // For me this seems a normal situation, It's necessary to handle it - warning("unpackLZW: Trying to write beyond the end of array(len=%d, destctr=%d, tok_len=%d)", - length, destctr, tokenlastlength); -#endif - i = 0; - for (; destctr < length; destctr++) { - dest[destctr++] = dest [tokenlist[token] + i]; - i++; - } - } else - for (i = 0; i < tokenlastlength; i++) { - dest[destctr++] = dest[tokenlist[token] + i]; - } - } - } else { - tokenlastlength = 1; - if (destctr >= length) { -#ifdef _SCI_DECOMPRESS_DEBUG - warning("unpackLZW: Try to write single byte beyond end of array"); -#endif - } else - dest[destctr++] = (byte)token; - } - - } - - if (tokenctr == maxtoken) { - if (bitlen < 12) { - bitlen++; - bitmask <<= 1; - bitmask |= 1; - maxtoken <<= 1; - } else - continue; // no further tokens allowed - } - - tokenlist[tokenctr] = destctr - tokenlastlength; - tokenlengthlist[tokenctr++] = tokenlastlength; - } - } - - return 0; -} - -// Huffman-style token encoding -/***************************************************************************/ -/* This code was taken from Carl Muckenhoupt's sde.c, with some minor */ -/* modifications. */ -/***************************************************************************/ - -// unpackHuffman helper function -int16 getc2(uint8 *node, uint8 *src, uint16 *bytectr, uint16 *bitctr, int complength) { - uint16 next; - - while (node[1] != 0) { - int16 value = (src[*bytectr] << (*bitctr)); - (*bitctr)++; - if (*bitctr == 8) { - (*bitctr) = 0; - (*bytectr)++; - } - - if (value & 0x80) { - next = node[1] & 0x0f; // low 4 bits - if (next == 0) { - uint16 result = (src[*bytectr] << (*bitctr)); - - if (++(*bytectr) > complength) - return -1; - else if (*bytectr < complength) - result |= src[*bytectr] >> (8 - (*bitctr)); - - result &= 0x0ff; - return (result | 0x100); - } - } else { - next = node[1] >> 4; // high 4 bits - } - node += next << 1; - } - - return (int16)READ_LE_UINT16(node); -} - -// Huffman token decryptor -int unpackHuffman(uint8* dest, uint8* src, int length, int complength) { - // no complength checking atm */ - uint8 numnodes, terminator; - uint8 *nodes; - int16 c; - uint16 bitctr = 0, bytectr; - - numnodes = src[0]; - terminator = src[1]; - bytectr = 2 + (numnodes << 1); - nodes = src + 2; - - while (((c = getc2(nodes, src, &bytectr, &bitctr, complength)) != (0x0100 | terminator)) && (c >= 0)) { - if (length-- == 0) - return SCI_ERROR_DECOMPRESSION_OVERFLOW; - - *dest = (uint8)c; - dest++; - } - - return (c == -1) ? SCI_ERROR_DECOMPRESSION_OVERFLOW : 0; - -} - -// Carl Muckenhoupt's decompression code ends here - -int sci0_get_compression_method(Common::ReadStream &stream) { - uint16 compressionMethod; - - stream.readUint16LE(); - stream.readUint16LE(); - stream.readUint16LE(); - compressionMethod = stream.readUint16LE(); - if (stream.err()) - return SCI_ERROR_IO_ERROR; - - return compressionMethod; -} - -int decompress0(Resource *result, Common::ReadStream &stream, int sci_version) { - uint16 compressedLength; - uint16 compressionMethod; - uint8 *buffer; - uint8 type; - - 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; - - 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 %s.%03hi encrypted with method %hi at %.2f%% ratio", - getResourceTypeName(result->type), result->number, compressionMethod, - (result->size == 0) ? -1.0 : - (100.0 * compressedLength / result->size)); - debug(" compressedLength = 0x%hx, actualLength=0x%hx", - compressedLength, result->size); -#endif - - bool overflow = false; - - switch (compressionMethod) { - case 0: // no compression - if (result->size != compressedLength) - overflow = true; - else - memcpy(result->data, buffer, compressedLength); - break; - - case 1: // LZW compression - if (unpackLZW(result->data, buffer, result->size, compressedLength)) - overflow = true; - break; - - case 2: // Some sort of Huffman encoding - if (unpackHuffman(result->data, buffer, result->size, compressedLength)) - overflow = true; - break; - - default: - warning("Resource %s.%03hi: Compression method %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; - } - - if (overflow) { - 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; - free(buffer); - return 0; -} - -} // End of namespace Sci |