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
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (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, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef DIRECTOR_LINGO_LINGO_H
24 #define DIRECTOR_LINGO_LINGO_H
25 
26 #include "audio/audiostream.h"
27 #include "common/hash-ptr.h"
28 #include "common/hash-str.h"
29 
30 #include "director/director.h"
31 #include "director/score.h"
32 #include "director/lingo/lingo-gr.h"
33 #include "director/lingo/lingo-the.h"
34 
35 namespace Director {
36 
37 enum LEvent {
38 	kEventPrepareMovie,
39 	kEventStartMovie,
40 	kEventStepMovie,
41 	kEventStopMovie,
42 
43 	kEventNew,
44 	kEventBeginSprite,
45 	kEventEndSprite,
46 
47 	kEventNone,
48 	kEventEnterFrame,
49 	kEventPrepareFrame,
50 	kEventIdle,
51 	kEventStepFrame,
52 	kEventExitFrame,
53 	kEventTimeout,
54 
55 	kEventActivateWindow,
56 	kEventDeactivateWindow,
57 	kEventMoveWindow,
58 	kEventResizeWindow,
59 	kEventOpenWindow,
60 	kEventCloseWindow,
61 
62 	kEventKeyUp,
63 	kEventKeyDown,
64 	kEventMouseUp,
65 	kEventMouseDown,
66 	kEventRightMouseUp,
67 	kEventRightMouseDown,
68 	kEventMouseEnter,
69 	kEventMouseLeave,
70 	kEventMouseUpOutSide,
71 	kEventMouseWithin,
72 
73 	kEventStart
74 };
75 
76 typedef void (*inst)(void);
77 #define	STOP (inst)0
78 #define ENTITY_INDEX(t,id) ((t) * 100000 + (id))
79 
80 typedef Common::Array<inst> ScriptData;
81 typedef Common::Array<double> FloatArray;
82 
83 struct FuncDesc {
84 	Common::String name;
85 	const char *proto;
86 
FuncDescFuncDesc87 	FuncDesc(Common::String n, const char *p) { name = n; proto = p; }
88 };
89 
90 typedef Common::HashMap<void *, FuncDesc *> FuncHash;
91 
92 struct Symbol {	/* symbol table entry */
93 	Common::String name;
94 	int type;
95 	union {
96 		int		i;			/* VAR */
97 		double	f;			/* FLOAT */
98 		ScriptData	*defn;	/* FUNCTION, PROCEDURE */
99 		void (*func)();		/* OPCODE */
100 		void (*bltin)(int);	/* BUILTIN */
101 		Common::String	*s;	/* STRING */
102 		FloatArray *arr;	/* ARRAY, POINT, RECT */
103 	} u;
104 	int nargs;		/* number of arguments */
105 	int maxArgs;	/* maximal number of arguments, for builtins */
106 	bool parens;	/* whether parens required or not, for builitins */
107 
108 	bool global;
109 
110 	Symbol();
111 };
112 
113 struct Datum {	/* interpreter stack type */
114 	int type;
115 
116 	union {
117 		int	i;
118 		double f;
119 		Common::String *s;
120 		Symbol	*sym;
121 		FloatArray *arr;	/* ARRAY, POINT, RECT */
122 	} u;
123 
DatumDatum124 	Datum() { u.sym = NULL; type = VOID; }
DatumDatum125 	Datum(int val) { u.i = val; type = INT; }
DatumDatum126 	Datum(double val) { u.f = val; type = FLOAT; }
DatumDatum127 	Datum(Common::String *val) { u.s = val; type = STRING; }
128 
129 	double toFloat();
130 	int toInt();
131 	Common::String *toString();
132 
133 	const char *type2str(bool isk = false);
134 };
135 
136 struct Builtin {
137 	void (*func)(void);
138 	int nargs;
139 
BuiltinBuiltin140 	Builtin(void (*func1)(void), int nargs1) : func(func1), nargs(nargs1) {}
141 };
142 
143 typedef Common::HashMap<int32, ScriptData *> ScriptHash;
144 typedef Common::Array<Datum> StackData;
145 typedef Common::HashMap<Common::String, Symbol *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SymbolHash;
146 typedef Common::HashMap<Common::String, Builtin *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> BuiltinHash;
147 
148 typedef Common::HashMap<Common::String, TheEntity *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> TheEntityHash;
149 typedef Common::HashMap<Common::String, TheEntityField *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> TheEntityFieldHash;
150 
151 struct CFrame {	/* proc/func call stack frame */
152 	Symbol	*sp;	/* symbol table entry */
153 	int		retpc;	/* where to resume after return */
154 	ScriptData	*retscript;	 /* which script to resume after return */
155 	SymbolHash *localvars;
156 };
157 
158 class Lingo {
159 public:
160 	Lingo(DirectorEngine *vm);
161 	~Lingo();
162 
163 	void restartLingo();
164 
165 	void addCode(const char *code, ScriptType type, uint16 id);
166 	void executeScript(ScriptType type, uint16 id);
167 	void printStack(const char *s);
168 	Common::String decodeInstruction(uint pc, uint *newPC = NULL);
169 
170 	void initBuiltIns();
171 	void initFuncs();
172 	void initTheEntities();
173 
174 	void runTests();
175 
176 private:
177 	const char *findNextDefinition(const char *s);
178 
179 	// lingo-events.cpp
180 private:
181 	void initEventHandlerTypes();
182 	void primaryEventHandler(LEvent event);
183 	void processInputEvent(LEvent event);
184 	void processFrameEvent(LEvent event);
185 	void processGenericEvent(LEvent event);
186 	void runMovieScript(LEvent event);
187 	void processSpriteEvent(LEvent event);
188 	void processEvent(LEvent event, ScriptType st, int entityId);
189 public:
190 	ScriptType event2script(LEvent ev);
191 	Symbol *getHandler(Common::String &name);
192 
193 	void processEvent(LEvent event);
194 
195 public:
196 	void execute(uint pc);
197 	void pushContext();
198 	void popContext();
199 	Symbol *lookupVar(const char *name, bool create = true, bool putInGlobalList = false);
200 	void cleanLocalVars();
201 	void define(Common::String &s, int start, int nargs, Common::String *prefix = NULL, int end = -1);
202 	void processIf(int elselabel, int endlabel);
203 
204 	int alignTypes(Datum &d1, Datum &d2);
205 
code1(inst code)206 	int code1(inst code) { _currentScript->push_back(code); return _currentScript->size() - 1; }
code2(inst code_1,inst code_2)207 	int code2(inst code_1, inst code_2) { int o = code1(code_1); code1(code_2); return o; }
code3(inst code_1,inst code_2,inst code_3)208 	int code3(inst code_1, inst code_2, inst code_3) { int o = code1(code_1); code1(code_2); code1(code_3); return o; }
209 	int codeString(const char *s);
210 	void codeLabel(int label);
211 	int codeConst(int val);
212 	int codeArray(int arraySize);
213 
calcStringAlignment(const char * s)214 	int calcStringAlignment(const char *s) {
215 		return calcCodeAlignment(strlen(s) + 1);
216 	}
calcCodeAlignment(int l)217 	int calcCodeAlignment(int l) {
218 		int instLen = sizeof(inst);
219 		return (l + instLen - 1) / instLen;
220 	}
221 
222 	void codeArg(Common::String *s);
223 	void codeArgStore();
224 	int codeSetImmediate(bool state);
225 	int codeFunc(Common::String *s, int numpar);
226 	int codeMe(Common::String *method, int numpar);
227 	int codeFloat(double f);
228 	void codeFactory(Common::String &s);
229 
230 	void pushVoid();
231 
232 	static void c_xpop();
233 	static void c_printtop();
234 
235 	static void c_add();
236 	static void c_sub();
237 	static void c_mul();
238 	static void c_div();
239 	static void c_mod();
240 	static void c_negate();
241 
242 	static void c_and();
243 	static void c_or();
244 	static void c_not();
245 
246 	static void c_ampersand();
247 	static void c_after();
248 	static void c_before();
249 	static void c_concat();
250 	static void c_contains();
251 	static void c_starts();
252 
253 	static void c_intersects();
254 	static void c_within();
255 	static void c_charOf();
256 	static void c_charToOf();
257 	static void c_itemOf();
258 	static void c_itemToOf();
259 	static void c_lineOf();
260 	static void c_lineToOf();
261 	static void c_wordOf();
262 	static void c_wordToOf();
263 
264 	static void c_constpush();
265 	static void c_voidpush();
266 	static void c_fconstpush();
267 	static void c_stringpush();
268 	static void c_symbolpush();
269 	static void c_varpush();
270 	static void c_arraypush();
271 	static void c_assign();
272 	bool verify(Symbol *s);
273 	static void c_eval();
274 	static void c_setImmediate();
275 
276 	static void c_swap();
277 
278 	static void c_theentitypush();
279 	static void c_theentityassign();
280 
281 	static void c_repeatwhilecode();
282 	static void c_repeatwithcode();
283 	static void c_ifcode();
284 	static void c_whencode();
285 	static void c_tellcode();
286 	static void c_exitRepeat();
287 	static void c_eq();
288 	static void c_neq();
289 	static void c_gt();
290 	static void c_lt();
291 	static void c_ge();
292 	static void c_le();
293 	static void c_call();
294 
295 	void call(Common::String name, int nargs);
296 
297 	static void c_procret();
298 
299 	static void c_mci();
300 	static void c_mciwait();
301 	static void c_goto();
302 	static void c_gotoloop();
303 	static void c_gotonext();
304 	static void c_gotoprevious();
305 	static void c_global();
306 	static void c_instance();
307 	static void c_property();
308 
309 	static void c_play();
310 	static void c_playdone();
311 
312 	static void c_open();
313 
314 	void printSTUBWithArglist(const char *funcname, int nargs, const char *prefix = "STUB:");
315 	void convertVOIDtoString(int arg, int nargs);
316 	void dropStack(int nargs);
317 	void drop(uint num);
318 
319 	static void b_abs(int nargs);
320 	static void b_atan(int nargs);
321 	static void b_cos(int nargs);
322 	static void b_exp(int nargs);
323 	static void b_float(int nargs);
324 	static void b_integer(int nargs);
325 	static void b_log(int nargs);
326 	static void b_pi(int nargs);
327 	static void b_power(int nargs);
328 	static void b_random(int nargs);
329 	static void b_sin(int nargs);
330 	static void b_sqrt(int nargs);
331 	static void b_tan(int nargs);
332 
333 	static void b_chars(int nargs);
334 	static void b_charToNum(int nargs);
335 	static void b_delete(int nargs);
336 	static void b_hilite(int nargs);
337 	static void b_length(int nargs);
338 	static void b_numToChar(int nargs);
339 	static void b_offset(int nargs);
340 	static void b_string(int nargs);
341 
342 	static void b_add(int nargs);
343 	static void b_addAt(int nargs);
344 	static void b_addProp(int nargs);
345 	static void b_append(int nargs);
346 	static void b_count(int nargs);
347 	static void b_deleteAt(int nargs);
348 	static void b_deleteProp(int nargs);
349 	static void b_findPos(int nargs);
350 	static void b_findPosNear(int nargs);
351 	static void b_getaProp(int nargs);
352 	static void b_getAt(int nargs);
353 	static void b_getLast(int nargs);
354 	static void b_getOne(int nargs);
355 	static void b_getPos(int nargs);
356 	static void b_getProp(int nargs);
357 	static void b_getPropAt(int nargs);
358 	static void b_list(int nargs);
359 	static void b_listP(int nargs);
360 	static void b_max(int nargs);
361 	static void b_min(int nargs);
362 	static void b_setaProp(int nargs);
363 	static void b_setAt(int nargs);
364 	static void b_setProp(int nargs);
365 	static void b_sort(int nargs);
366 
367 	static void b_floatP(int nargs);
368 	static void b_ilk(int nargs);
369 	static void b_integerp(int nargs);
370 	static void b_objectp(int nargs);
371 	static void b_pictureP(int nargs);
372 	static void b_stringp(int nargs);
373 	static void b_symbolp(int nargs);
374 	static void b_voidP(int nargs);
375 
376 	static void b_alert(int nargs);
377 	static void b_birth(int nargs);
378 	static void b_clearGlobals(int nargs);
379 	static void b_cursor(int nargs);
380 	static void b_framesToHMS(int nargs);
381 	static void b_HMStoFrames(int nargs);
382 	static void b_param(int nargs);
383 	static void b_printFrom(int nargs);
384 	static void b_showGlobals(int nargs);
385 	static void b_showLocals(int nargs);
386 	static void b_value(int nargs);
387 
388 	static void b_constrainH(int nargs);
389 	static void b_constrainV(int nargs);
390 	static void b_copyToClipBoard(int nargs);
391 	static void b_duplicate(int nargs);
392 	static void b_editableText(int nargs);
393 	static void b_erase(int nargs);
394 	static void b_findEmpty(int nargs);
395 	static void b_importFileInto(int nargs);
396 	static void b_installMenu(int nargs);
397 	static void b_label(int nargs);
398 	static void b_marker(int nargs);
399 	static void b_move(int nargs);
400 	static void b_moveableSprite(int nargs);
401 	static void b_pasteClipBoardInto(int nargs);
402 	static void b_puppetPalette(int nargs);
403 	static void b_puppetSound(int nargs);
404 	static void b_puppetSprite(int nargs);
405 	static void b_puppetTempo(int nargs);
406 	static void b_puppetTransition(int nargs);
407 	static void b_ramNeeded(int nargs);
408 	static void b_rollOver(int nargs);
409 	static void b_spriteBox(int nargs);
410 	static void b_unLoad(int nargs);
411 	static void b_unLoadCast(int nargs);
412 	static void b_updateStage(int nargs);
413 	static void b_zoomBox(int nargs);
414 
415 	static void b_abort(int nargs);
416 	static void b_continue(int nargs);
417 	static void b_dontPassEvent(int nargs);
418 	static void b_delay(int nargs);
419 	static void b_do(int nargs);
420 	static void b_halt(int nargs);
421 	static void b_nothing(int nargs);
422 	static void b_pass(int nargs);
423 	static void b_pause(int nargs);
424 	static void b_playAccel(int nargs);
425 	static void b_preLoad(int nargs);
426 	static void b_preLoadCast(int nargs);
427 	static void b_quit(int nargs);
428 	static void b_restart(int nargs);
429 	static void b_shutDown(int nargs);
430 	static void b_startTimer(int nargs);
431 
432 	static void b_closeDA(int nargs);
433 	static void b_closeResFile(int nargs);
434 	static void b_closeXlib(int nargs);
435 	static void b_getNthFileNameInFolder(int nargs);
436 	static void b_openDA(int nargs);
437 	static void b_openResFile(int nargs);
438 	static void b_openXlib(int nargs);
439 	static void b_setCallBack(int nargs);
440 	static void b_saveMovie(int nargs);
441 	static void b_showResFile(int nargs);
442 	static void b_showXlib(int nargs);
443 	static void b_xFactoryList(int nargs);
444 
445 	static void b_point(int nargs);
446 	static void b_inside(int nargs);
447 	static void b_intersect(int nargs);
448 	static void b_map(int nargs);
449 	static void b_offsetRect(int nargs);
450 	static void b_rect(int nargs);
451 	static void b_union(int nargs);
452 
453 	static void b_close(int nargs);
454 	static void b_forget(int nargs);
455 	static void b_inflate(int nargs);
456 	static void b_moveToBack(int nargs);
457 	static void b_moveToFront(int nargs);
458 	static void b_window(int nargs);
459 
460 	static void b_beep(int nargs);
461 	static void b_mci(int nargs);
462 	static void b_mciwait(int nargs);
463 	static void b_soundBusy(int nargs);
464 	static void b_soundClose(int nargs);
465 	static void b_soundFadeIn(int nargs);
466 	static void b_soundFadeOut(int nargs);
467 	static void b_soundPlayFile(int nargs);
468 	static void b_soundStop(int nargs);
469 
470 	static void b_ancestor(int nargs);
471 	static void b_backspace(int nargs);
472 	static void b_empty(int nargs);
473 	static void b_enter(int nargs);
474 	static void b_false(int nargs);
475 	static void b_quote(int nargs);
476 	static void b_return(int nargs);
477 	static void b_tab(int nargs);
478 	static void b_true(int nargs);
479 	static void b_version(int nargs);
480 
481 	static void b_factory(int nargs);
482 	void factoryCall(Common::String &name, int nargs);
483 
484 	static void b_cast(int nargs);
485 	static void b_field(int nargs);
486 	static void b_me(int nargs);
487 	static void b_script(int nargs);
488 
489 	void func_mci(Common::String &s);
490 	void func_mciwait(Common::String &s);
491 	void func_beep(int repeats);
492 	void func_goto(Datum &frame, Datum &movie);
493 	void func_gotoloop();
494 	void func_gotonext();
495 	void func_gotoprevious();
496 	void func_play(Datum &frame, Datum &movie);
497 	void func_playdone();
498 	void func_cursor(int c);
499 	int func_marker(int m);
500 
501 public:
502 	void setTheEntity(int entity, Datum &id, int field, Datum &d);
503 	void setTheSprite(Datum &id, int field, Datum &d);
504 	void setTheCast(Datum &id, int field, Datum &d);
505 	Datum getTheEntity(int entity, Datum &id, int field);
506 	Datum getTheSprite(Datum &id, int field);
507 	Datum getTheCast(Datum &id, int field);
508 
509 public:
510 	ScriptData *_currentScript;
511 	ScriptType _currentScriptType;
512 	uint16 _currentEntityId;
513 	bool _returning;
514 	bool _indef;
515 	bool _ignoreMe;
516 	bool _immediateMode;
517 
518 	Common::Array<CFrame *> _callstack;
519 	Common::Array<Common::String *> _argstack;
520 	TheEntityHash _theEntities;
521 	TheEntityFieldHash _theEntityFields;
522 	Common::Array<int> _labelstack;
523 
524 	SymbolHash _builtins;
525 	Common::HashMap<Common::String, bool> _twoWordBuiltins;
526 	Common::HashMap<uint32, Symbol *> _handlers;
527 
528 	int _linenumber;
529 	int _colnumber;
530 
531 	Common::String _floatPrecisionFormat;
532 
533 	bool _hadError;
534 
535 	bool _inFactory;
536 	Common::String _currentFactory;
537 
538 	bool _exitRepeat;
539 
540 	bool _cursorOnStack;
541 
542 private:
543 	int parse(const char *code);
544 	void parseMenu(const char *code);
545 
546 	void push(Datum d);
547 	Datum pop(void);
548 
549 	Common::HashMap<uint32, const char *> _eventHandlerTypes;
550 	Common::HashMap<Common::String, uint32> _eventHandlerTypeIds;
551 	Common::HashMap<Common::String, Audio::AudioStream *> _audioAliases;
552 
553 	ScriptHash _scripts[kMaxScriptType + 1];
554 
555 	SymbolHash _globalvars;
556 	SymbolHash *_localvars;
557 
558 	FuncHash _functions;
559 
560 	uint _pc;
561 
562 	StackData _stack;
563 
564 	DirectorEngine *_vm;
565 
566 	int _floatPrecision;
567 
568 	bool dontPassEvent;
569 
570 public:
571 	void executeImmediateScripts(Frame *frame);
572 };
573 
574 extern Lingo *g_lingo;
575 
576 } // End of namespace Director
577 
578 #endif
579