[Scummvm-git-logs] scummvm master -> 7423e9258007491b730cc1acb1826d1c20f844b2

elasota noreply at scummvm.org
Sat Jun 10 21:56:41 UTC 2023


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

Summary:
7423e92580 MTROPOLIS: Add hack to fix black square in MTI's MPZ-1000 screen


Commit: 7423e9258007491b730cc1acb1826d1c20f844b2
    https://github.com/scummvm/scummvm/commit/7423e9258007491b730cc1acb1826d1c20f844b2
Author: elasota (ejlasota at gmail.com)
Date: 2023-06-10T17:55:57-04:00

Commit Message:
MTROPOLIS: Add hack to fix black square in MTI's MPZ-1000 screen

Changed paths:
    engines/mtropolis/assets.cpp
    engines/mtropolis/assets.h
    engines/mtropolis/elements.cpp
    engines/mtropolis/hacks.cpp
    engines/mtropolis/hacks.h


diff --git a/engines/mtropolis/assets.cpp b/engines/mtropolis/assets.cpp
index 658fc7513e5..02b5b61e941 100644
--- a/engines/mtropolis/assets.cpp
+++ b/engines/mtropolis/assets.cpp
@@ -143,11 +143,12 @@ MToonMetadata::MToonMetadata() : imageFormat(kImageFormatWindows), bitsPerPixel(
 CachedMToon::RleFrame::RleFrame() : version(0), width(0), height(0), isKeyframe(0) {
 }
 
-CachedMToon::CachedMToon() : _isRLETemporalCompressed(false) {
+CachedMToon::CachedMToon() : _isRLETemporalCompressed(false), _hackFlags(0) {
 }
 
-bool CachedMToon::loadFromStream(const Common::SharedPtr<MToonMetadata> &metadata, Common::ReadStream *stream, size_t size) {
+bool CachedMToon::loadFromStream(const Common::SharedPtr<MToonMetadata> &metadata, Common::ReadStream *stream, size_t size, uint hackFlags) {
 	_metadata = metadata;
+	_hackFlags = hackFlags;
 
 	Common::Array<uint8> data;
 	data.resize(size);
@@ -207,7 +208,7 @@ void CachedMToon::decompressFrames(const Common::Array<uint8> &data) {
 }
 
 template<class TNumber, uint32 TLiteralMask, uint32 TTransparentRowSkipMask>
-bool CachedMToon::decompressMToonRLE(const RleFrame &frame, const Common::Array<TNumber> &coefsArray, Graphics::ManagedSurface &surface, bool isBottomUp) {
+bool CachedMToon::decompressMToonRLE(const RleFrame &frame, const Common::Array<TNumber> &coefsArray, Graphics::ManagedSurface &surface, bool isBottomUp, uint hackFlags) {
 	assert(sizeof(TNumber) == surface.format.bytesPerPixel);
 
 	size_t size = coefsArray.size();
@@ -244,7 +245,12 @@ bool CachedMToon::decompressMToonRLE(const RleFrame &frame, const Common::Array<
 
 			if (transparentCountCode & TTransparentRowSkipMask) {
 				// Vertical skip
-				y += (transparentCountCode - TTransparentRowSkipMask);
+				uint32 skipAmount = transparentCountCode - TTransparentRowSkipMask;
+
+				if ((hackFlags & MToonHackFlags::kMTIHispaniolaMPZHack) && (transparentCountCode - TTransparentRowSkipMask) == (TTransparentRowSkipMask - 2))
+					skipAmount = 0;
+
+				y += skipAmount;
 				x = 0;
 				if (y < h) {
 					rowData = static_cast<TNumber *>(surface.getBasePtr(0, isBottomUp ? (h - 1 - y) : y));
@@ -303,11 +309,11 @@ void CachedMToon::decompressRLEFrameToImage(size_t frameIndex, Graphics::Managed
 
 	bool decompressedOK = false;
 	if (_rleOptimizedFormat.bytesPerPixel == 4) {
-		decompressedOK = decompressMToonRLE<uint32, 0x80000000u, 0x80000000u>(_rleData[frameIndex], _rleData[frameIndex].data32, surface, isBottomUp);
+		decompressedOK = decompressMToonRLE<uint32, 0x80000000u, 0x80000000u>(_rleData[frameIndex], _rleData[frameIndex].data32, surface, isBottomUp, _hackFlags);
 	} else if (_rleOptimizedFormat.bytesPerPixel == 2) {
-		decompressedOK = decompressMToonRLE<uint16, 0x8000u, 0x8000u>(_rleData[frameIndex], _rleData[frameIndex].data16, surface, isBottomUp);
+		decompressedOK = decompressMToonRLE<uint16, 0x8000u, 0x8000u>(_rleData[frameIndex], _rleData[frameIndex].data16, surface, isBottomUp, _hackFlags);
 	} else if (_rleOptimizedFormat.bytesPerPixel == 1) {
-		decompressedOK = decompressMToonRLE<uint8, 0x80u, 0x80u>(_rleData[frameIndex], _rleData[frameIndex].data8, surface, isBottomUp);
+		decompressedOK = decompressMToonRLE<uint8, 0x80u, 0x80u>(_rleData[frameIndex], _rleData[frameIndex].data8, surface, isBottomUp, _hackFlags);
 	} else
 		error("Unknown mToon encoding");
 
@@ -502,7 +508,7 @@ void CachedMToon::decompressQuickTimeFrame(const Common::Array<uint8> &data, siz
 }
 
 template<class TSrcNumber, uint32 TSrcLiteralMask, uint32 TSrcTransparentSkipMask, class TDestNumber, uint32 TDestLiteralMask, uint32 TDestTransparentSkipMask>
-void CachedMToon::rleReformat(RleFrame &frame, const Common::Array<TSrcNumber> &srcData, const Graphics::PixelFormat &srcFormatRef, Common::Array<TDestNumber> &destData, const Graphics::PixelFormat &destFormatRef) {
+void CachedMToon::rleReformat(RleFrame &frame, const Common::Array<TSrcNumber> &srcData, const Graphics::PixelFormat &srcFormatRef, Common::Array<TDestNumber> &destData, const Graphics::PixelFormat &destFormatRef, uint hackFlags) {
 	const Graphics::PixelFormat srcFormat = srcFormatRef;
 	const Graphics::PixelFormat destFormat = destFormatRef;
 
@@ -594,14 +600,14 @@ void CachedMToon::optimizeRLE(const Graphics::PixelFormat &targetFormatRef) {
 	for (size_t i = 0; i < numFrames; i++) {
 		if (_rleInternalFormat.bytesPerPixel == 2) {
 			if (targetFormat.bytesPerPixel == 4)
-				rleReformat<uint16, 0x8000u, 0x8000u, uint32, 0x80000000u, 0x80000000u>(_rleData[i], _rleData[i].data16, _rleInternalFormat, _rleData[i].data32, targetFormat);
+				rleReformat<uint16, 0x8000u, 0x8000u, uint32, 0x80000000u, 0x80000000u>(_rleData[i], _rleData[i].data16, _rleInternalFormat, _rleData[i].data32, targetFormat, _hackFlags);
 			else if (targetFormat.bytesPerPixel == 2)
-				rleReformat<uint16, 0x8000u, 0x8000u, uint16, 0x8000u, 0x8000u>(_rleData[i], _rleData[i].data16, _rleInternalFormat, _rleData[i].data16, targetFormat);
+				rleReformat<uint16, 0x8000u, 0x8000u, uint16, 0x8000u, 0x8000u>(_rleData[i], _rleData[i].data16, _rleInternalFormat, _rleData[i].data16, targetFormat, _hackFlags);
 		} else if (_rleInternalFormat.bytesPerPixel == 4) {
 			if (targetFormat.bytesPerPixel == 4)
-				rleReformat<uint32, 0x80000000u, 0x80000000u, uint32, 0x80000000u, 0x80000000u>(_rleData[i], _rleData[i].data32, _rleInternalFormat, _rleData[i].data32, targetFormat);
+				rleReformat<uint32, 0x80000000u, 0x80000000u, uint32, 0x80000000u, 0x80000000u>(_rleData[i], _rleData[i].data32, _rleInternalFormat, _rleData[i].data32, targetFormat, _hackFlags);
 			else if (targetFormat.bytesPerPixel == 2)
-				rleReformat<uint32, 0x80000000u, 0x80000000u, uint16, 0x8000u, 0x8000u>(_rleData[i], _rleData[i].data32, _rleInternalFormat, _rleData[i].data16, targetFormat);
+				rleReformat<uint32, 0x80000000u, 0x80000000u, uint16, 0x8000u, 0x8000u>(_rleData[i], _rleData[i].data32, _rleInternalFormat, _rleData[i].data16, targetFormat, _hackFlags);
 		}
 	}
 
@@ -644,11 +650,11 @@ void CachedMToon::getOrRenderFrame(uint32 prevFrame, uint32 targetFrame, Common:
 
 		for (size_t i = firstFrameToRender; i <= targetFrame; i++) {
 			if (_rleOptimizedFormat.bytesPerPixel == 1)
-				decompressMToonRLE<uint8, 0x80u, 0x80u>(_rleData[i], _rleData[i].data8, *surface, isBottomUp);
+				decompressMToonRLE<uint8, 0x80u, 0x80u>(_rleData[i], _rleData[i].data8, *surface, isBottomUp, _hackFlags);
 			else if (_rleOptimizedFormat.bytesPerPixel == 2)
-				decompressMToonRLE<uint16, 0x8000u, 0x8000u>(_rleData[i], _rleData[i].data16, *surface, isBottomUp);
+				decompressMToonRLE<uint16, 0x8000u, 0x8000u>(_rleData[i], _rleData[i].data16, *surface, isBottomUp, _hackFlags);
 			else if (_rleOptimizedFormat.bytesPerPixel == 4)
-				decompressMToonRLE<uint32, 0x80000000u, 0x80000000u>(_rleData[i], _rleData[i].data32, *surface, isBottomUp);
+				decompressMToonRLE<uint32, 0x80000000u, 0x80000000u>(_rleData[i], _rleData[i].data32, *surface, isBottomUp, _hackFlags);
 		}
 	}
 }
@@ -657,8 +663,6 @@ const Common::SharedPtr<MToonMetadata>& CachedMToon::getMetadata() const {
 	return _metadata;
 }
 
-
-
 AudioMetadata::AudioMetadata() : encoding(kEncodingUncompressed), durationMSec(0),
 	sampleRate(0), channels(0), bitsPerSample(0), isBigEndian(false) {
 }
@@ -1097,11 +1101,14 @@ bool MToonAsset::load(AssetLoaderContext &context, const Data::MToonAsset &data)
 	return true;
 }
 
+MToonAsset::MToonAsset() : _frameDataPosition(0), _sizeOfFrameData(0), _streamIndex(0){
+}
+
 AssetType MToonAsset::getAssetType() const {
 	return kAssetTypeMToon;
 }
 
-const Common::SharedPtr<CachedMToon> &MToonAsset::loadAndCacheMToon(Runtime *runtime) {
+const Common::SharedPtr<CachedMToon> &MToonAsset::loadAndCacheMToon(Runtime *runtime, uint hackFlags) {
 	if (_cachedMToon)
 		return _cachedMToon;
 
@@ -1117,7 +1124,7 @@ const Common::SharedPtr<CachedMToon> &MToonAsset::loadAndCacheMToon(Runtime *run
 		return _cachedMToon;
 	}
 
-	if (!cachedMToon->loadFromStream(_metadata, stream, _sizeOfFrameData)) {
+	if (!cachedMToon->loadFromStream(_metadata, stream, _sizeOfFrameData, hackFlags)) {
 		warning("mToon data failed to load");
 		return _cachedMToon;
 	}
diff --git a/engines/mtropolis/assets.h b/engines/mtropolis/assets.h
index 2c076cad766..1a4b7218acb 100644
--- a/engines/mtropolis/assets.h
+++ b/engines/mtropolis/assets.h
@@ -59,6 +59,14 @@ private:
 	Common::Array<uint8> _data;
 };
 
+namespace MToonHackFlags {
+
+enum MToonHackFlag {
+	kMTIHispaniolaMPZHack = 1,
+};
+
+} // End of namespace MToonHackFlags
+
 struct MToonMetadata {
 	enum ImageFormat {
 		kImageFormatMac,
@@ -106,7 +114,7 @@ class CachedMToon {
 public:
 	CachedMToon();
 
-	bool loadFromStream(const Common::SharedPtr<MToonMetadata> &metadata, Common::ReadStream *stream, size_t size);
+	bool loadFromStream(const Common::SharedPtr<MToonMetadata> &metadata, Common::ReadStream *stream, size_t size, uint hackFlags);
 
 	void optimize(Runtime *runtime);
 
@@ -141,10 +149,10 @@ private:
 	void decompressQuickTimeFrame(const Common::Array<uint8> &data, size_t frameIndex);
 
 	template<class TSrcNumber, uint32 TSrcLiteralMask, uint32 TSrcTransparentSkipMask, class TDestNumber, uint32 TDestLiteralMask, uint32 TDestTransparentSkipMask>
-	void rleReformat(RleFrame &frame, const Common::Array<TSrcNumber> &srcData, const Graphics::PixelFormat &srcFormatRef, Common::Array<TDestNumber> &destData, const Graphics::PixelFormat &destFormatRef);
+	void rleReformat(RleFrame &frame, const Common::Array<TSrcNumber> &srcData, const Graphics::PixelFormat &srcFormatRef, Common::Array<TDestNumber> &destData, const Graphics::PixelFormat &destFormatRef, uint hackFlags);
 
 	template<class TNumber, uint32 TLiteralMask, uint32 TTransparentRowSkipMask>
-	static bool decompressMToonRLE(const RleFrame &frame, const Common::Array<TNumber> &coefsArray, Graphics::ManagedSurface &surface, bool isBottomUp);
+	static bool decompressMToonRLE(const RleFrame &frame, const Common::Array<TNumber> &coefsArray, Graphics::ManagedSurface &surface, bool isBottomUp, uint hackFlags);
 
 	Common::Array<RleFrame> _rleData;
 	bool _isRLETemporalCompressed;
@@ -156,6 +164,8 @@ private:
 	Graphics::PixelFormat _rleOptimizedFormat;
 
 	Common::SharedPtr<MToonMetadata> _metadata;
+
+	uint _hackFlags;
 };
 
 struct AudioMetadata {
@@ -281,10 +291,12 @@ private:
 
 struct MToonAsset : public Asset {
 public:
+	MToonAsset();
+
 	bool load(AssetLoaderContext &context, const Data::MToonAsset &data);
 	AssetType getAssetType() const override;
 
-	const Common::SharedPtr<CachedMToon> &loadAndCacheMToon(Runtime *runtime);
+	const Common::SharedPtr<CachedMToon> &loadAndCacheMToon(Runtime *runtime, uint hackFlags);
 
 private:
 	uint32 _frameDataPosition;
diff --git a/engines/mtropolis/elements.cpp b/engines/mtropolis/elements.cpp
index 31a73e9b544..89110dbf9c0 100644
--- a/engines/mtropolis/elements.cpp
+++ b/engines/mtropolis/elements.cpp
@@ -1340,7 +1340,12 @@ void MToonElement::activate() {
 		return;
 	}
 
-	_cachedMToon = static_cast<MToonAsset *>(asset.get())->loadAndCacheMToon(getRuntime());
+	uint hackFlags = 0;
+	if (getRuntime()->getHacks().mtiHispaniolaMToonHack && project->getAssetNameByID(_assetID) == "G00_HispaniolaMPZ.TUN") {
+		hackFlags |= MToonHackFlags::kMTIHispaniolaMPZHack;
+	}
+
+	_cachedMToon = static_cast<MToonAsset *>(asset.get())->loadAndCacheMToon(getRuntime(), hackFlags);
 	_metadata = _cachedMToon->getMetadata();
 
 	_playMediaSignaller = project->notifyOnPlayMedia(this);
diff --git a/engines/mtropolis/hacks.cpp b/engines/mtropolis/hacks.cpp
index 1bcf01908f0..751d484934f 100644
--- a/engines/mtropolis/hacks.cpp
+++ b/engines/mtropolis/hacks.cpp
@@ -44,6 +44,7 @@ Hacks::Hacks() {
 	allowAssetsFromOtherScenes = false;
 	mtiVariableReferencesHack = false;
 	mtiSceneReturnHack = false;
+	mtiHispaniolaMToonHack = false;
 }
 
 Hacks::~Hacks() {
@@ -1054,6 +1055,10 @@ void addMTIQuirks(const MTropolisGameDescription &desc, Hacks &hacks) {
 	// scene, which is supposed to activate a scene transtion modifier in the scene that transitions to itself.
 	// This doesn't work because the modifier is gone when the scene is unloaded.
 	hacks.mtiSceneReturnHack = true;
+
+	// Weird rendering bug in the MTZ-1000 Hispaniola mToon, it has a skip code that would normally skip 127 rows but
+	// doing that causes a big hole in the image.
+	hacks.mtiHispaniolaMToonHack = true;
 }
 
 } // End of namespace HackSuites
diff --git a/engines/mtropolis/hacks.h b/engines/mtropolis/hacks.h
index b1751c7a2a8..743c0a32f7d 100644
--- a/engines/mtropolis/hacks.h
+++ b/engines/mtropolis/hacks.h
@@ -54,6 +54,7 @@ struct Hacks {
 	bool allowAssetsFromOtherScenes;
 	bool mtiVariableReferencesHack;
 	bool mtiSceneReturnHack;
+	bool mtiHispaniolaMToonHack;
 
 	uint midiVolumeScale;	// 256 = 1.0
 




More information about the Scummvm-git-logs mailing list