aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstevenhoefel2017-01-12 08:58:48 +1100
committerstevenhoefel2017-01-12 08:58:48 +1100
commit1f95f5c161d8123d4d674dae2917dc6b180ca6aa (patch)
tree6a1540c12fce586183496fe114f428981a0be13c
parent5c985ab549ae9ac2c47bf32f7951fca80db071f1 (diff)
downloadscummvm-rg350-1f95f5c161d8123d4d674dae2917dc6b180ca6aa.tar.gz
scummvm-rg350-1f95f5c161d8123d4d674dae2917dc6b180ca6aa.tar.bz2
scummvm-rg350-1f95f5c161d8123d4d674dae2917dc6b180ca6aa.zip
DIRECTOR: Hook Lingo events through. Tie in frame events.
-rw-r--r--engines/director/lingo/lingo-builtins.cpp2
-rw-r--r--engines/director/lingo/lingo-code.cpp17
-rw-r--r--engines/director/lingo/lingo-codegen.cpp13
-rw-r--r--engines/director/lingo/lingo-gr.cpp8
-rw-r--r--engines/director/lingo/lingo-gr.y8
-rw-r--r--engines/director/lingo/lingo-lex.cpp16
-rw-r--r--engines/director/lingo/lingo-lex.l16
-rw-r--r--engines/director/lingo/lingo.cpp28
-rw-r--r--engines/director/lingo/lingo.h7
-rw-r--r--engines/director/score.cpp2
10 files changed, 69 insertions, 48 deletions
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 8da972232c..f26990caa2 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -172,7 +172,7 @@ void Lingo::initBuiltIns() {
sym->parens = blt->parens;
sym->u.bltin = blt->func;
- _handlers[blt->name] = sym;
+ _builtins[blt->name] = sym;
_functions[(void *)sym->u.s] = new FuncDesc(blt->name, "");
}
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 4543e52f02..82c7d2780f 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -234,19 +234,19 @@ void Lingo::c_symbolpush() {
}
void Lingo::c_varpush() {
- char *name = (char *)&(*g_lingo->_currentScript)[g_lingo->_pc];
+ Common::String name((char *)&(*g_lingo->_currentScript)[g_lingo->_pc]);
Datum d;
- g_lingo->_pc += g_lingo->calcStringAlignment(name);
+ g_lingo->_pc += g_lingo->calcStringAlignment(name.c_str());
- if (g_lingo->_handlers.contains(name)) {
+ if (g_lingo->getHandler(name) != NULL) {
d.type = HANDLER;
d.u.s = new Common::String(name);
g_lingo->push(d);
return;
}
- d.u.sym = g_lingo->lookupVar(name);
+ d.u.sym = g_lingo->lookupVar(name.c_str());
if (d.u.sym->type == CASTREF) {
d.type = INT;
int val = d.u.sym->u.i;
@@ -984,22 +984,21 @@ void Lingo::c_call() {
void Lingo::call(Common::String name, int nargs) {
bool dropArgs = false;
- Symbol *sym;
+ Symbol *sym = g_lingo->getHandler(name);
- if (!g_lingo->_handlers.contains(name)) {
+ if (!g_lingo->_eventHandlerTypeIds.contains(name)) {
Symbol *s = g_lingo->lookupVar(name.c_str(), false);
if (s && s->type == OBJECT) {
debugC(3, kDebugLingoExec, "Dereferencing object reference: %s to %s", name.c_str(), s->u.s->c_str());
name = *s->u.s;
+ sym = g_lingo->getHandler(name);
}
}
- if (!g_lingo->_handlers.contains(name)) {
+ if (sym == NULL) {
warning("Call to undefined handler '%s'. Dropping %d stack items", name.c_str(), nargs);
dropArgs = true;
} else {
- sym = g_lingo->_handlers[name];
-
if (sym->type == BLTIN && sym->nargs != -1 && sym->nargs != nargs && sym->maxArgs != nargs) {
if (sym->nargs == sym->maxArgs)
warning("Incorrect number of arguments to handler '%s', expecting %d. Dropping %d stack items", name.c_str(), sym->nargs, nargs);
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index 930e9924ec..f98ad0e6fe 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -200,24 +200,23 @@ void Lingo::cleanLocalVars() {
}
void Lingo::define(Common::String &name, int start, int nargs, Common::String *prefix, int end) {
- Symbol *sym;
-
if (prefix)
name = *prefix + "-" + name;
debugC(3, kDebugLingoCompile, "define(\"%s\", %d, %d, %d)", name.c_str(), start, _currentScript->size() - 1, nargs);
- if (!_handlers.contains(name)) { // Create variable if it was not defined
+ Symbol *sym = getHandler(name);
+ if (sym == NULL) { // Create variable if it was not defined
sym = new Symbol;
sym->name = (char *)calloc(name.size() + 1, 1);
Common::strlcpy(sym->name, name.c_str(), name.size() + 1);
sym->type = HANDLER;
- _handlers[name] = sym;
+ _handlers[ENTITY_INDEX(_eventHandlerTypeIds[name.c_str()], _currentEntityId)] = sym;
} else {
- sym = g_lingo->_handlers[name];
-
+ //we don't want to be here. The getHandler call should have used the EntityId and the result
+ //should have been unique!
warning("Redefining handler '%s'", name.c_str());
delete sym->u.defn;
}
@@ -368,7 +367,7 @@ void Lingo::codeFactory(Common::String &name) {
sym->parens = true;
sym->u.bltin = g_lingo->b_factory;
- _handlers[name] = sym;
+ _handlers[ENTITY_INDEX(_eventHandlerTypeIds[name.c_str()], _currentEntityId)] = sym;
}
}
diff --git a/engines/director/lingo/lingo-gr.cpp b/engines/director/lingo/lingo-gr.cpp
index 916072fc49..89e64cc75d 100644
--- a/engines/director/lingo/lingo-gr.cpp
+++ b/engines/director/lingo/lingo-gr.cpp
@@ -2433,7 +2433,7 @@ yyreduce:
case 61:
#line 394 "engines/director/lingo/lingo-gr.y"
{
- (yyval.code) = g_lingo->code1(g_lingo->_handlers[*(yyvsp[(1) - (1)].s)]->u.func);
+ (yyval.code) = g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (1)].s)]->u.func);
delete (yyvsp[(1) - (1)].s); ;}
break;
@@ -2647,21 +2647,21 @@ yyreduce:
case 105:
#line 459 "engines/director/lingo/lingo-gr.y"
{
- g_lingo->code1(g_lingo->_handlers[*(yyvsp[(1) - (2)].s)]->u.func);
+ g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (2)].s)]->u.func);
delete (yyvsp[(1) - (2)].s); ;}
break;
case 106:
#line 462 "engines/director/lingo/lingo-gr.y"
{
- g_lingo->code1(g_lingo->_handlers[*(yyvsp[(1) - (2)].s)]->u.func);
+ g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (2)].s)]->u.func);
delete (yyvsp[(1) - (2)].s); ;}
break;
case 107:
#line 465 "engines/director/lingo/lingo-gr.y"
{
- g_lingo->code2(g_lingo->c_voidpush, g_lingo->_handlers[*(yyvsp[(1) - (1)].s)]->u.func);
+ g_lingo->code2(g_lingo->c_voidpush, g_lingo->_builtins[*(yyvsp[(1) - (1)].s)]->u.func);
delete (yyvsp[(1) - (1)].s); ;}
break;
diff --git a/engines/director/lingo/lingo-gr.y b/engines/director/lingo/lingo-gr.y
index 60e780d727..392850bf51 100644
--- a/engines/director/lingo/lingo-gr.y
+++ b/engines/director/lingo/lingo-gr.y
@@ -392,7 +392,7 @@ expr: INT { $$ = g_lingo->codeConst($1); }
$$ = g_lingo->code1(g_lingo->c_stringpush);
g_lingo->codeString($1->c_str()); }
| BLTINNOARGS {
- $$ = g_lingo->code1(g_lingo->_handlers[*$1]->u.func);
+ $$ = g_lingo->code1(g_lingo->_builtins[*$1]->u.func);
delete $1; }
| ID '(' arglist ')' {
$$ = g_lingo->codeFunc($1, $3);
@@ -457,13 +457,13 @@ func: tPUT expr { g_lingo->code1(g_lingo->c_printtop); }
| tGLOBAL globallist
| tINSTANCE instancelist
| BLTINONEARG expr {
- g_lingo->code1(g_lingo->_handlers[*$1]->u.func);
+ g_lingo->code1(g_lingo->_builtins[*$1]->u.func);
delete $1; }
| BLTINNOARGSORONE expr {
- g_lingo->code1(g_lingo->_handlers[*$1]->u.func);
+ g_lingo->code1(g_lingo->_builtins[*$1]->u.func);
delete $1; }
| BLTINNOARGSORONE {
- g_lingo->code2(g_lingo->c_voidpush, g_lingo->_handlers[*$1]->u.func);
+ g_lingo->code2(g_lingo->c_voidpush, g_lingo->_builtins[*$1]->u.func);
delete $1; }
| BLTINARGLIST '(' arglist ')' { g_lingo->codeFunc($1, $3); }
| BLTINARGLIST arglist { g_lingo->codeFunc($1, $2); }
diff --git a/engines/director/lingo/lingo-lex.cpp b/engines/director/lingo/lingo-lex.cpp
index f3c498b5a8..dc502cf588 100644
--- a/engines/director/lingo/lingo-lex.cpp
+++ b/engines/director/lingo/lingo-lex.cpp
@@ -1443,19 +1443,19 @@ YY_RULE_SETUP
return tME;
}
- if (g_lingo->_handlers.contains(yytext)) {
- if (g_lingo->_handlers[yytext]->type == BLTIN && g_lingo->_handlers[yytext]->parens == false) {
- if (g_lingo->_handlers[yytext]->nargs == 0) {
- if (g_lingo->_handlers[yytext]->maxArgs == 0)
+ if (g_lingo->_builtins.contains(yytext)) {
+ if (g_lingo->_builtins[yytext]->type == BLTIN && g_lingo->_builtins[yytext]->parens == false) {
+ if (g_lingo->_builtins[yytext]->nargs == 0) {
+ if (g_lingo->_builtins[yytext]->maxArgs == 0)
return BLTINNOARGS;
- else if (g_lingo->_handlers[yytext]->maxArgs == 1)
+ else if (g_lingo->_builtins[yytext]->maxArgs == 1)
return BLTINNOARGSORONE;
else
error("Incorrect setup for builtin: %s", yytext);
- } else if (g_lingo->_handlers[yytext]->nargs == 1 &&
- g_lingo->_handlers[yytext]->maxArgs == 1) {
+ } else if (g_lingo->_builtins[yytext]->nargs == 1 &&
+ g_lingo->_builtins[yytext]->maxArgs == 1) {
return BLTINONEARG;
- } else if (g_lingo->_handlers[yytext]->nargs == -1) {
+ } else if (g_lingo->_builtins[yytext]->nargs == -1) {
return BLTINARGLIST;
} else {
error("Incorrect setup for builtin: %s", yytext);
diff --git a/engines/director/lingo/lingo-lex.l b/engines/director/lingo/lingo-lex.l
index 9d9dba7d39..e596c0bcb3 100644
--- a/engines/director/lingo/lingo-lex.l
+++ b/engines/director/lingo/lingo-lex.l
@@ -252,19 +252,19 @@ whitespace [\t ]
return tME;
}
- if (g_lingo->_handlers.contains(yytext)) {
- if (g_lingo->_handlers[yytext]->type == BLTIN && g_lingo->_handlers[yytext]->parens == false) {
- if (g_lingo->_handlers[yytext]->nargs == 0) {
- if (g_lingo->_handlers[yytext]->maxArgs == 0)
+ if (g_lingo->_builtins.contains(yytext)) {
+ if (g_lingo->_builtins[yytext]->type == BLTIN && g_lingo->_builtins[yytext]->parens == false) {
+ if (g_lingo->_builtins[yytext]->nargs == 0) {
+ if (g_lingo->_builtins[yytext]->maxArgs == 0)
return BLTINNOARGS;
- else if (g_lingo->_handlers[yytext]->maxArgs == 1)
+ else if (g_lingo->_builtins[yytext]->maxArgs == 1)
return BLTINNOARGSORONE;
else
error("Incorrect setup for builtin: %s", yytext);
- } else if (g_lingo->_handlers[yytext]->nargs == 1 &&
- g_lingo->_handlers[yytext]->maxArgs == 1) {
+ } else if (g_lingo->_builtins[yytext]->nargs == 1 &&
+ g_lingo->_builtins[yytext]->maxArgs == 1) {
return BLTINONEARG;
- } else if (g_lingo->_handlers[yytext]->nargs == -1) {
+ } else if (g_lingo->_builtins[yytext]->nargs == -1) {
return BLTINARGLIST;
} else {
error("Incorrect setup for builtin: %s", yytext);
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 1377b0841f..1fd4a43c3b 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -34,7 +34,7 @@ Lingo *g_lingo;
struct EventHandlerType {
LEvent handler;
const char *name;
-} static const eventHanlerDescs[] = {
+} static const eventHandlerDescs[] = {
{ kEventPrepareMovie, "prepareMovie" },
{ kEventStartMovie, "startMovie" },
{ kEventStopMovie, "stopMovie" },
@@ -86,8 +86,10 @@ Symbol::Symbol() {
Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
g_lingo = this;
- for (const EventHandlerType *t = &eventHanlerDescs[0]; t->handler != kEventNone; ++t)
+ for (const EventHandlerType *t = &eventHandlerDescs[0]; t->handler != kEventNone; ++t) {
+ _eventHandlerTypeIds[t->name] = t->handler;
_eventHandlerTypes[t->handler] = t->name;
+ }
initBuiltIns();
initFuncs();
@@ -161,6 +163,7 @@ void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
_currentScript = new ScriptData;
_currentScriptType = type;
_scripts[type][id] = _currentScript;
+ _currentEntityId = id;
_linenumber = _colnumber = 1;
_hadError = false;
@@ -268,8 +271,23 @@ ScriptType Lingo::event2script(LEvent ev) {
return kNoneScript;
}
+Symbol *Lingo::getHandler(Common::String &name) {
+ if (!_eventHandlerTypeIds.contains(name))
+ return NULL;
+
+ uint32 entityIndex = ENTITY_INDEX(_eventHandlerTypeIds[name], _currentEntityId);
+ if (!_handlers.contains(entityIndex))
+ return NULL;
+
+ return _handlers[entityIndex];
+}
+
void Lingo::processEvent(LEvent event, int entityId) {
- if (entityId <= 0) return;
+ if (entityId <= 0)
+ return;
+
+ _currentEntityId = entityId;
+
if (!_eventHandlerTypes.contains(event))
error("processEvent: Unknown event %d for entity %d", event, entityId);
@@ -277,8 +295,8 @@ void Lingo::processEvent(LEvent event, int entityId) {
if (st != kNoneScript) {
executeScript(st, entityId + 1);
- } else if (_handlers.contains(_eventHandlerTypes[event])) {
- call(_eventHandlerTypes[event], entityId);
+ } else if (_handlers.contains(ENTITY_INDEX(event, entityId))) {
+ call(_eventHandlerTypes[event], 0);
pop();
} else {
debugC(8, kDebugLingoExec, "STUB: processEvent(%s) for %d", _eventHandlerTypes[event], entityId);
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index a1daeaa526..41d0444a32 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -73,6 +73,7 @@ enum LEvent {
typedef void (*inst)(void);
#define STOP (inst)0
+#define ENTITY_INDEX(t,id) ((t) * 100000 + (id))
typedef Common::Array<inst> ScriptData;
typedef Common::Array<double> FloatArray;
@@ -178,6 +179,7 @@ public:
Common::String decodeInstruction(uint pc, uint *newPC = NULL);
ScriptType event2script(LEvent ev);
+ Symbol *getHandler(Common::String &name);
void processEvent(LEvent event, int entityId);
@@ -440,6 +442,7 @@ public:
public:
ScriptData *_currentScript;
ScriptType _currentScriptType;
+ uint16 _currentEntityId;
bool _returning;
bool _indef;
bool _ignoreMe;
@@ -450,8 +453,9 @@ public:
TheEntityFieldHash _theEntityFields;
Common::Array<int> _labelstack;
- SymbolHash _handlers;
+ SymbolHash _builtins;
Common::HashMap<Common::String, bool> _twoWordBuiltins;
+ Common::HashMap<uint32, Symbol *> _handlers;
int _linenumber;
int _colnumber;
@@ -475,6 +479,7 @@ private:
Datum pop(void);
Common::HashMap<uint32, const char *> _eventHandlerTypes;
+ Common::HashMap<Common::String, uint32> _eventHandlerTypeIds;
Common::HashMap<Common::String, Audio::AudioStream *> _audioAliases;
ScriptHash _scripts[kMaxScriptType + 1];
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 2b7465010b..fb384c2e6b 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -511,7 +511,7 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
CastInfo *ci = new CastInfo();
- if (castStrings.size() == 5) {
+ if (castStrings.size() >= 5) {
ci->script = castStrings[0];
ci->name = castStrings[1];
ci->directory = castStrings[2];