scummvm/engines/grim/movie/codecs/codec48.cpp
Paweł Kołodziejski 06902574b4
GRIM: Janitorial
2022-06-08 01:12:00 +02:00

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