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