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() {  | 
