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

sev- noreply at scummvm.org
Sat Jul 25 11:03:25 UTC 2026


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:
d3f4dcb5d8 DIRECTOR: Fix config chunk size and tag when saving movies


Commit: d3f4dcb5d8639a8aac0e8a5433b487b5e0bf9967
    https://github.com/scummvm/scummvm/commit/d3f4dcb5d8639a8aac0e8a5433b487b5e0bf9967
Author: Gianluca Boiano (morf3089 at gmail.com)
Date: 2026-07-25T13:03:20+02:00

Commit Message:
DIRECTOR: Fix config chunk size and tag when saving movies

Fixes checksum and length warnings reloading saved director-tests/saving movies

Changed paths:
    engines/director/archive-save.cpp
    engines/director/cast.cpp
    engines/director/cast.h


diff --git a/engines/director/archive-save.cpp b/engines/director/archive-save.cpp
index c77f9c974fc..d1ce7e9fb82 100644
--- a/engines/director/archive-save.cpp
+++ b/engines/director/archive-save.cpp
@@ -116,11 +116,21 @@ bool RIFXArchive::writeToFile(Common::String filename, Movie *movie) {
 			break;
 
 		case MKTAG('V', 'W', 'C', 'F'):
-			// There is only 'VWCF' resource, that is for the internal cast
+		case MKTAG('D', 'R', 'C', 'F'):
+			// There is only one config resource, that is for the internal cast
 			// The external casts don't have a config
 			// movie->getCast() returns the internal cast
 			cast = movie->getCast();
-			cast->saveConfig(saveFile, it->offset);
+			if (cast->getConfigSize() == 0) {
+				// Unsupported version (D10+): keep the original bytes
+				debugC(7, kDebugSaving, "Saving resource %s as it is, without modification", tag2str(it->tag));
+				saveFile->seek(it->offset, SEEK_SET);
+				saveFile->writeUint32LE(it->tag);
+				saveFile->writeUint32LE(it->size);
+				saveFile->writeStream(getResource(it->tag, it->index));
+			} else {
+				cast->saveConfig(saveFile, it->offset, it->tag);
+			}
 			break;
 
 		case MKTAG('B', 'I', 'T', 'D'):
@@ -516,16 +526,23 @@ Common::Array<Resource *> RIFXArchive::rebuildResources(Movie *movie) {
 			break;
 
 		case MKTAG('V', 'W', 'C', 'F'):
+		case MKTAG('D', 'R', 'C', 'F'):
 			{
-				// Only one cast config per movie
+				// Only one config resource per movie
 				// No need to update the key mapping
 				cast = movie->getCast();
 				resSize = cast->getConfigSize();
 
 				it->offset = currentSize;
 
+				if (resSize == 0) {
+					// Unsupported Director version: keep the original size
+					resSize = it->size;
+				} else {
+					it->size = resSize;
+				}
+
 				currentSize += resSize + 8;			// getConfigSize() doesn't include header and size
-				it->size = resSize;
 			}
 			break;
 
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 666c348369d..b1cabd72bda 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -635,7 +635,7 @@ bool Cast::loadConfig() {
 	return true;
 }
 
-void Cast::saveConfig(Common::SeekableWriteStream *writeStream, uint32 offset) {
+void Cast::saveConfig(Common::SeekableWriteStream *writeStream, uint32 offset, uint32 tag) {
 	if (_version < kFileVer400) {
 		error("Cast::saveConfig called on a pre-D4 Director movie");
 	}
@@ -644,7 +644,7 @@ void Cast::saveConfig(Common::SeekableWriteStream *writeStream, uint32 offset) {
 
 	uint32 configSize = getConfigSize();
 
-	writeStream->writeUint32LE(MKTAG('V', 'W', 'C', 'F'));
+	writeStream->writeUint32LE(tag);
 	writeStream->writeUint32LE(configSize);
 
 	// These offsets are only for Director Version 4 to Director version 6
@@ -655,8 +655,10 @@ void Cast::saveConfig(Common::SeekableWriteStream *writeStream, uint32 offset) {
 	Movie::writeRect(writeStream, _checkRect);      // 4, 6, 8, 10
 
 	writeStream->writeUint16BE(_castArrayStartForChecksum);    // 12
-	// This will change
-	writeStream->writeUint16BE(_castArrayStartForChecksum + _castArchive->getResourceIDList(MKTAG('C', 'A', 'S', 't')).size());      // 14
+
+	// computeChecksum() reads this field; keep it in sync with the disk
+	_castArrayEndForChecksum = _castArrayStartForChecksum + _castArchive->getResourceIDList(MKTAG('C', 'A', 'S', 't')).size();
+	writeStream->writeUint16BE(_castArrayEndForChecksum);      // 14
 
 	writeStream->writeByte(_readRate);              // 16
 	writeStream->writeByte(_lightswitch);           // 17
@@ -691,21 +693,24 @@ void Cast::saveConfig(Common::SeekableWriteStream *writeStream, uint32 offset) {
 	uint32 checksum = computeChecksum();
 	writeStream->writeUint32BE(checksum);           // 64
 
+	// Reverse the builtin-palette offset applied by loadConfig()
+	int16 paletteMember = _defaultPalette.member;
+	if (paletteMember < 0)
+		paletteMember += 1;
 	if (_version >= kFileVer400 && _version < kFileVer500) {
 		writeStream->writeSint16BE(_field30);       // 68
+		writeStream->writeSint16BE(paletteMember);  // 70
 
-		// This loop isn't writing meaningful data currently
-		// But it is possible that this data might be needed
-		for (int i = 0; i < 0x08; i++) {
-			writeStream->writeByte(0);              // 70, 71, 72, 73, 74, 75, 76, 77
-		}
-	} else if (_version >= kFileVer500 && _version < kFileVer600) {
 		for (int i = 0; i < 0x08; i++) {
-			writeStream->writeByte(0);              // 68, 69, 70, 71, 72, 73, 74, 75
+			writeStream->writeByte(0);              // 72, 73, 74, 75, 76, 77, 78, 79
 		}
+	} else if (_version >= kFileVer500 && _version < kFileVer1000) {
+		writeStream->writeSint16BE(_field30);       // 68
+		writeStream->writeSint16BE(_defPaletteNum);      // 70
+		writeStream->writeSint32BE(_chunkBaseNum);       // 72
 
 		writeStream->writeSint16BE(_defaultPalette.castLib);    // 76
-		writeStream->writeSint16BE(_defaultPalette.member);     // 78
+		writeStream->writeSint16BE(paletteMember);              // 78
 	}
 
 	if (_version >= kFileVer600 && _version < kFileVer1000) {
@@ -745,12 +750,12 @@ void Cast::saveConfig(Common::SeekableWriteStream *writeStream, uint32 offset) {
 
 uint32 Cast::getConfigSize() {
 	if (_version >= kFileVer400 && _version < kFileVer500) {
-		return 78; // 78 bytes of data in castConfig
-	} else if (_version >= kFileVer500 && _version < kFileVer600) {
 		return 80;	// 80 bytes of data in castConfig
+	} else if (_version >= kFileVer500 && _version < kFileVer1000) {
+		return _version < kFileVer600 ? 80 : 84;	// D5: 80 bytes; D6-D9: 84 bytes
 	}
 
-	warning("Cast::getConfigSize: Director version 6+ is not handled");
+	warning("Cast::getConfigSize: Director version %d is not handled", humanVersion(_version));
 	return 0;
 }
 
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 1ab81f0ffe5..7325732d977 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -110,7 +110,7 @@ public:
 	void loadSord(Common::SeekableReadStreamEndian &stream);
 	bool importFileInto(int castId, const Common::Path &path);
 
-	void saveConfig(Common::SeekableWriteStream *writeStream, uint32 offset);
+	void saveConfig(Common::SeekableWriteStream *writeStream, uint32 offset, uint32 tag);
 	void saveCastData(Common::SeekableWriteStream *writeStream, Resource *res);
 	void saveCastData();
 	void writeCastInfo(Common::SeekableWriteStream *writeStream, uint32 castId);




More information about the Scummvm-git-logs mailing list