diff options
-rw-r--r-- | scumm/gfx.cpp | 133 | ||||
-rw-r--r-- | scumm/gfx.h | 7 | ||||
-rw-r--r-- | scumm/intern.h | 3 | ||||
-rw-r--r-- | scumm/script_v90he.cpp | 93 |
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() { |