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 "illusions/illusions.h"
24 #include "illusions/resources/backgroundresource.h"
25 #include "illusions/actor.h"
26 #include "illusions/camera.h"
27 #include "illusions/dictionary.h"
28 #include "illusions/resources/actorresource.h"
29 #include "illusions/screen.h"
30 #include "illusions/sequenceopcodes.h"
31 #include "common/str.h"
32
33 namespace Illusions {
34
35 // BackgroundResourceLoader
36
load(Resource * resource)37 void BackgroundResourceLoader::load(Resource *resource) {
38 resource->_instance = _vm->_backgroundInstances->createBackgroundInstance(resource);
39 }
40
isFlag(int flag)41 bool BackgroundResourceLoader::isFlag(int flag) {
42 return
43 flag == kRlfLoadFile;
44 }
45
46 // TileMap
47
load(byte * dataStart,Common::SeekableReadStream & stream)48 void TileMap::load(byte *dataStart, Common::SeekableReadStream &stream) {
49 _width = stream.readSint16LE();
50 _height = stream.readSint16LE();
51 stream.skip(4); // Unknown
52 uint32 mapOffs = stream.pos();
53 _map = dataStart + mapOffs;
54 debug(0, "TileMap::load() _width: %d; _height: %d",
55 _width, _height);
56 }
57
58 // BgInfo
59
load(byte * dataStart,Common::SeekableReadStream & stream)60 void BgInfo::load(byte *dataStart, Common::SeekableReadStream &stream) {
61 _flags = stream.readUint32LE();
62 uint16 unknown = stream.readUint16LE(); // TODO Unknown
63 _priorityBase = stream.readSint16LE();
64 _surfInfo.load(stream);
65 loadPoint(stream, _panPoint);
66 uint32 tileMapOffs = stream.readUint32LE();
67 uint32 tilePixelsOffs = stream.readUint32LE();
68 stream.seek(tileMapOffs);
69 _tileMap.load(dataStart, stream);
70 _tilePixels = dataStart + tilePixelsOffs;
71 debug(0, "BgInfo::load() _flags: %08X; unknown: %04X; _priorityBase: %d; tileMapOffs: %08X; tilePixelsOffs: %08X",
72 _flags, unknown, _priorityBase, tileMapOffs, tilePixelsOffs);
73 }
74
75 // PriorityLayer
76
load(byte * dataStart,Common::SeekableReadStream & stream)77 void PriorityLayer::load(byte *dataStart, Common::SeekableReadStream &stream) {
78 _width = stream.readUint16LE();
79 _height = stream.readUint16LE();
80 uint32 mapOffs = stream.readUint32LE();
81 uint32 valuesOffs = stream.readUint32LE();
82 _map = dataStart + mapOffs;
83 _mapWidth = READ_LE_UINT16(_map + 0);
84 _mapHeight = READ_LE_UINT16(_map + 2);
85 _map += 8;
86 _values = dataStart + valuesOffs;
87 debug(0, "PriorityLayer::load() _width: %d; _height: %d; mapOffs: %08X; valuesOffs: %08X; _mapWidth: %d; _mapHeight: %d",
88 _width, _height, mapOffs, valuesOffs, _mapWidth, _mapHeight);
89 }
90
getPriority(Common::Point pos)91 int PriorityLayer::getPriority(Common::Point pos) {
92 pos.x = CLIP<int16>(pos.x, 0, _width - 1);
93 pos.y = CLIP<int16>(pos.y, 0, _height - 1);
94 const int16 tx = pos.x / 32, sx = pos.x % 32;
95 const int16 ty = pos.y / 8, sy = pos.y % 8;
96 uint16 mapIndex = READ_LE_UINT16(_map + 2 * (tx + ty * _mapWidth)) - 1;
97 return _values[mapIndex * 32 * 8 + sx + sy * 32];
98 }
99
100 // ScaleLayer
101
load(byte * dataStart,Common::SeekableReadStream & stream)102 void ScaleLayer::load(byte *dataStart, Common::SeekableReadStream &stream) {
103 _height = stream.readUint16LE();
104 stream.skip(2);
105 uint32 valuesOffs = stream.readUint32LE();
106 _values = dataStart + valuesOffs;
107 debug(0, "ScaleLayer::load() _height: %d; valuesOffs: %08X",
108 _height, valuesOffs);
109 }
110
getScale(Common::Point pos)111 int ScaleLayer::getScale(Common::Point pos) {
112 pos.y = CLIP<int16>(pos.y, 0, _height - 1);
113 return _values[pos.y];
114 }
115
116 // RegionLayer
117
load(byte * dataStart,Common::SeekableReadStream & stream)118 void RegionLayer::load(byte *dataStart, Common::SeekableReadStream &stream) {
119 _unk = stream.readUint32LE();
120 uint32 regionSequenceIdsOffs = stream.readUint32LE();
121 _width = stream.readUint16LE();
122 _height = stream.readUint16LE();
123 uint32 mapOffs = stream.readUint32LE();
124 uint32 valuesOffs = stream.readUint32LE();
125 _regionSequenceIds = dataStart + regionSequenceIdsOffs;
126 _map = dataStart + mapOffs;
127 _values = dataStart + valuesOffs;
128 _mapWidth = READ_LE_UINT16(_map + 0);
129 _mapHeight = READ_LE_UINT16(_map + 2);
130 _map += 8;
131 debug(1, "RegionLayer::load() %d; regionSequenceIdsOffs: %08X; _width: %d; _height: %d; mapOffs: %08X; valuesOffs: %08X",
132 _unk, regionSequenceIdsOffs, _width, _height, mapOffs, valuesOffs);
133 }
134
getRegionIndex(Common::Point pos)135 int RegionLayer::getRegionIndex(Common::Point pos) {
136 pos.x = CLIP<int16>(pos.x, 0, _width - 1);
137 pos.y = CLIP<int16>(pos.y, 0, _height - 1);
138 const int16 tx = pos.x / 32, sx = pos.x % 32;
139 const int16 ty = pos.y / 8, sy = pos.y % 8;
140 uint16 mapIndex = READ_LE_UINT16(_map + 2 * (tx + ty * _mapWidth)) - 1;
141 return _values[mapIndex * 32 * 8 + sx + sy * 32];
142 }
143
getRegionSequenceId(int regionIndex)144 uint32 RegionLayer::getRegionSequenceId(int regionIndex) {
145 return READ_LE_UINT32(_regionSequenceIds + 4 * regionIndex);
146 }
147
148 // Palette
149
load(byte * dataStart,Common::SeekableReadStream & stream)150 void Palette::load(byte *dataStart, Common::SeekableReadStream &stream) {
151 _count = stream.readUint16LE();
152 _unk = stream.readUint16LE();
153 uint32 paletteOffs = stream.readUint32LE();
154 _palette = dataStart + paletteOffs;
155 }
156
157 // BackgroundObject
158
load(byte * dataStart,Common::SeekableReadStream & stream)159 void BackgroundObject::load(byte *dataStart, Common::SeekableReadStream &stream) {
160 _objectId = stream.readUint32LE();
161 _flags = stream.readUint16LE();
162 _priority = stream.readUint16LE();
163 uint32 pointsConfigOffs = stream.readUint32LE();
164 _pointsConfig = dataStart + pointsConfigOffs;
165 debug(0, "BackgroundObject::load() _objectId: %08X; _flags: %04X; _priority: %d; pointsConfigOffs: %08X",
166 _objectId, _flags, _priority, pointsConfigOffs);
167 }
168
169 // PathWalkPoints
170
load(byte * dataStart,Common::SeekableReadStream & stream)171 void PathWalkPoints::load(byte *dataStart, Common::SeekableReadStream &stream) {
172 _points = new PointArray();
173 uint count = stream.readUint32LE();
174 uint32 pointsOffs = stream.readUint32LE();
175 _points->reserve(count);
176 stream.seek(pointsOffs);
177 for (uint i = 0; i < count; ++i) {
178 Common::Point pt;
179 loadPoint(stream, pt);
180 _points->push_back(pt);
181 }
182 debug(0, "PathWalkPoints::load() count: %d; pointsOffs: %08X",
183 count, pointsOffs);
184 }
185
186 // PathWalkRects
187
load(byte * dataStart,Common::SeekableReadStream & stream)188 void PathWalkRects::load(byte *dataStart, Common::SeekableReadStream &stream) {
189 _rects = new PathLines();
190 uint count = stream.readUint32LE();
191 uint32 rectsOffs = stream.readUint32LE();
192 _rects->reserve(count);
193 stream.seek(rectsOffs);
194 for (uint i = 0; i < count; ++i) {
195 PathLine rect;
196 loadPoint(stream, rect.p0);
197 loadPoint(stream, rect.p1);
198 _rects->push_back(rect);
199 }
200 debug(0, "PathWalkRects::load() count: %d; rectsOffs: %08X",
201 count, rectsOffs);
202 }
203
204 // BackgroundResource
205
BackgroundResource()206 BackgroundResource::BackgroundResource()
207 : _bgInfos(0), _scaleLayers(0), _priorityLayers(0), _regionLayers(0),
208 _regionSequences(0), _backgroundObjects(0), _pathWalkPoints(0),
209 _pathWalkRects(0), _palettes(0) {
210 }
211
~BackgroundResource()212 BackgroundResource::~BackgroundResource() {
213 delete[] _bgInfos;
214 delete[] _scaleLayers;
215 delete[] _priorityLayers;
216 delete[] _regionLayers;
217 delete[] _regionSequences;
218 delete[] _backgroundObjects;
219 delete[] _pathWalkPoints;
220 delete[] _pathWalkRects;
221 delete[] _palettes;
222 }
223
load(byte * data,uint32 dataSize)224 void BackgroundResource::load(byte *data, uint32 dataSize) {
225 Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
226
227 stream.seek(8);
228 _paletteIndex = stream.readUint16LE();
229
230 // Load background pixels
231 stream.seek(0x0A);
232 _bgInfosCount = stream.readUint16LE();
233 _bgInfos = new BgInfo[_bgInfosCount];
234 stream.seek(0x20);
235 uint32 bgInfosOffs = stream.readUint32LE();
236 for (uint i = 0; i < _bgInfosCount; ++i) {
237 stream.seek(bgInfosOffs + i * 0x1C);
238 _bgInfos[i].load(data, stream);
239 }
240
241 // Load scale layers
242 stream.seek(0x10);
243 _scaleLayersCount = stream.readUint16LE();
244 _scaleLayers = new ScaleLayer[_scaleLayersCount];
245 stream.seek(0x2C);
246 uint32 scaleLayersOffs = stream.readUint32LE();
247 debug(0, "_scaleLayersCount: %d", _scaleLayersCount);
248 for (uint i = 0; i < _scaleLayersCount; ++i) {
249 stream.seek(scaleLayersOffs + i * 8);
250 _scaleLayers[i].load(data, stream);
251 }
252
253 // Load priority layers
254 stream.seek(0x14);
255 _priorityLayersCount = stream.readUint16LE();
256 _priorityLayers = new PriorityLayer[_priorityLayersCount];
257 stream.seek(0x34);
258 uint32 priorityLayersOffs = stream.readUint32LE();
259 debug(1, "_priorityLayersCount: %d", _priorityLayersCount);
260 for (uint i = 0; i < _priorityLayersCount; ++i) {
261 stream.seek(priorityLayersOffs + i * 12);
262 _priorityLayers[i].load(data, stream);
263 }
264
265 // Load region layers
266 stream.seek(0x16);
267 _regionLayersCount = stream.readUint16LE();
268 _regionLayers = new RegionLayer[_regionLayersCount];
269 stream.seek(0x38);
270 uint32 regionLayersOffs = stream.readUint32LE();
271 debug(1, "_regionLayersCount: %d", _regionLayersCount);
272 for (uint i = 0; i < _regionLayersCount; ++i) {
273 stream.seek(regionLayersOffs + i * 20);
274 _regionLayers[i].load(data, stream);
275 }
276
277 // Load region sequences
278 stream.seek(0x1E);
279 _regionSequencesCount = stream.readUint16LE();
280 _regionSequences = new Sequence[_regionSequencesCount];
281 stream.seek(0x48);
282 uint32 regionSequencesOffs = stream.readUint32LE();
283 stream.seek(regionSequencesOffs);
284 for (uint i = 0; i < _regionSequencesCount; ++i) {
285 _regionSequences[i].load(data, stream);
286 }
287
288 // Load background objects
289 stream.seek(0x1C);
290 _backgroundObjectsCount = stream.readUint16LE();
291 _backgroundObjects = new BackgroundObject[_backgroundObjectsCount];
292 stream.seek(0x44);
293 uint32 backgroundObjectsOffs = stream.readUint32LE();
294 debug(0, "_backgroundObjectsCount: %d", _backgroundObjectsCount);
295 for (uint i = 0; i < _backgroundObjectsCount; ++i) {
296 stream.seek(backgroundObjectsOffs + i * 12);
297 _backgroundObjects[i].load(data, stream);
298 }
299
300 // Load path walk points
301 stream.seek(0x0E);
302 _pathWalkPointsCount = stream.readUint16LE();
303 debug(1, "_pathWalkPointsCount: %d", _pathWalkPointsCount);
304 _pathWalkPoints = new PathWalkPoints[_pathWalkPointsCount];
305 stream.seek(0x28);
306 uint32 pathWalkPointsOffs = stream.readUint32LE();
307 for (uint i = 0; i < _pathWalkPointsCount; ++i) {
308 stream.seek(pathWalkPointsOffs + i * 8);
309 _pathWalkPoints[i].load(data, stream);
310 }
311
312 // Load path walk rects
313 stream.seek(0x12);
314 _pathWalkRectsCount = stream.readUint16LE();
315 debug(1, "_pathWalkRectsCount: %d", _pathWalkRectsCount);
316 _pathWalkRects = new PathWalkRects[_pathWalkRectsCount];
317 stream.seek(0x30);
318 uint32 pathWalkRectsOffs = stream.readUint32LE();
319 for (uint i = 0; i < _pathWalkRectsCount; ++i) {
320 stream.seek(pathWalkRectsOffs + i * 8);
321 _pathWalkRects[i].load(data, stream);
322 }
323
324 // Load named points
325 stream.seek(0xC);
326 uint namedPointsCount = stream.readUint16LE();
327 stream.seek(0x24);
328 uint32 namedPointsOffs = stream.readUint32LE();
329 stream.seek(namedPointsOffs);
330 _namedPoints.load(namedPointsCount, stream);
331
332 // Load palettes
333 stream.seek(0x18);
334 _palettesCount = stream.readUint16LE();
335 _palettes = new Palette[_palettesCount];
336 stream.seek(0x3C);
337 uint32 palettesOffs = stream.readUint32LE();
338 debug(0, "_palettesCount: %d", _palettesCount);
339 for (uint i = 0; i < _palettesCount; ++i) {
340 stream.seek(palettesOffs + i * 8);
341 _palettes[i].load(data, stream);
342 }
343
344 }
345
findMasterBgIndex()346 int BackgroundResource::findMasterBgIndex() {
347 int index = 1;
348 while (!(_bgInfos[index - 1]._flags & 1)) { // TODO check if this is correct
349 ++index;
350 }
351 return index;
352 }
353
getPriorityLayer(uint index)354 PriorityLayer *BackgroundResource::getPriorityLayer(uint index) {
355 return &_priorityLayers[index];
356 }
357
getScaleLayer(uint index)358 ScaleLayer *BackgroundResource::getScaleLayer(uint index) {
359 return &_scaleLayers[index];
360 }
361
getRegionLayer(uint index)362 RegionLayer *BackgroundResource::getRegionLayer(uint index) {
363 return &_regionLayers[index];
364 }
365
getPathWalkPoints(uint index)366 PathWalkPoints *BackgroundResource::getPathWalkPoints(uint index) {
367 return &_pathWalkPoints[index];
368 }
369
getPathWalkRects(uint index)370 PathWalkRects *BackgroundResource::getPathWalkRects(uint index) {
371 return &_pathWalkRects[index];
372 }
373
getPalette(uint index)374 Palette *BackgroundResource::getPalette(uint index) {
375 return &_palettes[index];
376 }
377
findNamedPoint(uint32 namedPointId,Common::Point & pt)378 bool BackgroundResource::findNamedPoint(uint32 namedPointId, Common::Point &pt) {
379 return _namedPoints.findNamedPoint(namedPointId, pt);
380 }
381
382 // BackgroundInstance
383
BackgroundInstance(IllusionsEngine * vm)384 BackgroundInstance::BackgroundInstance(IllusionsEngine *vm)
385 : _vm(vm), _sceneId(0), _pauseCtr(0), _bgRes(0), _savedPalette(0) {
386 }
387
load(Resource * resource)388 void BackgroundInstance::load(Resource *resource) {
389 debug(1, "BackgroundResourceLoader::load() Loading background %08X from %s...", resource->_resId, resource->_filename.c_str());
390
391 BackgroundResource *backgroundResource = new BackgroundResource();
392 backgroundResource->load(resource->_data, resource->_dataSize);
393
394 _bgRes = backgroundResource;
395 _sceneId = resource->_sceneId;
396 initSurface();
397
398 // Insert background objects
399 for (uint i = 0; i < backgroundResource->_backgroundObjectsCount; ++i) {
400 _vm->_controls->placeBackgroundObject(&backgroundResource->_backgroundObjects[i]);
401 }
402
403 registerResources();
404
405 _vm->clearFader();
406
407 int index = _bgRes->findMasterBgIndex();
408 _vm->_camera->set(_bgRes->_bgInfos[index - 1]._panPoint, _bgRes->_bgInfos[index - 1]._surfInfo._dimensions);
409
410 if (_bgRes->_palettesCount > 0) {
411 Palette *palette = _bgRes->getPalette(_bgRes->_paletteIndex - 1);
412 _vm->_screenPalette->setPalette(palette->_palette, 1, palette->_count);
413 }
414
415 }
416
unload()417 void BackgroundInstance::unload() {
418 debug(1, "BackgroundInstance::unload()");
419 freeSurface();
420 unregisterResources();
421 delete _bgRes;
422 _vm->_backgroundInstances->removeBackgroundInstance(this);
423 _vm->setDefaultTextCoords();
424 }
425
pause()426 void BackgroundInstance::pause() {
427 ++_pauseCtr;
428 if (_pauseCtr <= 1) {
429 unregisterResources();
430 _vm->setDefaultTextCoords();
431 _vm->_camera->getActiveState(_savedCameraState);
432 _savedPalette = new byte[1024];
433 _vm->_screenPalette->getPalette(_savedPalette);
434 freeSurface();
435 }
436 }
437
unpause()438 void BackgroundInstance::unpause() {
439 --_pauseCtr;
440 if (_pauseCtr <= 0) {
441 registerResources();
442 initSurface();
443 _vm->_screenPalette->setPalette(_savedPalette, 1, 256);
444 delete[] _savedPalette;
445 _savedPalette = 0;
446 _vm->clearFader();
447 _vm->_camera->setActiveState(_savedCameraState);
448 _vm->_backgroundInstances->refreshPan();
449 }
450 }
451
registerResources()452 void BackgroundInstance::registerResources() {
453 for (uint i = 0; i < _bgRes->_regionSequencesCount; ++i) {
454 Sequence *sequence = &_bgRes->_regionSequences[i];
455 _vm->_dict->addSequence(sequence->_sequenceId, sequence);
456 }
457 }
458
unregisterResources()459 void BackgroundInstance::unregisterResources() {
460 for (uint i = 0; i < _bgRes->_regionSequencesCount; ++i) {
461 Sequence *sequence = &_bgRes->_regionSequences[i];
462 _vm->_dict->removeSequence(sequence->_sequenceId);
463 }
464 }
465
initSurface()466 void BackgroundInstance::initSurface() {
467 for (uint i = 0; i < kMaxBackgroundItemSurfaces; ++i) {
468 _surfaces[i] = 0;
469 }
470 for (uint i = 0; i < _bgRes->_bgInfosCount; ++i) {
471 BgInfo *bgInfo = &_bgRes->_bgInfos[i];
472 _panPoints[i] = bgInfo->_panPoint;
473 _surfaces[i] = _vm->_screen->allocSurface(bgInfo->_surfInfo);
474 drawTiles(_surfaces[i], bgInfo->_tileMap, bgInfo->_tilePixels);
475 #if 0
476 if (_bgRes->_pathWalkRectsCount > 0) {
477 PathLines *pl = _bgRes->_pathWalkRects->_rects;
478 for (int j=0; j < pl->size(); j++) {
479 PathLine pathLine = (*pl)[j];
480 debug(0, "walk path rect line[%d]. (%d,%d)->(%d,%d)", j, pathLine.p0.x, pathLine.p0.y, pathLine.p1.x, pathLine.p1.y);
481 _surfaces[i]->drawLine(pathLine.p0.x, pathLine.p0.y, pathLine.p1.x, pathLine.p1.y, 5);
482 }
483 }
484 #endif
485 }
486 }
487
freeSurface()488 void BackgroundInstance::freeSurface() {
489 for (uint i = 0; i < _bgRes->_bgInfosCount; ++i) {
490 if (_surfaces[i]) {
491 _surfaces[i]->free();
492 delete _surfaces[i];
493 _surfaces[i] = 0;
494 }
495 }
496 }
497
drawTiles(Graphics::Surface * surface,TileMap & tileMap,byte * tilePixels)498 void BackgroundInstance::drawTiles(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) {
499 switch (_vm->getGameId()) {
500 case kGameIdDuckman:
501 drawTiles8(surface, tileMap, tilePixels);
502 break;
503 case kGameIdBBDOU:
504 drawTiles16(surface, tileMap, tilePixels);
505 break;
506 default:
507 break;
508 }
509 }
510
drawTiles8(Graphics::Surface * surface,TileMap & tileMap,byte * tilePixels)511 void BackgroundInstance::drawTiles8(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) {
512 const int kTileWidth = 32;
513 const int kTileHeight = 8;
514 const int kTileSize = kTileWidth * kTileHeight;
515 uint tileMapIndex = 0;
516 for (int tileY = 0; tileY < tileMap._height; ++tileY) {
517 int tileDestY = tileY * kTileHeight;
518 int tileDestH = MIN(kTileHeight, surface->h - tileDestY);
519 for (int tileX = 0; tileX < tileMap._width; ++tileX) {
520 int tileDestX = tileX * kTileWidth;
521 int tileDestW = MIN(kTileWidth, surface->w - tileDestX);
522 uint16 tileIndex = READ_LE_UINT16(tileMap._map + 2 * tileMapIndex);
523 ++tileMapIndex;
524 byte *src = tilePixels + (tileIndex - 1) * kTileSize;
525 byte *dst = (byte*)surface->getBasePtr(tileDestX, tileDestY);
526 for (int h = 0; h < tileDestH; ++h) {
527 memcpy(dst, src, tileDestW);
528 dst += surface->pitch;
529 src += kTileWidth;
530 }
531 }
532 }
533 }
534
drawTiles16(Graphics::Surface * surface,TileMap & tileMap,byte * tilePixels)535 void BackgroundInstance::drawTiles16(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) {
536 const int kTileWidth = 32;
537 const int kTileHeight = 8;
538 const int kTileSize = kTileWidth * kTileHeight * 2;
539 uint tileMapIndex = 0;
540 for (int tileY = 0; tileY < tileMap._height; ++tileY) {
541 int tileDestY = tileY * kTileHeight;
542 int tileDestH = MIN(kTileHeight, surface->h - tileDestY);
543 for (int tileX = 0; tileX < tileMap._width; ++tileX) {
544 int tileDestX = tileX * kTileWidth;
545 int tileDestW = MIN(kTileWidth, surface->w - tileDestX);
546 uint16 tileIndex = READ_LE_UINT16(tileMap._map + 2 * tileMapIndex);
547 ++tileMapIndex;
548 byte *src = tilePixels + (tileIndex - 1) * kTileSize;
549 byte *dst = (byte*)surface->getBasePtr(tileDestX, tileDestY);
550 for (int h = 0; h < tileDestH; ++h) {
551 for (int w = 0; w < tileDestW; ++w) {
552 uint16 pixel = READ_LE_UINT16(src + w * 2);
553 WRITE_LE_UINT16(dst + w * 2, pixel);
554 }
555 dst += surface->pitch;
556 src += kTileWidth * 2;
557 }
558 }
559 }
560 }
561
562 // BackgroundInstanceList
563
BackgroundInstanceList(IllusionsEngine * vm)564 BackgroundInstanceList::BackgroundInstanceList(IllusionsEngine *vm)
565 : _vm(vm) {
566 }
567
~BackgroundInstanceList()568 BackgroundInstanceList::~BackgroundInstanceList() {
569 }
570
createBackgroundInstance(Resource * resource)571 BackgroundInstance *BackgroundInstanceList::createBackgroundInstance(Resource *resource) {
572 BackgroundInstance *backgroundInstance = new BackgroundInstance(_vm);
573 backgroundInstance->load(resource);
574 _items.push_back(backgroundInstance);
575 return backgroundInstance;
576 }
577
removeBackgroundInstance(BackgroundInstance * backgroundInstance)578 void BackgroundInstanceList::removeBackgroundInstance(BackgroundInstance *backgroundInstance) {
579 _items.remove(backgroundInstance);
580 }
581
pauseBySceneId(uint32 sceneId)582 void BackgroundInstanceList::pauseBySceneId(uint32 sceneId) {
583 for (ItemsIterator it = _items.begin(); it != _items.end(); ++it) {
584 if ((*it)->_sceneId == sceneId)
585 (*it)->pause();
586 }
587 }
588
unpauseBySceneId(uint32 sceneId)589 void BackgroundInstanceList::unpauseBySceneId(uint32 sceneId) {
590 for (ItemsIterator it = _items.begin(); it != _items.end(); ++it) {
591 if ((*it)->_sceneId == sceneId)
592 (*it)->unpause();
593 }
594 }
595
findActiveBackgroundInstance()596 BackgroundInstance *BackgroundInstanceList::findActiveBackgroundInstance() {
597 for (ItemsIterator it = _items.begin(); it != _items.end(); ++it) {
598 if ((*it)->_pauseCtr == 0)
599 return (*it);
600 }
601 return 0;
602 }
603
findBackgroundByResource(BackgroundResource * backgroundResource)604 BackgroundInstance *BackgroundInstanceList::findBackgroundByResource(BackgroundResource *backgroundResource) {
605 for (ItemsIterator it = _items.begin(); it != _items.end(); ++it) {
606 if ((*it)->_bgRes == backgroundResource)
607 return (*it);
608 }
609 return 0;
610 }
611
getActiveBgResource()612 BackgroundResource *BackgroundInstanceList::getActiveBgResource() {
613 BackgroundInstance *background = findActiveBackgroundInstance();
614 if (background)
615 return background->_bgRes;
616 return 0;
617 }
618
getMasterBgDimensions()619 WidthHeight BackgroundInstanceList::getMasterBgDimensions() {
620 BackgroundInstance *backgroundInstance = findActiveBackgroundInstance();
621 int16 index = backgroundInstance->_bgRes->findMasterBgIndex();
622 return backgroundInstance->_bgRes->_bgInfos[index - 1]._surfInfo._dimensions;
623 }
624
refreshPan()625 void BackgroundInstanceList::refreshPan() {
626 BackgroundInstance *backgroundInstance = findActiveBackgroundInstance();
627 if (backgroundInstance) {
628 WidthHeight dimensions = getMasterBgDimensions();
629 _vm->_camera->refreshPan(backgroundInstance, dimensions);
630 }
631 }
632
findActiveBackgroundNamedPoint(uint32 namedPointId,Common::Point & pt)633 bool BackgroundInstanceList::findActiveBackgroundNamedPoint(uint32 namedPointId, Common::Point &pt) {
634 BackgroundResource *backgroundResource = getActiveBgResource();
635 return backgroundResource ? backgroundResource->findNamedPoint(namedPointId, pt) : false;
636 }
637
638 } // End of namespace Illusions
639