[Scummvm-git-logs] scummvm master -> 8c5ad09c1af92a6bbb9bd5231e2ce5e5c628f3d7

sev- noreply at scummvm.org
Sun Sep 14 20:35:40 UTC 2025


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

Summary:
6e39a2fc88 DIRECTOR: Switch Score to _version instead of vm->getVersion()
0ae103b567 DIRECTOR: Compute maximum number of channels used in Score
e38046806f DIRECTOR: DT: Do not show long tail of unused sprites in score
18814581c2 DIRECTOR: Load behavior details on frame loading
a5553a246c DIRECTOR: DT: Use preloaded behaviors when displaying Channels
8c5ad09c1a DIRECTOR: Read Script channel behavior


Commit: 6e39a2fc88fd9c6cd11c4e2fe293308416504e09
    https://github.com/scummvm/scummvm/commit/6e39a2fc88fd9c6cd11c4e2fe293308416504e09
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2025-09-14T22:35:27+02:00

Commit Message:
DIRECTOR: Switch Score to _version instead of vm->getVersion()

Since we are dealing with the internal Score structure, I believe,
this approach is more consistent.

Changed paths:
    engines/director/score.cpp


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 025d5df3c54..14b84c677f4 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -322,7 +322,7 @@ void Score::startPlay() {
 		return;
 	}
 
-	if (_vm->getVersion() >= 300)
+	if (_version >= kFileVer300)
 		_movie->processEvent(kEventStartMovie);
 
 	// load first frame (either 1 or _nextFrame)
