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 "fullpipe/fullpipe.h"
24 
25 #include "fullpipe/constants.h"
26 #include "fullpipe/gameloader.h"
27 #include "fullpipe/messages.h"
28 #include "fullpipe/modal.h"
29 #include "fullpipe/motion.h"
30 #include "fullpipe/objectnames.h"
31 #include "fullpipe/scenes.h"
32 #include "fullpipe/statics.h"
33 
34 #include "engines/savestate.h"
35 
36 #include "graphics/palette.h"
37 #include "graphics/surface.h"
38 
39 namespace Fullpipe {
40 
ModalIntro()41 ModalIntro::ModalIntro() {
42 	_field_8 = 0;
43 	_countDown = 0;
44 	_stillRunning = 0;
45 
46 	if (g_vars->sceneIntro_skipIntro) {
47 		_introFlags = 4;
48 	} else {
49 		_introFlags = 33;
50 		_countDown = 150;
51 
52 		PictureObject *pict = g_fp->accessScene(SC_INTRO1)->getPictureObjectById(PIC_IN1_PIPETITLE, 0);
53 		pict->setFlags(pict->_flags & 0xFFFB);
54 	}
55 
56 	g_vars->sceneIntro_skipIntro = false;
57 	_sfxVolume = g_fp->_sfxVolume;
58 }
59 
~ModalIntro()60 ModalIntro::~ModalIntro() {
61 	g_fp->stopAllSounds();
62 	g_fp->_sfxVolume = _sfxVolume;
63 }
64 
handleMessage(ExCommand * message)65 bool ModalIntro::handleMessage(ExCommand *message) {
66 	if (message->_messageKind != 17)
67 		return false;
68 
69 	if (message->_messageNum != 36)
70 		return false;
71 
72 	if (message->_param != 13 && message->_param != 27 && message->_param != 32)
73 		return false;
74 
75 	if (_stillRunning) {
76 		if (!(_introFlags & 0x10)) {
77 			_countDown = 0;
78 			g_vars->sceneIntro_needBlackout = true;
79 			return true;
80 		}
81 		g_vars->sceneIntro_playing = false;
82 		g_vars->sceneIntro_needBlackout = true;
83 	}
84 
85 	return true;
86 }
87 
init(int counterdiff)88 bool ModalIntro::init(int counterdiff) {
89 	if (!g_vars->sceneIntro_playing) {
90 		if (!_stillRunning) {
91 			finish();
92 			return false;
93 		}
94 
95 		if (_introFlags & 0x10)
96 			g_fp->_gameLoader->updateSystems(42);
97 
98 		_introFlags |= 2;
99 
100 		return true;
101 	}
102 
103 	if (_introFlags & 4) {
104 		ModalVideoPlayer *player = new ModalVideoPlayer();
105 
106 		g_fp->_modalObject = player;
107 		player->_parentObj = this;
108 		player->play("intro.avi");
109 
110 		_countDown--;
111 
112 		if (_countDown > 0 )
113 			return true;
114 
115 		if (_stillRunning <= 0) {
116 			_countDown = 0;
117 			_stillRunning = 0;
118 			_introFlags = (_introFlags & 0xfb) | 0x40;
119 
120 			return true;
121 		}
122 
123 		_introFlags |= 2;
124 		return true;
125 	}
126 
127 	if (_introFlags & 0x40) {
128 		ModalVideoPlayer *player = new ModalVideoPlayer();
129 
130 		g_fp->_modalObject = player;
131 		player->_parentObj = this;
132 		player->play("intro2.avi");
133 
134 		_countDown--;
135 		if (_countDown > 0)
136 			return true;
137 
138 		if (_stillRunning <= 0) {
139 			_countDown = 50;
140 			_stillRunning = 0;
141 			_introFlags = (_introFlags & 0xbf) | 9;
142 
143 			return true;
144 		}
145 
146 		_introFlags |= 2;
147 		return true;
148 	}
149 
150 	if (_introFlags & 8) {
151 		_countDown--;
152 
153 		if (_countDown > 0 )
154 			return true;
155 
156 		if (_stillRunning > 0) {
157 			_introFlags |= 2;
158 			return true;
159 		}
160 
161 		_countDown = 150;
162 		_introFlags = (_introFlags & 0xf7) | 0x21;
163 		g_fp->accessScene(SC_INTRO1)->getPictureObjectById(PIC_IN1_PIPETITLE, 0)->_flags &= 0xfffb;
164 	}
165 
166 	if (!(_introFlags & 0x20)) {
167 		if (_introFlags & 0x10) {
168 			if (!_stillRunning) {
169 				_introFlags |= 1;
170 
171 				g_fp->accessScene(SC_INTRO1)->getPictureObjectById(PIC_IN1_PIPETITLE, 0)->_flags &= 0xfffb;
172 				g_fp->accessScene(SC_INTRO1)->getPictureObjectById(PIC_IN1_GAMETITLE, 0)->_flags &= 0xfffb;
173 
174 				chainQueue(QU_INTR_STARTINTRO, 1);
175 			}
176 			g_fp->_gameLoader->updateSystems(42);
177 		}
178 		return true;
179 	}
180 
181 	_countDown--;
182 
183 	if (_countDown <= 0) {
184 		if (_stillRunning > 0) {
185 			_introFlags |= 2;
186 
187 			return true;
188 		}
189 
190 		_introFlags = (_introFlags & 0xdf) | 0x10;
191 
192 		g_fp->accessScene(SC_INTRO1)->getPictureObjectById(PIC_IN1_GAMETITLE, 0)->_flags &= 0xfffb;
193 
194 		_stillRunning = 0;
195 	}
196 
197 	return true;
198 }
199 
update()200 void ModalIntro::update() {
201 	if (g_fp->_currentScene) {
202 		if (_introFlags & 1) {
203 			g_fp->sceneFade(g_fp->_currentScene, true);
204 			_stillRunning = 255;
205 			_introFlags &= 0xfe;
206 
207 			if (_introFlags & 0x20)
208 				g_fp->playSound(SND_INTR_019, 0);
209 		} else if (_introFlags & 2) {
210 			if (g_vars->sceneIntro_needBlackout) {
211 				g_fp->drawAlphaRectangle(0, 0, 800, 600, 0);
212 				g_vars->sceneIntro_needBlackout = 0;
213 				_stillRunning = 0;
214 				_introFlags &= 0xfd;
215 			} else {
216 				g_fp->sceneFade(g_fp->_currentScene, false);
217 				_stillRunning = 0;
218 				_introFlags &= 0xfd;
219 			}
220 		} else if (_stillRunning) {
221 			g_fp->_currentScene->draw();
222 		}
223 	}
224 }
225 
finish()226 void ModalIntro::finish() {
227 	g_fp->_gameLoader->unloadScene(SC_INTRO2);
228 
229 	g_fp->_currentScene = g_fp->accessScene(SC_INTRO1);
230 	g_fp->_gameLoader->preloadScene(SC_INTRO1, TrubaDown);
231 
232 	if (g_fp->_currentScene)
233 		g_fp->_gameLoader->updateSystems(42);
234 }
235 
ModalIntroDemo()236 ModalIntroDemo::ModalIntroDemo() {
237 	_field_8 = 0;
238 	_countDown = 50;
239 	_stillRunning = 0;
240 	_introFlags = 9;
241 	g_vars->sceneIntro_skipIntro = false;
242 	_sfxVolume = g_fp->_sfxVolume;
243 }
244 
~ModalIntroDemo()245 ModalIntroDemo::~ModalIntroDemo() {
246 	g_fp->stopAllSounds();
247 	g_fp->_sfxVolume = _sfxVolume;
248 }
249 
handleMessage(ExCommand * message)250 bool ModalIntroDemo::handleMessage(ExCommand *message) {
251 	if (message->_messageKind != 17)
252 		return false;
253 
254 	if (message->_messageNum != 36)
255 		return false;
256 
257 	if (message->_param != 13 && message->_param != 27 && message->_param != 32)
258 		return false;
259 
260 	if (_introFlags & 0x8) {
261 		_countDown = 0;
262 		g_vars->sceneIntro_needBlackout = true;
263 		return true;
264 	} else if (_stillRunning) {
265 		g_vars->sceneIntro_playing = false;
266 		g_vars->sceneIntro_needBlackout = true;
267 	}
268 
269 	return true;
270 }
271 
init(int counterdiff)272 bool ModalIntroDemo::init(int counterdiff) {
273 	if (!g_vars->sceneIntro_playing) {
274 		if (!_stillRunning) {
275 			finish();
276 			return false;
277 		}
278 
279 		if (_introFlags & 0x10)
280 			g_fp->_gameLoader->updateSystems(42);
281 
282 		_introFlags |= 2;
283 
284 		return true;
285 	}
286 
287 	if (_introFlags & 8) {
288 		_countDown--;
289 
290 		if (_countDown > 0)
291 			return true;
292 
293 		if (_stillRunning > 0) {
294 			_introFlags |= 2;
295 			return true;
296 		}
297 
298 		_countDown = 150;
299 		_introFlags = (_introFlags & 0xf7) | 0x21;
300 		g_fp->accessScene(SC_INTRO1)->getPictureObjectById(522, 0)->_flags &= 0xfffb;
301 	} else {
302 		if (!(_introFlags & 0x20))
303 			return true;
304 
305 		_countDown--;
306 
307 		if (_countDown > 0)
308 			return true;
309 
310 		if (_stillRunning > 0) {
311 			_introFlags |= 2;
312 			return true;
313 		}
314 
315 		_introFlags &= 0xDF;
316 
317 		g_vars->sceneIntro_playing = false;
318 		_stillRunning = 0;
319 	}
320 
321 	return true;
322 }
323 
update()324 void ModalIntroDemo::update() {
325 	if (g_fp->_currentScene) {
326 		if (_introFlags & 1) {
327 			if (g_vars->sceneIntro_needBlackout) {
328 				g_fp->drawAlphaRectangle(0, 0, 800, 600, 0);
329 				g_vars->sceneIntro_needBlackout = 0;
330 			} else {
331 				g_fp->sceneFade(g_fp->_currentScene, true);
332 			}
333 			_stillRunning = 255;
334 			_introFlags &= 0xfe;
335 
336 			if (_introFlags & 0x20)
337 				g_fp->playSound(SND_INTR_019, 0);
338 		} else if (_introFlags & 2) {
339 			if (g_vars->sceneIntro_needBlackout) {
340 				g_fp->drawAlphaRectangle(0, 0, 800, 600, 0);
341 				g_vars->sceneIntro_needBlackout = 0;
342 				_stillRunning = 0;
343 				_introFlags &= 0xfd;
344 			} else {
345 				g_fp->sceneFade(g_fp->_currentScene, false);
346 				_stillRunning = 0;
347 				_introFlags &= 0xfd;
348 			}
349 		} else if (_stillRunning) {
350 			g_fp->_currentScene->draw();
351 		}
352 	}
353 }
354 
finish()355 void ModalIntroDemo::finish() {
356 	g_fp->_currentScene = g_fp->accessScene(SC_INTRO1);
357 	g_fp->_gameLoader->preloadScene(SC_INTRO1, TrubaDown);
358 
359 	if (g_fp->_currentScene)
360 		g_fp->_gameLoader->updateSystems(42);
361 }
362 
checkSkipVideo(const Common::Event & event)363 static bool checkSkipVideo(const Common::Event &event) {
364 	switch (event.type) {
365 	case Common::EVENT_KEYDOWN:
366 		switch (event.kbd.keycode) {
367 		case Common::KEYCODE_ESCAPE:
368 		case Common::KEYCODE_RETURN:
369 		case Common::KEYCODE_SPACE:
370 			return true;
371 		default:
372 			return false;
373 		}
374 	case Common::EVENT_QUIT:
375 	case Common::EVENT_RTL:
376 		return true;
377 	default:
378 		return false;
379 	}
380 }
381 
play(const char * filename)382 void ModalVideoPlayer::play(const char *filename) {
383 	if (!_decoder.loadFile(filename))
384 		return;
385 
386 	uint16 x = (g_system->getWidth() - _decoder.getWidth()) / 2;
387 	uint16 y = (g_system->getHeight() - _decoder.getHeight()) / 2;
388 
389 	_decoder.start();
390 
391 	while (!g_fp->shouldQuit() && !_decoder.endOfVideo()) {
392 		if (_decoder.needsUpdate()) {
393 			const Graphics::Surface *frame = _decoder.decodeNextFrame();
394 			if (frame) {
395 				Common::ScopedPtr<Graphics::Surface, Graphics::SurfaceDeleter> tmpFrame;
396 				if (frame->format != g_system->getScreenFormat()) {
397 					tmpFrame.reset(frame->convertTo(g_system->getScreenFormat()));
398 					frame = tmpFrame.get();
399 				}
400 				g_fp->_system->copyRectToScreen(frame->getPixels(), frame->pitch,
401 					x, y, frame->w, frame->h);
402 
403 				if (_decoder.hasDirtyPalette())
404 					g_fp->_system->getPaletteManager()->setPalette(_decoder.getPalette(), 0, 256);
405 
406 				g_fp->_system->updateScreen();
407 			}
408 		}
409 
410 		Common::Event event;
411 		while (g_fp->_system->getEventManager()->pollEvent(event)) {
412 			if (checkSkipVideo(event)) {
413 				goto finish;
414 			}
415 		}
416 
417 		g_fp->_system->delayMillis(_decoder.getTimeToNextFrame());
418 	}
419 
420 finish:
421 	_decoder.close();
422 }
423 
ModalMap()424 ModalMap::ModalMap() {
425 	_mapScene = 0;
426 	_pic = NULL;
427 	_picI03 = NULL;
428 	_highlightedPic = NULL;
429 	_isRunning = false;
430 	_rect1 = g_fp->_sceneRect;
431 	_x = g_fp->_currentScene->_x;
432 	_y = g_fp->_currentScene->_y;
433 	_flag = 0;
434 	_mouseX = 0;
435 	_mouseY = 0;
436 	_dragX = 0;
437 	_dragY = 0;
438 	_hotSpotDelay = 12;
439 	_rect2.top = 0;
440 	_rect2.left = 0;
441 	_rect2.bottom = 600;
442 	_rect2.right = 800;
443 }
444 
~ModalMap()445 ModalMap::~ModalMap() {
446 	g_fp->_gameLoader->unloadScene(SC_MAP);
447 
448 	g_fp->_sceneRect = _rect1;
449 
450 	g_fp->_currentScene->_x = _x;
451 	g_fp->_currentScene->_y = _y;
452 }
453 
init(int counterdiff)454 bool ModalMap::init(int counterdiff) {
455 	if (_picI03)
456 		return init2(counterdiff);
457 
458 	g_fp->setCursor(PIC_CSR_ITN);
459 
460 	if (_flag) {
461 		_rect2.left = _mouseX + _dragX - g_fp->_mouseScreenPos.x;
462 		_rect2.top = _mouseY + _dragY - g_fp->_mouseScreenPos.y;
463 		_rect2.right = _rect2.left + 800;
464 		_rect2.bottom = _rect2.top + 600;
465 
466 		g_fp->_sceneRect = _rect2;
467 
468 		_mapScene->updateScrolling2();
469 
470 		_rect2 = g_fp->_sceneRect;
471 	}
472 
473 	_hotSpotDelay--;
474 
475 	if (_hotSpotDelay <= 0) {
476 		_hotSpotDelay = 12;
477 
478 		if (_pic)
479 			_pic->_flags ^= 4;
480 	}
481 
482 	return _isRunning;
483 }
484 
init2(int counterdiff)485 bool ModalMap::init2(int counterdiff) {
486 	g_fp->setCursor(PIC_CSR_DEFAULT);
487 
488 	_dragX = (int)((double)_dragX * 0.6666666666666666);
489 	_dragY = (int)((double)_dragY * 0.6666666666666666);
490 
491 	if (800 - g_fp->_mouseScreenPos.x < 67) {
492 		g_fp->setCursor(PIC_CSR_GOR);
493 
494 		_dragX = g_fp->_mouseScreenPos.x - 733;
495 		_dragY = (int)((double)_dragY * 0.6666666666666666);
496 	}
497 
498 	if (g_fp->_mouseScreenPos.x < 67) {
499 		g_fp->setCursor(PIC_CSR_GOL);
500 
501 		this->_dragX = g_fp->_mouseScreenPos.x - 67;
502 		this->_dragY = (int)((double)_dragY * 0.6666666666666666);
503 	}
504 
505 	if (g_fp->_mouseScreenPos.y < 67) {
506 		g_fp->setCursor(PIC_CSR_GOU);
507 
508 		_dragX = (int)((double)_dragX * 0.6666666666666666);
509 		_dragY = g_fp->_mouseScreenPos.y - 67;
510 	}
511 
512 	if (600 - g_fp->_mouseScreenPos.y < 87) {
513 		g_fp->setCursor(PIC_CSR_GOD);
514 
515 		_dragX = (int)((double)_dragX * 0.6666666666666666);
516 		_dragY = g_fp->_mouseScreenPos.y - 513;
517 	}
518 
519 	g_fp->_sceneRect.translate(_dragX, _dragY);
520 	_mapScene->updateScrolling2();
521 	_rect2 = g_fp->_sceneRect;
522 
523 	PictureObject *hpic = getSceneHPicture(_mapScene->getPictureObjectAtPos(g_fp->_mouseVirtX, g_fp->_mouseVirtY));
524 
525 	if (hpic != _highlightedPic) {
526 		if (_highlightedPic) {
527 			_highlightedPic->_flags &= 0xFFFB;
528 			_picI03->_flags &= 0xFFFB;
529 		}
530 
531 		_highlightedPic = hpic;
532 
533 		if (hpic) {
534 			PreloadItem pitem;
535 
536 			pitem.preloadId1 = g_fp->_currentScene->_sceneId;
537 			pitem.sceneId = findMapSceneId(hpic->_id);
538 
539 			if (pitem.preloadId1 == pitem.sceneId || checkScenePass(&pitem)) {
540 				_highlightedPic->_flags |= 4;
541 
542 				g_fp->playSound(SND_CMN_070, 0);
543 			} else {
544 				const Dims d1 = _picI03->getDimensions();
545 				const Dims d2 = _highlightedPic->getDimensions();
546 
547 				_picI03->setOXY(_highlightedPic->_ox + d2.x / 2 - d1.x / 2, _highlightedPic->_oy + d2.y / 2 - d1.y / 2);
548 				_picI03->_flags |= 4;
549 			}
550 		}
551 	}
552 
553 	if (this->_highlightedPic) {
554 		g_fp->setCursor(PIC_CSR_ITN);
555 
556 		_hotSpotDelay--;
557 
558 		if (_hotSpotDelay <= 0) {
559 			_hotSpotDelay = 12;
560 
561 			if (_pic)
562 				_pic->_flags ^= 4;
563 		}
564 	}
565 
566 	return _isRunning;
567 }
568 
findMapSceneId(int picId)569 int ModalMap::findMapSceneId(int picId) {
570 	for (uint i = 0; i < g_fp->_gameLoader->_preloadItems.size(); i++) {
571 		PreloadItem &pitem = g_fp->_gameLoader->_preloadItems[i];
572 
573 		if (pitem.preloadId1 == SC_MAP && pitem.preloadId2 == picId) {
574 			return pitem.sceneId;
575 		}
576 	}
577 
578 	return 0;
579 }
580 
581 
update()582 void ModalMap::update() {
583 	g_fp->_sceneRect = _rect2;
584 
585 	_mapScene->draw();
586 
587 	g_fp->drawArcadeOverlay(1);
588 }
589 
handleMessage(ExCommand * cmd)590 bool ModalMap::handleMessage(ExCommand *cmd) {
591 	if (cmd->_messageKind != 17)
592 		return false;
593 
594 	switch (cmd->_messageNum) {
595 	case 29:
596 		if (_picI03) {
597 			if (_highlightedPic)
598 				clickButton(_highlightedPic);
599 
600 			return false;
601 		}
602 
603 		_flag = 1;
604 		_mouseX = g_fp->_mouseScreenPos.x;
605 		_mouseY = g_fp->_mouseScreenPos.y;
606 
607 		_dragX = _rect2.left;
608 		_dragY = _rect2.top;
609 
610 		return false;
611 
612 	case 30:
613 		if (_picI03)
614 			return false;
615 
616 		_flag = 0;
617 		return false;
618 
619 	case 36:
620 		if (cmd->_param != 9 && cmd->_param != 27)
621 			return false;
622 
623 		break;
624 
625 	case 107:
626 		break;
627 
628 	default:
629 		return false;
630 	}
631 
632 	_isRunning = 0;
633 
634 	return true;
635 }
636 
initMap()637 void ModalMap::initMap() {
638 	_isRunning = 1;
639 
640 	_mapScene = g_fp->accessScene(SC_MAP);
641 
642 	if (!_mapScene)
643 		error("ModalMap::initMap(): error accessing scene SC_MAP");
644 
645 	PictureObject *pic;
646 
647 	for (int i = 0; i < 200; i++) {
648 		if (!(g_fp->_mapTable[i] >> 16))
649 			break;
650 
651 		pic = _mapScene->getPictureObjectById(g_fp->_mapTable[i] >> 16, 0);
652 
653 		if ((g_fp->_mapTable[i] & 0xffff) == 1)
654 			pic->_flags |= 4;
655 		else
656 			pic->_flags &= 0xfffb;
657 	}
658 
659 	pic = getScenePicture(g_fp->_currentScene->_sceneId);
660 
661 	if (pic) {
662 		const Dims dims = pic->getDimensions();
663 		Dims dims2;
664 
665 		_rect2.left = dims.x / 2 + pic->_ox - 400;
666 		_rect2.top = dims.y / 2 + pic->_oy - 300;
667 		_rect2.right = _rect2.left + 800;
668 		_rect2.bottom = _rect2.top + 600;
669 
670 		g_fp->_sceneRect = _rect2;
671 
672 		_mapScene->updateScrolling2();
673 
674 		_pic = _mapScene->getPictureObjectById(PIC_MAP_I02, 0);
675 		dims2 = _pic->getDimensions();
676 
677 		_pic->setOXY(pic->_ox + dims.x / 2 - dims2.x / 2, dims.y - dims2.y / 2 + pic->_oy - 24);
678 		_pic->_flags |= 4;
679 
680 		_pic = _mapScene->getPictureObjectById(PIC_MAP_I01, 0);
681 		dims2 = _pic->getDimensions();
682 
683 		_pic->setOXY(pic->_ox + dims.x / 2 - dims2.x / 2, dims.y - dims2.y / 2 + pic->_oy - 25);
684 		_pic->_flags |= 4;
685 	}
686 
687 	_picI03 = _mapScene->getPictureObjectById(PIC_MAP_I03, 0);
688 
689 	if (_picI03) {
690 		_picI03->_flags &= 0xFFFB;
691 	}
692 
693 	g_system->warpMouse(400, 300);
694 	g_fp->_mouseScreenPos.x = 400;
695 	g_fp->_mouseScreenPos.y = 300;
696 
697 	g_fp->setArcadeOverlay(PIC_CSR_MAP);
698 }
699 
clickButton(PictureObject * pic)700 void ModalMap::clickButton(PictureObject *pic) {
701 	if (g_fp->_currentScene == g_fp->_loaderScene) {
702 		_isRunning = 0;
703 		return;
704 	}
705 
706 	PreloadItem *pitem = nullptr;
707 
708 	for (uint i = 0; i < g_fp->_gameLoader->_preloadItems.size(); i++)
709 		if (g_fp->_gameLoader->_preloadItems[i].preloadId2 == SC_MAP) {
710 			pitem = &g_fp->_gameLoader->_preloadItems[i];
711 			break;
712 		}
713 
714 	if (!pitem) {
715 		PreloadItem preload;
716 
717 		preload.preloadId2 = SC_MAP;
718 		g_fp->_gameLoader->addPreloadItem(preload);
719 		pitem = &g_fp->_gameLoader->_preloadItems[g_fp->_gameLoader->_preloadItems.size() - 1];
720 	}
721 
722 	PreloadItem *pitem2 = nullptr;
723 
724 	for (uint i = 0; i < g_fp->_gameLoader->_preloadItems.size(); i++)
725 		if (g_fp->_gameLoader->_preloadItems[i].preloadId1 == SC_MAP &&
726 				g_fp->_gameLoader->_preloadItems[i].preloadId2 == pic->_id) {
727 			pitem2 = &g_fp->_gameLoader->_preloadItems[i];
728 			break;
729 		}
730 
731 	if (pitem && pitem2) {
732 		pitem->preloadId1 = g_fp->_currentScene->_sceneId;
733 		pitem->sceneId = pitem2->sceneId;
734 		pitem->param = pitem2->param;
735 
736 		if (pitem->preloadId1 == pitem2->sceneId) {
737 			_isRunning = 0;
738 		} else if (checkScenePass(pitem)) {
739 			_isRunning = 0;
740 
741 			if (!g_fp->isSaveAllowed()) {
742 				//g_fp->_gameLoader->loadAndDecryptSave("savetmp.sav");
743 			}
744 			g_fp->_gameLoader->preloadScene(pitem->preloadId1, SC_MAP);
745 		} else {
746 			g_fp->playSound(SND_CMN_056, 0);
747 		}
748 	}
749 }
750 
getScenePicture(int sceneId)751 PictureObject *ModalMap::getScenePicture(int sceneId) {
752 	int picId = 0;
753 
754 	switch (sceneId) {
755 	case SC_1:
756 		picId = PIC_MAP_S01;
757 		break;
758 	case SC_2:
759 		picId = PIC_MAP_S02;
760 		break;
761 	case SC_3:
762 		picId = PIC_MAP_S03;
763 		break;
764 	case SC_4:
765 		picId = PIC_MAP_S04;
766 		break;
767 	case SC_5:
768 		picId = PIC_MAP_S05;
769 		break;
770 	case SC_6:
771 		picId = PIC_MAP_S06;
772 		break;
773 	case SC_7:
774 		picId = PIC_MAP_S07;
775 		break;
776 	case SC_8:
777 		picId = PIC_MAP_S08;
778 		break;
779 	case SC_9:
780 		picId = PIC_MAP_S09;
781 		break;
782 	case SC_10:
783 		picId = PIC_MAP_S10;
784 		break;
785 	case SC_11:
786 		picId = PIC_MAP_S11;
787 		break;
788 	case SC_12:
789 		picId = PIC_MAP_S12;
790 		break;
791 	case SC_13:
792 		picId = PIC_MAP_S13;
793 		break;
794 	case SC_14:
795 		picId = PIC_MAP_S14;
796 		break;
797 	case SC_15:
798 		picId = PIC_MAP_S15;
799 		break;
800 	case SC_16:
801 		picId = PIC_MAP_S16;
802 		break;
803 	case SC_17:
804 		picId = PIC_MAP_S17;
805 		break;
806 	case SC_18:
807 	case SC_19:
808 		picId = PIC_MAP_S1819;
809 		break;
810 	case SC_20:
811 		picId = PIC_MAP_S20;
812 		break;
813 	case SC_21:
814 		picId = PIC_MAP_S21;
815 		break;
816 	case SC_22:
817 		picId = PIC_MAP_S22;
818 		break;
819 	case SC_23:
820 		picId = PIC_MAP_S23_1;
821 		break;
822 	case SC_24:
823 		picId = PIC_MAP_S24;
824 		break;
825 	case SC_25:
826 		picId = PIC_MAP_S25;
827 		break;
828 	case SC_26:
829 		picId = PIC_MAP_S26;
830 		break;
831 	case SC_27:
832 		picId = PIC_MAP_S27;
833 		break;
834 	case SC_28:
835 		picId = PIC_MAP_S28;
836 		break;
837 	case SC_29:
838 		picId = PIC_MAP_S29;
839 		break;
840 	case SC_30:
841 		picId = PIC_MAP_S30;
842 		break;
843 	case SC_31:
844 		picId = PIC_MAP_S31_1;
845 		break;
846 	case SC_32:
847 		picId = PIC_MAP_S32_1;
848 		break;
849 	case SC_33:
850 		picId = PIC_MAP_S33;
851 		break;
852 	case SC_34:
853 		picId = PIC_MAP_S34;
854 		break;
855 	case SC_35:
856 		picId = PIC_MAP_S35;
857 		break;
858 	case SC_36:
859 		picId = PIC_MAP_S36;
860 		break;
861 	case SC_37:
862 		picId = PIC_MAP_S37;
863 		break;
864 	case SC_38:
865 		picId = PIC_MAP_S38;
866 		break;
867 	case SC_FINAL1:
868 		picId = PIC_MAP_S38;
869 		break;
870 	}
871 
872 	if (picId)
873 		return _mapScene->getPictureObjectById(picId, 0);
874 
875 	error("ModalMap::getScenePicture(): Unknown scene id: %d", g_fp->_currentScene->_sceneId);
876 }
877 
getSceneHPicture(PictureObject * obj)878 PictureObject *ModalMap::getSceneHPicture(PictureObject *obj) {
879 	if (!obj)
880 		return NULL;
881 
882 	switch (obj->_id) {
883 	case PIC_MAP_S01:
884  		return _mapScene->getPictureObjectById(PIC_MAP_H01, 0);
885 	case PIC_MAP_S02:
886 		return _mapScene->getPictureObjectById(PIC_MAP_H02, 0);
887 	case PIC_MAP_S03:
888 		return _mapScene->getPictureObjectById(PIC_MAP_H03, 0);
889 	case PIC_MAP_S04:
890 		return _mapScene->getPictureObjectById(PIC_MAP_H04, 0);
891 	case PIC_MAP_S05:
892 		return _mapScene->getPictureObjectById(PIC_MAP_H05, 0);
893 	case PIC_MAP_S06:
894 		return _mapScene->getPictureObjectById(PIC_MAP_H06, 0);
895 	case PIC_MAP_S07:
896 		return _mapScene->getPictureObjectById(PIC_MAP_H07, 0);
897 	case PIC_MAP_S09:
898 		return _mapScene->getPictureObjectById(PIC_MAP_H09, 0);
899 	case PIC_MAP_S08:
900 		return _mapScene->getPictureObjectById(PIC_MAP_H08, 0);
901 	case PIC_MAP_S10:
902 		return _mapScene->getPictureObjectById(PIC_MAP_H10, 0);
903 	case PIC_MAP_S11:
904 		return _mapScene->getPictureObjectById(PIC_MAP_H11, 0);
905 	case PIC_MAP_S12:
906 		return _mapScene->getPictureObjectById(PIC_MAP_H12, 0);
907 	case PIC_MAP_S13:
908 		return _mapScene->getPictureObjectById(PIC_MAP_H13, 0);
909 	case PIC_MAP_S14:
910 		return _mapScene->getPictureObjectById(PIC_MAP_H14, 0);
911 	case PIC_MAP_S15:
912 		return _mapScene->getPictureObjectById(PIC_MAP_H15, 0);
913 	case PIC_MAP_S16:
914 		return _mapScene->getPictureObjectById(PIC_MAP_H16, 0);
915 	case PIC_MAP_S17:
916 		return _mapScene->getPictureObjectById(PIC_MAP_H17, 0);
917 	case PIC_MAP_S1819:
918 		return _mapScene->getPictureObjectById(PIC_MAP_H18, 0);
919 	case PIC_MAP_S20:
920 		return _mapScene->getPictureObjectById(PIC_MAP_H20, 0);
921 	case PIC_MAP_S21:
922 		return _mapScene->getPictureObjectById(PIC_MAP_H21, 0);
923 	case PIC_MAP_S22:
924 		return _mapScene->getPictureObjectById(PIC_MAP_H22, 0);
925 	case PIC_MAP_S23_1:
926 	case PIC_MAP_S23_2:
927 		return _mapScene->getPictureObjectById(PIC_MAP_H23, 0);
928 	case PIC_MAP_S24:
929 		return _mapScene->getPictureObjectById(PIC_MAP_H24, 0);
930 	case PIC_MAP_S25:
931 		return _mapScene->getPictureObjectById(PIC_MAP_H25, 0);
932 	case PIC_MAP_S26:
933 		return _mapScene->getPictureObjectById(PIC_MAP_H26, 0);
934 	case PIC_MAP_S27:
935 		return _mapScene->getPictureObjectById(PIC_MAP_H27, 0);
936 	case PIC_MAP_S28:
937 		return _mapScene->getPictureObjectById(PIC_MAP_H28, 0);
938 	case PIC_MAP_S29:
939 		return _mapScene->getPictureObjectById(PIC_MAP_H29, 0);
940 	case PIC_MAP_S30:
941 		return _mapScene->getPictureObjectById(PIC_MAP_H30, 0);
942 	case PIC_MAP_S31_1:
943 	case PIC_MAP_S31_2:
944 		return _mapScene->getPictureObjectById(PIC_MAP_H31, 0);
945 	case PIC_MAP_S32_1:
946 	case PIC_MAP_S32_2:
947 		return _mapScene->getPictureObjectById(PIC_MAP_H32, 0);
948 	case PIC_MAP_S33:
949 		return _mapScene->getPictureObjectById(PIC_MAP_H33, 0);
950 	case PIC_MAP_S34:
951 		return _mapScene->getPictureObjectById(PIC_MAP_H34, 0);
952 	case PIC_MAP_S35:
953 		return _mapScene->getPictureObjectById(PIC_MAP_H35, 0);
954 	case PIC_MAP_S36:
955 		return _mapScene->getPictureObjectById(PIC_MAP_H36, 0);
956 	case PIC_MAP_S37:
957 		return _mapScene->getPictureObjectById(PIC_MAP_H37, 0);
958 	case PIC_MAP_S38:
959 		return _mapScene->getPictureObjectById(PIC_MAP_H38, 0);
960 	default:
961 		return NULL;
962 	}
963 }
964 
isSceneEnabled(int sceneId)965 bool ModalMap::isSceneEnabled(int sceneId) {
966 	int id = getScenePicture(sceneId)->_id;
967 
968 	for (int i = 0; i < 200; i++) {
969 		int mapPic = g_fp->_mapTable[i] >> 16;
970 		if (!mapPic)
971 			return false;
972 
973 		if (mapPic == id)
974 			return (g_fp->_mapTable[i] & 0xffff) == 1;
975 	}
976 
977 	return false;
978 }
979 
checkScenePass(PreloadItem * item)980 bool ModalMap::checkScenePass(PreloadItem *item) {
981 	bool res = true;
982 
983 	switch (item->preloadId1) {
984 	case SC_13:
985 		if (!isSceneEnabled(SC_14))
986 			res = false;
987 		break;
988 
989 	case SC_27:
990 		if (item->sceneId == SC_25) {
991 			item->param = TrubaRight;
992 		} else {
993 			res = false;
994 		}
995 		break;
996 
997 	case SC_25:
998 		if (g_fp->getObjectState(sO_Board_25) != g_fp->getObjectEnumState(sO_Board_25, sO_NearDudesStairs)) {
999 			res = false;
1000 		}
1001 	}
1002 
1003 	switch (item->sceneId) {
1004 	case SC_13:
1005 		if (isSceneEnabled(SC_14)) {
1006 			item->param = TrubaLeft;
1007 			break;
1008 		}
1009 		item->param = TrubaUp;
1010 		break;
1011 
1012 	case SC_27:
1013 		res = false;
1014 		break;
1015 
1016 	case SC_25:
1017 		if (g_fp->getObjectState(sO_Pool) != g_fp->getObjectEnumState(sO_Pool, sO_Empty)) {
1018 			if (g_fp->getObjectState(sO_Pool) != g_fp->getObjectEnumState(sO_Pool, sO_HalfFull))
1019 				res = false;
1020 		}
1021 		break;
1022 
1023 	case SC_29:
1024 		if (isSceneEnabled(SC_30)) {
1025 			item->param = TrubaLeft;
1026 			break;
1027 		}
1028 		item->param = TrubaUp;
1029 		break;
1030 	}
1031 
1032 	if ((item->sceneId != SC_37 && item->preloadId1 != SC_37)
1033 		|| (g_fp->getObjectState(sO_Jawcrucnher) != g_fp->getObjectEnumState(sO_Jawcrucnher, sO_WithoutCarpet))) {
1034 			return res;
1035 	} else {
1036 		res = false;
1037 	}
1038 	return res;
1039 }
1040 
openMap()1041 void FullpipeEngine::openMap() {
1042 	if (!_modalObject) {
1043 		ModalMap *map = new ModalMap;
1044 
1045 		_modalObject = map;
1046 
1047 		map->initMap();
1048 	}
1049 }
1050 
ModalFinal()1051 ModalFinal::ModalFinal() {
1052 	_flags = 0;
1053 	_counter = 255;
1054 	_sfxVolume = g_fp->_sfxVolume;
1055 }
1056 
~ModalFinal()1057 ModalFinal::~ModalFinal() {
1058 	if (g_vars->sceneFinal_var01) {
1059 		g_fp->_gameLoader->unloadScene(SC_FINAL2);
1060 		g_fp->_gameLoader->unloadScene(SC_FINAL3);
1061 		g_fp->_gameLoader->unloadScene(SC_FINAL4);
1062 
1063 		g_fp->_currentScene = g_fp->accessScene(SC_FINAL1);
1064 
1065 		g_fp->stopAllSounds();
1066 
1067 		g_vars->sceneFinal_var01 = 0;
1068 	}
1069 
1070 	g_fp->_sfxVolume = _sfxVolume;
1071 }
1072 
init(int counterdiff)1073 bool ModalFinal::init(int counterdiff) {
1074 	if (g_vars->sceneFinal_var01) {
1075 		g_fp->_gameLoader->updateSystems(42);
1076 
1077 		return true;
1078 	}
1079 
1080 	if (_counter > 0) {
1081 		_flags |= 2u;
1082 
1083 		g_fp->_gameLoader->updateSystems(42);
1084 
1085 		return true;
1086 	}
1087 
1088 	unloadScenes();
1089 
1090 	g_fp->_modalObject = new ModalCredits();
1091 
1092 	return true;
1093 }
1094 
unloadScenes()1095 void ModalFinal::unloadScenes() {
1096 	g_fp->_gameLoader->unloadScene(SC_FINAL2);
1097 	g_fp->_gameLoader->unloadScene(SC_FINAL3);
1098 	g_fp->_gameLoader->unloadScene(SC_FINAL4);
1099 
1100 	g_fp->_currentScene = g_fp->accessScene(SC_FINAL1);
1101 
1102 	g_fp->stopAllSounds();
1103 }
1104 
handleMessage(ExCommand * cmd)1105 bool ModalFinal::handleMessage(ExCommand *cmd) {
1106 	if (cmd->_messageKind == 17 && cmd->_messageNum == 36 && cmd->_param == 27) {
1107 		g_fp->_modalObject = new ModalMainMenu();
1108 		g_fp->_modalObject->_parentObj = this;
1109 
1110 		return true;
1111 	}
1112 
1113 	return false;
1114 }
1115 
update()1116 void ModalFinal::update() {
1117 	if (g_fp->_currentScene) {
1118 		g_fp->_currentScene->draw();
1119 
1120 		if (_flags & 1) {
1121 			g_fp->drawAlphaRectangle(0, 0, 800, 600, 0xff - _counter);
1122 
1123 			_counter += 10;
1124 
1125 			if (_counter >= 255) {
1126 				_counter = 255;
1127 				_flags &= 0xfe;
1128 			}
1129 		} else {
1130 			if (!(_flags & 2))
1131 				return;
1132 
1133 			g_fp->drawAlphaRectangle(0, 0, 800, 600, 0xff - _counter);
1134 			_counter -= 10;
1135 
1136 			if (_counter <= 0) {
1137 				_counter = 0;
1138 				_flags &= 0xFD;
1139 			}
1140 		}
1141 
1142 		g_fp->_sfxVolume = _counter * (_sfxVolume + 3000) / 255 - 3000;
1143 
1144 		g_fp->updateSoundVolume();
1145 	}
1146 }
1147 
ModalCredits()1148 ModalCredits::ModalCredits() {
1149 	_sceneTitles = g_fp->accessScene(SC_TITLES);
1150 
1151 	_creditsPic = _sceneTitles->getPictureObjectById(PIC_TTL_CREDITS, 0);
1152 	_creditsPic->_flags |= 4;
1153 
1154 	_fadeIn = true;
1155 	_fadeOut = false;
1156 
1157 	const Dims dims = _creditsPic->getDimensions();
1158 
1159 	_countdown = dims.y / 2 + 470;
1160 	_sfxVolume = g_fp->_sfxVolume;
1161 
1162 	_currY = 630;
1163 	_maxY = -1000 - dims.y;
1164 
1165 	_currX = 400 - dims.x / 2;
1166 
1167 	_creditsPic->setOXY(_currX, _currY);
1168 }
1169 
~ModalCredits()1170 ModalCredits::~ModalCredits() {
1171 	g_fp->_gameLoader->unloadScene(SC_TITLES);
1172 
1173 	g_fp->_sfxVolume = _sfxVolume;
1174 }
1175 
handleMessage(ExCommand * cmd)1176 bool ModalCredits::handleMessage(ExCommand *cmd) {
1177 	if (cmd->_messageKind == 17 && cmd->_messageNum == 36 && cmd->_param == 27) {
1178 		_fadeIn = false;
1179 
1180 		return true;
1181 	}
1182 
1183 	return false;
1184 }
1185 
init(int counterdiff)1186 bool ModalCredits::init(int counterdiff) {
1187 	if (_fadeIn || _fadeOut) {
1188 		_countdown--;
1189 
1190 		if (_countdown < 0)
1191 			_fadeIn = false;
1192 
1193 		_creditsPic->setOXY(_currX, _currY);
1194 
1195 		if (_currY > _maxY)
1196 			_currY -= 2;
1197 	} else {
1198 		if (_parentObj)
1199 			return 0;
1200 
1201 		ModalMainMenu *menu = new ModalMainMenu;
1202 
1203 		g_fp->_modalObject = menu;
1204 
1205 		menu->_mfield_34 = 1;
1206 	}
1207 
1208 	return true;
1209 }
1210 
update()1211 void ModalCredits::update() {
1212 	if (_fadeOut) {
1213 		if (_fadeIn) {
1214 			_sceneTitles->draw();
1215 
1216 			return;
1217 		}
1218 	} else if (_fadeIn) {
1219 		g_fp->sceneFade(_sceneTitles, true);
1220 		_fadeOut = 1;
1221 
1222 		return;
1223 	}
1224 
1225 	if (_fadeOut) {
1226 		g_fp->sceneFade(_sceneTitles, false);
1227 		_fadeOut = 0;
1228 		return;
1229 	}
1230 
1231 	_sceneTitles->draw();
1232 }
1233 
ModalMainMenu()1234 ModalMainMenu::ModalMainMenu() {
1235 	_lastArea = 0;
1236 	_hoverAreaId = 0;
1237 	_mfield_34 = 0;
1238 	_scene = g_fp->accessScene(SC_MAINMENU);
1239 	_debugKeyCount = 0;
1240 	_sliderOffset = 0;
1241 	_screct.left = g_fp->_sceneRect.left;
1242 	_screct.top = g_fp->_sceneRect.top;
1243 	_screct.right = g_fp->_sceneRect.right;
1244 	_screct.bottom = g_fp->_sceneRect.bottom;
1245 
1246 	if (g_fp->_currentScene) {
1247 		_bgX = g_fp->_currentScene->_x;
1248 		_bgY = g_fp->_currentScene->_y;
1249 	} else {
1250 		_bgX = 0;
1251 		_bgY = 0;
1252 	}
1253 
1254 	g_fp->_sceneRect.top = 0;
1255 	g_fp->_sceneRect.left = 0;
1256 	g_fp->_sceneRect.right = 800;
1257 	g_fp->_sceneRect.bottom = 600;
1258 
1259 	MenuArea *area;
1260 
1261 	_areas.push_back(MenuArea());
1262 	area = &_areas.back();
1263 	area->picIdL = PIC_MNU_EXIT_L;
1264 	area->picObjD = 0;
1265 	area->picObjL = _scene->getPictureObjectById(area->picIdL, 0);
1266 	area->picObjL->_flags &= 0xFFFB;
1267 
1268 	_areas.push_back(MenuArea());
1269 	area = &_areas.back();
1270 	area->picIdL = PIC_MNU_CONTINUE_L;
1271 	area->picObjD = 0;
1272 	area->picObjL = _scene->getPictureObjectById(area->picIdL, 0);
1273 	area->picObjL->_flags &= 0xFFFB;
1274 
1275 	if (isSaveAllowed()) {
1276 		_areas.push_back(MenuArea());
1277 		area = &_areas.back();
1278 		area->picIdL = PIC_MNU_SAVE_L;
1279 		area->picObjD = 0;
1280 		area->picObjL = _scene->getPictureObjectById(area->picIdL, 0);
1281 		area->picObjL->_flags &= 0xFFFB;
1282 	}
1283 
1284 	_areas.push_back(MenuArea());
1285 	area = &_areas.back();
1286 	area->picIdL = PIC_MNU_LOAD_L;
1287 	area->picObjD = 0;
1288 	area->picObjL = _scene->getPictureObjectById(area->picIdL, 0);
1289 	area->picObjL->_flags &= 0xFFFB;
1290 
1291 	_areas.push_back(MenuArea());
1292 	area = &_areas.back();
1293 	area->picIdL = PIC_MNU_RESTART_L;
1294 	area->picObjD = 0;
1295 	area->picObjL = _scene->getPictureObjectById(area->picIdL, 0);
1296 	area->picObjL->_flags &= 0xFFFB;
1297 
1298 	_areas.push_back(MenuArea());
1299 	area = &_areas.back();
1300 	area->picIdL = PIC_MNU_AUTHORS_L;
1301 	area->picObjD = 0;
1302 	area->picObjL = _scene->getPictureObjectById(area->picIdL, 0);
1303 	area->picObjL->_flags &= 0xFFFB;
1304 
1305 	_areas.push_back(MenuArea());
1306 	area = &_areas.back();
1307 	area->picIdL = PIC_MNU_SLIDER_L;
1308 	area->picObjD = _scene->getPictureObjectById(PIC_MNU_SLIDER_D, 0);
1309 	area->picObjD->_flags |= 4;
1310 	area->picObjL = _scene->getPictureObjectById(area->picIdL, 0);
1311 	area->picObjL->_flags &= 0xFFFB;
1312 
1313 	_menuSliderIdx = _areas.size() - 1;
1314 
1315 	_areas.push_back(MenuArea());
1316 	area = &_areas.back();
1317 	area->picIdL = PIC_MNU_MUSICSLIDER_L;
1318 	area->picObjD = _scene->getPictureObjectById(PIC_MNU_MUSICSLIDER_D, 0);
1319 	area->picObjD->_flags |= 4;
1320 	area->picObjL = _scene->getPictureObjectById(area->picIdL, 0);
1321 	area->picObjL->_flags &= 0xFFFB;
1322 
1323 	_musicSliderIdx = _areas.size() - 1;
1324 
1325 	if (g_fp->_mainMenu_debugEnabled)
1326 		enableDebugMenuButton();
1327 
1328 	setSliderPos();
1329 }
1330 
update()1331 void ModalMainMenu::update() {
1332 	_scene->draw();
1333 }
1334 
handleMessage(ExCommand * message)1335 bool ModalMainMenu::handleMessage(ExCommand *message) {
1336 	if (message->_messageKind != 17)
1337 		return false;
1338 
1339 	if (!_scene)
1340 		return false;
1341 
1342 	Common::Point point;
1343 
1344 	if (message->_messageNum == 29) {
1345 		point.x = message->_x;
1346 		point.y = message->_y;
1347 
1348 		int numarea = checkHover(point);
1349 
1350 		if (numarea >= 0) {
1351 			if (numarea == _menuSliderIdx) {
1352 				_lastArea = &_areas[_menuSliderIdx];
1353 				_sliderOffset = _lastArea->picObjL->_ox - point.x;
1354 
1355 				return false;
1356 			}
1357 
1358 			if (numarea == _musicSliderIdx) {
1359 				_lastArea = &_areas[_musicSliderIdx];
1360 				_sliderOffset = _lastArea->picObjL->_ox - point.x;
1361 
1362 				return false;
1363 			}
1364 
1365 			_hoverAreaId = _areas[numarea].picIdL;
1366 		}
1367 
1368 		return false;
1369 	}
1370 
1371 	if (message->_messageNum == 30) {
1372 		if (_lastArea)
1373 			_lastArea = 0;
1374 
1375 		return false;
1376 	}
1377 
1378 	if (message->_messageNum != 36)
1379 		return false;
1380 
1381 	if (message->_param == 27)
1382 		_hoverAreaId = PIC_MNU_CONTINUE_L;
1383 	else
1384 		enableDebugMenu(message->_param);
1385 
1386 	return false;
1387 }
1388 
init(int counterdiff)1389 bool ModalMainMenu::init(int counterdiff) {
1390 	switch (_hoverAreaId) {
1391 	case PIC_MNU_RESTART_L:
1392 		g_fp->restartGame();
1393 
1394 		if (this == g_fp->_modalObject)
1395 			return false;
1396 
1397 		delete this;
1398 		break;
1399 
1400 	case PIC_MNU_EXIT_L:
1401 		{
1402 			ModalQuery *mq = new ModalQuery();
1403 
1404 			g_fp->_modalObject = mq;
1405 
1406 			mq->_parentObj = this;
1407 			mq->create(_scene, _scene, PIC_MEX_BGR);
1408 
1409 			_hoverAreaId = 0;
1410 
1411 			return true;
1412 		}
1413 
1414 	case PIC_MNU_DEBUG_L:
1415 		g_fp->_gameLoader->unloadScene(SC_MAINMENU);
1416 		_scene = nullptr;
1417 		g_fp->_sceneRect = _screct;
1418 
1419 		if (!g_fp->_currentScene)
1420 			error("ModalMainMenu::init: Bad state");
1421 
1422 		g_fp->_currentScene->_x = _bgX;
1423 		g_fp->_currentScene->_y = _bgY;
1424 
1425 		g_fp->_gameLoader->preloadScene(g_fp->_currentScene->_sceneId, SC_DBGMENU);
1426 
1427 		return false;
1428 
1429 	case PIC_MNU_CONTINUE_L:
1430 		if (!_mfield_34) {
1431 			g_fp->_gameLoader->unloadScene(SC_MAINMENU);
1432 			_areas.clear();
1433 			_scene = nullptr;
1434 			g_fp->_sceneRect = _screct;
1435 
1436 			if (g_fp->_currentScene) {
1437 				g_fp->_currentScene->_x = _bgX;
1438 				g_fp->_currentScene->_y = _bgY;
1439 			}
1440 
1441 			return false;
1442 		}
1443 
1444 		g_fp->restartGame();
1445 
1446 		if (this == g_fp->_modalObject)
1447 			return false;
1448 
1449 		delete this;
1450 		break;
1451 
1452 	case PIC_MNU_AUTHORS_L:
1453 		g_fp->_modalObject = new ModalCredits();
1454 		g_fp->_modalObject->_parentObj = this;
1455 
1456 		_hoverAreaId = 0;
1457 
1458 		return true;
1459 
1460 	case PIC_MNU_SAVE_L:
1461 	case PIC_MNU_LOAD_L:
1462 		{
1463 			ModalSaveGame *sg = new ModalSaveGame();
1464 
1465 			g_fp->_modalObject = sg;
1466 			g_fp->_modalObject->_parentObj = _parentObj;
1467 
1468 			int mode = 0;
1469 			if (_hoverAreaId == PIC_MNU_SAVE_L)
1470 				mode = 1;
1471 
1472 			sg->setup(g_fp->accessScene(SC_MAINMENU), mode);
1473 			sg->setScene(g_fp->accessScene(SC_MAINMENU));
1474 
1475 			sg->_rect = _screct;
1476 			sg->_oldBgX = _bgX;
1477 			sg->_oldBgY = _bgY;
1478 
1479 			delete this;
1480 		}
1481 
1482 		break;
1483 
1484 	default:
1485 		if (_lastArea) {
1486 			updateSliderPos();
1487 		} else {
1488 			g_fp->_cursorId = PIC_CSR_DEFAULT;
1489 
1490 			int idx = checkHover(g_fp->_mouseScreenPos);
1491 
1492 			if (idx < 0)
1493 				goto LABEL_40;
1494 
1495 			g_fp->_cursorId = PIC_CSR_DEFAULT;
1496 
1497 			if (idx != this->_menuSliderIdx && idx != this->_musicSliderIdx )
1498 				goto LABEL_40;
1499 		}
1500 
1501 		g_fp->_cursorId = PIC_CSR_LIFT;
1502 
1503 	LABEL_40:
1504 		g_fp->setCursor(g_fp->_cursorId);
1505 
1506 		updateVolume();
1507 
1508 		return true;
1509 	}
1510 
1511 	return true;
1512 }
1513 
updateVolume()1514 void ModalMainMenu::updateVolume() {
1515 	if (g_fp->_soundEnabled) {
1516 		for (int s = 0; s < g_fp->_currSoundListCount; s++)
1517 			for (int i = 0; i < g_fp->_currSoundList1[s]->getCount(); i++) {
1518 				updateSoundVolume(g_fp->_currSoundList1[s]->getSoundByIndex(i));
1519 			}
1520 	}
1521 }
1522 
updateSoundVolume(Sound & snd)1523 void ModalMainMenu::updateSoundVolume(Sound &snd) {
1524 	if (!snd._objectId)
1525 		return;
1526 
1527 	StaticANIObject *ani = g_fp->_currentScene->getStaticANIObject1ById(snd._objectId, -1);
1528 	if (!ani)
1529 		return;
1530 
1531 	int a, b;
1532 
1533 	if (ani->_ox >= _screct.left) {
1534 		int par, pan;
1535 
1536 		if (ani->_ox <= _screct.right) {
1537 			int dx;
1538 
1539 			if (ani->_oy <= _screct.bottom) {
1540 				if (ani->_oy >= _screct.top) {
1541 					snd.setPanAndVolume(g_fp->_sfxVolume, 0);
1542 
1543 					return;
1544 				}
1545 				dx = _screct.top - ani->_oy;
1546 			} else {
1547 				dx = ani->_oy - _screct.bottom;
1548 			}
1549 
1550 			par = 0;
1551 
1552 			if (dx > 800) {
1553 				snd.setPanAndVolume(-3500, 0);
1554 				return;
1555 			}
1556 
1557 			pan = -3500;
1558 			a = g_fp->_sfxVolume - (-3500);
1559 			b = 800 - dx;
1560 		} else {
1561 			int dx = ani->_ox - _screct.right;
1562 
1563 			if (dx > 800) {
1564 				snd.setPanAndVolume(-3500, 0);
1565 				return;
1566 			}
1567 
1568 			pan = -3500;
1569 			par = dx * (-3500) / -800;
1570 			a = g_fp->_sfxVolume - (-3500);
1571 			b = 800 - dx;
1572 		}
1573 
1574 		int32 pp = b * a;
1575 
1576 		snd.setPanAndVolume(pan + pp / 800, par);
1577 
1578 		return;
1579 	}
1580 
1581 	int dx = _screct.left - ani->_ox;
1582 	if (dx <= 800) {
1583 		int32 s = (800 - dx) * (g_fp->_sfxVolume - (-3500));
1584 		int32 p = -3500 + s / 800;
1585 
1586 		if (p > g_fp->_sfxVolume)
1587 			p = g_fp->_sfxVolume;
1588 
1589 		snd.setPanAndVolume(p, dx * (-3500) / 800);
1590 	} else {
1591 		snd.setPanAndVolume(-3500, 0);
1592 	}
1593 }
1594 
updateSliderPos()1595 void ModalMainMenu::updateSliderPos() {
1596 	if (_lastArea->picIdL == PIC_MNU_SLIDER_L) {
1597 		int x = g_fp->_mouseScreenPos.x + _sliderOffset;
1598 
1599 		if (x >= 65) {
1600 			if (x > 238)
1601 				x = 238;
1602 		} else {
1603 			x = 65;
1604 		}
1605 
1606 		_lastArea->picObjD->setOXY(x, _lastArea->picObjD->_oy);
1607 		_lastArea->picObjL->setOXY(x, _lastArea->picObjD->_oy);
1608 
1609 		int vol = 1000 * (3 * x - 195);
1610 		g_fp->_sfxVolume = vol / 173 - 3000;
1611 
1612 		if (!(vol / 173))
1613 			g_fp->_sfxVolume = -10000;
1614 
1615 		g_fp->updateSoundVolume();
1616 	} else if (_lastArea->picIdL == PIC_MNU_MUSICSLIDER_L) {
1617 		int x = g_fp->_mouseScreenPos.x + _sliderOffset;
1618 
1619 		if (x >= 65) {
1620 			if (x > 238)
1621 				x = 238;
1622 		} else {
1623 			x = 65;
1624 		}
1625 
1626 		_lastArea->picObjD->setOXY(x, _lastArea->picObjD->_oy);
1627 		_lastArea->picObjL->setOXY(x, _lastArea->picObjD->_oy);
1628 
1629 		g_fp->setMusicVolume(255 * (x - 65) / 173);
1630 	}
1631 }
1632 
checkHover(Common::Point & point)1633 int ModalMainMenu::checkHover(Common::Point &point) {
1634 	for (uint i = 0; i < _areas.size(); i++) {
1635 		if (_areas[i].picObjL->isPixelHitAtPos(point.x, point.y)) {
1636 			_areas[i].picObjL->_flags |= 4;
1637 
1638 			return i;
1639 		} else {
1640 			_areas[i].picObjL->_flags &= 0xFFFB;
1641 		}
1642 	}
1643 
1644 	if (isOverArea(_areas[_menuSliderIdx].picObjL, &point)) {
1645 		_areas[_menuSliderIdx].picObjL->_flags |= 4;
1646 
1647 		return _menuSliderIdx;
1648 	}
1649 
1650 	if (isOverArea(_areas[_musicSliderIdx].picObjL, &point)) {
1651 		_areas[_musicSliderIdx].picObjL->_flags |= 4;
1652 
1653 		return _musicSliderIdx;
1654 	}
1655 
1656 	return -1;
1657 }
1658 
isOverArea(PictureObject * obj,Common::Point * point)1659 bool ModalMainMenu::isOverArea(PictureObject *obj, Common::Point *point) {
1660 	const Dims dims = obj->getDimensions();
1661 
1662 	int left = point->x - 8;
1663 	int right = point->x + 12;
1664 	int down = point->y - 11;
1665 	int up = point->y + 9;
1666 
1667 	if (left >= obj->_ox && right < obj->_ox + dims.x && down >= obj->_oy && up < obj->_oy + dims.y)
1668 		return true;
1669 
1670 	return false;
1671 }
1672 
isSaveAllowed()1673 bool ModalMainMenu::isSaveAllowed() {
1674 	if (!g_fp->_isSaveAllowed)
1675 		return false;
1676 
1677 	if (g_fp->_aniMan->_flags & 0x100)
1678 		return false;
1679 
1680 	for (Common::Array<MessageQueue *>::iterator s = g_fp->_globalMessageQueueList->begin(); s != g_fp->_globalMessageQueueList->end(); ++s) {
1681 		if (!(*s)->_isFinished && ((*s)->getFlags() & 1))
1682 			return false;
1683 	}
1684 
1685 	return true;
1686 }
1687 
enableDebugMenu(char c)1688 void ModalMainMenu::enableDebugMenu(char c) {
1689 	const char deb[] = "debuger";
1690 
1691 	if (c == deb[_debugKeyCount]) {
1692 		_debugKeyCount++;
1693 
1694 		if (deb[_debugKeyCount] )
1695 			return;
1696 
1697 		enableDebugMenuButton();
1698 	}
1699 
1700 	_debugKeyCount = 0;
1701 }
1702 
enableDebugMenuButton()1703 void ModalMainMenu::enableDebugMenuButton() {
1704 	for (uint i = 0; i < _areas.size(); i++)
1705 		if (_areas[i].picIdL == PIC_MNU_DEBUG_L)
1706 			return;
1707 
1708 	_areas.push_back(MenuArea());
1709 	MenuArea *area = &_areas.back();
1710 	area->picIdL = PIC_MNU_DEBUG_L;
1711 	area->picObjD = 0;
1712 	area->picObjL = _scene->getPictureObjectById(area->picIdL, 0);
1713 	area->picObjL->_flags &= 0xFFFB;
1714 
1715 	g_fp->_mainMenu_debugEnabled = true;
1716 }
1717 
setSliderPos()1718 void ModalMainMenu::setSliderPos() {
1719 	int x = 173 * (g_fp->_sfxVolume + 3000) / 3000 + 65;
1720 	PictureObject *obj = _areas[_menuSliderIdx].picObjD;
1721 
1722 	if (x >= 65) {
1723 		if (x > 238)
1724 			x = 238;
1725 	} else {
1726 		x = 65;
1727 	}
1728 
1729 	obj->setOXY(x, obj->_oy);
1730 	_areas[_menuSliderIdx].picObjL->setOXY(x, obj->_oy);
1731 
1732 	x = 173 * g_fp->_musicVolume / 255 + 65;
1733 	obj = _areas[_musicSliderIdx].picObjD;
1734 
1735 	if (x >= 65) {
1736 		if (x > 238)
1737 			x = 238;
1738 	} else {
1739 		x = 65;
1740 	}
1741 
1742 	obj->setOXY(x, obj->_oy);
1743 	_areas[_musicSliderIdx].picObjL->setOXY(x, obj->_oy);
1744 }
1745 
ModalHelp()1746 ModalHelp::ModalHelp() {
1747 	_mainMenuScene = 0;
1748 	_bg = 0;
1749 	_isRunning = false;
1750 	_rect = g_fp->_sceneRect;
1751 	_hx = g_fp->_currentScene->_x;
1752 	_hy = g_fp->_currentScene->_y;
1753 
1754 	g_fp->_sceneRect.left = 0;
1755 	g_fp->_sceneRect.bottom = 600;
1756 	g_fp->_sceneRect.top = 0;
1757 	g_fp->_sceneRect.right = 800;
1758 }
1759 
~ModalHelp()1760 ModalHelp::~ModalHelp() {
1761 	g_fp->_gameLoader->unloadScene(SC_MAINMENU);
1762 
1763 	g_fp->_sceneRect = _rect;
1764 
1765 	g_fp->_currentScene->_x = _hx;
1766 	g_fp->_currentScene->_y = _hy;
1767 }
1768 
handleMessage(ExCommand * cmd)1769 bool ModalHelp::handleMessage(ExCommand *cmd) {
1770 	if (cmd->_messageKind == 17) {
1771 		int msg = cmd->_messageNum;
1772 
1773 		if (msg == 29 || msg == 36 || msg == 107) {
1774 			_isRunning = 0;
1775 
1776 			return true;
1777 		}
1778 	}
1779 
1780 	return false;
1781 }
1782 
init(int counterdiff)1783 bool ModalHelp::init(int counterdiff) {
1784 	g_fp->setCursor(PIC_CSR_DEFAULT);
1785 
1786 	return _isRunning;
1787 }
1788 
update()1789 void ModalHelp::update() {
1790 	g_fp->_sceneRect.left = 0;
1791 	g_fp->_sceneRect.top = 0;
1792 	g_fp->_sceneRect.right = 800;
1793 	g_fp->_sceneRect.bottom = 600;
1794 
1795 	_bg->draw(0, 0, 0, 0);
1796 }
1797 
launch()1798 void ModalHelp::launch() {
1799 	_mainMenuScene = g_fp->accessScene(SC_MAINMENU);
1800 
1801 	if (_mainMenuScene) {
1802 		if (g_fp->isDemo() && g_fp->getLanguage() == Common::RU_RUS)
1803 			_bg = _mainMenuScene->getPictureObjectById(364, 0)->_picture.get();
1804 		else
1805 			_bg = _mainMenuScene->getPictureObjectById(PIC_HLP_BGR, 0)->_picture.get();
1806 		_isRunning = 1;
1807 	}
1808 }
1809 
ModalQuery()1810 ModalQuery::ModalQuery() {
1811 	_bgScene = 0;
1812 	_bg = 0;
1813 	_okBtn = 0;
1814 	_cancelBtn = 0;
1815 	_queryResult = -1;
1816 }
1817 
~ModalQuery()1818 ModalQuery::~ModalQuery() {
1819 	_bg->_flags &= 0xFFFB;
1820 	_cancelBtn->_flags &= 0xFFFB;
1821 	_okBtn->_flags &= 0xFFFB;
1822 }
1823 
create(Scene * sc,Scene * bgScene,int id)1824 bool ModalQuery::create(Scene *sc, Scene *bgScene, int id) {
1825 	if (g_fp->isDemo() && g_fp->getLanguage() == Common::RU_RUS) {
1826 		_bg = sc->getPictureObjectById(386, 0);
1827 
1828 		if (!_bg)
1829 			return false;
1830 
1831 		_okBtn = sc->getPictureObjectById(392, 0);
1832 
1833 		if (!_okBtn)
1834 			return false;
1835 
1836 		_cancelBtn = sc->getPictureObjectById(396, 0);
1837 
1838 		if (!_cancelBtn)
1839 			return 0;
1840 
1841 		_queryResult = -1;
1842 		_bgScene = bgScene;
1843 
1844 		return true;
1845 	}
1846 
1847 	if (id == PIC_MEX_BGR) {
1848 		_bg = sc->getPictureObjectById(PIC_MEX_BGR, 0);
1849 
1850 		if (!_bg)
1851 			return false;
1852 
1853 		_okBtn = sc->getPictureObjectById(PIC_MEX_OK, 0);
1854 
1855 		if (!_okBtn)
1856 			return false;
1857 
1858 		_cancelBtn = sc->getPictureObjectById(PIC_MEX_CANCEL, 0);
1859 
1860 		if (!_cancelBtn)
1861 			return false;
1862 	} else {
1863 		if (id != PIC_MOV_BGR)
1864 			return false;
1865 
1866 		_bg = sc->getPictureObjectById(PIC_MOV_BGR, 0);
1867 
1868 		if (!_bg)
1869 			return false;
1870 
1871 		_okBtn = sc->getPictureObjectById(PIC_MOV_OK, 0);
1872 
1873 		if (!_okBtn)
1874 			return false;
1875 
1876 		_cancelBtn = sc->getPictureObjectById(PIC_MOV_CANCEL, 0);
1877 
1878 		if (!_cancelBtn)
1879 			return false;
1880 	}
1881 
1882 	_queryResult = -1;
1883 	_bgScene = bgScene;
1884 
1885 	return true;
1886 }
1887 
update()1888 void ModalQuery::update() {
1889 	if (_bgScene)
1890 		_bgScene->draw();
1891 
1892 	_bg->draw();
1893 
1894 	if (_okBtn->_flags & 4)
1895 		_okBtn->draw();
1896 
1897 	if (_cancelBtn->_flags & 4)
1898 		_cancelBtn->draw();
1899 }
1900 
handleMessage(ExCommand * cmd)1901 bool ModalQuery::handleMessage(ExCommand *cmd) {
1902 	if (cmd->_messageKind == 17) {
1903 		if (cmd->_messageNum == 29) {
1904 			if (_okBtn->isPointInside(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y)) {
1905 				_queryResult = 1;
1906 
1907 				return false;
1908 			}
1909 
1910 			if (_cancelBtn->isPointInside(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y))
1911 				_queryResult = 0;
1912 		} else if (cmd->_messageNum == 36 && cmd->_param == 27) {
1913 			_queryResult = 0;
1914 
1915 			return false;
1916 		}
1917 	}
1918 
1919 	return false;
1920 }
1921 
init(int counterdiff)1922 bool ModalQuery::init(int counterdiff) {
1923 	if (_okBtn->isPointInside(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y))
1924 		_okBtn->_flags |= 4;
1925 	else
1926 		_okBtn->_flags &= 0xFFFB;
1927 
1928 	if (_cancelBtn->isPointInside(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y))
1929 		_cancelBtn->_flags |= 4;
1930 	else
1931 		_cancelBtn->_flags &= 0xFFFB;
1932 
1933 	if (_queryResult == -1) {
1934 		return true;
1935 	} else {
1936 		if (g_fp->isDemo() && g_fp->getLanguage() == Common::RU_RUS) {
1937 			if (!_queryResult)
1938 				return false;
1939 
1940 			ModalDemo *demo = new ModalDemo;
1941 			demo->launch();
1942 
1943 			g_fp->_modalObject = demo;
1944 
1945 			return true;
1946 		}
1947 
1948 		if (_bg->_id == PIC_MEX_BGR) {
1949 			_cancelBtn->_flags &= 0xFFFB;
1950 			_okBtn->_flags &= 0xFFFB;
1951 
1952 			if (_queryResult == 1) {
1953 				if (_bgScene)
1954 					g_fp->sceneFade(_bgScene, false);
1955 
1956 				g_fp->_gameContinue = false;
1957 
1958 				return false;
1959 			}
1960 		}
1961 	}
1962 
1963 	return false;
1964 }
1965 
ModalSaveGame()1966 ModalSaveGame::ModalSaveGame() {
1967 	_oldBgX = 0;
1968 	_oldBgY = 0;
1969 
1970 	_bgr = 0;
1971 	_okD = 0;
1972 	_okL = 0;
1973 	_cancelD = 0;
1974 	_cancelL = 0;
1975 	_emptyD = 0;
1976 	_emptyL = 0;
1977 	_fullD = 0;
1978 	_fullL = 0;
1979 	_menuScene = 0;
1980 	_queryRes = -1;
1981 	_rect = g_fp->_sceneRect;
1982 	_queryDlg = 0;
1983 	_mode = 1;
1984 
1985 	_objtype = kObjTypeModalSaveGame;
1986 }
1987 
~ModalSaveGame()1988 ModalSaveGame::~ModalSaveGame() {
1989 	g_fp->_sceneRect = _rect;
1990 }
1991 
setScene(Scene * sc)1992 void ModalSaveGame::setScene(Scene *sc) {
1993 	_queryRes = -1;
1994 	_menuScene = sc;
1995 }
1996 
processKey(int key)1997 void ModalSaveGame::processKey(int key) {
1998 	if (key == 27)
1999 		_queryRes = 0;
2000 }
2001 
init(int counterdiff)2002 bool ModalSaveGame::init(int counterdiff) {
2003 	if (_queryDlg) {
2004 		if (!_queryDlg->init(counterdiff)) {
2005 			if (!_queryDlg->getQueryResult())
2006 				_queryRes = -1;
2007 
2008 			delete _queryDlg;
2009 			_queryDlg = 0;
2010 		}
2011 
2012 		return true;
2013 	}
2014 
2015 	if (_queryRes == -1)
2016 		return true;
2017 
2018 	g_fp->_sceneRect = _rect;
2019 
2020 	if (g_fp->_currentScene) {
2021 		g_fp->_currentScene->_x = _oldBgX;
2022 		g_fp->_currentScene->_y = _oldBgY;
2023 	}
2024 
2025 	if (!_queryRes) {
2026 		ModalMainMenu *m = new ModalMainMenu;
2027 
2028 		g_fp->_modalObject = m;
2029 
2030 		m->_parentObj = _parentObj;
2031 		m->_screct = _rect;
2032 		m->_bgX = _oldBgX;
2033 		m->_bgY = _oldBgY;
2034 
2035 		delete this;
2036 
2037 		return true;
2038 	}
2039 
2040 	return false;
2041 }
2042 
setup(Scene * sc,int mode)2043 void ModalSaveGame::setup(Scene *sc, int mode) {
2044 	_files.clear();
2045 	_arrayL.clear();
2046 	_arrayD.clear();
2047 	_mode = mode;
2048 
2049 	if (mode) {
2050 		_bgr = sc->getPictureObjectById(PIC_MSV_BGR, 0);
2051 		_cancelD = sc->getPictureObjectById(PIC_MSV_CANCEL_D, 0);
2052 		_cancelL = sc->getPictureObjectById(PIC_MSV_CANCEL_L, 0);
2053 		_okD = sc->getPictureObjectById(PIC_MSV_OK_D, 0);
2054 		_okL = sc->getPictureObjectById(PIC_MSV_OK_L, 0);
2055 		_emptyD = sc->getPictureObjectById(PIC_MSV_EMPTY_D, 0);
2056 		_emptyL = sc->getPictureObjectById(PIC_MSV_EMPTY_L, 0);
2057 	} else {
2058 		_bgr = sc->getPictureObjectById(PIC_MLD_BGR, 0);
2059 		_cancelD = sc->getPictureObjectById(PIC_MLD_CANCEL_D, 0);
2060 		_cancelL = sc->getPictureObjectById(PIC_MLD_CANCEL_L, 0);
2061 		_okD = sc->getPictureObjectById(PIC_MLD_OK_D, 0);
2062 		_okL = sc->getPictureObjectById(PIC_MLD_OK_L, 0);
2063 		_emptyD = sc->getPictureObjectById(PIC_MSV_EMPTY_D, 0);
2064 		_emptyL = sc->getPictureObjectById(PIC_MSV_EMPTY_D, 0);
2065 	}
2066 
2067 	_fullD = sc->getPictureObjectById(PIC_MSV_FULL_D, 0);
2068 	_fullL = sc->getPictureObjectById(PIC_MSV_FULL_L, 0);
2069 	_queryRes = -1;
2070 
2071 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_0_D, 0));
2072 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_0_L, 0));
2073 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_1_D, 0));
2074 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_1_L, 0));
2075 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_2_D, 0));
2076 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_2_L, 0));
2077 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_3_D, 0));
2078 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_3_L, 0));
2079 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_4_D, 0));
2080 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_4_L, 0));
2081 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_5_D, 0));
2082 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_5_L, 0));
2083 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_6_D, 0));
2084 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_6_L, 0));
2085 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_7_D, 0));
2086 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_7_L, 0));
2087 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_8_D, 0));
2088 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_8_L, 0));
2089 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_9_D, 0));
2090 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_9_L, 0));
2091 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_DOTS_D, 0));
2092 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_DOTS_L, 0));
2093 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_DOT_D, 0));
2094 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_DOT_L, 0));
2095 	_arrayL.push_back(sc->getPictureObjectById(PIC_MSV_SPACE_D, 0));
2096 	_arrayD.push_back(sc->getPictureObjectById(PIC_MSV_SPACE_L, 0));
2097 
2098 	int x = _bgr->_ox + _bgr->getDimensions().x / 2;
2099 	int y = _bgr->_oy + 90;
2100 	int w;
2101 
2102 	_files.clear();
2103 	_files.resize(7);
2104 	for (int i = 0; i < 7; i++) {
2105 		FileInfo &fileinfo = _files[i];
2106 
2107 		Common::strlcpy(fileinfo.filename, getSavegameFile(i), sizeof(fileinfo.filename));
2108 
2109 		if (!getFileInfo(i, &fileinfo)) {
2110 			fileinfo.empty = true;
2111 			w = _emptyD->getDimensions().x;
2112 		} else {
2113 			w = 0;
2114 
2115 			for (uint j = 0; j < _arrayL.size(); j++) {
2116 				w += _arrayL[j]->getDimensions().x + 2;
2117 			}
2118 		}
2119 
2120 		fileinfo.fx1 = x - w / 2;
2121 		fileinfo.fx2 = x + w / 2;
2122 		fileinfo.fy1 = y;
2123 		fileinfo.fy2 = y + _emptyD->getDimensions().y;
2124 		y = fileinfo.fy2 + 3;
2125 	}
2126 }
2127 
getSaveName()2128 char *ModalSaveGame::getSaveName() {
2129 	if (_queryRes < 0)
2130 		return 0;
2131 
2132 	return _files[_queryRes - 1].filename;
2133 }
2134 
getFileInfo(int slot,FileInfo * fileinfo)2135 bool ModalSaveGame::getFileInfo(int slot, FileInfo *fileinfo) {
2136 	Common::ScopedPtr<Common::InSaveFile> f(g_system->getSavefileManager()->openForLoading(
2137 		Fullpipe::getSavegameFile(slot)));
2138 
2139 	if (!f)
2140 		return false;
2141 
2142 	Fullpipe::FullpipeSavegameHeader header;
2143 	if (!Fullpipe::readSavegameHeader(f.get(), header))
2144 		return false;
2145 
2146 	// Create the return descriptor
2147 	SaveStateDescriptor desc(slot, header.saveName);
2148 	char res[17];
2149 
2150 	Fullpipe::parseSavegameHeader(header, desc);
2151 
2152 	snprintf(res, sizeof(res), "%s %s", desc.getSaveDate().c_str(), desc.getSaveTime().c_str());
2153 
2154 	for (int i = 0; i < 16; i++) {
2155 		switch (res[i]) {
2156 		case '-':
2157 		case '.':
2158 			fileinfo->date[i] = 11;
2159 			break;
2160 		case ' ':
2161 			fileinfo->date[i] = 12;
2162 			break;
2163 		case ':':
2164 			fileinfo->date[i] = 10;
2165 			break;
2166 		case '0':
2167 		case '1':
2168 		case '2':
2169 		case '3':
2170 		case '4':
2171 		case '5':
2172 		case '6':
2173 		case '7':
2174 		case '8':
2175 		case '9':
2176 			fileinfo->date[i] = res[i] - '0';
2177 			break;
2178 		default:
2179 			error("Incorrect date format: %s", res);
2180 		}
2181 	}
2182 
2183 	return true;
2184 }
2185 
update()2186 void ModalSaveGame::update() {
2187 	if (_menuScene)
2188 		_menuScene->draw();
2189 
2190 	_bgr->draw();
2191 
2192 	if (_queryDlg) {
2193 		_queryDlg->update();
2194 
2195 		return;
2196 	}
2197 
2198 	g_fp->_cursorId = PIC_CSR_DEFAULT;
2199 
2200 	g_fp->setCursor(g_fp->_cursorId);
2201 
2202 	for (uint i = 0; i < _files.size(); i++) {
2203 		if (g_fp->_mouseScreenPos.x < _files[i].fx1 || g_fp->_mouseScreenPos.x > _files[i].fx2 ||
2204 			g_fp->_mouseScreenPos.y < _files[i].fy1 || g_fp->_mouseScreenPos.y > _files[i].fy2 ) {
2205 			if (_files[i].empty) {
2206 				_emptyD->setOXY(_files[i].fx1, _files[i].fy1);
2207 				_emptyD->draw();
2208 			} else {
2209 				int x = _files[i].fx1;
2210 
2211 				for (int j = 0; j < 16; j++) {
2212 					_arrayL[_files[i].date[j]]->setOXY(x + 1, _files[i].fy1);
2213 					_arrayL[_files[i].date[j]]->draw();
2214 
2215 					x += _arrayL[_files[i].date[j]]->getDimensions().x + 2;
2216 				}
2217 			}
2218 		} else {
2219 			if (_files[i].empty) {
2220 				_emptyL->setOXY(_files[i].fx1, _files[i].fy1);
2221 				_emptyL->draw();
2222 			} else {
2223 				int x = _files[i].fx1;
2224 
2225 				for (int j = 0; j < 16; j++) {
2226 					_arrayD[_files[i].date[j]]->setOXY(x + 1, _files[i].fy1);
2227 					_arrayD[_files[i].date[j]]->draw();
2228 
2229 					x += _arrayD[_files[i].date[j]]->getDimensions().x + 2;
2230 				}
2231 			}
2232 		}
2233 	}
2234 	if (_cancelL->isPixelHitAtPos(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y))
2235 		_cancelL->draw();
2236 	else if (_okL->isPixelHitAtPos(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y))
2237 		_okL->draw();
2238 }
2239 
handleMessage(ExCommand * cmd)2240 bool ModalSaveGame::handleMessage(ExCommand *cmd) {
2241 	if (_queryDlg)
2242 		return _queryDlg->handleMessage(cmd);
2243 
2244 	if (cmd->_messageNum == 29)
2245 		processMouse(cmd->_x, cmd->_y);
2246 	else if (cmd->_messageNum == 36)
2247 		processKey(cmd->_param);
2248 
2249 	return false;
2250 }
2251 
processMouse(int x,int y)2252 void ModalSaveGame::processMouse(int x, int y) {
2253 	for (uint i = 0; i < _files.size(); i++) {
2254 		if (x >= _files[i].fx1 && x <= _files[i].fx2 && y >= _files[i].fy1 && y <= _files[i].fy2) {
2255 			_queryRes = i + 1;
2256 
2257 			if (_mode) {
2258 				if (!_files[i].empty) {
2259 					_queryDlg = new ModalQuery;
2260 
2261 					_queryDlg->create(_menuScene, 0, PIC_MOV_BGR);
2262 				}
2263 			}
2264 
2265 			return;
2266 		}
2267 	}
2268 
2269 	if (_cancelL->isPixelHitAtPos(x, y))
2270 		_queryRes = 0;
2271 }
2272 
saveload()2273 void ModalSaveGame::saveload() {
2274 	if (_objtype != kObjTypeModalSaveGame)
2275 		return;
2276 
2277 	if (_mode) {
2278 		if (getSaveName()) {
2279 			bool allowed = true;
2280 
2281 			for (Common::Array<MessageQueue *>::iterator s = g_fp->_globalMessageQueueList->begin(); s != g_fp->_globalMessageQueueList->end(); ++s) {
2282 				if (!(*s)->_isFinished && ((*s)->getFlags() & 1))
2283 					allowed = false;
2284 			}
2285 
2286 			if (g_fp->_isSaveAllowed && allowed)
2287 				g_fp->_gameLoader->writeSavegame(g_fp->_currentScene, getSaveName(), "");
2288 		}
2289 	} else {
2290 		if (getSaveName()) {
2291 			if (_parentObj) {
2292 				delete _parentObj;
2293 
2294 				_parentObj = 0;
2295 			}
2296 
2297 			g_fp->stopAllSoundStreams();
2298 			g_fp->stopSoundStream2();
2299 
2300 			g_fp->_gameLoader->readSavegame(getSaveName());
2301 		}
2302 	}
2303 }
2304 
ModalDemo()2305 ModalDemo::ModalDemo() {
2306 	_bg = 0;
2307 	_button = 0;
2308 	_text = 0;
2309 
2310 	if (g_fp->getLanguage() == Common::RU_RUS) {
2311 		_clickedQuit = 0;
2312 		_countdown = -10;
2313 	} else {
2314 		_clickedQuit = -1;
2315 		_countdown = 1000;
2316 	}
2317 	_scene = 0;
2318 }
2319 
~ModalDemo()2320 ModalDemo::~ModalDemo() {
2321 	if (_bg)
2322 		_bg->_flags &= 0xFFFB;
2323 
2324 	_button->_flags &= 0xFFFB;
2325 	_text->_flags &= 0xFFFB;
2326 }
2327 
launch()2328 bool ModalDemo::launch() {
2329 	Scene *sc = g_fp->accessScene(SC_MAINMENU);
2330 
2331 	if (g_fp->getLanguage() == Common::RU_RUS) {
2332 		_scene = sc;
2333 
2334 		for (uint i = 1; i < sc->_picObjList.size(); i++) {
2335 			if (sc->_picObjList[i]->_id == 399)
2336 				sc->_picObjList[i]->_flags |= 4;
2337 			else
2338 				sc->_picObjList[i]->_flags &= 0xFFFB;
2339 		}
2340 
2341 		_button = sc->getPictureObjectById(443, 0);
2342 		_text = sc->getPictureObjectById(402, 0);
2343 
2344 		_countdown = -10;
2345 
2346 		return true;
2347 	}
2348 
2349 	_bg = sc->getPictureObjectById(PIC_POST_BGR, 0);
2350 
2351 	if (!_bg)
2352 		return false;
2353 
2354 	_button = sc->getPictureObjectById(PIC_POST_BUTTON, 0);
2355 	_text = sc->getPictureObjectById(PIC_POST_TEXT, 0);
2356 
2357 	_clickedQuit = -1;
2358 
2359 	// fadeout
2360 	warning("STUB: ModelDemo: fadeout");
2361 	update();
2362 
2363 	g_fp->stopAllSoundStreams();
2364 	g_fp->stopAllSounds();
2365 	g_fp->playSound(SND_CMN_056, 0);
2366 	g_fp->playSound(SND_CMN_069, 1);
2367 
2368 	return true;
2369 }
2370 
init(int counterDiff)2371 bool ModalDemo::init(int counterDiff) {
2372 	if (g_fp->getLanguage() == Common::RU_RUS)
2373 		return init2(counterDiff);
2374 
2375 	g_fp->_cursorId = PIC_CSR_DEFAULT;
2376 
2377 	if (_button->isPointInside(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y)) {
2378 		if (!(_button->_flags & 4))
2379 			g_fp->playSound(SND_CMN_070, 0);
2380 
2381 		_button->_flags |= 4;
2382 
2383 		g_fp->_cursorId = PIC_CSR_ITN;
2384 	} else {
2385 		_button->_flags &= 0xFFFB;
2386 	}
2387 
2388 	g_fp->setCursor(g_fp->_cursorId);
2389 
2390 	_countdown -= counterDiff;
2391 
2392 	if (_countdown <= 0)
2393 		_countdown = 1000;
2394 
2395 	if (_clickedQuit == -1)
2396 		return true;
2397 
2398 	g_system->openUrl("http://www.amazon.de/EuroVideo-Bildprogramm-GmbH-Full-Pipe/dp/B003TO51YE/ref=sr_1_1");
2399 
2400 	g_fp->_gameContinue = false;
2401 
2402 	return false;
2403 }
2404 
init2(int counterDiff)2405 bool ModalDemo::init2(int counterDiff) {
2406 	if (_clickedQuit) {
2407 		g_system->openUrl("http://pipestudio.ru/fullpipe/");
2408 
2409 		g_fp->_gameContinue = false;
2410 
2411 		return false;
2412 	}
2413 
2414 	if (_countdown > 0) {
2415 		_countdown--;
2416 	} else {
2417 		_text->_flags ^= 4;
2418 		_countdown = 24;
2419 	}
2420 
2421 	if (_button->isPointInside(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y)) {
2422 		_button->_flags |= 4;
2423 
2424 		g_fp->_cursorId = PIC_CSR_ITN;
2425 	} else {
2426 		_button->_flags &= 0xFFFB;
2427 
2428 		g_fp->_cursorId = PIC_CSR_DEFAULT;
2429 	}
2430 
2431 	return true;
2432 }
2433 
update()2434 void ModalDemo::update() {
2435 	if (g_fp->getLanguage() == Common::RU_RUS) {
2436 		if (_countdown == -10)
2437 			g_fp->sceneFade(_scene, true);
2438 
2439 		_scene->draw();
2440 
2441 		return;
2442 	}
2443 
2444 	_bg->draw();
2445 
2446 	if (_button->_flags & 4)
2447 		_button->draw();
2448 
2449 	if (_text->_flags & 4)
2450 		_text->draw();
2451 }
2452 
handleMessage(ExCommand * cmd)2453 bool ModalDemo::handleMessage(ExCommand *cmd) {
2454 	if (cmd->_messageKind != 17)
2455 		return false;
2456 
2457 	if (cmd->_messageNum == 29) {
2458 		if (_button->isPointInside(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y))
2459 			_clickedQuit = 1;
2460 	} else if (cmd->_messageNum == 36 && (cmd->_param == 27 || g_fp->getLanguage() == Common::RU_RUS)) {
2461 		_clickedQuit = 1;
2462 	}
2463 
2464 	return false;
2465 }
2466 
openHelp()2467 void FullpipeEngine::openHelp() {
2468 	if (!_modalObject) {
2469 		ModalHelp *help = new ModalHelp;
2470 
2471 		_modalObject = help;
2472 
2473 		help->launch();
2474 	}
2475 }
2476 
openMainMenu()2477 void FullpipeEngine::openMainMenu() {
2478 	if (isDemo() && getLanguage() == Common::RU_RUS) {
2479 		ModalQuery *q = new ModalQuery;
2480 
2481 		Scene *sc = accessScene(SC_MAINMENU);
2482 
2483 		q->create(sc, 0, 0);
2484 
2485 		g_fp->_modalObject = q;
2486 
2487 		return;
2488 	}
2489 	ModalMainMenu *menu = new ModalMainMenu;
2490 
2491 	menu->_parentObj = g_fp->_modalObject;
2492 
2493 	g_fp->_modalObject = menu;
2494 }
2495 
2496 } // End of namespace Fullpipe
2497