diff options
Diffstat (limited to 'engines/made/screen.cpp')
-rw-r--r-- | engines/made/screen.cpp | 315 |
1 files changed, 211 insertions, 104 deletions
diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp index 74053e70a2..cecd0c8968 100644 --- a/engines/made/screen.cpp +++ b/engines/made/screen.cpp @@ -32,20 +32,27 @@ namespace Made { Screen::Screen(MadeEngine *vm) : _vm(vm) { - _screen1 = new Graphics::Surface(); - _screen1->create(320, 200, 1); - _screen2 = new Graphics::Surface(); - _screen2->create(320, 200, 1); - - _clipInfo1.x = _clipInfo2.x = 0; - _clipInfo1.y = _clipInfo2.y = 0; - _clipInfo1.w = _clipInfo2.w = 320; - _clipInfo1.h = _clipInfo2.h = 200; - - _clipInfo1.destSurface = _screen1; - _clipInfo2.destSurface = _screen2; - _clipArea.destSurface = _screen2; - + _backgroundScreen = new Graphics::Surface(); + _backgroundScreen->create(320, 200, 1); + + _workScreen = new Graphics::Surface(); + _workScreen->create(320, 200, 1); + + _backgroundScreenDrawCtx.clipRect = Common::Rect(320, 200); + _workScreenDrawCtx.clipRect = Common::Rect(320, 200); + + _backgroundScreenDrawCtx.destSurface = _backgroundScreen; + _workScreenDrawCtx.destSurface = _workScreen; + _clipArea.destSurface = _workScreen; + + // Screen mask is only needed in v2 games + if (_vm->getGameID() != GID_RTZ) { + _screenMask = new Graphics::Surface(); + _screenMask->create(320, 200, 1); + _maskDrawCtx.clipRect = Common::Rect(320, 200); + _maskDrawCtx.destSurface = _screenMask; + } + for (int i = 0; i <= 3; i++) _excludeClipAreaEnabled[i] = false; @@ -62,8 +69,10 @@ Screen::Screen(MadeEngine *vm) : _vm(vm) { _ground = 1; _clip = 0; _exclude = 0; + _mask = 0; _visualEffectNum = 0; + _fx = new ScreenEffects(this); _textX = 0; _textY = 0; @@ -74,64 +83,130 @@ Screen::Screen(MadeEngine *vm) : _vm(vm) { _textRect.bottom = 200; _font = NULL; _currentFontNum = 0; - _fontDrawCtx.x = 0; - _fontDrawCtx.y = 0; - _fontDrawCtx.w = 320; - _fontDrawCtx.h = 200; - _fontDrawCtx.destSurface = _screen1; + _fontDrawCtx.clipRect = Common::Rect(320, 200); + _fontDrawCtx.destSurface = _backgroundScreen; clearChannels(); } Screen::~Screen() { - delete _screen1; - delete _screen2; + delete _backgroundScreen; + delete _workScreen; + if (_vm->getGameID() != GID_RTZ) + delete _screenMask; + delete _fx; } void Screen::clearScreen() { - _screen1->fillRect(Common::Rect(0, 0, 320, 200), 0); - _screen2->fillRect(Common::Rect(0, 0, 320, 200), 0); + _backgroundScreen->fillRect(Common::Rect(0, 0, 320, 200), 0); + _workScreen->fillRect(Common::Rect(0, 0, 320, 200), 0); + if (_vm->getGameID() != GID_RTZ) + _screenMask->fillRect(Common::Rect(0, 0, 320, 200), 0); + _mask = 0; _needPalette = true; } -void Screen::drawSurface(Graphics::Surface *sourceSurface, int x, int y, const ClipInfo &clipInfo) { +void Screen::setExcludeArea(uint16 x1, uint16 y1, uint16 x2, uint16 y2) { + + _excludeClipAreaEnabled[0] = false; + _excludeClipAreaEnabled[1] = false; + _excludeClipAreaEnabled[2] = false; + _excludeClipAreaEnabled[3] = false; + + if (x1 == 0 && y1 == 0 && x2 == 0 && y2 == 0) { + _excludeClipArea[0].clipRect = Common::Rect(320, 200); + _excludeClipAreaEnabled[0] = true; + return; + } + + if (y1 > 0 && y2 > 0) { + _excludeClipArea[0].clipRect = Common::Rect(320, y1); + _excludeClipAreaEnabled[0] = true; + } + + if (y1 < 200 && y2 < 200) { + _excludeClipArea[1].clipRect = Common::Rect(0, y2, 320, 200); + _excludeClipAreaEnabled[1] = true; + } + + if (x1 > 0 && x2 > 0) { + _excludeClipArea[2].clipRect = Common::Rect(0, y1, x1, y2); + _excludeClipAreaEnabled[2] = true; + } + + if (x1 < 320 && x2 < 320) { + _excludeClipArea[3].clipRect = Common::Rect(x2, y1, 320, y2); + _excludeClipAreaEnabled[3] = true; + } + +} + +void Screen::drawSurface(Graphics::Surface *sourceSurface, int x, int y, int16 flipX, int16 flipY, int16 mask, const ClipInfo &clipInfo) { - byte *source, *dest; + byte *source, *dest, *maskp = 0; int startX = 0; int startY = 0; int clipWidth = sourceSurface->w; int clipHeight = sourceSurface->h; - if (x < 0) { - startX = -x; + if (x < clipInfo.clipRect.left) { + startX = clipInfo.clipRect.left - x; clipWidth -= startX; - x = 0; + x = clipInfo.clipRect.left; } - if (y < 0) { - startY = -y; + if (y < clipInfo.clipRect.top) { + startY = clipInfo.clipRect.top - y; clipHeight -= startY; - y = 0; + y = clipInfo.clipRect.top; } - if (x + clipWidth > clipInfo.x + clipInfo.w) { - clipWidth = clipInfo.x + clipInfo.w - x; + if (x + clipWidth > clipInfo.clipRect.right) { + clipWidth = clipInfo.clipRect.right - x; } - if (y + clipHeight > clipInfo.y + clipInfo.h) { - clipHeight = clipInfo.y + clipInfo.h - y; + if (y + clipHeight > clipInfo.clipRect.bottom) { + clipHeight = clipInfo.clipRect.bottom - y; } source = (byte*)sourceSurface->getBasePtr(startX, startY); dest = (byte*)clipInfo.destSurface->getBasePtr(x, y); + if (_vm->getGameID() != GID_RTZ) + maskp = (byte*)_maskDrawCtx.destSurface->getBasePtr(x, y); + + int32 sourcePitch, linePtrAdd; + byte *linePtr; + + if (flipX) { + linePtrAdd = -1; + } else { + linePtrAdd = 1; + } + + if (flipY) { + sourcePitch = -sourceSurface->pitch; + source += (clipHeight - 1) * sourceSurface->pitch; + } else { + sourcePitch = sourceSurface->pitch; + } for (int16 yc = 0; yc < clipHeight; yc++) { + if (flipX) { + linePtr = source + sourceSurface->w; + } else { + linePtr = source; + } for (int16 xc = 0; xc < clipWidth; xc++) { - if (source[xc]) - dest[xc] = source[xc]; + if (*linePtr && (_vm->getGameID() == GID_RTZ || (mask == 0 || maskp[xc] == 0))) { + if (*linePtr) + dest[xc] = *linePtr; + } + linePtr += linePtrAdd; } - source += sourceSurface->pitch; + source += sourcePitch; dest += clipInfo.destSurface->pitch; + if (_vm->getGameID() != GID_RTZ) + maskp += _maskDrawCtx.destSurface->pitch; } } @@ -191,11 +266,16 @@ uint16 Screen::setChannelLocation(uint16 channelIndex, int16 x, int16 y) { uint16 Screen::setChannelContent(uint16 channelIndex, uint16 index) { if (channelIndex < 1 || channelIndex >= 100 || _channels[channelIndex - 1].type == 0) return 0; - //debug(2, "setChannelContent(%d, %04X)\n", channelIndex, index); fflush(stdout); g_system->delayMillis(5000); _channels[channelIndex - 1].index = index; return updateChannel(channelIndex - 1) + 1; } +void Screen::setChannelUseMask(uint16 channelIndex) { + if (channelIndex < 1 || channelIndex >= 100) + return; + _channels[channelIndex - 1].mask = _mask; +} + void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask, int16 excludeStateMask) { for (int i = 0; i <= 3; i++) @@ -208,8 +288,8 @@ void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask debug(2, "drawSpriteChannels() i = %d\n", i); if (((_channels[i].state & includeStateMask) == includeStateMask) && (_channels[i].state & excludeStateMask) == 0) { - uint16 flag1 = _channels[i].state & 0x10; - uint16 flag2 = _channels[i].state & 0x20; + int16 flipX = _channels[i].state & 0x10; + int16 flipY = _channels[i].state & 0x20; debug(2, "drawSpriteChannels() type = %d; index = %04X\n", _channels[i].type, _channels[i].index); @@ -217,38 +297,38 @@ void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask case 1: // drawFlex if (_channels[i].state & 4) { - drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, _clipArea); + drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flipX, flipY, _channels[i].mask, _clipArea); } else if (_channels[i].state & 8) { for (int excludeIndex = 0; excludeIndex < 4; excludeIndex++) { if (_excludeClipAreaEnabled[excludeIndex]) { - drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, _excludeClipArea[excludeIndex]); + drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flipX, flipY, _channels[i].mask, _excludeClipArea[excludeIndex]); } } } else { - drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, clipInfo); + drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flipX, flipY, _channels[i].mask, clipInfo); } break; - + case 2: // drawObjectText printObjectText(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].fontNum, _channels[i].textColor, _channels[i].outlineColor, clipInfo); break; case 3: // drawAnimFrame if (_channels[i].state & 4) { - drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, _clipArea); + drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flipX, flipY, _clipArea); } else if (_channels[i].state & 8) { for (int excludeIndex = 0; excludeIndex < 4; excludeIndex++) { if (_excludeClipAreaEnabled[excludeIndex]) { - drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, _excludeClipArea[excludeIndex]); + drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flipX, flipY, _excludeClipArea[excludeIndex]); } } } else { - drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, clipInfo); + drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flipX, flipY, clipInfo); } break; case 4: // drawMenuText - // TODO + // Never used in any game break; default: @@ -265,12 +345,14 @@ void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask void Screen::updateSprites() { // TODO: This needs some more work, dirty rectangles are currently not used - memcpy(_screen2->pixels, _screen1->pixels, 64000); + memcpy(_workScreen->pixels, _backgroundScreen->pixels, 64000); - drawSpriteChannels(_clipInfo1, 3, 0); - drawSpriteChannels(_clipInfo2, 1, 2); + drawSpriteChannels(_backgroundScreenDrawCtx, 3, 0); + drawSpriteChannels(_workScreenDrawCtx, 1, 2); - _vm->_system->copyRectToScreen((const byte*)_screen2->pixels, _screen2->pitch, 0, 0, _screen2->w, _screen2->h); + _vm->_system->copyRectToScreen((const byte*)_workScreen->pixels, _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h); + + _vm->_system->updateScreen(); } @@ -278,11 +360,12 @@ void Screen::clearChannels() { for (uint16 i = 0; i < ARRAYSIZE(_channels); i++) { _channels[i].type = 0; _channels[i].index = 0; + _channels[i].mask = 0; } _channelsUsedCount = 0; } -uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo) { +uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, int16 flipX, int16 flipY, int16 mask, const ClipInfo &clipInfo) { if (flexIndex == 0) return 0; @@ -290,7 +373,7 @@ uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 PictureResource *flex = _vm->_res->getPicture(flexIndex); Graphics::Surface *sourceSurface = flex->getPicture(); - drawSurface(sourceSurface, x, y, clipInfo); + drawSurface(sourceSurface, x, y, flipX, flipY, mask, clipInfo); // Palette is set in showPage if (flex->hasPalette() && !_paletteLock && _needPalette) { @@ -307,7 +390,7 @@ uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 return 0; } -void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo) { +void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, int16 flipX, int16 flipY, const ClipInfo &clipInfo) { if (frameNum < 0) return; @@ -315,24 +398,29 @@ void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, u AnimationResource *anim = _vm->_res->getAnimation(animIndex); Graphics::Surface *sourceSurface = anim->getFrame(frameNum); - drawSurface(sourceSurface, x, y, clipInfo); + drawSurface(sourceSurface, x, y, flipX, flipY, 0, clipInfo); _vm->_res->freeResource(anim); } -uint16 Screen::drawPic(uint16 index, int16 x, int16 y, uint16 flag1, uint16 flag2) { - drawFlex(index, x, y, flag1, flag2, _clipInfo1); +uint16 Screen::drawPic(uint16 index, int16 x, int16 y, int16 flipX, int16 flipY) { + drawFlex(index, x, y, flipX, flipY, 0, _backgroundScreenDrawCtx); return 0; } -uint16 Screen::drawAnimPic(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2) { - drawAnimFrame(animIndex, x, y, frameNum, flag1, flag2, _clipInfo1); +uint16 Screen::drawMask(uint16 index, int16 x, int16 y) { + drawFlex(index, x, y, 0, 0, 0, _maskDrawCtx); + return 0; +} + +uint16 Screen::drawAnimPic(uint16 animIndex, int16 x, int16 y, int16 frameNum, int16 flipX, int16 flipY) { + drawAnimFrame(animIndex, x, y, frameNum, flipX, flipY, _backgroundScreenDrawCtx); return 0; } void Screen::addSprite(uint16 spriteIndex) { bool oldScreenLock = _screenLock; - drawFlex(spriteIndex, 0, 0, 0, 0, _clipInfo1); + drawFlex(spriteIndex, 0, 0, 0, 0, 0, _backgroundScreenDrawCtx); _screenLock = oldScreenLock; } @@ -342,7 +430,7 @@ uint16 Screen::drawSprite(uint16 flexIndex, int16 x, int16 y) { uint16 Screen::placeSprite(uint16 channelIndex, uint16 flexIndex, int16 x, int16 y) { - debug(2, "placeSprite(%d, %04X, %d, %d)\n", channelIndex, flexIndex, x, y); fflush(stdout); + debug(2, "placeSprite(%d, %04X, %d, %d)\n", channelIndex, flexIndex, x, y); if (channelIndex < 1 || channelIndex >= 100) return 0; @@ -379,8 +467,8 @@ uint16 Screen::placeSprite(uint16 channelIndex, uint16 flexIndex, int16 x, int16 _channels[channelIndex].y1 = y1; _channels[channelIndex].x2 = x2; _channels[channelIndex].y2 = y2; - _channels[channelIndex].area = (x2 - x2) * (y2 - y1); - + _channels[channelIndex].area = (x2 - x1) * (y2 - y1); + if (_channelsUsedCount <= channelIndex) _channelsUsedCount = channelIndex + 1; @@ -432,7 +520,7 @@ uint16 Screen::placeAnim(uint16 channelIndex, uint16 animIndex, int16 x, int16 y _channels[channelIndex].y1 = y1; _channels[channelIndex].x2 = x2; _channels[channelIndex].y2 = y2; - _channels[channelIndex].area = (x2 - x2) * (y2 - y1); + _channels[channelIndex].area = (x2 - x1) * (y2 - y1); if (_channelsUsedCount <= channelIndex) _channelsUsedCount = channelIndex + 1; @@ -462,17 +550,6 @@ int16 Screen::getAnimFrame(uint16 channelIndex) { return _channels[channelIndex - 1].frameNum; } -int16 Screen::getAnimFrameCount(uint16 animIndex) { - int16 frameCount = 0; - AnimationResource *anim = _vm->_res->getAnimation(animIndex); - if (anim) { - frameCount = anim->getCount(); - _vm->_res->freeResource(anim); - } - return frameCount; -} - - uint16 Screen::placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, int16 y, uint16 fontNum, int16 textColor, int16 outlineColor) { if (channelIndex < 1 || channelIndex >= 100 || textObjectIndex == 0 || fontNum == 0) @@ -525,7 +602,7 @@ uint16 Screen::placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, i _channels[channelIndex].y1 = y1; _channels[channelIndex].x2 = x2; _channels[channelIndex].y2 = y2; - _channels[channelIndex].area = (x2 - x2) * (y2 - y1); + _channels[channelIndex].area = (x2 - x1) * (y2 - y1); if (_channelsUsedCount <= channelIndex) _channelsUsedCount = channelIndex + 1; @@ -536,18 +613,17 @@ uint16 Screen::placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, i void Screen::show() { // TODO - + if (_screenLock) return; - drawSpriteChannels(_clipInfo1, 3, 0); - memcpy(_screen2->pixels, _screen1->pixels, 64000); - drawSpriteChannels(_clipInfo2, 1, 2); + drawSpriteChannels(_backgroundScreenDrawCtx, 3, 0); + memcpy(_workScreen->pixels, _backgroundScreen->pixels, 64000); + drawSpriteChannels(_workScreenDrawCtx, 1, 2); + + _fx->run(_visualEffectNum, _workScreen, _palette, _newPalette, _paletteColorCount); + _visualEffectNum = 0; - // TODO: Implement visual effects (palette fading etc.) - if (!_paletteLock) - setRGBPalette(_palette, 0, _paletteColorCount); - _vm->_system->copyRectToScreen((const byte*)_screen2->pixels, _screen2->pitch, 0, 0, _screen2->w, _screen2->h); _vm->_system->updateScreen(); if (!_paletteInitialized) { @@ -559,19 +635,7 @@ void Screen::show() { } void Screen::flash(int flashCount) { - int palSize = _paletteColorCount * 3; - if (flashCount < 1) - flashCount = 1; - for (int i = 0; i < palSize; i++) - _fxPalette[i] = CLIP<byte>(255 - _palette[i], 0, 255); - while (flashCount--) { - setRGBPalette(_fxPalette, 0, _paletteColorCount); - _vm->_system->updateScreen(); - _vm->_system->delayMillis(30); - setRGBPalette(_palette, 0, _paletteColorCount); - _vm->_system->updateScreen(); - _vm->_system->delayMillis(30); - } + _fx->flash(flashCount, _palette, _paletteColorCount); } void Screen::setFont(int16 fontNum) { @@ -588,7 +652,7 @@ void Screen::printChar(uint c, int16 x, int16 y, byte color) { if (!_font) return; - int height = _font->getHeight(); + uint width = 8, height = _font->getHeight(); byte *charData = _font->getChar(c); if (!charData) @@ -596,10 +660,10 @@ void Screen::printChar(uint c, int16 x, int16 y, byte color) { byte p; byte *dest = (byte*)_fontDrawCtx.destSurface->getBasePtr(x, y); - - for (int16 yc = 0; yc < height; yc++) { + + for (uint yc = 0; yc < height; yc++) { p = charData[yc]; - for (int16 xc = 0; xc < 8; xc++) { + for (uint xc = 0; xc < width; xc++) { if (p & 0x80) dest[xc] = color; p <<= 1; @@ -690,7 +754,7 @@ void Screen::printText(const char *text) { } void Screen::printTextEx(const char *text, int16 x, int16 y, int16 fontNum, int16 textColor, int16 outlineColor, const ClipInfo &clipInfo) { - if (*text == 0 || x == 0 || y == 0) + if (*text == 0 || x < 0 || y < 0) return; int16 oldFontNum = _currentFontNum; @@ -728,5 +792,48 @@ int16 Screen::getTextWidth(int16 fontNum, const char *text) { return _font->getTextWidth(text); } +Graphics::Surface *Screen::lockScreen() { + return _vm->_system->lockScreen(); +} + +void Screen::unlockScreen() { + _vm->_system->unlockScreen(); +} + +void Screen::showWorkScreen() { + _vm->_system->copyRectToScreen((const byte*)_workScreen->pixels, _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h); +} + +void Screen::updateScreenAndWait(int delay) { + _vm->_system->updateScreen(); + _vm->_system->delayMillis(delay); +} + +int16 Screen::addToSpriteList(int16 index, int16 xofs, int16 yofs) { + SpriteListItem item; + item.index = index; + item.xofs = xofs; + item.yofs = yofs; + _spriteList.push_back(item); + return _spriteList.size(); +} + +SpriteListItem Screen::getFromSpriteList(int16 index) { + if (((uint) index) > _spriteList.size()) { + SpriteListItem emptyItem; + emptyItem.index = 0; + return emptyItem; + } else { + return _spriteList[index - 1]; + } +} + +void Screen::clearSpriteList() { + _spriteList.clear(); +} + +void Screen::setDefaultMouseCursor() { + CursorMan.replaceCursor(defaultMouseCursor, 16, 16, 9, 2, 0); +} } // End of namespace Made |