Common::Rect Testsuite::writeOnScreen(const Common::String &textToDisplay, const Common::Point &pt, bool flag) { const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont)); uint fillColor = kColorBlack; uint textColor = kColorWhite; Graphics::Surface *screen = g_system->lockScreen(); int height = font.getFontHeight(); int width = screen->w; Common::Rect rect(pt.x, pt.y, pt.x + width, pt.y + height); if (flag) { Graphics::PixelFormat pf = g_system->getScreenFormat(); fillColor = pf.RGBToColor(0, 0, 0); textColor = pf.RGBToColor(255, 255, 255); } screen->fillRect(rect, fillColor); font.drawString(screen, textToDisplay, rect.left, rect.top, screen->w, textColor, Graphics::kTextAlignCenter); g_system->unlockScreen(); g_system->updateScreen(); return rect; }
SaveStateDescriptor TonyMetaEngine::querySaveMetaInfos(const char *target, int slot) const { Common::String saveName; byte difficulty; byte thumbData[160 * 120 * 2]; if (Tony::RMOptionScreen::loadThumbnailFromSaveState(slot, thumbData, saveName, difficulty)) { // Convert the 565 thumbnail data to the needed overlay format Common::MemoryReadStream thumbStream(thumbData, 160 * 120 * 2); Graphics::PixelFormat destFormat = g_system->getOverlayFormat(); Graphics::Surface *to = new Graphics::Surface(); to->create(160, 120, destFormat); OverlayColor *pixels = (OverlayColor *)to->pixels; for (int y = 0; y < to->h; ++y) { for (int x = 0; x < to->w; ++x) { uint8 r, g, b; Graphics::colorToRGB<Graphics::ColorMasks<555> >(thumbStream.readUint16LE(), r, g, b); // converting to current OSystem Color *pixels++ = destFormat.RGBToColor(r, g, b); } } // Create the return descriptor SaveStateDescriptor desc(slot, saveName); desc.setDeletableFlag(true); desc.setWriteProtectedFlag(false); desc.setThumbnail(to); return desc; } return SaveStateDescriptor(); }
Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) { ThumbnailHeader header; if (!loadHeader(in, header, true)) return 0; if (header.bpp != 2) { warning("trying to load thumbnail with unsupported bit depth %d", header.bpp); return 0; } Graphics::PixelFormat format = g_system->getOverlayFormat(); Graphics::Surface *const to = new Graphics::Surface(); to->create(header.width, header.height, format); OverlayColor *pixels = (OverlayColor *)to->pixels; for (int y = 0; y < to->h; ++y) { for (int x = 0; x < to->w; ++x) { uint8 r, g, b; colorToRGB<ColorMasks<565> >(in.readUint16BE(), r, g, b); // converting to current OSystem Color *pixels++ = format.RGBToColor(r, g, b); } } return to; }
bool SavePartSprite::readSprite(const Surface &sprite) { // The sprite's dimensions have to fit if (((uint32)sprite.getWidth()) != _width) return false; if (((uint32)sprite.getHeight()) != _height) return false; if (_trueColor) { if (sprite.getBPP() <= 1) return false; Graphics::PixelFormat pixelFormat = g_system->getScreenFormat(); byte *data = _dataSprite; ConstPixel pixel = sprite.get(); for (uint32 i = 0; i < (_width * _height); i++, ++pixel, data += 3) pixelFormat.colorToRGB(pixel.get(), data[0], data[1], data[2]); } else { if (sprite.getBPP() != 1) return false; memcpy(_dataSprite, sprite.getData(), _width * _height); } return true; }
bool SavePartSprite::writeSprite(Surface &sprite) const { // The sprite's dimensions have to fit if (((uint32)sprite.getWidth()) != _width) return false; if (((uint32)sprite.getHeight()) != _height) return false; if (_trueColor) { if (sprite.getBPP() <= 1) return false; Graphics::PixelFormat pixelFormat = g_system->getScreenFormat(); const byte *data = _dataSprite; Pixel pixel = sprite.get(); for (uint32 i = 0; i < (_width * _height); i++, ++pixel, data += 3) pixel.set(pixelFormat.RGBToColor(data[0], data[1], data[2])); } else { if (sprite.getBPP() != 1) return false; memcpy(sprite.getData(), _dataSprite, _spriteSize); } return true; }
static void drawMessage(int offset, const Common::String &text) { const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kGUIFont)); Graphics::Surface *screen = g_system->lockScreen(); assert(screen); assert(screen->pixels); Graphics::PixelFormat screenFormat = g_system->getScreenFormat(); uint16 h = font.getFontHeight(); uint16 y = g_system->getHeight() / 2 - h / 2 + offset * (h + 1); uint32 col; if (screenFormat.bytesPerPixel > 1) col = screenFormat.RGBToColor(0, 0, 0); else col = 0; Common::Rect r(0, y, screen->w, y + h); screen->fillRect(r, col); if (screenFormat.bytesPerPixel > 1) col = screenFormat.RGBToColor(0, 171, 0); else col = 1; font.drawString(screen, text, 0, y, screen->w, col, Graphics::kTextAlignCenter); g_system->unlockScreen(); g_system->updateScreen(); }
void BaseAnimationState::buildLookup() { // Do we already have lookup tables for this bit format? Graphics::PixelFormat format = _sys->getOverlayFormat(); if (format == _overlayFormat && _colorTab && _rgbToPix) return; free(_colorTab); free(_rgbToPix); _colorTab = (int16 *)malloc(4 * 256 * sizeof(int16)); int16 *Cr_r_tab = &_colorTab[0 * 256]; int16 *Cr_g_tab = &_colorTab[1 * 256]; int16 *Cb_g_tab = &_colorTab[2 * 256]; int16 *Cb_b_tab = &_colorTab[3 * 256]; _rgbToPix = (OverlayColor *)malloc(3 * 768 * sizeof(OverlayColor)); OverlayColor *r_2_pix_alloc = &_rgbToPix[0 * 768]; OverlayColor *g_2_pix_alloc = &_rgbToPix[1 * 768]; OverlayColor *b_2_pix_alloc = &_rgbToPix[2 * 768]; int16 CR, CB; int i; // Generate the tables for the display surface for (i = 0; i < 256; i++) { // Gamma correction (luminescence table) and chroma correction // would be done here. See the Berkeley mpeg_play sources. CR = CB = (i - 128); Cr_r_tab[i] = (int16) ( (0.419 / 0.299) * CR) + 0 * 768 + 256; Cr_g_tab[i] = (int16) (-(0.299 / 0.419) * CR) + 1 * 768 + 256; Cb_g_tab[i] = (int16) (-(0.114 / 0.331) * CB); Cb_b_tab[i] = (int16) ( (0.587 / 0.331) * CB) + 2 * 768 + 256; } // Set up entries 0-255 in rgb-to-pixel value tables. for (i = 0; i < 256; i++) { r_2_pix_alloc[i + 256] = format.RGBToColor(i, 0, 0); g_2_pix_alloc[i + 256] = format.RGBToColor(0, i, 0); b_2_pix_alloc[i + 256] = format.RGBToColor(0, 0, i); } // Spread out the values we have to the rest of the array so that we do // not need to check for overflow. for (i = 0; i < 256; i++) { r_2_pix_alloc[i] = r_2_pix_alloc[256]; r_2_pix_alloc[i + 512] = r_2_pix_alloc[511]; g_2_pix_alloc[i] = g_2_pix_alloc[256]; g_2_pix_alloc[i + 512] = g_2_pix_alloc[511]; b_2_pix_alloc[i] = b_2_pix_alloc[256]; b_2_pix_alloc[i + 512] = b_2_pix_alloc[511]; } _overlayFormat = format; }
int MidiDriver_MT32::open() { MT32Emu::SynthProperties prop; if (_isOpen) return MERR_ALREADY_OPEN; MidiDriver_Emulated::open(); memset(&prop, 0, sizeof(prop)); prop.sampleRate = getRate(); prop.useReverb = true; prop.useDefaultReverb = false; prop.reverbType = 0; prop.reverbTime = 5; prop.reverbLevel = 3; prop.userData = this; prop.printDebug = MT32_PrintDebug; prop.report = MT32_Report; prop.openFile = MT32_OpenFile; _synth = new MT32Emu::Synth(); Graphics::PixelFormat screenFormat = g_system->getScreenFormat(); if (screenFormat.bytesPerPixel == 1) { const byte dummy_palette[] = { 0, 0, 0, // background 0, 171, 0, // border, font 171, 0, 0 // fill }; g_system->getPaletteManager()->setPalette(dummy_palette, 0, 3); } _initializing = true; drawMessage(-1, _s("Initializing MT-32 Emulator")); if (!_synth->open(prop)) return MERR_DEVICE_NOT_AVAILABLE; double gain = (double)ConfMan.getInt("midi_gain") / 100.0; _synth->setOutputGain(1.0f * gain); _synth->setReverbOutputGain(0.68f * gain); _initializing = false; if (screenFormat.bytesPerPixel > 1) g_system->fillScreen(screenFormat.RGBToColor(0, 0, 0)); else g_system->fillScreen(0); g_system->updateScreen(); _mixer->playStream(Audio::Mixer::kSFXSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); return 0; }
void Surface::shadeRect(uint16 left, uint16 top, uint16 right, uint16 bottom, uint32 color, uint8 strength) { if (_bpp == 1) { // We can't properly shade in paletted mode, fill the rect instead fillRect(left, top, right, bottom, color); return; } // Just in case those are swapped if (left > right) SWAP(left, right); if (top > bottom) SWAP(top, bottom); if ((left >= _width) || (top >= _height)) // Nothing to do return; // Area to actually shade uint16 width = CLIP<int32>(right - left + 1, 0, _width - left); uint16 height = CLIP<int32>(bottom - top + 1, 0, _height - top); if ((width == 0) || (height == 0)) // Nothing to do return; Graphics::PixelFormat pixelFormat = g_system->getScreenFormat(); uint8 cR, cG, cB; pixelFormat.colorToRGB(color, cR, cG, cB); int shadeR = cR * (16 - strength); int shadeG = cG * (16 - strength); int shadeB = cB * (16 - strength); Pixel p = get(left, top); while (height-- > 0) { for (uint16 i = 0; i < width; i++, ++p) { uint8 r, g, b; pixelFormat.colorToRGB(p.get(), r, g, b); r = CLIP<int>((shadeR + strength * r) >> 4, 0, 255); g = CLIP<int>((shadeG + strength * g) >> 4, 0, 255); b = CLIP<int>((shadeB + strength * b) >> 4, 0, 255); p.set(pixelFormat.RGBToColor(r, g, b)); } p += _width - width; } }
void VisualExplodingImage::ExplosionUnit::setColor(uint32 color, const Graphics::PixelFormat &format) { _mainColor = color; byte a, r, g, b; format.colorToARGB(color, a, r, g, b); r >>= 1; g >>= 1; b >>= 1; _darkColor = format.ARGBToColor(a, r, g, b); }
bool VirtualKeyboardParser::parserCallback_layout(ParserNode *node) { assert(!_mode->resolution.empty()); String res = node->values["resolution"]; if (res != _mode->resolution) { node->ignore = true; return true; } _mode->bitmapName = node->values["bitmap"]; SeekableReadStream *file = _keyboard->_fileArchive->createReadStreamForMember(_mode->bitmapName); if (!file) return parserError("Bitmap '" + _mode->bitmapName + "' not found"); const Graphics::PixelFormat format = g_system->getOverlayFormat(); { Graphics::BitmapDecoder bmp; if (!bmp.loadStream(*file)) return parserError("Error loading bitmap '" + _mode->bitmapName + "'"); _mode->image = bmp.getSurface()->convertTo(format); } delete file; int r, g, b; if (node->values.contains("transparent_color")) { if (!parseIntegerKey(node->values["transparent_color"], 3, &r, &g, &b)) return parserError("Could not parse color value"); } else { // default to purple r = 255; g = 0; b = 255; } _mode->transparentColor = format.RGBToColor(r, g, b); if (node->values.contains("display_font_color")) { if (!parseIntegerKey(node->values["display_font_color"], 3, &r, &g, &b)) return parserError("Could not parse color value"); } else { r = g = b = 0; // default to black } _mode->displayFontColor = format.RGBToColor(r, g, b); _layoutParsed = true; return true; }
int MidiDriver_MT32::open() { if (_isOpen) return MERR_ALREADY_OPEN; MidiDriver_Emulated::open(); _reportHandler = new MT32Emu::ReportHandlerScummVM(); _synth = new MT32Emu::Synth(_reportHandler); Graphics::PixelFormat screenFormat = g_system->getScreenFormat(); if (screenFormat.bytesPerPixel == 1) { const byte dummy_palette[] = { 0, 0, 0, // background 0, 171, 0, // border, font 171, 0, 0 // fill }; g_system->getPaletteManager()->setPalette(dummy_palette, 0, 3); } _initializing = true; debug(4, _s("Initializing MT-32 Emulator")); _controlFile = new Common::File(); if (!_controlFile->open("MT32_CONTROL.ROM") && !_controlFile->open("CM32L_CONTROL.ROM")) error("Error opening MT32_CONTROL.ROM / CM32L_CONTROL.ROM"); _pcmFile = new Common::File(); if (!_pcmFile->open("MT32_PCM.ROM") && !_pcmFile->open("CM32L_PCM.ROM")) error("Error opening MT32_PCM.ROM / CM32L_PCM.ROM"); _controlROM = MT32Emu::ROMImage::makeROMImage(_controlFile); _pcmROM = MT32Emu::ROMImage::makeROMImage(_pcmFile); if (!_synth->open(*_controlROM, *_pcmROM)) return MERR_DEVICE_NOT_AVAILABLE; double gain = (double)ConfMan.getInt("midi_gain") / 100.0; _synth->setOutputGain(1.0f * gain); _synth->setReverbOutputGain(0.68f * gain); _initializing = false; if (screenFormat.bytesPerPixel > 1) g_system->fillScreen(screenFormat.RGBToColor(0, 0, 0)); else g_system->fillScreen(0); g_system->updateScreen(); _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); return 0; }
SaveDataWidget::SaveDataWidget(int slot, Gfx::Driver *gfx, SaveLoadMenuScreen *screen) : StaticLocationWidget(nullptr, nullptr, nullptr), _slot(slot), _screen(screen), _thumbWidth(StarkUserInterface->kThumbnailWidth), _thumbHeight(StarkUserInterface->kThumbnailHeight), _texture(gfx->createTexture()), _outline(gfx->createTexture()), _surfaceRenderer(gfx->createSurfaceRenderer()), _textDesc(gfx), _textTime(gfx), _isMouseHovered(false), _hasSave(false), _name() { // Load from the save data loadSaveDataElements(); _textDesc.setColor(_textColor); _textDesc.setFont(FontProvider::kCustomFont, 3); _textTime.setColor(_textColor); _textTime.setFont(FontProvider::kCustomFont, 3); Graphics::PixelFormat pixelFormat = Gfx::Driver::getRGBAPixelFormat(); uint32 outlineColor = pixelFormat.ARGBToColor( _outlineColor.a, _outlineColor.r, _outlineColor.g, _outlineColor.b ); // Create the outline texture Graphics::Surface lineSurface; lineSurface.create(_thumbWidth, _thumbHeight, pixelFormat); lineSurface.drawThickLine(0, 0, _thumbWidth - 1, 0, 2, 2, outlineColor); lineSurface.drawThickLine(0, 0, 0, _thumbHeight - 1, 2, 2, outlineColor); lineSurface.drawThickLine(_thumbWidth - 2, 0, _thumbWidth - 2, _thumbHeight - 2, 2, 2, outlineColor); lineSurface.drawThickLine(0, _thumbHeight - 2, _thumbWidth - 2, _thumbHeight - 2, 2, 2, outlineColor); _outline->update(&lineSurface); lineSurface.free(); // Set the position _thumbPos.x = 41 + (_slot % SaveLoadMenuScreen::_slotPerRow) * (_thumbWidth + 39); _thumbPos.y = 61 + (_slot % SaveLoadMenuScreen::_slotPerPage / SaveLoadMenuScreen::_slotPerColumn) * (_thumbHeight + 38); _textDescPos.x = _thumbPos.x; _textDescPos.y = _thumbPos.y + _thumbHeight + 2; _textTimePos.x = _thumbPos.x; _textTimePos.y = _textDescPos.y + 12; }
YUVToRGBLookup::YUVToRGBLookup(Graphics::PixelFormat format) { _colorTab = new int16[4 * 256]; // 2048 bytes int16 *Cr_r_tab = &_colorTab[0 * 256]; int16 *Cr_g_tab = &_colorTab[1 * 256]; int16 *Cb_g_tab = &_colorTab[2 * 256]; int16 *Cb_b_tab = &_colorTab[3 * 256]; _rgbToPix = new uint32[3 * 768]; // 9216 bytes uint32 *r_2_pix_alloc = &_rgbToPix[0 * 768]; uint32 *g_2_pix_alloc = &_rgbToPix[1 * 768]; uint32 *b_2_pix_alloc = &_rgbToPix[2 * 768]; int16 CR, CB; int i; // Generate the tables for the display surface for (i = 0; i < 256; i++) { // Gamma correction (luminescence table) and chroma correction // would be done here. See the Berkeley mpeg_play sources. CR = CB = (i - 128); Cr_r_tab[i] = (int16) ( (0.419 / 0.299) * CR) + 0 * 768 + 256; Cr_g_tab[i] = (int16) (-(0.299 / 0.419) * CR) + 1 * 768 + 256; Cb_g_tab[i] = (int16) (-(0.114 / 0.331) * CB); Cb_b_tab[i] = (int16) ( (0.587 / 0.331) * CB) + 2 * 768 + 256; } // Set up entries 0-255 in rgb-to-pixel value tables. for (i = 0; i < 256; i++) { r_2_pix_alloc[i + 256] = format.RGBToColor(i, 0, 0); g_2_pix_alloc[i + 256] = format.RGBToColor(0, i, 0); b_2_pix_alloc[i + 256] = format.RGBToColor(0, 0, i); } // Spread out the values we have to the rest of the array so that we do // not need to check for overflow. for (i = 0; i < 256; i++) { r_2_pix_alloc[i] = r_2_pix_alloc[256]; r_2_pix_alloc[i + 512] = r_2_pix_alloc[511]; g_2_pix_alloc[i] = g_2_pix_alloc[256]; g_2_pix_alloc[i + 512] = g_2_pix_alloc[511]; b_2_pix_alloc[i] = b_2_pix_alloc[256]; b_2_pix_alloc[i + 512] = b_2_pix_alloc[511]; } }
void MystCursorManager::setCursor(uint16 id) { // Zero means empty cursor if (id == 0) { static const byte emptyCursor[4] = { 0, 0, 0, 0 }; CursorMan.replaceCursor(&emptyCursor, 2, 2, 0, 0, 0); return; } // Both Myst and Myst ME use the "MystBitmap" format for cursor images. MohawkSurface *mhkSurface = _bmpDecoder->decodeImage(_vm->getResource(ID_WDIB, id)); Graphics::Surface *surface = mhkSurface->getSurface(); Common::SeekableReadStream *clrcStream = _vm->getResource(ID_CLRC, id); uint16 hotspotX = clrcStream->readUint16LE(); uint16 hotspotY = clrcStream->readUint16LE(); delete clrcStream; // Myst ME stores some cursors as 24bpp images instead of 8bpp if (surface->format.bytesPerPixel == 1) { CursorMan.replaceCursor(surface->getPixels(), surface->w, surface->h, hotspotX, hotspotY, 0); CursorMan.replaceCursorPalette(mhkSurface->getPalette(), 0, 256); } else { Graphics::PixelFormat pixelFormat = g_system->getScreenFormat(); CursorMan.replaceCursor(surface->getPixels(), surface->w, surface->h, hotspotX, hotspotY, pixelFormat.RGBToColor(255, 255, 255), false, &pixelFormat); } _vm->_needsUpdate = true; delete mhkSurface; }
void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) { if (w == -1) w = _w; if (h == -1) h = _h; _gfx.free(); _gfx.create(w, h, sizeof(OverlayColor)); OverlayColor *dst = (OverlayColor *)_gfx.pixels; Graphics::PixelFormat overlayFormat = g_system->getOverlayFormat(); OverlayColor fillCol = overlayFormat.RGBToColor(r, g, b); while (h--) { for (int i = 0; i < w; ++i) { *dst++ = fillCol; } } }
/** * 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->format.bytesPerPixel == 1 || screen->format.bytesPerPixel == 2); assert(screen->getPixels() != 0); Graphics::PixelFormat screenFormat = g_system->getScreenFormat(); surf->create(screen->w, screen->h, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); byte *palette = 0; if (screenFormat.bytesPerPixel == 1) { palette = new byte[256 * 3]; assert(palette); g_system->getPaletteManager()->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) { uint8 pixel = *(uint8 *)screen->getBasePtr(x, y); r = palette[pixel * 3 + 0]; g = palette[pixel * 3 + 1]; b = palette[pixel * 3 + 2]; } else if (screenFormat.bytesPerPixel == 2) { uint16 col = READ_UINT16(screen->getBasePtr(x, y)); screenFormat.colorToRGB(col, r, g, b); } *((uint16 *)surf->getBasePtr(x, y)) = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b); } } delete[] palette; g_system->unlockScreen(); return true; }
bool ImgLoader::decodeThumbnailImage(const byte *pFileData, uint fileSize, byte *&pUncompressedData, int &width, int &height, int &pitch) { const byte *src = pFileData + 4; // skip header width = READ_LE_UINT16(src); src += 2; height = READ_LE_UINT16(src); src += 2; src++; // version, ignored for now pitch = width * 4; uint32 totalSize = pitch * height; pUncompressedData = new byte[totalSize]; uint32 *dst = (uint32 *)pUncompressedData; // treat as uint32, for pixelformat output const Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); byte r, g, b; for (uint32 i = 0; i < totalSize / 4; i++) { r = *src++; g = *src++; b = *src++; *dst++ = format.RGBToColor(r, g, b); } return true; }
static void drawProgress(float progress) { const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kGUIFont)); Graphics::Surface *screen = g_system->lockScreen(); assert(screen); assert(screen->pixels); Graphics::PixelFormat screenFormat = g_system->getScreenFormat(); int16 w = g_system->getWidth() / 7 * 5; int16 h = font.getFontHeight(); int16 x = g_system->getWidth() / 7; int16 y = g_system->getHeight() / 2 - h / 2; Common::Rect r(x, y, x + w, y + h); uint32 col; if (screenFormat.bytesPerPixel > 1) col = screenFormat.RGBToColor(0, 171, 0); else col = 1; screen->frameRect(r, col); r.grow(-1); r.setWidth(uint16(progress * w)); if (screenFormat.bytesPerPixel > 1) col = screenFormat.RGBToColor(171, 0, 0); else col = 2; screen->fillRect(r, col); g_system->unlockScreen(); g_system->updateScreen(); }
bool createScreenShot(Graphics::Surface &surf) { Graphics::PixelFormat screenFormat = g_system->getScreenFormat(); //convert surface to 2 bytes pixel format to avoid problems with palette saving and loading if ((screenFormat.bytesPerPixel == 1) || (screenFormat.bytesPerPixel == 2)) { return grabScreen565(&surf); } else { Graphics::Surface *screen = g_system->lockScreen(); if (!screen) { return false; } surf.create(screen->w, screen->h, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); for (uint y = 0; y < screen->h; ++y) { for (uint x = 0; x < screen->w; ++x) { byte r = 0, g = 0, b = 0, a = 0; uint32 col = READ_UINT32(screen->getBasePtr(x, y)); screenFormat.colorToARGB(col, a, r, g, b); *((uint32 *)surf.getBasePtr(x, y)) = Graphics::ARGBToColor<Graphics::ColorMasks<8888> >(a, r, g, b); } } g_system->unlockScreen(); return true; } }
void MystCursorManager::setCursor(uint16 id) { // Zero means empty cursor if (id == 0) { static const byte emptyCursor[4] = { 0, 0, 0, 0 }; CursorMan.replaceCursor(&emptyCursor, 2, 2, 0, 0, 0); return; } Common::SeekableReadStream *clrcStream = _vm->getResource(ID_CLRC, id); uint16 hotspotX = clrcStream->readUint16LE(); uint16 hotspotY = clrcStream->readUint16LE(); delete clrcStream; // Both Myst and Myst ME use the "MystBitmap" format for cursor images. MohawkSurface *mhkSurface = _vm->_gfx->findImage(id); Graphics::Surface *surface = mhkSurface->getSurface(); // Myst ME stores some cursors as 24bpp images instead of 8bpp if (surface->format.bytesPerPixel == 1) { // The transparent color is almost always 255, except for the main cursor (100) // in the D'ni archive, where it is 0. // Using the color of the first pixel as the transparent color for the main cursor always works. byte transparentColor; if (id == kDefaultMystCursor) { transparentColor = ((byte *)surface->getPixels())[0]; } else { transparentColor = 255; } CursorMan.replaceCursor(surface->getPixels(), surface->w, surface->h, hotspotX, hotspotY, transparentColor); // We're using the screen palette for the original game, but we need // to use this for any 8bpp cursor in ME. if (_vm->getFeatures() & GF_ME) CursorMan.replaceCursorPalette(mhkSurface->getPalette(), 0, 256); } else { Graphics::PixelFormat pixelFormat = g_system->getScreenFormat(); CursorMan.replaceCursor(surface->getPixels(), surface->w, surface->h, hotspotX, hotspotY, pixelFormat.RGBToColor(255, 255, 255), false, &pixelFormat); } }
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; }
bool PCXDecoder::loadStream(Common::SeekableReadStream &stream) { destroy(); if (stream.readByte() != 0x0a) // ZSoft PCX return false; byte version = stream.readByte(); // 0 - 5 if (version > 5) return false; bool compressed = stream.readByte(); // encoding, 1 = run length encoding byte bitsPerPixel = stream.readByte(); // 1, 2, 4 or 8 // Window uint16 xMin = stream.readUint16LE(); uint16 yMin = stream.readUint16LE(); uint16 xMax = stream.readUint16LE(); uint16 yMax = stream.readUint16LE(); uint16 width = xMax - xMin + 1; uint16 height = yMax - yMin + 1; if (xMax < xMin || yMax < yMin) { warning("Invalid PCX image dimensions"); return false; } stream.skip(4); // HDpi, VDpi // Read the EGA palette (colormap) _palette = new byte[16 * 3]; for (uint16 i = 0; i < 16; i++) { _palette[i * 3 + 0] = stream.readByte(); _palette[i * 3 + 1] = stream.readByte(); _palette[i * 3 + 2] = stream.readByte(); } if (stream.readByte() != 0) // reserved, should be set to 0 return false; byte nPlanes = stream.readByte(); uint16 bytesPerLine = stream.readUint16LE(); uint16 bytesPerscanLine = nPlanes * bytesPerLine; if (bytesPerscanLine < width * bitsPerPixel * nPlanes / 8) { warning("PCX data is corrupted"); return false; } stream.skip(60); // PaletteInfo, HscreenSize, VscreenSize, Filler _surface = new Graphics::Surface(); byte *scanLine = new byte[bytesPerscanLine]; byte *dst; int x, y; if (nPlanes == 3 && bitsPerPixel == 8) { // 24bpp Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); _surface->create(width, height, format); dst = (byte *)_surface->getPixels(); _paletteColorCount = 0; for (y = 0; y < height; y++) { decodeRLE(stream, scanLine, bytesPerscanLine, compressed); for (x = 0; x < width; x++) { byte b = scanLine[x]; byte g = scanLine[x + bytesPerLine]; byte r = scanLine[x + (bytesPerLine << 1)]; uint32 color = format.RGBToColor(r, g, b); *((uint32 *)dst) = color; dst += format.bytesPerPixel; } } } else if (nPlanes == 1 && bitsPerPixel == 8) { // 8bpp indexed _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); dst = (byte *)_surface->getPixels(); _paletteColorCount = 16; for (y = 0; y < height; y++, dst += _surface->pitch) { decodeRLE(stream, scanLine, bytesPerscanLine, compressed); memcpy(dst, scanLine, width); } if (version == 5) { if (stream.readByte() != 12) { warning("Expected a palette after the PCX image data"); delete[] scanLine; return false; } // Read the VGA palette delete[] _palette; _palette = new byte[256 * 3]; for (uint16 i = 0; i < 256; i++) { _palette[i * 3 + 0] = stream.readByte(); _palette[i * 3 + 1] = stream.readByte(); _palette[i * 3 + 2] = stream.readByte(); } _paletteColorCount = 256; } } else if ((nPlanes == 2 || nPlanes == 3 || nPlanes == 4) && bitsPerPixel == 1) { // planar, 4, 8 or 16 colors _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); dst = (byte *)_surface->getPixels(); _paletteColorCount = 16; for (y = 0; y < height; y++, dst += _surface->pitch) { decodeRLE(stream, scanLine, bytesPerscanLine, compressed); for (x = 0; x < width; x++) { int m = 0x80 >> (x & 7), v = 0; for (int i = nPlanes - 1; i >= 0; i--) { v <<= 1; v += (scanLine[i * bytesPerLine + (x >> 3)] & m) == 0 ? 0 : 1; } dst[x] = v; } } } else {
// Function to blit a rect from one color format to another bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch, int w, int h, const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt) { // Error out if conversion is impossible if ((srcFmt.bytesPerPixel == 1) || (dstFmt.bytesPerPixel == 1) || (!srcFmt.bytesPerPixel) || (!dstFmt.bytesPerPixel) || (srcFmt.bytesPerPixel > dstFmt.bytesPerPixel)) return false; // Don't perform unnecessary conversion if (srcFmt == dstFmt) { if (dst == src) return true; if (dstpitch == srcpitch && ((w * dstFmt.bytesPerPixel) == dstpitch)) { memcpy(dst,src,dstpitch * h); return true; } else { for (int i = 0; i < h; i++) { memcpy(dst,src,w * dstFmt.bytesPerPixel); dst += dstpitch; src += srcpitch; } return true; } } // Faster, but larger, to provide optimized handling for each case. int srcDelta, dstDelta; srcDelta = (srcpitch - w * srcFmt.bytesPerPixel); dstDelta = (dstpitch - w * dstFmt.bytesPerPixel); // TODO: optimized cases for dstDelta of 0 uint8 r, g, b, a; if (dstFmt.bytesPerPixel == 2) { uint16 color; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++, src += 2, dst += 2) { color = *(const uint16 *)src; srcFmt.colorToARGB(color, a, r, g, b); color = dstFmt.ARGBToColor(a, r, g, b); *(uint16 *)dst = color; } src += srcDelta; dst += dstDelta; } } else if (dstFmt.bytesPerPixel == 3) { uint32 color; uint8 *col = (uint8 *) &color; #ifdef SCUMM_BIG_ENDIAN col++; #endif if (srcFmt.bytesPerPixel == 2) { for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++, src += 2, dst += 3) { color = *(const uint16 *)src; srcFmt.colorToARGB(color, a, r, g, b); color = dstFmt.ARGBToColor(a, r, g, b); memcpy(dst, col, 3); } src += srcDelta; dst += dstDelta; } } else { for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++, src += 3, dst += 3) { memcpy(col, src, 3); srcFmt.colorToARGB(color, a, r, g, b); color = dstFmt.ARGBToColor(a, r, g, b); memcpy(dst, col, 3); } src += srcDelta; dst += dstDelta; } } } else if (dstFmt.bytesPerPixel == 4) { uint32 color; if (srcFmt.bytesPerPixel == 2) { for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++, src += 2, dst += 4) { color = *(const uint16 *)src; srcFmt.colorToARGB(color, a, r, g, b); color = dstFmt.ARGBToColor(a, r, g, b); *(uint32 *)dst = color; } src += srcDelta; dst += dstDelta; } } else if (srcFmt.bytesPerPixel == 3) { uint8 *col = (uint8 *)&color; #ifdef SCUMM_BIG_ENDIAN col++; #endif for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++, src += 2, dst += 4) { memcpy(col, src, 3); srcFmt.colorToARGB(color, a, r, g, b); color = dstFmt.ARGBToColor(a, r, g, b); *(uint32 *)dst = color; } src += srcDelta; dst += dstDelta; } } else { for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++, src += 4, dst += 4) { color = *(const uint32 *)src; srcFmt.colorToARGB(color, a, r, g, b); color = dstFmt.ARGBToColor(a, r, g, b); *(uint32 *)dst = color; } src += srcDelta; dst += dstDelta; } } } else { return false; } return true; }
void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) { Graphics::PixelFormat inputFormat; #ifdef USE_RGB_COLOR if (format) { inputFormat = *format; } else { inputFormat = Graphics::PixelFormat::createFormatCLUT8(); } #else inputFormat = Graphics::PixelFormat::createFormatCLUT8(); #endif // In case the color format has changed we will need to create the texture. if (!_cursor || _cursor->getFormat() != inputFormat) { delete _cursor; _cursor = nullptr; GLenum glIntFormat, glFormat, glType; Graphics::PixelFormat textureFormat; if (inputFormat.bytesPerPixel == 1 || (inputFormat.aBits() && getGLPixelFormat(inputFormat, glIntFormat, glFormat, glType))) { // There is two cases when we can use the cursor format directly. // The first is when it's CLUT8, here color key handling can // always be applied because we use the alpha channel of // _defaultFormatAlpha for that. // The other is when the input format has alpha bits and // furthermore is directly supported. textureFormat = inputFormat; } else { textureFormat = _defaultFormatAlpha; } _cursor = createTexture(textureFormat, true); assert(_cursor); _cursor->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); } _cursorKeyColor = keycolor; _cursorHotspotX = hotspotX; _cursorHotspotY = hotspotY; _cursorDontScale = dontScale; _cursor->allocate(w, h); if (inputFormat.bytesPerPixel == 1) { // For CLUT8 cursors we can simply copy the input data into the // texture. _cursor->copyRectToTexture(0, 0, w, h, buf, w * inputFormat.bytesPerPixel); } else { // Otherwise it is a bit more ugly because we have to handle a key // color properly. Graphics::Surface *dst = _cursor->getSurface(); const uint srcPitch = w * inputFormat.bytesPerPixel; // Copy the cursor data to the actual texture surface. This will make // sure that the data is also converted to the expected format. Graphics::crossBlit((byte *)dst->getPixels(), (const byte *)buf, dst->pitch, srcPitch, w, h, dst->format, inputFormat); // We apply the color key by setting the alpha bits of the pixels to // fully transparent. const uint32 aMask = (0xFF >> dst->format.aLoss) << dst->format.aShift; if (dst->format.bytesPerPixel == 2) { if (inputFormat.bytesPerPixel == 2) { applyColorKey<uint16, uint16>((uint16 *)dst->getPixels(), (const uint16 *)buf, w, h, dst->pitch, srcPitch, keycolor, aMask); } else if (inputFormat.bytesPerPixel == 4) { applyColorKey<uint16, uint32>((uint16 *)dst->getPixels(), (const uint32 *)buf, w, h, dst->pitch, srcPitch, keycolor, aMask); } } else { if (inputFormat.bytesPerPixel == 2) { applyColorKey<uint32, uint16>((uint32 *)dst->getPixels(), (const uint16 *)buf, w, h, dst->pitch, srcPitch, keycolor, aMask); } else if (inputFormat.bytesPerPixel == 4) { applyColorKey<uint32, uint32>((uint32 *)dst->getPixels(), (const uint32 *)buf, w, h, dst->pitch, srcPitch, keycolor, aMask); } } // Flag the texture as dirty. _cursor->flagDirty(); } // In case we actually use a palette set that up properly. if (inputFormat.bytesPerPixel == 1) { updateCursorPalette(); } // Update the scaling. recalculateCursorScaling(); }
BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) { //TextLineList lines; // TODO: Use WideString-conversion here. //WrapText(text, width, maxHeight, lines); Common::Array<WideString> lines; _font->wordWrapText(text, width, lines); while (maxHeight > 0 && lines.size() * _lineHeight > maxHeight) { lines.pop_back(); } if (lines.size() == 0) { return nullptr; } Graphics::TextAlign alignment = Graphics::kTextAlignInvalid; if (align == TAL_LEFT) { alignment = Graphics::kTextAlignLeft; } else if (align == TAL_CENTER) { alignment = Graphics::kTextAlignCenter; } else if (align == TAL_RIGHT) { alignment = Graphics::kTextAlignRight; } // TODO: This debug call does not work with WideString because text.c_str() returns an uint32 array. //debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color)); // void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const; Graphics::Surface *surface = new Graphics::Surface(); surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _gameRef->_renderer->getPixelFormat()); uint32 useColor = 0xffffffff; Common::Array<WideString>::iterator it; int heightOffset = 0; for (it = lines.begin(); it != lines.end(); ++it) { _font->drawString(surface, *it, 0, heightOffset, width, useColor, alignment); heightOffset += (int)_lineHeight; } BaseSurface *retSurface = _gameRef->_renderer->createSurface(); if (_deletableFont) { // Reconstruct the alpha channel of the font. // Since we painted it with color 0xFFFFFFFF onto a black background, // the alpha channel is gone, but the color value of each pixel corresponds // to its original alpha value. Graphics::PixelFormat format = _gameRef->_renderer->getPixelFormat(); uint32 *pixels = (uint32 *)surface->getPixels(); // This is a Surface we created ourselves, so no empty space between rows. for (int i = 0; i < surface->w * surface->h; ++i) { uint8 a, r, g, b; format.colorToRGB(*pixels, r, g, b); a = r; *pixels++ = format.ARGBToColor(a, r, g, b); } } retSurface->putSurface(*surface, true); surface->free(); delete surface; return retSurface; // TODO: _isUnderline, _isBold, _isItalic, _isStriked }
bool UIWindow::display(int offsetX, int offsetY) { // go exclusive if (_mode == WINDOW_EXCLUSIVE || _mode == WINDOW_SYSTEM_EXCLUSIVE) { if (!_shieldWindow) { _shieldWindow = new UIWindow(_gameRef); } if (_shieldWindow) { _shieldWindow->_posX = _shieldWindow->_posY = 0; _shieldWindow->_width = _gameRef->_renderer->getWidth(); _shieldWindow->_height = _gameRef->_renderer->getHeight(); _shieldWindow->display(); } } else if (_isMenu) { if (!_shieldButton) { _shieldButton = new UIButton(_gameRef); _shieldButton->setName("close"); _shieldButton->setListener(this, _shieldButton, 0); _shieldButton->_parent = this; } if (_shieldButton) { _shieldButton->_posX = _shieldButton->_posY = 0; _shieldButton->setWidth(_gameRef->_renderer->getWidth()); _shieldButton->setHeight(_gameRef->_renderer->getHeight()); _shieldButton->display(); } } if (!_visible) { return STATUS_OK; } if (_fadeBackground) { Graphics::PixelFormat format = _gameRef->_renderer->getPixelFormat(); byte fadeR, fadeG, fadeB, fadeA; // First convert from the internal format to the screen-format uint32 fadeColor = format.ARGBToColor(RGBCOLGetA(_fadeColor), RGBCOLGetR(_fadeColor), RGBCOLGetG(_fadeColor), RGBCOLGetB(_fadeColor)); // Then get components format.colorToARGB(fadeColor, fadeA, fadeR, fadeG, fadeB); _gameRef->_renderer->fadeToColor(fadeR, fadeG, fadeB, fadeA); } if (_dragging) { _posX += (_gameRef->_mousePos.x - _dragFrom.x); _posY += (_gameRef->_mousePos.y - _dragFrom.y); _dragFrom.x = _gameRef->_mousePos.x; _dragFrom.y = _gameRef->_mousePos.y; } if (!_focusedWidget || (!_focusedWidget->canFocus() || _focusedWidget->isDisabled() || !_focusedWidget->isVisible())) { moveFocus(); } bool popViewport = false; if (_clipContents) { if (!_viewport) { _viewport = new BaseViewport(_gameRef); } if (_viewport) { _viewport->setRect(_posX + offsetX, _posY + offsetY, _posX + _width + offsetX, _posY + _height + offsetY); _gameRef->pushViewport(_viewport); popViewport = true; } } UITiledImage *back = _back; BaseSprite *image = _image; BaseFont *font = _font; if (!isFocused()) { if (_backInactive) { back = _backInactive; } if (_imageInactive) { image = _imageInactive; } if (_fontInactive) { font = _fontInactive; } } if (_alphaColor != 0) { _gameRef->_renderer->_forceAlphaColor = _alphaColor; } if (back) { back->display(_posX + offsetX, _posY + offsetY, _width, _height); } if (image) { image->draw(_posX + offsetX, _posY + offsetY, _transparent ? nullptr : this); } if (!BasePlatform::isRectEmpty(&_titleRect) && font && _text) { font->drawText((byte *)_text, _posX + offsetX + _titleRect.left, _posY + offsetY + _titleRect.top, _titleRect.right - _titleRect.left, _titleAlign, _titleRect.bottom - _titleRect.top); } if (!_transparent && !image) { _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, nullptr, _posX + offsetX, _posY + offsetY, _width, _height, 100, 100, false)); } for (uint32 i = 0; i < _widgets.size(); i++) { _widgets[i]->display(_posX + offsetX, _posY + offsetY); } if (_alphaColor != 0) { _gameRef->_renderer->_forceAlphaColor = 0; } if (popViewport) { _gameRef->popViewport(); } return STATUS_OK; }
int MidiDriver_MT32::open() { if (_isOpen) return MERR_ALREADY_OPEN; _reportHandler = new MT32Emu::ReportHandlerScummVM(); _synth = new MT32Emu::Synth(_reportHandler); Graphics::PixelFormat screenFormat = g_system->getScreenFormat(); if (screenFormat.bytesPerPixel == 1) { const byte dummy_palette[] = { 0, 0, 0, // background 0, 171, 0, // border, font 171, 0, 0 // fill }; g_system->getPaletteManager()->setPalette(dummy_palette, 0, 3); } _initializing = true; debug(4, _s("Initializing MT-32 Emulator")); _controlFile = new Common::File(); if (!_controlFile->open("CM32L_CONTROL.ROM") && !_controlFile->open("MT32_CONTROL.ROM")) error("Error opening MT32_CONTROL.ROM / CM32L_CONTROL.ROM"); _pcmFile = new Common::File(); if (!_pcmFile->open("CM32L_PCM.ROM") && !_pcmFile->open("MT32_PCM.ROM")) error("Error opening MT32_PCM.ROM / CM32L_PCM.ROM"); _controlROM = MT32Emu::ROMImage::makeROMImage(_controlFile); _pcmROM = MT32Emu::ROMImage::makeROMImage(_pcmFile); if (!_synth->open(*_controlROM, *_pcmROM)) return MERR_DEVICE_NOT_AVAILABLE; double gain = (double)ConfMan.getInt("midi_gain") / 100.0; _synth->setOutputGain(1.0f * gain); _synth->setReverbOutputGain(0.68f * gain); // We let the synthesizer play MIDI messages immediately. Our MIDI // handling is synchronous to sample generation. This makes delaying MIDI // events result in odd sound output in some cases. For example, the // shattering window in the Indiana Jones and the Fate of Atlantis intro // will sound like a bell if we use any delay here. // Bug #6242 "AUDIO: Built-In MT-32 MUNT Produces Wrong Sounds". _synth->setMIDIDelayMode(MT32Emu::MIDIDelayMode_IMMEDIATE); // We need to report the sample rate MUNT renders at as sample rate of our // AudioStream. _outputRate = _synth->getStereoOutputSampleRate(); MidiDriver_Emulated::open(); _initializing = false; if (screenFormat.bytesPerPixel > 1) g_system->fillScreen(screenFormat.RGBToColor(0, 0, 0)); else g_system->fillScreen(0); g_system->updateScreen(); _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); return 0; }
bool writePNG(Common::WriteStream &out, const Graphics::Surface &input, const bool bottomUp) { #ifdef USE_PNG const Graphics::PixelFormat requiredFormat_3byte(3, 8, 8, 8, 0, 16, 8, 0, 0); const Graphics::PixelFormat requiredFormat_4byte(4, 8, 8, 8, 8, 0, 8, 16, 24); if (input.format.bytesPerPixel == 3) { if (input.format != requiredFormat_3byte) { warning("Cannot currently write PNG with 3-byte pixel format other than %s", requiredFormat_3byte.toString().c_str()); return false; } } else if (input.format.bytesPerPixel != 4) { warning("Cannot currently write PNG with pixel format of bpp other than 3, 4"); return false; } int colorType; Graphics::Surface *tmp = NULL; const Graphics::Surface *surface; if (input.format == requiredFormat_3byte) { surface = &input; colorType = PNG_COLOR_TYPE_RGB; } else { if (input.format == requiredFormat_4byte) { surface = &input; } else { surface = tmp = input.convertTo(requiredFormat_4byte); } colorType = PNG_COLOR_TYPE_RGB_ALPHA; } png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!pngPtr) { return false; } png_infop infoPtr = png_create_info_struct(pngPtr); if (!infoPtr) { png_destroy_write_struct(&pngPtr, NULL); return false; } png_set_error_fn(pngPtr, NULL, pngError, pngWarning); // TODO: The manual says errors should be handled via setjmp png_set_write_fn(pngPtr, &out, pngWriteToStream, pngFlushStream); png_set_IHDR(pngPtr, infoPtr, surface->w, surface->h, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); Common::Array<const uint8 *> rows; rows.reserve(surface->h); if (bottomUp) { for (uint y = surface->h; y-- > 0;) { rows.push_back((const uint8 *)surface->getBasePtr(0, y)); } } else { for (uint y = 0; y < surface->h; ++y) { rows.push_back((const uint8 *)surface->getBasePtr(0, y)); } } png_set_rows(pngPtr, infoPtr, const_cast<uint8 **>(&rows.front())); png_write_png(pngPtr, infoPtr, 0, NULL); png_destroy_write_struct(&pngPtr, &infoPtr); // free tmp surface if (tmp) { tmp->free(); delete tmp; } return true; #else return false; #endif }
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 { delete _videoStreams[i].video; _videoStreams[i].clear(); continue; } } // Check if we need to draw a frame if (!_videoStreams[i]->isPaused() && _videoStreams[i]->needsUpdate()) { const Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame(); Graphics::Surface *convertedFrame = 0; if (frame && _videoStreams[i].enabled) { // Convert from 8bpp to the current screen format if necessary Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat(); 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; } } // 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); _vm->_system->copyRectToScreen((byte*)frame->pixels, frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height); // We've drawn something to the screen, make sure we update it updateScreen = true; // Delete 8bpp conversion surface if (convertedFrame) { convertedFrame->free(); delete convertedFrame; } } } } // Return true if we need to update the screen return updateScreen; }