[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