DIRECTOR: LINGO: Reduce compile/execute var reuse

The compile/execute steps can and do happen at the same time, so this
makes things slightly less messy.
This commit is contained in:
djsrv
2020-06-14 17:09:39 -04:00
parent c66191bfef
commit a7cbe1fbd2
11 changed files with 69 additions and 61 deletions
+1 -1
View File
@@ -1617,7 +1617,7 @@ void LB::b_installMenu(int nargs) {
}
// TODO: Menu callbacks should probably not be in the movie's lingo archive
g_lingo->addCode(handlers.c_str(), kMovieScript, 1337);
g_lingo->addCode(handlers.c_str(), 0, kMovieScript, 1337);
}
Common::String Lingo::genMenuHandler(int *commandId, Common::String &command) {
+21 -20
View File
@@ -703,7 +703,7 @@ void LC::cb_zeropush() {
g_lingo->push(d);
}
void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType type, uint16 id, Common::String &archName) {
void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIndex, ScriptType type, uint16 id, Common::String &archName) {
debugC(1, kDebugCompile, "Add V4 bytecode for type %s with id %d", scriptType2str(type), id);
if (getScriptContext(type, id)) {
@@ -713,9 +713,10 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
return;
}
_currentScriptContext = new ScriptContext;
_assemblyArchive = archiveIndex;
_assemblyContext = new ScriptContext;
_currentEntityId = id;
_archives[_archiveIndex].scriptContexts[type][id] = _currentScriptContext;
_archives[_assemblyArchive].scriptContexts[type][id] = _assemblyContext;
if (stream.size() < 0x5c) {
warning("Lscr header too small");
@@ -764,8 +765,8 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
stream.seek(globalsOffset);
for (uint16 i = 0; i < globalsCount; i++) {
uint16 index = stream.readUint16();
if (index < _archives[_archiveIndex].names.size()) {
const char *name = _archives[_archiveIndex].names[index].c_str();
if (index < _archives[_assemblyArchive].names.size()) {
const char *name = _archives[_assemblyArchive].names[index].c_str();
debugC(5, kDebugLoading, "%d: %s", i, name);
if (!_globalvars.contains(name)) {
_globalvars[name] = Symbol();
@@ -909,7 +910,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
break;
}
_currentScriptContext->constants.push_back(constant);
_assemblyContext->constants.push_back(constant);
}
free(constsStore);
@@ -989,8 +990,8 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
uint16 index = (uint16)READ_BE_UINT16(&codeStore[namePointer]);
namePointer += 2;
Common::String name;
if (index < _archives[_archiveIndex].names.size()) {
name = _archives[_archiveIndex].names[index];
if (index < _archives[_assemblyArchive].names.size()) {
name = _archives[_assemblyArchive].names[index];
argMap[j] = index;
} else {
name = Common::String::format("arg_%d", j);
@@ -1015,8 +1016,8 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
uint16 index = (uint16)READ_BE_UINT16(&codeStore[namePointer]);
namePointer += 2;
Common::String name;
if (index < _archives[_archiveIndex].names.size()) {
name = _archives[_archiveIndex].names[index];
if (index < _archives[_assemblyArchive].names.size()) {
name = _archives[_assemblyArchive].names[index];
varMap[j] = index;
} else {
name = Common::String::format("var_%d", j);
@@ -1057,7 +1058,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
warning("Opcode 0x%02x arg %d not a multiple of 6!", opcode, arg);
}
arg /= 6;
Datum constant = _currentScriptContext->constants[arg];
Datum constant = _assemblyContext->constants[arg];
switch (constant.type) {
case INT:
g_lingo->code1(LC::c_intpush);
@@ -1202,9 +1203,9 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
// Attach to handlers
Symbol sym;
if (nameIndex < _archives[_archiveIndex].names.size()) {
debugC(5, kDebugLoading, "Function %d binding: %s()", i, _archives[_archiveIndex].names[nameIndex].c_str());
sym = g_lingo->define(_archives[_archiveIndex].names[nameIndex], argCount, _currentAssembly, argNames, varNames);
if (nameIndex < _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);
} else {
warning("Function has unknown name id %d, skipping define", nameIndex);
sym.name = new Common::String();
@@ -1217,8 +1218,8 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
}
if (!skipdump && ConfMan.getBool("dump_scripts")) {
if (nameIndex < _archives[_archiveIndex].names.size())
out.writeString(Common::String::format("function %s, %d args\n", _archives[_archiveIndex].names[nameIndex].c_str(), argCount));
if (nameIndex < _archives[_assemblyArchive].names.size())
out.writeString(Common::String::format("function %s, %d args\n", _archives[_assemblyArchive].names[nameIndex].c_str(), argCount));
else
out.writeString(Common::String::format("<noname>, %d args\n", argCount));
@@ -1231,7 +1232,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
out.writeString(Common::String::format("<end code>\n\n"));
}
_currentScriptContext->functions.push_back(sym);
_assemblyContext->functions.push_back(sym);
_currentAssembly = nullptr;
}
@@ -1244,7 +1245,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
}
void Lingo::addNamesV4(Common::SeekableSubReadStreamEndian &stream) {
void Lingo::addNamesV4(Common::SeekableSubReadStreamEndian &stream, int archiveIndex) {
debugC(1, kDebugCompile, "Add V4 script name index");
if (stream.size() < 0x14) {
@@ -1276,7 +1277,7 @@ void Lingo::addNamesV4(Common::SeekableSubReadStreamEndian &stream) {
stream.seek(offset);
_archives[_archiveIndex].names.clear();
_archives[archiveIndex].names.clear();
Common::Array<Common::String> names;
for (uint32 i = 0; i < count; i++) {
@@ -1285,7 +1286,7 @@ void Lingo::addNamesV4(Common::SeekableSubReadStreamEndian &stream) {
for (uint8 j = 0; j < size; j++) {
name += stream.readByte();
}
_archives[_archiveIndex].names.push_back(name);
_archives[archiveIndex].names.push_back(name);
debugC(5, kDebugLoading, "%d: \"%s\"", i, name.c_str());
}
+4 -4
View File
@@ -73,8 +73,8 @@ Symbol Lingo::define(Common::String &name, int nargs, ScriptData *code, Common::
sym.maxArgs = nargs;
sym.argNames = argNames;
sym.varNames = varNames;
sym.ctx = _currentScriptContext;
sym.archiveIndex = _archiveIndex;
sym.ctx = _assemblyContext;
sym.archiveIndex = _assemblyArchive;
if (debugChannelSet(1, kDebugCompile)) {
uint pc = 0;
@@ -97,9 +97,9 @@ Symbol Lingo::define(Common::String &name, int nargs, ScriptData *code, Common::
warning("Redefining handler '%s'", name.c_str());
if (!_eventHandlerTypeIds.contains(name)) {
_archives[_archiveIndex].functionHandlers[name] = sym;
_archives[_assemblyArchive].functionHandlers[name] = sym;
} else {
_archives[_archiveIndex].eventHandlers[ENTITY_INDEX(_eventHandlerTypeIds[name], _currentEntityId)] = sym;
_archives[_assemblyArchive].eventHandlers[ENTITY_INDEX(_eventHandlerTypeIds[name], _currentEntityId)] = sym;
}
}
+2 -2
View File
@@ -102,8 +102,8 @@ int Lingo::getEventCount() {
void Lingo::setPrimaryEventHandler(LEvent event, const Common::String &code) {
debugC(3, kDebugLingoExec, "setting primary event handler (%s)", _eventHandlerTypes[event]);
_archives[_archiveIndex].primaryEventHandlers[event] = code;
addCode(code.c_str(), kGlobalScript, event);
_archives[0].primaryEventHandlers[event] = code;
addCode(code.c_str(), 0, kGlobalScript, event);
}
void Lingo::primaryEventHandler(LEvent event) {
+12 -11
View File
@@ -378,15 +378,15 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheKeyDownScript:
d.type = STRING;
if (_archives[_archiveIndex].primaryEventHandlers.contains(kEventKeyDown))
d.u.s = new Common::String(_archives[_archiveIndex].primaryEventHandlers[kEventKeyDown]);
if (_archives[0].primaryEventHandlers.contains(kEventKeyDown))
d.u.s = new Common::String(_archives[0].primaryEventHandlers[kEventKeyDown]);
else
d.u.s = new Common::String();
break;
case kTheKeyUpScript:
d.type = STRING;
if (_archives[_archiveIndex].primaryEventHandlers.contains(kEventKeyUp))
d.u.s = new Common::String(_archives[_archiveIndex].primaryEventHandlers[kEventKeyUp]);
if (_archives[0].primaryEventHandlers.contains(kEventKeyUp))
d.u.s = new Common::String(_archives[0].primaryEventHandlers[kEventKeyUp]);
else
d.u.s = new Common::String();
break;
@@ -480,8 +480,8 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheMouseDownScript:
d.type = STRING;
if (_archives[_archiveIndex].primaryEventHandlers.contains(kEventMouseDown))
d.u.s = new Common::String(_archives[_archiveIndex].primaryEventHandlers[kEventMouseDown]);
if (_archives[0].primaryEventHandlers.contains(kEventMouseDown))
d.u.s = new Common::String(_archives[0].primaryEventHandlers[kEventMouseDown]);
else
d.u.s = new Common::String();
break;
@@ -499,8 +499,8 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheMouseUpScript:
d.type = STRING;
if (_archives[_archiveIndex].primaryEventHandlers.contains(kEventMouseUp))
d.u.s = new Common::String(_archives[_archiveIndex].primaryEventHandlers[kEventMouseUp]);
if (_archives[0].primaryEventHandlers.contains(kEventMouseUp))
d.u.s = new Common::String(_archives[0].primaryEventHandlers[kEventMouseUp]);
else
d.u.s = new Common::String();
break;
@@ -563,8 +563,8 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheTimeoutScript:
d.type = STRING;
if (_archives[_archiveIndex].primaryEventHandlers.contains(kEventTimeout))
d.u.s = new Common::String(_archives[_archiveIndex].primaryEventHandlers[kEventTimeout]);
if (_archives[0].primaryEventHandlers.contains(kEventTimeout))
d.u.s = new Common::String(_archives[0].primaryEventHandlers[kEventTimeout]);
else
d.u.s = new Common::String();
break;
@@ -1082,7 +1082,8 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
warning("Lingo::setTheCast(): The cast %d not found. type: %d", id, castType);
return;
}
addCode(d.u.s->c_str(), kSpriteScript, id);
// FIXME: What if the cast member is in a different archive than the current one?
addCode(d.u.s->c_str(), _archiveIndex, kSpriteScript, id);
castInfo->script = d.asString();
break;
+12 -10
View File
@@ -156,6 +156,10 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
_currentScript = 0;
_currentScriptContext = nullptr;
_assemblyArchive = 0;
_currentAssembly = nullptr;
_assemblyContext = nullptr;
_currentEntityId = 0;
_currentChannelId = -1;
_pc = 0;
@@ -286,9 +290,7 @@ const char *Lingo::findNextDefinition(const char *s) {
return NULL;
}
void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
pushContext();
void Lingo::addCode(const char *code, int archiveIndex, ScriptType type, uint16 id) {
debugC(1, kDebugCompile, "Add code for type %s(%d) with id %d\n"
"***********\n%s\n\n***********", scriptType2str(type), type, id, code);
@@ -299,10 +301,11 @@ void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
warning("Script already defined for type %d, id %d", id, type);
}
_currentScriptContext = new ScriptContext;
_assemblyArchive = archiveIndex;
_assemblyContext = new ScriptContext;
_currentAssembly = new ScriptData;
_currentEntityId = id;
_archives[_archiveIndex].scriptContexts[type][id] = _currentScriptContext;
_archives[_assemblyArchive].scriptContexts[type][id] = _assemblyContext;
_methodVars = new Common::HashMap<Common::String, VarType, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo>();
_linenumber = _colnumber = 1;
@@ -399,7 +402,7 @@ void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
currentFunc.name = new Common::String("[unknown]");
}
currentFunc.ctx = _currentScriptContext;
currentFunc.archiveIndex = _archiveIndex;
currentFunc.archiveIndex = _assemblyArchive;
// 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++) {
@@ -429,10 +432,9 @@ void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
currentFunc.argNames = argNames;
currentFunc.varNames = varNames;
_currentScriptContext->functions.push_back(currentFunc);
_assemblyContext->functions.push_back(currentFunc);
_assemblyContext = nullptr;
_currentAssembly = nullptr;
popContext();
}
void Lingo::printStack(const char *s, uint pc) {
@@ -1019,7 +1021,7 @@ void Lingo::runTests() {
debug(">> Compiling file %s of size %d, id: %d", fileList[i].c_str(), size, counter);
_hadError = false;
addCode(script, kMovieScript, counter);
addCode(script, 0, kMovieScript, counter);
if (!debugChannelSet(-1, kDebugCompileOnly)) {
if (!_hadError)
+5 -3
View File
@@ -315,9 +315,9 @@ public:
void restartLingo(bool keepSharedCast);
void addCode(const char *code, ScriptType type, uint16 id);
void addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType type, uint16 id, Common::String &archName);
void addNamesV4(Common::SeekableSubReadStreamEndian &stream);
void addCode(const char *code, int archiveIndex, ScriptType type, uint16 id);
void addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIndex, ScriptType type, uint16 id, Common::String &archName);
void addNamesV4(Common::SeekableSubReadStreamEndian &stream, int archiveIndex);
void executeHandler(const Common::String &name);
void executeScript(ScriptType type, uint16 id, uint16 function);
void printStack(const char *s, uint pc);
@@ -468,6 +468,8 @@ public:
void processIf(int toplabel, int endlabel);
void varCreate(const Common::String &name, bool global, SymbolHash *localvars = nullptr);
int _assemblyArchive;
ScriptContext *_assemblyContext;
ScriptData *_currentAssembly;
LexerDefineState _indef;
LexerDefineState _indefStore;
+1 -3
View File
@@ -79,7 +79,7 @@ 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, kMovieScript, 0);
_lingo->addCode(script, 0, kMovieScript, 0);
_lingo->processEvent(kEventStartUp);
free(script);
} else {
@@ -304,11 +304,9 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) {
debug(0, "@@@@ Loading Shared cast '%s'", filename.c_str());
debug(0, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
_lingo->_archiveIndex = 1;
_sharedScore = new Score(this);
_sharedScore->setArchive(sharedCast);
_sharedScore->loadArchive(true);
_lingo->_archiveIndex = 0;
}
Cast *DirectorEngine::getCastMember(int castId) {
+9 -7
View File
@@ -78,6 +78,8 @@ void Score::setArchive(Archive *archive) {
}
bool Score::loadArchive(bool isSharedCast) {
_lingoArchive = isSharedCast ? 1 : 0;
Common::Array<uint16> clutList = _movieArchive->getResourceIDList(MKTAG('C', 'L', 'U', 'T'));
Common::SeekableSubReadStreamEndian *r = nullptr;
@@ -876,7 +878,7 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
if (scriptId < _castScriptIds.size()) {
int resourceId = _castScriptIds[scriptId];
Common::SeekableSubReadStreamEndian *r;
_lingo->addCodeV4(*(r = _movieArchive->getResource(MKTAG('L', 's', 'c', 'r'), resourceId)), ((ScriptCast *)member)->_scriptType, id, _macName);
_lingo->addCodeV4(*(r = _movieArchive->getResource(MKTAG('L', 's', 'c', 'r'), resourceId)), _lingoArchive, ((ScriptCast *)member)->_scriptType, id, _macName);
delete r;
} else {
warning("Score::loadCastData(): Lingo context missing a resource entry for script %d referenced in cast %d", scriptId, id);
@@ -888,7 +890,7 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
if (ConfMan.getBool("dump_scripts"))
dumpScript(ci->script.c_str(), ((ScriptCast *)member)->_scriptType, id);
_lingo->addCode(ci->script.c_str(), ((ScriptCast *)member)->_scriptType, id);
_lingo->addCode(ci->script.c_str(), _lingoArchive, ((ScriptCast *)member)->_scriptType, id);
} else {
warning("Score::loadCastData(): Wrong cast type: %d", member->_type);
}
@@ -1012,7 +1014,7 @@ void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) {
// continue;
}
if (!j->_value.empty()) {
_lingo->addCode(j->_value.c_str(), kFrameScript, j->_key);
_lingo->addCode(j->_value.c_str(), _lingoArchive, kFrameScript, j->_key);
processImmediateFrameScript(j->_value, j->_key);
}
@@ -1023,7 +1025,7 @@ void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) {
void Score::loadLingoNames(Common::SeekableSubReadStreamEndian &stream) {
if (_vm->getVersion() >= 4) {
_lingo->addNamesV4(stream);
_lingo->addNamesV4(stream, _lingoArchive);
} else {
error("Score::loadLingoNames: unsuported Director version (%d)", _vm->getVersion());
}
@@ -1098,7 +1100,7 @@ void Score::loadScriptText(Common::SeekableSubReadStreamEndian &stream) {
if (script.contains("\nmenu:") || script.hasPrefix("menu:"))
return;
_lingo->addCode(script.c_str(), kMovieScript, _movieScriptCount);
_lingo->addCode(script.c_str(), _lingoArchive, kMovieScript, _movieScriptCount);
_movieScriptCount++;
}
@@ -1129,7 +1131,7 @@ void Score::loadCastInfo(Common::SeekableSubReadStreamEndian &stream, uint16 id)
dumpScript(ci->script.c_str(), kSpriteScript, id);
if (!ci->script.empty())
_lingo->addCode(ci->script.c_str(), kSpriteScript, id);
_lingo->addCode(ci->script.c_str(), _lingoArchive, kSpriteScript, id);
ci->name = getString(castStrings[1]);
ci->directory = getString(castStrings[2]);
@@ -1157,7 +1159,7 @@ void Score::loadFileInfo(Common::SeekableSubReadStreamEndian &stream) {
dumpScript(_script.c_str(), kMovieScript, _movieScriptCount);
if (!_script.empty())
_lingo->addCode(_script.c_str(), kMovieScript, _movieScriptCount);
_lingo->addCode(_script.c_str(), _lingoArchive, kMovieScript, _movieScriptCount);
_movieScriptCount++;
_changedBy = fileInfoStrings[1];
+1
View File
@@ -45,6 +45,7 @@ Score::Score(DirectorEngine *vm) {
_backSurface = nullptr;
_backSurface2 = nullptr;
_lingo = _vm->getLingo();
_lingoArchive = 0;
_soundManager = _vm->getSoundManager();
_currentMouseDownSpriteId = 0;
_currentClickOnSpriteId = 0;
+1
View File
@@ -239,6 +239,7 @@ private:
uint16 _castArrayEnd;
uint16 _movieScriptCount;
Lingo *_lingo;
int _lingoArchive;
DirectorSound *_soundManager;
DirectorEngine *_vm;