aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Stewart2018-07-26 02:25:18 -0400
committerEugene Sandulenko2018-08-09 08:37:30 +0200
commit5660ce81340a013c0c653a55b7430737213783a4 (patch)
treee2a7ee405321733b69e8f5fab000473ac9419cc5
parent20904176129e7ad6f9435e9563e1fa0bca5cb0f6 (diff)
downloadscummvm-rg350-5660ce81340a013c0c653a55b7430737213783a4.tar.gz
scummvm-rg350-5660ce81340a013c0c653a55b7430737213783a4.tar.bz2
scummvm-rg350-5660ce81340a013c0c653a55b7430737213783a4.zip
STARTREK: Fix .BAN file rendering behind textboxes
-rw-r--r--engines/startrek/graphics.cpp11
-rw-r--r--engines/startrek/graphics.h12
-rw-r--r--engines/startrek/startrek.cpp58
3 files changed, 64 insertions, 17 deletions
diff --git a/engines/startrek/graphics.cpp b/engines/startrek/graphics.cpp
index 43358f8c1c..cce9861934 100644
--- a/engines/startrek/graphics.cpp
+++ b/engines/startrek/graphics.cpp
@@ -304,14 +304,14 @@ void Graphics::drawSprite(const Sprite &sprite, ::Graphics::Surface *surface) {
// rect is the portion of the sprite to update. It must be entirely contained within the
// sprite's actual, full rectangle.
-void Graphics::drawSprite(const Sprite &sprite, ::Graphics::Surface *surface, const Common::Rect &rect) {
+void Graphics::drawSprite(const Sprite &sprite, ::Graphics::Surface *surface, const Common::Rect &rect, int rectLeft, int rectTop) {
Common::Rect spriteRect = Common::Rect(sprite.drawX, sprite.drawY,
sprite.drawX + sprite.bitmap->width, sprite.drawY + sprite.bitmap->height);
assert(_screenRect.contains(rect));
assert(spriteRect.contains(rect));
- byte *dest = (byte *)surface->getPixels() + rect.top * SCREEN_WIDTH + rect.left;
+ byte *dest = (byte *)surface->getPixels() + (rect.top - rectTop) * SCREEN_WIDTH + (rect.left - rectLeft);
switch (sprite.drawMode) {
case 0: { // Normal sprite
@@ -583,8 +583,9 @@ void Graphics::drawAllSprites(bool updateScreen) {
this->updateScreen();
}
-void Graphics::drawAllSpritesInRect(const Common::Rect &rect) {
- ::Graphics::Surface *surface = _vm->_system->lockScreen();
+void Graphics::drawAllSpritesInRectToSurface(const Common::Rect &rect, ::Graphics::Surface *surface) {
+ surface->copyFrom(*_vm->_system->lockScreen());
+ _vm->_system->unlockScreen();
for (int i = 0; i < _numSprites; i++) {
Sprite *sprite = _sprites[i];
@@ -595,8 +596,6 @@ void Graphics::drawAllSpritesInRect(const Common::Rect &rect) {
if (!intersect.isEmpty())
drawSprite(*sprite, surface, intersect);
}
-
- _vm->_system->unlockScreen();
}
void Graphics::forceDrawAllSprites(bool updateScreen) {
diff --git a/engines/startrek/graphics.h b/engines/startrek/graphics.h
index 1a71aa29b3..bd5784e3a2 100644
--- a/engines/startrek/graphics.h
+++ b/engines/startrek/graphics.h
@@ -105,13 +105,21 @@ public:
void drawTextChar(::Graphics::Surface *surface, const Sprite &sprite, int x, int y, const Common::Rect &rect);
void drawSprite(const Sprite &sprite, ::Graphics::Surface *surface);
- void drawSprite(const Sprite &sprite, ::Graphics::Surface *surface, const Common::Rect &rect);
+ /**
+ * @param sprite The sprite to draw
+ * @param surface The surface to draw to
+ * @param rect The part of the sprite to draw (only draw the part of the sprite that
+ * intersects with it)
+ @ @param rectLeft X-offset to subtract before drawing to surface.
+ @ @param rectTop Y-offset to subtract before drawing to surface.
+ */
+ void drawSprite(const Sprite &sprite, ::Graphics::Surface *surface, const Common::Rect &rect, int rectLeft = 0, int rectTop = 0);
void drawAllSprites(bool updateScreen = true);
/**
* This function should only be called after "drawAllSprites" (so that sprite rects
* are updated).
*/
- void drawAllSpritesInRect(const Common::Rect &rect);
+ void drawAllSpritesInRectToSurface(const Common::Rect &rect, ::Graphics::Surface *surface);
/**
* Sets "bitmapChanged" to true on all sprites before calling drawAllSprites.
*/
diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp
index 4703bbebb4..9623ccccc8 100644
--- a/engines/startrek/startrek.cpp
+++ b/engines/startrek/startrek.cpp
@@ -884,23 +884,63 @@ void StarTrekEngine::renderBanAboveSprites() {
rect.top = _banFiles[i]->readSint16();
rect.right = _banFiles[i]->readSint16() + 1;
rect.bottom = _banFiles[i]->readSint16() + 1;
- _gfx->drawAllSpritesInRect(rect);
- // Just read through the BAN data to get the end address, not doing anything
- // with it.
+ // Draw all sprites in this rectangle to a custom surface, and only update the
+ // specific pixels that were updated by the BAN file this frame.
+ // Rationale behind this is that, since the background may not have been
+ // redrawn, the transparent sprites (ie. textboxes) would further darken any
+ // pixels behind them that haven't been updated this frame. So, we can't just
+ // update everything in this rectangle.
+ // FIXME: This copies the entire screen surface for temporary drawing, which
+ // is somewhat wasteful. Original game had one more graphics layer it drew to
+ // before the screen was updated...
+ ::Graphics::Surface surface;
+ _gfx->drawAllSpritesInRectToSurface(rect, &surface);
+
+ byte *destPixels = _gfx->lockScreenPixels();
+ byte *src = (byte *)surface.getPixels() + offset;
+ byte *dest = destPixels + offset;
+
+ /*
+ _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET);
+ renderBan(destPixels, _banFiles[i]);
+ */
+ // This is similar to renderBan(), except it copies pixels from the surface
+ // above instead of drawing directly to it. (Important since sprites may be
+ // drawn on top.)
while (--size >= 0) {
+ assert(dest >= destPixels && dest < destPixels + SCREEN_WIDTH * SCREEN_HEIGHT);
int8 b = _banFiles[i]->readByte();
- if (b == -128)
- _banFiles[i]->readUint16();
- else if (b < 0) {
- _banFiles[i]->readByte();
+ if (b == -128) {
+ uint16 skip = _banFiles[i]->readUint16();
+ dest += skip;
+ src += skip;
+ } else if (b < 0) {
+ byte c = _banFiles[i]->readByte();
+ if (c == 0) {
+ dest += (-b) + 1;
+ src += (-b) + 1;
+ }
+ else {
+ for (int j = 0; j < (-b) + 1; j++)
+ *(dest++) = *(src++);
+ }
} else {
b++;
- while (b-- != 0)
- _banFiles[i]->readByte();
+ while (b-- != 0) {
+ byte c = _banFiles[i]->readByte();
+ if (c == 0) {
+ dest++;
+ src++;
+ } else
+ *(dest++) = *(src++);
+ }
}
}
+ _gfx->unlockScreenPixels();
+ surface.free();
+
_banFileOffsets[i] = _banFiles[i]->pos();
}
}