scummvm/engines/scumm/he/gfx_primitives_he.cpp
AndywinXp 32a9265ba4 SCUMM: HE: Fix the majority of endianness issues on graphics
The system is about 80% fixed, and as usual the remaining 20%
is taking way too much to fix...

Anyhow this fixes all endianness/gfx related crashes we had up
until now, and properly implement all the hard stuff, such as:
* Transparency effects
* Additive/subtractive color effects
* Weird transitions

Still, there are some very minor glitches here and there
and I couldn't find the reason for those. But the games are
now very playable and without crashes.
2024-11-30 10:30:40 +01:00

2064 lines
58 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifdef ENABLE_HE
#include "common/system.h"
#include "scumm/he/intern_he.h"
#include "scumm/he/wiz_he.h"
namespace Scumm {
int Wiz::pgReadPixel(const WizSimpleBitmap *srcBM, int x, int y, int defaultValue) {
if ((x < 0) || (y < 0) || (x >= srcBM->bitmapWidth) || (y >= srcBM->bitmapHeight)) {
return defaultValue;
} else {
if (_uses16BitColor) {
return FROM_LE_16(*(((WizRawPixel16 *)srcBM->bufferPtr()) + y * srcBM->bitmapWidth + x));
} else {
return *(((WizRawPixel8 *)srcBM->bufferPtr()) + y * srcBM->bitmapWidth + x);
}
}
}
void Wiz::pgWritePixel(WizSimpleBitmap *srcBM, int x, int y, WizRawPixel value) {
if ((x >= 0) && (y >= 0) && (x < srcBM->bitmapWidth) && (y < srcBM->bitmapHeight)) {
if (_uses16BitColor) {
*(((WizRawPixel16 *)srcBM->bufferPtr()) + y * srcBM->bitmapWidth + x) = FROM_LE_16(value);
} else {
*(((WizRawPixel8 *)srcBM->bufferPtr()) + y * srcBM->bitmapWidth + x) = value;
}
}
}
void Wiz::pgClippedWritePixel(WizSimpleBitmap *srcBM, int x, int y, const Common::Rect *clipRectPtr, WizRawPixel value) {
if ((x >= clipRectPtr->left) && (y >= clipRectPtr->top) && (x <= clipRectPtr->right) && (y <= clipRectPtr->bottom)) {
if (_uses16BitColor) {
*(((WizRawPixel16 *)srcBM->bufferPtr()) + y * srcBM->bitmapWidth + x) = FROM_LE_16(value);
} else {
*(((WizRawPixel8 *)srcBM->bufferPtr()) + y * srcBM->bitmapWidth + x) = value;
}
}
}
#define GET_SIGN(x) ((x) > 0 ? 1 : ((x) == 0 ? 0 : (-1)))
void Wiz::pgClippedLineDraw(WizSimpleBitmap *destBM, int asx, int asy, int aex, int aey, const Common::Rect *clipRectPtr, WizRawPixel value) {
int x1, y1, x2, y2, d, dx, dy, sx, sy, incrA, incrB;
x1 = asx;
y1 = asy;
x2 = aex;
y2 = aey;
sx = GET_SIGN(x2 - x1);
sy = GET_SIGN(y2 - y1);
dx = abs(x2 - x1);
dy = abs(y2 - y1);
pgClippedWritePixel(destBM, x1, y1, clipRectPtr, value);
if (dx >= dy) {
d = (dy * 2) - dx;
incrA = dy * 2;
incrB = (dy - dx) * 2;
while (x1 != x2) {
if (d <= 0) {
d += incrA;
} else {
d += incrB;
y1 += sy;
}
x1 += sx;
pgClippedWritePixel(destBM, x1, y1, clipRectPtr, value);
}
} else {
d = (dx * 2) - dy;
incrA = dx * 2;
incrB = (dx - dy) * 2;
while (y1 != y2) {
if (d <= 0) {
d += incrA;
} else {
d += incrB;
x1 += sx;
}
y1 += sy;
pgClippedWritePixel(destBM, x1, y1, clipRectPtr, value);
}
}
}
#undef GET_SIGN
struct WizScanLine {
int iXMin;
int iXMax;
};
int scanEdge(WizScanLine *aScanLines, int iScanLineStart, bool bLeftSide, int iX1, int iY1, int iX2, int iY2) {
int iCurScanLine = iScanLineStart;
int iDX, iDY;
double fInverseSlope;
// Get deltas...
iDX = iX2 - iX1;
iDY = iY2 - iY1;
// Protect against horizontal lines...
if (iDY <= 0) {
return 0;
}
// Calculate inverse slope...
fInverseSlope = (double)iDX / (double)iDY;
for (int iY = iY1; iY < iY2; ++iY) {
if (bLeftSide) {
aScanLines[iCurScanLine].iXMin = iX1 + (int)(ceil((iY - iY1) * fInverseSlope));
} else {
aScanLines[iCurScanLine].iXMax = iX1 + (int)(ceil((iY - iY1) * fInverseSlope));
}
++iCurScanLine;
}
return iCurScanLine;
}
void Wiz::pgClippedThickLineDraw(WizSimpleBitmap *destBM, int asx, int asy, int aex, int aey, const Common::Rect *clipRectPtr, int iLineThickness, WizRawPixel value) {
int iDX = aex - asx;
int iDY = aey - asy;
double fDistance = sqrt((iDX * iDX) + (iDY * iDY));
// If distance is 0, don't draw...
if (fDistance == 0) {
return;
}
// The ratio of half the line thickness to the length of the line...
double fScale = (double)(iLineThickness) / (2 * fDistance);
// The x and y increments from an endpoint needed to create a rectangle...
float fDDX = -fScale * (float)iDY;
float fDDY = fScale * (float)iDX;
if (fDDX > 0) { // Round off
fDDX += 0.5;
} else {
fDDX -= 0.5;
}
if (fDDY > 0) {
fDDY += 0.5;
} else {
fDDY -= 0.5;
}
int iCompDX = (int)fDDX;
int iCompDY = (int)fDDY;
int aSortOrder[4] = { 0, 0, 0, 0 };
// Determine point order of polygons based on line orientation
// topmost (and topleft in case of x or y = 0)...
if ((iDX >= 0) && (iDY < 0)) {
aSortOrder[0] = 1;
aSortOrder[1] = 2;
aSortOrder[2] = 0;
aSortOrder[3] = 3;
}
if ((iDX > 0) && (iDY >= 0)) {
aSortOrder[0] = 0;
aSortOrder[1] = 1;
aSortOrder[2] = 3;
aSortOrder[3] = 2;
}
if ((iDX <= 0) && (iDY > 0)) {
aSortOrder[0] = 3;
aSortOrder[1] = 0;
aSortOrder[2] = 2;
aSortOrder[3] = 1;
}
if ((iDX < 0) && (iDY <= 0)) {
aSortOrder[0] = 2;
aSortOrder[1] = 3;
aSortOrder[2] = 1;
aSortOrder[3] = 0;
}
// Now we can compute the corner points...
int xPoints[4];
int yPoints[4];
xPoints[aSortOrder[0]] = asx - iCompDX;
yPoints[aSortOrder[0]] = asy - iCompDY;
xPoints[aSortOrder[1]] = asx + iCompDX;
yPoints[aSortOrder[1]] = asy + iCompDY;
xPoints[aSortOrder[2]] = aex - iCompDX;
yPoints[aSortOrder[2]] = aey - iCompDY;
xPoints[aSortOrder[3]] = aex + iCompDX;
yPoints[aSortOrder[3]] = aey + iCompDY;
// Determine how tall (how many scan lines) the polygon is...
int iNumScanLines = yPoints[2] - yPoints[0];
// Create scan line list...
WizScanLine *aScanLines = new WizScanLine[iNumScanLines];
// Scan left side...
int iNextScanLine = scanEdge(aScanLines, 0, true, xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
scanEdge(aScanLines, iNextScanLine, true, xPoints[1], yPoints[1], xPoints[2], yPoints[2]);
// Scan right side...
iNextScanLine = scanEdge(aScanLines, 0, false, xPoints[0], yPoints[0], xPoints[3], yPoints[3]);
scanEdge(aScanLines, iNextScanLine, false, xPoints[3], yPoints[3], xPoints[2], yPoints[2]);
// Draw polygon...
int iCurX, iCurY;
for (int iWhichScanLine = 0; iWhichScanLine < iNumScanLines; ++iWhichScanLine) {
iCurY = iWhichScanLine + yPoints[0];
for (iCurX = aScanLines[iWhichScanLine].iXMin; iCurX < aScanLines[iWhichScanLine].iXMax; ++iCurX) {
pgClippedWritePixel(destBM, iCurX, iCurY, clipRectPtr, value);
}
}
delete[] aScanLines;
}
int convertToFixed(int iNumber) {
return (iNumber << kWECFixedSize);
}
int convertFromFixed(int iFixedNumber) {
return (iFixedNumber >> kWECFixedSize);
}
void Wiz::pgDrawClippedEllipse(WizSimpleBitmap *pDestBitmap, int iPX, int iPY, int iQX, int iQY, int iKX, int iKY, int iLOD, const Common::Rect *pClipRectPtr, int iThickness, WizRawPixel aColor) {
// Since this is fixed point, limit the LOD to 14 bits precision...
if (iLOD > kWECFixedSize - 2) {
iLOD = kWECFixedSize - 2;
}
// Determine the rest of the rectangle verts using the midpoint formula...
int iKX1 = (2 * iQX) - iKX;
int iKY1 = (2 * iQY) - iKY;
int iKX3 = (2 * iPX) - iKX;
int iKY3 = (2 * iPY) - iKY;
int iKX2 = iKX1 - (iKX - iKX3);
int iKY2 = iKY1 + (iKY3 - iKY);
int iOpPX = (iKX1 + iKX2) / 2;
int iOpPY = (iKY1 + iKY2) / 2;
int iOpQX = (iKX3 + iKX2) / 2;
int iOpQY = (iKY3 + iKY2) / 2;
bool bFirstPass = true;
int x1 = 0, y1 = 0, x2 = 0, y2 = 0, iFirstX = 0, iFirstY = 0;
// Loop through each quadrant...
for (int iSide = 0; iSide < 4; ++iSide) {
int xP = 0, yP = 0, xQ = 0, yQ = 0, xK = 0, yK = 0;
// Determine quadrant and convert input to fixed point...
switch (iSide) {
case 0:
xP = convertToFixed(iPX);
yP = convertToFixed(iPY);
xQ = convertToFixed(iQX);
yQ = convertToFixed(iQY);
xK = convertToFixed(iKX);
yK = convertToFixed(iKY);
break;
case 1:
xP = convertToFixed(iQX);
yP = convertToFixed(iQY);
xQ = convertToFixed(iOpPX);
yQ = convertToFixed(iOpPY);
xK = convertToFixed(iKX1);
yK = convertToFixed(iKY1);
break;
case 2:
xP = convertToFixed(iOpPX);
yP = convertToFixed(iOpPY);
xQ = convertToFixed(iOpQX);
yQ = convertToFixed(iOpQY);
xK = convertToFixed(iKX2);
yK = convertToFixed(iKY2);
break;
case 3:
xP = convertToFixed(iOpQX);
yP = convertToFixed(iOpQY);
xQ = convertToFixed(iPX);
yQ = convertToFixed(iPY);
xK = convertToFixed(iKX3);
yK = convertToFixed(iKY3);
break;
}
int vx, ux, vy, uy, w, xJ, yJ;
vx = xK - xQ; // Displacements from center...
ux = xK - xP;
vy = yK - yQ;
uy = yK - yP;
xJ = xP - vx + kWECHalf; // Center of ellipse J...
yJ = yP - vy + kWECHalf;
ux -= (w = ux >> (2 * iLOD + 3)); // Cancel 2nd-order error...
ux -= (w >>= (2 * iLOD + 4)); // Cancel 4th-order error...
ux -= w >> (2 * iLOD + 3); // Cancel 6th-order error...
ux += vx >> (iLOD + 1); // Cancel 1st-order error...
uy -= (w = uy >> (2 * iLOD + 3)); // Cancel 2nd-order error...
uy -= (w >>= (2 * iLOD + 4)); // Cancel 4th-order error...
uy -= w >> (2 * iLOD + 3); // Cancel 6th-order error...
uy += vy >> (iLOD + 1); // Cancel 1st-order error...
for (int i = (kWECPiOver2 << iLOD) >> 16; i >= 0; --i) {
x2 = (xJ + vx) >> 16;
y2 = (yJ + vy) >> 16;
if (bFirstPass) {
x1 = x2;
y1 = y2;
iFirstX = x1;
iFirstY = y1;
bFirstPass = false;
} else {
if (iThickness > 0) {
pgClippedThickLineDraw(pDestBitmap, x1, y1, x2, y2, pClipRectPtr, 5, aColor);
} else {
// Specific to print pack, should be moved to a thick pixel...
pgClippedWritePixel(pDestBitmap, x2, y2, pClipRectPtr, aColor);
pgClippedWritePixel(pDestBitmap, x2 + 1, y2, pClipRectPtr, aColor);
pgClippedWritePixel(pDestBitmap, x2 - 1, y2, pClipRectPtr, aColor);
pgClippedWritePixel(pDestBitmap, x2, y2 + 1, pClipRectPtr, aColor);
pgClippedWritePixel(pDestBitmap, x2, y2 - 1, pClipRectPtr, aColor);
pgClippedWritePixel(pDestBitmap, x2 + 1, y2 + 1, pClipRectPtr, aColor);
pgClippedWritePixel(pDestBitmap, x2 + 1, y2 - 1, pClipRectPtr, aColor);
pgClippedWritePixel(pDestBitmap, x2 - 1, y2 + 1, pClipRectPtr, aColor);
pgClippedWritePixel(pDestBitmap, x2 - 1, y2 - 1, pClipRectPtr, aColor);
}
x1 = x2;
y1 = y2;
}
ux -= vx >> iLOD;
vx += ux >> iLOD;
uy -= vy >> iLOD;
vy += uy >> iLOD;
}
}
if (iThickness > 0) {
pgClippedThickLineDraw(pDestBitmap, x2, y2, iFirstX, iFirstY, pClipRectPtr, 5, aColor);
} else {
pgClippedLineDraw(pDestBitmap, x2, y2, iFirstX, iFirstY, pClipRectPtr, aColor);
}
}
void Wiz::pgDrawSolidRect(WizSimpleBitmap *destBM, const Common::Rect *rectPtr, WizRawPixel color) {
WizRawPixel16 *d16bit;
WizRawPixel8 *d8bit;
int cw, dw, ch;
int x1 = rectPtr->left, y1 = rectPtr->top, x2 = rectPtr->right, y2 = rectPtr->bottom;
// Common calcs...
dw = destBM->bitmapWidth;
cw = x2 - x1 + 1;
ch = y2 - y1 + 1;
d16bit = ((WizRawPixel16 *)destBM->bufferPtr()) + y1 * dw + x1;
d8bit = ((WizRawPixel8 *)destBM->bufferPtr()) + y1 * dw + x1;
if (cw > 1) {
while (--ch >= 0) {
if (_uses16BitColor) {
for (int i = 0; i < cw; i++)
WRITE_LE_UINT16(&d16bit[i], color);
d16bit += dw;
} else {
memset(d8bit, color, cw);
d8bit += dw;
}
}
} else {
while (--ch >= 0) {
if (_uses16BitColor) {
*d16bit = color;
d16bit += dw;
} else {
*d8bit = color;
d8bit += dw;
}
}
}
}
void Wiz::pgFloodFillCmd(int x, int y, int color, const Common::Rect *optionalClipRect) {
Common::Rect updateRect;
WizSimpleBitmap fakeBitmap;
int colorToWrite;
// Setup the bitmap...
int32 colorBackMask = _vm->_game.heversion > 99 ? 0x01000000 : 0x8000;
pgSimpleBitmapFromDrawBuffer(&fakeBitmap, (color & colorBackMask) != 0);
// Strip the color info down...
colorToWrite = getRawPixel(color);
// Call the primitive...
updateRect.left = updateRect.top = 12345;
updateRect.right = updateRect.bottom = -12345;
_vm->VAR(_vm->VAR_OPERATION_FAILURE) = floodSimpleFill(
&fakeBitmap, x, y, colorToWrite, optionalClipRect, &updateRect);
if (isRectValid(updateRect)) {
if (color & colorBackMask) {
_vm->backgroundToForegroundBlit(updateRect);
} else {
updateRect.bottom++;
_vm->markRectAsDirty(kMainVirtScreen, updateRect);
}
}
}
void Wiz::pgHistogramBitmapSubRect(int *tablePtr, const WizSimpleBitmap *bitmapPtr, const Common::Rect *sourceRect) {
if (!_uses16BitColor) {
Common::Rect rect, clipRect;
WizRawPixel8 *srcPtr;
int off, h, w, x;
rect = *sourceRect;
clipRect.left = 0;
clipRect.top = 0;
clipRect.right = (bitmapPtr->bitmapWidth - 1);
clipRect.bottom = (bitmapPtr->bitmapHeight - 1);
if (findRectOverlap(&rect, &clipRect)) {
srcPtr = ((WizRawPixel8 *)bitmapPtr->bufferPtr()) + bitmapPtr->bitmapWidth * rect.top + rect.left;
w = getRectWidth(&rect);
h = getRectHeight(&rect);
off = bitmapPtr->bitmapWidth - w;
while (--h >= 0) {
for (x = w; --x >= 0;) {
*(tablePtr + *srcPtr++) += 1;
}
srcPtr += off;
}
}
}
}
void Wiz::pgSimpleBitmapFromDrawBuffer(WizSimpleBitmap *bitmapPtr, bool background) {
VirtScreen *vs = &_vm->_virtscr[kMainVirtScreen];
bitmapPtr->bitmapWidth = vs->w;
bitmapPtr->bitmapHeight = vs->h;
if (background) {
bitmapPtr->bufferPtr = WizPxShrdBuffer(vs->getBackPixels(0, vs->topline), false);
} else {
bitmapPtr->bufferPtr = WizPxShrdBuffer(vs->getPixels(0, vs->topline), false);
}
}
bool Wiz::pgGetMultiTypeBitmapFromDrawBuffer(WizMultiTypeBitmap *multiBM, bool background) {
VirtScreen *vs = &_vm->_virtscr[kMainVirtScreen];
int pixelSize = _uses16BitColor ? sizeof(WizRawPixel16) : sizeof(WizRawPixel8);
multiBM->width = vs->w;
multiBM->height = vs->h;
multiBM->stride = (multiBM->width * pixelSize);
multiBM->format = _uses16BitColor ? 555 : 8;
multiBM->bpp = (pixelSize * 8);
if (background) {
multiBM->data = (byte *)vs->getBackPixels(0, vs->topline);
} else {
multiBM->data = (byte *)vs->getPixels(0, vs->topline);
}
return true;
}
void Wiz::pgDrawRawDataFormatImage(WizRawPixel *bufferPtr, const WizRawPixel *rawData, int bufferWidth, int bufferHeight, int x, int y, int width, int height, Common::Rect *clipRectPtr, int32 wizFlags, const byte *extraTable, int transparentColor) {
Common::Rect srcRect, dstRect, clipRect;
WizSimpleBitmap srcBitmap, dstBitmap;
int off, t;
clipRect.left = 0;
clipRect.top = 0;
clipRect.right = bufferWidth - 1;
clipRect.bottom = bufferHeight - 1;
if (clipRectPtr) {
if (!findRectOverlap(&clipRect, clipRectPtr)) {
return;
}
}
// Build the src and dest rects based on the passed in coords...
srcRect.left = 0;
srcRect.top = 0;
srcRect.right = (width - 1);
srcRect.bottom = (height - 1);
dstRect.left = x;
dstRect.top = y;
dstRect.right = (x + width - 1);
dstRect.bottom = (y + height - 1);
// Clip the src & dst coords to the clipping rect...
clipRectCoords(&srcRect, &dstRect, &clipRect);
if (dstRect.right < dstRect.left) {
return;
}
if (dstRect.bottom < dstRect.top) {
return;
}
if (srcRect.right < srcRect.left) {
return;
}
if (srcRect.bottom < srcRect.top) {
return;
}
if (_vm->_game.heversion > 90) {
if (wizFlags & kWRFHFlip) {
off = ((width - (srcRect.right + 1)) - srcRect.left);
t = srcRect.left + off;
srcRect.left = srcRect.right + off;
srcRect.right = t;
}
if (wizFlags & kWRFVFlip) {
off = ((height - (srcRect.bottom + 1)) - srcRect.top);
t = srcRect.top + off;
srcRect.top = srcRect.bottom + off;
srcRect.bottom = t;
}
}
// Setup the fake simple bitmaps...
dstBitmap.bufferPtr = WizPxShrdBuffer(bufferPtr, false);
dstBitmap.bitmapWidth = bufferWidth;
dstBitmap.bitmapHeight = bufferHeight;
srcBitmap.bufferPtr = WizPxShrdBuffer(const_cast<WizRawPixel *>(rawData), false);
srcBitmap.bitmapWidth = width;
srcBitmap.bitmapHeight = height;
// Dispatch the drawing to the specific drawing function...
if (_vm->_game.heversion <= 90) {
pgSimpleBlit(&dstBitmap, &dstRect, &srcBitmap, &srcRect);
} else {
if (extraTable) {
if (wizFlags & kWRFRemap) {
if (transparentColor == -1) {
pgSimpleBlitRemapColors(&dstBitmap, &dstRect, &srcBitmap, &srcRect, extraTable);
} else {
pgSimpleBlitTransparentRemapColors(&dstBitmap, &dstRect, &srcBitmap, &srcRect, (WizRawPixel)transparentColor, extraTable);
}
} else {
if (transparentColor == -1) {
pgSimpleBlitMixColors(&dstBitmap, &dstRect, &srcBitmap, &srcRect, extraTable);
} else {
pgSimpleBlitTransparentMixColors(&dstBitmap, &dstRect, &srcBitmap, &srcRect, (WizRawPixel)transparentColor, extraTable);
}
}
} else {
// Dispatch the drawing to the specific drawing function...
if (transparentColor == -1) {
pgSimpleBlit(&dstBitmap, &dstRect, &srcBitmap, &srcRect);
} else {
pgTransparentSimpleBlit(&dstBitmap, &dstRect, &srcBitmap, &srcRect, (WizRawPixel)transparentColor);
}
}
}
}
void Wiz::pgSimpleBlit(WizSimpleBitmap *destBM, Common::Rect *destRect, WizSimpleBitmap *sourceBM, Common::Rect *sourceRect) {
int cw, dw, sw, ch, cSize;
WizRawPixel8 *s8, *d8;
WizRawPixel16 *s16, *d16;
// Common calcs...
dw = destBM->bitmapWidth;
sw = sourceBM->bitmapWidth;
cw = abs(sourceRect->right - sourceRect->left) + 1;
ch = abs(sourceRect->bottom - sourceRect->top) + 1;
d8 = ((WizRawPixel8 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s8 = ((WizRawPixel8 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
d16 = ((WizRawPixel16 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s16 = ((WizRawPixel16 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
// Going up or down?
if (sourceRect->top > sourceRect->bottom) {
sw = -sw;
}
// Left or right?
if (sourceRect->left <= sourceRect->right) {
cSize = _uses16BitColor ? (cw * sizeof(WizRawPixel16)) : (cw * sizeof(WizRawPixel8));
while (--ch >= 0) {
if (!_uses16BitColor) {
memcpy(d8, s8, cSize);
d8 += dw;
s8 += sw;
} else {
memcpy(d16, s16, cSize);
d16 += dw;
s16 += sw;
}
}
} else {
dw -= cw;
sw += cw;
while (--ch >= 0) {
if (!_uses16BitColor) {
for (int i = cw; --i >= 0;) {
*d8++ = *s8--;
}
d8 += dw;
s8 += sw;
} else {
for (int i = cw; --i >= 0;) {
*d16++ = FROM_LE_16(*s16--);
}
d16 += dw;
s16 += sw;
}
}
}
}
void Wiz::pgSimpleBlitRemapColors(WizSimpleBitmap *destBM, Common::Rect *destRect, WizSimpleBitmap *sourceBM, Common::Rect *sourceRect, const byte *remapColorTable) {
int cw, dw, sw, ch;
WizRawPixel8 *s8, *d8;
WizRawPixel16 *s16, *d16;
// Common calcs...
dw = destBM->bitmapWidth;
sw = sourceBM->bitmapWidth;
cw = abs(sourceRect->right - sourceRect->left) + 1;
ch = abs(sourceRect->bottom - sourceRect->top) + 1;
d8 = ((WizRawPixel8 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s8 = ((WizRawPixel8 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
d16 = ((WizRawPixel16 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s16 = ((WizRawPixel16 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
// Going up or down?
if (sourceRect->top > sourceRect->bottom) {
sw = -sw;
}
// Left or right?
if (sourceRect->left <= sourceRect->right) {
if (!_uses16BitColor) {
while (--ch >= 0) {
pgForwardRemapPixelCopy((WizRawPixel *)d8, (WizRawPixel *)s8, cw, remapColorTable);
d8 += dw;
s8 += sw;
}
} else {
while (--ch >= 0) {
pgForwardRemapPixelCopy((WizRawPixel *)d16, (WizRawPixel *)s16, cw, remapColorTable);
d16 += dw;
s16 += sw;
}
}
} else {
if (!_uses16BitColor) {
d8 += (cw - 1);
s8 -= (cw - 1);
while (--ch >= 0) {
pgBackwardsRemapPixelCopy((WizRawPixel *)d8, (WizRawPixel *)s8, cw, remapColorTable);
d8 += dw;
s8 += sw;
}
} else {
d16 += (cw - 1);
s16 -= (cw - 1);
while (--ch >= 0) {
pgBackwardsRemapPixelCopy((WizRawPixel *)d16, (WizRawPixel *)s16, cw, remapColorTable);
d16 += dw;
s16 += sw;
}
}
}
}
void Wiz::pgSimpleBlitTransparentRemapColors(WizSimpleBitmap *destBM, Common::Rect *destRect, WizSimpleBitmap *sourceBM, Common::Rect *sourceRect, WizRawPixel transparentColor, const byte *remapColorTable) {
int cw, dw, sw, ch;
WizRawPixel8 *s8, *d8;
WizRawPixel16 *s16, *d16;
// Common calcs...
dw = destBM->bitmapWidth;
sw = sourceBM->bitmapWidth;
cw = abs(sourceRect->right - sourceRect->left) + 1;
ch = abs(sourceRect->bottom - sourceRect->top) + 1;
d8 = ((WizRawPixel8 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s8 = ((WizRawPixel8 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
d16 = ((WizRawPixel16 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s16 = ((WizRawPixel16 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
// Going up or down?
if (sourceRect->top > sourceRect->bottom) {
sw = -sw;
}
// Left or right?
if (sourceRect->left <= sourceRect->right) {
if (!_uses16BitColor) {
while (--ch >= 0) {
pgTransparentForwardRemapPixelCopy((WizRawPixel *)d8, (WizRawPixel *)s8, cw, transparentColor, remapColorTable);
d8 += dw;
s8 += sw;
}
} else {
while (--ch >= 0) {
pgTransparentForwardRemapPixelCopy((WizRawPixel *)d16, (WizRawPixel *)s16, cw, transparentColor, remapColorTable);
d16 += dw;
s16 += sw;
}
}
} else {
if (!_uses16BitColor) {
d8 += (cw - 1);
s8 -= (cw - 1);
while (--ch >= 0) {
pgTransparentBackwardsRemapPixelCopy((WizRawPixel *)d8, (WizRawPixel *)s8, cw, transparentColor, remapColorTable);
d8 += dw;
s8 += sw;
}
} else {
d16 += (cw - 1);
s16 -= (cw - 1);
while (--ch >= 0) {
pgTransparentBackwardsRemapPixelCopy((WizRawPixel *)d16, (WizRawPixel *)s16, cw, transparentColor, remapColorTable);
d16 += dw;
s16 += sw;
}
}
}
}
void Wiz::pgSimpleBlitMixColors(WizSimpleBitmap *destBM, Common::Rect *destRect, WizSimpleBitmap *sourceBM, Common::Rect *sourceRect, const byte *mixColorTable) {
int cw, dw, sw, ch;
WizRawPixel8 *s8, *d8;
WizRawPixel16 *s16, *d16;
// Common calcs...
dw = destBM->bitmapWidth;
sw = sourceBM->bitmapWidth;
cw = abs(sourceRect->right - sourceRect->left) + 1;
ch = abs(sourceRect->bottom - sourceRect->top) + 1;
d8 = ((WizRawPixel8 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s8 = ((WizRawPixel8 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
d16 = ((WizRawPixel16 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s16 = ((WizRawPixel16 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
// Going up or down?
if (sourceRect->top > sourceRect->bottom) {
sw = -sw;
}
// Left or right?
if (sourceRect->left <= sourceRect->right) {
if (!_uses16BitColor) {
while (--ch >= 0) {
pgForwardMixColorsPixelCopy((WizRawPixel *)d8, (WizRawPixel *)s8, cw, mixColorTable);
d8 += dw;
s8 += sw;
}
} else {
while (--ch >= 0) {
pgForwardMixColorsPixelCopy((WizRawPixel *)d16, (WizRawPixel *)s16, cw, mixColorTable);
d16 += dw;
s16 += sw;
}
}
} else {
if (!_uses16BitColor) {
d8 += (cw - 1);
s8 -= (cw - 1);
while (--ch >= 0) {
pgBackwardsMixColorsPixelCopy((WizRawPixel *)d8, (WizRawPixel *)s8, cw, mixColorTable);
d8 += dw;
s8 += sw;
}
} else {
d16 += (cw - 1);
s16 -= (cw - 1);
while (--ch >= 0) {
pgBackwardsMixColorsPixelCopy((WizRawPixel *)d16, (WizRawPixel *)s16, cw, mixColorTable);
d16 += dw;
s16 += sw;
}
}
}
}
void Wiz::pgSimpleBlitTransparentMixColors(WizSimpleBitmap *destBM, Common::Rect *destRect, WizSimpleBitmap *sourceBM, Common::Rect *sourceRect, WizRawPixel transparentColor, const byte *mixColorTable) {
int cw, dw, sw, ch;
WizRawPixel8 *s8, *d8;
WizRawPixel16 *s16, *d16;
// Common calcs...
dw = destBM->bitmapWidth;
sw = sourceBM->bitmapWidth;
cw = abs(sourceRect->right - sourceRect->left) + 1;
ch = abs(sourceRect->bottom - sourceRect->top) + 1;
d8 = ((WizRawPixel8 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s8 = ((WizRawPixel8 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
d16 = ((WizRawPixel16 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s16 = ((WizRawPixel16 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
// Going up or down?
if (sourceRect->top > sourceRect->bottom) {
sw = -sw;
}
// Left or right?
if (sourceRect->left <= sourceRect->right) {
if (!_uses16BitColor) {
while (--ch >= 0) {
pgTransparentForwardMixColorsPixelCopy((WizRawPixel *)d8, (WizRawPixel *)s8, cw, transparentColor, mixColorTable);
d8 += dw;
s8 += sw;
}
} else {
while (--ch >= 0) {
pgTransparentForwardMixColorsPixelCopy((WizRawPixel *)d16, (WizRawPixel *)s16, cw, transparentColor, mixColorTable);
d16 += dw;
s16 += sw;
}
}
} else {
if (!_uses16BitColor) {
d8 += (cw - 1);
s8 -= (cw - 1);
while (--ch >= 0) {
pgTransparentBackwardsMixColorsPixelCopy((WizRawPixel *)d8, (WizRawPixel *)s8, cw, transparentColor, mixColorTable);
d8 += dw;
s8 += sw;
}
} else {
d16 += (cw - 1);
s16 -= (cw - 1);
while (--ch >= 0) {
pgTransparentBackwardsMixColorsPixelCopy((WizRawPixel *)d16, (WizRawPixel *)s16, cw, transparentColor, mixColorTable);
d16 += dw;
s16 += sw;
}
}
}
}
void Wiz::pgTransparentSimpleBlit(WizSimpleBitmap *destBM, Common::Rect *destRect, WizSimpleBitmap *sourceBM, Common::Rect *sourceRect, WizRawPixel transparentColor) {
int value, cw, dw, sw, ch, soff, doff, tColor;
WizRawPixel8 *s8, *d8;
WizRawPixel16 *s16, *d16;
// Common calcs...
dw = destBM->bitmapWidth;
sw = sourceBM->bitmapWidth;
cw = abs(sourceRect->right - sourceRect->left) + 1;
ch = abs(sourceRect->bottom - sourceRect->top) + 1;
d8 = ((WizRawPixel8 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s8 = ((WizRawPixel8 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
d16 = ((WizRawPixel16 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s16 = ((WizRawPixel16 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
tColor = (int)transparentColor;
// Going up or down?
if (sourceRect->top > sourceRect->bottom) {
sw = -sw;
}
// Left or right?
if (sourceRect->left <= sourceRect->right) {
soff = sw - cw;
doff = dw - cw;
while (--ch >= 0) {
if (!_uses16BitColor) {
for (int x = cw; --x >= 0;) {
value = *s8++;
if (value != tColor) {
*d8++ = (WizRawPixel8)value;
} else {
d8++;
}
}
s8 += soff;
d8 += doff;
} else {
for (int x = cw; --x >= 0;) {
value = FROM_LE_16(*s16++);
if (value != tColor) {
*d16++ = (WizRawPixel16)value;
} else {
d16++;
}
}
s16 += soff;
d16 += doff;
}
}
} else {
soff = sw + cw;
doff = dw - cw;
while (--ch >= 0) {
if (!_uses16BitColor) {
for (int x = cw; --x >= 0;) {
value = *s8--;
if (value != tColor) {
*d8++ = (WizRawPixel8)value;
} else {
d8++;
}
}
s8 += soff;
d8 += doff;
} else {
for (int x = cw; --x >= 0;) {
value = FROM_LE_16(*s16--);
if (value != tColor) {
*d16++ = (WizRawPixel16)value;
} else {
d16++;
}
}
s16 += soff;
d16 += doff;
}
}
}
}
void Wiz::pgDrawWarpDrawLetter(WizRawPixel *bitmapBuffer, int bitmapWidth, int bitmapHeight, const byte *charData, int x1, int y1, int width, int height, byte *colorLookupTable) {
WizRawPixel *remapTable = (_vm->_game.heversion <= 90) ? nullptr : (WizRawPixel *)_vm->getHEPaletteSlot(1);
if (colorLookupTable) {
auxDecompRemappedTRLEImage(
bitmapBuffer, charData, bitmapWidth, bitmapHeight, x1, y1, width, height, nullptr,
colorLookupTable,
remapTable
);
} else {
auxDecompTRLEImage(
bitmapBuffer, charData, bitmapWidth, bitmapHeight, x1, y1, width, height, nullptr,
remapTable
);
}
}
void Wiz::pgDraw8BppFormatImage(WizRawPixel *bufferPtr, const byte *rawData, int bufferWidth, int bufferHeight, int x, int y, int width, int height, Common::Rect *clipRectPtr, int32 wizFlags, const byte *extraTable, int transparentColor, const WizRawPixel *conversionTable) {
Common::Rect srcRect, dstRect, clipRect;
WizSimpleBitmap srcBitmap, dstBitmap;
clipRect.left = 0;
clipRect.top = 0;
clipRect.right = bufferWidth - 1;
clipRect.bottom = bufferHeight - 1;
if (clipRectPtr) {
if (!findRectOverlap(&clipRect, clipRectPtr)) {
return;
}
}
// Build the src and dest rects based on the passed in coords...
srcRect.left = 0;
srcRect.top = 0;
srcRect.right = (width - 1);
srcRect.bottom = (height - 1);
dstRect.left = x;
dstRect.top = y;
dstRect.right = (x + width - 1);
dstRect.bottom = (y + height - 1);
// Clip the src & dst coords to the clipping rect...
clipRectCoords(&srcRect, &dstRect, &clipRect);
if (dstRect.right < dstRect.left) {
return;
}
if (dstRect.bottom < dstRect.top) {
return;
}
if (srcRect.right < srcRect.left) {
return;
}
if (srcRect.bottom < srcRect.top) {
return;
}
if (wizFlags & kWRFHFlip) {
int off, t;
off = ((width - (srcRect.right + 1)) - srcRect.left);
t = srcRect.left + off;
srcRect.left = srcRect.right + off;
srcRect.right = t;
}
if (wizFlags & kWRFVFlip) {
int off, t;
off = ((height - (srcRect.bottom + 1)) - srcRect.top);
t = srcRect.top + off;
srcRect.top = srcRect.bottom + off;
srcRect.bottom = t;
}
// Setup the fake simple bitmaps...
dstBitmap.bufferPtr = WizPxShrdBuffer(bufferPtr, false);
dstBitmap.bitmapWidth = bufferWidth;
dstBitmap.bitmapHeight = bufferHeight;
srcBitmap.bufferPtr = WizPxShrdBuffer(const_cast<byte *>(rawData), false);
srcBitmap.bitmapWidth = width;
srcBitmap.bitmapHeight = height;
// Dispatch the drawing to the specific drawing function...
if (transparentColor == -1) {
pgDraw8BppSimpleBlit(&dstBitmap, &dstRect, &srcBitmap, &srcRect, conversionTable);
} else {
pgDraw8BppTransparentSimpleBlit(&dstBitmap, &dstRect, &srcBitmap, &srcRect, transparentColor, conversionTable);
}
}
void Wiz::pgDraw8BppSimpleBlit(WizSimpleBitmap *destBM, Common::Rect *destRect, WizSimpleBitmap *sourceBM, Common::Rect *sourceRect, const WizRawPixel *conversionTable) {
int x, cw, dw, sw, ch;
const WizRawPixel8 *s8; // Source is always 8-bit
WizRawPixel16 *d16; // Dest is always 16-bit
// Common calcs...
dw = destBM->bitmapWidth;
sw = sourceBM->bitmapWidth;
cw = abs(sourceRect->right - sourceRect->left) + 1;
ch = abs(sourceRect->bottom - sourceRect->top) + 1;
d16 = ((WizRawPixel16 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s8 = ((const WizRawPixel8 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
// Going up or down?
if (sourceRect->top > sourceRect->bottom) {
sw = -sw;
}
// Left or right?
if (sourceRect->left <= sourceRect->right) {
while (--ch >= 0) {
memcpy8BppConversion(d16, s8, cw, conversionTable);
d16 += dw;
s8 += sw;
}
} else {
dw -= cw;
sw += cw;
while (--ch >= 0) {
for (x = cw; --x >= 0;) {
*d16 = (WizRawPixel16)convert8BppToRawPixel((WizRawPixel)*s8, conversionTable);
d16++;
s8--;
}
d16 += dw;
s8 += sw;
}
}
}
void Wiz::pgDraw8BppTransparentSimpleBlit(WizSimpleBitmap *destBM, Common::Rect *destRect, WizSimpleBitmap *sourceBM, Common::Rect *sourceRect, int transparentColor, const WizRawPixel *conversionTable) {
int cw, dw, sw, ch, soff, doff, value;
const WizRawPixel8 *s8; // Source is always 8-bit
WizRawPixel16 *d16; // Dest is always 16-bit
// Common calcs...
dw = destBM->bitmapWidth;
sw = sourceBM->bitmapWidth;
cw = abs(sourceRect->right - sourceRect->left) + 1;
ch = abs(sourceRect->bottom - sourceRect->top) + 1;
d16 = ((WizRawPixel16 *)destBM->bufferPtr()) + destRect->top * dw + destRect->left;
s8 = ((const WizRawPixel8 *)sourceBM->bufferPtr()) + sourceRect->top * sw + sourceRect->left;
// Going up or down?
if (sourceRect->top > sourceRect->bottom) {
sw = -sw;
}
// Left or right?
if (sourceRect->left <= sourceRect->right) {
soff = sw - cw;
doff = dw - cw;
while (--ch >= 0) {
for (int x = cw; --x >= 0;) {
value = *s8++;
if (value != transparentColor) {
*d16++ = (WizRawPixel16)convert8BppToRawPixel((WizRawPixel)value, conversionTable);
} else {
d16++;
}
}
s8 += soff;
d16 += doff;
}
} else {
soff = sw + cw;
doff = dw - cw;
while (--ch >= 0) {
for (int x = cw; --x >= 0;) {
value = *s8--;
if (value != transparentColor) {
*d16++ = (WizRawPixel16)convert8BppToRawPixel((WizRawPixel)value, conversionTable);
} else {
d16++;
}
}
s8 += soff;
d16 += doff;
}
}
}
void Wiz::pgDrawImageWith16BitZBuffer(WizSimpleBitmap *psbDst, const WizSimpleBitmap *psbZBuffer, const byte *imgData, int x, int y, int z, int width, int height, Common::Rect *prcClip) {
// This is available only on HE100+, which hopefully means it should only be called for 16-bit games!
assert(_uses16BitColor);
// Validate parameters...
assert(psbDst && psbZBuffer && imgData && prcClip);
// Z-Buffer and destination buffer must have the same dimensions...
assert(psbDst->bitmapWidth == psbZBuffer->bitmapWidth);
assert(psbDst->bitmapHeight == psbZBuffer->bitmapHeight);
// Make sure that clip rect is clipped to destination buffer...
Common::Rect dstRect;
makeSizedRect(&dstRect, psbDst->bitmapWidth, psbDst->bitmapHeight);
if (!findRectOverlap(prcClip, &dstRect)) {
// Rectangles don't intersect - no drawing necessary...
return;
}
// Make sure that clip rect is clipped to source image...
Common::Rect srcRect;
srcRect.left = x;
srcRect.top = y;
srcRect.right = x + (width - 1);
srcRect.bottom = y + (height - 1);
if (!findRectOverlap(prcClip, &srcRect)) {
// Rectangles don't intersect - no drawing necessary...
return;
}
// Perform the drawing...
int dstWidth = psbDst->bitmapWidth; // Same for destination and Z-Buffer...
const int drawWidth = (prcClip->right - prcClip->left + 1);
const int drawHeight = (prcClip->bottom - prcClip->top + 1);
WizRawPixel *pSrc = (WizRawPixel *)const_cast<byte *>(imgData) + (prcClip->top - y) * width + (prcClip->left - x);
WizRawPixel *pDst = psbDst->bufferPtr() + prcClip->top * dstWidth + prcClip->left;
WizRawPixel *pZB = psbZBuffer->bufferPtr() + prcClip->top * dstWidth + prcClip->left;
for (int row = 0; row < drawHeight; ++row) {
for (int col = 0; col < drawWidth; ++col, ++pZB, ++pDst, ++pSrc) {
// Left hand rule - don't draw unless we're closer than the Z-Buffer value...
if (*pZB > z) {
*pDst = *pSrc;
}
}
// Move to the next line...
pSrc += width - drawWidth;
pDst += dstWidth - drawWidth;
pZB += dstWidth - drawWidth;
}
}
void Wiz::pgForwardRemapPixelCopy(WizRawPixel *dstPtr, const WizRawPixel *srcPtr, int size, const byte *lookupTable) {
if (!_uses16BitColor) {
WizRawPixel8 *dst8 = (WizRawPixel8 *)dstPtr;
const WizRawPixel8 *src8 = (const WizRawPixel8 *)srcPtr;
while (size-- > 0) {
*dst8++ = *(lookupTable + *src8++);
}
} else {
WizRawPixel16 *dst16 = (WizRawPixel16 *)dstPtr;
const WizRawPixel16 *src16 = (const WizRawPixel16 *)srcPtr;
while (size-- > 0) {
*dst16++ = FROM_LE_16(*src16++);
}
}
}
void Wiz::pgTransparentForwardRemapPixelCopy(WizRawPixel *dstPtr, const WizRawPixel *srcPtr, int size, WizRawPixel transparentColor, const byte *lookupTable) {
if (!_uses16BitColor) {
WizRawPixel8 *dst8 = (WizRawPixel8 *)dstPtr;
const WizRawPixel8 *src8 = (const WizRawPixel8 *)srcPtr;
while (size-- > 0) {
WizRawPixel8 srcColor = *src8++;
if (transparentColor != srcColor) {
WizRawPixel8 remappedColor = *(lookupTable + srcColor);
if (transparentColor != remappedColor) {
*dst8++ = remappedColor;
} else {
++dst8;
}
} else {
++dst8;
}
}
} else {
WizRawPixel16 *dst16 = (WizRawPixel16 *)dstPtr;
const WizRawPixel16 *src16 = (const WizRawPixel16 *)srcPtr;
while (size-- > 0) {
WizRawPixel16 srcColor = FROM_LE_16(*src16++);
if (transparentColor != srcColor) {
*dst16++ = srcColor;
} else {
++dst16;
}
}
}
}
void Wiz::pgTransparentBackwardsRemapPixelCopy(WizRawPixel *dstPtr, const WizRawPixel *srcPtr, int size, WizRawPixel transparentColor, const byte *lookupTable) {
if (!_uses16BitColor) {
WizRawPixel8 *dst8 = (WizRawPixel8 *)dstPtr;
const WizRawPixel8 *src8 = (const WizRawPixel8 *)srcPtr;
while (size-- > 0) {
WizRawPixel srcColor = *src8++;
if (transparentColor != srcColor) {
WizRawPixel8 remappedColor = *(lookupTable + srcColor);
if (transparentColor != remappedColor) {
*dst8-- = remappedColor;
} else {
--dst8;
}
} else {
--dst8;
}
}
} else {
WizRawPixel16 *dst16 = (WizRawPixel16 *)dstPtr;
const WizRawPixel16 *src16 = (const WizRawPixel16 *)srcPtr;
while (size-- > 0) {
WizRawPixel16 srcColor = FROM_LE_16(*src16++);
if (transparentColor != srcColor) {
*dst16-- = srcColor;
} else {
--dst16;
}
}
}
}
void Wiz::pgBackwardsRemapPixelCopy(WizRawPixel *dstPtr, const WizRawPixel *srcPtr, int size, const byte *lookupTable) {
if (!_uses16BitColor) {
WizRawPixel8 *dst8 = (WizRawPixel8 *)dstPtr;
const WizRawPixel8 *src8 = (const WizRawPixel8 *)srcPtr;
while (size-- > 0) {
*dst8-- = *(lookupTable + *src8++);
}
} else {
WizRawPixel16 *dst16 = (WizRawPixel16 *)dstPtr;
const WizRawPixel16 *src16 = (const WizRawPixel16 *)srcPtr;
while (size-- > 0) {
*dst16-- = FROM_LE_16(*src16++);
}
}
}
void Wiz::pgForwardMixColorsPixelCopy(WizRawPixel *dstPtr, const WizRawPixel *srcPtr, int size, const byte *lookupTable) {
if (!_uses16BitColor) {
WizRawPixel8 *dst8 = (WizRawPixel8 *)dstPtr;
const WizRawPixel8 *src8 = (const WizRawPixel8 *)srcPtr;
while (size-- > 0) {
*dst8 = *(lookupTable + ((*src8++) * 256) + *dst8);
dst8++;
}
} else {
WizRawPixel16 *dst16 = (WizRawPixel16 *)dstPtr;
const WizRawPixel16 *src16 = (const WizRawPixel16 *)srcPtr;
while (size-- > 0) {
if (_vm->_game.heversion >= 99) {
WizRawPixel16 srcColor = FROM_LE_16(*src16++);
WizRawPixel16 dstColor = *dst16;
*dst16++ = WIZRAWPIXEL_50_50_MIX(
WIZRAWPIXEL_50_50_PREMIX_COLOR(srcColor),
WIZRAWPIXEL_50_50_PREMIX_COLOR(dstColor));
} else {
*dst16++ = FROM_LE_16(*src16++);
}
}
}
}
void Wiz::pgBackwardsMixColorsPixelCopy(WizRawPixel *dstPtr, const WizRawPixel *srcPtr, int size, const byte *lookupTable) {
if (!_uses16BitColor) {
WizRawPixel8 *dst8 = (WizRawPixel8 *)dstPtr;
const WizRawPixel8 *src8 = (const WizRawPixel8 *)srcPtr;
while (size-- > 0) {
*dst8 = *(lookupTable + ((*src8++) * 256) + *dst8);
dst8--;
}
} else {
WizRawPixel16 *dst16 = (WizRawPixel16 *)dstPtr;
const WizRawPixel16 *src16 = (const WizRawPixel16 *)srcPtr;
while (size-- > 0) {
if (_vm->_game.heversion >= 99) {
WizRawPixel16 srcColor = FROM_LE_16(*src16++);
WizRawPixel16 dstColor = *dst16;
*dst16-- = WIZRAWPIXEL_50_50_MIX(
WIZRAWPIXEL_50_50_PREMIX_COLOR(srcColor),
WIZRAWPIXEL_50_50_PREMIX_COLOR(dstColor));
} else {
*dst16-- = FROM_LE_16(*src16++);
}
}
}
}
void Wiz::pgTransparentForwardMixColorsPixelCopy(WizRawPixel *dstPtr, const WizRawPixel *srcPtr, int size, WizRawPixel transparentColor, const byte *lookupTable) {
if (!_uses16BitColor) {
WizRawPixel8 *dst8 = (WizRawPixel8 *)dstPtr;
const WizRawPixel8 *src8 = (const WizRawPixel8 *)srcPtr;
while (size-- > 0) {
WizRawPixel8 srcColor = *src8++;
if (transparentColor != srcColor) {
WizRawPixel8 resultColor = *(lookupTable + (srcColor * 256) + *dst8);
if (transparentColor != resultColor) {
*dst8++ = resultColor;
} else {
++dst8;
}
} else {
++dst8;
}
}
} else {
WizRawPixel16 *dst16 = (WizRawPixel16 *)dstPtr;
const WizRawPixel16 *src16 = (const WizRawPixel16 *)srcPtr;
while (size-- > 0) {
WizRawPixel16 srcColor = FROM_LE_16(*src16++);
if (transparentColor != srcColor) {
WizRawPixel16 dstColor = *dst16;
*dst16++ = WIZRAWPIXEL_50_50_MIX(
WIZRAWPIXEL_50_50_PREMIX_COLOR(srcColor),
WIZRAWPIXEL_50_50_PREMIX_COLOR(dstColor));
} else {
++dst16;
}
}
}
}
void Wiz::pgTransparentBackwardsMixColorsPixelCopy(WizRawPixel *dstPtr, const WizRawPixel *srcPtr, int size, WizRawPixel transparentColor, const byte *lookupTable) {
if (!_uses16BitColor) {
WizRawPixel8 *dst8 = (WizRawPixel8 *)dstPtr;
const WizRawPixel8 *src8 = (const WizRawPixel8 *)srcPtr;
while (size-- > 0) {
WizRawPixel8 srcColor = *src8++;
if (transparentColor != srcColor) {
WizRawPixel8 resultColor = *(lookupTable + (srcColor * 256) + *dst8);
if (transparentColor != resultColor) {
*dst8-- = resultColor;
} else {
--dst8;
}
} else {
--dst8;
}
}
} else {
WizRawPixel16 *dst16 = (WizRawPixel16 *)dstPtr;
const WizRawPixel16 *src16 = (const WizRawPixel16 *)srcPtr;
while (size-- > 0) {
WizRawPixel16 srcColor = FROM_LE_16(*src16++);
if (transparentColor != srcColor) {
WizRawPixel16 dstColor = *dst16;
*dst16-- = WIZRAWPIXEL_50_50_MIX(
WIZRAWPIXEL_50_50_PREMIX_COLOR(srcColor),
WIZRAWPIXEL_50_50_PREMIX_COLOR(dstColor));
} else {
--dst16;
}
}
}
}
static void pgBlitForwardSrcArbitraryDstPixelTransfer(Wiz *wiz, WizRawPixel *dstPtr, int dstStep, const WizRawPixel *srcPtr, int count, const void *userParam, const void *userParam2) {
if (!wiz->_uses16BitColor) {
WizRawPixel8 *dst8 = (WizRawPixel8 *)dstPtr;
const WizRawPixel8 *src8 = (const WizRawPixel8 *)srcPtr;
for (int i = 0; i < count; i++) {
*dst8 = *src8++;
dst8 += dstStep;
}
} else {
WizRawPixel16 *dst16 = (WizRawPixel16 *)dstPtr;
const WizRawPixel16 *src16 = (const WizRawPixel16 *)srcPtr;
for (int i = 0; i < count; i++) {
*dst16 = FROM_LE_16(*src16++);
dst16 += dstStep;
}
}
}
static void pgBlitForwardSrcArbitraryDstTransparentPixelTransfer(Wiz *wiz, WizRawPixel *dstPtr, int dstStep, const WizRawPixel *srcPtr, int count, const void *userParam, const void *userParam2) {
if (!wiz->_uses16BitColor) {
WizRawPixel8 *dst8 = (WizRawPixel8 *)dstPtr;
const WizRawPixel8 *src8 = (const WizRawPixel8 *)srcPtr;
WizRawPixel8 transparentColor, color;
transparentColor = *((const WizRawPixel8 *)userParam);
for (int i = 0; i < count; i++) {
color = *src8++;
if (transparentColor != color) {
*dst8 = color;
}
dst8 += dstStep;
}
} else {
WizRawPixel16 *dst16 = (WizRawPixel16 *)dstPtr;
const WizRawPixel16 *src16 = (const WizRawPixel16 *)srcPtr;
WizRawPixel16 transparentColor, color;
transparentColor = *((const WizRawPixel16 *)userParam);
for (int i = 0; i < count; i++) {
color = FROM_LE_16(*src16++);
if (transparentColor != color) {
*dst16 = color;
}
dst16 += dstStep;
}
}
}
void Wiz::pgBlit90DegreeRotate(WizSimpleBitmap *dstBitmap, int x, int y, const WizSimpleBitmap *srcBitmap, const Common::Rect *optionalSrcRect, const Common::Rect *optionalClipRect, bool hFlip, bool vFlip) {
pgBlit90DegreeRotateCore(
dstBitmap, x, y, srcBitmap, optionalSrcRect, optionalClipRect,
hFlip, vFlip, nullptr, nullptr, pgBlitForwardSrcArbitraryDstPixelTransfer);
}
void Wiz::pgBlit90DegreeRotateTransparent(WizSimpleBitmap *dstBitmap, int x, int y, const WizSimpleBitmap *srcBitmap, const Common::Rect *optionalSrcRect, const Common::Rect *optionalClipRect, bool hFlip, bool vFlip, WizRawPixel transparentColor) {
pgBlit90DegreeRotateCore(
dstBitmap, x, y, srcBitmap, optionalSrcRect, optionalClipRect,
hFlip, vFlip, &transparentColor, nullptr, pgBlitForwardSrcArbitraryDstTransparentPixelTransfer);
}
void Wiz::pgBlit90DegreeRotateCore(WizSimpleBitmap *dstBitmap, int x, int y, const WizSimpleBitmap *srcBitmap, const Common::Rect *optionalSrcRect,
const Common::Rect *optionalClipRect, bool hFlip, bool vFlip, const void *userParam, const void *userParam2,
void (*srcTransferFP)(Wiz *wiz, WizRawPixel *dstPtr, int dstStep, const WizRawPixel *srcPtr, int count, const void *userParam, const void *userParam2)) {
Common::Rect dstRect, srcRect, clipRect, clippedDstRect, clippedSrcRect;
int dstOffset, dstStep, w, h, srcOffset, dstX, dstY;
const WizRawPixel8 *src8;
WizRawPixel8 *dst8;
const WizRawPixel16 *src16;
WizRawPixel16 *dst16;
// Do as much pre-clipping as possible...
makeSizedRect(&clipRect, dstBitmap->bitmapWidth, dstBitmap->bitmapHeight);
if (optionalClipRect) {
if (!findRectOverlap(&clipRect, optionalClipRect)) {
return;
}
}
// Clip the source rect against the actual src bitmap limits...
makeSizedRect(&srcRect, srcBitmap->bitmapWidth, srcBitmap->bitmapHeight);
if (optionalSrcRect) {
if (!findRectOverlap(&srcRect, optionalSrcRect)) {
return;
}
}
// Make the dest rect, then clip it against the clip rect...
makeSizedRectAt(&dstRect, x, y, getRectHeight(&srcRect), getRectWidth(&srcRect));
clippedDstRect = dstRect;
if (!findRectOverlap(&clippedDstRect, &clipRect)) {
return;
}
// Make the clipped src rect adjusted for the 90 degree rotation...
clippedSrcRect.left = srcRect.left + (clippedDstRect.top - dstRect.top);
clippedSrcRect.top = srcRect.top + (dstRect.right - clippedDstRect.right);
clippedSrcRect.right = srcRect.right - (dstRect.bottom - clippedDstRect.bottom);
clippedSrcRect.bottom = srcRect.bottom - (clippedDstRect.left - dstRect.left);
// Perform any flipping of the coords and setup the step variables...
if (hFlip) {
horzFlipAlignWithRect(&clippedSrcRect, &srcRect);
dstY = clippedDstRect.bottom;
dstStep = -dstBitmap->bitmapWidth;
} else {
dstY = clippedDstRect.top;
dstStep = dstBitmap->bitmapWidth;
}
if (vFlip) {
vertFlipAlignWithRect(&clippedSrcRect, &srcRect);
dstX = clippedDstRect.left;
dstOffset = 1;
} else {
dstX = clippedDstRect.right;
dstOffset = -1;
}
// Finally get down to business and do the blit...
w = getRectWidth(&clippedSrcRect);
h = getRectHeight(&clippedSrcRect);
// Transfer the src line to the dest line using the passed transfer prim...
srcOffset = srcBitmap->bitmapWidth;
if (!_uses16BitColor) {
dst8 = ((WizRawPixel8 *)dstBitmap->bufferPtr()) + dstX + (dstY * dstBitmap->bitmapWidth);
src8 = ((WizRawPixel8 *)srcBitmap->bufferPtr()) + clippedSrcRect.left + (clippedSrcRect.top * srcBitmap->bitmapWidth);
while (--h >= 0) {
(*srcTransferFP)(this, (WizRawPixel *)dst8, dstStep, (const WizRawPixel *)src8, w, userParam, userParam2);
dst8 += dstOffset;
src8 += srcOffset;
}
} else {
dst16 = ((WizRawPixel16 *)dstBitmap->bufferPtr()) + dstX + (dstY * dstBitmap->bitmapWidth);
src16 = ((WizRawPixel16 *)srcBitmap->bufferPtr()) + clippedSrcRect.left + (clippedSrcRect.top * srcBitmap->bitmapWidth);
while (--h >= 0) {
(*srcTransferFP)(this, (WizRawPixel *)dst16, dstStep, (const WizRawPixel *)src16, w, userParam, userParam2);
dst16 += dstOffset;
src16 += srcOffset;
}
}
}
bool Wiz::findRectOverlap(Common::Rect *destRectPtr, const Common::Rect *sourceRectPtr) {
// Make sure only points inside the viewPort are being set...
if ((destRectPtr->left > sourceRectPtr->right) || (destRectPtr->top > sourceRectPtr->bottom) ||
(destRectPtr->right < sourceRectPtr->left) || (destRectPtr->bottom < sourceRectPtr->top)) {
return false;
}
// Perform the actual clipping...
if (destRectPtr->left < sourceRectPtr->left) {
destRectPtr->left = sourceRectPtr->left;
}
if (destRectPtr->top < sourceRectPtr->top) {
destRectPtr->top = sourceRectPtr->top;
}
if (destRectPtr->right > sourceRectPtr->right) {
destRectPtr->right = sourceRectPtr->right;
}
if (destRectPtr->bottom > sourceRectPtr->bottom) {
destRectPtr->bottom = sourceRectPtr->bottom;
}
return true;
}
bool Wiz::isPointInRect(Common::Rect *r, Common::Point *pt) {
return (pt->x >= r->left) && (pt->x <= r->right) && (pt->y >= r->top) && (pt->y <= r->bottom);
}
bool Wiz::isRectValid(Common::Rect r) {
return r.left <= r.right && r.top <= r.bottom;
}
void Wiz::makeSizedRectAt(Common::Rect *rectPtr, int x, int y, int width, int height) {
rectPtr->left = x;
rectPtr->top = y;
rectPtr->right = x + width - 1;
rectPtr->bottom = y + height - 1;
}
void Wiz::makeSizedRect(Common::Rect *rectPtr, int width, int height) {
makeSizedRectAt(rectPtr, 0, 0, width, height);
}
void Wiz::combineRects(Common::Rect *destRect, Common::Rect *ra, Common::Rect *rb) {
destRect->left = MIN<int16>(ra->left, rb->left);
destRect->top = MIN<int16>(ra->top, rb->top);
destRect->right = MAX<int16>(ra->right, rb->right);
destRect->bottom = MAX<int16>(ra->bottom, rb->bottom);
}
void Wiz::clipRectCoords(Common::Rect *sourceRectPtr, Common::Rect *destRectPtr, Common::Rect *clipRectPtr) {
int16 value = destRectPtr->left - clipRectPtr->left;
if (value < 0) {
sourceRectPtr->left -= value;
destRectPtr->left -= value;
}
value = destRectPtr->right - clipRectPtr->right;
if (value > 0) {
sourceRectPtr->right -= value;
destRectPtr->right -= value;
}
value = destRectPtr->top - clipRectPtr->top;
if (value < 0) {
sourceRectPtr->top -= value;
destRectPtr->top -= value;
}
value = destRectPtr->bottom - clipRectPtr->bottom;
if (value > 0) {
sourceRectPtr->bottom -= value;
destRectPtr->bottom -= value;
}
}
void Wiz::floodInitFloodState(WizFloodState *statePtr, WizSimpleBitmap *bitmapPtr, int colorToWrite, const Common::Rect *optionalClippingRect) {
statePtr->colorToWrite = colorToWrite;
statePtr->bitmapPtr = bitmapPtr;
if (!optionalClippingRect) {
if (bitmapPtr) {
makeSizedRect(&statePtr->clipping, bitmapPtr->bitmapWidth, bitmapPtr->bitmapHeight);
} else {
makeSizedRect(&statePtr->clipping, 1, 1);
}
} else {
statePtr->clipping = *optionalClippingRect;
}
statePtr->sp = statePtr->stack;
statePtr->top = statePtr->stack + statePtr->numStackElements;
}
WizFloodState *Wiz::floodCreateFloodState(int numStackElements) {
WizFloodState *statePtr;
statePtr = (WizFloodState *)malloc(sizeof(WizFloodState));
if (!statePtr) {
return nullptr;
}
statePtr->numStackElements = numStackElements;
statePtr->stack = (WizFloodSegment *)malloc(numStackElements * sizeof(WizFloodSegment));
if (!statePtr->stack) {
floodDestroyFloodState(statePtr);
return nullptr;
}
floodInitFloodState(statePtr, nullptr, 0, nullptr);
return statePtr;
}
void Wiz::floodDestroyFloodState(WizFloodState *statePtr) {
if (statePtr->stack) {
free(statePtr->stack);
statePtr->stack = nullptr;
}
free(statePtr);
statePtr = nullptr;
}
static bool floodSimpleFloodCheckPixel(Wiz *w, int x, int y, WizFloodState *state) {
return (w->pgReadPixel(state->bitmapPtr, x, y, state->colorToWrite) == state->writeOverColor);
}
bool Wiz::floodBoundryColorFloodCheckPixel(int x, int y, WizFloodState *state) {
int pixel = pgReadPixel(state->bitmapPtr, x, y, state->colorToWrite);
return (pixel != state->boundryColor) && (pixel != state->colorToWrite);
}
#define FLOOD_PUSH(Y, XL, XR, DY, SS) \
if ((SS)->sp < (SS)->top && Y + (DY) >= (SS)->clipping.top && Y + (DY) <= (SS)->clipping.bottom) { \
(SS)->sp->y = Y; \
(SS)->sp->xl = XL; \
(SS)->sp->xr = XR; \
(SS)->sp->dy = DY; \
(SS)->sp++; \
}
#define FLOOD_POP(Y, XL, XR, DY, SS) { \
(SS)->sp--; \
Y = (SS)->sp->y + (DY = (SS)->sp->dy); \
XL = (SS)->sp->xl; \
XR = (SS)->sp->xr; \
}
void Wiz::floodFloodFillPrim(int x, int y, WizFloodState *statePtr, bool (*checkPixelFnPtr)(Wiz *w, int x, int y, WizFloodState *state)) {
Common::Rect fillRect;
int l, x1, x2, dy;
// Make the initial update invalid...
statePtr->updateRect.left = statePtr->updateRect.top = 12345;
statePtr->updateRect.right = statePtr->updateRect.bottom = -12345;
FLOOD_PUSH(y, x, x, 1, statePtr);
FLOOD_PUSH(y + 1, x, x, -1, statePtr);
while (statePtr->sp > statePtr->stack) {
FLOOD_POP(y, x1, x2, dy, statePtr);
// Fill the left span from this point!
fillRect.left = x1 + 1;
fillRect.top = y;
fillRect.right = x1;
fillRect.bottom = y;
for (x = x1; (x >= statePtr->clipping.left) && (*checkPixelFnPtr)(this, x, y, statePtr); x--) {
fillRect.left = x;
}
if (isRectValid(fillRect)) {
floodPerformOpOnRect(statePtr, &fillRect);
}
// This goto, while ugly, allows me to avoid rewriting
// a second version of the do-while loop below... Have mercy :-)
if (x >= x1)
goto skip;
l = x + 1;
if (l < x1) {
FLOOD_PUSH(y, l, x1 - 1, -dy, statePtr);
}
x = x1 + 1;
do {
// Fill the right span from this point!
fillRect.left = x;
fillRect.top = y;
fillRect.right = x - 1;
fillRect.bottom = y;
for (; (x <= statePtr->clipping.right) && (*checkPixelFnPtr)(this, x, y, statePtr); x++) {
fillRect.right = x;
}
if (isRectValid(fillRect)) {
floodPerformOpOnRect(statePtr, &fillRect);
}
FLOOD_PUSH(y, l, x - 1, dy, statePtr);
if (x > (x2 + 1)) {
FLOOD_PUSH(y, x2 + 1, x - 1, -dy, statePtr);
}
skip:
for (x++; (x <= x2) && (!(*checkPixelFnPtr)(this, x, y, statePtr)); x++)
;
l = x;
} while (x <= x2);
}
}
#undef FLOOD_POP
#undef FLOOD_PUSH
void Wiz::floodPerformOpOnRect(WizFloodState *statePtr, Common::Rect *rectPtr) {
pgDrawSolidRect(statePtr->bitmapPtr, rectPtr, (WizRawPixel)statePtr->colorToWrite);
if (isRectValid(statePtr->updateRect)) {
combineRects(&statePtr->updateRect, &statePtr->updateRect, rectPtr);
} else {
statePtr->updateRect = *rectPtr;
}
}
bool Wiz::floodSimpleFill(WizSimpleBitmap *bitmapPtr, int x, int y, int colorToWrite, const Common::Rect *optionalClipRect, Common::Rect *updateRectPtr) {
WizFloodState *statePtr;
statePtr = floodCreateFloodState(bitmapPtr->bitmapHeight * 2);
if (!statePtr) {
return false;
}
floodInitFloodState(statePtr, bitmapPtr, colorToWrite, optionalClipRect);
statePtr->writeOverColor = pgReadPixel(bitmapPtr, x, y, colorToWrite);
if (colorToWrite != statePtr->writeOverColor) {
floodFloodFillPrim(x, y, statePtr, floodSimpleFloodCheckPixel);
*updateRectPtr = statePtr->updateRect;
}
floodDestroyFloodState(statePtr);
return true;
}
int Wiz::getRectWidth(Common::Rect *rectPtr) {
return abs(rectPtr->width()) + 1;
}
int Wiz::getRectHeight(Common::Rect *rectPtr) {
return abs(rectPtr->height()) + 1;
}
void Wiz::moveRect(Common::Rect *rectPtr, int dx, int dy) {
rectPtr->left += dx;
rectPtr->right += dx;
rectPtr->top += dy;
rectPtr->bottom += dy;
}
void Wiz::horzFlipAlignWithRect(Common::Rect *rectToAlign, const Common::Rect *baseRect) {
int dx = (baseRect->right - rectToAlign->right) - (rectToAlign->left - baseRect->left);
moveRect(rectToAlign, dx, 0);
}
void Wiz::vertFlipAlignWithRect(Common::Rect *rectToAlign, const Common::Rect *baseRect) {
int dy = (baseRect->bottom - rectToAlign->bottom) - (rectToAlign->top - baseRect->top);
moveRect(rectToAlign, 0, dy);
}
void Wiz::swapRectX(Common::Rect *rectPtr) {
int16 t = rectPtr->right;
rectPtr->right = rectPtr->left;
rectPtr->left = t;
}
void Wiz::swapRectY(Common::Rect *rectPtr) {
int16 t = rectPtr->bottom;
rectPtr->bottom = rectPtr->top;
rectPtr->top = t;
}
int Wiz::getRawPixel(int color) {
return color & WIZRAWPIXEL_MASK;
}
void Wiz::memset8BppConversion(void *dstPtr, int value, size_t count, const WizRawPixel *conversionTable) {
if (_uses16BitColor) {
rawPixelMemset((WizRawPixel16 *)dstPtr, (int)convert8BppToRawPixel((WizRawPixel16)value, conversionTable), count);
} else {
memset((WizRawPixel8 *)dstPtr, value, count);
}
}
void Wiz::memcpy8BppConversion(void *dstPtr, const void *srcPtr, size_t count, const WizRawPixel *conversionTable) {
if (_uses16BitColor) {
WizRawPixel16 *dstWritePtr = (WizRawPixel16 *)(dstPtr);
const byte *srcReadPtr = (const byte *)(srcPtr);
int counter = count;
while (0 <= --counter) {
*dstWritePtr++ = convert8BppToRawPixel((WizRawPixel16)(*srcReadPtr++), conversionTable);
}
} else {
memcpy((WizRawPixel8 *)dstPtr, (const byte *)srcPtr, count);
}
}
void Wiz::rawPixelMemset(void *dstPtr, int value, size_t count) {
if (_uses16BitColor) {
WizRawPixel16 *dst16Bit = (WizRawPixel16 *)dstPtr;
for (size_t i = 0; i < count; i++)
WRITE_UINT16(&dst16Bit[i], value);
} else {
WizRawPixel8 *dst8Bit = (WizRawPixel8 *)dstPtr;
memset(dst8Bit, value, count);
}
}
WizRawPixel Wiz::convert8BppToRawPixel(WizRawPixel value, const WizRawPixel *conversionTable) {
if (_uses16BitColor) {
return FROM_LE_16(*(((const WizRawPixel16 *)conversionTable) + value));
} else {
return value;
}
}
bool Wiz::compareDoPixelStreamsOverlap(const WizRawPixel *a, const WizRawPixel *b, int width, WizRawPixel transparentColor) {
const WizRawPixel8 *a8 = (const WizRawPixel8 *)a;
const WizRawPixel8 *b8 = (const WizRawPixel8 *)b;
const WizRawPixel16 *a16 = (const WizRawPixel16 *)a;
const WizRawPixel16 *b16 = (const WizRawPixel16 *)b;
if (!_uses16BitColor) {
for (int i = 0; i < width; i++) {
if ((*a8++ != (WizRawPixel8)transparentColor) && (*b8++ != (WizRawPixel8)transparentColor)) {
return true;
}
}
} else {
for (int i = 0; i < width; i++) {
if ((FROM_LE_16(*a16++) != (WizRawPixel16)transparentColor) && (FROM_LE_16(*b16++) != (WizRawPixel16)transparentColor)) {
return true;
}
}
}
return false;
}
void Wiz::rawPixelExtractComponents(WizRawPixel aPixel, int &r, int &g, int &b) {
r = (aPixel & WIZRAWPIXEL_R_MASK) >> WIZRAWPIXEL_R_SHIFT;
g = (aPixel & WIZRAWPIXEL_G_MASK) >> WIZRAWPIXEL_G_SHIFT;
b = (aPixel & WIZRAWPIXEL_B_MASK) >> WIZRAWPIXEL_B_SHIFT;
}
void Wiz::rawPixelPackComponents(WizRawPixel &aPixel, int r, int g, int b) {
aPixel = (r << WIZRAWPIXEL_R_SHIFT) | (g << WIZRAWPIXEL_G_SHIFT) | (b << WIZRAWPIXEL_B_SHIFT);
}
} // End of namespace Scumm
#endif // ENABLE_HE