[Scummvm-cvs-logs] SF.net SVN: scummvm:[39311] scummvm/trunk

gregfrieger at users.sourceforge.net gregfrieger at users.sourceforge.net
Tue Mar 10 22:44:03 CET 2009


Revision: 39311
          http://scummvm.svn.sourceforge.net/scummvm/?rev=39311&view=rev
Author:   gregfrieger
Date:     2009-03-10 21:44:03 +0000 (Tue, 10 Mar 2009)

Log Message:
-----------
Resource decompression functions moved to scicore\decompressor.cpp and turned into classes. 

Modified Paths:
--------------
    scummvm/trunk/dists/msvc8/sci.vcproj
    scummvm/trunk/engines/sci/module.mk
    scummvm/trunk/engines/sci/scicore/resource.cpp
    scummvm/trunk/engines/sci/scicore/resource.h

Added Paths:
-----------
    scummvm/trunk/engines/sci/scicore/decompressor.cpp
    scummvm/trunk/engines/sci/scicore/decompressor.h

Removed Paths:
-------------
    scummvm/trunk/engines/sci/scicore/decompress0.cpp
    scummvm/trunk/engines/sci/scicore/decompress01.cpp
    scummvm/trunk/engines/sci/scicore/decompress1.cpp
    scummvm/trunk/engines/sci/scicore/decompress11.cpp

Modified: scummvm/trunk/dists/msvc8/sci.vcproj
===================================================================
--- scummvm/trunk/dists/msvc8/sci.vcproj	2009-03-10 20:37:54 UTC (rev 39310)
+++ scummvm/trunk/dists/msvc8/sci.vcproj	2009-03-10 21:44:03 UTC (rev 39311)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="windows-1252"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="8,00"
+	Version="8.00"
 	Name="sci"
 	ProjectGUID="{53F17B2B-0412-4EC3-A999-ED0537BB5223}"
 	RootNamespace="sci"
@@ -486,22 +486,14 @@
 			Name="scicore"
 			>
 			<File
-				RelativePath="..\..\engines\sci\scicore\decompress0.cpp"
+				RelativePath="..\..\engines\sci\scicore\decompressor.cpp"
 				>
 			</File>
 			<File
-				RelativePath="..\..\engines\sci\scicore\decompress01.cpp"
+				RelativePath="..\..\engines\sci\scicore\decompressor.h"
 				>
 			</File>
 			<File
-				RelativePath="..\..\engines\sci\scicore\decompress1.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\engines\sci\scicore\decompress11.cpp"
-				>
-			</File>
-			<File
 				RelativePath="..\..\engines\sci\scicore\resource.cpp"
 				>
 			</File>

Modified: scummvm/trunk/engines/sci/module.mk
===================================================================
--- scummvm/trunk/engines/sci/module.mk	2009-03-10 20:37:54 UTC (rev 39310)
+++ scummvm/trunk/engines/sci/module.mk	2009-03-10 21:44:03 UTC (rev 39311)
@@ -55,10 +55,7 @@
 	gfx/resource/res_pic.o \
 	gfx/resource/res_view0.o \
 	gfx/resource/res_view1.o \
-	scicore/decompress0.o \
-	scicore/decompress01.o \
-	scicore/decompress1.o \
-	scicore/decompress11.o \
+	scicore/decompressor.o \
 	scicore/resource.o \
 	scicore/sciconsole.o \
 	scicore/versions.o \

Deleted: scummvm/trunk/engines/sci/scicore/decompress0.cpp
===================================================================
--- scummvm/trunk/engines/sci/scicore/decompress0.cpp	2009-03-10 20:37:54 UTC (rev 39310)
+++ scummvm/trunk/engines/sci/scicore/decompress0.cpp	2009-03-10 21:44:03 UTC (rev 39311)
@@ -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

