[Scummvm-git-logs] scummvm master -> 44d985d1221bbf4ce207a0744238b11e7838136f
moralrecordings
code at moral.net.au
Fri Jan 24 17:39:27 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:
f1e6fe5109 CREDITS: Add myself to Director
44d985d122 DIRECTOR: LINGO: Process variable and argument names
Commit: f1e6fe5109f53a55c23c055beb4829b20dd5b7ae
https://github.com/scummvm/scummvm/commit/f1e6fe5109f53a55c23c055beb4829b20dd5b7ae
Author: Scott Percival (code at moral.net.au)
Date: 2020-01-25T01:38:39+08:00
Commit Message:
CREDITS: Add myself to Director
Changed paths:
AUTHORS
diff --git a/AUTHORS b/AUTHORS
index 7baffe0..0972ca5 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -109,6 +109,7 @@ ScummVM Team
Director:
Eugene Sandulenko
Dmitry Iskrich
+ Scott Percival
Steven Hoefel
Tobia Tesan
Commit: 44d985d1221bbf4ce207a0744238b11e7838136f
https://github.com/scummvm/scummvm/commit/44d985d1221bbf4ce207a0744238b11e7838136f
Author: Scott Percival (code at moral.net.au)
Date: 2020-01-25T01:38:39+08:00
Commit Message:
DIRECTOR: LINGO: Process variable and argument names
Changed paths:
engines/director/lingo/lingo-bytecode.cpp
engines/director/lingo/lingo-code.cpp
engines/director/lingo/lingo-codegen.cpp
engines/director/lingo/lingo.h
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 0e376c8..8cd0155 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -67,9 +67,11 @@ static LingoV4Bytecode lingoV4[] = {
// 0x44, push a constant
{ 0x45, LC::c_namepush, "b" },
{ 0x49, LC::cb_globalpush, "b" },
- { 0x4c, LC::cb_varpush, "b" },
+ { 0x4b, LC::cb_varpush, "bpa" },
+ { 0x4c, LC::cb_varpush, "bpv" },
{ 0x4f, LC::cb_globalassign,"b" },
- { 0x52, LC::cb_varassign, "b" },
+ { 0x51, LC::cb_varassign, "bpa" },
+ { 0x52, LC::cb_varassign, "bpv" },
{ 0x53, LC::c_jump, "jb" },
{ 0x54, LC::c_jump, "jbn" },
{ 0x55, LC::c_jumpifz, "jb" },
@@ -84,9 +86,11 @@ static LingoV4Bytecode lingoV4[] = {
{ 0x83, LC::c_argcpush, "w" },
// 0x84, push a constant
{ 0x89, LC::cb_globalpush, "w" },
- { 0x8c, LC::cb_varpush, "w" },
+ { 0x8b, LC::cb_varpush, "wpa" },
+ { 0x8c, LC::cb_varpush, "wpv" },
{ 0x8f, LC::cb_globalassign,"w" },
- { 0x92, LC::cb_varassign, "w" },
+ { 0x91, LC::cb_varassign, "wpa" },
+ { 0x92, LC::cb_varassign, "wpv" },
{ 0x93, LC::c_jump, "jw" },
{ 0x94, LC::c_jump, "jwn" },
{ 0x95, LC::c_jumpifz, "jw" },
@@ -599,13 +603,13 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
debugC(5, kDebugLoading, "Lscr globals list:");
stream.seek(globalsOffset);
for (uint16 i = 0; i < globalsCount; i++) {
- uint16 nameIndex = stream.readUint16();
- if (nameIndex < _namelist.size()) {
- const char *name = _namelist[nameIndex].c_str();
+ uint16 index = stream.readUint16();
+ if (index < _namelist.size()) {
+ const char *name = _namelist[index].c_str();
debugC(5, kDebugLoading, "%d: %s", i, name);
- Symbol *s = g_lingo->lookupVar(name, true, true);
+ g_lingo->lookupVar(name, true, true);
} else {
- warning("Global %d has unknown name id %d, skipping define", i, nameIndex);
+ warning("Global %d has unknown name id %d, skipping define", i, index);
}
}
@@ -721,17 +725,14 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
stream.hexdump(0x2a);
}
- _currentScriptFunction = i;
- _currentScript = new ScriptData;
-
uint16 nameIndex = stream.readUint16();
stream.readUint16();
uint32 length = stream.readUint32();
uint32 startOffset = stream.readUint32();
uint16 argCount = stream.readUint16();
- /*uint32 argOffset = */stream.readUint32();
- /*uint16 varCount = */stream.readUint16();
- /*uint32 varNamesOffset = */stream.readUint32();
+ uint32 argOffset = stream.readUint32();
+ uint16 varCount = stream.readUint16();
+ uint32 varOffset = stream.readUint32();
stream.readUint16();
stream.readUint16();
stream.readUint16();
@@ -750,6 +751,61 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
continue;
}
+ // Fetch argument name list
+ Common::Array<Common::String> *argNames = new Common::Array<Common::String>;
+ Common::HashMap<uint16, uint16> argMap;
+ if (argOffset < codeStoreOffset) {
+ warning("Function %d argument names start offset is out of bounds!", i);
+ } else if (argOffset + argCount*2 >= codeStoreOffset + codeStoreSize) {
+ warning("Function %d argument names end offset is out of bounds!", i);
+ } else {
+ debugC(5, kDebugLoading, "Function %d argument list:", i);
+ uint16 namePointer = argOffset - codeStoreOffset;
+ for (int j = 0; j < argCount; j++) {
+ uint16 index = (uint16)READ_BE_UINT16(&codeStore[namePointer]);
+ namePointer += 2;
+ Common::String name;
+ if (index < _namelist.size()) {
+ name = _namelist[index];
+ argMap[j] = index;
+ } else {
+ name = Common::String::format("arg_%d", j);
+ warning("Argument has unknown name id %d, using name %s", j, name.c_str());
+ }
+ debugC(5, kDebugLoading, "%d: %s", j, name.c_str());
+ argNames->push_back(name);
+ }
+ }
+
+ // Fetch variable name list
+ Common::Array<Common::String> *varNames = new Common::Array<Common::String>;
+ Common::HashMap<uint16, uint16> varMap;
+ if (varOffset < codeStoreOffset) {
+ warning("Function %d variable names start offset is out of bounds!", i);
+ } else if (varOffset + varCount*2 >= codeStoreOffset + codeStoreSize) {
+ warning("Function %d variable names end offset is out of bounds!", i);
+ } else {
+ debugC(5, kDebugLoading, "Function %d variable list:", i);
+ uint16 namePointer = varOffset - codeStoreOffset;
+ for (int j = 0; j < varCount; j++) {
+ uint16 index = (uint16)READ_BE_UINT16(&codeStore[namePointer]);
+ namePointer += 2;
+ Common::String name;
+ if (index < _namelist.size()) {
+ name = _namelist[index];
+ varMap[j] = index;
+ } else {
+ name = Common::String::format("var_%d", j);
+ warning("Variable has unknown name id %d, using name %s", j, name.c_str());
+ }
+ debugC(5, kDebugLoading, "%d: %s", j, name.c_str());
+ varNames->push_back(name);
+ }
+ }
+
+ _currentScriptFunction = i;
+ _currentScript = new ScriptData;
+
if (debugChannelSet(5, kDebugLoading)) {
debugC(5, kDebugLoading, "Function %d code:", i);
Common::hexdump(codeStore, length, 16, startOffset);
@@ -839,6 +895,31 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
// argument is negative
arg *= -1;
break;
+ case 'p':
+ // argument is some kind of denormalised offset
+ if (arg % 6) {
+ warning("Argument %d was expected to be a multiple of 6", arg);
+ }
+ arg /= 6;
+ break;
+ case 'a':
+ // argument is a function argument ID
+ if (argMap.contains(arg)) {
+ arg = argMap[arg];
+ } else {
+ warning("No argument name found for ID %d", arg);
+ arg = -1;
+ }
+ break;
+ case 'v':
+ // argument is a local variable ID
+ if (varMap.contains(arg)) {
+ arg = varMap[arg];
+ } else {
+ warning("No variable name found for ID %d", arg);
+ arg = -1;
+ }
+ break;
case 'j':
// argument refers to a code offset; fix alignment in post
jumpList.push_back(offsetList.size());
@@ -900,6 +981,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
// Attach to handlers
Symbol *sym = NULL;
if (nameIndex < _namelist.size()) {
+ debugC(5, kDebugLoading, "Function %d binding: %s()", i, _namelist[nameIndex].c_str());
sym = g_lingo->define(_namelist[nameIndex], argCount, _currentScript);
} else {
warning("Function has unknown name id %d, skipping define", nameIndex);
@@ -909,6 +991,8 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
sym->nargs = argCount;
sym->maxArgs = argCount;
}
+ sym->argNames = argNames;
+ sym->varNames = varNames;
sym->ctx = _currentScriptContext;
_currentScriptContext->functions.push_back(sym);
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 7a94b6d..33b3016 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -1223,6 +1223,41 @@ void LC::call(Symbol *sym, int nargs) {
// Create new set of local variables
g_lingo->_localvars = new SymbolHash;
+ if (sym->argNames) {
+
+ if ((int)sym->argNames->size() < sym->nargs) {
+ int dropSize = sym->nargs - sym->argNames->size();
+ warning("%d arg names defined for %d args! Dropping the last %d values", sym->argNames->size(), sym->nargs, dropSize);
+ for (int i = 0; i < dropSize; i++) {
+ g_lingo->pop();
+ sym->nargs -= 1;
+ }
+ } else if ((int)sym->argNames->size() > sym->nargs) {
+ warning("%d arg names defined for %d args! Ignoring the last %d names", sym->argNames->size(), sym->nargs, sym->argNames->size() - sym->nargs);
+ }
+ for (int i = sym->nargs - 1; i >= 0; i--) {
+ Common::String name = (*sym->argNames)[i];
+ if (!g_lingo->_localvars->contains(name)) {
+ Datum arg;
+ arg.type = VAR;
+ arg.u.sym = g_lingo->lookupVar(name.c_str(), true, false);
+ Datum value = g_lingo->pop();
+ g_lingo->varAssign(arg, value);
+ } else {
+ warning("Argument %s already defined", name.c_str());
+ }
+ }
+ }
+ if (sym->varNames) {
+ for (Common::Array<Common::String>::iterator it = sym->varNames->begin(); it != sym->varNames->end(); ++it) {
+ Common::String name = *it;
+ if (!g_lingo->_localvars->contains(name)) {
+ g_lingo->lookupVar(name.c_str(), true, false);
+ } else {
+ warning("Variable %s already defined", name.c_str());
+ }
+ }
+ }
g_lingo->_callstack.push_back(fp);
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index cc78fba..ee8b582 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -271,6 +271,9 @@ Symbol *Lingo::define(Common::String &name, int nargs, ScriptData *code) {
sym->u.defn = code;
sym->nargs = nargs;
sym->maxArgs = nargs;
+ // TODO: Assign these properties from here
+ sym->argNames = NULL;
+ sym->varNames = NULL;
sym->ctx = NULL;
if (debugChannelSet(1, kDebugLingoCompile)) {
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 1445e01..337099d 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -85,6 +85,8 @@ struct Symbol { /* symbol table entry */
bool parens; /* whether parens required or not, for builitins */
bool global;
+ Common::Array<Common::String> *argNames;
+ Common::Array<Common::String> *varNames;
ScriptContext *ctx; /* optional script context to execute with */
Symbol();
More information about the Scummvm-git-logs
mailing list