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/endian.h"
24 #include "common/stream.h"
25
26 #include "gob/gob.h"
27 #include "gob/scenery.h"
28 #include "gob/global.h"
29 #include "gob/draw.h"
30 #include "gob/game.h"
31 #include "gob/script.h"
32 #include "gob/resources.h"
33 #include "gob/inter.h"
34 #include "gob/map.h"
35 #include "gob/videoplayer.h"
36
37 namespace Gob {
38
Scenery(GobEngine * vm)39 Scenery::Scenery(GobEngine *vm) : _vm(vm) {
40 for (int i = 0; i < 20; i++) {
41 _spriteRefs[i] = 0;
42 _spriteResId[i] = 0;
43 }
44
45 for (int i = 0; i < 10; i++) {
46 _staticPictCount[i] = 0;
47 _staticResId[i] = 0;
48 _animPictCount[i] = 0;
49 _animResId[i] = 0;
50 }
51
52 _curStatic = 0;
53 _curStaticLayer = 0;
54
55 _toRedrawLeft = 0;
56 _toRedrawRight = 0;
57 _toRedrawTop = 0;
58 _toRedrawBottom = 0;
59
60 _animTop = 0;
61 _animLeft = 0;
62
63 _pCaptureCounter = 0;
64
65 for (int i = 0; i < 70; i++) {
66 _staticPictToSprite[i] = 0;
67 _animPictToSprite[i] = 0;
68 }
69 }
70
~Scenery()71 Scenery::~Scenery() {
72 for (int i = 0; i < 10; i++) {
73 freeStatic(i);
74 freeAnim(i);
75 }
76 }
77
init()78 void Scenery::init() {
79 for (int i = 0; i < 10; i++) {
80 if (_vm->getGameType() == kGameTypeFascination) {
81 freeAnim(i);
82 freeStatic(i);
83 }
84 _animPictCount[i] = 0;
85 _staticPictCount[i] = -1;
86 }
87
88 for (int i = 0; i < 20; i++) {
89 _spriteRefs[i] = 0;
90 _spriteResId[i] = -1;
91 }
92
93 _curStaticLayer = -1;
94 _curStatic = -1;
95 }
96
loadStatic(char search)97 int16 Scenery::loadStatic(char search) {
98 int16 size;
99 byte *backsPtr;
100 int16 picsCount;
101 int16 resId;
102 int16 sceneryIndex;
103 Static *ptr;
104 int16 width;
105 int16 height;
106 int16 sprResId;
107 int16 sprIndex;
108
109 _vm->_game->_script->evalExpr(&sceneryIndex);
110
111 size = _vm->_game->_script->readInt16();
112 backsPtr = _vm->_game->_script->getData() + _vm->_game->_script->pos();
113 _vm->_game->_script->skip(size * 2);
114 picsCount = _vm->_game->_script->readInt16();
115 resId = _vm->_game->_script->readInt16();
116
117 if (search) {
118 int i;
119
120 for (i = 0; i < 10; i++) {
121 if ((_staticPictCount[i] != -1) && (_staticResId[i] == resId)) {
122 _vm->_game->_script->skip(8 * _staticPictCount[i]);
123 return i;
124 }
125
126 if (_staticPictCount[i] == -1 && i < sceneryIndex)
127 sceneryIndex = i;
128 }
129 }
130
131 _staticPictCount[sceneryIndex] = picsCount;
132 _staticResId[sceneryIndex] = resId;
133
134 Resource *resource = _vm->_game->_resources->getResource((uint16) resId);
135 if (!resource)
136 return 0;
137
138 ptr = &_statics[sceneryIndex];
139
140 ptr->layersCount = resource->stream()->readSint16LE();
141
142 ptr->layers = new StaticLayer[ptr->layersCount];
143
144 for (int i = 0; i < ptr->layersCount; i++) {
145 Common::SeekableReadStream &layerData = *resource->stream();
146
147 layerData.seek(2 + i * 2);
148 layerData.seek(layerData.readUint16LE());
149
150 ptr->layers[i].backResId = layerData.readSint16LE();
151 ptr->layers[i].planeCount = layerData.readSint16LE();
152 if (ptr->layers[i].planeCount > 0) {
153 ptr->layers[i].planes = new StaticPlane[ptr->layers[i].planeCount];
154 for (int j = 0; j < ptr->layers[i].planeCount; j++) {
155 ptr->layers[i].planes[j].pictIndex = layerData.readByte();
156 ptr->layers[i].planes[j].pieceIndex = layerData.readByte();
157 ptr->layers[i].planes[j].drawOrder = layerData.readByte();
158 ptr->layers[i].planes[j].destX = layerData.readSint16LE();
159 ptr->layers[i].planes[j].destY = layerData.readSint16LE();
160 ptr->layers[i].planes[j].transp = layerData.readSByte();
161 }
162 } else
163 ptr->layers[i].planes = 0;
164
165 ptr->layers[i].backResId = (int16) READ_LE_UINT16(backsPtr);
166 backsPtr += 2;
167 }
168
169 ptr->pieces = new PieceDesc*[picsCount];
170 ptr->piecesCount = new uint32[picsCount];
171
172 for (int i = 0; i < picsCount; i++) {
173 int16 pictDescId = _vm->_game->_script->readInt16();
174
175 loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]);
176
177 width = _vm->_game->_script->readInt16();
178 height = _vm->_game->_script->readInt16();
179 sprResId = _vm->_game->_script->readInt16();
180 for (sprIndex = 0; sprIndex < 20; sprIndex++) {
181 if (_spriteResId[sprIndex] == sprResId)
182 break;
183 }
184
185 if (sprIndex < 20) {
186 _staticPictToSprite[7 * sceneryIndex + i] = sprIndex;
187 _spriteRefs[sprIndex]++;
188 } else {
189 for (sprIndex = 19; _vm->_draw->_spritesArray[sprIndex] != 0; sprIndex--) { }
190
191 _staticPictToSprite[7 * sceneryIndex + i] = sprIndex;
192 _spriteRefs[sprIndex] = 1;
193 _spriteResId[sprIndex] = sprResId;
194 _vm->_draw->initSpriteSurf(sprIndex, width, height, 2);
195
196 _vm->_draw->_spritesArray[sprIndex]->clear();
197 _vm->_draw->_destSurface = sprIndex;
198 _vm->_draw->_spriteLeft = sprResId;
199 _vm->_draw->_transparency = 0;
200 _vm->_draw->_destSpriteX = 0;
201 _vm->_draw->_destSpriteY = 0;
202 _vm->_draw->spriteOperation(DRAW_LOADSPRITE);
203 }
204 }
205
206 delete resource;
207 return sceneryIndex + 100;
208 }
209
freeStatic(int16 index)210 void Scenery::freeStatic(int16 index) {
211 int16 spr;
212
213 if (index == -1)
214 _vm->_game->_script->evalExpr(&index);
215
216 if (_staticPictCount[index] == -1)
217 return;
218
219 for (int i = 0; i < _staticPictCount[index]; i++) {
220 delete[] _statics[index].pieces[i];
221
222 spr = _staticPictToSprite[index * 7 + i];
223 _spriteRefs[spr]--;
224 if (_spriteRefs[spr] == 0) {
225 _vm->_draw->freeSprite(spr);
226 _spriteResId[spr] = -1;
227 }
228 }
229
230 for (int i = 0; i < _statics[index].layersCount; i++)
231 delete[] _statics[index].layers[i].planes;
232
233 delete[] _statics[index].layers;
234 delete[] _statics[index].pieces;
235 delete[] _statics[index].piecesCount;
236
237 _statics[index].layersCount = 0;
238 _staticPictCount[index] = -1;
239 }
240
renderStatic(int16 scenery,int16 layer)241 void Scenery::renderStatic(int16 scenery, int16 layer) {
242 Static *ptr;
243 StaticLayer *layerPtr;
244 StaticPlane *planePtr;
245 int16 planeCount;
246 int16 order;
247 int16 plane;
248
249 uint16 pieceIndex;
250 uint16 pictIndex;
251
252 int16 left;
253 int16 right;
254 int16 top;
255 int16 bottom;
256
257 ptr = &_statics[scenery];
258 if (layer >= ptr->layersCount)
259 return;
260
261 layerPtr = &ptr->layers[layer];
262
263 _vm->_draw->_spriteLeft = layerPtr->backResId;
264 if (_vm->_draw->_spriteLeft != -1) {
265 _vm->_draw->_destSpriteX = 0;
266 _vm->_draw->_destSpriteY = 0;
267 _vm->_draw->_destSurface = Draw::kBackSurface;
268 _vm->_draw->_transparency = 0;
269 _vm->_draw->spriteOperation(DRAW_LOADSPRITE);
270 }
271
272 planeCount = layerPtr->planeCount;
273 for (order = 0; order < 100; order++) {
274 for (plane = 0, planePtr = layerPtr->planes; plane < planeCount; plane++, planePtr++) {
275 if (planePtr->drawOrder != order)
276 continue;
277
278 pieceIndex = planePtr->pieceIndex;
279 pictIndex = planePtr->pictIndex - 1;
280
281 if (pictIndex >= _staticPictCount[scenery])
282 continue;
283
284 if (!ptr->pieces || !ptr->pieces[pictIndex])
285 continue;
286
287 if (pieceIndex >= ptr->piecesCount[pictIndex])
288 continue;
289
290 _vm->_draw->_destSpriteX = planePtr->destX;
291 _vm->_draw->_destSpriteY = planePtr->destY;
292 left = ptr->pieces[pictIndex][pieceIndex].left;
293 right = ptr->pieces[pictIndex][pieceIndex].right;
294 top = ptr->pieces[pictIndex][pieceIndex].top;
295 bottom = ptr->pieces[pictIndex][pieceIndex].bottom;
296
297 _vm->_draw->_sourceSurface =
298 _staticPictToSprite[scenery * 7 + pictIndex];
299 _vm->_draw->_destSurface = Draw::kBackSurface;
300 _vm->_draw->_spriteLeft = left;
301 _vm->_draw->_spriteTop = top;
302 _vm->_draw->_spriteRight = right - left + 1;
303 _vm->_draw->_spriteBottom = bottom - top + 1;
304 _vm->_draw->_transparency = planePtr->transp ? 3 : 0;
305 _vm->_draw->spriteOperation(DRAW_BLITSURF);
306 }
307 }
308 }
309
updateStatic(int16 orderFrom,byte index,byte layer)310 void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
311 StaticLayer *layerPtr;
312 PieceDesc **pictPtr;
313 StaticPlane *planePtr;
314 int16 planeCount;
315 int16 order;
316 int16 plane;
317 uint16 pieceIndex;
318 uint16 pictIndex;
319
320 int16 left;
321 int16 right;
322 int16 top;
323 int16 bottom;
324
325 if ((index >= 10) || layer >= _statics[index].layersCount)
326 return;
327
328 layerPtr = &_statics[index].layers[layer];
329 pictPtr = _statics[index].pieces;
330
331 planeCount = layerPtr->planeCount;
332
333 for (order = orderFrom; order < 100; order++) {
334 for (planePtr = layerPtr->planes, plane = 0;
335 plane < planeCount; plane++, planePtr++) {
336 if (planePtr->drawOrder != order)
337 continue;
338
339 pieceIndex = planePtr->pieceIndex;
340 pictIndex = planePtr->pictIndex - 1;
341
342 if (pictIndex >= _staticPictCount[index])
343 continue;
344
345 if (!pictPtr || !pictPtr[pictIndex])
346 continue;
347
348 if (pieceIndex >= _statics[index].piecesCount[pictIndex])
349 continue;
350
351 _vm->_draw->_destSpriteX = planePtr->destX;
352 _vm->_draw->_destSpriteY = planePtr->destY;
353
354 left = pictPtr[pictIndex][pieceIndex].left;
355 right = pictPtr[pictIndex][pieceIndex].right;
356 top = pictPtr[pictIndex][pieceIndex].top;
357 bottom = pictPtr[pictIndex][pieceIndex].bottom;
358
359 if (_vm->_draw->_destSpriteX > _toRedrawRight)
360 continue;
361
362 if (_vm->_draw->_destSpriteY > _toRedrawBottom)
363 continue;
364
365 if (_vm->_draw->_destSpriteX < _toRedrawLeft) {
366 left += _toRedrawLeft - _vm->_draw->_destSpriteX;
367 _vm->_draw->_destSpriteX = _toRedrawLeft;
368 }
369
370 if (_vm->_draw->_destSpriteY < _toRedrawTop) {
371 top += _toRedrawTop - _vm->_draw->_destSpriteY;
372 _vm->_draw->_destSpriteY = _toRedrawTop;
373 }
374
375 _vm->_draw->_spriteLeft = left;
376 _vm->_draw->_spriteTop = top;
377 _vm->_draw->_spriteRight = right - left + 1;
378 _vm->_draw->_spriteBottom = bottom - top + 1;
379
380 if ((_vm->_draw->_spriteRight <= 0) ||
381 (_vm->_draw->_spriteBottom <= 0))
382 continue;
383
384 if ((_vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1) >
385 _toRedrawRight)
386 _vm->_draw->_spriteRight =
387 _toRedrawRight - _vm->_draw->_destSpriteX + 1;
388
389 if ((_vm->_draw->_destSpriteY + _vm->_draw->_spriteBottom - 1) >
390 _toRedrawBottom)
391 _vm->_draw->_spriteBottom =
392 _toRedrawBottom - _vm->_draw->_destSpriteY + 1;
393
394 _vm->_draw->_sourceSurface =
395 _staticPictToSprite[index * 7 + pictIndex];
396 _vm->_draw->_destSurface = Draw::kBackSurface;
397 _vm->_draw->_transparency = planePtr->transp ? 3 : 0;
398 _vm->_draw->spriteOperation(DRAW_BLITSURF);
399 }
400 }
401 }
402
updateStatic(int16 orderFrom)403 void Scenery::updateStatic(int16 orderFrom) {
404 if (_curStatic == -1)
405 return;
406
407 if (_curStatic < 10000) {
408 updateStatic(orderFrom, _curStatic & 0xFF, _curStaticLayer & 0xFF);
409
410 if (_curStatic & 0xFF00)
411 updateStatic(orderFrom, ((_curStatic >> 8) & 0xFF) - 1,
412 (_curStaticLayer >> 8) & 0xFF);
413 } else
414 for (int i = 0; i < (_curStatic - 10000); i++)
415 updateStatic(orderFrom, i, 0);
416 }
417
loadAnim(char search)418 int16 Scenery::loadAnim(char search) {
419 int16 picsCount;
420 int16 resId;
421 int16 i;
422 int16 j;
423 int16 sceneryIndex;
424 int16 framesCount;
425 Animation *ptr;
426 int16 width;
427 int16 height;
428 int16 sprResId;
429 int16 sprIndex;
430 uint32 layerPos;
431
432 _vm->_game->_script->evalExpr(&sceneryIndex);
433 picsCount = _vm->_game->_script->readInt16();
434 resId = _vm->_game->_script->readInt16();
435
436 if (search) {
437 for (i = 0; i < 10; i++) {
438 if ((_animPictCount[i] != 0) && (_animResId[i] == resId)) {
439 _vm->_game->_script->skip(8 * _animPictCount[i]);
440 return i;
441 }
442
443 if ((_animPictCount[i] == 0) && (i < sceneryIndex))
444 sceneryIndex = i;
445 }
446 }
447
448 _animPictCount[sceneryIndex] = picsCount;
449 _animResId[sceneryIndex] = resId;
450
451 Resource *resource = _vm->_game->_resources->getResource((uint16) resId);
452 if (!resource)
453 return 0;
454
455 ptr = &_animations[sceneryIndex];
456
457 ptr->layersCount = resource->stream()->readSint16LE();
458
459 ptr->layers = new AnimLayer[ptr->layersCount];
460
461 for (i = 0; i < ptr->layersCount; i++) {
462 Common::SeekableReadStream &layerData = *resource->stream();
463
464 layerData.seek(2 + i * 2);
465 layerData.seek(layerData.readUint16LE());
466
467 ptr->layers[i].unknown0 = layerData.readSint16LE();
468 ptr->layers[i].posX = layerData.readSint16LE();
469 ptr->layers[i].posY = layerData.readSint16LE();
470 ptr->layers[i].animDeltaX = layerData.readSint16LE();
471 ptr->layers[i].animDeltaY = layerData.readSint16LE();
472 ptr->layers[i].transp = layerData.readSByte();
473 ptr->layers[i].framesCount = layerData.readSint16LE();
474
475 // Going through the AnimFramePiece, finding the end for each
476 layerPos = layerData.pos();
477 framesCount = 0;
478 for (j = 0; j < ptr->layers[i].framesCount; j++) {
479 layerData.skip(4); // pictIndex, pieceIndex, destX, destY
480 while (layerData.readByte() == 1) {
481 framesCount++;
482 layerData.skip(4); // pictIndex, pieceIndex, destX, destY
483 }
484 framesCount++;
485 }
486 layerData.seek(layerPos);
487
488 ptr->layers[i].frames = new AnimFramePiece[framesCount];
489 for (j = 0; j < framesCount; j++) {
490 ptr->layers[i].frames[j].pictIndex = layerData.readByte();
491 ptr->layers[i].frames[j].pieceIndex = layerData.readByte();
492 ptr->layers[i].frames[j].destX = layerData.readSByte();
493 ptr->layers[i].frames[j].destY = layerData.readSByte();
494 ptr->layers[i].frames[j].notFinal = layerData.readSByte();
495 }
496 }
497
498 ptr->pieces = new PieceDesc*[picsCount];
499 ptr->piecesCount = new uint32[picsCount];
500
501 for (i = 0; i < picsCount; i++) {
502 int16 pictDescId = _vm->_game->_script->readInt16();
503
504 loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]);
505
506 width = _vm->_game->_script->readInt16();
507 height = _vm->_game->_script->readInt16();
508 sprResId = _vm->_game->_script->readInt16();
509 for (sprIndex = 0; sprIndex < 20; sprIndex++)
510 if (_spriteResId[sprIndex] == sprResId)
511 break;
512
513 if (sprIndex < 20) {
514 _animPictToSprite[7 * sceneryIndex + i] = sprIndex;
515 _spriteRefs[sprIndex]++;
516 } else {
517 for (sprIndex = 19; _vm->_draw->_spritesArray[sprIndex];
518 sprIndex--)
519 ;
520
521 _animPictToSprite[7 * sceneryIndex + i] = sprIndex;
522 _spriteRefs[sprIndex] = 1;
523 _spriteResId[sprIndex] = sprResId;
524 _vm->_draw->initSpriteSurf(sprIndex, width, height, 2);
525
526 _vm->_draw->_spritesArray[sprIndex]->clear();
527 _vm->_draw->_destSurface = sprIndex;
528 _vm->_draw->_spriteLeft = sprResId;
529 _vm->_draw->_transparency = 0;
530 _vm->_draw->_destSpriteX = 0;
531 _vm->_draw->_destSpriteY = 0;
532 _vm->_draw->spriteOperation(DRAW_LOADSPRITE);
533 }
534 }
535
536 delete resource;
537 return sceneryIndex + 100;
538 }
539
freeAnim(int16 index)540 void Scenery::freeAnim(int16 index) {
541 int16 spr;
542
543 if (index == -1)
544 _vm->_game->_script->evalExpr(&index);
545
546 if (_animPictCount[index] == 0)
547 return;
548
549 for (int i = 0; i < _animPictCount[index]; i++) {
550 delete[] _animations[index].pieces[i];
551
552 spr = _animPictToSprite[index * 7 + i];
553 _spriteRefs[spr]--;
554 if (_spriteRefs[spr] == 0) {
555 _vm->_draw->freeSprite(spr);
556 _spriteResId[spr] = -1;
557 }
558 }
559
560 for (int i = 0; i < _animations[index].layersCount; i++)
561 delete[] _animations[index].layers[i].frames;
562
563 delete[] _animations[index].layers;
564 delete[] _animations[index].pieces;
565 delete[] _animations[index].piecesCount;
566
567 _animPictCount[index] = 0;
568 }
569
570 // flags & 1 - do capture all area animation is occupying
571 // flags & 4 == 0 - calculate animation final size
572 // flags & 2 != 0 - don't check with "toRedraw"'s
573 // flags & 4 != 0 - checkk view toRedraw
updateAnim(int16 layer,int16 frame,int16 animation,int16 flags,int16 drawDeltaX,int16 drawDeltaY,char doDraw)574 void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
575 int16 drawDeltaX, int16 drawDeltaY, char doDraw) {
576 AnimLayer *layerPtr;
577 PieceDesc **pictPtr;
578 AnimFramePiece *framePtr;
579
580 uint16 pieceIndex;
581 uint16 pictIndex;
582
583 int16 left;
584 int16 right;
585 int16 top;
586 int16 bottom;
587
588 byte highX;
589 byte highY;
590
591 int16 i;
592 int16 transp;
593
594 int16 destX;
595 int16 destY;
596
597 if ((animation < 0) &&
598 ((_vm->getGameType() == kGameTypeWoodruff) ||
599 (_vm->getGameType() == kGameTypeAdibou2))) {
600 // Object video
601
602 if (flags & 1) { // Do capture
603 updateAnim(layer, frame, animation, 0, drawDeltaX, drawDeltaY, 0);
604
605 if (_toRedrawLeft == -12345)
606 return;
607
608 _vm->_game->capturePush(_toRedrawLeft, _toRedrawTop,
609 _toRedrawRight - _toRedrawLeft + 1,
610 _toRedrawBottom - _toRedrawTop + 1);
611
612 *_pCaptureCounter = *_pCaptureCounter + 1;
613 }
614
615 Mult::Mult_Object &obj = _vm->_mult->_objects[-animation - 1];
616
617 if ((obj.videoSlot == 0) || !_vm->_vidPlayer->slotIsOpen(obj.videoSlot - 1)) {
618 _toRedrawLeft = -12345;
619 return;
620 }
621
622 if (frame >= (int32)_vm->_vidPlayer->getFrameCount(obj.videoSlot - 1))
623 frame = _vm->_vidPlayer->getFrameCount(obj.videoSlot - 1) - 1;
624
625 if ((int32)_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) >= 255) {
626 // Allow for object videos with more than 255 frames, although the
627 // object frame counter is just a byte.
628
629 uint32 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) + 1;
630 uint16 frameWrap = curFrame / 256;
631
632 frame = ((frame + 1) % 256) + frameWrap * 256;
633 }
634
635 if (frame != (int32)_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1)) {
636 // Seek to frame
637
638 VideoPlayer::Properties props;
639
640 props.forceSeek = true;
641 props.waitEndFrame = false;
642 props.lastFrame = frame;
643
644 if ((int32)_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) < frame)
645 props.startFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) + 1;
646 else
647 props.startFrame = frame;
648
649 _vm->_vidPlayer->play(obj.videoSlot - 1, props);
650 }
651
652 int32 subtitle = _vm->_vidPlayer->getSubtitleIndex(obj.videoSlot - 1);
653 if (subtitle != -1)
654 _vm->_draw->printTotText(subtitle);
655
656 destX = 0;
657 destY = 0;
658 left = *(obj.pPosX);
659 top = *(obj.pPosY);
660 right = left + _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - 1;
661 bottom = top + _vm->_vidPlayer->getHeight(obj.videoSlot - 1) - 1;
662
663 if (flags & 2) {
664 if (left < _vm->_mult->_animLeft) {
665 destX += _vm->_mult->_animLeft - left;
666 left = _vm->_mult->_animLeft;
667 }
668
669 if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right)
670 right = _vm->_mult->_animLeft + _vm->_mult->_animWidth - 1;
671
672 if (top < _vm->_mult->_animTop) {
673 destY += _vm->_mult->_animTop - top;
674 top = _vm->_mult->_animTop;
675 }
676
677 if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom)
678 bottom = _vm->_mult->_animTop + _vm->_mult->_animHeight - 1;
679
680 } else if (flags & 4) {
681 if (left < _toRedrawLeft) {
682 destX += _toRedrawLeft - left;
683 left = _toRedrawLeft;
684 }
685
686 if (right > _toRedrawRight)
687 right = _toRedrawRight;
688
689 if (top < _toRedrawTop) {
690 destY += _toRedrawTop - top;
691 top = _toRedrawTop;
692 }
693
694 if (bottom > _toRedrawBottom)
695 bottom = _toRedrawBottom;
696
697 } else {
698 _toRedrawTop = top;
699 _toRedrawLeft = left;
700 _toRedrawRight = right;
701 _toRedrawBottom = bottom;
702 }
703
704 if (doDraw) {
705 if ((left > right) || (top > bottom))
706 return;
707
708 if (left < _vm->_mult->_animLeft) {
709 destX += _vm->_mult->_animLeft - left;
710 left = _vm->_mult->_animLeft;
711 }
712
713 if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right)
714 right = _vm->_mult->_animLeft + _vm->_mult->_animWidth - 1;
715
716 if (top < _vm->_mult->_animTop) {
717 destY += _vm->_mult->_animTop - top;
718 top = _vm->_mult->_animTop;
719 }
720
721 if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom)
722 bottom = _vm->_mult->_animTop + _vm->_mult->_animHeight - 1;
723
724 _vm->_draw->_spriteLeft = destX;
725 _vm->_draw->_spriteTop = destY;
726 _vm->_draw->_spriteRight = right - left + 1;
727 _vm->_draw->_spriteBottom = bottom - top + 1;
728 _vm->_draw->_destSpriteX = left;
729 _vm->_draw->_destSpriteY = top;
730 _vm->_draw->_transparency = layer;
731 if (layer & 0x80)
732 _vm->_draw->_spriteLeft = _vm->_vidPlayer->getWidth(obj.videoSlot - 1) -
733 (destX + _vm->_draw->_spriteRight);
734
735 _vm->_vidPlayer->copyFrame(obj.videoSlot - 1, *_vm->_draw->_backSurface,
736 _vm->_draw->_spriteLeft, _vm->_draw->_spriteTop,
737 _vm->_draw->_spriteRight, _vm->_draw->_spriteBottom,
738 _vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY,
739 (_vm->_draw->_transparency != 0) ? 0 : -1);
740
741 _vm->_draw->invalidateRect(_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY,
742 _vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1,
743 _vm->_draw->_destSpriteY + _vm->_draw->_spriteBottom - 1);
744 }
745
746 if (!(flags & 4)) {
747 _animLeft = _toRedrawLeft = left;
748 _animTop = _toRedrawTop = top;
749 _animRight = _toRedrawRight = right;
750 _animBottom = _toRedrawBottom = bottom;
751 }
752
753 return;
754 }
755
756 if ((animation < 0) || (animation >= 10))
757 return;
758 if ((_animPictCount[animation] == 0) || (layer < 0))
759 return;
760 if (layer >= _animations[animation].layersCount)
761 return;
762
763 layerPtr = &_animations[animation].layers[layer];
764
765 if (frame >= layerPtr->framesCount)
766 return;
767
768 if (flags & 1) { // Do capture
769 updateAnim(layer, frame, animation, 0, drawDeltaX, drawDeltaY, 0);
770
771 if (_toRedrawLeft == -12345)
772 return;
773
774 _vm->_game->capturePush(_toRedrawLeft, _toRedrawTop,
775 _toRedrawRight - _toRedrawLeft + 1,
776 _toRedrawBottom - _toRedrawTop + 1);
777
778 *_pCaptureCounter = *_pCaptureCounter + 1;
779 }
780
781 pictPtr = _animations[animation].pieces;
782 framePtr = layerPtr->frames;
783
784 for (i = 0; i < frame; i++, framePtr++)
785 while (framePtr->notFinal == 1)
786 framePtr++;
787
788 if (flags & 4) {
789 _toRedrawLeft = MAX(_toRedrawLeft, _vm->_mult->_animLeft);
790 _toRedrawTop = MAX(_toRedrawTop, _vm->_mult->_animTop);
791 _toRedrawRight = MIN(_toRedrawRight,
792 (int16)(_vm->_mult->_animLeft + _vm->_mult->_animWidth - 1));
793 _toRedrawBottom = MIN(_toRedrawBottom,
794 (int16)(_vm->_mult->_animTop + _vm->_mult->_animHeight - 1));
795 } else
796 _toRedrawLeft = -12345;
797
798 transp = layerPtr->transp ? 3 : 0;
799
800 framePtr--;
801 do {
802 framePtr++;
803
804 pieceIndex = framePtr->pieceIndex;
805 pictIndex = framePtr->pictIndex;
806
807 destX = framePtr->destX;
808 destY = framePtr->destY;
809
810 highX = pictIndex & 0xC0;
811 highY = pictIndex & 0x30;
812 highX >>= 6;
813 highY >>= 4;
814 if (destX >= 0)
815 destX += ((uint16)highX) << 7;
816 else
817 destX -= ((uint16)highX) << 7;
818
819 if (destY >= 0)
820 destY += ((uint16)highY) << 7;
821 else
822 destY -= ((uint16)highY) << 7;
823
824 if (drawDeltaX == 1000)
825 destX += layerPtr->posX;
826 else
827 destX += drawDeltaX;
828
829 if (drawDeltaY == 1000)
830 destY += layerPtr->posY;
831 else
832 destY += drawDeltaY;
833
834 pictIndex = (pictIndex & 15) - 1;
835
836 if (pictIndex >= _animPictCount[animation])
837 continue;
838
839 if (!pictPtr[pictIndex])
840 continue;
841
842 if (pieceIndex >= _animations[animation].piecesCount[pictIndex])
843 continue;
844
845 left = pictPtr[pictIndex][pieceIndex].left;
846 right = pictPtr[pictIndex][pieceIndex].right;
847 top = pictPtr[pictIndex][pieceIndex].top;
848 bottom = pictPtr[pictIndex][pieceIndex].bottom;
849
850 if (flags & 2) {
851 if (destX < _vm->_mult->_animLeft) {
852 left += _vm->_mult->_animLeft - destX;
853 destX = _vm->_mult->_animLeft;
854 }
855
856 if ((left <= right) && ((destX + right - left) >=
857 (_vm->_mult->_animLeft + _vm->_mult->_animWidth)))
858 right -= (destX + right - left) -
859 (_vm->_mult->_animLeft + _vm->_mult->_animWidth) + 1;
860
861 if (destY < _vm->_mult->_animTop) {
862 top += _vm->_mult->_animTop - destY;
863 destY = _vm->_mult->_animTop;
864 }
865
866 if ((top <= bottom) && ((destY + bottom - top) >=
867 (_vm->_mult->_animTop + _vm->_mult->_animHeight)))
868 bottom -= (destY + bottom - top) -
869 (_vm->_mult->_animTop + _vm->_mult->_animHeight) + 1;
870
871 } else if (flags & 4) {
872 if (destX < _toRedrawLeft) {
873 left += _toRedrawLeft - destX;
874 destX = _toRedrawLeft;
875 }
876
877 if ((left <= right) && ((destX + right - left) > _toRedrawRight))
878 right -= destX + right - left - _toRedrawRight;
879
880 if (destY < _toRedrawTop) {
881 top += _toRedrawTop - destY;
882 destY = _toRedrawTop;
883 }
884
885 if ((top <= bottom) && ((destY + bottom - top) > _toRedrawBottom))
886 bottom -= destY + bottom - top - _toRedrawBottom;
887 }
888
889 if ((left > right) || (top > bottom))
890 continue;
891
892 if (doDraw) {
893 _vm->_draw->_sourceSurface =
894 _animPictToSprite[animation * 7 + pictIndex];
895 _vm->_draw->_destSurface = Draw::kBackSurface;
896
897 _vm->_draw->_spriteLeft = left;
898 _vm->_draw->_spriteTop = top;
899 _vm->_draw->_spriteRight = right - left + 1;
900 _vm->_draw->_spriteBottom = bottom - top + 1;
901 _vm->_draw->_destSpriteX = destX;
902 _vm->_draw->_destSpriteY = destY;
903 _vm->_draw->_transparency = transp;
904 _vm->_draw->spriteOperation(DRAW_BLITSURF);
905 }
906
907 if (!(flags & 4)) {
908 if (_toRedrawLeft == -12345) {
909 _toRedrawLeft = destX;
910 _animLeft = destX;
911 _toRedrawTop = destY;
912 _animTop = destY;
913 _toRedrawRight = destX + right - left;
914 _animRight = destX + right - left;
915 _toRedrawBottom = destY + bottom - top;
916 _animBottom = destY + bottom - top;
917 } else {
918 _toRedrawLeft = MIN(_toRedrawLeft, destX);
919 _toRedrawTop = MIN(_toRedrawTop, destY);
920 _toRedrawRight =
921 MAX(_toRedrawRight, (int16)(destX + right - left));
922 _toRedrawBottom =
923 MAX(_toRedrawBottom, (int16)(destY + bottom - top));
924 }
925 }
926
927 } while (framePtr->notFinal == 1);
928 }
929
writeAnimLayerInfo(uint16 index,uint16 layer,int16 varDX,int16 varDY,int16 varUnk0,int16 varFrames)930 void Scenery::writeAnimLayerInfo(uint16 index, uint16 layer,
931 int16 varDX, int16 varDY, int16 varUnk0, int16 varFrames) {
932
933 assert(index < 10);
934
935 // WORKAROUND - Fascination Hebrew is using scripts from the CD versions, but of course
936 // no CD track, so the anim syncing failed, and the anims were suppressed. But they
937 // didn't updated the scripts. Skipping the wrong anims is a solution.
938 if ((_vm->getGameType() == kGameTypeFascination) && (layer >= _animations[index].layersCount)) {
939 WRITE_VAR_OFFSET(varDX, 0);
940 WRITE_VAR_OFFSET(varDY, 0);
941 WRITE_VAR_OFFSET(varUnk0, 0);
942 WRITE_VAR_OFFSET(varFrames, 0);
943 } else {
944 assert(layer < _animations[index].layersCount);
945
946 AnimLayer &animLayer = _animations[index].layers[layer];
947 WRITE_VAR_OFFSET(varDX, animLayer.animDeltaX);
948 WRITE_VAR_OFFSET(varDY, animLayer.animDeltaY);
949 WRITE_VAR_OFFSET(varUnk0, animLayer.unknown0);
950 WRITE_VAR_OFFSET(varFrames, animLayer.framesCount);
951 }
952 }
953
getStaticLayersCount(uint16 index)954 int16 Scenery::getStaticLayersCount(uint16 index) {
955 assert(index < 10);
956
957 return _statics[index].layersCount;
958 }
959
getAnimLayersCount(uint16 index)960 int16 Scenery::getAnimLayersCount(uint16 index) {
961 assert(index < 10);
962
963 return _animations[index].layersCount;
964 }
965
getStaticLayer(uint16 index,uint16 layer)966 Scenery::StaticLayer *Scenery::getStaticLayer(uint16 index, uint16 layer) {
967 assert(index < 10);
968 assert(layer < _statics[index].layersCount);
969
970 return &_statics[index].layers[layer];
971 }
972
getAnimLayer(uint16 index,uint16 layer)973 Scenery::AnimLayer *Scenery::getAnimLayer(uint16 index, uint16 layer) {
974 assert(index < 10);
975 assert(layer < _animations[index].layersCount);
976
977 return &_animations[index].layers[layer];
978 }
979
loadPieces(int16 pictDescId,PieceDesc * & pieceDesc,uint32 & piecesCount)980 void Scenery::loadPieces(int16 pictDescId, PieceDesc *&pieceDesc, uint32 &piecesCount) {
981 Resource *resource = _vm->_game->_resources->getResource(pictDescId);
982 if (!resource) {
983 warning("Scenery::loadPieces(): Can't load %d", pictDescId);
984 return;
985 }
986
987 piecesCount = resource->getSize() / 8;
988 pieceDesc = new PieceDesc[piecesCount];
989
990 for (uint32 i = 0; i < piecesCount; i++) {
991 pieceDesc[i].left = resource->stream()->readSint16LE();
992 pieceDesc[i].right = resource->stream()->readSint16LE();
993 pieceDesc[i].top = resource->stream()->readSint16LE();
994 pieceDesc[i].bottom = resource->stream()->readSint16LE();
995 }
996
997 delete resource;
998 }
999
1000 } // End of namespace Gob
1001