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 "voyeur/voyeur.h"
24 #include "voyeur/staticres.h"
25 #include "voyeur/animation.h"
26 
27 namespace Voyeur {
28 
playStamp()29 void VoyeurEngine::playStamp() {
30 	_stampLibPtr = NULL;
31 	_filesManager->openBoltLib("stampblt.blt", _stampLibPtr);
32 
33 	_stampLibPtr->getBoltGroup(0);
34 	_controlPtr->_state = _stampLibPtr->boltEntry(_controlPtr->_stateId >> 16)._stateResource;
35 	assert(_controlPtr->_state);
36 
37 	_resolvePtr = &RESOLVE_TABLE[0];
38 	initStamp();
39 
40 	PtrResource *threadsList = _stampLibPtr->boltEntry(3)._ptrResource;
41 	_mainThread = threadsList->_entries[0]->_threadResource;
42 	_mainThread->initThreadStruct(0, 0);
43 
44 	_voy->_isAM = false;
45 	_gameHour = 9;
46 	_gameMinute = 0;
47 	_voy->_abortInterface = true;
48 
49 	int buttonId;
50 	bool breakFlag = false;
51 	while (!breakFlag && !shouldQuit()) {
52 		_voyeurArea = AREA_NONE;
53 		_eventsManager->getMouseInfo();
54 		_playStampGroupId = _currentVocId = -1;
55 		_audioVideoId = -1;
56 
57 		_mainThread->parsePlayCommands();
58 
59 		bool flag = breakFlag = (_voy->_eventFlags & EVTFLAG_2) != 0;
60 
61 		switch (_voy->_playStampMode) {
62 		case 5:
63 			buttonId = _mainThread->doInterface();
64 			if (shouldQuit())
65 				return;
66 
67 			if (buttonId == -2) {
68 				switch (_mainThread->doApt()) {
69 				case 0:
70 					_voy->_aptLoadMode = 140;
71 					break;
72 				case 1:
73 					_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
74 					_voy->_abortInterface = true;
75 					_mainThread->chooseSTAMPButton(22);
76 					_voy->_aptLoadMode = 143;
77 					break;
78 				case 2:
79 					_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
80 					reviewTape();
81 					_voy->_abortInterface = true;
82 					_voy->_aptLoadMode = 142;
83 					break;
84 				case 3:
85 					_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
86 					_mainThread->chooseSTAMPButton(21);
87 					break;
88 				case 4:
89 					breakFlag = true;
90 					_eventsManager->_mouseClicked = false;
91 					break;
92 				case 5:
93 					doGossip();
94 					_voy->_abortInterface = true;
95 					_voy->_aptLoadMode = 141;
96 					_voy->_eventFlags &= ~EVTFLAG_100;
97 					break;
98 				default:
99 					break;
100 				}
101 			} else {
102 				_mainThread->chooseSTAMPButton(buttonId);
103 			}
104 
105 			flag = true;
106 			break;
107 
108 		case 6:
109 			_mainThread->doRoom();
110 			flag = true;
111 			break;
112 
113 		case 16:
114 			_voy->_transitionId = 17;
115 			buttonId = _mainThread->doApt();
116 
117 			switch (buttonId) {
118 			case 1:
119 				_mainThread->chooseSTAMPButton(22);
120 				flag = true;
121 				break;
122 			case 2:
123 				reviewTape();
124 				_voy->_abortInterface = true;
125 				break;
126 			case 4:
127 				flag = true;
128 				breakFlag = true;
129 				break;
130 			default:
131 				break;
132 			}
133 			break;
134 
135 		case 17:
136 			// Called the police, showing the tape
137 			doTapePlaying();
138 			if (!checkForMurder() && _voy->_transitionId <= 15)
139 				checkForIncriminate();
140 
141 			if (_voy->_videoEventId != -1) {
142 				// Show the found video that is of interest to the police
143 				playAVideoEvent(_voy->_videoEventId);
144 				_voy->_eventFlags &= ~EVTFLAG_RECORDING;
145 			}
146 
147 			// Handle response
148 			_mainThread->chooseSTAMPButton(0);
149 			flag = true;
150 			break;
151 
152 		case 130: {
153 			// user selected to send the tape
154 			if (_bVoy->getBoltGroup(_playStampGroupId)) {
155 				_screen->_backgroundPage = _bVoy->boltEntry(_playStampGroupId)._picResource;
156 				_screen->_backColors = _bVoy->boltEntry(_playStampGroupId + 1)._cMapResource;
157 
158 				buttonId = getChooseButton();
159 				if (_eventsManager->_rightClick)
160 					// Aborted out of selecting a recipient
161 					buttonId = 4;
162 
163 				_bVoy->freeBoltGroup(_playStampGroupId);
164 				_screen->screenReset();
165 				_playStampGroupId = -1;
166 				flag = true;
167 
168 				if (buttonId != 4) {
169 					_voy->_playStampMode = 131;
170 					_voy->checkForKey();
171 					_mainThread->chooseSTAMPButton(buttonId);
172 				} else {
173 					_mainThread->chooseSTAMPButton(buttonId);
174 					_voy->_abortInterface = true;
175 				}
176 			}
177 			break;
178 		}
179 
180 		default:
181 			break;
182 		}
183 
184 		do {
185 			if (flag) {
186 				if (_currentVocId != -1) {
187 					_soundManager->stopVOCPlay();
188 					_currentVocId = -1;
189 				}
190 
191 				_audioVideoId = -1;
192 
193 				if (_voy->_boltGroupId2 != -1) {
194 					_bVoy->freeBoltGroup(_voy->_boltGroupId2);
195 					_voy->_boltGroupId2 = -1;
196 				}
197 
198 				if (_playStampGroupId != -1) {
199 					_bVoy->freeBoltGroup(_playStampGroupId);
200 					_playStampGroupId = -1;
201 				}
202 
203 				// Break out of loop
204 				flag = false;
205 
206 			} else if (_mainThread->_stateFlags & 2) {
207 				_eventsManager->getMouseInfo();
208 				_mainThread->chooseSTAMPButton(0);
209 				flag = true;
210 			} else {
211 				_mainThread->chooseSTAMPButton(0);
212 				flag = true;
213 			}
214 		} while (flag);
215 	}
216 
217 	_voy->_viewBounds = nullptr;
218 	closeStamp();
219 	_stampLibPtr->freeBoltGroup(0);
220 	delete _stampLibPtr;
221 }
222 
initStamp()223 void VoyeurEngine::initStamp() {
224 	_stampFlags &= ~1;
225 	_stackGroupPtr = _controlGroupPtr;
226 
227 	if (!_controlPtr->_entries[0])
228 		error("No control entries");
229 
230 	ThreadResource::initUseCount();
231 }
232 
closeStamp()233 void VoyeurEngine::closeStamp() {
234 	ThreadResource::unloadAllStacks(this);
235 }
236 
doTailTitle()237 void VoyeurEngine::doTailTitle() {
238 	_screen->_vPort->setupViewPort(NULL);
239 	_screen->screenReset();
240 
241 	if (_bVoy->getBoltGroup(0x600)) {
242 		if (!getIsDemo()) {
243 			RL2Decoder decoder;
244 			decoder.loadRL2File("a1100200.rl2", false);
245 			decoder.start();
246 			decoder.play(this);
247 		}
248 
249 		if (!shouldQuit() && !_eventsManager->_mouseClicked) {
250 			doClosingCredits();
251 
252 			if (!shouldQuit() && !_eventsManager->_mouseClicked) {
253 				_screen->screenReset();
254 
255 				PictureResource *pic = _bVoy->boltEntry(0x602)._picResource;
256 				CMapResource *pal = _bVoy->boltEntry(0x603)._cMapResource;
257 
258 				_screen->_vPort->setupViewPort(pic);
259 				pal->startFade();
260 				flipPageAndWaitForFade();
261 				_eventsManager->delayClick(300);
262 
263 				pic = _bVoy->boltEntry(0x604)._picResource;
264 				pal = _bVoy->boltEntry(0x605)._cMapResource;
265 
266 				_screen->_vPort->setupViewPort(pic);
267 				pal->startFade();
268 				flipPageAndWaitForFade();
269 				_eventsManager->delayClick(120);
270 
271 				_soundManager->stopVOCPlay();
272 			}
273 		}
274 
275 		_bVoy->freeBoltGroup(0x600);
276 	}
277 
278 	if (!shouldQuit()) {
279 		_bVoy->getBoltGroup(0x100);
280 		doPiracy();
281 	}
282 }
283 
doClosingCredits()284 void VoyeurEngine::doClosingCredits() {
285 	if (!_bVoy->getBoltGroup(0x400))
286 		return;
287 
288 	const char *msg = (const char *)_bVoy->memberAddr(0x404);
289 	const byte *creditList = (const byte *)_bVoy->memberAddr(0x405);
290 
291 	_screen->_vPort->setupViewPort(NULL);
292 	_screen->setColor(1, 180, 180, 180);
293 	_screen->setColor(2, 200, 200, 200);
294 	_eventsManager->_intPtr._hasPalette = true;
295 
296 	_screen->_fontPtr->_curFont = _bVoy->boltEntry(0x402)._fontResource;
297 	_screen->_fontPtr->_foreColor = 2;
298 	_screen->_fontPtr->_backColor = 2;
299 	_screen->_fontPtr->_fontSaveBack = false;
300 	_screen->_fontPtr->_fontFlags = DISPFLAG_NONE;
301 
302 	_soundManager->startVOCPlay(152);
303 	FontInfoResource &fi = *_screen->_fontPtr;
304 
305 	for (int idx = 0; idx < 78; ++idx) {
306 		const byte *entry = creditList + idx * 6;
307 		int flags = READ_LE_UINT16(entry + 4);
308 
309 		if (flags & 0x10)
310 			_screen->_vPort->fillPic(0);
311 
312 		if (flags & 1) {
313 			fi._foreColor = 1;
314 			fi._curFont = _bVoy->boltEntry(0x402)._fontResource;
315 			fi._justify = ALIGN_CENTER;
316 			fi._justifyWidth = 384;
317 			fi._justifyHeight = 240;
318 			fi._pos = Common::Point(0, READ_LE_UINT16(entry));
319 
320 			_screen->_vPort->drawText(msg);
321 			msg += strlen(msg) + 1;
322 		}
323 
324 		if (flags & 0x40) {
325 			fi._foreColor = 2;
326 			fi._curFont = _bVoy->boltEntry(0x400)._fontResource;
327 			fi._justify = ALIGN_CENTER;
328 			fi._justifyWidth = 384;
329 			fi._justifyHeight = 240;
330 			fi._pos = Common::Point(0, READ_LE_UINT16(entry));
331 
332 			_screen->_vPort->drawText(msg);
333 			msg += strlen(msg) + 1;
334 		}
335 
336 		if (flags & 2) {
337 			fi._foreColor = 1;
338 			fi._curFont = _bVoy->boltEntry(0x400)._fontResource;
339 			fi._justify = ALIGN_LEFT;
340 			fi._justifyWidth = 384;
341 			fi._justifyHeight = 240;
342 			fi._pos = Common::Point(38, READ_LE_UINT16(entry));
343 
344 			_screen->_vPort->drawText(msg);
345 			msg += strlen(msg) + 1;
346 
347 			fi._foreColor = 2;
348 			fi._justify = ALIGN_LEFT;
349 			fi._justifyWidth = 384;
350 			fi._justifyHeight = 240;
351 			fi._pos = Common::Point(198, READ_LE_UINT16(entry));
352 
353 			_screen->_vPort->drawText(msg);
354 			msg += strlen(msg) + 1;
355 		}
356 
357 		if (flags & 4) {
358 			fi._foreColor = 1;
359 			fi._curFont = _bVoy->boltEntry(0x402)._fontResource;
360 			fi._justify = ALIGN_CENTER;
361 			fi._justifyWidth = 384;
362 			fi._justifyHeight = 240;
363 			fi._pos = Common::Point(0, READ_LE_UINT16(entry));
364 
365 			_screen->_vPort->drawText(msg);
366 			msg += strlen(msg) + 1;
367 
368 			fi._foreColor = 2;
369 			fi._curFont = _bVoy->boltEntry(0x400)._fontResource;
370 			fi._justify = ALIGN_CENTER;
371 			fi._justifyWidth = 384;
372 			fi._justifyHeight = 240;
373 			fi._pos = Common::Point(0, READ_LE_UINT16(entry) + 13);
374 
375 			_screen->_vPort->drawText(msg);
376 			msg += strlen(msg) + 1;
377 		}
378 
379 		if (flags & 0x20) {
380 			flipPageAndWait();
381 			_eventsManager->delayClick(READ_LE_UINT16(entry + 2) * 60);
382 		}
383 
384 		if (shouldQuit() || _eventsManager->_mouseClicked)
385 			break;
386 	}
387 
388 	_soundManager->stopVOCPlay();
389 	_screen->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
390 	_bVoy->freeBoltGroup(0x400);
391 }
392 
doPiracy()393 void VoyeurEngine::doPiracy() {
394 	_screen->screenReset();
395 	_screen->setColor(1, 0, 0, 0);
396 	_screen->setColor(2, 255, 255, 255);
397 	_eventsManager->_intPtr._hasPalette = true;
398 	_screen->_vPort->setupViewPort(NULL);
399 	_screen->_vPort->fillPic(1);
400 
401 	FontInfoResource &fi = *_screen->_fontPtr;
402 	fi._curFont = _bVoy->boltEntry(0x101)._fontResource;
403 	fi._foreColor = 2;
404 	fi._backColor = 2;
405 	fi._fontSaveBack = false;
406 	fi._fontFlags = DISPFLAG_NONE;
407 	fi._justify = ALIGN_CENTER;
408 	fi._justifyWidth = 384;
409 	fi._justifyHeight = 230;
410 
411 	// Loop through the piracy message array to draw each line
412 	for (int idx = 0, yp = 33; idx < 10; ++idx) {
413 		fi._pos = Common::Point(0, yp);
414 		_screen->_vPort->drawText(PIRACY_MESSAGE[idx]);
415 
416 		yp += fi._curFont->_fontHeight + 4;
417 	}
418 
419 	flipPageAndWait();
420 	_eventsManager->getMouseInfo();
421 	_eventsManager->delayClick(720);
422 }
423 
reviewTape()424 void VoyeurEngine::reviewTape() {
425 	int eventStart = 0;
426 	int newX = -1;
427 	int newY = -1;
428 	int eventLine = 7;
429 	Common::Rect tempRect(58, 30, 58 + 223, 30 + 124);
430 	Common::Point pt;
431 	int foundIndex;
432 
433 	_bVoy->getBoltGroup(0x900);
434 	PictureResource *cursor = _bVoy->boltEntry(0x903)._picResource;
435 
436 	if ((_voy->_eventCount - 8) != 0)
437 		eventStart = MAX(_voy->_eventCount - 8, 0);
438 
439 	if ((eventStart + _voy->_eventCount) <= 7)
440 		eventLine = eventStart + _voy->_eventCount - 1;
441 
442 	bool breakFlag = false;
443 	while (!shouldQuit() && !breakFlag) {
444 		_voy->_viewBounds = _bVoy->boltEntry(0x907)._rectResource;
445 		Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(0x906)._rectResource->_entries;
446 
447 		_screen->_backColors = _bVoy->boltEntry(0x902)._cMapResource;
448 		_screen->_backgroundPage = _bVoy->boltEntry(0x901)._picResource;
449 		_screen->_vPort->setupViewPort(_screen->_backgroundPage);
450 		_screen->_backColors->startFade();
451 
452 		flipPageAndWaitForFade();
453 
454 		_screen->setColor(1, 32, 32, 32);
455 		_screen->setColor(2, 96, 96, 96);
456 		_screen->setColor(3, 160, 160, 160);
457 		_screen->setColor(4, 224, 224, 224);
458 		_screen->setColor(9, 24, 64, 24);
459 		_screen->setColor(10, 64, 132, 64);
460 		_screen->setColor(11, 100, 192, 100);
461 		_screen->setColor(12, 120, 248, 120);
462 		_eventsManager->setCursorColor(128, 1);
463 
464 		_eventsManager->_intPtr._hasPalette = true;
465 		_screen->_fontPtr->_curFont = _bVoy->boltEntry(0x909)._fontResource;
466 		_screen->_fontPtr->_fontSaveBack = false;
467 		_screen->_fontPtr->_fontFlags = DISPFLAG_NONE;
468 
469 		_eventsManager->getMouseInfo();
470 		if (newX == -1) {
471 			_eventsManager->setMousePos(Common::Point(hotspots[1].left + 12, hotspots[1].top + 6));
472 		} else {
473 			_eventsManager->setMousePos(Common::Point(newX, newY));
474 		}
475 
476 		_currentVocId = 151;
477 		_voy->_vocSecondsOffset = 0;
478 		bool needRedraw = true;
479 		do {
480 			if (_currentVocId != -1 && !_soundManager->getVOCStatus()) {
481 				_voy->_musicStartTime = _voy->_RTVNum;
482 				_soundManager->startVOCPlay(_currentVocId);
483 			}
484 
485 			if (needRedraw) {
486 				needRedraw = false;
487 				flipPageAndWait();
488 
489 				_screen->_drawPtr->_penColor = 0;
490 				_screen->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top);
491 				_screen->_backgroundPage->sFillBox(tempRect.width(), tempRect.height());
492 
493 				int yp = 45;
494 				int eventNum = eventStart;
495 				for (int lineNum = 0; lineNum < 8 && eventNum < _voy->_eventCount; ++lineNum, ++eventNum) {
496 					_screen->_fontPtr->_picFlags = DISPFLAG_NONE;
497 					_screen->_fontPtr->_picSelect = 0xff;
498 					_screen->_fontPtr->_picPick = 7;
499 					_screen->_fontPtr->_picOnOff = (lineNum == eventLine) ? 8 : 0;
500 					_screen->_fontPtr->_pos = Common::Point(68, yp);
501 					_screen->_fontPtr->_justify = ALIGN_LEFT;
502 					_screen->_fontPtr->_justifyWidth = 0;
503 					_screen->_fontPtr->_justifyHeight = 0;
504 
505 					Common::String msg = _eventsManager->getEvidString(eventNum);
506 					_screen->_backgroundPage->drawText(msg);
507 
508 					yp += 15;
509 				}
510 
511 				_screen->_vPort->addSaveRect(
512 					_screen->_vPort->_lastPage, tempRect);
513 				flipPageAndWait();
514 
515 				_screen->_vPort->addSaveRect(
516 					_screen->_vPort->_lastPage, tempRect);
517 			}
518 
519 			_screen->sDrawPic(cursor, _screen->_vPort,
520 				_eventsManager->getMousePos());
521 			flipPageAndWait();
522 
523 			_eventsManager->getMouseInfo();
524 			foundIndex = -1;
525 
526 			Common::Point tempPos = _eventsManager->getMousePos() + Common::Point(14, 7);
527 			for (uint idx = 0; idx < hotspots.size(); ++idx) {
528 				if (hotspots[idx].contains(tempPos)) {
529 					// Found hotspot area
530 					foundIndex = idx;
531 					break;
532 				}
533 			}
534 
535 			pt = _eventsManager->getMousePos();
536 			if (tempPos.x >= 68 && tempPos.x <= 277 && tempPos.y >= 31 && tempPos.y <= 154) {
537 				tempPos.y -= 2;
538 				foundIndex = (tempPos.y - 31) / 15;
539 				if ((tempPos.y - 31) % 15 >= 12 || (eventStart + foundIndex) >= _voy->_eventCount) {
540 					_eventsManager->setCursorColor(128, 0);
541 					foundIndex = 999;
542 				} else if (!_eventsManager->_leftClick) {
543 					_eventsManager->setCursorColor(128, 2);
544 					foundIndex = -1;
545 				} else {
546 					_eventsManager->setCursorColor(128, 2);
547 					eventLine =  foundIndex;
548 
549 					flipPageAndWait();
550 
551 					_screen->_drawPtr->_penColor = 0;
552 					_screen->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top);
553 					_screen->_backgroundPage->sFillBox(tempRect.width(), tempRect.height());
554 
555 					int yp = 45;
556 					int eventNum = eventStart;
557 					for (int idx = 0; idx < 8 && eventNum < _voy->_eventCount; ++idx, ++eventNum) {
558 						_screen->_fontPtr->_picFlags = DISPFLAG_NONE;
559 						_screen->_fontPtr->_picSelect = 0xff;
560 						_screen->_fontPtr->_picPick = 7;
561 						_screen->_fontPtr->_picOnOff = (idx == eventLine) ? 8 : 0;
562 						_screen->_fontPtr->_pos = Common::Point(68, yp);
563 						_screen->_fontPtr->_justify = ALIGN_LEFT;
564 						_screen->_fontPtr->_justifyWidth = 0;
565 						_screen->_fontPtr->_justifyHeight = 0;
566 
567 						Common::String msg = _eventsManager->getEvidString(eventNum);
568 						_screen->_backgroundPage->drawText(msg);
569 
570 						yp += 15;
571 					}
572 
573 					_screen->_vPort->addSaveRect(
574 						_screen->_vPort->_lastPage, tempRect);
575 					flipPageAndWait();
576 
577 					_screen->_vPort->addSaveRect(
578 						_screen->_vPort->_lastPage, tempRect);
579 					flipPageAndWait();
580 
581 					_eventsManager->getMouseInfo();
582 					foundIndex = -1;
583 				}
584 			} else if ((_voy->_eventFlags & EVTFLAG_40) && _voy->_viewBounds->left == pt.x &&
585 					_voy->_viewBounds->bottom == pt.y) {
586 				foundIndex = 999;
587 			} else if ((_voy->_eventFlags & EVTFLAG_40) && _voy->_viewBounds->left == pt.x &&
588 					_voy->_viewBounds->top == pt.y) {
589 				foundIndex = 998;
590 			} else {
591 				_eventsManager->setCursorColor(128, (foundIndex == -1) ? 0 : 1);
592 			}
593 
594 			_eventsManager->_intPtr._hasPalette = true;
595 
596 			if (_eventsManager->_mouseClicked) {
597 				switch (foundIndex) {
598 				case 2:
599 					if (eventStart > 0) {
600 						--eventStart;
601 						needRedraw = true;
602 					}
603 					foundIndex = -1;
604 					break;
605 
606 				case 3:
607 					if (eventStart > 0) {
608 						eventStart -= 8;
609 						if (eventStart < 0)
610 							eventStart = 0;
611 						needRedraw = true;
612 					}
613 					foundIndex = -1;
614 					break;
615 
616 				case 4:
617 					if ((_voy->_eventCount - 8) > eventStart) {
618 						++eventStart;
619 						needRedraw = true;
620 					}
621 					foundIndex = -1;
622 					break;
623 
624 				case 5:
625 					if (_voy->_eventCount >= 8 && (_voy->_eventCount - 8) != eventStart) {
626 						eventStart += 8;
627 						if ((_voy->_eventCount - 8) < eventStart)
628 							eventStart = _voy->_eventCount - 8;
629 						needRedraw = true;
630 					}
631 					foundIndex = -1;
632 					break;
633 
634 				default:
635 					break;
636 				}
637 
638 				while (eventLine > 0 && (eventLine + eventStart) >= _voy->_eventCount)
639 					--eventLine;
640 			}
641 
642 			pt = _eventsManager->getMousePos();
643 			if (_eventsManager->_mouseClicked && _voy->_viewBounds->left == pt.x &&
644 					(_voy->_eventFlags & EVTFLAG_40) && _eventsManager->_rightClick) {
645 				_controlPtr->_state->_victimIndex = (pt.y / 60) + 1;
646 				foundIndex = -1;
647 				_eventsManager->_rightClick = 0;
648 			}
649 
650 			if (_eventsManager->_rightClick)
651 				foundIndex = 0;
652 
653 		} while (!shouldQuit() && (!_eventsManager->_mouseClicked || foundIndex == -1));
654 
655 		if (shouldQuit())
656 			return;
657 
658 		newY = _eventsManager->getMousePos().y;
659 		_voy->_fadingType = 0;
660 		_voy->_viewBounds = nullptr;
661 		_screen->_vPort->setupViewPort(NULL);
662 
663 		if (_currentVocId != -1) {
664 			_voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime;
665 			_soundManager->stopVOCPlay();
666 		}
667 
668 		// Break out if the exit button was pressed
669 		if (!foundIndex)
670 			break;
671 
672 		int eventIndex = eventStart + eventLine;
673 		VoyeurEvent &e = _voy->_events[eventIndex];
674 		switch (e._type) {
675 		case EVTYPE_VIDEO:
676 			playAVideoEvent(eventIndex);
677 			break;
678 
679 		case EVTYPE_AUDIO: {
680 			_audioVideoId = e._audioVideoId;
681 			_voy->_vocSecondsOffset = e._computerOn;
682 
683 			_bVoy->getBoltGroup(0x7F00);
684 			_screen->_backgroundPage = _bVoy->boltEntry(0x7F00 +
685 				BLIND_TABLE[_audioVideoId] * 2)._picResource;
686 			_screen->_backColors = _bVoy->boltEntry(0x7F01 +
687 				BLIND_TABLE[_audioVideoId] * 2)._cMapResource;
688 
689 			_screen->_vPort->setupViewPort(_screen->_backgroundPage);
690 			_screen->_backColors->startFade();
691 			flipPageAndWaitForFade();
692 
693 			_eventsManager->_intPtr._flashStep = 1;
694 			_eventsManager->_intPtr._flashTimer = 0;
695 			_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
696 
697 			// Play sound for the given duration
698 			_soundManager->setVOCOffset(_voy->_vocSecondsOffset);
699 			Common::String filename = _soundManager->getVOCFileName(
700 				_audioVideoId + 159);
701 			_soundManager->startVOCPlay(filename);
702 
703 			uint32 secondsDuration = e._computerOff;
704 
705 			_eventsManager->getMouseInfo();
706 			while (!_eventsManager->_mouseClicked && _soundManager->getVOCStatus() &&
707 					_soundManager->getVOCFrame() < secondsDuration) {
708 				_eventsManager->getMouseInfo();
709 				_eventsManager->delay(10);
710 			}
711 
712 			_voy->_eventFlags |= EVTFLAG_TIME_DISABLED;
713 			_soundManager->stopVOCPlay();
714 			_bVoy->freeBoltGroup(0x7F00);
715 			break;
716 		}
717 
718 		case EVTYPE_EVID:
719 			_voy->reviewAnEvidEvent(eventIndex);
720 
721 			_voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime;
722 			_soundManager->stopVOCPlay();
723 			_bVoy->getBoltGroup(0x900);
724 			break;
725 
726 		case EVTYPE_COMPUTER:
727 			_voy->reviewComputerEvent(eventIndex);
728 
729 			_voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime;
730 			_soundManager->stopVOCPlay();
731 			_bVoy->getBoltGroup(0x900);
732 			break;
733 
734 		default:
735 			break;
736 		}
737 	}
738 
739 	_screen->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
740 
741 	_screen->_vPort->fillPic(0);
742 	flipPageAndWait();
743 	_bVoy->freeBoltGroup(0x900);
744 }
745 
doGossip()746 void VoyeurEngine::doGossip() {
747 	_screen->resetPalette();
748 	_screen->screenReset();
749 
750 	if (!_bVoy->getBoltGroup(0x300))
751 		return;
752 
753 	// Load the gossip animation
754 	RL2Decoder decoder;
755 	decoder.loadRL2File("a2050100.rl2", false);
756 	decoder.start();
757 
758 	// Get the resource data for the first gossip video
759 	PictureResource *bgPic = _bVoy->boltEntry(0x300)._picResource;
760 	CMapResource *pal = _bVoy->boltEntry(0x301)._cMapResource;
761 	pal->startFade();
762 
763 	// Transfer initial background to video decoder
764 	PictureResource videoFrame(decoder.getRL2VideoTrack()->getBackSurface());
765 	bgPic->_bounds.moveTo(0, 0);
766 	_screen->sDrawPic(bgPic, &videoFrame, Common::Point(0, 0));
767 
768 	byte *frameNumsP = _bVoy->memberAddr(0x309);
769 	byte *posP = _bVoy->boltEntry(0x30A)._data;
770 
771 	// Play the initial gossip video
772 	decoder.play(this, 0x302, frameNumsP, posP);
773 	decoder.close();
774 
775 	// Reset the palette and clear the screen
776 	_screen->resetPalette();
777 	_screen->screenReset();
778 
779 	// Play interview video
780 	RL2Decoder decoder2;
781 	decoder2.loadRL2File("a2110100.rl2", true);
782 	decoder2.start();
783 
784 	_eventsManager->getMouseInfo();
785 	decoder2.play(this);
786 	decoder2.close();
787 
788 	_bVoy->freeBoltGroup(0x300);
789 	_screen->screenReset();
790 }
791 
doTapePlaying()792 void VoyeurEngine::doTapePlaying() {
793 	if (!_bVoy->getBoltGroup(0xA00))
794 		return;
795 
796 	_eventsManager->getMouseInfo();
797 	_screen->_backColors = _bVoy->boltEntry(0xA01)._cMapResource;
798 	_screen->_backgroundPage = _bVoy->boltEntry(0xA00)._picResource;
799 	PictureResource *pic = _bVoy->boltEntry(0xA02)._picResource;
800 	VInitCycleResource *cycle = _bVoy->boltEntry(0xA05)._vInitCycleResource;
801 
802 	_screen->_vPort->setupViewPort(_screen->_backgroundPage);
803 	_screen->sDrawPic(pic, _screen->_vPort, Common::Point(57, 30));
804 	_screen->_backColors->startFade();
805 	flipPageAndWaitForFade();
806 
807 	cycle->vStartCycle();
808 
809 	_soundManager->startVOCPlay("vcr.voc");
810 	while (!shouldQuit() && !_eventsManager->_mouseClicked && _soundManager->getVOCStatus()) {
811 		_eventsManager->delayClick(2);
812 	}
813 
814 	_soundManager->stopVOCPlay();
815 	cycle->vStopCycle();
816 	_bVoy->freeBoltGroup(0xA00);
817 }
818 
checkForMurder()819 bool VoyeurEngine::checkForMurder() {
820 	int oldMurderIndex = _controlPtr->_state->_victimMurderIndex;
821 
822 	for (int idx = 0; idx < _voy->_eventCount; ++idx) {
823 		VoyeurEvent &evt = _voy->_events[idx];
824 
825 		if (evt._type == EVTYPE_VIDEO) {
826 			switch (_controlPtr->_state->_victimIndex) {
827 			case 1:
828 				if (evt._audioVideoId == 41 && evt._computerOn <= 15 &&
829 						(evt._computerOff + evt._computerOn) >= 16) {
830 					_controlPtr->_state->_victimMurderIndex = 1;
831 				}
832 				break;
833 
834 			case 2:
835 				if (evt._audioVideoId == 53 && evt._computerOn <= 19 &&
836 						(evt._computerOff + evt._computerOn) >= 21) {
837 					_controlPtr->_state->_victimMurderIndex = 2;
838 				}
839 				break;
840 
841 			case 3:
842 				if (evt._audioVideoId == 50 && evt._computerOn <= 28 &&
843 						(evt._computerOff + evt._computerOn) >= 29) {
844 					_controlPtr->_state->_victimMurderIndex = 3;
845 				}
846 				break;
847 
848 			case 4:
849 				if (evt._audioVideoId == 43 && evt._computerOn <= 10 &&
850 						(evt._computerOff + evt._computerOn) >= 14) {
851 					_controlPtr->_state->_victimMurderIndex = 4;
852 				}
853 				break;
854 
855 			default:
856 				break;
857 			}
858 		}
859 
860 		if (_controlPtr->_state->_victimMurderIndex == _controlPtr->_state->_victimIndex) {
861 			_voy->_videoEventId = idx;
862 			return true;
863 		}
864 	}
865 
866 	_controlPtr->_state->_victimMurderIndex = oldMurderIndex;
867 	_voy->_videoEventId = -1;
868 	return false;
869 }
870 
checkForIncriminate()871 bool VoyeurEngine::checkForIncriminate() {
872 	_voy->_incriminatedVictimNumber = 0;
873 
874 	for (int idx = 0; idx < _voy->_eventCount; ++idx) {
875 		VoyeurEvent &evt = _voy->_events[idx];
876 
877 		if (evt._type == EVTYPE_VIDEO) {
878 			if (evt._audioVideoId == 44 && evt._computerOn <= 40 &&
879 					(evt._computerOff + evt._computerOn) >= 70) {
880 				_voy->_incriminatedVictimNumber = 1;
881 			}
882 
883 			if (evt._audioVideoId == 44 && evt._computerOn <= 79 &&
884 					(evt._computerOff + evt._computerOn) >= 129) {
885 				_voy->_incriminatedVictimNumber = 1;
886 			}
887 
888 			if (evt._audioVideoId == 20 && evt._computerOn <= 28 &&
889 					(evt._computerOff + evt._computerOn) >= 45) {
890 				_voy->_incriminatedVictimNumber = 2;
891 			}
892 
893 			if (evt._audioVideoId == 35 && evt._computerOn <= 17 &&
894 					(evt._computerOff + evt._computerOn) >= 36) {
895 				_voy->_incriminatedVictimNumber = 3;
896 			}
897 
898 			if (evt._audioVideoId == 30 && evt._computerOn <= 80 &&
899 					(evt._computerOff + evt._computerOn) >= 139) {
900 				_voy->_incriminatedVictimNumber = 4;
901 			}
902 		}
903 
904 		if (_voy->_incriminatedVictimNumber) {
905 			_controlPtr->_state->_victimMurderIndex = 88;
906 			_voy->_videoEventId = idx;
907 			return true;
908 		}
909 	}
910 
911 	_voy->_videoEventId = -1;
912 	return false;
913 }
914 
playAVideoEvent(int eventIndex)915 void VoyeurEngine::playAVideoEvent(int eventIndex) {
916 	VoyeurEvent &evt = _voy->_events[eventIndex];
917 	_audioVideoId = evt._audioVideoId;
918 	_voy->_vocSecondsOffset = evt._computerOn;
919 	_eventsManager->_videoDead = evt._dead;
920 	_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
921 
922 	playAVideoDuration(_audioVideoId, evt._computerOff);
923 
924 	_voy->_eventFlags |= EVTFLAG_TIME_DISABLED;
925 	if (_eventsManager->_videoDead != -1) {
926 		_bVoy->freeBoltGroup(0xE00);
927 		_eventsManager->_videoDead = -1;
928 		flipPageAndWait();
929 		_eventsManager->_videoDead = -1;
930 	}
931 
932 	_audioVideoId = -1;
933 	if (_eventsManager->_videoDead != -1) {
934 		_bVoy->freeBoltGroup(0xE00);
935 		_eventsManager->_videoDead = -1;
936 		flipPageAndWait();
937 	}
938 }
939 
getChooseButton()940 int VoyeurEngine::getChooseButton()  {
941 	int prevIndex = -2;
942 	Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(_playStampGroupId
943 		+ 6)._rectResource->_entries;
944 	int selectedIndex = -1;
945 
946 	_screen->_vPort->setupViewPort(_screen->_backgroundPage);
947 	_screen->_backColors->_steps = 0;
948 	_screen->_backColors->startFade();
949 	flipPageAndWait();
950 
951 	_voy->_viewBounds = _bVoy->boltEntry(_playStampGroupId + 7)._rectResource;
952 	PictureResource *cursorPic = _bVoy->boltEntry(_playStampGroupId + 2)._picResource;
953 
954 	do {
955 		do {
956 			if (_currentVocId != -1 && !_soundManager->getVOCStatus())
957 				_soundManager->startVOCPlay(_currentVocId);
958 
959 			_eventsManager->getMouseInfo();
960 			selectedIndex = -1;
961 			Common::Point pt = _eventsManager->getMousePos();
962 
963 			for (uint idx = 0; idx < hotspots.size(); ++idx) {
964 				if (hotspots[idx].contains(pt)) {
965 					if (!_voy->_victimMurdered || ((int)idx + 1) != _controlPtr->_state->_victimIndex) {
966 						selectedIndex = idx;
967 						if (selectedIndex != prevIndex) {
968 							PictureResource *btnPic = _bVoy->boltEntry(_playStampGroupId + 8 + idx)._picResource;
969 							_screen->sDrawPic(btnPic, _screen->_vPort,
970 								Common::Point(106, 200));
971 
972 							cursorPic = _bVoy->boltEntry(_playStampGroupId + 4)._picResource;
973 						}
974 					}
975 				}
976 			}
977 
978 			if (selectedIndex == -1) {
979 				cursorPic = _bVoy->boltEntry(_playStampGroupId + 2)._picResource;
980 				PictureResource *btnPic = _bVoy->boltEntry(_playStampGroupId + 12)._picResource;
981 				_screen->sDrawPic(btnPic, _screen->_vPort,
982 					Common::Point(106, 200));
983 			}
984 
985 			_screen->sDrawPic(cursorPic, _screen->_vPort,
986 				Common::Point(pt.x + 13, pt.y - 12));
987 
988 			flipPageAndWait();
989 		} while (!shouldQuit() && !_eventsManager->_mouseClicked);
990 	} while (!shouldQuit() && selectedIndex == -1 && !_eventsManager->_rightClick);
991 
992 	return selectedIndex;
993 }
994 
makeViewFinder()995 void VoyeurEngine::makeViewFinder() {
996 	_screen->_backgroundPage = _bVoy->boltEntry(0x103)._picResource;
997 	_screen->sDrawPic(_screen->_backgroundPage,
998 		_screen->_vPort, Common::Point(0, 0));
999 	CMapResource *pal = _bVoy->boltEntry(0x104)._cMapResource;
1000 
1001 	int palOffset = 0;
1002 	switch (_voy->_transitionId) {
1003 	case 1:
1004 	case 2:
1005 	case 5:
1006 	case 6:
1007 	case 7:
1008 	case 8:
1009 	case 9:
1010 	case 17:
1011 		palOffset = 0;
1012 		break;
1013 	case 3:
1014 		palOffset = 1;
1015 		break;
1016 	case 4:
1017 	case 10:
1018 	case 11:
1019 	case 12:
1020 	case 13:
1021 	case 14:
1022 	case 15:
1023 	case 16:
1024 		palOffset = 2;
1025 		break;
1026 	default:
1027 		break;
1028 	}
1029 
1030 	_screen->_vPort->drawIfaceTime();
1031 	doTimeBar();
1032 	pal->startFade();
1033 
1034 	flipPageAndWaitForFade();
1035 
1036 	_screen->setColor(241, 105, 105, 105);
1037 	_screen->setColor(242, 105, 105, 105);
1038 	_screen->setColor(243, 105, 105, 105);
1039 	_screen->setColor(palOffset + 241, 219, 235, 235);
1040 
1041 	_eventsManager->_intPtr._hasPalette = true;
1042 }
1043 
makeViewFinderP()1044 void VoyeurEngine::makeViewFinderP() {
1045 	_screen->screenReset();
1046 }
1047 
initIFace()1048 void VoyeurEngine::initIFace() {
1049 	int playStamp1 = _playStampGroupId;
1050 	switch (_voy->_transitionId) {
1051 	case 0:
1052 		break;
1053 	case 1:
1054 	case 2:
1055 	case 5:
1056 	case 6:
1057 	case 7:
1058 	case 8:
1059 	case 9:
1060 		_playStampGroupId = 0xB00;
1061 		break;
1062 	case 3:
1063 		_playStampGroupId = 0xC00;
1064 		break;
1065 	default:
1066 		_playStampGroupId = 0xD00;
1067 		break;
1068 	}
1069 	if (playStamp1 != -1)
1070 		_bVoy->freeBoltGroup(playStamp1);
1071 
1072 	_bVoy->getBoltGroup(_playStampGroupId);
1073 	CMapResource *pal = _bVoy->boltEntry(_playStampGroupId + 2)._cMapResource;
1074 	pal->startFade();
1075 
1076 	// Reset the mansion view off to it's prior position (if any)
1077 	doScroll(_mansionViewPos);
1078 
1079 	_voy->_viewBounds = _bVoy->boltEntry(_playStampGroupId)._rectResource;
1080 
1081 	// Show the cursor using ScummVM functionality
1082 	_eventsManager->showCursor();
1083 
1084 	// Note: the original did two loops to preload members here, which is
1085 	// redundant for ScummVM, since computers are faster these days, and
1086 	// getting resources as needed will be fast enough.
1087 }
1088 
doScroll(const Common::Point & pt)1089 void VoyeurEngine::doScroll(const Common::Point &pt) {
1090 	Common::Rect clipRect(72, 47, 72 + 240, 47 + 148);
1091 	_screen->_vPort->setupViewPort(NULL, &clipRect);
1092 
1093 	int base = 0;
1094 	switch (_voy->_transitionId) {
1095 	case 0:
1096 		break;
1097 	case 1:
1098 	case 2:
1099 	case 5:
1100 	case 6:
1101 	case 7:
1102 	case 8:
1103 	case 9:
1104 		base = 0xB00;
1105 		break;
1106 	case 3:
1107 		base = 0xC00;
1108 		break;
1109 	default:
1110 		base = 0xD00;
1111 	}
1112 
1113 	if (base) {
1114 		PictureResource *pic = _bVoy->boltEntry(base + 3)._picResource;
1115  		_screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y - 104));
1116 		pic = _bVoy->boltEntry(base + 4)._picResource;
1117 		_screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y - 44));
1118 		pic = _bVoy->boltEntry(base + 5)._picResource;
1119 		_screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 16));
1120 		pic = _bVoy->boltEntry(base + 6)._picResource;
1121 		_screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 76));
1122 		pic = _bVoy->boltEntry(base + 7)._picResource;
1123 		_screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 136));
1124 	}
1125 
1126 	_screen->_vPort->setupViewPort(NULL);
1127 }
1128 
checkTransition()1129 void VoyeurEngine::checkTransition() {
1130 	Common::String time, day;
1131 
1132 	if (_voy->_transitionId != _checkTransitionId) {
1133 		// Get the day
1134 		day = getDayName();
1135 
1136 		// Only proceed if a valid day string was returned
1137 		if (!day.empty()) {
1138 			_screen->fadeDownICF(6);
1139 
1140 			// Get the time of day string
1141 			time = getTimeOfDay();
1142 
1143 			// Show a transition card with the day and time, and wait
1144 			doTransitionCard(day, time);
1145 			_eventsManager->delayClick(180);
1146 		}
1147 
1148 		_checkTransitionId = _voy->_transitionId;
1149 		centerMansionView();
1150 	}
1151 }
1152 
getDayName()1153 Common::String VoyeurEngine::getDayName() {
1154 	switch (_voy->_transitionId) {
1155 	case 0:
1156 		return "";
1157 	case 1:
1158 	case 2:
1159 	case 3:
1160 	case 4:
1161 		return SATURDAY;
1162 	case 17:
1163 		return MONDAY;
1164 	default:
1165 		return SUNDAY;
1166 	}
1167 }
1168 
getTimeOfDay()1169 Common::String VoyeurEngine::getTimeOfDay() {
1170 	if (_voy->_transitionId == 17)
1171 		return "";
1172 
1173 	return Common::String::format("%d:%02d%s", _gameHour, _gameMinute, _voy->_isAM ? AM : PM);
1174 }
1175 
doComputerText(int maxLen)1176 int VoyeurEngine::doComputerText(int maxLen) {
1177 	FontInfoResource &font = *_screen->_fontPtr;
1178 	int totalChars = 0;
1179 
1180 	font._curFont = _bVoy->boltEntry(0x4910)._fontResource;
1181 	font._foreColor = 129;
1182 	font._fontSaveBack = false;
1183 	font._fontFlags = DISPFLAG_NONE;
1184 	if (_voy->_vocSecondsOffset > 60)
1185 		_voy->_vocSecondsOffset = 0;
1186 
1187 	if (_voy->_RTVNum > _voy->_computerTimeMax && maxLen == 9999) {
1188 		if (_currentVocId != -1)
1189 			_soundManager->startVOCPlay(_currentVocId);
1190 		font._justify = ALIGN_LEFT;
1191 		font._justifyWidth = 384;
1192 		font._justifyHeight = 100;
1193 		font._pos = Common::Point(128, 100);
1194 		_screen->_vPort->drawText(END_OF_MESSAGE);
1195 	} else if (_voy->_RTVNum < _voy->_computerTimeMin && maxLen == 9999) {
1196 		if (_currentVocId != -1)
1197 			_soundManager->startVOCPlay(_currentVocId);
1198 		font._justify = ALIGN_LEFT;
1199 		font._justifyWidth = 384;
1200 		font._justifyHeight = 100;
1201 		font._pos = Common::Point(120, 100);
1202 		_screen->_vPort->drawText(START_OF_MESSAGE);
1203 	} else {
1204 		char *msg = (char *)_bVoy->memberAddr(0x4900 + _voy->_computerTextId);
1205 		font._pos = Common::Point(96, 60);
1206 
1207 		bool showEnd = true;
1208 		int yp = 60;
1209 		do {
1210 			if (_currentVocId != -1 && !_soundManager->getVOCStatus()) {
1211 				if (_voy->_vocSecondsOffset > 60)
1212 					_voy->_vocSecondsOffset = 0;
1213 				_soundManager->startVOCPlay(_currentVocId);
1214 			}
1215 
1216 			char c = *msg++;
1217 			if (c == '\0') {
1218 				if (showEnd) {
1219 					_eventsManager->delay(90);
1220 					_screen->_drawPtr->_pos = Common::Point(96, 54);
1221 					_screen->_drawPtr->_penColor = 254;
1222 					_screen->_vPort->sFillBox(196, 124);
1223 					_screen->_fontPtr->_justify = ALIGN_LEFT;
1224 					_screen->_fontPtr->_justifyWidth = 384;
1225 					_screen->_fontPtr->_justifyHeight = 100;
1226 					_screen->_fontPtr->_pos = Common::Point(128, 100);
1227 					_screen->_vPort->drawText(END_OF_MESSAGE);
1228 				}
1229 				break;
1230 			}
1231 
1232 			if (c == '~' || c == '^') {
1233 				if (c == '^') {
1234 					yp += 10;
1235 				} else {
1236 					_eventsManager->delay(90);
1237 					_screen->_drawPtr->_pos = Common::Point(96, 54);
1238 					_screen->_drawPtr->_penColor = 255;
1239 					_screen->_vPort->sFillBox(196, 124);
1240 					yp = 60;
1241 				}
1242 
1243 				_screen->_fontPtr->_pos = Common::Point(96, yp);
1244 			} else if (c == '_') {
1245 				showEnd = false;
1246 			} else {
1247 				_screen->_fontPtr->_justify = ALIGN_LEFT;
1248 				_screen->_fontPtr->_justifyWidth = 0;
1249 				_screen->_fontPtr->_justifyHeight = 0;
1250 				_screen->_vPort->drawText(Common::String(c));
1251 				_eventsManager->delay(4);
1252 			}
1253 
1254 			flipPageAndWait();
1255 			_eventsManager->getMouseInfo();
1256 			++totalChars;
1257 
1258 		} while (!shouldQuit() && !_eventsManager->_mouseClicked && totalChars < maxLen);
1259 
1260 		_voy->_computerTimeMax = 0;
1261 	}
1262 
1263 	flipPageAndWait();
1264 
1265 	_screen->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
1266 	return totalChars;
1267 }
1268 
getComputerBrush()1269 void VoyeurEngine::getComputerBrush() {
1270 	if (!_bVoy->getBoltGroup(0x4900))
1271 		return;
1272 
1273 	PictureResource *pic = _bVoy->boltEntry(0x490E)._picResource;
1274 	int xp = (384 - pic->_bounds.width()) / 2;
1275 	int yp = (240 - pic->_bounds.height()) / 2 - 4;
1276 
1277 	_screen->_vPort->drawPicPerm(pic, Common::Point(xp, yp));
1278 
1279 	CMapResource *pal = _bVoy->boltEntry(0x490F)._cMapResource;
1280 	pal->startFade();
1281 }
1282 
doTimeBar()1283 void VoyeurEngine::doTimeBar() {
1284 	flashTimeBar();
1285 
1286 	if (_voy->_RTVLimit > 0) {
1287 		if (_voy->_RTVNum > _voy->_RTVLimit || _voy->_RTVNum < 0)
1288 			_voy->_RTVNum = _voy->_RTVLimit - 1;
1289 
1290 		_timeBarVal = _voy->_RTVNum;
1291 		int height = ((_voy->_RTVLimit - _voy->_RTVNum) * 59) / _voy->_RTVLimit;
1292 		int fullHeight = MAX(151 - height, 93);
1293 
1294 		_screen->_drawPtr->_penColor = 134;
1295 		_screen->_drawPtr->_pos = Common::Point(39, 92);
1296 
1297 		_screen->_vPort->sFillBox(6, fullHeight - 92);
1298 		if (height > 0) {
1299 			_screen->setColor(215, 238, 238, 238);
1300 			_eventsManager->_intPtr._hasPalette = true;
1301 
1302 			_screen->_drawPtr->_penColor = 215;
1303 			_screen->_drawPtr->_pos = Common::Point(39, fullHeight);
1304 			_screen->_vPort->sFillBox(6, height);
1305 		}
1306 	}
1307 }
1308 
flashTimeBar()1309 void VoyeurEngine::flashTimeBar() {
1310 	if (_voy->_RTVNum >= 0 && (_voy->_RTVLimit - _voy->_RTVNum) < 11 &&
1311 		(_eventsManager->_intPtr._flashTimer >= (_flashTimeVal + 15) ||
1312 		_eventsManager->_intPtr._flashTimer < _flashTimeVal)) {
1313 		// Within camera low power range
1314 		_flashTimeVal = _eventsManager->_intPtr._flashTimer;
1315 
1316 		if (_flashTimeFlag)
1317 			_screen->setColor(240, 220, 20, 20);
1318 		else
1319 			_screen->setColor(240, 220, 220, 220);
1320 
1321 		_eventsManager->_intPtr._hasPalette = true;
1322 		_flashTimeFlag = !_flashTimeFlag;
1323 	}
1324 }
1325 
checkPhoneCall()1326 void VoyeurEngine::checkPhoneCall() {
1327 	if ((_voy->_RTVLimit - _voy->_RTVNum) >= 36 && _voy->_totalPhoneCalls < 5 &&
1328 			_currentVocId <= 151 && _currentVocId > 146) {
1329 		if ((_voy->_switchBGNum < _checkPhoneVal || _checkPhoneVal > 180) &&
1330 				!_soundManager->getVOCStatus()) {
1331 			int soundIndex;
1332 			do {
1333 				soundIndex = getRandomNumber(4);
1334 			} while (_voy->_phoneCallsReceived[soundIndex]);
1335 			_currentVocId = 154 + soundIndex;
1336 
1337 			_soundManager->stopVOCPlay();
1338 			_soundManager->startVOCPlay(_currentVocId);
1339 			_checkPhoneVal = _voy->_switchBGNum;
1340 			_voy->_phoneCallsReceived[soundIndex] = true;
1341 			++_voy->_totalPhoneCalls;
1342 		}
1343 	}
1344 }
1345 
doEvidDisplay(int evidId,int eventId)1346 void VoyeurEngine::doEvidDisplay(int evidId, int eventId) {
1347 	_eventsManager->getMouseInfo();
1348 	flipPageAndWait();
1349 
1350 	if (_currentVocId != -1) {
1351 		_voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime;
1352 		_soundManager->stopVOCPlay();
1353 	}
1354 
1355 	_bVoy->getBoltGroup(_voy->_boltGroupId2);
1356 	PictureResource *pic = _bVoy->boltEntry(_voy->_boltGroupId2 + evidId * 2)._picResource;
1357 	_screen->sDrawPic(pic, _screen->_vPort, Common::Point(
1358 		(384 - pic->_bounds.width()) / 2, (240 - pic->_bounds.height()) / 2));
1359 	_bVoy->freeBoltMember(_voy->_boltGroupId2 + evidId * 2);
1360 
1361 	CMapResource *pal = _bVoy->boltEntry(_voy->_boltGroupId2 + evidId * 2 + 1)._cMapResource;
1362 	pal->startFade();
1363 
1364 	while (!shouldQuit() && (_eventsManager->_fadeStatus & 1))
1365 		_eventsManager->delay(1);
1366 	_bVoy->freeBoltMember(_voy->_boltGroupId2 + evidId * 2 + 1);
1367 
1368 	Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(_playStampGroupId + 4)._rectResource->_entries;
1369 	int count = hotspots[evidId]._count;
1370 
1371 	if (count > 0) {
1372 		for (int idx = 1; idx <= count; ++idx) {
1373 			_voy->_evPicPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 +
1374 				(evidId + idx) * 2)._picResource;
1375 			_voy->_evCmPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 +
1376 				(evidId + idx) * 2 + 1)._cMapResource;
1377 		}
1378 	}
1379 
1380 	flipPageAndWait();
1381 	_eventsManager->stopEvidDim();
1382 
1383 	if (eventId == 999)
1384 		_voy->addEvidEventStart(evidId);
1385 
1386 	_eventsManager->getMouseInfo();
1387 
1388 	int arrIndex = 0;
1389 	int evidIdx = evidId;
1390 
1391 	while (!shouldQuit() && !_eventsManager->_rightClick) {
1392 		_voyeurArea = AREA_EVIDENCE;
1393 
1394 		if (_currentVocId != -1 && !_soundManager->getVOCStatus()) {
1395 			if (_voy->_vocSecondsOffset > 60)
1396 				_voy->_vocSecondsOffset = 0;
1397 
1398 			_soundManager->startVOCPlay(_currentVocId);
1399 		}
1400 
1401 		_eventsManager->delayClick(600);
1402 		if (_eventsManager->_rightClick)
1403 			break;
1404 		if (count == 0 || evidIdx >= eventId)
1405 			continue;
1406 
1407 		pic = _voy->_evPicPtrs[arrIndex];
1408 		_screen->sDrawPic(pic, _screen->_vPort,
1409 			Common::Point((384 - pic->_bounds.width()) / 2,
1410 			(240 - pic->_bounds.height()) / 2));
1411 		_voy->_evCmPtrs[arrIndex]->startFade();
1412 		while (!shouldQuit() && (_eventsManager->_fadeStatus & 1))
1413 			_eventsManager->delay(1);
1414 
1415 		flipPageAndWait();
1416 		_eventsManager->delay(6);
1417 
1418 		++evidIdx;
1419 		++arrIndex;
1420 		--count;
1421 	}
1422 
1423 	if (eventId == 999)
1424 		_voy->addEvidEventEnd(evidIdx);
1425 
1426 	for (int idx = 1; idx <= hotspots[evidId]._count; ++idx) {
1427 		_bVoy->freeBoltMember(_voy->_boltGroupId2 + (evidId + idx) * 2);
1428 		_bVoy->freeBoltMember(_voy->_boltGroupId2 + (evidId + idx) * 2 + 1);
1429 	}
1430 }
1431 
centerMansionView()1432 void VoyeurEngine::centerMansionView() {
1433 	_mansionViewPos = Common::Point((MANSION_MAX_X - MANSION_VIEW_WIDTH) / 2,
1434 		(MANSION_MAX_Y - MANSION_VIEW_HEIGHT) / 2);
1435 }
1436 
1437 } // End of namespace Voyeur
1438