[Scummvm-git-logs] scummvm master -> f8d604dfc24d7fa40961d10879f5a586f4bdcc6c
sev-
noreply at scummvm.org
Wed Jul 15 21:02:58 UTC 2026
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
df4e2580bc DIRECTOR: Bind digital-video channel before applying sprite properties
f8d604dfc2 DIRECTOR: Decode off-screen digital videos used as timing clocks
Commit: df4e2580bcc6818f6197e2cd28d39a42b89ea864
https://github.com/scummvm/scummvm/commit/df4e2580bcc6818f6197e2cd28d39a42b89ea864
Author: Gianluca Boiano (morf3089 at gmail.com)
Date: 2026-07-15T23:02:54+02:00
Commit Message:
DIRECTOR: Bind digital-video channel before applying sprite properties
setTheSprite() applied `the movieRate`/`movieTime`/`stopTime` to a
digital-video cast member before its channel was bound, so the setters
dereferenced a null channel and decoder.
Fixes crash at the intro concert video in opera fatal (OPERA.EXE plays
opera\intro\intro, CON0822.MOV)
Changed paths:
engines/director/castmember/digitalvideo.cpp
engines/director/lingo/lingo-the.cpp
diff --git a/engines/director/castmember/digitalvideo.cpp b/engines/director/castmember/digitalvideo.cpp
index 883137ef2a8..e4fcd3d600d 100644
--- a/engines/director/castmember/digitalvideo.cpp
+++ b/engines/director/castmember/digitalvideo.cpp
@@ -561,9 +561,14 @@ uint DigitalVideoCastMember::getMovieTotalTime() {
}
void DigitalVideoCastMember::seekMovie(int stamp) {
- if (!_video)
+ if (!_channel)
return;
+ if (!_video || !_video->isVideoLoaded()) {
+ if (!loadVideoFromCast())
+ return;
+ }
+
_channel->_startTime = stamp;
Audio::Timestamp dur = _video->getDuration();
@@ -578,9 +583,14 @@ void DigitalVideoCastMember::seekMovie(int stamp) {
}
void DigitalVideoCastMember::setStopTime(int stamp) {
- if (!_video)
+ if (!_channel)
return;
+ if (!_video || !_video->isVideoLoaded()) {
+ if (!loadVideoFromCast())
+ return;
+ }
+
_channel->_stopTime = stamp;
Audio::Timestamp dur = _video->getDuration();
@@ -589,9 +599,14 @@ void DigitalVideoCastMember::setStopTime(int stamp) {
}
void DigitalVideoCastMember::setMovieRate(double rate) {
- if (!_video)
+ if (!_channel)
return;
+ if (!_video || !_video->isVideoLoaded()) {
+ if (!loadVideoFromCast())
+ return;
+ }
+
_channel->_movieRate = rate;
if (rate < 0.0)
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index fc469c70e70..05819b2f74b 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -2036,16 +2036,18 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
break;
case kTheMovieRate:
channel->_movieRate = d.asFloat();
- if (sprite->_cast && sprite->_cast->_type == kCastDigitalVideo)
+ if (sprite->_cast && sprite->_cast->_type == kCastDigitalVideo) {
+ ((DigitalVideoCastMember *)sprite->_cast)->setChannel(channel);
((DigitalVideoCastMember *)sprite->_cast)->setMovieRate(channel->_movieRate);
- else
+ } else
warning("Setting movieTime for non-digital video");
break;
case kTheMovieTime:
channel->_movieTime = d.asInt();
- if (sprite->_cast->_type == kCastDigitalVideo)
+ if (sprite->_cast && sprite->_cast->_type == kCastDigitalVideo) {
+ ((DigitalVideoCastMember *)sprite->_cast)->setChannel(channel);
((DigitalVideoCastMember *)sprite->_cast)->seekMovie(channel->_movieTime);
- else
+ } else
warning("Setting movieTime for non-digital video");
break;
case kThePattern:
@@ -2080,16 +2082,18 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
break;
case kTheStartTime:
channel->_startTime = d.asInt();
- if (sprite->_cast->_type == kCastDigitalVideo)
+ if (sprite->_cast && sprite->_cast->_type == kCastDigitalVideo) {
+ ((DigitalVideoCastMember *)sprite->_cast)->setChannel(channel);
((DigitalVideoCastMember *)sprite->_cast)->seekMovie(channel->_startTime);
- else
+ } else
warning("Setting startTime for non-digital video");
break;
case kTheStopTime:
channel->_stopTime = d.asInt();
- if (sprite->_cast->_type == kCastDigitalVideo)
+ if (sprite->_cast && sprite->_cast->_type == kCastDigitalVideo) {
+ ((DigitalVideoCastMember *)sprite->_cast)->setChannel(channel);
((DigitalVideoCastMember *)sprite->_cast)->setStopTime(channel->_stopTime);
- else
+ } else
warning("Setting stopTime for non-digital video");
break;
case kTheStretch:
Commit: f8d604dfc24d7fa40961d10879f5a586f4bdcc6c
https://github.com/scummvm/scummvm/commit/f8d604dfc24d7fa40961d10879f5a586f4bdcc6c
Author: Gianluca Boiano (morf3089 at gmail.com)
Date: 2026-07-15T23:02:54+02:00
Commit Message:
DIRECTOR: Decode off-screen digital videos used as timing clocks
A zero-sized video sprite is never rendered, so createWidget() returned
before decoding a frame and left a playing decoder unpumped; its
audio-mastered clock then stalled after the initial buffer.
Fixes the frozen, silent intro in opera fatal, which advances scenes from
`the movieTime` of the off-stage CON0822.MOV (opera\intro\intro)
Changed paths:
engines/director/castmember/digitalvideo.cpp
diff --git a/engines/director/castmember/digitalvideo.cpp b/engines/director/castmember/digitalvideo.cpp
index e4fcd3d600d..09828990c33 100644
--- a/engines/director/castmember/digitalvideo.cpp
+++ b/engines/director/castmember/digitalvideo.cpp
@@ -478,9 +478,13 @@ Graphics::MacWidget *DigitalVideoCastMember::createWidget(Common::Rect &bbox, Ch
}
}
- // Zero-sized bbox: nothing to render, and scaling to it would divide by zero.
- if (bbox.width() <= 0 || bbox.height() <= 0)
+ // Zero-sized bbox: nothing to render. Still pump the decoder so an
+ // invisible video used only as a timing/audio clock keeps advancing.
+ if (bbox.width() <= 0 || bbox.height() <= 0) {
+ if (_channel && _channel->_movieRate != 0.0 && _video->needsUpdate())
+ _video->decodeNextFrame();
return nullptr;
+ }
Graphics::MacWidget *widget = new Graphics::MacWidget(g_director->getCurrentWindow()->getMacWindow(), bbox.left, bbox.top, bbox.width(), bbox.height(), g_director->_wm, false);
More information about the Scummvm-git-logs
mailing list