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 "prince/prince.h"
24 #include "prince/hero.h"
25 #include "prince/script.h"
26
27 namespace Prince {
28
walkTo()29 void PrinceEngine::walkTo() {
30 if (_mainHero->_visible) {
31 _mainHero->freeHeroAnim();
32 _mainHero->freeOldMove();
33 _interpreter->storeNewPC(_script->_scriptInfo.usdCode);
34 int destX, destY;
35 if (_optionsMob != -1) {
36 destX = _mobList[_optionsMob]._examPosition.x;
37 destY = _mobList[_optionsMob]._examPosition.y;
38 _mainHero->_destDirection = _mobList[_optionsMob]._examDirection;
39 } else {
40 Common::Point mousePos = _system->getEventManager()->getMousePos();
41 destX = mousePos.x + _picWindowX;
42 destY = mousePos.y + _picWindowY;
43 _mainHero->_destDirection = 0;
44 }
45 _mainHero->_coords = makePath(kMainHero, _mainHero->_middleX, _mainHero->_middleY, destX, destY);
46 if (_mainHero->_coords != nullptr) {
47 _mainHero->_currCoords = _mainHero->_coords;
48 _mainHero->_dirTab = _directionTable;
49 _mainHero->_currDirTab = _directionTable;
50 _directionTable = nullptr;
51 _mainHero->_state = Hero::kHeroStateMove;
52 moveShandria();
53 }
54 }
55 }
56
moveRunHero(int heroId,int x,int y,int dir,bool runHeroFlag)57 void PrinceEngine::moveRunHero(int heroId, int x, int y, int dir, bool runHeroFlag) {
58 Hero *hero = nullptr;
59 if (!heroId) {
60 hero = _mainHero;
61 } else if (heroId == 1) {
62 hero = _secondHero;
63 }
64
65 if (hero != nullptr) {
66 if (dir) {
67 hero->_destDirection = dir;
68 }
69 if (x || y) {
70 hero->freeOldMove();
71 hero->_coords = makePath(heroId, hero->_middleX, hero->_middleY, x, y);
72 if (hero->_coords != nullptr) {
73 hero->_currCoords = hero->_coords;
74 hero->_dirTab = _directionTable;
75 hero->_currDirTab = _directionTable;
76 _directionTable = nullptr;
77 if (runHeroFlag) {
78 hero->_state = Hero::kHeroStateRun;
79 } else {
80 hero->_state = Hero::kHeroStateMove;
81 }
82 if (heroId == kMainHero && _mouseFlag) {
83 moveShandria();
84 }
85 }
86 } else {
87 hero->freeOldMove();
88 hero->_state = Hero::kHeroStateTurn;
89 }
90 hero->freeHeroAnim();
91 hero->_visible = 1;
92 }
93 }
94
95 // Modified version of Graphics::drawLine() to allow breaking the loop and return value
drawLine(int x0,int y0,int x1,int y1,int (* plotProc)(int,int,void *),void * data)96 int PrinceEngine::drawLine(int x0, int y0, int x1, int y1, int (*plotProc)(int, int, void *), void *data) {
97 // Bresenham's line algorithm, as described by Wikipedia
98 const bool steep = ABS(y1 - y0) > ABS(x1 - x0);
99
100 if (steep) {
101 SWAP(x0, y0);
102 SWAP(x1, y1);
103 }
104
105 const int delta_x = ABS(x1 - x0);
106 const int delta_y = ABS(y1 - y0);
107 const int delta_err = delta_y;
108 int x = x0;
109 int y = y0;
110 int err = 0;
111
112 const int x_step = (x0 < x1) ? 1 : -1;
113 const int y_step = (y0 < y1) ? 1 : -1;
114
115 int stopFlag = 0;
116 if (steep)
117 stopFlag = (*plotProc)(y, x, data);
118 else
119 stopFlag = (*plotProc)(x, y, data);
120
121 while (x != x1 && !stopFlag) {
122 x += x_step;
123 err += delta_err;
124 if (2 * err > delta_x) {
125 y += y_step;
126 err -= delta_x;
127 }
128 if (steep)
129 stopFlag = (*plotProc)(y, x, data);
130 else
131 stopFlag = (*plotProc)(x, y, data);
132 }
133 return stopFlag;
134 }
135
getPixelAddr(byte * pathBitmap,int x,int y)136 int PrinceEngine::getPixelAddr(byte *pathBitmap, int x, int y) {
137 int mask = 128 >> (x & 7);
138 byte value = pathBitmap[x / 8 + y * 80];
139 return (mask & value);
140 }
141
findPoint(int x,int y)142 void PrinceEngine::findPoint(int x, int y) {
143 _fpX = x;
144 _fpY = y;
145
146 if (getPixelAddr(_roomPathBitmap, x, y)) {
147 return;
148 }
149
150 int fpL = x;
151 int fpU = y;
152 int fpR = x;
153 int fpD = y;
154
155 while (1) {
156 if (fpD != kMaxPicHeight) {
157 if (getPixelAddr(_roomPathBitmap, x, fpD)) {
158 _fpX = x;
159 _fpY = fpD;
160 break;
161 }
162 fpD++;
163 }
164 if (fpU) {
165 if (getPixelAddr(_roomPathBitmap, x, fpU)) {
166 _fpX = x;
167 _fpY = fpU;
168 break;
169 }
170 fpU--;
171 }
172 if (fpL) {
173 if (getPixelAddr(_roomPathBitmap, fpL, y)) {
174 _fpX = fpL;
175 _fpY = y;
176 break;
177 }
178 fpL--;
179 }
180 if (fpR != _sceneWidth) {
181 if (getPixelAddr(_roomPathBitmap, fpR, y)) {
182 _fpX = fpR;
183 _fpY = y;
184 break;
185 }
186 fpR++;
187 }
188 if (!fpU && (fpD == kMaxPicHeight)) {
189 if (!fpL && (fpR == _sceneWidth)) {
190 break;
191 }
192 }
193 }
194 }
195
makeDirection(int x1,int y1,int x2,int y2)196 Direction PrinceEngine::makeDirection(int x1, int y1, int x2, int y2) {
197 if (x1 != x2) {
198 if (y1 != y2) {
199 if (x1 > x2) {
200 if (y1 > y2) {
201 if (x1 - x2 >= y1 - y2) {
202 return kDirLU;
203 } else {
204 return kDirUL;
205 }
206 } else {
207 if (x1 - x2 >= y2 - y1) {
208 return kDirLD;
209 } else {
210 return kDirDL;
211 }
212 }
213 } else {
214 if (y1 > y2) {
215 if (x2 - x1 >= y1 - y2) {
216 return kDirRU;
217 } else {
218 return kDirUR;
219 }
220 } else {
221 if (x2 - x1 >= y2 - y1) {
222 return kDirRD;
223 } else {
224 return kDirDR;
225 }
226 }
227 }
228 } else {
229 if (x1 >= x2) {
230 return kDirL;
231 } else {
232 return kDirR;
233 }
234 }
235 } else {
236 if (y1 >= y2) {
237 return kDirU;
238 } else {
239 return kDirD;
240 }
241 }
242 }
243
specialPlot(int x,int y)244 void PrinceEngine::specialPlot(int x, int y) {
245 if (_coords < _coordsBufEnd) {
246 WRITE_LE_UINT16(_coords, x);
247 _coords += 2;
248 WRITE_LE_UINT16(_coords, y);
249 _coords += 2;
250 specialPlot2(x, y);
251 }
252 }
253
specialPlot2(int x,int y)254 void PrinceEngine::specialPlot2(int x, int y) {
255 int mask = 128 >> (x & 7);
256 _roomPathBitmapTemp[x / 8 + y * 80] |= mask;
257 }
258
specialPlotInside(int x,int y)259 void PrinceEngine::specialPlotInside(int x, int y) {
260 if (_coords < _coordsBufEnd) {
261 WRITE_LE_UINT16(_coords, x);
262 _coords += 2;
263 WRITE_LE_UINT16(_coords, y);
264 _coords += 2;
265 }
266 }
267
plotTraceLine(int x,int y,void * data)268 int PrinceEngine::plotTraceLine(int x, int y, void *data) {
269 PrinceEngine *traceLine = (PrinceEngine *)data;
270 if (!traceLine->_traceLineFirstPointFlag) {
271 if (!traceLine->getPixelAddr(traceLine->_roomPathBitmapTemp, x, y)) {
272 if (traceLine->getPixelAddr(traceLine->_roomPathBitmap, x, y)) {
273 traceLine->specialPlotInside(x, y);
274 traceLine->_traceLineLen++;
275 return 0;
276 } else {
277 return -1;
278 }
279 } else {
280 return 1;
281 }
282 } else {
283 traceLine->_traceLineFirstPointFlag = false;
284 return 0;
285 }
286 }
287
leftDownDir()288 int PrinceEngine::leftDownDir() {
289 if (!checkLeftDownDir()) {
290 specialPlot(_checkX, _checkY);
291 return 0;
292 }
293 if (!checkLeftDir()) {
294 specialPlot(_checkX, _checkY);
295 return 0;
296 }
297 if (!checkDownDir()) {
298 specialPlot(_checkX, _checkY);
299 return 0;
300 }
301 if (!checkLeftUpDir()) {
302 specialPlot(_checkX, _checkY);
303 return 0;
304 }
305 if (!checkRightDownDir()) {
306 specialPlot(_checkX, _checkY);
307 return 0;
308 }
309 if (!checkUpDir()) {
310 specialPlot(_checkX, _checkY);
311 return 0;
312 }
313 if (!checkRightDir()) {
314 specialPlot(_checkX, _checkY);
315 return 0;
316 }
317 if (!checkRightUpDir()) {
318 specialPlot(_checkX, _checkY);
319 return 0;
320 }
321 return -1;
322 }
323
leftDir()324 int PrinceEngine::leftDir() {
325 if (!checkLeftDir()) {
326 specialPlot(_checkX, _checkY);
327 return 0;
328 }
329 if (!checkLeftUpDir()) {
330 specialPlot(_checkX, _checkY);
331 return 0;
332 }
333 if (!checkLeftDownDir()) {
334 specialPlot(_checkX, _checkY);
335 return 0;
336 }
337 if (!checkUpDir()) {
338 specialPlot(_checkX, _checkY);
339 return 0;
340 }
341 if (!checkDownDir()) {
342 specialPlot(_checkX, _checkY);
343 return 0;
344 }
345 if (!checkRightUpDir()) {
346 specialPlot(_checkX, _checkY);
347 return 0;
348 }
349 if (!checkRightDownDir()) {
350 specialPlot(_checkX, _checkY);
351 return 0;
352 }
353 if (!checkRightDir()) {
354 specialPlot(_checkX, _checkY);
355 return 0;
356 }
357 return -1;
358 }
359
leftUpDir()360 int PrinceEngine::leftUpDir() {
361 if (!checkLeftUpDir()) {
362 specialPlot(_checkX, _checkY);
363 return 0;
364 }
365 if (!checkLeftDir()) {
366 specialPlot(_checkX, _checkY);
367 return 0;
368 }
369 if (!checkUpDir()) {
370 specialPlot(_checkX, _checkY);
371 return 0;
372 }
373 if (!checkLeftDownDir()) {
374 specialPlot(_checkX, _checkY);
375 return 0;
376 }
377 if (!checkRightUpDir()) {
378 specialPlot(_checkX, _checkY);
379 return 0;
380 }
381 if (!checkDownDir()) {
382 specialPlot(_checkX, _checkY);
383 return 0;
384 }
385 if (!checkRightDir()) {
386 specialPlot(_checkX, _checkY);
387 return 0;
388 }
389 if (!checkRightDownDir()) {
390 specialPlot(_checkX, _checkY);
391 return 0;
392 }
393 return -1;
394 }
395
rightDownDir()396 int PrinceEngine::rightDownDir() {
397 if (!checkRightDownDir()) {
398 specialPlot(_checkX, _checkY);
399 return 0;
400 }
401 if (!checkRightDir()) {
402 specialPlot(_checkX, _checkY);
403 return 0;
404 }
405 if (!checkDownDir()) {
406 specialPlot(_checkX, _checkY);
407 return 0;
408 }
409 if (!checkRightUpDir()) {
410 specialPlot(_checkX, _checkY);
411 return 0;
412 }
413 if (!checkLeftDownDir()) {
414 specialPlot(_checkX, _checkY);
415 return 0;
416 }
417 if (!checkUpDir()) {
418 specialPlot(_checkX, _checkY);
419 return 0;
420 }
421 if (!checkLeftDir()) {
422 specialPlot(_checkX, _checkY);
423 return 0;
424 }
425 if (!checkLeftUpDir()) {
426 specialPlot(_checkX, _checkY);
427 return 0;
428 }
429 return -1;
430 }
431
rightDir()432 int PrinceEngine::rightDir() {
433 if (!checkRightDir()) {
434 specialPlot(_checkX, _checkY);
435 return 0;
436 }
437 if (!checkRightUpDir()) {
438 specialPlot(_checkX, _checkY);
439 return 0;
440 }
441 if (!checkRightDownDir()) {
442 specialPlot(_checkX, _checkY);
443 return 0;
444 }
445 if (!checkUpDir()) {
446 specialPlot(_checkX, _checkY);
447 return 0;
448 }
449 if (!checkDownDir()) {
450 specialPlot(_checkX, _checkY);
451 return 0;
452 }
453 if (!checkLeftUpDir()) {
454 specialPlot(_checkX, _checkY);
455 return 0;
456 }
457 if (!checkLeftDownDir()) {
458 specialPlot(_checkX, _checkY);
459 return 0;
460 }
461 if (!checkLeftDir()) {
462 specialPlot(_checkX, _checkY);
463 return 0;
464 }
465 return -1;
466 }
467
rightUpDir()468 int PrinceEngine::rightUpDir() {
469 if (!checkRightUpDir()) {
470 specialPlot(_checkX, _checkY);
471 return 0;
472 }
473 if (!checkRightDir()) {
474 specialPlot(_checkX, _checkY);
475 return 0;
476 }
477 if (!checkUpDir()) {
478 specialPlot(_checkX, _checkY);
479 return 0;
480 }
481 if (!checkRightDownDir()) {
482 specialPlot(_checkX, _checkY);
483 return 0;
484 }
485 if (!checkLeftUpDir()) {
486 specialPlot(_checkX, _checkY);
487 return 0;
488 }
489 if (!checkDownDir()) {
490 specialPlot(_checkX, _checkY);
491 return 0;
492 }
493 if (!checkLeftDir()) {
494 specialPlot(_checkX, _checkY);
495 return 0;
496 }
497 if (!checkLeftDownDir()) {
498 specialPlot(_checkX, _checkY);
499 return 0;
500 }
501 return -1;
502 }
503
upLeftDir()504 int PrinceEngine::upLeftDir() {
505 if (!checkLeftUpDir()) {
506 specialPlot(_checkX, _checkY);
507 return 0;
508 }
509 if (!checkUpDir()) {
510 specialPlot(_checkX, _checkY);
511 return 0;
512 }
513 if (!checkLeftDir()) {
514 specialPlot(_checkX, _checkY);
515 return 0;
516 }
517 if (!checkRightUpDir()) {
518 specialPlot(_checkX, _checkY);
519 return 0;
520 }
521 if (!checkLeftDownDir()) {
522 specialPlot(_checkX, _checkY);
523 return 0;
524 }
525 if (!checkRightDir()) {
526 specialPlot(_checkX, _checkY);
527 return 0;
528 }
529 if (!checkDownDir()) {
530 specialPlot(_checkX, _checkY);
531 return 0;
532 }
533 if (!checkRightDownDir()) {
534 specialPlot(_checkX, _checkY);
535 return 0;
536 }
537 return -1;
538 }
539
upDir()540 int PrinceEngine::upDir() {
541 if (!checkUpDir()) {
542 specialPlot(_checkX, _checkY);
543 return 0;
544 }
545 if (!checkLeftUpDir()) {
546 specialPlot(_checkX, _checkY);
547 return 0;
548 }
549 if (!checkRightUpDir()) {
550 specialPlot(_checkX, _checkY);
551 return 0;
552 }
553 if (!checkLeftDir()) {
554 specialPlot(_checkX, _checkY);
555 return 0;
556 }
557 if (!checkRightDir()) {
558 specialPlot(_checkX, _checkY);
559 return 0;
560 }
561 if (!checkLeftDownDir()) {
562 specialPlot(_checkX, _checkY);
563 return 0;
564 }
565 if (!checkRightDownDir()) {
566 specialPlot(_checkX, _checkY);
567 return 0;
568 }
569 if (!checkDownDir()) {
570 specialPlot(_checkX, _checkY);
571 return 0;
572 }
573 return -1;
574 }
575
upRightDir()576 int PrinceEngine::upRightDir() {
577 if (!checkRightUpDir()) {
578 specialPlot(_checkX, _checkY);
579 return 0;
580 }
581 if (!checkUpDir()) {
582 specialPlot(_checkX, _checkY);
583 return 0;
584 }
585 if (!checkRightDir()) {
586 specialPlot(_checkX, _checkY);
587 return 0;
588 }
589 if (!checkLeftUpDir()) {
590 specialPlot(_checkX, _checkY);
591 return 0;
592 }
593 if (!checkRightDownDir()) {
594 specialPlot(_checkX, _checkY);
595 return 0;
596 }
597 if (!checkLeftDir()) {
598 specialPlot(_checkX, _checkY);
599 return 0;
600 }
601 if (!checkDownDir()) {
602 specialPlot(_checkX, _checkY);
603 return 0;
604 }
605 if (!checkLeftDownDir()) {
606 specialPlot(_checkX, _checkY);
607 return 0;
608 }
609 return -1;
610 }
611
downLeftDir()612 int PrinceEngine::downLeftDir() {
613 if (!checkLeftDownDir()) {
614 specialPlot(_checkX, _checkY);
615 return 0;
616 }
617 if (!checkDownDir()) {
618 specialPlot(_checkX, _checkY);
619 return 0;
620 }
621 if (!checkLeftDir()) {
622 specialPlot(_checkX, _checkY);
623 return 0;
624 }
625 if (!checkRightDownDir()) {
626 specialPlot(_checkX, _checkY);
627 return 0;
628 }
629 if (!checkLeftUpDir()) {
630 specialPlot(_checkX, _checkY);
631 return 0;
632 }
633 if (!checkRightDir()) {
634 specialPlot(_checkX, _checkY);
635 return 0;
636 }
637 if (!checkUpDir()) {
638 specialPlot(_checkX, _checkY);
639 return 0;
640 }
641 if (!checkRightUpDir()) {
642 specialPlot(_checkX, _checkY);
643 return 0;
644 }
645 return -1;
646 }
647
downDir()648 int PrinceEngine::downDir() {
649 if (!checkDownDir()) {
650 specialPlot(_checkX, _checkY);
651 return 0;
652 }
653 if (!checkRightDownDir()) {
654 specialPlot(_checkX, _checkY);
655 return 0;
656 }
657 if (!checkLeftDownDir()) {
658 specialPlot(_checkX, _checkY);
659 return 0;
660 }
661 if (!checkRightDir()) {
662 specialPlot(_checkX, _checkY);
663 return 0;
664 }
665 if (!checkLeftDir()) {
666 specialPlot(_checkX, _checkY);
667 return 0;
668 }
669 if (!checkRightUpDir()) {
670 specialPlot(_checkX, _checkY);
671 return 0;
672 }
673 if (!checkLeftUpDir()) {
674 specialPlot(_checkX, _checkY);
675 return 0;
676 }
677 if (!checkUpDir()) {
678 specialPlot(_checkX, _checkY);
679 return 0;
680 }
681 return -1;
682 }
683
downRightDir()684 int PrinceEngine::downRightDir() {
685 if (!checkRightDownDir()) {
686 specialPlot(_checkX, _checkY);
687 return 0;
688 }
689 if (!checkDownDir()) {
690 specialPlot(_checkX, _checkY);
691 return 0;
692 }
693 if (!checkRightDir()) {
694 specialPlot(_checkX, _checkY);
695 return 0;
696 }
697 if (!checkLeftDownDir()) {
698 specialPlot(_checkX, _checkY);
699 return 0;
700 }
701 if (!checkRightUpDir()) {
702 specialPlot(_checkX, _checkY);
703 return 0;
704 }
705 if (!checkLeftDir()) {
706 specialPlot(_checkX, _checkY);
707 return 0;
708 }
709 if (!checkUpDir()) {
710 specialPlot(_checkX, _checkY);
711 return 0;
712 }
713 if (!checkLeftUpDir()) {
714 specialPlot(_checkX, _checkY);
715 return 0;
716 }
717 return -1;
718 }
719
cpe()720 int PrinceEngine::cpe() {
721 if ((*(_checkBitmap - kPBW) & _checkMask)) {
722 if ((*(_checkBitmap + kPBW) & _checkMask)) {
723 int value;
724 switch (_checkMask) {
725 case 128:
726 value = READ_LE_UINT16(_checkBitmap - 1);
727 value &= 0x4001;
728 if (value != 0x4001) {
729 return 0;
730 }
731 break;
732 case 64:
733 value = *_checkBitmap;
734 value &= 0xA0;
735 if (value != 0xA0) {
736 return 0;
737 }
738 break;
739 case 32:
740 value = *_checkBitmap;
741 value &= 0x50;
742 if (value != 0x50) {
743 return 0;
744 }
745 break;
746 case 16:
747 value = *_checkBitmap;
748 value &= 0x28;
749 if (value != 0x28) {
750 return 0;
751 }
752 break;
753 case 8:
754 value = *_checkBitmap;
755 value &= 0x14;
756 if (value != 0x14) {
757 return 0;
758 }
759 break;
760 case 4:
761 value = *_checkBitmap;
762 value &= 0xA;
763 if (value != 0xA) {
764 return 0;
765 }
766 break;
767 case 2:
768 value = *_checkBitmap;
769 value &= 0x5;
770 if (value != 0x5) {
771 return 0;
772 }
773 break;
774 case 1:
775 value = READ_LE_UINT16(_checkBitmap);
776 value &= 0x8002;
777 if (value != 0x8002) {
778 return 0;
779 }
780 break;
781 default:
782 error("Wrong _checkMask value - cpe()");
783 break;
784 }
785 _checkX = _rembX;
786 _checkY = _rembY;
787 _checkBitmapTemp = _rembBitmapTemp;
788 _checkBitmap = _rembBitmap;
789 _checkMask = _rembMask;
790 return -1;
791 }
792 return 0;
793 }
794 return 0;
795 }
796
checkLeftDownDir()797 int PrinceEngine::checkLeftDownDir() {
798 if (_checkX && _checkY != (kMaxPicHeight / 2 - 1)) {
799 int tempMask = _checkMask;
800 if (tempMask != 128) {
801 tempMask <<= 1;
802 if ((*(_checkBitmap + kPBW) & tempMask)) {
803 if (!(*(_checkBitmapTemp + kPBW) & tempMask)) {
804 _checkBitmap += kPBW;
805 _checkBitmapTemp += kPBW;
806 _checkMask = tempMask;
807 } else {
808 return 1;
809 }
810 } else {
811 return -1;
812 }
813 } else {
814 if ((*(_checkBitmap + kPBW - 1) & 1)) {
815 if (!(*(_checkBitmapTemp + kPBW - 1) & 1)) {
816 _checkBitmap += (kPBW - 1);
817 _checkBitmapTemp += (kPBW - 1);
818 _checkMask = 1;
819 } else {
820 return 1;
821 }
822 } else {
823 return -1;
824 }
825 }
826 _checkX--;
827 _checkY++;
828 return cpe();
829 } else {
830 return -1;
831 }
832 }
833
checkLeftDir()834 int PrinceEngine::checkLeftDir() {
835 if (_checkX) {
836 int tempMask = _checkMask;
837 if (tempMask != 128) {
838 tempMask <<= 1;
839 if ((*(_checkBitmap) & tempMask)) {
840 if (!(*(_checkBitmapTemp) & tempMask)) {
841 _checkMask = tempMask;
842 } else {
843 return 1;
844 }
845 } else {
846 return -1;
847 }
848 } else {
849 if ((*(_checkBitmap - 1) & 1)) {
850 if (!(*(_checkBitmapTemp - 1) & 1)) {
851 _checkBitmap--;
852 _checkBitmapTemp--;
853 _checkMask = 1;
854 } else {
855 return 1;
856 }
857 } else {
858 return -1;
859 }
860 }
861 _checkX--;
862 return cpe();
863 } else {
864 return -1;
865 }
866 }
867
checkDownDir()868 int PrinceEngine::checkDownDir() {
869 if (_checkY != (kMaxPicHeight / 2 - 1)) {
870 if ((*(_checkBitmap + kPBW) & _checkMask)) {
871 if (!(*(_checkBitmapTemp + kPBW) & _checkMask)) {
872 _checkBitmap += kPBW;
873 _checkBitmapTemp += kPBW;
874 _checkY++;
875 return cpe();
876 } else {
877 return 1;
878 }
879 } else {
880 return -1;
881 }
882 } else {
883 return -1;
884 }
885 }
886
checkUpDir()887 int PrinceEngine::checkUpDir() {
888 if (_checkY) {
889 if ((*(_checkBitmap - kPBW) & _checkMask)) {
890 if (!(*(_checkBitmapTemp - kPBW) & _checkMask)) {
891 _checkBitmap -= kPBW;
892 _checkBitmapTemp -= kPBW;
893 _checkY--;
894 return cpe();
895 } else {
896 return 1;
897 }
898 } else {
899 return -1;
900 }
901 } else {
902 return -1;
903 }
904 }
905
checkRightDir()906 int PrinceEngine::checkRightDir() {
907 if (_checkX != (kMaxPicWidth / 2 - 1)) {
908 int tempMask = _checkMask;
909 if (tempMask != 1) {
910 tempMask >>= 1;
911 if ((*(_checkBitmap) & tempMask)) {
912 if (!(*(_checkBitmapTemp) & tempMask)) {
913 _checkMask = tempMask;
914 } else {
915 return 1;
916 }
917 } else {
918 return -1;
919 }
920 } else {
921 if ((*(_checkBitmap + 1) & 128)) {
922 if (!(*(_checkBitmapTemp + 1) & 128)) {
923 _checkBitmap++;
924 _checkBitmapTemp++;
925 _checkMask = 128;
926 } else {
927 return 1;
928 }
929 } else {
930 return -1;
931 }
932 }
933 _checkX++;
934 return cpe();
935 } else {
936 return -1;
937 }
938 }
939
checkLeftUpDir()940 int PrinceEngine::checkLeftUpDir() {
941 if (_checkX && _checkY) {
942 int tempMask = _checkMask;
943 if (tempMask != 128) {
944 tempMask <<= 1;
945 if ((*(_checkBitmap - kPBW) & tempMask)) {
946 if (!(*(_checkBitmapTemp - kPBW) & tempMask)) {
947 _checkBitmap -= kPBW;
948 _checkBitmapTemp -= kPBW;
949 _checkMask = tempMask;
950 } else {
951 return 1;
952 }
953 } else {
954 return -1;
955 }
956 } else {
957 if ((*(_checkBitmap - (kPBW + 1)) & 1)) {
958 if (!(*(_checkBitmapTemp - (kPBW + 1)) & 1)) {
959 _checkBitmap -= (kPBW + 1);
960 _checkBitmapTemp -= (kPBW + 1);
961 _checkMask = 1;
962 } else {
963 return 1;
964 }
965 } else {
966 return -1;
967 }
968 }
969 _checkX--;
970 _checkY--;
971 return cpe();
972 } else {
973 return -1;
974 }
975 }
976
checkRightDownDir()977 int PrinceEngine::checkRightDownDir() {
978 if (_checkX != (kMaxPicWidth / 2 - 1) && _checkY != (kMaxPicHeight / 2 - 1)) {
979 int tempMask = _checkMask;
980 if (tempMask != 1) {
981 tempMask >>= 1;
982 if ((*(_checkBitmap + kPBW) & tempMask)) {
983 if (!(*(_checkBitmapTemp + kPBW) & tempMask)) {
984 _checkBitmap += kPBW;
985 _checkBitmapTemp += kPBW;
986 _checkMask = tempMask;
987 } else {
988 return 1;
989 }
990 } else {
991 return -1;
992 }
993 } else {
994 if ((*(_checkBitmap + kPBW + 1) & 128)) {
995 if (!(*(_checkBitmapTemp + kPBW + 1) & 128)) {
996 _checkBitmap += kPBW + 1;
997 _checkBitmapTemp += kPBW + 1;
998 _checkMask = 128;
999 } else {
1000 return 1;
1001 }
1002 } else {
1003 return -1;
1004 }
1005 }
1006 _checkX++;
1007 _checkY++;
1008 return cpe();
1009 } else {
1010 return -1;
1011 }
1012 }
1013
checkRightUpDir()1014 int PrinceEngine::checkRightUpDir() {
1015 if (_checkX != (kMaxPicWidth / 2 - 1) && _checkY) {
1016 int tempMask = _checkMask;
1017 if (tempMask != 1) {
1018 tempMask >>= 1;
1019 if ((*(_checkBitmap - kPBW) & tempMask)) {
1020 if (!(*(_checkBitmapTemp - kPBW) & tempMask)) {
1021 _checkBitmap -= kPBW;
1022 _checkBitmapTemp -= kPBW;
1023 _checkMask = tempMask;
1024 } else {
1025 return 1;
1026 }
1027 } else {
1028 return -1;
1029 }
1030 } else {
1031 if ((*(_checkBitmap - kPBW + 1) & 128)) {
1032 if (!(*(_checkBitmapTemp - kPBW + 1) & 128)) {
1033 _checkBitmap -= (kPBW - 1);
1034 _checkBitmapTemp -= (kPBW - 1);
1035 _checkMask = 128;
1036 } else {
1037 return 1;
1038 }
1039 } else {
1040 return -1;
1041 }
1042 }
1043 _checkX++;
1044 _checkY--;
1045 return cpe();
1046 } else {
1047 return -1;
1048 }
1049 }
1050
tracePath(int x1,int y1,int x2,int y2)1051 bool PrinceEngine::tracePath(int x1, int y1, int x2, int y2) {
1052 for (uint i = 0; i < kPathBitmapLen; i++) {
1053 _roomPathBitmapTemp[i] = 0;
1054 }
1055 if (x1 != x2 || y1 != y2) {
1056 if (getPixelAddr(_roomPathBitmap, x1, y1)) {
1057 if (getPixelAddr(_roomPathBitmap, x2, y2)) {
1058 _coords = _coordsBuf;
1059 specialPlot(x1, y1);
1060
1061 int x = x1;
1062 int y = y1;
1063
1064 while (1) {
1065 int btx = x;
1066 int bty = y;
1067 byte *bcad = _coords;
1068
1069 _traceLineLen = 0;
1070 _traceLineFirstPointFlag = true;
1071 int drawLineFlag = drawLine(x, y, x2, y2, &this->plotTraceLine, this);
1072
1073 if (!drawLineFlag) {
1074 return true;
1075 } else if (drawLineFlag == -1 && _traceLineLen >= 2) {
1076 byte *tempCorrds = bcad;
1077 while (tempCorrds != _coords) {
1078 x = READ_LE_UINT16(tempCorrds);
1079 y = READ_LE_UINT16(tempCorrds + 2);
1080 tempCorrds += 4;
1081 specialPlot2(x, y);
1082 }
1083 } else {
1084 _coords = bcad;
1085 x = btx;
1086 y = bty;
1087 }
1088
1089 Direction dir = makeDirection(x, y, x2, y2);
1090
1091 _rembBitmapTemp = &_roomPathBitmapTemp[x / 8 + y * 80];
1092 _rembBitmap = &_roomPathBitmap[x / 8 + y * 80];
1093 _rembMask = 128 >> (x & 7);
1094 _rembX = x;
1095 _rembY = y;
1096
1097 _checkBitmapTemp = _rembBitmapTemp;
1098 _checkBitmap = _rembBitmap;
1099 _checkMask = _rembMask;
1100 _checkX = _rembX;
1101 _checkY = _rembY;
1102
1103 int result;
1104 switch (dir) {
1105 case kDirLD:
1106 result = leftDownDir();
1107 break;
1108 case kDirL:
1109 result = leftDir();
1110 break;
1111 case kDirLU:
1112 result = leftUpDir();
1113 break;
1114 case kDirRD:
1115 result = rightDownDir();
1116 break;
1117 case kDirR:
1118 result = rightDir();
1119 break;
1120 case kDirRU:
1121 result = rightUpDir();
1122 break;
1123 case kDirUL:
1124 result = upLeftDir();
1125 break;
1126 case kDirU:
1127 result = upDir();
1128 break;
1129 case kDirUR:
1130 result = upRightDir();
1131 break;
1132 case kDirDL:
1133 result = downLeftDir();
1134 break;
1135 case kDirD:
1136 result = downDir();
1137 break;
1138 case kDirDR:
1139 result = downRightDir();
1140 break;
1141 default:
1142 result = -1;
1143 error("tracePath: wrong direction %d", dir);
1144 break;
1145 }
1146
1147 if (result) {
1148 byte *tempCoords = _coords;
1149 tempCoords -= 4;
1150 if (tempCoords > _coordsBuf) {
1151 int tempX = READ_LE_UINT16(tempCoords);
1152 int tempY = READ_LE_UINT16(tempCoords + 2);
1153 if (_checkX == tempX && _checkY == tempY) {
1154 _coords = tempCoords;
1155 }
1156 x = READ_LE_UINT16(tempCoords);
1157 y = READ_LE_UINT16(tempCoords + 2);
1158 } else {
1159 return false;
1160 }
1161 } else {
1162 x = _checkX;
1163 y = _checkY;
1164 }
1165 }
1166 return true;
1167 } else {
1168 error("tracePath: wrong destination point");
1169 }
1170 } else {
1171 error("tracePath: wrong start point");
1172 }
1173 } else {
1174 error("tracePath: same point");
1175 }
1176 }
1177
specialPlotInside2(int x,int y)1178 void PrinceEngine::specialPlotInside2(int x, int y) {
1179 WRITE_LE_UINT16(_coords2, x);
1180 _coords2 += 2;
1181 WRITE_LE_UINT16(_coords2, y);
1182 _coords2 += 2;
1183 }
1184
plotTracePoint(int x,int y,void * data)1185 int PrinceEngine::plotTracePoint(int x, int y, void *data) {
1186 PrinceEngine *tracePoint = (PrinceEngine *)data;
1187 if (!tracePoint->_tracePointFirstPointFlag) {
1188 if (tracePoint->getPixelAddr(tracePoint->_roomPathBitmap, x, y)) {
1189 tracePoint->specialPlotInside2(x, y);
1190 return 0;
1191 } else {
1192 return -1;
1193 }
1194 } else {
1195 tracePoint->_tracePointFirstPointFlag = false;
1196 return 0;
1197 }
1198 }
1199
approxPath()1200 void PrinceEngine::approxPath() {
1201 byte *oldCoords;
1202 _coords2 = _coordsBuf2;
1203 byte *tempCoordsBuf = _coordsBuf; // first point on path
1204 byte *tempCoords = _coords;
1205 if (tempCoordsBuf != tempCoords) {
1206 tempCoords -= 4; // last point on path
1207 while (tempCoordsBuf != tempCoords) {
1208 int x1 = READ_LE_UINT16(tempCoords);
1209 int y1 = READ_LE_UINT16(tempCoords + 2);
1210 int x2 = READ_LE_UINT16(tempCoordsBuf);
1211 int y2 = READ_LE_UINT16(tempCoordsBuf + 2);
1212 tempCoordsBuf += 4;
1213 //TracePoint
1214 oldCoords = _coords2;
1215 if (_coords2 == _coordsBuf2) {
1216 WRITE_LE_UINT16(_coords2, x1);
1217 WRITE_LE_UINT16(_coords2 + 2, y1);
1218 _coords2 += 4;
1219 } else {
1220 int testX = READ_LE_UINT16(_coords2 - 4);
1221 int testY = READ_LE_UINT16(_coords2 - 2);
1222 if (testX != x1 || testY != y1) {
1223 WRITE_LE_UINT16(_coords2, x1);
1224 WRITE_LE_UINT16(_coords2 + 2, y1);
1225 _coords2 += 4;
1226 }
1227 }
1228 _tracePointFirstPointFlag = true;
1229 bool drawLineFlag = drawLine(x1, y1, x2, y2, &this->plotTracePoint, this);
1230 if (!drawLineFlag) {
1231 tempCoords = tempCoordsBuf - 4;
1232 tempCoordsBuf = _coordsBuf;
1233 } else {
1234 _coords2 = oldCoords;
1235 }
1236 }
1237 }
1238 }
1239
freeDirectionTable()1240 void PrinceEngine::freeDirectionTable() {
1241 if (_directionTable != nullptr) {
1242 free(_directionTable);
1243 _directionTable = nullptr;
1244 }
1245 }
1246
scanDirectionsFindNext(byte * tempCoordsBuf,int xDiff,int yDiff)1247 int PrinceEngine::scanDirectionsFindNext(byte *tempCoordsBuf, int xDiff, int yDiff) {
1248
1249 int tempX, tempY, direction;
1250
1251 tempX = Hero::kHeroDirLeft;
1252 if (xDiff < 0) {
1253 tempX = Hero::kHeroDirRight;
1254 }
1255
1256 tempY = Hero::kHeroDirUp;
1257 if (yDiff < 0) {
1258 tempY = Hero::kHeroDirDown;
1259 }
1260
1261 while (1) {
1262 int againPointX1 = READ_LE_UINT16(tempCoordsBuf);
1263 int againPointY1 = READ_LE_UINT16(tempCoordsBuf + 2);
1264 tempCoordsBuf += 4;
1265
1266 if (tempCoordsBuf == _coords) {
1267 direction = tempX;
1268 break;
1269 }
1270
1271 int dX = againPointX1 - READ_LE_UINT16(tempCoordsBuf);
1272 int dY = againPointY1 - READ_LE_UINT16(tempCoordsBuf + 2);
1273
1274 if (dX != xDiff) {
1275 direction = tempY;
1276 break;
1277 }
1278
1279 if (dY != yDiff) {
1280 direction = tempX;
1281 break;
1282 }
1283 }
1284 return direction;
1285 }
1286
scanDirections()1287 void PrinceEngine::scanDirections() {
1288 freeDirectionTable();
1289 byte *tempCoordsBuf = _coordsBuf;
1290 if (tempCoordsBuf != _coords) {
1291 int size = (_coords - tempCoordsBuf) / 4 + 1; // number of coord points plus one for end marker
1292 _directionTable = (byte *)malloc(size);
1293 byte *tempDirTab = _directionTable;
1294 int direction = -1;
1295 int lastDirection = -1;
1296
1297 while (1) {
1298 int x1 = READ_LE_UINT16(tempCoordsBuf);
1299 int y1 = READ_LE_UINT16(tempCoordsBuf + 2);
1300 tempCoordsBuf += 4;
1301 if (tempCoordsBuf == _coords) {
1302 break;
1303 }
1304 int x2 = READ_LE_UINT16(tempCoordsBuf);
1305 int y2 = READ_LE_UINT16(tempCoordsBuf + 2);
1306
1307 int xDiff = x1 - x2;
1308 int yDiff = y1 - y2;
1309
1310 if (xDiff) {
1311 if (yDiff) {
1312 if (lastDirection != -1) {
1313 direction = lastDirection;
1314 if (direction == Hero::kHeroDirLeft) {
1315 if (xDiff < 0) {
1316 direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
1317 }
1318 } else if (direction == Hero::kHeroDirRight) {
1319 if (xDiff >= 0) {
1320 direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
1321 }
1322 } else if (direction == Hero::kHeroDirUp) {
1323 if (yDiff < 0) {
1324 direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
1325 }
1326 } else {
1327 if (yDiff >= 0) {
1328 direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
1329 }
1330 }
1331 } else {
1332 direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
1333 }
1334 } else {
1335 direction = Hero::kHeroDirLeft;
1336 if (xDiff < 0) {
1337 direction = Hero::kHeroDirRight;
1338 }
1339 }
1340 } else {
1341 if (yDiff) {
1342 direction = Hero::kHeroDirUp;
1343 if (yDiff < 0) {
1344 direction = Hero::kHeroDirDown;
1345 }
1346 } else {
1347 direction = lastDirection;
1348 }
1349 }
1350 lastDirection = direction;
1351 *tempDirTab = direction;
1352 tempDirTab++;
1353 }
1354 *tempDirTab = *(tempDirTab - 1);
1355 tempDirTab++;
1356 *tempDirTab = 0;
1357 }
1358 }
1359
moveShandria()1360 void PrinceEngine::moveShandria() {
1361 int shanLen1 = _shanLen;
1362 if (_flags->getFlagValue(Flags::SHANDOG)) {
1363 _secondHero->freeHeroAnim();
1364 _secondHero->freeOldMove();
1365 byte *shanCoords = _mainHero->_currCoords + shanLen1 * 4 - 4;
1366 int shanX = READ_LE_UINT16(shanCoords - 4);
1367 int shanY = READ_LE_UINT16(shanCoords - 2);
1368 int xDiff = shanX - _secondHero->_middleX;
1369 if (xDiff < 0) {
1370 xDiff *= -1;
1371 }
1372 int yDiff = shanY - _secondHero->_middleY;
1373 if (yDiff < 0) {
1374 yDiff *= -1;
1375 }
1376 shanCoords -= 4;
1377 if (shanCoords != _mainHero->_currCoords) {
1378 yDiff *= 1.5;
1379 int shanDis = xDiff * xDiff + yDiff * yDiff;
1380 if (shanDis >= kMinDistance) {
1381 while (1) {
1382 shanCoords -= 4;
1383 if (shanCoords == _mainHero->_currCoords) {
1384 break;
1385 }
1386 int x = READ_LE_UINT16(shanCoords);
1387 int y = READ_LE_UINT16(shanCoords + 2);
1388 int pointDiffX = x - shanX;
1389 if (pointDiffX < 0) {
1390 pointDiffX *= -1;
1391 }
1392 int pointDiffY = y - shanY;
1393 if (pointDiffY < 0) {
1394 pointDiffY *= -1;
1395 }
1396 pointDiffY *= 1.5;
1397 int distance = pointDiffX * pointDiffX + pointDiffY * pointDiffY;
1398 if (distance >= kMinDistance) {
1399 break;
1400 }
1401 }
1402 int pathSizeDiff = (shanCoords - _mainHero->_currCoords) / 4;
1403 int destDir = *(_mainHero->_currDirTab + pathSizeDiff);
1404 _secondHero->_destDirection = destDir;
1405 int destX = READ_LE_UINT16(shanCoords);
1406 int destY = READ_LE_UINT16(shanCoords + 2);
1407 _secondHero->_coords = makePath(kSecondHero, _secondHero->_middleX, _secondHero->_middleY, destX, destY);
1408 if (_secondHero->_coords != nullptr) {
1409 _secondHero->_currCoords = _secondHero->_coords;
1410 int delay = shanLen1 - _shanLen;
1411 if (delay < 6) {
1412 delay = 6;
1413 }
1414 _secondHero->_moveDelay = delay / 2;
1415 _secondHero->_state = Hero::kHeroStateDelayMove;
1416 _secondHero->_dirTab = _directionTable;
1417 _secondHero->_currDirTab = _directionTable;
1418 _directionTable = nullptr;
1419 }
1420 }
1421 }
1422 }
1423 }
1424
makePath(int heroId,int currX,int currY,int destX,int destY)1425 byte *PrinceEngine::makePath(int heroId, int currX, int currY, int destX, int destY) {
1426 int realDestX = destX;
1427 int realDestY = destY;
1428 _flags->setFlagValue(Flags::MOVEDESTX, destX);
1429 _flags->setFlagValue(Flags::MOVEDESTY, destY);
1430
1431 int x1 = currX / 2;
1432 int y1 = currY / 2;
1433 int x2 = destX / 2;
1434 int y2 = destY / 2;
1435
1436 if ((x1 != x2) || (y1 != y2)) {
1437 findPoint(x1, y1);
1438 if (!getPixelAddr(_roomPathBitmap, _fpX, _fpY)) {
1439 return nullptr;
1440 }
1441 if ((x1 != _fpX) || (y1 != _fpY)) {
1442 x1 = _fpX;
1443 y1 = _fpY;
1444 }
1445 findPoint(x2, y2);
1446 if (!getPixelAddr(_roomPathBitmap, _fpX, _fpY)) {
1447 return nullptr;
1448 }
1449 if ((x2 != _fpX) || (y2 != _fpY)) {
1450 x2 = _fpX;
1451 y2 = _fpY;
1452 if (!_flags->getFlagValue(Flags::EXACTMOVE)) {
1453 realDestX = x2 * 2;
1454 realDestY = y2 * 2;
1455 _flags->setFlagValue(Flags::MOVEDESTX, realDestX);
1456 _flags->setFlagValue(Flags::MOVEDESTY, realDestY);
1457 } else {
1458 return nullptr;
1459 }
1460 }
1461
1462 if ((x1 == x2) && (y1 == y2)) {
1463 if (!heroId) {
1464 _mainHero->freeOldMove();
1465 _mainHero->_state = Hero::kHeroStateTurn;
1466 } else if (heroId == 1) {
1467 _secondHero->freeOldMove();
1468 _secondHero->_state = Hero::kHeroStateTurn;
1469 }
1470 return nullptr;
1471 }
1472
1473 int pathLen1 = 0;
1474 int pathLen2 = 0;
1475 int stX = x1;
1476 int stY = y1;
1477 int sizeCoords2 = 0;
1478
1479 if (tracePath(x1, y1, x2, y2)) {
1480 allocCoords2();
1481 approxPath();
1482 sizeCoords2 = _coords2 - _coordsBuf2;
1483 for (int i = 0; i < sizeCoords2; i++) {
1484 _coordsBuf[i] = _coordsBuf2[i];
1485 }
1486 _coords = _coordsBuf + sizeCoords2;
1487 approxPath();
1488 _coordsBuf3 = _coordsBuf2;
1489 _coordsBuf2 = nullptr;
1490 _coords3 = _coords2;
1491 _coords2 = nullptr;
1492 pathLen1 = _coords3 - _coordsBuf3;
1493 }
1494 if (tracePath(x2, y2, x1, y1)) {
1495 allocCoords2();
1496 approxPath();
1497 sizeCoords2 = _coords2 - _coordsBuf2;
1498 for (int i = 0; i < sizeCoords2; i++) {
1499 _coordsBuf[i] = _coordsBuf2[i];
1500 }
1501 _coords = _coordsBuf + sizeCoords2;
1502 approxPath();
1503 pathLen2 = _coords2 - _coordsBuf2;
1504 }
1505
1506 byte *chosenCoordsBuf = _coordsBuf2;
1507 byte *choosenCoords = _coords2;
1508 int choosenLength = pathLen1;
1509 if (pathLen1 < pathLen2) {
1510 chosenCoordsBuf = _coordsBuf3;
1511 choosenCoords = _coords3;
1512 choosenLength = pathLen2;
1513 }
1514
1515 if (choosenLength) {
1516 if (chosenCoordsBuf != nullptr) {
1517 int tempXBegin = READ_LE_UINT16(chosenCoordsBuf);
1518 int tempYBegin = READ_LE_UINT16(chosenCoordsBuf + 2);
1519 if (stX != tempXBegin || stY != tempYBegin) {
1520 SWAP(chosenCoordsBuf, choosenCoords);
1521 chosenCoordsBuf -= 4;
1522 byte *tempCoordsBuf = _coordsBuf;
1523 while (1) {
1524 int cord = READ_LE_UINT32(chosenCoordsBuf);
1525 WRITE_LE_UINT32(tempCoordsBuf, cord);
1526 tempCoordsBuf += 4;
1527 if (chosenCoordsBuf == choosenCoords) {
1528 break;
1529 }
1530 chosenCoordsBuf -= 4;
1531 }
1532 _coords = tempCoordsBuf;
1533 } else {
1534 int sizeChoosen = choosenCoords - chosenCoordsBuf;
1535 for (int i = 0; i < sizeChoosen; i++) {
1536 _coordsBuf[i] = chosenCoordsBuf[i];
1537 }
1538 _coords = _coordsBuf + sizeChoosen;
1539 }
1540 WRITE_LE_UINT32(_coords, 0xFFFFFFFF);
1541 freeCoords2();
1542 freeCoords3();
1543 scanDirections();
1544
1545 byte *tempCoordsBuf = _coordsBuf;
1546 byte *tempCoords = _coords;
1547 byte *newCoords;
1548 if (tempCoordsBuf != tempCoords) {
1549 int normCoordsSize = _coords - _coordsBuf + 4;
1550 newCoords = (byte *)malloc(normCoordsSize);
1551 byte *newCoordsBegin = newCoords;
1552 while (tempCoordsBuf != tempCoords) {
1553 int newValueX = READ_LE_UINT16(tempCoordsBuf);
1554 WRITE_LE_UINT16(newCoords, newValueX * 2);
1555 newCoords += 2;
1556 int newValueY = READ_LE_UINT16(tempCoordsBuf + 2);
1557 WRITE_LE_UINT16(newCoords, newValueY * 2);
1558 newCoords += 2;
1559 tempCoordsBuf += 4;
1560 }
1561 WRITE_LE_UINT16(newCoords - 4, realDestX);
1562 WRITE_LE_UINT16(newCoords - 2, realDestY);
1563 WRITE_LE_UINT32(newCoords, 0xFFFFFFFF);
1564 newCoords += 4;
1565 _shanLen = (newCoords - newCoordsBegin);
1566 _shanLen /= 4;
1567 return newCoordsBegin;
1568 }
1569 }
1570 }
1571 _coords = _coordsBuf;
1572 freeCoords2();
1573 freeCoords3();
1574 return nullptr;
1575 } else {
1576 if (!heroId) {
1577 _mainHero->freeOldMove();
1578 _mainHero->_state = Hero::kHeroStateTurn;
1579 } else if (heroId == 1) {
1580 _secondHero->freeOldMove();
1581 _secondHero->_state = Hero::kHeroStateTurn;
1582 }
1583 return nullptr;
1584 }
1585 }
1586
allocCoords2()1587 void PrinceEngine::allocCoords2() {
1588 if (_coordsBuf2 == nullptr) {
1589 _coordsBuf2 = (byte *)malloc(kTracePts * 4);
1590 _coords2 = _coordsBuf2;
1591 }
1592 }
1593
freeCoords2()1594 void PrinceEngine::freeCoords2() {
1595 if (_coordsBuf2 != nullptr) {
1596 free(_coordsBuf2);
1597 _coordsBuf2 = nullptr;
1598 _coords2 = nullptr;
1599 }
1600 }
1601
freeCoords3()1602 void PrinceEngine::freeCoords3() {
1603 if (_coordsBuf3 != nullptr) {
1604 free(_coordsBuf3);
1605 _coordsBuf3 = nullptr;
1606 _coords3 = nullptr;
1607 }
1608 }
1609
1610 } // End of namespace Prince
1611