Logo Search packages:      
Sourcecode: scummvm version File versions

wiz_he.cpp

/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001  Ludvig Strigeus
 * Copyright (C) 2001-2004 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/scumm/wiz_he.cpp,v 2.1.2.1 2005/03/12 14:21:57 kirben Exp $
 *
 */

#include "stdafx.h"

#include "scumm/intern.h"
#include "scumm/resource.h"
#include "scumm/scumm.h"
#include "scumm/wiz_he.h"

namespace Scumm {

Wiz::Wiz() {
      _imagesNum = 0;
      memset(&_images, 0, sizeof(_images));
      memset(&_polygons, 0, sizeof(_polygons));
}

void Wiz::polygonStore(int id, bool flag, int vert1x, int vert1y, int vert2x, int vert2y, int vert3x, int vert3y, int vert4x, int vert4y) {
      WizPolygon *wp = NULL;
      for (int i = 0; i < ARRAYSIZE(_polygons); ++i) {
            if (_polygons[i].id == 0) {
                  wp = &_polygons[i];
                  break;
            }
      }
      if (!wp) {
            error("Wiz::polygonStore: out of polygon slot, max = %d", ARRAYSIZE(_polygons));
      }

      wp->vert[0].x = vert1x;
      wp->vert[0].y = vert1y;
      wp->vert[1].x = vert2x;
      wp->vert[1].y = vert2y;
      wp->vert[2].x = vert3x;
      wp->vert[2].y = vert3y;
      wp->vert[3].x = vert4x;
      wp->vert[3].y = vert4y;
      wp->vert[4].x = vert1x;
      wp->vert[4].y = vert1y;
      wp->id = id;
      wp->numVerts = 5;
      wp->flag = flag;  

      wp->bound.left = 10000;
      wp->bound.top = 10000;
      wp->bound.right = -10000;
      wp->bound.bottom = -10000;

      // compute bounding box
      for (int j = 0; j < wp->numVerts; j++) {
            Common::Rect r(wp->vert[j].x, wp->vert[j].y, wp->vert[j].x + 1, wp->vert[j].y + 1);
            wp->bound.extend(r);
      }
}

void Wiz::polygonErase(int fromId, int toId) {
      for (int i = 0; i < ARRAYSIZE(_polygons); i++) {
            if (_polygons[i].id >= fromId && _polygons[i].id <= toId)
                  memset(&_polygons[i], 0, sizeof(WizPolygon));
      }
}

int Wiz::polygonHit(int id, int x, int y) {
      for (int i = 0; i < ARRAYSIZE(_polygons); i++) {
            if ((id == 0 || _polygons[i].id == id) && _polygons[i].bound.contains(x, y)) {
                  if (polygonContains(_polygons[i], x, y)) {
                        return _polygons[i].id;
                  }
            }
      }
      return 0;
}

bool Wiz::polygonDefined(int id) {
      for (int i = 0; i < ARRAYSIZE(_polygons); i++)
            if (_polygons[i].id == id)
                  return true;
      return false;
}

bool Wiz::polygonContains(const WizPolygon &pol, int x, int y) {
      int pi = pol.numVerts - 1;
      bool diry = (y < pol.vert[pi].y);
      bool curdir;
      bool r = false;

      for (int i = 0; i < pol.numVerts; i++) {
            curdir = (y <= pol.vert[i].y);

            if (curdir != diry) {
                  if (((pol.vert[pi].y - pol.vert[i].y) * (pol.vert[i].x - x) <=
                         (pol.vert[pi].x - pol.vert[i].x) * (pol.vert[i].y - y)) == diry)
                        r = !r;
            }

            pi = i;
            diry = curdir;
      }

      return r;
}

void Wiz::copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch) {
      Common::Rect dstRect(srcx, srcy, srcx + srcw, srcy + srch);
      dstRect.clip(dstw, dsth);
      
      int rw = dstRect.width();
      int rh = dstRect.height();
      if (rh <= 0 || rw <= 0)
            return;
      
      uint8 *dst1Ptr = dst1 + dstRect.left + dstRect.top * dstw;
      uint8 *dst2Ptr = dst2 + dstRect.left + dstRect.top * dstw;
      const uint8 *dataPtr = src;

      while (rh--) {
            uint16 off = READ_LE_UINT16(dataPtr); dataPtr += 2;
            const uint8 *dataPtrNext = off + dataPtr;
            uint8 *dst1PtrNext = dst1Ptr + dstw;
            uint8 *dst2PtrNext = dst2Ptr + dstw;
            if (off != 0) {
                  int w = rw;
                  while (w > 0) {
                        uint8 code = *dataPtr++;
                        if (code & 1) {
                              code >>= 1;
                              dst1Ptr += code;
                              dst2Ptr += code;
                              w -= code;
                        } else if (code & 2) {
                              code = (code >> 2) + 1;
                              w -= code;
                              if (w >= 0) {
                                    memset(dst1Ptr, *dataPtr++, code);
                                    dst1Ptr += code;
                                    dst2Ptr += code;
                              } else {
                                    code += w;
                                    memset(dst1Ptr, *dataPtr, code);
                              }
                        } else {
                              code = (code >> 2) + 1;
                              w -= code;
                              if (w >= 0) {
                                    memcpy(dst1Ptr, dst2Ptr, code);
                                    dst1Ptr += code;
                                    dst2Ptr += code;
                              } else {
                                    code += w;
                                    memcpy(dst1Ptr, dst2Ptr, code);
                              }
                        }
                  }
            }
            dataPtr = dataPtrNext;
            dst1Ptr = dst1PtrNext;
            dst2Ptr = dst2PtrNext;
      }
}

static bool calcClipRects(int dst_w, int dst_h, int src_x, int src_y, int src_w, int src_h, const Common::Rect *rect, Common::Rect &srcRect, Common::Rect &dstRect) {
      Common::Rect r3;
      if (rect) {
            r3 = *rect;
            Common::Rect r4(dst_w, dst_h);
            if (r3.intersects(r4)) {
                  r3.clip(r4);
            } else {
                  return false;
            }
      } else {
            r3 = Common::Rect(dst_w, dst_h);
      }
      dstRect = Common::Rect(src_x, src_y, src_x + src_w, src_y + src_h);
      dstRect.clip(r3);
      srcRect = dstRect;
      srcRect.moveTo(0, 0);
      return srcRect.isValidRect() && dstRect.isValidRect();
}

void Wiz::copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect) {
      Common::Rect r1, r2;
      if (calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, r1, r2)) {
            dst += r2.left + r2.top * dstw;
            decompressWizImage(dst, dstw, r2, src, r1);
      }
}

