SAGA: Support masked blit for sprites

ECS version does it in original for verb buttons, let's do the same
This commit is contained in:
Vladimir Serbinenko 2022-12-17 20:10:21 +01:00
parent fcf31d2593
commit 73f04a31ab
3 changed files with 46 additions and 21 deletions

View File

@ -207,7 +207,7 @@ Interface::Interface(SagaEngine *vm) : _vm(vm) {
#endif
// Main panel sprites
_vm->_sprite->loadList(_vm->getResourceDescription()->mainPanelSpritesResourceId, _mainPanel.sprites);
_vm->_sprite->loadList(_vm->getResourceDescription()->mainPanelSpritesResourceId, _mainPanel.sprites, _vm->isECS() ? 0x10 : 0);
if (!_vm->_script->isNonInteractiveDemo()) {
// Option panel sprites
_vm->_sprite->loadList(_vm->getResourceDescription()->optionPanelSpritesResourceId, _optionPanel.sprites);

View File

@ -146,7 +146,7 @@ Sprite::~Sprite() {
debug(8, "Shutting down sprite subsystem...");
}
void Sprite::loadList(int resourceId, SpriteList &spriteList) {
void Sprite::loadList(int resourceId, SpriteList &spriteList, byte keepMask) {
ByteArray spriteListData;
_vm->_resource->loadResource(_spriteContext, resourceId, spriteListData);
@ -220,6 +220,7 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
blitAmigaSprite<4, 8>(&_decodeBuf.front(), spriteInfo->width, spriteDataPointer, inputLength, spriteInfo->width, spriteInfo->height);
} else
decodeRLEBuffer(spriteDataPointer, inputLength, outputLength);
spriteInfo->keepMask = keepMask;
byte *dst = &spriteInfo->decodedBuffer.front();
#ifdef ENABLE_IHNM
// IHNM sprites are upside-down, for reasons which i can only
@ -273,7 +274,7 @@ void Sprite::getScaledSpriteBuffer(SpriteList &spriteList, uint spriteNumber, in
}
}
void Sprite::drawClip(const Point &spritePointer, int width, int height, const byte *spriteBuffer, bool clipToScene) {
void Sprite::drawClip(const Point &spritePointer, int width, int height, const byte *spriteBuffer, bool clipToScene, byte keepMask) {
Common::Rect clipRect = clipToScene ? _vm->_scene->getSceneClip() : _vm->getDisplayClip();
int xDstOffset, yDstOffset, xSrcOffset, ySrcOffset, xDiff, yDiff, cWidth, cHeight;
@ -332,25 +333,48 @@ void Sprite::drawClip(const Point &spritePointer, int width, int height, const b
assert(((const byte *)spriteBuffer + (width * height)) >= (const byte *)(srcRowPointer + width * (cHeight - 1) + cWidth));
const byte *srcPointerFinish2 = srcRowPointer + width * cHeight;
for (;;) {
srcPointer = srcRowPointer;
bufPointer = bufRowPointer;
const byte *srcPointerFinish = srcRowPointer + cWidth;
if (keepMask) {
for (;;) {
if (*srcPointer != 0) {
*bufPointer = *srcPointer;
srcPointer = srcRowPointer;
bufPointer = bufRowPointer;
const byte *srcPointerFinish = srcRowPointer + cWidth;
for (;;) {
if (*srcPointer != 0) {
*bufPointer = *srcPointer | (*bufPointer & keepMask);
}
srcPointer++;
bufPointer++;
if (srcPointer == srcPointerFinish) {
break;
}
}
srcPointer++;
bufPointer++;
if (srcPointer == srcPointerFinish) {
srcRowPointer += width;
if (srcRowPointer == srcPointerFinish2) {
break;
}
bufRowPointer += backBufferPitch;
}
srcRowPointer += width;
if (srcRowPointer == srcPointerFinish2) {
break;
} else {
for (;;) {
srcPointer = srcRowPointer;
bufPointer = bufRowPointer;
const byte *srcPointerFinish = srcRowPointer + cWidth;
for (;;) {
if (*srcPointer != 0) {
*bufPointer = *srcPointer;
}
srcPointer++;
bufPointer++;
if (srcPointer == srcPointerFinish) {
break;
}
}
srcRowPointer += width;
if (srcRowPointer == srcPointerFinish2) {
break;
}
bufRowPointer += backBufferPitch;
}
bufRowPointer += backBufferPitch;
}
_vm->_render->addDirtyRect(Common::Rect(xDstOffset, yDstOffset, xDstOffset + cWidth, yDstOffset + cHeight));
@ -369,7 +393,7 @@ void Sprite::draw(SpriteList &spriteList, uint spriteNumber, const Point &screen
spritePointer.x = screenCoord.x + xAlign;
spritePointer.y = screenCoord.y + yAlign;
drawClip(spritePointer, width, height, spriteBuffer, clipToScene);
drawClip(spritePointer, width, height, spriteBuffer, clipToScene, spriteList[spriteNumber].keepMask);
}
void Sprite::draw(SpriteList &spriteList, uint spriteNumber, const Rect &screenRect, int scale, bool clipToScene) {
@ -393,7 +417,7 @@ void Sprite::draw(SpriteList &spriteList, uint spriteNumber, const Rect &screenR
}
spritePointer.x = screenRect.left + xAlign + spw;
spritePointer.y = screenRect.top + yAlign + sph;
drawClip(spritePointer, width, height, spriteBuffer, clipToScene);
drawClip(spritePointer, width, height, spriteBuffer, clipToScene, spriteList[spriteNumber].keepMask);
}
bool Sprite::hitTest(SpriteList &spriteList, uint spriteNumber, const Point &screenCoord, int scale, const Point &testPoint) {

View File

@ -35,8 +35,9 @@ struct SpriteInfo {
int height;
int xAlign;
int yAlign;
byte keepMask;
SpriteInfo() : width(0), height(0), xAlign(0), yAlign(0) {
SpriteInfo() : width(0), height(0), xAlign(0), yAlign(0), keepMask(0) {
}
};
@ -59,11 +60,11 @@ public:
void draw(SpriteList &spriteList, uint spriteNumber, const Point &screenCoord, int scale, bool clipToScene = false);
// main function
void drawClip(const Point &spritePointer, int width, int height, const byte *spriteBuffer, bool clipToScene = false);
void drawClip(const Point &spritePointer, int width, int height, const byte *spriteBuffer, bool clipToScene = false, byte keepMask = 0);
void draw(SpriteList &spriteList, uint spriteNumber, const Rect &screenRect, int scale, bool clipToScene = false);
void loadList(int resourceId, SpriteList &spriteList); // load or append spriteList
void loadList(int resourceId, SpriteList &spriteList, byte keepMask = 0); // load or append spriteList
bool hitTest(SpriteList &spriteList, uint spriteNumber, const Point &screenCoord, int scale, const Point &testPoint);
void getScaledSpriteBuffer(SpriteList &spriteList, uint spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer);