[Scummvm-git-logs] scummvm master -> 79febe2586114757c7a960a4ab5e0692a10d746e

bluegr noreply at scummvm.org
Wed Jul 15 14:38:33 UTC 2026


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
4050c4bfee SCI: Cleanup LZW view/pic decompressors
79febe2586 SCI: Cleanup decompressor code


Commit: 4050c4bfeeddeb589b9eb04ab2995a4162c14596
    https://github.com/scummvm/scummvm/commit/4050c4bfeeddeb589b9eb04ab2995a4162c14596
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2026-07-15T17:38:28+03:00

Commit Message:
SCI: Cleanup LZW view/pic decompressors

Changed paths:
    engines/sci/graphics/view.cpp
    engines/sci/resource/decompressor.cpp
    engines/sci/resource/decompressor.h


diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp
index 3bc1bc7cbe4..f6a66fa4fa1 100644
--- a/engines/sci/graphics/view.cpp
+++ b/engines/sci/graphics/view.cpp
@@ -134,7 +134,7 @@ void GfxView::initData() {
 	case kViewAmiga: // Amiga ECS (32 colors)
 	case kViewAmiga64: // Amiga AGA (64 colors)
 	case kViewVga: { // View-format SCI1
-		// LoopCount:WORD MirrorMask:WORD Version:WORD PaletteOffset:WORD LoopOffset0:WORD LoopOffset1:WORD...
+		// LoopCount:BYTE Flags:BYTE MirrorMask:WORD Version:WORD PaletteOffset:WORD LoopOffset0:WORD LoopOffset1:WORD...
 
 		_loop.resize(_resource->getUint8At(0));
 		// bit 0x8000 of _resourceData[1] means palette is set
diff --git a/engines/sci/resource/decompressor.cpp b/engines/sci/resource/decompressor.cpp
index f94a2537c39..45430285f87 100644
--- a/engines/sci/resource/decompressor.cpp
+++ b/engines/sci/resource/decompressor.cpp
@@ -143,6 +143,7 @@ int16 DecompressorHuffman::getc2() {
 
 int DecompressorLZW::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) {
 	byte *buffer = nullptr;
+	int result = SCI_ERROR_NONE;
 
 	switch (_compression) {
 	case kCompLZW:	// SCI0 LZW compression
@@ -150,19 +151,23 @@ int DecompressorLZW::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked,
 		return unpackLZW(src, dest, nPacked, nUnpacked);
 	case kCompLZW1View:
 		buffer = new byte[nUnpacked];
-		unpackLZW(src, buffer, nPacked, nUnpacked);
-		reorderView(buffer, dest);
+		result = unpackLZW(src, buffer, nPacked, nUnpacked);
+		if (result == SCI_ERROR_NONE) {
+			unpackView(buffer, dest);
+		}
 		break;
 	case kCompLZW1Pic:
 		buffer = new byte[nUnpacked];
-		unpackLZW(src, buffer, nPacked, nUnpacked);
-		reorderPic(buffer, dest, nUnpacked);
+		result = unpackLZW(src, buffer, nPacked, nUnpacked);
+		if (result == SCI_ERROR_NONE) {
+			unpackPic(buffer, dest, nUnpacked);
+		}
 		break;
 	default:
 		break;
 	}
 	delete[] buffer;
-	return 0;
+	return result;
 }
 
 // Decompresses SCI0 LZW and SCI01/1 LZW, depending on _compression value.
@@ -181,6 +186,7 @@ int DecompressorLZW::unpackLZW(Common::ReadStream *src, byte *dest, uint32 nPack
 	uint16 *stringOffsets = new uint16[4096]; // 0-257: unused
 	uint16 *stringLengths = new uint16[4096]; // 0-257: unused
 
+	bool terminatorFound = false;
 	while (!isFinished()) {
 		uint16 code = (_compression == kCompLZW) ?
 		              getBitsLSB(codeBitLength) :
@@ -192,6 +198,7 @@ int DecompressorLZW::unpackLZW(Common::ReadStream *src, byte *dest, uint32 nPack
 		}
 
 		if (code == 257) { // terminator
+			terminatorFound = true;
 			break;
 		}
 
@@ -240,290 +247,251 @@ int DecompressorLZW::unpackLZW(Common::ReadStream *src, byte *dest, uint32 nPack
 	delete[] stringOffsets;
 	delete[] stringLengths;
 
-	return _dwWrote == _szUnpacked ? 0 : SCI_ERROR_DECOMPRESSION_ERROR;
-}
-
-#define PAL_SIZE 1284
-#define EXTRA_MAGIC_SIZE 15
-#define VIEW_HEADER_COLORS_8BIT 0x80
-
-void DecompressorLZW::decodeRLE(byte **rledata, byte **pixeldata, byte *outbuffer, int size) {
-	int pos = 0;
-	byte 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:
-		default:
-			break;
-		case 0x80:
-			nextbyte = *pd++;
-			*ob++ = nextbyte;
-			pos++;
-			break;
-		}
-	}
-
-	*rledata = rd;
-	*pixeldata = pd;
+	// Reaching the compression terminator before writing _szUnpacked bytes is
+	// expected. For kCompLZW1View and kCompLZW1Pic, the unpacked size is not
+	// the LZW output size, it is the final size after processing LZW output.
+	return (terminatorFound || (_dwWrote == _szUnpacked)) ?
+		SCI_ERROR_NONE:
+		SCI_ERROR_DECOMPRESSION_ERROR;
 }
 
-/**
- * Does the same this as decodeRLE, only to determine the length of the
- * compressed source data.
- */
-int DecompressorLZW::getRLEsize(byte *rledata, int dsize) {
-	int pos = 0;
-	int size = 0;
-
-	while (pos < dsize) {
-		byte nextbyte = *(rledata++);
-		pos++;
-		size++;
-
-		switch (nextbyte & 0xC0) {
-		case 0x40:
-		case 0x00:
-			pos += nextbyte;
-			break;
-		case 0xC0:
-		default:
-			break;
-		case 0x80:
-			pos++;
-			break;
-		}
-	}
-
-	return size;
-}
-
-enum {
-	PIC_OPX_EMBEDDED_VIEW = 1,
-	PIC_OPX_SET_PALETTE = 2,
-	PIC_OP_OPX = 0xfe
-};
-
-void DecompressorLZW::reorderPic(byte *src, byte *dest, int dsize) {
-	uint16 view_size, view_start, cdata_size;
-	int i;
+void DecompressorLZW::unpackView(byte *src, byte *dest) {
 	byte *seeker = src;
 	byte *writer = dest;
-	char viewdata[7];
-	byte *cdata, *cdata_start;
 
-	*writer++ = PIC_OP_OPX;
-	*writer++ = PIC_OPX_SET_PALETTE;
-
-	for (i = 0; i < 256; i++) /* Palette translation map */
-		*writer++ = i;
-
-	WRITE_LE_UINT32(writer, 0); /* Palette stamp */
-	writer += 4;
-
-	view_size = READ_LE_UINT16(seeker);
+	// read compressed header
+	byte *celLengths = src + READ_LE_UINT16(seeker) + 2;
 	seeker += 2;
-	view_start = READ_LE_UINT16(seeker);
+	byte loopCount = *seeker++;
+	byte loopHeaderCount = *seeker++; // non-mirrored loops
+	uint16 mirrorMask = READ_LE_UINT16(seeker);
 	seeker += 2;
-	cdata_size = READ_LE_UINT16(seeker);
+	uint16 version = READ_LE_UINT16(seeker);
+	seeker += 2;
+	uint16 paletteOffset = READ_LE_UINT16(seeker); // offset in output view
+	seeker += 2;
+	int celHeaderCount = READ_LE_UINT16(seeker); // non-mirrored loops
 	seeker += 2;
 
-	memcpy(viewdata, seeker, sizeof(viewdata));
-	seeker += sizeof(viewdata);
-
-	memcpy(writer, seeker, 4*256); /* Palette */
-	seeker += 4*256;
-	writer += 4*256;
+	// read cel counts for each loop header
+	byte *celCounts = seeker;
+	seeker += loopHeaderCount;
 
-	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;
+	// read lengths of decoded cels
+	uint16 *celDecodedLengths = new uint16[celHeaderCount];
+	for (int i = 0; i < celHeaderCount; i++) {
+		celDecodedLengths[i] = READ_LE_UINT16(celLengths + (2 * i));
 	}
 
-	if (dsize != view_start + EXTRA_MAGIC_SIZE + view_size) {
-		memcpy(dest + 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;
+	// locate pixel data by seeking past each cel's RLE data
+	byte *rleData = celLengths + (2 * celHeaderCount);
+	byte *pixelData = rleData;
+	for (int i = 0; i < celHeaderCount; i++) {
+		skipRLE(&pixelData, celDecodedLengths[i]);
 	}
 
-	cdata_start = cdata = (byte *)malloc(cdata_size);
-	memcpy(cdata, seeker, cdata_size);
-	seeker += cdata_size;
-
-	writer = dest + view_start;
-	*writer++ = PIC_OP_OPX;
-	*writer++ = PIC_OPX_EMBEDDED_VIEW;
-	*writer++ = 0;
-	*writer++ = 0;
-	*writer++ = 0;
-	WRITE_LE_UINT16(writer, view_size + 8);
+	// write view header
+	*writer++ = loopCount;
+	*writer++ = 0x80; // flags for a VGA pic with RLE compression
+	WRITE_LE_UINT16(writer, mirrorMask);
+	writer += 2;
+	WRITE_LE_UINT16(writer, version);
+	writer += 2;
+	WRITE_LE_UINT16(writer, paletteOffset);
 	writer += 2;
 
-	memcpy(writer, viewdata, sizeof(viewdata));
-	writer += sizeof(viewdata);
+	// skip loop offset table, we will write it while writing loops
+	byte *loopOffsets = writer;
+	writer += 2 * loopCount;
+
+	// write loops and their cels
+	int loopTableIndex = 0;
+	int celTableIndex = 0;
+	for (int loop = 0; loop < loopCount; loop++) {
+		if (mirrorMask & (1 << loop)) {
+			// mirrored loop: write previous loop offset to table
+			memcpy(loopOffsets, loopOffsets - 2, 2);
+		} else {
+			// write loop offset to table
+			WRITE_LE_UINT16(loopOffsets, writer - dest);
+
+			// write loop header
+			byte celCount = celCounts[loopTableIndex];
+			*writer++ = celCount;
+			memset(writer, 0, 3);
+			writer += 3;
+
+			// write cel offset table
+			int celOffset = (writer - dest) + (2 * celCount);
+			for (int cel = 0; cel < celCount; cel++) {
+				WRITE_LE_UINT16(writer, celOffset);
+				writer += 2;
+				celOffset += 8 + celDecodedLengths[celTableIndex + cel];
+			}
 
-	*writer++ = 0;
+			// write cels
+			for (int cel = 0; cel < celCount; cel++) {
+				// cel header
+				memcpy(writer, seeker, 7);
+				seeker += 7;
+				writer += 7;
+				*writer++ = 0;
+
+				// cel data
+				int celDecodedLength = celDecodedLengths[celTableIndex + cel];
+				decodeRLE(&rleData, &pixelData, writer, celDecodedLength);
+				writer += celDecodedLength;
+			}
 
-	decodeRLE(&seeker, &cdata, writer, view_size);
+			celTableIndex += celCount;
+			loopTableIndex++;
+		}
+		loopOffsets += 2;
+	}
 
-	free(cdata_start);
-}
+	// write palette
+	if (paletteOffset != 0) {
+		*writer++ = 'P';
+		*writer++ = 'A';
+		*writer++ = 'L';
 
-void DecompressorLZW::buildCelHeaders(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++;
+		// palette translation map
+		for (int i = 0; i < 256; i++) {
+			*writer++ = i;
+		}
+
+		// palette time stamp and palette colors
+		// include the unrelated four bytes before the palette so that
+		// they are written to the palette time stamp. this is a bogus
+		// value but it's what sierra's decompressor did, so we do it
+		// to be consistent with it and other SCI tools. this field is
+		// ignored by the interpreter when reading a view.
+		memcpy(writer, seeker - 4, 4 + 1024);
 	}
+
+	delete[] celDecodedLengths;
 }
 
-void DecompressorLZW::reorderView(byte *src, byte *dest) {
-	byte *cellengths;
-	int loopheaders;
-	int lh_present;
-	int lh_mask;
-	int pal_offset;
-	int cel_total;
-	int unknown;
+void DecompressorLZW::unpackPic(byte *src, byte *dest, int unpackedSize) {
 	byte *seeker = src;
-	char celcounts[100];
 	byte *writer = dest;
-	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 = src + 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);
+	// begin writing set-palette instruction
+	*writer++ = 0xfe; // PIC_OP_OPX
+	*writer++ = 0x02; // PIC_OPX_VGA_SET_PALETTE
 
-	for (c = 0; c < cel_total; c++)
-		cc_lengths[c] = READ_LE_UINT16(cellengths + 2 * c);
+	// write palette translation map
+	for (int i = 0; i < 256; i++) {
+		*writer++ = i;
+	}
 
-	*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;
+	// write palette time stamp
+	memset(writer, 0, 4);
+	writer += 4;
 
-	lh_ptr = writer;
-	writer += 2 * loopheaders; /* Make room for the loop offset table */
+	// read compressed header
+	uint16 viewCelSize = READ_LE_UINT16(seeker);
+	seeker += 2;
+	uint16 viewOpPos = READ_LE_UINT16(seeker); // offset in output pic
+	seeker += 2;
+	uint16 viewPixelDataSize = READ_LE_UINT16(seeker);
+	seeker += 2;
+	byte *viewHeader = seeker;
+	seeker += 7;
+
+	// write palette colors
+	memcpy(writer, seeker, 1024);
+	seeker += 1024;
+	writer += 1024;
+
+	// write optional data before embedded-view instruction
+	if (viewOpPos != 1286) { // 1286 = set-palette instruction size
+		int preViewDataSize = viewOpPos - 1286;
+		memcpy(writer, seeker, preViewDataSize);
+		seeker += preViewDataSize;
+		writer += preViewDataSize;
+	}
 
-	pix_ptr = writer;
+	// write optional data after embedded-view instruction (written to end)
+	int postViewDataPosition = viewOpPos + 15 + viewCelSize;
+	if (unpackedSize != postViewDataPosition) {
+		int postViewDataSize = unpackedSize - postViewDataPosition;
+		memcpy(dest + postViewDataPosition, seeker, postViewDataSize);
+		seeker += postViewDataSize;
+	}
 
-	memcpy(celcounts, seeker, lh_present);
-	seeker += lh_present;
+	// begin writing embedded-view instruction
+	*writer++ = 0xfe; // PIC_OP_OPX
+	*writer++ = 0x01; // PIC_OPX_VGA_EMBEDDED_VIEW
 
-	lb = 1;
-	celindex = 0;
+	// write coordinates (0, 0)
+	memset(writer, 0, 3);
+	writer += 3;
 
-	rle_ptr = pix_ptr = cellengths + (2 * cel_total);
-	w = 0;
+	// write cel size
+	WRITE_LE_UINT16(writer, 8 + viewCelSize);
+	writer += 2;
 
-	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 - dest;
-			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 - dest) + (2 * celcounts[w]);
-
-			for (c = 0; c < celcounts[w]; c++) {
-				WRITE_LE_UINT16(writer, chptr);
-				writer += 2;
-				cc_pos[celindex+c] = dest + chptr;
-				chptr += 8 + READ_LE_UINT16(cellengths + 2 * (celindex + c));
-			}
+	// write view header
+	memcpy(writer, viewHeader, 7);
+	writer += 7;
+	*writer++ = 0;
 
-			buildCelHeaders(&seeker, &writer, celindex, cc_lengths, celcounts[w]);
+	// write view cel (stored as pixel data followed by RLE data)
+	byte *viewRleData = seeker + viewPixelDataSize;;
+	decodeRLE(&viewRleData, &seeker, writer, viewCelSize);
+}
 
-			celindex += celcounts[w];
-			w++;
-		}
+/***
+ * Decodes a cel's data from two separate RLE and pixel buffers.
+ */
+void DecompressorLZW::decodeRLE(byte **rleData, byte **pixelData, byte *dest, int decodedSize) {
+	int pos = 0;
+	byte *rleSeeker = *rleData;
+	byte *pixelSeeker = *pixelData;
 
-		lb = lb << 1;
-	}
+	while (pos < decodedSize) {
+		byte currentByte = *rleSeeker++;
+		*dest++ = currentByte;
+		pos++;
 
-	if (celindex < cel_total) {
-		warning("View decompression generated too few (%d / %d) headers", celindex, cel_total);
-		free(cc_pos);
-		free(cc_lengths);
-		return;
+		byte upperBits = (currentByte & 0xc0);
+		if (upperBits <= 0x40) { // 00, 40
+			memcpy(dest, pixelSeeker, currentByte);
+			pixelSeeker += currentByte;
+			dest += currentByte;
+			pos += currentByte;
+		} else if (upperBits == 0x80) {
+			*dest++ = *pixelSeeker++;
+			pos++;
+		}
 	}
 
-	/* Figure out where the pixel data begins. */
-	for (c = 0; c < cel_total; c++)
-		pix_ptr += getRLEsize(pix_ptr, cc_lengths[c]);
-
-	rle_ptr = cellengths + (2 * cel_total);
-	for (c = 0; c < cel_total; c++)
-		decodeRLE(&rle_ptr, &pix_ptr, cc_pos[c] + 8, cc_lengths[c]);
+	*rleData = rleSeeker;
+	*pixelData = pixelSeeker;
+}
 
-	if (pal_offset) {
-		*writer++ = 'P';
-		*writer++ = 'A';
-		*writer++ = 'L';
+/**
+ * Seeks past a cel's RLE data without decoding.
+ * Used to seek past all RLE data to locate the start of pixel data.
+ */
+void DecompressorLZW::skipRLE(byte **rleData, int decodedSize) {
+	int pos = 0;
+	byte *rleSeeker = *rleData;
 
-		for (c = 0; c < 256; c++)
-			*writer++ = c;
+	while (pos < decodedSize) {
+		byte currentByte = *(rleSeeker++);
+		pos++;
 
-		seeker -= 4; /* The missing four. Don't ask why. */
-		memcpy(writer, seeker, 4*256 + 4);
+		byte upperBits = (currentByte & 0xc0);
+		if (upperBits <= 0x40) { // 00, 40
+			pos += currentByte;
+		} else if (upperBits == 0x80) {
+			pos++;
+		}
 	}
 
-	free(cc_pos);
-	free(cc_lengths);
+	*rleData = rleSeeker;
 }
 
 //----------------------------------------------
diff --git a/engines/sci/resource/decompressor.h b/engines/sci/resource/decompressor.h
index 8d16b4fb88e..750d2da702c 100644
--- a/engines/sci/resource/decompressor.h
+++ b/engines/sci/resource/decompressor.h
@@ -143,7 +143,6 @@ protected:
 
 /**
  * LZW decompressor for SCI0/01/1
- * TODO: Clean-up post-processing functions
  */
 class DecompressorLZW : public Decompressor {
 public:
@@ -153,12 +152,11 @@ public:
 protected:
 	int unpackLZW(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked);
 
-	// functions to post-process view and pic resources
-	void reorderPic(byte *src, byte *dest, int dsize);
-	void reorderView(byte *src, byte *dest);
-	void decodeRLE(byte **rledata, byte **pixeldata, byte *outbuffer, int size);
-	int getRLEsize(byte *rledata, int dsize);
-	void buildCelHeaders(byte **seeker, byte **writer, int celindex, int *cc_lengths, int max);
+	// post-processing functions for view and pic resources
+	static void unpackView(byte *src, byte *dest);
+	static void unpackPic(byte *src, byte *dest, int unpackedSize);
+	static void decodeRLE(byte **rleData, byte **pixelData, byte *dest, int decodedSize);
+	static void skipRLE(byte **rleData, int decodedSize);
 
 	ResourceCompression _compression;
 };


Commit: 79febe2586114757c7a960a4ab5e0692a10d746e
    https://github.com/scummvm/scummvm/commit/79febe2586114757c7a960a4ab5e0692a10d746e
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2026-07-15T17:38:28+03:00

Commit Message:
SCI: Cleanup decompressor code

Changed paths:
    engines/sci/resource/decompressor.cpp
    engines/sci/resource/decompressor.h


diff --git a/engines/sci/resource/decompressor.cpp b/engines/sci/resource/decompressor.cpp
index 45430285f87..46475ddc633 100644
--- a/engines/sci/resource/decompressor.cpp
+++ b/engines/sci/resource/decompressor.cpp
@@ -19,8 +19,6 @@
  *
  */
 
-// Resource library
-
 #include "common/compression/dcl.h"
 #include "common/util.h"
 #include "common/endian.h"
@@ -32,18 +30,13 @@
 #include "sci/resource/resource.h"
 
 namespace Sci {
+
 int Decompressor::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) {
-	while (nPacked && !(src->eos() || src->err())) {
-		uint32 chunk = MIN<uint32>(1024, nPacked);
-		src->read(dest, chunk);
-		nPacked -= chunk;
-		dest += chunk;
-	}
-	return (src->eos() || src->err()) ? 1 : 0;
+	uint32 bytesRead = src->read(dest, nPacked);
+	return (bytesRead == nPacked) ? SCI_ERROR_NONE : SCI_ERROR_IO_ERROR;
 }
 
-void Decompressor::init(Common::ReadStream *src, byte *dest, uint32 nPacked,
-						uint32 nUnpacked) {
+void Decompressor::init(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) {
 	_src = src;
 	_dest = dest;
 	_szPacked = nPacked;
@@ -100,26 +93,25 @@ byte Decompressor::getByteLSB() {
 void Decompressor::putByte(byte b) {
 	_dest[_dwWrote++] = b;
 }
+
 //-------------------------------
 //  Huffman decompressor
 //-------------------------------
-int DecompressorHuffman::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked,
-								uint32 nUnpacked) {
+
+int DecompressorHuffman::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) {
 	init(src, dest, nPacked, nUnpacked);
-	byte numnodes;
-	int16 c;
-	uint16 terminator;
 
-	numnodes = _src->readByte();
-	terminator = _src->readByte() | 0x100;
+	byte numnodes = _src->readByte();
+	uint16 terminator = _src->readByte() | 0x100;
 	_nodes = new byte [numnodes << 1];
 	_src->read(_nodes, numnodes << 1);
 
+	int16 c;
 	while ((c = getc2()) != terminator && (c >= 0) && !isFinished())
 		putByte(c);
 
 	delete[] _nodes;
-	return _dwWrote == _szUnpacked ? 0 : 1;
+	return (_dwWrote == _szUnpacked) ? SCI_ERROR_NONE : SCI_ERROR_DECOMPRESSION_ERROR;
 }
 
 int16 DecompressorHuffman::getc2() {
@@ -498,8 +490,7 @@ void DecompressorLZW::skipRLE(byte **rleData, int decodedSize) {
 // DCL decompressor for SCI1.1
 //----------------------------------------------
 
-int DecompressorDCL::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked,
-							uint32 nUnpacked) {
+int DecompressorDCL::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) {
 	return Common::decompressDCL(src, dest, nPacked, nUnpacked) ? 0 : SCI_ERROR_DECOMPRESSION_ERROR;
 }
 
@@ -510,6 +501,7 @@ int DecompressorDCL::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked,
 // Based on Andre Beck's code from
 // https://web.archive.org/web/20070817214826/http://micky.ibh.de/~beck/stuff/lzs4i4l/
 //----------------------------------------------
+
 int DecompressorLZS::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) {
 	init(src, dest, nPacked, nUnpacked);
 	return unpackLZS();
@@ -541,7 +533,7 @@ int DecompressorLZS::unpackLZS() {
 		} else // Literal byte follows
 			putByte(getByteMSB());
 	} // end of while ()
-	return _dwWrote == _szUnpacked ? 0 : SCI_ERROR_DECOMPRESSION_ERROR;
+	return (_dwWrote == _szUnpacked) ? 0 : SCI_ERROR_DECOMPRESSION_ERROR;
 }
 
 uint32 DecompressorLZS::getCompLen() {
diff --git a/engines/sci/resource/decompressor.h b/engines/sci/resource/decompressor.h
index 750d2da702c..77742b9729e 100644
--- a/engines/sci/resource/decompressor.h
+++ b/engines/sci/resource/decompressor.h
@@ -33,15 +33,15 @@ namespace Sci {
 enum ResourceCompression {
 	kCompUnknown = -1,
 	kCompNone = 0,
-	kCompLZW,
-	kCompHuffman,
-	kCompLZW1,			// LZW-like compression used in SCI01 and SCI1
-	kCompLZW1View,		// Comp3 + view Post-processing
-	kCompLZW1Pic,		// Comp3 + pic Post-processing
+	kCompLZW,           // LZW compression used in SCI0
+	kCompHuffman,       // Huffman compression used for vector pics
+	kCompLZW1,			// LZW compression used in SCI01 and SCI1
+	kCompLZW1View,		// LZW + view post-processing
+	kCompLZW1Pic,		// LZW + pic post-processing
+	kCompDCL            // SCI11
 #ifdef ENABLE_SCI32
-	kCompSTACpack,	// ? Used in SCI32
+,	kCompSTACpack       // SCI32
 #endif
-	kCompDCL
 };
 
 /**
@@ -63,7 +63,11 @@ public:
 
 	virtual ~Decompressor() {}
 
-
+	/**
+	 * Unpack data from source stream to destination buffer.
+	 *
+	 * @return SCI_ERROR_NONE on success, non-zero on error
+	 */
 	virtual int unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked);
 
 protected:
@@ -73,7 +77,6 @@ protected:
 	 * @param dest		destination stream to write to
 	 * @param nPacked	size of packed data
 	 * @param nUnpacket	size of unpacked data
-	 * @return 0 on success, non-zero on error
 	 */
 	virtual void init(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked);
 
@@ -107,7 +110,6 @@ protected:
 	 * Write one byte into _dest stream
 	 * @param b byte to put
 	 */
-
 	virtual void putByte(byte b);
 
 	/**
@@ -170,17 +172,20 @@ public:
 };
 
 #ifdef ENABLE_SCI32
+
 /**
  * STACpack decompressor for SCI32
  */
 class DecompressorLZS : public Decompressor {
 public:
 	int unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) override;
+
 protected:
 	int unpackLZS();
 	uint32 getCompLen();
 	void copyComp(int offs, uint32 clen);
 };
+
 #endif
 
 } // End of namespace Sci




More information about the Scummvm-git-logs mailing list