aboutsummaryrefslogtreecommitdiff
path: root/scumm
diff options
context:
space:
mode:
authorGregory Montoir2004-11-27 17:50:23 +0000
committerGregory Montoir2004-11-27 17:50:23 +0000
commit5e351b0c312a921f9e2e8090462afec5cce7dbb1 (patch)
treea296ddd9e2256768d6d36d4d793a2befd78dd751 /scumm
parentb92b8e8d6aa4108663e309cef08e5bbae609f734 (diff)
downloadscummvm-rg350-5e351b0c312a921f9e2e8090462afec5cce7dbb1.tar.gz
scummvm-rg350-5e351b0c312a921f9e2e8090462afec5cce7dbb1.tar.bz2
scummvm-rg350-5e351b0c312a921f9e2e8090462afec5cce7dbb1.zip
moved all the HE wiz stuff to a separate module, with minor cleanups and simplifications
svn-id: r15921
Diffstat (limited to 'scumm')
-rw-r--r--scumm/actor.cpp2
-rw-r--r--scumm/akos.cpp5
-rw-r--r--scumm/charset.cpp8
-rw-r--r--scumm/gfx.cpp467
-rw-r--r--scumm/gfx.h12
-rw-r--r--scumm/intern.h46
-rw-r--r--scumm/module.mk1
-rw-r--r--scumm/saveload.cpp2
-rw-r--r--scumm/script_v72he.cpp536
-rw-r--r--scumm/script_v7he.cpp103
-rw-r--r--scumm/script_v80he.cpp46
-rw-r--r--scumm/script_v90he.cpp274
-rw-r--r--scumm/scumm.cpp14
-rw-r--r--scumm/scumm.h16
-rw-r--r--scumm/wiz_he.cpp1392
-rw-r--r--scumm/wiz_he.h111
16 files changed, 1529 insertions, 1506 deletions
diff --git a/scumm/actor.cpp b/scumm/actor.cpp
index 9609ae41ef..6d6f953d3c 100644
--- a/scumm/actor.cpp
+++ b/scumm/actor.cpp
@@ -1921,7 +1921,7 @@ void ScummEngine::postProcessAuxQueue() {
uint8 *dst2 = pvs->getBackPixels(0, pvs->topline);
switch (comp) {
case 1:
- gdi.copyAuxImage(dst1, dst2, axfd + 10, pvs->w, pvs->h, x, y, w, h, NULL);
+ _wiz.copyAuxImage(dst1, dst2, axfd + 10, pvs->w, pvs->h, x, y, w, h);
break;
default:
warning("unimplemented compression type %d", comp);
diff --git a/scumm/akos.cpp b/scumm/akos.cpp
index bf615c6fe1..48b4e09c43 100644
--- a/scumm/akos.cpp
+++ b/scumm/akos.cpp
@@ -1234,10 +1234,7 @@ byte AkosRenderer::codec32(int xmoveCur, int ymoveCur) {
_draw_bottom = dst.bottom;
byte *dstPtr = (byte *)_out.pixels + dst.left + dst.top * _out.pitch;
-
- for (int i = 0; i < 256; i++)
- _vm->gdi._wizImagePalette[i] = i;
- _vm->gdi.decompressWizImage(dstPtr, _out.pitch, dst, _srcptr, src);
+ _vm->_wiz.decompressWizImage(dstPtr, _out.pitch, dst, _srcptr, src);
return 0;
}
diff --git a/scumm/charset.cpp b/scumm/charset.cpp
index 76128abc7f..b997110a65 100644
--- a/scumm/charset.cpp
+++ b/scumm/charset.cpp
@@ -1394,10 +1394,10 @@ void CharsetRendererClassic::printChar(int chr) {
src = dst;
src.moveTo(0, 0);
- memset(_vm->gdi._wizImagePalette, 255, sizeof(_vm->gdi._wizImagePalette));
- memcpy(_vm->gdi._wizImagePalette, _vm->_charsetColorMap, 16);
-
- _vm->gdi.decompressWizImage(dstPtr, vs->w, dst, charPtr, src);
+ byte imagePalette[256];
+ memset(imagePalette, 255, sizeof(imagePalette));
+ memcpy(imagePalette, _vm->_charsetColorMap, 16);
+ _vm->_wiz.decompressWizImage(dstPtr, vs->w, dst, charPtr, src, imagePalette);
if (_blitAlso && vs->hasTwoBuffers)
_vm->gdi.copyVirtScreenBuffers(dst);
diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp
index a98f4cf13e..96405490e5 100644
--- a/scumm/gfx.cpp
+++ b/scumm/gfx.cpp
@@ -1437,7 +1437,7 @@ void Gdi::drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y,
if (code == 8 || code == 9) {
Common::Rect rScreen(0, 0, vs->w, vs->h);
byte *dst = (byte *)_vm->virtscr[0].backBuf + scrX;
- copyWizImage(dst, bmap_ptr, vs->w, vs->h, x - scrX, y, w, h, &rScreen);
+ _vm->_wiz.copyWizImage(dst, bmap_ptr, vs->w, vs->h, x - scrX, y, w, h, &rScreen);
}
Common::Rect rect1(x, y, x + w, y + h);
@@ -1453,471 +1453,6 @@ void Gdi::drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y,
}
}
-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 Gdi::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)) {
- for (int i = 0; i < 256; i++)
- _wizImagePalette[i] = i;
- dst += r2.left + r2.top * dstw;
- decompressWizImage(dst, dstw, r2, src, r1);
- }
-}
-
-void Gdi::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;
- }
- if (!palPtr) {
- for (int i = 0; i < 256; i++) {
- _wizImagePalette[i] = i;
- }
- palPtr = _wizImagePalette;
- }
- int h = r1.height();
- int w = r1.width();
- dst += r2.left + r2.top * dstw;
- while (h--) {
- for (int i = 0; i < w; ++i) {
- uint8 col = *src++;
- if (transColor == -1 || transColor != col) {
- dst[i] = palPtr[col];
- }
- }
- dst += dstw;
- }
- }
-}
-
-void Gdi::decompressWizImage(uint8 *dst, int dstPitch, const Common::Rect &dstRect, const uint8 *src, const Common::Rect &srcRect) {
- const uint8 *dataPtr, *dataPtrNext;
- uint8 *dstPtr, *dstPtrNext;
- uint32 code;
- uint8 databit;
- int h, w, xoff;
- uint16 off;
- int color;
-
- 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();
- if (h <= 0)
- return;
- w = srcRect.width();
- if (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;
- }
- color = _wizImagePalette[*dataPtr++];
- memset(dstPtr, color, code);
- dstPtr += code;
- } else {
-dec_sub3: w -= code;
- if (w < 0) {
- code += w;
- }
- while (code--) {
- color = _wizImagePalette[*dataPtr++];
- *dstPtr++ = color;
- }
- }
- }
- }
-dec_next:
- dataPtr = dataPtrNext;
- dstPtr = dstPtrNext;
- }
-}
-
-int Gdi::isWizPixelNonTransparent(const uint8 *data, int x, int y, int w, int h) {
- int ret = 0;
- while (y != 0) {
- data += READ_LE_UINT16(data) + 2;
- --y;
- }
- uint16 off = READ_LE_UINT16(data); data += 2;
- if (off != 0) {
- if (x == 0) {
- ret = (~*data) & 1;
- } else {
- do {
- uint8 code = *data++;
- if (code & 1) {
- code >>= 1;
- if (code > x) {
- ret = 0;
- break;
- }
- x -= code;
- } else if (code & 2) {
- code = (code >> 2) + 1;
- if (code > x) {
- ret = 1;
- break;
- }
- x -= code;
- ++data;
- } else {
- code = (code >> 2) + 1;
- if (code > x) {
- ret = 1;
- break;
- }
- x -= code;
- data += code;
- }
- } while (x > 0);
- }
- }
- return ret;
-}
-
-uint8 Gdi::getRawWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 color) {
- uint8 c;
- if (x >= 0 && x < w && y >= 0 && y < h) {
- c = *(data + y * w + x);
- } else {
- c = color;
- }
- return c;
-}
-
-uint8 Gdi::getWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 color) {
- uint8 c = color;
- if (x >= 0 && x < w && y >= 0 && y < h) {
- while (y != 0) {
- data += READ_LE_UINT16(data) + 2;
- --y;
- }
- uint16 off = READ_LE_UINT16(data); data += 2;
- if (off != 0) {
- if (x == 0) {
- c = (*data & 1) ? color : *data;
- } else {
- do {
- uint8 code = *data++;
- if (code & 1) {
- code >>= 1;
- if (code > x) {
- c = color;
- break;
- }
- x -= code;
- } else if (code & 2) {
- code = (code >> 2) + 1;
- if (code > x) {
- c = *data;
- break;
- }
- x -= code;
- ++data;
- } else {
- code = (code >> 2) + 1;
- if (code > x) {
- c = *(data + x);
- break;
- }
- x -= code;
- data += code;
- }
- } while (x > 0);
- }
- }
- }
- return c;
-}
-
-void Gdi::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 Gdi::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;
- }
-}
-
-void Gdi::copyAuxImage(uint8 *dst1, uint8 *dst2, 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)) {
- decompressAuxImage(dst1, dst2, dstw, r2, src, r1);
- }
-}
-
-void Gdi::decompressAuxImage(uint8 *dst1, uint8 *dst2, int dstPitch, const Common::Rect &dstRect, const uint8 *src, const Common::Rect &srcRect) {
- const uint8 *dataPtr, *dataPtrNext;
- uint8 *dst1Ptr, *dst2Ptr, *dst1PtrNext, *dst2PtrNext;
- int h, w, xoff;
- uint16 off;
- uint8 code;
-
- dst1Ptr = dst1 + dstRect.left + dstRect.top * dstPitch;
- dst2Ptr = dst2 + dstRect.left + dstRect.top * dstPitch;
- 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();
- if (h <= 0)
- return;
- w = srcRect.width();
- if (w <= 0)
- return;
-
- while (h--) {
- xoff = srcRect.left;
- off = READ_LE_UINT16(dataPtr);
- w = srcRect.right - srcRect.left;
- dst1PtrNext = dstPitch + dst1Ptr;
- dst2PtrNext = dstPitch + dst2Ptr;
- 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++;
- if (code & 1) {
- code >>= 1;
- if (code > xoff) {
- code -= xoff;
- goto dec_sub1;
- }
- xoff -= code;
- } else if (code & 2) {
- code = (code >> 2) + 1;
- if (code > xoff) {
- code -= xoff;
- goto dec_sub2;
- }
- xoff -= code;
- ++dataPtr;
- } else {
- code = (code >> 2) + 1;
- if (code > xoff) {
- code -= xoff;
- dataPtr += xoff;
- goto dec_sub3;
- }
- xoff -= code;
- dataPtr += code;
- }
- }
- while (w > 0) {
- code = *dataPtr++;
- if (code & 1) {
- code >>= 1;
-dec_sub1: dst1Ptr += code;
- dst2Ptr += code;
- w -= code;
- } else if (code & 2) {
- code = (code >> 2) + 1;
-dec_sub2: 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;
-dec_sub3: w -= code;
- if (w >= 0) {
- memcpy(dst1Ptr, dst2Ptr, code);
- dst1Ptr += code;
- dst2Ptr += code;
- } else {
- code += w;
- memcpy(dst1Ptr, dst2Ptr, code);
- }
- }
- }
-
-dec_next:
- dataPtr = dataPtrNext;
- dst1Ptr = dst1PtrNext;
- dst2Ptr = dst2PtrNext;
- }
-}
-
void Gdi::copyVirtScreenBuffers(const Common::Rect &rect) {
const int rw = rect.width();
const int rh = rect.height();
diff --git a/scumm/gfx.h b/scumm/gfx.h
index 65e15d717f..cf0b41f12f 100644
--- a/scumm/gfx.h
+++ b/scumm/gfx.h
@@ -205,7 +205,6 @@ class Gdi {
ScummEngine *_vm;
public:
- byte _wizImagePalette[256];
int _numZBuffer;
int _imgBufOffs[8];
@@ -277,16 +276,7 @@ public:
void drawBMAPBg(const byte *ptr, VirtScreen *vs, int startstrip);
void drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y, int w, int h);
- void copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect);
- void 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);
- void decompressWizImage(uint8 *dst, int dstPitch, const Common::Rect &dstRect, const uint8 *src, const Common::Rect &srcRect);
- int isWizPixelNonTransparent(const uint8 *data, int x, int y, int w, int h);
- uint8 getWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 color);
- uint8 getRawWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 color);
- void computeWizHistogram(uint32 *histogram, const uint8 *data, const Common::Rect *srcRect);
- void computeRawWizHistogram(uint32 *histogram, const uint8 *data, int srcPitch, const Common::Rect *srcRect);
- void copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect);
- void decompressAuxImage(uint8 *dst1, uint8 *dst2, int dstPitch, const Common::Rect &dstRect, const uint8 *src, const Common::Rect &srcRect);
+
void copyVirtScreenBuffers(const Common::Rect &rect);
void disableZBuffer() { _zbufferDisabled = true; }
diff --git a/scumm/intern.h b/scumm/intern.h
index f013558d3b..cd9f748f2a 100644
--- a/scumm/intern.h
+++ b/scumm/intern.h
@@ -659,10 +659,6 @@ protected:
void appendSubstring(int dst, int src, int len2, int len);
int findObject(int x, int y, int num, int *args);
- void polygonErase(int fromId, int toId);
- bool polygonContains(const WizPolygon &pol, int x, int y);
- bool polygonDefined(int id);
- int polygonHit(int id, int x, int y);
virtual void setCursorFromImg(uint img, uint room, uint imgindex);
@@ -709,25 +705,14 @@ protected:
byte data[1]; //14
} GCC_PACK;
- struct WizImage {
- int resNum;
- int x1;
- int y1;
- int flags;
- int state;
- int unk;
- };
-
#if !defined(__GNUC__)
#pragma END_PACK_STRUCTS
#endif
const OpcodeEntryV72he *_opcodesV72he;
- WizImage _wizImages[255];
- uint16 _wizImagesNum;
public:
- ScummEngine_v72he(GameDetector *detector, OSystem *syst, const ScummGameSettings &gs, uint8 md5sum[16]) : ScummEngine_v70he(detector, syst, gs, md5sum), _wizImagesNum(0) {}
+ ScummEngine_v72he(GameDetector *detector, OSystem *syst, const ScummGameSettings &gs, uint8 md5sum[16]) : ScummEngine_v70he(detector, syst, gs, md5sum) {}
protected:
virtual void setupScummVars();
@@ -747,12 +732,12 @@ protected:
int readFileToArray(int slot, int32 size);
void writeFileFromArray(int slot, int resID);
+ void captureWizImage(int restype, int resnum, const Common::Rect& r, bool frontBuffer, int compType);
void displayWizImage(const WizImage *pwi);
void getWizImageDim(int resnum, int state, int32 &w, int32 &h);
uint8 *drawWizImage(int restype, const WizImage *pwi);
void drawWizPolygon(int resnum, int state, int id, int flags);
void flushWizBuffer();
- void captureWizImage(int restype, int resnum, const Common::Rect& r, bool frontBuffer, int compType);
virtual void decodeParseString(int a, int b);
void decodeScriptString(byte *dst, bool scriptString = false);
@@ -856,31 +841,6 @@ protected:
int _heObject, _heObjectNum;
int _hePaletteNum;
-
- struct WizParameters {
- byte filename[260];
- Common::Rect box;
- int processFlags;
- int processMode;
- int unk_11C;
- int unk_120;
- int unk_124;
- int unk_128;
- int unk_12C;
- int unk_130;
- int unk_134;
- int unk_138;
- int compType;
- int unk_14C;
- int angle;
- int zoom;
- int unk_15C;
- int unk_160;
- uint8 remapColor[256];
- uint8 remapIndex[256];
- int remapNum;
- WizImage img;
- };
const OpcodeEntryV90he *_opcodesV90he;
WizParameters _wizParams;
@@ -895,10 +855,10 @@ protected:
virtual void executeOpcode(byte i);
virtual const char *getOpcodeDesc(byte i);
- int getWizImageStates(int resnum);
void drawWizComplexPolygon(int resnum, int state, int po_x, int po_y, int arg14, int angle, int zoom, const Common::Rect *r);
void displayWizComplexImage(const WizParameters *params);
void processWizImage(const WizParameters *params);
+ int getWizImageStates(int resnum);
int isWizPixelNonTransparent(int restype, int resnum, int state, int x, int y, int flags);
uint8 getWizPixelColor(int restype, int resnum, int state, int x, int y, int flags);
int computeWizHistogram(int resnum, int state, int x, int y, int w, int h);
diff --git a/scumm/module.mk b/scumm/module.mk
index 701ef2a223..4e23c3aa93 100644
--- a/scumm/module.mk
+++ b/scumm/module.mk
@@ -51,6 +51,7 @@ MODULE_OBJS := \
scumm/usage_bits.o \
scumm/vars.o \
scumm/verbs.o \
+ scumm/wiz_he.o \
scumm/imuse_digi/dimuse.o \
scumm/imuse_digi/dimuse_bndmgr.o \
scumm/imuse_digi/dimuse_codecs.o \
diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp
index 4c495f28d5..95d4c548a4 100644
--- a/scumm/saveload.cpp
+++ b/scumm/saveload.cpp
@@ -727,7 +727,7 @@ void ScummEngine::saveOrLoad(Serializer *s, uint32 savegameVersion) {
s->saveLoadArrayOf(vm.slot, NUM_SCRIPT_SLOT, sizeof(vm.slot[0]), scriptSlotEntries);
if (_heversion >= 71)
- s->saveLoadArrayOf(_wizPolygons, _wizNumPolygons, sizeof(_wizPolygons[0]), polygonEntries);
+ s->saveLoadArrayOf(_wiz._polygons, ARRAYSIZE(_wiz._polygons), sizeof(_wiz._polygons[0]), polygonEntries);
s->saveLoadArrayOf(_objs, _numLocalObjects, sizeof(_objs[0]), objectEntries);
if (s->isLoading() && savegameVersion < VER(13)) {
// Since roughly v13 of the save games, the objs storage has changed a bit
diff --git a/scumm/script_v72he.cpp b/scumm/script_v72he.cpp
index 47ffe6d35e..9f5193dbd7 100644
--- a/scumm/script_v72he.cpp
+++ b/scumm/script_v72he.cpp
@@ -683,252 +683,6 @@ void ScummEngine_v72he::o72_getObjectImageY() {
push(_objs[objnum].y_pos);
}
-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::o72_captureWizImage() {
Common::Rect grab;
grab.bottom = pop() + 1;
@@ -1713,296 +1467,6 @@ void ScummEngine_v72he::o72_traceStatus() {
pop();
}
-void ScummEngine_v72he::displayWizImage(const WizImage *pwi) {
- if (_fullRedraw) {
- assert(_wizImagesNum < ARRAYSIZE(_wizImages));
- memcpy(&_wizImages[_wizImagesNum], pwi, sizeof(WizImage));
- ++_wizImagesNum;
- } 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 {
- gdi.copyWizImage(dst, wizd, cw, ch, pwi->x1, pwi->y1, width, height, &rScreen);
- }
- } else if (comp == 0 || comp == 2) {
- 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;
- }
- gdi.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 < _wizNumPolygons; ++i) {
- if (_wizPolygons[i].id == id) {
- wp = &_wizPolygons[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 < _wizImagesNum; ++i) {
- WizImage *pwi = &_wizImages[i];
- if (pwi->flags & 0x40) {
- drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags);
- } else {
- drawWizImage(rtImage, pwi);
- }
- }
- _wizImagesNum = 0;
-}
-
void ScummEngine_v72he::o72_kernelGetFunctions() {
int args[29];
int retval;
diff --git a/scumm/script_v7he.cpp b/scumm/script_v7he.cpp
index 8cfdceb0e1..e12f018f01 100644
--- a/scumm/script_v7he.cpp
+++ b/scumm/script_v7he.cpp
@@ -416,8 +416,8 @@ int ScummEngine_v70he::findObject(int x, int y, int num, int *args) {
continue;
// Check polygon bounds
- if (polygonDefined(_objs[i].obj_nr)) {
- if (polygonHit(_objs[i].obj_nr, x, y) != 0)
+ if (_wiz.polygonDefined(_objs[i].obj_nr)) {
+ if (_wiz.polygonHit(_objs[i].obj_nr, x, y) != 0)
result = _objs[i].obj_nr;
else if (VAR_POLYGONS_ONLY != 0xFF && VAR(VAR_POLYGONS_ONLY))
continue;
@@ -1042,116 +1042,23 @@ void ScummEngine_v70he::o70_polygonOps() {
vert1y = pop();
vert1x = pop();
id = pop();
-
- polygonStore(id, (subOp == 69 || subOp == 248), vert1x, vert1y, vert2x, vert2y, vert3x, vert3y,
- vert4x, vert4y);
+ _wiz.polygonStore(id, (subOp == 69 || subOp == 248), vert1x, vert1y, vert2x, vert2y, vert3x, vert3y, vert4x, vert4y);
break;
case 28: // HE 100
case 247:
toId = pop();
fromId = pop();
-
- polygonErase(fromId, toId);
+ _wiz.polygonErase(fromId, toId);
break;
default:
error("o70_polygonOps: default case %d", subOp);
}
}
-void ScummEngine::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 < _wizNumPolygons; ++i) {
- if (_wizPolygons[i].id == 0) {
- wp = &_wizPolygons[i];
- break;
- }
- }
- if (!wp) {
- error("ScummEngine::polygonStore: out of polygon slot, max = %d",
- _wizNumPolygons);
- }
-
- 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 ScummEngine_v70he::polygonErase(int fromId, int toId) {
- for (int i = 0; i < _wizNumPolygons; i++) {
- if (_wizPolygons[i].id >= fromId && _wizPolygons[i].id <= toId)
- memset(&_wizPolygons[i], 0, sizeof(WizPolygon));
- }
-}
-
void ScummEngine_v70he::o70_polygonHit() {
int y = pop();
int x = pop();
-
- push(polygonHit(0, x, y));
-}
-
-int ScummEngine_v70he::polygonHit(int id, int x, int y) {
- for (int i = 0; i < _wizNumPolygons; i++) {
- if ((!id || _wizPolygons[i].id == id) && _wizPolygons[i].bound.contains(x, y)) {
- if (polygonContains(_wizPolygons[i], x, y)) {
- return _wizPolygons[i].id;
- }
- }
- }
-
- return 0;
-}
-
-bool ScummEngine_v70he::polygonDefined(int id) {
- for (int i = 0; i < _wizNumPolygons; i++)
- if (_wizPolygons[i].id == id)
- return true;
-
- return false;
-}
-
-bool ScummEngine_v70he::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;
+ push(_wiz.polygonHit(0, x, y));
}
} // End of namespace Scumm
diff --git a/scumm/script_v80he.cpp b/scumm/script_v80he.cpp
index f4806a9c86..4070a27d98 100644
--- a/scumm/script_v80he.cpp
+++ b/scumm/script_v80he.cpp
@@ -543,52 +543,6 @@ void ScummEngine_v80he::o80_cursorCommand() {
VAR(VAR_USERPUT) = _userPut;
}
-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_v80he::o80_setState() {
int state = pop();
int obj = pop();
diff --git a/scumm/script_v90he.cpp b/scumm/script_v90he.cpp
index 11b72709a9..8d311cf9dd 100644
--- a/scumm/script_v90he.cpp
+++ b/scumm/script_v90he.cpp
@@ -476,176 +476,6 @@ void ScummEngine_v90he::o90_jumpToScriptUnk() {
runScript(script, (flags == 199 || flags == 200), (flags == 195 || flags == 200), args);
}
-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(_wizImagesNum < ARRAYSIZE(_wizImages));
- WizImage *pwi = &_wizImages[_wizImagesNum];
- pwi->resNum = params->img.resNum;
- pwi->x1 = po_x;
- pwi->y1 = po_y;
- pwi->state = state;
- pwi->flags = flags;
- pwi->unk = unk;
- ++_wizImagesNum;
- } 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::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 6:
- // HE 99+
- case 7:
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- warning("unhandled processWizImage mode %d", params->processMode);
- break;
- default:
- warning("invalid processWizImage mode %d", params->processMode);
- }
-}
-
void ScummEngine_v90he::o90_wizImageOps() {
int a, b;
int subOp = fetchScriptByte();
@@ -1176,108 +1006,6 @@ void ScummEngine_v90he::o90_unknown28() {
debug(1,"o90_unknown28 stub (%d)", subOp);
}
-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 = gdi.isWizPixelNonTransparent(wizd, x, y, w, h);
- } else if (c == 0 || c == 2 || c == 3) {
- ret = gdi.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 = gdi.getWizPixelColor(wizd, x, y, w, h, VAR(VAR_WIZ_TCOLOR));
- } else if (c == 0 || c == 2 || c == 3) {
- color = gdi.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) {
- gdi.computeWizHistogram(histogram, wizd, &rCap);
- } else if (ic == 0) {
- gdi.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);
-}
-
void ScummEngine_v90he::o90_getWizData() {
int state, resId;
int32 w, h;
@@ -1494,7 +1222,7 @@ void ScummEngine_v90he::o90_getPolygonOverlap() {
wp.vert[i].x = args1[i * 2 + 0];
wp.vert[i].y = args1[i * 2 + 1];
}
- push(polygonContains(wp, args2[0], args2[1]) ? 1 : 0);
+ push(_wiz.polygonContains(wp, args2[0], args2[1]) ? 1 : 0);
}
}
break;
diff --git a/scumm/scumm.cpp b/scumm/scumm.cpp
index de512d26c2..29a4681e44 100644
--- a/scumm/scumm.cpp
+++ b/scumm/scumm.cpp
@@ -690,8 +690,6 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS
_costumeRenderer = NULL;
_2byteFontPtr = 0;
_V1TalkingActor = 0;
- _wizNumPolygons = 200; // Used as constant in original
- _wizPolygons = NULL;
_actorClipOverride.top = 0;
_actorClipOverride.bottom = 480;
@@ -1300,12 +1298,6 @@ void ScummEngine_v60he::scummInit() {
// setCursorHotspot(8, 7);
if (_gameId == GID_FUNPACK)
setCursorHotspot(16, 16);
-
- if (_heversion >= 70) {
- free(_wizPolygons);
-
- _wizPolygons = (WizPolygon *)calloc(_wizNumPolygons, sizeof(WizPolygon));
- }
}
void ScummEngine_v90he::scummInit() {
@@ -1797,8 +1789,8 @@ void ScummEngine::startScene(int room, Actor *a, int objectNr) {
stopCycle(0);
_sound->processSoundQues();
- if (_heversion >= 71 && _wizPolygons) {
- memset(_wizPolygons, 0, _wizNumPolygons * sizeof(WizPolygon));
+ if (_heversion >= 71) {
+ memset(_wiz._polygons, 0, sizeof(_wiz._polygons));
}
// For HE80+ games
@@ -2354,7 +2346,7 @@ void ScummEngine::initRoomSubBlocks() {
vert4y = READ_LE_UINT32(ptr + 36);
ptr += 40;
- polygonStore(id, flag, vert1x, vert1y, vert2x, vert2y, vert3x, vert3y, vert4x, vert4y);
+ _wiz.polygonStore(id, flag, vert1x, vert1y, vert2x, vert2y, vert3x, vert3y, vert4x, vert4y);
}
}
diff --git a/scumm/scumm.h b/scumm/scumm.h
index 03be6cbea4..f6974feb45 100644
--- a/scumm/scumm.h
+++ b/scumm/scumm.h
@@ -31,6 +31,7 @@
#include "scumm/gfx.h"
#include "scumm/script.h"
+#include "scumm/wiz_he.h"
namespace GUI {
class Dialog;
@@ -311,14 +312,6 @@ struct LangIndexNode {
int32 offset;
};
-struct WizPolygon {
- Common::Point vert[5];
- Common::Rect bound;
- int id;
- int numVerts;
- bool flag;
-};
-
struct AuxBlock {
bool visible;
Common::Rect r;
@@ -362,6 +355,9 @@ public:
/** Graphics manager */
Gdi gdi;
+
+ /** Wiz graphics manager (HE) */
+ Wiz _wiz;
protected:
/** Central resource data. */
@@ -663,8 +659,6 @@ protected:
uint32 *_heV7RoomIntOffsets;
const byte *_resourceLastSearchBuf; // FIXME: need to put it to savefile?
uint32 _resourceLastSearchSize; // FIXME: need to put it to savefile?
- int _wizNumPolygons;
- WizPolygon *_wizPolygons;
void allocateArrays();
void openRoom(int room);
@@ -705,8 +699,6 @@ protected:
void loadRoomObjects();
void loadRoomObjectsSmall();
void loadRoomObjectsOldBundle();
- void polygonStore(int id, bool flag, int vert1x, int vert1y, int vert2x, int vert2y,
- int vert3x, int vert3y, int vert4x, int vert4y);
virtual void readArrayFromIndexFile();
virtual void readMAXS(int blockSize);
diff --git a/scumm/wiz_he.cpp b/scumm/wiz_he.cpp
new file mode 100644
index 0000000000..6e68454a7d
--- /dev/null
+++ b/scumm/wiz_he.cpp
@@ -0,0 +1,1392 @@
+/* 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$
+ *
+ */
+
+#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();
+ dst += r2.left + r2.top * dstw;
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ uint8 col = *src++;
+ if (transColor == -1 || transColor != col) {
+ dst[i] = palPtr[col];
+ }
+ }
+ 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) {
+ int ret = 0;
+ while (y != 0) {
+ data += READ_LE_UINT16(data) + 2;
+ --y;
+ }
+ uint16 off = READ_LE_UINT16(data); data += 2;
+ if (off != 0) {
+ if (x == 0) {
+ ret = (~*data) & 1;
+ } else {
+ do {
+ uint8 code = *data++;
+ if (code & 1) {
+ code >>= 1;
+ if (code > x) {
+ ret = 0;
+ break;
+ }
+ x -= code;
+ } else if (code & 2) {
+ code = (code >> 2) + 1;
+ if (code > x) {
+ ret = 1;
+ break;
+ }
+ x -= code;
+ ++data;
+ } else {
+ code = (code >> 2) + 1;
+ if (code > x) {
+ ret = 1;
+ break;
+ }
+ x -= code;
+ data += code;
+ }
+ } while (x > 0);
+ }
+ }
+ return ret;
+}
+
+uint8 Wiz::getWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 color) {
+ uint8 c = color;
+ if (x >= 0 && x < w && y >= 0 && y < h) {
+ while (y != 0) {
+ data += READ_LE_UINT16(data) + 2;
+ --y;
+ }
+ uint16 off = READ_LE_UINT16(data); data += 2;
+ if (off != 0) {
+ if (x == 0) {
+ c = (*data & 1) ? color : *data;
+ } else {
+ do {
+ uint8 code = *data++;
+ if (code & 1) {
+ code >>= 1;
+ if (code > x) {
+ c = color;
+ break;
+ }
+ x -= code;
+ } else if (code & 2) {
+ code = (code >> 2) + 1;
+ if (code > x) {
+ c = *data;
+ break;
+ }
+ x -= code;
+ ++data;
+ } else {
+ code = (code >> 2) + 1;
+ if (code > x) {
+ c = *(data + x);
+ break;
+ }
+ x -= code;
+ data += code;
+ }
+ } while (x > 0);
+ }
+ }
+ }
+ return c;
+}
+
+uint8 Wiz::getRawWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 color) {
+ uint8 c;
+ if (x >= 0 && x < w && y >= 0 && y < h) {
+ c = data[y * w + x];
+ } else {
+ c = color;
+ }
+ return c;
+}
+
+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::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 6:
+ // HE 99+
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ warning("unhandled processWizImage mode %d", params->processMode);
+ 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
diff --git a/scumm/wiz_he.h b/scumm/wiz_he.h
new file mode 100644
index 0000000000..277d0d1498
--- /dev/null
+++ b/scumm/wiz_he.h
@@ -0,0 +1,111 @@
+/* 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$
+ *
+ */
+
+#ifndef WIZ_HE_H
+#define WIZ_HE_H
+
+#include "common/rect.h"
+
+namespace Scumm {
+
+struct WizPolygon {
+ Common::Point vert[5];
+ Common::Rect bound;
+ int id;
+ int numVerts;
+ bool flag;
+};
+
+struct WizImage {
+ int resNum;
+ int x1;
+ int y1;
+ int flags;
+ int state;
+ int unk;
+};
+
+struct WizParameters {
+ byte filename[260];
+ Common::Rect box;
+ int processFlags;
+ int processMode;
+ int unk_11C;
+ int unk_120;
+ int unk_124;
+ int unk_128;
+ int unk_12C;
+ int unk_130;
+ int unk_134;
+ int unk_138;
+ int compType;
+ int unk_14C;
+ int angle;
+ int zoom;
+ int unk_15C;
+ int unk_160;
+ uint8 remapColor[256];
+ uint8 remapIndex[256];
+ int remapNum;
+ WizImage img;
+};
+
+struct Wiz {
+ enum {
+ FW_PRINT = 0x4,
+ FW_MEM = 0x20,
+ FW_POLYGON = 0x40,
+ FW_XFLIP = 0x400,
+ FW_YFLIP = 0x800
+ };
+
+ enum {
+ NUM_POLYGONS = 200,
+ NUM_IMAGES = 255
+ };
+
+ WizImage _images[NUM_IMAGES];
+ uint16 _imagesNum;
+ WizPolygon _polygons[NUM_POLYGONS];
+
+ Wiz();
+
+ void polygonStore(int id, bool flag, int vert1x, int vert1y, int vert2x, int vert2y, int vert3x, int vert3y, int vert4x, int vert4y);
+ void polygonErase(int fromId, int toId);
+ int polygonHit(int id, int x, int y);
+ bool polygonDefined(int id);
+ bool polygonContains(const WizPolygon &pol, int x, int y);
+
+ void copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch);
+ void copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect);
+ void 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);
+ void decompressWizImage(uint8 *dst, int dstPitch, const Common::Rect &dstRect, const uint8 *src, const Common::Rect &srcRect, const uint8 *imagePal = NULL);
+ int isWizPixelNonTransparent(const uint8 *data, int x, int y, int w, int h);
+ uint8 getWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 color);
+ uint8 getRawWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 color);
+ void computeWizHistogram(uint32 *histogram, const uint8 *data, const Common::Rect *srcRect);
+ void computeRawWizHistogram(uint32 *histogram, const uint8 *data, int srcPitch, const Common::Rect *srcRect);
+};
+
+} // End of namespace Scumm
+
+#endif