mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-15 14:18:37 +00:00
SCI: Merged the cel data unpacking code for views and pictures
This commit is contained in:
parent
0b24fc3acc
commit
d2ad7898d9
@ -224,19 +224,20 @@ void GfxPicture::drawSci32Vga(int16 celNo, int16 drawX, int16 drawY, int16 pictu
|
||||
}
|
||||
#endif
|
||||
|
||||
extern void unpackCelData(byte *inBuffer, byte *celBitmap, byte clearColor, int pixelCount, int rlePos, int literalPos, ViewType viewType, uint16 width, bool isMacSci11ViewData);
|
||||
|
||||
void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 drawX, int16 drawY, int16 pictureX) {
|
||||
byte *celBitmap = NULL;
|
||||
byte *ptr = NULL;
|
||||
byte *headerPtr = inbuffer + headerPos;
|
||||
byte *rlePtr = inbuffer + rlePos;
|
||||
byte *literalPtr = inbuffer + literalPos;
|
||||
int16 displaceX, displaceY;
|
||||
byte priority = _addToFlag ? _priority : 0;
|
||||
byte clearColor;
|
||||
bool compression = true;
|
||||
byte curByte, runLength;
|
||||
byte curByte;
|
||||
int16 y, lastY, x, leftX, rightX;
|
||||
int pixelNr, pixelCount;
|
||||
int pixelCount;
|
||||
uint16 width, height;
|
||||
|
||||
#ifdef ENABLE_SCI32
|
||||
@ -247,12 +248,11 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
|
||||
height = READ_LE_UINT16(headerPtr + 2);
|
||||
displaceX = (signed char)headerPtr[4];
|
||||
displaceY = (unsigned char)headerPtr[5];
|
||||
if (_resourceType == SCI_PICTURE_TYPE_SCI11) {
|
||||
if (_resourceType == SCI_PICTURE_TYPE_SCI11)
|
||||
// SCI1.1 uses hardcoded clearcolor for pictures, even if cel header specifies otherwise
|
||||
clearColor = _screen->getColorWhite();
|
||||
} else {
|
||||
else
|
||||
clearColor = headerPtr[6];
|
||||
}
|
||||
#ifdef ENABLE_SCI32
|
||||
} else {
|
||||
width = READ_SCI11ENDIAN_UINT16(headerPtr + 0);
|
||||
@ -268,91 +268,18 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
|
||||
if (displaceX || displaceY)
|
||||
error("unsupported embedded cel-data in picture");
|
||||
|
||||
// We will unpack cel-data into a temporary buffer and then plot it to screen
|
||||
// That needs to be done cause a mirrored picture may be requested
|
||||
pixelCount = width * height;
|
||||
celBitmap = new byte[pixelCount];
|
||||
if (!celBitmap)
|
||||
error("Unable to allocate temporary memory for picture drawing");
|
||||
|
||||
if (compression) {
|
||||
// We will unpack cel-data into a temporary buffer and then plot it to screen
|
||||
// That needs to be done cause a mirrored picture may be requested
|
||||
memset(celBitmap, clearColor, pixelCount);
|
||||
pixelNr = 0;
|
||||
ptr = celBitmap;
|
||||
if (literalPos == 0) {
|
||||
// decompression for data that has only one stream (vecor embedded view data)
|
||||
switch (_resMan->getViewType()) {
|
||||
case kViewEga:
|
||||
while (pixelNr < pixelCount) {
|
||||
curByte = *rlePtr++;
|
||||
runLength = curByte >> 4;
|
||||
memset(ptr + pixelNr, curByte & 0x0F, MIN<uint16>(runLength, pixelCount - pixelNr));
|
||||
pixelNr += runLength;
|
||||
}
|
||||
break;
|
||||
case kViewVga:
|
||||
case kViewVga11:
|
||||
while (pixelNr < pixelCount) {
|
||||
curByte = *rlePtr++;
|
||||
runLength = curByte & 0x3F;
|
||||
switch (curByte & 0xC0) {
|
||||
case 0: // copy bytes as-is
|
||||
while (runLength-- && pixelNr < pixelCount)
|
||||
ptr[pixelNr++] = *rlePtr++;
|
||||
break;
|
||||
case 0x80: // fill with color
|
||||
memset(ptr + pixelNr, *rlePtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
|
||||
pixelNr += runLength;
|
||||
break;
|
||||
case 0xC0: // fill with transparent
|
||||
pixelNr += runLength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kViewAmiga:
|
||||
while (pixelNr < pixelCount) {
|
||||
curByte = *rlePtr++;
|
||||
if (curByte & 0x07) { // fill with color
|
||||
runLength = curByte & 0x07;
|
||||
curByte = curByte >> 3;
|
||||
while (runLength-- && pixelNr < pixelCount) {
|
||||
ptr[pixelNr++] = curByte;
|
||||
}
|
||||
} else { // fill with transparent
|
||||
runLength = curByte >> 3;
|
||||
pixelNr += runLength;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Unsupported picture viewtype");
|
||||
}
|
||||
} else {
|
||||
// decompression for data that has two separate streams (probably SCI 1.1 picture)
|
||||
while (pixelNr < pixelCount) {
|
||||
curByte = *rlePtr++;
|
||||
runLength = curByte & 0x3F;
|
||||
switch (curByte & 0xC0) {
|
||||
case 0: // copy bytes as-is
|
||||
while (runLength-- && pixelNr < pixelCount)
|
||||
ptr[pixelNr++] = *literalPtr++;
|
||||
break;
|
||||
case 0x80: // fill with color
|
||||
memset(ptr + pixelNr, *literalPtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
|
||||
pixelNr += runLength;
|
||||
break;
|
||||
case 0xC0: // fill with transparent
|
||||
pixelNr += runLength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (compression)
|
||||
unpackCelData(inbuffer, celBitmap, clearColor, pixelCount, rlePos, literalPos, _resMan->getViewType(), width, false);
|
||||
else
|
||||
// No compression (some SCI32 pictures)
|
||||
memcpy(celBitmap, rlePtr, pixelCount);
|
||||
}
|
||||
|
||||
Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea();
|
||||
|
||||
|
@ -370,22 +370,120 @@ void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int1
|
||||
outRect.top = outRect.bottom - scaledHeight;
|
||||
}
|
||||
|
||||
void unpackCelData(byte *inBuffer, byte *celBitmap, byte clearColor, int pixelCount, int rlePos, int literalPos, ViewType viewType, uint16 width, bool isMacSci11ViewData) {
|
||||
byte *outPtr = celBitmap;
|
||||
byte curByte, runLength;
|
||||
byte *rlePtr = inBuffer + rlePos;
|
||||
byte *literalPtr = inBuffer + literalPos;
|
||||
int pixelNr = 0;
|
||||
|
||||
memset(celBitmap, clearColor, pixelCount);
|
||||
|
||||
if (!literalPos) {
|
||||
// decompression for data that has only one combined stream
|
||||
switch (viewType) {
|
||||
case kViewEga:
|
||||
while (pixelNr < pixelCount) {
|
||||
curByte = *rlePtr++;
|
||||
runLength = curByte >> 4;
|
||||
memset(outPtr + pixelNr, curByte & 0x0F, MIN<uint16>(runLength, pixelCount - pixelNr));
|
||||
pixelNr += runLength;
|
||||
}
|
||||
break;
|
||||
case kViewAmiga:
|
||||
while (pixelNr < pixelCount) {
|
||||
curByte = *rlePtr++;
|
||||
if (curByte & 0x07) { // fill with color
|
||||
runLength = curByte & 0x07;
|
||||
curByte = curByte >> 3;
|
||||
while (runLength-- && pixelNr < pixelCount) {
|
||||
outPtr[pixelNr++] = curByte;
|
||||
}
|
||||
} else { // fill with transparent
|
||||
runLength = curByte >> 3;
|
||||
pixelNr += runLength;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kViewVga:
|
||||
case kViewVga11:
|
||||
while (pixelNr < pixelCount) {
|
||||
curByte = *rlePtr++;
|
||||
runLength = curByte & 0x3F;
|
||||
switch (curByte & 0xC0) {
|
||||
case 0: // copy bytes as-is
|
||||
while (runLength-- && pixelNr < pixelCount)
|
||||
outPtr[pixelNr++] = *rlePtr++;
|
||||
break;
|
||||
case 0x40: // copy bytes as is (In copy case, runLength can go upto 127 i.e. pixel & 0x40). Fixes bug #3135872.
|
||||
runLength += 64;
|
||||
break;
|
||||
case 0x80: // fill with color
|
||||
memset(outPtr + pixelNr, *rlePtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
|
||||
pixelNr += runLength;
|
||||
break;
|
||||
case 0xC0: // fill with transparent
|
||||
pixelNr += runLength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error("Unsupported picture viewtype");
|
||||
}
|
||||
} else {
|
||||
if (isMacSci11ViewData) {
|
||||
// KQ6/Freddy Pharkas use byte lengths, all others use uint16
|
||||
// The SCI devs must have realized that a max of 255 pixels wide
|
||||
// was not very good for 320 or 640 width games.
|
||||
bool hasByteLengths = (g_sci->getGameId() == GID_KQ6 || g_sci->getGameId() == GID_FREDDYPHARKAS);
|
||||
|
||||
// compression for SCI1.1+ Mac
|
||||
while (pixelNr < pixelCount) {
|
||||
uint32 pixelLine = pixelNr;
|
||||
|
||||
if (hasByteLengths) {
|
||||
pixelNr += *rlePtr++;
|
||||
runLength = *rlePtr++;
|
||||
} else {
|
||||
pixelNr += READ_BE_UINT16(rlePtr);
|
||||
runLength = READ_BE_UINT16(rlePtr + 2);
|
||||
rlePtr += 4;
|
||||
}
|
||||
|
||||
while (runLength-- && pixelNr < pixelCount)
|
||||
outPtr[pixelNr++] = *literalPtr++;
|
||||
|
||||
pixelNr = pixelLine + width;
|
||||
}
|
||||
}
|
||||
// decompression for data that has two separate streams (probably SCI 1.1 view)
|
||||
while (pixelNr < pixelCount) {
|
||||
curByte = *rlePtr++;
|
||||
runLength = curByte & 0x3F;
|
||||
switch (curByte & 0xC0) {
|
||||
case 0: // copy bytes as-is
|
||||
while (runLength-- && pixelNr < pixelCount)
|
||||
outPtr[pixelNr++] = *literalPtr++;
|
||||
break;
|
||||
case 0x80: // fill with color
|
||||
memset(outPtr + pixelNr, *literalPtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
|
||||
pixelNr += runLength;
|
||||
break;
|
||||
case 0xC0: // fill with transparent
|
||||
pixelNr += runLength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount) {
|
||||
const CelInfo *celInfo = getCelInfo(loopNo, celNo);
|
||||
byte *rlePtr;
|
||||
byte *literalPtr;
|
||||
uint32 pixelNo = 0, runLength;
|
||||
byte pixel;
|
||||
|
||||
if (celInfo->offsetEGA) {
|
||||
// decompression for EGA views
|
||||
literalPtr = _resourceData + _loop[loopNo].cel[celNo].offsetEGA;
|
||||
while (pixelNo < pixelCount) {
|
||||
pixel = *literalPtr++;
|
||||
runLength = pixel >> 4;
|
||||
memset(outPtr + pixelNo, pixel & 0x0F, MIN<uint32>(runLength, pixelCount - pixelNo));
|
||||
pixelNo += runLength;
|
||||
}
|
||||
unpackCelData(_resourceData, outPtr, 0, pixelCount, celInfo->offsetEGA, 0, _resMan->getViewType(), celInfo->width, false);
|
||||
} else {
|
||||
// We fill the buffer with transparent pixels, so that we can later skip
|
||||
// over pixels to automatically have them transparent
|
||||
@ -408,100 +506,8 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou
|
||||
clearColor = 0;
|
||||
}
|
||||
|
||||
memset(outPtr, clearColor, pixelCount);
|
||||
|
||||
rlePtr = _resourceData + celInfo->offsetRLE;
|
||||
if (!celInfo->offsetLiteral) { // no additional literal data
|
||||
if (_resMan->getViewType() == kViewAmiga) {
|
||||
// decompression for amiga views
|
||||
while (pixelNo < pixelCount) {
|
||||
pixel = *rlePtr++;
|
||||
if (pixel & 0x07) { // fill with color
|
||||
runLength = pixel & 0x07;
|
||||
pixel = pixel >> 3;
|
||||
while (runLength-- && pixelNo < pixelCount) {
|
||||
outPtr[pixelNo++] = pixel;
|
||||
}
|
||||
} else { // fill with transparent
|
||||
runLength = pixel >> 3;
|
||||
pixelNo += runLength;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// decompression for data that has just one combined stream
|
||||
while (pixelNo < pixelCount) {
|
||||
pixel = *rlePtr++;
|
||||
runLength = pixel & 0x3F;
|
||||
switch (pixel & 0xC0) {
|
||||
case 0x40: // copy bytes as is (In copy case, runLength can go upto 127 i.e. pixel & 0x40)
|
||||
runLength += 64;
|
||||
case 0x00: // copy bytes as-is
|
||||
while (runLength-- && pixelNo < pixelCount)
|
||||
outPtr[pixelNo++] = *rlePtr++;
|
||||
break;
|
||||
case 0x80: // fill with color
|
||||
memset(outPtr + pixelNo, *rlePtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
|
||||
pixelNo += runLength;
|
||||
break;
|
||||
case 0xC0: // fill with transparent
|
||||
pixelNo += runLength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
literalPtr = _resourceData + celInfo->offsetLiteral;
|
||||
if (celInfo->offsetRLE) {
|
||||
if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() == SCI_VERSION_1_1) {
|
||||
// KQ6/Freddy Pharkas use byte lengths, all others use uint16
|
||||
// The SCI devs must have realized that a max of 255 pixels wide
|
||||
// was not very good for 320 or 640 width games.
|
||||
bool hasByteLengths = (g_sci->getGameId() == GID_KQ6 || g_sci->getGameId() == GID_FREDDYPHARKAS);
|
||||
|
||||
// compression for SCI1.1+ Mac
|
||||
while (pixelNo < pixelCount) {
|
||||
uint32 pixelLine = pixelNo;
|
||||
|
||||
if (hasByteLengths) {
|
||||
pixelNo += *rlePtr++;
|
||||
runLength = *rlePtr++;
|
||||
} else {
|
||||
pixelNo += READ_BE_UINT16(rlePtr);
|
||||
runLength = READ_BE_UINT16(rlePtr + 2);
|
||||
rlePtr += 4;
|
||||
}
|
||||
|
||||
while (runLength-- && pixelNo < pixelCount)
|
||||
outPtr[pixelNo++] = *literalPtr++;
|
||||
|
||||
pixelNo = pixelLine + celInfo->width;
|
||||
}
|
||||
} else {
|
||||
// decompression for data that has separate rle and literal streams
|
||||
while (pixelNo < pixelCount) {
|
||||
pixel = *rlePtr++;
|
||||
runLength = pixel & 0x3F;
|
||||
switch (pixel & 0xC0) {
|
||||
case 0: // copy bytes as-is
|
||||
while (runLength-- && pixelNo < pixelCount)
|
||||
outPtr[pixelNo++] = *literalPtr++;
|
||||
break;
|
||||
case 0x80: // fill with color
|
||||
memset(outPtr + pixelNo, *literalPtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
|
||||
pixelNo += runLength;
|
||||
break;
|
||||
case 0xC0: // fill with transparent
|
||||
pixelNo += runLength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// literal stream only, so no compression
|
||||
memcpy(outPtr, literalPtr, pixelCount);
|
||||
pixelNo = pixelCount;
|
||||
}
|
||||
}
|
||||
bool isMacSci11ViewData = g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() == SCI_VERSION_1_1;
|
||||
unpackCelData(_resourceData, outPtr, clearColor, pixelCount, celInfo->offsetRLE, celInfo->offsetLiteral, _resMan->getViewType(), celInfo->width, isMacSci11ViewData);
|
||||
|
||||
// Swap 0 and 0xff pixels for Mac SCI1.1+ games (see above)
|
||||
if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) {
|
||||
|
Loading…
Reference in New Issue
Block a user