Navigation Menu

Skip to content

Commit

Permalink
STARTREK: Fix .BAN file rendering behind textboxes
Browse files Browse the repository at this point in the history
  • Loading branch information
Stewmath authored and sev- committed Aug 9, 2018
1 parent 2090417 commit 5660ce8
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 17 deletions.
11 changes: 5 additions & 6 deletions engines/startrek/graphics.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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];
Expand All @@ -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) {
Expand Down
12 changes: 10 additions & 2 deletions engines/startrek/graphics.h
Expand Up @@ -105,13 +105,21 @@ class Graphics {

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.
*/
Expand Down
58 changes: 49 additions & 9 deletions engines/startrek/startrek.cpp
Expand Up @@ -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();
}
}
Expand Down

0 comments on commit 5660ce8

Please sign in to comment.