1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "parallaction/exec.h"
24 #include "parallaction/input.h"
25 #include "parallaction/parallaction.h"
26
27 #include "common/textconsole.h"
28
29 namespace Parallaction {
30
31 #define INST_ON 1
32 #define INST_OFF 2
33 #define INST_X 3
34 #define INST_Y 4
35 #define INST_Z 5
36 #define INST_F 6
37 #define INST_LOOP 7
38 #define INST_ENDLOOP 8
39 #define INST_SHOW 9
40 #define INST_INC 10
41 #define INST_DEC 11
42 #define INST_SET 12
43 #define INST_PUT 13
44 #define INST_CALL 14
45 #define INST_WAIT 15
46 #define INST_START 16
47 #define INST_PROCESS 17
48 #define INST_MOVE 18
49 #define INST_COLOR 19
50 #define INST_SOUND 20
51 #define INST_MASK 21
52 #define INST_PRINT 22
53 #define INST_TEXT 23
54 #define INST_MUL 24
55 #define INST_DIV 25
56 #define INST_IFEQ 26
57 #define INST_IFLT 27
58 #define INST_IFGT 28
59 #define INST_ENDIF 29
60 #define INST_STOP 30
61 #define INST_ENDSCRIPT 31
62
63 #define SetOpcodeTable(x) table = &x;
64
65 typedef Common::Functor1Mem<CommandContext&, void, CommandExec_br> OpcodeV1;
66 #define COMMAND_OPCODE(op) table->push_back(new OpcodeV1(this, &CommandExec_br::cmdOp_##op))
67 #define DECLARE_COMMAND_OPCODE(op) void CommandExec_br::cmdOp_##op(CommandContext &ctxt)
68
69 typedef Common::Functor1Mem<ProgramContext&, void, ProgramExec_br> OpcodeV2;
70 #define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &ProgramExec_br::instOp_##op))
71 #define DECLARE_INSTRUCTION_OPCODE(op) void ProgramExec_br::instOp_##op(ProgramContext &ctxt)
72
73 extern const char *_instructionNamesRes_br[];
74
setupSubtitles(const char * s,const char * s2,int y)75 void Parallaction_br::setupSubtitles(const char *s, const char *s2, int y) {
76 debugC(5, kDebugExec, "setupSubtitles(%s, %s, %i)", s, s2, y);
77
78 clearSubtitles();
79
80 if (!scumm_stricmp("clear", s)) {
81 return;
82 }
83
84 if (y != -1) {
85 _subtitleY = y;
86 }
87
88 // FIXME: render subtitles using the right color (10 instead of 0).
89 // The original game features a nasty hack, having the font rendering routine
90 // replacing color 12 of font RUSSIA with 10 when preparing subtitles.
91 uint8 color = (getPlatform() == Common::kPlatformAmiga) ? 11 : 0;
92 _subtitle[0] = _gfx->createLabel(_labelFont, s, color);
93 _gfx->showLabel(_subtitle[0], CENTER_LABEL_HORIZONTAL, _subtitleY);
94 if (s2) {
95 _subtitle[1] = _gfx->createLabel(_labelFont, s2, color);
96 _gfx->showLabel(_subtitle[1], CENTER_LABEL_HORIZONTAL, _subtitleY + 5 + _labelFont->height());
97 } else {
98 _subtitle[1] = 0;
99 }
100 #if 0 // disabled because no references to lip sync has been found in the scripts
101 _subtitleLipSync = 0;
102 #endif
103 }
104
clearSubtitles()105 void Parallaction_br::clearSubtitles() {
106 if (_subtitle[0]) {
107 _gfx->hideLabel(_subtitle[0]);
108 }
109 delete _subtitle[0];
110 _subtitle[0] = 0;
111
112 if (_subtitle[1]) {
113 _gfx->hideLabel(_subtitle[1]);
114 }
115 delete _subtitle[1];
116 _subtitle[1] = 0;
117 }
118
119
DECLARE_COMMAND_OPCODE(location)120 DECLARE_COMMAND_OPCODE(location) {
121 _vm->_location._startPosition = ctxt._cmd->_startPos;
122 _vm->_location._startFrame = 0;
123 _vm->_location._followerStartPosition = ctxt._cmd->_startPos2;
124 _vm->_location._followerStartFrame = 0;
125
126 _vm->scheduleLocationSwitch(ctxt._cmd->_string.c_str());
127 }
128
129
DECLARE_COMMAND_OPCODE(open)130 DECLARE_COMMAND_OPCODE(open) {
131 _vm->updateDoor(ctxt._cmd->_zone, false);
132 }
133
134
DECLARE_COMMAND_OPCODE(close)135 DECLARE_COMMAND_OPCODE(close) {
136 _vm->updateDoor(ctxt._cmd->_zone, true);
137 }
138
139
DECLARE_COMMAND_OPCODE(on)140 DECLARE_COMMAND_OPCODE(on) {
141 _vm->showZone(ctxt._cmd->_zone, true);
142 }
143
144
DECLARE_COMMAND_OPCODE(off)145 DECLARE_COMMAND_OPCODE(off) {
146 _vm->showZone(ctxt._cmd->_zone, false);
147 }
148
149
DECLARE_COMMAND_OPCODE(call)150 DECLARE_COMMAND_OPCODE(call) {
151 _vm->callFunction(ctxt._cmd->_callable, &ctxt._z);
152 }
153
154
DECLARE_COMMAND_OPCODE(drop)155 DECLARE_COMMAND_OPCODE(drop) {
156 _vm->dropItem(ctxt._cmd->_object);
157 }
158
159
DECLARE_COMMAND_OPCODE(move)160 DECLARE_COMMAND_OPCODE(move) {
161 _vm->scheduleWalk(ctxt._cmd->_move.x, ctxt._cmd->_move.y, false);
162 suspend();
163 }
164
DECLARE_COMMAND_OPCODE(start)165 DECLARE_COMMAND_OPCODE(start) {
166 ctxt._cmd->_zone->_flags |= kFlagsActing;
167 }
168
DECLARE_COMMAND_OPCODE(stop)169 DECLARE_COMMAND_OPCODE(stop) {
170 ctxt._cmd->_zone->_flags &= ~kFlagsActing;
171 }
172
173
DECLARE_COMMAND_OPCODE(character)174 DECLARE_COMMAND_OPCODE(character) {
175 debugC(9, kDebugExec, "Parallaction_br::cmdOp_character(%s)", ctxt._cmd->_string.c_str());
176 _vm->changeCharacter(ctxt._cmd->_string.c_str());
177 }
178
179
DECLARE_COMMAND_OPCODE(followme)180 DECLARE_COMMAND_OPCODE(followme) {
181 Common::String s(ctxt._cmd->_string);
182 if (!s.compareToIgnoreCase("NULL")) {
183 s.clear();
184 }
185 _vm->setFollower(s);
186 }
187
188
DECLARE_COMMAND_OPCODE(onmouse)189 DECLARE_COMMAND_OPCODE(onmouse) {
190 _vm->_input->setMouseState(MOUSE_ENABLED_SHOW);
191 }
192
193
DECLARE_COMMAND_OPCODE(offmouse)194 DECLARE_COMMAND_OPCODE(offmouse) {
195 _vm->_input->setMouseState(MOUSE_DISABLED);
196 }
197
198
DECLARE_COMMAND_OPCODE(add)199 DECLARE_COMMAND_OPCODE(add) {
200 _vm->addInventoryItem(ctxt._cmd->_object);
201 }
202
203
DECLARE_COMMAND_OPCODE(leave)204 DECLARE_COMMAND_OPCODE(leave) {
205 ZonePtr z = ctxt._cmd->_zone;
206 _vm->dropItem(z->u._getIcon);
207 _vm->showZone(z, true);
208 }
209
210
DECLARE_COMMAND_OPCODE(inc)211 DECLARE_COMMAND_OPCODE(inc) {
212 int v = _vm->getCounterValue(ctxt._cmd->_counterName);
213 _vm->setCounterValue(ctxt._cmd->_counterName, v + ctxt._cmd->_counterValue);
214 }
215
216
DECLARE_COMMAND_OPCODE(dec)217 DECLARE_COMMAND_OPCODE(dec) {
218 int v = _vm->getCounterValue(ctxt._cmd->_counterName);
219 _vm->setCounterValue(ctxt._cmd->_counterName, v - ctxt._cmd->_counterValue);
220 }
221
222 // these definitions must match those in parser_br.cpp
223 #define CMD_TEST 25
224 #define CMD_TEST_GT 26
225 #define CMD_TEST_LT 27
226
DECLARE_COMMAND_OPCODE(ifeq)227 DECLARE_COMMAND_OPCODE(ifeq) {
228 _vm->testCounterCondition(ctxt._cmd->_counterName, CMD_TEST, ctxt._cmd->_counterValue);
229 }
230
DECLARE_COMMAND_OPCODE(iflt)231 DECLARE_COMMAND_OPCODE(iflt) {
232 _vm->testCounterCondition(ctxt._cmd->_counterName, CMD_TEST_LT, ctxt._cmd->_counterValue);
233 }
234
DECLARE_COMMAND_OPCODE(ifgt)235 DECLARE_COMMAND_OPCODE(ifgt) {
236 _vm->testCounterCondition(ctxt._cmd->_counterName, CMD_TEST_GT, ctxt._cmd->_counterValue);
237 }
238
239
DECLARE_COMMAND_OPCODE(let)240 DECLARE_COMMAND_OPCODE(let) {
241 _vm->setCounterValue(ctxt._cmd->_counterName, ctxt._cmd->_counterValue);
242 }
243
244
DECLARE_COMMAND_OPCODE(music)245 DECLARE_COMMAND_OPCODE(music) {
246 warning("Parallaction_br::cmdOp_music not yet implemented");
247 }
248
249
DECLARE_COMMAND_OPCODE(fix)250 DECLARE_COMMAND_OPCODE(fix) {
251 ctxt._cmd->_zone->_flags |= kFlagsFixed;
252 }
253
254
DECLARE_COMMAND_OPCODE(unfix)255 DECLARE_COMMAND_OPCODE(unfix) {
256 ctxt._cmd->_zone->_flags &= ~kFlagsFixed;
257 }
258
259
DECLARE_COMMAND_OPCODE(zeta)260 DECLARE_COMMAND_OPCODE(zeta) {
261 _vm->_location._zeta0 = ctxt._cmd->_zeta0;
262 _vm->_location._zeta1 = ctxt._cmd->_zeta1;
263 _vm->_location._zeta2 = ctxt._cmd->_zeta2;
264 }
265
266
DECLARE_COMMAND_OPCODE(scroll)267 DECLARE_COMMAND_OPCODE(scroll) {
268 Common::Point p;
269 _vm->_gfx->getScrollPos(p);
270 _vm->_gfx->initiateScroll(ctxt._cmd->_counterValue - p.x, 0);
271 }
272
273
DECLARE_COMMAND_OPCODE(swap)274 DECLARE_COMMAND_OPCODE(swap) {
275 warning("Parallaction_br::cmdOp_swap does not handle a follower yet");
276
277 /*
278 TODO:
279 - fixup follower
280 - change mouse pointer
281 */
282
283 const char *newCharacterName = ctxt._cmd->_string.c_str();
284 AnimationPtr newCharacterAnimation = _vm->_location.findAnimation(newCharacterName);
285 AnimationPtr oldCharaterAnimation = _vm->_char._ani;
286
287 Common::strlcpy(oldCharaterAnimation->_name, _vm->_char.getName(), ZONENAME_LENGTH);
288 _vm->_char.setName(newCharacterName);
289
290 _vm->_char._ani = newCharacterAnimation;
291 _vm->_char._talk = _vm->_disk->loadTalk(newCharacterName);
292 Common::strlcpy(_vm->_char._ani->_name, "yourself", ZONENAME_LENGTH);
293
294 _vm->linkUnlinkedZoneAnimations();
295
296 _vm->_inventory = _vm->findInventory(newCharacterName);
297 _vm->_inventoryRenderer->setInventory(_vm->_inventory);
298
299 _vm->_input->setCharacterPointer(newCharacterName);
300 }
301
302
DECLARE_COMMAND_OPCODE(give)303 DECLARE_COMMAND_OPCODE(give) {
304 int item = ctxt._cmd->_object;
305 Inventory *targetInventory = _vm->findInventory(ctxt._cmd->_characterName.c_str());
306
307 if (targetInventory) {
308 targetInventory->addItem(item);
309 }
310
311 _vm->_inventory->removeItem(item);
312 }
313
314
DECLARE_COMMAND_OPCODE(text)315 DECLARE_COMMAND_OPCODE(text) {
316 _vm->setupSubtitles(ctxt._cmd->_string.c_str(), ctxt._cmd->_string2.c_str(), ctxt._cmd->_zeta0);
317 }
318
319
DECLARE_COMMAND_OPCODE(part)320 DECLARE_COMMAND_OPCODE(part) {
321 _vm->_nextPart = ctxt._cmd->_counterValue;
322 }
323
324
DECLARE_COMMAND_OPCODE(testsfx)325 DECLARE_COMMAND_OPCODE(testsfx) {
326 warning("Parallaction_br::cmdOp_testsfx not completely implemented");
327 _vm->clearLocationFlags(kFlagsTestTrue); // should test if sfx are enabled
328 }
329
330
DECLARE_COMMAND_OPCODE(ret)331 DECLARE_COMMAND_OPCODE(ret) {
332 g_engineFlags |= kEngineReturn;
333 }
334
335
DECLARE_COMMAND_OPCODE(onsave)336 DECLARE_COMMAND_OPCODE(onsave) {
337 warning("Parallaction_br::cmdOp_onsave not yet implemented");
338 }
339
340
DECLARE_COMMAND_OPCODE(offsave)341 DECLARE_COMMAND_OPCODE(offsave) {
342 warning("Parallaction_br::cmdOp_offsave not yet implemented");
343 }
344
DECLARE_INSTRUCTION_OPCODE(invalid)345 DECLARE_INSTRUCTION_OPCODE(invalid) {
346 error("Can't execute invalid opcode %i", ctxt._inst->_index);
347 }
348
DECLARE_COMMAND_OPCODE(clear)349 DECLARE_COMMAND_OPCODE(clear) {
350 if (ctxt._cmd->_flags & kFlagsGlobal) {
351 ctxt._cmd->_flags &= ~kFlagsGlobal;
352 g_globalFlags &= ~ctxt._cmd->_flags;
353 } else {
354 _vm->clearLocationFlags(ctxt._cmd->_flags);
355 }
356 }
357
DECLARE_COMMAND_OPCODE(speak)358 DECLARE_COMMAND_OPCODE(speak) {
359 // WORKAROUND: this avoids crashing when the zone is not parsed, like in the case
360 // of script bug in ticket #4251.
361 if (!ctxt._cmd->_zone) {
362 return;
363 }
364
365 if (ACTIONTYPE(ctxt._cmd->_zone) == kZoneSpeak && ctxt._cmd->_zone->u._speakDialogue) {
366 _vm->enterDialogueMode(ctxt._cmd->_zone);
367 } else {
368 _vm->_activeZone = ctxt._cmd->_zone;
369 }
370 }
371
372
DECLARE_COMMAND_OPCODE(get)373 DECLARE_COMMAND_OPCODE(get) {
374 ctxt._cmd->_zone->_flags &= ~kFlagsFixed;
375 _vm->runZone(ctxt._cmd->_zone);
376 }
377
DECLARE_COMMAND_OPCODE(toggle)378 DECLARE_COMMAND_OPCODE(toggle) {
379 if (ctxt._cmd->_flags & kFlagsGlobal) {
380 ctxt._cmd->_flags &= ~kFlagsGlobal;
381 g_globalFlags ^= ctxt._cmd->_flags;
382 } else {
383 _vm->toggleLocationFlags(ctxt._cmd->_flags);
384 }
385 }
386
DECLARE_COMMAND_OPCODE(quit)387 DECLARE_COMMAND_OPCODE(quit) {
388 _vm->quitGame();
389 }
390
DECLARE_COMMAND_OPCODE(invalid)391 DECLARE_COMMAND_OPCODE(invalid) {
392 error("Can't execute invalid command '%i'", ctxt._cmd->_id);
393 }
394
DECLARE_COMMAND_OPCODE(set)395 DECLARE_COMMAND_OPCODE(set) {
396 if (ctxt._cmd->_flags & kFlagsGlobal) {
397 ctxt._cmd->_flags &= ~kFlagsGlobal;
398 g_globalFlags |= ctxt._cmd->_flags;
399 } else {
400 _vm->setLocationFlags(ctxt._cmd->_flags);
401 }
402 }
403
404
405
DECLARE_INSTRUCTION_OPCODE(on)406 DECLARE_INSTRUCTION_OPCODE(on) {
407 _vm->showZone(ctxt._inst->_z, true);
408 }
409
410
DECLARE_INSTRUCTION_OPCODE(off)411 DECLARE_INSTRUCTION_OPCODE(off) {
412 _vm->showZone(ctxt._inst->_z, false);
413 }
414
415
DECLARE_INSTRUCTION_OPCODE(set)416 DECLARE_INSTRUCTION_OPCODE(set) {
417 ctxt._inst->_opA.setValue(ctxt._inst->_opB.getValue());
418 }
419
420
421
DECLARE_INSTRUCTION_OPCODE(inc)422 DECLARE_INSTRUCTION_OPCODE(inc) {
423 InstructionPtr inst = ctxt._inst;
424
425 int16 rvalue = inst->_opB.getValue();
426
427 if (inst->_flags & kInstMod) { // mod
428 int16 _bx = (rvalue > 0 ? rvalue : -rvalue);
429 if (ctxt._modCounter % _bx != 0) return;
430
431 rvalue = (rvalue > 0 ? 1 : -1);
432 }
433
434 int16 lvalue = inst->_opA.getValue();
435
436 switch (inst->_index) {
437 case INST_INC:
438 lvalue += rvalue;
439 break;
440
441 case INST_DEC:
442 lvalue -= rvalue;
443 break;
444
445 case INST_MUL:
446 lvalue *= rvalue;
447 break;
448
449 case INST_DIV:
450 lvalue /= rvalue;
451 break;
452
453 default:
454 error("This should never happen. Report immediately");
455 }
456
457 inst->_opA.setValue(lvalue);
458
459 }
460
461
DECLARE_INSTRUCTION_OPCODE(put)462 DECLARE_INSTRUCTION_OPCODE(put) {
463 // NOTE: there is not a single occurrence of PUT in the scripts
464 warning("PUT instruction is not implemented");
465 }
466
467
468
DECLARE_INSTRUCTION_OPCODE(wait)469 DECLARE_INSTRUCTION_OPCODE(wait) {
470 // NOTE: there is not a single occurrence of WAIT in the scripts
471 warning("WAIT instruction is not implemented");
472 }
473
474
DECLARE_INSTRUCTION_OPCODE(start)475 DECLARE_INSTRUCTION_OPCODE(start) {
476 ctxt._inst->_z->_flags |= kFlagsActing;
477 }
478
479
DECLARE_INSTRUCTION_OPCODE(process)480 DECLARE_INSTRUCTION_OPCODE(process) {
481 _vm->_activeZone2 = ctxt._inst->_z;
482 }
483
484
DECLARE_INSTRUCTION_OPCODE(move)485 DECLARE_INSTRUCTION_OPCODE(move) {
486 // NOTE: I couldn't find evidence of scripts containing this instruction being used
487 InstructionPtr inst = ctxt._inst;
488 _vm->scheduleWalk(inst->_opA.getValue(), inst->_opB.getValue(), false);
489 ctxt._suspend = true;
490 }
491
492
DECLARE_INSTRUCTION_OPCODE(color)493 DECLARE_INSTRUCTION_OPCODE(color) {
494 InstructionPtr inst = ctxt._inst;
495 _vm->_gfx->_palette.setEntry(inst->_opB.getValue(), inst->_colors[0], inst->_colors[1], inst->_colors[2]);
496 _vm->_gfx->setPalette(_vm->_gfx->_palette);
497 }
498
499
DECLARE_INSTRUCTION_OPCODE(mask)500 DECLARE_INSTRUCTION_OPCODE(mask) {
501 #if 0
502 Instruction *inst = *ctxt._inst;
503 _gfx->_bgLayers[0] = inst->_opA.getRValue();
504 _gfx->_bgLayers[1] = inst->_opB.getRValue();
505 _gfx->_bgLayers[2] = inst->_opC.getRValue();
506 #endif
507 }
508
509
DECLARE_INSTRUCTION_OPCODE(print)510 DECLARE_INSTRUCTION_OPCODE(print) {
511 // NOTE: there is not a single occurrence of PRINT in the scripts
512 // I suppose it was used for debugging
513 warning("PRINT instruction is not implemented");
514 }
515
DECLARE_INSTRUCTION_OPCODE(text)516 DECLARE_INSTRUCTION_OPCODE(text) {
517 InstructionPtr inst = ctxt._inst;
518 _vm->setupSubtitles(inst->_text.c_str(), inst->_text2.c_str(), inst->_y);
519 }
520
521
DECLARE_INSTRUCTION_OPCODE(ifeq)522 DECLARE_INSTRUCTION_OPCODE(ifeq) {
523 InstructionPtr inst = ctxt._inst;
524 bool cond = inst->_opA.getValue() == inst->_opB.getValue();
525 if (!cond) {
526 ctxt._ip = inst->_endif;
527 }
528 }
529
530
DECLARE_INSTRUCTION_OPCODE(iflt)531 DECLARE_INSTRUCTION_OPCODE(iflt) {
532 InstructionPtr inst = ctxt._inst;
533 bool cond = inst->_opA.getValue() < inst->_opB.getValue();
534 if (!cond) {
535 ctxt._ip = inst->_endif;
536 }
537 }
538
539
DECLARE_INSTRUCTION_OPCODE(ifgt)540 DECLARE_INSTRUCTION_OPCODE(ifgt) {
541 InstructionPtr inst = ctxt._inst;
542 bool cond = inst->_opA.getValue() > inst->_opB.getValue();
543 if (!cond) {
544 ctxt._ip = inst->_endif;
545 }
546 }
547
548
DECLARE_INSTRUCTION_OPCODE(endif)549 DECLARE_INSTRUCTION_OPCODE(endif) {
550 // nothing to do here
551 }
552
553
DECLARE_INSTRUCTION_OPCODE(stop)554 DECLARE_INSTRUCTION_OPCODE(stop) {
555 ZonePtr z = ctxt._inst->_z;
556
557 // Prevent execution if zone is missing. The known case is "PART2/insegui.scr", which has
558 // "STOP insegui", which doesn't exist (see ticket #9193 for the gory details)
559 if (!z) return;
560
561 if (ACTIONTYPE(z) == kZoneHear) {
562 warning("Parallaction_br::instOp_stop not yet implemented for HEAR zones");
563 // TODO: stop music or sound effects generated by a zone.
564 } else {
565 z->_flags &= ~kFlagsActing;
566 }
567 }
568
DECLARE_INSTRUCTION_OPCODE(loop)569 DECLARE_INSTRUCTION_OPCODE(loop) {
570 InstructionPtr inst = ctxt._inst;
571
572 ctxt._program->_loopCounter = inst->_opB.getValue();
573 ctxt._program->_loopStart = ctxt._ip;
574 }
575
576
DECLARE_INSTRUCTION_OPCODE(endloop)577 DECLARE_INSTRUCTION_OPCODE(endloop) {
578 if (--ctxt._program->_loopCounter > 0) {
579 ctxt._ip = ctxt._program->_loopStart;
580 }
581 }
582
DECLARE_INSTRUCTION_OPCODE(show)583 DECLARE_INSTRUCTION_OPCODE(show) {
584 ctxt._suspend = true;
585 }
586
DECLARE_INSTRUCTION_OPCODE(call)587 DECLARE_INSTRUCTION_OPCODE(call) {
588 _vm->callFunction(ctxt._inst->_immediate, 0);
589 }
590
591
DECLARE_INSTRUCTION_OPCODE(endscript)592 DECLARE_INSTRUCTION_OPCODE(endscript) {
593 if ((ctxt._anim->_flags & kFlagsLooping) == 0) {
594 ctxt._anim->_flags &= ~kFlagsActing;
595 _vm->_cmdExec->run(ctxt._anim->_commands, ctxt._anim);
596 ctxt._program->_status = kProgramDone;
597 }
598
599 ctxt._ip = 0;
600 ctxt._suspend = true;
601 }
602
603
CommandExec_br(Parallaction_br * vm)604 CommandExec_br::CommandExec_br(Parallaction_br* vm) : CommandExec(vm), _vm(vm) {
605 CommandOpcodeSet *table = 0;
606
607 SetOpcodeTable(_opcodes);
608 COMMAND_OPCODE(invalid);
609 COMMAND_OPCODE(set);
610 COMMAND_OPCODE(clear);
611 COMMAND_OPCODE(start);
612 COMMAND_OPCODE(speak);
613 COMMAND_OPCODE(get);
614 COMMAND_OPCODE(location);
615 COMMAND_OPCODE(open);
616 COMMAND_OPCODE(close);
617 COMMAND_OPCODE(on);
618 COMMAND_OPCODE(off);
619 COMMAND_OPCODE(call);
620 COMMAND_OPCODE(toggle);
621 COMMAND_OPCODE(drop);
622 COMMAND_OPCODE(quit);
623 COMMAND_OPCODE(move);
624 COMMAND_OPCODE(stop);
625 COMMAND_OPCODE(character);
626 COMMAND_OPCODE(followme);
627 COMMAND_OPCODE(onmouse);
628 COMMAND_OPCODE(offmouse);
629 COMMAND_OPCODE(add);
630 COMMAND_OPCODE(leave);
631 COMMAND_OPCODE(inc);
632 COMMAND_OPCODE(dec);
633 COMMAND_OPCODE(ifeq);
634 COMMAND_OPCODE(iflt);
635 COMMAND_OPCODE(ifgt);
636 COMMAND_OPCODE(let);
637 COMMAND_OPCODE(music);
638 COMMAND_OPCODE(fix);
639 COMMAND_OPCODE(unfix);
640 COMMAND_OPCODE(zeta);
641 COMMAND_OPCODE(scroll);
642 COMMAND_OPCODE(swap);
643 COMMAND_OPCODE(give);
644 COMMAND_OPCODE(text);
645 COMMAND_OPCODE(part);
646 COMMAND_OPCODE(testsfx);
647 COMMAND_OPCODE(ret);
648 COMMAND_OPCODE(onsave);
649 COMMAND_OPCODE(offsave);
650 }
651
652
ProgramExec_br(Parallaction_br * vm)653 ProgramExec_br::ProgramExec_br(Parallaction_br *vm) : _vm(vm) {
654 _instructionNames = _instructionNamesRes_br;
655
656 ProgramOpcodeSet *table = 0;
657
658 SetOpcodeTable(_opcodes);
659 INSTRUCTION_OPCODE(invalid);
660 INSTRUCTION_OPCODE(on);
661 INSTRUCTION_OPCODE(off);
662 INSTRUCTION_OPCODE(set); // x
663 INSTRUCTION_OPCODE(set); // y
664 INSTRUCTION_OPCODE(set); // z
665 INSTRUCTION_OPCODE(set); // f
666 INSTRUCTION_OPCODE(loop);
667 INSTRUCTION_OPCODE(endloop);
668 INSTRUCTION_OPCODE(show); // show
669 INSTRUCTION_OPCODE(inc);
670 INSTRUCTION_OPCODE(inc); // dec
671 INSTRUCTION_OPCODE(set);
672 INSTRUCTION_OPCODE(put);
673 INSTRUCTION_OPCODE(call);
674 INSTRUCTION_OPCODE(wait);
675 INSTRUCTION_OPCODE(start);
676 INSTRUCTION_OPCODE(process);
677 INSTRUCTION_OPCODE(move);
678 INSTRUCTION_OPCODE(color);
679 INSTRUCTION_OPCODE(process); // sound
680 INSTRUCTION_OPCODE(mask);
681 INSTRUCTION_OPCODE(print);
682 INSTRUCTION_OPCODE(text);
683 INSTRUCTION_OPCODE(inc); // mul
684 INSTRUCTION_OPCODE(inc); // div
685 INSTRUCTION_OPCODE(ifeq);
686 INSTRUCTION_OPCODE(iflt);
687 INSTRUCTION_OPCODE(ifgt);
688 INSTRUCTION_OPCODE(endif);
689 INSTRUCTION_OPCODE(stop);
690 INSTRUCTION_OPCODE(endscript);
691 }
692
693
694
695 } // namespace Parallaction
696