Ticket #234: script_v1.cpp

File script_v1.cpp, 58.2 KB (added by SF/cccp_99, 19 years ago)

Fixed Loom CD Audio not playing when MP3 audio is enabled.

Line 
1/* ScummVM - Scumm Interpreter
2 * Copyright (C) 2001 Ludvig Strigeus
3 * Copyright (C) 2001/2002 The ScummVM project
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 * $Header: /cvsroot/scummvm/scummvm/script_v1.cpp,v 1.102 2002/05/08 10:33:30 ender Exp $
20 *
21 */
22
23#include "stdafx.h"
24#include "scumm.h"
25
26void Scumm::setupOpcodes()
27{
28 static const OpcodeProc opcode_list[] = {
29 /* 00 */
30 &Scumm::o5_stopObjectCode,
31 &Scumm::o5_putActor,
32 &Scumm::o5_startMusic,
33 &Scumm::o5_getActorRoom,
34 /* 04 */
35 &Scumm::o5_isGreaterEqual,
36 &Scumm::o5_drawObject,
37 &Scumm::o5_getActorElevation,
38 &Scumm::o5_setState,
39 /* 08 */
40 &Scumm::o5_isNotEqual,
41 &Scumm::o5_faceActor,
42 &Scumm::o5_startScript,
43 &Scumm::o5_getVerbEntrypoint,
44 /* 0C */
45 &Scumm::o5_resourceRoutines,
46 &Scumm::o5_walkActorToActor,
47 &Scumm::o5_putActorAtObject,
48 &Scumm::o5_getObjectState,
49 /* 10 */
50 &Scumm::o5_getObjectOwner,
51 &Scumm::o5_animateActor,
52 &Scumm::o5_panCameraTo,
53 &Scumm::o5_actorSet,
54 /* 14 */
55 &Scumm::o5_print,
56 &Scumm::o5_actorFromPos,
57 &Scumm::o5_getRandomNr,
58 &Scumm::o5_and,
59 /* 18 */
60 &Scumm::o5_jumpRelative,
61 &Scumm::o5_doSentence,
62 &Scumm::o5_move,
63 &Scumm::o5_multiply,
64 /* 1C */
65 &Scumm::o5_startSound,
66 &Scumm::o5_ifClassOfIs,
67 &Scumm::o5_walkActorTo,
68 &Scumm::o5_isActorInBox,
69 /* 20 */
70 &Scumm::o5_stopMusic,
71 &Scumm::o5_putActor,
72 &Scumm::o5_getAnimCounter,
73 &Scumm::o5_getActorY,
74 /* 24 */
75 &Scumm::o5_loadRoomWithEgo,
76 &Scumm::o5_pickupObject,
77 &Scumm::o5_setVarRange,
78 &Scumm::o5_stringOps,
79 /* 28 */
80 &Scumm::o5_equalZero,
81 &Scumm::o5_setOwnerOf,
82 &Scumm::o5_startScript,
83 &Scumm::o5_delayVariable,
84 /* 2C */
85 &Scumm::o5_cursorCommand,
86 &Scumm::o5_putActorInRoom,
87 &Scumm::o5_delay,
88 &Scumm::o5_getObjectState,
89 /* 30 */
90 &Scumm::o5_matrixOps,
91 &Scumm::o5_getInventoryCount,
92 &Scumm::o5_setCameraAt,
93 &Scumm::o5_roomOps,
94 /* 34 */
95 &Scumm::o5_getDist,
96 &Scumm::o5_findObject,
97 &Scumm::o5_walkActorToObject,
98 &Scumm::o5_startObject,
99 /* 38 */
100 &Scumm::o5_lessOrEqual,
101 &Scumm::o5_doSentence,
102 &Scumm::o5_subtract,
103 &Scumm::o5_getActorScale,
104 /* 3C */
105 &Scumm::o5_stopSound,
106 &Scumm::o5_findInventory,
107 &Scumm::o5_walkActorTo,
108 &Scumm::o5_drawBox,
109 /* 40 */
110 &Scumm::o5_cutscene,
111 &Scumm::o5_putActor,
112 &Scumm::o5_chainScript,
113 &Scumm::o5_getActorX,
114 /* 44 */
115 &Scumm::o5_isLess,
116 &Scumm::o5_drawObject,
117 &Scumm::o5_increment,
118 &Scumm::o5_setState,
119 /* 48 */
120 &Scumm::o5_isEqual,
121 &Scumm::o5_faceActor,
122 &Scumm::o5_startScript,
123 &Scumm::o5_getVerbEntrypoint,
124 /* 4C */
125 &Scumm::o5_soundKludge,
126 &Scumm::o5_walkActorToActor,
127 &Scumm::o5_putActorAtObject,
128 &Scumm::o5_badOpcode,
129 /* 50 */
130 &Scumm::o5_pickupObjectOld,
131 &Scumm::o5_animateActor,
132 &Scumm::o5_actorFollowCamera,
133 &Scumm::o5_actorSet,
134 /* 54 */
135 &Scumm::o5_setObjectName,
136 &Scumm::o5_actorFromPos,
137 &Scumm::o5_getActorMoving,
138 &Scumm::o5_or,
139 /* 58 */
140 &Scumm::o5_overRide,
141 &Scumm::o5_doSentence,
142 &Scumm::o5_add,
143 &Scumm::o5_divide,
144 /* 5C */
145 &Scumm::o5_oldRoomEffect,
146 &Scumm::o5_actorSetClass,
147 &Scumm::o5_walkActorTo,
148 &Scumm::o5_isActorInBox,
149 /* 60 */
150 &Scumm::o5_freezeScripts,
151 &Scumm::o5_putActor,
152 &Scumm::o5_stopScript,
153 &Scumm::o5_getActorFacing,
154 /* 64 */
155 &Scumm::o5_loadRoomWithEgo,
156 &Scumm::o5_pickupObject,
157 &Scumm::o5_getClosestObjActor,
158 &Scumm::o5_dummy,
159 /* 68 */
160 &Scumm::o5_getScriptRunning,
161 &Scumm::o5_setOwnerOf,
162 &Scumm::o5_startScript,
163 &Scumm::o5_debug,
164 /* 6C */
165 &Scumm::o5_getActorWidth,
166 &Scumm::o5_putActorInRoom,
167 &Scumm::o5_stopObjectScript,
168 &Scumm::o5_badOpcode,
169 /* 70 */
170 &Scumm::o5_lights,
171 &Scumm::o5_getActorCostume,
172 &Scumm::o5_loadRoom,
173 &Scumm::o5_roomOps,
174 /* 74 */
175 &Scumm::o5_getDist,
176 &Scumm::o5_findObject,
177 &Scumm::o5_walkActorToObject,
178 &Scumm::o5_startObject,
179 /* 78 */
180 &Scumm::o5_isGreater, /* less? */
181 &Scumm::o5_doSentence,
182 &Scumm::o5_verbOps,
183 &Scumm::o5_getActorWalkBox,
184 /* 7C */
185 &Scumm::o5_isSoundRunning,
186 &Scumm::o5_findInventory,
187 &Scumm::o5_walkActorTo,
188 &Scumm::o5_drawBox,
189 /* 80 */
190 &Scumm::o5_breakHere,
191 &Scumm::o5_putActor,
192 &Scumm::o5_startMusic,
193 &Scumm::o5_getActorRoom,
194 /* 84 */
195 &Scumm::o5_isGreaterEqual, /* less equal? */
196 &Scumm::o5_drawObject,
197 &Scumm::o5_getActorElevation,
198 &Scumm::o5_setState,
199 /* 88 */
200 &Scumm::o5_isNotEqual,
201 &Scumm::o5_faceActor,
202 &Scumm::o5_startScript,
203 &Scumm::o5_getVerbEntrypoint,
204 /* 8C */
205 &Scumm::o5_resourceRoutines,
206 &Scumm::o5_walkActorToActor,
207 &Scumm::o5_putActorAtObject,
208 &Scumm::o5_getObjectState,
209 /* 90 */
210 &Scumm::o5_getObjectOwner,
211 &Scumm::o5_animateActor,
212 &Scumm::o5_panCameraTo,
213 &Scumm::o5_actorSet,
214 /* 94 */
215 &Scumm::o5_print,
216 &Scumm::o5_actorFromPos,
217 &Scumm::o5_getRandomNr,
218 &Scumm::o5_and,
219 /* 98 */
220 &Scumm::o5_quitPauseRestart,
221 &Scumm::o5_doSentence,
222 &Scumm::o5_move,
223 &Scumm::o5_multiply,
224 /* 9C */
225 &Scumm::o5_startSound,
226 &Scumm::o5_ifClassOfIs,
227 &Scumm::o5_walkActorTo,
228 &Scumm::o5_isActorInBox,
229 /* A0 */
230 &Scumm::o5_stopObjectCode,
231 &Scumm::o5_putActor,
232 &Scumm::o5_getAnimCounter,
233 &Scumm::o5_getActorY,
234 /* A4 */
235 &Scumm::o5_loadRoomWithEgo,
236 &Scumm::o5_pickupObject,
237 &Scumm::o5_setVarRange,
238 &Scumm::o5_dummy,
239 /* A8 */
240 &Scumm::o5_notEqualZero,
241 &Scumm::o5_setOwnerOf,
242 &Scumm::o5_startScript,
243 &Scumm::o5_saveRestoreVerbs,
244 /* AC */
245 &Scumm::o5_expression,
246 &Scumm::o5_putActorInRoom,
247 &Scumm::o5_wait,
248 &Scumm::o5_badOpcode,
249 /* B0 */
250 &Scumm::o5_matrixOps,
251 &Scumm::o5_getInventoryCount,
252 &Scumm::o5_setCameraAt,
253 &Scumm::o5_roomOps,
254 /* B4 */
255 &Scumm::o5_getDist,
256 &Scumm::o5_findObject,
257 &Scumm::o5_walkActorToObject,
258 &Scumm::o5_startObject,
259 /* B8 */
260 &Scumm::o5_lessOrEqual,
261 &Scumm::o5_doSentence,
262 &Scumm::o5_subtract,
263 &Scumm::o5_getActorScale,
264 /* BC */
265 &Scumm::o5_stopSound,
266 &Scumm::o5_findInventory,
267 &Scumm::o5_walkActorTo,
268 &Scumm::o5_drawBox,
269 /* C0 */
270 &Scumm::o5_endCutscene,
271 &Scumm::o5_putActor,
272 &Scumm::o5_chainScript,
273 &Scumm::o5_getActorX,
274 /* C4 */
275 &Scumm::o5_isLess,
276 &Scumm::o5_drawObject,
277 &Scumm::o5_decrement,
278 &Scumm::o5_setState,
279 /* C8 */
280 &Scumm::o5_isEqual,
281 &Scumm::o5_faceActor,
282 &Scumm::o5_startScript,
283 &Scumm::o5_getVerbEntrypoint,
284 /* CC */
285 &Scumm::o5_pseudoRoom,
286 &Scumm::o5_walkActorToActor,
287 &Scumm::o5_putActorAtObject,
288 &Scumm::o5_badOpcode,
289 /* D0 */
290 &Scumm::o5_pickupObjectOld,
291 &Scumm::o5_animateActor,
292 &Scumm::o5_actorFollowCamera,
293 &Scumm::o5_actorSet,
294 /* D4 */
295 &Scumm::o5_setObjectName,
296 &Scumm::o5_actorFromPos,
297 &Scumm::o5_getActorMoving,
298 &Scumm::o5_or,
299 /* D8 */
300 &Scumm::o5_printEgo,
301 &Scumm::o5_doSentence,
302 &Scumm::o5_add,
303 &Scumm::o5_divide,
304 /* DC */
305 &Scumm::o5_oldRoomEffect,
306 &Scumm::o5_actorSetClass,
307 &Scumm::o5_walkActorTo,
308 &Scumm::o5_isActorInBox,
309 /* E0 */
310 &Scumm::o5_freezeScripts,
311 &Scumm::o5_putActor,
312 &Scumm::o5_stopScript,
313 &Scumm::o5_getActorFacing,
314 /* E4 */
315 &Scumm::o5_loadRoomWithEgo,
316 &Scumm::o5_pickupObject,
317 &Scumm::o5_getClosestObjActor,
318 &Scumm::o5_dummy,
319 /* E8 */
320 &Scumm::o5_getScriptRunning,
321 &Scumm::o5_setOwnerOf,
322 &Scumm::o5_startScript,
323 &Scumm::o5_debug,
324 /* EC */
325 &Scumm::o5_getActorWidth,
326 &Scumm::o5_putActorInRoom,
327 &Scumm::o5_stopObjectScript,
328 &Scumm::o5_badOpcode,
329 /* F0 */
330 &Scumm::o5_lights,
331 &Scumm::o5_getActorCostume,
332 &Scumm::o5_loadRoom,
333 &Scumm::o5_roomOps,
334 /* F4 */
335 &Scumm::o5_getDist,
336 &Scumm::o5_findObject,
337 &Scumm::o5_walkActorToObject,
338 &Scumm::o5_startObject,
339 /* F8 */
340 &Scumm::o5_isGreater,
341 &Scumm::o5_doSentence,
342 &Scumm::o5_verbOps,
343 &Scumm::o5_getActorWalkBox,
344 /* FC */
345 &Scumm::o5_isSoundRunning,
346 &Scumm::o5_findInventory,
347 &Scumm::o5_walkActorTo,
348 &Scumm::o5_drawBox
349 };
350
351 static const char *opcode_lookup[] = {
352 /* 00 */
353 "o5_stopObjectCode",
354 "o5_putActor",
355 "o5_startMusic",
356 "o5_getActorRoom",
357 /* 04 */
358 "o5_isGreaterEqual",
359 "o5_drawObject",
360 "o5_getActorElevation",
361 "o5_setState",
362 /* 08 */
363 "o5_isNotEqual",
364 "o5_faceActor",
365 "o5_startScript",
366 "o5_getVerbEntrypoint",
367 /* 0C */
368 "o5_resourceRoutines",
369 "o5_walkActorToActor",
370 "o5_putActorAtObject",
371 "o5_getObjectState",
372 /* 10 */
373 "o5_getObjectOwner",
374 "o5_animateActor",
375 "o5_panCameraTo",
376 "o5_actorSet",
377 /* 14 */
378 "o5_print",
379 "o5_actorFromPos",
380 "o5_getRandomNr",
381 "o5_and",
382 /* 18 */
383 "o5_jumpRelative",
384 "o5_doSentence",
385 "o5_move",
386 "o5_multiply",
387 /* 1C */
388 "o5_startSound",
389 "o5_ifClassOfIs",
390 "o5_walkActorTo",
391 "o5_isActorInBox",
392 /* 20 */
393 "o5_stopMusic",
394 "o5_putActor",
395 "o5_getAnimCounter",
396 "o5_getActorY",
397 /* 24 */
398 "o5_loadRoomWithEgo",
399 "o5_pickupObject",
400 "o5_setVarRange",
401 "o5_stringOps",
402 /* 28 */
403 "o5_equalZero",
404 "o5_setOwnerOf",
405 "o5_startScript",
406 "o5_delayVariable",
407 /* 2C */
408 "o5_cursorCommand",
409 "o5_putActorInRoom",
410 "o5_delay",
411 "o5_badOpcode",
412 /* 30 */
413 "o5_matrixOps",
414 "o5_getInventoryCount",
415 "o5_setCameraAt",
416 "o5_roomOps",
417 /* 34 */
418 "o5_getDist",
419 "o5_findObject",
420 "o5_walkActorToObject",
421 "o5_startObject",
422 /* 38 */
423 "o5_lessOrEqual",
424 "o5_doSentence",
425 "o5_subtract",
426 "o5_getActorScale",
427 /* 3C */
428 "o5_stopSound",
429 "o5_findInventory",
430 "o5_walkActorTo",
431 "o5_drawBox",
432 /* 40 */
433 "o5_cutscene",
434 "o5_putActor",
435 "o5_chainScript",
436 "o5_getActorX",
437 /* 44 */
438 "o5_isLess",
439 "o5_badOpcode",
440 "o5_increment",
441 "o5_setState",
442 /* 48 */
443 "o5_isEqual",
444 "o5_faceActor",
445 "o5_startScript",
446 "o5_getVerbEntrypoint",
447 /* 4C */
448 "o5_soundKludge",
449 "o5_walkActorToActor",
450 "o5_putActorAtObject",
451 "o5_badOpcode",
452 /* 50 */
453 "o5_pickupObjectOld",
454 "o5_animateActor",
455 "o5_actorFollowCamera",
456 "o5_actorSet",
457 /* 54 */
458 "o5_setObjectName",
459 "o5_actorFromPos",
460 "o5_getActorMoving",
461 "o5_or",
462 /* 58 */
463 "o5_overRide",
464 "o5_doSentence",
465 "o5_add",
466 "o5_divide",
467 /* 5C */
468 "o5_oldRoomEffect",
469 "o5_actorSetClass",
470 "o5_walkActorTo",
471 "o5_isActorInBox",
472 /* 60 */
473 "o5_freezeScripts",
474 "o5_putActor",
475 "o5_stopScript",
476 "o5_getActorFacing",
477 /* 64 */
478 "o5_loadRoomWithEgo",
479 "o5_pickupObject",
480 "o5_getClosestObjActor",
481 "o5_dummy",
482 /* 68 */
483 "o5_getScriptRunning",
484 "o5_setOwnerOf",
485 "o5_startScript",
486 "o5_debug",
487 /* 6C */
488 "o5_getActorWidth",
489 "o5_putActorInRoom",
490 "o5_stopObjectScript",
491 "o5_badOpcode",
492 /* 70 */
493 "o5_lights",
494 "o5_getActorCostume",
495 "o5_loadRoom",
496 "o5_roomOps",
497 /* 74 */
498 "o5_getDist",
499 "o5_findObject",
500 "o5_walkActorToObject",
501 "o5_startObject",
502 /* 78 */
503 "o5_isGreater", /* less? */
504 "o5_doSentence",
505 "o5_verbOps",
506 "o5_getActorWalkBox",
507 /* 7C */
508 "o5_isSoundRunning",
509 "o5_findInventory",
510 "o5_walkActorTo",
511 "o5_drawBox",
512 /* 80 */
513 "o5_breakHere",
514 "o5_putActor",
515 "o5_startMusic",
516 "o5_getActorRoom",
517 /* 84 */
518 "o5_isGreaterEqual", /* less equal? */
519 "o5_drawObject",
520 "o5_getActorElevation",
521 "o5_setState",
522 /* 88 */
523 "o5_isNotEqual",
524 "o5_faceActor",
525 "o5_startScript",
526 "o5_getVerbEntrypoint",
527 /* 8C */
528 "o5_resourceRoutines",
529 "o5_walkActorToActor",
530 "o5_putActorAtObject",
531 "o5_getObjectState",
532 /* 90 */
533 "o5_getObjectOwner",
534 "o5_animateActor",
535 "o5_panCameraTo",
536 "o5_actorSet",
537 /* 94 */
538 "o5_print",
539 "o5_actorFromPos",
540 "o5_getRandomNr",
541 "o5_and",
542 /* 98 */
543 "o5_quitPauseRestart",
544 "o5_doSentence",
545 "o5_move",
546 "o5_multiply",
547 /* 9C */
548 "o5_startSound",
549 "o5_ifClassOfIs",
550 "o5_walkActorTo",
551 "o5_isActorInBox",
552 /* A0 */
553 "o5_stopObjectCode",
554 "o5_putActor",
555 "o5_getAnimCounter",
556 "o5_getActorY",
557 /* A4 */
558 "o5_loadRoomWithEgo",
559 "o5_pickupObject",
560 "o5_setVarRange",
561 "o5_dummy",
562 /* A8 */
563 "o5_notEqualZero",
564 "o5_setOwnerOf",
565 "o5_startScript",
566 "o5_saveRestoreVerbs",
567 /* AC */
568 "o5_expression",
569 "o5_putActorInRoom",
570 "o5_wait",
571 "o5_badOpcode",
572 /* B0 */
573 "o5_matrixOps",
574 "o5_getInventoryCount",
575 "o5_setCameraAt",
576 "o5_roomOps",
577 /* B4 */
578 "o5_getDist",
579 "o5_findObject",
580 "o5_walkActorToObject",
581 "o5_startObject",
582 /* B8 */
583 "o5_lessOrEqual",
584 "o5_doSentence",
585 "o5_subtract",
586 "o5_getActorScale",
587 /* BC */
588 "o5_stopSound",
589 "o5_findInventory",
590 "o5_walkActorTo",
591 "o5_drawBox",
592 /* C0 */
593 "o5_endCutscene",
594 "o5_putActor",
595 "o5_chainScript",
596 "o5_getActorX",
597 /* C4 */
598 "o5_isLess",
599 "o5_badOpcode",
600 "o5_decrement",
601 "o5_setState",
602 /* C8 */
603 "o5_isEqual",
604 "o5_faceActor",
605 "o5_startScript",
606 "o5_getVerbEntrypoint",
607 /* CC */
608 "o5_pseudoRoom",
609 "o5_walkActorToActor",
610 "o5_putActorAtObject",
611 "o5_badOpcode",
612 /* D0 */
613 "o5_pickupObjectOld",
614 "o5_animateActor",
615 "o5_actorFollowCamera",
616 "o5_actorSet",
617 /* D4 */
618 "o5_setObjectName",
619 "o5_actorFromPos",
620 "o5_getActorMoving",
621 "o5_or",
622 /* D8 */
623 "o5_printEgo",
624 "o5_doSentence",
625 "o5_add",
626 "o5_divide",
627 /* DC */
628 "o5_oldRoomEffect",
629 "o5_actorSetClass",
630 "o5_walkActorTo",
631 "o5_isActorInBox",
632 /* E0 */
633 "o5_freezeScripts",
634 "o5_putActor",
635 "o5_stopScript",
636 "o5_getActorFacing",
637 /* E4 */
638 "o5_loadRoomWithEgo",
639 "o5_pickupObject",
640 "o5_getClosestObjActor",
641 "o5_dummy",
642 /* E8 */
643 "o5_getScriptRunning",
644 "o5_setOwnerOf",
645 "o5_startScript",
646 "o5_debug",
647 /* EC */
648 "o5_getActorWidth",
649 "o5_putActorInRoom",
650 "o5_stopObjectScript",
651 "o5_badOpcode",
652 /* F0 */
653 "o5_lights",
654 "o5_getActorCostume",
655 "o5_loadRoom",
656 "o5_roomOps",
657 /* F4 */
658 "o5_getDist",
659 "o5_findObject",
660 "o5_walkActorToObject",
661 "o5_startObject",
662 /* F8 */
663 "o5_isGreater",
664 "o5_doSentence",
665 "o5_verbOps",
666 "o5_getActorWalkBox",
667 /* FC */
668 "o5_isSoundRunning",
669 "o5_findInventory",
670 "o5_walkActorTo",
671 "o5_drawBox",
672 };
673
674
675 _opcodes = opcode_list;
676 _opcodes_lookup = opcode_lookup;
677}
678
679void Scumm::o5_actorFollowCamera()
680{
681 actorFollowCamera(getVarOrDirectByte(0x80));
682}
683
684void Scumm::o5_actorFromPos()
685{
686 int x, y;
687 getResultPos();
688 x = getVarOrDirectWord(0x80);
689 y = getVarOrDirectWord(0x40);
690 setResult(getActorFromPos(x, y));
691}
692
693void Scumm::o5_actorSet()
694{
695 static const byte convertTable[20] =
696 { 1, 0, 0, 2, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20 };
697 int act = getVarOrDirectByte(0x80);
698 Actor *a;
699 int i, j;
700
701 if (act == 0)
702 act = 1;
703
704 a = derefActorSafe(act, "actorSet");
705
706 while ((_opcode = fetchScriptByte()) != 0xFF) {
707 if (_features & GF_SMALL_HEADER)
708 _opcode = (_opcode & 0xE0) | convertTable[(_opcode & 0x1F) - 1];
709
710 if (!a)
711 return;
712
713 switch (_opcode & 0x1F) {
714 case 0: /* dummy case */
715 getVarOrDirectByte(0x80);
716 break;
717 case 1: /* costume */
718 setActorCostume(a, getVarOrDirectByte(0x80));
719 break;
720 case 2: /* walkspeed */
721 i = getVarOrDirectByte(0x80);
722 j = getVarOrDirectByte(0x40);
723 setActorWalkSpeed(a, i, j);
724 break;
725 case 3: /* sound */
726 a->sound[0] = getVarOrDirectByte(0x80);
727 break;
728 case 4: /* walkanim */
729 a->walkFrame = getVarOrDirectByte(0x80);
730 break;
731 case 5: /* talkanim */
732 a->talkFrame1 = getVarOrDirectByte(0x80);
733 a->talkFrame2 = getVarOrDirectByte(0x40);
734 break;
735 case 6: /* standanim */
736 a->standFrame = getVarOrDirectByte(0x80);
737 break;
738 case 7: /* ignore */
739 getVarOrDirectByte(0x80);
740 getVarOrDirectByte(0x40);
741 getVarOrDirectByte(0x20);
742 break;
743 case 8: /* init */
744 initActor(a, 0);
745 break;
746 case 9: /* elevation */
747 a->elevation = getVarOrDirectWord(0x80);
748 a->needRedraw = true;
749 a->needBgReset = true;
750 break;
751 case 10: /* defaultanims */
752 a->initFrame = 1;
753 a->walkFrame = 2;
754 a->standFrame = 3;
755 a->talkFrame1 = 4;
756 a->talkFrame2 = 5;
757 break;
758 case 11: /* palette */
759 i = getVarOrDirectByte(0x80);
760 j = getVarOrDirectByte(0x40);
761 checkRange(31, 0, i, "Illegal palet slot %d");
762 a->palette[i] = j;
763 a->needRedraw = true;
764 break;
765 case 12: /* talk color */
766 a->talkColor = getVarOrDirectByte(0x80);
767 break;
768 case 13: /* name */
769 loadPtrToResource(rtActorName, a->number, NULL);
770 break;
771 case 14: /* initanim */
772 a->initFrame = getVarOrDirectByte(0x80);
773 break;
774 case 15: /* unk */
775 error("o5_actorset:unk not implemented");
776 break;
777 case 16: /* width */
778 a->width = getVarOrDirectByte(0x80);
779 break;
780 case 17: /* scale */
781 if (_gameId == GID_MONKEY_VGA) {
782 a->scalex = a->scaley = getVarOrDirectByte(0x80);
783 } else {
784 a->scalex = getVarOrDirectByte(0x80);
785 a->scaley = getVarOrDirectByte(0x40);
786 }
787
788 if (a->scalex > 255 || a->scaley > 255)
789 error("Setting an bad actor scale!");
790 a->needRedraw = true;
791 a->needBgReset = true;
792 break;
793 case 18: /* neverzclip */
794 a->forceClip = 0;
795 break;
796 case 19: /* setzclip */
797 a->forceClip = getVarOrDirectByte(0x80);
798 break;
799 case 20: /* ignoreboxes */
800 a->ignoreBoxes = 1;
801 a->forceClip = 0;
802 FixRoom:
803 if (a->room == _currentRoom)
804 putActor(a, a->x, a->y, a->room);
805 break;
806 case 21: /* followboxes */
807 a->ignoreBoxes = 0;
808 a->forceClip = 0;
809 goto FixRoom;
810
811 case 22: /* animspeed */
812 a->animSpeed = getVarOrDirectByte(0x80);
813 a->animProgress = 0;
814 break;
815 case 23: /* unk2 */
816 a->shadow_mode = getVarOrDirectByte(0x80); /* shadow mode */
817 break;
818 default:
819 warning("o5_actorSet: default case");
820 }
821 }
822}
823
824void Scumm::o5_actorSetClass()
825{
826 int act = getVarOrDirectWord(0x80);
827 int newClass;
828
829 while ((_opcode = fetchScriptByte()) != 0xFF) {
830 newClass = getVarOrDirectWord(0x80);
831 if (newClass == 0) {
832 _classData[act] = 0;
833 if((_features & GF_SMALL_HEADER) && act <= NUM_ACTORS)
834 {
835 Actor *a;
836 a = derefActorSafe(act, "actorSetClass");
837 a->forceClip=0;
838 }
839 continue;
840 }
841
842
843 if(_gameId == GID_INDY3_256)
844
845 newClass--;
846
847
848 if (newClass & 0x80)
849 putClass(act, newClass, 1);
850 else
851 putClass(act, newClass, 0);
852 }
853}
854
855void Scumm::o5_add()
856{
857 int a;
858 getResultPos();
859 a = getVarOrDirectWord(0x80);
860 setResult(readVar(_resultVarNumber) + a);
861}
862
863void Scumm::o5_and()
864{
865 int a;
866 getResultPos();
867 a = getVarOrDirectWord(0x80);
868 setResult(readVar(_resultVarNumber) & a);
869}
870
871void Scumm::o5_animateActor()
872{
873 int act, anim;
874
875 act = getVarOrDirectByte(0x80);
876 anim = getVarOrDirectByte(0x40);
877 animateActor(act, anim);
878}
879
880void Scumm::o5_badOpcode()
881{
882 error("Scumm opcode %d illegal", _opcode);
883}
884
885void Scumm::o5_breakHere()
886{
887 updateScriptPtr();
888 _currentScript = 0xFF;
889}
890
891void Scumm::o5_chainScript()
892{
893 int16 vars[16];
894 int data;
895 int cur;
896
897 data = getVarOrDirectByte(0x80);
898
899 getWordVararg(vars);
900
901 cur = _currentScript;
902
903 vm.slot[cur].number = 0;
904 vm.slot[cur].status = 0;
905 _currentScript = 0xFF;
906
907 runScript(data, vm.slot[cur].unk1, vm.slot[cur].unk2, vars);
908}
909
910void Scumm::o5_cursorCommand()
911{
912 int i, j, k;
913 int16 table[16];
914 switch ((_opcode = fetchScriptByte()) & 0x1F) {
915 case 1: /* cursor show */
916 _cursorState = 1;
917 verbMouseOver(0);
918 break;
919 case 2: /* cursor hide */
920 _cursorState = 0;
921 verbMouseOver(0);
922 break;
923 case 3: /* userput on */
924 _userPut = 1;
925 break;
926 case 4: /* userput off */
927 _userPut = 0;
928 break;
929 case 5: /* cursor soft on */
930 _cursorState++;
931 verbMouseOver(0);
932 break;
933 case 6: /* cursor soft off */
934 _cursorState--;
935 verbMouseOver(0);
936 break;
937 case 7: /* userput soft on */
938 _userPut++;
939 break;
940 case 8: /* userput soft off */
941 _userPut--;
942 break;
943 case 10: /* set cursor img */
944 i = getVarOrDirectByte(0x80);
945 j = getVarOrDirectByte(0x40);
946 if (_gameId != GID_LOOM256)
947 setCursorImg(i, j, 1);
948 break;
949 case 11: /* set cursor hotspot */
950 i = getVarOrDirectByte(0x80);
951 j = getVarOrDirectByte(0x40);
952 k = getVarOrDirectByte(0x20);
953 setCursorHotspot2(j, k);
954 break;
955
956 case 12: /* init cursor */
957 setCursor(getVarOrDirectByte(0x80));
958 break;
959 case 13: /* init charset */
960 initCharset(getVarOrDirectByte(0x80));
961 break;
962 case 14: /* unk */
963 getWordVararg(table);
964 for (i = 0; i < 16; i++)
965 charset._colorMap[i] = _charsetData[string[1].t_charset][i] =
966 (unsigned char)table[i];
967 break;
968 }
969
970 _vars[VAR_CURSORSTATE] = _cursorState;
971 _vars[VAR_USERPUT] = _userPut;
972}
973
974void Scumm::o5_cutscene()
975{
976 int16 args[16];
977 getWordVararg(args);
978 cutscene(args);
979}
980
981void Scumm::o5_endCutscene()
982{
983 // FIXME MI2: wrong direction/levitation of G. on the bridge
984 if ((_gameId == GID_MONKEY2) && (_currentRoom == 7) &&
985 (vm.slot[_currentScript].number == 203)) {
986 Actor *a = derefActor(1);
987 if (a->x == 571)
988 a->facing = 90;
989 }
990
991 endCutscene();
992}
993
994void Scumm::o5_debug()
995{
996 getVarOrDirectWord(0x80);
997}
998
999void Scumm::o5_decrement()
1000{
1001 getResultPos();
1002 setResult(readVar(_resultVarNumber) - 1);
1003}
1004
1005void Scumm::o5_delay()
1006{
1007 int delay = fetchScriptByte();
1008 delay |= fetchScriptByte() << 8;
1009 delay |= fetchScriptByte() << 16;
1010 vm.slot[_currentScript].delay = delay;
1011 vm.slot[_currentScript].status = 1;
1012
1013 o5_breakHere();
1014}
1015
1016void Scumm::o5_delayVariable()
1017{
1018 vm.slot[_currentScript].delay = readVar(fetchScriptWord());
1019 vm.slot[_currentScript].status = 1;
1020 o5_breakHere();
1021}
1022
1023void Scumm::o5_divide()
1024{
1025 int a;
1026 getResultPos();
1027 a = getVarOrDirectWord(0x80);
1028 if (a == 0) {
1029 error("Divide by zero");
1030 setResult(0);
1031 } else
1032 setResult(readVar(_resultVarNumber) / a);
1033}
1034
1035void Scumm::o5_doSentence()
1036{
1037 int a, b;
1038 SentenceTab *st;
1039
1040 a = getVarOrDirectByte(0x80);
1041 if (a == 0xFE) {
1042 _sentenceNum = 0;
1043 stopScriptNr(_vars[VAR_SENTENCE_SCRIPT]);
1044 clearClickedStatus();
1045 return;
1046 }
1047
1048 st = &sentence[_sentenceNum++];
1049
1050 st->unk5 = a;
1051 st->unk4 = getVarOrDirectWord(0x40);
1052 b = st->unk3 = getVarOrDirectWord(0x20);
1053 if (b == 0) {
1054 st->unk2 = 0;
1055 } else {
1056 st->unk2 = 1;
1057 }
1058 st->unk = 0;
1059}
1060
1061void Scumm::o5_drawBox()
1062{
1063 int x, y, x2, y2, color;
1064
1065 x = getVarOrDirectWord(0x80);
1066 y = getVarOrDirectWord(0x40);
1067
1068 _opcode = fetchScriptByte();
1069 x2 = getVarOrDirectWord(0x80);
1070 y2 = getVarOrDirectWord(0x40);
1071 color = getVarOrDirectByte(0x20);
1072
1073 drawBox(x, y, x2, y2, color);
1074}
1075
1076void Scumm::o5_drawObject()
1077{
1078 int state, obj, idx, i;
1079 ObjectData *od;
1080 uint16 x, y, w, h;
1081 int xpos, ypos;
1082
1083 state = 1;
1084 xpos = ypos = 255;
1085 obj = getVarOrDirectWord(0x80);
1086
1087 if (_features & GF_SMALL_HEADER) {
1088 int temp = getVarOrDirectWord(0x40);
1089 int temp2= getVarOrDirectWord(0x20); // Room
1090
1091 idx = getObjectIndex(obj);
1092 if (idx == -1)
1093 return;
1094 od = &_objs[idx];
1095 xpos = ypos = 255;
1096 if (temp != 0xFF) {
1097
1098 od->x_pos = temp<<3;
1099
1100 od->y_pos = temp2<<3;
1101 }
1102
1103
1104
1105 addObjectToDrawQue(idx);
1106
1107 x = od->x_pos;
1108 y = od->y_pos;
1109 w = od->width;
1110 h = od->height;
1111
1112 i = _numObjectsInRoom;
1113 do {
1114 if (_objs[i].x_pos == x && _objs[i].y_pos == y && _objs[i].width == w
1115 && _objs[i].height == h)
1116 putState(_objs[i].obj_nr, 0);
1117 } while (--i);
1118
1119 putState(obj, state);
1120 return;
1121 }
1122
1123 switch ((_opcode = fetchScriptByte()) & 0x1F) {
1124 case 1: /* draw at */
1125 xpos = getVarOrDirectWord(0x80);
1126 ypos = getVarOrDirectWord(0x40);
1127 break;
1128 case 2: /* set state */
1129 state = getVarOrDirectWord(0x80);
1130 break;
1131 case 0x1F: /* neither */
1132 break;
1133 default:
1134 error("o5_drawObject: default case");
1135 }
1136
1137 idx = getObjectIndex(obj);
1138 if (idx == -1)
1139 return;
1140 od = &_objs[idx];
1141 if (xpos != 0xFF) {
1142 od->walk_x += (xpos << 3) - od->x_pos;
1143 od->x_pos = xpos << 3;
1144 od->walk_y += (ypos << 3) - od->y_pos;
1145 od->y_pos = ypos << 3;
1146 }
1147 addObjectToDrawQue(idx);
1148
1149 x = od->x_pos;
1150 y = od->y_pos;
1151 w = od->width;
1152 h = od->height;
1153
1154 i = _numObjectsInRoom;
1155 do {
1156 if (_objs[i].x_pos == x && _objs[i].y_pos == y
1157 && _objs[i].width == w && _objs[i].height == h)
1158 putState(_objs[i].obj_nr, 0);
1159 } while (--i);
1160
1161 putState(obj, state);
1162}
1163
1164void Scumm::o5_dummy()
1165{
1166 /* nothing */
1167}
1168
1169
1170void Scumm::o5_expression()
1171{
1172 int dst, i;
1173
1174 _scummStackPos = 0;
1175 getResultPos();
1176 dst = _resultVarNumber;
1177
1178 while ((_opcode = fetchScriptByte()) != 0xFF) {
1179 switch (_opcode & 0x1F) {
1180 case 1: /* varordirect */
1181 push(getVarOrDirectWord(0x80));
1182 break;
1183 case 2: /* add */
1184 i = pop();
1185 push(i + pop());
1186 break;
1187 case 3: /* sub */
1188 i = pop();
1189 push(pop() - i);
1190 break;
1191 case 4: /* mul */
1192 i = pop();
1193 push(i * pop());
1194 break;
1195 case 5: /* div */
1196 i = pop();
1197 if (i == 0)
1198 error("Divide by zero");
1199 push(pop() / i);
1200 break;
1201 case 6: /* normal opcode */
1202 _opcode = fetchScriptByte();
1203 (this->*(getOpcode(_opcode))) ();
1204 push(_vars[0]);
1205 break;
1206 }
1207 }
1208
1209 _resultVarNumber = dst;
1210 setResult(pop());
1211}
1212
1213void Scumm::o5_faceActor()
1214{
1215 int act, obj;
1216 act = getVarOrDirectByte(0x80);
1217 obj = getVarOrDirectWord(0x40);
1218 faceActorToObj(act, obj);
1219}
1220
1221void Scumm::o5_findInventory()
1222{
1223 int t;
1224 getResultPos();
1225 t = getVarOrDirectByte(0x80);
1226 setResult(findInventory(t, getVarOrDirectByte(0x40)));
1227}
1228
1229void Scumm::o5_findObject()
1230{
1231 int t;
1232 getResultPos();
1233 t = getVarOrDirectWord(0x80);
1234 setResult(findObject(t, getVarOrDirectWord(0x40)));
1235}
1236
1237void Scumm::o5_freezeScripts()
1238{
1239 int scr = getVarOrDirectByte(0x80);
1240
1241 if (scr != 0)
1242 freezeScripts(scr);
1243 else
1244 unfreezeScripts();
1245}
1246
1247void Scumm::o5_getActorCostume()
1248{
1249 getResultPos();
1250 setResult(derefActorSafe(getVarOrDirectByte(0x80), "o5_getActorCostume")->
1251 costume);
1252}
1253
1254void Scumm::o5_getActorElevation()
1255{
1256 getResultPos();
1257 setResult(derefActorSafe(getVarOrDirectByte(0x80), "o5_getActorElevation")->
1258 elevation);
1259}
1260
1261void Scumm::o5_getActorFacing()
1262{
1263 getResultPos();
1264 setResult(newDirToOldDir
1265 (derefActorSafe(getVarOrDirectByte(0x80), "o5_getActorFacing")->
1266 facing));
1267}
1268
1269void Scumm::o5_getActorMoving()
1270{
1271 getResultPos();
1272 setResult(derefActorSafe(getVarOrDirectByte(0x80), "o5_getActorMoving")->
1273 moving);
1274}
1275
1276void Scumm::o5_getActorRoom()
1277{
1278 int temp;
1279 Actor *act;
1280 getResultPos();
1281 temp = getVarOrDirectByte(0x80);
1282
1283 act = derefActorSafe(temp, "o5_getActorRoom");
1284 if (!act)
1285 return;
1286
1287 setResult(act->room);
1288}
1289
1290void Scumm::o5_getActorScale()
1291{
1292 if (_gameId == GID_INDY3_256) {
1293 getVarOrDirectByte(0x80); /*FIXME: missing stuff here */
1294 return;
1295 }
1296 getResultPos();
1297 setResult(derefActorSafe(getVarOrDirectByte(0x80), "o5_getActorScale")->
1298 scalex);
1299}
1300
1301void Scumm::o5_getActorWalkBox()
1302{
1303 getResultPos();
1304 setResult(derefActorSafe(getVarOrDirectByte(0x80), "o5_getActorWalkbox")->
1305 walkbox);
1306}
1307
1308void Scumm::o5_getActorWidth()
1309{
1310 getResultPos();
1311 setResult(derefActorSafe(getVarOrDirectByte(0x80), "o5_getActorWidth")->
1312 width);
1313}
1314
1315void Scumm::o5_getActorX()
1316{
1317 int actor;
1318 getResultPos();
1319
1320 if(_gameId == GID_INDY3_256)
1321
1322 actor = getVarOrDirectByte(0x80);
1323
1324 else
1325 actor = getVarOrDirectWord(0x80);
1326
1327 setResult(getObjX(actor));
1328}
1329
1330void Scumm::o5_getActorY()
1331{
1332
1333 int actor;
1334 getResultPos();
1335
1336 if(_gameId == GID_INDY3_256)
1337
1338 actor = getVarOrDirectByte(0x80);
1339
1340 else
1341
1342 actor = getVarOrDirectWord(0x80);
1343 setResult(getObjY(actor));
1344}
1345
1346void Scumm::o5_getAnimCounter()
1347{
1348
1349 Actor *a;
1350 getResultPos();
1351
1352 a=derefActorSafe(getVarOrDirectByte(0x80),"o5_getActorAnimCounter");
1353
1354 if(a) // FIXME
1355 setResult(a->cost.animCounter1);
1356
1357 else
1358
1359 setResult(0);
1360}
1361
1362void Scumm::o5_getClosestObjActor()
1363{
1364 int obj;
1365 int act;
1366 int closest_obj = 0xFF, closest_dist = 0xFF;
1367 int dist;
1368
1369 getResultPos();
1370
1371 act = getVarOrDirectWord(0x80);
1372 obj = _vars[VAR_V5_OBJECT_HI];
1373
1374 do {
1375 dist = getObjActToObjActDist(act, obj);
1376 if (dist < closest_dist) {
1377 closest_dist = dist;
1378 closest_obj = obj;
1379 }
1380 } while (--obj >= _vars[VAR_V5_OBJECT_LO]);
1381
1382 setResult(closest_dist);
1383}
1384
1385void Scumm::o5_getDist()
1386{
1387 int o1, o2;
1388 int r;
1389 getResultPos();
1390 o1 = getVarOrDirectWord(0x80);
1391 o2 = getVarOrDirectWord(0x40);
1392 r = getObjActToObjActDist(o1, o2);
1393
1394 /* Fix for monkey 2, dunno what's wrong in scummvm */
1395 if (_gameId == GID_MONKEY2 && vm.slot[_currentScript].number == 40
1396 && r < 60)
1397 r = 60;
1398
1399 if (r > 0) // FIXME: Fixes several off-by-one errors (eg,
1400 r--; // zak's tv). Find real cause of bug.
1401 setResult(r);
1402}
1403
1404void Scumm::o5_getInventoryCount()
1405{
1406 getResultPos();
1407 setResult(getInventoryCount(getVarOrDirectByte(0x80)));
1408}
1409
1410void Scumm::o5_getObjectOwner()
1411{
1412 getResultPos();
1413 setResult(getOwner(getVarOrDirectWord(0x80)));
1414}
1415
1416void Scumm::o5_getObjectState()
1417{
1418 if (_features & GF_SMALL_HEADER) {
1419 int a = getVarOrDirectWord(0x80);
1420 int b = getVarOrDirectByte(0x40);
1421
1422 if ((getState(a) & 0xF0 >> 4) != b)
1423 o5_jumpRelative();
1424 else
1425 ignoreScriptWord();
1426 } else {
1427 getResultPos();
1428 setResult(getState(getVarOrDirectWord(0x80)));
1429 }
1430}
1431
1432void Scumm::o5_getRandomNr()
1433{
1434 getResultPos();
1435 setResult(getRandomNumber(getVarOrDirectByte(0x80) + 1));
1436}
1437
1438void Scumm::o5_getScriptRunning()
1439{
1440 getResultPos();
1441 setResult(isScriptRunning(getVarOrDirectByte(0x80)));
1442}
1443
1444void Scumm::o5_getVerbEntrypoint()
1445{
1446 int a, b;
1447 getResultPos();
1448 a = getVarOrDirectWord(0x80);
1449 b = getVarOrDirectWord(0x40);
1450
1451 setResult(getVerbEntrypoint(a, b));
1452}
1453
1454void Scumm::o5_ifClassOfIs()
1455{
1456 int act, cls, b;
1457 bool cond = true;
1458
1459 act = getVarOrDirectWord(0x80);
1460
1461 while ((_opcode = fetchScriptByte()) != 0xFF) {
1462 cls = getVarOrDirectWord(0x80);
1463 b = getClass(act, cls);
1464
1465 if (cls & 0x80 && !b || !(cls & 0x80) && b)
1466 cond = false;
1467 }
1468 if (cond)
1469 ignoreScriptWord();
1470 else
1471 o5_jumpRelative();
1472}
1473
1474void Scumm::o5_increment()
1475{
1476 getResultPos();
1477 setResult(readVar(_resultVarNumber) + 1);
1478}
1479
1480void Scumm::o5_isActorInBox()
1481{
1482 int box;
1483 Actor *a;
1484
1485 a = derefActorSafe(getVarOrDirectByte(0x80), "o5_isActorInBox");
1486 box = getVarOrDirectByte(0x40);
1487
1488 if (!checkXYInBoxBounds(box, a->x, a->y))
1489 o5_jumpRelative();
1490 else
1491 ignoreScriptWord();
1492}
1493
1494void Scumm::o5_isEqual()
1495{
1496 int16 a = readVar(fetchScriptWord());
1497 int16 b = getVarOrDirectWord(0x80);
1498 if (b == a)
1499 ignoreScriptWord();
1500 else
1501 o5_jumpRelative();
1502
1503}
1504
1505void Scumm::o5_isGreater()
1506{
1507 int16 a = readVar(fetchScriptWord());
1508 int16 b = getVarOrDirectWord(0x80);
1509 if (b > a)
1510 ignoreScriptWord();
1511 else
1512 o5_jumpRelative();
1513}
1514
1515void Scumm::o5_isGreaterEqual()
1516{
1517 int16 a = readVar(fetchScriptWord());
1518 int16 b = getVarOrDirectWord(0x80);
1519 if (b >= a)
1520 ignoreScriptWord();
1521 else
1522 o5_jumpRelative();
1523}
1524
1525void Scumm::o5_isLess()
1526{
1527 int16 a = readVar(fetchScriptWord());
1528 int16 b = getVarOrDirectWord(0x80);
1529
1530 if (b < a)
1531 ignoreScriptWord();
1532 else
1533 o5_jumpRelative();
1534}
1535
1536void Scumm::o5_lessOrEqual()
1537{
1538 int16 a = readVar(fetchScriptWord());
1539 int16 b = getVarOrDirectWord(0x80);
1540 if (b <= a)
1541 ignoreScriptWord();
1542 else
1543 o5_jumpRelative();
1544}
1545
1546void Scumm::o5_isNotEqual()
1547{
1548 int16 a = readVar(fetchScriptWord());
1549 int16 b = getVarOrDirectWord(0x80);
1550 if (b != a)
1551 ignoreScriptWord();
1552 else
1553 o5_jumpRelative();
1554}
1555
1556void Scumm::o5_notEqualZero()
1557{
1558 int a = readVar(fetchScriptWord());
1559 if (a != 0)
1560 ignoreScriptWord();
1561 else
1562 o5_jumpRelative();
1563}
1564
1565void Scumm::o5_equalZero()
1566{
1567 int a = readVar(fetchScriptWord());
1568 if (a == 0)
1569 ignoreScriptWord();
1570 else
1571 o5_jumpRelative();
1572}
1573
1574void Scumm::o5_isSoundRunning()
1575{
1576 int snd;
1577 getResultPos();
1578 snd = getVarOrDirectByte(0x80);
1579 if (snd)
1580 snd = isSoundRunning(snd);
1581 setResult(snd);
1582}
1583
1584void Scumm::o5_jumpRelative()
1585{
1586 _scriptPointer += (int16) fetchScriptWord();
1587}
1588
1589void Scumm::o5_lights()
1590{
1591 int a, b, c;
1592
1593 a = getVarOrDirectByte(0x80);
1594 b = fetchScriptByte();
1595 c = fetchScriptByte();
1596
1597/* if (c==0)
1598 _vars[VAR_V5_DRAWFLAGS] = a;
1599 else if (c==1) {*/
1600 warning("o5_lights: lights not implemented");
1601// }
1602 _fullRedraw = 1;
1603}
1604
1605void Scumm::o5_loadRoom()
1606{
1607 int room;
1608
1609 room = getVarOrDirectByte(0x80);
1610 startScene(room, 0, 0);
1611 _fullRedraw = 1;
1612}
1613
1614void Scumm::o5_loadRoomWithEgo()
1615{
1616 int obj, room, x, y;
1617 Actor *a;
1618
1619 obj = getVarOrDirectWord(0x80);
1620 room = getVarOrDirectByte(0x40);
1621
1622 a = derefActorSafe(_vars[VAR_EGO], "o5_loadRoomWithEgo");
1623
1624 /* Warning: used previously _xPos, _yPos from a previous update of those */
1625 putActor(a, a->x, a->y, room);
1626
1627 x = (int16) fetchScriptWord();
1628 y = (int16) fetchScriptWord();
1629
1630 _egoPositioned = false;
1631
1632 _vars[VAR_WALKTO_OBJ] = obj;
1633 startScene(a->room, a, obj);
1634 _vars[VAR_WALKTO_OBJ] = 0;
1635
1636 camera._dest.x = camera._cur.x = a->x;
1637 setCameraFollows(a);
1638
1639 _fullRedraw = 1;
1640
1641 if (x != -1) {
1642 startWalkActor(a, x, y, -1);
1643 }
1644}
1645
1646void Scumm::o5_matrixOps()
1647{
1648 int a, b;
1649
1650 if (_features & GF_OLD256) {
1651 a = getVarOrDirectByte(0x80);
1652 b = fetchScriptByte();
1653 if (b == 0x40) // Lock Box
1654 setBoxFlags(a, 0x80);
1655 else
1656 setBoxFlags(a, 0);
1657 return;
1658 }
1659
1660 _opcode = fetchScriptByte();
1661 switch (_opcode & 0x1F) {
1662 case 1:
1663 a = getVarOrDirectByte(0x80);
1664 b = getVarOrDirectByte(0x40);
1665 setBoxFlags(a, b);
1666 break;
1667 case 2:
1668 a = getVarOrDirectByte(0x80);
1669 b = getVarOrDirectByte(0x40);
1670 setBoxScale(a, b);
1671 break;
1672 case 3:
1673 a = getVarOrDirectByte(0x80);
1674 b = getVarOrDirectByte(0x40);
1675 setBoxScale(a, (b - 1) | 0x8000);
1676 break;
1677 case 4:
1678 createBoxMatrix();
1679 break;
1680 }
1681}
1682
1683void Scumm::o5_move()
1684{
1685 getResultPos();
1686 setResult(getVarOrDirectWord(0x80));
1687}
1688
1689void Scumm::o5_multiply()
1690{
1691 int a;
1692 getResultPos();
1693 a = getVarOrDirectWord(0x80);
1694 setResult(readVar(_resultVarNumber) * a);
1695}
1696
1697
1698void Scumm::o5_or()
1699{
1700 int a;
1701 getResultPos();
1702 a = getVarOrDirectWord(0x80);
1703 setResult(readVar(_resultVarNumber) | a);
1704}
1705
1706void Scumm::o5_overRide()
1707{
1708 if (fetchScriptByte() != 0)
1709 beginOverride();
1710 else
1711 endOverride();
1712}
1713
1714void Scumm::o5_panCameraTo()
1715{
1716 panCameraTo(getVarOrDirectWord(0x80), 0);
1717}
1718
1719void Scumm::o5_pickupObject()
1720{
1721 int obj, room;
1722 if (_features & GF_OLD256) {
1723 o5_drawObject();
1724 return;
1725 }
1726
1727 obj = getVarOrDirectWord(0x80);
1728 room = getVarOrDirectByte(0x40);
1729 if (room == 0)
1730 room = _roomResource;
1731 addObjectToInventory(obj, room);
1732 putOwner(obj, _vars[VAR_EGO]);
1733 putClass(obj, 32, 1);
1734 putState(obj, 1);
1735 removeObjectFromRoom(obj);
1736 clearDrawObjectQueue();
1737 runHook(1);
1738}
1739
1740void Scumm::o5_print()
1741{
1742 _actorToPrintStrFor = getVarOrDirectByte(0x80);
1743 decodeParseString();
1744}
1745
1746void Scumm::o5_printEgo()
1747{
1748 _actorToPrintStrFor = (unsigned char)_vars[VAR_EGO];
1749 decodeParseString();
1750}
1751
1752void Scumm::o5_pseudoRoom()
1753{
1754 int i = fetchScriptByte(), j;
1755 while ((j = fetchScriptByte()) != 0) {
1756 if (j >= 0x80) {
1757 _resourceMapper[j & 0x7F] = i;
1758 }
1759 }
1760}
1761
1762void Scumm::o5_putActor()
1763{
1764 int x, y;
1765 Actor *a;
1766
1767 a = derefActorSafe(getVarOrDirectByte(0x80), "o5_putActor");
1768 if (!a)
1769 return;
1770 x = getVarOrDirectWord(0x40);
1771 y = getVarOrDirectWord(0x20);
1772
1773 putActor(a, x, y, a->room);
1774}
1775
1776
1777void Scumm::o5_putActorAtObject()
1778{
1779 int obj;
1780 Actor *a;
1781
1782 a = derefActorSafe(getVarOrDirectByte(0x80), "o5_putActorAtObject");
1783 obj = getVarOrDirectWord(0x40);
1784 if (whereIsObject(obj) != WIO_NOT_FOUND)
1785 getObjectXYPos(obj);
1786 else {
1787 _xPos = 240;
1788 _yPos = 120;
1789 }
1790 putActor(a, _xPos, _yPos, a->room);
1791}
1792
1793void Scumm::o5_putActorInRoom()
1794{
1795 int room;
1796 Actor *a;
1797
1798 a = derefActorSafe(getVarOrDirectByte(0x80), "o5_putActorInRoom");
1799 room = getVarOrDirectByte(0x40);
1800 if (a->visible && _currentRoom != room
1801 && _vars[VAR_TALK_ACTOR] == a->number) {
1802 clearMsgQueue();
1803 }
1804 a->room = room;
1805 if (!room)
1806 putActor(a, 0, 0, 0);
1807}
1808
1809void Scumm::o5_quitPauseRestart()
1810{
1811 switch (fetchScriptByte()) {
1812 case 1:
1813 pauseGame(false);
1814 break;
1815 case 3:
1816 shutDown(0);
1817 break;
1818 }
1819}
1820
1821void Scumm::o5_resourceRoutines()
1822{
1823 int resid = 0;
1824
1825 _opcode = fetchScriptByte();
1826 if (_opcode != 17)
1827 resid = getVarOrDirectByte(0x80);
1828 if (_features & GF_OLD256) /*FIXME: find a better way to implement this */
1829 _opcode &= 0x3F;
1830 switch (_opcode & 0x1F) {
1831 case 1: /* load script */
1832 ensureResourceLoaded(rtScript, resid);
1833 break;
1834 case 2: /* load sound */
1835 ensureResourceLoaded(rtSound, resid);
1836 break;
1837 case 3: /* load costume */
1838 ensureResourceLoaded(rtCostume, resid);
1839 break;
1840 case 4: /* load room */
1841 if (_features & GF_OLD256)
1842 ensureResourceLoaded(rtScript, resid & 0x7F); /*FIXME: missing stuff... */
1843 else
1844 ensureResourceLoaded(rtRoom, resid);
1845 break;
1846 case 5: /* nuke script */
1847 setResourceCounter(rtScript, resid, 0x7F);
1848 break;
1849 case 6: /* nuke sound */
1850 setResourceCounter(rtSound, resid, 0x7F);
1851 break;
1852 case 7: /* nuke costume */
1853 setResourceCounter(rtCostume, resid, 0x7F);
1854 break;
1855 case 8: /* nuke room */
1856 setResourceCounter(rtRoom, resid, 0x7F);
1857 break;
1858 case 9: /* lock script */
1859 if (resid >= _numGlobalScripts)
1860 break;
1861 lock(rtScript, resid);
1862 break;
1863 case 10: /* lock sound */
1864 lock(rtSound, resid);
1865 break;
1866 case 11: /* lock costume */
1867 lock(rtCostume, resid);
1868 break;
1869 case 12: /* lock room */
1870 if (resid > 0x7F)
1871 resid = _resourceMapper[resid & 0x7F];
1872 lock(rtRoom, resid);
1873 break;
1874 case 13: /* unlock script */
1875 if (resid >= _numGlobalScripts)
1876 break;
1877 unlock(rtScript, resid);
1878 break;
1879 case 14: /* unlock sound */
1880 unlock(rtSound, resid);
1881 break;
1882 case 15: /* unlock costume */
1883 unlock(rtCostume, resid);
1884 break;
1885 case 16: /* unlock room */
1886 if (resid > 0x7F)
1887 resid = _resourceMapper[resid & 0x7F];
1888 unlock(rtRoom, resid);
1889 break;
1890 case 17: /* clear heap */
1891 heapClear(0);
1892 unkHeapProc2(0, 0);
1893 break;
1894 case 18: /* load charset */
1895 loadCharset(resid);
1896 break;
1897 case 19: /* nuke charset */
1898 nukeCharset(resid);
1899 break;
1900 case 20: /* load fl object */
1901 loadFlObject(getVarOrDirectWord(0x40), resid);
1902 break;
1903 default:
1904 warning("Unknown o5_resourcesroutine: %d", _opcode & 0x1F);
1905 break;
1906 }
1907}
1908
1909void Scumm::o5_roomOps()
1910{
1911 int a = 0, b = 0, c, d, e;
1912
1913 if (_features & GF_OLD256) {
1914 a = getVarOrDirectWord(0x80);
1915 b = getVarOrDirectWord(0x40);
1916 }
1917
1918 _opcode = fetchScriptByte();
1919
1920 switch (_opcode & 0x1F) {
1921 case 1: /* room scroll */
1922 if (!(_features & GF_OLD256)) {
1923 a = getVarOrDirectWord(0x80);
1924 b = getVarOrDirectWord(0x40);
1925 }
1926 if (a < 160)
1927 a = 160;
1928 if (b < 160)
1929 b = 160;
1930 if (a > _scrWidth - 160)
1931 a = _scrWidth - 160;
1932 if (b > _scrWidth - 160)
1933 b = _scrWidth - 160;
1934 _vars[VAR_CAMERA_MIN_X] = a;
1935 _vars[VAR_CAMERA_MAX_X] = b;
1936 break;
1937 case 2: /* room color */
1938 if (_features & GF_SMALL_HEADER) {
1939 if (!(_features & GF_OLD256)) {
1940 a = getVarOrDirectWord(0x80);
1941 b = getVarOrDirectWord(0x40);
1942 }
1943 checkRange(256, 0, a, "o5_roomOps: 2: Illegal room color slot (%d)");
1944 _currentPalette[a] = b;
1945 _fullRedraw = 1;
1946 } else {
1947 error("room-color is no longer a valid command");
1948 }
1949 break;
1950
1951 case 3: /* set screen */
1952 if (!(_features & GF_OLD256)) {
1953 a = getVarOrDirectWord(0x80);
1954 b = getVarOrDirectWord(0x40);
1955 }
1956 initScreens(0, a, 320, b);
1957 break;
1958 case 4: /* set palette color */
1959 if (_features & GF_SMALL_HEADER) {
1960 if (!(_features & GF_OLD256)) {
1961 a = getVarOrDirectWord(0x80);
1962 b = getVarOrDirectWord(0x40);
1963 }
1964 checkRange(256, 0, a, "o5_roomOps: 2: Illegal room color slot (%d)");
1965 _currentPalette[a] = b; /*FIXME: should be shadow palette */
1966 // _fullRedraw = 1;
1967 } else {
1968 a = getVarOrDirectWord(0x80);
1969 b = getVarOrDirectWord(0x40);
1970 c = getVarOrDirectWord(0x20);
1971 _opcode = fetchScriptByte();
1972 d = getVarOrDirectByte(0x80);
1973 setPalColor(d, a, b, c); /* index, r, g, b */
1974 }
1975 break;
1976 case 5: /* shake on */
1977 setShake(1);
1978 break;
1979 case 6: /* shake off */
1980 setShake(0);
1981 break;
1982 case 7: /* room scale for old games */
1983 a = getVarOrDirectByte(0x80);
1984 b = getVarOrDirectByte(0x40);
1985 _opcode = fetchScriptByte();
1986 c = getVarOrDirectByte(0x80);
1987 d = getVarOrDirectByte(0x40);
1988 _opcode = fetchScriptByte();
1989 e = getVarOrDirectByte(0x40);
1990 setScaleItem(e - 1, b, a, d, c);
1991 case 8: /* room scale? */
1992 if (_features & GF_SMALL_HEADER) {
1993 if (!(_features & GF_OLD256)) {
1994 a = getVarOrDirectWord(0x80);
1995 b = getVarOrDirectWord(0x40);
1996 }
1997 c = getVarOrDirectWord(0x20);
1998 } else {
1999 a = getVarOrDirectByte(0x80);
2000 b = getVarOrDirectByte(0x40);
2001 c = getVarOrDirectByte(0x20);
2002 }
2003 darkenPalette(b, c, a, a, a);
2004 break;
2005 case 9: /* ? */
2006 _saveLoadFlag = getVarOrDirectByte(0x80);
2007 _saveLoadSlot = getVarOrDirectByte(0x40);
2008 _saveLoadSlot = 99; /* use this slot */
2009 _saveLoadCompatible = true;
2010 break;
2011 case 10: /* ? */
2012 a = getVarOrDirectWord(0x80);
2013 if (a) {
2014 _switchRoomEffect = (byte)(a);
2015 _switchRoomEffect2 = (byte)(a >> 8);
2016 } else {
2017 screenEffect(_newEffect);
2018 }
2019 break;
2020 case 11: /* ? */
2021 a = getVarOrDirectWord(0x80);
2022 b = getVarOrDirectWord(0x40);
2023 c = getVarOrDirectWord(0x20);
2024 _opcode = fetchScriptByte();
2025 d = getVarOrDirectByte(0x80);
2026 e = getVarOrDirectByte(0x40);
2027 darkenPalette(d, e, a, b, c);
2028 break;
2029 case 12: /* ? */
2030 a = getVarOrDirectWord(0x80);
2031 b = getVarOrDirectWord(0x40);
2032 c = getVarOrDirectWord(0x20);
2033 _opcode = fetchScriptByte();
2034 d = getVarOrDirectByte(0x80);
2035 e = getVarOrDirectByte(0x40);
2036 unkRoomFunc3(d, e, a, b, c);
2037 break;
2038
2039 case 13:{ /* save-string */
2040 char buf[256], *s;
2041 a = getVarOrDirectByte(0x80);
2042 s = buf;
2043 while ((*s++ = fetchScriptByte()))
2044 ;
2045 warning("roomops:13 save-string(%d,\"%s\") not implemented", a, buf);
2046 break;
2047 }
2048 case 14: /* load-string */
2049 char buf[256], *s;
2050 a = getVarOrDirectByte(0x80);
2051 s = buf;
2052 while ((*s++ = fetchScriptByte()))
2053 ;
2054 warning("roomops:14 load-string(%d,\"%s\") not implemented", a, buf);
2055 break;
2056 case 15: /* palmanip? */
2057 a = getVarOrDirectByte(0x80);
2058 _opcode = fetchScriptByte();
2059 b = getVarOrDirectByte(0x80);
2060 c = getVarOrDirectByte(0x40);
2061 _opcode = fetchScriptByte();
2062 d = getVarOrDirectByte(0x80);
2063 unkRoomFunc4(b, c, a, d, 1);
2064 break;
2065
2066 case 16:
2067 a = getVarOrDirectByte(0x80);
2068 b = getVarOrDirectByte(0x40);
2069 if (a < 1)
2070 a = 1; /* FIXME: ZAK256 */
2071 checkRange(16, 1, a, "o5_roomOps: 16: color cycle out of range (%d)");
2072 _colorCycle[a - 1].delay = (b != 0) ? 0x4000 / (b * 0x4C) : 0;
2073 break;
2074 }
2075}
2076
2077void Scumm::o5_saveRestoreVerbs()
2078{
2079 int a, b, c, slot, slot2;
2080
2081 _opcode = fetchScriptByte();
2082
2083 a = getVarOrDirectByte(0x80);
2084 b = getVarOrDirectByte(0x40);
2085 c = getVarOrDirectByte(0x20);
2086
2087 switch (_opcode) {
2088 case 1: /* hide verbs */
2089 while (a <= b) {
2090 slot = getVerbSlot(a, 0);
2091 if (slot && _verbs[slot].saveid == 0) {
2092 _verbs[slot].saveid = c;
2093 drawVerb(slot, 0);
2094 verbMouseOver(0);
2095 }
2096 a++;
2097 }
2098 break;
2099 case 2: /* show verbs */
2100 while (a <= b) {
2101 slot = getVerbSlot(a, c);
2102 if (slot) {
2103 slot2 = getVerbSlot(a, 0);
2104 if (slot2)
2105 killVerb(slot2);
2106 slot = getVerbSlot(a, c);
2107 _verbs[slot].saveid = 0;
2108 drawVerb(slot, 0);
2109 verbMouseOver(0);
2110 }
2111 a++;
2112 }
2113 break;
2114 case 3: /* kill verbs */
2115 while (a <= b) {
2116 slot = getVerbSlot(a, c);
2117 if (slot)
2118 killVerb(slot);
2119 a++;
2120 }
2121 break;
2122 default:
2123 error("o5_saveRestoreVerbs: invalid opcode");
2124 }
2125}
2126
2127void Scumm::o5_setCameraAt()
2128{
2129 setCameraAtEx(getVarOrDirectWord(0x80));
2130}
2131
2132void Scumm::o5_setObjectName()
2133{
2134 int obj = getVarOrDirectWord(0x80);
2135 int size;
2136 int a;
2137 int i;
2138 byte *name;
2139 unsigned char work[255];
2140
2141 if (obj < NUM_ACTORS)
2142 error("Can't set actor %d name with new-name-of", obj);
2143
2144 if (!getOBCDFromObject(obj))
2145 error("Can't set name of object %d", obj);
2146
2147 name = getObjOrActorName(obj);
2148 size = getResourceDataSize(name);
2149 i = 0;
2150
2151 while ((a = fetchScriptByte()) != 0) {
2152 work[i++] = a;
2153
2154 if (a == 0xFF) {
2155 work[i++] = fetchScriptByte();
2156 work[i++] = fetchScriptByte();
2157 work[i++] = fetchScriptByte();
2158 }
2159
2160 }
2161
2162 if (i >= size) {
2163 work[i] = 0;
2164 warning("New name of object %d too long (old *%s* new *%s*)",
2165 obj, name, work);
2166 i = size - 1;
2167 }
2168
2169 work[i] = 0;
2170 strcpy((char *)name, (char *)work);
2171 runHook(0);
2172}
2173
2174void Scumm::o5_setOwnerOf()
2175{
2176 int obj, owner;
2177
2178 obj = getVarOrDirectWord(0x80);
2179 owner = getVarOrDirectByte(0x40);
2180
2181 setOwnerOf(obj, owner);
2182}
2183
2184void Scumm::o5_setState()
2185{
2186 int obj, state;
2187 obj = getVarOrDirectWord(0x80);
2188 state = getVarOrDirectByte(0x40);
2189 putState(obj, state);
2190 removeObjectFromRoom(obj);
2191 if (_BgNeedsRedraw)
2192 clearDrawObjectQueue();
2193}
2194
2195void Scumm::o5_setVarRange()
2196{
2197 int a, b;
2198
2199 getResultPos();
2200 a = fetchScriptByte();
2201 do {
2202 if (_opcode & 0x80)
2203 b = fetchScriptWord();
2204 else
2205 b = fetchScriptByte();
2206
2207 setResult(b);
2208 _resultVarNumber++;
2209 } while (--a);
2210}
2211
2212void Scumm::o5_soundKludge()
2213{
2214 int16 items[15];
2215 int i;
2216
2217 if (_features & GF_SMALL_HEADER) // Is dummy function in
2218 return; // SCUMM V3
2219
2220 for (i = 0; i < 15; i++)
2221 items[i] = 0;
2222
2223 getWordVararg(items);
2224
2225 soundKludge(items);
2226}
2227
2228void Scumm::o5_startMusic()
2229{
2230
2231 addSoundToQueue(getVarOrDirectByte(0x80));
2232}
2233
2234void Scumm::o5_startObject()
2235{
2236 int obj, script;
2237 int16 data[16];
2238
2239 obj = getVarOrDirectWord(0x80);
2240 script = getVarOrDirectByte(0x40);
2241
2242 getWordVararg(data);
2243 runVerbCode(obj, script, 0, 0, data);
2244}
2245
2246void Scumm::o5_startScript()
2247{
2248 int op, script;
2249 int16 data[16];
2250 int a, b;
2251
2252 op = _opcode;
2253 script = getVarOrDirectByte(0x80);
2254
2255 getWordVararg(data);
2256
2257 a = b = 0;
2258 if (op & 0x40)
2259 b = 1;
2260 if (op & 0x20)
2261 a = 1;
2262
2263 runScript(script, a, b, data);
2264}
2265
2266void Scumm::o5_startSound()
2267{
2268
2269 _vars[VAR_MUSIC_FLAG]=0;
2270
2271 addSoundToQueue(getVarOrDirectByte(0x80));
2272}
2273
2274void Scumm::o5_stopMusic()
2275{
2276 stopAllSounds();
2277}
2278
2279void Scumm::o5_stopObjectCode()
2280{
2281 stopObjectCode();
2282}
2283
2284void Scumm::o5_stopObjectScript()
2285{
2286 stopObjectScript(getVarOrDirectWord(0x80));
2287}
2288
2289void Scumm::o5_stopScript()
2290{
2291 int script;
2292
2293 script = getVarOrDirectByte(0x80);
2294 if (!script)
2295 stopObjectCode();
2296 else
2297 stopScriptNr(script);
2298}
2299
2300void Scumm::o5_stopSound()
2301{
2302 stopSound(getVarOrDirectByte(0x80));
2303}
2304
2305void Scumm::o5_stringOps()
2306{
2307 int a, b, c, i;
2308 byte *ptr;
2309
2310 _opcode = fetchScriptByte();
2311 switch (_opcode & 0x1F) {
2312 case 1: /* loadstring */
2313 loadPtrToResource(rtString, getVarOrDirectByte(0x80), NULL);
2314 break;
2315 case 2: /* copystring */
2316 a = getVarOrDirectByte(0x80);
2317 b = getVarOrDirectByte(0x40);
2318 nukeResource(rtString, a);
2319 ptr = getResourceAddress(rtString, b);
2320 if (ptr)
2321 loadPtrToResource(rtString, a, ptr);
2322 break;
2323 case 3: /* set string char */
2324 a = getVarOrDirectByte(0x80);
2325 b = getVarOrDirectByte(0x40);
2326 ptr = getResourceAddress(rtString, a);
2327 if (!(_gameId == GID_LOOM256)) { /* FIXME - LOOM256 */
2328 if (ptr == NULL)
2329 error("String %d does not exist", a);
2330 c = getVarOrDirectByte(0x20);
2331 ptr[b] = c;
2332 } else
2333 getVarOrDirectByte(0x20);
2334
2335 break;
2336
2337 case 4: /* get string char */
2338 getResultPos();
2339 a = getVarOrDirectByte(0x80);
2340 b = getVarOrDirectByte(0x40);
2341 ptr = getResourceAddress(rtString, a);
2342 if (ptr == NULL)
2343 error("String %d does not exist", a);
2344 setResult(ptr[b]);
2345 break;
2346
2347 case 5: /* create empty string */
2348 a = getVarOrDirectByte(0x80);
2349 b = getVarOrDirectByte(0x40);
2350 nukeResource(rtString, a);
2351 if (b) {
2352 ptr = createResource(rtString, a, b);
2353 if (ptr) {
2354 for (i = 0; i < b; i++)
2355 ptr[i] = 0;
2356 }
2357 }
2358 break;
2359 }
2360}
2361
2362void Scumm::o5_subtract()
2363{
2364 int a;
2365 getResultPos();
2366 a = getVarOrDirectWord(0x80);
2367 setResult(readVar(_resultVarNumber) - a);
2368}
2369
2370void Scumm::o5_verbOps()
2371{
2372 int verb, slot;
2373 VerbSlot *vs;
2374 int a, b;
2375 byte *ptr;
2376
2377 verb = getVarOrDirectByte(0x80);
2378
2379 slot = getVerbSlot(verb, 0);
2380 checkRange(_maxVerbs - 1, 0, slot, "Illegal new verb slot %d");
2381
2382 vs = &_verbs[slot];
2383 vs->verbid = verb;
2384
2385 while ((_opcode = fetchScriptByte()) != 0xFF) {
2386 switch (_opcode & 0x1F) {
2387 case 1: /* load image */
2388 a = getVarOrDirectWord(0x80);
2389 if (slot) {
2390 setVerbObject(_roomResource, a, slot);
2391 vs->type = 1;
2392 }
2393 break;
2394 case 2: /* load from code */
2395 loadPtrToResource(rtVerb, slot, NULL);
2396 if (slot == 0)
2397 nukeResource(rtVerb, slot);
2398 vs->type = 0;
2399 vs->imgindex = 0;
2400 break;
2401 case 3: /* color */
2402 vs->color = getVarOrDirectByte(0x80);
2403 break;
2404 case 4: /* set hi color */
2405 vs->hicolor = getVarOrDirectByte(0x80);
2406 break;
2407 case 5: /* set xy */
2408 vs->x = getVarOrDirectWord(0x80);
2409 vs->y = getVarOrDirectWord(0x40);
2410 // FIXME: hack loom notes into right spot
2411 if (_gameId == GID_LOOM256) {
2412 if ((verb >= 90) && (verb <= 97)) { // Notes
2413 switch (verb) {
2414 case 90:
2415 case 91:
2416 vs->y -= 7;
2417 break;
2418 case 92:
2419 vs->y -= 6;
2420 break;
2421 case 93:
2422 vs->y -= 4;
2423 break;
2424 case 94:
2425 vs->y -= 3;
2426 break;
2427 case 95:
2428 vs->y -= 1;
2429 break;
2430 case 97:
2431 vs->y -= 5;
2432 }
2433 }
2434 }
2435 break;
2436 case 6: /* set on */
2437 vs->curmode = 1;
2438 break;
2439 case 7: /* set off */
2440 vs->curmode = 0;
2441 break;
2442 case 8: /* delete */
2443 killVerb(slot);
2444 break;
2445 case 9: /* new */
2446 slot = getVerbSlot(verb, 0);
2447 if (slot == 0) {
2448 for (slot = 1; slot < _maxVerbs; slot++) {
2449 if (_verbs[slot].verbid == 0)
2450 break;
2451 }
2452 if (slot == _maxVerbs)
2453 error("Too many verbs");
2454 }
2455 vs = &_verbs[slot];
2456 vs->verbid = verb;
2457 vs->color = 2;
2458 vs->hicolor = 0;
2459 vs->dimcolor = 8;
2460 vs->type = 0;
2461 vs->charset_nr = string[0].t_charset;
2462 vs->curmode = 0;
2463 vs->saveid = 0;
2464 vs->key = 0;
2465 vs->center = 0;
2466 vs->imgindex = 0;
2467 break;
2468
2469 case 16: /* set dim color */
2470 vs->dimcolor = getVarOrDirectByte(0x80);
2471 break;
2472 case 17: /* dim */
2473 vs->curmode = 2;
2474 break;
2475 case 18: /* set key */
2476 vs->key = getVarOrDirectByte(0x80);
2477 break;
2478 case 19: /* set center */
2479 vs->center = 1;
2480 break;
2481 case 20: /* set to string */
2482 ptr = getResourceAddress(rtString, getVarOrDirectWord(0x80));
2483 if (!ptr)
2484 nukeResource(rtVerb, slot);
2485 else {
2486 loadPtrToResource(rtVerb, slot, ptr);
2487 }
2488 if (slot == 0)
2489 nukeResource(rtVerb, slot);
2490 vs->type = 0;
2491 vs->imgindex = 0;
2492 break;
2493 case 22: /* assign object */
2494 a = getVarOrDirectWord(0x80);
2495 b = getVarOrDirectByte(0x40);
2496 if (slot && vs->imgindex != a) {
2497 setVerbObject(b, a, slot);
2498 vs->type = 1;
2499 vs->imgindex = a;
2500 }
2501 break;
2502 case 23: /* set back color */
2503 vs->bkcolor = getVarOrDirectByte(0x80);
2504 break;
2505 }
2506 }
2507 drawVerb(slot, 0);
2508 verbMouseOver(0);
2509}
2510
2511void Scumm::o5_wait()
2512{
2513 byte *oldaddr;
2514
2515
2516 oldaddr = _scriptPointer - 1;
2517
2518 if (_opcode == 0xAE && _gameId == GID_INDY3_256) {
2519 _opcode = 2;
2520 } else
2521 _opcode = fetchScriptByte();
2522
2523 switch (_opcode & 0x1F) {
2524 case 1: /* wait for actor */
2525 if (derefActorSafe(getVarOrDirectByte(0x80), "o5_wait")->moving)
2526 break;
2527 return;
2528 case 2: /* wait for message */
2529 if (_vars[VAR_HAVE_MSG])
2530 break;
2531 return;
2532 case 3: /* wait for camera */
2533 if (camera._cur.x >> 3 != camera._dest.x >> 3)
2534 break;
2535 return;
2536 case 4: /* wait for sentence */
2537 if (_sentenceNum) {
2538 if (sentence[_sentenceNum - 1].unk &&
2539 !isScriptInUse(_vars[VAR_SENTENCE_SCRIPT]))
2540 return;
2541 break;
2542 }
2543 if (!isScriptInUse(_vars[VAR_SENTENCE_SCRIPT]))
2544 return;
2545 break;
2546 default:
2547 error("o5_wait: default case");
2548 return;
2549 }
2550
2551 _scriptPointer = oldaddr;
2552 o5_breakHere();
2553}
2554
2555void Scumm::o5_walkActorTo()
2556{
2557 int x, y;
2558 Actor *a;
2559 a = derefActorSafe(getVarOrDirectByte(0x80), "o5_walkActorTo");
2560 x = getVarOrDirectWord(0x40);
2561 y = getVarOrDirectWord(0x20);
2562 startWalkActor(a, x, y, -1);
2563}
2564
2565void Scumm::o5_walkActorToActor()
2566{
2567 int b, x, y;
2568 Actor *a, *a2;
2569 int nr;
2570 int nr2 = getVarOrDirectByte(0x80);
2571 a = derefActorSafe(nr2, "o5_walkActorToActor");
2572 if (!a)
2573 return;
2574
2575 if (a->room != _currentRoom) {
2576 getVarOrDirectByte(0x40);
2577 fetchScriptByte();
2578 return;
2579 }
2580
2581 nr = getVarOrDirectByte(0x40);
2582 if (nr == 106 && _gameId == GID_INDY4) {
2583 warning("Bypassing Indy4 bug");
2584 fetchScriptByte();
2585 return;
2586 }
2587 // warning("walk actor %d to actor %d", nr, nr2);
2588 a2 = derefActorSafe(nr, "o5_walkActorToActor(2)");
2589 if (!a2)
2590 return;
2591
2592 if (a2->room != _currentRoom) {
2593 fetchScriptByte();
2594 return;
2595 }
2596 b = fetchScriptByte(); /* distance from actor */
2597 if (b == 0xFF) {
2598 b = a2->scalex * a->width / 0xFF;
2599 b = b + b / 2;
2600 }
2601 x = a2->x;
2602 y = a2->y;
2603 if (x < a->x)
2604 x += b;
2605 else
2606 x -= b;
2607
2608 startWalkActor(a, x, y, -1);
2609}
2610
2611void Scumm::o5_walkActorToObject()
2612{
2613 int obj;
2614 Actor *a;
2615
2616 // warning("walk object to object");
2617
2618 a = derefActorSafe(getVarOrDirectByte(0x80), "o5_walkActorToObject");
2619 obj = getVarOrDirectWord(0x40);
2620 if (whereIsObject(obj) != WIO_NOT_FOUND) {
2621 getObjectXYPos(obj);
2622 startWalkActor(a, _xPos, _yPos, _dir);
2623 }
2624}
2625
2626int Scumm::getWordVararg(int16 * ptr)
2627{
2628 int i;
2629
2630 for (i = 0; i < 15; i++)
2631 ptr[i] = 0;
2632
2633 i = 0;
2634 while ((_opcode = fetchScriptByte()) != 0xFF) {
2635 ptr[i++] = getVarOrDirectWord(0x80);
2636 }
2637 return i;
2638}
2639
2640int Scumm::getVarOrDirectWord(byte mask)
2641{
2642 if (_opcode & mask)
2643 return readVar(fetchScriptWord());
2644 return (int16) fetchScriptWord();
2645}
2646
2647int Scumm::getVarOrDirectByte(byte mask)
2648{
2649 if (_opcode & mask)
2650 return readVar(fetchScriptWord());
2651 return fetchScriptByte();
2652}
2653
2654void Scumm::decodeParseString()
2655{
2656 int textSlot;
2657
2658 switch (_actorToPrintStrFor) {
2659 case 252:
2660 textSlot = 3;
2661 break;
2662 case 253:
2663 textSlot = 2;
2664 break;
2665 case 254:
2666 textSlot = 1;
2667 break;
2668 default:
2669 textSlot = 0;
2670 }
2671
2672 string[textSlot].xpos = string[textSlot].t_xpos;
2673 string[textSlot].ypos = string[textSlot].t_ypos;
2674 string[textSlot].center = string[textSlot].t_center;
2675 string[textSlot].overhead = string[textSlot].t_overhead;
2676 string[textSlot].right = string[textSlot].t_right;
2677 string[textSlot].color = string[textSlot].t_color;
2678 string[textSlot].charset = string[textSlot].t_charset;
2679
2680 while ((_opcode = fetchScriptByte()) != 0xFF) {
2681 switch (_opcode & 0xF) {
2682 case 0: /* set string xy */
2683 string[textSlot].xpos = getVarOrDirectWord(0x80);
2684 string[textSlot].ypos = getVarOrDirectWord(0x40);
2685 string[textSlot].overhead = false;
2686 break;
2687 case 1: /* color */
2688 string[textSlot].color = getVarOrDirectByte(0x80);
2689 break;
2690 case 2: /* right */
2691 string[textSlot].right = getVarOrDirectWord(0x80);
2692 break;
2693 case 4: /* center */
2694 string[textSlot].center = true;
2695 string[textSlot].overhead = false;
2696 break;
2697 case 6: /* left */
2698 string[textSlot].center = false;
2699 string[textSlot].overhead = false;
2700 break;
2701 case 7: /* overhead */
2702 string[textSlot].overhead = true;
2703 break;
2704 case 8:{ /* play loom talkie sound - use in other games ? */
2705 int x = getVarOrDirectWord(0x80);
2706 int offset;
2707 int delay;
2708
2709 if (x != 0)
2710 offset = (int)((x & 0xffff) * 7.5 - 22650);
2711 else
2712 offset = 0;
2713 delay = (int)((getVarOrDirectWord(0x40) & 0xffff) * 7.5);
2714 if (_gameId == GID_LOOM256) {
2715#ifdef COMPRESSED_SOUND_FILE
2716 if(playMP3CDTrack(1, 0, offset, delay) == -1)
2717#endif
2718 _system->play_cdrom(1, 0, offset, delay);
2719 }
2720 else
2721 warning("parseString: 8");
2722 }
2723 break;
2724 case 15:
2725 _messagePtr = _scriptPointer;
2726 switch (textSlot) {
2727 case 0:
2728 actorTalk();
2729 break;
2730 case 1:
2731 drawString(1);
2732 break;
2733 case 2:
2734 unkMessage1();
2735 break;
2736 case 3:
2737 unkMessage2();
2738 break;
2739 }
2740 _scriptPointer = _messagePtr;
2741 return;
2742 default:
2743 return;
2744 }
2745 }
2746
2747 string[textSlot].t_xpos = string[textSlot].xpos;
2748 string[textSlot].t_ypos = string[textSlot].ypos;
2749 string[textSlot].t_center = string[textSlot].center;
2750 string[textSlot].t_overhead = string[textSlot].overhead;
2751 string[textSlot].t_right = string[textSlot].right;
2752 string[textSlot].t_color = string[textSlot].color;
2753 string[textSlot].t_charset = string[textSlot].charset;
2754}
2755
2756void Scumm::o5_oldRoomEffect()
2757{
2758 int a;
2759
2760 _opcode = fetchScriptByte();
2761 if ((_opcode & 0x1F) == 3) {
2762 a = getVarOrDirectWord(0x80);
2763 switch(a) {
2764 case 4:
2765 _fullRedraw =true;
2766 break;
2767 default:
2768 warning("Unsupported oldRoomEffect %d", a);
2769 break;
2770 }
2771 }
2772}
2773
2774void Scumm::o5_pickupObjectOld()
2775{
2776 int obj = getVarOrDirectWord(0x80);
2777
2778 // FIXME: Zak256 (Zaire): Why does this happen at all?
2779 if (obj < 1) {
2780 warning("pickupObjectOld recieved negative index");
2781 return;
2782 }
2783
2784 if (getObjectIndex(obj) == -1)
2785 return;
2786
2787 if (whereIsObject(obj) == WIO_INVENTORY) /* Don't take an */
2788 return; /* object twice */
2789
2790 // warning("adding %d from %d to inventoryOld", obj, _currentRoom);
2791 addObjectToInventory(obj, _roomResource);
2792 removeObjectFromRoom(obj);
2793 putOwner(obj, _vars[VAR_EGO]);
2794 putClass(obj, 32, 1);
2795 putState(obj, 1);
2796 clearDrawObjectQueue();
2797 runHook(1);
2798}