1 /* ScummVM Tools
2  *
3  * ScummVM Tools is the legal property of its developers, whose
4  * names are too numerous to list here. Please refer to the
5  * COPYRIGHT 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 /* Scumm Script Disassembler (version 6-8 scripts) */
23 
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 
28 #include "descumm.h"
29 
30 #include "common/util.h"
31 
32 /*
33 switch/case statements have a pattern that look as follows (they were probably
34 generated by some Scumm script compiler):
35 
36 push SOMETHING		- the value we are switching on
37 dup					- duplicate it
38 push caseA			- push the first case value
39 eq					- compare
40 jump if false		- if not equal, jump to next case
41   kill				- we entered this case - kill the switch value from the stack
42   ...
43   jump AFTER		- leave this switch
44 dup
45 push caseB
46 eq
47 jump if false
48   kill
49   ...
50   jump AFTER
51 [optional: default case here ?!?]
52 AFTER:
53 
54 
55 Unfortunatly, in reality it is somewhat more complicated. E.g. in script 55,
56 in some cases the "jump AFTER" instead jumps into the middle of some other case.
57 Maybe they did have some sort of code optimized after all?
58 
59 Anyway, the fixed key pattern here seems to be for each case:
60   dup - push - eq - jumpFalse - kill
61 And of course a push before the first of these. Note that there doesn't have
62 to be a jump before each case: after all, "fall through" is possible with C(++)
63 switch/case statements, too, so it's possible they used that in Scumm, too.
64 
65 */
66 
67 class StackEnt;
68 
69 const char *getVarName(uint var);
70 StackEnt *pop();
71 
72 
73 static int dupindex = 0;
74 
75 
76 
77 enum StackEntType {
78 	seInt = 1,
79 	seVar = 2,
80 	seArray = 3,
81 	seBinary = 4,
82 	seUnary = 5,
83 	seComplex = 6,
84 	seStackList = 7,
85 	seDup = 8,
86 	seNeg = 9
87 };
88 
89 enum {
90 	isZero,
91 	isEqual,
92 	isNotEqual,
93 	isGreater,
94 	isLess,
95 	isLessEqual,
96 	isGreaterEqual,
97 	operAdd,
98 	operSub,
99 	operMul,
100 	operDiv,
101 	operLand,
102 	operLor,
103 	operBand,
104 	operBor,
105 	operMod
106 };
107 
108 static const char *oper_list[] = {
109 	"!",
110 	"==",
111 	"!=",
112 	">",
113 	"<",
114 	"<=",
115 	">=",
116 	"+",
117 	"-",
118 	"*",
119 	"/",
120 	"&&",
121 	"||",
122 	"&",
123 	"|",
124 	"%"
125 };
126 
127 
128 
129 class StackEnt {
130 public:
131 	StackEntType type;
132 
133 public:
~StackEnt()134 	virtual ~StackEnt() {}
135 	virtual char *asText(char *where, bool wantparens = true) const = 0;
136 	virtual StackEnt* dup(char *output);
137 
getIntVal() const138 	virtual int getIntVal() const { error("getIntVal call on StackEnt type %d", type); }
139 };
140 
141 class IntStackEnt : public StackEnt {
142 	int _val;
143 public:
IntStackEnt(int val)144 	IntStackEnt(int val) : _val(val) { type = seInt; }
asText(char * where,bool wantparens) const145 	virtual char *asText(char *where, bool wantparens) const {
146 		where += sprintf(where, "%d", _val);
147 		return where;
148 	}
dup(char * output)149 	virtual StackEnt* dup(char *output) {
150 		return new IntStackEnt(_val);
151 	}
getIntVal() const152 	virtual int getIntVal() const { return _val; }
153 };
154 
155 class VarStackEnt : public StackEnt {
156 	int _var;
157 public:
VarStackEnt(int var)158 	VarStackEnt(int var) : _var(var) { type = seVar; }
asText(char * where,bool wantparens=true) const159 	virtual char *asText(char *where, bool wantparens = true) const {
160 		int var;
161 		const char *s;
162 		if (g_options.scriptVersion == 8) {
163 			if (!(_var & 0xF0000000)) {
164 				var = _var & 0xFFFFFFF;
165 				if ((s = getVarName(var)) != NULL)
166 					where = strecpy(where, s);
167 				else
168 					where += sprintf(where, "var%d", _var & 0xFFFFFFF);
169 			} else if (_var & 0x80000000) {
170 				where += sprintf(where, "bitvar%d", _var & 0x7FFFFFFF);
171 			} else if (_var & 0x40000000) {
172 				where += sprintf(where, "localvar%d", _var & 0xFFFFFFF);
173 			} else {
174 				where += sprintf(where, "?var?%d", _var);
175 			}
176 		} else {
177 			if (!(_var & 0xF000)) {
178 				var = _var & 0xFFF;
179 				if ((s = getVarName(var)) != NULL)
180 					where = strecpy(where, s);
181 				else
182 					where += sprintf(where, "var%d", _var & 0xFFF);
183 			} else if (_var & 0x8000) {
184 				if (g_options.heVersion >= 80) {
185 					where += sprintf(where, "roomvar%d", _var & 0xFFF);
186 				} else {
187 					where += sprintf(where, "bitvar%d", _var & 0x7FFF);
188 				}
189 			} else if (_var & 0x4000) {
190 				where += sprintf(where, "localvar%d", _var & 0xFFF);
191 			} else {
192 				where += sprintf(where, "?var?%d", _var);
193 			}
194 		}
195 		return where;
196 	}
197 };
198 
199 class ArrayStackEnt : public StackEnt {
200 	int _idx;
201 	StackEnt *_dim1;
202 	StackEnt *_dim2;
203 public:
ArrayStackEnt(int idx,StackEnt * dim2,StackEnt * dim1)204 	ArrayStackEnt(int idx, StackEnt *dim2, StackEnt *dim1) : _idx(idx), _dim1(dim1), _dim2(dim2) { type = seArray; }
asText(char * where,bool wantparens) const205 	virtual char *asText(char *where, bool wantparens) const {
206 		const char *s;
207 
208 		if(g_options.scriptVersion == 8 && !(_idx & 0xF0000000) &&
209 		   (s = getVarName(_idx & 0xFFFFFFF)) != NULL)
210 			where += sprintf(where, "%s[",s);
211 		else if(g_options.scriptVersion < 8 && !(_idx & 0xF000) &&
212 			(s = getVarName(_idx & 0xFFF)) != NULL)
213 			where += sprintf(where, "%s[",s);
214 		else if(g_options.scriptVersion < 8 && g_options.heVersion >= 80 && (_idx & 0x8000))
215 			where += sprintf(where, "roomarray%d[", _idx & 0xfff);
216 		else if(g_options.scriptVersion < 8 && (_idx & 0x4000))
217 			where += sprintf(where, "localarray%d[", _idx & 0xfff);
218 		else
219 			where += sprintf(where, "array%d[", _idx);
220 
221 		if (_dim2) {
222 			where = _dim2->asText(where);
223 			where = strecpy(where, "][");
224 		}
225 
226 		where = _dim1->asText(where);
227 		where = strecpy(where, "]");
228 
229 		return where;
230 	}
231 };
232 
233 class UnaryOpStackEnt : public StackEnt {
234 	int _op;
235 	StackEnt *_valA;
236 public:
UnaryOpStackEnt(int op,StackEnt * valA)237 	UnaryOpStackEnt(int op, StackEnt *valA) : _op(op), _valA(valA) { type = seUnary; }
asText(char * where,bool wantparens) const238 	virtual char *asText(char *where, bool wantparens) const {
239 		where += sprintf(where, "%s", oper_list[_op]);
240 		where = _valA->asText(where);
241 		return where;
242 	}
243 };
244 
245 class BinaryOpStackEnt : public StackEnt {
246 	int _op;
247 	StackEnt *_valA;
248 	StackEnt *_valB;
249 public:
BinaryOpStackEnt(int op,StackEnt * valA,StackEnt * valB)250 	BinaryOpStackEnt(int op, StackEnt *valA, StackEnt *valB) : _op(op), _valA(valA), _valB(valB) { type = seBinary; }
asText(char * where,bool wantparens) const251 	virtual char *asText(char *where, bool wantparens) const {
252 		if (wantparens)
253 			*where++ = '(';
254 		where = _valA->asText(where);
255 		where += sprintf(where, " %s ", oper_list[_op]);
256 		where = _valB->asText(where);
257 		if (wantparens)
258 			*where++ = ')';
259 		*where = 0;
260 		return where;
261 	}
262 };
263 
264 class ComplexStackEnt : public StackEnt {
265 	char *_str;
266 public:
ComplexStackEnt(const char * s)267 	ComplexStackEnt(const char *s) { _str = strdup(s); type = seComplex; }
~ComplexStackEnt()268 	~ComplexStackEnt() { free(_str); }
asText(char * where,bool wantparens) const269 	virtual char *asText(char *where, bool wantparens) const {
270 		where = strecpy(where, _str);
271 		return where;
272 	}
273 };
274 
275 class ListStackEnt : public StackEnt {
276 public:
277 	int _size;
278 	StackEnt **_list;
279 public:
ListStackEnt(StackEnt * senum)280 	ListStackEnt(StackEnt *senum) {
281 		type = seStackList;
282 
283 		_size = senum->getIntVal();
284 		_list = new StackEnt* [_size];
285 
286 		for (int i = 0; i < _size; ++i) {
287 			_list[i] = pop();
288 		}
289 	}
~ListStackEnt()290 	~ListStackEnt() { delete [] _list; }
asText(char * where,bool wantparens) const291 	virtual char *asText(char *where, bool wantparens) const {
292 		*where++ = '[';
293 		for (int i = _size - 1; i >= 0; --i) {
294 			where = _list[i]->asText(where);
295 			if (i)
296 				*where++ = ',';
297 		}
298 		*where++ = ']';
299 		*where = 0;
300 		return where;
301 	}
302 };
303 
304 class DupStackEnt : public StackEnt {
305 public:
306 	int _idx;
307 public:
DupStackEnt(int idx)308 	DupStackEnt(int idx) : _idx(idx) { type = seDup; }
asText(char * where,bool wantparens) const309 	virtual char *asText(char *where, bool wantparens) const {
310 		where += sprintf(where, "dup[%d]", _idx);
311 		return where;
312 	}
313 };
314 
315 class NegStackEnt : public StackEnt {
316 	StackEnt *_op;
317 public:
NegStackEnt(StackEnt * op)318 	NegStackEnt(StackEnt *op) : _op(op) { type = seNeg; }
asText(char * where,bool wantparens) const319 	virtual char *asText(char *where, bool wantparens) const {
320 		*where++ = '!';
321 		where = _op->asText(where);
322 		return where;
323 	}
324 };
325 #define MAX_STACK_SIZE	256
326 static StackEnt *stack[MAX_STACK_SIZE];
327 static int num_stack = 0;
328 
329 const char *var_names72[] = {
330 	/* 0 */
331 	"VAR_KEYPRESS",
332 	"VAR_DEBUGMODE",
333 	"VAR_TIMER_NEXT",
334 	"VAR_OVERRIDE",
335 	/* 4 */
336 	"VAR_WALKTO_OBJ",
337 	"VAR_RANDOM_NR",
338 	NULL,
339 	NULL,
340 	/* 8 */
341 	"VAR_GAME_LOADED",
342 	"VAR_EGO",
343 	"VAR_NUM_ACTOR",
344 	NULL,
345 	/* 12 */
346 	NULL,
347 	"VAR_VIRT_MOUSE_X",
348 	"VAR_VIRT_MOUSE_Y",
349 	"VAR_MOUSE_X",
350 	/* 16 */
351 	"VAR_MOUSE_Y",
352 	"VAR_LEFTBTN_HOLD",
353 	"VAR_RIGHTBTN_HOLD",
354 	"VAR_CURSORSTATE",
355 	/* 20 */
356 	"VAR_USERPUT",
357 	"VAR_ROOM",
358 	"VAR_ROOM_WIDTH",
359 	"VAR_ROOM_HEIGHT",
360 	/* 24 */
361 	"VAR_CAMERA_POS_X",
362 	"VAR_CAMERA_MIN_X",
363 	"VAR_CAMERA_MAX_X",
364 	"VAR_ROOM_RESOURCE",
365 	/* 28 */
366 	"VAR_SCROLL_SCRIPT",
367 	"VAR_ENTRY_SCRIPT",
368 	"VAR_ENTRY_SCRIPT2",
369 	"VAR_EXIT_SCRIPT",
370 	/* 32 */
371 	"VAR_EXIT_SCRIPT2",
372 	"VAR_VERB_SCRIPT",
373 	"VAR_SENTENCE_SCRIPT",
374 	"VAR_INVENTORY_SCRIPT",
375 	/* 36 */
376 	"VAR_CUTSCENE_START_SCRIPT",
377 	"VAR_CUTSCENE_END_SCRIPT",
378 	"VAR_SAVELOAD_ENTER_SCRIPT",
379 	"VAR_SAVELOAD_EXIT_SCRIPT",
380 	/* 40 */
381 	"VAR_SAVELOAD_SCRIPT",
382 	"VAR_OPTIONS_SCRIPT",
383 	"VAR_RESTART_KEY",
384 	"VAR_PAUSE_KEY",
385 	/* 44 */
386 	"VAR_CUTSCENEEXIT_KEY",
387 	"VAR_TALKSTOP_KEY",
388 	"VAR_HAVE_MSG",
389 	"VAR_NOSUBTITLES",
390 	/* 48 */
391 	"VAR_CHARINC",
392 	"VAR_TALK_ACTOR",
393 	"VAR_LAST_SOUND",
394 	"VAR_TALK_CHANNEL",
395 	/* 52 */
396 	"VAR_SOUND_CHANNEL",
397 	NULL,
398 	"VAR_SOUND_ENABLED",
399 	NULL,
400 	/* 56 */
401 	"VAR_NUM_SOUND_CHANNELS",
402 	"VAR_MEMORY_PERFORMANCE",
403 	"VAR_VIDEO_PERFORMANCE",
404 	"VAR_NEW_ROOM",
405 	/* 60 */
406 	"VAR_TMR_1",
407 	"VAR_TMR_2",
408 	"VAR_TMR_3",
409 	"VAR_TIMEDATE_HOUR",
410 	/* 64 */
411 	"VAR_TIMEDATE_MINUTE",
412 	"VAR_TIMEDATE_DAY",
413 	"VAR_TIMEDATE_MONTH",
414 	"VAR_TIMEDATE_YEAR",
415 	/* 68 */
416 	"VAR_NUM_ROOMS",
417 	"VAR_NUM_SCRIPTS",
418 	"VAR_NUM_SOUNDS",
419 	"VAR_NUM_COSTUMES",
420 	/* 72 */
421 	"VAR_NUM_IMAGES",
422 	"VAR_NUM_CHARSETS",
423 	"VAR_NUM_GLOBAL_OBJS",
424 	"VAR_MOUSE_STATE",
425 	/* 76 */
426 	"VAR_POLYGONS_ONLY",
427 	NULL,
428 	"VAR_PLATFORM",
429 	"VAR_PLATFORM_VERSION",
430 	/* 80 */
431 	"VAR_CURRENT_CHARSET",
432 	"VAR_HIDE_ALL_TEXT",
433 	"VAR_NO_SPEECH",
434 	"VAR_MOUSE_OVERRIDE",
435 	/* 84 */
436 	"VAR_SOUNDCODE_TMR",
437 	"VAR_DEBUG_ENABLED",
438 	"VAR_KEY_STATE",
439 	NULL,
440 	/* 88 */
441 	"VAR_NUM_SOUND_CHANNELS",
442 	"VAR_COLOR_DEPTH",
443 	NULL,
444 	"VAR_PRINTING_ENABED",
445 	/* 92 */
446 	"VAR_FADE_COLOR",
447 	"VAR_BLACK_COLOR",
448 	"VAR_WHITE_COLOR",
449 	"VAR_REDRAW_ALL_ACTORS",
450 	/* 96 */
451 	"VAR_TIMER_1",
452 	"VAR_TIMER_2",
453 	"VAR_NETWORK_START_SCRIPT",
454 	"VAR_NETWORK_TIMEOUT",
455 	/* 100 */
456 	"VAR_NETWORK_ENABLED",
457 	"VAR_NETWORK_ARRAY_SCRIPT",
458 	NULL,
459 	"VAR_SCRIPT_CYCLE",
460 	/* 104 */
461 	"VAR_NUM_SCRIPT_CYCLES",
462 	"VAR_NUM_SPRITE_GROUPS",
463 	"VAR_NUM_SPRITES",
464 	"VAR_U32_VERSION",
465 	/* 108 */
466 	NULL,
467 	NULL,
468 	NULL,
469 	NULL,
470 	/* 112 */
471 	NULL,
472 	NULL,
473 	NULL,
474 	NULL,
475 	/* 116 */
476 	"VAR_U32_ARRAY_UNK",
477 	"VAR_WIZ_TCOLOR",
478 	"VAR_SMACKER_ENABLED",
479 	"VAR_ERROR_CODE",
480 	/* 120 */
481 	"VAR_RESERVED_SOUND_CHANNELS",
482 	NULL,
483 	"VAR_JOYSTICK_UNK1",
484 	"VAR_JOYSTICK_UNK2",
485 	/* 124 */
486 	"VAR_JOYSTICK_DETECTED",
487 	"VAR_SKIP_RESET_TALK_ACTOR",
488 	"VAR_UPDATE_SCREEN_TYPE",
489 	"VAR_MAIN_SCRIPT",
490 	/* 128 */
491 	"VAR_JOYSTICK_DISABLED",
492 	"VAR_BASE_NAME",
493 	"VAR_NUM_PALETTES",
494 	"VAR_NUM_WINDOWS",
495 	/* 132 */
496 	NULL,
497 	NULL,
498 	NULL,
499 	NULL,
500 	/* 136 */
501 	NULL,
502 	NULL,
503 	NULL,
504 	"VAR_SET_SPRITE_DIFF",
505 	/* 140 */
506 	"VAR_BINK_ENABLED",
507 	NULL,
508 	NULL,
509 	NULL,
510 };
511 
512 const char *var_names6[] = {
513 	/* 0 */
514 	NULL,
515 	"VAR_EGO",
516 	"VAR_CAMERA_POS_X",
517 	"VAR_HAVE_MSG",
518 	/* 4 */
519 	"VAR_ROOM",
520 	"VAR_OVERRIDE",
521 	"VAR_MACHINE_SPEED",
522 	NULL,
523 	/* 8 */
524 	"VAR_NUM_ACTOR",
525 	"VAR_V6_SOUNDMODE",
526 	"VAR_CURRENTDRIVE",
527 	"VAR_TMR_1",
528 	/* 12 */
529 	"VAR_TMR_2",
530 	"VAR_TMR_3",
531 	NULL,
532 	NULL,
533 	/* 16 */
534 	NULL,
535 	"VAR_CAMERA_MIN_X",
536 	"VAR_CAMERA_MAX_X",
537 	"VAR_TIMER_NEXT",
538 	/* 20 */
539 	"VAR_VIRT_MOUSE_X",
540 	"VAR_VIRT_MOUSE_Y",
541 	"VAR_ROOM_RESOURCE",
542 	"VAR_LAST_SOUND",
543 	/* 24 */
544 	"VAR_CUTSCENEEXIT_KEY",
545 	"VAR_TALK_ACTOR",
546 	"VAR_CAMERA_FAST_X",
547 	"VAR_SCROLL_SCRIPT",
548 	/* 28 */
549 	"VAR_ENTRY_SCRIPT",
550 	"VAR_ENTRY_SCRIPT2",
551 	"VAR_EXIT_SCRIPT",
552 	"VAR_EXIT_SCRIPT2",
553 	/* 32 */
554 	"VAR_VERB_SCRIPT",
555 	"VAR_SENTENCE_SCRIPT",
556 	"VAR_INVENTORY_SCRIPT",
557 	"VAR_CUTSCENE_START_SCRIPT",
558 	/* 36 */
559 	"VAR_CUTSCENE_END_SCRIPT",
560 	"VAR_CHARINC",
561 	"VAR_WALKTO_OBJ",
562 	"VAR_DEBUGMODE",
563 	/* 40 */
564 	"VAR_HEAPSPACE",
565 	"VAR_ROOM_WIDTH",
566 	"VAR_RESTART_KEY",
567 	"VAR_PAUSE_KEY",
568 	/* 44 */
569 	"VAR_MOUSE_X",
570 	"VAR_MOUSE_Y",
571 	"VAR_TIMER",
572 	"VAR_TMR_4",
573 	/* 48 */
574 	NULL,
575 	"VAR_VIDEOMODE",
576 	"VAR_MAINMENU_KEY",
577 	"VAR_FIXEDDISK",
578 	/* 52 */
579 	"VAR_CURSORSTATE",
580 	"VAR_USERPUT",
581 	"VAR_ROOM_HEIGHT",
582 	NULL,
583 	/* 56 */
584 	"VAR_SOUNDRESULT",
585 	"VAR_TALKSTOP_KEY",
586 	NULL,
587 	"VAR_FADE_DELAY",
588 	/* 60 */
589 	"VAR_NOSUBTITLES",
590 	"VAR_SAVELOAD_SCRIPT",
591 	"VAR_SAVELOAD_SCRIPT2",
592 	NULL,
593 	/* 64 */
594 	"VAR_SOUNDPARAM",
595 	"VAR_SOUNDPARAM2",
596 	"VAR_SOUNDPARAM3",
597 	"VAR_INPUTMODE",
598 	/* 68 */
599 	"VAR_MEMORY_PERFORMANCE",
600 	"VAR_VIDEO_PERFORMANCE",
601 	"VAR_ROOM_FLAG",
602 	"VAR_GAME_LOADED",
603 	/* 72 */
604 	"VAR_NEW_ROOM",
605 	NULL,
606 	"VAR_LEFTBTN_DOWN",
607 	"VAR_RIGHTBTN_DOWN",
608 	/* 76 */
609 	"VAR_V6_EMSSPACE",
610 	NULL,
611 	NULL,
612 	NULL,
613 	/* 80 */
614 	NULL,
615 	NULL,
616 	NULL,
617 	NULL,
618 	/* 84 */
619 	NULL,
620 	NULL,
621 	NULL,
622 	NULL,
623 	/* 88 */
624 	NULL,
625 	NULL,
626 	"VAR_GAME_DISK_MSG",
627 	"VAR_OPEN_FAILED_MSG",
628 	/* 92 */
629 	"VAR_READ_ERROR_MSG",
630 	"VAR_PAUSE_MSG",
631 	"VAR_RESTART_MSG",
632 	"VAR_QUIT_MSG",
633 	/* 96 */
634 	"VAR_SAVE_BTN",
635 	"VAR_LOAD_BTN",
636 	"VAR_PLAY_BTN",
637 	"VAR_CANCEL_BTN",
638 	/* 100 */
639 	"VAR_QUIT_BTN",
640 	"VAR_OK_BTN",
641 	"VAR_SAVE_DISK_MSG",
642 	"VAR_ENTER_NAME_MSG",
643 	/* 104 */
644 	"VAR_NOT_SAVED_MSG",
645 	"VAR_NOT_LOADED_MSG",
646 	"VAR_SAVE_MSG",
647 	"VAR_LOAD_MSG",
648 	/* 108 */
649 	"VAR_SAVE_MENU_TITLE",
650 	"VAR_LOAD_MENU_TITLE",
651 	"VAR_GUI_COLORS",
652 	"VAR_DEBUG_PASSWORD",
653 	/* 112 */
654 	NULL,
655 	NULL,
656 	NULL,
657 	NULL,
658 	/* 116 */
659 	NULL,
660 	"VAR_MAIN_MENU_TITLE",
661 	"VAR_RANDOM_NR",
662 	"VAR_TIMEDATE_YEAR",
663 	/* 120 */
664 	NULL,
665 	"VAR_GAME_VERSION",
666 	NULL,
667 	"VAR_CHARSET_MASK",
668 	/* 124 */
669 	NULL,
670 	"VAR_TIMEDATE_HOUR",
671 	"VAR_TIMEDATE_MINUTE",
672 	NULL,
673 	/* 128 */
674 	"VAR_TIMEDATE_DAY",
675 	"VAR_TIMEDATE_MONTH",
676 	NULL,
677 	NULL,
678 };
679 
680 const char *var_names7[] = {
681 	/* 0 */
682 	NULL,
683 	"VAR_MOUSE_X",
684 	"VAR_MOUSE_Y",
685 	"VAR_VIRT_MOUSE_X",
686 	/* 4 */
687 	"VAR_VIRT_MOUSE_Y",
688 	"VAR_ROOM_WIDTH",
689 	"VAR_ROOM_HEIGHT",
690 	"VAR_CAMERA_POS_X",
691 	/* 8 */
692 	"VAR_CAMERA_POS_Y",
693 	"VAR_OVERRIDE",
694 	"VAR_ROOM",
695 	"VAR_ROOM_RESOURCE",
696 	/* 12 */
697 	"VAR_TALK_ACTOR",
698 	"VAR_HAVE_MSG",
699 	"VAR_TIMER",
700 	"VAR_TMR_4",
701 	/* 16 */
702 	"VAR_TIMEDATE_YEAR",
703 	"VAR_TIMEDATE_MONTH",
704 	"VAR_TIMEDATE_DAY",
705 	"VAR_TIMEDATE_HOUR",
706 	/* 20 */
707 	"VAR_TIMEDATE_MINUTE",
708 	"VAR_TIMEDATE_SECOND",
709 	"VAR_LEFTBTN_DOWN",
710 	"VAR_RIGHTBTN_DOWN",
711 	/* 24 */
712 	"VAR_LEFTBTN_HOLD",
713 	"VAR_RIGHTBTN_HOLD",
714 	"VAR_MEMORY_PERFORMANCE",
715 	"VAR_VIDEO_PERFORMANCE",
716 	/* 28 */
717 	NULL,
718 	"VAR_GAME_LOADED",
719 	NULL,
720 	NULL,
721 	/* 32 */
722 	"VAR_V6_EMSSPACE",
723 	"VAR_VOICE_MODE",
724 	"VAR_RANDOM_NR",
725 	"VAR_NEW_ROOM",
726 	/* 36 */
727 	"VAR_WALKTO_OBJ",
728 	"VAR_NUM_GLOBAL_OBJS",
729 	"VAR_CAMERA_DEST_X",
730 	"VAR_CAMERA_DEST_>",
731 	/* 40 */
732 	"VAR_CAMERA_FOLLOWED_ACTOR",
733 	NULL,
734 	NULL,
735 	NULL,
736 	/* 44 */
737 	NULL,
738 	NULL,
739 	NULL,
740 	NULL,
741 	/* 48 */
742 	NULL,
743 	NULL,
744 	"VAR_SCROLL_SCRIPT",
745 	"VAR_ENTRY_SCRIPT",
746 	/* 52 */
747 	"VAR_ENTRY_SCRIPT2",
748 	"VAR_EXIT_SCRIPT",
749 	"VAR_EXIT_SCRIPT2",
750 	"VAR_VERB_SCRIPT",
751 	/* 56 */
752 	"VAR_SENTENCE_SCRIPT",
753 	"VAR_INVENTORY_SCRIPT",
754 	"VAR_CUTSCENE_START_SCRIPT",
755 	"VAR_CUTSCENE_END_SCRIPT",
756 	/* 60 */
757 	"VAR_SAVELOAD_SCRIPT",
758 	"VAR_SAVELOAD_SCRIPT2",
759 	"VAR_CUTSCENEEXIT_KEY",
760 	"VAR_RESTART_KEY",
761 	/* 64 */
762 	"VAR_PAUSE_KEY",
763 	"VAR_MAINMENU_KEY",
764 	"VAR_VERSION_KEY",
765 	"VAR_TALKSTOP_KEY",
766 	/* 68 */
767 	NULL,
768 	NULL,
769 	"VAR_SAVE_BTN",
770 	"VAR_LOAD_BTN",
771 	/* 72 */
772 	"VAR_PLAY_BTN",
773 	"VAR_CANCEL_BTN",
774 	"VAR_QUIT_BTN",
775 	"VAR_OK_BTN",
776 	/* 76 */
777 	"VAR_SAVE_MENU_TITLE",
778 	"VAR_LOAD_MENU_TITLE",
779 	"VAR_ENTER_NAME_MSG",
780 	"VAR_SAVE_MSG",
781 	/* 80 */
782 	"VAR_LOAD_MSG",
783 	"VAR_NOT_SAVED_MSG",
784 	"VAR_NOT_LOADED_MSG",
785 	"VAR_OPEN_FAILED_MSG",
786 	/* 84 */
787 	"VAR_READ_ERROR_MSG",
788 	"VAR_PAUSE_MSG",
789 	"VAR_RESTART_MSG",
790 	"VAR_QUIT_MSG",
791 	/* 88 */
792 	NULL,
793 	"VAR_DEBUG_PASSWORD",
794 	NULL,
795 	NULL,
796 	/* 92 */
797 	NULL,
798 	NULL,
799 	NULL,
800 	NULL,
801 	/* 96 */
802 	NULL,
803 	"VAR_TIMER_NEXT",
804 	"VAR_TMR_1",
805 	"VAR_TMR_2",
806 	/* 100 */
807 	"VAR_TMR_3",
808 	"VAR_CAMERA_MIN_X",
809 	"VAR_CAMERA_MAX_X",
810 	"VAR_CAMERA_MIN_Y",
811 	/* 104 */
812 	"VAR_CAMERA_MAX_Y",
813 	"VAR_CAMERA_THRESHOLD_X",
814 	"VAR_CAMERA_THRESHOLD_Y",
815 	"VAR_CAMERA_SPEED_X",
816 	/* 108 */
817 	"VAR_CAMERA_SPEED_Y",
818 	"VAR_CAMERA_ACCEL_X",
819 	"VAR_CAMERA_ACCEL_Y",
820 	"VAR_EGO",
821 	/* 112 */
822 	"VAR_CURSORSTATE",
823 	"VAR_USERPUT",
824 	"VAR_DEFAULT_TALK_DELAY",
825 	"VAR_CHARINC",
826 	/* 116 */
827 	"VAR_DEBUGMODE",
828 	"VAR_FADE_DELAY",
829 	NULL,
830 	"VAR_CHARSET_MASK",
831 	/* 120 */
832 	NULL,
833 	NULL,
834 	NULL,
835 	"VAR_VIDEONAME",
836 	/* 124 */
837 	NULL,
838 	NULL,
839 	NULL,
840 	NULL,
841 	/* 128 */
842 	NULL,
843 	NULL,
844 	"VAR_STRING2DRAW",
845 	"VAR_CUSTOMSCALETABLE",
846 	/* 132 */
847 	NULL,
848 	"VAR_BLAST_ABOVE_TEXT",
849 	NULL,
850 	"VAR_MUSIC_BUNDLE_LOADED",
851 	/* 136 */
852 	"VAR_VOICE_BUNDLE_LOADED",
853 	NULL,
854 };
855 
856 const char *var_names8[] = {
857 	/* 0 */
858 	NULL,
859 	"VAR_ROOM_WIDTH",
860 	"VAR_ROOM_HEIGHT",
861 	"VAR_MOUSE_X",
862 	/* 4 */
863 	"VAR_MOUSE_Y",
864 	"VAR_VIRT_MOUSE_X",
865 	"VAR_VIRT_MOUSE_Y",
866 	"VAR_CURSORSTATE",
867 	/* 8 */
868 	"VAR_USERPUT",
869 	"VAR_CAMERA_POS_X",
870 	"VAR_CAMERA_POS_Y",
871 	"VAR_CAMERA_DEST_X",
872 	/* 12 */
873 	"VAR_CAMERA_DEST_Y",
874 	"VAR_CAMERA_FOLLOWED_ACTOR",
875 	"VAR_TALK_ACTOR",
876 	"VAR_HAVE_MSG",
877 	/* 16 */
878 	"VAR_LEFTBTN_DOWN",
879 	"VAR_RIGHTBTN_DOWN",
880 	"VAR_LEFTBTN_HOLD",
881 	"VAR_RIGHTBTN_HOLD",
882 	/* 20 */
883 	NULL,
884 	NULL,
885 	NULL,
886 	NULL,
887 	/* 24 */
888 	"VAR_TIMEDATE_YEAR",
889 	"VAR_TIMEDATE_MONTH",
890 	"VAR_TIMEDATE_DAY",
891 	"VAR_TIMEDATE_HOUR",
892 	/* 28 */
893 	"VAR_TIMEDATE_MINUTE",
894 	"VAR_TIMEDATE_SECOND",
895 	"VAR_OVERRIDE",
896 	"VAR_ROOM",
897 	/* 32 */
898 	"VAR_NEW_ROOM",
899 	"VAR_WALKTO_OBJ",
900 	"VAR_TIMER",
901 	NULL,
902 	/* 36 */
903 	NULL,
904 	NULL,
905 	NULL,
906 	"VAR_VOICE_MODE",
907 	/* 40 */
908 	"VAR_GAME_LOADED",
909 	"VAR_LANGUAGE",
910 	"VAR_CURRENTDISK",
911 	NULL,
912 	/* 44 */
913 	NULL,
914 	"VAR_MUSIC_BUNDLE_LOADED",
915 	"VAR_VOICE_BUNDLE_LOADED",
916 	NULL,
917 	/* 48 */
918 	NULL,
919 	NULL,
920 	"VAR_SCROLL_SCRIPT",
921 	"VAR_ENTRY_SCRIPT",
922 	/* 52 */
923 	"VAR_ENTRY_SCRIPT2",
924 	"VAR_EXIT_SCRIPT",
925 	"VAR_EXIT_SCRIPT2",
926 	"VAR_VERB_SCRIPT",
927 	/* 56 */
928 	"VAR_SENTENCE_SCRIPT",
929 	"VAR_INVENTORY_SCRIPT",
930 	"VAR_CUTSCENE_START_SCRIPT",
931 	"VAR_CUTSCENE_END_SCRIPT",
932 	/* 60 */
933 	NULL,
934 	NULL,
935 	"VAR_CUTSCENEEXIT_KEY",
936 	"VAR_RESTART_KEY",
937 	/* 64 */
938 	"VAR_PAUSE_KEY",
939 	"VAR_MAINMENU_KEY",
940 	"VAR_VERSION_KEY",
941 	"VAR_TALKSTOP_KEY",
942 	/* 68 */
943 	NULL,
944 	NULL,
945 	NULL,
946 	NULL,
947 	/* 72 */
948 	NULL,
949 	NULL,
950 	NULL,
951 	NULL,
952 	/* 76 */
953 	NULL,
954 	NULL,
955 	NULL,
956 	NULL,
957 	/* 80 */
958 	NULL,
959 	NULL,
960 	NULL,
961 	NULL,
962 	/* 84 */
963 	NULL,
964 	NULL,
965 	NULL,
966 	NULL,
967 	/* 88 */
968 	NULL,
969 	NULL,
970 	NULL,
971 	NULL,
972 	/* 92 */
973 	NULL,
974 	NULL,
975 	NULL,
976 	NULL,
977 	/* 96 */
978 	NULL,
979 	NULL,
980 	NULL,
981 	NULL,
982 	/* 100 */
983 	NULL,
984 	NULL,
985 	NULL,
986 	NULL,
987 	/* 104 */
988 	NULL,
989 	NULL,
990 	NULL,
991 	NULL,
992 	/* 108 */
993 	NULL,
994 	NULL,
995 	NULL,
996 	"VAR_CUSTOMSCALETABLE",
997 	/* 112 */
998 	"VAR_TIMER_NEXT",
999 	"VAR_TMR_1",
1000 	"VAR_TMR_2",
1001 	"VAR_TMR_3",
1002 	/* 116 */
1003 	"VAR_CAMERA_MIN_X",
1004 	"VAR_CAMERA_MAX_X",
1005 	"VAR_CAMERA_MIN_Y",
1006 	"VAR_CAMERA_MAX_Y",
1007 	/* 120 */
1008 	"VAR_CAMERA_SPEED_X",
1009 	"VAR_CAMERA_SPEED_Y",
1010 	"VAR_CAMERA_ACCEL_X",
1011 	"VAR_CAMERA_ACCEL_Y",
1012 	/* 124 */
1013 	"VAR_CAMERA_THRESHOLD_X",
1014 	"VAR_CAMERA_THRESHOLD_Y",
1015 	"VAR_EGO",
1016 	NULL,
1017 	/* 128 */
1018 	"VAR_DEFAULT_TALK_DELAY",
1019 	"VAR_CHARINC",
1020 	"VAR_DEBUGMODE",
1021 	NULL,
1022 	/* 132 */
1023 	"VAR_KEYPRESS",
1024 	"VAR_BLAST_ABOVE_TEXT",
1025 	"VAR_SYNC",
1026 	NULL,
1027 };
1028 
getVarName(uint var)1029 const char *getVarName(uint var) {
1030 	if (g_options.heVersion >= 72) {
1031 		if (var >= sizeof(var_names72) / sizeof(var_names72[0]))
1032 			return NULL;
1033 		return var_names72[var];
1034 	} else if (g_options.scriptVersion == 8) {
1035 		if (var >= sizeof(var_names8) / sizeof(var_names8[0]))
1036 			return NULL;
1037 		return var_names8[var];
1038 	} else if (g_options.scriptVersion == 7) {
1039 		if (var >= sizeof(var_names7) / sizeof(var_names7[0]))
1040 			return NULL;
1041 		return var_names7[var];
1042 	} else {
1043 		if (var >= sizeof(var_names6) / sizeof(var_names6[0]))
1044 			return NULL;
1045 		return var_names6[var];
1046 	}
1047 }
1048 
se_neg(StackEnt * se)1049 StackEnt *se_neg(StackEnt *se) {
1050 	return new NegStackEnt(se);
1051 }
1052 
se_int(int i)1053 StackEnt *se_int(int i) {
1054 	return new IntStackEnt(i);
1055 }
1056 
se_var(int i)1057 StackEnt *se_var(int i) {
1058 	return new VarStackEnt(i);
1059 }
1060 
se_array(int i,StackEnt * dim2,StackEnt * dim1)1061 StackEnt *se_array(int i, StackEnt *dim2, StackEnt *dim1) {
1062 	return new ArrayStackEnt(i, dim2, dim1);
1063 }
1064 
se_oper(StackEnt * a,int op)1065 StackEnt *se_oper(StackEnt *a, int op) {
1066 	return new UnaryOpStackEnt(op, a);
1067 }
1068 
se_oper(StackEnt * a,int op,StackEnt * b)1069 StackEnt *se_oper(StackEnt *a, int op, StackEnt *b) {
1070 	return new BinaryOpStackEnt(op, a, b);
1071 }
1072 
se_complex(const char * s)1073 StackEnt *se_complex(const char *s) {
1074 	return new ComplexStackEnt(s);
1075 }
1076 
se_astext(StackEnt * se,char * where,bool wantparens=true)1077 char *se_astext(StackEnt *se, char *where, bool wantparens = true) {
1078 	return se->asText(where, wantparens);
1079 }
1080 
se_get_list()1081 StackEnt *se_get_list() {
1082 	return new ListStackEnt(pop());
1083 }
1084 
get_var6(char * buf)1085 char *get_var6(char *buf) {
1086 	VarStackEnt tmp(get_word());
1087 	return tmp.asText(buf);
1088 }
1089 
invalidop(const char * cmd,int op)1090 void invalidop(const char *cmd, int op) {
1091 	if (cmd)
1092 		error("Unknown opcode %s:0x%x (stack count %d)", cmd, op, num_stack);
1093 	else
1094 		error("Unknown opcode 0x%x (stack count %d)", op, num_stack);
1095 }
1096 
push(StackEnt * se)1097 void push(StackEnt *se) {
1098 	assert(se);
1099 	assert(num_stack < MAX_STACK_SIZE);
1100 	stack[num_stack++] = se;
1101 }
1102 
pop()1103 StackEnt *pop() {
1104 	if (num_stack == 0) {
1105 		printf("ERROR: No items on stack to pop!\n");
1106 
1107 		if (!g_options.haltOnError)
1108 			return se_complex("**** INVALID DATA ****");
1109 		exit(1);
1110 	}
1111 	return stack[--num_stack];
1112 }
1113 
1114 
kill(char * output,StackEnt * se)1115 void kill(char *output, StackEnt *se) {
1116 	if (se->type != seDup) {
1117 		char *e = strecpy(output, "pop(");
1118 		e = se_astext(se, e);
1119 		strcpy(e, ")");
1120 		delete se;
1121 	} else {
1122 		// FIXME: Evil hack: We re-push DUPs, instead of killing
1123 		// them. We do this to support switch-case constructs
1124 		// (see comment at the start of this file) w/o applying a full
1125 		// flow analysis (which would normally be required).
1126 		push(se);
1127 	}
1128 }
1129 
doAssign(char * output,StackEnt * dst,StackEnt * src)1130 void doAssign(char *output, StackEnt *dst, StackEnt *src) {
1131 	if (src->type == seDup && dst->type == seDup) {
1132 		((DupStackEnt *)dst)->_idx = ((DupStackEnt *)src)->_idx;
1133 		return;
1134 	}
1135 	char *e = se_astext(dst, output);
1136 	e = strecpy(e, " = ");
1137 	se_astext(src, e);
1138 }
1139 
dup(char * output)1140 StackEnt* StackEnt::dup(char *output) {
1141 	StackEnt *dse = new DupStackEnt(++dupindex);
1142 	doAssign(output, dse, this);
1143 	return dse;
1144 }
1145 
doAdd(char * output,StackEnt * se,int val)1146 void doAdd(char *output, StackEnt *se, int val) {
1147 	char *e = se_astext(se, output);
1148 	if (val == 1) {
1149 		sprintf(e, "++");
1150 	} else if (val == -1) {
1151 		sprintf(e, "--");
1152 	} else {
1153 		/* SCUMM doesn't support this */
1154 		sprintf(e, " += %d", val);
1155 	}
1156 }
1157 
dup(char * output,StackEnt * se)1158 StackEnt *dup(char *output, StackEnt *se) {
1159 	return se->dup(output);
1160 }
1161 
writeArray(char * output,int i,StackEnt * dim2,StackEnt * dim1,StackEnt * value)1162 void writeArray(char *output, int i, StackEnt *dim2, StackEnt *dim1, StackEnt *value) {
1163 	StackEnt *array = se_array(i, dim2, dim1);
1164 	doAssign(output, array, value);
1165 	delete array;
1166 }
1167 
writeVar(char * output,int i,StackEnt * value)1168 void writeVar(char *output, int i, StackEnt *value) {
1169 	StackEnt *se = se_var(i);
1170 	doAssign(output, se, value);
1171 	delete se;
1172 }
1173 
addArray(char * output,int i,StackEnt * dim1,int val)1174 void addArray(char *output, int i, StackEnt *dim1, int val) {
1175 	StackEnt *array = se_array(i, NULL, dim1);
1176 	doAdd(output, array, val);
1177 	delete array;
1178 }
1179 
addVar(char * output,int i,int val)1180 void addVar(char *output, int i, int val) {
1181 	StackEnt *se = se_var(i);
1182 	doAdd(output, se, val);
1183 	delete se;
1184 }
1185 
1186 
se_get_string()1187 StackEnt *se_get_string() {
1188 	char buf[1024];
1189 	get_string(buf); // ignore returned value
1190 	return se_complex(buf);
1191 }
1192 
1193 int _stringLength = 1;
1194 byte _stringBuffer[4096];
1195 
getScriptString()1196 void getScriptString() {
1197 	byte chr;
1198 
1199 	while ((chr = get_byte()) != 0) {
1200 		_stringBuffer[_stringLength] = chr;
1201 		_stringLength++;
1202 
1203 		if (_stringLength >= 4096)
1204 			error("String stack overflow");
1205 	}
1206 
1207 	_stringBuffer[_stringLength] = 0;
1208 	_stringLength++;
1209 }
1210 
se_get_string_he()1211 StackEnt *se_get_string_he() {
1212 	char buf[1024];
1213 	char *e = buf;
1214 
1215 	byte string[1024];
1216 	byte chr;
1217 	int len = 1;
1218 	StackEnt *value;
1219 
1220 	value = pop();
1221 
1222 	*e++ = '"';
1223 	if (value->type == seInt && value->getIntVal() == -1) {
1224 		if (_stringLength == 1) {
1225 			*e++ = '"';
1226 			*e++ = 0;
1227 			return se_complex(buf);
1228 		}
1229 
1230 		_stringLength -= 2;
1231 		 while ((chr = _stringBuffer[_stringLength]) != 0) {
1232 			string[len++] = chr;
1233 			_stringLength--;
1234 		}
1235 
1236 		string[len] = 0;
1237 		_stringLength++;
1238 
1239 		// Reverse string
1240 		while (--len)
1241 			*e++ = string[len];
1242 	} else {
1243 		e += sprintf(e, ":");
1244 		e = value->asText(e);
1245 		e += sprintf(e, ":");
1246 	}
1247 	*e++ = '"';
1248 
1249 	*e++ = 0;
1250 	return se_complex(buf);
1251 }
1252 
ext(char * output,const char * fmt)1253 void ext(char *output, const char *fmt) {
1254 	bool wantresult;
1255 	byte cmd, extcmd;
1256 	const char *extstr = NULL;
1257 	const char *prep = NULL;
1258 	StackEnt *args[20];
1259 	int numArgs = 0;
1260 	char *e = (char *)output;
1261 
1262 	/* return the result? */
1263 	wantresult = false;
1264 	if (*fmt == 'r') {
1265 		wantresult = true;
1266 		fmt++;
1267 	}
1268 
1269 	while ((cmd = *fmt++) != '|') {
1270 		if (cmd == 'x' && !extstr) {
1271 			/* Sub-op: next byte specifies which one */
1272 			extstr = fmt;
1273 			while (*fmt++)
1274 				;
1275 			e += sprintf(e, "%s.", extstr);
1276 
1277 			/* extended thing */
1278 			extcmd = get_byte();
1279 
1280 			/* locate our extended item */
1281 			while ((cmd = *fmt++) != extcmd) {
1282 				/* scan until we find , or \0 */
1283 				while ((cmd = *fmt++) != ',') {
1284 					if (cmd == 0) {
1285 						invalidop(extstr, extcmd);
1286 					}
1287 				}
1288 			}
1289 			/* found a command, continue at the beginning */
1290 			continue;
1291 		}
1292 		if (cmd == 'u' && !extstr) {
1293 			/* Sub-op: next byte specifies which one */
1294 			extstr = fmt;
1295 			while (*fmt++)
1296 				;
1297 			e += sprintf(e, "%s.", extstr);
1298 
1299 			/* extended thing */
1300 			extcmd = pop()->getIntVal();
1301 
1302 			/* locate our extended item */
1303 			while ((cmd = *fmt++) != extcmd) {
1304 				/* scan until we find , or \0 */
1305 				while ((cmd = *fmt++) != ',') {
1306 					if (cmd == 0) {
1307 						invalidop(extstr, extcmd);
1308 					}
1309 				}
1310 			}
1311 			/* found a command, continue at the beginning */
1312 			continue;
1313 		}
1314 		if (cmd == 'y' && !extstr) {
1315 			/* Sub-op: parameters are in a list, first element of the list specified the command */
1316 			ListStackEnt *se;
1317 			extstr = fmt;
1318 			while (*fmt++)
1319 				;
1320 			e += sprintf(e, "%s.", extstr);
1321 
1322 			se = new ListStackEnt(pop());
1323 			args[numArgs++] = se;
1324 
1325 			/* extended thing */
1326 			se->_size--;
1327 			extcmd = (byte) se->_list[se->_size]->getIntVal();
1328 
1329 			/* locate our extended item */
1330 			while ((cmd = *fmt++) != extcmd) {
1331 				/* scan until we find , or \0 */
1332 				while ((cmd = *fmt++) != ',') {
1333 					if (cmd == 0) {
1334 						/* End reached and command was not found: re-add the extcmd to
1335 						   the list and output the whole thing as "unknown".
1336 						 */
1337 						se->_size++;
1338 						fmt = "Unknown";
1339 						goto output_command;
1340 					}
1341 				}
1342 			}
1343 
1344 			/* found a command, continue at the beginning */
1345 			continue;
1346 		}
1347 
1348 		if (cmd == 'p') {
1349 			args[numArgs++] = pop();
1350 		} else if (cmd == 'z') {	// = popRoomAndObj()
1351 			args[numArgs++] = pop();
1352 			if (g_options.scriptVersion < 7 && g_options.heVersion == 0)
1353 				args[numArgs++] = pop();
1354 		} else if (cmd == 'h') {
1355 			if (g_options.heVersion >= 72)
1356 				args[numArgs++] = se_get_string_he();
1357 		} else if (cmd == 's') {
1358 			args[numArgs++] = se_get_string();
1359 		} else if (cmd == 'w') {
1360 			args[numArgs++] = se_int(get_word());
1361 		} else if (cmd == 'i') {
1362 			args[numArgs++] = se_int(get_byte());
1363 		} else if (cmd == 'l') {
1364 			args[numArgs++] = se_get_list();
1365 		} else if (cmd == 'j') {
1366 			args[numArgs++] = se_int(get_word());
1367 		} else if (cmd == 'v') {
1368 			args[numArgs++] = se_var(get_word());
1369 		} else {
1370 			error("Character '%c' unknown in argument string '%s', \n", fmt, cmd);
1371 		}
1372 	}
1373 
1374 output_command:
1375 
1376 	/* create a string from the arguments */
1377 	if (prep)
1378 		e = strecpy(e, prep);
1379 	while (*fmt != 0 && *fmt != ',')
1380 		*e++ = *fmt++;
1381 	*e++ = '(';
1382 	while (--numArgs >= 0) {
1383 		e = se_astext(args[numArgs], e);
1384 		if (numArgs)
1385 			*e++ = ',';
1386 	}
1387 	*e++ = ')';
1388 	*e = 0;
1389 
1390 	if (wantresult) {
1391 		push(se_complex((char *)output));
1392 		output[0] = 0;
1393 		return;
1394 	}
1395 }
1396 
jump(char * output)1397 void jump(char *output) {
1398 	int offset = get_word();
1399 	int cur = get_curoffs();
1400 	int to = cur + offset;
1401 
1402 	if (offset == 1) {
1403 		// Sometimes, jumps with offset 1 occur. I used to suppress those.
1404 		// But it turns out that's not quite correct in some cases. With this
1405 		// code, it can sometimes happens that you get an empty 'else' branch;
1406 		// but in many other cases, an otherwise hidden instruction is revealed,
1407 		// or an instruction is placed into an else branch instead of being
1408 		// (incorrectly) placed inside the body of the 'if' itself.
1409 		sprintf(output, "/* jump %x; */", to);
1410 	} else if (!g_options.dontOutputElse && maybeAddElse(cur, to)) {
1411 		pendingElse = true;
1412 		pendingElseTo = to;
1413 		pendingElseOffs = cur;
1414 		pendingElseOpcode = g_jump_opcode;
1415 		pendingElseIndent = g_blockStack.size();
1416 	} else {
1417 		if (!g_blockStack.empty() && !g_options.dontOutputWhile) {
1418 			Block p = g_blockStack.top();
1419 			if (p.isWhile && cur == (int)p.to)
1420 				return;		// A 'while' ends here.
1421 			if (!g_options.dontOutputBreaks && maybeAddBreak(cur, to)) {
1422 				sprintf(output, "break");
1423 				return;
1424 		  }
1425 		}
1426 		sprintf(output, "jump %x", to);
1427 	}
1428 }
1429 
jumpif(char * output,StackEnt * se,bool negate)1430 void jumpif(char *output, StackEnt *se, bool negate) {
1431 	int offset = get_word();
1432 	int cur = get_curoffs();
1433 	int to = cur + offset;
1434 	char *e = output;
1435 
1436 	if (!g_options.dontOutputElseif && pendingElse) {
1437 		if (maybeAddElseIf(cur, pendingElseTo, to)) {
1438 			pendingElse = false;
1439 			haveElse = true;
1440 			e = strecpy(e, "} else if (");
1441 			e = se_astext(se, e, false);
1442 			sprintf(e, g_options.alwaysShowOffs ? ") /*%.4X*/ {" : ") {", to);
1443 			return;
1444 		}
1445 	}
1446 
1447 	if (!g_options.dontOutputIfs && maybeAddIf(cur, to)) {
1448 		if (!g_options.dontOutputWhile && g_blockStack.top().isWhile)
1449 			e = strecpy(e, negate ? "until (" : "while (");
1450 		else
1451 			e = strecpy(e, negate ? "unless (" : "if (");
1452 		e = se_astext(se, e, false);
1453 		sprintf(e, g_options.alwaysShowOffs ? ") /*%.4X*/ {" : ") {", to);
1454 		return;
1455 	}
1456 
1457 	e = strecpy(e, negate ? "if (" : "unless (");
1458 	e = se_astext(se, e);
1459 	sprintf(e, ") jump %x", to);
1460 }
1461 
dup_n()1462 void dup_n() {
1463 	push(se_int(get_word()));
1464 	ListStackEnt *list = (ListStackEnt *)se_get_list();
1465 
1466 	for (int i = 0; i < 2; i++)
1467 		for (int j = 0; j < list->_size; j++)
1468 			push(list->_list[j]);
1469 }
1470 
1471 
1472 #define PRINT_V100HE(name)           \
1473 	do {                          \
1474 		ext(output, "x" name "\0"         \
1475 				"\x6pp|XY,"      \
1476 				"\xC|center,"    \
1477 				"\x12p|right,"    \
1478 				"\x14p|color,"    \
1479 				"\x15l|colors,"	  \
1480 				"\x23lps|debug,"  \
1481 				"\x2E|left,"      \
1482 				"\x33|mumble,"    \
1483 				"\x38|overhead,"  \
1484 				"\x4Ep|getText,"  \
1485 				"\x4Fs|msg,"      \
1486 				"\x5B|begin,"     \
1487 				"\x5C|end"        \
1488 				);                \
1489 	} while(0)
1490 
next_line_HE_V100(char * output)1491 void next_line_HE_V100(char *output) {
1492 	byte code = get_byte();
1493 	StackEnt *se_a, *se_b;
1494 
1495 	switch (code) {
1496 	case 0x0:
1497 		ext(output, "x" "actorOps\0"
1498 				"\x3ppp|actorSet:3:??,"
1499 				"\x4p|setAnimSpeed,"
1500 				"\x6pp|putActor,"
1501 				"\x8|resetDrawToBackBuf,"
1502 				"\x9|drawToBackBuf,"
1503 				"\xEp|charset,"
1504 				"\x12pppp|setClipRect,"
1505 				"\x16l|setUserConditions,"
1506 				"\x19p|setCostume,"
1507 				"\x1B|init,"
1508 				"\x20p|setHEFlag,"
1509 				"\x34h|setName,"
1510 				"\x35|initLittle,"
1511 				"\x39pp|setPalette,"
1512 				"\x3Bp|layer,"
1513 				"\x3Fp|setPaletteNum,"
1514 				"\x41p|setScale,"
1515 				"\x46p|setShadowMode,"
1516 				"\x4App|setWalkSpeed,"
1517 				"\x4Ehp|setTalkieSlot,"
1518 				"\x53pp|setAnimVar,"
1519 				"\x57p|setAlwayZClip,"
1520 				"\x59|setNeverZClip,"
1521 				"\x80pppp|setActorClipRect,"
1522 				"\x81p|setCurActor,"
1523 				"\x82l|setSound,"
1524 				"\x83p|setWidth,"
1525 				"\x84|setDefAnim,"
1526 				"\x85p|setElevation,"
1527 				"\x86|setFollowBoxes,"
1528 				"\x87|setIgnoreBoxes,"
1529 				"\x88|setIgnoreTurnsOff,"
1530 				"\x89|setIgnoreTurnsOn,"
1531 				"\x8Ap|setInitFrame,"
1532 				"\x8Bp|setStandFrame,"
1533 				"\x8Cpp|setTalkFrame,"
1534 				"\x8Dp|setTalkColor,"
1535 				"\x8Ep|setTalkCondition,"
1536 				"\x8Fpp|setTalkPos,"
1537 				"\x90p|setWalkFrame");
1538 		break;
1539 	case 0x1:
1540 		se_a = pop();
1541 		se_b = pop();
1542 		push(se_oper(se_b, 6 + isEqual, se_a));
1543 		break;
1544 	case 0x2:
1545 		ext(output, "pp|faceActor");
1546 		break;
1547 
1548 	case 0x03:
1549 		ext(output, "x" "sortArray\0"
1550 				"\x86pppppv|sort,");
1551 		break;
1552 	case 0x04:
1553 		switch (get_byte()) {
1554 		case 35:
1555 			se_get_list();
1556 			pop();
1557 			se_a = se_get_string_he();
1558 			writeArray(output, get_word(), NULL, se_a, se_a);
1559 			break;
1560 		case 77:
1561 			se_a = se_get_string_he();
1562 			writeArray(output, get_word(), NULL, se_a, se_a);
1563 			break;
1564 		case 128:
1565 			se_b = se_get_list();
1566 			se_a = pop();
1567 			writeArray(output, get_word(), NULL, se_a, se_b);
1568 			break;
1569 		case 129:
1570 			se_a = pop();
1571 			se_b = se_get_list();
1572 			writeArray(output, get_word(), NULL, se_a, se_b);
1573 			break;
1574 		case 130:
1575 			// TODO: Add support for writeListIntoArray
1576 			ext(output, "lppppv|writeListIntoArray");
1577 			break;
1578 		case 131:
1579 			// TODO: Add support for copyArray
1580 			ext(output, "ppppvppppv|copyArray");
1581 			break;
1582 		case 132:
1583 			// TODO: Add support for math operations
1584 			ext(output, "pppppppppppppvvv|mathOpsInArray");
1585 			break;
1586 		case 133:
1587 			// TODO: Add support for writeRangeIntoArray
1588 			ext(output, "ppppppv|writeRangeIntoArray");
1589 			break;
1590 		}
1591 		break;
1592 	case 0x05:
1593 		se_a = pop();
1594 		se_b = pop();
1595 		push(se_oper(se_b, operBand, se_a));
1596 		break;
1597 	case 0x06:
1598 		se_a = pop();
1599 		se_b = pop();
1600 		push(se_oper(se_b, operBor, se_a));
1601 		break;
1602 	case 0x07:
1603 		ext(output, "|breakHere");
1604 		break;
1605 	case 0x08:
1606 		ext(output, "p|delayFrames");
1607 		break;
1608 	case 0x09:
1609 		ext(output, "rpp|shl");
1610 		break;
1611 	case 0x0A:
1612 		ext(output, "rpp|shr");
1613 		break;
1614 	case 0x0B:
1615 		ext(output, "rpp|xor");
1616 		break;
1617 	case 0x0C:
1618 		ext(output, "p|setCameraAt");
1619 		break;
1620 	case 0x0D:
1621 		ext(output, "p|actorFollowCamera");
1622 		break;
1623 	case 0x0E:
1624 		ext(output, "p|loadRoom");
1625 		break;
1626 	case 0x0F:
1627 		ext(output, "p|panCameraTo");
1628 		break;
1629 	case 0x10:
1630 		ext(output, "ppppp|captureWizImage");
1631 		break;
1632 	case 0x11:
1633 		ext(output, "lpi|jumpToScript");
1634 		break;
1635 	case 0x12:
1636 		ext(output, "lp|setClass");
1637 		break;
1638 	case 0x13:
1639 		ext(output, "p|closeFile");
1640 		break;
1641 	case 0x14:
1642 		ext(output, "ppz|loadRoomWithEgo");
1643 		break;
1644 	case 0x16:
1645 		ext(output, "h|createDirectory");
1646 		break;
1647 	case 0x17:
1648 		ext(output, "x" "createSound\0"
1649 				"\x0p|setId,"
1650 				"\x35|reset,"
1651 				"\x5C|dummy,"
1652 				"\x80p|create");
1653 		break;
1654 	case 0x18:
1655 		ext(output, "l|beginCutscene");
1656 		break;
1657 	case 0x19:
1658 	case 0x53:
1659 		kill(output, pop());
1660 		break;
1661 	case 0x1A:
1662 		ext(output, "hp|traceStatus");
1663 		break;
1664 	case 0x1B:
1665 		addVar(output, get_word(), -1);
1666 		break;
1667 	case 0x1C:
1668 		addArray(output, get_word(), pop(), -1);
1669 		break;
1670 	case 0x1D:
1671 		ext(output, "h|deleteFile");
1672 		break;
1673 	case 0x1E:
1674 		ext(output, "x" "dim2dimArray\0"
1675 				"\x29ppv|bit,"
1676 				"\x2Appv|int,"
1677 				"\x2Bppv|dword,"
1678 				"\x2Cppv|nibble,"
1679 				"\x2Dppv|byte,"
1680 				"\x4Dppv|string");
1681 		break;
1682 	case 0x1F:
1683 		ext(output, "x" "dimArray\0"
1684 				"\x29pv|bit,"
1685 				"\x2Apv|int,"
1686 				"\x2Bpv|dword,"
1687 				"\x2Cpv|nibble,"
1688 				"\x2Dpv|byte,"
1689 				"\x4Dpv|string,"
1690 				"\x87v|nukeArray");
1691 		break;
1692 	case 0x20:
1693 		se_a = pop();
1694 		se_b = pop();
1695 		push(se_oper(se_b, 9 + isEqual, se_a));
1696 		break;
1697 	case 0x21:
1698 		ext(output, "pp|animateActor");
1699 		break;
1700 	case 0x22:
1701 		ext(output, "pppp|doSentence");
1702 		break;
1703 	case 0x23:
1704 		ext(output, "ppppp|drawBox");
1705 		break;
1706 	case 0x24:
1707 		ext(output, "pppp|drawWizImage");
1708 		break;
1709 	case 0x25:
1710 		ext(output, "pp|drawWizPolygon");
1711 		break;
1712 	case 0x26:
1713 		ext(output, "x" "drawLine\0"
1714 				"\x1pppppp|pixel,"
1715 				"\x14pppppp|wizImage,"
1716 				"\x28pppppp|actor");
1717 		break;
1718 	case 0x27:
1719 		ext(output, "x" "drawObject\0"
1720 				"\x6ppp|setPosition,"
1721 				"\x7pppp|setup,"
1722 				"\x28pp|setState");
1723 		break;
1724 	case 0x28:
1725 		se_a = dup(output, pop());
1726 		push(se_a);
1727 		push(se_a);
1728 		break;
1729 	case 0x29:
1730 		dup_n();
1731 		break;
1732 	case 0x2A:
1733 		ext(output, "|endCutscene");
1734 		break;
1735 	case 0x2B:
1736 		ext(output, "|stopObjectCodeA");
1737 		break;
1738 	case 0x2C:
1739 		ext(output, "|stopObjectCodeB");
1740 		break;
1741 	case 0x2D:
1742 		se_a = pop();
1743 		se_b = pop();
1744 		push(se_oper(se_b, 0 + isEqual, se_a));
1745 		break;
1746 	case 0x2E:
1747 		ext(output, "x" "floodFill\0"
1748 				"\x0p|reset,"
1749 				"\x6pp|setXY,"
1750 				"\x12pppp|setBoxRect,"
1751 				"\x14p|setFlags,"
1752 				"\x36|dummy,"
1753 				"\x5C|floodFill");
1754 		break;
1755 	case 0x2F:
1756 		ext(output, "p|freezeUnfreeze");
1757 		break;
1758 	case 0x30:
1759 		se_a = pop();
1760 		se_b = pop();
1761 		push(se_oper(se_b, 5 + isEqual, se_a));
1762 		break;
1763 	case 0x31:
1764 		ext(output, "|getDateTime");
1765 		break;
1766 	case 0x32:
1767 		ext(output, "x" "setSpriteGroupInfo\0"
1768 				"\x0p|setId,"
1769 				"\x6pp|setPosition,"
1770 				"\x12pppp|setBounds,"
1771 				"\x26pp|misc,"
1772 				"\x28p|setImage,"
1773 				"\x31pp|move,"
1774 				"\x34h|stringUnk,"
1775 				"\x35|reset,"
1776 				"\x36pp|dummy,"
1777 				"\x3Bp|setPriority,"
1778 				"\x3Cpp|setXYScale?,"
1779 				"\x59|resetBounds");
1780 		break;
1781 	case 0x33:
1782 		se_a = pop();
1783 		se_b = pop();
1784 		push(se_oper(se_b, 2 + isEqual, se_a));
1785 		break;
1786 	case 0x34:
1787 		ext(output, "x" "resourceRoutines\0"
1788 				"\xEp|setCharset,"
1789 				"\x19p|setCostume,"
1790 				"\x22p|setFlObject,"
1791 				"\x28p|setImage,"
1792 				"\x2F|loadResource,"
1793 				"\x3Ep|setRoom,"
1794 				"\x42p|setScript,"
1795 				"\x48p|setSound,"
1796 				"\x80|clearHeap,"
1797 				"\x81|dummy,"
1798 				"\x84|lockResource,"
1799 				"\x85|nukeResource,"
1800 				"\x86|setOffHeapOn,"
1801 				"\x87|setOffHeapOff,"
1802 				"\x88|queueResource,"
1803 				"\x89|unlock");
1804 		break;
1805 	case 0x35:
1806 		jumpif(output, pop(), true);
1807 		break;
1808 	case 0x36:
1809 		jumpif(output, pop(), false);
1810 		break;
1811 	case 0x37:
1812 		ext(output, "x" "wizImageOps\0"
1813 				"\x0p|setImage,"
1814 				"\x6pp|setPosition,"
1815 				"\x7p|setSourceImage,"
1816 				"\xBppppp|setCaptureRect,"
1817 				"\x12pppp|setClipRect,"
1818 				"\x15p|remapWizImagePal,"
1819 				"\x1D|processMode1,"
1820 				"\x24pppp|setRect,"
1821 				"\x27p|setResDefImageHeight,"
1822 				"\x2Fh|readFile,"
1823 				"\x35|createWizImage,"
1824 				"\x36pp|setThickLine,"
1825 				"\x37ppppp|drawWizImage,"
1826 				"\x39p|setPalette,"
1827 				"\x3Appp|capturePolygon,"
1828 				"\x40hp|writeFile,"
1829 				"\x41p|setScale,"
1830 				"\x43p|setFlags,"
1831 				"\x44p|setupPolygon,"
1832 				"\x46p|setShadow,"
1833 				"\x49p|setImageState,"
1834 				"\x54p|setResDefImageWidth,"
1835 				"\x5C|processWizImage,"
1836 				"\x80pppph|createFont,"
1837 				"\x81|endFont,"
1838 				"\x82pph|renderFontString,"
1839 				"\x83|startFont,"
1840 				"\x84pp|setPosition,"
1841 				"\x85pppppppp|ellipse,"
1842 				"\x86ppp|fillWizFlood,"
1843 				"\x87p|setDstResNum,"
1844 				"\x88ppppp|fillWizLine,"
1845 				"\x89ppp|fillWizPixel,"
1846 				"\x8Appppp|fillWizRect");
1847 		break;
1848 	case 0x38:
1849 		ext(output, "rlp|isAnyOf2");
1850 		break;
1851 	case 0x39:
1852 		addVar(output, get_word(), 1);
1853 		break;
1854 	case 0x3A:
1855 		addArray(output, get_word(), pop(), 1);
1856 		break;
1857 	case 0x3B:
1858 		jump(output);
1859 		break;
1860 	case 0x3C:
1861 		ext(output, "y" "kernelSetFunctions\0"
1862 				"\x1|virtScreenLoad,"
1863 				"\x14|queueAuxBlock,"
1864 				"\x15|pauseDrawObjects,"
1865 				"\x16|resumeDrawObjects,"
1866 				"\x17|clearCharsetMask,"
1867 				"\x18|pauseActors,"
1868 				"\x19|resumActors,"
1869 				"\x1E|actorBottomClipOverride,"
1870 				"\x2A|setWizImageClip,"
1871 				"\x2B|setWizImageClipOff");
1872 		break;
1873 	case 0x3D:
1874 		se_a = pop();
1875 		se_b = pop();
1876 		push(se_oper(se_b, 0xA + isEqual, se_a));
1877 		break;
1878 	case 0x3E:
1879 		se_a = pop();
1880 		se_b = pop();
1881 		push(se_oper(se_b, 4 + isEqual, se_a));
1882 		break;
1883 	case 0x3F:
1884 		ext(output, "p|localizeArrayToScript");
1885 		break;
1886 	case 0x40:
1887 		push(se_array(get_word(), NULL, pop()));
1888 		break;
1889 	case 0x41:
1890 		se_a = pop();
1891 		push(se_array(get_word(), pop(), se_a));
1892 		break;
1893 	case 0x42:
1894 		se_a = pop();
1895 		se_b = pop();
1896 		push(se_oper(se_b, 0xB + isEqual, se_a));
1897 		break;
1898 	case 0x43:
1899 		se_a = pop();
1900 		se_b = pop();
1901 		push(se_oper(se_b, 3 + isEqual, se_a));
1902 		break;
1903 	case 0x44:
1904 		ext(output, "rpp|mod");
1905 		break;
1906 	case 0x45:
1907 		se_a = pop();
1908 		se_b = pop();
1909 		push(se_oper(se_b, 8 + isEqual, se_a));
1910 		break;
1911 	case 0x46:
1912 		se_a = pop();
1913 		se_b = pop();
1914 		push(se_oper(se_b, 1 + isEqual, se_a));
1915 		break;
1916 	case 0x47:
1917 		ext(output, "x" "dim2dim2Array\0"
1918 				"\x29pppppv|bit,"
1919 				"\x2Apppppv|int,"
1920 				"\x2Bpppppv|dword,"
1921 				"\x2Cpppppv|nibble,"
1922 				"\x2Dpppppv|byte,"
1923 				"\x4Dpppppv|string");
1924 		break;
1925 	case 0x49:
1926 		ext(output, "x" "redim2dimArray\0"
1927 				"\x2Appppv|int,"
1928 				"\x2Bppppv|dword,"
1929 				"\x2Dppppv|byte");
1930 		break;
1931 	case 0x4A:
1932 		push(se_oper(pop(), isZero));
1933 		break;
1934 	case 0x4C:
1935 		ext(output, "|beginOverride");
1936 		break;
1937 	case 0x4D:
1938 		ext(output, "|endOverride");
1939 		break;
1940 	case 0x4E:
1941 		ext(output, "|resetCutScene");
1942 		break;
1943 	case 0x4F:
1944 		ext(output, "pp|setOwner");
1945 		break;
1946 	case 0x50:
1947 		ext(output, "x" "paletteOps\0"
1948 				"\x0p|setPaletteNum,"
1949 				"\x14ppppp|setPaletteColor,"
1950 				"\x19p|setPaletteFromCostume,"
1951 				"\x28pp|setPaletteFromImage,"
1952 				"\x35|restorePalette,"
1953 				"\x39p|copyPalette,"
1954 				"\x3Fpp|setPaletteFromRoom,"
1955 				"\x51ppp|copyPaletteColor,"
1956 				"\x5C|resetPaletteNum");
1957 		break;
1958 	case 0x51:
1959 		ext(output, "z|pickupObject");
1960 		break;
1961 	case 0x52:
1962 		ext(output, "x" "polygonOps\0"
1963 				"\x1Cpp|polygonErase,"
1964 				"\x44ppppppppp|polygonStore,"
1965 				"\x45ppppppppp|polygonStore");
1966 		break;
1967 	case 0x54:
1968 		PRINT_V100HE("printDebug");
1969 		break;
1970 	case 0x55:
1971 		ext(output, "p|printWizImage");
1972 		break;
1973 	case 0x56:
1974 		PRINT_V100HE("printLine");
1975 		break;
1976 	case 0x57:
1977 		PRINT_V100HE("printSystem");
1978 		break;
1979 	case 0x58:
1980 		PRINT_V100HE("printCursor");
1981 		break;
1982 	case 0x59:
1983 		ext(output, "lppi|jumpToScriptUnk");
1984 		break;
1985 	case 0x5A:
1986 		ext(output, "lppi|startScriptUnk");
1987 		break;
1988 	case 0x5B:
1989 		ext(output, "lp|pseudoRoom");
1990 		break;
1991 	case 0x5C:
1992 		push(se_int(get_byte()));
1993 		break;
1994 	case 0x5D:
1995 		push(se_int(get_dword()));
1996 		break;
1997 	case 0x5E:
1998 		getScriptString();
1999 		break;
2000 	case 0x5F:
2001 		push(se_int(get_word()));
2002 		break;
2003 	case 0x60:
2004 		push(se_var(get_word()));
2005 		break;
2006 	case 0x61:
2007 		ext(output, "zp|putActorAtObject");
2008 		break;
2009 	case 0x62:
2010 		ext(output, "pppp|putActorInXY");
2011 		break;
2012 	case 0x64:
2013 		ext(output, "x" "redimArray\0"
2014 				"\x2Appv|int,"
2015 				"\x2Bppv|dword,"
2016 				"\x2Dppv|byte");
2017 		break;
2018 	case 0x65:
2019 		ext(output, "hh|renameFile");
2020 		break;
2021 	case 0x66:
2022 		ext(output, "|stopObjectCode");
2023 		break;
2024 	case 0x67:
2025 		ext(output, "p|localizeArrayToRoom");
2026 		break;
2027 	case 0x68:
2028 		ext(output, "x" "roomOps\0"
2029 				"\x3Fpppp|setPalColor,"
2030 				"\x81pp|swapObjects,"
2031 				"\x82pp|copyPalColor,"
2032 				"\x83p|screenEffect,"
2033 				"\x84ppp|darkenPalette,"
2034 				"\x85ppppp|darkenPalette,"
2035 				"\x86p|setPalette,"
2036 				"\x87pp|setRoomPalette,"
2037 				"\x88pp|saveLoadRoom,"
2038 				"\x89hp|saveOrLoad,"
2039 				"\x8App|setScreen,"
2040 				"\x8Bpp|roomScroll");
2041 		break;
2042 	case 0x69:
2043 		// This is *almost* identical to the other print opcodes, only the 'begine' subop differs
2044 		ext(output, "x" "printActor\0"
2045 				"\x6pp|XY,"
2046 				"\xC|center,"
2047 				"\x12p|right,"
2048 				"\x14p|color,"
2049 				"\x15l|colors,"
2050 				"\x2E|left,"
2051 				"\x33|mumble,"
2052 				"\x38|overhead,"
2053 				"\x4Ep|getText,"
2054 				"\x4Fs|msg,"
2055 				"\x5Bp|begin,"
2056 				"\x5C|end");
2057 		break;
2058 	case 0x6A:
2059 		PRINT_V100HE("printEgo");
2060 		break;
2061 	case 0x6B:
2062 		ext(output, "ps|talkActor");
2063 		break;
2064 	case 0x6C:
2065 		ext(output, "s|talkEgo");
2066 		break;
2067 	case 0x6E:
2068 		ext(output, "ppp|seekFilePos");
2069 		break;
2070 	case 0x6F:
2071 		ext(output, "pl|setBoxFlags");
2072 		break;
2073 	case 0x71:
2074 		ext(output, "p|setBotSet");
2075 		break;
2076 	case 0x72:
2077 		ext(output, "x" "setSystemMessage\0"
2078 				"\x50h|titleMsg,"
2079 				"\x83h|versionMsg");
2080 		break;
2081 	case 0x73:
2082 		ext(output, "wpp|shuffle");
2083 		break;
2084 	case 0x74:
2085 		ext(output, "p|delay");
2086 		break;
2087 	case 0x75:
2088 		ext(output, "p|delayMinutes");
2089 		break;
2090 	case 0x76:
2091 		ext(output, "p|delaySeconds");
2092 		break;
2093 	case 0x77:
2094 		ext(output, "x" "soundOps\0"
2095 				"\x6p|setOffset,"
2096 				"\x2Fhp|loadSoundFromFile,"
2097 				"\x37|setQuickStart,"
2098 				"\x53ppp|setSoundVar,"
2099 				"\x5C|start,"
2100 				"\x80|setAppend,"
2101 				"\x81p|setChannel,"
2102 				"\x82p|setFrequency,"
2103 				"\x83|setLoop,"
2104 				"\x84p|setMusicId,"
2105 				"\x85p|setPan,"
2106 				"\x86p|setSoundId,"
2107 				"\x87|setSoftSound,"
2108 				"\x88p|setVolume");
2109 		break;
2110 	case 0x79:
2111 		ext(output, "x" "setSpriteInfo\0"
2112 				"\x0pp|setRange,"
2113 				"\x2p|setAngle,"
2114 				"\x3p|setAutoAnimFlag,"
2115 				"\x4p|setAnimSpeed,"
2116 				"\x6pp|setPosition,"
2117 				"\x7p|setSourceImage,"
2118 				"\x10l|setClass,"
2119 				"\x20p|setEraseType,"
2120 				"\x26p|setGroup,"
2121 				"\x28p|setImage,"
2122 				"\x30p|setMaskImage,"
2123 				"\x31pp|move,"
2124 				"\x34|stringUnk,"
2125 				"\x35|resetSprite,"
2126 				"\x36pp|setGeneralProperty,"
2127 				"\x39p|setPalette,"
2128 				"\x3Bp|setPriority,"
2129 				"\x3Cpp|setFlags,"
2130 				"\x3D|resetTables,"
2131 				"\x41p|setScale,"
2132 				"\x46p|setAutoShadow,"
2133 				"\x49p|setImageState,"
2134 				"\x4App|setDist,"
2135 				"\x4Bp|setDistX,"
2136 				"\x4Cp|setDistY,"
2137 				"\x52p|setUpdateType,"
2138 				"\x53pp|setUserValue,"
2139 				"\x58p|setField84,"
2140 				"\x59|clearField84");
2141 		break;
2142 	case 0x7A:
2143 		ext(output, "pppp|stampObject");
2144 		break;
2145 	case 0x7B:
2146 		ext(output, "lppi|startObject");
2147 		break;
2148 	case 0x7C:
2149 		ext(output, "lpi|startScript");
2150 		break;
2151 	case 0x7D:
2152 		ext(output, "lp|startScriptQuick");
2153 		break;
2154 	case 0x7E:
2155 		ext(output, "pp|setState");
2156 		break;
2157 	case 0x7F:
2158 		ext(output, "p|stopObjectScript");
2159 		break;
2160 	case 0x80:
2161 		ext(output, "p|stopScript");
2162 		break;
2163 	case 0x81:
2164 		ext(output, "|stopSentence");
2165 		break;
2166 	case 0x82:
2167 		ext(output, "p|stopSound");
2168 		break;
2169 	case 0x83:
2170 		ext(output, "|stopTalking");
2171 		break;
2172 	case 0x84:
2173 		writeVar(output, get_word(), pop());
2174 		break;
2175 	case 0x85:
2176 		se_a = pop();
2177 		writeArray(output, get_word(), NULL, pop(), se_a);
2178 		break;
2179 	case 0x86:
2180 		se_a = pop();
2181 		se_b = pop();
2182 		writeArray(output, get_word(), pop(), se_b, se_a);
2183 		break;
2184 	case 0x87:
2185 		se_a = pop();
2186 		se_b = pop();
2187 		push(se_oper(se_b, 7 + isEqual, se_a));
2188 		break;
2189 	case 0x88:
2190 		ext(output, "x" "systemOps\0"
2191 				 "\x3D|restart,"
2192 				 "\x80|clearDrawQueue,"
2193 				 "\x84|confirmShutDown,"
2194 				 "\x85|shutDown,"
2195 				 "\x86|startGame,"
2196 				 "\x87|startExec,"
2197 				 "\x88|copyVirtBuf");
2198 		break;
2199 	case 0x89:
2200 		ext(output, "x" "windowOps\0"
2201 				"\x0p|case0,"
2202 				"\x6pp|case6,"
2203 				"\x11p|case17,"
2204 				"\x27p|case39,"
2205 				"\x28p|case40,"
2206 				"\x31pp|case49,"
2207 				"\x35|case53,"
2208 				"\x42p|case66,"
2209 				"\x43p|case67,"
2210 				"\x47p|case71,"
2211 				"\x50h|case80,"
2212 				"\x54p|case84,"
2213 				"\x5C|case92");
2214 		break;
2215 	case 0x8A:
2216 		ext(output, "pi|setTimer");
2217 		break;
2218 	case 0x8B:
2219 		ext(output, "x" "cursorCommand\0"
2220 				"\xEp|initCharset,"
2221 				"\xFl|charsetColors,"
2222 				"\x80z|setCursorImg,"
2223 				"\x81z|setCursorImg,"
2224 				"\x82zp|setCursorImgWithPal,"
2225 				"\x86|cursorOn,"
2226 				"\x87|cursorOff,"
2227 				"\x88|softCursorOn,"
2228 				"\x89|softCursorOff,"
2229 				"\x8B|userPutOn,"
2230 				"\x8C|userPutOff,"
2231 				"\x8D|softUserputOn,"
2232 				"\x8E|softUserputOff");
2233 
2234 		break;
2235 	case 0x8C:
2236 		ext(output, "x" "videoOps\0"
2237 				"\x0p|setUnk2,"
2238 				"\x13|setStatus,"
2239 				"\x28p|setWizResNumX,"
2240 				"\x2Fh|setFilename,"
2241 				"\x43p|setFlags,"
2242 				"\x5C|playOrStopVideo,");
2243 		break;
2244 	case 0x8D:
2245 		ext(output, "x" "wait\0"
2246 				"\x80pj|waitForActor,"
2247 				"\x81|waitForCamera,"
2248 				"\x82|waitForMessage,"
2249 				"\x83|waitForSentence");
2250 		break;
2251 	case 0x8E:
2252 		ext(output, "ppp|walkActorToObj");
2253 		break;
2254 	case 0x8F:
2255 		ext(output, "ppp|walkActorTo");
2256 		break;
2257 	case 0x90:
2258 		ext(output, "x" "writeFile\0"
2259 				"\x5ppi|writeArrayToFile,"
2260 				"\x2App|writeWord,"
2261 				"\x2Bpp|writeDWord,"
2262 				"\x2Dpp|writeByte");
2263 		break;
2264 	case 0x91:
2265 		ext(output, "x" "writeINI\0"
2266 				"\x2Bph|number,"
2267 				"\x4Dhh|string");
2268 		break;
2269 	case 0x92:
2270 		ext(output, "x" "writeConfigFile\0"
2271 				"\x2Bphhh|number,"
2272 				"\x4Dhhhh|string");
2273 		break;
2274 	case 0x93:
2275 		ext(output, "rp|abs");
2276 		break;
2277 	case 0x94:
2278 		ext(output, "rp|getActorWalkBox");
2279 		break;
2280 	case 0x95:
2281 		ext(output, "rp|getActorCostume");
2282 		break;
2283 	case 0x96:
2284 		ext(output, "rp|getActorElevation");
2285 		break;
2286 	case 0x97:
2287 		ext(output, "rp|getObjectDir");
2288 		break;
2289 	case 0x98:
2290 		ext(output, "rp|getActorMoving");
2291 		break;
2292 	case 0x99:
2293 		ext(output, "rppp|getActorData");
2294 		break;
2295 	case 0x9A:
2296 		ext(output, "rp|getActorRoom");
2297 		break;
2298 	case 0x9B:
2299 		ext(output, "rp|getActorScaleX");
2300 		break;
2301 	case 0x9C:
2302 		ext(output, "rpp|getAnimateVariable");
2303 		break;
2304 	case 0x9D:
2305 		ext(output, "rp|getActorWidth");
2306 		break;
2307 	case 0x9E:
2308 		ext(output, "rp|objectX");
2309 		break;
2310 	case 0x9F:
2311 		ext(output, "rp|objectY");
2312 		break;
2313 	case 0xA0:
2314 		ext(output, "rpp|atan2");
2315 		break;
2316 	case 0xA1:
2317 		ext(output, "rpppp|getSegmentAngle");
2318 		break;
2319 	case 0xA2:
2320 		ext(output, "rp|getActorAnimProgress");
2321 		break;
2322 	case 0xA3:
2323 		ext(output, "rx" "getDistanceBetweenPoints\0"
2324 				"\x17pppp|case17,"
2325 				"\x18pppppp|case18");
2326 		break;
2327 	case 0xA4:
2328 		ext(output, "rlp|ifClassOfIs");
2329 		break;
2330 	case 0xA6:
2331 		ext(output, "rppp|cond");
2332 		break;
2333 	case 0xA7:
2334 		ext(output, "rp|cos");
2335 		break;
2336 	case 0xA8:
2337 		// Backyard Baseball 2003 / Basketball / Football 2002
2338 		if (g_options.heVersion == 101) {
2339 			ext(output, "rh|debugInput");
2340 		} else {
2341 		// All other games
2342 			switch (get_byte()) {
2343 			case 0:
2344 				ext(output, "h|debugInput: case 0");
2345 				break;
2346 			case 26:
2347 				ext(output, "p|debugInput: case 26");
2348 				break;
2349 			case 27:
2350 				ext(output, "h|debugInput: case 27");
2351 				break;
2352 			case 80:
2353 				ext(output, "h|debugInput: case 80");
2354 				break;
2355 			case 92:
2356 				ext(output, "r|debugInput: case 92");
2357 				break;
2358 			}
2359 		}
2360 		break;
2361 	case 0xA9:
2362 		ext(output, "rh|getFileSize");
2363 		break;
2364 	case 0xAA:
2365 		ext(output, "rpp|getActorFromXY");
2366 		break;
2367 	case 0xAB:
2368 		ext(output, "rp|findAllObjects");
2369 		break;
2370 	case 0xAC:
2371 		ext(output, "rlp|findAllObjectsWithClassOf");
2372 		break;
2373 
2374 	case 0xAE:
2375 		ext(output, "rpp|findInventory");
2376 		break;
2377 	case 0xAF:
2378 		ext(output, "rpp|findObject");
2379 		break;
2380 	case 0xB0:
2381 		ext(output, "rlpp|findObjectWithClassOf");
2382 		break;
2383 	case 0xB1:
2384 			ext(output, "rpp|polygonHit");
2385 		break;
2386 	case 0xB2:
2387 		ext(output, "rwwpppppppp|getLinesIntersectionPoint");
2388 		break;
2389 	case 0xB3:
2390 		ext(output, "rx" "fontUnk\0"
2391 				"\x0|case0,"
2392 				"\x3Cpp|case60");
2393 		break;
2394 	case 0xB4:
2395 		ext(output, "r|getNumFreeArrays");
2396 		break;
2397 	case 0xB5:
2398 		ext(output, "rx" "getArrayDimSize\0"
2399 				"\x1v|dim1size,"
2400 				"\x2v|dim2size,"
2401 				"\x3v|dim1size,"
2402 				"\x4v|dim1start,"
2403 				"\x5v|dim1end,"
2404 				"\x6v|dim2start,"
2405 				"\x7v|dim2end");
2406 		break;
2407 	case 0xB6:
2408 		ext(output, "rx" "isResourceLoaded\0"
2409 				"\x19p|costume,"
2410 				"\x28p|image,"
2411 				"\x3Ep|room,"
2412 				"\x42p|script,"
2413 				"\x48p|sound");
2414 		break;
2415 	case 0xB7:
2416 		ext(output, "rx" "getResourceSize\0"
2417 				"\x19p|costume,"
2418 				"\x28p|image,"
2419 				"\x3Ep|roomImage,"
2420 				"\x42p|script,"
2421 				"\x48p|sound");
2422 		break;
2423 	case 0xB8:
2424 		ext(output, "rx" "getSpriteGroupInfo\0"
2425 				"\x5p|getSpriteArray,"
2426 				"\x28p|getDstResNum,"
2427 				"\x36pp|dummy,"
2428 				"\x3Bp|getPriority,"
2429 				"\x3Cpp|getXYScale?,"
2430 				"\x55p|getPositionX,"
2431 				"\x56p|getPositionY");
2432 		break;
2433 	case 0xB9:
2434 		ext(output, "rx" "getHeap\0"
2435 				"\x82|freeSpace,"
2436 				"\x83|largestBlockSize");
2437 		break;
2438 	case 0xBA:
2439 		ext(output, "rx" "getWizData\0"
2440 				"\x14pppp|pixelColor,"
2441 				"\x1Ap|imageCount,"
2442 				"\x21pppp|isPixelNonTransparentnumber,"
2443 				"\x27pp|height,"
2444 				"\x36ppp|block,"
2445 				"\x54pp|width,"
2446 				"\x55pp|imageSpotX,"
2447 				"\x56pp|imageSpotY,"
2448 				"\x83php|case131,"
2449 				"\x84pppppp|histogram");
2450 		break;
2451 	case 0xBB:
2452 		ext(output, "rpp|isActorInBox");
2453 		break;
2454 	case 0xBC:
2455 		ext(output, "rlp|isAnyOf");
2456 		break;
2457 	case 0xBD:
2458 		ext(output, "rp|getInventoryCount");
2459 		break;
2460 	case 0xBE:
2461 		ext(output, "ry" "kernelGetFunctions\0"
2462 				"\x1|virtScreenSave"
2463 				);
2464 		break;
2465 	case 0xBF:
2466 		ext(output, "rpp|max");
2467 		break;
2468 	case 0xC0:
2469 		ext(output, "rpp|min");
2470 		break;
2471 	case 0xC1:
2472 		ext(output, "rp|getObjectX");
2473 		break;
2474 	case 0xC2:
2475 		ext(output, "rp|getObjectY");
2476 		break;
2477 	case 0xC3:
2478 		ext(output, "rp|isRoomScriptRunning");
2479 		break;
2480 	case 0xC4:
2481 		ext(output, "rx" "getObjectData\0"
2482 				"\x20|getWidth,"
2483 				"\x21|getHeight,"
2484 				"\x24|getImageCount,"
2485 				"\x26|getX,"
2486 				"\x27|getY,"
2487 				"\x34|getState,"
2488 				"\x39p|setId,"
2489 				"\x8Bp|dummy");
2490 		break;
2491 	case 0xC5:
2492 		ext(output, "rph|openFile");
2493 		break;
2494 	case 0xC6:
2495 		ext(output, "rllp|getPolygonOverlap");
2496 		break;
2497 	case 0xC7:
2498 		ext(output, "rp|getOwner");
2499 		break;
2500 	case 0xC8:
2501 		ext(output, "rx" "getPaletteData\0"
2502 				"\xDpp|get16BitColorComponent,"
2503 				"\x14pp|getColor,"
2504 				"\x21pppppp|getSimilarColor,"
2505 				"\x35ppp|get16BitColor,"
2506 				"\x49ppp|getColorCompontent");
2507 		break;
2508 	case 0xC9:
2509 		ext(output, "rlp|pickOneOf");
2510 		break;
2511 	case 0xCA:
2512 		ext(output, "rplp|pickOneOfDefault");
2513 		break;
2514 	case 0xCB:
2515 		ext(output, "rlw|pickVarRandom");
2516 		break;
2517 	case 0xCC:
2518 		ext(output, "rx" "getPixel\0"
2519 				"\x8pp|foreground,"
2520 				"\x9pp|background");
2521 		break;
2522 	case 0xCD:
2523 		ext(output, "rpp|getDistObjObj");
2524 		break;
2525 	case 0xCE:
2526 		ext(output, "rppp|getDistObjPt");
2527 		break;
2528 	case 0xCF:
2529 		ext(output, "rpppp|getDistPtPt");
2530 		break;
2531 	case 0xD0:
2532 		ext(output, "rp|getRandomNumber");
2533 		break;
2534 	case 0xD1:
2535 		ext(output, "rpp|getRandomNumberRange");
2536 		break;
2537 	case 0xD3:
2538 		ext(output, "rx" "readFile\0"
2539 				"\x5ppi|readArrayFromFile,"
2540 				"\x2Ap|readWord,"
2541 				"\x2Bp|readDWord,"
2542 				"\x2Dp|readByte");
2543 		break;
2544 	case 0xD4:
2545 		ext(output, "rx" "readINI\0"
2546 				"\x2Bh|number,"
2547 				"\x4Dh|string");
2548 		break;
2549 	case 0xD5:
2550 		ext(output, "rx" "readConfigFile\0"
2551 				"\x2Bhhh|number,"
2552 				"\x4Dhhh|string");
2553 		break;
2554 	case 0xD6:
2555 		ext(output, "rp|isScriptRunning");
2556 		break;
2557 	case 0xD7:
2558 		ext(output, "rp|sin");
2559 		break;
2560 	case 0xD8:
2561 		ext(output, "rp|getSoundPosition");
2562 		break;
2563 	case 0xD9:
2564 		ext(output, "rp|isSoundRunning");
2565 		break;
2566 	case 0xDA:
2567 		ext(output, "rpp|getSoundVar");
2568 		break;
2569 	case 0xDB:
2570 			ext(output, "rx" "getSpriteInfo\0"
2571 					"\x3p|getFlagAutoAnim,"
2572 					"\x4p|getAnimSpeed,"
2573 					"\x7p|getSourceImage,"
2574 					"\x10lp|getClass,"
2575 					"\x1Ap|getImageStateCount,"
2576 					"\x1Ep|getDisplayX,"
2577 					"\x1Fp|getDisplayY,"
2578 					"\x20p|getEraseType,"
2579 					"\x21lpppp|findSprite,"
2580 					"\x26p|getGroup,"
2581 					"\x27p|getImageY,"
2582 					"\x28p|getImage,"
2583 					"\x30p|getMaskImage,"
2584 					"\x36pp|getGeneralProperty,"
2585 					"\x39p|getPalette,"
2586 					"\x3Bp|getPriority,"
2587 					"\x3Cpp|getFlags,"
2588 					"\x41p|getScale,"
2589 					"\x46p|getShadow,"
2590 					"\x49p|getImageState,"
2591 					"\x4Bp|getDistX,"
2592 					"\x4Cp|getDistY,"
2593 					"\x52p|getUpdateType,"
2594 					"\x53pp|getUserValue,"
2595 					"\x54p|getImageX,"
2596 					"\x55p|getPosX,"
2597 					"\x56p|getPosY");
2598 		break;
2599 	case 0xDC:
2600 		ext(output, "rp|sqrt");
2601 		break;
2602 	case 0xDD:
2603 		// TODO: this loads another script which does something like
2604 		// stack altering and then finishes (usually with opcode 0xBD).
2605 		// When stack is changed, further disassembly is wrong.
2606 		// This is widely used in HE games.
2607 		// As there are cases when called script does not alter the
2608 		// stack, it's not correct to use "rlpp|..." here
2609 		ext(output, "lpp|startObjectQuick");
2610 		break;
2611 	case 0xDE:
2612 		ext(output, "lp|startScriptQuick2");
2613 		break;
2614 	case 0xDF:
2615 		ext(output, "rp|getState");
2616 		break;
2617 	case 0xE0:
2618 		ext(output, "rpp|compareString");
2619 		break;
2620 	case 0xE1:
2621 		ext(output, "rp|copyString");
2622 		break;
2623 	case 0xE2:
2624 		ext(output, "rppp|appendString");
2625 		break;
2626 	case 0xE3:
2627 		ext(output, "rpp|concatString");
2628 		break;
2629 	case 0xE4:
2630 		ext(output, "rp|getStringLen");
2631 		break;
2632 	case 0xE5:
2633 		ext(output, "rppp|getStringLenForWidth");
2634 		break;
2635 	case 0xE6:
2636 		ext(output, "rp|stringToInt");
2637 		break;
2638 	case 0xE7:
2639 		ext(output, "rpppp|getCharIndexInString");
2640 		break;
2641 	case 0xE8:
2642 		ext(output, "rppp|getStringWidth");
2643 		break;
2644 	case 0xE9:
2645 		ext(output, "rp|readFilePos");
2646 		break;
2647 	case 0xEA:
2648 		ext(output, "ri|getTimer");
2649 		break;
2650 	case 0xEB:
2651 		ext(output, "rpp|getVerbEntrypoint");
2652 		break;
2653 	case 0xEC:
2654 		ext(output, "rx" "getVideoData\0"
2655 				"\x1Ap|frameCount,"
2656 				"\x27p|height,"
2657 				"\x28p|imageNum,"
2658 				"\x36pp|statistics,"
2659 				"\x49p|curFrame,"
2660 				"\x54p|width");
2661 		break;
2662 	default:
2663 		invalidop(NULL, code);
2664 		break;
2665 	}
2666 }
2667 
2668 #define PRINT_V7HE(name)           \
2669 	do {                          \
2670 		ext(output, "x" name "\0"         \
2671 				"\x41pp|XY,"      \
2672 				"\x42p|color,"    \
2673 				"\x43p|right,"    \
2674 				"\x45|center,"    \
2675 				"\x47|left,"      \
2676 				"\x48|overhead,"  \
2677 				"\x4A|mumble,"    \
2678 				"\x4Bs|msg,"      \
2679 				"\xF9l|colors,"	  \
2680 				"\xC2lps|debug,"  \
2681 				"\xE1p|getText,"  \
2682 				"\xFE|begin,"     \
2683 				"\xFF|end"        \
2684 				);                \
2685 	} while(0)
2686 
next_line_HE_V72(char * output)2687 void next_line_HE_V72(char *output) {
2688 	byte code = get_byte();
2689 	StackEnt *se_a, *se_b;
2690 
2691 	switch (code) {
2692 	case 0x0:
2693 		push(se_int(get_byte()));
2694 		break;
2695 	case 0x1:
2696 		push(se_int(get_word()));
2697 		break;
2698 	case 0x2:
2699 		push(se_int(get_dword()));
2700 		break;
2701 	case 0x3:
2702 		push(se_var(get_word()));
2703 		break;
2704 	case 0x4:
2705 		getScriptString();
2706 		break;
2707 	case 0x7:
2708 		push(se_array(get_word(), NULL, pop()));
2709 		break;
2710 	case 0xA: // HE90+
2711 		dup_n();
2712 		break;
2713 	case 0xB:
2714 		se_a = pop();
2715 		push(se_array(get_word(), pop(), se_a));
2716 		break;
2717 	case 0xC:
2718 		se_a = dup(output, pop());
2719 		push(se_a);
2720 		push(se_a);
2721 		break;
2722 	case 0xD:
2723 		push(se_oper(pop(), isZero));
2724 		break;
2725 	case 0xE:
2726 	case 0xF:
2727 	case 0x10:
2728 	case 0x11:
2729 	case 0x12:
2730 	case 0x13:
2731 	case 0x14:
2732 	case 0x15:
2733 	case 0x16:
2734 	case 0x17:
2735 	case 0x18:
2736 	case 0x19:
2737 		se_a = pop();
2738 		se_b = pop();
2739 		push(se_oper(se_b, (code - 0xE) + isEqual, se_a));
2740 		break;
2741 	case 0x1A:
2742 	case 0xA7:
2743 		kill(output, pop());
2744 		break;
2745 	case 0x1B:
2746 		ext(output, "rlp|isAnyOf2");
2747 		break;
2748 	case 0x1C: // HE90+
2749 		ext(output, "x" "wizImageOps\0"
2750 				"\x20p|setResDefImageWidth,"
2751 				"\x21p|setResDefImageHeight,"
2752 				"\x30|processMode1,"
2753 				"\x31h|readFile,"
2754 				"\x32hp|writeFile,"
2755 				"\x33ppppp|setCaptureRect,"
2756 				"\x34p|setImageState,"
2757 				"\x35p|setAngle,"
2758 				"\x36p|setFlags,"
2759 				"\x38ppppp|drawWizImage,"
2760 				"\x39p|setImage,"
2761 				"\x3Ep|setSourceImage,"
2762 				"\x41pp|setPosition,"
2763 				"\x42pp|remapPalette,"
2764 				"\x43pppp|setClipRect,"
2765 				"\x56p|setPalette,"
2766 				"\x5Cp|setScale,"
2767 				"\x62p|setShadow,"
2768 				"\x83ppp|capturePolygon,"
2769 				"\x85ppppp|fillWizRect,"
2770 				"\x86ppppp|fillWizLine,"
2771 				"\x87ppp|fillWizPixel,"
2772 				"\x88ppp|fillWizFlood,"
2773 				"\x89p|setDstResNum,"
2774 				"\x8Bpp|setThickLine,"
2775 				"\x8D|startFont,"
2776 				"\x8Epppph|createFont,"
2777 				"\x8Fpph|renderFontString,"
2778 				"\x9App|setPosition,"
2779 				"\xBDpppppppp|ellipse,"
2780 				"\xC4|endFont,"
2781 				"\xD9|createWizImage,"
2782 				"\xF6p|setupPolygon,"
2783 				"\xF9pp|remapPalette,"
2784 				"\xFF|processWizImage");
2785 		break;
2786 	case 0x1D: // HE90+
2787 		ext(output, "rpp|min");
2788 		break;
2789 	case 0x1E: // HE90+
2790 		ext(output, "rpp|max");
2791 		break;
2792 	case 0x1F: // HE90+
2793 		ext(output, "rp|sin");
2794 		break;
2795 	case 0x20: // HE90+
2796 		ext(output, "rp|cos");
2797 		break;
2798 	case 0x21: // HE90+
2799 		ext(output, "rp|sqrt");
2800 		break;
2801 	case 0x22: // HE90+
2802 		ext(output, "rpp|atan2");
2803 		break;
2804 	case 0x23: // HE90+
2805 		ext(output, "rpppp|getSegmentAngle");
2806 		break;
2807 	case 0x24: // HE90+
2808 		ext(output, "rx" "getDistanceBetweenPoints\0"
2809 				"\x1Cpppp|case28,"
2810 				"\x1Dpppppp|case29");
2811 		break;
2812 	case 0x25: // HE90+
2813 		if (g_options.heVersion >= 99) {
2814 			ext(output, "rx" "getSpriteInfo\0"
2815 					"\x1Ep|getPosX,"
2816 					"\x1Fp|getPosY,"
2817 					"\x20p|getImageX,"
2818 					"\x21p|getImageY,"
2819 					"\x22p|getDistX,"
2820 					"\x23p|getDistY,"
2821 					"\x24p|getImageStateCount,"
2822 					"\x25p|getGroup,"
2823 					"\x26p|getDisplayX,"
2824 					"\x27p|getDisplayY,"
2825 					"\x2App|getFlags,"
2826 					"\x2Bp|getPriority,"
2827 					"\x2Dlpppp|findSprite,"
2828 					"\x34p|getImageState,"
2829 					"\x3Ep|getSourceImage,"
2830 					"\x3Fp|getImage,"
2831 					"\x44p|getEraseType,"
2832 					"\x52p|getFlagAutoAnim,"
2833 					"\x56p|getPalette,"
2834 					"\x5Cp|getScale,"
2835 					"\x61p|getAnimSpeed,"
2836 					"\x62p|getShadow,"
2837 					"\x7Cp|getUpdateType,"
2838 					"\x7Dlp|getClass,"
2839 					"\x8Bpp|getGeneralProperty,"
2840 					"\x8Cp|getMaskImage,"
2841 					"\xC6pp|getUserValue");
2842 		} else if (g_options.heVersion >= 98) {
2843 			ext(output, "rx" "getSpriteInfo\0"
2844 					"\x1Ep|getPosX,"
2845 					"\x1Fp|getPosY,"
2846 					"\x20p|getImageX,"
2847 					"\x21p|getImageY,"
2848 					"\x22p|getDistX,"
2849 					"\x23p|getDistY,"
2850 					"\x24p|getImageStateCount,"
2851 					"\x25p|getGroup,"
2852 					"\x26p|getDisplayX,"
2853 					"\x27p|getDisplayY,"
2854 					"\x2App|getFlags,"
2855 					"\x2Bp|getPriority,"
2856 					"\x2Dpppp|findSprite,"
2857 					"\x34p|getImageState,"
2858 					"\x3Ep|getSourceImage,"
2859 					"\x3Fp|getImage,"
2860 					"\x44p|getEraseType,"
2861 					"\x52p|getFlagAutoAnim,"
2862 					"\x56p|getPalette,"
2863 					"\x5Cp|getScale,"
2864 					"\x61p|getAnimSpeed,"
2865 					"\x62p|getShadow,"
2866 					"\x7Cp|getUpdateType,"
2867 					"\x7Dlp|getClass,"
2868 					"\x8Bpp|getGeneralProperty,"
2869 					"\x8Cp|getMaskImage,"
2870 					"\xC6pp|getUserValue");
2871 		} else {
2872 			ext(output, "rx" "getSpriteInfo\0"
2873 					"\x1Ep|getPosX,"
2874 					"\x1Fp|getPosY,"
2875 					"\x20p|getImageX,"
2876 					"\x21p|getImageY,"
2877 					"\x22p|getDistX,"
2878 					"\x23p|getDistY,"
2879 					"\x24p|getImageStateCount,"
2880 					"\x25p|getGroup,"
2881 					"\x26p|getDisplayX,"
2882 					"\x27p|getDisplayY,"
2883 					"\x2App|getFlags,"
2884 					"\x2Bp|getPriority,"
2885 					"\x2Dppp|findSprite,"
2886 					"\x34p|getImageState,"
2887 					"\x3Ep|getSourceImage,"
2888 					"\x3Fp|getImage,"
2889 					"\x44p|getEraseType,"
2890 					"\x52p|getFlagAutoAnim,"
2891 					"\x56p|getPalette,"
2892 					"\x5Cp|getScale,"
2893 					"\x61p|getAnimSpeed,"
2894 					"\x62p|getShadow,"
2895 					"\x7Cp|getUpdateType,"
2896 					"\x7Dlp|getClass,"
2897 					"\x8Bpp|getGeneralProperty,"
2898 					"\x8Cp|getMaskImage,"
2899 					"\xC6pp|getUserValue");
2900 		}
2901 		break;
2902 	case 0x26: // HE90+
2903 		if (g_options.heVersion >= 99) {
2904 			ext(output, "x" "setSpriteInfo\0"
2905 					"\x22p|setDistX,"
2906 					"\x23p|setDistY,"
2907 					"\x25p|setGroup,"
2908 					"\x2App|setFlags,"
2909 					"\x2Bp|setPriority,"
2910 					"\x2Cpp|move,"
2911 					"\x34p|setImageState,"
2912 					"\x35p|setAngle,"
2913 					"\x39pp|setRange,"
2914 					"\x3Ep|setSourceImage,"
2915 					"\x3Fp|setImage,"
2916 					"\x41pp|setPosition,"
2917 					"\x44p|setEraseType,"
2918 					"\x4Dpp|setDist,"
2919 					"\x52p|setAutoAnimFlag,"
2920 					"\x56p|setPalette,"
2921 					"\x5Cp|setScale,"
2922 					"\x61p|setAnimSpeed,"
2923 					"\x62p|setAutoShadow,"
2924 					"\x7Cp|setUpdateType,"
2925 					"\x7Dl|setClass,"
2926 					"\x8Bpp|setGeneralProperty,"
2927 					"\x8Cp|setMaskImage,"
2928 					"\x9E|resetTables,"
2929 					"\xC6pp|setUserValue,"
2930 					"\xD9|resetSprite");
2931 		} else {
2932 			ext(output, "x" "setSpriteInfo\0"
2933 					"\x22p|setDistX,"
2934 					"\x23p|setDistY,"
2935 					"\x25p|setGroup,"
2936 					"\x2App|setFlags,"
2937 					"\x2Bp|setPriority,"
2938 					"\x2Cpp|move,"
2939 					"\x34p|setImageState,"
2940 					"\x35p|setAngle,"
2941 					"\x39p|setRange,"
2942 					"\x3Ep|setSourceImage,"
2943 					"\x3Fp|setImage,"
2944 					"\x41pp|setPosition,"
2945 					"\x44p|setEraseType,"
2946 					"\x4Dpp|setDist,"
2947 					"\x52p|setAutoAnimFlag,"
2948 					"\x56p|setPalette,"
2949 					"\x5Cp|setScale,"
2950 					"\x61p|setAnimSpeed,"
2951 					"\x62p|setAutoShadow,"
2952 					"\x7Cp|setUpdateType,"
2953 					"\x7Dl|setClass,"
2954 					"\x8Bpp|setGeneralProperty,"
2955 					"\x8Cp|setMaskImage,"
2956 					"\x9E|resetTables,"
2957 					"\xC6pp|setUserValue,"
2958 					"\xD9|resetSprite");
2959 		}
2960 		break;
2961 	case 0x27: // HE90+
2962 		ext(output, "rx" "getSpriteGroupInfo\0"
2963 				"\x8p|getSpriteArray,"
2964 				"\x1Ep|getPositionX,"
2965 				"\x1Fp|getPositionY,"
2966 				"\x2App|getXYScale?,"
2967 				"\x2Bp|getPriority,"
2968 				"\x3Fp|getDstResNum,"
2969 				"\x8Bpp|dummy");
2970 		break;
2971 	case 0x28: // HE90+
2972 		ext(output, "x" "setSpriteGroupInfo\0"
2973 				"\x25pp|misc,"
2974 				"\x2App|setXYScale?,"
2975 				"\x2Bp|setPriority,"
2976 				"\x2Cpp|move,"
2977 				"\x39p|setId,"
2978 				"\x3Fp|setImage,"
2979 				"\x41pp|setPosition,"
2980 				"\x43pppp|setBounds,"
2981 				"\x5D|resetBounds,"
2982 				"\xD9|reset");
2983 		break;
2984 	case 0x29: // HE90+
2985 		ext(output, "rx" "getWizData\0"
2986 				"\x1Epp|imageSpotX,"
2987 				"\x1Fpp|imageSpotY,"
2988 				"\x20pp|width,"
2989 				"\x21pp|height,"
2990 				"\x24p|imageCount,"
2991 				"\x2Dpppp|isPixelNonTransparentnumber,"
2992 				"\x42pppp|pixelColor,"
2993 				"\x82pppppp|histogram,"
2994 				"\x8Dphp|case141");
2995 		break;
2996 	case 0x2A: // HE90+
2997 		ext(output, "rppp|getActorData");
2998 		break;
2999 	case 0x2B: // HE90+
3000 		ext(output, "lppi|startScriptUnk");
3001 		break;
3002 	case 0x2C: // HE90+
3003 		ext(output, "lppi|jumpToScriptUnk");
3004 		break;
3005 	case 0x2D: // HE90+
3006 		ext(output, "x" "videoOps\0"
3007 				"\x31h|setFilename,"
3008 				"\x36p|setFlags,"
3009 				"\x39p|setUnk2,"
3010 				"\x3Fp|setWizResNumX,"
3011 				"\xA5|setStatus,"
3012 				"\xFF|playOrStopVideo,");
3013 		break;
3014 	case 0x2E: // HE95+
3015 		ext(output, "rx" "getVideoData\0"
3016 				"\x20p|width,"
3017 				"\x21p|height,"
3018 				"\x24p|frameCount,"
3019 				"\x34p|curFrame,"
3020 				"\x3Fp|imageNum,"
3021 				"\x8Bpp|statistics");
3022 		break;
3023 	case 0x2F: // HE90+
3024 		ext(output, "x" "floodFill\0"
3025 				"\x36p|dummy,"
3026 				"\x39|reset,"
3027 				"\x41pp|setXY,"
3028 				"\x42p|setFlags,"
3029 				"\x43pppp|setBoxRect,"
3030 				"\xFF|floodFill");
3031 		break;
3032 	case 0x30: // HE90+
3033 		ext(output, "rpp|mod");
3034 		break;
3035 	case 0x31: // HE90+
3036 		ext(output, "rpp|shl");
3037 		break;
3038 	case 0x32: // HE90+
3039 		ext(output, "rpp|shr");
3040 		break;
3041 	case 0x33: // HE90+
3042 		ext(output, "rpp|xor");
3043 		break;
3044 	case 0x34:
3045 		ext(output, "rlp|findAllObjectsWithClassOf");
3046 		break;
3047 	case 0x35: // HE90+
3048 		ext(output, "rllp|getPolygonOverlap");
3049 		break;
3050 	case 0x36: // HE90+
3051 		ext(output, "rppp|cond");
3052 		break;
3053 	case 0x37: // HE90+
3054 		ext(output, "x" "dim2dim2Array\0"
3055 				"\x2pppppv|bit,"
3056 				"\x3pppppv|nibble,"
3057 				"\x4pppppv|byte,"
3058 				"\x5pppppv|int,"
3059 				"\x6pppppv|dword,"
3060 				"\x7pppppv|string");
3061 		break;
3062 	case 0x38: // HE90+
3063 		ext(output, "x" "redim2dimArray\0"
3064 				"\x4ppppv|byte,"
3065 				"\x5ppppv|int,"
3066 				"\x6ppppv|dword");
3067 		break;
3068 	case 0x39: // HE90+
3069 		ext(output, "rwwpppppppp|getLinesIntersectionPoint");
3070 		break;
3071 	case 0x3A: // HE90+
3072 		ext(output, "x" "sortArray\0"
3073 				"\x81pppppv|sort,");
3074 		break;
3075 	case 0x43:
3076 		writeVar(output, get_word(), pop());
3077 		break;
3078 	case 0x44: // HE90+
3079 		ext(output, "rx" "getObjectData\0"
3080 				"\x20|getWidth,"
3081 				"\x21|getHeight,"
3082 				"\x24|getImageCount,"
3083 				"\x26|getX,"
3084 				"\x27|getY,"
3085 				"\x34|getState,"
3086 				"\x39p|setId,"
3087 				"\x8Bp|dummy");
3088 		break;
3089 	case 0x45: // HE80+
3090 		ext(output, "x" "createSound\0"
3091 				"\x1Bp|create,"
3092 				"\xD9|reset,"
3093 				"\xE8p|setId,"
3094 				"\xFF|dummy");
3095 		break;
3096 	case 0x46: // HE80+
3097 		ext(output, "rh|getFileSize");
3098 		break;
3099 	case 0x47:
3100 		se_a = pop();
3101 		writeArray(output, get_word(), NULL, pop(), se_a);
3102 		break;
3103 	case 0x48: // HE80+
3104 		ext(output, "rp|stringToInt");
3105 		break;
3106 	case 0x49: // HE80+
3107 		ext(output, "rpp|getSoundVar");
3108 		break;
3109 	case 0x4A: // HE80+
3110 		ext(output, "p|localizeArrayToRoom");
3111 		break;
3112 	case 0x4B:
3113 		se_a = pop();
3114 		se_b = pop();
3115 		writeArray(output, get_word(), pop(), se_b, se_a);
3116 		break;
3117 	case 0x4D: // HE80+
3118 		ext(output, "rx" "readConfigFile\0"
3119 				"\x6hhh|number,"
3120 				"\x7hhh|string");
3121 		break;
3122 	case 0x4E: // HE80+
3123 		ext(output, "x" "writeConfigFile\0"
3124 				"\x6phhh|number,"
3125 				"\x7hhhh|string");
3126 		break;
3127 	case 0x4F:
3128 		addVar(output, get_word(), 1);
3129 		break;
3130 	case 0x50:
3131 		ext(output, "|resetCutScene");
3132 		break;
3133 	case 0x51:
3134 		ext(output, "rx" "getHeap\0"
3135 				"\xb|freeSpace,"
3136 				"\xc|largestBlockSize");
3137 		break;
3138 	case 0x52:
3139 		ext(output, "rlpp|findObjectWithClassOf");
3140 		break;
3141 	case 0x53:
3142 		addArray(output, get_word(), pop(), 1);
3143 		break;
3144 	case 0x54:
3145 		ext(output, "rp|objectX");
3146 		break;
3147 	case 0x55:
3148 		ext(output, "rp|objectY");
3149 		break;
3150 	case 0x56:
3151 		ext(output, "ppppp|captureWizImage");
3152 		break;
3153 	case 0x57:
3154 		addVar(output, get_word(), -1);
3155 		break;
3156 	case 0x58:
3157 		ext(output, "ri|getTimer");
3158 		break;
3159 	case 0x59:
3160 		ext(output, "pi|setTimer");
3161 		break;
3162 	case 0x5A:
3163 		ext(output, "rp|getSoundPosition");
3164 		break;
3165 	case 0x5B:
3166 		addArray(output, get_word(), pop(), -1);
3167 		break;
3168 	case 0x5C:
3169 		jumpif(output, pop(), true);
3170 		break;
3171 	case 0x5D:
3172 		jumpif(output, pop(), false);
3173 		break;
3174 	case 0x5E:
3175 		ext(output, "lpi|startScript");
3176 		break;
3177 	case 0x5F:
3178 		ext(output, "lp|startScriptQuick");
3179 		break;
3180 	case 0x60:
3181 		ext(output, "lppi|startObject");
3182 		break;
3183 	case 0x61:
3184 		ext(output, "x" "drawObject\0"
3185 				"\x3Epppp|setup,"
3186 				"\x3Fpp|setState,"
3187 				"\x41ppp|setPosition,");
3188 		break;
3189 	case 0x62:
3190 		ext(output, "p|printWizImage");
3191 		break;
3192 	case 0x63:
3193 		ext(output, "rx" "getArrayDimSize\0"
3194 				"\x1v|dim1size,"
3195 				"\x2v|dim2size,"
3196 				"\x3v|dim1size,"
3197 				"\x4v|dim1start,"
3198 				"\x5v|dim1end,"
3199 				"\x6v|dim2start,"
3200 				"\x7v|dim2end,");
3201 		break;
3202 	case 0x64:
3203 		ext(output, "r|getNumFreeArrays");
3204 		break;
3205 	case 0x65:
3206 		ext(output, "|stopObjectCodeA");
3207 		break;
3208 	case 0x66:
3209 		ext(output, "|stopObjectCodeB");
3210 		break;
3211 	case 0x67:
3212 		ext(output, "|endCutscene");
3213 		break;
3214 	case 0x68:
3215 		ext(output, "l|beginCutscene");
3216 		break;
3217 	case 0x69:
3218 		if (g_options.heVersion >= 80) {
3219 			ext(output, "x" "windowOps\0"
3220 					"\x2Cpp|case44,"
3221 					"\x39p|case57,"
3222 					"\x3Ap|case58,"
3223 					"\x3Bp|case59,"
3224 					"\x3Fp|case63,"
3225 					"\x41pp|case65,"
3226 					"\xD9|case217,"
3227 					"\xF3h|case243,"
3228 					"\xFF|case255");
3229 		} else {
3230 			ext(output, "|stopMusic");
3231 		}
3232 		break;
3233 	case 0x6A:
3234 		ext(output, "p|freezeUnfreeze");
3235 		break;
3236 	case 0x6B:
3237 		ext(output, "x" "cursorCommand\0"
3238 				"\x13z|setCursorImg,"
3239 				"\x14z|setCursorImg,"
3240 				"\x3Czp|setCursorImgWithPal,"
3241 				"\x90|cursorOn,"
3242 				"\x91|cursorOff,"
3243 				"\x92|userPutOn,"
3244 				"\x93|userPutOff,"
3245 				"\x94|softCursorOn,"
3246 				"\x95|softCursorOff,"
3247 				"\x96|softUserputOn,"
3248 				"\x97|softUserputOff,"
3249 				"\x99z|setCursorImg,"
3250 				"\x9App|setCursorHotspot,"
3251 				"\x9Cp|initCharset,"
3252 				"\x9Dl|charsetColors,"
3253 				"\xD6p|makeCursorColorTransparent");
3254 		break;
3255 	case 0x6C:
3256 		ext(output, "|breakHere");
3257 		break;
3258 	case 0x6D:
3259 		ext(output, "rlp|ifClassOfIs");
3260 		break;
3261 	case 0x6E:
3262 		ext(output, "lp|setClass");
3263 		break;
3264 	case 0x6F:
3265 		ext(output, "rp|getState");
3266 		break;
3267 	case 0x70:
3268 		ext(output, "pp|setState");
3269 		break;
3270 	case 0x71:
3271 		ext(output, "pp|setOwner");
3272 		break;
3273 	case 0x72:
3274 		ext(output, "rp|getOwner");
3275 		break;
3276 	case 0x73:
3277 		jump(output);
3278 		break;
3279 	case 0x74:
3280 		ext(output, "x" "soundOps\0"
3281 				"\x9|setSoftSound,"
3282 				"\x17ppp|setSoundVar,"
3283 				"\x19pp|setVolume,"
3284 				"\x38|setQuickStart,"
3285 				"\xA4|setAppend,"
3286 				"\xDE|dummy,"
3287 				"\xE0p|setFrequency,"
3288 				"\xE6p|setChannel,"
3289 				"\xE7p|setOffset,"
3290 				"\xE8p|setSoundId,"
3291 				"\xF5|setLoop,"
3292 				"\xFF|start");
3293 		break;
3294 	case 0x75:
3295 		ext(output, "p|stopSound");
3296 		break;
3297 	case 0x76:
3298 		ext(output, "p|startMusic");
3299 		break;
3300 	case 0x77:
3301 		ext(output, "p|stopObjectScript");
3302 		break;
3303 	case 0x78:
3304 		ext(output, "p|panCameraTo");
3305 		break;
3306 	case 0x79:
3307 		ext(output, "p|actorFollowCamera");
3308 		break;
3309 	case 0x7A:
3310 		ext(output, "p|setCameraAt");
3311 		break;
3312 	case 0x7B:
3313 		ext(output, "p|loadRoom");
3314 		break;
3315 	case 0x7C:
3316 		ext(output, "p|stopScript");
3317 		break;
3318 	case 0x7D:
3319 		ext(output, "ppp|walkActorToObj");
3320 		break;
3321 	case 0x7E:
3322 		ext(output, "ppp|walkActorTo");
3323 		break;
3324 	case 0x7F:
3325 		ext(output, "pppp|putActorInXY");
3326 		break;
3327 	case 0x80:
3328 		ext(output, "zp|putActorAtObject");
3329 		break;
3330 	case 0x81:
3331 		ext(output, "pp|faceActor");
3332 		break;
3333 	case 0x82:
3334 		ext(output, "pp|animateActor");
3335 		break;
3336 	case 0x83:
3337 		ext(output, "pppp|doSentence");
3338 		break;
3339 	case 0x84:
3340 		ext(output, "z|pickupObject");
3341 		break;
3342 	case 0x85:
3343 		ext(output, "ppz|loadRoomWithEgo");
3344 		break;
3345 	case 0x87:
3346 		ext(output, "rp|getRandomNumber");
3347 		break;
3348 	case 0x88:
3349 		ext(output, "rpp|getRandomNumberRange");
3350 		break;
3351 	case 0x8A:
3352 		ext(output, "rp|getActorMoving");
3353 		break;
3354 	case 0x8B:
3355 		ext(output, "rp|isScriptRunning");
3356 		break;
3357 	case 0x8C:
3358 		ext(output, "rp|getActorRoom");
3359 		break;
3360 	case 0x8D:
3361 		ext(output, "rp|getObjectX");
3362 		break;
3363 	case 0x8E:
3364 		ext(output, "rp|getObjectY");
3365 		break;
3366 	case 0x8F:
3367 		ext(output, "rp|getObjectDir");
3368 		break;
3369 	case 0x90:
3370 		ext(output, "rp|getActorWalkBox");
3371 		break;
3372 	case 0x91:
3373 		ext(output, "rp|getActorCostume");
3374 		break;
3375 	case 0x92:
3376 		ext(output, "rpp|findInventory");
3377 		break;
3378 	case 0x93:
3379 		ext(output, "rp|getInventoryCount");
3380 		break;
3381 	case 0x94:
3382 		if (g_options.heVersion >= 90) {
3383 			ext(output, "rx" "getPaletteData\0"
3384 					"\x2Dpppppp|getSimilarColor,"
3385 					"\x34ppp|getColorCompontent,"
3386 					"\x42pp|getColor,"
3387 					"\x84pp|get16BitColorComponent,"
3388 					"\xD9ppp|get16BitColor");
3389 		} else {
3390 			ext(output, "rpp|getVerbFromXY");
3391 		}
3392 		break;
3393 	case 0x95:
3394 		ext(output, "|beginOverride");
3395 		break;
3396 	case 0x96:
3397 		ext(output, "|endOverride");
3398 		break;
3399 	case 0x97:
3400 		ext(output, "ps|setObjectName");
3401 		break;
3402 	case 0x98:
3403 		ext(output, "rp|isSoundRunning");
3404 		break;
3405 	case 0x99:
3406 		ext(output, "pl|setBoxFlags");
3407 		break;
3408 	case 0x9B:
3409 		ext(output, "x" "resourceRoutines\0"
3410 				"\x64p|loadScript,"
3411 				"\x65p|loadSound,"
3412 				"\x66p|loadCostume,"
3413 				"\x67p|loadRoom,"
3414 				"\x68p|nukeScript,"
3415 				"\x69p|nukeSound,"
3416 				"\x6Ap|nukeCostume,"
3417 				"\x6Bp|nukeRoom,"
3418 				"\x6Cp|lockScript,"
3419 				"\x6Dp|lockSound,"
3420 				"\x6Ep|lockCostume,"
3421 				"\x6Fp|lockRoom,"
3422 				"\x70p|unlockScript,"
3423 				"\x71p|unlockSound,"
3424 				"\x72p|unlockCostume,"
3425 				"\x73p|unlockRoom,"
3426 				"\x74|clearHeap,"
3427 				"\x75p|loadCharset,"
3428 				"\x76p|nukeCharset,"
3429 				"\x77z|loadFlObject,"
3430 				"\x78p|queueloadScript,"
3431 				"\x79p|queueloadSound,"
3432 				"\x7Ap|queueloadCostume,"
3433 				"\x7Bp|queueloadRoomImage,"
3434 				"\x9fp|unlockImage,"
3435 				"\xc0p|nukeImage,"
3436 				"\xc9p|loadImage,"
3437 				"\xcap|lockImage,"
3438 				"\xcbp|queueloadImage,"
3439 				"\xe9p|lockFlObject,"
3440 				"\xebp|unlockFlObject,"
3441 				"\xef|dummy");
3442 		break;
3443 	case 0x9C:
3444 		ext(output, "x" "roomOps\0"
3445 				"\xACpp|roomScroll,"
3446 				"\xAEpp|setScreen,"
3447 				"\xAFpppp|setPalColor,"
3448 				"\xB0|shakeOn,"
3449 				"\xB1|shakeOff,"
3450 				"\xB3ppp|darkenPalette,"
3451 				"\xB4pp|saveLoadRoom,"
3452 				"\xB5p|screenEffect,"
3453 				"\xB6ppppp|darkenPalette,"
3454 				"\xB7ppppp|setupShadowPalette,"
3455 				"\xBApppp|palManipulate,"
3456 				"\xBBpp|colorCycleDelay,"
3457 				"\xD5p|setPalette,"
3458 				"\xDCpp|copyPalColor,"
3459 				"\xDDhp|saveOrLoad,"
3460 				"\xEApp|swapObjects,"
3461 				"\xECpp|setRoomPalette");
3462 		break;
3463 	case 0x9D:
3464 		ext(output, "x" "actorOps\0"
3465 				"\x15l|setUserConditions,"
3466 				"\x18p|setTalkCondition,"
3467 				"\x2Bp|layer,"
3468 				"\xC5p|setCurActor,"
3469 				"\x40pppp|setClipRect,"
3470 				"\x41pp|putActor,"
3471 				"\x43pppp|setActorClipRect,"
3472 				"\x44p|setHEFlag,"
3473 				"\x4Cp|setCostume,"
3474 				"\x4Dpp|setWalkSpeed,"
3475 				"\x4El|setSound,"
3476 				"\x4Fp|setWalkFrame,"
3477 				"\x50pp|setTalkFrame,"
3478 				"\x51p|setStandFrame,"
3479 				"\x52ppp|actorSet:82:??,"
3480 				"\x53|init,"
3481 				"\x54p|setElevation,"
3482 				"\x55|setDefAnim,"
3483 				"\x56pp|setPalette,"
3484 				"\x57p|setTalkColor,"
3485 				"\x58h|setName,"
3486 				"\x59p|setInitFrame,"
3487 				"\x5Bp|setWidth,"
3488 				"\x5Cp|setScale,"
3489 				"\x5D|setNeverZClip,"
3490 				"\x5Ep|setAlwayZClip,"
3491 				"\x5F|setIgnoreBoxes,"
3492 				"\x60|setFollowBoxes,"
3493 				"\x61p|setAnimSpeed,"
3494 				"\x62p|setShadowMode,"
3495 				"\x63pp|setTalkPos,"
3496 				"\x8Bpp|case139,"
3497 				"\x9Cp|charset,"
3498 				"\xAFp|setPaletteNum,"
3499 				"\xC6pp|setAnimVar,"
3500 				"\xD7|setIgnoreTurnsOn,"
3501 				"\xD8|setIgnoreTurnsOff,"
3502 				"\xD9|initLittle,"
3503 				"\xDA|drawToBackBuf,"
3504 				"\xE1hp|setTalkieSlot");
3505 		break;
3506 	case 0x9E:
3507 		if (g_options.heVersion >= 90) {
3508 			ext(output, "x" "paletteOps\0"
3509 					"\x39p|setPaletteNum,"
3510 					"\x3Fpp|setPaletteFromImage,"
3511 					"\x42ppppp|setPaletteColor,"
3512 					"\x46ppp|copyPaletteColor,"
3513 					"\x4Cp|setPaletteFromCostume,"
3514 					"\x56p|copyPalette,"
3515 					"\xAFpp|setPaletteFromRoom,"
3516 					"\xD9|restorePalette,"
3517 					"\xFF|resetPaletteNum");
3518 		} else {
3519 			ext(output, "x" "verbOps\0"
3520 					"\xC4p|setCurVerb,"
3521 					"\x7Cp|loadImg,"
3522 					"\x7Dh|loadString,"
3523 					"\x7Ep|setColor,"
3524 					"\x7Fp|setHiColor,"
3525 					"\x80pp|setXY,"
3526 					"\x81|setOn,"
3527 					"\x82|setOff,"
3528 					"\x83p|kill,"
3529 					"\x84|init,"
3530 					"\x85p|setDimColor,"
3531 					"\x86|setDimmed,"
3532 					"\x87p|setKey,"
3533 					"\x88|setCenter,"
3534 					"\x89p|setToString,"
3535 					"\x8Bpp|setToObject,"
3536 					"\x8Cp|setBkColor,"
3537 					"\xFF|redraw");
3538 		}
3539 		break;
3540 	case 0x9F:
3541 		ext(output, "rpp|getActorFromXY");
3542 		break;
3543 	case 0xA0:
3544 		ext(output, "rpp|findObject");
3545 		break;
3546 	case 0xA1:
3547 		ext(output, "lp|pseudoRoom");
3548 		break;
3549 	case 0xA2:
3550 		ext(output, "rp|getActorElevation");
3551 		break;
3552 	case 0xA3:
3553 		ext(output, "rpp|getVerbEntrypoint");
3554 		break;
3555 	case 0xA4:
3556 		switch (get_byte()) {
3557 		case 7:
3558 			se_a = se_get_string_he();
3559 			writeArray(output, get_word(), NULL, se_a, se_a);
3560 			break;
3561 		case 126:
3562 			// TODO: Add support for writeListIntoArray
3563 			ext(output, "lppppv|writeListIntoArray");
3564 			break;
3565 		case 127:
3566 			// TODO: Add support for copyArray
3567 			ext(output, "ppppvppppv|copyArray");
3568 			break;
3569 		case 128:
3570 			// TODO: Add support for writeRangeIntoArray
3571 			ext(output, "ppppppv|writeRangeIntoArray");
3572 			break;
3573 		case 138:
3574 			// TODO: Add support for math operations
3575 			ext(output, "pppppppppppppvvv|mathOpsInArray");
3576 			break;
3577 		case 194:
3578 			se_get_list();
3579 			pop();
3580 			se_a = se_get_string_he();
3581 			writeArray(output, get_word(), NULL, se_a, se_a);
3582 			break;
3583 		case 208:
3584 			se_a = pop();
3585 			se_b = se_get_list();
3586 			writeArray(output, get_word(), NULL, se_a, se_b);
3587 			break;
3588 		case 212:
3589 			se_b = se_get_list();
3590 			se_a = pop();
3591 			writeArray(output, get_word(), NULL, se_a, se_b);
3592 			break;
3593 		}
3594 		break;
3595 	case 0xA5:
3596 		if (g_options.heVersion >= 99) {
3597 			ext(output, "rx" "fontUnk\0"
3598 					"\x2App|case42,"
3599 					"\x39|case57");
3600 		} else if (g_options.heVersion >= 80) {
3601 			invalidop(NULL, code);
3602 		} else {
3603 			ext(output, "x" "saveRestoreVerbs\0"
3604 					"\x8Dppp|saveVerbs,"
3605 					"\x8Eppp|restoreVerbs,"
3606 					"\x8Fppp|deleteVerbs");
3607 		}
3608 		break;
3609 	case 0xA6:
3610 		ext(output, "ppppp|drawBox");
3611 		break;
3612 	case 0xA8:
3613 		ext(output, "rp|getActorWidth");
3614 		break;
3615 	case 0xA9:
3616 		ext(output, "x" "wait\0"
3617 				"\xA8pj|waitForActor,"
3618 				"\xA9|waitForMessage,"
3619 				"\xAA|waitForCamera,"
3620 				"\xAB|waitForSentence");
3621 		break;
3622 	case 0xAA:
3623 		ext(output, "rp|getActorScaleX");
3624 		break;
3625 	case 0xAB:
3626 		if (g_options.heVersion >= 90) {
3627 			ext(output, "rp|getActorAnimProgress");
3628 		} else {
3629 			ext(output, "rp|getActorAnimCounter1");
3630 		}
3631 		break;
3632 	case 0xAC: // HE80+
3633 		ext(output, "pp|drawWizPolygon");
3634 		break;
3635 	case 0xAD:
3636 		ext(output, "rlp|isAnyOf");
3637 		break;
3638 	case 0xAE:
3639 		ext(output, "x" "systemOps\0"
3640 				 "\x16|clearDrawQueue,"
3641 				 "\x1A|copyVirtBuf,"
3642 				 "\x9E|restart,"
3643 				 "\xA0|confirmShutDown,"
3644 				 "\xF4|shutDown,"
3645 				 "\xFB|startExec,"
3646 				 "\xFC|startGame");
3647 		break;
3648 	case 0xAF:
3649 		ext(output, "rpp|isActorInBox");
3650 		break;
3651 	case 0xB0:
3652 		ext(output, "p|delay");
3653 		break;
3654 	case 0xB1:
3655 		ext(output, "p|delaySeconds");
3656 		break;
3657 	case 0xB2:
3658 		ext(output, "p|delayMinutes");
3659 		break;
3660 	case 0xB3:
3661 		ext(output, "|stopSentence");
3662 		break;
3663 	case 0xB4:
3664 		PRINT_V7HE("printLine");
3665 		break;
3666 	case 0xB5:
3667 		PRINT_V7HE("printCursor");
3668 		break;
3669 	case 0xB6:
3670 		PRINT_V7HE("printDebug");
3671 		break;
3672 	case 0xB7:
3673 		PRINT_V7HE("printSystem");
3674 		break;
3675 	case 0xB8:
3676 		// This is *almost* identical to the other print opcodes, only the 'begine' subop differs
3677 		ext(output, "x" "printActor\0"
3678 				"\x41pp|XY,"
3679 				"\x42p|color,"
3680 				"\x43p|right,"
3681 				"\x45|center,"
3682 				"\x47|left,"
3683 				"\x48|overhead,"
3684 				"\x4A|mumble,"
3685 				"\x4Bs|msg,"
3686 				"\xE1p|getText,"
3687 				"\xF9l|colors,"
3688 				"\xFEp|begin,"
3689 				"\xFF|end");
3690 		break;
3691 	case 0xB9:
3692 		PRINT_V7HE("printEgo");
3693 		break;
3694 	case 0xBA:
3695 		ext(output, "ps|talkActor");
3696 		break;
3697 	case 0xBB:
3698 		ext(output, "s|talkEgo");
3699 		break;
3700 	case 0xBC:
3701 		ext(output, "x" "dimArray\0"
3702 				"\x2pv|bit,"
3703 				"\x3pv|nibble,"
3704 				"\x4pv|byte,"
3705 				"\x5pv|int,"
3706 				"\x6pv|dword,"
3707 				"\x7pv|string,"
3708 				"\xCCv|nukeArray");
3709 		break;
3710 	case 0xBD:
3711 		ext(output, "|stopObjectCode");
3712 		break;
3713 	case 0xBE:
3714 		// TODO: this loads another script which does something like
3715 		// stack altering and then finishes (usually with opcode 0xBD).
3716 		// When stack is changed, further disassembly is wrong.
3717 		// This is widely used in HE games.
3718 		// As there are cases when called script does not alter the
3719 		// stack, it's not correct to use "rlpp|..." here
3720 		ext(output, "lpp|startObjectQuick");
3721 		break;
3722 	case 0xBF:
3723 		ext(output, "lp|startScriptQuick2");
3724 		break;
3725 	case 0xC0:
3726 		ext(output, "x" "dim2dimArray\0"
3727 				"\x2ppv|bit,"
3728 				"\x3ppv|nibble,"
3729 				"\x4ppv|byte,"
3730 				"\x5ppv|int,"
3731 				"\x6ppv|dword,"
3732 				"\x7ppv|string");
3733 		break;
3734 	case 0xC1:
3735 		ext(output, "hp|traceStatus");
3736 		break;
3737 	case 0xC4:
3738 		ext(output, "rp|abs");
3739 		break;
3740 	case 0xC5:
3741 		ext(output, "rpp|getDistObjObj");
3742 		break;
3743 	case 0xC6:
3744 		ext(output, "rppp|getDistObjPt");
3745 		break;
3746 	case 0xC7:
3747 		ext(output, "rpppp|getDistPtPt");
3748 		break;
3749 	case 0xC8:
3750 		ext(output, "ry" "kernelGetFunctions\0"
3751 				"\x1|virtScreenSave"
3752 				);
3753 		break;
3754 	case 0xC9:
3755 		ext(output, "y" "kernelSetFunctions\0"
3756 				"\x1|virtScreenLoad,"
3757 				"\x14|queueAuxBlock,"
3758 				"\x15|pauseDrawObjects,"
3759 				"\x16|resumeDrawObjects,"
3760 				"\x17|clearCharsetMask,"
3761 				"\x18|pauseActors,"
3762 				"\x19|resumActors,"
3763 				"\x1E|actorBottomClipOverride,"
3764 				"\x2A|setWizImageClip,"
3765 				"\x2B|setWizImageClipOff,"
3766 				);
3767 		break;
3768 	case 0xCA:
3769 		ext(output, "p|delayFrames");
3770 		break;
3771 	case 0xCB:
3772 		ext(output, "rlp|pickOneOf");
3773 		break;
3774 	case 0xCC:
3775 		ext(output, "rplp|pickOneOfDefault");
3776 		break;
3777 	case 0xCD:
3778 		ext(output, "pppp|stampObject");
3779 		break;
3780 	case 0xCE:
3781 		ext(output, "pppp|drawWizImage");
3782 		break;
3783 	case 0xCF:
3784 		ext(output, "rh|debugInput");
3785 		break;
3786 	case 0xD0:
3787 		ext(output, "|getDateTime");
3788 		break;
3789 	case 0xD1:
3790 		ext(output, "|stopTalking");
3791 		break;
3792 	case 0xD2:
3793 		ext(output, "rpp|getAnimateVariable");
3794 		break;
3795 	case 0xD4:
3796 		ext(output, "wpp|shuffle");
3797 		break;
3798 	case 0xD5:
3799 		ext(output, "lpi|jumpToScript");
3800 		break;
3801 	case 0xD6:
3802 		se_a = pop();
3803 		se_b = pop();
3804 		push(se_oper(se_b, operBand, se_a));
3805 		break;
3806 	case 0xD7:
3807 		se_a = pop();
3808 		se_b = pop();
3809 		push(se_oper(se_b, operBor, se_a));
3810 		break;
3811 	case 0xD8:
3812 		ext(output, "rp|isRoomScriptRunning");
3813 		break;
3814 	case 0xD9:
3815 		ext(output, "p|closeFile");
3816 		break;
3817 	case 0xDA:
3818 		ext(output, "rph|openFile");
3819 		break;
3820 	case 0xDB:
3821 		ext(output, "rx" "readFile\0"
3822 				"\x4p|readByte,"
3823 				"\x5p|readWord,"
3824 				"\x6p|readDWord,"
3825 				"\x8ppi|readArrayFromFile");
3826 		break;
3827 	case 0xDC:
3828 		ext(output, "x" "writeFile\0"
3829 				"\x4pp|writeByte,"
3830 				"\x5pp|writeWord,"
3831 				"\x6pp|writeDWord,"
3832 				"\x8ppi|writeArrayToFile");
3833 		break;
3834 	case 0xDD:
3835 		ext(output, "rp|findAllObjects");
3836 		break;
3837 	case 0xDE:
3838 		ext(output, "h|deleteFile");
3839 		break;
3840 	case 0xDF:
3841 		ext(output, "hh|renameFile");
3842 		break;
3843 	case 0xE0:
3844 		ext(output, "x" "drawLine\0"
3845 				"\x37pppppp|pixel,"
3846 				"\x3Fpppppp|actor,"
3847 				"\x42pppppp|wizImage");
3848 		break;
3849 	case 0xE1:
3850 		ext(output, "rx" "getPixel\0"
3851 				"\xDApp|background,"
3852 				"\xDBpp|foreground");
3853 		break;
3854 	case 0xE2:
3855 		ext(output, "p|localizeArrayToScript");
3856 		break;
3857 	case 0xE3:
3858 		ext(output, "rlw|pickVarRandom");
3859 		break;
3860 	case 0xE4:
3861 		ext(output, "p|setBotSet");
3862 		break;
3863 	case 0xE9:
3864 		ext(output, "ppp|seekFilePos");
3865 		break;
3866 	case 0xEA:
3867 		ext(output, "x" "redimArray\0"
3868 				"\x4ppv|byte,"
3869 				"\x5ppv|int,"
3870 				"\x6ppv|dword");
3871 		break;
3872 	case 0xEB:
3873 		ext(output, "rp|readFilePos");
3874 		break;
3875 	case 0xEC:
3876 		ext(output, "rp|copyString");
3877 		break;
3878 	case 0xED:
3879 		ext(output, "rppp|getStringWidth");
3880 		break;
3881 	case 0xEE:
3882 		ext(output, "rp|getStringLen");
3883 		break;
3884 	case 0xEF:
3885 		ext(output, "rppp|appendString");
3886 		break;
3887 	case 0xF0:
3888 		ext(output, "rpp|concatString");
3889 		break;
3890 	case 0xF1:
3891 		ext(output, "rpp|compareString");
3892 		break;
3893 	case 0xF2:
3894 		ext(output, "rx" "isResourceLoaded\0"
3895 				"\x12p|image,"
3896 				"\xE2p|room,"
3897 				"\xE3p|costume,"
3898 				"\xE4p|sound,"
3899 				"\xE5p|script");
3900 		break;
3901 	case 0xF3:
3902 		ext(output, "rx" "readINI\0"
3903 				"\x06h|number,"
3904 				"\x07h|string");
3905 		break;
3906 	case 0xF4:
3907 		ext(output, "x" "writeINI\0"
3908 				"\x06ph|number,"
3909 				"\x07hh|string");
3910 		break;
3911 	case 0xF5:
3912 		ext(output, "rppp|getStringLenForWidth");
3913 		break;
3914 	case 0xF6:
3915 		ext(output, "rpppp|getCharIndexInString");
3916 		break;
3917 	case 0xF8:
3918 		if (g_options.heVersion >= 73) {
3919 			ext(output, "rx" "getResourceSize\0"
3920 					"\xDp|sound,"
3921 					"\xEp|roomImage,"
3922 					"\xFp|image,"
3923 					"\x10p|costume,"
3924 					"\x11p|script");
3925 		} else {
3926 			ext(output, "rp|getSoundResourceSize");
3927 		}
3928 		break;
3929 	case 0xF9:
3930 		ext(output, "h|createDirectory");
3931 		break;
3932 	case 0xFA:
3933 		ext(output, "x" "setSystemMessage\0"
3934 				"\xF0h|case240,"
3935 				"\xF1h|versionMsg,"
3936 				"\xF2h|case242,"
3937 				"\xF3h|titleMsg");
3938 		break;
3939 	case 0xFB:
3940 		ext(output, "x" "polygonOps\0"
3941 				"\xF6ppppppppp|polygonStore,"
3942 				"\xF7pp|polygonErase,"
3943 				"\xF8ppppppppp|polygonStore,"
3944 				);
3945 		break;
3946 	case 0xFC:
3947 			ext(output, "rpp|polygonHit");
3948 		break;
3949 
3950 	default:
3951 		invalidop(NULL, code);
3952 		break;
3953 	}
3954 }
3955 
3956 #define PRINT_V8(name)            \
3957 	do {                          \
3958 		ext(output,               \
3959 				"x" name "\0"     \
3960 				"\xC8|baseop,"    \
3961 				"\xC9|end,"       \
3962 				"\xCApp|XY,"      \
3963 				"\xCBp|color,"    \
3964 				"\xCC|center,"    \
3965 				"\xCDp|charset,"  \
3966 				"\xCE|left,"      \
3967 				"\xCF|overhead,"  \
3968 				"\xD0|mumble,"    \
3969 				"\xD1s|msg,"      \
3970 				"\xD2|wrap"       \
3971 				);                \
3972 	} while(0)
3973 
3974 
next_line_V8(char * output)3975 void next_line_V8(char *output) {
3976 	byte code = get_byte();
3977 	StackEnt *se_a, *se_b;
3978 
3979 	switch (code) {
3980 	case 0x1:
3981 		push(se_int(get_word()));
3982 		break;
3983 	case 0x2:
3984 		push(se_var(get_word()));
3985 		break;
3986 	case 0x3:
3987 		push(se_array(get_word(), NULL, pop()));
3988 		break;
3989 	case 0x4:
3990 		se_a = pop();
3991 		push(se_array(get_word(), pop(), se_a));
3992 		break;
3993 	case 0x5:
3994 		se_a = dup(output, pop());
3995 		push(se_a);
3996 		push(se_a);
3997 		break;
3998 	case 0x6:
3999 		kill(output, pop());
4000 		break;
4001 	case 0x7:
4002 		push(se_oper(pop(), isZero));
4003 		break;
4004 	case 0x8:
4005 	case 0x9:
4006 	case 0xA:
4007 	case 0xB:
4008 	case 0xC:
4009 	case 0xD:
4010 	case 0xE:
4011 	case 0xF:
4012 	case 0x10:
4013 	case 0x11:
4014 	case 0x12:
4015 	case 0x13:
4016 	case 0x14:
4017 	case 0x15:
4018 	case 0x16:
4019 		se_a = pop();
4020 		se_b = pop();
4021 		push(se_oper(se_b, (code - 0x8) + isEqual, se_a));
4022 		break;
4023 
4024 	case 0x64:
4025 		jumpif(output, pop(), true);
4026 		break;
4027 	case 0x65:
4028 		jumpif(output, pop(), false);
4029 		break;
4030 	case 0x66:
4031 		jump(output);
4032 		break;
4033 	case 0x67:
4034 		ext(output, "|breakHere");
4035 		break;
4036 	case 0x68:
4037 		ext(output, "p|delayFrames");
4038 		break;
4039 	case 0x69:
4040 		ext(output, "x" "wait\0"
4041 				"\x1Epj|waitForActor,"
4042 				"\x1F|waitForMessage,"
4043 				"\x20|waitForCamera,"
4044 				"\x21|waitForSentence,"
4045 				"\x22pj|waitUntilActorDrawn,"
4046 				"\x23pj|waitUntilActorTurned,"
4047 				);
4048 		break;
4049 	case 0x6A:
4050 		ext(output, "p|delay");
4051 		break;
4052 	case 0x6B:
4053 		ext(output, "p|delaySeconds");
4054 		break;
4055 	case 0x6C:
4056 		ext(output, "p|delayMinutes");
4057 		break;
4058 	case 0x6D:
4059 		writeVar(output, get_word(), pop());
4060 		break;
4061 	case 0x6E:
4062 		addVar(output, get_word(), +1);
4063 		break;
4064 	case 0x6F:
4065 		addVar(output, get_word(), -1);
4066 		break;
4067 	case 0x70:
4068 		// FIXME - is this correct?!? Also, make the display nicer...
4069 		ext(output, "x" "dimArray\0"
4070 				"\x0Apw|dim-scummvar,"
4071 				"\x0Bpw|dim-string,"
4072 				"\xCAw|undim"
4073 				);
4074 		break;
4075 	case 0x71:
4076 		se_a = pop();
4077 		writeArray(output, get_word(), NULL, pop(), se_a);
4078 		break;
4079 
4080 	case 0x74:
4081 		// FIXME - is this correct?!? Also, make the display nicer...
4082 		ext(output, "x" "dim2dimArray\0"
4083 				"\x0Appw|dim2-scummvar,"
4084 				"\x0Bppw|dim2-string,"
4085 				"\xCAw|undim2"
4086 				);
4087 		break;
4088 	case 0x75:
4089 		se_a = pop();
4090 		se_b = pop();
4091 		writeArray(output, get_word(), pop(), se_b, se_a);
4092 		break;
4093 	case 0x76:
4094 		switch (get_byte()) {
4095 		case 0x14:{
4096 			int array = get_word();
4097 			writeArray(output, array, NULL, pop(), se_get_string());
4098 			}
4099 			break;
4100 		case 0x15:
4101 			se_a = pop();
4102 			se_b = se_get_list();
4103 			writeArray(output, get_word(), NULL, se_a, se_b);
4104 			break;
4105 		case 0x16:
4106 			se_a = pop();
4107 			se_b = se_get_list();
4108 			writeArray(output, get_word(), pop(), se_a, se_b);
4109 			break;
4110 		}
4111 		break;
4112 
4113 	case 0x79:
4114 		ext(output, "lpp|startScript");
4115 		break;
4116 	case 0x7A:
4117 		ext(output, "lp|startScriptQuick");
4118 		break;
4119 	case 0x7B:
4120 		ext(output, "|stopObjectCode");
4121 		break;
4122 	case 0x7C:
4123 		ext(output, "p|stopScript");
4124 		break;
4125 	case 0x7D:
4126 		ext(output, "lpp|jumpToScript");
4127 		break;
4128 	case 0x7E:
4129 		ext(output, "p|return");
4130 		break;
4131 	case 0x7F:
4132 		ext(output, "lppp|startObject");
4133 		break;
4134 
4135 	case 0x81:
4136 		ext(output, "l|beginCutscene");
4137 		break;
4138 	case 0x82:
4139 		ext(output, "|endCutscene");
4140 		break;
4141 	case 0x83:
4142 		ext(output, "p|freezeUnfreeze");
4143 		break;
4144 	case 0x84:
4145 		ext(output, "|beginOverride");
4146 		break;
4147 	case 0x85:
4148 		ext(output, "|endOverride");
4149 		break;
4150 	case 0x86:
4151 		ext(output, "|stopSentence");
4152 		break;
4153 	case 0x87:
4154 		ext(output, "p|debug");
4155 		break;
4156 	case 0x89:
4157 		ext(output, "lp|setClass");
4158 		break;
4159 	case 0x8A:
4160 		ext(output, "pp|setState");
4161 		break;
4162 	case 0x8B:
4163 		ext(output, "pp|setOwner");
4164 		break;
4165 	case 0x8C:
4166 		ext(output, "pp|panCameraTo");
4167 		break;
4168 	case 0x8D:
4169 		ext(output, "p|actorFollowCamera");
4170 		break;
4171 	case 0x8E:
4172 		ext(output, "pp|setCameraAt");
4173 		break;
4174 	case 0x8F:
4175 		ext(output,
4176 				"x" "printActor\0"
4177 				"\xC8p|baseop,"
4178 				"\xC9|end,"
4179 				"\xCApp|XY,"
4180 				"\xCBp|color,"
4181 				"\xCC|center,"
4182 				"\xCDp|charset,"
4183 				"\xCE|left,"
4184 				"\xCF|overhead,"
4185 				"\xD0|mumble,"
4186 				"\xD1s|msg,"
4187 				"\xD2|wrap"
4188 				);
4189 		break;
4190 	case 0x90:
4191 		PRINT_V8("printEgo");
4192 		break;
4193 	case 0x91:
4194 		ext(output, "ps|talkActor");
4195 		break;
4196 	case 0x92:
4197 		ext(output, "s|talkEgo");
4198 		break;
4199 	case 0x93:
4200 		PRINT_V8("printLine");
4201 		break;
4202 	case 0x94:
4203 		PRINT_V8("printCursor");
4204 		break;
4205 	case 0x95:
4206 		PRINT_V8("printDebug");
4207 		break;
4208 	case 0x96:
4209 		PRINT_V8("printSystem");
4210 		break;
4211 	case 0x97:
4212 		PRINT_V8("blastText");
4213 		break;
4214 	case 0x98:
4215 		ext(output, "pppp|drawObject");
4216 		break;
4217 
4218 	case 0x9C:
4219 		ext(output, "x" "cursorCommand\0"
4220 				"\xDC|cursorOn,"
4221 				"\xDD|cursorOff,"
4222 				"\xDE|userPutOn,"
4223 				"\xDF|userPutOff,"
4224 				"\xE0|softCursorOn,"
4225 				"\xE1|softCursorOff,"
4226 				"\xE2|softUserputOn,"
4227 				"\xE3|softUserputOff,"
4228 				"\xE4pp|setCursorImg,"
4229 				"\xE5pp|setCursorHotspot,"
4230 				"\xE6p|makeCursorColorTransparent,"
4231 				"\xE7p|initCharset,"
4232 				"\xE8l|charsetColors,"
4233 				"\xE9pp|setCursorPosition");
4234 		break;
4235 	case 0x9D:
4236 		ext(output, "p|loadRoom");
4237 		break;
4238 	case 0x9E:
4239 		ext(output, "ppz|loadRoomWithEgo");
4240 		break;
4241 	case 0x9F:
4242 		ext(output, "ppp|walkActorToObj");
4243 		break;
4244 	case 0xA0:
4245 		ext(output, "ppp|walkActorTo");
4246 		break;
4247 	case 0xA1:
4248 		ext(output, "pppp|putActorAtXY");
4249 		break;
4250 	case 0xA2:
4251 		ext(output, "zp|putActorAtObject");
4252 		break;
4253 	case 0xA3:
4254 		ext(output, "pp|faceActor");
4255 		break;
4256 	case 0xA4:
4257 		ext(output, "pp|animateActor");
4258 		break;
4259 	case 0xA5:
4260 		ext(output, "ppp|doSentence");
4261 		break;
4262 	case 0xA6:
4263 		ext(output, "z|pickupObject");
4264 		break;
4265 	case 0xA7:
4266 		ext(output, "pl|setBoxFlags");
4267 		break;
4268 	case 0xA8:
4269 		ext(output, "|createBoxMatrix");
4270 		break;
4271 
4272 	case 0xAA:
4273 		ext(output, "x" "resourceRoutines\0"
4274 				"\x3Cp|loadCharset,"
4275 				"\x3Dp|loadCostume,"
4276 				"\x3Ep|loadObject,"
4277 				"\x3Fp|loadRoom,"
4278 				"\x40p|loadScript,"
4279 				"\x41p|loadSound,"
4280 				"\x42p|lockCostume,"
4281 				"\x43p|lockRoom,"
4282 				"\x44p|lockScript,"
4283 				"\x45p|lockSound,"
4284 				"\x46p|unlockCostume,"
4285 				"\x47p|unlockRoom,"
4286 				"\x48p|unlockScript,"
4287 				"\x49p|unlockSound,"
4288 				"\x4Ap|nukeCostume,"
4289 				"\x4Bp|nukeRoom,"
4290 				"\x4Cp|nukeScript,"
4291 				"\x4Dp|nukeSound"
4292 				);
4293 		break;
4294 	case 0xAB:
4295 		ext(output, "x" "roomOps\0"
4296 				"\x52pppp|setRoomPalette,"
4297 				"\x55ppp|setRoomIntensity,"
4298 				"\x57p|fade,"
4299 				"\x58ppppp|setRoomRBGIntensity,"
4300 				"\x59pppp|transformRoom,"
4301 				"\x5App|colorCycleDelay,"
4302 				"\x5Bpp|copyPalette,"
4303 				"\x5Cp|newPalette,"
4304 				"\x5D|saveGame,"
4305 				"\x5Ep|LoadGame,"
4306 				"\x5Fppppp|setRoomSaturation"
4307 				);
4308 		break;
4309 	case 0xAC:
4310 		// Note: these are guesses and may partially be wrong
4311 		ext(output, "x" "actorOps\0"
4312 				"\x64p|setActorCostume,"
4313 				"\x65pp|setActorWalkSpeed,"
4314 				"\x67|setActorDefAnim,"
4315 				"\x68p|setActorInitFrame,"
4316 				"\x69pp|setActorTalkFrame,"
4317 				"\x6Ap|setActorWalkFrame,"
4318 				"\x6Bp|setActorStandFrame,"
4319 				"\x6C|setActorAnimSpeed,"
4320 				"\x6D|setActorDefault,"	// = initActorLittle ?
4321 				"\x6Ep|setActorElevation,"
4322 				"\x6Fpp|setActorPalette,"
4323 				"\x70p|setActorTalkColor,"
4324 				"\x71s|setActorName,"
4325 				"\x72p|setActorWidth,"
4326 				"\x73p|setActorScale,"
4327 				"\x74|setActorNeverZClip,"
4328 				"\x75p|setActorAlwayZClip?,"
4329 				"\x76|setActorIgnoreBoxes,"
4330 				"\x77|setActorFollowBoxes,"
4331 				"\x78p|setShadowMode,"
4332 				"\x79pp|setActorTalkPos,"
4333 				"\x7Ap|setCurActor,"
4334 				"\x7Bpp|setActorAnimVar,"
4335 				"\x7C|setActorIgnoreTurnsOn,"
4336 				"\x7D|setActorIgnoreTurnsOff,"
4337 				"\x7E|newActor,"
4338 				"\x7Fp|setActorLayer,"
4339 				"\x80|setActorStanding,"
4340 				"\x81p|setActorDirection,"
4341 				"\x82p|actorTurnToDirection,"
4342 				"\x83p|setActorWalkScript,"
4343 				"\x84p|setTalkScript,"
4344 				"\x85|freezeActor,"
4345 				"\x86|unfreezeActor,"
4346 				"\x87p|setActorVolume,"
4347 				"\x88p|setActorFrequency,"
4348 				"\x89p|setActorPan"
4349 				);
4350 		break;
4351 	case 0xAD:
4352 		ext(output, "x" "cameraOps\0"
4353 				"\x32|freezeCamera,"
4354 				"\x33|unfreezeCamera"
4355 				);
4356 		break;
4357 	case 0xAE:
4358 		ext(output, "x" "verbOps\0"
4359 				"\x96p|verbInit,"
4360 				"\x97|verbNew,"
4361 				"\x98|verbDelete,"
4362 				"\x99s|verbLoadString,"
4363 				"\x9App|verbSetXY,"
4364 				"\x9B|verbOn,"
4365 				"\x9C|verbOff,"
4366 				"\x9Dp|verbSetColor,"
4367 				"\x9Ep|verbSetHiColor,"
4368 
4369 				"\xA0p|verbSetDimColor,"
4370 				"\xA1|verbSetDim,"
4371 				"\xA2p|verbSetKey,"
4372 				"\xA3p|verbLoadImg,"
4373 				"\xA4p|verbSetToString,"
4374 				"\xA5|verbSetCenter,"
4375 				"\xA6p|verbSetCharset,"
4376 				"\xA7p|verbSetLineSpacing"
4377 				);
4378 		break;
4379 	case 0xAF:
4380 		ext(output, "p|startSound");
4381 		break;
4382 
4383 	case 0xB1:
4384 		ext(output, "p|stopSound");
4385 		break;
4386 	case 0xB2:
4387 		ext(output, "l|soundKludge");
4388 		break;
4389 	case 0xB3:
4390 		ext(output, "x" "systemOps\0"
4391 				"\x28|restart,"
4392 				"\x29|quit");
4393 		break;
4394 	case 0xB4:
4395 		ext(output, "x" "saveRestoreVerbs\0"
4396 				"\xB4ppp|saveVerbs,"
4397 				"\xB5ppp|restoreVerbs,"
4398 				"\xB6ppp|deleteVerbs");
4399 		break;
4400 	case 0xB5:
4401 		ext(output, "ps|setObjectName");
4402 		break;
4403 	case 0xB6:
4404 		ext(output, "|getDateTime");
4405 		break;
4406 	case 0xB7:
4407 		ext(output, "ppppp|drawBox");
4408 		break;
4409 
4410 	case 0xB9:
4411 		ext(output, "s|startVideo");
4412 		break;
4413 	case 0xBA:
4414 		ext(output, "y" "kernelSetFunctions\0"
4415 				"\xB|lockObject,"
4416 				"\xC|unlockObject,"
4417 				"\xD|remapCostume,"
4418 				"\xE|remapCostumeInsert,"
4419 				"\xF|setVideoFrameRate,"
4420 
4421 				"\x14|setBoxScale,"
4422 				"\x15|setScaleSlot,"
4423 				"\x16|setBannerColors,"
4424 				"\x17|setActorChoreLimbFrame,"
4425 				"\x18|clearTextQueue,"
4426 				"\x19|saveGameWrite,"
4427 				"\x1A|saveGameRead,"
4428 				"\x1B|saveGameReadName,"
4429 				"\x1C|saveGameStampScreenshot,"
4430 				"\x1D|setKeyScript,"
4431 				"\x1E|killAllScriptsExceptCurrent,"
4432 				"\x1F|stopAllVideo,"
4433 				"\x20|writeRegistryValue,"
4434 				"\x21|paletteSetIntensity,"
4435 				"\x22|queryQuit,"
4436 
4437 				"\x6C|buildPaletteShadow,"
4438 				"\x6D|setPaletteShadow,"
4439 
4440 				"\x76|blastShadowObject,"
4441 				"\x77|superBlastObject"
4442 				);
4443 		break;
4444 
4445 	case 0xC8:
4446 		ext(output, "rlp|startScriptQuick2");
4447 		break;
4448 	case 0xC9:
4449 		ext(output, "lppp|startObjectQuick");
4450 		break;
4451 	case 0xCA:
4452 		ext(output, "rlp|pickOneOf");
4453 		break;
4454 	case 0xCB:
4455 		ext(output, "rplp|pickOneOfDefault");
4456 		break;
4457 
4458 	case 0xCD:
4459 		ext(output, "rlp|isAnyOf");
4460 		break;
4461 	case 0xCE:
4462 		ext(output, "rp|getRandomNumber");
4463 		break;
4464 	case 0xCF:
4465 		ext(output, "rpp|getRandomNumberRange");
4466 		break;
4467 	case 0xD0:
4468 		ext(output, "rlp|ifClassOfIs");
4469 		break;
4470 	case 0xD1:
4471 		ext(output, "rp|getState");
4472 		break;
4473 	case 0xD2:
4474 		ext(output, "rp|getOwner");
4475 		break;
4476 	case 0xD3:
4477 		ext(output, "rp|isScriptRunning");
4478 		break;
4479 
4480 	case 0xD5:
4481 		ext(output, "rp|isSoundRunning");
4482 		break;
4483 	case 0xD6:
4484 		ext(output, "rp|abs");
4485 		break;
4486 
4487 	case 0xD8:
4488 		ext(output, "ry" "kernelGetFunctions\0"
4489 				"\x73|getWalkBoxAt,"
4490 				"\x74|isPointInBox,"
4491 				"\xCE|getRGBSlot,"
4492 				"\xD3|getKeyState,"
4493 				"\xD7|getBox,"
4494 				"\xD8|findBlastObject,"
4495 				"\xD9|actorHit,"
4496 				"\xDA|lipSyncWidth,"
4497 				"\xDB|lipSyncHeight,"
4498 				"\xDC|actorTalkAnimation,"
4499 				"\xDD|getMasterSFXVol,"
4500 				"\xDE|getMasterVoiceVol,"
4501 				"\xDF|getMasterMusicVol,"
4502 				"\xE0|readRegistryValue,"
4503 				"\xE1|imGetMusicPosition,"
4504 				"\xE2|musicLipSyncWidth,"
4505 				"\xE3|musicLipSyncHeight"
4506 				);
4507 		break;
4508 	case 0xD9:
4509 		ext(output, "rpp|isActorInBox");
4510 		break;
4511 	case 0xDA:
4512 		ext(output, "rpp|getVerbEntrypoint");
4513 		break;
4514 	case 0xDB:
4515 		ext(output, "rpp|getActorFromXY");
4516 		break;
4517 	case 0xDC:
4518 		ext(output, "rpp|findObject");
4519 		break;
4520 	case 0xDD:
4521 		ext(output, "rpp|getVerbFromXY");
4522 		break;
4523 
4524 	case 0xDF:
4525 		ext(output, "rpp|findInventory");
4526 		break;
4527 	case 0xE0:
4528 		ext(output, "rp|getInventoryCount");
4529 		break;
4530 	case 0xE1:
4531 		ext(output, "rpp|getAnimateVariable");
4532 		break;
4533 	case 0xE2:
4534 		ext(output, "rp|getActorRoom");
4535 		break;
4536 	case 0xE3:
4537 		ext(output, "rp|getActorWalkBox");
4538 		break;
4539 	case 0xE4:
4540 		ext(output, "rp|getActorMoving");
4541 		break;
4542 	case 0xE5:
4543 		ext(output, "rp|getActorCostume");
4544 		break;
4545 	case 0xE6:
4546 		ext(output, "rp|getActorScaleX");
4547 		break;
4548 	case 0xE7:
4549 		ext(output, "rp|getActorLayer");
4550 		break;
4551 	case 0xE8:
4552 		ext(output, "rp|getActorElevation");
4553 		break;
4554 	case 0xE9:
4555 		ext(output, "rp|getActorWidth");
4556 		break;
4557 	case 0xEA:
4558 		ext(output, "rp|getObjectDir");
4559 		break;
4560 	case 0xEB:
4561 		ext(output, "rp|getObjectX");
4562 		break;
4563 	case 0xEC:
4564 		ext(output, "rp|getObjectY");
4565 		break;
4566 	case 0xED:
4567 		ext(output, "rp|getActorChore");
4568 		break;
4569 	case 0xEE:
4570 		ext(output, "rpp|getDistObjObj");
4571 		break;
4572 	case 0xEF:
4573 		ext(output, "rpppp|getDistPtPt");
4574 		break;
4575 	case 0xF0:
4576 		ext(output, "rp|getObjectImageX");
4577 		break;
4578 	case 0xF1:
4579 		ext(output, "rp|getObjectImageY");
4580 		break;
4581 	case 0xF2:
4582 		ext(output, "rp|getObjectImageWidth");
4583 		break;
4584 	case 0xF3:
4585 		ext(output, "rp|getObjectImageHeight");
4586 		break;
4587 	case 0xF4:
4588 		ext(output, "rp|getVerbX");
4589 		break;
4590 	case 0xF5:
4591 		ext(output, "rp|getVerbY");
4592 		break;
4593 	case 0xF6:
4594 		ext(output, "rps|stringWidth");
4595 		break;
4596 	case 0xF7:
4597 		ext(output, "rp|getActorZPlane");
4598 		break;
4599 
4600 	default:
4601 		invalidop(NULL, code);
4602 		break;
4603 	}
4604 }
4605 
4606 #define PRINT_V67(name)           \
4607 	do {                          \
4608 		ext(output, "x" name "\0"         \
4609 				"\x41pp|XY,"      \
4610 				"\x42p|color,"    \
4611 				"\x43p|right,"    \
4612 				"\x45|center,"    \
4613 				"\x47|left,"      \
4614 				"\x48|overhead,"  \
4615 				"\x4A|mumble,"    \
4616 				"\x4Bs|msg,"      \
4617 				"\xFE|begin,"     \
4618 				"\xFF|end"        \
4619 				);                \
4620 	} while(0)
4621 
next_line_V67(char * output)4622 void next_line_V67(char *output) {
4623 	byte code = get_byte();
4624 	StackEnt *se_a, *se_b;
4625 
4626 	switch (code) {
4627 	case 0x0:
4628 		push(se_int(get_byte()));
4629 		break;
4630 	case 0x1:
4631 		push(se_int(get_word()));
4632 		break;
4633 	case 0x2:
4634 		push(se_var(get_byte()));
4635 		break;
4636 	case 0x3:
4637 		push(se_var(get_word()));
4638 		break;
4639 	case 0x6:
4640 		push(se_array(get_byte(), NULL, pop()));
4641 		break;
4642 	case 0x7:
4643 		push(se_array(get_word(), NULL, pop()));
4644 		break;
4645 	case 0xA:
4646 		se_a = pop();
4647 		push(se_array(get_byte(), pop(), se_a));
4648 		break;
4649 	case 0xB:
4650 		se_a = pop();
4651 		push(se_array(get_word(), pop(), se_a));
4652 		break;
4653 	case 0xC:
4654 		se_a = dup(output, pop());
4655 		push(se_a);
4656 		push(se_a);
4657 		break;
4658 	case 0xD:
4659 		push(se_oper(pop(), isZero));
4660 		break;
4661 	case 0xE:
4662 	case 0xF:
4663 	case 0x10:
4664 	case 0x11:
4665 	case 0x12:
4666 	case 0x13:
4667 	case 0x14:
4668 	case 0x15:
4669 	case 0x16:
4670 	case 0x17:
4671 	case 0x18:
4672 	case 0x19:
4673 		se_a = pop();
4674 		se_b = pop();
4675 		push(se_oper(se_b, (code - 0xE) + isEqual, se_a));
4676 		break;
4677 	case 0x1A:
4678 	case 0xA7:
4679 		kill(output, pop());
4680 		break;
4681 	case 0x42:
4682 		writeVar(output, get_byte(), pop());
4683 		break;
4684 	case 0x43:
4685 		writeVar(output, get_word(), pop());
4686 		break;
4687 	case 0x46:
4688 		se_a = pop();
4689 		writeArray(output, get_byte(), NULL, pop(), se_a);
4690 		break;
4691 	case 0x47:
4692 		se_a = pop();
4693 		writeArray(output, get_word(), NULL, pop(), se_a);
4694 		break;
4695 	case 0x4A:
4696 		se_a = pop();
4697 		se_b = pop();
4698 		writeArray(output, get_byte(), pop(), se_b, se_a);
4699 		break;
4700 	case 0x4B:
4701 		se_a = pop();
4702 		se_b = pop();
4703 		writeArray(output, get_word(), pop(), se_b, se_a);
4704 		break;
4705 	case 0x4E:
4706 		addVar(output, get_byte(), 1);
4707 		break;
4708 	case 0x4F:
4709 		addVar(output, get_word(), 1);
4710 		break;
4711 	case 0x52:
4712 		addArray(output, get_byte(), pop(), 1);
4713 		break;
4714 	case 0x53:
4715 		addArray(output, get_word(), pop(), 1);
4716 		break;
4717 	case 0x56:
4718 		addVar(output, get_byte(), -1);
4719 		break;
4720 	case 0x57:
4721 		addVar(output, get_word(), -1);
4722 		break;
4723 	case 0x5A:
4724 		addArray(output, get_byte(), pop(), -1);
4725 		break;
4726 	case 0x5B:
4727 		addArray(output, get_word(), pop(), -1);
4728 		break;
4729 	case 0x5C:
4730 		jumpif(output, pop(), true);
4731 		break;
4732 	case 0x5D:
4733 		jumpif(output, pop(), false);
4734 		break;
4735 	case 0x5E:
4736 		ext(output, "lpp|startScript");
4737 		break;
4738 	case 0x5F:
4739 		ext(output, "lp|startScriptQuick");
4740 		break;
4741 	case 0x60:
4742 		ext(output, "lppp|startObject");
4743 		break;
4744 	case 0x61:
4745 		ext(output, "pp|drawObject");
4746 		break;
4747 	case 0x62:
4748 		ext(output, "ppp|drawObjectAt");
4749 		break;
4750 	case 0x63:
4751 		if (g_options.heVersion)
4752 			invalidop(NULL, code);
4753 		else
4754 			ext(output, "ppppp|drawBlastObject");
4755 		break;
4756 	case 0x64:
4757 		if (g_options.heVersion)
4758 			invalidop(NULL, code);
4759 		else
4760 			ext(output, "pppp|setBlastObjectWindow");
4761 		break;
4762 	case 0x65:
4763 		ext(output, "|stopObjectCodeA");
4764 		break;
4765 	case 0x66:
4766 		ext(output, "|stopObjectCodeB");
4767 		break;
4768 	case 0x67:
4769 		ext(output, "|endCutscene");
4770 		break;
4771 	case 0x68:
4772 		ext(output, "l|beginCutscene");
4773 		break;
4774 	case 0x69:
4775 		ext(output, "|stopMusic");
4776 		break;
4777 	case 0x6A:
4778 		ext(output, "p|freezeUnfreeze");
4779 		break;
4780 	case 0x6B:
4781 		ext(output, "x" "cursorCommand\0"
4782 				"\x90|cursorOn,"
4783 				"\x91|cursorOff,"
4784 				"\x92|userPutOn,"
4785 				"\x93|userPutOff,"
4786 				"\x94|softCursorOn,"
4787 				"\x95|softCursorOff,"
4788 				"\x96|softUserputOn,"
4789 				"\x97|softUserputOff,"
4790 				"\x99z|setCursorImg,"
4791 				"\x9App|setCursorHotspot,"
4792 				"\x9Cp|initCharset,"
4793 				"\x9Dl|charsetColors,"
4794 				"\xD6p|makeCursorColorTransparent");
4795 		break;
4796 	case 0x6C:
4797 		ext(output, "|breakHere");
4798 		break;
4799 	case 0x6D:
4800 		ext(output, "rlp|ifClassOfIs");
4801 		break;
4802 	case 0x6E:
4803 		ext(output, "lp|setClass");
4804 		break;
4805 	case 0x6F:
4806 		ext(output, "rp|getState");
4807 		break;
4808 	case 0x70:
4809 		ext(output, "pp|setState");
4810 		break;
4811 	case 0x71:
4812 		ext(output, "pp|setOwner");
4813 		break;
4814 	case 0x72:
4815 		ext(output, "rp|getOwner");
4816 		break;
4817 	case 0x73:
4818 		jump(output);
4819 		break;
4820 	case 0x74:
4821 		if (g_options.heVersion >= 70) {
4822 			ext(output, "x" "startSound\0"
4823 					"\x9|setSoundFlag4,"
4824 					"\x17ppp|setSoundVar,"
4825 					"\x19pp|startWithFlag8,"
4826 					"\x38|setQuickStartFlag,"
4827 					"\xA4|setForceQueueFlag,"
4828 					"\xDE|dummy,"
4829 					"\xE0p|setFrequency,"
4830 					"\xE6p|setChannel,"
4831 					"\xE7p|setOffset,"
4832 					"\xE8p|setId,"
4833 					"\xF5|setLoop,"
4834 					"\xFF|start");
4835 			break;
4836 		} else if (g_options.heVersion) {
4837 			ext(output, "pp|startSound");
4838 		} else {
4839 			ext(output, "p|startSound");
4840 		}
4841 		break;
4842 	case 0x75:
4843 		ext(output, "p|stopSound");
4844 		break;
4845 	case 0x76:
4846 		ext(output, "p|startMusic");
4847 		break;
4848 	case 0x77:
4849 		ext(output, "p|stopObjectScript");
4850 		break;
4851 	case 0x78:
4852 		if (g_options.scriptVersion < 7)
4853 			ext(output, "p|panCameraTo");
4854 		else
4855 			ext(output, "pp|panCameraTo");
4856 		break;
4857 	case 0x79:
4858 		ext(output, "p|actorFollowCamera");
4859 		break;
4860 	case 0x7A:
4861 		if (g_options.scriptVersion < 7)
4862 			ext(output, "p|setCameraAt");
4863 		else
4864 			ext(output, "pp|setCameraAt");
4865 		break;
4866 	case 0x7B:
4867 		ext(output, "p|loadRoom");
4868 		break;
4869 	case 0x7C:
4870 		ext(output, "p|stopScript");
4871 		break;
4872 	case 0x7D:
4873 		ext(output, "ppp|walkActorToObj");
4874 		break;
4875 	case 0x7E:
4876 		ext(output, "ppp|walkActorTo");
4877 		break;
4878 	case 0x7F:
4879 		ext(output, "pppp|putActorInXY");
4880 		break;
4881 	case 0x80:
4882 		ext(output, "zp|putActorAtObject");
4883 		break;
4884 	case 0x81:
4885 		ext(output, "pp|faceActor");
4886 		break;
4887 	case 0x82:
4888 		ext(output, "pp|animateActor");
4889 		break;
4890 	case 0x83:
4891 		ext(output, "pppp|doSentence");
4892 		break;
4893 	case 0x84:
4894 		ext(output, "z|pickupObject");
4895 		break;
4896 	case 0x85:
4897 		ext(output, "ppz|loadRoomWithEgo");
4898 		break;
4899 	case 0x87:
4900 		ext(output, "rp|getRandomNumber");
4901 		break;
4902 	case 0x88:
4903 		ext(output, "rpp|getRandomNumberRange");
4904 		break;
4905 	case 0x8A:
4906 		ext(output, "rp|getActorMoving");
4907 		break;
4908 	case 0x8B:
4909 		ext(output, "rp|isScriptRunning");
4910 		break;
4911 	case 0x8C:
4912 		ext(output, "rp|getActorRoom");
4913 		break;
4914 	case 0x8D:
4915 		ext(output, "rp|getObjectX");
4916 		break;
4917 	case 0x8E:
4918 		ext(output, "rp|getObjectY");
4919 		break;
4920 	case 0x8F:
4921 		ext(output, "rp|getObjectDir");
4922 		break;
4923 	case 0x90:
4924 		ext(output, "rp|getActorWalkBox");
4925 		break;
4926 	case 0x91:
4927 		ext(output, "rp|getActorCostume");
4928 		break;
4929 	case 0x92:
4930 		ext(output, "rpp|findInventory");
4931 		break;
4932 	case 0x93:
4933 		ext(output, "rp|getInventoryCount");
4934 		break;
4935 	case 0x94:
4936 		ext(output, "rpp|getVerbFromXY");
4937 		break;
4938 	case 0x95:
4939 		ext(output, "|beginOverride");
4940 		break;
4941 	case 0x96:
4942 		ext(output, "|endOverride");
4943 		break;
4944 	case 0x97:
4945 		ext(output, "ps|setObjectName");
4946 		break;
4947 	case 0x98:
4948 		ext(output, "rp|isSoundRunning");
4949 		break;
4950 	case 0x99:
4951 		ext(output, "pl|setBoxFlags");
4952 		break;
4953 	case 0x9A:
4954 		if (g_options.heVersion)
4955 			invalidop(NULL, code);
4956 		else
4957 			ext(output, "|createBoxMatrix");
4958 		break;
4959 	case 0x9B:
4960 		if (g_options.heVersion)
4961 			ext(output, "x" "resourceRoutines\0"
4962 					"\x64p|loadScript,"
4963 					"\x65p|loadSound,"
4964 					"\x66p|loadCostume,"
4965 					"\x67p|loadRoom,"
4966 					"\x68p|nukeScript,"
4967 					"\x69p|nukeSound,"
4968 					"\x6Ap|nukeCostume,"
4969 					"\x6Bp|nukeRoom,"
4970 					"\x6Cp|lockScript,"
4971 					"\x6Dp|lockSound,"
4972 					"\x6Ep|lockCostume,"
4973 					"\x6Fp|lockRoom,"
4974 					"\x70p|unlockScript,"
4975 					"\x71p|unlockSound,"
4976 					"\x72p|unlockCostume,"
4977 					"\x73p|unlockRoom,"
4978 					"\x75p|loadCharset,"
4979 					"\x76p|nukeCharset,"
4980 					"\x77z|loadFlObject,"
4981 					"\x78p|queueloadScript,"
4982 					"\x79p|queueloadSound,"
4983 					"\x7Ap|queueloadCostume,"
4984 					"\x7Bp|queueloadRoomImage,"
4985 					"\x9fp|unlockImage,"
4986 					"\xc0p|nukeImage,"
4987 					"\xc9p|loadImage,"
4988 					"\xcap|lockImage,"
4989 					"\xcbp|queueloadImage,"
4990 					"\xe9p|lockFlObject,"
4991 					"\xebp|unlockFlObject,"
4992 					"\xef|dummy");
4993 		else
4994 			ext(output, "x" "resourceRoutines\0"
4995 					"\x64p|loadScript,"
4996 					"\x65p|loadSound,"
4997 					"\x66p|loadCostume,"
4998 					"\x67p|loadRoom,"
4999 					"\x68p|nukeScript,"
5000 					"\x69p|nukeSound,"
5001 					"\x6Ap|nukeCostume,"
5002 					"\x6Bp|nukeRoom,"
5003 					"\x6Cp|lockScript,"
5004 					"\x6Dp|lockSound,"
5005 					"\x6Ep|lockCostume,"
5006 					"\x6Fp|lockRoom,"
5007 					"\x70p|unlockScript,"
5008 					"\x71p|unlockSound,"
5009 					"\x72p|unlockCostume,"
5010 					"\x73p|unlockRoom,"
5011 					"\x75p|loadCharset,"
5012 					"\x76p|nukeCharset,"
5013 					"\x77z|loadFlObject");
5014 		break;
5015 	case 0x9C:
5016 		if (g_options.heVersion)
5017 			ext(output, "x" "roomOps\0"
5018 					"\xACpp|roomScroll,"
5019 					"\xAEpp|setScreen,"
5020 					"\xAFpppp|setPalColor,"
5021 					"\xB0|shakeOn,"
5022 					"\xB1|shakeOff,"
5023 					"\xB3ppp|darkenPalette,"
5024 					"\xB4pp|saveLoadRoom,"
5025 					"\xB5p|screenEffect,"
5026 					"\xB6ppppp|darkenPalette,"
5027 					"\xB7ppppp|setupShadowPalette,"
5028 					"\xBApppp|palManipulate,"
5029 					"\xBBpp|colorCycleDelay,"
5030 					"\xD5p|setPalette,"
5031 					"\xDCpp|copyPalColor,"
5032 					"\xDDsp|saveLoad,"
5033 					"\xEApp|swapObjects,"
5034 					"\xECpp|setRoomPalette");
5035 		else
5036 			ext(output, "x" "roomOps\0"
5037 					"\xACpp|roomScroll,"
5038 					"\xAEpp|setScreen,"
5039 					"\xAFpppp|setPalColor,"
5040 					"\xB0|shakeOn,"
5041 					"\xB1|shakeOff,"
5042 					"\xB3ppp|darkenPalette,"
5043 					"\xB4pp|saveLoadRoom,"
5044 					"\xB5p|screenEffect,"
5045 					"\xB6ppppp|darkenPalette,"
5046 					"\xB7ppppp|setupShadowPalette,"
5047 					"\xBApppp|palManipulate,"
5048 					"\xBBpp|colorCycleDelay,"
5049 					"\xD5p|setPalette,"
5050 					"\xDCpp|copyPalColor");
5051 		break;
5052 	case 0x9D:
5053 		if (g_options.heVersion)
5054 			ext(output, "x" "actorOps\0"
5055 					"\xC5p|setCurActor,"
5056 					"\x1Epppp|setClipRect,"
5057 					"\x4Cp|setCostume,"
5058 					"\x4Dpp|setWalkSpeed,"
5059 					"\x4El|setSound,"
5060 					"\x4Fp|setWalkFrame,"
5061 					"\x50pp|setTalkFrame,"
5062 					"\x51p|setStandFrame,"
5063 					"\x52ppp|actorSet:82:??,"
5064 					"\x53|init,"
5065 					"\x54p|setElevation,"
5066 					"\x55|setDefAnim,"
5067 					"\x56pp|setPalette,"
5068 					"\x57p|setTalkColor,"
5069 					"\x58s|setName,"
5070 					"\x59p|setInitFrame,"
5071 					"\x5Bp|setWidth,"
5072 					"\x5Cp|setScale,"
5073 					"\x5D|setNeverZClip,"
5074 					"\x5Ep|setAlwayZClip,"
5075 					"\x5F|setIgnoreBoxes,"
5076 					"\x60|setFollowBoxes,"
5077 					"\x61p|setAnimSpeed,"
5078 					"\x62p|setShadowMode,"
5079 					"\x63pp|setTalkPos,"
5080 					"\xC6pp|setAnimVar,"
5081 					"\xD7|setIgnoreTurnsOn,"
5082 					"\xD8|setIgnoreTurnsOff,"
5083 					"\xD9|initLittle,"
5084 					"\xDA|drawToBackBuf,"
5085 					"\xE1sp|setTalkieSlot");
5086 		else
5087 			ext(output, "x" "actorOps\0"
5088 					"\xC5p|setCurActor,"
5089 					"\x4Cp|setCostume,"
5090 					"\x4Dpp|setWalkSpeed,"
5091 					"\x4El|setSound,"
5092 					"\x4Fp|setWalkFrame,"
5093 					"\x50pp|setTalkFrame,"
5094 					"\x51p|setStandFrame,"
5095 					"\x52ppp|actorSet:82:??,"
5096 					"\x53|init,"
5097 					"\x54p|setElevation,"
5098 					"\x55|setDefAnim,"
5099 					"\x56pp|setPalette,"
5100 					"\x57p|setTalkColor,"
5101 					"\x58s|setName,"
5102 					"\x59p|setInitFrame,"
5103 					"\x5Bp|setWidth,"
5104 					"\x5Cp|setScale,"
5105 					"\x5D|setNeverZClip,"
5106 					"\x5Ep|setAlwayZClip,"
5107 					"\x5F|setIgnoreBoxes,"
5108 					"\x60|setFollowBoxes,"
5109 					"\x61p|setAnimSpeed,"
5110 					"\x62p|setShadowMode,"
5111 					"\x63pp|setTalkPos,"
5112 					"\xC6pp|setAnimVar,"
5113 					"\xD7|setIgnoreTurnsOn,"
5114 					"\xD8|setIgnoreTurnsOff,"
5115 					"\xD9|initLittle,"
5116 					"\xE1p|setAlwayZClip?,"
5117 					"\xE3p|setLayer,"
5118 					"\xE4p|setWalkScript,"
5119 					"\xE5|setStanding,"
5120 					"\xE6p|setDirection,"
5121 					"\xE7p|turnToDirection,"
5122 					"\xE9|freeze,"
5123 					"\xEA|unfreeze,"
5124 					"\xEBp|setTalkScript");
5125 		break;
5126 	case 0x9E:
5127 		if (g_options.heVersion)
5128 			ext(output, "x" "verbOps\0"
5129 					"\xC4p|setCurVerb,"
5130 					"\x7Cp|loadImg,"
5131 					"\x7Ds|loadString,"
5132 					"\x7Ep|setColor,"
5133 					"\x7Fp|setHiColor,"
5134 					"\x80pp|setXY,"
5135 					"\x81|setOn,"
5136 					"\x82|setOff,"
5137 					"\x83p|kill,"
5138 					"\x84|init,"
5139 					"\x85p|setDimColor,"
5140 					"\x86|setDimmed,"
5141 					"\x87p|setKey,"
5142 					"\x88|setCenter,"
5143 					"\x89p|setToString,"
5144 					"\x8Bpp|setToObject,"
5145 					"\x8Cp|setBkColor,"
5146 					"\xFF|redraw");
5147 		else
5148 			ext(output, "x" "verbOps\0"
5149 					"\xC4p|setCurVerb,"
5150 					"\x7Cp|loadImg,"
5151 					"\x7Ds|loadString,"
5152 					"\x7Ep|setColor,"
5153 					"\x7Fp|setHiColor,"
5154 					"\x80pp|setXY,"
5155 					"\x81|setOn,"
5156 					"\x82|setOff,"
5157 					"\x83|kill,"
5158 					"\x84|init,"
5159 					"\x85p|setDimColor,"
5160 					"\x86|setDimmed,"
5161 					"\x87p|setKey,"
5162 					"\x88|setCenter,"
5163 					"\x89p|setToString,"
5164 					"\x8Bpp|setToObject,"
5165 					"\x8Cp|setBkColor,"
5166 					"\xFF|redraw");
5167 		break;
5168 	case 0x9F:
5169 		ext(output, "rpp|getActorFromXY");
5170 		break;
5171 	case 0xA0:
5172 		ext(output, "rpp|findObject");
5173 		break;
5174 	case 0xA1:
5175 		ext(output, "lp|pseudoRoom");
5176 		break;
5177 	case 0xA2:
5178 		ext(output, "rp|getActorElevation");
5179 		break;
5180 	case 0xA3:
5181 		ext(output, "rpp|getVerbEntrypoint");
5182 		break;
5183 	case 0xA4:
5184 		switch (get_byte()) {
5185 		case 205:{
5186 			int array = get_word();
5187 			writeArray(output, array, NULL, pop(), se_get_string());
5188 			}
5189 			break;
5190 		case 208:
5191 			se_a = pop();
5192 			se_b = se_get_list();
5193 			writeArray(output, get_word(), NULL, se_a, se_b);
5194 			break;
5195 		case 212:
5196 			se_a = pop();
5197 			se_b = se_get_list();
5198 			writeArray(output, get_word(), pop(), se_a, se_b);
5199 			break;
5200 		}
5201 		break;
5202 	case 0xA5:
5203 		ext(output, "x" "saveRestoreVerbs\0"
5204 				"\x8Dppp|saveVerbs,"
5205 				"\x8Eppp|restoreVerbs,"
5206 				"\x8Fppp|deleteVerbs");
5207 		break;
5208 	case 0xA6:
5209 		ext(output, "ppppp|drawBox");
5210 		break;
5211 	case 0xA8:
5212 		ext(output, "rp|getActorWidth");
5213 		break;
5214 	case 0xA9:
5215 		ext(output, "x" "wait\0"
5216 				"\xA8pj|waitForActor,"
5217 				"\xA9|waitForMessage,"
5218 				"\xAA|waitForCamera,"
5219 				"\xAB|waitForSentence,"
5220 				"\xE2pj|waitUntilActorDrawn,"
5221 				"\xE8pj|waitUntilActorTurned,"
5222 				);
5223 		break;
5224 	case 0xAA:
5225 		ext(output, "rp|getActorScaleX");
5226 		break;
5227 	case 0xAB:
5228 		ext(output, "rp|getActorAnimCounter1");
5229 		break;
5230 	case 0xAC:
5231 		ext(output, "l|soundKludge");
5232 		break;
5233 	case 0xAD:
5234 		ext(output, "rlp|isAnyOf");
5235 		break;
5236 	case 0xAE:
5237 		if (g_options.heVersion)
5238 			ext(output, "x" "systemOps\0"
5239 					 "\x9E|restart,"
5240 					 "\xA0|confirmShutDown,"
5241 					 "\xF4|shutDown,"
5242 					 "\xFB|startExec,"
5243 					 "\xFC|startGame");
5244 		else
5245 			ext(output, "x" "systemOps\0"
5246 					"\x9E|restartGame,"
5247 					"\x9F|pauseGame,"
5248 					"\xA0|shutDown");
5249 		break;
5250 	case 0xAF:
5251 		ext(output, "rpp|isActorInBox");
5252 		break;
5253 	case 0xB0:
5254 		ext(output, "p|delay");
5255 		break;
5256 	case 0xB1:
5257 		ext(output, "p|delaySeconds");
5258 		break;
5259 	case 0xB2:
5260 		ext(output, "p|delayMinutes");
5261 		break;
5262 	case 0xB3:
5263 		ext(output, "|stopSentence");
5264 		break;
5265 	case 0xB4:
5266 		if (g_options.heVersion)
5267 			PRINT_V7HE("printLine");
5268 		else
5269 			PRINT_V67("printLine");
5270 		break;
5271 	case 0xB5:
5272 		if (g_options.heVersion)
5273 			PRINT_V7HE("printCursor");
5274 		else
5275 			PRINT_V67("printCursor");
5276 		break;
5277 	case 0xB6:
5278 		if (g_options.heVersion)
5279 			PRINT_V7HE("printDebug");
5280 		else
5281 			PRINT_V67("printDebug");
5282 		break;
5283 	case 0xB7:
5284 		if (g_options.heVersion)
5285 			PRINT_V7HE("printSystem");
5286 		else
5287 			PRINT_V67("printSystem");
5288 		break;
5289 	case 0xB8:
5290 		// This is *almost* identical to the other print opcodes, only the 'begin' subop differs
5291 		if (g_options.heVersion) {
5292 			ext(output, "x" "printActor\0"
5293 					"\x41pp|XY,"
5294 					"\x42p|color,"
5295 					"\x43p|right,"
5296 					"\x45|center,"
5297 					"\x47|left,"
5298 					"\x48|overhead,"
5299 					"\x4A|mumble,"
5300 					"\x4Bs|msg,"
5301 					"\xF9l|colors,"
5302 					"\xC2lps|debug,"
5303 					"\xE1p|getText,"
5304 					"\xFEp|begin,"
5305 					"\xFF|end");
5306 		} else {
5307 			ext(output, "x" "printActor\0"
5308 					"\x41pp|XY,"
5309 					"\x42p|color,"
5310 					"\x43p|right,"
5311 					"\x45|center,"
5312 					"\x47|left,"
5313 					"\x48|overhead,"
5314 					"\x4A|mumble,"
5315 					"\x4Bs|msg,"
5316 					"\xFEp|begin,"
5317 					"\xFF|end");
5318 		}
5319 		break;
5320 	case 0xB9:
5321 		if (g_options.heVersion)
5322 			PRINT_V7HE("printEgo");
5323 		else
5324 			PRINT_V67("printEgo");
5325 		break;
5326 	case 0xBA:
5327 		ext(output, "ps|talkActor");
5328 		break;
5329 	case 0xBB:
5330 		ext(output, "s|talkEgo");
5331 		break;
5332 	case 0xBC:
5333 		ext(output, "x" "dimArray\0"
5334 				"\xC7pv|int,"
5335 				"\xC8pv|bit,"
5336 				"\xC9pv|nibble,"
5337 				"\xCApv|byte,"
5338 				"\xCBpv|string,"
5339 				"\xCCv|nukeArray");
5340 		break;
5341 	case 0xBD:
5342 		if (g_options.heVersion)
5343 			ext(output, "|stopObjectCode");
5344 		else
5345 			invalidop(NULL, code);
5346 		break;
5347 	case 0xBE:
5348 		// TODO: this loads another script which does something like
5349 		// stack altering and then finishes (usually with opcode 0xBD).
5350 		// When stack is changed, further disassembly is wrong.
5351 		// This is widely used in HE games.
5352 		// As there are cases when called script does not alter the
5353 		// stack, it's not correct to use "rlpp|..." here
5354 		ext(output, "lpp|startObjectQuick");
5355 		break;
5356 	case 0xBF:
5357 		ext(output, "lp|startScriptQuick2");
5358 		break;
5359 	case 0xC0:
5360 		ext(output, "x" "dim2dimArray\0"
5361 				"\xC7ppv|int,"
5362 				"\xC8ppv|bit,"
5363 				"\xC9ppv|nibble,"
5364 				"\xCAppv|byte,"
5365 				"\xCBppv|string");
5366 		break;
5367 	case 0xC1:
5368 		ext(output, "ps|trace");
5369 		break;
5370 	case 0xC4:
5371 		ext(output, "rp|abs");
5372 		break;
5373 	case 0xC5:
5374 		ext(output, "rpp|getDistObjObj");
5375 		break;
5376 	case 0xC6:
5377 		ext(output, "rppp|getDistObjPt");
5378 		break;
5379 	case 0xC7:
5380 		ext(output, "rpppp|getDistPtPt");
5381 		break;
5382 	case 0xC8:
5383 		if (g_options.heVersion)
5384 				ext(output, "ry" "kernelGetFunctions\0"
5385 					"\x1|virtScreenSave"
5386 					);
5387 		else if (g_options.scriptVersion == 7)
5388 				ext(output, "ry" "kernelGetFunctions\0"
5389 					"\x73|getWalkBoxAt,"
5390 					"\x74|isPointInBox,"
5391 					"\xCE|getRGBSlot,"
5392 					"\xCF|getObjectXPos,"
5393 					"\xD0|getObjectYPos,"
5394 					"\xD1|getObjectWidth,"
5395 					"\xD2|getObjectHeight,"
5396 					"\xD3|getKeyState,"
5397 					"\xD4|getActorFrame,"
5398 					"\xD5|getVerbXPos,"
5399 					"\xD6|getVerbYPos,"
5400 					"\xD7|getBoxFlags"
5401 					);
5402 		else
5403 				ext(output, "ry" "kernelGetFunctions\0"
5404 					"\x71|getPixel"
5405 					);
5406 		break;
5407 	case 0xC9:
5408 		if (g_options.heVersion)
5409 				ext(output, "y" "kernelSetFunctions\0"
5410 					"\x1|virtScreenLoad"
5411 					);
5412 		else if (g_options.scriptVersion == 7)
5413 			ext(output, "y" "kernelSetFunctions\0"
5414 					"\x4|grabCursor,"
5415 					"\x6|startVideo,"
5416 					"\xC|setCursorImg,"
5417 					"\xD|remapCostume,"
5418 					"\xE|remapCostumeInsert,"
5419 					"\xF|setVideoFrameRate,"
5420 
5421 					"\x10|enqueueTextCentered,"
5422 					"\x11|enqueueTextNormal,"
5423 					"\x12|setMouseXY,"
5424 					"\x14|setRadioChatter,"
5425 
5426 					"\x6B|setActorScale,"
5427 					"\x6C|buildPaletteShadow,"
5428 					"\x6D|setPaletteShadow,"
5429 
5430 					"\x72|unk114,"
5431 					"\x75|freezeScripts,"
5432 					"\x76|blastShadowObject,"
5433 					"\x77|superBlastObject,"
5434 					"\x7C|setSaveSound,"
5435 					"\xD7|setSubtitles,"
5436 					);
5437 		else
5438 			ext(output, "y" "kernelSetFunctions\0"
5439 					"\x3|dummy,"
5440 					"\x4|grabCursor,"
5441 					"\x5|fadeOut,"
5442 					"\x6|redrawScreen,"
5443 					"\x8|startManiac,"
5444 					"\x9|killAllScriptsExceptCurrent,"
5445 					"\x68|nukeFlObjects,"
5446 					"\x6B|setActorScale,"
5447 					"\x6C|setupShadowPalette,"
5448 					"\x6D|setupShadowPalette,"
5449 					"\x6E|clearCharsetMask,"
5450 					"\x6F|setActorShadowMode,"
5451 					"\x70|shiftShadowPalette,"
5452 					"\x72|noirMode,"
5453 					"\x75|freezeScripts,"
5454 					"\x77|superBlastObject,"
5455 					"\x78|swapPalColors,"
5456 					"\x7A|setSoundResult,"
5457 					"\x7B|copyPalColor,"
5458 					"\x7C|setSaveSound,"
5459 					);
5460 		break;
5461 	case 0xCA:
5462 		ext(output, "p|delayFrames");
5463 		break;
5464 	case 0xCB:
5465 		ext(output, "rlp|pickOneOf");
5466 		break;
5467 	case 0xCC:
5468 		ext(output, "rplp|pickOneOfDefault");
5469 		break;
5470 	case 0xCD:
5471 		ext(output, "pppp|stampObject");
5472 		break;
5473 	case 0xD0:
5474 		ext(output, "|getDateTime");
5475 		break;
5476 	case 0xD1:
5477 		ext(output, "|stopTalking");
5478 		break;
5479 	case 0xD2:
5480 		ext(output, "rpp|getAnimateVariable");
5481 		break;
5482 	case 0xD4:
5483 		ext(output, "vpp|shuffle");
5484 		break;
5485 	case 0xD5:
5486 		ext(output, "lpp|jumpToScript");
5487 		break;
5488 	case 0xD6:
5489 		se_a = pop();
5490 		se_b = pop();
5491 		push(se_oper(se_b, operBand, se_a));
5492 		break;
5493 	case 0xD7:
5494 		se_a = pop();
5495 		se_b = pop();
5496 		push(se_oper(se_b, operBor, se_a));
5497 		break;
5498 	case 0xD8:
5499 		ext(output, "rp|isRoomScriptRunning");
5500 		break;
5501 	case 0xD9:
5502 		if (g_options.heVersion)
5503 			ext(output, "p|closeFile");
5504 		else
5505 			invalidop(NULL, code);
5506 		break;
5507 	case 0xDA:
5508 		if (g_options.heVersion)
5509 			ext(output, "rsp|openFile");
5510 		else
5511 			invalidop(NULL, code);
5512 		break;
5513 	case 0xDB:
5514 		if (g_options.heVersion)
5515 			ext(output, "rpp|readFile");
5516 		else
5517 			invalidop(NULL, code);
5518 		break;
5519 	case 0xDC:
5520 		if (g_options.heVersion)
5521 
5522 			ext(output, "ppp|writeFile");
5523 		else
5524 			invalidop(NULL, code);
5525 		break;
5526 
5527 	case 0xDD:
5528 		ext(output, "rp|findAllObjects");
5529 		break;
5530 	case 0xDE:
5531 		if (g_options.heVersion)
5532 			ext(output, "s|deleteFile");
5533 		else
5534 			invalidop(NULL, code);
5535 		break;
5536 	case 0xDF:
5537 		if (g_options.heVersion)
5538 			ext(output, "ss|renameFile");
5539 		else
5540 			invalidop(NULL, code);
5541 		break;
5542 	case 0xE0:
5543 		if (g_options.heVersion)
5544 			ext(output, "x" "soundOps\0"
5545 				"\xDEp|setMusicVolume,"
5546 				"\xDF|dummy,"
5547 				"\xE0p|setSoundFrequency");
5548 		else
5549 			invalidop(NULL, code);
5550 		break;
5551 	case 0xE1:
5552 		ext(output, "rpp|getPixel");
5553 		break;
5554 	case 0xE2:
5555 		if (g_options.heVersion)
5556 			ext(output, "p|localizeArrayToScript");
5557 		else
5558 			invalidop(NULL, code);
5559 		break;
5560 	case 0xE3:
5561 		ext(output, "rlw|pickVarRandom");
5562 		break;
5563 	case 0xE4:
5564 		ext(output, "p|setBotSet");
5565 		break;
5566 	case 0xE9:
5567 		if (g_options.heVersion)
5568 			ext(output, "ppp|seekFilePos");
5569 		else
5570 			invalidop(NULL, code);
5571 		break;
5572 	case 0xEA:
5573 		if (g_options.heVersion)
5574 			ext(output, "x" "redimArray\0"
5575 					"\xC7ppv|int,"
5576 					"\xCAppv|byte");
5577 		else
5578 			invalidop(NULL, code);
5579 		break;
5580 	case 0xEB:
5581 		if (g_options.heVersion)
5582 			ext(output, "rp|readFilePos");
5583 		else
5584 			invalidop(NULL, code);
5585 		break;
5586 	case 0xEC:
5587 		if (g_options.heVersion)
5588 			invalidop(NULL, code);
5589 		else
5590 			ext(output, "rp|getActorLayer");
5591 		break;
5592 	case 0xED:
5593 		if (g_options.heVersion)
5594 			ext(output, "rppp|getStringWidth");
5595 		else
5596 			ext(output, "rp|getObjectNewDir");
5597 		break;
5598 	case 0xEE:
5599 		if (g_options.heVersion)
5600 			ext(output, "rp|getStringLen");
5601 		else
5602 			invalidop(NULL, code);
5603 		break;
5604 	case 0xEF:
5605 		if (g_options.heVersion)
5606 			ext(output, "rppp|appendString");
5607 		else
5608 			invalidop(NULL, code);
5609 		break;
5610 	case 0xF1:
5611 		if (g_options.heVersion)
5612 			ext(output, "rpp|compareString");
5613 		else
5614 			invalidop(NULL, code);
5615 		break;
5616 	case 0xF2:
5617 		if (g_options.heVersion) {
5618 			ext(output, "rx" "isResourceLoaded\0"
5619 					"\x12p|image,"
5620 					"\xE2p|room,"
5621 					"\xE3p|costume,"
5622 					"\xE4p|sound,"
5623 					"\xE5p|script");
5624 		} else {
5625 			invalidop(NULL, code);
5626 		}
5627 		break;
5628 	case 0xF3:
5629 		if (g_options.heVersion) {
5630 			ext(output, "ru" "readINI\0"
5631 					"\x01s|number,"
5632 					"\x02s|string");
5633 		} else {
5634 			invalidop(NULL, code);
5635 		}
5636 		break;
5637 	case 0xF4:
5638 		if (g_options.heVersion) {
5639 			ext(output, "u" "writeINI\0"
5640 					"\x01ps|number,"
5641 					"\x02pss|string");
5642 		} else {
5643 			invalidop(NULL, code);
5644 		}
5645 		break;
5646 	case 0xF5:
5647 		if (g_options.heVersion)
5648 			ext(output, "rppp|getStringLenForWidth");
5649 		else
5650 			invalidop(NULL, code);
5651 		break;
5652 	case 0xF6:
5653 		if (g_options.heVersion)
5654 			ext(output, "rpppp|getCharIndexInString");
5655 		else
5656 			invalidop(NULL, code);
5657 		break;
5658 	case 0xF7:
5659 		if (g_options.heVersion)
5660 			ext(output, "rpp|findBox");
5661 		else
5662 			invalidop(NULL, code);
5663 		break;
5664 	case 0xF9:
5665 		if (g_options.heVersion)
5666 			ext(output, "s|createDirectory");
5667 		else
5668 			invalidop(NULL, code);
5669 		break;
5670 	case 0xFA:
5671 		if (g_options.heVersion) {
5672 			ext(output, "x" "setSystemMessage\0"
5673 					"\xF0s|unk1,"
5674 					"\xF1s|versionMsg,"
5675 					"\xF2s|unk3,"
5676 					"\xF3s|titleMsg");
5677 		} else
5678 			invalidop(NULL, code);
5679 		break;
5680 	case 0xFB:
5681 		if (g_options.heVersion)
5682 			ext(output, "x" "polygonOps\0"
5683 					"\xF6ppppppppp|polygonStore,"
5684 					"\xF7pp|polygonErase,"
5685 					"\xF8ppppppppp|polygonStore,"
5686 					);
5687 		else
5688 			invalidop(NULL, code);
5689 		break;
5690 	case 0xFC:
5691 		if (g_options.heVersion)
5692 			ext(output, "rpp|polygonHit");
5693 		else
5694 			invalidop(NULL, code);
5695 		break;
5696 	default:
5697 		invalidop(NULL, code);
5698 		break;
5699 	}
5700 }
5701