[Scummvm-git-logs] scummvm master -> 68518fc8a9b04ccfff5822d99b28615d30762a22
moralrecordings
code at moral.net.au
Mon Oct 11 17:11:14 UTC 2021
This automated email contains information about 11 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
d61a03d120 DIRECTOR: LINGO: Fix memory leak
0ecdd9b26f DIRECTOR: Add preliminary loader for film loops
0efc7139a9 DIRECTOR: Refactor FilmLoopCastMember to use Sprite
6f60e8c54e DIRECTOR: Add stub for FilmLoopCastMember::createWidget
e4f767c916 DIRECTOR: Move methods from Channel to Sprite
8963cf211a DIRECTOR: Move methods from Window to DirectorPlotData
257fd958e7 DIRECTOR: Add blitting code to FilmLoopCastMember
0e0254a5f7 DIRECTOR: Fix currentFrameRate loading for v4
8b240f69b8 DIRECTOR: Fix inkBlitShape to use destRect for drawing
47c5b37067 DIRECTOR: Fix use-after-free in Sprite
68518fc8a9 DIRECTOR: Fix default palette index
Commit: d61a03d12081012ae2f068f061e10794a790012a
https://github.com/scummvm/scummvm/commit/d61a03d12081012ae2f068f061e10794a790012a
Author: Scott Percival (code at moral.net.au)
Date: 2021-10-12T01:08:34+08:00
Commit Message:
DIRECTOR: LINGO: Fix memory leak
Changed paths:
engines/director/lingo/lingo.cpp
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index dabbcb772b..6d25d24e1a 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -721,7 +721,7 @@ Datum Datum::eval() const {
return g_lingo->varFetch(*this);
}
- return *this;
+ return Datum(*this);
}
int Datum::asInt() const {
@@ -1368,8 +1368,8 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
case CASTREF:
case CHUNKREF:
{
- result.type = STRING;
- result.u.s = new Common::String(evalChunkRef(var), Common::kUtf8);
+ Common::String chunk(evalChunkRef(var), Common::kUtf8);
+ result = Datum(chunk);
}
break;
default:
Commit: 0ecdd9b26f64d7ed3d86fad6eecd9ea9e5245e2d
https://github.com/scummvm/scummvm/commit/0ecdd9b26f64d7ed3d86fad6eecd9ea9e5245e2d
Author: Scott Percival (code at moral.net.au)
Date: 2021-10-12T01:08:34+08:00
Commit Message:
DIRECTOR: Add preliminary loader for film loops
Changed paths:
engines/director/cast.cpp
engines/director/cast.h
engines/director/castmember.cpp
engines/director/castmember.h
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 1b9273f866..17ec4c5442 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -417,11 +417,6 @@ void Cast::loadCast() {
debug("STUB: Unhandled 'PICT' resource");
}
- // Film Loop resources
- if (_castArchive->hasResource(MKTAG('S', 'C', 'V', 'W'), -1)) {
- debug("STUB: Unhandled 'SCVW' resource");
- }
-
// External Cast Reference resources
if (_castArchive->hasResource(MKTAG('S', 'C', 'R', 'F'), -1)) {
debug("STUB: Unhandled 'SCRF' resource");
@@ -505,7 +500,31 @@ void Cast::loadCastChildren() {
// for D2, we shall use the castId to get the palette
member->_palette = g_director->getPalette(member->getID());
} else {
- warning("Cast::loadSpriteChildren(): Expected 1 child for palette cast, got %d", member->_children.size());
+ warning("Cast::loadCastChildren(): Expected 1 child for palette cast, got %d", member->_children.size());
+ }
+ continue;
+ }
+
+ // Then load film loops
+ if (c->_value->_type == kCastFilmLoop) {
+ FilmLoopCastMember *member = ((FilmLoopCastMember *)c->_value);
+
+ if (_version >= kFileVer400 && _version < kFileVer500) {
+ if (member->_children.size() == 1) {
+ uint16 filmLoopId = member->_children[0].index;
+ uint32 tag = member->_children[0].tag;
+ if (_castArchive->hasResource(tag, filmLoopId)) {
+ Common::SeekableReadStreamEndian *loop = _castArchive->getResource(tag, filmLoopId);
+ debugC(2, kDebugLoading, "****** Loading '%s' id: %d, %d bytes", tag2str(tag), filmLoopId, (int)loop->size());
+ member->loadFilmLoopData(*loop);
+ } else {
+ warning("Cast::loadCastChildren(): Film loop not found");
+ }
+ } else {
+ warning("Cast::loadCastChildren(): Expected 1 child for film loop cast, got %d", member->_children.size());
+ }
+ } else {
+ warning("STUB: Cast::loadCastChildren(): Film loops not supported for version %d", _version);
}
continue;
}
@@ -925,8 +944,8 @@ void Cast::loadCastData(Common::SeekableReadStreamEndian &stream, uint16 id, Res
_loadedCast->setVal(id, new DigitalVideoCastMember(this, id, castStream, _version));
break;
case kCastFilmLoop:
- warning("STUB: Cast::loadCastData(): kCastFilmLoop (id=%d, %d children)! This will be missing from the movie and may cause problems", id, res->children.size());
- castInfoSize = 0;
+ debugC(3, kDebugLoading, "Cast::loadCastData(): loading kCastFilmLoop (%d children)", res->children.size());
+ _loadedCast->setVal(id, new FilmLoopCastMember(this, id, castStream, _version));
break;
case kCastPalette:
debugC(3, kDebugLoading, "Cast::loadCastData(): loading kCastPalette (%d children)", res->children.size());
@@ -1206,6 +1225,14 @@ void Cast::loadCastInfo(Common::SeekableReadStreamEndian &stream, uint16 id) {
((SoundCastMember *)member)->_looping = castInfo.flags & 16 ? 0 : 1;
}
+ // For FilmLoopCastMember, read the flags in the CastInfo
+ if (_version >= kFileVer400 && _version < kFileVer500 && member->_type == kCastFilmLoop) {
+ ((FilmLoopCastMember *)member)->_looping = castInfo.flags & 64 ? 0 : 1;
+ ((FilmLoopCastMember *)member)->_enableSound = castInfo.flags & 8 ? 1 : 0;
+ ((FilmLoopCastMember *)member)->_crop = castInfo.flags & 2 ? 0 : 1;
+ ((FilmLoopCastMember *)member)->_center = castInfo.flags & 1 ? 1 : 0;
+ }
+
ci->autoHilite = castInfo.flags & 2;
ci->scriptId = castInfo.scriptId;
if (ci->scriptId != 0)
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 8b55496342..c5d1baf971 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -42,6 +42,7 @@ struct LingoArchive;
struct Resource;
class Stxt;
class BitmapCastMember;
+class FilmLoopCastMember;
class ScriptCastMember;
class ShapeCastMember;
class TextCastMember;
diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp
index 3a78185174..7a8fc344ce 100644
--- a/engines/director/castmember.cpp
+++ b/engines/director/castmember.cpp
@@ -548,6 +548,128 @@ void DigitalVideoCastMember::setFrameRate(int rate) {
warning("STUB: DigitalVideoCastMember::setFrameRate(%d)", rate);
}
+/////////////////////////////////////
+// Film loops
+/////////////////////////////////////
+
+FilmLoopCastMember::FilmLoopCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version)
+ : CastMember(cast, castId, stream) {
+ _type = kCastFilmLoop;
+ _looping = true;
+ _enableSound = true;
+ _crop = false;
+ _center = false;
+}
+
+FilmLoopCastMember::~FilmLoopCastMember() {
+
+}
+
+void FilmLoopCastMember::loadFilmLoopData(Common::SeekableReadStreamEndian &stream) {
+ _bbox = Common::Rect();
+ _frames.clear();
+
+ uint32 size = stream.readUint32BE();
+ if (debugChannelSet(5, kDebugLoading)) {
+ debugC(5, kDebugLoading, "SCVW body:");
+ uint32 pos = stream.pos();
+ stream.seek(0);
+ stream.hexdump(size);
+ stream.seek(pos);
+ }
+ uint32 framesOffset = stream.readUint32BE();
+ if (debugChannelSet(5, kDebugLoading)) {
+ debugC(5, kDebugLoading, "SCVW header:");
+ stream.hexdump(framesOffset - 8);
+ }
+ stream.skip(6);
+ uint16 channelSize = stream.readUint16BE(); // should be 20!
+ stream.skip(framesOffset - 16);
+
+ FilmLoopFrame newFrame;
+
+ while (stream.pos() < size) {
+ uint16 frameSize = stream.readUint16BE() - 2;
+ if (debugChannelSet(5, kDebugLoading)) {
+ debugC(5, kDebugLoading, "Frame entry:");
+ stream.hexdump(frameSize);
+ }
+
+ while (frameSize > 0) {
+ uint16 msgWidth = stream.readUint16BE();
+ uint16 order = stream.readUint16BE();
+ frameSize -= 4;
+
+ int channel = (order / channelSize) - 1;
+ int channelOffset = order % channelSize;
+
+ uint16 spriteCastId = 0;
+ int16 x = 0;
+ int16 y = 0;
+ uint16 width = 0;
+ uint16 height = 0;
+ if (newFrame.sprites.contains(channel)) {
+ FilmLoopSprite s = newFrame.sprites.getVal(channel);
+ spriteCastId = s.castId;
+ x = s.bbox.left;
+ y = s.bbox.top;
+ width = s.bbox.width();
+ height = s.bbox.height();
+ }
+ debugC(8, kDebugLoading, "Message: msgWidth %d, channel %d, channelOffset %d", msgWidth, channel, channelOffset);
+ if (debugChannelSet(8, kDebugLoading)) {
+ stream.hexdump(msgWidth);
+ }
+
+ for (int i = channelOffset; i < channelOffset + msgWidth; i += 2) {
+ switch (i) {
+ case 6:
+ spriteCastId = stream.readUint16BE();
+ break;
+ case 8:
+ y = stream.readSint16BE();
+ break;
+ case 10:
+ x = stream.readSint16BE();
+ break;
+ case 12:
+ height = stream.readUint16BE();
+ break;
+ case 14:
+ width = stream.readUint16BE();
+ break;
+ default:
+ stream.readUint16BE();
+ break;
+ }
+ }
+
+ frameSize -= msgWidth;
+
+ Common::Rect spriteBbox(x, y, x + width, y + height);
+ newFrame.sprites.setVal(channel, FilmLoopSprite(spriteCastId, spriteBbox));
+ if (!_bbox.isValidRect()) {
+ _bbox = spriteBbox;
+ } else {
+ _bbox.extend(spriteBbox);
+ }
+ }
+
+ if (debugChannelSet(5, kDebugLoading)) {
+ for (Common::HashMap<int, FilmLoopSprite>::iterator s = newFrame.sprites.begin(); s != newFrame.sprites.end(); ++s) {
+ debugC(5, kDebugLoading, "FilmLoopSprite: channel %d, castId %d, bbox %d %d %d %d", s->_key,
+ s->_value.castId, s->_value.bbox.left, s->_value.bbox.top,
+ s->_value.bbox.width(), s->_value.bbox.height());
+
+ }
+ }
+
+ _frames.push_back(newFrame);
+
+ }
+
+}
+
/////////////////////////////////////
// Sound
diff --git a/engines/director/castmember.h b/engines/director/castmember.h
index d76960ef6b..b2cc36be17 100644
--- a/engines/director/castmember.h
+++ b/engines/director/castmember.h
@@ -189,6 +189,35 @@ public:
Channel *_channel;
};
+
+
+struct FilmLoopSprite {
+ uint16 castId;
+ Common::Rect bbox;
+ FilmLoopSprite() { castId = 0; }
+ FilmLoopSprite(uint16 castId1, Common::Rect &bbox1) { castId = castId1; bbox = bbox1; }
+};
+
+struct FilmLoopFrame {
+ Common::HashMap<int, FilmLoopSprite> sprites;
+};
+
+class FilmLoopCastMember : public CastMember {
+public:
+ FilmLoopCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version);
+ ~FilmLoopCastMember();
+
+ void loadFilmLoopData(Common::SeekableReadStreamEndian &stream);
+
+ bool _enableSound;
+ bool _looping;
+ bool _crop;
+ bool _center;
+
+ Common::Rect _bbox;
+ Common::Array<FilmLoopFrame> _frames;
+};
+
class SoundCastMember : public CastMember {
public:
SoundCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version);
Commit: 0efc7139a9100617c8ea079edc234dbca74cc1af
https://github.com/scummvm/scummvm/commit/0efc7139a9100617c8ea079edc234dbca74cc1af
Author: Scott Percival (code at moral.net.au)
Date: 2021-10-12T01:08:34+08:00
Commit Message:
DIRECTOR: Refactor FilmLoopCastMember to use Sprite
Changed paths:
engines/director/castmember.cpp
engines/director/castmember.h
engines/director/sprite.cpp
engines/director/sprite.h
diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp
index 7a8fc344ce..89d3bc678c 100644
--- a/engines/director/castmember.cpp
+++ b/engines/director/castmember.cpp
@@ -30,6 +30,7 @@
#include "director/cursor.h"
#include "director/channel.h"
#include "director/movie.h"
+#include "director/sprite.h"
#include "director/sound.h"
#include "director/window.h"
#include "director/stxt.h"
@@ -603,63 +604,93 @@ void FilmLoopCastMember::loadFilmLoopData(Common::SeekableReadStreamEndian &stre
int channel = (order / channelSize) - 1;
int channelOffset = order % channelSize;
- uint16 spriteCastId = 0;
- int16 x = 0;
- int16 y = 0;
- uint16 width = 0;
- uint16 height = 0;
+ Sprite sprite(nullptr);
if (newFrame.sprites.contains(channel)) {
- FilmLoopSprite s = newFrame.sprites.getVal(channel);
- spriteCastId = s.castId;
- x = s.bbox.left;
- y = s.bbox.top;
- width = s.bbox.width();
- height = s.bbox.height();
+ sprite = newFrame.sprites.getVal(channel);
}
debugC(8, kDebugLoading, "Message: msgWidth %d, channel %d, channelOffset %d", msgWidth, channel, channelOffset);
if (debugChannelSet(8, kDebugLoading)) {
stream.hexdump(msgWidth);
}
- for (int i = channelOffset; i < channelOffset + msgWidth; i += 2) {
- switch (i) {
- case 6:
- spriteCastId = stream.readUint16BE();
+ int fieldPosition = channelOffset;
+ int finishPosition = channelOffset + msgWidth;
+ while (fieldPosition < finishPosition) {
+ switch (fieldPosition) {
+ case kSpritePositionUnk1:
+ stream.readByte();
+ fieldPosition++;
+ break;
+ case kSpritePositionEnabled:
+ sprite._enabled = stream.readByte() != 0;
+ fieldPosition++;
+ break;
+ case kSpritePositionUnk2:
+ stream.readUint16BE();
+ fieldPosition += 2;
+ break;
+ case kSpritePositionFlags:
+ sprite._thickness = stream.readByte();
+ sprite._inkData = stream.readByte();
+ sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
+
+ if (sprite._inkData & 0x40)
+ sprite._trails = 1;
+ else
+ sprite._trails = 0;
+
+ fieldPosition += 2;
+ break;
+ case kSpritePositionCastId:
+ sprite._castId = CastMemberID(stream.readUint16(), 0);
+ fieldPosition += 2;
break;
- case 8:
- y = stream.readSint16BE();
+ case kSpritePositionY:
+ sprite._startPoint.y = stream.readUint16();
+ fieldPosition += 2;
break;
- case 10:
- x = stream.readSint16BE();
+ case kSpritePositionX:
+ sprite._startPoint.x = stream.readUint16();
+ fieldPosition += 2;
break;
- case 12:
- height = stream.readUint16BE();
+ case kSpritePositionWidth:
+ sprite._width = stream.readUint16();
+ fieldPosition += 2;
break;
- case 14:
- width = stream.readUint16BE();
+ case kSpritePositionHeight:
+ sprite._height = stream.readUint16();
+ fieldPosition += 2;
break;
default:
stream.readUint16BE();
+ fieldPosition += 2;
break;
}
}
frameSize -= msgWidth;
- Common::Rect spriteBbox(x, y, x + width, y + height);
- newFrame.sprites.setVal(channel, FilmLoopSprite(spriteCastId, spriteBbox));
- if (!_bbox.isValidRect()) {
- _bbox = spriteBbox;
- } else {
- _bbox.extend(spriteBbox);
+ Common::Rect spriteBbox(
+ sprite._startPoint.x,
+ sprite._startPoint.y,
+ sprite._startPoint.x + sprite._width,
+ sprite._startPoint.y + sprite._height
+ );
+ newFrame.sprites.setVal(channel, sprite);
+ if (!((spriteBbox.width() == 0) && (spriteBbox.height() == 0))) {
+ if ((_bbox.width() == 0) && (_bbox.height() == 0)) {
+ _bbox = spriteBbox;
+ } else {
+ _bbox.extend(spriteBbox);
+ }
}
}
if (debugChannelSet(5, kDebugLoading)) {
- for (Common::HashMap<int, FilmLoopSprite>::iterator s = newFrame.sprites.begin(); s != newFrame.sprites.end(); ++s) {
- debugC(5, kDebugLoading, "FilmLoopSprite: channel %d, castId %d, bbox %d %d %d %d", s->_key,
- s->_value.castId, s->_value.bbox.left, s->_value.bbox.top,
- s->_value.bbox.width(), s->_value.bbox.height());
+ for (Common::HashMap<int, Sprite>::iterator s = newFrame.sprites.begin(); s != newFrame.sprites.end(); ++s) {
+ debugC(5, kDebugLoading, "Sprite: channel %d, castId %s, bbox %d %d %d %d", s->_key,
+ s->_value._castId.asString().c_str(), s->_value._startPoint.x, s->_value._startPoint.y,
+ s->_value._width, s->_value._height);
}
}
@@ -667,6 +698,7 @@ void FilmLoopCastMember::loadFilmLoopData(Common::SeekableReadStreamEndian &stre
_frames.push_back(newFrame);
}
+ debugC(5, kDebugLoading, "Full bounding box: %d %d %d %d", _bbox.left, _bbox.top, _bbox.width(), _bbox.height());
}
diff --git a/engines/director/castmember.h b/engines/director/castmember.h
index b2cc36be17..7d7cc5ac27 100644
--- a/engines/director/castmember.h
+++ b/engines/director/castmember.h
@@ -26,6 +26,7 @@
#include "graphics/font.h"
#include "director/archive.h"
+#include "director/sprite.h"
#include "director/stxt.h"
#include "director/lingo/lingo-object.h"
@@ -58,6 +59,7 @@ class AudioDecoder;
struct CastMemberInfo;
class Channel;
struct Resource;
+class Sprite;
class Stxt;
class CastMember : public Object<CastMember> {
@@ -190,16 +192,8 @@ public:
};
-
-struct FilmLoopSprite {
- uint16 castId;
- Common::Rect bbox;
- FilmLoopSprite() { castId = 0; }
- FilmLoopSprite(uint16 castId1, Common::Rect &bbox1) { castId = castId1; bbox = bbox1; }
-};
-
struct FilmLoopFrame {
- Common::HashMap<int, FilmLoopSprite> sprites;
+ Common::HashMap<int, Sprite> sprites;
};
class FilmLoopCastMember : public CastMember {
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 7e5899143a..27d9275887 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -35,8 +35,8 @@ namespace Director {
Sprite::Sprite(Frame *frame) {
_frame = frame;
- _score = _frame->getScore();
- _movie = _score->getMovie();
+ _score = _frame ? _frame->getScore() : nullptr;
+ _movie = _score ? _score->getMovie() : nullptr;
_scriptId = CastMemberID(0, 0);
_colorcode = 0;
@@ -71,6 +71,45 @@ Sprite::Sprite(Frame *frame) {
_stretch = 0;
}
+Sprite::Sprite(const Sprite &sprite) {
+ _frame = sprite._frame;
+ _score = sprite._score;
+ _movie = sprite._movie;
+
+ _scriptId = sprite._scriptId;
+ _colorcode = sprite._colorcode;
+ _blendAmount = sprite._blendAmount;
+ _unk3 = sprite._unk3;
+
+ _enabled = sprite._enabled;
+ _castId = sprite._castId;
+ _pattern = sprite._pattern;
+
+ _spriteType = sprite._spriteType;
+ _inkData = sprite._inkData;
+ _ink = sprite._ink;
+ _trails = sprite._trails;
+
+ _matte = sprite._matte;
+ _cast = sprite._cast;
+
+ _thickness = sprite._thickness;
+ _startPoint = sprite._startPoint;
+ _width = sprite._width;
+ _height = sprite._height;
+ _moveable = sprite._moveable;
+ _editable = sprite._editable;
+ _puppet = sprite._puppet;
+ _immediate = sprite._immediate;
+ _backColor = sprite._backColor;
+ _foreColor = sprite._foreColor;
+
+ _blend = sprite._blend;
+
+ _volume = sprite._volume;
+ _stretch = sprite._stretch;
+}
+
Sprite::~Sprite() {
delete _matte;
}
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
index 26ea5a14a1..04734a2dd1 100644
--- a/engines/director/sprite.h
+++ b/engines/director/sprite.h
@@ -32,8 +32,8 @@ class TextCastMember;
enum SpritePosition {
kSpritePositionUnk1 = 0,
- kSpritePositionEnabled,
- kSpritePositionUnk2,
+ kSpritePositionEnabled = 1,
+ kSpritePositionUnk2 = 2,
kSpritePositionFlags = 4,
kSpritePositionCastId = 6,
kSpritePositionY = 8,
@@ -59,7 +59,8 @@ enum MainChannelsPosition {
class Sprite {
public:
- Sprite(Frame *frame);
+ Sprite(Frame *frame = nullptr);
+ Sprite(const Sprite &sprite);
~Sprite();
Frame *getFrame() const { return _frame; }
Commit: 6f60e8c54e4ca6e7cad108e7f57e3f106241a5b3
https://github.com/scummvm/scummvm/commit/6f60e8c54e4ca6e7cad108e7f57e3f106241a5b3
Author: Scott Percival (code at moral.net.au)
Date: 2021-10-12T01:08:34+08:00
Commit Message:
DIRECTOR: Add stub for FilmLoopCastMember::createWidget
Changed paths:
engines/director/castmember.cpp
engines/director/castmember.h
diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp
index 89d3bc678c..683bea1876 100644
--- a/engines/director/castmember.cpp
+++ b/engines/director/castmember.cpp
@@ -566,6 +566,50 @@ FilmLoopCastMember::~FilmLoopCastMember() {
}
+bool FilmLoopCastMember::isModified() {
+ if (_frames.size())
+ return true;
+
+ if (_bbox.width() && _bbox.height())
+ return true;
+
+ return false;
+}
+
+Graphics::MacWidget *FilmLoopCastMember::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);
+
+ if (channel->_filmLoopFrame >= _frames.size()) {
+ warning("Film loop frame %d requested, only %d available", channel->_filmLoopFrame, _frames.size());
+ return widget;
+ }
+
+ // get the list of sprite IDs for this frame
+ Common::Array<int> spriteIds;
+ for (Common::HashMap<int, Director::Sprite>::iterator iter = _frames[channel->_filmLoopFrame].sprites.begin(); iter != _frames[channel->_filmLoopFrame].sprites.end(); ++iter) {
+ spriteIds.push_back(iter->_key);
+ }
+ Common::sort(spriteIds.begin(), spriteIds.end());
+
+ // render the sprites in order onto the widget surface
+ for (Common::Array<int>::iterator iter = spriteIds.begin(); iter != spriteIds.end(); ++iter) {
+ Sprite src = _frames[channel->_filmLoopFrame].sprites[*iter];
+ if (src._castId.member == 0)
+ continue;
+ // translate sprite relative to the global bounding box
+ int16 x = (src._startPoint.x - _bbox.left) * bbox.width() / _bbox.width() + bbox.left;
+ int16 y = (src._startPoint.y - _bbox.top) * bbox.height() / _bbox.height() + bbox.top;
+ int16 width = src._width * bbox.width() / _bbox.width();
+ int16 height = src._height * bbox.height() / _bbox.height();
+ Common::Rect srcBbox(x, y, x + width, y + height);
+ //Graphics::MacWidget *srcWidget = src._cast->createWidget(srcBbox, channel, spriteType);
+ //widget->getSurface()->blitFrom(*srcWidget->getSurface(), Common::Point(x, y));
+ //delete srcWidget;
+ }
+
+ return widget;
+}
+
void FilmLoopCastMember::loadFilmLoopData(Common::SeekableReadStreamEndian &stream) {
_bbox = Common::Rect();
_frames.clear();
@@ -605,6 +649,7 @@ void FilmLoopCastMember::loadFilmLoopData(Common::SeekableReadStreamEndian &stre
int channelOffset = order % channelSize;
Sprite sprite(nullptr);
+ sprite._movie = g_director->getCurrentMovie();
if (newFrame.sprites.contains(channel)) {
sprite = newFrame.sprites.getVal(channel);
}
@@ -642,7 +687,7 @@ void FilmLoopCastMember::loadFilmLoopData(Common::SeekableReadStreamEndian &stre
fieldPosition += 2;
break;
case kSpritePositionCastId:
- sprite._castId = CastMemberID(stream.readUint16(), 0);
+ sprite.setCast(CastMemberID(stream.readUint16(), 0));
fieldPosition += 2;
break;
case kSpritePositionY:
diff --git a/engines/director/castmember.h b/engines/director/castmember.h
index 7d7cc5ac27..84067b7411 100644
--- a/engines/director/castmember.h
+++ b/engines/director/castmember.h
@@ -201,6 +201,9 @@ public:
FilmLoopCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version);
~FilmLoopCastMember();
+ virtual bool isModified() override;
+ virtual Graphics::MacWidget *createWidget(Common::Rect &bbox, Channel *channel, SpriteType spriteType) override;
+
void loadFilmLoopData(Common::SeekableReadStreamEndian &stream);
bool _enableSound;
Commit: e4f767c91621f35aa0243be8675807291ef19f5b
https://github.com/scummvm/scummvm/commit/e4f767c91621f35aa0243be8675807291ef19f5b
Author: Scott Percival (code at moral.net.au)
Date: 2021-10-12T01:08:34+08:00
Commit Message:
DIRECTOR: Move methods from Channel to Sprite
Changed paths:
engines/director/channel.cpp
engines/director/channel.h
engines/director/sprite.cpp
engines/director/sprite.h
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index e545afbf87..079e9abdf2 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -28,6 +28,7 @@
#include "director/channel.h"
#include "director/sprite.h"
#include "director/castmember.h"
+#include "director/types.h"
#include "director/window.h"
#include "graphics/macgui/mactext.h"
@@ -56,6 +57,8 @@ Channel::Channel(Sprite *sp, int priority) {
_startTime = 0;
_stopTime = 0;
+ _filmLoopFrame = 0;
+
_visible = true;
_dirty = true;
@@ -69,7 +72,7 @@ Channel::~Channel() {
}
DirectorPlotData Channel::getPlotData() {
- DirectorPlotData pd(g_director->_wm, _sprite->_spriteType, _sprite->_ink, _sprite->_blend, getBackColor(), getForeColor());
+ DirectorPlotData pd(g_director->_wm, _sprite->_spriteType, _sprite->_ink, _sprite->_blend, _sprite->getBackColor(), _sprite->getForeColor());
pd.colorWhite = pd._wm->_colorWhite;
pd.colorBlack = pd._wm->_colorBlack;
pd.dst = nullptr;
@@ -77,7 +80,7 @@ DirectorPlotData Channel::getPlotData() {
pd.srf = getSurface();
if (!pd.srf && _sprite->_spriteType != kBitmapSprite) {
// Shapes come colourized from macDrawPixel
- pd.ms = getShape();
+ pd.ms = _sprite->getShape();
pd.applyColor = false;
} else {
pd.setApplyColor();
@@ -338,6 +341,18 @@ void Channel::setClean(Sprite *nextSprite, int spriteId, bool partial) {
((DigitalVideoCastMember *)nextSprite->_cast)->loadVideo(pathMakeRelative(path, true, false));
((DigitalVideoCastMember *)nextSprite->_cast)->startVideo(this);
}
+ } else if (nextSprite->_cast->_type == kCastFilmLoop) {
+ // brand new film loop, reset the frame counter
+ _filmLoopFrame = 0;
+ }
+ }
+
+ // if the next sprite in the channel shares the cast member
+ if (nextSprite->_cast && _sprite->_castId == nextSprite->_castId) {
+ if (nextSprite->_cast->_type == kCastFilmLoop) {
+ // increment the film loop counter
+ _filmLoopFrame += 1;
+ _filmLoopFrame %= ((FilmLoopCastMember *)nextSprite->_cast)->_frames.size();
}
}
@@ -694,86 +709,4 @@ Common::Point Channel::getPosition() {
return res;
}
-MacShape *Channel::getShape() {
- if (!_sprite->isQDShape() && (_sprite->_cast && _sprite->_cast->_type != kCastShape))
- return nullptr;
-
- MacShape *shape = new MacShape();
-
- shape->ink = _sprite->_ink;
- shape->spriteType = _sprite->_spriteType;
- shape->foreColor = _sprite->_foreColor;
- shape->backColor = _sprite->_backColor;
- shape->lineSize = _sprite->_thickness & 0x3;
- shape->pattern = _sprite->getPattern();
-
- if (g_director->getVersion() >= 300 && shape->spriteType == kCastMemberSprite) {
- if (!_sprite->_cast) {
- warning("Channel::getShape(): kCastMemberSprite has no cast defined");
- delete shape;
- return nullptr;
- }
-
- ShapeCastMember *sc = (ShapeCastMember *)_sprite->_cast;
- switch (sc->_shapeType) {
- case kShapeRectangle:
- shape->spriteType = sc->_fillType ? kRectangleSprite : kOutlinedRectangleSprite;
- break;
- case kShapeRoundRect:
- shape->spriteType = sc->_fillType ? kRoundedRectangleSprite : kOutlinedRoundedRectangleSprite;
- break;
- case kShapeOval:
- shape->spriteType = sc->_fillType ? kOvalSprite : kOutlinedOvalSprite;
- break;
- case kShapeLine:
- shape->spriteType = sc->_lineDirection == 6 ? kLineBottomTopSprite : kLineTopBottomSprite;
- break;
- default:
- break;
- }
-
- if (g_director->getVersion() >= 400) {
- shape->foreColor = sc->getForeColor();
- shape->backColor = sc->getBackColor();
- shape->lineSize = sc->_lineThickness;
- shape->ink = sc->_ink;
- }
- }
-
- // for outlined shapes, line thickness of 1 means invisible.
- shape->lineSize -= 1;
-
- return shape;
-}
-
-uint32 Channel::getBackColor() {
- if (!_sprite->_cast)
- return _sprite->_backColor;
-
- switch (_sprite->_cast->_type) {
- case kCastText:
- case kCastButton:
- case kCastShape: {
- return _sprite->_cast->getBackColor();
- }
- default:
- return _sprite->_backColor;
- }
-}
-
-uint32 Channel::getForeColor() {
- if (!_sprite->_cast)
- return _sprite->_foreColor;
-
- switch (_sprite->_cast->_type) {
- case kCastText:
- case kCastButton:
- case kCastShape: {
- return _sprite->_cast->getForeColor();
- }
- default:
- return _sprite->_foreColor;
- }
-}
-
} // End of namespace Director
diff --git a/engines/director/channel.h b/engines/director/channel.h
index cd81175b50..2167ec3480 100644
--- a/engines/director/channel.h
+++ b/engines/director/channel.h
@@ -97,18 +97,18 @@ public:
int _width;
int _height;
- // Using in digital movie sprites
+ // Used in digital movie sprites
double _movieRate;
int _movieTime;
int _startTime;
int _stopTime;
+ // Used in film loops
+ uint _filmLoopFrame;
+
private:
Graphics::ManagedSurface *getSurface();
- MacShape *getShape();
Common::Point getPosition();
- uint32 getForeColor();
- uint32 getBackColor();
void addRegistrationOffset(Common::Point &pos, bool subtract = false);
};
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 27d9275887..4dda654a18 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -187,6 +187,88 @@ Graphics::Surface *Sprite::getQDMatte() {
return _matte ? _matte->getMask() : nullptr;
}
+MacShape *Sprite::getShape() {
+ if (!isQDShape() && (_cast && _cast->_type != kCastShape))
+ return nullptr;
+
+ MacShape *shape = new MacShape();
+
+ shape->ink = _ink;
+ shape->spriteType = _spriteType;
+ shape->foreColor = _foreColor;
+ shape->backColor = _backColor;
+ shape->lineSize = _thickness & 0x3;
+ shape->pattern = getPattern();
+
+ if (g_director->getVersion() >= 300 && shape->spriteType == kCastMemberSprite) {
+ if (!_cast) {
+ warning("Sprite::getShape(): kCastMemberSprite has no cast defined");
+ delete shape;
+ return nullptr;
+ }
+
+ ShapeCastMember *sc = (ShapeCastMember *)_cast;
+ switch (sc->_shapeType) {
+ case kShapeRectangle:
+ shape->spriteType = sc->_fillType ? kRectangleSprite : kOutlinedRectangleSprite;
+ break;
+ case kShapeRoundRect:
+ shape->spriteType = sc->_fillType ? kRoundedRectangleSprite : kOutlinedRoundedRectangleSprite;
+ break;
+ case kShapeOval:
+ shape->spriteType = sc->_fillType ? kOvalSprite : kOutlinedOvalSprite;
+ break;
+ case kShapeLine:
+ shape->spriteType = sc->_lineDirection == 6 ? kLineBottomTopSprite : kLineTopBottomSprite;
+ break;
+ default:
+ break;
+ }
+
+ if (g_director->getVersion() >= 400) {
+ shape->foreColor = sc->getForeColor();
+ shape->backColor = sc->getBackColor();
+ shape->lineSize = sc->_lineThickness;
+ shape->ink = sc->_ink;
+ }
+ }
+
+ // for outlined shapes, line thickness of 1 means invisible.
+ shape->lineSize -= 1;
+
+ return shape;
+}
+
+uint32 Sprite::getBackColor() {
+ if (!_cast)
+ return _backColor;
+
+ switch (_cast->_type) {
+ case kCastText:
+ case kCastButton:
+ case kCastShape: {
+ return _cast->getBackColor();
+ }
+ default:
+ return _backColor;
+ }
+}
+
+uint32 Sprite::getForeColor() {
+ if (!_cast)
+ return _foreColor;
+
+ switch (_cast->_type) {
+ case kCastText:
+ case kCastButton:
+ case kCastShape: {
+ return _cast->getForeColor();
+ }
+ default:
+ return _foreColor;
+ }
+}
+
void Sprite::updateEditable() {
if (!_cast)
return;
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
index 04734a2dd1..86b2e15dde 100644
--- a/engines/director/sprite.h
+++ b/engines/director/sprite.h
@@ -80,6 +80,9 @@ public:
bool isQDShape();
Graphics::Surface *getQDMatte();
void createQDMatte();
+ MacShape *getShape();
+ uint32 getForeColor();
+ uint32 getBackColor();
Frame *_frame;
Score *_score;
Commit: 8963cf211ac8d6cb2558899a2a4c48e168f4a1d1
https://github.com/scummvm/scummvm/commit/8963cf211ac8d6cb2558899a2a4c48e168f4a1d1
Author: Scott Percival (code at moral.net.au)
Date: 2021-10-12T01:08:34+08:00
Commit Message:
DIRECTOR: Move methods from Window to DirectorPlotData
Changed paths:
engines/director/director.h
engines/director/graphics.cpp
engines/director/window.cpp
engines/director/window.h
diff --git a/engines/director/director.h b/engines/director/director.h
index ee79766255..4f6a989a8e 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -126,6 +126,8 @@ struct MacShape {
Graphics::MacPlotData *pd;
};
+const int SCALE_THRESHOLD = 0x100;
+
// An extension of MacPlotData for interfacing with inks and patterns without
// needing extra surfaces.
struct DirectorPlotData {
@@ -148,7 +150,12 @@ struct DirectorPlotData {
uint32 foreColor;
bool applyColor;
- void setApplyColor(); // graphics.cpp
+ // graphics.cpp
+ void setApplyColor();
+ uint32 preprocessColor(uint32 src);
+ void inkBlitShape(Common::Rect &srcRect);
+ void inkBlitSurface(Common::Rect &srcRect, const Graphics::Surface *mask);
+ void inkBlitStretchSurface(Common::Rect &srcRect, const Graphics::Surface *mask);
DirectorPlotData(Graphics::MacWindowManager *w, SpriteType s, InkType i, int a, uint32 b, uint32 f) : _wm(w), sprite(s), ink(i), alpha(a), backColor(b), foreColor(f) {
srf = nullptr;
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index 099873c6dc..9b0df3f0c9 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -300,4 +300,184 @@ void DirectorPlotData::setApplyColor() {
}
}
+uint32 DirectorPlotData::preprocessColor(uint32 src) {
+ // HACK: Right now this method is just used for adjusting the colourization on text
+ // sprites, as it would be costly to colourize the chunks on the fly each
+ // time a section needs drawing. It's ugly but mostly works.
+ if (sprite == kTextSprite) {
+ switch(ink) {
+ case kInkTypeMask:
+ src = (src == backColor ? foreColor : 0xff);
+ break;
+ case kInkTypeReverse:
+ src = (src == foreColor ? 0 : colorWhite);
+ break;
+ case kInkTypeNotReverse:
+ src = (src == backColor ? colorWhite : 0);
+ break;
+ // looks like this part is wrong, maybe it's very same as reverse?
+ // check warlock/DATA/WARLOCKSHIP/ENG/ABOUT to see more detail.
+// case kInkTypeGhost:
+// src = (src == foreColor ? backColor : colorWhite);
+// break;
+ case kInkTypeNotGhost:
+ src = (src == backColor ? colorWhite : backColor);
+ break;
+ case kInkTypeNotCopy:
+ src = (src == foreColor ? backColor : foreColor);
+ break;
+ case kInkTypeNotTrans:
+ src = (src == foreColor ? backColor : colorWhite);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return src;
+}
+
+void DirectorPlotData::inkBlitShape(Common::Rect &srcRect) {
+ if (!ms)
+ return;
+
+ // Preprocess shape colours
+ switch (ink) {
+ case kInkTypeNotTrans:
+ case kInkTypeNotReverse:
+ case kInkTypeNotGhost:
+ return;
+ case kInkTypeReverse:
+ ms->foreColor = 0;
+ ms->backColor = 0;
+ break;
+ default:
+ break;
+ }
+
+ Common::Rect fillAreaRect((int)srcRect.width(), (int)srcRect.height());
+ fillAreaRect.moveTo(srcRect.left, srcRect.top);
+ Graphics::MacPlotData plotFill(dst, nullptr, &g_director->getPatterns(), ms->pattern, srcRect.left, srcRect.top, 1, ms->backColor);
+
+ Common::Rect strokeRect(MAX((int)srcRect.width() - ms->lineSize, 0), MAX((int)srcRect.height() - ms->lineSize, 0));
+ strokeRect.moveTo(srcRect.left, srcRect.top);
+ Graphics::MacPlotData plotStroke(dst, nullptr, &g_director->getPatterns(), 1, strokeRect.left, strokeRect.top, ms->lineSize, ms->backColor);
+
+ switch (ms->spriteType) {
+ case kRectangleSprite:
+ ms->pd = &plotFill;
+ Graphics::drawFilledRect(fillAreaRect, ms->foreColor, g_director->getInkDrawPixel(), this);
+ // fall through
+ case kOutlinedRectangleSprite:
+ // if we have lineSize <= 0, means we are not drawing anything. so we may return directly.
+ if (ms->lineSize <= 0)
+ break;
+ ms->pd = &plotStroke;
+ Graphics::drawRect(strokeRect, ms->foreColor, g_director->getInkDrawPixel(), this);
+ break;
+ case kRoundedRectangleSprite:
+ ms->pd = &plotFill;
+ Graphics::drawRoundRect(fillAreaRect, 12, ms->foreColor, true, g_director->getInkDrawPixel(), this);
+ // fall through
+ case kOutlinedRoundedRectangleSprite:
+ if (ms->lineSize <= 0)
+ break;
+ ms->pd = &plotStroke;
+ Graphics::drawRoundRect(strokeRect, 12, ms->foreColor, false, g_director->getInkDrawPixel(), this);
+ break;
+ case kOvalSprite:
+ ms->pd = &plotFill;
+ Graphics::drawEllipse(fillAreaRect.left, fillAreaRect.top, fillAreaRect.right, fillAreaRect.bottom, ms->foreColor, true, g_director->getInkDrawPixel(), this);
+ // fall through
+ case kOutlinedOvalSprite:
+ if (ms->lineSize <= 0)
+ break;
+ ms->pd = &plotStroke;
+ Graphics::drawEllipse(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, ms->foreColor, false, g_director->getInkDrawPixel(), this);
+ break;
+ case kLineTopBottomSprite:
+ ms->pd = &plotStroke;
+ Graphics::drawLine(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, ms->foreColor, g_director->getInkDrawPixel(), this);
+ break;
+ case kLineBottomTopSprite:
+ ms->pd = &plotStroke;
+ Graphics::drawLine(strokeRect.left, strokeRect.bottom, strokeRect.right, strokeRect.top, ms->foreColor, g_director->getInkDrawPixel(), this);
+ break;
+ default:
+ warning("DirectorPlotData::inkBlitShape: Expected shape type but got type %d", ms->spriteType);
+ }
+}
+
+void DirectorPlotData::inkBlitSurface(Common::Rect &srcRect, const Graphics::Surface *mask) {
+ if (!srf)
+ return;
+
+ // TODO: Determine why colourization causes problems in Warlock
+ if (sprite == kTextSprite)
+ applyColor = false;
+
+ srcPoint.y = abs(srcRect.top - destRect.top);
+ for (int i = 0; i < destRect.height(); i++, srcPoint.y++) {
+ if (_wm->_pixelformat.bytesPerPixel == 1) {
+ srcPoint.x = abs(srcRect.left - destRect.left);
+ const byte *msk = mask ? (const byte *)mask->getBasePtr(srcPoint.x, srcPoint.y) : nullptr;
+
+ for (int j = 0; j < destRect.width(); j++, srcPoint.x++) {
+ if (!mask || (msk && !(*msk++))) {
+ (g_director->getInkDrawPixel())(destRect.left + j, destRect.top + i,
+ preprocessColor(*((byte *)srf->getBasePtr(srcPoint.x, srcPoint.y))), this);
+ }
+ }
+ } else {
+ srcPoint.x = abs(srcRect.left - destRect.left);
+ const uint32 *msk = mask ? (const uint32 *)mask->getBasePtr(srcPoint.x, srcPoint.y) : nullptr;
+
+ for (int j = 0; j < destRect.width(); j++, srcPoint.x++) {
+ if (!mask || (msk && !(*msk++))) {
+ (g_director->getInkDrawPixel())(destRect.left + j, destRect.top + i,
+ preprocessColor(*((int *)srf->getBasePtr(srcPoint.x, srcPoint.y))), this);
+ }
+ }
+ }
+ }
+}
+
+void DirectorPlotData::inkBlitStretchSurface(Common::Rect &srcRect, const Graphics::Surface *mask) {
+ if (!srf)
+ return;
+
+ // TODO: Determine why colourization causes problems in Warlock
+ if (sprite == kTextSprite)
+ applyColor = false;
+
+ int scaleX = SCALE_THRESHOLD * srcRect.width() / destRect.width();
+ int scaleY = SCALE_THRESHOLD * srcRect.height() / destRect.height();
+
+ srcPoint.y = abs(srcRect.top - destRect.top);
+
+ for (int i = 0, scaleYCtr = 0; i < destRect.height(); i++, scaleYCtr += scaleY, srcPoint.y++) {
+ if (_wm->_pixelformat.bytesPerPixel == 1) {
+ srcPoint.x = abs(srcRect.left - destRect.left);
+ const byte *msk = mask ? (const byte *)mask->getBasePtr(srcPoint.x, srcPoint.y) : nullptr;
+
+ for (int xCtr = 0, scaleXCtr = 0; xCtr < destRect.width(); xCtr++, scaleXCtr += scaleX, srcPoint.x++) {
+ if (!mask || !(*msk++)) {
+ (g_director->getInkDrawPixel())(destRect.left + xCtr, destRect.top + i,
+ preprocessColor(*((byte *)srf->getBasePtr(scaleXCtr / SCALE_THRESHOLD, scaleYCtr / SCALE_THRESHOLD))), this);
+ }
+ }
+ } else {
+ srcPoint.x = abs(srcRect.left - destRect.left);
+ const uint32 *msk = mask ? (const uint32 *)mask->getBasePtr(srcPoint.x, srcPoint.y) : nullptr;
+
+ for (int xCtr = 0, scaleXCtr = 0; xCtr < destRect.width(); xCtr++, scaleXCtr += scaleX, srcPoint.x++) {
+ if (!mask || !(*msk++)) {
+ (g_director->getInkDrawPixel())(destRect.left + xCtr, destRect.top + i,
+ preprocessColor(*((int *)srf->getBasePtr(scaleXCtr / SCALE_THRESHOLD, scaleYCtr / SCALE_THRESHOLD))), this);
+ }
+ }
+ }
+ }
+}
+
} // End of namespace Director
diff --git a/engines/director/window.cpp b/engines/director/window.cpp
index 0bdcc0784f..3e50e30ada 100644
--- a/engines/director/window.cpp
+++ b/engines/director/window.cpp
@@ -198,13 +198,13 @@ void Window::inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::Mana
pd.dst = blitTo;
if (pd.ms) {
- inkBlitShape(&pd, srcRect);
+ pd.inkBlitShape(srcRect);
} else if (pd.srf) {
if (channel->isStretched()) {
srcRect = channel->getBbox(true);
- inkBlitStretchSurface(&pd, srcRect, channel->getMask());
+ pd.inkBlitStretchSurface(srcRect, channel->getMask());
} else {
- inkBlitSurface(&pd, srcRect, channel->getMask());
+ pd.inkBlitSurface(srcRect, channel->getMask());
}
} else {
if (debugChannelSet(kDebugImages, 2))
@@ -212,186 +212,6 @@ void Window::inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::Mana
}
}
-void Window::inkBlitShape(DirectorPlotData *pd, Common::Rect &srcRect) {
- if (!pd->ms)
- return;
-
- // Preprocess shape colours
- switch (pd->ink) {
- case kInkTypeNotTrans:
- case kInkTypeNotReverse:
- case kInkTypeNotGhost:
- return;
- case kInkTypeReverse:
- pd->ms->foreColor = 0;
- pd->ms->backColor = 0;
- break;
- default:
- break;
- }
-
- Common::Rect fillAreaRect((int)srcRect.width(), (int)srcRect.height());
- fillAreaRect.moveTo(srcRect.left, srcRect.top);
- Graphics::MacPlotData plotFill(pd->dst, nullptr, &g_director->getPatterns(), pd->ms->pattern, srcRect.left, srcRect.top, 1, pd->ms->backColor);
-
- Common::Rect strokeRect(MAX((int)srcRect.width() - pd->ms->lineSize, 0), MAX((int)srcRect.height() - pd->ms->lineSize, 0));
- strokeRect.moveTo(srcRect.left, srcRect.top);
- Graphics::MacPlotData plotStroke(pd->dst, nullptr, &g_director->getPatterns(), 1, strokeRect.left, strokeRect.top, pd->ms->lineSize, pd->ms->backColor);
-
- switch (pd->ms->spriteType) {
- case kRectangleSprite:
- pd->ms->pd = &plotFill;
- Graphics::drawFilledRect(fillAreaRect, pd->ms->foreColor, g_director->getInkDrawPixel(), pd);
- // fall through
- case kOutlinedRectangleSprite:
- // if we have lineSize <= 0, means we are not drawing anything. so we may return directly.
- if (pd->ms->lineSize <= 0)
- break;
- pd->ms->pd = &plotStroke;
- Graphics::drawRect(strokeRect, pd->ms->foreColor, g_director->getInkDrawPixel(), pd);
- break;
- case kRoundedRectangleSprite:
- pd->ms->pd = &plotFill;
- Graphics::drawRoundRect(fillAreaRect, 12, pd->ms->foreColor, true, g_director->getInkDrawPixel(), pd);
- // fall through
- case kOutlinedRoundedRectangleSprite:
- if (pd->ms->lineSize <= 0)
- break;
- pd->ms->pd = &plotStroke;
- Graphics::drawRoundRect(strokeRect, 12, pd->ms->foreColor, false, g_director->getInkDrawPixel(), pd);
- break;
- case kOvalSprite:
- pd->ms->pd = &plotFill;
- Graphics::drawEllipse(fillAreaRect.left, fillAreaRect.top, fillAreaRect.right, fillAreaRect.bottom, pd->ms->foreColor, true, g_director->getInkDrawPixel(), pd);
- // fall through
- case kOutlinedOvalSprite:
- if (pd->ms->lineSize <= 0)
- break;
- pd->ms->pd = &plotStroke;
- Graphics::drawEllipse(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, pd->ms->foreColor, false, g_director->getInkDrawPixel(), pd);
- break;
- case kLineTopBottomSprite:
- pd->ms->pd = &plotStroke;
- Graphics::drawLine(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, pd->ms->foreColor, g_director->getInkDrawPixel(), pd);
- break;
- case kLineBottomTopSprite:
- pd->ms->pd = &plotStroke;
- Graphics::drawLine(strokeRect.left, strokeRect.bottom, strokeRect.right, strokeRect.top, pd->ms->foreColor, g_director->getInkDrawPixel(), pd);
- break;
- default:
- warning("Window::inkBlitFrom: Expected shape type but got type %d", pd->ms->spriteType);
- }
-}
-
-void Window::inkBlitSurface(DirectorPlotData *pd, Common::Rect &srcRect, const Graphics::Surface *mask) {
- if (!pd->srf)
- return;
-
- // TODO: Determine why colourization causes problems in Warlock
- if (pd->sprite == kTextSprite)
- pd->applyColor = false;
-
- pd->srcPoint.y = abs(srcRect.top - pd->destRect.top);
- for (int i = 0; i < pd->destRect.height(); i++, pd->srcPoint.y++) {
- if (_wm->_pixelformat.bytesPerPixel == 1) {
- pd->srcPoint.x = abs(srcRect.left - pd->destRect.left);
- const byte *msk = mask ? (const byte *)mask->getBasePtr(pd->srcPoint.x, pd->srcPoint.y) : nullptr;
-
- for (int j = 0; j < pd->destRect.width(); j++, pd->srcPoint.x++) {
- if (!mask || (msk && !(*msk++))) {
- (g_director->getInkDrawPixel())(pd->destRect.left + j, pd->destRect.top + i,
- preprocessColor(pd, *((byte *)pd->srf->getBasePtr(pd->srcPoint.x, pd->srcPoint.y))), pd);
- }
- }
- } else {
- pd->srcPoint.x = abs(srcRect.left - pd->destRect.left);
- const uint32 *msk = mask ? (const uint32 *)mask->getBasePtr(pd->srcPoint.x, pd->srcPoint.y) : nullptr;
-
- for (int j = 0; j < pd->destRect.width(); j++, pd->srcPoint.x++) {
- if (!mask || (msk && !(*msk++))) {
- (g_director->getInkDrawPixel())(pd->destRect.left + j, pd->destRect.top + i,
- preprocessColor(pd, *((int *)pd->srf->getBasePtr(pd->srcPoint.x, pd->srcPoint.y))), pd);
- }
- }
- }
- }
-}
-
-void Window::inkBlitStretchSurface(DirectorPlotData *pd, Common::Rect &srcRect, const Graphics::Surface *mask) {
- if (!pd->srf)
- return;
-
- // TODO: Determine why colourization causes problems in Warlock
- if (pd->sprite == kTextSprite)
- pd->applyColor = false;
-
- int scaleX = SCALE_THRESHOLD * srcRect.width() / pd->destRect.width();
- int scaleY = SCALE_THRESHOLD * srcRect.height() / pd->destRect.height();
-
- pd->srcPoint.y = abs(srcRect.top - pd->destRect.top);
-
- for (int i = 0, scaleYCtr = 0; i < pd->destRect.height(); i++, scaleYCtr += scaleY, pd->srcPoint.y++) {
- if (_wm->_pixelformat.bytesPerPixel == 1) {
- pd->srcPoint.x = abs(srcRect.left - pd->destRect.left);
- const byte *msk = mask ? (const byte *)mask->getBasePtr(pd->srcPoint.x, pd->srcPoint.y) : nullptr;
-
- for (int xCtr = 0, scaleXCtr = 0; xCtr < pd->destRect.width(); xCtr++, scaleXCtr += scaleX, pd->srcPoint.x++) {
- if (!mask || !(*msk++)) {
- (g_director->getInkDrawPixel())(pd->destRect.left + xCtr, pd->destRect.top + i,
- preprocessColor(pd, *((byte *)pd->srf->getBasePtr(scaleXCtr / SCALE_THRESHOLD, scaleYCtr / SCALE_THRESHOLD))), pd);
- }
- }
- } else {
- pd->srcPoint.x = abs(srcRect.left - pd->destRect.left);
- const uint32 *msk = mask ? (const uint32 *)mask->getBasePtr(pd->srcPoint.x, pd->srcPoint.y) : nullptr;
-
- for (int xCtr = 0, scaleXCtr = 0; xCtr < pd->destRect.width(); xCtr++, scaleXCtr += scaleX, pd->srcPoint.x++) {
- if (!mask || !(*msk++)) {
- (g_director->getInkDrawPixel())(pd->destRect.left + xCtr, pd->destRect.top + i,
- preprocessColor(pd, *((int *)pd->srf->getBasePtr(scaleXCtr / SCALE_THRESHOLD, scaleYCtr / SCALE_THRESHOLD))), pd);
- }
- }
- }
- }
-}
-
-int Window::preprocessColor(DirectorPlotData *p, uint32 src) {
- // HACK: Right now this method is just used for adjusting the colourization on text
- // sprites, as it would be costly to colourize the chunks on the fly each
- // time a section needs drawing. It's ugly but mostly works.
- if (p->sprite == kTextSprite) {
- switch(p->ink) {
- case kInkTypeMask:
- src = (src == p->backColor ? p->foreColor : 0xff);
- break;
- case kInkTypeReverse:
- src = (src == p->foreColor ? 0 : p->colorWhite);
- break;
- case kInkTypeNotReverse:
- src = (src == p->backColor ? p->colorWhite : 0);
- break;
- // looks like this part is wrong, maybe it's very same as reverse?
- // check warlock/DATA/WARLOCKSHIP/ENG/ABOUT to see more detail.
-// case kInkTypeGhost:
-// src = (src == p->foreColor ? p->backColor : p->colorWhite);
-// break;
- case kInkTypeNotGhost:
- src = (src == p->backColor ? p->colorWhite : p->backColor);
- break;
- case kInkTypeNotCopy:
- src = (src == p->foreColor ? p->backColor : p->foreColor);
- break;
- case kInkTypeNotTrans:
- src = (src == p->foreColor ? p->backColor : p->colorWhite);
- break;
- default:
- break;
- }
- }
-
- return src;
-}
-
Common::Point Window::getMousePos() {
return g_system->getEventManager()->getMousePos() - Common::Point(_innerDims.left, _innerDims.top);
}
diff --git a/engines/director/window.h b/engines/director/window.h
index 4baaba0092..dc4003949b 100644
--- a/engines/director/window.h
+++ b/engines/director/window.h
@@ -38,8 +38,6 @@ class MacWindowManager;
namespace Director {
-const int SCALE_THRESHOLD = 0x100;
-
class Channel;
class MacArchive;
struct MacShape;
@@ -201,13 +199,9 @@ private:
bool _titleVisible;
private:
- int preprocessColor(DirectorPlotData *p, uint32 src);
void inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::ManagedSurface *blitTo = nullptr);
- void inkBlitShape(DirectorPlotData *pd, Common::Rect &srcRect);
- void inkBlitSurface(DirectorPlotData *pd, Common::Rect &srcRect, const Graphics::Surface *mask);
- void inkBlitStretchSurface(DirectorPlotData *pd, Common::Rect &srcRect, const Graphics::Surface *mask);
};
} // End of namespace Director
Commit: 257fd958e724fddcc72bc9904477f8f092fee3c4
https://github.com/scummvm/scummvm/commit/257fd958e724fddcc72bc9904477f8f092fee3c4
Author: Scott Percival (code at moral.net.au)
Date: 2021-10-12T01:08:34+08:00
Commit Message:
DIRECTOR: Add blitting code to FilmLoopCastMember
Changed paths:
engines/director/castmember.cpp
engines/director/graphics.cpp
diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp
index 683bea1876..1daf876b4e 100644
--- a/engines/director/castmember.cpp
+++ b/engines/director/castmember.cpp
@@ -577,7 +577,10 @@ bool FilmLoopCastMember::isModified() {
}
Graphics::MacWidget *FilmLoopCastMember::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);
+ Common::Rect widgetRect(bbox.width() ? bbox.width() : _bbox.width(), bbox.height() ? bbox.height() : _bbox.height());
+ channel->_width = widgetRect.width();
+ channel->_height = widgetRect.height();
+ Graphics::MacWidget *widget = new Graphics::MacWidget(g_director->getCurrentWindow(), bbox.left, bbox.top, widgetRect.width(), widgetRect.height(), g_director->_wm, false);
if (channel->_filmLoopFrame >= _frames.size()) {
warning("Film loop frame %d requested, only %d available", channel->_filmLoopFrame, _frames.size());
@@ -594,17 +597,38 @@ Graphics::MacWidget *FilmLoopCastMember::createWidget(Common::Rect &bbox, Channe
// render the sprites in order onto the widget surface
for (Common::Array<int>::iterator iter = spriteIds.begin(); iter != spriteIds.end(); ++iter) {
Sprite src = _frames[channel->_filmLoopFrame].sprites[*iter];
- if (src._castId.member == 0)
+ if (!src._cast)
continue;
// translate sprite relative to the global bounding box
- int16 x = (src._startPoint.x - _bbox.left) * bbox.width() / _bbox.width() + bbox.left;
- int16 y = (src._startPoint.y - _bbox.top) * bbox.height() / _bbox.height() + bbox.top;
- int16 width = src._width * bbox.width() / _bbox.width();
- int16 height = src._height * bbox.height() / _bbox.height();
- Common::Rect srcBbox(x, y, x + width, y + height);
- //Graphics::MacWidget *srcWidget = src._cast->createWidget(srcBbox, channel, spriteType);
- //widget->getSurface()->blitFrom(*srcWidget->getSurface(), Common::Point(x, y));
- //delete srcWidget;
+ int16 relX = (src._startPoint.x - _bbox.left) * widgetRect.width() / _bbox.width();
+ int16 absX = relX + bbox.left;
+ int16 relY = (src._startPoint.y - _bbox.top) * widgetRect.height() / _bbox.height();
+ int16 absY = relY + bbox.top;
+ int16 width = src._width * widgetRect.width() / _bbox.width();
+ int16 height = src._height * widgetRect.height() / _bbox.height();
+ Common::Rect absBbox(absX, absY, absX + width, absY + height);
+ Common::Rect relBbox(relX, relY, relX + width, relY + height);
+
+ Graphics::MacWidget *srcWidget = src._cast->createWidget(absBbox, channel, spriteType);
+ DirectorPlotData pd(g_director->_wm, src._spriteType, src._ink, src._blend, src.getBackColor(), src.getForeColor());
+ pd.colorWhite = pd._wm->_colorWhite;
+ pd.colorBlack = pd._wm->_colorBlack;
+ pd.dst = widget->getSurface();
+ pd.destRect = widgetRect;
+
+ pd.srf = srcWidget ? srcWidget->getSurface() : nullptr;
+ if (!pd.srf && src._spriteType != kBitmapSprite) {
+ // Shapes come colourized from macDrawPixel
+ pd.ms = src.getShape();
+ pd.applyColor = false;
+ pd.inkBlitShape(relBbox);
+ } else {
+ pd.setApplyColor();
+ // TODO: Support masks
+ pd.inkBlitSurface(relBbox, nullptr);
+ }
+ if (srcWidget)
+ delete srcWidget;
}
return widget;
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index 9b0df3f0c9..f62062fdbe 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -435,7 +435,7 @@ void DirectorPlotData::inkBlitSurface(Common::Rect &srcRect, const Graphics::Sur
for (int j = 0; j < destRect.width(); j++, srcPoint.x++) {
if (!mask || (msk && !(*msk++))) {
(g_director->getInkDrawPixel())(destRect.left + j, destRect.top + i,
- preprocessColor(*((int *)srf->getBasePtr(srcPoint.x, srcPoint.y))), this);
+ preprocessColor(*((uint32 *)srf->getBasePtr(srcPoint.x, srcPoint.y))), this);
}
}
}
Commit: 0e0254a5f78475beea0fc89e54ea921ad224080e
https://github.com/scummvm/scummvm/commit/0e0254a5f78475beea0fc89e54ea921ad224080e
Author: Scott Percival (code at moral.net.au)
Date: 2021-10-12T01:08:34+08:00
Commit Message:
DIRECTOR: Fix currentFrameRate loading for v4
Changed paths:
engines/director/cast.cpp
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 17ec4c5442..1117976b7a 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -223,12 +223,9 @@ bool Cast::loadConfig() {
_castArrayStart = stream->readUint16();
_castArrayEnd = stream->readUint16();
+
+ // v3 and below use this, override for v4 and over
byte currentFrameRate = stream->readByte();
- if (!_isShared) {
- _movie->getScore()->_currentFrameRate = currentFrameRate;
- if (_movie->getScore()->_currentFrameRate == 0)
- _movie->getScore()->_currentFrameRate = 20;
- }
byte lightswitch = stream->readByte();
uint16 unk1 = stream->readUint16();
@@ -246,8 +243,8 @@ bool Cast::loadConfig() {
// uint16 stageColorG = stream.readUint16();
// uint16 stageColorB = stream.readUint16();
- debugC(1, kDebugLoading, "Cast::loadConfig(): len: %d, fileVersion: %d, framerate: %d, light: %d, unk: %d, font: %d, size: %d"
- ", style: %d", len, fileVersion, currentFrameRate, lightswitch, unk1, commentFont, commentSize, commentStyle);
+ debugC(1, kDebugLoading, "Cast::loadConfig(): len: %d, fileVersion: %d, light: %d, unk: %d, font: %d, size: %d"
+ ", style: %d", len, fileVersion, lightswitch, unk1, commentFont, commentSize, commentStyle);
debugC(1, kDebugLoading, "Cast::loadConfig(): stagecolor: %d, depth: %d",
_stageColor, bitdepth);
if (debugChannelSet(1, kDebugLoading))
@@ -269,9 +266,10 @@ bool Cast::loadConfig() {
}
if (_version >= kFileVer400) {
- for (int i = 0; i < 0x08; i++) {
+ for (int i = 0; i < 0x07; i++) {
stream->readByte();
}
+ currentFrameRate = stream->readByte();
_platform = platformFromID(stream->readUint16());
for (int i = 0; i < 0x0c; i++) {
stream->readByte();
@@ -283,6 +281,13 @@ bool Cast::loadConfig() {
debugC(1, kDebugLoading, "Cast::loadConfig(): platform: %s, defaultPalette: %d", getPlatformAbbrev(_platform), _defaultPalette);
}
+ if (!_isShared) {
+ debugC(1, kDebugLoading, "Cast::loadConfig(): currentFrameRate: %d", currentFrameRate);
+ _movie->getScore()->_currentFrameRate = currentFrameRate;
+ if (_movie->getScore()->_currentFrameRate == 0)
+ _movie->getScore()->_currentFrameRate = 20;
+ }
+
uint16 humanVer = humanVersion(_version);
if (humanVer > _vm->getVersion()) {
if (_vm->getVersion() > 0)
Commit: 8b240f69b8aa6605e67fca5a9e4bb93a5e73c0f0
https://github.com/scummvm/scummvm/commit/8b240f69b8aa6605e67fca5a9e4bb93a5e73c0f0
Author: Scott Percival (code at moral.net.au)
Date: 2021-10-12T01:08:34+08:00
Commit Message:
DIRECTOR: Fix inkBlitShape to use destRect for drawing
Changed paths:
engines/director/castmember.cpp
engines/director/director.h
engines/director/graphics.cpp
engines/director/window.cpp
diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp
index 1daf876b4e..cc9211bca7 100644
--- a/engines/director/castmember.cpp
+++ b/engines/director/castmember.cpp
@@ -601,31 +601,29 @@ Graphics::MacWidget *FilmLoopCastMember::createWidget(Common::Rect &bbox, Channe
continue;
// translate sprite relative to the global bounding box
int16 relX = (src._startPoint.x - _bbox.left) * widgetRect.width() / _bbox.width();
- int16 absX = relX + bbox.left;
int16 relY = (src._startPoint.y - _bbox.top) * widgetRect.height() / _bbox.height();
- int16 absY = relY + bbox.top;
int16 width = src._width * widgetRect.width() / _bbox.width();
int16 height = src._height * widgetRect.height() / _bbox.height();
- Common::Rect absBbox(absX, absY, absX + width, absY + height);
Common::Rect relBbox(relX, relY, relX + width, relY + height);
- Graphics::MacWidget *srcWidget = src._cast->createWidget(absBbox, channel, spriteType);
+ Graphics::MacWidget *srcWidget = src._cast->createWidget(relBbox, channel, spriteType);
DirectorPlotData pd(g_director->_wm, src._spriteType, src._ink, src._blend, src.getBackColor(), src.getForeColor());
pd.colorWhite = pd._wm->_colorWhite;
pd.colorBlack = pd._wm->_colorBlack;
pd.dst = widget->getSurface();
- pd.destRect = widgetRect;
+ pd.destRect = relBbox;
pd.srf = srcWidget ? srcWidget->getSurface() : nullptr;
+ Common::Rect srcWidgetBbox(width, height);
if (!pd.srf && src._spriteType != kBitmapSprite) {
// Shapes come colourized from macDrawPixel
pd.ms = src.getShape();
pd.applyColor = false;
- pd.inkBlitShape(relBbox);
+ pd.inkBlitShape();
} else {
pd.setApplyColor();
// TODO: Support masks
- pd.inkBlitSurface(relBbox, nullptr);
+ pd.inkBlitStretchSurface(srcWidgetBbox, nullptr);
}
if (srcWidget)
delete srcWidget;
diff --git a/engines/director/director.h b/engines/director/director.h
index 4f6a989a8e..f28281de08 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -153,7 +153,7 @@ struct DirectorPlotData {
// graphics.cpp
void setApplyColor();
uint32 preprocessColor(uint32 src);
- void inkBlitShape(Common::Rect &srcRect);
+ void inkBlitShape();
void inkBlitSurface(Common::Rect &srcRect, const Graphics::Surface *mask);
void inkBlitStretchSurface(Common::Rect &srcRect, const Graphics::Surface *mask);
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index f62062fdbe..36fdb1f59f 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -337,7 +337,7 @@ uint32 DirectorPlotData::preprocessColor(uint32 src) {
return src;
}
-void DirectorPlotData::inkBlitShape(Common::Rect &srcRect) {
+void DirectorPlotData::inkBlitShape() {
if (!ms)
return;
@@ -355,12 +355,12 @@ void DirectorPlotData::inkBlitShape(Common::Rect &srcRect) {
break;
}
- Common::Rect fillAreaRect((int)srcRect.width(), (int)srcRect.height());
- fillAreaRect.moveTo(srcRect.left, srcRect.top);
- Graphics::MacPlotData plotFill(dst, nullptr, &g_director->getPatterns(), ms->pattern, srcRect.left, srcRect.top, 1, ms->backColor);
+ Common::Rect fillAreaRect((int)destRect.width(), (int)destRect.height());
+ fillAreaRect.moveTo(destRect.left, destRect.top);
+ Graphics::MacPlotData plotFill(dst, nullptr, &g_director->getPatterns(), ms->pattern, destRect.left, destRect.top, 1, ms->backColor);
- Common::Rect strokeRect(MAX((int)srcRect.width() - ms->lineSize, 0), MAX((int)srcRect.height() - ms->lineSize, 0));
- strokeRect.moveTo(srcRect.left, srcRect.top);
+ Common::Rect strokeRect(MAX((int)destRect.width() - ms->lineSize, 0), MAX((int)destRect.height() - ms->lineSize, 0));
+ strokeRect.moveTo(destRect.left, destRect.top);
Graphics::MacPlotData plotStroke(dst, nullptr, &g_director->getPatterns(), 1, strokeRect.left, strokeRect.top, ms->lineSize, ms->backColor);
switch (ms->spriteType) {
diff --git a/engines/director/window.cpp b/engines/director/window.cpp
index 3e50e30ada..3c147fffd8 100644
--- a/engines/director/window.cpp
+++ b/engines/director/window.cpp
@@ -198,7 +198,7 @@ void Window::inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::Mana
pd.dst = blitTo;
if (pd.ms) {
- pd.inkBlitShape(srcRect);
+ pd.inkBlitShape();
} else if (pd.srf) {
if (channel->isStretched()) {
srcRect = channel->getBbox(true);
Commit: 47c5b37067ebd53ccda509e077774afd893f649e
https://github.com/scummvm/scummvm/commit/47c5b37067ebd53ccda509e077774afd893f649e
Author: Scott Percival (code at moral.net.au)
Date: 2021-10-12T01:08:34+08:00
Commit Message:
DIRECTOR: Fix use-after-free in Sprite
Changed paths:
engines/director/sprite.cpp
engines/director/sprite.h
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 4dda654a18..f388d0cfda 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -90,8 +90,8 @@ Sprite::Sprite(const Sprite &sprite) {
_ink = sprite._ink;
_trails = sprite._trails;
- _matte = sprite._matte;
_cast = sprite._cast;
+ _matte = nullptr;
_thickness = sprite._thickness;
_startPoint = sprite._startPoint;
@@ -111,7 +111,8 @@ Sprite::Sprite(const Sprite &sprite) {
}
Sprite::~Sprite() {
- delete _matte;
+ if (_matte)
+ delete _matte;
}
bool Sprite::isQDShape() {
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
index 86b2e15dde..dc3754f854 100644
--- a/engines/director/sprite.h
+++ b/engines/director/sprite.h
@@ -61,6 +61,7 @@ class Sprite {
public:
Sprite(Frame *frame = nullptr);
Sprite(const Sprite &sprite);
+ Sprite& operator=(const Sprite &sprite) = default;
~Sprite();
Frame *getFrame() const { return _frame; }
Commit: 68518fc8a9b04ccfff5822d99b28615d30762a22
https://github.com/scummvm/scummvm/commit/68518fc8a9b04ccfff5822d99b28615d30762a22
Author: Scott Percival (code at moral.net.au)
Date: 2021-10-12T01:08:34+08:00
Commit Message:
DIRECTOR: Fix default palette index
Changed paths:
engines/director/cast.cpp
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 1117976b7a..87ccc10b52 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -274,7 +274,13 @@ bool Cast::loadConfig() {
for (int i = 0; i < 0x0c; i++) {
stream->readByte();
}
- _defaultPalette = (int16)stream->readUint16();
+ _defaultPalette = stream->readSint16();
+ // In this header value, the first builtin palette starts at 0 and
+ // continues down into negative numbers.
+ // For frames, 0 is used to represent an absence of a palette change,
+ // with the builtin palettes starting from -1.
+ if (_defaultPalette <= 0)
+ _defaultPalette -= 1;
for (int i = 0; i < 0x08; i++) {
stream->readByte();
}
More information about the Scummvm-git-logs
mailing list