GRAPHICS: Rewrite PictDecoder's opcode handling
In preparation for adding support for multiple CompressedQuickTime opcodes
This commit is contained in:
parent
d5a763b763
commit
583bef28ff
2 changed files with 255 additions and 82 deletions
|
@ -45,10 +45,164 @@ PictDecoder::~PictDecoder() {
|
||||||
delete _jpeg;
|
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) {
|
Surface *PictDecoder::decodeImage(Common::SeekableReadStream *stream, byte *palette) {
|
||||||
assert(stream);
|
assert(stream);
|
||||||
|
|
||||||
|
// Initialize opcodes to their normal state
|
||||||
|
_opcodes.clear();
|
||||||
|
setupOpcodesNormal();
|
||||||
|
|
||||||
_outputSurface = 0;
|
_outputSurface = 0;
|
||||||
|
_continueParsing = true;
|
||||||
|
memset(_palette, 0, sizeof(_palette));
|
||||||
|
|
||||||
uint16 fileSize = stream->readUint16BE();
|
uint16 fileSize = stream->readUint16BE();
|
||||||
|
|
||||||
|
@ -63,70 +217,41 @@ Surface *PictDecoder::decodeImage(Common::SeekableReadStream *stream, byte *pale
|
||||||
_imageRect.bottom = stream->readUint16BE();
|
_imageRect.bottom = stream->readUint16BE();
|
||||||
_imageRect.right = stream->readUint16BE();
|
_imageRect.right = stream->readUint16BE();
|
||||||
_imageRect.debugPrint(0, "PICT Rect:");
|
_imageRect.debugPrint(0, "PICT Rect:");
|
||||||
_isPaletted = false;
|
|
||||||
|
|
||||||
// NOTE: This is only a subset of the full PICT format.
|
// 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
|
// - CompressedQuickTime (JPEG) compressed data is supported
|
||||||
// - DirectBitsRect/PackBitsRect 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();
|
uint16 opcode = stream->readUint16BE();
|
||||||
debug(2, "Found PICT opcode %04x", opcode);
|
|
||||||
|
|
||||||
if (opNum == 0 && opcode != 0x0011)
|
if (opNum == 0 && opcode != 0x0011)
|
||||||
error ("Cannot find PICT version opcode");
|
error("Cannot find PICT version opcode");
|
||||||
else if (opNum == 1 && opcode != 0x0C00)
|
else if (opNum == 1 && opcode != 0x0C00)
|
||||||
error ("Cannot find PICT header opcode");
|
error("Cannot find PICT header opcode");
|
||||||
|
|
||||||
if (opcode == 0x0000) { // Nop
|
// Since opcodes are word-aligned, we need to mark our starting
|
||||||
stream->readUint16BE(); // Unknown
|
// position here.
|
||||||
} else if (opcode == 0x0001) { // Clip
|
uint32 startPos = stream->pos();
|
||||||
// Ignore
|
|
||||||
uint16 clipSize = stream->readUint16BE();
|
for (uint32 i = 0; i < _opcodes.size(); i++) {
|
||||||
stream->seek(clipSize - 2, SEEK_CUR);
|
if (_opcodes[i].op == opcode) {
|
||||||
} else if (opcode == 0x0007) { // PnSize
|
debug(4, "Running PICT opcode %04x '%s'", opcode, _opcodes[i].desc);
|
||||||
// Ignore
|
(this->*(_opcodes[i].proc))(stream);
|
||||||
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;
|
break;
|
||||||
} else if (opcode == 0x0C00) { // HeaderOp
|
} else if (i == _opcodes.size() - 1) {
|
||||||
/* uint16 version = */ stream->readUint16BE();
|
// Unknown opcode; attempt to continue forward
|
||||||
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);
|
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 we got a palette throughout this nonsense, go and grab it
|
||||||
if (palette && _isPaletted)
|
if (palette)
|
||||||
memcpy(palette, _palette, 256 * 3);
|
memcpy(palette, _palette, 256 * 3);
|
||||||
|
|
||||||
return _outputSurface;
|
return _outputSurface;
|
||||||
|
@ -155,21 +280,18 @@ PictDecoder::PixMap PictDecoder::readPixMap(Common::SeekableReadStream *stream,
|
||||||
return pixMap;
|
return pixMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DirectBitsRectData {
|
struct PackBitsRectData {
|
||||||
PictDecoder::PixMap pixMap;
|
PictDecoder::PixMap pixMap;
|
||||||
Common::Rect srcRect;
|
Common::Rect srcRect;
|
||||||
Common::Rect dstRect;
|
Common::Rect dstRect;
|
||||||
uint16 mode;
|
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);
|
static const PixelFormat directBitsFormat16 = PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
|
||||||
|
|
||||||
// Clear the palette
|
PackBitsRectData packBitsData;
|
||||||
memset(_palette, 0, sizeof(_palette));
|
packBitsData.pixMap = readPixMap(stream, !hasPalette);
|
||||||
|
|
||||||
DirectBitsRectData directBitsData;
|
|
||||||
directBitsData.pixMap = readPixMap(stream, !hasPalette);
|
|
||||||
|
|
||||||
// Read in the palette if there is one present
|
// Read in the palette if there is one present
|
||||||
if (hasPalette) {
|
if (hasPalette) {
|
||||||
|
@ -186,47 +308,47 @@ void PictDecoder::decodeDirectBitsRect(Common::SeekableReadStream *stream, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
directBitsData.srcRect.top = stream->readUint16BE();
|
packBitsData.srcRect.top = stream->readUint16BE();
|
||||||
directBitsData.srcRect.left = stream->readUint16BE();
|
packBitsData.srcRect.left = stream->readUint16BE();
|
||||||
directBitsData.srcRect.bottom = stream->readUint16BE();
|
packBitsData.srcRect.bottom = stream->readUint16BE();
|
||||||
directBitsData.srcRect.right = stream->readUint16BE();
|
packBitsData.srcRect.right = stream->readUint16BE();
|
||||||
directBitsData.dstRect.top = stream->readUint16BE();
|
packBitsData.dstRect.top = stream->readUint16BE();
|
||||||
directBitsData.dstRect.left = stream->readUint16BE();
|
packBitsData.dstRect.left = stream->readUint16BE();
|
||||||
directBitsData.dstRect.bottom = stream->readUint16BE();
|
packBitsData.dstRect.bottom = stream->readUint16BE();
|
||||||
directBitsData.dstRect.right = stream->readUint16BE();
|
packBitsData.dstRect.right = stream->readUint16BE();
|
||||||
directBitsData.mode = stream->readUint16BE();
|
packBitsData.mode = stream->readUint16BE();
|
||||||
|
|
||||||
uint16 width = directBitsData.srcRect.width();
|
uint16 width = packBitsData.srcRect.width();
|
||||||
uint16 height = directBitsData.srcRect.height();
|
uint16 height = packBitsData.srcRect.height();
|
||||||
|
|
||||||
byte bytesPerPixel = 0;
|
byte bytesPerPixel = 0;
|
||||||
|
|
||||||
if (directBitsData.pixMap.pixelSize <= 8)
|
if (packBitsData.pixMap.pixelSize <= 8)
|
||||||
bytesPerPixel = 1;
|
bytesPerPixel = 1;
|
||||||
else if (directBitsData.pixMap.pixelSize == 32)
|
else if (packBitsData.pixMap.pixelSize == 32)
|
||||||
bytesPerPixel = 3;
|
bytesPerPixel = 3;
|
||||||
else
|
else
|
||||||
bytesPerPixel = directBitsData.pixMap.pixelSize / 8;
|
bytesPerPixel = packBitsData.pixMap.pixelSize / 8;
|
||||||
|
|
||||||
_outputSurface = new Graphics::Surface();
|
_outputSurface = new Graphics::Surface();
|
||||||
_outputSurface->create(width, height, (bytesPerPixel == 1) ? PixelFormat::createFormatCLUT8() : _pixelFormat);
|
_outputSurface->create(width, height, (bytesPerPixel == 1) ? PixelFormat::createFormatCLUT8() : _pixelFormat);
|
||||||
byte *buffer = new byte[width * height * bytesPerPixel];
|
byte *buffer = new byte[width * height * bytesPerPixel];
|
||||||
|
|
||||||
// Read in amount of data per row
|
// 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.
|
// 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
|
// In the future, we may need to have something to set the "default" packing
|
||||||
// format, but this is good for now.
|
// 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).
|
// TODO: Finish this. Hasn't been needed (yet).
|
||||||
error("Unpacked DirectBitsRect data (padded)");
|
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).
|
// TODO: Finish this. Hasn't been needed (yet).
|
||||||
error("Unpacked DirectBitsRect data (not padded)");
|
error("Unpacked DirectBitsRect data (not padded)");
|
||||||
} else if (directBitsData.pixMap.packType == 0 || directBitsData.pixMap.packType > 2) { // Packed
|
} else if (packBitsData.pixMap.packType == 0 || packBitsData.pixMap.packType > 2) { // Packed
|
||||||
uint16 byteCount = (directBitsData.pixMap.rowBytes > 250) ? stream->readUint16BE() : stream->readByte();
|
uint16 byteCount = (packBitsData.pixMap.rowBytes > 250) ? stream->readUint16BE() : stream->readByte();
|
||||||
decodeDirectBitsLine(buffer + i * _outputSurface->w * bytesPerPixel, directBitsData.pixMap.rowBytes, stream->readStream(byteCount), directBitsData.pixMap.pixelSize, bytesPerPixel);
|
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;
|
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;
|
uint32 dataDecoded = 0;
|
||||||
byte bytesPerDecode = (bytesPerPixel == 2) ? 2 : 1;
|
byte bytesPerDecode = (bytesPerPixel == 2) ? 2 : 1;
|
||||||
|
|
||||||
|
@ -299,11 +421,16 @@ void PictDecoder::decodeDirectBitsLine(byte *out, uint32 length, Common::Seekabl
|
||||||
dataDecoded += length / 4;
|
dataDecoded += length / 4;
|
||||||
|
|
||||||
if (length != dataDecoded)
|
if (length != dataDecoded)
|
||||||
warning("Mismatched DirectBits read (%d/%d)", dataDecoded, length);
|
warning("Mismatched PackBits read (%d/%d)", dataDecoded, length);
|
||||||
|
|
||||||
delete data;
|
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) {
|
void PictDecoder::outputPixelBuffer(byte *&out, byte value, byte bitsPerPixel) {
|
||||||
switch (bitsPerPixel) {
|
switch (bitsPerPixel) {
|
||||||
case 1:
|
case 1:
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#ifndef GRAPHICS_PICT_H
|
#ifndef GRAPHICS_PICT_H
|
||||||
#define GRAPHICS_PICT_H
|
#define GRAPHICS_PICT_H
|
||||||
|
|
||||||
|
#include "common/array.h"
|
||||||
#include "common/rect.h"
|
#include "common/rect.h"
|
||||||
#include "common/scummsys.h"
|
#include "common/scummsys.h"
|
||||||
|
|
||||||
|
@ -37,6 +38,8 @@ namespace Graphics {
|
||||||
class JPEG;
|
class JPEG;
|
||||||
struct Surface;
|
struct Surface;
|
||||||
|
|
||||||
|
#define DECLARE_OPCODE(x) void x(Common::SeekableReadStream *stream)
|
||||||
|
|
||||||
class PictDecoder {
|
class PictDecoder {
|
||||||
public:
|
public:
|
||||||
PictDecoder(Graphics::PixelFormat pixelFormat);
|
PictDecoder(Graphics::PixelFormat pixelFormat);
|
||||||
|
@ -70,13 +73,56 @@ private:
|
||||||
byte _palette[256 * 3];
|
byte _palette[256 * 3];
|
||||||
bool _isPaletted;
|
bool _isPaletted;
|
||||||
Graphics::Surface *_outputSurface;
|
Graphics::Surface *_outputSurface;
|
||||||
|
bool _continueParsing;
|
||||||
|
|
||||||
void decodeDirectBitsRect(Common::SeekableReadStream *stream, bool hasPalette);
|
// Utility Functions
|
||||||
void decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bitsPerPixel, byte bytesPerPixel);
|
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 decodeCompressedQuickTime(Common::SeekableReadStream *stream);
|
||||||
void outputPixelBuffer(byte *&out, byte value, byte bitsPerPixel);
|
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
|
} // End of namespace Graphics
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue