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 &params) {
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 &params) {
718 	_vm->_draw->printTotText(_vm->_game->_script->readInt16());
719 }
720 
o1_loadCursor(OpFuncParams & params)721 void Inter_v1::o1_loadCursor(OpFuncParams &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
1288 	params.cmdCount = _vm->_game->_script->readByte();
1289 	params.counter = 0;
1290 }
1291 
o1_return(OpFuncParams & params)1292 void Inter_v1::o1_return(OpFuncParams &params) {
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 &params) {
1301 	renewTimeInVars();
1302 }
1303 
o1_speakerOn(OpFuncParams & params)1304 void Inter_v1::o1_speakerOn(OpFuncParams &params) {
1305 	_vm->_sound->speakerOn(_vm->_game->_script->readValExpr(), -1);
1306 }
1307 
o1_speakerOff(OpFuncParams & params)1308 void Inter_v1::o1_speakerOff(OpFuncParams &params) {
1309 	_vm->_sound->speakerOff();
1310 }
1311 
o1_putPixel(OpFuncParams & params)1312 void Inter_v1::o1_putPixel(OpFuncParams &params) {
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 &params) {
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 &params) {
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 &params) {
1394 	_vm->_draw->freeSprite(_vm->_game->_script->readInt16());
1395 }
1396 
o1_returnTo(OpFuncParams & params)1397 void Inter_v1::o1_returnTo(OpFuncParams &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
1565 	loadSound(-1);
1566 }
1567 
o1_freeSoundSlot(OpFuncParams & params)1568 void Inter_v1::o1_freeSoundSlot(OpFuncParams &params) {
1569 	_vm->_game->freeSoundSlot(-1);
1570 }
1571 
o1_waitEndPlay(OpFuncParams & params)1572 void Inter_v1::o1_waitEndPlay(OpFuncParams &params) {
1573 	_vm->_sound->blasterWaitEndPlay();
1574 }
1575 
o1_playComposition(OpFuncParams & params)1576 void Inter_v1::o1_playComposition(OpFuncParams &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
1677 	_vm->_util->setFrameRate(_vm->_game->_script->readValExpr());
1678 }
1679 
o1_animatePalette(OpFuncParams & params)1680 void Inter_v1::o1_animatePalette(OpFuncParams &params) {
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 &params) {
1689 	_vm->_draw->animateCursor(1);
1690 }
1691 
o1_blitCursor(OpFuncParams & params)1692 void Inter_v1::o1_blitCursor(OpFuncParams &params) {
1693 	_vm->_draw->blitCursor();
1694 }
1695 
o1_loadFont(OpFuncParams & params)1696 void Inter_v1::o1_loadFont(OpFuncParams &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
1871 	params.retVarPtr = (uint32) params.objDesc->state;
1872 }
1873 
o1_getCurFrame(OpGobParams & params)1874 void Inter_v1::o1_getCurFrame(OpGobParams &params) {
1875 	params.retVarPtr = (uint32) params.objDesc->curFrame;
1876 }
1877 
o1_getNextState(OpGobParams & params)1878 void Inter_v1::o1_getNextState(OpGobParams &params) {
1879 	params.retVarPtr = (uint32) params.objDesc->nextState;
1880 }
1881 
o1_getMultState(OpGobParams & params)1882 void Inter_v1::o1_getMultState(OpGobParams &params) {
1883 	params.retVarPtr = (uint32) params.objDesc->multState;
1884 }
1885 
o1_getOrder(OpGobParams & params)1886 void Inter_v1::o1_getOrder(OpGobParams &params) {
1887 	params.retVarPtr = (uint32) params.objDesc->order;
1888 }
1889 
o1_getActionStartState(OpGobParams & params)1890 void Inter_v1::o1_getActionStartState(OpGobParams &params) {
1891 	params.retVarPtr = (uint32) params.objDesc->actionStartState;
1892 }
1893 
o1_getCurLookDir(OpGobParams & params)1894 void Inter_v1::o1_getCurLookDir(OpGobParams &params) {
1895 	params.retVarPtr = (uint32) params.objDesc->curLookDir;
1896 }
1897 
o1_getType(OpGobParams & params)1898 void Inter_v1::o1_getType(OpGobParams &params) {
1899 	params.retVarPtr = (uint32) params.objDesc->type;
1900 }
1901 
o1_getNoTick(OpGobParams & params)1902 void Inter_v1::o1_getNoTick(OpGobParams &params) {
1903 	params.retVarPtr = (uint32) params.objDesc->noTick;
1904 }
1905 
o1_getPickable(OpGobParams & params)1906 void Inter_v1::o1_getPickable(OpGobParams &params) {
1907 	params.retVarPtr = (uint32) params.objDesc->pickable;
1908 }
1909 
o1_getObjMaxFrame(OpGobParams & params)1910 void Inter_v1::o1_getObjMaxFrame(OpGobParams &params) {
1911 	params.retVarPtr = (uint32) _vm->_goblin->getObjMaxFrame(params.objDesc);
1912 }
1913 
o1_getXPos(OpGobParams & params)1914 void Inter_v1::o1_getXPos(OpGobParams &params) {
1915 	params.retVarPtr = (uint32) params.objDesc->xPos;
1916 }
1917 
o1_getYPos(OpGobParams & params)1918 void Inter_v1::o1_getYPos(OpGobParams &params) {
1919 	params.retVarPtr = (uint32) params.objDesc->yPos;
1920 }
1921 
o1_getDoAnim(OpGobParams & params)1922 void Inter_v1::o1_getDoAnim(OpGobParams &params) {
1923 	params.retVarPtr = (uint32) params.objDesc->doAnim;
1924 }
1925 
o1_getRelaxTime(OpGobParams & params)1926 void Inter_v1::o1_getRelaxTime(OpGobParams &params) {
1927 	params.retVarPtr = (uint32) params.objDesc->relaxTime;
1928 }
1929 
o1_getMaxTick(OpGobParams & params)1930 void Inter_v1::o1_getMaxTick(OpGobParams &params) {
1931 	params.retVarPtr = (uint32) params.objDesc->maxTick;
1932 }
1933 
o1_manipulateMap(OpGobParams & params)1934 void Inter_v1::o1_manipulateMap(OpGobParams &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
2102 	_vm->_goblin->_itemIdInPocket = _vm->_game->_script->readInt16();
2103 }
2104 
o1_setItemIndInPocket(OpGobParams & params)2105 void Inter_v1::o1_setItemIndInPocket(OpGobParams &params) {
2106 	_vm->_goblin->_itemIndInPocket = _vm->_game->_script->readInt16();
2107 }
2108 
o1_getItemIdInPocket(OpGobParams & params)2109 void Inter_v1::o1_getItemIdInPocket(OpGobParams &params) {
2110 	params.retVarPtr = (uint32) _vm->_goblin->_itemIdInPocket;
2111 }
2112 
o1_getItemIndInPocket(OpGobParams & params)2113 void Inter_v1::o1_getItemIndInPocket(OpGobParams &params) {
2114 	params.retVarPtr = (uint32) _vm->_goblin->_itemIndInPocket;
2115 }
2116 
o1_setGoblinPos(OpGobParams & params)2117 void Inter_v1::o1_setGoblinPos(OpGobParams &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
2233 	_vm->_goblin->_pathExistence = 0;
2234 }
2235 
o1_setGoblinVisible(OpGobParams & params)2236 void Inter_v1::o1_setGoblinVisible(OpGobParams &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
2288 	_vm->_goblin->freeAllObjects();
2289 }
2290 
o1_animateObjects(OpGobParams & params)2291 void Inter_v1::o1_animateObjects(OpGobParams &params) {
2292 	_vm->_goblin->animateObjects();
2293 }
2294 
o1_drawObjects(OpGobParams & params)2295 void Inter_v1::o1_drawObjects(OpGobParams &params) {
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 &params) {
2304 	_vm->_map->loadMapsInitGobs();
2305 }
2306 
o1_moveGoblin(OpGobParams & params)2307 void Inter_v1::o1_moveGoblin(OpGobParams &params) {
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 &params) {
2327 	_vm->_goblin->switchGoblin(0);
2328 }
2329 
o1_loadGoblin(OpGobParams & params)2330 void Inter_v1::o1_loadGoblin(OpGobParams &params) {
2331 	_vm->_goblin->loadGobDataFromVars();
2332 }
2333 
o1_writeTreatItem(OpGobParams & params)2334 void Inter_v1::o1_writeTreatItem(OpGobParams &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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