Deleted: scummvm/trunk/engines/sci/scicore/decompress01.cpp
===================================================================
--- scummvm/trunk/engines/sci/scicore/decompress01.cpp	2009-03-10 20:37:54 UTC (rev 39310)
+++ scummvm/trunk/engines/sci/scicore/decompress01.cpp	2009-03-10 21:44:03 UTC (rev 39311)
@@ -1,601 +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/stream.h"
-#include "common/endian.h"
-
-#include "sci/sci_memory.h"
-#include "sci/scicore/resource.h"
-
-namespace Sci {
-
-// The following code was originally created by Carl Muckenhoupt for his
-// SCI decoder. It has been ported to the FreeSCI environment by Sergey Lapin.
-
-// TODO: Clean up, re-organize, improve speed-wise */
-
-struct tokenlist {
-	uint8 data;
-	int16 next;
-} tokens[0x1004];
-
-static int8 stak[0x1014] = {0};
-static int8 lastchar = 0;
-static int16 stakptr = 0;
-static uint16 s_numbits, s_bitstring, lastbits, decryptstart;
-static int16 curtoken, endtoken;
-
-uint32 gbits(int numbits,  uint8 * data, int dlen);
-
-int decrypt3(uint8 *dest, uint8 *src, int length, int complength) {
-	// Init
-	int i;
-
-	lastchar = lastbits = s_bitstring = stakptr = 0;
-	s_numbits = 9;
-	curtoken = 0x102;
-	endtoken = 0x1ff;
-	decryptstart = 0;
-	gbits(0, 0, 0);
-
-	for (i = 0;i < 0x1004;i++) {
-		tokens[i].next = 0;
-		tokens[i].data = 0;
-	}
-
-	// Start decrypting
-
-	static int16 token;
-	while (length != 0) {
-		switch (decryptstart) {
-		case 0:
-		case 1:
-			s_bitstring = gbits(s_numbits, src, complength);
-			if (s_bitstring == 0x101) { // found end-of-data signal
-				decryptstart = 4;
-				return 0;
-			}
-			if (decryptstart == 0) { // first char
-				decryptstart = 1;
-				lastbits = s_bitstring;
-				*(dest++) = lastchar = (s_bitstring & 0xff);
-				if (--length != 0)
-					continue;
-				return 0;
-			}
-			if (s_bitstring == 0x100) { // start-over signal
-				s_numbits = 9;
-				endtoken = 0x1ff;
-				curtoken = 0x102;
-				decryptstart = 0;
-				continue;
-			}
-			token = s_bitstring;
-			if (token >= curtoken) { // index past current point
-				token = lastbits;
-				stak[stakptr++] = lastchar;
-			}
-			while ((token > 0xff) && (token < 0x1004)) { // follow links back in data
-				stak[stakptr++] = tokens[token].data;
-				token = tokens[token].next;
-			}
-			lastchar = stak[stakptr++] = token & 0xff;
-		case 2:
-			while (stakptr > 0) { // put stack in buffer
-				*(dest++) = stak[--stakptr];
-				length--;
-				if (length == 0) {
-					decryptstart = 2;
-					return 0;
-				}
-			}
-			decryptstart = 1;
-			if (curtoken <= endtoken) { // put token into record
-				tokens[curtoken].data = lastchar;
-				tokens[curtoken].next = lastbits;
-				curtoken++;
-				if (curtoken == endtoken && s_numbits != 12) {
-					s_numbits++;
-					endtoken <<= 1;
-					endtoken++;
-				}
-			}
-			lastbits = s_bitstring;
-			continue; // When are "break" and "continue" synonymous?
-		case 4:
-			return 0;
-		}
-	}
-
-	return 0;
-}
-
-uint32 gbits(int numbits,  uint8 * data, int dlen) {
-	int place; // indicates location within byte
-	uint32 bitstring;
-	static uint32 whichbit = 0;
-	int i;
-
-	if (numbits == 0) {
-		whichbit = 0;
-		return 0;
-	}
-
-	place = whichbit >> 3;
-	bitstring = 0;
-	for (i = (numbits >> 3) + 1;i >= 0;i--) {
-		if (i + place < dlen)
-			bitstring |= data[place+i] << (8 * (2 - i));
-	}
-	//bitstring = data[place + 2] | (long)(data[place + 1]) << 8 | (long)(data[place]) << 16;
-	bitstring >>= 24 - (whichbit & 7) - numbits;
-	bitstring &= (0xffffffff >> (32 - numbits));
-	// Okay, so this could be made faster with a table lookup.
-	// It doesn't matter. It's fast enough as it is.
-	whichbit += numbits;
-
-	return bitstring;
-}
-
-// Carl Muckenhoupt's code ends here
-
-enum {
-	PIC_OP_SET_COLOR = 0xf0,
-	PIC_OP_DISABLE_VISUAL = 0xf1,
-	PIC_OP_SET_PRIORITY = 0xf2,
-	PIC_OP_DISABLE_PRIORITY = 0xf3,
-	PIC_OP_SHORT_PATTERNS = 0xf4,
-	PIC_OP_MEDIUM_LINES = 0xf5,
-	PIC_OP_LONG_LINES = 0xf6,
-	PIC_OP_SHORT_LINES = 0xf7,
-	PIC_OP_FILL = 0xf8,
-	PIC_OP_SET_PATTERN = 0xf9,
-	PIC_OP_ABSOLUTE_PATTERN = 0xfa,
-	PIC_OP_SET_CONTROL = 0xfb,
-	PIC_OP_DISABLE_CONTROL = 0xfc,
-	PIC_OP_MEDIUM_PATTERNS = 0xfd,
-	PIC_OP_OPX = 0xfe,
-	PIC_OP_TERMINATE = 0xff
-};
-
-enum {
-	PIC_OPX_SET_PALETTE_ENTRIES = 0,
-	PIC_OPX_EMBEDDED_VIEW = 1,
-	PIC_OPX_SET_PALETTE = 2,
-	PIC_OPX_PRIORITY_TABLE_EQDIST = 3,
-	PIC_OPX_PRIORITY_TABLE_EXPLICIT = 4
-};
-
-#define PAL_SIZE 1284
-#define CEL_HEADER_SIZE 7
-#define EXTRA_MAGIC_SIZE 15
-
-static void decode_rle(byte **rledata, byte **pixeldata, byte *outbuffer, int size) {
-	int pos = 0;
-	char nextbyte;
-	byte *rd = *rledata;
-	byte *ob = outbuffer;
-	byte *pd = *pixeldata;
-
-	while (pos < size) {
-		nextbyte = *(rd++);
-		*(ob++) = nextbyte;
-		pos ++;
-		switch (nextbyte&0xC0) {
-		case 0x40 :
-		case 0x00 :
-			memcpy(ob, pd, nextbyte);
-			pd += nextbyte;
-			ob += nextbyte;
-			pos += nextbyte;
-			break;
-		case 0xC0 :
-			break;
-		case 0x80 :
-			nextbyte = *(pd++);
-			*(ob++) = nextbyte;
-			pos ++;
-			break;
-		}
-	}
-
-	*rledata = rd;
-	*pixeldata = pd;
-}
-
-/*
- * Does the same this as above, only to determine the length of the compressed
- * source data.
- *
- * Yes, this is inefficient.
- */
-static int rle_size(byte *rledata, int dsize) {
-	int pos = 0;
-	char nextbyte;
-	int size = 0;
-
-	while (pos < dsize) {
-		nextbyte = *(rledata++);
-		pos ++;
-		size ++;
-
-		switch (nextbyte&0xC0) {
-		case 0x40 :
-		case 0x00 :
-			pos += nextbyte;
-			break;
-		case 0xC0 :
-			break;
-		case 0x80 :
-			pos ++;
-			break;
-		}
-	}
-
-	return size;
-}
-
-byte *pic_reorder(byte *inbuffer, int dsize) {
-	byte *reorderBuffer;
-	int view_size;
-	int view_start;
-	int cdata_size;
-	int i;
-	byte *seeker = inbuffer;
-	byte *writer;
-	char viewdata[CEL_HEADER_SIZE];
-	byte *cdata, *cdata_start;
-
-	writer = reorderBuffer = (byte *) malloc(dsize);
-
-	*(writer++) = PIC_OP_OPX;
-	*(writer++) = PIC_OPX_SET_PALETTE;
-
-	for (i = 0;i < 256;i++) // Palette translation map
-		*(writer++) = i;
-
-	WRITE_LE_UINT16(writer, 0); // Palette stamp
-	writer += 2;
-	WRITE_LE_UINT16(writer, 0);
-	writer += 2;
-
-	view_size = READ_LE_UINT16(seeker);
-	seeker += 2;
-	view_start = READ_LE_UINT16(seeker);
-	seeker += 2;
-	cdata_size = READ_LE_UINT16(seeker);
-	seeker += 2;
-
-	memcpy(viewdata, seeker, sizeof(viewdata));
-	seeker += sizeof(viewdata);
-
-	memcpy(writer, seeker, 4 * 256); // Palette
-	seeker += 4 * 256;
-	writer += 4 * 256;
-
-	if (view_start != PAL_SIZE + 2) { // +2 for the opcode
-		memcpy(writer, seeker, view_start - PAL_SIZE - 2);
-		seeker += view_start - PAL_SIZE - 2;
-		writer += view_start - PAL_SIZE - 2;
-	}
-
-	if (dsize != view_start + EXTRA_MAGIC_SIZE + view_size) {
-		memcpy(reorderBuffer + view_size + view_start + EXTRA_MAGIC_SIZE, seeker,
-		       dsize - view_size - view_start - EXTRA_MAGIC_SIZE);
-		seeker += dsize - view_size - view_start - EXTRA_MAGIC_SIZE;
-	}
-
-	cdata_start = cdata = (byte *)malloc(cdata_size);
-	memcpy(cdata, seeker, cdata_size);
-	seeker += cdata_size;
-
-	writer = reorderBuffer + view_start;
-	*(writer++) = PIC_OP_OPX;
-	*(writer++) = PIC_OPX_EMBEDDED_VIEW;
-	*(writer++) = 0;
-	*(writer++) = 0;
-	*(writer++) = 0;
-	WRITE_LE_UINT16(writer, view_size + 8);
-	writer += 2;
-
-	memcpy(writer, viewdata, sizeof(viewdata));
-	writer += sizeof(viewdata);
-
-	*(writer++) = 0;
-
-	decode_rle(&seeker, &cdata, writer, view_size);
-
-	free(cdata_start);
-	free(inbuffer);
-
-	return reorderBuffer;
-}
-
-#define VIEW_HEADER_COLORS_8BIT 0x80
-
-static void build_cel_headers(byte **seeker, byte **writer, int celindex, int *cc_lengths, int max) {
-	int c, w;
-
-	for (c = 0;c < max;c++) {
-		w = READ_LE_UINT16(*seeker);
-		WRITE_LE_UINT16(*writer, w);
-		*seeker += 2;
-		*writer += 2;
-		w = READ_LE_UINT16(*seeker);
-		WRITE_LE_UINT16(*writer, w);
-		*seeker += 2;
-		*writer += 2;
-		w = READ_LE_UINT16(*seeker);
-		WRITE_LE_UINT16(*writer, w);
-		*seeker += 2;
-		*writer += 2;
-		w = *((*seeker)++);
-		WRITE_LE_UINT16(*writer, w); // Zero extension
-		*writer += 2;
-
-		*writer += cc_lengths[celindex];
-		celindex ++;
-	}
-}
-
-byte *view_reorder(byte *inbuffer, int dsize) {
-	byte *cellengths;
-	int loopheaders;
-	int lh_present;
-	int lh_mask;
-	int pal_offset;
-	int cel_total;
-	int unknown;
-	byte *seeker = inbuffer;
-	char celcounts[100];
-	byte *outbuffer = (byte *)malloc(dsize);
-	byte *writer = outbuffer;
-	byte *lh_ptr;
-	byte *rle_ptr, *pix_ptr;
-	int l, lb, c, celindex, lh_last = -1;
-	int chptr;
-	int w;
-	int *cc_lengths;
-	byte **cc_pos;
-
-	// Parse the main header
-	cellengths = inbuffer + READ_LE_UINT16(seeker) + 2;
-	seeker += 2;
-	loopheaders = *(seeker++);
-	lh_present = *(seeker++);
-	lh_mask = READ_LE_UINT16(seeker);
-	seeker += 2;
-	unknown = READ_LE_UINT16(seeker);
-	seeker += 2;
-	pal_offset = READ_LE_UINT16(seeker);
-	seeker += 2;
-	cel_total = READ_LE_UINT16(seeker);
-	seeker += 2;
-
-	cc_pos = (byte **)malloc(sizeof(byte *) * cel_total);
-	cc_lengths = (int *)malloc(sizeof(int) * cel_total);
-
-	for (c = 0;c < cel_total;c++)
-		cc_lengths[c] = READ_LE_UINT16(cellengths + 2 * c);
-
-	*(writer++) = loopheaders;
-	*(writer++) = VIEW_HEADER_COLORS_8BIT;
-	WRITE_LE_UINT16(writer, lh_mask);
-	writer += 2;
-	WRITE_LE_UINT16(writer, unknown);
-	writer += 2;
-	WRITE_LE_UINT16(writer, pal_offset);
-	writer += 2;
-
-	lh_ptr = writer;
-	writer += 2 * loopheaders; // Make room for the loop offset table
-
-	pix_ptr = writer;
-
-	memcpy(celcounts, seeker, lh_present);
-	seeker += lh_present;
-
-	lb = 1;
-	celindex = 0;
-
-	rle_ptr = pix_ptr = cellengths + (2 * cel_total);
-	w = 0;
-
-	for (l = 0;l < loopheaders;l++) {
-		if (lh_mask & lb) { // The loop is _not_ present
-			if (lh_last == -1) {
-				warning("While reordering view: Loop not present, but can't re-use last loop");
-				lh_last = 0;
-			}
-			WRITE_LE_UINT16(lh_ptr, lh_last);
-			lh_ptr += 2;
-		} else {
-			lh_last = writer - outbuffer;
-			WRITE_LE_UINT16(lh_ptr, lh_last);
-			lh_ptr += 2;
-			WRITE_LE_UINT16(writer, celcounts[w]);
-			writer += 2;
-			WRITE_LE_UINT16(writer, 0);
-			writer += 2;
-
-			// Now, build the cel offset table
-			chptr = (writer - outbuffer) + (2 * celcounts[w]);
-
-			for (c = 0; c < celcounts[w]; c++) {
-				WRITE_LE_UINT16(writer, chptr);
-				writer += 2;
-				cc_pos[celindex + c] = outbuffer + chptr;
-				chptr += 8 + READ_LE_UINT16(cellengths + 2 * (celindex + c));
-			}
-
-			build_cel_headers(&seeker, &writer, celindex, cc_lengths, celcounts[w]);
-
-			celindex += celcounts[w];
-			w++;
-		}
-
-		lb = lb << 1;
-	}
-
-	if (celindex < cel_total) {
-		warning("View decompression generated too few (%d / %d) headers", celindex, cel_total);
-		return NULL;
-	}
-
-	// Figure out where the pixel data begins.
-	for (c = 0;c < cel_total;c++)
-		pix_ptr += rle_size(pix_ptr, cc_lengths[c]);
-
-	rle_ptr = cellengths + (2 * cel_total);
-	for (c = 0;c < cel_total;c++)
-		decode_rle(&rle_ptr, &pix_ptr, cc_pos[c] + 8, cc_lengths[c]);
-
-	*(writer++) = 'P';
-	*(writer++) = 'A';
-	*(writer++) = 'L';
-
-	for (c = 0;c < 256;c++)
-		*(writer++) = c;
-
-	seeker -= 4; // The missing four. Don't ask why.
-	memcpy(writer, seeker, 4 * 256 + 4);
-
-	free(cc_pos);
-	free(cc_lengths);
-	free(inbuffer);
-
-	return outbuffer;
-}
-
-int decompress01(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 SCI01/%hi at %.2f%% ratio",
-	        sci_resource_types[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: // Some huffman encoding
-		if (unpackHuffman(result->data, buffer, result->size, compressedLength))
-			overflow = true;
-		break;
-
-	case 2:
-	case 3:
-	case 4:
-		if (decrypt3(result->data, buffer, result->size, compressedLength)) {
-			overflow = true;
-		} else {
-			if (compressionMethod == 3)
-				result->data = view_reorder(result->data, result->size);
-			if (compressionMethod == 4)
-				result->data = pic_reorder(result->data, result->size);
-		}
-		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;
-	}
-
-	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

Deleted: scummvm/trunk/engines/sci/scicore/decompress1.cpp
===================================================================
--- scummvm/trunk/engines/sci/scicore/decompress1.cpp	2009-03-10 20:37:54 UTC (rev 39310)
+++ scummvm/trunk/engines/sci/scicore/decompress1.cpp	2009-03-10 21:44:03 UTC (rev 39311)
@@ -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

Deleted: scummvm/trunk/engines/sci/scicore/decompress11.cpp
===================================================================
--- scummvm/trunk/engines/sci/scicore/decompress11.cpp	2009-03-10 20:37:54 UTC (rev 39310)
+++ scummvm/trunk/engines/sci/scicore/decompress11.cpp	2009-03-10 21:44:03 UTC (rev 39311)
@@ -1,146 +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/stream.h"
-
-#include "sci/sci_memory.h"
-#include "sci/scicore/resource.h"
-
-namespace Sci {
-
-int unpackDCL(uint8* dest, uint8* src, int length, int complength);
-
-int decompress11(Resource *result, Common::ReadStream &stream, int sci_version) {
-	uint16 compressedLength;
-	uint16 compressionMethod;
-	uint8 *buffer;
-	uint16 type;
-
-	result->id = stream.readByte();
-	if (stream.err())
-		return SCI_ERROR_IO_ERROR;
-
-	type = result->id & 0x7f;
-	if (type > kResourceTypeInvalid)
-		return SCI_ERROR_DECOMPRESSION_INSANE;
-
-	result->type = (ResourceType)type;
-
-	result->number = stream.readUint16LE();
-	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 > 0)
-		compressedLength -= 0;
-	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;
-	};
-
-	if (!(compressedLength & 1)) { // Align
-		stream.readByte();
-	}
-
-#ifdef _SCI_DECOMPRESS_DEBUG
-	debug("Resource %i.%s encrypted with method SCI1.1/%hi at %.2f%% ratio",
-	        result->number, getResourceTypeSuffix(result->type),
-	        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 18:
-	case 19:
-	case 20:
-		if (unpackDCL(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 3:
-	case 4: // NYI
-		warning("Resource %d.%s: Warning: compression type #%d not yet implemented",
-		        result->number, getResourceTypeSuffix(result->type), compressionMethod);
-		free(result->data);
-		result->data = NULL;
-		result->status = SCI_STATUS_NOMALLOC;
-		break;
-
-	default:
-		warning("Resource %d.%s: Compression method SCI1/%hi not  supported",
-		        result->number, getResourceTypeSuffix(result->type),
-		        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

Added: scummvm/trunk/engines/sci/scicore/decompressor.cpp
===================================================================
--- scummvm/trunk/engines/sci/scicore/decompressor.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sci/scicore/decompressor.cpp	2009-03-10 21:44:03 UTC (rev 39311)
@@ -0,0 +1,877 @@
+/* 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$
+ *
+ */
+
+// Resource library
+
+#include <common/util.h>
+#include <common/endian.h>
+#include <common/debug.h>
+#include "sci/scicore/decompressor.h"
+#include "sci/sci.h"
+
+namespace Sci {
+
+int Decompressor::unpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+			uint32 nUnpacked) {
+	init(src, dest, nPacked, nUnpacked);
+	byte buff[1024];
+	uint32 chunk;
+	while (_szPacked && !_src->ioFailed() && !_dest->ioFailed()) {
+		chunk = MIN<uint32>(1024, _szPacked);
+		_src->read(buff, chunk);
+		_dest->write(buff, chunk);
+		_szPacked -= chunk;
+	}
+	return _src->ioFailed() || _dest->ioFailed() ? 1 : 0;
+}
+
+void Decompressor::init(Common::ReadStream*src, Common::WriteStream*dest, uint32 nPacked,
+		uint32 nUnpacked) {
+	_src = src;
+	_dest = dest;
+	_szPacked = nPacked;
+	_szUnpacked = nUnpacked;
+	_nBits = 0;
+	_dwRead = _dwWrote = 0;
+	_dwBits = 0;
+}
+
+void Decompressor::fetchBits() {
+	while (_nBits <= 24) {
+		_dwBits |= ((uint32)_src->readByte()) << (24-_nBits);
+		_nBits += 8;
+		_dwRead ++;
+	}
+}
+
+bool Decompressor::getBit() {
+	// fetching more bits to _dwBits buffer
+	if (_nBits == 0) 
+		fetchBits();
+	bool b = _dwBits & 0x80000000;
+	_dwBits <<= 1;
+	_nBits--;
+	return b;
+}
+
+uint32 Decompressor::getBits(int n) {
+	// fetching more data to buffer if needed
+	if(_nBits < n)
+		fetchBits();
+	uint32 ret = _dwBits >> (32-n);
+	_dwBits <<= n;
+	_nBits -= n;
+	return ret;
+}
+
+void Decompressor::putByte(byte b) {
+	_dest->writeByte(b);
+	_dwWrote++;
+}
+//-------------------------------
+//  Huffman decompressor
+//-------------------------------
+int DecompressorHuffman::unpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+			uint32 nUnpacked) {
+	init(src, dest, nPacked, nUnpacked);
+
+	byte numnodes;
+	int16 c;
+	uint16 terminator;
+
+	numnodes = _src->readByte();
+	terminator = _src->readByte() | 0x100;
+	_nodes = (byte *)malloc(numnodes << 1);
+	_src->read(_nodes, numnodes << 1);
+
+	while ((c = getc2()) != terminator && (c >= 0) && (_szUnpacked-- > 0))
+		putByte(c);
+	
+	free(_nodes);
+	return _dwWrote ? 0 : 1;
+}
+
+int16 DecompressorHuffman::getc2() {
+	byte *node = _nodes;
+	int16 next;
+	while (node[1]) {
+		if (getBit()) {
+			next = node[1] & 0x0F; // use lower 4 bits
+			if (next == 0) 
+				return getBits(8) | 0x100;
+		} else
+			next = node[1] >> 4; // use higher 4 bits
+		node += next << 1;
+	}
+	return (int16)(*node | (node[1] << 8));
+}
+
+
+//-------------------------------
+// LZW-like Decompressor
+//-------------------------------
+void DecompressorComp3::init(Common::ReadStream*src, Common::WriteStream*dest, uint32 nPacked, uint32 nUnpacked) {
+	Decompressor::init(src, dest, nPacked, nUnpacked);
+	
+	_lastchar = _lastbits = _stakptr = 0;
+	_numbits = 9;
+	_curtoken = 0x102;
+	_endtoken = 0x1ff;
+	memset(_tokens, 0, sizeof(_tokens));
+}
+
+int DecompressorComp3::unpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+			uint32 nUnpacked) {
+	byte *buffer = NULL;
+	byte *buffer2 = NULL;
+	Common::MemoryWriteStream *pBuff = NULL;
+
+	switch (_compression) {
+	case kComp3: // Comp3 compression
+		return doUnpack(src, dest, nPacked, nUnpacked);
+		break;
+	case kComp3View:	
+	case kComp3Pic:	
+		buffer = new byte[nUnpacked];
+		buffer2 = new byte[nUnpacked];
+		pBuff = new Common::MemoryWriteStream(buffer, nUnpacked);
+		doUnpack(src, pBuff, nPacked, nUnpacked);
+		if (_compression == kComp3View)
+			view_reorder(buffer, buffer2);
+		else
+			pic_reorder(buffer, buffer2, nUnpacked);
+		dest->write(buffer2, nUnpacked);
+		delete[] buffer2;
+		delete[] buffer;
+	break;
+	}
+	return 0;
+}
+
+int DecompressorComp3::doUnpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+			uint32 nUnpacked) {
+	init(src, dest, nPacked, nUnpacked);
+
+	byte decryptstart = 0;
+	uint16 bitstring;
+	uint16 token;
+	bool bExit = false;
+
+	while (_szUnpacked && !bExit) {
+		switch (decryptstart) {
+		case 0:
+			bitstring = getBits(_numbits);
+			if (bitstring == 0x101) {// found end-of-data signal
+				bExit = true;
+				continue;
+			}
+			putByte(bitstring);
+			_szUnpacked--;
+			_lastbits = bitstring;
+			_lastchar = (bitstring & 0xff);
+			decryptstart = 1;
+			break;
+
+		case 1:
+			bitstring = getBits(_numbits);
+			if (bitstring == 0x101) { // found end-of-data signal
+				bExit = true;
+				continue;
+			}
+			if (bitstring == 0x100) { // start-over signal
+				_numbits = 9;
+				_curtoken = 0x102;
+				_endtoken = 0x1ff;
+				decryptstart = 0;
+				continue;
+			}
+
+			token = bitstring;
+			if (token >= _curtoken) { // index past current point
+				token = _lastbits;
+				_stak[_stakptr++] = _lastchar;
+			}
+			while ((token > 0xff) && (token < 0x1004)) { // follow links back in data
+				_stak[_stakptr++] = _tokens[token].data;
+				token = _tokens[token].next;
+			}
+			_lastchar = _stak[_stakptr++] = token & 0xff;
+			// put stack in buffer
+			while (_stakptr > 0) { 
+				putByte(_stak[--_stakptr]);
+				if (--_szUnpacked == 0) {
+					bExit = true;
+					continue;
+				}
+			}
+			// put token into record
+			if (_curtoken <= _endtoken) { 
+				_tokens[_curtoken].data = _lastchar;
+				_tokens[_curtoken].next = _lastbits;
+				_curtoken++;
+				if (_curtoken == _endtoken && _numbits != 12) {
+					_numbits++;
+					_endtoken = (_endtoken << 1) + 1;
+				}
+			}
+			_lastbits = bitstring;
+			break;
+		}
+	}
+	return _dwWrote ? 0 : 1;
+}
+
+enum {
+	PIC_OP_SET_COLOR = 0xf0,
+	PIC_OP_DISABLE_VISUAL = 0xf1,
+	PIC_OP_SET_PRIORITY = 0xf2,
+	PIC_OP_DISABLE_PRIORITY = 0xf3,
+	PIC_OP_SHORT_PATTERNS = 0xf4,
+	PIC_OP_MEDIUM_LINES = 0xf5,
+	PIC_OP_LONG_LINES = 0xf6,
+	PIC_OP_SHORT_LINES = 0xf7,
+	PIC_OP_FILL = 0xf8,
+	PIC_OP_SET_PATTERN = 0xf9,
+	PIC_OP_ABSOLUTE_PATTERN = 0xfa,
+	PIC_OP_SET_CONTROL = 0xfb,
+	PIC_OP_DISABLE_CONTROL = 0xfc,
+	PIC_OP_MEDIUM_PATTERNS = 0xfd,
+	PIC_OP_OPX = 0xfe,
+	PIC_OP_TERMINATE = 0xff
+};
+
+enum {
+	PIC_OPX_SET_PALETTE_ENTRIES = 0,
+	PIC_OPX_EMBEDDED_VIEW = 1,
+	PIC_OPX_SET_PALETTE = 2,
+	PIC_OPX_PRIORITY_TABLE_EQDIST = 3,
+	PIC_OPX_PRIORITY_TABLE_EXPLICIT = 4
+};
+
+#define PAL_SIZE 1284
+#define CEL_HEADER_SIZE 7
+#define EXTRA_MAGIC_SIZE 15
+
+void DecompressorComp3::decode_rle(byte **rledata, byte **pixeldata, byte *outbuffer, int size) {
+	int pos = 0;
+	char nextbyte;
+	byte *rd = *rledata;
+	byte *ob = outbuffer;
+	byte *pd = *pixeldata;
+
+	while (pos < size) {
+		nextbyte = *(rd++);
+		*(ob++) = nextbyte;
+		pos ++;
+		switch (nextbyte&0xC0) {
+		case 0x40 :
+		case 0x00 :
+			memcpy(ob, pd, nextbyte);
+			pd += nextbyte;
+			ob += nextbyte;
+			pos += nextbyte;
+			break;
+		case 0xC0 :
+			break;
+		case 0x80 :
+			nextbyte = *(pd++);
+			*(ob++) = nextbyte;
+			pos ++;
+			break;
+		}
+	}
+
+	*rledata = rd;
+	*pixeldata = pd;
+}
+
+/*
+ * Does the same this as above, only to determine the length of the compressed
+ * source data.
+ *
+ * Yes, this is inefficient.
+ */
+int DecompressorComp3::rle_size(byte *rledata, int dsize) {
+	int pos = 0;
+	char nextbyte;
+	int size = 0;
+	
+	while (pos < dsize) {
+		nextbyte = *(rledata++);
+		pos ++;
+		size ++;
+		
+		switch (nextbyte&0xC0) {
+		case 0x40 :
+		case 0x00 :
+			pos += nextbyte;
+			break;
+		case 0xC0 :
+			break;
+		case 0x80 :
+			pos ++;
+			break;
+		}
+	}
+
+	return size;
+}
+
+void DecompressorComp3::pic_reorder(byte *inbuffer, byte *outbuffer, int dsize) {
+	int view_size;
+	int view_start;
+	int cdata_size;
+	int i;
+	byte *seeker = inbuffer;
+	byte *writer;
+	char viewdata[CEL_HEADER_SIZE];
+	byte *cdata, *cdata_start;
+	
+	writer = outbuffer;
+
+	*(writer++) = PIC_OP_OPX;
+	*(writer++) = PIC_OPX_SET_PALETTE;
+
+	for (i = 0; i < 256; i++) /* Palette translation map */
+		*(writer++) = i;
+
+	WRITE_LE_UINT16(writer, 0); /* Palette stamp */
+	writer += 2;
+	WRITE_LE_UINT16(writer, 0);
+	writer += 2;
+
+	view_size = READ_LE_UINT16(seeker);
+	seeker += 2;
+	view_start = READ_LE_UINT16(seeker);
+	seeker += 2;
+	cdata_size = READ_LE_UINT16(seeker);
+	seeker += 2;
+
+	memcpy(viewdata, seeker, sizeof(viewdata));
+	seeker += sizeof(viewdata);
+	
+	memcpy(writer, seeker, 4*256); /* Palette */
+	seeker += 4*256;
+	writer += 4*256;
+
+	if (view_start != PAL_SIZE + 2) { /* +2 for the opcode */
+		memcpy(writer, seeker, view_start-PAL_SIZE-2);
+		seeker += view_start - PAL_SIZE - 2;
+		writer += view_start - PAL_SIZE - 2;
+	}
+
+	if (dsize != view_start+EXTRA_MAGIC_SIZE+view_size) {
+		memcpy(outbuffer+view_size+view_start+EXTRA_MAGIC_SIZE, seeker, 
+		       dsize-view_size-view_start-EXTRA_MAGIC_SIZE);
+		seeker += dsize-view_size-view_start-EXTRA_MAGIC_SIZE;
+	}
+
+	cdata_start = cdata = (byte *)malloc(cdata_size);
+	memcpy(cdata, seeker, cdata_size);
+	seeker += cdata_size;
+	
+	writer = outbuffer + view_start;
+	*(writer++) = PIC_OP_OPX;
+	*(writer++) = PIC_OPX_EMBEDDED_VIEW;
+	*(writer++) = 0;
+	*(writer++) = 0;
+	*(writer++) = 0;
+	WRITE_LE_UINT16(writer, view_size + 8);
+	writer += 2;
+
+	memcpy(writer, viewdata, sizeof(viewdata));
+	writer += sizeof(viewdata);
+
+	*(writer++) = 0;
+	
+	decode_rle(&seeker, &cdata, writer, view_size);
+	
+	free(cdata_start);
+}
+
+#define VIEW_HEADER_COLORS_8BIT 0x80
+
+void DecompressorComp3::build_cel_headers(byte **seeker, byte **writer, int celindex, int *cc_lengths, int max) {
+	for (int c = 0; c < max; c++) {
+		memcpy(*writer, *seeker, 6);
+		*seeker += 6; *writer += 6;
+		int w = *((*seeker)++);
+		WRITE_LE_UINT16(*writer, w); /* Zero extension */
+		*writer += 2;
+
+		*writer += cc_lengths[celindex];
+		celindex++;
+	}
+}
+
+void DecompressorComp3::view_reorder(byte *inbuffer, byte *outbuffer) {
+	byte *cellengths;
+	int loopheaders;
+	int lh_present;
+	int lh_mask;
+	int pal_offset;
+	int cel_total;
+	int unknown;
+	byte *seeker = inbuffer;
+	char celcounts[100];
+	byte *writer = outbuffer;
+	byte *lh_ptr;
+	byte *rle_ptr,*pix_ptr;
+	int l, lb, c, celindex, lh_last = -1;
+	int chptr;
+	int w;
+	int *cc_lengths;
+	byte **cc_pos;
+	
+	/* Parse the main header */
+	cellengths = inbuffer+READ_LE_UINT16(seeker)+2;
+	seeker += 2;
+	loopheaders = *(seeker++);
+	lh_present = *(seeker++);
+	lh_mask = READ_LE_UINT16(seeker);
+	seeker += 2;
+	unknown = READ_LE_UINT16(seeker);
+	seeker += 2;
+	pal_offset = READ_LE_UINT16(seeker);
+	seeker += 2;
+	cel_total = READ_LE_UINT16(seeker);
+	seeker += 2;
+
+	cc_pos = (byte **) malloc(sizeof(byte *)*cel_total);
+	cc_lengths = (int *) malloc(sizeof(int)*cel_total);
+	
+	for (c = 0; c < cel_total; c++)
+		cc_lengths[c] = READ_LE_UINT16(cellengths+2*c);
+	
+	*(writer++) = loopheaders;
+	*(writer++) = VIEW_HEADER_COLORS_8BIT;
+	WRITE_LE_UINT16(writer, lh_mask);
+	writer += 2;
+	WRITE_LE_UINT16(writer, unknown);
+	writer += 2;
+	WRITE_LE_UINT16(writer, pal_offset);
+	writer += 2;
+
+	lh_ptr = writer;
+	writer += 2*loopheaders; /* Make room for the loop offset table */
+
+	pix_ptr = writer;
+	
+	memcpy(celcounts, seeker, lh_present);
+	seeker += lh_present;
+
+	lb = 1;
+	celindex = 0;
+
+	rle_ptr = pix_ptr = cellengths + (2*cel_total);
+	w = 0;
+	
+	for (l = 0; l < loopheaders; l++) {
+		if (lh_mask & lb) { /* The loop is _not_ present */
+			if (lh_last == -1) {
+				warning("Error: While reordering view: Loop not present, but can't re-use last loop");
+				lh_last = 0;
+			}
+			WRITE_LE_UINT16(lh_ptr, lh_last);
+			lh_ptr += 2;
+		} else {
+			lh_last = writer-outbuffer;
+			WRITE_LE_UINT16(lh_ptr, lh_last);
+			lh_ptr += 2;
+			WRITE_LE_UINT16(writer, celcounts[w]);
+			writer += 2;
+			WRITE_LE_UINT16(writer, 0);
+			writer += 2;
+
+			/* Now, build the cel offset table */
+			chptr = (writer - outbuffer) + (2*celcounts[w]);
+
+			for (c = 0; c < celcounts[w]; c++) {
+				WRITE_LE_UINT16(writer, chptr);
+				writer += 2;
+				cc_pos[celindex+c] = outbuffer + chptr;
+				chptr += 8 + READ_LE_UINT16(cellengths+2*(celindex+c));
+			}
+
+			build_cel_headers(&seeker, &writer, celindex, cc_lengths, celcounts[w]);
+			
+			celindex += celcounts[w];
+			w++;
+		}
+
+		lb = lb << 1;	
+	}	
+
+	if (celindex < cel_total) {
+		warning("View decompression generated too few (%d / %d) headers", celindex, cel_total);
+		return;
+	}
+	
+	/* Figure out where the pixel data begins. */
+	for (c = 0; c < cel_total; c++)
+		pix_ptr += rle_size(pix_ptr, cc_lengths[c]);
+
+	rle_ptr = cellengths + (2*cel_total);
+	for (c = 0; c < cel_total; c++)
+		decode_rle(&rle_ptr, &pix_ptr, cc_pos[c]+8, cc_lengths[c]);
+
+	*(writer++) = 'P';
+	*(writer++) = 'A';
+	*(writer++) = 'L';
+	
+	for (c = 0; c < 256; c++)
+		*(writer++) = c;
+
+	seeker -= 4; /* The missing four. Don't ask why. */
+	memcpy(writer, seeker, 4*256+4);
+	
+	free(cc_pos);
+	free(cc_lengths);
+}
+
+//----------------------------------------------
+// LZW 9-12 bits decompressor for SCI0
+//----------------------------------------------
+int DecompressorLZW::unpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+	uint32 nUnpacked) {
+	init(src, dest, nPacked, nUnpacked);
+	byte *buffin = new byte[nPacked];
+	byte *buffout = new byte[nUnpacked];
+	src->read(buffin, nPacked);
+	
+	doUnpack(buffin, buffout, nUnpacked, nPacked);
+	
+	dest->write(buffout, nUnpacked);
+	delete[] buffin;
+	delete[] buffout;
+	return 0;
+}
+
+int DecompressorLZW::doUnpack(byte *src, byte *dest, int length, int complength) {
+	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;
+}
+
+//----------------------------------------------
+// DCL decompressor for SCI1.1
+//----------------------------------------------
+#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; }
+
+int DecompressorDCL::unpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+	uint32 nUnpacked) {
+	init(src, dest, nPacked, nUnpacked);
+	byte *buffin = new byte[nPacked];
+	byte *buffout = new byte[nUnpacked];
+	src->read(buffin, nPacked);
+	
+	unpackDCL(buffin, buffout, nUnpacked, nPacked);
+	
+	dest->write(buffout, nUnpacked);
+	delete[] buffin;
+	delete[] buffout;
+	return 0;
+}
+
+int DecompressorDCL::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 -7;
+	}
+
+	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;
+}
+
+int DecompressorDCL::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 DecompressorDCL::unpackDCL(uint8* src, uint8* dest, 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;
+}
+
+} // End of namespace Sci