void Wiz::copyRawWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor) {
      Common::Rect r1, r2;
      if (calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, r1, r2)) {
            if (flags & 0x400) {
                  int l = r1.left;
                  int r = r1.right;
                  r1.left = srcw - r;
                  r1.right = srcw - l;
            }
            if (flags & 0x800) {
                  int t = r1.top;
                  int b = r1.bottom;
                  r1.top = srch - b;
                  r1.bottom = srch - t;
            }
            byte imagePal[256];
            if (!palPtr) {
                  for (int i = 0; i < 256; i++) {
                        imagePal[i] = i;
                  }
                  palPtr = imagePal;
            }
            int h = r1.height();
            int w = r1.width();
            if (srcx < 0) {
                  src -= srcx;
            }
            if (srcy < 0) {
                  src -= srcy * srcw;
            }
            dst += r2.left + r2.top * dstw;
            while (h--) {
                  const uint8 *p = src;
                  for (int i = 0; i < w; ++i) {
                        uint8 col = *p++;
                        if (transColor == -1 || transColor != col) {
                              dst[i] = palPtr[col];
                        }
                  }
                  src += srcw;
                  dst += dstw;
            }
      }
}

void Wiz::decompressWizImage(uint8 *dst, int dstPitch, const Common::Rect &dstRect, const uint8 *src, const Common::Rect &srcRect, const uint8 *imagePal) {
      const uint8 *dataPtr, *dataPtrNext;
      uint8 *dstPtr, *dstPtrNext;
      uint32 code;
      uint8 databit;
      int h, w, xoff;
      uint16 off;
      
      dstPtr = dst;
      dataPtr = src;
      
      // Skip over the first 'srcRect->top' lines in the data
      h = srcRect.top;
      while (h--) {
            dataPtr += READ_LE_UINT16(dataPtr) + 2;
      }
      h = srcRect.height();
      w = srcRect.width();
      if (h <= 0 || w <= 0)
            return;
            
      while (h--) {
            xoff = srcRect.left;
            off = READ_LE_UINT16(dataPtr);
            w = srcRect.right - srcRect.left;
            dstPtrNext = dstPitch + dstPtr;
            dataPtrNext = off + 2 + dataPtr;
            dataPtr += 2;
            if (off == 0)
                  goto dec_next;

            // Skip over the leftmost 'srcRect->left' pixels.
            // TODO: This code could be merged (at a loss of efficency) with the
            // loop below which does the actual drawing.
            while (xoff > 0) {
                  code = *dataPtr++;
                  databit = code & 1;
                  code >>= 1;
                  if (databit) {
                        xoff -= code;
                        if (xoff < 0) {
                              code = -xoff;
                              goto dec_sub1;
                        }
                  } else {
                        databit = code & 1;
                        code = (code >> 1) + 1;
                        if (databit) {
                              ++dataPtr;
                              xoff -= code;
                              if (xoff < 0) {
                                    code = -xoff;
                                    --dataPtr;
                                    goto dec_sub2;
                              }
                        } else {
                              dataPtr += code;
                              xoff -= code;
                              if (xoff < 0) {
                                    dataPtr += xoff;
                                    code = -xoff;
                                    goto dec_sub3;
                              }
                        }
                  }
            }

            while (w > 0) {
                  code = *dataPtr++;
                  databit = code & 1;
                  code >>= 1;
                  if (databit) {
dec_sub1:         dstPtr += code;
                        w -= code;
                  } else {
                        databit = code & 1;
                        code = (code >> 1) + 1;
                        if (databit) {
dec_sub2:               w -= code;
                              if (w < 0) {
                                    code += w;
                              }
                              uint8 color = *dataPtr++;
                              if (imagePal) {
                                    color = imagePal[color];
                              }
                              memset(dstPtr, color, code);
                              dstPtr += code;
                        } else {
dec_sub3:               w -= code;
                              if (w < 0) {
                                    code += w;
                              }
                              if (imagePal) {
                                    while (code--) {
                                          *dstPtr++ = imagePal[*dataPtr++];
                                    }
                              } else {
                                    memcpy(dstPtr, dataPtr, code);
                                    dstPtr += code;
                                    dataPtr += code;
                              }
                        }
                  }
            }
dec_next:
            dataPtr = dataPtrNext;
            dstPtr = dstPtrNext;
      }
}

int Wiz::isWizPixelNonTransparent(const uint8 *data, int x, int y, int w, int h) {
      if (x < 0 || x >= w || y < 0 || y >= h) {
            return 0;
      }
      while (y != 0) {
            data += READ_LE_UINT16(data) + 2;
            --y;
      }
      uint16 off = READ_LE_UINT16(data); data += 2;
      if (off == 0) {
            return 0;
      }
      while (x > 0) {
            uint8 code = *data++;
            if (code & 1) {
                  code >>= 1;
                  if (code > x) {
                        return 0;
                  }
                  x -= code;
            } else if (code & 2) {
                  code = (code >> 2) + 1;
                  if (code > x) {
                        return 1;
                  }
                  x -= code;
                  ++data;
            } else {
                  code = (code >> 2) + 1;
                  if (code > x) {
                        return 1;
                  }
                  x -= code;
                  data += code;
            }
      }
      return (~data[0]) & 1;
}

uint8 Wiz::getWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 color) {
      if (x < 0 || x >= w || y < 0 || y >= h) {
            return color;
      }
      while (y != 0) {
            data += READ_LE_UINT16(data) + 2;
            --y;
      }
      uint16 off = READ_LE_UINT16(data); data += 2;
      if (off == 0) {
            return color;
      }
      while (x > 0) {
            uint8 code = *data++;
            if (code & 1) {
                  code >>= 1;
                  if (code > x) {
                        return color;
                  }
                  x -= code;
            } else if (code & 2) {
                  code = (code >> 2) + 1;
                  if (code > x) {
                        return data[0];
                  }
                  x -= code;
                  ++data;
            } else {
                  code = (code >> 2) + 1;
                  if (code > x) {
                        return data[x];
                  }
                  x -= code;
                  data += code;
            }
      }
      return (data[0] & 1) ? color : data[1];
}

uint8 Wiz::getRawWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 color) {
      if (x < 0 || x >= w || y < 0 || y >= h) {
            return color;
      }
      return data[y * w + x];
}

