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