diff options
Diffstat (limited to 'engines/scumm/gfx.cpp')
-rw-r--r-- | engines/scumm/gfx.cpp | 233 |
1 files changed, 123 insertions, 110 deletions
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index 3b8d9c296a..2ee54337b8 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -51,7 +51,6 @@ static void copy8Col(byte *dst, int dstPitch, const byte *src, int height, uint8 static void clear8Col(byte *dst, int dstPitch, int height, uint8 bitDepth); static void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height); -static void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h); struct StripTable { int offsets[160]; @@ -323,6 +322,16 @@ void ScummEngine::initScreens(int b, int h) { _res->nukeResource(rtBuffer, i + 5); } + if (_townsScreen) { + if (!_townsClearLayerFlag && (h - b != _virtscr[kMainVirtScreen].h)) + _townsScreen->clearLayer(0); + + if (_game.id == GID_MONKEY2 || _game.id == GID_INDY4) { + _textSurface.fillRect(Common::Rect(0, 0, _textSurface.w * _textSurfaceMultiplier, _textSurface.h * _textSurfaceMultiplier), 0); + _townsScreen->clearLayer(1); + } + } + if (!getResourceAddress(rtBuffer, 4)) { // Since the size of screen 3 is fixed, there is no need to reallocate // it if its size changed. @@ -611,16 +620,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i int m = _textSurfaceMultiplier; int vsPitch; int pitch = vs->pitch; - - if (_useCJKMode && _textSurfaceMultiplier == 2) { - scale2x(_fmtownsBuf, _screenWidth * m, (const byte *)src, vs->pitch, width, height); - src = _fmtownsBuf; - - vsPitch = _screenWidth * m - width * m; - - } else { - vsPitch = vs->pitch - width * vs->bytesPerPixel; - } + vsPitch = vs->pitch - width * vs->bytesPerPixel; if (_game.version < 7) { @@ -643,7 +643,10 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i #ifdef USE_ARM_GFX_ASM asmDrawStripToScreen(height, width, text, src, _compositeBuf, vs->pitch, width, _textSurface.pitch); #else - if (_bytesPerPixel == 2) { + if (_game.platform == Common::kPlatformFMTowns) { + towns_drawStripToScreen(vs, x, y, x, top, width, height); + return; + } else if (_bytesPerPixelOutput == 2) { const byte *srcPtr = (const byte *)src; const byte *textPtr = (byte *)_textSurface.getBasePtr(x * m, y * m); byte *dstPtr = _compositeBuf; @@ -824,28 +827,6 @@ void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *wid *height = dsty - *y; } -void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h) { - /* dst and dstPitch should both be even. So the use of (void *) in - * the following casts to avoid the unnecessary warning is valid. */ - uint16 *dstL1 = (uint16 *)(void *)dst; - uint16 *dstL2 = (uint16 *)(void *)(dst + dstPitch); - - const int dstAdd = dstPitch - w; - const int srcAdd = srcPitch - w; - - while (h--) { - for (int x = 0; x < w; ++x) { - uint16 col = *src++; - col |= col << 8; - *dstL1++ = col; - *dstL2++ = col; - } - dstL1 += dstAdd; dstL2 += dstAdd; - src += srcAdd; - } -} - - #pragma mark - #pragma mark --- Background buffers & charset mask --- #pragma mark - @@ -1017,7 +998,7 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) { VirtScreen *vs; byte *screenBuf; - if (rect.top < 0) + if (rect.top < 0) rect.top = 0; if (rect.left >= rect.right || rect.top >= rect.bottom) return; @@ -1028,6 +1009,9 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) { if (rect.left > vs->w) return; + if (_game.platform == Common::kPlatformFMTowns && _game.id == GID_MONKEY && vs->number == kVerbVirtScreen && rect.bottom <= 154) + rect.right = 320; + // Convert 'rect' to local (virtual screen) coordinates rect.top -= vs->topline; rect.bottom -= vs->topline; @@ -1047,10 +1031,21 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) { if (vs->hasTwoBuffers && _currentRoom != 0 && isLightOn()) { blit(screenBuf, vs->pitch, vs->getBackPixels(rect.left, rect.top), vs->pitch, width, height, vs->bytesPerPixel); if (vs->number == kMainVirtScreen && _charset->_hasMask) { - byte *mask = (byte *)_textSurface.getBasePtr(rect.left, rect.top - _screenTop); - fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height, _textSurface.bytesPerPixel); + if (_game.platform == Common::kPlatformFMTowns) { + byte *mask = (byte *)_textSurface.getBasePtr(rect.left * _textSurfaceMultiplier, (rect.top + vs->topline) * _textSurfaceMultiplier); + fill(mask, _textSurface.pitch, 0, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel); + } else { + byte *mask = (byte *)_textSurface.getBasePtr(rect.left, rect.top - _screenTop); + fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel); + } } } else { + if (_game.platform == Common::kPlatformFMTowns) { + backColor |= (backColor << 4); + byte *mask = (byte *)_textSurface.getBasePtr(rect.left * _textSurfaceMultiplier, (rect.top + vs->topline) * _textSurfaceMultiplier); + fill(mask, _textSurface.pitch, backColor, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel); + } + if (_game.features & GF_16BIT_COLOR) fill(screenBuf, vs->pitch, _16BitPalette[backColor], width, height, vs->bytesPerPixel); else @@ -1102,7 +1097,10 @@ void ScummEngine::clearCharsetMask() { } void ScummEngine::clearTextSurface() { - fill((byte*)_textSurface.pixels, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, _textSurface.w, _textSurface.h, _textSurface.bytesPerPixel); + if (_townsScreen) + _townsScreen->fillLayerRect(1, 0, 0, _textSurface.w, _textSurface.h, 0); + + fill((byte*)_textSurface.pixels, _textSurface.pitch, _game.platform == Common::kPlatformFMTowns ? 0 : CHARSET_MASK_TRANSPARENCY, _textSurface.w, _textSurface.h, _textSurface.bytesPerPixel); } byte *ScummEngine::getMaskBuffer(int x, int y, int z) { @@ -1256,13 +1254,25 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) { backbuff = vs->getPixels(x, y); bgbuff = vs->getBackPixels(x, y); - if (color == -1) { - if (vs->number != kMainVirtScreen) - error("can only copy bg to main window"); - blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->bytesPerPixel); - if (_charset->_hasMask) { - byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop) * _textSurfaceMultiplier); - fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel); + // A check for -1 might be wrong in all cases since o5_drawBox() in its current form + // is definitely not capable of passing a parameter of -1 (color range is 0 - 255). + // Just to make sure I don't break anything I restrict the code change to FM-Towns + // version 5 games where this change is necessary to fix certain long standing bugs. + if (color == -1 || (color >= 254 && _game.platform == Common::kPlatformFMTowns && (_game.id == GID_MONKEY2 || _game.id == GID_INDY4))) { + if (_game.platform == Common::kPlatformFMTowns) { + if (color == 254) { + color = color; + towns_setupPalCycleField(x, y, x2, y2); + } + } else { + if (vs->number != kMainVirtScreen) + error("can only copy bg to main window"); + + blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->bytesPerPixel); + if (_charset->_hasMask) { + byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop) * _textSurfaceMultiplier); + fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel); + } } } else if (_game.heversion >= 72) { // Flags are used for different methods in HE games @@ -1293,10 +1303,20 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) { fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel); } } else { - if (_game.features & GF_16BIT_COLOR) + if (_game.features & GF_16BIT_COLOR) { fill(backbuff, vs->pitch, _16BitPalette[color], width, height, vs->bytesPerPixel); - else + } else { + if (_game.platform == Common::kPlatformFMTowns) { + color = ((color & 0x0f) << 4) | (color & 0x0f); + byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop + vs->topline) * _textSurfaceMultiplier); + fill(mask, _textSurface.pitch, color, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel); + + if (_game.id == GID_MONKEY2 || _game.id == GID_INDY4) + return; + } + fill(backbuff, vs->pitch, color, width, height, vs->bytesPerPixel); + } } } @@ -1703,6 +1723,11 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const warning("Gdi::drawBitmap, strip drawn to %d below window bottom %d", y + height, vs->h); } + if (_vm->_townsPaletteFlags & 2) { + int cx = (x - _vm->_screenStartStrip) << 3; + _vm->_textSurface.fillRect(Common::Rect(cx * _vm->_textSurfaceMultiplier, y * _vm->_textSurfaceMultiplier, (cx + width - 1) * _vm->_textSurfaceMultiplier, (y + height - 1) * _vm->_textSurfaceMultiplier), 0); + } + _vertStripNextInc = height * vs->pitch - 1 * vs->bytesPerPixel; _objectMode = (flag & dbObjectMode) == dbObjectMode; @@ -3662,6 +3687,9 @@ void ScummEngine::fadeOut(int effect) { // Fill screen 0 with black memset(vs->getPixels(0, 0), 0, vs->pitch * vs->h); + if (_game.version == 3 && _game.platform == Common::kPlatformFMTowns) + _textSurface.fillRect(Common::Rect(0, vs->topline * _textSurfaceMultiplier, _textSurface.pitch, (vs->topline + vs->h) * _textSurfaceMultiplier), 0); + // Fade to black with the specified effect, if any. switch (effect) { case 1: @@ -3856,15 +3884,10 @@ void ScummEngine::dissolveEffect(int width, int height) { x = offsets[i] % vs->pitch; y = offsets[i] / vs->pitch; - if (_useCJKMode && _textSurfaceMultiplier == 2) { - int m = _textSurfaceMultiplier; - byte *dst = _fmtownsBuf + x * m + y * m * _screenWidth * m; - scale2x(dst, _screenWidth * m, vs->getPixels(x, y), vs->pitch, width, height); - - _system->copyRectToScreen(dst, _screenWidth * m, x * m, (y + vs->topline) * m, width * m, height * m); - } else { + if (_game.platform == Common::kPlatformFMTowns) + towns_drawStripToScreen(vs, x, y + vs->topline, x, y, width, height); + else _system->copyRectToScreen(vs->getPixels(x, y), vs->pitch, x, y + vs->topline, width, height); - } if (++blits >= blits_before_refresh) { @@ -3904,23 +3927,19 @@ void ScummEngine::scrollEffect(int dir) { y = 1 + step; while (y < vs->h) { moveScreen(0, -step, vs->h); - - src = vs->getPixels(0, y - step); - if (_useCJKMode && m == 2) { - int x1 = 0, y1 = vs->h - step; - byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m; - scale2x(dst, _screenWidth * m, src, vs->pitch, vs->w, step); - src = dst; - vsPitch = _screenWidth * 2; + + if (_townsScreen) { + towns_drawStripToScreen(vs, 0, vs->topline + vs->h - step, 0, y - step, vs->w, step); + } else { + src = vs->getPixels(0, y - step); + _system->copyRectToScreen(src, + vsPitch, + 0, (vs->h - step) * m, + vs->w * m, step * m); + _system->updateScreen(); } - - _system->copyRectToScreen(src, - vsPitch, - 0 * m, (vs->h - step) * m, - vs->w * m, step * m); - _system->updateScreen(); + waitForTimer(delay); - y += step; } break; @@ -3929,21 +3948,19 @@ void ScummEngine::scrollEffect(int dir) { y = 1 + step; while (y < vs->h) { moveScreen(0, step, vs->h); - src = vs->getPixels(0, vs->h - y); - if (_useCJKMode && m == 2) { - int x1 = 0, y1 = 0; - byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m; - scale2x(dst, _screenWidth * m, src, vs->pitch, vs->w, step); - src = dst; - vsPitch = _screenWidth * 2; + + if (_townsScreen) { + towns_drawStripToScreen(vs, 0, vs->topline, 0, vs->h - y, vs->w, step); + } else { + src = vs->getPixels(0, vs->h - y); + _system->copyRectToScreen(src, + vsPitch, + 0, 0, + vs->w * m, step * m); + _system->updateScreen(); } - _system->copyRectToScreen(src, - vsPitch, - 0, 0, - vs->w * m, step * m); - _system->updateScreen(); + waitForTimer(delay); - y += step; } break; @@ -3952,21 +3969,19 @@ void ScummEngine::scrollEffect(int dir) { x = 1 + step; while (x < vs->w) { moveScreen(-step, 0, vs->h); - src = vs->getPixels(x - step, 0); - if (_useCJKMode && m == 2) { - int x1 = vs->w - step, y1 = 0; - byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m; - scale2x(dst, _screenWidth * m, src, vs->pitch, step, vs->h); - src = dst; - vsPitch = _screenWidth * 2; + + if (_townsScreen) { + towns_drawStripToScreen(vs, vs->w - step, vs->topline, x - step, 0, step, vs->h); + } else { + src = vs->getPixels(x - step, 0); + _system->copyRectToScreen(src, + vsPitch, + (vs->w - step) * m, 0, + step * m, vs->h * m); + _system->updateScreen(); } - _system->copyRectToScreen(src, - vsPitch, - (vs->w - step) * m, 0, - step * m, vs->h * m); - _system->updateScreen(); - waitForTimer(delay); + waitForTimer(delay); x += step; } break; @@ -3975,21 +3990,19 @@ void ScummEngine::scrollEffect(int dir) { x = 1 + step; while (x < vs->w) { moveScreen(step, 0, vs->h); - src = vs->getPixels(vs->w - x, 0); - if (_useCJKMode && m == 2) { - int x1 = 0, y1 = 0; - byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m; - scale2x(dst, _screenWidth * m, src, vs->pitch, step, vs->h); - src = dst; - vsPitch = _screenWidth * 2; - } - _system->copyRectToScreen(src, - vsPitch, - 0, 0, - step, vs->h); - _system->updateScreen(); - waitForTimer(delay); + if (_townsScreen) { + towns_drawStripToScreen(vs, 0, vs->topline, vs->w - x, 0, step, vs->h); + } else { + src = vs->getPixels(vs->w - x, 0); + _system->copyRectToScreen(src, + vsPitch, + 0, 0, + step, vs->h); + _system->updateScreen(); + } + + waitForTimer(delay); x += step; } break; |