[Scummvm-git-logs] scummvm master -> 0e9fd00720930813a6389322ac69ebdb8f456766

djsrv dservilla at gmail.com
Thu Jul 1 02:32:31 UTC 2021


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

Summary:
2d5ca7a1d6 DIRECTOR: Remove getCastMemberByScriptId from Movie
1724a158c6 DIRECTOR: Create CastMemberID type
615995fdc1 DIRECTOR: Change member refs to use CastMemberID
8bbd6da3a4 DIRECTOR: LINGO: Remove unbalanced 'end if' patches
8dfa5f4e73 DIRECTOR: LINGO: Use member ID as script ID in D2-3
b27696e49c DIRECTOR: LINGO: Fix movie script IDs in patcher
7bfa8aa6dc DIRECTOR: Add castLibID to Cast
0e9fd00720 DIRECTOR: LINGO: Take castLib into account in patcher


Commit: 2d5ca7a1d649ca17d1bf61c10f043a1cda09812f
    https://github.com/scummvm/scummvm/commit/2d5ca7a1d649ca17d1bf61c10f043a1cda09812f
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-30T22:32:19-04:00

Commit Message:
DIRECTOR: Remove getCastMemberByScriptId from Movie

This can be called on the correct cast directly.

Changed paths:
    engines/director/lingo/lingo-bytecode.cpp
    engines/director/movie.cpp
    engines/director/movie.h


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 5714d36348..a91e01b28a 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -965,14 +965,14 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
 	// initialise the script
 	ScriptType scriptType = kCastScript;
 	Common::String castName;
