From d39cdd8e1cfdcf9992f03f6ef72138dbdc3f6bbb Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 14 Oct 2011 13:51:59 +0300 Subject: SCI: More work on the vertical plane offset for SCI32. Still WIP. Vertical clipping is still not finished. This fixes the display in the Torin demo (which uses a scene with loads of items with a vertical offset). --- engines/sci/graphics/frameout.cpp | 36 ++++++++++++++++++++++++----- engines/sci/graphics/frameout.h | 1 + engines/sci/graphics/picture.cpp | 48 +++++++++++++++++++++++++++++---------- engines/sci/graphics/picture.h | 5 ++-- 4 files changed, 70 insertions(+), 20 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 9d15c8233f..9a44f07a60 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -90,6 +90,7 @@ void GfxFrameout::kernelAddPlane(reg_t object) { newPlane.priority = readSelectorValue(_segMan, object, SELECTOR(priority)); newPlane.lastPriority = 0xFFFF; // hidden newPlane.planeOffsetX = 0; + newPlane.planeOffsetY = 0; newPlane.pictureId = 0xFFFF; newPlane.planePictureMirrored = false; newPlane.planeBack = 0; @@ -132,9 +133,14 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) { } else { it->planeOffsetX = 0; } - - if (it->planeRect.top < 0) + + if (it->planeRect.top < 0) { + it->planeOffsetY = -it->planeRect.top; it->planeRect.top = 0; + } else { + it->planeOffsetY = 0; + } + // We get bad plane-bottom in sq6 if (it->planeRect.right > _screen->getWidth()) it->planeRect.right = _screen->getWidth(); @@ -447,7 +453,14 @@ void GfxFrameout::kernelFrameout() { continue; // Out of view vertically (sanity checks) - // TODO + int16 pictureCelStartY = itemEntry->picStartY + itemEntry->y; + int16 pictureCelEndY = pictureCelStartY + itemEntry->picture->getSci32celHeight(itemEntry->celNo); + int16 planeStartY = it->planeOffsetY; + int16 planeEndY = planeStartY + it->planeRect.height(); + if (pictureCelEndY < planeStartY) + continue; + if (pictureCelStartY > planeEndY) + continue; int16 pictureOffsetX = it->planeOffsetX; int16 pictureX = itemEntry->x; @@ -460,8 +473,18 @@ void GfxFrameout::kernelFrameout() { } } - // TODO: pictureOffsetY - itemEntry->picture->drawSci32Vga(itemEntry->celNo, pictureX, itemEntry->y, pictureOffsetX, it->planePictureMirrored); + int16 pictureOffsetY = it->planeOffsetY; + int16 pictureY = itemEntry->y; + if ((it->planeOffsetY) || (itemEntry->picStartY)) { + if (it->planeOffsetY <= itemEntry->picStartY) { + pictureY += itemEntry->picStartY - it->planeOffsetY; + pictureOffsetY = 0; + } else { + pictureOffsetY = it->planeOffsetY - itemEntry->picStartY; + } + } + + itemEntry->picture->drawSci32Vga(itemEntry->celNo, pictureX, itemEntry->y, pictureOffsetX, pictureOffsetY, it->planePictureMirrored); // warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority); } else if (itemEntry->viewId != 0xFFFF) { @@ -482,6 +505,7 @@ void GfxFrameout::kernelFrameout() { // Adjust according to current scroll position itemEntry->x -= it->planeOffsetX; + itemEntry->y -= it->planeOffsetY; uint16 useInsetRect = readSelectorValue(_segMan, itemEntry->object, SELECTOR(useInsetRect)); if (useInsetRect) { @@ -504,7 +528,7 @@ void GfxFrameout::kernelFrameout() { Common::Rect nsRect = itemEntry->celRect; // Translate back to actual coordinate within scrollable plane - nsRect.translate(it->planeOffsetX, 0); + nsRect.translate(it->planeOffsetX, it->planeOffsetY); if (view->isSci2Hires()) { view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left); diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 3176db25fd..160c343b05 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -32,6 +32,7 @@ struct PlaneEntry { uint16 priority; uint16 lastPriority; int16 planeOffsetX; + int16 planeOffsetY; GuiResourceId pictureId; Common::Rect planeRect; Common::Rect planeClipRect; diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index dad2b77036..1c85ecddcf 100644 --- a/engines/sci/graphics/picture.cpp +++ b/engines/sci/graphics/picture.cpp @@ -132,7 +132,7 @@ void GfxPicture::drawSci11Vga() { _palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette); _palette->set(&palette, true); - drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, 0, 0, 0); + drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, 0, 0, 0, 0); } // process vector data @@ -148,18 +148,18 @@ int16 GfxPicture::getSci32celCount() { return inbuffer[2]; } -int16 GfxPicture::getSci32celY(int16 celNo) { +int16 GfxPicture::getSci32celX(int16 celNo) { byte *inbuffer = _resource->data; int header_size = READ_SCI11ENDIAN_UINT16(inbuffer); int cel_headerPos = header_size + 42 * celNo; - return READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 40); + return READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 38); } -int16 GfxPicture::getSci32celX(int16 celNo) { +int16 GfxPicture::getSci32celY(int16 celNo) { byte *inbuffer = _resource->data; int header_size = READ_SCI11ENDIAN_UINT16(inbuffer); int cel_headerPos = header_size + 42 * celNo; - return READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 38); + return READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 40); } int16 GfxPicture::getSci32celWidth(int16 celNo) { @@ -169,6 +169,14 @@ int16 GfxPicture::getSci32celWidth(int16 celNo) { return READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 0); } +int16 GfxPicture::getSci32celHeight(int16 celNo) { + byte *inbuffer = _resource->data; + int header_size = READ_SCI11ENDIAN_UINT16(inbuffer); + int cel_headerPos = header_size + 42 * celNo; + return READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 2); +} + + int16 GfxPicture::getSci32celPriority(int16 celNo) { byte *inbuffer = _resource->data; int header_size = READ_SCI11ENDIAN_UINT16(inbuffer); @@ -176,7 +184,7 @@ int16 GfxPicture::getSci32celPriority(int16 celNo) { return READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 36); } -void GfxPicture::drawSci32Vga(int16 celNo, int16 drawX, int16 drawY, int16 pictureX, bool mirrored) { +void GfxPicture::drawSci32Vga(int16 celNo, int16 drawX, int16 drawY, int16 pictureX, int16 pictureY, bool mirrored) { byte *inbuffer = _resource->data; int size = _resource->size; int header_size = READ_SCI11ENDIAN_UINT16(inbuffer); @@ -216,14 +224,14 @@ void GfxPicture::drawSci32Vga(int16 celNo, int16 drawX, int16 drawY, int16 pictu cel_RlePos = READ_SCI11ENDIAN_UINT32(inbuffer + cel_headerPos + 24); cel_LiteralPos = READ_SCI11ENDIAN_UINT32(inbuffer + cel_headerPos + 28); - drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, drawX, drawY, pictureX); + drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, drawX, drawY, pictureX, pictureY); cel_headerPos += 42; } #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) { +void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 drawX, int16 drawY, int16 pictureX, int16 pictureY) { byte *celBitmap = NULL; byte *ptr = NULL; byte *headerPtr = inbuffer + headerPos; @@ -300,10 +308,11 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea(); + // Horizontal clipping uint16 skipCelBitmapPixels = 0; int16 displayWidth = width; if (pictureX) { - // scroll position for picture active, we need to adjust drawX accordingly + // horizontal scroll position for picture active, we need to adjust drawX accordingly drawX -= pictureX; if (drawX < 0) { skipCelBitmapPixels = -drawX; @@ -312,7 +321,21 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos } } - if (displayWidth > 0) { + // Vertical clipping + uint16 skipCelBitmapLines = 0; + int16 displayHeight = height; + if (pictureY) { + // vertical scroll position for picture active, we need to adjust drawY accordingly + // TODO: Finish this + /*drawY -= pictureY; + if (drawY < 0) { + skipCelBitmapLines = -drawY; + displayHeight -= skipCelBitmapLines; + drawY = 0; + }*/ + } + + if (displayWidth > 0 && displayHeight > 0) { y = displayArea.top + drawY; lastY = MIN(height + y, displayArea.bottom); leftX = displayArea.left + drawX; @@ -334,6 +357,7 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos ptr = celBitmap; ptr += skipCelBitmapPixels; + ptr += skipCelBitmapLines * width; if (!_mirroredFlag) { // Draw bitmap to screen x = leftX; @@ -714,7 +738,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, 0); + drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y, 0, 0); curPos += size; break; case PIC_OPX_EGA_SET_PRIORITY_TABLE: @@ -757,7 +781,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, 0); + drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y, 0, 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 78623d5e09..4f075a6226 100644 --- a/engines/sci/graphics/picture.h +++ b/engines/sci/graphics/picture.h @@ -56,15 +56,16 @@ public: int16 getSci32celY(int16 celNo); int16 getSci32celX(int16 celNo); int16 getSci32celWidth(int16 celNo); + int16 getSci32celHeight(int16 celNo); int16 getSci32celPriority(int16 celNo); - void drawSci32Vga(int16 celNo, int16 callerX, int16 callerY, int16 pictureX, bool mirrored); + void drawSci32Vga(int16 celNo, int16 callerX, int16 callerY, int16 pictureX, int16 pictureY, 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 drawX, int16 drawY, int16 pictureX); + void drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 drawX, int16 drawY, int16 pictureX, int16 pictureY); void drawVectorData(byte *data, int size); bool vectorIsNonOpcode(byte pixel); void vectorGetAbsCoords(byte *data, int &curPos, int16 &x, int16 &y); -- cgit v1.2.3