mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-16 06:39:17 +00:00
87e7f85410
svn-id: r38411
636 lines
16 KiB
C++
636 lines
16 KiB
C++
/* 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 "sci/include/sci_memory.h"
|
|
#include "sci/include/sciresource.h"
|
|
|
|
/***************************************************************************
|
|
* 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 {
|
|
guint8 data;
|
|
gint16 next;
|
|
} tokens[0x1004];
|
|
|
|
static gint8 stak[0x1014] = {0};
|
|
static gint8 lastchar = 0;
|
|
static gint16 stakptr = 0;
|
|
static guint16 numbits, s_bitstring, lastbits, decryptstart;
|
|
static gint16 curtoken, endtoken;
|
|
|
|
|
|
guint32 gbits(int numbits, guint8 * data, int dlen);
|
|
|
|
void decryptinit3(void) {
|
|
int i;
|
|
lastchar = lastbits = s_bitstring = stakptr = 0;
|
|
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;
|
|
}
|
|
}
|
|
|
|
int decrypt3(guint8 *dest, guint8 *src, int length, int complength) {
|
|
static gint16 token;
|
|
while (length != 0) {
|
|
|
|
switch (decryptstart) {
|
|
case 0:
|
|
case 1:
|
|
s_bitstring = gbits(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 */
|
|
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 && numbits != 12) {
|
|
numbits++;
|
|
endtoken <<= 1;
|
|
endtoken++;
|
|
}
|
|
}
|
|
lastbits = s_bitstring;
|
|
continue; /* When are "break" and "continue" synonymous? */
|
|
case 4:
|
|
return 0;
|
|
}
|
|
}
|
|
return 0; /* [DJ] shut up compiler warning */
|
|
}
|
|
|
|
guint32 gbits(int numbits, guint8 * data, int dlen) {
|
|
int place; /* indicates location within byte */
|
|
guint32 bitstring;
|
|
static guint32 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;
|
|
|
|
putInt16(writer, 0); /* Palette stamp */
|
|
writer += 2;
|
|
putInt16(writer, 0);
|
|
writer += 2;
|
|
|
|
view_size = getUInt16(seeker);
|
|
seeker += 2;
|
|
view_start = getUInt16(seeker);
|
|
seeker += 2;
|
|
cdata_size = getUInt16(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;
|
|
putInt16(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 = getUInt16(*seeker);
|
|
putInt16(*writer, w);
|
|
*seeker += 2;
|
|
*writer += 2;
|
|
w = getUInt16(*seeker);
|
|
putInt16(*writer, w);
|
|
*seeker += 2;
|
|
*writer += 2;
|
|
w = getUInt16(*seeker);
|
|
putInt16(*writer, w);
|
|
*seeker += 2;
|
|
*writer += 2;
|
|
w = *((*seeker)++);
|
|
putInt16(*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 + getUInt16(seeker) + 2;
|
|
seeker += 2;
|
|
loopheaders = *(seeker++);
|
|
lh_present = *(seeker++);
|
|
lh_mask = getUInt16(seeker);
|
|
seeker += 2;
|
|
unknown = getUInt16(seeker);
|
|
seeker += 2;
|
|
pal_offset = getUInt16(seeker);
|
|
seeker += 2;
|
|
cel_total = getUInt16(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] = getUInt16(cellengths + 2 * c);
|
|
|
|
*(writer++) = loopheaders;
|
|
*(writer++) = VIEW_HEADER_COLORS_8BIT;
|
|
putInt16(writer, lh_mask);
|
|
writer += 2;
|
|
putInt16(writer, unknown);
|
|
writer += 2;
|
|
putInt16(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) {
|
|
fprintf(stderr, "Error: While reordering view: Loop not present, but can't re-use last loop!\n");
|
|
lh_last = 0;
|
|
}
|
|
putInt16(lh_ptr, lh_last);
|
|
lh_ptr += 2;
|
|
} else {
|
|
lh_last = writer - outbuffer;
|
|
putInt16(lh_ptr, lh_last);
|
|
lh_ptr += 2;
|
|
putInt16(writer, celcounts[w]);
|
|
writer += 2;
|
|
putInt16(writer, 0);
|
|
writer += 2;
|
|
|
|
/* Now, build the cel offset table */
|
|
chptr = (writer - outbuffer) + (2 * celcounts[w]);
|
|
|
|
for (c = 0;c < celcounts[w];c++) {
|
|
putInt16(writer, chptr);
|
|
writer += 2;
|
|
cc_pos[celindex+c] = outbuffer + chptr;
|
|
chptr += 8 + getUInt16(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) {
|
|
fprintf(stderr, "View decompression generated too few (%d / %d) headers!\n", 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_t *result, int resh, int sci_version) {
|
|
guint16 compressedLength, result_size;
|
|
guint16 compressionMethod;
|
|
guint8 *buffer;
|
|
|
|
if (read(resh, &(result->id), 2) != 2)
|
|
return SCI_ERROR_IO_ERROR;
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
result->id = GUINT16_SWAP_LE_BE_CONSTANT(result->id);
|
|
#endif
|
|
|
|
result->number = result->id & 0x07ff;
|
|
result->type = result->id >> 11;
|
|
|
|
if ((result->number > sci_max_resource_nr[sci_version] || (result->type > sci_invalid_resource)))
|
|
return SCI_ERROR_DECOMPRESSION_INSANE;
|
|
|
|
if ((read(resh, &compressedLength, 2) != 2) ||
|
|
(read(resh, &result_size, 2) != 2) ||
|
|
(read(resh, &compressionMethod, 2) != 2))
|
|
return SCI_ERROR_IO_ERROR;
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
compressedLength = GUINT16_SWAP_LE_BE_CONSTANT(compressedLength);
|
|
result_size = GUINT16_SWAP_LE_BE_CONSTANT(result_size);
|
|
compressionMethod = GUINT16_SWAP_LE_BE_CONSTANT(compressionMethod);
|
|
#endif
|
|
result->size = result_size;
|
|
|
|
/* if ((result->size < 0) || (compressedLength < 0))
|
|
return SCI_ERROR_DECOMPRESSION_INSANE; */
|
|
/* This return will never happen in SCI0 or SCI1 (does it have any use?) */
|
|
|
|
if ((result->size > SCI_MAX_RESOURCE_SIZE) ||
|
|
(compressedLength > 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 = (guint8*)sci_malloc(compressedLength);
|
|
result->data = (unsigned char*)sci_malloc(result->size);
|
|
|
|
if (read(resh, buffer, compressedLength) != compressedLength) {
|
|
free(result->data);
|
|
free(buffer);
|
|
return SCI_ERROR_IO_ERROR;
|
|
};
|
|
|
|
|
|
#ifdef _SCI_DECOMPRESS_DEBUG
|
|
fprintf(stderr, "Resource %s.%03hi encrypted with method SCI01/%hi at %.2f%%"
|
|
" ratio\n",
|
|
sci_resource_types[result->type], result->number, compressionMethod,
|
|
(result->size == 0) ? -1.0 :
|
|
(100.0 * compressedLength / result->size));
|
|
fprintf(stderr, " compressedLength = 0x%hx, actualLength=0x%hx\n",
|
|
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: /* Some huffman encoding */
|
|
if (decrypt2(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: /* ??? */
|
|
decryptinit3();
|
|
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;
|
|
}
|
|
result->status = SCI_STATUS_ALLOCATED;
|
|
break;
|
|
|
|
case 3:
|
|
decryptinit3();
|
|
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;
|
|
}
|
|
result->data = view_reorder(result->data, result->size);
|
|
result->status = SCI_STATUS_ALLOCATED;
|
|
break;
|
|
|
|
case 4:
|
|
decryptinit3();
|
|
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;
|
|
}
|
|
result->data = pic_reorder(result->data, result->size);
|
|
result->status = SCI_STATUS_ALLOCATED;
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr, "Resource %s.%03hi: Compression method SCI1/%hi not "
|
|
"supported!\n", sci_resource_types[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;
|
|
}
|
|
|