Property changes on: scummvm/trunk/engines/sci/scicore/decompressor.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/engines/sci/scicore/decompressor.h
===================================================================
--- scummvm/trunk/engines/sci/scicore/decompressor.h	                        (rev 0)
+++ scummvm/trunk/engines/sci/scicore/decompressor.h	2009-03-10 21:44:03 UTC (rev 39311)
@@ -0,0 +1,179 @@
+/* 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 SCI_SCICORE_DECOMPRESSOR_H
+#define SCI_SCICORE_DECOMPRESSOR_H
+
+#include "common/file.h"
+
+namespace Sci {
+enum ResourceCompression {
+	kCompUnknown = -1,
+	kCompNone = 0,
+	kCompLZW,
+	kCompHuffman,
+	kComp3,			// LZW-like compression used in SCI01 and SCI1 
+	kComp3View,		// Comp3 + view Post-processing
+	kComp3Pic,		// Comp3 + pic Post-processing
+	kCompDCL,
+	kCompSTACpack	// ? Used in SCI32
+};
+//----------------------------------------------
+// Base class for decompressors
+// Simply copies nPacked bytes from src to dest 
+//----------------------------------------------
+class Decompressor {
+public:
+	Decompressor(){}
+	~Decompressor(){}
+
+	//! get a number of bits from _src stream
+	/** @param n - number of bits to get
+		@return (uint32) n-bits number
+	  */
+	virtual int unpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+			uint32 nUnpacked);
+
+protected:
+	//! Initialize decompressor
+	/** @param src - source stream to read from
+		@param dest - destination stream to write to
+		@param nPacked - size of packed data
+		@param nUnpacket - size of unpacked data
+		@return (int) 0 on success, non-zero on error
+	  */
+	virtual void init(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+			uint32 nUnpacked);	//! get one bit from _src stream
+	/** @return (bool) bit;
+	  */
+	virtual bool getBit();
+	//! get a number of bits from _src stream
+	/** @param n - number of bits to get
+		@return (uint32) n-bits number
+	  */
+	virtual uint32 getBits(int n);
+	//! put byte to _dest stream
+	/** @param b - byte to put
+	  */
+	virtual void putByte(byte b);
+	virtual void fetchBits();
+
+	uint32 _dwBits;
+	byte _nBits;
+
+	uint32 _szPacked;
+	uint32 _szUnpacked;
+	uint32 _dwRead;
+	uint32 _dwWrote;
+
+	Common::ReadStream *_src;
+	Common::WriteStream *_dest;
+};
+
+//----------------------------------------------
+// Huffman decompressor
+//----------------------------------------------
+class DecompressorHuffman : public Decompressor {
+public:
+	int unpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+			uint32 nUnpacked);
+
+protected:
+	int16 getc2();
+
+	byte *_nodes;
+};
+
+//----------------------------------------------
+// LZW-like decompressor for SCI01/SCI1
+// TODO: Needs clean-up of post-processing fncs
+//----------------------------------------------
+class DecompressorComp3 : public Decompressor {
+public:
+	DecompressorComp3(int nCompression) {
+		_compression = nCompression;
+	}
+	void init(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked, uint32 nUnpacked);
+	int unpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+			uint32 nUnpacked);
+
+protected:
+	// actual unpacking procedure
+	int doUnpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+			uint32 nUnpacked);
+	// functions to post-process view and pic resources 
+	void decode_rle(byte **rledata, byte **pixeldata, byte *outbuffer, int size);
+	int rle_size(byte *rledata, int dsize);
+	void pic_reorder(byte *inbuffer, byte *outbuffer, int dsize);
+	void build_cel_headers(byte **seeker, byte **writer, int celindex, int *cc_lengths, int max);
+	void view_reorder(byte *inbuffer, byte *outbuffer);
+
+	struct tokenlist {
+		byte data;
+		uint16 next;
+		} _tokens[0x1004];
+	byte _stak[0x1014];
+	byte _lastchar;
+	uint16 _stakptr;
+	uint16 _numbits, _lastbits;
+	uint16 _curtoken, _endtoken;
+	int _compression;
+};
+
+//----------------------------------------------
+// LZW 9-12 bits decompressor for SCI0
+// TODO : Needs clean-up of doUnpack()
+//----------------------------------------------
+class DecompressorLZW : public Decompressor {
+public:
+//	void init(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked, uint32 nUnpacked);
+	int unpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+			uint32 nUnpacked);
+
+protected:
+	int doUnpack(byte *src, byte *dest, int length, int complength);
+
+};
+
+//----------------------------------------------
+// DCL decompressor for SCI1.1
+// TODO : Needs clean-up of doUnpack()
+//----------------------------------------------
+class DecompressorDCL : public Decompressor {
+public:
+//	void init(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked, uint32 nUnpacked);
+	int unpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
+			uint32 nUnpacked);
+
+protected:
+	int unpackDCL(byte *src, byte *dest, int length, int complength);
+	int getbits(struct bit_read_struct *inp, int bits);
+	int huffman_lookup(struct bit_read_struct *inp, int *tree);
+
+};
+
+} // End of namespace Sci
+
+#endif // SCI_SCICORE_DECOMPRESSOR_H
\ No newline at end of file


