[Scummvm-git-logs] scummvm master -> fd119949ec323e943c81ed8b30cfcb5262a34907
djsrv
dservilla at gmail.com
Thu Jul 2 02:07:43 UTC 2020
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
38d17341e2 DIRECTOR: LINGO: Move lingo archive to Cast
fd119949ec DIRECTOR: LINGO: Add temp fix for D4 factories
Commit: 38d17341e29bf0757438b74bdbf54012205eb10e
https://github.com/scummvm/scummvm/commit/38d17341e29bf0757438b74bdbf54012205eb10e
Author: djsrv (dservilla at gmail.com)
Date: 2020-07-01T22:07:13-04:00
Commit Message:
DIRECTOR: LINGO: Move lingo archive to Cast
Changed paths:
engines/director/cast.cpp
engines/director/cast.h
engines/director/director.cpp
engines/director/lingo/lingo-builtins.cpp
engines/director/lingo/lingo-bytecode.cpp
engines/director/lingo/lingo-code.cpp
engines/director/lingo/lingo-codegen.cpp
engines/director/lingo/lingo-events.cpp
engines/director/lingo/lingo-the.cpp
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
engines/director/lingo/xlibs/fileio.cpp
engines/director/movie.cpp
engines/director/movie.h
engines/director/resource.cpp
engines/director/score.cpp
engines/director/sprite.cpp
engines/director/types.h
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 3101a76593..83f62fb07e 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -64,7 +64,7 @@ Cast::Cast(DirectorEngine *vm, Movie *movie) {
_lingo = _vm->getLingo();
_movie = movie;
- _lingoArchive = _movie ? kArchMain : kArchShared;
+ _lingoArchive = new LingoArchive;
_movieScriptCount = 0;
_castArrayStart = _castArrayEnd = 0;
@@ -94,6 +94,19 @@ Cast::~Cast() {
delete _loadedStxts;
delete _loadedCast;
+
+ for (int i = 0; i <= kMaxScriptType; i++) {
+ for (ScriptContextHash::iterator it = _lingoArchive->scriptContexts[i].begin(); it != _lingoArchive->scriptContexts[i].end(); ++it) {
+ it->_value->_eventHandlers.clear();
+ it->_value->_functionHandlers.clear();
+ delete it->_value;
+ }
+
+ _lingoArchive->scriptContexts[i].clear();
+ }
+ _lingoArchive->names.clear();
+ _lingoArchive->functionHandlers.clear();
+ delete _lingoArchive;
}
CastMember *Cast::getCastMember(int castId) {
@@ -836,7 +849,7 @@ void Cast::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
if (ConfMan.getBool("dump_scripts"))
dumpScript(ci->script.c_str(), scriptType, id);
- _lingo->addCode(ci->script.c_str(), _lingoArchive, scriptType, id, ci->name.c_str());
+ _lingoArchive->addCode(ci->script.c_str(), scriptType, id, ci->name.c_str());
}
}
@@ -849,7 +862,7 @@ void Cast::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
void Cast::loadLingoNames(Common::SeekableSubReadStreamEndian &stream) {
if (_vm->getVersion() >= 4) {
- _lingo->addNamesV4(stream, _lingoArchive);
+ _lingoArchive->addNamesV4(stream);
} else {
error("Cast::loadLingoNames: unsuported Director version (%d)", _vm->getVersion());
}
@@ -894,7 +907,7 @@ void Cast::loadLingoContext(Common::SeekableSubReadStreamEndian &stream) {
for (Common::Array<int16>::iterator iterator = lscr.begin(); iterator != lscr.end(); ++iterator) {
if (*iterator >= 0) {
Common::SeekableSubReadStreamEndian *r;
- _lingo->addCodeV4(*(r = _castArchive->getResource(MKTAG('L', 's', 'c', 'r'), *iterator)), _lingoArchive, _macName);
+ _lingoArchive->addCodeV4(*(r = _castArchive->getResource(MKTAG('L', 's', 'c', 'r'), *iterator)), _macName);
delete r;
}
}
@@ -930,7 +943,7 @@ void Cast::loadScriptText(Common::SeekableSubReadStreamEndian &stream) {
if (script.contains("\nmenu:") || script.hasPrefix("menu:"))
return;
- _lingo->addCode(script.c_str(), _lingoArchive, kMovieScript, _movieScriptCount);
+ _lingoArchive->addCode(script.c_str(), kMovieScript, _movieScriptCount);
_movieScriptCount++;
}
@@ -961,7 +974,7 @@ void Cast::loadCastInfo(Common::SeekableSubReadStreamEndian &stream, uint16 id)
dumpScript(ci->script.c_str(), kCastScript, id);
if (!ci->script.empty())
- _lingo->addCode(ci->script.c_str(), _lingoArchive, kCastScript, id, ci->name.c_str());
+ _lingoArchive->addCode(ci->script.c_str(), kCastScript, id, ci->name.c_str());
ci->name = getString(castStrings[1]);
ci->directory = getString(castStrings[2]);
diff --git a/engines/director/cast.h b/engines/director/cast.h
index b7b2eb594d..f416397ec3 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -38,6 +38,7 @@ struct CastMemberInfo;
class CastMember;
class DirectorEngine;
class Lingo;
+struct LingoArchive;
struct Resource;
class Stxt;
class BitmapCastMember;
@@ -92,7 +93,7 @@ public:
uint16 _castArrayEnd;
uint16 _movieScriptCount;
- int _lingoArchive;
+ LingoArchive *_lingoArchive;
private:
DirectorEngine *_vm;
diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index a7835501fb..a2cbfafddd 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -164,9 +164,6 @@ Common::Error DirectorEngine::run() {
//_mainArchive = new RIFFArchive();
//_mainArchive->openFile("bookshelf_example.mmm");
- _currentMovie = new Movie(this);
- _currentPath = getPath(getEXEName(), _currentPath);
-
if (getPlatform() == Common::kPlatformWindows)
_machineType = 256; // IBM PC-type machine
@@ -184,8 +181,6 @@ Common::Error DirectorEngine::run() {
_sharedCastFile = "Shared.dir";
}
- _currentMovie->loadSharedCastsFrom(_currentPath + _sharedCastFile);
-
debug(0, "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\nObtaining score name\n");
if (getGameGID() == GID_TESTALL) {
@@ -306,13 +301,12 @@ Common::Error DirectorEngine::run() {
_currentMovie->setArchive(mov);
debug(0, "Switching to movie '%s'", _currentMovie->getMacName().c_str());
+ _lingo->resetLingo();
if (sharedCast && sharedCast->_castArchive
&& sharedCast->_castArchive->getFileName().equalsIgnoreCase(_currentPath + _sharedCastFile)) {
- _lingo->resetLingo(true);
_currentMovie->_sharedCast = sharedCast;
} else {
delete sharedCast;
- _lingo->resetLingo(false);
_currentMovie->loadSharedCastsFrom(_currentPath + _sharedCastFile);
}
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 428d043deb..7af9ed594f 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1633,8 +1633,9 @@ void LB::b_installMenu(int nargs) {
menu->createSubMenuFromString(submenu, submenuText.c_str(), 0);
}
- // TODO: Menu callbacks should probably not be in the movie's lingo archive
- g_lingo->addCode(handlers.c_str(), kArchMain, kMovieScript, 1337);
+ // TODO: Menu callbacks should probably not be defined as a movie script
+ LingoArchive *mainArchive = g_director->getCurrentMovie()->getMainLingoArch();
+ mainArchive->addCode(handlers.c_str(), kMovieScript, 1337);
}
Common::String Lingo::genMenuHandler(int *commandId, Common::String &command) {
@@ -2191,11 +2192,11 @@ void LB::b_script(int nargs) {
if (cast->_type == kCastLingoScript) {
// script cast can be either a movie script or score script
- script = g_lingo->getScriptContext(cast->_cast->_lingoArchive, kMovieScript, castId);
+ script = g_director->getCurrentMovie()->getScriptContext(kMovieScript, castId);
if (!script)
- script = g_lingo->getScriptContext(cast->_cast->_lingoArchive, kScoreScript, castId);
+ script = g_director->getCurrentMovie()->getScriptContext(kScoreScript, castId);
} else {
- script = g_lingo->getScriptContext(cast->_cast->_lingoArchive, kCastScript, castId);
+ g_director->getCurrentMovie()->getScriptContext(kCastScript, castId);
}
if (script) {
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 4154701291..182a4b45db 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -498,7 +498,7 @@ void LC::cb_proplist() {
void LC::cb_call() {
int nameId = g_lingo->readInt();
- Common::String name = g_lingo->getName(nameId);
+ Common::String name = g_lingo->_currentArchive->getName(nameId);
Datum nargs = g_lingo->pop();
if ((nargs.type == ARGC) || (nargs.type == ARGCNORET)) {
@@ -513,7 +513,7 @@ void LC::cb_call() {
void LC::cb_globalpush() {
int nameId = g_lingo->readInt();
- Common::String name = g_lingo->getName(nameId);
+ Common::String name = g_lingo->_currentArchive->getName(nameId);
Datum target(name);
target.type = VAR;
debugC(3, kDebugLingoExec, "cb_globalpush: pushing %s to stack", name.c_str());
@@ -524,7 +524,7 @@ void LC::cb_globalpush() {
void LC::cb_globalassign() {
int nameId = g_lingo->readInt();
- Common::String name = g_lingo->getName(nameId);
+ Common::String name = g_lingo->_currentArchive->getName(nameId);
Datum target(name);
target.type = VAR;
debugC(3, kDebugLingoExec, "cb_globalassign: assigning to %s", name.c_str());
@@ -538,7 +538,7 @@ void LC::cb_globalassign() {
void LC::cb_objectfieldassign() {
int fieldNameId = g_lingo->readInt();
- Common::String fieldName = g_lingo->getName(fieldNameId);
+ Common::String fieldName = g_lingo->_currentArchive->getName(fieldNameId);
Datum object = g_lingo->pop();
Datum value = g_lingo->pop();
g_lingo->setObjectProp(object, fieldName, value);
@@ -546,14 +546,14 @@ void LC::cb_objectfieldassign() {
void LC::cb_objectfieldpush() {
int fieldNameId = g_lingo->readInt();
- Common::String fieldName = g_lingo->getName(fieldNameId);
+ Common::String fieldName = g_lingo->_currentArchive->getName(fieldNameId);
Datum object = g_lingo->pop();
g_lingo->push(g_lingo->getObjectProp(object, fieldName));
}
void LC::cb_objectpush() {
int nameId = g_lingo->readInt();
- Common::String name = g_lingo->getName(nameId);
+ Common::String name = g_lingo->_currentArchive->getName(nameId);
Datum result(name);
result.type = SYMBOL;
g_lingo->push(result);
@@ -561,7 +561,7 @@ void LC::cb_objectpush() {
void LC::cb_tellcall() {
int nameId = g_lingo->readInt();
- Common::String name = g_lingo->getName(nameId);
+ Common::String name = g_lingo->_currentArchive->getName(nameId);
warning("STUB: cb_tellcall(%s)", name.c_str());
Datum nargs = g_lingo->pop();
@@ -578,7 +578,7 @@ void LC::cb_tellcall() {
void LC::cb_theassign() {
int nameId = g_lingo->readInt();
- Common::String name = g_lingo->getName(nameId);
+ Common::String name = g_lingo->_currentArchive->getName(nameId);
Datum value = g_lingo->pop();
if (g_lingo->_currentMe.type == OBJECT) {
if (g_lingo->_currentMe.u.obj->hasProp(name)) {
@@ -593,14 +593,14 @@ void LC::cb_theassign() {
void LC::cb_theassign2() {
int nameId = g_lingo->readInt();
- Common::String name = g_lingo->getName(nameId);
+ Common::String name = g_lingo->_currentArchive->getName(nameId);
Datum value = g_lingo->pop();
warning("STUB: cb_theassign2(%s, %s)", name.c_str(), value.asString().c_str());
}
void LC::cb_thepush() {
int nameId = g_lingo->readInt();
- Common::String name = g_lingo->getName(nameId);
+ Common::String name = g_lingo->_currentArchive->getName(nameId);
if (g_lingo->_currentMe.type == OBJECT) {
if (g_lingo->_currentMe.u.obj->hasProp(name)) {
g_lingo->push(g_lingo->_currentMe.u.obj->getProp(name));
@@ -618,7 +618,7 @@ void LC::cb_thepush() {
void LC::cb_thepush2() {
int nameId = g_lingo->readInt();
Datum result;
- Common::String name = g_lingo->getName(nameId);
+ Common::String name = g_lingo->_currentArchive->getName(nameId);
if (g_lingo->_theEntities.contains(name)) {
TheEntity *entity = g_lingo->_theEntities[name];
Datum id;
@@ -635,7 +635,7 @@ void LC::cb_thepush2() {
void LC::cb_varpush() {
int nameId = g_lingo->readInt();
- Common::String name = g_lingo->getName(nameId);
+ Common::String name = g_lingo->_currentArchive->getName(nameId);
Datum target(name);
target.type = VAR;
debugC(3, kDebugLingoExec, "cb_varpush: pushing %s to stack", name.c_str());
@@ -646,7 +646,7 @@ void LC::cb_varpush() {
void LC::cb_varassign() {
int nameId = g_lingo->readInt();
- Common::String name = g_lingo->getName(nameId);
+ Common::String name = g_lingo->_currentArchive->getName(nameId);
Datum target(name);
target.type = VAR;
debugC(3, kDebugLingoExec, "cb_varassign: assigning to %s", name.c_str());
@@ -732,7 +732,7 @@ void LC::cb_v4theentitynamepush() {
}
int nameId = g_lingo->readInt();
- Common::String name = g_lingo->getName(nameId);
+ Common::String name = g_lingo->_currentArchive->getName(nameId);
Datum id;
id.u.s = NULL;
@@ -817,10 +817,10 @@ void LC::cb_zeropush() {
g_lingo->push(d);
}
-void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIndex, const Common::String &archName) {
+ScriptContext *Lingo::compileLingoV4(Common::SeekableSubReadStreamEndian &stream, LingoArchive *archive, const Common::String &archName) {
if (stream.size() < 0x5c) {
warning("Lscr header too small");
- return;
+ return nullptr;
}
if (debugChannelSet(5, kDebugLoading)) {
@@ -894,15 +894,16 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
castName = info->name;
}
- _assemblyArchive = archiveIndex;
+ _assemblyArchive = archive;
+ ScriptContext *sc = nullptr;
Common::String factoryName;
if (scriptFlags & kScriptFlagFactoryDef) {
- if (0 <= factoryNameId && factoryNameId < (int16)_archives[_assemblyArchive].names.size()) {
- factoryName = _archives[_assemblyArchive].names[factoryNameId];
+ if (0 <= factoryNameId && factoryNameId < (int16)archive->names.size()) {
+ factoryName = archive->names[factoryNameId];
} else {
warning("Factory %d has unknown name id %d, skipping define", castId, factoryNameId);
- return;
+ return nullptr;
}
debugC(1, kDebugCompile, "Add V4 bytecode for factory '%s' with id %d", factoryName.c_str(), castId);
@@ -911,29 +912,28 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
} else {
debugC(1, kDebugCompile, "Add V4 bytecode for type %s with id %d", scriptType2str(scriptType), castId);
- if (getScriptContext(archiveIndex, scriptType, castId)) {
+ if (archive->getScriptContext(scriptType, castId)) {
// We can't undefine context data because it could be used in e.g. symbols.
// Abort on double definitions.
error("Script already defined for type %d, id %d", scriptType, castId);
- return;
+ return nullptr;
}
- _assemblyContext = new ScriptContext(scriptType, !castName.empty() ? castName : Common::String::format("%d", castId));
- _archives[_assemblyArchive].scriptContexts[scriptType][castId] = _assemblyContext;
+ sc = _assemblyContext = new ScriptContext(!castName.empty() ? castName : Common::String::format("%d", castId), _assemblyArchive, scriptType, castId);
}
// initialise each property
if ((uint32)stream.size() < propertiesOffset + propertiesCount * 2) {
warning("Lscr properties store missing");
- return;
+ return nullptr;
}
debugC(5, kDebugLoading, "Lscr property list:");
stream.seek(propertiesOffset);
for (uint16 i = 0; i < propertiesCount; i++) {
int16 index = stream.readSint16();
- if (0 <= index && index < (int16)_archives[_assemblyArchive].names.size()) {
- const char *name = _archives[_assemblyArchive].names[index].c_str();
+ if (0 <= index && index < (int16)archive->names.size()) {
+ const char *name = archive->names[index].c_str();
debugC(5, kDebugLoading, "%d: %s", i, name);
if (scriptFlags & kScriptFlagFactoryDef) {
_currentFactory->properties[name] = Datum();
@@ -948,15 +948,15 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
// initialise each global variable
if ((uint32)stream.size() < globalsOffset + globalsCount * 2) {
warning("Lscr globals store missing");
- return;
+ return nullptr;
}
debugC(5, kDebugLoading, "Lscr globals list:");
stream.seek(globalsOffset);
for (uint16 i = 0; i < globalsCount; i++) {
int16 index = stream.readSint16();
- if (0 <= index && index < (int16)_archives[_assemblyArchive].names.size()) {
- const char *name = _archives[_assemblyArchive].names[index].c_str();
+ if (0 <= index && index < (int16)archive->names.size()) {
+ const char *name = archive->names[index].c_str();
debugC(5, kDebugLoading, "%d: %s", i, name);
if (!_globalvars.contains(name)) {
_globalvars[name] = Datum();
@@ -976,7 +976,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
if ((uint32)stream.size() < constsStoreOffset) {
warning("Lscr consts store missing");
- return;
+ return nullptr;
}
stream.seek(constsStoreOffset);
@@ -1101,7 +1101,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
// copy the storage area first.
if ((uint32)stream.size() < functionsOffset) {
warning("Lscr functions store missing");
- return;
+ return nullptr;
}
uint32 codeStoreSize = functionsOffset - codeStoreOffset;
@@ -1171,19 +1171,19 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
int16 index = READ_BE_INT16(&codeStore[namePointer]);
namePointer += 2;
Common::String name;
- if (0 <= index && index < (int16)_archives[_assemblyArchive].names.size()) {
- name = _archives[_assemblyArchive].names[index];
+ if (0 <= index && index < (int16)archive->names.size()) {
+ name = archive->names[index];
argMap[j] = index;
} else if (j == 0 && (scriptFlags & kScriptFlagFactoryDef)) {
name = "me";
// find or add "me" in the names list
- for (index = 0; index < (int16)_archives[_assemblyArchive].names.size(); index++) {
- if (_archives[_assemblyArchive].names[index].equalsIgnoreCase(name))
+ for (index = 0; index < (int16)archive->names.size(); index++) {
+ if (archive->names[index].equalsIgnoreCase(name))
break;
}
- if (index == (int16)_archives[_assemblyArchive].names.size())
- _archives[_assemblyArchive].names.push_back(name);
+ if (index == (int16)archive->names.size())
+ archive->names.push_back(name);
argMap[j] = index;
} else {
@@ -1209,8 +1209,8 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
int16 index = READ_BE_INT16(&codeStore[namePointer]);
namePointer += 2;
Common::String name;
- if (0 <= index && index < (int16)_archives[_assemblyArchive].names.size()) {
- name = _archives[_assemblyArchive].names[index];
+ if (0 <= index && index < (int16)archive->names.size()) {
+ name = archive->names[index];
varMap[j] = index;
} else {
name = Common::String::format("var_%d", j);
@@ -1396,9 +1396,9 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
// Attach to handlers
Symbol sym;
- if (0 <= nameIndex && nameIndex < (int16)_archives[_assemblyArchive].names.size()) {
- debugC(5, kDebugLoading, "Function %d binding: %s()", i, _archives[_assemblyArchive].names[nameIndex].c_str());
- sym = g_lingo->define(_archives[_assemblyArchive].names[nameIndex], argCount, _currentAssembly, argNames, varNames);
+ if (0 <= nameIndex && nameIndex < (int16)archive->names.size()) {
+ debugC(5, kDebugLoading, "Function %d binding: %s()", i, archive->names[nameIndex].c_str());
+ sym = _assemblyContext->define(archive->names[nameIndex], argCount, _currentAssembly, argNames, varNames);
} else {
warning("Function has unknown name id %d, skipping define", nameIndex);
sym.name = new Common::String();
@@ -1411,8 +1411,8 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
}
if (!skipdump && ConfMan.getBool("dump_scripts")) {
- if (0 <= nameIndex && nameIndex < (int16)_archives[_assemblyArchive].names.size())
- out.writeString(Common::String::format("function %s, %d args\n", _archives[_assemblyArchive].names[nameIndex].c_str(), argCount));
+ if (0 <= nameIndex && nameIndex < (int16)archive->names.size())
+ out.writeString(Common::String::format("function %s, %d args\n", archive->names[nameIndex].c_str(), argCount));
else
out.writeString(Common::String::format("<noname>, %d args\n", argCount));
@@ -1435,11 +1435,19 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
}
free(codeStore);
+ _assemblyContext = nullptr;
_currentFactory = nullptr;
+
+ return sc;
}
+void LingoArchive::addCodeV4(Common::SeekableSubReadStreamEndian &stream, const Common::String &archName) {
+ ScriptContext *ctx = g_lingo->compileLingoV4(stream, this, archName);
+ if (ctx)
+ scriptContexts[ctx->_type][ctx->_id] = ctx;
+}
-void Lingo::addNamesV4(Common::SeekableSubReadStreamEndian &stream, int archiveIndex) {
+void LingoArchive::addNamesV4(Common::SeekableSubReadStreamEndian &stream) {
debugC(1, kDebugCompile, "Add V4 script name index");
if (stream.size() < 0x14) {
@@ -1471,16 +1479,15 @@ void Lingo::addNamesV4(Common::SeekableSubReadStreamEndian &stream, int archiveI
stream.seek(offset);
- _archives[archiveIndex].names.clear();
+ names.clear();
- Common::Array<Common::String> names;
for (uint32 i = 0; i < count; i++) {
uint8 size = stream.readByte();
Common::String name;
for (uint8 j = 0; j < size; j++) {
name += stream.readByte();
}
- _archives[archiveIndex].names.push_back(name);
+ names.push_back(name);
debugC(5, kDebugLoading, "%d: \"%s\"", i, name.c_str());
}
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index d5be25d086..5f6dc5a644 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -215,7 +215,7 @@ void Lingo::pushContext(const Symbol funcSym, bool preserveVarFrame) {
fp->retpc = g_lingo->_pc;
fp->retscript = g_lingo->_currentScript;
fp->retctx = g_lingo->_currentScriptContext;
- fp->retarchive = g_lingo->_archiveIndex;
+ fp->retarchive = g_lingo->_currentArchive;
fp->localvars = g_lingo->_localvars;
fp->retMe = g_lingo->_currentMe;
fp->sp = funcSym;
@@ -225,11 +225,10 @@ void Lingo::pushContext(const Symbol funcSym, bool preserveVarFrame) {
g_lingo->_currentScriptContext = funcSym.ctx;
g_lingo->_currentMe = funcSym.ctx->_target; // reference-counted datum
}
- g_lingo->_archiveIndex = funcSym.archiveIndex;
+ g_lingo->_currentArchive = funcSym.archive;
- // Functions with an archiveIndex of -1 are anonymous.
- // Execute them within the current var frame.
- if (!preserveVarFrame && funcSym.archiveIndex >= 0)
+ // Execute anonymous functions within the current var frame.
+ if (!preserveVarFrame && !funcSym.anonymous)
g_lingo->_localvars = new DatumHash;
g_lingo->_callstack.push_back(fp);
@@ -244,19 +243,19 @@ void Lingo::popContext() {
CFrame *fp = g_lingo->_callstack.back();
g_lingo->_callstack.pop_back();
- // Destroy anonymous context
- if (g_lingo->_archiveIndex < 0) {
+ // Destroy anonymous function context
+ if (fp->sp.anonymous) {
delete g_lingo->_currentScriptContext;
}
g_lingo->_currentScript = fp->retscript;
g_lingo->_currentScriptContext = fp->retctx;
- g_lingo->_archiveIndex = fp->retarchive;
+ g_lingo->_currentArchive = fp->retarchive;
g_lingo->_pc = fp->retpc;
g_lingo->_currentMe = fp->retMe;
// Restore local variables
- if (fp->sp.archiveIndex >= 0) {
+ if (!fp->sp.anonymous) {
g_lingo->cleanLocalVars();
g_lingo->_localvars = fp->localvars;
}
@@ -351,7 +350,7 @@ void LC::c_symbolpush() {
void LC::c_namepush() {
Datum d;
int i = g_lingo->readInt();
- g_lingo->push(Datum(Common::String(g_lingo->getName(i))));
+ g_lingo->push(Datum(Common::String(g_lingo->_currentArchive->getName(i))));
}
void LC::c_argcpush() {
@@ -1456,7 +1455,7 @@ void LC::call(const Symbol &funcSym, int nargs) {
g_lingo->pushContext(funcSym, true);
DatumHash *localvars = g_lingo->_localvars;
- if (funcSym.archiveIndex >= 0) {
+ if (!funcSym.anonymous) {
// Create new set of local variables
// g_lingo->_localvars is not set until later so any lazy arguments
// can be evaluated within the current variable frame
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index 19f10d0924..a1186bcee9 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -62,7 +62,7 @@ void Lingo::cleanLocalVars() {
g_lingo->_localvars = nullptr;
}
-Symbol Lingo::define(Common::String &name, int nargs, ScriptData *code, Common::Array<Common::String> *argNames, Common::Array<Common::String> *varNames, Object *factory) {
+Symbol ScriptContext::define(Common::String &name, int nargs, ScriptData *code, Common::Array<Common::String> *argNames, Common::Array<Common::String> *varNames) {
Symbol sym;
sym.name = new Common::String(name);
sym.type = HANDLER;
@@ -71,36 +71,26 @@ Symbol Lingo::define(Common::String &name, int nargs, ScriptData *code, Common::
sym.maxArgs = nargs;
sym.argNames = argNames;
sym.varNames = varNames;
- sym.ctx = _assemblyContext;
- sym.archiveIndex = _assemblyArchive;
+ sym.ctx = this;
+ sym.archive = _archive;
if (debugChannelSet(1, kDebugCompile)) {
uint pc = 0;
while (pc < sym.u.defn->size()) {
uint spc = pc;
- Common::String instr = g_lingo->decodeInstruction(_assemblyArchive, sym.u.defn, pc, &pc);
+ Common::String instr = g_lingo->decodeInstruction(_archive, sym.u.defn, pc, &pc);
debugC(1, kDebugCompile, "[%5d] %s", spc, instr.c_str());
}
debugC(1, kDebugCompile, "<end define code>");
}
- if (factory) {
- if (factory->ctx->_functionHandlers.contains(name)) {
- warning("Redefining method '%s' on factory '%s'", name.c_str(), factory->name->c_str());
- }
- factory->ctx->_functionHandlers[name] = sym;
- } else if (_assemblyArchive >= 0) {
- Symbol existing = getHandler(name);
- if (existing.type != VOID)
- warning("Redefining handler '%s'", name.c_str());
-
- if (!_eventHandlerTypeIds.contains(name)) {
- if (_assemblyContext->_type == kMovieScript && !_archives[_assemblyArchive].functionHandlers.contains(name))
- _archives[_assemblyArchive].functionHandlers[name] = sym;
- _assemblyContext->_functionHandlers[name] = sym;
- } else {
- _assemblyContext->_eventHandlers[_eventHandlerTypeIds[name]] = sym;
+ if (!g_lingo->_eventHandlerTypeIds.contains(name)) {
+ _functionHandlers[name] = sym;
+ if (_type == kMovieScript && _archive && !_archive->functionHandlers.contains(name)) {
+ _archive->functionHandlers[name] = sym;
}
+ } else {
+ _eventHandlers[g_lingo->_eventHandlerTypeIds[name]] = sym;
}
return sym;
@@ -123,7 +113,9 @@ Symbol Lingo::codeDefine(Common::String &name, int start, int nargs, Object *fac
if (it->_value == kVarLocal)
varNames->push_back(Common::String(it->_key));
}
- Symbol sym = define(name, nargs, code, argNames, varNames, factory);
+
+ ScriptContext *ctx = factory ? factory->ctx : _assemblyContext;
+ Symbol sym = ctx->define(name, nargs, code, argNames, varNames);
if (debugChannelSet(1, kDebugCompile)) {
debug("Function vars");
@@ -292,7 +284,7 @@ void Lingo::varCreate(const Common::String &name, bool global, DatumHash *localv
}
void Lingo::codeFactory(Common::String &name) {
- ScriptContext *ctx = new ScriptContext(kNoneScript, name);
+ ScriptContext *ctx = new ScriptContext(name);
Object *obj = new Object(name, kFactoryObj, ctx);
_currentFactory = obj;
diff --git a/engines/director/lingo/lingo-events.cpp b/engines/director/lingo/lingo-events.cpp
index dc8b7c2464..9055127243 100644
--- a/engines/director/lingo/lingo-events.cpp
+++ b/engines/director/lingo/lingo-events.cpp
@@ -23,6 +23,7 @@
#include "director/director.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-code.h"
+#include "director/cast.h"
#include "director/movie.h"
#include "director/frame.h"
#include "director/score.h"
@@ -103,8 +104,9 @@ int Lingo::getEventCount() {
void Lingo::setPrimaryEventHandler(LEvent event, const Common::String &code) {
debugC(3, kDebugLingoExec, "setting primary event handler (%s)", _eventHandlerTypes[event]);
- _archives[kArchMain].primaryEventHandlers[event] = code;
- addCode(code.c_str(), kArchMain, kGlobalScript, event);
+ LingoArchive *mainArchive = g_director->getCurrentMovie()->getMainLingoArch();
+ mainArchive->primaryEventHandlers[event] = code;
+ mainArchive->addCode(code.c_str(), kGlobalScript, event);
}
void Lingo::queueSpriteEvent(LEvent event, int eventId, int spriteId) {
@@ -118,7 +120,8 @@ void Lingo::queueSpriteEvent(LEvent event, int eventId, int spriteId) {
* When more than one movie script [...]
* [D4 docs] */
- Score *score = _vm->getCurrentMovie()->getScore();
+ Movie *movie = _vm->getCurrentMovie();
+ Score *score = movie->getScore();
Frame *currentFrame = score->_frames[score->getCurrentFrame()];
assert(currentFrame != nullptr);
Sprite *sprite = score->getSpriteById(spriteId);
@@ -130,25 +133,20 @@ void Lingo::queueSpriteEvent(LEvent event, int eventId, int spriteId) {
// If sprite is immediate, its script is run on mouseDown, otherwise on mouseUp
if ((event == kEventMouseDown && sprite->_immediate)
|| (event == kEventMouseUp && !sprite->_immediate)) {
- _eventQueue.push(LingoEvent(kEventNone, eventId, kArchMain, kScoreScript, sprite->_scriptId, false, spriteId));
+ _eventQueue.push(LingoEvent(kEventNone, eventId, kScoreScript, sprite->_scriptId, false, spriteId));
}
} else {
- ScriptContext *script = getScriptContext(kArchMain, kScoreScript, sprite->_scriptId);
+ ScriptContext *script = movie->getScriptContext(kScoreScript, sprite->_scriptId);
if (script && script->_eventHandlers.contains(event)) {
- _eventQueue.push(LingoEvent(event, eventId, kArchMain, kScoreScript, sprite->_scriptId, false, spriteId));
+ _eventQueue.push(LingoEvent(event, eventId, kScoreScript, sprite->_scriptId, false, spriteId));
}
}
}
// Cast script
- int archiveIndex = kArchMain;
- ScriptContext *script = getScriptContext(archiveIndex, kCastScript, sprite->_castId);
- if (!script) {
- archiveIndex = kArchShared;
- script = getScriptContext(archiveIndex, kCastScript, sprite->_castId);
- }
+ ScriptContext *script = movie->getScriptContext(kCastScript, sprite->_castId);
if (script && script->_eventHandlers.contains(event)) {
- _eventQueue.push(LingoEvent(event, eventId, archiveIndex, kCastScript, sprite->_castId, false, spriteId));
+ _eventQueue.push(LingoEvent(event, eventId, kCastScript, sprite->_castId, false, spriteId));
}
}
@@ -160,7 +158,8 @@ void Lingo::queueFrameEvent(LEvent event, int eventId) {
* [p.81 of D4 docs]
*/
- Score *score = _vm->getCurrentMovie()->getScore();
+ Movie *movie = _vm->getCurrentMovie();
+ Score *score = movie->getScore();
// if (event == kEventPrepareFrame || event == kEventIdle) {
// entity = score->getCurrentFrame();
@@ -171,11 +170,11 @@ void Lingo::queueFrameEvent(LEvent event, int eventId) {
if (scriptId) {
if (event == kEventEnterFrame && _vm->getVersion() <= 3) {
- _eventQueue.push(LingoEvent(kEventNone, eventId, kArchMain, kScoreScript, scriptId, false));
+ _eventQueue.push(LingoEvent(kEventNone, eventId, kScoreScript, scriptId, false));
} else {
- ScriptContext *script = getScriptContext(kArchMain, kScoreScript, scriptId);
+ ScriptContext *script = movie->getScriptContext(kScoreScript, scriptId);
if (script && script->_eventHandlers.contains(event)) {
- _eventQueue.push(LingoEvent(event, eventId, kArchMain, kScoreScript, scriptId, false));
+ _eventQueue.push(LingoEvent(event, eventId, kScoreScript, scriptId, false));
}
}
}
@@ -188,18 +187,23 @@ void Lingo::queueMovieEvent(LEvent event, int eventId) {
*/
// FIXME: shared cast movie scripts could come before main movie ones
- for (ScriptContextHash::iterator it = _archives[kArchMain].scriptContexts[kMovieScript].begin();
- it != _archives[kArchMain].scriptContexts[kMovieScript].end(); ++it) {
+ Movie *movie = g_director->getCurrentMovie();
+ LingoArchive *mainArchive = movie->getMainLingoArch();
+ 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, kArchMain, kMovieScript, it->_key, false));
+ _eventQueue.push(LingoEvent(event, eventId, kMovieScript, it->_key, false));
return;
}
}
- for (ScriptContextHash::iterator it = _archives[kArchShared].scriptContexts[kMovieScript].begin();
- it != _archives[kArchShared].scriptContexts[kMovieScript].end(); ++it) {
- if (it->_value->_eventHandlers.contains(event)) {
- _eventQueue.push(LingoEvent(event, eventId, kArchShared, kMovieScript, it->_key, false));
- return;
+ LingoArchive *sharedArchive = movie->getSharedLingoArch();
+ if (sharedArchive) {
+ 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));
+ return;
+ }
}
}
}
@@ -228,8 +232,8 @@ void Lingo::registerEvent(LEvent event, int spriteId) {
case kEventKeyUp:
case kEventKeyDown:
case kEventTimeout:
- if (getScriptContext(kArchMain, kGlobalScript, event)) {
- _eventQueue.push(LingoEvent(kEventNone, eventId, kArchMain, kGlobalScript, event, true));
+ if (g_director->getCurrentMovie()->getScriptContext(kGlobalScript, event)) {
+ _eventQueue.push(LingoEvent(kEventNone, eventId, kGlobalScript, event, true));
}
break;
default:
@@ -320,25 +324,25 @@ void Lingo::processEvents() {
continue;
_passEvent = el.passByDefault;
- processEvent(el.event, el.archiveIndex, el.scriptType, el.scriptId, el.channelId);
+ processEvent(el.event, el.scriptType, el.scriptId, el.channelId);
lastEventId = el.eventId;
}
}
-void Lingo::processEvent(LEvent event, int archiveIndex, ScriptType st, int scriptId, int channelId) {
+void Lingo::processEvent(LEvent event, ScriptType st, int scriptId, int channelId) {
_currentChannelId = channelId;
if (!_eventHandlerTypes.contains(event))
error("processEvent: Unknown event %d", event);
- ScriptContext *script = getScriptContext(archiveIndex, st, scriptId);
+ ScriptContext *script = g_director->getCurrentMovie()->getScriptContext(st, scriptId);
if (script && script->_eventHandlers.contains(event)) {
- debugC(1, kDebugEvents, "Lingo::processEvent(%s, %d, %s, %d): executing event handler", _eventHandlerTypes[event], archiveIndex, scriptType2str(st), scriptId);
+ debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d): executing event handler", _eventHandlerTypes[event], scriptType2str(st), scriptId);
LC::call(script->_eventHandlers[event], 0);
execute(_pc);
} else {
- debugC(9, kDebugEvents, "Lingo::processEvent(%s, %d, %s, %d): no handler", _eventHandlerTypes[event], archiveIndex, scriptType2str(st), scriptId);
+ debugC(9, kDebugEvents, "Lingo::processEvent(%s, %s, %d): no handler", _eventHandlerTypes[event], scriptType2str(st), scriptId);
}
}
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 7c036d223c..7c5f40e346 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -342,6 +342,8 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
return d;
}
+ LingoArchive *mainArchive = _vm->getCurrentMovie()->getMainLingoArch();
+
switch (entity) {
case kTheCast:
d = getTheCast(id, field);
@@ -380,15 +382,15 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheKeyDownScript:
d.type = STRING;
- if (_archives[kArchMain].primaryEventHandlers.contains(kEventKeyDown))
- d.u.s = new Common::String(_archives[kArchMain].primaryEventHandlers[kEventKeyDown]);
+ if (mainArchive->primaryEventHandlers.contains(kEventKeyDown))
+ d.u.s = new Common::String(mainArchive->primaryEventHandlers[kEventKeyDown]);
else
d.u.s = new Common::String();
break;
case kTheKeyUpScript:
d.type = STRING;
- if (_archives[kArchMain].primaryEventHandlers.contains(kEventKeyUp))
- d.u.s = new Common::String(_archives[kArchMain].primaryEventHandlers[kEventKeyUp]);
+ if (mainArchive->primaryEventHandlers.contains(kEventKeyUp))
+ d.u.s = new Common::String(mainArchive->primaryEventHandlers[kEventKeyUp]);
else
d.u.s = new Common::String();
break;
@@ -482,8 +484,8 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheMouseDownScript:
d.type = STRING;
- if (_archives[kArchMain].primaryEventHandlers.contains(kEventMouseDown))
- d.u.s = new Common::String(_archives[kArchMain].primaryEventHandlers[kEventMouseDown]);
+ if (mainArchive->primaryEventHandlers.contains(kEventMouseDown))
+ d.u.s = new Common::String(mainArchive->primaryEventHandlers[kEventMouseDown]);
else
d.u.s = new Common::String();
break;
@@ -501,8 +503,8 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheMouseUpScript:
d.type = STRING;
- if (_archives[kArchMain].primaryEventHandlers.contains(kEventMouseUp))
- d.u.s = new Common::String(_archives[kArchMain].primaryEventHandlers[kEventMouseUp]);
+ if (mainArchive->primaryEventHandlers.contains(kEventMouseUp))
+ d.u.s = new Common::String(mainArchive->primaryEventHandlers[kEventMouseUp]);
else
d.u.s = new Common::String();
break;
@@ -573,8 +575,8 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheTimeoutScript:
d.type = STRING;
- if (_archives[kArchMain].primaryEventHandlers.contains(kEventTimeout))
- d.u.s = new Common::String(_archives[kArchMain].primaryEventHandlers[kEventTimeout]);
+ if (mainArchive->primaryEventHandlers.contains(kEventTimeout))
+ d.u.s = new Common::String(mainArchive->primaryEventHandlers[kEventTimeout]);
else
d.u.s = new Common::String();
break;
@@ -1119,9 +1121,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
warning("Lingo::setTheCast(): The cast %d not found. type: %d", id, castType);
return;
}
- // FIXME: What if the cast member is in a different archive than the current one?
- addCode(d.u.s->c_str(), _archiveIndex, kCastScript, id);
-
+ member->_cast->_lingoArchive->addCode(d.u.s->c_str(), kCastScript, id);
castInfo->script = d.asString();
break;
case kTheText:
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 0cb8a8870f..91ca1a03e5 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -55,7 +55,8 @@ Symbol::Symbol() {
argNames = nullptr;
varNames = nullptr;
ctx = nullptr;
- archiveIndex = kArchMain;
+ archive = nullptr;
+ anonymous = false;
}
Symbol::Symbol(const Symbol &s) {
@@ -71,7 +72,8 @@ Symbol::Symbol(const Symbol &s) {
argNames = s.argNames;
varNames = s.varNames;
ctx = s.ctx;
- archiveIndex = s.archiveIndex;
+ archive = s.archive;
+ anonymous = s.anonymous;
}
Symbol& Symbol::operator=(const Symbol &s) {
@@ -89,7 +91,8 @@ Symbol& Symbol::operator=(const Symbol &s) {
argNames = s.argNames;
varNames = s.varNames;
ctx = s.ctx;
- archiveIndex = s.archiveIndex;
+ archive = s.archive;
+ anonymous = s.anonymous;
}
return *this;
}
@@ -133,10 +136,11 @@ PCell::PCell(const Datum &prop, const Datum &val) {
Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
g_lingo = this;
+ _currentArchive = nullptr;
_currentScript = 0;
_currentScriptContext = nullptr;
- _assemblyArchive = 0;
+ _assemblyArchive = nullptr;
_currentAssembly = nullptr;
_assemblyContext = nullptr;
@@ -162,8 +166,6 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
_localvars = NULL;
- _archiveIndex = kArchMain;
-
// events
_nextEventId = 0;
_passEvent = false;
@@ -182,52 +184,41 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
}
Lingo::~Lingo() {
- resetLingo(false);
+ resetLingo();
cleanupBuiltins();
}
-ScriptContext *Lingo::getScriptContext(int archiveIndex, ScriptType type, uint16 id) {
- if (archiveIndex < 0)
- return NULL;
-
- if (!_archives[archiveIndex].scriptContexts[type].contains(id)) {
- return NULL;
+ScriptContext *LingoArchive::getScriptContext(ScriptType type, uint16 id) {
+ if (!scriptContexts[type].contains(id)) {
+ return nullptr;
}
-
- return _archives[archiveIndex].scriptContexts[type][id];
+ return scriptContexts[type][id];
}
-Common::String Lingo::getName(uint16 id) {
+Common::String LingoArchive::getName(uint16 id) {
Common::String result;
- if (id >= _archives[_archiveIndex].names.size()) {
+ if (id >= names.size()) {
warning("Name id %d not in list", id);
return result;
}
- result = _archives[_archiveIndex].names[id];
+ result = names[id];
return result;
}
Symbol Lingo::getHandler(const Common::String &name) {
- Symbol result;
if (!_eventHandlerTypeIds.contains(name)) {
// local functions
if (_currentScriptContext && _currentScriptContext->_functionHandlers.contains(name))
return _currentScriptContext->_functionHandlers[name];
- // local scripts
- if (_archives[kArchMain].functionHandlers.contains(name))
- return _archives[kArchMain].functionHandlers[name];
-
- // shared scripts
- if (_archives[kArchShared].functionHandlers.contains(name))
- return _archives[kArchShared].functionHandlers[name];
+ Symbol sym = g_director->getCurrentMovie()->getHandler(name);
+ if (sym.type != VOID)
+ return sym;
if (_builtins.contains(name))
return _builtins[name];
-
- return result;
}
- return result;
+ return Symbol();
}
const char *Lingo::findNextDefinition(const char *s) {
@@ -267,16 +258,11 @@ const char *Lingo::findNextDefinition(const char *s) {
return NULL;
}
-void Lingo::addCode(const char *code, int archiveIndex, ScriptType type, uint16 id, const char *scriptName) {
- if (_archiveIndex < 0) {
- warning("Lingo::addCode(): Invalid archiveIndex");
- return;
- }
-
+void LingoArchive::addCode(const char *code, ScriptType type, uint16 id, const char *scriptName) {
debugC(1, kDebugCompile, "Add code for type %s(%d) with id %d\n"
"***********\n%s\n\n***********", scriptType2str(type), type, id, code);
- if (getScriptContext(archiveIndex, type, id)) {
+ if (getScriptContext(type, id)) {
// We can't undefine context data because it could be used in e.g. symbols.
// Although it has a legit case when kTheScriptText re sets code.
// Warn on double definitions.
@@ -289,20 +275,20 @@ void Lingo::addCode(const char *code, int archiveIndex, ScriptType type, uint16
else
contextName = Common::String::format("%d", id);
- ScriptContext *sc = compileLingo(code, archiveIndex, type, id, contextName);
- _archives[_assemblyArchive].scriptContexts[type][id] = sc;
+ ScriptContext *sc = g_lingo->compileLingo(code, this, type, id, contextName);
+ scriptContexts[type][id] = sc;
}
ScriptContext *Lingo::compileAnonymous(const char *code) {
debugC(1, kDebugCompile, "Compiling anonymous lingo\n"
"***********\n%s\n\n***********", code);
- return compileLingo(code, kArchNone, kNoneScript, 0, "[anonymous]");
+ return compileLingo(code, nullptr, kNoneScript, 0, "[anonymous]", true);
}
-ScriptContext *Lingo::compileLingo(const char *code, int archiveIndex, ScriptType type, uint16 id, const Common::String &scriptName) {
- _assemblyArchive = archiveIndex;
- ScriptContext *sc = _assemblyContext = new ScriptContext(type, scriptName);
+ScriptContext *Lingo::compileLingo(const char *code, LingoArchive *archive, ScriptType type, uint16 id, const Common::String &scriptName, bool anonymous) {
+ _assemblyArchive = archive;
+ ScriptContext *sc = _assemblyContext = new ScriptContext(scriptName, archive, type, id);
_currentAssembly = new ScriptData;
_methodVars = new VarTypeHash;
@@ -393,7 +379,8 @@ ScriptContext *Lingo::compileLingo(const char *code, int archiveIndex, ScriptTyp
Common::String typeStr = Common::String(scriptType2str(type));
currentFunc.name = new Common::String("[" + typeStr + " " + _assemblyContext->_name + "]");
currentFunc.ctx = _assemblyContext;
- currentFunc.archiveIndex = _assemblyArchive;
+ currentFunc.archive = archive;
+ currentFunc.anonymous = anonymous;
// arg names should be empty, but just in case
Common::Array<Common::String> *argNames = new Common::Array<Common::String>;
for (uint i = 0; i < _argstack.size(); i++) {
@@ -423,9 +410,10 @@ ScriptContext *Lingo::compileLingo(const char *code, int archiveIndex, ScriptTyp
currentFunc.argNames = argNames;
currentFunc.varNames = varNames;
+ _currentAssembly = nullptr;
_assemblyContext->_eventHandlers[kEventNone] = currentFunc;
_assemblyContext = nullptr;
- _currentAssembly = nullptr;
+ _assemblyArchive = nullptr;
return sc;
}
@@ -460,7 +448,7 @@ void Lingo::printCallStack(uint pc) {
}
}
-Common::String Lingo::decodeInstruction(int archiveIndex, ScriptData *sd, uint pc, uint *newPc) {
+Common::String Lingo::decodeInstruction(LingoArchive *archive, ScriptData *sd, uint pc, uint *newPc) {
Symbol sym;
Common::String res;
@@ -527,7 +515,7 @@ Common::String Lingo::decodeInstruction(int archiveIndex, ScriptData *sd, uint p
i = (*sd)[pc++];
int v = READ_UINT32(&i);
- res += Common::String::format(" \"%s\"", _archives[archiveIndex].names[v].c_str());
+ res += Common::String::format(" \"%s\"", archive->names[v].c_str());
break;
}
default:
@@ -551,7 +539,7 @@ void Lingo::execute(uint pc) {
int counter = 0;
for (_pc = pc; !_abort && (*_currentScript)[_pc] != STOP;) {
- Common::String instr = decodeInstruction(_archiveIndex, _currentScript, _pc);
+ Common::String instr = decodeInstruction(_currentArchive, _currentScript, _pc);
uint current = _pc;
if (debugChannelSet(5, kDebugLingoExec))
@@ -593,7 +581,13 @@ void Lingo::execute(uint pc) {
}
void Lingo::executeScript(ScriptType type, uint16 id) {
- ScriptContext *sc = getScriptContext(_archiveIndex, type, id);
+ Movie *movie = _vm->getCurrentMovie();
+ if (!movie) {
+ warning("Request to execute script with no movie");
+ return;
+ }
+
+ ScriptContext *sc = movie->getScriptContext(type, id);
if (!sc) {
debugC(3, kDebugLingoExec, "Request to execute non-existant script type %d id %d", type, id);
@@ -614,28 +608,9 @@ void Lingo::executeHandler(const Common::String &name) {
execute(_pc);
}
-void Lingo::resetLingo(bool keepSharedCast) {
+void Lingo::resetLingo() {
debugC(3, kDebugLingoExec, "Resetting Lingo!");
- for (int a = 0; a < 2; a++) {
- if (a == 1 && keepSharedCast)
- continue;
-
- LingoArchive *arch = &_archives[a];
- for (int i = 0; i <= kMaxScriptType; i++) {
- for (ScriptContextHash::iterator it = arch->scriptContexts[i].begin(); it != arch->scriptContexts[i].end(); ++it) {
- it->_value->_eventHandlers.clear();
- it->_value->_functionHandlers.clear();
- delete it->_value;
- }
-
- arch->scriptContexts[i].clear();
- }
-
- arch->names.clear();
- arch->functionHandlers.clear();
- }
-
g_director->_wm->removeMenu();
// TODO
@@ -1085,6 +1060,8 @@ void Lingo::runTests() {
SearchMan.listMatchingMembers(fsList, "*.lingo");
Common::StringArray fileList;
+ LingoArchive *mainArchive = g_director->getCurrentMovie()->getMainLingoArch();
+
// Repurpose commandline option --start-movie to run a specific lingo script.
if (ConfMan.hasKey("start_movie")) {
fileList.push_back(ConfMan.get("start_movie"));
@@ -1109,7 +1086,7 @@ void Lingo::runTests() {
debug(">> Compiling file %s of size %d, id: %d", fileList[i].c_str(), size, counter);
_hadError = false;
- addCode(script, kArchMain, kMovieScript, counter);
+ mainArchive->addCode(script, kMovieScript, counter);
if (!debugChannelSet(-1, kDebugCompileOnly)) {
if (!_hadError)
@@ -1133,9 +1110,9 @@ void Lingo::executeImmediateScripts(Frame *frame) {
// From D5 only explicit event handlers are processed
// Before that you could specify commands which will be executed on mouse up
if (_vm->getVersion() < 5)
- g_lingo->processEvent(kEventNone, kArchMain, kScoreScript, frame->_sprites[i]->_scriptId, i);
+ g_lingo->processEvent(kEventNone, kScoreScript, frame->_sprites[i]->_scriptId, i);
else
- g_lingo->processEvent(kEventMouseUp, kArchMain, kScoreScript, frame->_sprites[i]->_scriptId, i);
+ g_lingo->processEvent(kEventMouseUp, kScoreScript, frame->_sprites[i]->_scriptId, i);
}
}
}
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 321d74619c..3b1da06c76 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -26,6 +26,8 @@
#include "common/hash-ptr.h"
#include "common/hash-str.h"
+#include "director/types.h"
+
namespace Audio {
class AudioStream;
}
@@ -37,6 +39,7 @@ namespace Director {
struct TheEntity;
struct TheEntityField;
+struct LingoArchive;
struct LingoV4Bytecode;
struct LingoV4TheEntity;
struct Object;
@@ -93,7 +96,8 @@ struct Symbol { /* symbol table entry */
Common::Array<Common::String> *argNames;
Common::Array<Common::String> *varNames;
ScriptContext *ctx; /* optional script context to execute with */
- int archiveIndex; /* optional archive to execute with */
+ LingoArchive *archive; /* optional archive to execute with */
+ bool anonymous;
Symbol();
Symbol(const Symbol &s);
@@ -168,8 +172,10 @@ typedef Common::HashMap<Common::String, TheEntityField *, Common::IgnoreCase_Has
class ScriptContext {
public:
- ScriptType _type;
Common::String _name;
+ LingoArchive *_archive;
+ ScriptType _type;
+ uint16 _id;
Common::Array<Common::String> _functionNames; // used by cb_localcall
SymbolHash _functionHandlers;
Common::HashMap<uint32, Symbol> _eventHandlers;
@@ -177,7 +183,8 @@ public:
Common::Array<Common::String> _propNames;
Datum _target;
- ScriptContext(ScriptType type, Common::String name) : _type(type), _name(name) {}
+ ScriptContext(Common::String name, LingoArchive *archive = nullptr, ScriptType type = kNoneScript, uint16 id = 0)
+ : _name(name), _archive(archive), _type(type), _id(id) {}
ScriptContext(const ScriptContext &sc) {
_type = sc._type;
_name = sc._name;
@@ -195,6 +202,7 @@ public:
}
Datum getParentScript();
+ Symbol define(Common::String &name, int nargs, ScriptData *code, Common::Array<Common::String> *argNames, Common::Array<Common::String> *varNames);
private:
Datum _parentScript;
@@ -274,9 +282,9 @@ struct Object {
struct CFrame { /* proc/func call stack frame */
Symbol sp; /* symbol table entry */
int retpc; /* where to resume after return */
- ScriptData *retscript; /* which script to resume after return */
- ScriptContext *retctx; /* which script context to use after return */
- int retarchive; /* which archive to use after return */
+ ScriptData *retscript; /* which script to resume after return */
+ ScriptContext *retctx; /* which script context to use after return */
+ LingoArchive *retarchive; /* which archive to use after return */
DatumHash *localvars;
Datum retMe; /* which me obj to use after return */
};
@@ -284,16 +292,14 @@ struct CFrame { /* proc/func call stack frame */
struct LingoEvent {
LEvent event;
int eventId;
- int archiveIndex;
ScriptType scriptType;
int scriptId;
bool passByDefault;
int channelId;
- LingoEvent (LEvent e, int ei, int ai, ScriptType st, int si, bool pass, int ci = -1) {
+ LingoEvent (LEvent e, int ei, ScriptType st, int si, bool pass, int ci = -1) {
event = e;
eventId = ei;
- archiveIndex = ai;
scriptType = st;
scriptId = si;
passByDefault = pass;
@@ -307,6 +313,13 @@ struct LingoArchive {
Common::Array<Common::String> names;
Common::HashMap<uint32, Common::String> primaryEventHandlers;
SymbolHash functionHandlers;
+
+ ScriptContext *getScriptContext(ScriptType type, uint16 id);
+ Common::String getName(uint16 id);
+
+ void addCode(const char *code, ScriptType type, uint16 id, const char *scriptName = nullptr);
+ void addCodeV4(Common::SeekableSubReadStreamEndian &stream, const Common::String &archName);
+ void addNamesV4(Common::SeekableSubReadStreamEndian &stream);
};
struct RepeatBlock {
@@ -320,17 +333,16 @@ public:
Lingo(DirectorEngine *vm);
~Lingo();
- void resetLingo(bool keepSharedCast);
+ void resetLingo();
- void addCode(const char *code, int archiveIndex, ScriptType type, uint16 id, const char *scriptName = nullptr);
ScriptContext *compileAnonymous(const char *code);
- void addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIndex, const Common::String &archName);
- void addNamesV4(Common::SeekableSubReadStreamEndian &stream, int archiveIndex);
+ ScriptContext *compileLingo(const char *code, LingoArchive *archive, ScriptType type, uint16 id, const Common::String &scriptName, bool anonyomous = false);
+ ScriptContext *compileLingoV4(Common::SeekableSubReadStreamEndian &stream, LingoArchive *archive, const Common::String &archName);
void executeHandler(const Common::String &name);
void executeScript(ScriptType type, uint16 id);
void printStack(const char *s, uint pc);
void printCallStack(uint pc);
- Common::String decodeInstruction(int archiveIndex, ScriptData *sd, uint pc, uint *newPC = NULL);
+ Common::String decodeInstruction(LingoArchive *archive, ScriptData *sd, uint pc, uint *newPC = NULL);
void initBuiltIns();
void cleanupBuiltins();
@@ -351,7 +363,6 @@ public:
// lingo.cpp
private:
- ScriptContext *compileLingo(const char *code, int archiveIndex, ScriptType type, uint16 id, const Common::String &scriptName);
const char *findNextDefinition(const char *s);
// lingo-events.cpp
@@ -361,14 +372,12 @@ private:
void queueSpriteEvent(LEvent event, int eventId, int spriteId);
void queueFrameEvent(LEvent event, int eventId);
void queueMovieEvent(LEvent event, int eventId);
- void processEvent(LEvent event, int archiveIndex, ScriptType st, int entityId, int channelId = -1);
+ void processEvent(LEvent event, ScriptType st, int entityId, int channelId = -1);
int _nextEventId;
Common::Queue<LingoEvent> _eventQueue;
public:
- ScriptContext *getScriptContext(int archiveIndex, ScriptType type, uint16 id);
- Common::String getName(uint16 id);
ScriptType event2script(LEvent ev);
Symbol getHandler(const Common::String &name);
@@ -473,11 +482,10 @@ public:
int codeInt(int val);
void codeLabel(int label);
int codeString(const char *s);
- Symbol define(Common::String &s, int nargs, ScriptData *code, Common::Array<Common::String> *argNames = nullptr, Common::Array<Common::String> *varNames = nullptr, Object *obj = nullptr);
void processIf(int toplabel, int endlabel);
void varCreate(const Common::String &name, bool global, DatumHash *localvars = nullptr);
- int _assemblyArchive;
+ LingoArchive *_assemblyArchive;
ScriptContext *_assemblyContext;
ScriptData *_currentAssembly;
LexerDefineState _indef;
@@ -500,6 +508,7 @@ public:
public:
int _currentChannelId;
+ LingoArchive *_currentArchive;
ScriptContext *_currentScriptContext;
ScriptData *_currentScript;
Datum _currentMe;
@@ -552,9 +561,6 @@ public:
Common::HashMap<int, LingoV4Bytecode *> _lingoV4;
Common::HashMap<int, LingoV4TheEntity *> _lingoV4TheEntity;
- LingoArchive _archives[2];
- int _archiveIndex;
-
uint _pc;
StackData _stack;
diff --git a/engines/director/lingo/xlibs/fileio.cpp b/engines/director/lingo/xlibs/fileio.cpp
index 8adb3a1762..bcd0eee72c 100644
--- a/engines/director/lingo/xlibs/fileio.cpp
+++ b/engines/director/lingo/xlibs/fileio.cpp
@@ -61,7 +61,7 @@ static struct MethodProto {
void FileIO::initialize(int type) {
if (type & kXObj) {
if (!g_lingo->_globalvars.contains(xlibName)) {
- ScriptContext *ctx = new ScriptContext(kNoneScript, Common::String(xlibName));
+ ScriptContext *ctx = new ScriptContext(Common::String(xlibName));
FileObject *xobj = new FileObject(kXObj, ctx);
xobj->initMethods();
g_lingo->_globalvars[xlibName] = xobj->ctx->_target;
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index 9c7e29cfd8..145cd93b49 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -189,7 +189,7 @@ void Movie::loadFileInfo(Common::SeekableSubReadStreamEndian &stream) {
_cast->dumpScript(_script.c_str(), kMovieScript, _cast->_movieScriptCount);
if (!_script.empty())
- _lingo->addCode(_script.c_str(), _cast->_lingoArchive, kMovieScript, _cast->_movieScriptCount);
+ _cast->_lingoArchive->addCode(_script.c_str(), kMovieScript, _cast->_movieScriptCount);
_cast->_movieScriptCount++;
_changedBy = fileInfoStrings[1];
@@ -245,4 +245,31 @@ const Stxt *Movie::getStxt(int castId) {
return result;
}
+LingoArchive *Movie::getMainLingoArch() {
+ return _cast->_lingoArchive;
+}
+
+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);
+ }
+ return result;
+}
+
+Symbol Movie::getHandler(const Common::String &name) {
+ if (!g_lingo->_eventHandlerTypeIds.contains(name)) {
+ if (_cast->_lingoArchive->functionHandlers.contains(name))
+ return _cast->_lingoArchive->functionHandlers[name];
+
+ if (_sharedCast && _sharedCast->_lingoArchive->functionHandlers.contains(name))
+ return _sharedCast->_lingoArchive->functionHandlers[name];
+ }
+ return Symbol();
+}
+
} // End of namespace Director
diff --git a/engines/director/movie.h b/engines/director/movie.h
index 3bd11705d5..37b8bcaddf 100644
--- a/engines/director/movie.h
+++ b/engines/director/movie.h
@@ -36,6 +36,9 @@ struct CastMemberInfo;
class CastMember;
class DirectorEngine;
class Lingo;
+struct LingoArchive;
+struct ScriptContext;
+struct Symbol;
class Movie {
public:
@@ -59,6 +62,11 @@ public:
CastMember *getCastMember(int castId);
const Stxt *getStxt(int castId);
+ LingoArchive *getMainLingoArch();
+ LingoArchive *getSharedLingoArch();
+ ScriptContext *getScriptContext(ScriptType type, uint16 id);
+ Symbol getHandler(const Common::String &name);
+
private:
void loadFileInfo(Common::SeekableSubReadStreamEndian &stream);
diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index 9b13aeb4c9..a7d13ceae9 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -29,6 +29,7 @@
#include "director/castmember.h"
#include "director/movie.h"
#include "director/lingo/lingo.h"
+#include "director/util.h"
namespace Director {
@@ -51,6 +52,10 @@ void DirectorEngine::loadInitialMovie(const Common::String movie) {
loadEXE(movie);
else
loadMac(movie);
+
+ _currentMovie = new Movie(this);
+ _currentPath = getPath(getEXEName(), _currentPath);
+ _currentMovie->loadSharedCastsFrom(_currentPath + _sharedCastFile);
}
Archive *DirectorEngine::openMainArchive(const Common::String movie) {
@@ -74,9 +79,13 @@ void DirectorEngine::loadEXE(const Common::String movie) {
if (iniStream) {
char *script = (char *)calloc(iniStream->size() + 1, 1);
iniStream->read(script, iniStream->size());
- _lingo->addCode(script, kArchMain, kMovieScript, 0);
+
+ _currentMovie = new Movie(this);
+ _currentMovie->getMainLingoArch()->addCode(script, kMovieScript, 0);
_lingo->processEvent(kEventStartUp);
- _lingo->resetLingo(true);
+ delete _currentMovie;
+ _currentMovie = nullptr;
+
free(script);
} else {
warning("No LINGO.INI");
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 3ce9567f13..74f9a6f174 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -904,7 +904,7 @@ void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) {
// continue;
}
if (!j->_value.empty()) {
- _lingo->addCode(j->_value.c_str(), _movie->getCast()->_lingoArchive, kScoreScript, j->_key);
+ _movie->getMainLingoArch()->addCode(j->_value.c_str(), kScoreScript, j->_key);
processImmediateFrameScript(j->_value, j->_key);
}
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index f99826b201..691199bdcf 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -82,8 +82,7 @@ bool Sprite::isActive() {
if (_moveable || _puppet || _scriptId)
return true;
- if (g_lingo->getScriptContext(kArchMain, kCastScript, _castId)
- || g_lingo->getScriptContext(kArchShared, kCastScript, _castId))
+ if (g_director->getCurrentMovie()->getScriptContext(kCastScript, _castId))
return true;
return false;
diff --git a/engines/director/types.h b/engines/director/types.h
index fb4454acd0..fd2bbfbb3a 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -261,12 +261,6 @@ enum {
kCursorMouseUp
};
-enum ArchiveType {
- kArchNone = -1,
- kArchMain = 0,
- kArchShared = 1
-};
-
struct Datum;
struct PCell;
typedef Common::Array<Datum> DatumArray;
Commit: fd119949ec323e943c81ed8b30cfcb5262a34907
https://github.com/scummvm/scummvm/commit/fd119949ec323e943c81ed8b30cfcb5262a34907
Author: djsrv (dservilla at gmail.com)
Date: 2020-07-01T22:07:13-04:00
Commit Message:
DIRECTOR: LINGO: Add temp fix for D4 factories
Changed paths:
engines/director/lingo/lingo-codegen.cpp
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index a1186bcee9..f3435d55d3 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -284,7 +284,9 @@ void Lingo::varCreate(const Common::String &name, bool global, DatumHash *localv
}
void Lingo::codeFactory(Common::String &name) {
- ScriptContext *ctx = new ScriptContext(name);
+ // FIXME: The factory's context should not be tied to the LingoArchive
+ // but bytecode needs it to resolve names
+ ScriptContext *ctx = new ScriptContext(name, _assemblyArchive);
Object *obj = new Object(name, kFactoryObj, ctx);
_currentFactory = obj;
More information about the Scummvm-git-logs
mailing list