diff options
Diffstat (limited to 'engines/sci/graphics')
-rw-r--r-- | engines/sci/graphics/frameout.cpp | 12 | ||||
-rw-r--r-- | engines/sci/graphics/picture.cpp | 121 | ||||
-rw-r--r-- | engines/sci/graphics/picture.h | 4 |
3 files changed, 79 insertions, 58 deletions
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 1efde7cb33..df1273933a 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -209,9 +209,13 @@ void GfxFrameout::kernelFrameout() { planeRect.bottom = (planeRect.bottom * _screen->getHeight()) / scriptsRunningHeight; planeRect.right = (planeRect.right * _screen->getWidth()) / scriptsRunningWidth; + int16 planeOffsetX = 0; + // We get negative left in kq7 in scrolling rooms - if (planeRect.left < 0) + if (planeRect.left < 0) { + planeOffsetX = -planeRect.left; planeRect.left = 0; + } if (planeRect.top < 0) planeRect.top = 0; // We get bad plane-bottom in sq6 @@ -301,8 +305,6 @@ void GfxFrameout::kernelFrameout() { FrameoutEntry *pictureCels = NULL; if (planePicture) { - // Show base picture -// planePicture->drawSci32Vga(0, planePicture->getSci32celX(0), planePicture->getSci32celY(0), planePictureMirrored); // Allocate memory for picture cels pictureCels = new FrameoutEntry[planePicture->getSci32celCount()]; // Add following cels to the itemlist @@ -336,7 +338,7 @@ void GfxFrameout::kernelFrameout() { itemEntry->y = ((itemEntry->y * _screen->getHeight()) / scriptsRunningHeight); itemEntry->x = ((itemEntry->x * _screen->getWidth()) / scriptsRunningWidth); - planePicture->drawSci32Vga(itemEntry->celNo, itemEntry->x, itemEntry->y, planePictureMirrored); + planePicture->drawSci32Vga(itemEntry->celNo, itemEntry->x, itemEntry->y, planeOffsetX, planePictureMirrored); // warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority); } else if (itemEntry->viewId != 0xFFFF) { @@ -360,6 +362,8 @@ void GfxFrameout::kernelFrameout() { default: break; } + // Adjust according to current scroll position + itemEntry->x -= planeOffsetX; uint16 useInsetRect = readSelectorValue(_segMan, itemEntry->object, SELECTOR(useInsetRect)); if (useInsetRect) { diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index 20228b75c4..e10a319c4c 100644 --- a/engines/sci/graphics/picture.cpp +++ b/engines/sci/graphics/picture.cpp @@ -117,7 +117,7 @@ void GfxPicture::drawSci11Vga() { // display Cel-data if (has_cel) - drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, 0, 0); + drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, 0, 0, 0); // process vector data drawVectorData(inbuffer + vector_dataPos, vector_size); @@ -153,7 +153,7 @@ int16 GfxPicture::getSci32celPriority(int16 celNo) { return READ_LE_UINT16(inbuffer + cel_headerPos + 36); } -void GfxPicture::drawSci32Vga(int16 celNo, int16 callerX, int16 callerY, bool mirrored) { +void GfxPicture::drawSci32Vga(int16 celNo, int16 drawX, int16 drawY, int16 pictureX, bool mirrored) { byte *inbuffer = _resource->data; int size = _resource->size; int header_size = READ_LE_UINT16(inbuffer); @@ -187,18 +187,18 @@ void GfxPicture::drawSci32Vga(int16 celNo, int16 callerX, int16 callerY, bool mi if (mirrored) { // switch around relativeXpos Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea(); - callerX = displayArea.width() - callerX - READ_LE_UINT16(inbuffer + cel_headerPos + 0); + drawX = displayArea.width() - drawX - READ_LE_UINT16(inbuffer + cel_headerPos + 0); } cel_RlePos = READ_LE_UINT32(inbuffer + cel_headerPos + 24); cel_LiteralPos = READ_LE_UINT32(inbuffer + cel_headerPos + 28); - drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, callerX, callerY); + drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, drawX, drawY, pictureX); cel_headerPos += 42; } #endif -void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 callerX, int16 callerY) { +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; @@ -326,54 +326,71 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea(); - y = callerY + displayArea.top; - lastY = MIN<int16>(height + y, displayArea.bottom); - leftX = callerX + displayArea.left; - rightX = MIN<int16>(width + leftX, displayArea.right); - - // Change clearcolor to white, if we dont add to an existing picture. That way we will paint everything on screen - // but white and that wont matter because the screen is supposed to be already white. It seems that most (if not all) - // SCI1.1 games use color 0 as transparency and SCI1 games use color 255 as transparency. Sierra SCI seems to paint - // the whole data to screen and wont skip over transparent pixels. So this will actually make it work like Sierra - if (!_addToFlag) - clearColor = _screen->getColorWhite(); - - byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY; - - ptr = celBitmap; - if (!_mirroredFlag) { - // Draw bitmap to screen - x = leftX; - while (y < lastY) { - curByte = *ptr++; - if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y))) - _screen->putPixel(x, y, drawMask, curByte, priority, 0); - - x++; - - if (x >= rightX) { - if (width > rightX - leftX) // Skip extra pixels at the end of the row - ptr += width - (rightX - leftX); - x = leftX; - y++; - } + uint16 skipCelBitmapPixels = 0; + int16 displayWidth = width; + if (pictureX) { + // scroll position for picture active, we need to adjust drawX accordingly + drawX -= pictureX; + if (drawX < 0) { + skipCelBitmapPixels = -drawX; + displayWidth -= skipCelBitmapPixels; + drawX = 0; } - } else { - // Draw bitmap to screen (mirrored) - x = rightX - 1; - while (y < lastY) { - curByte = *ptr++; - if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y))) - _screen->putPixel(x, y, drawMask, curByte, priority, 0); - - if (x == leftX) { - if (width > rightX - leftX) // Skip extra pixels at the end of the row - ptr += width - (rightX - leftX); - x = rightX; - y++; + } + + if (displayWidth > 0) { + y = displayArea.top + drawY; + lastY = MIN<int16>(height + y, displayArea.bottom); + leftX = displayArea.left + drawX; + rightX = MIN<int16>(displayWidth + leftX, displayArea.right); + + uint16 sourcePixelSkipPerRow = 0; + if (width > rightX - leftX) + sourcePixelSkipPerRow = width - (rightX - leftX); + + // Change clearcolor to white, if we dont add to an existing picture. That way we will paint everything on screen + // but white and that wont matter because the screen is supposed to be already white. It seems that most (if not all) + // SCI1.1 games use color 0 as transparency and SCI1 games use color 255 as transparency. Sierra SCI seems to paint + // the whole data to screen and wont skip over transparent pixels. So this will actually make it work like Sierra + if (!_addToFlag) + clearColor = _screen->getColorWhite(); + + byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY; + + ptr = celBitmap; + ptr += skipCelBitmapPixels; + if (!_mirroredFlag) { + // Draw bitmap to screen + x = leftX; + while (y < lastY) { + curByte = *ptr++; + if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y))) + _screen->putPixel(x, y, drawMask, curByte, priority, 0); + + x++; + + if (x >= rightX) { + ptr += sourcePixelSkipPerRow; + x = leftX; + y++; + } } + } else { + // Draw bitmap to screen (mirrored) + x = rightX - 1; + while (y < lastY) { + curByte = *ptr++; + if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y))) + _screen->putPixel(x, y, drawMask, curByte, priority, 0); + + if (x == leftX) { + ptr += sourcePixelSkipPerRow; + x = rightX; + y++; + } - x--; + x--; + } } } @@ -652,7 +669,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) { vectorGetAbsCoordsNoMirror(data, curPos, x, y); size = READ_LE_UINT16(data + curPos); curPos += 2; _priority = pic_priority; // set global priority so the cel gets drawn using current priority as well - drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y); + drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y, 0); curPos += size; break; case PIC_OPX_EGA_SET_PRIORITY_TABLE: @@ -692,7 +709,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) { vectorGetAbsCoordsNoMirror(data, curPos, x, y); size = READ_LE_UINT16(data + curPos); curPos += 2; _priority = pic_priority; // set global priority so the cel gets drawn using current priority as well - drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y); + drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y, 0); curPos += size; break; case PIC_OPX_VGA_PRIORITY_TABLE_EQDIST: diff --git a/engines/sci/graphics/picture.h b/engines/sci/graphics/picture.h index c3e844fb9b..b3a0a1509c 100644 --- a/engines/sci/graphics/picture.h +++ b/engines/sci/graphics/picture.h @@ -59,14 +59,14 @@ public: int16 getSci32celY(int16 celNo); int16 getSci32celX(int16 celNo); int16 getSci32celPriority(int16 celNo); - void drawSci32Vga(int16 celNo, int16 callerX, int16 callerY, bool mirrored); + void drawSci32Vga(int16 celNo, int16 callerX, int16 callerY, int16 pictureX, bool mirrored); #endif private: void initData(GuiResourceId resourceId); void reset(); void drawSci11Vga(); - void drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 callerX, int16 callerY); + void drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 drawX, int16 drawY, int16 pictureX); void drawVectorData(byte *data, int size); bool vectorIsNonOpcode(byte pixel); void vectorGetAbsCoords(byte *data, int &curPos, int16 &x, int16 &y); |