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 "common/file.h"
24 #include "common/system.h"
25 #include "common/textconsole.h"
26
27 #include "graphics/surface.h"
28
29 #include "agos/agos.h"
30 #include "agos/intern.h"
31
32 namespace AGOS {
33
loadIconFile()34 void AGOSEngine::loadIconFile() {
35 Common::File in;
36 uint32 srcSize;
37
38 in.open(getFileName(GAME_ICONFILE));
39 if (in.isOpen() == false)
40 error("Can't open icons file '%s'", getFileName(GAME_ICONFILE));
41
42 srcSize = in.size();
43
44 if (getGameType() == GType_WW && getPlatform() == Common::kPlatformAmiga) {
45 byte *srcBuf = (byte *)malloc(srcSize);
46 in.read(srcBuf, srcSize);
47
48 uint32 dstSize = READ_BE_UINT32(srcBuf + srcSize - 4);
49 _iconFilePtr = (byte *)malloc(dstSize);
50 if (_iconFilePtr == NULL)
51 error("Out of icon memory");
52
53 decrunchFile(srcBuf, _iconFilePtr, srcSize);
54 free(srcBuf);
55 } else if (getGameType() == GType_PN && getPlatform() == Common::kPlatformAtariST) {
56 // The icon data is hard coded in the program file.
57 _iconFilePtr = (byte *)malloc(15038);
58 if (_iconFilePtr == NULL)
59 error("Out of icon memory");
60
61 in.seek(48414);
62 in.read(_iconFilePtr, 15038);
63 } else {
64 _iconFilePtr = (byte *)malloc(srcSize);
65 if (_iconFilePtr == NULL)
66 error("Out of icon memory");
67
68 in.read(_iconFilePtr, srcSize);
69 }
70 in.close();
71 }
72
loadIconData()73 void AGOSEngine::loadIconData() {
74 loadZone(8);
75 VgaPointersEntry *vpe = &_vgaBufferPointers[8];
76
77 byte *src = vpe->vgaFile2 + READ_LE_UINT32(vpe->vgaFile2 + 8);
78
79 _iconFilePtr = (byte *)malloc(43 * 336);
80 if (_iconFilePtr == NULL)
81 error("Out of icon memory");
82
83 memcpy(_iconFilePtr, src, 43 * 336);
84 unfreezeBottom();
85 }
86
87 // Thanks to Stuart Caie for providing the original
88 // C conversion upon which this function is based.
decompressIconPlanar(byte * dst,byte * src,uint width,uint height,byte base,uint pitch,bool decompress=true)89 static void decompressIconPlanar(byte *dst, byte *src, uint width, uint height, byte base, uint pitch, bool decompress = true) {
90 byte *i, *icon_pln, *o, *srcPtr;
91 byte x, y;
92
93 icon_pln = 0;
94 srcPtr = src;
95
96 if (decompress) {
97 icon_pln = (byte *)calloc(width * height, 1);
98
99 // Decode RLE planar icon data
100 i = src;
101 o = icon_pln;
102 while (o < &icon_pln[width * height]) {
103 x = *i++;
104 if (x < 128) {
105 do {
106 *o++ = *i++;
107 *o++ = *i++;
108 *o++ = *i++;
109 } while (x-- > 0);
110 } else {
111 x = 256 - x;
112 do {
113 *o++ = i[0];
114 *o++ = i[1];
115 *o++ = i[2];
116 } while (x-- > 0);
117 i += 3;
118 }
119 }
120 srcPtr = icon_pln;
121 }
122
123 // Translate planar data to chunky (very slow method)
124 for (y = 0; y < height * 2; y++) {
125 for (x = 0; x < width; x++) {
126 byte pixel =
127 (srcPtr[((height * 0 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 1 : 0)
128 | (srcPtr[((height * 2 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 2 : 0)
129 | (srcPtr[((height * 4 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 4 : 0)
130 | (srcPtr[((height * 6 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 8 : 0);
131 if (pixel)
132 dst[x] = pixel | base;
133 }
134 dst += pitch;
135 }
136
137 free(icon_pln);
138 }
139
decompressIcon(byte * dst,byte * src,uint width,uint height,byte base,uint pitch)140 static void decompressIcon(byte *dst, byte *src, uint width, uint height, byte base, uint pitch) {
141 int8 reps;
142 byte color_1, color_2;
143 byte *dst_org = dst;
144 uint h = height;
145
146 for (;;) {
147 reps = *src++;
148 if (reps < 0) {
149 reps--;
150 color_1 = *src >> 4;
151 if (color_1 != 0)
152 color_1 |= base;
153 color_2 = *src++ & 0xF;
154 if (color_2 != 0)
155 color_2 |= base;
156
157 do {
158 if (color_1 != 0)
159 *dst = color_1;
160 dst += pitch;
161 if (color_2 != 0)
162 *dst = color_2;
163 dst += pitch;
164
165 // reached bottom?
166 if (--h == 0) {
167 // reached right edge?
168 if (--width == 0)
169 return;
170 dst = ++dst_org;
171 h = height;
172 }
173 } while (++reps != 0);
174 } else {
175 do {
176 color_1 = *src >> 4;
177 if (color_1 != 0)
178 *dst = color_1 | base;
179 dst += pitch;
180
181 color_2 = *src++ & 0xF;
182 if (color_2 != 0)
183 *dst = color_2 | base;
184 dst += pitch;
185
186 // reached bottom?
187 if (--h == 0) {
188 // reached right edge?
189 if (--width == 0)
190 return;
191 dst = ++dst_org;
192 h = height;
193 }
194 } while (--reps >= 0);
195 }
196 }
197 }
198
drawIcon(WindowBlock * window,uint icon,uint x,uint y)199 void AGOSEngine_Simon2::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
200 byte *dst;
201 byte *src;
202
203 _videoLockOut |= 0x8000;
204
205 Graphics::Surface *screen = _system->lockScreen();
206 dst = (byte *)screen->getPixels();
207
208 dst += 110;
209 dst += x;
210 dst += (y + window->y) * screen->pitch;
211
212 src = _iconFilePtr;
213 src += READ_LE_UINT16(src + icon * 4 + 0);
214 decompressIcon(dst, src, 20, 10, 224, screen->pitch);
215
216 src = _iconFilePtr;
217 src += READ_LE_UINT16(src + icon * 4 + 2);
218 decompressIcon(dst, src, 20, 10, 208, screen->pitch);
219
220 _system->unlockScreen();
221
222 _videoLockOut &= ~0x8000;
223 }
224
drawIcon(WindowBlock * window,uint icon,uint x,uint y)225 void AGOSEngine_Simon1::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
226 byte *dst;
227 byte *src;
228
229 _videoLockOut |= 0x8000;
230
231 Graphics::Surface *screen = _system->lockScreen();
232 dst = (byte *)screen->getPixels();
233
234 dst += (x + window->x) * 8;
235 dst += (y * 25 + window->y) * screen->pitch;
236
237 if (getPlatform() == Common::kPlatformAmiga) {
238 src = _iconFilePtr;
239 src += READ_BE_UINT32(src + icon * 4);
240 uint8 color = (getFeatures() & GF_32COLOR) ? 224 : 240;
241 decompressIconPlanar(dst, src, 24, 12, color, screen->pitch);
242 } else {
243 src = _iconFilePtr;
244 src += READ_LE_UINT16(src + icon * 2);
245 decompressIcon(dst, src, 24, 12, 224, screen->pitch);
246 }
247
248 _system->unlockScreen();
249
250 _videoLockOut &= ~0x8000;
251 }
252
drawIcon(WindowBlock * window,uint icon,uint x,uint y)253 void AGOSEngine_Waxworks::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
254 byte *dst;
255 byte *src;
256
257 _videoLockOut |= 0x8000;
258
259 Graphics::Surface *screen = _system->lockScreen();
260 dst = (byte *)screen->getPixels();
261
262 dst += (x + window->x) * 8;
263 dst += (y * 20 + window->y) * screen->pitch;
264
265 uint8 color = dst[0] & 0xF0;
266 if (getPlatform() == Common::kPlatformAmiga) {
267 src = _iconFilePtr;
268 src += READ_BE_UINT32(src + icon * 4);
269 decompressIconPlanar(dst, src, 24, 10, color, screen->pitch);
270 } else {
271 src = _iconFilePtr;
272 src += READ_LE_UINT16(src + icon * 2);
273 decompressIcon(dst, src, 24, 10, color, screen->pitch);
274 }
275
276 _system->unlockScreen();
277
278 _videoLockOut &= ~0x8000;
279 }
280
drawIcon(WindowBlock * window,uint icon,uint x,uint y)281 void AGOSEngine_Elvira2::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
282 byte *dst;
283 byte *src;
284
285 _videoLockOut |= 0x8000;
286
287 Graphics::Surface *screen = _system->lockScreen();
288 dst = (byte *)screen->getPixels();
289
290 dst += (x + window->x) * 8;
291 dst += (y * 8 + window->y) * screen->pitch;
292
293 uint color = dst[0] & 0xF0;
294 if (getFeatures() & GF_PLANAR) {
295 src = _iconFilePtr;
296 src += READ_BE_UINT32(src + icon * 4);
297 decompressIconPlanar(dst, src, 24, 12, color, screen->pitch);
298 } else {
299 src = _iconFilePtr;
300 src += READ_LE_UINT16(src + icon * 2);
301 decompressIcon(dst, src, 24, 12, color, screen->pitch);
302 }
303
304 _system->unlockScreen();
305
306 _videoLockOut &= ~0x8000;
307 }
308
drawIcon(WindowBlock * window,uint icon,uint x,uint y)309 void AGOSEngine_Elvira1::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
310 byte *dst;
311 byte *src;
312
313 _videoLockOut |= 0x8000;
314
315 Graphics::Surface *screen = _system->lockScreen();
316 dst = (byte *)screen->getPixels();
317
318 dst += (x + window->x) * 8;
319 dst += (y * 8 + window->y) * screen->pitch;
320
321 if (getFeatures() & GF_PLANAR) {
322 src = _iconFilePtr;
323 src += READ_BE_UINT16(src + icon * 2);
324 decompressIconPlanar(dst, src, 24, 12, 16, screen->pitch);
325 } else {
326 src = _iconFilePtr;
327 src += icon * 288;
328 decompressIconPlanar(dst, src, 24, 12, 16, screen->pitch, false);
329 }
330
331 _system->unlockScreen();
332
333 _videoLockOut &= ~0x8000;
334 }
335
drawIcon(WindowBlock * window,uint icon,uint x,uint y)336 void AGOSEngine::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
337 byte *dst;
338 byte *src;
339
340 _videoLockOut |= 0x8000;
341
342 Graphics::Surface *screen = _system->lockScreen();
343 dst = (byte *)screen->getBasePtr(x * 8, y);
344 src = _iconFilePtr + icon * 146;
345
346 if (icon == 0xFF) {
347 // Draw Blank Icon
348 for (int yp = 0; yp < 24; yp++) {
349 memset(dst, 0, 24);
350 dst += screen->pitch;
351 }
352 } else {
353 uint8 palette[4];
354 palette[0] = *src >> 4;
355 palette[1] = *src++ & 0xf;
356 palette[2] = *src >> 4;
357 palette[3] = *src++ & 0xf;
358 for (int yp = 0; yp < 24; ++yp, src += 6) {
359 // Get bit-set representing the 24 pixels for the line
360 uint32 v1 = (READ_BE_UINT16(src) << 8) | *(src + 4);
361 uint32 v2 = (READ_BE_UINT16(src + 2) << 8) | *(src + 5);
362 for (int xp = 0; xp < 24; ++xp, v1 >>= 1, v2 >>= 1) {
363 dst[yp * screen->pitch + (23 - xp)] = palette[((v1 & 1) << 1) | (v2 & 1)];
364 }
365 }
366 }
367
368 _system->unlockScreen();
369
370 _videoLockOut &= ~0x8000;
371 }
372
373 #ifdef ENABLE_AGOS2
drawIconArray(uint num,Item * itemRef,int line,int classMask)374 void AGOSEngine_Feeble::drawIconArray(uint num, Item *itemRef, int line, int classMask) {
375 Item *item_ptr_org = itemRef;
376 WindowBlock *window;
377 uint16 flagnumber = 201;
378 uint16 iconperline = 458;
379 uint16 iconsdown = 384;
380 uint16 idone = 0;
381 uint16 icount = 0;
382 uint16 xp = 188, yp = 306;
383 int k;
384 _iOverflow = 0;
385
386 line = _variableArray[30];
387 if (line == 0)
388 _variableArray[31] = 0;
389
390 window = _windowArray[num & 7];
391 if (window == NULL)
392 return;
393
394 for (k = flagnumber; k <= flagnumber + 18; k++)
395 _variableArray[k] = 0;
396
397 if (window->iconPtr)
398 removeIconArray(num);
399
400 window->iconPtr=(IconBlock *)malloc(sizeof(IconBlock));
401 window->iconPtr->itemRef = itemRef;
402 window->iconPtr->upArrow = -1;
403 window->iconPtr->downArrow = -1;
404 window->iconPtr->line = line;
405 window->iconPtr->classMask = classMask;
406
407 itemRef = derefItem(itemRef->child);
408 k = flagnumber;
409
410 while (itemRef && (line > 65)) {
411 uint16 ct = xp;
412 while (itemRef && ct < iconperline) {
413 if ((classMask == 0) || ((itemRef->classFlags & classMask) != 0)) {
414 if (hasIcon(itemRef)) {
415 ct += 45;
416 k++;
417 }
418 }
419 itemRef = derefItem(itemRef->next);
420 }
421 line -= 52;
422 if (k == (flagnumber + 18))
423 k = flagnumber;
424 }
425 yp -= line; // Adjust starting y
426
427 if (itemRef == NULL) {
428 window->iconPtr->line = 0;
429 itemRef = derefItem(item_ptr_org->child);
430 }
431
432 while (itemRef) {
433 if ((classMask != 0) && ((itemRef->classFlags & classMask) == 0))
434 goto l1;
435 if (hasIcon(itemRef) == 0)
436 goto l1;
437 if (!idone) {
438 /*
439 * Create thee icon and graphics rendering
440 */
441 window->iconPtr->iconArray[icount].item = itemRef;
442 _variableArray[k] = itemGetIconNumber(itemRef);
443 window->iconPtr->iconArray[icount++].boxCode =
444 setupIconHitArea(window, k++, xp, yp, itemRef);
445 } else {
446 /*
447 * Just remember the overflow has occurred
448 */
449 window->iconPtr->iconArray[icount].item = NULL; /* END MARKINGS */
450 _iOverflow = 1;
451 }
452 xp += 45;
453 if (xp >= iconperline) { /* End of line ? */
454 if (k == (flagnumber + 18))
455 k = flagnumber;
456 xp = 188;
457 yp += 52; /* Move down */
458 if (yp >= iconsdown) { /* Full ? */
459 idone = 1; /* Note completed screen */
460 }
461 }
462 l1:; itemRef = derefItem(itemRef->next);
463 }
464 window->iconPtr->iconArray[icount].item = NULL; /* END MARKINGS */
465 if (_variableArray[30] == 0) {
466 if (yp != 306)
467 _variableArray[31] = 52;
468 if ((xp == 188) && (yp == 358))
469 _variableArray[31] = 0;
470 }
471
472 /* Plot arrows and add their boxes */
473 addArrows(window, num);
474 window->iconPtr->upArrow = _scrollUpHitArea;
475 window->iconPtr->downArrow = _scrollDownHitArea;
476 }
477 #endif
478
drawIconArray(uint num,Item * itemRef,int line,int classMask)479 void AGOSEngine::drawIconArray(uint num, Item *itemRef, int line, int classMask) {
480 Item *item_ptr_org = itemRef;
481 WindowBlock *window;
482 uint width, height;
483 uint k, curWidth;
484 bool item_again, showArrows;
485 uint x_pos, y_pos;
486 const int iconSize = (getGameType() == GType_SIMON2) ? 20 : 1;
487
488 window = _windowArray[num & 7];
489
490 if (getGameType() == GType_SIMON2) {
491 width = 100;
492 height = 40;
493 } else if (getGameType() == GType_WW) {
494 width = window->width / 3;
495 height = window->height / 2;
496 } else {
497 width = window->width / 3;
498 height = window->height / 3;
499 }
500
501 if (window == NULL)
502 return;
503
504 if (window->iconPtr)
505 removeIconArray(num);
506
507 window->iconPtr = (IconBlock *) malloc(sizeof(IconBlock));
508 window->iconPtr->itemRef = itemRef;
509 window->iconPtr->upArrow = -1;
510 window->iconPtr->downArrow = -1;
511 window->iconPtr->line = line;
512 window->iconPtr->classMask = classMask;
513
514 itemRef = derefItem(itemRef->child);
515
516 while (itemRef && line-- != 0) {
517 curWidth = 0;
518 while (itemRef && width > curWidth) {
519 if ((classMask == 0 || itemRef->classFlags & classMask) && hasIcon(itemRef))
520 curWidth += iconSize;
521 itemRef = derefItem(itemRef->next);
522 }
523 }
524
525 if (itemRef == NULL) {
526 window->iconPtr->line = 0;
527 itemRef = derefItem(item_ptr_org->child);
528 }
529
530 x_pos = 0;
531 y_pos = 0;
532 k = 0;
533 item_again = false;
534 showArrows = false;
535
536 while (itemRef) {
537 if ((classMask == 0 || itemRef->classFlags & classMask) && hasIcon(itemRef)) {
538 if (item_again == false) {
539 window->iconPtr->iconArray[k].item = itemRef;
540 if (getGameType() == GType_SIMON2) {
541 drawIcon(window, itemGetIconNumber(itemRef), x_pos, y_pos);
542 window->iconPtr->iconArray[k].boxCode =
543 setupIconHitArea(window, 0, x_pos, y_pos, itemRef);
544 } else if (getGameType() == GType_SIMON1 || getGameType() == GType_WW) {
545 drawIcon(window, itemGetIconNumber(itemRef), x_pos * 3, y_pos);
546 window->iconPtr->iconArray[k].boxCode =
547 setupIconHitArea(window, 0, x_pos * 3, y_pos, itemRef);
548 } else {
549 drawIcon(window, itemGetIconNumber(itemRef), x_pos * 3, y_pos * 3);
550 window->iconPtr->iconArray[k].boxCode =
551 setupIconHitArea(window, 0, x_pos * 3, y_pos * 3, itemRef);
552 }
553 k++;
554 } else {
555 window->iconPtr->iconArray[k].item = NULL;
556 showArrows = 1;
557 }
558
559 x_pos += iconSize;
560 if (x_pos >= width) {
561 x_pos = 0;
562 y_pos += iconSize;
563 if (y_pos >= height)
564 item_again = true;
565 }
566 }
567 itemRef = derefItem(itemRef->next);
568 }
569
570 window->iconPtr->iconArray[k].item = NULL;
571
572 if (showArrows != 0 || window->iconPtr->line != 0) {
573 /* Plot arrows and add their boxes */
574 addArrows(window, num);
575 window->iconPtr->upArrow = _scrollUpHitArea;
576 window->iconPtr->downArrow = _scrollDownHitArea;
577 }
578 }
579
580 #ifdef ENABLE_AGOS2
setupIconHitArea(WindowBlock * window,uint num,uint x,uint y,Item * itemPtr)581 uint AGOSEngine_Feeble::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *itemPtr) {
582 HitArea *ha = findEmptyHitArea();
583
584 ha->x = x;
585 ha->y = y;
586 ha->itemPtr = itemPtr;
587 ha->width = 45;
588 ha->height = 44;
589 ha->flags = kBFBoxInUse | kBFBoxItem;
590 ha->id = num;
591 ha->priority = 100;
592 ha->verb = 208;
593
594 return ha - _hitAreas;
595 }
596 #endif
597
setupIconHitArea(WindowBlock * window,uint num,uint x,uint y,Item * itemPtr)598 uint AGOSEngine_Simon2::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *itemPtr) {
599 HitArea *ha = findEmptyHitArea();
600
601 ha->x = x + 110;
602 ha->y = window->y + y;
603 ha->itemPtr = itemPtr;
604 ha->width = 20;
605 ha->height = 20;
606 ha->flags = kBFDragBox | kBFBoxInUse | kBFBoxItem;
607 ha->id = 0x7FFD;
608 ha->priority = 100;
609 ha->verb = 208;
610
611 return ha - _hitAreas;
612 }
613
setupIconHitArea(WindowBlock * window,uint num,uint x,uint y,Item * itemPtr)614 uint AGOSEngine_Simon1::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *itemPtr) {
615 HitArea *ha = findEmptyHitArea();
616
617 ha->x = (x + window->x) * 8;
618 ha->y = y * 25 + window->y;
619 ha->itemPtr = itemPtr;
620 ha->width = 24;
621 ha->height = 24;
622 ha->flags = kBFDragBox | kBFBoxInUse | kBFBoxItem;
623 ha->id = 0x7FFD;
624 ha->priority = 100;
625 ha->verb = 208;
626
627 return ha - _hitAreas;
628 }
629
setupIconHitArea(WindowBlock * window,uint num,uint x,uint y,Item * itemPtr)630 uint AGOSEngine_Waxworks::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *itemPtr) {
631 HitArea *ha = findEmptyHitArea();
632
633 ha->x = (x + window->x) * 8;
634 ha->y = y * 20 + window->y;
635 ha->itemPtr = itemPtr;
636 ha->width = 24;
637 ha->height = 20;
638 ha->flags = kBFDragBox | kBFBoxInUse | kBFBoxItem;
639 ha->id = 0x7FFD;
640 ha->priority = 100;
641 ha->verb = 208;
642
643 return ha - _hitAreas;
644 }
645
setupIconHitArea(WindowBlock * window,uint num,uint x,uint y,Item * itemPtr)646 uint AGOSEngine_Elvira2::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *itemPtr) {
647 HitArea *ha = findEmptyHitArea();
648
649 ha->x = (x + window->x) * 8;
650 ha->y = y * 8 + window->y;
651 ha->itemPtr = itemPtr;
652 ha->width = 24;
653 ha->height = 24;
654 ha->id = 0x7FFD;
655 ha->priority = 100;
656
657 if (window->iconPtr->classMask == 2) {
658 ha->flags = kBFDragBox | kBFBoxInUse;
659 ha->verb = 248 + 0x4000;
660 } else {
661 ha->flags = kBFDragBox | kBFBoxInUse | kBFBoxItem;
662 ha->verb = 208;
663 }
664
665 return ha - _hitAreas;
666 }
667
setupIconHitArea(WindowBlock * window,uint num,uint x,uint y,Item * itemPtr)668 uint AGOSEngine::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *itemPtr) {
669 HitArea *ha = findEmptyHitArea();
670
671 ha->x = (x + window->x) * 8;
672 ha->y = y * 8 + window->y;
673 ha->itemPtr = itemPtr;
674 ha->width = 24;
675 ha->height = 24;
676 ha->flags = kBFDragBox | kBFBoxInUse | kBFBoxItem;
677 ha->id = 0x7FFD;
678 ha->priority = 100;
679 ha->verb = 253;
680
681 return ha - _hitAreas;
682 }
683
684 #ifdef ENABLE_AGOS2
addArrows(WindowBlock * window,uint8 num)685 void AGOSEngine_Feeble::addArrows(WindowBlock *window, uint8 num) {
686 HitArea *ha;
687
688 ha = findEmptyHitArea();
689 _scrollUpHitArea = ha - _hitAreas;
690
691 ha->x = 496;
692 ha->y = 279;
693 ha->width = 30;
694 ha->height = 45;
695 ha->flags = kBFBoxInUse | kBFNoTouchName;
696 ha->id = 0x7FFB;
697 ha->priority = 100;
698 ha->window = window;
699 ha->verb = 1;
700
701 ha = findEmptyHitArea();
702 _scrollDownHitArea = ha - _hitAreas;
703
704 ha->x = 496;
705 ha->y = 324;
706 ha->width = 30;
707 ha->height = 44;
708 ha->flags = kBFBoxInUse | kBFNoTouchName;
709 ha->id = 0x7FFC;
710 ha->priority = 100;
711 ha->window = window;
712 ha->verb = 1;
713 }
714 #endif
715
addArrows(WindowBlock * window,uint8 num)716 void AGOSEngine_Simon2::addArrows(WindowBlock *window, uint8 num) {
717 HitArea *ha;
718
719 ha = findEmptyHitArea();
720 _scrollUpHitArea = ha - _hitAreas;
721
722 ha->x = 81;
723 ha->y = 158;
724 ha->width = 12;
725 ha->height = 26;
726 ha->flags = kBFBoxInUse | kBFNoTouchName;
727 ha->id = 0x7FFB;
728 ha->priority = 100;
729 ha->window = window;
730 ha->verb = 1;
731
732 ha = findEmptyHitArea();
733 _scrollDownHitArea = ha - _hitAreas;
734
735 ha->x = 227;
736 ha->y = 162;
737 ha->width = 12;
738 ha->height = 26;
739 ha->flags = kBFBoxInUse | kBFNoTouchName;
740 ha->id = 0x7FFC;
741 ha->priority = 100;
742 ha->window = window;
743 ha->verb = 1;
744 }
745
addArrows(WindowBlock * window,uint8 num)746 void AGOSEngine_Simon1::addArrows(WindowBlock *window, uint8 num) {
747 HitArea *ha;
748
749 ha = findEmptyHitArea();
750 _scrollUpHitArea = ha - _hitAreas;
751
752 ha->x = 308;
753 ha->y = 149;
754 ha->width = 12;
755 ha->height = 17;
756 ha->flags = kBFBoxInUse | kBFNoTouchName;
757 ha->id = 0x7FFB;
758 ha->priority = 100;
759 ha->window = window;
760 ha->verb = 1;
761
762 ha = findEmptyHitArea();
763 _scrollDownHitArea = ha - _hitAreas;
764
765 ha->x = 308;
766 ha->y = 176;
767 ha->width = 12;
768 ha->height = 17;
769 ha->flags = kBFBoxInUse | kBFNoTouchName;
770 ha->id = 0x7FFC;
771 ha->priority = 100;
772 ha->window = window;
773 ha->verb = 1;
774
775 _videoLockOut |= 0x8;
776
777 VgaPointersEntry *vpe = &_vgaBufferPointers[1];
778 byte *curVgaFile2Orig = _curVgaFile2;
779 uint16 windowNumOrig = _windowNum;
780 uint8 palette = (getPlatform() == Common::kPlatformAmiga) ? 15 : 14;
781
782 _windowNum = 0;
783 _curVgaFile2 = vpe->vgaFile2;
784 drawImage_init(1, palette, 38, 150, 4);
785
786 _curVgaFile2 = curVgaFile2Orig;
787 _windowNum = windowNumOrig;
788
789 _videoLockOut &= ~0x8;
790 }
791
addArrows(WindowBlock * window,uint8 num)792 void AGOSEngine_Waxworks::addArrows(WindowBlock *window, uint8 num) {
793 HitArea *ha;
794
795 ha = findEmptyHitArea();
796 _scrollUpHitArea = ha - _hitAreas;
797
798 setBitFlag(22, true);
799 ha->x = 255;
800 ha->y = 153;
801 ha->width = 9;
802 ha->height = 11;
803 ha->flags = kBFBoxInUse | kBFNoTouchName;
804 ha->id = 0x7FFB;
805 ha->priority = 100;
806 ha->window = window;
807 ha->verb = 1;
808
809 ha = findEmptyHitArea();
810 _scrollDownHitArea = ha - _hitAreas;
811
812 ha->x = 255;
813 ha->y = 170;
814 ha->width = 9;
815 ha->height = 11;
816 ha->flags = kBFBoxInUse | kBFNoTouchName;
817 ha->id = 0x7FFC;
818 ha->priority = 100;
819 ha->window = window;
820 ha->verb = 1;
821 setWindowImageEx(6, 103);
822 }
823
addArrows(WindowBlock * window,uint8 num)824 void AGOSEngine_Elvira2::addArrows(WindowBlock *window, uint8 num) {
825 HitArea *ha;
826
827 ha = findEmptyHitArea();
828 _scrollUpHitArea = ha - _hitAreas;
829
830 setBitFlag(21, true);
831 ha->x = 54;
832 ha->y = 154;
833 ha->width = 12;
834 ha->height = 10;
835 ha->flags = kBFBoxInUse;
836 ha->id = 0x7FFB;
837 ha->priority = 100;
838 ha->window = window;
839 ha->verb = 1;
840
841 ha = findEmptyHitArea();
842 _scrollDownHitArea = ha - _hitAreas;
843
844 ha->x = 54;
845 ha->y = 178;
846 ha->width = 12;
847 ha->height = 10;
848 ha->flags = kBFBoxInUse;
849 ha->id = 0x7FFC;
850 ha->priority = 100;
851 ha->window = window;
852 ha->verb = 1;
853 setWindowImageEx(6, 106);
854 }
855
addArrows(WindowBlock * window,uint8 num)856 void AGOSEngine::addArrows(WindowBlock *window, uint8 num) {
857 HitArea *ha;
858 uint16 x, y;
859
860 x = 30;
861 y = 151;
862 if (num != 2) {
863 y = window->y + window->height * 4 - 19;
864 x = window->x + window->width;
865 }
866 drawArrow(x, y, 16);
867
868 ha = findEmptyHitArea();
869 _scrollUpHitArea = ha - _hitAreas;
870
871 ha->x = x * 8;
872 ha->y = y;
873 ha->width = 16;
874 ha->height = 19;
875 ha->flags = kBFBoxInUse;
876 ha->id = 0x7FFB;
877 ha->priority = 100;
878 ha->window = window;
879 ha->verb = 1;
880
881 x = 30;
882 y = 170;
883 if (num != 2) {
884 y = window->y + window->height * 4;
885 x = window->x + window->width;
886 }
887 drawArrow(x, y, -16);
888
889 ha = findEmptyHitArea();
890 _scrollDownHitArea = ha - _hitAreas;
891
892 ha->x = x * 8;
893 ha->y = y;
894 ha->width = 16;
895 ha->height = 19;
896 ha->flags = kBFBoxInUse;
897 ha->id = 0x7FFC;
898 ha->priority = 100;
899 ha->window = window;
900 ha->verb = 1;
901 }
902
903 static const byte _arrowImage[] = {
904 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
905 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
906 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
907 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
908 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b,
909 0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
910 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0a,
911 0x0d, 0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00,
912 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0a, 0x0d,
913 0x03, 0x0d, 0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x00,
914 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0a, 0x0d, 0x03,
915 0x04, 0x03, 0x0d, 0x0a, 0x0b, 0x0a, 0x00, 0x00,
916 0x00, 0x00, 0x0a, 0x0b, 0x0a, 0x0d, 0x03, 0x04,
917 0x0f, 0x04, 0x03, 0x0d, 0x0a, 0x0b, 0x0a, 0x00,
918 0x00, 0x0a, 0x0b, 0x0a, 0x0d, 0x0d, 0x0d, 0x03,
919 0x04, 0x03, 0x0d, 0x0d, 0x0d, 0x0a, 0x0b, 0x0a,
920 0x00, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x0d,
921 0x03, 0x0d, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b,
922 0x00, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0d,
923 0x0d, 0x0d, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
924 0x00, 0x0a, 0x0a, 0x0a, 0x0e, 0x0b, 0x0b, 0x0c,
925 0x0e, 0x0c, 0x0b, 0x0b, 0x0e, 0x0a, 0x0a, 0x0a,
926 0x00, 0x00, 0x02, 0x02, 0x0a, 0x0b, 0x0a, 0x0d,
927 0x0d, 0x0d, 0x0a, 0x0b, 0x0a, 0x02, 0x02, 0x00,
928 0x00, 0x00, 0x00, 0x02, 0x0a, 0x0b, 0x0b, 0x0c,
929 0x0e, 0x0c, 0x0b, 0x0b, 0x0a, 0x02, 0x00, 0x00,
930 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0a, 0x0d,
931 0x0d, 0x0d, 0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x00,
932 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0b, 0x0c,
933 0x0e, 0x0c, 0x0b, 0x0b, 0x0a, 0x00, 0x00, 0x00,
934 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0b, 0x0b,
935 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x00, 0x00, 0x00,
936 0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x0a, 0x0a,
937 0x0e, 0x0a, 0x0a, 0x0e, 0x02, 0x00, 0x00, 0x00,
938 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
939 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00,
940 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
941 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
942 };
943
drawArrow(uint16 x,uint16 y,int8 dir)944 void AGOSEngine::drawArrow(uint16 x, uint16 y, int8 dir) {
945 const byte *src;
946 uint8 w, h;
947
948 if (dir < 0) {
949 src = _arrowImage + 288;
950 } else {
951 src = _arrowImage;
952 }
953
954 Graphics::Surface *screen = _system->lockScreen();
955 byte *dst = (byte *)screen->getBasePtr(x * 8, y);
956
957 for (h = 0; h < 19; h++) {
958 for (w = 0; w < 16; w++) {
959 if (src[w])
960 dst[w] = src[w] + 16;
961 }
962
963 src += dir;
964 dst+= screen->pitch;
965 }
966
967 _system->unlockScreen();
968 }
969
removeArrows(WindowBlock * window,uint num)970 void AGOSEngine_Simon1::removeArrows(WindowBlock *window, uint num) {
971 if (getGameType() == GType_SIMON1) {
972 restoreBlock(304, 146, 320, 200);
973 }
974 }
975
removeArrows(WindowBlock * window,uint num)976 void AGOSEngine_Waxworks::removeArrows(WindowBlock *window, uint num) {
977 setBitFlag(22, false);
978 setWindowImageEx(6, 103);
979 }
980
removeArrows(WindowBlock * window,uint num)981 void AGOSEngine_Elvira2::removeArrows(WindowBlock *window, uint num) {
982 setBitFlag(21, false);
983 setWindowImageEx(6, 106);
984 }
985
removeArrows(WindowBlock * window,uint num)986 void AGOSEngine::removeArrows(WindowBlock *window, uint num) {
987 if (num != 2) {
988 uint y = window->y + window->height * 4 - 19;
989 uint x = (window->x + window->width) * 8;
990 restoreBlock(x, y, x + 16, y + 38);
991 } else {
992 colorBlock(window, 240, 151, 16, 38);
993 }
994 }
995
removeIconArray(uint num)996 void AGOSEngine::removeIconArray(uint num) {
997 WindowBlock *window;
998 uint16 curWindow;
999 uint16 i;
1000
1001 window = _windowArray[num & 7];
1002 curWindow = _curWindow;
1003
1004 if (window == NULL || window->iconPtr == NULL)
1005 return;
1006
1007 if (getGameType() != GType_FF && getGameType() != GType_PP) {
1008 changeWindow(num);
1009 sendWindow(12);
1010 changeWindow(curWindow);
1011 }
1012
1013 for (i = 0; window->iconPtr->iconArray[i].item != NULL; i++) {
1014 freeBox(window->iconPtr->iconArray[i].boxCode);
1015 }
1016
1017 if (window->iconPtr->upArrow != -1) {
1018 freeBox(window->iconPtr->upArrow);
1019 }
1020
1021 if (window->iconPtr->downArrow != -1) {
1022 freeBox(window->iconPtr->downArrow);
1023 removeArrows(window, num);
1024 }
1025
1026 free(window->iconPtr);
1027 window->iconPtr = NULL;
1028
1029 _fcsData1[num] = 0;
1030 _fcsData2[num] = 0;
1031 }
1032
1033 static const byte hitBarData[12 * 7] = {
1034 0x3C, 0x00, 0x80, 0x00, 0x88, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00,
1035 0x20, 0x00, 0x04, 0x00, 0xD8, 0x00, 0x00, 0x04, 0x48, 0x00, 0x00, 0x00,
1036 0x20, 0x89, 0x8E, 0x00, 0xA8, 0x86, 0x10, 0x04, 0x08, 0x21, 0x88, 0x00,
1037 0x38, 0x50, 0x84, 0x00, 0x89, 0x49, 0x28, 0x04, 0x08, 0x52, 0x14, 0x00,
1038 0x20, 0x20, 0x84, 0x00, 0x89, 0x48, 0x38, 0x04, 0x08, 0x53, 0x9C, 0x00,
1039 0x20, 0x50, 0x84, 0x00, 0x89, 0x48, 0x20, 0x04, 0x48, 0x50, 0x90, 0x00,
1040 0x3C, 0x89, 0xC3, 0x00, 0x88, 0x88, 0x18, 0x03, 0x86, 0x23, 0x0C, 0x00
1041 };
1042
1043 // Personal Nightmare specific
drawIconHitBar()1044 void AGOSEngine_PN::drawIconHitBar() {
1045 Graphics::Surface *screen = _system->lockScreen();
1046 byte *dst = (byte *)screen->getBasePtr(6 * 8, 3);
1047 const byte *src = hitBarData;
1048 uint8 color = (getPlatform() == Common::kPlatformDOS) ? 7 : 15;
1049
1050 for (int h = 0; h < 7; h++) {
1051 for (int w = 0; w < 12; w++) {
1052 int8 b = *src++;
1053 for (int i = 0; i < 8; i++) {
1054 if (b < 0) {
1055 dst[w * 8 + i] = color;
1056 }
1057
1058 b <<= 1;
1059 }
1060 }
1061 dst += screen->pitch;
1062 }
1063
1064 _system->unlockScreen();
1065 }
1066
iconPage()1067 void AGOSEngine_PN::iconPage() {
1068 _objectCountS = -1;
1069
1070 mouseOff();
1071
1072 uint8 objRoom = getptr(_quickptr[12] + _variableArray[210] * _quickshort[5] + 20);
1073 uint8 iconNum = getptr(_quickptr[0] + objRoom * _quickshort[0] + 4);
1074
1075 drawIcon(NULL, iconNum, 6, 12);
1076
1077 HitArea *ha = _invHitAreas + 5;
1078 for (uint8 r = 0; r < 5; r++) {
1079 for (uint8 i = 0; i < 7; i++) {
1080 printIcon(ha, i, r);
1081 ha++;
1082 }
1083 }
1084
1085 mouseOn();
1086 }
1087
ifObjectInInv(uint16 a)1088 bool AGOSEngine_PN::ifObjectInInv(uint16 a) {
1089 return _variableArray[210] == getptr(_quickptr[11] + a * _quickshort[4] + 2);
1090 }
1091
testContainer(uint16 a)1092 bool AGOSEngine_PN::testContainer(uint16 a) {
1093 return bitextract(_quickptr[1] + a * _quickshort[1], 0) != 0;
1094 }
1095
testObvious(uint16 a)1096 bool AGOSEngine_PN::testObvious(uint16 a) {
1097 return bitextract(_quickptr[1] + a * _quickshort[1], 4) != 0;
1098 }
1099
testSeen(uint16 a)1100 bool AGOSEngine_PN::testSeen(uint16 a) {
1101 return bitextract(_quickptr[1] + a * _quickshort[1], 3) != 0;
1102 }
1103
printIcon(HitArea * ha,uint8 i,uint8 r)1104 void AGOSEngine_PN::printIcon(HitArea *ha, uint8 i, uint8 r) {
1105 if (_objects == _objectCountS) {
1106 ha->flags |= kOBFBoxDisabled;
1107 drawIcon(NULL, 0xFF, 12 + i * 3, 12 + 24 * r);
1108 } else {
1109 _objectCountS++;
1110 if (!ifObjectInInv(_objectCountS) || !testObvious(_objectCountS)) {
1111 printIcon(ha, i, r);
1112 } else {
1113
1114 uint8 iconNum = getptr(_quickptr[0] + _objectCountS * _quickshort[0] + 4);
1115 drawIcon(NULL, iconNum, 12 + i * 3, 12 + 24 * r);
1116
1117 ha->msg1 = _objectCountS | 0x8000;
1118 ha->flags &= ~kOBFBoxDisabled;
1119 }
1120 }
1121 }
1122
1123 } // End of namespace AGOS
1124