Property changes on: scummvm/trunk/engines/sci/scicore/decompressor.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Modified: scummvm/trunk/engines/sci/scicore/resource.cpp
===================================================================
--- scummvm/trunk/engines/sci/scicore/resource.cpp	2009-03-10 20:37:54 UTC (rev 39310)
+++ scummvm/trunk/engines/sci/scicore/resource.cpp	2009-03-10 21:44:03 UTC (rev 39311)
@@ -32,6 +32,7 @@
 #include "sci/sci_memory.h"
 #include "sci/scicore/resource.h"
 #include "sci/scicore/vocabulary.h"
+#include "sci/scicore/decompressor.h"
 
 namespace Sci {
 
@@ -93,18 +94,6 @@
 typedef int decomp_funct(Resource *result, Common::ReadStream &stream, int sci_version);
 typedef void patch_sprintf_funct(char *string, Resource *res);
 
-static decomp_funct *decompressors[] = {
-	NULL,
-	&decompress0,
-	&decompress01,
-	&decompress01,
-	&decompress01,
-	&decompress1,
-	&decompress1,
-	&decompress11,
-	NULL
-};
-
 //-- Resource main functions --
 Resource::Resource() {
 	data = NULL;
@@ -113,7 +102,7 @@
 	id = 0;
 	size = 0;
 	file_offset = 0;
-	status = SCI_STATUS_NOMALLOC;
+	status = kResStatusNoMalloc;
 	lockers = 0;
 	source = NULL;
 }
@@ -127,7 +116,7 @@
 void Resource::unalloc() {
 	delete[] data;
 	data = NULL;
-	status = SCI_STATUS_NOMALLOC;
+	status = kResStatusNoMalloc;
 }
 
 //-- Resmgr helper functions --
@@ -213,7 +202,7 @@
 	if (really_read != res->size) {
 		error("Read %d bytes from %s but expected %d!", really_read, filename, res->size);
 	}
-	res->status = SCI_STATUS_ALLOCATED;
+	res->status = kResStatusAllocated;
 	return true;
 }
 
