[Scummvm-cvs-logs] scummvm master -> 3f0c9e0910e7bf7b6cd0ebb217167a6a4ce7ec31

clone2727 clone2727 at gmail.com
Fri Oct 7 19:15:43 CEST 2011


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

Summary:
583bef28ff GRAPHICS: Rewrite PictDecoder's opcode handling
ed13991f37 GRAPHICS: Properly parse the CompressQuickTime header
75d2a43302 GRAPHICS: Add support for multiple CompressedQuickTime calls
711d0ff037 COMMON: Ensure numTypes is set to 0 on close
c0dcfc8060 GRAPHICS: Add support for true 32bpp DirectBits images
5fab8cb521 VIDEO: Ensure audio paused status remains after a QuickTime seek
a064b7bc0b VIDEO: Fix Cinepak variant detection
6a54c7953a VIDEO: Fix getNextFramePacket() to actually be efficient
3f0c9e0910 GRAPHICS: Fix PICT buffer overflow


Commit: 583bef28ff48ae9589348c72c952bef515ce039b
    https://github.com/scummvm/scummvm/commit/583bef28ff48ae9589348c72c952bef515ce039b
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2011-10-07T08:31:41-07:00

Commit Message:
GRAPHICS: Rewrite PictDecoder's opcode handling

In preparation for adding support for multiple CompressedQuickTime opcodes

Changed paths:
    graphics/pict.cpp
    graphics/pict.h



diff --git a/graphics/pict.cpp b/graphics/pict.cpp
index 80bcb7a..f768ecd 100644
--- a/graphics/pict.cpp
+++ b/graphics/pict.cpp
@@ -45,10 +45,164 @@ PictDecoder::~PictDecoder() {
 	delete _jpeg;
 }
 