-	CastMember *member = g_director->getCurrentMovie()->getCastMemberByScriptId(scriptId);
+	CastMember *member = archive->cast->getCastMemberByScriptId(scriptId);
 	int castId;
 	if (member) {
 		if (member->_type == kCastLingoScript)
 			scriptType = ((ScriptCastMember *)member)->_scriptType;
 
 		castId = member->getID();
-		CastMemberInfo *info = g_director->getCurrentMovie()->getCastMemberInfo(castId);
+		CastMemberInfo *info = member->getInfo();
 		if (info)
 			castName = info->name;
 	} else {
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index f3648ccf2d..2516d6cc6b 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -312,14 +312,6 @@ CastMember *Movie::getCastMemberByName(const Common::String &name) {
 	return result;
 }
 
-CastMember *Movie::getCastMemberByScriptId(int scriptId) {
-	CastMember *result = _cast->getCastMemberByScriptId(scriptId);
-	if (result == nullptr && _sharedCast) {
-		result = _sharedCast->getCastMemberByScriptId(scriptId);
-	}
-	return result;
-}
-
 CastMemberInfo *Movie::getCastMemberInfo(int castId) {
 	CastMemberInfo *result = _cast->getCastMemberInfo(castId);
 	if (result == nullptr && _sharedCast) {
diff --git a/engines/director/movie.h b/engines/director/movie.h
index b1dbc6e93f..2e84544070 100644
--- a/engines/director/movie.h
+++ b/engines/director/movie.h
@@ -119,7 +119,6 @@ public:
 
 	CastMember *getCastMember(int castId);
 	CastMember *getCastMemberByName(const Common::String &name);
-	CastMember *getCastMemberByScriptId(int scriptId);
 	CastMemberInfo *getCastMemberInfo(int castId);
 	const Stxt *getStxt(int castId);
 


Commit: 1724a158c676ce68437822a25a6a4d3602421658
    https://github.com/scummvm/scummvm/commit/1724a158c676ce68437822a25a6a4d3602421658
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-30T22:32:19-04:00

Commit Message:
DIRECTOR: Create CastMemberID type

Changed paths:
    engines/director/lingo/lingo.cpp
    engines/director/lingo/lingo.h
    engines/director/types.h
    engines/director/util.cpp


diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 578ee12407..b3b6906e04 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1346,4 +1346,36 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
 	return result;
 }
 
+CastMemberID Lingo::resolveCastMember(const Datum &memberID, const Datum &castLib) {
+	Movie *movie = g_director->getCurrentMovie();
+	if (!movie) {
+		warning("Lingo::resolveCastMember: No movie");
+		return CastMemberID(-1, castLib.asInt());
+	}
+
+	switch (memberID.type) {
+	case STRING:
+		{
+			CastMember *member = movie->getCastMemberByName(memberID.asString(), castLib.asInt());
+			if (member)
+				return CastMemberID(member->getID(), castLib.asInt());
+
+			warning("Lingo::resolveCastMember: reference to non-existent cast member: %s", memberID.asString().c_str());
+			return CastMemberID(-1, castLib.asInt());
+		}
+		break;
+	case INT:
+	case FLOAT:
+		return CastMemberID(memberID.asInt(), castLib.asInt());
+		break;
+	case VOID:
+		warning("Lingo::resolveCastMember: reference to VOID member ID");
+		break;
+	default:
+		error("Lingo::resolveCastMember: unsupported member ID type %s", memberID.type2str());
+	}
+
+	return CastMemberID(-1, castLib.asInt());
+}
+
 } // End of namespace Director
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 01c1f203d8..036bd1d2fb 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -280,6 +280,7 @@ public:
 	void varAssign(const Datum &var, const Datum &value);
 	Datum varFetch(const Datum &var, bool silent = false);
 	Datum findVarV4(int varType, const Datum &id);
+	CastMemberID resolveCastMember(const Datum &memberID, const Datum &castLib);
 
 	int getAlignedType(const Datum &d1, const Datum &d2, bool numsOnly);
 
diff --git a/engines/director/types.h b/engines/director/types.h
index fa64f4c11b..ed2fcdd844 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -363,6 +363,24 @@ enum VarType {
 	kVarLocal
 };
 
+struct CastMemberID {
+	int member;
+	int castLib;
+
+	CastMemberID() : member(0), castLib(0) {}
+	CastMemberID(int memberID, int castLibID)
+		: member(memberID), castLib(castLibID) {}
+	
+	bool operator==(const CastMemberID &c) {
+		return member == c.member && castLib == c.castLib;
+	}
+	bool operator!=(const CastMemberID &c) {
+		return member != c.member || castLib != c.castLib;
+	}
+
+	const char *str() const;
+};
+
 struct Datum;
 struct PCell;
 typedef Common::Array<Datum> DatumArray;
diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index 30ac00238f..e6cf0d99e0 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -26,6 +26,7 @@
 #include "common/zlib.h"
 
 #include "director/director.h"
+#include "director/movie.h"
 #include "director/util.h"
 
 namespace Director {
@@ -200,6 +201,19 @@ char *numToCastNum(int num) {
 	return res;
 }
 
+const char *CastMemberID::str() const {
+	static char res[40];
+
+	if (g_director->getVersion() < 400 || g_director->getCurrentMovie()->_allowOutdatedLingo)
+		snprintf(res, 40, "member %d(%s)", member, numToCastNum(member));
+	else if (g_director->getVersion() < 500)
+		snprintf(res, 40, "member %d", member);
+	else
+		snprintf(res, 40, "member %d of castLib %d", member, castLib);
+
+	return res;
+}
+
 // This is table for built-in Macintosh font lowercasing.
 // '.' means that the symbol should be not changed, rest
 // of the symbols are stripping the diacritics


Commit: 615995fdc1c5f51ce9587659eaa618a108542305
    https://github.com/scummvm/scummvm/commit/615995fdc1c5f51ce9587659eaa618a108542305
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-30T22:32:19-04:00

Commit Message:
DIRECTOR: Change member refs to use CastMemberID

Changed paths:
    engines/director/channel.cpp
    engines/director/channel.h
    engines/director/cursor.cpp
    engines/director/cursor.h
    engines/director/frame.cpp
    engines/director/frame.h
    engines/director/lingo/lingo-builtins.cpp
    engines/director/lingo/lingo-bytecode.cpp
    engines/director/lingo/lingo-code.cpp
    engines/director/lingo/lingo-events.cpp
    engines/director/lingo/lingo-funcs.cpp
    engines/director/lingo/lingo-the.cpp
    engines/director/lingo/lingo.cpp
    engines/director/lingo/lingo.h
    engines/director/movie.cpp
    engines/director/movie.h
    engines/director/score.cpp
    engines/director/score.h
    engines/director/sound.cpp
    engines/director/sound.h
    engines/director/sprite.cpp
    engines/director/sprite.h
    engines/director/types.h
    engines/director/util.cpp
    engines/director/window.cpp


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 47d498d229..b07df4d75d 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -115,7 +115,8 @@ const Graphics::Surface *Channel::getMask(bool forceMatte) {
 			return nullptr;
 		}
 	} else if (_sprite->_ink == kInkTypeMask) {
-		CastMember *member = g_director->getCurrentMovie()->getCastMember(_sprite->_castId + 1);
+		CastMemberID maskID(_sprite->_castId.member + 1, _sprite->_castId.castLib);
+		CastMember *member = g_director->getCurrentMovie()->getCastMember(maskID);
 
 		if (member && member->_initialRect == _sprite->_cast->_initialRect) {
 			Common::Rect bbox(getBbox());
@@ -287,24 +288,24 @@ Common::Rect Channel::getBbox(bool unstretched) {
 	return result;
 }
 
-void Channel::setCast(uint16 castId) {
-	_sprite->setCast(castId);
+void Channel::setCast(CastMemberID memberID) {
+	_sprite->setCast(memberID);
 	_width = _sprite->_width;
 	_height = _sprite->_height;
-	replaceWidget(0);
+	replaceWidget();
 }
 
 void Channel::setClean(Sprite *nextSprite, int spriteId, bool partial) {
 	if (!nextSprite)
 		return;
 
-	uint16 previousCastId = 0;
+	CastMemberID previousCastId(0, 0);
 	bool replace = isDirty(nextSprite);
 
 	if (nextSprite) {
 		if (nextSprite->_cast && (_dirty || _sprite->_castId != nextSprite->_castId)) {
 			if (nextSprite->_cast->_type == kCastDigitalVideo) {
-				Common::String path = nextSprite->_cast->getCast()->getVideoPath(nextSprite->_castId);
+				Common::String path = nextSprite->_cast->getCast()->getVideoPath(nextSprite->_castId.member);
 
 				if (!path.empty()) {
 					((DigitalVideoCastMember *)nextSprite->_cast)->loadVideo(pathMakeRelative(path));
@@ -452,15 +453,15 @@ void Channel::setBbox(int l, int t, int r, int b) {
 // here is the place for deciding whether the widget can be keep or not
 // here's the definition, we first need to have widgets to keep, and the cast is not modified(modified means we need to re-create the widget)
 // and the castId should be same while castId should not be zero
-bool Channel::canKeepWidget(uint16 castId) {
-	if (_widget && _sprite && _sprite->_cast && !_sprite->_cast->isModified() && castId && castId == _sprite->_castId) {
+bool Channel::canKeepWidget(CastMemberID castId) {
+	if (_widget && _sprite && _sprite->_cast && !_sprite->_cast->isModified() && castId.member && castId == _sprite->_castId) {
 		return true;
 	}
 	return false;
 }
 
 bool Channel::canKeepWidget(Sprite *currentSprite, Sprite *nextSprite) {
-	if (_widget && currentSprite && currentSprite->_cast && nextSprite && nextSprite->_cast && !currentSprite->_cast->isModified() && currentSprite->_castId == nextSprite->_castId && currentSprite->_castId) {
+	if (_widget && currentSprite && currentSprite->_cast && nextSprite && nextSprite->_cast && !currentSprite->_cast->isModified() && currentSprite->_castId == nextSprite->_castId && currentSprite->_castId.member) {
 		return true;
 	}
 	return false;
@@ -468,10 +469,10 @@ bool Channel::canKeepWidget(Sprite *currentSprite, Sprite *nextSprite) {
 
 // currently, when we are setting hilite, we delete the widget and the re-create it
 // so we may optimize this if this operation takes much time
-void Channel::replaceWidget(uint16 previousCastId) {
+void Channel::replaceWidget(CastMemberID previousCastId) {
 	// if the castmember is the same, and we are not modifying anything which cannot be handle by channel. Then we don't replace the widget
 	if (canKeepWidget(previousCastId)) {
-		debug(5, "Channel::replaceWidget(): skip deleting %d %s", _sprite->_castId, numToCastNum(_sprite->_castId));
+		debug(5, "Channel::replaceWidget(): skip deleting %s", _sprite->_castId.asString().c_str());
 		return;
 	}
 
diff --git a/engines/director/channel.h b/engines/director/channel.h
index f03ff153e3..3e19c1c20c 100644
--- a/engines/director/channel.h
+++ b/engines/director/channel.h
@@ -58,18 +58,18 @@ public:
 	void setWidth(int w);
 	void setHeight(int h);
 	void setBbox(int l, int t, int r, int b);
-	void setCast(uint16 castId);
+	void setCast(CastMemberID memberID);
 	void setClean(Sprite *nextSprite, int spriteId, bool partial = false);
 	void setEditable(bool editable);
 	void replaceSprite(Sprite *nextSprite);
-	void replaceWidget(uint16 previousCastId = 0);
+	void replaceWidget(CastMemberID previousCastId = CastMemberID(0, 0));
 	bool updateWidget();
 	void updateTextCast();
 
 	void updateGlobalAttr();
 
 	void addDelta(Common::Point pos);
-	bool canKeepWidget(uint16 castId);
+	bool canKeepWidget(CastMemberID castId);
 	bool canKeepWidget(Sprite *currentSprite, Sprite *nextSprite);
 
 public:
diff --git a/engines/director/cursor.cpp b/engines/director/cursor.cpp
index b1fb01c099..68a4e677aa 100644
--- a/engines/director/cursor.cpp
+++ b/engines/director/cursor.cpp
@@ -34,8 +34,8 @@ Cursor::Cursor() {
 	_cursorResId = 0;
 	_cursorType = Graphics::kMacCursorArrow;
 
-	_cursorCastId = 0;
-	_cursorMaskId = 0;
+	_cursorCastId = CastMemberID(0, 0);
+	_cursorMaskId = CastMemberID(0, 0);
 
 	_usePalette = false;
 }
@@ -47,7 +47,7 @@ bool Cursor::operator==(const Cursor &c) {
 		_cursorMaskId == c._cursorMaskId;
 }
 
-void Cursor::readFromCast(uint cursorId, uint maskId) {
+void Cursor::readFromCast(CastMemberID cursorId, CastMemberID maskId) {
 	if (cursorId == _cursorCastId && maskId == _cursorMaskId)
 		return;
 
@@ -147,7 +147,7 @@ void Cursor::readFromResource(int resourceId) {
 	}
 }
 
-void Cursor::resetCursor(Graphics::MacCursorType type, bool shouldClear, int resId, uint castId, uint maskId) {
+void Cursor::resetCursor(Graphics::MacCursorType type, bool shouldClear, int resId, CastMemberID castId, CastMemberID maskId) {
 	if (shouldClear)
 		clear();
 
diff --git a/engines/director/cursor.h b/engines/director/cursor.h
index 57473d6052..119c2164b0 100644
--- a/engines/director/cursor.h
+++ b/engines/director/cursor.h
@@ -37,10 +37,10 @@ class Cursor : public Graphics::MacCursor {
  public:
 	Cursor();
 
-	void readFromCast(uint cursorId, uint maskId);
+	void readFromCast(CastMemberID cursorId, CastMemberID maskId);
 	void readFromResource(int resourceId);
 
-	bool isEmpty() { return !(_cursorResId || _cursorCastId); }
+	bool isEmpty() { return _cursorResId == 0 && _cursorCastId.member == 0; }
 	bool operator==(const Cursor &c);
 
 	virtual byte getKeyColor() const override { return _keyColor; }
@@ -50,11 +50,11 @@ class Cursor : public Graphics::MacCursor {
 	Graphics::MacCursorType _cursorType;
 	int _cursorResId;
 
-	uint _cursorCastId;
-	uint _cursorMaskId;
+	CastMemberID _cursorCastId;
+	CastMemberID _cursorMaskId;
 
 private:
-	void resetCursor(Graphics::MacCursorType type, bool shouldClear = false, int resId = 0, uint castId = 0, uint maskId = 0);
+	void resetCursor(Graphics::MacCursorType type, bool shouldClear = false, int resId = 0, CastMemberID castId = CastMemberID(0, 0), CastMemberID maskId = CastMemberID(0, 0));
 
 private:
 	bool _usePalette;
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index df4fac284f..af44beaa32 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -42,12 +42,12 @@ Frame::Frame(Score *score, int numChannels) {
 
 	_numChannels = numChannels;
 
-	_sound1 = 0;
-	_sound2 = 0;
+	_sound1 = CastMemberID(0, 0);
+	_sound2 = CastMemberID(0, 0);
 	_soundType1 = 0;
 	_soundType2 = 0;
 
-	_actionId = 0;
+	_actionId = CastMemberID(0, 0);
 	_skipFrameFlag = 0;
 	_blend = 0;
 
@@ -91,7 +91,7 @@ Frame::Frame(const Frame &frame) {
 
 	_score = frame._score;
 
-	debugC(1, kDebugLoading, "Frame. action: %d transType: %d transDuration: %d", _actionId, _transType, _transDuration);
+	debugC(1, kDebugLoading, "Frame. action: %s transType: %d transDuration: %d", _actionId.asString().c_str(), _transType, _transDuration);
 
 	_sprites.resize(_numChannels + 1);
 
@@ -131,7 +131,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 
 	if (version < kFileVer400) {
 		// Sound/Tempo/Transition
-		_actionId = stream->readByte();
+		_actionId = CastMemberID(stream->readByte(), 0);
 		_soundType1 = stream->readByte(); // type: 0x17 for sounds (sound is cast id), 0x16 for MIDI (sound is cmd id)
 		uint8 transFlags = stream->readByte(); // 0x80 is whole stage (vs changed area), rest is duration in 1/4ths of a second
 
@@ -144,10 +144,10 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 		_transChunkSize = stream->readByte();
 		_tempo = stream->readByte();
 		_transType = static_cast<TransitionType>(stream->readByte());
-		_sound1 = stream->readUint16();
+		_sound1 = CastMemberID(stream->readUint16(), 0);
 
 		if (_vm->getPlatform() == Common::kPlatformMacintosh) {
-			_sound2 = stream->readUint16();
+			_sound2 = CastMemberID(stream->readUint16(), 0);
 			_soundType2 = stream->readByte();
 		} else {
 			stream->read(unk, 3);
@@ -158,7 +158,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 		_blend = stream->readByte();
 
 		if (_vm->getPlatform() != Common::kPlatformMacintosh) {
-			_sound2 = stream->readUint16();
+			_sound2 = CastMemberID(stream->readUint16(), 0);
 			_soundType2 = stream->readByte();
 		}
 
@@ -188,7 +188,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 			stream->read(unk, 4);
 		}
 
-		debugC(8, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1, _skipFrameFlag, _blend, _sound2, _soundType2);
+		debugC(8, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId.member, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1.member, _skipFrameFlag, _blend, _sound2.member, _soundType2);
 
 		if (_vm->getPlatform() == Common::kPlatformMacintosh)
 			stream->read(unk, 3);
@@ -210,9 +210,9 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 		_transChunkSize = stream->readByte();
 		_tempo = stream->readByte();
 		_transType = static_cast<TransitionType>(stream->readByte());
-		_sound1 = stream->readUint16();
+		_sound1 = CastMemberID(stream->readUint16(), 0);
 
-		_sound2 = stream->readUint16();
+		_sound2 = CastMemberID(stream->readUint16(), 0);
 		_soundType2 = stream->readByte();
 
 		_skipFrameFlag = stream->readByte();
@@ -222,7 +222,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 		_colorSound1 = stream->readByte();
 		_colorSound2 = stream->readByte();
 
-		_actionId = stream->readUint16();
+		_actionId = CastMemberID(stream->readUint16(), 0);
 
 		_colorScript = stream->readByte();
 		_colorTrans = stream->readByte();
@@ -247,7 +247,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 
 		stream->readByte();
 
-		debugC(8, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1, _skipFrameFlag, _blend, _sound2, _soundType2);
+		debugC(8, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId.member, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1.member, _skipFrameFlag, _blend, _sound2.member, _soundType2);
 	} else if (version >= kFileVer500 && version < kFileVer600) {
 		// Sound/Tempo/Transition channel
 		stream->read(unk, 24);
@@ -269,7 +269,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 		Sprite &sprite = *_sprites[i + 1];
 
 		if (version < kFileVer500) {
-			sprite._scriptId = stream->readByte();
+			sprite._scriptId = CastMemberID(stream->readByte(), 0);
 			sprite._spriteType = (SpriteType)stream->readByte();
 			sprite._enabled = sprite._spriteType != kInactiveSprite;
 			if (version >= kFileVer400) {
@@ -287,7 +287,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 			if (sprite.isQDShape()) {
 				sprite._pattern = stream->readUint16();
 			} else {
-				sprite._castId = stream->readUint16();
+				sprite._castId = CastMemberID(stream->readUint16(), 0);
 			}
 
 			sprite._startPoint.y = (int16)stream->readUint16();
@@ -297,7 +297,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 			sprite._width = (int16)stream->readUint16();
 
 			if (version >= kFileVer400) {
-				sprite._scriptId = stream->readUint16();
+				sprite._scriptId = CastMemberID(stream->readUint16(), 0);
 				// & 0x0f scorecolor
 				// 0x10 forecolor is rgb
 				// 0x20 bgcolor is rgb
@@ -310,11 +310,13 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 			sprite._spriteType = (SpriteType)stream->readByte();
 			sprite._inkData = stream->readByte();
 
-			sprite._castIndex = stream->readUint16();
-			sprite._castId = stream->readUint16();
+			uint16 castLib = stream->readUint16();
+			uint16 memberID = stream->readUint16();
+			sprite._castId = CastMemberID(memberID, castLib);
 
-			sprite._scriptCastIndex = stream->readUint16();
-			sprite._scriptId = stream->readUint16();
+			uint16 scriptCastLib = stream->readUint16();
+			uint16 scriptMemberID = stream->readUint16();
+			sprite._scriptId = CastMemberID(scriptMemberID, scriptCastLib);
 
 			sprite._foreColor = _vm->transformColor((uint8)stream->readByte());
 			sprite._backColor = _vm->transformColor((uint8)stream->readByte());
@@ -336,8 +338,9 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 			sprite._foreColor = _vm->transformColor((uint8)stream->readByte());
 			sprite._backColor = _vm->transformColor((uint8)stream->readByte());
 
-			sprite._castIndex = stream->readUint16();
-			sprite._castId = stream->readUint16();
+			uint16 castLib = stream->readUint16();
+			uint16 memberID = stream->readUint16();
+			sprite._castId = CastMemberID(memberID, castLib);
 
 			/* uint32 spriteId = */stream->readUint32();
 
@@ -369,12 +372,12 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 
 		sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
 
-		if (sprite._castId) {
-			debugC(4, kDebugLoading, "CH: %-3d castId: %03d(%s) [flags:%04x [ink: %x trails: %d line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d] script: %d, flags2: %x, unk2: %x, unk3: %x",
-				i + 1, sprite._castId, numToCastNum(sprite._castId), sprite._inkData,
+		if (sprite._castId.member) {
+			debugC(4, kDebugLoading, "CH: %-3d castId: %s [flags:%04x [ink: %x trails: %d line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d] script: %s, flags2: %x, unk2: %x, unk3: %x",
+				i + 1, sprite._castId.asString().c_str(), sprite._inkData,
 				sprite._ink, sprite._trails, sprite._thickness, sprite._width, sprite._height,
 				sprite._startPoint.x, sprite._startPoint.y,
-				sprite._spriteType, sprite._foreColor, sprite._backColor, sprite._scriptId, sprite._colorcode, sprite._blendAmount, sprite._unk3);
+				sprite._spriteType, sprite._foreColor, sprite._backColor, sprite._scriptId.asString().c_str(), sprite._colorcode, sprite._blendAmount, sprite._unk3);
 		} else {
 			debugC(4, kDebugLoading, "CH: %-3d castId: 000", i + 1);
 		}
@@ -387,7 +390,7 @@ void Frame::readMainChannels(Common::SeekableReadStreamEndian &stream, uint16 of
 	while (offset < finishPosition) {
 		switch(offset) {
 		case kScriptIdPosition:
-			_actionId = stream.readByte();
+			_actionId = CastMemberID(stream.readByte(), 0);
 			offset++;
 			break;
 		case kSoundType1Position:
@@ -417,7 +420,7 @@ void Frame::readMainChannels(Common::SeekableReadStreamEndian &stream, uint16 of
 			offset++;
 			break;
 		case kSound1Position:
-			_sound1 = stream.readUint16();
+			_sound1 = CastMemberID(stream.readUint16(), 0);
 			offset+=2;
 			break;
 		case kSkipFrameFlagsPosition:
@@ -429,7 +432,7 @@ void Frame::readMainChannels(Common::SeekableReadStreamEndian &stream, uint16 of
 			offset++;
 			break;
 		case kSound2Position:
-			_sound2 = stream.readUint16();
+			_sound2 = CastMemberID(stream.readUint16(), 0);
 			offset += 2;
 			break;
 		case kSound2TypePosition:
@@ -449,7 +452,7 @@ void Frame::readMainChannels(Common::SeekableReadStreamEndian &stream, uint16 of
 		}
 	}
 
-	debugC(1, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1, _skipFrameFlag, _blend, _sound2, _soundType2);
+	debugC(1, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId.member, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1.member, _skipFrameFlag, _blend, _sound2.member, _soundType2);
 }
 
 void Frame::readPaletteInfo(Common::SeekableReadStreamEndian &stream) {
@@ -499,7 +502,7 @@ void Frame::readSprite(Common::SeekableReadStreamEndian &stream, uint16 offset,
 			fieldPosition += 2;
 			break;
 		case kSpritePositionCastId:
-			sprite._castId = stream.readUint16();
+			sprite._castId = CastMemberID(stream.readUint16(), 0);
 			fieldPosition += 2;
 			break;
 		case kSpritePositionY:
@@ -525,7 +528,7 @@ void Frame::readSprite(Common::SeekableReadStreamEndian &stream, uint16 offset,
 			break;
 		}
 	}
-	warning("Frame::readSprite(): %03d(%d)[%x,%x,%02x %02x,%d/%d/%d/%d]", sprite._castId, sprite._enabled, x1, x2, sprite._thickness, sprite._inkData, sprite._startPoint.x, sprite._startPoint.y, sprite._width, sprite._height);
+	warning("Frame::readSprite(): %s(%d)[%x,%x,%02x %02x,%d/%d/%d/%d]", sprite._castId.asString().c_str(), sprite._enabled, x1, x2, sprite._thickness, sprite._inkData, sprite._startPoint.x, sprite._startPoint.y, sprite._width, sprite._height);
 
 }
 
diff --git a/engines/director/frame.h b/engines/director/frame.h
index e123b54fe3..74b6b628a0 100644
--- a/engines/director/frame.h
+++ b/engines/director/frame.h
@@ -101,7 +101,7 @@ private:
 public:
 	int _numChannels;
 	byte _channelData[kChannelDataSize];
-	uint16 _actionId;
+	CastMemberID _actionId;
 	uint16 _transDuration;
 	uint8 _transArea; // 1 - Whole Window, 0 - Changing Area
 	uint8 _transChunkSize;
@@ -109,9 +109,9 @@ public:
 	PaletteInfo _palette;
 	uint8 _tempo;
 
-	uint16 _sound1;
+	CastMemberID _sound1;
 	uint8 _soundType1;
-	uint16 _sound2;
+	CastMemberID _sound2;
 	uint8 _soundType2;
 
 	byte _colorTempo;
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 142db50cbb..5935dab49b 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1518,9 +1518,9 @@ void LB::b_cursor(int nargs) {
 		Datum sprite = d.u.farr->operator[](0);
 		Datum mask = d.u.farr->operator[](1);
 
-		g_lingo->func_cursor(sprite.asCastId(), mask.asCastId());
+		g_lingo->func_cursor(sprite.asMemberID(), mask.asMemberID());
 	} else {
-		g_lingo->func_cursor(d.asInt(), -1);
+		g_lingo->func_cursor(d.asInt());
 	}
 }
 
@@ -1658,25 +1658,24 @@ void LB::b_installMenu(int nargs) {
 	// installMenu castNum
 	Datum d = g_lingo->pop();
 
-	int castId = d.asCastId();
-
-	if (castId == 0) {
+	CastMemberID memberID = d.asMemberID();
+	if (memberID.member == 0) {
 		g_director->_wm->removeMenu();
 		return;
 	}
 
-	CastMember *member = g_director->getCurrentMovie()->getCastMember(castId);
+	CastMember *member = g_director->getCurrentMovie()->getCastMember(memberID);
 	if (!member) {
-		g_lingo->lingoError("installMenu: Unknown cast number #%d", castId);
+		g_lingo->lingoError("installMenu: Unknown %s", memberID.asString().c_str());
 		return;
 	}
 	if (member->_type != kCastText) {
-		g_lingo->lingoError("installMenu: Cast member %d is not a field", castId);
+		g_lingo->lingoError("installMenu: %s is not a field", memberID.asString().c_str());
 		return;
 	}
 	TextCastMember *field = static_cast<TextCastMember *>(member);
 
-	Common::String menuStxt = g_lingo->_compiler->codePreprocessor(field->getText().c_str(), field->getCast()->_lingoArchive, kNoneScript, castId, true);
+	Common::String menuStxt = g_lingo->_compiler->codePreprocessor(field->getText().c_str(), field->getCast()->_lingoArchive, kNoneScript, memberID.member, true);
 	Common::String line;
 	int linenum = -1; // We increment it before processing
 
@@ -1843,14 +1842,10 @@ void LB::b_puppetPalette(int nargs) {
 				palette = kClutNTSC;
 			} else if (palStr.equalsIgnoreCase("Metallic")) {
 				palette = kClutMetallic;
-			} else {
-				CastMember *member = g_director->getCurrentMovie()->getCastMemberByName(palStr);
-
-				if (member && member->_type == kCastPalette)
-					palette = ((PaletteCastMember *)member)->getPaletteId();
 			}
-		} else {
-			CastMember *member = g_director->getCurrentMovie()->getCastMember(d.asInt());
+		}
+		if (!palette) {
+			CastMember *member = g_director->getCurrentMovie()->getCastMember(d.asMemberID());
 
 			if (member && member->_type == kCastPalette)
 				palette = ((PaletteCastMember *)member)->getPaletteId();
@@ -1896,7 +1891,7 @@ void LB::b_puppetSound(int nargs) {
 		return;
 	}
 
-	int castId = castMember.asCastId();
+	CastMemberID castId = castMember.asMemberID();
 	sound->playCastMember(castId, channel);
 }
 
@@ -2414,26 +2409,26 @@ void LB::b_version(int nargs) {
 ///////////////////
 void LB::b_cast(int nargs) {
 	Datum d = g_lingo->pop();
-	Datum res = d.asCastId();
+	Datum res = d.asMemberID();
 	res.type = CASTREF;
 	g_lingo->push(res);
 }
 
 void LB::b_script(int nargs) {
 	Datum d = g_lingo->pop();
-	int castId = d.asCastId();
-	CastMember *cast = g_director->getCurrentMovie()->getCastMember(castId);
+	CastMemberID memberID = d.asMemberID();
+	CastMember *cast = g_director->getCurrentMovie()->getCastMember(memberID);
 
 	if (cast) {
 		ScriptContext *script = nullptr;
 
 		if (cast->_type == kCastLingoScript) {
 			// script cast can be either a movie script or score script
-			script = g_director->getCurrentMovie()->getScriptContext(kMovieScript, castId);
+			script = g_director->getCurrentMovie()->getScriptContext(kMovieScript, memberID);
 			if (!script)
-				script = g_director->getCurrentMovie()->getScriptContext(kScoreScript, castId);
+				script = g_director->getCurrentMovie()->getScriptContext(kScoreScript, memberID);
 		} else {
-			g_director->getCurrentMovie()->getScriptContext(kCastScript, castId);
+			g_director->getCurrentMovie()->getScriptContext(kCastScript, memberID);
 		}
 
 		if (script) {
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index a91e01b28a..b58278c0a2 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -358,7 +358,7 @@ Datum Lingo::findVarV4(int varType, const Datum &id) {
 		}
 		break;
 	case 6: // field
-		res = id.asCastId();
+		res = id.asMemberID();
 		res.type = FIELDREF;
 		break;
 	default:
@@ -396,7 +396,7 @@ void LC::cb_delete() {
 }
 
 void LC::cb_hilite() {
-	Datum fieldID = g_lingo->pop().asCastId();
+	Datum fieldID = g_lingo->pop().asMemberID();
 	fieldID.type = FIELDREF;
 	Datum chunkRef = readChunkRef(fieldID);
 	g_lingo->push(chunkRef);
@@ -756,7 +756,7 @@ void LC::cb_v4theentitypush() {
 			break;
 		case kTEAChunk:
 			{
-				Datum fieldRef = g_lingo->pop().asCastId();
+				Datum fieldRef = g_lingo->pop().asMemberID();
 				fieldRef.type = FIELDREF;
 				Datum chunkRef = readChunkRef(fieldRef);
 				result = g_lingo->getTheEntity(entity, chunkRef, field);
@@ -862,7 +862,7 @@ void LC::cb_v4theentityassign() {
 		break;
 	case kTEAChunk:
 		{
-			Datum fieldRef = g_lingo->pop().asCastId();
+			Datum fieldRef = g_lingo->pop().asMemberID();
 			fieldRef.type = FIELDREF;
 			Datum chunkRef = readChunkRef(fieldRef);
 			g_lingo->setTheEntity(entity, chunkRef, field, value);
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index c2f50d8089..36d125204d 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -1633,7 +1633,8 @@ void LC::c_delete() {
 void LC::c_hilite() {
 	Datum d = g_lingo->pop();
 
-	int fieldId, start, end;
+	CastMemberID fieldId;
+	int start, end;
 	if (d.type == CHUNKREF) {
 		start = d.u.cref->start;
 		end = d.u.cref->end;
@@ -1644,13 +1645,13 @@ void LC::c_hilite() {
 			src = src.u.cref->source;
 		}
 		if (src.isCastRef()) {
-			fieldId = src.u.i;
+			fieldId = *d.u.cast;
 		} else {
 			warning("BUILDBOT: c_hilite: bad chunk ref field type: %s", src.type2str());
 			return;
 		}
 	} else if (d.isCastRef()) {
-		fieldId = d.u.i;
+		fieldId = *d.u.cast;
 		start = 0;
 		end = -1;
 	} else {
@@ -1675,7 +1676,7 @@ void LC::c_hilite() {
 
 void LC::c_fieldref() {
 	Datum d = g_lingo->pop();
-	Datum res = d.asCastId();
+	Datum res = d.asMemberID();
 	res.type = FIELDREF;
 	g_lingo->push(res);
 }
diff --git a/engines/director/lingo/lingo-events.cpp b/engines/director/lingo/lingo-events.cpp
index 8559cdd768..3c750d4c8d 100644
--- a/engines/director/lingo/lingo-events.cpp
+++ b/engines/director/lingo/lingo-events.cpp
@@ -128,7 +128,7 @@ void Movie::queueSpriteEvent(LEvent event, int eventId, int spriteId) {
 	Sprite *sprite = _score->getSpriteById(spriteId);
 
 	// Sprite (score) script
-	if (sprite->_scriptId) {
+	if (sprite->_scriptId.member) {
 		ScriptContext *script = getScriptContext(kScoreScript, sprite->_scriptId);
 		if (script) {
 			// In D3 the event lingo is not contained in a handler
@@ -162,8 +162,8 @@ void Movie::queueFrameEvent(LEvent event, int eventId) {
 	// } else {
 
 	assert(_score->_frames[_score->getCurrentFrame()] != nullptr);
-	int scriptId = _score->_frames[_score->getCurrentFrame()]->_actionId;
-	if (!scriptId)
+	CastMemberID scriptId = _score->_frames[_score->getCurrentFrame()]->_actionId;
+	if (!scriptId.member)
 		return;
 
 	ScriptContext *script = getScriptContext(kScoreScript, scriptId);
@@ -188,7 +188,7 @@ void Movie::queueMovieEvent(LEvent event, int eventId) {
 	for (ScriptContextHash::iterator it = mainArchive->scriptContexts[kMovieScript].begin();
 			it != mainArchive->scriptContexts[kMovieScript].end(); ++it) {
 		if (it->_value->_eventHandlers.contains(event)) {
-			_eventQueue.push(LingoEvent(event, eventId, kMovieScript, it->_key, false));
+			_eventQueue.push(LingoEvent(event, eventId, kMovieScript, CastMemberID(it->_key, 0), false));
 			return;
 		}
 	}
@@ -197,7 +197,7 @@ void Movie::queueMovieEvent(LEvent event, int eventId) {
 		for (ScriptContextHash::iterator it = sharedArchive->scriptContexts[kMovieScript].begin();
 				it != sharedArchive->scriptContexts[kMovieScript].end(); ++it) {
 			if (it->_value->_eventHandlers.contains(event)) {
-				_eventQueue.push(LingoEvent(event, eventId, kMovieScript, it->_key, false));
+				_eventQueue.push(LingoEvent(event, eventId, kMovieScript, CastMemberID(it->_key, 0), false));
 				return;
 			}
 		}
@@ -228,13 +228,19 @@ void Movie::registerEvent(LEvent event, int targetId) {
 	case kEventKeyUp:
 	case kEventKeyDown:
 	case kEventTimeout:
-		if (getScriptContext(kEventScript, event)) {
-			_eventQueue.push(LingoEvent(kEventGeneric, eventId, kEventScript, event, true));
+		{
+			CastMemberID scriptID = CastMemberID(event, 0);
+			if (getScriptContext(kEventScript, scriptID)) {
+				_eventQueue.push(LingoEvent(kEventGeneric, eventId, kEventScript, scriptID, true));
+			}
 		}
 		break;
 	case kEventMenuCallback:
-		if (getScriptContext(kEventScript, targetId)) {
-			_eventQueue.push(LingoEvent(kEventGeneric, eventId, kEventScript, targetId, true));
+		{
+			CastMemberID scriptID = CastMemberID(targetId, 0);
+			if (getScriptContext(kEventScript, scriptID)) {
+				_eventQueue.push(LingoEvent(kEventGeneric, eventId, kEventScript, scriptID, true));
+			}
 		}
 		break;
 	default:
@@ -336,7 +342,7 @@ void Lingo::processEvents() {
 	}
 }
 
-void Lingo::processEvent(LEvent event, ScriptType st, int scriptId, int channelId) {
+void Lingo::processEvent(LEvent event, ScriptType st, CastMemberID scriptId, int channelId) {
 	_currentChannelId = channelId;
 
 	if (!_eventHandlerTypes.contains(event))
@@ -345,11 +351,11 @@ void Lingo::processEvent(LEvent event, ScriptType st, int scriptId, int channelI
 	ScriptContext *script = g_director->getCurrentMovie()->getScriptContext(st, scriptId);
 
 	if (script && script->_eventHandlers.contains(event)) {
-		debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d): executing event handler", _eventHandlerTypes[event], scriptType2str(st), scriptId);
+		debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %s): executing event handler", _eventHandlerTypes[event], scriptType2str(st), scriptId.asString().c_str());
 		LC::call(script->_eventHandlers[event], 0, false);
 		execute(_pc);
 	} else {
-		debugC(9, kDebugEvents, "Lingo::processEvent(%s, %s, %d): no handler", _eventHandlerTypes[event], scriptType2str(st), scriptId);
+		debugC(9, kDebugEvents, "Lingo::processEvent(%s, %s, %s): no handler", _eventHandlerTypes[event], scriptType2str(st), scriptId.asString().c_str());
 	}
 }
 
diff --git a/engines/director/lingo/lingo-funcs.cpp b/engines/director/lingo/lingo-funcs.cpp
index 3a70aaa044..ec80c8186b 100644
--- a/engines/director/lingo/lingo-funcs.cpp
+++ b/engines/director/lingo/lingo-funcs.cpp
@@ -301,15 +301,16 @@ void Lingo::func_play(Datum &frame, Datum &movie) {
 	func_goto(frame, movie);
 }
 
-void Lingo::func_cursor(int cursorId, int maskId) {
+void Lingo::func_cursor(CastMemberID cursorId, CastMemberID maskId) {
 	Cursor cursor;
+	cursor.readFromCast(cursorId, maskId);
+	// TODO: Figure out why there are artifacts here
+	_vm->_wm->replaceCursor(cursor._cursorType, ((Graphics::Cursor *)&cursor));
+}
 
-	if (maskId == -1) {
-		cursor.readFromResource(cursorId);
-	} else {
-		cursor.readFromCast(cursorId, maskId);
-	}
-
+void Lingo::func_cursor(int cursorId) {
+	Cursor cursor;
+	cursor.readFromResource(cursorId);
 	// TODO: Figure out why there are artifacts here
 	_vm->_wm->replaceCursor(cursor._cursorType, ((Graphics::Cursor *)&cursor));
 }
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index d0cb4af99a..11f62f4c12 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -593,10 +593,11 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
 		break;
 	case kTheMouseCast:
 		{
+			// TODO: How is this handled with multiple casts in D5?
 			Common::Point pos = g_director->getCurrentWindow()->getMousePos();
 			uint16 spriteId = score->getSpriteIDFromPos(pos);
 			d.type = INT;
-			d.u.i = score->getSpriteById(spriteId)->_castId;
+			d.u.i = score->getSpriteById(spriteId)->_castId.member;
 			if (d.u.i == 0)
 				d.u.i = -1;
 		}
@@ -1139,7 +1140,8 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
 		d.u.i = channel->getBbox().bottom;
 		break;
 	case kTheCastNum:
-		d.u.i = sprite->_castId;
+		// TODO: How is this handled with multiple casts in D5?
+		d.u.i = sprite->_castId.member;
 		break;
 	case kTheConstraint:
 		d.u.i = channel->_constraint;
@@ -1151,8 +1153,9 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
 			d.type = ARRAY;
 			d.u.farr = new DatumArray(2);
 
-			d.u.farr->operator[](0) = (int)channel->_cursor._cursorCastId;
-			d.u.farr->operator[](1) = (int)channel->_cursor._cursorMaskId;
+			// TODO: How is this handled with multiple casts in D5?
+			d.u.farr->operator[](0) = (int)channel->_cursor._cursorCastId.member;
+			d.u.farr->operator[](1) = (int)channel->_cursor._cursorMaskId.member;
 		}
 		break;
 	case kTheEditableText:
@@ -1293,11 +1296,11 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
 		break;
 	case kTheCastNum:
 		{
-			int castId = d.asCastId();
+			CastMemberID castId = d.asMemberID();
 			CastMember *castMember = g_director->getCurrentMovie()->getCastMember(castId);
 
 			if (castMember && castMember->_type == kCastDigitalVideo) {
-				Common::String path = castMember->getCast()->getVideoPath(castId);
+				Common::String path = castMember->getCast()->getVideoPath(castId.member);
 				if (!path.empty()) {
 					((DigitalVideoCastMember *)castMember)->loadVideo(pathMakeRelative(path));
 					((DigitalVideoCastMember *)castMember)->startVideo(channel);
@@ -1321,9 +1324,9 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
 			if (d.type == CASTREF) {
 				// Reference: CastMember ID
 				// Find the first channel that uses this cast.
-				int castId = d.u.i;
+				CastMemberID memberID = *d.u.cast;
 				for (uint i = 0; i < score->_channels.size(); i++) {
-					if (score->_channels[i]->_sprite->_castId == castId) {
+					if (score->_channels[i]->_sprite->_castId == memberID) {
 						channelId = i;
 						break;
 					}
@@ -1342,8 +1345,8 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
 			channel->_cursor.readFromResource(d.asInt());
 			score->_cursorDirty = true;
 		} else if (d.type == ARRAY && d.u.farr->size() == 2) {
-			uint cursorId =	d.u.farr->operator[](0).asCastId();
-			uint maskId = d.u.farr->operator[](1).asCastId();
+			CastMemberID cursorId =	d.u.farr->operator[](0).asMemberID();
+			CastMemberID maskId = d.u.farr->operator[](1).asMemberID();
 
 			if (cursorId == channel->_cursor._cursorCastId &&
 					maskId == channel->_cursor._cursorMaskId)
@@ -1502,7 +1505,7 @@ Datum Lingo::getTheCast(Datum &id1, int field) {
 		return d;
 	}
 
-	int id = id1.asCastId();
+	CastMemberID id = id1.asMemberID();
 
 	CastMember *member = movie->getCastMember(id);
 	if (!member) {
@@ -1517,7 +1520,7 @@ Datum Lingo::getTheCast(Datum &id1, int field) {
 	}
 
 	if (!member->hasField(field)) {
-		warning("Lingo::getTheCast(): CastMember %d has no property '%s'", id, field2str(field));
+		warning("Lingo::getTheCast(): %s has no property '%s'", id.asString().c_str(), field2str(field));
 		return d;
 	}
 
@@ -1533,16 +1536,16 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
 		return;
 	}
 
-	int id = id1.asCastId();
+	CastMemberID id = id1.asMemberID();
 
 	CastMember *member = movie->getCastMember(id);
 	if (!member) {
-		g_lingo->lingoError("Lingo::setTheCast(): CastMember %d not found", id);
+		g_lingo->lingoError("Lingo::setTheCast(): %s not found", id.asString().c_str());
 		return;
 	}
 
 	if (!member->hasField(field)) {
-		warning("Lingo::setTheCast(): CastMember %d has no property '%s'", id, field2str(field));
+		warning("Lingo::setTheCast(): %s has no property '%s'", id.asString().c_str(), field2str(field));
 		return;
 	}
 
@@ -1558,24 +1561,24 @@ Datum Lingo::getTheField(Datum &id1, int field) {
 		return d;
 	}
 
-	int id = id1.asCastId();
+	CastMemberID id = id1.asMemberID();
 
 	CastMember *member = movie->getCastMember(id);
 	if (!member) {
 		if (field == kTheLoaded) {
 			d = 0;
 		} else {
-			g_lingo->lingoError("Lingo::getTheField(): CastMember %d not found", id);
+			g_lingo->lingoError("Lingo::getTheField(): %s not found", id.asString().c_str());
 		}
 		return d;
 	}
 	if (member->_type != kCastText) {
-		g_lingo->lingoError("Lingo::getTheField(): CastMember %d is not a field", id);
+		g_lingo->lingoError("Lingo::getTheField(): %s is not a field", id.asString().c_str());
 		return d;
 	}
 
 	if (!member->hasField(field)) {
-		warning("Lingo::getTheField(): CastMember %d has no property '%s'", id, field2str(field));
+		warning("Lingo::getTheField(): %s has no property '%s'", id.asString().c_str(), field2str(field));
 		return d;
 	}
 
@@ -1591,20 +1594,20 @@ void Lingo::setTheField(Datum &id1, int field, Datum &d) {
 		return;
 	}
 
-	int id = id1.asCastId();
+	CastMemberID id = id1.asMemberID();
 
 	CastMember *member = movie->getCastMember(id);
 	if (!member) {
-		g_lingo->lingoError("Lingo::setTheField(): CastMember %d not found", id);
+		g_lingo->lingoError("Lingo::setTheField(): %s not found", id.asString().c_str());
 		return;
 	}
 	if (member->_type != kCastText) {
-		g_lingo->lingoError("Lingo::setTheField(): CastMember %d is not a field", id);
+		g_lingo->lingoError("Lingo::setTheField(): %s is not a field", id.asString().c_str());
 		return;
 	}
 
 	if (!member->hasField(field)) {
-		warning("Lingo::setTheField(): CastMember %d has no property '%s'", id, field2str(field));
+		warning("Lingo::setTheField(): %s has no property '%s'", id.asString().c_str(), field2str(field));
 		return;
 	}
 
@@ -1639,18 +1642,19 @@ Datum Lingo::getTheChunk(Datum &chunk, int field) {
 		return d;
 	}
 
-	CastMember *member = movie->getCastMember(src.u.i);
+	CastMemberID memberID = *src.u.cast;
+	CastMember *member = movie->getCastMember(memberID);
 	if (!member) {
-		g_lingo->lingoError("Lingo::getTheChunk(): CastMember %d not found", src.u.i);
+		g_lingo->lingoError("Lingo::getTheChunk(): %s not found", memberID.asString().c_str());
 		return d;
 	}
 	if (member->_type != kCastText) {
-		g_lingo->lingoError("Lingo::getTheChunk(): CastMember %d is not a field", src.u.i);
+		g_lingo->lingoError("Lingo::getTheChunk(): %s is not a field", memberID.asString().c_str());
 		return d;
 	}
 
 	if (!((TextCastMember *)member)->hasChunkField(field)) {
-		warning("Lingo::getTheChunk(): CastMember %d has no chunk property '%s'", src.u.i, field2str(field));
+		warning("Lingo::getTheChunk(): %s has no chunk property '%s'", memberID.asString().c_str(), field2str(field));
 		return d;
 	}
 
@@ -1685,18 +1689,19 @@ void Lingo::setTheChunk(Datum &chunk, int field, Datum &d) {
 		return;
 	}
 
-	CastMember *member = movie->getCastMember(src.u.i);
+	CastMemberID memberID = *src.u.cast;
+	CastMember *member = movie->getCastMember(memberID);
 	if (!member) {
-		g_lingo->lingoError("Lingo::setTheChunk(): CastMember %d not found", src.u.i);
+		g_lingo->lingoError("Lingo::setTheChunk(): %s not found", memberID.asString().c_str());
 		return;
 	}
 	if (member->_type != kCastText) {
-		g_lingo->lingoError("Lingo::setTheChunk(): CastMember %d is not a field", src.u.i);
+		g_lingo->lingoError("Lingo::setTheChunk(): %s is not a field", memberID.asString().c_str());
 		return;
 	}
 
 	if (!((TextCastMember *)member)->hasChunkField(field)) {
-		warning("Lingo::setTheChunk(): CastMember %d has no chunk property '%s'", src.u.i, field2str(field));
+		warning("Lingo::setTheChunk(): %s has no chunk property '%s'", memberID.asString().c_str(), field2str(field));
 		return;
 	}
 
@@ -1730,13 +1735,13 @@ void Lingo::getObjectProp(Datum &obj, Common::String &propName) {
 			return;
 		}
 
-		int id = obj.u.i;
+		CastMemberID id = *obj.u.cast;
 		CastMember *member = movie->getCastMember(id);
 		if (!member) {
 			if (propName.equalsIgnoreCase("loaded")) {
 				d = 0;
 			} else {
-				g_lingo->lingoError("Lingo::getObjectProp(): CastMember %d not found", id);
+				g_lingo->lingoError("Lingo::getObjectProp(): %s not found", id.asString().c_str());
 			}
 			g_lingo->push(d);
 			return;
@@ -1745,7 +1750,7 @@ void Lingo::getObjectProp(Datum &obj, Common::String &propName) {
 		if (member->hasProp(propName)) {
 			d = member->getProp(propName);
 		} else {
-			g_lingo->lingoError("Lingo::getObjectProp(): CastMember %d has no property '%s'", id, propName.c_str());
+			g_lingo->lingoError("Lingo::getObjectProp(): %s has no property '%s'", id.asString().c_str(), propName.c_str());
 		}
 		g_lingo->push(d);
 		return;
@@ -1781,17 +1786,17 @@ void Lingo::setObjectProp(Datum &obj, Common::String &propName, Datum &val) {
 			return;
 		}
 
-		int id = obj.u.i;
+		CastMemberID id = *obj.u.cast;
 		CastMember *member = movie->getCastMember(id);
 		if (!member) {
-			g_lingo->lingoError("Lingo::setObjectProp(): CastMember %d not found", id);
+			g_lingo->lingoError("Lingo::setObjectProp(): %s not found", id.asString().c_str());
 			return;
 		}
 
 		if (member->hasProp(propName)) {
 			member->setProp(propName, val);
 		} else {
-			g_lingo->lingoError("Lingo::setObjectProp(): CastMember %d has no property '%s'", id, propName.c_str());
+			g_lingo->lingoError("Lingo::setObjectProp(): %s has no property '%s'", id.asString().c_str(), propName.c_str());
 		}
 	} else {
 		g_lingo->lingoError("Lingo::setObjectProp: Invalid object: %s", obj.asString(true).c_str());
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index b3b6906e04..9c5d1e2dd2 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -449,7 +449,7 @@ void Lingo::execute(uint pc) {
 	_abort = false;
 }
 
-void Lingo::executeScript(ScriptType type, uint16 id) {
+void Lingo::executeScript(ScriptType type, CastMemberID id) {
 	Movie *movie = _vm->getCurrentMovie();
 	if (!movie) {
 		warning("Request to execute script with no movie");
@@ -459,16 +459,16 @@ void Lingo::executeScript(ScriptType type, uint16 id) {
 	ScriptContext *sc = movie->getScriptContext(type, id);
 
 	if (!sc) {
-		debugC(3, kDebugLingoExec, "Request to execute non-existent script type %d id %d", type, id);
+		debugC(3, kDebugLingoExec, "Request to execute non-existent script type %d id %d of castLib %d", type, id.member, id.castLib);
 		return;
 	}
 
 	if (!sc->_eventHandlers.contains(kEventGeneric)) {
-		debugC(3, kDebugLingoExec, "Request to execute script type %d id %d with no scopeless lingo", type, id);
+		debugC(3, kDebugLingoExec, "Request to execute script type %d id %d of castLib %d with no scopeless lingo", type, id.member, id.castLib);
 		return;
 	}
 
-	debugC(1, kDebugLingoExec, "Executing script type: %s, id: %d", scriptType2str(type), id);
+	debugC(1, kDebugLingoExec, "Executing script type: %s, id: %d, castLib %d", scriptType2str(type), id.member, id.castLib);
 
 	Symbol sym = sc->_eventHandlers[kEventGeneric];
 	LC::call(sym, 0, false);
@@ -625,6 +625,13 @@ Datum::Datum(AbstractObject *val) {
 	}
 }
 
+Datum::Datum(const CastMemberID &val) {
+	u.cast = new CastMemberID(val);
+	type = CASTREF;
+	refCount = new int;
+	*refCount = 1;
+}
+
 void Datum::reset() {
 	if (!refCount)
 		return;
@@ -664,6 +671,10 @@ void Datum::reset() {
 		case CHUNKREF:
 			delete u.cref;
 			break;
+		case CASTREF:
+		case FIELDREF:
+			delete u.cast;
+			break;
 		default:
 			break;
 		}
@@ -802,20 +813,10 @@ Common::String Datum::asString(bool printonly) const {
 		s = Common::String::format("property: #%s", u.s->c_str());
 		break;
 	case CASTREF:
-		s = Common::String::format("cast %d", u.i);
+		s = Common::String::format("member %d of castLib %d", u.cast->member, u.cast->castLib);
 		break;
 	case FIELDREF:
-		{
-			int idx = u.i;
-			CastMember *member = g_director->getCurrentMovie()->getCastMember(idx);
-			if (!member) {
-				warning("asString(): Unknown cast id %d", idx);
-				s = "";
-				break;
-			}
-
-			s = Common::String::format("field: \"%s\"", ((TextCastMember *)member)->getText().c_str());
-		}
+		s = Common::String::format("field %d of castLib %d", u.cast->member, u.cast->castLib);
 		break;
 	case CHUNKREF:
 		{
@@ -875,40 +876,11 @@ Common::String Datum::asString(bool printonly) const {
 	return s;
 }
 
-int Datum::asCastId() const {
-	Movie *movie = g_director->getCurrentMovie();
-	if (!movie) {
-		warning("Datum::asCastId: No movie");
-		return 0;
-	}
-
-	int castId = 0;
-	switch (type) {
-	case STRING:
-		{
-			CastMember *member = movie->getCastMemberByName(asString());
-			if (member)
-				return member->getID();
-
-			warning("Datum::asCastId: reference to non-existent cast member: %s", asString().c_str());
-			return -1;
-		}
-		break;
-	case INT:
-	case CASTREF:
-		castId = u.i;
-		break;
-	case FLOAT:
-		castId = u.f;
-		break;
-	case VOID:
-		warning("Datum::asCastId: reference to VOID cast ID");
-		break;
-	default:
-		error("Datum::asCastId: unsupported cast ID type %s", type2str());
-	}
+CastMemberID Datum::asMemberID() const {
+	if (type == CASTREF || type == FIELDREF)
+		return *u.cast;
 
-	return castId;
+	return g_lingo->resolveCastMember(*this, 0);
 }
 
 bool Datum::isRef() const {
@@ -1056,7 +1028,7 @@ void Lingo::runTests() {
 
 			if (!debugChannelSet(-1, kDebugCompileOnly)) {
 				if (!_compiler->_hadError)
-					executeScript(kTestScript, counter);
+					executeScript(kTestScript, CastMemberID(counter, 0));
 				else
 					debug(">> Skipping execution");
 			}
@@ -1072,7 +1044,7 @@ void Lingo::runTests() {
 
 void Lingo::executeImmediateScripts(Frame *frame) {
 	for (uint16 i = 0; i <= _vm->getCurrentMovie()->getScore()->_numChannelsDisplayed; i++) {
-		if (_vm->getCurrentMovie()->getScore()->_immediateActions.contains(frame->_sprites[i]->_scriptId)) {
+		if (_vm->getCurrentMovie()->getScore()->_immediateActions.contains(frame->_sprites[i]->_scriptId.member)) {
 			// From D5 only explicit event handlers are processed
 			// Before that you could specify commands which will be executed on mouse up
 			if (_vm->getVersion() < 500)
@@ -1189,10 +1161,9 @@ void Lingo::varAssign(const Datum &var, const Datum &value) {
 				warning("varAssign: Assigning to a reference to an empty movie");
 				return;
 			}
-			int castId = var.u.i;
-			CastMember *member = movie->getCastMember(castId);
+			CastMember *member = movie->getCastMember(*var.u.cast);
 			if (!member) {
-				warning("varAssign: Unknown cast id %d", castId);
+				warning("varAssign: Unknown %s", var.u.cast->asString().c_str());
 				return;
 			}
 			switch (member->_type) {
@@ -1310,10 +1281,9 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
 				warning("varFetch: Assigning to a reference to an empty movie");
 				return result;
 			}
-			int castId = var.u.i;
-			CastMember *member = movie->getCastMember(castId);
+			CastMember *member = movie->getCastMember(*var.u.cast);
 			if (!member) {
-				warning("varFetch: Unknown cast id %d", castId);
+				warning("varFetch: Unknown %s", var.u.cast->asString().c_str());
 				return result;
 			}
 			switch (member->_type) {
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 036bd1d2fb..89ada9dc2b 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -112,6 +112,7 @@ struct Datum {	/* interpreter stack type */
 		PropertyArray *parr; /* PARRAY */
 		AbstractObject *obj; /* OBJECT */
 		ChunkReference *cref; /* CHUNKREF */
+		CastMemberID *cast;	/* CASTREF, FIELDREF */
 	} u;
 
 	int *refCount;
@@ -123,6 +124,7 @@ struct Datum {	/* interpreter stack type */
 	Datum(double val);
 	Datum(const Common::String &val);
 	Datum(AbstractObject *val);
+	Datum(const CastMemberID &val);
 	void reset();
 
 	~Datum() {
@@ -133,7 +135,7 @@ struct Datum {	/* interpreter stack type */
 	double asFloat() const;
 	int asInt() const;
 	Common::String asString(bool printonly = false) const;
-	int asCastId() const;
+	CastMemberID asMemberID() const;
 
 	bool isRef() const;
 	bool isVarRef() const;
@@ -199,11 +201,11 @@ struct LingoEvent {
 	LEvent event;
 	int eventId;
 	ScriptType scriptType;
-	int scriptId;
+	CastMemberID scriptId;
 	bool passByDefault;
 	int channelId;
 
-	LingoEvent (LEvent e, int ei, ScriptType st, int si, bool pass, int ci = -1) {
+	LingoEvent (LEvent e, int ei, ScriptType st, CastMemberID si, bool pass, int ci = -1) {
 		event = e;
 		eventId = ei;
 		scriptType = st;
@@ -242,7 +244,7 @@ public:
 	void resetLingo();
 
 	void executeHandler(const Common::String &name);
-	void executeScript(ScriptType type, uint16 id);
+	void executeScript(ScriptType type, CastMemberID id);
 	void printStack(const char *s, uint pc);
 	void printCallStack(uint pc);
 	Common::String decodeInstruction(LingoArchive *archive, ScriptData *sd, uint pc, uint *newPC = NULL);
@@ -264,7 +266,7 @@ public:
 	// lingo-events.cpp
 private:
 	void initEventHandlerTypes();
-	void processEvent(LEvent event, ScriptType st, int entityId, int channelId = -1);
+	void processEvent(LEvent event, ScriptType st, CastMemberID scriptId, int channelId = -1);
 
 public:
 	ScriptType event2script(LEvent ev);
@@ -313,7 +315,8 @@ public:
 	void func_gotoprevious();
 	void func_play(Datum &frame, Datum &movie);
 	void func_playdone();
-	void func_cursor(int cursorId, int maskId);
+	void func_cursor(CastMemberID cursorId, CastMemberID maskId);
+	void func_cursor(int cursorId);
 	int func_marker(int m);
 	uint16 func_label(Datum &label);
 
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index 2516d6cc6b..7229e23d62 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -296,34 +296,54 @@ void Movie::loadSharedCastsFrom(Common::String filename) {
 	_sharedCast->loadArchive();
 }
 
-CastMember *Movie::getCastMember(int castId) {
-	CastMember *result = _cast->getCastMember(castId);
-	if (result == nullptr && _sharedCast) {
-		result = _sharedCast->getCastMember(castId);
+CastMember *Movie::getCastMember(CastMemberID memberID) {
+	CastMember *result = nullptr;
+	if (memberID.castLib == 0) {
+		result = _cast->getCastMember(memberID.member);
+		if (result == nullptr && _sharedCast) {
+			result = _sharedCast->getCastMember(memberID.member);
+		}
+	} else {
+		warning("Movie::getCastMember: Unknown castLib %d", memberID.castLib);
 	}
 	return result;
 }
 
-CastMember *Movie::getCastMemberByName(const Common::String &name) {
-	CastMember *result = _cast->getCastMemberByName(name);
-	if (result == nullptr && _sharedCast) {
-		result = _sharedCast->getCastMemberByName(name);
+CastMember *Movie::getCastMemberByName(const Common::String &name, int castLib) {
+	CastMember *result = nullptr;
+	if (castLib == 0) {
+		result = _cast->getCastMemberByName(name);
+		if (result == nullptr && _sharedCast) {
+			result = _sharedCast->getCastMemberByName(name);
+		}
+	} else {
+		warning("Movie::getCastMemberByName: Unknown castLib %d", castLib);
 	}
 	return result;
 }
 
-CastMemberInfo *Movie::getCastMemberInfo(int castId) {
-	CastMemberInfo *result = _cast->getCastMemberInfo(castId);
-	if (result == nullptr && _sharedCast) {
-		result = _sharedCast->getCastMemberInfo(castId);
+CastMemberInfo *Movie::getCastMemberInfo(CastMemberID memberID) {
+	CastMemberInfo *result = nullptr;
+	if (memberID.castLib == 0) {
+		result = _cast->getCastMemberInfo(memberID.member);
+		if (result == nullptr && _sharedCast) {
+			result = _sharedCast->getCastMemberInfo(memberID.member);
+		}
+	} else {
+		warning("Movie::getCastMemberInfo: Unknown castLib %d", memberID.castLib);
 	}
 	return result;
 }
 
-const Stxt *Movie::getStxt(int castId) {
-	const Stxt *result = _cast->getStxt(castId);
-	if (result == nullptr && _sharedCast) {
-		result = _sharedCast->getStxt(castId);
+const Stxt *Movie::getStxt(CastMemberID memberID) {
+	const Stxt *result = nullptr;
+	if (memberID.castLib == 0) {
+		result = _cast->getStxt(memberID.member);
+		if (result == nullptr && _sharedCast) {
+			result = _sharedCast->getStxt(memberID.member);
+		}
+	} else {
+		warning("Movie::getStxt: Unknown castLib %d", memberID.castLib);
 	}
 	return result;
 }
@@ -336,10 +356,15 @@ LingoArchive *Movie::getSharedLingoArch() {
 	return _sharedCast ? _sharedCast->_lingoArchive : nullptr;
 }
 
-ScriptContext *Movie::getScriptContext(ScriptType type, uint16 id) {
-	ScriptContext *result = _cast->_lingoArchive->getScriptContext(type, id);
-	if (result == nullptr && _sharedCast) {
-		result = _sharedCast->_lingoArchive->getScriptContext(type, id);
+ScriptContext *Movie::getScriptContext(ScriptType type, CastMemberID id) {
+	ScriptContext *result = nullptr;
+	if (id.castLib == 0) {
+		result = _cast->_lingoArchive->getScriptContext(type, id.member);
+		if (result == nullptr && _sharedCast) {
+			result = _sharedCast->_lingoArchive->getScriptContext(type, id.member);
+		}
+	} else {
+		warning("Movie::getScriptContext: Unknown castLib %d", id.castLib);
 	}
 	return result;
 }
diff --git a/engines/director/movie.h b/engines/director/movie.h
index 2e84544070..59ac8b6723 100644
--- a/engines/director/movie.h
+++ b/engines/director/movie.h
@@ -117,14 +117,14 @@ public:
 	void clearSharedCast();
 	void loadSharedCastsFrom(Common::String filename);
 
-	CastMember *getCastMember(int castId);
-	CastMember *getCastMemberByName(const Common::String &name);
-	CastMemberInfo *getCastMemberInfo(int castId);
-	const Stxt *getStxt(int castId);
+	CastMember *getCastMember(CastMemberID memberID);
+	CastMember *getCastMemberByName(const Common::String &name, int castLib);
+	CastMemberInfo *getCastMemberInfo(CastMemberID memberID);
+	const Stxt *getStxt(CastMemberID memberID);
 
 	LingoArchive *getMainLingoArch();
 	LingoArchive *getSharedLingoArch();
-	ScriptContext *getScriptContext(ScriptType type, uint16 id);
+	ScriptContext *getScriptContext(ScriptType type, CastMemberID id);
 	Symbol getHandler(const Common::String &name);
 
 	// events.cpp
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index d36290f161..1c529ba9bb 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -98,8 +98,9 @@ int Score::getCurrentPalette() {
 }
 
 int Score::resolvePaletteId(int id) {
+	// TODO: Palette ID should be a CastMemberID to allow for palettes in different casts
 	if (id > 0) {
-		CastMember *member = _movie->getCastMember(id);
+		CastMember *member = _movie->getCastMember(CastMemberID(id, 0));
 		id = (member && member->_type == kCastPalette) ? ((PaletteCastMember *)member)->getPaletteId() : 0;
 	}
 
@@ -458,7 +459,7 @@ void Score::renderFrame(uint16 frameId, RenderMode mode) {
 	if (mode != kRenderNoWindowRender)
 		_window->render();
 
-	if (_frames[frameId]->_sound1 || _frames[frameId]->_sound2)
+	if (_frames[frameId]->_sound1.member || _frames[frameId]->_sound2.member)
 		playSoundChannel(frameId);
 
 	if (_cursorDirty) {
@@ -513,7 +514,7 @@ void Score::renderSprites(uint16 frameId, RenderMode mode) {
 				_movie->_videoPlayback = true;
 
 			_window->addDirtyRect(channel->getBbox());
-			debugC(2, kDebugImages, "Score::renderSprites(): CH: %-3d castId: %03d(%s) [ink: %d, puppet: %d, moveable: %d, visible: %d] [bbox: %d,%d,%d,%d] [type: %d fg: %d bg: %d] [script: %d]", i, currentSprite->_castId, numToCastNum(currentSprite->_castId), currentSprite->_ink, currentSprite->_puppet, currentSprite->_moveable, channel->_visible, PRINT_RECT(channel->getBbox()), currentSprite->_spriteType, currentSprite->_foreColor, currentSprite->_backColor, currentSprite->_scriptId);
+			debugC(2, kDebugImages, "Score::renderSprites(): CH: %-3d castId: %s [ink: %d, puppet: %d, moveable: %d, visible: %d] [bbox: %d,%d,%d,%d] [type: %d fg: %d bg: %d] [script: %s]", i, currentSprite->_castId.asString().c_str(), currentSprite->_ink, currentSprite->_puppet, currentSprite->_moveable, channel->_visible, PRINT_RECT(channel->getBbox()), currentSprite->_spriteType, currentSprite->_foreColor, currentSprite->_backColor, currentSprite->_scriptId.asString().c_str());
 		} else {
 			channel->setClean(nextSprite, i, true);
 		}
@@ -618,7 +619,7 @@ Common::List<Channel *> Score::getSpriteIntersections(const Common::Rect &r) {
 	return intersections;
 }
 
-uint16 Score::getSpriteIdByMemberId(uint16 id) {
+uint16 Score::getSpriteIdByMemberId(CastMemberID id) {
 	for (uint i = 0; i < _channels.size(); i++)
 		if (_channels[i]->_sprite->_castId == id)
 			return i;
@@ -657,7 +658,7 @@ Channel *Score::getChannelById(uint16 id) {
 void Score::playSoundChannel(uint16 frameId) {
 	Frame *frame = _frames[frameId];
 
-	debugC(5, kDebugLoading, "playSoundChannel(): Sound1 %d Sound2 %d", frame->_sound1, frame->_sound2);
+	debugC(5, kDebugLoading, "playSoundChannel(): Sound1 %s Sound2 %s", frame->_sound1.asString().c_str(), frame->_sound2.asString().c_str());
 	DirectorSound *sound = _vm->getSoundManager();
 	sound->playCastMember(frame->_sound1, 1, false);
 	sound->playCastMember(frame->_sound2, 2, false);
@@ -776,7 +777,7 @@ void Score::loadFrames(Common::SeekableReadStreamEndian &stream, uint16 version)
 			frame->readChannels(str, version);
 			delete str;
 
-			debugC(8, kDebugLoading, "Score::loadFrames(): Frame %d actionId: %d", _frames.size(), frame->_actionId);
+			debugC(8, kDebugLoading, "Score::loadFrames(): Frame %d actionId: %s", _frames.size(), frame->_actionId.asString().c_str());
 
 			_frames.push_back(frame);
 		} else {
@@ -792,7 +793,7 @@ void Score::setSpriteCasts() {
 		for (uint16 j = 0; j < _frames[i]->_sprites.size(); j++) {
 			_frames[i]->_sprites[j]->setCast(_frames[i]->_sprites[j]->_castId);
 
-			debugC(1, kDebugImages, "Score::setSpriteCasts(): Frame: %d Channel: %d castId: %d type: %d", i, j, _frames[i]->_sprites[j]->_castId, _frames[i]->_sprites[j]->_spriteType);
+			debugC(1, kDebugImages, "Score::setSpriteCasts(): Frame: %d Channel: %d castId: %s type: %d", i, j, _frames[i]->_sprites[j]->_castId.asString().c_str(), _frames[i]->_sprites[j]->_spriteType);
 		}
 	}
 }
@@ -886,12 +887,12 @@ void Score::loadActions(Common::SeekableReadStreamEndian &stream) {
 
 	// Now let's scan which scripts are actually referenced
 	for (uint i = 0; i < _frames.size(); i++) {
-		if (_frames[i]->_actionId <= _actions.size())
-			scriptRefs[_frames[i]->_actionId] = true;
+		if ((uint)_frames[i]->_actionId.member <= _actions.size())
+			scriptRefs[_frames[i]->_actionId.member] = true;
 
 		for (uint16 j = 0; j <= _frames[i]->_numChannels; j++) {
-			if (_frames[i]->_sprites[j]->_scriptId <= _actions.size())
-				scriptRefs[_frames[i]->_sprites[j]->_scriptId] = true;
+			if ((uint)_frames[i]->_sprites[j]->_scriptId.member <= _actions.size())
+				scriptRefs[_frames[i]->_sprites[j]->_scriptId.member] = true;
 		}
 	}
 
diff --git a/engines/director/score.h b/engines/director/score.h
index 6447d9aa2b..3b8ddb6601 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -106,7 +106,7 @@ public:
 	uint16 getActiveSpriteIDFromPos(Common::Point pos);
 	bool checkSpriteIntersection(uint16 spriteId, Common::Point pos);
 	Common::List<Channel *> getSpriteIntersections(const Common::Rect &r);
-	uint16 getSpriteIdByMemberId(uint16 id);
+	uint16 getSpriteIdByMemberId(CastMemberID id);
 
 	bool renderTransition(uint16 frameId);
 	void renderFrame(uint16 frameId, RenderMode mode = kRenderModeNormal);
diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp
index 51d93b848a..008650705d 100644
--- a/engines/director/sound.cpp
+++ b/engines/director/sound.cpp
@@ -95,21 +95,21 @@ void DirectorSound::playStream(Audio::AudioStream &stream, uint8 soundChannel) {
 	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_channels[soundChannel - 1].handle, &stream, -1, _channels[soundChannel - 1].volume);
 }
 
-void DirectorSound::playCastMember(int castId, uint8 soundChannel, bool allowRepeat) {
-	if (castId == 0) {
+void DirectorSound::playCastMember(CastMemberID memberID, uint8 soundChannel, bool allowRepeat) {
+	if (memberID.member == 0) {
 		stopSound(soundChannel);
 	} else {
-		CastMember *soundCast = _vm->getCurrentMovie()->getCastMember(castId);
+		CastMember *soundCast = _vm->getCurrentMovie()->getCastMember(memberID);
 		if (soundCast) {
 			if (soundCast->_type != kCastSound) {
-				warning("DirectorSound::playCastMember: attempted to play a non-SoundCastMember cast member %d", castId);
+				warning("DirectorSound::playCastMember: attempted to play a non-SoundCastMember %s", memberID.asString().c_str());
 			} else {
-				if (!allowRepeat && lastPlayingCast(soundChannel) == castId)
+				if (!allowRepeat && lastPlayingCast(soundChannel) == memberID)
 					return;
 				bool looping = ((SoundCastMember *)soundCast)->_looping;
 				AudioDecoder *ad = ((SoundCastMember *)soundCast)->_audio;
 				if (!ad) {
-					warning("DirectorSound::playCastMember: no audio data attached to cast member %d", castId);
+					warning("DirectorSound::playCastMember: no audio data attached to %s", memberID.asString().c_str());
 					return;
 				}
 				Audio::AudioStream *as;
@@ -122,10 +122,10 @@ void DirectorSound::playCastMember(int castId, uint8 soundChannel, bool allowRep
 					return;
 				}
 				playStream(*as, soundChannel);
-				_channels[soundChannel - 1].lastPlayingCast = castId;
+				_channels[soundChannel - 1].lastPlayingCast = memberID;
 			}
 		} else {
-			warning("DirectorSound::playCastMember: couldn't find cast member %d", castId);
+			warning("DirectorSound::playCastMember: couldn't find %s", memberID.asString().c_str());
 		}
 	}
 }
@@ -194,9 +194,9 @@ bool DirectorSound::isChannelValid(uint8 soundChannel) {
 	return true;
 }
 
-int DirectorSound::lastPlayingCast(uint8 soundChannel) {
+CastMemberID DirectorSound::lastPlayingCast(uint8 soundChannel) {
 	if (!isChannelValid(soundChannel))
-		return false;
+		return CastMemberID(0, 0);
 
 	return _channels[soundChannel - 1].lastPlayingCast;
 }
@@ -207,7 +207,7 @@ void DirectorSound::stopSound(uint8 soundChannel) {
 
 	cancelFade(soundChannel);
 	_mixer->stopHandle(_channels[soundChannel - 1].handle);
-	_channels[soundChannel - 1].lastPlayingCast = 0;
+	_channels[soundChannel - 1].lastPlayingCast = CastMemberID(0, 0);
 	return;
 }
 
@@ -216,7 +216,7 @@ void DirectorSound::stopSound() {
 		cancelFade(i + 1);
 
 		_mixer->stopHandle(_channels[i].handle);
-		_channels[i].lastPlayingCast = 0;
+		_channels[i].lastPlayingCast = CastMemberID(0, 0);
 	}
 
 	_mixer->stopHandle(_scriptSound);
diff --git a/engines/director/sound.h b/engines/director/sound.h
index 85eab9d949..b9147065d5 100644
--- a/engines/director/sound.h
+++ b/engines/director/sound.h
@@ -48,11 +48,11 @@ struct FadeParams {
 
 struct SoundChannel {
 	Audio::SoundHandle handle;
-	int lastPlayingCast;
+	CastMemberID lastPlayingCast;
 	byte volume;
 	FadeParams *fade;
 
-	SoundChannel(): handle(), lastPlayingCast(0), volume(255), fade(nullptr) {}
+	SoundChannel(): handle(), volume(255), fade(nullptr) {}
 };
 
 class DirectorSound {
@@ -73,14 +73,14 @@ public:
 	void playFile(Common::String filename, uint8 soundChannel);
 	void playMCI(Audio::AudioStream &stream, uint32 from, uint32 to);
 	void playStream(Audio::AudioStream &stream, uint8 soundChannel);
-	void playCastMember(int castId, uint8 soundChannel, bool allowRepeat = true);
+	void playCastMember(CastMemberID memberID, uint8 soundChannel, bool allowRepeat = true);
 	void systemBeep();
 
 	void registerFade(uint8 soundChannel, bool fadeIn, int ticks);
 	bool fadeChannel(uint8 soundChannel);
 
 	bool isChannelActive(uint8 soundChannel);
-	int lastPlayingCast(uint8 soundChannel);
+	CastMemberID lastPlayingCast(uint8 soundChannel);
 	void stopSound(uint8 soundChannel);
 	void stopSound();
 
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 5e0b241484..53ddf5512d 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -38,17 +38,15 @@ Sprite::Sprite(Frame *frame) {
 	_score = _frame->getScore();
 	_movie = _score->getMovie();
 
-	_scriptId = 0;
-	_scriptCastIndex = 0;
+	_scriptId = CastMemberID(0, 0);
 	_colorcode = 0;
 	_blendAmount = 0;
 	_unk3 = 0;
 
 	_enabled = false;
-	_castId = 0;
+	_castId = CastMemberID(0, 0);
 	_pattern = 0;
 
-	_castIndex = 0;
 	_spriteType = kInactiveSprite;
 	_inkData = 0;
 	_ink = kInkTypeCopy;
@@ -263,11 +261,11 @@ void Sprite::setPattern(uint16 pattern) {
 	}
 }
 
-void Sprite::setCast(uint16 castId) {
-	CastMember *member = _movie->getCastMember(castId);
-	_castId = castId;
+void Sprite::setCast(CastMemberID memberID) {
+	CastMember *member = _movie->getCastMember(memberID);
+	_castId = memberID;
 
-	if (castId == 0)
+	if (memberID.member == 0)
 		return;
 
 	if (member) {
@@ -293,7 +291,7 @@ void Sprite::setCast(uint16 castId) {
 			_height = dims.height();
 		}
 	} else {
-		warning("Sprite::setCast(): CastMember id %d(%s) has null member", castId, numToCastNum(castId));
+		warning("Sprite::setCast(): %s has null member", memberID.asString().c_str());
 	}
 }
 
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
index 02faa8651b..233cae70e8 100644
--- a/engines/director/sprite.h
+++ b/engines/director/sprite.h
@@ -74,7 +74,7 @@ public:
 	uint16 getPattern();
 	void setPattern(uint16 pattern);
 
-	void setCast(uint16 castid);
+	void setCast(CastMemberID memberID);
 	bool isQDShape();
 	Graphics::Surface *getQDMatte();
 	void createQDMatte();
@@ -83,20 +83,18 @@ public:
 	Score *_score;
 	Movie *_movie;
 
-	uint16 _scriptId;
-	uint16 _scriptCastIndex;
+	CastMemberID _scriptId;
 	byte _colorcode; // x40 editable, 0x80 moveable
 	byte _blendAmount;
 	uint32 _unk3;
 
 	bool _enabled;
-	uint16 _castIndex;
 	SpriteType _spriteType;
 	byte _inkData;
 	InkType _ink;
 	uint16 _trails;
 
-	uint16 _castId;
+	CastMemberID _castId;
 	uint16 _pattern;
 	CastMember *_cast;
 
diff --git a/engines/director/types.h b/engines/director/types.h
index ed2fcdd844..78c9e702d7 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -378,7 +378,7 @@ struct CastMemberID {
 		return member != c.member || castLib != c.castLib;
 	}
 
-	const char *str() const;
+	Common::String asString() const;
 };
 
 struct Datum;
diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index e6cf0d99e0..07667a8f3c 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -201,15 +201,13 @@ char *numToCastNum(int num) {
 	return res;
 }
 
-const char *CastMemberID::str() const {
-	static char res[40];
+Common::String CastMemberID::asString() const {
+	Common::String res = Common::String::format("member %d", member);
 
 	if (g_director->getVersion() < 400 || g_director->getCurrentMovie()->_allowOutdatedLingo)
-		snprintf(res, 40, "member %d(%s)", member, numToCastNum(member));
-	else if (g_director->getVersion() < 500)
-		snprintf(res, 40, "member %d", member);
-	else
-		snprintf(res, 40, "member %d of castLib %d", member, castLib);
+		res += "(" + Common::String(numToCastNum(member)) + ")";
+	else if (g_director->getVersion() >= 500)
+		res += Common::String::format(" of castLib %d", castLib);
 
 	return res;
 }
diff --git a/engines/director/window.cpp b/engines/director/window.cpp
index 2f93c7eea2..9d72bbd281 100644
--- a/engines/director/window.cpp
+++ b/engines/director/window.cpp
@@ -173,7 +173,7 @@ void Window::inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::Mana
 			inkBlitSurface(&pd, srcRect, channel->getMask());
 		}
 	} else {
-		warning("Window::inkBlitFrom: No source surface: spriteType: %d, castType: %d, castId: %d", channel->_sprite->_spriteType, channel->_sprite->_cast ? channel->_sprite->_cast->_type : 0, channel->_sprite->_castId);
+		warning("Window::inkBlitFrom: No source surface: spriteType: %d, castType: %d, castId: %s", channel->_sprite->_spriteType, channel->_sprite->_cast ? channel->_sprite->_cast->_type : 0, channel->_sprite->_castId.asString().c_str());
 	}
 }
 


Commit: 8bbd6da3a430eb91f288e22212f86b851ce766be
    https://github.com/scummvm/scummvm/commit/8bbd6da3a430eb91f288e22212f86b851ce766be
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-30T22:32:19-04:00

Commit Message:
DIRECTOR: LINGO: Remove unbalanced 'end if' patches

This is handled in the grammar now.

Changed paths:
    engines/director/lingo/lingo-patcher.cpp


diff --git a/engines/director/lingo/lingo-patcher.cpp b/engines/director/lingo/lingo-patcher.cpp
index 500e276ca5..6d728b3a2e 100644
--- a/engines/director/lingo/lingo-patcher.cpp
+++ b/engines/director/lingo/lingo-patcher.cpp
@@ -101,14 +101,6 @@ struct ScriptPatch {
 	{"warlock", nullptr, kPlatformMacintosh, "DATA/K/KT/OutMarauderKT", kMovieScript, 2,
 			23, "set Spacesuit = 0 then", "set Spacesuit = 0"},
 
-	// Unbalanced 'end if' at the end of the script
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/STAMBUL/DRUNK", kMovieScript, 4,
-			5, "end if", ""},
-
-	// Unbalanced 'end if' at the end of the script
-	{"warlock", nullptr, kPlatformMacintosh, "STAMBUL/DRUNK", kMovieScript, 5,
-			5, "end if", ""},
-
 	// Missing '&'
 	{"warlock", nullptr, kPlatformMacintosh, "DATA/NAV/Shared Cast", kMovieScript, 1,
 			19, "alert \"Failed Save.\" & return & \"Error message number: \" string ( filer )",
@@ -122,10 +114,6 @@ struct ScriptPatch {
 	{"warlock", "", kPlatformWindows, "WRLCKSHP/UpForeECall", kScoreScript, 12,
 			4, "Frames 150 to 160", ""},
 
-	// Unbalanced 'end if' at the end of the script
-	{"warlock", "", kPlatformWindows, "STAMBUL/DRUNK", kMovieScript, 5,
-			5, "end if", ""},
-
 	// Missing '&'
 	{"warlock", nullptr, kPlatformUnknown, "NAV/Shared Cast", kMovieScript, 0,
 			23, "alert \"Failed Save.\" & return & \"Error message number: \" string ( filer )",
@@ -156,9 +144,6 @@ struct ScriptPatch {
 			   "GO \"SPACE\" OF MOVIE \"L-ZONE:DATA:R-G:ST-A2\""},
 
 
-	// Unbalanced 'end if' at the end of the script
-	{"jman", "", kPlatformWindows, "mmm/TSA RR 06", kScoreScript, 26,
-			17, "end if", ""},
 	{"jman", "", kPlatformWindows, "mmm/Mars Space Game 05", kMovieScript, 3,
 			68, "set DamageParameter = (gProcessorSpeed/2) + 7)", "set DamageParameter = (gProcessorSpeed/2) + 7"},
 


Commit: 8dfa5f4e737fe12b8666808872e62c62c41253a7
    https://github.com/scummvm/scummvm/commit/8dfa5f4e737fe12b8666808872e62c62c41253a7
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-30T22:32:19-04:00

Commit Message:
DIRECTOR: LINGO: Use member ID as script ID in D2-3

Movie scripts have a corresponding text cast member, so it makes sense
to have the IDs match.

Changed paths:
    engines/director/cast.cpp
    engines/director/cast.h
    engines/director/movie.cpp


diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 78f1ce6d2a..e7cdc09992 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -70,7 +70,6 @@ Cast::Cast(Movie *movie, bool isShared) {
 
 	_lingoArchive = new LingoArchive(this);
 
-	_movieScriptCount = 0;
 	_castArrayStart = _castArrayEnd = 0;
 
 	_castIDoffset = 0;
@@ -432,7 +431,7 @@ void Cast::loadCast() {
 			if (debugChannelSet(-1, kDebugFewFramesOnly))
 				warning("Compiling STXT %d", *iterator);
 
-			loadScriptText(*(r = _castArchive->getResource(MKTAG('S','T','X','T'), *iterator)));
+			loadScriptText(*(r = _castArchive->getResource(MKTAG('S','T','X','T'), *iterator)), *iterator - _castIDoffset);
 			delete r;
 		}
 
@@ -1023,7 +1022,7 @@ void Cast::loadLingoContext(Common::SeekableReadStreamEndian &stream) {
 	}
 }
 
-void Cast::loadScriptText(Common::SeekableReadStreamEndian &stream) {
+void Cast::loadScriptText(Common::SeekableReadStreamEndian &stream, uint16 id) {
 	/*uint32 unk1 = */ stream.readUint32();
 	uint32 strLen = stream.readUint32();
 	/*uin32 dataLen = */ stream.readUint32();
@@ -1045,14 +1044,12 @@ void Cast::loadScriptText(Common::SeekableReadStreamEndian &stream) {
 		return;
 
 	if (ConfMan.getBool("dump_scripts"))
-		dumpScript(script.c_str(), kMovieScript, _movieScriptCount);
+		dumpScript(script.c_str(), kMovieScript, id);
 
 	if (script.contains("\nmenu:") || script.hasPrefix("menu:"))
 		return;
 
-	_lingoArchive->addCode(script.c_str(), kMovieScript, _movieScriptCount);
-
-	_movieScriptCount++;
+	_lingoArchive->addCode(script.c_str(), kMovieScript, id);
 }
 
 void Cast::dumpScript(const char *script, ScriptType type, uint16 id) {
diff --git a/engines/director/cast.h b/engines/director/cast.h
index dc342e6ab4..2a578a419a 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -80,7 +80,7 @@ public:
 
 private:
 	PaletteV4 loadPalette(Common::SeekableReadStreamEndian &stream);
-	void loadScriptText(Common::SeekableReadStreamEndian &stream);
+	void loadScriptText(Common::SeekableReadStreamEndian &stream, uint16 id);
 	void loadFontMap(Common::SeekableReadStreamEndian &stream);
 	Common::String getString(Common::String str);
 
@@ -100,7 +100,6 @@ public:
 	uint16 _stageColor;
 	int _defaultPalette;
 
-	uint16 _movieScriptCount;
 	LingoArchive *_lingoArchive;
 
 private:
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index 7229e23d62..d734223ccd 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -230,12 +230,11 @@ void Movie::loadFileInfo(Common::SeekableReadStreamEndian &stream) {
 	_script = fileInfo.strings[0].readString(false);
 
 	if (!_script.empty() && ConfMan.getBool("dump_scripts"))
-		_cast->dumpScript(_script.c_str(), kMovieScript, _cast->_movieScriptCount);
+		_cast->dumpScript(_script.c_str(), kMovieScript, 0);
 
 	if (!_script.empty())
-		_cast->_lingoArchive->addCode(_script.c_str(), kMovieScript, _cast->_movieScriptCount);
+		_cast->_lingoArchive->addCode(_script.c_str(), kMovieScript, 0);
 
-	_cast->_movieScriptCount++;
 	_changedBy = fileInfo.strings[1].readString();
 	_createdBy = fileInfo.strings[2].readString();
 	_createdBy = fileInfo.strings[3].readString();


Commit: b27696e49c36760f751c7d3e7f2549765636321f
    https://github.com/scummvm/scummvm/commit/b27696e49c36760f751c7d3e7f2549765636321f
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-30T22:32:19-04:00

Commit Message:
DIRECTOR: LINGO: Fix movie script IDs in patcher

Changed paths:
    engines/director/lingo/lingo-patcher.cpp


diff --git a/engines/director/lingo/lingo-patcher.cpp b/engines/director/lingo/lingo-patcher.cpp
index 6d728b3a2e..c126aee3c3 100644
--- a/engines/director/lingo/lingo-patcher.cpp
+++ b/engines/director/lingo/lingo-patcher.cpp
@@ -98,11 +98,11 @@ struct ScriptPatch {
 			4, "Frames 20 to 20", ""},
 
 	// Stray 'then' (obvious copy/paste error)
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/K/KT/OutMarauderKT", kMovieScript, 2,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/K/KT/OutMarauderKT", kMovieScript, 14,
 			23, "set Spacesuit = 0 then", "set Spacesuit = 0"},
 
 	// Missing '&'
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/NAV/Shared Cast", kMovieScript, 1,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/NAV/Shared Cast", kMovieScript, 510,
 			19, "alert \"Failed Save.\" & return & \"Error message number: \" string ( filer )",
 				"alert \"Failed Save.\" & return & \"Error message number: \" & string ( filer )"},
 
@@ -115,11 +115,7 @@ struct ScriptPatch {
 			4, "Frames 150 to 160", ""},
 
 	// Missing '&'
-	{"warlock", nullptr, kPlatformUnknown, "NAV/Shared Cast", kMovieScript, 0,
-			23, "alert \"Failed Save.\" & return & \"Error message number: \" string ( filer )",
-				"alert \"Failed Save.\" & return & \"Error message number: \" & string ( filer )"},
-
-	{"warlock", nullptr, kPlatformUnknown, "NAV/Shared Cast", kMovieScript, 1,	// For running by the buildbot
+	{"warlock", nullptr, kPlatformUnknown, "NAV/Shared Cast", kMovieScript, 510,
 			23, "alert \"Failed Save.\" & return & \"Error message number: \" string ( filer )",
 				"alert \"Failed Save.\" & return & \"Error message number: \" & string ( filer )"},
 
@@ -144,7 +140,7 @@ struct ScriptPatch {
 			   "GO \"SPACE\" OF MOVIE \"L-ZONE:DATA:R-G:ST-A2\""},
 
 
-	{"jman", "", kPlatformWindows, "mmm/Mars Space Game 05", kMovieScript, 3,
+	{"jman", "", kPlatformWindows, "mmm/Mars Space Game 05", kMovieScript, 10,
 			68, "set DamageParameter = (gProcessorSpeed/2) + 7)", "set DamageParameter = (gProcessorSpeed/2) + 7"},
 
 	{nullptr, nullptr, kPlatformUnknown, nullptr, kNoneScript, 0, 0, nullptr, nullptr}


Commit: 7bfa8aa6dc378de3a627a3c7e4d8a1543ac659da
    https://github.com/scummvm/scummvm/commit/7bfa8aa6dc378de3a627a3c7e4d8a1543ac659da
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-30T22:32:19-04:00

Commit Message:
DIRECTOR: Add castLibID to Cast

Changed paths:
    engines/director/cast.cpp
    engines/director/cast.h
    engines/director/movie.cpp


diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index e7cdc09992..88801db5ad 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -61,11 +61,12 @@ const char *scriptType2str(ScriptType scr) {
 	return scriptTypes[scr];
 }
 
-Cast::Cast(Movie *movie, bool isShared) {
+Cast::Cast(Movie *movie, uint16 castLibID, bool isShared) {
 	_movie = movie;
 	_vm = _movie->getVM();
 	_lingo = _vm->getLingo();
 
+	_castLibID = castLibID;
 	_isShared = isShared;
 
 	_lingoArchive = new LingoArchive(this);
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 2a578a419a..367dabd1cf 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -48,7 +48,7 @@ class TextCastMember;
 
 class Cast {
 public:
-	Cast(Movie *movie, bool shared = false);
+	Cast(Movie *movie, uint16 castLibID, bool shared = false);
 	~Cast();
 
 	void loadArchive();
@@ -87,6 +87,7 @@ private:
 public:
 	Archive *_castArchive;
 	uint16 _version;
+	uint16 _castLibID;
 
 	Common::HashMap<uint16, Common::String> _fontMap;
 
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index d734223ccd..fe4a9c5a32 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -69,7 +69,7 @@ Movie::Movie(Window *window) {
 
 	_movieArchive = nullptr;
 
-	_cast = new Cast(this);
+	_cast = new Cast(this, 0);
 	_sharedCast = nullptr;
 	_score = new Score(this);
 
@@ -290,7 +290,7 @@ void Movie::loadSharedCastsFrom(Common::String filename) {
 	debug(0, "@@@@   Loading shared cast '%s'", filename.c_str());
 	debug(0, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
 
-	_sharedCast = new Cast(this, true);
+	_sharedCast = new Cast(this, 0, true);
 	_sharedCast->setArchive(sharedCast);
 	_sharedCast->loadArchive();
 }


Commit: 0e9fd00720930813a6389322ac69ebdb8f456766
    https://github.com/scummvm/scummvm/commit/0e9fd00720930813a6389322ac69ebdb8f456766
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-30T22:32:19-04:00

Commit Message:
DIRECTOR: LINGO: Take castLib into account in patcher

Changed paths:
    engines/director/lingo/lingo-builtins.cpp
    engines/director/lingo/lingo-codegen.cpp
    engines/director/lingo/lingo-codegen.h
    engines/director/lingo/lingo-patcher.cpp
    engines/director/lingo/lingo-preprocessor.cpp
    engines/director/lingo/lingo.cpp


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 5935dab49b..62c38c1d91 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1675,7 +1675,7 @@ void LB::b_installMenu(int nargs) {
 	}
 	TextCastMember *field = static_cast<TextCastMember *>(member);
 
-	Common::String menuStxt = g_lingo->_compiler->codePreprocessor(field->getText().c_str(), field->getCast()->_lingoArchive, kNoneScript, memberID.member, true);
+	Common::String menuStxt = g_lingo->_compiler->codePreprocessor(field->getText().c_str(), field->getCast()->_lingoArchive, kNoneScript, memberID, true);
 	Common::String line;
 	int linenum = -1; // We increment it before processing
 
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index e598b8ea07..1114cd78fd 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -96,13 +96,13 @@ ScriptContext *LingoCompiler::compileAnonymous(const char *code) {
 	debugC(1, kDebugCompile, "Compiling anonymous lingo\n"
 			"***********\n%s\n\n***********", code);
 
-	return compileLingo(code, nullptr, kNoneScript, 0, "[anonymous]", true);
+	return compileLingo(code, nullptr, kNoneScript, CastMemberID(0, 0), "[anonymous]", true);
 }
 
-ScriptContext *LingoCompiler::compileLingo(const char *code, LingoArchive *archive, ScriptType type, uint16 id, const Common::String &scriptName, bool anonymous) {
+ScriptContext *LingoCompiler::compileLingo(const char *code, LingoArchive *archive, ScriptType type, CastMemberID id, const Common::String &scriptName, bool anonymous) {
 	_assemblyArchive = archive;
 	_assemblyAST = nullptr;
-	ScriptContext *mainContext = _assemblyContext = new ScriptContext(scriptName, archive, type, id);
+	ScriptContext *mainContext = _assemblyContext = new ScriptContext(scriptName, archive, type, id.member);
 	_currentAssembly = new ScriptData;
 
 	_methodVars = new VarTypeHash;
diff --git a/engines/director/lingo/lingo-codegen.h b/engines/director/lingo/lingo-codegen.h
index 0e205843b6..8e69ec9e99 100644
--- a/engines/director/lingo/lingo-codegen.h
+++ b/engines/director/lingo/lingo-codegen.h
@@ -35,7 +35,7 @@ public:
 	virtual ~LingoCompiler() {}
 
 	ScriptContext *compileAnonymous(const char *code);
-	ScriptContext *compileLingo(const char *code, LingoArchive *archive, ScriptType type, uint16 id, const Common::String &scriptName, bool anonyomous = false);
+	ScriptContext *compileLingo(const char *code, LingoArchive *archive, ScriptType type, CastMemberID id, const Common::String &scriptName, bool anonyomous = false);
 	ScriptContext *compileLingoV4(Common::SeekableReadStreamEndian &stream, LingoArchive *archive, const Common::String &archName, uint16 version);
 
 	int code1(inst code) { _currentAssembly->push_back(code); return _currentAssembly->size() - 1; }
@@ -131,10 +131,10 @@ private:
 
 public:
 	// lingo-preprocessor.cpp
-	Common::String codePreprocessor(const char *s, LingoArchive *archive, ScriptType type, uint16 id, bool simple = false);
+	Common::String codePreprocessor(const char *s, LingoArchive *archive, ScriptType type, CastMemberID id, bool simple = false);
 
 	// lingo-patcher.cpp
-	Common::String patchLingoCode(Common::String &line, LingoArchive *archive, ScriptType type, uint16 id, int linenumber);
+	Common::String patchLingoCode(Common::String &line, LingoArchive *archive, ScriptType type, CastMemberID id, int linenumber);
 };
 
 } // End of namespace Director
diff --git a/engines/director/lingo/lingo-patcher.cpp b/engines/director/lingo/lingo-patcher.cpp
index c126aee3c3..21ab06333a 100644
--- a/engines/director/lingo/lingo-patcher.cpp
+++ b/engines/director/lingo/lingo-patcher.cpp
@@ -37,116 +37,117 @@ struct ScriptPatch {
 	const char *movie;
 	ScriptType type;
 	uint16 id;
+	uint16 castLib;
 	int linenum;
 	const char *orig;
 	const char *replace;
 } const scriptPatches[] = {
 	// Garbage at end of script
-	{"warlock", nullptr, kPlatformMacintosh, "WARLOCKSHIP/UpForeECall", kScoreScript, 12,
+	{"warlock", nullptr, kPlatformMacintosh, "WARLOCKSHIP/UpForeECall", kScoreScript, 12, 0,
 			2, "SS Warlock:DATA:WARLOCKSHIP:Up.GCGunner", ""},
-	{"warlock", nullptr, kPlatformMacintosh, "WARLOCKSHIP/UpForeECall", kScoreScript, 12,
+	{"warlock", nullptr, kPlatformMacintosh, "WARLOCKSHIP/UpForeECall", kScoreScript, 12, 0,
 			3, "Channels 17 to 18", ""},
-	{"warlock", nullptr, kPlatformMacintosh, "WARLOCKSHIP/UpForeECall", kScoreScript, 12,
+	{"warlock", nullptr, kPlatformMacintosh, "WARLOCKSHIP/UpForeECall", kScoreScript, 12, 0,
 			4, "Frames 150 to 160", ""},
 
 	// Garbage at end of script
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/HE.Aft", kScoreScript, 8,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/HE.Aft", kScoreScript, 8, 0,
 			2, "SS Warlock:DATA:WARLOCKSHIP:HangStairsFore", ""},
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/HE.Aft", kScoreScript, 8,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/HE.Aft", kScoreScript, 8, 0,
 			3, "Channels 4 to 5", ""},
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/HE.Aft", kScoreScript, 8,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/HE.Aft", kScoreScript, 8, 0,
 			4, "Frames 20 to 20", ""},
 
 	// Garbage at end of script
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/ENG/D10", kScoreScript, 8,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/ENG/D10", kScoreScript, 8, 0,
 			2, "SS Warlock:ENG.Fold:C9", ""},
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/ENG/D10", kScoreScript, 8,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/ENG/D10", kScoreScript, 8, 0,
 			3, "Channels 19 to 20", ""},
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/ENG/D10", kScoreScript, 8,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/ENG/D10", kScoreScript, 8, 0,
 			4, "Frames 165 to 180", ""},
 
 	// Garbage at end of script
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.c2", kScoreScript, 10,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.c2", kScoreScript, 10, 0,
 			2, "Frames 150 to 160", ""},
 
 	// Garbage at end of script
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.ForeECall", kScoreScript, 12,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.ForeECall", kScoreScript, 12, 0,
 			2, "SS Warlock:DATA:WARLOCKSHIP:Up.GCGunner", ""},
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.ForeECall", kScoreScript, 12,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.ForeECall", kScoreScript, 12, 0,
 			3, "Channels 17 to 18", ""},
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.ForeECall", kScoreScript, 12,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.ForeECall", kScoreScript, 12, 0,
 			4, "Frames 150 to 160", ""},
 
 	// Garbage at end of script
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.B2", kScoreScript, 9,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.B2", kScoreScript, 9, 0,
 			2, "SS Warlock:DATA:WARLOCKSHIP:Up.GCGunner", ""},
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.B2", kScoreScript, 9,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.B2", kScoreScript, 9, 0,
 			3, "Channels 17 to 18", ""},
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.B2", kScoreScript, 9,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/Up.B2", kScoreScript, 9, 0,
 			4, "Frames 150 to 160", ""},
 
 	// Garbage at end of script
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/BELSHAZZAR/STELLA/ORIGIN", kScoreScript, 12,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/BELSHAZZAR/STELLA/ORIGIN", kScoreScript, 12, 0,
 			2, "Frames 1 to 1", ""},
 
 	// Garbage at end of script
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/HangHallAft", kScoreScript, 7,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/HangHallAft", kScoreScript, 7, 0,
 			2, "SS Warlock:DATA:WARLOCKSHIP:HangStairsFore", ""},
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/HangHallAft", kScoreScript, 7,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/HangHallAft", kScoreScript, 7, 0,
 			3, "Channels 4 to 5", ""},
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/HangHallAft", kScoreScript, 7,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/WARLOCKSHIP/HangHallAft", kScoreScript, 7, 0,
 			4, "Frames 20 to 20", ""},
 
 	// Stray 'then' (obvious copy/paste error)
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/K/KT/OutMarauderKT", kMovieScript, 14,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/K/KT/OutMarauderKT", kMovieScript, 14, 0,
 			23, "set Spacesuit = 0 then", "set Spacesuit = 0"},
 
 	// Missing '&'
-	{"warlock", nullptr, kPlatformMacintosh, "DATA/NAV/Shared Cast", kMovieScript, 510,
+	{"warlock", nullptr, kPlatformMacintosh, "DATA/NAV/Shared Cast", kMovieScript, 510, 0,
 			19, "alert \"Failed Save.\" & return & \"Error message number: \" string ( filer )",
 				"alert \"Failed Save.\" & return & \"Error message number: \" & string ( filer )"},
 
 	// Garbage at end of script
-	{"warlock", "", kPlatformWindows, "WRLCKSHP/UpForeECall", kScoreScript, 12,
+	{"warlock", "", kPlatformWindows, "WRLCKSHP/UpForeECall", kScoreScript, 12, 0,
 			2, "SS Warlock:DATA:WARLOCKSHIP:Up.GCGunner", ""},
-	{"warlock", "", kPlatformWindows, "WRLCKSHP/UpForeECall", kScoreScript, 12,
+	{"warlock", "", kPlatformWindows, "WRLCKSHP/UpForeECall", kScoreScript, 12, 0,
 			3, "Channels 17 to 18", ""},
-	{"warlock", "", kPlatformWindows, "WRLCKSHP/UpForeECall", kScoreScript, 12,
+	{"warlock", "", kPlatformWindows, "WRLCKSHP/UpForeECall", kScoreScript, 12, 0,
 			4, "Frames 150 to 160", ""},
 
 	// Missing '&'
-	{"warlock", nullptr, kPlatformUnknown, "NAV/Shared Cast", kMovieScript, 510,
+	{"warlock", nullptr, kPlatformUnknown, "NAV/Shared Cast", kMovieScript, 510, 0,
 			23, "alert \"Failed Save.\" & return & \"Error message number: \" string ( filer )",
 				"alert \"Failed Save.\" & return & \"Error message number: \" & string ( filer )"},
 
 
 	// Patching dead loop which was fixed in v2
-	{"lzone", "", kPlatformMacintosh, "DATA/R-A/Ami-00", kScoreScript, 3,
+	{"lzone", "", kPlatformMacintosh, "DATA/R-A/Ami-00", kScoreScript, 3, 0,
 			2, "continue", "go \"OUT\""},
 
 	// Garbage at end of statements
-	{"lzone", "", kPlatformMacintosh, "DATA/R-E/ZD2-LAS", kScoreScript, 7,
+	{"lzone", "", kPlatformMacintosh, "DATA/R-E/ZD2-LAS", kScoreScript, 7, 0,
 			4, "go to the frame 0", "go to the frame"},
-	{"lzone", "", kPlatformMacintosh, "DATA/R-E/zd1-con1", kScoreScript, 27,
+	{"lzone", "", kPlatformMacintosh, "DATA/R-E/zd1-con1", kScoreScript, 27, 0,
 			1, "go to the frame 0", "go to the frame"},
-	{"lzone", "", kPlatformMacintosh, "DATA/R-E/zd1-con1", kScoreScript, 30,
+	{"lzone", "", kPlatformMacintosh, "DATA/R-E/zd1-con1", kScoreScript, 30, 0,
 			4, "go the frame 0", "go to the frame"},
-	{"lzone", "", kPlatformMacintosh, "DATA/R-G/st-c", kScoreScript, 14,
+	{"lzone", "", kPlatformMacintosh, "DATA/R-G/st-c", kScoreScript, 14, 0,
 			1, "go to the frame 0", "go to the frame"},
-	{"lzone", "", kPlatformMacintosh, "DATA/R-G/st-d.mo", kScoreScript, 4,
+	{"lzone", "", kPlatformMacintosh, "DATA/R-G/st-d.mo", kScoreScript, 4, 0,
 			1, "go to the frame 0", "go to the frame"},
-	{"lzone", "", kPlatformMacintosh, "DATA/R-F/ARCH-U.D-1", kScoreScript, 8,
+	{"lzone", "", kPlatformMacintosh, "DATA/R-F/ARCH-U.D-1", kScoreScript, 8, 0,
 			1, "GO \"SPACE\" OF MOVIE \"L-ZONE:DATA:R-G:ST-A2\",\"242,197\"",
 			   "GO \"SPACE\" OF MOVIE \"L-ZONE:DATA:R-G:ST-A2\""},
 
 
-	{"jman", "", kPlatformWindows, "mmm/Mars Space Game 05", kMovieScript, 10,
+	{"jman", "", kPlatformWindows, "mmm/Mars Space Game 05", kMovieScript, 10, 0,
 			68, "set DamageParameter = (gProcessorSpeed/2) + 7)", "set DamageParameter = (gProcessorSpeed/2) + 7"},
 
-	{nullptr, nullptr, kPlatformUnknown, nullptr, kNoneScript, 0, 0, nullptr, nullptr}
+	{nullptr, nullptr, kPlatformUnknown, nullptr, kNoneScript, 0, 0, 0, nullptr, nullptr}
 };
 
-Common::String LingoCompiler::patchLingoCode(Common::String &line, LingoArchive *archive, ScriptType type, uint16 id, int linenum) {
+Common::String LingoCompiler::patchLingoCode(Common::String &line, LingoArchive *archive, ScriptType type, CastMemberID id, int linenum) {
 	if (!archive)
 		return line;
 
@@ -156,7 +157,7 @@ Common::String LingoCompiler::patchLingoCode(Common::String &line, LingoArchive
 	// So far, we have not many patches, so do linear lookup
 	while (patch->gameId) {
 		// First, we do cheap comparisons
-		if (patch->type != type || patch->id != id || patch->linenum != linenum ||
+		if (patch->type != type || patch->id != id.member || patch->castLib != id.castLib || patch->linenum != linenum ||
 				(patch->platform != kPlatformUnknown && patch->platform != g_director->getPlatform())) {
 			patch++;
 			continue;
@@ -171,15 +172,15 @@ Common::String LingoCompiler::patchLingoCode(Common::String &line, LingoArchive
 
 		// Now do a safeguard
 		if (!line.contains(patch->orig)) {
-			warning("Lingo::patchLingoCode(): Unmatched patch for '%s', '%s' %s:%d @ %d. Expecting '%s' but got '%s'",
-					patch->gameId, patch->movie, scriptType2str(type), id, linenum,
+			warning("Lingo::patchLingoCode(): Unmatched patch for '%s', '%s' %s:%s @ %d. Expecting '%s' but got '%s'",
+					patch->gameId, patch->movie, scriptType2str(type), id.asString().c_str(), linenum,
 					patch->orig, line.c_str());
 			return line;
 		}
 
 		// Now everything matched
-		warning("Lingo::patchLingoCode(): Applied a patch for '%s', '%s' %s:%d @ %d. \"%s\" -> \"%s\"",
-				patch->gameId, patch->movie, scriptType2str(type), id, linenum,
+		warning("Lingo::patchLingoCode(): Applied a patch for '%s', '%s' %s:%s @ %d. \"%s\" -> \"%s\"",
+				patch->gameId, patch->movie, scriptType2str(type), id.asString().c_str(), linenum,
 				patch->orig, patch->replace);
 		return patch->replace;
 	}
diff --git a/engines/director/lingo/lingo-preprocessor.cpp b/engines/director/lingo/lingo-preprocessor.cpp
index a3e6a020b6..bdba2df9d5 100644
--- a/engines/director/lingo/lingo-preprocessor.cpp
+++ b/engines/director/lingo/lingo-preprocessor.cpp
@@ -90,7 +90,7 @@ static const char *findtokstart(const char *start, const char *token) {
 	return ptr;
 }
 
-Common::String LingoCompiler::codePreprocessor(const char *s, LingoArchive *archive, ScriptType type, uint16 id, bool simple) {
+Common::String LingoCompiler::codePreprocessor(const char *s, LingoArchive *archive, ScriptType type, CastMemberID id, bool simple) {
 	Common::String res;
 
 	// We start from processing the continuation synbols
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 9c5d1e2dd2..0472f2a7ee 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -265,7 +265,7 @@ void LingoArchive::addCode(const char *code, ScriptType type, uint16 id, const c
 	else
 		contextName = Common::String::format("%d", id);
 
-	ScriptContext *sc = g_lingo->_compiler->compileLingo(code, this, type, id, contextName);
+	ScriptContext *sc = g_lingo->_compiler->compileLingo(code, this, type, CastMemberID(id, cast->_castLibID), contextName);
 	if (sc) {
 		scriptContexts[type][id] = sc;
 		*sc->_refCount += 1;




More information about the Scummvm-git-logs mailing list