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 "scumm/scumm_v7.h"
24 #include "scumm/smush/smush_player.h"
25 #include "scumm/insane/insane.h"
26 
27 namespace Scumm {
28 
procIACT(byte * renderBitmap,int32 codecparam,int32 setupsan12,int32 setupsan13,Common::SeekableReadStream & b,int32 size,int32 flags,int16 par1,int16 par2,int16 par3,int16 par4)29 void Insane::procIACT(byte *renderBitmap, int32 codecparam, int32 setupsan12,
30 					  int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
31 					  int16 par1, int16 par2, int16 par3, int16 par4) {
32 	if (_keyboardDisable)
33 		return;
34 
35 	switch (_currSceneId) {
36 	case 1:
37 		iactScene1(renderBitmap, codecparam, setupsan12, setupsan13, b, size, flags, par1, par2, par3, par4);
38 		break;
39 	case 3:
40 	case 13:
41 		iactScene3(renderBitmap, codecparam, setupsan12, setupsan13, b, size, flags, par1, par2, par3, par4);
42 		break;
43 	case 4:
44 	case 5:
45 		iactScene4(renderBitmap, codecparam, setupsan12, setupsan13, b, size, flags, par1, par2, par3, par4);
46 		break;
47 	case 6:
48 		iactScene6(renderBitmap, codecparam, setupsan12, setupsan13, b, size, flags, par1, par2, par3, par4);
49 		break;
50 	case 17:
51 		iactScene17(renderBitmap, codecparam, setupsan12, setupsan13, b, size, flags, par1, par2, par3, par4);
52 		break;
53 	case 21:
54 		iactScene21(renderBitmap, codecparam, setupsan12, setupsan13, b, size, flags, par1, par2, par3, par4);
55 		break;
56 	default:
57 		break;
58 	}
59 }
60 
iactScene1(byte * renderBitmap,int32 codecparam,int32 setupsan12,int32 setupsan13,Common::SeekableReadStream & b,int32 size,int32 flags,int16 par1,int16 par2,int16 par3,int16 par4)61 void Insane::iactScene1(byte *renderBitmap, int32 codecparam, int32 setupsan12,
62 					  int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
63 					  int16 par1, int16 par2, int16 par3, int16 par4) {
64 	int16 par5, par6, par7, par9, par11, par13;
65 
66 	switch (par1) {
67 	case 2: // PATCH
68 		if (par3 != 1)
69 			break;
70 
71 		par5 = b.readUint16LE(); // si
72 		if (_actor[0].field_8 == 112) {
73 			setBit(par5);
74 			break;
75 		}
76 
77 		if (_approachAnim == -1) {
78 			chooseEnemy(); //PATCH
79 			_approachAnim = _enemy[_currEnemy].apprAnim;
80 		}
81 
82 		if (_approachAnim == par4)
83 			clearBit(par5);
84 		else
85 			setBit(par5);
86 		break;
87 	case 3:
88 		if (par3 == 1) {
89 			setBit(b.readUint16LE());
90 			_approachAnim = -1;
91 		}
92 		break;
93 	case 4:
94 		if (par3 == 1 && (_approachAnim < 0 || _approachAnim > 4))
95 			setBit(b.readUint16LE());
96 		break;
97 	case 5:
98 		if (par2 != 13)
99 			break;
100 
101 		b.readUint16LE();			// +8
102 		b.readUint16LE();			// +10
103 		par7 = b.readUint16LE();	// +12 dx
104 		b.readUint16LE();			// +14
105 		par9 = b.readUint16LE();	// +16 bx
106 		b.readUint16LE();			// +18
107 		par11 = b.readUint16LE();	// +20 cx
108 		b.readUint16LE();			// +22
109 		par13 = b.readUint16LE();	// +24 ax
110 
111 		if (par13 > _actor[0].x || par11 < _actor[0].x) {
112 			_tiresRustle = true;
113 			_actor[0].x1 = -_actor[0].x1;
114 			_actor[0].damage++; // PATCH
115 		}
116 
117 		if (par9 < _actor[0].x || par7 > _actor[0].x) {
118 			_tiresRustle = true;
119 			_actor[0].damage += 4; // PATCH
120 		}
121 		break;
122 	case 6:
123 		switch (par2) {
124 		case 38:
125 			smlayer_drawSomething(renderBitmap, codecparam, 50-19, 20-13, 3,
126 								  _smush_iconsNut, 7, 0, 0);
127 			_roadBranch = true;
128 			_iactSceneId = par4;
129 			break;
130 		case 25:
131 			_roadBumps = true;
132 			_actor[0].y1 = -_actor[0].y1;
133 			break;
134 		case 11:
135 			if (_approachAnim >= 1 && _approachAnim <= 4 && !_needSceneSwitch)
136 				queueSceneSwitch(13, _smush_minefiteFlu, "minefite.san", 64, 0,
137 								 _continueFrame1, 1300);
138 			break;
139 		case 9:
140 			par5 = b.readUint16LE(); // si
141 			par6 = b.readUint16LE(); // bx
142 			smlayer_setFluPalette(_smush_roadrsh3Rip, 0);
143 			if (par5 == par6 - 1)
144 				smlayer_setFluPalette(_smush_roadrashRip, 0);
145 			break;
146 		default:
147 			break;
148 		}
149 		break;
150 	case 7:
151 		switch (par4) {
152 		case 1:
153 			_actor[0].x -= (b.readUint16LE() - 160) / 10;
154 			break;
155 		case 2:
156 			par5 = b.readUint16LE();
157 
158 			if (par5 - 8 > _actor[0].x || par5 + 8 < _actor[0].x) {
159 				if (smlayer_isSoundRunning(86))
160 					smlayer_stopSound(86);
161 			} else {
162 				if (!smlayer_isSoundRunning(86))
163 					smlayer_startSfx(86);
164 			}
165 			break;
166 		default:
167 			break;
168 		}
169 		break;
170 	default:
171 		break;
172 	}
173 
174 	if (_approachAnim < 0 || _approachAnim > 4)
175 		if (readArray(8)) {
176 			smlayer_drawSomething(renderBitmap, codecparam, 270-19, 20-18, 3,
177 								  _smush_iconsNut, 20, 0, 0);
178 			_benHasGoggles = true;
179 		}
180 }
181 
chooseEnemy()182 void Insane::chooseEnemy() {
183 	if ((_vm->_game.features & GF_DEMO) && (_vm->_game.platform == Common::kPlatformDOS)) {
184 		_currEnemy = EN_ROTT1;
185 		return;
186 	}
187 
188 	if (readArray(58) != 0)
189 		_enemy[EN_TORQUE].isEmpty = 1;
190 
191 	if (_enemy[EN_TORQUE].occurences == 0) {
192 		_currEnemy = EN_TORQUE;
193 		_metEnemiesListTail++;
194 		_metEnemiesList[_metEnemiesListTail] = EN_TORQUE;
195 		return;
196 	}
197 
198 	removeEmptyEnemies();
199 
200 	int32 count, i, j, en, en2;
201 	bool notfound;
202 
203 	en = 0;
204 	for (i = 0; i < 9; i++)
205 		if (_enemy[i].isEmpty == 0)
206 			++en;
207 
208 	en -= 4;
209 	assert(en >= 0);
210 
211 	count = 0;
212 	while (1) {
213 		count++;
214 		if (count < 14) {
215 			en2 = _vm->_rnd.getRandomNumber(10);
216 			if (en2 == 9)
217 				en2 = 6;
218 			else if (en2 > 9)
219 				en2 = 7;
220 
221 			notfound = true;
222 
223 			if (_enemy[en2].isEmpty != 0)
224 				continue;
225 
226 			if (0 < _metEnemiesListTail) {
227 				i = 0;
228 				do {
229 					if (en2 == _metEnemiesList[i + 1])
230 						notfound = false;
231 					i++;
232 				} while (i < _metEnemiesListTail && notfound);
233 			}
234 			if (!notfound) {
235 				continue;
236 			}
237 		} else {
238 			j = 0;
239 			do {
240 				notfound = true;
241 				en2 = j;
242 				if (0 < _metEnemiesListTail) {
243 					i = 0;
244 					do {
245 						if (en2 == _metEnemiesList[i + 1])
246 							notfound = false;
247 						i++;
248 					} while (i < _metEnemiesListTail && notfound);
249 				}
250 				j++;
251 			} while (j < 9 && !notfound);
252 			if (!notfound) {
253 				_metEnemiesListTail = 0;
254 				count = 0;
255 				continue;
256 			}
257 		}
258 
259 		++_metEnemiesListTail;
260 		assert(_metEnemiesListTail < ARRAYSIZE(_metEnemiesList));
261 		_metEnemiesList[_metEnemiesListTail] = en2;
262 
263 		if (_metEnemiesListTail >= en) {
264 			removeEnemyFromMetList(0);
265 		}
266 
267 		if (notfound)
268 			break;
269 	}
270 
271 	_currEnemy = en2;
272 }
273 
removeEmptyEnemies()274 void Insane::removeEmptyEnemies() {
275 	if (_metEnemiesListTail > 0) {
276 		for (int i = 0; i < _metEnemiesListTail; i++)
277 			if (_enemy[i].isEmpty == 1)
278 				removeEnemyFromMetList(i);
279 	}
280 }
281 
removeEnemyFromMetList(int32 enemy1)282 void Insane::removeEnemyFromMetList(int32 enemy1) {
283 	if (enemy1 >= _metEnemiesListTail)
284 		return;
285 
286 	int en = enemy1;
287 	do {
288 		++en;
289 		assert(en + 1 < ARRAYSIZE(_metEnemiesList));
290 		_metEnemiesList[en] = _metEnemiesList[en + 1];
291 	} while (en < _metEnemiesListTail);
292 	_metEnemiesListTail--;
293 }
294 
iactScene3(byte * renderBitmap,int32 codecparam,int32 setupsan12,int32 setupsan13,Common::SeekableReadStream & b,int32 size,int32 flags,int16 command,int16 par1,int16,int16)295 void Insane::iactScene3(byte *renderBitmap, int32 codecparam, int32 setupsan12,
296 					  int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
297 					  int16 command, int16 par1, int16, int16) {
298 	int par2, par3;
299 	if (command == 6) {
300 		if (par1 == 9) {
301 			par2 = b.readUint16LE(); // ptr + 8
302 			par3 = b.readUint16LE(); // ptr + 10
303 
304 			if (!par2)
305 				smlayer_setFluPalette(_smush_roadrsh3Rip, 0);
306 			else {
307 				if (par2 == par3 - 1)
308 					smlayer_setFluPalette(_smush_roadrashRip, 0);
309 			}
310 		} else if (par1 == 25) {
311 			_roadBumps = true;
312 			_actor[0].y1 = -_actor[0].y1;
313 			_actor[1].y1 = -_actor[1].y1;
314 		}
315 	}
316 }
317 
iactScene4(byte * renderBitmap,int32 codecparam,int32 setupsan12,int32 setupsan13,Common::SeekableReadStream & b,int32 size,int32 flags,int16 par1,int16 par2,int16 par3,int16 par4)318 void Insane::iactScene4(byte *renderBitmap, int32 codecparam, int32 setupsan12,
319 					  int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
320 					  int16 par1, int16 par2, int16 par3, int16 par4) {
321 	int16 par5;
322 
323 	switch (par1) {
324 	case 2:
325 	case 4:
326 		par5 = b.readUint16LE(); // si
327 		switch (par3) {
328 		case 1:
329 			if (par4 == 1) {
330 				if (readArray(6))
331 					setBit(par5);
332 				else
333 					clearBit(par5);
334 			} else {
335 				if (readArray(6))
336 					clearBit(par5);
337 				else
338 					setBit(par5);
339 			}
340 			break;
341 		case 2:
342 			if (readArray(5))
343 				clearBit(par5);
344 			else
345 				setBit(par5);
346 			break;
347 		default:
348 			break;
349 		}
350 		break;
351 	case 6:
352 		switch (par2) {
353 		case 38:
354 
355 			smlayer_drawSomething(renderBitmap, codecparam, 270-19, 20-13, 3,
356 								  _smush_icons2Nut, 10, 0, 0);
357 			_roadBranch = true;
358 			_iactSceneId = par4;
359 			break;
360 		case 7:
361 			if (readArray(4) != 0)
362 				return;
363 
364 			smlayer_drawSomething(renderBitmap, codecparam, 160-13, 20-10, 3, // QW
365 								  _smush_icons2Nut, 8, 0, 0);
366 			_roadStop = true;
367 			break;
368 		case 8:
369 			if (readArray(4) == 0 || readArray(6) == 0)
370 				return;
371 
372 			writeArray(1, _posBrokenTruck);
373 			writeArray(3, _val57d);
374 			smush_setToFinish();
375 
376 			break;
377 		case 25:
378 			if (readArray(5) == 0)
379 				return;
380 
381 			_carIsBroken = true;
382 			smlayer_drawSomething(renderBitmap, codecparam, 160-13, 20-10, 3, // QW
383 								  _smush_icons2Nut, 8, 0, 0);
384 			break;
385 		case 11:
386 			smlayer_drawSomething(renderBitmap, codecparam, 50-19, 20-13, 3,
387 								  _smush_icons2Nut, 9, 0, 0);
388 			_roadBranch = true;
389 			_iactSceneId = par4;
390 			break;
391 		default:
392 			break;
393 		}
394 		break;
395 	default:
396 		break;
397 	}
398 }
399 
iactScene6(byte * renderBitmap,int32 codecparam,int32 setupsan12,int32 setupsan13,Common::SeekableReadStream & b,int32 size,int32 flags,int16 par1,int16 par2,int16 par3,int16 par4)400 void Insane::iactScene6(byte *renderBitmap, int32 codecparam, int32 setupsan12,
401 					  int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
402 					  int16 par1, int16 par2, int16 par3, int16 par4) {
403 	int16 par5;
404 
405 	switch (par1) {
406 	case 7:
407 		par5 = b.readUint16LE();
408 		if (par4 != 3)
409 			break;
410 
411 		if (par5 >= _actor[0].x)
412 			break;
413 
414 		_actor[0].x = par5;
415 		break;
416 	case 2:
417 	case 4:
418 		par5 = b.readUint16LE();
419 		switch (par3) {
420 		case 1:
421 			if (par4 == 1) {
422 				if (readArray(6))
423 					setBit(par5);
424 				else
425 					clearBit(par5);
426 			} else {
427 				if (readArray(6))
428 					clearBit(par5);
429 				else
430 					setBit(par5);
431 			}
432 			break;
433 		case 2:
434 			if (readArray(5))
435 				clearBit(par5);
436 			else
437 				setBit(par5);
438 			break;
439 		default:
440 			break;
441 		}
442 		break;
443 	case 6:
444 		switch (par2) {
445 		case 38:
446 			smlayer_drawSomething(renderBitmap, codecparam, 270-19, 20-13, 3,
447 								  _smush_icons2Nut, 10, 0, 0);
448 			_roadBranch = true;
449 			_iactSceneId = par4;
450 			break;
451 		case 7:
452 			if (readArray(4) != 0)
453 				return;
454 
455 			_roadStop = true;
456 			smlayer_drawSomething(renderBitmap, codecparam, 160-13, 20-10, 3, //QW
457 								  _smush_icons2Nut, 8, 0, 0);
458 			break;
459 		case 8:
460 			if (readArray(4) == 0 || readArray(6) == 0)
461 				return;
462 
463 			writeArray(1, _posBrokenTruck);
464 			writeArray(3, _posVista);
465 			smush_setToFinish();
466 
467 			break;
468 		case 25:
469 			if (readArray(5) == 0)
470 				return;
471 
472 			_carIsBroken = true;
473 			smlayer_drawSomething(renderBitmap, codecparam, 160-13, 20-10, 3, //QW
474 								  _smush_icons2Nut, 8, 0, 0);
475 			break;
476 		case 11:
477 			smlayer_drawSomething(renderBitmap, codecparam, 50-19, 20-13, 3,
478 								  _smush_icons2Nut, 9, 0, 0);
479 			_roadBranch = true;
480 			_iactSceneId = par4;
481 			break;
482 		default:
483 			break;
484 		}
485 		break;
486 	default:
487 		break;
488 	}
489 }
490 
iactScene17(byte * renderBitmap,int32 codecparam,int32 setupsan12,int32 setupsan13,Common::SeekableReadStream & b,int32 size,int32 flags,int16 par1,int16 par2,int16 par3,int16 par4)491 void Insane::iactScene17(byte *renderBitmap, int32 codecparam, int32 setupsan12,
492 					  int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
493 					  int16 par1, int16 par2, int16 par3, int16 par4) {
494 	switch (par1) {
495 	case 2:
496 	case 3:
497 	case 4:
498 		if (par3 == 1) {
499 			setBit(b.readUint16LE());
500 			_approachAnim = -1;
501 		}
502 		break;
503 	case 6:
504 		switch (par2) {
505 		case 38:
506 			smlayer_drawSomething(renderBitmap, codecparam, 28, 48, 1,
507 								  _smush_iconsNut, 6, 0, 0);
508 			_roadBranch = true;
509 			_iactSceneId = par4;
510 			if (_counter1 <= 4) {
511 				if (_counter1 == 4)
512 					smlayer_startSfx(94);
513 
514 				smlayer_showStatusMsg(-1, renderBitmap, codecparam, 24, 167, 1,
515 									  2, 0, "%s", handleTrsTag(5000));
516 			}
517 			_objectDetected = true;
518 			break;
519 		case 10:
520 			smlayer_drawSomething(renderBitmap, codecparam, 28, 48, 1,
521 								  _smush_iconsNut, 6, 0, 0);
522 			if (_counter1 <= 4) {
523 				if (_counter1 == 4)
524 					smlayer_startSfx(94);
525 
526 				smlayer_showStatusMsg(-1, renderBitmap, codecparam, 24, 167, 1,
527 									  2, 0, "%s", handleTrsTag(5001));
528 			}
529 			_objectDetected = true;
530 			_mineCaveIsNear = true;
531 			break;
532 		default:
533 			break;
534 		}
535 		break;
536 	default:
537 		break;
538 	}
539 }
540 
iactScene21(byte * renderBitmap,int32 codecparam,int32 setupsan12,int32 setupsan13,Common::SeekableReadStream & b,int32 size,int32 flags,int16 par1,int16 par2,int16 par3,int16 par4)541 void Insane::iactScene21(byte *renderBitmap, int32 codecparam, int32 setupsan12,
542 					  int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
543 					  int16 par1, int16 par2, int16 par3, int16 par4) {
544 	// void implementation
545 }
546 
547 }
548