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).

svn-id: r31306
This commit is contained in:
Florian Kagerer 2008-03-29 23:16:44 +00:00
parent 7b295995dc
commit 25b9a8a1cb
4 changed files with 578 additions and 683 deletions

File diff suppressed because it is too large Load Diff

View File

@ -170,6 +170,7 @@ public:
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,7 +178,52 @@ public:
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();

View File

@ -551,255 +551,6 @@ uint8 *Screen_v2::makeShapeCopy(const uint8 *src, int index) {
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;

View File

@ -68,8 +68,6 @@ public:
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);