@@ -233,17 +222,13 @@
 	}
 	file.seek(res->file_offset, SEEK_SET);
 
-	// Check whether we support this at all
-	if (decompressors[_sciVersion] == NULL)
-		error("Resource manager's SCI version (%d) is invalid", _sciVersion);
-	// Decompress from regular resource file
-	int error = decompressors[_sciVersion](res, file, _sciVersion);
-
+	int error = decompress(res, &file);
 	if (error) {
 		warning("Error %d occured while reading %s.%03d from resource file: %s\n",
 			error, getResourceTypeName(res->type), res->number, sci_error_types[error]);
 		res->unalloc();
 	}
+
 }
 
 Resource *ResourceManager::testResource(ResourceType type, int number) {
@@ -252,8 +237,19 @@
 	return NULL;
 }
 
-int sci0_get_compression_method(Common::ReadStream &stream);
+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 sci_test_view_type(ResourceManager *mgr) {
 	Common::File file;
 	char filename[MAXPATHLEN];
@@ -421,7 +417,7 @@
 			_sciVersion = version = SCI_VERSION_1_EARLY;
 			loadResource(res);
 
-			if (res->status == SCI_STATUS_NOMALLOC)
+			if (res->status == kResStatusNoMalloc)
 				version = SCI_VERSION_1_LATE;
 			break;
 		}
