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/debug.h"
24 #include "common/endian.h"
25 #include "common/system.h"
26 #include "common/stream.h"
27 #include "common/textconsole.h"
28
29 #include "graphics/surface.h"
30
31 #include "video/dxa_decoder.h"
32
33 #ifdef USE_ZLIB
34 #include "common/zlib.h"
35 #endif
36
37 namespace Video {
38
DXADecoder()39 DXADecoder::DXADecoder() {
40 }
41
~DXADecoder()42 DXADecoder::~DXADecoder() {
43 close();
44 }
45
loadStream(Common::SeekableReadStream * stream)46 bool DXADecoder::loadStream(Common::SeekableReadStream *stream) {
47 close();
48
49 uint32 tag = stream->readUint32BE();
50
51 if (tag != MKTAG('D','E','X','A')) {
52 close();
53 return false;
54 }
55
56 DXAVideoTrack *track = new DXAVideoTrack(stream);
57 addTrack(track);
58
59 readSoundData(stream);
60
61 track->setFrameStartPos();
62 return true;
63 }
64
readSoundData(Common::SeekableReadStream * stream)65 void DXADecoder::readSoundData(Common::SeekableReadStream *stream) {
66 // Skip over the tag by default
67 stream->readUint32BE();
68 }
69
DXAVideoTrack(Common::SeekableReadStream * stream)70 DXADecoder::DXAVideoTrack::DXAVideoTrack(Common::SeekableReadStream *stream) {
71 _fileStream = stream;
72 _curFrame = -1;
73 _frameStartOffset = 0;
74 _decompBuffer = 0;
75 _inBuffer = 0;
76 memset(_palette, 0, 256 * 3);
77
78 uint8 flags = _fileStream->readByte();
79 _frameCount = _fileStream->readUint16BE();
80 int32 frameRate = _fileStream->readSint32BE();
81
82 if (frameRate > 0)
83 _frameRate = 1000 / frameRate;
84 else if (frameRate < 0)
85 _frameRate = 100000 / (-frameRate);
86 else
87 _frameRate = 10;
88
89 _width = _fileStream->readUint16BE();
90 _height = _fileStream->readUint16BE();
91
92 if (flags & 0x80) {
93 _scaleMode = S_INTERLACED;
94 _curHeight = _height / 2;
95 } else if (flags & 0x40) {
96 _scaleMode = S_DOUBLE;
97 _curHeight = _height / 2;
98 } else {
99 _scaleMode = S_NONE;
100 _curHeight = _height;
101 }
102
103 _surface = new Graphics::Surface();
104 _surface->format = Graphics::PixelFormat::createFormatCLUT8();
105
106 debug(2, "flags 0x0%x framesCount %d width %d height %d rate %d", flags, getFrameCount(), getWidth(), getHeight(), getFrameRate().toInt());
107
108 _frameSize = _width * _height;
109 _decompBufferSize = _frameSize;
110 _frameBuffer1 = new byte[_frameSize];
111 memset(_frameBuffer1, 0, _frameSize);
112 _frameBuffer2 = new byte[_frameSize];
113 memset(_frameBuffer2, 0, _frameSize);
114
115 _scaledBuffer = 0;
116 if (_scaleMode != S_NONE) {
117 _scaledBuffer = new byte[_frameSize];
118 memset(_scaledBuffer, 0, _frameSize);
119 }
120
121 #ifdef DXA_EXPERIMENT_MAXD
122 // Check for an extended header
123 if (flags & 1) {
124 uint32 size;
125
126 do {
127 tag = _fileStream->readUint32BE();
128
129 if (tag != 0)
130 size = _fileStream->readUint32BE();
131
132 switch (tag) {
133 case 0: // No more tags
134 break;
135 case MKTAG('M','A','X','D'):
136 assert(size == 4);
137 _decompBufferSize = _fileStream->readUint32BE();
138 break;
139 default: // Unknown tag - skip it.
140 while (size > 0) {
141 byte dummy = _fileStream->readByte();
142 size--;
143 }
144 break;
145 }
146 } while (tag != 0);
147 }
148 #endif
149 }
150
~DXAVideoTrack()151 DXADecoder::DXAVideoTrack::~DXAVideoTrack() {
152 delete _fileStream;
153 delete _surface;
154 delete[] _frameBuffer1;
155 delete[] _frameBuffer2;
156 delete[] _scaledBuffer;
157 delete[] _inBuffer;
158 delete[] _decompBuffer;
159 }
160
rewind()161 bool DXADecoder::DXAVideoTrack::rewind() {
162 _curFrame = -1;
163 _fileStream->seek(_frameStartOffset);
164 return true;
165 }
166
getPixelFormat() const167 Graphics::PixelFormat DXADecoder::DXAVideoTrack::getPixelFormat() const {
168 return _surface->format;
169 }
170
setFrameStartPos()171 void DXADecoder::DXAVideoTrack::setFrameStartPos() {
172 _frameStartOffset = _fileStream->pos();
173 }
174
decodeZlib(byte * data,int size,int totalSize)175 void DXADecoder::DXAVideoTrack::decodeZlib(byte *data, int size, int totalSize) {
176 #ifdef USE_ZLIB
177 unsigned long dstLen = totalSize;
178 Common::uncompress(data, &dstLen, _inBuffer, size);
179 #endif
180 }
181
182 #define BLOCKW 4
183 #define BLOCKH 4
184
decode12(int size)185 void DXADecoder::DXAVideoTrack::decode12(int size) {
186 #ifdef USE_ZLIB
187 if (!_decompBuffer) {
188 _decompBuffer = new byte[_decompBufferSize];
189 memset(_decompBuffer, 0, _decompBufferSize);
190 }
191
192 /* decompress the input data */
193 decodeZlib(_decompBuffer, size, _decompBufferSize);
194
195 byte *dat = _decompBuffer;
196
197 memcpy(_frameBuffer2, _frameBuffer1, _frameSize);
198
199 for (uint32 by = 0; by < _height; by += BLOCKH) {
200 for (uint32 bx = 0; bx < _width; bx += BLOCKW) {
201 byte type = *dat++;
202 byte *b2 = _frameBuffer1 + bx + by * _width;
203
204 switch (type) {
205 case 0:
206 break;
207 case 10:
208 case 11:
209 case 12:
210 case 13:
211 case 14:
212 case 15:
213 case 1: {
214 unsigned short diffMap;
215 if (type >= 10 && type <= 15) {
216 static const struct { uint8 sh1, sh2; } shiftTbl[6] = {
217 {0, 0}, {8, 0}, {8, 8}, {8, 4}, {4, 0}, {4, 4}
218 };
219 diffMap = ((*dat & 0xF0) << shiftTbl[type-10].sh1) |
220 ((*dat & 0x0F) << shiftTbl[type-10].sh2);
221 dat++;
222 } else {
223 diffMap = *(unsigned short*)dat;
224 dat += 2;
225 }
226
227 for (int yc = 0; yc < BLOCKH; yc++) {
228 for (int xc = 0; xc < BLOCKW; xc++) {
229 if (diffMap & 0x8000) {
230 b2[xc] = *dat++;
231 }
232 diffMap <<= 1;
233 }
234 b2 += _width;
235 }
236 break;
237 }
238 case 2: {
239 byte color = *dat++;
240
241 for (int yc = 0; yc < BLOCKH; yc++) {
242 for (int xc = 0; xc < BLOCKW; xc++) {
243 b2[xc] = color;
244 }
245 b2 += _width;
246 }
247 break;
248 }
249 case 3: {
250 for (int yc = 0; yc < BLOCKH; yc++) {
251 for (int xc = 0; xc < BLOCKW; xc++) {
252 b2[xc] = *dat++;
253 }
254 b2 += _width;
255 }
256 break;
257 }
258 case 4: {
259 byte mbyte = *dat++;
260 int mx = (mbyte >> 4) & 0x07;
261 if (mbyte & 0x80)
262 mx = -mx;
263 int my = mbyte & 0x07;
264 if (mbyte & 0x08)
265 my = -my;
266 byte *b1 = _frameBuffer2 + (bx+mx) + (by+my) * _width;
267 for (int yc = 0; yc < BLOCKH; yc++) {
268 memcpy(b2, b1, BLOCKW);
269 b1 += _width;
270 b2 += _width;
271 }
272 break;
273 }
274 case 5:
275 break;
276 default:
277 error("decode12: Unknown type %d", type);
278 }
279 }
280 }
281 #endif
282 }
283
decode13(int size)284 void DXADecoder::DXAVideoTrack::decode13(int size) {
285 #ifdef USE_ZLIB
286 uint8 *codeBuf, *dataBuf, *motBuf, *maskBuf;
287
288 if (!_decompBuffer) {
289 _decompBuffer = new byte[_decompBufferSize];
290 memset(_decompBuffer, 0, _decompBufferSize);
291 }
292
293 /* decompress the input data */
294 decodeZlib(_decompBuffer, size, _decompBufferSize);
295
296 memcpy(_frameBuffer2, _frameBuffer1, _frameSize);
297
298 int codeSize = _width * _curHeight / 16;
299 int dataSize, motSize;
300
301 dataSize = READ_BE_UINT32(&_decompBuffer[0]);
302 motSize = READ_BE_UINT32(&_decompBuffer[4]);
303 //maskSize = READ_BE_UINT32(&_decompBuffer[8]);
304
305 codeBuf = &_decompBuffer[12];
306 dataBuf = &codeBuf[codeSize];
307 motBuf = &dataBuf[dataSize];
308 maskBuf = &motBuf[motSize];
309
310 for (uint32 by = 0; by < _curHeight; by += BLOCKH) {
311 for (uint32 bx = 0; bx < _width; bx += BLOCKW) {
312 uint8 type = *codeBuf++;
313 uint8 *b2 = (uint8 *)_frameBuffer1 + bx + by * _width;
314
315 switch (type) {
316 case 0:
317 break;
318
319 case 1: {
320 uint16 diffMap = READ_BE_UINT16(maskBuf);
321 maskBuf += 2;
322
323 for (int yc = 0; yc < BLOCKH; yc++) {
324 for (int xc = 0; xc < BLOCKW; xc++) {
325 if (diffMap & 0x8000) {
326 b2[xc] = *dataBuf++;
327 }
328 diffMap <<= 1;
329 }
330 b2 += _width;
331 }
332 break;
333 }
334 case 2: {
335 uint8 color = *dataBuf++;
336
337 for (int yc = 0; yc < BLOCKH; yc++) {
338 for (int xc = 0; xc < BLOCKW; xc++) {
339 b2[xc] = color;
340 }
341 b2 += _width;
342 }
343 break;
344 }
345 case 3: {
346 for (int yc = 0; yc < BLOCKH; yc++) {
347 for (int xc = 0; xc < BLOCKW; xc++) {
348 b2[xc] = *dataBuf++;
349 }
350 b2 += _width;
351 }
352 break;
353 }
354 case 4: {
355 uint8 mbyte = *motBuf++;
356
357 int mx = (mbyte >> 4) & 0x07;
358 if (mbyte & 0x80)
359 mx = -mx;
360 int my = mbyte & 0x07;
361 if (mbyte & 0x08)
362 my = -my;
363
364 uint8 *b1 = (uint8 *)_frameBuffer2 + (bx+mx) + (by+my) * _width;
365 for (int yc = 0; yc < BLOCKH; yc++) {
366 memcpy(b2, b1, BLOCKW);
367 b1 += _width;
368 b2 += _width;
369 }
370 break;
371 }
372 case 8: {
373 static const int subX[4] = {0, 2, 0, 2};
374 static const int subY[4] = {0, 0, 2, 2};
375
376 uint8 subMask = *maskBuf++;
377
378 for (int subBlock = 0; subBlock < 4; subBlock++) {
379 int sx = bx + subX[subBlock], sy = by + subY[subBlock];
380 b2 = (uint8 *)_frameBuffer1 + sx + sy * _width;
381 switch (subMask & 0xC0) {
382 // 00: skip
383 case 0x00:
384 break;
385 // 01: solid color
386 case 0x40: {
387 uint8 subColor = *dataBuf++;
388 for (int yc = 0; yc < BLOCKH / 2; yc++) {
389 for (int xc = 0; xc < BLOCKW / 2; xc++) {
390 b2[xc] = subColor;
391 }
392 b2 += _width;
393 }
394 break;
395 }
396 // 02: motion vector
397 case 0x80: {
398 uint8 mbyte = *motBuf++;
399
400 int mx = (mbyte >> 4) & 0x07;
401 if (mbyte & 0x80)
402 mx = -mx;
403
404 int my = mbyte & 0x07;
405 if (mbyte & 0x08)
406 my = -my;
407
408 uint8 *b1 = (uint8 *)_frameBuffer2 + (sx+mx) + (sy+my) * _width;
409 for (int yc = 0; yc < BLOCKH / 2; yc++) {
410 memcpy(b2, b1, BLOCKW / 2);
411 b1 += _width;
412 b2 += _width;
413 }
414 break;
415 }
416 // 03: raw
417 case 0xC0:
418 for (int yc = 0; yc < BLOCKH / 2; yc++) {
419 for (int xc = 0; xc < BLOCKW / 2; xc++) {
420 b2[xc] = *dataBuf++;
421 }
422 b2 += _width;
423 }
424 break;
425 }
426 subMask <<= 2;
427 }
428 break;
429 }
430 case 32:
431 case 33:
432 case 34: {
433 int count = type - 30;
434 uint8 pixels[4];
435
436 memcpy(pixels, dataBuf, count);
437 dataBuf += count;
438
439 if (count == 2) {
440 uint16 code = READ_BE_UINT16(maskBuf);
441 maskBuf += 2;
442 for (int yc = 0; yc < BLOCKH; yc++) {
443 for (int xc = 0; xc < BLOCKW; xc++) {
444 b2[xc] = pixels[code & 1];
445 code >>= 1;
446 }
447 b2 += _width;
448 }
449 } else {
450 uint32 code = READ_BE_UINT32(maskBuf);
451 maskBuf += 4;
452 for (int yc = 0; yc < BLOCKH; yc++) {
453 for (int xc = 0; xc < BLOCKW; xc++) {
454 b2[xc] = pixels[code & 3];
455 code >>= 2;
456 }
457 b2 += _width;
458 }
459 }
460 break;
461 }
462 default:
463 error("decode13: Unknown type %d", type);
464 }
465 }
466 }
467 #endif
468 }
469
decodeNextFrame()470 const Graphics::Surface *DXADecoder::DXAVideoTrack::decodeNextFrame() {
471 uint32 tag = _fileStream->readUint32BE();
472 if (tag == MKTAG('C','M','A','P')) {
473 _fileStream->read(_palette, 256 * 3);
474 _dirtyPalette = true;
475 }
476
477 tag = _fileStream->readUint32BE();
478 if (tag == MKTAG('F','R','A','M')) {
479 byte type = _fileStream->readByte();
480 uint32 size = _fileStream->readUint32BE();
481
482 if (!_inBuffer || _inBufferSize < size) {
483 delete[] _inBuffer;
484 _inBuffer = new byte[size];
485 memset(_inBuffer, 0, size);
486 _inBufferSize = size;
487 }
488
489 _fileStream->read(_inBuffer, size);
490
491 switch (type) {
492 case 2:
493 decodeZlib(_frameBuffer1, size, _frameSize);
494 break;
495 case 3:
496 decodeZlib(_frameBuffer2, size, _frameSize);
497 break;
498 case 12:
499 decode12(size);
500 break;
501 case 13:
502 decode13(size);
503 break;
504 default:
505 error("decodeFrame: Unknown compression type %d", type);
506 }
507
508 if (type == 3) {
509 for (uint32 j = 0; j < _curHeight; ++j) {
510 for (uint32 i = 0; i < _width; ++i) {
511 const int offs = j * _width + i;
512 _frameBuffer1[offs] ^= _frameBuffer2[offs];
513 }
514 }
515 }
516 }
517
518 switch (_scaleMode) {
519 case S_INTERLACED:
520 for (int cy = 0; cy < _curHeight; cy++) {
521 memcpy(&_scaledBuffer[2 * cy * _width], &_frameBuffer1[cy * _width], _width);
522 memset(&_scaledBuffer[((2 * cy) + 1) * _width], 0, _width);
523 }
524 _surface->setPixels(_scaledBuffer);
525 break;
526 case S_DOUBLE:
527 for (int cy = 0; cy < _curHeight; cy++) {
528 memcpy(&_scaledBuffer[2 * cy * _width], &_frameBuffer1[cy * _width], _width);
529 memcpy(&_scaledBuffer[((2 * cy) + 1) * _width], &_frameBuffer1[cy * _width], _width);
530 }
531 _surface->setPixels(_scaledBuffer);
532 break;
533 case S_NONE:
534 _surface->setPixels(_frameBuffer1);
535 break;
536 }
537
538 // Copy in the relevant info to the Surface
539 _surface->w = getWidth();
540 _surface->h = getHeight();
541 _surface->pitch = getWidth();
542
543 _curFrame++;
544
545 return _surface;
546 }
547
548 } // End of namespace Video
549