void Wiz::computeWizHistogram(uint32 *histogram, const uint8 *data, const Common::Rect *srcRect) {
      int y = srcRect->top;
      while (y != 0) {
            data += READ_LE_UINT16(data) + 2;
            --y;
      }
      int ih = srcRect->height();
      while (ih--) {
            uint16 off = READ_LE_UINT16(data); data += 2;
            if (off != 0) {
                  const uint8 *p = data;
                  int x1 = srcRect->left;
                  int x2 = srcRect->right;
                  uint8 code;
                  while (x1 > 0) {
                        code = *p++;
                        if (code & 1) {
                              code >>= 1;
                              if (code > x1) {
                                    code -= x1;
                                    x2 -= code;
                                    break;
                              }
                              x1 -= code;
                        } else if (code & 2) {
                              code = (code >> 2) + 1;
                              if (code > x1) {
                                    code -= x1;
                                    goto dec_sub2;
                              }
                              x1 -= code;
                              ++p;
                        } else {
                              code = (code >> 2) + 1;
                              if (code > x1) {
                                    code -= x1;
                                    p += x1;
                                    goto dec_sub3;
                              }
                              x1 -= code;
                              p += code;
                        }
                  }
                  while (x2 > 0) {
                        code = *p++;
                        if (code & 1) {
                              code >>= 1;
                              x2 -= code;
                        } else if (code & 2) {
                              code = (code >> 2) + 1;
dec_sub2:               x2 -= code;
                              if (x2 < 0) {
                                    code += x2;
                              }
                              histogram[*p++] += code;
                        } else {
                              code = (code >> 2) + 1;
dec_sub3:               x2 -= code;
                              if (x2 < 0) {
                                    code += x2;
                              }
                              int n = code;
                              while (n--) {
                                    ++histogram[*p++];
                              }
                        }
                  }
                  data += off;
            }
      }
}

void Wiz::computeRawWizHistogram(uint32 *histogram, const uint8 *data, int srcPitch, const Common::Rect *srcRect) {
      data += srcRect->top * srcPitch + srcRect->left;
      int iw = srcRect->width();
      int ih = srcRect->height();
      while (ih--) {
            for (int i = 0; i < iw; ++i) {
                  ++histogram[data[i]];
            }
            data += srcPitch;
      }
}

struct wizPackCtx {
      uint32 len;
      uint8 saveCode;
      uint8 saveBuf[0x100];
};

static void wizPackType1Helper1(uint8 *&dst, int len, byte newColor, byte prevColor, wizPackCtx *ctx) {
      assert(len > 0);
      if (newColor == prevColor) {
            do {
                  int blockLen = MIN(len, 0x7F);
                  len -= blockLen;
                  if (dst) {
                        *dst++ = (blockLen * 2) | 1;
                  }
                  ++ctx->len;
            } while (len > 0);
      } else {
            do {
                  int blockLen = MIN(len, 0x40);
                  len -= blockLen;
                  if (dst) {
                        *dst++ = ((blockLen - 1) * 4) | 2;
                  }
                  ++ctx->len;
                  if (dst) {
                        *dst++ = newColor;
                  }
                  ++ctx->len;
            } while (len > 0);
      }
}

static void wizPackType1Helper2(uint8 *&dst, int len, wizPackCtx *ctx) {
      assert(len > 0);
      const uint8 *src = ctx->saveBuf;
      do {
            int blockLen = MIN(len, 0x40);
            len -= blockLen;
            if (dst) {
                  *dst++ = (blockLen - 1) * 4;
            }
            ++ctx->len;
            while (blockLen--) {
                  if (dst) {
                        *dst++ = *src++;
                  }
                  ++ctx->len;
            }
      } while (len > 0);
}

static int wizPackType1(uint8 *dst, const uint8 *src, int srcPitch, const Common::Rect& rCapt, uint8 tColor) {
      debug(1, "wizPackType1(%d, [%d,%d,%d,%d])", tColor, rCapt.left, rCapt.top, rCapt.right, rCapt.bottom);
      wizPackCtx ctx;
      memset(&ctx, 0, sizeof(ctx));
      
      src += rCapt.top * srcPitch + rCapt.left;
      int w = rCapt.width();
      int h = rCapt.height();
      
      uint8 *nextDstPtr, *curDstPtr;
      uint8 curColor, prevColor;
      int saveBufPos;
      
      nextDstPtr = curDstPtr = 0;
      
      int dataSize = 0;
      while (h--) {
            if (dst) {
                  curDstPtr = dst;
                  nextDstPtr = dst;
                  dst += 2;
            }
            dataSize += 2;
            int numBytes = 0;
            
            int i, code;
            for (i = 0; i < w; ++i) {
                  if (src[i] != tColor)
                        break;
            }
            if (i != w) {
                  curDstPtr = dst;
                  ctx.len = 0;
                  prevColor = ctx.saveBuf[0] = *src;
                  const uint8 *curSrcPtr = src + 1;
                  saveBufPos = 1;
                  code = (tColor - ctx.saveBuf[0] == 0) ? 1 : 0;
                  int curw = w;
                  while (curw--) {
                        ctx.saveBuf[saveBufPos] = curColor = *curSrcPtr++;
                        ++saveBufPos;
                        if (code == 0) {
                              if (curColor == tColor) {
                                    --saveBufPos;
                                    wizPackType1Helper2(curDstPtr, saveBufPos, &ctx);
                                    code = saveBufPos = 1;
                                    ctx.saveBuf[0] = curColor;
                                    numBytes = 0;
                                    prevColor = curColor;
                                    continue;
                              }
                              if (saveBufPos > 0x80) {
                                    --saveBufPos;
                                    wizPackType1Helper2(curDstPtr, saveBufPos, &ctx);
                                    saveBufPos = 1;
                                    ctx.saveBuf[0] = curColor;
                                    numBytes = 0;
                                    prevColor = curColor;
                                    continue;
                              }
                              if (prevColor != curColor) {
                                    numBytes = saveBufPos - 1;
                                    prevColor = curColor;
                                    continue;
                              }
                              code = 1;
                              if (numBytes != 0) {
                                    if (saveBufPos - numBytes < 3) {
                                          code = 0;
                                    } else {
                                          wizPackType1Helper2(curDstPtr, numBytes, &ctx);
                                    }
                              }
                        }
                        if (prevColor != curColor || saveBufPos - numBytes > 0x80) {
                              saveBufPos -= numBytes;
                              --saveBufPos;
                              wizPackType1Helper1(curDstPtr, saveBufPos, prevColor, tColor, &ctx);
                              saveBufPos = 1;
                              numBytes = 0;
                              ctx.saveBuf[0] = curColor;
                              code = (tColor - ctx.saveBuf[0] == 0) ? 1 : 0;
                        }
                        prevColor = curColor;
                  }
                  if (code == 0) {
                        wizPackType1Helper2(curDstPtr, saveBufPos, &ctx);
                  } else {
                        saveBufPos -= numBytes;
                        wizPackType1Helper1(curDstPtr, saveBufPos, prevColor, tColor, &ctx);
                  }
                  dataSize += ctx.len;
                  src += srcPitch;
                  if (dst) {
                        dst += ctx.len;
                        *(uint16 *)nextDstPtr = TO_LE_16(ctx.len);
                  }
            }
      }
      return dataSize;
}

