aboutsummaryrefslogtreecommitdiff
path: root/engines/illusions/screen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/illusions/screen.cpp')
-rw-r--r--engines/illusions/screen.cpp399
1 files changed, 314 insertions, 85 deletions
diff --git a/engines/illusions/screen.cpp b/engines/illusions/screen.cpp
index 9e03a40bd9..0eb78321a9 100644
--- a/engines/illusions/screen.cpp
+++ b/engines/illusions/screen.cpp
@@ -22,12 +22,15 @@
#include "illusions/illusions.h"
#include "illusions/screen.h"
+#include "engines/util.h"
+#include "graphics/palette.h"
namespace Illusions {
// SpriteDecompressQueue
-SpriteDecompressQueue::SpriteDecompressQueue() {
+SpriteDecompressQueue::SpriteDecompressQueue(Screen *screen)
+ : _screen(screen) {
}
SpriteDecompressQueue::~SpriteDecompressQueue() {
@@ -56,80 +59,7 @@ void SpriteDecompressQueue::decompressAll() {
}
void SpriteDecompressQueue::decompress(SpriteDecompressQueueItem *item) {
- byte *src = item->_compressedPixels;
- Graphics::Surface *dstSurface = item->_surface;
- int dstSize = item->_dimensions._width * item->_dimensions._height;
- int processedSize = 0;
- int xincr, x, xstart;
- int yincr, y;
-
- // Safeguard
- if (item->_dimensions._width > item->_surface->w ||
- item->_dimensions._height > item->_surface->h) {
- debug("Incorrect frame dimensions (%d, %d <> %d, %d)",
- item->_dimensions._width, item->_dimensions._height,
- item->_surface->w, item->_surface->h);
- return;
- }
-
- if (item->_flags & 1) {
- x = xstart = item->_dimensions._width - 1;
- xincr = -1;
- } else {
- x = xstart = 0;
- xincr = 1;
- }
-
- if (item->_flags & 2) {
- y = item->_dimensions._height - 1;
- yincr = -1;
- } else {
- y = 0;
- yincr = 1;
- }
-
- byte *dst = (byte*)dstSurface->getBasePtr(x, y);
-
- while (processedSize < dstSize) {
- int16 op = READ_LE_UINT16(src);
- src += 2;
- if (op & 0x8000) {
- int runCount = (op & 0x7FFF) + 1;
- processedSize += runCount;
- uint16 runColor = READ_LE_UINT16(src);
- src += 2;
- while (runCount--) {
- WRITE_LE_UINT16(dst, runColor);
- x += xincr;
- if (x >= item->_dimensions._width || x < 0) {
- x = xstart;
- y += yincr;
- dst = (byte*)dstSurface->getBasePtr(x, y);
- } else {
- dst += 2 * xincr;
- }
- }
- } else {
- int copyCount = op + 1;
- processedSize += copyCount;
- while (copyCount--) {
- uint16 color = READ_LE_UINT16(src);
- src += 2;
- WRITE_LE_UINT16(dst, color);
- x += xincr;
- if (x >= item->_dimensions._width || x < 0) {
- x = xstart;
- y += yincr;
- dst = (byte*)dstSurface->getBasePtr(x, y);
- } else {
- dst += 2 * xincr;
- }
- }
- }
- }
-
- *item->_drawFlags &= ~1;
-
+ _screen->decompressSprite(item);
}
// SpriteDrawQueue
@@ -258,7 +188,7 @@ bool SpriteDrawQueue::calcItemRect(SpriteDrawQueueItem *item, Common::Rect &srcR
*/
// Check if the sprite is on-screen
- if (dstRect.left >= 640 || dstRect.right <= 0 || dstRect.top >= 480 || dstRect.bottom <= 0)
+ if (dstRect.left >= _screen->getScreenWidth() || dstRect.right <= 0 || dstRect.top >= _screen->getScreenHeight() || dstRect.bottom <= 0)
return false;
// Clip the sprite rect if neccessary
@@ -273,14 +203,14 @@ bool SpriteDrawQueue::calcItemRect(SpriteDrawQueueItem *item, Common::Rect &srcR
dstRect.top = 0;
}
- if (dstRect.right > 640) {
- srcRect.right += 100 * (640 - dstRect.right) / item->_scale;
- dstRect.right = 640;
+ if (dstRect.right > _screen->getScreenWidth()) {
+ srcRect.right += 100 * (_screen->getScreenWidth() - dstRect.right) / item->_scale;
+ dstRect.right = _screen->getScreenWidth();
}
- if (dstRect.bottom > 480) {
- srcRect.bottom += 100 * (480 - dstRect.bottom) / item->_scale;
- dstRect.bottom = 480;
+ if (dstRect.bottom > _screen->getScreenHeight()) {
+ srcRect.bottom += 100 * (_screen->getScreenHeight() - dstRect.bottom) / item->_scale;
+ dstRect.bottom = _screen->getScreenHeight();
}
return true;
@@ -288,13 +218,24 @@ bool SpriteDrawQueue::calcItemRect(SpriteDrawQueueItem *item, Common::Rect &srcR
// Screen
-Screen::Screen(IllusionsEngine *vm)
+Screen::Screen(IllusionsEngine *vm, int16 width, int16 height, int bpp)
: _vm(vm), _colorKey2(0) {
_displayOn = true;
- _backSurface = allocSurface(640, 480);
- _decompressQueue = new SpriteDecompressQueue();
+ _decompressQueue = new SpriteDecompressQueue(this);
_drawQueue = new SpriteDrawQueue(this);
_colorKey1 = 0xF800 | 0x1F;
+ if (bpp == 8) {
+ initGraphics(width, height, false);
+ } else {
+ Graphics::PixelFormat pixelFormat16(2, 5, 6, 5, 0, 11, 5, 0, 0);
+ initGraphics(width, height, true, &pixelFormat16);
+ }
+
+ _backSurface = allocSurface(width, height);
+
+ _needRefreshPalette = false;
+ memset(_mainPalette, 0, sizeof(_mainPalette));
+
}
Screen::~Screen() {
@@ -336,7 +277,295 @@ void Screen::updateSprites() {
g_system->copyRectToScreen((byte*)_backSurface->getBasePtr(0, 0), _backSurface->pitch, 0, 0, _backSurface->w, _backSurface->h);
}
+void Screen::decompressSprite(SpriteDecompressQueueItem *item) {
+ switch (_backSurface->format.bytesPerPixel) {
+ case 1:
+ decompressSprite8(item);
+ break;
+ case 2:
+ decompressSprite16(item);
+ break;
+ default:
+ break;
+ }
+}
+
void Screen::drawSurface(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags) {
+ switch (_backSurface->format.bytesPerPixel) {
+ case 1:
+ drawSurface8(dstRect, surface, srcRect, scale, flags);
+ break;
+ case 2:
+ drawSurface16(dstRect, surface, srcRect, scale, flags);
+ break;
+ default:
+ break;
+ }
+}
+
+void Screen::setPalette(byte *colors, uint start, uint count) {
+ byte *dstPal = &_mainPalette[3 * (start - 1)];
+ for (uint i = 0; i < count; ++i) {
+ *dstPal++ = *colors++;
+ *dstPal++ = *colors++;
+ *dstPal++ = *colors++;
+ ++colors;
+ }
+ // TODO Build colorTransTbl
+ _needRefreshPalette = true;
+}
+
+void Screen::getPalette(byte *colors) {
+ byte *srcPal = _mainPalette;
+ for (uint i = 0; i < 256; ++i) {
+ *colors++ = *srcPal++;
+ *colors++ = *srcPal++;
+ *colors++ = *srcPal++;
+ ++colors;
+ }
+}
+
+void Screen::updatePalette() {
+ if (_needRefreshPalette) {
+ // TODO Update fader palette
+ setSystemPalette(_mainPalette);
+ _needRefreshPalette = false;
+ }
+}
+
+void Screen::setSystemPalette(byte *palette) {
+ g_system->getPaletteManager()->setPalette(palette, 0, 256);
+}
+
+void Screen::decompressSprite8(SpriteDecompressQueueItem *item) {
+ byte *src = item->_compressedPixels;
+ Graphics::Surface *dstSurface = item->_surface;
+ int dstSize = item->_dimensions._width * item->_dimensions._height;
+ int processedSize = 0;
+ int xincr, x, xstart;
+ int yincr, y;
+
+ *item->_drawFlags &= ~1;
+
+ // Safeguard
+ if (item->_dimensions._width > item->_surface->w ||
+ item->_dimensions._height > item->_surface->h) {
+ debug("Incorrect frame dimensions (%d, %d <> %d, %d)",
+ item->_dimensions._width, item->_dimensions._height,
+ item->_surface->w, item->_surface->h);
+ return;
+ }
+
+ if (item->_flags & 1) {
+ x = xstart = item->_dimensions._width - 1;
+ xincr = -1;
+ } else {
+ x = xstart = 0;
+ xincr = 1;
+ }
+
+ if (item->_flags & 2) {
+ y = item->_dimensions._height - 1;
+ yincr = -1;
+ } else {
+ y = 0;
+ yincr = 1;
+ }
+
+ byte *dst = (byte*)dstSurface->getBasePtr(x, y);
+
+ while (processedSize < dstSize) {
+ byte op = *src++;
+ if (op & 0x80) {
+ int runCount = (op & 0x7F) + 1;
+ processedSize += runCount;
+ byte runColor = *src++;
+ while (runCount--) {
+ *dst = runColor;
+ x += xincr;
+ if (x >= item->_dimensions._width || x < 0) {
+ x = xstart;
+ y += yincr;
+ dst = (byte*)dstSurface->getBasePtr(x, y);
+ } else {
+ dst += xincr;
+ }
+ }
+ } else {
+ int copyCount = op + 1;
+ processedSize += copyCount;
+ while (copyCount--) {
+ byte color = *src++;
+ *dst = color;
+ x += xincr;
+ if (x >= item->_dimensions._width || x < 0) {
+ x = xstart;
+ y += yincr;
+ dst = (byte*)dstSurface->getBasePtr(x, y);
+ } else {
+ dst += xincr;
+ }
+ }
+ }
+ }
+
+}
+
+void Screen::drawSurface8(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags) {
+ drawSurface81(dstRect.left, dstRect.top, surface, srcRect);
+ /*
+ if (scale == 100) {
+ drawSurface81(dstRect.left, dstRect.top, surface, srcRect);
+ } else {
+ drawSurface82(dstRect, surface, srcRect);
+ }
+ */
+}
+
+void Screen::drawSurface81(int16 destX, int16 destY, Graphics::Surface *surface, Common::Rect &srcRect) {
+ // Unscaled
+ const int16 w = srcRect.width();
+ const int16 h = srcRect.height();
+ for (int16 yc = 0; yc < h; ++yc) {
+ byte *src = (byte*)surface->getBasePtr(srcRect.left, srcRect.top + yc);
+ byte *dst = (byte*)_backSurface->getBasePtr(destX, destY + yc);
+ for (int16 xc = 0; xc < w; ++xc) {
+ byte pixel = *src++;
+ if (pixel != 0)
+ *dst = pixel;
+ ++dst;
+ }
+ }
+}
+
+void Screen::drawSurface82(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect) {
+ // Scaled
+ const int dstWidth = dstRect.width(), dstHeight = dstRect.height();
+ const int srcWidth = srcRect.width(), srcHeight = srcRect.height();
+ const int errYStart = srcHeight / dstHeight;
+ const int errYIncr = srcHeight % dstHeight;
+ const int midY = dstHeight / 2;
+ const int errXStart = srcWidth / dstWidth;
+ const int errXIncr = srcWidth % dstWidth;
+ const int midX = dstWidth / 2;
+ int h = dstHeight, errY = 0, skipY, srcY = srcRect.top;
+ byte *dst = (byte*)_backSurface->getBasePtr(dstRect.left, dstRect.top);
+ skipY = (dstHeight < srcHeight) ? 0 : dstHeight / (2*srcHeight) + 1;
+ h -= skipY;
+ while (h-- > 0) {
+ int w = dstWidth, errX = 0, skipX;
+ skipX = (dstWidth < srcWidth) ? 0 : dstWidth / (2*srcWidth) + 1;
+ w -= skipX;
+ byte *src = (byte*)surface->getBasePtr(srcRect.left, srcY);
+ byte *dstRow = dst;
+ while (w-- > 0) {
+ byte pixel = *src;
+ if (pixel != 0) {
+ *dstRow = pixel;
+ }
+ ++dstRow;
+ src += errXStart;
+ errX += errXIncr;
+ if (errX >= dstWidth) {
+ errX -= dstWidth;
+ ++src;
+ }
+ }
+ while (skipX-- > 0) {
+ byte pixel = *src;
+ if (pixel != 0)
+ *dstRow = pixel;
+ ++src;
+ ++dstRow;
+ }
+ dst += _backSurface->pitch;
+ srcY += errYStart;
+ errY += errYIncr;
+ if (errY >= dstHeight) {
+ errY -= dstHeight;
+ ++srcY;
+ }
+ }
+}
+
+void Screen::decompressSprite16(SpriteDecompressQueueItem *item) {
+ byte *src = item->_compressedPixels;
+ Graphics::Surface *dstSurface = item->_surface;
+ int dstSize = item->_dimensions._width * item->_dimensions._height;
+ int processedSize = 0;
+ int xincr, x, xstart;
+ int yincr, y;
+
+ *item->_drawFlags &= ~1;
+
+ // Safeguard
+ if (item->_dimensions._width > item->_surface->w ||
+ item->_dimensions._height > item->_surface->h) {
+ debug("Incorrect frame dimensions (%d, %d <> %d, %d)",
+ item->_dimensions._width, item->_dimensions._height,
+ item->_surface->w, item->_surface->h);
+ return;
+ }
+
+ if (item->_flags & 1) {
+ x = xstart = item->_dimensions._width - 1;
+ xincr = -1;
+ } else {
+ x = xstart = 0;
+ xincr = 1;
+ }
+
+ if (item->_flags & 2) {
+ y = item->_dimensions._height - 1;
+ yincr = -1;
+ } else {
+ y = 0;
+ yincr = 1;
+ }
+
+ byte *dst = (byte*)dstSurface->getBasePtr(x, y);
+
+ while (processedSize < dstSize) {
+ int16 op = READ_LE_UINT16(src);
+ src += 2;
+ if (op & 0x8000) {
+ int runCount = (op & 0x7FFF) + 1;
+ processedSize += runCount;
+ uint16 runColor = READ_LE_UINT16(src);
+ src += 2;
+ while (runCount--) {
+ WRITE_LE_UINT16(dst, runColor);
+ x += xincr;
+ if (x >= item->_dimensions._width || x < 0) {
+ x = xstart;
+ y += yincr;
+ dst = (byte*)dstSurface->getBasePtr(x, y);
+ } else {
+ dst += 2 * xincr;
+ }
+ }
+ } else {
+ int copyCount = op + 1;
+ processedSize += copyCount;
+ while (copyCount--) {
+ uint16 color = READ_LE_UINT16(src);
+ src += 2;
+ WRITE_LE_UINT16(dst, color);
+ x += xincr;
+ if (x >= item->_dimensions._width || x < 0) {
+ x = xstart;
+ y += yincr;
+ dst = (byte*)dstSurface->getBasePtr(x, y);
+ } else {
+ dst += 2 * xincr;
+ }
+ }
+ }
+ }
+
+}
+
+void Screen::drawSurface16(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags) {
if (scale == 100) {
if (flags & 1)
drawSurface10(dstRect.left, dstRect.top, surface, srcRect, _colorKey2);