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

sev- noreply at scummvm.org
Wed Sep 3 21:53:05 UTC 2025


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

Summary:
b1a5acf067 DIRECTOR: Properly read BitmapCastMembers for D6+


Commit: b1a5acf0673350a26dfe9ef2142d8669e56f94d7
    https://github.com/scummvm/scummvm/commit/b1a5acf0673350a26dfe9ef2142d8669e56f94d7
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2025-09-03T23:52:58+02:00

Commit Message:
DIRECTOR: Properly read BitmapCastMembers for D6+

Changed paths:
    engines/director/castmember/bitmap.cpp
    engines/director/castmember/bitmap.h


diff --git a/engines/director/castmember/bitmap.cpp b/engines/director/castmember/bitmap.cpp
index 6d78b08cbf9..1b377a7fcb1 100644
--- a/engines/director/castmember/bitmap.cpp
+++ b/engines/director/castmember/bitmap.cpp
@@ -57,6 +57,9 @@ BitmapCastMember::BitmapCastMember(Cast *cast, uint16 castId, Common::SeekableRe
 	_ditheredTargetClut = CastMemberID(0, 0);
 	_bitsPerPixel = 0;
 	_external = false;
+	_editVersion = 0;
+	_updateFlags = 0;
+	_version = version;
 
 	if (debugChannelSet(5, kDebugLoading)) {
 		stream.hexdump(stream.size());
@@ -65,6 +68,9 @@ BitmapCastMember::BitmapCastMember(Cast *cast, uint16 castId, Common::SeekableRe
 	if (version < kFileVer400) {
 		_flags1 = flags1;	// region: 0 - auto, 1 - matte, 2 - disabled
 
+		_updateFlags |= (_flags1 & kFlagCenterRegPointD4) ? kFlagCenterRegPoint : 0;
+		_updateFlags |= (_flags1 & kFlagMatteD4) ? kFlagMatte : 0;
+
 		_bytes = stream.readUint16();
 		// A little context about how bitmap bounding boxes are stored.
 		// In the Director editor, images can be edited on a big scrolling canvas with
@@ -100,8 +106,12 @@ BitmapCastMember::BitmapCastMember(Cast *cast, uint16 castId, Common::SeekableRe
 		_pitch *= _bitsPerPixel;
 		_pitch >>= 3;
 
-	} else if (version >= kFileVer400 && version < kFileVer700) {
+	} else if (version >= kFileVer400 && version < kFileVer600) {
 		_flags1 = flags1;
+
+		_updateFlags |= (_flags1 & kFlagCenterRegPointD4) ? kFlagCenterRegPoint : 0;
+		_updateFlags |= (_flags1 & kFlagMatteD4) ? kFlagMatte : 0;
+
 		_pitch = stream.readUint16();
 		_pitch &= 0x0fff;
 
@@ -146,6 +156,65 @@ BitmapCastMember::BitmapCastMember(Cast *cast, uint16 castId, Common::SeekableRe
 		if (_bitsPerPixel == 0)
 			_bitsPerPixel = 1;
 
+		int tail = stream.size() - stream.pos();
+		if (tail > 0) {
+			warning("BUILDBOT: BitmapCastMember: %d bytes left", tail);
+			if (debugChannelSet(2, kDebugLoading)) {
+				byte buf[256];
+				tail = MIN(256, tail);
+				stream.read(buf, tail);
+				debug("BitmapCastMember: tail");
+				Common::hexdump(buf, tail);
+			}
+		}
+	} else if (version >= kFileVer600 && version < kFileVer1100) {
+		_flags1 = flags1;
+		_pitch = stream.readUint16();
+
+		_initialRect = Movie::readRect(stream);
+
+		if (version >= kFileVer700) {
+			_alphaThreshold = stream.readByte();
+			stream.readByte(); // padding
+		} else {
+			stream.readUint16(); // padding
+		}
+
+		_editVersion = stream.readUint16();
+
+		_scrollPoint.y = stream.readSint16();
+		_scrollPoint.x = stream.readSint16();
+
+		_regY = stream.readUint16();
+		_regX = stream.readUint16();
+
+		_updateFlags = stream.readByte();
+
+		// 22 bytes
+		// This is color image flag
+		if (_pitch & 0x8000) {
+			_pitch &= 0x0fff;
+
+			_bitsPerPixel = stream.readByte();
+
+			int clutCastLib = -1;
+			if (version >= kFileVer500) {
+				clutCastLib = stream.readSint16();
+			}
+			int clutId = stream.readSint16();
+
+			if (clutId <= 0) // builtin palette
+				_clut = CastMemberID(clutId - 1, -1);
+			else if (clutId > 0) {
+				if (clutCastLib == -1) {
+					clutCastLib = _cast->_castLibID;
+				}
+				_clut = CastMemberID(clutId, clutCastLib);
+			}
+		} else {
+			_bitsPerPixel = 1;
+		}
+
 		int tail = stream.size() - stream.pos();
 		if (tail > 0) {
 			warning("BUILDBOT: BitmapCastMember: %d bytes left", tail);
@@ -187,6 +256,10 @@ BitmapCastMember::BitmapCastMember(Cast *cast, uint16 castId, Image::ImageDecode
 	_flags2 = 0;
 	_tag = 0;
 	_external = false;
+	_editVersion = 0;
+	_updateFlags = 0;
+
+	_version = g_director->getVersion();
 }
 
 BitmapCastMember::BitmapCastMember(Cast *cast, uint16 castId, BitmapCastMember &source)
@@ -212,6 +285,9 @@ BitmapCastMember::BitmapCastMember(Cast *cast, uint16 castId, BitmapCastMember &
 	_bytes = source._bytes;
 	_clut = source._clut;
 	_ditheredTargetClut = source._ditheredTargetClut;
+	_editVersion = source._editVersion;
+	_updateFlags = source._updateFlags;
+	_scrollPoint = source._scrollPoint;
 
 	_bitsPerPixel = source._bitsPerPixel;
 
@@ -219,6 +295,8 @@ BitmapCastMember::BitmapCastMember(Cast *cast, uint16 castId, BitmapCastMember &
 	_noMatte = source._noMatte;
 	_external = source._external;
 
+	_version = source._version;
+
 	warning("BitmapCastMember(): Duplicating source %d to target %d! This is unlikely to work properly, as the resource loader is based on the cast ID", source._castId, castId);
 }
 
@@ -548,15 +626,28 @@ Graphics::Surface *BitmapCastMember::getMatte(const Common::Rect &bbox) {
 }
 
 Common::String BitmapCastMember::formatInfo() {
-	return Common::String::format(
-		"initialRect: %dx%d@%d,%d, boundingRect: %dx%d@%d,%d, foreColor: %d, backColor: %d, regX: %d, regY: %d, pitch: %d, bitsPerPixel: %d, palette: %s",
-		_initialRect.width(), _initialRect.height(),
-		_initialRect.left, _initialRect.top,
-		_boundingRect.width(), _boundingRect.height(),
-		_boundingRect.left, _boundingRect.top,
-		getForeColor(), getBackColor(),
-		_regX, _regY, _pitch, _bitsPerPixel, _clut.asString().c_str()
-	);
+	if (_version < kFileVer600) {
+		return Common::String::format(
+			"initialRect: %dx%d@%d,%d, boundingRect: %dx%d@%d,%d, foreColor: %d, backColor: %d, regX: %d, regY: %d, pitch: %d, bitsPerPixel: %d, palette: %s",
+			_initialRect.width(), _initialRect.height(),
+			_initialRect.left, _initialRect.top,
+			_boundingRect.width(), _boundingRect.height(),
+			_boundingRect.left, _boundingRect.top,
+			getForeColor(), getBackColor(),
+			_regX, _regY, _pitch, _bitsPerPixel, _clut.asString().c_str()
+		);
+	} else {
+		return Common::String::format(
+			"initialRect: %dx%d@%d,%d, scrollPoint: %d,%d, alphaThreshold: %d, foreColor: %d, backColor: %d, regX: %d, regY: %d, pitch: %d, bitsPerPixel: %d, palette: %s, editVersion: %d, updateFlags: 0x%02x",
+			_initialRect.width(), _initialRect.height(),
+			_initialRect.left, _initialRect.top,
+			_scrollPoint.x, _scrollPoint.y,
+			_alphaThreshold,
+			getForeColor(), getBackColor(),
+			_regX, _regY, _pitch, _bitsPerPixel, _clut.asString().c_str(),
+			_editVersion, _updateFlags
+		);
+	}
 }
 
 void BitmapCastMember::load() {
@@ -1012,6 +1103,8 @@ void BitmapCastMember::writeCastData(Common::SeekableWriteStream *writeStream) {
 	writeStream->writeUint16BE(_regY);
 	writeStream->writeUint16BE(_regX);
 
+	warning("BitmapCastMember::writeCastData(): TODO process D6+");
+
 	if (_bitsPerPixel != 0) {
 		writeStream->writeByte(0);		// Skip one byte (not stored)
 		writeStream->writeByte(_bitsPerPixel);
diff --git a/engines/director/castmember/bitmap.h b/engines/director/castmember/bitmap.h
index 77aa9d01f2e..d505538401f 100644
--- a/engines/director/castmember/bitmap.h
+++ b/engines/director/castmember/bitmap.h
@@ -74,19 +74,58 @@ public:
 	Graphics::Surface *_ditheredImg;
 	Graphics::Surface *_matte;
 
-	uint16 _pitch;
-	int16 _regX;
-	int16 _regY;
+	int _version;
+
 	uint16 _flags2;
 	uint16 _bytes;
 	CastMemberID _clut;
 	CastMemberID _ditheredTargetClut;
 
-	uint8 _bitsPerPixel;
-
 	uint32 _tag;
 	bool _noMatte;
 	bool _external;
+
+	// D4 stucture:
+	// uint16 _pitch;
+	// _initialRect			// 2
+	// _boundingRect		// 10
+	// int16 _regY;			// 18
+	// int16 _regX;			// 20
+	// uint8 _bitsPerPixel;	// 22  when _pitch & 0x8000
+
+	// D6+ structure
+	uint16 _pitch;
+	// _initialRect			// 2
+	// _boundingRect		// 10  D%-
+	byte _alphaThreshold; 	// 10  D7+
+	   // padding
+	uint16 _editVersion;	// 12  D6+
+	Common::Point _scrollPoint; // 14
+	int16 _regY;			// 18
+	int16 _regX;			// 20
+	byte _updateFlags;		// 21
+
+	uint8 _bitsPerPixel;	// 22  when _pitch & 0x8000
+
+	// These sit in _flags1
+	enum {
+		kFlagCenterRegPointD4	= 0x01,	// centerRegPoint property
+		kFlagMatteD4			= 0x20,	// double check value
+	};
+
+	enum {
+		kFlagDither 			= 0x01,	// Bitmap needs dithering
+		kFlagRemapPalette 		= 0x02,	// Bitmap needs palette remap
+		kFlagSyncPalette 		= 0x04,	// When bitmap comes from outside, sync its palette castmember
+		kFlagDitherOnUpdate 	= 0x08,	// Forced dither
+
+		// D7+
+		kFlagFollowAlpha 		= 0x10,	// Alpha channel for 32-bit images must be followed
+		kFlagCenterRegPoint 	= 0x20,	// centerRegPoint property
+		kFlagMatte 				= 0x40,	// it is used for matte image
+		kFlagNoAutoCrop 		= 0x80,	// do not automatically crop the image
+	};
+
 };
 
 } // End of namespace Director




More information about the Scummvm-git-logs mailing list