static int wizPackType0(uint8 *dst, const uint8 *src, int srcPitch, const Common::Rect& rCapt, uint8 tColor) {
      int w = rCapt.width();
      int h = rCapt.height();
      int size = w * h;
      if (dst) {
            src += rCapt.top * srcPitch + rCapt.left;
            while (h--) {
                  memcpy(dst, src, w);
                  dst += w;
                  src += srcPitch;
            }
      }
      return size;
}

void ScummEngine_v72he::captureWizImage(int resType, int resNum, const Common::Rect& r, bool frontBuffer, int compType) {
      debug(1, "ScummEngine_v72he::captureWizImage(%d, %d, %d, [%d,%d,%d,%d])", resType, resNum, compType, r.left, r.top, r.right, r.bottom);
      uint8 *src = NULL;
      VirtScreen *pvs = &virtscr[kMainVirtScreen];
      if (frontBuffer) {
            src = pvs->getPixels(0, 0);
      } else {
            src = pvs->getBackPixels(0, 0);
      }
      Common::Rect rCapt(0, 0, pvs->w, pvs->h);
      if (rCapt.intersects(r)) {
            rCapt.clip(r);
            const uint8 *palPtr = _currentPalette;

            int w = rCapt.width();
            int h = rCapt.height();
            int tColor = (VAR_WIZ_TCOLOR != 0xFF) ? VAR(VAR_WIZ_TCOLOR) : 5;

            // compute compressed size
            int dataSize = 0;
            int headerSize = palPtr ? 1080 : 36;
            switch (compType) {
            case 1:
                  dataSize = wizPackType1(0, src, pvs->pitch, rCapt, tColor);
                  break;
            case 0:
                  dataSize = wizPackType0(0, src, pvs->pitch, rCapt, tColor);
                  break;
            default:
                  warning("unhandled compression type %d", compType);
                  break;
            }

            // alignment
            dataSize = (dataSize + 1) & ~1;
            int wizSize = headerSize + dataSize;
            // write header
            uint8 *wizImg = createResource(resType, resNum, dataSize + headerSize);
            *(uint32 *)(wizImg + 0x00) = MKID('AWIZ');
            *(uint32 *)(wizImg + 0x04) = TO_BE_32(wizSize);
            *(uint32 *)(wizImg + 0x08) = MKID('WIZH');
            *(uint32 *)(wizImg + 0x0C) = TO_BE_32(0x14);
            *(uint32 *)(wizImg + 0x10) = TO_LE_32(compType);
            *(uint32 *)(wizImg + 0x14) = TO_LE_32(w);
            *(uint32 *)(wizImg + 0x18) = TO_LE_32(h);
            int curSize = 0x1C;
            if (palPtr) {
                  *(uint32 *)(wizImg + 0x1C) = MKID('RGBS');
                  *(uint32 *)(wizImg + 0x20) = TO_BE_32(0x308);
                  memcpy(wizImg + 0x24, palPtr, 0x300);
                  *(uint32 *)(wizImg + 0x324) = MKID('RMAP');
                  *(uint32 *)(wizImg + 0x328) = TO_BE_32(0x10C);
                  *(uint32 *)(wizImg + 0x32C) = 0;
                  curSize = 0x330;
                  for (int i = 0; i < 256; ++i) {
                        wizImg[curSize] = i;
                        ++curSize;
                  }
            }
            *(uint32 *)(wizImg + curSize + 0x0) = MKID('WIZD');
            *(uint32 *)(wizImg + curSize + 0x4) = TO_BE_32(dataSize + 8);
            curSize += 8;

            // write compressed data
            switch (compType) {
            case 1:
                  wizPackType1(wizImg + headerSize, src, pvs->pitch, rCapt, tColor);
                  break;
            case 0:
                  wizPackType0(wizImg + headerSize, src, pvs->pitch, rCapt, tColor);
                  break;
            default:
                  break;
            }
      }
}

void ScummEngine_v72he::displayWizImage(const WizImage *pwi) {
      if (_fullRedraw) {
            assert(_wiz._imagesNum < ARRAYSIZE(_wiz._images));
            memcpy(&_wiz._images[_wiz._imagesNum], pwi, sizeof(WizImage));
            ++_wiz._imagesNum;
      } else if (pwi->flags & 0x40) {
            drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags);
      } else {
            drawWizImage(rtImage, pwi);
      }
}

void ScummEngine_v72he::getWizImageDim(int resnum, int state, int32 &w, int32 &h) {
      const uint8 *dataPtr = getResourceAddress(rtImage, resnum);
      if (dataPtr) {
            const uint8 *wizh = findWrappedBlock(MKID('WIZH'), dataPtr, state, 0);
            w = READ_LE_UINT32(wizh + 0x4);
            h = READ_LE_UINT32(wizh + 0x8);
      } else {
            w = 0;
            h = 0;
      }
}

