diff options
Diffstat (limited to 'engines/illusions/screen.cpp')
-rw-r--r-- | engines/illusions/screen.cpp | 399 |
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); |