[Scummvm-git-logs] scummvm master -> f3ff05e6589980a5a21bc13d6e48c4c44a255a3b

elasota noreply at scummvm.org
Thu Jun 8 04:56:44 UTC 2023


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
55d578078b MTROPOLIS: Add basic support for image effect modifiers, which should fix most object highlights in MTI
f3ff05e658 VCRUISE: Properly fix EOS flag handling in Gentee Installer unpacker


Commit: 55d578078babb8aac9b04728cab13b3eb2b05761
    https://github.com/scummvm/scummvm/commit/55d578078babb8aac9b04728cab13b3eb2b05761
Author: elasota (ejlasota at gmail.com)
Date: 2023-06-07T23:48:36-04:00

Commit Message:
MTROPOLIS: Add basic support for image effect modifiers, which should fix most object highlights in MTI

Changed paths:
    engines/mtropolis/elements.cpp
    engines/mtropolis/modifiers.cpp
    engines/mtropolis/modifiers.h
    engines/mtropolis/runtime.cpp
    engines/mtropolis/runtime.h


diff --git a/engines/mtropolis/elements.cpp b/engines/mtropolis/elements.cpp
index 50b8666b2d3..90d8701be5b 100644
--- a/engines/mtropolis/elements.cpp
+++ b/engines/mtropolis/elements.cpp
@@ -73,10 +73,14 @@ MiniscriptInstructionOutcome GraphicElement::writeRefAttribute(MiniscriptThread
 
 
 void GraphicElement::render(Window *window) {
-	if (_renderProps.getInkMode() == VisualElementRenderProperties::kInkModeDefault || _renderProps.getInkMode() == VisualElementRenderProperties::kInkModeInvisible || _rect.isEmpty()) {
-		// Not rendered at all
-		_mask.reset();
-		return;
+	bool haveEffect = (_bottomRightBevelShading != 0 || _topLeftBevelShading != 0 || _interiorShading != 0);
+
+	if (!haveEffect) {
+		if (_renderProps.getInkMode() == VisualElementRenderProperties::kInkModeDefault || _renderProps.getInkMode() == VisualElementRenderProperties::kInkModeInvisible || _rect.isEmpty()) {
+			// Not rendered at all
+			_mask.reset();
+			return;
+		}
 	}
 
 	if (!_visible)
@@ -182,9 +186,6 @@ void GraphicElement::render(Window *window) {
 					Common::Point *leftVert = triPoints[half][1];
 					Common::Point *rightVert = triPoints[half][2];
 
-					if (leftVert->x == rightVert->x || commonPoint->y == points[1].y)
-						continue; // Degenerate tri
-
 					if (leftVert->x > rightVert->x) {
 						Common::Point *temp = leftVert;
 						leftVert = rightVert;
@@ -255,10 +256,27 @@ void GraphicElement::render(Window *window) {
 							xSpan[ray] = resolved;
 						}
 
-						int32 spanWidth = xSpan[1] - xSpan[0];
-						uint8 *bits = static_cast<uint8 *>(_mask->getBasePtr(xSpan[0], y));
-						for (int32 i = 0; i < spanWidth; i++)
-							bits[i] ^= 0xff;
+						if (xSpan[1] < xSpan[0]) {
+							int32 temp = xSpan[1];
+							xSpan[1] = xSpan[0];
+							xSpan[0] = temp;
+						}
+
+						// Clip to the graphic area
+						if (y >= 0 && y < static_cast<int32>(height)) {
+							for (int i = 0; i < 2; i++) {
+								int32 &xVal = xSpan[i];
+								if (xVal < 0)
+									xVal = 0;
+								if (xVal >= static_cast<int32>(width))
+									xVal = width - 1;
+							}
+
+							int32 spanWidth = xSpan[1] - xSpan[0];
+							uint8 *bits = static_cast<uint8 *>(_mask->getBasePtr(xSpan[0], y));
+							for (int32 i = 0; i < spanWidth; i++)
+								bits[i] ^= 0xff;
+						}
 					}
 				}
 			}
@@ -413,10 +431,64 @@ void GraphicElement::render(Window *window) {
 				}
 			}
 		} break;
+	case VisualElementRenderProperties::kInkModeInvisible:
+	case VisualElementRenderProperties::kInkModeDefault:
+		break;
 	default:
 		warning("Unimplemented graphic ink mode");
 		return;
 	}