uint8 *ScummEngine_v72he::drawWizImage(int restype, const WizImage *pwi) {
      debug(1, "drawWizImage(%d, %d, %d, %d, 0x%X)", restype, pwi->resNum, pwi->x1, pwi->y1, pwi->flags);
      uint8 *dst = NULL;
      const uint8 *dataPtr = getResourceAddress(restype, pwi->resNum);
      if (dataPtr) {
            const uint8 *rmap = NULL;
            const uint8 *xmap = findWrappedBlock(MKID('XMAP'), dataPtr, pwi->state, 0);
            
            const uint8 *wizh = findWrappedBlock(MKID('WIZH'), dataPtr, pwi->state, 0);
            assert(wizh);
            uint32 comp   = READ_LE_UINT32(wizh + 0x0);
            uint32 width  = READ_LE_UINT32(wizh + 0x4);
            uint32 height = READ_LE_UINT32(wizh + 0x8);
            assert(comp == 0 || comp == 1 || comp == 2 || comp == 3 || comp == 10 || comp == 11);
            
            const uint8 *wizd = findWrappedBlock(MKID('WIZD'), dataPtr, pwi->state, 0);
            assert(wizd);
            if (pwi->flags & 1) {
                  const uint8 *pal = findWrappedBlock(MKID('RGBS'), dataPtr, pwi->state, 0);
                  assert(pal);
                  setPaletteFromPtr(pal, 256);
            }
            if (pwi->flags & 2) {
                  rmap = findWrappedBlock(MKID('RMAP'), dataPtr, pwi->state, 0);
                  assert(rmap);
                  const uint8 *rgbs = findWrappedBlock(MKID('RGBS'), dataPtr, pwi->state, 0);
                  assert(rgbs);
                  warning("drawWizImage() unhandled flag 0x2");
                  // XXX modify 'RMAP' buffer
            }
            if (pwi->flags & 4) {
                  warning("WizImage printing is unimplemented");
                  return NULL;
            }
            uint32 cw, ch;
            if (pwi->flags & 0x20) {
                  dst = (uint8 *)malloc(width * height);
                  int color = 255; // FIXME: should be (VAR_WIZ_TCOLOR != 0xFF) ? VAR(VAR_WIZ_TCOLOR) : 5;
                  memset(dst, color, width * height);
                  cw = width;
                  ch = height;
            } else {
                  VirtScreen *pvs = &virtscr[kMainVirtScreen];
                  if (pwi->flags & 0x10) {
                        dst = pvs->getPixels(0, pvs->topline);
                  } else {
                        dst = pvs->getBackPixels(0, pvs->topline);
                  }
                  cw = pvs->w;
                  ch = pvs->h;
            }
            Common::Rect rScreen(cw, ch);
            // XXX handle 'XMAP' / 'RMAP' data
            if (comp == 1) {
                  if (pwi->flags & 0x80) {
                        warning("drawWizImage() unhandled flag 0x80");
                  } else if (pwi->flags & 0x100) {
                        warning("drawWizImage() unhandled flag 0x100");
                  } else {
                        _wiz.copyWizImage(dst, wizd, cw, ch, pwi->x1, pwi->y1, width, height, &rScreen);
                  }
            } else if (comp == 0 || comp == 2 || comp == 3) {
                  const uint8 *trns = findWrappedBlock(MKID('TRNS'), dataPtr, pwi->state, 0);
                  int color = (trns == NULL) ? VAR(VAR_WIZ_TCOLOR) : -1;
                  const uint8 *pal = xmap;
                  if (pwi->flags & 2) {
                        pal = rmap + 4;
                  }
                  _wiz.copyRawWizImage(dst, wizd, cw, ch, pwi->x1, pwi->y1, width, height, &rScreen, pwi->flags, pal, color);
            } else {
                  warning("unhandled wiz compression type %d", comp);
            }

            if (!(pwi->flags & 0x20)) {
                  Common::Rect rImage(pwi->x1, pwi->y1, pwi->x1 + width, pwi->y1 + height);
                  if (rImage.intersects(rScreen)) {
                        rImage.clip(rScreen);
                        if (!(pwi->flags & 8) && pwi->flags & 0x18) {
                              ++rImage.bottom;
                              markRectAsDirty(kMainVirtScreen, rImage);
                        } else {
                              gdi.copyVirtScreenBuffers(rImage);
                        }
                  }
            }
      }
      return dst;
}

struct PolygonDrawData {
      struct InterArea {
            bool valid;
            int32 xmin;
            int32 xmax;
            int32 x1;
            int32 y1;
            int32 x2;
            int32 y2;
      };
      Common::Point pto;
      InterArea *ia;
      int areasNum;
      
      PolygonDrawData(int n) {
            areasNum = n;
            ia = new InterArea[areasNum];
            memset(ia, 0, sizeof(InterArea) * areasNum);
      }
      
      ~PolygonDrawData() {
            delete[] ia;
      }
      
      void calcIntersection(const Common::Point *p1, const Common::Point *p2, const Common::Point *p3, const Common::Point *p4) {
            int32 x1_acc = p1->x << 0x10;
            int32 x3_acc = p3->x << 0x10;
            int32 y3_acc = p3->y << 0x10;
            uint16 dy = ABS(p2->y - p1->y) + 1;
            int32 x1_step = ((p2->x - p1->x) << 0x10) / dy;
            int32 x3_step = ((p4->x - p3->x) << 0x10) / dy;
            int32 y3_step = ((p4->y - p3->y) << 0x10) / dy;

            int iaidx = p1->y - pto.y;
            while (dy--) {
                  assert(iaidx >= 0 && iaidx < areasNum);
                  InterArea *pia = &ia[iaidx];
                  int32 tx1 = x1_acc >> 0x10;
                  int32 tx3 = x3_acc >> 0x10;
                  int32 ty3 = y3_acc >> 0x10;
                  
                  if (!pia->valid || pia->xmin > tx1) {
                        pia->xmin = tx1;
                        pia->x1 = tx3;
                        pia->y1 = ty3;
                  }
                  if (!pia->valid || pia->xmax < tx1) {
                        pia->xmax = tx1;
                        pia->x2 = tx3;
                        pia->y2 = ty3;
                  }
                  pia->valid = true;

                  x1_acc += x1_step;
                  x3_acc += x3_step;
                  y3_acc += y3_step;
                  
                  if (p2->y <= p1->y) {
                        --iaidx;
                  } else {
                        ++iaidx;
                  }                 
            }
      }
};

