aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scumm/gfx.cpp133
-rw-r--r--scumm/gfx.h7
-rw-r--r--scumm/intern.h3
-rw-r--r--scumm/script_v90he.cpp93
4 files changed, 213 insertions, 23 deletions
diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp
index c5a45d9a45..051d52823b 100644
--- a/scumm/gfx.cpp
+++ b/scumm/gfx.cpp
@@ -1624,7 +1624,50 @@ dec_next:
}
}
-uint8 Gdi::getWizPixelColor_type0(const uint8 *data, int x, int y, int w, int h, uint8 color) {
+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);
@@ -1634,14 +1677,14 @@ uint8 Gdi::getWizPixelColor_type0(const uint8 *data, int x, int y, int w, int h,
return c;
}
-uint8 Gdi::getWizPixelColor_type1(const uint8 *data, int x, int y, int w, int h, uint8 color) {
+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);
+ uint16 off = READ_LE_UINT16(data); data += 2;
if (off != 0) {
if (x == 0) {
c = (*data & 1) ? color : *data;
@@ -1679,6 +1722,90 @@ uint8 Gdi::getWizPixelColor_type1(const uint8 *data, int x, int y, int w, int h,
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)) {
diff --git a/scumm/gfx.h b/scumm/gfx.h
index 843d1f9946..65e15d717f 100644
--- a/scumm/gfx.h
+++ b/scumm/gfx.h
@@ -280,8 +280,11 @@ public:
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);
- uint8 getWizPixelColor_type0(const uint8 *data, int x, int y, int w, int h, uint8 color);
- uint8 getWizPixelColor_type1(const uint8 *data, int x, int y, int w, int h, uint8 color);
+ 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);
diff --git a/scumm/intern.h b/scumm/intern.h
index 24de77aadb..bf6d686034 100644
--- a/scumm/intern.h
+++ b/scumm/intern.h
@@ -877,6 +877,7 @@ protected:
void processWizImage(const WizParameters *params);
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);
/* HE version 90 script opcodes */
void o90_dup();
@@ -895,7 +896,7 @@ protected:
void o90_unknown26();
void o90_unknown27();
void o90_unknown28();
- void o90_unknown29();
+ void o90_getWizData();
void o90_unknown2F();
void o90_mod();
void o90_unknown31();
diff --git a/scumm/script_v90he.cpp b/scumm/script_v90he.cpp
index fb43810bde..9be6c21d74 100644
--- a/scumm/script_v90he.cpp
+++ b/scumm/script_v90he.cpp
@@ -95,7 +95,7 @@ void ScummEngine_v90he::setupOpcodes() {
OPCODE(o90_unknown27),
/* 28 */
OPCODE(o90_unknown28),
- OPCODE(o90_unknown29),
+ OPCODE(o90_getWizData),
OPCODE(o6_invalid),
OPCODE(o90_startScriptUnk),
/* 2C */
@@ -1197,8 +1197,30 @@ int ScummEngine_v90he::getWizImageStates(int resnum) {
}
int ScummEngine_v90he::isWizPixelNonTransparent(int restype, int resnum, int state, int x, int y, int flags) {
- warning("ScummEngine_v90he::isWizPixelNonTransparent() unimplemented");
- return 0;
+ 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);
+ }
+ }
+ return ret;
}
uint8 ScummEngine_v90he::getWizPixelColor(int restype, int resnum, int state, int x, int y, int flags) {
@@ -1213,16 +1235,50 @@ uint8 ScummEngine_v90he::getWizPixelColor(int restype, int resnum, int state, in
const uint8 *wizd = findWrappedBlock(MKID('WIZD'), data, state, 0);
assert(wizd);
if (c == 1) {
- color = gdi.getWizPixelColor_type1(wizd, x, y, w, h, VAR(VAR_WIZ_TCOLOR));
+ color = gdi.getWizPixelColor(wizd, x, y, w, h, VAR(VAR_WIZ_TCOLOR));
} else if (c == 0 || c == 2 || c == 3) {
- color = gdi.getWizPixelColor_type0(wizd, x, y, w, h, VAR(VAR_WIZ_TCOLOR));
+ color = gdi.getRawWizPixelColor(wizd, x, y, w, h, VAR(VAR_WIZ_TCOLOR));
} else {
color = VAR(VAR_WIZ_TCOLOR);
}
return color;
}
-void ScummEngine_v90he::o90_unknown29() {
+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;
int16 x, y;
@@ -1273,14 +1329,19 @@ void ScummEngine_v90he::o90_unknown29() {
resId = pop();
push(getWizPixelColor(rtImage, resId, state, x, y, 0));
break;
- case 100: // SO_GET_WIZ_HISTOGRAM
- pop();
- pop();
- pop();
- pop();
- pop();
- pop();
- push(0);
+ case 100:
+ h = pop();
+ w = pop();
+ y = pop();
+ x = pop();
+ state = pop();
+ resId = pop();
+ if (x == -1 && y == -1 && w == -1 && h == -1) {
+ getWizImageDim(resId, state, w, h);
+ x = 0;
+ y = 0;
+ }
+ push(computeWizHistogram(resId, state, x, y, w, h));
break;
case 109:
pop();
@@ -1288,10 +1349,8 @@ void ScummEngine_v90he::o90_unknown29() {
push(0);
break;
default:
- error("o90_unknown29: Unknown case %d", subOp);
+ error("o90_getWizData: Unknown case %d", subOp);
}
-
- debug(1,"o90_unknown29 stub (%d)", subOp);
}
void ScummEngine_v90he::o90_unknown2F() {