From 1f95f5c161d8123d4d674dae2917dc6b180ca6aa Mon Sep 17 00:00:00 2001 From: stevenhoefel Date: Thu, 12 Jan 2017 08:58:48 +1100 Subject: DIRECTOR: Hook Lingo events through. Tie in frame events. --- engines/director/lingo/lingo-builtins.cpp | 2 +- engines/director/lingo/lingo-code.cpp | 17 ++++++++--------- engines/director/lingo/lingo-codegen.cpp | 13 ++++++------- engines/director/lingo/lingo-gr.cpp | 8 ++++---- engines/director/lingo/lingo-gr.y | 8 ++++---- engines/director/lingo/lingo-lex.cpp | 16 ++++++++-------- engines/director/lingo/lingo-lex.l | 16 ++++++++-------- engines/director/lingo/lingo.cpp | 28 +++++++++++++++++++++++----- engines/director/lingo/lingo.h | 7 ++++++- engines/director/score.cpp | 2 +- 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 ScriptData; typedef Common::Array 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 _labelstack; - SymbolHash _handlers; + SymbolHash _builtins; Common::HashMap _twoWordBuiltins; + Common::HashMap _handlers; int _linenumber; int _colnumber; @@ -475,6 +479,7 @@ private: Datum pop(void); Common::HashMap _eventHandlerTypes; + Common::HashMap _eventHandlerTypeIds; Common::HashMap _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]; -- cgit v1.2.3