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 
24 
25 #include "agos/agos.h"
26 #include "agos/intern.h"
27 
28 namespace AGOS {
29 
30 #define OPCODE(x)	_OPCODE(AGOSEngine_Elvira2, x)
31 
setupOpcodes()32 void AGOSEngine_Elvira2::setupOpcodes() {
33 	static const OpcodeEntryElvira2 opcodes[] = {
34 		/* 00 */
35 		OPCODE(o_invalid),
36 		OPCODE(o_at),
37 		OPCODE(o_notAt),
38 		OPCODE(o_invalid),
39 		/* 04 */
40 		OPCODE(o_invalid),
41 		OPCODE(o_carried),
42 		OPCODE(o_notCarried),
43 		OPCODE(o_isAt),
44 		/* 08 */
45 		OPCODE(oe1_isNotAt),
46 		OPCODE(oe1_sibling),
47 		OPCODE(oe1_notSibling),
48 		OPCODE(o_zero),
49 		/* 12 */
50 		OPCODE(o_notZero),
51 		OPCODE(o_eq),
52 		OPCODE(o_notEq),
53 		OPCODE(o_gt),
54 		/* 16 */
55 		OPCODE(o_lt),
56 		OPCODE(o_eqf),
57 		OPCODE(o_notEqf),
58 		OPCODE(o_ltf),
59 		/* 20 */
60 		OPCODE(o_gtf),
61 		OPCODE(oe1_isIn),
62 		OPCODE(oe1_isNotIn),
63 		OPCODE(o_chance),
64 		/* 24 */
65 		OPCODE(oe1_isPlayer),
66 		OPCODE(o_isRoom),
67 		OPCODE(o_isObject),
68 		OPCODE(o_state),
69 		/* 28 */
70 		OPCODE(o_oflag),
71 		OPCODE(oe1_canPut),
72 		OPCODE(o_invalid),
73 		OPCODE(o_destroy),
74 		/* 32 */
75 		OPCODE(o_invalid),
76 		OPCODE(o_place),
77 		OPCODE(oe1_copyof),
78 		OPCODE(oe1_copyfo),
79 		/* 36 */
80 		OPCODE(o_copyff),
81 		OPCODE(oe1_whatO),
82 		OPCODE(o_invalid),
83 		OPCODE(oe1_weigh),
84 		/* 40 */
85 		OPCODE(o_invalid),
86 		OPCODE(o_clear),
87 		OPCODE(o_let),
88 		OPCODE(o_add),
89 		/* 44 */
90 		OPCODE(o_sub),
91 		OPCODE(o_addf),
92 		OPCODE(o_subf),
93 		OPCODE(o_mul),
94 		/* 48 */
95 		OPCODE(o_div),
96 		OPCODE(o_mulf),
97 		OPCODE(o_divf),
98 		OPCODE(o_mod),
99 		/* 52 */
100 		OPCODE(o_modf),
101 		OPCODE(o_random),
102 		OPCODE(oe2_moveDirn),
103 		OPCODE(o_goto),
104 		/* 56 */
105 		OPCODE(o_oset),
106 		OPCODE(o_oclear),
107 		OPCODE(o_putBy),
108 		OPCODE(o_inc),
109 		/* 60 */
110 		OPCODE(o_dec),
111 		OPCODE(o_setState),
112 		OPCODE(o_print),
113 		OPCODE(o_message),
114 		/* 64 */
115 		OPCODE(o_msg),
116 		OPCODE(o_invalid),
117 		OPCODE(o_invalid),
118 		OPCODE(o_invalid),
119 		/* 68 */
120 		OPCODE(o_end),
121 		OPCODE(o_done),
122 		OPCODE(o_invalid),
123 		OPCODE(o_process),
124 		/* 72 */
125 		OPCODE(oe2_doClass),
126 		OPCODE(oe2_pObj),
127 		OPCODE(oe1_pName),
128 		OPCODE(oe1_pcName),
129 		/* 76 */
130 		OPCODE(o_when),
131 		OPCODE(o_if1),
132 		OPCODE(o_if2),
133 		OPCODE(oe2_isCalled),
134 		/* 80 */
135 		OPCODE(o_is),
136 		OPCODE(o_invalid),
137 		OPCODE(o_debug),
138 		OPCODE(oe1_rescan),
139 		/* 84 */
140 		OPCODE(o_invalid),
141 		OPCODE(o_invalid),
142 		OPCODE(o_invalid),
143 		OPCODE(o_comment),
144 		/* 88 */
145 		OPCODE(o_invalid),
146 		OPCODE(oe1_loadGame),
147 		OPCODE(o_getParent),
148 		OPCODE(o_getNext),
149 		/* 92 */
150 		OPCODE(o_getChildren),
151 		OPCODE(o_invalid),
152 		OPCODE(oe1_findMaster),
153 		OPCODE(oe1_nextMaster),
154 		/* 96 */
155 		OPCODE(o_picture),
156 		OPCODE(o_loadZone),
157 		OPCODE(oe1_animate),
158 		OPCODE(oe1_stopAnimate),
159 		/* 100 */
160 		OPCODE(o_killAnimate),
161 		OPCODE(o_defWindow),
162 		OPCODE(o_window),
163 		OPCODE(o_cls),
164 		/* 104 */
165 		OPCODE(o_closeWindow),
166 		OPCODE(oe2_menu),
167 		OPCODE(o_invalid),
168 		OPCODE(o_addBox),
169 		/* 108 */
170 		OPCODE(o_delBox),
171 		OPCODE(o_enableBox),
172 		OPCODE(o_disableBox),
173 		OPCODE(o_moveBox),
174 		/* 112 */
175 		OPCODE(o_invalid),
176 		OPCODE(oe2_drawItem),
177 		OPCODE(o_doIcons),
178 		OPCODE(o_isClass),
179 		/* 116 */
180 		OPCODE(o_setClass),
181 		OPCODE(o_unsetClass),
182 		OPCODE(o_invalid),
183 		OPCODE(o_waitSync),
184 		/* 120*/
185 		OPCODE(o_sync),
186 		OPCODE(o_defObj),
187 		OPCODE(o_invalid),
188 		OPCODE(oe1_setTime),
189 		/* 124 */
190 		OPCODE(oe1_ifTime),
191 		OPCODE(o_here),
192 		OPCODE(o_doClassIcons),
193 		OPCODE(o_playTune),
194 		/* 128 */
195 		OPCODE(o_invalid),
196 		OPCODE(o_invalid),
197 		OPCODE(o_setAdjNoun),
198 		OPCODE(o_invalid),
199 		/* 132 */
200 		OPCODE(o_saveUserGame),
201 		OPCODE(o_loadUserGame),
202 		OPCODE(o_invalid),
203 		OPCODE(oe2_pauseGame),
204 		/* 136 */
205 		OPCODE(o_copysf),
206 		OPCODE(o_restoreIcons),
207 		OPCODE(o_freezeZones),
208 		OPCODE(o_placeNoIcons),
209 		/* 140 */
210 		OPCODE(o_clearTimers),
211 		OPCODE(o_setDollar),
212 		OPCODE(o_isBox),
213 		OPCODE(oe2_doTable),
214 		/* 144 */
215 		OPCODE(oe2_setDoorOpen),
216 		OPCODE(oe2_setDoorClosed),
217 		OPCODE(oe2_setDoorLocked),
218 		OPCODE(oe2_setDoorClosed),
219 		/* 148 */
220 		OPCODE(oe2_ifDoorOpen),
221 		OPCODE(oe2_ifDoorClosed),
222 		OPCODE(oe2_ifDoorLocked),
223 		OPCODE(oe2_storeItem),
224 		/* 152 */
225 		OPCODE(oe2_getItem),
226 		OPCODE(oe2_bSet),
227 		OPCODE(oe2_bClear),
228 		OPCODE(oe2_bZero),
229 		/* 156 */
230 		OPCODE(oe2_bNotZero),
231 		OPCODE(oe2_getOValue),
232 		OPCODE(oe2_setOValue),
233 		OPCODE(o_invalid),
234 		/* 160 */
235 		OPCODE(oe2_ink),
236 		OPCODE(oe2_printStats),
237 		OPCODE(o_invalid),
238 		OPCODE(o_invalid),
239 		/* 164 */
240 		OPCODE(o_invalid),
241 		OPCODE(oe2_setSuperRoom),
242 		OPCODE(oe2_getSuperRoom),
243 		OPCODE(oe2_setExitOpen),
244 		/* 168 */
245 		OPCODE(oe2_setExitClosed),
246 		OPCODE(oe2_setExitLocked),
247 		OPCODE(oe2_setExitClosed),
248 		OPCODE(oe2_ifExitOpen),
249 		/* 172 */
250 		OPCODE(oe2_ifExitClosed),
251 		OPCODE(oe2_ifExitLocked),
252 		OPCODE(oe2_playEffect),
253 		OPCODE(oe2_getDollar2),
254 		/* 176 */
255 		OPCODE(oe2_setSRExit),
256 		OPCODE(oe2_printPlayerDamage),
257 		OPCODE(oe2_printMonsterDamage),
258 		OPCODE(oe2_isAdjNoun),
259 		/* 180 */
260 		OPCODE(oe2_b2Set),
261 		OPCODE(oe2_b2Clear),
262 		OPCODE(oe2_b2Zero),
263 		OPCODE(oe2_b2NotZero)
264 	};
265 
266 	_opcodesElvira2 = opcodes;
267 	_numOpcodes = 184;
268 }
269 
executeOpcode(int opcode)270 void AGOSEngine_Elvira2::executeOpcode(int opcode) {
271 	OpcodeProcElvira2 op = _opcodesElvira2[opcode].proc;
272 	(this->*op) ();
273 }
274 
275 // -----------------------------------------------------------------------
276 // Elvira 2 Opcodes
277 // -----------------------------------------------------------------------
278 
oe2_moveDirn()279 void AGOSEngine_Elvira2::oe2_moveDirn() {
280 	// 54: move direction
281 	int16 d = getVarOrByte();
282 	moveDirn(me(), d);
283 }
284 
oe2_doClass()285 void AGOSEngine_Elvira2::oe2_doClass() {
286 	// 72: do class
287 	Item *i = getNextItemPtr();
288 	byte cm = getByte();
289 	int16 num = getVarOrWord();
290 
291 	_classMask = (cm != 0xFF) ? 1 << cm : 0;
292 	_classLine = (SubroutineLine *)((byte *)_currentTable + _currentLine->next);
293 	if (num == 1) {
294 		_subjectItem = findInByClass(i, (1 << cm));
295 		if (_subjectItem)
296 			_classMode1 = 1;
297 		else
298 			_classMode1 = 0;
299 	} else {
300 		_objectItem = findInByClass(i, (1 << cm));
301 		if (_objectItem)
302 			_classMode2 = 1;
303 		else
304 			_classMode2 = 0;
305 	}
306 }
307 
oe2_pObj()308 void AGOSEngine_Elvira2::oe2_pObj() {
309 	// 73: print object
310 	SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
311 
312 	if (subObject != NULL && subObject->objectFlags & kOFText)
313 		showMessageFormat("%s", (const char *)getStringPtrByID(subObject->objectFlagValue[0]));
314 }
315 
oe2_isCalled()316 void AGOSEngine_Elvira2::oe2_isCalled() {
317 	// 79: childstruct fr2 is
318 	Item *i = getNextItemPtr();
319 	uint stringId = getNextStringID();
320 	setScriptCondition(i->itemName == stringId);
321 }
322 
oe2_menu()323 void AGOSEngine_Elvira2::oe2_menu() {
324 	// 105: set agos menu
325 	_agosMenu = getVarOrByte();
326 }
327 
oe2_drawItem()328 void AGOSEngine_Elvira2::oe2_drawItem() {
329 	// 113: draw item
330 	Item *i = getNextItemPtr();
331 	int a = getVarOrByte();
332 	int x = getVarOrWord();
333 	int y = getVarOrWord();
334 	mouseOff();
335 	drawIcon(_windowArray[a % 8], itemGetIconNumber(i), x, y);
336 	mouseOn();
337 }
338 
oe2_doTable()339 void AGOSEngine_Elvira2::oe2_doTable() {
340 	// 143: start item sub
341 	Item *i = getNextItemPtr();
342 
343 	SubRoom *r = (SubRoom *)findChildOfType(i, kRoomType);
344 	if (r != NULL) {
345 		Subroutine *sub = getSubroutineByID(r->subroutine_id);
346 		if (sub) {
347 			startSubroutine(sub);
348 			return;
349 		}
350 	}
351 
352 	if (getGameType() == GType_ELVIRA2) {
353 		SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
354 		if (sr != NULL) {
355 			Subroutine *sub = getSubroutineByID(sr->subroutine_id);
356 			if (sub) {
357 				startSubroutine(sub);
358 				return;
359 			}
360 		}
361 	}
362 }
363 
oe2_pauseGame()364 void AGOSEngine_Elvira2::oe2_pauseGame() {
365 	// 135: pause game
366 	HitArea *ha;
367 
368 	uint32 pauseTime = getTime();
369 	haltAnimation();
370 
371 	while (!shouldQuit()) {
372 		_lastHitArea = NULL;
373 		_lastHitArea3 = NULL;
374 
375 		while (!shouldQuit()) {
376 			if (processSpecialKeys() != 0 || _lastHitArea3 != 0)
377 				break;
378 			delay(1);
379 		}
380 
381 		ha = _lastHitArea;
382 
383 		if (ha == NULL) {
384 		} else if (ha->id == 201) {
385 			break;
386 		}
387 	}
388 
389 	restartAnimation();
390 	_gameStoppedClock = getTime() - pauseTime + _gameStoppedClock;
391 }
392 
oe2_setDoorOpen()393 void AGOSEngine_Elvira2::oe2_setDoorOpen() {
394 	// 144: set door open
395 	Item *i = getNextItemPtr();
396 	setDoorState(i, getVarOrByte(), 1);
397 }
398 
oe2_setDoorClosed()399 void AGOSEngine_Elvira2::oe2_setDoorClosed() {
400 	// 145: set door closed
401 	Item *i = getNextItemPtr();
402 	setDoorState(i, getVarOrByte(), 2);
403 }
404 
oe2_setDoorLocked()405 void AGOSEngine_Elvira2::oe2_setDoorLocked() {
406 	// 146: set door locked
407 	Item *i = getNextItemPtr();
408 	setDoorState(i, getVarOrByte(), 3);
409 }
410 
oe2_ifDoorOpen()411 void AGOSEngine_Elvira2::oe2_ifDoorOpen() {
412 	// 148: if door open
413 	Item *i = getNextItemPtr();
414 	uint16 d = getVarOrByte();
415 
416 	if (getGameType() == GType_WW) {
417 		// WORKAROUND bug #2686883: A NULL item can occur when
418 		// walking through Jack the Ripper scene
419 		if (i == NULL) {
420 			setScriptCondition(false);
421 			return;
422 		}
423 	}
424 
425 	setScriptCondition(getDoorState(i, d) == 1);
426 }
427 
oe2_ifDoorClosed()428 void AGOSEngine_Elvira2::oe2_ifDoorClosed() {
429 	// 149: if door closed
430 	Item *i = getNextItemPtr();
431 	uint16 d = getVarOrByte();
432 	setScriptCondition(getDoorState(i, d) == 2);
433 }
434 
oe2_ifDoorLocked()435 void AGOSEngine_Elvira2::oe2_ifDoorLocked() {
436 	// 150: if door locked
437 	Item *i=getNextItemPtr();
438 	uint16 d = getVarOrByte();
439 	setScriptCondition(getDoorState(i, d) == 3);
440 }
441 
oe2_storeItem()442 void AGOSEngine_Elvira2::oe2_storeItem() {
443 	// 151: set array6 to item
444 	uint var = getVarOrByte();
445 	Item *item = getNextItemPtr();
446 	_itemStore[var] = item;
447 }
448 
oe2_getItem()449 void AGOSEngine_Elvira2::oe2_getItem() {
450 	// 152: set m1 to m3 to array 6
451 	Item *item = _itemStore[getVarOrByte()];
452 	uint var = getVarOrByte();
453 	if (var == 1) {
454 		_subjectItem = item;
455 	} else {
456 		_objectItem = item;
457 	}
458 }
459 
oe2_bSet()460 void AGOSEngine_Elvira2::oe2_bSet() {
461 	// 153: set bit
462 	setBitFlag(getVarWrapper(), true);
463 }
464 
oe2_bClear()465 void AGOSEngine_Elvira2::oe2_bClear() {
466 	// 154: clear bit
467 	setBitFlag(getVarWrapper(), false);
468 }
469 
oe2_bZero()470 void AGOSEngine_Elvira2::oe2_bZero() {
471 	// 155: is bit clear
472 	setScriptCondition(!getBitFlag(getVarWrapper()));
473 }
474 
oe2_bNotZero()475 void AGOSEngine_Elvira2::oe2_bNotZero() {
476 	// 156: is bit set
477 	uint bit = getVarWrapper();
478 
479 	// WORKAROUND: Enable copy protection again, in cracked version.
480 	if (getGameType() == GType_SIMON1 && _currentTable && _currentTable->id == 2962 && bit == 63) {
481 		bit = 50;
482 	}
483 
484 	setScriptCondition(getBitFlag(bit));
485 }
486 
oe2_getOValue()487 void AGOSEngine_Elvira2::oe2_getOValue() {
488 	// 157: get item int prop
489 	Item *item = getNextItemPtr();
490 	SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
491 	uint prop = getVarOrByte();
492 
493 	if (subObject != NULL && subObject->objectFlags & (1 << prop) && prop < 16) {
494 		uint offs = getOffsetOfChild2Param(subObject, 1 << prop);
495 		writeNextVarContents(subObject->objectFlagValue[offs]);
496 	} else {
497 		writeNextVarContents(0);
498 	}
499 }
500 
oe2_setOValue()501 void AGOSEngine_Elvira2::oe2_setOValue() {
502 	// 158: set item prop
503 	Item *item = getNextItemPtr();
504 	SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
505 	uint prop = getVarOrByte();
506 	int value = getVarOrWord();
507 
508 	if (subObject != NULL && subObject->objectFlags & (1 << prop) && prop < 16) {
509 		uint offs = getOffsetOfChild2Param(subObject, 1 << prop);
510 		subObject->objectFlagValue[offs] = value;
511 	}
512 }
513 
oe2_ink()514 void AGOSEngine_Elvira2::oe2_ink() {
515 	// 160
516 	setTextColor(getVarOrByte());
517 }
518 
oe2_printStats()519 void AGOSEngine_Elvira2::oe2_printStats() {
520 	// 161: print stats
521 	printStats();
522 }
523 
oe2_setSuperRoom()524 void AGOSEngine_Elvira2::oe2_setSuperRoom() {
525 	// 165: set super room
526 	_superRoomNumber = getVarOrWord();
527 }
528 
oe2_getSuperRoom()529 void AGOSEngine_Elvira2::oe2_getSuperRoom() {
530 	// 166: get super room
531 	writeNextVarContents(_superRoomNumber);
532 }
533 
oe2_setExitOpen()534 void AGOSEngine_Elvira2::oe2_setExitOpen() {
535 	// 167: set exit open
536 	Item *i = getNextItemPtr();
537 	uint16 n = getVarOrWord();
538 	uint16 d = getVarOrByte();
539 	setExitState(i, n, d, 1);
540 }
541 
oe2_setExitClosed()542 void AGOSEngine_Elvira2::oe2_setExitClosed() {
543 	// 168: set exit closed
544 	Item *i = getNextItemPtr();
545 	uint16 n = getVarOrWord();
546 	uint16 d = getVarOrByte();
547 	setExitState(i, n, d, 2);
548 }
549 
oe2_setExitLocked()550 void AGOSEngine_Elvira2::oe2_setExitLocked() {
551 	// 169: set exit locked
552 	Item *i = getNextItemPtr();
553 	uint16 n = getVarOrWord();
554 	uint16 d = getVarOrByte();
555 	setExitState(i, n, d, 3);
556 }
557 
oe2_ifExitOpen()558 void AGOSEngine_Elvira2::oe2_ifExitOpen() {
559 	// 171: if exit open
560 	Item *i = getNextItemPtr();
561 	uint16 n = getVarOrWord();
562 	uint16 d = getVarOrByte();
563 	setScriptCondition(getExitState(i, n, d) == 1);
564 }
565 
oe2_ifExitClosed()566 void AGOSEngine_Elvira2::oe2_ifExitClosed() {
567 	// 172: if exit closed
568 	Item *i = getNextItemPtr();
569 	uint16 n = getVarOrWord();
570 	uint16 d = getVarOrByte();
571 	setScriptCondition(getExitState(i, n, d) == 2);
572 }
573 
oe2_ifExitLocked()574 void AGOSEngine_Elvira2::oe2_ifExitLocked() {
575 	// 173: if exit locked
576 	Item *i = getNextItemPtr();
577 	uint16 n = getVarOrWord();
578 	uint16 d = getVarOrByte();
579 	setScriptCondition(getExitState(i, n, d) == 3);
580 }
581 
oe2_playEffect()582 void AGOSEngine_Elvira2::oe2_playEffect() {
583 	// 174: play sound
584 	uint soundId = getVarOrWord();
585 	loadSound(soundId, 0, 0);
586 }
587 
oe2_getDollar2()588 void AGOSEngine_Elvira2::oe2_getDollar2() {
589 	// 175
590 	_showPreposition = true;
591 
592 	setup_cond_c_helper();
593 
594 	_objectItem = _hitAreaObjectItem;
595 
596 	if (_objectItem == _dummyItem2)
597 		_objectItem = me();
598 
599 	if (_objectItem == _dummyItem3)
600 		_objectItem = derefItem(me()->parent);
601 
602 	if (_objectItem != NULL) {
603 		_scriptNoun2 = _objectItem->noun;
604 		_scriptAdj2 = _objectItem->adjective;
605 	} else {
606 		_scriptNoun2 = -1;
607 		_scriptAdj2 = -1;
608 	}
609 
610 	_showPreposition = false;
611 }
612 
oe2_setSRExit()613 void AGOSEngine_Elvira2::oe2_setSRExit() {
614 	// 176: set super room exit
615 	Item *i = getNextItemPtr();
616 	uint n = getVarOrWord();
617 	uint d = getVarOrByte();
618 	uint s = getVarOrByte();
619 	setSRExit(i, n, d, s);
620 }
621 
oe2_printPlayerDamage()622 void AGOSEngine_Elvira2::oe2_printPlayerDamage() {
623 	// 177: set player damage event
624 	uint a = getVarOrByte();
625 	if (_opcode177Var1 && !_opcode177Var2 && a != 0 && a <= 10) {
626 		addVgaEvent(_vgaBaseDelay, PLAYER_DAMAGE_EVENT, NULL, 0, a);
627 		_opcode177Var2 = 0;
628 		_opcode177Var1 = 0;
629 	}
630 }
631 
oe2_printMonsterDamage()632 void AGOSEngine_Elvira2::oe2_printMonsterDamage() {
633 	// 178: set monster damage event
634 	uint a = getVarOrByte();
635 	if (_opcode178Var1 && !_opcode178Var2 && a != 0 && a <= 10) {
636 		addVgaEvent(_vgaBaseDelay, MONSTER_DAMAGE_EVENT, NULL, 0, a);
637 		_opcode178Var2 = 0;
638 		_opcode178Var1 = 0;
639 	}
640 }
641 
oe2_isAdjNoun()642 void AGOSEngine_Elvira2::oe2_isAdjNoun() {
643 	// 179: item unk1 unk2 is
644 	Item *item = getNextItemPtr();
645 	int16 a = getNextWord();
646 	int16 n = getNextWord();
647 
648 	if (getGameType() == GType_ELVIRA2 && item == NULL) {
649 		// WORKAROUND bug #1745996: A NULL item can occur when
650 		// interacting with items in the dinning room
651 		setScriptCondition(false);
652 		return;
653 	}
654 
655 	assert(item);
656 	setScriptCondition(item->adjective == a && item->noun == n);
657 }
658 
oe2_b2Set()659 void AGOSEngine_Elvira2::oe2_b2Set() {
660 	// 180: set bit2
661 	uint bit = getVarOrByte();
662 	_bitArrayTwo[bit / 16] |= (1 << (bit & 15));
663 }
664 
oe2_b2Clear()665 void AGOSEngine_Elvira2::oe2_b2Clear() {
666 	// 181: clear bit2
667 	uint bit = getVarOrByte();
668 	_bitArrayTwo[bit / 16] &= ~(1 << (bit & 15));
669 }
670 
oe2_b2Zero()671 void AGOSEngine_Elvira2::oe2_b2Zero() {
672 	// 182: is bit2 clear
673 	uint bit = getVarOrByte();
674 	setScriptCondition((_bitArrayTwo[bit / 16] & (1 << (bit & 15))) == 0);
675 }
676 
oe2_b2NotZero()677 void AGOSEngine_Elvira2::oe2_b2NotZero() {
678 	// 183: is bit2 set
679 	uint bit = getVarOrByte();
680 	setScriptCondition((_bitArrayTwo[bit / 16] & (1 << (bit & 15))) != 0);
681 }
682 
printStats()683 void AGOSEngine_Elvira2::printStats() {
684 	WindowBlock *window = _dummyWindow;
685 	int val;
686 	const uint8 y = (getPlatform() == Common::kPlatformAtariST) ? 132 : 134;
687 
688 	window->flags = 1;
689 
690 	mouseOff();
691 
692 	// Level
693 	val = _variableArray[20];
694 	if (val < -99)
695 		val = -99;
696 	if (val > 99)
697 		val = 99;
698 	writeChar(window, 10, y, 0, val);
699 
700 	// PP
701 	val = _variableArray[22];
702 	if (val < -99)
703 		val = -99;
704 	if (val > 99)
705 		val = 99;
706 	writeChar(window, 16, y, 6, val);
707 
708 	// HP
709 	val = _variableArray[23];
710 	if (val < -99)
711 		val = -99;
712 	if (val > 99)
713 		val = 99;
714 	writeChar(window, 23, y, 4, val);
715 
716 	// Experience
717 	val = _variableArray[21];
718 	if (val < -99)
719 		val = -99;
720 	if (val > 9999)
721 		val = 9999;
722 	writeChar(window, 30, y, 6, val / 100);
723 	writeChar(window, 32, y, 2, val % 100);
724 
725 	mouseOn();
726 }
727 
728 } // End of namespace AGOS
729