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

video.cpp

/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 Ivan Dubrov
 * Copyright (C) 2004-2005 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.      See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/gob/video.cpp,v 1.15.2.1 2005/10/18 02:11:18 sev Exp $
 *
 */
#include "gob/gob.h"
#include "gob/global.h"
#include "gob/video.h"
#include "gob/dataio.h"

#include "gob/driver_vga.h"

namespace Gob {

VideoDriver *_videoDriver;


/* NOT IMPLEMENTED */

//XXX: Use this function to update the screen for now.
//     This should be moved to a better location later on.
void vid_waitRetrace(int16) {
      if (pPrimarySurfDesc) {
            g_system->copyRectToScreen(pPrimarySurfDesc->vidPtr, 320, 0, 0, 320, 200);
            g_system->updateScreen();
      }
}

char vid_initDriver(int16 vidMode) {
      warning("STUB: vid_initDriver");

      // FIXME: Finish all this stuff :)
      _videoDriver = new VGAVideoDriver();

      return 1;
}

void vid_freeDriver() {
      delete _videoDriver;
      warning("STUB: vid_freeDriver");
}

int32 vid_getRectSize(int16 width, int16 height, int16 flag, int16 mode) {
      int32 size;

      if ((mode & 0x7f) != 0x13)
            warning
                ("vid_getRectSize: Video mode %d is not fully supported!",
                mode & 0x7f);
      switch (mode & 0x7f) {
      case 5:
      case 7:
            size = ((int32)((width + 3) / 4)) * height * (flag + 1);
            break;
      case 0x13:
            size = (int32)width *height;
            break;
      case 0x14:
      case 0x15:
      case 0x16:
            size = ((int32)((width + 3) / 4)) * height * 4;
            break;
      default:
            size = ((int32)((width + 7) / 8)) * height * (flag + 4);
            break;
      }
      return size;
}

SurfaceDesc *vid_initSurfDesc(int16 vidMode, int16 width, int16 height, int16 flags) {
      int8 flagsAnd2;
      byte *vidMem;
      int32 sprSize;
      int16 someFlags = 1;
      SurfaceDesc *descPtr;

      if (flags != PRIMARY_SURFACE)
            sprAllocated++;

      if (flags & RETURN_PRIMARY)
            return pPrimarySurfDesc;

      if (vidMode != 0x13)
            error("vid_initSurfDesc: Only VGA 0x13 mode is supported!");

      if ((flags & PRIMARY_SURFACE) == 0)
            vidMode += 0x80;

      if (flags & 2)
            flagsAnd2 = 1;
      else
            flagsAnd2 = 0;

      if (flags & PRIMARY_SURFACE) {
            vidMem = 0;
            primaryWidth = width;
            mouseMaxCol = width;
            primaryHeight = height;
            mouseMaxRow = height;
            sprSize = 0;

      } else {
            vidMem = 0;
            sprSize = vid_getRectSize(width, height, flagsAnd2, vidMode);
            if (flagsAnd2)
                  someFlags += 0x80;
      }
      if (flags & PRIMARY_SURFACE) {
            descPtr = pPrimarySurfDesc;
            vidMem = (byte *)malloc(320 * 200);
      } else {
            if (flags & DISABLE_SPR_ALLOC)
                  descPtr = (SurfaceDesc *)malloc(sizeof(SurfaceDesc));
            else
                  descPtr = (SurfaceDesc *)malloc(sizeof(SurfaceDesc) + sprSize);
      }
      if (descPtr == 0)
            return 0;

      descPtr->width = width;
      descPtr->height = height;
      descPtr->flag = someFlags;
      descPtr->vidMode = vidMode;
      if (vidMem == 0)
            vidMem = ((byte *)descPtr) + sizeof(SurfaceDesc);
      descPtr->vidPtr = vidMem;

      descPtr->reserved1 = 0;
      descPtr->reserved2 = 0;
      return descPtr;
}

void vid_freeSurfDesc(SurfaceDesc * surfDesc) {
      sprAllocated--;
      if (surfDesc != pPrimarySurfDesc)
            free(surfDesc);
      else
            free(surfDesc->vidPtr);
}

int16 vid_clampValue(int16 val, int16 max) {
      if (val >= max)
            val = max - 1;

      if (val < 0)
            val = 0;

      return val;
}

void vid_drawSprite(SurfaceDesc *source, SurfaceDesc *dest,
          int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) {
      int16 temp;
      int16 destRight;
      int16 destBottom;

      if (doRangeClamp) {
            if (left > right) {
                  temp = left;
                  left = right;
                  right = temp;
            }
            if (top > bottom) {
                  temp = top;
                  top = bottom;
                  bottom = temp;
            }
            if (right < 0)
                  return;
            if (bottom < 0)
                  return;
            if (left >= source->width)
                  return;
            if (top >= source->height)
                  return;

            if (left < 0) {
                  x -= left;
                  left = 0;
            }
            if (top < 0) {
                  y -= top;
                  top = 0;
            }
            right = vid_clampValue(right, source->width);
            bottom = vid_clampValue(bottom, source->height);
            if (right - left >= source->width)
                  right = left + source->width - 1;
            if (bottom - top >= source->height)
                  bottom = top + source->height - 1;

            if (x < 0) {
                  left -= x;
                  x = 0;
            }
            if (y < 0) {
                  top -= y;
                  y = 0;
            }
            if (left > right)
                  return;
            if (top > bottom)
                  return;

            if (x >= dest->width)
                  return;

            if (y >= dest->height)
                  return;

            destRight = x + right - left;
            destBottom = y + bottom - top;
            if (destRight >= dest->width)
                  right -= destRight - dest->width + 1;

            if (destBottom >= dest->height)
                  bottom -= destBottom - dest->height + 1;
      }

      _videoDriver->drawSprite(source, dest, left, top, right, bottom, x, y, transp);
}

void vid_fillRect(SurfaceDesc *dest, int16 left, int16 top, int16 right, int16 bottom,
          int16 color) {
      int16 temp;

      if (doRangeClamp) {
            if (left > right) {
                  temp = left;
                  left = right;
                  right = temp;
            }
            if (top > bottom) {
                  temp = top;
                  top = bottom;
                  bottom = temp;
            }
            if (right < 0)
                  return;
            if (bottom < 0)
                  return;
            if (left >= dest->width)
                  return;
            if (top >= dest->height)
                  return;

            left = vid_clampValue(left, dest->width);
            top = vid_clampValue(top, dest->height);
            right = vid_clampValue(right, dest->width);
            bottom = vid_clampValue(bottom, dest->height);
      }

      _videoDriver->fillRect(dest, left, top, right, bottom, color);
}

void vid_drawLine(SurfaceDesc *dest, int16 x0, int16 y0, int16 x1, int16 y1, int16 color) {
      if (x0 == x1 || y0 == y1) {
            vid_fillRect(dest, x0, y0, x1, y1, color);
            return;
      }

      _videoDriver->drawLine(dest, x0, y0, x1, y1, color);
}

void vid_putPixel(int16 x, int16 y, int16 color, SurfaceDesc *dest) {
      if (x < 0 || y < 0 || x >= dest->width || y >= dest->height)
            return;

      _videoDriver->putPixel(x, y, color, dest);
}

void vid_drawLetter(unsigned char item, int16 x, int16 y, FontDesc *fontDesc, int16 color1,
          int16 color2, int16 transp, SurfaceDesc *dest) {

      _videoDriver->drawLetter(item, x, y, fontDesc, color1, color2, transp, dest);
}

void vid_clearSurf(SurfaceDesc *dest) {
      vid_fillRect(dest, 0, 0, dest->width - 1, dest->height - 1, 0);
}

void vid_drawPackedSprite(byte *sprBuf, int16 width, int16 height, int16 x, int16 y,
          int16 transp, SurfaceDesc *dest) {

      if (vid_spriteUncompressor(sprBuf, width, height, x, y, transp, dest))
            return;

      if ((dest->vidMode & 0x7f) != 0x13)
            error("vid_drawPackedSprite: Vide mode 0x%x is not fully supported!",
                dest->vidMode & 0x7f);

      _videoDriver->drawPackedSprite(sprBuf, width, height, x, y, transp, dest);
}

void vid_setPalElem(int16 index, char red, char green, char blue, int16 unused,
          int16 vidMode) {
      byte pal[4];

      redPalette[index] = red;
      greenPalette[index] = green;
      bluePalette[index] = blue;

      if (vidMode != 0x13)
            error("vid_setPalElem: Video mode 0x%x is not supported!",
                vidMode);

      pal[0] = (red << 2) | (red >> 4);
      pal[1] = (green << 2) | (green >> 4);
      pal[2] = (blue << 2) | (blue >> 4);
      pal[3] = 0;
      g_system->setPalette(pal, index, 1);
}

void vid_setPalette(PalDesc *palDesc) {
      int16 i;
      byte pal[1024];
      int16 numcolors;

      if (videoMode != 0x13)
            error("vid_setPalette: Video mode 0x%x is not supported!",
                videoMode);

      if (setAllPalette)
            numcolors = 256;
      else
            numcolors = 16;

      for (i = 0; i < numcolors; i++) {
            pal[i * 4 + 0] = (palDesc->vgaPal[i].red << 2) | (palDesc->vgaPal[i].red >> 4);
            pal[i * 4 + 1] = (palDesc->vgaPal[i].green << 2) | (palDesc->vgaPal[i].green >> 4);
            pal[i * 4 + 2] = (palDesc->vgaPal[i].blue << 2) | (palDesc->vgaPal[i].blue >> 4);
            pal[i * 4 + 3] = 0;
      }

      g_system->setPalette(pal, 0, numcolors);
}

void vid_setFullPalette(PalDesc *palDesc) {
      Color *colors;
      int16 i;
      byte pal[1024];

      if (setAllPalette) {
            colors = palDesc->vgaPal;
            for (i = 0; i < 256; i++) {
                  redPalette[i] = colors[i].red;
                  greenPalette[i] = colors[i].green;
                  bluePalette[i] = colors[i].blue;
            }

            for (i = 0; i < 256; i++) {
                  pal[i * 4 + 0] = (colors[i].red << 2) | (colors[i].red >> 4);
                  pal[i * 4 + 1] = (colors[i].green << 2) | (colors[i].green >> 4);
                  pal[i * 4 + 2] = (colors[i].blue << 2) | (colors[i].blue >> 4);
                  pal[i * 4 + 3] = 0;
            }
            g_system->setPalette(pal, 0, 256);
      } else {
            vid_setPalette(palDesc);
      }
}

void vid_initPrimary(int16 mode) {
      int16 old;
      if (curPrimaryDesc) {
            vid_freeSurfDesc(curPrimaryDesc);
            vid_freeSurfDesc(allocatedPrimary);

            curPrimaryDesc = 0;
            allocatedPrimary = 0;
      }
      if (mode != 0x13 && mode != 3 && mode != -1)
            error("vid_initPrimary: Video mode 0x%x is not supported!",
                mode);

      if (videoMode != 0x13)
            error("vid_initPrimary: Video mode 0x%x is not supported!",
                mode);

      old = oldMode;
      if (mode == -1)
            mode = 3;

      oldMode = mode;
      if (mode != 3)
            vid_initDriver(mode);

      if (mode != 3) {
            vid_initSurfDesc(mode, 320, 200, PRIMARY_SURFACE);

            if (dontSetPalette)
                  return;

            vid_setFullPalette(pPaletteDesc);
      }
}

char vid_spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight,
          int16 x, int16 y, int16 transp, SurfaceDesc *destDesc) {
      SurfaceDesc sourceDesc;
      byte *memBuffer;
      byte *srcPtr;
      byte *destPtr;
      byte *linePtr;
      byte temp;
      uint16 sourceLeft;
      int16 curWidth;
      int16 curHeight;
      int16 offset;
      int16 counter2;
      uint16 cmdVar;
      int16 bufPos;
      int16 strLen;

      if (!destDesc)
            return 1;

      if ((destDesc->vidMode & 0x7f) != 0x13)
            error("vid_spriteUncompressor: Video mode 0x%x is not supported!",
                destDesc->vidMode & 0x7f);

      if (sprBuf[0] != 1)
            return 0;

      if (sprBuf[1] != 2)
            return 0;

      if (sprBuf[2] == 2) {
            sourceDesc.width = srcWidth;
            sourceDesc.height = srcHeight;
            sourceDesc.vidMode = 0x93;
            sourceDesc.vidPtr = sprBuf + 3;
            vid_drawSprite(&sourceDesc, destDesc, 0, 0, srcWidth - 1,
                srcHeight - 1, x, y, transp);
            return 1;
      } else {
            memBuffer = (byte *)malloc(4114);
            if (memBuffer == 0)
                  return 0;

            srcPtr = sprBuf + 3;
            sourceLeft = READ_LE_UINT16(srcPtr);

            destPtr = destDesc->vidPtr + destDesc->width * y + x;

            curWidth = 0;
            curHeight = 0;

            linePtr = destPtr;
            srcPtr += 4;

            for (offset = 0; offset < 4078; offset++)
                  memBuffer[offset] = 0x20;

            cmdVar = 0;
            bufPos = 4078;
            while (1) {
                  cmdVar >>= 1;
                  if ((cmdVar & 0x100) == 0) {
                        cmdVar = *srcPtr | 0xff00;
                        srcPtr++;
                  }
                  if ((cmdVar & 1) != 0) {
                        temp = *srcPtr++;
                        if (temp != 0 || transp == 0)
                              *destPtr = temp;
                        destPtr++;
                        curWidth++;
                        if (curWidth >= srcWidth) {
                              curWidth = 0;
                              linePtr += destDesc->width;
                              destPtr = linePtr;
                              curHeight++;
                              if (curHeight >= srcHeight)
                                    break;
                        }
                        sourceLeft--;
                        if (sourceLeft == 0)
                              break;

                        memBuffer[bufPos] = temp;
                        bufPos++;
                        bufPos %= 4096;
                  } else {
                        offset = *srcPtr;
                        srcPtr++;
                        offset |= (*srcPtr & 0xf0) << 4;
                        strLen = (*srcPtr & 0x0f) + 3;
                        srcPtr++;

                        for (counter2 = 0; counter2 < strLen;
                            counter2++) {
                              temp =
                                  memBuffer[(offset +
                                    counter2) % 4096];
                              if (temp != 0 || transp == 0)
                                    *destPtr = temp;
                              destPtr++;

                              curWidth++;
                              if (curWidth >= srcWidth) {
                                    curWidth = 0;
                                    linePtr += destDesc->width;
                                    destPtr = linePtr;
                                    curHeight++;
                                    if (curHeight >= srcHeight) {
                                          free(memBuffer);
                                          return 1;
                                    }
                              }
                              sourceLeft--;
                              if (sourceLeft == 0) {
                                    free(memBuffer);
                                    return 1;
                              }
                              memBuffer[bufPos] = temp;
                              bufPos++;
                              bufPos %= 4096;
                        }
                  }
            }
      }
      free(memBuffer);
      return 1;
}

void vid_setHandlers() {
      setAllPalette = 1;
}

}                       // End of namespace Gob

Generated by  Doxygen 1.6.0   Back to index