@@ -349,7 +349,7 @@ void Score::step() {
 	if (!_movie->_inputEventQueue.empty() && !_window->frozenLingoStateCount()) {
 		_lingo->processEvents(_movie->_inputEventQueue, true);
 	}
-	if (_vm->getVersion() >= 300 && !_window->_newMovieStarted && _playState != kPlayStopped) {
+	if (_version >= kFileVer300 && !_window->_newMovieStarted && _playState != kPlayStopped) {
 		_movie->processEvent(kEventIdle);
 	}
 
@@ -374,7 +374,7 @@ void Score::stopPlay() {
 	if (_stopPlayCalled)
 		return;
 	_stopPlayCalled = true;
-	if (_vm->getVersion() >= 300)
+	if (_version >= kFileVer300)
 		_movie->processEvent(kEventStopMovie);
 	_lingo->executePerFrameHook(-1, 0);
 }
@@ -482,7 +482,7 @@ void Score::updateCurrentFrame() {
 		// Cache the previous bounding box for the purposes of rollOver.
 		// If the sprite is blank, D4 and below will use whatever the previous valid bounding
 		// box was for rollOver testing.
-		if (g_director->getVersion() < 500) {
+		if (_version < kFileVer500) {
 			for (uint ch = 0; ch < _channels.size(); ch++) {
 				if (_channels[ch]->_sprite->_castId.member != 0) {
 					_channels[ch]->_rollOverBbox = _channels[ch]->getBbox();
@@ -524,11 +524,11 @@ void Score::updateNextFrameTime() {
 	}
 
 	if (tempo) {
-		const bool waitForClickOnly = _vm->getVersion() < 300;
+		const bool waitForClickOnly = _version < kFileVer300;
 		int maxDelay = 60;
-		if (_vm->getVersion() < 300) {
+		if (_version < kFileVer300) {
 			maxDelay = 120;
-		} else if (_vm->getVersion() < 400) {
+		} else if (_version < kFileVer400) {
 			// Director 3 has a slider that goes up to 120, but any value
 			// beyond 95 gets converted into a video wait instruction.
 			maxDelay = 95;
@@ -650,7 +650,7 @@ void Score::update() {
 	uint32 count = _window->frozenLingoStateCount();
 
 	// Director 4 and below will allow infinite recursion via the perFrameHook.
-	if (_vm->getVersion() < 500) {
+	if (_version < kFileVer500) {
 		// new frame, first call the perFrameHook (if one exists)
 		if (!_window->_newMovieStarted && !_vm->_playbackPaused) {
 			// Call the perFrameHook as soon as a frame switch is done.
@@ -665,7 +665,7 @@ void Score::update() {
 	}
 
 	// Check to see if we've hit the recursion limit
-	if (_vm->getVersion() >= 400 && _window->frozenLingoRecursionCount() >= 2) {
+	if (_version >= kFileVer400 && _window->frozenLingoRecursionCount() >= 2) {
 		debugC(1, kDebugEvents, "Score::update(): hitting D4 recursion depth limit, defrosting");
 		processFrozenScripts(true);
 		return;
@@ -676,7 +676,7 @@ void Score::update() {
 	}
 
 	// Director 5 and above actually check for recursion for the perFrameHook.
-	if (_vm->getVersion() >= 500) {
+	if (_version >= kFileVer500) {
 		// new frame, first call the perFrameHook (if one exists)
 		if (!_window->_newMovieStarted && !_vm->_playbackPaused) {
 			// Call the perFrameHook as soon as a frame switch is done.
@@ -690,7 +690,7 @@ void Score::update() {
 			return;
 	}
 
-	if (_vm->getVersion() >= 600) {
+	if (_version >= kFileVer600) {
 		// _movie->processEvent(kEventBeginSprite);
 		// TODO: Director 6 step: send beginSprite event to any sprites whose span begin in the upcoming frame
 		// _movie->processEvent(kEventPrepareFrame);
@@ -704,7 +704,7 @@ void Score::update() {
 	// then call the stepMovie hook (if one exists)
 	// D4 and above only call it if _allowOutdatedLingo is enabled.
 	count = _window->frozenLingoStateCount();
-	if (!_vm->_playbackPaused && (_vm->getVersion() < 400 || _movie->_allowOutdatedLingo)) {
+	if (!_vm->_playbackPaused && (_version < kFileVer400 || _movie->_allowOutdatedLingo)) {
 		_movie->processEvent(kEventStepMovie);
 	}
 	// If this stepMovie call is frozen, drop the next enterFrame event
@@ -712,7 +712,7 @@ void Score::update() {
 		return;
 
 	// If we've hit the recursion limit, don't enterFrame
-	if (_vm->getVersion() >= 400 && _window->frozenLingoRecursionCount() >= 2) {
+	if (_version >= kFileVer400 && _window->frozenLingoRecursionCount() >= 2) {
 		debugC(1, kDebugEvents, "Score::update: exiting early due to recursion depth limit");
 		return;
 	}
@@ -721,7 +721,7 @@ void Score::update() {
 	count = _window->frozenLingoStateCount();
 	if (!_vm->_playbackPaused) {
 		_exitFrameCalled = false;
-		if (_vm->getVersion() >= 400) {
+		if (_version >= kFileVer400) {
 			_movie->processEvent(kEventEnterFrame);
 		}
 	}
@@ -930,7 +930,7 @@ bool Score::renderPrePaletteCycle(RenderMode mode) {
 
 		int frameDelay = 1000 / 60;
 		int fadeFrames = kFadeColorFrames[frameRate - 1];
-		if (_vm->getVersion() >= 500)
+		if (_version >= kFileVer500)
 			fadeFrames = kFadeColorFramesD5[frameRate - 1];
 		byte calcPal[768];
 
@@ -1260,7 +1260,7 @@ void Score::renderPaletteCycle(RenderMode mode) {
 
 				int frameDelay = 1000 / 60;
 				int fadeFrames = kFadeColorFrames[frameRate - 1];
-				if (_vm->getVersion() >= 500)
+				if (_version >= kFileVer500)
 					fadeFrames = kFadeColorFramesD5[frameRate - 1];
 
 				// Wait for a fixed time
@@ -1725,7 +1725,7 @@ void Score::playSoundChannel(bool puppetOnly) {
 	}
 
 	// Channels above 2 are only usable by Lingo.
-	if (g_director->getVersion() >= 300) {
+	if (_version >= kFileVer300) {
 		sound->playPuppetSound(3);
 		sound->playPuppetSound(4);
 	}
@@ -1932,7 +1932,7 @@ bool Score::readOneFrame() {
 
 		while (frameSize != 0) {
 
-			if (_vm->getVersion() < 400) {
+			if (_version < kFileVer400) {
 				channelSize = _framesStream->readByte() * 2;
 				channelOffset = _framesStream->readByte() * 2;
 				frameSize -= channelSize + 2;


Commit: 0ae103b567742bd5851678943f55c43537541b3c
    https://github.com/scummvm/scummvm/commit/0ae103b567742bd5851678943f55c43537541b3c
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2025-09-14T22:35:27+02:00

Commit Message:
DIRECTOR: Compute maximum number of channels used in Score

Changed paths:
    engines/director/score.cpp
    engines/director/score.h


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 14b84c677f4..4e0ca9699b5 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -1751,6 +1751,7 @@ void Score::loadFrames(Common::SeekableReadStreamEndian &stream, uint16 version)
 	}
 
 	_frameDataOffset = 0;
+	_maxChannelsUsed = 0;
 
 	if (version < kFileVer400) {
 		_framesStreamSize = _framesStream->readUint32();
@@ -1844,6 +1845,11 @@ void Score::loadFrames(Common::SeekableReadStreamEndian &stream, uint16 version)
 	// numOfFrames in the header is often incorrect
 	for (_numFrames = 1; loadFrame(_numFrames, false); _numFrames++) {
 		_scoreCache.push_back(new Frame(*_currentFrame));
+
+		for (int i = 0; i < _currentFrame->_sprites.size(); i++) {
+			if (_currentFrame->_sprites[i]->_castId.member && i > _maxChannelsUsed)
+				_maxChannelsUsed = i;
+		}
 	}
 
 	debugC(1, kDebugLoading, "Score::loadFrames(): Calculated, total number of frames %d!", _numFrames);
diff --git a/engines/director/score.h b/engines/director/score.h
index 342cbda65f1..5c28448e35f 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -255,6 +255,8 @@ public:
 	int16 _numChannelsDisplayed;  // D7+, no-op in earlier versions
 	//  20 bytes in total
 
+	int16 _maxChannelsUsed; // max channel number used in the score, used to optimize rendering
+
 	uint _firstFramePosition;
 	uint _indexStart = 0;
 	uint _frameDataOffset = 0;


Commit: e38046806f567f2e9cce9591c3783c80d67f65b5
    https://github.com/scummvm/scummvm/commit/e38046806f567f2e9cce9591c3783c80d67f65b5
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2025-09-14T22:35:27+02:00

Commit Message:
DIRECTOR: DT: Do not show long tail of unused sprites in score

Changed paths:
    engines/director/debugger.cpp
    engines/director/debugger/dt-score.cpp


diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 0a9ca695d04..96ecce2e850 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -332,7 +332,7 @@ bool Debugger::cmdMovie(int argc, const char **argv) {
 bool Debugger::cmdChannels(int argc, const char **argv) {
 	Score *score = g_director->getCurrentMovie()->getScore();
 
-	int maxSize = (int)score->getFramesNum();
+	int maxSize = MIN<int>(score->_maxChannelsUsed + 3, score->_scoreCache[0]->_sprites.size());
 	int frameId = score->getCurrentFrameNum();
 	if (argc == 1) {
 		debugPrintf("Channel info for current frame %d of %d\n", frameId, maxSize);
diff --git a/engines/director/debugger/dt-score.cpp b/engines/director/debugger/dt-score.cpp
index fa78b61a109..199d5d19e64 100644
--- a/engines/director/debugger/dt-score.cpp
+++ b/engines/director/debugger/dt-score.cpp
@@ -571,7 +571,7 @@ void showScore() {
 			ImGui::EndChild();
 		}
 
-		uint numChannels = score->_scoreCache[0]->_sprites.size();
+		uint numChannels = MIN<int>(score->_scoreCache[0]->_sprites.size(), score->_maxChannelsUsed + 10);
 		uint tableColumns = MAX(numFrames + 5, 25U); // Set minimal table width to 25
 
 		if (tableColumns > kMaxColumnsInTable - 3) // Current restriction of ImGui
@@ -793,7 +793,8 @@ void showChannels() {
 			ImGui::TableSetupColumn("movieTime", flags);
 
 			ImGui::TableAngledHeadersRow();
-			for (int i = 0; i < frame._numChannels; i++) {
+
+			for (int i = 0; i < MIN<int>(frame._numChannels, score->_maxChannelsUsed + 10); i++) {
 				Channel &channel = *score->_channels[i + 1];
 				Sprite &sprite = *channel._sprite;
 


Commit: 18814581c258ef41b526e7f3e7035a8f63972706
    https://github.com/scummvm/scummvm/commit/18814581c258ef41b526e7f3e7035a8f63972706
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2025-09-14T22:35:27+02:00

Commit Message:
DIRECTOR: Load behavior details on frame loading

Changed paths:
    engines/director/score.cpp
    engines/director/score.h
    engines/director/sprite.cpp
    engines/director/sprite.h


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 4e0ca9699b5..bd311902e27 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -1861,6 +1861,35 @@ void Score::loadFrames(Common::SeekableReadStreamEndian &stream, uint16 version)
 	debugC(1, kDebugLoading, "Score::loadFrames(): Number of frames: %d, framesStreamSize: %d", _numFrames, _framesStreamSize);
 }
 
+void Score::loadFrameSpriteDetails() {
+	for (int i = 0; i < _currentFrame->_sprites.size(); i++) {
+		Sprite *sprite = _currentFrame->_sprites[i];
+		if (sprite->_spriteListIdx) {
+			Common::MemoryReadStreamEndian *stream = getSpriteDetailsStream(sprite->_spriteListIdx + 1);
+			if (stream) {
+				BehaviorElement behavior;
+
+				while (stream->pos() < stream->size()) {
+					behavior.read(*stream);
+
+					if (behavior.initializerIndex) {
+						Common::MemoryReadStreamEndian *stream1 = getSpriteDetailsStream(behavior.initializerIndex);
+
+						if (stream1) {
+							behavior.initializerParams = stream1->readString();
+							delete stream1;
+						}
+					}
+
+					sprite->_behaviors.push_back(behavior);
+				}
+				delete stream;
+			}
+		}
+	}
+}
+
+
 void Score::seekToMemberInList(int frameNum) {
 	if (frameNum < 1 || frameNum >= _numOfFrames) {
 		warning("Score::seekToMemberInList(): frameNum %d out of bounds [1, %d)", frameNum, _numOfFrames);
@@ -1907,6 +1936,9 @@ bool Score::loadFrame(int frameNum, bool loadCast) {
 	if (!isFrameRead)
 		return false;
 
+	if (_version >= kFileVer600)
+		loadFrameSpriteDetails();
+
 	// We have read the frame, now update current frame number
 	_curFrameNumber = targetFrame;
 
diff --git a/engines/director/score.h b/engines/director/score.h
index 5c28448e35f..eacf4881333 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -61,17 +61,6 @@ struct Label {
 	Label(Common::String name1, uint16 number1, Common::String comment1) { name = name1; number = number1; comment = comment1;}
 };
 
-struct BehaviorElement {
-	CastMemberID memberID;
-	int32 initializerIndex = 0;
-
-	void read(Common::ReadStreamEndian &stream) {
-		memberID.castLib = (int16)stream.readUint16();
-		memberID.member = (int16)stream.readUint16();
-		initializerIndex = (int32)stream.readUint32();
-	}
-};
-
 struct TweenInfo{
     int32 curvature;
     int32 flags;
@@ -229,6 +218,8 @@ private:
 
 	void seekToMemberInList(int frame);
 
+	void loadFrameSpriteDetails();
+
 public:
 	Common::Array<Channel *> _channels;
 	Common::SortedArray<Label *> *_labels;
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 009cbf98bcd..c048fb541cd 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -137,6 +137,8 @@ Sprite& Sprite::operator=(const Sprite &sprite) {
 	_angleRot = sprite._angleRot;
 	_angleSkew = sprite._angleSkew;
 
+	_behaviors = sprite._behaviors;
+
 	return *this;
 }
 
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
index 99f86104651..d5d29724db4 100644
--- a/engines/director/sprite.h
+++ b/engines/director/sprite.h
@@ -63,6 +63,18 @@ enum ThicknessFlags {
 	kTTweened   = 0x80,
 };
 
+struct BehaviorElement {
+	CastMemberID memberID;
+	int32 initializerIndex = 0;
+	Common::String initializerParams;
+
+	void read(Common::ReadStreamEndian &stream) {
+		memberID.castLib = (int16)stream.readUint16();
+		memberID.member = (int16)stream.readUint16();
+		initializerIndex = (int32)stream.readUint32();
+	}
+};
+
 class Sprite {
 public:
 	Sprite(Frame *frame = nullptr);
@@ -156,6 +168,8 @@ public:
 	byte _bgColorG, _bgColorB;		// R component sits in _backColor
 	int32 _angleRot;
 	int32 _angleSkew;
+
+	Common::Array<BehaviorElement> _behaviors;
 };
 
 } // End of namespace Director


Commit: a5553a246c1d5d49f5d221715c76a61dfbed93e8
    https://github.com/scummvm/scummvm/commit/a5553a246c1d5d49f5d221715c76a61dfbed93e8
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2025-09-14T22:35:27+02:00

Commit Message:
DIRECTOR: DT: Use preloaded behaviors when displaying Channels

Changed paths:
    engines/director/debugger/dt-score.cpp


diff --git a/engines/director/debugger/dt-score.cpp b/engines/director/debugger/dt-score.cpp
index 199d5d19e64..ab9425d6629 100644
--- a/engines/director/debugger/dt-score.cpp
+++ b/engines/director/debugger/dt-score.cpp
@@ -878,32 +878,15 @@ void showChannels() {
 					ImGui::TableNextColumn();
 
 					if (score->_version >= kFileVer600) {
-						if (sprite._spriteListIdx) {
-							Common::MemoryReadStreamEndian *stream = score->getSpriteDetailsStream(sprite._spriteListIdx + 1);
-
-							if (stream) {
-								BehaviorElement behavior;
-								while (stream->pos() < stream->size()) {
-									behavior.read(*stream);
-									displayScriptRef(behavior.memberID);
-									ImGui::SameLine();
-
-									if (behavior.initializerIndex) {
-										Common::MemoryReadStreamEndian *stream1 = score->getSpriteDetailsStream(behavior.initializerIndex);
-
-										if (stream1) {
-											Common::String init = stream1->readString();
-											ImGui::Text("(%s)", init.c_str());
-
-											delete stream1;
-										} else {
-											ImGui::Text("(\"\")");
-										}
-									}
+						if (sprite._behaviors.size() > 0) {
+							for (uint j = 0; j < sprite._behaviors.size(); j++) {
+								displayScriptRef(sprite._behaviors[j].memberID);
+								ImGui::SameLine();
+								if (sprite._behaviors[j].initializerIndex) {
+									ImGui::Text("(%s)", sprite._behaviors[j].initializerParams.c_str());
+								} else {
+									ImGui::Text("(\"\")");
 								}
-								delete stream;
-							} else {
-								ImGui::Text(" ");
 							}
 						} else {
 							ImGui::PushID(i + 1);


Commit: 8c5ad09c1af92a6bbb9bd5231e2ce5e5c628f3d7
    https://github.com/scummvm/scummvm/commit/8c5ad09c1af92a6bbb9bd5231e2ce5e5c628f3d7
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2025-09-14T22:35:28+02:00

Commit Message:
DIRECTOR: Read Script channel behavior

Changed paths:
    engines/director/frame.h
    engines/director/score.cpp
    engines/director/sprite.h


diff --git a/engines/director/frame.h b/engines/director/frame.h
index e30f6f848ac..40d47b9cf1b 100644
--- a/engines/director/frame.h
+++ b/engines/director/frame.h
@@ -95,9 +95,22 @@ struct PaletteInfo {
 	}
 };
 
+struct BehaviorElement {
+	CastMemberID memberID;
+	int32 initializerIndex = 0;
+	Common::String initializerParams;
+
+	void read(Common::ReadStreamEndian &stream) {
+		memberID.castLib = (int16)stream.readUint16();
+		memberID.member = (int16)stream.readUint16();
+		initializerIndex = (int32)stream.readUint32();
+	}
+};
+
 struct MainChannels {
 	CastMemberID actionId;
 	uint32 scriptSpriteListIdx; // D6+
+	BehaviorElement behavior; 	// D6+
 
 	uint16 transDuration;
 	uint8 transArea; // 1 - Whole Window, 0 - Changing Area
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index bd311902e27..7145a8a3f28 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -1887,6 +1887,23 @@ void Score::loadFrameSpriteDetails() {
 			}
 		}
 	}
+
+	if (_currentFrame->_mainChannels.scriptSpriteListIdx) {
+		Common::MemoryReadStreamEndian *stream = getSpriteDetailsStream(_currentFrame->_mainChannels.scriptSpriteListIdx);
+		if (stream) {
+			_currentFrame->_mainChannels.behavior.read(*stream);
+			delete stream;
+
+			if (_currentFrame->_mainChannels.behavior.initializerIndex) {
+				Common::MemoryReadStreamEndian *stream1 = getSpriteDetailsStream(_currentFrame->_mainChannels.behavior.initializerIndex);
+
+				if (stream1) {
+					_currentFrame->_mainChannels.behavior.initializerParams = stream1->readString();
+					delete stream1;
+				}
+			}
+		}
+	}
 }
 
 
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
index d5d29724db4..379d6584bfc 100644
--- a/engines/director/sprite.h
+++ b/engines/director/sprite.h
@@ -63,18 +63,7 @@ enum ThicknessFlags {
 	kTTweened   = 0x80,
 };
 
-struct BehaviorElement {
-	CastMemberID memberID;
-	int32 initializerIndex = 0;
-	Common::String initializerParams;
-
-	void read(Common::ReadStreamEndian &stream) {
-		memberID.castLib = (int16)stream.readUint16();
-		memberID.member = (int16)stream.readUint16();
-		initializerIndex = (int32)stream.readUint32();
-	}
-};
-
+struct BehaviorElement;
 class Sprite {
 public:
 	Sprite(Frame *frame = nullptr);




More information about the Scummvm-git-logs mailing list