TOLTECS: Changed how screen masks are handled.

At load time, a Surface is created for each screen mask, in which the gfx data from the background is copied.
This is the first step towards more optimized gfx rendering (more to come later).
This commit is contained in:
Benjamin Haisch
2011-11-20 22:43:06 +01:00
committed by Willem Jan Palenstijn
parent 150e555953
commit d299bbba01
2 changed files with 65 additions and 73 deletions
+59 -66
View File
@@ -43,22 +43,23 @@
namespace Toltecs {
SegmentMap::SegmentMap(ToltecsEngine *vm) : _vm(vm) {
_maskRectData = new byte[32768];
}
SegmentMap::~SegmentMap() {
delete[] _maskRectData;
freeSegmapMaskRectSurfaces();
}
void SegmentMap::load(byte *source) {
// TODO: Use MemoryReadStream
freeSegmapMaskRectSurfaces();
_maskRects.clear();
_pathRects.clear();
_infoRects.clear();
// Load mask rects
byte *maskData = source + 2;
uint16 maskSize = READ_LE_UINT16(source);
source += 2;
uint16 maskRectCount = READ_LE_UINT16(source);
@@ -69,24 +70,24 @@ void SegmentMap::load(byte *source) {
for (uint16 i = 0; i < maskRectCount; i++) {
SegmapMaskRect maskRect;
int16 maskOffset;
maskRect.y = READ_LE_UINT16(source);
maskRect.x = READ_LE_UINT16(source + 2);
maskRect.height = READ_LE_UINT16(source + 4);
maskRect.width = READ_LE_UINT16(source + 6);
maskRect.maskOffset = READ_LE_UINT16(source + 8);
maskRect.maskOffset -= maskRectDataSize;
maskOffset = READ_LE_UINT16(source + 8);
maskRect.priority = READ_LE_UINT16(source + 10);
loadSegmapMaskRectSurface(maskData + maskOffset, maskRect);
debug(0, "SegmentMap::load() (%d, %d, %d, %d, %04X, %d)",
maskRect.x, maskRect.y, maskRect.width, maskRect.height, maskRect.maskOffset, maskRect.priority);
maskRect.x, maskRect.y, maskRect.width, maskRect.height, maskOffset, maskRect.priority);
source += 12;
_maskRects.push_back(maskRect);
}
memcpy(_maskRectData, source, maskSize - maskRectDataSize);
source += maskSize - maskRectDataSize;
// Load path rects
source += 2; // skip rects array size
@@ -304,7 +305,7 @@ void SegmentMap::findPath(int16 *pointsArray, int16 destX, int16 destY, int16 so
pointsCount = 2;
adjustPathPoint(sourceX, sourceY);
adjustPathPoint(sourceX, sourceY);
currentRectIndex = findPathRectAtPoint(sourceX, sourceY);
adjustPathPoint(destX, destY);
@@ -388,44 +389,59 @@ void SegmentMap::getRgbModifiertAtPoint(int16 x, int16 y, int16 id, byte &r, byt
debug(0, "SegmentMap::getRgbModifiertAtPoint() r: %d; g: %d; b: %d", r, g, b);
}
void SegmentMap::restoreMasksBySprite(SpriteDrawItem *sprite) {
// TODO: This needs more optimization
for (uint i = 0; i < _maskRects.size(); i++) {
#if 0
if ( *(__int16 *)((char *)&spriteDrawList[0].y2 + v5) <= (unsigned __int16)v3->priority )
{
if ( (unsigned __int16)(*(__int16 *)((char *)&spriteDrawList[0].height + v5)
+ *(__int16 *)((char *)&spriteDrawList[0].y + v5)) > v3->y )
{
if ( (unsigned __int16)(v3->height + v3->y) > *(__int16 *)((char *)&spriteDrawList[0].y + v5) )
{
if ( (unsigned __int16)(*(__int16 *)((char *)&spriteDrawList[0].width + v5)
+ *(__int16 *)((char *)&spriteDrawList[0].x + v5)) > v3->x )
{
if ( (unsigned __int16)(v3->width + v3->x) > *(__int16 *)((char *)&spriteDrawList[0].x + v5) )
{
void SegmentMap::loadSegmapMaskRectSurface(byte *maskData, SegmapMaskRect &maskRect) {
#endif
if (sprite->priority <= _maskRects[i].priority) {
restoreMask(i);
maskRect.surface = new Graphics::Surface();
maskRect.surface->create(maskRect.width, maskRect.height, 1);
byte *backScreen = _vm->_screen->_backScreen + maskRect.x + (maskRect.y * _vm->_sceneWidth);
byte *dest = (byte*)maskRect.surface->getBasePtr(0, 0);
for (int16 h = 0; h < maskRect.height; h++) {
int16 w = maskRect.width;
while (w > 0) {
byte mask = *maskData++;
byte count = mask & 0x7F;
if (mask & 0x80)
memcpy(dest, backScreen, count);
else
memset(dest, 0xFF, count);
w -= count;
dest += count;
backScreen += count;
}
backScreen += _vm->_sceneWidth - maskRect.width;
}
}
void SegmentMap::freeSegmapMaskRectSurfaces() {
for (uint i = 0; i < _maskRects.size(); i++) {
delete _maskRects[i].surface;
}
}
void SegmentMap::restoreMasksBySprite(SpriteDrawItem *sprite) {
// TODO: This needs more optimization
for (uint i = 0; i < _maskRects.size(); i++) {
if (sprite->priority <= _maskRects[i].priority) {
restoreMask(i);
}
}
}
void SegmentMap::restoreMask(int16 index) {
// TODO: This needs more optimization
SegmapMaskRect *maskRect = &_maskRects[index];
int16 maskX = maskRect->x, maskY = maskRect->y;
int16 skipX = 0;
int16 x = maskRect->x - _vm->_cameraX;
int16 y = maskRect->y - _vm->_cameraY;
int16 width = maskRect->width;
int16 height = maskRect->height;
byte *mask = _maskRectData + maskRect->maskOffset;
byte *maskSurface = (byte*)maskRect->surface->getBasePtr(0, 0);
byte *frontScreen;
debug(0, "SegmentMap::restoreMask() screenX = %d; screenY = %d; maskX = %d; maskY = %d",
x, y, maskRect->x, maskRect->y);
@@ -437,19 +453,14 @@ void SegmentMap::restoreMask(int16 index) {
if (x < 0) {
skipX = -x;
x = 0;
width -= skipX;
}
if (y < 0) {
int16 skipY = -y;
for (int16 h = 0; h < skipY; h++) {
int16 w = width;
while (w > 0) {
w -= (*mask++) & 0x7F;
}
}
maskSurface += maskRect->width * skipY;
y = 0;
height -= skipY;
maskY += skipY;
}
if (x + width >= 640) {
@@ -460,38 +471,20 @@ void SegmentMap::restoreMask(int16 index) {
height -= y + height - _vm->_cameraHeight;
}
byte *backScreen = _vm->_screen->_backScreen + maskX + (maskY * _vm->_sceneWidth);
byte *frontScreen = _vm->_screen->_frontScreen + x + (y * 640);
frontScreen = _vm->_screen->_frontScreen + x + (y * 640);
for (int16 h = 0; h < height; h++) {
byte *src = backScreen;
byte *dst = frontScreen;
byte maskLine[640], *maskLineP = maskLine;
int16 w = width;
while (w > 0) {
byte m = *mask++;
byte count = m & 0x7F;
if (m & 0x80)
memset(maskLineP, 1, count);
else
memset(maskLineP, 0, count);
maskLineP += count;
w -= count;
maskSurface += skipX;
for (int16 w = 0; w < width; w++) {
if (*maskSurface != 0xFF)
*frontScreen = *maskSurface;
frontScreen++;
maskSurface++;
}
src += skipX;
for (int16 c = skipX; c < width; c++) {
if (maskLine[c] == 1)
*dst = *src;
dst++;
src++;
}
backScreen += _vm->_sceneWidth;
frontScreen += 640;
frontScreen += 640 - width;
maskSurface += maskRect->width - width - skipX;
}
}
void SegmentMap::debugDrawRects(Graphics::Surface *surf) {
+6 -7
View File
@@ -80,17 +80,13 @@ public:
public: // for debugging purposes
struct SegmapMaskRect {
int16 y, x;
int16 height, width;
int16 maskOffset;
int16 x, y;
int16 width, height;
int16 priority;
Graphics::Surface *surface;
};
struct SegmapPathRect {
/*
int16 y, x;
int16 height, width;
*/
int16 x1, y1, x2, y2;
};
@@ -128,6 +124,9 @@ public: // for debugging purposes
int16 findNextPathRect(int16 srcRectIndex, int16 destX, int16 destY);
void loadSegmapMaskRectSurface(byte *maskData, SegmapMaskRect &maskRect);
void freeSegmapMaskRectSurfaces();
};
} // End of namespace Toltecs