void ScreenFader::setFaderValue(const int32 value) { if (value != getFaderValue()) { Fader::setFaderValue(value); if (_screen->getPixels()) { // The original game does a gamma fade here using the Mac API. In order to do // that, it would require an immense amount of CPU processing. This does a // linear fade instead, which looks fairly well, IMO. Graphics::Surface *screen = g_system->lockScreen(); for (uint y = 0; y < _screen->h; y++) { for (uint x = 0; x < _screen->w; x++) { if (_screen->format.bytesPerPixel == 2) WRITE_UINT16(screen->getBasePtr(x, y), fadePixel(READ_UINT16(_screen->getBasePtr(x, y)), value)); else WRITE_UINT32(screen->getBasePtr(x, y), fadePixel(READ_UINT32(_screen->getBasePtr(x, y)), value)); } } g_system->unlockScreen(); g_system->updateScreen(); } } }
void Frame::drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) { uint8 skipColor = _vm->getPaletteColorCount() - 1; for (int ii = 0; ii < sprite.h; ii++) { const byte *src = (const byte *)sprite.getBasePtr(0, ii); byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii); for (int j = 0; j < drawRect.width(); j++) { if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0) && (*src != skipColor)) *dst = (_vm->getPaletteColorCount() - 1) - *src; //Oposite color src++; dst++; } } }
Graphics::Surface BladeRunnerEngine::generateThumbnail() const { Graphics::Surface thumbnail; thumbnail.create(640 / 8, 480 / 8, createRGB555()); for (int y = 0; y < thumbnail.h; ++y) { for (int x = 0; x < thumbnail.w; ++x) { uint16 *dstPixel = (uint16 *)thumbnail.getBasePtr(x, y); const uint16 *srcPixel = (const uint16 *)_surfaceFront.getBasePtr(x * 8, y * 8); *dstPixel = *srcPixel; } } return thumbnail; }
/* * This command draws the scene regions onto the screen. These are the regions * used by hotspots that have non-rectangular areas. */ bool Debugger::Cmd_SceneRegions(int argc, const char **argv) { int regionNum = 0; // Check for an optional specific region to display if (argc == 2) regionNum = strToInt(argv[1]); // Color index to use for the first priority region int color = 16; int count = 0; // Lock the background surface for access Graphics::Surface destSurface = g_globals->_sceneManager._scene->_backSurface.lockSurface(); Common::List<Region>::iterator i = g_globals->_sceneRegions.begin(); Common::String regionsDesc; for (; i != g_globals->_sceneRegions.end(); ++i, ++color, ++count) { Region &r = *i; if ((regionNum == 0) || (regionNum == (count + 1))) { for (int y = 0; y < destSurface.h; ++y) { byte *destP = (byte *)destSurface.getBasePtr(0, y); for (int x = 0; x < destSurface.w; ++x) { if (r.contains(Common::Point(g_globals->_sceneManager._scene->_sceneBounds.left + x, g_globals->_sceneManager._scene->_sceneBounds.top + y))) *destP = color; ++destP; } } } regionsDesc += Common::String::format("Region id = %d bounds=%d,%d,%d,%d\n", r._regionId, r._bounds.left, r._bounds.top, r._bounds.right, r._bounds.bottom); } // Release the surface g_globals->_sceneManager._scene->_backSurface.unlockSurface(); // Mark the scene as requiring a full redraw g_globals->_paneRefreshFlag[0] = 2; DebugPrintf("Total regions = %d\n", count); DebugPrintf("%s", regionsDesc.c_str()); return true; }
void Cursor::loadAvailableCursors() { assert(_textures.empty()); // Load available cursors for (uint i = 0; i < ARRAYSIZE(availableCursors); i++) { // Check if a cursor sharing the same texture has already been loaded if (_textures.contains(availableCursors[i].nodeID)) continue; // Load the cursor bitmap const DirectorySubEntry *cursorDesc = _vm->getFileDescription("GLOB", availableCursors[i].nodeID, 0, DirectorySubEntry::kRawData); if (!cursorDesc) error("Cursor %d does not exist", availableCursors[i].nodeID); Common::MemoryReadStream *bmpStream = cursorDesc->getData(); Image::BitmapDecoder bitmapDecoder; if (!bitmapDecoder.loadStream(*bmpStream)) error("Could not decode Myst III bitmap"); const Graphics::Surface *surfaceBGRA = bitmapDecoder.getSurface(); Graphics::Surface *surfaceRGBA = surfaceBGRA->convertTo(Texture::getRGBAPixelFormat()); delete bmpStream; // Apply the colorkey for transparency for (uint y = 0; y < surfaceRGBA->h; y++) { byte *pixels = (byte *)(surfaceRGBA->getBasePtr(0, y)); for (uint x = 0; x < surfaceRGBA->w; x++) { byte *r = pixels + 0; byte *g = pixels + 1; byte *b = pixels + 2; byte *a = pixels + 3; if (*r == 0 && *g == 0xFF && *b == 0 && *a == 0xFF) { *g = 0; *a = 0; } pixels += 4; } } // Create and store the texture _textures.setVal(availableCursors[i].nodeID, _vm->_gfx->createTexture(surfaceRGBA)); surfaceRGBA->free(); delete surfaceRGBA; } }
/** * Writes out a character at the currently set position using the active font * * @ch Character to display */ int GfxFont::writeChar(const char ch) { assert((_fontData != NULL) && ((uint8)ch < _numChars)); uint32 charOffset = READ_LE_UINT32(_fontData + 12 + (uint8)ch * 4); int charWidth = _fontData[charOffset] & 0x1f; int charHeight = (READ_LE_UINT16(_fontData + charOffset) >> 5) & 0x3f; int yOffset = (_fontData[charOffset + 1] >> 3) & 0x1f; const uint8 *dataP = &_fontData[charOffset + 2]; // Lock the surface for access Graphics::Surface surfacePtr = _gfxManager->lockSurface(); Rect charRect; charRect.set(0, 0, charWidth, _fontSize.y); charRect.translate(_topLeft.x + _position.x, _topLeft.y + _position.y + yOffset); if (_fillFlag) surfacePtr.fillRect(charRect, _colors.background); charRect.bottom = charRect.top + charHeight; // Display the character int bitCtr = 0; uint8 v = 0; for (int yp = charRect.top; yp < charRect.bottom; ++yp) { byte *destP = (byte *)surfacePtr.getBasePtr(charRect.left, yp); for (int xs = 0; xs < charRect.width(); ++xs, ++destP) { // Get the next color index to use if ((bitCtr % 8) == 0) v = *dataP++; int colIndex = 0; for (int subCtr = 0; subCtr < _bpp; ++subCtr, ++bitCtr) { colIndex = (colIndex << 1) | (v & 0x80 ? 1 : 0); v <<= 1; } switch (colIndex) { //case 0: *destP = _colors.background; break; case 1: *destP = _colors.foreground; break; case 2: *destP = _colors2.background; break; case 3: *destP = _colors2.foreground; break; } } } _position.x += charWidth; _gfxManager->unlockSurface(); return charWidth; }
void Animation::drawFontFrame(Graphics::Surface &surface, int32 frame, int16 xx, int16 yy, byte *colorMap) { debugC(4, kDebugAnim, "drawFontFrame(surface, %d, %d, %d, colorMap)", frame, xx, yy); if (frame < 0) frame = 0; if (frame >= _numFrames) frame = _numFrames - 1; if (_numFrames == 0) return; int16 dataFrame = frame; if (_frames[frame]._ref != -1) dataFrame = _frames[frame]._ref; int16 rectX = _frames[frame]._x2 - _frames[frame]._x1; int16 rectY = _frames[frame]._y2 - _frames[frame]._y1; if ((xx + _x1 + _frames[frame]._x1 < 0) || (yy + _y1 + _frames[frame]._y1 < 0)) return; if (rectX + xx + _x1 + _frames[frame]._x1 >= surface.getWidth()) rectX = surface.getWidth() - xx - _x1 - _frames[frame]._x1; if (rectX < 0) return; if (rectY + yy + _y1 + _frames[frame]._y1 >= surface.getHeight()) rectY = surface.getHeight() - yy - _y1 - _frames[frame]._y1; if (rectY < 0) return; int32 destPitch = surface.getPitch(); uint8 *c = _frames[dataFrame]._data; uint8 *curRow = (uint8 *)surface.getBasePtr(xx + _x1 + _frames[frame]._x1, yy + _frames[frame]._y1 + _y1); for (int16 y = 0; y < rectY; y++) { unsigned char *cur = curRow; for (int16 x = 0; x < rectX; x++) { if (*c && *c < 4) *cur = colorMap[*c]; c++; cur++; } curRow += destPitch; } }
void Frame::drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) { uint8 skipColor = _vm->getPaletteColorCount() - 1; //FIXME is it always white (last entry in pallette) ? for (int ii = 0; ii < sprite.h; ii++) { const byte *src = (const byte *)sprite.getBasePtr(0, ii); byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii); for (int j = 0; j < drawRect.width(); j++) { if (*src != skipColor) *dst = *src; src++; dst++; } } }
void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) { // The PSX videos have half resolution Graphics::Surface scaledFrame; scaledFrame.create(frame->w, frame->h * 2, frame->format); for (int y = 0; y < scaledFrame.h; y++) memcpy(scaledFrame.getBasePtr(0, y), frame->getBasePtr(0, y / 2), scaledFrame.w * scaledFrame.format.bytesPerPixel); uint16 x = (g_system->getWidth() - scaledFrame.w) / 2; uint16 y = (g_system->getHeight() - scaledFrame.h) / 2; _vm->_system->copyRectToScreen((byte *)scaledFrame.pixels, scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h); scaledFrame.free(); }
bool Movie::playVideo(bool isFirstIntroVideo) { debugC(1, kDebugMovie, "playVideo(isFirstIntroVideo: %d)", isFirstIntroVideo); while (!_vm->shouldQuit() && !_decoder->endOfVideo()) { if (_decoder->needsUpdate()) { const Graphics::Surface *frame = _decoder->decodeNextFrame(); if (frame) { if (_decoder->isLowRes()) { // handle manually 2x scaling here Graphics::Surface* surf = _vm->getSystem()->lockScreen(); for (int y = 0; y < frame->h / 2; y++) { memcpy(surf->getBasePtr(0, y * 2 + 0), frame->getBasePtr(0, y), frame->pitch); memcpy(surf->getBasePtr(0, y * 2 + 1), frame->getBasePtr(0, y), frame->pitch); } _vm->getSystem()->unlockScreen(); } else { _vm->getSystem()->copyRectToScreen((byte *)frame->pixels, frame->pitch, 0, 0, frame->w, frame->h); // WORKAROUND: There is an encoding glitch in the first intro video. This hides this using the adjacent pixels. if (isFirstIntroVideo) { int32 currentFrame = _decoder->getCurFrame(); if (currentFrame >= 956 && currentFrame <= 1038) { debugC(1, kDebugMovie, "Triggered workaround for glitch in first intro video..."); _vm->getSystem()->copyRectToScreen((const byte *)frame->getBasePtr(frame->w-188, 123), frame->pitch, frame->w-188, 124, 188, 1); _vm->getSystem()->copyRectToScreen((const byte *)frame->getBasePtr(frame->w-188, 126), frame->pitch, frame->w-188, 125, 188, 1); _vm->getSystem()->copyRectToScreen((const byte *)frame->getBasePtr(0, 125), frame->pitch, 0, 126, 64, 1); _vm->getSystem()->copyRectToScreen((const byte *)frame->getBasePtr(0, 128), frame->pitch, 0, 127, 64, 1); } } } } _decoder->setSystemPalette(); _vm->getSystem()->updateScreen(); } Common::Event event; while (_vm->getSystem()->getEventManager()->pollEvent(event)) if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE)) { _vm->dirtyAllScreen(); return false; } _vm->getSystem()->delayMillis(10); } _vm->dirtyAllScreen(); return !_vm->shouldQuit(); }
void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &pt, bool flipped, int overrideColor, int scaleVal) { if (scaleVal == 256) { transBlitFromUnscaled(src, pt, flipped, overrideColor); return; } int scaleX = SCALE_THRESHOLD * SCALE_THRESHOLD / scaleVal; int scaleY = scaleX; int scaleXCtr = 0, scaleYCtr = 0; for (int yCtr = 0, destY = pt.y; yCtr < src.h && destY < this->h(); ++yCtr) { // Handle skipping lines if Y scaling scaleYCtr += scaleY; while (scaleYCtr >= SCALE_THRESHOLD && destY < this->h()) { scaleYCtr -= SCALE_THRESHOLD; if (destY >= 0) { // Handle drawing the line const byte *pSrc = (const byte *)src.getBasePtr(flipped ? src.w - 1 : 0, yCtr); byte *pDest = (byte *)getBasePtr(pt.x, destY); scaleXCtr = 0; for (int xCtr = 0, destX = pt.x; xCtr < src.w && destX < this->w(); ++xCtr) { // Handle horizontal scaling scaleXCtr += scaleX; while (scaleXCtr >= SCALE_THRESHOLD && destX < this->w()) { scaleXCtr -= SCALE_THRESHOLD; // Only handle on-screen pixels if (destX >= 0 && *pSrc != TRANSPARENCY) *pDest = *pSrc; ++pDest; ++destX; } pSrc = pSrc + (flipped ? -1 : 1); } } ++destY; } } }
bool LBGraphics::imageIsTransparentAt(uint16 image, bool useOffsets, int x, int y) { MohawkSurface *mhkSurface = findImage(image); if (useOffsets) { x += mhkSurface->getOffsetX(); y += mhkSurface->getOffsetY(); } if (x < 0 || y < 0) return true; Graphics::Surface *surface = mhkSurface->getSurface(); if (x >= surface->w || y >= surface->h) return true; return *(byte *)surface->getBasePtr(x, y) == 0; }
void Scalpel3DOScreen::transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt, bool flipped, int overrideColor) { error("TODO: Refactor"); #if 0 if (!_vm->_isScreenDoubled) { ScalpelScreen::transBlitFromUnscaled(src, pt, flipped, overrideColor); return; } Common::Rect drawRect(0, 0, src.w, src.h); Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h); // Clip the display area to on-screen if (!clip(drawRect, destRect)) // It's completely off-screen return; if (flipped) drawRect = Common::Rect(src.w - drawRect.right, src.h - drawRect.bottom, src.w - drawRect.left, src.h - drawRect.top); Common::Point destPt(destRect.left, destRect.top); addDirtyRect(Common::Rect(destPt.x * 2, destPt.y * 2, (destPt.x + drawRect.width()) * 2, (destPt.y + drawRect.height()) * 2)); assert(src.format.bytesPerPixel == 2 && _surface.format.bytesPerPixel == 2); for (int yp = 0; yp < drawRect.height(); ++yp) { const uint16 *srcP = (const uint16 *)src.getBasePtr( flipped ? drawRect.right - 1 : drawRect.left, drawRect.top + yp); uint16 *destP = (uint16 *)getBasePtr(destPt.x * 2, (destPt.y + yp) * 2); for (int xp = 0; xp < drawRect.width(); ++xp, destP += 2) { // RGB 0, 0, 0 -> transparent on 3DO if (*srcP) { *destP = *srcP; *(destP + 1) = *srcP; *(destP + 640) = *srcP; *(destP + 640 + 1) = *srcP; } srcP = flipped ? srcP - 1 : srcP + 1; } } #endif }
Graphics::Surface *Hero::zoomSprite(Graphics::Surface *heroFrame) { Graphics::Surface *zoomedFrame = new Graphics::Surface(); zoomedFrame->create(_scaledFrameXSize, _scaledFrameYSize, Graphics::PixelFormat::createFormatCLUT8()); int sprZoomX; int sprZoomY = _vm->_scaleValue; uint xSource = 0; uint ySource = 0; uint xDest = 0; uint yDest = 0; for (int i = 0; i < _scaledFrameYSize; i++) { // linear_loop: while (1) { sprZoomY -= 100; if (sprZoomY >= 0 || _vm->_scaleValue == 10000) { // all_r_y sprZoomX = _vm->_scaleValue; break; // to loop_lin } else { sprZoomY += _vm->_scaleValue; xSource = 0; ySource++; } } // loop_lin: for (int j = 0; j < _scaledFrameXSize; j++) { sprZoomX -= 100; if (sprZoomX >= 0) { // its_all_r memcpy(zoomedFrame->getBasePtr(xDest, yDest), heroFrame->getBasePtr(xSource, ySource), 1); xDest++; } else { sprZoomX += _vm->_scaleValue; j--; } xSource++; } xDest = 0; yDest++; xSource = 0; ySource++; } return zoomedFrame; }
int Font::drawChar(ASurface *s, char c, Common::Point &pt) { Graphics::Surface &ch = _chars[c - ' ']; Graphics::Surface dest = s->getSubArea(Common::Rect(pt.x, pt.y, pt.x + ch.w, pt.y + ch.h)); // Loop through the lines of the character for (int y = 0; y < ch.h; ++y) { byte *pSrc = (byte *)ch.getBasePtr(0, y); byte *pDest = (byte *)dest.getBasePtr(0, y); // Loop through the horizontal pixels of the line for (int x = 0; x < ch.w; ++x, ++pSrc, ++pDest) { if (*pSrc != 0) *pDest = _fontColors[*pSrc]; } } return ch.w; }
bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h, const uint8 *palette) { assert(surf); Graphics::Surface screen; screen.create(w, h, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); for (uint y = 0; y < screen.h; ++y) { for (uint x = 0; x < screen.w; ++x) { byte r, g, b; r = palette[pixels[y * w + x] * 3]; g = palette[pixels[y * w + x] * 3 + 1]; b = palette[pixels[y * w + x] * 3 + 2]; *((uint16 *)screen.getBasePtr(x, y)) = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b); } } return createThumbnail(*surf, screen); }
bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAlpha) { _loaded = true; if (surface.format == _surface->format && surface.pitch == _surface->pitch && surface.h == _surface->h) { const byte *src = (const byte *)surface.getBasePtr(0, 0); byte *dst = (byte *)_surface->getBasePtr(0, 0); memcpy(dst, src, surface.pitch * surface.h); } else { _surface->free(); _surface->copyFrom(surface); } if (hasAlpha) { _alphaType = TransparentSurface::ALPHA_FULL; } else { _alphaType = TransparentSurface::ALPHA_OPAQUE; } BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer); renderer->invalidateTicketsFromSurface(this); return STATUS_OK; }
void DreamWebEngine::printUnderMonitor() { uint8 *dst = workspace() + kScreenwidth * 43 + 76; Graphics::Surface *s = _system->lockScreen(); if (!s) error("lockScreen failed"); for (uint y = 0; y < 104; ++y) { uint8 *src = (uint8 *)s->getBasePtr(76, 43 + 8 + y); for (uint x = 0; x < 170; ++x) { if (*src < 231) *dst++ = *src++; else { ++dst; ++src; } } dst += kScreenwidth - 170; } _system->unlockScreen(); }
/** * Copies the current screen contents to a new surface, using RGB565 format. * WARNING: surf->free() must be called by the user to avoid leaking. * * @param surf the surface to store the data in it */ static bool grabScreen565(Graphics::Surface *surf) { Graphics::Surface *screen = g_system->lockScreen(); if (!screen) return false; assert(screen->bytesPerPixel == 1 || screen->bytesPerPixel == 2); assert(screen->pixels != 0); Graphics::PixelFormat screenFormat = g_system->getScreenFormat(); surf->create(screen->w, screen->h, 2); byte *palette = 0; if (screenFormat.bytesPerPixel == 1) { palette = new byte[256 * 4]; assert(palette); g_system->grabPalette(palette, 0, 256); } for (uint y = 0; y < screen->h; ++y) { for (uint x = 0; x < screen->w; ++x) { byte r = 0, g = 0, b = 0; if (screenFormat.bytesPerPixel == 1) { r = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4]; g = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4 + 1]; b = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4 + 2]; } else if (screenFormat.bytesPerPixel == 2) { uint16 col = READ_UINT16(screen->getBasePtr(x, y)); screenFormat.colorToRGB(col, r, g, b); } ((uint16 *)surf->pixels)[y * surf->w + x] = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b); } } delete[] palette; g_system->unlockScreen(); return true; }
/** * Highlights the specified graphics element */ void GfxElement::highlight() { // Get a lock on the surface GfxManager &gfxManager = _globals->gfxManager(); Graphics::Surface surface = gfxManager.lockSurface(); // Scan through the contents of the element, switching any occurances of the foreground // color with the background color and vice versa Rect tempRect(_bounds); tempRect.collapse(_globals->_gfxEdgeAdjust - 1, _globals->_gfxEdgeAdjust - 1); for (int yp = tempRect.top; yp < tempRect.bottom; ++yp) { byte *lineP = (byte *)surface.getBasePtr(tempRect.left, yp); for (int xp = tempRect.left; xp < tempRect.right; ++xp, ++lineP) { if (*lineP == _colors.background) *lineP = _colors.foreground; else if (*lineP == _colors.foreground) *lineP = _colors.background; } } // Release the surface gfxManager.unlockSurface(); }
void Cursor::loadAvailableCursors() { assert(_textures.empty()); // Load available cursors for (uint i = 0; i < ARRAYSIZE(availableCursors); i++) { // Check if a cursor sharing the same texture has already been loaded if (_textures.contains(availableCursors[i].nodeID)) continue; // Load the cursor bitmap const DirectorySubEntry *cursorDesc = _vm->getFileDescription("GLOB", availableCursors[i].nodeID, 0, DirectorySubEntry::kRawData); if (!cursorDesc) error("Cursor %d does not exist", availableCursors[i].nodeID); Common::MemoryReadStream *bmpStream = cursorDesc->getData(); Image::BitmapDecoder bitmapDecoder; if (!bitmapDecoder.loadStream(*bmpStream)) error("Could not decode Myst III bitmap"); const Graphics::Surface *surfaceBGRA = bitmapDecoder.getSurface(); Graphics::Surface *surfaceRGBA = surfaceBGRA->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)); delete bmpStream; // Apply the colorkey for transparency for (uint u = 0; u < surfaceRGBA->w; u++) { for (uint v = 0; v < surfaceRGBA->h; v++) { uint32 *pixel = (uint32*)(surfaceRGBA->getBasePtr(u, v)); if (*pixel == 0xFF00FF00) *pixel = 0x0000FF00; } } // Create and store the texture _textures.setVal(availableCursors[i].nodeID, _vm->_gfx->createTexture(surfaceRGBA)); surfaceRGBA->free(); delete surfaceRGBA; } }
int BitmapFont::getSourceCharacterWidth(uint charIndex, const Graphics::Surface &src, const Common::Rect &charBounds) { if (charIndex == 0) // The space character is treated as half the width of bounding area return charBounds.width() / 2; // Scan through the rows to find the right most pixel, getting the width from that int maxWidth = 0, rowX; for (int y = charBounds.top; y < charBounds.bottom; ++y) { rowX = 0; const byte *srcP = (const byte *)src.getBasePtr(charBounds.left, y); for (int x = 0; x < charBounds.width(); ++x, ++srcP) { if (!*srcP) rowX = x; } maxWidth = MAX(maxWidth, MIN(rowX + 2, (int)charBounds.width())); } return maxWidth; }
void SceneExt::refreshBackground(int xAmount, int yAmount) { switch (_activeScreenNumber) { case 700: case 1020: case 1100: case 1700: case 2600: case 2950: case 3100: case 3101: case 3275: case 3600: // Use traditional style sectioned screen loading Scene::refreshBackground(xAmount, yAmount); return; default: // Break out to new style screen loading break; } /* New style background loading */ // Get the screen data byte *dataP = g_resourceManager->getResource(RT18, _activeScreenNumber, 0); int screenSize = g_vm->_memoryManager.getSize(dataP); // Lock the background for update Graphics::Surface s = _backSurface.lockSurface(); assert(screenSize == (s.w * s.h)); // Copy the data byte *destP = (byte *)s.getBasePtr(0, 0); Common::copy(dataP, dataP + (s.w * s.h), destP); _backSurface.unlockSurface(); // Free the resource data DEALLOCATE(dataP); }
/** * Loads a quarter of a screen from a resource */ void GfxSurface::loadScreenSection(Graphics::Surface &dest, int xHalf, int yHalf, int xSection, int ySection) { int screenNum = _globals->_sceneManager._scene->_activeScreenNumber; Rect updateRect(0, 0, 160, 100); updateRect.translate(xHalf * 160, yHalf * 100); int xHalfCount = (_globals->_sceneManager._scene->_backgroundBounds.right + 159) / 160; int yHalfCount = (_globals->_sceneManager._scene->_backgroundBounds.bottom + 99) / 100; if (xSection < xHalfCount && ySection < yHalfCount) { int rlbNum = xSection * yHalfCount + ySection; byte *data = _resourceManager->getResource(RES_BITMAP, screenNum, rlbNum); for (int y = 0; y < updateRect.height(); ++y) { byte *pSrc = data + y * 160; byte *pDest = (byte *)dest.getBasePtr(updateRect.left, updateRect.top + y); for (int x = 0; x < updateRect.width(); ++x, ++pSrc, ++pDest) { *pDest = *pSrc; } } DEALLOCATE(data); } }
/** * Locks the surface for access, and returns a raw ScummVM surface to manipulate it */ Graphics::Surface GfxSurface::lockSurface() { ++_lockSurfaceCtr; Graphics::Surface *src; if (_screenSurface) { if (_lockSurfaceCtr == 1) _screenSurfaceP = g_system->lockScreen(); src = _screenSurfaceP; } else src = _customSurface; assert(src); // Setup the returned surface either as one pointing to the same pixels as the source, or // as a subset of the source one based on the currently set bounds Graphics::Surface result; result.w = _bounds.width(); result.h = _bounds.height(); result.pitch = src->pitch; result.format = src->format; result.pixels = src->getBasePtr(_bounds.left, _bounds.top); return result; }
void Font::drawCharacter(const char character, Graphics::Surface &surface, int x, int y) { uint8 characterIndex = (uint8)character + 1; if (x < 0 || x >= _screenWidth || y < 0 || y >= _screenHeight || !_data || characterIndex >= _characterCount) { return; } uint16 *dstPtr = (uint16*)surface.getBasePtr(x + _characters[characterIndex]._x, y + _characters[characterIndex]._y); uint16 *srcPtr = &_data[_characters[characterIndex]._dataOffset]; int width = _characters[characterIndex]._width; int height = _characters[characterIndex]._height; if (_intersperse && y & 1) { dstPtr += surface.pitch / 2; } int endY = height + y - 1; int currentY = y; while (currentY <= endY && currentY < _screenHeight) { int currentX = x; int endX = width + x - 1; while (currentX <= endX && currentX < _screenWidth) { if ((*srcPtr & 0x8000) == 0) { *dstPtr = *srcPtr; } dstPtr++; srcPtr++; currentX++; } dstPtr += surface.pitch / 2 - width; if (_intersperse) { srcPtr += width; dstPtr += surface.pitch / 2; currentY++; } currentY++; } }
void RMWindow::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) { if (GLOBALS._bCfgAnni30) { if (!RMGfxTargetBuffer::_precalcTable) { RMGfxTargetBuffer::createBWPrecalcTable(); g_vm->getEngine()->getPointer().updateCursor(); } Graphics::Surface *screen = g_system->lockScreen(); const uint16 *src = (const uint16 *)buf; for (int i = 0; i < h; i++) { uint16 *dst = (uint16 *)screen->getBasePtr(x, y + i); for (int j = 0; j < w; j++) { dst[j] = RMGfxTargetBuffer::_precalcTable[src[j] & 0x7FFF]; } src += (pitch / 2); } g_system->unlockScreen(); } else { if (RMGfxTargetBuffer::_precalcTable) { RMGfxTargetBuffer::freeBWPrecalcTable(); g_vm->getEngine()->getPointer().updateCursor(); } g_system->copyRectToScreen(buf, pitch, x, y, w, h); } }
void AVISurface::copyMovieFrame(const Graphics::Surface &src, Graphics::ManagedSurface &dest) { // WORKAROUND: Handle rare cases where frame sizes don't match the video size Common::Rect copyRect(0, 0, MIN(src.w, dest.w), MIN(src.h, dest.h)); if (src.format.bytesPerPixel == 1) { // Paletted 8-bit, so convert to 16-bit and copy over const byte *palette = _decoder->getPalette(); if (palette) { Graphics::Surface *s = src.convertTo(dest.format, palette); dest.blitFrom(*s, copyRect, Common::Point(0, 0)); s->free(); delete s; } } else if (src.format.bytesPerPixel == 2) { // Source is already 16-bit, with no alpha, so do a straight copy dest.blitFrom(src, copyRect, Common::Point(0, 0)); } else { // Source is 32-bit which may have transparent pixels. Copy over each // pixel, replacing transparent pixels with the special transparency color byte a, r, g, b; assert(src.format.bytesPerPixel == 4 && dest.format.bytesPerPixel == 2); uint16 transPixel = _videoSurface->getTransparencyColor(); for (uint y = 0; y < MIN(src.h, dest.h); ++y) { const uint32 *pSrc = (const uint32 *)src.getBasePtr(0, y); uint16 *pDest = (uint16 *)dest.getBasePtr(0, y); for (uint x = 0; x < MIN(src.w, dest.w); ++x, ++pSrc, ++pDest) { src.format.colorToARGB(*pSrc, a, r, g, b); assert(a == 0 || a == 0xff); *pDest = (a == 0) ? transPixel : dest.format.RGBToColor(r, g, b); } } } }
void ScreenEffects::copyFxRect(Graphics::Surface *surface, int16 x1, int16 y1, int16 x2, int16 y2) { // TODO: Clean up byte *src, *dst; x1 = CLIP<int16>(x1, 0, 320); y1 = CLIP<int16>(y1, 0, 200); x2 = CLIP<int16>(x2, 0, 320); y2 = CLIP<int16>(y2, 0, 200); x2 -= x1; y2 -= y1; vfxX1 = x1 & 0x0E; x1 += 16; x1 = x1 & 0xFFF0; x2 += vfxX1; x2 -= 15; if (x2 < 0) x2 = 0; vfxWidth = x2 & 0x0E; x2 = x2 & 0xFFF0; vfxY1 = y1 & 7; byte *source = (byte*)surface->getBasePtr(x1, y1); Graphics::Surface *vgaScreen = _screen->lockScreen(); byte *dest = (byte*)vgaScreen->getBasePtr(x1, y1); int16 addX = x2 / 16; while (y2-- > 0) { int16 addVal = vfxOffsTablePtr[vfxY1] * 2; int16 w = 0; vfxY1 = (vfxY1 + 1) & 7; src = source + addVal; dst = dest + addVal; if (addVal < vfxX1) { if (addVal < vfxWidth) w = 1; else w = 0; } else { src -= 16; dst -= 16; if (addVal < vfxWidth) w = 2; else w = 1; } w += addX; while (w-- > 0) { *dst++ = *src++; *dst++ = *src++; src += 14; dst += 14; } source += 320; dest += 320; } vfxHeight = (vfxHeight + 1) & 7; vfxOffsTablePtr = &vfxOffsTable[vfxOffsIndexTable[vfxHeight] * 8]; _screen->unlockScreen(); }
bool VideoManager::updateMovies() { bool updateScreen = false; for (uint32 i = 0; i < _videoStreams.size() && !_vm->shouldQuit(); i++) { // Skip deleted videos if (!_videoStreams[i].video) continue; // Remove any videos that are over if (_videoStreams[i].endOfVideo()) { if (_videoStreams[i].loop) { _videoStreams[i]->seekToTime(_videoStreams[i].start); } else { // Check the video time one last time before deleting it _vm->doVideoTimer(i, true); delete _videoStreams[i].video; _videoStreams[i].clear(); continue; } } // Nothing more to do if we're paused if (_videoStreams[i]->isPaused()) continue; // Check if we need to draw a frame if (_videoStreams[i]->needsUpdate()) { const Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame(); Graphics::Surface *convertedFrame = 0; if (frame && _videoStreams[i].enabled) { Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat(); // Create (or resize) the off-screen surface if (frame->w > _videoStreams[i].surface.w || frame->h > _videoStreams[i].surface.h) { _videoStreams[i].surface.create(frame->w, frame->h, pixelFormat); } // Convert from 8bpp to the current screen format if necessary if (frame->format.bytesPerPixel == 1) { if (pixelFormat.bytesPerPixel == 1) { if (_videoStreams[i]->hasDirtyPalette()) _videoStreams[i]->setSystemPalette(); } else { convertedFrame = new Graphics::Surface(); const byte *palette = _videoStreams[i]->getPalette(); assert(palette); convertedFrame->create(frame->w, frame->h, pixelFormat); for (uint16 j = 0; j < frame->h; j++) { for (uint16 k = 0; k < frame->w; k++) { byte palIndex = *((const byte *)frame->getBasePtr(k, j)); byte r = palette[palIndex * 3]; byte g = palette[palIndex * 3 + 1]; byte b = palette[palIndex * 3 + 2]; if (pixelFormat.bytesPerPixel == 2) *((uint16 *)convertedFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b); else *((uint32 *)convertedFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b); } } frame = convertedFrame; } } // Copy frame to the off-screen surface for (int y = 0; y < frame->h; ++y) { memcpy(_videoStreams[i].surface.getBasePtr(0, y), frame->getBasePtr(0, y), frame->w * pixelFormat.bytesPerPixel); } // Delete 8bpp conversion surface if (convertedFrame) { convertedFrame->free(); delete convertedFrame; } } } // Don't draw anything until we have a valid surface if (_videoStreams[i].surface.w == 0 || _videoStreams[i].surface.h == 0) continue; // Clip the width/height to make sure we stay on the screen (Myst does this a few times) uint16 width = MIN<int32>(_videoStreams[i]->getWidth(), _vm->_system->getWidth() - _videoStreams[i].x); uint16 height = MIN<int32>(_videoStreams[i]->getHeight(), _vm->_system->getHeight() - _videoStreams[i].y); // Render the off-screen surface _vm->_system->copyRectToScreen((byte *)_videoStreams[i].surface.pixels, _videoStreams[i].surface.pitch, _videoStreams[i].x, _videoStreams[i].y, width, height); updateScreen = true; // Check the video time _vm->doVideoTimer(i, false); } // Return true if we need to update the screen return updateScreen; }