ScummVM API documentation
lingo.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef DIRECTOR_LINGO_LINGO_H
23 #define DIRECTOR_LINGO_LINGO_H
24 
25 namespace Audio {
26 class AudioStream;
27 }
28 namespace Common {
29 class SeekableReadStreamEndian;
30 }
31 
32 namespace Director {
33 
34 struct ChunkReference;
35 struct MenuReference;
36 struct PictureReference;
37 struct TheEntity;
38 struct TheEntityField;
39 struct LingoArchive;
40 struct LingoV4Bytecode;
41 struct LingoV4TheEntity;
42 struct Node;
43 struct Picture;
44 class AbstractObject;
45 class Cast;
46 class ScriptContext;
47 class DirectorEngine;
48 class Frame;
49 class LingoCompiler;
50 
51 typedef void (*inst)(void);
52 #define STOP (inst)0
53 #define ENTITY_INDEX(t,id) ((t) * 100000 + (id))
54 #define printWithArgList g_lingo->printSTUBWithArglist
55 
56 int calcStringAlignment(const char *s);
57 int calcCodeAlignment(int l);
58 
59 typedef Common::Array<inst> ScriptData;
60 
61 struct FuncDesc {
62  Common::String name;
63  const char *proto;
64 
65  FuncDesc(Common::String n, const char *p) { name = n; proto = p; }
66 };
67 
69 
71 
72 struct BuiltinProto {
73  const char *name;
74  void (*func)(int);
75  int minArgs; // -1 -- arglist
76  int maxArgs;
77  int version;
78  SymbolType type;
79 };
80 
81 struct Symbol { /* symbol table entry */
82  Common::String *name;
83  SymbolType type;
84  union {
85  ScriptData *defn; /* HANDLER */
86  void (*func)(); /* OPCODE */
87  void (*bltin)(int); /* BUILTIN */
88  Common::String *s; /* STRING */
89  } u;
90 
91  int *refCount;
92 
93  int nargs; /* number of arguments */
94  int maxArgs; /* maximal number of arguments, for builtins */
95  int targetType; /* valid target objects, for method builtins */
96 
99  ScriptContext *ctx; /* optional script context to execute with */
100  AbstractObject *target; /* optional method target */
101  bool anonymous;
102 
103  Symbol();
104  Symbol(const Symbol &s);
105  Symbol& operator=(const Symbol &s);
106  void reset();
107  ~Symbol();
108 };
109 
110 struct PArray {
111  bool _sorted;
112  PropertyArray arr;
113 
114  PArray() : _sorted(false) {}
115 
116  PArray(int size) : _sorted(false), arr(size) {}
117 };
118 
119 struct FArray {
120  bool _sorted;
121  DatumArray arr;
122 
123  FArray() : _sorted(false) {}
124 
125  FArray(int size) : _sorted(false), arr(size) {}
126 };
127 
128 
129 struct Datum { /* interpreter stack type */
130  DatumType type;
131 
132  union {
133  int i; /* INT, ARGC, ARGCNORET */
134  double f; /* FLOAT */
135  Common::String *s; /* STRING, VARREF, OBJECT */
136  FArray *farr; /* ARRAY, POINT, RECT */
137  PArray *parr; /* PARRAY */
138  AbstractObject *obj; /* OBJECT */
139  ChunkReference *cref; /* CHUNKREF */
140  CastMemberID *cast; /* CASTREF, FIELDREF */
141  MenuReference *menu; /* MENUREF */
142  PictureReference *picture; /* PICTUREREF */
143  } u;
144 
145  int *refCount;
146 
147  bool ignoreGlobal; // True if this Datum should be ignored by showGlobals and clearGlobals
148 
149  Datum();
150  Datum(const Datum &d);
151  Datum& operator=(const Datum &d);
152  Datum(int val);
153  Datum(double val);
154  Datum(const Common::String &val);
155  Datum(AbstractObject *val);
156  Datum(const CastMemberID &val);
157  Datum(const Common::Point &point);
158  Datum(const Common::Rect &rect);
159  void reset();
160 
161  ~Datum() {
162  reset();
163  }
164 
165  Datum eval() const;
166  double asFloat() const;
167  int asInt() const;
168  Common::String asString(bool printonly = false) const;
169  CastMemberID asMemberID(CastType castType = kCastTypeAny) const;
170  Common::Point asPoint() const;
171 
172  bool isRef() const;
173  bool isVarRef() const;
174  bool isCastRef() const;
175  bool isArray() const;
176  bool isNumeric() const;
177 
178  const char *type2str(bool ilk = false) const;
179 
180  int equalTo(Datum &d, bool ignoreCase = false) const;
181  uint32 compareTo(Datum &d) const;
182 
183  bool operator==(Datum &d) const;
184  bool operator>(Datum &d) const;
185  bool operator<(Datum &d) const;
186  bool operator>=(Datum &d) const;
187  bool operator<=(Datum &d) const;
188 };
189 
191  Datum source;
192  ChunkType type;
193  int startChunk;
194  int endChunk;
195  int start;
196  int end;
197 
198  ChunkReference(const Datum &src, ChunkType t, int sc, int ec, int s, int e)
199  : source(src), type(t), startChunk(sc), endChunk(ec), start(s), end(e) {}
200 };
201 
203  int menuIdNum;
204  Common::String *menuIdStr;
205  int menuItemIdNum;
206  Common::String *menuItemIdStr;
207 
208  MenuReference();
209 };
210 
212  Picture *_picture = nullptr;
213  ~PictureReference();
214 };
215 
216 struct PCell {
217  Datum p;
218  Datum v;
219 
220  PCell();
221  PCell(const Datum &prop, const Datum &val);
222 };
223 
224 struct Builtin {
225  void (*func)(void);
226  int nargs;
227 
228  Builtin(void (*func1)(void), int nargs1) : func(func1), nargs(nargs1) {}
229 };
230 
238 typedef void (*XLibOpenerFunc)(ObjectType, const Common::Path &);
239 typedef void (*XLibCloserFunc)(ObjectType);
244 
247 
248 struct CFrame { /* proc/func call stack frame */
249  Symbol sp; /* symbol table entry */
250  int retPC; /* where to resume after return */
251  ScriptData *retScript; /* which script to resume after return */
252  ScriptContext *retContext; /* which script context to use after return */
253  DatumHash *retLocalVars;
254  Datum retMe; /* which me obj to use after return */
255  uint stackSizeBefore;
256  bool allowRetVal; /* whether to allow a return value */
257  Datum defaultRetVal; /* default return value */
258  int paramCount; /* original number of arguments submitted */
259 };
260 
261 struct LingoEvent {
262  LEvent event;
263  int eventId;
264  ScriptType scriptType;
265  CastMemberID scriptId;
266  bool passByDefault;
267  int channelId;
268 
269  LingoEvent (LEvent e, int ei, ScriptType st, CastMemberID si, bool pass, int ci = -1) {
270  event = e;
271  eventId = ei;
272  scriptType = st;
273  scriptId = si;
274  passByDefault = pass;
275  channelId = ci;
276  }
277 };
278 
279 
280 struct LingoArchive {
281  LingoArchive(Cast *c) : cast(c) {};
282  ~LingoArchive();
283 
284  Cast *cast;
285  ScriptContextHash lctxContexts;
286  ScriptContextHash scriptContexts[kMaxScriptType + 1];
287  FactoryContextHash factoryContexts;
289  Common::HashMap<uint32, Common::String> primaryEventHandlers;
290  SymbolHash functionHandlers;
291 
292  ScriptContext *getScriptContext(ScriptType type, uint16 id);
293  ScriptContext *findScriptContext(uint16 id);
294  Common::String getName(uint16 id);
295  Common::String formatFunctionList(const char *prefix);
296 
297  void addCode(const Common::U32String &code, ScriptType type, uint16 id, const char *scriptName = nullptr, uint32 preprocFlags = kLPPNone);
298  void patchCode(const Common::U32String &code, ScriptType type, uint16 id, const char *scriptName = nullptr, uint32 preprocFlags = kLPPNone);
299  void removeCode(ScriptType type, uint16 id);
300  void replaceCode(const Common::U32String &code, ScriptType type, uint16 id, const char *scriptName = nullptr);
301  void addCodeV4(Common::SeekableReadStreamEndian &stream, uint16 lctxIndex, const Common::String &archName, uint16 version);
302  void addNamesV4(Common::SeekableReadStreamEndian &stream);
303 
304  // lingo-patcher.cpp
305  void patchScriptHandler(ScriptType type, CastMemberID id);
306 };
307 
308 struct LingoState {
309  // Execution state for a Lingo process, created every time
310  // a top-level handler is called (e.g. on mouseDown).
311  // Can be swapped out when another script gets called with priority.
312  // Call frames are pushed and popped from the callstack with
313  // pushContext and popContext.
314  Common::Array<CFrame *> callstack; // call stack
315  uint pc = 0; // current program counter
316  ScriptData *script = nullptr; // current Lingo script
317  ScriptContext *context = nullptr; // current Lingo script context
318  DatumHash *localVars = nullptr; // current local variables
319  Datum me; // current me object
320 
321  ~LingoState();
322 };
323 
324 class Lingo {
325 
326 public:
327  Lingo(DirectorEngine *vm);
328  ~Lingo();
329 
330  void resetLingo();
331  void cleanupLingo();
332  void resetLingoGo();
333 
334  int getMenuNum();
335  int getMenuItemsNum(Datum &d);
336  int getXtrasNum();
337  int getCastlibsNum();
338  int getMembersNum();
339 
340  void executeHandler(const Common::String &name);
341  void executeScript(ScriptType type, CastMemberID id);
342  Common::String formatStack();
343  void printStack(const char *s, uint pc);
344  Common::String formatCallStack(uint pc);
345  void printCallStack(uint pc);
346  Common::String formatFrame();
347  Common::String formatCurrentInstruction();
348  Common::String decodeInstruction(ScriptData *sd, uint pc, uint *newPC = NULL);
349  Common::String decodeScript(ScriptData *sd);
350  Common::String formatFunctionName(Symbol &sym);
351  Common::String formatFunctionBody(Symbol &sym);
352 
353  void reloadBuiltIns();
354  void initBuiltIns();
355  void initBuiltIns(BuiltinProto protos[]);
356  void cleanupBuiltIns();
357  void cleanupBuiltIns(BuiltinProto protos[]);
358  void initFuncs();
359  void cleanupFuncs();
360  void initBytecode();
361  void initMethods();
362  void cleanupMethods();
363  void initXLibs();
364  void cleanupXLibs();
365 
366  Common::String normalizeXLibName(Common::String name);
367  void openXLib(Common::String name, ObjectType type, const Common::Path &path);
368  void closeXLib(Common::String name);
369  void closeOpenXLibs();
370  void reloadOpenXLibs();
371 
372  void runTests();
373 
374  // lingo-events.cpp
375 private:
376  void initEventHandlerTypes();
377  void processEvent(LEvent event, ScriptType st, CastMemberID scriptId, int channelId = -1);
378 
379 public:
380  ScriptType event2script(LEvent ev);
381  Symbol getHandler(const Common::String &name);
382 
383  void processEvents(Common::Queue<LingoEvent> &queue);
384 
385 public:
386  void execute();
387  void switchStateFromWindow();
388  void freezeState();
389  void pushContext(const Symbol funcSym, bool allowRetVal, Datum defaultRetVal, int paramCount);
390  void popContext(bool aborting = false);
391  void cleanLocalVars();
392  void varAssign(const Datum &var, const Datum &value);
393  Datum varFetch(const Datum &var, bool silent = false);
394  Common::U32String evalChunkRef(const Datum &var);
395  Datum findVarV4(int varType, const Datum &id);
396  CastMemberID resolveCastMember(const Datum &memberID, const Datum &castLib, CastType type);
397  void exposeXObject(const char *name, Datum obj);
398 
399  int getAlignedType(const Datum &d1, const Datum &d2, bool equality);
400 
401  Common::String formatAllVars();
402  void printAllVars();
403 
404  inst readInst() { return getInst(_state->pc++); }
405  inst getInst(uint pc) { return (*_state->script)[pc]; }
406  int readInt() { return getInt(_state->pc++); }
407  int getInt(uint pc);
408  double readFloat() { double d = getFloat(_state->pc); _state->pc += calcCodeAlignment(sizeof(double)); return d; }
409  double getFloat(uint pc) { return *(double *)(&((*_state->script)[_state->pc])); }
410  char *readString() { char *s = getString(_state->pc); _state->pc += calcStringAlignment(s); return s; }
411  char *getString(uint pc) { return (char *)(&((*_state->script)[_state->pc])); }
412 
413  Datum getVoid();
414  void pushVoid();
415 
416  void printSTUBWithArglist(const char *funcname, int nargs, const char *prefix = "STUB:");
417  void convertVOIDtoString(int arg, int nargs);
418  void dropStack(int nargs);
419  void drop(uint num);
420 
421  void lingoError(const char *s, ...);
422 
423  void func_mci(const Common::String &name);
424  void func_mciwait(const Common::String &name);
425  void func_beep(int repeats);
426  void func_goto(Datum &frame, Datum &movie, bool commandgo = false );
427  void func_gotoloop();
428  void func_gotonext();
429  void func_gotoprevious();
430  void func_play(Datum &frame, Datum &movie);
431  void func_playdone();
432  void func_cursor(Datum cursorDatum);
433  int func_marker(int m);
434  uint16 func_label(Datum &label);
435 
436  // lingo-the.cpp
437 public:
438  void initTheEntities();
439  void cleanUpTheEntities();
440  const char *entity2str(int id);
441  const char *field2str(int id);
442 
443  // global kTheEntity
444  Datum _actorList;
445  Common::u32char_type_t _itemDelimiter;
446  bool _exitLock;
447  bool _preLoadEventAbort; // no-op, everything is always preloaded
448  Datum _searchPath;
449  bool _trace; // state of movie's trace function
450  int _traceLoad; // internal Director verbosity level
451  bool _updateMovieEnabled;
452  bool _romanLingo;
453 
454  Datum getTheEntity(int entity, Datum &id, int field);
455  void setTheEntity(int entity, Datum &id, int field, Datum &d);
456  Datum getTheSprite(Datum &id, int field);
457  void setTheSprite(Datum &id, int field, Datum &d);
458  Datum getTheCast(Datum &id, int field);
459  void setTheCast(Datum &id, int field, Datum &d);
460  Datum getTheField(Datum &id1, int field);
461  void setTheField(Datum &id1, int field, Datum &d);
462  Datum getTheChunk(Datum &chunk, int field);
463  void setTheChunk(Datum &chunk, int field, Datum &d);
464  void getObjectProp(Datum &obj, Common::String &propName);
465  void setObjectProp(Datum &obj, Common::String &propName, Datum &d);
466  Datum getTheDate(int field);
467  Datum getTheTime(int field);
468  Datum getTheDeskTopRectList();
469 
470 private:
471  Common::StringArray _entityNames;
472  Common::StringArray _fieldNames;
473 
474 public:
475  LingoCompiler *_compiler;
476  LingoState *_state;
477 
478  int _currentChannelId;
479 
480  bool _freezeState;
481  bool _abort;
482  bool _expectError;
483  bool _caughtError;
484 
485  TheEntityHash _theEntities;
486  TheEntityFieldHash _theEntityFields;
487 
488  int _objectEntityId;
489 
490  SymbolHash _builtinCmds;
491  SymbolHash _builtinFuncs;
492  SymbolHash _builtinConsts;
493  SymbolHash _builtinListHandlers;
494  SymbolHash _methods;
495  XLibOpenerFuncHash _xlibOpeners;
496  XLibCloserFuncHash _xlibClosers;
497 
498  OpenXLibsHash _openXLibs;
499  OpenXLibsStateHash _openXLibsState;
500 
501  Common::String _floatPrecisionFormat;
502 
503 public:
504  void push(Datum d);
505  Datum pop();
506  Datum peek(uint offset);
507 
508 public:
509  Common::HashMap<uint32, const char *> _eventHandlerTypes;
512 
513  DatumHash _globalvars;
514 
515  FuncHash _functions;
516 
519 
520  uint _globalCounter;
521 
522  StackData _stack;
523 
524  DirectorEngine *_vm;
525 
526  int _floatPrecision;
527 
528  Datum _theResult;
529 
530  // events
531  bool _passEvent;
532  Datum _perFrameHook;
533 
534  Datum _windowList;
535 
536 public:
537  void executeImmediateScripts(Frame *frame);
538  void executePerFrameHook(int frame, int subframe);
539 
540  // lingo-utils.cpp
541 private:
542  Common::HashMap<uint32, Common::U32String> _charNormalizations;
543  void initCharNormalizations();
544 
545 public:
546  Common::String normalizeString(const Common::String &str);
547 };
548 
549 extern Lingo *g_lingo;
550 
551 } // End of namespace Director
552 
553 #endif
Definition: lingo.h:110
Definition: cast.h:80
Definition: lingo.h:81
Definition: str.h:59
Definition: lingo.h:280
Definition: lingo.h:61
Definition: lingo.h:119
Definition: array.h:52
Definition: picture.h:33
Definition: lingo.h:248
Definition: rect.h:144
Definition: path.h:52
Definition: lingo.h:261
Definition: lingo.h:190
Definition: archive.h:35
Definition: queue.h:42
Definition: lingo.h:211
Definition: lingo.h:224
Definition: ustr.h:57
Definition: algorithm.h:29
Definition: rect.h:45
Definition: lingo-codegen.h:30
Definition: lingo.h:129
char32_t u32char_type_t
Definition: ustr.h:41
Definition: lingo.h:202
Definition: stream.h:944
Definition: director.h:147
Definition: lingo.h:72
Definition: lingo-object.h:37
Definition: lingo.h:216
Definition: lobject.h:332
Definition: frame.h:151
Definition: lingo.h:324
Definition: types.h:401
Definition: system.h:37
Definition: lingo-object.h:200
Definition: lingo.h:308