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 "cruise/cruise_main.h"
24 #include "cruise/polys.h"
25 #include "common/endian.h"
26 #include "common/util.h"
27
28 namespace Cruise {
29
30 struct autoCellStruct {
31 struct autoCellStruct *next;
32 short int ovlIdx;
33 short int objIdx;
34 short int type;
35 short int newValue;
36 cellStruct *pCell;
37 };
38
39 autoCellStruct autoCellHead;
40
addAutoCell(int overlayIdx,int idx,int type,int newVal,cellStruct * pObject)41 void addAutoCell(int overlayIdx, int idx, int type, int newVal, cellStruct *pObject) {
42 autoCellStruct *pNewEntry;
43
44 pNewEntry = new autoCellStruct;
45
46 pNewEntry->next = autoCellHead.next;
47 autoCellHead.next = pNewEntry;
48
49 pNewEntry->ovlIdx = overlayIdx;
50 pNewEntry->objIdx = idx;
51 pNewEntry->type = type;
52 pNewEntry->newValue = newVal;
53 pNewEntry->pCell = pObject;
54 }
55
freeAutoCell()56 void freeAutoCell() {
57 autoCellStruct *pCurrent = autoCellHead.next;
58
59 while (pCurrent) {
60 autoCellStruct *next = pCurrent->next;
61
62 if (pCurrent->type == 5) {
63 objInit(pCurrent->ovlIdx, pCurrent->objIdx, pCurrent->newValue);
64 } else {
65 setObjectPosition(pCurrent->ovlIdx, pCurrent->objIdx, pCurrent->type, pCurrent->newValue);
66 }
67
68 if (pCurrent->pCell->animWait < 0) {
69 objectParamsQuery params;
70
71 getMultipleObjectParam(pCurrent->ovlIdx, pCurrent->objIdx, ¶ms);
72
73 pCurrent->pCell->animCounter = params.state2 - 1;
74 }
75
76 delete pCurrent;
77
78 pCurrent = next;
79 }
80 }
81
calcRGB(uint8 * pColorSrc,uint8 * pColorDst,int * offsetTable)82 void calcRGB(uint8* pColorSrc, uint8* pColorDst, int* offsetTable) {
83 for (unsigned long int i = 0; i < 3; i++) {
84 int color = *(pColorSrc++);
85 int offset = offsetTable[i];
86
87 color += offset;
88 if (color < 0)
89 color = 0;
90 if (color > 0xFF)
91 color = 0xFF;
92
93 *(pColorDst++) = (uint8)color;
94 }
95 }
96
fadeIn()97 void fadeIn() {
98 for (long int i = 256; i >= 0; i -= 32) {
99 for (long int j = 0; j < 256; j++) {
100 int offsetTable[3];
101 offsetTable[0] = -i;
102 offsetTable[1] = -i;
103 offsetTable[2] = -i;
104 calcRGB(&palScreen[masterScreen][3*j], &workpal[3*j], offsetTable);
105 }
106 gfxModuleData_setPal256(workpal);
107
108 gfxModuleData_updatePalette();
109 gfxModuleData_updateScreen();
110 }
111
112 for (long int j = 0; j < 256; j++) {
113 int offsetTable[3];
114 offsetTable[0] = 0;
115 offsetTable[1] = 0;
116 offsetTable[2] = 0;
117 calcRGB(&palScreen[masterScreen][3*j], &workpal[3*j], offsetTable);
118 }
119
120 gfxModuleData_setPal256(workpal);
121
122 fadeFlag = 0;
123 PCFadeFlag = false;
124 }
125
flipScreen()126 void flipScreen() {
127 if (switchPal) {
128 for (unsigned long int i = 0; i < 256*3; i++) {
129 workpal[i] = palScreen[masterScreen][i];
130 }
131 switchPal = 0;
132 gfxModuleData_setPal256(workpal);
133 }
134
135 SWAP(gfxModuleData.pPage00, gfxModuleData.pPage10);
136
137 gfxModuleData_flipScreen();
138
139 if (doFade) {
140 fadeIn();
141 doFade = 0;
142 }
143 }
144
145 int spriteX1;
146 int spriteX2;
147 int spriteY1;
148 int spriteY2;
149
150 char *polyOutputBuffer;
151
pixel(int x,int y,char color)152 void pixel(int x, int y, char color) {
153 if (x >= 0 && x < 320 && y >= 0 && y < 200)
154 polyOutputBuffer[320 * y + x] = color;
155 }
156
157 // this function checks if the dataPtr is not 0, else it retrives the data for X, Y, scale and DataPtr again (OLD: mainDrawSub1Sub1)
flipPoly(int fileId,int16 * dataPtr,int scale,char ** newFrame,int X,int Y,int * outX,int * outY,int * outScale)158 void flipPoly(int fileId, int16 *dataPtr, int scale, char** newFrame, int X, int Y, int *outX, int *outY, int *outScale) {
159 if (*dataPtr == 0) {
160 int16 offset;
161 int16 newX;
162 int16 newY;
163
164 dataPtr ++;
165
166 offset = (int16)READ_BE_UINT16(dataPtr);
167 dataPtr++;
168
169 newX = (int16)READ_BE_UINT16(dataPtr);
170 dataPtr++;
171
172 newY = (int16)READ_BE_UINT16(dataPtr);
173 dataPtr++;
174
175 offset += fileId;
176
177 if (offset >= 0) {
178 if (filesDatabase[offset].resType == OBJ_TYPE_LINE && filesDatabase[offset].subData.ptr) {
179 dataPtr = (int16 *)filesDatabase[offset].subData.ptr;
180 }
181 }
182
183 scale = -scale;
184 X -= newX;
185 Y -= newY;
186 }
187
188 *newFrame = (char *)dataPtr;
189 *outX = X;
190 *outY = Y;
191 *outScale = scale;
192 }
193
upscaleValue(int value,int scale)194 int upscaleValue(int value, int scale) {
195 return (((value * scale) << 8) / 2);
196 }
197
198 int m_flipLeftRight;
199 int m_useSmallScale;
200 int m_lowerX;
201 int m_lowerY;
202 int m_coordCount;
203 int m_first_X;
204 int m_first_Y;
205 int m_scaleValue;
206 int m_color;
207
208 /*
209 FIXME: Whether intentional or not, the game often seems to use negative indexing
210 of one or more of the arrays below and expects(?) to end up in the preceding one.
211 This "worked" on many platforms so far, but on OSX apparently the buffers don't
212 occupy contiguous memory, and this causes severe corruption and subsequent crashes.
213 Since I'm not really familiar with how the strange drawing code is supposed to work,
214 or whether this behavior is intentional or not, the short-term fix is to allocate a big
215 buffer and setup pointers within it. This fixes the crashes I'm seeing without causing any
216 (visual) side-effects.
217 If anyone wants to look, this is easily reproduced by starting the game and examining the rug.
218 drawPolyMode1() will then (indirectly) negatively index polyBuffer4. Good luck!
219 */
220
221 //int16 DIST_3D[512];
222 //int16 polyBuffer2[512];
223 //int16 XMIN_XMAX[404];
224 //int16 polyBuffer4[512];
225
226 int16 bigPolyBuf[512 + 512 + 404 + 512]; /* consolidates the 4 separate buffers above */
227
228 //set up the replacement index pointers.
229 int16 *DIST_3D = &bigPolyBuf[0];
230 int16 *polyBuffer2 = &bigPolyBuf[512];
231 int16 *XMIN_XMAX = &bigPolyBuf[512 + 512];
232 int16 *polyBuffer4 = &bigPolyBuf[512 + 512 + 404];
233
234
235
236
237 // this function fills the sizeTable for the poly (OLD: mainDrawSub1Sub2)
getPolySize(int positionX,int positionY,int scale,int sizeTable[4],unsigned char * dataPtr)238 void getPolySize(int positionX, int positionY, int scale, int sizeTable[4], unsigned char *dataPtr) {
239 int upperBorder;
240 int lowerBorder;
241 m_flipLeftRight = 0;
242
243 if (scale < 0) { // flip left right
244 m_flipLeftRight = 1;
245 scale = -scale;
246 }
247 // X1
248
249 upperBorder = *(dataPtr + 3);
250
251 if (m_flipLeftRight) {
252 upperBorder = -upperBorder;
253 }
254
255 upperBorder = (upscaleValue(upperBorder, scale) + 0x8000) >> 16;
256 upperBorder = -upperBorder;
257 lowerBorder = upperBorder;
258
259 // X2
260
261 upperBorder = *(dataPtr + 1);
262 upperBorder -= *(dataPtr + 3);
263
264 if (m_flipLeftRight) {
265 upperBorder = -upperBorder;
266 }
267
268 upperBorder = (upscaleValue(upperBorder, scale) + 0x8000) >> 16;
269
270 if (upperBorder < lowerBorder) { // exchange borders if lower > upper
271 SWAP(upperBorder, lowerBorder);
272 }
273
274 sizeTable[0] = lowerBorder + positionX; // left
275 sizeTable[1] = upperBorder + positionX; // right
276
277 // Y1
278
279 upperBorder = *(dataPtr + 4);
280 upperBorder = (upscaleValue(upperBorder, scale) + 0x8000) >> 16;
281 upperBorder = -upperBorder;
282 lowerBorder = upperBorder;
283
284 // Y2
285
286 upperBorder = *(dataPtr + 2);
287 upperBorder -= *(dataPtr + 4);
288 upperBorder = (upscaleValue(upperBorder, scale) + 0x8000) >> 16;
289
290 if (upperBorder < lowerBorder) { // exchange borders if lower > upper
291 SWAP(upperBorder, lowerBorder);
292 }
293
294 sizeTable[2] = lowerBorder + positionY; // bottom
295 sizeTable[3] = upperBorder + positionY; // top
296 }
297
298 int nbseg;
299 int16 nbligne;
300
blitPolyMode1(char * dest,char * pMask,int16 * buffer,char color)301 void blitPolyMode1(char *dest, char *pMask, int16 * buffer, char color) {
302 int Y = XMIN_XMAX[0];
303
304 for (int i = 0; i < nbligne; i++) {
305 int currentY = Y + i;
306 int XMIN = XMIN_XMAX[1+i*2];
307 int XMAX = XMIN_XMAX[1+i*2+1];
308
309 for (int x = XMIN; x <= XMAX; x++) {
310 if (testMask(x, currentY, (unsigned char*)pMask, 40)) {
311 *(dest + currentY * 320 + x) = color;
312 }
313 }
314 //line(XMIN, currentY, XMAX, currentY, color);
315 }
316 }
317
blitPolyMode2(char * dest,int16 * buffer,char color)318 void blitPolyMode2(char *dest, int16 * buffer, char color) {
319 int Y = XMIN_XMAX[0];
320
321 for (int i = 0; i < nbligne; i++) {
322 int currentY = Y + i;
323 int XMIN = XMIN_XMAX[1+i*2];
324 int XMAX = XMIN_XMAX[1+i*2+1];
325
326 for (int x = XMIN; x <= XMAX; x++) {
327 *(dest + currentY * 320 + x) = color;
328 }
329 }
330 }
331
332 int polyXMin;
333 int polyXMax;
334 int polyYMax;
335 int polyYMin;
336
337 int16 *A2ptr;
338
339
340
buildSegment()341 void buildSegment() {
342 int16* pOut = XMIN_XMAX;
343
344 if ((polyXMin >= 320) || (polyXMax < 0) || (polyYMax < 0) || (polyYMin >= 200)) {
345 XMIN_XMAX[0] = -1;
346 nbligne = -1;
347 return;
348 }
349
350 if (polyYMin == polyYMax) { // line
351 *(pOut++) = polyYMin; // store initial Y
352
353 int cx = nbseg - 1;
354 int16* pIn = A2ptr;
355
356 int XLeft;
357 int XRight;
358
359 XLeft = XRight = *pIn; // init to first X
360 pIn += 2;
361
362 do {
363 int X = *pIn;
364 if (XLeft > X)
365 XLeft = X;
366 if (XRight < X)
367 XRight = X;
368 pIn += 2;
369 } while (--cx);
370
371 // now store left and right coordinates in XMIN_XMAX
372
373 int XMin = XLeft;
374 int XMax = XRight;
375
376 if (XLeft < 0)
377 XMin = 0;
378
379 if (XRight >= 320)
380 XMax = 319;
381
382 *(pOut++) = XMin;
383 *(pOut++) = XMax;
384 *(pOut++) = -1;
385
386 nbligne = 1;
387 return;
388 }
389
390 // true polygon
391
392 int ydep;
393
394 if (polyYMin < 0)
395 ydep = 0;
396 else
397 ydep = polyYMin;
398
399 int yfin;
400
401 if (polyYMax > 199)
402 yfin = 199;
403 else
404 yfin = polyYMax;
405
406 nbligne = yfin - ydep + 1;
407
408 int16* ptrMini = XMIN_XMAX + 1;
409 XMIN_XMAX[0] = ydep;
410
411 int16* ptrMax = XMIN_XMAX + ((yfin - ydep) * 2) + 1;
412 ptrMax[2] = -1; // mark the end
413
414 // init table with default values
415 int16* si = XMIN_XMAX + 1;
416 int tempCount = nbligne;
417 do {
418 si[0] = 5000;
419 si[1] = -5000;
420 si += 2;
421 } while (--tempCount);
422
423 int16* di = A2ptr;
424 int segCount = nbseg;
425
426 do {
427 int X2 = di[2];
428 int X1 = di[0];
429 int Y2 = di[3];
430 int Y1 = di[1];
431
432
433 int tempAX = Y1;
434 int tempDX = Y2;
435 if (tempAX > tempDX) {
436 // swap
437 tempAX = Y2;
438 tempDX = Y1;
439 }
440
441 // is segment on screen ?
442 if (!((tempAX > 199) || (tempDX < 0))) {
443 int cx = X2 - X1;
444 if (cx == 0) {
445 // vertical line
446 int CX = X2;
447 if (CX < 0)
448 CX = 0;
449
450 int DX = X2;
451 if (DX > 319)
452 DX = 319;
453
454 int16* BX = XMIN_XMAX + (Y2 - ydep) * 2 + 1;
455 int16* DI = XMIN_XMAX + (Y1 - ydep) * 2 + 1;
456
457 if (Y2 >= Y1) {
458 SWAP(BX, DI);
459 }
460
461 do {
462 if ((BX <= ptrMax) && (BX >= ptrMini)) { // are we in screen ?
463 if (CX < BX[0])
464 BX[0] = CX;
465
466 if (DX > BX[1])
467 BX[1] = DX;
468 }
469
470 BX += 2;
471 } while (BX <= DI);
472 } else {
473 if (cx < 0) {
474 cx = -cx;
475
476 SWAP(X1, X2);
477 SWAP(Y1, Y2);
478 }
479 // swap again ?
480 SWAP(X1, X2);
481
482 int dy = Y2 - Y1;
483 if (dy == 0) {
484 // hline
485 int16* ptr = (Y1 - ydep) * 2 + XMIN_XMAX + 1;
486
487 if ((ptr <= ptrMax) && (ptr >= ptrMini)) { // are we in screen ?
488 int CX = X1;
489 if (CX < 0)
490 CX = 0;
491
492 int SI = X2;
493 if (SI > 319)
494 SI = 319;
495
496 if (CX < ptr[0])
497 ptr[0] = CX;
498
499 if (SI > ptr[1])
500 ptr[1] = SI;
501 }
502 } else {
503 int patchAdd = 2;
504
505 if (dy < 0) {
506 dy = -dy;
507 patchAdd = -2;
508 }
509
510 int stepType = 0; // small DY <= DX
511
512 if (dy > cx) {
513 stepType = 1; // DX < DY
514
515 SWAP(dy, cx);
516 }
517 int patchinc1 = 2 * dy;
518
519 int d = 2 * dy - cx;
520 int bx = 2 * (dy - cx);
521
522 int patchinc2 = bx;
523
524 cx++; // cx is the number of pixels to trace
525
526 int16* ptr = (Y1 - ydep) * 2 + XMIN_XMAX + 1;
527
528 if (stepType == 0) {
529 // small step
530 int BP = X2;
531
532 int SI = BP;
533 if (SI < 0)
534 SI = 0;
535 int DX = BP;
536 if (DX > 319)
537 DX = 319;
538
539 do {
540 if ((ptr <= ptrMax) && (ptr >= ptrMini)) { // are we in screen ?
541 if (SI < ptr[0])
542 ptr[0] = SI;
543
544 if (DX > ptr[1])
545 ptr[1] = DX;
546 }
547
548 BP ++;
549
550 // test limits
551 SI = BP;
552 if (SI < 0)
553 SI = 0;
554 DX = BP;
555 if (DX > 319)
556 DX = 319;
557
558 if (d < 0) {
559 d += patchinc1;
560 if (cx == 1) { // last ?
561 if ((ptr <= ptrMax) && (ptr >= ptrMini)) { // are we in screen ?
562 if (SI < ptr[0])
563 ptr[0] = SI;
564
565 if (DX > ptr[1])
566 ptr[1] = DX;
567 }
568 }
569 } else {
570 d += patchinc2;
571 ptr += patchAdd;
572 }
573 } while (--cx);
574 } else {
575 // big step
576 int BP = X2;
577
578 int SI = BP;
579 if (SI < 0)
580 SI = 0;
581 int DX = BP;
582 if (DX > 319)
583 DX = 319;
584
585 do {
586 if ((ptr <= ptrMax) && (ptr >= ptrMini)) { // are we in screen ?
587 if (SI < ptr[0])
588 ptr[0] = SI;
589
590 if (DX > ptr[1])
591 ptr[1] = DX;
592 }
593
594 ptr += patchAdd; // next line
595
596 if (d < 0) {
597 d += patchinc1;
598 } else {
599 d += patchinc2;
600 BP ++;
601
602 // test limits
603 SI = BP;
604 if (SI < 0)
605 SI = 0;
606 DX = BP;
607 if (DX > 319)
608 DX = 319;
609 }
610 } while (--cx);
611 }
612
613 }
614 }
615 }
616
617 di += 2;
618 } while (--segCount);
619 }
620
drawPolyMode1(unsigned char * dataPointer,int linesToDraw)621 unsigned char *drawPolyMode1(unsigned char *dataPointer, int linesToDraw) {
622 int index;
623 int16 *pBufferDest = polyBuffer4 + nbseg * 2;
624
625 nbseg = linesToDraw;
626 index = *(dataPointer++);
627
628 polyXMin = polyXMax = pBufferDest[-2] = pBufferDest[-2 + linesToDraw * 2] = polyBuffer2[index * 2];
629 polyYMin = polyYMax = pBufferDest[-1] = pBufferDest[-1 + linesToDraw * 2] = polyBuffer2[(index * 2) + 1];
630
631 linesToDraw--;
632
633 pBufferDest -= 2;
634
635 A2ptr = pBufferDest;
636
637 do {
638 int value;
639
640 index = *(dataPointer++);
641 value = pBufferDest[-2] = pBufferDest[-2 + nbseg * 2] = polyBuffer2[index * 2];
642
643 if (value < polyXMin) {
644 polyXMin = value;
645 }
646 if (value > polyXMax) {
647 polyXMax = value;
648 }
649
650 value = pBufferDest[-1] = pBufferDest[-1 + nbseg * 2] = polyBuffer2[(index * 2) + 1];
651
652 if (value < polyYMin) {
653 polyYMin = value;
654 }
655 if (value > polyYMax) {
656 polyYMax = value;
657 A2ptr = pBufferDest;
658 }
659
660 pBufferDest -= 2;
661
662 } while (--linesToDraw);
663
664 buildSegment();
665
666 return dataPointer;
667 }
668
drawPolyMode2(unsigned char * dataPointer,int linesToDraw)669 unsigned char *drawPolyMode2(unsigned char *dataPointer, int linesToDraw) {
670 int index;
671 int16 *pBufferDest;
672
673 pBufferDest = polyBuffer4;
674 nbseg = linesToDraw;
675 A2ptr = polyBuffer4;
676 index = *(dataPointer++);
677
678 polyXMin = polyXMax = pBufferDest[0] = pBufferDest[linesToDraw * 2] = polyBuffer2[index * 2];
679 polyYMin = polyYMax = pBufferDest[1] = pBufferDest[linesToDraw * 2 + 1] = polyBuffer2[(index * 2) + 1];
680
681 linesToDraw--;
682
683 pBufferDest += 2;
684
685 do {
686 int value;
687
688 index = *(dataPointer++);
689 value = pBufferDest[0] = pBufferDest[nbseg * 2] = polyBuffer2[index * 2];
690
691 if (value < polyXMin) {
692 polyXMin = value;
693 }
694 if (value > polyXMax) {
695 polyXMax = value;
696 }
697
698 value = pBufferDest[1] = pBufferDest[nbseg * 2 + 1] = polyBuffer2[(index * 2) + 1];
699
700 if (value < polyYMin) {
701 polyYMin = value;
702 }
703 if (value > polyYMax) {
704 polyYMax = value;
705 A2ptr = pBufferDest;
706 }
707
708 pBufferDest += 2;
709
710 } while (--linesToDraw);
711
712 buildSegment();
713
714 return dataPointer;
715 }
716
717 // this function builds the poly model and then calls the draw functions (OLD: mainDrawSub1Sub5)
buildPolyModel(int positionX,int positionY,int scale,char * pMask,char * destBuffer,char * dataPtr)718 void buildPolyModel(int positionX, int positionY, int scale, char *pMask, char *destBuffer, char *dataPtr) {
719 int counter = 0; // numbers of coordinates to process
720 int startX = 0; // first X in model
721 int startY = 0; // first Y in model
722 int x = 0; // current X
723 int offsetXinModel = 0; // offset of the X value in the model
724 int offsetYinModel = 0; // offset of the Y value in the model
725 unsigned char *dataPointer = (unsigned char *)dataPtr;
726 int16 *ptrPoly_1_Buf = DIST_3D;
727 int16 *ptrPoly_2_Buf;
728 polyOutputBuffer = destBuffer; // global
729
730 m_flipLeftRight = 0;
731 m_useSmallScale = 0;
732 m_lowerX = *(dataPointer + 3);
733 m_lowerY = *(dataPointer + 4);
734
735 if (scale < 0) {
736 scale = -scale; // flip left right
737 m_flipLeftRight = 1;
738 }
739
740 if (scale < 0x180) { // If scale is smaller than 384
741 m_useSmallScale = 1;
742 m_scaleValue = scale << 1; // double scale
743 } else {
744 m_scaleValue = scale;
745 }
746
747 dataPointer += 5;
748
749 m_coordCount = (*(dataPointer++)) + 1; // original uses +1 here but its later substracted again, we could skip it
750 m_first_X = *(dataPointer);
751 dataPointer++;
752 m_first_Y = *(dataPointer);
753 dataPointer++;
754 startX = m_lowerX - m_first_X;
755 startY = m_lowerY - m_first_Y;
756
757 if (m_useSmallScale) {
758 startX >>= 1;
759 startY >>= 1;
760 }
761
762 if (m_flipLeftRight)
763 startX = -startX;
764
765 /*
766 * NOTE:
767 *
768 * The original code continues here with using X, Y instead of startX and StartY.
769 *
770 * Original code:
771 * positionX -= (upscaleValue(startX, m_scaleValue) + 0x8000) >> 16;
772 * positionY -= (upscaleValue(startX, m_scaleValue) + 0x8000) >> 16;
773 */
774
775 // get coordinates from data
776
777 startX = positionX - ((upscaleValue(startX, m_scaleValue) + 0x8000) >> 16);
778 startY = positionY - ((upscaleValue(startY, m_scaleValue) + 0x8000) >> 16);
779
780 ptrPoly_1_Buf[0] = 0;
781 ptrPoly_1_Buf[1] = 0;
782 ptrPoly_1_Buf += 2;
783 counter = m_coordCount - 1 - 1; // skip the first pair, we already have the values
784
785 // dpbcl0
786 do {
787 x = *(dataPointer) - m_first_X;
788 dataPointer++;
789 if (m_useSmallScale) { // shrink all coordinates by factor 2 if a scale smaller than 384 is used
790 x >>= 1;
791 }
792 ptrPoly_1_Buf[0] = offsetXinModel - x;
793 ptrPoly_1_Buf++;
794 offsetXinModel = x;
795
796 int y = *(dataPointer) - m_first_Y;
797 dataPointer++;
798 if (m_useSmallScale) {
799 y >>= 1;
800 }
801 ptrPoly_1_Buf[0] = -(offsetYinModel - y);
802 ptrPoly_1_Buf++;
803 offsetYinModel = y;
804
805 } while (--counter);
806
807 // scale and adjust coordinates with offset (using two polybuffers by doing that)
808 ptrPoly_2_Buf = DIST_3D;
809 ptrPoly_1_Buf = polyBuffer2;
810 counter = m_coordCount - 1; // reset counter // process first pair two
811 int m_current_X = 0;
812 int m_current_Y = 0;
813
814 do {
815 x = ptrPoly_2_Buf[0];
816
817 if (m_flipLeftRight == 0) {
818 x = -x;
819 }
820 //////////////////
821
822 m_current_X += upscaleValue(x, m_scaleValue);
823 ptrPoly_1_Buf[0] = ((m_current_X + 0x8000) >> 16) + startX; // adjust X value with start offset
824
825 m_current_Y += upscaleValue(ptrPoly_2_Buf[1], m_scaleValue);
826 ptrPoly_1_Buf[1] = ((m_current_Y + 0x8000) >> 16) + startY; // adjust Y value with start offset
827
828 /////////////////
829
830 ptrPoly_1_Buf += 2;
831 ptrPoly_2_Buf += 2;
832
833 } while (--counter);
834
835 // position of the dataPointer is m_coordCount * 2
836
837 int polygonCount = 0;
838
839 do {
840 int linesToDraw = *dataPointer++;
841
842 if (linesToDraw > 1) { // if value not zero
843 uint16 minimumScale;
844
845 m_color = *dataPointer; // color
846 dataPointer += 2;
847
848 minimumScale = READ_BE_UINT16(dataPointer);
849 dataPointer += 2;
850
851 if ((minimumScale <= scale)) {
852 if (m_flipLeftRight) {
853 drawPolyMode1((unsigned char *)dataPointer, linesToDraw);
854 } else {
855 drawPolyMode2((unsigned char *)dataPointer, linesToDraw);
856 }
857
858 if (destBuffer) {
859 if (pMask) {
860 blitPolyMode1(destBuffer, pMask, polyBuffer4, m_color & 0xFF);
861 } else {
862 blitPolyMode2(destBuffer, polyBuffer4, m_color & 0xFF);
863 }
864 }
865 }
866
867 dataPointer += linesToDraw;
868 } else {
869 dataPointer += 4;
870 }
871
872 polygonCount ++;
873 } while (*dataPointer != 0xFF);
874 }
875
findPoly(char * dataPtr,int positionX,int positionY,int scale,int mouseX,int mouseY)876 bool findPoly(char* dataPtr, int positionX, int positionY, int scale, int mouseX, int mouseY) {
877 int counter = 0; // numbers of coordinates to process
878 int startX = 0; // first X in model
879 int startY = 0; // first Y in model
880 int x = 0; // current X
881 int offsetXinModel = 0; // offset of the X value in the model
882 int offsetYinModel = 0; // offset of the Y value in the model
883 unsigned char *dataPointer = (unsigned char *)dataPtr;
884 int16 *ptrPoly_1_Buf = DIST_3D;
885 int16 *ptrPoly_2_Buf;
886
887 m_flipLeftRight = 0;
888 m_useSmallScale = 0;
889 m_lowerX = *(dataPointer + 3);
890 m_lowerY = *(dataPointer + 4);
891
892 if (scale < 0) {
893 scale = -scale; // flip left right
894 m_flipLeftRight = 1;
895 }
896
897 if (scale < 0x180) { // If scale is smaller than 384
898 m_useSmallScale = 1;
899 m_scaleValue = scale << 1; // double scale
900 } else {
901 m_scaleValue = scale;
902 }
903
904 dataPointer += 5;
905
906 m_coordCount = (*(dataPointer++)) + 1; // original uses +1 here but its later substracted again, we could skip it
907 m_first_X = *(dataPointer);
908 dataPointer++;
909 m_first_Y = *(dataPointer);
910 dataPointer++;
911 startX = m_lowerX - m_first_X;
912 startY = m_lowerY - m_first_Y;
913
914 if (m_useSmallScale) {
915 startX >>= 1;
916 startY >>= 1;
917 }
918
919 if (m_flipLeftRight) {
920 startX = -startX;
921 }
922
923 /*
924 * NOTE:
925 *
926 * The original code continues here with using X, Y instead of startX and StartY.
927 *
928 * Original code:
929 * positionX -= (upscaleValue(startX, m_scaleValue) + 0x8000) >> 16;
930 * positionY -= (upscaleValue(startX, m_scaleValue) + 0x8000) >> 16;
931 */
932
933 // get coordinates from data
934
935 startX = positionX - ((upscaleValue(startX, m_scaleValue) + 0x8000) >> 16);
936 startY = positionY - ((upscaleValue(startY, m_scaleValue) + 0x8000) >> 16);
937
938 ptrPoly_1_Buf[0] = 0;
939 ptrPoly_1_Buf[1] = 0;
940 ptrPoly_1_Buf += 2;
941 counter = m_coordCount - 1 - 1; // skip the first pair, we already have the values
942
943 // dpbcl0
944 do {
945 x = *(dataPointer) - m_first_X;
946 dataPointer++;
947 if (m_useSmallScale) { // shrink all coordinates by factor 2 if a scale smaller than 384 is used
948 x >>= 1;
949 }
950 ptrPoly_1_Buf[0] = offsetXinModel - x;
951 ptrPoly_1_Buf++;
952 offsetXinModel = x;
953
954 int y = *(dataPointer) - m_first_Y;
955 dataPointer++;
956 if (m_useSmallScale)
957 y >>= 1;
958
959 ptrPoly_1_Buf[0] = -(offsetYinModel - y);
960 ptrPoly_1_Buf++;
961 offsetYinModel = y;
962
963 } while (--counter);
964
965 // scale and adjust coordinates with offset (using two polybuffers by doing that)
966 ptrPoly_2_Buf = DIST_3D;
967 ptrPoly_1_Buf = polyBuffer2;
968 counter = m_coordCount - 1; // reset counter // process first pair two
969 int m_current_X = 0;
970 int m_current_Y = 0;
971
972 do {
973 x = ptrPoly_2_Buf[0];
974
975 if (m_flipLeftRight == 0) {
976 x = -x;
977 }
978 //////////////////
979
980 m_current_X += upscaleValue(x, m_scaleValue);
981 ptrPoly_1_Buf[0] = ((m_current_X + 0x8000) >> 16) + startX; // adjust X value with start offset
982
983 m_current_Y += upscaleValue(ptrPoly_2_Buf[1], m_scaleValue);
984 ptrPoly_1_Buf[1] = ((m_current_Y + 0x8000) >> 16) + startY; // adjust Y value with start offset
985
986 /////////////////
987
988 ptrPoly_1_Buf += 2;
989 ptrPoly_2_Buf += 2;
990
991 } while (--counter);
992
993 // position of the dataPointer is m_coordCount * 2
994
995 int polygonCount = 0;
996
997 do {
998 int linesToDraw = *dataPointer++;
999
1000 if (linesToDraw > 1) { // if value not zero
1001 uint16 minimumScale;
1002
1003 m_color = *dataPointer; // color
1004 dataPointer += 2;
1005
1006 minimumScale = READ_BE_UINT16(dataPointer);
1007 dataPointer += 2;
1008
1009 if ((minimumScale <= scale)) {
1010 if (m_flipLeftRight) {
1011 drawPolyMode1((unsigned char *)dataPointer, linesToDraw);
1012 } else {
1013 drawPolyMode2((unsigned char *)dataPointer, linesToDraw);
1014 }
1015
1016 int polygonYMin = XMIN_XMAX[0];
1017 int polygonYMax = polygonYMin + nbligne;
1018
1019 if ((mouseY >= polygonYMin) && (mouseY < polygonYMax)) {
1020 int polygonLineNumber = mouseY - polygonYMin;
1021
1022 int XMIN = XMIN_XMAX[1+polygonLineNumber*2];
1023 int XMAX = XMIN_XMAX[1+polygonLineNumber*2+1];
1024
1025 if ((mouseX >= XMIN) && (mouseX <= XMAX))
1026 return true;
1027 }
1028 }
1029
1030 dataPointer += linesToDraw;
1031 } else {
1032 dataPointer += 4;
1033 }
1034
1035 polygonCount ++;
1036 } while (*dataPointer != 0xFF);
1037
1038 return false;
1039 }
1040
clearMaskBit(int x,int y,unsigned char * pData,int stride)1041 void clearMaskBit(int x, int y, unsigned char* pData, int stride) {
1042 unsigned char* ptr = y * stride + x / 8 + pData;
1043
1044 unsigned char bitToTest = 0x80 >> (x & 7);
1045
1046 *(ptr) &= ~bitToTest;
1047 }
1048
1049
drawMask(unsigned char * workBuf,int wbWidth,int wbHeight,unsigned char * pMask,int maskWidth,int maskHeight,int maskX,int maskY,int passIdx)1050 void drawMask(unsigned char* workBuf, int wbWidth, int wbHeight, unsigned char* pMask, int maskWidth, int maskHeight, int maskX, int maskY, int passIdx) {
1051 for (int y = 0; y < maskHeight; y++) {
1052 for (int x = 0; x < maskWidth*8; x++) {
1053 if (testMask(x, y, pMask, maskWidth)) {
1054 int destX = maskX + x;
1055 int destY = maskY + y;
1056
1057 if ((destX >= 0) && (destX < wbWidth*8) && (destY >= 0) && (destY < wbHeight))
1058 clearMaskBit(destX, destY, workBuf, wbWidth);
1059 }
1060 }
1061 }
1062 }
1063
1064 unsigned char polygonMask[(320*200)/8];
1065
1066 // draw poly sprite (OLD: mainDrawSub1)
mainDrawPolygons(int fileIndex,cellStruct * plWork,int X,int scale,int Y,char * destBuffer,char * dataPtr)1067 void mainDrawPolygons(int fileIndex, cellStruct *plWork, int X, int scale, int Y, char *destBuffer, char *dataPtr) {
1068 int newX;
1069 int newY;
1070 int newScale;
1071 char *newFrame;
1072
1073 int sizeTable[4]; // 0 = left, 1 = right, 2 = bottom, 3 = top
1074
1075 // this function checks if the dataPtr is not 0, else it retrives the data for X, Y, scale and DataPtr again (OLD: mainDrawSub1Sub1)
1076 flipPoly(fileIndex, (int16 *)dataPtr, scale, &newFrame, X, Y, &newX, &newY, &newScale);
1077
1078 // this function fills the sizeTable for the poly (OLD: mainDrawSub1Sub2)
1079 getPolySize(newX, newY, newScale, sizeTable, (unsigned char*)newFrame);
1080
1081 spriteX2 = sizeTable[0] - 2; // left border
1082 spriteX1 = sizeTable[1] + 18; // right border
1083 spriteY2 = sizeTable[2] - 2; // bottom border
1084 spriteY1 = sizeTable[3] + 2; // top border
1085
1086 if (spriteX2 >= 320)
1087 return;
1088 if (spriteX1 < 0)
1089 return;
1090 if (spriteY2 >= 200)
1091 return;
1092 if (spriteY1 < 0)
1093 return;
1094
1095 if (spriteX2 < 0) {
1096 spriteX2 = 0;
1097 }
1098 if (spriteX1 > 320) {
1099 spriteX1 = 320;
1100 }
1101 if (spriteY2 < 0) {
1102 spriteY2 = 0;
1103 }
1104 if (spriteY1 > 200) {
1105 spriteY1 = 200;
1106 }
1107
1108 if (spriteX1 == spriteX2)
1109 return;
1110 if (spriteY1 == spriteY2)
1111 return;
1112
1113 gfxModuleData_addDirtyRect(Common::Rect(spriteX2, spriteY2, spriteX1, spriteY1));
1114
1115 memset(polygonMask, 0xFF, (320*200) / 8);
1116
1117 int numPasses = 0;
1118
1119 while (plWork) {
1120 if (plWork->type == OBJ_TYPE_BGMASK && plWork->freeze == 0) {
1121 objectParamsQuery params;
1122
1123 getMultipleObjectParam(plWork->overlay, plWork->idx, ¶ms);
1124
1125 int maskX = params.X;
1126 int maskY = params.Y;
1127 int maskFrame = params.fileIdx;
1128
1129 if (filesDatabase[maskFrame].subData.resourceType == OBJ_TYPE_BGMASK && filesDatabase[maskFrame].subData.ptrMask) {
1130 drawMask(polygonMask, 40, 200, filesDatabase[maskFrame].subData.ptrMask, filesDatabase[maskFrame].width / 8, filesDatabase[maskFrame].height, maskX, maskY, numPasses++);
1131 } else
1132 if (filesDatabase[maskFrame].subData.resourceType == OBJ_TYPE_SPRITE && filesDatabase[maskFrame].subData.ptrMask) {
1133 drawMask(polygonMask, 40, 200, filesDatabase[maskFrame].subData.ptrMask, filesDatabase[maskFrame].width / 8, filesDatabase[maskFrame].height, maskX, maskY, numPasses++);
1134 }
1135
1136 }
1137
1138 plWork = plWork->next;
1139 }
1140
1141 // this function builds the poly model and then calls the draw functions (OLD: mainDrawSub1Sub5)
1142 buildPolyModel(newX, newY, newScale, (char *)polygonMask, destBuffer, newFrame);
1143 }
1144
drawMessage(const gfxEntryStruct * pGfxPtr,int globalX,int globalY,int width,int newColor,uint8 * ouputPtr)1145 void drawMessage(const gfxEntryStruct *pGfxPtr, int globalX, int globalY, int width, int newColor, uint8 *ouputPtr) {
1146 // this is used for font only
1147
1148 if (pGfxPtr) {
1149 const uint8 *ptr = pGfxPtr->imagePtr;
1150 int height = pGfxPtr->height;
1151
1152 if (width > 310)
1153 width = 310;
1154 if (width + globalX > 319)
1155 globalX = 319 - width;
1156 if (globalY < 0)
1157 globalY = 0;
1158 if (globalX < 0)
1159 globalX = 0;
1160
1161 if (globalY + pGfxPtr->height >= 198) {
1162 globalY = 198 - pGfxPtr->height;
1163 }
1164
1165 gfxModuleData_addDirtyRect(Common::Rect(globalX, globalY, globalX + width, globalY + height));
1166
1167 uint8 *initialOuput = ouputPtr + (globalY * 320) + globalX;
1168
1169 for (int yp = 0; yp < height; yp++) {
1170 uint8 *output = initialOuput + 320 * yp;
1171 int y = globalY + yp;
1172
1173 for (int xp = 0; xp < pGfxPtr->width; xp++) {
1174 int x = globalX + xp;
1175 uint8 color = *(ptr++);
1176
1177 if (color) {
1178 if ((x >= 0) && (x < 320) && (y >= 0) && (y < 200)) {
1179 if (color == 1) {
1180 *output = (uint8) 0;
1181 } else {
1182 *output = (uint8) newColor;
1183 }
1184 }
1185 }
1186 output++;
1187 }
1188 }
1189 }
1190 }
1191
drawSprite(int width,int height,cellStruct * currentObjPtr,const uint8 * dataIn,int ys,int xs,uint8 * output,const uint8 * dataBuf)1192 void drawSprite(int width, int height, cellStruct *currentObjPtr, const uint8 *dataIn, int ys, int xs, uint8 *output, const uint8 *dataBuf) {
1193 int x = 0;
1194 int y = 0;
1195
1196 // Flag the given area as having been changed
1197 Common::Point ps = Common::Point(MAX(MIN(xs, 320), 0), MAX(MIN(ys, 200), 0));
1198 Common::Point pe = Common::Point(MAX(MIN(xs + width, 320), 0), MAX(MIN(ys + height, 200), 0));
1199 if ((ps.x != pe.x) && (ps.y != pe.y))
1200 // At least part of sprite is on-screen
1201 gfxModuleData_addDirtyRect(Common::Rect(ps.x, ps.y, pe.x, pe.y));
1202
1203 cellStruct* plWork = currentObjPtr;
1204 int workBufferSize = height * (width / 8);
1205
1206 unsigned char* workBuf = (unsigned char*)MemAlloc(workBufferSize);
1207 memcpy(workBuf, dataBuf, workBufferSize);
1208
1209 int numPasses = 0;
1210
1211 while (plWork) {
1212 if (plWork->type == OBJ_TYPE_BGMASK && plWork->freeze == 0) {
1213 objectParamsQuery params;
1214
1215 getMultipleObjectParam(plWork->overlay, plWork->idx, ¶ms);
1216
1217 int maskX = params.X;
1218 int maskY = params.Y;
1219 int maskFrame = params.fileIdx;
1220
1221 if (filesDatabase[maskFrame].subData.resourceType == OBJ_TYPE_BGMASK && filesDatabase[maskFrame].subData.ptrMask) {
1222 drawMask(workBuf, width / 8, height, filesDatabase[maskFrame].subData.ptrMask, filesDatabase[maskFrame].width / 8, filesDatabase[maskFrame].height, maskX - xs, maskY - ys, numPasses++);
1223 } else
1224 if (filesDatabase[maskFrame].subData.resourceType == OBJ_TYPE_SPRITE && filesDatabase[maskFrame].subData.ptrMask) {
1225 drawMask(workBuf, width / 8, height, filesDatabase[maskFrame].subData.ptrMask, filesDatabase[maskFrame].width / 8, filesDatabase[maskFrame].height, maskX - xs, maskY - ys, numPasses++);
1226 }
1227
1228 }
1229
1230 plWork = plWork->next;
1231 }
1232
1233 for (y = 0; y < height; y++) {
1234 for (x = 0; x < (width); x++) {
1235 uint8 color = *dataIn++;
1236
1237 if ((x + xs) >= 0 && (x + xs) < 320 && (y + ys) >= 0 && (y + ys) < 200) {
1238 if (testMask(x, y, workBuf, width / 8)) {
1239 output[320 * (y + ys) + x + xs] = color;
1240 }
1241 }
1242 }
1243 }
1244
1245 MemFree(workBuf);
1246 }
1247
1248 #ifdef _DEBUG
drawCtp()1249 void drawCtp() {
1250 /* if (ctp_walkboxTable) {
1251 for (int i = 0; i < 15; i++) {
1252 uint16 *dataPtr = &ctp_walkboxTable[i * 40];
1253 int type = walkboxColor[i]; // show different types in different colors
1254
1255 if (*dataPtr) {
1256 fillpoly((short *)dataPtr + 1, *dataPtr, type);
1257
1258 for (int j = 0; j < (*dataPtr - 1); j++) {
1259 line(dataPtr[1 + j * 2],
1260 dataPtr[1 + j * 2 + 1],
1261 dataPtr[1 + (j + 1) * 2],
1262 dataPtr[1 + (j + 1) * 2 + 1], 0);
1263 }
1264
1265 line(dataPtr[1 + j * 2],
1266 dataPtr[1 + j * 2 + 1], dataPtr[1],
1267 dataPtr[2], 0);
1268 }
1269 }
1270 }*/
1271 }
1272 #endif
1273
drawMenu(menuStruct * pMenu)1274 void drawMenu(menuStruct *pMenu) {
1275 if (pMenu == NULL)
1276 return;
1277
1278 if (pMenu->numElements == 0)
1279 return;
1280
1281 int hline = pMenu->gfx->height;
1282 int x = pMenu->x;
1283 int y = pMenu->y + hline;
1284
1285 int numItemByLine = (199 - hline * 2) / hline;
1286 int nbcol = pMenu->numElements / numItemByLine;
1287
1288 if (!nbcol) {
1289 nbcol++;
1290
1291 if (y + pMenu->numElements*hline > 199 - hline) {
1292 y = 200 - (pMenu->numElements * hline) - hline;
1293 }
1294 } else {
1295 if (pMenu->numElements % numItemByLine) {
1296 nbcol++;
1297 }
1298
1299 y = hline;
1300 }
1301
1302 if (x > (320 - (nbcol*160)))
1303 x = 320 - (nbcol * 160);
1304
1305 if (x < 0)
1306 x = 0;
1307
1308 int wx = x + (nbcol - 1) * (160 / 2);
1309
1310 if (wx <= 320 - 160) {
1311 drawMessage(pMenu->gfx, wx, y - hline, 160, titleColor, gfxModuleData.pPage10);
1312 }
1313
1314 wx = x;
1315 int wy = y;
1316 int wc = 0;
1317 menuElementStruct* p1 = pMenu->ptrNextElement;
1318
1319 while (p1) {
1320 gfxEntryStruct *p2 = p1->gfx;
1321
1322 p1->x = wx;
1323 p1->y = wy;
1324 p1->varA = 160;
1325
1326 int color;
1327
1328 if (p1->selected) {
1329 color = selectColor;
1330 } else {
1331 if (p1->color != 255) {
1332 color = p1->color;
1333 } else {
1334 color = itemColor;
1335 }
1336 }
1337
1338 if (wx <= (320 - 160)) {
1339 drawMessage(p2, wx, wy, 160, color, gfxModuleData.pPage10);
1340 }
1341
1342 wy += hline;
1343 wc ++;
1344
1345 if (wc == numItemByLine) {
1346 wc = 0;
1347 wx += 160;
1348 wy = y;
1349 }
1350
1351 p1 = p1->next;
1352 }
1353 }
1354
getValueFromObjectQuerry(objectParamsQuery * params,int idx)1355 int getValueFromObjectQuerry(objectParamsQuery *params, int idx) {
1356 switch (idx) {
1357 case 0:
1358 return params->X;
1359 case 1:
1360 return params->Y;
1361 case 2:
1362 return params->baseFileIdx;
1363 case 3:
1364 return params->fileIdx;
1365 case 4:
1366 return params->scale;
1367 case 5:
1368 return params->state;
1369 case 6:
1370 return params->state2;
1371 case 7:
1372 return params->nbState;
1373 default:
1374 break;
1375 }
1376
1377 assert(0);
1378
1379 return 0;
1380 }
1381
mainDraw(bool waitFl)1382 void mainDraw(bool waitFl) {
1383 uint8 *bgPtr;
1384 cellStruct *currentObjPtr;
1385 int16 currentObjIdx;
1386 int16 objX1 = 0;
1387 int16 objY1 = 0;
1388 int16 objZ1 = 0;
1389 int16 objX2 = 0;
1390 int16 objY2 = 0;
1391 int16 objZ2 = 0;
1392 int16 spriteHeight;
1393
1394 /*if (PCFadeFlag) {
1395 return;
1396 }*/
1397
1398 bgPtr = backgroundScreens[masterScreen];
1399
1400 if (bgPtr) {
1401 gfxModuleData_gfxCopyScreen(bgPtr, gfxModuleData.pPage10);
1402 if (backgroundChanged[masterScreen]) {
1403 backgroundChanged[masterScreen] = false;
1404 switchBackground(bgPtr);
1405 }
1406 }
1407
1408 autoCellHead.next = NULL;
1409
1410 currentObjPtr = cellHead.next;
1411
1412 #ifdef _DEBUG
1413 /* polyOutputBuffer = (char *)bgPtr;
1414 drawCtp(); */
1415 #endif
1416
1417 //-------------------------------------------------- PROCESS SPRITES -----------------------------------------//
1418
1419 while (currentObjPtr) {
1420 if ((masterScreen == currentObjPtr->backgroundPlane) && (currentObjPtr->freeze == 0) && (currentObjPtr->type == OBJ_TYPE_SPRITE)) {
1421 objectParamsQuery params;
1422
1423 currentObjIdx = currentObjPtr->idx;
1424
1425 if ((currentObjPtr->followObjectOverlayIdx != currentObjPtr->overlay) || (currentObjPtr->followObjectIdx != currentObjPtr->idx)) {
1426 // Declaring this twice ?
1427 // objectParamsQuery params;
1428
1429 getMultipleObjectParam(currentObjPtr->followObjectOverlayIdx, currentObjPtr->followObjectIdx, ¶ms);
1430
1431 objX1 = params.X;
1432 objY1 = params.Y;
1433 objZ1 = params.fileIdx;
1434 } else {
1435 objX1 = 0;
1436 objY1 = 0;
1437 objZ1 = 0;
1438 }
1439
1440 getMultipleObjectParam(currentObjPtr->overlay, currentObjIdx, ¶ms);
1441
1442 objX2 = objX1 + params.X;
1443 objY2 = objY1 + params.Y;
1444 objZ2 = params.fileIdx;
1445
1446 if (objZ2 >= 0) {
1447 objZ2 += objZ1;
1448 }
1449
1450 if ((params.state >= 0) && (objZ2 >= 0) && filesDatabase[objZ2].subData.ptr) {
1451 if (filesDatabase[objZ2].subData.resourceType == 8) { // Poly
1452 mainDrawPolygons(objZ2, currentObjPtr, objX2, params.scale, objY2, (char *)gfxModuleData.pPage10, (char *)filesDatabase[objZ2].subData.ptr); // poly
1453 } else if (filesDatabase[objZ2].subData.resourceType == OBJ_TYPE_SOUND) {
1454 } else if (filesDatabase[objZ2].resType == OBJ_TYPE_MASK) {
1455 } else if (filesDatabase[objZ2].subData.resourceType == OBJ_TYPE_SPRITE) {
1456 objX1 = filesDatabase[objZ2].width; // width
1457 spriteHeight = filesDatabase[objZ2].height; // height
1458
1459 if (filesDatabase[objZ2].subData.ptr) {
1460 drawSprite(objX1, spriteHeight, currentObjPtr, filesDatabase[objZ2].subData.ptr, objY2, objX2, gfxModuleData.pPage10, filesDatabase[objZ2].subData.ptrMask);
1461 }
1462 }
1463 }
1464
1465 // automatic animation process
1466 if (currentObjPtr->animStep && !waitFl) {
1467 if (currentObjPtr->animCounter <= 0) {
1468
1469 bool change = true;
1470
1471 int newVal = getValueFromObjectQuerry(¶ms, currentObjPtr->animChange) + currentObjPtr->animStep;
1472
1473 if (currentObjPtr->animStep > 0) {
1474 if (newVal > currentObjPtr->animEnd) {
1475 if (currentObjPtr->animLoop) {
1476 newVal = currentObjPtr->animStart;
1477 if (currentObjPtr->animLoop > 0)
1478 currentObjPtr->animLoop--;
1479 } else {
1480 change = false;
1481 currentObjPtr->animStep = 0;
1482
1483 if (currentObjPtr->animType) { // should we resume the script ?
1484 if (currentObjPtr->parentType == 20) {
1485 changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &procHead, -1, 0);
1486 } else if (currentObjPtr->parentType == 30) {
1487 changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &relHead, -1, 0);
1488 }
1489 }
1490 }
1491 }
1492 } else {
1493 if (newVal < currentObjPtr->animEnd) {
1494 if (currentObjPtr->animLoop) {
1495 newVal = currentObjPtr->animStart;
1496 if (currentObjPtr->animLoop > 0)
1497 currentObjPtr->animLoop--;
1498 } else {
1499 change = false;
1500 currentObjPtr->animStep = 0;
1501
1502 if (currentObjPtr->animType) { // should we resume the script ?
1503 if (currentObjPtr->parentType == 20) {
1504 changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &procHead, -1, 0);
1505 } else if (currentObjPtr->parentType == 30) {
1506 changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &relHead, -1, 0);
1507 }
1508 }
1509 }
1510 }
1511 }
1512
1513 if (currentObjPtr->animWait >= 0) {
1514 currentObjPtr->animCounter = currentObjPtr->animWait;
1515 }
1516
1517 if ((currentObjPtr->animSignal >= 0) && (currentObjPtr->animSignal == newVal) && (currentObjPtr->animType != 0)) {
1518 if (currentObjPtr->parentType == 20) {
1519 changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &procHead, -1, 0);
1520 } else if (currentObjPtr->parentType == 30) {
1521 changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &relHead, -1, 0);
1522 }
1523
1524 currentObjPtr->animType = 0;
1525 }
1526
1527 if (change) {
1528 addAutoCell(currentObjPtr->overlay, currentObjPtr->idx, currentObjPtr->animChange, newVal, currentObjPtr);
1529 }
1530 } else {
1531 currentObjPtr->animCounter--;
1532 }
1533 }
1534 }
1535
1536 currentObjPtr = currentObjPtr->next;
1537 }
1538
1539 //----------------------------------------------------------------------------------------------------------------//
1540
1541 freeAutoCell();
1542 isMessage = 0;
1543
1544 //-------------------------------------------------- DRAW OBJECTS TYPE 5 (MSG)-----------------------------------------//
1545
1546 currentObjPtr = cellHead.next;
1547
1548 while (currentObjPtr) {
1549 if (currentObjPtr->type == OBJ_TYPE_MESSAGE && currentObjPtr->freeze == 0) {
1550 drawMessage(currentObjPtr->gfxPtr, currentObjPtr->x, currentObjPtr->field_C, currentObjPtr->spriteIdx, currentObjPtr->color, gfxModuleData.pPage10);
1551 isMessage = 1;
1552 }
1553 currentObjPtr = currentObjPtr->next;
1554 }
1555
1556 //----------------------------------------------------------------------------------------------------------------//
1557
1558 if (currentActiveMenu != -1) {
1559 if (menuTable[currentActiveMenu]) {
1560 drawMenu(menuTable[currentActiveMenu]);
1561 return;
1562 }
1563 } else if ((linkedRelation) && (linkedMsgList)) {
1564 int16 mouseX;
1565 int16 mouseY;
1566 int16 button;
1567 getMouseStatus(&main10, &mouseX, &button, &mouseY);
1568
1569 if (mouseY > (linkedMsgList->height)*2)
1570 drawMessage(linkedMsgList, 0, 0, 320, findHighColor(), gfxModuleData.pPage10);
1571 else
1572 drawMessage(linkedMsgList, 0, 200, 320, findHighColor(), gfxModuleData.pPage10);
1573 }
1574 }
1575
1576 } // End of namespace Cruise
1577