// Diagonally displays new screen starting from center - works on _picRect area // only. Assumes that height of rect is larger than width. void GfxTransitions::diagonalRollFromCenter(bool blackoutFlag) { int16 halfHeight = _picRect.height() / 2; Common::Rect upperRect(_picRect.left + halfHeight - 2, _picRect.top + halfHeight, _picRect.right - halfHeight + 1, _picRect.top + halfHeight + 1); Common::Rect lowerRect(upperRect.left, upperRect.top, upperRect.right, upperRect.bottom); Common::Rect leftRect(upperRect.left, upperRect.top, upperRect.left + 1, lowerRect.bottom); Common::Rect rightRect(upperRect.right, upperRect.top, upperRect.right + 1, lowerRect.bottom); uint32 msecCount = 0; while ((upperRect.top >= _picRect.top) || (lowerRect.bottom <= _picRect.bottom)) { if (upperRect.top < _picRect.top) { upperRect.translate(0, 1); leftRect.top++; rightRect.top++; } if (lowerRect.bottom > _picRect.bottom) { lowerRect.translate(0, -1); leftRect.bottom--; rightRect.bottom--; } if (leftRect.left < _picRect.left) { leftRect.translate(1, 0); upperRect.left++; lowerRect.left++; } if (rightRect.right > _picRect.right) { rightRect.translate(-1, 0); upperRect.right--; lowerRect.right--; } copyRectToScreen(upperRect, blackoutFlag); upperRect.translate(0, -1); upperRect.left--; upperRect.right++; copyRectToScreen(lowerRect, blackoutFlag); lowerRect.translate(0, 1); lowerRect.left--; lowerRect.right++; copyRectToScreen(leftRect, blackoutFlag); leftRect.translate(-1, 0); leftRect.top--; leftRect.bottom++; copyRectToScreen(rightRect, blackoutFlag); rightRect.translate(1, 0); rightRect.top--; rightRect.bottom++; msecCount += 4; if (doCreateFrame(msecCount)) { updateScreenAndWait(msecCount); } } }
// Directly shows new screen starting up/down/left/right and going to the // opposite direction - works on _picRect area only void GfxTransitions::straight(int16 number, bool blackoutFlag) { int16 stepNr = 0; Common::Rect newScreenRect = _picRect; uint32 msecCount = 0; switch (number) { case SCI_TRANSITIONS_STRAIGHT_FROM_RIGHT: newScreenRect.left = newScreenRect.right - 1; while (newScreenRect.left >= _picRect.left) { copyRectToScreen(newScreenRect, blackoutFlag); if ((stepNr & 1) == 0) { msecCount += 2; updateScreenAndWait(msecCount); } stepNr++; newScreenRect.translate(-1, 0); } break; case SCI_TRANSITIONS_STRAIGHT_FROM_LEFT: newScreenRect.right = newScreenRect.left + 1; while (newScreenRect.right <= _picRect.right) { copyRectToScreen(newScreenRect, blackoutFlag); if ((stepNr & 1) == 0) { msecCount += 2; updateScreenAndWait(msecCount); } stepNr++; newScreenRect.translate(1, 0); } break; case SCI_TRANSITIONS_STRAIGHT_FROM_BOTTOM: newScreenRect.top = newScreenRect.bottom - 1; while (newScreenRect.top >= _picRect.top) { copyRectToScreen(newScreenRect, blackoutFlag); msecCount += 4; updateScreenAndWait(msecCount); stepNr++; newScreenRect.translate(0, -1); } break; case SCI_TRANSITIONS_STRAIGHT_FROM_TOP: newScreenRect.bottom = newScreenRect.top + 1; while (newScreenRect.bottom <= _picRect.bottom) { copyRectToScreen(newScreenRect, blackoutFlag); msecCount += 4; updateScreenAndWait(msecCount); stepNr++; newScreenRect.translate(0, 1); } break; } }
// Horizontally displays new screen starting from upper and lower edge - works // on _picRect area only void GfxTransitions::horizontalRollToCenter(bool blackoutFlag) { Common::Rect upperRect = Common::Rect(_picRect.left, _picRect.top, _picRect.right, _picRect.top + 1); Common::Rect lowerRect = Common::Rect(upperRect.left, _picRect.bottom - 1, upperRect.right, _picRect.bottom); uint32 msecCount = 0; while (upperRect.top < lowerRect.bottom) { copyRectToScreen(upperRect, blackoutFlag); upperRect.translate(0, 1); copyRectToScreen(lowerRect, blackoutFlag); lowerRect.translate(0, -1); msecCount += 4; updateScreenAndWait(msecCount); } }
// Vertically displays new screen starting from edges - works on _picRect area // only void GfxTransitions::verticalRollToCenter(bool blackoutFlag) { Common::Rect leftRect = Common::Rect(_picRect.left, _picRect.top, _picRect.left + 1, _picRect.bottom); Common::Rect rightRect = Common::Rect(_picRect.right - 1, _picRect.top, _picRect.right, _picRect.bottom); uint32 msecCount = 0; while (leftRect.left < rightRect.right) { copyRectToScreen(leftRect, blackoutFlag); leftRect.translate(1, 0); copyRectToScreen(rightRect, blackoutFlag); rightRect.translate(-1, 0); msecCount += 3; updateScreenAndWait(msecCount); } }
void RMWindow::getNewFrame(RMGfxTargetBuffer &bigBuf, Common::Rect *rcBoundEllipse) { // Get a pointer to the bytes of the source buffer byte *lpBuf = bigBuf; if (rcBoundEllipse != NULL) { // Circular wipe effect getNewFrameWipe(lpBuf, *rcBoundEllipse); _wiping = true; } else if (_wiping) { // Just finished a wiping effect, so copy the full screen copyRectToScreen(lpBuf, RM_SX * 2, 0, 0, RM_SX, RM_SY); _wiping = false; } else { // Standard screen copy - iterate through the dirty rects Common::List<Common::Rect> dirtyRects = bigBuf.getDirtyRects(); Common::List<Common::Rect>::iterator i; // If showing dirty rects, copy the entire screen background and set up a surface pointer Graphics::Surface *s = NULL; if (_showDirtyRects) { copyRectToScreen(lpBuf, RM_SX * 2, 0, 0, RM_SX, RM_SY); s = g_system->lockScreen(); } for (i = dirtyRects.begin(); i != dirtyRects.end(); ++i) { Common::Rect &r = *i; const byte *lpSrc = lpBuf + (RM_SX * 2) * r.top + (r.left * 2); copyRectToScreen(lpSrc, RM_SX * 2, r.left, r.top, r.width(), r.height()); } if (_showDirtyRects) { for (i = dirtyRects.begin(); i != dirtyRects.end(); ++i) { // Frame the copied area with a rectangle s->frameRect(*i, 0xffffff); } g_system->unlockScreen(); } } if (_bGrabThumbnail) { // Need to generate a thumbnail RMSnapshot s; s.grabScreenshot(lpBuf, 4, _wThumbBuf); _bGrabThumbnail = false; } // Clear the dirty rect list bigBuf.clearDirtyRects(); }
// Diagonally displays new screen starting from edges - works on _picRect area // only. Assumes that height of rect is larger than width. void GfxTransitions::diagonalRollToCenter(bool blackoutFlag) { Common::Rect upperRect(_picRect.left, _picRect.top, _picRect.right, _picRect.top + 1); Common::Rect lowerRect(_picRect.left, _picRect.bottom - 1, _picRect.right, _picRect.bottom); Common::Rect leftRect(_picRect.left, _picRect.top, _picRect.left + 1, _picRect.bottom); Common::Rect rightRect(_picRect.right - 1, _picRect.top, _picRect.right, _picRect.bottom); uint32 msecCount = 0; while (upperRect.top < lowerRect.bottom) { copyRectToScreen(upperRect, blackoutFlag); upperRect.translate(0, 1); upperRect.left++; upperRect.right--; copyRectToScreen(lowerRect, blackoutFlag); lowerRect.translate(0, -1); lowerRect.left++; lowerRect.right--; copyRectToScreen(leftRect, blackoutFlag); leftRect.translate(1, 0); copyRectToScreen(rightRect, blackoutFlag); rightRect.translate(-1, 0); msecCount += 4; updateScreenAndWait(msecCount); } }
// Horizontally displays new screen starting from center - works on _picRect // area only void GfxTransitions::horizontalRollFromCenter(bool blackoutFlag) { Common::Rect upperRect = Common::Rect(_picRect.left, _picRect.top + (_picRect.height() / 2) - 1, _picRect.right, _picRect.top + (_picRect.height() / 2)); Common::Rect lowerRect = Common::Rect(upperRect.left, upperRect.bottom, upperRect.right, upperRect.bottom + 1); uint32 msecCount = 0; while ((upperRect.top >= _picRect.top) || (lowerRect.bottom <= _picRect.bottom)) { if (upperRect.top < _picRect.top) upperRect.translate(0, 1); if (lowerRect.bottom > _picRect.bottom) lowerRect.translate(0, -1); copyRectToScreen(upperRect, blackoutFlag); upperRect.translate(0, -1); copyRectToScreen(lowerRect, blackoutFlag); lowerRect.translate(0, 1); msecCount += 4; updateScreenAndWait(msecCount); } }
// Vertically displays new screen starting from center - works on _picRect area // only void GfxTransitions::verticalRollFromCenter(bool blackoutFlag) { Common::Rect leftRect = Common::Rect(_picRect.left + (_picRect.width() / 2) -1, _picRect.top, _picRect.left + (_picRect.width() / 2), _picRect.bottom); Common::Rect rightRect = Common::Rect(leftRect.right, _picRect.top, leftRect.right + 1, _picRect.bottom); uint32 msecCount = 0; while ((leftRect.left >= _picRect.left) || (rightRect.right <= _picRect.right)) { if (leftRect.left < _picRect.left) leftRect.translate(1, 0); if (rightRect.right > _picRect.right) rightRect.translate(-1, 0); copyRectToScreen(leftRect, blackoutFlag); leftRect.translate(-1, 0); copyRectToScreen(rightRect, blackoutFlag); rightRect.translate(1, 0); msecCount += 3; updateScreenAndWait(msecCount); } }
/** * Handles drawing the line splices for the circle of viewable area */ void RMWindow::plotLines(const byte *lpBuf, const Common::Point ¢er, int x, int y) { // Skips lines that have no width (i.e. at the top of the circle) if ((x == 0) || (y > center.y)) return; const byte *pSrc; int xs = MAX(center.x - x, 0); int width = MIN(RM_SX - xs, x * 2); if ((center.y - y) >= 0) { // Draw line in top half of circle pSrc = lpBuf + ((center.y - y) * RM_SX * 2) + xs * 2; copyRectToScreen(pSrc, RM_SX * 2, xs, center.y - y, width, 1); } if ((center.y + y) < RM_SY) { // Draw line in bottom half of circle pSrc = lpBuf + ((center.y + y) * RM_SX * 2) + xs * 2; copyRectToScreen(pSrc, RM_SX * 2, xs, center.y + y, width, 1); } }
/** * Wipes an area of the screen */ void RMWindow::wipeEffect(Common::Rect &rcBoundEllipse) { if ((rcBoundEllipse.left == 0) && (rcBoundEllipse.top == 0) && (rcBoundEllipse.right == RM_SX) && (rcBoundEllipse.bottom == RM_SY)) { // Full screen clear wanted, so use shortcut method g_system->fillScreen(0); } else { // Clear the designated area a line at a time uint16 line[RM_SX]; Common::fill(line, line + RM_SX, 0); // Loop through each line for (int yp = rcBoundEllipse.top; yp < rcBoundEllipse.bottom; ++yp) { copyRectToScreen((const byte *)&line[0], RM_SX * 2, rcBoundEllipse.left, yp, rcBoundEllipse.width(), 1); } } }
// Like pixelation but uses 8x8 blocks - works against the whole screen. // TODO: it seems this needs to get applied on _picRect only if possible void GfxTransitions::blocks(bool blackoutFlag) { uint16 mask = 0x40, stepNr = 0; Common::Rect blockRect; uint32 msecCount = 0; do { mask = (mask & 1) ? (mask >> 1) ^ 0x240 : mask >> 1; if (mask >= 40 * 25) continue; blockRect.left = (mask % 40) << 3; blockRect.right = blockRect.left + 8; blockRect.top = (mask / 40) << 3; blockRect.bottom = blockRect.top + 8; blockRect.clip(_picRect); if (!blockRect.isEmpty()) copyRectToScreen(blockRect, blackoutFlag); if ((stepNr & 7) == 0) { msecCount += 5; updateScreenAndWait(msecCount); } stepNr++; } while (mask != 0x40); }
// Pixelates the new picture over the old one - works against the whole screen. // TODO: it seems this needs to get applied on _picRect only if possible void GfxTransitions::pixelation(bool blackoutFlag) { uint16 mask = 0x40, stepNr = 0; Common::Rect pixelRect; uint32 msecCount = 0; do { mask = (mask & 1) ? (mask >> 1) ^ 0xB400 : mask >> 1; if (mask >= _screen->getWidth() * _screen->getHeight()) continue; pixelRect.left = mask % _screen->getWidth(); pixelRect.right = pixelRect.left + 1; pixelRect.top = mask / _screen->getWidth(); pixelRect.bottom = pixelRect.top + 1; pixelRect.clip(_picRect); if (!pixelRect.isEmpty()) copyRectToScreen(pixelRect, blackoutFlag); if ((stepNr & 0x3FF) == 0) { msecCount += 9; updateScreenAndWait(msecCount); } stepNr++; } while (mask != 0x40); }
void ScreenSurface::copyRectToScreen(const Common::Rect &bounds) { copyRectToScreen(Common::Point(bounds.left, bounds.top), bounds); }