mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
570 lines
25 KiB
C++
570 lines
25 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "common/endian.h"
|
|
#include "common/util.h"
|
|
#include "common/textconsole.h"
|
|
|
|
#include "engines/grim/movie/codecs/codec48.h"
|
|
|
|
namespace Grim {
|
|
|
|
Codec48Decoder::Codec48Decoder() {
|
|
_frameSize = 640 * 480; // Yes, this is correct. Looks like the buffers are always this size
|
|
|
|
_curBuf = 0;
|
|
_deltaBuf[0] = new byte[_frameSize * 2];
|
|
_deltaBuf[1] = _deltaBuf[0] + _frameSize;
|
|
|
|
_offsetTable = new int16[255];
|
|
_tableLastPitch = -1;
|
|
_tableLastIndex = -1;
|
|
|
|
_interTable = nullptr;
|
|
}
|
|
|
|
void Codec48Decoder::init(int width, int height) {
|
|
if (_width == width && _height == height)
|
|
return;
|
|
deinit();
|
|
_width = width;
|
|
_height = height;
|
|
|
|
_blockX = (_width + 7) / 8;
|
|
_blockY = (_height + 7) / 8;
|
|
_pitch = _blockX * 8;
|
|
|
|
// don't support when this is not equal yet
|
|
assert(_width == _pitch);
|
|
}
|
|
|
|
void Codec48Decoder::deinit() {
|
|
}
|
|
|
|
Codec48Decoder::~Codec48Decoder() {
|
|
delete[] _deltaBuf[0];
|
|
delete[] _offsetTable;
|
|
delete[] _interTable;
|
|
}
|
|
|
|
bool Codec48Decoder::decode(byte *dst, const byte *src) {
|
|
// The header is identical to codec 37, except the flags field is somewhat different
|
|
|
|
const byte *gfxData = src + 0x10;
|
|
|
|
makeTable(_pitch, src[1]);
|
|
|
|
int16 seqNb = READ_LE_UINT16(src + 2);
|
|
|
|
if (seqNb == 0)
|
|
memset(_deltaBuf[0], 0, _frameSize * 2);
|
|
|
|
if (src[12] & (1 << 3)) {
|
|
// Interpolation table present
|
|
if (!_interTable)
|
|
_interTable = new byte[65536];
|
|
|
|
byte *ptr = _interTable;
|
|
|
|
for (int i = 0; i < 256; i++) {
|
|
byte *ptr1 = ptr + i;
|
|
byte *ptr2 = ptr + i;
|
|
|
|
for (int j = 256 - i; j > 0; j--) {
|
|
byte pixel = *gfxData++;
|
|
*ptr2 = pixel;
|
|
*ptr1++ = pixel;
|
|
ptr2 += 256;
|
|
}
|
|
|
|
ptr += 256;
|
|
}
|
|
}
|
|
|
|
switch (src[0]) {
|
|
case 0:
|
|
// Raw frame
|
|
memcpy(_deltaBuf[_curBuf], gfxData, READ_LE_UINT32(src + 4));
|
|
break;
|
|
case 2:
|
|
// Blast object
|
|
bompDecodeLine(_deltaBuf[_curBuf], gfxData, _width * _height);
|
|
break;
|
|
case 3:
|
|
// 8x8 block encoding
|
|
if (!(seqNb && seqNb != _prevSeqNb + 1)) {
|
|
if (seqNb & 1 || !(src[12] & 1) || src[12] & 0x10)
|
|
_curBuf ^= 1;
|
|
|
|
decode3(_deltaBuf[_curBuf], gfxData, _deltaBuf[_curBuf ^ 1] - _deltaBuf[_curBuf]);
|
|
}
|
|
break;
|
|
case 5:
|
|
// Some other encoding, but it's unused. (Good)
|
|
warning("SmushDecoder::decode() codec 48 frame type 5 encountered! Please report!");
|
|
break;
|
|
default:
|
|
warning("SmushDecoder::decode() Unknown codec 48 frame type %d", src[0]);
|
|
break;
|
|
}
|
|
|
|
_prevSeqNb = seqNb;
|
|
memcpy(dst, _deltaBuf[_curBuf], _pitch * _height);
|
|
return true;
|
|
}
|
|
|
|
void Codec48Decoder::bompDecodeLine(byte *dst, const byte *src, int len) {
|
|
while (len > 0) {
|
|
byte code = *src++;
|
|
byte num = (code >> 1) + 1;
|
|
|
|
if (num > len)
|
|
num = len;
|
|
|
|
len -= num;
|
|
|
|
if (code & 1) {
|
|
byte color = *src++;
|
|
memset(dst, color, num);
|
|
} else {
|
|
memcpy(dst, src, num);
|
|
src += num;
|
|
}
|
|
|
|
dst += num;
|
|
}
|
|
}
|
|
|
|
void Codec48Decoder::makeTable(int pitch, int index) {
|
|
// codec48's table is codec47's table appended by the first
|
|
// part of codec37's table
|
|
|
|
// This is essentially Codec37Decoder::makeTable() with a different table
|
|
|
|
static const int8 table[] = {
|
|
0, 0, -1, -43, 6, -43, -9, -42, 13, -41,
|
|
-16, -40, 19, -39, -23, -36, 26, -34, -2, -33,
|
|
4, -33, -29, -32, -9, -32, 11, -31, -16, -29,
|
|
32, -29, 18, -28, -34, -26, -22, -25, -1, -25,
|
|
3, -25, -7, -24, 8, -24, 24, -23, 36, -23,
|
|
-12, -22, 13, -21, -38, -20, 0, -20, -27, -19,
|
|
-4, -19, 4, -19, -17, -18, -8, -17, 8, -17,
|
|
18, -17, 28, -17, 39, -17, -12, -15, 12, -15,
|
|
-21, -14, -1, -14, 1, -14, -41, -13, -5, -13,
|
|
5, -13, 21, -13, -31, -12, -15, -11, -8, -11,
|
|
8, -11, 15, -11, -2, -10, 1, -10, 31, -10,
|
|
-23, -9, -11, -9, -5, -9, 4, -9, 11, -9,
|
|
42, -9, 6, -8, 24, -8, -18, -7, -7, -7,
|
|
-3, -7, -1, -7, 2, -7, 18, -7, -43, -6,
|
|
-13, -6, -4, -6, 4, -6, 8, -6, -33, -5,
|
|
-9, -5, -2, -5, 0, -5, 2, -5, 5, -5,
|
|
13, -5, -25, -4, -6, -4, -3, -4, 3, -4,
|
|
9, -4, -19, -3, -7, -3, -4, -3, -2, -3,
|
|
-1, -3, 0, -3, 1, -3, 2, -3, 4, -3,
|
|
6, -3, 33, -3, -14, -2, -10, -2, -5, -2,
|
|
-3, -2, -2, -2, -1, -2, 0, -2, 1, -2,
|
|
2, -2, 3, -2, 5, -2, 7, -2, 14, -2,
|
|
19, -2, 25, -2, 43, -2, -7, -1, -3, -1,
|
|
-2, -1, -1, -1, 0, -1, 1, -1, 2, -1,
|
|
3, -1, 10, -1, -5, 0, -3, 0, -2, 0,
|
|
-1, 0, 1, 0, 2, 0, 3, 0, 5, 0,
|
|
7, 0, -10, 1, -7, 1, -3, 1, -2, 1,
|
|
-1, 1, 0, 1, 1, 1, 2, 1, 3, 1,
|
|
-43, 2, -25, 2, -19, 2, -14, 2, -5, 2,
|
|
-3, 2, -2, 2, -1, 2, 0, 2, 1, 2,
|
|
2, 2, 3, 2, 5, 2, 7, 2, 10, 2,
|
|
14, 2, -33, 3, -6, 3, -4, 3, -2, 3,
|
|
-1, 3, 0, 3, 1, 3, 2, 3, 4, 3,
|
|
19, 3, -9, 4, -3, 4, 3, 4, 7, 4,
|
|
25, 4, -13, 5, -5, 5, -2, 5, 0, 5,
|
|
2, 5, 5, 5, 9, 5, 33, 5, -8, 6,
|
|
-4, 6, 4, 6, 13, 6, 43, 6, -18, 7,
|
|
-2, 7, 0, 7, 2, 7, 7, 7, 18, 7,
|
|
-24, 8, -6, 8, -42, 9, -11, 9, -4, 9,
|
|
5, 9, 11, 9, 23, 9, -31, 10, -1, 10,
|
|
2, 10, -15, 11, -8, 11, 8, 11, 15, 11,
|
|
31, 12, -21, 13, -5, 13, 5, 13, 41, 13,
|
|
-1, 14, 1, 14, 21, 14, -12, 15, 12, 15,
|
|
-39, 17, -28, 17, -18, 17, -8, 17, 8, 17,
|
|
17, 18, -4, 19, 0, 19, 4, 19, 27, 19,
|
|
38, 20, -13, 21, 12, 22, -36, 23, -24, 23,
|
|
-8, 24, 7, 24, -3, 25, 1, 25, 22, 25,
|
|
34, 26, -18, 28, -32, 29, 16, 29, -11, 31,
|
|
9, 32, 29, 32, -4, 33, 2, 33, -26, 34,
|
|
23, 36, -19, 39, 16, 40, -13, 41, 9, 42,
|
|
-6, 43, 1, 43, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 1, 0, 2, 0, 3, 0, 5, 0,
|
|
8, 0, 13, 0, 21, 0, -1, 0, -2, 0,
|
|
-3, 0, -5, 0, -8, 0, -13, 0, -17, 0,
|
|
-21, 0, 0, 1, 1, 1, 2, 1, 3, 1,
|
|
5, 1, 8, 1, 13, 1, 21, 1, -1, 1,
|
|
-2, 1, -3, 1, -5, 1, -8, 1, -13, 1,
|
|
-17, 1, -21, 1, 0, 2, 1, 2, 2, 2,
|
|
3, 2, 5, 2, 8, 2, 13, 2, 21, 2,
|
|
-1, 2, -2, 2, -3, 2, -5, 2, -8, 2,
|
|
-13, 2, -17, 2, -21, 2, 0, 3, 1, 3,
|
|
2, 3, 3, 3, 5, 3, 8, 3, 13, 3,
|
|
21, 3, -1, 3, -2, 3, -3, 3, -5, 3,
|
|
-8, 3, -13, 3, -17, 3, -21, 3, 0, 5,
|
|
1, 5, 2, 5, 3, 5, 5, 5, 8, 5,
|
|
13, 5, 21, 5, -1, 5, -2, 5, -3, 5,
|
|
-5, 5, -8, 5, -13, 5, -17, 5, -21, 5,
|
|
0, 8, 1, 8, 2, 8, 3, 8, 5, 8,
|
|
8, 8, 13, 8, 21, 8, -1, 8, -2, 8,
|
|
-3, 8, -5, 8, -8, 8, -13, 8, -17, 8,
|
|
-21, 8, 0, 13, 1, 13, 2, 13, 3, 13,
|
|
5, 13, 8, 13, 13, 13, 21, 13, -1, 13,
|
|
-2, 13, -3, 13, -5, 13, -8, 13, -13, 13,
|
|
-17, 13, -21, 13, 0, 21, 1, 21, 2, 21,
|
|
3, 21, 5, 21, 8, 21, 13, 21, 21, 21,
|
|
-1, 21, -2, 21, -3, 21, -5, 21, -8, 21,
|
|
-13, 21, -17, 21, -21, 21, 0, -1, 1, -1,
|
|
2, -1, 3, -1, 5, -1, 8, -1, 13, -1,
|
|
21, -1, -1, -1, -2, -1, -3, -1, -5, -1,
|
|
-8, -1, -13, -1, -17, -1, -21, -1, 0, -2,
|
|
1, -2, 2, -2, 3, -2, 5, -2, 8, -2,
|
|
13, -2, 21, -2, -1, -2, -2, -2, -3, -2,
|
|
-5, -2, -8, -2, -13, -2, -17, -2, -21, -2,
|
|
0, -3, 1, -3, 2, -3, 3, -3, 5, -3,
|
|
8, -3, 13, -3, 21, -3, -1, -3, -2, -3,
|
|
-3, -3, -5, -3, -8, -3, -13, -3, -17, -3,
|
|
-21, -3, 0, -5, 1, -5, 2, -5, 3, -5,
|
|
5, -5, 8, -5, 13, -5, 21, -5, -1, -5,
|
|
-2, -5, -3, -5, -5, -5, -8, -5, -13, -5,
|
|
-17, -5, -21, -5, 0, -8, 1, -8, 2, -8,
|
|
3, -8, 5, -8, 8, -8, 13, -8, 21, -8,
|
|
-1, -8, -2, -8, -3, -8, -5, -8, -8, -8,
|
|
-13, -8, -17, -8, -21, -8, 0, -13, 1, -13,
|
|
2, -13, 3, -13, 5, -13, 8, -13, 13, -13,
|
|
21, -13, -1, -13, -2, -13, -3, -13, -5, -13,
|
|
-8, -13, -13, -13, -17, -13, -21, -13, 0, -17,
|
|
1, -17, 2, -17, 3, -17, 5, -17, 8, -17,
|
|
13, -17, 21, -17, -1, -17, -2, -17, -3, -17,
|
|
-5, -17, -8, -17, -13, -17, -17, -17, -21, -17,
|
|
0, -21, 1, -21, 2, -21, 3, -21, 5, -21,
|
|
8, -21, 13, -21, 21, -21, -1, -21, -2, -21,
|
|
-3, -21, -5, -21, -8, -21, -13, -21, -17, -21
|
|
};
|
|
|
|
if (_tableLastPitch == pitch && _tableLastIndex == index)
|
|
return;
|
|
|
|
_tableLastPitch = pitch;
|
|
_tableLastIndex = index;
|
|
index *= 255;
|
|
assert(index + 254 < (int32)(sizeof(table) / 2));
|
|
|
|
for (int32 i = 0; i < 255; i++) {
|
|
int32 j = (i + index) * 2;
|
|
_offsetTable[i] = table[j + 1] * pitch + table[j];
|
|
}
|
|
}
|
|
|
|
void Codec48Decoder::decode3(byte *dst, const byte *src, int bufOffset) {
|
|
for (int i = 0; i < _blockY; i++) {
|
|
for (int j = 0; j < _blockX; j++) {
|
|
byte opcode = *src++;
|
|
|
|
switch (opcode) {
|
|
case 0xFF: {
|
|
// Interpolate a 4x4 block based on 1 pixel, then scale to 8x8
|
|
byte scaleBuffer[16];
|
|
scaleBuffer[15] = *src++;
|
|
scaleBuffer[7] = _interTable[(dst[-_pitch + 7] << 8) | scaleBuffer[15]];
|
|
scaleBuffer[3] = _interTable[(dst[-_pitch + 7] << 8) | scaleBuffer[7]];
|
|
scaleBuffer[11] = _interTable[(scaleBuffer[15] << 8) | scaleBuffer[7]];
|
|
|
|
scaleBuffer[1] = _interTable[(dst[-1] << 8) | scaleBuffer[3]];
|
|
scaleBuffer[0] = _interTable[(dst[-1] << 8) | scaleBuffer[1]];
|
|
scaleBuffer[2] = _interTable[(scaleBuffer[3] << 8) | scaleBuffer[1]];
|
|
|
|
scaleBuffer[5] = _interTable[(dst[_pitch * 2 - 1] << 8) | scaleBuffer[7]];
|
|
scaleBuffer[4] = _interTable[(dst[_pitch * 2 - 1] << 8) | scaleBuffer[5]];
|
|
scaleBuffer[6] = _interTable[(scaleBuffer[7] << 8) | scaleBuffer[5]];
|
|
|
|
scaleBuffer[9] = _interTable[(dst[_pitch * 3 - 1] << 8) | scaleBuffer[11]];
|
|
scaleBuffer[8] = _interTable[(dst[_pitch * 3 - 1] << 8) | scaleBuffer[9]];
|
|
scaleBuffer[10] = _interTable[(scaleBuffer[11] << 8) | scaleBuffer[9]];
|
|
|
|
scaleBuffer[13] = _interTable[(dst[_pitch * 4 - 1] << 8) | scaleBuffer[15]];
|
|
scaleBuffer[12] = _interTable[(dst[_pitch * 4 - 1] << 8) | scaleBuffer[13]];
|
|
scaleBuffer[14] = _interTable[(scaleBuffer[15] << 8) | scaleBuffer[13]];
|
|
|
|
scaleBlock(dst, scaleBuffer);
|
|
break;
|
|
}
|
|
case 0xFE:
|
|
// Copy a block using an absolute offset
|
|
copyBlock(dst, bufOffset, (int16)READ_LE_UINT16(src));
|
|
src += 2;
|
|
break;
|
|
case 0xFD: {
|
|
// Interpolate a 4x4 block based on 4 pixels, then scale to 8x8
|
|
byte scaleBuffer[16];
|
|
scaleBuffer[5] = src[0];
|
|
scaleBuffer[7] = src[1];
|
|
scaleBuffer[13] = src[2];
|
|
scaleBuffer[15] = src[3];
|
|
|
|
scaleBuffer[1] = _interTable[(dst[-_pitch + 3] << 8) | scaleBuffer[5]];
|
|
scaleBuffer[3] = _interTable[(dst[-_pitch + 7] << 8) | scaleBuffer[7]];
|
|
scaleBuffer[11] = _interTable[(scaleBuffer[15] << 8) | scaleBuffer[7]];
|
|
scaleBuffer[9] = _interTable[(scaleBuffer[13] << 8) | scaleBuffer[5]];
|
|
|
|
scaleBuffer[0] = _interTable[(dst[-1] << 8) | scaleBuffer[1]];
|
|
scaleBuffer[2] = _interTable[(scaleBuffer[3] << 8) | scaleBuffer[1]];
|
|
scaleBuffer[4] = _interTable[(dst[_pitch * 2 - 1] << 8) | scaleBuffer[5]];
|
|
scaleBuffer[6] = _interTable[(scaleBuffer[7] << 8) | scaleBuffer[5]];
|
|
|
|
scaleBuffer[8] = _interTable[(dst[_pitch * 3 - 1] << 8) | scaleBuffer[9]];
|
|
scaleBuffer[10] = _interTable[(scaleBuffer[11] << 8) | scaleBuffer[9]];
|
|
scaleBuffer[12] = _interTable[(dst[_pitch * 4 - 1] << 8) | scaleBuffer[13]];
|
|
scaleBuffer[14] = _interTable[(scaleBuffer[15] << 8) | scaleBuffer[13]];
|
|
|
|
scaleBlock(dst, scaleBuffer);
|
|
|
|
src += 4;
|
|
break;
|
|
}
|
|
case 0xFC:
|
|
// Copy 4 4x4 blocks using the offset table
|
|
*((uint32 *)dst) = *((uint32 *)(dst + bufOffset + _offsetTable[src[0]]));
|
|
*((uint32 *)(dst + _pitch)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[0]] + _pitch));
|
|
*((uint32 *)(dst + _pitch * 2)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[0]] + _pitch * 2));
|
|
*((uint32 *)(dst + _pitch * 3)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[0]] + _pitch * 3));
|
|
|
|
*((uint32 *)(dst + 4)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[1]] + 4));
|
|
*((uint32 *)(dst + _pitch + 4)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[1]] + _pitch + 4));
|
|
*((uint32 *)(dst + _pitch * 2 + 4)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[1]] + _pitch * 2 + 4));
|
|
*((uint32 *)(dst + _pitch * 3 + 4)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[1]] + _pitch * 3 + 4));
|
|
|
|
*((uint32 *)(dst + _pitch * 4)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[2]] + _pitch * 4));
|
|
*((uint32 *)(dst + _pitch * 5)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[2]] + _pitch * 5));
|
|
*((uint32 *)(dst + _pitch * 6)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[2]] + _pitch * 6));
|
|
*((uint32 *)(dst + _pitch * 7)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[2]] + _pitch * 7));
|
|
|
|
*((uint32 *)(dst + _pitch * 4 + 4)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[3]] + _pitch * 4 + 4));
|
|
*((uint32 *)(dst + _pitch * 5 + 4)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[3]] + _pitch * 5 + 4));
|
|
*((uint32 *)(dst + _pitch * 6 + 4)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[3]] + _pitch * 6 + 4));
|
|
*((uint32 *)(dst + _pitch * 7 + 4)) = *((uint32 *)(dst + bufOffset + _offsetTable[src[3]] + _pitch * 7 + 4));
|
|
|
|
src += 4;
|
|
break;
|
|
case 0xFB:
|
|
// Copy 4 4x4 blocks using absolute offsets
|
|
*((uint32 *)dst) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src)));
|
|
*((uint32 *)(dst + _pitch)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src) + _pitch));
|
|
*((uint32 *)(dst + _pitch * 2)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src) + _pitch * 2));
|
|
*((uint32 *)(dst + _pitch * 3)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src) + _pitch * 3));
|
|
|
|
*((uint32 *)(dst + 4)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 2) + 4));
|
|
*((uint32 *)(dst + _pitch + 4)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 2) + _pitch + 4));
|
|
*((uint32 *)(dst + _pitch * 2 + 4)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 2) + _pitch * 2 + 4));
|
|
*((uint32 *)(dst + _pitch * 3 + 4)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 2) + _pitch * 3 + 4));
|
|
|
|
*((uint32 *)(dst + _pitch * 4)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 4) + _pitch * 4));
|
|
*((uint32 *)(dst + _pitch * 5)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 4) + _pitch * 5));
|
|
*((uint32 *)(dst + _pitch * 6)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 4) + _pitch * 6));
|
|
*((uint32 *)(dst + _pitch * 7)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 4) + _pitch * 7));
|
|
|
|
*((uint32 *)(dst + _pitch * 4 + 4)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 6) + _pitch * 4 + 4));
|
|
*((uint32 *)(dst + _pitch * 5 + 4)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 6) + _pitch * 5 + 4));
|
|
*((uint32 *)(dst + _pitch * 6 + 4)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 6) + _pitch * 6 + 4));
|
|
*((uint32 *)(dst + _pitch * 7 + 4)) = *((uint32 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 6) + _pitch * 7 + 4));
|
|
src += 8;
|
|
break;
|
|
case 0xFA:
|
|
// Scale a 4x4 block to an 8x8 block
|
|
scaleBlock(dst, src);
|
|
src += 16;
|
|
break;
|
|
case 0xF9:
|
|
// Copy 16 2x2 blocks using the offset table
|
|
*((uint16 *)dst) = *((uint16 *)(dst + bufOffset + _offsetTable[src[0]]));
|
|
*((uint16 *)(dst + _pitch)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[0]] + _pitch));
|
|
|
|
*((uint16 *)(dst + 2)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[1]] + 2));
|
|
*((uint16 *)(dst + _pitch + 2)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[1]] + _pitch + 2));
|
|
|
|
*((uint16 *)(dst + 4)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[2]] + 4));
|
|
*((uint16 *)(dst + _pitch + 4)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[2]] + _pitch + 4));
|
|
|
|
*((uint16 *)(dst + 6)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[3]] + 6));
|
|
*((uint16 *)(dst + _pitch + 6)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[3]] + _pitch + 6));
|
|
|
|
*((uint16 *)(dst + _pitch * 2)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[4]] + _pitch * 2));
|
|
*((uint16 *)(dst + _pitch * 3)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[4]] + _pitch * 3));
|
|
|
|
*((uint16 *)(dst + _pitch * 2 + 2)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[5]] + _pitch * 2 + 2));
|
|
*((uint16 *)(dst + _pitch * 3 + 2)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[5]] + _pitch * 3 + 2));
|
|
|
|
*((uint16 *)(dst + _pitch * 2 + 4)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[6]] + _pitch * 2 + 4));
|
|
*((uint16 *)(dst + _pitch * 3 + 4)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[6]] + _pitch * 3 + 4));
|
|
|
|
*((uint16 *)(dst + _pitch * 2 + 6)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[7]] + _pitch * 2 + 6));
|
|
*((uint16 *)(dst + _pitch * 3 + 6)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[7]] + _pitch * 3 + 6));
|
|
|
|
*((uint16 *)(dst + _pitch * 4)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[8]] + _pitch * 4));
|
|
*((uint16 *)(dst + _pitch * 5)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[8]] + _pitch * 5));
|
|
|
|
*((uint16 *)(dst + _pitch * 4 + 2)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[9]] + _pitch * 4 + 2));
|
|
*((uint16 *)(dst + _pitch * 5 + 2)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[9]] + _pitch * 5 + 2));
|
|
|
|
*((uint16 *)(dst + _pitch * 4 + 4)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[10]] + _pitch * 4 + 4));
|
|
*((uint16 *)(dst + _pitch * 5 + 4)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[10]] + _pitch * 5 + 4));
|
|
|
|
*((uint16 *)(dst + _pitch * 4 + 6)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[11]] + _pitch * 4 + 6));
|
|
*((uint16 *)(dst + _pitch * 5 + 6)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[11]] + _pitch * 5 + 6));
|
|
|
|
*((uint16 *)(dst + _pitch * 6)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[12]] + _pitch * 6));
|
|
*((uint16 *)(dst + _pitch * 7)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[12]] + _pitch * 7));
|
|
|
|
*((uint16 *)(dst + _pitch * 6 + 2)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[13]] + _pitch * 6 + 2));
|
|
*((uint16 *)(dst + _pitch * 7 + 2)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[13]] + _pitch * 7 + 2));
|
|
|
|
*((uint16 *)(dst + _pitch * 6 + 4)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[14]] + _pitch * 6 + 4));
|
|
*((uint16 *)(dst + _pitch * 7 + 4)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[14]] + _pitch * 7 + 4));
|
|
|
|
*((uint16 *)(dst + _pitch * 6 + 6)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[15]] + _pitch * 6 + 6));
|
|
*((uint16 *)(dst + _pitch * 7 + 6)) = *((uint16 *)(dst + bufOffset + _offsetTable[src[15]] + _pitch * 7 + 6));
|
|
src += 16;
|
|
break;
|
|
case 0xF8:
|
|
// Copy 16 2x2 blocks using absolute offsets
|
|
*((uint16 *)dst) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src)));
|
|
*((uint16 *)(dst + _pitch)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src) + _pitch));
|
|
|
|
*((uint16 *)(dst + 2)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 2) + 2));
|
|
*((uint16 *)(dst + _pitch + 2)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 2) + _pitch + 2));
|
|
|
|
*((uint16 *)(dst + 4)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 4) + 4));
|
|
*((uint16 *)(dst + _pitch + 4)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 4) + _pitch + 4));
|
|
|
|
*((uint16 *)(dst + 6)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 6) + 6));
|
|
*((uint16 *)(dst + _pitch + 6)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 6) + _pitch + 6));
|
|
|
|
*((uint16 *)(dst + _pitch * 2)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 8) + _pitch * 2));
|
|
*((uint16 *)(dst + _pitch * 3)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 8) + _pitch * 3));
|
|
|
|
*((uint16 *)(dst + _pitch * 2 + 2)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 10) + _pitch * 2 + 2));
|
|
*((uint16 *)(dst + _pitch * 3 + 2)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 10) + _pitch * 3 + 2));
|
|
|
|
*((uint16 *)(dst + _pitch * 2 + 4)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 12) + _pitch * 2 + 4));
|
|
*((uint16 *)(dst + _pitch * 3 + 4)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 12) + _pitch * 3 + 4));
|
|
|
|
*((uint16 *)(dst + _pitch * 2 + 6)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 14) + _pitch * 2 + 6));
|
|
*((uint16 *)(dst + _pitch * 3 + 6)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 14) + _pitch * 3 + 6));
|
|
|
|
*((uint16 *)(dst + _pitch * 4)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 16) + _pitch * 4));
|
|
*((uint16 *)(dst + _pitch * 5)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 16) + _pitch * 5));
|
|
|
|
*((uint16 *)(dst + _pitch * 4 + 2)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 18) + _pitch * 4 + 2));
|
|
*((uint16 *)(dst + _pitch * 5 + 2)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 18) + _pitch * 5 + 2));
|
|
|
|
*((uint16 *)(dst + _pitch * 4 + 4)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 20) + _pitch * 4 + 4));
|
|
*((uint16 *)(dst + _pitch * 5 + 4)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 20) + _pitch * 5 + 4));
|
|
|
|
*((uint16 *)(dst + _pitch * 4 + 6)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 22) + _pitch * 4 + 6));
|
|
*((uint16 *)(dst + _pitch * 5 + 6)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 22) + _pitch * 5 + 6));
|
|
|
|
*((uint16 *)(dst + _pitch * 6)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 24) + _pitch * 6));
|
|
*((uint16 *)(dst + _pitch * 7)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 24) + _pitch * 7));
|
|
|
|
*((uint16 *)(dst + _pitch * 6 + 2)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 26) + _pitch * 6 + 2));
|
|
*((uint16 *)(dst + _pitch * 7 + 2)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 26) + _pitch * 7 + 2));
|
|
|
|
*((uint16 *)(dst + _pitch * 6 + 4)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 28) + _pitch * 6 + 4));
|
|
*((uint16 *)(dst + _pitch * 7 + 4)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 28) + _pitch * 7 + 4));
|
|
|
|
*((uint16 *)(dst + _pitch * 6 + 6)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 30) + _pitch * 6 + 6));
|
|
*((uint16 *)(dst + _pitch * 7 + 6)) = *((uint16 *)(dst + bufOffset + (int16)READ_LE_UINT16(src + 30) + _pitch * 7 + 6));
|
|
|
|
src += 32;
|
|
break;
|
|
case 0xF7:
|
|
// Raw 8x8 block
|
|
*((uint32 *)dst) = *((const uint32 *)src);
|
|
*((uint32 *)(dst + 4)) = *((const uint32 *)(src + 4));
|
|
*((uint32 *)(dst + _pitch)) = *((const uint32 *)(src + 8));
|
|
*((uint32 *)(dst + _pitch + 4)) = *((const uint32 *)(src + 12));
|
|
*((uint32 *)(dst + _pitch * 2)) = *((const uint32 *)(src + 16));
|
|
*((uint32 *)(dst + _pitch * 2 + 4)) = *((const uint32 *)(src + 20));
|
|
*((uint32 *)(dst + _pitch * 3)) = *((const uint32 *)(src + 24));
|
|
*((uint32 *)(dst + _pitch * 3 + 4)) = *((const uint32 *)(src + 28));
|
|
*((uint32 *)(dst + _pitch * 4)) = *((const uint32 *)(src + 32));
|
|
*((uint32 *)(dst + _pitch * 4 + 4)) = *((const uint32 *)(src + 36));
|
|
*((uint32 *)(dst + _pitch * 5)) = *((const uint32 *)(src + 40));
|
|
*((uint32 *)(dst + _pitch * 5 + 4)) = *((const uint32 *)(src + 44));
|
|
*((uint32 *)(dst + _pitch * 6)) = *((const uint32 *)(src + 48));
|
|
*((uint32 *)(dst + _pitch * 6 + 4)) = *((const uint32 *)(src + 52));
|
|
*((uint32 *)(dst + _pitch * 7)) = *((const uint32 *)(src + 56));
|
|
*((uint32 *)(dst + _pitch * 7 + 4)) = *((const uint32 *)(src + 60));
|
|
|
|
src += 64;
|
|
break;
|
|
default:
|
|
// Copy a block using the offset table
|
|
copyBlock(dst, bufOffset, _offsetTable[opcode]);
|
|
break;
|
|
}
|
|
|
|
dst += 8;
|
|
}
|
|
|
|
dst += _pitch * 7;
|
|
}
|
|
}
|
|
|
|
void Codec48Decoder::copyBlock(byte *dst, int deltaBufOffset, int offset) {
|
|
const byte *src = dst + deltaBufOffset + offset;
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
*((uint32 *)(dst + _pitch * i)) = *((const uint32 *)(src + _pitch * i));
|
|
*((uint32 *)(dst + _pitch * i + 4)) = *((const uint32 *)(src + _pitch * i + 4));
|
|
}
|
|
}
|
|
|
|
void Codec48Decoder::scaleBlock(byte *dst, const byte *src) {
|
|
// This is doing a 2x scale of data
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
uint16 pixels = src[0];
|
|
pixels = (pixels << 8) | pixels;
|
|
*((uint16 *)dst) = pixels;
|
|
*((uint16 *)(dst + _pitch)) = pixels;
|
|
pixels = src[1];
|
|
pixels = (pixels << 8) | pixels;
|
|
*((uint16 *)(dst + 2)) = pixels;
|
|
*((uint16 *)(dst + _pitch + 2)) = pixels;
|
|
pixels = src[2];
|
|
pixels = (pixels << 8) | pixels;
|
|
*((uint16 *)(dst + 4)) = pixels;
|
|
*((uint16 *)(dst + _pitch + 4)) = pixels;
|
|
pixels = src[3];
|
|
pixels = (pixels << 8) | pixels;
|
|
*((uint16 *)(dst + 6)) = pixels;
|
|
*((uint16 *)(dst + _pitch + 6)) = pixels;
|
|
src += 4;
|
|
dst += _pitch * 2;
|
|
}
|
|
}
|
|
|
|
} // end of namespace Grim
|