[Scummvm-git-logs] scummvm master -> 94e482145bf740e644f950de729a8554fab668fc
sev-
noreply at scummvm.org
Wed Oct 5 22:05:26 UTC 2022
This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
dcceb4c34b DIRECTOR: Add "disasm all" debugger command
32f87b27cb VIDEO: Fix VideoDecoder::needsUpdate to work for audio-only files
802c583b10 DIRECTOR: Improve breakpoint debugger command
e477106daa DIRECTOR: Update Channel::_movieTime in Score::updateWidgets
b2d13c5ea1 DIRECTOR: Stop playing videos when sprite gets replaced
2a261d0fba DIRECTOR: Allow for tempo changes when seeking to arbitrary frames
0dce88baf3 DIRECTOR: Add CompuServe Demo to detection list
94e482145b VIDEO: Fix infinite loop when loading greyscale QT videos
Commit: dcceb4c34bb3ecf639f6da5a214da5d557fca6e8
https://github.com/scummvm/scummvm/commit/dcceb4c34bb3ecf639f6da5a214da5d557fca6e8
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-06T00:05:17+02:00
Commit Message:
DIRECTOR: Add "disasm all" debugger command
Changed paths:
engines/director/debugger.cpp
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index a7281c163fd..bc735ec06b3 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -136,6 +136,7 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf(" repl - Switches to a REPL interface for evaluating Lingo code\n");
debugPrintf(" backtrace / bt - Prints a backtrace of all stack frames\n");
debugPrintf(" disasm / da [scriptId:funcName] - Lists the bytecode disassembly for a script function\n");
+ debugPrintf(" disasm / da all - Lists the bytecode disassembly for all available script functions\n");
debugPrintf(" stack / st - Lists the elements on the stack\n");
debugPrintf(" scriptframe / sf - Prints the current script frame\n");
debugPrintf(" funcs - Lists all of the functions available in the current script frame\n");
@@ -329,6 +330,60 @@ bool Debugger::cmdBacktrace(int argc, const char **argv) {
bool Debugger::cmdDisasm(int argc, const char **argv) {
Lingo *lingo = g_director->getLingo();
if (argc == 2) {
+ if (!strcmp(argv[1], "all")) {
+ Movie *movie = g_director->getCurrentMovie();
+ Score *score = movie->getScore();
+ ScriptContext *csc = lingo->_currentScriptContext;
+ if (csc) {
+ debugPrintf("Functions attached to frame %d:\n", score->getCurrentFrame());
+ for (auto &it : csc->_functionHandlers) {
+ debugPrintf("%s\n\n", g_lingo->formatFunctionBody(it._value).c_str());
+ }
+ } else {
+ debugPrintf("Functions attached to frame %d:\n", score->getCurrentFrame());
+ debugPrintf(" [empty]\n");
+ }
+ debugPrintf("\n");
+ debugPrintf("Cast functions:\n");
+ Cast *cast = movie->getCast();
+ if (cast && cast->_lingoArchive) {
+ for (int i = 0; i <= kMaxScriptType; i++) {
+ debugPrintf(" %s:\n", scriptType2str((ScriptType)i));
+ if (cast->_lingoArchive->scriptContexts[i].size() == 0)
+ debugPrintf(" [empty]\n");
+
+ for (auto &it : cast->_lingoArchive->scriptContexts[i]) {
+ for (auto &jt : it._value->_functionHandlers) {
+ debugPrintf("%s\n", g_lingo->formatFunctionBody(jt._value).c_str());
+ }
+ }
+ }
+
+ } else {
+ debugPrintf(" [empty]\n");
+ }
+ debugPrintf("\n");
+ debugPrintf("Shared cast functions:\n");
+ Cast *sharedCast = movie->getSharedCast();
+ if (sharedCast && sharedCast->_lingoArchive) {
+ for (int i = 0; i <= kMaxScriptType; i++) {
+ debugPrintf(" %s:\n", scriptType2str((ScriptType)i));
+ if (cast->_lingoArchive->scriptContexts[i].size() == 0)
+ debugPrintf(" [empty]\n");
+
+ for (auto &it : sharedCast->_lingoArchive->scriptContexts[i]) {
+ for (auto &jt : it._value->_functionHandlers) {
+ debugPrintf("%s\n", g_lingo->formatFunctionBody(jt._value).c_str());
+ }
+ }
+ }
+
+ } else {
+ debugPrintf(" [empty]\n");
+ }
+
+ return true;
+ }
Common::String target(argv[1]);
uint splitPoint = target.findFirstOf(":");
if (splitPoint == Common::String::npos) {
@@ -502,9 +557,9 @@ bool Debugger::cmdBpDel(int argc, const char **argv) {
bool Debugger::cmdBpEnable(int argc, const char **argv) {
if (argc == 2 && atoi(argv[1]) > 0) {
bool found = false;
- for (auto it = _breakpoints.begin(); it != _breakpoints.end(); ++it) {
- if (it->id == atoi(argv[1])) {
- it->enabled = true;
+ for (auto &it : _breakpoints) {
+ if (it.id == atoi(argv[1])) {
+ it.enabled = true;
found = true;
bpUpdateState();
debugPrintf("Enabled breakpoint %s.\n", argv[1]);
@@ -522,9 +577,9 @@ bool Debugger::cmdBpEnable(int argc, const char **argv) {
bool Debugger::cmdBpDisable(int argc, const char **argv) {
if (argc == 2 && atoi(argv[1]) > 0) {
bool found = false;
- for (auto it = _breakpoints.begin(); it != _breakpoints.end(); ++it) {
- if (it->id == atoi(argv[1])) {
- it->enabled = false;
+ for (auto &it : _breakpoints) {
+ if (it.id == atoi(argv[1])) {
+ it.enabled = false;
found = true;
bpUpdateState();
debugPrintf("Disabled breakpoint %s.\n", argv[1]);
Commit: 32f87b27cbf0fcc160ab91e975555f589030dc6b
https://github.com/scummvm/scummvm/commit/32f87b27cbf0fcc160ab91e975555f589030dc6b
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-06T00:05:17+02:00
Commit Message:
VIDEO: Fix VideoDecoder::needsUpdate to work for audio-only files
VideoDecoder::needsUpdate() only returns true if there are frames
remaining to be rendered. This won't work for video files that are
audio-only, so in the event of a such a file, fall back to checking
endOfVideo() which includes audio tracks.
Fixes audio-only DigitalVideoCastMembers in the Director engine.
Fixes playback of the cupcake song in Chop Suey.
Changed paths:
video/video_decoder.cpp
diff --git a/video/video_decoder.cpp b/video/video_decoder.cpp
index 841e6637be6..28ed9e1ef88 100644
--- a/video/video_decoder.cpp
+++ b/video/video_decoder.cpp
@@ -96,7 +96,26 @@ bool VideoDecoder::loadFile(const Common::Path &filename) {
}
bool VideoDecoder::needsUpdate() const {
- return hasFramesLeft() && getTimeToNextFrame() == 0;
+ bool hasVideo = false;
+ bool hasAudio = false;
+ for (auto &it : _tracks) {
+ switch (it->getTrackType()) {
+ case Track::kTrackTypeAudio:
+ hasAudio = true;
+ break;
+ case Track::kTrackTypeVideo:
+ hasVideo = true;
+ break;
+ default:
+ break;
+ }
+ }
+ if (hasVideo) {
+ return hasFramesLeft() && getTimeToNextFrame() == 0;
+ } else if (hasAudio) {
+ return !endOfVideo();
+ }
+ return false;
}
void VideoDecoder::pauseVideo(bool pause) {
Commit: 802c583b10cef98982fec99b90387e687a345753
https://github.com/scummvm/scummvm/commit/802c583b10cef98982fec99b90387e687a345753
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-06T00:05:17+02:00
Commit Message:
DIRECTOR: Improve breakpoint debugger command
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/lingo/lingo.cpp
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index bc735ec06b3..497ed8921ac 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -100,9 +100,10 @@ Debugger::Debugger(): GUI::Debugger() {
_nextFrame = false;
_nextFrameCounter = 0;
_bpNextId = 1;
- _bpCheckFuncName = false;
+ _bpCheckFunc = false;
_bpCheckMoviePath = false;
_bpNextMovieMatch = false;
+ _bpMatchScriptId = 0;
}
Debugger::~Debugger() {
@@ -147,7 +148,9 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf(" continue / c - Continues execution\n");
debugPrintf("\n");
debugPrintf("Breakpoints:\n");
+ debugPrintf(" bpset / b - Creates a breakpoint at the current Lingo function and offset\n");
debugPrintf(" bpset / b [funcName] - Creates a breakpoint on a Lingo function matching a name\n");
+ debugPrintf(" bpset / b [offset] - Creates a breakpoint on the current Lingo function matching an offset\n");
debugPrintf(" bpset / b [funcName] [offset] - Creates a breakpoint on a Lingo function matching a name and offset\n");
debugPrintf(" bpset / b [scriptId:funcName] - Creates a breakpoint on a Lingo function matching a script ID and name\n");
debugPrintf(" bpset / b [scriptId:funcName] [offset] - Creates a breakpoint on a Lingo function matching a script ID, name and offset\n");
@@ -465,28 +468,71 @@ bool Debugger::cmdFinish(int argc, const char **argv) {
}
bool Debugger::cmdBpSet(int argc, const char **argv) {
- if (argc == 2 || argc == 3) {
- Breakpoint bp;
- bp.id = _bpNextId;
- _bpNextId++;
- bp.type = kBreakpointFunction;
+ Breakpoint bp;
+ bp.id = _bpNextId;
+ bp.type = kBreakpointFunction;
+ if (argc == 1) {
+ Common::Array<CFrame *> &callstack = g_director->getCurrentWindow()->_callstack;
+ if (callstack.size() == 0) {
+ debugPrintf("Lingo is not executing, no current function to add breakpoint to.\n");
+ return true;
+ }
+ CFrame *frame = callstack[callstack.size() - 1];
+ if (!frame->sp.ctx) {
+ debugPrintf("Unable to add breakpoint, current script context is not addressable.\n");
+ return true;
+ }
+ if (!frame->sp.name) {
+ debugPrintf("Unable to add breakpoint, current function is not addressable.\n");
+ return true;
+ }
+ bp.scriptId = frame->sp.ctx->_id;
+ bp.funcName = *frame->sp.name;
+ bp.funcOffset = g_lingo->_pc;
+ } else if (argc == 2 || argc == 3) {
Common::String target(argv[1]);
uint splitPoint = target.findFirstOf(":");
if (splitPoint == Common::String::npos) {
- bp.funcName = target;
+ if (argc == 2 && atoi(argv[1]) > 0) {
+ // first and only argument is a number, use as an offset for the current function
+ Common::Array<CFrame *> &callstack = g_director->getCurrentWindow()->_callstack;
+ if (callstack.size() == 0) {
+ debugPrintf("Lingo is not executing, no current function to add breakpoint to.\n");
+ return true;
+ }
+ CFrame *frame = callstack[callstack.size() - 1];
+ if (!frame->sp.ctx) {
+ debugPrintf("Unable to add breakpoint, current script context is not addressable.\n");
+ return true;
+ }
+ if (!frame->sp.name) {
+ debugPrintf("Unable to add breakpoint, current function is not addressable.\n");
+ return true;
+ }
+ bp.scriptId = frame->sp.ctx->_id;
+ bp.funcName = *frame->sp.name;
+ bp.funcOffset = atoi(argv[1]);
+ } else {
+ // first argument is a string, do a function name match
+ bp.funcName = target;
+ }
} else {
+ // first argument is n:funcname, do an exact function match
bp.scriptId = atoi(target.substr(0, splitPoint).c_str());
bp.funcName = target.substr(splitPoint + 1, Common::String::npos);
}
if (argc == 3) {
+ // if there's a second argument, use it as the function offset
bp.funcOffset = atoi(argv[2]);
}
- _breakpoints.push_back(bp);
- bpUpdateState();
- debugPrintf("Added %s\n", bp.format().c_str());
} else {
- debugPrintf("Must specify a function name.\n");
+ debugPrintf("Too many arguments.\n");
+ return true;
}
+ _breakpoints.push_back(bp);
+ bpUpdateState();
+ debugPrintf("Added %s\n", bp.format().c_str());
+ _bpNextId++;
return true;
}
@@ -606,11 +652,12 @@ bool Debugger::cmdBpList(int argc, const char **argv) {
}
void Debugger::bpUpdateState() {
- _bpCheckFuncName = false;
+ _bpCheckFunc = false;
_bpCheckMoviePath = false;
_bpNextMovieMatch = false;
_bpMatchFuncOffsets.clear();
_bpMatchFuncName.clear();
+ _bpMatchScriptId = 0;
_bpMatchMoviePath.clear();
_bpMatchFrameOffsets.clear();
Movie *movie = g_director->getCurrentMovie();
@@ -619,15 +666,25 @@ void Debugger::bpUpdateState() {
if (!it.enabled)
continue;
if (it.type == kBreakpointFunction) {
- _bpCheckFuncName = true;
+ _bpCheckFunc = true;
if (!callstack.size())
continue;
CFrame *head = callstack[callstack.size() - 1];
if (!head->sp.name)
continue;
+ if (!head->sp.ctx)
+ continue;
if (it.funcName.equalsIgnoreCase(*head->sp.name)) {
- _bpMatchFuncName = it.funcName;
- _bpMatchFuncOffsets.setVal(it.funcOffset, nullptr);
+ if (it.scriptId) {
+ if (it.scriptId == head->sp.ctx->_id) {
+ _bpMatchScriptId = head->sp.ctx->_id;
+ _bpMatchFuncName = it.funcName;
+ _bpMatchFuncOffsets.setVal(it.funcOffset, nullptr);
+ }
+ } else {
+ _bpMatchFuncName = it.funcName;
+ _bpMatchFuncOffsets.setVal(it.funcOffset, nullptr);
+ }
}
} else if (it.type == kBreakpointMovie || it.type == kBreakpointMovieFrame) {
_bpCheckMoviePath = true;
@@ -645,7 +702,7 @@ void Debugger::bpTest(bool forceCheck) {
uint funcOffset = g_lingo->_pc;
Score *score = g_director->getCurrentMovie()->getScore();
uint frameOffset = score->getCurrentFrame();
- if (_bpCheckFuncName) {
+ if (_bpCheckFunc) {
stop |= _bpMatchFuncOffsets.contains(funcOffset);
}
if (_bpCheckMoviePath) {
@@ -657,7 +714,7 @@ void Debugger::bpTest(bool forceCheck) {
if (!it.enabled)
continue;
if (it.type == kBreakpointFunction) {
- if (it.funcName.equalsIgnoreCase(_bpMatchFuncName) && it.funcOffset == funcOffset)
+ if (it.funcName.equalsIgnoreCase(_bpMatchFuncName) && it.scriptId == _bpMatchScriptId && it.funcOffset == funcOffset)
debugPrintf("%s\n", it.format().c_str());
} else if (it.type == kBreakpointMovie && _bpNextMovieMatch) {
if (it.moviePath.equalsIgnoreCase(_bpMatchMoviePath))
@@ -757,7 +814,7 @@ void Debugger::builtinHook(const Symbol &funcSym) {
return;
bpUpdateState();
bool builtinMatch = false;
- if (_bpCheckFuncName) {
+ if (_bpCheckFunc) {
for (auto &it : _breakpoints) {
if (it.type != kBreakpointFunction)
continue;
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index 1f99d428bf0..f0e1da5afe1 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -138,10 +138,11 @@ private:
Common::Array<Breakpoint> _breakpoints;
int _bpNextId;
- bool _bpCheckFuncName;
+ bool _bpCheckFunc;
bool _bpCheckMoviePath;
bool _bpNextMovieMatch;
Common::String _bpMatchFuncName;
+ uint _bpMatchScriptId;
Common::String _bpMatchMoviePath;
Common::HashMap<uint, void *> _bpMatchFuncOffsets;
Common::HashMap<uint, void *> _bpMatchFrameOffsets;
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 57b23a5b699..aa2f44c7e9f 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -374,12 +374,16 @@ Common::String Lingo::formatCallStack(uint pc) {
framePc = callstack[callstack.size() - i]->retPC;
if (frame->sp.type != VOIDSYM) {
- result += Common::String::format("#%d %s:%d\n", i,
+ result += Common::String::format("#%d ", i);
+ if (frame->sp.ctx && frame->sp.ctx->_id) {
+ result += Common::String::format("%d:", frame->sp.ctx->_id);
+ }
+ result += Common::String::format("%s at [%5d]\n",
frame->sp.name->c_str(),
framePc
);
} else {
- result += Common::String::format("#%d [unknown]:%d\n", i,
+ result += Common::String::format("#%d [unknown] at [%5d]\n", i,
framePc
);
}
Commit: e477106daaafa4e441c27aec3857d2ac44e9b1c8
https://github.com/scummvm/scummvm/commit/e477106daaafa4e441c27aec3857d2ac44e9b1c8
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-06T00:05:17+02:00
Commit Message:
DIRECTOR: Update Channel::_movieTime in Score::updateWidgets
Previously this would be updated in
DigitalVideoCastMember::createWidget, which meant it was possible for a
movie to complete without updating _movieTime to the final end position.
Fixes the cupcakes from not stopping animating once the song is finished
in Chop Suey.
Changed paths:
engines/director/castmember.cpp
engines/director/channel.cpp
engines/director/score.cpp
diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp
index 526f7c567d9..3145115bd90 100644
--- a/engines/director/castmember.cpp
+++ b/engines/director/castmember.cpp
@@ -825,10 +825,9 @@ Graphics::MacWidget *DigitalVideoCastMember::createWidget(Common::Rect &bbox, Ch
return widget;
}
- debugC(1, kDebugImages, "Video time: %d rate: %f", _channel->_movieTime, _channel->_movieRate);
const Graphics::Surface *frame = _video->decodeNextFrame();
- _channel->_movieTime = getMovieCurrentTime();
+ debugC(1, kDebugImages, "Video time: %d rate: %f", _channel->_movieTime, _channel->_movieRate);
if (frame) {
if (_lastFrame) {
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 77fcf91cf98..1728ab278bb 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -321,7 +321,7 @@ bool Channel::isActiveVideo() {
}
void Channel::updateVideoTime() {
- if (_sprite)
+ if (isActiveVideo())
_movieTime = ((DigitalVideoCastMember *)_sprite->_cast)->getMovieCurrentTime();
}
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 0d486c1a0ec..013eb5de61b 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -915,6 +915,8 @@ void Score::updateWidgets(bool hasVideoPlayback) {
for (uint16 i = 0; i < _channels.size(); i++) {
Channel *channel = _channels[i];
CastMember *cast = channel->_sprite->_cast;
+ if (hasVideoPlayback)
+ channel->updateVideoTime();
if (cast && (cast->_type != kCastDigitalVideo || hasVideoPlayback) && cast->isModified()) {
channel->replaceWidget();
_window->addDirtyRect(channel->getBbox());
Commit: b2d13c5ea15dde572bbdbcff1423f09ee61a3c1d
https://github.com/scummvm/scummvm/commit/b2d13c5ea15dde572bbdbcff1423f09ee61a3c1d
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-06T00:05:17+02:00
Commit Message:
DIRECTOR: Stop playing videos when sprite gets replaced
Fixes cupcake song not stopping in Chop Suey.
Changed paths:
engines/director/castmember.cpp
engines/director/castmember.h
engines/director/channel.cpp
diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp
index 3145115bd90..2f60c2523d2 100644
--- a/engines/director/castmember.cpp
+++ b/engines/director/castmember.cpp
@@ -795,7 +795,7 @@ void DigitalVideoCastMember::startVideo(Channel *channel) {
_duration = getMovieTotalTime();
}
-void DigitalVideoCastMember::stopVideo(Channel *channel) {
+void DigitalVideoCastMember::stopVideo() {
if (!_video || !_video->isVideoLoaded()) {
warning("DigitalVideoCastMember::stopVideo: No video decoder");
return;
@@ -806,6 +806,17 @@ void DigitalVideoCastMember::stopVideo(Channel *channel) {
debugC(2, kDebugImages, "STOPPING VIDEO %s", _filename.c_str());
}
+void DigitalVideoCastMember::rewindVideo() {
+ if (!_video || !_video->isVideoLoaded()) {
+ warning("DigitalVideoCastMember::rewindVideo: No video decoder");
+ return;
+ }
+
+ _video->rewind();
+
+ debugC(2, kDebugImages, "REWINDING VIDEO %s", _filename.c_str());
+}
+
Graphics::MacWidget *DigitalVideoCastMember::createWidget(Common::Rect &bbox, Channel *channel, SpriteType spriteType) {
Graphics::MacWidget *widget = new Graphics::MacWidget(g_director->getCurrentWindow(), bbox.left, bbox.top, bbox.width(), bbox.height(), g_director->_wm, false);
diff --git a/engines/director/castmember.h b/engines/director/castmember.h
index ff21581c8d1..577b4da81d4 100644
--- a/engines/director/castmember.h
+++ b/engines/director/castmember.h
@@ -164,7 +164,8 @@ public:
bool loadVideo(Common::String path);
void startVideo(Channel *channel);
- void stopVideo(Channel *channel);
+ void stopVideo();
+ void rewindVideo();
uint getMovieCurrentTime();
uint getDuration();
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 1728ab278bb..5b214ba5564 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -504,6 +504,10 @@ void Channel::replaceSprite(Sprite *nextSprite) {
_sprite->_cast->releaseWidget();
newSprite = true;
}
+ if (_sprite->_castId != nextSprite->_castId && _sprite->_cast && _sprite->_cast->_type == kCastDigitalVideo) {
+ ((DigitalVideoCastMember *)_sprite->_cast)->stopVideo();
+ ((DigitalVideoCastMember *)_sprite->_cast)->rewindVideo();
+ }
int width = _width;
int height = _height;
Commit: 2a261d0fba7bc325945ea26b6b334f53526f166c
https://github.com/scummvm/scummvm/commit/2a261d0fba7bc325945ea26b6b334f53526f166c
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-06T00:05:17+02:00
Commit Message:
DIRECTOR: Allow for tempo changes when seeking to arbitrary frames
In Director, FPS entries in the tempo channel apply to all subsequent
frames. If we seek to an arbitrary frame, the correct tempo settings
should be applied.
Fixes the animation speeds of the cauldron and the walking teapot in
Chop Suey.
Changed paths:
engines/director/frame.cpp
engines/director/frame.h
engines/director/score.cpp
engines/director/score.h
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 540f6a9aa36..6820450a553 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -38,6 +38,7 @@ Frame::Frame(Score *score, int numChannels) {
_transArea = 0;
_transChunkSize = 0;
_tempo = 0;
+ _scoreCachedTempo = 0;
_numChannels = numChannels;
@@ -73,6 +74,7 @@ Frame::Frame(const Frame &frame) {
_transType = frame._transType;
_transChunkSize = frame._transChunkSize;
_tempo = frame._tempo;
+ _scoreCachedTempo = frame._scoreCachedTempo;
_sound1 = frame._sound1;
_sound2 = frame._sound2;
_soundType1 = frame._soundType1;
diff --git a/engines/director/frame.h b/engines/director/frame.h
index d66f45da71d..27042cdea39 100644
--- a/engines/director/frame.h
+++ b/engines/director/frame.h
@@ -117,6 +117,7 @@ public:
TransitionType _transType;
PaletteInfo _palette;
uint8 _tempo;
+ uint8 _scoreCachedTempo;
CastMemberID _sound1;
uint8 _soundType1;
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 013eb5de61b..2080ca5bf6b 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -71,7 +71,9 @@ Score::Score(Movie *movie) {
_nextFrame = 0;
_currentLabel = 0;
_nextFrameTime = 0;
+ _lastTempo = 0;
_waitForChannel = 0;
+ _waitForVideoChannel = 0;
_cursorDirty = false;
_waitForClick = false;
_waitForClickCursor = false;
@@ -336,6 +338,13 @@ void Score::update() {
_nextFrameTime = g_system->getMillis();
}
keepWaiting = true;
+ } else if (_waitForVideoChannel) {
+ Channel *movieChannel = _channels[_waitForVideoChannel];
+ if (movieChannel->isActiveVideo() && movieChannel->_movieRate != 0.0) {
+ keepWaiting = true;
+ } else {
+ _waitForVideoChannel = 0;
+ }
} else if (g_system->getMillis() < _nextFrameTime && !_nextFrame) {
keepWaiting = true;
}
@@ -462,15 +471,18 @@ void Score::update() {
}
}
- byte tempo = _frames[_currentFrame]->_tempo;
- if (tempo) {
+ byte tempo = _frames[_currentFrame]->_scoreCachedTempo;
+ // puppetTempo is overridden by changes in score tempo
+ if (_frames[_currentFrame]->_tempo || tempo != _lastTempo) {
_puppetTempo = 0;
} else if (_puppetTempo) {
tempo = _puppetTempo;
}
if (tempo) {
- if (tempo > 161) {
+ const bool waitForClickOnly = _vm->getVersion() < 300;
+ const int maxDelay = _vm->getVersion() < 400 ? 120 : 60;
+ if (tempo >= 256 - maxDelay) {
// Delay
_nextFrameTime = g_system->getMillis() + (256 - tempo) * 1000;
} else if (tempo <= 120) {
@@ -482,20 +494,25 @@ void Score::update() {
_waitForClick = true;
_waitForClickCursor = false;
renderCursor(_movie->getWindow()->getMousePos());
- } else if (tempo == 135) {
+ } else if (!waitForClickOnly && tempo == 135) {
// Wait for sound channel 1
_waitForChannel = 1;
- } else if (tempo == 134) {
+ } else if (!waitForClickOnly && tempo == 134) {
// Wait for sound channel 2
_waitForChannel = 2;
+
+ } else if (!waitForClickOnly && tempo >= 136 && tempo <= 135 + _numChannelsDisplayed) {
+ // Wait for a digital video in a channel to finish playing
+ _waitForVideoChannel = tempo - 135;
} else {
- warning("STUB: tempo %d", tempo);
+ warning("Unhandled tempo instruction: %d", tempo);
}
_nextFrameTime = g_system->getMillis();
}
} else {
_nextFrameTime = g_system->getMillis() + 1000.0 / (float)_currentFrameRate;
}
+ _lastTempo = tempo;
if (debugChannelSet(-1, kDebugSlow))
_nextFrameTime += 1000;
@@ -1154,6 +1171,8 @@ void Score::loadFrames(Common::SeekableReadStreamEndian &stream, uint16 version)
byte channelData[kChannelDataSize];
memset(channelData, 0, kChannelDataSize);
+ uint8 currentTempo = 0;
+
while (size != 0 && !stream.eos()) {
uint16 frameSize = stream.readUint16();
debugC(3, kDebugLoading, "++++++++++ score frame %d (frameSize %d) size %d", _frames.size(), frameSize, size);
@@ -1183,6 +1202,12 @@ void Score::loadFrames(Common::SeekableReadStreamEndian &stream, uint16 version)
// str->hexdump(str->size(), 32);
frame->readChannels(str, version);
delete str;
+ // Precache the current FPS tempo, as this carries forward to frames to the right
+ // of the instruction.
+ // Delay type tempos (e.g. wait commands, delays) apply to only a single frame, and are ignored here.
+ if (frame->_tempo && frame->_tempo <= 120)
+ currentTempo = frame->_tempo;
+ frame->_scoreCachedTempo = frame->_tempo ? frame->_tempo : currentTempo;
debugC(8, kDebugLoading, "Score::loadFrames(): Frame %d actionId: %s", _frames.size(), frame->_actionId.asString().c_str());
diff --git a/engines/director/score.h b/engines/director/score.h
index 63f1e5a2877..a4d77edee32 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -145,7 +145,9 @@ public:
PlayState _playState;
uint32 _nextFrameTime;
+ int _lastTempo;
int _waitForChannel;
+ int _waitForVideoChannel;
bool _waitForClick;
bool _waitForClickCursor;
bool _cursorDirty;
Commit: 0dce88baf32d150f47f06864105690d1663612eb
https://github.com/scummvm/scummvm/commit/0dce88baf32d150f47f06864105690d1663612eb
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-06T00:05:17+02:00
Commit Message:
DIRECTOR: Add CompuServe Demo to detection list
Changed paths:
engines/director/detection_tables.h
diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index fcf56023623..1b758b96665 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -1289,6 +1289,7 @@ static const PlainGameDescriptor directorGames[] = {
{ "blaster", "Blaster Series Demo" },
{ "bpmc", "Byron Preiss Multimedia Catalog" },
{ "cmc", "Creative Multimedia Catalog" },
+ { "compuserve", "CompuServe Demo" },
{ "coreltour", "Corel Product Tour" },
{ "davidsonpp", "Davidson Product Previews" },
{ "davidsonps", "Davidson Product Sampler" },
@@ -1914,6 +1915,8 @@ static const DirectorGameDescription gameDescriptions[] = {
MACGAME1("cmc", "1993", "xn--Other Products...-", "1ae45c23586b41997ba52e2e7c771c4c", 5748468, 310),
+ WINGAME1t("compuserve", "", "CSDEMO.EXE", "df9fd39763c4cc922e2cdad28d086a4c", 5331595, 404),
+
// Found on CD-ROM Today, #4
WINGAME1t("coreltour", "", "PRODTOUR.EXE", "296661dda59fcc1a4980e72797aac158", 375291, 300),
Commit: 94e482145bf740e644f950de729a8554fab668fc
https://github.com/scummvm/scummvm/commit/94e482145bf740e644f950de729a8554fab668fc
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-06T00:05:17+02:00
Commit Message:
VIDEO: Fix infinite loop when loading greyscale QT videos
Changed paths:
video/qt_decoder.cpp
diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp
index 75d7f5962f2..94efc64064a 100644
--- a/video/qt_decoder.cpp
+++ b/video/qt_decoder.cpp
@@ -161,7 +161,7 @@ Common::QuickTimeParser::SampleDesc *QuickTimeDecoder::readSampleDesc(Common::Qu
uint16 colorCount = 1 << colorDepth;
int16 colorIndex = 255;
byte colorDec = 256 / (colorCount - 1);
- for (byte j = 0; j < colorCount; j++) {
+ for (uint16 j = 0; j < colorCount; j++) {
entry->_palette[j * 3] = entry->_palette[j * 3 + 1] = entry->_palette[j * 3 + 2] = colorIndex;
colorIndex -= colorDec;
if (colorIndex < 0)
More information about the Scummvm-git-logs
mailing list