mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-03 17:33:05 +00:00
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:
parent
7b295995dc
commit
25b9a8a1cb
File diff suppressed because it is too large
Load Diff
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user