[Scummvm-cvs-logs] SF.net SVN: scummvm: [31306] scummvm/trunk/engines/kyra
athrxx at users.sourceforge.net
athrxx at users.sourceforge.net
Sun Mar 30 00:16:44 CET 2008
Revision: 31306
http://scummvm.svn.sourceforge.net/scummvm/?rev=31306&view=rev
Author: athrxx
Date: 2008-03-29 16:16:44 -0700 (Sat, 29 Mar 2008)
Log Message:
-----------
New drawShape code for Kyra 1 and 2. Scaled sprites no longer appear mutilated. This also fixes bug #1582675 (KYRA1: Brandon standing IN the floor).
This still needs some testing (for both Kyra 1 and Kyra 2).
Modified Paths:
--------------
scummvm/trunk/engines/kyra/screen.cpp
scummvm/trunk/engines/kyra/screen.h
scummvm/trunk/engines/kyra/screen_v2.cpp
scummvm/trunk/engines/kyra/screen_v2.h
Modified: scummvm/trunk/engines/kyra/screen.cpp
===================================================================
--- scummvm/trunk/engines/kyra/screen.cpp 2008-03-29 23:04:10 UTC (rev 31305)
+++ scummvm/trunk/engines/kyra/screen.cpp 2008-03-29 23:16:44 UTC (rev 31306)
@@ -1118,35 +1118,49 @@
_curDim = &_screenDimTable[dim];
}
+const ScreenDim *Screen::getScreenDim(int dim) {
+ debugC(9, kDebugLevelScreen, "Screen::getScreenDim(%d)", dim);
+ assert(dim < _screenDimTableCount);
+ return &_screenDimTable[dim];
+}
+
void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...) {
debugC(9, kDebugLevelScreen, "Screen::drawShape(%d, %p, %d, %d, %d, 0x%.04X, ...)", pageNum, (const void *)shapeData, x, y, sd, flags);
if (!shapeData)
return;
+
+ int f = _vm->gameFlags().useAltShapeHeader ? 2 : 0;
+ if (shapeData[f] & 1)
+ flags |= 0x400;
+
va_list args;
va_start(args, flags);
- static int drawShapeVar1 = 0;
static int drawShapeVar2[] = {
1, 3, 2, 5, 4, 3, 2, 1
};
- static int drawShapeVar3 = 1;
- static int drawShapeVar4 = 0;
- static int drawShapeVar5 = 0;
- uint8 *table = 0;
- int tableLoopCount = 0;
- int drawLayer = 0;
- uint8 *table2 = 0;
+ _drawShapeVar1 = 0;
+ _drawShapeVar3 = 1;
+ _drawShapeVar4 = 0;
+ _drawShapeVar5 = 0;
+
+ _dsTable = 0;
+ _dsTableLoopCount = 0;
+ _dsTable2 = 0;
+ _dsDrawLayer = 0;
+
uint8 *table3 = 0;
uint8 *table4 = 0;
- if (flags & 0x8000)
- table2 = va_arg(args, uint8*);
+ if (flags & 0x8000) {
+ _dsTable2 = va_arg(args, uint8*);
+ }
if (flags & 0x100) {
- table = va_arg(args, uint8*);
- tableLoopCount = va_arg(args, int);
- if (!tableLoopCount)
+ _dsTable = va_arg(args, uint8*);
+ _dsTableLoopCount = va_arg(args, int);
+ if (!_dsTableLoopCount)
flags &= 0xFFFFFEFF;
}
@@ -1156,480 +1170,566 @@
}
if (flags & 0x200) {
- drawShapeVar1 += 1;
- drawShapeVar1 &= 7;
- drawShapeVar3 = drawShapeVar2[drawShapeVar1];
- drawShapeVar4 = 0;
- drawShapeVar5 = 256;
+ _drawShapeVar1 += 1;
+ _drawShapeVar1 &= 7;
+ _drawShapeVar3 = drawShapeVar2[_drawShapeVar1];
+ _drawShapeVar4 = 0;
+ _drawShapeVar5 = 256;
}
if (flags & 0x4000) {
- drawShapeVar5 = va_arg(args, int);
+ _drawShapeVar5 = va_arg(args, int);
}
if (flags & 0x800) {
- drawLayer = va_arg(args, int);
+ _dsDrawLayer = va_arg(args, int);
}
- int scale_w, scale_h;
if (flags & DSF_SCALE) {
- scale_w = va_arg(args, int);
- scale_h = va_arg(args, int);
+ _dsScaleW = va_arg(args, int);
+ _dsScaleH = va_arg(args, int);
} else {
- scale_w = 0x100;
- scale_h = 0x100;
+ _dsScaleW = 0x100;
+ _dsScaleH = 0x100;
}
+ if (flags & 0x2000 && _vm->gameFlags().gameID == GI_KYRA2) {
+ int UNK = va_arg(args, int);
+ }
+
+ static const DsMarginSkipFunc dsMarginFunc[] = {
+ &Screen::drawShape_margin_noScale_upwind,
+ &Screen::drawShape_margin_noScale_downwind,
+ &Screen::drawShape_margin_noScale_upwind,
+ &Screen::drawShape_margin_noScale_downwind,
+ &Screen::drawShape_margin_scale_upwind,
+ &Screen::drawShape_margin_scale_downwind,
+ &Screen::drawShape_margin_scale_upwind,
+ &Screen::drawShape_margin_scale_downwind
+ };
+
+ static const DsMarginSkipFunc dsSkipFunc[] = {
+ &Screen::drawShape_margin_noScale_upwind,
+ &Screen::drawShape_margin_noScale_downwind,
+ &Screen::drawShape_margin_noScale_upwind,
+ &Screen::drawShape_margin_noScale_downwind,
+ &Screen::drawShape_skip_scale_upwind,
+ &Screen::drawShape_skip_scale_downwind,
+ &Screen::drawShape_skip_scale_upwind,
+ &Screen::drawShape_skip_scale_downwind
+ };
+
+ static const DsLineFunc dsLineFunc[] = {
+ &Screen::drawShape_processLine_noScale_upwind,
+ &Screen::drawShape_processLine_noScale_downwind,
+ &Screen::drawShape_processLine_noScale_upwind,
+ &Screen::drawShape_processLine_noScale_downwind,
+ &Screen::drawShape_processLine_scale_upwind,
+ &Screen::drawShape_processLine_scale_downwind,
+ &Screen::drawShape_processLine_scale_upwind,
+ &Screen::drawShape_processLine_scale_downwind
+ };
+
+ static const DsPlotFunc dsPlotFunc[] = {
+ &Screen::drawShapePlotType0, // used by Kyra 1 + 2
+ 0, 0, 0,
+ &Screen::drawShapePlotType4, // used by Kyra 1 + 2
+ 0, 0, 0,
+ &Screen::drawShapePlotType8, // used by Kyra 2
+ &Screen::drawShapePlotType9, // used by Kyra 1
+ 0, 0,
+ &Screen::drawShapePlotType12, // used by Kyra 2
+ &Screen::drawShapePlotType13, // used by Kyra 1
+ &Screen::drawShapePlotType14, // used by Kyra 1 (invisibility)
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ int scaleCounterV = 0;
+
+ f = flags & 0x0f;
+ _dsProcessMargin = dsMarginFunc[f];
+ _dsScaleSkip = dsSkipFunc[f];
+ _dsProcessLine = dsLineFunc[f];
+
int ppc = (flags >> 8) & 0x3F;
+ _dsPlot = dsPlotFunc[ppc];
+ if (!_dsPlot) {
+ warning("Missing drawShape plotting method type %d", ppc);
+ va_end(args);
+ return;
+ }
+
const uint8 *src = shapeData;
+ const uint8 *dst = _dsDstPage = getPagePtr(pageNum);
+
+ const ScreenDim *dsDim = getScreenDim(sd);
+ dst += (dsDim->sx << 3);
+
+ if (!(flags & 0x10))
+ x -= (dsDim->sx << 3);
+
+ int x2 = (dsDim->w << 3);
+ int y1 = dsDim->sy;
+ if (flags & 0x10)
+ y += y1;
+
+ int y2 = y1 + dsDim->h;
+
if (_vm->gameFlags().useAltShapeHeader)
src += 2;
-
uint16 shapeFlags = READ_LE_UINT16(src); src += 2;
int shapeHeight = *src++;
- int scaledShapeHeight = (shapeHeight * scale_h) >> 8;
- if (scaledShapeHeight == 0) {
- va_end(args);
- return;
- }
+ uint16 shapeWidth = READ_LE_UINT16(src); src += 2;
- int shapeWidth = READ_LE_UINT16(src); src += 2;
- int scaledShapeWidth = (shapeWidth * scale_w) >> 8;
- if (scaledShapeWidth == 0) {
- va_end(args);
- return;
+ int shpWidthScaled1 = shapeWidth;
+ int shpWidthScaled2 = shapeWidth;
+
+ if (flags & DSF_SCALE) {
+ shapeHeight = (shapeHeight * _dsScaleH) >> 8;
+ shpWidthScaled1 = shpWidthScaled2 = (shapeWidth * _dsScaleW) >> 8;
+
+ if (!shapeHeight || !shpWidthScaled1) {
+ va_end(args);
+ return;
+ }
}
if (flags & DSF_CENTER) {
- x -= scaledShapeWidth >> 1;
- y -= scaledShapeHeight >> 1;
+ x -= (shpWidthScaled1 >> 1);
+ y -= (shapeHeight >> 1);
}
src += 3;
uint16 frameSize = READ_LE_UINT16(src); src += 2;
- if ((shapeFlags & 1) || (flags & 0x400))
- src += 0x10;
+ int colorTableColors = ((_vm->gameFlags().gameID == GI_KYRA2) && (shapeFlags & 4)) ? *src++ : 16;
+
+ if (!(flags & 0x8000) && (shapeFlags & 1))
+ _dsTable2 = src;
+
+ if (flags & 0x400)
+ src += colorTableColors;
+
if (!(shapeFlags & 2)) {
decodeFrame4(src, _animBlockPtr, frameSize);
src = _animBlockPtr;
}
- int shapeSize = shapeWidth * shapeHeight;
- if (_decodeShapeBufferSize < shapeSize) {
- delete [] _decodeShapeBuffer;
- _decodeShapeBuffer = new uint8[shapeSize];
- _decodeShapeBufferSize = shapeSize;
+ int t = (flags & 2) ? y2 - y - shapeHeight : y - y1;
+
+ const uint8 *s = (uint8*) src;
+
+ if (t < 0) {
+ shapeHeight += t;
+ if (shapeHeight <= 0) {
+ va_end(args);
+ return;
+ }
+
+ t *= -1;
+ const uint8 *tmp = dst;
+
+ do {
+ _dsOffscreenScaleVal1 = 0;
+ _dsTmpWidth = shapeWidth;
+ int cnt = shapeWidth;
+ (this->*_dsScaleSkip)(tmp, s, cnt);
+ scaleCounterV += _dsScaleH;
+ if (!(scaleCounterV & 0xff00))
+ continue;
+ uint8 r = scaleCounterV >> 8;
+ scaleCounterV &= 0xff;
+ t -= r;
+ } while (t > 0);
+
+ if (t < 0)
+ scaleCounterV += (-t << 8);
+
+ if (!(flags & 2))
+ y = y1;
}
- if (!_decodeShapeBuffer) {
- _decodeShapeBufferSize = 0;
+ t = (flags & 2) ? y + shapeHeight - y1 : y2 - y;
+ if (t <= 0) {
va_end(args);
return;
}
- memset(_decodeShapeBuffer, 0, _decodeShapeBufferSize);
- uint8 *decodedShapeFrame = _decodeShapeBuffer;
- // only used if shapeFlag & 1 is NOT zero
- const uint8 *colorTable = shapeData + 10;
- if (_vm->gameFlags().useAltShapeHeader)
- colorTable += 2;
+ if (t < shapeHeight) {
+ shapeHeight = t;
+ if (flags & 2)
+ y = y1;
+ }
- for (int j = 0; j < shapeHeight; ++j) {
- uint8 *dsbNextLine = decodedShapeFrame + shapeWidth;
- int count = shapeWidth;
- while (count > 0) {
- uint8 code = *src++;
- if (code != 0) {
- // this is guessed
- if (shapeFlags & 1) {
- if (code < 16)
- *decodedShapeFrame++ = colorTable[code];
- } else {
- *decodedShapeFrame++ = code;
- }
- --count;
- } else {
- code = *src++;
- decodedShapeFrame += code;
- count -= code;
- }
+ _dsOffscreenLeft = 0;
+ if (x < 0) {
+ shpWidthScaled1 += x;
+ _dsOffscreenLeft = -x;
+ if (_dsOffscreenLeft >= shpWidthScaled2) {
+ va_end(args);
+ return;
}
- decodedShapeFrame = dsbNextLine;
+ x = 0;
}
- uint16 sx1 = _screenDimTable[sd].sx * 8;
- uint16 sy1 = _screenDimTable[sd].sy;
- uint16 sx2 = sx1 + _screenDimTable[sd].w * 8;
- uint16 sy2 = sy1 + _screenDimTable[sd].h;
- if (flags & DSF_WND_COORDS) {
- x += sx1;
- y += sy1;
+ _dsOffscreenRight = 0;
+ t = x2 - x;
+
+ if (t <= 0) {
+ va_end(args);
+ return;
}
- int x1, x2;
- if (x >= 0) {
- x1 = 0;
- if (x + scaledShapeWidth < sx2)
- x2 = scaledShapeWidth;
- else
- x2 = sx2 - x;
- } else {
- x2 = scaledShapeWidth;
- x1 = -x;
- x = 0;
- if (x2 > sx2)
- x2 = sx2;
+ if (t < shpWidthScaled1) {
+ shpWidthScaled1 = t;
+ _dsOffscreenRight = shpWidthScaled2 - _dsOffscreenLeft - shpWidthScaled1;
}
- int y1, y2;
- if (y >= 0) {
- y1 = 0;
- if (y + scaledShapeHeight < sy2)
- y2 = scaledShapeHeight;
- else
- y2 = sy2 - y;
- } else {
- y2 = scaledShapeHeight;
- y1 = -y;
- y = 0;
- if (y2 > sy2)
- y2 = sy2;
+ int dsPitch = 320;
+ int ty = y;
+
+ if (flags & 2) {
+ dsPitch *= -1;
+ ty = ty - 1 + shapeHeight;
}
- uint8 *dst = getPagePtr(pageNum) + y * SCREEN_W + x;
- uint8 *dstStart = getPagePtr(pageNum);
+ if (flags & DSF_X_FLIPPED) {
+ SWAP(_dsOffscreenLeft, _dsOffscreenRight);
+ dst += (shpWidthScaled1 - 1);
+ }
+
+ dst += (320 * ty + x);
+ const uint8 *d = dst;
+
+ if (flags & DSF_SCALE) {
+ _dsOffscreenRight = 0;
+ _dsOffscreenScaleVal2 = _dsOffscreenLeft;
+ _dsOffscreenLeft <<= 8;
+ _dsOffscreenScaleVal1 = _dsOffscreenLeft % _dsScaleW;
+ _dsOffscreenLeft /= _dsScaleW;
+ }
+
if (pageNum == 0 || pageNum == 1)
- addDirtyRect(x, y, x2-x1, y2-y1);
- clearOverlayRect(pageNum, x, y, x2-x1, y2-y1);
+ addDirtyRect(x, y, shpWidthScaled1, shapeHeight);
+ clearOverlayRect(pageNum, x, y, shpWidthScaled1, shapeHeight);
- int scaleYTable[SCREEN_H];
- assert(y1 >= 0 && y2 < SCREEN_H);
- for (y = y1; y < y2; ++y)
- scaleYTable[y] = (y << 8) / scale_h;
+ while (shapeHeight--) {
+ while (!(scaleCounterV & 0xff00)) {
+ scaleCounterV += _dsScaleH;
+ if (!(scaleCounterV & 0xff00)) {
+ _dsTmpWidth = shapeWidth;
+ int cnt = shapeWidth;
+ (this->*_dsScaleSkip)(d, s, cnt);
+ }
+ }
- int scaleXTable[SCREEN_W];
- assert(x1 >= 0 && x2 < SCREEN_W);
- for (x = x1; x < x2; ++x)
- scaleXTable[x] = (x << 8) / scale_w;
+ const uint8 *b_src = s;
- const uint8 *shapeBuffer = _decodeShapeBuffer;
- if (flags & DSF_Y_FLIPPED)
- shapeBuffer += shapeWidth * (shapeHeight - 1);
- if (flags & DSF_X_FLIPPED)
- shapeBuffer += shapeWidth - 1;
+ do {
+ s = b_src;
+ _dsTmpWidth = shapeWidth;
+ int cnt = _dsOffscreenLeft;
+ int scaleState = (this->*_dsProcessMargin)(d, s, cnt);
+ if (_dsTmpWidth) {
+ cnt += shpWidthScaled1;
+ if (cnt > 0)
+ (this->*_dsProcessLine)(d, s, cnt, scaleState);
+ cnt += _dsOffscreenRight;
+ if (cnt)
+ (this->*_dsScaleSkip)(d, s, cnt);
+ }
+ dst += dsPitch;
+ d = dst;
+ scaleCounterV -= 256;
+ } while (scaleCounterV & 0xff00);
+ }
- for (y = y1; y < y2; ++y) {
- uint8 *dstNextLine = dst + SCREEN_W;
- int j = scaleYTable[y];
- if (flags & DSF_Y_FLIPPED)
- j = -j;
+ va_end(args);
+}
- for (x = x1; x < x2; ++x) {
- int xpos = scaleXTable[x];
- if (flags & DSF_X_FLIPPED)
- xpos = -xpos;
+int Screen::drawShape_margin_noScale_upwind(const uint8 *& dst, const uint8 *& src, int & cnt) {
+ while (cnt-- > 0) {
+ if (*src++)
+ continue;
+ cnt = cnt + 1 - (*src++);
+ }
+
+ cnt++;
+ dst -= cnt;
+ return 0;
+}
- uint8 color = shapeBuffer[j * shapeWidth + xpos];
- if (color != 0) {
- switch (ppc) {
- case 0:
- *dst = color;
- break;
+int Screen::drawShape_margin_noScale_downwind(const uint8 *& dst, const uint8 *& src, int & cnt) {
+ while (cnt-- > 0) {
+ if (*src++)
+ continue;
+ cnt = cnt + 1 - (*src++);
+ }
+
+ cnt++;
+ dst += cnt;
+ return 0;
+}
- case 1:
- for (int i = 0; i < tableLoopCount; ++i)
- color = table[color];
- break;
+int Screen::drawShape_margin_scale_upwind(const uint8 *& dst, const uint8 *& src, int & cnt) {
+ _dsTmpWidth -= cnt;
+ bool found = false;
- case 2: {
- int temp = drawShapeVar4 + drawShapeVar5;
- if (temp & 0xFF00) {
- drawShapeVar4 = temp & 0xFF;
- dst += drawShapeVar3;
- color = *dst;
- dst -= drawShapeVar3;
- } else {
- drawShapeVar4 = temp;
- }
- }
- break;
+ if (src == dst || !cnt)
+ return _dsOffscreenScaleVal1;
- case 7:
- case 3:
- color = *dst;
- for (int i = 0; i < tableLoopCount; ++i)
- color = table[color];
- break;
+ while (cnt-- > 0) {
+ if (*src++)
+ continue;
+ found = true;
+ cnt = cnt + 1 - (*src++);
+ }
- case 4:
- color = table2[color];
- break;
+ if (!found)
+ return _dsOffscreenScaleVal1;
- case 5:
- color = table2[color];
- for (int i = 0; i < tableLoopCount; ++i)
- color = table[color];
- break;
+ _dsTmpWidth += cnt;
- case 6: {
- int temp = drawShapeVar4 + drawShapeVar5;
- if (temp & 0xFF00) {
- drawShapeVar4 = temp & 0xFF;
- dst += drawShapeVar3;
- color = *dst;
- dst -= drawShapeVar3;
- } else {
- drawShapeVar4 = temp;
- color = table2[color];
- }
- }
- break;
+ int i = (_dsOffscreenLeft - cnt) * _dsScaleW;
+ int res = i & 0xff;
+ i >>= 8;
+ i -= _dsOffscreenScaleVal2;
+ dst += i;
+ cnt = -i;
- case 8: {
- int offset = dst - dstStart;
- uint8 pixel = *(_shapePages[0] + offset);
- pixel &= 0x7F;
- pixel &= 0x87;
- if (drawLayer < pixel)
- color = *(_shapePages[1] + offset);
- }
- break;
+ return res;
+}
- case 9: {
- int offset = dst - dstStart;
- uint8 pixel = *(_shapePages[0] + offset);
- pixel &= 0x7F;
- pixel &= 0x87;
+int Screen::drawShape_margin_scale_downwind(const uint8 *& dst, const uint8 *& src, int & cnt) {
+ _dsTmpWidth -= cnt;
+ bool found = false;
- if (drawLayer < pixel) {
- color = *(_shapePages[1] + offset);
- } else {
- for (int i = 0; i < tableLoopCount; ++i)
- color = table[color];
- }
- }
- break;
+ if (src == dst || !cnt)
+ return _dsOffscreenScaleVal1;
- case 10: {
- int offset = dst - dstStart;
- uint8 pixel = *(_shapePages[0] + offset);
- pixel &= 0x7F;
- pixel &= 0x87;
- if (drawLayer < pixel) {
- color = *(_shapePages[1] + offset);
- drawShapeVar4 = pixel;
- } else {
- int temp = drawShapeVar4 + drawShapeVar5;
- if (temp & 0xFF00) {
- dst += drawShapeVar3;
- color = *dst;
- dst -= drawShapeVar3;
- }
- drawShapeVar4 = temp & 0xFF;
- }
- }
- break;
+ while (cnt-- > 0) {
+ if (*src++)
+ continue;
+ found = true;
+ cnt = cnt + 1 - (*src++);
+ }
- case 15:
- case 11: {
- int offset = dst - dstStart;
- uint8 pixel = *(_shapePages[0] + offset);
- pixel &= 0x7F;
- pixel &= 0x87;
- if (drawLayer < pixel) {
- color = *(_shapePages[1] + offset);
- } else {
- color = *dst;
- for (int i = 0; i < tableLoopCount; ++i)
- color = table[color];
- }
- }
- break;
+ if (!found)
+ return _dsOffscreenScaleVal1;
- case 12: {
- int offset = dst - dstStart;
- uint8 pixel = *(_shapePages[0] + offset);
- pixel &= 0x7F;
- pixel &= 0x87;
- if (drawLayer < pixel) {
- color = *(_shapePages[1] + offset);
- } else {
- color = table2[color];
- }
- }
- break;
+ _dsTmpWidth += cnt;
- case 13: {
- int offset = dst - dstStart;
- uint8 pixel = *(_shapePages[0] + offset);
- pixel &= 0x7F;
- pixel &= 0x87;
- if (drawLayer < pixel) {
- color = *(_shapePages[1] + offset);
- } else {
- color = table2[color];
- for (int i = 0; i < tableLoopCount; ++i)
- color = table[color];
- }
- }
- break;
+ int i = (_dsOffscreenLeft - cnt) * _dsScaleW;
+ int res = i & 0xff;
+ i >>= 8;
+ i -= _dsOffscreenScaleVal2;
+ dst -= i;
+ cnt = -i;
- case 14: {
- int offset = dst - dstStart;
- uint8 pixel = *(_shapePages[0] + offset);
- pixel &= 0x7F;
- pixel &= 0x87;
- if (drawLayer < pixel) {
- color = *(_shapePages[1] + offset);
- drawShapeVar4 = pixel;
- } else {
- int temp = drawShapeVar4 + drawShapeVar5;
- if (temp & 0xFF00) {
- dst += drawShapeVar3;
- color = *dst;
- dst -= drawShapeVar3;
- drawShapeVar4 = temp % 0xFF;
- } else {
- drawShapeVar4 = temp;
- color = table2[color];
- }
- }
- }
- break;
+ return res;
+}
- case 16: {
- uint8 newColor = table3[color];
- if (!(newColor & 0x80)) {
- color = *dst;
- color = table4[color + (newColor << 8)];
- }
- }
- break;
+int Screen::drawShape_skip_scale_upwind(const uint8 *& dst, const uint8 *& src, int & cnt) {
+ cnt = _dsTmpWidth;
- case 17: {
- for (int i = 0; i < tableLoopCount; ++i)
- color = table[color];
+ if (cnt <= 0)
+ return 0;
- uint8 newColor = table3[color];
- if (!(newColor & 0x80)) {
- color = *dst;
- color = table4[color + (newColor << 8)];
- }
- }
- break;
+ while (cnt-- > 0) {
+ if (*src++)
+ continue;
+ cnt = cnt + 1 - (*src++);
+ }
- case 18: {
- int temp = drawShapeVar4 + drawShapeVar5;
- if (temp & 0xFF00) {
- drawShapeVar4 = temp & 0xFF;
- dst += drawShapeVar3;
- color = *dst;
- dst -= drawShapeVar3;
- uint8 newColor = table3[color];
- if (!(newColor & 0x80)) {
- color = *dst;
- color = table4[color + (newColor << 8)];
- }
- } else {
- drawShapeVar4 = temp;
- }
- }
- break;
+ return 0;
+}
- case 23:
- case 19: {
- color = *dst;
- for (int i = 0; i < tableLoopCount; ++i)
- color = table[color];
+int Screen::drawShape_skip_scale_downwind(const uint8 *& dst, const uint8 *& src, int & cnt) {
+ cnt = _dsTmpWidth;
+ bool found = false;
- uint8 newColor = table3[color];
- if (!(newColor & 0x80)) {
- color = *dst;
- color = table4[color + (newColor << 8)];
- }
- }
- break;
+ if (cnt <= 0)
+ return 0;
- case 20: {
- color = table2[color];
- uint8 newColor = table3[color];
- if (!(newColor & 0x80)) {
- color = *dst;
- color = table4[color + (newColor << 8)];
- }
- }
- break;
+ while (cnt-- > 0) {
+ if (*src++)
+ continue;
+ found = true;
+ cnt = cnt + 1 - (*src++);
+ }
- case 21: {
- color = table2[color];
- for (int i = 0; i < tableLoopCount; ++i)
- color = table[color];
+ return found ? 0 : _dsOffscreenScaleVal1;
+}
- uint8 newColor = table3[color];
- if (!(newColor & 0x80)) {
- color = *dst;
- color = table4[color + (newColor << 8)];
- }
- }
- break;
+void Screen::drawShape_processLine_noScale_upwind(const uint8 *& dst, const uint8 *& src, int & cnt, int) {
+ do {
+ uint8 c = *src++;
+ if (c) {
+ uint8 *d = (uint8*) dst++;
+ (this->*_dsPlot)(d, c);
+ cnt--;
+ } else {
+ c = *src++;
+ dst += c;
+ cnt -= c;
+ }
+ } while (cnt > 0);
+}
- case 22: {
- int temp = drawShapeVar4 + drawShapeVar5;
- if (temp & 0xFF00) {
- drawShapeVar4 = temp & 0xFF;
- dst += drawShapeVar3;
- color = *dst;
- dst -= drawShapeVar3;
- uint8 newColor = table3[color];
- if (!(newColor & 0x80)) {
- color = *dst;
- color = table4[color + (newColor << 8)];
- }
- } else {
- drawShapeVar4 = temp;
- color = table2[color];
- uint8 newColor = table3[color];
- if (!(newColor & 0x80)) {
- color = *dst;
- color = table4[color + (newColor << 8)];
- }
- }
- }
- break;
+void Screen::drawShape_processLine_noScale_downwind(const uint8 *& dst, const uint8 *& src, int & cnt, int) {
+ do {
+ uint8 c = *src++;
+ if (c) {
+ uint8 *d = (uint8*) dst--;
+ (this->*_dsPlot)(d, c);
+ cnt--;
+ } else {
+ c = *src++;
+ dst -= c;
+ cnt -= c;
+ }
+ } while (cnt > 0);
+}
- case 24: {
- int offset = dst - dstStart;
- uint8 pixel = *(_shapePages[0] + offset);
- pixel &= 0x7F;
- pixel &= 0x87;
- if (drawLayer < pixel)
- color = *(_shapePages[1] + offset);
+void Screen::drawShape_processLine_scale_upwind(const uint8 *& dst, const uint8 *& src, int & cnt, int scaleState) {
+ int c = 0;
- uint8 newColor = table3[color];
- if (!(newColor & 0x80)) {
- color = *dst;
- color = table4[color + (newColor << 8)];
- }
- }
- break;
+ do {
+ if ((scaleState >> 8) <= 0) {
+ c = *src++;
+ _dsTmpWidth--;
+ if (c) {
+ scaleState += _dsScaleW;
+ } else {
+ _dsTmpWidth++;
+ c = *src++;
+ _dsTmpWidth -= c;
+ int r = c * _dsScaleW + scaleState;
+ dst += (r >> 8);
+ cnt -= (r >> 8);
+ scaleState = r & 0xff;
+ }
+ } else {
+ uint8 *d = (uint8*) dst++;
+ (this->*_dsPlot)(d, c);
+ scaleState -= 256;
+ cnt--;
+ }
+ } while (cnt > 0);
- default:
- warning("unhandled ppc: %d", ppc);
- break;
- }
- *dst = color;
+ cnt = -1;
+}
+
+void Screen::drawShape_processLine_scale_downwind(const uint8 *& dst, const uint8 *& src, int & cnt, int scaleState) {
+ int c = 0;
+
+ do {
+ if ((scaleState >> 8) <= 0) {
+ c = *src++;
+ _dsTmpWidth--;
+ if (c) {
+ scaleState += _dsScaleW;
+ } else {
+ _dsTmpWidth++;
+ c = *src++;
+ _dsTmpWidth -= c;
+ int r = c * _dsScaleW + scaleState;
+ dst -= (r >> 8);
+ cnt -= (r >> 8);
+ scaleState = r & 0xff;
}
- ++dst;
+ } else {
+ uint8 *d = (uint8*) dst--;
+ (this->*_dsPlot)(d, c);
+ scaleState -= 256;
+ cnt--;
}
- dst = dstNextLine;
+ } while (cnt > 0);
+
+ cnt = -1;
+}
+
+void Screen::drawShapePlotType0(uint8 *dst, uint8 cmd) {
+ *dst = cmd;
+}
+
+void Screen::drawShapePlotType4(uint8 *dst, uint8 cmd) {
+ *dst = _dsTable2[cmd];
+}
+
+void Screen::drawShapePlotType8(uint8 *dst, uint8 cmd) {
+ uint32 relOffs = dst - _dsDstPage;
+ int t = (_shapePages[0][relOffs] & 0x7f) & 0x87;
+ if (_dsDrawLayer < t)
+ cmd = _shapePages[1][relOffs];
+
+ *dst = cmd;
+}
+
+void Screen::drawShapePlotType9(uint8 *dst, uint8 cmd) {
+ uint32 relOffs = dst - _dsDstPage;
+ int t = (_shapePages[0][relOffs] & 0x7f) & 0x87;
+ if (_dsDrawLayer < t) {
+ cmd = _shapePages[1][relOffs];
+ } else {
+ for (int i = 0; i < _dsTableLoopCount; ++i)
+ cmd = _dsTable[cmd];
}
- va_end(args);
+
+ if (cmd)
+ *dst = cmd;
}
+void Screen::drawShapePlotType12(uint8 *dst, uint8 cmd) {
+ uint32 relOffs = dst - _dsDstPage;
+ int t = (_shapePages[0][relOffs] & 0x7f) & 0x87;
+ if (_dsDrawLayer < t) {
+ cmd = _shapePages[1][relOffs];
+ } else {
+ cmd = _dsTable2[cmd];
+ }
+
+ *dst = cmd;
+}
+
+void Screen::drawShapePlotType13(uint8 *dst, uint8 cmd) {
+ uint32 relOffs = dst - _dsDstPage;
+ int t = (_shapePages[0][relOffs] & 0x7f) & 0x87;
+ if (_dsDrawLayer < t) {
+ cmd = _shapePages[1][relOffs];
+ } else {
+ cmd = _dsTable2[cmd];
+ for (int i = 0; i < _dsTableLoopCount; ++i)
+ cmd = _dsTable[cmd];
+ }
+
+ if (cmd)
+ *dst = cmd;
+}
+
+void Screen::drawShapePlotType14(uint8 *dst, uint8 cmd) {
+ uint32 relOffs = dst - _dsDstPage;
+ int t = (_shapePages[0][relOffs] & 0x7f) & 0x87;
+ if (_dsDrawLayer < t) {
+ cmd = _shapePages[1][relOffs];
+ } else {
+ t = _drawShapeVar4 + _drawShapeVar5;
+ if (t & 0xff00) {
+ cmd = dst[_drawShapeVar3];
+ t &= 0xff;
+ } else {
+ cmd = _dsTable2[cmd];
+ }
+ }
+
+ _drawShapeVar4 = t;
+ *dst = cmd;
+}
+
void Screen::decodeFrame3(const uint8 *src, uint8 *dst, uint32 size) {
debugC(9, kDebugLevelScreen, "Screen::decodeFrame3(%p, %p, %u)", (const void *)src, (const void *)dst, size);
const uint8 *dstEnd = dst + size;
Modified: scummvm/trunk/engines/kyra/screen.h
===================================================================
--- scummvm/trunk/engines/kyra/screen.h 2008-03-29 23:04:10 UTC (rev 31305)
+++ scummvm/trunk/engines/kyra/screen.h 2008-03-29 23:16:44 UTC (rev 31306)
@@ -170,6 +170,7 @@
void setTextColor(const uint8 *cmap, int a, int b);
virtual void setScreenDim(int dim);
+ virtual const ScreenDim *getScreenDim(int dim);
// shape handling
uint8 *encodeShape(int x, int y, int w, int h, int flags);
@@ -177,8 +178,53 @@
int setNewShapeHeight(uint8 *shape, int height);
int resetShapeHeight(uint8 *shape);
- virtual void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...);
+ void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...);
+ int drawShape_margin_noScale_upwind(const uint8 *& dst, const uint8 *& src, int & cnt);
+ int drawShape_margin_noScale_downwind(const uint8 *& dst, const uint8 *& src, int & cnt);
+ int drawShape_margin_scale_upwind(const uint8 *& dst, const uint8 *& src, int & cnt);
+ int drawShape_margin_scale_downwind(const uint8 *& dst, const uint8 *& src, int & cnt);
+ int drawShape_skip_scale_upwind(const uint8 *& dst, const uint8 *& src, int & cnt);
+ int drawShape_skip_scale_downwind(const uint8 *& dst, const uint8 *& src, int & cnt);
+ void drawShape_processLine_noScale_upwind(const uint8 *& dst, const uint8 *& src, int & cnt, int scaleState);
+ void drawShape_processLine_noScale_downwind(const uint8 *& dst, const uint8 *& src, int & cnt, int scaleState);
+ void drawShape_processLine_scale_upwind(const uint8 *& dst, const uint8 *& src, int & cnt, int scaleState);
+ void drawShape_processLine_scale_downwind(const uint8 *& dst, const uint8 *& src, int & cnt, int scaleState);
+
+ void drawShapePlotType0(uint8 *dst, uint8 cmd);
+ void drawShapePlotType4(uint8 *dst, uint8 cmd);
+ void drawShapePlotType8(uint8 *dst, uint8 cmd);
+ void drawShapePlotType9(uint8 *dst, uint8 cmd);
+ void drawShapePlotType12(uint8 *dst, uint8 cmd);
+ void drawShapePlotType13(uint8 *dst, uint8 cmd);
+ void drawShapePlotType14(uint8 *dst, uint8 cmd);
+
+ typedef int (Screen::*DsMarginSkipFunc)(const uint8 *& dst, const uint8 *& src, int & cnt);
+ typedef void (Screen::*DsLineFunc)(const uint8 *& dst, const uint8 *& src, int & cnt, int scaleState);
+ typedef void (Screen::*DsPlotFunc)(uint8 * dst, uint8 cmd);
+
+ DsMarginSkipFunc _dsProcessMargin;
+ DsMarginSkipFunc _dsScaleSkip;
+ DsLineFunc _dsProcessLine;
+ DsPlotFunc _dsPlot;
+
+ const uint8 *_dsTable;
+ int _dsTableLoopCount;
+ const uint8 *_dsTable2;
+ int _dsDrawLayer;
+ uint8 *_dsDstPage;
+ int _dsTmpWidth;
+ int _dsOffscreenLeft;
+ int _dsOffscreenRight;
+ int _dsScaleW;
+ int _dsScaleH;
+ int _dsOffscreenScaleVal1;
+ int _dsOffscreenScaleVal2;
+ int _drawShapeVar1;
+ int _drawShapeVar3;
+ int _drawShapeVar4;
+ int _drawShapeVar5;
+
// mouse handling
void hideMouse();
void showMouse();
Modified: scummvm/trunk/engines/kyra/screen_v2.cpp
===================================================================
--- scummvm/trunk/engines/kyra/screen_v2.cpp 2008-03-29 23:04:10 UTC (rev 31305)
+++ scummvm/trunk/engines/kyra/screen_v2.cpp 2008-03-29 23:16:44 UTC (rev 31306)
@@ -551,255 +551,6 @@
return copy;
}
-void Screen_v2::drawShape(uint8 page, const uint8 *shape, int x, int y, int sd, int flags, ...) {
- if (!shape)
- return;
-
- if (*shape & 1)
- flags |= 0x400;
-
- va_list args;
- va_start(args, flags);
-
- static int drawShapeVar1 = 0;
- static int drawShapeVar2[] = {
- 1, 3, 2, 5, 4, 3, 2, 1
- };
- static int drawShapeVar3 = 1;
- static int drawShapeVar4 = 0;
- static int drawShapeVar5 = 0;
-
- uint8 *table = 0;
- int tableLoopCount = 0;
- int drawLayer = 0;
- const uint8 *table2 = 0;
- uint8 *table3 = 0;
- uint8 *table4 = 0;
-
- if (flags & 0x8000) {
- table2 = va_arg(args, uint8*);
- }
- if (flags & 0x100) {
- table = va_arg(args, uint8*);
- tableLoopCount = va_arg(args, int);
- if (!tableLoopCount)
- flags &= 0xFFFFFEFF;
- }
- if (flags & 0x1000) {
- table3 = va_arg(args, uint8*);
- table4 = va_arg(args, uint8*);
- }
- if (flags & 0x200) {
- drawShapeVar1 += 1;
- drawShapeVar1 &= 7;
- drawShapeVar3 = drawShapeVar2[drawShapeVar1];
- drawShapeVar4 = 0;
- drawShapeVar5 = 256;
- }
- if (flags & 0x4000) {
- drawShapeVar5 = va_arg(args, int);
- }
- if (flags & 0x800) {
- drawLayer = va_arg(args, int);
- }
- int scale_w, scale_h;
- if (flags & 0x04) {
- scale_w = va_arg(args, int);
- scale_h = va_arg(args, int);
- } else {
- scale_w = 0x100;
- scale_h = 0x100;
- }
-
- int ppc = (flags >> 8) & 0x3F;
-
- const uint8 *src = shape;
- uint16 shapeFlags = READ_LE_UINT16(src); src += 2;
-
- int shapeHeight = *src++;
- int scaledShapeHeight = (shapeHeight * scale_h) >> 8;
- if (scaledShapeHeight == 0) {
- va_end(args);
- return;
- }
-
- int shapeWidth = READ_LE_UINT16(src); src += 2;
- int scaledShapeWidth = (shapeWidth * scale_w) >> 8;
- if (scaledShapeWidth == 0) {
- va_end(args);
- return;
- }
-
- if (flags & 0x20) {
- x -= scaledShapeWidth >> 1;
- y -= scaledShapeHeight >> 1;
- }
-
- src += 3;
-
- uint16 frameSize = READ_LE_UINT16(src); src += 2;
- int colorTableColors = 0x10;
-
- if (shapeFlags & 4)
- colorTableColors = *src++;
-
- if (!(flags & 0x8000) && (shapeFlags & 1))
- table2 = src;
-
- if ((shapeFlags & 1) || (flags & 0x400))
- src += colorTableColors;
-
- if (!(shapeFlags & 2)) {
- decodeFrame4(src, _animBlockPtr, frameSize);
- src = _animBlockPtr;
- }
-
- int shapeSize = shapeWidth * shapeHeight;
- if (_decodeShapeBufferSize < shapeSize) {
- delete [] _decodeShapeBuffer;
- _decodeShapeBuffer = new uint8[shapeSize];
- _decodeShapeBufferSize = shapeSize;
- }
- if (!_decodeShapeBuffer) {
- _decodeShapeBufferSize = 0;
- va_end(args);
- return;
- }
- memset(_decodeShapeBuffer, 0, _decodeShapeBufferSize);
- uint8 *decodedShapeFrame = _decodeShapeBuffer;
-
- for (int j = 0; j < shapeHeight; ++j) {
- uint8 *dsbNextLine = decodedShapeFrame + shapeWidth;
- int count = shapeWidth;
- while (count > 0) {
- uint8 code = *src++;
- if (code != 0) {
- *decodedShapeFrame++ = code;
- --count;
- } else {
- code = *src++;
- decodedShapeFrame += code;
- count -= code;
- }
- }
- decodedShapeFrame = dsbNextLine;
- }
-
- uint16 sx1 = getScreenDim(sd)->sx << 3;
- uint16 sy1 = getScreenDim(sd)->sy;
- uint16 sx2 = sx1 + (getScreenDim(sd)->w << 3);
- uint16 sy2 = sy1 + getScreenDim(sd)->h;
- if (flags & 0x10) {
- x += sx1;
- y += sy1;
- }
-
- int x1, x2;
- if (x >= 0) {
- x1 = 0;
- if (x + scaledShapeWidth < sx2) {
- x2 = scaledShapeWidth;
- } else {
- x2 = sx2 - x;
- }
- } else {
- x2 = scaledShapeWidth;
- x1 = -x;
- x = 0;
- if (x2 > sx2) {
- x2 = sx2;
- }
- }
-
- int y1, y2;
- if (y >= 0) {
- y1 = 0;
- if (y + scaledShapeHeight < sy2) {
- y2 = scaledShapeHeight;
- } else {
- y2 = sy2 - y;
- }
- } else {
- y2 = scaledShapeHeight;
- y1 = -y;
- y = 0;
- if (y2 > sy2) {
- y2 = sy2;
- }
- }
-
- uint8 *dst = getPagePtr(page) + y * 320 + x;
- uint8 *dstStart = getPagePtr(page);
- if (page == 0 || page == 1)
- addDirtyRect(x, y, x2-x1, y2-y1);
- clearOverlayRect(page, x, y, x2-x1, y2-y1);
-
- int scaleYTable[200];
- for (y = y1; y < y2; ++y) {
- scaleYTable[y] = (y << 8) / scale_h;
- }
- int scaleXTable[320];
- for (x = x1; x < x2; ++x) {
- scaleXTable[x] = (x << 8) / scale_w;
- }
-
- const uint8 *shapeBuffer = _decodeShapeBuffer;
- if (flags & 0x02) {
- shapeBuffer += shapeWidth * (shapeHeight - 1);
- }
- if (flags & 0x01) {
- shapeBuffer += shapeWidth - 1;
- }
-
- for (y = y1; y < y2; ++y) {
- uint8 *dstNextLine = dst + 320;
- int j = scaleYTable[y];
- if (flags & 0x02) {
- j = -j;
- }
- for (x = x1; x < x2; ++x) {
- int xpos = scaleXTable[x];
- if (flags & 0x01)
- xpos = -xpos;
- uint8 color = shapeBuffer[j * shapeWidth + xpos];
- if (color != 0) {
- switch (ppc) {
- case 0:
- *dst = color;
- break;
-
- case 4:
- *dst = table2[color];
- break;
-
- case 8: {
- int layer = _shapePages[0][dst - dstStart] & 7;
- if (drawLayer < layer)
- color = _shapePages[1][dst - dstStart];
- *dst = color;
- } break;
-
- case 12: {
- int layer = _shapePages[0][dst - dstStart] & 7;
- if (drawLayer < layer)
- color = _shapePages[1][dst - dstStart];
- else
- color = table2[color];
- *dst = color;
- } break;
-
- default:
- warning("unhandled ppc: %d", ppc);
- break;
- }
- }
- ++dst;
- }
- dst = dstNextLine;
- }
- va_end(args);
-}
-
int Screen_v2::getRectSize(int w, int h) {
if (w > 320 || h > 200)
return 0;
Modified: scummvm/trunk/engines/kyra/screen_v2.h
===================================================================
--- scummvm/trunk/engines/kyra/screen_v2.h 2008-03-29 23:04:10 UTC (rev 31305)
+++ scummvm/trunk/engines/kyra/screen_v2.h 2008-03-29 23:16:44 UTC (rev 31306)
@@ -68,8 +68,6 @@
uint8 *makeShapeCopy(const uint8 *src, int index);
- void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...);
-
// rect handling
virtual int getRectSize(int w, int h);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list