Experimental semi-transparency for fillRect, used in the green/red menu areas of Urban Runner

svn-id: r35406
This commit is contained in:
Sven Hesse 2008-12-16 23:27:35 +00:00
parent 98bbf9c417
commit adae869c8a
6 changed files with 121 additions and 2 deletions

View File

@ -137,6 +137,12 @@ inline int PaletteLUT::getIndex(byte c1, byte c2, byte c3) const {
return ((c1 >> _shift) << _depth2) | ((c2 >> _shift) << _depth1) | (c3 >> _shift);
}
void PaletteLUT::getEntry(byte index, byte &c1, byte &c2, byte &c3) const {
c1 = _realPal[index * 3 + 0];
c2 = _realPal[index * 3 + 1];
c3 = _realPal[index * 3 + 2];
}
byte PaletteLUT::findNearest(byte c1, byte c2, byte c3) {
return _lut[getIndex(c1, c2, c3)];
}

View File

@ -60,6 +60,7 @@ public:
void buildNext();
void getEntry(byte index, byte &c1, byte &c2, byte &c3) const;
byte findNearest(byte c1, byte c2, byte c3);
byte findNearest(byte c1, byte c2, byte c3, byte &nC1, byte &nC2, byte &nC3);

View File

@ -630,6 +630,7 @@ protected:
bool o6_evaluateStore(OpFuncParams &params);
bool o6_palLoad(OpFuncParams &params);
bool o6_freeCollision(OpFuncParams &params);
bool o6_fillRect(OpFuncParams &params);
void probe16bitMusic(char *fileName);
};

View File

@ -439,7 +439,7 @@ void Inter_v6::setupOpcodes() {
OPCODE(o1_returnTo),
OPCODE(o1_loadSpriteContent),
OPCODE(o1_copySprite),
OPCODE(o1_fillRect),
OPCODE(o6_fillRect),
/* 34 */
OPCODE(o1_drawLine),
OPCODE(o1_strToLong),
@ -947,6 +947,45 @@ bool Inter_v6::o6_freeCollision(OpFuncParams &params) {
return false;
}
bool Inter_v6::o6_fillRect(OpFuncParams &params) {
int16 destSurf;
_vm->_draw->_destSurface = destSurf = load16();
_vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
_vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
_vm->_draw->_spriteRight = _vm->_parse->parseValExpr();
_vm->_draw->_spriteBottom = _vm->_parse->parseValExpr();
evalExpr(0);
_vm->_draw->_backColor = _vm->_global->_inter_resVal & 0xFFFF;
uint16 word_63E64 = _vm->_global->_inter_resVal >> 16;
if (word_63E64 != 0)
warning("Urban Stub: o6_fillRect(), word_63E64 = %d", word_63E64);
if (_vm->_draw->_spriteRight < 0) {
_vm->_draw->_destSpriteX += _vm->_draw->_spriteRight - 1;
_vm->_draw->_spriteRight = -_vm->_draw->_spriteRight + 2;
}
if (_vm->_draw->_spriteBottom < 0) {
_vm->_draw->_destSpriteY += _vm->_draw->_spriteBottom - 1;
_vm->_draw->_spriteBottom = -_vm->_draw->_spriteBottom + 2;
}
if (destSurf & 0x80) {
warning("Urban Stub: o6_fillRect(), destSurf & 0x80");
return false;
}
if (!_vm->_draw->_spritesArray[(destSurf > 100) ? (destSurf - 80) : destSurf])
return false;
_vm->_draw->spriteOperation(DRAW_FILLRECT);
return false;
}
void Inter_v6::probe16bitMusic(char *fileName) {
int len = strlen(fileName);

View File

@ -137,7 +137,7 @@ public:
void sparseRetrace(int max);
void putPixel(int16 x, int16 y, int16 color, SurfaceDesc *dest);
void fillRect(SurfaceDesc *dest, int16 left, int16 top,
virtual void fillRect(SurfaceDesc *dest, int16 left, int16 top,
int16 right, int16 bottom, int16 color);
void drawLine(SurfaceDesc *dest, int16 x0, int16 y0, int16 x1, int16 y1,
int16 color);
@ -223,6 +223,9 @@ public:
virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight,
int16 x, int16 y, int16 transp, SurfaceDesc *destDesc);
virtual void fillRect(SurfaceDesc *dest, int16 left, int16 top,
int16 right, int16 bottom, int16 color);
virtual void init();
Video_v6(GobEngine *vm);
@ -231,6 +234,9 @@ public:
private:
static const byte _ditherPalette[768];
void shadeRect(SurfaceDesc *dest,
int16 left, int16 top, int16 right, int16 bottom, byte color, byte strength);
void drawPacked(const byte *sprBuf, int16 x, int16 y, SurfaceDesc *surfDesc);
void drawYUVData(const byte *srcData, SurfaceDesc *destDesc,
int16 width, int16 height, int16 x, int16 y);

View File

@ -66,6 +66,72 @@ char Video_v6::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight,
return 1;
}
void Video_v6::fillRect(SurfaceDesc *dest,
int16 left, int16 top, int16 right, int16 bottom, int16 color) {
if (!(color & 0xFF00)) {
Video::fillRect(dest, left, top, right, bottom, color);
return;
}
if (!(color & 0x0100)) {
Video::fillRect(dest, left, top, right, bottom, color);
return;
}
if (_doRangeClamp) {
if (left > right)
SWAP(left, right);
if (top > bottom)
SWAP(top, bottom);
if ((left >= dest->getWidth()) || (right < 0) ||
(top >= dest->getHeight()) || (bottom < 0))
return;
left = CLIP(left, (int16) 0, (int16) (dest->getWidth() - 1));
top = CLIP(top, (int16) 0, (int16) (dest->getHeight() - 1));
right = CLIP(right, (int16) 0, (int16) (dest->getWidth() - 1));
bottom = CLIP(bottom, (int16) 0, (int16) (dest->getHeight() - 1));
}
byte strength = 16 - (((uint16) color) >> 12);
shadeRect(dest, left, top, right, bottom, color, strength);
}
void Video_v6::shadeRect(SurfaceDesc *dest,
int16 left, int16 top, int16 right, int16 bottom, byte color, byte strength) {
int width = right - left + 1;
int height = bottom - top + 1;
int dWidth = dest->getWidth();
byte *vidMem = dest->getVidMem() + dWidth * top + left;
byte sY, sU, sV;
_palLUT->getEntry(color, sY, sU, sV);
SierraLight *dither = new SierraLight(width, height, _palLUT);
for (int i = 0; i < height; i++) {
byte *d = vidMem;
for (int j = 0; j < width; j++) {
byte dY, dU, dV;
byte dC = *d;
_palLUT->getEntry(dC, dY, dU, dV);
dY = CLIP<int>(sY + (dY >> 2), 0, 255);
*d++ = dither->dither(dY, sU, sV, j);
}
dither->nextLine();
vidMem += dWidth;
}
delete dither;
}
void Video_v6::drawPacked(const byte *sprBuf, int16 x, int16 y, SurfaceDesc *surfDesc) {
const byte *data = sprBuf + 2;