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/screen.h"
24 #include "voyeur/voyeur.h"
25 #include "voyeur/staticres.h"
26 #include "engines/util.h"
27 #include "graphics/palette.h"
28 #include "graphics/surface.h"
29
30 namespace Voyeur {
31
32 /*------------------------------------------------------------------------*/
33
DrawInfo(int penColor,const Common::Point & pos)34 DrawInfo::DrawInfo(int penColor, const Common::Point &pos) {
35 _penColor = penColor;
36 _pos = pos;
37 }
38
39 /*------------------------------------------------------------------------*/
40
Screen(VoyeurEngine * vm)41 Screen::Screen(VoyeurEngine *vm) : Graphics::Screen(), _vm(vm), _drawPtr(&_defaultDrawInfo),
42 _defaultDrawInfo(1, Common::Point()) {
43 _SVGAMode = 0;
44 _planeSelect = 0;
45 _saveBack = true;
46 _clipPtr = NULL;
47 _viewPortListPtr = NULL;
48 _backgroundPage = NULL;
49 _vPort = NULL;
50 _fontPtr = NULL;
51 Common::fill(&_VGAColors[0], &_VGAColors[PALETTE_SIZE], 0);
52 _fontChar = new PictureResource(DISPFLAG_NONE, 0xff, 0xff, 0, Common::Rect(), 0, NULL, 0);
53 _backColors = nullptr;
54 }
55
sInitGraphics()56 void Screen::sInitGraphics() {
57 initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT);
58 create(SCREEN_WIDTH, SCREEN_HEIGHT);
59 clearPalette();
60 }
61
~Screen()62 Screen::~Screen() {
63 delete _fontChar;
64 }
65
setupMCGASaveRect(ViewPortResource * viewPort)66 void Screen::setupMCGASaveRect(ViewPortResource *viewPort) {
67 if (viewPort->_activePage) {
68 viewPort->_activePage->_flags |= DISPFLAG_1;
69 Common::Rect *clipRect = _clipPtr;
70 _clipPtr = &viewPort->_clipRect;
71
72 sDrawPic(viewPort->_activePage, viewPort->_currentPic, Common::Point());
73
74 _clipPtr = clipRect;
75 }
76
77 viewPort->_rectListCount[1] = -1;
78 }
79
addRectOptSaveRect(ViewPortResource * viewPort,int idx,const Common::Rect & bounds)80 void Screen::addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds) {
81 if (viewPort->_rectListCount[idx] == -1)
82 return;
83
84 // TODO: Lots of code in original, which I suspect may be overlapping rect merging
85 viewPort->_rectListPtr[idx]->push_back(bounds);
86 ++viewPort->_rectListCount[idx];
87 }
88
restoreMCGASaveRect(ViewPortResource * viewPort)89 void Screen::restoreMCGASaveRect(ViewPortResource *viewPort) {
90 if (viewPort->_rectListCount[0] != -1) {
91 for (int i = 0; i < viewPort->_rectListCount[0]; ++i) {
92 addRectOptSaveRect(viewPort, 1, (*viewPort->_rectListPtr[0])[i]);
93 }
94 } else {
95 viewPort->_rectListCount[1] = -1;
96 }
97
98 restoreBack(*viewPort->_rectListPtr[1], viewPort->_rectListCount[1], viewPort->_pages[0],
99 viewPort->_pages[1]);
100
101 int count = viewPort->_rectListCount[0];
102 restoreBack(*viewPort->_rectListPtr[0], viewPort->_rectListCount[0],
103 viewPort->_activePage, viewPort->_currentPic);
104
105 SWAP(viewPort->_rectListPtr[0], viewPort->_rectListPtr[1]);
106 viewPort->_rectListCount[1] = count;
107 }
108
addRectNoSaveBack(ViewPortResource * viewPort,int idx,const Common::Rect & bounds)109 void Screen::addRectNoSaveBack(ViewPortResource *viewPort, int idx, const Common::Rect &bounds) {
110 // Stubbed/dummy method in the original.
111 }
112
sDrawPic(DisplayResource * srcDisplay,DisplayResource * destDisplay,const Common::Point & initialOffset)113 void Screen::sDrawPic(DisplayResource *srcDisplay, DisplayResource *destDisplay,
114 const Common::Point &initialOffset) {
115 int width1, width2;
116 int widthDiff, widthDiff2;
117 int height1;
118 int srcOffset;
119 int screenOffset;
120 int srcFlags, destFlags;
121 ViewPortResource *destViewPort = NULL;
122 Common::Rect newBounds;
123 Common::Rect backBounds;
124 int tmpWidth = 0;
125 int tmpHeight = 0;
126 bool isClipped = false;
127 byte pixel = 0;
128 int runLength;
129
130 byte *srcImgData, *destImgData;
131 const byte *srcP;
132 byte *destP;
133 byte byteVal, byteVal2;
134
135 PictureResource *srcPic;
136 PictureResource *destPic;
137
138 // Get the picture parameters, or deference viewport pointers to get their pictures
139 if (srcDisplay->_flags & DISPFLAG_VIEWPORT) {
140 // A viewport was passed, not a picture
141 srcPic = ((ViewPortResource *)srcDisplay)->_currentPic;
142 } else {
143 srcPic = (PictureResource *)srcDisplay;
144 }
145
146 if (destDisplay->_flags & DISPFLAG_VIEWPORT) {
147 // A viewport was passed, not a picture
148 destViewPort = (ViewPortResource *)destDisplay;
149 destPic = destViewPort->_currentPic;
150 } else {
151 destPic = (PictureResource *)destDisplay;
152 }
153
154 Common::Point offset = Common::Point(initialOffset.x + srcPic->_bounds.left - destPic->_bounds.left,
155 initialOffset.y + srcPic->_bounds.top - destPic->_bounds.top);
156 width1 = width2 = srcPic->_bounds.width();
157 height1 = srcPic->_bounds.height();
158 srcOffset = 0;
159 srcFlags = srcPic->_flags;
160 destFlags = destPic->_flags;
161 byte *cursorData = NULL;
162
163 if (srcFlags & DISPFLAG_1) {
164 if (_clipPtr) {
165 int xs = _clipPtr->left - destPic->_bounds.left;
166 int ys = _clipPtr->top - destPic->_bounds.top;
167 newBounds = Common::Rect(xs, ys, xs + _clipPtr->width(), ys + _clipPtr->height());
168 } else if (destViewPort) {
169 int xs = destViewPort->_clipRect.left - destPic->_bounds.left;
170 int ys = destViewPort->_clipRect.top - destPic->_bounds.top;
171 newBounds = Common::Rect(xs, ys, xs + destViewPort->_clipRect.width(),
172 ys + destViewPort->_clipRect.height());
173 } else {
174 newBounds = Common::Rect(0, 0, destPic->_bounds.width(), destPic->_bounds.height());
175 }
176
177 tmpHeight = offset.y - newBounds.top;
178 if (tmpHeight < 0) {
179 srcOffset -= tmpHeight * width2;
180 height1 += tmpHeight;
181 offset.y = newBounds.top;
182
183 if (height1 <= 0)
184 return;
185
186 isClipped = true;
187 }
188
189 int yMin = newBounds.bottom - (offset.y + height1);
190 if (yMin < 0) {
191 height1 += yMin;
192 if (height1 <= 0)
193 return;
194 }
195
196 tmpWidth = offset.x - newBounds.left;
197 if (tmpWidth < 0) {
198 srcOffset -= tmpWidth;
199 width2 += tmpWidth;
200 offset.x = newBounds.left;
201
202 if (width2 <= 0)
203 return;
204
205 isClipped = true;
206 }
207
208 int xMin = newBounds.right - (offset.x + width2);
209 if (xMin < 0) {
210 width2 += xMin;
211 if (width2 <= 0)
212 return;
213
214 isClipped = true;
215 }
216 }
217
218 screenOffset = offset.y * destPic->_bounds.width() + offset.x;
219 widthDiff = width1 - width2;
220 widthDiff2 = destPic->_bounds.width() - width2;
221
222 if (destViewPort) {
223 if (!_saveBack || (srcPic->_flags & DISPFLAG_800)) {
224 backBounds.left = destPic->_bounds.left + offset.x;
225 backBounds.top = destPic->_bounds.top + offset.y;
226 backBounds.setWidth(width2);
227 backBounds.setHeight(height1);
228 addRectOptSaveRect(destViewPort, 1, backBounds);
229
230 } else if (!destViewPort->_addFn) {
231 if (destViewPort->_rectListCount[destViewPort->_pageIndex] < -1) {
232 Common::Rect r;
233 r.left = destPic->_bounds.left + offset.x;
234 r.top = destPic->_bounds.top + offset.y;
235 r.setWidth(width2);
236 r.setHeight(height1);
237
238 (*destViewPort->_rectListPtr[destViewPort->_pageIndex]).push_back(r);
239 ++destViewPort->_rectListCount[destViewPort->_pageIndex];
240 }
241 } else {
242 int xs = offset.x + destPic->_bounds.left;
243 int ys = offset.y + destPic->_bounds.top;
244 backBounds = Common::Rect(xs, ys, xs + width2, ys + height1);
245
246 (this->*destViewPort->_addFn)(destViewPort, destViewPort->_bounds.top, backBounds);
247 }
248 }
249
250 if (srcFlags & DISPFLAG_1000) {
251 int imageDataShift = 0;
252 srcImgData = srcPic->_imgData + (imageDataShift << 14);
253 for (uint idx = 0; idx < srcPic->_maskData; ++idx) {
254 if (imageDataShift < 4)
255 ++imageDataShift;
256 }
257
258 destImgData = destPic->_imgData + (imageDataShift << 14);
259 for (uint idx = 0; idx < srcPic->_maskData; ++idx) {
260 if (imageDataShift < 4)
261 ++imageDataShift;
262 }
263 } else {
264 srcImgData = srcPic->_imgData;
265 destImgData = destPic->_imgData;
266 }
267
268 if (srcPic->_select != 0xff)
269 return;
270
271 if (destFlags & DISPFLAG_CURSOR) {
272 cursorData = new byte[width2 * height1];
273 Common::fill(cursorData, cursorData + width2 * height1, 0);
274 destImgData = cursorData;
275 }
276
277 if (srcPic->_pick == 0xff) {
278 if (srcFlags & DISPFLAG_8) {
279 error("TODO: sDrawPic variation");
280 } else {
281 // loc_258B8
282 srcP = srcImgData + srcOffset;
283
284 if (destFlags & DISPFLAG_8) {
285 // loc_258D8
286 destP = destImgData + screenOffset;
287
288 if (srcFlags & DISPFLAG_2) {
289 // loc_25652
290 srcP = srcImgData + srcOffset;
291
292 if (destFlags & DISPFLAG_8) {
293 // loc_2566F
294 if (srcFlags & DISPFLAG_2) {
295 // loc_256FA
296 srcP = (const byte *)getPixels() + srcOffset;
297
298 for (int yp = 0; yp < height1; ++yp) {
299 for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
300 pixel = *srcP;
301 if (pixel)
302 *destP = pixel;
303 }
304
305 srcP += widthDiff;
306 destP += widthDiff2;
307 }
308 } else {
309 // loc_25706
310 for (int yp = 0; yp < height1; ++yp) {
311 Common::copy(srcP, srcP + width2, destP);
312 srcP += width2 + widthDiff;
313 destP += width2 + widthDiff2;
314 }
315 }
316 } else {
317 // loc_25773
318 destP = destImgData + screenOffset;
319
320 if (srcFlags & DISPFLAG_2) {
321 // loc_25793
322 for (int yp = 0; yp < height1; ++yp) {
323 Common::copy(srcP, srcP + width2, destP);
324 srcP += width2 + widthDiff;
325 destP += width2 + widthDiff2;
326 }
327 } else {
328 // loc_25829
329 destP = (byte *)getPixels() + screenOffset;
330
331 for (int yp = 0; yp < height1; ++yp) {
332 Common::copy(srcP, srcP + width2, destP);
333 srcP += width2 + widthDiff;
334 destP += width2 + widthDiff2;
335 }
336
337 addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
338 offset.y + height1));
339 }
340 }
341 } else {
342 // loc_25D40
343 if (srcFlags & DISPFLAG_100) {
344 // loc_25D4A
345 error("TODO: sDrawPic variation");
346 } else {
347 // loc_2606D
348 destP = (byte *)getPixels() + screenOffset;
349
350 for (int yp = 0; yp < height1; ++yp) {
351 Common::copy(srcP, srcP + width2, destP);
352 destP += width2 + widthDiff2;
353 srcP += width2 + widthDiff;
354 }
355
356 addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
357 offset.y + height1));
358 }
359 }
360 } else {
361 // loc_2615E
362 destP = destImgData + screenOffset;
363
364 if (srcFlags & DISPFLAG_2) {
365 // loc_2617e
366 if (srcFlags & DISPFLAG_100) {
367 // loc_26188
368 srcP = srcImgData;
369 if (isClipped) {
370 // loc_26199
371 tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
372 int xMax = tmpWidth + width2;
373 tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
374
375 width2 = srcPic->_bounds.width();
376 height1 = tmpHeight + height1;
377
378 for (int yp = 0; yp < height1; ++yp) {
379 runLength = 0;
380
381 for (int xp = 0; xp < width2; ++xp, --runLength) {
382 if (runLength <= 0) {
383 pixel = *srcP++;
384 if (pixel & 0x80) {
385 pixel &= 0x7f;
386 runLength = *srcP++;
387 if (!runLength)
388 runLength = width2;
389 }
390 }
391
392 if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
393 if (pixel > 0)
394 *destP = pixel;
395 ++destP;
396 }
397 }
398
399 if (yp >= tmpHeight)
400 destP += widthDiff2;
401 }
402 } else {
403 // loc_262BE
404 byteVal = 0;
405 for (int yp = 0; yp < height1; ++yp) {
406 for (int xp = 0; xp < width2; ++xp) {
407 byteVal2 = 0;
408 if (!byteVal2) {
409 byteVal = *++srcP;
410 if (byteVal & 0x80) {
411 byteVal &= 0x7f;
412 byteVal2 = *srcP++;
413
414 if (!byteVal2)
415 byteVal2 = width2;
416 }
417 }
418
419 if (byteVal > 0)
420 *destP = byteVal;
421
422 ++destP;
423 --byteVal2;
424 }
425
426 destP += widthDiff2;
427 }
428 }
429 } else {
430 // loc_2637F
431 // Copy with transparency
432 for (int yp = 0; yp < height1; ++yp) {
433 for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
434 if (*srcP != 0)
435 *destP = *srcP;
436 }
437
438 destP += widthDiff2;
439 srcP += widthDiff;
440 }
441 }
442 } else {
443 if (srcFlags & DISPFLAG_100) {
444 // Simple run-length encoded image
445 srcP = srcImgData;
446
447 if (isClipped) {
448 // loc_26424
449 tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
450 int xMax = tmpWidth + width2;
451 tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
452 width2 = srcPic->_bounds.width();
453 height1 = tmpHeight + height1;
454
455 for (int yp = 0; yp < height1; ++yp) {
456 runLength = 0;
457 for (int xp = 0; xp < width2; ++xp, --runLength) {
458 if (runLength <= 0) {
459 pixel = *srcP++;
460 if (pixel & 0x80) {
461 pixel &= 0x7F;
462 runLength = *srcP++;
463
464 if (!runLength)
465 runLength = width2;
466 }
467 }
468
469 if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
470 *destP++ = pixel;
471 }
472 }
473
474 if (yp >= tmpHeight)
475 destP += widthDiff2;
476 }
477 } else {
478 // loc_26543
479 for (int yp = 0; yp < height1; ++yp) {
480 int runLen = 0;
481 for (int xp = 0; xp < width2; ++xp, --runLen) {
482 if (runLen <= 0) {
483 // Start of run length, so get pixel and repeat length
484 pixel = *srcP++;
485 if (pixel & 0x80) {
486 pixel &= 0x7f;
487 runLen = *srcP++;
488 if (runLen == 0)
489 runLen = width2;
490 }
491 }
492
493 // Copy pixel to output
494 *destP++ = pixel;
495 }
496
497 destP += widthDiff2;
498 }
499 }
500 } else {
501 for (int yp = 0; yp < height1; ++yp) {
502 Common::copy(srcP, srcP + width2, destP);
503 destP += width2 + widthDiff2;
504 srcP += width2 + widthDiff;
505 }
506 }
507 }
508 }
509 }
510 } else {
511 // loc_26666
512 if (srcPic->_pick == 0) {
513 // loc_2727A
514 byte onOff = srcPic->_onOff;
515
516 if (srcFlags & DISPFLAG_2) {
517 if (!(srcFlags & DISPFLAG_8)) {
518 srcP = srcImgData + srcOffset;
519
520 if (destFlags & DISPFLAG_8) {
521 // loc_272C3
522 error("TODO: sDrawPic variation");
523 } else {
524 destP = destImgData + screenOffset;
525 for (int yp = 0; yp < height1; ++yp) {
526 for (int xp = 0; xp < width2; ++xp, ++destP) {
527 if ((int8)*srcP++ < 0)
528 *destP = onOff;
529 }
530
531 destP += widthDiff2;
532 srcP += widthDiff;
533 }
534 }
535 }
536 } else {
537 // loc_27477
538 if (destFlags & DISPFLAG_8) {
539 // loc_27481
540 destP = (byte *)getPixels() + screenOffset;
541 for (int yp = 0; yp < height1; ++yp) {
542 Common::fill(destP, destP + width2, onOff);
543 destP += width2 + widthDiff2;
544 }
545
546 addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
547 offset.y + height1));
548 } else {
549 // loc_2753C
550 destP = destImgData + screenOffset;
551
552 for (int yp = 0; yp < height1; ++yp) {
553 Common::fill(destP, destP + width2, onOff);
554 destP += width2 + widthDiff2;
555 }
556 }
557 }
558
559 } else {
560 // loc_26673
561 byte pick = srcPic->_pick;
562 byte onOff = srcPic->_onOff;
563
564 if (!(srcFlags & PICFLAG_PIC_OFFSET)) {
565 srcP = srcImgData += srcOffset;
566 pixel = 0;
567
568 if (destFlags & PICFLAG_PIC_OFFSET) {
569 destP = destImgData + screenOffset;
570 if (srcFlags & PICFLAG_2) {
571 if (srcFlags & PICFLAG_100) {
572 if (isClipped) {
573 // loc_266E3
574 destP = (byte *)getPixels() + screenOffset;
575 tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
576 int xMax = tmpWidth + width2;
577 tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
578 pick = 0x7F;
579 width2 = srcPic->_bounds.width();
580 height1 = tmpHeight + height1;
581
582 for (int yp = 0; yp < height1; ++yp) {
583 int runLen = 0;
584 for (int xp = 0; xp < width2; ++xp, --runLen) {
585 if (runLen <= 0) {
586 pixel = *srcP++;
587 if (pixel & 0x80) {
588 pixel &= 0x7F;
589 runLen = *srcP++;
590 if (!runLen)
591 runLen = width2;
592 }
593 }
594
595 if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
596 if (pixel) {
597 *destP = (pixel & pick) ^ onOff;
598 }
599 ++destP;
600 }
601 }
602 if (yp >= tmpHeight)
603 destP += widthDiff2;
604 }
605
606 addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
607 offset.y + height1));
608 } else {
609 // loc_26815
610 destP = (byte *)getPixels() + screenOffset;
611
612 for (int yp = 0; yp < height1; ++yp) {
613 for (int xi = 0; xi < width2; ++xi, ++destP) {
614 byteVal2 = 0;
615 for (int xp = 0; xp < width2; ++xp, ++destP, --byteVal2) {
616 if (!byteVal2) {
617 pixel = *srcP++;
618 if (pixel & 0x80) {
619 pixel &= 0x7F;
620 byteVal2 = *srcP++;
621 if (!byteVal2) {
622 byteVal2 = width2;
623 }
624 }
625 }
626
627 if (pixel)
628 *destP = (pixel & pick) ^ onOff;
629 }
630 }
631
632 destP += widthDiff2;
633 }
634
635 addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
636 offset.y + height1));
637 }
638 } else {
639 // Direct screen write
640 destP = (byte *)getPixels() + screenOffset;
641
642 for (int yp = 0; yp < height1; ++yp) {
643 for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
644 if (*srcP)
645 *destP = (*srcP & pick) ^ onOff;
646 }
647 destP += widthDiff2;
648 srcP += widthDiff;
649 }
650
651 addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
652 offset.y + height1));
653 }
654 } else if (srcFlags & PICFLAG_100) {
655 srcP = srcImgData;
656 if (isClipped) {
657 // loc_269FD
658 tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
659 int xMax = tmpWidth + width2;
660 tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
661 width2 = srcPic->_bounds.width();
662 height1 = tmpHeight + height1;
663
664 for (int yp = 0; yp < height1; ++yp) {
665 runLength = 0;
666 for (int xp = 0; xp < width2; ++xp, --runLength) {
667 if (runLength <= 0) {
668 pixel = *srcP++;
669 if (pixel & 0x80) {
670 pixel &= 0x7F;
671 runLength = *srcP++;
672
673 if (!runLength)
674 runLength = width2;
675 }
676 }
677
678 if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
679 *destP++ = (pixel & 0x80) ^ onOff;
680 }
681 }
682 }
683 } else {
684 // loc_26BD5
685 destP = (byte *)getPixels() + screenOffset;
686
687 for (int yp = 0; yp < height1; ++yp) {
688 byteVal2 = 0;
689
690 for (int xp = 0; xp < width2; ++xp, ++destP) {
691 if (!byteVal2) {
692 pixel = *srcP++;
693 if (pixel & 0x80) {
694 pixel &= 0x7F;
695 byteVal2 = *srcP++;
696 if (!byteVal2)
697 byteVal2 = width2;
698 }
699 }
700
701 *destP = (pixel & pick) ^ onOff;
702 }
703
704 destP += widthDiff2;
705 }
706
707 addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
708 offset.y + height1));
709 }
710 } else {
711 // loc_26C9A
712 destP = (byte *)getPixels() + screenOffset;
713
714 for (int yp = 0; yp < height1; ++yp) {
715 for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
716 *destP = (*srcP & pick) ^ onOff;
717 }
718 destP += widthDiff2;
719 srcP += widthDiff;
720 }
721
722 addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
723 offset.y + height1));
724 }
725 } else {
726 // loc_26D2F
727 destP = destImgData + screenOffset;
728
729 if (srcFlags & PICFLAG_2) {
730 // loc_26D4F
731 if (srcFlags & PICFLAG_100) {
732 srcP = srcImgData;
733
734 if (isClipped) {
735 // loc_26D6A
736 tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
737 int xMax = tmpWidth + width2;
738 tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
739 width2 = srcPic->_bounds.width();
740 height1 = tmpHeight + height1;
741
742 for (int yp = 0; yp < height1; ++yp) {
743 runLength = 0;
744
745 for (int xp = 0; xp < width2; ++xp, --runLength) {
746 if (runLength <= 0) {
747 pixel = *srcP++;
748 if (pixel & 0x80) {
749 pixel &= 0x7F;
750 runLength = *srcP++;
751 if (!runLength)
752 runLength = width2;
753 }
754 }
755
756 if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
757 if (pixel)
758 *destP = (pixel & pick) ^ onOff;
759
760 ++destP;
761 }
762 }
763
764 if (yp >= tmpHeight)
765 destP += widthDiff2;
766 }
767 } else {
768 // loc_26E95
769 for (int yp = 0; yp < height1; ++yp) {
770 byteVal2 = 0;
771 for (int xp = 0; xp < width2; ++xp, ++destP, --byteVal2) {
772 if (!byteVal2) {
773 pixel = *srcP++;
774 if (pixel & 0x80) {
775 pixel &= 0x7F;
776 byteVal2 = *srcP++;
777 if (!byteVal2)
778 byteVal2 = width2;
779 }
780 }
781
782 if (pixel)
783 *destP = (pixel & pick) ^ onOff;
784 }
785
786 destP += widthDiff2;
787 }
788 }
789 } else {
790 // loc_26F5D
791 for (int yp = 0; yp < height1; ++yp) {
792 for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
793 if (*srcP)
794 *destP = (*srcP & pick) ^ onOff;
795 }
796 destP += widthDiff2;
797 srcP += widthDiff;
798 }
799 }
800 } else {
801 // loc_26FEF
802 if (srcFlags & PICFLAG_100) {
803 // loc_26FF9
804 for (int yp = 0; yp < height1; ++yp) {
805 for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
806 *destP = (*srcP & pick) ^ onOff;
807 }
808 destP += widthDiff2;
809 srcP += widthDiff;
810 }
811 } else {
812 // loc_271F0
813 srcP = srcImgData;
814
815 if (isClipped) {
816 // loc_2700A
817 tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
818 int xMax = tmpWidth + width2;
819 tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
820 width2 = srcPic->_bounds.width();
821 height1 = tmpHeight + height1;
822
823 for (int yp = 0; yp < height1; ++yp) {
824 runLength = 0;
825
826 for (int xp = 0; xp < width2; ++xp, --runLength) {
827 if (runLength <= 0) {
828 pixel = *srcP++;
829 if (pixel & 0x80) {
830 pixel &= 0x7F;
831 runLength = *srcP++;
832 if (!runLength)
833 runLength = width2;
834 }
835 }
836
837 if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
838 *destP++ = (pixel & pick) ^ onOff;
839 }
840 }
841
842 if (yp >= tmpHeight)
843 destP += widthDiff2;
844 }
845 } else {
846 // loc_2712F
847 for (int yp = 0; yp < height1; ++yp) {
848 byteVal2 = 0;
849 for (int xp = 0; xp < width2; ++xp, ++destP, --byteVal2) {
850 if (!byteVal2) {
851 pixel = *srcP++;
852 if (pixel & 0x80) {
853 pixel &= 0x7F;
854 byteVal2 = *srcP++;
855 if (!byteVal2)
856 byteVal2 = width2;
857 }
858 }
859
860 *destP = (*srcP & pick) ^ onOff;
861 }
862 destP += widthDiff2;
863 }
864 }
865 }
866 }
867 }
868 }
869 }
870 }
871
872 if (cursorData) {
873 _vm->_eventsManager->setCursor(cursorData, width2, height1, srcPic->_keyColor);
874 delete[] cursorData;
875 }
876 }
877
drawANumber(DisplayResource * display,int num,const Common::Point & pt)878 void Screen::drawANumber(DisplayResource *display, int num, const Common::Point &pt) {
879 PictureResource *pic = _vm->_bVoy->boltEntry(num + 261)._picResource;
880 sDrawPic(pic, display, pt);
881 }
882
fillPic(DisplayResource * display,byte onOff)883 void Screen::fillPic(DisplayResource *display, byte onOff) {
884 PictureResource *pic;
885 if (display->_flags & DISPFLAG_VIEWPORT) {
886 pic = ((ViewPortResource *)display)->_currentPic;
887 } else {
888 pic = (PictureResource *)display;
889 }
890
891 PictureResource picResource;
892 picResource._flags = DISPFLAG_NONE;
893 picResource._select = 0xff;
894 picResource._pick = 0;
895 picResource._onOff = onOff;
896 picResource._bounds = pic->_bounds;
897
898 sDrawPic(&picResource, display, Common::Point());
899 }
900
901 /**
902 * Queues the given picture for display
903 */
sDisplayPic(PictureResource * pic)904 void Screen::sDisplayPic(PictureResource *pic) {
905 _vm->_eventsManager->_intPtr._flipWait = true;
906 }
907
flipPage()908 void Screen::flipPage() {
909 Common::Array<ViewPortResource *> &viewPorts = _viewPortListPtr->_entries;
910 bool flipFlag = false;
911
912 for (uint idx = 0; idx < viewPorts.size(); ++idx) {
913 if (viewPorts[idx]->_flags & DISPFLAG_20) {
914 flipFlag = false;
915 if ((viewPorts[idx]->_flags & DISPFLAG_8) && (viewPorts[idx]->_flags & DISPFLAG_1)) {
916 if (_planeSelect == idx)
917 sDisplayPic(viewPorts[idx]->_currentPic);
918 flipFlag = true;
919 }
920 }
921
922 if (flipFlag) {
923 ViewPortResource &viewPort = *viewPorts[idx];
924
925 viewPort._lastPage = viewPort._pageIndex;
926 ++viewPort._pageIndex;
927
928 if (viewPort._pageIndex >= viewPort._pageCount)
929 viewPort._pageIndex = 0;
930
931 assert(viewPort._pageIndex < 2);
932 viewPort._currentPic = viewPort._pages[viewPort._pageIndex];
933 viewPort._flags = (viewPort._flags & ~DISPFLAG_8) | DISPFLAG_40;
934 }
935 }
936 }
937
restoreBack(Common::Array<Common::Rect> & rectList,int rectListCount,PictureResource * srcPic,PictureResource * destPic)938 void Screen::restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount,
939 PictureResource *srcPic, PictureResource *destPic) {
940 // WORKAROUND: Since _backgroundPage can point to a resource freed at the end of display methods,
941 // I'm now explicitly resetting it to null in screenReset(), so at this point it can be null
942 if (!srcPic)
943 return;
944
945 bool saveBack = _saveBack;
946 _saveBack = false;
947
948 if (rectListCount == -1) {
949 sDrawPic(srcPic, destPic, Common::Point());
950 } else {
951 for (int i = rectListCount - 1; i >= 0; --i) {
952 _clipPtr = &rectList[i];
953 sDrawPic(srcPic, destPic, Common::Point());
954 }
955 }
956
957 _saveBack = saveBack;
958 }
959
setPalette(const byte * palette,int start,int count)960 void Screen::setPalette(const byte *palette, int start, int count) {
961 Graphics::Screen::setPalette(palette, start, count);
962 _vm->_eventsManager->_gameData._hasPalette = false;
963 }
964
setPalette128(const byte * palette,int start,int count)965 void Screen::setPalette128(const byte *palette, int start, int count) {
966 byte rgb[3];
967 getPalette(&rgb[0], 128, 1);
968 Graphics::Screen::setPalette(palette, start, count);
969 Graphics::Screen::setPalette(&rgb[0], 128, 1);
970 }
971
resetPalette()972 void Screen::resetPalette() {
973 for (int i = 0; i < 256; ++i)
974 setColor(i, 0, 0, 0);
975
976 _vm->_eventsManager->_intPtr._hasPalette = true;
977 }
978
setColor(int idx,byte r,byte g,byte b)979 void Screen::setColor(int idx, byte r, byte g, byte b) {
980 byte *vgaP = &_VGAColors[idx * 3];
981 vgaP[0] = r;
982 vgaP[1] = g;
983 vgaP[2] = b;
984
985 _vm->_eventsManager->_intPtr._palStartIndex = MIN(_vm->_eventsManager->_intPtr._palStartIndex, idx);
986 _vm->_eventsManager->_intPtr._palEndIndex = MAX(_vm->_eventsManager->_intPtr._palEndIndex, idx);
987 }
988
setOneColor(int idx,byte r,byte g,byte b)989 void Screen::setOneColor(int idx, byte r, byte g, byte b) {
990 byte palEntry[3];
991 palEntry[0] = r;
992 palEntry[1] = g;
993 palEntry[2] = b;
994 g_system->getPaletteManager()->setPalette(&palEntry[0], idx, 1);
995 }
996
setColors(int start,int count,const byte * pal)997 void Screen::setColors(int start, int count, const byte *pal) {
998 for (int i = 0; i < count; ++i) {
999 if ((i + start) != 128) {
1000 const byte *rgb = pal + i * 3;
1001 setColor(i + start, rgb[0], rgb[1], rgb[2]);
1002 }
1003 }
1004
1005 _vm->_eventsManager->_intPtr._hasPalette = true;
1006 }
1007
screenReset()1008 void Screen::screenReset() {
1009 resetPalette();
1010
1011 _backgroundPage = NULL;
1012 _vPort->setupViewPort(NULL);
1013 fillPic(_vPort, 0);
1014
1015 _vm->flipPageAndWait();
1016 }
1017
fadeDownICF1(int steps)1018 void Screen::fadeDownICF1(int steps) {
1019 if (steps > 0) {
1020 int stepAmount = _vm->_voy->_fadingAmount2 / steps;
1021
1022 for (int idx = 0; idx < steps; ++idx) {
1023 _vm->_voy->_fadingAmount2 -= stepAmount;
1024 _vm->_eventsManager->delay(1);
1025 }
1026 }
1027
1028 _vm->_voy->_fadingAmount2 = 0;
1029 }
1030
fadeUpICF1(int steps)1031 void Screen::fadeUpICF1(int steps) {
1032 if (steps > 0) {
1033 int stepAmount = (63 - _vm->_voy->_fadingAmount2) / steps;
1034
1035 for (int idx = 0; idx < steps; ++idx) {
1036 _vm->_voy->_fadingAmount2 += stepAmount;
1037 _vm->_eventsManager->delay(1);
1038 }
1039 }
1040
1041 _vm->_voy->_fadingAmount2 = 63;
1042 }
1043
fadeDownICF(int steps)1044 void Screen::fadeDownICF(int steps) {
1045 if (steps > 0) {
1046 _vm->_eventsManager->hideCursor();
1047 int stepAmount1 = _vm->_voy->_fadingAmount1 / steps;
1048 int stepAmount2 = _vm->_voy->_fadingAmount2 / steps;
1049
1050 for (int idx = 0; idx < steps; ++idx) {
1051 _vm->_voy->_fadingAmount1 -= stepAmount1;
1052 _vm->_voy->_fadingAmount2 -= stepAmount2;
1053 _vm->_eventsManager->delay(1);
1054 }
1055 }
1056
1057 _vm->_voy->_fadingAmount1 = 0;
1058 _vm->_voy->_fadingAmount2 = 0;
1059 }
1060
drawDot()1061 void Screen::drawDot() {
1062 for (int idx = 0; idx < 9; ++idx) {
1063 uint offset = DOT_LINE_START[idx] + DOT_LINE_OFFSET[idx];
1064 int xp = offset % SCREEN_WIDTH;
1065 int yp = offset / SCREEN_WIDTH;
1066
1067 byte *pDest = (byte *)getPixels() + offset;
1068 Common::fill(pDest, pDest + DOT_LINE_LENGTH[idx], 0x80);
1069 addDirtyRect(Common::Rect(xp, yp, xp + DOT_LINE_LENGTH[idx], yp + 1));
1070 }
1071 }
1072
synchronize(Common::Serializer & s)1073 void Screen::synchronize(Common::Serializer &s) {
1074 s.syncBytes(&_VGAColors[0], PALETTE_SIZE);
1075 }
1076
1077 } // End of namespace Voyeur
1078