@@ -469,17 +465,17 @@
 }
 
 void ResourceManager::removeFromLRU(Resource *res) {
-	if (res->status != SCI_STATUS_ENQUEUED) {
+	if (res->status != kResStatusEnqueued) {
 		sciprintf("Resmgr: Oops: trying to remove resource that isn't enqueued\n");
 		return;
 	}
 	_LRU.remove(res);
 	_memoryLRU -= res->size;
-	res->status = SCI_STATUS_ALLOCATED;
+	res->status = kResStatusAllocated;
 }
 
 void ResourceManager::addToLRU(Resource *res) {
-	if (res->status != SCI_STATUS_ALLOCATED) {
+	if (res->status != kResStatusAllocated) {
 		warning("Resmgr: Oops: trying to enqueue resource with state %d", res->status);
 		return;
 	}
@@ -491,7 +487,7 @@
 	        mgr->_memoryLRU);
 
 #endif
-	res->status = SCI_STATUS_ENQUEUED;
+	res->status = kResStatusEnqueued;
 }
 
 void ResourceManager::printLRU() {
@@ -547,26 +543,26 @@
 	if (!retval->status)
 		loadResource(retval);
 
-	else if (retval->status == SCI_STATUS_ENQUEUED)
+	else if (retval->status == kResStatusEnqueued)
 		removeFromLRU(retval);
 	// Unless an error occured, the resource is now either
 	// locked or allocated, but never queued or freed.
 
 	if (lock) {
-		if (retval->status == SCI_STATUS_ALLOCATED) {
-			retval->status = SCI_STATUS_LOCKED;
+		if (retval->status == kResStatusAllocated) {
+			retval->status = kResStatusLocked;
 			retval->lockers = 0;
 			_memoryLocked += retval->size;
 		}
 
 		++retval->lockers;
 
-	} else if (retval->status != SCI_STATUS_LOCKED) { // Don't lock it
-		if (retval->status == SCI_STATUS_ALLOCATED)
+	} else if (retval->status != kResStatusLocked) { // Don't lock it
+		if (retval->status == kResStatusAllocated)
 			addToLRU(retval);
 	}
 
-	freeOldResources(retval->status == SCI_STATUS_ALLOCATED);
+	freeOldResources(retval->status == kResStatusAllocated);
 
 	if (retval->data)
 		return retval;
@@ -585,14 +581,14 @@
 		return;
 	}
 
-	if (res->status != SCI_STATUS_LOCKED) {
+	if (res->status != kResStatusLocked) {
 		sciprintf("Resmgr: Warning: Attempt to unlock unlocked resource %s.%03d\n",
 		          getResourceTypeName(res->type), res->number);
 		return;
 	}
 
 	if (!--res->lockers) { // No more lockers?
-		res->status = SCI_STATUS_ALLOCATED;
+		res->status = kResStatusAllocated;
 		_memoryLocked -= res->size;
 		addToLRU(res);
 	}
@@ -677,8 +673,8 @@
 	}
 	// SCI0 volume format:  {wResId wPacked+4 wUnpacked wCompression} = 8 bytes
 	// SCI1 volume format:  {bResType wResNumber wPacked+4 wUnpacked wCompression} = 9 bytes
-	// SCI1.1 volume format:  {bResType wResNumber wPacked+4 wUnpacked wCompression} = 9 bytes
-	// SCI32 volume format :  {bResType wResNumber dwPacked+4 dwUnpacked wCompression} = 13 bytes
+	// SCI1.1 volume format:  {bResType wResNumber wPacked wUnpacked wCompression} = 9 bytes
+	// SCI32 volume format :  {bResType wResNumber dwPacked dwUnpacked wCompression} = 13 bytes
 	// Try to parse volume with SCI0 scheme to see if it make sense
 	// Checking 1MB of data should be enough to determine the version
 	uint16 resId, wCompression;
@@ -814,7 +810,7 @@
 	// Overwrite everything, because we're patching
 	newrsc->id = resId;
 	newrsc->number = resnumber;
-	newrsc->status = SCI_STATUS_NOMALLOC;
+	newrsc->status = kResStatusNoMalloc;
 	newrsc->type = restype;
 	newrsc->source = source;
 	newrsc->size = fsize - patch_data_offset - 2;
@@ -899,7 +895,7 @@
 		// adding a new resource
 		if (_resMap.contains(resId) == false) {
 			res = new Resource;
-			res->id = id;
+			res->id = resId;//id;
 			res->file_offset = offset & (((~bMask) << 24) | 0xFFFFFF);
 			res->number = number;
 			res->type = type;
@@ -953,7 +949,7 @@
 				_resMap.setVal(resId, res);
 				res->type = (ResourceType)type;
 				res->number = number;
-				res->id = res->number | (res->type << 16);
+				res->id = resId;//res->number | (res->type << 16);
 				res->source = _mapVersion < SCI_VERSION_1_1 ? getVolume(map, off  >> 28) : vol;
 				if (_mapVersion < SCI_VERSION_32)
 					res->file_offset = _mapVersion < SCI_VERSION_1_1 ? off & 0x0FFFFFFF : off << 1;
@@ -965,4 +961,149 @@
 	return 0;
 }
 
+int ResourceManager::readResourceInfo(Resource *res, Common::File *file, 
+		uint32&szPacked, ResourceCompression &compression) {
+	// SCI0 volume format:  {wResId wPacked+4 wUnpacked wCompression} = 8 bytes
+	// SCI1 volume format:  {bResType wResNumber wPacked+4 wUnpacked wCompression} = 9 bytes
+	// SCI1.1 volume format:  {bResType wResNumber wPacked wUnpacked wCompression} = 9 bytes
+	// SCI32 volume format :  {bResType wResNumber dwPacked dwUnpacked wCompression} = 13 bytes
+	uint16 w, number, szUnpacked;
+	uint32 wCompression;
+	ResourceType type;
+
+	switch (_volVersion) {
+	case SCI_VERSION_0:
+		w = file->readUint16LE();
+		type = (ResourceType)(w >> 11);
+		number = w & 0x7FF;
+		szPacked = file->readUint16LE() - 4;
+		szUnpacked = file->readUint16LE();
+		wCompression = file->readUint16LE();
+		break;
+	case SCI_VERSION_1:
+		type = (ResourceType)file->readByte();
+		number = file->readUint16LE();
+		szPacked = file->readUint16LE() - 4;
+		szUnpacked = file->readUint16LE();
+		wCompression = file->readUint16LE();
+		break;
+	case SCI_VERSION_1_1:
+		type = (ResourceType)file->readByte();
+		number = file->readUint16LE();
+		szPacked = file->readUint16LE();
+		szUnpacked = file->readUint16LE();
+		wCompression = file->readUint16LE();
+		break;
+	case SCI_VERSION_32:
+		type = (ResourceType)file->readByte();
+		number = file->readUint16LE();
+		szPacked = file->readUint32LE();
+		szUnpacked = file->readUint32LE();
+		wCompression = file->readUint16LE();
+		break;
+	default:
+		return SCI_ERROR_INVALID_RESMAP_ENTRY;
+	}
+	// check if there were errors while reading
+	if (file->ioFailed())
+		return SCI_ERROR_IO_ERROR;
+	res->id = RESOURCE_HASH(type, number);
+	res->type = type;
+	res->number = number;
+	res->size = szUnpacked;
+	// checking compression method
+	if (wCompression == 0)
+		compression = kCompNone;
+	switch (_sciVersion) {
+		case SCI_VERSION_0:
+			if (wCompression == 1)
+				compression = kCompLZW;
+			else if (wCompression == 2)
+				compression = kCompHuffman;
+			break;
+		case SCI_VERSION_01:
+		case SCI_VERSION_01_VGA:
+		case SCI_VERSION_01_VGA_ODD:
+		case SCI_VERSION_1_EARLY:
+		case SCI_VERSION_1_LATE:
+			if (wCompression == 1)
+				compression = kCompHuffman;
+			else if (wCompression == 2)
+				compression = kComp3;
+			else if (wCompression == 3)
+				compression = kComp3View;
+			else if (wCompression == 4)
+				compression = kComp3Pic;
+			break;
+		case SCI_VERSION_1_1:
+			if (wCompression >= 18 && wCompression <= 20)
+				compression = kCompDCL;
+			break;
+		case SCI_VERSION_32:
+			if (wCompression == 32)
+				compression = kCompSTACpack;
+			break;
+		default:
+			compression = kCompUnknown;
+	}
+
+	return compression == kCompUnknown ? SCI_ERROR_UNKNOWN_COMPRESSION : 0;
+}
+
+int ResourceManager::decompress(Resource *res, Common::File *file) {
+	int error;
+	uint32 szPacked = 0;
+	Common::MemoryWriteStream *pDest = NULL;
+	ResourceCompression compression = kCompUnknown;
+
+	// fill resource info
+	error = readResourceInfo(res, file, szPacked, compression);
+	if (error)
+		return error;
+	// getting a decompressor
+	Decompressor *dec = NULL;
+	switch (compression) {
+	case kCompNone:
+		dec = new Decompressor;
+		break;
+	case kCompLZW:
+		dec = new DecompressorLZW;
+		break;
+	case kCompHuffman:
+		dec = new DecompressorHuffman;
+		break;
+	case kComp3:
+	case kComp3View:
+	case kComp3Pic:
+		dec = new DecompressorComp3(compression);
+		break;
+	case kCompDCL:
+		dec = new DecompressorDCL;
+		break;
+	default:
+		warning("Resource %s #%d: Compression method %d not supported",
+		        getResourceTypeName(res->type), res->number, compression);
+		break;
+	}
+	
+	if (dec) {
+		res->data = new byte[res->size];
+		pDest = new Common::MemoryWriteStream(res->data , res->size);
+		error = dec->unpack(file, pDest, szPacked, res->size);
+	} else 
+		error = SCI_ERROR_UNKNOWN_COMPRESSION;
+	
+	if (!error)
+		res->status = kResStatusAllocated;
+	else {
+		delete res->data;
+		res->data = 0;
+		res->status = kResStatusNoMalloc;
+	}
+	delete dec;
+	delete pDest;
+
+	return error;
+}
+
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/scicore/resource.h
===================================================================
--- scummvm/trunk/engines/sci/scicore/resource.h	2009-03-10 20:37:54 UTC (rev 39310)
+++ scummvm/trunk/engines/sci/scicore/resource.h	2009-03-10 21:44:03 UTC (rev 39311)
@@ -30,6 +30,8 @@
 #include "common/file.h"
 #include "common/archive.h"
 
+#include "sci/scicore/decompressor.h"
+
 namespace Common {
 	class ReadStream;
 }
@@ -40,10 +42,12 @@
 #define SCI_MAX_RESOURCE_SIZE 0x0400000
 
 /*** RESOURCE STATUS TYPES ***/
-#define SCI_STATUS_NOMALLOC 0
-#define SCI_STATUS_ALLOCATED 1
-#define SCI_STATUS_ENQUEUED 2 /* In the LRU queue */
-#define SCI_STATUS_LOCKED 3 /* Allocated and in use */
+enum ResourceStatus {
+	kResStatusNoMalloc=0,
+	kResStatusAllocated,
+	kResStatusEnqueued, /* In the LRU queue */
+	kResStatusLocked /* Allocated and in use */
+};
 
 /*** INITIALIZATION RESULT TYPES ***/
 #define SCI_ERROR_IO_ERROR 1
@@ -163,12 +167,12 @@
 	byte *data;
 	uint16 number;
 	ResourceType type;
-	uint16 id;	// contains number and type. 
+	uint32 id;	// contains number and type. 
 				// TODO: maybe use uint32 and set id = RESOURCE_HASH()
 				// for all SCI versions
 	unsigned int size;
 	unsigned int file_offset; /* Offset in file */
-	byte status;
+	ResourceStatus status;
 	unsigned short lockers; /* Number of places where this resource was locked */
 	ResourceSource *source;
 };
@@ -267,6 +271,8 @@
 	void loadResource(Resource *res);
 	bool loadFromPatchFile(Resource *res);
 	void freeOldResources(int last_invulnerable);
+	int decompress(Resource *res, Common::File *file);
+	int readResourceInfo(Resource *res, Common::File *file, uint32&szPacked, ResourceCompression &compression);
 
 	/**--- Resource map decoding functions ---*/
 	int detectMapVersion();
@@ -295,57 +301,6 @@
 	void removeFromLRU(Resource *res);
 };
 