+
+	// TODO: The accurate behavior for polys is complicated.
+	// It looks like the way that it works is that a "line mask" is constructed by inverting the mask, dilating it
+	// by HALF the bevel size, then masking that out using the original mask, which results in a border mask.
+	// Then, the bevel diagonal is computed as simply a line going from the lower-left corner to the top-right corner.
+
+	if (_interiorShading) {
+		const Graphics::PixelFormat &pixFmt = window->getPixelFormat();
+
+		if (pixFmt.bytesPerPixel > 1) {
+			uint32 rMask = pixFmt.ARGBToColor(0, 255, 0, 0);
+			uint32 gMask = pixFmt.ARGBToColor(0, 0, 255, 0);
+			uint32 bMask = pixFmt.ARGBToColor(0, 0, 0, 255);
+
+			uint32 rAdd = quantizeShading(rMask, _interiorShading);
+			uint32 gAdd = quantizeShading(gMask, _interiorShading);
+			uint32 bAdd = quantizeShading(bMask, _interiorShading);
+
+			bool isBrighten = (_interiorShading > 0);
+
+			Graphics::ManagedSurface *windowSurface = window->getSurface().get();
+
+			for (int32 srcY = clippedSrcRect.top; srcY < clippedSrcRect.bottom; srcY++) {
+				int32 spanWidth = clippedDrawRect.width();
+
+				int32 effectLength = 0;
+
+				if (_mask) {
+					const uint8 *maskBytes = static_cast<const uint8 *>(_mask->getBasePtr(clippedSrcRect.left, srcY));
+
+					for (int32 x = 0; x < spanWidth; x++) {
+						if (maskBytes[x])
+							effectLength++;
+						else {
+							if (effectLength > 0) {
+								void *effectPixels = windowSurface->getBasePtr(clippedDrawRect.left + x - effectLength, srcY + srcToDestY);
+								renderShadingScanlineDynamic(effectPixels, effectLength, rMask, rAdd, gMask, gAdd, bMask, bAdd, isBrighten, windowSurface->format.bytesPerPixel);
+							}
+							effectLength = 0;
+						}
+					}
+				} else
+					effectLength = spanWidth;  
+				
+				if (effectLength > 0) {
+					void *effectPixels = windowSurface->getBasePtr(clippedDrawRect.left + spanWidth - effectLength, srcY + srcToDestY);
+					renderShadingScanlineDynamic(effectPixels, effectLength, rMask, rAdd, gMask, gAdd, bMask, bAdd, isBrighten, windowSurface->format.bytesPerPixel);
+				}
+			}
+		}
+	}
 }
 
 MovieResizeFilter::~MovieResizeFilter() {
@@ -1107,6 +1179,16 @@ void ImageElement::render(Window *window) {
 
 		uint8 alpha = _transitionProps.getAlpha();
 
+		Graphics::Surface *postShadingSource = optimized->surfacePtr();
+
+		Graphics::Surface tempSurface;
+		if (_interiorShading != 0 || (_bevelSize > 0 && (_bottomRightBevelShading != 0 || _topLeftBevelShading != 0))) {
+			tempSurface.copyFrom(*postShadingSource);
+			renderShading(tempSurface);
+			postShadingSource = &tempSurface;
+		}
+
+
 		if (inkMode == VisualElementRenderProperties::kInkModeBackgroundMatte || inkMode == VisualElementRenderProperties::kInkModeBackgroundTransparent) {
 			const ColorRGB8 transColorRGB8 = _renderProps.getBackColor();
 			uint32 transColor = optimized->format.ARGBToColor(0, transColorRGB8.r, transColorRGB8.g, transColorRGB8.b);
diff --git a/engines/mtropolis/modifiers.cpp b/engines/mtropolis/modifiers.cpp
index bac15fe5150..614720a9169 100644
--- a/engines/mtropolis/modifiers.cpp
+++ b/engines/mtropolis/modifiers.cpp
@@ -163,6 +163,15 @@ void BehaviorModifier::disable(Runtime *runtime) {
 		child->disable(runtime);
 }
 
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void BehaviorModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+
+	report->declareDynamic("switchable", _switchable ? "true" : "false");
+	report->declareDynamic("enabled", _isEnabled ? "true" : "false");
+}
+#endif
+
 VThreadState BehaviorModifier::switchTask(const SwitchTaskData &taskData) {
 	if (_isEnabled != taskData.targetState) {
 		_isEnabled = taskData.targetState;
@@ -2532,11 +2541,25 @@ bool ImageEffectModifier::respondsToEvent(const Event &evt) const {
 }
 
 VThreadState ImageEffectModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
-	warning("Image effect modifier not implemented");
+	if (_removeWhen.respondsTo(msg->getEvent())) {
+		RemoveTaskData *removeTask = runtime->getVThread().pushTask("ImageEffectModifier::removeTask", this, &ImageEffectModifier::removeTask);
+		removeTask->runtime = runtime;
+	}
+	if (_applyWhen.respondsTo(msg->getEvent())) {
+		ApplyTaskData *applyTask = runtime->getVThread().pushTask("ImageEffectModifier::applyTask", this, &ImageEffectModifier::applyTask);
+		applyTask->runtime = runtime;
+	}
+
 	return kVThreadReturn;
 }
 
 void ImageEffectModifier::disable(Runtime *runtime) {
+	Structural *structural = findStructuralOwner();
+	if (!structural || !structural->isElement() || !static_cast<Element *>(structural)->isVisual())
+		return;
+
+	VisualElement *visual = static_cast<VisualElement *>(structural);
+	visual->setShading(0, 0, 0, 0);
 }
 
 Common::SharedPtr<Modifier> ImageEffectModifier::shallowClone() const {
@@ -2547,6 +2570,41 @@ const char *ImageEffectModifier::getDefaultName() const {
 	return "Image Effect Modifier";
 }
 
+VThreadState ImageEffectModifier::applyTask(const ApplyTaskData &taskData) {
+	Structural *structural = findStructuralOwner();
+	if (!structural || !structural->isElement() || !static_cast<Element *>(structural)->isVisual())
+		return kVThreadReturn;
+
+	VisualElement *visual = static_cast<VisualElement *>(structural);
+
+	int16 shadingLevel = static_cast<int16>(_toneAmount) * 256 / 100;
+
+	switch (_type) {
+	case kTypeDeselectedBevels:
+		visual->setShading(-shadingLevel, shadingLevel, 0, _bevelWidth);
+		break;
+	case kTypeSelectedBevels:
+		visual->setShading(shadingLevel, -shadingLevel, 0, _bevelWidth);
+		break;
+	case kTypeToneUp:
+		visual->setShading(0, 0, shadingLevel, 0);
+		break;
+	case kTypeToneDown:
+		visual->setShading(0, 0, -shadingLevel, 0);
+		break;
+	default:
+		break;
+	}
+
+	return kVThreadReturn;
+}
+
+VThreadState ImageEffectModifier::removeTask(const RemoveTaskData &taskData) {
+	this->disable(taskData.runtime);
+
+	return kVThreadReturn;
+}
+
 ReturnModifier::ReturnModifier() {
 }
 
diff --git a/engines/mtropolis/modifiers.h b/engines/mtropolis/modifiers.h
index a9fb82349f6..bc4c5fbc860 100644
--- a/engines/mtropolis/modifiers.h
+++ b/engines/mtropolis/modifiers.h
@@ -59,6 +59,7 @@ public:
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Behavior Modifier"; }
 	SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
+	void debugInspect(IDebugInspectionReport *report) const override;
 #endif
 
 private:
@@ -998,9 +999,24 @@ private:
 		kTypeToneUp,
 	};
 
+	struct ApplyTaskData {
+		ApplyTaskData() : runtime(nullptr) {}
+
+		Runtime *runtime;
+	};
+
+	struct RemoveTaskData {
+		RemoveTaskData() : runtime(nullptr) {}
+
+		Runtime *runtime;
+	};
+
 	Common::SharedPtr<Modifier> shallowClone() const override;
 	const char *getDefaultName() const override;
 
+	VThreadState applyTask(const ApplyTaskData &taskData);
+	VThreadState removeTask(const RemoveTaskData &taskData);
+
 	Event _applyWhen;
 	Event _removeWhen;
 	Type _type;
diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index cf43de38edb..f7ee53e18a4 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -4381,11 +4381,10 @@ bool Runtime::runFrame() {
 		if (_forceCursorRefreshOnce) {
 			_forceCursorRefreshOnce = false;
 
-			_mouseOverObject.reset();
-
 			UpdateMousePositionTaskData *taskData = _vthread->pushTask("Runtime::updateMousePositionTask", this, &Runtime::updateMousePositionTask);
 			taskData->x = _cachedMousePosition.x;
 			taskData->y = _cachedMousePosition.y;
+			continue;
 		}
 
 		if (_queuedProjectDesc) {
@@ -8026,7 +8025,8 @@ VisualElementRenderProperties &VisualElementRenderProperties::operator=(const Vi
 }
 
 VisualElement::VisualElement()
-	: _rect(0, 0, 0, 0), _cachedAbsoluteOrigin(Common::Point(0, 0)), _contentsDirty(true), _directToScreen(false), _visible(false), _visibleByDefault(true), _layer(0) {
+	: _rect(0, 0, 0, 0), _cachedAbsoluteOrigin(Common::Point(0, 0)), _contentsDirty(true), _directToScreen(false), _visible(false), _visibleByDefault(true), _layer(0),
+	  _topLeftBevelShading(0), _bottomRightBevelShading(0), _interiorShading(0), _bevelSize(0) {
 }
 
 bool VisualElement::isVisual() const {
@@ -8431,6 +8431,17 @@ const Common::WeakPtr<GraphicModifier> &VisualElement::getPrimaryGraphicModifier
 	return _primaryGraphicModifier;
 }
 
+void VisualElement::setShading(int16 topLeftBevelShading, int16 bottomRightBevelShading, int16 interiorShading, uint32 bevelSize) {
+	if (_topLeftBevelShading != topLeftBevelShading || _bottomRightBevelShading != bottomRightBevelShading || _interiorShading != interiorShading || _bevelSize != bevelSize) {
+		_topLeftBevelShading = topLeftBevelShading;
+		_bottomRightBevelShading = bottomRightBevelShading;
+		_interiorShading = interiorShading;
+		_bevelSize = bevelSize;
+
+		_contentsDirty = true;
+	}
+}
+
 bool VisualElement::needsRender() const {
 	if (_renderProps.isDirty() || _prevRect != _rect || _contentsDirty)
 		return true;
@@ -8727,6 +8738,195 @@ VisualElement *VisualElement::recursiveFindItemWithLayer(VisualElement *element,
 	return nullptr;
 }
 
+void VisualElement::renderShading(Graphics::Surface &surf) const {
+	uint32 bevelSize = _bevelSize;
+	uint32 w = surf.w;
+	uint32 h = surf.h;
+
+	uint32 maxHBevel = (w + 1) / 2;
+	uint32 maxVBevel = (h + 1) / 2;
+
+	if (bevelSize > maxHBevel)
+		bevelSize = maxHBevel;
+	if (bevelSize > maxVBevel)
+		bevelSize = maxVBevel;
+
+	uint32 rMask = surf.format.ARGBToColor(0, 255, 0, 0);
+	uint32 gMask = surf.format.ARGBToColor(0, 0, 255, 0);
+	uint32 bMask = surf.format.ARGBToColor(0, 0, 0, 255);
+
+	byte bytesPerPixel = surf.format.bytesPerPixel;
+
+	if (_topLeftBevelShading != 0) {
+		bool isBrighten = (_topLeftBevelShading > 0);
+
+		uint32 rAdd = quantizeShading(rMask, _topLeftBevelShading);
+		uint32 gAdd = quantizeShading(gMask, _topLeftBevelShading);
+		uint32 bAdd = quantizeShading(bMask, _topLeftBevelShading);
+
+		// Top bar
+		for (uint y = 0; y < bevelSize; y++)
+			renderShadingScanlineDynamic(surf.getBasePtr(0, y), w - y, rMask, rAdd, gMask, gAdd, bMask, bAdd, isBrighten, bytesPerPixel);
+
+		// Left bar
+		uint leftBarEndY = h + 1 - bevelSize;
+		for (uint y = bevelSize; y < leftBarEndY; y++)
+			renderShadingScanlineDynamic(surf.getBasePtr(0, y), bevelSize, rMask, rAdd, gMask, gAdd, bMask, bAdd, isBrighten, bytesPerPixel);
+
+		// Lower diagonal
+		for (uint y = leftBarEndY; y < h; y++)
+			renderShadingScanlineDynamic(surf.getBasePtr(0, y), bevelSize - 1 - (y - leftBarEndY), rMask, rAdd, gMask, gAdd, bMask, bAdd, isBrighten, bytesPerPixel);
+	}
+
+	if (_bottomRightBevelShading != 0) {
+		bool isBrighten = (_bottomRightBevelShading > 0);
+
+		uint32 rAdd = quantizeShading(rMask, _bottomRightBevelShading);
+		uint32 gAdd = quantizeShading(gMask, _bottomRightBevelShading);
+		uint32 bAdd = quantizeShading(bMask, _bottomRightBevelShading);
+
+		// Upper diagonal
+		for (uint y = 1; y < bevelSize; y++)
+			renderShadingScanlineDynamic(surf.getBasePtr(w - y, y), y, rMask, rAdd, gMask, gAdd, bMask, bAdd, isBrighten, bytesPerPixel);
+
+		uint rightBarEndY = h - bevelSize;
+		if (rightBarEndY < bevelSize)
+			rightBarEndY = bevelSize;
+
+		uint rightBarX = w - bevelSize;
+		if (rightBarX < bevelSize)
+			rightBarX = bevelSize;
+
+		// Right bar
+		for (uint y = bevelSize; y < rightBarEndY; y++)
+			renderShadingScanlineDynamic(surf.getBasePtr(rightBarX, y), w - rightBarX, rMask, rAdd, gMask, gAdd, bMask, bAdd, isBrighten, bytesPerPixel);
+
+		// Bottom bar
+		for (uint y = rightBarEndY; y < h; y++) {
+			uint bottomBarStartX = bevelSize - (y - rightBarEndY);
+			renderShadingScanlineDynamic(surf.getBasePtr(bottomBarStartX, y), w - bottomBarStartX, rMask, rAdd, gMask, gAdd, bMask, bAdd, isBrighten, bytesPerPixel);
+		}
+	}
+
+	if (_interiorShading != 0) {
+		uint32 startX = bevelSize;
+		uint32 endX = w - bevelSize;
+		uint32 startY = bevelSize;
+		uint32 endY = h - bevelSize;
+
+		if (startX < endX && startY < endY) {
+			bool isBrighten = (_bottomRightBevelShading > 0);
+
+			uint32 rAdd = quantizeShading(rMask, _bottomRightBevelShading);
+			uint32 gAdd = quantizeShading(gMask, _bottomRightBevelShading);
+			uint32 bAdd = quantizeShading(bMask, _bottomRightBevelShading);
+
+			for (uint y = startY; y < endY; y++)
+				renderShadingScanlineDynamic(surf.getBasePtr(startX, y), endX - startX, rMask, rAdd, gMask, gAdd, bMask, bAdd, isBrighten, bytesPerPixel);
+		}
+	}
+}
+
+uint32 VisualElement::quantizeShading(uint32 mask, int16 shading) {
+	uint32 absShading = (shading < 0) ? static_cast<int32>(-shading) : static_cast<int32>(shading);
+
+	if ((mask & 0xff) == 0) {
+		// Nothing in the low bytes, so shift down to avoid upper bits overflow
+		return ((mask >> 8) * absShading) & mask;
+	}
+
+	// Something was in the low bits, so avoid lower bits underflow instead
+	return ((mask * absShading) >> 8) & mask;
+}
+
+void VisualElement::renderShadingScanlineDynamic(void *data, size_t numElements, uint32 rMask, uint32 rAdd, uint32 gMask, uint32 gAdd, uint32 bMask, uint32 bAdd, bool isBrighten, byte bytesPerPixel) {
+	if (isBrighten) {
+		switch (bytesPerPixel) {
+		case 2:
+			renderBrightenScanline<uint16>(static_cast<uint16 *>(data), numElements, rMask, rAdd, gMask, gAdd, bMask, bAdd);
+			break;
+		case 4:
+			renderBrightenScanline<uint32>(static_cast<uint32 *>(data), numElements, rMask, rAdd, gMask, gAdd, bMask, bAdd);
+			break;
+		default:
+			break;
+		}
+	} else {
+		switch (bytesPerPixel) {
+		case 2:
+			renderDarkenScanline<uint16>(static_cast<uint16 *>(data), numElements, rMask, rAdd, gMask, gAdd, bMask, bAdd);
+			break;
+		case 4:
+			renderDarkenScanline<uint32>(static_cast<uint32 *>(data), numElements, rMask, rAdd, gMask, gAdd, bMask, bAdd);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+template<class TElement>
+void VisualElement::renderBrightenScanline(TElement *element, size_t numElements, TElement rMask, TElement rAdd, TElement gMask, TElement gAdd, TElement bMask, TElement bAdd) {
+	TElement rLimit = rMask - rAdd;
+	TElement gLimit = gMask - gAdd;
+	TElement bLimit = bMask - bAdd;
+
+	while (numElements > 0) {
+		TElement v = *element;
+
+		if ((v & rMask) > rLimit)
+			v |= rMask;
+		else
+			v += rAdd;
+
+		if ((v & gMask) > gLimit)
+			v |= gMask;
+		else
+			v += gAdd;
+
+		if ((v & bMask) > bLimit)
+			v |= bMask;
+		else
+			v += bAdd;
+
+		*element = v;
+
+		numElements--;
+		element++;
+	}
+}
+
+template<class TElement>
+static void VisualElement::renderDarkenScanline(TElement *element, size_t numElements, TElement rMask, TElement rSub, TElement gMask, TElement gSub, TElement bMask, TElement bSub) {
+	TElement rZero = ~rMask;
+	TElement gZero = ~gMask;
+	TElement bZero = ~bMask;
+
+	while (numElements > 0) {
+		TElement v = *element;
+
+		if ((v & rMask) < rSub)
+			v &= rZero;
+		else
+			v -= rSub;
+
+		if ((v & gMask) < gSub)
+			v &= gZero;
+		else
+			v -= gSub;
+
+		if ((v & bMask) < bSub)
+			v &= bZero;
+		else
+			v -= bSub;
+
+		*element = v;
+
+		numElements--;
+		element++;
+	}
+}
+
 bool NonVisualElement::isVisual() const {
 	return false;
 }
diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h
index 8d94ebae0b1..508c47ad685 100644
--- a/engines/mtropolis/runtime.h
+++ b/engines/mtropolis/runtime.h
@@ -2756,6 +2756,8 @@ public:
 	const VisualElementRenderProperties &getRenderProperties() const;
 	const Common::WeakPtr<GraphicModifier> &getPrimaryGraphicModifier() const;
 
+	void setShading(int16 topLeftBevelShading, int16 bottomRightBevelShading, int16 interiorShading, uint32 bevelSize);
+
 	void setTransitionProperties(const VisualElementTransitionProperties &props);
 	const VisualElementTransitionProperties &getTransitionProperties() const;
 
@@ -2803,6 +2805,18 @@ protected:
 
 	static VisualElement *recursiveFindItemWithLayer(VisualElement *element, int32 layer);
 
+	void renderShading(Graphics::Surface &surf) const;
+
+	static uint32 quantizeShading(uint32 mask, int16 shading);
+
+	static void renderShadingScanlineDynamic(void *data, size_t numElements, uint32 rMask, uint32 rAdd, uint32 gMask, uint32 gAdd, uint32 bMask, uint32 bAdd, bool isBrighten, byte bytesPerPixel);
+
+	template<class TElement>
+	static void renderBrightenScanline(TElement *element, size_t numElements, TElement rMask, TElement rAdd, TElement gMask, TElement gAdd, TElement bMask, TElement bAdd);
+
+	template<class TElement>
+	static void renderDarkenScanline(TElement *element, size_t numElements, TElement rMask, TElement rSub, TElement gMask, TElement gSub, TElement bMask, TElement bSub);
+
 	bool _directToScreen;
 	bool _visible;
 	bool _visibleByDefault;
@@ -2810,6 +2824,11 @@ protected:
 	Common::Point _cachedAbsoluteOrigin;
 	uint16 _layer;
 
+	int16 _topLeftBevelShading;
+	int16 _bottomRightBevelShading;
+	int16 _interiorShading;
+	uint32 _bevelSize;
+
 	Common::SharedPtr<DragMotionProperties> _dragProps;
 
 	// Quirk: When a graphic modifier is applied, it becomes the primary graphic modifier, and disabling it


Commit: f3ff05e6589980a5a21bc13d6e48c4c44a255a3b
    https://github.com/scummvm/scummvm/commit/f3ff05e6589980a5a21bc13d6e48c4c44a255a3b
Author: elasota (ejlasota at gmail.com)
Date: 2023-06-07T23:55:33-04:00

Commit Message:
VCRUISE: Properly fix EOS flag handling in Gentee Installer unpacker

Changed paths:
    engines/vcruise/gentee_installer.cpp


diff --git a/engines/vcruise/gentee_installer.cpp b/engines/vcruise/gentee_installer.cpp
index 7640b785bbf..93a8762671d 100644
--- a/engines/vcruise/gentee_installer.cpp
+++ b/engines/vcruise/gentee_installer.cpp
@@ -540,6 +540,7 @@ uint32 DecompressingStream::read(void *dataPtr, uint32 dataSize) {
 	uint32 bytesAvailable = _decompressedSize - _pos;
 
 	if (dataSize > bytesAvailable) {
+		_eosFlag = true;
 		dataSize = bytesAvailable;
 	}
 




More information about the Scummvm-git-logs mailing list