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; }
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; }
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; }
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]; } }
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; }
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; }
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; } }
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(); }
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; }
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; } } }
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; }
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 {
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; }
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; }
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 BitmapDecoder::loadStream(Common::SeekableReadStream &stream) { destroy(); if (stream.readByte() != 'B') return false; if (stream.readByte() != 'M') return false; /* uint32 fileSize = */ stream.readUint32LE(); /* uint16 res1 = */ stream.readUint16LE(); /* uint16 res2 = */ stream.readUint16LE(); uint32 imageOffset = stream.readUint32LE(); uint32 infoSize = stream.readUint32LE(); if (infoSize != 40) { warning("Only Windows v3 bitmaps are supported"); return false; } uint32 width = stream.readUint32LE(); int32 height = stream.readSint32LE(); if (width == 0 || height == 0) return false; if (height < 0) { warning("Right-side up bitmaps not supported"); return false; } /* uint16 planes = */ stream.readUint16LE(); uint16 bitsPerPixel = stream.readUint16LE(); if (bitsPerPixel != 8 && bitsPerPixel != 24 && bitsPerPixel != 32) { warning("%dbpp bitmaps not supported", bitsPerPixel); return false; } uint32 compression = stream.readUint32LE(); if (compression != 0) { warning("Compressed bitmaps not supported"); return false; } /* uint32 imageSize = */ stream.readUint32LE(); /* uint32 pixelsPerMeterX = */ stream.readUint32LE(); /* uint32 pixelsPerMeterY = */ stream.readUint32LE(); _paletteColorCount = stream.readUint32LE(); /* uint32 colorsImportant = */ stream.readUint32LE(); if (bitsPerPixel == 8) { if (_paletteColorCount == 0) _paletteColorCount = 256; // Read the palette _palette = new byte[_paletteColorCount * 3]; for (uint16 i = 0; i < _paletteColorCount; i++) { _palette[i * 3 + 2] = stream.readByte(); _palette[i * 3 + 1] = stream.readByte(); _palette[i * 3 + 0] = stream.readByte(); stream.readByte(); } } // Start us at the beginning of the image stream.seek(imageOffset); Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8(); // BGRA for 24bpp and 32 bpp if (bitsPerPixel == 24 || bitsPerPixel == 32) format = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0); _surface = new Graphics::Surface(); _surface->create(width, height, format); int srcPitch = width * (bitsPerPixel >> 3); const int extraDataLength = (srcPitch % 4) ? 4 - (srcPitch % 4) : 0; if (bitsPerPixel == 8) { byte *dst = (byte *)_surface->pixels; for (int32 i = 0; i < height; i++) { stream.read(dst + (height - i - 1) * width, width); stream.skip(extraDataLength); } } else if (bitsPerPixel == 24) { byte *dst = (byte *)_surface->pixels + (height - 1) * _surface->pitch; for (int32 i = 0; i < height; i++) { for (uint32 j = 0; j < width; j++) { byte b = stream.readByte(); byte g = stream.readByte(); byte r = stream.readByte(); uint32 color = format.RGBToColor(r, g, b); *((uint32 *)dst) = color; dst += format.bytesPerPixel; } stream.skip(extraDataLength); dst -= _surface->pitch * 2; } } else { // 32 bpp byte *dst = (byte *)_surface->pixels + (height - 1) * _surface->pitch; for (int32 i = 0; i < height; i++) { for (uint32 j = 0; j < width; j++) { byte b = stream.readByte(); byte g = stream.readByte(); byte r = stream.readByte(); // Ignore the last byte, as in v3 it is unused // and should thus NOT be used as alpha. // ref: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376%28v=vs.85%29.aspx stream.readByte(); uint32 color = format.RGBToColor(r, g, b); *((uint32 *)dst) = color; dst += format.bytesPerPixel; } stream.skip(extraDataLength); dst -= _surface->pitch * 2; } } return true; }
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 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; }