Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

void Scumm::ScummEngine::drawStripToScreen ( VirtScreen vs,
int  x,
int  width,
int  top,
int  bottom 
) [protected, inherited]

Blit the specified rectangle from the given virtual screen to the display. Note: t and b are in *virtual screen* coordinates, while x is relative to the *real screen*. This is due to the way tdirty/vdirty work: they are arrays which map 'strips' (sections of the real screen) to dirty areas as specified by top/bottom coordinate in the virtual screen.

Definition at line 552 of file gfx.cpp.

References Scumm::ScummEngine::_textSurface, Graphics::Surface::getBasePtr(), Scumm::VirtScreen::getPixels(), Graphics::Surface::h, Scumm::VirtScreen::number, Graphics::Surface::pitch, Graphics::Surface::pixels, Scumm::GameSettings::platform, Scumm::VirtScreen::topline, Scumm::GameSettings::version, and Graphics::Surface::w.

Referenced by Scumm::ScummEngine::drawDirtyScreenParts(), and Scumm::ScummEngine::updateDirtyScreen().

                                                                                         {

      // Short-circuit if nothing has to be drawn
      if (bottom <= top || top >= vs->h)
            return;

      // Some paranoia checks
      assert(top >= 0 && bottom <= vs->h);
      assert(x >= 0 && width <= vs->pitch);
      assert(_textSurface.pixels);

      // Perform some clipping
      if (width > vs->w - x)
            width = vs->w - x;
      if (top < _screenTop)
            top = _screenTop;
      if (bottom > _screenTop + _screenHeight)
            bottom = _screenTop + _screenHeight;

      // Convert the vertical coordinates to real screen coords
      int y = vs->topline + top - _screenTop;
      int height = bottom - top;

      if (width <= 0 || height <= 0)
            return;

      const byte *src = vs->getPixels(x, top);
      int m = _textSurfaceMultiplier;
      byte *dst;
      int vsPitch;
      int pitch = vs->pitch;

      if (_useCJKMode && _textSurfaceMultiplier == 2) {
            dst = _fmtownsBuf;

            scale2x(dst, _screenWidth * m, src, vs->pitch,  width, height);
            src = dst;

            vsPitch = _screenWidth * m - width * m;

      } else {
            vsPitch = vs->pitch - width;
      }

      dst = _compositeBuf;

      if (_game.version < 7) {
            // For The Dig, FT and COMI, we just blit everything to the screen at once.
            // For older games, things are more complicated. First off, we need to
            // deal with the _textSurface, which needs to be composited over the
            // screen contents. Secondly, a rendering mode might be active, which
            // means a filter has to be applied.

            // Compute pointer to the text surface
            assert(_compositeBuf);
            const byte *text = (byte *)_textSurface.getBasePtr(x * m, y * m);

            // The values x, width, etc. are all multiples of 8 at this point,
            // so loop unrolloing might be a good idea...
            assert(0 == ((long)text & 3));
            assert(0 == (width & 3));

            // Compose the text over the game graphics

            // TODO: Optimize this code. There are several things that come immediately to mind:
            // (1) Loop unrolling: We could read 4 or even 8 pixels at once, since everything is
            //     a multiple of 8 here.
            // (2) More ASM versions (in particular, the ARM code for the NDS could be used on
            //     all ARM systems, couldn't it?)
            // (3) Better encoding of the text surface data. This is the one with the biggest
            //     potential.
            //     (a) Keep an "isEmpty" marker for each pixel row in the _textSurface. The idea
            //         is that most rows won't contain any text data, so we can just use memcpy.
            //     (b) RLE encode the _textSurface row-wise. This is an improved variant of (a),
            //         but also more complicated to implement, and incurs a bigger overhead when
            //         writing to the text surface.
#ifdef ARM_USE_GFX_ASM
            asmDrawStripToScreen(height, width, text, src, dst, vs->pitch, width, _textSurface.pitch);
#else
            for (int h = 0; h < height * m; ++h) {
                  for (int w = 0; w < width * m; ++w) {
                        byte tmp = *text++;
                        if (tmp == CHARSET_MASK_TRANSPARENCY)
                              tmp = *src;
                        *dst++ = tmp;
                        src++;
                  }
                  src += vsPitch;
                  text += _textSurface.pitch - width * m;
            }
#endif
            src = _compositeBuf;
            pitch = width;

            if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
                  ditherHerc(_compositeBuf, _herculesBuf, width, &x, &y, &width, &height);

                  src = _herculesBuf + x + y * Common::kHercW;
                  pitch = Common::kHercW;

                  // center image on the screen
                  x += (Common::kHercW - _screenWidth * 2) / 2;   // (720 - 320*2)/2 = 40
            } else if (_useCJKMode && m == 2) {
                  pitch *= m;
                  x *= m;
                  y *= m;
                  width *= m;
                  height *= m;
            } else {
                  if (_renderMode == Common::kRenderCGA)
                        ditherCGA(_compositeBuf, width, x, y, width, height);

                  // HACK: This is dirty hack which renders narrow NES rooms centered
                  // NES can address negative number strips and that poses problem for
                  // our code. So instead of adding zillions of fixes and potentially
                  // breaking other games, we shift it right at the rendering stage.
                  if ((_game.platform == Common::kPlatformNES) && (((_NESStartStrip > 0) && (vs->number == kMainVirtScreen)) || (vs->number == kTextVirtScreen))) {
                        x += 16;
                        while (x + width >= _screenWidth)
                              width -= 16;
                        if (width < 0)
                              return;
                  }

            }
      }

      // Finally blit the whole thing to the screen
      _system->copyRectToScreen(src, pitch, x, y, width, height);
}


Generated by  Doxygen 1.6.0   Back to index