void ScummEngine_v72he::drawWizPolygon(int resnum, int state, int id, int flags) {
      int i;
      WizPolygon *wp = NULL;
      for (i = 0; i < ARRAYSIZE(_wiz._polygons); ++i) {
            if (_wiz._polygons[i].id == id) {
                  wp = &_wiz._polygons[i];
                  break;
            }
      }
      if (!wp) {
            error("Polygon %d is not defined", id);
      }
      if (wp->numVerts != 5) {
            error("Invalid point count %d for Polygon %d", wp->numVerts, id);
      }
      WizImage wi;
      wi.resNum = resnum;
      wi.state = state;
      wi.x1 = wi.y1 = 0;
      wi.flags = 0x20;
      uint8 *srcWizBuf = drawWizImage(rtImage, &wi);
      if (srcWizBuf) {
            uint8 *dst;
            VirtScreen *pvs = &virtscr[kMainVirtScreen];
            if (flags & 0x10) {
                  dst = pvs->getPixels(0, 0);
            } else {
                  dst = pvs->getBackPixels(0, 0);
            }
            if (wp->bound.left < 0 || wp->bound.top < 0 || wp->bound.right >= pvs->w || wp->bound.bottom >= pvs->h) {
                  error("Invalid coords polygon %d", wp->id);
            }

            int32 wizW, wizH;
            getWizImageDim(resnum, state, wizW, wizH);
            Common::Point bbox[4];
            bbox[0].x = 0;
            bbox[0].y = 0;
            bbox[1].x = wizW - 1;
            bbox[1].y = 0;
            bbox[2].x = wizW - 1;
            bbox[2].y = wizH - 1;
            bbox[3].x = 0;
            bbox[3].y = wizH - 1;

            int16 xmin_p, xmax_p, ymin_p, ymax_p;
            xmin_p = xmax_p = wp->vert[0].x;
            ymin_p = ymax_p = wp->vert[0].y;
            for (i = 1; i < 4; ++i) {
                  xmin_p = MIN(wp->vert[i].x, xmin_p);
                  xmax_p = MAX(wp->vert[i].x, xmax_p);
                  ymin_p = MIN(wp->vert[i].y, ymin_p);
                  ymax_p = MAX(wp->vert[i].y, ymax_p);
            }
            
            int16 xmin_b, xmax_b, ymin_b, ymax_b;
            xmin_b = 0;
            xmax_b = wizW - 1;
            ymin_b = 0;
            ymax_b = wizH - 1;

            PolygonDrawData pdd(ymax_p - ymin_p + 1);
            pdd.pto.x = xmin_p;
            pdd.pto.y = ymin_p;
            
            for (i = 0; i < 3; ++i) {
                  pdd.calcIntersection(&wp->vert[i], &wp->vert[i + 1], &bbox[i], &bbox[i + 1]);
            }
            pdd.calcIntersection(&wp->vert[3], &wp->vert[0], &bbox[3], &bbox[0]);
                        
            uint yoff = pdd.pto.y * pvs->w;
            for (i = 0; i < pdd.areasNum; ++i) {
                  PolygonDrawData::InterArea *pia = &pdd.ia[i];
                  uint16 dx = pia->xmax - pia->xmin + 1;
                  uint8 *dstPtr = dst + pia->xmin + yoff;
                  int32 x_acc = pia->x1 << 0x10;
                  int32 y_acc = pia->y1 << 0x10;
                  int32 x_step = ((pia->x2 - pia->x1) << 0x10) / dx;
                  int32 y_step = ((pia->y2 - pia->y1) << 0x10) / dx;
                  while (dx--) {
                        uint srcWizOff = (y_acc >> 0x10) * wizW + (x_acc >> 0x10);
                        assert(srcWizOff < (uint32)(wizW * wizH));
                        x_acc += x_step;
                        y_acc += y_step;
                        *dstPtr++ = srcWizBuf[srcWizOff];
                  }
                  yoff += pvs->pitch;
            }

            if (flags & 0x10) {
                  markRectAsDirty(kMainVirtScreen, wp->bound);
            } else {
                  gdi.copyVirtScreenBuffers(wp->bound);
            }

            free(srcWizBuf);
      }
}

void ScummEngine_v72he::flushWizBuffer() {
      for (int i = 0; i < _wiz._imagesNum; ++i) {
            WizImage *pwi = &_wiz._images[i];
            if (pwi->flags & 0x40) {
                  drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags);
            } else {
                  drawWizImage(rtImage, pwi);
            }
      }
      _wiz._imagesNum = 0;
}

void ScummEngine_v80he::loadImgSpot(int resId, int state, int16 &x, int16 &y) {
      const uint8 *dataPtr = getResourceAddress(rtImage, resId);
      if (!dataPtr) {
            warning("loadImgSpot: unknown Image %d", resId);
            x = y = 0;
            return;
      }

      const uint8 *spotPtr = findWrappedBlock(MKID('SPOT'), dataPtr, state, 0);
      if (spotPtr) {
            x = (int16)READ_LE_UINT32(spotPtr + 0);
            y = (int16)READ_LE_UINT32(spotPtr + 4);
      } else {
            x = 0;
            y = 0;
      }
}

void ScummEngine_v80he::loadWizCursor(int resId, int resType, bool state) {
      int16 x, y;
      loadImgSpot(resId, 0, x, y);
      if (x < 0) {
            x = 0;
      } else if (x > 32) {
            x = 32;
      }
      if (y < 0) {
            y = 0;
      } else if (y > 32) {
            y = 32;
      }

      WizImage wi;
      wi.resNum = resId;
      wi.x1 = wi.y1 = 0;
      wi.state = 0;
      wi.flags = 0x20;  
      uint8 *cursor = drawWizImage(rtImage, &wi);
      int32 cw, ch;     
      getWizImageDim(resId, 0, cw, ch);
      setCursorFromBuffer(cursor, cw, ch, cw);
      setCursorHotspot(x, y);
      free(cursor);
}

void ScummEngine_v90he::drawWizComplexPolygon(int resnum, int state, int po_x, int po_y, int arg14, int angle, int zoom, const Common::Rect *r) {
      Common::Point pts[4];
      int32 w, h;
      getWizImageDim(resnum, state, w, h);

      pts[1].x = pts[2].x = w / 2 - 1;
      pts[0].x = pts[0].y = pts[1].y = pts[3].x = -w / 2;
      pts[2].y = pts[3].y = h / 2 - 1;

      // transform points
      if (zoom != 256) {
            for (int i = 0; i < 4; ++i) {
                  pts[i].x = pts[i].x * zoom / 256;
                  pts[i].y = pts[i].y * zoom / 256;
            }
      }
      if (angle != 0) {
            double alpha = angle * PI / 180.;
            double cos_alpha = cos(alpha);
            double sin_alpha = sin(alpha);
            for (int i = 0; i < 4; ++i) {
                  int16 x = pts[i].x;
                  int16 y = pts[i].y;
                  pts[i].x = (int16)(x * cos_alpha - y * sin_alpha);
                  pts[i].y = (int16)(y * cos_alpha + x * sin_alpha);
            }
      }
      for (int i = 0; i < 4; ++i) {
            pts[i].x += po_x;
            pts[i].y += po_y;
      }
      // XXX drawWizPolygonPoints(resnum, state, pts, r, VAR(117));
      warning("ScummEngine_v90he::drawWizComplexPolygon() partially implemented");
}

