[Scummvm-git-logs] scummvm master -> 91cfbfc8727032fc422a841637e8d7ad8fe79249
sev-
noreply at scummvm.org
Thu Feb 12 23:36:30 UTC 2026
This automated email contains information about 10 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
930dbfd461 DIRECTOR: Fix quirks for Incarnatia
c820f4bb30 VIDEO: QTVR: Add guardrail for hotspot lookup
bdcbc26a65 DIRECTOR: LINGO: Make Lingo::executeHandler use string LC::call
a5a6878b53 DIRECTOR: LINGO: Improve accuracy of b_rollOver
3e21503ee6 DIRECTOR: Improve accuracy of Transparent/NotTrans ink in 32bpp mode
e4e2f4990c DIRECTOR: Add method for Channel/Sprite debug formatting
99e7c2cad8 DIRECTOR: Fix applyColor mode for copy ink in 32-bit
eaea9cd636 VIDEO: Improve performance of PacoDecoder
40a30f6225 DIRECTOR: XFCN: Add playfile command to XPlayPACoXFCN
91cfbfc872 DIRECTOR: Swap out sprite for frame copy when puppet flag disabled
Commit: 930dbfd461a9db9bd41c9fcc808e6a4334998b0a
https://github.com/scummvm/scummvm/commit/930dbfd461a9db9bd41c9fcc808e6a4334998b0a
Author: Scott Percival (code at moral.net.au)
Date: 2026-02-13T00:36:22+01:00
Commit Message:
DIRECTOR: Fix quirks for Incarnatia
Changed paths:
engines/director/detection_tables.h
engines/director/game-quirks.cpp
diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index 8b0a062f3f5..afdf7a3595e 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -7254,8 +7254,8 @@ static const DirectorGameDescription gameDescriptions[] = {
WINGAME1_l("ichsehewas", "", "ichsehewas.exe", "t:f5127fbc00272caecc04eccd6bb69eca", 1436195, Common::DE_DEU, 501),
// Installers for both platforms also use Director
- MACGAME1_l("incarnatia", "", "Install_Mac/CopyTo_HD/incarnatia_PowerMac", "r:2e7d373f75c014be20cfb04c5cd65dae", 108480, Common::JA_JPN, 501),
- WINGAME1_l("incarnatia", "", "Install_Win/CopyTo_HD/incarnatia_Win.exe", "t:7c640323fff4890486c5fbabb177ce29", 1414152, Common::JA_JPN, 501),
+ MACGAME1f_l("incarnatia", "", "Install_Mac/CopyTo_HD/incarnatia_PowerMac", "r:2e7d373f75c014be20cfb04c5cd65dae", 108480, Common::JA_JPN, 501, GF_32BPP),
+ WINGAME1f_l("incarnatia", "", "Install_Win/CopyTo_HD/incarnatia_Win.exe", "t:7c640323fff4890486c5fbabb177ce29", 1414152, Common::JA_JPN, 501, GF_32BPP),
// Australian Broadcasting Corporation (ABC) has made this available for free download
// https://www.abc.net.au/science/ingenious/patch.htm
@@ -10119,7 +10119,7 @@ static const DirectorGameDescription gameDescriptions[] = {
WINGAME1_l("greveholm3", "", "Greveholm3.exe", "t:ea8943fe1d6f2cf8df68d2f77b964f8e", 2408960, Common::SV_SWE, 800),
// Multilingual version
WINGAME1("greveholm3", "", "Greveholm3.exe", "t:c72fe7b88a22c8a4b28482a6e31fc409", 2286633, 800),
-
+
// Early Education Series from Ariss Computer Inc. of Beirut
WINGAME1_l("hamamalachkal", "", "SHAPE.EXE", "c163f36141579ee374f7b4b2bddee95a", 3784670, Common::AR_ARB, 850),
diff --git a/engines/director/game-quirks.cpp b/engines/director/game-quirks.cpp
index 2362bbf63b5..c0d47387e77 100644
--- a/engines/director/game-quirks.cpp
+++ b/engines/director/game-quirks.cpp
@@ -298,6 +298,8 @@ const struct Quirk {
{ "finkletimes", Common::kPlatformMacintosh, &quirkPretend16Bit },
{ "flipper", Common::kPlatformMacintosh, &quirkPretend16Bit },
{ "flipper", Common::kPlatformWindows, &quirkPretend16Bit },
+ { "incarnatia", Common::kPlatformMacintosh, &quirkPretend16Bit },
+ { "incarnatia", Common::kPlatformWindows, &quirkPretend16Bit },
// The standard FileIO xlib exists as both an XObject and Xtra version, with similar functionality
// but incompatible APIs.
Commit: c820f4bb30b1c59ff560e286066cc783f0f50455
https://github.com/scummvm/scummvm/commit/c820f4bb30b1c59ff560e286066cc783f0f50455
Author: Scott Percival (code at moral.net.au)
Date: 2026-02-13T00:36:22+01:00
Commit Message:
VIDEO: QTVR: Add guardrail for hotspot lookup
Changed paths:
video/qtvr_decoder.cpp
diff --git a/video/qtvr_decoder.cpp b/video/qtvr_decoder.cpp
index f85ba4e35c4..bd348f8d5ba 100644
--- a/video/qtvr_decoder.cpp
+++ b/video/qtvr_decoder.cpp
@@ -1487,6 +1487,10 @@ Common::String QuickTimeDecoder::getHotSpotName(int id) {
return "";
PanoHotSpot *hotspot = _panoTrack->panoSamples[_currentSample].hotSpotTable.get(id);
+ if (!hotspot) {
+ warning("QuickTimeDecoder::getHotSpotName: no hotspot found for id %d", id);
+ return "";
+ }
return _panoTrack->panoSamples[_currentSample].strTable.getString(hotspot->nameStrOffset);
}
Commit: bdcbc26a65cacaaab5a50f9b4d6bc4b9163bf347
https://github.com/scummvm/scummvm/commit/bdcbc26a65cacaaab5a50f9b4d6bc4b9163bf347
Author: Scott Percival (code at moral.net.au)
Date: 2026-02-13T00:36:22+01:00
Commit Message:
DIRECTOR: LINGO: Make Lingo::executeHandler use string LC::call
The string version of LC::call searches through multiple contexts for a
matching handler, including e.g. the builtins namespace.
Fixes screen updates in Incarnatia, which sets a QTVR callback to
"updateScreen".
Changed paths:
engines/director/lingo/lingo.cpp
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 76e66c49bb6..04bb552a964 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -760,10 +760,9 @@ void Lingo::executeScript(ScriptType type, CastMemberID id) {
void Lingo::executeHandler(const Common::String &name, int numargs) {
debugC(1, kDebugLingoExec, "Executing script handler : %s", name.c_str());
- Symbol sym = getHandler(name);
int frame = _state->callstack.size();
- LC::call(sym, numargs, false);
+ LC::call(name, numargs, false);
execute(frame);
}
Commit: a5a6878b535d8e0dbd7089a9ee844d7dc2aa311d
https://github.com/scummvm/scummvm/commit/a5a6878b535d8e0dbd7089a9ee844d7dc2aa311d
Author: Scott Percival (code at moral.net.au)
Date: 2026-02-13T00:36:22+01:00
Commit Message:
DIRECTOR: LINGO: Improve accuracy of b_rollOver
Fixes interaction checking scripts in Incarnatia.
Changed paths:
engines/director/lingo/lingo-builtins.cpp
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index f382c132fbc..2bfb94aa681 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -201,7 +201,7 @@ static const BuiltinProto builtins[] = {
{ "puppetTempo", LB::b_puppetTempo, 1, 1, 200, CBLTIN }, // D2 c
{ "puppetTransition",LB::b_puppetTransition,-1,0,200, CBLTIN }, // D2 c
{ "ramNeeded", LB::b_ramNeeded, 2, 2, 300, FBLTIN }, // D3.1 f
- { "rollOver", LB::b_rollOver, 1, 1, 200, FBLTIN }, // D2 f
+ { "rollOver", LB::b_rollOver, 0, 1, 200, FBLTIN }, // D2 f
{ "sendAllSprites", LB::b_sendAllSprites,-1,0,600, CBLTIN }, // D6 c
{ "sendSprite", LB::b_sendSprite, -1,0, 600, CBLTIN }, // D6 c
{ "spriteBox", LB::b_spriteBox, 5, 5, 200, CBLTIN }, // D2 c
@@ -3313,7 +3313,10 @@ void LB::b_ramNeeded(int nargs) {
}
void LB::b_rollOver(int nargs) {
- Datum d = g_lingo->pop();
+ Datum d(0);
+ if (nargs == 1) {
+ d = g_lingo->pop();
+ }
Datum res(0);
int arg = 0;
if (d.type == SPRITEREF) {
@@ -3329,13 +3332,25 @@ void LB::b_rollOver(int nargs) {
return;
}
- if (arg >= (int32) score->_channels.size()) {
- g_lingo->push(res);
+ if ((arg >= (int32) score->_channels.size()) || (arg < 0)) {
+ g_lingo->lingoError("b_rollOver: Sprite number %d out of range", arg);
return;
}
Common::Point pos = g_director->getCurrentWindow()->getMousePos();
+ if (arg == 0) {
+ if (g_director->getVersion() >= 500) {
+ // return the channel ID under the pointer, or 0 for no match
+ res.u.i = score->getRollOverSpriteIDFromPos(pos);
+ g_lingo->push(res);
+ return;
+ } else {
+ g_lingo->lingoError("b_rollOver: 0 not supported as an argument in D4 or lower");
+ return;
+ }
+ }
+
if (score->checkSpriteRollOver(arg, pos))
res.u.i = 1; // TRUE
Commit: 3e21503ee6090a68de12efecab0627bbecae60cd
https://github.com/scummvm/scummvm/commit/3e21503ee6090a68de12efecab0627bbecae60cd
Author: Scott Percival (code at moral.net.au)
Date: 2026-02-13T00:36:22+01:00
Commit Message:
DIRECTOR: Improve accuracy of Transparent/NotTrans ink in 32bpp mode
Changed paths:
engines/director/graphics.cpp
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index d09b6152098..dcd2f0fa8f2 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -428,18 +428,28 @@ void InkPrimitives<T>::drawPoint(int x, int y, uint32 src, void *data) {
if (p->oneBitImage || p->applyColor) {
*dst = (src == p->colorBlack) ? p->foreColor : *dst;
} else {
- // OR dst palette index with src.
- // Originally designed for 1-bit mode to make white pixels
- // transparent.
- *dst = *dst | src;
+ if (sizeof(T) == 1) {
+ // OR dst palette index with src.
+ // Originally designed for 1-bit mode to make white pixels
+ // transparent.
+ *dst = *dst | src;
+ } else {
+ // In 32-bit mode, this is an AND.
+ *dst = *dst & src;
+ }
}
break;
case kInkTypeNotTrans:
if (p->oneBitImage || p->applyColor) {
*dst = (src == p->colorWhite) ? p->foreColor : *dst;
} else {
- // OR dst palette index with the inverse of src.
- *dst = *dst | ~src;
+ if (sizeof(T) == 1) {
+ // OR dst palette index with the inverse of src.
+ *dst = *dst | ~src;
+ } else {
+ // In 32-bit mode, this is an AND.
+ *dst = *dst & ~(src & 0xffffff00);
+ }
}
break;
case kInkTypeReverse:
Commit: e4e2f4990c8e7e86b2de71edb2185b339634b675
https://github.com/scummvm/scummvm/commit/e4e2f4990c8e7e86b2de71edb2185b339634b675
Author: Scott Percival (code at moral.net.au)
Date: 2026-02-13T00:36:22+01:00
Commit Message:
DIRECTOR: Add method for Channel/Sprite debug formatting
Changed paths:
engines/director/channel.cpp
engines/director/channel.h
engines/director/frame.cpp
engines/director/score.cpp
engines/director/sprite.cpp
engines/director/sprite.h
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 5f90f298b15..d12d8e44941 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -806,4 +806,10 @@ CastMemberID Channel::getSubChannelSound2() {
return CastMemberID();
}
+Common::String Channel::formatInfo() {
+ return Common::String::format("[sprite: %s], visible: %d, constraint: %d, movieRate: %f, movieTime: %d (%f), filmLoopFrame: %d",
+ _sprite->formatInfo().c_str(), _visible,
+ _constraint, _movieRate, _movieTime, (float)(_movieTime/60.0f), _filmLoopFrame);
+}
+
} // End of namespace Director
diff --git a/engines/director/channel.h b/engines/director/channel.h
index 3ce735a44de..3e50aaeb6c8 100644
--- a/engines/director/channel.h
+++ b/engines/director/channel.h
@@ -98,6 +98,8 @@ public:
CastMemberID getSubChannelSound1();
CastMemberID getSubChannelSound2();
+ Common::String formatInfo();
+
public:
Sprite *_sprite;
Cursor _cursor;
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 1590c286b24..96ed96e6091 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -2244,15 +2244,9 @@ Common::String Frame::formatChannelInfo() {
for (int i = 0; i < _numChannels; i++) {
Sprite &sprite = *_sprites[i + 1];
if (sprite._castId.member) {
- result += Common::String::format("CH: %-3d castId: %s, [inkData: 0x%02x [ink: %d, trails: %d, stretch: %d, line: %d], %dx%d@%d,%d type: %d (%s) fg: %d bg: %d], script: %s, colorcode: 0x%x, blendAmount: 0x%x, unk3: 0x%x\n",
- i + 1, sprite._castId.asString().c_str(), sprite._inkData,
- sprite._ink, sprite._trails, sprite._stretch, sprite._thickness, sprite._width, sprite._height,
- sprite._startPoint.x, sprite._startPoint.y,
- sprite._spriteType, spriteType2str(sprite._spriteType), sprite._foreColor,
- sprite._backColor, sprite._scriptId.asString().c_str(), sprite._colorcode,
- sprite._blendAmount, sprite._unk3);
+ result += Common::String::format("CH: %-3d - [sprite: %s]\n", i + 1, sprite.formatInfo().c_str());
} else {
- result += Common::String::format("CH: %-3d castId: 000\n", i + 1);
+ result += Common::String::format("CH: %-3d - [sprite: castId: 000]\n", i + 1);
}
}
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index de958d337e9..3ad2e37a7f1 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -2133,8 +2133,10 @@ bool Score::loadFrame(int frameNum, bool loadCast) {
debugC(7, kDebugLoading, "****** Source frame %d to Destination frame %d, current offset 0x%x", sourceFrame, targetFrame, (uint32)_framesStream->pos());
+ _curFrameNumber = sourceFrame + 1;
while (sourceFrame < targetFrame - 1 && readOneFrame()) {
sourceFrame++;
+ _curFrameNumber = sourceFrame + 1;
}
// Finally read the target frame!
@@ -2381,15 +2383,8 @@ Common::String Score::formatChannelInfo() {
for (int i = 0; (i < frame._numChannels && ((i + 1) < (int)_channels.size())); i++) {
Channel &channel = *_channels[i + 1];
Sprite &sprite = *channel._sprite;
- Common::Point position = channel.getPosition();
if (sprite._castId.member) {
- result += Common::String::format("CH: %-3d castId: %s, visible: %d, [inkData: 0x%02x [ink: %d, trails: %d, stretch: %d, line: %d], %dx%d@%d,%d type: %d (%s) fg: %08x bg: %08x], script: %s, colorcode: 0x%x, blendAmount: 0x%x, unk3: 0x%x, constraint: %d, puppet: %d, moveable: %d, movieRate: %f, movieTime: %d (%f), filmLoopFrame: %d\n",
- i + 1, sprite._castId.asString().c_str(), channel._visible, sprite._inkData,
- sprite._ink, sprite._trails, sprite._stretch, sprite._thickness,
- channel.getWidth(), channel.getHeight(), position.x, position.y,
- sprite._spriteType, spriteType2str(sprite._spriteType), sprite._foreColor, sprite._backColor,
- sprite._scriptId.asString().c_str(), sprite._colorcode, sprite._blendAmount, sprite._unk3,
- channel._constraint, sprite._puppet, sprite._moveable, channel._movieRate, channel._movieTime, (float)(channel._movieTime/60.0f), channel._filmLoopFrame);
+ result += Common::String::format("CH: %-3d - %s\n", i + 1, channel.formatInfo().c_str());
if (!sprite._behaviors.empty()) {
result += Common::String::format(" behaviours: ");
for (auto &it : sprite._behaviors) {
@@ -2401,7 +2396,7 @@ Common::String Score::formatChannelInfo() {
skipped = false;
} else {
if (i == frame._numChannels - 1 || (i > 0 && _channels[i]->_sprite->_castId.member)) {
- result += Common::String::format("CH: %-3d castId: 000\n", i + 1);
+ result += Common::String::format("CH: %-3d - [sprite: castId: 000]\n", i + 1);
} else {
if (!skipped) {
result += "...\n";
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index d2a20cdf575..e140e184483 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -600,4 +600,17 @@ void Sprite::setCast(CastMemberID memberID, bool replaceDims) {
}
}
+
+Common::String Sprite::formatInfo() {
+ return Common::String::format("castId: %s, [inkData: 0x%02x [ink: %s, trails: %d, stretch: %d, line: %d], %dx%d@%d,%d type: %d (%s) fg: %08x bg: %08x], script: %s, colorcode: 0x%x, blendAmount: 0x%x, unk3: 0x%x, puppet: %d, moveable: %d",
+ _castId.asString().c_str(), _inkData,
+ inkType2str(_ink), _trails, _stretch, _thickness,
+ _width, _height, _startPoint.x, _startPoint.y,
+ _spriteType, spriteType2str(_spriteType), _foreColor, _backColor,
+ _scriptId.asString().c_str(), _colorcode, _blendAmount, _unk3,
+ _puppet, _moveable);
+}
+
+
+
} // End of namespace Director
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
index dba092de338..c997478a2e6 100644
--- a/engines/director/sprite.h
+++ b/engines/director/sprite.h
@@ -109,6 +109,8 @@ public:
Common::Point getPosition();
void setPosition(int x, int y);
+ Common::String formatInfo();
+
Frame *_frame;
Score *_score;
Movie *_movie;
Commit: 99e7c2cad890bbd83b62d7c1f001c4d03cf26484
https://github.com/scummvm/scummvm/commit/99e7c2cad890bbd83b62d7c1f001c4d03cf26484
Author: Scott Percival (code at moral.net.au)
Date: 2026-02-13T00:36:22+01:00
Commit Message:
DIRECTOR: Fix applyColor mode for copy ink in 32-bit
It is unclear what the original code was doing. It's also pretty old,
and a lot about the rendering pipeline has changed since then.
Changed paths:
engines/director/graphics.cpp
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index dcd2f0fa8f2..08b676d916e 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -373,24 +373,7 @@ void InkPrimitives<T>::drawPoint(int x, int y, uint32 src, void *data) {
// Otherwise, treat it like a Matte image.
case kInkTypeCopy: {
if (p->applyColor) {
- if (sizeof(T) == 1) {
- *dst = (src == 0xff) ? p->foreColor : ((src == 0x00) ? p->backColor : *dst);
- } else {
- // TODO: Improve the efficiency of this composition
- byte rSrc, gSrc, bSrc;
- byte rDst, gDst, bDst;
- byte rFor, gFor, bFor;
- byte rBak, gBak, bBak;
-
- wm->decomposeColor<T>(src, rSrc, gSrc, bSrc);
- wm->decomposeColor<T>(*dst, rDst, gDst, bDst);
- wm->decomposeColor<T>(p->foreColor, rFor, gFor, bFor);
- wm->decomposeColor<T>(p->backColor, rBak, gBak, bBak);
-
- *dst = wm->findBestColor((rSrc | rFor) & (~rSrc | rBak),
- (gSrc | gFor) & (~gSrc | gBak),
- (bSrc | bFor) & (~bSrc | bBak));
- }
+ *dst = (src == p->colorBlack) ? p->foreColor : ((src == p->colorWhite) ? p->backColor : *dst);
} else {
*dst = src;
}
@@ -399,22 +382,11 @@ void InkPrimitives<T>::drawPoint(int x, int y, uint32 src, void *data) {
case kInkTypeNotCopy:
if (p->applyColor) {
if (sizeof(T) == 1) {
- *dst = (src == 0xff) ? p->backColor : ((src == 0x00) ? p->foreColor : src);
- } else {
- // TODO: Improve the efficiency of this composition
- byte rSrc, gSrc, bSrc;
- byte rDst, gDst, bDst;
- byte rFor, gFor, bFor;
- byte rBak, gBak, bBak;
-
- wm->decomposeColor<T>(src, rSrc, gSrc, bSrc);
- wm->decomposeColor<T>(*dst, rDst, gDst, bDst);
- wm->decomposeColor<T>(p->foreColor, rFor, gFor, bFor);
- wm->decomposeColor<T>(p->backColor, rBak, gBak, bBak);
-
- *dst = wm->findBestColor((~rSrc | rFor) & (rSrc | rBak),
- (~gSrc | gFor) & (gSrc | gBak),
- (~bSrc | bFor) & (bSrc | bBak));
+ *dst = (src == p->colorBlack) ? p->backColor : ((src == p->colorWhite) ? p->foreColor : src);
+ } else if (sizeof(T) == 4) {
+ // In 32-bit, apply color mode seems to just return the original src
+ // with no changes. This is different to kInkTypeCopy.
+ *dst = src;
}
} else {
// Find the inverse of the colour and match it back to the palette if required
Commit: eaea9cd6363e8e3b7ea169e5479d6eaff94502cf
https://github.com/scummvm/scummvm/commit/eaea9cd6363e8e3b7ea169e5479d6eaff94502cf
Author: Scott Percival (code at moral.net.au)
Date: 2026-02-13T00:36:22+01:00
Commit Message:
VIDEO: Improve performance of PacoDecoder
Previously, audio would pop due to buffer underruns between frames.
New approach is to have two substreams, so the audio can be buffered
independently from the video.
Changed paths:
audio/audiostream.h
audio/decoders/raw.cpp
audio/decoders/raw.h
video/paco_decoder.cpp
video/paco_decoder.h
diff --git a/audio/audiostream.h b/audio/audiostream.h
index 1f7127e4fc6..7af56edaec4 100644
--- a/audio/audiostream.h
+++ b/audio/audiostream.h
@@ -485,6 +485,9 @@ public:
bool endOfData() const { return _stream->endOfData(); }
bool endOfStream() const { return _stream->endOfStream(); }
+ // QueuingAudioStream API
+ uint32 numQueuedStreams() const { return _stream->numQueuedStreams(); }
+
// PacketizedAudioStream API
void queuePacket(Common::SeekableReadStream *data) { _stream->queueAudioStream(makeStream(data)); }
void finish() { _stream->finish(); }
diff --git a/audio/decoders/raw.cpp b/audio/decoders/raw.cpp
index acf97bbb663..705778f7659 100644
--- a/audio/decoders/raw.cpp
+++ b/audio/decoders/raw.cpp
@@ -238,7 +238,7 @@ AudioStream *PacketizedRawStream::makeStream(Common::SeekableReadStream *data) {
return makeRawStream(data, getRate(), _flags);
}
-PacketizedAudioStream *makePacketizedRawStream(int rate, byte flags) {
+StatelessPacketizedAudioStream *makePacketizedRawStream(int rate, byte flags) {
return new PacketizedRawStream(rate, flags);
}
diff --git a/audio/decoders/raw.h b/audio/decoders/raw.h
index 00b071e4cd8..fcbb5a62fb1 100644
--- a/audio/decoders/raw.h
+++ b/audio/decoders/raw.h
@@ -34,7 +34,7 @@ class SeekableReadStream;
namespace Audio {
-class PacketizedAudioStream;
+class StatelessPacketizedAudioStream;
class SeekableAudioStream;
/**
@@ -93,15 +93,15 @@ SeekableAudioStream *makeRawStream(Common::SeekableReadStream *stream,
DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
/**
- * Creates a PacketizedAudioStream that will automatically queue
+ * Creates a StatelessPacketizedAudioStream that will automatically queue
* packets as individual AudioStreams like returned by makeRawStream.
*
* @param rate Rate of the sound data.
* @param flags Audio flags combination.
* @see RawFlags
- * @return The new PacketizedAudioStream.
+ * @return The new StatelessPacketizedAudioStream.
*/
-PacketizedAudioStream *makePacketizedRawStream(int rate, byte flags);
+StatelessPacketizedAudioStream *makePacketizedRawStream(int rate, byte flags);
} // End of namespace Audio
diff --git a/video/paco_decoder.cpp b/video/paco_decoder.cpp
index fecc686c10f..9f0c8ec4890 100644
--- a/video/paco_decoder.cpp
+++ b/video/paco_decoder.cpp
@@ -22,6 +22,7 @@
#include "common/endian.h"
#include "common/rect.h"
#include "common/stream.h"
+#include "common/substream.h"
#include "common/system.h"
#include "common/textconsole.h"
#include "graphics/surface.h"
@@ -50,7 +51,7 @@ enum frameTypes {
};
PacoDecoder::PacoDecoder()
- : _fileStream(nullptr), _videoTrack(nullptr), _audioTrack(nullptr) {
+ : _fileStream(nullptr), _videoStream(nullptr), _audioStream(nullptr), _videoTrack(nullptr), _audioTrack(nullptr) {
}
PacoDecoder::~PacoDecoder() {
@@ -60,6 +61,10 @@ PacoDecoder::~PacoDecoder() {
void PacoDecoder::PacoDecoder::close() {
Video::VideoDecoder::close();
+ delete _videoStream;
+ _videoStream = nullptr;
+ delete _audioStream;
+ _audioStream = nullptr;
delete _fileStream;
_fileStream = nullptr;
_videoTrack = nullptr;
@@ -99,6 +104,11 @@ bool PacoDecoder::loadStream(Common::SeekableReadStream *stream) {
}
_fileStream = stream;
+ int loc = _fileStream->pos();
+ _videoStream = new Common::SafeSeekableSubReadStream(stream, 0, stream->size());
+ _videoStream->seek(loc);
+ _audioStream = new Common::SafeSeekableSubReadStream(stream, 0, stream->size());
+ _audioStream->seek(loc);
_videoTrack = new PacoVideoTrack(frameRate, frameCount, width, height);
addTrack(_videoTrack);
@@ -117,23 +127,23 @@ int PacoDecoder::getAudioSamplingRate() {
const Common::Array<int> samplingRates = {5563, 7418, 11127, 22254};
int index = 0;
- int64 startPos = _fileStream->pos();
+ int64 startPos = _audioStream->pos();
- while (_fileStream->pos() < _fileStream->size()) {
- int64 currentPos = _fileStream->pos();
- int frameType = _fileStream->readByte();
- int v = _fileStream->readByte();
- uint32 chunkSize = (v << 16 ) | _fileStream->readUint16BE();
+ while (_audioStream->pos() < _audioStream->size()) {
+ int64 currentPos = _audioStream->pos();
+ int frameType = _audioStream->readByte();
+ int v = _audioStream->readByte();
+ uint32 chunkSize = (v << 16 ) | _audioStream->readUint16BE();
if (frameType != AUDIO) {
- _fileStream->seek(currentPos + chunkSize);
+ _audioStream->seek(currentPos + chunkSize);
continue;
}
- uint16 header = _fileStream->readUint16BE();
- _fileStream->readUint16BE();
+ uint16 header = _audioStream->readUint16BE();
+ _audioStream->readUint16BE();
index = (header >> 10) & 7;
break;
}
- _fileStream->seek(startPos);
+ _audioStream->seek(startPos);
return samplingRates[index];
}
@@ -208,34 +218,58 @@ Graphics::PixelFormat PacoDecoder::PacoVideoTrack::getPixelFormat() const {
}
void PacoDecoder::readNextPacket() {
+ if (_audioTrack) {
+ while (_audioTrack->needsAudio() && (_audioStream->pos() < _audioStream->size())) {
+ // buffer as much audio as we need
+ int64 currentPos = _audioStream->pos();
+ int frameType = _audioStream->readByte();
+ int v = _audioStream->readByte();
+ uint32 chunkSize = (v << 16 ) | _audioStream->readUint16BE();
+ debugC(2, kDebugLevelGVideo, " _audioStream: slot type %d size %d @ %lX", frameType, chunkSize, long(_videoStream->pos() - 4));
+ switch (frameType) {
+ case AUDIO:
+ _audioTrack->queueSound(_audioStream, chunkSize - 4);
+ break;
+ case VIDEO:
+ case PALETTE:
+ case EOC:
+ case NOP:
+ _audioStream->skip(chunkSize - 4);
+ break;
+ default:
+ error("PacoDecoder::decodeFrame(): unknown main chunk type (type = 0x%02X)", frameType);
+ break;
+ }
+ }
+ }
+
if (_curFrame >= _videoTrack->getFrameCount())
return;
- uint32 nextFrame = _fileStream->pos() + _frameSizes[_curFrame];
+ uint32 nextFrame = _videoStream->pos() + _frameSizes[_curFrame];
- debugC(2, kDebugLevelGVideo, " frame %3d size %d @ %lX", _curFrame, _frameSizes[_curFrame], long(_fileStream->pos()));
+ debugC(2, kDebugLevelGVideo, " frame %3d size %d @ %lX", _curFrame, _frameSizes[_curFrame], long(_videoStream->pos()));
_curFrame++;
- while (_fileStream->pos() < nextFrame) {
- int64 currentPos = _fileStream->pos();
- int frameType = _fileStream->readByte();
- int v = _fileStream->readByte();
- uint32 chunkSize = (v << 16 ) | _fileStream->readUint16BE();
- debugC(2, kDebugLevelGVideo, " slot type %d size %d @ %lX", frameType, chunkSize, long(_fileStream->pos() - 4));
+ while (_videoStream->pos() < nextFrame) {
+ int64 currentPos = _videoStream->pos();
+ int frameType = _videoStream->readByte();
+ int v = _videoStream->readByte();
+ uint32 chunkSize = (v << 16 ) | _videoStream->readUint16BE();
+ debugC(2, kDebugLevelGVideo, " _videoStream: slot type %d size %d @ %lX", frameType, chunkSize, long(_videoStream->pos() - 4));
switch (frameType) {
case AUDIO:
- if (_audioTrack)
- _audioTrack->queueSound(_fileStream, chunkSize - 4);
+ _videoStream->skip(chunkSize - 4);
break;
case VIDEO:
if (_videoTrack)
- _videoTrack->handleFrame(_fileStream, chunkSize - 4, _curFrame);
+ _videoTrack->handleFrame(_videoStream, chunkSize - 4, _curFrame);
break;
case PALETTE:
if (_videoTrack)
- _videoTrack->handlePalette(_fileStream);
+ _videoTrack->handlePalette(_videoStream);
break;
case EOC:
if (_videoTrack)
@@ -247,9 +281,8 @@ void PacoDecoder::readNextPacket() {
error("PacoDecoder::decodeFrame(): unknown main chunk type (type = 0x%02X)", frameType);
break;
}
- _fileStream->seek(currentPos + chunkSize);
- }
-
+ _videoStream->seek(currentPos + chunkSize);
+ }
}
@@ -611,5 +644,9 @@ void PacoDecoder::PacoAudioTrack::queueSound(Common::SeekableReadStream *fileStr
_packetStream->queuePacket(fileStream->readStream(chunkSize - 4));
}
+bool PacoDecoder::PacoAudioTrack::needsAudio() const {
+ // TODO: 5 is very arbitrary. We probably should do something like QuickTime does.
+ return _packetStream->numQueuedStreams() < 5;
+}
} // End of namespace Video
diff --git a/video/paco_decoder.h b/video/paco_decoder.h
index 28218a30b0c..f144212bee3 100644
--- a/video/paco_decoder.h
+++ b/video/paco_decoder.h
@@ -30,6 +30,7 @@
namespace Common {
class SeekableReadStream;
+class SafeSeekableSubReadStream;
}
namespace Graphics {
@@ -105,12 +106,13 @@ protected:
PacoAudioTrack(int samplingRate);
~PacoAudioTrack();
void queueSound(Common::SeekableReadStream *fileStream, uint32 chunkSize);
+ bool needsAudio() const;
protected:
Audio::AudioStream *getAudioStream() const { return _packetStream; }
private:
- Audio::PacketizedAudioStream *_packetStream;
+ Audio::StatelessPacketizedAudioStream *_packetStream;
int _samplingRate;
};
@@ -118,6 +120,8 @@ private:
PacoVideoTrack *_videoTrack;
PacoAudioTrack *_audioTrack;
Common::SeekableReadStream *_fileStream;
+ Common::SafeSeekableSubReadStream *_videoStream;
+ Common::SafeSeekableSubReadStream *_audioStream;
int _curFrame = 0;
int _frameSizes[65536]; // can be done differently?
int getAudioSamplingRate();
Commit: 40a30f6225ecf6746cf4f6d46cbd64622e2388bb
https://github.com/scummvm/scummvm/commit/40a30f6225ecf6746cf4f6d46cbd64622e2388bb
Author: Scott Percival (code at moral.net.au)
Date: 2026-02-13T00:36:22+01:00
Commit Message:
DIRECTOR: XFCN: Add playfile command to XPlayPACoXFCN
Fixes video clip playback in Better Dead Ratification.
Changed paths:
engines/director/lingo/xlibs/x/xplaypacoxfcn.cpp
diff --git a/engines/director/lingo/xlibs/x/xplaypacoxfcn.cpp b/engines/director/lingo/xlibs/x/xplaypacoxfcn.cpp
index 31f10725ed9..dbeeedf770d 100644
--- a/engines/director/lingo/xlibs/x/xplaypacoxfcn.cpp
+++ b/engines/director/lingo/xlibs/x/xplaypacoxfcn.cpp
@@ -218,6 +218,33 @@ void XPlayPACoXFCN::m_XPlayPACo(int nargs) {
} else {
warning("XPlayPACoXFCN: expected at least 1 arg for play");
}
+
+
+ } else if (cmd.equals("playfile")) {
+ if (nargs >= 2) {
+ Common::String filename = g_lingo->peek(nargs - 2).asString();
+ int playerId = state->openfile(filename);
+ int posX = 0;
+ int posY = 0;
+ for (int i = nargs - 3; i >= 0; i -= 2) {
+ Datum paramName = g_lingo->peek(i);
+ Datum paramValue = g_lingo->peek(i - 1);
+ if (paramName.asString().equalsIgnoreCase("centering") && paramValue.asInt() == 1) {
+ posX = (g_system->getWidth() - state->_players[playerId]._video->getWidth()) / 2;
+ posY = (g_system->getHeight() - state->_players[playerId]._video->getHeight()) / 2;
+ } else if (paramName.asString().equalsIgnoreCase("posX")) {
+ posX = paramValue.asInt();
+ } else if (paramName.asString().equalsIgnoreCase("posY")) {
+ posY = paramValue.asInt();
+ } else if (paramName.asString().equalsIgnoreCase("window")) {
+ // ignore
+ }
+ }
+ result = state->play(playerId, posX, posY);
+ } else {
+ warning("XPlayPACoXFCN: expected at least 1 arg for playfile");
+ }
+
} else if (cmd.equals("close")) {
if (nargs == 2) {
int playerId = g_lingo->peek(nargs - 2).asInt();
Commit: 91cfbfc8727032fc422a841637e8d7ad8fe79249
https://github.com/scummvm/scummvm/commit/91cfbfc8727032fc422a841637e8d7ad8fe79249
Author: Scott Percival (code at moral.net.au)
Date: 2026-02-13T00:36:22+01:00
Commit Message:
DIRECTOR: Swap out sprite for frame copy when puppet flag disabled
Games can do the following:
- Call "puppetSprite 1, TRUE"
- Jump to an earlier frame (sprite 1 should be unchanged)
- Call "puppetSprite 1, FALSE" (sprite 1 should swap out to
be whatever is in the frame).
Previously we were filtering out puppeted sprites/properties in the
frame loader, which made it impossible to do a just-in-time swap.
The new approach is to filter out the sprites/properties in
Channel::replaceSprite.
Fixes moving about in The Journeyman Project.
Changed paths:
engines/director/channel.cpp
engines/director/frame.cpp
engines/director/lingo/lingo-builtins.cpp
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index d12d8e44941..adfa14aac13 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -573,6 +573,13 @@ void Channel::replaceSprite(Sprite *nextSprite) {
if (!nextSprite)
return;
+ if (_sprite->_puppet) {
+ // Whole sprite is in puppet mode.
+ // The only thing we want to copy over is the script ID.
+ nextSprite->_scriptId = _sprite->_scriptId;
+ return;
+ }
+
bool widgetKeeped = _sprite->_cast && _widget;
// if there's a video in the old sprite that's different, stop it before we continue
@@ -595,11 +602,49 @@ void Channel::replaceSprite(Sprite *nextSprite) {
editable = _sprite->_editable;
}
+
int width = _sprite->_width;
int height = _sprite->_height;
bool immediate = _sprite->_immediate;
- *_sprite = *nextSprite;
+ // Copy over all the sprite fields from one to another.
+ // For D6+, exclude individual fields with autopuppet switched on
+ _sprite->_spriteType = nextSprite->_spriteType;
+ _sprite->_enabled = nextSprite->_enabled;
+ if (!_sprite->getAutoPuppet(kAPInk)) {
+ _sprite->_inkData = nextSprite->_inkData;
+ _sprite->_ink = nextSprite->_ink;
+ _sprite->_trails = nextSprite->_trails;
+ _sprite->_stretch = nextSprite->_stretch;
+ }
+ if (!_sprite->getAutoPuppet(kAPForeColor)) {
+ _sprite->_foreColor = nextSprite->_foreColor;
+ }
+ if (!_sprite->getAutoPuppet(kAPBackColor)) {
+ _sprite->_backColor = nextSprite->_backColor;
+ }
+ if (!_sprite->getAutoPuppet(kAPCast)) {
+ _sprite->_castId = nextSprite->_castId;
+ _sprite->_cast = nextSprite->_cast;
+ _sprite->_spriteListIdx = nextSprite->_spriteListIdx;
+ }
+ if (!_sprite->getAutoPuppet(kAPLoc)) {
+ _sprite->_startPoint = nextSprite->_startPoint;
+ }
+ if (!_sprite->getAutoPuppet(kAPHeight)) {
+ _sprite->_height = nextSprite->_height;
+ }
+ if (!_sprite->getAutoPuppet(kAPWidth)) {
+ _sprite->_width = nextSprite->_width;
+ }
+ if (!_sprite->getAutoPuppet(kAPMoveable)) {
+ _sprite->_colorcode = nextSprite->_colorcode;
+ _sprite->_editable = nextSprite->_editable;
+ _sprite->_moveable = nextSprite->_moveable;
+ }
+ _sprite->_blendAmount = nextSprite->_blendAmount;
+ _sprite->_thickness = nextSprite->_thickness;
+ _sprite->_pattern = nextSprite->_pattern;
// Persist the immediate flag
_sprite->_immediate = immediate;
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 96ed96e6091..b6d72c559d4 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -331,87 +331,47 @@ void readSpriteDataD2(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
sprite._scriptId = CastMemberID(stream.readByte(), DEFAULT_CAST_LIB);
break;
case 1:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._spriteType = (SpriteType)stream.readByte();
- sprite._enabled = sprite._spriteType != kInactiveSprite;
- }
+ sprite._spriteType = (SpriteType)stream.readByte();
+ sprite._enabled = sprite._spriteType != kInactiveSprite;
break;
case 2:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- // Normalize D2 and D3 colors from -128 ... 127 to 0 ... 255.
- sprite._foreColor = g_director->transformColor(stream.readByte() ^ 0x80);
- }
+ // Normalize D2 and D3 colors from -128 ... 127 to 0 ... 255.
+ sprite._foreColor = g_director->transformColor(stream.readByte() ^ 0x80);
break;
case 3:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- // Normalize D2 and D3 colors from -128 ... 127 to 0 ... 255.
- sprite._backColor = g_director->transformColor(stream.readByte() ^ 0x80);
- }
+ // Normalize D2 and D3 colors from -128 ... 127 to 0 ... 255.
+ sprite._backColor = g_director->transformColor(stream.readByte() ^ 0x80);
break;
case 4:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._thickness = stream.readByte() & 0x7f;
- }
+ sprite._thickness = stream.readByte() & 0x7f;
break;
case 5:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._inkData = stream.readByte();
+ sprite._inkData = stream.readByte();
- sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
- sprite._trails = sprite._inkData & 0x40 ? true : false;
- sprite._stretch = sprite._inkData & 0x80 ? true : false;
- }
+ sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
+ sprite._trails = sprite._inkData & 0x40 ? true : false;
+ sprite._stretch = sprite._inkData & 0x80 ? true : false;
break;
case 6:
- if (sprite._puppet) {
- stream.readUint16();
+ if (sprite.isQDShape()) {
+ sprite._pattern = stream.readUint16();
+ sprite._castId = CastMemberID(0, 0);
} else {
- if (sprite.isQDShape()) {
- sprite._pattern = stream.readUint16();
- sprite._castId = CastMemberID(0, 0);
- } else {
- sprite._pattern = 0;
- sprite._castId = CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB);
- }
+ sprite._pattern = 0;
+ sprite._castId = CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB);
}
break;
case 8:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
- sprite._startPoint.y = (int16)stream.readUint16();
- }
+ sprite._startPoint.y = (int16)stream.readUint16();
break;
case 10:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
- sprite._startPoint.x = (int16)stream.readUint16();
- }
+ sprite._startPoint.x = (int16)stream.readUint16();
break;
case 12:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
- sprite._height = (int16)stream.readUint16();
- }
+ sprite._height = (int16)stream.readUint16();
break;
case 14:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
- sprite._width = (int16)stream.readUint16();
- }
+ sprite._width = (int16)stream.readUint16();
break;
default:
// This means that a `case` label has to be split at this position
@@ -680,112 +640,66 @@ void readSpriteDataD4(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
while (stream.pos() < finishPosition) {
switch (stream.pos() - startPosition) {
case 0:
- sprite._scriptId = CastMemberID(stream.readByte(), DEFAULT_CAST_LIB);
+ // scriptID, not used in D4
+ stream.readByte();
+ //sprite._scriptId = CastMemberID(stream.readByte(), DEFAULT_CAST_LIB);
break;
case 1:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._spriteType = (SpriteType)stream.readByte();
- sprite._enabled = sprite._spriteType != kInactiveSprite;
- }
+ sprite._spriteType = (SpriteType)stream.readByte();
+ sprite._enabled = sprite._spriteType != kInactiveSprite;
break;
case 2:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._foreColor = g_director->transformColor((uint8)stream.readByte());
- }
+ sprite._foreColor = g_director->transformColor((uint8)stream.readByte());
break;
case 3:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._backColor = g_director->transformColor((uint8)stream.readByte());
- }
+ sprite._backColor = g_director->transformColor((uint8)stream.readByte());
break;
case 4:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._thickness = stream.readByte();
- }
+ sprite._thickness = stream.readByte();
break;
case 5:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._inkData = stream.readByte();
+ sprite._inkData = stream.readByte();
- sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
- sprite._trails = sprite._inkData & 0x40 ? true : false;
- sprite._stretch = sprite._inkData & 0x80 ? true : false;
- }
+ sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
+ sprite._trails = sprite._inkData & 0x40 ? true : false;
+ sprite._stretch = sprite._inkData & 0x80 ? true : false;
break;
case 6:
- if (sprite._puppet) {
- stream.readUint16();
+ if (sprite.isQDShape()) {
+ sprite._pattern = stream.readUint16();
} else {
- if (sprite.isQDShape()) {
- sprite._pattern = stream.readUint16();
- } else {
- sprite._castId = CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB);
- }
+ sprite._castId = CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB);
}
break;
case 8:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
- sprite._startPoint.y = (int16)stream.readUint16();
- }
+ sprite._startPoint.y = (int16)stream.readUint16();
break;
case 10:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
- sprite._startPoint.x = (int16)stream.readUint16();
- }
+ sprite._startPoint.x = (int16)stream.readUint16();
break;
case 12:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
- sprite._height = (int16)stream.readUint16();
- }
+ sprite._height = (int16)stream.readUint16();
break;
case 14:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
- sprite._width = (int16)stream.readUint16();
- }
+ sprite._width = (int16)stream.readUint16();
break;
case 16:
sprite._scriptId = CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB);
break;
case 18:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- // & 0x0f scorecolor
- // 0x10 forecolor is rgb
- // 0x20 bgcolor is rgb
- // 0x40 editable
- // 0x80 moveable
- sprite._colorcode = stream.readByte();
+ // & 0x0f scorecolor
+ // 0x10 forecolor is rgb
+ // 0x20 bgcolor is rgb
+ // 0x40 editable
+ // 0x80 moveable
+ sprite._colorcode = stream.readByte();
- sprite._editable = ((sprite._colorcode & 0x40) == 0x40);
- sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
- sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
- }
+ sprite._editable = ((sprite._colorcode & 0x40) == 0x40);
+ sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
+ sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
break;
case 19:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._blendAmount = stream.readByte();
- }
+ sprite._blendAmount = stream.readByte();
break;
default:
// This means that a `case` label has to be split at this position
@@ -1052,35 +966,21 @@ void readSpriteDataD5(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
while (stream.pos() < finishPosition) {
switch (stream.pos() - startPosition) {
case 0:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._spriteType = (SpriteType)stream.readByte();
- }
+ sprite._spriteType = (SpriteType)stream.readByte();
break;
case 1:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._inkData = stream.readByte();
+ sprite._inkData = stream.readByte();
- sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
- sprite._trails = sprite._inkData & 0x40 ? true : false;
- sprite._stretch = sprite._inkData & 0x80 ? true : false;
- }
+ sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
+ sprite._trails = sprite._inkData & 0x40 ? true : false;
+ sprite._stretch = sprite._inkData & 0x80 ? true : false;
break;
- case 2:
- if (sprite._puppet) {
- stream.readSint16();
- } else {
+ case 2: {
int castLib = stream.readSint16();
sprite._castId = CastMemberID(sprite._castId.member, castLib);
}
break;
- case 4:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
+ case 4: {
uint16 memberID = stream.readUint16();
sprite._castId = CastMemberID(memberID, sprite._castId.castLib); // Inherit castLib from previous frame
}
@@ -1096,76 +996,40 @@ void readSpriteDataD5(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
}
break;
case 10:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._foreColor = g_director->transformColor((uint8)stream.readByte());
- }
+ sprite._foreColor = g_director->transformColor((uint8)stream.readByte());
break;
case 11:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._backColor = g_director->transformColor((uint8)stream.readByte());
- }
+ sprite._backColor = g_director->transformColor((uint8)stream.readByte());
break;
case 12:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
- sprite._startPoint.y = (int16)stream.readUint16();
- }
+ sprite._startPoint.y = (int16)stream.readUint16();
break;
case 14:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
- sprite._startPoint.x = (int16)stream.readUint16();
- }
+ sprite._startPoint.x = (int16)stream.readUint16();
break;
case 16:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
- sprite._height = (int16)stream.readUint16();
- }
+ sprite._height = (int16)stream.readUint16();
break;
case 18:
- if (sprite._puppet) {
- stream.readUint16();
- } else {
- sprite._width = (int16)stream.readUint16();
- }
+ sprite._width = (int16)stream.readUint16();
break;
case 20:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- // & 0x0f scorecolor
- // 0x10 forecolor is rgb
- // 0x20 bgcolor is rgb
- // 0x40 editable
- // 0x80 moveable
- sprite._colorcode = stream.readByte();
+ // & 0x0f scorecolor
+ // 0x10 forecolor is rgb
+ // 0x20 bgcolor is rgb
+ // 0x40 editable
+ // 0x80 moveable
+ sprite._colorcode = stream.readByte();
- sprite._editable = ((sprite._colorcode & 0x40) == 0x40);
- sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
- sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
- }
+ sprite._editable = ((sprite._colorcode & 0x40) == 0x40);
+ sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
+ sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
break;
case 21:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._blendAmount = stream.readByte();
- }
+ sprite._blendAmount = stream.readByte();
break;
case 22:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._thickness = stream.readByte();
- }
+ sprite._thickness = stream.readByte();
break;
case 23:
(void)stream.readByte(); // unused
@@ -1527,28 +1391,20 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
while (stream.pos() < finishPosition) {
switch (stream.pos() - startPosition) {
case 0:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._spriteType = (SpriteType)stream.readByte();
- debugC(6, kDebugLoading, " sprite._spriteType: %d", sprite._spriteType);
- }
+ sprite._spriteType = (SpriteType)stream.readByte();
+ debugC(6, kDebugLoading, " sprite._spriteType: %d", sprite._spriteType);
break;
case 1:
- if (sprite._puppet || sprite.getAutoPuppet(kAPInk)) {
- stream.readByte();
- } else {
- sprite._inkData = stream.readByte();
+ sprite._inkData = stream.readByte();
- sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
- sprite._trails = sprite._inkData & 0x40 ? true : false;
- sprite._stretch = sprite._inkData & 0x80 ? true : false;
+ sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
+ sprite._trails = sprite._inkData & 0x40 ? true : false;
+ sprite._stretch = sprite._inkData & 0x80 ? true : false;
- debugC(6, kDebugLoading, " sprite._inkData: 0x%02x", sprite._inkData);
- debugC(6, kDebugLoading, " sprite._ink: %d", sprite._ink);
- debugC(6, kDebugLoading, " sprite._trails: %d", sprite._trails);
- debugC(6, kDebugLoading, " sprite._stretch: %d", sprite._stretch);
- }
+ debugC(6, kDebugLoading, " sprite._inkData: 0x%02x", sprite._inkData);
+ debugC(6, kDebugLoading, " sprite._ink: %d", sprite._ink);
+ debugC(6, kDebugLoading, " sprite._trails: %d", sprite._trails);
+ debugC(6, kDebugLoading, " sprite._stretch: %d", sprite._stretch);
break;
case 2:
if (sprite._puppet || sprite.getAutoPuppet(kAPForeColor)) {
@@ -1560,113 +1416,68 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
}
break;
case 3:
- if (sprite._puppet || sprite.getAutoPuppet(kAPBackColor)) {
- stream.readByte();
- } else {
- sprite._backColor = g_director->transformColor((uint8)stream.readByte());
- debugC(6, kDebugLoading, " sprite._backColor: 0x%02x", sprite._backColor);
- }
+ sprite._backColor = g_director->transformColor((uint8)stream.readByte());
+ debugC(6, kDebugLoading, " sprite._backColor: 0x%02x", sprite._backColor);
break;
- case 4:
- if (sprite._puppet || sprite.getAutoPuppet(kAPCast)) {
- stream.readSint16();
- } else {
+ case 4: {
int castLib = stream.readSint16();
sprite._castId = CastMemberID(sprite._castId.member, castLib);
debugC(6, kDebugLoading, " sprite._castId: %d", sprite._castId.member);
}
break;
- case 6:
- if (sprite._puppet || sprite.getAutoPuppet(kAPCast)) {
- stream.readUint16();
- } else {
+ case 6: {
uint16 memberID = stream.readUint16();
sprite._castId = CastMemberID(memberID, sprite._castId.castLib); // Inherit castLib from previous frame
debugC(6, kDebugLoading, " sprite._castId: %d", sprite._castId.member);
}
break;
case 8:
- if (sprite._puppet || sprite.getAutoPuppet(kAPCast)) {
- stream.readUint32();
- } else {
- sprite._spriteListIdx = stream.readUint32();
- debugC(6, kDebugLoading, " sprite._spriteListIdx: %d", sprite._spriteListIdx);
- }
+ sprite._spriteListIdx = stream.readUint32();
+ debugC(6, kDebugLoading, " sprite._spriteListIdx: %d", sprite._spriteListIdx);
break;
case 10: // This field could be optimized
- if (sprite._puppet || sprite.getAutoPuppet(kAPCast)) {
- stream.readUint16();
- } else {
- sprite._spriteListIdx = stream.readUint16();
- debugC(6, kDebugLoading, " sprite._spriteListIdx (16): %d", sprite._spriteListIdx);
- }
+ sprite._spriteListIdx = stream.readUint16();
+ debugC(6, kDebugLoading, " sprite._spriteListIdx (16): %d", sprite._spriteListIdx);
break;
case 12:
- if (sprite._puppet || sprite.getAutoPuppet(kAPLoc)) {
- stream.readUint16();
- } else {
- sprite._startPoint.y = (int16)stream.readUint16();
- debugC(6, kDebugLoading, " sprite._startPoint.y: %d", sprite._startPoint.y);
- }
+ sprite._startPoint.y = (int16)stream.readUint16();
+ debugC(6, kDebugLoading, " sprite._startPoint.y: %d", sprite._startPoint.y);
break;
case 14:
- if (sprite._puppet || sprite.getAutoPuppet(kAPLoc)) {
- stream.readUint16();
- } else {
- sprite._startPoint.x = (int16)stream.readUint16();
- debugC(6, kDebugLoading, " sprite._startPoint.x: %d", sprite._startPoint.x);}
+ sprite._startPoint.x = (int16)stream.readUint16();
+ debugC(6, kDebugLoading, " sprite._startPoint.x: %d", sprite._startPoint.x);
break;
case 16:
- if (sprite._puppet || sprite.getAutoPuppet(kAPHeight)) {
- stream.readUint16();
- } else {
- sprite._height = (int16)stream.readUint16();
- debugC(6, kDebugLoading, " sprite._height: %d", sprite._height);
- }
+ sprite._height = (int16)stream.readUint16();
+ debugC(6, kDebugLoading, " sprite._height: %d", sprite._height);
break;
case 18:
- if (sprite._puppet || sprite.getAutoPuppet(kAPWidth)) {
- stream.readUint16();
- } else {
- sprite._width = (int16)stream.readUint16();
- debugC(6, kDebugLoading, " sprite._width: %d", sprite._width);
- }
+ sprite._width = (int16)stream.readUint16();
+ debugC(6, kDebugLoading, " sprite._width: %d", sprite._width);
break;
case 20:
- if (sprite._puppet || sprite.getAutoPuppet(kAPMoveable)) {
- stream.readByte();
- } else {
- // & 0x0f scorecolor
- // 0x10 forecolor is rgb
- // 0x20 bgcolor is rgb
- // 0x40 editable
- // 0x80 moveable
- sprite._colorcode = stream.readByte();
+ // & 0x0f scorecolor
+ // 0x10 forecolor is rgb
+ // 0x20 bgcolor is rgb
+ // 0x40 editable
+ // 0x80 moveable
+ sprite._colorcode = stream.readByte();
- sprite._editable = ((sprite._colorcode & 0x40) == 0x40);
- sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
- sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
+ sprite._editable = ((sprite._colorcode & 0x40) == 0x40);
+ sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
+ sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
- debugC(6, kDebugLoading, " sprite._colorcode: 0x%02x", sprite._colorcode);
- debugC(6, kDebugLoading, " sprite._editable: %d", sprite._editable);
- debugC(6, kDebugLoading, " sprite._moveable: %d", sprite._moveable);
- }
+ debugC(6, kDebugLoading, " sprite._colorcode: 0x%02x", sprite._colorcode);
+ debugC(6, kDebugLoading, " sprite._editable: %d", sprite._editable);
+ debugC(6, kDebugLoading, " sprite._moveable: %d", sprite._moveable);
break;
case 21:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._blendAmount = stream.readByte();
- debugC(6, kDebugLoading, " sprite._blendAmount: %d", sprite._blendAmount);
- }
+ sprite._blendAmount = stream.readByte();
+ debugC(6, kDebugLoading, " sprite._blendAmount: %d", sprite._blendAmount);
break;
case 22:
- if (sprite._puppet) {
- stream.readByte();
- } else {
- sprite._thickness = stream.readByte();
- debugC(6, kDebugLoading, " sprite._thickness: %d", sprite._thickness);
- }
+ sprite._thickness = stream.readByte();
+ debugC(6, kDebugLoading, " sprite._thickness: %d", sprite._thickness);
break;
case 23:
(void)stream.readByte(); // unused
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 2bfb94aa681..95a353425f0 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -3213,7 +3213,8 @@ void LB::b_immediateSprite(int nargs) {
}
void LB::b_puppetSprite(int nargs) {
- Score *sc = g_director->getCurrentMovie()->getScore();
+ Movie *movie = g_director->getCurrentMovie();
+ Score *sc = movie->getScore();
if (!sc) {
warning("b_puppetSprite: no score");
g_lingo->dropStack(nargs);
@@ -3225,7 +3226,18 @@ void LB::b_puppetSprite(int nargs) {
Datum sprite = g_lingo->pop();
if ((uint)sprite.asInt() < sc->_channels.size()) {
- sc->getSpriteById(sprite.asInt())->_puppet = (bool)state.asInt();
+ int spriteId = sprite.asInt();
+ Sprite *target = sc->getSpriteById(spriteId);
+ bool val = (bool)state.asInt();
+ bool refresh = (!val) && (target->_puppet);
+ target->_puppet = val;
+ if (refresh) {
+ // puppetSprite set to FALSE, copy back sprite data from frame cache
+ Channel *chan = sc->getChannelById(spriteId);
+ movie->getWindow()->addDirtyRect(chan->getBbox());
+ chan->setClean(sc->_currentFrame->_sprites[spriteId]);
+ chan->_dirty = true;
+ }
} else {
warning("b_puppetSprite: sprite index out of bounds");
}
More information about the Scummvm-git-logs
mailing list