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 "common/str.h"
24
25 #include "gob/gob.h"
26 #include "gob/inter.h"
27 #include "gob/global.h"
28 #include "gob/util.h"
29 #include "gob/dataio.h"
30 #include "gob/draw.h"
31 #include "gob/game.h"
32 #include "gob/expression.h"
33 #include "gob/script.h"
34 #include "gob/resources.h"
35 #include "gob/hotspots.h"
36 #include "gob/goblin.h"
37 #include "gob/inter.h"
38 #include "gob/map.h"
39 #include "gob/mult.h"
40 #include "gob/palanim.h"
41 #include "gob/scenery.h"
42 #include "gob/video.h"
43 #include "gob/videoplayer.h"
44 #include "gob/sound/sound.h"
45
46 namespace Gob {
47
48 #define OPCODEVER Inter_v1
49 #define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x)
50 #define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
51 #define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
52
Inter_v1(GobEngine * vm)53 Inter_v1::Inter_v1(GobEngine *vm) : Inter(vm) {
54 }
55
setupOpcodesDraw()56 void Inter_v1::setupOpcodesDraw() {
57 OPCODEDRAW(0x00, o1_loadMult);
58 OPCODEDRAW(0x01, o1_playMult);
59 OPCODEDRAW(0x02, o1_freeMultKeys);
60
61 OPCODEDRAW(0x07, o1_initCursor);
62
63 OPCODEDRAW(0x08, o1_initCursorAnim);
64 OPCODEDRAW(0x09, o1_clearCursorAnim);
65 OPCODEDRAW(0x0A, o1_setRenderFlags);
66
67 OPCODEDRAW(0x10, o1_loadAnim);
68 OPCODEDRAW(0x11, o1_freeAnim);
69 OPCODEDRAW(0x12, o1_updateAnim);
70
71 OPCODEDRAW(0x14, o1_initMult);
72 OPCODEDRAW(0x15, o1_freeMult);
73 OPCODEDRAW(0x16, o1_animate);
74 OPCODEDRAW(0x17, o1_loadMultObject);
75
76 OPCODEDRAW(0x18, o1_getAnimLayerInfo);
77 OPCODEDRAW(0x19, o1_getObjAnimSize);
78 OPCODEDRAW(0x1A, o1_loadStatic);
79 OPCODEDRAW(0x1B, o1_freeStatic);
80
81 OPCODEDRAW(0x1C, o1_renderStatic);
82 OPCODEDRAW(0x1D, o1_loadCurLayer);
83
84 OPCODEDRAW(0x20, o1_playCDTrack);
85 OPCODEDRAW(0x21, o1_getCDTrackPos);
86 OPCODEDRAW(0x22, o1_stopCD);
87
88 OPCODEDRAW(0x30, o1_loadFontToSprite);
89 OPCODEDRAW(0x31, o1_freeFontToSprite);
90 }
91
setupOpcodesFunc()92 void Inter_v1::setupOpcodesFunc() {
93 OPCODEFUNC(0x00, o1_callSub);
94 OPCODEFUNC(0x01, o1_callSub);
95 OPCODEFUNC(0x02, o1_printTotText);
96 OPCODEFUNC(0x03, o1_loadCursor);
97
98 OPCODEFUNC(0x05, o1_switch);
99 OPCODEFUNC(0x06, o1_repeatUntil);
100 OPCODEFUNC(0x07, o1_whileDo);
101
102 OPCODEFUNC(0x08, o1_if);
103 OPCODEFUNC(0x09, o1_assign);
104 OPCODEFUNC(0x0A, o1_loadSpriteToPos);
105 OPCODEFUNC(0x11, o1_printText);
106 OPCODEFUNC(0x12, o1_loadTot);
107 OPCODEFUNC(0x13, o1_palLoad);
108
109 OPCODEFUNC(0x14, o1_keyFunc);
110 OPCODEFUNC(0x15, o1_capturePush);
111 OPCODEFUNC(0x16, o1_capturePop);
112 OPCODEFUNC(0x17, o1_animPalInit);
113
114 OPCODEFUNC(0x1E, o1_drawOperations);
115 OPCODEFUNC(0x1F, o1_setcmdCount);
116
117 OPCODEFUNC(0x20, o1_return);
118 OPCODEFUNC(0x21, o1_renewTimeInVars);
119 OPCODEFUNC(0x22, o1_speakerOn);
120 OPCODEFUNC(0x23, o1_speakerOff);
121
122 OPCODEFUNC(0x24, o1_putPixel);
123 OPCODEFUNC(0x25, o1_goblinFunc);
124 OPCODEFUNC(0x26, o1_createSprite);
125 OPCODEFUNC(0x27, o1_freeSprite);
126
127 OPCODEFUNC(0x30, o1_returnTo);
128 OPCODEFUNC(0x31, o1_loadSpriteContent);
129 OPCODEFUNC(0x32, o1_copySprite);
130 OPCODEFUNC(0x33, o1_fillRect);
131
132 OPCODEFUNC(0x34, o1_drawLine);
133 OPCODEFUNC(0x35, o1_strToLong);
134 OPCODEFUNC(0x36, o1_invalidate);
135 OPCODEFUNC(0x37, o1_setBackDelta);
136
137 OPCODEFUNC(0x38, o1_playSound);
138 OPCODEFUNC(0x39, o1_stopSound);
139 OPCODEFUNC(0x3A, o1_loadSound);
140 OPCODEFUNC(0x3B, o1_freeSoundSlot);
141
142 OPCODEFUNC(0x3C, o1_waitEndPlay);
143 OPCODEFUNC(0x3D, o1_playComposition);
144 OPCODEFUNC(0x3E, o1_getFreeMem);
145 OPCODEFUNC(0x3F, o1_checkData);
146
147 OPCODEFUNC(0x41, o1_cleanupStr);
148 OPCODEFUNC(0x42, o1_insertStr);
149 OPCODEFUNC(0x43, o1_cutStr);
150
151 OPCODEFUNC(0x44, o1_strstr);
152 OPCODEFUNC(0x45, o1_istrlen);
153 OPCODEFUNC(0x46, o1_setMousePos);
154 OPCODEFUNC(0x47, o1_setFrameRate);
155
156 OPCODEFUNC(0x48, o1_animatePalette);
157 OPCODEFUNC(0x49, o1_animateCursor);
158 OPCODEFUNC(0x4A, o1_blitCursor);
159 OPCODEFUNC(0x4B, o1_loadFont);
160
161 OPCODEFUNC(0x4C, o1_freeFont);
162 OPCODEFUNC(0x4D, o1_readData);
163 OPCODEFUNC(0x4E, o1_writeData);
164 OPCODEFUNC(0x4F, o1_manageDataFile);
165 }
166
setupOpcodesGob()167 void Inter_v1::setupOpcodesGob() {
168 OPCODEGOB( 1, o1_setState);
169 OPCODEGOB( 2, o1_setCurFrame);
170 OPCODEGOB( 3, o1_setNextState);
171 OPCODEGOB( 4, o1_setMultState);
172 OPCODEGOB( 5, o1_setOrder);
173 OPCODEGOB( 6, o1_setActionStartState);
174 OPCODEGOB( 7, o1_setCurLookDir);
175 OPCODEGOB( 8, o1_setType);
176 OPCODEGOB( 9, o1_setNoTick);
177 OPCODEGOB( 10, o1_setPickable);
178 OPCODEGOB( 12, o1_setXPos);
179 OPCODEGOB( 13, o1_setYPos);
180 OPCODEGOB( 14, o1_setDoAnim);
181 OPCODEGOB( 15, o1_setRelaxTime);
182 OPCODEGOB( 16, o1_setMaxTick);
183 OPCODEGOB( 21, o1_getState);
184 OPCODEGOB( 22, o1_getCurFrame);
185 OPCODEGOB( 23, o1_getNextState);
186 OPCODEGOB( 24, o1_getMultState);
187 OPCODEGOB( 25, o1_getOrder);
188 OPCODEGOB( 26, o1_getActionStartState);
189 OPCODEGOB( 27, o1_getCurLookDir);
190 OPCODEGOB( 28, o1_getType);
191 OPCODEGOB( 29, o1_getNoTick);
192 OPCODEGOB( 30, o1_getPickable);
193 OPCODEGOB( 32, o1_getObjMaxFrame);
194 OPCODEGOB( 33, o1_getXPos);
195 OPCODEGOB( 34, o1_getYPos);
196 OPCODEGOB( 35, o1_getDoAnim);
197 OPCODEGOB( 36, o1_getRelaxTime);
198 OPCODEGOB( 37, o1_getMaxTick);
199 OPCODEGOB( 40, o1_manipulateMap);
200 OPCODEGOB( 41, o1_getItem);
201 OPCODEGOB( 42, o1_manipulateMapIndirect);
202 OPCODEGOB( 43, o1_getItemIndirect);
203 OPCODEGOB( 44, o1_setPassMap);
204 OPCODEGOB( 50, o1_setGoblinPosH);
205 OPCODEGOB( 52, o1_getGoblinPosXH);
206 OPCODEGOB( 53, o1_getGoblinPosYH);
207 OPCODEGOB( 150, o1_setGoblinMultState);
208 OPCODEGOB( 152, o1_setGoblinUnk14);
209 OPCODEGOB( 200, o1_setItemIdInPocket);
210 OPCODEGOB( 201, o1_setItemIndInPocket);
211 OPCODEGOB( 202, o1_getItemIdInPocket);
212 OPCODEGOB( 203, o1_getItemIndInPocket);
213 OPCODEGOB( 204, o1_setItemPos);
214 OPCODEGOB( 250, o1_setGoblinPos);
215 OPCODEGOB( 251, o1_setGoblinState);
216 OPCODEGOB( 252, o1_setGoblinStateRedraw);
217 OPCODEGOB( 500, o1_decRelaxTime);
218 OPCODEGOB( 502, o1_getGoblinPosX);
219 OPCODEGOB( 503, o1_getGoblinPosY);
220 OPCODEGOB( 600, o1_clearPathExistence);
221 OPCODEGOB( 601, o1_setGoblinVisible);
222 OPCODEGOB( 602, o1_setGoblinInvisible);
223 OPCODEGOB( 603, o1_getObjectIntersect);
224 OPCODEGOB( 604, o1_getGoblinIntersect);
225 OPCODEGOB( 605, o1_setItemPos);
226 OPCODEGOB(1000, o1_loadObjects);
227 OPCODEGOB(1001, o1_freeObjects);
228 OPCODEGOB(1002, o1_animateObjects);
229 OPCODEGOB(1003, o1_drawObjects);
230 OPCODEGOB(1004, o1_loadMap);
231 OPCODEGOB(1005, o1_moveGoblin);
232 OPCODEGOB(1006, o1_switchGoblin);
233 OPCODEGOB(1008, o1_loadGoblin);
234 OPCODEGOB(1009, o1_writeTreatItem);
235 OPCODEGOB(1010, o1_moveGoblin0);
236 OPCODEGOB(1011, o1_setGoblinTarget);
237 OPCODEGOB(1015, o1_setGoblinObjectsPos);
238 OPCODEGOB(2005, o1_initGoblin);
239 }
240
checkSwitchTable(uint32 & offset)241 void Inter_v1::checkSwitchTable(uint32 &offset) {
242 int16 len;
243 int32 value;
244 bool found;
245 bool notFound;
246
247 found = false;
248 notFound = true;
249 offset = 0;
250 value = VAR_OFFSET(_vm->_game->_script->readVarIndex());
251
252 len = _vm->_game->_script->readInt8();
253 while (len != -5) {
254 for (int i = 0; i < len; i++) {
255 _vm->_game->_script->evalExpr(0);
256
257 if (_terminate)
258 return;
259
260 if (_vm->_game->_script->getResultInt() == value) {
261 found = true;
262 notFound = false;
263 }
264 }
265
266 if (found)
267 offset = _vm->_game->_script->pos();
268
269 _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
270 found = false;
271 len = _vm->_game->_script->readInt8();
272 }
273
274 if ((_vm->_game->_script->peekByte() >> 4) != 4)
275 return;
276
277 _vm->_game->_script->skip(1);
278 if (notFound)
279 offset = _vm->_game->_script->pos();
280
281 _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
282 }
283
o1_loadMult()284 void Inter_v1::o1_loadMult() {
285 _vm->_mult->loadMult(_vm->_game->_script->readInt16());
286 }
287
o1_playMult()288 void Inter_v1::o1_playMult() {
289 // NOTE: The EGA version of Gobliiins has an MDY tune.
290 // While the original doesn't play it, we do.
291 bool isGob1EGAIntro = _vm->getGameType() == kGameTypeGob1 &&
292 _vm->isEGA() &&
293 _vm->_game->_script->pos() == 1010 &&
294 _vm->isCurrentTot("intro.tot") &&
295 VAR(57) != 0xFFFFFFFF &&
296 _vm->_dataIO->hasFile("goblins.mdy") &&
297 _vm->_dataIO->hasFile("goblins.tbr");
298
299 int16 checkEscape = _vm->_game->_script->readInt16();
300
301 if (isGob1EGAIntro) {
302 _vm->_sound->adlibLoadTBR("goblins.tbr");
303 _vm->_sound->adlibLoadMDY("goblins.mdy");
304 _vm->_sound->adlibSetRepeating(-1);
305
306 _vm->_sound->adlibPlay();
307 }
308
309 _vm->_mult->playMult(VAR(57), -1, checkEscape, 0);
310
311 if (isGob1EGAIntro) {
312
313 // User didn't escape the intro mult, wait for an escape here
314 if (VAR(57) != 0xFFFFFFFF) {
315 while (_vm->_util->getKey() != kKeyEscape) {
316 _vm->_util->processInput();
317 _vm->_util->longDelay(1);
318 }
319 }
320
321 _vm->_sound->adlibUnload();
322 }
323 }
324
o1_freeMultKeys()325 void Inter_v1::o1_freeMultKeys() {
326 _vm->_game->_script->readInt16();
327 _vm->_mult->freeMultKeys();
328 }
329
o1_initCursor()330 void Inter_v1::o1_initCursor() {
331 int16 width;
332 int16 height;
333 int16 count;
334
335 _vm->_draw->_cursorHotspotXVar = ((uint16) _vm->_game->_script->readVarIndex()) / 4;
336 _vm->_draw->_cursorHotspotYVar = ((uint16) _vm->_game->_script->readVarIndex()) / 4;
337
338 width = _vm->_game->_script->readInt16();
339 if (width < 16)
340 width = 16;
341
342 height = _vm->_game->_script->readInt16();
343 if (height < 16)
344 height = 16;
345
346 _vm->_draw->adjustCoords(0, &width, &height);
347
348 count = _vm->_game->_script->readInt16();
349
350 if (count < 2)
351 count = 2;
352
353 if ((width != _vm->_draw->_cursorWidth) ||
354 (height != _vm->_draw->_cursorHeight) ||
355 (_vm->_draw->_cursorSprites->getWidth() != (width * count))) {
356
357 _vm->_draw->freeSprite(Draw::kCursorSurface);
358 _vm->_draw->_cursorSprites.reset();
359 _vm->_draw->_cursorSpritesBack.reset();
360 _vm->_draw->_scummvmCursor.reset();
361
362 _vm->_draw->_cursorWidth = width;
363 _vm->_draw->_cursorHeight = height;
364
365 if (count < 0x80)
366 _vm->_draw->_transparentCursor = 1;
367 else
368 _vm->_draw->_transparentCursor = 0;
369
370 if (count > 0x80)
371 count -= 0x80;
372
373 _vm->_draw->initSpriteSurf(Draw::kCursorSurface, _vm->_draw->_cursorWidth * count,
374 _vm->_draw->_cursorHeight, 2);
375 _vm->_draw->_cursorSpritesBack = _vm->_draw->_spritesArray[Draw::kCursorSurface];
376 _vm->_draw->_cursorSprites = _vm->_draw->_cursorSpritesBack;
377
378 _vm->_draw->_scummvmCursor =
379 _vm->_video->initSurfDesc(_vm->_draw->_cursorWidth,
380 _vm->_draw->_cursorHeight, SCUMMVM_CURSOR);
381
382 for (int i = 0; i < 40; i++) {
383 _vm->_draw->_cursorAnimLow[i] = -1;
384 _vm->_draw->_cursorAnimDelays[i] = 0;
385 _vm->_draw->_cursorAnimHigh[i] = 0;
386 }
387 _vm->_draw->_cursorAnimLow[1] = 0;
388 }
389 }
390
o1_initCursorAnim()391 void Inter_v1::o1_initCursorAnim() {
392 int16 ind;
393
394 _vm->_draw->_showCursor = 3;
395 ind = _vm->_game->_script->readValExpr();
396 _vm->_draw->_cursorAnimLow[ind] = _vm->_game->_script->readInt16();
397 _vm->_draw->_cursorAnimHigh[ind] = _vm->_game->_script->readInt16();
398 _vm->_draw->_cursorAnimDelays[ind] = _vm->_game->_script->readInt16();
399 }
400
o1_clearCursorAnim()401 void Inter_v1::o1_clearCursorAnim() {
402 int16 ind;
403
404 _vm->_draw->_showCursor = 0;
405 ind = _vm->_game->_script->readValExpr();
406 _vm->_draw->_cursorAnimLow[ind] = -1;
407 _vm->_draw->_cursorAnimHigh[ind] = 0;
408 _vm->_draw->_cursorAnimDelays[ind] = 0;
409 }
410
o1_setRenderFlags()411 void Inter_v1::o1_setRenderFlags() {
412 _vm->_draw->_renderFlags = _vm->_game->_script->readValExpr();
413 }
414
o1_loadAnim()415 void Inter_v1::o1_loadAnim() {
416 _vm->_scenery->loadAnim(0);
417 }
418
o1_freeAnim()419 void Inter_v1::o1_freeAnim() {
420 _vm->_scenery->freeAnim(-1);
421 }
422
o1_updateAnim()423 void Inter_v1::o1_updateAnim() {
424 int16 deltaX;
425 int16 deltaY;
426 int16 flags;
427 int16 frame;
428 int16 layer;
429 int16 animation;
430
431 _vm->_game->_script->evalExpr(&deltaX);
432 _vm->_game->_script->evalExpr(&deltaY);
433 _vm->_game->_script->evalExpr(&animation);
434 _vm->_game->_script->evalExpr(&layer);
435 _vm->_game->_script->evalExpr(&frame);
436 flags = _vm->_game->_script->readInt16();
437 _vm->_scenery->updateAnim(layer, frame, animation, flags,
438 deltaX, deltaY, 1);
439 }
440
o1_initMult()441 void Inter_v1::o1_initMult() {
442 int16 oldAnimHeight;
443 int16 oldAnimWidth;
444 int16 oldObjCount;
445 int16 posXVar;
446 int16 posYVar;
447 int16 animDataVar;
448
449 oldAnimWidth = _vm->_mult->_animWidth;
450 oldAnimHeight = _vm->_mult->_animHeight;
451 oldObjCount = _vm->_mult->_objCount;
452
453 _vm->_mult->_animLeft = _vm->_game->_script->readInt16();
454 _vm->_mult->_animTop = _vm->_game->_script->readInt16();
455 _vm->_mult->_animWidth = _vm->_game->_script->readInt16();
456 _vm->_mult->_animHeight = _vm->_game->_script->readInt16();
457 _vm->_mult->_objCount = _vm->_game->_script->readInt16();
458 posXVar = _vm->_game->_script->readVarIndex();
459 posYVar = _vm->_game->_script->readVarIndex();
460 animDataVar = _vm->_game->_script->readVarIndex();
461
462 if (_vm->_mult->_objects && (oldObjCount != _vm->_mult->_objCount)) {
463 warning("Initializing new objects without having "
464 "cleaned up the old ones at first");
465
466 for (int i = 0; i < _vm->_mult->_objCount; i++) {
467 delete _vm->_mult->_objects[i].pPosX;
468 delete _vm->_mult->_objects[i].pPosY;
469 }
470
471 delete[] _vm->_mult->_objects;
472 delete[] _vm->_mult->_renderData;
473
474 _vm->_mult->_objects = 0;
475 _vm->_mult->_renderObjs = 0;
476
477 }
478
479 if (_vm->_mult->_objects == 0) {
480 _vm->_mult->_renderData = new int16[_vm->_mult->_objCount * 9];
481 memset(_vm->_mult->_renderData, 0,
482 _vm->_mult->_objCount * 9 * sizeof(int16));
483 _vm->_mult->_objects = new Mult::Mult_Object[_vm->_mult->_objCount];
484 memset(_vm->_mult->_objects, 0,
485 _vm->_mult->_objCount * sizeof(Mult::Mult_Object));
486
487 for (int i = 0; i < _vm->_mult->_objCount; i++) {
488 uint32 offPosX = i * 4 + (posXVar / 4) * 4;
489 uint32 offPosY = i * 4 + (posYVar / 4) * 4;
490 uint32 offAnim = animDataVar + i * 4 * _vm->_global->_inter_animDataSize;
491
492 _vm->_mult->_objects[i].pPosX = new VariableReference(*_variables, offPosX);
493 _vm->_mult->_objects[i].pPosY = new VariableReference(*_variables, offPosY);
494
495 _vm->_mult->_objects[i].pAnimData =
496 (Mult::Mult_AnimData *)_variables->getAddressOff8(offAnim);
497
498 _vm->_mult->_objects[i].pAnimData->isStatic = 1;
499 _vm->_mult->_objects[i].tick = 0;
500 _vm->_mult->_objects[i].lastLeft = -1;
501 _vm->_mult->_objects[i].lastRight = -1;
502 _vm->_mult->_objects[i].lastTop = -1;
503 _vm->_mult->_objects[i].lastBottom = -1;
504 }
505 }
506
507 if (_vm->_mult->_animSurf &&
508 ((oldAnimWidth != _vm->_mult->_animWidth) ||
509 (oldAnimHeight != _vm->_mult->_animHeight))) {
510 _vm->_draw->freeSprite(Draw::kAnimSurface);
511 _vm->_mult->_animSurf.reset();
512 }
513
514 if (!_vm->_mult->_animSurf) {
515 _vm->_draw->initSpriteSurf(Draw::kAnimSurface, _vm->_mult->_animWidth,
516 _vm->_mult->_animHeight, 0);
517 _vm->_mult->_animSurf = _vm->_draw->_spritesArray[Draw::kAnimSurface];
518 }
519
520 _vm->_mult->_animSurf->blit(*_vm->_draw->_backSurface,
521 _vm->_mult->_animLeft, _vm->_mult->_animTop,
522 _vm->_mult->_animLeft + _vm->_mult->_animWidth - 1,
523 _vm->_mult->_animTop + _vm->_mult->_animHeight - 1, 0, 0);
524
525 debugC(4, kDebugGraphics, "o1_initMult: x = %d, y = %d, w = %d, h = %d",
526 _vm->_mult->_animLeft, _vm->_mult->_animTop,
527 _vm->_mult->_animWidth, _vm->_mult->_animHeight);
528 debugC(4, kDebugGraphics, " _vm->_mult->_objCount = %d, "
529 "animation data size = %d", _vm->_mult->_objCount,
530 _vm->_global->_inter_animDataSize);
531 }
532
o1_freeMult()533 void Inter_v1::o1_freeMult() {
534 _vm->_mult->freeMult();
535 }
536
o1_animate()537 void Inter_v1::o1_animate() {
538 _vm->_mult->animate();
539 }
540
o1_loadMultObject()541 void Inter_v1::o1_loadMultObject() {
542 int16 val;
543 int16 objIndex;
544 byte *multData;
545
546 _vm->_game->_script->evalExpr(&objIndex);
547 _vm->_game->_script->evalExpr(&val);
548 *_vm->_mult->_objects[objIndex].pPosX = val;
549 _vm->_game->_script->evalExpr(&val);
550 *_vm->_mult->_objects[objIndex].pPosY = val;
551
552 debugC(4, kDebugGameFlow, "Loading mult object %d", objIndex);
553
554 multData = (byte *)_vm->_mult->_objects[objIndex].pAnimData;
555 for (int i = 0; i < 11; i++) {
556 if (_vm->_game->_script->peekUint16() != 99) {
557 _vm->_game->_script->evalExpr(&val);
558 multData[i] = val;
559 } else
560 _vm->_game->_script->skip(1);
561 }
562 }
563
o1_getAnimLayerInfo()564 void Inter_v1::o1_getAnimLayerInfo() {
565 int16 anim;
566 int16 layer;
567 int16 varDX, varDY;
568 int16 varUnk0;
569 int16 varFrames;
570
571 _vm->_game->_script->evalExpr(&anim);
572 _vm->_game->_script->evalExpr(&layer);
573
574 varDX = _vm->_game->_script->readVarIndex();
575 varDY = _vm->_game->_script->readVarIndex();
576 varUnk0 = _vm->_game->_script->readVarIndex();
577 varFrames = _vm->_game->_script->readVarIndex();
578
579 _vm->_scenery->writeAnimLayerInfo(anim, layer,
580 varDX, varDY, varUnk0, varFrames);
581 }
582
o1_getObjAnimSize()583 void Inter_v1::o1_getObjAnimSize() {
584 int16 objIndex;
585
586 _vm->_game->_script->evalExpr(&objIndex);
587
588 uint16 varLeft = _vm->_game->_script->readVarIndex();
589 uint16 varTop = _vm->_game->_script->readVarIndex();
590 uint16 varRight = _vm->_game->_script->readVarIndex();
591 uint16 varBottom = _vm->_game->_script->readVarIndex();
592
593 if ((objIndex < 0) || (objIndex >= _vm->_mult->_objCount)) {
594 warning("o1_getObjAnimSize(): objIndex = %d (%d)", objIndex, _vm->_mult->_objCount);
595 _vm->_scenery->_toRedrawLeft = 0;
596 _vm->_scenery->_toRedrawTop = 0;
597 _vm->_scenery->_toRedrawRight = 0;
598 _vm->_scenery->_toRedrawBottom = 0;
599 } else {
600 Mult::Mult_AnimData &animData = *(_vm->_mult->_objects[objIndex].pAnimData);
601 if (animData.isStatic == 0)
602 _vm->_scenery->updateAnim(animData.layer, animData.frame,
603 animData.animation, 0, *(_vm->_mult->_objects[objIndex].pPosX),
604 *(_vm->_mult->_objects[objIndex].pPosY), 0);
605
606 _vm->_scenery->_toRedrawLeft = MAX<int16>(_vm->_scenery->_toRedrawLeft, 0);
607 _vm->_scenery->_toRedrawTop = MAX<int16>(_vm->_scenery->_toRedrawTop , 0);
608 }
609
610 WRITE_VAR_OFFSET(varLeft , _vm->_scenery->_toRedrawLeft);
611 WRITE_VAR_OFFSET(varTop , _vm->_scenery->_toRedrawTop);
612 WRITE_VAR_OFFSET(varRight , _vm->_scenery->_toRedrawRight);
613 WRITE_VAR_OFFSET(varBottom, _vm->_scenery->_toRedrawBottom);
614 }
615
o1_loadStatic()616 void Inter_v1::o1_loadStatic() {
617 _vm->_scenery->loadStatic(0);
618 }
619
o1_freeStatic()620 void Inter_v1::o1_freeStatic() {
621 _vm->_scenery->freeStatic(-1);
622 }
623
o1_renderStatic()624 void Inter_v1::o1_renderStatic() {
625 int16 layer;
626 int16 index;
627
628 _vm->_game->_script->evalExpr(&index);
629 _vm->_game->_script->evalExpr(&layer);
630 _vm->_scenery->renderStatic(index, layer);
631 }
632
o1_loadCurLayer()633 void Inter_v1::o1_loadCurLayer() {
634 _vm->_game->_script->evalExpr(&_vm->_scenery->_curStatic);
635 _vm->_game->_script->evalExpr(&_vm->_scenery->_curStaticLayer);
636 }
637
o1_playCDTrack()638 void Inter_v1::o1_playCDTrack() {
639 _vm->_sound->adlibPlayBgMusic(); // Mac version
640 _vm->_sound->cdPlay(_vm->_game->_script->evalString()); // PC CD version
641 }
642
o1_getCDTrackPos()643 void Inter_v1::o1_getCDTrackPos() {
644 // Used in gob1 CD
645
646 // Some scripts busy-wait while calling this opcode.
647 // This is a very nasty thing to do, so let's add a
648 // short delay here. It's probably a safe thing to do.
649
650 _vm->_util->longDelay(1);
651
652 int pos = _vm->_sound->cdGetTrackPos();
653 if (pos == -1)
654 pos = 32767;
655 WRITE_VAR(5, pos);
656 }
657
o1_stopCD()658 void Inter_v1::o1_stopCD() {
659 _vm->_sound->adlibStop(); // Mac version
660 _vm->_sound->cdStop(); // PC CD version
661 }
662
o1_loadFontToSprite()663 void Inter_v1::o1_loadFontToSprite() {
664 int16 i = _vm->_game->_script->readInt16();
665 _vm->_draw->_fontToSprite[i].sprite = _vm->_game->_script->readInt16();
666 _vm->_draw->_fontToSprite[i].base = _vm->_game->_script->readInt16();
667 _vm->_draw->_fontToSprite[i].width = _vm->_game->_script->readInt16();
668 _vm->_draw->_fontToSprite[i].height = _vm->_game->_script->readInt16();
669 }
670
o1_freeFontToSprite()671 void Inter_v1::o1_freeFontToSprite() {
672 int16 i = _vm->_game->_script->readInt16();
673 _vm->_draw->_fontToSprite[i].sprite = -1;
674 _vm->_draw->_fontToSprite[i].base = -1;
675 _vm->_draw->_fontToSprite[i].width = -1;
676 _vm->_draw->_fontToSprite[i].height = -1;
677 }
678
o1_callSub(OpFuncParams & params)679 void Inter_v1::o1_callSub(OpFuncParams ¶ms) {
680 uint16 offset = _vm->_game->_script->readUint16();
681
682 debugC(5, kDebugGameFlow, "tot = \"%s\", offset = %d",
683 _vm->_game->_curTotFile.c_str(), offset);
684
685 if (offset < 128) {
686 warning("Inter_v1::o1_callSub(): Offset %d points into the header. "
687 "Skipping call", offset);
688 return;
689 }
690
691 // Skipping the copy protection screen in Gobliiins
692 if (!_vm->_copyProtection && (_vm->getGameType() == kGameTypeGob1) && (offset == 3905) &&
693 _vm->isCurrentTot(_vm->_startTot)) {
694 debugC(2, kDebugGameFlow, "Skipping copy protection screen");
695 return;
696 }
697 // Skipping the copy protection screen in Gobliins 2
698 if (!_vm->_copyProtection && (_vm->getGameType() == kGameTypeGob2) && (offset == 1746) &&
699 _vm->isCurrentTot("intro0.tot")) {
700 debugC(2, kDebugGameFlow, "Skipping copy protection screen");
701 return;
702 }
703
704 _vm->_game->_script->call(offset);
705
706 if ((params.counter == params.cmdCount) && (params.retFlag == 2)) {
707 _vm->_game->_script->pop(false);
708 params.doReturn = true;
709 return;
710 }
711
712 callSub(2);
713
714 _vm->_game->_script->pop();
715 }
716
o1_printTotText(OpFuncParams & params)717 void Inter_v1::o1_printTotText(OpFuncParams ¶ms) {
718 _vm->_draw->printTotText(_vm->_game->_script->readInt16());
719 }
720
o1_loadCursor(OpFuncParams & params)721 void Inter_v1::o1_loadCursor(OpFuncParams ¶ms) {
722 int16 id = _vm->_game->_script->readInt16();
723 int8 index = _vm->_game->_script->readInt8();
724
725 if ((index * _vm->_draw->_cursorWidth) >= _vm->_draw->_cursorSprites->getWidth())
726 return;
727
728 Resource *resource = _vm->_game->_resources->getResource(id);
729 if (!resource)
730 return;
731
732 _vm->_draw->_cursorSprites->fillRect(index * _vm->_draw->_cursorWidth, 0,
733 index * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1,
734 _vm->_draw->_cursorHeight - 1, 0);
735
736 _vm->_video->drawPackedSprite(resource->getData(),
737 resource->getWidth(), resource->getHeight(),
738 index * _vm->_draw->_cursorWidth, 0, 0, *_vm->_draw->_cursorSprites);
739 _vm->_draw->_cursorAnimLow[index] = 0;
740
741 delete resource;
742 }
743
o1_switch(OpFuncParams & params)744 void Inter_v1::o1_switch(OpFuncParams ¶ms) {
745 uint32 offset;
746
747 checkSwitchTable(offset);
748
749 _vm->_game->_script->call(offset);
750
751 if (offset == 0)
752 _vm->_game->_script->setFinished(true);
753
754 if ((params.counter == params.cmdCount) && (params.retFlag == 2)) {
755 _vm->_game->_script->pop(false);
756 params.doReturn = true;
757 return;
758 }
759
760 funcBlock(0);
761
762 _vm->_game->_script->pop();
763 }
764
o1_repeatUntil(OpFuncParams & params)765 void Inter_v1::o1_repeatUntil(OpFuncParams ¶ms) {
766 int16 size;
767 bool flag;
768
769 _nestLevel[0]++;
770
771 uint32 blockPos = _vm->_game->_script->pos();
772
773 do {
774 _vm->_game->_script->seek(blockPos);
775 size = _vm->_game->_script->peekUint16(2) + 2;
776
777 funcBlock(1);
778
779 _vm->_game->_script->seek(blockPos + size + 1);
780
781 flag = _vm->_game->_script->evalBool();
782 } while (!flag && !_break && !_terminate && !_vm->shouldQuit());
783
784 _nestLevel[0]--;
785
786 if (*_breakFromLevel > -1) {
787 _break = false;
788 *_breakFromLevel = -1;
789 }
790 }
791
o1_whileDo(OpFuncParams & params)792 void Inter_v1::o1_whileDo(OpFuncParams ¶ms) {
793 bool flag;
794 int16 size;
795
796 _nestLevel[0]++;
797 do {
798 uint32 startPos = _vm->_game->_script->pos();
799
800 flag = _vm->_game->_script->evalBool();
801
802 if (_terminate)
803 return;
804
805 uint32 blockPos = _vm->_game->_script->pos();
806
807 size = _vm->_game->_script->peekUint16(2) + 2;
808
809 if (flag) {
810 funcBlock(1);
811 _vm->_game->_script->seek(startPos);
812 } else
813 _vm->_game->_script->skip(size);
814
815 if (_break || _terminate || _vm->shouldQuit()) {
816 _vm->_game->_script->seek(blockPos);
817 _vm->_game->_script->skip(size);
818 break;
819 }
820 } while (flag);
821
822 _nestLevel[0]--;
823 if (*_breakFromLevel > -1) {
824 _break = false;
825 *_breakFromLevel = -1;
826 }
827 }
828
o1_if(OpFuncParams & params)829 void Inter_v1::o1_if(OpFuncParams ¶ms) {
830 byte cmd;
831 bool boolRes;
832
833 // WORKAROUND: Gob1 goblin stuck on reload bugs present in original - bugs #3018918 and 3065914
834 if ((_vm->getGameType() == kGameTypeGob1) && (_vm->_game->_script->pos() == 2933) &&
835 _vm->isCurrentTot("inter.tot") && VAR(285) != 0) {
836 warning("Workaround for Gob1 Goblin Stuck On Reload Bug applied...");
837 // VAR(59) actually locks goblin movement, but these variables trigger this in the script.
838 WRITE_VAR(285, 0);
839 }
840
841 boolRes = _vm->_game->_script->evalBool();
842 if (boolRes) {
843 if ((params.counter == params.cmdCount) && (params.retFlag == 2)) {
844 params.doReturn = true;
845 return;
846 }
847
848 _vm->_game->_script->push();
849 funcBlock(0);
850 _vm->_game->_script->pop();
851
852 _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
853
854 debugC(6, kDebugGameFlow, "cmd = %d", (int16) _vm->_game->_script->peekByte());
855
856 cmd = _vm->_game->_script->readByte() >> 4;
857 if (cmd != 12)
858 return;
859
860 _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
861 } else {
862 _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
863
864 debugC(6, kDebugGameFlow, "cmd = %d", (int16) _vm->_game->_script->peekByte());
865
866 cmd = _vm->_game->_script->readByte() >> 4;
867 if (cmd != 12)
868 return;
869
870 if ((params.counter == params.cmdCount) && (params.retFlag == 2)) {
871 params.doReturn = true;
872 return;
873 }
874
875 _vm->_game->_script->push();
876 funcBlock(0);
877 _vm->_game->_script->pop();
878
879 _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2);
880 }
881 }
882
o1_assign(OpFuncParams & params)883 void Inter_v1::o1_assign(OpFuncParams ¶ms) {
884 byte destType = _vm->_game->_script->peekByte();
885 int16 dest = _vm->_game->_script->readVarIndex();
886
887 int16 result;
888 int16 srcType = _vm->_game->_script->evalExpr(&result);
889
890 switch (destType) {
891 case TYPE_VAR_INT32:
892 case TYPE_ARRAY_INT32:
893 WRITE_VAR_OFFSET(dest, _vm->_game->_script->getResultInt());
894 break;
895
896 case TYPE_VAR_STR:
897 case TYPE_ARRAY_STR:
898 if (srcType == TYPE_IMM_INT16)
899 WRITE_VARO_UINT8(dest, result);
900 else
901 WRITE_VARO_STR(dest, _vm->_game->_script->getResultStr());
902 break;
903
904 }
905 }
906
o1_loadSpriteToPos(OpFuncParams & params)907 void Inter_v1::o1_loadSpriteToPos(OpFuncParams ¶ms) {
908 _vm->_draw->_spriteLeft = _vm->_game->_script->readInt16();
909
910 _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
911
912 // WORKAROUND: The EGA version of Gobliiins 1 has an invalid expression there
913 if (_vm->isEGA() && (_vm->_game->_script->pos() == 1398) &&
914 _vm->isCurrentTot("intro.tot")) {
915
916 _vm->_draw->_destSpriteY = 0;
917 _vm->_game->_script->skip(1);
918
919 } else
920 _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
921
922 _vm->_draw->_transparency = _vm->_game->_script->peekByte() & 1;
923 _vm->_draw->_destSurface = ((int16) (_vm->_game->_script->peekByte() >> 1)) - 1;
924 if (_vm->_draw->_destSurface < 0)
925 _vm->_draw->_destSurface = 101;
926
927 _vm->_game->_script->skip(2);
928
929 _vm->_draw->spriteOperation(DRAW_LOADSPRITE);
930 }
931
o1_printText(OpFuncParams & params)932 void Inter_v1::o1_printText(OpFuncParams ¶ms) {
933 char buf[60];
934 int i;
935
936 _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
937 _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
938
939 _vm->_draw->_backColor = _vm->_game->_script->readValExpr();
940 _vm->_draw->_frontColor = _vm->_game->_script->readValExpr();
941 _vm->_draw->_fontIndex = _vm->_game->_script->readValExpr();
942 _vm->_draw->_destSurface = Draw::kBackSurface;
943 _vm->_draw->_textToPrint = buf;
944 _vm->_draw->_transparency = 0;
945
946 if (_vm->_draw->_backColor >= 16) {
947 _vm->_draw->_backColor = 0;
948 _vm->_draw->_transparency = 1;
949 }
950
951 do {
952 for (i = 0; ((_vm->_game->_script->peekChar()) != '.') &&
953 (_vm->_game->_script->peekByte() != 200);
954 i++, _vm->_game->_script->skip(1)) {
955 buf[i] = _vm->_game->_script->peekChar();
956 }
957
958 if (_vm->_game->_script->peekByte() != 200) {
959 _vm->_game->_script->skip(1);
960 switch (_vm->_game->_script->peekByte()) {
961 case TYPE_VAR_INT32:
962 case TYPE_ARRAY_INT32:
963 sprintf(buf + i, "%d",
964 (int32)VAR_OFFSET(_vm->_game->_script->readVarIndex()));
965 break;
966
967 case TYPE_VAR_STR:
968 case TYPE_ARRAY_STR:
969 sprintf(buf + i, "%s",
970 GET_VARO_STR(_vm->_game->_script->readVarIndex()));
971 break;
972 }
973 _vm->_game->_script->skip(1);
974 } else
975 buf[i] = 0;
976
977 _vm->_draw->spriteOperation(DRAW_PRINTTEXT);
978 } while (_vm->_game->_script->peekByte() != 200);
979
980 _vm->_game->_script->skip(1);
981 }
982
o1_loadTot(OpFuncParams & params)983 void Inter_v1::o1_loadTot(OpFuncParams ¶ms) {
984 if ((_vm->_game->_script->peekByte() & 0x80) != 0) {
985 _vm->_game->_script->skip(1);
986 _vm->_game->_totToLoad = _vm->_game->_script->evalString();
987 } else {
988 uint8 size = _vm->_game->_script->readInt8();
989 _vm->_game->_totToLoad = Common::String(_vm->_game->_script->readString(size), size);
990 }
991
992 _vm->_game->_totToLoad += ".tot";
993
994 if (_terminate != 2)
995 _terminate = 1;
996 }
997
o1_palLoad(OpFuncParams & params)998 void Inter_v1::o1_palLoad(OpFuncParams ¶ms) {
999 int index1, index2;
1000 int16 id;
1001 byte cmd;
1002 Resource *resource;
1003
1004 cmd = _vm->_game->_script->readByte();
1005 switch (cmd & 0x7F) {
1006 case 48:
1007 if ((_vm->_global->_fakeVideoMode < 0x32) ||
1008 (_vm->_global->_fakeVideoMode > 0x63)) {
1009 _vm->_game->_script->skip(48);
1010 return;
1011 }
1012 break;
1013
1014 case 49:
1015 if ((_vm->_global->_fakeVideoMode != 5) &&
1016 (_vm->_global->_fakeVideoMode != 7)) {
1017 _vm->_game->_script->skip(18);
1018 return;
1019 }
1020 break;
1021
1022 case 50:
1023 if (_vm->_global->_colorCount == 256) {
1024 _vm->_game->_script->skip(16);
1025 return;
1026 }
1027 break;
1028
1029 case 51:
1030 if (_vm->_global->_fakeVideoMode < 0x64) {
1031 _vm->_game->_script->skip(2);
1032 return;
1033 }
1034 break;
1035
1036 case 52:
1037 if (_vm->_global->_colorCount == 256) {
1038 _vm->_game->_script->skip(48);
1039 return;
1040 }
1041 break;
1042
1043 case 53:
1044 if (_vm->_global->_colorCount != 256) {
1045 _vm->_game->_script->skip(2);
1046 return;
1047 }
1048 break;
1049
1050 case 54:
1051 if (_vm->_global->_fakeVideoMode < 0x13) {
1052 return;
1053 }
1054 break;
1055
1056 case 61:
1057 if (_vm->_global->_fakeVideoMode < 0x13) {
1058 _vm->_game->_script->skip(4);
1059 return;
1060 }
1061 break;
1062 }
1063
1064 if ((cmd & 0x7F) == 0x30) {
1065 _vm->_game->_script->skip(48);
1066 return;
1067 }
1068
1069 _vm->_draw->_applyPal = !(cmd & 0x80);
1070 cmd &= 0x7F;
1071
1072 if (cmd == 49) {
1073 bool allZero = true;
1074
1075 for (int i = 2; i < 18; i++) {
1076 if (_vm->_game->_script->peekByte(i) != 0) {
1077 allZero = false;
1078 break;
1079 }
1080 }
1081 if (!allZero) {
1082 _vm->_draw->_frontSurface->clear();
1083 _vm->_draw->_noInvalidated57 = true;
1084 _vm->_game->_script->skip(48);
1085 return;
1086 }
1087 _vm->_draw->_noInvalidated57 = false;
1088
1089 for (int i = 0; i < 18; i++) {
1090 if (i < 2) {
1091 if (!_vm->_draw->_applyPal)
1092 continue;
1093
1094 _vm->_draw->_unusedPalette1[i] = _vm->_game->_script->peekByte();
1095 continue;
1096 }
1097
1098 index1 = _vm->_game->_script->peekByte() >> 4;
1099 index2 = _vm->_game->_script->peekByte() & 0xF;
1100
1101 _vm->_draw->_unusedPalette1[i] =
1102 ((_vm->_draw->_palLoadData1[index1] +
1103 _vm->_draw->_palLoadData2[index2]) << 8) +
1104 (_vm->_draw->_palLoadData2[index1] +
1105 _vm->_draw->_palLoadData1[index2]);
1106
1107 _vm->_game->_script->skip(1);
1108 }
1109
1110 _vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1;
1111 _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
1112 return;
1113 }
1114
1115 switch (cmd) {
1116 case 50:
1117 for (int i = 0; i < 16; i++)
1118 _vm->_draw->_unusedPalette2[i] = _vm->_game->_script->readByte();
1119 break;
1120
1121 case 52:
1122 for (int i = 0; i < 16; i++) {
1123 _vm->_draw->_vgaPalette[i].red = _vm->_game->_script->readByte();
1124 _vm->_draw->_vgaPalette[i].green = _vm->_game->_script->readByte();
1125 _vm->_draw->_vgaPalette[i].blue = _vm->_game->_script->readByte();
1126 }
1127 break;
1128
1129 case 53:
1130 resource = _vm->_game->_resources->getResource(_vm->_game->_script->readInt16());
1131 if (!resource)
1132 break;
1133
1134 memcpy((char *)_vm->_draw->_vgaPalette, resource->getData(), MIN<int>(768, resource->getSize()));
1135 delete resource;
1136 break;
1137
1138 case 54:
1139 memset((char *)_vm->_draw->_vgaPalette, 0, 768);
1140 break;
1141
1142 case 61:
1143 index1 = _vm->_game->_script->readByte();
1144 index2 = (_vm->_game->_script->readByte() - index1 + 1) * 3;
1145 id = _vm->_game->_script->readInt16();
1146 resource = _vm->_game->_resources->getResource(id);
1147 if (!resource)
1148 break;
1149
1150 memcpy((char *)_vm->_draw->_vgaPalette + index1 * 3,
1151 resource->getData() + index1 * 3, index2);
1152 delete resource;
1153
1154 // WORKAROUND: The Last Dynasty overwrites the 0. palette entry but depends on it staying black.
1155 if ((_vm->getGameType() == kGameTypeDynasty) && (index1 == 0)) {
1156 _vm->_draw->_vgaPalette[0].red = 0;
1157 _vm->_draw->_vgaPalette[0].green = 0;
1158 _vm->_draw->_vgaPalette[0].blue = 0;
1159 }
1160
1161 if (_vm->_draw->_applyPal) {
1162 _vm->_draw->_applyPal = false;
1163 _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
1164 return;
1165 }
1166 break;
1167 }
1168
1169 if (!_vm->_draw->_applyPal) {
1170 _vm->_global->_pPaletteDesc->unused2 = _vm->_draw->_unusedPalette2;
1171 _vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1;
1172
1173 if (_vm->_global->_videoMode < 0x13) {
1174 _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette;
1175 _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, 0, 0);
1176 return;
1177 }
1178 if ((_vm->_global->_videoMode < 0x32) ||
1179 (_vm->_global->_videoMode >= 0x64)) {
1180 _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette;
1181 _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, 0, 0);
1182 return;
1183 }
1184 _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette;
1185 _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, 0, 0);
1186 }
1187 }
1188
o1_keyFunc(OpFuncParams & params)1189 void Inter_v1::o1_keyFunc(OpFuncParams ¶ms) {
1190 if (!_vm->_vidPlayer->isPlayingLive()) {
1191 _vm->_draw->forceBlit();
1192 _vm->_video->retrace();
1193 }
1194
1195 animPalette();
1196 _vm->_draw->blitInvalidated();
1197
1198 handleBusyWait();
1199
1200 // WORKAROUND for bug #1726130: Ween busy-waits in the intro for a counter
1201 // to become 5000. We deliberately slow down busy-waiting, so we shorten
1202 // the counting, too.
1203 if ((_vm->getGameType() == kGameTypeWeen) && (VAR(59) < 4000) &&
1204 (_vm->_game->_script->pos() == 729) && _vm->isCurrentTot("intro5.tot"))
1205 WRITE_VAR(59, 4000);
1206
1207 int16 cmd = _vm->_game->_script->readInt16();
1208 int16 key;
1209
1210 switch (cmd) {
1211 case -1:
1212 break;
1213
1214 case 0:
1215 _vm->_draw->_showCursor &= ~2;
1216 _vm->_util->longDelay(1);
1217 key = _vm->_game->_hotspots->check(0, 0);
1218 storeKey(key);
1219
1220 _vm->_util->clearKeyBuf();
1221 break;
1222
1223 case 1:
1224 if (_vm->getGameType() != kGameTypeFascination)
1225 _vm->_util->forceMouseUp(true);
1226 key = _vm->_game->checkKeys(&_vm->_global->_inter_mouseX,
1227 &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons, 0);
1228 storeKey(key);
1229 break;
1230
1231 case 2:
1232 _vm->_util->processInput(true);
1233 key = _vm->_util->checkKey();
1234
1235 WRITE_VAR(0, key);
1236 _vm->_util->clearKeyBuf();
1237 break;
1238
1239 default:
1240 _vm->_sound->speakerOnUpdate(cmd);
1241 if (cmd < 20) {
1242 _vm->_util->delay(cmd);
1243 _noBusyWait = true;
1244 } else
1245 _vm->_util->longDelay(cmd);
1246 break;
1247 }
1248 }
1249
o1_capturePush(OpFuncParams & params)1250 void Inter_v1::o1_capturePush(OpFuncParams ¶ms) {
1251 int16 left, top;
1252 int16 width, height;
1253
1254 left = _vm->_game->_script->readValExpr();
1255 top = _vm->_game->_script->readValExpr();
1256 width = _vm->_game->_script->readValExpr();
1257 height = _vm->_game->_script->readValExpr();
1258
1259 if ((width < 0) || (height < 0))
1260 return;
1261
1262 _vm->_game->capturePush(left, top, width, height);
1263 (*_vm->_scenery->_pCaptureCounter)++;
1264 }
1265
o1_capturePop(OpFuncParams & params)1266 void Inter_v1::o1_capturePop(OpFuncParams ¶ms) {
1267 if (*_vm->_scenery->_pCaptureCounter != 0) {
1268 (*_vm->_scenery->_pCaptureCounter)--;
1269 _vm->_game->capturePop(1);
1270 }
1271 }
1272
o1_animPalInit(OpFuncParams & params)1273 void Inter_v1::o1_animPalInit(OpFuncParams ¶ms) {
1274 _animPalDir[0] = _vm->_game->_script->readInt16();
1275 _animPalLowIndex[0] = _vm->_game->_script->readValExpr();
1276 _animPalHighIndex[0] = _vm->_game->_script->readValExpr();
1277 }
1278
o1_drawOperations(OpFuncParams & params)1279 void Inter_v1::o1_drawOperations(OpFuncParams ¶ms) {
1280 byte cmd;
1281
1282 cmd = _vm->_game->_script->readByte();
1283
1284 executeOpcodeDraw(cmd);
1285 }
1286
o1_setcmdCount(OpFuncParams & params)1287 void Inter_v1::o1_setcmdCount(OpFuncParams ¶ms) {
1288 params.cmdCount = _vm->_game->_script->readByte();
1289 params.counter = 0;
1290 }
1291
o1_return(OpFuncParams & params)1292 void Inter_v1::o1_return(OpFuncParams ¶ms) {
1293 if (params.retFlag != 2)
1294 _break = true;
1295
1296 _vm->_game->_script->setFinished(true);
1297 params.doReturn = true;
1298 }
1299
o1_renewTimeInVars(OpFuncParams & params)1300 void Inter_v1::o1_renewTimeInVars(OpFuncParams ¶ms) {
1301 renewTimeInVars();
1302 }
1303
o1_speakerOn(OpFuncParams & params)1304 void Inter_v1::o1_speakerOn(OpFuncParams ¶ms) {
1305 _vm->_sound->speakerOn(_vm->_game->_script->readValExpr(), -1);
1306 }
1307
o1_speakerOff(OpFuncParams & params)1308 void Inter_v1::o1_speakerOff(OpFuncParams ¶ms) {
1309 _vm->_sound->speakerOff();
1310 }
1311
o1_putPixel(OpFuncParams & params)1312 void Inter_v1::o1_putPixel(OpFuncParams ¶ms) {
1313 _vm->_draw->_destSurface = _vm->_game->_script->readInt16();
1314
1315 _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
1316 _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
1317 _vm->_draw->_frontColor = _vm->_game->_script->readValExpr();
1318 _vm->_draw->spriteOperation(DRAW_PUTPIXEL);
1319 }
1320
o1_goblinFunc(OpFuncParams & params)1321 void Inter_v1::o1_goblinFunc(OpFuncParams ¶ms) {
1322 OpGobParams gobParams;
1323 bool objDescSet = false;
1324 int16 cmd;
1325
1326 gobParams.extraData = 0;
1327 gobParams.objDesc = 0;
1328 gobParams.retVarPtr.set(*_variables, 236);
1329
1330 cmd = _vm->_game->_script->readInt16();
1331 gobParams.paramCount = _vm->_game->_script->readInt16();
1332
1333 if ((cmd > 0) && (cmd < 17)) {
1334 objDescSet = true;
1335 gobParams.extraData = _vm->_game->_script->readInt16();
1336 gobParams.objDesc = _vm->_goblin->_objects[gobParams.extraData];
1337 gobParams.extraData = _vm->_game->_script->readInt16();
1338 }
1339
1340 if ((cmd > 90) && (cmd < 107)) {
1341 objDescSet = true;
1342 gobParams.extraData = _vm->_game->_script->readInt16();
1343 gobParams.objDesc = _vm->_goblin->_goblins[gobParams.extraData];
1344 gobParams.extraData = _vm->_game->_script->readInt16();
1345 cmd -= 90;
1346 }
1347
1348 if ((cmd > 110) && (cmd < 128)) {
1349 objDescSet = true;
1350 gobParams.extraData = _vm->_game->_script->readInt16();
1351 gobParams.objDesc = _vm->_goblin->_goblins[gobParams.extraData];
1352 cmd -= 90;
1353 } else if ((cmd > 20) && (cmd < 38)) {
1354 objDescSet = true;
1355 gobParams.extraData = _vm->_game->_script->readInt16();
1356 gobParams.objDesc = _vm->_goblin->_objects[gobParams.extraData];
1357 }
1358
1359 /*
1360 NB: The original gobliiins engine did not initialize the gobParams.objDesc
1361 variable, so we manually check if gobParams.objDesc is properly set before
1362 checking if it is zero. If it was not set, we do not return. This
1363 fixes a crash in the EGA version if the life bar is depleted, because
1364 interFunc is called multiple times with cmd == 39.
1365 Bug #1324814
1366 */
1367
1368 if ((cmd < 40) && objDescSet && !gobParams.objDesc)
1369 return;
1370
1371 executeOpcodeGob(cmd, gobParams);
1372 }
1373
o1_createSprite(OpFuncParams & params)1374 void Inter_v1::o1_createSprite(OpFuncParams ¶ms) {
1375 int16 index;
1376 int16 width, height;
1377 int16 flag;
1378
1379 if (_vm->_game->_script->peekByte(1) == 0) {
1380 index = _vm->_game->_script->readInt16();
1381 width = _vm->_game->_script->readInt16();
1382 height = _vm->_game->_script->readInt16();
1383 } else {
1384 index = _vm->_game->_script->readValExpr();
1385 width = _vm->_game->_script->readValExpr();
1386 height = _vm->_game->_script->readValExpr();
1387 }
1388
1389 flag = _vm->_game->_script->readInt16();
1390 _vm->_draw->initSpriteSurf(index, width, height, flag ? 2 : 0);
1391 }
1392
o1_freeSprite(OpFuncParams & params)1393 void Inter_v1::o1_freeSprite(OpFuncParams ¶ms) {
1394 _vm->_draw->freeSprite(_vm->_game->_script->readInt16());
1395 }
1396
o1_returnTo(OpFuncParams & params)1397 void Inter_v1::o1_returnTo(OpFuncParams ¶ms) {
1398 if (params.retFlag == 1) {
1399 _break = true;
1400 _vm->_game->_script->setFinished(true);
1401 params.doReturn = true;
1402 return;
1403 }
1404
1405 if (*_nestLevel == 0)
1406 return;
1407
1408 *_breakFromLevel = *_nestLevel;
1409 _break = true;
1410 _vm->_game->_script->setFinished(true);
1411
1412 params.doReturn = true;
1413 }
1414
o1_loadSpriteContent(OpFuncParams & params)1415 void Inter_v1::o1_loadSpriteContent(OpFuncParams ¶ms) {
1416 _vm->_draw->_spriteLeft = _vm->_game->_script->readInt16();
1417 _vm->_draw->_destSurface = _vm->_game->_script->readInt16();
1418 _vm->_draw->_transparency = _vm->_game->_script->readInt16();
1419 _vm->_draw->_destSpriteX = 0;
1420 _vm->_draw->_destSpriteY = 0;
1421
1422 _vm->_draw->spriteOperation(DRAW_LOADSPRITE);
1423 }
1424
o1_copySprite(OpFuncParams & params)1425 void Inter_v1::o1_copySprite(OpFuncParams ¶ms) {
1426 if (_vm->_game->_script->peekByte(1) == 0)
1427 _vm->_draw->_sourceSurface = _vm->_game->_script->readInt16();
1428 else
1429 _vm->_draw->_sourceSurface = _vm->_game->_script->readValExpr();
1430
1431 if (_vm->_game->_script->peekByte(1) == 0)
1432 _vm->_draw->_destSurface = _vm->_game->_script->readInt16();
1433 else
1434 _vm->_draw->_destSurface = _vm->_game->_script->readValExpr();
1435
1436 _vm->_draw->_spriteLeft = _vm->_game->_script->readValExpr();
1437 _vm->_draw->_spriteTop = _vm->_game->_script->readValExpr();
1438 _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr();
1439 _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr();
1440
1441 _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
1442 _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
1443
1444 _vm->_draw->_transparency = _vm->_game->_script->readInt16();
1445
1446 _vm->_draw->spriteOperation(DRAW_BLITSURF);
1447 }
1448
o1_fillRect(OpFuncParams & params)1449 void Inter_v1::o1_fillRect(OpFuncParams ¶ms) {
1450 int16 destSurf;
1451
1452 _vm->_draw->_destSurface = destSurf = _vm->_game->_script->readInt16();
1453
1454 _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
1455 _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
1456 _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr();
1457 _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr();
1458
1459 _vm->_draw->_backColor = _vm->_game->_script->readValExpr();
1460
1461 if (!_vm->_draw->_spritesArray[(destSurf >= 100) ? (destSurf - 80) : destSurf])
1462 return;
1463
1464 if (_vm->_draw->_spriteRight < 0) {
1465 _vm->_draw->_destSpriteX += _vm->_draw->_spriteRight - 1;
1466 _vm->_draw->_spriteRight = -_vm->_draw->_spriteRight + 2;
1467 }
1468 if (_vm->_draw->_spriteBottom < 0) {
1469 _vm->_draw->_destSpriteY += _vm->_draw->_spriteBottom - 1;
1470 _vm->_draw->_spriteBottom = -_vm->_draw->_spriteBottom + 2;
1471 }
1472
1473 _vm->_draw->spriteOperation(DRAW_FILLRECT);
1474 }
1475
o1_drawLine(OpFuncParams & params)1476 void Inter_v1::o1_drawLine(OpFuncParams ¶ms) {
1477 _vm->_draw->_destSurface = _vm->_game->_script->readInt16();
1478
1479 _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
1480 _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
1481 _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr();
1482 _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr();
1483
1484 _vm->_draw->_frontColor = _vm->_game->_script->readValExpr();
1485 _vm->_draw->spriteOperation(DRAW_DRAWLINE);
1486 }
1487
o1_strToLong(OpFuncParams & params)1488 void Inter_v1::o1_strToLong(OpFuncParams ¶ms) {
1489 char str[20];
1490 int16 strVar;
1491 int16 destVar;
1492 int32 res;
1493
1494 strVar = _vm->_game->_script->readVarIndex();
1495 Common::strlcpy(str, GET_VARO_STR(strVar), 20);
1496 res = atoi(str);
1497
1498 destVar = _vm->_game->_script->readVarIndex();
1499 WRITE_VAR_OFFSET(destVar, res);
1500 }
1501
o1_invalidate(OpFuncParams & params)1502 void Inter_v1::o1_invalidate(OpFuncParams ¶ms) {
1503 _vm->_draw->_destSurface = _vm->_game->_script->readInt16();
1504 _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr();
1505 _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr();
1506 _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr();
1507 _vm->_draw->_frontColor = _vm->_game->_script->readValExpr();
1508 _vm->_draw->spriteOperation(DRAW_INVALIDATE);
1509 }
1510
o1_setBackDelta(OpFuncParams & params)1511 void Inter_v1::o1_setBackDelta(OpFuncParams ¶ms) {
1512 _vm->_draw->_backDeltaX = _vm->_game->_script->readValExpr();
1513 _vm->_draw->_backDeltaY = _vm->_game->_script->readValExpr();
1514 }
1515
o1_playSound(OpFuncParams & params)1516 void Inter_v1::o1_playSound(OpFuncParams ¶ms) {
1517 int16 frequency;
1518 int16 freq2;
1519 int16 repCount;
1520 int16 index;
1521 int16 endRep;
1522
1523 index = _vm->_game->_script->readValExpr();
1524 repCount = _vm->_game->_script->readValExpr();
1525 frequency = _vm->_game->_script->readValExpr();
1526
1527 SoundDesc *sample = _vm->_sound->sampleGetBySlot(index);
1528
1529 _soundEndTimeKey = 0;
1530 if (!sample || sample->empty())
1531 return;
1532
1533 if (repCount < 0) {
1534 if (_vm->_global->_soundFlags < 2)
1535 return;
1536
1537 repCount = -repCount;
1538 _soundEndTimeKey = _vm->_util->getTimeKey();
1539
1540 freq2 = frequency ? frequency : sample->_frequency;
1541 endRep = MAX(repCount - 1, 1);
1542
1543 _soundStopVal = sample->calcFadeOutLength(freq2);
1544 _soundEndTimeKey += sample->calcLength(endRep, freq2, true);
1545 }
1546
1547 if (sample->getType() == SOUND_ADL) {
1548 _vm->_sound->adlibLoadADL(sample->getData(), sample->size(), index);
1549 _vm->_sound->adlibSetRepeating(repCount - 1);
1550 _vm->_sound->adlibPlay();
1551 } else {
1552 _vm->_sound->blasterStop(0);
1553 _vm->_sound->blasterPlay(sample, repCount - 1, frequency);
1554 }
1555 }
1556
o1_stopSound(OpFuncParams & params)1557 void Inter_v1::o1_stopSound(OpFuncParams ¶ms) {
1558 _vm->_sound->adlibStop();
1559 _vm->_sound->blasterStop(_vm->_game->_script->readValExpr());
1560
1561 _soundEndTimeKey = 0;
1562 }
1563
o1_loadSound(OpFuncParams & params)1564 void Inter_v1::o1_loadSound(OpFuncParams ¶ms) {
1565 loadSound(-1);
1566 }
1567
o1_freeSoundSlot(OpFuncParams & params)1568 void Inter_v1::o1_freeSoundSlot(OpFuncParams ¶ms) {
1569 _vm->_game->freeSoundSlot(-1);
1570 }
1571
o1_waitEndPlay(OpFuncParams & params)1572 void Inter_v1::o1_waitEndPlay(OpFuncParams ¶ms) {
1573 _vm->_sound->blasterWaitEndPlay();
1574 }
1575
o1_playComposition(OpFuncParams & params)1576 void Inter_v1::o1_playComposition(OpFuncParams ¶ms) {
1577 int16 dataVar = _vm->_game->_script->readVarIndex();
1578 int16 freqVal = _vm->_game->_script->readValExpr();
1579
1580 int16 composition[50];
1581 int maxEntries = MIN<int>(50, (_variables->getSize() - dataVar) / 4);
1582 for (int i = 0; i < 50; i++)
1583 composition[i] = (i < maxEntries) ? ((int16) VAR_OFFSET(dataVar + i * 4)) : -1;
1584
1585 _vm->_sound->blasterPlayComposition(composition, freqVal);
1586 }
1587
o1_getFreeMem(OpFuncParams & params)1588 void Inter_v1::o1_getFreeMem(OpFuncParams ¶ms) {
1589 int16 freeVar;
1590 int16 maxFreeVar;
1591
1592 freeVar = _vm->_game->_script->readVarIndex();
1593 maxFreeVar = _vm->_game->_script->readVarIndex();
1594
1595 // HACK
1596 WRITE_VAR_OFFSET(freeVar, 1000000);
1597 WRITE_VAR_OFFSET(maxFreeVar, 1000000);
1598 }
1599
o1_checkData(OpFuncParams & params)1600 void Inter_v1::o1_checkData(OpFuncParams ¶ms) {
1601 const char *file = _vm->_game->_script->evalString();
1602 int16 varOff = _vm->_game->_script->readVarIndex();
1603
1604 if (!_vm->_dataIO->hasFile(file)) {
1605 warning("File \"%s\" not found", file);
1606 WRITE_VAR_OFFSET(varOff, (uint32) -1);
1607 } else
1608 WRITE_VAR_OFFSET(varOff, 50); // "handle" between 50 and 128 = in archive
1609 }
1610
o1_cleanupStr(OpFuncParams & params)1611 void Inter_v1::o1_cleanupStr(OpFuncParams ¶ms) {
1612 int16 strVar;
1613
1614 strVar = _vm->_game->_script->readVarIndex();
1615 _vm->_util->cleanupStr(GET_VARO_FSTR(strVar));
1616 }
1617
o1_insertStr(OpFuncParams & params)1618 void Inter_v1::o1_insertStr(OpFuncParams ¶ms) {
1619 int16 pos;
1620 int16 strVar;
1621
1622 strVar = _vm->_game->_script->readVarIndex();
1623 _vm->_game->_script->evalExpr(0);
1624 pos = _vm->_game->_script->readValExpr();
1625
1626 char *str = GET_VARO_FSTR(strVar);
1627 _vm->_util->insertStr(_vm->_game->_script->getResultStr(), str, pos);
1628 }
1629
o1_cutStr(OpFuncParams & params)1630 void Inter_v1::o1_cutStr(OpFuncParams ¶ms) {
1631 int16 strVar;
1632 int16 pos;
1633 int16 size;
1634
1635 strVar = _vm->_game->_script->readVarIndex();
1636 pos = _vm->_game->_script->readValExpr();
1637 size = _vm->_game->_script->readValExpr();
1638 _vm->_util->cutFromStr(GET_VARO_STR(strVar), pos, size);
1639 }
1640
o1_strstr(OpFuncParams & params)1641 void Inter_v1::o1_strstr(OpFuncParams ¶ms) {
1642 int16 strVar;
1643 int16 resVar;
1644 int16 pos;
1645
1646 strVar = _vm->_game->_script->readVarIndex();
1647 _vm->_game->_script->evalExpr(0);
1648 resVar = _vm->_game->_script->readVarIndex();
1649
1650 char *res = strstr(GET_VARO_STR(strVar), _vm->_game->_script->getResultStr());
1651 pos = res ? (res - (GET_VARO_STR(strVar))) : -1;
1652 WRITE_VAR_OFFSET(resVar, pos);
1653 }
1654
o1_istrlen(OpFuncParams & params)1655 void Inter_v1::o1_istrlen(OpFuncParams ¶ms) {
1656 int16 len;
1657 int16 strVar;
1658
1659 strVar = _vm->_game->_script->readVarIndex();
1660 len = strlen(GET_VARO_STR(strVar));
1661 strVar = _vm->_game->_script->readVarIndex();
1662
1663 WRITE_VAR_OFFSET(strVar, len);
1664 }
1665
o1_setMousePos(OpFuncParams & params)1666 void Inter_v1::o1_setMousePos(OpFuncParams ¶ms) {
1667 _vm->_global->_inter_mouseX = _vm->_game->_script->readValExpr();
1668 _vm->_global->_inter_mouseY = _vm->_game->_script->readValExpr();
1669 _vm->_global->_inter_mouseX -= _vm->_video->_scrollOffsetX;
1670 _vm->_global->_inter_mouseY -= _vm->_video->_scrollOffsetY;
1671 if (_vm->_global->_useMouse != 0)
1672 _vm->_util->setMousePos(_vm->_global->_inter_mouseX,
1673 _vm->_global->_inter_mouseY);
1674 }
1675
o1_setFrameRate(OpFuncParams & params)1676 void Inter_v1::o1_setFrameRate(OpFuncParams ¶ms) {
1677 _vm->_util->setFrameRate(_vm->_game->_script->readValExpr());
1678 }
1679
o1_animatePalette(OpFuncParams & params)1680 void Inter_v1::o1_animatePalette(OpFuncParams ¶ms) {
1681 _vm->_draw->blitInvalidated();
1682 _vm->_util->waitEndFrame();
1683 animPalette();
1684 storeKey(_vm->_game->checkKeys(&_vm->_global->_inter_mouseX,
1685 &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons, 0));
1686 }
1687
o1_animateCursor(OpFuncParams & params)1688 void Inter_v1::o1_animateCursor(OpFuncParams ¶ms) {
1689 _vm->_draw->animateCursor(1);
1690 }
1691
o1_blitCursor(OpFuncParams & params)1692 void Inter_v1::o1_blitCursor(OpFuncParams ¶ms) {
1693 _vm->_draw->blitCursor();
1694 }
1695
o1_loadFont(OpFuncParams & params)1696 void Inter_v1::o1_loadFont(OpFuncParams ¶ms) {
1697 const char *font = _vm->_game->_script->evalString();
1698 uint16 index = _vm->_game->_script->readInt16();
1699
1700 _vm->_draw->animateCursor(4);
1701 _vm->_draw->loadFont(index, font);
1702 }
1703
o1_freeFont(OpFuncParams & params)1704 void Inter_v1::o1_freeFont(OpFuncParams ¶ms) {
1705 int16 index;
1706
1707 index = _vm->_game->_script->readInt16();
1708
1709 if (index >= Draw::kFontCount) {
1710 warning("o1_freeFont(): Index %d > count %d", index, Draw::kFontCount);
1711 return;
1712 }
1713
1714 delete _vm->_draw->_fonts[index];
1715 _vm->_draw->_fonts[index] = 0;
1716 }
1717
o1_readData(OpFuncParams & params)1718 void Inter_v1::o1_readData(OpFuncParams ¶ms) {
1719 const char *file = _vm->_game->_script->evalString();
1720 int16 dataVar = _vm->_game->_script->readVarIndex();
1721 int16 size = _vm->_game->_script->readValExpr();
1722 int16 offset = _vm->_game->_script->readValExpr();
1723 int16 retSize = 0;
1724
1725 WRITE_VAR(1, 1);
1726
1727 Common::SeekableReadStream *stream = _vm->_dataIO->getFile(file);
1728 if (!stream)
1729 return;
1730
1731 _vm->_draw->animateCursor(4);
1732 if (offset < 0)
1733 stream->seek(offset + 1, SEEK_END);
1734 else
1735 stream->seek(offset);
1736
1737 if (((dataVar >> 2) == 59) && (size == 4))
1738 WRITE_VAR(59, stream->readUint32LE());
1739 else
1740 retSize = stream->read((byte *)_variables->getAddressOff8(dataVar), size);
1741
1742 if (retSize == size)
1743 WRITE_VAR(1, 0);
1744
1745 delete stream;
1746 }
1747
o1_writeData(OpFuncParams & params)1748 void Inter_v1::o1_writeData(OpFuncParams ¶ms) {
1749 // This writes into a file. It's not portable and isn't needed anyway
1750 // (Gobliiins 1 doesn't use save file), so we just warn should it be
1751 // called regardless.
1752
1753 const char *file = _vm->_game->_script->evalString();
1754
1755 int16 dataVar = _vm->_game->_script->readVarIndex();
1756 int16 size = _vm->_game->_script->readValExpr();
1757 int16 offset = _vm->_game->_script->readValExpr();
1758
1759 warning("Attempted to write to file \"%s\" (%d, %d, %d)", file, dataVar, size, offset);
1760 WRITE_VAR(1, 0);
1761 }
1762
o1_manageDataFile(OpFuncParams & params)1763 void Inter_v1::o1_manageDataFile(OpFuncParams ¶ms) {
1764 Common::String file = _vm->_game->_script->evalString();
1765
1766 if (!file.empty()) {
1767 _vm->_dataIO->openArchive(file, true);
1768 } else {
1769 _vm->_dataIO->closeArchive(true);
1770
1771 // NOTE: Lost in Time might close a data file without explicitely closing a video in it.
1772 // So we make sure that all open videos are still available.
1773 _vm->_vidPlayer->reopenAll();
1774 }
1775 }
1776
o1_setState(OpGobParams & params)1777 void Inter_v1::o1_setState(OpGobParams ¶ms) {
1778 params.objDesc->state = params.extraData;
1779 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1780 _vm->_goblin->_destItemStateVarPtr = (uint32) params.extraData;
1781 }
1782
o1_setCurFrame(OpGobParams & params)1783 void Inter_v1::o1_setCurFrame(OpGobParams ¶ms) {
1784 params.objDesc->curFrame = params.extraData;
1785 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1786 _vm->_goblin->_destItemFrameVarPtr = (uint32) params.extraData;
1787 }
1788
o1_setNextState(OpGobParams & params)1789 void Inter_v1::o1_setNextState(OpGobParams ¶ms) {
1790 params.objDesc->nextState = params.extraData;
1791 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1792 _vm->_goblin->_destItemNextStateVarPtr = (uint32) params.extraData;
1793 }
1794
o1_setMultState(OpGobParams & params)1795 void Inter_v1::o1_setMultState(OpGobParams ¶ms) {
1796 params.objDesc->multState = params.extraData;
1797 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1798 _vm->_goblin->_destItemMultStateVarPtr = (uint32) params.extraData;
1799 }
1800
o1_setOrder(OpGobParams & params)1801 void Inter_v1::o1_setOrder(OpGobParams ¶ms) {
1802 params.objDesc->order = params.extraData;
1803 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1804 _vm->_goblin->_destItemOrderVarPtr = (uint32) params.extraData;
1805 }
1806
o1_setActionStartState(OpGobParams & params)1807 void Inter_v1::o1_setActionStartState(OpGobParams ¶ms) {
1808 params.objDesc->actionStartState = params.extraData;
1809 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1810 _vm->_goblin->_destItemActStartStVarPtr = (uint32) params.extraData;
1811 }
1812
o1_setCurLookDir(OpGobParams & params)1813 void Inter_v1::o1_setCurLookDir(OpGobParams ¶ms) {
1814 params.objDesc->curLookDir = params.extraData;
1815 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1816 _vm->_goblin->_destItemLookDirVarPtr = (uint32) params.extraData;
1817 }
1818
o1_setType(OpGobParams & params)1819 void Inter_v1::o1_setType(OpGobParams ¶ms) {
1820 params.objDesc->type = params.extraData;
1821 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1822 _vm->_goblin->_destItemTypeVarPtr = (uint32) params.extraData;
1823
1824 if (params.extraData == 0)
1825 params.objDesc->toRedraw = 1;
1826 }
1827
o1_setNoTick(OpGobParams & params)1828 void Inter_v1::o1_setNoTick(OpGobParams ¶ms) {
1829 params.objDesc->noTick = params.extraData;
1830 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1831 _vm->_goblin->_destItemNoTickVarPtr = (uint32) params.extraData;
1832 }
1833
o1_setPickable(OpGobParams & params)1834 void Inter_v1::o1_setPickable(OpGobParams ¶ms) {
1835 params.objDesc->pickable = params.extraData;
1836 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1837 _vm->_goblin->_destItemPickableVarPtr = (uint32) params.extraData;
1838 }
1839
o1_setXPos(OpGobParams & params)1840 void Inter_v1::o1_setXPos(OpGobParams ¶ms) {
1841 params.objDesc->xPos = params.extraData;
1842 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1843 _vm->_goblin->_destItemScrXVarPtr = (uint32) params.extraData;
1844 }
1845
o1_setYPos(OpGobParams & params)1846 void Inter_v1::o1_setYPos(OpGobParams ¶ms) {
1847 params.objDesc->yPos = params.extraData;
1848 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1849 _vm->_goblin->_destItemScrYVarPtr = (uint32) params.extraData;
1850 }
1851
o1_setDoAnim(OpGobParams & params)1852 void Inter_v1::o1_setDoAnim(OpGobParams ¶ms) {
1853 params.objDesc->doAnim = params.extraData;
1854 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1855 _vm->_goblin->_destItemDoAnimVarPtr = (uint32) params.extraData;
1856 }
1857
o1_setRelaxTime(OpGobParams & params)1858 void Inter_v1::o1_setRelaxTime(OpGobParams ¶ms) {
1859 params.objDesc->relaxTime = params.extraData;
1860 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1861 _vm->_goblin->_destItemRelaxVarPtr = (uint32) params.extraData;
1862 }
1863
o1_setMaxTick(OpGobParams & params)1864 void Inter_v1::o1_setMaxTick(OpGobParams ¶ms) {
1865 params.objDesc->maxTick = params.extraData;
1866 if (params.objDesc == _vm->_goblin->_actDestItemDesc)
1867 _vm->_goblin->_destItemMaxTickVarPtr = (uint32) params.extraData;
1868 }
1869
o1_getState(OpGobParams & params)1870 void Inter_v1::o1_getState(OpGobParams ¶ms) {
1871 params.retVarPtr = (uint32) params.objDesc->state;
1872 }
1873
o1_getCurFrame(OpGobParams & params)1874 void Inter_v1::o1_getCurFrame(OpGobParams ¶ms) {
1875 params.retVarPtr = (uint32) params.objDesc->curFrame;
1876 }
1877
o1_getNextState(OpGobParams & params)1878 void Inter_v1::o1_getNextState(OpGobParams ¶ms) {
1879 params.retVarPtr = (uint32) params.objDesc->nextState;
1880 }
1881
o1_getMultState(OpGobParams & params)1882 void Inter_v1::o1_getMultState(OpGobParams ¶ms) {
1883 params.retVarPtr = (uint32) params.objDesc->multState;
1884 }
1885
o1_getOrder(OpGobParams & params)1886 void Inter_v1::o1_getOrder(OpGobParams ¶ms) {
1887 params.retVarPtr = (uint32) params.objDesc->order;
1888 }
1889
o1_getActionStartState(OpGobParams & params)1890 void Inter_v1::o1_getActionStartState(OpGobParams ¶ms) {
1891 params.retVarPtr = (uint32) params.objDesc->actionStartState;
1892 }
1893
o1_getCurLookDir(OpGobParams & params)1894 void Inter_v1::o1_getCurLookDir(OpGobParams ¶ms) {
1895 params.retVarPtr = (uint32) params.objDesc->curLookDir;
1896 }
1897
o1_getType(OpGobParams & params)1898 void Inter_v1::o1_getType(OpGobParams ¶ms) {
1899 params.retVarPtr = (uint32) params.objDesc->type;
1900 }
1901
o1_getNoTick(OpGobParams & params)1902 void Inter_v1::o1_getNoTick(OpGobParams ¶ms) {
1903 params.retVarPtr = (uint32) params.objDesc->noTick;
1904 }
1905
o1_getPickable(OpGobParams & params)1906 void Inter_v1::o1_getPickable(OpGobParams ¶ms) {
1907 params.retVarPtr = (uint32) params.objDesc->pickable;
1908 }
1909
o1_getObjMaxFrame(OpGobParams & params)1910 void Inter_v1::o1_getObjMaxFrame(OpGobParams ¶ms) {
1911 params.retVarPtr = (uint32) _vm->_goblin->getObjMaxFrame(params.objDesc);
1912 }
1913
o1_getXPos(OpGobParams & params)1914 void Inter_v1::o1_getXPos(OpGobParams ¶ms) {
1915 params.retVarPtr = (uint32) params.objDesc->xPos;
1916 }
1917
o1_getYPos(OpGobParams & params)1918 void Inter_v1::o1_getYPos(OpGobParams ¶ms) {
1919 params.retVarPtr = (uint32) params.objDesc->yPos;
1920 }
1921
o1_getDoAnim(OpGobParams & params)1922 void Inter_v1::o1_getDoAnim(OpGobParams ¶ms) {
1923 params.retVarPtr = (uint32) params.objDesc->doAnim;
1924 }
1925
o1_getRelaxTime(OpGobParams & params)1926 void Inter_v1::o1_getRelaxTime(OpGobParams ¶ms) {
1927 params.retVarPtr = (uint32) params.objDesc->relaxTime;
1928 }
1929
o1_getMaxTick(OpGobParams & params)1930 void Inter_v1::o1_getMaxTick(OpGobParams ¶ms) {
1931 params.retVarPtr = (uint32) params.objDesc->maxTick;
1932 }
1933
o1_manipulateMap(OpGobParams & params)1934 void Inter_v1::o1_manipulateMap(OpGobParams ¶ms) {
1935 int16 xPos = _vm->_game->_script->readInt16();
1936 int16 yPos = _vm->_game->_script->readInt16();
1937 int16 item = _vm->_game->_script->readInt16();
1938
1939 manipulateMap(xPos, yPos, item);
1940 }
1941
o1_getItem(OpGobParams & params)1942 void Inter_v1::o1_getItem(OpGobParams ¶ms) {
1943 int16 xPos = _vm->_game->_script->readInt16();
1944 int16 yPos = _vm->_game->_script->readInt16();
1945
1946 if ((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0)
1947 params.retVarPtr = (uint32) ((_vm->_map->getItem(xPos, yPos) & 0xFF00) >> 8);
1948 else
1949 params.retVarPtr = (uint32) _vm->_map->getItem(xPos, yPos);
1950 }
1951
o1_manipulateMapIndirect(OpGobParams & params)1952 void Inter_v1::o1_manipulateMapIndirect(OpGobParams ¶ms) {
1953 int16 xPos = _vm->_game->_script->readInt16();
1954 int16 yPos = _vm->_game->_script->readInt16();
1955 int16 item = _vm->_game->_script->readInt16();
1956
1957 xPos = VAR(xPos);
1958 yPos = VAR(yPos);
1959 item = VAR(item);
1960
1961 manipulateMap(xPos, yPos, item);
1962 }
1963
o1_getItemIndirect(OpGobParams & params)1964 void Inter_v1::o1_getItemIndirect(OpGobParams ¶ms) {
1965 int16 xPos = _vm->_game->_script->readInt16();
1966 int16 yPos = _vm->_game->_script->readInt16();
1967
1968 xPos = VAR(xPos);
1969 yPos = VAR(yPos);
1970
1971 if ((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0)
1972 params.retVarPtr = (uint32) ((_vm->_map->getItem(xPos, yPos) & 0xFF00) >> 8);
1973 else
1974 params.retVarPtr = (uint32) _vm->_map->getItem(xPos, yPos);
1975 }
1976
o1_setPassMap(OpGobParams & params)1977 void Inter_v1::o1_setPassMap(OpGobParams ¶ms) {
1978 int16 xPos = _vm->_game->_script->readInt16();
1979 int16 yPos = _vm->_game->_script->readInt16();
1980 int16 val = _vm->_game->_script->readInt16();
1981 _vm->_map->setPass(xPos, yPos, val);
1982 }
1983
o1_setGoblinPosH(OpGobParams & params)1984 void Inter_v1::o1_setGoblinPosH(OpGobParams ¶ms) {
1985 int16 layer;
1986 int16 item = _vm->_game->_script->readInt16();
1987 int16 xPos = _vm->_game->_script->readInt16();
1988 int16 yPos = _vm->_game->_script->readInt16();
1989
1990 _vm->_goblin->_gobPositions[item].x = xPos * 2;
1991 _vm->_goblin->_gobPositions[item].y = yPos * 2;
1992
1993 params.objDesc = _vm->_goblin->_goblins[item];
1994 params.objDesc->nextState = 21;
1995
1996 _vm->_goblin->nextLayer(params.objDesc);
1997
1998 layer = params.objDesc->stateMach[params.objDesc->state][0]->layer;
1999
2000 _vm->_scenery->updateAnim(layer, 0, params.objDesc->animation, 0,
2001 params.objDesc->xPos, params.objDesc->yPos, 0);
2002
2003 params.objDesc->yPos = (_vm->_goblin->_gobPositions[item].y * 6 + 6) -
2004 (_vm->_scenery->_toRedrawBottom - _vm->_scenery->_animTop);
2005 params.objDesc->xPos =
2006 _vm->_goblin->_gobPositions[item].x * 12 -
2007 (_vm->_scenery->_toRedrawLeft - _vm->_scenery->_animLeft);
2008
2009 params.objDesc->curFrame = 0;
2010 params.objDesc->state = 21;
2011 if (_vm->_goblin->_currentGoblin == item) {
2012 _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos;
2013 _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos;
2014
2015 _vm->_goblin->_curGobFrameVarPtr = 0;
2016 _vm->_goblin->_curGobStateVarPtr = 18;
2017 _vm->_goblin->_pressedMapX = _vm->_goblin->_gobPositions[item].x;
2018 _vm->_goblin->_pressedMapY = _vm->_goblin->_gobPositions[item].y;
2019 }
2020 }
2021
o1_getGoblinPosXH(OpGobParams & params)2022 void Inter_v1::o1_getGoblinPosXH(OpGobParams ¶ms) {
2023 int16 item = _vm->_game->_script->readInt16();
2024 params.retVarPtr = (uint32) (_vm->_goblin->_gobPositions[item].x >> 1);
2025 }
2026
o1_getGoblinPosYH(OpGobParams & params)2027 void Inter_v1::o1_getGoblinPosYH(OpGobParams ¶ms) {
2028 int16 item = _vm->_game->_script->readInt16();
2029 params.retVarPtr = (uint32) (_vm->_goblin->_gobPositions[item].y >> 1);
2030 }
2031
o1_setGoblinMultState(OpGobParams & params)2032 void Inter_v1::o1_setGoblinMultState(OpGobParams ¶ms) {
2033 int16 layer;
2034 int16 item = _vm->_game->_script->readInt16();
2035 int16 xPos = _vm->_game->_script->readInt16();
2036 int16 yPos = _vm->_game->_script->readInt16();
2037
2038 params.objDesc = _vm->_goblin->_goblins[item];
2039 if (yPos == 0) {
2040 params.objDesc->multState = xPos;
2041 params.objDesc->nextState = xPos;
2042 _vm->_goblin->nextLayer(params.objDesc);
2043
2044 layer = params.objDesc->stateMach[params.objDesc->state][0]->layer;
2045
2046 Scenery::AnimLayer *animLayer =
2047 _vm->_scenery->getAnimLayer(params.objDesc->animation, layer);
2048 params.objDesc->xPos = animLayer->posX;
2049 params.objDesc->yPos = animLayer->posY;
2050
2051 _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos;
2052 _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos;
2053 _vm->_goblin->_curGobFrameVarPtr = 0;
2054 _vm->_goblin->_curGobStateVarPtr = (uint32) params.objDesc->state;
2055 _vm->_goblin->_curGobNextStateVarPtr = (uint32) params.objDesc->nextState;
2056 _vm->_goblin->_curGobMultStateVarPtr = (uint32) params.objDesc->multState;
2057 _vm->_goblin->_curGobMaxFrameVarPtr =
2058 (uint32) _vm->_goblin->getObjMaxFrame(params.objDesc);
2059 _vm->_goblin->_noPick = 1;
2060 return;
2061 }
2062
2063 params.objDesc->multState = 21;
2064 params.objDesc->nextState = 21;
2065 params.objDesc->state = 21;
2066 _vm->_goblin->nextLayer(params.objDesc);
2067 layer = params.objDesc->stateMach[params.objDesc->state][0]->layer;
2068
2069 _vm->_scenery->updateAnim(layer, 0, params.objDesc->animation, 0,
2070 params.objDesc->xPos, params.objDesc->yPos, 0);
2071
2072 params.objDesc->yPos = (yPos * 6 + 6) -
2073 (_vm->_scenery->_toRedrawBottom - _vm->_scenery->_animTop);
2074 params.objDesc->xPos = xPos * 12 -
2075 (_vm->_scenery->_toRedrawLeft - _vm->_scenery->_animLeft);
2076
2077 _vm->_goblin->_gobPositions[item].x = xPos;
2078 _vm->_goblin->_pressedMapX = xPos;
2079 _vm->_map->_curGoblinX = xPos;
2080
2081 _vm->_goblin->_gobPositions[item].y = yPos;
2082 _vm->_goblin->_pressedMapY = yPos;
2083 _vm->_map->_curGoblinY = yPos;
2084
2085 _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos;
2086 _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos;
2087 _vm->_goblin->_curGobFrameVarPtr = 0;
2088 _vm->_goblin->_curGobStateVarPtr = 21;
2089 _vm->_goblin->_curGobNextStateVarPtr = 21;
2090 _vm->_goblin->_curGobMultStateVarPtr = (uint32) -1;
2091 _vm->_goblin->_noPick = 0;
2092 }
2093
o1_setGoblinUnk14(OpGobParams & params)2094 void Inter_v1::o1_setGoblinUnk14(OpGobParams ¶ms) {
2095 int16 item = _vm->_game->_script->readInt16();
2096 int16 val = _vm->_game->_script->readInt16();
2097 params.objDesc = _vm->_goblin->_objects[item];
2098 params.objDesc->unk14 = val;
2099 }
2100
o1_setItemIdInPocket(OpGobParams & params)2101 void Inter_v1::o1_setItemIdInPocket(OpGobParams ¶ms) {
2102 _vm->_goblin->_itemIdInPocket = _vm->_game->_script->readInt16();
2103 }
2104
o1_setItemIndInPocket(OpGobParams & params)2105 void Inter_v1::o1_setItemIndInPocket(OpGobParams ¶ms) {
2106 _vm->_goblin->_itemIndInPocket = _vm->_game->_script->readInt16();
2107 }
2108
o1_getItemIdInPocket(OpGobParams & params)2109 void Inter_v1::o1_getItemIdInPocket(OpGobParams ¶ms) {
2110 params.retVarPtr = (uint32) _vm->_goblin->_itemIdInPocket;
2111 }
2112
o1_getItemIndInPocket(OpGobParams & params)2113 void Inter_v1::o1_getItemIndInPocket(OpGobParams ¶ms) {
2114 params.retVarPtr = (uint32) _vm->_goblin->_itemIndInPocket;
2115 }
2116
o1_setGoblinPos(OpGobParams & params)2117 void Inter_v1::o1_setGoblinPos(OpGobParams ¶ms) {
2118 int16 layer;
2119 int16 item = _vm->_game->_script->readInt16();
2120 int16 xPos = _vm->_game->_script->readInt16();
2121 int16 yPos = _vm->_game->_script->readInt16();
2122
2123 _vm->_goblin->_gobPositions[item].x = xPos;
2124 _vm->_goblin->_gobPositions[item].y = yPos;
2125
2126 params.objDesc = _vm->_goblin->_goblins[item];
2127 params.objDesc->nextState = 21;
2128 _vm->_goblin->nextLayer(params.objDesc);
2129
2130 layer = params.objDesc->stateMach[params.objDesc->state][0]->layer;
2131
2132 _vm->_scenery->updateAnim(layer, 0, params.objDesc->animation, 0,
2133 params.objDesc->xPos, params.objDesc->yPos, 0);
2134
2135 params.objDesc->yPos = (yPos * 6 + 6) -
2136 (_vm->_scenery->_toRedrawBottom - _vm->_scenery->_animTop);
2137 params.objDesc->xPos = xPos * 12 -
2138 (_vm->_scenery->_toRedrawLeft - _vm->_scenery->_animLeft);
2139
2140 params.objDesc->curFrame = 0;
2141 params.objDesc->state = 21;
2142
2143 if (_vm->_goblin->_currentGoblin == item) {
2144 _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos;
2145 _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos;
2146 _vm->_goblin->_curGobFrameVarPtr = 0;
2147 _vm->_goblin->_curGobStateVarPtr = 18;
2148
2149 _vm->_goblin->_pressedMapX = _vm->_goblin->_gobPositions[item].x;
2150 _vm->_goblin->_pressedMapY = _vm->_goblin->_gobPositions[item].y;
2151 }
2152 }
2153
o1_setGoblinState(OpGobParams & params)2154 void Inter_v1::o1_setGoblinState(OpGobParams ¶ms) {
2155 int16 layer;
2156 int16 item = _vm->_game->_script->readInt16();
2157 int16 state = _vm->_game->_script->readInt16();
2158
2159 params.objDesc = _vm->_goblin->_goblins[item];
2160 params.objDesc->nextState = state;
2161
2162 _vm->_goblin->nextLayer(params.objDesc);
2163 layer = params.objDesc->stateMach[params.objDesc->state][0]->layer;
2164
2165 Scenery::AnimLayer *animLayer =
2166 _vm->_scenery->getAnimLayer(params.objDesc->animation, layer);
2167 params.objDesc->xPos = animLayer->posX;
2168 params.objDesc->yPos = animLayer->posY;
2169
2170 if (item == _vm->_goblin->_currentGoblin) {
2171 _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos;
2172 _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos;
2173 _vm->_goblin->_curGobFrameVarPtr = 0;
2174 _vm->_goblin->_curGobStateVarPtr = (uint32) params.objDesc->state;
2175 _vm->_goblin->_curGobMultStateVarPtr = (uint32) params.objDesc->multState;
2176 }
2177 }
2178
o1_setGoblinStateRedraw(OpGobParams & params)2179 void Inter_v1::o1_setGoblinStateRedraw(OpGobParams ¶ms) {
2180 int16 layer;
2181 int16 item = _vm->_game->_script->readInt16();
2182 int16 state = _vm->_game->_script->readInt16();
2183 params.objDesc = _vm->_goblin->_objects[item];
2184
2185 params.objDesc->nextState = state;
2186
2187 _vm->_goblin->nextLayer(params.objDesc);
2188 layer = params.objDesc->stateMach[params.objDesc->state][0]->layer;
2189
2190 Scenery::AnimLayer *animLayer =
2191 _vm->_scenery->getAnimLayer(params.objDesc->animation, layer);
2192 params.objDesc->xPos = animLayer->posX;
2193 params.objDesc->yPos = animLayer->posY;
2194
2195 params.objDesc->toRedraw = 1;
2196 params.objDesc->type = 0;
2197 if (params.objDesc == _vm->_goblin->_actDestItemDesc) {
2198 _vm->_goblin->_destItemScrXVarPtr = (uint32) params.objDesc->xPos;
2199 _vm->_goblin->_destItemScrYVarPtr = (uint32) params.objDesc->yPos;
2200
2201 _vm->_goblin->_destItemStateVarPtr = (uint32) params.objDesc->state;
2202 _vm->_goblin->_destItemNextStateVarPtr = (uint32) -1;
2203 _vm->_goblin->_destItemMultStateVarPtr = (uint32) -1;
2204 _vm->_goblin->_destItemFrameVarPtr = 0;
2205 }
2206 }
2207
o1_decRelaxTime(OpGobParams & params)2208 void Inter_v1::o1_decRelaxTime(OpGobParams ¶ms) {
2209 params.extraData = _vm->_game->_script->readInt16();
2210 params.objDesc = _vm->_goblin->_objects[params.extraData];
2211
2212 params.objDesc->relaxTime--;
2213 if ((params.objDesc->relaxTime < 0) &&
2214 (_vm->_goblin->getObjMaxFrame(params.objDesc) ==
2215 params.objDesc->curFrame)) {
2216 params.objDesc->relaxTime = _vm->_util->getRandom(100) + 50;
2217 params.objDesc->curFrame = 0;
2218 params.objDesc->toRedraw = 1;
2219 }
2220 }
2221
o1_getGoblinPosX(OpGobParams & params)2222 void Inter_v1::o1_getGoblinPosX(OpGobParams ¶ms) {
2223 int16 item = _vm->_game->_script->readInt16();
2224 params.retVarPtr = (uint32) _vm->_goblin->_gobPositions[item].x;
2225 }
2226
o1_getGoblinPosY(OpGobParams & params)2227 void Inter_v1::o1_getGoblinPosY(OpGobParams ¶ms) {
2228 int16 item = _vm->_game->_script->readInt16();
2229 params.retVarPtr = (uint32) _vm->_goblin->_gobPositions[item].y;
2230 }
2231
o1_clearPathExistence(OpGobParams & params)2232 void Inter_v1::o1_clearPathExistence(OpGobParams ¶ms) {
2233 _vm->_goblin->_pathExistence = 0;
2234 }
2235
o1_setGoblinVisible(OpGobParams & params)2236 void Inter_v1::o1_setGoblinVisible(OpGobParams ¶ms) {
2237 params.extraData = _vm->_game->_script->readInt16();
2238 _vm->_goblin->_goblins[params.extraData]->visible = 1;
2239 }
2240
o1_setGoblinInvisible(OpGobParams & params)2241 void Inter_v1::o1_setGoblinInvisible(OpGobParams ¶ms) {
2242 params.extraData = _vm->_game->_script->readInt16();
2243 _vm->_goblin->_goblins[params.extraData]->visible = 0;
2244 }
2245
o1_getObjectIntersect(OpGobParams & params)2246 void Inter_v1::o1_getObjectIntersect(OpGobParams ¶ms) {
2247 params.extraData = _vm->_game->_script->readInt16();
2248 int16 item = _vm->_game->_script->readInt16();
2249
2250 params.objDesc = _vm->_goblin->_objects[params.extraData];
2251 if (_vm->_goblin->objIntersected(params.objDesc,
2252 _vm->_goblin->_goblins[item]))
2253 params.retVarPtr = 1;
2254 else
2255 params.retVarPtr = 0;
2256 }
2257
o1_getGoblinIntersect(OpGobParams & params)2258 void Inter_v1::o1_getGoblinIntersect(OpGobParams ¶ms) {
2259 params.extraData = _vm->_game->_script->readInt16();
2260 int16 item = _vm->_game->_script->readInt16();
2261
2262 params.objDesc = _vm->_goblin->_goblins[params.extraData];
2263 if (_vm->_goblin->objIntersected(params.objDesc,
2264 _vm->_goblin->_goblins[item]))
2265 params.retVarPtr = 1;
2266 else
2267 params.retVarPtr = 0;
2268 }
2269
o1_setItemPos(OpGobParams & params)2270 void Inter_v1::o1_setItemPos(OpGobParams ¶ms) {
2271 int16 item = _vm->_game->_script->readInt16();
2272 int16 xPos = _vm->_game->_script->readInt16();
2273 int16 yPos = _vm->_game->_script->readInt16();
2274 int16 val = _vm->_game->_script->readInt16();
2275
2276 _vm->_map->_itemPoses[item].x = xPos;
2277 _vm->_map->_itemPoses[item].y = yPos;
2278 _vm->_map->_itemPoses[item].orient = val;
2279 }
2280
o1_loadObjects(OpGobParams & params)2281 void Inter_v1::o1_loadObjects(OpGobParams ¶ms) {
2282 params.extraData = _vm->_game->_script->readInt16();
2283
2284 _vm->_goblin->loadObjects(_variables->getAddressVarString(params.extraData));
2285 }
2286
o1_freeObjects(OpGobParams & params)2287 void Inter_v1::o1_freeObjects(OpGobParams ¶ms) {
2288 _vm->_goblin->freeAllObjects();
2289 }
2290
o1_animateObjects(OpGobParams & params)2291 void Inter_v1::o1_animateObjects(OpGobParams ¶ms) {
2292 _vm->_goblin->animateObjects();
2293 }
2294
o1_drawObjects(OpGobParams & params)2295 void Inter_v1::o1_drawObjects(OpGobParams ¶ms) {
2296 _vm->_goblin->drawObjects();
2297
2298 _vm->_sound->adlibPlayBgMusic(); // Mac version
2299 if (_vm->_sound->cdGetTrackPos() == -1)
2300 _vm->_sound->cdPlayBgMusic(); // PC CD version
2301 }
2302
o1_loadMap(OpGobParams & params)2303 void Inter_v1::o1_loadMap(OpGobParams ¶ms) {
2304 _vm->_map->loadMapsInitGobs();
2305 }
2306
o1_moveGoblin(OpGobParams & params)2307 void Inter_v1::o1_moveGoblin(OpGobParams ¶ms) {
2308 int16 item;
2309 params.extraData = _vm->_game->_script->readInt16();
2310 int16 xPos = _vm->_game->_script->readInt16();
2311
2312 if ((uint16) VAR(xPos) == 0) {
2313 item =
2314 _vm->_goblin->doMove(_vm->_goblin->_goblins[_vm->_goblin->_currentGoblin],
2315 1, (uint16) VAR(params.extraData));
2316 } else {
2317 item =
2318 _vm->_goblin->doMove(_vm->_goblin->_goblins[_vm->_goblin->_currentGoblin],
2319 1, 3);
2320 }
2321
2322 if (item != 0)
2323 _vm->_goblin->switchGoblin(item);
2324 }
2325
o1_switchGoblin(OpGobParams & params)2326 void Inter_v1::o1_switchGoblin(OpGobParams ¶ms) {
2327 _vm->_goblin->switchGoblin(0);
2328 }
2329
o1_loadGoblin(OpGobParams & params)2330 void Inter_v1::o1_loadGoblin(OpGobParams ¶ms) {
2331 _vm->_goblin->loadGobDataFromVars();
2332 }
2333
o1_writeTreatItem(OpGobParams & params)2334 void Inter_v1::o1_writeTreatItem(OpGobParams ¶ms) {
2335 params.extraData = _vm->_game->_script->readInt16();
2336 int16 cmd = _vm->_game->_script->readInt16();
2337 int16 xPos = _vm->_game->_script->readInt16();
2338
2339 if ((uint16) VAR(xPos) == 0) {
2340 WRITE_VAR(cmd, _vm->_goblin->treatItem((uint16) VAR(params.extraData)));
2341 return;
2342 }
2343
2344 WRITE_VAR(cmd, _vm->_goblin->treatItem(3));
2345 }
2346
o1_moveGoblin0(OpGobParams & params)2347 void Inter_v1::o1_moveGoblin0(OpGobParams ¶ms) {
2348 _vm->_goblin->doMove(_vm->_goblin->_goblins[_vm->_goblin->_currentGoblin],
2349 0, 0);
2350 }
2351
o1_setGoblinTarget(OpGobParams & params)2352 void Inter_v1::o1_setGoblinTarget(OpGobParams ¶ms) {
2353 params.extraData = _vm->_game->_script->readInt16();
2354 if (VAR(params.extraData) != 0)
2355 _vm->_goblin->_goesAtTarget = 1;
2356 else
2357 _vm->_goblin->_goesAtTarget = 0;
2358 }
2359
o1_setGoblinObjectsPos(OpGobParams & params)2360 void Inter_v1::o1_setGoblinObjectsPos(OpGobParams ¶ms) {
2361 params.extraData = _vm->_game->_script->readInt16();
2362 params.extraData = VAR(params.extraData);
2363 _vm->_goblin->_objects[10]->xPos = params.extraData;
2364
2365 params.extraData = _vm->_game->_script->readInt16();
2366 params.extraData = VAR(params.extraData);
2367 _vm->_goblin->_objects[10]->yPos = params.extraData;
2368 }
2369
o1_initGoblin(OpGobParams & params)2370 void Inter_v1::o1_initGoblin(OpGobParams ¶ms) {
2371 Goblin::Gob_Object *gobDesc = _vm->_goblin->_goblins[0];
2372 int16 xPos;
2373 int16 yPos;
2374 int16 layer;
2375
2376 if (_vm->_goblin->_currentGoblin != 0) {
2377 _vm->_goblin->_goblins[_vm->_goblin->_currentGoblin]->doAnim = 1;
2378 _vm->_goblin->_goblins[_vm->_goblin->_currentGoblin]->nextState = 21;
2379
2380 _vm->_goblin->nextLayer(_vm->_goblin->_goblins[_vm->_goblin->_currentGoblin]);
2381 _vm->_goblin->_currentGoblin = 0;
2382
2383 gobDesc->doAnim = 0;
2384 gobDesc->type = 0;
2385 gobDesc->toRedraw = 1;
2386
2387 _vm->_goblin->_pressedMapX = _vm->_goblin->_gobPositions[0].x;
2388 _vm->_map->_destX = _vm->_goblin->_gobPositions[0].x;
2389 _vm->_goblin->_gobDestX = _vm->_goblin->_gobPositions[0].x;
2390
2391 _vm->_goblin->_pressedMapY = _vm->_goblin->_gobPositions[0].y;
2392 _vm->_map->_destY = _vm->_goblin->_gobPositions[0].y;
2393 _vm->_goblin->_gobDestY = _vm->_goblin->_gobPositions[0].y;
2394
2395 _vm->_goblin->_curGobVarPtr = 0;
2396 _vm->_goblin->_pathExistence = 0;
2397 _vm->_goblin->_readyToAct = 0;
2398 }
2399
2400 if ((gobDesc->state != 10) && (_vm->_goblin->_itemIndInPocket != -1) &&
2401 (_vm->_goblin->getObjMaxFrame(gobDesc) == gobDesc->curFrame)) {
2402
2403 gobDesc->stateMach = gobDesc->realStateMach;
2404 xPos = _vm->_goblin->_gobPositions[0].x;
2405 yPos = _vm->_goblin->_gobPositions[0].y;
2406
2407 gobDesc->nextState = 10;
2408 layer = _vm->_goblin->nextLayer(gobDesc);
2409
2410 _vm->_scenery->updateAnim(layer, 0, gobDesc->animation, 0,
2411 gobDesc->xPos, gobDesc->yPos, 0);
2412
2413 gobDesc->yPos = (yPos * 6 + 6) -
2414 (_vm->_scenery->_toRedrawBottom - _vm->_scenery->_animTop);
2415 gobDesc->xPos = xPos * 12 -
2416 (_vm->_scenery->_toRedrawLeft - _vm->_scenery->_animLeft);
2417 }
2418
2419 if (gobDesc->state != 10)
2420 return;
2421
2422 if (_vm->_goblin->_itemIndInPocket == -1)
2423 return;
2424
2425 if (gobDesc->curFrame != 10)
2426 return;
2427
2428 params.objDesc = _vm->_goblin->_objects[_vm->_goblin->_itemIndInPocket];
2429 params.objDesc->type = 0;
2430 params.objDesc->toRedraw = 1;
2431 params.objDesc->curFrame = 0;
2432
2433 params.objDesc->order = gobDesc->order;
2434 params.objDesc->animation =
2435 params.objDesc->stateMach[params.objDesc->state][0]->animation;
2436
2437 layer = params.objDesc->stateMach[params.objDesc->state][0]->layer;
2438
2439 _vm->_scenery->updateAnim(layer, 0, params.objDesc->animation, 0,
2440 params.objDesc->xPos, params.objDesc->yPos, 0);
2441
2442 params.objDesc->yPos += (_vm->_goblin->_gobPositions[0].y * 6 + 5) -
2443 _vm->_scenery->_toRedrawBottom;
2444
2445 if (gobDesc->curLookDir == 4) {
2446 params.objDesc->xPos += _vm->_goblin->_gobPositions[0].x * 12 + 14
2447 - (_vm->_scenery->_toRedrawLeft + _vm->_scenery->_toRedrawRight) / 2;
2448 } else {
2449 params.objDesc->xPos += _vm->_goblin->_gobPositions[0].x * 12
2450 - (_vm->_scenery->_toRedrawLeft + _vm->_scenery->_toRedrawRight) / 2;
2451 }
2452
2453 _vm->_goblin->_itemIndInPocket = -1;
2454 _vm->_goblin->_itemIdInPocket = -1;
2455 _vm->_util->beep(50);
2456 }
2457
loadSound(int16 slot)2458 int16 Inter_v1::loadSound(int16 slot) {
2459 if (slot == -1)
2460 slot = _vm->_game->_script->readValExpr();
2461
2462 uint16 id = _vm->_game->_script->readUint16();
2463 if (id == 0xFFFF) {
2464 _vm->_game->_script->skip(9);
2465 return 0;
2466 }
2467
2468 Resource *resource = _vm->_game->_resources->getResource(id);
2469 if (!resource)
2470 return 0;
2471
2472 SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot);
2473 if (!sample)
2474 return 0;
2475
2476 sample->load(SOUND_SND, resource);
2477 return 0;
2478 }
2479
animPalette()2480 void Inter_v1::animPalette() {
2481 int16 i;
2482 Video::Color col;
2483
2484 if (_animPalDir[0] == 0)
2485 return;
2486
2487 _vm->_video->waitRetrace();
2488
2489 if (_animPalDir[0] == -1) {
2490 col = _vm->_draw->_vgaPalette[_animPalLowIndex[0]];
2491
2492 for (i = _animPalLowIndex[0]; i < _animPalHighIndex[0]; i++)
2493 _vm->_draw->_vgaPalette[i] = _vm->_draw->_vgaPalette[i + 1];
2494
2495 _vm->_draw->_vgaPalette[_animPalHighIndex[0]] = col;
2496 } else {
2497 col = _vm->_draw->_vgaPalette[_animPalHighIndex[0]];
2498 for (i = _animPalHighIndex[0]; i > _animPalLowIndex[0]; i--)
2499 _vm->_draw->_vgaPalette[i] = _vm->_draw->_vgaPalette[i - 1];
2500
2501 _vm->_draw->_vgaPalette[_animPalLowIndex[0]] = col;
2502 }
2503
2504 _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette;
2505 _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
2506 }
2507
manipulateMap(int16 xPos,int16 yPos,int16 item)2508 void Inter_v1::manipulateMap(int16 xPos, int16 yPos, int16 item) {
2509 for (int y = 0; y < _vm->_map->getMapHeight(); y++) {
2510 for (int x = 0; x < _vm->_map->getMapWidth(); x++) {
2511 if ((_vm->_map->getItem(x, y) & 0xFF) == item)
2512 _vm->_map->setItem(x, y, _vm->_map->getItem(x, y) & 0xFF00);
2513 else if (((_vm->_map->getItem(x, y) & 0xFF00) >> 8) == item)
2514 _vm->_map->setItem(x, y, _vm->_map->getItem(x, y) & 0xFF);
2515 }
2516 }
2517
2518 if (xPos < _vm->_map->getMapWidth() - 1) {
2519 if (yPos > 0) {
2520 if (((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0) ||
2521 ((_vm->_map->getItem(xPos, yPos - 1) & 0xFF00) != 0) ||
2522 ((_vm->_map->getItem(xPos + 1, yPos) & 0xFF00) != 0) ||
2523 ((_vm->_map->getItem(xPos + 1, yPos - 1) & 0xFF00) != 0)) {
2524
2525 _vm->_map->setItem(xPos, yPos,
2526 (_vm->_map->getItem(xPos, yPos) & 0xFF00) + item);
2527
2528 _vm->_map->setItem(xPos, yPos - 1,
2529 (_vm->_map->getItem(xPos, yPos - 1) & 0xFF00) + item);
2530
2531 _vm->_map->setItem(xPos + 1, yPos,
2532 (_vm->_map->getItem(xPos + 1, yPos) & 0xFF00) + item);
2533
2534 _vm->_map->setItem(xPos + 1, yPos - 1,
2535 (_vm->_map->getItem(xPos + 1, yPos - 1) & 0xFF00) + item);
2536
2537 } else {
2538 _vm->_map->setItem(xPos, yPos,
2539 (_vm->_map->getItem(xPos, yPos) & 0xFF) + (item << 8));
2540
2541 _vm->_map->setItem(xPos, yPos - 1,
2542 (_vm->_map->getItem(xPos, yPos - 1) & 0xFF) + (item << 8));
2543
2544 _vm->_map->setItem(xPos + 1, yPos,
2545 (_vm->_map->getItem(xPos + 1, yPos) & 0xFF) + (item << 8));
2546
2547 _vm->_map->setItem(xPos + 1, yPos - 1,
2548 (_vm->_map->getItem(xPos + 1, yPos - 1) & 0xFF) + (item << 8));
2549 }
2550 } else {
2551 if (((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0) ||
2552 ((_vm->_map->getItem(xPos + 1, yPos) & 0xFF00) != 0)) {
2553
2554 _vm->_map->setItem(xPos, yPos,
2555 (_vm->_map->getItem(xPos, yPos) & 0xFF00) + item);
2556
2557 _vm->_map->setItem(xPos + 1, yPos,
2558 (_vm->_map->getItem(xPos + 1, yPos) & 0xFF00) + item);
2559
2560 } else {
2561 _vm->_map->setItem(xPos, yPos,
2562 (_vm->_map->getItem(xPos, yPos) & 0xFF) + (item << 8));
2563
2564 _vm->_map->setItem(xPos + 1, yPos,
2565 (_vm->_map->getItem(xPos + 1, yPos) & 0xFF) + (item << 8));
2566 }
2567 }
2568 } else {
2569 if (yPos > 0) {
2570 if (((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0) ||
2571 ((_vm->_map->getItem(xPos, yPos - 1) & 0xFF00) != 0)) {
2572
2573 _vm->_map->setItem(xPos, yPos,
2574 (_vm->_map->getItem(xPos, yPos) & 0xFF00) + item);
2575
2576 _vm->_map->setItem(xPos, yPos - 1,
2577 (_vm->_map->getItem(xPos, yPos - 1) & 0xFF00) + item);
2578
2579 } else {
2580 _vm->_map->setItem(xPos, yPos,
2581 (_vm->_map->getItem(xPos, yPos) & 0xFF) + (item << 8));
2582
2583 _vm->_map->setItem(xPos, yPos - 1,
2584 (_vm->_map->getItem(xPos, yPos - 1) & 0xFF) + (item << 8));
2585 }
2586 } else {
2587 if ((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0) {
2588 _vm->_map->setItem(xPos, yPos,
2589 (_vm->_map->getItem(xPos, yPos) & 0xFF00) + item);
2590 } else {
2591 _vm->_map->setItem(xPos, yPos,
2592 (_vm->_map->getItem(xPos, yPos) & 0xFF) + (item << 8));
2593 }
2594 }
2595 }
2596
2597 if ((item < 0) || (item >= 20))
2598 return;
2599
2600 if ((xPos > 1) && (_vm->_map->getPass(xPos - 2, yPos) == 1)) {
2601 _vm->_map->_itemPoses[item].x = xPos - 2;
2602 _vm->_map->_itemPoses[item].y = yPos;
2603 _vm->_map->_itemPoses[item].orient = 4;
2604 return;
2605 }
2606
2607 if ((xPos < _vm->_map->getMapWidth() - 2) &&
2608 (_vm->_map->getPass(xPos + 2, yPos) == 1)) {
2609 _vm->_map->_itemPoses[item].x = xPos + 2;
2610 _vm->_map->_itemPoses[item].y = yPos;
2611 _vm->_map->_itemPoses[item].orient = 0;
2612 return;
2613 }
2614
2615 if ((xPos < _vm->_map->getMapWidth() - 1) &&
2616 (_vm->_map->getPass(xPos + 1, yPos) == 1)) {
2617 _vm->_map->_itemPoses[item].x = xPos + 1;
2618 _vm->_map->_itemPoses[item].y = yPos;
2619 _vm->_map->_itemPoses[item].orient = 0;
2620 return;
2621 }
2622
2623 if ((xPos > 0) && (_vm->_map->getPass(xPos - 1, yPos) == 1)) {
2624 _vm->_map->_itemPoses[item].x = xPos - 1;
2625 _vm->_map->_itemPoses[item].y = yPos;
2626 _vm->_map->_itemPoses[item].orient = 4;
2627 return;
2628 }
2629 }
2630
2631 } // End of namespace Gob
2632