+#define OPCODE(a, b, c) _opcodes.push_back(PICTOpcode(a, &PictDecoder::b, c))
+
+void PictDecoder::setupOpcodesCommon() {
+	OPCODE(0x0000, o_nop, "NOP");
+	OPCODE(0x0001, o_clip, "Clip");
+	OPCODE(0x0003, o_txFont, "TxFont");
+	OPCODE(0x0004, o_txFace, "TxFace");
+	OPCODE(0x0007, o_pnSize, "PnSize");
+	OPCODE(0x000D, o_txSize, "TxSize");
+	OPCODE(0x0010, o_txRatio, "TxRatio");
+	OPCODE(0x0011, o_versionOp, "VersionOp");
+	OPCODE(0x001E, o_nop, "DefHilite");
+	OPCODE(0x0028, o_longText, "LongText");
+	OPCODE(0x00A1, o_longComment, "LongComment");
+	OPCODE(0x00FF, o_opEndPic, "OpEndPic");
+	OPCODE(0x0C00, o_headerOp, "HeaderOp");
+}
+
+void PictDecoder::setupOpcodesNormal() {
+	setupOpcodesCommon();
+	OPCODE(0x0098, on_packBitsRect, "PackBitsRect");
+	OPCODE(0x009A, on_directBitsRect, "DirectBitsRect");
+	OPCODE(0x8200, on_compressedQuickTime, "CompressedQuickTime");
+}
+
+void PictDecoder::setupOpcodesQuickTime() {
+	setupOpcodesCommon();
+	OPCODE(0x0098, oq_packBitsRect, "PackBitsRect");
+	OPCODE(0x009A, oq_directBitsRect, "DirectBitsRect");
+	OPCODE(0x8200, oq_compressedQuickTime, "CompressedQuickTime");
+}
+
+#undef OPCODE
+
+void PictDecoder::o_nop(Common::SeekableReadStream *) {
+	// Nothing to do
+}
+
+void PictDecoder::o_clip(Common::SeekableReadStream *stream) {
+	// Ignore
+	stream->skip(stream->readUint16BE() - 2);
+}
+
+void PictDecoder::o_txFont(Common::SeekableReadStream *stream) {
+	// Ignore
+	stream->readUint16BE();
+}
+
+void PictDecoder::o_txFace(Common::SeekableReadStream *stream) {
+	// Ignore
+	stream->readByte();
+}
+
+void PictDecoder::o_pnSize(Common::SeekableReadStream *stream) {
+	// Ignore
+	stream->readUint16BE();
+	stream->readUint16BE();
+}
+
+void PictDecoder::o_txSize(Common::SeekableReadStream *stream) {
+	// Ignore
+	stream->readUint16BE();
+}
+
+void PictDecoder::o_txRatio(Common::SeekableReadStream *stream) {
+	// Ignore
+	stream->readUint16BE();
+	stream->readUint16BE();
+	stream->readUint16BE();
+	stream->readUint16BE();
+}
+
+void PictDecoder::o_versionOp(Common::SeekableReadStream *stream) {
+	// We only support v2 extended
+	if (stream->readUint16BE() != 0x02FF)
+		error("Unknown PICT version");
+}
+
+void PictDecoder::o_longText(Common::SeekableReadStream *stream) {
+	// Ignore
+	stream->readUint16BE();
+	stream->readUint16BE();
+	stream->skip(stream->readByte());
+}
+
+void PictDecoder::o_longComment(Common::SeekableReadStream *stream) {
+	// Ignore
+	stream->readUint16BE();
+	stream->skip(stream->readUint16BE());
+}
+
+void PictDecoder::o_opEndPic(Common::SeekableReadStream *stream) {
+	// We've reached the end of the picture
+	_continueParsing = false;
+}
+
+void PictDecoder::o_headerOp(Common::SeekableReadStream *stream) {
+	// Read the basic header, but we don't really have to do anything with it
+	/* uint16 version = */ stream->readUint16BE();
+	stream->readUint16BE(); // Reserved
+	/* uint32 hRes = */ stream->readUint32BE();
+	/* uint32 vRes = */ stream->readUint32BE();
+	Common::Rect origResRect;
+	origResRect.top = stream->readUint16BE();
+	origResRect.left = stream->readUint16BE();
+	origResRect.bottom = stream->readUint16BE();
+	origResRect.right = stream->readUint16BE();
+	stream->readUint32BE(); // Reserved
+}
+
+void PictDecoder::on_packBitsRect(Common::SeekableReadStream *stream) {
+	// Unpack data (8bpp or lower)
+	unpackBitsRect(stream, true);
+}
+
+void PictDecoder::on_directBitsRect(Common::SeekableReadStream *stream) {
+	// Unpack data (16bpp or higher)
+	unpackBitsRect(stream, false);
+}
+
+void PictDecoder::on_compressedQuickTime(Common::SeekableReadStream *stream) {
+	// OK, here's the fun. We get to completely change how QuickDraw draws
+	// the data in PICT files.
+
+	// Swap out the opcodes to the new ones
+	_opcodes.clear();
+	setupOpcodesQuickTime();
+
+	// We'll decode the first QuickTime data from here, but the QuickTime-specific
+	// opcodes will take over from here on out. Normal opcodes, signing off.
+	decodeCompressedQuickTime(stream);
+}
+
+void PictDecoder::oq_packBitsRect(Common::SeekableReadStream *stream) {
+	// Skip any data here (8bpp or lower)
+	skipBitsRect(stream, true);
+}
+
+void PictDecoder::oq_directBitsRect(Common::SeekableReadStream *stream) {
+	// Skip any data here (16bpp or higher)
+	skipBitsRect(stream, false);
+}
+
+void PictDecoder::oq_compressedQuickTime(Common::SeekableReadStream *stream) {
+	// Just pass the data along
+	decodeCompressedQuickTime(stream);
+}
+
 Surface *PictDecoder::decodeImage(Common::SeekableReadStream *stream, byte *palette) {
 	assert(stream);
 
+	// Initialize opcodes to their normal state
+	_opcodes.clear();
+	setupOpcodesNormal();
+
 	_outputSurface = 0;
+	_continueParsing = true;
+	memset(_palette, 0, sizeof(_palette));
 
 	uint16 fileSize = stream->readUint16BE();
 
@@ -63,70 +217,41 @@ Surface *PictDecoder::decodeImage(Common::SeekableReadStream *stream, byte *pale
 	_imageRect.bottom = stream->readUint16BE();
 	_imageRect.right = stream->readUint16BE();
 	_imageRect.debugPrint(0, "PICT Rect:");
-	_isPaletted = false;
 
 	// NOTE: This is only a subset of the full PICT format.
-	//     - Only V2 Images Supported
+	//     - Only V2 (Extended) Images Supported
 	//     - CompressedQuickTime (JPEG) compressed data is supported
 	//     - DirectBitsRect/PackBitsRect compressed data is supported
-	for (uint32 opNum = 0; !stream->eos() && !stream->err() && stream->pos() < stream->size(); opNum++) {
+	for (uint32 opNum = 0; !stream->eos() && !stream->err() && stream->pos() < stream->size() && _continueParsing; opNum++) {
+		// PICT v2 opcodes are two bytes
 		uint16 opcode = stream->readUint16BE();
-		debug(2, "Found PICT opcode %04x", opcode);
 
 		if (opNum == 0 && opcode != 0x0011)
-			error ("Cannot find PICT version opcode");
+			error("Cannot find PICT version opcode");
 		else if (opNum == 1 && opcode != 0x0C00)
-			error ("Cannot find PICT header opcode");
-
-		if (opcode == 0x0000) {        // Nop
-			stream->readUint16BE(); // Unknown
-		} else if (opcode == 0x0001) { // Clip
-			// Ignore
-			uint16 clipSize = stream->readUint16BE();
-			stream->seek(clipSize - 2, SEEK_CUR);
-		} else if (opcode == 0x0007) { // PnSize
-			// Ignore
-			stream->readUint16BE();
-			stream->readUint16BE();
-		} else if (opcode == 0x0011) { // VersionOp
-			uint16 version = stream->readUint16BE();
-			if (version != 0x02FF)
-				error ("Unknown PICT version");
-		} else if (opcode == 0x001E) { // DefHilite
-			// Ignore, Contains no Data
-		} else if (opcode == 0x0098) { // PackBitsRect
-			decodeDirectBitsRect(stream, true);
-			_isPaletted = true;
-		} else if (opcode == 0x009A) { // DirectBitsRect
-			decodeDirectBitsRect(stream, false);
-		} else if (opcode == 0x00A1) { // LongComment
-			stream->readUint16BE();
-			uint16 dataSize = stream->readUint16BE();
-			stream->seek(dataSize, SEEK_CUR);
-		} else if (opcode == 0x00FF) { // OpEndPic
-			stream->readUint16BE();
-			break;
-		} else if (opcode == 0x0C00) { // HeaderOp
-			/* uint16 version = */ stream->readUint16BE();
-			stream->readUint16BE(); // Reserved
-			/* uint32 hRes = */ stream->readUint32BE();
-			/* uint32 vRes = */ stream->readUint32BE();
-			Common::Rect origResRect;
-			origResRect.top = stream->readUint16BE();
-			origResRect.left = stream->readUint16BE();
-			origResRect.bottom = stream->readUint16BE();
-			origResRect.right = stream->readUint16BE();
-			stream->readUint32BE(); // Reserved
-		} else if (opcode == 0x8200) { // CompressedQuickTime
-			decodeCompressedQuickTime(stream);
-			break;
-		} else {
-			warning("Unknown PICT opcode %04x", opcode);
+			error("Cannot find PICT header opcode");
+
+		// Since opcodes are word-aligned, we need to mark our starting
+		// position here.
+		uint32 startPos = stream->pos();
+
+		for (uint32 i = 0; i < _opcodes.size(); i++) {
+			if (_opcodes[i].op == opcode) {
+				debug(4, "Running PICT opcode %04x '%s'", opcode, _opcodes[i].desc);
+				(this->*(_opcodes[i].proc))(stream);
+				break;
+			} else if (i == _opcodes.size() - 1) {
+				// Unknown opcode; attempt to continue forward
+				warning("Unknown PICT opcode %04x", opcode);
+			}
 		}
+
+		// Align
+		stream->skip((stream->pos() - startPos) & 1);
 	}
 
 	// If we got a palette throughout this nonsense, go and grab it
-	if (palette && _isPaletted)
+	if (palette)
 		memcpy(palette, _palette, 256 * 3);
 
 	return _outputSurface;
@@ -155,21 +280,18 @@ PictDecoder::PixMap PictDecoder::readPixMap(Common::SeekableReadStream *stream,
 	return pixMap;
 }
 
-struct DirectBitsRectData {
+struct PackBitsRectData {
 	PictDecoder::PixMap pixMap;
 	Common::Rect srcRect;
 	Common::Rect dstRect;
 	uint16 mode;
 };
 
-void PictDecoder::decodeDirectBitsRect(Common::SeekableReadStream *stream, bool hasPalette) {
+void PictDecoder::unpackBitsRect(Common::SeekableReadStream *stream, bool hasPalette) {
 	static const PixelFormat directBitsFormat16 = PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
 
-	// Clear the palette
-	memset(_palette, 0, sizeof(_palette));
-
-	DirectBitsRectData directBitsData;
-	directBitsData.pixMap = readPixMap(stream, !hasPalette);
+	PackBitsRectData packBitsData;
+	packBitsData.pixMap = readPixMap(stream, !hasPalette);
 
 	// Read in the palette if there is one present
 	if (hasPalette) {
@@ -186,47 +308,47 @@ void PictDecoder::decodeDirectBitsRect(Common::SeekableReadStream *stream, bool
 		}
 	}
 
-	directBitsData.srcRect.top = stream->readUint16BE();
-	directBitsData.srcRect.left = stream->readUint16BE();
-	directBitsData.srcRect.bottom = stream->readUint16BE();
-	directBitsData.srcRect.right = stream->readUint16BE();
-	directBitsData.dstRect.top = stream->readUint16BE();
-	directBitsData.dstRect.left = stream->readUint16BE();
-	directBitsData.dstRect.bottom = stream->readUint16BE();
-	directBitsData.dstRect.right = stream->readUint16BE();
-	directBitsData.mode = stream->readUint16BE();
+	packBitsData.srcRect.top = stream->readUint16BE();
+	packBitsData.srcRect.left = stream->readUint16BE();
+	packBitsData.srcRect.bottom = stream->readUint16BE();
+	packBitsData.srcRect.right = stream->readUint16BE();
+	packBitsData.dstRect.top = stream->readUint16BE();
+	packBitsData.dstRect.left = stream->readUint16BE();
+	packBitsData.dstRect.bottom = stream->readUint16BE();
+	packBitsData.dstRect.right = stream->readUint16BE();
+	packBitsData.mode = stream->readUint16BE();
 
-	uint16 width = directBitsData.srcRect.width();
-	uint16 height = directBitsData.srcRect.height();
+	uint16 width = packBitsData.srcRect.width();
+	uint16 height = packBitsData.srcRect.height();
 
 	byte bytesPerPixel = 0;
 
-	if (directBitsData.pixMap.pixelSize <= 8)
+	if (packBitsData.pixMap.pixelSize <= 8)
 		bytesPerPixel = 1;
-	else if (directBitsData.pixMap.pixelSize == 32)
+	else if (packBitsData.pixMap.pixelSize == 32)
 		bytesPerPixel = 3;
 	else
-		bytesPerPixel = directBitsData.pixMap.pixelSize / 8;
+		bytesPerPixel = packBitsData.pixMap.pixelSize / 8;
 
 	_outputSurface = new Graphics::Surface();
 	_outputSurface->create(width, height, (bytesPerPixel == 1) ? PixelFormat::createFormatCLUT8() : _pixelFormat);
 	byte *buffer = new byte[width * height * bytesPerPixel];
 
 	// Read in amount of data per row
-	for (uint16 i = 0; i < directBitsData.pixMap.bounds.height(); i++) {
+	for (uint16 i = 0; i < packBitsData.pixMap.bounds.height(); i++) {
 		// NOTE: Compression 0 is "default". The format in SCI games is packed when 0.
 		// In the future, we may need to have something to set the  "default" packing
 		// format, but this is good for now.
 
-		if (directBitsData.pixMap.packType == 1 || directBitsData.pixMap.rowBytes < 8) { // Unpacked, Pad-Byte (on 24-bit)
+		if (packBitsData.pixMap.packType == 1 || packBitsData.pixMap.rowBytes < 8) { // Unpacked, Pad-Byte (on 24-bit)
 			// TODO: Finish this. Hasn't been needed (yet).
 			error("Unpacked DirectBitsRect data (padded)");
-		} else if (directBitsData.pixMap.packType == 2) { // Unpacked, No Pad-Byte (on 24-bit)
+		} else if (packBitsData.pixMap.packType == 2) { // Unpacked, No Pad-Byte (on 24-bit)
 			// TODO: Finish this. Hasn't been needed (yet).
 			error("Unpacked DirectBitsRect data (not padded)");
-		} else if (directBitsData.pixMap.packType == 0 || directBitsData.pixMap.packType > 2) { // Packed
-			uint16 byteCount = (directBitsData.pixMap.rowBytes > 250) ? stream->readUint16BE() : stream->readByte();
-			decodeDirectBitsLine(buffer + i * _outputSurface->w * bytesPerPixel, directBitsData.pixMap.rowBytes, stream->readStream(byteCount), directBitsData.pixMap.pixelSize, bytesPerPixel);
+		} else if (packBitsData.pixMap.packType == 0 || packBitsData.pixMap.packType > 2) { // Packed
+			uint16 byteCount = (packBitsData.pixMap.rowBytes > 250) ? stream->readUint16BE() : stream->readByte();
+			unpackBitsLine(buffer + i * _outputSurface->w * bytesPerPixel, packBitsData.pixMap.rowBytes, stream->readStream(byteCount), packBitsData.pixMap.pixelSize, bytesPerPixel);
 		}
 	}
 
@@ -264,7 +386,7 @@ void PictDecoder::decodeDirectBitsRect(Common::SeekableReadStream *stream, bool
 	delete[] buffer;
 }
 
-void PictDecoder::decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bitsPerPixel, byte bytesPerPixel) {
+void PictDecoder::unpackBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bitsPerPixel, byte bytesPerPixel) {
 	uint32 dataDecoded = 0;
 	byte bytesPerDecode = (bytesPerPixel == 2) ? 2 : 1;
 
@@ -299,11 +421,16 @@ void PictDecoder::decodeDirectBitsLine(byte *out, uint32 length, Common::Seekabl
 		dataDecoded += length / 4;
 
 	if (length != dataDecoded)
-		warning("Mismatched DirectBits read (%d/%d)", dataDecoded, length);
+		warning("Mismatched PackBits read (%d/%d)", dataDecoded, length);
 
 	delete data;
 }
 
+void PictDecoder::skipBitsRect(Common::SeekableReadStream *stream, bool hasPalette) {
+	// TODO
+	error("TODO: PICT-QuickTime mode: skip PackBitsRect/DirectBitsRect");
+}
+
 void PictDecoder::outputPixelBuffer(byte *&out, byte value, byte bitsPerPixel) {
 	switch (bitsPerPixel) {
 	case 1:
diff --git a/graphics/pict.h b/graphics/pict.h
index 485c88b..b426c6e 100644
--- a/graphics/pict.h
+++ b/graphics/pict.h
@@ -23,6 +23,7 @@
 #ifndef GRAPHICS_PICT_H
 #define GRAPHICS_PICT_H
 
+#include "common/array.h"
 #include "common/rect.h"
 #include "common/scummsys.h"
 
@@ -37,6 +38,8 @@ namespace Graphics {
 class JPEG;
 struct Surface;
 
+#define DECLARE_OPCODE(x) void x(Common::SeekableReadStream *stream)
+
 class PictDecoder {
 public:
 	PictDecoder(Graphics::PixelFormat pixelFormat);
@@ -70,13 +73,56 @@ private:
 	byte _palette[256 * 3];
 	bool _isPaletted;
 	Graphics::Surface *_outputSurface;
+	bool _continueParsing;
 
-	void decodeDirectBitsRect(Common::SeekableReadStream *stream, bool hasPalette);
-	void decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bitsPerPixel, byte bytesPerPixel);
+	// Utility Functions
+	void unpackBitsRect(Common::SeekableReadStream *stream, bool hasPalette);
+	void unpackBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bitsPerPixel, byte bytesPerPixel);
+	void skipBitsRect(Common::SeekableReadStream *stream, bool hasPalette);
 	void decodeCompressedQuickTime(Common::SeekableReadStream *stream);
 	void outputPixelBuffer(byte *&out, byte value, byte bitsPerPixel);
+
+	// Opcodes
+	typedef void (PictDecoder::*OpcodeProcPICT)(Common::SeekableReadStream *stream);
+	struct PICTOpcode {
+		PICTOpcode() { op = 0; proc = 0; desc = 0; }
+		PICTOpcode(uint16 o, OpcodeProcPICT p, const char *d) { op = o; proc = p; desc = d; }
+		uint16 op;
+		OpcodeProcPICT proc;
+		const char *desc;
+	};
+	Common::Array<PICTOpcode> _opcodes;
+
+	// Common Opcodes
+	void setupOpcodesCommon();
+	DECLARE_OPCODE(o_nop);
+	DECLARE_OPCODE(o_clip);
+	DECLARE_OPCODE(o_txFont);
+	DECLARE_OPCODE(o_txFace);
+	DECLARE_OPCODE(o_pnSize);
+	DECLARE_OPCODE(o_txSize);
+	DECLARE_OPCODE(o_txRatio);
+	DECLARE_OPCODE(o_versionOp);
+	DECLARE_OPCODE(o_longText);
+	DECLARE_OPCODE(o_longComment);
+	DECLARE_OPCODE(o_opEndPic);
+	DECLARE_OPCODE(o_headerOp);
+
+	// Regular-mode Opcodes
+	void setupOpcodesNormal();
+	DECLARE_OPCODE(on_packBitsRect);
+	DECLARE_OPCODE(on_directBitsRect);
+	DECLARE_OPCODE(on_compressedQuickTime);
+
+	// QuickTime-mode Opcodes
+	void setupOpcodesQuickTime();
+	DECLARE_OPCODE(oq_packBitsRect);
+	DECLARE_OPCODE(oq_directBitsRect);
+	DECLARE_OPCODE(oq_compressedQuickTime);
 };
 
+#undef DECLARE_OPCODE
+
 } // End of namespace Graphics
 
 #endif


Commit: ed13991f37a1f0ea93e516d7a916438ed6521eea
    https://github.com/scummvm/scummvm/commit/ed13991f37a1f0ea93e516d7a916438ed6521eea
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2011-10-07T08:32:08-07:00

Commit Message:
GRAPHICS: Properly parse the CompressQuickTime header

Changed paths:
    graphics/pict.cpp



diff --git a/graphics/pict.cpp b/graphics/pict.cpp
index f768ecd..718214c 100644
--- a/graphics/pict.cpp
+++ b/graphics/pict.cpp
@@ -453,13 +453,36 @@ void PictDecoder::outputPixelBuffer(byte *&out, byte value, byte bitsPerPixel) {
 // Compressed QuickTime details can be found here:
 // http://developer.apple.com/legacy/mac/library/#documentation/QuickTime/Rm/CompressDecompress/ImageComprMgr/B-Chapter/2TheImageCompression.html
 // http://developer.apple.com/legacy/mac/library/#documentation/QuickTime/Rm/CompressDecompress/ImageComprMgr/F-Chapter/6WorkingwiththeImage.html
-// I'm just ignoring that because Myst ME uses none of that extra stuff. The offset is always the same.
 
 void PictDecoder::decodeCompressedQuickTime(Common::SeekableReadStream *stream) {
+	// First, read all the fields from the opcode
 	uint32 dataSize = stream->readUint32BE();
 	uint32 startPos = stream->pos();
 
-	Common::SeekableReadStream *jpegStream = new Common::SeekableSubReadStream(stream, stream->pos() + 156, stream->pos() + dataSize);
+	/* uint16 version = */ stream->readUint16BE();
+
+	uint32 matrix[3][3];
+	for (uint32 i = 0; i < 3; i++)
+		for (uint32 j = 0; j < 3; j++)
+			matrix[i][j] = stream->readUint32BE();
+
+	uint32 matteSize = stream->readUint32BE();
+	stream->skip(8); // matte rect
+	/* uint16 transferMode = */ stream->readUint16BE();
+	stream->skip(8); // src rect
+	/* uint32 accuracy = */ stream->readUint32BE();
+	uint32 maskSize = stream->readUint32BE();
+	
+	stream->skip(matteSize + maskSize);
+	
+	// Now we've reached the image descriptor, so read the relevant data from that
+	uint32 idStart = stream->pos();
+	uint32 idSize = stream->readUint32BE();
+	stream->skip(40);
+	uint32 jpegSize = stream->readUint32BE();
+	stream->skip(idSize - (stream->pos() - idStart));
+
+	Common::SeekableReadStream *jpegStream = new Common::SeekableSubReadStream(stream, stream->pos(), stream->pos() + jpegSize);
 
 	if (!_jpeg->read(jpegStream))
 		error("PictDecoder::decodeCompressedQuickTime(): Could not decode JPEG data");


Commit: 75d2a43302e5f59bed2678ab21a41586d1c6a6eb
    https://github.com/scummvm/scummvm/commit/75d2a43302e5f59bed2678ab21a41586d1c6a6eb
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2011-10-07T08:32:35-07:00

Commit Message:
GRAPHICS: Add support for multiple CompressedQuickTime calls

Changed paths:
    graphics/pict.cpp



diff --git a/graphics/pict.cpp b/graphics/pict.cpp
index 718214c..a4cc67f 100644
--- a/graphics/pict.cpp
+++ b/graphics/pict.cpp
@@ -173,6 +173,11 @@ void PictDecoder::on_compressedQuickTime(Common::SeekableReadStream *stream) {
 	_opcodes.clear();
 	setupOpcodesQuickTime();
 
+	// We set up the surface for JPEG here too
+	if (!_outputSurface)
+		_outputSurface = new Graphics::Surface();
+	_outputSurface->create(_imageRect.width(), _imageRect.height(), _pixelFormat);
+
 	// We'll decode the first QuickTime data from here, but the QuickTime-specific
 	// opcodes will take over from here on out. Normal opcodes, signing off.
 	decodeCompressedQuickTime(stream);
@@ -427,8 +432,50 @@ void PictDecoder::unpackBitsLine(byte *out, uint32 length, Common::SeekableReadS
 }
 
 void PictDecoder::skipBitsRect(Common::SeekableReadStream *stream, bool hasPalette) {
-	// TODO
-	error("TODO: PICT-QuickTime mode: skip PackBitsRect/DirectBitsRect");
+	// Step through a PackBitsRect/DirectBitsRect function
+
+	if (!hasPalette)
+		stream->readUint32BE();
+
+	uint16 rowBytes = stream->readUint16BE();
+	uint16 height = stream->readUint16BE();
+	stream->readUint16BE();
+	height = stream->readUint16BE() - height;
+	stream->readUint16BE();
+
+	uint16 packType;
+	uint16 pixelSize;
+
+	// Top two bits signify PixMap vs BitMap
+	if (rowBytes & 0xC000) {
+		// PixMap
+		stream->readUint16BE();
+		packType = stream->readUint16BE();
+		stream->skip(14);
+		pixelSize = stream->readUint16BE();
+		stream->skip(16);
+
+		if (hasPalette) {
+			stream->readUint32BE();
+			stream->readUint16BE();
+			stream->skip((stream->readUint16BE() + 1) * 8);
+		}
+
+		rowBytes &= 0x3FFF;
+	} else {
+		// BitMap
+		packType = 0;
+		pixelSize = 1;
+	}
+
+	stream->skip(18);
+
+	for (uint16 i = 0; i < height; i++) {
+		if (packType == 1 || packType == 2 || rowBytes < 8)
+			error("Unpacked PackBitsRect data");
+		else if (packType == 0 || packType > 2)
+			stream->skip((rowBytes > 250) ? stream->readUint16BE() : stream->readByte());
+	}
 }
 
 void PictDecoder::outputPixelBuffer(byte *&out, byte value, byte bitsPerPixel) {
@@ -461,33 +508,42 @@ void PictDecoder::decodeCompressedQuickTime(Common::SeekableReadStream *stream)
 
 	/* uint16 version = */ stream->readUint16BE();
 
+	// Read in the display matrix
 	uint32 matrix[3][3];
 	for (uint32 i = 0; i < 3; i++)
 		for (uint32 j = 0; j < 3; j++)
 			matrix[i][j] = stream->readUint32BE();
 
+	// We currently only support offseting images vertically from the matrix
+	uint16 xOffset = 0;
+	uint16 yOffset = matrix[2][1] >> 16;
+
 	uint32 matteSize = stream->readUint32BE();
 	stream->skip(8); // matte rect
 	/* uint16 transferMode = */ stream->readUint16BE();
 	stream->skip(8); // src rect
 	/* uint32 accuracy = */ stream->readUint32BE();
 	uint32 maskSize = stream->readUint32BE();
-	
+
+	// Skip the matte and mask
 	stream->skip(matteSize + maskSize);
 	
 	// Now we've reached the image descriptor, so read the relevant data from that
 	uint32 idStart = stream->pos();
 	uint32 idSize = stream->readUint32BE();
-	stream->skip(40);
+	stream->skip(40); // miscellaneous stuff
 	uint32 jpegSize = stream->readUint32BE();
-	stream->skip(idSize - (stream->pos() - idStart));
+	stream->skip(idSize - (stream->pos() - idStart)); // more useless stuff
 
 	Common::SeekableReadStream *jpegStream = new Common::SeekableSubReadStream(stream, stream->pos(), stream->pos() + jpegSize);
 
 	if (!_jpeg->read(jpegStream))
 		error("PictDecoder::decodeCompressedQuickTime(): Could not decode JPEG data");
 
-	_outputSurface = _jpeg->getSurface(_pixelFormat);
+	Graphics::Surface *jpegSurface = _jpeg->getSurface(_pixelFormat);
+
+	for (uint16 y = 0; y < jpegSurface->h; y++)
+		memcpy(_outputSurface->getBasePtr(0 + xOffset, y + yOffset), jpegSurface->getBasePtr(0, y), jpegSurface->w * _pixelFormat.bytesPerPixel);
 
 	stream->seek(startPos + dataSize);
 	delete jpegStream;


Commit: 711d0ff0379ba03c60d7a5ab0e30753c32c9c634
    https://github.com/scummvm/scummvm/commit/711d0ff0379ba03c60d7a5ab0e30753c32c9c634
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2011-10-07T08:32:57-07:00

Commit Message:
COMMON: Ensure numTypes is set to 0 on close

Changed paths:
    common/macresman.cpp



diff --git a/common/macresman.cpp b/common/macresman.cpp
index c1cab8b..2b9c68a 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -69,6 +69,7 @@ void MacResManager::close() {
 	delete[] _resLists; _resLists = 0;
 	delete[] _resTypes; _resTypes = 0;
 	delete _stream; _stream = 0;
+	_resMap.numTypes = 0;
 }
 
 bool MacResManager::hasDataFork() const {


Commit: c0dcfc8060bcdc52bb21d9dac2196a737c5751cc
    https://github.com/scummvm/scummvm/commit/c0dcfc8060bcdc52bb21d9dac2196a737c5751cc
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2011-10-07T08:33:09-07:00

Commit Message:
GRAPHICS: Add support for true 32bpp DirectBits images

Changed paths:
    graphics/pict.cpp



diff --git a/graphics/pict.cpp b/graphics/pict.cpp
index a4cc67f..b2d8140 100644
--- a/graphics/pict.cpp
+++ b/graphics/pict.cpp
@@ -331,7 +331,7 @@ void PictDecoder::unpackBitsRect(Common::SeekableReadStream *stream, bool hasPal
 	if (packBitsData.pixMap.pixelSize <= 8)
 		bytesPerPixel = 1;
 	else if (packBitsData.pixMap.pixelSize == 32)
-		bytesPerPixel = 3;
+		bytesPerPixel = packBitsData.pixMap.cmpCount;
 	else
 		bytesPerPixel = packBitsData.pixMap.pixelSize / 8;
 
@@ -357,10 +357,12 @@ void PictDecoder::unpackBitsRect(Common::SeekableReadStream *stream, bool hasPal
 		}
 	}
 
-	if (bytesPerPixel == 1) {
+	switch (bytesPerPixel) {
+	case 1:
 		// Just copy to the image
 		memcpy(_outputSurface->pixels, buffer, _outputSurface->w * _outputSurface->h);
-	} else if (bytesPerPixel == 2) {
+		break;
+	case 2:
 		// Convert from 16-bit to whatever surface we need
 		for (uint16 y = 0; y < _outputSurface->h; y++) {
 			for (uint16 x = 0; x < _outputSurface->w; x++) {
@@ -373,7 +375,8 @@ void PictDecoder::unpackBitsRect(Common::SeekableReadStream *stream, bool hasPal
 					*((uint32 *)_outputSurface->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
 			}
 		}
-	} else {
+		break;
+	case 3:
 		// Convert from 24-bit (planar!) to whatever surface we need
 		for (uint16 y = 0; y < _outputSurface->h; y++) {
 			for (uint16 x = 0; x < _outputSurface->w; x++) {
@@ -386,6 +389,22 @@ void PictDecoder::unpackBitsRect(Common::SeekableReadStream *stream, bool hasPal
 					*((uint32 *)_outputSurface->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
 			}
 		}
+		break;
+	case 4:
+		// Convert from 32-bit (planar!) to whatever surface we need
+		for (uint16 y = 0; y < _outputSurface->h; y++) {
+			for (uint16 x = 0; x < _outputSurface->w; x++) {
+				byte r = *(buffer + y * _outputSurface->w * 4 + x);
+				byte g = *(buffer + y * _outputSurface->w * 4 + _outputSurface->w + x);
+				byte b = *(buffer + y * _outputSurface->w * 4 + _outputSurface->w * 2 + x);
+				byte a = *(buffer + y * _outputSurface->w * 4 + _outputSurface->w * 3 + x);
+				if (_pixelFormat.bytesPerPixel == 2)
+					*((uint16 *)_outputSurface->getBasePtr(x, y)) = _pixelFormat.ARGBToColor(r, g, b, a);
+				else
+					*((uint32 *)_outputSurface->getBasePtr(x, y)) = _pixelFormat.ARGBToColor(r, g, b, a);
+			}
+		}
+		break;
 	}
 
 	delete[] buffer;
@@ -421,7 +440,7 @@ void PictDecoder::unpackBitsLine(byte *out, uint32 length, Common::SeekableReadS
 		}
 	}
 
-	// HACK: rowBytes is in 32-bit, but the data is 24-bit...
+	// HACK: Even if the data is 24-bit, rowBytes is still 32-bit
 	if (bytesPerPixel == 3)
 		dataDecoded += length / 4;
 


Commit: 5fab8cb521856b74605ba4523a144e270126a6a9
    https://github.com/scummvm/scummvm/commit/5fab8cb521856b74605ba4523a144e270126a6a9
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2011-10-07T08:33:24-07:00

Commit Message:
VIDEO: Ensure audio paused status remains after a QuickTime seek

Changed paths:
    video/qt_decoder.cpp



diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp
index f93f0d6..2dfb56d 100644
--- a/video/qt_decoder.cpp
+++ b/video/qt_decoder.cpp
@@ -176,6 +176,10 @@ void QuickTimeDecoder::seekToFrame(uint32 frame) {
 
 		// Restart the audio
 		startAudio();
+
+		// Pause the audio again if we're still paused
+		if (isPaused() && _audStream)
+			g_system->getMixer()->pauseHandle(_audHandle, true);
 	}
 }
 


Commit: a064b7bc0b38268b14d52755d8d3747db28240ae
    https://github.com/scummvm/scummvm/commit/a064b7bc0b38268b14d52755d8d3747db28240ae
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2011-10-07T08:34:03-07:00

Commit Message:
VIDEO: Fix Cinepak variant detection

Changed paths:
    video/codecs/cinepak.cpp



diff --git a/video/codecs/cinepak.cpp b/video/codecs/cinepak.cpp
index c8b23df..c197e0c 100644
--- a/video/codecs/cinepak.cpp
+++ b/video/codecs/cinepak.cpp
@@ -73,7 +73,8 @@ CinepakDecoder::~CinepakDecoder() {
 
 const Graphics::Surface *CinepakDecoder::decodeImage(Common::SeekableReadStream *stream) {
 	_curFrame.flags = stream->readByte();
-	_curFrame.length = (stream->readByte() << 16) + stream->readUint16BE();
+	_curFrame.length = (stream->readByte() << 16);
+	_curFrame.length |= stream->readUint16BE();
 	_curFrame.width = stream->readUint16BE();
 	_curFrame.height = stream->readUint16BE();
 	_curFrame.stripCount = stream->readUint16BE();
@@ -86,8 +87,11 @@ const Graphics::Surface *CinepakDecoder::decodeImage(Common::SeekableReadStream
 	// Borrowed from FFMPEG. This should cut out the extra data Cinepak for Sega has (which is useless).
 	// The theory behind this is that this is here to confuse standard Cinepak decoders. But, we won't let that happen! ;)
 	if (_curFrame.length != (uint32)stream->size()) {
-		if (stream->readUint16BE() == 0xFE00)
+		uint16 temp = stream->readUint16BE();
+		if (temp == 0xFE00)
 			stream->readUint32BE();
+		else if (temp != _curFrame.width)
+			stream->seek(-2, SEEK_CUR);
 	}
 
 	if (!_curFrame.surface) {


Commit: 6a54c7953a03b901e928c1a4c95bbcead1342c20
    https://github.com/scummvm/scummvm/commit/6a54c7953a03b901e928c1a4c95bbcead1342c20
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2011-10-07T08:34:30-07:00

Commit Message:
VIDEO: Fix getNextFramePacket() to actually be efficient

Changed paths:
    video/qt_decoder.cpp



diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp
index 2dfb56d..389acea 100644
--- a/video/qt_decoder.cpp
+++ b/video/qt_decoder.cpp
@@ -483,23 +483,18 @@ Common::SeekableReadStream *QuickTimeDecoder::getNextFramePacket(uint32 &descId)
 	int32 totalSampleCount = 0;
 	int32 sampleInChunk = 0;
 	int32 actualChunk = -1;
+	uint32 sampleToChunkIndex = 0;
 
 	for (uint32 i = 0; i < _tracks[_videoTrackIndex]->chunkCount; i++) {
-		int32 sampleToChunkIndex = -1;
+		if (i >= _tracks[_videoTrackIndex]->sampleToChunk[sampleToChunkIndex].first)
+			sampleToChunkIndex++;
 
-		for (uint32 j = 0; j < _tracks[_videoTrackIndex]->sampleToChunkCount; j++)
-			if (i >= _tracks[_videoTrackIndex]->sampleToChunk[j].first)
-				sampleToChunkIndex = j;
-
-		if (sampleToChunkIndex < 0)
-			error("This chunk (%d) is imaginary", sampleToChunkIndex);
-
-		totalSampleCount += _tracks[_videoTrackIndex]->sampleToChunk[sampleToChunkIndex].count;
+		totalSampleCount += _tracks[_videoTrackIndex]->sampleToChunk[sampleToChunkIndex - 1].count;
 
 		if (totalSampleCount > getCurFrame()) {
 			actualChunk = i;
-			descId = _tracks[_videoTrackIndex]->sampleToChunk[sampleToChunkIndex].id;
-			sampleInChunk = _tracks[_videoTrackIndex]->sampleToChunk[sampleToChunkIndex].count - totalSampleCount + getCurFrame();
+			descId = _tracks[_videoTrackIndex]->sampleToChunk[sampleToChunkIndex - 1].id;
+			sampleInChunk = _tracks[_videoTrackIndex]->sampleToChunk[sampleToChunkIndex - 1].count - totalSampleCount + getCurFrame();
 			break;
 		}
 	}


Commit: 3f0c9e0910e7bf7b6cd0ebb217167a6a4ce7ec31
    https://github.com/scummvm/scummvm/commit/3f0c9e0910e7bf7b6cd0ebb217167a6a4ce7ec31
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2011-10-07T08:34:56-07:00

Commit Message:
GRAPHICS: Fix PICT buffer overflow

Changed paths:
    graphics/pict.cpp



diff --git a/graphics/pict.cpp b/graphics/pict.cpp
index b2d8140..0f4dcd4 100644
--- a/graphics/pict.cpp
+++ b/graphics/pict.cpp
@@ -337,7 +337,11 @@ void PictDecoder::unpackBitsRect(Common::SeekableReadStream *stream, bool hasPal
 
 	_outputSurface = new Graphics::Surface();
 	_outputSurface->create(width, height, (bytesPerPixel == 1) ? PixelFormat::createFormatCLUT8() : _pixelFormat);
-	byte *buffer = new byte[width * height * bytesPerPixel];
+
+	// Create an temporary buffer, but allocate a bit more than we need to avoid overflow
+	// (align it to the next highest two-byte packed boundary, which may be more unpacked,
+	// as m68k and therefore QuickDraw is word-aligned)
+	byte *buffer = new byte[width * height * bytesPerPixel + (8 * 2 / packBitsData.pixMap.pixelSize)];
 
 	// Read in amount of data per row
 	for (uint16 i = 0; i < packBitsData.pixMap.bounds.height(); i++) {






More information about the Scummvm-git-logs mailing list