SCI: some scrolling support for sci32

not fully done yet

svn-id: r51308
This commit is contained in:
Martin Kiewitz 2010-07-26 12:20:07 +00:00
parent ea8271f3cb
commit c0d915b616
3 changed files with 80 additions and 59 deletions

View File

@ -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) {

View File

@ -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++;
}
}
x--;
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--;
}
}
}
@ -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:

View File

@ -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);