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 // Based on http://wiki.multimedia.cx/index.php?title=Smacker
24 // and the FFmpeg Smacker decoder (libavcodec/smacker.c), revision 16143
25 // http://git.ffmpeg.org/?p=ffmpeg;a=blob;f=libavcodec/smacker.c;hb=b8437a00a2f14d4a437346455d624241d726128e
26 
27 #include "video/smk_decoder.h"
28 
29 #include "common/endian.h"
30 #include "common/util.h"
31 #include "common/stream.h"
32 #include "common/bitstream.h"
33 #include "common/system.h"
34 #include "common/textconsole.h"
35 
36 #include "audio/audiostream.h"
37 #include "audio/mixer.h"
38 #include "audio/decoders/raw.h"
39 
40 namespace Video {
41 
42 enum SmkBlockTypes {
43 	SMK_BLOCK_MONO = 0,
44 	SMK_BLOCK_FULL = 1,
45 	SMK_BLOCK_SKIP = 2,
46 	SMK_BLOCK_FILL = 3
47 };
48 
49 /*
50  * class SmallHuffmanTree
51  * A Huffman-tree to hold 8-bit values.
52  */
53 
54 class SmallHuffmanTree {
55 public:
56 	SmallHuffmanTree(Common::BitStreamMemory8LSB &bs);
57 
58 	uint16 getCode(Common::BitStreamMemory8LSB &bs);
59 private:
60 	enum {
61 		SMK_NODE = 0x8000
62 	};
63 
64 	uint16 decodeTree(uint32 prefix, int length);
65 
66 	uint16 _treeSize;
67 	uint16 _tree[511];
68 
69 	uint16 _prefixtree[256];
70 	byte _prefixlength[256];
71 
72 	Common::BitStreamMemory8LSB &_bs;
73 };
74 
SmallHuffmanTree(Common::BitStreamMemory8LSB & bs)75 SmallHuffmanTree::SmallHuffmanTree(Common::BitStreamMemory8LSB &bs)
76 	: _treeSize(0), _bs(bs) {
77 	uint32 bit = _bs.getBit();
78 	assert(bit);
79 
80 	for (uint16 i = 0; i < 256; ++i)
81 		_prefixtree[i] = _prefixlength[i] = 0;
82 
83 	decodeTree(0, 0);
84 
85 	bit = _bs.getBit();
86 	assert(!bit);
87 }
88 
decodeTree(uint32 prefix,int length)89 uint16 SmallHuffmanTree::decodeTree(uint32 prefix, int length) {
90 	if (!_bs.getBit()) { // Leaf
91 		_tree[_treeSize] = _bs.getBits(8);
92 
93 		if (length <= 8) {
94 			for (int i = 0; i < 256; i += (1 << length)) {
95 				_prefixtree[prefix | i] = _treeSize;
96 				_prefixlength[prefix | i] = length;
97 			}
98 		}
99 		++_treeSize;
100 
101 		return 1;
102 	}
103 
104 	uint16 t = _treeSize++;
105 
106 	if (length == 8) {
107 		_prefixtree[prefix] = t;
108 		_prefixlength[prefix] = 8;
109 	}
110 
111 	uint16 r1 = decodeTree(prefix, length + 1);
112 
113 	_tree[t] = (SMK_NODE | r1);
114 
115 	uint16 r2 = decodeTree(prefix | (1 << length), length + 1);
116 
117 	return r1+r2+1;
118 }
119 
getCode(Common::BitStreamMemory8LSB & bs)120 uint16 SmallHuffmanTree::getCode(Common::BitStreamMemory8LSB &bs) {
121 	byte peek = bs.peekBits(MIN<uint32>(bs.size() - bs.pos(), 8));
122 	uint16 *p = &_tree[_prefixtree[peek]];
123 	bs.skip(_prefixlength[peek]);
124 
125 	while (*p & SMK_NODE) {
126 		if (bs.getBit())
127 			p += *p & ~SMK_NODE;
128 		p++;
129 	}
130 
131 	return *p;
132 }
133 
134 /*
135  * class BigHuffmanTree
136  * A Huffman-tree to hold 16-bit values.
137  */
138 
139 class BigHuffmanTree {
140 public:
141 	BigHuffmanTree(Common::BitStreamMemory8LSB &bs, int allocSize);
142 	~BigHuffmanTree();
143 
144 	void reset();
145 	uint32 getCode(Common::BitStreamMemory8LSB &bs);
146 private:
147 	enum {
148 		SMK_NODE = 0x80000000
149 	};
150 
151 	uint32 decodeTree(uint32 prefix, int length);
152 
153 	uint32  _treeSize;
154 	uint32 *_tree;
155 	uint32  _last[3];
156 
157 	uint32 _prefixtree[256];
158 	byte _prefixlength[256];
159 
160 	/* Used during construction */
161 	Common::BitStreamMemory8LSB &_bs;
162 	uint32 _markers[3];
163 	SmallHuffmanTree *_loBytes;
164 	SmallHuffmanTree *_hiBytes;
165 };
166 
BigHuffmanTree(Common::BitStreamMemory8LSB & bs,int allocSize)167 BigHuffmanTree::BigHuffmanTree(Common::BitStreamMemory8LSB &bs, int allocSize)
168 	: _bs(bs) {
169 	uint32 bit = _bs.getBit();
170 	if (!bit) {
171 		_tree = new uint32[1];
172 		_tree[0] = 0;
173 		_last[0] = _last[1] = _last[2] = 0;
174 		return;
175 	}
176 
177 	for (uint32 i = 0; i < 256; ++i)
178 		_prefixtree[i] = _prefixlength[i] = 0;
179 
180 	_loBytes = new SmallHuffmanTree(_bs);
181 	_hiBytes = new SmallHuffmanTree(_bs);
182 
183 	_markers[0] = _bs.getBits(16);
184 	_markers[1] = _bs.getBits(16);
185 	_markers[2] = _bs.getBits(16);
186 
187 	_last[0] = _last[1] = _last[2] = 0xffffffff;
188 
189 	_treeSize = 0;
190 	_tree = new uint32[allocSize / 4];
191 	decodeTree(0, 0);
192 	bit = _bs.getBit();
193 	assert(!bit);
194 
195 	for (uint32 i = 0; i < 3; ++i) {
196 		if (_last[i] == 0xffffffff) {
197 			_last[i] = _treeSize;
198 			_tree[_treeSize++] = 0;
199 		}
200 	}
201 
202 	delete _loBytes;
203 	delete _hiBytes;
204 }
205 
~BigHuffmanTree()206 BigHuffmanTree::~BigHuffmanTree() {
207 	delete[] _tree;
208 }
209 
reset()210 void BigHuffmanTree::reset() {
211 	_tree[_last[0]] = _tree[_last[1]] = _tree[_last[2]] = 0;
212 }
213 
decodeTree(uint32 prefix,int length)214 uint32 BigHuffmanTree::decodeTree(uint32 prefix, int length) {
215 	uint32 bit = _bs.getBit();
216 
217 	if (!bit) { // Leaf
218 		uint32 lo = _loBytes->getCode(_bs);
219 		uint32 hi = _hiBytes->getCode(_bs);
220 
221 		uint32 v = (hi << 8) | lo;
222 
223 		_tree[_treeSize] = v;
224 
225 		if (length <= 8) {
226 			for (int i = 0; i < 256; i += (1 << length)) {
227 				_prefixtree[prefix | i] = _treeSize;
228 				_prefixlength[prefix | i] = length;
229 			}
230 		}
231 
232 		for (int i = 0; i < 3; ++i) {
233 			if (_markers[i] == v) {
234 				_last[i] = _treeSize;
235 				_tree[_treeSize] = 0;
236 			}
237 		}
238 		++_treeSize;
239 
240 		return 1;
241 	}
242 
243 	uint32 t = _treeSize++;
244 
245 	if (length == 8) {
246 		_prefixtree[prefix] = t;
247 		_prefixlength[prefix] = 8;
248 	}
249 
250 	uint32 r1 = decodeTree(prefix, length + 1);
251 
252 	_tree[t] = SMK_NODE | r1;
253 
254 	uint32 r2 = decodeTree(prefix | (1 << length), length + 1);
255 	return r1+r2+1;
256 }
257 
getCode(Common::BitStreamMemory8LSB & bs)258 uint32 BigHuffmanTree::getCode(Common::BitStreamMemory8LSB &bs) {
259 	byte peek = bs.peekBits(MIN<uint32>(bs.size() - bs.pos(), 8));
260 	uint32 *p = &_tree[_prefixtree[peek]];
261 	bs.skip(_prefixlength[peek]);
262 
263 	while (*p & SMK_NODE) {
264 		if (bs.getBit())
265 			p += (*p) & ~SMK_NODE;
266 		p++;
267 	}
268 
269 	uint32 v = *p;
270 	if (v != _tree[_last[0]]) {
271 		_tree[_last[2]] = _tree[_last[1]];
272 		_tree[_last[1]] = _tree[_last[0]];
273 		_tree[_last[0]] = v;
274 	}
275 
276 	return v;
277 }
278 
SmackerDecoder()279 SmackerDecoder::SmackerDecoder() {
280 	_fileStream = 0;
281 	_firstFrameStart = 0;
282 	_frameTypes = 0;
283 	_frameSizes = 0;
284 }
285 
~SmackerDecoder()286 SmackerDecoder::~SmackerDecoder() {
287 	close();
288 }
289 
loadStream(Common::SeekableReadStream * stream)290 bool SmackerDecoder::loadStream(Common::SeekableReadStream *stream) {
291 	close();
292 
293 	_fileStream = stream;
294 
295 	// Read in the Smacker header
296 	_header.signature = _fileStream->readUint32BE();
297 
298 	if (_header.signature != MKTAG('S', 'M', 'K', '2') && _header.signature != MKTAG('S', 'M', 'K', '4'))
299 		return false;
300 
301 	uint32 width = _fileStream->readUint32LE();
302 	uint32 height = _fileStream->readUint32LE();
303 	uint32 frameCount = _fileStream->readUint32LE();
304 	int32 frameDelay = _fileStream->readSint32LE();
305 
306 	// frame rate contains 2 digits after the comma, so 1497 is actually 14.97 fps
307 	Common::Rational frameRate;
308 	if (frameDelay > 0)
309 		frameRate = Common::Rational(1000, frameDelay);
310 	else if (frameDelay < 0)
311 		frameRate = Common::Rational(100000, -frameDelay);
312 	else
313 		frameRate = 1000;
314 
315 	// Flags are determined by which bit is set, which can be one of the following:
316 	// 0 - set to 1 if file contains a ring frame.
317 	// 1 - set to 1 if file is Y-interlaced
318 	// 2 - set to 1 if file is Y-doubled
319 	// If bits 1 or 2 are set, the frame should be scaled to twice its height
320 	// before it is displayed.
321 	_header.flags = _fileStream->readUint32LE();
322 
323 	SmackerVideoTrack *videoTrack = createVideoTrack(width, height, frameCount, frameRate, _header.flags, _header.signature);
324 	addTrack(videoTrack);
325 
326 	// TODO: should we do any extra processing for Smacker files with ring frames?
327 
328 	// TODO: should we do any extra processing for Y-doubled videos? Are they the
329 	// same as Y-interlaced videos?
330 
331 	uint32 i;
332 	for (i = 0; i < 7; ++i)
333 		_header.audioSize[i] = _fileStream->readUint32LE();
334 
335 	_header.treesSize = _fileStream->readUint32LE();
336 	_header.mMapSize = _fileStream->readUint32LE();
337 	_header.mClrSize = _fileStream->readUint32LE();
338 	_header.fullSize = _fileStream->readUint32LE();
339 	_header.typeSize = _fileStream->readUint32LE();
340 
341 	for (i = 0; i < 7; ++i) {
342 		// AudioRate - Frequency and format information for each sound track, up to 7 audio tracks.
343 		// The 32 constituent bits have the following meaning:
344 		// * bit 31 - indicates Huffman + DPCM compression
345 		// * bit 30 - indicates that audio data is present for this track
346 		// * bit 29 - 1 = 16-bit audio; 0 = 8-bit audio
347 		// * bit 28 - 1 = stereo audio; 0 = mono audio
348 		// * bit 27 - indicates Bink RDFT compression
349 		// * bit 26 - indicates Bink DCT compression
350 		// * bits 25-24 - unused
351 		// * bits 23-0 - audio sample rate
352 		uint32 audioInfo = _fileStream->readUint32LE();
353 		_header.audioInfo[i].hasAudio = audioInfo & 0x40000000;
354 		_header.audioInfo[i].is16Bits = audioInfo & 0x20000000;
355 		_header.audioInfo[i].isStereo = audioInfo & 0x10000000;
356 		_header.audioInfo[i].sampleRate = audioInfo & 0xFFFFFF;
357 
358 		if (audioInfo & 0x8000000)
359 			_header.audioInfo[i].compression = kCompressionRDFT;
360 		else if (audioInfo & 0x4000000)
361 			_header.audioInfo[i].compression = kCompressionDCT;
362 		else if (audioInfo & 0x80000000)
363 			_header.audioInfo[i].compression = kCompressionDPCM;
364 		else
365 			_header.audioInfo[i].compression = kCompressionNone;
366 
367 		if (_header.audioInfo[i].hasAudio) {
368 			if (_header.audioInfo[i].compression == kCompressionRDFT || _header.audioInfo[i].compression == kCompressionDCT)
369 				warning("Unhandled Smacker v2 audio compression");
370 
371 			addTrack(new SmackerAudioTrack(_header.audioInfo[i], getSoundType()));
372 		}
373 	}
374 
375 	_header.dummy = _fileStream->readUint32LE();
376 
377 	_frameSizes = new uint32[frameCount];
378 	for (i = 0; i < frameCount; ++i)
379 		_frameSizes[i] = _fileStream->readUint32LE();
380 
381 	_frameTypes = new byte[frameCount];
382 	for (i = 0; i < frameCount; ++i)
383 		_frameTypes[i] = _fileStream->readByte();
384 
385 	byte *huffmanTrees = (byte *) malloc(_header.treesSize);
386 	_fileStream->read(huffmanTrees, _header.treesSize);
387 
388 	Common::BitStreamMemory8LSB bs(new Common::BitStreamMemoryStream(huffmanTrees, _header.treesSize, DisposeAfterUse::YES), DisposeAfterUse::YES);
389 	videoTrack->readTrees(bs, _header.mMapSize, _header.mClrSize, _header.fullSize, _header.typeSize);
390 
391 	_firstFrameStart = _fileStream->pos();
392 
393 	return true;
394 }
395 
close()396 void SmackerDecoder::close() {
397 	VideoDecoder::close();
398 
399 	delete _fileStream;
400 	_fileStream = 0;
401 
402 	delete[] _frameTypes;
403 	_frameTypes = 0;
404 
405 	delete[] _frameSizes;
406 	_frameSizes = 0;
407 }
408 
rewind()409 bool SmackerDecoder::rewind() {
410 	// Call the parent method to rewind the tracks first
411 	if (!VideoDecoder::rewind())
412 		return false;
413 
414 	// And seek back to where the first frame begins
415 	_fileStream->seek(_firstFrameStart);
416 	return true;
417 }
418 
readNextPacket()419 void SmackerDecoder::readNextPacket() {
420 	SmackerVideoTrack *videoTrack = (SmackerVideoTrack *)getTrack(0);
421 
422 	if (videoTrack->endOfTrack())
423 		return;
424 
425 	videoTrack->increaseCurFrame();
426 
427 	uint i;
428 	uint32 chunkSize = 0;
429 	uint32 dataSizeUnpacked = 0;
430 
431 	uint32 startPos = _fileStream->pos();
432 
433 	// Check if we got a frame with palette data, and
434 	// call back the virtual setPalette function to set
435 	// the current palette
436 	if (_frameTypes[videoTrack->getCurFrame()] & 1)
437 		videoTrack->unpackPalette(_fileStream);
438 
439 	// Load audio tracks
440 	for (i = 0; i < 7; ++i) {
441 		if (!(_frameTypes[videoTrack->getCurFrame()] & (2 << i)))
442 			continue;
443 
444 		chunkSize = _fileStream->readUint32LE();
445 		chunkSize -= 4;    // subtract the first 4 bytes (chunk size)
446 
447 		if (_header.audioInfo[i].compression == kCompressionNone) {
448 			dataSizeUnpacked = chunkSize;
449 		} else {
450 			dataSizeUnpacked = _fileStream->readUint32LE();
451 			chunkSize -= 4;    // subtract the next 4 bytes (unpacked data size)
452 		}
453 
454 		handleAudioTrack(i, chunkSize, dataSizeUnpacked);
455 	}
456 
457 	uint32 frameSize = _frameSizes[videoTrack->getCurFrame()] & ~3;
458 //	uint32 remainder =  _frameSizes[videoTrack->getCurFrame()] & 3;
459 
460 	if (_fileStream->pos() - startPos > frameSize)
461 		error("Smacker actual frame size exceeds recorded frame size");
462 
463 	uint32 frameDataSize = frameSize - (_fileStream->pos() - startPos);
464 
465 	byte *frameData = (byte *)malloc(frameDataSize + 1);
466 	// Padding to keep the BigHuffmanTrees from reading past the data end
467 	frameData[frameDataSize] = 0x00;
468 
469 	_fileStream->read(frameData, frameDataSize);
470 
471 	Common::BitStreamMemory8LSB bs(new Common::BitStreamMemoryStream(frameData, frameDataSize + 1, DisposeAfterUse::YES), DisposeAfterUse::YES);
472 	videoTrack->decodeFrame(bs);
473 
474 	_fileStream->seek(startPos + frameSize);
475 }
476 
handleAudioTrack(byte track,uint32 chunkSize,uint32 unpackedSize)477 void SmackerDecoder::handleAudioTrack(byte track, uint32 chunkSize, uint32 unpackedSize) {
478 	if (chunkSize == 0)
479 		return;
480 
481 	if (_header.audioInfo[track].hasAudio) {
482 		// Get the audio track, which start at offset 1 (first track is video)
483 		SmackerAudioTrack *audioTrack = (SmackerAudioTrack *)getTrack(track + 1);
484 
485 		// If it's track 0, play the audio data
486 		byte *soundBuffer = (byte *)malloc(chunkSize + 1);
487 		// Padding to keep the SmallHuffmanTrees from reading past the data end
488 		soundBuffer[chunkSize] = 0x00;
489 
490 		_fileStream->read(soundBuffer, chunkSize);
491 
492 		if (_header.audioInfo[track].compression == kCompressionRDFT || _header.audioInfo[track].compression == kCompressionDCT) {
493 			// TODO: Compressed audio (Bink RDFT/DCT encoded)
494 			free(soundBuffer);
495 			return;
496 		} else if (_header.audioInfo[track].compression == kCompressionDPCM) {
497 			// Compressed audio (Huffman DPCM encoded)
498 			audioTrack->queueCompressedBuffer(soundBuffer, chunkSize + 1, unpackedSize);
499 			free(soundBuffer);
500 		} else {
501 			// Uncompressed audio (PCM)
502 			audioTrack->queuePCM(soundBuffer, chunkSize);
503 		}
504 	} else {
505 		// Ignore possibly unused data
506 		_fileStream->skip(chunkSize);
507 	}
508 }
509 
getAudioTrack(int index)510 VideoDecoder::AudioTrack *SmackerDecoder::getAudioTrack(int index) {
511 	// Smacker audio track indexes are relative to the first audio track
512 	Track *track = getTrack(index + 1);
513 
514 	if (!track || track->getTrackType() != Track::kTrackTypeAudio)
515 		return 0;
516 
517 	return (AudioTrack *)track;
518 }
519 
SmackerVideoTrack(uint32 width,uint32 height,uint32 frameCount,const Common::Rational & frameRate,uint32 flags,uint32 signature)520 SmackerDecoder::SmackerVideoTrack::SmackerVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, uint32 flags, uint32 signature) {
521 	_surface = new Graphics::Surface();
522 	_surface->create(width, height * (flags ? 2 : 1), Graphics::PixelFormat::createFormatCLUT8());
523 	_frameCount = frameCount;
524 	_frameRate = frameRate;
525 	_flags = flags;
526 	_signature = signature;
527 	_curFrame = -1;
528 	_dirtyPalette = false;
529 	_MMapTree = _MClrTree = _FullTree = _TypeTree = 0;
530 	memset(_palette, 0, 3 * 256);
531 }
532 
~SmackerVideoTrack()533 SmackerDecoder::SmackerVideoTrack::~SmackerVideoTrack() {
534 	_surface->free();
535 	delete _surface;
536 
537 	delete _MMapTree;
538 	delete _MClrTree;
539 	delete _FullTree;
540 	delete _TypeTree;
541 }
542 
getWidth() const543 uint16 SmackerDecoder::SmackerVideoTrack::getWidth() const {
544 	return _surface->w;
545 }
546 
getHeight() const547 uint16 SmackerDecoder::SmackerVideoTrack::getHeight() const {
548 	return _surface->h;
549 }
550 
getPixelFormat() const551 Graphics::PixelFormat SmackerDecoder::SmackerVideoTrack::getPixelFormat() const {
552 	return _surface->format;
553 }
554 
readTrees(Common::BitStreamMemory8LSB & bs,uint32 mMapSize,uint32 mClrSize,uint32 fullSize,uint32 typeSize)555 void SmackerDecoder::SmackerVideoTrack::readTrees(Common::BitStreamMemory8LSB &bs, uint32 mMapSize, uint32 mClrSize, uint32 fullSize, uint32 typeSize) {
556 	_MMapTree = new BigHuffmanTree(bs, mMapSize);
557 	_MClrTree = new BigHuffmanTree(bs, mClrSize);
558 	_FullTree = new BigHuffmanTree(bs, fullSize);
559 	_TypeTree = new BigHuffmanTree(bs, typeSize);
560 }
561 
decodeFrame(Common::BitStreamMemory8LSB & bs)562 void SmackerDecoder::SmackerVideoTrack::decodeFrame(Common::BitStreamMemory8LSB &bs) {
563 	_MMapTree->reset();
564 	_MClrTree->reset();
565 	_FullTree->reset();
566 	_TypeTree->reset();
567 
568 	// Height needs to be doubled if we have flags (Y-interlaced or Y-doubled)
569 	uint doubleY = _flags ? 2 : 1;
570 
571 	uint bw = getWidth() / 4;
572 	uint bh = getHeight() / doubleY / 4;
573 	uint stride = getWidth();
574 	uint block = 0, blocks = bw*bh;
575 
576 	byte *out;
577 	uint type, run, j, mode;
578 	uint32 p1, p2, clr, map;
579 	byte hi, lo;
580 	uint i;
581 
582 	while (block < blocks) {
583 		type = _TypeTree->getCode(bs);
584 		run = getBlockRun((type >> 2) & 0x3f);
585 
586 		switch (type & 3) {
587 		case SMK_BLOCK_MONO:
588 			while (run-- && block < blocks) {
589 				clr = _MClrTree->getCode(bs);
590 				map = _MMapTree->getCode(bs);
591 				out = (byte *)_surface->getPixels() + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
592 				hi = clr >> 8;
593 				lo = clr & 0xff;
594 				for (i = 0; i < 4; i++) {
595 					for (j = 0; j < doubleY; j++) {
596 						out[0] = (map & 1) ? hi : lo;
597 						out[1] = (map & 2) ? hi : lo;
598 						out[2] = (map & 4) ? hi : lo;
599 						out[3] = (map & 8) ? hi : lo;
600 						out += stride;
601 					}
602 					map >>= 4;
603 				}
604 				++block;
605 			}
606 			break;
607 		case SMK_BLOCK_FULL:
608 			// Smacker v2 has one mode, Smacker v4 has three
609 			if (_signature == MKTAG('S','M','K','2')) {
610 				mode = 0;
611 			} else {
612 				// 00 - mode 0
613 				// 10 - mode 1
614 				// 01 - mode 2
615 				mode = 0;
616 				if (bs.getBit()) {
617 					mode = 1;
618 				} else if (bs.getBit()) {
619 					mode = 2;
620 				}
621 			}
622 
623 			while (run-- && block < blocks) {
624 				out = (byte *)_surface->getPixels() + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
625 				switch (mode) {
626 					case 0:
627 						for (i = 0; i < 4; ++i) {
628 							p1 = _FullTree->getCode(bs);
629 							p2 = _FullTree->getCode(bs);
630 							for (j = 0; j < doubleY; ++j) {
631 								out[2] = p1 & 0xff;
632 								out[3] = p1 >> 8;
633 								out[0] = p2 & 0xff;
634 								out[1] = p2 >> 8;
635 								out += stride;
636 							}
637 						}
638 						break;
639 					case 1:
640 						p1 = _FullTree->getCode(bs);
641 						out[0] = out[1] = p1 & 0xFF;
642 						out[2] = out[3] = p1 >> 8;
643 						out += stride;
644 						out[0] = out[1] = p1 & 0xFF;
645 						out[2] = out[3] = p1 >> 8;
646 						out += stride;
647 						p2 = _FullTree->getCode(bs);
648 						out[0] = out[1] = p2 & 0xFF;
649 						out[2] = out[3] = p2 >> 8;
650 						out += stride;
651 						out[0] = out[1] = p2 & 0xFF;
652 						out[2] = out[3] = p2 >> 8;
653 						out += stride;
654 						break;
655 					case 2:
656 						for (i = 0; i < 2; i++) {
657 							// We first get p2 and then p1
658 							// Check ffmpeg thread "[PATCH] Smacker video decoder bug fix"
659 							// http://article.gmane.org/gmane.comp.video.ffmpeg.devel/78768
660 							p2 = _FullTree->getCode(bs);
661 							p1 = _FullTree->getCode(bs);
662 							for (j = 0; j < doubleY; ++j) {
663 								out[0] = p1 & 0xff;
664 								out[1] = p1 >> 8;
665 								out[2] = p2 & 0xff;
666 								out[3] = p2 >> 8;
667 								out += stride;
668 							}
669 							for (j = 0; j < doubleY; ++j) {
670 								out[0] = p1 & 0xff;
671 								out[1] = p1 >> 8;
672 								out[2] = p2 & 0xff;
673 								out[3] = p2 >> 8;
674 								out += stride;
675 							}
676 						}
677 						break;
678 				}
679 				++block;
680 			}
681 			break;
682 		case SMK_BLOCK_SKIP:
683 			while (run-- && block < blocks)
684 				block++;
685 			break;
686 		case SMK_BLOCK_FILL:
687 			uint32 col;
688 			mode = type >> 8;
689 			while (run-- && block < blocks) {
690 				out = (byte *)_surface->getPixels() + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
691 				col = mode * 0x01010101;
692 				for (i = 0; i < 4 * doubleY; ++i) {
693 					out[0] = out[1] = out[2] = out[3] = col;
694 					out += stride;
695 				}
696 				++block;
697 			}
698 			break;
699 		}
700 	}
701 }
702 
unpackPalette(Common::SeekableReadStream * stream)703 void SmackerDecoder::SmackerVideoTrack::unpackPalette(Common::SeekableReadStream *stream) {
704 	uint startPos = stream->pos();
705 	uint32 len = 4 * stream->readByte();
706 
707 	byte *chunk = (byte *)malloc(len);
708 	stream->read(chunk, len);
709 	byte *p = chunk;
710 
711 	byte oldPalette[3 * 256];
712 	memcpy(oldPalette, _palette, 3 * 256);
713 
714 	byte *pal = _palette;
715 
716 	int sz = 0;
717 	byte b0;
718 	while (sz < 256) {
719 		b0 = *p++;
720 		if (b0 & 0x80) {               // if top bit is 1 (0x80 = 10000000)
721 			sz += (b0 & 0x7f) + 1;     // get lower 7 bits + 1 (0x7f = 01111111)
722 			pal += 3 * ((b0 & 0x7f) + 1);
723 		} else if (b0 & 0x40) {        // if top 2 bits are 01 (0x40 = 01000000)
724 			byte c = (b0 & 0x3f) + 1;  // get lower 6 bits + 1 (0x3f = 00111111)
725 			uint s = 3 * *p++;
726 			sz += c;
727 
728 			while (c--) {
729 				*pal++ = oldPalette[s + 0];
730 				*pal++ = oldPalette[s + 1];
731 				*pal++ = oldPalette[s + 2];
732 				s += 3;
733 			}
734 		} else {                       // top 2 bits are 00
735 			sz++;
736 			// get the lower 6 bits for each component (0x3f = 00111111)
737 			byte r = b0 & 0x3f;
738 			byte g = (*p++) & 0x3f;
739 			byte b = (*p++) & 0x3f;
740 
741 			// upscale to full 8-bit color values. The Multimedia Wiki suggests
742 			// a lookup table for this, but this should produce the same result.
743 			*pal++ = (r * 4 + r / 16);
744 			*pal++ = (g * 4 + g / 16);
745 			*pal++ = (b * 4 + b / 16);
746 		}
747 	}
748 
749 	stream->seek(startPos + len);
750 	free(chunk);
751 
752 	_dirtyPalette = true;
753 }
754 
SmackerAudioTrack(const AudioInfo & audioInfo,Audio::Mixer::SoundType soundType)755 SmackerDecoder::SmackerAudioTrack::SmackerAudioTrack(const AudioInfo &audioInfo, Audio::Mixer::SoundType soundType) :
756 		AudioTrack(soundType),
757 		_audioInfo(audioInfo) {
758 	_audioStream = Audio::makeQueuingAudioStream(_audioInfo.sampleRate, _audioInfo.isStereo);
759 }
760 
~SmackerAudioTrack()761 SmackerDecoder::SmackerAudioTrack::~SmackerAudioTrack() {
762 	delete _audioStream;
763 }
764 
rewind()765 bool SmackerDecoder::SmackerAudioTrack::rewind() {
766 	delete _audioStream;
767 	_audioStream = Audio::makeQueuingAudioStream(_audioInfo.sampleRate, _audioInfo.isStereo);
768 	return true;
769 }
770 
getAudioStream() const771 Audio::AudioStream *SmackerDecoder::SmackerAudioTrack::getAudioStream() const {
772 	return _audioStream;
773 }
774 
queueCompressedBuffer(byte * buffer,uint32 bufferSize,uint32 unpackedSize)775 void SmackerDecoder::SmackerAudioTrack::queueCompressedBuffer(byte *buffer, uint32 bufferSize, uint32 unpackedSize) {
776 	Common::BitStreamMemory8LSB audioBS(new Common::BitStreamMemoryStream(buffer, bufferSize), DisposeAfterUse::YES);
777 	bool dataPresent = audioBS.getBit();
778 
779 	if (!dataPresent)
780 		return;
781 
782 	bool isStereo = audioBS.getBit();
783 	assert(isStereo == _audioInfo.isStereo);
784 	bool is16Bits = audioBS.getBit();
785 	assert(is16Bits == _audioInfo.is16Bits);
786 
787 	int numBytes = 1 * (isStereo ? 2 : 1) * (is16Bits ? 2 : 1);
788 
789 	byte *unpackedBuffer = (byte *)malloc(unpackedSize);
790 	byte *curPointer = unpackedBuffer;
791 	uint32 curPos = 0;
792 
793 	SmallHuffmanTree *audioTrees[4];
794 	for (int k = 0; k < numBytes; k++)
795 		audioTrees[k] = new SmallHuffmanTree(audioBS);
796 
797 	// Base values, stored as big endian
798 
799 	int32 bases[2];
800 
801 	if (isStereo) {
802 		if (is16Bits) {
803 			bases[1] = SWAP_BYTES_16(audioBS.getBits(16));
804 		} else {
805 			bases[1] = audioBS.getBits(8);
806 		}
807 	}
808 
809 	if (is16Bits) {
810 		bases[0] = SWAP_BYTES_16(audioBS.getBits(16));
811 	} else {
812 		bases[0] = audioBS.getBits(8);
813 	}
814 
815 	// The bases are the first samples, too
816 	for (int i = 0; i < (isStereo ? 2 : 1); i++, curPointer += (is16Bits ? 2 : 1), curPos += (is16Bits ? 2 : 1)) {
817 		if (is16Bits)
818 			WRITE_BE_UINT16(curPointer, bases[i]);
819 		else
820 			*curPointer = (bases[i] & 0xFF) ^ 0x80;
821 	}
822 
823 	// Next follow the deltas, which are added to the corresponding base values and
824 	// are stored as little endian
825 	// We store the unpacked bytes in big endian format
826 
827 	while (curPos < unpackedSize) {
828 		// If the sample is stereo, the data is stored for the left and right channel, respectively
829 		// (the exact opposite to the base values)
830 		if (!is16Bits) {
831 			for (int k = 0; k < (isStereo ? 2 : 1); k++) {
832 				int8 delta = (int8) ((int16) audioTrees[k]->getCode(audioBS));
833 				bases[k] = (bases[k] + delta) & 0xFF;
834 				*curPointer++ = bases[k] ^ 0x80;
835 				curPos++;
836 			}
837 		} else {
838 			for (int k = 0; k < (isStereo ? 2 : 1); k++) {
839 				byte lo = audioTrees[k * 2]->getCode(audioBS);
840 				byte hi = audioTrees[k * 2 + 1]->getCode(audioBS);
841 				bases[k] += (int16) (lo | (hi << 8));
842 
843 				WRITE_BE_UINT16(curPointer, bases[k]);
844 				curPointer += 2;
845 				curPos += 2;
846 			}
847 		}
848 
849 	}
850 
851 	for (int k = 0; k < numBytes; k++)
852 		delete audioTrees[k];
853 
854 	queuePCM(unpackedBuffer, unpackedSize);
855 }
856 
queuePCM(byte * buffer,uint32 bufferSize)857 void SmackerDecoder::SmackerAudioTrack::queuePCM(byte *buffer, uint32 bufferSize) {
858 	byte flags = 0;
859 	if (_audioInfo.is16Bits)
860 		flags |= Audio::FLAG_16BITS;
861 	if (_audioInfo.isStereo)
862 		flags |= Audio::FLAG_STEREO;
863 
864 	_audioStream->queueBuffer(buffer, bufferSize, DisposeAfterUse::YES, flags);
865 }
866 
createVideoTrack(uint32 width,uint32 height,uint32 frameCount,const Common::Rational & frameRate,uint32 flags,uint32 signature) const867 SmackerDecoder::SmackerVideoTrack *SmackerDecoder::createVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, uint32 flags, uint32 signature) const {
868 	return new SmackerVideoTrack(width, height, frameCount, frameRate, flags, signature);
869 }
870 
871 } // End of namespace Video
872