void ScummEngine_v90he::displayWizComplexImage(const WizParameters *params) {
      // XXX merge with ScummEngine_v72he::displayWizImage
      int zoom = 256;
      if (params->processFlags & 0x8) {
            zoom = params->zoom;
      }
      int rotationAngle = 0;
      if (params->processFlags & 0x10) {
            rotationAngle = params->angle;
      }
      int state = 0;
      if (params->processFlags & 0x400) {
            state = params->img.state;
      }
      int flags = 0;
      if (params->processFlags & 0x20) {
            flags = params->img.flags;
      }
      int po_x = 0;
      int po_y = 0;
      if (params->processFlags & 0x1) {
            po_x = params->img.x1;
            po_y = params->img.y1;
      }
      int unk = 0;
      if (params->processFlags & 0x4) {
            unk = params->unk_15C;
      }
      const Common::Rect *r = NULL;
      if (params->processFlags & 0x200) {
            r = &params->box;
      }

      if (_fullRedraw) {
            assert(_wiz._imagesNum < ARRAYSIZE(_wiz._images));
            WizImage *pwi = &_wiz._images[_wiz._imagesNum];
            pwi->resNum = params->img.resNum;
            pwi->x1 = po_x;
            pwi->y1 = po_y;
            pwi->state = state;
            pwi->flags = flags;
            pwi->unk = unk;
            ++_wiz._imagesNum;
      } else if (params->processFlags & 0x18) {
            drawWizComplexPolygon(params->img.resNum, state, po_x, po_y, unk, rotationAngle, zoom, r);
      } else if (flags & 0x40) {
            drawWizPolygon(params->img.resNum, state, po_x, flags); // XXX , VAR(117));
      } else {
            if ((flags & 0x200) || (flags & 0x24)) {
                  warning("ScummEngine_v90he::displayWizComplexImage() unhandled flags = 0x%X", flags);
            }
            // XXX flags 0x200, 0x24
            WizImage wi;
            wi.resNum = params->img.resNum;
            wi.x1 = po_x;
            wi.y1 = po_y;
            wi.state = state;
            wi.flags = flags;
            wi.unk = unk;
            drawWizImage(rtImage, &wi);
      }
}

void ScummEngine_v90he::createWizEmptyImage(const WizParameters *params) {
      debug(1, "ScummEngine_v90he::createWizEmptyImage(%d, %d, %d)", params->img.resNum, params->resDefImgW, params->resDefImgH);
      int img_w = 640;
      if (params->processFlags & 0x2000) {
            img_w = params->resDefImgW;
      }
      int img_h = 480;
      if (params->processFlags & 0x4000) {
            img_h = params->resDefImgH;
      }
      int img_x = 0;
      int img_y = 0;
      if (params->processFlags & 1) {
            img_x = params->img.x1;
            img_y = params->img.y1;
      }
      const uint16 flags = 0xB;
      int res_size = 0x1C;
      if (flags & 1) {
            res_size += 0x308;
      }
      if (flags & 2) {
            res_size += 0x10;
      }
      if (flags & 8) {
            res_size += 0x10C;
      }
      res_size += 8 + img_w * img_h;
      
      uint8 *res_data = createResource(rtImage, params->img.resNum, res_size);
      if (!res_data) {
            VAR(119) = -1;
      } else {
            VAR(119) = 0;
            WRITE_BE_UINT32(res_data, 'AWIZ'); res_data += 4;
            WRITE_BE_UINT32(res_data, res_size); res_data += 4;
            WRITE_BE_UINT32(res_data, 'WIZH'); res_data += 4;
            WRITE_BE_UINT32(res_data, 0x14); res_data += 4;
            WRITE_LE_UINT32(res_data, 0); res_data += 4;
            WRITE_LE_UINT32(res_data, img_w); res_data += 4;
            WRITE_LE_UINT32(res_data, img_h); res_data += 4;
            if (flags & 1) {
                  WRITE_BE_UINT32(res_data, 'RGBS'); res_data += 4;
                  WRITE_BE_UINT32(res_data, 0x308); res_data += 4;
                  memcpy(res_data, _currentPalette, 0x300); res_data += 0x300;                  
            }
            if (flags & 2) {
                  WRITE_BE_UINT32(res_data, 'SPOT'); res_data += 4;
                  WRITE_BE_UINT32(res_data, 0x10); res_data += 4;
                  WRITE_BE_UINT32(res_data, img_x); res_data += 4;
                  WRITE_BE_UINT32(res_data, img_y); res_data += 4;
            }
            if (flags & 8) {
                  WRITE_BE_UINT32(res_data, 'RMAP'); res_data += 4;
                  WRITE_BE_UINT32(res_data, 0x10C); res_data += 4;
                  WRITE_BE_UINT32(res_data, 0); res_data += 4;
                  for (int i = 0; i < 0x100; ++i) {
                        *res_data++ = i;
                  }
            }
            WRITE_BE_UINT32(res_data, 'WIZD'); res_data += 4;
            WRITE_BE_UINT32(res_data, 8 + img_w * img_h); res_data += 4;
      }
}

void ScummEngine_v90he::fillWizRect(const WizParameters *params) {
      int state = 0;
      if (params->processFlags & 0x400) {
            state = params->img.state;
      }
      uint8 *dataPtr = getResourceAddress(rtImage, params->img.resNum);
      if (dataPtr) {    
            const uint8 *wizh = findWrappedBlock(MKID('WIZH'), dataPtr, state, 0);
            assert(wizh);
            uint32 ic = READ_LE_UINT32(wizh + 0x0);
            uint32 iw = READ_LE_UINT32(wizh + 0x4);
            uint32 ih = READ_LE_UINT32(wizh + 0x8);
            assert(ic == 0 || ic == 2 || ic == 3);    
            Common::Rect r1(iw, ih);
            if (params->processFlags & 0x200) {
                  if (!r1.intersects(params->box)) {
                        return;
                  }
                  r1.clip(params->box);
            }
            if (params->processFlags & 0x40000) {
                  r1.clip(params->box2);
            }
            uint8 color;
            if (params->processFlags & 0x20000) {
                  color = params->fillColor;
            } else {
                  color = VAR(93);
            }
            /*
            uint8 *wizd = findWrappedBlock(MKID('WIZD'), dataPtr, state, 0);
            assert(wizd);
            int dx = r1.width();
            int dy = r1.height();
            wizd += r1.top * iw + r1.left;
            while (dy--) {
                  memset(wizd, color, dx);
                  wizd += iw;
            } 
            */    
}
}

