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 "cruise/cruise.h"
24 #include "cruise/cruise_main.h"
25 #include "cruise/cell.h"
26 #include "cruise/sound.h"
27 #include "cruise/staticres.h"
28
29 #include "common/textconsole.h"
30 #include "common/util.h"
31
32 namespace Cruise {
33
Period(uint32 hz)34 uint32 Period(uint32 hz) {
35 return ((uint32)(100000000L / ((uint32)hz * 28L)));
36 }
37
38 //#define FUNCTION_DEBUG
39
Op_LoadOverlay()40 int16 Op_LoadOverlay() {
41 char *pOverlayName;
42 char overlayName[38] = "";
43 int overlayLoadResult;
44
45 pOverlayName = (char *)popPtr();
46
47 if (strlen(pOverlayName) == 0)
48 return 0;
49
50 strcpy(overlayName, pOverlayName);
51 strToUpper(overlayName);
52
53 //gfxModuleData.field_84();
54 //gfxModuleData.field_84();
55
56 overlayLoadResult = loadOverlay(overlayName);
57
58 updateAllScriptsImports();
59
60 Common::strlcpy(nextOverlay, overlayName, sizeof(nextOverlay));
61
62 return overlayLoadResult;
63 }
64
Op_Strcpy()65 int16 Op_Strcpy() {
66 char *ptr1 = (char *)popPtr();
67 char *ptr2 = (char *)popPtr();
68
69 while (*ptr1) {
70 *ptr2 = *ptr1;
71
72 ptr2++;
73 ptr1++;
74 }
75
76 *ptr2 = 0;
77
78 return (0);
79 }
80
Op_Exec()81 int16 Op_Exec() {
82 int scriptIdx;
83 int ovlIdx;
84 uint8 *ptr;
85 uint8 *ptr2;
86 int16 popTable[200];
87
88 int numOfArgToPop = popVar();
89
90 for (int i = 0; i < numOfArgToPop; i++) {
91 popTable[numOfArgToPop - i - 1] = popVar();
92 }
93
94 scriptIdx = popVar();
95 ovlIdx = popVar();
96
97 if (!ovlIdx) {
98 ovlIdx = currentScriptPtr->overlayNumber;
99 }
100
101 ptr = attacheNewScriptToTail(&procHead, ovlIdx, scriptIdx, currentScriptPtr->type, currentScriptPtr->scriptNumber, currentScriptPtr->overlayNumber, scriptType_MinusPROC);
102
103 if (!ptr)
104 return (0);
105
106 if (numOfArgToPop <= 0) {
107 return (0);
108 }
109
110 ptr2 = ptr;
111
112 for (int i = 0; i < numOfArgToPop; i++) {
113 WRITE_BE_UINT16(ptr2, popTable[i]);
114 ptr2 += 2;
115 }
116
117 return (0);
118 }
119
Op_AddProc()120 int16 Op_AddProc() {
121 int pop1 = popVar();
122 int pop2;
123 int overlay;
124 int param[160];
125
126 for (long int i = 0; i < pop1; i++) {
127 param[i] = popVar();
128 }
129
130 pop2 = popVar();
131 overlay = popVar();
132
133 if (!overlay)
134 overlay = currentScriptPtr->overlayNumber;
135
136 if (!overlay)
137 return (0);
138
139 uint8* procBss = attacheNewScriptToTail(&procHead, overlay, pop2, currentScriptPtr->type, currentScriptPtr->scriptNumber, currentScriptPtr->overlayNumber, scriptType_PROC);
140
141 if (procBss) {
142 for (long int i = 0; i < pop1; i++) {
143 int16* ptr = (int16 *)(procBss + i * 2);
144 *ptr = param[i];
145 bigEndianShortToNative(ptr);
146 }
147 }
148
149 return (0);
150 }
151
Op_Narrator()152 int16 Op_Narrator() {
153 int pop1 = popVar();
154 int pop2 = popVar();
155
156 if (!pop2)
157 pop2 = currentScriptPtr->overlayNumber;
158
159 narratorOvl = pop2;
160 narratorIdx = pop1;
161
162 return (0);
163 }
164
Op_GetMouseX()165 int16 Op_GetMouseX() {
166 int16 dummy;
167 int16 mouseX;
168 int16 mouseY;
169 int16 mouseButton;
170
171 getMouseStatus(&dummy, &mouseX, &mouseButton, &mouseY);
172
173 return (mouseX);
174 }
175
Op_GetMouseY()176 int16 Op_GetMouseY() {
177 int16 dummy;
178 int16 mouseX;
179 int16 mouseY;
180 int16 mouseButton;
181
182 getMouseStatus(&dummy, &mouseX, &mouseButton, &mouseY);
183
184 return (mouseY);
185 }
186
Op_Random()187 int16 Op_Random() {
188 int var = popVar();
189
190 if (var < 2) {
191 return (0);
192 }
193
194 return (_vm->_rnd.getRandomNumber(var - 1));
195 }
196
Op_PlayFX()197 int16 Op_PlayFX() {
198 int volume = popVar();
199
200 #if 0
201 int speed = popVar();
202 int channelNum = popVar();
203 #else
204 popVar();
205 popVar();
206 #endif
207
208 int sampleNum = popVar();
209
210 if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) {
211 #if 0
212 if (speed == -1)
213 speed = filesDatabase[sampleNum].subData.transparency;
214 #endif
215
216 _vm->sound().playSound(filesDatabase[sampleNum].subData.ptr,
217 filesDatabase[sampleNum].width, volume);
218 }
219
220 return (0);
221 }
222
Op_LoopFX()223 int16 Op_LoopFX() {
224 int volume = popVar();
225
226 #if 0
227 int speed = popVar();
228 int channelNum = popVar();
229 #else
230 popVar();
231 popVar();
232 #endif
233
234 int sampleNum = popVar();
235
236 if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) {
237
238 #if 0
239 if (speed == -1)
240 speed = filesDatabase[sampleNum].subData.transparency;
241 #endif
242
243 _vm->sound().playSound(filesDatabase[sampleNum].subData.ptr,
244 filesDatabase[sampleNum].width, volume);
245 }
246
247 return (0);
248 }
249
Op_StopFX()250 int16 Op_StopFX() {
251 int channelNum = popVar();
252
253 if (channelNum == -1) {
254 _vm->sound().stopChannel(0);
255 _vm->sound().stopChannel(1);
256 _vm->sound().stopChannel(2);
257 _vm->sound().stopChannel(3);
258 } else {
259 _vm->sound().stopChannel(channelNum);
260 }
261
262 return 0;
263 }
264
Op_FreqFX()265 int16 Op_FreqFX() {
266 int volume = popVar();
267 int freq2 = popVar();
268 int channelNum = popVar();
269 int sampleNum = popVar();
270
271 if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) {
272 int freq = Period(freq2 * 1000);
273
274 _vm->sound().startNote(channelNum, volume, freq);
275 }
276
277 return (0);
278 }
279
Op_FreeCT()280 int16 Op_FreeCT() {
281 freeCTP();
282 return (0);
283 }
284
freeObjectList(cellStruct * pListHead)285 void freeObjectList(cellStruct *pListHead) {
286 int var_2 = 0;
287 cellStruct *pCurrent = pListHead->next;
288
289 while (pCurrent) {
290 cellStruct *pNext = pCurrent->next;
291
292 if (pCurrent->freeze == 0) {
293 if (pCurrent->gfxPtr)
294 freeGfx(pCurrent->gfxPtr);
295 MemFree(pCurrent);
296 }
297
298 var_2 = 1;
299
300 pCurrent = pNext;
301 }
302
303 if (var_2) {
304 resetPtr(pListHead);
305 }
306 }
307
Op_FreeCell()308 int16 Op_FreeCell() {
309 freeObjectList(&cellHead);
310 return (0);
311 }
312
Op_freeBackgroundInscrustList()313 int16 Op_freeBackgroundInscrustList() {
314 freeBackgroundIncrustList(&backgroundIncrustHead);
315 return (0);
316 }
317
318
Op_UnmergeBackgroundIncrust()319 int16 Op_UnmergeBackgroundIncrust() {
320 int obj = popVar();
321 int ovl = popVar();
322
323 if (!ovl) {
324 ovl = currentScriptPtr->overlayNumber;
325 }
326
327 unmergeBackgroundIncrust(&backgroundIncrustHead, ovl, obj);
328
329 return (0);
330 }
331
Op_FreePreload()332 int16 Op_FreePreload() {
333 // TODO: See if this is needed
334 debug(1, "Op_FreePreload not implemented");
335 return (0);
336 }
337
Op_RemoveMessage()338 int16 Op_RemoveMessage() {
339 int idx;
340 int overlay;
341
342 idx = popVar();
343 overlay = popVar();
344
345 if (!overlay) {
346 overlay = currentScriptPtr->overlayNumber;
347 }
348
349 removeCell(&cellHead, overlay, idx, 5, masterScreen);
350
351 return (0);
352 }
353
Op_FindSet()354 int16 Op_FindSet() {
355 char *ptr = (char *) popPtr();
356 if (!ptr)
357 return -1;
358
359 char name[36] = "";
360 Common::strlcpy(name, ptr, sizeof(name));
361 strToUpper(name);
362
363 for (int i = 0; i < NUM_FILE_ENTRIES; i++) {
364 if (!strcmp(name, filesDatabase[i].subData.name)) {
365 return (i);
366 }
367 }
368
369 return -1;
370 }
371
Op_RemoveFrame()372 int16 Op_RemoveFrame() {
373 int count = popVar();
374 int start = popVar();
375
376 resetFileEntryRange(start, count);
377
378 return (0);
379 }
380
Op_comment()381 int16 Op_comment() {
382 char *var;
383
384 var = (char *)popPtr();
385
386 debug(1, "COMMENT: \"%s\"", var);
387
388 return (0);
389 }
390
Op_RemoveProc()391 int16 Op_RemoveProc() {
392 int idx;
393 int overlay;
394
395 idx = popVar();
396 overlay = popVar();
397
398 if (!overlay) {
399 overlay = currentScriptPtr->overlayNumber;
400 }
401
402 removeScript(overlay, idx, &procHead);
403
404 return (0);
405 }
406
Op_FreeOverlay()407 int16 Op_FreeOverlay() {
408 char localName[36] = "";
409 char *namePtr;
410
411 namePtr = (char *) popPtr();
412 Common::strlcpy(localName, namePtr, sizeof(localName));
413
414 if (localName[0]) {
415 strToUpper(localName);
416 releaseOverlay((char *)localName);
417 }
418
419 return 0;
420 }
421
Op_FindProc()422 int16 Op_FindProc() {
423 char name[36] = "";
424
425 char *ptr = (char *)popPtr();
426 Common::strlcpy(name, ptr, sizeof(name));
427 int param = getProcParam(popVar(), 20, name);
428
429 return param;
430 }
431
Op_GetRingWord()432 int16 Op_GetRingWord() {
433 // Original method had a ringed queue allowing this method to return words one at a time.
434 // But it never seemed to be used; no entries were ever added to the list
435 return 0;
436 }
437
Op_KillMenu()438 int16 Op_KillMenu() {
439 // Free menus, if active
440 if (menuTable[0]) {
441 freeMenu(menuTable[0]);
442 menuTable[0] = NULL;
443 currentActiveMenu = -1;
444 }
445
446 if (menuTable[1]) {
447 freeMenu(menuTable[1]);
448 menuTable[1] = NULL;
449 currentActiveMenu = -1;
450 }
451
452 // Free the message list
453 // if (linkedMsgList) freeMsgList(linkedMsgList);
454 linkedMsgList = NULL;
455 linkedRelation = NULL;
456
457 return 0;
458 }
459
Op_UserMenu()460 int16 Op_UserMenu() {
461 int oldValue = playerMenuEnabled;
462 playerMenuEnabled = popVar();
463
464 return oldValue;
465 }
466
Op_UserOn()467 int16 Op_UserOn() {
468 int oldValue = userEnabled;
469 int newValue = popVar();
470
471 if (newValue != -1) {
472 userEnabled = newValue;
473 }
474
475 return oldValue;
476 }
477
Op_Display()478 int16 Op_Display() {
479 int oldValue = displayOn;
480 int newValue = popVar();
481
482 if (newValue != -1) {
483 displayOn = newValue;
484 }
485
486 return oldValue;
487 }
488
Op_FreezeParent()489 int16 Op_FreezeParent() {
490 if (currentScriptPtr->var1A == 20) {
491 changeScriptParamInList(currentScriptPtr->var18, currentScriptPtr->var16, &procHead, -1, 9997);
492 } else if (currentScriptPtr->var1A == 30) {
493 changeScriptParamInList(currentScriptPtr->var18, currentScriptPtr->var16, &relHead, -1, 9997);
494 }
495
496 return 0;
497 }
498
Op_LoadBackground()499 int16 Op_LoadBackground() {
500 int result = 0;
501 char bgName[36] = "";
502 char *ptr;
503 int bgIdx;
504
505 ptr = (char *) popPtr();
506
507 Common::strlcpy(bgName, ptr, sizeof(bgName));
508
509 bgIdx = popVar();
510
511 if (bgIdx >= 0 && bgIdx < NBSCREENS) {
512 strToUpper(bgName);
513
514 gfxModuleData_gfxWaitVSync();
515 gfxModuleData_gfxWaitVSync();
516
517 result = loadBackground(bgName, bgIdx);
518
519 gfxModuleData_addDirtyRect(Common::Rect(0, 0, 320, 200));
520 }
521
522 changeCursor(CURSOR_NORMAL);
523
524 return result;
525 }
526
Op_FrameExist()527 int16 Op_FrameExist() {
528 int param;
529
530 param = popVar();
531
532 if (param < 0 || param > 255) {
533 return 0;
534 }
535
536 if (filesDatabase[param].subData.ptr) {
537 return 1;
538 }
539
540 return 0;
541 }
542
Op_LoadFrame()543 int16 Op_LoadFrame() {
544 int param1;
545 int param2;
546 int param3;
547
548 char name[36] = "";
549 char *ptr = (char *) popPtr();
550 Common::strlcpy(name, ptr, sizeof(name));
551
552 param1 = popVar();
553 param2 = popVar();
554 param3 = popVar();
555
556 if (param3 >= 0 && param3 < NUM_FILE_ENTRIES) {
557 strToUpper(name);
558
559 gfxModuleData_gfxWaitVSync();
560 gfxModuleData_gfxWaitVSync();
561
562 lastAni[0] = 0;
563
564 loadFileRange(name, param2, param3, param1);
565
566 lastAni[0] = 0;
567 }
568
569 changeCursor(CURSOR_NORMAL);
570 return 0;
571 }
572
Op_LoadAbs()573 int16 Op_LoadAbs() {
574 int result = 0;
575
576 char *ptr = (char *) popPtr();
577 int slot = popVar();
578
579 if ((slot >= 0) && (slot < NUM_FILE_ENTRIES)) {
580 char name[36] = "";
581 Common::strlcpy(name, ptr, sizeof(name));
582 strToUpper(name);
583
584 gfxModuleData_gfxWaitVSync();
585 gfxModuleData_gfxWaitVSync();
586
587 result = loadFullBundle(name, slot);
588 }
589
590 changeCursor(CURSOR_NORMAL);
591 return result;
592 }
593
Op_InitializeState()594 int16 Op_InitializeState() {
595 int param1 = popVar();
596 int objIdx = popVar();
597 int ovlIdx = popVar();
598
599 if (!ovlIdx)
600 ovlIdx = currentScriptPtr->overlayNumber;
601
602 #ifdef FUNCTION_DEBUG
603 debug(1, "Init %s state to %d", getObjectName(objIdx, overlayTable[ovlIdx].ovlData->arrayNameObj), param1);
604 #endif
605
606 objInit(ovlIdx, objIdx, param1);
607
608 return (0);
609 }
610
Op_GetlowMemory()611 int16 Op_GetlowMemory() {
612 return 0;
613 }
614
Op_AniDir()615 int16 Op_AniDir() {
616 int type = popVar();
617 int objIdx = popVar();
618 int ovlIdx = popVar();
619
620 if (!ovlIdx)
621 ovlIdx = currentScriptPtr->overlayNumber;
622
623 actorStruct *pActor = findActor(&actorHead, ovlIdx, objIdx, type);
624 if (pActor)
625 return pActor->startDirection;
626
627 return -1;
628 }
629
Op_FadeOut()630 int16 Op_FadeOut() {
631 for (long int i = 0; i < 256; i += 32) {
632 for (long int j = 0; j < 256; j++) {
633 int offsetTable[3];
634 offsetTable[0] = -32;
635 offsetTable[1] = -32;
636 offsetTable[2] = -32;
637 calcRGB(&workpal[3*j], &workpal[3*j], offsetTable);
638 }
639 gfxModuleData_setPal256(workpal);
640 gfxModuleData_flipScreen();
641 }
642
643 memset(globalScreen, 0, 320 * 200);
644 flip();
645
646 fadeFlag = 1;
647 PCFadeFlag = true;
648
649 return 0;
650 }
651
isOverlayLoaded(const char * name)652 int16 isOverlayLoaded(const char * name) {
653 int16 i;
654
655 for (i = 1; i < numOfLoadedOverlay; i++) {
656 if (!strcmp(overlayTable[i].overlayName, name) && overlayTable[i].alreadyLoaded) {
657 return i;
658 }
659 }
660
661 return 0;
662 }
663
Op_FindOverlay()664 int16 Op_FindOverlay() {
665 char name[36] = "";
666 char *ptr;
667
668 ptr = (char *) popPtr();
669 Common::strlcpy(name, ptr, sizeof(name));
670 strToUpper(name);
671
672 return (isOverlayLoaded(name));
673 }
674
Op_WriteObject()675 int16 Op_WriteObject() {
676 int16 returnParam;
677
678 int16 param1 = popVar();
679 int16 param2 = popVar();
680 int16 param3 = popVar();
681 int16 param4 = popVar();
682
683 getSingleObjectParam(param4, param3, param2, &returnParam);
684 setObjectPosition(param4, param3, param2, param1);
685
686 return returnParam;
687 }
688
Op_ReadObject()689 int16 Op_ReadObject() {
690 int16 returnParam;
691
692 int member = popVar();
693 int obj = popVar();
694 int ovl = popVar();
695
696 getSingleObjectParam(ovl, obj, member, &returnParam);
697
698 return returnParam;
699 }
700
Op_FadeIn()701 int16 Op_FadeIn() {
702 doFade = 1;
703 return 0;
704 }
705
Op_GetMouseButton()706 int16 Op_GetMouseButton() {
707 int16 dummy;
708 int16 mouseX;
709 int16 mouseY;
710 int16 mouseButton;
711
712 getMouseStatus(&dummy, &mouseX, &mouseButton, &mouseY);
713
714 return mouseButton;
715 }
716
Op_AddCell()717 int16 Op_AddCell() {
718 int16 objType = popVar();
719 int16 objIdx = popVar();
720 int16 overlayIdx = popVar();
721
722 if (!overlayIdx)
723 overlayIdx = currentScriptPtr->overlayNumber;
724
725 addCell(&cellHead, overlayIdx, objIdx, objType, masterScreen, currentScriptPtr->overlayNumber, currentScriptPtr->scriptNumber, currentScriptPtr->type);
726
727 return 0;
728 }
729
Op_AddBackgroundIncrust()730 int16 Op_AddBackgroundIncrust() {
731
732 int16 objType = popVar();
733 int16 objIdx = popVar();
734 int16 overlayIdx = popVar();
735
736 if (!overlayIdx)
737 overlayIdx = currentScriptPtr->overlayNumber;
738
739 addBackgroundIncrust(overlayIdx, objIdx, &backgroundIncrustHead, currentScriptPtr->scriptNumber, currentScriptPtr->overlayNumber, masterScreen, objType);
740
741 return 0;
742 }
743
Op_RemoveCell()744 int16 Op_RemoveCell() {
745 int objType = popVar();
746 int objectIdx = popVar();
747 int ovlNumber = popVar();
748
749 if (!ovlNumber) {
750 ovlNumber = currentScriptPtr->overlayNumber;
751 }
752
753 removeCell(&cellHead, ovlNumber, objectIdx, objType, masterScreen);
754
755 return 0;
756 }
757
758 int16 fontFileIndex = -1;
759
Op_SetFont()760 int16 Op_SetFont() {
761 fontFileIndex = popVar();
762
763 return 0;
764 }
765
Op_UnfreezeParent()766 int16 Op_UnfreezeParent() {
767 if (currentScriptPtr->var1A == 0x14) {
768 changeScriptParamInList(currentScriptPtr->var18, currentScriptPtr->var16, &procHead, -1, 0);
769 } else if (currentScriptPtr->var1A == 0x1E) {
770 changeScriptParamInList(currentScriptPtr->var18, currentScriptPtr->var16, &relHead, -1, 0);
771 }
772
773 return 0;
774 }
775
Op_ProtectionFlag()776 int16 Op_ProtectionFlag() {
777 int16 temp = protectionCode;
778 int16 newVar;
779
780 newVar = popVar();
781 if (newVar != -1) {
782 protectionCode = newVar;
783 }
784
785 return temp;
786 }
787
Op_ClearScreen()788 int16 Op_ClearScreen() {
789 int bgIdx = popVar();
790
791 if ((bgIdx >= 0) && (bgIdx < NBSCREENS) && (backgroundScreens[bgIdx])) {
792 memset(backgroundScreens[bgIdx], 0, 320 * 200);
793 backgroundChanged[bgIdx] = true;
794 strcpy(backgroundTable[0].name, "");
795 }
796
797 return 0;
798 }
799
Op_AddMessage()800 int16 Op_AddMessage() {
801 int16 color = popVar();
802 int16 var_2 = popVar();
803 int16 var_4 = popVar();
804 int16 var_6 = popVar();
805 int16 var_8 = popVar();
806 int16 overlayIdx = popVar();
807
808 if (!overlayIdx)
809 overlayIdx = currentScriptPtr->overlayNumber;
810
811 if (color == -1) {
812 color = findHighColor();
813 } else {
814 if (CVTLoaded) {
815 color = cvtPalette[color];
816 }
817 }
818
819 createTextObject(&cellHead, overlayIdx, var_8, var_6, var_4, var_2, color, masterScreen, currentScriptPtr->overlayNumber, currentScriptPtr->scriptNumber);
820
821 return 0;
822 }
823
Op_Preload()824 int16 Op_Preload() {
825 popPtr();
826 popVar();
827
828 return 0;
829 }
830
Op_LoadCt()831 int16 Op_LoadCt() {
832 return initCt((const char *)popPtr());
833 }
834
Op_EndAnim()835 int16 Op_EndAnim() {
836 int param1 = popVar();
837 int param2 = popVar();
838 int overlay = popVar();
839
840 if (!overlay)
841 overlay = currentScriptPtr->overlayNumber;
842
843 return isAnimFinished(overlay, param2, &actorHead, param1);
844 }
845
Op_Protect()846 int16 Op_Protect() {
847 popPtr();
848 popVar();
849
850 return 0;
851 }
852
Op_AutoCell()853 int16 Op_AutoCell() {
854 cellStruct *pObject;
855
856 int signal = popVar();
857 int loop = popVar();
858 int wait = popVar();
859 int animStep = popVar();
860 int end = popVar();
861 int start = popVar();
862 int type = popVar();
863 int change = popVar();
864 int obj = popVar();
865 int overlay = popVar();
866
867 if (!overlay)
868 overlay = currentScriptPtr->overlayNumber;
869
870 pObject = addCell(&cellHead, overlay, obj, 4, masterScreen, currentScriptPtr->overlayNumber, currentScriptPtr->scriptNumber, currentScriptPtr->type);
871
872 if (!pObject)
873 return 0;
874
875 pObject->animSignal = signal;
876 pObject->animLoop = loop;
877 pObject->animWait = wait;
878 pObject->animStep = animStep;
879 pObject->animEnd = end;
880 pObject->animStart = start;
881 pObject->animType = type;
882 pObject->animChange = change;
883
884 if (type) {
885 if (currentScriptPtr->type == scriptType_PROC) {
886 changeScriptParamInList(currentScriptPtr->overlayNumber, currentScriptPtr->scriptNumber, &procHead, -1, 9996);
887 } else if (currentScriptPtr->type == scriptType_REL) {
888 changeScriptParamInList(currentScriptPtr->overlayNumber, currentScriptPtr->scriptNumber, &relHead, -1, 9996);
889 }
890 }
891
892 if (change == 5) {
893 objInit(pObject->overlay, pObject->idx, start);
894 } else {
895 setObjectPosition(pObject->overlay, pObject->idx, pObject->animChange, start);
896 }
897
898 if (wait < 0) {
899 objectParamsQuery params;
900
901 getMultipleObjectParam(overlay, obj, ¶ms);
902 pObject->animCounter = params.state2 - 1;
903 }
904
905 return 0;
906 }
907
Op_Sizeof()908 int16 Op_Sizeof() {
909 objectParamsQuery params;
910 int index = popVar();
911 int overlay = popVar();
912
913 if (!overlay)
914 overlay = currentScriptPtr->overlayNumber;
915
916 getMultipleObjectParam(overlay, index, ¶ms);
917
918 return params.nbState - 1;
919 }
920
Op_SetActiveBackground()921 int16 Op_SetActiveBackground() {
922 int currentPlane = masterScreen;
923 int newPlane = popVar();
924
925 if (newPlane >= 0 && newPlane < NBSCREENS) {
926 if (backgroundScreens[newPlane]) {
927 masterScreen = newPlane;
928 backgroundChanged[newPlane] = true;
929 switchPal = 1;
930 }
931 }
932
933 return currentPlane;
934 }
935
Op_RemoveBackground()936 int16 Op_RemoveBackground() {
937 int backgroundIdx = popVar();
938
939 if (backgroundIdx > 0 && backgroundIdx < 8) {
940 if (backgroundScreens[backgroundIdx])
941 MemFree(backgroundScreens[backgroundIdx]);
942
943 if (masterScreen == backgroundIdx) {
944 masterScreen = 0;
945 backgroundChanged[0] = true;
946 }
947
948 strcpy(backgroundTable[backgroundIdx].name, "");
949 } else {
950 strcpy(backgroundTable[0].name, "");
951 }
952
953 return (0);
954 }
955
956 int vblLimit;
957
Op_VBL()958 int16 Op_VBL() {
959 vblLimit = popVar();
960 return 0;
961 }
962
963 int op7BVar = 0;
964
Op_Sec()965 int16 Op_Sec() {
966 int di = popVar();
967 int si = 1 - op7BVar;
968 int sign;
969
970 if (di) {
971 sign = di / (ABS(di));
972 } else {
973 sign = 0;
974 }
975
976 op7BVar = -sign;
977
978 return si;
979 }
980
Op_RemoveBackgroundIncrust()981 int16 Op_RemoveBackgroundIncrust() {
982 int idx = popVar();
983 int overlay = popVar();
984
985 if (!overlay) {
986 overlay = currentScriptPtr->overlayNumber;
987 }
988
989 removeBackgroundIncrust(overlay, idx, &backgroundIncrustHead);
990
991 return 0;
992 }
993
Op_SetColor()994 int16 Op_SetColor() {
995 int colorB = popVar();
996 int colorG = popVar();
997 int colorR = popVar();
998 int endIdx = popVar();
999 int startIdx = popVar();
1000
1001 #define convertRatio 36.571428571428571428571428571429
1002
1003 for (int i = startIdx; i <= endIdx; i++) {
1004 int offsetTable[3];
1005
1006 offsetTable[0] = (int)(colorR * convertRatio);
1007 offsetTable[1] = (int)(colorG * convertRatio);
1008 offsetTable[2] = (int)(colorB * convertRatio);
1009
1010 if (CVTLoaded) {
1011 int colorIdx = cvtPalette[i];
1012 calcRGB(&palScreen[masterScreen][3*colorIdx], &workpal[3*colorIdx], offsetTable);
1013 } else {
1014 calcRGB(&palScreen[masterScreen][3*i], &workpal[3*i], offsetTable);
1015 }
1016 }
1017
1018 gfxModuleData_setPalEntries(workpal, 0, 32);
1019
1020 return 0;
1021 }
1022
Op_Inventory()1023 int16 Op_Inventory() {
1024 int si = var41;
1025
1026 var41 = popVar();
1027
1028 return si;
1029 }
1030
Op_RemoveOverlay()1031 int16 Op_RemoveOverlay() {
1032 int overlayIdx;
1033
1034 overlayIdx = popVar();
1035
1036 if (strlen(overlayTable[overlayIdx].overlayName)) {
1037 releaseOverlay(overlayTable[overlayIdx].overlayName);
1038 }
1039
1040 return 0;
1041 }
1042
Op_ComputeLine()1043 int16 Op_ComputeLine() {
1044 int y2 = popVar();
1045 int x2 = popVar();
1046 int y1 = popVar();
1047 int x1 = popVar();
1048
1049 point* pDest = (point *)popPtr();
1050
1051 int maxValue = cor_droite(x1, y1, x2, y2, pDest);
1052
1053 flipGen(pDest, maxValue * 4);
1054
1055 return maxValue;
1056 }
1057
Op_FindMsg()1058 int16 Op_FindMsg() {
1059 int si = popVar();
1060 popVar();
1061
1062 return si;
1063 }
1064
Op_SetZoom()1065 int16 Op_SetZoom() {
1066 var46 = popVar();
1067 var45 = popVar();
1068 var42 = popVar();
1069 var39 = popVar();
1070 return 0;
1071 }
1072
computeZoom(int param)1073 int16 computeZoom(int param) {
1074 return (((param - var46) * (var39 - var42)) / (var45 - var46)) + var42;
1075 }
1076
subOp23(int param1,int param2)1077 int16 subOp23(int param1, int param2) {
1078 return (param1 * param2) >> 8;
1079 }
1080
Op_GetStep()1081 int16 Op_GetStep() {
1082 int si = popVar();
1083 int dx = popVar();
1084
1085 return subOp23(dx, si);
1086 }
1087
Op_GetZoom()1088 int16 Op_GetZoom() {
1089 return (computeZoom(popVar()));
1090 }
1091
addAnimation(actorStruct * pHead,int overlay,int objIdx,int param,int param2)1092 actorStruct *addAnimation(actorStruct * pHead, int overlay, int objIdx, int param, int param2) {
1093 actorStruct *pPrevious = pHead;
1094 actorStruct *pCurrent = pHead->next;
1095
1096 // go to the end of the list
1097 while (pCurrent) {
1098 pPrevious = pCurrent;
1099 pCurrent = pPrevious->next;
1100 }
1101
1102 actorStruct *pNewElement = (actorStruct *) MemAlloc(sizeof(actorStruct));
1103 if (!pNewElement)
1104 return NULL;
1105
1106 memset(pNewElement, 0, sizeof(actorStruct));
1107 pNewElement->next = pPrevious->next;
1108 pPrevious->next = pNewElement;
1109
1110 if (!pCurrent) {
1111 pCurrent = pHead;
1112 }
1113
1114 pNewElement->prev = pCurrent->prev;
1115 pCurrent->prev = pNewElement;
1116
1117 pNewElement->idx = objIdx;
1118 pNewElement->type = param2;
1119 pNewElement->pathId = -1;
1120 pNewElement->overlayNumber = overlay;
1121 pNewElement->startDirection = param;
1122 pNewElement->nextDirection = -1;
1123 pNewElement->stepX = 5;
1124 pNewElement->stepY = 2;
1125 pNewElement->phase = ANIM_PHASE_WAIT;
1126 pNewElement->flag = 0;
1127 pNewElement->freeze = 0;
1128
1129 return pNewElement;
1130 }
1131
removeAnimation(actorStruct * pHead,int overlay,int objIdx,int objType)1132 int removeAnimation(actorStruct * pHead, int overlay, int objIdx, int objType) {
1133 actorStruct* pl;
1134 actorStruct* pl2;
1135 actorStruct* pl3;
1136 actorStruct* pl4;
1137
1138 int dir = 0;
1139
1140 pl = pHead;
1141 pl2 = pl;
1142 pl = pl2->next;
1143
1144 while (pl) {
1145 pl2 = pl;
1146
1147 if (((pl->overlayNumber == overlay) || (overlay == -1)) &&
1148 ((pl->idx == objIdx) || (objIdx == -1)) &&
1149 ((pl->type == objType) || (objType == -1))) {
1150 pl->type = -1;
1151 }
1152
1153 pl = pl2->next;
1154 }
1155
1156 pl = pHead;
1157 pl2 = pl;
1158 pl = pl2->next;
1159
1160 while (pl) {
1161 if (pl->type == -1) {
1162 pl4 = pl->next;
1163 pl2->next = pl4;
1164 pl3 = pl4;
1165
1166 if (pl3 == NULL)
1167 pl3 = pHead;
1168
1169 pl3->prev = pl->prev;
1170
1171 dir = pl->startDirection;
1172
1173 if (pl->pathId >= 0)
1174 freePerso(pl->pathId);
1175
1176 MemFree(pl);
1177 pl = pl4;
1178 } else {
1179 pl2 = pl;
1180 pl = pl2->next;
1181 }
1182 }
1183
1184 return dir;
1185 }
1186
1187 int flag_obstacle; // numPolyBis
1188
1189 // add animation
Op_AddAnimation()1190 int16 Op_AddAnimation() {
1191 int stepY = popVar();
1192 int stepX = popVar();
1193 int direction = popVar();
1194 int start = popVar();
1195 int type = popVar();
1196 int obj = popVar();
1197 int overlay = popVar();
1198
1199 if (!overlay) {
1200 overlay = currentScriptPtr->overlayNumber;
1201 }
1202
1203 if (direction >= 0 && direction <= 3) {
1204 actorStruct *si;
1205
1206 si = addAnimation(&actorHead, overlay, obj, direction, type);
1207
1208 if (si) {
1209 objectParamsQuery params;
1210
1211 getMultipleObjectParam(overlay, obj, ¶ms);
1212
1213 si->x = params.X;
1214 si->y = params.Y;
1215 si->x_dest = -1;
1216 si->y_dest = -1;
1217 si->endDirection = -1;
1218 si->start = start;
1219 si->stepX = stepX;
1220 si->stepY = stepY;
1221
1222 int newFrame = ABS(actor_end[direction][0]) - 1;
1223
1224 int zoom = computeZoom(params.Y);
1225
1226 if (actor_end[direction][0] < 0) {
1227 zoom = -zoom;
1228 }
1229
1230 getPixel(params.X, params.Y);
1231
1232 setObjectPosition(overlay, obj, 3, newFrame + start);
1233 setObjectPosition(overlay, obj, 4, zoom);
1234 setObjectPosition(overlay, obj, 5, numPoly);
1235
1236 animationStart = false;
1237 }
1238 }
1239
1240 return 0;
1241 }
1242
Op_RemoveAnimation()1243 int16 Op_RemoveAnimation() {
1244 int objType = popVar();
1245 int objIdx = popVar();
1246 int ovlIdx = popVar();
1247
1248 if (!ovlIdx) {
1249 ovlIdx = currentScriptPtr->overlayNumber;
1250 }
1251
1252 return removeAnimation(&actorHead, ovlIdx, objIdx, objType);
1253 }
1254
Op_regenerateBackgroundIncrust()1255 int16 Op_regenerateBackgroundIncrust() {
1256 regenerateBackgroundIncrust(&backgroundIncrustHead);
1257 return 0;
1258 }
1259
Op_SetStringColors()1260 int16 Op_SetStringColors() {
1261 // TODO: here ignore if low color mode
1262
1263 subColor = (uint8) popVar();
1264 itemColor = (uint8) popVar();
1265 selectColor = (uint8) popVar();
1266 titleColor = (uint8) popVar();
1267
1268 return 0;
1269 }
1270
Op_XClick()1271 int16 Op_XClick() {
1272 int x = popVar();
1273
1274 if (x != -1) {
1275 aniX = x;
1276 animationStart = true;
1277 }
1278
1279 return aniX;
1280 }
1281
Op_YClick()1282 int16 Op_YClick() {
1283 int y = popVar();
1284
1285 if (y != -1) {
1286 aniY = y;
1287 animationStart = true;
1288 }
1289
1290 return aniY;
1291 }
1292
Op_GetPixel()1293 int16 Op_GetPixel() {
1294 int x = popVar();
1295 int y = popVar();
1296
1297 getPixel(x, y);
1298 return numPoly;
1299 }
1300
Op_TrackAnim()1301 int16 Op_TrackAnim() { // setup actor position
1302 actorStruct *pActor;
1303
1304 int var0 = popVar();
1305 int actorY = popVar();
1306 int actorX = popVar();
1307 int var1 = popVar();
1308 int var2 = popVar();
1309 int overlay = popVar();
1310
1311 if (!overlay) {
1312 overlay = currentScriptPtr->overlayNumber;
1313 }
1314
1315 pActor = findActor(&actorHead, overlay, var2, var1);
1316
1317 if (!pActor) {
1318 return 1;
1319 }
1320
1321 animationStart = false;
1322
1323 pActor->x_dest = actorX;
1324 pActor->y_dest = actorY;
1325 pActor->flag = 1;
1326 pActor->endDirection = var0;
1327
1328 return 0;
1329 }
1330
Op_BgName()1331 int16 Op_BgName() {
1332 char* bgName = (char *)popPtr();
1333 int bgIdx = popVar();
1334
1335 if ((bgIdx >= 0) && (bgIdx < NBSCREENS) && bgName) {
1336 strcpy(bgName, backgroundTable[bgIdx].name);
1337
1338 if (strlen(bgName))
1339 return 1;
1340
1341 return 0;
1342 }
1343
1344 return 0;
1345 }
1346
Op_LoadSong()1347 int16 Op_LoadSong() {
1348 const char *ptr = (const char *)popPtr();
1349 char buffer[33];
1350
1351 Common::strlcpy(buffer, ptr, sizeof(buffer));
1352 strToUpper(buffer);
1353 _vm->sound().loadMusic(buffer);
1354
1355 changeCursor(CURSOR_NORMAL);
1356 return 0;
1357 }
1358
Op_PlaySong()1359 int16 Op_PlaySong() {
1360 if (_vm->sound().songLoaded() && !_vm->sound().songPlayed())
1361 _vm->sound().playMusic();
1362
1363 return 0;
1364 }
1365
Op_StopSong()1366 int16 Op_StopSong() {
1367 if (_vm->sound().isPlaying())
1368 _vm->sound().stopMusic();
1369
1370 return 0;
1371 }
1372
Op_RestoreSong()1373 int16 Op_RestoreSong() {
1374 // Used in the original to restore the contents of a song. Doesn't seem to be used,
1375 // since the backup buffer it uses is never set
1376 return 0;
1377 }
1378
Op_SongSize()1379 int16 Op_SongSize() {
1380 int oldSize;
1381 if (_vm->sound().songLoaded()) {
1382 oldSize = _vm->sound().numOrders();
1383
1384 int size = popVar();
1385 if ((size >= 1) && (size < 128))
1386 _vm->sound().setNumOrders(size);
1387 } else
1388 oldSize = 0;
1389
1390 return oldSize;
1391 }
1392
Op_SetPattern()1393 int16 Op_SetPattern() {
1394 int value = popVar();
1395 int offset = popVar();
1396
1397 if (_vm->sound().songLoaded()) {
1398 _vm->sound().setPattern(offset, value);
1399 }
1400
1401 return 0;
1402 }
1403
Op_FadeSong()1404 int16 Op_FadeSong() {
1405 _vm->sound().fadeSong();
1406
1407 return 0;
1408 }
1409
Op_FreeSong()1410 int16 Op_FreeSong() {
1411 _vm->sound().stopMusic();
1412 _vm->sound().removeMusic();
1413 return 0;
1414 }
1415
Op_SongLoop()1416 int16 Op_SongLoop() {
1417 bool oldLooping = _vm->sound().musicLooping();
1418 _vm->sound().musicLoop(popVar() != 0);
1419
1420 return oldLooping;
1421 }
1422
Op_SongPlayed()1423 int16 Op_SongPlayed() {
1424 return _vm->sound().songPlayed();
1425 }
1426
setVar49Value(int value)1427 void setVar49Value(int value) {
1428 flagCt = value;
1429 }
1430
Op_CTOn()1431 int16 Op_CTOn() {
1432 setVar49Value(1);
1433 return 0;
1434 }
1435
Op_CTOff()1436 int16 Op_CTOff() {
1437 setVar49Value(0);
1438 return 0;
1439 }
1440
Op_FreezeOverlay()1441 int16 Op_FreezeOverlay() {
1442 //int var0;
1443 //int var1;
1444 int temp;
1445
1446 int var0 = popVar();
1447 int var1 = popVar();
1448
1449 if (!var1) {
1450 var1 = currentScriptPtr->overlayNumber;
1451 }
1452
1453 temp = overlayTable[var1].executeScripts;
1454 overlayTable[var1].executeScripts = var0;
1455
1456 return temp;
1457 }
1458
Op_FreezeCell()1459 int16 Op_FreezeCell() {
1460 int newFreezz = popVar();
1461 int oldFreeze = popVar();
1462 int backgroundPlante = popVar();
1463 int objType = popVar();
1464 int objIdx = popVar();
1465 int overlayIdx = popVar();
1466
1467 if (!overlayIdx) {
1468 overlayIdx = currentScriptPtr->overlayNumber;
1469 }
1470
1471 freezeCell(&cellHead, overlayIdx, objIdx, objType, backgroundPlante, oldFreeze, newFreezz);
1472
1473 return 0;
1474 }
1475
Op_60Sub(int overlayIdx,actorStruct * pActorHead,int _var0,int _var1,int _var2,int _var3)1476 void Op_60Sub(int overlayIdx, actorStruct * pActorHead, int _var0, int _var1, int _var2, int _var3) {
1477 actorStruct *pActor = findActor(pActorHead, overlayIdx, _var0, _var3);
1478
1479 if (pActor) {
1480 if ((pActor->freeze == _var2) || (_var2 == -1)) {
1481 pActor->freeze = _var1;
1482 }
1483 }
1484 }
1485
Op_FreezeAni()1486 int16 Op_FreezeAni() {
1487 /*
1488 * int var0;
1489 * int var1;
1490 * int var2;
1491 * int var3;
1492 * int var4;
1493 */
1494
1495 int var0 = popVar();
1496 int var1 = popVar();
1497 int var2 = popVar();
1498 int var3 = popVar();
1499 int var4 = popVar();
1500
1501 if (!var4) {
1502 var4 = currentScriptPtr->overlayNumber;
1503 }
1504
1505 Op_60Sub(var4, &actorHead, var3, var0, var1, var2);
1506
1507 return 0;
1508 }
1509
Op_Itoa()1510 int16 Op_Itoa() {
1511 int nbp = popVar();
1512 int param[160];
1513 char txt[40];
1514
1515 for (int i = 0; i < 160; ++i)
1516 param[i] = 0;
1517
1518 for (int i = nbp - 1; i >= 0; i--)
1519 param[i] = popVar();
1520
1521 int val = popVar();
1522 char* pDest = (char *)popPtr();
1523
1524 if (!nbp)
1525 sprintf(txt, "%d", val);
1526 else {
1527 char format[30];
1528 char nbf[20];
1529 strcpy(format, "%");
1530 sprintf(nbf, "%d", param[0]);
1531 strcat(format, nbf);
1532 strcat(format, "d");
1533 sprintf(txt, format, val);
1534 }
1535
1536 for (int i = 0; txt[i]; i++)
1537 *(pDest++) = txt[i];
1538 *(pDest++) = '\0';
1539
1540 return 0;
1541 }
1542
Op_Strcat()1543 int16 Op_Strcat() {
1544 char *pSource = (char *)popPtr();
1545 char *pDest = (char *)popPtr();
1546
1547 while (*pDest)
1548 pDest++;
1549
1550 while (*pSource)
1551 *(pDest++) = *(pSource++);
1552 *(pDest++) = '\0';
1553
1554 return 0;
1555 }
1556
Op_FindSymbol()1557 int16 Op_FindSymbol() {
1558 int var0 = popVar();
1559 char *ptr = (char *)popPtr();
1560 int var1 = popVar();
1561
1562 if (!var1)
1563 var1 = currentScriptPtr->overlayNumber;
1564
1565 return getProcParam(var1, var0, ptr);
1566 }
1567
Op_FindObject()1568 int16 Op_FindObject() {
1569 char var_26[36];
1570 char *ptr = (char *)popPtr();
1571 int overlayIdx;
1572
1573 var_26[0] = 0;
1574
1575 if (ptr) {
1576 Common::strlcpy(var_26, ptr, sizeof(var_26));
1577 }
1578
1579 overlayIdx = popVar();
1580
1581 if (!overlayIdx)
1582 overlayIdx = currentScriptPtr->overlayNumber;
1583
1584 return getProcParam(overlayIdx, 40, var_26);
1585 }
1586
Op_SetObjectAtNode()1587 int16 Op_SetObjectAtNode() {
1588 int16 node = popVar();
1589 int16 obj = popVar();
1590 int16 ovl = popVar();
1591
1592 if (!ovl)
1593 ovl = currentScriptPtr->overlayNumber;
1594
1595 int nodeInfo[2];
1596
1597 if (!getNode(nodeInfo, node)) {
1598 setObjectPosition(ovl, obj, 0, nodeInfo[0]);
1599 setObjectPosition(ovl, obj, 1, nodeInfo[1]);
1600 setObjectPosition(ovl, obj, 2, nodeInfo[1]);
1601 setObjectPosition(ovl, obj, 4, computeZoom(nodeInfo[1]));
1602 }
1603
1604 return 0;
1605 }
1606
Op_GetNodeX()1607 int16 Op_GetNodeX() {
1608 int16 node = popVar();
1609
1610 int nodeInfo[2];
1611
1612 int result = getNode(nodeInfo, node);
1613
1614 assert(result == 0);
1615
1616 return nodeInfo[0];
1617 }
1618
Op_GetNodeY()1619 int16 Op_GetNodeY() {
1620 int16 node = popVar();
1621
1622 int nodeInfo[2];
1623
1624 int result = getNode(nodeInfo, node);
1625
1626 assert(result == 0);
1627
1628 return nodeInfo[1];
1629 }
1630
Op_SetVolume()1631 int16 Op_SetVolume() {
1632 int oldVolume = _vm->sound().getVolume();
1633 int newVolume = popVar();
1634
1635 if (newVolume > 63) newVolume = 63;
1636 if (newVolume >= 0) {
1637 int volume = 63 - newVolume;
1638 _vm->sound().setVolume(volume);
1639 }
1640
1641 return oldVolume >> 2;
1642 }
1643
Op_SongExist()1644 int16 Op_SongExist() {
1645 const char *songName = (char *)popPtr();
1646
1647 if (songName) {
1648 char name[33];
1649 Common::strlcpy(name, songName, sizeof(name));
1650 strToUpper(name);
1651
1652 if (!strcmp(_vm->sound().musicName(), name))
1653 return 1;
1654 }
1655
1656 return 0;
1657 }
1658
Op_TrackPos()1659 int16 Op_TrackPos() {
1660 // This function returns a variable that never seems to change from 0
1661 return 0;
1662 }
1663
Op_SetNodeState()1664 int16 Op_SetNodeState() {
1665 int16 state = popVar();
1666 int16 node = popVar();
1667
1668 return setNodeState(node, state);
1669 }
1670
Op_SetNodeColor()1671 int16 Op_SetNodeColor() {
1672 int16 color = popVar();
1673 int16 node = popVar();
1674
1675 return setNodeColor(node, color);
1676 }
1677
Op_SetXDial()1678 int16 Op_SetXDial() {
1679 int16 old = xdial;
1680 xdial = popVar();
1681
1682 return old;
1683 }
1684
Op_DialogOn()1685 int16 Op_DialogOn() {
1686 dialogueObj = popVar();
1687 dialogueOvl = popVar();
1688
1689 if (dialogueOvl == 0)
1690 dialogueOvl = currentScriptPtr->overlayNumber;
1691
1692 dialogueEnabled = true;
1693
1694 return 0;
1695 }
1696
Op_DialogOff()1697 int16 Op_DialogOff() {
1698 dialogueEnabled = false;
1699
1700 objectReset();
1701
1702 if (menuTable[0]) {
1703 freeMenu(menuTable[0]);
1704 menuTable[0] = NULL;
1705 changeCursor(CURSOR_NORMAL);
1706 currentActiveMenu = -1;
1707 }
1708
1709 return 0;
1710 }
1711
Op_LinkObjects()1712 int16 Op_LinkObjects() {
1713 int type = popVar();
1714 int obj2 = popVar();
1715 int ovl2 = popVar();
1716 int obj = popVar();
1717 int ovl = popVar();
1718
1719 if (!ovl)
1720 ovl = currentScriptPtr->overlayNumber;
1721 if (!ovl2)
1722 ovl2 = currentScriptPtr->overlayNumber;
1723
1724 linkCell(&cellHead, ovl, obj, type, ovl2, obj2);
1725
1726 return 0;
1727 }
1728
Op_UserClick()1729 int16 Op_UserClick() {
1730 sysKey = popVar();
1731 sysY = popVar();
1732 sysX = popVar();
1733
1734 return 0;
1735 }
1736
Op_XMenuItem()1737 int16 Op_XMenuItem() {
1738 int index = popVar();
1739 int count = 0;
1740
1741 if (!menuTable[0] || (menuTable[0]->numElements == 0))
1742 return 0;
1743
1744 menuElementStruct *p = menuTable[0]->ptrNextElement;
1745
1746 while (p) {
1747 if (count == index)
1748 return p->x + 1;
1749
1750 ++count;
1751 p = p->next;
1752 }
1753
1754 return 0;
1755 }
1756
Op_YMenuItem()1757 int16 Op_YMenuItem() {
1758 int index = popVar();
1759 int count = 0;
1760
1761 if (!menuTable[0] || (menuTable[0]->numElements == 0))
1762 return 0;
1763
1764 menuElementStruct *p = menuTable[0]->ptrNextElement;
1765
1766 while (p) {
1767 if (count == index)
1768 return p->y + 1;
1769
1770 ++count;
1771 p = p->next;
1772 }
1773
1774 return 0;
1775 }
1776
1777
Op_Menu()1778 int16 Op_Menu() {
1779 return (int16)(menuTable[0] != NULL);
1780 }
1781
Op_AutoControl()1782 int16 Op_AutoControl() {
1783 int oldValue = automaticMode;
1784 int newValue = popVar();
1785
1786 if (newValue >= 0) {
1787 automaticMode = newValue;
1788 activeMouse = newValue;
1789 }
1790
1791 return oldValue;
1792 }
1793
Op_MouseMove()1794 int16 Op_MouseMove() {
1795 int16 handle, button;
1796 Common::Point pt;
1797
1798 getMouseStatus(&handle, &pt.x, &button, &pt.y);
1799
1800 // x/y parameters aren't used
1801 popVar();
1802 popVar();
1803
1804 return 0;
1805 }
1806
Op_MouseEnd()1807 int16 Op_MouseEnd() {
1808 if (automoveInc < automoveMax)
1809 return (int16)false;
1810
1811 return (int16)true;
1812 }
1813
Op_MsgExist()1814 int16 Op_MsgExist() {
1815 return isMessage;
1816 }
1817
Op_UserDelay()1818 int16 Op_UserDelay() {
1819 int delay = popVar();
1820
1821 if (delay >= 0) {
1822 userDelay = delay;
1823 }
1824
1825 return userDelay;
1826 }
1827
Op_ThemeReset()1828 int16 Op_ThemeReset() {
1829 objectReset();
1830
1831 return 0;
1832 }
1833
Op_UserWait()1834 int16 Op_UserWait() {
1835 userWait = true;
1836 if (currentScriptPtr->type == scriptType_PROC) {
1837 changeScriptParamInList(currentScriptPtr->overlayNumber, currentScriptPtr->scriptNumber, &procHead, -1, 9999);
1838 } else if (currentScriptPtr->type == scriptType_REL) {
1839 changeScriptParamInList(currentScriptPtr->overlayNumber, currentScriptPtr->scriptNumber, &relHead, -1, 9999);
1840 }
1841
1842 return 0;
1843 }
1844
1845 opcodeFunction opcodeTablePtr[] = {
1846 NULL, // 0x00
1847 Op_FadeIn,
1848 Op_FadeOut,
1849 Op_LoadBackground,
1850 Op_LoadAbs,
1851 Op_AddCell,
1852 Op_AddProc,
1853 Op_InitializeState,
1854 Op_RemoveCell,
1855 Op_FreeCell,
1856 Op_RemoveProc,
1857 Op_RemoveFrame,
1858 Op_LoadOverlay,
1859 Op_SetColor,
1860 Op_PlayFX,
1861 NULL, // used to be debug
1862
1863 Op_FreeOverlay, // 0x10
1864 Op_FindOverlay,
1865 NULL, // used to be exec debug
1866 Op_AddMessage,
1867 Op_RemoveMessage,
1868 Op_UserWait,
1869 Op_FreezeCell,
1870 Op_LoadCt,
1871 Op_AddAnimation,
1872 Op_RemoveAnimation,
1873 Op_SetZoom,
1874 Op_SetObjectAtNode,
1875 Op_SetNodeState,
1876 Op_SetNodeColor,
1877 Op_TrackAnim,
1878 Op_GetNodeX,
1879
1880 Op_GetNodeY, // 0x20
1881 Op_EndAnim,
1882 Op_GetZoom,
1883 Op_GetStep,
1884 Op_SetStringColors,
1885 Op_XClick,
1886 Op_YClick,
1887 Op_GetPixel,
1888 Op_UserOn,
1889 Op_FreeCT,
1890 Op_FindObject,
1891 Op_FindProc,
1892 Op_WriteObject,
1893 Op_ReadObject,
1894 Op_RemoveOverlay,
1895 Op_AddBackgroundIncrust,
1896
1897 Op_RemoveBackgroundIncrust, // 0x30
1898 Op_UnmergeBackgroundIncrust,
1899 Op_freeBackgroundInscrustList,
1900 Op_DialogOn,
1901 Op_DialogOff,
1902 Op_UserDelay,
1903 Op_ThemeReset,
1904 Op_Narrator,
1905 Op_RemoveBackground,
1906 Op_SetActiveBackground,
1907 Op_CTOn,
1908 Op_CTOff,
1909 Op_Random,
1910 Op_LoadSong,
1911 Op_FadeSong,
1912 Op_PlaySong,
1913
1914 Op_FreeSong, // 0x40
1915 Op_FrameExist,
1916 Op_SetVolume,
1917 Op_SongExist,
1918 Op_TrackPos,
1919 Op_StopSong,
1920 Op_RestoreSong,
1921 Op_SongSize,
1922 Op_SetPattern,
1923 Op_SongLoop,
1924 Op_SongPlayed,
1925 Op_LinkObjects,
1926 Op_UserClick,
1927 Op_XMenuItem,
1928 Op_YMenuItem,
1929 Op_Menu,
1930
1931 Op_AutoControl, // 0x50
1932 Op_MouseMove,
1933 Op_MouseEnd,
1934 Op_MsgExist,
1935 Op_SetFont,
1936 NULL, // MergeMsg
1937 Op_Display,
1938 Op_GetMouseX,
1939 Op_GetMouseY,
1940 Op_GetMouseButton,
1941 Op_FindSet,
1942 Op_regenerateBackgroundIncrust,
1943 Op_BgName,
1944 Op_LoopFX,
1945 Op_StopFX,
1946 Op_FreqFX,
1947
1948 Op_FreezeAni, // 0x60
1949 Op_FindMsg,
1950 Op_FreezeParent,
1951 Op_UnfreezeParent,
1952 Op_Exec,
1953 Op_AutoCell,
1954 Op_Sizeof,
1955 Op_Preload,
1956 Op_FreePreload,
1957 NULL, // DeletePreload
1958 Op_VBL,
1959 Op_LoadFrame,
1960 Op_FreezeOverlay,
1961 Op_Strcpy,
1962 Op_Strcat,
1963 Op_Itoa,
1964
1965 Op_comment, // 0x70
1966 Op_ComputeLine,
1967 Op_FindSymbol,
1968 Op_SetXDial,
1969 Op_GetlowMemory,
1970 Op_AniDir,
1971 Op_Protect,
1972 Op_ClearScreen,
1973 Op_Inventory,
1974 Op_UserMenu,
1975 Op_GetRingWord,
1976 Op_Sec,
1977 Op_ProtectionFlag,
1978 Op_KillMenu,
1979 };
1980
opcodeType8()1981 int32 opcodeType8() {
1982 int opcode = getByteFromScript();
1983
1984 if (!opcode)
1985 return (-21);
1986
1987 if (opcode > 0x100)
1988 return (-21);
1989
1990 if (opcode < ARRAYSIZE(opcodeTablePtr) && opcodeTablePtr[opcode]) {
1991 pushVar(opcodeTablePtr[opcode]());
1992 return (0);
1993 } else {
1994 warning("Unsupported opcode %d in opcode type 8", opcode);
1995 pushVar(0);
1996 // exit(1);
1997 }
1998
1999 return 0;
2000
2001 }
2002
2003 } // End of namespace Cruise
2004