-	/**--- Decompression functions ---**/
-	int decompress0(Resource *result, Common::ReadStream &stream, int sci_version);
-	/* Decrypts resource data and stores the result for SCI0-style compression.
-	** Parameters : result: The Resource the decompressed data is stored in.
-	**              stream: Stream of the resource file
-	**              sci_version : Actual SCI resource version
-	** Returns    : (int) 0 on success, one of SCI_ERROR_* if a problem was
-	**               encountered.
-	*/
-
-	int decompress01(Resource *result, Common::ReadStream &stream, int sci_version);
-	/* Decrypts resource data and stores the result for SCI01-style compression.
-	** Parameters : result: The Resource the decompressed data is stored in.
-	**              stream: Stream of the resource file
-	**              sci_version : Actual SCI resource version
-	** Returns    : (int) 0 on success, one of SCI_ERROR_* if a problem was
-	**               encountered.
-	*/
-
-	int decompress1(Resource *result, Common::ReadStream &stream, int sci_version);
-	/* Decrypts resource data and stores the result for SCI1.1-style compression.
-	** Parameters : result: The Resource the decompressed data is stored in.
-	**              sci_version : Actual SCI resource version
-	**              stream: Stream of the resource file
-	** Returns    : (int) 0 on success, one of SCI_ERROR_* if a problem was
-	**               encountered.
-	*/
-
-	int decompress11(Resource *result, Common::ReadStream &stream, int sci_version);
-	/* Decrypts resource data and stores the result for SCI1.1-style compression.
-	** Parameters : result: The Resource the decompressed data is stored in.
-	**              sci_version : Actual SCI resource version
-	**              stream: Stream of the resource file
-	** Returns    : (int) 0 on success, one of SCI_ERROR_* if a problem was
-	**               encountered.
-	*/
-
-	int unpackHuffman(uint8* dest, uint8* src, int length, int complength);
-	/* Huffman token decryptor - defined in decompress0.c and used in decompress01.c
-	*/
-
-	int unpackDCL(uint8* dest, uint8* src, int length, int complength);
-	/* DCL inflate- implemented in decompress1.c
-	*/
-
-	byte *view_reorder(byte *inbuffer, int dsize);
-	/* SCI1 style view compression */
-
-	byte *pic_reorder(byte *inbuffer, int dsize);
-	/* SCI1 style pic compression */
-
 } // End of namespace Sci
 
 #endif // SCI_SCICORE_RESOURCE_H


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list