void ScummEngine_v90he::processWizImage(const WizParameters *params) {
      debug(1, "ScummEngine_v90he::processWizImage()");
      switch (params->processMode) {
      case 1:
            displayWizComplexImage(params);
            break;
      case 2:
            captureWizImage(rtImage, params->img.resNum, params->box, (params->img.flags & 8) == 8, params->compType);
            break;
      case 3:
            if (params->processFlags & 0x800) {
                  File f;
                  if (!f.open((const char *)params->filename, File::kFileReadMode)) {
                        warning("Unable to open for read '%s'", params->filename);
                  } else {
                        uint32 id = f.readUint32BE();
                        if (id != MKID('AWIZ') && id != MKID('MULT')) {
                              VAR(VAR_GAME_LOADED) = -1;
                        } else {
                              uint32 size = f.readUint32BE();
                              f.seek(0, SEEK_SET);
                              byte *p = createResource(rtImage, params->img.resNum, size);
                              if (f.read(p, size) != size) {
                                    nukeResource(rtImage, params->img.resNum);
                                    warning("i/o error when reading '%s'", params->filename);
                                    VAR(VAR_GAME_LOADED) = -2;
                              } else {
                                    VAR(VAR_GAME_LOADED) = 0;
                              }
                        }
                        f.close();
                  }
            }
            break;
      case 4:
            if (params->processFlags & 0x800) {
                  if (params->unk_14C != 0) {
                        VAR(119) = -1;
                  } else {
                        File f;
                        if (!f.open((const char *)params->filename, File::kFileWriteMode)) {
                              warning("Unable to open for write '%s'", params->filename);
                              VAR(119) = -3;
                        } else {
                              byte *p = getResourceAddress(rtImage, params->img.resNum);
                              uint32 size = READ_BE_UINT32(p + 4);
                              if (f.write(p, size) != size) {
                                    warning("i/o error when writing '%s'", params->filename);
                                    VAR(119) = -2;
                              } else {
                                    VAR(119) = 0;
                              }
                              f.close();
                        }
                  }
            }
            break;
      case 8:
            createWizEmptyImage(params);
            break;
      case 9:
            fillWizRect(params);
            break;
      default:
            warning("invalid processWizImage mode %d", params->processMode);
      }
}

int ScummEngine_v90he::getWizImageStates(int resnum) {
      const uint8 *dataPtr = getResourceAddress(rtImage, resnum);
      assert(dataPtr);
      if (READ_UINT32(dataPtr) == MKID('MULT')) {
            const byte *offs, *wrap;

            wrap = findResource(MKID('WRAP'), dataPtr);
            if (wrap == NULL)
                  return 1;

            offs = findResourceData(MKID('OFFS'), wrap);
            if (offs == NULL)
                  return 1;

            return getResourceDataSize(offs) / 4;
      } else {
            return 1;
      }
}

int ScummEngine_v90he::isWizPixelNonTransparent(int restype, int resnum, int state, int x, int y, int flags) {
      int ret = 0;
      const uint8 *data = getResourceAddress(restype, resnum);
      assert(data);
      const uint8 *wizh = findWrappedBlock(MKID('WIZH'), data, state, 0);
      assert(wizh);
      uint32 c = READ_LE_UINT32(wizh + 0x0);
      int w = READ_LE_UINT32(wizh + 0x4);
      int h = READ_LE_UINT32(wizh + 0x8);
      const uint8 *wizd = findWrappedBlock(MKID('WIZD'), data, state, 0);
      assert(wizd);
      if (x >= 0 && x < w && y >= 0 && y < h) {
            if (flags & 0x400) {
                  x = w - x - 1;
            }
            if (flags & 0x800) {
                  y = h - y - 1;
            }
            if (c == 1) {
                  ret = _wiz.isWizPixelNonTransparent(wizd, x, y, w, h);
            } else if (c == 0 || c == 2 || c == 3) {
                  ret = _wiz.getRawWizPixelColor(wizd, x, y, w, h, VAR(VAR_WIZ_TCOLOR)) != VAR(VAR_WIZ_TCOLOR) ? 1 : 0;
            }
      }
      return ret;
}

uint8 ScummEngine_v90he::getWizPixelColor(int restype, int resnum, int state, int x, int y, int flags) {
      uint8 color;
      const uint8 *data = getResourceAddress(restype, resnum);
      assert(data);
      const uint8 *wizh = findWrappedBlock(MKID('WIZH'), data, state, 0);
      assert(wizh);
      uint32 c = READ_LE_UINT32(wizh + 0x0);
      uint32 w = READ_LE_UINT32(wizh + 0x4);
      uint32 h = READ_LE_UINT32(wizh + 0x8);
      const uint8 *wizd = findWrappedBlock(MKID('WIZD'), data, state, 0);
      assert(wizd);           
      if (c == 1) {
            color = _wiz.getWizPixelColor(wizd, x, y, w, h, VAR(VAR_WIZ_TCOLOR));
      } else if (c == 0 || c == 2 || c == 3) {
            color = _wiz.getRawWizPixelColor(wizd, x, y, w, h, VAR(VAR_WIZ_TCOLOR));
      } else {
            color = VAR(VAR_WIZ_TCOLOR);
      }
      return color;
}

int ScummEngine_v90he::computeWizHistogram(int resnum, int state, int x, int y, int w, int h) {
      writeVar(0, 0);
      defineArray(0, kDwordArray, 0, 0, 0, 255);
      if (readVar(0) != 0) {
            const uint8 *data = getResourceAddress(rtImage, resnum);
            assert(data);
            const uint8 *wizh = findWrappedBlock(MKID('WIZH'), data, state, 0);
            assert(wizh);
            uint32 ic = READ_LE_UINT32(wizh + 0x0);
            uint32 iw = READ_LE_UINT32(wizh + 0x4);
            uint32 ih = READ_LE_UINT32(wizh + 0x8);
            const uint8 *wizd = findWrappedBlock(MKID('WIZD'), data, state, 0);
            assert(wizd);
            Common::Rect rWiz(iw, ih);
            Common::Rect rCap(x, y, w + 1, h + 1);
            if (rCap.intersects(rWiz)) {
                  rCap.clip(rWiz);
                  uint32 histogram[0x100];
                  memset(histogram, 0, sizeof(histogram));
                  if (ic == 1) {
                        _wiz.computeWizHistogram(histogram, wizd, &rCap);
                  } else if (ic == 0 || ic == 2 || ic == 3) {
                        _wiz.computeRawWizHistogram(histogram, wizd, w, &rCap);
                  } else {
                        warning("Unable to return histogram for type %d", ic);
                  }
                  for (int i = 0; i < 0x100; ++i) {
                        writeArray(0, 0, i, histogram[i]);
                  }
            }
      }
      return readVar(0);
}

} // End of namespace Scumm

Generated by  Doxygen 1.6.0   Back to index