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 2-5 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   Similar to the code that detects "head" while loops like this:
34   while(Condition) {
35   }
36   add code to detect tail while loops, i.e. something of the kind
37   do {
38   } while(Condition);
39   In V2-V5, those are the most frequent type of loops (and in V6-V8 they
40   sometimes occur, too).
41 
42   However, implementing this might be quite tricky, and require us to refactor the
43   code, because unlike a "head if/while", we don't know we are inside a loop until its
44   end. This means a problem for indention, and when outputing the initial "do {".
45   To solve this, we could implement some sort of look ahead; but that would be very
46   complicated, because essentially we have to perform full parsing of the data anyway.
47   Instead of doing multiple look aheads, one could also do a 2 pass descumming:
48   In pass 1, we find all jump statement, and identify all jump targets. From this data
49   we can work backwards to detect all loops (and also if/else/elsif).
50   Yet another approach would be to not emit any lines until we fully descummed the script.
51   Instead, we keep each line in a line buffer, with indention but with an associated
52   "indention" variable. When we discover a do/while loop, we can then insert a "do {"
53   line and increase the indention of all intermediate lines. However this approach
54   needs a lot of memory, and won't output anything until the script is fully descummed,
55   which is annoying when debugging descumm.
56 
57 */
58 
59 enum TokenType {
60 	TOK_BYTE = 1,
61 	TOK_WORD = 2,
62 	TOK_VAR = 3,
63 	TOK_LIST = 4,
64 	TOK_ASCII = 5,
65 	TOK_CHAR = 6
66 };
67 
68 
69 #define A1B (TOK_BYTE<<0)
70 #define A1W (TOK_WORD<<0)
71 #define A1V (TOK_VAR<<0)
72 #define A1LIST (TOK_LIST<<0)
73 #define A1ASCII (TOK_ASCII<<0)
74 
75 #define A2B (TOK_BYTE<<4)
76 #define A2W (TOK_WORD<<4)
77 #define A2V (TOK_VAR<<4)
78 #define A2LIST (TOK_LIST<<4)
79 #define A2ASCII (TOK_ASCII<<4)
80 
81 #define A3B (TOK_BYTE<<8)
82 #define A3W (TOK_WORD<<8)
83 #define A3V (TOK_VAR<<8)
84 #define A3LIST (TOK_LIST<<8)
85 #define A3ASCII (TOK_ASCII<<8)
86 #define A3CHAR (TOK_CHAR<<8)
87 
88 #define A4B (TOK_BYTE<<12)
89 #define A4W (TOK_WORD<<12)
90 #define A4V (TOK_VAR<<12)
91 #define A4LIST (TOK_LIST<<12)
92 #define A4ASCII (TOK_ASCII<<12)
93 #define A4CHAR (TOK_CHAR<<12)
94 
95 #define A5ASCII (TOK_ASCII<<16)
96 
97 #define ATO (1<<31)
98 #define ANOLASTPAREN (1<<30)
99 #define ANOFIRSTPAREN (1<<29)
100 #define ASTARTCOMMA (1<<28)
101 #define AVARSTORE (1<<27)
102 #define ANOENDSEMICOLON (1<<26)
103 #define ATOWITHLASTPAREN (1<<25)
104 
105 
106 void emit_if(char *buf, char *condition);
107 
108 
109 const char *var_names0[] = {
110 	/* 0 */
111 	"VAR_EGO",
112 	"VAR_RESULT",
113 	"VAR_CAMERA_POS_X",
114 	"VAR_HAVE_MSG",
115 	/* 4 */
116 	"VAR_ROOM",
117 	"VAR_ACTIVE_ACTOR",
118 	"VAR_OVERRIDE",
119 	NULL,
120 	/* 8 */
121 	"VAR_IS_SOUND_RUNNING",
122 	"VAR_ACTIVE_VERB",
123 	"VAR_CHARCOUNT",
124 	NULL
125 };
126 
127 const char *var_names2[] = {
128 	/* 0 */
129 	"VAR_EGO",
130 	"VAR_RESULT",
131 	"VAR_CAMERA_POS_X",
132 	"VAR_HAVE_MSG",
133 	/* 4 */
134 	"VAR_ROOM",
135 	"VAR_OVERRIDE",
136 	"VAR_MACHINE_SPEED",
137 	"VAR_CHARCOUNT",
138 	/* 8 */
139 	"VAR_ACTIVE_VERB",
140 	"VAR_ACTIVE_OBJECT1",
141 	"VAR_ACTIVE_OBJECT2",
142 	"VAR_NUM_ACTOR",
143 	/* 12 */
144 	"VAR_CURRENT_LIGHTS",
145 	"VAR_CURRENTDRIVE",
146 	NULL,
147 	NULL,
148 	/* 16 */
149 	NULL,
150 	"VAR_MUSIC_TIMER",
151 	"VAR_VERB_ALLOWED",
152 	"VAR_ACTOR_RANGE_MIN",
153 	/* 20 */
154 	"VAR_ACTOR_RANGE_MAX",
155 	NULL,
156 	NULL,
157 	"VAR_CAMERA_MIN_X",
158 	/* 24 */
159 	"VAR_CAMERA_MAX_X",
160 	"VAR_TIMER_NEXT",
161 	"VAR_SENTENCE_VERB",
162 	"VAR_SENTENCE_OBJECT1",
163 	/* 28 */
164 	"VAR_SENTENCE_OBJECT2",
165 	"VAR_SENTENCE_PREPOSITION",
166 	"VAR_VIRT_MOUSE_X",
167 	"VAR_VIRT_MOUSE_Y",
168 	/* 32 */
169 	"VAR_CLICK_AREA",
170 	"VAR_CLICK_VERB",
171 	NULL,
172 	"VAR_CLICK_OBJECT",
173 	/* 36 */
174 	"VAR_ROOM_RESOURCE",
175 	"VAR_LAST_SOUND",
176 	"VAR_BACKUP_VERB",
177 	"VAR_KEYPRESS",
178 	/* 40 */
179 	"VAR_CUTSCENEEXIT_KEY",
180 	"VAR_TALK_ACTOR",
181 	NULL,
182 	NULL
183 };
184 
185 const char *var_names3[] = {
186 	/* 0 */
187 	"VAR_RESULT",
188 	"VAR_EGO",
189 	"VAR_CAMERA_POS_X",
190 	"VAR_HAVE_MSG",
191 	/* 4 */
192 	"VAR_ROOM",
193 	"VAR_OVERRIDE",
194 	"VAR_MACHINE_SPEED",
195 	"VAR_ME",
196 	/* 8 */
197 	"VAR_NUM_ACTOR",
198 	"VAR_CURRENT_LIGHTS",
199 	"VAR_CURRENTDRIVE",
200 	"VAR_TMR_1",
201 	/* 12 */
202 	"VAR_TMR_2",
203 	"VAR_TMR_3",
204 	"VAR_MUSIC_TIMER",
205 	"VAR_ACTOR_RANGE_MIN",
206 	/* 16 */
207 	"VAR_ACTOR_RANGE_MAX",
208 	"VAR_CAMERA_MIN_X",
209 	"VAR_CAMERA_MAX_X",
210 	"VAR_TIMER_NEXT",
211 	/* 20 */
212 	"VAR_VIRT_MOUSE_X",
213 	"VAR_VIRT_MOUSE_Y",
214 	"VAR_ROOM_RESOURCE",
215 	"VAR_LAST_SOUND",
216 	/* 24 */
217 	"VAR_CUTSCENEEXIT_KEY",
218 	"VAR_TALK_ACTOR",
219 	"VAR_CAMERA_FAST_X",
220 	NULL,
221 	/* 28 */
222 	"VAR_ENTRY_SCRIPT",
223 	"VAR_ENTRY_SCRIPT2",
224 	"VAR_EXIT_SCRIPT",
225 	"VAR_EXIT_SCRIPT2",
226 	/* 32 */
227 	"VAR_VERB_SCRIPT",
228 	"VAR_SENTENCE_SCRIPT",
229 	"VAR_INVENTORY_SCRIPT",
230 	"VAR_CUTSCENE_START_SCRIPT",
231 	/* 36 */
232 	"VAR_CUTSCENE_END_SCRIPT",
233 	"VAR_CHARINC",
234 	"VAR_WALKTO_OBJ",
235 	NULL,
236 	/* 40 */
237 	NULL,
238 	NULL,
239 	"VAR_RESTART_KEY",
240 	"VAR_PAUSE_KEY",
241 	/* 44 */
242 	"VAR_MOUSE_X",
243 	"VAR_MOUSE_Y",
244 	"VAR_TIMER",
245 	"VAR_TIMER_TOTAL",
246 	/* 48 */
247 	"VAR_SOUNDCARD",
248 	"VAR_VIDEOMODE",
249 	NULL,
250 	NULL
251 };
252 
253 const char *var_names4[] = {
254 	/* 0 */
255 	"VAR_RESULT",
256 	"VAR_EGO",
257 	"VAR_CAMERA_POS_X",
258 	"VAR_HAVE_MSG",
259 	/* 4 */
260 	"VAR_ROOM",
261 	"VAR_OVERRIDE",
262 	"VAR_MACHINE_SPEED",
263 	"VAR_ME",
264 	/* 8 */
265 	"VAR_NUM_ACTOR",
266 	"VAR_CURRENT_LIGHTS",
267 	"VAR_CURRENTDRIVE",
268 	"VAR_TMR_1",
269 	/* 12 */
270 	"VAR_TMR_2",
271 	"VAR_TMR_3",
272 	"VAR_MUSIC_TIMER",
273 	"VAR_ACTOR_RANGE_MIN",
274 	/* 16 */
275 	"VAR_ACTOR_RANGE_MAX",
276 	"VAR_CAMERA_MIN_X",
277 	"VAR_CAMERA_MAX_X",
278 	"VAR_TIMER_NEXT",
279 	/* 20 */
280 	"VAR_VIRT_MOUSE_X",
281 	"VAR_VIRT_MOUSE_Y",
282 	"VAR_ROOM_RESOURCE",
283 	"VAR_LAST_SOUND",
284 	/* 24 */
285 	"VAR_CUTSCENEEXIT_KEY",
286 	"VAR_TALK_ACTOR",
287 	"VAR_CAMERA_FAST_X",
288 	"VAR_SCROLL_SCRIPT",
289 	/* 28 */
290 	"VAR_ENTRY_SCRIPT",
291 	"VAR_ENTRY_SCRIPT2",
292 	"VAR_EXIT_SCRIPT",
293 	"VAR_EXIT_SCRIPT2",
294 	/* 32 */
295 	"VAR_VERB_SCRIPT",
296 	"VAR_SENTENCE_SCRIPT",
297 	"VAR_INVENTORY_SCRIPT",
298 	"VAR_CUTSCENE_START_SCRIPT",
299 	/* 36 */
300 	"VAR_CUTSCENE_END_SCRIPT",
301 	"VAR_CHARINC",
302 	"VAR_WALKTO_OBJ",
303 	"VAR_DEBUGMODE",
304 	/* 40 */
305 	"VAR_HEAPSPACE",
306 	NULL,
307 	"VAR_RESTART_KEY",
308 	"VAR_PAUSE_KEY",
309 	/* 44 */
310 	"VAR_MOUSE_X",
311 	"VAR_MOUSE_Y",
312 	"VAR_TIMER",
313 	"VAR_TIMER_TOTAL",
314 	/* 48 */
315 	"VAR_SOUNDCARD",
316 	"VAR_VIDEOMODE",
317 	"VAR_MAINMENU_KEY",
318 	"VAR_FIXEDDISK",
319 	/* 52 */
320 	"VAR_CURSORSTATE",
321 	"VAR_USERPUT",
322 	"VAR_V5_TALK_STRING_Y",
323 	/* Loom CD specific */
324 	NULL,
325 	/* 56 */
326 	NULL,
327 	NULL,
328 	NULL,
329 	NULL,
330 	/* 60 */
331 	"VAR_NOSUBTITLES",
332 	NULL,
333 	NULL,
334 	NULL,
335 	/* 64 */
336 	"VAR_SOUNDPARAM",
337 	"VAR_SOUNDPARAM2",
338 	"VAR_SOUNDPARAM3",
339 	NULL
340 };
341 
342 const char *var_names5[] = {
343 	/* 0 */
344 	"VAR_RESULT",
345 	"VAR_EGO",
346 	"VAR_CAMERA_POS_X",
347 	"VAR_HAVE_MSG",
348 	/* 4 */
349 	"VAR_ROOM",
350 	"VAR_OVERRIDE",
351 	"VAR_MACHINE_SPEED",
352 	"VAR_ME",
353 	/* 8 */
354 	"VAR_NUM_ACTOR",
355 	"VAR_CURRENT_LIGHTS",
356 	"VAR_CURRENTDRIVE",
357 	"VAR_TMR_1",
358 	/* 12 */
359 	"VAR_TMR_2",
360 	"VAR_TMR_3",
361 	"VAR_MUSIC_TIMER",
362 	"VAR_ACTOR_RANGE_MIN",
363 	/* 16 */
364 	"VAR_ACTOR_RANGE_MAX",
365 	"VAR_CAMERA_MIN_X",
366 	"VAR_CAMERA_MAX_X",
367 	"VAR_TIMER_NEXT",
368 	/* 20 */
369 	"VAR_VIRT_MOUSE_X",
370 	"VAR_VIRT_MOUSE_Y",
371 	"VAR_ROOM_RESOURCE",
372 	"VAR_LAST_SOUND",
373 	/* 24 */
374 	"VAR_CUTSCENEEXIT_KEY",
375 	"VAR_TALK_ACTOR",
376 	"VAR_CAMERA_FAST_X",
377 	"VAR_SCROLL_SCRIPT",
378 	/* 28 */
379 	"VAR_ENTRY_SCRIPT",
380 	"VAR_ENTRY_SCRIPT2",
381 	"VAR_EXIT_SCRIPT",
382 	"VAR_EXIT_SCRIPT2",
383 	/* 32 */
384 	"VAR_VERB_SCRIPT",
385 	"VAR_SENTENCE_SCRIPT",
386 	"VAR_INVENTORY_SCRIPT",
387 	"VAR_CUTSCENE_START_SCRIPT",
388 	/* 36 */
389 	"VAR_CUTSCENE_END_SCRIPT",
390 	"VAR_CHARINC",
391 	"VAR_WALKTO_OBJ",
392 	"VAR_DEBUGMODE",
393 	/* 40 */
394 	"VAR_HEAPSPACE",
395 	NULL,
396 	"VAR_RESTART_KEY",
397 	"VAR_PAUSE_KEY",
398 	/* 44 */
399 	"VAR_MOUSE_X",
400 	"VAR_MOUSE_Y",
401 	"VAR_TIMER",
402 	"VAR_TIMER_TOTAL",
403 	/* 48 */
404 	"VAR_SOUNDCARD",
405 	"VAR_VIDEOMODE",
406 	"VAR_MAINMENU_KEY",
407 	"VAR_FIXEDDISK",
408 	/* 52 */
409 	"VAR_CURSORSTATE",
410 	"VAR_USERPUT",
411 	NULL,
412 	NULL,
413 	/* 56 */
414 	"VAR_SOUNDRESULT",
415 	"VAR_TALKSTOP_KEY",
416 	NULL,
417 	"VAR_FADE_DELAY",
418 	/* 60 */
419 	"VAR_NOSUBTITLES",
420 	NULL,
421 	NULL,
422 	NULL,
423 	/* 64 */
424 	"VAR_SOUNDPARAM",
425 	"VAR_SOUNDPARAM2",
426 	"VAR_SOUNDPARAM3",
427 	"VAR_INPUTMODE",
428 	/* 68 */
429 	"VAR_MEMORY_PERFORMANCE",
430 	"VAR_VIDEO_PERFORMANCE",
431 	"VAR_ROOM_FLAG",
432 	"VAR_GAME_LOADED",
433 	/* 72 */
434 	"VAR_NEW_ROOM",
435 	NULL,
436 	NULL,
437 	NULL,
438 	/* 76 */
439 	NULL,
440 	NULL,
441 	NULL,
442 	NULL
443 };
444 
445 
get_num_string(int i)446 const char *get_num_string(int i) {
447 	const char *s;
448 
449 	if (i & 0x8000) {							/* Bit var */
450 		i &= 0xFFF;
451 		if (i >= 0x800)
452 			s = "??Bit??";
453 		else
454 			s = "Bit";
455 	} else if (i & 0x4000) {
456 		i &= g_options.IndyFlag ? 0xF : 0xFFF;
457 		if (i > 0x10)
458 			s = "??Local??";
459 		else
460 			s = "Local";
461 	} else {
462 		i &= 0xFFF;
463 		if (i >= 0x320)
464 			s = "??Var??";
465 		else
466 			s = "Var";
467 	}
468 
469 	if (g_options.haltOnError && (s[0] == '?')) {
470 		error("%s out of range, was %d", s, i);
471 	}
472 
473 	return s;
474 }
475 
476 
get_var(char * buf)477 char *get_var(char *buf) {
478 	int i;
479 
480 	if (g_options.scriptVersion <= 2)
481 		i = get_byte();
482 	else
483 		i = (uint16)get_word();
484 
485 	assert(i >= 0);
486 
487 	if (g_options.scriptVersion >= 5 &&
488 			i < ARRAYSIZE(var_names5) && var_names5[i]) {
489 		buf += sprintf(buf, "%s", var_names5[i]);
490 		return buf;
491 	} else if (g_options.scriptVersion >= 4 &&
492 			i < ARRAYSIZE(var_names4) && var_names4[i]) {
493 		buf += sprintf(buf, "%s", var_names4[i]);
494 		return buf;
495 	} else if (g_options.scriptVersion >= 3 &&
496 			i < ARRAYSIZE(var_names3) && var_names3[i]) {
497 		buf += sprintf(buf, "%s", var_names3[i]);
498 		return buf;
499 	} else if (g_options.scriptVersion >= 1 &&
500 			i < ARRAYSIZE(var_names2) && var_names2[i]) {
501 		buf += sprintf(buf, "%s", var_names2[i]);
502 		return buf;
503 	} else if (g_options.scriptVersion == 0 &&
504 			i < ARRAYSIZE(var_names0) && var_names0[i]) {
505 		buf += sprintf(buf, "%s", var_names0[i]);
506 		return buf;
507 	} else if (g_options.scriptVersion <= 2 && g_options.ZakFlag && (i == 234 || i == 235)) {
508 		buf += sprintf(buf, (i == 234) ? "ZERO" : "ONE");
509 		return buf;
510 	} else if ((i & 0x8000) && (g_options.GF_UNBLOCKED || g_options.ZakFlag))
511 		buf += sprintf(buf, "Var[%d Bit %d", (i & 0x0FFF) >> 4, i & 0x000F);
512 	else
513 		buf += sprintf(buf, "%s[%d", get_num_string(i), i & 0xFFF);
514 
515 	if (i & 0x2000) {
516 		int j = get_word();
517 		if (j & 0x2000) {
518 			j ^= 0x2000;
519 			sprintf(buf, " + %s[%d]", get_num_string(j), j & 0xFFF);
520 		} else
521 			sprintf(buf, " + %d", j & 0xFFF);
522 	}
523 	strcat(buf, "]");
524 
525 	return strchr(buf, 0);
526 
527 }
528 
get_var_or_word(char * buf,char condition)529 char *get_var_or_word(char *buf, char condition) {
530 	if (condition)
531 		get_var(buf);
532 	else
533 		sprintf(buf, "%d", get_word());
534 	return strchr(buf, 0);
535 }
536 
get_var_or_byte(char * buf,char condition)537 char *get_var_or_byte(char *buf, char condition) {
538 	if (condition)
539 		get_var(buf);
540 	else
541 		sprintf(buf, "%d", get_byte());
542 	return strchr(buf, 0);
543 }
544 
get_list(char * buf)545 char *get_list(char *buf) {
546 	int i;
547 	int j = 0;
548 	bool first = true;
549 
550 	buf = strecpy(buf, "[");
551 	do {
552 		i = get_byte();
553 		if (i == 0xFF)
554 			break;
555 		if (!first)
556 			buf = strecpy(buf, ",");
557 		first = false;
558 		buf = get_var_or_word(buf, i & 0x80);
559 		j++;
560 		if (j > 16) {
561 			printf("ERROR: too many variables in argument list!\n");
562 			if (g_options.haltOnError)
563 				exit(1);
564 			break;
565 		}
566 	} while (1);
567 
568 	return strecpy(buf, "]");
569 }
570 
571 
add_a_tok(char * buf,int type)572 char *add_a_tok(char *buf, int type) {
573 	switch (type) {
574 	case TOK_BYTE:
575 		buf += sprintf(buf, "%d", get_byte());
576 		break;
577 	case TOK_WORD:
578 		buf += sprintf(buf, "%d", get_word());
579 		break;
580 	case TOK_VAR:
581 		buf = get_var(buf);
582 		break;
583 	case TOK_LIST:
584 		buf = get_list(buf);
585 		break;
586 	case TOK_ASCII:
587 		buf = get_string(buf);
588 		break;
589 	case TOK_CHAR:
590 		error("this code seems to be dead");
591 		buf = put_ascii(buf, get_byte());
592 		break;
593 	}
594 	return buf;
595 }
596 
do_tok(char * buf,const char * text,int args)597 char *do_tok(char *buf, const char *text, int args) {
598 	char *buforg = buf;
599 
600 
601 	if (args & AVARSTORE) {
602 		buf = get_var(buf);
603 		buf = strecpy(buf, " = ");
604 	}
605 
606 	if (text)
607 		buf = strecpy(buf, text);
608 
609 	if (!(args & ANOFIRSTPAREN))
610 		buf = strecpy(buf, "(");
611 
612 	if (args & ASTARTCOMMA)
613 		buf = strecpy(buf, ",");
614 
615 	if (args & 0xF) {
616 		buf = add_a_tok(buf, args & 0xF);
617 		if (args & 0xF0) {
618 			buf = add_a_tok(strecpy(buf, ","), (args >> 4) & 0xF);
619 			if (args & 0xF00) {
620 				buf = add_a_tok(strecpy(buf, ","), (args >> 8) & 0xF);
621 				if (args & 0xF000) {
622 					buf = add_a_tok(strecpy(buf, ","), (args >> 12) & 0xF);
623 					if (args & 0xF0000)
624 						buf = add_a_tok(strecpy(buf, ","), (args >> 16) & 0xF);
625 				}
626 			}
627 		}
628 	}
629 
630 	if (args & ATO) {
631 		char tmp[256];
632 		if (args & ATOWITHLASTPAREN) {
633 			buf = strecpy(buf, ")");
634 		}
635 		strcpy(tmp, buforg);
636 		emit_if(buforg, tmp);
637 	} else {
638 		if (!(args & ANOLASTPAREN)) {
639 		buf = strecpy(buf, ")");
640 		}
641 		if (!(args & ANOENDSEMICOLON) && buf[(strlen(buf) - 1)] != ';') {
642 			buf = strecpy(buf, ";");
643 		}
644 	}
645 
646 	return strchr(buf, 0);
647 }
648 
do_decodeparsestring_v2(char * buf,byte opcode)649 void do_decodeparsestring_v2(char *buf, byte opcode) {
650 	byte c;
651 	bool flag;
652 
653 	while ((c = get_byte())) {
654 		flag = (c & 0x80) != 0;
655 		c &= 0x7f;
656 
657 		if (c < 8) {
658 			buf += sprintf(buf, "\\x%.2X", (int)c);
659 			if (c > 3) {
660 				buf += sprintf(buf, "\\x%.2X", (int)get_byte());
661 			}
662 		} else {
663 			if (c == '\\' || c == '"') // backslash is the escape character
664 				*buf++ = '\\';
665 			}
666 			*buf++ = c;
667 		if (flag)
668 			*buf++ = ' ';
669 	}
670 	*buf = 0;
671 }
672 
do_actorops_v12(char * buf,byte opcode)673 void do_actorops_v12(char *buf, byte opcode) {
674 	buf = strecpy(buf, "ActorOps(");
675 	buf = get_var_or_byte(buf, opcode & 0x80);
676 	buf = strecpy(buf, ",[");
677 
678 	char arg[256];
679 	get_var_or_byte(arg, opcode & 0x40);
680 
681 	int subop = get_byte();
682 	switch(subop) {
683 		case 1:
684 			buf += sprintf(buf, "Sound(%s)", arg);
685 			break;
686 		case 2:
687 			if (g_options.scriptVersion == 1)
688 				buf += sprintf(buf, "Color(%s)", arg);
689 			else
690 				buf += sprintf(buf, "Color(%d, %s)", get_byte(), arg);
691 			break;
692 		case 3:
693 			buf = do_tok(buf, "Name", A1ASCII | ANOENDSEMICOLON);
694 			break;
695 		case 4:
696 			buf += sprintf(buf, "Costume(%s)", arg);
697 			break;
698 		case 5:
699 			buf += sprintf(buf, "TalkColor(%s)", arg);
700 			break;
701 		default:
702 			error("do_actorops_v12: unknown subop %d", subop);
703 	}
704 	strecpy(buf, "]);");
705 }
706 
do_actorops(char * buf,byte opcode)707 void do_actorops(char *buf, byte opcode) {
708 	static const byte convertTable[20] =
709 		{ 1, 0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20 };
710 
711 	char first = 1;
712 
713 	buf = do_tok(buf, "ActorOps", ((opcode & 0x80) ? A1V : A1B) | ANOLASTPAREN | ANOENDSEMICOLON);
714 
715 	buf = strecpy(buf, ",[");
716 
717 	do {
718 		opcode = get_byte();
719 		if (opcode == 0xFF)
720 			break;
721 		if (!first)
722 			buf = strecpy(buf, ",");
723 		first = 0;
724 
725 		// FIXME - this really should be a check for GF_SMALL_HEADER instead!
726 		if (g_options.scriptVersion < 5)
727 			opcode = (opcode & 0xE0) | convertTable[(opcode & 0x1F) - 1];
728 
729 		switch (opcode & 0x1F) {
730 		case 0x00:
731 			buf = do_tok(buf, "Unknown", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
732 			break;
733 		case 0x01:
734 			buf = do_tok(buf, "Costume", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
735 			break;
736 		case 0x02:
737 			buf = do_tok(buf, "WalkSpeed", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | ANOENDSEMICOLON);
738 			break;
739 		case 0x03:
740 			buf = do_tok(buf, "Sound", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
741 			break;
742 		case 0x04:
743 			buf = do_tok(buf, "WalkAnimNr", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
744 			break;
745 		case 0x05:
746 			buf =
747 				do_tok(buf, "TalkAnimNr", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | ANOENDSEMICOLON);
748 			break;
749 		case 0x06:
750 			buf = do_tok(buf, "StandAnimNr", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
751 			break;
752 		case 0x07:
753 			buf =
754 				do_tok(buf, "Nothing",
755 							 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) |
756 							 ((opcode & 0x20) ? A3V : A3B) | ANOENDSEMICOLON);
757 			break;
758 		case 0x08:
759 			buf = do_tok(buf, "Init", ANOENDSEMICOLON);
760 			break;
761 		case 0x09:
762 			buf = do_tok(buf, "Elevation", ((opcode & 0x80) ? A1V : A1W) | ANOENDSEMICOLON);
763 			break;
764 		case 0x0A:
765 			buf = do_tok(buf, "DefaultAnims", ANOENDSEMICOLON);
766 			break;
767 		case 0x0B:
768 			buf = do_tok(buf, "Palette", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | ANOENDSEMICOLON);
769 			break;
770 		case 0x0C:
771 			buf = do_tok(buf, "TalkColor", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
772 			break;
773 		case 0x0D:
774 			buf = do_tok(buf, "Name", A1ASCII | ANOENDSEMICOLON);
775 			break;
776 		case 0x0E:
777 			buf = do_tok(buf, "InitAnimNr", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
778 			break;
779 //		case 0x0F: buf=do_tok(buf, "PaletteList", A1LIST); break;
780 		case 0x10:
781 			buf = do_tok(buf, "Width", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
782 			break;
783 		case 0x11:
784 			if (g_options.scriptVersion == 5)
785 				buf = do_tok(buf, "Scale", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | ANOENDSEMICOLON);
786 			else
787 				buf = do_tok(buf, "Scale", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
788 			break;
789 		case 0x12:
790 			buf = do_tok(buf, "NeverZClip", ANOENDSEMICOLON);
791 			break;
792 		case 0x13:
793 			buf = do_tok(buf, "SetZClip", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
794 			break;
795 		case 0x14:
796 			buf = do_tok(buf, "IgnoreBoxes", ANOENDSEMICOLON);
797 			break;
798 		case 0x15:
799 			buf = do_tok(buf, "FollowBoxes", ANOENDSEMICOLON);
800 			break;
801 		case 0x16:
802 			buf = do_tok(buf, "AnimSpeed", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
803 			break;
804 		case 0x17:
805 			buf=do_tok(buf, "ShadowMode", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
806 			break;
807 		default:
808 			buf += sprintf(buf, "Unknown%.2X()", opcode);
809 		}
810 	} while (1);
811 
812 	strecpy(buf, "]);");
813 
814 }
815 
816 static int g_numInExprStack;
817 static char *g_exprStack[256];
818 
pushExprStack(char * s)819 void pushExprStack(char *s) {
820 	assert(g_numInExprStack < 256);
821 	g_exprStack[g_numInExprStack++] = strdup(s);
822 }
823 
popExprStack(char * buf)824 char *popExprStack(char *buf) {
825 	char *s;
826 
827 	if (g_numInExprStack <= 0) {
828 		printf("Expression stack is empty!\n");
829 		exit(0);
830 	}
831 
832 	s = g_exprStack[--g_numInExprStack];
833 	buf = strecpy(buf, s);
834 	free(s);
835 	return buf;
836 }
837 
838 
do_expr_code(char * buf)839 void do_expr_code(char *buf) {
840 	int i;
841 	const char *s;
842 	char *buf2;
843 
844 	char tmp[256];
845 
846 	buf = strecpy(buf, "Exprmode ");
847 	buf = get_var(buf);
848 	buf = strecpy(buf, " = ");
849 
850 	g_numInExprStack = 0;
851 
852 	do {
853 		i = get_byte();
854 		if (i == 0xFF)
855 			break;
856 		switch (i & 0x1F) {
857 		case 0x1:
858 			get_var_or_word(buf, i & 0x80);
859 			pushExprStack(buf);
860 			break;
861 
862 		case 0x2:
863 			s = " + ";
864 			goto do_oper;
865 
866 		case 0x3:
867 			s = " - ";
868 			goto do_oper;
869 
870 		case 0x4:
871 			s = " * ";
872 			goto do_oper;
873 
874 		case 0x5:
875 			s = " / ";
876 		do_oper:;
877 			buf2 = strecpy(buf, "(");
878 			popExprStack(tmp);
879 			buf2 = popExprStack(buf2);
880 			buf2 = strecpy(buf2, s);
881 			buf2 = strecpy(buf2, tmp);
882 			strecpy(buf2, ")");
883 			pushExprStack(buf);
884 			break;
885 
886 		case 0x6:
887 			buf2 = strecpy(buf, "<");
888 			if (g_options.scriptVersion <= 2)
889 				next_line_V12(buf2);
890 			else
891 				next_line_V345(buf2);
892 			if (buf2[(strlen(buf2) - 1)] == ';') {
893 				buf2[(strlen(buf2) - 1)] = 0;
894 			}
895 			strecpy(strchr(buf2, 0), ">");
896 			pushExprStack(buf);
897 			break;
898 
899 		default:
900 			printf("Warning, Invalid expression code %.2X\n", i);
901 		}
902 
903 	} while (1);
904 
905 	strcpy(popExprStack(buf), ";");
906 }
907 
908 
do_load_code_to_string(char * buf,byte opcode)909 void do_load_code_to_string(char *buf, byte opcode) {
910 
911 	buf = strchr(strcpy(buf, "PutCodeInString("), 0);
912 	buf = get_var_or_byte(buf, opcode & 0x80);
913 	buf = strchr(strcpy(buf, ", "), 0);
914 	buf = get_string(buf);
915 	strcpy(buf, ");");
916 }
917 
do_resource_v2(char * buf,byte opcode)918 void do_resource_v2(char *buf, byte opcode) {
919 	const char *resTypes[] = {
920 			"UnkResType0",
921 			"UnkResType1",
922 			"Costume",
923 			"Room",
924 			"UnkResType4",
925 			"Script",
926 			"Sound"
927 		};
928 	char resid[256];
929 	int subop;
930 
931 	get_var_or_byte(resid, opcode & 0x80);
932 	subop = get_byte();
933 
934 	int type = subop >> 4;
935 
936 	if (((subop & 0x0F) == 0) || ((subop & 0x0F) == 1)) {
937 		if (subop & 1)
938 			buf += sprintf(buf, "load");
939 		else
940 			buf += sprintf(buf, "nuke");
941 		assert(0 <= type && type < ARRAYSIZE(resTypes));
942 		buf += sprintf(buf, "%s", resTypes[type]);
943 		buf += sprintf(buf, "(%s)", resid);
944 	} else {
945 		if (subop & 1)
946 			buf += sprintf(buf, "lock");
947 		else
948 			buf += sprintf(buf, "unlock");
949 		assert(0 <= type && type < ARRAYSIZE(resTypes));
950 		buf += sprintf(buf, "%s", resTypes[type]);
951 		buf += sprintf(buf, "(%s)", resid);
952 	}
953 }
954 
do_resource(char * buf,byte opco)955 void do_resource(char *buf, byte opco) {
956 	char opcode = get_byte();
957 	int subop;
958 	if (g_options.scriptVersion != 5)
959 		subop = opcode & 0x3F;	// FIXME - actually this should only be done for Zak256
960 	else
961 		subop = opcode & 0x1F;
962 
963 	buf += sprintf(buf, "Resource.");
964 
965 	switch (subop) {
966 	case 0x1:
967 		do_tok(buf, "loadScript", ((opcode & 0x80) ? A1V : A1B));
968 		break;
969 	case 0x2:
970 		do_tok(buf, "loadSound", ((opcode & 0x80) ? A1V : A1B));
971 		break;
972 	case 0x3:
973 		do_tok(buf, "loadCostume", ((opcode & 0x80) ? A1V : A1B));
974 		break;
975 	case 0x4:
976 		do_tok(buf, "loadRoom", ((opcode & 0x80) ? A1V : A1B));
977 		break;
978 	case 0x5:
979 		do_tok(buf, "nukeScript", ((opcode & 0x80) ? A1V : A1B));
980 		break;
981 	case 0x6:
982 		do_tok(buf, "nukeSound", ((opcode & 0x80) ? A1V : A1B));
983 		break;
984 	case 0x7:
985 		do_tok(buf, "nukeCostume", ((opcode & 0x80) ? A1V : A1B));
986 		break;
987 	case 0x8:
988 		do_tok(buf, "nukeRoom", ((opcode & 0x80) ? A1V : A1B));
989 		break;
990 	case 0x9:
991 		do_tok(buf, "lockScript", ((opcode & 0x80) ? A1V : A1B));
992 		break;
993 	case 0xA:
994 		do_tok(buf, "lockSound", ((opcode & 0x80) ? A1V : A1B));
995 		break;
996 	case 0xB:
997 		do_tok(buf, "lockCostume", ((opcode & 0x80) ? A1V : A1B));
998 		break;
999 	case 0xC:
1000 		do_tok(buf, "lockRoom", ((opcode & 0x80) ? A1V : A1B));
1001 		break;
1002 	case 0xD:
1003 		do_tok(buf, "unlockScript", ((opcode & 0x80) ? A1V : A1B));
1004 		break;
1005 	case 0xE:
1006 		do_tok(buf, "unlockSound", ((opcode & 0x80) ? A1V : A1B));
1007 		break;
1008 	case 0xF:
1009 		do_tok(buf, "unlockCostume", ((opcode & 0x80) ? A1V : A1B));
1010 		break;
1011 	case 0x10:
1012 		do_tok(buf, "unlockRoom", ((opcode & 0x80) ? A1V : A1B));
1013 		break;
1014 	case 0x11:
1015 		do_tok(buf, "clearHeap", 0);
1016 		break;
1017 	case 0x12:
1018 		do_tok(buf, "loadCharset", ((opcode & 0x80) ? A1V : A1B));
1019 		break;
1020 	case 0x13:
1021 		do_tok(buf, "nukeCharset", ((opcode & 0x80) ? A1V : A1B));
1022 		break;
1023 	case 0x14:
1024 		do_tok(buf, "loadFlObject", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2W));
1025 		break;
1026 
1027 	case 0x22 + 1:
1028 		do_tok(buf, "setCDVolume", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
1029 		break;
1030 	case 0x23 + 1:
1031 		do_tok(buf, "setSoundLoudness", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | A3B);
1032 		break;
1033 	case 0x24 + 1:
1034 		do_tok(buf, "setSoundPitch", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
1035 		break;
1036 
1037 
1038 	default:
1039 		error("do_resource: unhandled subop %d\n", subop);
1040 		break;
1041 	}
1042 
1043 }
1044 
do_pseudoRoom(char * buf)1045 void do_pseudoRoom(char *buf) {
1046 	int j, i = get_byte();
1047 
1048 	buf += sprintf(buf, "PseudoRoom(%d", i);
1049 
1050 	do {
1051 		j = get_byte();
1052 		if (!j)
1053 			break;
1054 
1055 		if (j & 128)
1056 			buf += sprintf(buf, ",%d", j & 127);
1057 		else
1058 			buf = strecpy(buf, ",IG");
1059 	} while (1);
1060 
1061 	strcpy(buf, ");");
1062 }
1063 
do_room_ops(char * buf)1064 void do_room_ops(char *buf) {
1065 	int opcode = get_byte();
1066 
1067 	//buf+=sprintf(buf, "SubCode33%.2X", opcode);
1068 
1069 	switch (opcode & 0x1F) {
1070 	case 0x01:
1071 		do_tok(buf, "RoomScroll", ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2W));
1072 		break;
1073 	case 0x02:
1074 		do_tok(buf, "RoomColor", 0);
1075 		break;
1076 	case 0x03:
1077 		do_tok(buf, "SetScreen", ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2W));
1078 		break;
1079 	case 0x04:
1080 		buf =
1081 			do_tok(buf, "SetPalColor",
1082 						 ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2W) |
1083 						 ((opcode & 0x20) ? A3V : A3W) | ANOLASTPAREN | ANOENDSEMICOLON);
1084 		opcode = get_byte();
1085 		buf = do_tok(buf, NULL, ASTARTCOMMA | ANOFIRSTPAREN | ((opcode & 0x80) ? A1V : A1B));
1086 		break;
1087 	case 0x05:
1088 		do_tok(buf, "ShakeOn", 0);
1089 		break;
1090 	case 0x06:
1091 		do_tok(buf, "ShakeOff", 0);
1092 		break;
1093 	case 0x07:
1094 		// Possibly unused, but changed to match ScummVM anyway
1095 		//do_tok(buf, "Unused", 0);
1096 		buf = do_tok(buf, "SetRoomScale",
1097 						 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) |
1098 						  ANOLASTPAREN | ANOENDSEMICOLON);
1099 		opcode = get_byte();
1100 		buf = do_tok(buf, NULL,
1101 						 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) |
1102 						  ASTARTCOMMA | ANOFIRSTPAREN | ANOLASTPAREN | ANOENDSEMICOLON);
1103 		opcode = get_byte();
1104 		buf = do_tok(buf, NULL,
1105 						 ((opcode & 0x40) ? A2V : A2B) | // apparently it uses the param 2 bit
1106 						  ASTARTCOMMA | ANOFIRSTPAREN);
1107 		break;
1108 	case 0x08:
1109 		buf =
1110 			do_tok(buf, "RoomIntensity",
1111 						 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) |
1112 						 ((opcode & 0x20) ? A3V : A3B));
1113 		break;
1114 	case 0x09:
1115 		buf = do_tok(buf, "saveLoad", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
1116 		break;
1117 	case 0x0A:
1118 		buf = do_tok(buf, "screenEffect", ((opcode & 0x80) ? A1V : A1W));
1119 		break;
1120 	case 0x0B:
1121 		buf =
1122 			do_tok(buf, "setRGBRoomIntensity",
1123 						 ANOLASTPAREN | ANOENDSEMICOLON | ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ?
1124 																														 A2V : A2W) |
1125 						 ((opcode & 0x20) ? A3V : A3W));
1126 		opcode = get_byte();
1127 		buf =
1128 			do_tok(buf, NULL,
1129 						 ASTARTCOMMA | ANOFIRSTPAREN | ((opcode & 0x80) ? A1V : A1B) |
1130 						 ((opcode & 0x40) ? A2V : A2B));
1131 		break;
1132 
1133 	case 0x0C:
1134 		buf =
1135 			do_tok(buf, "setRoomShadow",
1136 						 ANOLASTPAREN | ANOENDSEMICOLON | ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ?
1137 																														 A2V : A2W) |
1138 						 ((opcode & 0x20) ? A3V : A3W));
1139 		opcode = get_byte();
1140 		buf =
1141 			do_tok(buf, NULL,
1142 						 ASTARTCOMMA | ANOFIRSTPAREN | ((opcode & 0x80) ? A1V : A1B) |
1143 						 ((opcode & 0x40) ? A2V : A2B));
1144 		break;
1145 
1146 	case 0x0D:
1147 		do_tok(buf, "saveString", ((opcode & 0x80) ? A1V : A1B) | A2ASCII);
1148 		break;
1149 	case 0x0E:
1150 		do_tok(buf, "loadString", ((opcode & 0x80) ? A1V : A1B) | A2ASCII);
1151 		break;
1152 
1153 	case 0x0F:
1154 		buf = do_tok(buf, "palManipulate", ANOLASTPAREN | ANOENDSEMICOLON | ((opcode & 0x80) ? A1V : A1B));
1155 		opcode = get_byte();
1156 		buf =
1157 			do_tok(buf, NULL,
1158 						 ASTARTCOMMA | ANOFIRSTPAREN | ANOLASTPAREN | ANOENDSEMICOLON | ((opcode & 0x80) ?
1159 																													 A1V : A1B) |
1160 						 ((opcode & 0x40) ? A2V : A2B));
1161 		opcode = get_byte();
1162 		buf = do_tok(buf, NULL, ASTARTCOMMA | ANOFIRSTPAREN | ((opcode & 0x80) ? A1V : A1B));
1163 		break;
1164 
1165 	case 0x10:
1166 		do_tok(buf, "colorCycleDelay", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
1167 		break;
1168 
1169 	default:
1170 		strcpy(buf, "Unknown??");
1171 	}
1172 }
1173 
do_room_ops_old(char * buf,byte opcode)1174 void do_room_ops_old(char *buf, byte opcode) {
1175 	char	a[256];
1176 	char	b[256];
1177 
1178 	if (g_options.scriptVersion <= 2) {
1179 		get_var_or_byte(a, (opcode & 0x80));
1180 		get_var_or_byte(b, (opcode & 0x40));
1181 	} else if (g_options.scriptVersion == 3) {
1182 		get_var_or_word(a, (opcode & 0x80));
1183 		get_var_or_word(b, (opcode & 0x40));
1184 	}
1185 
1186 	opcode = get_byte();
1187 	switch (opcode & 0x1F) {
1188 	case 0x01:
1189 		if (g_options.scriptVersion > 3) {
1190 			get_var_or_word(a, (opcode & 0x80));
1191 			get_var_or_word(b, (opcode & 0x40));
1192 		}
1193 		buf = strecpy(buf, "RoomScroll(");
1194 		buf = strecpy(buf, a);
1195 		buf = strecpy(buf, ",");
1196 		buf = strecpy(buf, b);
1197 		buf = strecpy(buf, ")");
1198 		break;
1199 	case 0x02:
1200 		if (g_options.scriptVersion > 3) {
1201 			get_var_or_word(a, (opcode & 0x80));
1202 			get_var_or_word(b, (opcode & 0x40));
1203 		}
1204 		buf = strecpy(buf, "RoomColor(");
1205 		buf = strecpy(buf, a);
1206 		buf = strecpy(buf, ",");
1207 		buf = strecpy(buf, b);
1208 		buf = strecpy(buf, ")");
1209 		break;
1210 	case 0x03:
1211 		if (g_options.scriptVersion > 3) {
1212 			get_var_or_word(a, (opcode & 0x80));
1213 			get_var_or_word(b, (opcode & 0x40));
1214 		}
1215 		buf = strecpy(buf, "SetScreen(");
1216 		buf = strecpy(buf, a);
1217 		buf = strecpy(buf, ",");
1218 		buf = strecpy(buf, b);
1219 		buf = strecpy(buf, ")");
1220 		break;
1221 	case 0x04:
1222 		if (g_options.scriptVersion > 3) {
1223 			get_var_or_word(a, (opcode & 0x80));
1224 			get_var_or_word(b, (opcode & 0x40));
1225 		}
1226 		buf = strecpy(buf, "SetPalColor(");
1227 		buf = strecpy(buf, a);
1228 		buf = strecpy(buf, ",");
1229 		buf = strecpy(buf, b);
1230 		buf = strecpy(buf, ")");
1231 		break;
1232 	case 0x05:
1233 		do_tok(buf, "ShakeOn", 0);
1234 		break;
1235 	case 0x06:
1236 		do_tok(buf, "ShakeOff", 0);
1237 		break;
1238 	default:
1239 		error("do_room_ops_old: unknown subop %d", opcode & 0x1F);
1240 	}
1241 }
1242 
do_cursor_command(char * buf)1243 void do_cursor_command(char *buf) {
1244 	int opcode = get_byte();
1245 
1246 	switch (opcode & 0x1f) {
1247 	case 0x01:
1248 		do_tok(buf, "CursorShow", 0);
1249 		break;
1250 	case 0x02:
1251 		do_tok(buf, "CursorHide", 0);
1252 		break;
1253 	case 0x03:
1254 		do_tok(buf, "UserputOn", 0);
1255 		break;
1256 	case 0x04:
1257 		do_tok(buf, "UserputOff", 0);
1258 		break;
1259 	case 0x05:
1260 		do_tok(buf, "CursorSoftOn", 0);
1261 		break;
1262 	case 0x06:
1263 		do_tok(buf, "CursorSoftOff", 0);
1264 		break;
1265 	case 0x07:
1266 		do_tok(buf, "UserputSoftOn", 0);
1267 		break;
1268 	case 0x08:
1269 		do_tok(buf, "UserputSoftOff", 0);
1270 		break;
1271 
1272 	case 0x0A:
1273 		do_tok(buf, "SetCursorImg", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
1274 		break;
1275 	case 0x0B:
1276 		do_tok(buf, "SetCursorHotspot",
1277 					 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) |
1278 					 ((opcode & 0x20) ? A3V : A3B));
1279 		break;
1280 	case 0x0C:
1281 		do_tok(buf, "InitCursor", ((opcode & 0x80) ? A1V : A1B));
1282 		break;
1283 	case 0x0D:
1284 		do_tok(buf, "InitCharset", ((opcode & 0x80) ? A1V : A1B));
1285 		break;
1286 
1287 	case 0x0E:
1288 		if (g_options.scriptVersion == 3)
1289 			do_tok(buf, "LoadCharset", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
1290 		else
1291 			do_tok(buf, "CursorCommand", A1LIST);
1292 		break;
1293 	default:
1294 		sprintf(buf, "UnknownCursorCommand%.2X", opcode);
1295 	}
1296 }
1297 
do_verbops_v2(char * buf,byte opcode)1298 void do_verbops_v2(char *buf, byte opcode) {
1299 	int subop = get_byte();
1300 
1301 	buf = do_tok(buf, "VerbOps", ANOLASTPAREN | ANOENDSEMICOLON);
1302 	switch (subop) {
1303 		case 0:
1304 			buf = do_tok(buf, "Delete", (opcode & 0x80) ? A1V : A1B | ANOENDSEMICOLON);
1305 			break;
1306 		case 0xFF:
1307 			buf = do_tok(buf, "State", A1B | A2B | ANOENDSEMICOLON);
1308 			break;
1309 		default:
1310 			buf += sprintf(buf, "New-%d", subop);
1311 			buf = do_tok(buf, "", A1B | A2B | ((opcode & 0x80) ? A3V : A3B) | A4B | A5ASCII | ANOENDSEMICOLON);
1312 	}
1313 	strecpy(buf, ");");
1314 }
1315 
do_verbops(char * buf,byte opcode)1316 void do_verbops(char *buf, byte opcode) {
1317 	char first = 1;
1318 
1319 	buf = do_tok(buf, "VerbOps", ((opcode & 0x80) ? A1V : A1B) | ANOLASTPAREN | ANOENDSEMICOLON);
1320 	buf = strecpy(buf, ",[");
1321 
1322 	do {
1323 		opcode = get_byte();
1324 		if (opcode == 0xFF)
1325 			break;
1326 		if (!first)
1327 			buf = strecpy(buf, ",");
1328 		first = 0;
1329 		switch (opcode & 0x1F) {
1330 		case 0x1:
1331 			buf = do_tok(buf, "Image", (opcode & 0x80) ? A1V : A1W | ANOENDSEMICOLON);
1332 			break;
1333 		case 0x2:
1334 			buf = do_tok(buf, "Text", A1ASCII | ANOENDSEMICOLON);
1335 			break;
1336 		case 0x3:
1337 			buf = do_tok(buf, "Color", (opcode & 0x80) ? A1V : A1B | ANOENDSEMICOLON);
1338 			break;
1339 		case 0x4:
1340 			buf = do_tok(buf, "HiColor", (opcode & 0x80) ? A1V : A1B | ANOENDSEMICOLON);
1341 			break;
1342 		case 0x5:
1343 			buf = do_tok(buf, "SetXY", ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2W) | ANOENDSEMICOLON);
1344 			break;
1345 		case 0x6:
1346 			buf = do_tok(buf, "On", ANOENDSEMICOLON);
1347 			break;
1348 		case 0x7:
1349 			buf = do_tok(buf, "Off", ANOENDSEMICOLON);
1350 			break;
1351 		case 0x8:
1352 			buf = do_tok(buf, "Delete", ANOENDSEMICOLON);
1353 			break;
1354 		case 0x9:
1355 			buf = do_tok(buf, "New", ANOENDSEMICOLON);
1356 			break;
1357 		case 0x10:
1358 			buf = do_tok(buf, "DimColor", (opcode & 0x80) ? A1V : A1B | ANOENDSEMICOLON);
1359 			break;
1360 		case 0x11:
1361 			buf = do_tok(buf, "Dim", ANOENDSEMICOLON);
1362 			break;
1363 		case 0x12:
1364 			buf = do_tok(buf, "Key", (opcode & 0x80) ? A1V : A1B | ANOENDSEMICOLON);
1365 			break;
1366 		case 0x13:
1367 			buf = do_tok(buf, "Center", ANOENDSEMICOLON);
1368 			break;
1369 		case 0x14:
1370 			buf = do_tok(buf, "SetToString", (opcode & 0x80) ? A1V : A1W | ANOENDSEMICOLON);
1371 			break;
1372 		case 0x16:
1373 			buf =
1374 				do_tok(buf, "SetToObject", ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2B) | ANOENDSEMICOLON);
1375 			break;
1376 		case 0x17:
1377 			buf = do_tok(buf, "BackColor", (opcode & 0x80) ? A1V : A1B | ANOENDSEMICOLON);
1378 			break;
1379 		default:
1380 			buf += sprintf(buf, "Invalid%.2X()", opcode);
1381 		}
1382 
1383 	} while (1);
1384 	strecpy(buf, "]);");
1385 }
1386 
do_print_ego(char * buf,byte opcode)1387 void do_print_ego(char *buf, byte opcode) {
1388 	char first = 1;
1389 
1390 	if (opcode == 0xD8) {
1391 		buf = strecpy(buf, "printEgo([");
1392 	} else {
1393 		buf = do_tok(buf, "print", ((opcode & 0x80) ? A1V : A1B) | ANOLASTPAREN | ANOENDSEMICOLON);
1394 		buf = strecpy(buf, ",[");
1395 	}
1396 
1397 	do {
1398 		opcode = get_byte();
1399 		if (opcode == 0xFF)
1400 			break;
1401 
1402 		if (!first)
1403 			buf = strecpy(buf, ",");
1404 		first = 0;
1405 
1406 		switch (opcode & 0x1f) {
1407 		case 0x0:
1408 			buf = do_tok(buf, "Pos", ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2W) | ANOENDSEMICOLON);
1409 			break;
1410 		case 0x1:
1411 			buf = do_tok(buf, "Color", ((opcode & 0x80) ? A1V : A1B) | ANOENDSEMICOLON);
1412 			break;
1413 		case 0x2:
1414 			buf = do_tok(buf, "Clipped", ((opcode & 0x80) ? A1V : A1W) | ANOENDSEMICOLON);
1415 			break;
1416 		case 0x3:
1417 			buf = do_tok(buf, "RestoreBG", ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2W) | ANOENDSEMICOLON);
1418 			break;
1419 		case 0x4:
1420 			buf = do_tok(buf, "Center", ANOENDSEMICOLON);
1421 			break;
1422 		case 0x6:
1423 			if (g_options.GF_UNBLOCKED)
1424 				buf = do_tok(buf, "Height", ((opcode & 0x80) ? A1V: A1W) | ANOENDSEMICOLON);
1425 			else
1426 				buf = do_tok(buf, "Left", ANOENDSEMICOLON);
1427 			break;
1428 		case 0x7:
1429 			buf = do_tok(buf, "Overhead", ANOENDSEMICOLON);
1430 			break;
1431 		case 0x8:
1432 			buf = do_tok(buf, "PlayCDTrack", ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2W) | ANOENDSEMICOLON);
1433 			break;
1434 		case 0xF:{
1435 				buf = strecpy(buf, "Text(");
1436 				buf = get_string(buf);
1437 				buf = strecpy(buf, ")");
1438 			}
1439 			goto exit_proc;
1440 		default:
1441 			buf += sprintf(buf, "Unknown%.2X()", opcode);
1442 			goto exit_proc;
1443 		}
1444 	} while (1);
1445 
1446 exit_proc:;
1447 	buf = strecpy(buf, "]);");
1448 
1449 }
1450 
do_unconditional_jump(char * buf)1451 void do_unconditional_jump(char *buf) {
1452 	int offset = get_word();
1453 	int cur = get_curoffs();
1454 	int to = cur + offset;
1455 
1456 	if (offset == 0) {
1457 		sprintf(buf, "/* goto %.4X; */", to);
1458 	} else if (!g_options.dontOutputElse && maybeAddElse(cur, to)) {
1459 		pendingElse = true;
1460 		pendingElseTo = to;
1461 		pendingElseOffs = cur;
1462 		pendingElseOpcode = g_jump_opcode;
1463 		pendingElseIndent = g_blockStack.size();
1464 		buf[0] = 0;
1465 	} else {
1466 		if (!g_blockStack.empty() && !g_options.dontOutputWhile) {
1467 			Block p = g_blockStack.top();
1468 			if (p.isWhile && cur == (int)p.to)
1469 				return;		// A 'while' ends here.
1470 		}
1471 		sprintf(buf, "goto %.4X;", to);
1472 	}
1473 }
1474 
emit_if(char * buf,char * condition)1475 void emit_if(char *buf, char *condition) {
1476 	int offset = get_word();
1477 	int cur = get_curoffs();
1478 	int to = cur + offset;
1479 
1480 	if (!g_options.dontOutputElseif && pendingElse) {
1481 		if (maybeAddElseIf(cur, pendingElseTo, to)) {
1482 			pendingElse = false;
1483 			haveElse = true;
1484 			buf = strecpy(buf, "} else if (");
1485 			buf = strecpy(buf, condition);
1486 			sprintf(buf, g_options.alwaysShowOffs ? ") /*%.4X*/ {" : ") {", to);
1487 			return;
1488 		}
1489 	}
1490 
1491 	if (!g_options.dontOutputIfs && maybeAddIf(cur, to)) {
1492 		if (!g_options.dontOutputWhile && g_blockStack.top().isWhile) {
1493 			buf = strecpy(buf, "while (");
1494 		} else
1495 			buf = strecpy(buf, "if (");
1496 		buf = strecpy(buf, condition);
1497 		sprintf(buf, g_options.alwaysShowOffs ? ") /*%.4X*/ {" : ") {", to);
1498 		return;
1499 	}
1500 
1501 //	buf = strecpy(buf, negate ? "if (" : "unless (");
1502 	buf = strecpy(buf, "unless (");
1503 	buf = strecpy(buf, condition);
1504 	sprintf(buf, ") goto %.4X;", to);
1505 }
1506 
do_if_code(char * buf,byte opcode)1507 void do_if_code(char *buf, byte opcode) {
1508 	char var[256];
1509 	char tmp[256], tmp2[256];
1510 	int txt;
1511 
1512 	const char *cmp_texts[8] = {
1513 		" >= ", " < ", " <= ", " > ", " == ", " != ", "!", "",
1514 	};
1515 
1516 	var[0] = 0;
1517 	if (opcode != 0x28 && opcode != 0xA8)
1518 		get_var(var);
1519 
1520 	switch (opcode & 0x7F) {
1521 	case 0x38:
1522 		txt = 0;
1523 		break;											/* lessOrEqual */
1524 	case 0x04:
1525 		txt = 2;
1526 		break;											/* isGreaterEqual */
1527 	case 0x08:
1528 		txt = 5;
1529 		break;											/* isNotEqual */
1530 	case 0x48:
1531 		txt = 4;
1532 		break;											/* isEqual */
1533 	case 0x78:
1534 		txt = 1;
1535 		break;											/* isGreater */
1536 	case 0x44:
1537 		txt = 3;
1538 		break;											/* isLess */
1539 	case 0x28:
1540 		txt = opcode & 128 ? 7 : 6;
1541 		break;
1542 	default:
1543 		/* Exit, this should never happen, only if my code is buggy */
1544 		error("Unknown IF code %x", opcode);
1545 	}
1546 
1547 	if (opcode == 0x28 || opcode == 0xA8) {
1548 		get_var(tmp2);
1549 	} else {
1550 		if (g_options.scriptVersion == 0)
1551 			get_var_or_byte(tmp2, opcode & 0x80);
1552 		else
1553 			get_var_or_word(tmp2, opcode & 0x80);
1554 	}
1555 
1556 	sprintf(tmp, "%s%s%s", var, cmp_texts[txt], tmp2);
1557 	emit_if(buf, tmp);
1558 }
1559 
do_if_active_object(char * buf,byte opcode)1560 void do_if_active_object(char *buf, byte opcode) {
1561 	char tmp[256];
1562 
1563 	int obj = get_byte();
1564 	if (opcode & 0x80)
1565 		obj |= 0x100;
1566 
1567 	sprintf(tmp, "activeObject2 == %d", obj);
1568 
1569 	emit_if(buf, tmp);
1570 }
1571 
do_walk_actor_to_object(char * buf,byte opcode)1572 void do_walk_actor_to_object(char *buf, byte opcode) {
1573 
1574 	buf += sprintf(buf, "walkActorToObject(");
1575 	buf = add_a_tok(buf, (opcode & 0x80) ? A1V : A1B);
1576 
1577 	int obj = get_byte();
1578 	if (opcode & 0x40)
1579 		obj |= 0x100;
1580 
1581 	sprintf(buf, ",%d);", obj);
1582 }
1583 
do_put_actor_at_object(char * buf,byte opcode)1584 void do_put_actor_at_object(char *buf, byte opcode) {
1585 
1586 	buf += sprintf(buf, "putActorAtObject(");
1587 	buf = add_a_tok(buf, (opcode & 0x80) ? A1V : A1B);
1588 
1589 	int obj = get_byte();
1590 	if (opcode & 0x40)
1591 		obj |= 0x100;
1592 
1593 	sprintf(buf, ",%d);", obj);
1594 }
1595 
do_sentence(char * buf,byte opcode)1596 void do_sentence(char *buf, byte opcode) {
1597 	int verb = get_byte();
1598 	int obj1 = get_byte();
1599 	int obj2 = get_byte();
1600 
1601 	// Not _cmdObject / _cmdObject2
1602 	if (obj1 != 0xFF && obj1 != 0xFE) {
1603 		if(opcode & 0x80)
1604 			obj1 |= 0x100;
1605 	}
1606 	// Not _cmdObject / _cmdObject2
1607 	if (obj2 != 0xFF && obj2 != 0xFE) {
1608 		if (opcode & 0x40)
1609 			obj2 |= 0x100;
1610 	}
1611 
1612 	sprintf(buf, "doSentence(%d,%d,%d);", verb, obj1, obj2);
1613 }
1614 
1615 
do_set_object_name(char * buf,byte opcode)1616 void do_set_object_name(char *buf, byte opcode) {
1617 	int obj = get_byte();
1618 
1619 	if (opcode & 0x40)
1620 		obj |= 0x100;
1621 
1622 	buf += sprintf(buf, "setObjectName(%d,", obj);
1623 	buf = add_a_tok(buf, A1B | A1ASCII);
1624 
1625 	sprintf(buf, ");");
1626 }
1627 
do_if_state_code(char * buf,byte opcode)1628 void do_if_state_code(char *buf, byte opcode) {
1629 	char var[256];
1630 	char tmp[256], tmp2[256];
1631 	byte neg;
1632 	int state = 0;
1633 
1634 	var[0] = 0;
1635 	if (g_options.scriptVersion == 0) {
1636 		if (opcode & 0x40)
1637 			sprintf(var, "activeObject");
1638 		else
1639 			sprintf(var, "%d", get_byte());
1640 	} else {
1641 		get_var_or_word(var, opcode & 0x80);
1642 	}
1643 
1644 	if (g_options.scriptVersion > 2) {
1645 		switch (opcode & 0x2F) {
1646 		case 0x0f:
1647 			neg = 0;
1648 			break;
1649 		case 0x2f:
1650 			neg = 1;
1651 			break;
1652 		default:
1653 			/* Exit, this should never happen, only if my code is buggy */
1654 			error("Unknown IF code %x", opcode);
1655 		}
1656 
1657 		get_var_or_byte(tmp2, opcode & 0x40);
1658 	} else {
1659 		if (g_options.scriptVersion == 0) {
1660 			switch (opcode) {
1661 			case 0x7f:
1662 			case 0xbf:
1663 				state = 2;
1664 				neg = 1;
1665 				break;
1666 			case 0x9f:
1667 			case 0xdf:
1668 				state = 4;
1669 				neg = 1;
1670 				break;
1671 			case 0xaf:
1672 			case 0xef:
1673 				state = 8;
1674 				neg = 1;
1675 				break;
1676 			case 0x3f:
1677 			case 0xff:
1678 				state = 2;
1679 				neg = 0;
1680 				break;
1681 			case 0x1f:
1682 			case 0x5f:
1683 				state = 4;
1684 				neg = 0;
1685 				break;
1686 			case 0x2f:
1687 			case 0x6f:
1688 				state = 8;
1689 				neg = 0;
1690 				break;
1691 			default:
1692 				/* Exit, this should never happen, only if my code is buggy */
1693 				error("Unknown IF code %x", opcode);
1694 			}
1695 		} else {
1696 			switch (opcode) {
1697 			case 0x3f:
1698 			case 0xbf:
1699 				state = 1;
1700 				neg = 1;
1701 				break;
1702 			case 0x5f:
1703 			case 0xdf:
1704 				state = 2;
1705 				neg = 1;
1706 				break;
1707 			case 0x2f:
1708 			case 0xaf:
1709 				state = 4;
1710 				neg = 1;
1711 				break;
1712 			case 0x0f:
1713 			case 0x8f:
1714 				state = 8;
1715 				neg = 1;
1716 				break;
1717 			case 0x7f:
1718 			case 0xff:
1719 				state = 1;
1720 				neg = 0;
1721 				break;
1722 			case 0x1f:
1723 			case 0x9f:
1724 				state = 2;
1725 				neg = 0;
1726 				break;
1727 			case 0x6f:
1728 			case 0xef:
1729 				state = 4;
1730 				neg = 0;
1731 				break;
1732 			case 0x4f:
1733 			case 0xcf:
1734 				state = 8;
1735 				neg = 0;
1736 				break;
1737 			default:
1738 				/* Exit, this should never happen, only if my code is buggy */
1739 				error("Unknown IF code %x", opcode);
1740 			}
1741 		}
1742 	}
1743 
1744 	if (g_options.scriptVersion > 2)
1745 		sprintf(tmp, "getState(%s)%s%s", var, neg ? " != " : " == ", tmp2);
1746 	else
1747 		sprintf(tmp, "%sgetState%02d(%s)", neg ? "!" : "", state, var);
1748 	emit_if(buf, tmp);
1749 }
1750 
do_varset_code(char * buf,byte opcode)1751 void do_varset_code(char *buf, byte opcode) {
1752 	const char *s;
1753 
1754 	if ((g_options.scriptVersion <= 2)
1755 		&& ((opcode & 0x7F) == 0x0A
1756 		 || (opcode & 0x7F) == 0x2A
1757 		 || (opcode & 0x7F) == 0x6A)) {
1758 
1759 		int i = get_byte();
1760 		buf += sprintf(buf, "Var[Var[%d]]", i);
1761 	} else
1762 		buf = get_var(buf);
1763 
1764 	switch (opcode & 0x7F) {
1765 	case 0x0A:
1766 	case 0x1A:
1767 	case 0x2C:
1768 		s = " = ";
1769 		break;											/* move */
1770 	case 0x1B:
1771 		s = " *= ";
1772 		break;											/* mul */
1773 	case 0x3A:
1774 	case 0x6A:
1775 		s = " -= ";
1776 		break;											/* sub */
1777 	case 0x57:
1778 		s = " |= ";
1779 		break;											/* or */
1780 	case 0x2A:
1781 	case 0x5A:
1782 		s = " += ";
1783 		break;											/* add */
1784 	case 0x5B:
1785 		s = " /= ";
1786 		break;											/* divide */
1787 	case 0x17:
1788 		s = " &= ";
1789 		break;											/* and */
1790 	case 0x46:
1791 		if (opcode & 128)
1792 			s = "--";
1793 		else
1794 			s = "++";
1795 		break;											/* increment & decrement */
1796 	default:
1797 		/* Exit, this should never happen, only if my code is buggy */
1798 		error("Unknown VARSET code %x", opcode);
1799 	}
1800 
1801 	buf = strecpy(buf, s);
1802 
1803 
1804 	if ((g_options.scriptVersion <= 2) && (opcode & 0x7F) == 0x2C) { /* assignVarByte */
1805 		sprintf(buf, "%d", get_byte());
1806 		buf = strchr(buf, 0);
1807 	} else if ((opcode & 0x7F) != 0x46) {	/* increment or decrement */
1808 		if (g_options.scriptVersion == 0)
1809 			buf = get_var_or_byte(buf, opcode & 0x80);
1810 		else
1811 			buf = get_var_or_word(buf, opcode & 0x80);
1812 	}
1813 	strecpy(buf, ";");
1814 }
1815 
do_matrix_ops(char * buf,byte opcode)1816 void do_matrix_ops(char *buf, byte opcode) {
1817 	opcode = get_byte();
1818 
1819 	switch (opcode & 0x1F) {
1820 	case 0x1:
1821 		do_tok(buf, "setBoxFlags", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
1822 		break;
1823 	case 0x2:
1824 		do_tok(buf, "setBoxScale", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
1825 		break;
1826 	case 0x3:
1827 		do_tok(buf, "SetBoxSlot", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
1828 		break;
1829 	case 0x4:
1830 		do_tok(buf, "createBoxMatrix", 0);
1831 		break;
1832 	default:
1833 		sprintf(buf, "SetBoxUnknown%.2X;", opcode);
1834 	}
1835 }
1836 
next_line_V12(char * buf)1837 void next_line_V12(char *buf) {
1838 	byte opcode = get_byte();
1839 
1840 	switch (opcode) {
1841 
1842 	case 0x58:
1843 		do_tok(buf, "beginOverride", 0);
1844 		break;
1845 	case 0x52:
1846 	case 0xD2:
1847 		do_tok(buf, "actorFollowCamera", ((opcode & 0x80) ? A1V : A1B));
1848 		break;
1849 	case 0x15:
1850 	case 0x55:
1851 	case 0x95:
1852 	case 0xD5:
1853 		do_tok(buf, "actorFromPos",
1854 					 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | AVARSTORE);
1855 		break;
1856 	case 0x13:
1857 	case 0x53:
1858 	case 0x93:
1859 	case 0xD3:
1860 		// actorSet
1861 		do_actorops_v12(buf, opcode);
1862 		break;
1863 
1864 	case 0x2A:
1865 	case 0xAA:
1866 		// addDirect
1867 	case 0x3A:
1868 	case 0xBA:
1869 		//subtract
1870 	case 0x6A:
1871 	case 0xEA:
1872 		//subDirect
1873 	case 0x0A:
1874 	case 0x8A:
1875 		// assignVarWordDirect
1876 	case 0x1A:
1877 	case 0x5A:
1878 	case 0x9A:
1879 	case 0xDA:
1880 		do_varset_code(buf, opcode);
1881 		break;
1882 
1883 	case 0x11:
1884 	case 0x51:
1885 	case 0x91:
1886 	case 0xD1:
1887 		// animateActor
1888 		do_tok(buf, "animateActor", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
1889 		break;
1890 	case 0x2C:
1891 		// assignVarByte
1892 		do_varset_code(buf, opcode);
1893 		break;
1894 	case 0x80:
1895 		do_tok(buf, "breakHere", 0);
1896 		break;
1897 	case 0x4A:
1898 	case 0xCA:
1899 		do_tok(buf, "chainScript", ((opcode & 0x80) ? A1V : A1B));
1900 		break;
1901 
1902 	case 0x60:
1903 	case 0xE0:
1904 		//do_tok(buf, "cursorCommand", ((opcode & 0x80) ? A1V : A1W));
1905 		if (opcode & 0x80) {
1906 			char tmp[256];
1907 			get_var(tmp);
1908 			buf += sprintf(buf, "cursorCommand(Hi(%s), Lo(%s));", tmp, tmp);
1909 		} else {
1910 			int val = get_word();
1911 			buf += sprintf(buf, "cursorCommand(%d, %d);", (val >> 8) & 0xFF, val & 0xFF);
1912 		}
1913 
1914 		break;
1915 	case 0x40:
1916 		sprintf(buf, "cutscene();");
1917 		break;
1918 	case 0xC0:
1919 		sprintf(buf, "endCutscene();");
1920 		break;
1921 
1922 	case 0x46:
1923 	case 0xC6:
1924 		// increment / decrement
1925 		do_varset_code(buf, opcode);
1926 		break;
1927 
1928 	case 0x2E: {
1929 		//delay
1930 		int d = get_byte();
1931 		d |= get_byte() << 8;
1932 		d |= get_byte() << 16;
1933 		d = 0xFFFFFF - d;
1934 		sprintf(buf, "delay(%d);", d);
1935 		break;
1936 	}
1937 
1938 	case 0x2B:
1939 		do_tok(buf, "delayVariable", A1V);
1940 		break;
1941 
1942 	case 0x19:
1943 	case 0x39:
1944 	case 0x59:
1945 	case 0x79:
1946 	case 0x99:
1947 	case 0xB9:
1948 	case 0xD9:
1949 	case 0xF9:{
1950 			buf = strecpy(buf, "doSentence(");
1951 			if (!(opcode & 0x80) && *g_scriptCurPos == 0xFC) {
1952 				strcpy(buf, "STOP);");
1953 				g_scriptCurPos++;
1954 			} else if (!(opcode & 0x80) && *g_scriptCurPos == 0xFB) {
1955 				strcpy(buf, "RESET);");
1956 				g_scriptCurPos++;
1957 			} else {
1958 				do_tok(buf, "",
1959 							 ANOFIRSTPAREN | ((opcode & 0x80) ? A1V : A1B) |
1960 							 ((opcode & 0x40) ? A2V : A2W) | ((opcode & 0x20) ? A3V : A3W) | A4B);
1961 			}
1962 		}
1963 		break;
1964 
1965 	case 0x05:
1966 	case 0x25:
1967 	case 0x45:
1968 	case 0x65:
1969 	case 0x85:
1970 	case 0xA5:
1971 	case 0xC5:
1972 	case 0xE5:
1973 		//drawObject
1974 		buf = do_tok(buf, "drawObject",
1975 					 ((opcode & 0x80) ? A1V : A1W) |
1976 					 ((opcode & 0x40) ? A2V : A2B) |
1977 					 ((opcode & 0x20) ? A3V : A3B));
1978 		break;
1979 	case 0xAC:
1980 		//drawSentence
1981 		do_tok(buf, "drawSentence", 0);
1982 		break;
1983 	case 0x5C:
1984 	case 0x6B:
1985 	case 0x6E:
1986 	case 0xAB:
1987 	case 0xDC:
1988 	case 0xEB:
1989 	case 0xEE:
1990 		//dummy
1991 		sprintf(buf, "dummy(%.2X);", opcode);
1992 
1993 		break;
1994 
1995 	case 0x09:
1996 	case 0x49:
1997 	case 0x89:
1998 	case 0xC9:
1999 		do_tok(buf, "faceActor", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
2000 		break;
2001 	case 0x35:
2002 	case 0x75:
2003 	case 0xB5:
2004 	case 0xF5:
2005 		do_tok(buf, "findObject",
2006 					 AVARSTORE | ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
2007 		break;
2008 	case 0x71:
2009 	case 0xF1:
2010 		do_tok(buf, "getActorCostume", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2011 		break;
2012 	case 0x06:
2013 	case 0x86:
2014 		do_tok(buf, "getActorElevation", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2015 		break;
2016 	case 0x63:
2017 	case 0xE3:
2018 		do_tok(buf, "getActorFacing", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2019 		break;
2020 	case 0x56:
2021 	case 0xD6:
2022 		do_tok(buf, "getActorMoving", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2023 		break;
2024 	case 0x03:
2025 	case 0x83:
2026 		do_tok(buf, "getActorRoom", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2027 		break;
2028 	case 0x7B:
2029 	case 0xFB:
2030 		do_tok(buf, "getActorWalkBox", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2031 		break;
2032 	case 0x43:
2033 	case 0xC3:
2034 		do_tok(buf, "getActorX", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2035 		break;
2036 
2037 	case 0x23:
2038 	case 0xA3:
2039 		do_tok(buf, "getActorY", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2040 		break;
2041 
2042 	case 0x31:
2043 	case 0xB1:
2044 		do_tok(buf, "getBitVar", AVARSTORE | A1W | ((opcode & 0x80) ? A2V : A2B));
2045 		break;
2046 
2047 	case 0x1B:
2048 	case 0x5B:
2049 	case 0x9B:
2050 	case 0xDB:
2051 		do_tok(buf, "setBitVar", A1W | ((opcode & 0x80) ? A2V : A2B) | ((opcode & 0x40) ? A3V : A3B));
2052 		break;
2053 
2054 	case 0x66:
2055 	case 0xE6:
2056 		do_tok(buf, "getClosestObjActor", AVARSTORE | ((opcode & 0x80) ? A1V : A1W));
2057 		break;
2058 
2059 	case 0x34:
2060 	case 0x74:
2061 	case 0xB4:
2062 	case 0xF4:
2063 		do_tok(buf, "getDist",
2064 					 AVARSTORE | ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2W));
2065 		break;
2066 	case 0x10:
2067 	case 0x90:
2068 		do_tok(buf, "getObjectOwner", AVARSTORE | ((opcode & 0x80) ? A1V : A1W));
2069 		break;
2070 	case 0x6C:
2071 	case 0xEC:
2072 		do_tok(buf, "getObjPreposition", AVARSTORE | ((opcode & 0x80) ? A1V : A1W));
2073 		break;
2074 	case 0x16:
2075 	case 0x96:
2076 		do_tok(buf, "getRandomNr", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2077 		break;
2078 
2079 	case 0x1D:
2080 	case 0x5D:
2081 	case 0x9D:
2082 	case 0xDD:
2083 		//ifClassOfIs
2084 		do_tok(buf, "classOfIs", ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2B) | ATO | ATOWITHLASTPAREN);
2085 		break;
2086 
2087 	case 0x3F:
2088 	case 0xBF:
2089 		//ifNotState01
2090 	case 0x5F:
2091 	case 0xDF:
2092 		//ifNotState02
2093 	case 0x2F:
2094 	case 0xAF:
2095 		//ifNotState04
2096 	case 0x0F:
2097 	case 0x8F:
2098 		//ifNotState08
2099 	case 0x7F:
2100 	case 0xFF:
2101 		//ifState01
2102 	case 0x1F:
2103 	case 0x9F:
2104 		//ifState02
2105 	case 0x6F:
2106 	case 0xEF:
2107 		//ifState04
2108 	case 0x4F:
2109 	case 0xCF:
2110 		//ifState08
2111 		do_if_state_code(buf, opcode);
2112 		break;
2113 
2114 	case 0x48:
2115 	case 0xC8:
2116 		//isEqual
2117 	case 0x78:
2118 	case 0xF8:
2119 		//isGreater
2120 	case 0x04:
2121 	case 0x84:
2122 		//isGreaterEqual
2123 	case 0x44:
2124 	case 0xC4:
2125 		//isLess
2126 	case 0x08:
2127 	case 0x88:
2128 		//isNotEqual
2129 	case 0x38:
2130 	case 0xB8:
2131 		//lessOrEqual
2132 	case 0x28:
2133 		//equalZero
2134 	case 0xA8:
2135 		//notEqualZero
2136 		do_if_code(buf, opcode);
2137 		break;
2138 
2139 	case 0x68:
2140 	case 0xE8:
2141 		do_tok(buf, "isScriptRunning", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2142 		break;
2143 	case 0x7C:
2144 	case 0xFC:
2145 		do_tok(buf, "isSoundRunning", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2146 		break;
2147 
2148 	case 0x18:
2149 		do_unconditional_jump(buf);
2150 		break;
2151 
2152 	case 0x70:
2153 	case 0xF0:
2154 		buf = do_tok(buf, "lights", ((opcode & 0x80) ? A1V : A1B) | A2B | A3B);
2155 		break;
2156 	case 0x72:
2157 	case 0xF2:
2158 		do_tok(buf, "loadRoom", ((opcode & 0x80) ? A1V : A1B));
2159 		break;
2160 
2161 	case 0x24:
2162 	case 0x64:
2163 	case 0xA4:
2164 	case 0xE4:
2165 		//loadRoomWithEgo
2166 		buf =
2167 			do_tok(buf, "loadRoomWithEgo",
2168 						 ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2B) | ANOLASTPAREN | ANOENDSEMICOLON);
2169 		do_tok(buf, NULL, A1B | A2B | ANOFIRSTPAREN | ASTARTCOMMA);
2170 		break;
2171 
2172 	case 0x30:
2173 	case 0xB0:
2174 		do_tok(buf, "setBoxFlags", ((opcode & 0x80) ? A1V : A1B) | A2B);
2175 		break;
2176 
2177 	case 0x12:
2178 	case 0x92:
2179 		//panCameraTo
2180 		do_tok(buf, "panCameraTo", ((opcode & 0x80) ? A1V : A1B));
2181 		break;
2182 	case 0x50:
2183 	case 0xD0:
2184 		//pickupObject
2185 		do_tok(buf, "pickupObject", ((opcode & 0x80) ? A1V : A1W));
2186 		break;
2187 	case 0x14:
2188 	case 0x94:
2189 		// print
2190 		buf += sprintf(buf, "print(");
2191 		buf = get_var_or_byte(buf, (opcode & 0x80));
2192 		buf += sprintf(buf, ",\"");
2193 		do_decodeparsestring_v2(buf, opcode);
2194 		strcat(buf, "\");");
2195 		break;
2196 	case 0xD8:
2197 		//printEgo
2198 		buf += sprintf(buf, "printEgo(\"");
2199 		do_decodeparsestring_v2(buf, opcode);
2200 		strcat(buf, "\");");
2201 		break;
2202 
2203 	case 0xCC:
2204 		// pseudoRoom
2205 		do_pseudoRoom(buf);
2206 		break;
2207 	case 0x01:
2208 	case 0x21:
2209 	case 0x41:
2210 	case 0x61:
2211 	case 0x81:
2212 	case 0xA1:
2213 	case 0xC1:
2214 	case 0xE1:
2215 		do_tok(buf, "putActor",
2216 					 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) |
2217 					 ((opcode & 0x20) ? A3V : A3B));
2218 		break;
2219 	case 0x0E:
2220 	case 0x4E:
2221 	case 0x8E:
2222 	case 0xCE:
2223 		//putActorAtObject
2224 		do_tok(buf, "putActorAtObject", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2W) );
2225 		break;
2226 	case 0x2D:
2227 	case 0x6D:
2228 	case 0xAD:
2229 	case 0xED:
2230 		do_tok(buf, "putActorInRoom", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
2231 		break;
2232 	case 0x0C:
2233 	case 0x8C:
2234 		//resourceRoutines
2235 		do_resource_v2(buf, opcode);
2236 		break;
2237 	case 0x98:
2238 		do_tok(buf, "restart", 0);
2239 		break;
2240 
2241 	case 0x33:
2242 	case 0x73:
2243 	case 0xB3:
2244 	case 0xF3:
2245 		do_room_ops_old(buf, opcode);
2246 		break;
2247 
2248 	case 0x22:
2249 	case 0xA2:
2250 		do_tok(buf, "saveLoadGame", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2251 		break;
2252 
2253 	case 0x3D:
2254 	case 0x7D:
2255 	case 0xBD:
2256 	case 0xFD:
2257 		do_tok(buf, "setActorElevation", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
2258 		break;
2259 
2260 	case 0x32:
2261 	case 0xB2:
2262 		do_tok(buf, "setCameraAt", ((opcode & 0x80) ? A1V : A1B));
2263 		break;
2264 
2265 	case 0x54:
2266 	case 0xD4:
2267 		do_tok(buf, "setObjectName", ((opcode & 0x80) ? A1V : A1W) | A2ASCII);
2268 		break;
2269 
2270 	case 0x0B:
2271 	case 0x4B:
2272 	case 0x8B:
2273 	case 0xCB:
2274 		do_tok(buf, "setObjPreposition", ((opcode & 0x80) ? A1V : A1W) | A2B);
2275 		break;
2276 	case 0x29:
2277 	case 0x69:
2278 	case 0xA9:
2279 	case 0xE9:
2280 		//setOwnerOf
2281 		do_tok(buf, "setOwnerOf", ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2B));
2282 		break;
2283 
2284 	case 0x77:
2285 	case 0xF7:
2286 		// clearState01
2287 		do_tok(buf, "clearState01", ((opcode & 0x80) ? A1V : A1W));
2288 		break;
2289 	case 0x17:
2290 	case 0x97:
2291 		// clearState02
2292 		do_tok(buf, "clearState02", ((opcode & 0x80) ? A1V : A1W));
2293 		break;
2294 	case 0x67:
2295 	case 0xE7:
2296 		// clearState04
2297 		do_tok(buf, "clearState04", ((opcode & 0x80) ? A1V : A1W));
2298 		break;
2299 	case 0x47:
2300 	case 0xC7:
2301 		// clearState08
2302 		do_tok(buf, "clearState08", ((opcode & 0x80) ? A1V : A1W));
2303 		break;
2304 
2305 	case 0x37:
2306 	case 0xB7:
2307 		//setState01
2308 		do_tok(buf, "setState01", ((opcode & 0x80) ? A1V : A1W));
2309 		break;
2310 	case 0x57:
2311 	case 0xD7:
2312 		//setState02
2313 		do_tok(buf, "setState02", ((opcode & 0x80) ? A1V : A1W));
2314 		break;
2315 	case 0x27:
2316 	case 0xA7:
2317 		//setState04
2318 		do_tok(buf, "setState04", ((opcode & 0x80) ? A1V : A1W));
2319 		break;
2320 	case 0x07:
2321 	case 0x87:
2322 		//setState08
2323 		do_tok(buf, "setState08", ((opcode & 0x80) ? A1V : A1W));
2324 		break;
2325 
2326 	case 0x26:
2327 	case 0xA6: {
2328 			int i;
2329 			char first = 1;
2330 
2331 			buf = do_tok(buf, "setVarRange", A1V | ANOLASTPAREN | ANOENDSEMICOLON);
2332 			i = get_byte();
2333 
2334 			buf += sprintf(buf, ",%d,[", i);
2335 
2336 			while (i > 0) {
2337 				if (!first)
2338 					buf = strecpy(buf, ",");
2339 				first = 0;
2340 
2341 				buf += sprintf(buf, "%d", (opcode & 0x80) ? get_word() : get_byte());
2342 				i--;
2343 			}
2344 
2345 			strcpy(buf, "]);");
2346 
2347 		}
2348 		break;
2349 
2350 	case 0x02:
2351 	case 0x82:
2352 		do_tok(buf, "startMusic", ((opcode & 0x80) ? A1V : A1B));
2353 		break;
2354 	case 0x42:
2355 	case 0xC2:
2356 		//startScript
2357 		do_tok(buf, "startScript", ((opcode & 0x80) ? A1V : A1B));
2358 		break;
2359 
2360 	case 0x1C:
2361 	case 0x9C:
2362 		do_tok(buf, "startSound", ((opcode & 0x80) ? A1V : A1B));
2363 		break;
2364 
2365 	case 0x20:
2366 		do_tok(buf, "stopMusic", 0);
2367 		break;
2368 	case 0x00:
2369 	case 0xA0:
2370 		do_tok(buf, "stopObjectCode", 0);
2371 		break;
2372 	case 0x62:
2373 	case 0xE2:
2374 		do_tok(buf, "stopScript", ((opcode & 0x80) ? A1V : A1B));
2375 		break;
2376 
2377 	case 0x3C:
2378 	case 0xBC:
2379 		do_tok(buf, "stopSound", ((opcode & 0x80) ? A1V : A1B));
2380 		break;
2381 
2382 	case 0x7A:
2383 	case 0xFA:
2384 		// verbOps
2385 		do_verbops_v2(buf, opcode);
2386 		break;
2387 
2388 	case 0x3B:
2389 	case 0xBB:
2390 		do_tok(buf, "waitForActor", ((opcode & 0x80) ? A1V : A1B));
2391 		break;
2392 
2393 	case 0x4C:
2394 		do_tok(buf, "waitForSentence", 0);
2395 		break;
2396 
2397 	case 0xAE:
2398 		do_tok(buf, "waitForMessage", 0);
2399 		break;
2400 	case 0x1E:
2401 	case 0x3E:
2402 	case 0x5E:
2403 	case 0x7E:
2404 	case 0x9E:
2405 	case 0xBE:
2406 	case 0xDE:
2407 	case 0xFE:
2408 		do_tok(buf, "walkActorTo",
2409 					 ((opcode & 0x80) ? A1V : A1B) |
2410 					 ((opcode & 0x40) ? A2V : A2B) |
2411 					 ((opcode & 0x20) ? A3V : A3B));
2412 		break;
2413 
2414 	case 0x0D:
2415 	case 0x4D:
2416 	case 0x8D:
2417 	case 0xCD:
2418 		do_tok(buf, "walkActorToActor",
2419 					 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | A3B);
2420 		break;
2421 	case 0x36:
2422 	case 0x76:
2423 	case 0xB6:
2424 	case 0xF6:
2425 		do_tok(buf, "walkActorToObject", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2W));
2426 		break;
2427 
2428 	default:
2429 		error("Unknown opcode %.2X", opcode);
2430 	}
2431 }
2432 
next_line_V0(char * buf)2433 void next_line_V0(char *buf) {
2434 	byte opcode = get_byte();
2435 
2436 	switch (opcode) {
2437 	case 0x05:
2438 	case 0x09:
2439 	case 0x0A:
2440 	case 0x19:
2441 	case 0x23:
2442 	case 0x2C:
2443 	case 0x35:
2444 	case 0x39:
2445 	case 0x3B:
2446 	case 0x45:
2447 	case 0x49:
2448 	case 0x59:
2449 	case 0x63:
2450 	case 0x65:
2451 	case 0x6A:
2452 	case 0x6C:
2453 	case 0x79:
2454 	case 0x7A:
2455 	case 0x7B:
2456 	case 0x80:
2457 	case 0x82:
2458 	case 0x85:
2459 	case 0x89:
2460 	case 0x8A:
2461 	case 0x8D:
2462 	case 0x96:
2463 	case 0x99:
2464 	case 0xA3:
2465 	case 0xA6:
2466 	case 0xAA:
2467 	case 0xAC:
2468 	case 0xB5:
2469 	case 0xB9:
2470 	case 0xBB:
2471 	case 0xC5:
2472 	case 0xC9:
2473 	case 0xD8:
2474 	case 0xD9:
2475 	case 0xE3:
2476 	case 0xE6:
2477 	case 0xEA:
2478 	case 0xEC:
2479 	case 0xF5:
2480 	case 0xF9:
2481 	case 0xFA:
2482 	case 0xFB:
2483 		do_tok(buf, "stopCurrentScript", 0);
2484 		break;
2485 
2486 	case 0x67:
2487 	case 0xE7:
2488 		do_tok(buf, "getActorFacing", AVARSTORE | A1B | ((opcode & 0x80) ? A2V : A2B));
2489 		break;
2490 
2491 	case 0x31:
2492 	case 0x71:
2493 	case 0xB1:
2494 	case 0xF1:
2495 		do_tok(buf, "getBitVar", AVARSTORE | ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
2496 		break;
2497 
2498 	case 0x1D:
2499 	case 0x3D:
2500 	case 0x5D:
2501 	case 0x7D:
2502 	case 0x9D:
2503 	case 0xBD:
2504 	case 0xDD:
2505 	case 0xFD:
2506 		do_tok(buf, "setBitVar", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | ((opcode & 0x20) ? A3V : A3B));
2507 		break;
2508 
2509 	case 0x1B:
2510 	case 0x5B:
2511 	case 0x9B:
2512 	case 0xDB:
2513 		do_tok(buf, "getActorBitVar", AVARSTORE | ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
2514 		break;
2515 
2516 	case 0x0B:
2517 	case 0x2B:
2518 	case 0x4B:
2519 	case 0x6B:
2520 	case 0x8B:
2521 	case 0xAB:
2522 	case 0xCB:
2523 	case 0xEB:
2524 		do_tok(buf, "setActorBitVar", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | ((opcode & 0x20) ? A3V : A3B));
2525 		break;
2526 
2527 	case 0x58:
2528 		do_tok(buf, "beginOverride", 0);
2529 		get_byte();
2530 		get_byte();
2531 		get_byte();
2532 		break;
2533 	case 0x52:
2534 	case 0xD2:
2535 		do_tok(buf, "actorFollowCamera", ((opcode & 0x80) ? A1V : A1B));
2536 		break;
2537 	case 0x95:
2538 	case 0xD5:
2539 		do_tok(buf, "actorFromPos",
2540 					 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | AVARSTORE);
2541 		break;
2542 	case 0x15:
2543 	case 0x55:
2544 		do_tok(buf, "walkActorToActor",
2545 					 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | A3B);
2546 		break;											/* arg1=actor, arg2=actor */
2547 	case 0x13:
2548 		do_tok(buf, "lockCostume", A1B);
2549 		break;
2550 	case 0x4D:
2551 		do_tok(buf, "lockRoom", A1B);
2552 		break;
2553 	case 0xCD:
2554 		do_tok(buf, "unlockRoom", A1B);
2555 		break;
2556 	case 0x93:
2557 		do_tok(buf, "unlockCostume", A1B);
2558 		break;
2559 	case 0x1A:
2560 	case 0x9a:
2561 		//move
2562 	case 0x5A:
2563 	case 0xDA:
2564 		//add;
2565 	case 0x3A:
2566 	case 0xBA:
2567 		//subtract
2568 		do_varset_code(buf, opcode);
2569 		break;
2570 
2571 	case 0x11:
2572 	case 0x51:
2573 	case 0x91:
2574 	case 0xD1:
2575 		buf = do_tok(buf, "animateActor", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | A3B);
2576 		break;
2577 	case 0x10:
2578 		do_tok(buf, "breakHere", 0);
2579 		break;
2580 	case 0x4A:
2581 	case 0xCA:
2582 		do_tok(buf, "loadRoom_c64", ((opcode & 0x80) ? A1V : A1B));
2583 		break;
2584 
2585 	case 0x60:
2586 	case 0xE0:
2587 		//cursorCommand
2588 		do_tok(buf, "cursorCommand", ((opcode & 0x80) ? A1V : A1B));
2589 		break;
2590 	case 0x40:
2591 		do_tok(buf, "cutscene", 0);
2592 		break;
2593 	case 0xC0:
2594 		do_tok(buf, "endCutscene", 0);
2595 		break;
2596 
2597 	case 0x46:
2598 	case 0xC6:
2599 		// increment / decrement
2600 		do_varset_code(buf, opcode);
2601 		break;
2602 
2603 	case 0x2A: {
2604 		//delay
2605 		int d = get_byte();
2606 		d |= get_byte() << 8;
2607 		d |= get_byte() << 16;
2608 		d = 0xFFFFFF - d;
2609 		sprintf(buf, "delay(%d);", d);
2610 		break;
2611 	}
2612 
2613 	case 0x50:
2614 	case 0x72:
2615 	case 0xD0:
2616 	case 0xF2:
2617 		do_tok(buf, "nop", 0);
2618 		break;
2619 	case 0x14:
2620 	case 0x94:
2621 		// print
2622 		buf += sprintf(buf, "print(");
2623 		buf = get_var_or_byte(buf, (opcode & 0x80));
2624 		buf += sprintf(buf, ",\"");
2625 		do_decodeparsestring_v2(buf, opcode);
2626 		strcat(buf, "\");");
2627 		break;
2628 	case 0x75:
2629 		//printEgo
2630 		buf += sprintf(buf, "printEgo(\"");
2631 		do_decodeparsestring_v2(buf, opcode);
2632 		strcat(buf, "\");");
2633 		break;
2634 	case 0x2E:
2635 	case 0xAE:
2636 		// print_c64
2637 		buf += sprintf(buf, "print_c64(");
2638 		buf = get_var_or_byte(buf, (opcode & 0x80));
2639 		buf += sprintf(buf, ",\"");
2640 		do_decodeparsestring_v2(buf, opcode);
2641 		strcat(buf, "\");");
2642 		break;
2643 	case 0x0D:
2644 		//printEgo_c64
2645 		buf += sprintf(buf, "printEgo_c64(\"");
2646 		do_decodeparsestring_v2(buf, opcode);
2647 		strcat(buf, "\");");
2648 		break;
2649 
2650 	case 0x2D:
2651 	case 0x6D:
2652 	case 0xAD:
2653 	case 0xED:
2654 		do_tok(buf, "putActorInRoom", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
2655 		break;
2656 	case 0xE5:
2657 		do_tok(buf, "loadRoomWithEgo", A1B | A2B);
2658 		break;
2659 	case 0x6E:
2660 		do_tok(buf, "screenPrepare", 0);
2661 		break;
2662 	case 0xEE:
2663 		//dummy
2664 		sprintf(buf, "dummy%.2X();", opcode);
2665 		break;
2666 
2667 	case 0x86:
2668 		do_tok(buf, "bad", 0);
2669 		break;
2670 	case 0x56:
2671 	case 0xD6:
2672 		do_tok(buf, "getActorMoving", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2673 		break;
2674 	case 0x03:
2675 	case 0x43:
2676 	case 0x83:
2677 	case 0xC3:
2678 		do_sentence(buf, opcode);
2679 		break;
2680 	case 0x07:
2681 	case 0x87:
2682 		do_tok(buf, "getActorRoom", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2683 		break;
2684 	case 0x47:
2685 	case 0xC7:
2686 		do_tok(buf, "getActorX", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2687 		break;
2688 
2689 	case 0x27:
2690 	case 0xA7:
2691 		do_tok(buf, "getActorY", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2692 		break;
2693 
2694 	case 0x26:
2695 		do_tok(buf, "getClosestObjActor7", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2696 		break;
2697 	case 0x66:
2698 		do_tok(buf, "getClosestObjActor25", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2699 		break;
2700 
2701 	case 0x06:
2702 	case 0x34:
2703 	case 0x74:
2704 	case 0xB4:
2705 	case 0xF4:
2706 		do_tok(buf, "getDist",
2707 					 AVARSTORE | ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
2708 		break;
2709 	case 0x90:
2710 		do_tok(buf, "pickupObject", A1B);
2711 		break;
2712 	case 0x16:
2713 		do_tok(buf, "getRandomNr", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2714 		break;
2715 
2716 	case 0x0f:
2717 	case 0x4f:
2718 		do_tok(buf, "clearState02", ((opcode & 0x40) ? 0 : A1B));
2719 		break;
2720 	case 0x37:
2721 	case 0x77:
2722 		do_tok(buf, "clearState04", ((opcode & 0x40) ? 0 : A1B));
2723 		break;
2724 	case 0x17:
2725 	case 0x57:
2726 		do_tok(buf, "clearState08", ((opcode & 0x40) ? 0 : A1B));
2727 		break;
2728 	case 0x8f:
2729 	case 0xcf:
2730 		do_tok(buf, "setState02", ((opcode & 0x40) ? 0 : A1B));
2731 		break;
2732 	case 0xb7:
2733 	case 0xf7:
2734 		do_tok(buf, "setState04", ((opcode & 0x40) ? 0 : A1B));
2735 		break;
2736 	case 0x97:
2737 	case 0xd7:
2738 		do_tok(buf, "setState08", ((opcode & 0x40) ? 0 : A1B));
2739 		break;
2740 
2741 	case 0x3f:
2742 	case 0xff:
2743 		//ifState02;
2744 	case 0x1f:
2745 	case 0x5f:
2746 		//ifState04;
2747 	case 0x2f:
2748 	case 0x6f:
2749 		//ifState08;
2750 	case 0x7f:
2751 	case 0xbf:
2752 		//ifNotState02;
2753 	case 0x9f:
2754 	case 0xdf:
2755 		//ifNotState04;
2756 	case 0xaf:
2757 	case 0xef:
2758 		//ifNotState08;
2759 		do_if_state_code(buf, opcode);
2760 		break;
2761 
2762 	case 0x48:
2763 	case 0xC8:
2764 		//isEqual
2765 	case 0x78:
2766 	case 0xF8:
2767 		//isGreater
2768 	case 0x04:
2769 	case 0x84:
2770 		//isGreaterEqual
2771 	case 0x44:
2772 	case 0xC4:
2773 		//isLess
2774 	case 0x08:
2775 	case 0x88:
2776 		//isNotEqual
2777 	case 0x38:
2778 	case 0xB8:
2779 		//lessOrEqual
2780 	case 0x28:
2781 		//equalZero
2782 	case 0xA8:
2783 		//notEqualZero
2784 		do_if_code(buf, opcode);
2785 		break;
2786 
2787 	case 0x68:
2788 	case 0xE8:
2789 		do_tok(buf, "isScriptRunning", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2790 		break;
2791 	case 0x7C:
2792 	case 0xFC:
2793 		do_tok(buf, "isSoundRunning", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2794 		break;
2795 
2796 	case 0x53:
2797 		do_tok(buf, "lockSound", A1B);
2798 		break;
2799 
2800 	case 0xD3:
2801 		do_tok(buf, "unlockSound", A1B);
2802 		break;
2803 
2804 	case 0x18:
2805 		do_unconditional_jump(buf);
2806 		break;
2807 
2808 	case 0x70:
2809 	case 0xF0:
2810 		buf = do_tok(buf, "lights", ((opcode & 0x80) ? A1V : A1B));
2811 		break;
2812 	case 0x25:
2813 	case 0xA5:
2814 		do_tok(buf, "loadRoom", ((opcode & 0x80) ? A1V : A1B));
2815 		break;
2816 
2817 	case 0x24:
2818 	case 0xA4:
2819 		do_tok(buf, "unknown2", A1B);
2820 		break;
2821 	case 0x64:
2822 	case 0xE4:
2823 		do_if_active_object(buf, opcode);
2824 		break;
2825 
2826 	case 0x30:
2827 	case 0xB0:
2828 		do_tok(buf, "loadCostume", ((opcode & 0x80) ? A1V : A1B));
2829 		break;
2830 
2831 	case 0x12:
2832 	case 0x92:
2833 		//panCameraTo
2834 		do_tok(buf, "panCameraTo", ((opcode & 0x80) ? A1V : A1B));
2835 		break;
2836 
2837 	case 0x01:
2838 	case 0x21:
2839 	case 0x41:
2840 	case 0x61:
2841 	case 0x81:
2842 	case 0xA1:
2843 	case 0xC1:
2844 	case 0xE1:
2845 		do_tok(buf, "putActor",
2846 					 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) |
2847 					 ((opcode & 0x20) ? A3V : A3B));
2848 		break;
2849 	case 0x4E:
2850 	case 0xCE:
2851 	case 0x0E:
2852 	case 0x8E:
2853 		do_put_actor_at_object(buf, opcode);
2854 		break;
2855 	case 0x0C:
2856 	case 0x8C:
2857 		do_tok(buf, "loadSound", A1B);
2858 		break;
2859 	case 0x98:
2860 		do_tok(buf, "restart", 0);
2861 		break;
2862 
2863 	case 0x33:
2864 		do_tok(buf, "lockScript", A1B);
2865 		break;
2866 	case 0xB3:
2867 		do_tok(buf, "unlockScript", A1B);
2868 		break;
2869 	case 0x73:
2870 	case 0xF3:
2871 		do_tok(buf, "getObjectOwner", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2872 		break;
2873 
2874 	case 0x22:
2875 	case 0xA2:
2876 		do_tok(buf, "saveLoadGame", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2877 		break;
2878 
2879 	case 0x32:
2880 	case 0xB2:
2881 		do_tok(buf, "setCameraAt", ((opcode & 0x80) ? A1V : A1B));
2882 		break;
2883 
2884 	case 0x54:
2885 	case 0xD4:
2886 		do_set_object_name(buf, opcode);
2887 		break;
2888 
2889 	case 0x29:
2890 	case 0x69:
2891 	case 0xA9:
2892 	case 0xE9:
2893 		//setOwnerOf
2894 		do_tok(buf, "setOwnerOf", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
2895 		break;
2896 
2897 	case 0x02:
2898 		do_tok(buf, "startMusic", ((opcode & 0x80) ? A1V : A1B));
2899 		break;
2900 	case 0x42:
2901 	case 0xC2:
2902 		//startScript
2903 		do_tok(buf, "startScript", ((opcode & 0x80) ? A1V : A1B));
2904 		break;
2905 
2906 	case 0x1C:
2907 	case 0x5C:
2908 	case 0x9C:
2909 	case 0xDC:
2910 		do_tok(buf, "startSound", ((opcode & 0x80) ? A1V : A1B));
2911 		break;
2912 
2913 	case 0x20:
2914 		do_tok(buf, "stopMusic", 0);
2915 		break;
2916 	case 0x00:
2917 	case 0xA0:
2918 		do_tok(buf, "stopObjectCode", 0);
2919 		break;
2920 	case 0x62:
2921 	case 0xE2:
2922 		do_tok(buf, "stopScript", ((opcode & 0x80) ? A1V : A1B));
2923 		break;
2924 
2925 	case 0x3C:
2926 	case 0xBC:
2927 		do_tok(buf, "stopSound", ((opcode & 0x80) ? A1V : A1B));
2928 		break;
2929 
2930 	case 0x4C:
2931 	case 0xCC:
2932 		do_tok(buf, "loadScript", ((opcode & 0x80) ? A1V : A1B));
2933 		break;
2934 
2935 	case 0x1E:
2936 	case 0x3E:
2937 	case 0x5E:
2938 	case 0x7E:
2939 	case 0x9E:
2940 	case 0xBE:
2941 	case 0xDE:
2942 	case 0xFE:
2943 		do_tok(buf, "walkActorTo",
2944 					 ((opcode & 0x80) ? A1V : A1B) |
2945 					 ((opcode & 0x40) ? A2V : A2B) |
2946 					 ((opcode & 0x20) ? A3V : A3B));
2947 		break;
2948 
2949 	case 0x36:
2950 	case 0xB6:
2951 	case 0x76:
2952 	case 0xF6:
2953 		do_walk_actor_to_object(buf, opcode);
2954 		break;
2955 
2956 	default:
2957 		error("Unknown opcode %.2X", opcode);
2958 	}
2959 }
2960 
next_line_V345(char * buf)2961 void next_line_V345(char *buf) {
2962 	byte opcode = get_byte();
2963 
2964 	switch (opcode) {
2965 
2966 	case 0x00:
2967 	case 0xA0:
2968 		do_tok(buf, "stopObjectCode", 0);
2969 		break;
2970 
2971 	case 0x01:
2972 	case 0x21:
2973 	case 0x41:
2974 	case 0x61:
2975 	case 0x81:
2976 	case 0xA1:
2977 	case 0xC1:
2978 	case 0xE1:
2979 		do_tok(buf, "putActor",
2980 					 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2W) |
2981 					 ((opcode & 0x20) ? A3V : A3W));
2982 		break;
2983 
2984 	case 0x15:
2985 	case 0x55:
2986 	case 0x95:
2987 	case 0xD5:
2988 		do_tok(buf, "actorFromPos",
2989 					 ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2W) | AVARSTORE);
2990 		break;
2991 
2992 	case 0x03:
2993 	case 0x83:
2994 		do_tok(buf, "getActorRoom", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
2995 		break;
2996 
2997 
2998 	case 0x38:
2999 	case 0xB8:
3000 	case 0x04:
3001 	case 0x84:
3002 	case 0x08:
3003 	case 0x88:
3004 	case 0x48:
3005 	case 0xC8:
3006 	case 0x44:
3007 	case 0xC4:
3008 	case 0x78:
3009 	case 0xF8:
3010 	case 0x28:
3011 	case 0xA8:
3012 		do_if_code(buf, opcode);
3013 		break;
3014 
3015 	case 0x05:
3016 	case 0x45:
3017 	case 0x85:
3018 	case 0xC5:
3019 		if (g_options.scriptVersion == 5) {
3020 			buf = do_tok(buf, "drawObject", ((opcode & 0x80) ? A1V : A1W) | ANOLASTPAREN | ANOENDSEMICOLON);
3021 			opcode = get_byte();
3022 			switch (opcode & 0x1F) {
3023 			case 1:
3024 				do_tok(buf, "setXY",
3025 							 ASTARTCOMMA | ANOENDSEMICOLON | ((opcode & 0x80) ? A1V : A1W) |
3026 							 ((opcode & 0x40) ? A2V : A2W));
3027 				break;
3028 			case 2:
3029 				do_tok(buf, "setImage", ASTARTCOMMA | ANOENDSEMICOLON | ((opcode & 0x80) ? A1V : A1W));
3030 				break;
3031 			}
3032 			strcat(buf, ");");
3033 
3034 		} else {
3035 			buf = do_tok(buf, "drawObject",
3036 						 ((opcode & 0x80) ? A1V : A1W) |
3037 						 ((opcode & 0x40) ? A2V : A2W) |
3038 						 ((opcode & 0x20) ? A3V : A3W));
3039 		}
3040 		break;
3041 
3042 	case 0x25:
3043 	case 0x65:
3044 	case 0xA5:
3045 	case 0xE5:
3046 		if (g_options.scriptVersion == 5) {
3047 			do_tok(buf, "pickupObject", ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2B));
3048 		} else {
3049 			buf = do_tok(buf, "drawObject",
3050 						 ((opcode & 0x80) ? A1V : A1W) |
3051 						 ((opcode & 0x40) ? A2V : A2W) |
3052 						 ((opcode & 0x20) ? A3V : A3W));
3053 		}
3054 		break;
3055 
3056 	case 0x06:
3057 	case 0x86:
3058 		do_tok(buf, "getActorElevation", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3059 		break;
3060 
3061 	case 0x07:
3062 	case 0x47:
3063 	case 0x87:
3064 	case 0xC7:
3065 		do_tok(buf, "setState", ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2B));
3066 		break;
3067 
3068 	case 0x09:
3069 	case 0x49:
3070 	case 0x89:
3071 	case 0xC9:
3072 		do_tok(buf, "faceActor", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2W));
3073 		break;
3074 
3075 	case 0x0A:
3076 	case 0x8A:
3077 	case 0x2A:
3078 	case 0xAA:
3079 	case 0x4A:
3080 	case 0xCA:
3081 	case 0x6A:
3082 	case 0xEA:
3083 		buf = do_tok(buf, "startScript", ((opcode & 0x80) ? A1V : A1B) | A2LIST | ANOLASTPAREN | ANOENDSEMICOLON);
3084 		if (opcode & 0x20) { // freeze resistant
3085 			buf += sprintf(buf, ",F");
3086 		}
3087 		if (opcode & 0x40) { // recursive
3088 			buf += sprintf(buf, ",R");
3089 		}
3090 		buf += sprintf(buf, ");");
3091 		break;
3092 
3093 	case 0x0B:
3094 	case 0x4B:
3095 	case 0x8B:
3096 	case 0xCB:
3097 		do_tok(buf, "getVerbEntryPoint",
3098 					 AVARSTORE | ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2W));
3099 		break;
3100 
3101 	case 0x0c:
3102 	case 0x8C:
3103 		do_resource(buf, opcode);
3104 		break;
3105 
3106 	case 0x0D:
3107 	case 0x4D:
3108 	case 0x8D:
3109 	case 0xCD:
3110 		do_tok(buf, "walkActorToActor",
3111 					 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) | A3B);
3112 		break;											/* arg1=actor, arg2=actor */
3113 
3114 	case 0x0F:
3115 	case 0x8F:
3116 		if (g_options.scriptVersion == 5) {
3117 			do_tok(buf, "getObjectState", AVARSTORE | ((opcode & 0x80) ? A1V : A1W));
3118 			break;
3119 		}
3120 		// fall through
3121 	case 0x2F:
3122 	case 0x4F:
3123 	case 0x6F:
3124 	case 0xAF:
3125 	case 0xCF:
3126 	case 0xEF:
3127 		do_if_state_code(buf, opcode);
3128 		break;
3129 
3130 	case 0x10:
3131 	case 0x90:
3132 		do_tok(buf, "getObjectOwner", AVARSTORE | ((opcode & 0x80) ? A1V : A1W));
3133 		break;
3134 
3135 
3136 	case 0x14:
3137 	case 0xD8:
3138 	case 0x94:
3139 		do_print_ego(buf, opcode);
3140 		break;
3141 
3142 	case 0x17:
3143 	case 0x97:
3144 	case 0x1A:
3145 	case 0x9A:
3146 	case 0x1B:
3147 	case 0x9B:
3148 	case 0x3A:
3149 	case 0xBA:
3150 	case 0x46:
3151 	case 0x57:
3152 	case 0xD7:
3153 	case 0x5A:
3154 	case 0xDA:
3155 	case 0x5B:
3156 	case 0xDB:
3157 	case 0xC6:
3158 		do_varset_code(buf, opcode);
3159 		break;
3160 
3161 	case 0x18:
3162 		do_unconditional_jump(buf);
3163 		break;
3164 
3165 	case 0x1D:
3166 	case 0x9D:
3167 		do_tok(buf, "classOfIs", ((opcode & 0x80) ? A1V : A1W) | A2LIST | ATO | ATOWITHLASTPAREN);
3168 		break;											/* arg1=object; vararg=classes to test; arg3=jumpoffs */
3169 
3170 	case 0x1E:
3171 	case 0x3E:
3172 	case 0x5E:
3173 	case 0x7E:
3174 	case 0x9E:
3175 	case 0xBE:
3176 	case 0xDE:
3177 	case 0xFE:
3178 		do_tok(buf, "walkActorTo",
3179 					 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2W) |
3180 					 ((opcode & 0x20) ? A3V : A3W));
3181 		break;
3182 
3183 	case 0x24:
3184 	case 0x64:
3185 	case 0xA4:
3186 	case 0xE4:
3187 		buf =
3188 			do_tok(buf, "loadRoomWithEgo",
3189 						 ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2B) | ANOLASTPAREN | ANOENDSEMICOLON);
3190 		do_tok(buf, NULL, A1W | A2W | ANOFIRSTPAREN | ASTARTCOMMA);
3191 		break;
3192 
3193 	case 0x2C:
3194 		do_cursor_command(buf);
3195 		break;
3196 
3197 	case 0x40:
3198 		do_tok(buf, "cutscene", A1LIST);
3199 		break;
3200 
3201 	case 0x42:
3202 	case 0xC2:
3203 		do_tok(buf, "chainScript", ((opcode & 0x80) ? A1V : A1B) | A2LIST);
3204 		break;
3205 
3206 	case 0x56:
3207 	case 0xD6:
3208 		do_tok(buf, "getActorMoving", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3209 		break;
3210 	case 0x72:
3211 	case 0xF2:
3212 		do_tok(buf, "loadRoom", ((opcode & 0x80) ? A1V : A1B));
3213 		break;
3214 
3215 	case 0x63:
3216 	case 0xE3:
3217 		do_tok(buf, "getActorFacing", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3218 		break;
3219 
3220 	case 0x66:
3221 	case 0xE6:
3222 		do_tok(buf, "getClosestObjActor", AVARSTORE | ((opcode & 0x80) ? A1V : A1W));
3223 		break;
3224 
3225 	case 0x6C:
3226 	case 0xEC:
3227 		do_tok(buf, "getActorWidth", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3228 		break;
3229 
3230 	case 0x71:
3231 	case 0xF1:
3232 		do_tok(buf, "getActorCostume", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3233 		break;
3234 
3235 	case 0x3B:
3236 	case 0xBB:
3237 		if (g_options.IndyFlag)
3238 			do_tok(buf, "waitForActor", ((opcode & 0x80) ? A1V : A1B));
3239 		else
3240 			do_tok(buf, "getActorScale", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3241 		break;
3242 
3243 	case 0xAE:{
3244 			if (g_options.IndyFlag)
3245 				opcode = 2;
3246 			else
3247 				opcode = get_byte();
3248 
3249 			switch (opcode) {
3250 			case 0x01:
3251 			case 0x81:
3252 				do_tok(buf, "WaitForActor", ((opcode & 0x80) ? A1V : A1B));
3253 				break;
3254 			case 0x02:
3255 				do_tok(buf, "WaitForMessage", 0);
3256 				break;
3257 			case 0x03:
3258 				do_tok(buf, "WaitForCamera", 0);
3259 				break;
3260 			case 0x04:
3261 				do_tok(buf, "WaitForSentence", 0);
3262 				break;
3263 			default:
3264 				do_tok(buf, "UnknownWait", 0);
3265 			}
3266 		}
3267 		break;
3268 
3269 
3270 	case 0x34:
3271 	case 0x74:
3272 	case 0xB4:
3273 	case 0xF4:
3274 		do_tok(buf, "getDist",
3275 					 AVARSTORE | ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2W));
3276 		break;
3277 
3278 
3279 	case 0x36:
3280 	case 0x76:
3281 	case 0xB6:
3282 	case 0xF6:
3283 		do_tok(buf, "walkActorToObject", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2W));
3284 		break;
3285 
3286 	case 0x37:
3287 	case 0x77:
3288 	case 0xB7:
3289 	case 0xF7:
3290 		do_tok(buf, "startObject",
3291 					 ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2B) | A3LIST);
3292 		break;
3293 
3294 	case 0x19:
3295 	case 0x39:
3296 	case 0x59:
3297 	case 0x79:
3298 	case 0x99:
3299 	case 0xB9:
3300 	case 0xD9:
3301 	case 0xF9:{
3302 			buf = strecpy(buf, "doSentence(");
3303 			// FIXME: this is not exactly what ScummVM does...
3304 			if (!(opcode & 0x80) && (*g_scriptCurPos == 0xFE)) {
3305 				strcpy(buf, "STOP);");
3306 				g_scriptCurPos++;
3307 			} else {
3308 				do_tok(buf, "",
3309 							 ANOFIRSTPAREN | ((opcode & 0x80) ? A1V : A1B) |
3310 							 ((opcode & 0x40) ? A2V : A2W) | ((opcode & 0x20) ? A3V : A3W));
3311 			}
3312 		}
3313 		break;
3314 
3315 
3316 	case 0x62:
3317 	case 0xE2:
3318 		do_tok(buf, "stopScript", ((opcode & 0x80) ? A1V : A1B));
3319 		break;
3320 
3321 	case 0xAC:
3322 		do_expr_code(buf);
3323 		break;
3324 
3325 	case 0x11:
3326 	case 0x51:
3327 	case 0x91:
3328 	case 0xD1:
3329 		do_tok(buf, "animateCostume", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
3330 		break;
3331 
3332 	case 0x80:
3333 		do_tok(buf, "breakHere", 0);
3334 		break;
3335 
3336 	case 0xc0:
3337 		do_tok(buf, "endCutscene", 0);
3338 		break;
3339 
3340 	case 0x27:{									/* String management subcode */
3341 			switch ((opcode = get_byte()) & 0x1F) {
3342 			case 0x01:
3343 				do_load_code_to_string(buf, opcode);
3344 				break;
3345 			case 0x02:
3346 				do_tok(buf, "CopyString", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
3347 				break;
3348 			case 0x03:
3349 				do_tok(buf, "SetStringChar",
3350 							 ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) |
3351 							 ((opcode & 0x20) ? A3V : A3B));
3352 				break;									/* string(arg1)[arg2] = arg3 */
3353 			case 0x04:
3354 				do_tok(buf, "GetStringChar",
3355 							 AVARSTORE | ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
3356 				break;									/* arg1 = string(arg2)[arg3] */
3357 			case 0x05:
3358 				do_tok(buf, "CreateString", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
3359 				break;									/* arg1=index, arg2=size */
3360 			default:
3361 				do_tok(buf, "StringFuncUnknown", 0);
3362 			}
3363 		}
3364 		break;
3365 
3366 	case 0x13:
3367 	case 0x53:
3368 	case 0x93:
3369 	case 0xD3:
3370 		do_actorops(buf, opcode);
3371 		break;
3372 
3373 	case 0x20:
3374 		do_tok(buf, "stopMusic", 0);
3375 		break;
3376 
3377 	case 0x70:
3378 	case 0xF0:
3379 		buf = do_tok(buf, "lights", ((opcode & 0x80) ? A1V : A1B) | A2B | A3B);
3380 		break;
3381 
3382 	case 0x3F:
3383 	case 0x7F:
3384 	case 0xBF:
3385 	case 0xFF:
3386 		buf =
3387 			do_tok(buf, "drawBox",
3388 						 ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2W) | ANOLASTPAREN | ANOENDSEMICOLON);
3389 		opcode = get_byte();
3390 		do_tok(buf, NULL,
3391 					 ASTARTCOMMA | ANOFIRSTPAREN | ((opcode & 0x80) ? A1V : A1W) |
3392 					 ((opcode & 0x40) ? A2V : A2W) | ((opcode & 0x20) ? A3V : A3B));
3393 		break;
3394 
3395 
3396 	case 0x02:
3397 	case 0x82:
3398 		if (g_options.ZakFlag)
3399 			do_tok(buf, "startMusic", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3400 		else
3401 			do_tok(buf, "startMusic", ((opcode & 0x80) ? A1V : A1B));
3402 		break;
3403 
3404 	case 0xCC:
3405 		do_pseudoRoom(buf);
3406 		break;
3407 
3408 	case 0x33:
3409 	case 0x73:
3410 	case 0xB3:
3411 	case 0xF3:
3412 		if (g_options.scriptVersion == 5)
3413 			do_room_ops(buf);
3414 		else
3415 			do_room_ops_old(buf, opcode);
3416 		break;
3417 
3418 	case 0x68:
3419 	case 0xE8:
3420 		do_tok(buf, "isScriptRunning", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3421 		break;
3422 
3423 	case 0x2E:{
3424 			int d;
3425 			d = get_byte();
3426 			d |= get_byte() << 8;
3427 			d |= get_byte() << 16;
3428 			sprintf(buf, "delay(%d);", d);
3429 			break;
3430 		}
3431 
3432 	case 0x29:
3433 	case 0x69:
3434 	case 0xA9:
3435 	case 0xE9:
3436 		do_tok(buf, "setOwnerOf", ((opcode & 0x80) ? A1V : A1W) | ((opcode & 0x40) ? A2V : A2B));
3437 		break;
3438 
3439 	case 0x52:
3440 	case 0xD2:
3441 		do_tok(buf, "actorFollowCamera", ((opcode & 0x80) ? A1V : A1B));
3442 		break;
3443 
3444 	case 0x58:{
3445 			int d;
3446 			d = get_byte();
3447 			if (d != 0)
3448 				sprintf(buf, "beginOverride();");
3449 			else
3450 				sprintf(buf, "endOverride();");
3451 			break;
3452 		}
3453 
3454 	case 0x1C:
3455 	case 0x9C:
3456 		do_tok(buf, "startSound", ((opcode & 0x80) ? A1V : A1B));
3457 		break;
3458 
3459 	case 0x4C:
3460 		if (g_options.scriptVersion <= 3)
3461 			do_tok(buf, "waitForSentence", 0);
3462 		else
3463 			do_tok(buf, "soundKludge", A1LIST);
3464 		break;
3465 
3466 	case 0x3C:
3467 	case 0xBC:
3468 		do_tok(buf, "stopSound", ((opcode & 0x80) ? A1V : A1B));
3469 		break;
3470 
3471 	case 0x98:
3472 		do_tok(buf, "systemOps", A1B);
3473 		break;
3474 
3475 	case 0x7B:
3476 	case 0xFB:
3477 		do_tok(buf, "getActorWalkBox", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3478 		break;
3479 
3480 	case 0x43:
3481 	case 0xC3:
3482 		if (g_options.IndyFlag)
3483 			do_tok(buf, "getActorX", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3484 		else
3485 			do_tok(buf, "getActorX", AVARSTORE | ((opcode & 0x80) ? A1V : A1W));
3486 		break;
3487 
3488 	case 0x23:
3489 	case 0xA3:
3490 		if (g_options.IndyFlag)
3491 			do_tok(buf, "getActorY", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3492 		else
3493 			do_tok(buf, "getActorY", AVARSTORE | ((opcode & 0x80) ? A1V : A1W));
3494 		break;
3495 
3496 	case 0x7A:
3497 	case 0xFA:
3498 		do_verbops(buf, opcode);
3499 		break;
3500 
3501 	case 0x2D:
3502 	case 0x6D:
3503 	case 0xAD:
3504 	case 0xED:
3505 		do_tok(buf, "putActorInRoom", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
3506 		break;
3507 
3508 	case 0x54:
3509 	case 0xD4:
3510 		do_tok(buf, "setObjectName", ((opcode & 0x80) ? A1V : A1W) | A2ASCII);
3511 		break;
3512 
3513 	case 0x5D:
3514 	case 0xDD:
3515 		do_tok(buf, "setClass", ((opcode & 0x80) ? A1V : A1W) | A2LIST);
3516 		break;
3517 
3518 	case 0x35:
3519 	case 0x75:
3520 	case 0xB5:
3521 	case 0xF5:
3522 		do_tok(buf, "findObject",
3523 					 AVARSTORE | ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
3524 		break;
3525 
3526 	case 0x26:
3527 	case 0xA6:{
3528 			int i;
3529 			char first = 1;
3530 
3531 			buf = do_tok(buf, "setVarRange", A1V | ANOLASTPAREN | ANOENDSEMICOLON);
3532 			i = get_byte();
3533 
3534 			buf += sprintf(buf, ",%d,[", i);
3535 
3536 			while (i > 0) {
3537 				if (!first)
3538 					buf = strecpy(buf, ",");
3539 				first = 0;
3540 
3541 				buf += sprintf(buf, "%d", (opcode & 0x80) ? get_word() : get_byte());
3542 				i--;
3543 			}
3544 
3545 			strcpy(buf, "]);");
3546 
3547 		}
3548 		break;
3549 
3550 	case 0x16:
3551 	case 0x96:
3552 		do_tok(buf, "getRandomNr", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3553 		break;
3554 
3555 	case 0x2B:
3556 		do_tok(buf, "delayVariable", A1V);
3557 		break;
3558 
3559 	case 0x0E:
3560 	case 0x4E:
3561 	case 0x8E:
3562 	case 0xCE:
3563 		do_tok(buf, "putActorAtObject", ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2W));
3564 		break;
3565 
3566 	case 0x12:
3567 	case 0x92:
3568 		do_tok(buf, "panCameraTo", ((opcode & 0x80) ? A1V : A1W));
3569 		break;
3570 
3571 	case 0x32:
3572 	case 0xB2:
3573 		do_tok(buf, "setCameraAt", ((opcode & 0x80) ? A1V : A1W));
3574 		break;
3575 
3576 	case 0x30:
3577 	case 0xB0:
3578 		if (g_options.scriptVersion == 3)
3579 			do_tok(buf, "setBoxFlags", ((opcode & 0x80) ? A1V : A1B) | A2B);
3580 		else
3581 			do_matrix_ops(buf, opcode);
3582 		break;
3583 
3584 	case 0x7C:
3585 	case 0xFC:
3586 		do_tok(buf, "isSoundRunning", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3587 		break;
3588 
3589 	case 0x31:
3590 	case 0xB1:
3591 		do_tok(buf, "getInventoryCount", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3592 		break;
3593 
3594 	case 0x1f:
3595 	case 0x5f:
3596 	case 0x9f:
3597 	case 0xdf:
3598 		do_tok(buf, "isActorInBox",
3599 					 ATO | ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
3600 		break;
3601 
3602 	case 0x22:
3603 	case 0xA2:
3604 		if (g_options.scriptVersion == 5)
3605 			do_tok(buf, "getAnimCounter", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3606 		else
3607 			do_tok(buf, "saveLoadGame", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3608 		break;
3609 
3610 	case 0x3d:
3611 	case 0x7d:
3612 	case 0xBD:
3613 	case 0xFD:
3614 		do_tok(buf, "findInventory",
3615 					 AVARSTORE | ((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B));
3616 		break;
3617 
3618 	case 0xAB:{
3619 			int code;
3620 			opcode = get_byte();
3621 			code =
3622 				((opcode & 0x80) ? A1V : A1B) | ((opcode & 0x40) ? A2V : A2B) |
3623 				((opcode & 0x20) ? A3V : A3B);
3624 			switch (opcode & 0x1F) {
3625 			case 0x01:
3626 				do_tok(buf, "saveVerbs", code);
3627 				break;
3628 			case 0x02:
3629 				do_tok(buf, "restoreVerbs", code);
3630 				break;
3631 			case 0x03:
3632 				do_tok(buf, "deleteVerbs", code);
3633 				break;
3634 			default:
3635 				error("opcode 0xAB: Unhandled subop %d", opcode & 0x1F);
3636 			}
3637 		}
3638 		break;
3639 
3640 	case 0x60:
3641 	case 0xE0:
3642 		do_tok(buf, "freezeScripts", ((opcode & 0x80) ? A1V : A1B));
3643 		break;
3644 
3645 	case 0x6E:
3646 	case 0xEE:
3647 		do_tok(buf, "stopObjectScript", ((opcode & 0x80) ? A1V : A1W));
3648 		break;
3649 
3650 		// dodgy?
3651 	case 0x5C:{
3652 	case 0xDC:
3653 			int d = get_byte();
3654 			if ((d & 0x1F) == 3)
3655 				do_tok(buf, "oldRoomEffect-set", ((opcode & 0x80) ? A1V : A1W));
3656 			else
3657 				do_tok(buf, "oldRoomEffect-fadein", ((opcode & 0x80) ? A1V : A1W));
3658 			break;
3659 		}
3660 
3661 	case 0x50:
3662 	case 0xD0:
3663 		do_tok(buf, "pickupObject", ((opcode & 0x80) ? A1V : A1W));
3664 		break;
3665 
3666 	case 0xA7:
3667 		if (g_options.scriptVersion == 5) {
3668 			sprintf(buf, "dummy(%.2X);", opcode);
3669 		} else {
3670 			int d = get_byte();
3671 			buf += sprintf(buf, "saveLoadVars(");
3672 			if (d == 1) {
3673 				buf += sprintf(buf, "Save");
3674 			} else {
3675 				buf += sprintf(buf, "Load");
3676 			}
3677 			while ((d = get_byte()) != 0) {
3678 				switch (d & 0x1F) {
3679 				case 0x01:
3680 					buf += sprintf(buf, ", VarRange(");
3681 					buf = get_var(buf);
3682 					buf += sprintf(buf, ",");
3683 					buf = get_var(buf);
3684 					buf += sprintf(buf, ")");
3685 					break;
3686 				case 0x02:
3687 					buf += sprintf(buf, ", StringRange(");
3688 					buf = get_var_or_byte(buf, (d & 0x80));
3689 					buf += sprintf(buf, ",");
3690 					buf = get_var_or_byte(buf, (d & 0x40));
3691 					buf += sprintf(buf, ")");
3692 					break;
3693 				case 0x03:
3694 					buf += sprintf(buf, ", Open(");
3695 					buf = get_string(buf);
3696 					buf += sprintf(buf, ")");
3697 					break;
3698 				case 0x04:
3699 					buf += sprintf(buf, ", Append)");
3700 					return;
3701 				case 0x1F:
3702 					buf += sprintf(buf, ", Close)");
3703 					return;
3704 				}
3705 			}
3706 			buf += sprintf(buf, ");");
3707 		}
3708 		break;
3709 
3710 	case 0x67:
3711 	case 0xE7:
3712 		do_tok(buf, "getStringWidth", AVARSTORE | ((opcode & 0x80) ? A1V : A1B));
3713 		break;
3714 
3715 	case 0x6B:
3716 		do_tok(buf, "debug", ((opcode & 0x80) ? A1V : A1W));
3717 		break;
3718 
3719 	default:
3720 		if (g_options.haltOnError) {
3721 			error("Unknown opcode %.2X", opcode);
3722 		}
3723 		sprintf(buf, "ERROR: Unknown opcode %.2X!", opcode);
3724 	}
3725 }
3726